From f3ef083169e70ead293b0de3c06f909ba8c8827d Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Thu, 13 Jun 2024 00:05:15 +0200 Subject: [PATCH 01/16] Proto: Introduce ParisC --- src/proto_020_PsParisC/bin_accuser/dune | 30 + .../bin_accuser/main_accuser_019_PtParisB.ml | 39 + src/proto_020_PsParisC/bin_baker/dune | 30 + .../bin_baker/main_baker_019_PtParisB.ml | 54 + .../lib_benchmark/README.md | 42 + .../lib_benchmark/autocomp.ml | 380 + src/proto_020_PsParisC/lib_benchmark/dune | 33 + .../lib_benchmark/execution_context.ml | 103 + .../lib_benchmark/kernel.ml | 39 + .../lib_benchmark_type_inference/dune | 23 + .../lib_benchmark_type_inference/inference.ml | 1150 ++++ .../inference.mli | 145 + .../lib_benchmark_type_inference/int_map.ml | 26 + .../mikhailsky.ml | 422 ++ .../mikhailsky.mli | 331 + .../mikhailsky_prim.ml | 575 ++ .../lib_benchmark_type_inference/monads.ml | 83 + .../lib_benchmark_type_inference/stores.ml | 85 + .../lib_benchmark_type_inference/test/dune | 29 + .../test/test_inference.ml | 615 ++ .../test/test_uf.ml | 63 + .../lib_benchmark_type_inference/type.ml | 200 + .../lib_benchmark_type_inference/type.mli | 111 + .../lib_benchmark_type_inference/uf.ml | 99 + .../lib_benchmark/micheline_sampler.ml | 110 + .../lib_benchmark/micheline_sampler.mli | 70 + .../lib_benchmark/michelson_mcmc_samplers.ml | 339 + .../lib_benchmark/michelson_mcmc_samplers.mli | 115 + .../lib_benchmark/michelson_samplers.ml | 823 +++ .../lib_benchmark/michelson_samplers.mli | 172 + .../lib_benchmark/michelson_samplers_base.ml | 139 + .../lib_benchmark/michelson_samplers_base.mli | 67 + .../lib_benchmark/mikhailsky_to_michelson.ml | 229 + src/proto_020_PsParisC/lib_benchmark/rules.ml | 975 +++ .../lib_benchmark/sampling_helpers.ml | 41 + .../lib_benchmark/state_space.ml | 78 + .../lib_benchmark/test/dune | 39 + .../lib_benchmark/test/test_autocompletion.ml | 120 + .../lib_benchmark/test/test_distribution.ml | 157 + .../lib_benchmark/test/test_helpers.ml | 97 + .../lib_benchmark/test/test_sampling_code.ml | 96 + .../lib_benchmark/test/test_sampling_data.ml | 85 + .../lib_benchmark/type_helpers.ml | 88 + .../lib_benchmark/type_helpers.mli | 57 + .../lib_benchmarks_proto/apply_benchmarks.ml | 151 + .../lib_benchmarks_proto/benchmarks_proto.ml | 153 + .../lib_benchmarks_proto/benchmarks_proto.mli | 131 + .../lib_benchmarks_proto/cache_benchmarks.ml | 204 + .../carbonated_map_benchmarks.ml | 341 + .../lib_benchmarks_proto/dal_benchmarks.ml | 146 + .../lib_benchmarks_proto/dune | 44 + .../encodings_benchmarks.ml | 507 ++ .../lib_benchmarks_proto/gas_helpers.ml | 36 + .../global_constants_storage_benchmarks.ml | 667 ++ .../interpreter_benchmarks.ml | 4203 ++++++++++++ .../lib_benchmarks_proto/interpreter_model.ml | 851 +++ .../interpreter_workload.ml | 1717 +++++ .../michelson_commands.ml | 213 + .../michelson_generation.ml | 113 + .../michelson_generation.mli | 61 + .../lib_benchmarks_proto/michelson_types.ml | 130 + .../registration_helpers.ml | 58 + .../sapling_benchmarks.ml | 171 + .../lib_benchmarks_proto/sapling_commands.ml | 138 + .../sapling_generation.ml | 608 ++ .../sc_rollup_benchmarks.ml | 707 ++ .../script_repr_benchmarks.ml | 139 + .../script_typed_ir_size_benchmarks.ml | 305 + .../skip_list_benchmarks.ml | 188 + .../storage_benchmarks.ml | 253 + .../lib_benchmarks_proto/tags.ml | 35 + .../lib_benchmarks_proto/ticket_benchmarks.ml | 293 + .../translator_benchmarks.ml | 833 +++ .../lib_benchmarks_proto/translator_model.ml | 70 + .../translator_workload.ml | 193 + .../lib_client/annotated_manager_operation.ml | 139 + .../annotated_manager_operation.mli | 98 + .../lib_client/client_proto_args.ml | 1089 +++ .../lib_client/client_proto_args.mli | 303 + .../lib_client/client_proto_context.ml | 1505 ++++ .../lib_client/client_proto_context.mli | 1018 +++ .../lib_client/client_proto_contracts.ml | 263 + .../lib_client/client_proto_contracts.mli | 108 + .../lib_client/client_proto_fa12.ml | 1023 +++ .../lib_client/client_proto_fa12.mli | 164 + .../lib_client/client_proto_multisig.ml | 1283 ++++ .../lib_client/client_proto_multisig.mli | 155 + .../lib_client/client_proto_programs.ml | 551 ++ .../lib_client/client_proto_programs.mli | 266 + .../lib_client/client_proto_rollups.ml | 48 + .../lib_client/client_proto_rollups.mli | 29 + .../lib_client/client_proto_tzt.ml | 178 + .../lib_client/client_proto_tzt.mli | 19 + .../lib_client/client_proto_utils.ml | 59 + .../lib_client/client_proto_utils.mli | 40 + src/proto_020_PsParisC/lib_client/dune | 35 + .../lib_client/injection.ml | 1619 +++++ .../lib_client/injection.mli | 128 + src/proto_020_PsParisC/lib_client/light.ml | 37 + src/proto_020_PsParisC/lib_client/limit.ml | 84 + src/proto_020_PsParisC/lib_client/limit.mli | 49 + .../lib_client/managed_contract.ml | 362 + .../lib_client/managed_contract.mli | 136 + .../lib_client/michelson_v1_emacs.ml | 230 + .../lib_client/michelson_v1_emacs.mli | 39 + .../lib_client/michelson_v1_entrypoints.ml | 287 + .../lib_client/michelson_v1_entrypoints.mli | 110 + .../lib_client/michelson_v1_error_reporter.ml | 857 +++ .../michelson_v1_error_reporter.mli | 40 + .../lib_client/michelson_v1_helpers.ml | 63 + .../lib_client/michelson_v1_macros.ml | 1571 +++++ .../lib_client/michelson_v1_macros.mli | 86 + .../lib_client/michelson_v1_parser.ml | 133 + .../lib_client/michelson_v1_parser.mli | 69 + .../lib_client/michelson_v1_printer.ml | 239 + .../lib_client/michelson_v1_printer.mli | 72 + .../lib_client/michelson_v1_stack.ml | 663 ++ .../lib_client/michelson_v1_stack.mli | 68 + src/proto_020_PsParisC/lib_client/mockup.ml | 652 ++ .../lib_client/operation_result.ml | 1143 +++ .../lib_client/operation_result.mli | 43 + .../lib_client/protocol_client_context.ml | 337 + src/proto_020_PsParisC/lib_client/proxy.ml | 181 + src/proto_020_PsParisC/lib_client/test/dune | 54 + .../test/test_client_proto_context.ml | 69 + .../test/test_client_proto_contracts.ml | 105 + .../test/test_michelson_v1_macros.ml | 1374 ++++ .../lib_client/test/test_proxy.ml | 90 + .../alpha_commands_registration.ml | 38 + .../client_proto_context_commands.ml | 3801 ++++++++++ .../client_proto_contracts_commands.ml | 98 + .../client_proto_fa12_commands.ml | 709 ++ .../client_proto_mockup_commands.ml | 82 + .../client_proto_mockup_commands.mli | 26 + .../client_proto_multisig_commands.ml | 1063 +++ .../client_proto_multisig_commands.mli | 26 + .../client_proto_programs_commands.ml | 1535 +++++ .../client_proto_programs_commands.mli | 26 + .../client_proto_stresstest_commands.ml | 1929 ++++++ .../client_proto_stresstest_commands.mli | 29 + .../client_proto_stresstest_contracts.ml | 258 + .../client_proto_stresstest_contracts.mli | 88 + .../client_proto_utils_commands.ml | 179 + .../client_proto_utils_commands.mli | 26 + .../lib_client_commands/dune | 72 + .../client_sapling_commands.ml | 788 +++ .../client_sapling_commands.mli | 8 + .../lib_client_sapling/context.ml | 538 ++ .../lib_client_sapling/context.mli | 132 + .../lib_client_sapling/dune | 28 + .../lib_client_sapling/wallet.ml | 112 + .../lib_client_sapling/wallet.mli | 51 + .../lib_dac_plugin/dac_plugin_registration.ml | 106 + src/proto_020_PsParisC/lib_dac_plugin/dune | 29 + .../lib_dac_plugin/test/dune | 51 + .../test/test_dac_pages_encoding.ml | 648 ++ .../test/test_dac_plugin_registration.ml | 159 + .../lib_dac_plugin/test/test_helpers.ml | 45 + .../lib_dal/RPC_directory.ml | 40 + .../lib_dal/RPC_directory.mli | 10 + .../lib_dal/dal_plugin_registration.ml | 280 + .../lib_dal/dal_proto_client.ml | 36 + .../lib_dal/dal_proto_client.mli | 30 + .../lib_dal/dal_services.ml | 48 + .../lib_dal/dal_services.mli | 32 + .../lib_dal/dal_slot_frame_encoding.ml | 257 + .../lib_dal/dal_slot_frame_encoding.mli | 182 + src/proto_020_PsParisC/lib_dal/dune | 31 + src/proto_020_PsParisC/lib_dal/test/dune | 47 + .../test/test_dal_slot_frame_encoding.ml | 420 ++ .../lib_dal/test/test_helpers.ml | 45 + .../lib_delegate/abstract_context_index.ml | 38 + .../lib_delegate/abstract_context_index.mli | 33 + .../lib_delegate/baking_actions.ml | 1006 +++ .../lib_delegate/baking_actions.mli | 118 + .../lib_delegate/baking_cache.ml | 84 + .../lib_delegate/baking_commands.ml | 716 ++ .../lib_delegate/baking_commands.mli | 33 + .../baking_commands_registration.ml | 29 + .../lib_delegate/baking_configuration.ml | 367 + .../lib_delegate/baking_configuration.mli | 138 + .../lib_delegate/baking_errors.ml | 251 + .../lib_delegate/baking_events.ml | 1178 ++++ .../lib_delegate/baking_files.ml | 41 + .../lib_delegate/baking_files.mli | 35 + .../lib_delegate/baking_highwatermarks.ml | 264 + .../lib_delegate/baking_highwatermarks.mli | 105 + .../lib_delegate/baking_lib.ml | 767 +++ .../lib_delegate/baking_lib.mli | 84 + .../lib_delegate/baking_nonces.ml | 588 ++ .../lib_delegate/baking_nonces.mli | 79 + .../lib_delegate/baking_pow.ml | 134 + .../lib_delegate/baking_pow.mli | 40 + .../lib_delegate/baking_scheduling.ml | 1036 +++ .../lib_delegate/baking_scheduling.mli | 111 + .../lib_delegate/baking_simulator.ml | 172 + .../lib_delegate/baking_simulator.mli | 81 + .../lib_delegate/baking_state.ml | 1392 ++++ .../lib_delegate/baking_state.mli | 412 ++ .../lib_delegate/baking_vdf.ml | 503 ++ .../lib_delegate/baking_vdf.mli | 33 + .../lib_delegate/block_forge.ml | 511 ++ .../lib_delegate/block_forge.mli | 63 + .../lib_delegate/client_baking_blocks.ml | 217 + .../lib_delegate/client_baking_blocks.mli | 68 + .../client_baking_denunciation.ml | 639 ++ .../client_baking_denunciation.mli | 31 + .../lib_delegate/client_baking_scheduling.ml | 33 + .../lib_delegate/client_baking_scheduling.mli | 54 + .../lib_delegate/client_daemon.ml | 229 + .../lib_delegate/client_daemon.mli | 67 + .../lib_delegate/delegate_events.ml | 250 + src/proto_020_PsParisC/lib_delegate/dune | 111 + .../lib_delegate/forge_worker.ml | 238 + .../lib_delegate/forge_worker.mli | 71 + .../lib_delegate/node_rpc.ml | 312 + .../lib_delegate/node_rpc.mli | 103 + .../lib_delegate/operation_pool.ml | 402 ++ .../lib_delegate/operation_pool.mli | 168 + .../lib_delegate/operation_selection.ml | 417 ++ .../lib_delegate/operation_selection.mli | 71 + .../lib_delegate/operation_worker.ml | 643 ++ .../lib_delegate/operation_worker.mli | 88 + .../lib_delegate/per_block_vote_file.ml | 154 + .../lib_delegate/per_block_vote_file.mli | 77 + .../lib_delegate/state_transitions.ml | 1088 +++ .../lib_delegate/state_transitions.mli | 90 + .../lib_delegate/test/README.md | 127 + src/proto_020_PsParisC/lib_delegate/test/dune | 56 + .../mockup_simulator/broadcast_services.ml | 85 + .../lib_delegate/test/mockup_simulator/dune | 33 + .../mockup_simulator/faked_client_context.ml | 177 + .../test/mockup_simulator/faked_daemon.ml | 38 + .../test/mockup_simulator/faked_services.ml | 373 + .../test/mockup_simulator/mockup_simulator.ml | 1565 +++++ .../mockup_simulator/mockup_simulator.mli | 253 + .../lib_delegate/test/tenderbrute/dune | 23 + .../lib_delegate/test/tenderbrute/lib/dune | 21 + .../test/tenderbrute/lib/tenderbrute.ml | 229 + .../test/tenderbrute/lib/tenderbrute.mli | 83 + .../test/tenderbrute/tenderbrute_main.ml | 187 + .../lib_delegate/test/test_scenario.ml | 1986 ++++++ .../lib_delegate/vdf_helpers.ml | 31 + .../lib_delegate/vdf_helpers.mli | 35 + src/proto_020_PsParisC/lib_injector/dune | 23 + .../lib_injector/injector_plugin.ml | 442 ++ src/proto_020_PsParisC/lib_layer2_utils/dune | 19 + .../lib_layer2_utils/layer1_services.ml | 148 + .../lib_layer2_utils/layer1_services.mli | 76 + .../lib_parameters/default_parameters.ml | 486 ++ .../lib_parameters/default_parameters.mli | 62 + src/proto_020_PsParisC/lib_parameters/dune | 61 + src/proto_020_PsParisC/lib_parameters/gen.ml | 69 + src/proto_020_PsParisC/lib_plugin/RPC.ml | 4473 ++++++++++++ src/proto_020_PsParisC/lib_plugin/dune | 36 + src/proto_020_PsParisC/lib_plugin/index.mld | 17 + src/proto_020_PsParisC/lib_plugin/mempool.ml | 793 +++ src/proto_020_PsParisC/lib_plugin/mempool.mli | 219 + .../lib_plugin/metrics_plugin.ml | 70 + src/proto_020_PsParisC/lib_plugin/plugin.ml | 32 + .../lib_plugin/plugin_errors.ml | 62 + .../lib_plugin/plugin_registerer.ml | 46 + .../lib_plugin/script_interpreter_logging.ml | 2460 +++++++ .../lib_plugin/script_interpreter_logging.mli | 43 + src/proto_020_PsParisC/lib_plugin/test/dune | 62 + .../lib_plugin/test/helpers.ml | 172 + .../lib_plugin/test/test_conflict_handler.ml | 226 + .../lib_plugin/test/test_consensus_filter.ml | 491 ++ .../test/test_fee_needed_to_overtake.ml | 178 + .../test/test_fee_needed_to_replace_by_fee.ml | 210 + .../lib_plugin/view_helpers.ml | 293 + .../lib_protocol/.ocamlformat-ignore | 486 ++ .../lib_protocol/TEZOS_PROTOCOL | 295 + .../lib_protocol/adaptive_issuance_costs.ml | 42 + .../lib_protocol/adaptive_issuance_costs.mli | 40 + .../adaptive_issuance_services.ml | 307 + .../adaptive_issuance_services.mli | 64 + .../lib_protocol/adaptive_issuance_storage.ml | 397 ++ .../adaptive_issuance_storage.mli | 132 + .../lib_protocol/alpha_context.ml | 776 +++ .../lib_protocol/alpha_context.mli | 5411 +++++++++++++++ .../lib_protocol/alpha_services.ml | 282 + .../lib_protocol/alpha_services.mli | 93 + .../lib_protocol/already_denounced_storage.ml | 83 + .../already_denounced_storage.mli | 62 + .../lib_protocol/amendment.ml | 229 + .../lib_protocol/amendment.mli | 133 + src/proto_020_PsParisC/lib_protocol/apply.ml | 3229 +++++++++ src/proto_020_PsParisC/lib_protocol/apply.mli | 166 + .../lib_protocol/apply_internal_results.ml | 694 ++ .../lib_protocol/apply_internal_results.mli | 152 + .../lib_protocol/apply_operation_result.ml | 54 + .../lib_protocol/apply_operation_result.mli | 43 + .../lib_protocol/apply_results.ml | 2849 ++++++++ .../lib_protocol/apply_results.mli | 359 + src/proto_020_PsParisC/lib_protocol/baking.ml | 152 + .../lib_protocol/baking.mli | 64 + src/proto_020_PsParisC/lib_protocol/bitset.ml | 70 + .../lib_protocol/bitset.mli | 77 + .../lib_protocol/blinded_public_key_hash.ml | 60 + .../lib_protocol/blinded_public_key_hash.mli | 45 + .../lib_protocol/block_header_repr.ml | 431 ++ .../lib_protocol/block_header_repr.mli | 115 + .../lib_protocol/block_payload_hash.ml | 42 + .../lib_protocol/block_payload_hash.mli | 28 + .../lib_protocol/block_payload_repr.ml | 42 + .../lib_protocol/block_payload_repr.mli | 41 + .../lib_protocol/bond_id_repr.ml | 119 + .../lib_protocol/bond_id_repr.mli | 42 + .../lib_protocol/bootstrap_storage.ml | 257 + .../lib_protocol/bootstrap_storage.mli | 46 + .../lib_protocol/bounded_history_repr.ml | 287 + .../lib_protocol/bounded_history_repr.mli | 125 + .../lib_protocol/cache_memory_helpers.ml | 183 + .../lib_protocol/cache_repr.ml | 322 + .../lib_protocol/cache_repr.mli | 244 + .../lib_protocol/cache_repr_costs.ml | 30 + .../cache_repr_costs_generated.ml | 16 + .../lib_protocol/carbonated_map.ml | 244 + .../lib_protocol/carbonated_map.mli | 167 + .../lib_protocol/carbonated_map_costs.ml | 70 + .../lib_protocol/carbonated_map_costs.mli | 47 + .../carbonated_map_costs_generated.ml | 32 + .../lib_protocol/commitment_repr.ml | 36 + .../lib_protocol/commitment_repr.mli | 34 + .../lib_protocol/commitment_storage.ml | 53 + .../lib_protocol/commitment_storage.mli | 52 + .../constants_parametric_previous_repr.ml | 650 ++ .../constants_parametric_previous_repr.mli | 203 + .../lib_protocol/constants_parametric_repr.ml | 761 ++ .../constants_parametric_repr.mli | 238 + .../lib_protocol/constants_repr.ml | 389 ++ .../lib_protocol/constants_repr.mli | 142 + .../lib_protocol/constants_services.ml | 70 + .../lib_protocol/constants_services.mli | 38 + .../lib_protocol/constants_storage.ml | 299 + .../lib_protocol/constants_storage.mli | 185 + .../lib_protocol/context_binary_proof.ml | 57 + .../lib_protocol/context_binary_proof.mli | 36 + .../lib_protocol/contract_delegate_storage.ml | 111 + .../contract_delegate_storage.mli | 98 + .../lib_protocol/contract_hash.ml | 51 + .../lib_protocol/contract_hash.mli | 32 + .../lib_protocol/contract_manager_storage.ml | 173 + .../lib_protocol/contract_manager_storage.mli | 85 + .../lib_protocol/contract_repr.ml | 235 + .../lib_protocol/contract_repr.mli | 98 + .../lib_protocol/contract_services.ml | 843 +++ .../lib_protocol/contract_services.mli | 187 + .../lib_protocol/contract_storage.ml | 939 +++ .../lib_protocol/contract_storage.mli | 343 + .../lib_protocol/contracts/cpmm.bin | 1 + .../lib_protocol/contracts/cpmm.mligo | 388 ++ .../lib_protocol/contracts/cpmm.tz | 929 +++ .../lib_protocol/contracts/lqt.bin | 1 + .../lib_protocol/contracts/lqt.mligo | 164 + .../lib_protocol/contracts/lqt.tz | 327 + .../lib_protocol/contracts/timelock_flip.tz | 95 + .../lib_protocol/cycle_repr.ml | 85 + .../lib_protocol/cycle_repr.mli | 66 + .../lib_protocol/dal_apply.ml | 132 + .../lib_protocol/dal_apply.mli | 72 + .../lib_protocol/dal_attestation_repr.ml | 141 + .../lib_protocol/dal_attestation_repr.mli | 119 + .../lib_protocol/dal_costs.ml | 26 + .../lib_protocol/dal_costs_generated.ml | 14 + .../lib_protocol/dal_costs_generated.mli | 26 + .../lib_protocol/dal_errors_repr.ml | 248 + .../lib_protocol/dal_operations_repr.ml | 84 + .../lib_protocol/dal_operations_repr.mli | 70 + .../lib_protocol/dal_services.ml | 54 + .../lib_protocol/dal_services.mli | 32 + .../lib_protocol/dal_slot_index_repr.ml | 90 + .../lib_protocol/dal_slot_index_repr.mli | 73 + .../lib_protocol/dal_slot_repr.ml | 1079 +++ .../lib_protocol/dal_slot_repr.mli | 388 ++ .../lib_protocol/dal_slot_storage.ml | 101 + .../lib_protocol/dal_slot_storage.mli | 82 + .../delegate_activation_storage.ml | 97 + .../delegate_activation_storage.mli | 55 + .../lib_protocol/delegate_consensus_key.ml | 236 + .../lib_protocol/delegate_consensus_key.mli | 97 + .../lib_protocol/delegate_cycles.ml | 254 + .../lib_protocol/delegate_cycles.mli | 48 + .../delegate_missed_attestations_storage.ml | 245 + .../delegate_missed_attestations_storage.mli | 101 + .../lib_protocol/delegate_rewards.ml | 162 + .../lib_protocol/delegate_rewards.mli | 62 + .../lib_protocol/delegate_sampler.ml | 289 + .../lib_protocol/delegate_sampler.mli | 93 + .../lib_protocol/delegate_services.ml | 862 +++ .../lib_protocol/delegate_services.mli | 204 + .../delegate_slashed_deposits_storage.ml | 613 ++ .../delegate_slashed_deposits_storage.mli | 102 + .../delegate_staking_parameters.ml | 80 + .../delegate_staking_parameters.mli | 44 + .../lib_protocol/delegate_storage.ml | 428 ++ .../lib_protocol/delegate_storage.mli | 168 + .../lib_protocol/denunciations_repr.ml | 31 + .../lib_protocol/denunciations_repr.mli | 30 + .../lib_protocol/dependent_bool.ml | 64 + .../lib_protocol/dependent_bool.mli | 65 + .../lib_protocol/deposits_repr.ml | 50 + .../lib_protocol/deposits_repr.mli | 44 + .../lib_protocol/destination_repr.ml | 159 + .../lib_protocol/destination_repr.mli | 63 + .../lib_protocol/destination_storage.ml | 35 + .../lib_protocol/destination_storage.mli | 31 + src/proto_020_PsParisC/lib_protocol/dune | 1186 ++++ .../lib_protocol/entrypoint_repr.ml | 255 + .../lib_protocol/entrypoint_repr.mli | 149 + .../lib_protocol/fees_storage.ml | 154 + .../lib_protocol/fees_storage.mli | 116 + .../lib_protocol/fitness_repr.ml | 308 + .../lib_protocol/fitness_repr.mli | 96 + .../lib_protocol/fixed_point_repr.ml | 94 + .../lib_protocol/fixed_point_repr.mli | 105 + .../forbidden_delegates_storage.ml | 116 + .../forbidden_delegates_storage.mli | 39 + .../lib_protocol/frozen_staker_repr.ml | 109 + .../lib_protocol/frozen_staker_repr.mli | 37 + .../lib_protocol/full_staking_balance_repr.ml | 413 ++ .../full_staking_balance_repr.mli | 96 + .../lib_protocol/gas_comparable_input_size.ml | 137 + .../gas_comparable_input_size.mli | 73 + .../lib_protocol/gas_input_size.ml | 79 + .../lib_protocol/gas_input_size.mli | 55 + .../lib_protocol/gas_limit_repr.ml | 239 + .../lib_protocol/gas_limit_repr.mli | 130 + .../lib_protocol/gas_monad.ml | 127 + .../lib_protocol/gas_monad.mli | 120 + .../lib_protocol/gas_parameters.json | 729 ++ .../lib_protocol/global_constants_costs.ml | 46 + .../lib_protocol/global_constants_costs.mli | 34 + .../global_constants_costs_generated.ml | 23 + .../lib_protocol/global_constants_storage.ml | 289 + .../lib_protocol/global_constants_storage.mli | 150 + .../lib_protocol/indexable.ml | 200 + .../lib_protocol/indexable.mli | 197 + .../lib_protocol/init_storage.ml | 380 + .../lib_protocol/init_storage.mli | 59 + .../lib_protocol/issuance_bonus_repr.ml | 66 + .../lib_protocol/issuance_bonus_repr.mli | 41 + .../lib_protocol/lazy_storage_diff.ml | 428 ++ .../lib_protocol/lazy_storage_diff.mli | 53 + .../lib_protocol/lazy_storage_kind.ml | 321 + .../lib_protocol/lazy_storage_kind.mli | 178 + .../lib_protocol/legacy_script_patches.ml | 52 + .../lib_protocol/level_repr.ml | 367 + .../lib_protocol/level_repr.mli | 123 + .../lib_protocol/level_storage.ml | 129 + .../lib_protocol/level_storage.mli | 77 + .../lib_protocol/liquidity_baking_cpmm.ml | 20 + .../lib_protocol/liquidity_baking_lqt.ml | 20 + .../liquidity_baking_migration.ml | 267 + .../liquidity_baking_migration.mli | 33 + .../lib_protocol/liquidity_baking_storage.ml | 69 + .../lib_protocol/liquidity_baking_storage.mli | 45 + .../lib_protocol/local_gas_counter.ml | 98 + .../lib_protocol/local_gas_counter.mli | 68 + src/proto_020_PsParisC/lib_protocol/main.ml | 483 ++ src/proto_020_PsParisC/lib_protocol/main.mli | 59 + .../lib_protocol/manager_counter_repr.ml | 61 + .../lib_protocol/manager_counter_repr.mli | 69 + .../lib_protocol/manager_repr.ml | 52 + .../lib_protocol/manager_repr.mli | 39 + .../lib_protocol/mempool_validation.ml | 220 + .../lib_protocol/mempool_validation.mli | 184 + .../lib_protocol/merkle_list.ml | 363 + .../lib_protocol/merkle_list.mli | 118 + .../lib_protocol/michelson_v1_gas.ml | 956 +++ .../lib_protocol/michelson_v1_gas.mli | 550 ++ .../lib_protocol/michelson_v1_gas_costs.ml | 216 + .../michelson_v1_gas_costs_generated.ml | 3722 ++++++++++ .../lib_protocol/michelson_v1_primitives.ml | 850 +++ .../lib_protocol/michelson_v1_primitives.mli | 241 + .../lib_protocol/migration_repr.ml | 65 + .../lib_protocol/migration_repr.mli | 39 + .../lib_protocol/misbehaviour_repr.ml | 44 + .../lib_protocol/misbehaviour_repr.mli | 40 + src/proto_020_PsParisC/lib_protocol/misc.ml | 91 + src/proto_020_PsParisC/lib_protocol/misc.mli | 51 + .../lib_protocol/non_empty_string.ml | 34 + .../lib_protocol/non_empty_string.mli | 39 + .../lib_protocol/nonce_hash.ml | 45 + .../lib_protocol/nonce_hash.mli | 31 + .../lib_protocol/nonce_storage.ml | 144 + .../lib_protocol/nonce_storage.mli | 87 + .../lib_protocol/operation_costs.ml | 42 + .../lib_protocol/operation_costs.mli | 29 + .../lib_protocol/operation_repr.ml | 2783 ++++++++ .../lib_protocol/operation_repr.mli | 828 +++ .../lib_protocol/origination_nonce.ml | 43 + .../lib_protocol/origination_nonce.mli | 39 + .../lib_protocol/parameters_repr.ml | 285 + .../lib_protocol/parameters_repr.mli | 73 + .../lib_protocol/path_encoding.ml | 55 + .../lib_protocol/path_encoding.mli | 50 + .../pending_denunciations_storage.ml | 47 + .../pending_denunciations_storage.mli | 67 + .../lib_protocol/per_block_votes_repr.ml | 133 + .../lib_protocol/per_block_votes_repr.mli | 88 + .../lib_protocol/percentage.ml | 75 + .../lib_protocol/percentage.mli | 56 + .../lib_protocol/period_repr.ml | 167 + .../lib_protocol/period_repr.mli | 73 + .../lib_protocol/ratio_repr.ml | 38 + .../lib_protocol/ratio_repr.mli | 30 + .../lib_protocol/raw_context.ml | 2009 ++++++ .../lib_protocol/raw_context.mli | 458 ++ .../lib_protocol/raw_context_intf.ml | 599 ++ .../lib_protocol/raw_level_repr.ml | 131 + .../lib_protocol/raw_level_repr.mli | 75 + .../lib_protocol/receipt_repr.ml | 686 ++ .../lib_protocol/receipt_repr.mli | 138 + .../lib_protocol/round_repr.ml | 531 ++ .../lib_protocol/round_repr.mli | 249 + .../lib_protocol/sampler.ml | 219 + .../lib_protocol/sampler.mli | 111 + .../lib_protocol/sapling_repr.ml | 205 + .../lib_protocol/sapling_services.ml | 103 + .../lib_protocol/sapling_storage.ml | 514 ++ .../lib_protocol/sapling_storage_costs.ml | 27 + .../sapling_storage_costs_generated.ml | 18 + .../lib_protocol/sapling_validator.ml | 115 + .../lib_protocol/saturation_repr.ml | 200 + .../lib_protocol/saturation_repr.mli | 234 + .../lib_protocol/sc_rollup_PVM_sig.ml | 625 ++ .../lib_protocol/sc_rollup_arith.ml | 1773 +++++ .../lib_protocol/sc_rollup_arith.mli | 166 + .../lib_protocol/sc_rollup_commitment_repr.ml | 117 + .../sc_rollup_commitment_repr.mli | 101 + .../sc_rollup_commitment_storage.ml | 139 + .../sc_rollup_commitment_storage.mli | 242 + .../lib_protocol/sc_rollup_costs.ml | 129 + .../lib_protocol/sc_rollup_costs.mli | 91 + .../lib_protocol/sc_rollup_costs_generated.ml | 28 + .../sc_rollup_dal_parameters_repr.ml | 42 + .../sc_rollup_dal_parameters_repr.mli | 28 + .../sc_rollup_data_version_sig.ml | 49 + .../sc_rollup_dissection_chunk_repr.ml | 322 + .../sc_rollup_dissection_chunk_repr.mli | 108 + .../lib_protocol/sc_rollup_errors.ml | 759 ++ .../lib_protocol/sc_rollup_game_repr.ml | 1026 +++ .../lib_protocol/sc_rollup_game_repr.mli | 445 ++ ...up_inbox_merkelized_payload_hashes_repr.ml | 215 + ...p_inbox_merkelized_payload_hashes_repr.mli | 118 + .../sc_rollup_inbox_message_repr.ml | 223 + .../sc_rollup_inbox_message_repr.mli | 107 + .../lib_protocol/sc_rollup_inbox_repr.ml | 857 +++ .../lib_protocol/sc_rollup_inbox_repr.mli | 421 ++ .../lib_protocol/sc_rollup_inbox_storage.ml | 162 + .../lib_protocol/sc_rollup_inbox_storage.mli | 63 + .../sc_rollup_machine_no_proofs.ml | 140 + .../sc_rollup_machine_no_proofs.mli | 54 + .../sc_rollup_management_protocol.ml | 221 + .../sc_rollup_management_protocol.mli | 121 + .../lib_protocol/sc_rollup_metadata_repr.ml | 54 + .../lib_protocol/sc_rollup_metadata_repr.mli | 42 + .../lib_protocol/sc_rollup_operations.ml | 702 ++ .../lib_protocol/sc_rollup_operations.mli | 90 + .../sc_rollup_outbox_message_repr.ml | 214 + .../sc_rollup_outbox_message_repr.mli | 80 + .../lib_protocol/sc_rollup_outbox_storage.ml | 82 + .../lib_protocol/sc_rollup_outbox_storage.mli | 45 + .../lib_protocol/sc_rollup_proof_repr.ml | 597 ++ .../lib_protocol/sc_rollup_proof_repr.mli | 315 + .../sc_rollup_refutation_storage.ml | 665 ++ .../sc_rollup_refutation_storage.mli | 220 + .../lib_protocol/sc_rollup_repr.ml | 108 + .../lib_protocol/sc_rollup_repr.mli | 102 + .../lib_protocol/sc_rollup_reveal_hash.ml | 133 + .../lib_protocol/sc_rollup_reveal_hash.mli | 91 + .../lib_protocol/sc_rollup_riscv.ml | 136 + .../lib_protocol/sc_rollup_riscv.mli | 34 + .../lib_protocol/sc_rollup_stake_storage.ml | 829 +++ .../lib_protocol/sc_rollup_stake_storage.mli | 244 + .../sc_rollup_staker_index_repr.ml | 54 + .../sc_rollup_staker_index_repr.mli | 40 + .../sc_rollup_staker_index_storage.ml | 84 + .../sc_rollup_staker_index_storage.mli | 86 + .../lib_protocol/sc_rollup_storage.ml | 226 + .../lib_protocol/sc_rollup_storage.mli | 102 + .../lib_protocol/sc_rollup_tick_repr.ml | 69 + .../lib_protocol/sc_rollup_tick_repr.mli | 74 + .../lib_protocol/sc_rollup_wasm.ml | 733 ++ .../lib_protocol/sc_rollup_wasm.mli | 129 + .../lib_protocol/sc_rollup_whitelist_repr.ml | 80 + .../lib_protocol/sc_rollup_whitelist_repr.mli | 45 + .../sc_rollup_whitelist_storage.ml | 147 + .../sc_rollup_whitelist_storage.mli | 107 + .../lib_protocol/sc_rollups.ml | 111 + .../lib_protocol/sc_rollups.mli | 80 + .../lib_protocol/script_big_map.ml | 101 + .../lib_protocol/script_big_map.mli | 83 + .../lib_protocol/script_bytes.ml | 204 + .../lib_protocol/script_bytes.mli | 103 + .../lib_protocol/script_cache.ml | 126 + .../lib_protocol/script_cache.mli | 81 + .../lib_protocol/script_comparable.ml | 89 + .../lib_protocol/script_comparable.mli | 29 + .../lib_protocol/script_expr_hash.ml | 44 + .../lib_protocol/script_expr_hash.mli | 31 + .../lib_protocol/script_int.ml | 126 + .../lib_protocol/script_int.mli | 168 + .../lib_protocol/script_interpreter.ml | 1997 ++++++ .../lib_protocol/script_interpreter.mli | 253 + .../lib_protocol/script_interpreter_defs.ml | 1070 +++ .../lib_protocol/script_ir_annot.ml | 315 + .../lib_protocol/script_ir_annot.mli | 83 + .../lib_protocol/script_ir_translator.ml | 6107 +++++++++++++++++ .../lib_protocol/script_ir_translator.mli | 468 ++ .../script_ir_translator_config.ml | 91 + .../lib_protocol/script_ir_unparser.ml | 855 +++ .../lib_protocol/script_ir_unparser.mli | 257 + .../lib_protocol/script_list.ml | 47 + .../lib_protocol/script_list.mli | 50 + .../lib_protocol/script_map.ml | 147 + .../lib_protocol/script_map.mli | 80 + .../lib_protocol/script_repr.ml | 320 + .../lib_protocol/script_repr.mli | 137 + .../lib_protocol/script_repr_costs.ml | 43 + .../script_repr_costs_generated.ml | 58 + .../lib_protocol/script_set.ml | 81 + .../lib_protocol/script_set.mli | 57 + .../lib_protocol/script_string.ml | 82 + .../lib_protocol/script_string.mli | 50 + .../lib_protocol/script_tc_context.ml | 69 + .../lib_protocol/script_tc_context.mli | 80 + .../lib_protocol/script_tc_errors.ml | 226 + .../script_tc_errors_registration.ml | 832 +++ .../script_tc_errors_registration.mli | 34 + .../lib_protocol/script_timestamp.ml | 66 + .../lib_protocol/script_timestamp.mli | 75 + .../lib_protocol/script_typed_ir.ml | 2468 +++++++ .../lib_protocol/script_typed_ir.mli | 1889 +++++ .../lib_protocol/script_typed_ir_size.ml | 708 ++ .../lib_protocol/script_typed_ir_size.mli | 85 + .../script_typed_ir_size_costs.ml | 40 + .../script_typed_ir_size_costs.mli | 30 + .../script_typed_ir_size_costs_generated.ml | 34 + .../lib_protocol/seed_repr.ml | 201 + .../lib_protocol/seed_repr.mli | 100 + .../lib_protocol/seed_storage.ml | 265 + .../lib_protocol/seed_storage.mli | 100 + .../lib_protocol/services_registration.ml | 143 + .../lib_protocol/services_registration.mli | 145 + .../lib_protocol/shared_stake.ml | 198 + .../lib_protocol/shared_stake.mli | 37 + .../lib_protocol/skip_list_costs.ml | 35 + .../lib_protocol/skip_list_costs.mli | 40 + .../lib_protocol/skip_list_costs_generated.ml | 20 + .../lib_protocol/slash_percentage.ml | 50 + .../lib_protocol/slash_percentage.mli | 30 + .../lib_protocol/slot_repr.ml | 121 + .../lib_protocol/slot_repr.mli | 121 + .../lib_protocol/stake_context.ml | 104 + .../lib_protocol/stake_context.mli | 45 + .../lib_protocol/stake_repr.ml | 59 + .../lib_protocol/stake_repr.mli | 55 + .../lib_protocol/stake_storage.ml | 318 + .../lib_protocol/stake_storage.mli | 163 + .../lib_protocol/staking.ml | 429 ++ .../lib_protocol/staking.mli | 82 + .../lib_protocol/staking_parameters_repr.ml | 112 + .../lib_protocol/staking_parameters_repr.mli | 41 + .../lib_protocol/staking_pseudotoken_repr.ml | 40 + .../lib_protocol/staking_pseudotoken_repr.mli | 54 + .../staking_pseudotokens_storage.ml | 530 ++ .../staking_pseudotokens_storage.mli | 92 + .../lib_protocol/state_hash.ml | 44 + .../lib_protocol/state_hash.mli | 30 + .../lib_protocol/storage.ml | 2308 +++++++ .../lib_protocol/storage.mli | 1072 +++ .../lib_protocol/storage_costs.ml | 51 + .../lib_protocol/storage_costs.mli | 34 + .../lib_protocol/storage_costs_generated.ml | 22 + .../lib_protocol/storage_description.ml | 395 ++ .../lib_protocol/storage_description.mli | 93 + .../lib_protocol/storage_functors.ml | 1500 ++++ .../lib_protocol/storage_functors.mli | 125 + .../lib_protocol/storage_sigs.ml | 517 ++ .../lib_protocol/test/README.md | 30 + .../lib_protocol/test/helpers/README.md | 3 + .../lib_protocol/test/helpers/account.ml | 147 + .../lib_protocol/test/helpers/account.mli | 100 + .../test/helpers/adaptive_issuance_helpers.ml | 1276 ++++ .../lib_protocol/test/helpers/assert.ml | 324 + .../test/helpers/big_map_helpers.ml | 71 + .../test/helpers/big_map_helpers.mli | 40 + .../lib_protocol/test/helpers/block.ml | 1330 ++++ .../lib_protocol/test/helpers/block.mli | 429 ++ .../test/helpers/consensus_helpers.ml | 191 + .../lib_protocol/test/helpers/context.ml | 789 +++ .../lib_protocol/test/helpers/context.mli | 458 ++ .../test/helpers/contract_helpers.ml | 160 + .../lib_protocol/test/helpers/cpmm_logic.ml | 102 + .../lib_protocol/test/helpers/cpmm_repr.ml | 386 ++ .../lib_protocol/test/helpers/dal_helpers.ml | 282 + .../lib_protocol/test/helpers/dal_helpers.mli | 188 + .../test/helpers/dummy_zk_rollup.ml | 632 ++ .../lib_protocol/test/helpers/dune | 42 + .../lib_protocol/test/helpers/expr.ml | 50 + .../lib_protocol/test/helpers/expr_common.ml | 98 + .../lib_protocol/test/helpers/incremental.ml | 311 + .../lib_protocol/test/helpers/incremental.mli | 139 + .../helpers/liquidity_baking_generator.ml | 328 + .../helpers/liquidity_baking_generator.mli | 86 + .../test/helpers/liquidity_baking_machine.ml | 1399 ++++ .../test/helpers/liquidity_baking_machine.mli | 387 ++ .../test/helpers/lqt_fa12_repr.ml | 261 + .../test/helpers/lwt_result_wrap_syntax.ml | 51 + .../test/helpers/lwt_result_wrap_syntax.mli | 73 + .../test/helpers/merkle_list_helper.ml | 54 + .../lib_protocol/test/helpers/nonce.ml | 33 + .../lib_protocol/test/helpers/nonce.mli | 33 + .../lib_protocol/test/helpers/op.ml | 1065 +++ .../lib_protocol/test/helpers/op.mli | 633 ++ .../test/helpers/operation_generator.ml | 726 ++ .../test/helpers/result_wrap_syntax.ml | 22 + .../test/helpers/result_wrap_syntax.mli | 32 + .../lib_protocol/test/helpers/rewards.ml | 1641 +++++ .../test/helpers/sapling_helpers.ml | 501 ++ .../test/helpers/sc_rollup_helpers.ml | 1021 +++ .../test/helpers/script_big_map.ml | 14 + .../test/helpers/script_big_map.mli | 28 + .../lib_protocol/test/helpers/script_map.ml | 36 + .../lib_protocol/test/helpers/script_map.mli | 31 + .../lib_protocol/test/helpers/script_set.ml | 31 + .../lib_protocol/test/helpers/script_set.mli | 32 + .../test/helpers/test_global_constants.ml | 325 + .../lib_protocol/test/helpers/test_tez.ml | 68 + .../lib_protocol/test/helpers/testable.ml | 37 + .../test/helpers/ticket_helpers.ml | 39 + .../lib_protocol/test/helpers/transfers.ml | 71 + .../lib_protocol/test/helpers/transfers.mli | 68 + .../test/helpers/zk_rollup_l2_helpers.ml | 26 + .../test/integration/consensus/dune | 64 + .../integration/consensus/test_attestation.ml | 894 +++ .../test/integration/consensus/test_baking.ml | 488 ++ .../consensus/test_consensus_key.ml | 345 + .../consensus/test_deactivation.ml | 402 ++ .../integration/consensus/test_delegation.ml | 1804 +++++ .../consensus/test_double_attestation.ml | 963 +++ .../consensus/test_double_baking.ml | 647 ++ .../consensus/test_double_preattestation.ml | 472 ++ .../consensus/test_frozen_deposits.ml | 1075 +++ .../consensus/test_helpers_rpcs.ml | 69 + .../consensus/test_participation.ml | 250 + .../consensus/test_preattestation.ml | 255 + .../consensus/test_preattestation_functor.ml | 285 + .../test/integration/consensus/test_seed.ml | 716 ++ .../lib_protocol/test/integration/dune | 60 + .../lib_protocol/test/integration/gas/dune | 45 + .../test/integration/gas/test_gas_costs.ml | 291 + .../test/integration/gas/test_gas_levels.ml | 632 ++ .../contracts/big_interpreter_stack.tz | 5 + .../integration/michelson/contracts/emit.tz | 16 + .../michelson/contracts/fail_rec.tz | 8 + .../forbidden_op_in_view_CREATE_CONTRACT.tz | 24 + .../contracts/forbidden_op_in_view_SELF.tz | 11 + .../forbidden_op_in_view_SET_DELEGATE.tz | 11 + .../forbidden_op_in_view_TRANSFER_TOKENS.tz | 12 + .../michelson/contracts/int-store.tz | 3 + .../integration/michelson/contracts/omega.tz | 9 + .../michelson/contracts/rec_fact.tz | 19 + .../michelson/contracts/rec_fact_apply.tz | 24 + .../contracts/rec_fact_apply_store.tz | 27 + .../michelson/contracts/rec_fact_store.tz | 22 + .../michelson/contracts/sapling_contract.tz | 73 + .../contracts/sapling_contract_double.tz | 27 + .../contracts/sapling_contract_drop.tz | 13 + .../contracts/sapling_contract_send.tz | 20 + .../sapling_contract_state_as_arg.tz | 18 + .../contracts/sapling_push_sapling_state.tz | 11 + .../contracts/sapling_use_existing_state.tz | 12 + .../michelson/contracts/temp_big_maps.tz | 81 + .../test/integration/michelson/dune | 84 + .../integration/michelson/test_annotations.ml | 150 + .../michelson/test_block_time_instructions.ml | 84 + .../michelson/test_contract_event.ml | 140 + .../test_global_constants_storage.ml | 156 + .../michelson/test_interpretation.ml | 487 ++ .../michelson/test_lambda_normalization.ml | 244 + .../michelson/test_lazy_storage_diff.ml | 153 + .../michelson/test_patched_contracts.ml | 221 + .../integration/michelson/test_sapling.ml | 1331 ++++ .../michelson/test_script_cache.ml | 484 ++ .../michelson/test_script_typed_ir_size.ml | 1053 +++ .../michelson/test_temp_big_maps.ml | 118 + .../michelson/test_ticket_accounting.ml | 1447 ++++ .../michelson/test_ticket_balance.ml | 1791 +++++ .../michelson/test_ticket_balance_key.ml | 453 ++ .../michelson/test_ticket_direct_spending.ml | 195 + .../test_ticket_lazy_storage_diff.ml | 698 ++ .../michelson/test_ticket_manager.ml | 819 +++ .../michelson/test_ticket_operations_diff.ml | 1327 ++++ .../michelson/test_ticket_scanner.ml | 707 ++ .../michelson/test_ticket_storage.ml | 280 + .../michelson/test_typechecking.ml | 1019 +++ .../test/integration/operations/dune | 63 + .../integration/operations/test_activation.ml | 603 ++ .../operations/test_combined_operations.ml | 449 ++ .../operations/test_failing_noop.ml | 55 + .../operations/test_origination.ml | 360 + .../operations/test_paid_storage_increase.ml | 246 + .../integration/operations/test_reveal.ml | 839 +++ .../integration/operations/test_sc_rollup.ml | 3822 +++++++++++ .../operations/test_sc_rollup_transfer.ml | 430 ++ .../integration/operations/test_transfer.ml | 979 +++ .../operations/test_transfer_ticket.ml | 346 + .../integration/operations/test_voting.ml | 2275 ++++++ .../integration/operations/test_zk_rollup.ml | 1293 ++++ .../test_adaptive_issuance_launch.ml | 604 ++ .../test_adaptive_issuance_roundtrip.ml | 2952 ++++++++ .../test/integration/test_constants.ml | 275 + .../test/integration/test_frozen_bonds.ml | 768 +++ .../test/integration/test_liquidity_baking.ml | 657 ++ .../test/integration/test_storage.ml | 242 + .../integration/test_storage_functions.ml | 240 + .../test/integration/test_token.ml | 789 +++ .../test/integration/validate/dune | 65 + .../validate/generator_descriptors.ml | 873 +++ .../validate/generator_descriptors.mli | 161 + .../test/integration/validate/generators.ml | 258 + .../validate/manager_operation_helpers.ml | 1391 ++++ .../validate/test_1m_restriction.ml | 213 + .../integration/validate/test_covalidity.ml | 142 + .../test_manager_operation_validation.ml | 619 ++ .../test/integration/validate/test_mempool.ml | 395 ++ .../test/integration/validate/test_sanity.ml | 147 + .../validate/test_validation_batch.ml | 615 ++ .../validate/valid_operations_generators.ml | 243 + .../integration/validate/validate_helpers.ml | 399 ++ .../test/integration/wasm_kernel/README.md | 73 + .../integration/wasm_kernel/computation.wasm | Bin 0 -> 9199 bytes .../test/integration/wasm_kernel/echo.wasm | Bin 0 -> 408 bytes .../test/integration/wasm_kernel/echo.wast | 106 + .../wasm_kernel/no_parse_bad_fingerprint.wasm | Bin 0 -> 9863 bytes .../wasm_kernel/no_parse_random.wasm | 1 + .../integration/wasm_kernel/tx-kernel.wasm | Bin 0 -> 382363 bytes .../lib_protocol/test/pbt/dune | 84 + .../test/pbt/liquidity_baking_pbt.ml | 327 + .../test/pbt/saturation_fuzzing.ml | 202 + .../test/pbt/test_balance_updates_encoding.ml | 208 + .../lib_protocol/test/pbt/test_bitset.ml | 125 + .../test/pbt/test_bytes_conversion.ml | 215 + .../test/pbt/test_carbonated_map.ml | 547 ++ .../test/pbt/test_compare_operations.ml | 102 + .../test/pbt/test_dal_slot_proof.ml | 261 + .../test/pbt/test_gas_properties.ml | 144 + .../lib_protocol/test/pbt/test_merkle_list.ml | 144 + .../test/pbt/test_operation_encoding.ml | 71 + .../test/pbt/test_refutation_game.ml | 1648 +++++ .../lib_protocol/test/pbt/test_sampler.ml | 271 + .../test/pbt/test_sc_rollup_encoding.ml | 348 + .../test/pbt/test_sc_rollup_inbox.ml | 77 + .../test/pbt/test_sc_rollup_tick_repr.ml | 110 + .../test/pbt/test_script_comparison.ml | 353 + .../test/pbt/test_script_roundtrip.ml | 283 + .../lib_protocol/test/pbt/test_tez_repr.ml | 138 + .../test/pbt/test_zk_rollup_encoding.ml | 230 + .../test/regression/contracts/accounts.tz | 67 + .../test/regression/contracts/append.tz | 10 + .../test/regression/contracts/auction.tz | 30 + .../regression/contracts/big_map_union.tz | 14 + .../regression/contracts/check_signature.tz | 11 + .../test/regression/contracts/comb-get.tz | 27 + .../test/regression/contracts/comb-set.tz | 13 + .../test/regression/contracts/concat.tz | 9 + .../test/regression/contracts/conditionals.tz | 12 + .../test/regression/contracts/cps_fact.tz | 28 + .../test/regression/contracts/dign.tz | 11 + .../test/regression/contracts/dipn.tz | 15 + .../test/regression/contracts/dugn.tz | 14 + .../test/regression/contracts/ediv.tz | 28 + .../test/regression/contracts/faucet.tz | 17 + .../contracts/get_and_update_map.tz | 7 + .../test/regression/contracts/if.tz | 7 + .../regression/contracts/insertion_sort.tz | 21 + .../regression/contracts/list_map_block.tz | 9 + .../test/regression/contracts/loop_left.tz | 16 + .../test/regression/contracts/opt_map.tz | 12 + .../test/regression/contracts/packunpack.tz | 13 + .../test/regression/contracts/pexec.tz | 9 + .../test/regression/contracts/rec_id_unit.tz | 9 + .../test/regression/contracts/reverse_loop.tz | 12 + .../test/regression/contracts/set_delegate.tz | 3 + .../test/regression/contracts/shifts.tz | 7 + .../regression/contracts/spawn_identities.tz | 28 + .../test/regression/contracts/ticket_join.tz | 10 + .../test/regression/contracts/ticket_split.tz | 21 + .../test/regression/contracts/view_fib.tz | 6 + .../regression/contracts/view_toplevel_lib.tz | 80 + .../test/regression/contracts/xor.tz | 7 + .../lib_protocol/test/regression/dune | 52 + .../expected/test_logging.ml/accounts.out | 149 + .../expected/test_logging.ml/append.out | 135 + .../expected/test_logging.ml/auction.out | 415 ++ .../test_logging.ml/big_map_union.out | 499 ++ .../test_logging.ml/check_signature.out | 230 + .../expected/test_logging.ml/comb-get.out | 234 + .../expected/test_logging.ml/comb-set.out | 61 + .../expected/test_logging.ml/concat.out | 69 + .../expected/test_logging.ml/conditionals.out | 66 + .../expected/test_logging.ml/cps_fact.out | 276 + .../expected/test_logging.ml/dign.out | 107 + .../expected/test_logging.ml/dipn.out | 119 + .../expected/test_logging.ml/dugn.out | 97 + .../expected/test_logging.ml/ediv.out | 259 + .../expected/test_logging.ml/faucet.out | 122 + .../test_logging.ml/get_and_update_map.out | 53 + .../expected/test_logging.ml/if.out | 38 + .../test_logging.ml/insertion_sort.out | 5949 ++++++++++++++++ .../test_logging.ml/list_map_block.out | 451 ++ .../expected/test_logging.ml/loop_left.out | 253 + .../expected/test_logging.ml/opt_map.out | 82 + .../expected/test_logging.ml/packunpack.out | 103 + .../expected/test_logging.ml/pexec.out | 83 + .../expected/test_logging.ml/rec_id_unit.out | 56 + .../expected/test_logging.ml/reverse_loop.out | 261 + .../expected/test_logging.ml/set_delegate.out | 51 + .../expected/test_logging.ml/shifts.out | 44 + .../test_logging.ml/spawn_identities.out | 4341 ++++++++++++ .../expected/test_logging.ml/ticket_join.out | 42 + .../expected/test_logging.ml/ticket_split.out | 180 + .../expected/test_logging.ml/view_fib.out | 41 + .../test_logging.ml/view_toplevel_lib.out | 21 + .../expected/test_logging.ml/xor.out | 48 + .../test/regression/test_logging.ml | 398 ++ .../lib_protocol/test/unit/dune | 97 + .../test/unit/test_adaptive_issuance.ml | 616 ++ .../test/unit/test_adaptive_issuance_ema.ml | 310 + .../test/unit/test_alpha_context.ml | 296 + .../test/unit/test_bond_id_repr.ml | 118 + .../test/unit/test_consensus_key.ml | 260 + .../test/unit/test_contract_repr.ml | 124 + .../test/unit/test_dal_slot_proof.ml | 467 ++ .../test/unit/test_destination_repr.ml | 232 + .../lib_protocol/test/unit/test_fitness.ml | 164 + .../test/unit/test_fixed_point.ml | 196 + .../unit/test_full_staking_balance_repr.ml | 125 + .../lib_protocol/test/unit/test_gas_monad.ml | 225 + .../unit/test_global_constants_storage.ml | 431 ++ .../test/unit/test_level_module.ml | 286 + .../test/unit/test_liquidity_baking_repr.ml | 282 + .../test/unit/test_local_contexts.ml | 144 + .../test/unit/test_merkle_list.ml | 261 + .../test/unit/test_operation_repr.ml | 192 + .../lib_protocol/test/unit/test_percentage.ml | 173 + .../lib_protocol/test/unit/test_qty.ml | 167 + .../test/unit/test_raw_level_repr.ml | 188 + .../lib_protocol/test/unit/test_receipt.ml | 108 + .../lib_protocol/test/unit/test_round_repr.ml | 676 ++ .../lib_protocol/test/unit/test_saturation.ml | 267 + .../test/unit/test_sc_rollup_arith.ml | 813 +++ .../test/unit/test_sc_rollup_game.ml | 489 ++ .../test/unit/test_sc_rollup_inbox.ml | 944 +++ .../test/unit/test_sc_rollup_inbox_legacy.ml | 543 ++ .../test_sc_rollup_management_protocol.ml | 400 ++ .../test/unit/test_sc_rollup_storage.ml | 2800 ++++++++ .../test/unit/test_sc_rollup_wasm.ml | 435 ++ .../test/unit/test_skip_list_repr.ml | 188 + .../lib_protocol/test/unit/test_tez_repr.ml | 208 + .../lib_protocol/test/unit/test_time_repr.ml | 58 + .../test/unit/test_zk_rollup_storage.ml | 370 + .../lib_protocol/tez_repr.ml | 326 + .../lib_protocol/tez_repr.mli | 115 + .../lib_protocol/ticket_accounting.ml | 296 + .../lib_protocol/ticket_accounting.mli | 76 + .../lib_protocol/ticket_amount.ml | 48 + .../lib_protocol/ticket_amount.mli | 46 + .../lib_protocol/ticket_balance_key.ml | 92 + .../lib_protocol/ticket_balance_key.mli | 51 + .../lib_protocol/ticket_costs.ml | 56 + .../lib_protocol/ticket_costs.mli | 64 + .../lib_protocol/ticket_costs_generated.ml | 28 + .../lib_protocol/ticket_hash_builder.ml | 83 + .../lib_protocol/ticket_hash_builder.mli | 47 + .../lib_protocol/ticket_hash_repr.ml | 38 + .../lib_protocol/ticket_hash_repr.mli | 61 + .../lib_protocol/ticket_lazy_storage_diff.ml | 309 + .../lib_protocol/ticket_lazy_storage_diff.mli | 32 + .../lib_protocol/ticket_operations_diff.ml | 304 + .../lib_protocol/ticket_operations_diff.mli | 51 + .../lib_protocol/ticket_receipt.ml | 50 + .../lib_protocol/ticket_receipt.mli | 42 + .../lib_protocol/ticket_scanner.ml | 575 ++ .../lib_protocol/ticket_scanner.mli | 104 + .../lib_protocol/ticket_storage.ml | 133 + .../lib_protocol/ticket_storage.mli | 75 + .../lib_protocol/ticket_token.ml | 52 + .../lib_protocol/ticket_token.mli | 51 + .../lib_protocol/ticket_token_map.ml | 151 + .../lib_protocol/ticket_token_map.mli | 123 + .../lib_protocol/ticket_token_unparser.ml | 51 + .../lib_protocol/ticket_token_unparser.mli | 34 + .../lib_protocol/ticket_transfer.ml | 152 + .../lib_protocol/ticket_transfer.mli | 103 + .../lib_protocol/time_repr.ml | 74 + .../lib_protocol/time_repr.mli | 55 + src/proto_020_PsParisC/lib_protocol/token.ml | 284 + src/proto_020_PsParisC/lib_protocol/token.mli | 187 + .../lib_protocol/tx_rollup_l2_address.ml | 53 + .../lib_protocol/tx_rollup_l2_address.mli | 73 + .../lib_protocol/unstake_requests_storage.ml | 252 + .../lib_protocol/unstake_requests_storage.mli | 97 + .../unstaked_frozen_deposits_repr.ml | 103 + .../unstaked_frozen_deposits_repr.mli | 59 + .../unstaked_frozen_deposits_storage.ml | 101 + .../unstaked_frozen_deposits_storage.mli | 111 + .../unstaked_frozen_staker_repr.ml | 64 + .../unstaked_frozen_staker_repr.mli | 22 + .../lib_protocol/validate.ml | 2922 ++++++++ .../lib_protocol/validate.mli | 339 + .../lib_protocol/validate_errors.ml | 1377 ++++ .../lib_protocol/validate_errors.mli | 216 + .../lib_protocol/vote_repr.ml | 50 + .../lib_protocol/vote_repr.mli | 37 + .../lib_protocol/vote_storage.ml | 290 + .../lib_protocol/vote_storage.mli | 193 + .../lib_protocol/votes_EMA_repr.ml | 146 + .../lib_protocol/votes_EMA_repr.mli | 56 + .../lib_protocol/voting_period_repr.ml | 175 + .../lib_protocol/voting_period_repr.mli | 82 + .../lib_protocol/voting_period_storage.ml | 229 + .../lib_protocol/voting_period_storage.mli | 76 + .../lib_protocol/voting_services.ml | 162 + .../lib_protocol/voting_services.mli | 69 + .../lib_protocol/zk_rollup_account_repr.ml | 127 + .../lib_protocol/zk_rollup_account_repr.mli | 61 + .../lib_protocol/zk_rollup_apply.ml | 494 ++ .../lib_protocol/zk_rollup_apply.mli | 292 + .../zk_rollup_circuit_public_inputs_repr.ml | 73 + .../zk_rollup_circuit_public_inputs_repr.mli | 67 + .../lib_protocol/zk_rollup_errors.ml | 136 + .../lib_protocol/zk_rollup_operation_repr.ml | 78 + .../lib_protocol/zk_rollup_operation_repr.mli | 61 + .../lib_protocol/zk_rollup_parameters.ml | 51 + .../lib_protocol/zk_rollup_parameters.mli | 51 + .../lib_protocol/zk_rollup_repr.ml | 154 + .../lib_protocol/zk_rollup_repr.mli | 70 + .../lib_protocol/zk_rollup_scalar.ml | 37 + .../lib_protocol/zk_rollup_scalar.mli | 40 + .../lib_protocol/zk_rollup_state_repr.ml | 28 + .../lib_protocol/zk_rollup_state_repr.mli | 34 + .../lib_protocol/zk_rollup_storage.ml | 315 + .../lib_protocol/zk_rollup_storage.mli | 158 + .../lib_protocol/zk_rollup_ticket_repr.ml | 40 + .../lib_protocol/zk_rollup_ticket_repr.mli | 37 + .../lib_protocol/zk_rollup_update_repr.ml | 86 + .../lib_protocol/zk_rollup_update_repr.mli | 60 + .../lib_sc_rollup/README.md | 8 + .../lib_sc_rollup/context_helpers.ml | 75 + .../lib_sc_rollup/context_helpers.mli | 36 + src/proto_020_PsParisC/lib_sc_rollup/dune | 17 + .../lib_sc_rollup/game_helpers.ml | 178 + .../lib_sc_rollup/game_helpers.mli | 72 + .../lib_sc_rollup/pvm_in_memory.ml | 59 + .../lib_sc_rollup/pvm_in_memory.mli | 50 + .../lib_sc_rollup_layer2/README.md | 7 + .../lib_sc_rollup_layer2/dune | 21 + .../sc_rollup_proto_types.ml | 489 ++ .../sc_rollup_proto_types.mli | 207 + .../sc_rollup_services.ml | 462 ++ .../lib_sc_rollup_node/RPC_directory.ml | 338 + .../lib_sc_rollup_node/RPC_directory.mli | 33 + .../lib_sc_rollup_node/arith_pvm.ml | 112 + .../lib_sc_rollup_node/batcher_constants.ml | 56 + .../lib_sc_rollup_node/batcher_constants.mli | 32 + .../lib_sc_rollup_node/context_wrapper.ml | 110 + .../lib_sc_rollup_node/context_wrapper.mli | 48 + .../lib_sc_rollup_node/daemon_helpers.ml | 360 + .../lib_sc_rollup_node/daemon_helpers.mli | 30 + .../lib_sc_rollup_node/dal_pages_request.ml | 232 + .../lib_sc_rollup_node/dal_pages_request.mli | 82 + .../lib_sc_rollup_node/dal_slots_tracker.ml | 187 + .../lib_sc_rollup_node/dal_slots_tracker.mli | 41 + .../dal_slots_tracker_event.ml | 49 + .../lib_sc_rollup_node/dune | 76 + .../lib_sc_rollup_node/fueled_pvm.ml | 550 ++ .../lib_sc_rollup_node/inbox.ml | 308 + .../lib_sc_rollup_node/inbox.mli | 122 + .../lib_sc_rollup_node/inbox_event.ml | 45 + .../lib_sc_rollup_node/inbox_event.mli | 28 + .../lib_sc_rollup_node/layer1_helpers.ml | 270 + .../lib_sc_rollup_node/layer1_helpers.mli | 17 + .../lib_sc_rollup_node/outbox.ml | 87 + .../lib_sc_rollup_node/outbox.mli | 26 + .../lib_sc_rollup_node/pvm.ml | 35 + .../lib_sc_rollup_node/pvm_plugin.ml | 188 + .../lib_sc_rollup_node/pvm_plugin.mli | 27 + .../lib_sc_rollup_node/pvm_rpc.ml | 43 + .../lib_sc_rollup_node/pvm_sig.ml | 128 + .../refutation_game_helpers.ml | 383 ++ .../refutation_game_helpers.mli | 28 + .../lib_sc_rollup_node/reveals.ml | 170 + .../lib_sc_rollup_node/reveals.mli | 80 + .../lib_sc_rollup_node/riscv_pvm.ml | 219 + .../lib_sc_rollup_node/rollup_node_plugin.ml | 39 + .../lib_sc_rollup_node/sc_rollup_injector.ml | 466 ++ .../lib_sc_rollup_node/sc_rollup_injector.mli | 32 + .../sc_rollup_node_errors.ml | 33 + .../lib_sc_rollup_node/test/dune | 47 + .../test/serialized_proofs.ml | 121 + .../test/serialized_proofs.mli | 27 + .../test/test_octez_conversions.ml | 490 ++ .../lib_sc_rollup_node/wasm_2_0_0_pvm.ml | 202 + .../lib_sc_rollup_node/wasm_2_0_0_rpc.ml | 82 + src/proto_020_PsParisC/parameters/dune | 4 + 1110 files changed, 321812 insertions(+) create mode 100644 src/proto_020_PsParisC/bin_accuser/dune create mode 100644 src/proto_020_PsParisC/bin_accuser/main_accuser_019_PtParisB.ml create mode 100644 src/proto_020_PsParisC/bin_baker/dune create mode 100644 src/proto_020_PsParisC/bin_baker/main_baker_019_PtParisB.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/README.md create mode 100644 src/proto_020_PsParisC/lib_benchmark/autocomp.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/dune create mode 100644 src/proto_020_PsParisC/lib_benchmark/execution_context.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/kernel.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/int_map.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky_prim.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/monads.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/stores.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_inference.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_uf.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/uf.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/micheline_sampler.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/micheline_sampler.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/michelson_samplers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/michelson_samplers.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.mli create mode 100644 src/proto_020_PsParisC/lib_benchmark/mikhailsky_to_michelson.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/rules.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/sampling_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/state_space.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/test/dune create mode 100644 src/proto_020_PsParisC/lib_benchmark/test/test_autocompletion.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/test/test_distribution.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/test/test_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/test/test_sampling_code.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/test/test_sampling_data.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/type_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmark/type_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/apply_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.mli create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/cache_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/carbonated_map_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/dal_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/dune create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/encodings_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/gas_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/global_constants_storage_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_model.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_workload.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/michelson_commands.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.mli create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/michelson_types.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/registration_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/sapling_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/sapling_commands.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/sapling_generation.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/sc_rollup_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/script_repr_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/script_typed_ir_size_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/skip_list_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/storage_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/tags.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/ticket_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/translator_benchmarks.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/translator_model.ml create mode 100644 src/proto_020_PsParisC/lib_benchmarks_proto/translator_workload.ml create mode 100644 src/proto_020_PsParisC/lib_client/annotated_manager_operation.ml create mode 100644 src/proto_020_PsParisC/lib_client/annotated_manager_operation.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_args.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_args.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_context.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_context.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_contracts.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_contracts.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_fa12.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_fa12.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_multisig.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_multisig.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_programs.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_programs.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_rollups.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_rollups.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_tzt.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_tzt.mli create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_utils.ml create mode 100644 src/proto_020_PsParisC/lib_client/client_proto_utils.mli create mode 100644 src/proto_020_PsParisC/lib_client/dune create mode 100644 src/proto_020_PsParisC/lib_client/injection.ml create mode 100644 src/proto_020_PsParisC/lib_client/injection.mli create mode 100644 src/proto_020_PsParisC/lib_client/light.ml create mode 100644 src/proto_020_PsParisC/lib_client/limit.ml create mode 100644 src/proto_020_PsParisC/lib_client/limit.mli create mode 100644 src/proto_020_PsParisC/lib_client/managed_contract.ml create mode 100644 src/proto_020_PsParisC/lib_client/managed_contract.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_emacs.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_emacs.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_macros.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_macros.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_parser.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_parser.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_printer.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_printer.mli create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_stack.ml create mode 100644 src/proto_020_PsParisC/lib_client/michelson_v1_stack.mli create mode 100644 src/proto_020_PsParisC/lib_client/mockup.ml create mode 100644 src/proto_020_PsParisC/lib_client/operation_result.ml create mode 100644 src/proto_020_PsParisC/lib_client/operation_result.mli create mode 100644 src/proto_020_PsParisC/lib_client/protocol_client_context.ml create mode 100644 src/proto_020_PsParisC/lib_client/proxy.ml create mode 100644 src/proto_020_PsParisC/lib_client/test/dune create mode 100644 src/proto_020_PsParisC/lib_client/test/test_client_proto_context.ml create mode 100644 src/proto_020_PsParisC/lib_client/test/test_client_proto_contracts.ml create mode 100644 src/proto_020_PsParisC/lib_client/test/test_michelson_v1_macros.ml create mode 100644 src/proto_020_PsParisC/lib_client/test/test_proxy.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/alpha_commands_registration.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_context_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_contracts_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_fa12_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.mli create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.mli create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.mli create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.mli create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.mli create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.mli create mode 100644 src/proto_020_PsParisC/lib_client_commands/dune create mode 100644 src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.ml create mode 100644 src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.mli create mode 100644 src/proto_020_PsParisC/lib_client_sapling/context.ml create mode 100644 src/proto_020_PsParisC/lib_client_sapling/context.mli create mode 100644 src/proto_020_PsParisC/lib_client_sapling/dune create mode 100644 src/proto_020_PsParisC/lib_client_sapling/wallet.ml create mode 100644 src/proto_020_PsParisC/lib_client_sapling/wallet.mli create mode 100644 src/proto_020_PsParisC/lib_dac_plugin/dac_plugin_registration.ml create mode 100644 src/proto_020_PsParisC/lib_dac_plugin/dune create mode 100644 src/proto_020_PsParisC/lib_dac_plugin/test/dune create mode 100644 src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_pages_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_plugin_registration.ml create mode 100644 src/proto_020_PsParisC/lib_dac_plugin/test/test_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_dal/RPC_directory.ml create mode 100644 src/proto_020_PsParisC/lib_dal/RPC_directory.mli create mode 100644 src/proto_020_PsParisC/lib_dal/dal_plugin_registration.ml create mode 100644 src/proto_020_PsParisC/lib_dal/dal_proto_client.ml create mode 100644 src/proto_020_PsParisC/lib_dal/dal_proto_client.mli create mode 100644 src/proto_020_PsParisC/lib_dal/dal_services.ml create mode 100644 src/proto_020_PsParisC/lib_dal/dal_services.mli create mode 100644 src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.mli create mode 100644 src/proto_020_PsParisC/lib_dal/dune create mode 100644 src/proto_020_PsParisC/lib_dal/test/dune create mode 100644 src/proto_020_PsParisC/lib_dal/test/test_dal_slot_frame_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_dal/test/test_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/abstract_context_index.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/abstract_context_index.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_actions.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_actions.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_cache.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_commands.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_commands.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_commands_registration.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_configuration.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_configuration.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_errors.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_events.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_files.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_files.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_lib.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_lib.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_nonces.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_nonces.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_pow.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_pow.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_scheduling.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_scheduling.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_simulator.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_simulator.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_state.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_state.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_vdf.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/baking_vdf.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/block_forge.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/block_forge.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/client_baking_blocks.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/client_baking_blocks.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/client_daemon.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/client_daemon.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/delegate_events.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/dune create mode 100644 src/proto_020_PsParisC/lib_delegate/forge_worker.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/forge_worker.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/node_rpc.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/node_rpc.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/operation_pool.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/operation_pool.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/operation_selection.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/operation_selection.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/operation_worker.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/operation_worker.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/per_block_vote_file.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/per_block_vote_file.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/state_transitions.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/state_transitions.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/test/README.md create mode 100644 src/proto_020_PsParisC/lib_delegate/test/dune create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/broadcast_services.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_client_context.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_daemon.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_services.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune create mode 100644 src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune create mode 100644 src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.mli create mode 100644 src/proto_020_PsParisC/lib_delegate/test/tenderbrute/tenderbrute_main.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/test/test_scenario.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/vdf_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_delegate/vdf_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_injector/dune create mode 100644 src/proto_020_PsParisC/lib_injector/injector_plugin.ml create mode 100644 src/proto_020_PsParisC/lib_layer2_utils/dune create mode 100644 src/proto_020_PsParisC/lib_layer2_utils/layer1_services.ml create mode 100644 src/proto_020_PsParisC/lib_layer2_utils/layer1_services.mli create mode 100644 src/proto_020_PsParisC/lib_parameters/default_parameters.ml create mode 100644 src/proto_020_PsParisC/lib_parameters/default_parameters.mli create mode 100644 src/proto_020_PsParisC/lib_parameters/dune create mode 100644 src/proto_020_PsParisC/lib_parameters/gen.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/RPC.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/dune create mode 100644 src/proto_020_PsParisC/lib_plugin/index.mld create mode 100644 src/proto_020_PsParisC/lib_plugin/mempool.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/mempool.mli create mode 100644 src/proto_020_PsParisC/lib_plugin/metrics_plugin.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/plugin.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/plugin_errors.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/plugin_registerer.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.mli create mode 100644 src/proto_020_PsParisC/lib_plugin/test/dune create mode 100644 src/proto_020_PsParisC/lib_plugin/test/helpers.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/test/test_conflict_handler.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/test/test_consensus_filter.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_overtake.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_replace_by_fee.ml create mode 100644 src/proto_020_PsParisC/lib_plugin/view_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/.ocamlformat-ignore create mode 100644 src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL create mode 100644 src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/alpha_context.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/alpha_context.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/alpha_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/alpha_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/already_denounced_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/already_denounced_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/amendment.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/amendment.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/apply.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/apply.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/apply_internal_results.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/apply_internal_results.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/apply_operation_result.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/apply_operation_result.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/apply_results.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/apply_results.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/baking.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/baking.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/bitset.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/bitset.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/block_header_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/block_header_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/block_payload_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/block_payload_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/block_payload_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/block_payload_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/bond_id_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/bond_id_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/bootstrap_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/bootstrap_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/bounded_history_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/bounded_history_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/cache_memory_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/cache_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/cache_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/cache_repr_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/cache_repr_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/carbonated_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/carbonated_map.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/carbonated_map_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/commitment_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/commitment_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/commitment_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/commitment_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/constants_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/context_binary_proof.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/context_binary_proof.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_manager_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_manager_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/contract_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/cpmm.bin create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/cpmm.mligo create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/cpmm.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/lqt.bin create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/lqt.mligo create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/lqt.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/contracts/timelock_flip.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/cycle_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/cycle_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_apply.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_apply.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_costs_generated.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_errors_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_operations_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_operations_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_slot_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_slot_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_slot_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dal_slot_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_cycles.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_cycles.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_rewards.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_rewards.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_sampler.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_sampler.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/delegate_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/denunciations_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/denunciations_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dependent_bool.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/dependent_bool.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/deposits_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/deposits_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/destination_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/destination_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/destination_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/destination_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/entrypoint_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/entrypoint_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/fees_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/fees_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/fitness_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/fitness_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/fixed_point_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/fixed_point_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_input_size.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_input_size.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_limit_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_limit_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_monad.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_monad.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/gas_parameters.json create mode 100644 src/proto_020_PsParisC/lib_protocol/global_constants_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/global_constants_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/global_constants_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/global_constants_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/global_constants_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/indexable.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/indexable.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/init_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/init_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/legacy_script_patches.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/level_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/level_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/level_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/level_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/liquidity_baking_cpmm.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/liquidity_baking_lqt.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/local_gas_counter.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/local_gas_counter.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/main.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/main.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/manager_counter_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/manager_counter_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/manager_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/manager_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/mempool_validation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/mempool_validation.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/merkle_list.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/merkle_list.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/migration_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/migration_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/misc.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/misc.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/non_empty_string.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/non_empty_string.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/nonce_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/nonce_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/nonce_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/nonce_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/operation_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/operation_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/operation_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/operation_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/origination_nonce.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/origination_nonce.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/parameters_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/parameters_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/path_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/path_encoding.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/percentage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/percentage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/period_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/period_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ratio_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ratio_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/raw_context.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/raw_context.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/raw_context_intf.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/raw_level_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/raw_level_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/receipt_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/receipt_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/round_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/round_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sampler.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sampler.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sapling_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sapling_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sapling_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sapling_storage_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sapling_storage_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sapling_validator.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/saturation_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/saturation_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_PVM_sig.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_data_version_sig.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_errors.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollups.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/sc_rollups.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_big_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_big_map.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_bytes.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_bytes.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_cache.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_cache.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_comparable.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_comparable.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_expr_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_expr_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_int.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_int.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_interpreter.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_interpreter.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_interpreter_defs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_annot.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_annot.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_translator.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_translator.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_translator_config.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_unparser.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_ir_unparser.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_list.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_list.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_map.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_repr_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_repr_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_set.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_set.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_string.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_string.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_tc_context.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_tc_context.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_tc_errors.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_timestamp.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_timestamp.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/seed_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/seed_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/seed_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/seed_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/services_registration.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/services_registration.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/shared_stake.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/shared_stake.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/skip_list_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/skip_list_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/skip_list_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/slash_percentage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/slash_percentage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/slot_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/slot_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/stake_context.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/stake_context.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/stake_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/stake_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/stake_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/stake_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/staking.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/staking.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/state_hash.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/state_hash.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_description.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_description.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_functors.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_functors.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/storage_sigs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/README.md create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/README.md create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/account.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/account.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/adaptive_issuance_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/assert.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/block.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/block.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/consensus_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/context.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/context.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/contract_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_logic.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/dummy_zk_rollup.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/expr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/expr_common.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/lqt_fa12_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/merkle_list_helper.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/op.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/op.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/operation_generator.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/rewards.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/sapling_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/sc_rollup_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/test_global_constants.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/test_tez.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/testable.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/ticket_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_attestation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_baking.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_consensus_key.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_deactivation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_delegation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_attestation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_baking.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_preattestation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_frozen_deposits.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_helpers_rpcs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_participation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation_functor.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_seed.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_levels.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/big_interpreter_stack.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/emit.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/fail_rec.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_CREATE_CONTRACT.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SELF.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SET_DELEGATE.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_TRANSFER_TOKENS.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/int-store.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/omega.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply_store.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_store.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_double.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_drop.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_send.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_state_as_arg.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_push_sapling_state.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_use_existing_state.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/temp_big_maps.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_annotations.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_block_time_instructions.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_contract_event.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_global_constants_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_interpretation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lambda_normalization.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lazy_storage_diff.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_patched_contracts.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_sapling.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_cache.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_typed_ir_size.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_temp_big_maps.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_accounting.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance_key.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_direct_spending.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_lazy_storage_diff.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_manager.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_scanner.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_typechecking.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_activation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_combined_operations.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_failing_noop.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_origination.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_paid_storage_increase.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_reveal.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer_ticket.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_voting.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_zk_rollup.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_launch.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_constants.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_frozen_bonds.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_liquidity_baking.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_storage_functions.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/test_token.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/generators.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/manager_operation_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_1m_restriction.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_covalidity.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_manager_operation_validation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_mempool.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_sanity.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_validation_batch.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/valid_operations_generators.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/validate/validate_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/README.md create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/computation.wasm create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wasm create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wast create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_bad_fingerprint.wasm create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_random.wasm create mode 100644 src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/tx-kernel.wasm create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/liquidity_baking_pbt.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/saturation_fuzzing.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_balance_updates_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_bitset.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_bytes_conversion.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_carbonated_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_compare_operations.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_dal_slot_proof.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_gas_properties.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_merkle_list.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_operation_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_refutation_game.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_sampler.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_inbox.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_tick_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_comparison.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_roundtrip.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_tez_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/pbt/test_zk_rollup_encoding.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/accounts.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/append.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/auction.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/big_map_union.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/check_signature.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-get.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-set.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/concat.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/conditionals.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/cps_fact.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dign.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dipn.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dugn.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ediv.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/faucet.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/get_and_update_map.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/if.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/insertion_sort.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/list_map_block.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/loop_left.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/opt_map.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/packunpack.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/pexec.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/rec_id_unit.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/reverse_loop.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/set_delegate.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/shifts.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/spawn_identities.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_join.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_split.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_fib.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_toplevel_lib.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/contracts/xor.tz create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/accounts.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/append.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/auction.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/big_map_union.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/check_signature.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-get.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-set.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/concat.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/conditionals.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/cps_fact.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dign.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dipn.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dugn.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ediv.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/faucet.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/get_and_update_map.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/if.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/insertion_sort.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/list_map_block.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/loop_left.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/opt_map.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/packunpack.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/pexec.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/rec_id_unit.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/reverse_loop.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/set_delegate.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/shifts.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/spawn_identities.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_join.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_split.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_fib.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_toplevel_lib.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/xor.out create mode 100644 src/proto_020_PsParisC/lib_protocol/test/regression/test_logging.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/dune create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance_ema.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_alpha_context.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_bond_id_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_consensus_key.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_contract_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_dal_slot_proof.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_destination_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_fitness.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_fixed_point.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_full_staking_balance_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_gas_monad.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_global_constants_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_level_module.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_liquidity_baking_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_local_contexts.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_merkle_list.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_operation_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_percentage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_qty.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_raw_level_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_receipt.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_round_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_saturation.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_arith.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_game.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox_legacy.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_skip_list_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_tez_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_time_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/test/unit/test_zk_rollup_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/tez_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/tez_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_accounting.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_accounting.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_amount.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_amount.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_balance_key.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_balance_key.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_costs.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_costs.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_costs_generated.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_receipt.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_receipt.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_scanner.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_scanner.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_token.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_token.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_token_map.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_token_map.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_transfer.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/ticket_transfer.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/time_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/time_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/token.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/token.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/validate.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/validate.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/validate_errors.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/validate_errors.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/vote_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/vote_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/vote_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/vote_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/voting_period_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/voting_period_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/voting_period_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/voting_period_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/voting_services.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/voting_services.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_errors.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.mli create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.ml create mode 100644 src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/README.md create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/context_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/context_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/dune create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/game_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/game_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_layer2/README.md create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_layer2/dune create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_services.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/arith_pvm.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker_event.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/dune create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/fueled_pvm.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/inbox.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/inbox.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/outbox.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/outbox.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/pvm.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/pvm_rpc.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/pvm_sig.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/reveals.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/reveals.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/riscv_pvm.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/rollup_node_plugin.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_node_errors.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/test/dune create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.mli create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/test/test_octez_conversions.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_pvm.ml create mode 100644 src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_rpc.ml create mode 100644 src/proto_020_PsParisC/parameters/dune diff --git a/src/proto_020_PsParisC/bin_accuser/dune b/src/proto_020_PsParisC/bin_accuser/dune new file mode 100644 index 000000000000..503007b46e4d --- /dev/null +++ b/src/proto_020_PsParisC/bin_accuser/dune @@ -0,0 +1,30 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executable + (name main_accuser_019_PtParisB) + (public_name octez-accuser-PtParisB) + (package octez-accuser-PtParisB) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-protocol-019-PtParisB-libs.baking-commands + octez-libs.stdlib-unix + octez-shell-libs.client-base-unix) + (link_flags + (:standard) + (:include %{workspace_root}/static-link-flags.sexp) + (:include %{workspace_root}/macos-link-flags.sexp)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_baking_019_PtParisB_commands + -open Tezos_stdlib_unix + -open Tezos_client_base_unix)) diff --git a/src/proto_020_PsParisC/bin_accuser/main_accuser_019_PtParisB.ml b/src/proto_020_PsParisC/bin_accuser/main_accuser_019_PtParisB.ml new file mode 100644 index 000000000000..17efa9e364ad --- /dev/null +++ b/src/proto_020_PsParisC/bin_accuser/main_accuser_019_PtParisB.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash @@ fun _network -> + List.map (Tezos_clic.map_command (new Protocol_client_context.wrap_full)) + @@ Baking_commands.accuser_commands () + +let select_commands _ _ = + let open Lwt_result_syntax in + return + (List.map + (Tezos_clic.map_command (new Protocol_client_context.wrap_full)) + (Baking_commands.accuser_commands ())) + +let () = Client_main_run.run (module Daemon_config) ~select_commands diff --git a/src/proto_020_PsParisC/bin_baker/dune b/src/proto_020_PsParisC/bin_baker/dune new file mode 100644 index 000000000000..29400fb90f62 --- /dev/null +++ b/src/proto_020_PsParisC/bin_baker/dune @@ -0,0 +1,30 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executable + (name main_baker_019_PtParisB) + (public_name octez-baker-PtParisB) + (package octez-baker-PtParisB) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-protocol-019-PtParisB-libs.baking-commands + octez-libs.stdlib-unix + octez-shell-libs.client-base-unix) + (link_flags + (:standard) + (:include %{workspace_root}/static-link-flags.sexp) + (:include %{workspace_root}/macos-link-flags.sexp)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_baking_019_PtParisB_commands + -open Tezos_stdlib_unix + -open Tezos_client_base_unix)) diff --git a/src/proto_020_PsParisC/bin_baker/main_baker_019_PtParisB.ml b/src/proto_020_PsParisC/bin_baker/main_baker_019_PtParisB.ml new file mode 100644 index 000000000000..05b95923263b --- /dev/null +++ b/src/proto_020_PsParisC/bin_baker/main_baker_019_PtParisB.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash @@ fun _network -> + List.map (Tezos_clic.map_command (new Protocol_client_context.wrap_full)) + @@ Baking_commands.baker_commands () + +let select_commands _ _ = + let open Lwt_result_syntax in + return + (List.map + (Tezos_clic.map_command (new Protocol_client_context.wrap_full)) + (Baking_commands.baker_commands ())) + +(* This call is not strictly necessary as the parameters are initialized + lazily the first time a Sapling operation (validation or forging) is + done. This is what the client does. + For a long running binary however it is important to make sure that the + parameters files are there at the start and avoid failing much later while + validating an operation. Plus paying this cost upfront means that the first + validation will not be more expensive. *) +let () = Tezos_sapling.Core.Validator.init_params () + +module Config = struct + include Daemon_config + + let default_daily_logs_path = Some ("octez-baker-" ^ Protocol.name) +end + +let () = Client_main_run.run (module Config) ~select_commands diff --git a/src/proto_020_PsParisC/lib_benchmark/README.md b/src/proto_020_PsParisC/lib_benchmark/README.md new file mode 100644 index 000000000000..8adba76cbf90 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/README.md @@ -0,0 +1,42 @@ +# `Tezos_benchmark_alpha` + +This library is dedicated to sampling Michelson values and in particular +Michelson programs. + +## Architecture + +This library provides a sampling-based interface for well-typed +Michelson generation. Internally, this library is built on a sampler for an +intermediate language called Mikhailsky post-composed with a function to +map Mikhailsky terms to Michelson ones. + +### Layer 1: Mikhailsky + Mikhailsky corresponds to "Michelson with typed holes". Mikhailsky terms + are encoded inside Micheline. The library `lib_benchmark_type_inference` + provides the language definition as well as a type inference engine. + +### Layer 2: Sampling Mikhailsky terms + We sample Mikhailsky terms using a Markov chain where transitions correspond + to local rewriting rules. The state space of the Markov chain is defined + in `State_space` module. The rewriting infrastructure is provided in the + `Kernel` module by instantiating `lib_micheline_rewriting`. + Rewrites are checked to preserved well-typedness in the Mikhailsky sense + using the type inference engine provided with Mikhailsky. The `Rules` + module defines all rewriting rules, for both Mikhailsky _programs_ + (submodule `Rules.Instruction`) and _data_ + (submodule `Rules.Data_rewrite_leaves`). The function `Rules.rewriting` + performs the enumeration of possible rewritings. + + The Markov chain is biased to sample terms of a specified + size using the Metropolis-Hasting functors provided by `StaTz`. + The instantiation of this Markov chain is defined in the `Sampler` + module. + +### Layer 3: + Once we can sample Mikhaislky terms of a specified size, we need + to convert them to Michelson ones. This is performed in two steps. + - In the first step, we use the `Autocomplete` module to fill holes + in Mikhailsky terms (resp. data) with well-typed code (resp. data). + This is a relatively ad-hoc process. + - The last step is to convert Mikhaislky to Michelson using the + `Michelson` module. diff --git a/src/proto_020_PsParisC/lib_benchmark/autocomp.ml b/src/proto_020_PsParisC/lib_benchmark/autocomp.ml new file mode 100644 index 000000000000..0b3f0d8b62de --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/autocomp.ml @@ -0,0 +1,380 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Autocompletion functions (removing holes from Mikhailsky terms). *) + +open Sampling_helpers + +(* ------------------------------------------------------------------------- *) +(* Helpers *) + +let rec stack_length (stack : Type.Stack.t) acc = + match stack.node with + | Empty_t -> acc + | Stack_var_t _ -> acc + 1 + | Item_t (_, tl) -> stack_length tl (acc + 1) + +(* We need to sort and remove duplicate elements + of sets and maps to make them Michelson-compatible. *) +let sort_set_elements elements = + List.sort_uniq + (Structural_compare.compare + ~prim_compare:Mikhailsky.Mikhailsky_signature.compare) + elements + +let sort_map_elements elements = + let open Micheline in + List.sort_uniq + (fun node1 node2 -> + match (node1, node2) with + | ( Prim (_, Mikhailsky_prim.D_Elt, [k1; _v1], _), + Prim (_, Mikhailsky_prim.D_Elt, [k2; _v2], _) ) -> + Structural_compare.compare + ~prim_compare:Mikhailsky.Mikhailsky_signature.compare + k1 + k2 + | _ -> Stdlib.failwith "Autocomp.sort_map_elements: invalid Michelson map") + elements + +(* ------------------------------------------------------------------------- *) +(* Error handling *) + +type error_case = + | Cannot_complete_data of Mikhailsky.node * Kernel.Path.t + | Cannot_complete_code of Mikhailsky.node * Kernel.Path.t + +exception Autocompletion_error of error_case + +let cannot_complete_data node path = + raise (Autocompletion_error (Cannot_complete_data (node, path))) + +let cannot_complete_code node path = + raise (Autocompletion_error (Cannot_complete_code (node, path))) + +(* ------------------------------------------------------------------------- *) +(* Code & data autocompletion *) + +(* By default, comparable values are unit. *) +let default_comparable_type = Type.unit + +let generate_comparable _sp = Mikhailsky.Data.unit + +(* Instantiates variables in a base type, remaining variables + are mapped to some consistent choice of ground type + (this is made complicated by comparability constraints) *) +let rec instantiate_and_set ty = + let open Inference.M in + Inference.instantiate_base ty >>= fun ty -> replace_vars ty + +and replace_vars (ty : Type.Base.t) = + let open Inference.M in + let node = ty.node in + match node with + | Type.Base.Unit_t | Type.Base.Int_t | Type.Base.Nat_t | Type.Base.Bool_t + | Type.Base.String_t | Type.Base.Bytes_t | Type.Base.Key_hash_t + | Type.Base.Timestamp_t | Type.Base.Mutez_t | Type.Base.Key_t -> + return ty + | Type.Base.Var_t v -> ( + get_repr_exn v >>= fun repr -> + match repr with + | Inference.Stack_type _ -> assert false + | Inference.Base_type {comparable = _; repr = Some _} -> assert false + | Inference.Base_type {comparable; repr = None} -> ( + match comparable with + | Inference.Comparable -> return default_comparable_type + | Inference.Unconstrained | Inference.Not_comparable -> + return Type.unit)) + | Type.Base.Option_t ty -> + replace_vars ty >>= fun ty -> return (Type.option ty) + | Type.Base.Pair_t (lt, rt) -> + replace_vars lt >>= fun lt -> + replace_vars rt >>= fun rt -> return (Type.pair lt rt) + | Type.Base.Or_t (lt, rt) -> + replace_vars lt >>= fun lt -> + replace_vars rt >>= fun rt -> return (Type.or_ lt rt) + | Type.Base.List_t ty -> replace_vars ty >>= fun ty -> return (Type.list ty) + | Type.Base.Set_t ty -> replace_vars ty >>= fun ty -> return (Type.set ty) + | Type.Base.Map_t (k, v) -> + replace_vars k >>= fun k -> + replace_vars v >>= fun v -> return (Type.map k v) + | Type.Base.Lambda_t (dom, range) -> + replace_vars dom >>= fun dom -> + replace_vars range >>= fun range -> return (Type.lambda dom range) + +let rec instantiate_and_set_stack (stack_ty : Type.Stack.t) = + let open Inference.M in + let node = stack_ty.node in + match node with + | Type.Stack.Empty_t -> return Type.empty + | Type.Stack.Stack_var_t _ -> return Type.empty + | Type.Stack.Item_t (hd, tl) -> + instantiate_and_set hd >>= fun hd -> + instantiate_and_set_stack tl >>= fun tl -> return (Type.item hd tl) + +(* In the following we perform computations in the composite monad + (sampler o Inference.M.t), it is convenient to define the bind and return + explicitly. *) +module SM = struct + type 'a t = 'a Inference.M.t sampler + + let ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t = + fun m f rng_state s -> + let x, s = m rng_state s in + f x rng_state s + [@@inline] + + let sample : 'a sampler -> 'a Inference.M.t sampler = + fun x rng_state st -> (x rng_state, st) + [@@inline] + + let deterministic : 'a Inference.M.t -> 'a t = fun x _rng_state -> x + + let return x _ s = (x, s) [@@inline] +end + +module Make + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) = +struct + (* Generates minimally sized random data of specified type. + Used in autocompletion. *) + (* /!\ Always call [instantiate_and_set] on the type argument of + [generate_data]. /!\ *) + let rec generate_data : Type.Base.t -> Mikhailsky.node SM.t = + fun ty -> + let open SM in + let open Type.Base in + let desc = ty.node in + match desc with + | Var_t _v -> assert false + | Unit_t -> return Mikhailsky.Data.unit + | Int_t -> + sample @@ Michelson_base.int >>= fun i -> + let i = Protocol.Script_int.to_zint i in + return (Mikhailsky.Data.big_integer i) + | Nat_t -> + sample @@ Michelson_base.nat >>= fun n -> + let n = Protocol.Script_int.to_zint n in + return (Mikhailsky.Data.big_natural n) + | Bool_t -> + sample Base_samplers.uniform_bool >>= fun b -> + if b then return Mikhailsky.Data.true_ + else return Mikhailsky.Data.false_ + | String_t -> + sample Michelson_base.string >>= fun str -> + let str = Protocol.Script_string.to_string str in + return (Mikhailsky.Data.string str) + | Bytes_t -> + sample Michelson_base.bytes >>= fun bytes -> + return (Mikhailsky.Data.bytes bytes) + | Key_hash_t -> + sample Crypto_samplers.pkh >>= fun pkh -> + return (Mikhailsky.Data.key_hash pkh) + | Timestamp_t -> + sample Michelson_base.timestamp >>= fun tstamp -> + return (Mikhailsky.Data.timestamp tstamp) + | Mutez_t -> + sample Michelson_base.tez >>= fun tz -> + return (Mikhailsky.Data.mutez tz) + | Key_t -> + sample Crypto_samplers.pk >>= fun pk -> return (Mikhailsky.Data.key pk) + | Option_t ty -> + sample Base_samplers.uniform_bool >>= fun b -> + if b then return Mikhailsky.Data.none + else generate_data ty >>= fun res -> return (Mikhailsky.Data.some res) + | Pair_t (lty, rty) -> + generate_data lty >>= fun lv -> + generate_data rty >>= fun rv -> return (Mikhailsky.Data.pair lv rv) + | Or_t (lty, rty) -> + sample Base_samplers.uniform_bool >>= fun b -> + if b then generate_data lty >>= fun v -> return (Mikhailsky.Data.left v) + else generate_data rty >>= fun v -> return (Mikhailsky.Data.right v) + | List_t _ty -> return (Mikhailsky.Data.list []) + | Set_t _ty -> return (Mikhailsky.Data.set []) + | Map_t (_kty, _vty) -> return (Mikhailsky.Data.map []) + | Lambda_t (dom, range) -> + invent_term Type.(item dom empty) Type.(item range empty) + >>= fun code -> return (Mikhailsky.Data.lambda code) + + and invent_term (bef : Type.Stack.t) (aft : Type.Stack.t) : + Mikhailsky.node list SM.t = + let open SM in + install_dummy_stack aft [] >>= fun code -> + let terms = drop_stack bef code in + return terms + + and drop_stack (stack : Type.Stack.t) code = + Mikhailsky.Instructions.dropn (stack_length stack 0) :: code + + and install_dummy_stack (stack : Type.Stack.t) (acc : Mikhailsky.node list) = + let open SM in + match stack.node with + | Empty_t -> return acc + | Stack_var_t _ -> + let acc = Mikhailsky.(Instructions.push unit_ty Data.unit) :: acc in + return acc + | Item_t (hd, tl) -> + deterministic @@ instantiate_and_set hd >>= fun hd -> + (match hd.node with + | Lambda_t (dom, range) -> + invent_term Type.(item dom empty) Type.(item range empty) + >>= fun code -> + let instr = Mikhailsky.(prim I_LAMBDA [seq code] []) in + return instr + | _ -> + generate_data hd >>= fun term -> + let ty = Mikhailsky.unparse_ty_exn hd in + return (Mikhailsky.Instructions.push ty term)) + >>= fun instr -> install_dummy_stack tl (instr :: acc) + + (* Autocomplete Mikhailsky data. + When encountering a hole, we lookup its type and instantiate + some random data of the specified type. *) + let rec complete_data : + Mikhailsky.node -> Kernel.Path.t -> Mikhailsky.node SM.t = + let open SM in + fun node path -> + match node with + | Micheline.Int (_, _) | Micheline.String (_, _) | Micheline.Bytes (_, _) + -> + return node + | Micheline.Prim (_, D_Hole, _, _) -> ( + deterministic @@ Inference.M.get_data_annot path >>= fun ty_opt -> + match ty_opt with + | None -> cannot_complete_data node path + | Some ty -> + deterministic @@ instantiate_and_set ty >>= fun ty -> + generate_data ty) + | Micheline.Prim (_, A_Set, [Micheline.Seq (_, elements)], _) -> + complete_data_list (Kernel.Path.at_index 0 path) 0 elements [] + >>= fun elements -> + let elements = sort_set_elements elements in + return (Mikhailsky.Data.set elements) + | Micheline.Prim (_, A_Map, [Micheline.Seq (_, elements)], _) -> + complete_data_list (Kernel.Path.at_index 0 path) 0 elements [] + >>= fun elements -> + let elements = sort_map_elements elements in + return (Mikhailsky.Data.map elements) + | Micheline.Prim (_, prim, subterms, _) -> + complete_data_list path 0 subterms [] >>= fun subterms -> + return (Mikhailsky.prim prim subterms []) + | Micheline.Seq (_, subterms) -> + complete_data_list path 0 subterms [] >>= fun subterms -> + return (Mikhailsky.seq subterms) + + and complete_data_list path i subterms acc = + let open SM in + match subterms with + | [] -> return (List.rev acc) + | subterm :: tl -> + let path' = Kernel.Path.at_index i path in + complete_data subterm path' >>= fun term -> + complete_data_list path (i + 1) tl (term :: acc) + + let complete_data typing node rng_state = + let root_type_opt, _ = Inference.M.get_data_annot Kernel.Path.root typing in + match root_type_opt with + | None -> Stdlib.failwith "Autocomp.complete_data: cannot get type of expr" + | Some ty -> + let _, typing = Inference.instantiate_base ty typing in + let result, _ = + try complete_data node Kernel.Path.root rng_state typing + with Autocompletion_error (Cannot_complete_data (subterm, path)) -> + Format.eprintf "Cannot complete data@." ; + Format.eprintf "at path %s@." (Kernel.Path.to_string path) ; + Format.eprintf "%a@." Mikhailsky.pp subterm ; + Stdlib.failwith "in autocomp.ml: unrecoverable failure" + in + let typ, _typing = + try Inference.infer_data_with_state result + with Inference.Ill_typed_script error -> + Format.eprintf "%a@." Inference.pp_inference_error error ; + Format.eprintf "%a@." Mikhailsky.pp result ; + assert false + in + (result, typ) + + (* Autocomplete Mikhailsky code. *) + + let rec complete_code : + Mikhailsky.node -> Kernel.Path.t -> Mikhailsky.node SM.t = + let open SM in + fun node path -> + match node with + | Micheline.Int (_, _) | Micheline.String (_, _) | Micheline.Bytes (_, _) + -> + return node + | Micheline.Prim (_, I_Hole, _, _) -> ( + deterministic @@ Inference.M.get_instr_annot path >>= function + | None -> cannot_complete_code node path + | Some {bef; aft} -> + deterministic @@ Inference.instantiate bef >>= fun bef -> + deterministic @@ Inference.instantiate aft >>= fun aft -> + invent_term bef aft >>= fun code -> return (Mikhailsky.seq code)) + | Micheline.Prim (_, prim, subterms, _) -> + complete_code_list path 0 subterms [] >>= fun subterms -> + return (Mikhailsky.prim prim subterms []) + | Micheline.Seq (_, subterms) -> + complete_code_list path 0 subterms [] >>= fun subterms -> + return (Mikhailsky.seq subterms) + + and complete_code_list path i subterms acc = + let open SM in + match subterms with + | [] -> return (List.rev acc) + | subterm :: tl -> + let path' = Kernel.Path.at_index i path in + complete_code subterm path' >>= fun term -> + complete_code_list path (i + 1) tl (term :: acc) + + let complete_code typing node rng_state = + let root_type_opt, _ = + Inference.M.get_instr_annot Kernel.Path.root typing + in + match root_type_opt with + | None -> Stdlib.failwith "Autocomp.complete_code: cannot get type of expr" + | Some {bef; aft} -> + let _, typing = Inference.instantiate bef typing in + let _, typing = Inference.instantiate aft typing in + let result, _ = + try complete_code node Kernel.Path.root rng_state typing with + | Autocompletion_error (Cannot_complete_code (subterm, path)) -> + Format.eprintf "Cannot complete code@." ; + Format.eprintf "at path %s@." (Kernel.Path.to_string path) ; + Format.eprintf "%a@." Mikhailsky.pp subterm ; + Stdlib.failwith "in autocomp.ml: unrecoverable failure" + | _ -> assert false + in + let (bef, aft), typing = + try Inference.infer_with_state result + with Inference.Ill_typed_script error -> + Format.eprintf "%a@." Inference.pp_inference_error error ; + Format.eprintf "%a@." Mikhailsky.pp result ; + assert false + in + let bef, typing = instantiate_and_set_stack bef typing in + let aft, typing = instantiate_and_set_stack aft typing in + (result, (bef, aft), typing) +end diff --git a/src/proto_020_PsParisC/lib_benchmark/dune b/src/proto_020_PsParisC/lib_benchmark/dune new file mode 100644 index 000000000000..6e34995fefab --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/dune @@ -0,0 +1,33 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_benchmark_019_PtParisB) + (public_name tezos-benchmark-019-PtParisB) + (libraries + octez-libs.stdlib + octez-libs.base + octez-libs.error-monad + octez-libs.micheline + tezos-micheline-rewriting + tezos-benchmark + tezos-benchmark-type-inference-019-PtParisB + tezos-protocol-019-PtParisB.protocol + octez-libs.crypto + tezos-protocol-019-PtParisB.parameters + hashcons + octez-protocol-019-PtParisB-libs.test-helpers + prbnmcn-stats) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_stdlib + -open Tezos_base + -open Tezos_error_monad + -open Tezos_micheline + -open Tezos_micheline_rewriting + -open Tezos_benchmark + -open Tezos_benchmark_type_inference_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_019_PtParisB_test_helpers) + (private_modules kernel rules state_space)) diff --git a/src/proto_020_PsParisC/lib_benchmark/execution_context.ml b/src/proto_020_PsParisC/lib_benchmark/execution_context.ml new file mode 100644 index 000000000000..1dce1b3b59e6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/execution_context.ml @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +type context = Alpha_context.context * Script_interpreter.step_constants + +let initial_balance = 4_000_000_000_000L + +let context_init_memory ?dal ~rng_state () = + let open Lwt_result_wrap_syntax in + let dal_enable = Option.is_some dal in + let* block, accounts = + Context.init_n + ~rng_state + ~dal_enable + ?dal + ~bootstrap_balances: + [ + initial_balance; + initial_balance; + initial_balance; + initial_balance; + initial_balance; + ] + 5 + () + in + match accounts with + | [bs1; bs2; bs3; bs4; bs5] -> + return (`Mem_block (block, (bs1, bs2, bs3, bs4, bs5))) + | _ -> assert false + +let context_init ?dal ~rng_state () = context_init_memory ?dal ~rng_state () + +let make ?dal ~rng_state () = + let open Lwt_result_wrap_syntax in + let* context = context_init_memory ?dal ~rng_state () in + let amount = Alpha_context.Tez.one in + let chain_id = Tezos_crypto.Hashed.Chain_id.zero in + let now = Script_timestamp.of_zint Z.zero in + let level = Script_int.zero_n in + let open Script_interpreter in + let* block, step_constants = + match context with + | `Mem_block (block, (bs1, _, _, _, _)) -> + let sender = Alpha_context.Destination.Contract bs1 in + let payer = Contract_helpers.default_payer in + let self = Contract_helpers.default_self in + let step_constants = + { + sender; + payer; + self; + amount; + balance = Alpha_context.Tez.of_mutez_exn initial_balance; + chain_id; + now; + level; + } + in + return (block, step_constants) + in + let* csts = Context.get_constants (B block) in + let minimal_block_delay = + Protocol.Alpha_context.Period.to_seconds csts.parametric.minimal_block_delay + in + let* vs = + Incremental.begin_construction + ~timestamp: + (Time.Protocol.add block.header.shell.timestamp minimal_block_delay) + block + in + let ctxt = Incremental.alpha_ctxt vs in + let ctxt = + (* Required for eg Create_contract *) + Protocol.Alpha_context.Origination_nonce.init + ctxt + Tezos_crypto.Hashed.Operation_hash.zero + in + return (ctxt, step_constants) diff --git a/src/proto_020_PsParisC/lib_benchmark/kernel.ml b/src/proto_020_PsParisC/lib_benchmark/kernel.ml new file mode 100644 index 000000000000..0932302aa20b --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/kernel.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* ------------------------------------------------------------------------- *) +(* Instantiate rewriting subsystem *) + +module Lang = + Micheline_with_hash_consing.Make + (Mikhailsky.Mikhailsky_signature) + (struct + let initial_size = None + end) + +module Path = Mikhailsky.Path +module Patt = Pattern.Make (Mikhailsky.Mikhailsky_signature) (Lang) (Path) +module Rewriter = + Rewrite.Make (Mikhailsky.Mikhailsky_signature) (Lang) (Path) (Patt) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune new file mode 100644 index 000000000000..451962a79cbb --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune @@ -0,0 +1,23 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_benchmark_type_inference_019_PtParisB) + (public_name tezos-benchmark-type-inference-019-PtParisB) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.stdlib + octez-libs.error-monad + octez-libs.crypto + octez-libs.micheline + tezos-micheline-rewriting + tezos-protocol-019-PtParisB.protocol + hashcons) + (flags + (:standard) + -open Tezos_stdlib + -open Tezos_error_monad + -open Tezos_crypto + -open Tezos_micheline + -open Tezos_micheline_rewriting + -open Tezos_protocol_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.ml new file mode 100644 index 000000000000..d8c47801dca3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.ml @@ -0,0 +1,1150 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Micheline +module UF = Uf.UF + +(* The domain of comparability: + * + * Comparable Not_comparable + * ^ ^ + * \ / + * \ / + * Unconstrained + * + * The higher we go, the more information we have. + * This domain admits all glbs but not all lubs. + *) + +type comparability = Comparable | Not_comparable | Unconstrained + +let pp_comparability fmtr (cmp : comparability) = + match cmp with + | Comparable -> Format.fprintf fmtr "Comparable" + | Not_comparable -> Format.fprintf fmtr "Not_comparable" + | Unconstrained -> Format.fprintf fmtr "Unconstrained" + +let sup_comparability (c1 : comparability) (c2 : comparability) = + match (c1, c2) with + | Unconstrained, c | c, Unconstrained -> Some c + | Comparable, Comparable -> Some Comparable + | Not_comparable, Not_comparable -> Some Not_comparable + | Comparable, Not_comparable | Not_comparable, Comparable -> None + +type michelson_type = + | Base_type of {repr : Type.Base.t option; comparable : comparability} + | Stack_type of Type.Stack.t option + +type transformer = {bef : Type.Stack.t; aft : Type.Stack.t} + +let michelson_type_to_string (x : michelson_type) = + match x with + | Base_type {repr = None; comparable} -> + Format.asprintf "?::[%a]" pp_comparability comparable + | Base_type {repr = Some ty; comparable} -> + Format.asprintf "%a::[%a]" Type.Base.pp ty pp_comparability comparable + | Stack_type None -> "" + | Stack_type (Some sty) -> Format.asprintf "%a" Type.Stack.pp sty + +(* ------------------------------------------------------------------------- *) +(* Typechecking errors *) + +type inference_error = + (* | Expected_data_with_ground_type of Mikhailsky.Path.t * Mikhailsky.node *) + | Unhandled_micheline of Mikhailsky.Path.t * Mikhailsky.node + | Expected_micheline_prim + | Unsatisfiable_comparability_constraint of comparability_error_witness + | Base_types_incompatible of Type.Base.t * Type.Base.t + | Stack_types_incompatible of Type.Stack.t * Type.Stack.t + | Badly_typed_arithmetic of Mikhailsky_prim.prim * Type.Base.t * Type.Base.t + | Ill_formed_arithmetic of Mikhailsky.Path.t * Mikhailsky.node + | Cyclic_stack_type + | Cyclic_base_type + | Invalid_ast of string option * Mikhailsky.Path.t * Mikhailsky.node + +and comparability_error_witness = + | Comparability_error_types of michelson_type * michelson_type + | Comparability_error_tags of Type.Base.t * comparability * comparability + +let pp_inference_error fmtr (err : inference_error) = + match err with + (* | Expected_data_with_ground_type (path, node) -> + * let path = Mikhailsky.Path.to_string path in + * let node = Mikhailsky.to_string node in + * Format.fprintf fmtr "Expected data with ground type: %s at path %s" node path *) + | Unhandled_micheline (path, node) -> + let path = Mikhailsky.Path.to_string path in + let node = Mikhailsky.to_string node in + Format.fprintf fmtr "Unhandled micheline: %s at path %s" node path + | Expected_micheline_prim -> + Format.fprintf fmtr "%s" "Expected_micheline_prim" + | Unsatisfiable_comparability_constraint + (Comparability_error_types (ty1, ty2)) -> + let ty1 = michelson_type_to_string ty1 in + let ty2 = michelson_type_to_string ty2 in + Format.fprintf + fmtr + "Unsatisfiable comparability constraint: %s # %s" + ty1 + ty2 + | Unsatisfiable_comparability_constraint + (Comparability_error_tags (ty, cmp1, cmp2)) -> + Format.fprintf + fmtr + "Unsatisfiable comparability constraint: %a :: %a # %a" + Type.Base.pp + ty + pp_comparability + cmp1 + pp_comparability + cmp2 + | Base_types_incompatible (ty1, ty2) -> + Format.fprintf + fmtr + "Base types incompatible: %a %a" + Type.Base.pp + ty1 + Type.Base.pp + ty2 + | Stack_types_incompatible (sty1, sty2) -> + Format.fprintf + fmtr + "Stack types incompatible: %a %a" + Type.Stack.pp + sty1 + Type.Stack.pp + sty2 + | Badly_typed_arithmetic (prim, ty1, ty2) -> + Format.fprintf + fmtr + "Badly typed arithmetic: %a(%a, %a)" + Mikhailsky_prim.pp + prim + Type.Base.pp + ty1 + Type.Base.pp + ty2 + | Ill_formed_arithmetic (path, node) -> + let path = Mikhailsky.Path.to_string path in + let node = Mikhailsky.to_string node in + Format.fprintf fmtr "Ill formed arithmetic: %s at path %s" node path + | Cyclic_stack_type -> Format.fprintf fmtr "Cyclic stack type" + | Cyclic_base_type -> Format.fprintf fmtr "Cyclic base type" + | Invalid_ast (msg_opt, path, node) -> ( + let path = Mikhailsky.Path.to_string path in + let node = Mikhailsky.to_string node in + match msg_opt with + | None -> Format.fprintf fmtr "Invalid ast: %s at path %s" node path + | Some msg -> + Format.fprintf fmtr "Invalid ast: %s at path %s (%s)" node path msg) + +exception Ill_typed_script of inference_error + +let unsatisfiable_comparability ty cmp1 cmp2 = + raise + (Ill_typed_script + (Unsatisfiable_comparability_constraint + (Comparability_error_tags (ty, cmp1, cmp2)))) + +let invalid_ast ?msg path node = + raise (Ill_typed_script (Invalid_ast (msg, path, node))) + +let () = + Printexc.register_printer (fun exn -> + match exn with + | Ill_typed_script error -> + Some (Format.asprintf "%a" pp_inference_error error) + | _ -> None) + +(* ------------------------------------------------------------------------- *) + +module Repr_store = + Stores.Map + (Int_map) + (struct + type key = int + + type value = michelson_type + + let key_to_string = string_of_int + + let value_to_string = michelson_type_to_string + end) + +module Repr_sm = Monads.Make_state_monad (Repr_store) +module Path_map = Map.Make (Mikhailsky.Path) + +module Annot_instr_store = + Stores.Map + (Path_map) + (struct + type key = Mikhailsky.Path.t + + type value = transformer + + let key_to_string = Mikhailsky.Path.to_string + + let value_to_string {bef; aft} = + Format.asprintf "%a => %a" Type.Stack.pp bef Type.Stack.pp aft + end) + +module Annot_instr_sm = Monads.Make_state_monad (Annot_instr_store) + +module Annot_data_store = + Stores.Map + (Path_map) + (struct + type key = Mikhailsky.Path.t + + type value = Type.Base.t + + let key_to_string = Mikhailsky.Path.to_string + + let value_to_string ty = Format.asprintf "%a" Type.Base.pp ty + end) + +module Annot_data_sm = Monads.Make_state_monad (Annot_data_store) + +type state = { + uf : UF.M.state; + repr : Repr_sm.state; + annot_instr : Annot_instr_sm.state; + annot_data : Annot_data_sm.state; +} + +module M = struct + type 'a t = state -> 'a * state + + let empty : unit -> state = + fun () -> + { + uf = UF.M.empty (); + repr = Repr_sm.empty (); + annot_instr = Annot_instr_sm.empty (); + annot_data = Annot_data_sm.empty (); + } + + let ( >>= ) m f s = + let x, s = m s in + f x s + [@@inline] + + let return x s = (x, s) + + (* let run m = fst (m (empty ())) *) + + let uf_lift : 'a UF.M.t -> 'a t = + fun computation state -> + let res, uf = computation state.uf in + (res, {state with uf}) + [@@inline] + + let repr_lift : 'a Repr_sm.t -> 'a t = + fun computation state -> + let res, repr = computation state.repr in + (res, {state with repr}) + [@@inline] + + let annot_instr_lift : 'a Annot_instr_sm.t -> 'a t = + fun computation state -> + let res, annot_instr = computation state.annot_instr in + (res, {state with annot_instr}) + [@@inline] + + let annot_data_lift : 'a Annot_data_sm.t -> 'a t = + fun computation state -> + let res, annot_data = computation state.annot_data in + (res, {state with annot_data}) + [@@inline] + + let set_repr k v = repr_lift (Repr_sm.set k v) [@@inline] + + let get_repr_exn k = + repr_lift (Repr_sm.get k) >>= function + | None -> Stdlib.failwith "get_repr_exn" + | Some res -> return res + [@@inline] + + let set_instr_annot k v = annot_instr_lift (Annot_instr_sm.set k v) [@@inline] + + let get_instr_annot k = annot_instr_lift (Annot_instr_sm.get k) [@@inline] + + let set_data_annot k v = annot_data_lift (Annot_data_sm.set k v) [@@inline] + + let get_data_annot k = annot_data_lift (Annot_data_sm.get k) [@@inline] + + let get_state state = (state, state) +end + +module S = Set.Make (Int) + +let rec instantiate (encountered : S.t) (stack_ty : Type.Stack.t) : + Type.Stack.t M.t = + let open Type.Stack in + let open M in + if S.mem stack_ty.tag encountered then + raise (Ill_typed_script Cyclic_stack_type) + else + let encountered = S.add stack_ty.tag encountered in + match stack_ty.node with + | Empty_t -> return stack_ty + | Stack_var_t x -> ( + uf_lift (UF.find x) >>= fun root -> + get_repr_exn root >>= function + | Stack_type None -> return (Type.stack_var root) + | Stack_type (Some ty) -> instantiate encountered ty + | _ -> assert false) + | Item_t (head, tail) -> + instantiate_base S.empty head >>= fun head -> + instantiate encountered tail >>= fun tail -> + return (Type.item head tail) + +and instantiate_base (encountered : S.t) (ty : Type.Base.t) : Type.Base.t M.t = + let open Type.Base in + let open M in + if S.mem ty.tag encountered then raise (Ill_typed_script Cyclic_base_type) + else + let encountered = S.add ty.tag encountered in + match ty.node with + | Unit_t | Int_t | Nat_t | Bool_t | String_t | Bytes_t | Key_hash_t | Key_t + | Timestamp_t | Mutez_t -> + return ty + | Option_t ty -> + instantiate_base encountered ty >>= fun ty -> return (Type.option ty) + | List_t ty -> + instantiate_base encountered ty >>= fun ty -> return (Type.list ty) + | Set_t ty -> + instantiate_base encountered ty >>= fun ty -> return (Type.set ty) + | Map_t (kty, vty) -> + instantiate_base encountered kty >>= fun kty -> + instantiate_base encountered vty >>= fun vty -> + return (Type.map kty vty) + | Pair_t (lty, rty) -> + instantiate_base encountered lty >>= fun lty -> + instantiate_base encountered rty >>= fun rty -> + return (Type.pair lty rty) + | Or_t (lty, rty) -> + instantiate_base encountered lty >>= fun lty -> + instantiate_base encountered rty >>= fun rty -> + return (Type.or_ lty rty) + | Lambda_t (dom, range) -> + instantiate_base encountered dom >>= fun dom -> + instantiate_base encountered range >>= fun range -> + return (Type.lambda dom range) + | Var_t x -> ( + uf_lift (UF.find x) >>= fun root -> + get_repr_exn root >>= function + | Base_type {repr = None; _} -> return (Type.var root) + | Base_type {repr = Some ty; _} -> instantiate_base encountered ty + | _ -> assert false) + +let instantiate_base base_ty = instantiate_base S.empty base_ty + +let instantiate stack_ty = instantiate S.empty stack_ty + +let rec unify (x : Type.Stack.t) (y : Type.Stack.t) : unit M.t = + let open Type.Stack in + let open M in + let unify_single_stack v x = + (match Type.Stack.vars x with + | None -> return () + | Some v' -> + if v = v' then raise (Ill_typed_script Cyclic_stack_type) else return ()) + >>= fun () -> + M.uf_lift (UF.find v) >>= fun root -> + get_repr_exn root >>= fun repr -> + merge_reprs (Stack_type (Some x)) repr >>= fun repr -> set_repr root repr + in + if x.tag = y.tag then return () + else + match (x.node, y.node) with + | Empty_t, Empty_t -> return () + | Stack_var_t x, Stack_var_t y -> + M.uf_lift (UF.find x) >>= fun root_x -> + M.uf_lift (UF.find y) >>= fun root_y -> + get_repr_exn root_x >>= fun repr_x -> + get_repr_exn root_y >>= fun repr_y -> + M.uf_lift (UF.union x y) >>= fun root -> + merge_reprs repr_x repr_y >>= fun repr -> set_repr root repr + | Stack_var_t v, _ -> unify_single_stack v y + | _, Stack_var_t v -> unify_single_stack v x + | Item_t (ty1, tail1), Item_t (ty2, tail2) -> + unify_base ty1 ty2 >>= fun () -> + unify tail1 tail2 >>= fun () -> return () + | _ -> raise (Ill_typed_script (Stack_types_incompatible (x, y))) + +and unify_base (x : Type.Base.t) (y : Type.Base.t) : unit M.t = + let open Type.Base in + let open M in + let unify_single_var v x = + (if List.mem v (Type.Base.vars x) then + raise (Ill_typed_script Cyclic_base_type) + else return ()) + >>= fun () -> + M.uf_lift (UF.find v) >>= fun root -> + get_repr_exn root >>= fun repr -> + get_comparability x >>= fun comparable -> + merge_reprs (Base_type {repr = Some x; comparable}) repr >>= fun repr -> + set_repr root repr + in + if x.tag = y.tag then return () + else + match (x.node, y.node) with + | Unit_t, Unit_t + | Int_t, Int_t + | Nat_t, Nat_t + | Bool_t, Bool_t + | String_t, String_t + | Bytes_t, Bytes_t + | Key_hash_t, Key_hash_t + | Timestamp_t, Timestamp_t + | Mutez_t, Mutez_t + | Key_t, Key_t -> + return () + | Option_t x, Option_t y -> unify_base x y + | List_t x, List_t y -> unify_base x y + | Set_t x, Set_t y -> unify_base x y + | Map_t (kx, vx), Map_t (ky, vy) -> + unify_base kx ky >>= fun () -> unify_base vx vy + | Pair_t (x, x'), Pair_t (y, y') -> + unify_base x y >>= fun () -> unify_base x' y' + | Or_t (x, x'), Or_t (y, y') -> + unify_base x y >>= fun () -> unify_base x' y' + | Lambda_t (x, x'), Lambda_t (y, y') -> + unify_base x y >>= fun () -> unify_base x' y' + | Var_t x, Var_t y -> + M.uf_lift (UF.find x) >>= fun root_x -> + M.uf_lift (UF.find y) >>= fun root_y -> + get_repr_exn root_x >>= fun repr_x -> + get_repr_exn root_y >>= fun repr_y -> + M.uf_lift (UF.union x y) >>= fun root -> + merge_reprs repr_x repr_y >>= fun repr -> set_repr root repr + | Var_t v, _ -> unify_single_var v y + | _, Var_t v -> unify_single_var v x + | _ -> + instantiate_base x >>= fun x -> + instantiate_base y >>= fun y -> + raise (Ill_typed_script (Base_types_incompatible (x, y))) + +and merge_reprs (repr1 : michelson_type) (repr2 : michelson_type) : + michelson_type M.t = + let open M in + match (repr1, repr2) with + | (Stack_type None as repr), Stack_type None + | (Stack_type (Some _) as repr), Stack_type None + | Stack_type None, (Stack_type (Some _) as repr) -> + return repr + | (Stack_type (Some sty1) as repr), Stack_type (Some sty2) -> + unify sty1 sty2 >>= fun () -> return repr + | ( Base_type {repr = opt1; comparable = cmp1}, + Base_type {repr = opt2; comparable = cmp2} ) -> ( + let comparable_opt = sup_comparability cmp1 cmp2 in + match comparable_opt with + | None -> + raise + (Ill_typed_script + (Unsatisfiable_comparability_constraint + (Comparability_error_types (repr1, repr2)))) + | Some comparable -> ( + match (opt1, opt2) with + | None, None -> return (Base_type {repr = None; comparable}) + | (Some ty as repr), None -> + assert_comparability comparable ty >>= fun () -> + return (Base_type {repr; comparable}) + | None, (Some ty as repr) -> + assert_comparability comparable ty >>= fun () -> + return (Base_type {repr; comparable}) + | Some ty1, Some ty2 -> + unify_base ty1 ty2 >>= fun () -> + assert_comparability comparable ty1 >>= fun () -> + assert_comparability comparable ty2 >>= fun () -> + return (Base_type {repr = opt1; comparable}))) + | _ -> assert false + +and assert_comparability comparable ty = + assert_comparability_aux comparable ty [] + +and assert_comparability_aux lower_bound (ty : Type.Base.t) + (encountered : int list) : unit M.t = + let open M in + if List.mem ty.tag encountered then raise (Ill_typed_script Cyclic_base_type) + else + let encountered = ty.tag :: encountered in + match ty.node with + | Var_t v -> ( + uf_lift (UF.find v) >>= fun root -> + get_repr_exn root >>= fun repr -> + match repr with + | Base_type {repr = None; comparable} -> ( + match sup_comparability comparable lower_bound with + | None -> unsatisfiable_comparability ty comparable lower_bound + | Some comparable -> + set_repr root (Base_type {repr = None; comparable})) + | Base_type {repr = Some ty; comparable} -> ( + match sup_comparability comparable lower_bound with + | None -> unsatisfiable_comparability ty comparable lower_bound + | Some comparable -> + assert_comparability_aux lower_bound ty encountered + >>= fun () -> + set_repr root (Base_type {repr = Some ty; comparable})) + | Stack_type _ -> assert false) + | List_t _ | Set_t _ | Map_t _ | Lambda_t _ | Key_t -> ( + match lower_bound with + | Unconstrained | Not_comparable -> return () + | Comparable -> unsatisfiable_comparability ty Unconstrained lower_bound + ) + | Unit_t | Int_t | Nat_t | Bool_t | String_t | Bytes_t | Key_hash_t + | Timestamp_t | Mutez_t -> + (* if not (le_comparability lower_bound Comparable) then + * unsatisfiable_comparability ty Comparable lower_bound + * else *) + return () + | Option_t ty -> ( + match lower_bound with + | Comparable -> assert_comparability_aux Comparable ty encountered + | Not_comparable | Unconstrained -> return ()) + | Pair_t (l, r) -> ( + match lower_bound with + | Comparable -> + assert_comparability_aux Comparable l encountered >>= fun () -> + assert_comparability_aux Comparable r encountered + | Unconstrained | Not_comparable -> return ()) + | Or_t (l, r) -> ( + match lower_bound with + | Comparable -> + assert_comparability_aux Comparable l encountered >>= fun () -> + assert_comparability_aux Comparable r encountered + | Unconstrained | Not_comparable -> return ()) + +and get_comparability (ty : Type.Base.t) : comparability M.t = + let open M in + match ty.node with + | Var_t v -> ( + get_repr_exn v >>= fun repr -> + match repr with + | Stack_type _ -> assert false + | Base_type {comparable; _} -> return comparable) + | Unit_t | Int_t | Nat_t | Bool_t | String_t | Bytes_t | Key_hash_t + | Timestamp_t | Mutez_t -> + return Comparable + | List_t _ | Set_t _ | Map_t _ | Lambda_t _ | Key_t -> return Not_comparable + | Option_t ty -> get_comparability ty + | Or_t (lt, rt) | Pair_t (lt, rt) -> ( + get_comparability lt >>= fun lc -> + get_comparability rt >>= fun rc -> + match (lc, rc) with + | Comparable, Comparable -> return Comparable + | _ -> return Unconstrained) + +let fresh = + let x = ref ~-1 in + fun () -> + incr x ; + !x + +let exists_stack : unit -> Type.Stack.t M.t = + let open M in + fun () -> + let fresh = fresh () in + uf_lift (UF.add fresh) >>= fun () -> + set_repr fresh (Stack_type None) >>= fun () -> return (Type.stack_var fresh) + +let exists : unit -> Type.Base.t M.t = + let open M in + fun () -> + let fresh = fresh () in + uf_lift (UF.add fresh) >>= fun () -> + set_repr fresh (Base_type {repr = None; comparable = Unconstrained}) + >>= fun () -> return (Type.var fresh) + +let exists_cmp : unit -> Type.Base.t M.t = + let open M in + fun () -> + let fresh = fresh () in + uf_lift (UF.add fresh) >>= fun () -> + set_repr fresh (Base_type {repr = None; comparable = Comparable}) + >>= fun () -> return (Type.var fresh) + +(* Adapted from [script_ir_translator] *) +let parse_uint30 n : int = + let max_uint30 = 0x3fffffff in + match n with + | Micheline.Int (_, n') + when Compare.Z.(Z.zero <= n') && Compare.Z.(n' <= Z.of_int max_uint30) -> + Z.to_int n' + | _ -> assert false + +(* encodes the per-instruction relationship between input and output types + of binary arithmetic operations. *) +let arith_type (instr : Mikhailsky_prim.prim) (ty1 : Type.Base.t) + (ty2 : Type.Base.t) : Type.Base.t option = + match (instr, ty1.node, ty2.node) with + | (I_ADD | I_MUL), Int_t, Int_t + | (I_ADD | I_MUL), Int_t, Nat_t + | (I_ADD | I_MUL), Nat_t, Int_t -> + Some Type.int + | (I_ADD | I_MUL), Nat_t, Nat_t -> Some Type.nat + | I_SUB, Int_t, Int_t + | I_SUB, Int_t, Nat_t + | I_SUB, Nat_t, Int_t + | I_SUB, Nat_t, Nat_t + | I_SUB, Timestamp_t, Timestamp_t -> + Some Type.int + | I_EDIV, Int_t, Int_t + | I_EDIV, Int_t, Nat_t + | I_EDIV, Nat_t, Int_t + | I_EDIV, Nat_t, Nat_t -> + Some Type.(option (pair nat nat)) + (* Timestamp *) + | I_ADD, Timestamp_t, Int_t + | I_ADD, Int_t, Timestamp_t + | I_SUB, Timestamp_t, Int_t -> + Some Type.timestamp + (* Mutez *) + | I_ADD, Mutez_t, Mutez_t + | I_SUB, Mutez_t, Mutez_t + | I_MUL, Mutez_t, Nat_t + | I_MUL, Nat_t, Mutez_t -> + Some Type.mutez + | I_EDIV, Mutez_t, Nat_t -> Some Type.(option (pair mutez mutez)) + | I_EDIV, Mutez_t, Mutez_t -> Some Type.(option (pair nat mutez)) + | _ -> None + +let rec generate_constraints (path : Mikhailsky.Path.t) (node : Mikhailsky.node) + (bef : Type.Stack.t) (aft : Type.Stack.t) : unit M.t = + let open M in + set_instr_annot path {bef; aft} >>= fun () -> + match node with + | Int (_, _) -> + assert false (* Ints should always be guarded by annotations *) + | String (_, _) | Bytes (_, _) -> + raise (Ill_typed_script Expected_micheline_prim) + (* Hole *) + | Prim (_, I_Hole, [], _) -> return () + (* Stack ops - simple cases *) + | Prim (_loc, I_DROP, [], _annot) -> + exists () >>= fun top -> unify bef (Type.item top aft) + | Prim (_loc, I_DROP, [n], _annot) -> + let n = parse_uint30 n in + generate_constraints_dropn n bef aft + | Prim (_loc, I_DUP, [], _annot) -> + exists () >>= fun top -> + exists_stack () >>= fun rest -> + unify bef Type.(item top rest) >>= fun () -> + unify aft Type.(item top (item top rest)) + | Prim (_loc, I_SWAP, [], _annot) -> + exists () >>= fun a -> + exists () >>= fun b -> + exists_stack () >>= fun rest -> + unify bef Type.(item a (item b rest)) >>= fun () -> + unify aft Type.(item b (item a rest)) + | Prim (_loc, I_PUSH, [t; d], _annot) -> + let ty = + Mikhailsky.parse_ty + ~allow_big_map:false + ~allow_operation:false + ~allow_contract:false + t + in + generate_constraints_data (Mikhailsky.Path.at_index 1 path) d ty + >>= fun () -> + (* assert_data_has_ground_type (Mikhailsky.Path.at_index 1 path) d ty >>= fun () -> *) + unify aft Type.(item ty bef) + | Prim (_loc, I_UNIT, [], _annot) -> unify aft Type.(item unit bef) + | Prim (_loc, I_DIP, [code], _annot) -> + exists () >>= fun top -> + exists_stack () >>= fun bef_rest -> + exists_stack () >>= fun aft_rest -> + unify bef Type.(item top bef_rest) >>= fun () -> + unify aft Type.(item top aft_rest) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + bef_rest + aft_rest + (* TODO: DIGn, etc *) + (* Option-related instructions *) + | Prim (_, I_SOME, [], _) -> + exists () >>= fun top -> + exists_stack () >>= fun rest -> + unify bef Type.(item top rest) >>= fun () -> + unify aft Type.(item (option top) rest) + | Prim (_, I_NONE, [t], _) -> + let ty = + Mikhailsky.parse_ty + ~allow_big_map:true + ~allow_operation:true + ~allow_contract:true + t + in + unify aft Type.(item (option ty) bef) + | Prim (_, I_IF_NONE, [bt; bf], _) -> + exists () >>= fun a -> + exists_stack () >>= fun rest -> + unify bef Type.(item (option a) rest) >>= fun () -> + generate_constraints (Mikhailsky.Path.at_index 0 path) bt rest aft + >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 1 path) + bf + Type.(item a rest) + aft + (* bool-based control flow *) + | Prim (_, I_IF, [bt; bf], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item bool rest) >>= fun () -> + generate_constraints (Mikhailsky.Path.at_index 0 path) bt rest aft + >>= fun () -> + generate_constraints (Mikhailsky.Path.at_index 1 path) bf rest aft + | Prim (_, I_LOOP, [body], _) -> + unify bef Type.(item bool aft) >>= fun () -> + generate_constraints (Mikhailsky.Path.at_index 0 path) body aft bef + (* Boolean binops *) + | Prim (_, I_AND, [], _) | Prim (_, I_OR, [], _) | Prim (_, I_XOR, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item bool (item bool rest)) >>= fun () -> + unify aft Type.(item bool rest) + (* Arithmetic *) + | Prim (_, ((I_ADD | I_SUB | I_MUL | I_EDIV) as instr), [ty1; ty2], _) -> ( + let ty1 = + Mikhailsky.parse_ty + ~allow_big_map:false + ~allow_operation:false + ~allow_contract:false + ty1 + in + let ty2 = + Mikhailsky.parse_ty + ~allow_big_map:false + ~allow_operation:false + ~allow_contract:false + ty2 + in + match arith_type instr ty1 ty2 with + | None -> + raise (Ill_typed_script (Badly_typed_arithmetic (instr, ty1, ty2))) + | Some ret -> + exists_stack () >>= fun rest -> + unify bef Type.(item ty1 (item ty2 rest)) >>= fun () -> + unify aft Type.(item ret rest)) + | Prim (_, (I_ADD | I_SUB | I_MUL | I_EDIV), _, _) -> + raise (Ill_typed_script (Ill_formed_arithmetic (path, node))) + | Prim (_, I_COMPARE, [], _) -> + exists_cmp () >>= fun a -> + exists_stack () >>= fun rest -> + unify bef Type.(item a (item a rest)) >>= fun () -> + unify aft Type.(item int rest) + | Prim (_, I_ABS, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item int rest) >>= fun () -> + unify aft Type.(item nat rest) + | Prim (_, I_GT, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item int rest) >>= fun () -> + unify aft Type.(item bool rest) + (* Strings/bytes *) + | Prim (_, I_CONCAT, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item string (item string rest)) >>= fun () -> + unify aft Type.(item string rest) + | Prim (_, I_SIZE_STRING, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item string rest) >>= fun () -> + unify aft Type.(item nat rest) + | Prim (_, I_SIZE_BYTES, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item bytes rest) >>= fun () -> + unify aft Type.(item nat rest) + (* Crypto *) + | Prim (_, I_SHA256, [], _) + | Prim (_, I_SHA512, [], _) + | Prim (_, I_BLAKE2B, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item bytes rest) >>= fun () -> + unify aft Type.(item bytes rest) + | Prim (_, I_HASH_KEY, [], _) -> + exists_stack () >>= fun rest -> + unify bef Type.(item key rest) >>= fun () -> + unify aft Type.(item key_hash rest) + (* sets *) + | Prim (_, I_EMPTY_SET, [], _) -> + exists_cmp () >>= fun cmpty -> unify aft Type.(item (set cmpty) bef) + | Prim (_, I_UPDATE_SET, [], _) -> + exists_cmp () >>= fun cty -> + exists_stack () >>= fun rest -> + unify bef Type.(item cty (item bool (item (set cty) rest))) >>= fun () -> + unify aft Type.(item (set cty) rest) + | Prim (_, I_SIZE_SET, [], _) -> + exists_cmp () >>= fun cmpty -> + exists_stack () >>= fun rest -> + unify bef Type.(item (set cmpty) rest) >>= fun () -> + unify aft Type.(item nat rest) + | Prim (_, I_ITER_SET, [code], _) -> + exists_cmp () >>= fun cmpty -> + unify bef Type.(item (set cmpty) aft) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + Type.(item cmpty aft) + aft + | Prim (_, I_MEM_SET, [], _) -> + exists_cmp () >>= fun cmpty -> + exists_stack () >>= fun rest -> + unify bef Type.(item cmpty (item (set cmpty) rest)) >>= fun () -> + unify aft Type.(item bool rest) + (* maps *) + | Prim (_, I_EMPTY_MAP, [], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty -> unify aft Type.(item (map kty vty) bef) + | Prim (_, I_UPDATE_MAP, [], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty -> + exists_stack () >>= fun rest -> + unify bef Type.(item kty (item (option vty) (item (map kty vty) rest))) + >>= fun () -> unify aft Type.(item (map kty vty) rest) + | Prim (_, I_SIZE_MAP, [], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty -> + exists_stack () >>= fun rest -> + unify bef Type.(item (map kty vty) rest) >>= fun () -> + unify aft Type.(item nat rest) + | Prim (_, I_ITER_MAP, [code], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty -> + unify bef Type.(item (map kty vty) aft) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + Type.(item (pair kty vty) aft) + aft + | Prim (_, I_MAP_MAP, [code], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty1 -> + exists () >>= fun vty2 -> + exists_stack () >>= fun rest -> + unify bef Type.(item (map kty vty1) rest) >>= fun () -> + unify aft Type.(item (map kty vty2) rest) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + Type.(item (pair kty vty1) rest) + Type.(item vty2 rest) + | Prim (_, I_MEM_MAP, [], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty -> + exists_stack () >>= fun rest -> + unify bef Type.(item kty (item (map kty vty) rest)) >>= fun () -> + unify aft Type.(item bool rest) + | Prim (_, I_GET_MAP, [], _) -> + exists_cmp () >>= fun kty -> + exists () >>= fun vty -> + exists_stack () >>= fun rest -> + unify bef Type.(item kty (item (map kty vty) rest)) >>= fun () -> + unify aft Type.(item (option vty) rest) + (* Pairs *) + | Prim (_, I_PAIR, [], _) -> + exists () >>= fun a -> + exists () >>= fun b -> + exists_stack () >>= fun rest -> + unify bef Type.(item a (item b rest)) >>= fun () -> + unify aft Type.(item (pair a b) rest) + | Prim (_, I_CAR, [], _) -> + exists () >>= fun a -> + exists () >>= fun b -> + exists_stack () >>= fun rest -> + unify bef Type.(item (pair a b) rest) >>= fun () -> + unify aft Type.(item a rest) + | Prim (_, I_CDR, [], _) -> + exists () >>= fun a -> + exists () >>= fun b -> + exists_stack () >>= fun rest -> + unify bef Type.(item (pair a b) rest) >>= fun () -> + unify aft Type.(item b rest) + (* Ors *) + | Prim (_, I_LEFT, [], _) -> + exists () >>= fun lt -> + exists () >>= fun rt -> + exists_stack () >>= fun rest -> + unify bef (Type.item lt rest) >>= fun () -> + unify aft Type.(item (or_ lt rt) rest) >>= fun res -> return res + | Prim (_, I_RIGHT, [], _) -> + exists () >>= fun lt -> + exists () >>= fun rt -> + exists_stack () >>= fun rest -> + unify bef Type.(item rt rest) >>= fun () -> + unify aft Type.(item (or_ lt rt) rest) + | Prim (_, (I_LEFT | I_RIGHT), _ :: _, _) -> + invalid_ast ~msg:__LOC__ path node + | Prim (_, I_LOOP_LEFT, [body], _) -> + exists () >>= fun l -> + exists () >>= fun r -> + exists_stack () >>= fun rest -> + unify bef Type.(item (or_ l r) rest) >>= fun () -> + unify aft Type.(item r rest) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + body + Type.(item l rest) + bef + | Prim (_, I_IF_LEFT, [bt; bf], _) -> + exists () >>= fun a -> + exists () >>= fun b -> + exists_stack () >>= fun rest -> + unify bef Type.(item (or_ a b) rest) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + bt + (Type.item a rest) + aft + >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 1 path) + bf + (Type.item b rest) + aft + (* lambdas *) + | Prim (_, I_LAMBDA, [code], _) -> + exists () >>= fun dom -> + exists () >>= fun range -> + unify aft Type.(item (lambda dom range) bef) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + Type.(item dom empty) + Type.(item range empty) + | Prim (_, I_LAMBDA, _, _) -> invalid_ast ~msg:__LOC__ path node + | Prim (_, I_APPLY, [], _) -> + exists () >>= fun a -> + exists () >>= fun b -> + exists () >>= fun ret -> + exists_stack () >>= fun rest -> + unify bef Type.(item a (item (lambda (pair a b) ret) rest)) >>= fun () -> + unify aft Type.(item (lambda b ret) rest) + | Prim (_, I_EXEC, [], _) -> + exists () >>= fun a -> + exists () >>= fun ret -> + exists_stack () >>= fun rest -> + unify bef Type.(item a (item (lambda a ret) rest)) >>= fun () -> + unify aft Type.(item ret rest) + (* lists *) + | Prim (_, I_NIL, [], _) -> + exists () >>= fun a -> unify aft Type.(item (list a) bef) + | Prim (_, I_CONS, [], _) -> + exists () >>= fun a -> + exists_stack () >>= fun rest -> + unify bef Type.(item a (item (list a) rest)) >>= fun () -> + unify aft Type.(item (list a) rest) + | Prim (_, I_SIZE_LIST, [], _) -> + exists () >>= fun ty -> + exists_stack () >>= fun rest -> + unify bef Type.(item (list ty) rest) >>= fun () -> + unify aft Type.(item nat rest) + | Prim (_, I_ITER_LIST, [code], _) -> + exists () >>= fun ty -> + unify bef Type.(item (list ty) aft) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + Type.(item ty aft) + aft + | Prim (_, I_MAP_LIST, [code], _) -> + exists () >>= fun ty1 -> + exists () >>= fun ty2 -> + exists_stack () >>= fun rest -> + unify bef Type.(item (list ty1) rest) >>= fun () -> + unify aft Type.(item (list ty2) rest) >>= fun () -> + generate_constraints + (Mikhailsky.Path.at_index 0 path) + code + Type.(item ty1 rest) + Type.(item ty2 rest) + (* pack/unpack*) + | Prim (_, I_PACK, [], _) -> + exists () >>= fun ty -> + exists_stack () >>= fun rest -> + unify bef Type.(item ty rest) >>= fun () -> + unify aft Type.(item bytes rest) + | Prim (_, I_UNPACK, [], _) -> + exists () >>= fun ty -> + exists_stack () >>= fun rest -> + unify bef Type.(item bytes rest) >>= fun () -> + unify aft Type.(item (option ty) rest) + (* Others *) + | Seq (_, []) -> unify bef aft + | Seq (_, [single]) -> + generate_constraints (Mikhailsky.Path.at_index 0 path) single bef aft + | Seq (_, instrs) -> generate_constraints_seq path 0 instrs bef aft + | _ -> raise (Ill_typed_script (Unhandled_micheline (path, node))) + +and generate_constraints_seq path index instrs bef aft = + let open M in + match instrs with + | [] -> assert false + | [single] -> + generate_constraints (Mikhailsky.Path.at_index index path) single bef aft + | hd :: tl -> + exists_stack () >>= fun stack_ty -> + generate_constraints (Mikhailsky.Path.at_index index path) hd bef stack_ty + >>= fun () -> generate_constraints_seq path (index + 1) tl stack_ty aft + +and generate_constraints_data (path : Mikhailsky.Path.t) + (node : Mikhailsky.node) (ty : Type.Base.t) : unit M.t = + let open M in + set_data_annot path ty >>= fun () -> + match node with + | Prim (_, D_Hole, [], _) -> return () + | Prim (_, D_Unit, [], _) -> unify_base ty Type.unit + | Prim (_, D_True, [], _) | Prim (_, D_False, [], _) -> + unify_base ty Type.bool + | String _ -> unify_base ty Type.string + | Bytes _ -> unify_base ty Type.bytes + | Prim (_, D_Pair, [vl; vr], _) -> + exists () >>= fun lty -> + exists () >>= fun rty -> + generate_constraints_data (Mikhailsky.Path.at_index 0 path) vl lty + >>= fun () -> + generate_constraints_data (Mikhailsky.Path.at_index 1 path) vr rty + >>= fun () -> unify_base ty (Type.pair lty rty) + | Prim (_, D_Left, [term], _) -> + exists () >>= fun lty -> + exists () >>= fun rty -> + generate_constraints_data (Mikhailsky.Path.at_index 0 path) term lty + >>= fun () -> unify_base ty (Type.or_ lty rty) + | Prim (_, D_Right, [term], _) -> + exists () >>= fun lty -> + exists () >>= fun rty -> + generate_constraints_data (Mikhailsky.Path.at_index 0 path) term rty + >>= fun () -> unify_base ty (Type.or_ lty rty) + | Prim (_, D_None, [], _) -> + exists () >>= fun elt_ty -> unify_base ty (Type.option elt_ty) + | Prim (_, D_Some, [v], _) -> + exists () >>= fun elt_ty -> + generate_constraints_data (Mikhailsky.Path.at_index 0 path) v elt_ty + >>= fun () -> unify_base ty (Type.option elt_ty) + | Prim (_, A_Int, [Int (_, _)], _) -> unify_base ty Type.int + | Prim (_, A_Nat, [Int (_, _)], _) -> unify_base ty Type.nat + | Prim (_, A_Timestamp, [Int (_, _)], _) -> unify_base ty Type.timestamp + | Prim (_, A_Mutez, [Int (_, _)], _) -> unify_base ty Type.mutez + | Prim (_, A_Key_hash, [Bytes (_, _)], _) -> unify_base ty Type.key_hash + | Prim (_, A_Key, [Bytes (_, _)], _) -> unify_base ty Type.key + | Prim (_, A_List, [Seq (_, subterms)], _) -> + exists () >>= fun elt_ty -> + unify_base ty Type.(list elt_ty) >>= fun () -> + (* path' accounts for the fact that the Seq is hidden under an annot. *) + let path' = Mikhailsky.Path.at_index 0 path in + generate_constraints_data_list path' 0 subterms elt_ty + | Prim (_, A_Set, [Seq (_, subterms)], _) -> + exists_cmp () >>= fun elt_ty -> + unify_base ty Type.(set elt_ty) >>= fun () -> + (* path' accounts for the fact that the Seq is hidden under an annot. *) + let path' = Mikhailsky.Path.at_index 0 path in + generate_constraints_data_set path' 0 subterms elt_ty + | Prim (_, A_Map, [Seq (_, subterms)], _) -> + exists_cmp () >>= fun k_ty -> + exists () >>= fun v_ty -> + unify_base ty Type.(map k_ty v_ty) >>= fun () -> + (* path' accounts for the fact that the Seq is hidden under an annot. *) + let path' = Mikhailsky.Path.at_index 0 path in + generate_constraints_data_map path' 0 subterms k_ty v_ty + | Prim (_, A_Lambda, [(Seq (_, _) as node)], _) -> + exists () >>= fun dom -> + exists () >>= fun range -> + unify_base ty Type.(lambda dom range) >>= fun () -> + let path' = Mikhailsky.Path.at_index 0 path in + let bef = Type.(item dom empty) in + let aft = Type.(item range empty) in + generate_constraints path' node bef aft + | Prim (_, (A_Int | A_Nat | A_List), _, _) -> + invalid_ast ~msg:__LOC__ path node + | Int _ + (* Ints should always be guarded by annotations *) + | Seq (_, _) + (* Lists, sets, maps, lambdas, should always be guarded by annotations *) + | _ -> + invalid_ast ~msg:__LOC__ path node + +(* raise (Ill_typed_script (Invalid_ast (path, node))) *) +and generate_constraints_data_list path index data ty = + let open M in + match data with + | [] -> return () + | hd :: tl -> + let hd_path = Mikhailsky.Path.at_index index path in + generate_constraints_data hd_path hd ty >>= fun () -> + generate_constraints_data_list path (index + 1) tl ty + +and generate_constraints_data_set path index data ty = + let open M in + match data with + | [] -> return () + | hd :: tl -> + let hd_path = Mikhailsky.Path.at_index index path in + generate_constraints_data hd_path hd ty >>= fun () -> + generate_constraints_data_list path (index + 1) tl ty + +and generate_constraints_data_map path index data k_ty v_ty = + let open M in + match data with + | [] -> return () + | elt :: tl -> ( + let elt_path = Mikhailsky.Path.at_index index path in + match elt with + | Prim (_, D_Elt, [k; v], _) -> + let k_path = Mikhailsky.Path.at_index 0 elt_path in + generate_constraints_data k_path k k_ty >>= fun () -> + let v_path = Mikhailsky.Path.at_index 1 elt_path in + generate_constraints_data v_path v v_ty >>= fun () -> + generate_constraints_data_map path (index + 1) tl k_ty v_ty + | _ -> invalid_ast ~msg:__LOC__ elt_path elt) + +and generate_constraints_dropn n bef aft = + let open M in + if n = 0 then unify bef aft + else + exists () >>= fun top -> + generate_constraints_dropn (n - 1) bef (Type.item top aft) + +let infer_with_state (node : Mikhailsky.node) : + (Type.Stack.t * Type.Stack.t) * state = + let open M in + ( exists_stack () >>= fun bef -> + exists_stack () >>= fun aft -> + generate_constraints Mikhailsky.Path.root node bef aft >>= fun () -> + instantiate bef >>= fun bef -> + instantiate aft >>= fun aft -> return (bef, aft) ) + (M.empty ()) + +let infer (node : Mikhailsky.node) : Type.Stack.t * Type.Stack.t = + fst (infer_with_state node) + +let infer_data_with_state (node : Mikhailsky.node) : Type.Base.t * state = + let open M in + ( exists () >>= fun ty -> + generate_constraints_data Mikhailsky.Path.root node ty >>= fun () -> + instantiate_base ty >>= fun ty -> return ty ) + (M.empty ()) + +let infer_data (node : Mikhailsky.node) : Type.Base.t = + fst (infer_data_with_state node) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.mli b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.mli new file mode 100644 index 000000000000..e44d83fab069 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/inference.mli @@ -0,0 +1,145 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Errors and their pretty-printing function *) +type inference_error + +exception Ill_typed_script of inference_error + +val pp_inference_error : Format.formatter -> inference_error -> unit + +(** Comparability tag. *) +type comparability = Comparable | Not_comparable | Unconstrained + +(** Michelson types. *) +type michelson_type = + | Base_type of {repr : Type.Base.t option; comparable : comparability} + | Stack_type of Type.Stack.t option + +type transformer = {bef : Type.Stack.t; aft : Type.Stack.t} + +(** State of the type inference module *) + +(** Store implementation for type representatives *) +module Repr_store : Stores.S with type key = int and type value = michelson_type + +(** State monad built on [Repr_store] *) +module Repr_sm : + Monads.State_sig + with type state = Repr_store.state + and type key = int + and type value = michelson_type + +(** Store implementation for instruction type representatives *) +module Annot_instr_store : + Stores.S with type key = Mikhailsky.Path.t and type value = transformer + +(** State monad handling annotations on instructions *) +module Annot_instr_sm : + Monads.State_sig + with type state = Annot_instr_store.state + and type value = transformer + and type key = Mikhailsky.Path.t + +(** Store implementation for data type representatives *) +module Annot_data_store : + Stores.S with type key = Mikhailsky.Path.t and type value = Type.Base.t + +(** State monad handling annotations on data *) +module Annot_data_sm : + Monads.State_sig + with type state = Annot_data_store.state + and type value = Type.Base.t + and type key = Mikhailsky.Path.t + +(** State of the inference module *) +type state = { + uf : Uf.UF.M.state; + repr : Repr_sm.state; + annot_instr : Annot_instr_sm.state; + annot_data : Annot_data_sm.state; +} + +(** State monad of the inference module. *) +module M : sig + type 'a t = state -> 'a * state + + val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t + + val empty : unit -> state + + val return : 'a -> 'a t + + val set_repr : int -> michelson_type -> unit t + + val get_repr_exn : int -> michelson_type t + + val get_instr_annot : Annot_data_sm.key -> transformer option t + + val get_data_annot : Annot_data_sm.key -> Type.Base.t option t + + val uf_lift : 'a Uf.UF.M.t -> 'a t + + val repr_lift : 'a Repr_sm.t -> 'a t + + val annot_instr_lift : 'a Annot_instr_sm.t -> 'a t + + val annot_data_lift : 'a Annot_data_sm.t -> 'a t + + val get_state : state t +end + +(** Unifies two stack types. *) +val unify : Type.Stack.t -> Type.Stack.t -> unit M.t + +(** Unifies two base types. *) +val unify_base : Type.Base.t -> Type.Base.t -> unit M.t + +(** Instantiate type variables with the associated terms in a base type. *) +val instantiate_base : Type.Base.t -> Type.Base.t M.t + +(** Instantiate type variables with the associated terms in a stack type. *) +val instantiate : Type.Stack.t -> Type.Stack.t M.t + +(** Get comparability flag for a base type. *) +val get_comparability : Type.Base.t -> comparability M.t + +(** Performs inference on the given Mikhailsky term and returns + its type (as a pair of [before] and [after] stack) as well as the + inference engine state. *) +val infer_with_state : Mikhailsky.node -> (Type.Stack.t * Type.Stack.t) * state + +(** Performs inference on the given Mikhailsky term and throws + the inference engine state away. *) +val infer : Mikhailsky.node -> Type.Stack.t * Type.Stack.t + +(** Performs inference on a piece of Mikhailsky [data] and + returns the inference engine state along the inferred type. *) +val infer_data_with_state : Mikhailsky.node -> Type.Base.t * state + +(** Performs inference on a piece of Mikhailsky [data] and + returns the inferred type, throwing the inference engine + state away. *) +val infer_data : Mikhailsky.node -> Type.Base.t diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/int_map.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/int_map.ml new file mode 100644 index 000000000000..e9b05fe91caa --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/int_map.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Map.Make (Compare.Int) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.ml new file mode 100644 index 000000000000..4cdfbb80b285 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.ml @@ -0,0 +1,422 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +exception Term_contains_holes + +module Mikhailsky_signature : + Algebraic_signature.S with type t = Mikhailsky_prim.prim = struct + type t = Mikhailsky_prim.prim + + let compare (x : t) (y : t) = Stdlib.compare x y + + let hash (x : t) = Hashtbl.hash x + + let pp = Mikhailsky_prim.pp +end + +include + Micheline_with_hash_consing.Make + (Mikhailsky_signature) + (struct + let initial_size = None + end) + +module Path = Path.With_hash_consing (struct + let initial_size = None +end) + +(* Prints a Mikhailsky term. *) +let pp fmt node = + let canonical = Micheline.strip_locations node in + let printable = + Micheline_printer.printable Mikhailsky_prim.string_of_prim canonical + in + Micheline_printer.print_expr fmt printable + +let to_string node = + pp Format.str_formatter node ; + Format.flush_str_formatter () + +(* Adapted from Script_ir_translator.parse_ty *) +let rec parse_ty : + allow_big_map:bool -> + allow_operation:bool -> + allow_contract:bool -> + node -> + Type.Base.t = + fun ~allow_big_map ~allow_operation ~allow_contract node -> + match node with + | Prim (_loc, T_unit, [], _annot) -> Type.unit + | Prim (_loc, T_int, [], _annot) -> Type.int + | Prim (_loc, T_nat, [], _annot) -> Type.nat + | Prim (_loc, T_string, [], _annot) -> Type.string + | Prim (_loc, T_bytes, [], _annot) -> Type.bytes + | Prim (_loc, T_bool, [], _annot) -> Type.bool + | Prim (_loc, T_key_hash, [], _annot) -> Type.key_hash + | Prim (_loc, T_timestamp, [], _annot) -> Type.timestamp + | Prim (_loc, T_mutez, [], _annot) -> Type.mutez + | Prim (_loc, T_option, [ut], _annot) -> + let ty = parse_ty ~allow_big_map ~allow_operation ~allow_contract ut in + Type.option ty + | Prim (_loc, T_pair, [utl; utr], _annot) -> + let lty = parse_ty ~allow_big_map ~allow_operation ~allow_contract utl in + let rty = parse_ty ~allow_big_map ~allow_operation ~allow_contract utr in + Type.pair lty rty + | Prim (_loc, T_or, [utl; utr], _annot) -> + let lty = parse_ty ~allow_big_map ~allow_operation ~allow_contract utl in + let rty = parse_ty ~allow_big_map ~allow_operation ~allow_contract utr in + Type.or_ lty rty + | Prim (_loc, T_set, [ut], _annot) -> + let ut = parse_ty ~allow_big_map ~allow_operation ~allow_contract ut in + Type.set ut + | Prim (_loc, T_map, [uta; utb], _annot) -> + let uta = parse_ty ~allow_big_map ~allow_operation ~allow_contract uta in + let utb = parse_ty ~allow_big_map ~allow_operation ~allow_contract utb in + Type.map uta utb + | Prim (_loc, T_lambda, [dom; range], _annot) -> + let dom = parse_ty ~allow_big_map ~allow_operation ~allow_contract dom in + let range = + parse_ty ~allow_big_map ~allow_operation ~allow_contract range + in + Type.lambda dom range + | Prim (_loc, T_list, [elt], _annot) -> + let elt = parse_ty ~allow_big_map ~allow_operation ~allow_contract elt in + Type.list elt + | _ -> + let s = to_string node in + Stdlib.failwith ("Mikhailsky.parse_ty: could not parse " ^ s) + +exception Term_has_variables + +exception Ill_formed_mikhailsky + +let rec map_var f (x : Type.Base.t) = + match x.node with + | Unit_t -> prim T_unit [] [] + | Var_t v -> f v + | Int_t -> prim T_int [] [] + | Nat_t -> prim T_nat [] [] + | Bool_t -> prim T_bool [] [] + | String_t -> prim T_string [] [] + | Bytes_t -> prim T_bytes [] [] + | Key_hash_t -> prim T_key_hash [] [] + | Timestamp_t -> prim T_timestamp [] [] + | Mutez_t -> prim T_mutez [] [] + | Key_t -> prim T_key [] [] + | Option_t ty -> + let mty = map_var f ty in + prim T_option [mty] [] + | Pair_t (lty, rty) -> + let lty = map_var f lty in + let rty = map_var f rty in + prim T_pair [lty; rty] [] + | Or_t (lty, rty) -> + let lty = map_var f lty in + let rty = map_var f rty in + prim T_or [lty; rty] [] + | List_t ty -> + let mty = map_var f ty in + prim T_list [mty] [] + | Set_t ty -> + let mty = map_var f ty in + prim T_set [mty] [] + | Map_t (kty, vty) -> + let mkty = map_var f kty in + let mvty = map_var f vty in + prim T_map [mkty; mvty] [] + | Lambda_t (dom, range) -> + let dom = map_var f dom in + let range = map_var f range in + prim T_lambda [dom; range] [] + +let unparse_ty_exn (x : Type.Base.t) = + map_var (fun _ -> raise Term_has_variables) x + +let unparse_ty (x : Type.Base.t) = + try Some (unparse_ty_exn x) with Term_has_variables -> None + +(* Exports a Mikhailsky term to Michelson. Fails if term contains holes. + Erases annotations, introduces types where missing. *) +let rec to_michelson (n : node) = + match n with + | Micheline.Int (_, i) -> Micheline.Int (0, i) + | Micheline.Prim (_, head, [term], _) + when Mikhailsky_prim.kind head = Annot_kind && head <> A_Lambda -> + to_michelson term + | Micheline.Prim (_, I_Hole, _, _) -> raise Term_contains_holes + | Micheline.Prim (_, D_Hole, _, _) -> raise Term_contains_holes + | Micheline.Prim (_, head, subterms, annots) -> + let head = Mikhailsky_prim.to_michelson head in + Micheline.Prim (0, head, List.map to_michelson subterms, annots) + | Micheline.String (_, s) -> Micheline.String (0, s) + | Micheline.Bytes (_, b) -> Micheline.Bytes (0, b) + | Micheline.Seq (_, subterms) -> + Micheline.Seq (0, List.map to_michelson subterms) + +let to_michelson (n : node) : Script_repr.expr = + Micheline.strip_locations (to_michelson n) + +let rec size : node -> int = + fun node -> + match node with + | Micheline.Int (_, _) -> 1 + | Micheline.String (_, _) -> 1 + | Micheline.Bytes (_, _) -> 1 + | Micheline.Prim (_, _, subterms, _) -> + List.fold_left (fun acc n -> acc + size n) 1 subterms + | Micheline.Seq (_, subterms) -> + List.fold_left (fun acc n -> acc + size n) 1 subterms + +let instr_hole = prim I_Hole [] [] + +let data_hole = prim D_Hole [] [] + +(* types *) +let unit_ty = prim T_unit [] [] + +let bool_ty = prim T_bool [] [] + +let int_ty = prim T_int [] [] + +let nat_ty = prim T_nat [] [] + +let string_ty = prim T_string [] [] + +let bytes_ty = prim T_bytes [] [] + +let key_hash_ty = prim T_key_hash [] [] + +let option_ty x = prim T_option [x] [] + +let list_ty x = prim T_list [x] [] + +(* Unique identifier provided by hash-consing Micheline terms. *) +let tag node = + let l = label node in + l.tag + +(* hash of term *) +let hash node = + let l = label node in + l.hash + +module Instructions = struct + (* arithmetic *) + + let add ty1 ty2 = prim I_ADD [ty1; ty2] [] + + let sub ty1 ty2 = prim I_SUB [ty1; ty2] [] + + let mul ty1 ty2 = prim I_MUL [ty1; ty2] [] + + let ediv ty1 ty2 = prim I_EDIV [ty1; ty2] [] + + let abs = prim I_ABS [] [] + + let gt = prim I_GT [] [] + + (* stack ops *) + let push ty v = prim I_PUSH [ty; v] [] + + let dip code = prim I_DIP [seq [code]] [] + + let dup = prim I_DUP [] [] + + let drop = prim I_DROP [] [] + + let dropn n = prim I_DROP [int (Z.of_int n)] [] + + let swap = prim I_SWAP [] [] + + (* crypto *) + let blake2b = prim I_BLAKE2B [] [] + + let sha256 = prim I_SHA256 [] [] + + let sha512 = prim I_SHA512 [] [] + + let hash_key = prim I_HASH_KEY [] [] + + (* control *) + let if_ bt bf = prim I_IF [seq [bt]; seq [bf]] [] + + let if_left bt bf = prim I_IF_LEFT [seq [bt]; seq [bf]] [] + + let if_none bt bf = prim I_IF_NONE [seq [bt]; seq [bf]] [] + + let loop b = prim I_LOOP [seq [b]] [] + + let loop_left b = prim I_LOOP_LEFT [seq [b]] [] + + (* pairs *) + let car = prim I_CAR [] [] + + let cdr = prim I_CDR [] [] + + let pair = prim I_PAIR [] [] + + (* ors *) + + let left = prim I_LEFT [] [] + + let right = prim I_RIGHT [] [] + + (* boolean *) + let and_ = prim I_AND [] [] + + (* compare *) + let compare = prim I_COMPARE [] [] + + (* map/set *) + let empty_set = prim I_EMPTY_SET [] [] + + let update_set = prim I_UPDATE_SET [] [] + + let size_set = prim I_SIZE_SET [] [] + + let iter_set code = prim I_ITER_SET [seq code] [] + + let mem_set = prim I_MEM_SET [] [] + + let empty_map = prim I_EMPTY_MAP [] [] + + let update_map = prim I_UPDATE_MAP [] [] + + let size_map = prim I_SIZE_MAP [] [] + + let iter_map code = prim I_ITER_MAP [seq code] [] + + let map_map code = prim I_MAP_MAP [seq code] [] + + let get_map = prim I_GET_MAP [] [] + + let mem_map = prim I_MEM_MAP [] [] + + (* lists*) + let nil = prim I_NIL [] [] + + let cons = prim I_CONS [] [] + + let size_list = prim I_SIZE_LIST [] [] + + let iter_list code = prim I_ITER_LIST [seq code] [] + + let map_list code = prim I_MAP_LIST [seq code] [] + + (* strings *) + let concat = prim I_CONCAT [] [] + + let size_string = prim I_SIZE_STRING [] [] + + let size_bytes = prim I_SIZE_BYTES [] [] + + (* Lambdas *) + let lambda code = prim I_LAMBDA [seq code] [] + + let exec = prim I_EXEC [] [] + + let apply = prim I_APPLY [] [] + + (* pack/unpack *) + let pack = prim I_PACK [] [] + + let unpack = prim I_UNPACK [] [] + + (* hole *) + let hole = instr_hole +end + +(* value constructors *) +module Data = struct + let unit = prim D_Unit [] [] + + let false_ = prim D_False [] [] + + let true_ = prim D_True [] [] + + let none = prim D_None [] [] + + let some x = prim D_Some [x] [] + + let pair x y = prim D_Pair [x; y] [] + + let left x = prim D_Left [x] [] + + let right x = prim D_Right [x] [] + + let list elts = prim A_List [seq elts] [] + + let set elts = prim A_Set [seq elts] [] + + let map_elt k v = prim D_Elt [k; v] [] + + let map elts = prim A_Map [seq elts] [] + + let timestamp ts = + let z = Protocol.Script_timestamp.to_zint ts in + prim A_Timestamp [int z] [] + + let mutez (tz : Protocol.Alpha_context.Tez.t) = + let i = Protocol.Alpha_context.Tez.to_mutez tz in + prim A_Mutez [int (Z.of_int64 i)] [] + + let key_hash kh = + let b = + Data_encoding.Binary.to_bytes_exn + Environment.Signature.Public_key_hash.encoding + kh + in + prim A_Key_hash [bytes b] [] + + let key k = + let b = + Data_encoding.Binary.to_bytes_exn + Environment.Signature.Public_key.encoding + k + in + prim A_Key [bytes b] [] + + let integer (i : int) = prim A_Int [int (Z.of_int i)] [] + + let natural (i : int) = + assert (i >= 0) ; + prim A_Nat [int (Z.of_int i)] [] + + let big_integer (i : Z.t) = prim A_Int [int i] [] + + let big_natural (i : Z.t) = + assert (Z.geq i Z.zero) ; + prim A_Nat [int i] [] + + let string = string + + let bytes = bytes + + let lambda code = prim A_Lambda [seq code] [] + + let hole = data_hole +end diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.mli b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.mli new file mode 100644 index 000000000000..724bfa299074 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky.mli @@ -0,0 +1,331 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Mikhailsky: Michelson in Micheline form, with typed holes and annotations. + Mikhailsky terms are hash-consed. *) + +(** + Michelson code is a hard to type-check and generate incrementally due to + the presence of ambiguous constructs, such as literals + like [{ 1 ; 2 ; 3 }]. Is it a list of ints? of nats? of tez? Or a set? + + Thus, we will work with Mikhailsky, a better behaved version of Michelson + allowing local reconstruction of types. + + Differences wrt Michelson: + + 1. non string/byte literals are explicitly annotated with their head type constructor. + Here is an int i: Prim (_, D_int, [Int i], _) + Here is an nat n: Prim (_, D_nat, [Int i], _) + Here is an list of something: Prim (_, D_list, michelson_list, _) + Here is a set: Prim (_, D_set, michelson_set, _) + Here is a map: Prim (_, D_map, michelson_map, _) + etc. + Projecting back from this language to Michelson is trivial. + + 2. Instructions `LEFT/RIGHT` do not need to carry the type of the other + component of the disjunction. These has to be filled in back when + generating Michelson from Mikhailsky. + + 4. The same holds for the input/output type of a lambda as specified in the + `LAMBDA` instruction. + + 3. Some instructions are annotated with the type on which they operate. + Eg if Prim (_, I_ADD, [], []) is the (ad-hoc polymorphic) addition in Michelson, + we will have the following variants in Mikhailsky: + - Prim (_, I_ADD, [ Prim (_, T_mutez, [], []), + Prim (_, T_mutez, [], []) ], []) for mutez addition + - Prim (_, I_ADD, [ Prim (_, T_int, [], []), + Prim (_, T_nat, [], []) ], []) for int+nat addition + etc. +*) + +(** The signature of Mikhailsky terms. *) +module Mikhailsky_signature : + Algebraic_signature.S with type t = Mikhailsky_prim.prim + +(** Elements of type [Path.t] allow to index subterms of Mikhailsky terms. *) +module Path : Path.S + +(** The following types correspond to those provided when instantiating the + functor [Micheline_with_hash_consing.Make] on [Mikhailsky_signature]. *) +type label = Micheline_with_hash_consing.hcons_info + +type head = Mikhailsky_signature.t + +type node = (label, head) Micheline.node + +exception Term_contains_holes + +exception Ill_formed_mikhailsky + +(** [parse_ty] returns a type from a Mikhailsky term. *) +val parse_ty : + allow_big_map:bool -> + allow_operation:bool -> + allow_contract:bool -> + node -> + Type.Base.t + +(** [map_var f x] maps the function f on all variables contained + in the type [x]. *) +val map_var : (int -> node) -> Type.Base.t -> node + +(** [unparse_ty] returns a Mikhailsky term representing a type. *) +val unparse_ty_exn : Type.Base.t -> node + +val unparse_ty : Type.Base.t -> node option + +(** Extracts a Michelson term from a Mikhailsky one. Raises + [Term_contains_holes] if it cannot be done. *) +val to_michelson : node -> Script_repr.expr + +(** Pretty printer. *) +val pp : Format.formatter -> node -> unit + +val to_string : node -> string + +(** Returns the number of nodes of a Mikhailsky term. *) +val size : node -> int + +(** Micheline generic constructors *) +val prim : Mikhailsky_prim.prim -> node list -> string list -> node + +val seq : node list -> node + +val string : string -> node + +val bytes : Bytes.t -> node + +(** Mikhailsky smart constructors*) + +(** Holes *) +val instr_hole : node + +val data_hole : node + +(** Types *) +val unit_ty : node + +val int_ty : node + +val nat_ty : node + +val bool_ty : node + +val string_ty : node + +val bytes_ty : node + +val key_hash_ty : node + +val option_ty : node -> node + +val list_ty : node -> node + +(** Project unique tag out of Mikhailsky node *) +val tag : node -> int + +(** Project hash out of Mikhailsky node *) +val hash : node -> int + +(** Instructions *) +module Instructions : sig + (** Arithmetic. Binary operations take the input types as extra arguments. *) + val add : node -> node -> node + + val sub : node -> node -> node + + val mul : node -> node -> node + + val ediv : node -> node -> node + + val abs : node + + val gt : node + + (** Stack *) + val push : node -> node -> node + + val dip : node -> node + + val dup : node + + val drop : node + + val dropn : int -> node + + val swap : node + + (** Crypto *) + val blake2b : node + + val sha256 : node + + val sha512 : node + + val hash_key : node + + (** Control *) + val if_ : node -> node -> node + + val if_left : node -> node -> node + + val if_none : node -> node -> node + + val loop : node -> node + + val loop_left : node -> node + + (** Pairs *) + val car : node + + val cdr : node + + val pair : node + + (** Unions *) + val left : node + + val right : node + + (** Booleans *) + val and_ : node + + (** Compare *) + val compare : node + + (** Set/Map *) + val empty_set : node + + val update_set : node + + val size_set : node + + val iter_set : node list -> node + + val mem_set : node + + val empty_map : node + + val update_map : node + + val size_map : node + + val iter_map : node list -> node + + val map_map : node list -> node + + val get_map : node + + val mem_map : node + + (** Lists *) + val nil : node + + val cons : node + + val size_list : node + + val iter_list : node list -> node + + val map_list : node list -> node + + (** Strings/bytes *) + val concat : node + + val size_string : node + + val size_bytes : node + + (** Lambdas *) + val lambda : node list -> node + + val exec : node + + val apply : node + + (** pack/unpack *) + + val pack : node + + val unpack : node + + (** Hole *) + val hole : node +end + +(** data *) +module Data : sig + val unit : node + + val false_ : node + + val true_ : node + + val none : node + + val some : node -> node + + val pair : node -> node -> node + + val left : node -> node + + val right : node -> node + + val list : node list -> node + + val set : node list -> node + + val map_elt : node -> node -> node + + val map : node list -> node + + val timestamp : Script_timestamp.t -> node + + val mutez : Alpha_context.Tez.t -> node + + val key_hash : Environment.Signature.Public_key_hash.t -> node + + val key : Environment.Signature.Public_key.t -> node + + val integer : int -> node + + val natural : int -> node + + val big_integer : Z.t -> node + + val big_natural : Z.t -> node + + val string : string -> node + + val bytes : Bytes.t -> node + + val lambda : node list -> node + + val hole : node +end diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky_prim.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky_prim.ml new file mode 100644 index 000000000000..cd6689498404 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/mikhailsky_prim.ml @@ -0,0 +1,575 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Mikhailsky primitives correspond to Michelson primitives plus special + "holes" for instructions and data. *) + +type prim = + | K_parameter + | K_storage + | K_code + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | D_Ticket + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET_MAP + | I_GET_AND_UPDATE_MAP + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LE + | I_LEFT + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP_MAP + | I_MAP_LIST + | I_MEM_SET + | I_MEM_MAP + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE_SET + | I_SIZE_MAP + | I_SIZE_LIST + | I_SIZE_STRING + | I_SIZE_BYTES + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE_SET + | I_UPDATE_MAP + | I_XOR + | I_ITER_MAP + | I_ITER_LIST + | I_ITER_SET + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_DIG + | I_DUG + | I_LEVEL + | I_SELF_ADDRESS + | I_NEVER + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_chain_id + | T_never + | T_sapling_state + | T_sapling_transaction_deprecated + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + (* Holes in programs and data. *) + | I_Hole + | D_Hole + (* Annotations. *) + | A_Int + | A_Nat + | A_Timestamp + | A_Mutez + | A_Key_hash + | A_Key + | A_List + | A_Set + | A_Map + | A_Lambda + +let relation = + [ + (K_parameter, Michelson_v1_primitives.K_parameter); + (K_storage, Michelson_v1_primitives.K_storage); + (K_code, Michelson_v1_primitives.K_code); + (D_False, Michelson_v1_primitives.D_False); + (D_Elt, Michelson_v1_primitives.D_Elt); + (D_Left, Michelson_v1_primitives.D_Left); + (D_None, Michelson_v1_primitives.D_None); + (D_Pair, Michelson_v1_primitives.D_Pair); + (D_Right, Michelson_v1_primitives.D_Right); + (D_Some, Michelson_v1_primitives.D_Some); + (D_True, Michelson_v1_primitives.D_True); + (D_Unit, Michelson_v1_primitives.D_Unit); + (I_PACK, Michelson_v1_primitives.I_PACK); + (I_UNPACK, Michelson_v1_primitives.I_UNPACK); + (I_BLAKE2B, Michelson_v1_primitives.I_BLAKE2B); + (I_SHA256, Michelson_v1_primitives.I_SHA256); + (I_SHA512, Michelson_v1_primitives.I_SHA512); + (I_ABS, Michelson_v1_primitives.I_ABS); + (I_ADD, Michelson_v1_primitives.I_ADD); + (I_AMOUNT, Michelson_v1_primitives.I_AMOUNT); + (I_AND, Michelson_v1_primitives.I_AND); + (I_BALANCE, Michelson_v1_primitives.I_BALANCE); + (I_CAR, Michelson_v1_primitives.I_CAR); + (I_CDR, Michelson_v1_primitives.I_CDR); + (I_CHAIN_ID, Michelson_v1_primitives.I_CHAIN_ID); + (I_CHECK_SIGNATURE, Michelson_v1_primitives.I_CHECK_SIGNATURE); + (I_COMPARE, Michelson_v1_primitives.I_COMPARE); + (I_CONCAT, Michelson_v1_primitives.I_CONCAT); + (I_CONS, Michelson_v1_primitives.I_CONS); + (I_CREATE_ACCOUNT, Michelson_v1_primitives.I_CREATE_ACCOUNT); + (I_CREATE_CONTRACT, Michelson_v1_primitives.I_CREATE_CONTRACT); + (I_IMPLICIT_ACCOUNT, Michelson_v1_primitives.I_IMPLICIT_ACCOUNT); + (I_DIP, Michelson_v1_primitives.I_DIP); + (I_DROP, Michelson_v1_primitives.I_DROP); + (I_DUP, Michelson_v1_primitives.I_DUP); + (I_EDIV, Michelson_v1_primitives.I_EDIV); + (I_EMPTY_BIG_MAP, Michelson_v1_primitives.I_EMPTY_BIG_MAP); + (I_EMPTY_MAP, Michelson_v1_primitives.I_EMPTY_MAP); + (I_EMPTY_SET, Michelson_v1_primitives.I_EMPTY_SET); + (I_EQ, Michelson_v1_primitives.I_EQ); + (I_EXEC, Michelson_v1_primitives.I_EXEC); + (I_APPLY, Michelson_v1_primitives.I_APPLY); + (I_FAILWITH, Michelson_v1_primitives.I_FAILWITH); + (I_GE, Michelson_v1_primitives.I_GE); + (I_GET_MAP, Michelson_v1_primitives.I_GET); + (I_GET_AND_UPDATE_MAP, Michelson_v1_primitives.I_GET_AND_UPDATE); + (I_GT, Michelson_v1_primitives.I_GT); + (I_HASH_KEY, Michelson_v1_primitives.I_HASH_KEY); + (I_IF, Michelson_v1_primitives.I_IF); + (I_IF_CONS, Michelson_v1_primitives.I_IF_CONS); + (I_IF_LEFT, Michelson_v1_primitives.I_IF_LEFT); + (I_IF_NONE, Michelson_v1_primitives.I_IF_NONE); + (I_INT, Michelson_v1_primitives.I_INT); + (I_LAMBDA, Michelson_v1_primitives.I_LAMBDA); + (I_LE, Michelson_v1_primitives.I_LE); + (I_LEFT, Michelson_v1_primitives.I_LEFT); + (I_LEVEL, Michelson_v1_primitives.I_LEVEL); + (I_LOOP, Michelson_v1_primitives.I_LOOP); + (I_LSL, Michelson_v1_primitives.I_LSL); + (I_LSR, Michelson_v1_primitives.I_LSR); + (I_LT, Michelson_v1_primitives.I_LT); + (I_MAP_MAP, Michelson_v1_primitives.I_MAP); + (I_MAP_LIST, Michelson_v1_primitives.I_MAP); + (I_MEM_SET, Michelson_v1_primitives.I_MEM); + (I_MEM_MAP, Michelson_v1_primitives.I_MEM); + (I_MUL, Michelson_v1_primitives.I_MUL); + (I_NEG, Michelson_v1_primitives.I_NEG); + (I_NEQ, Michelson_v1_primitives.I_NEQ); + (I_NIL, Michelson_v1_primitives.I_NIL); + (I_NONE, Michelson_v1_primitives.I_NONE); + (I_NOT, Michelson_v1_primitives.I_NOT); + (I_NOW, Michelson_v1_primitives.I_NOW); + (I_OR, Michelson_v1_primitives.I_OR); + (I_PAIR, Michelson_v1_primitives.I_PAIR); + (I_UNPAIR, Michelson_v1_primitives.I_UNPAIR); + (I_PUSH, Michelson_v1_primitives.I_PUSH); + (I_RIGHT, Michelson_v1_primitives.I_RIGHT); + (I_SIZE_SET, Michelson_v1_primitives.I_SIZE); + (I_SIZE_MAP, Michelson_v1_primitives.I_SIZE); + (I_SIZE_LIST, Michelson_v1_primitives.I_SIZE); + (I_SIZE_STRING, Michelson_v1_primitives.I_SIZE); + (I_SIZE_BYTES, Michelson_v1_primitives.I_SIZE); + (I_SOME, Michelson_v1_primitives.I_SOME); + (I_SOURCE, Michelson_v1_primitives.I_SOURCE); + (I_SENDER, Michelson_v1_primitives.I_SENDER); + (I_SELF, Michelson_v1_primitives.I_SELF); + (I_SELF_ADDRESS, Michelson_v1_primitives.I_SELF_ADDRESS); + (I_SLICE, Michelson_v1_primitives.I_SLICE); + (I_STEPS_TO_QUOTA, Michelson_v1_primitives.I_STEPS_TO_QUOTA); + (I_SUB, Michelson_v1_primitives.I_SUB); + (I_SWAP, Michelson_v1_primitives.I_SWAP); + (I_TRANSFER_TOKENS, Michelson_v1_primitives.I_TRANSFER_TOKENS); + (I_SET_DELEGATE, Michelson_v1_primitives.I_SET_DELEGATE); + (I_UNIT, Michelson_v1_primitives.I_UNIT); + (I_UPDATE_SET, Michelson_v1_primitives.I_UPDATE); + (I_UPDATE_MAP, Michelson_v1_primitives.I_UPDATE); + (I_XOR, Michelson_v1_primitives.I_XOR); + (I_ITER_MAP, Michelson_v1_primitives.I_ITER); + (I_ITER_LIST, Michelson_v1_primitives.I_ITER); + (I_ITER_SET, Michelson_v1_primitives.I_ITER); + (I_LOOP_LEFT, Michelson_v1_primitives.I_LOOP_LEFT); + (I_ADDRESS, Michelson_v1_primitives.I_ADDRESS); + (I_CONTRACT, Michelson_v1_primitives.I_CONTRACT); + (I_ISNAT, Michelson_v1_primitives.I_ISNAT); + (I_CAST, Michelson_v1_primitives.I_CAST); + (I_RENAME, Michelson_v1_primitives.I_RENAME); + (I_SAPLING_EMPTY_STATE, Michelson_v1_primitives.I_SAPLING_EMPTY_STATE); + (I_SAPLING_VERIFY_UPDATE, Michelson_v1_primitives.I_SAPLING_VERIFY_UPDATE); + (I_DIG, Michelson_v1_primitives.I_DIG); + (I_DUG, Michelson_v1_primitives.I_DUG); + (I_NEVER, Michelson_v1_primitives.I_NEVER); + (I_VOTING_POWER, Michelson_v1_primitives.I_VOTING_POWER); + (I_TOTAL_VOTING_POWER, Michelson_v1_primitives.I_TOTAL_VOTING_POWER); + (I_KECCAK, Michelson_v1_primitives.I_KECCAK); + (I_SHA3, Michelson_v1_primitives.I_SHA3); + (I_PAIRING_CHECK, Michelson_v1_primitives.I_PAIRING_CHECK); + (I_TICKET, Michelson_v1_primitives.I_TICKET); + (I_READ_TICKET, Michelson_v1_primitives.I_READ_TICKET); + (I_SPLIT_TICKET, Michelson_v1_primitives.I_SPLIT_TICKET); + (I_JOIN_TICKETS, Michelson_v1_primitives.I_JOIN_TICKETS); + (T_bool, Michelson_v1_primitives.T_bool); + (T_contract, Michelson_v1_primitives.T_contract); + (T_int, Michelson_v1_primitives.T_int); + (T_key, Michelson_v1_primitives.T_key); + (T_key_hash, Michelson_v1_primitives.T_key_hash); + (T_lambda, Michelson_v1_primitives.T_lambda); + (T_list, Michelson_v1_primitives.T_list); + (T_map, Michelson_v1_primitives.T_map); + (T_big_map, Michelson_v1_primitives.T_big_map); + (T_nat, Michelson_v1_primitives.T_nat); + (T_option, Michelson_v1_primitives.T_option); + (T_or, Michelson_v1_primitives.T_or); + (T_pair, Michelson_v1_primitives.T_pair); + (T_set, Michelson_v1_primitives.T_set); + (T_signature, Michelson_v1_primitives.T_signature); + (T_string, Michelson_v1_primitives.T_string); + (T_bytes, Michelson_v1_primitives.T_bytes); + (T_mutez, Michelson_v1_primitives.T_mutez); + (T_timestamp, Michelson_v1_primitives.T_timestamp); + (T_unit, Michelson_v1_primitives.T_unit); + (T_operation, Michelson_v1_primitives.T_operation); + (T_address, Michelson_v1_primitives.T_address); + ( T_sapling_transaction_deprecated, + Michelson_v1_primitives.T_sapling_transaction_deprecated ); + (T_sapling_state, Michelson_v1_primitives.T_sapling_state); + (T_chain_id, Michelson_v1_primitives.T_chain_id); + (T_never, Michelson_v1_primitives.T_never); + (T_bls12_381_g1, Michelson_v1_primitives.T_bls12_381_g1); + (T_bls12_381_g2, Michelson_v1_primitives.T_bls12_381_g2); + (T_bls12_381_fr, Michelson_v1_primitives.T_bls12_381_fr); + (T_ticket, Michelson_v1_primitives.T_ticket); + ] + +let relation_table = + let table = Hashtbl.create 269 in + List.iter + (fun (mikhailsky, michelson) -> Hashtbl.add table mikhailsky michelson) + relation ; + table + +exception Primitive_cannot_be_cast_back_to_Michelson of prim + +let to_michelson prim = + match Hashtbl.find relation_table prim with + | exception Not_found -> + raise (Primitive_cannot_be_cast_back_to_Michelson prim) + | res -> res + +let string_of_prim prim = + match prim with + | K_parameter -> "K_parameter" + | K_storage -> "K_storage" + | K_code -> "K_code" + | D_False -> "D_False" + | D_Elt -> "D_Elt" + | D_Left -> "D_Left" + | D_None -> "D_None" + | D_Pair -> "D_Pair" + | D_Right -> "D_Right" + | D_Some -> "D_Some" + | D_True -> "D_True" + | D_Unit -> "D_Unit" + | D_Ticket -> "D_Ticket" + | I_PACK -> "I_PACK" + | I_UNPACK -> "I_UNPACK" + | I_BLAKE2B -> "I_BLAKE2B" + | I_SHA256 -> "I_SHA256" + | I_SHA512 -> "I_SHA512" + | I_ABS -> "I_ABS" + | I_ADD -> "I_ADD" + | I_AMOUNT -> "I_AMOUNT" + | I_AND -> "I_AND" + | I_BALANCE -> "I_BALANCE" + | I_CAR -> "I_CAR" + | I_CDR -> "I_CDR" + | I_CHAIN_ID -> "I_CHAIN_ID" + | I_CHECK_SIGNATURE -> "I_CHECK_SIGNATURE" + | I_COMPARE -> "I_COMPARE" + | I_CONCAT -> "I_CONCAT" + | I_CONS -> "I_CONS" + | I_CREATE_ACCOUNT -> "I_CREATE_ACCOUNT" + | I_CREATE_CONTRACT -> "I_CREATE_CONTRACT" + | I_IMPLICIT_ACCOUNT -> "I_IMPLICIT_ACCOUNT" + | I_DIP -> "I_DIP" + | I_DROP -> "I_DROP" + | I_DUP -> "I_DUP" + | I_EDIV -> "I_EDIV" + | I_EMPTY_BIG_MAP -> "I_EMPTY_BIG_MAP" + | I_EMPTY_MAP -> "I_EMPTY_MAP" + | I_EMPTY_SET -> "I_EMPTY_SET" + | I_EQ -> "I_EQ" + | I_EXEC -> "I_EXEC" + | I_APPLY -> "I_APPLY" + | I_FAILWITH -> "I_FAILWITH" + | I_GE -> "I_GE" + | I_GET_MAP -> "I_GET_MAP" + | I_GET_AND_UPDATE_MAP -> "I_GET_AND_UPDATE_MAP" + | I_GT -> "I_GT" + | I_HASH_KEY -> "I_HASH_KEY" + | I_IF -> "I_IF" + | I_IF_CONS -> "I_IF_CONS" + | I_IF_LEFT -> "I_IF_LEFT" + | I_IF_NONE -> "I_IF_NONE" + | I_INT -> "I_INT" + | I_LAMBDA -> "I_LAMBDA" + | I_LE -> "I_LE" + | I_LEFT -> "I_LEFT" + | I_LOOP -> "I_LOOP" + | I_LSL -> "I_LSL" + | I_LSR -> "I_LSR" + | I_LT -> "I_LT" + | I_MAP_MAP -> "I_MAP_MAP" + | I_MAP_LIST -> "I_MAP_LIST" + | I_MEM_SET -> "I_MEM_SET" + | I_MEM_MAP -> "I_MEM_MAP" + | I_MUL -> "I_MUL" + | I_NEG -> "I_NEG" + | I_NEQ -> "I_NEQ" + | I_NIL -> "I_NIL" + | I_NONE -> "I_NONE" + | I_NOT -> "I_NOT" + | I_NOW -> "I_NOW" + | I_OR -> "I_OR" + | I_PAIR -> "I_PAIR" + | I_UNPAIR -> "I_UNPAIR" + | I_PUSH -> "I_PUSH" + | I_RIGHT -> "I_RIGHT" + | I_SIZE_SET -> "I_SIZE_SET" + | I_SIZE_MAP -> "I_SIZE_MAP" + | I_SIZE_LIST -> "I_SIZE_LIST" + | I_SIZE_STRING -> "I_SIZE_STRING" + | I_SIZE_BYTES -> "I_SIZE_BYTES" + | I_SOME -> "I_SOME" + | I_SOURCE -> "I_SOURCE" + | I_SENDER -> "I_SENDER" + | I_SELF -> "I_SELF" + | I_SLICE -> "I_SLICE" + | I_STEPS_TO_QUOTA -> "I_STEPS_TO_QUOTA" + | I_SUB -> "I_SUB" + | I_SWAP -> "I_SWAP" + | I_TRANSFER_TOKENS -> "I_TRANSFER_TOKENS" + | I_SET_DELEGATE -> "I_SET_DELEGATE" + | I_UNIT -> "I_UNIT" + | I_UPDATE_SET -> "I_UPDATE_SET" + | I_UPDATE_MAP -> "I_UPDATE_MAP" + | I_XOR -> "I_XOR" + | I_ITER_MAP -> "I_ITER_MAP" + | I_ITER_LIST -> "I_ITER_LIST" + | I_ITER_SET -> "I_ITER_SET" + | I_LOOP_LEFT -> "I_LOOP_LEFT" + | I_ADDRESS -> "I_ADDRESS" + | I_CONTRACT -> "I_CONTRACT" + | I_ISNAT -> "I_ISNAT" + | I_CAST -> "I_CAST" + | I_RENAME -> "I_RENAME" + | I_DIG -> "I_DIG" + | I_DUG -> "I_DUG" + | I_LEVEL -> "I_LEVEL" + | I_SELF_ADDRESS -> "I_SELF_ADDRESS" + | I_NEVER -> "I_NEVER" + | I_SAPLING_EMPTY_STATE -> "I_SAPLING_EMPTY_STATE" + | I_SAPLING_VERIFY_UPDATE -> "I_SAPLING_VERIFY_UPDATE" + | I_VOTING_POWER -> "I_VOTING_POWER" + | I_TOTAL_VOTING_POWER -> "I_TOTAL_VOTING_POWER" + | I_KECCAK -> "I_KECCAK" + | I_SHA3 -> "I_SHA3" + | I_PAIRING_CHECK -> "I_PAIRING_CHECK" + | I_TICKET -> "I_TICKET" + | I_READ_TICKET -> "I_READ_TICKET" + | I_SPLIT_TICKET -> "I_SPLIT_TICKET" + | I_JOIN_TICKETS -> "I_JOIN_TICKETS" + | T_bool -> "T_bool" + | T_contract -> "T_contract" + | T_int -> "T_int" + | T_key -> "T_key" + | T_key_hash -> "T_key_hash" + | T_lambda -> "T_lambda" + | T_list -> "T_list" + | T_map -> "T_map" + | T_big_map -> "T_big_map" + | T_nat -> "T_nat" + | T_option -> "T_option" + | T_or -> "T_or" + | T_pair -> "T_pair" + | T_set -> "T_set" + | T_signature -> "T_signature" + | T_string -> "T_string" + | T_bytes -> "T_bytes" + | T_mutez -> "T_mutez" + | T_timestamp -> "T_timestamp" + | T_unit -> "T_unit" + | T_operation -> "T_operation" + | T_address -> "T_address" + | T_chain_id -> "T_chain_id" + | T_never -> "T_never" + | T_sapling_state -> "T_sapling_state" + | T_sapling_transaction_deprecated -> "T_sapling_transaction_deprecated" + | T_bls12_381_g1 -> "T_bls12_381_g1" + | T_bls12_381_g2 -> "T_bls12_381_g2" + | T_bls12_381_fr -> "T_bls12_381_fr" + | T_ticket -> "T_ticket" + | I_Hole -> "I_Hole" + | D_Hole -> "D_Hole" + | A_Int -> "A_Int" + | A_Nat -> "A_Nat" + | A_Timestamp -> "A_Timestamp" + | A_Mutez -> "A_Mutez" + | A_Key_hash -> "A_Key_hash" + | A_Key -> "A_Key" + | A_List -> "A_List" + | A_Set -> "A_Set" + | A_Map -> "A_Map" + | A_Lambda -> "A_Lambda" + +let pp fmtr prim = Format.fprintf fmtr "%s" (string_of_prim prim) + +type kind = Data_kind | Instr_kind | Type_kind | Keyword_kind | Annot_kind + +let kind (x : prim) = + match x with + | K_parameter | K_storage | K_code -> Keyword_kind + | D_Hole | D_False | D_Elt | D_Left | D_None | D_Pair | D_Right | D_Some + | D_True | D_Unit | D_Ticket -> + Data_kind + | I_PACK | I_UNPACK | I_BLAKE2B | I_SHA256 | I_SHA512 | I_ABS | I_ADD + | I_AMOUNT | I_AND | I_BALANCE | I_CAR | I_CDR | I_CHAIN_ID + | I_CHECK_SIGNATURE | I_COMPARE | I_CONCAT | I_CONS | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT | I_IMPLICIT_ACCOUNT | I_DIP | I_DROP | I_DUP | I_EDIV + | I_EMPTY_BIG_MAP | I_EMPTY_MAP | I_EMPTY_SET | I_EQ | I_EXEC | I_APPLY + | I_FAILWITH | I_GE | I_GET_MAP | I_GET_AND_UPDATE_MAP | I_GT | I_HASH_KEY + | I_IF | I_IF_CONS | I_IF_LEFT | I_IF_NONE | I_INT | I_LAMBDA | I_LE | I_LEFT + | I_LOOP | I_LSL | I_LSR | I_LT | I_MAP_MAP | I_MAP_LIST | I_MEM_SET + | I_MEM_MAP | I_MUL | I_NEG | I_NEQ | I_NIL | I_NONE | I_NOT | I_NOW | I_OR + | I_PAIR | I_UNPAIR | I_PUSH | I_RIGHT | I_SIZE_SET | I_SIZE_MAP | I_SIZE_LIST + | I_SIZE_STRING | I_SIZE_BYTES | I_SOME | I_SOURCE | I_SENDER | I_SELF + | I_SLICE | I_STEPS_TO_QUOTA | I_SUB | I_SWAP | I_TRANSFER_TOKENS + | I_SET_DELEGATE | I_UNIT | I_UPDATE_SET | I_UPDATE_MAP | I_XOR | I_ITER_MAP + | I_ITER_LIST | I_ITER_SET | I_LOOP_LEFT | I_ADDRESS | I_CONTRACT | I_ISNAT + | I_CAST | I_RENAME | I_DIG | I_DUG | I_LEVEL | I_SELF_ADDRESS | I_NEVER + | I_SAPLING_EMPTY_STATE | I_SAPLING_VERIFY_UPDATE | I_VOTING_POWER + | I_TOTAL_VOTING_POWER | I_KECCAK | I_SHA3 | I_PAIRING_CHECK | I_TICKET + | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS | I_Hole -> + Instr_kind + | T_bool | T_contract | T_int | T_key | T_key_hash | T_lambda | T_list | T_map + | T_big_map | T_nat | T_option | T_or | T_pair | T_set | T_signature + | T_string | T_bytes | T_mutez | T_timestamp | T_unit | T_operation + | T_address | T_chain_id | T_never | T_sapling_state + | T_sapling_transaction_deprecated | T_bls12_381_g1 | T_bls12_381_g2 + | T_bls12_381_fr | T_ticket -> + Type_kind + (* Holes in programs and data. *) + (* Annotations. *) + | A_Int | A_Nat | A_Timestamp | A_Mutez | A_Key_hash | A_Key | A_List | A_Set + | A_Map | A_Lambda -> + Annot_kind diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/monads.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/monads.ml new file mode 100644 index 000000000000..47273406af50 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/monads.ml @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Widely used module types. *) + +module type S = sig + type 'a t + + val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t + + val return : 'a -> 'a t + + val run : 'a t -> 'a +end + +(* Signature of a state monad. *) +module type State_sig = sig + type state + + type key + + type value + + include S with type 'a t = state -> 'a * state + + val empty : unit -> state + + val set : key -> value -> unit t + + val get : key -> value option t + + val iter_list : ('a -> unit t) -> 'a list -> unit t +end + +module Make_state_monad (X : Stores.S) : + State_sig + with type state = X.state + and type key = X.key + and type value = X.value + and type 'a t = X.state -> 'a * X.state = struct + include X + + type 'a t = state -> 'a * state + + let ( >>= ) m f s = + let x, s = m s in + f x s + + let return x s = (x, s) + + let run m = fst (m (empty ())) + + let set k v s = ((), set k v s) + + let get k s = (get k s, s) + + let rec iter_list (f : 'a -> unit t) (l : 'a list) = + match l with + | [] -> return () + | elt :: tl -> f elt >>= fun () -> iter_list f tl +end diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/stores.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/stores.ml new file mode 100644 index 000000000000..dff87824d1b4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/stores.ml @@ -0,0 +1,85 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Various implementations of Monads.Store_sig *) + +(* Signature of a persistent store. *) +module type S = sig + type state + + type key + + type value + + val empty : unit -> state + + val set : key -> value -> state -> state + + val get : key -> state -> value option + + val map : (value -> value) -> state -> state + + val to_string : state -> string +end + +module type Map_store_param_sig = sig + type key + + type value + + val key_to_string : key -> string + + val value_to_string : value -> string +end + +(* An implemention of [S] using maps. *) +module Map (M : Map.S) (V : Map_store_param_sig with type key = M.key) : + S with type state = V.value M.t and type key = M.key and type value = V.value = +struct + type state = V.value M.t + + type key = M.key + + type value = V.value + + let empty () = M.empty + + let set = M.add + + let get = M.find_opt + + let map = M.map + + let to_string s = + M.fold + (fun key node acc -> + Printf.sprintf + "%s\n%s |-> %s" + acc + (V.key_to_string key) + (V.value_to_string node)) + s + "" +end diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune new file mode 100644 index 000000000000..b8e36d5fc439 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune @@ -0,0 +1,29 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executables + (names test_uf test_inference) + (libraries + octez-libs.micheline + tezos-micheline-rewriting + tezos-benchmark-type-inference-019-PtParisB + tezos-protocol-019-PtParisB.protocol + octez-libs.error-monad + octez-protocol-019-PtParisB-libs.client) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (flags + (:standard) + -open Tezos_micheline + -open Tezos_benchmark_type_inference_019_PtParisB)) + +(rule + (alias runtest) + (package tezos-benchmark-type-inference-019-PtParisB) + (action (run %{dep:./test_uf.exe}))) + +(rule + (alias runtest) + (package tezos-benchmark-type-inference-019-PtParisB) + (action (run %{dep:./test_inference.exe}))) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_inference.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_inference.ml new file mode 100644 index 000000000000..4b702dd05667 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_inference.ml @@ -0,0 +1,615 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* open Tezos_rewriting *) +open Mikhailsky + +let unopt x = match x with Some x -> x | None -> assert false + +let time f = + let now = Unix.gettimeofday () in + let res = f () in + let later = Unix.gettimeofday () in + (later -. now, res) + +let add_ii = Instructions.(add Mikhailsky.int_ty Mikhailsky.int_ty) + +let add_in = Instructions.(add Mikhailsky.int_ty Mikhailsky.nat_ty) + +let mul_ii = Instructions.(mul Mikhailsky.int_ty Mikhailsky.int_ty) + +let push_int = Instructions.push int_ty (Data.big_integer (Z.of_int 100)) + +let push_nat = Instructions.push nat_ty (Data.big_natural (Z.of_int 100)) + +module Test1 = struct + open Data + open Instructions + + let program = seq [add_ii; push bool_ty false_; dip instr_hole; dip swap] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test2 = struct + open Instructions + + let program = seq [loop swap; and_] + + let () = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING FAILURE\n" ; + Format.printf "Program: %a\n" Mikhailsky.pp program ; + let exception Test_failed in + try + ignore + ( time @@ fun () -> + ignore @@ Inference.infer program ; + raise Test_failed ) + with + | Inference.Ill_typed_script error -> + Format.printf "Error:\n" ; + Format.printf "%a\n" Inference.pp_inference_error error + | Test_failed -> Format.printf "No type error: Test failed!" + + let _ = print_newline () +end + +module Test3 = struct + open Instructions + + let program = + seq + [ + dip (seq [swap; dup]); + swap; + dip cdr; + loop (seq [dip instr_hole; cdr; loop instr_hole]); + car; + car; + push int_ty (Data.integer 10); + compare; + ] + + let _ = + Format.printf "Testing rewriting and type inference\n" ; + Format.printf "Source program: %a\n" Mikhailsky.pp program + + open Tezos_micheline_rewriting + + module Lang = + Micheline_with_hash_consing.Make + (Mikhailsky.Mikhailsky_signature) + (struct + let initial_size = None + end) + + module Path = Mikhailsky.Path + module Patt = Pattern.Make (Mikhailsky.Mikhailsky_signature) (Lang) (Path) + module Rewriter = + Rewrite.Make (Mikhailsky.Mikhailsky_signature) (Lang) (Path) (Patt) + + let timing, ((bef, aft), state) = + try time @@ fun () -> Inference.infer_with_state program + with Inference.Ill_typed_script error -> + let s = Mikhailsky.to_string program in + Format.printf + "Ill-typed script:%a\n%s\n" + Inference.pp_inference_error + error + s ; + Format.printf "Test failed\n" ; + exit 1 + + let () = + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft + + let () = + try + ignore + ((let open Inference in + let open M in + M.uf_lift Uf.UF.show >>= fun uf_state -> + Inference.M.repr_lift (fun s -> (Inference.Repr_store.to_string s, s)) + >>= fun repr_state -> + Printf.printf "uf_state:\n%s\n" uf_state ; + Printf.printf "repr_state:\n%s\n" repr_state ; + let path = + Path.(at_index 2 (at_index 0 (at_index 0 (at_index 3 root)))) + in + let subterm = Rewriter.get_subterm ~term:program ~path in + Format.printf + "subterm at path %s:\n%a\n" + (Path.to_string path) + Mikhailsky.pp + subterm ; + Inference.M.annot_instr_lift (Inference.Annot_instr_sm.get path) + >>= fun typ -> + (match typ with + | None -> assert false + | Some {bef; aft} -> + Inference.instantiate bef >>= fun bef -> + Inference.instantiate aft >>= fun aft -> + Format.printf "Type of subterm:\n" ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + return ()) + >>= fun () -> return ()) + state) + with Inference.Ill_typed_script error -> + let s = Mikhailsky.to_string program in + Format.printf + "Ill-typed script:\n%a\n%s\n" + Inference.pp_inference_error + error + s + + let _ = print_newline () +end + +module Test4 = struct + open Instructions + + let program = + seq + [ + empty_set; + push Type.(unopt (unparse_ty bool)) Data.true_; + push + Type.(unopt (unparse_ty (pair int int))) + Data.(pair (integer 0) (integer 0)); + update_set; + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test5 = struct + open Instructions + + let unopt x = match x with Some x -> x | None -> assert false + + let program = + seq + [ + empty_map; + push Type.(unopt (unparse_ty (option (set int)))) Data.none; + push + Type.(unopt (unparse_ty (pair int int))) + Data.(pair (integer 0) (integer 0)); + update_map; + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () + + let program = + seq + [ + push + Type.(unopt (unparse_ty (map (pair int int) (set int)))) + Data.( + map + [ + map_elt + (pair (integer 0) (integer 1)) + (set [integer 42; integer 44]); + map_elt + (pair (integer 1) (integer 2)) + (set [integer 42; integer 48]); + ]); + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test6 = struct + open Instructions + + (* We remove a chunk from a well-typed program to make it ill-typed, and + expect the type inference to fail *) + let program = + seq + [ + push int_ty (Data.integer 0); + push int_ty (Data.integer 100); + swap; + drop; + drop; + drop; + push unit_ty Data.unit; + push bool_ty Data.false_; + push unit_ty Data.unit; + push int_ty (Data.integer 4073851221413541140); + push string_ty (string "n"); + push string_ty (string "k"); + push int_ty (Data.integer 1391989767887046289); + (* push int_ty (integer 100); + * abs; + * drop; *) + dip (prim I_CONCAT [] []); + compare; + ] + + let () = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING FAILURE\n" ; + Format.printf "Program: %a\n" Mikhailsky.pp program ; + let exception Test_failed in + try + ignore (Inference.infer program) ; + raise Test_failed + with + | Inference.Ill_typed_script error -> + Format.printf "Got error, as expected:\n" ; + Format.printf "%a@." Inference.pp_inference_error error + | Test_failed -> + Format.printf "No type error: Test failed!" ; + exit 1 +end + +module Test7 = struct + open Instructions + + let program = + seq + [ + push int_ty (Data.integer 42); + left; + push string_ty (Data.string "forty-two"); + right; + pair; + left; + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test8 = struct + open Instructions + + let program = + seq + [ + hole; + add_ii; + push int_ty (Data.big_integer (Z.of_int 100)); + abs; + right; + dup; + push int_ty (Data.big_integer (Z.of_int 100)); + dip (loop_left hole); + push_int; + hole; + mul_ii; + hole; + loop_left left; + sha512; + push_int; + dup; + add_ii; + right; + swap; + hole; + drop; + compare; + mul_ii; + push_int; + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test9 = struct + open Instructions + + let program = seq [car; if_none hole hole] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test10 = struct + open Instructions + + let program = seq [hash_key] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test11 = struct + open Instructions + + let program = + seq [lambda [dup; car; dip cdr; add_in]; push_int; apply; push_nat; exec] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test12 = struct + open Instructions + + let program = seq [dup; dup; if_none hole (seq [drop]); dup; compare] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test13 = struct + open Instructions + + let program = + seq [push Type.(unparse_ty_exn (lambda int int)) (Data.lambda [])] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test14 = struct + open Instructions + + let program = seq [nil; push_int; cons] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test15 = struct + open Instructions + + let program = seq [empty_set; size_set; empty_map; size_map; nil; size_list] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test16 = struct + open Instructions + + let program = + seq + [ + empty_set; + push bool_ty Data.true_; + push_int; + update_set; + iter_set [dup; add_ii; add_ii]; + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test17 = struct + open Instructions + + let program = + seq + [ + empty_map; + push (option_ty (list_ty bool_ty)) Data.(some (list [false_; true_])); + push_int; + update_map; + map_map + [ + cdr; + map_list + [ + if_ + (seq [push bool_ty Data.false_]) + (seq [push bool_ty Data.true_]); + ]; + ]; + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end + +module Test18 = struct + open Instructions + + let program = + seq + [ + empty_map; + push (option_ty (list_ty bool_ty)) Data.(some (list [false_; true_])); + push_int; + update_map; + map_map + [ + cdr; + map_list + [ + if_ + (seq [push bool_ty Data.false_]) + (seq [push bool_ty Data.true_]); + ]; + ]; + dup; + dip push_int; + push_int; + mem_map; + if_ + (seq [get_map]) + (seq [drop; drop; push (option_ty (list_ty bool_ty)) Data.none]); + ] + + let timing, (bef, aft) = time @@ fun () -> Inference.infer program + + let _ = + Format.printf "Testing type inference\n" ; + Format.printf "EXPECTING SUCCESS\n" ; + Format.printf "Program\n" ; + Format.printf "%a\n" Mikhailsky.pp program ; + Format.printf "In %f seconds:\n" timing ; + Format.printf "bef: %a@." Type.Stack.pp bef ; + Format.printf "aft: %a@." Type.Stack.pp aft ; + print_newline () +end diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_uf.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_uf.ml new file mode 100644 index 000000000000..84fdd856e9ba --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/test_uf.ml @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let _ = + print_newline () ; + Printf.printf "Testing union-find algorithm\n" + +module UF = Uf.UF + +let test = + let open UF.M in + UF.add 0 >>= fun () -> + UF.add 1 >>= fun () -> + UF.add 2 >>= fun () -> + UF.add 3 >>= fun () -> + UF.add 4 >>= fun () -> + UF.find 0 >>= fun v0_repr -> + UF.find 1 >>= fun v1_repr -> + assert (v0_repr <> v1_repr) ; + UF.union 0 1 >>= fun _ -> + UF.find 0 >>= fun v0_repr -> + UF.find 1 >>= fun v1_repr -> + UF.find 2 >>= fun v2_repr -> + assert (v0_repr = v1_repr) ; + assert (v0_repr <> v2_repr) ; + UF.union 2 3 >>= fun _ -> + UF.union 0 3 >>= fun _ -> + UF.find 1 >>= fun v1_repr -> + UF.find 2 >>= fun v2_repr -> + UF.find 3 >>= fun v3_repr -> + UF.find 4 >>= fun v4_repr -> + assert (v1_repr = v2_repr) ; + UF.union 4 4 >>= fun _ -> + assert (v3_repr <> v4_repr) ; + UF.show >>= fun s -> + Printf.printf "UF state:%s\n" s ; + return () + +let () = UF.M.run test + +let _ = Printf.printf "Success.\n" diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.ml new file mode 100644 index 000000000000..bc8d164c6c5c --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.ml @@ -0,0 +1,200 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Michelson types. *) + +module Base = struct + type comparable_tag = Comparable | Maybe_not_comparable + + type t = t_node Hashcons.hash_consed + + and t_node = + | Unit_t + | Var_t of int + | Int_t + | Nat_t + | Bool_t + | String_t + | Bytes_t + | Key_hash_t + | Timestamp_t + | Mutez_t + | Key_t + | Option_t of t + | Pair_t of t * t + | Or_t of t * t + | List_t of t + | Set_t of t + | Map_t of t * t + | Lambda_t of t * t + + module Hashed = struct + type t = t_node + + let equal (t1 : t) (t2 : t) = + match (t1, t2) with + | Var_t v1, Var_t v2 -> v1 = v2 + | Unit_t, Unit_t + | Int_t, Int_t + | Nat_t, Nat_t + | Bool_t, Bool_t + | String_t, String_t + | Bytes_t, Bytes_t + | Key_hash_t, Key_hash_t + | Timestamp_t, Timestamp_t + | Mutez_t, Mutez_t + | Key_t, Key_t -> + true + | Option_t ty1, Option_t ty2 -> ty1.tag = ty2.tag + | Pair_t (l1, r1), Pair_t (l2, r2) -> l1.tag = l2.tag && r1.tag = r2.tag + | Or_t (l1, r1), Or_t (l2, r2) -> l1.tag = l2.tag && r1.tag = r2.tag + | List_t ty1, List_t ty2 -> ty1.tag = ty2.tag + | Set_t ty1, Set_t ty2 -> ty1.tag = ty2.tag + | Map_t (kty1, vty1), Map_t (kty2, vty2) -> + kty1.tag = kty2.tag && vty1.tag = vty2.tag + | Lambda_t (dom1, range1), Lambda_t (dom2, range2) -> + dom1.tag = dom2.tag && range1.tag = range2.tag + | _ -> false + + let hash (t : t) = Hashtbl.hash t + end + + module Table = Hashcons.Make (Hashed) + + let table = Table.create 101 + + let rec pp fmtr x = + match x.Hashcons.node with + | Unit_t -> Format.pp_print_string fmtr "unit" + | Var_t v -> Format.fprintf fmtr "%d" v + | Int_t -> Format.pp_print_string fmtr "int" + | Nat_t -> Format.pp_print_string fmtr "nat" + | Bool_t -> Format.pp_print_string fmtr "bool" + | String_t -> Format.pp_print_string fmtr "string" + | Bytes_t -> Format.pp_print_string fmtr "bytes" + | Key_hash_t -> Format.pp_print_string fmtr "key_hash" + | Timestamp_t -> Format.pp_print_string fmtr "timestamp" + | Mutez_t -> Format.pp_print_string fmtr "mutez" + | Key_t -> Format.pp_print_string fmtr "key" + | Option_t ty -> Format.fprintf fmtr "(option %a)" pp ty + | List_t ty -> Format.fprintf fmtr "(list %a)" pp ty + | Pair_t (lty, rty) -> Format.fprintf fmtr "(pair %a %a)" pp lty pp rty + | Or_t (lty, rty) -> Format.fprintf fmtr "(or %a %a)" pp lty pp rty + | Set_t ty -> Format.fprintf fmtr "(set %a)" pp ty + | Map_t (kty, vty) -> Format.fprintf fmtr "(map %a %a)" pp kty pp vty + | Lambda_t (dom, range) -> + Format.fprintf fmtr "(lambda %a %a)" pp dom pp range + + let rec vars x acc = + match x.Hashcons.node with + | Unit_t | Int_t | Nat_t | Bool_t | String_t | Bytes_t | Key_hash_t + | Timestamp_t | Mutez_t | Key_t -> + acc + | Var_t v -> v :: acc + | Option_t ty | List_t ty | Set_t ty -> vars ty acc + | Pair_t (lty, rty) | Or_t (lty, rty) -> vars lty (vars rty acc) + | Map_t (kty, vty) -> vars kty (vars vty acc) + | Lambda_t (dom, range) -> vars dom (vars range acc) + + let vars x = vars x [] +end + +module Stack = struct + type t = t_node Hashcons.hash_consed + + and t_node = Empty_t | Stack_var_t of int | Item_t of Base.t * t + + module Hashed = struct + type t = t_node + + let equal (t1 : t) (t2 : t) = + match (t1, t2) with + | Empty_t, Empty_t -> true + | Stack_var_t v1, Stack_var_t v2 -> v1 = v2 + | Item_t (h1, tl1), Item_t (h2, tl2) -> h1 == h2 && tl1 == tl2 + | _ -> false + + let hash (t : t) = Hashtbl.hash t + end + + module Table = Hashcons.Make (Hashed) + + let table = Table.create 101 + + let rec pp fmtr x = + match x.Hashcons.node with + | Empty_t -> Format.pp_print_string fmtr "[]" + | Stack_var_t v -> Format.fprintf fmtr "<%d>" v + | Item_t (head, tail) -> Format.fprintf fmtr "%a :: %a" Base.pp head pp tail + + let rec vars x = + match x.Hashcons.node with + | Empty_t -> None + | Stack_var_t v -> Some v + | Item_t (_head, tail) -> vars tail +end + +let unit = Base.Table.hashcons Base.table Unit_t + +let var x = Base.Table.hashcons Base.table (Var_t x) + +let int = Base.Table.hashcons Base.table Int_t + +let nat = Base.Table.hashcons Base.table Nat_t + +let bool = Base.Table.hashcons Base.table Bool_t + +let string = Base.Table.hashcons Base.table String_t + +let bytes = Base.Table.hashcons Base.table Bytes_t + +let key_hash = Base.Table.hashcons Base.table Key_hash_t + +let timestamp = Base.Table.hashcons Base.table Timestamp_t + +let mutez = Base.Table.hashcons Base.table Mutez_t + +let key = Base.Table.hashcons Base.table Key_t + +let option ty = Base.Table.hashcons Base.table (Option_t ty) + +let pair lty rty = Base.Table.hashcons Base.table (Pair_t (lty, rty)) + +let or_ lty rty = Base.Table.hashcons Base.table (Or_t (lty, rty)) + +let list ty = Base.Table.hashcons Base.table (List_t ty) + +let set ty = Base.Table.hashcons Base.table (Set_t ty) + +let map kty vty = Base.Table.hashcons Base.table (Map_t (kty, vty)) + +let lambda dom range = Base.Table.hashcons Base.table (Lambda_t (dom, range)) + +(* Stack smart constructors *) +let empty = Stack.Table.hashcons Stack.table Empty_t + +let stack_var x = Stack.Table.hashcons Stack.table (Stack_var_t x) + +let item head tail = Stack.Table.hashcons Stack.table (Item_t (head, tail)) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.mli b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.mli new file mode 100644 index 000000000000..bdc806590b25 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/type.mli @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Michelson types, hash-consed. *) + +(** Base types *) +module Base : sig + type comparable_tag = Comparable | Maybe_not_comparable + + type t = t_node Hashcons.hash_consed + + and t_node = private + | Unit_t + | Var_t of int + | Int_t + | Nat_t + | Bool_t + | String_t + | Bytes_t + | Key_hash_t + | Timestamp_t + | Mutez_t + | Key_t + | Option_t of t + | Pair_t of t * t + | Or_t of t * t + | List_t of t + | Set_t of t + | Map_t of t * t + | Lambda_t of t * t + + val pp : Format.formatter -> t -> unit + + val vars : t -> int list +end + +(** Stack types *) +module Stack : sig + type t = t_node Hashcons.hash_consed + + and t_node = private Empty_t | Stack_var_t of int | Item_t of Base.t * t + + val pp : Format.formatter -> t -> unit + + val vars : t -> int option +end + +(** Smart constructors *) +val unit : Base.t + +val var : int -> Base.t + +val int : Base.t + +val nat : Base.t + +val bool : Base.t + +val string : Base.t + +val bytes : Base.t + +val key_hash : Base.t + +val timestamp : Base.t + +val mutez : Base.t + +val key : Base.t + +val option : Base.t -> Base.t + +val pair : Base.t -> Base.t -> Base.t + +val or_ : Base.t -> Base.t -> Base.t + +val list : Base.t -> Base.t + +val set : Base.t -> Base.t + +val map : Base.t -> Base.t -> Base.t + +val lambda : Base.t -> Base.t -> Base.t + +val empty : Stack.t + +val stack_var : int -> Stack.t + +val item : Base.t -> Stack.t -> Stack.t diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/uf.ml b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/uf.ml new file mode 100644 index 000000000000..f14a166939a7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/uf.ml @@ -0,0 +1,99 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* ------------------------------------------------------------------------- *) +(* Union find parameterized over a persistent store. *) + +module type S = sig + module M : Monads.State_sig + + type key = int + + val add : key -> unit M.t + + val find : key -> key M.t + + val union : key -> key -> key M.t + + val show : string M.t +end + +module UF : S = struct + type node = T of {rank : int} | Ptr of key + + and key = int + + module S = + Stores.Map + (Int_map) + (struct + type key = int + + type value = node + + let key_to_string = string_of_int + + let value_to_string (x : value) = + match x with + | T {rank} -> Printf.sprintf "[%d]" rank + | Ptr k -> Printf.sprintf "ptr(%d)" k + end) + + module M = Monads.Make_state_monad (S) + + let add (k : key) = + let open M in + set k (T {rank = 1}) + + let rec get_root (k : key) (acc : key list) = + let open M in + get k >>= function + | None -> + let msg = Printf.sprintf "UF.get_root: invalid key %d" k in + Stdlib.failwith msg + | Some (T {rank}) -> + let ptr_to_root = Ptr k in + iter_list (fun key -> set key ptr_to_root) acc >>= fun () -> + return (k, rank) + | Some (Ptr k') -> get_root k' (k :: acc) + + let find (k : key) = + let open M in + get_root k [] >>= fun (res, _) -> return res + + let union k1 k2 = + let open M in + get_root k1 [] >>= fun (k1, rank1) -> + get_root k2 [] >>= fun (k2, rank2) -> + if k1 = k2 then return k1 + else if rank1 < rank2 then set k1 (Ptr k2) >>= fun () -> return k2 + else if rank1 > rank2 then set k2 (Ptr k1) >>= fun () -> return k1 + else + let new_root = T {rank = rank1 + 1} in + set k2 (Ptr k1) >>= fun () -> + set k1 new_root >>= fun () -> return k1 + + let show s = (S.to_string s, s) +end diff --git a/src/proto_020_PsParisC/lib_benchmark/micheline_sampler.ml b/src/proto_020_PsParisC/lib_benchmark/micheline_sampler.ml new file mode 100644 index 000000000000..1e4778f856f0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/micheline_sampler.ml @@ -0,0 +1,110 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Micheline sampling. *) + +type width_function = depth:int -> int Base_samplers.sampler + +(** [Base_samplers] specifies samplers for leaves, primitives and annotations. *) +module type Base_samplers = sig + (** The type of primitives. *) + type prim + + val sample_prim : prim Base_samplers.sampler + + val sample_annots : string list Base_samplers.sampler + + val sample_string : string Base_samplers.sampler + + val sample_bytes : Bytes.t Base_samplers.sampler + + val sample_z : Z.t Base_samplers.sampler + + val width_function : width_function +end + +module type S = sig + type prim + + val sample : (int, prim) Micheline.node Base_samplers.sampler +end + +type node_kind = Int_node | String_node | Bytes_node | Seq_node | Prim_node + +(* The distribution can be skewed towards non-leaf nodes by repeating their + relevant kind in the array below. *) +let all_kinds = [|Int_node; String_node; Bytes_node; Seq_node; Prim_node|] + +let sample_kind : node_kind Base_samplers.sampler = + fun rng_state -> + let i = Random.State.int rng_state (Array.length all_kinds) in + all_kinds.(i) + +let reasonable_width_function ~depth rng_state = + (* Entirely ad-hoc *) + Base_samplers.( + sample_in_interval + ~range:{min = 0; max = 20 / (Bits.numbits depth + 1)} + rng_state) + +module Make (P : Base_samplers) : S with type prim = P.prim = struct + type prim = P.prim + + let sample (w : width_function) rng_state = + let rec sample depth rng_state k = + match sample_kind rng_state with + | Int_node -> k (Micheline.Int (0, P.sample_z rng_state)) + | String_node -> k (Micheline.String (0, P.sample_string rng_state)) + | Bytes_node -> k (Micheline.Bytes (0, P.sample_bytes rng_state)) + | Seq_node -> + let width = w ~depth rng_state in + sample_list + depth + width + [] + (fun terms -> k (Micheline.Seq (0, terms))) + rng_state + | Prim_node -> + let prim = P.sample_prim rng_state in + let annots = P.sample_annots rng_state in + let width = w ~depth rng_state in + sample_list + depth + width + [] + (fun terms -> k (Micheline.Prim (0, prim, terms, annots))) + rng_state + and sample_list depth width acc k rng_state = + if width < 0 then invalid_arg "sample_list: negative width" + else if width = 0 then k (List.rev acc) + else + sample (depth + 1) rng_state (fun x -> + sample_list depth (width - 1) (x :: acc) k rng_state) + in + sample 0 rng_state (fun x -> x) + + let sample rng_state = sample P.width_function rng_state +end diff --git a/src/proto_020_PsParisC/lib_benchmark/micheline_sampler.mli b/src/proto_020_PsParisC/lib_benchmark/micheline_sampler.mli new file mode 100644 index 000000000000..97e3d4ec1e12 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/micheline_sampler.mli @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Micheline sampling. *) + +(** A [width_function] specifies the distribution of node degree as a function + of [depth]. A [width_function] {e must} be supported by the nonnegative + integers. + + Note that picking a [width_function] which doesn't converge fast enough to + the singular distribution on 0 could yield very large terms. *) +type width_function = depth:int -> int Base_samplers.sampler + +(** [reasonable_width_function] is a width function which works well + empirically. *) +val reasonable_width_function : width_function + +(** [Base_samplers] specifies samplers for leaves, primitives and annotations. *) +module type Base_samplers = sig + (** The type of primitives. *) + type prim + + val sample_prim : prim Base_samplers.sampler + + val sample_annots : string list Base_samplers.sampler + + val sample_string : string Base_samplers.sampler + + val sample_bytes : Bytes.t Base_samplers.sampler + + val sample_z : Z.t Base_samplers.sampler + + val width_function : width_function +end + +(** Applying the [Make] functor below yields a module with the following + type. *) +module type S = sig + type prim + + (** [sample w] is a Micheline sampler for the prescribed primitive + type. The sampler uses the provided width function [w]. *) + val sample : (int, prim) Micheline.node Base_samplers.sampler +end + +(** [Make] instantiates a micheline sampler. *) +module Make (P : Base_samplers) : S with type prim = P.prim diff --git a/src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.ml b/src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.ml new file mode 100644 index 000000000000..a5b66c0f53af --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.ml @@ -0,0 +1,339 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** MCMC-based Michelson data and code samplers. *) + +open Protocol +open Stats + +type michelson_code = { + term : Script_repr.expr; + bef : Script_repr.expr list; + aft : Script_repr.expr list; +} + +type michelson_data = {term : Script_repr.expr; typ : Script_repr.expr} + +type michelson_sample = Code of michelson_code | Data of michelson_data + +let michelson_sample_list_encoding = + let open Data_encoding in + let e = Script_repr.expr_encoding in + list + @@ union + [ + case + ~title:"Code" + (Tag 0) + (tup3 e (list e) (list e)) + (function + | Code {term; bef; aft} -> Some (term, bef, aft) | _ -> None) + (fun (term, bef, aft) -> Code {term; bef; aft}); + case + ~title:"Data" + (Tag 1) + (tup2 e e) + (function Data {term; typ} -> Some (term, typ) | _ -> None) + (fun (term, typ) -> Data {term; typ}); + ] + +let save ~filename ~terms = + let str = + match + Data_encoding.Binary.to_string michelson_sample_list_encoding terms + with + | Error err -> + Format.eprintf + "Michelson_mcmc_samplers.save: encoding failed (%a); exiting@." + Data_encoding.Binary.pp_write_error + err ; + exit 1 + | Ok res -> res + in + try Lwt_main.run @@ Tezos_stdlib_unix.Lwt_utils_unix.create_file filename str + with exn -> + Format.eprintf + "Michelson_mcmc_samplers.save: create_file %s failed (%s); exiting@." + filename + (Printexc.to_string exn) ; + exit 1 + +let load ~filename = + let open TzPervasives in + let string = + try Lwt_main.run @@ Tezos_stdlib_unix.Lwt_utils_unix.read_file filename + with exn -> + Format.eprintf + "Michelson_mcmc_samplers.load: read_file %s failed (%s); exiting@." + filename + (Printexc.to_string exn) ; + exit 1 + in + let bytes = Bytes.of_string string in + match Data_encoding.Binary.of_bytes michelson_sample_list_encoding bytes with + | Ok result -> result + | Error err -> + Format.eprintf + "Michelson_mcmc_samplers.load: decoding %s failed (%a); exiting@." + filename + Data_encoding.Binary.pp_read_error + err ; + exit 1 + +(* Helpers *) + +let base_type_to_michelson_type (typ : Type.Base.t) = + let typ = Mikhailsky.map_var (fun _ -> Mikhailsky.unit_ty) typ in + Mikhailsky.to_michelson typ + +module type Sampler_parameters_sig = sig + val initial : State_space.t + + val energy : State_space.t -> float + + val rules : Rules.rule_set list + + val infer : Mikhailsky.node -> Inference.state + + val verbosity : [`Silent | `Progress | `Trace] +end + +(* The Markov chain in state [state] *) +type mc_state = { + state : State_space.t; + jump : State_space.t Fin.Float.prb Lazy.t; +} + +module State_hashtbl = Hashtbl.Make (State_space) + +(** Generic MCMC michelson sampler (can be used for code and data) *) +module Make_generic (P : Sampler_parameters_sig) = struct + let uniform (l : State_space.t list) : State_space.t Fin.Float.prb = + match l with + | [] -> + (* This can only happen is the MCMC was driven to a coffin state, + which means that it's not reversible (this is a bug) *) + assert false + | _ -> + let arr = Array.of_list l in + let emp = Emp.of_raw_data arr in + Fin.Float.counts_of_empirical (module State_hashtbl) emp + |> Fin.Float.normalize + + let unrecoverable_failure err current result = + Format.eprintf "Error when typechecking term:@." ; + Format.eprintf "%a@." Inference.pp_inference_error err ; + Format.eprintf "Original state: @[%a@]@." State_space.pp current ; + Format.eprintf "Erroneous term: %a@." Mikhailsky.pp result ; + Stdlib.failwith "in sampler.ml: unrecoverable failure." + + let of_state : State_space.t -> mc_state = + fun state -> + { + state; + jump = + Lazy.from_fun (fun () -> + let current = state in + let rewriting_options = Rules.rewriting current P.rules in + let term = current.term in + let rewritings = + List.fold_left + (fun rewritings (path, replacement) -> + let result = Kernel.Rewriter.subst ~term ~path ~replacement in + let typing = + Lazy.from_fun (fun () -> + try P.infer result + with Inference.Ill_typed_script err -> + unrecoverable_failure err current result) + in + {State_space.typing; term = result} :: rewritings) + [] + rewriting_options + in + uniform rewritings); + } + + module MH_params : Mh.MH_parameters with type t = mc_state = struct + type t = mc_state + + let pp fmtr {state; jump = _} = State_space.pp fmtr state + + let trace state = + match P.verbosity with + | `Silent | `Progress -> () + | `Trace -> + Format.eprintf "@." ; + Format.eprintf "%a" State_space.pp state ; + Format.eprintf "energy:@." ; + Format.eprintf "%f:@." (P.energy state) + + let proposal_log_density s1 s2 = + let jump = Lazy.force s1.jump in + let p = try Fin.Float.eval_prb jump s2.state with Not_found -> 0.0 in + Log_space.of_float p + + let proposal mcmc_state rng_state = + trace mcmc_state.state ; + let dist = Lazy.force mcmc_state.jump in + let next = Fin.Float.sample (Fin.Float.as_measure dist) rng_state in + of_state next + + let log_weight state = Log_space.unsafe_cast (-.P.energy state.state) + end + + module Sampler = Mh.Make (MH_params) + + let generator ~burn_in = + P.(Sampler.mcmc ~verbosity ~initial:(of_state initial) ~burn_in) +end + +module Make_code_sampler + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) (X : sig + val rng_state : Random.State.t + + val target_size : int + + val verbosity : [`Silent | `Progress | `Trace] + end) = +struct + module Autocomp = Autocomp.Make (Michelson_base) (Crypto_samplers) + + module MCMC = Make_generic (struct + let initial = + let term = Mikhailsky.Instructions.hole in + let typing = Lazy.from_val @@ snd (Inference.infer_with_state term) in + {State_space.term; typing} + + let energy state = + let stats = State_space.statistics state in + let size_deficit = + abs_float + (float_of_int X.target_size -. float_of_int stats.State_space.size) + in + let holes_proportion = float stats.holes /. float stats.size in + let holes_deficit = + (* we want at least 1% of holes, above is ok *) + if holes_proportion < 0.01 then + (0.01 -. holes_proportion) *. size_deficit + else 0.0 + in + size_deficit +. holes_deficit + + let rules = Rules.Instruction.rules + + let infer term = snd (Inference.infer_with_state term) + + let verbosity = X.verbosity + end) + + let to_michelson {state = ({typing; term} : State_space.t); jump = _} = + let typing = Lazy.force typing in + let node, (bef, aft), state = + Autocomp.complete_code typing term X.rng_state + in + let node = + Micheline.strip_locations @@ Mikhailsky_to_michelson.convert node state + in + { + term = node; + bef = Type_helpers.stack_type_to_michelson_type_list bef; + aft = Type_helpers.stack_type_to_michelson_type_list aft; + } + + let generator ~burn_in = + Gen.map (MCMC.generator ~burn_in) @@ fun after_burn_in -> + Gen.map after_burn_in to_michelson +end + +module Make_data_sampler + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) (X : sig + val rng_state : Random.State.t + + val target_size : int + + val verbosity : [`Silent | `Progress | `Trace] + end) = +struct + module Autocomp = Autocomp.Make (Michelson_base) (Crypto_samplers) + module Rewrite_rules = + Rules.Data_rewrite_leaves (Michelson_base) (Crypto_samplers) + + module MCMC = Make_generic (struct + let initial = + let term = Mikhailsky.Data.hole in + let typing = + Lazy.from_val @@ snd (Inference.infer_data_with_state term) + in + {State_space.term; typing} + + let energy state = + let stats = State_space.statistics state in + let size_deficit = + abs_float + (float_of_int X.target_size -. float_of_int stats.State_space.size) + in + let holes_proportion = + float_of_int stats.holes /. float_of_int stats.size + in + let holes_deficit = + (* we want at least 10% of holes, above is ok *) + if holes_proportion < 0.5 then (0.5 -. holes_proportion) *. size_deficit + else 0.0 + in + let depth_deficit = + abs_float + ((0.1 *. float_of_int X.target_size) -. float_of_int stats.depth) + in + size_deficit +. holes_deficit +. depth_deficit + + let rules = Rewrite_rules.rules X.rng_state + + let infer term = snd (Inference.infer_data_with_state term) + + let verbosity = X.verbosity + end) + + let to_michelson {state = ({typing; term} : State_space.t); jump = _} = + let typing = Lazy.force typing in + let node, _ = Autocomp.complete_data typing term X.rng_state in + let typ, state = + try Inference.infer_data_with_state node + with _ -> + Format.eprintf "Bug found!@." ; + Format.eprintf "Ill-typed autocompletion. Resulting term:@." ; + Format.eprintf "%a@." Mikhailsky.pp node ; + Stdlib.failwith "in generators.ml: unrecoverable failure" + in + let node = + Micheline.strip_locations @@ Mikhailsky_to_michelson.convert node state + in + {term = node; typ = base_type_to_michelson_type typ} + + let generator ~burn_in = + Gen.map (MCMC.generator ~burn_in) @@ fun after_burn_in -> + Gen.map after_burn_in to_michelson +end diff --git a/src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.mli b/src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.mli new file mode 100644 index 000000000000..bd67d13e3c16 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/michelson_mcmc_samplers.mli @@ -0,0 +1,115 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** MCMC-based Michelson data and code samplers. *) + +open Protocol + +(** MCMC samplers can either produce data or code. Note that the samplers + natively produce data and code in Micheline (ie untyped) form. *) + +type michelson_code = { + term : Script_repr.expr; + (** [term] is a typeable Michelson program in Micheline form. *) + bef : Script_repr.expr list; + (** [bef] is an input stack type for which [term] is a well-typed script. *) + aft : Script_repr.expr list; + (** [aft] is the stack type corresponding to the execution of [term] + on a stack of type [bef]. *) +} + +type michelson_data = { + term : Script_repr.expr; + (** [term] is a typeable Michelson data in Micheline form. *) + typ : Script_repr.expr; (** [typ] is the type of [term]. *) +} + +(** A [michelson_sample] is either a code sample or a data sample. *) +type michelson_sample = Code of michelson_code | Data of michelson_data + +(** Encoding used for saving or loading data. *) +val michelson_sample_list_encoding : michelson_sample list Data_encoding.t + +(** Saving a list of samples to a file. + Exits with code 1 if an error arises during encoding or file manipulation. *) +val save : filename:string -> terms:michelson_sample list -> unit + +(** Loading a list of samples from a file. + Exits with code 1 if an error arises during decoding or file manipulation. *) +val load : filename:string -> michelson_sample list + +(** [Make_code_sampler] produces a sampler for well-typed Michelson code. + The parameters of the functor are: + - a module [Michelson_base] implementing samplers for basic values + - a module [Crypto_samplers] implementing samplers for pk/pkh/sk triplets + - a module [X] containing some parameters to the Markov chain sampler: + - [rng_state] is the mutable state that will be used during sampling + - [target_size] specifies the size, in terms of Micheline nodes, of the + terms that the sampler should try to produce + - [verbosity] specifies how much information should be written on stdout + during the sampling process. + + The outcome is a [michelson_code] [generator]. The [burn_in] parameter + specifies how much samples should be thrown away before starting to + produce sample (this is used to let the underlying Markov chain reach + its stationary distribution - the value should be commensurate with + the [target_size]. + *) +module Make_code_sampler : functor + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) + (X : sig + val rng_state : Random.State.t + + val target_size : int + + val verbosity : [`Progress | `Silent | `Trace] + end) + -> sig + (** [generator ~burn_in rng_state] performs a burn-in phase consisting of sampling [burn_in] times, + throwing the results away and returns a michelson term sampler. The goal of burn-in is + to drive the underlying Markov chain to its stationary distribution, ie to sample + terms around the specified [X.target_size]. *) + val generator : burn_in:int -> Random.State.t -> michelson_code Stats.Gen.t +end + +(** See documentation for [Make_code_sampler] *) +module Make_data_sampler : functor + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) + (X : sig + val rng_state : Random.State.t + + val target_size : int + + val verbosity : [`Progress | `Silent | `Trace] + end) + -> sig + (** [generator ~burn_in rng_state] performs a burn-in phase consisting of sampling [burn_in] times, + throwing the results away and returns a michelson term sampler. The goal of burn-in is + to drive the underlying Markov chain to its stationary distribution, ie to sample + terms around the specified [X.target_size]. *) + val generator : burn_in:int -> Random.State.t -> michelson_data Stats.Gen.t +end diff --git a/src/proto_020_PsParisC/lib_benchmark/michelson_samplers.ml b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers.ml new file mode 100644 index 000000000000..5929ded858d9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers.ml @@ -0,0 +1,823 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Script_typed_ir + +type parameters = { + base_parameters : Michelson_samplers_base.parameters; + list_size : Base_samplers.range; + set_size : Base_samplers.range; + map_size : Base_samplers.range; +} + +let parameters_encoding = + let open Data_encoding in + let range_encoding = Base_samplers.range_encoding in + conv + (fun {base_parameters; list_size; set_size; map_size} -> + (base_parameters, (list_size, set_size, map_size))) + (fun (base_parameters, (list_size, set_size, map_size)) -> + {base_parameters; list_size; set_size; map_size}) + (merge_objs + Michelson_samplers_base.parameters_encoding + (obj3 + (req "list_size" range_encoding) + (req "set_size" range_encoding) + (req "map_size" range_encoding))) + +(* ------------------------------------------------------------------------- *) +(* Type names. *) + +(* We only want to generated inhabited types, hence Never is not included. *) + +type type_name = + [ `TUnit + | `TInt + | `TNat + | `TSignature + | `TString + | `TBytes + | `TMutez + | `TKey_hash + | `TKey + | `TTimestamp + | `TAddress + | `TBool + | `TPair + | `TOr + | `TLambda + | `TOption + | `TList + | `TSet + | `TMap + | `TBig_map + | `TContract + | `TSapling_transaction + | `TSapling_transaction_deprecated + | `TSapling_state + | `TOperation + | `TChain_id + | `TBls12_381_g1 + | `TBls12_381_g2 + | `TBls12_381_fr + | `TTicket ] + +type atomic_type_name = + [ `TUnit + | `TInt + | `TNat + | `TSignature + | `TString + | `TBytes + | `TMutez + | `TKey_hash + | `TKey + | `TTimestamp + | `TAddress + | `TBool + | `TSapling_transaction + | `TSapling_transaction_deprecated + | `TSapling_state + | `TChain_id + | `TBls12_381_g1 + | `TBls12_381_g2 + | `TBls12_381_fr ] + +type non_atomic_type_name = + [ `TPair + | `TOr + | `TLambda + | `TOption + | `TList + | `TSet + | `TMap + | `TBig_map + | `TContract + | `TTicket ] + +(* Ensure inclusion of atomic_type_name in type_name *) +let (_ : atomic_type_name -> type_name) = fun x -> (x :> type_name) + +(* Ensure inclusion of non_atomic_type_name in type_name *) +let (_ : non_atomic_type_name -> type_name) = fun x -> (x :> type_name) + +let all_atomic_type_names : atomic_type_name array = + [| + `TUnit; + `TInt; + `TNat; + `TSignature; + `TString; + `TBytes; + `TMutez; + `TKey_hash; + `TKey; + `TTimestamp; + `TAddress; + `TBool; + `TSapling_transaction; + `TSapling_transaction_deprecated; + `TSapling_state; + `TChain_id; + `TBls12_381_g1; + `TBls12_381_g2; + `TBls12_381_fr; + |] + +let all_non_atomic_type_names : non_atomic_type_name array = + [| + `TPair; + `TOr; + `TLambda; + `TOption; + `TList; + `TSet; + `TMap; + `TBig_map; + `TContract; + `TTicket; + |] + +type comparable_type_name = + [ `TUnit + | `TInt + | `TNat + | `TSignature + | `TString + | `TBytes + | `TMutez + | `TBool + | `TKey_hash + | `TKey + | `TTimestamp + | `TChain_id + | `TAddress + | `TPair + | `TOr + | `TOption ] + +(* Ensure inclusion of comparable_type_name in type_name *) +let (_ : comparable_type_name -> type_name) = fun x -> (x :> type_name) + +type 'a comparable_and_atomic = 'a + constraint 'a = [< comparable_type_name] constraint 'a = [< atomic_type_name] + +let all_comparable_atomic_type_names : 'a comparable_and_atomic array = + [| + `TUnit; + `TInt; + `TNat; + `TSignature; + `TString; + `TBytes; + `TMutez; + `TBool; + `TKey_hash; + `TKey; + `TTimestamp; + `TChain_id; + `TAddress; + |] + +type 'a comparable_and_non_atomic = 'a + constraint 'a = [< comparable_type_name] + constraint 'a = [< non_atomic_type_name] + +let all_comparable_non_atomic_type_names : 'a comparable_and_non_atomic array = + [|`TPair; `TOr; `TOption|] + +(* Ensure inclusion of comparable_and_atomic in type_name *) +let (_ : 'a comparable_and_atomic -> type_name) = fun x -> (x :> type_name) + +(* ------------------------------------------------------------------------- *) +(* Uniform type name generators *) + +open Sampling_helpers + +let uniform : ?blacklist:('a -> bool) -> 'a array -> 'a sampler = + fun ?blacklist arr rng_state -> + let arr = + match blacklist with + | None -> arr + | Some blacklist -> + Array.to_seq arr + |> Seq.filter (fun x -> not (blacklist x)) + |> Array.of_seq + in + let i = Random.State.int rng_state (Array.length arr) in + arr.(i) + +let uniform_atomic_type_name ?blacklist : atomic_type_name sampler = + uniform ?blacklist all_atomic_type_names + +let uniform_comparable_atomic_type_name : 'a comparable_and_atomic sampler = + uniform all_comparable_atomic_type_names + +let uniform_comparable_non_atomic_type_name : + 'a comparable_and_non_atomic sampler = + uniform all_comparable_non_atomic_type_names + +(* ------------------------------------------------------------------------- *) +(* Random generation functor. *) + +module type S = sig + module Michelson_base : Michelson_samplers_base.S + + module Random_type : sig + val m_type : + size:int -> + ?blacklist:(type_name -> bool) -> + unit -> + Script_typed_ir.ex_ty sampler + + val m_comparable_type : + size:int -> Script_ir_translator.ex_comparable_ty sampler + end + + module Random_value : sig + val value : ('a, _) Script_typed_ir.ty -> 'a sampler + + val comparable : 'a Script_typed_ir.comparable_ty -> 'a sampler + + val stack : ('a, 'b) Script_typed_ir.stack_ty -> ('a * 'b) sampler + end +end + +exception SamplingError of string + +let fail_sampling error = raise (SamplingError error) + +module Make (P : sig + val parameters : parameters +end) +(Crypto_samplers : Crypto_samplers.Finite_key_pool_S) : S = struct + module Michelson_base = Michelson_samplers_base.Make (struct + let parameters = P.parameters.base_parameters + end) + + let memo_size = + Alpha_context.Sapling.Memo_size.parse_z Z.zero |> Result.get_ok + + (* [pick_split x] randomly splits the integer [x] into two integers [left] + and [right] such that [1 <= left], [1 <= right], and [left + right = x]. + Expects [x >= 2]. *) + let pick_split : int -> (int * int) sampler = + fun x rng_state -> + if x < 2 then invalid_arg "pick_split" + else + (* x >= 2 *) + let left = 1 + Random.State.int rng_state (x - 1) in + let right = x - left in + assert (left + right = x) ; + (left, right) + + (* Random generation of Michelson types. *) + module Random_type = struct + let type_of_atomic_type_name (at_tn : atomic_type_name) : + Script_typed_ir.ex_ty = + match at_tn with + | `TString -> Ex_ty string_t + | `TNat -> Ex_ty nat_t + | `TKey -> Ex_ty key_t + | `TBytes -> Ex_ty bytes_t + | `TBool -> Ex_ty bool_t + | `TAddress -> Ex_ty address_t + | `TTimestamp -> Ex_ty timestamp_t + | `TKey_hash -> Ex_ty key_hash_t + | `TMutez -> Ex_ty mutez_t + | `TSignature -> Ex_ty signature_t + | `TUnit -> Ex_ty unit_t + | `TInt -> Ex_ty int_t + | `TSapling_state -> Ex_ty (sapling_state_t ~memo_size) + | `TSapling_transaction -> Ex_ty (sapling_transaction_t ~memo_size) + | `TSapling_transaction_deprecated -> + Ex_ty (sapling_transaction_deprecated_t ~memo_size) + | `TChain_id -> Ex_ty chain_id_t + | `TBls12_381_g1 -> Ex_ty bls12_381_g1_t + | `TBls12_381_g2 -> Ex_ty bls12_381_g2_t + | `TBls12_381_fr -> Ex_ty bls12_381_fr_t + + let comparable_type_of_comparable_atomic_type_name + (cmp_tn : 'a comparable_and_atomic) : + Script_ir_translator.ex_comparable_ty = + match cmp_tn with + | `TString -> Ex_comparable_ty string_t + | `TNat -> Ex_comparable_ty nat_t + | `TBytes -> Ex_comparable_ty bytes_t + | `TBool -> Ex_comparable_ty bool_t + | `TAddress -> Ex_comparable_ty address_t + | `TTimestamp -> Ex_comparable_ty timestamp_t + | `TKey_hash -> Ex_comparable_ty key_hash_t + | `TMutez -> Ex_comparable_ty mutez_t + | `TInt -> Ex_comparable_ty int_t + | `TUnit -> Ex_comparable_ty unit_t + | `TSignature -> Ex_comparable_ty signature_t + | `TKey -> Ex_comparable_ty key_t + | `TChain_id -> Ex_comparable_ty chain_id_t + + let rec m_type ~size ?blacklist () : Script_typed_ir.ex_ty sampler = + let open Script_ir_translator in + let open M in + let blacklist = + match blacklist with + | None -> None + | Some blacklist -> Some (fun x -> blacklist (x :> type_name)) + in + if size <= 0 then Stdlib.failwith "m_type: size <= 0" + else if size = 1 then + (* only atomic types can have size 1 *) + let* at_tn = uniform_atomic_type_name ?blacklist in + return (type_of_atomic_type_name at_tn) + else if size = 2 then + bind + (uniform [|`TOption; `TList; `TSet; `TTicket; `TContract|] ?blacklist) + @@ function + | `TOption -> ( + let* (Ex_ty t) = m_type ~size:1 ?blacklist () in + match option_t (-1) t with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TList -> ( + let* (Ex_ty t) = m_type ~size:1 ?blacklist () in + match list_t (-1) t with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TSet -> ( + let* (Ex_comparable_ty t) = m_comparable_type ~size:1 in + match set_t (-1) t with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TTicket -> ( + let* (Ex_comparable_ty contents) = m_comparable_type ~size:1 in + match ticket_t (-1) contents with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TContract -> ( + let* (Ex_ty t) = m_type ~size:1 ?blacklist () in + match contract_t (-1) t with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + else + bind (uniform all_non_atomic_type_names ?blacklist) @@ function + | `TPair -> ( + let* lsize, rsize = pick_split (size - 1) in + let* (Ex_ty left) = m_type ~size:lsize ?blacklist () in + let* (Ex_ty right) = m_type ~size:rsize ?blacklist () in + match pair_t (-1) left right with + | Error _ -> assert false + | Ok (Ty_ex_c res_ty) -> return @@ Ex_ty res_ty) + | `TLambda -> ( + let* lsize, rsize = pick_split (size - 1) in + let* (Ex_ty domain) = m_type ~size:lsize ?blacklist () in + let* (Ex_ty range) = m_type ~size:rsize ?blacklist () in + match lambda_t (-1) domain range with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TOr -> ( + let* lsize, rsize = pick_split (size - 1) in + let* (Ex_ty left) = m_type ~size:lsize ?blacklist () in + let* (Ex_ty right) = m_type ~size:rsize ?blacklist () in + match or_t (-1) left right with + | Error _ -> assert false + | Ok (Ty_ex_c res_ty) -> return @@ Ex_ty res_ty) + | `TOption -> ( + let* (Ex_ty t) = m_type ~size:(size - 1) ?blacklist () in + match option_t (-1) t with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TMap -> ( + let* lsize, rsize = pick_split (size - 1) in + let* (Ex_comparable_ty key) = m_comparable_type ~size:lsize in + let* (Ex_ty elt) = m_type ~size:rsize ?blacklist () in + match map_t (-1) key elt with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TSet -> ( + let* (Ex_comparable_ty key_ty) = + m_comparable_type ~size:(size - 1) + in + match set_t (-1) key_ty with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TList -> ( + let* (Ex_ty elt) = m_type ~size:(size - 1) ?blacklist () in + match list_t (-1) elt with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TTicket -> ( + let* (Ex_comparable_ty contents) = + m_comparable_type ~size:(size - 1) + in + match ticket_t (-1) contents with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TContract -> ( + let* (Ex_ty t) = m_type ~size:(size - 1) ?blacklist () in + match contract_t (-1) t with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_ty res_ty) + | `TBig_map -> + (* Don't know what to do with theses. Redraw. *) + m_type ~size ?blacklist () + + and m_comparable_type ~size : Script_ir_translator.ex_comparable_ty sampler + = + let open M in + let open Script_ir_translator in + let atomic_case () = + let* at_tn = uniform_comparable_atomic_type_name in + return (comparable_type_of_comparable_atomic_type_name at_tn) + in + let option_case size = + let size = size - 1 in + let* (Ex_comparable_ty t) = m_comparable_type ~size in + match option_t (-1) t with + | Error _ -> (* what should be done here? *) assert false + | Ok res_ty -> return @@ Ex_comparable_ty res_ty + in + let pair_case size = + let size = size - 1 in + let* size_left = + Base_samplers.sample_in_interval ~range:{min = 1; max = size - 1} + in + let size_right = size - size_left in + let* (Ex_comparable_ty l) = m_comparable_type ~size:size_left in + let* (Ex_comparable_ty r) = m_comparable_type ~size:size_right in + match comparable_pair_t (-1) l r with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_comparable_ty res_ty + in + let or_case size = + let size = size - 1 in + let* size_left = + Base_samplers.sample_in_interval ~range:{min = 1; max = size - 1} + in + let size_right = size - size_left in + let* (Ex_comparable_ty l) = m_comparable_type ~size:size_left in + let* (Ex_comparable_ty r) = m_comparable_type ~size:size_right in + match comparable_or_t (-1) l r with + | Error _ -> assert false + | Ok res_ty -> return @@ Ex_comparable_ty res_ty + in + + if size <= 1 then atomic_case () + else if size = 2 then option_case size + else + let* cmp_tn = uniform_comparable_non_atomic_type_name in + match cmp_tn with + | `TPair -> pair_case size + | `TOr -> or_case size + | `TOption -> option_case size + end + + (* Type-directed generation of random values. *) + module Random_value : sig + val value : ('a, _) Script_typed_ir.ty -> 'a sampler + + val comparable : 'a Script_typed_ir.comparable_ty -> 'a sampler + + val stack : ('a, 'b) Script_typed_ir.stack_ty -> ('a * 'b) sampler + end = struct + let implicit = Crypto_samplers.pkh + + let originated rng_state = + (* For a description of the format, see + tezos-codec describe alpha.contract binary encoding *) + let string = + "\001" ^ Base_samplers.uniform_string ~nbytes:20 rng_state ^ "\000" + in + Data_encoding.Binary.of_string_exn + Alpha_context.Contract.originated_encoding + string + + let sc_rollup rng_state = + let string = Base_samplers.uniform_string ~nbytes:20 rng_state in + Data_encoding.Binary.of_string_exn + Alpha_context.Sc_rollup.Address.encoding + string + + let entrypoint rng_state = + Alpha_context.Entrypoint.of_string_strict_exn + @@ Base_samplers.string ~size:{min = 1; max = 31} rng_state + + let address rng_state = + if Base_samplers.uniform_bool rng_state then + let destination = + Alpha_context.Destination.Contract (Implicit (implicit rng_state)) + in + {destination; entrypoint = Alpha_context.Entrypoint.default} + else + let destination = + Alpha_context.Destination.Contract (Originated (originated rng_state)) + in + let entrypoint = entrypoint rng_state in + {destination; entrypoint} + + let generate_originated_contract : + type arg argc. + (arg, argc) Script_typed_ir.ty -> + arg Script_typed_ir.typed_contract sampler = + fun arg_ty -> + let open M in + let* c = originated in + let* entrypoint in + let destination = Alpha_context.Destination.Contract (Originated c) in + return + (Typed_contract.Internal_for_tests.typed_exn + arg_ty + destination + entrypoint) + + let generate_sc_rollup_contract : + type arg argc. + (arg, argc) Script_typed_ir.ty -> + arg Script_typed_ir.typed_contract sampler = + fun arg_ty -> + let open M in + let* ru = sc_rollup in + let destination = Alpha_context.Destination.Sc_rollup ru in + return + (Typed_contract.Internal_for_tests.typed_exn + arg_ty + destination + Alpha_context.Entrypoint.default) + + let generate_any_type_contract : + type arg argc. + (arg, argc) Script_typed_ir.ty -> + arg Script_typed_ir.typed_contract sampler = + fun arg_ty -> + let open M in + let* b = Base_samplers.uniform_bool in + if b then generate_originated_contract arg_ty + else generate_sc_rollup_contract arg_ty + + let generate_contract : + type arg argc. + (arg, argc) Script_typed_ir.ty -> + arg Script_typed_ir.typed_contract sampler = + fun arg_ty -> + let open M in + match arg_ty with + | Unit_t -> + let* b = Base_samplers.uniform_bool in + if b then + let* pkh = implicit in + let destination = + Alpha_context.Destination.Contract (Implicit pkh) + in + let entrypoint = Alpha_context.Entrypoint.default in + return + (Typed_contract.Internal_for_tests.typed_exn + arg_ty + destination + entrypoint) + else generate_any_type_contract arg_ty + | _ -> generate_any_type_contract arg_ty + + let chain_id rng_state = + let string = Base_samplers.uniform_string ~nbytes:4 rng_state in + Data_encoding.Binary.of_string_exn Script_chain_id.encoding string + + let signature rng_state = + Script_signature.make (Michelson_base.signature rng_state) + + let rec value : type a ac. (a, ac) Script_typed_ir.ty -> a sampler = + let open Script_typed_ir in + fun typ -> + match typ with + | Never_t -> assert false + | Unit_t -> M.return () + | Int_t -> Michelson_base.int + | Nat_t -> Michelson_base.nat + | Signature_t -> signature + | String_t -> Michelson_base.string + | Bytes_t -> Michelson_base.bytes + | Mutez_t -> Michelson_base.tez + | Key_hash_t -> Crypto_samplers.pkh + | Key_t -> Crypto_samplers.pk + | Timestamp_t -> Michelson_base.timestamp + | Bool_t -> Base_samplers.uniform_bool + | Address_t -> address + | Pair_t (left_t, right_t, _, _) -> + M.( + let* left_v = value left_t in + let* right_v = value right_t in + return (left_v, right_v)) + | Or_t (left_t, right_t, _, _) -> + fun rng_state -> + if Base_samplers.uniform_bool rng_state then + L (value left_t rng_state) + else R (value right_t rng_state) + | Lambda_t (arg_ty, ret_ty, _) -> generate_lambda arg_ty ret_ty + | Option_t (ty, _, _) -> + fun rng_state -> + if Base_samplers.uniform_bool rng_state then None + else Some (value ty rng_state) + | List_t (elt_ty, _) -> generate_list elt_ty + | Set_t (elt_ty, _) -> generate_set elt_ty + | Map_t (key_ty, val_ty, _) -> generate_map key_ty val_ty + | Contract_t (arg_ty, _) -> generate_contract arg_ty + | Operation_t -> generate_operation + | Big_map_t (key_ty, val_ty, _) -> generate_big_map key_ty val_ty + | Chain_id_t -> chain_id + | Bls12_381_g1_t -> generate_bls12_381_g1 + | Bls12_381_g2_t -> generate_bls12_381_g2 + | Bls12_381_fr_t -> generate_bls12_381_fr + | Ticket_t (contents_ty, _) -> generate_ticket contents_ty + | Sapling_transaction_t _ -> + fail_sampling + "Michelson_samplers: sapling transactions not handled yet" + | Sapling_transaction_deprecated_t _ -> + fail_sampling + "Michelson_samplers: sapling transactions not handled yet" + | Sapling_state_t _ -> + fail_sampling "Michelson_samplers: sapling state not handled yet" + | Chest_key_t -> + fail_sampling "Michelson_samplers: chest key not handled yet" + | Chest_t -> fail_sampling "Michelson_samplers: chest not handled yet" + + and generate_lambda : + type arg argc ret retc. + (arg, argc) Script_typed_ir.ty -> + (ret, retc) Script_typed_ir.ty -> + (arg, ret) Script_typed_ir.lambda sampler = + fun _arg_ty _ret_ty _rng_state -> + fail_sampling "Michelson_samplers: lambda not handled yet" + + and generate_list : + type elt eltc. + (elt, eltc) Script_typed_ir.ty -> elt Script_list.t sampler = + fun elt_type -> + let open M in + let* _, elements = + Structure_samplers.list + ~range:P.parameters.list_size + ~sampler:(value elt_type) + in + return @@ Script_list.of_list elements + + (* Note that we might very well generate sets smaller than the specified range (consider the + case of a set of type [unit]). *) + and generate_set : + type elt. + elt Script_typed_ir.comparable_ty -> elt Script_typed_ir.set sampler = + fun elt_ty -> + let open M in + let* _, elements = + Structure_samplers.list + ~range:P.parameters.set_size + ~sampler:(value elt_ty) + in + return + @@ List.fold_left + (fun set x -> Script_set.update x true set) + (Script_set.empty elt_ty) + elements + + and generate_map : + type key elt eltc. + key Script_typed_ir.comparable_ty -> + (elt, eltc) Script_typed_ir.ty -> + (key, elt) Script_typed_ir.map sampler = + fun key_ty elt_ty rng_state -> + let size = + Base_samplers.sample_in_interval rng_state ~range:P.parameters.map_size + in + let keys = List.init size (fun _ -> value key_ty rng_state) in + let elts = List.init size (fun _ -> value elt_ty rng_state) in + List.fold_left2 + (fun map key elt -> Script_map.update key (Some elt) map) + (Script_map.empty key_ty) + keys + elts + + and generate_big_map : + type key elt eltc. + key Script_typed_ir.comparable_ty -> + (elt, eltc) Script_typed_ir.ty -> + (key, elt) Script_typed_ir.big_map sampler = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + fun key_ty elt_ty rng_state -> + let open TzPervasives in + let result = + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let big_map = Script_big_map.empty key_ty elt_ty in + (* Cannot have big maps under big maps *) + let*? opt_elt_ty = + option_t (-1) elt_ty |> Environment.wrap_tzresult + in + let map = generate_map key_ty opt_elt_ty rng_state in + let* big_map, _ = + let*! result = + Script_map.fold + (fun k v acc -> + let* bm, ctxt_acc = acc in + Script_big_map.update ctxt_acc k v bm) + map + (return (big_map, ctxt)) + in + Lwt.return @@ Environment.wrap_tzresult result + in + return big_map) + in + match result with + | Ok x -> x + | Error e -> + Format.eprintf + "%a@." + (Error_monad.TzTrace.pp_print Error_monad.pp) + e ; + fail_sampling "raise_if_error" + + and generate_operation : Script_typed_ir.operation sampler = + fun rng_state -> + let transfer = generate_transfer_tokens rng_state in + Script_typed_ir.{piop = transfer; lazy_storage_diff = None} + + and generate_transfer_tokens : + Script_typed_ir.packed_internal_operation sampler = + fun _rng_state -> fail_sampling "generate_transfer_tokens: unimplemented" + + and generate_bls12_381_g1 : Script_bls.G1.t sampler = + fun rng_state -> + let b = Bls12_381.G1.(to_bytes (random ~state:rng_state ())) in + match Script_bls.G1.of_bytes_opt b with + | Some x -> x + | None -> assert false + + and generate_bls12_381_g2 : Script_bls.G2.t sampler = + fun rng_state -> + let b = Bls12_381.G2.(to_bytes (random ~state:rng_state ())) in + match Script_bls.G2.of_bytes_opt b with + | Some x -> x + | None -> assert false + + and generate_bls12_381_fr : Script_bls.Fr.t sampler = + fun rng_state -> + let b = Bls12_381.Fr.(to_bytes (random ~state:rng_state ())) in + match Script_bls.Fr.of_bytes_opt b with + | Some x -> x + | None -> assert false + + and generate_ticket : + type a ac. + (a, ac) Script_typed_ir.ty -> a Script_typed_ir.ticket sampler = + fun ty rng_state -> + let contents = value ty rng_state in + let ticketer = + Alpha_context.Contract.Implicit (Crypto_samplers.pkh rng_state) + in + let amount = + let open Ticket_amount in + match of_n (Michelson_base.nat rng_state) with + | Some amount -> add amount one + | None -> one + in + Script_typed_ir.{ticketer; contents; amount} + + let comparable ty = value ty + + (* Random stack generation. *) + let rec stack : type a b. (a, b) Script_typed_ir.stack_ty -> (a * b) sampler + = + let open M in + let open Script_typed_ir in + fun stack_ty -> + match stack_ty with + | Item_t (ty, tl) -> + let* elt = value ty in + let* tl = stack tl in + return ((elt, tl) : a * b) + | Bot_t -> return (EmptyCell, EmptyCell) + end +end + +module Internal_for_tests = struct + type nonrec type_name = type_name +end diff --git a/src/proto_020_PsParisC/lib_benchmark/michelson_samplers.mli b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers.mli new file mode 100644 index 000000000000..78ee62a3392c --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers.mli @@ -0,0 +1,172 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Sampling various Michelson values. *) + +exception SamplingError of string + +open Protocol +open Base_samplers + +(** This module exposes a functor implementing various samplers for Michelson. + These allow to sample: + - types and comparable types (given a target size), + - values and comparable values of a given Michelson type (given some more + parameters fixed at functor instantiation time) + - stacks + + Note that some kind of values might not be supported. At the time of writing, + the value sampler doesn't handle the following types: + - Sapling transaction and states + - Timelock chests and chest keys + - Operations + - Lambdas (ie code) + + For the latter, consider using the samplers in {!Michelson_mcmc_samplers}. +*) + +(** Parameters for the Michelson samplers. *) +type parameters = { + base_parameters : Michelson_samplers_base.parameters; + list_size : Base_samplers.range; + (** The range of the size, measured in number of elements, in which lists must be sampled.*) + set_size : Base_samplers.range; + (** The range of the size, measured in number of elements, in which sets must be sampled.*) + map_size : Base_samplers.range; + (** The range of the size, measured in number of bindings, in which maps must be sampled.*) +} + +(** Encoding for sampler prameters. *) +val parameters_encoding : parameters Data_encoding.t + +type type_name = + [ `TUnit + | `TInt + | `TNat + | `TSignature + | `TString + | `TBytes + | `TMutez + | `TKey_hash + | `TKey + | `TTimestamp + | `TAddress + | `TBool + | `TPair + | `TOr + | `TLambda + | `TOption + | `TList + | `TSet + | `TMap + | `TBig_map + | `TContract + | `TSapling_transaction + | `TSapling_transaction_deprecated + | `TSapling_state + | `TOperation + | `TChain_id + | `TBls12_381_g1 + | `TBls12_381_g2 + | `TBls12_381_fr + | `TTicket ] + +(** The module type produced by the [Make] functor. *) +module type S = sig + (** Basic Michelson samplers, re-exported for convenience by the functor. *) + module Michelson_base : Michelson_samplers_base.S + + (** Samplers for random Michelson types. *) + module Random_type : sig + (** [m_type ~size ?blacklist] samples a type containing exactly + [size] constructors. The [blacklist] is a predicate which can + be used to discard some unwanted cases. *) + val m_type : + size:int -> + ?blacklist:(type_name -> bool) -> + unit -> + Script_typed_ir.ex_ty sampler + + (** [m_comparable_type ~size] samples a comparable type containing + exactly [size] constructors. *) + val m_comparable_type : + size:int -> Script_ir_translator.ex_comparable_ty sampler + end + + (** Samplers for random Michelson values. Restrictions apply on the + supported types as listed at the beginning of this file. *) + module Random_value : sig + (** Sample a value given its type. *) + val value : ('a, _) Script_typed_ir.ty -> 'a sampler + + (** Sample a comparable value given its type. *) + val comparable : 'a Script_typed_ir.comparable_ty -> 'a sampler + + (** Sample a stack given its type. *) + val stack : ('a, 'b) Script_typed_ir.stack_ty -> ('a * 'b) sampler + end +end + +(** Instantiate a module of type {!S}. *) +module Make : functor + (P : sig + val parameters : parameters + end) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) + -> S + +module Internal_for_tests : sig + type type_name = + [ `TAddress + | `TBig_map + | `TBls12_381_fr + | `TBls12_381_g1 + | `TBls12_381_g2 + | `TBool + | `TBytes + | `TChain_id + | `TContract + | `TInt + | `TKey + | `TKey_hash + | `TLambda + | `TList + | `TMap + | `TMutez + | `TNat + | `TOperation + | `TOption + | `TPair + | `TSapling_state + | `TSapling_transaction + | `TSapling_transaction_deprecated + | `TSet + | `TSignature + | `TString + | `TTicket + | `TTimestamp + | `TOr + | `TUnit ] +end diff --git a/src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.ml b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.ml new file mode 100644 index 000000000000..651a385016bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.ml @@ -0,0 +1,139 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Sampling_helpers + +(** Parameters for basic samplers *) +type parameters = { + int_size : Base_samplers.range; + string_size : Base_samplers.range; + bytes_size : Base_samplers.range; +} + +(** Encoding for basic samplers parameters *) +let parameters_encoding = + let open Data_encoding in + let range = Base_samplers.range_encoding in + conv + (fun {int_size; string_size; bytes_size} -> + (int_size, string_size, bytes_size)) + (fun (int_size, string_size, bytes_size) -> + {int_size; string_size; bytes_size}) + (obj3 + (req "int_size" range) + (req "string_size" range) + (req "bytes_size" range)) + +(** A module of type [S] packs samplers used to construct basic Michelson values. *) +module type S = sig + val int : Script_int.z Script_int.num sampler + + val nat : Script_int.n Script_int.num sampler + + val signature : Tezos_crypto.Signature.t sampler + + val string : Script_string.t sampler + + val bytes : bytes sampler + + val tez : Alpha_context.Tez.t sampler + + val timestamp : Script_timestamp.t sampler +end + +(* Samplers for basic Michelson types. *) + +module Make (P : sig + val parameters : parameters +end) : S = struct + let int rng_state = + let i = Base_samplers.int ~size:P.parameters.int_size rng_state in + Script_int.of_zint i + + let nat rng_state = + let i = Base_samplers.nat ~size:P.parameters.int_size rng_state in + Script_int.abs (Script_int.of_zint i) + + let signature rng_state = + let i = Random.State.int rng_state 5 in + match i with + | 0 -> ( + let open Tezos_crypto.Signature.Ed25519 in + let bytes = Base_samplers.uniform_bytes ~nbytes:size rng_state in + match of_bytes_opt bytes with + | None -> assert false + | Some s -> Tezos_crypto.Signature.of_ed25519 s) + | 1 -> ( + let open Tezos_crypto.Signature.Secp256k1 in + let bytes = Base_samplers.uniform_bytes ~nbytes:size rng_state in + match of_bytes_opt bytes with + | None -> assert false + | Some s -> Tezos_crypto.Signature.of_secp256k1 s) + | 2 -> ( + let open Tezos_crypto.Signature.P256 in + let bytes = Base_samplers.uniform_bytes ~nbytes:size rng_state in + match of_bytes_opt bytes with + | None -> assert false + | Some s -> Tezos_crypto.Signature.of_p256 s) + | 3 -> + (* BLS checks that signatures are on the curve so we need to generate real + ones by signing a message. *) + let open Tezos_crypto.Signature.Bls in + let msg = Base_samplers.uniform_bytes ~nbytes:32 rng_state in + let seed = Base_samplers.uniform_bytes ~nbytes:32 rng_state in + let _, _, sk = generate_key ~seed () in + Tezos_crypto.Signature.of_bls (sign sk msg) + | _ -> + let open Tezos_crypto.Signature in + let bytes = + Base_samplers.uniform_bytes + ~nbytes:Tezos_crypto.Signature.Ed25519.size + rng_state + in + Unknown bytes + + let string rng_state = + let s = + Base_samplers.readable_ascii_string + ~size:P.parameters.string_size + rng_state + in + match Protocol.Script_string.of_string s with + | Ok s -> s + | Error _ -> assert false + + let bytes = Base_samplers.bytes ~size:P.parameters.bytes_size + + let tez rng_state = + let i = Random.State.int64 rng_state (Int64.of_int max_int) in + match Protocol.Alpha_context.Tez.of_mutez i with + | Some res -> res + | None -> assert false + + let timestamp rng_state = + let i = Base_samplers.int ~size:P.parameters.int_size rng_state in + Script_timestamp.of_zint i +end diff --git a/src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.mli b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.mli new file mode 100644 index 000000000000..91ebc6b4f10d --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/michelson_samplers_base.mli @@ -0,0 +1,67 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Samplers for basic Michelson values (not including pairs, ors, tickets, big maps, etc) *) + +open Protocol +open Base_samplers + +(** Parameters for basic samplers *) +type parameters = { + int_size : Base_samplers.range; + (** The range of the size, measured in bytes, in which big integers must be sampled.*) + string_size : Base_samplers.range; + (** The range of the size, measured in bytes, in which strings must be sampled.*) + bytes_size : Base_samplers.range; + (** The range of the size, measured in bytes, in which [bytes] must be sampled.*) +} + +(** Encoding for [parameters] *) +val parameters_encoding : parameters Data_encoding.t + +(** A module of type [S] packs samplers used to construct basic Michelson values. *) +module type S = sig + val int : Script_int.z Script_int.num sampler + + val nat : Script_int.n Script_int.num sampler + + val signature : Tezos_crypto.Signature.t sampler + + val string : Script_string.t sampler + + val bytes : bytes sampler + + val tez : Alpha_context.Tez.t sampler + + val timestamp : Script_timestamp.t sampler +end + +(** The [Make] functor instantiates a module of type [S], where the + samplers satisfy the given parameters. *) +module Make : functor + (P : sig + val parameters : parameters + end) + -> S diff --git a/src/proto_020_PsParisC/lib_benchmark/mikhailsky_to_michelson.ml b/src/proto_020_PsParisC/lib_benchmark/mikhailsky_to_michelson.ml new file mode 100644 index 000000000000..6ee761048306 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/mikhailsky_to_michelson.ml @@ -0,0 +1,229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +exception Cannot_get_type of Mikhailsky.node * Kernel.Path.t + +exception Unexpected_stack_type of string + +exception Unexpected_base_type + +let unparse_type = Mikhailsky.map_var (fun _ -> Mikhailsky.prim T_unit [] []) + +let project_top (aft : Type.Stack.t) = + match aft.node with + | Type.Stack.Empty_t -> raise (Unexpected_stack_type "empty") + | Type.Stack.Stack_var_t _ -> raise (Unexpected_stack_type "var") + | Type.Stack.Item_t (top, _) -> top + +let project_or (aft : Type.Stack.t) = + let top = project_top aft in + match top.node with + | Type.Base.Or_t (l, r) -> (l, r) + | _ -> raise Unexpected_base_type + +let project_lambda (aft : Type.Stack.t) = + let top = project_top aft in + match top.node with + | Type.Base.Lambda_t (dom, range) -> (dom, range) + | _ -> raise Unexpected_base_type + +let project_list (aft : Type.Stack.t) = + let top = project_top aft in + match top.node with + | Type.Base.List_t t -> t + | _ -> raise Unexpected_base_type + +let project_set (aft : Type.Stack.t) = + let top = project_top aft in + match top.node with Type.Base.Set_t t -> t | _ -> raise Unexpected_base_type + +let project_map (aft : Type.Stack.t) = + let top = project_top aft in + match top.node with + | Type.Base.Map_t (k, v) -> (k, v) + | _ -> raise Unexpected_base_type + +let project_option (aft : Type.Stack.t) = + let top = project_top aft in + match top.node with + | Type.Base.Option_t t -> t + | _ -> raise Unexpected_base_type + +let rec convert_raw : Mikhailsky.node -> (int, 'a) Micheline.node = + fun node -> + match node with + | Micheline.Int (_, i) -> Micheline.Int (0, i) + | Micheline.Prim (_, head, subterms, annots) -> + let head = Mikhailsky_prim.to_michelson head in + Micheline.Prim (0, head, List.map convert_raw subterms, annots) + | Micheline.String (_, s) -> Micheline.String (0, s) + | Micheline.Bytes (_, b) -> Micheline.Bytes (0, b) + | Micheline.Seq (_, subterms) -> + Micheline.Seq (0, List.map convert_raw subterms) + +(* We assume that the term has been completed. *) +let rec convert : + Mikhailsky.node -> Kernel.Path.t -> (int, 'a) Micheline.node Inference.M.t = + fun node path -> + let open Inference.M in + match node with + | Micheline.Int (_, i) -> return (Micheline.Int (0, i)) + | Micheline.String (_, s) -> return (Micheline.String (0, s)) + | Micheline.Bytes (_, b) -> return (Micheline.Bytes (0, b)) + (* Remove annotations *) + | Micheline.Prim (_, prim, [term], _) + when Mikhailsky_prim.kind prim = Annot_kind -> + let path = Kernel.Path.at_index 0 path in + convert term path + (* Fail on holes *) + | Micheline.Prim (_, I_Hole, _, _) | Micheline.Prim (_, D_Hole, _, _) -> + raise Mikhailsky.Term_contains_holes + (* Add type information to or injections *) + | Micheline.Prim (_, I_LEFT, [], annots) -> ( + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let _, r = project_or aft in + Inference.instantiate_base r >>= fun r -> + Autocomp.replace_vars r >>= fun r -> + let r = unparse_type r in + let head = Mikhailsky_prim.to_michelson I_LEFT in + return (Micheline.Prim (0, head, [convert_raw r], annots))) + | Micheline.Prim (_, I_RIGHT, [], annots) -> ( + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let l, _ = project_or aft in + Inference.instantiate_base l >>= fun l -> + Autocomp.replace_vars l >>= fun l -> + let l = unparse_type l in + let head = Mikhailsky_prim.to_michelson I_RIGHT in + return (Micheline.Prim (0, head, [convert_raw l], annots))) + | Micheline.Prim (_, (I_LEFT | I_RIGHT), _, _) -> + raise Mikhailsky.Ill_formed_mikhailsky + (* Add type information for lambdas *) + | Micheline.Prim (_, I_LAMBDA, [code], annots) -> ( + convert code (Kernel.Path.at_index 0 path) >>= fun code -> + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let dom, range = project_lambda aft in + Inference.instantiate_base dom >>= fun dom -> + Autocomp.replace_vars dom >>= fun dom -> + Inference.instantiate_base range >>= fun range -> + Autocomp.replace_vars range >>= fun range -> + let dom = unparse_type dom in + let range = unparse_type range in + let head = Mikhailsky_prim.to_michelson I_LAMBDA in + return + (Micheline.Prim + (0, head, [convert_raw dom; convert_raw range; code], annots))) + (* Add type information for empty_set, empty_map *) + | Micheline.Prim (_, I_EMPTY_SET, [], annots) -> ( + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let elt = project_set aft in + Inference.instantiate_base elt >>= fun elt -> + Autocomp.replace_vars elt >>= fun elt -> + let elt = unparse_type elt in + let head = Mikhailsky_prim.to_michelson I_EMPTY_SET in + return (Micheline.Prim (0, head, [convert_raw elt], annots))) + | Micheline.Prim (_, I_EMPTY_MAP, [], annots) -> ( + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let k, v = project_map aft in + Inference.instantiate_base k >>= fun k -> + Autocomp.replace_vars k >>= fun k -> + Inference.instantiate_base v >>= fun v -> + Autocomp.replace_vars v >>= fun v -> + let k = convert_raw (unparse_type k) in + let v = convert_raw (unparse_type v) in + let head = Mikhailsky_prim.to_michelson I_EMPTY_MAP in + return (Micheline.Prim (0, head, [k; v], annots))) + (* Add type information for UNPACK *) + | Micheline.Prim (_, I_UNPACK, [], annots) -> ( + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let elt = project_option aft in + Inference.instantiate_base elt >>= fun elt -> + Autocomp.replace_vars elt >>= fun elt -> + let elt = unparse_type elt in + let head = Mikhailsky_prim.to_michelson I_UNPACK in + return (Micheline.Prim (0, head, [convert_raw elt], annots))) + (* Add type information for NIL *) + | Micheline.Prim (_, I_NIL, [], annots) -> ( + get_instr_annot path >>= fun ty_opt -> + match ty_opt with + | None -> raise (Cannot_get_type (node, path)) + | Some {aft; _} -> + Inference.instantiate aft >>= fun aft -> + let elt = project_list aft in + Inference.instantiate_base elt >>= fun elt -> + Autocomp.replace_vars elt >>= fun elt -> + let elt = unparse_type elt in + let head = Mikhailsky_prim.to_michelson I_NIL in + return (Micheline.Prim (0, head, [convert_raw elt], annots))) + | Micheline.Prim (_, I_NIL, _, _) -> raise Mikhailsky.Ill_formed_mikhailsky + (* Project out type information from arithmetic ops *) + | Prim (_, ((I_ADD | I_SUB | I_MUL | I_EDIV) as instr), [_ty1; _ty2], annots) + -> + let head = Mikhailsky_prim.to_michelson instr in + return (Micheline.Prim (0, head, [], annots)) + | Prim (_, (I_ADD | I_SUB | I_MUL | I_EDIV), _, _) -> + raise Mikhailsky.Ill_formed_mikhailsky + (* Base case *) + | Micheline.Prim (_, head, subterms, annots) -> + let head = Mikhailsky_prim.to_michelson head in + convert_list path 0 subterms [] >>= fun subterms -> + return (Micheline.Prim (0, head, subterms, annots)) + | Micheline.Seq (_, subterms) -> + convert_list path 0 subterms [] >>= fun subterms -> + return (Micheline.Seq (0, subterms)) + +and convert_list path i subterms acc = + let open Inference.M in + match subterms with + | [] -> return (List.rev acc) + | subterm :: tl -> + let path' = Kernel.Path.at_index i path in + convert subterm path' >>= fun term -> + convert_list path (i + 1) tl (term :: acc) + +let convert node state = fst (convert node Kernel.Path.root state) diff --git a/src/proto_020_PsParisC/lib_benchmark/rules.ml b/src/proto_020_PsParisC/lib_benchmark/rules.ml new file mode 100644 index 000000000000..88a148e0213e --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/rules.ml @@ -0,0 +1,975 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Kernel + +type rule_set = {rule_patt : pattern; replacements : guarded_replacement list} + +and guarded_replacement = { + type_constraint : type_constraint; + replacement : replacement list; +} + +and type_constraint = + | No_cnstrnt + | Data_cnstrnt of {cnstrnt : Type.Base.t; fresh : int list} + | Instr_cnstrnt of { + cnstrnt : Inference.transformer; + fresh : var list; + fresh_stack : int list; + } + +and replacement = + | Context_aware of (Mikhailsky.node -> Mikhailsky.node) + | Context_blind of (unit -> Mikhailsky.node) + +and pattern = Pattern of Patt.t | Root + +and var = Plain of int | Cmp of int + +let stack_repr = Inference.Stack_type None + +let base_repr = + Inference.Base_type {repr = None; comparable = Inference.Unconstrained} + +let cmp_repr = + Inference.Base_type {repr = None; comparable = Inference.Comparable} + +let rec add_fresh_stack_variables vars = + let open Inference.M in + match vars with + | [] -> return () + | fresh :: tl -> + uf_lift (Uf.UF.add fresh) >>= fun () -> + set_repr fresh stack_repr >>= fun () -> add_fresh_stack_variables tl + +let rec add_fresh_data_variables vars = + let open Inference.M in + match vars with + | [] -> return () + | fresh :: tl -> + uf_lift (Uf.UF.add fresh) >>= fun () -> + set_repr fresh base_repr >>= fun () -> add_fresh_data_variables tl + +let rec add_fresh_variables vars plain_repr cmp_repr = + let open Inference.M in + match vars with + | [] -> return () + | Plain fresh :: tl -> + uf_lift (Uf.UF.add fresh) >>= fun () -> + set_repr fresh plain_repr >>= fun () -> + add_fresh_variables tl plain_repr cmp_repr + | Cmp fresh :: tl -> + uf_lift (Uf.UF.add fresh) >>= fun () -> + set_repr fresh cmp_repr >>= fun () -> + add_fresh_variables tl plain_repr cmp_repr + +let evaluate_guard_monadic guard path = + let open Inference.M in + match guard with + | No_cnstrnt -> return () + | Data_cnstrnt {cnstrnt = base_type_constraint; fresh} -> ( + add_fresh_data_variables fresh >>= fun () -> + get_data_annot path >>= fun res_opt -> + match res_opt with + | None -> assert false + | Some type_of_expr -> + Inference.unify_base type_of_expr base_type_constraint >>= fun () -> + Inference.instantiate_base type_of_expr >>= fun _ -> return ()) + | Instr_cnstrnt {cnstrnt = {bef = pre; aft = post}; fresh; fresh_stack} -> ( + (* Add base fresh type variables *) + add_fresh_variables fresh base_repr cmp_repr + >>= fun () -> + add_fresh_stack_variables fresh_stack >>= fun () -> + get_instr_annot path >>= fun res_opt -> + match res_opt with + | None -> assert false + | Some {bef; aft} -> + Inference.unify pre bef >>= fun () -> + Inference.unify post aft >>= fun () -> + Inference.instantiate bef >>= fun _bef -> + Inference.instantiate aft >>= fun _aft -> return ()) + +let evaluate_guard typing guard path = + try + let _ = evaluate_guard_monadic guard path typing in + true + with Inference.Ill_typed_script _ -> false + +let filter_matches typing guard matches = + List.filter (evaluate_guard typing guard) matches + +(* Provides a speedup but should better be done in the + rewriting module (so that not only top matches are hash-consed). *) +let matches_with_hash_consing = + let match_table : (int * int, Kernel.Path.t list) Hashtbl.t = + Hashtbl.create 97 + in + fun pattern term -> + match pattern with + | Root -> [Path.root] + | Pattern patt -> ( + let key = (Kernel.Patt.uid patt, Mikhailsky.tag term) in + match Hashtbl.find_opt match_table key with + | None -> + let res = Rewriter.all_matches patt term in + Hashtbl.add match_table key res ; + res + | Some res -> res) + +let matches_without_consing pattern term = + match pattern with + | Root -> [Path.root] + | Pattern patt -> Rewriter.all_matches patt term + +let rewriting (state : State_space.t) (rules : rule_set list) = + List.fold_left + (fun acc rule -> + let matches = matches_without_consing rule.rule_patt state.term in + List.fold_left + (fun acc guarded_replacement -> + let matches = + filter_matches + (Lazy.force state.typing) + guarded_replacement.type_constraint + matches + in + List.fold_left + (fun acc replacement -> + match replacement with + | Context_blind term -> + List.fold_left + (fun acc path -> (path, term ()) :: acc) + acc + matches + | Context_aware f -> + List.fold_left + (fun acc path -> + let term = Rewriter.get_subterm ~term:state.term ~path in + (path, f term) :: acc) + acc + matches) + acc + guarded_replacement.replacement) + acc + rule.replacements) + [] + rules + +module Instruction = struct + (* ----------------------------------------------------------------------- *) + (* Rule: replace instruction by hole. *) + + (* Matches instructions *) + let match_any_instr = + let open Patt in + Pattern + (focus + (prim_pred + (fun prim -> Mikhailsky_prim.kind prim = Mikhailsky_prim.Instr_kind) + list_any)) + + let replace_any_instr_by_hole = + let replace_by_hole = + { + type_constraint = No_cnstrnt; + replacement = [Context_blind (fun () -> Mikhailsky.instr_hole)]; + } + in + {rule_patt = match_any_instr; replacements = [replace_by_hole]} + + (* ----------------------------------------------------------------------- *) + (* Rule: replace instruction hole by instruction satisfying typing + constraints. *) + + (* Matches instruction holes *) + let match_instr_hole = + let open Patt in + Pattern (focus (prim I_Hole list_any)) + + let replacement ?(fresh = []) ?(fresh_stack = []) ~bef ~aft ~replacement () : + guarded_replacement = + { + type_constraint = Instr_cnstrnt {cnstrnt = {bef; aft}; fresh; fresh_stack}; + replacement; + } + + let instructions = + let open Type in + let module M = Mikhailsky in + let module I = Inference in + let alpha = ~-1 in + let beta = ~-2 in + let gamma = ~-3 in + let delta = ~-4 in + [ + replacement + ~fresh_stack:[alpha] + ~bef:(item bytes (stack_var alpha)) + ~aft:(item bytes (stack_var alpha)) + ~replacement: + [ + Context_blind (fun () -> M.Instructions.blake2b); + Context_blind (fun () -> M.Instructions.sha256); + Context_blind (fun () -> M.Instructions.sha512); + ] + (); + replacement + ~fresh_stack:[alpha] + ~bef:(item int (stack_var alpha)) + ~aft:(item bool (stack_var alpha)) + ~replacement:[Context_blind (fun () -> M.Instructions.gt)] + (); + replacement + ~fresh_stack:[alpha] + ~bef:(item int (stack_var alpha)) + ~aft:(item nat (stack_var alpha)) + ~replacement:[Context_blind (fun () -> M.Instructions.abs)] + (); + replacement + ~fresh_stack:[alpha] + ~bef:(item int (item int (stack_var alpha))) + ~aft:(item int (stack_var alpha)) + ~replacement: + [ + Context_blind (fun () -> M.Instructions.add M.int_ty M.int_ty); + Context_blind (fun () -> M.Instructions.mul M.int_ty M.int_ty); + ] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (pair (var alpha) (var beta)) (stack_var gamma)) + ~aft:(item (var alpha) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.car)] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (pair (var alpha) (var beta)) (stack_var gamma)) + ~aft:(item (var beta) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.cdr)] + (); + replacement + ~fresh:[Cmp alpha] + ~fresh_stack:[gamma] + ~bef:(item (var alpha) (item (var alpha) (stack_var gamma))) + ~aft:(item int (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.compare)] + (); + replacement + ~fresh_stack:[gamma] + ~bef:(item string (item string (stack_var gamma))) + ~aft:(item string (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.concat)] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[beta; gamma] + ~bef:(item (var alpha) (stack_var beta)) + ~aft:(item (var alpha) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.(dip hole))] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[beta] + ~bef:(item (var alpha) (stack_var beta)) + ~aft:(stack_var beta) + ~replacement:[Context_blind (fun () -> M.Instructions.drop)] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[beta] + ~bef:(item (var alpha) (stack_var beta)) + ~aft:(item (var alpha) (item (var alpha) (stack_var beta))) + ~replacement:[Context_blind (fun () -> M.Instructions.dup)] + (); + replacement + ~fresh:[] + ~fresh_stack:[alpha] + ~bef:(stack_var alpha) + ~aft:(item int (stack_var alpha)) + ~replacement: + [ + (* TODO : push random integer? *) + Context_blind + (fun () -> M.Instructions.push M.int_ty (M.Data.integer 100)); + ] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (var alpha) (item (var beta) (stack_var gamma))) + ~aft:(item (var beta) (item (var alpha) (stack_var gamma))) + ~replacement:[Context_blind (fun () -> M.Instructions.swap)] + (); + (* control *) + replacement + ~fresh_stack:[alpha] + ~bef:(item bool (stack_var alpha)) + ~aft:(stack_var alpha) + ~replacement:[Context_blind (fun () -> M.Instructions.(loop hole))] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (or_ (var alpha) (var beta)) (stack_var gamma)) + ~aft:(item (var beta) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.(loop_left hole))] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[beta; gamma] + ~bef:(item (option (var alpha)) (stack_var beta)) + ~aft:(stack_var gamma) + ~replacement: + [Context_blind (fun () -> M.Instructions.(if_none hole hole))] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma; delta] + ~bef:(item (or_ (var alpha) (var beta)) (stack_var gamma)) + ~aft:(stack_var delta) + ~replacement: + [Context_blind (fun () -> M.Instructions.(if_left hole hole))] + (); + replacement + ~fresh:[] + ~fresh_stack:[alpha; beta] + ~bef:(item bool (stack_var alpha)) + ~aft:(stack_var beta) + ~replacement:[Context_blind (fun () -> M.Instructions.(if_ hole hole))] + (); + replacement + ~fresh_stack:[alpha; beta] + ~bef:(stack_var alpha) + ~aft:(stack_var beta) + ~replacement: + [ + Context_blind + (fun () -> M.seq [M.Instructions.hole; M.Instructions.hole]); + ] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (var alpha) (stack_var gamma)) + ~aft:(item (or_ (var alpha) (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.left)] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (var beta) (stack_var gamma)) + ~aft:(item (or_ (var alpha) (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.right)] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(stack_var gamma) + ~aft:(item (lambda (var alpha) (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.(lambda [hole]))] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(stack_var gamma) + ~aft:(item (lambda (var alpha) (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.(lambda [hole]))] + (); + (* set/map/list*) + replacement + ~fresh:[Cmp alpha] + ~fresh_stack:[gamma] + ~bef: + (item + (var alpha) + (item bool (item (set (var alpha)) (stack_var gamma)))) + ~aft:(item (set (var alpha)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.update_set)] + (); + replacement + ~fresh:[Cmp alpha] + ~fresh_stack:[gamma] + ~bef:(stack_var gamma) + ~aft:(item (set (var alpha)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.empty_set)] + (); + replacement + ~fresh:[Cmp alpha] + ~fresh_stack:[gamma] + ~bef:(item (set (var alpha)) (stack_var gamma)) + ~aft:(stack_var gamma) + ~replacement: + [Context_blind (fun () -> M.Instructions.(iter_set [hole]))] + (); + replacement + ~fresh:[Cmp alpha] + ~fresh_stack:[gamma] + ~bef:(item (var alpha) (item (set (var alpha)) (stack_var gamma))) + ~aft:(item bool (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.mem_set)] + (); + replacement + ~fresh:[Cmp alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef: + (item + (var alpha) + (item + (option (var beta)) + (item (map (var alpha) (var beta)) (stack_var gamma)))) + ~aft:(item (map (var alpha) (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.update_map)] + (); + replacement + ~fresh:[Cmp alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(stack_var gamma) + ~aft:(item (map (var alpha) (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.empty_map)] + (); + replacement + ~fresh:[Cmp alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (map (var alpha) (var beta)) (stack_var gamma)) + ~aft:(stack_var gamma) + ~replacement: + [Context_blind (fun () -> M.Instructions.(iter_map [hole]))] + (); + replacement + ~fresh:[Cmp alpha; Plain beta; Plain delta] + ~fresh_stack:[gamma] + ~bef:(item (map (var alpha) (var beta)) (stack_var gamma)) + ~aft:(item (map (var alpha) (var delta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.(map_map [hole]))] + (); + replacement + ~fresh:[Cmp alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef: + (item + (var alpha) + (item (map (var alpha) (var beta)) (stack_var gamma))) + ~aft:(item bool (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.mem_map)] + (); + replacement + ~fresh:[Cmp alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef: + (item + (var alpha) + (item (map (var alpha) (var beta)) (stack_var gamma))) + ~aft:(item (option (var beta)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.get_map)] + (); + (* lists *) + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[gamma] + ~bef:(stack_var gamma) + ~aft:(item (list (var alpha)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.nil)] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[gamma] + ~bef:(item (var alpha) (item (list (var alpha)) (stack_var gamma))) + ~aft:(item (list (var alpha)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.cons)] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[gamma] + ~bef:(item (list (var alpha)) (stack_var gamma)) + ~aft:(stack_var gamma) + ~replacement: + [Context_blind (fun () -> M.Instructions.(iter_list [hole]))] + (); + replacement + ~fresh:[Plain alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (list (var alpha)) (stack_var gamma)) + ~aft:(item (list (var beta)) (stack_var gamma)) + ~replacement: + [Context_blind (fun () -> M.Instructions.(map_list [hole]))] + (); + (* sizes *) + replacement + ~fresh:[Cmp alpha] + ~fresh_stack:[gamma] + ~bef:(item (set (var alpha)) (stack_var gamma)) + ~aft:(item nat (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.size_set)] + (); + replacement + ~fresh:[Cmp alpha; Plain beta] + ~fresh_stack:[gamma] + ~bef:(item (map (var alpha) (var beta)) (stack_var gamma)) + ~aft:(item nat (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.size_map)] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[gamma] + ~bef:(item (list (var alpha)) (stack_var gamma)) + ~aft:(item nat (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.size_list)] + (); + replacement + ~fresh:[] + ~fresh_stack:[gamma] + ~bef:(item string (stack_var gamma)) + ~aft:(item nat (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.size_string)] + (); + replacement + ~fresh:[] + ~fresh_stack:[gamma] + ~bef:(item bytes (stack_var gamma)) + ~aft:(item nat (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.size_bytes)] + (); + (* pack/unpack *) + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[gamma] + ~bef:(item (var alpha) (stack_var gamma)) + ~aft:(item bytes (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.pack)] + (); + replacement + ~fresh:[Plain alpha] + ~fresh_stack:[gamma] + ~bef:(item bytes (stack_var gamma)) + ~aft:(item (option (var alpha)) (stack_var gamma)) + ~replacement:[Context_blind (fun () -> M.Instructions.unpack)] + (); + ] + + let rules = + [ + replace_any_instr_by_hole; + {rule_patt = match_instr_hole; replacements = instructions}; + ] +end + +module Data_rewrite_leaves + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) = +struct + let hole_patt = + let open Patt in + prim_pred (fun prim -> prim = D_Hole) list_empty + + (* Matches a data hole *) + let match_hole = + let open Patt in + Pattern (focus hole_patt) + + (* Matches an integer literal *) + let match_int = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_Int) list_any)) + + (* Matches a list literal *) + let match_list = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_List) list_any)) + + (* Matches a set literal *) + let match_set = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_Set) list_any)) + + (* Matches a map literal *) + let match_map = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_Map) list_any)) + + (* Matches a timestamp literal *) + let match_timestamp = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_Timestamp) list_any)) + + (* Matches a mutez literal *) + let match_mutez = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_Mutez) list_any)) + + (* Matches a key_hash literal *) + let match_key_hash = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_Key_hash) list_any)) + + let match_int_mutez_timestamp_key_hash_key_or_none = + let open Patt in + Pattern + (focus + (prim_pred + (function + | A_Int | A_Nat | A_Mutez | A_Timestamp | A_Key_hash | A_Key + | D_None -> + true + | _ -> false) + list_any)) + + (* Matches an empty list, set or map literal *) + let match_empty_list_set_or_map = + let open Patt in + Pattern + (focus + (prim_pred + (function A_List | A_Set | A_Map -> true | _ -> false) + (list_cons (seq list_empty) list_empty))) + + (* Matches a pair containing two holes*) + let match_empty_pair = + let open Patt in + Pattern + (focus + (prim_pred + (fun prim -> prim = D_Pair) + (list_cons hole_patt (list_cons hole_patt list_empty)))) + + (* Match a Some, Left or Right containing a hole *) + let match_empty_some_left_or_right = + let open Patt in + Pattern + (focus + (prim_pred + (function D_Left | D_Right | D_Some -> true | _ -> false) + (list_cons hole_patt list_empty))) + + (* Match a None constructor *) + let match_none = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = D_None) list_empty)) + + (* rules *) + + (* fresh type variables *) + let alpha, beta = (-1, -2) + + let replacement ~fresh ~typ ~replacement = + { + type_constraint = Data_cnstrnt {cnstrnt = typ; fresh}; + replacement = [Context_blind (fun () -> replacement)]; + } + + let replacement_gen ~fresh ~typ ~replacement = + { + type_constraint = Data_cnstrnt {cnstrnt = typ; fresh}; + replacement = [Context_blind replacement]; + } + + let fill_in_hole rng_state = + let replace_by_singleton_list = + replacement + ~fresh:[alpha] + ~typ:Type.(list (var alpha)) + ~replacement:Mikhailsky.Data.(list [hole]) + in + let replace_by_empty_pair = + replacement + ~fresh:[alpha; beta] + ~typ:Type.(pair (var alpha) (var beta)) + ~replacement:Mikhailsky.Data.(pair hole hole) + in + let replace_by_singleton_set = + replacement + ~fresh:[alpha] + ~typ:Type.(set (var alpha)) + ~replacement:Mikhailsky.Data.(set [hole]) + in + let replace_by_singleton_map = + replacement + ~fresh:[alpha; beta] + ~typ:Type.(map (var alpha) (var beta)) + ~replacement:Mikhailsky.Data.(map [map_elt hole hole]) + in + let replace_by_random_int rng_state = + let type_constraint = Data_cnstrnt {cnstrnt = Type.int; fresh = []} in + let replacement = + Context_blind + (fun () -> + Mikhailsky.Data.big_integer + (Protocol.Script_int.to_zint (Michelson_base.int rng_state))) + in + {type_constraint; replacement = [replacement]} + in + let replace_by_left = + replacement + ~fresh:[alpha; beta] + ~typ:Type.(or_ (var alpha) (var beta)) + ~replacement:Mikhailsky.Data.(left hole) + in + let replace_by_right = + replacement + ~fresh:[alpha; beta] + ~typ:Type.(or_ (var alpha) (var beta)) + ~replacement:Mikhailsky.Data.(right hole) + in + let replace_by_some = + replacement + ~fresh:[alpha] + ~typ:Type.(option (var alpha)) + ~replacement:Mikhailsky.Data.(some hole) + in + let replace_by_none = + replacement + ~fresh:[alpha] + ~typ:Type.(option (var alpha)) + ~replacement:Mikhailsky.Data.none + in + let replace_by_mutez rng_state = + replacement_gen ~fresh:[] ~typ:Type.mutez ~replacement:(fun () -> + Mikhailsky.Data.mutez (Michelson_base.tez rng_state)) + in + let replace_by_key_hash rng_state = + replacement_gen ~fresh:[] ~typ:Type.key_hash ~replacement:(fun () -> + Mikhailsky.Data.key_hash (Crypto_samplers.pkh rng_state)) + in + let replace_by_key rng_state = + replacement_gen ~fresh:[] ~typ:Type.key ~replacement:(fun () -> + Mikhailsky.Data.key (Crypto_samplers.pk rng_state)) + in + { + rule_patt = match_hole; + replacements = + [ + replace_by_singleton_list; + replace_by_empty_pair; + replace_by_singleton_set; + replace_by_singleton_map; + replace_by_random_int rng_state; + replace_by_left; + replace_by_right; + replace_by_some; + replace_by_none; + replace_by_mutez rng_state; + replace_by_key_hash rng_state; + replace_by_key rng_state; + ]; + } + + let kill_empty_pair = + { + rule_patt = match_empty_pair; + replacements = + [ + { + type_constraint = No_cnstrnt; + replacement = [Context_blind (fun () -> Mikhailsky.Data.hole)]; + }; + ]; + } + + let kill_int_mutez_timestamp_key_hash_none = + { + rule_patt = match_int_mutez_timestamp_key_hash_key_or_none; + replacements = + [ + { + type_constraint = No_cnstrnt; + replacement = [Context_blind (fun () -> Mikhailsky.Data.hole)]; + }; + ]; + } + + let kill_empty_list_set_or_map = + { + rule_patt = match_empty_list_set_or_map; + replacements = + [ + { + type_constraint = No_cnstrnt; + replacement = [Context_blind (fun () -> Mikhailsky.Data.hole)]; + }; + ]; + } + + let kill_empty_some_left_or_right = + { + rule_patt = match_empty_some_left_or_right; + replacements = + [ + { + type_constraint = No_cnstrnt; + replacement = [Context_blind (fun () -> Mikhailsky.Data.hole)]; + }; + ]; + } + + let modify_set = + let grow_ungrow_set = + { + type_constraint = No_cnstrnt; + replacement = + [ + Context_aware + (fun set -> + match set with + | Micheline.Prim (_, A_Set, [Micheline.Seq (_, elements)], _) -> + Mikhailsky.Data.(set (hole :: elements)) + | _ -> assert false); + Context_aware + (fun set -> + match set with + | Micheline.Prim (_, A_Set, [Micheline.Seq (_, elements)], _) + -> ( + match elements with + | [] -> Mikhailsky.Data.hole + | _ :: tl -> Mikhailsky.Data.set tl) + | _ -> assert false); + ]; + } + in + {rule_patt = match_set; replacements = [grow_ungrow_set]} + + let modify_map = + let grow_ungrow_map = + { + type_constraint = No_cnstrnt; + replacement = + [ + Context_aware + (fun set -> + match set with + | Micheline.Prim (_, A_Map, [Micheline.Seq (_, elements)], _) -> + Mikhailsky.Data.(map (map_elt hole hole :: elements)) + | _ -> assert false); + Context_aware + (fun set -> + match set with + | Micheline.Prim (_, A_Map, [Micheline.Seq (_, elements)], _) + -> ( + match elements with + | [] -> Mikhailsky.Data.hole + | _ :: tl -> Mikhailsky.Data.map tl) + | _ -> assert false); + ]; + } + in + {rule_patt = match_map; replacements = [grow_ungrow_map]} + + let modify_list = + let grow_ungrow_list = + { + type_constraint = No_cnstrnt; + replacement = + [ + Context_aware + (fun list -> + match list with + | Micheline.Prim (_, A_List, [Micheline.Seq (_, terms)], _) -> + Mikhailsky.Data.(list (hole :: terms)) + | _ -> assert false); + Context_aware + (fun list -> + match list with + | Micheline.Prim (_, A_List, [Micheline.Seq (_, terms)], _) -> ( + match terms with + | [] -> Mikhailsky.Data.hole + | _ :: tl -> Mikhailsky.Data.list tl) + | _ -> assert false); + ]; + } + in + {rule_patt = match_list; replacements = [grow_ungrow_list]} + + let rules rng_state = + [ + fill_in_hole rng_state; + kill_empty_pair; + kill_empty_list_set_or_map; + kill_empty_some_left_or_right; + kill_int_mutez_timestamp_key_hash_none; + modify_list; + modify_set; + modify_map; + ] +end + +module Data + (Michelson_base : Michelson_samplers_base.S) + (Crypto_samplers : Crypto_samplers.Finite_key_pool_S) = +struct + let match_data_node = + let open Patt in + Pattern + (focus + (prim_pred + (function + | Mikhailsky_prim.D_Elt | D_Hole -> false + | D_False | D_Left | D_None | D_Pair | D_Right | D_Some | D_True + | D_Unit | A_Int | A_Nat | A_Set | A_List | A_Map | A_Key_hash + | A_Mutez | A_Timestamp | A_Key -> + true + | _ -> false) + list_any)) + + let match_list = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = A_List) list_any)) + + let match_data_hole = + let open Patt in + Pattern (focus (prim_pred (fun prim -> prim = D_Hole) list_any)) + + let replace_by_hole = + let replace_by_hole = + { + type_constraint = No_cnstrnt; + replacement = [Context_blind (fun () -> Mikhailsky.Data.hole)]; + } + in + {rule_patt = match_data_node; replacements = [replace_by_hole]} + + let pack_root = + let replacement = + [ + Context_aware (fun node -> Mikhailsky.Data.list [node]); + Context_aware (fun node -> Mikhailsky.Data.(pair node hole)); + Context_aware (fun node -> Mikhailsky.Data.(pair hole node)); + ] + in + let guarded_replacements = [{type_constraint = No_cnstrnt; replacement}] in + {rule_patt = Root; replacements = guarded_replacements} + + module Data_rewrite_leaves_rules = + Data_rewrite_leaves (Michelson_base) (Crypto_samplers) + + let rules rng_state = + [ + Data_rewrite_leaves_rules.fill_in_hole rng_state; + replace_by_hole; + Data_rewrite_leaves_rules.modify_list; + Data_rewrite_leaves_rules.modify_map; + Data_rewrite_leaves_rules.modify_set; + ] +end diff --git a/src/proto_020_PsParisC/lib_benchmark/sampling_helpers.ml b/src/proto_020_PsParisC/lib_benchmark/sampling_helpers.ml new file mode 100644 index 000000000000..8b36fc09e0bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/sampling_helpers.ml @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* ------------------------------------------------------------------------- *) + +(* TODO: use Statz's def. of sampler once upstreamed. *) +type 'a sampler = Random.State.t -> 'a + +module M = struct + let ( let* ) : 'a sampler -> ('a -> 'b sampler) -> 'b sampler = + fun sampler f rng_state -> + let x = sampler rng_state in + f x rng_state + [@@inline] + + let bind = ( let* ) + + let return x _ = x +end diff --git a/src/proto_020_PsParisC/lib_benchmark/state_space.ml b/src/proto_020_PsParisC/lib_benchmark/state_space.ml new file mode 100644 index 000000000000..60d14970e610 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/state_space.ml @@ -0,0 +1,78 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* The state of rewriting is a typed term *) +type t = {typing : Inference.state lazy_t; term : Mikhailsky.node} + +let compare (term1 : t) (term2 : t) = + let tag1 = Mikhailsky.tag term1.term in + let tag2 = Mikhailsky.tag term2.term in + if tag1 < tag2 then -1 else if tag1 > tag2 then 1 else 0 + +let equal (term1 : t) (term2 : t) = + let tag1 = Mikhailsky.tag term1.term in + let tag2 = Mikhailsky.tag term2.term in + tag1 = tag2 + +let hash (t : t) = Mikhailsky.hash t.term + +type node_statistics = { + mutable size : int; + mutable bytes : int; + mutable holes : int; + mutable depth : int; +} + +let pp_statistics fmtr stats = + Format.fprintf + fmtr + "{ size = %d ; bytes = %d ; holes = %d }" + stats.size + stats.bytes + stats.holes + +let rec statistics stats depth (n : Mikhailsky.node) = + stats.size <- stats.size + 1 ; + stats.depth <- max depth stats.depth ; + match n with + | Micheline.Int (_, z) -> stats.bytes <- stats.bytes + (Z.numbits z / 8) + | Micheline.String (_, s) -> stats.bytes <- stats.bytes + String.length s + | Micheline.Bytes (_, b) -> stats.bytes <- stats.bytes + Bytes.length b + | Micheline.Prim (_, Mikhailsky_prim.I_Hole, _, _) + | Micheline.Prim (_, Mikhailsky_prim.D_Hole, _, _) -> + stats.holes <- stats.holes + 1 + | Micheline.Prim (_, _, subterms, _) | Micheline.Seq (_, subterms) -> + List.iter (statistics stats (depth + 1)) subterms + +let statistics {term; _} = + let stats = {size = 0; bytes = 0; holes = 0; depth = 0} in + statistics stats 0 term ; + stats + +let pp fmtr (state : t) = + Format.fprintf fmtr "current term:@." ; + Format.fprintf fmtr "%a@." Mikhailsky.pp state.term ; + Format.fprintf fmtr "stats:@." ; + Format.fprintf fmtr "%a:@." pp_statistics (statistics state) diff --git a/src/proto_020_PsParisC/lib_benchmark/test/dune b/src/proto_020_PsParisC/lib_benchmark/test/dune new file mode 100644 index 000000000000..c679d23d8cbf --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/test/dune @@ -0,0 +1,39 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executables + (names + test_sampling_data + test_sampling_code + test_autocompletion + test_distribution) + (libraries + octez-libs.base + octez-libs.micheline + tezos-micheline-rewriting + tezos-protocol-019-PtParisB.protocol + tezos-benchmark + tezos-benchmark-type-inference-019-PtParisB + tezos-benchmark-019-PtParisB + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.error-monad + prbnmcn-stats) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (flags + (:standard) + -open Tezos_micheline + -open Tezos_protocol_019_PtParisB + -open Tezos_benchmark + -open Tezos_benchmark_type_inference_019_PtParisB + -open Tezos_benchmark_019_PtParisB + -open Tezos_019_PtParisB_test_helpers)) + +(rule + (alias runtest_micheline_rewriting_data) + (action (run %{exe:test_sampling_data.exe} 1234))) + +(rule + (alias runtest_micheline_rewriting_code) + (action (run %{exe:test_sampling_code.exe} 1234))) diff --git a/src/proto_020_PsParisC/lib_benchmark/test/test_autocompletion.ml b/src/proto_020_PsParisC/lib_benchmark/test/test_autocompletion.ml new file mode 100644 index 000000000000..c2f3e6c74295 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/test/test_autocompletion.ml @@ -0,0 +1,120 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let rng_state = Random.State.make [|42; 987897; 54120|] + +module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct + let algo = `Default + + let size = 16 +end) + +module Michelson_base_samplers = Michelson_samplers_base.Make (struct + let parameters = + let size = {Base_samplers.min = 4; max = 32} in + { + Michelson_samplers_base.int_size = size; + string_size = size; + bytes_size = size; + } +end) + +module Autocomp = Autocomp.Make (Michelson_base_samplers) (Crypto_samplers) + +let () = Format.eprintf "===============================@.%!" + +let () = Format.eprintf "Testing dummy program generator@.%!" + +let run x = x rng_state (Inference.M.empty ()) + +let invent_term bef aft = + let term, _state = run (Autocomp.invent_term bef aft) in + Mikhailsky.seq term + +let invent_term bef aft = + Format.eprintf + "requested type: %a => %a@." + Type.Stack.pp + bef + Type.Stack.pp + aft ; + let term = invent_term bef aft in + let bef', aft' = Inference.infer term in + Format.eprintf + "generated type: %a => %a@." + Type.Stack.pp + bef' + Type.Stack.pp + aft' ; + Format.eprintf "%a@." Mikhailsky.pp term + +module T = Type + +let bef = T.(item unit (item unit (item unit empty))) + +let aft = T.(item int (item unit (item (pair nat nat) empty))) + +let () = invent_term bef aft + +let () = Format.eprintf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@.%!" + +let () = invent_term bef aft + +let () = Format.eprintf "===============================@.%!" + +let () = Format.eprintf "Testing completion@.%!" + +let complete term = + Format.eprintf "term: %a@." Mikhailsky.pp term ; + let (bef, aft), state = Inference.infer_with_state term in + Format.eprintf "Inferred type: %a => %a@." Type.Stack.pp bef Type.Stack.pp aft ; + let term, (bef', aft'), _state = + Autocomp.complete_code state term rng_state + in + Format.eprintf "completed: %a@." Mikhailsky.pp term ; + Format.eprintf + "Inferred type after generation: %a => %a@." + Type.Stack.pp + bef' + Type.Stack.pp + aft' ; + let node = + Micheline.strip_locations @@ Mikhailsky_to_michelson.convert term state + in + let bef' = Type_helpers.stack_type_to_michelson_type_list bef' in + Test_helpers.typecheck_by_tezos bef' node + +open Mikhailsky +open Instructions + +let push_int = Instructions.push int_ty (Data.big_integer (Z.of_int 100)) + +let add_ii = Instructions.(add Mikhailsky.int_ty Mikhailsky.int_ty) + +let () = complete (lambda [if_left right (dip (seq [push_int; hole]))]) + +let () = Format.eprintf "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@.%!" + +let () = complete (seq [push_int; add_ii; lambda [dip (seq [dup; dip hole])]]) diff --git a/src/proto_020_PsParisC/lib_benchmark/test/test_distribution.ml b/src/proto_020_PsParisC/lib_benchmark/test/test_distribution.ml new file mode 100644 index 000000000000..c067d74dec09 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/test/test_distribution.ml @@ -0,0 +1,157 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Michelson_samplers +open Protocol +open Internal_for_tests + +let pp_type_name fmtr (t : type_name) = + Format.pp_print_string fmtr + @@ + match t with + | `TString -> "string" + | `TNat -> "nat" + | `TPair -> "pair" + | `TKey -> "key" + | `TLambda -> "lambda" + | `TOr -> "or" + | `TOperation -> "operation" + | `TOption -> "option" + | `TSapling_state -> "sapling_state" + | `TBytes -> "bytes" + | `TChain_id -> "chain_id" + | `TBool -> "bool" + | `TBls12_381_g2 -> "bls12_381_g2" + | `TTicket -> "ticket" + | `TMap -> "map" + | `TAddress -> "address" + | `TContract -> "contract" + | `TBls12_381_fr -> "bls12_381_fr" + | `TSapling_transaction -> "sapling_transaction" + | `TSapling_transaction_deprecated -> "sapling_transaction_deprecated" + | `TTimestamp -> "timestamp" + | `TKey_hash -> "key_hash" + | `TBig_map -> "big_map" + | `TSet -> "set" + | `TBls12_381_g1 -> "bls12_381_g1" + | `TList -> "list" + | `TMutez -> "mutez" + | `TSignature -> "signature" + | `TUnit -> "unit" + | `TInt -> "int" + +module Type_name = struct + type t = type_name + + let equal (x : t) (y : t) = x = y + + let pp = pp_type_name + + let hash = Stdlib.Hashtbl.hash +end + +module Type_name_hashtbl = Stdlib.Hashtbl.Make (Type_name) + +let rec tnames_of_type : + type a ac. (a, ac) Script_typed_ir.ty -> type_name list -> type_name list = + fun t acc -> + match t with + | Script_typed_ir.Unit_t -> `TUnit :: acc + | Script_typed_ir.Int_t -> `TInt :: acc + | Script_typed_ir.Nat_t -> `TNat :: acc + | Script_typed_ir.Signature_t -> `TSignature :: acc + | Script_typed_ir.String_t -> `TString :: acc + | Script_typed_ir.Bytes_t -> `TBytes :: acc + | Script_typed_ir.Mutez_t -> `TMutez :: acc + | Script_typed_ir.Key_hash_t -> `TKey_hash :: acc + | Script_typed_ir.Key_t -> `TKey :: acc + | Script_typed_ir.Timestamp_t -> `TTimestamp :: acc + | Script_typed_ir.Address_t -> `TAddress :: acc + | Script_typed_ir.Bool_t -> `TBool :: acc + | Script_typed_ir.Pair_t (lty, rty, _, _) -> + tnames_of_type lty (tnames_of_type rty (`TPair :: acc)) + | Script_typed_ir.Or_t (lty, rty, _, _) -> + tnames_of_type lty (tnames_of_type rty (`TOr :: acc)) + | Script_typed_ir.Lambda_t (dom, range, _) -> + tnames_of_type dom (tnames_of_type range (`TLambda :: acc)) + | Script_typed_ir.Option_t (ty, _, _) -> tnames_of_type ty (`TOption :: acc) + | Script_typed_ir.List_t (ty, _) -> tnames_of_type ty (`TList :: acc) + | Script_typed_ir.Set_t (ty, _) -> tnames_of_type ty (`TSet :: acc) + | Script_typed_ir.Map_t (kty, vty, _) -> + tnames_of_type kty (tnames_of_type vty (`TMap :: acc)) + | Script_typed_ir.Big_map_t (kty, vty, _) -> + tnames_of_type kty (tnames_of_type vty (`TBig_map :: acc)) + | Script_typed_ir.Contract_t (ty, _) -> tnames_of_type ty (`TContract :: acc) + | Script_typed_ir.Sapling_transaction_t _ -> `TSapling_transaction :: acc + | Script_typed_ir.Sapling_transaction_deprecated_t _ -> + `TSapling_transaction_deprecated :: acc + | Script_typed_ir.Sapling_state_t _ -> `TSapling_state :: acc + | Script_typed_ir.Operation_t -> `TOperation :: acc + | Script_typed_ir.Chain_id_t -> `TChain_id :: acc + | Script_typed_ir.Never_t -> assert false + | Script_typed_ir.Bls12_381_g1_t -> `TBls12_381_g1 :: acc + | Script_typed_ir.Bls12_381_g2_t -> `TBls12_381_g2 :: acc + | Script_typed_ir.Bls12_381_fr_t -> `TBls12_381_fr :: acc + | Script_typed_ir.Ticket_t (ty, _) -> tnames_of_type ty (`TTicket :: acc) + | Script_typed_ir.Chest_key_t -> assert false + | Script_typed_ir.Chest_t -> assert false + +module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct + let algo = `Default + + let size = 16 +end) + +module Sampler = + Michelson_samplers.Make + (struct + let parameters = + { + base_parameters = + { + Michelson_samplers_base.int_size = {min = 8; max = 32}; + string_size = {min = 8; max = 128}; + bytes_size = {min = 8; max = 128}; + }; + list_size = {min = 10; max = 1000}; + set_size = {min = 10; max = 1000}; + map_size = {min = 10; max = 1000}; + } + end) + (Crypto_samplers) + +open Stats + +let tnames_dist : type_name list -> type_name Fin.Float.prb = + fun tnames -> + Emp.of_raw_data (Array.of_list tnames) + |> Fin.Float.counts_of_empirical (module Type_name_hashtbl) + |> Fin.Float.normalize + +let rec sample nsamples acc = + let open Sampling_helpers.M in + if nsamples = 0 then return acc + else + let* size = + Base_samplers.(sample_in_interval ~range:{min = 1; max = 1000}) + in + let* (Ex_ty ty) = Sampler.Random_type.m_type ~size () in + let* acc = sample (nsamples - 1) acc in + return (tnames_of_type ty acc) + +let sample nsamples = sample nsamples [] + +let dist nsamples = + let open Sampling_helpers.M in + let* samples = sample nsamples in + return (tnames_dist samples) + +let () = + Format.printf + "stats:@.%a@." + (Fin.Float.pp_fin_mes Type_name.pp) + (Fin.Float.as_measure (dist 500 (Random.State.make [|0x1337; 0x533D|]))) diff --git a/src/proto_020_PsParisC/lib_benchmark/test/test_helpers.ml b/src/proto_020_PsParisC/lib_benchmark/test/test_helpers.ml new file mode 100644 index 000000000000..e3d49fe0ec1c --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/test/test_helpers.ml @@ -0,0 +1,97 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let rng_state = Random.State.make [|42; 987897; 54120|] + +let print_script_expr fmtr (expr : Protocol.Script_repr.expr) = + Micheline_printer.print_expr + fmtr + (Micheline_printer.printable + Protocol.Michelson_v1_primitives.string_of_prim + expr) + +let print_script_expr_list fmtr (exprs : Protocol.Script_repr.expr list) = + Format.pp_print_list + ~pp_sep:(fun fmtr () -> Format.fprintf fmtr " :: ") + print_script_expr + fmtr + exprs + +let typecheck_by_tezos = + let open Lwt_result_wrap_syntax in + let context_init_memory ~rng_state = + let* block, _accounts = + Context.init_n + ~rng_state + ~bootstrap_balances: + [ + 4_000_000_000_000L; + 4_000_000_000_000L; + 4_000_000_000_000L; + 4_000_000_000_000L; + 4_000_000_000_000L; + ] + 5 + () + in + let* csts = Context.get_constants (B block) in + let minimal_block_delay = + Protocol.Alpha_context.Period.to_seconds + csts.parametric.minimal_block_delay + in + let* vs = + Incremental.begin_construction + ~timestamp: + (Tezos_base.Time.Protocol.add + block.header.shell.timestamp + minimal_block_delay) + block + in + let ctxt = Incremental.alpha_ctxt vs in + (* Required for eg Create_contract *) + return + @@ Protocol.Alpha_context.Origination_nonce.init + ctxt + Tezos_crypto.Hashed.Operation_hash.zero + in + fun bef node -> + Stdlib.Result.get_ok + (Lwt_main.run + (let* ctxt = context_init_memory ~rng_state in + let (Protocol.Script_ir_translator.Ex_stack_ty bef) = + Type_helpers.michelson_type_list_to_ex_stack_ty bef ctxt + in + let*@ (_ : + _ Protocol.Script_ir_translator.judgement + * Protocol.Alpha_context.t) = + Protocol.Script_ir_translator.parse_instr + Protocol.Script_tc_context.data + ctxt + ~elab_conf: + (Protocol.Script_ir_translator_config.make ~legacy:false ()) + (Micheline.root node) + bef + in + return_unit)) diff --git a/src/proto_020_PsParisC/lib_benchmark/test/test_sampling_code.ml b/src/proto_020_PsParisC/lib_benchmark/test/test_sampling_code.ml new file mode 100644 index 000000000000..e5e8edf378d5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/test/test_sampling_code.ml @@ -0,0 +1,96 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Input parameter parsing *) + +let verbose = + if Array.length Sys.argv < 2 then ( + Format.eprintf "Executable expects random seed on input\n%!" ; + exit 1) + else + (Random.init (int_of_string Sys.argv.(1)) ; + List.exists (( = ) "-v")) + (Array.to_list Sys.argv) + +(* ------------------------------------------------------------------------- *) +(* Base sampler parameters *) + +let state = Random.State.make [|42; 987897; 54120|] + +module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct + let algo = `Default + + let size = 16 +end) + +module Michelson_base_samplers = Michelson_samplers_base.Make (struct + let parameters = + let size = {Base_samplers.min = 4; max = 32} in + { + Michelson_samplers_base.int_size = size; + string_size = size; + bytes_size = size; + } +end) + +(* ------------------------------------------------------------------------- *) +(* MCMC instantiation *) + +module Code = + Michelson_mcmc_samplers.Make_code_sampler + (Michelson_base_samplers) + (Crypto_samplers) + (struct + let rng_state = state + + let target_size = 500 + + let verbosity = if verbose then `Trace else `Silent + end) + +let start = Unix.gettimeofday () + +let generator = Code.generator ~burn_in:(500 * 7) state + +let stop = Unix.gettimeofday () + +let () = Format.printf "Burn in time: %f seconds@." (stop -. start) + +let _ = + for i = 1 to 1000 do + let Michelson_mcmc_samplers.{term = michelson; bef; aft} = + generator state + in + Test_helpers.typecheck_by_tezos bef michelson ; + if verbose then ( + Format.eprintf "result %d/1000:@." i ; + Format.eprintf + "type: %a => %a@." + Test_helpers.print_script_expr_list + bef + Test_helpers.print_script_expr_list + aft ; + Format.eprintf "%a@." Test_helpers.print_script_expr michelson) + done diff --git a/src/proto_020_PsParisC/lib_benchmark/test/test_sampling_data.ml b/src/proto_020_PsParisC/lib_benchmark/test/test_sampling_data.ml new file mode 100644 index 000000000000..fb67a046d1ef --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/test/test_sampling_data.ml @@ -0,0 +1,85 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Input parameter parsing *) + +let verbose = + if Array.length Sys.argv < 2 then ( + Format.eprintf "Executable expects random seed on input\n%!" ; + exit 1) + else + (Random.init (int_of_string Sys.argv.(1)) ; + List.exists (( = ) "-v")) + (Array.to_list Sys.argv) + +(* ------------------------------------------------------------------------- *) +(* MCMC instantiation *) + +let state = Random.State.make [|42; 987897; 54120|] + +module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct + let algo = `Default + + let size = 16 +end) + +module Michelson_base_samplers = Michelson_samplers_base.Make (struct + let parameters = + let size = {Base_samplers.min = 4; max = 32} in + { + Michelson_samplers_base.int_size = size; + string_size = size; + bytes_size = size; + } +end) + +module Data = + Michelson_mcmc_samplers.Make_data_sampler + (Michelson_base_samplers) + (Crypto_samplers) + (struct + let rng_state = state + + let target_size = 500 + + let verbosity = if verbose then `Trace else `Silent + end) + +let start = Unix.gettimeofday () + +let generator = Data.generator ~burn_in:(200 * 7) state + +let stop = Unix.gettimeofday () + +let () = Format.printf "Burn in time: %f seconds@." (stop -. start) + +let _ = + for _i = 0 to 1000 do + let Michelson_mcmc_samplers.{term = michelson; typ} = generator state in + if verbose then ( + Format.eprintf "result:@." ; + Format.eprintf "type: %a@." Test_helpers.print_script_expr typ ; + Format.eprintf "%a@." Test_helpers.print_script_expr michelson) + done diff --git a/src/proto_020_PsParisC/lib_benchmark/type_helpers.ml b/src/proto_020_PsParisC/lib_benchmark/type_helpers.ml new file mode 100644 index 000000000000..989ee7782901 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/type_helpers.ml @@ -0,0 +1,88 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Type conversion helpers *) + +open Protocol + +exception Type_helpers_error of string + +let helpers_error msg = raise (Type_helpers_error msg) + +(* Convert a Micheline-encoded type to its internal GADT format. *) +let michelson_type_to_ex_ty (typ : Alpha_context.Script.expr) + (ctxt : Alpha_context.t) = + Script_ir_translator.parse_ty + ctxt + ~legacy:false + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:false + ~allow_ticket:false + (Micheline.root typ) + |> Environment.wrap_tzresult + |> function + | Ok (ex_ty, _ctxt) -> ex_ty + | Error errs -> + let msg = + Format.asprintf + "Michelson_generation.michelson_type_to_ex_ty (%a)" + Error_monad.pp_print_trace + errs + in + helpers_error msg + +(* Convert a list of Micheline-encoded Michelson types to the + internal GADT format. *) +let rec michelson_type_list_to_ex_stack_ty + (stack_ty : Alpha_context.Script.expr list) ctxt = + let open Script_ir_translator in + let open Script_typed_ir in + match stack_ty with + | [] -> Ex_stack_ty Bot_t + | hd :: tl -> ( + let ex_ty = michelson_type_to_ex_ty hd ctxt in + match ex_ty with + | Ex_ty ty -> ( + let ex_stack_ty = michelson_type_list_to_ex_stack_ty tl ctxt in + match ex_stack_ty with + | Ex_stack_ty tl -> Ex_stack_ty (Item_t (ty, tl)))) + +let base_type_to_michelson_type (typ : Type.Base.t) = + let typ = Mikhailsky.map_var (fun _ -> Mikhailsky.unit_ty) typ in + Mikhailsky.to_michelson typ + +(* Convert a Mikhailsky stack to a list of Micheline-encoded types *) +let rec stack_type_to_michelson_type_list (typ : Type.Stack.t) = + let node = typ.node in + match node with + | Type.Stack.Stack_var_t _ -> + helpers_error "stack_type_to_michelson_type_list: bug found" + | Type.Stack.Empty_t -> [] + | Type.Stack.Item_t (ty, tl) -> + base_type_to_michelson_type ty :: stack_type_to_michelson_type_list tl + +let base_type_to_ex_ty ty = + michelson_type_to_ex_ty (base_type_to_michelson_type ty) diff --git a/src/proto_020_PsParisC/lib_benchmark/type_helpers.mli b/src/proto_020_PsParisC/lib_benchmark/type_helpers.mli new file mode 100644 index 000000000000..0cf310d3afcf --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmark/type_helpers.mli @@ -0,0 +1,57 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Type conversion helpers *) + +open Protocol + +(** Exception raised in case an error occurs in this module. *) +exception Type_helpers_error of string + +(** [michelson_type_list_to_ex_stack_ty] converts a list of types in + Micheline form to a stack type in IR form. + + @raise Type_helpers_error if parsing the Michelson type fails. + *) +val michelson_type_list_to_ex_stack_ty : + Alpha_context.Script.expr list -> + Alpha_context.t -> + Script_ir_translator.ex_stack_ty + +(** [michelson_type_to_ex_ty ty ctxt] parses the type [ty]. + + @raise Type_helpers_error if an error arises during parsing. *) +val michelson_type_to_ex_ty : + Alpha_context.Script.expr -> Alpha_context.t -> Script_typed_ir.ex_ty + +(** [stack_type_to_michelson_type_list] converts a Mikhailsky stack type + to a stack represented as a list of Micheline expressions, each + element denoting a type on the stack type. + + @raise Type_helpers_error if the stack type contains variables. *) +val stack_type_to_michelson_type_list : Type.Stack.t -> Script_repr.expr list + +(** [base_type_to_ex_ty] converts a Mikhailsky type to a Michelson one. *) +val base_type_to_ex_ty : Type.Base.t -> Alpha_context.t -> Script_typed_ir.ex_ty diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/apply_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/apply_benchmarks.ml new file mode 100644 index 000000000000..1e35f214a934 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/apply_benchmarks.ml @@ -0,0 +1,151 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_benchmark +open Benchmarks_proto + +let ns = Namespace.make Registration.ns "apply" + +let fv s = Free_variable.of_namespace (ns s) + +let initial_balance = 4_000_000_000_000L + +let make_context ~rng_state = + let open Lwt_result_syntax in + let* block, (_, src, dst) = + Context.init3 + ~rng_state + ~bootstrap_balances:[initial_balance; initial_balance; initial_balance] + () + in + let* csts = Context.get_constants (B block) in + let minimal_block_delay = + Protocol.Alpha_context.Period.to_seconds csts.parametric.minimal_block_delay + in + let* vs = + Incremental.begin_construction + ~timestamp: + (Time.Protocol.add block.header.shell.timestamp minimal_block_delay) + block + in + let ctxt = Incremental.alpha_ctxt vs in + let ctxt = + (* Required for eg Create_contract *) + Protocol.Alpha_context.Origination_nonce.init + ctxt + Tezos_crypto.Hashed.Operation_hash.zero + in + return (ctxt, src, dst) + +(* This benchmark is introduced for !7761 and #4788. Its result is not used in the protocol + therefore we do not need to perform it regularly. +*) +module Take_fees_benchmark = struct + let name = ns "Take_fees" + + let info = "Benchmark for take_fees" + + let module_filename = __FILE__ + + let purpose = + Benchmark.Other_purpose "Measuring the time spent for Apply.take_fees" + + let group = Benchmark.Standalone + + let tags = ["apply"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = {batch_length : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {batch_length} -> batch_length) + (fun batch_length -> {batch_length}) + (obj1 (req "batch_length" int31)) + + let workload_to_vector {batch_length} = + Sparse_vec.String.of_list [("batch_length", float_of_int batch_length)] + + let model = + Model.make ~conv:(fun {batch_length} -> (batch_length, ())) Model.affine + + let create_benchmark ~rng_state _conf = + let open Annotated_manager_operation in + let open Alpha_context in + let open Lwt_result_syntax in + let batch_length = + Base_samplers.sample_in_interval ~range:{min = 1; max = 100} rng_state + in + let workload = {batch_length} in + let closure_result = + Lwt_main.run + (let* ctxt, src, dest = make_context ~rng_state in + let* parameters = Client_proto_context.parse_arg_transfer None in + let transaction = + Transaction + { + amount = Tez.one; + parameters; + entrypoint = Entrypoint_repr.default; + destination = dest; + } + in + let pkh = match src with Implicit pkh -> pkh | _ -> assert false in + let manager_info = + Manager_info + { + source = Some pkh; + fee = Limit.known Tez.one; + gas_limit = Limit.known (Gas.Arith.integral_exn (Z.of_int 2000)); + storage_limit = Limit.known (Z.of_int 10); + counter = Some (Manager_counter.Internal_for_tests.of_int 0); + operation = transaction; + } + in + let tr = Annotated_manager_operation manager_info in + let transaction_list = List.repeat batch_length tr in + let (Manager_list annotated_list) = manager_of_list transaction_list in + let* batch = Lwt.return (manager_list_from_annotated annotated_list) in + let closure () = + Protocol.Apply.Internal_for_benchmark.take_fees ctxt batch + in + return closure) + in + let closure = + match closure_result with + | Ok c -> c + | Error _ -> assert false (* TODO better error *) + in + Generator.Plain {workload; closure} +end + +let () = Benchmarks_proto.Registration.register (module Take_fees_benchmark) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.ml new file mode 100644 index 000000000000..da8f8ad556a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.ml @@ -0,0 +1,153 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Benchmark_base = Benchmark + +module Benchmark = struct + type group = Benchmark_base.group = Standalone | Group of string | Generic + + type purpose = Benchmark_base.purpose = + | Other_purpose of string + | Generate_code of string + + module type S = sig + val name : Namespace.t + + val info : string + + val module_filename : string + + val group : group + + val tags : string list + + type config + + val default_config : config + + val config_encoding : config Data_encoding.t + + type workload + + val workload_encoding : workload Data_encoding.t + + val workload_to_vector : workload -> Sparse_vec.String.t + + val model : name:Namespace.t -> workload Model.t + + val purpose : Benchmark_base.purpose + + val create_benchmark : + rng_state:Random.State.t -> config -> workload Generator.benchmark + end + + type t = (module S) +end + +module Registration = struct + let ns = Namespace.root + + let register ((module Bench) : Benchmark.t) = + let module B : Benchmark_base.S = struct + include Bench + + let models = + [ + ( (match Bench.group with + | Generic -> "*" + | Group g -> g + | Standalone -> Namespace.(cons Bench.name "model" |> to_string)), + Bench.model ~name ); + ] + + let create_benchmarks ~rng_state ~bench_num config = + List.repeat bench_num (fun () -> + Bench.create_benchmark ~rng_state config) + end in + Registration_helpers.register (module B) + + let register_simple_with_num ((module Bench) : Benchmark_base.simple_with_num) + = + let module B : Benchmark_base.Simple_with_num = struct + include Bench + + let tags = Tags.common :: tags + end in + Registration.register_simple_with_num (module B) + + let register_as_simple_with_num ~group (module B : Benchmark_base.S) = + let modules = + List.map + (fun (model_name, model) : (module Benchmark_base.Simple_with_num) -> + (module struct + include B + + let name = Namespace.cons name model_name + + let group = group + + let model = model + end)) + B.models + in + List.iter (fun x -> register_simple_with_num x) modules +end + +module Model = struct + include Model + + type 'workload t = 'workload Model.t + + let make ?takes_saturation_reprs ~name ~conv model = + make ?takes_saturation_reprs ~conv (model name) + + let unknown_const1 ?const name = + let ns s = Free_variable.of_namespace (Namespace.cons name s) in + let const = Option.value ~default:(ns "const") const in + unknown_const1 ~name ~const + + let affine ?intercept ?coeff name = + let ns s = Free_variable.of_namespace (Namespace.cons name s) in + let intercept = Option.value ~default:(ns "intercept") intercept in + let coeff = Option.value ~default:(ns "coeff") coeff in + affine ~name ~intercept ~coeff + + let logn ?coeff name = + let ns s = Free_variable.of_namespace (Namespace.cons name s) in + let coeff = Option.value ~default:(ns "coeff") coeff in + logn ~name ~coeff + + let nlogn ?intercept ?coeff name = + let ns s = Free_variable.of_namespace (Namespace.cons name s) in + let coeff = Option.value ~default:(ns "coeff") coeff in + let intercept = Option.value ~default:(ns "intercept") intercept in + nlogn ~name ~intercept ~coeff + + let linear ?coeff name = + let ns s = Free_variable.of_namespace (Namespace.cons name s) in + let coeff = Option.value ~default:(ns "coeff") coeff in + linear ~name ~coeff +end diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.mli b/src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.mli new file mode 100644 index 000000000000..e0ed328124ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/benchmarks_proto.mli @@ -0,0 +1,131 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Benchmark_base = Benchmark + +module Benchmark : sig + type group = Benchmark_base.group = Standalone | Group of string | Generic + + type purpose = Benchmark_base.purpose = + | Other_purpose of string + | Generate_code of string + + (** The module type of benchmarks, a simplification of {!Benchmark.S} used by + [registration_simple] below. *) + + module type S = sig + (** Name of the benchmark *) + val name : Namespace.t + + (** Description of the benchmark *) + val info : string + + (** Filename of the benchmark module *) + val module_filename : string + + (** Inference group of the benchmark *) + val group : group + + (** Tags of the benchmark *) + val tags : string list + + (** Configuration of the benchmark (eg sampling parameters, paths, etc) *) + type config + + (** Default configuration of the benchmark *) + val default_config : config + + (** Configuration encoding *) + val config_encoding : config Data_encoding.t + + (** Benchmark workload *) + type workload + + (** Workload encoding *) + val workload_encoding : workload Data_encoding.t + + (** Optional conversion to vector, for report generation purposes *) + val workload_to_vector : workload -> Sparse_vec.String.t + + (** Cost model *) + val model : name:Namespace.t -> workload Model.t + + (** Benchmark purpose. + The developer can submit an explanation as to what the benchmark is for when it's not generating code + (i.e. in the case of [Other_purpose]). *) + val purpose : Benchmark_base.purpose + + (** Creates a benchmark, ready to be run. + The benchmarks are thunked to prevent evaluating the workload until + needed. *) + val create_benchmark : + rng_state:Random.State.t -> config -> workload Generator.benchmark + end + + type t = (module S) +end + +module Registration : sig + val ns : Namespace.cons + + (** Registers a benchmark with a model, model names are uniformely generated + *) + val register : Benchmark.t -> unit + + val register_as_simple_with_num : + group:Benchmark.group -> Benchmark_base.t -> unit +end + +module Model : sig + open Model + + type 'workload t = 'workload Model.t + + val make : + ?takes_saturation_reprs:bool -> + name:Namespace.t -> + conv:('a -> 'b) -> + (Namespace.t -> 'b model) -> + 'a t + + val unknown_const1 : ?const:Free_variable.t -> Namespace.t -> unit model + + val affine : + ?intercept:Free_variable.t -> + ?coeff:Free_variable.t -> + Namespace.t -> + (int * unit) model + + val logn : ?coeff:Free_variable.t -> Namespace.t -> (int * unit) model + + val nlogn : + ?intercept:Free_variable.t -> + ?coeff:Free_variable.t -> + Namespace.t -> + (int * unit) model + + val linear : ?coeff:Free_variable.t -> Namespace.t -> (int * unit) model +end diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/cache_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/cache_benchmarks.ml new file mode 100644 index 000000000000..9706b5507681 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/cache_benchmarks.ml @@ -0,0 +1,204 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Benchmarks_proto + +let ns = Namespace.make Registration_helpers.ns "cache" + +let fv s = Free_variable.of_namespace (ns s) + +(** {2 [Alpha_context.Cache]-related benchmarks} *) + +let assert_ok_lwt x = + match Lwt_main.run x with Ok x -> x | Error _ -> assert false + +let assert_ok = function Ok x -> x | Error _ -> assert false + +module Admin = Alpha_context.Cache.Admin + +(** We can't construct a dummy cache client from outside the protocol. + We'll have to benchmark the {!Environment_cache} through the interface + exposed by {!Script_cache}. *) +module Cache = Script_cache + +(** {2 Constructing a dummy cached value} *) + +let make_context ~rng_state = + Execution_context.make ~rng_state () |> assert_ok_lwt |> fst + +let throwaway_context = + let rng_state = Random.State.make [|0x1337; 0x533D|] in + make_context ~rng_state + +let dummy_script : Cache.cached_contract = + let str = "{ parameter unit; storage unit; code FAILWITH }" in + let storage = + let parsed, _ = Michelson_v1_parser.parse_expression "Unit" in + Alpha_context.Script.lazy_expr parsed.expanded + in + let code = + let parsed, _ = Michelson_v1_parser.parse_expression ~check:false str in + Alpha_context.Script.lazy_expr parsed.expanded + in + let script = Alpha_context.Script.{code; storage} in + let ex_script, _ = + Script_ir_translator.parse_script + throwaway_context + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets_in_storage:false + ~allow_forged_lazy_storage_id_in_storage:false + script + |> assert_ok_lwt + in + (script, ex_script) + +(** {2 Creating dummy cache value identifiers.} *) + +(** Configuration shared among all cache benchmarks. *) +module Cache_shared_config = struct + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = {cache_cardinal : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {cache_cardinal} -> cache_cardinal) + (fun cache_cardinal -> {cache_cardinal}) + (obj1 (req "cache_cardinal" int31)) + + let tags = [Tags.cache] + + let workload_to_vector {cache_cardinal} = + Sparse_vec.String.of_list [("cache_cardinal", float_of_int cache_cardinal)] +end + +(* We can't produce a Script_cache.identifier without calling [Script_cache.find]. *) +let identifier_of_contract (c : Contract_hash.t) : Cache.identifier = + let _, id, _ = Cache.find throwaway_context c |> assert_ok_lwt in + id + +let contract_of_int i : Contract_hash.t = + Contract_hash.(of_b58check_exn (to_b58check (hash_string [string_of_int i]))) + +let identifier_of_int i = identifier_of_contract @@ contract_of_int i + +(** Prepare a context with a cache of the prescribed cardinality. A key in the domain of + the cache is returned along the context: this key is used to benchmark + (successful) cache accesses. *) +let prepare_context rng_state cache_cardinal = + assert (cache_cardinal > 0) ; + let ctxt = make_context ~rng_state in + let some_key_in_domain = identifier_of_int 0 in + let rec loop i ctxt = + if Compare.Int.(i = cache_cardinal) then ctxt + else + let key = identifier_of_int i in + loop (i + 1) (Cache.update ctxt key dummy_script 1 |> assert_ok) + in + (loop 0 ctxt, some_key_in_domain) + +(** Benchmark {!Script_cache.update}. This almost directly calls {!Environment_cache.update}. + We also use the result of this benchmark to assign a cost to {!Environment_cache.find}, + which alas can't be directly benchmarked from the interface provided by {!Script_cache}. *) +module Cache_update_benchmark : Benchmarks_proto.Benchmark.S = struct + include Cache_shared_config + + let name = ns "CACHE_UPDATE" + + let info = "Benchmarking the time it takes to update a key in the cache" + + let module_filename = __FILE__ + + let group = Benchmark.Group "cache_repr" + + let purpose = Benchmark.Generate_code "cache_repr" + + (** It is expected that cache keys are non-adversarial, + ie do not share a long common prefix. This is the case for [Script_cache], + for which the keys are B58-encoded contract hashes. + + To rephrase: with high probability, comparing two keys in the domain of the cache is + a constant-time operation (two keys will differ after the first few characters). + We therefore do not take into account the length of the key in the model. *) + let model = + let affine_logn name = + let open Tezos_benchmark.Model in + let param_name param = + Free_variable.of_namespace (Namespace.cons name param) + in + let intercept = param_name "intercept" in + let coeff = param_name "coeff" in + let module M = struct + let name = name + + let takes_saturation_reprs = false + + type arg_type = int * unit + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size + + let arity = arity_1 + + let model = + lam ~name:"size" @@ fun size -> + free ~name:intercept + (free ~name:coeff * log2 (int 1 + size)) + end + end in + (module M : Model_impl with type arg_type = int * unit) + in + (* Looking at the plots, it looks like this benchmark underestimates the constant term. + In the interpreter, this would warrant a dedicated benchmark for the intercept. *) + Benchmarks_proto.Model.make + ~conv:(function {cache_cardinal} -> (cache_cardinal, ())) + affine_logn + + let cache_update_benchmark ctxt some_key_in_domain cache_cardinal = + let workload = {cache_cardinal} in + let closure () = + ignore (Cache.update ctxt some_key_in_domain dummy_script 1) + in + Generator.Plain {workload; closure} + + (** At the time of writing (Protocol H) the worst case execution path for + [Cache.update] is to update a key which is already present. *) + let create_benchmark ~rng_state _cfg = + let cache_cardinal = + Base_samplers.sample_in_interval ~range:{min = 1; max = 100_000} rng_state + in + let ctxt, some_key_in_domain = prepare_context rng_state cache_cardinal in + cache_update_benchmark ctxt some_key_in_domain cache_cardinal +end + +let () = Benchmarks_proto.Registration.register (module Cache_update_benchmark) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/carbonated_map_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/carbonated_map_benchmarks.ml new file mode 100644 index 000000000000..a3f54995d788 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/carbonated_map_benchmarks.ml @@ -0,0 +1,341 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_benchmark +open Benchmarks_proto + +let ns = Namespace.make Registration.ns "carbonated_map" + +let fv s = Free_variable.of_namespace (ns s) + +let group = Benchmark.Group "carbonated_map" + +let make_context ~rng_state = + match Lwt_main.run @@ Execution_context.make ~rng_state () with + | Ok (ctxt, _) -> ctxt + | Error _ -> assert false + +module Config_and_workload = struct + type config = {size : int} + + let config_encoding = + let open Data_encoding in + conv (fun {size} -> size) (fun size -> {size}) (obj1 (req "size" int31)) + + let default_config = {size = 100_000} + + type workload = config + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "carbonated_map" + + let tags = ["carbonated_map"] + + let group = group + + let workload_encoding = config_encoding + + let workload_to_vector {size} = + Sparse_vec.String.of_list [("size", float_of_int size)] +end + +module Alpha_context_gas = struct + type context = Alpha_context.context + + let consume = Alpha_context.Gas.consume +end + +(** + Benchmarks the [fold] functions of [Carbonated_map]. + This benchmark does not depend on the size of the keys or types of elements. +*) +module Fold_benchmark : Benchmark.S = struct + include Config_and_workload + + module Int = struct + include Int + + (** Dummy value *) + let compare_cost _ = Saturation_repr.safe_int 0 + end + + let name = ns "fold" + + let info = "Carbonated map to list" + + let model = + Model.make + ~conv:(fun {size} -> (size, ())) + (Model.affine + ~intercept:(fv "fold_const") + ~coeff:(fv "fold_cost_per_item")) + + let create_benchmark ~rng_state config = + let module M = Carbonated_map.Make (Alpha_context_gas) (Int) in + let _, list = + let sampler rng_state = + let key = Base_samplers.int rng_state ~size:{min = 1; max = 5} in + (* Value should not be important *) + let value = () in + (Z.to_int key, value) + in + Structure_samplers.list + rng_state + ~range:{min = 1; max = config.size} + ~sampler + in + let ctxt = make_context ~rng_state in + let map = + match + M.of_list + ctxt + ~merge_overlap:(fun ctxt _left right -> Ok (right, ctxt)) + list + with + | Ok (map, _) -> map + | _ -> assert false + in + let workload = {size = M.size map} in + let closure () = + ignore @@ M.fold_e ctxt (fun ctxt _ _ _ -> Ok ((), ctxt)) () map + in + Generator.Plain {workload; closure} +end + +(** Module type that consists of a comparable type along with a sampler + function. *) +module type COMPARABLE_SAMPLER = sig + include Compare.COMPARABLE + + val type_name : string + + val sampler : t Base_samplers.sampler +end + +(** + Functor for constructing a benchmark for the cost of comparing values. This + functor can be used to generate [compare_cost] data for a particular + key-type for [Carbonated_map] instances. +*) +module Make (CS : COMPARABLE_SAMPLER) = struct + let compare_var type_name = fv (Printf.sprintf "compare_%s" type_name) + + module Compare = struct + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = config + + let tags = ["carbonated_map"] + + let workload_encoding = config_encoding + + let workload_to_vector () = Sparse_vec.String.of_list [] + + let name = ns @@ Printf.sprintf "compare_%s" CS.type_name + + let info = + Printf.sprintf "Carbonated map compare cost for %s keys" CS.type_name + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "carbonated_map" + + let group = group + + let model = + Model.make + ~conv:(fun () -> ()) + (Model.unknown_const1 ~const:(compare_var CS.type_name)) + + let create_benchmark ~rng_state _conf = + let key = CS.sampler rng_state in + let workload = () in + let closure () = ignore (CS.compare key key) in + Generator.Plain {workload; closure} + end + + module Find = struct + include Config_and_workload + + module M = + Carbonated_map.Make + (Alpha_context_gas) + (struct + include CS + + (** Dummy cost*) + let compare_cost _ = Saturation_repr.safe_int 0 + end) + + let name = ns "find" + + let info = Printf.sprintf "Carbonated find model" + + let ns s = Free_variable.of_namespace (Namespace.cons name s) + + let fv_intercept = ns "intercept" + + (** + Given the cost of comparing keys, the model is used for deducing [intercept] + and [traversal_overhead] from: + + [intercept + (log2 size * compare_cost) + (log2 size * traversal_overhead)] + *) + let find_model name = + let open Tezos_benchmark in + let traversal_overhead = ns "traversal_overhead" in + let intercept = fv_intercept in + let module M = struct + type arg_type = int * unit + + let name = name + + let takes_saturation_reprs = false + + module Def (L : Costlang.S) = struct + type model_type = L.size -> L.size + + let arity = Model.arity_1 + + let model = + let open L in + lam ~name:"size" @@ fun size -> + let compare_cost = + log2 size * free ~name:(compare_var CS.type_name) + in + let traversal_overhead = + log2 size * free ~name:traversal_overhead + in + free ~name:intercept + compare_cost + traversal_overhead + end + end in + (module M : Model.Model_impl with type arg_type = int * unit) + + let model = Model.make ~conv:(fun {size} -> (size, ())) find_model + + let create_benchmark ~rng_state (config : config) = + let _, list = + let sampler rng_state = (CS.sampler rng_state, ()) in + Structure_samplers.list + rng_state + ~range:{min = 1; max = config.size} + ~sampler + in + let ctxt = make_context ~rng_state in + let map = + match + M.of_list ctxt ~merge_overlap:(fun ctxt _ _ -> Ok ((), ctxt)) list + with + | Ok (map, _) -> map + | _ -> assert false + in + (* Pick the min binding from the map to guarantee longest path. *) + let key = + match M.to_list ctxt map with + | Ok (kvs, _) -> ( + match List.hd kvs with Some (k, _) -> k | None -> assert false) + | Error _ -> assert false + in + let workload = {size = M.size map} in + let closure () = ignore @@ M.find ctxt key map in + Generator.Plain {workload; closure} + end + + module Find_intercept = struct + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = config + + let tags = ["carbonated_map"] + + let workload_encoding = config_encoding + + let workload_to_vector () = Sparse_vec.String.of_list [] + + module M = + Carbonated_map.Make + (Alpha_context_gas) + (struct + include CS + + (** Dummy cost*) + let compare_cost _ = Saturation_repr.safe_int 0 + end) + + let name = ns "find_intercept" + + let info = Printf.sprintf "Carbonated find model (intercept case)" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "carbonated_map" + + let group = group + + let model = + Model.make + ~conv:(fun () -> ()) + (Model.unknown_const1 ~const:Find.fv_intercept) + + let create_benchmark ~rng_state (_config : config) = + let ctxt = make_context ~rng_state in + let map = M.empty in + let key = CS.sampler rng_state in + let workload = () in + let closure () = ignore @@ M.find ctxt key map in + Generator.Plain {workload; closure} + end +end + +(** A comparable and a sampler for [int] values. *) +module Int = struct + type t = int + + let compare = Int.compare + + let type_name = "int" + + let sampler rng_state = + Z.to_int @@ Base_samplers.int rng_state ~size:{min = 1; max = 6} +end + +module Benchmarks_int = Make (Int) + +let () = + let open Registration in + register (module Fold_benchmark) ; + register (module Benchmarks_int.Compare) ; + register (module Benchmarks_int.Find) ; + register (module Benchmarks_int.Find_intercept) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/dal_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/dal_benchmarks.ml new file mode 100644 index 000000000000..6f274f1c0f02 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/dal_benchmarks.ml @@ -0,0 +1,146 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let ns = Namespace.make Registration_helpers.ns "dal" + +let fv s = Free_variable.of_namespace (ns s) + +module Publish_commitment : Benchmark.S = struct + let name = ns "Dal_publish_commitment" + + let info = "Estimating the cost of publishing a slot header" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "dal" + + let tags = ["dal"] + + type config = Environment.Dal.parameters + + let default_config = + Default_parameters.constants_mainnet.dal.cryptobox_parameters + + let config_encoding = Tezos_crypto_dal.Cryptobox.parameters_encoding + + type workload = unit + + let workload_encoding = Data_encoding.unit + + let workload_to_vector _ = Sparse_vec.String.of_list [] + + let model = + Model.make + ~conv:(fun () -> ()) + (Model.unknown_const1 ~name ~const:(fv "publish_commitment_const")) + + let models = [("dal", model)] + + let operation_generator cryptobox rng_state = + let open Result_syntax in + let open Alpha_context in + let module Crypto = Tezos_crypto_dal.Cryptobox in + let config = Crypto.parameters cryptobox in + let slot_index = Dal.Slot_index.zero in + let slot = Base_samplers.uniform_bytes ~nbytes:config.slot_size rng_state in + let* polynomial = Crypto.polynomial_from_slot cryptobox slot in + let* commitment = Crypto.commit cryptobox polynomial in + let* commitment_proof = Crypto.prove_commitment cryptobox polynomial in + return + @@ Dal.Operations.Publish_commitment. + {slot_index; commitment; commitment_proof} + + let make_bench rng_state (config : config) () : workload Generator.benchmark = + let open Lwt_result_wrap_syntax in + let bench_promise = + let dal = + {Default_parameters.constants_mainnet.dal with feature_enable = true} + in + let* ctxt, _ = Execution_context.make ~dal ~rng_state () in + let* cryptobox = + match Tezos_crypto_dal.Cryptobox.make config with + | Ok cryptobox -> return cryptobox + | Error (`Fail msg) -> + failwith "Dal_benchmarks: failed to initialize cryptobox (%s)" msg + in + (* Memoize the cryptobox in the context *) + let*?@ ctxt, _abstract_cryptobox = Alpha_context.Dal.make ctxt in + let* op = + match operation_generator cryptobox rng_state with + | Ok op -> return op + | Error err -> + let msg = + match err with + | `Slot_wrong_size s -> Format.asprintf "Slot_wrong_size(%s)" s + | `Invalid_degree_strictly_less_than_expected {given; expected} -> + Format.asprintf + "Invalid_degree_strictly_less_than_expected {given=%d, \ + expected=%d}" + given + expected + | `Prover_SRS_not_loaded -> "Prover_SRS_not_loaded" + in + failwith "Dal_benchmarks: failed to generate operation (%s)" msg + in + let workload = () in + let closure () = + match Dal_apply.apply_publish_commitment ctxt op with + | Error errs -> + Format.eprintf "%a@." Environment.Error_monad.pp_trace errs ; + Stdlib.failwith + "Dal_benchmarks: error raised during closure execution@." + | exception _ -> assert false + | Ok _ -> () + in + return (Generator.Plain {workload; closure}) + in + Lwt_main.run bench_promise |> function + | Ok closure -> closure + | Error errs -> + Format.eprintf "%a@." Error_monad.pp_print_trace errs ; + Stdlib.failwith "Dal_benchmarks: failed to run benchmark" + + let create_benchmarks ~rng_state ~bench_num config = + let () = + Lwt_main.run + @@ Tezos_crypto_dal.Cryptobox.Config.init_prover_dal + ~find_srs_files:(Fun.const (Ok ("", ""))) + { + activated = true; + use_mock_srs_for_testing = true; + bootstrap_peers = []; + } + |> function + | Ok () -> () + | Error errs -> + Format.eprintf "%a@." Error_monad.pp_print_trace errs ; + Stdlib.failwith "Dal_benchmarks: failed to initialize" + in + Format.printf "Initialized DAL@." ; + List.repeat bench_num (make_bench rng_state config) +end + +let () = Registration_helpers.register (module Publish_commitment) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/dune b/src/proto_020_PsParisC/lib_benchmarks_proto/dune new file mode 100644 index 000000000000..e03de329df4d --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/dune @@ -0,0 +1,44 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_benchmarks_proto_019_PtParisB) + (public_name tezos-benchmarks-proto-019-PtParisB) + (instrumentation (backend bisect_ppx)) + (libraries + str + octez-libs.stdlib + octez-libs.base + octez-libs.error-monad + tezos-protocol-019-PtParisB.parameters + octez-libs.lazy-containers + tezos-benchmark + tezos-benchmark-019-PtParisB + tezos-benchmark-type-inference-019-PtParisB + tezos-protocol-019-PtParisB.protocol + octez-libs.crypto + octez-shell-libs.shell-benchmarks + octez-libs.micheline + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.tezos-sapling + octez-protocol-019-PtParisB-libs.client + octez-protocol-019-PtParisB-libs.plugin + octez-proto-libs.protocol-environment) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_stdlib + -open Tezos_base + -open Tezos_base.TzPervasives + -open Tezos_error_monad + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_lazy_containers + -open Tezos_benchmark + -open Tezos_benchmark_019_PtParisB + -open Tezos_benchmark_type_inference_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB.Protocol + -open Tezos_micheline + -open Tezos_019_PtParisB_test_helpers + -open Tezos_client_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/encodings_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/encodings_benchmarks.ml new file mode 100644 index 000000000000..ddb82d3c4192 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/encodings_benchmarks.ml @@ -0,0 +1,507 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +module Encodings = +Tezos_shell_benchmarks.Encoding_benchmarks_helpers.Make (struct + let file = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" +end) + +module Size = Gas_input_size + +let ns = Namespace.make Registration_helpers.ns "encoding" + +let fv s = Free_variable.of_namespace (ns s) + +module Micheline_common = struct + let make_printable node = + Micheline_printer.printable + Michelson_v1_primitives.string_of_prim + (Micheline.strip_locations node) + + type phase = Trace_production | In_protocol | Global + + type error = + | Bad_micheline of { + benchmark_name : Namespace.t; + micheline : Alpha_context.Script.node; + phase : phase; + } + + exception Micheline_benchmark of error + + let pp_phase fmtr (phase : phase) = + match phase with + | Trace_production -> Format.fprintf fmtr "trace production" + | In_protocol -> Format.fprintf fmtr "in protocol" + | Global -> Format.fprintf fmtr "global" + + let pp_error fmtr = function + | Bad_micheline {benchmark_name; micheline; phase} -> + Format.open_vbox 1 ; + Format.fprintf fmtr "Bad micheline:@," ; + Format.fprintf fmtr "benchmark = %a@," Namespace.pp benchmark_name ; + Format.fprintf + fmtr + "expression = @[%a@]@," + Micheline_printer.print_expr + (make_printable micheline) ; + Format.fprintf fmtr "phase = %a@," pp_phase phase ; + Format.close_box () + + let bad_micheline benchmark_name micheline phase = + raise + (Micheline_benchmark (Bad_micheline {benchmark_name; micheline; phase})) + + type workload = {size : Size.micheline_size; bytes : int} + + let workload_encoding = + let open Data_encoding in + def "encoding_micheline_trace" + @@ conv + (fun {size; bytes} -> (size, bytes)) + (fun (size, bytes) -> {size; bytes}) + (obj2 + (req "micheline_size" Size.micheline_size_encoding) + (req "micheline_bytes" Size.encoding)) + + let workload_to_vector (workload : workload) = + let keys = + [ + ( "encoding_micheline_traversal", + float_of_int (Size.to_int workload.size.traversal) ); + ( "encoding_micheline_int_bytes", + float_of_int (Size.to_int workload.size.int_bytes) ); + ( "encoding_micheline_string_bytes", + float_of_int (Size.to_int workload.size.string_bytes) ); + ("encoding_micheline_bytes", float_of_int (Size.to_int workload.bytes)); + ] + in + Sparse_vec.String.of_list keys + + let tags = [Tags.encoding] + + let model_size name = + Model.make + ~takes_saturation_reprs:true + ~conv:(fun {size = {Size.traversal; int_bytes; string_bytes}; _} -> + (traversal, (int_bytes, (string_bytes, ())))) + (Model.trilinear + ~name:(ns name) + ~coeff1:(fv (Format.asprintf "%s_micheline_traversal" name)) + ~coeff2:(fv (Format.asprintf "%s_micheline_int_bytes" name)) + ~coeff3:(fv (Format.asprintf "%s_micheline_string_bytes" name))) + + let model_bytes name = + Model.make + ~takes_saturation_reprs:true + ~conv:(fun {bytes; _} -> (bytes, ())) + (Model.linear + ~name:(ns (name ^ "_bytes")) + ~coeff:(fv (Format.asprintf "%s_micheline_bytes" name))) + + let models name = + [("micheline", model_size name); ("micheline_bytes", model_bytes name)] +end + +let group = Benchmark.Group "script_repr" + +module Encoding_micheline : Benchmark.S = struct + include Translator_benchmarks.Config + include Micheline_common + + let name = ns "ENCODING_MICHELINE" + + let info = "Benchmarking strip_location + encoding of Micheline to bytes" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_repr" + + let micheline_serialization_trace (micheline_node : Alpha_context.Script.node) + = + match + Data_encoding.Binary.to_string + Protocol.Script_repr.expr_encoding + (Micheline.strip_locations micheline_node) + with + | Error err -> + Format.eprintf + "micheline_serialization_trace: %a@." + Data_encoding.Binary.pp_write_error + err ; + None + | Ok str -> + let micheline_size = Size.of_micheline micheline_node in + Some {size = micheline_size; bytes = Size.string str} + + let encoding_micheline_benchmark (node : Protocol.Script_repr.expr) = + let node = Micheline.root node in + let workload = + match micheline_serialization_trace node with + | None -> Micheline_common.bad_micheline name node Trace_production + | Some trace -> trace + in + let closure () = + try + ignore + (Data_encoding.Binary.to_string_exn + Protocol.Script_repr.expr_encoding + (Micheline.strip_locations node)) + with _ -> Micheline_common.bad_micheline name node In_protocol + in + Generator.Plain {workload; closure} + + let make_bench rng_state cfg () = + let Michelson_mcmc_samplers.{term; typ = _} = + Michelson_generation.make_data_sampler rng_state cfg.generator_config + in + encoding_micheline_benchmark term + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.map + (function + | Michelson_mcmc_samplers.Data {term; typ = _} + | Michelson_mcmc_samplers.Code {term; bef = _; aft = _} -> + fun () -> encoding_micheline_benchmark term) + terms + | None -> List.repeat bench_num (make_bench rng_state config) + + let models = models (Namespace.basename name) +end + +let () = + Benchmarks_proto.Registration.register_as_simple_with_num + ~group + (module Encoding_micheline) + +module Decoding_micheline : Benchmark.S = struct + include Translator_benchmarks.Config + include Micheline_common + + let name = ns "DECODING_MICHELINE" + + let info = "Decoding of bytes to Micheline" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_repr" + + let micheline_deserialization_trace (micheline_str : string) = + match + Data_encoding.Binary.of_string + Protocol.Script_repr.expr_encoding + micheline_str + with + | Error err -> + Format.eprintf + "micheline_deserialization_trace: %a@." + Data_encoding.Binary.pp_read_error + err ; + None + | Ok micheline_node -> + let micheline_size = + Size.of_micheline (Micheline.root micheline_node) + in + Some {size = micheline_size; bytes = Size.string micheline_str} + + let decoding_micheline_benchmark (node : Protocol.Script_repr.expr) = + let encoded = + Data_encoding.Binary.to_string_exn Protocol.Script_repr.expr_encoding node + in + let node = Micheline.root node in + let workload = + match micheline_deserialization_trace encoded with + | None -> bad_micheline name node Trace_production + | Some trace -> trace + in + let closure () = + try + ignore + (Data_encoding.Binary.of_string_exn + Protocol.Script_repr.expr_encoding + encoded) + with _ -> bad_micheline name node In_protocol + in + Generator.Plain {workload; closure} + + let make_bench rng_state cfg () = + let Michelson_mcmc_samplers.{term; typ = _} = + Michelson_generation.make_data_sampler rng_state cfg.generator_config + in + decoding_micheline_benchmark term + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.map + (function + | Michelson_mcmc_samplers.Data {term; typ = _} + | Michelson_mcmc_samplers.Code {term; bef = _; aft = _} -> + fun () -> decoding_micheline_benchmark term) + terms + | None -> List.repeat bench_num (make_bench rng_state config) + + let models = models (Namespace.basename name) +end + +let () = + Benchmarks_proto.Registration.register_as_simple_with_num + ~group + (module Decoding_micheline) + +module Timestamp = struct + open Encodings + + let () = + Registration_helpers.register_simple_with_num + @@ fixed_size_shared + ~name:"TIMESTAMP_READABLE_ENCODING" + ~generator:(fun rng_state -> + let seconds_in_year = 30_000_000 in + let offset = Random.State.int rng_state seconds_in_year in + Script_timestamp.of_zint (Z.of_int (1597764116 + offset))) + ~make_bench:(fun generator () -> + let tstamp_string = generator () in + let closure () = + ignore (Script_timestamp.to_notation tstamp_string) + in + Generator.Plain {workload = (); closure}) + () + + let () = + let b, b_intercept = + nsqrtn_shared_with_intercept + ~name:"TIMESTAMP_READABLE_DECODING" + ~generator:(fun rng_state -> + let offset = + Base_samplers.nat ~size:{min = 1; max = 100_000} rng_state + in + let tstamp = + Script_timestamp.of_zint Z.(of_int 1597764116 + offset) + in + Script_timestamp.to_string tstamp) + ~make_bench:(fun generator -> + let tstamp_string = generator () in + let bytes = String.length tstamp_string in + let closure () = ignore (Script_timestamp.of_string tstamp_string) in + Generator.Plain {workload = {bytes}; closure}) + ~generator_intercept:(fun rng_state -> + let seconds_in_year = 30_000_000 in + let offset = Random.State.int rng_state seconds_in_year in + let tstamp = + Script_timestamp.of_zint (Z.of_int (1597764116 + offset)) + in + Script_timestamp.to_string tstamp) + ~make_bench_intercept:(fun generator -> + let tstamp_string = generator () in + let closure () = ignore (Script_timestamp.of_string tstamp_string) in + Generator.Plain {workload = {bytes = 0}; closure}) + in + Registration_helpers.register_simple b ; + Registration_helpers.register_simple b_intercept +end + +(* when benchmarking, compile bls12-381 without ADX, see + https://gitlab.com/dannywillems/ocaml-bls12-381/-/blob/71d0b4d467fbfaa6452d702fcc408d7a70916a80/README.md#install +*) +module BLS = struct + open Encodings + + let check () = + if not Bls12_381.built_with_blst_portable then ( + Format.eprintf + "BLS must be built without ADX to run the BLS benchmarks. Try \ + compiling again after setting the environment variable BLST_PORTABLE. \ + Aborting.@." ; + Stdlib.failwith "bls_not_built_with_blst_portable") + + let () = + Registration_helpers.register_simple_with_num + @@ make_encode_fixed_size_to_bytes + ~check + ~name:"ENCODING_BLS_FR" + ~to_bytes:Bls12_381.Fr.to_bytes + ~generator:(fun rng_state -> Bls12_381.Fr.random ~state:rng_state ()) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_encode_fixed_size_to_bytes + ~check + ~name:"ENCODING_BLS_G1" + ~to_bytes:Bls12_381.G1.to_bytes + ~generator:(fun rng_state -> Bls12_381.G1.random ~state:rng_state ()) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_encode_fixed_size_to_bytes + ~check + ~name:"ENCODING_BLS_G2" + ~to_bytes:Bls12_381.G2.to_bytes + ~generator:(fun rng_state -> Bls12_381.G2.random ~state:rng_state ()) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_decode_fixed_size_from_bytes + ~check + ~name:"DECODING_BLS_FR" + ~to_bytes:Bls12_381.Fr.to_bytes + ~from_bytes:Bls12_381.Fr.of_bytes_exn + ~generator:(fun rng_state -> Bls12_381.Fr.random ~state:rng_state ()) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_decode_fixed_size_from_bytes + ~check + ~name:"DECODING_BLS_G1" + ~to_bytes:Bls12_381.G1.to_bytes + ~from_bytes:Bls12_381.G1.of_bytes_exn + ~generator:(fun rng_state -> Bls12_381.G1.random ~state:rng_state ()) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_decode_fixed_size_from_bytes + ~check + ~name:"DECODING_BLS_G2" + ~to_bytes:Bls12_381.G2.to_bytes + ~from_bytes:Bls12_381.G2.of_bytes_exn + ~generator:(fun rng_state -> Bls12_381.G2.random ~state:rng_state ()) + () + + let () = + Registration_helpers.register_simple_with_num + @@ fixed_size_shared + ~check + ~name:"BLS_FR_FROM_Z" + ~generator:(fun rng_state -> Bls12_381.Fr.random ~state:rng_state ()) + ~make_bench:(fun generator () -> + let generated = generator () in + let z = Bls12_381.Fr.to_z generated in + let closure () = ignore (Bls12_381.Fr.of_z z) in + Generator.Plain {workload = (); closure}) + () + + let () = + Registration_helpers.register_simple_with_num + @@ fixed_size_shared + ~check + ~name:"BLS_FR_TO_Z" + ~generator:(fun rng_state -> Bls12_381.Fr.random ~state:rng_state ()) + ~make_bench:(fun generator () -> + let generated = generator () in + let closure () = ignore (Bls12_381.Fr.to_z generated) in + Generator.Plain {workload = (); closure}) + () +end + +module Timelock = struct + open Encodings + + let generator rng_state = + let log_time = + Base_samplers.sample_in_interval ~range:{min = 0; max = 20} rng_state + in + let time = Int.shift_left 1 log_time in + let plaintext_size = + Base_samplers.sample_in_interval ~range:{min = 1; max = 10000} rng_state + in + let chest, chest_key = + Tezos_crypto.Timelock.chest_sampler ~plaintext_size ~time ~rng_state + in + ((chest, chest_key), plaintext_size) + + let () = + Registration_helpers.register_simple_with_num + @@ make_encode_variable_size_to_string + ~name:"ENCODING_Chest" + ~to_string: + (Data_encoding.Binary.to_string_exn + Tezos_crypto.Timelock.chest_encoding) + ~generator:(fun rng_state -> + let (chest, _), plaintext_size = generator rng_state in + (chest, {bytes = plaintext_size})) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_encode_fixed_size_to_string + ~name:"ENCODING_Chest_key" + ~to_string: + (Data_encoding.Binary.to_string_exn + Tezos_crypto.Timelock.chest_key_encoding) + ~generator:(fun rng_state -> + let (_, chest_key), _w = generator rng_state in + chest_key) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_decode_variable_size_from_bytes + ~name:"DECODING_Chest" + ~to_bytes: + (Data_encoding.Binary.to_bytes_exn + Tezos_crypto.Timelock.chest_encoding) + ~from_bytes: + (Data_encoding.Binary.of_bytes_exn + Tezos_crypto.Timelock.chest_encoding) + ~generator:(fun rng_state -> + let (chest, _), _ = generator rng_state in + let b = + Data_encoding.Binary.to_bytes_exn + Tezos_crypto.Timelock.chest_encoding + chest + in + (chest, {bytes = Bytes.length b})) + () + + let () = + Registration_helpers.register_simple_with_num + @@ make_decode_fixed_size_from_bytes + ~name:"DECODING_Chest_key" + ~to_bytes: + (Data_encoding.Binary.to_bytes_exn + Tezos_crypto.Timelock.chest_key_encoding) + ~from_bytes: + (Data_encoding.Binary.of_bytes_exn + Tezos_crypto.Timelock.chest_key_encoding) + ~generator:(fun rng_state -> + let (_, chest_key), _w = generator rng_state in + chest_key) + () +end diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/gas_helpers.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/gas_helpers.ml new file mode 100644 index 000000000000..bf8bcde60256 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/gas_helpers.ml @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let set_limit ctxt = + Alpha_context.Gas.set_limit + ctxt + (Alpha_context.Gas.Arith.integral_of_int_exn 999_999_999_999) + +let fp_to_z (fp : Alpha_context.Gas.Arith.fp) = + let open Data_encoding in + Binary.to_bytes_exn Alpha_context.Gas.Arith.z_fp_encoding fp + |> Binary.of_bytes_exn z diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/global_constants_storage_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/global_constants_storage_benchmarks.ml new file mode 100644 index 000000000000..db3e3b072362 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/global_constants_storage_benchmarks.ml @@ -0,0 +1,667 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022-2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* This module includes benchmarks for [Global_constants_storage.expand] + and [Global_constants_storage.Internal_for_tests.expr_to_address_in_context]. + The other main function exported by [Global_constants_storage] is [register]; + however, [register] calls [expand] and does little else, and thus does + not need to be further carbonated. + + In the process of creating these benchmarks, we benchmarked several OCaml + stdlib functions and [Script_expr_hash.of_b58check_opt]. While these cost + models are not used in the protocol, they are kept here to ensure the + assumptions underlying [register] and [expand] don't change out + from under us.*) + +open Tezos_benchmark +open Benchmarks_proto +open Tezos_micheline +open Protocol + +let ns = Namespace.make Registration_helpers.ns "global_constants_storage" + +let fv s = Free_variable.of_namespace (ns s) + +let assert_ok_lwt x = + match Lwt_main.run x with + | Ok x -> x + | Error errs -> + Format.eprintf "%a@." pp_print_trace errs ; + exit 1 + +let assert_ok = function + | Ok x -> x + | Error errs -> + Format.eprintf "%a@." pp_print_trace errs ; + exit 1 + +(** [seq_of_n_constants n hash] generates a Seq filled + with [n] constant primitives containing [hash] *) +let seq_of_n_constants n hash = + let open Micheline in + Seq + ( -1, + Stdlib.List.init n (fun _ -> + Prim (-1, Michelson_v1_primitives.H_constant, [String (-1, hash)], [])) + ) + +(** Computes the b58check hash of a Micheline node as a string. *) +let node_to_hash node = + let expr_bytes = + Micheline.strip_locations node + |> Script_repr.lazy_expr |> Script_repr.force_bytes |> Stdlib.Result.get_ok + in + Script_expr_hash.hash_bytes [expr_bytes] |> Script_expr_hash.to_b58check + +(* An ad-hoc sampler for Micheline values. Boltzmann sampling would do well + here. + + Copied from lib_micheline and modified to use [Michelson_v1_primitives.prim]. *) +module Micheline_sampler = struct + type node = Alpha_context.Script.node + + let prims = + let open Protocol.Michelson_v1_primitives in + [| + K_parameter; + K_storage; + K_code; + D_False; + D_Elt; + D_Left; + D_None; + D_Pair; + D_Right; + D_Some; + D_True; + D_Unit; + I_PACK; + I_UNPACK; + I_BLAKE2B; + I_SHA256; + I_SHA512; + I_ABS; + I_ADD; + I_AMOUNT; + I_AND; + I_BALANCE; + I_CAR; + I_CDR; + I_CHAIN_ID; + I_CHECK_SIGNATURE; + I_COMPARE; + I_CONCAT; + I_CONS; + I_CREATE_ACCOUNT; + I_CREATE_CONTRACT; + I_IMPLICIT_ACCOUNT; + I_DIP; + I_DROP; + I_DUP; + I_EDIV; + I_EMPTY_BIG_MAP; + I_EMPTY_MAP; + I_EMPTY_SET; + I_EQ; + I_EXEC; + I_APPLY; + I_FAILWITH; + I_GE; + I_GET; + I_GET_AND_UPDATE; + I_GT; + I_HASH_KEY; + I_IF; + I_IF_CONS; + I_IF_LEFT; + I_IF_NONE; + I_INT; + I_LAMBDA; + I_LE; + I_LEFT; + I_LEVEL; + I_LOOP; + I_LSL; + I_LSR; + I_LT; + I_MAP; + I_MEM; + I_MUL; + I_NEG; + I_NEQ; + I_NIL; + I_NONE; + I_NOT; + I_NOW; + I_OR; + I_PAIR; + I_UNPAIR; + I_PUSH; + I_RIGHT; + I_SIZE; + I_SOME; + I_SOURCE; + I_SENDER; + I_SELF; + I_SELF_ADDRESS; + I_SLICE; + I_STEPS_TO_QUOTA; + I_SUB; + I_SWAP; + I_TRANSFER_TOKENS; + I_SET_DELEGATE; + I_UNIT; + I_UPDATE; + I_XOR; + I_ITER; + I_LOOP_LEFT; + I_ADDRESS; + I_CONTRACT; + I_ISNAT; + I_CAST; + I_RENAME; + I_SAPLING_EMPTY_STATE; + I_SAPLING_VERIFY_UPDATE; + I_DIG; + I_DUG; + I_NEVER; + I_VOTING_POWER; + I_TOTAL_VOTING_POWER; + I_KECCAK; + I_SHA3; + I_PAIRING_CHECK; + I_TICKET; + I_READ_TICKET; + I_SPLIT_TICKET; + I_JOIN_TICKETS; + T_bool; + T_contract; + T_int; + T_key; + T_key_hash; + T_lambda; + T_list; + T_map; + T_big_map; + T_nat; + T_option; + T_or; + T_pair; + T_set; + T_signature; + T_string; + T_bytes; + T_mutez; + T_timestamp; + T_unit; + T_operation; + T_address; + T_sapling_transaction_deprecated; + T_sapling_state; + T_chain_id; + T_never; + T_bls12_381_g1; + T_bls12_381_g2; + T_bls12_381_fr; + T_ticket + (* We don't want constants in our generator, else the constants + functions might fail because it's ill-formed. *) + (* H_constant; *); + |] + + module Sampler = Micheline_sampler.Make (struct + type prim = Michelson_v1_primitives.prim + + let sample_prim : Michelson_v1_primitives.prim Base_samplers.sampler = + fun rng_state -> + let i = Random.State.int rng_state (Array.length prims) in + prims.(i) + + let sample_annots : string list Base_samplers.sampler = fun _rng_state -> [] + + let sample_string _ = "" + + let sample_bytes _ = Bytes.empty + + let sample_z _ = Z.zero + + let width_function = Micheline_sampler.reasonable_width_function + end) + + let sample = Sampler.sample + + type size = {nodes : int; bytes : int} + + let int z = {nodes = 1; bytes = (Z.numbits z + 7) / 8} + + let string s = {nodes = 1; bytes = String.length s} + + let bytes b = {nodes = 1; bytes = Bytes.length b} + + let node = {nodes = 1; bytes = 0} + + let ( @+ ) x y = {nodes = x.nodes + y.nodes; bytes = x.bytes + y.bytes} + + let micheline_size (n : node) = + let rec micheline_size n acc = + let open Micheline in + match n with + | Int (_, i) -> acc @+ int i + | String (_, s) -> acc @+ string s + | Bytes (_, b) -> acc @+ bytes b + | Seq (_, terms) -> + List.fold_left + (fun acc term -> micheline_size term acc) + (acc @+ node) + terms + | Prim (_, _, terms, _) -> + List.fold_left + (fun acc term -> micheline_size term acc) + (acc @+ node) + terms + in + micheline_size n {nodes = 0; bytes = 0} +end + +(** Cost model and benchmarks for set element addition from the + OCaml stdlib. + + The cost model is not currently used + in the protocol, but we include the benchmarks to validate our + assumptions about functions that use this. *) +module Set_add : Benchmark.S = struct + let name = ns "Set_add" + + let info = + "Benchmarks and cost model for set element addition from OCaml stdlib." + + let module_filename = __FILE__ + + let purpose = + Benchmark.Other_purpose + "Validate assumptions about functions using Set.add." + + let group = Benchmark.Group "global_constants" + + let tags = ["global_constants"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector : workload -> Sparse_vec.String.t = + fun size -> Sparse_vec.String.of_list [("size", float_of_int size)] + + (* As an OCaml set is a balanced binary tree, complexity is O(log n). *) + let model = Model.(make ~conv:(fun size -> (size, ())) logn) + + module Int_set = Set.Make (Int) + + let create_benchmark ~rng_state _config = + let range : Base_samplers.range = {min = 0; max = 10_000} in + let size = Base_samplers.sample_in_interval ~range rng_state in + let set = Stdlib.List.init size Fun.id |> Int_set.of_list in + let closure () = ignore (Int_set.add (size + 1) set) in + Generator.Plain {workload = size; closure} +end + +let () = Registration.register (module Set_add) + +(** Cost model and benchmarks for set elements from the + OCaml stdlib. + + The cost model is not currently used + in the protocol, but we include the benchmarks to validate our + assumptions about functions that use this. *) +module Set_elements : Benchmark.S = struct + let name = ns "Set_elements" + + let info = "Benchmarks and cost model for set elements from OCaml stdlib." + + let module_filename = __FILE__ + + let purpose = + Benchmark.Other_purpose + "Validate assumptions about functions using Set.elements." + + let group = Benchmark.Group "global_constants" + + let tags = ["global_constants"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector : workload -> Sparse_vec.String.t = + fun size -> Sparse_vec.String.of_list [("size", float_of_int size)] + + (* Cost of retrieving all elements from the set is linear with the size + of the set.*) + let model = Model.(make ~conv:(fun size -> (size, ())) linear) + + module Int_set = Set.Make (Int) + + let create_benchmark ~rng_state _config = + let range : Base_samplers.range = {min = 0; max = 10_000} in + let size = Base_samplers.sample_in_interval ~range rng_state in + let set = Stdlib.List.init size (fun x -> x) |> Int_set.of_list in + let closure () = ignore (Int_set.elements set) in + Generator.Plain {workload = size; closure} +end + +let () = Registration.register (module Set_elements) + +(** Cost model and benchmarks for [Script_expr_hash.of_b58_check_opt]. + Under the hood this function uses the [Blake2b] functor, which uses + the HACL* crypto library. + + The cost model is not currently used + in the protocol, but we include the benchmarks to validate our + assumptions about functions that use this. *) +module Script_expr_hash_of_b58check_opt : Benchmark.S = struct + let name = ns "Script_expr_hash_of_b58check_opt" + + let info = "Benchmark for Script_expr_hash.of_b58check_opt" + + let module_filename = __FILE__ + + let purpose = + Benchmark.Other_purpose + "Validate assumptions about functions using \ + Script_expr_hash.of_b58check_opt." + + let group = Benchmark.Group "script_expr_hash" + + let tags = ["global_constants"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = Micheline_sampler.size + + let workload_encoding = + let open Data_encoding in + conv + (fun Micheline_sampler.{nodes; bytes} -> (nodes, bytes)) + (fun (nodes, bytes) -> {nodes; bytes}) + (obj2 (req "nodes" int31) (req "bytes" int31)) + + let workload_to_vector Micheline_sampler.{nodes; bytes} = + Sparse_vec.String.of_list + [("nodes", float_of_int nodes); ("bytes", float_of_int bytes)] + + (* On testing we found that this function is a constant + time operation. However, to test this, we use an affine model. If + our assumption holds, the coefficient should be near zero. *) + let model = + Model.(make ~conv:(fun Micheline_sampler.{nodes; _} -> (nodes, ())) affine) + + (* To create realistic benchmarks, we generate a random Micheline expression, + hash it, then benchmark the cost of validating the hash. *) + let create_benchmark ~rng_state _config = + let open Protocol in + let term = Micheline_sampler.sample rng_state in + let size = Micheline_sampler.micheline_size term in + let expr_encoding = Alpha_context.Script.expr_encoding in + let lazy_expr = + Data_encoding.make_lazy expr_encoding (Micheline.strip_locations term) + in + let expr_bytes = Data_encoding.force_bytes lazy_expr in + let hash = Script_expr_hash.hash_bytes [expr_bytes] in + let hash_str = Script_expr_hash.to_b58check hash in + let closure () = ignore (Script_expr_hash.of_b58check_opt hash_str) in + Generator.Plain {workload = size; closure} +end + +let () = Registration.register (module Script_expr_hash_of_b58check_opt) + +module Global_constants_storage_expr_to_address_in_context : Benchmark.S = +struct + let name = ns "expr_to_address_in_context" + + let info = + "Benchmark for the \ + Global_constants_storage.Internal_for_tests.expr_to_address_in_context \ + function" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "global_constants" + + let group = Benchmark.Group "global_constants" + + let tags = ["global_constants"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector : workload -> Sparse_vec.String.t = + fun size -> Sparse_vec.String.of_list [("size", float_of_int size)] + + (** The cost of a Blake2b hashing function is linear with the size of the input *) + let model = Model.(make ~conv:(fun size -> (size, ())) linear) + + let create_benchmark ~rng_state _config = + let open Micheline in + let expr = Micheline_sampler.sample rng_state |> strip_locations in + let b = + Script_repr.lazy_expr expr |> Script_repr.force_bytes + |> Environment.wrap_tzresult |> assert_ok + in + let size = Bytes.length b in + + let closure () = ignore (Script_expr_hash.hash_bytes [b]) in + Generator.Plain {workload = size; closure} +end + +let () = + Registration.register + (module Global_constants_storage_expr_to_address_in_context) + +(** [Global_constants_storage.expand] traverses a Micheline node, + searching for constants and replacing them with their values + retrieved from storage. + + There are three branches in the iterations of [Global_constants_storage.expand] + can take, each with different costs: + - Branch 1: The first time a particular constant is found, the hash is parsed with + [Script_expr_hash.of_b58check_opt], and its value is retrieved + from storage. This storage call (implemented [Global_constants_storage.get]) + is already carbonated and dominates the cost in this case, so do not need to + benchmark Branch 1 - the benchmarks for storage access are sufficient. + - Branch 2: If the same constant is found a subsequent time, its value is looked up + in a map. On testing we determined that the cost of [Script_expr_hash.of_b58check_opt] + dominates the cost of this branch - the cost of an OCaml map lookup is O(log 2 n), and + n has to be unreasonably large to catch up to the constant time cost of validating the + hash. + - Branch 3: When no constant is found, the cost is merely that of pattern matching + and calling the continuation (similar to that of [Micheline.strip_locations]). + + Because we don't know the full size of node being traversed ahead of time (because they + are retrieved from storage), it is impossible to calculate the full gas cost upfront. + However, each time we find a new expression to traverse, we can calculate its size upfront + and charge the cost of all Branch 3 cases. We can then do an additional charge for Branch 2 + each time we find a constant, and let storage handle charging for Branch 1. + + Below are models for Branch 2 and 3 respectively. + *) +module Global_constants_storage_expand_models = struct + module Global_constants_storage_expand_constant_branch : Benchmark.S = struct + let name = ns "expand_constant_branch" + + let info = + "Benchmark for the constant branch Global_constants_storage.expand \ + function" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "global_constants" + + let group = Benchmark.Group "global_constants" + + let tags = ["global_constants"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector : workload -> Sparse_vec.String.t = + fun constants -> + Sparse_vec.String.of_list + [("number_of_constants", float_of_int constants)] + + (** The cost of Branch 2 is linear to the number of constants in the expression. As + discussed above, the constant time operation [Script_expr_hash.of_b58check_opt] + dominates the cost of each iteration. *) + let model = Model.(make ~conv:(fun size -> (size, ())) linear) + + (* To test Branch 2 as nearly as possible, we generate a Micheline Seq + consisting of the same constant repeated n times. As n increases, + the benchmark more closely approximates the true cost of Branch 2. *) + let create_benchmark ~rng_state _config = + let open Lwt_syntax in + let open Micheline in + let node = Micheline_sampler.sample rng_state in + let size = (Micheline_sampler.micheline_size node).nodes in + let registered_constant = Int (-1, Z.of_int 1) in + let hash = registered_constant |> node_to_hash in + let context, _ = Execution_context.make ~rng_state () |> assert_ok_lwt in + let context, _, _ = + (let+ result = + Alpha_context.Global_constants_storage.register + context + (strip_locations registered_constant) + in + Environment.wrap_tzresult result) + |> assert_ok_lwt + in + let node = seq_of_n_constants size hash in + let closure () = + ignore + (Lwt_main.run + @@ Alpha_context.Global_constants_storage.expand + context + (strip_locations node)) + in + Generator.Plain {workload = size; closure} + end + + let () = + Registration.register + (module Global_constants_storage_expand_constant_branch) + + module Global_constants_storage_expand_no_constant_branch : Benchmark.S = + struct + let name = ns "expand_no_constant_branch" + + let info = + "Benchmark for the Global_constants_storage.expand function on the case \ + without constants" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "global_constants" + + let group = Benchmark.Group "global_constants" + + let tags = ["global_constants"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector : workload -> Sparse_vec.String.t = + fun size -> + Sparse_vec.String.of_list [("number_of_nodes", float_of_int size)] + + (* The cost of Branch 3 is the cost of traversing a single node. It + is therefore linear to the number of nodes being traversed. This is + very similar to [Micheline.strip_locations]. + + On testing I observed that while the linear model was accurate + for small numbers of nodes, after 1000 nodes the cost seems to increase more + than linearly. I think I would have to fine tune the sampler to better test + past this amount; however, I don't think it's necessary - to get large orders + of nodes, you need to use constants, in which case the cost of + [Script_expr_hash.of_b58check_opt] will dominate. A n*log(n) model seems + accurate enough for the range of values tested. + *) + let model = Model.(make ~conv:(fun size -> (size, ())) nlogn) + + (** We benchmark this by generating a random Micheline expression without constants + and calling [expand] on it. This causes the function to spend all its time in + Branch 3. *) + let create_benchmark ~rng_state _config = + let open Micheline in + let node = Micheline_sampler.sample rng_state in + let size = (Micheline_sampler.micheline_size node).nodes in + let context, _ = Execution_context.make ~rng_state () |> assert_ok_lwt in + let expr = strip_locations node in + let closure () = + ignore + (Lwt_main.run + @@ Alpha_context.Global_constants_storage.expand context expr) + in + Generator.Plain {workload = size; closure} + end + + let () = + Registration.register + (module Global_constants_storage_expand_no_constant_branch) +end diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_benchmarks.ml new file mode 100644 index 000000000000..ed15db1546c9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_benchmarks.ml @@ -0,0 +1,4203 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let ns = Interpreter_model.ns + +let fv = Interpreter_model.fv + +module Timelock_samplers = Tezos_crypto.Timelock +open Protocol + +(* ------------------------------------------------------------------------- *) + +type ex_stack_and_kinstr = + | Ex_stack_and_kinstr : { + stack : 'a * 'b; + stack_type : ('a, 'b) Script_typed_ir.stack_ty; + kinstr : ('a, 'b, 'c, 'd) Script_typed_ir.kinstr; + } + -> ex_stack_and_kinstr + +type ex_stack_and_continuation = + | Ex_stack_and_cont : { + stack : 'a * 'b; + stack_type : ('a, 'b) Script_typed_ir.stack_ty; + cont : ('a, 'b, 'c, 'd) Script_typed_ir.continuation; + } + -> ex_stack_and_continuation + +type ex_value = + | Ex_value : {value : 'a; ty : ('a, _) Script_typed_ir.ty} -> ex_value + +type benchmark_type = Registration_helpers.benchmark_type = Time | Alloc + +let gas_unit_per_allocation_word = 4 + +(* ------------------------------------------------------------------------- *) + +let sf = Printf.sprintf + +(* End of Stack *) +let eos = Script_typed_ir.(EmptyCell, EmptyCell) + +let info_and_name ~benchmark_type ~intercept ?(salt = "") s = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6072 + Time benchmarks should be qualified with "time" when we switch to time-alloc cost model + *) + let s = s ^ salt in + + let info = + let type_str = + match benchmark_type with + | Time -> "Time benchmark" + | Alloc -> "Allocation benchmark" + in + let intercept_str = if intercept then " (intercept case)" else "" in + sf "%s %s%s" type_str s intercept_str + in + + let benchmark_type = + match benchmark_type with Time -> [] | Alloc -> ["alloc"] + in + let intercept = if intercept then ["intercept"] else [] in + let name = s :: (benchmark_type @ intercept) in + + let rec make_name ns = function + | [] -> assert false + | [s] -> ns s + | s :: ss -> make_name (Namespace.make ns s) ss + in + + (info, make_name ns name) + +module Default_boilerplate = struct + type workload = Interpreter_workload.t + + let workload_encoding = Interpreter_workload.encoding + + let workload_to_vector = Interpreter_workload.trace_to_sparse_vec + + let tags = [Tags.interpreter] +end + +module Default_config = struct + (* Configuration specific to sapling benchmarks *) + type sapling_config = {sapling_txs_file : string; seed : int option} + + (* Configuration specific to benchmarking Dign/Dipn/Dupn/Dropn/Combs *) + type comb_config = {max_depth : int} + + (* Configuration specific to benchmarking ICompare *) + type compare_config = {type_size : Base_samplers.range} + + type config = { + sampler : Michelson_samplers.parameters; + sapling : sapling_config; + comb : comb_config; + compare : compare_config; + } + + let default_config = + let open Michelson_samplers in + let open Michelson_samplers_base in + let sampler = + { + base_parameters = + { + int_size = {min = 8; max = 100_000}; + string_size = {min = 1 lsl 10; max = 1 lsl 17}; + bytes_size = {min = 1 lsl 10; max = 1 lsl 17}; + }; + list_size = {min = 10; max = 1000}; + set_size = {min = 10; max = 1000}; + map_size = {min = 10; max = 1000}; + } + in + { + sampler; + sapling = {sapling_txs_file = {|/no/such/file|}; seed = None}; + comb = {max_depth = 1000}; + compare = {type_size = {min = 1; max = 15}}; + } + + let sapling_config_encoding = + let open Data_encoding in + conv + (fun {sapling_txs_file; seed} -> (sapling_txs_file, seed)) + (fun (sapling_txs_file, seed) -> {sapling_txs_file; seed}) + (obj2 (req "sapling_txs_file" string) (req "seed" (option int31))) + + let comb_config_encoding = + let open Data_encoding in + conv + (fun {max_depth} -> max_depth) + (fun max_depth -> {max_depth}) + (obj1 (req "max_depth" int31)) + + let compare_config_encoding = + let open Data_encoding in + conv + (fun {type_size} -> type_size) + (fun type_size -> {type_size}) + (obj1 (req "type_size" Base_samplers.range_encoding)) + + let config_encoding = + let open Data_encoding in + conv + (fun {sampler; sapling; comb; compare} -> + (sampler, sapling, comb, compare)) + (fun (sampler, sapling, comb, compare) -> + {sampler; sapling; comb; compare}) + (obj4 + (req "sampler" Michelson_samplers.parameters_encoding) + (req "sapling" sapling_config_encoding) + (req "comb" comb_config_encoding) + (req "compare" compare_config_encoding)) +end + +let make_default_samplers ?(algo = `Default) cfg : + (module Crypto_samplers.Finite_key_pool_S) * (module Michelson_samplers.S) = + let module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct + let size = 16 + + let algo = algo + end) in + let module Michelson_samplers = + Michelson_samplers.Make + (struct + let parameters = cfg + end) + (Crypto_samplers) + in + ((module Crypto_samplers), (module Michelson_samplers)) + +(* ------------------------------------------------------------------------- *) +(* Helpers for creating benchmarks for the interpreter *) + +(* Register only a model for code generation *) +let register_model_for_code_generation model = + let model = Model.make ~conv:Fun.id model in + Registration.register_model_for_code_generation + "interpreter" + model + ~destination:"michelson_v1_gas" + +let register_time_alloc_codegen_model instr_or_cont_name = + let (Model.Model codegen_model) = + Interpreter_model.make_time_alloc_codegen_model instr_or_cont_name + in + register_model_for_code_generation codegen_model + +let prepare_workload ?amplification ctxt step_constants stack_type kinstr stack + = + let workload = + Interpreter_workload.extract_deps + ctxt + step_constants + stack_type + kinstr + stack + in + match amplification with + | None -> workload + | Some n -> List.repeat n workload |> List.flatten + +let time_benchmark_from_kinstr_and_stack : + ?amplification:int -> + Alpha_context.context -> + Protocol.Script_interpreter.step_constants -> + ex_stack_and_kinstr -> + Interpreter_workload.ir_sized_step list Generator.benchmark = + fun ?amplification ctxt step_constants stack_kinstr -> + let ctxt = Gas_helpers.set_limit ctxt in + let (Ex_stack_and_kinstr {stack = bef_top, bef; stack_type; kinstr}) = + stack_kinstr + in + let workload = + prepare_workload + ?amplification + ctxt + step_constants + stack_type + kinstr + (bef_top, bef) + in + let _gas_counter, outdated_ctxt = + Local_gas_counter.local_gas_counter_and_outdated_context ctxt + in + + let closure = + match amplification with + | None -> + let closure () = + (* Lwt_main.run *) + ignore + (Script_interpreter.Internals.step + (outdated_ctxt, step_constants) + (Local_gas_counter 9_999_999_999) + kinstr + bef_top + bef) + in + closure + | Some amplification_factor -> + assert (amplification_factor > 0) ; + let closure () = + for _i = 1 to amplification_factor do + ignore + (* Lwt_main.run *) + (Script_interpreter.Internals.step + (outdated_ctxt, step_constants) + (Local_gas_counter 9_999_999_999) + kinstr + bef_top + bef) + done + in + closure + in + Generator.Plain {workload; closure} + +let alloc_benchmark_from_kinstr_and_stack : + Alpha_context.context -> + Protocol.Script_interpreter.step_constants -> + ex_stack_and_kinstr -> + Interpreter_workload.ir_sized_step list Generator.benchmark = + fun ctxt step_constants stack_kinstr -> + let ctxt = Gas_helpers.set_limit ctxt in + let (Ex_stack_and_kinstr {stack = bef_top, bef; stack_type; kinstr}) = + stack_kinstr + in + let workload = + prepare_workload ctxt step_constants stack_type kinstr (bef_top, bef) + in + let _gas_counter, outdated_ctxt = + Local_gas_counter.local_gas_counter_and_outdated_context ctxt + in + + let measure () = + let result = + Lwt_main.run + @@ Script_interpreter.Internals.step + (outdated_ctxt, step_constants) + (Local_gas_counter 9_999_999_999) + kinstr + bef_top + bef + in + Result.fold + ~error:(fun _ -> 0.0) + ~ok:(fun (stack_top, stack, _, _) -> + let size_after = + Obj.reachable_words (Obj.repr (stack_top, stack, bef_top, bef)) + in + let size_before = + Obj.reachable_words (Obj.repr (bef_top, bef, bef_top, bef)) + in + + float_of_int ((size_after - size_before) * gas_unit_per_allocation_word)) + result + in + + Generator.Calculated {workload; measure} + +let benchmark_from_kinstr_and_stack : + ?amplification:int -> + benchmark_type -> + Alpha_context.context -> + Protocol.Script_interpreter.step_constants -> + ex_stack_and_kinstr -> + Interpreter_workload.ir_sized_step list Generator.benchmark = + fun ?amplification benchmark_type -> + match benchmark_type with + | Time -> time_benchmark_from_kinstr_and_stack ?amplification + | Alloc -> + (* amplification wouldn't make sense, + because the measurement resolution doesn't matter for the allocation *) + assert (amplification = None) ; + alloc_benchmark_from_kinstr_and_stack + +let time_and_alloc (f : benchmark_type -> unit) = + f Time ; + f Alloc + +let make_benchmark : + ?amplification:int -> + ?intercept:bool -> + ?salt:string -> + ?more_tags:string list -> + ?check:(unit -> unit) -> + name:Interpreter_workload.instruction_name -> + benchmark_type:benchmark_type -> + kinstr_and_stack_sampler: + (Default_config.config -> Random.State.t -> unit -> ex_stack_and_kinstr) -> + unit -> + Benchmark.t = + fun ?amplification + ?(intercept = false) + ?salt + ?(more_tags = []) + ?(check = fun () -> ()) + ~name + ~benchmark_type + ~kinstr_and_stack_sampler + () -> + let module B : Benchmark.S = struct + include Default_config + include Default_boilerplate + + let tags = tags @ more_tags + + let models = + (* [intercept = true] implies there's a benchmark with [intercept = false]. + No need to register the model twice. *) + Interpreter_model.make_model + benchmark_type + ?amplification + (Instr_name name) + + let info, name = + info_and_name + ~benchmark_type + ~intercept + ?salt + (Interpreter_workload.string_of_instruction_name name) + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let benchmark kinstr_and_stack_sampler ctxt step_constants () = + let stack_instr = kinstr_and_stack_sampler () in + benchmark_from_kinstr_and_stack + ?amplification + benchmark_type + ctxt + step_constants + stack_instr + + let create_benchmarks ~rng_state ~bench_num (config : config) = + check () ; + match Lwt_main.run (Execution_context.make ~rng_state ()) with + | Error _errs -> assert false + | Ok (ctxt, step_constants) -> + let kinstr_and_stack_sampler = + kinstr_and_stack_sampler config rng_state + in + List.repeat + bench_num + (benchmark kinstr_and_stack_sampler ctxt step_constants) + end in + (module B : Benchmark.S) + +let make_simple_benchmark : + type bef_top bef res_top res. + ?amplification:int -> + ?intercept:bool -> + ?more_tags:string list -> + ?salt:string -> + ?check:(unit -> unit) -> + name:Interpreter_workload.instruction_name -> + benchmark_type:benchmark_type -> + stack_type:(bef_top, bef) Script_typed_ir.stack_ty -> + kinstr:(bef_top, bef, res_top, res) Script_typed_ir.kinstr -> + unit -> + Benchmark.t = + fun ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~stack_type + ~kinstr + () -> + let kinstr_and_stack_sampler config rng_state = + let _, (module Samplers) = + make_default_samplers config.Default_config.sampler + in + fun () -> + Ex_stack_and_kinstr + { + stack = Samplers.Random_value.stack stack_type rng_state; + stack_type; + kinstr; + } + in + make_benchmark + ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~kinstr_and_stack_sampler + () + +let benchmark ?(benchmark_type = Time) ?amplification ?intercept ?more_tags + ?salt ?check ~name ~kinstr_and_stack_sampler () = + let bench = + make_benchmark + ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~kinstr_and_stack_sampler + () + in + Registration_helpers.register ~benchmark_type bench + +let time_alloc_benchmark ?amplification ?intercept ?more_tags ?salt ?check ~name + ~kinstr_and_stack_sampler () = + benchmark + ~benchmark_type:Time + ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~kinstr_and_stack_sampler + () ; + benchmark + ~benchmark_type:Alloc + ?intercept + ?more_tags + ?salt + ?check + ~name + ~kinstr_and_stack_sampler + () ; + register_time_alloc_codegen_model (Instr_name name) + +let benchmark_with_stack_sampler ?(benchmark_type = Time) ?amplification + ?intercept ?more_tags ?salt ?check ~stack_type ~name ~kinstr ~stack_sampler + () = + let kinstr_and_stack_sampler config rng_state = + let stack_sampler = stack_sampler config rng_state in + fun () -> Ex_stack_and_kinstr {stack = stack_sampler (); stack_type; kinstr} + in + let bench = + make_benchmark + ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~kinstr_and_stack_sampler + () + in + Registration_helpers.register ~benchmark_type bench + +let benchmark_with_fixed_stack ?(benchmark_type = Time) ?amplification + ?intercept ?more_tags ?salt ?check ~name ~stack_type ~stack ~kinstr () = + benchmark_with_stack_sampler + ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~stack_type + ~benchmark_type + ~kinstr + ~stack_sampler:(fun _cfg _rng_state () -> stack) + () + +let time_alloc_benchmark_with_fixed_stack ?amplification ?intercept ?more_tags + ?salt ?check ~name ~stack_type ~stack ~kinstr () = + benchmark_with_fixed_stack + ~benchmark_type:Time + ?amplification + ?intercept + ?more_tags + ?salt + ?check + ~name + ~stack_type + ~stack + ~kinstr + () ; + benchmark_with_fixed_stack + ~benchmark_type:Alloc + ?intercept + ?more_tags + ?salt + ?check + ~name + ~stack_type + ~stack + ~kinstr + () ; + register_time_alloc_codegen_model (Instr_name name) + +let simple_benchmark_with_stack_sampler ?(benchmark_type = Time) ?amplification + ?intercept_stack ?salt ?more_tags ?check ~name ~stack_type ~kinstr + ~stack_sampler () = + benchmark_with_stack_sampler + ?amplification + ~intercept:false + ?salt + ?more_tags + ?check + ~name + ~benchmark_type + ~stack_type + ~kinstr + ~stack_sampler + () ; + Option.iter + (fun stack -> + benchmark_with_fixed_stack + ?amplification + ~intercept:true + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~stack_type + ~stack + ~kinstr + ()) + intercept_stack + +let simple_time_alloc_benchmark_with_stack_sampler ?amplification + ?intercept_stack ?(alloc_intercept = true) ?salt ?more_tags ?check ~name + ~stack_type ~kinstr ~stack_sampler () = + simple_benchmark_with_stack_sampler + ~benchmark_type:Time + ?amplification + ?intercept_stack + ?salt + ?more_tags + ?check + ~name + ~stack_type + ~kinstr + ~stack_sampler + () ; + simple_benchmark_with_stack_sampler + ~benchmark_type:Alloc + ?intercept_stack:(if alloc_intercept then intercept_stack else None) + ?salt + ?more_tags + ?check + ~name + ~stack_type + ~kinstr + ~stack_sampler + () ; + register_time_alloc_codegen_model (Instr_name name) + +let simple_benchmark ?(benchmark_type = Time) ?amplification ?intercept_stack + ?more_tags ?salt ?check ~name ~stack_type ~kinstr () = + let bench = + make_simple_benchmark + ?amplification + ~intercept:false + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~stack_type + ~kinstr + () + in + Registration_helpers.register ~benchmark_type bench ; + Option.iter + (fun stack -> + benchmark_with_fixed_stack + ?amplification + ~intercept:true + ?more_tags + ?salt + ?check + ~name + ~benchmark_type + ~stack_type + ~stack + ~kinstr + ()) + intercept_stack + +let simple_time_alloc_benchmark ?amplification ?intercept_stack ?more_tags ?salt + ?check ~name ~stack_type ~kinstr () = + simple_benchmark + ~benchmark_type:Time + ?amplification + ?intercept_stack + ?more_tags + ?salt + ?check + ~name + ~stack_type + ~kinstr + () ; + simple_benchmark + ~benchmark_type:Alloc + ?intercept_stack + ?more_tags + ?salt + ?check + ~name + ~stack_type + ~kinstr + () ; + register_time_alloc_codegen_model (Instr_name name) + +(* ------------------------------------------------------------------------- *) +(* Helpers for creating benchmarks for [Script_interpreter.next] *) + +let time_benchmark_from_continuation : + ?amplification:int -> + Alpha_context.context -> + Protocol.Script_interpreter.step_constants -> + ex_stack_and_continuation -> + Interpreter_workload.ir_sized_step list Generator.benchmark = + fun ?amplification ctxt step_constants stack_cont -> + let ctxt = Gas_helpers.set_limit ctxt in + match stack_cont with + | Ex_stack_and_cont {stack = bef_top, bef; cont; stack_type} -> + let workload, closure = + match amplification with + | None -> + let workload = + Interpreter_workload.extract_deps_continuation + ctxt + step_constants + stack_type + cont + (bef_top, bef) + in + let _gas_counter, outdated_ctxt = + Local_gas_counter.local_gas_counter_and_outdated_context ctxt + in + let closure () = + ignore + (* Lwt_main.run *) + (Script_interpreter.Internals.next + None + (outdated_ctxt, step_constants) + (Local_gas_counter 9_999_999_999) + stack_type + cont + bef_top + bef) + in + (workload, closure) + | Some amplification_factor -> + assert (amplification_factor > 0) ; + let workload = + Interpreter_workload.extract_deps_continuation + ctxt + step_constants + stack_type + cont + (bef_top, bef) + in + let workload = + List.repeat amplification_factor workload |> List.flatten + in + let _gas_counter, outdated_ctxt = + Local_gas_counter.local_gas_counter_and_outdated_context ctxt + in + let closure () = + for _i = 1 to amplification_factor do + ignore + (* Lwt_main.run *) + (Script_interpreter.Internals.next + None + (outdated_ctxt, step_constants) + (Local_gas_counter 9_999_999_999) + stack_type + cont + bef_top + bef) + done + in + (workload, closure) + in + Generator.Plain {workload; closure} + +let alloc_benchmark_from_continuation : + Alpha_context.context -> + Protocol.Script_interpreter.step_constants -> + ex_stack_and_continuation -> + Interpreter_workload.ir_sized_step list Generator.benchmark = + fun ctxt step_constants stack_cont -> + let ctxt = Gas_helpers.set_limit ctxt in + let (Ex_stack_and_cont {stack = bef_top, bef; cont; stack_type}) = + stack_cont + in + let workload = + Interpreter_workload.extract_deps_continuation + ctxt + step_constants + stack_type + cont + (bef_top, bef) + in + let _gas_counter, outdated_ctxt = + Local_gas_counter.local_gas_counter_and_outdated_context ctxt + in + let measure () = + let result = + Lwt_main.run + @@ Script_interpreter.Internals.next + None + (outdated_ctxt, step_constants) + (Local_gas_counter 9_999_999_999) + stack_type + cont + bef_top + bef + in + Result.fold + ~error:(fun _ -> 0.0) + ~ok:(fun (stack_top, stack, _, _) -> + let size_after = + Obj.reachable_words (Obj.repr (stack_top, stack, bef_top, bef, cont)) + in + let size_before = + Obj.reachable_words (Obj.repr (bef_top, bef, bef_top, bef, cont)) + in + + float_of_int ((size_after - size_before) * gas_unit_per_allocation_word)) + result + in + Generator.Calculated {workload; measure} + +let benchmark_from_continuation : + ?amplification:int -> + benchmark_type -> + Alpha_context.context -> + Protocol.Script_interpreter.step_constants -> + ex_stack_and_continuation -> + Interpreter_workload.ir_sized_step list Generator.benchmark = + fun ?amplification benchmark_type -> + match benchmark_type with + | Time -> time_benchmark_from_continuation ?amplification + | Alloc -> + (* amplification wouldn't make sense, + because the measurement resolution doesn't matter for the allocation *) + assert (amplification = None) ; + alloc_benchmark_from_continuation + +let make_continuation_benchmark : + ?amplification:int -> + ?intercept:bool -> + ?salt:string -> + ?more_tags:string list -> + ?check:(unit -> unit) -> + name:Interpreter_workload.continuation_name -> + benchmark_type:benchmark_type -> + cont_and_stack_sampler: + (Default_config.config -> + Random.State.t -> + unit -> + ex_stack_and_continuation) -> + unit -> + Benchmark.t = + fun ?amplification + ?(intercept = false) + ?salt + ?(more_tags = []) + ?(check = fun () -> ()) + ~name + ~benchmark_type + ~cont_and_stack_sampler + () -> + let module B : Benchmark.S = struct + include Default_config + include Default_boilerplate + + let tags = tags @ more_tags + + let models = + Interpreter_model.make_model + benchmark_type + ?amplification + (Cont_name name) + + let info, name = + info_and_name + ~benchmark_type + ~intercept + ?salt + (Interpreter_workload.string_of_continuation_name name) + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let benchmark cont_and_stack_sampler ctxt step_constants () = + let stack_instr = cont_and_stack_sampler () in + benchmark_from_continuation + ?amplification + benchmark_type + ctxt + step_constants + stack_instr + + let create_benchmarks ~rng_state ~bench_num (config : config) = + check () ; + match Lwt_main.run (Execution_context.make ~rng_state ()) with + | Error _errs -> assert false + | Ok (ctxt, step_constants) -> + let cont_and_stack_sampler = + cont_and_stack_sampler config rng_state + in + List.repeat + bench_num + (benchmark cont_and_stack_sampler ctxt step_constants) + end in + (module B : Benchmark.S) + +let continuation_benchmark ?(benchmark_type = Time) ?amplification ?intercept + ?salt ?more_tags ?check ~name ~cont_and_stack_sampler () = + let bench = + make_continuation_benchmark + ?amplification + ?intercept + ?salt + ?more_tags + ?check + ~name + ~benchmark_type + ~cont_and_stack_sampler + () + in + Registration_helpers.register ~benchmark_type bench + +let continuation_time_alloc_benchmark ?amplification ?intercept ?salt ?more_tags + ?check ~name ~cont_and_stack_sampler () = + continuation_benchmark + ?amplification + ?intercept + ?salt + ?more_tags + ?check + ~name + ~benchmark_type:Time + ~cont_and_stack_sampler + () ; + continuation_benchmark + ?intercept + ?salt + ?more_tags + ?check + ~name + ~benchmark_type:Alloc + ~cont_and_stack_sampler + () ; + register_time_alloc_codegen_model (Cont_name name) + +(* ------------------------------------------------------------------------- *) +(* Sampling helpers *) + +let nat_of_positive_int (i : int) = + let open Script_int in + match is_nat (of_int i) with None -> assert false | Some x -> x + +let adversarial_ints rng_state (cfg : Default_config.config) n = + let _common_prefix, ls = + Base_samplers.Adversarial.integers + ~prefix_size:cfg.sampler.base_parameters.int_size + ~card:n + rng_state + in + List.map Script_int.of_zint ls + +(* ------------------------------------------------------------------------- *) +(* Error helpers *) + +let raise_if_error = function + | Ok x -> x + | Error e -> + Format.eprintf "%a@." (Error_monad.TzTrace.pp_print Error_monad.pp) e ; + Stdlib.failwith "raise_if_error" + +(* ------------------------------------------------------------------------- *) + +(** [Registration_section] contains all interpreter benchmarks. The goal of + a benchmark is to gather enough data to reliably estimate the parameters + of the cost model associated to each instruction. In general, it can + take several distinct benchmarks to properly cover all the execution + paths. + + In particular, for affine cost model, it is often worth estimating the + intercept separately from the size-dependent coefficients. + *) + +module Registration_section = struct + open Script_typed_ir + open Michelson_types + + let sf = Printf.sprintf + + let dummy_loc = 0 + + let halt = IHalt dummy_loc + + let () = + (* KHalt *) + simple_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_IHalt + ~stack_type:(unit @$ bot) + ~kinstr:halt + () + + module Amplification = struct + module Loop : Benchmark.S = struct + let name = ns "amplification_loop" + + let info = "Benchmarking the cost of an empty loop" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let tags = [Tags.interpreter] + + type config = {max_iterations : int} + + let config_encoding = + let open Data_encoding in + conv + (fun {max_iterations} -> max_iterations) + (fun max_iterations -> {max_iterations}) + (obj1 (req "max_iterations" int31)) + + let default_config = {max_iterations = 100000} + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector n = + Sparse_vec.String.of_list [("iterations", float_of_int n)] + + let models = [("interpreter", Interpreter_model.amplification_loop_model)] + + let benchmark rng_state config () = + let workload = Random.State.int rng_state config.max_iterations in + let closure () = + for _i = 1 to workload do + Sys.opaque_identity () + done + in + Generator.Plain {workload; closure} + + let create_benchmarks ~rng_state ~bench_num (config : config) = + List.repeat bench_num (benchmark rng_state config) + end + end + + let () = Registration_helpers.register (module Amplification.Loop) + + module Stack = struct + let () = + (* KDrop ; KHalt *) + simple_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_IDrop + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(IDrop (dummy_loc, halt)) + () + + let () = + (* IDup ; IHalt *) + simple_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_IDup + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(IDup (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_ISwap + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(ISwap (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_IPush + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(IPush (dummy_loc, unit, (), halt)) + () + + let () = + simple_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_IUnit + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(IUnit (dummy_loc, halt)) + () + + (* deep stack manipulation *) + + (* Constructing these instructions is made especially painful by the + fact that they include "stack preservation witnesses", which are not + exposed in Script_ir_translator. + We must go through [Script_ir_translator.parse_instr] to construct + the corresponding terms. *) + type ex_stack = + | Ex_stack : ('a, 'b) Script_typed_ir.stack_ty * ('a * 'b) -> ex_stack + + let rec make_stack (depth : int) = + if depth = 0 then assert false + else if depth = 1 then Ex_stack (unit @$ Script_typed_ir.Bot_t, ((), eos)) + else + let stack = make_stack (depth - 1) in + match stack with + | Ex_stack (stack_ty, stack) -> Ex_stack (unit @$ stack_ty, ((), stack)) + + let parse_instr rng_state node stack = + let open Lwt_result_syntax in + match stack with + | Ex_stack (stack_ty, stack) -> + raise_if_error + (Lwt_main.run + (let* ctxt, _step_constants = + Execution_context.make ~rng_state () + in + let* judgement, _ = + let*! result = + Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf: + (Script_ir_translator_config.make ~legacy:false ()) + node + stack_ty + in + Lwt.return (Environment.wrap_tzresult result) + in + match judgement with + | Script_ir_translator.Typed descr -> + let kinstr = descr.instr.apply (IHalt dummy_loc) in + return + (Ex_stack_and_kinstr + {stack; kinstr; stack_type = descr.bef}) + | Script_ir_translator.Failed _ -> assert false)) + + open Protocol.Michelson_v1_primitives + + (* The size parameter of a deep stack instruction must fit on 10 bits. See + [Script_ir_translator.parse_uint10]. *) + let stack_size = 1023 + + let long_stack = make_stack stack_size + + let sample_depth rng_state = + Base_samplers.( + sample_in_interval rng_state ~range:{min = 0; max = stack_size - 2}) + + let () = + let dig = Micheline.(Prim (0, I_DIG, [Int (0, Z.of_int 0)], [])) in + benchmark + ~amplification:100 + ~intercept:true + ~name:Interpreter_workload.N_IDig + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dig in + parse_instr rng_state node long_stack) + () + + let () = + let dig n = Micheline.(Prim (0, I_DIG, [Int (0, Z.of_int n)], [])) in + time_alloc_benchmark + ~name:Interpreter_workload.N_IDig + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dig (sample_depth rng_state) in + parse_instr rng_state node long_stack) + () + + let () = + let dug = Micheline.(Prim (0, I_DUG, [Int (0, Z.of_int 0)], [])) in + benchmark + ~intercept:true + ~name:Interpreter_workload.N_IDug + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dug in + parse_instr rng_state node long_stack) + () + + let () = + let dug n = Micheline.(Prim (0, I_DUG, [Int (0, Z.of_int n)], [])) in + time_alloc_benchmark + ~name:Interpreter_workload.N_IDug + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dug (sample_depth rng_state) in + parse_instr rng_state node long_stack) + () + + let () = + let nop = Micheline.Seq (0, []) in + let dip = Micheline.(Prim (0, I_DIP, [Int (0, Z.of_int 0); nop], [])) in + benchmark + ~intercept:true + ~name:Interpreter_workload.N_IDipN + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dip in + parse_instr rng_state node long_stack) + () + + let () = + let nop = Micheline.Seq (0, []) in + let dip n = Micheline.(Prim (0, I_DIP, [Int (0, Z.of_int n); nop], [])) in + time_alloc_benchmark + ~name:Interpreter_workload.N_IDipN + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dip (sample_depth rng_state) in + parse_instr rng_state node long_stack) + () + + let () = + let drop = Micheline.(Prim (0, I_DROP, [Int (0, Z.of_int 0)], [])) in + benchmark + ~intercept:true + ~name:Interpreter_workload.N_IDropN + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = drop in + parse_instr rng_state node long_stack) + () + + let () = + let drop n = Micheline.(Prim (0, I_DROP, [Int (0, Z.of_int n)], [])) in + time_alloc_benchmark + ~name:Interpreter_workload.N_IDropN + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = drop (sample_depth rng_state) in + parse_instr rng_state node long_stack) + () + + let () = + let pair n = Micheline.(Prim (0, I_PAIR, [Int (0, Z.of_int n)], [])) in + ( time_and_alloc @@ fun benchmark_type -> + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_IComb + ~kinstr_and_stack_sampler:(fun cfg rng_state () -> + let width = + Base_samplers.( + sample_in_interval + rng_state + ~range:{min = 2; max = cfg.comb.max_depth}) + in + let node = pair width in + parse_instr rng_state node long_stack) + () ) ; + benchmark + ~name:Interpreter_workload.N_IComb + ~intercept:true + ~kinstr_and_stack_sampler:(fun _ rng_state () -> + let node = pair 2 in + parse_instr rng_state node long_stack) + () ; + register_time_alloc_codegen_model + (Instr_name Interpreter_workload.N_IComb) + + let rec make_comb_stack (comb_width : int) (depth : int) acc = + if depth = 0 then + match acc with + | Ex_stack (stack_ty, stack) -> ( + match make_comb comb_width (Ex_value {value = (); ty = unit}) with + | Ex_value {value; ty} -> Ex_stack (ty @$ stack_ty, (value, stack))) + else + match acc with + | Ex_stack (stack_ty, stack) -> + make_comb_stack + comb_width + (depth - 1) + (Ex_stack (unit @$ stack_ty, ((), stack))) + + and make_comb comb_width comb_acc = + if comb_width = 0 then assert false + else if comb_width = 1 then comb_acc + else + match comb_acc with + | Ex_value {value; ty} -> + let (Ty_ex_c ty) = pair unit ty in + make_comb (comb_width - 1) (Ex_value {value = ((), value); ty}) + + let () = + let unpair n = + Micheline.(Prim (0, I_UNPAIR, [Int (0, Z.of_int n)], [])) + in + ( time_and_alloc @@ fun benchmark_type -> + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_IUncomb + ~kinstr_and_stack_sampler:(fun cfg rng_state () -> + let width = + Base_samplers.( + sample_in_interval + rng_state + ~range:{min = 2; max = cfg.comb.max_depth - 2}) + in + let node = unpair width in + let stack = + make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos))) + in + parse_instr rng_state node stack) + () ) ; + benchmark + ~name:Interpreter_workload.N_IUncomb + ~intercept:true + ~kinstr_and_stack_sampler:(fun _ rng_state () -> + let width = 2 in + let node = unpair width in + let stack = + make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos))) + in + parse_instr rng_state node stack) + () ; + register_time_alloc_codegen_model + (Instr_name Interpreter_workload.N_IUncomb) + + let () = + let comb_get n = Micheline.(Prim (0, I_GET, [Int (0, Z.of_int n)], [])) in + ( time_and_alloc @@ fun benchmark_type -> + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_IComb_get + ~kinstr_and_stack_sampler:(fun cfg rng_state () -> + let width = + Base_samplers.( + sample_in_interval + rng_state + ~range:{min = 2; max = cfg.comb.max_depth - 2}) + in + let index = + Base_samplers.( + sample_in_interval rng_state ~range:{min = 0; max = width}) + in + let node = comb_get index in + let stack = + make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos))) + in + parse_instr rng_state node stack) + () ) ; + benchmark + ~name:Interpreter_workload.N_IComb_get + ~intercept:true + ~kinstr_and_stack_sampler:(fun _ rng_state () -> + let node = comb_get 0 in + let stack = make_comb_stack 2 1 (Ex_stack (unit @$ bot, ((), eos))) in + parse_instr rng_state node stack) + () ; + + register_time_alloc_codegen_model + (Instr_name Interpreter_workload.N_IComb_get) + + let () = + let comb_set n = + Micheline.(Prim (0, I_UPDATE, [Int (0, Z.of_int n)], [])) + in + ( time_and_alloc @@ fun benchmark_type -> + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_IComb_set + ~kinstr_and_stack_sampler:(fun cfg rng_state () -> + let width = + Base_samplers.( + sample_in_interval + rng_state + ~range:{min = 2; max = cfg.comb.max_depth - 2}) + in + let index = + Base_samplers.( + sample_in_interval rng_state ~range:{min = 0; max = width}) + in + let node = comb_set index in + let stack = + let (Ex_stack (stack_ty, stack)) = + make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos))) + in + Ex_stack (unit @$ stack_ty, ((), stack)) + in + parse_instr rng_state node stack) + () ; + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_IComb_set + ~intercept:true + ~kinstr_and_stack_sampler:(fun _ rng_state () -> + let node = comb_set 0 in + let stack = + let (Ex_stack (stack_ty, stack)) = + make_comb_stack 2 1 (Ex_stack (unit @$ bot, ((), eos))) + in + Ex_stack (unit @$ stack_ty, ((), stack)) + in + parse_instr rng_state node stack) + () ) ; + + register_time_alloc_codegen_model + (Instr_name Interpreter_workload.N_IComb_set) + + let () = + let dup n = Micheline.(Prim (0, I_DUP, [Int (0, Z.of_int n)], [])) in + time_alloc_benchmark + ~name:Interpreter_workload.N_IDupN + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dup (1 + sample_depth rng_state) in + parse_instr rng_state node long_stack) + () ; + time_alloc_benchmark + ~name:Interpreter_workload.N_IDupN + ~intercept:true + ~kinstr_and_stack_sampler:(fun _cfg rng_state () -> + let node = dup 1 in + parse_instr rng_state node long_stack) + () + end + + module Pairs = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICons_pair + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(ICons_pair (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICar + ~stack_type:(cpair unit unit @$ bot) + ~kinstr:(ICar (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICdr + ~stack_type:(cpair unit unit @$ bot) + ~kinstr:(ICdr (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IUnpair + ~stack_type:(cpair unit unit @$ bot) + ~kinstr:(IUnpair (dummy_loc, halt)) + () + end + + module Options = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICons_some + ~stack_type:(unit @$ bot) + ~kinstr:(ICons_some (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICons_none + ~stack_type:(unit @$ bot) + ~kinstr:(ICons_none (dummy_loc, unit, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IIf_none + ~stack_type:(option unit @$ bot) + ~kinstr: + (IIf_none + { + loc = dummy_loc; + branch_if_none = halt; + branch_if_some = IDrop (dummy_loc, halt); + k = halt; + }) + () + + let () = + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_IOpt_map_none + ~stack:(None, ((), eos)) + ~stack_type:(option unit @$ unit @$ bot) + ~kinstr:(IOpt_map {loc = dummy_loc; body = halt; k = halt}) + () + + let () = + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_IOpt_map_some + ~stack:(Some (), ((), eos)) + ~stack_type:(option unit @$ unit @$ bot) + ~kinstr:(IOpt_map {loc = dummy_loc; body = halt; k = halt}) + () + + let () = + let model = + Interpreter_model.Models.max_branching_model + ~case_0:"none_const" + ~case_1:"some_const" + "N_IOpt_map" + in + register_model_for_code_generation model + end + + module Ors = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ILeft + ~stack_type:(unit @$ bot) + ~kinstr:(ICons_left (dummy_loc, unit, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IRight + ~stack_type:(unit @$ bot) + ~kinstr:(ICons_right (dummy_loc, unit, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IIf_left + ~stack_type:(cor unit unit @$ bot) + ~kinstr: + (IIf_left + { + loc = dummy_loc; + branch_if_left = halt; + branch_if_right = halt; + k = halt; + }) + () + end + + module Lists = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICons_list + ~stack_type:(unit @$ list unit @$ bot) + ~kinstr:(ICons_list (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INil + ~stack_type:(unit @$ bot) + ~kinstr:(INil (dummy_loc, unit, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IIf_cons + ~stack_type:(list unit @$ unit @$ bot) + ~kinstr: + (IIf_cons + { + loc = dummy_loc; + branch_if_cons = IDrop (dummy_loc, IDrop (dummy_loc, halt)); + branch_if_nil = halt; + k = halt; + }) + () + + module Mapping = struct + let () = + (* + IList_map -> + IList_enter_body (empty case) -> + IHalt + *) + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_IList_map + ~stack:(Script_list.empty, ((), eos)) + ~stack_type:(list unit @$ unit @$ bot) + ~kinstr:(IList_map (dummy_loc, halt, Some (list unit), halt)) + () + end + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IList_size + ~stack_type:(list unit @$ bot) + ~kinstr:(IList_size (dummy_loc, halt)) + () + + let () = + (* + IList_iter -> + IIter (empty case) -> + IHalt + *) + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_IList_iter + ~stack:(Script_list.empty, ((), eos)) + ~stack_type:(list unit @$ unit @$ bot) + ~kinstr: + (IList_iter (dummy_loc, Some unit, IDrop (dummy_loc, halt), halt)) + () + end + + module Sets = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEmpty_set + ~stack_type:(unit @$ bot) + ~kinstr:(IEmpty_set (dummy_loc, unit, halt)) + () + + let set_iter_code = + ISet_iter (dummy_loc, Some int, IDrop (dummy_loc, halt), halt) + + let () = + (* + ISet_iter -> + (List.rev (set_fold)) -> + { + IIter -> + IDrop -> + ICons -> + ... + } + *) + simple_benchmark + ~name:Interpreter_workload.N_ISet_iter + ~intercept_stack:(Script_set.empty int, ((), eos)) + ~stack_type:(set int @$ unit @$ bot) + ~kinstr:set_iter_code + () ; + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_ISet_iter + ~stack_type:(set int @$ unit @$ bot) + ~kinstr:set_iter_code + () ; + register_time_alloc_codegen_model (Instr_name N_ISet_iter) + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ISet_mem + ~stack_type:(int @$ set int @$ unit @$ bot) + ~kinstr:(ISet_mem (dummy_loc, halt)) + ~intercept_stack:(Script_int.zero, (Script_set.empty int, ((), eos))) + ~alloc_intercept:false + ~stack_sampler:(fun cfg rng_state () -> + assert (cfg.sampler.set_size.min >= 1) ; + let n = + Base_samplers.sample_in_interval + rng_state + ~range:cfg.sampler.set_size + in + let elts = adversarial_ints rng_state cfg n in + let set = + List.fold_left + (fun set elt -> Script_set.update elt true set) + (Script_set.empty int) + elts + in + let elt = + List.nth_opt elts (Random.State.int rng_state n) + |> WithExceptions.Option.get ~loc:__LOC__ + in + (elt, (set, ((), eos)))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ISet_update + ~stack_type:(int @$ bool @$ set int @$ bot) + ~kinstr:(ISet_update (dummy_loc, halt)) + ~intercept_stack:(Script_int.zero, (false, (Script_set.empty int, eos))) + ~stack_sampler:(fun cfg rng_state () -> + assert (cfg.sampler.set_size.min >= 2) ; + let n = + Base_samplers.sample_in_interval + rng_state + ~range:cfg.sampler.set_size + in + let elts = adversarial_ints rng_state cfg (n + 1) in + let out_of_set, in_set = + match elts with [] -> assert false | hd :: tl -> (hd, tl) + in + let set = + List.fold_left + (fun set elt -> Script_set.update elt true set) + (Script_set.empty int) + in_set + in + let stack = + let flip = Random.State.bool rng_state in + if flip then + (* add an element not in the set *) + (out_of_set, (true, (set, eos))) + else + (* remove an element in the set *) + let elt = out_of_set in + let set = Script_set.update elt true set in + (elt, (flip, (set, eos))) + in + stack) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISet_size + ~stack_type:(set unit @$ bot) + ~kinstr:(ISet_size (dummy_loc, halt)) + () + end + + module Maps = struct + let generate_map_and_key_in_map (cfg : Default_config.config) rng_state = + let n = + Base_samplers.sample_in_interval rng_state ~range:cfg.sampler.set_size + in + let keys = adversarial_ints rng_state cfg n in + let map = + List.fold_left + (fun map i -> Script_map.update i (Some ()) map) + (Script_map.empty int) + keys + in + let (module M) = Script_map.get_module map in + let key = + M.OPS.fold (fun k _ -> function None -> Some k | x -> x) M.boxed None + |> WithExceptions.Option.get ~loc:__LOC__ + in + (key, map) + + let generate_map_and_key_not_in_map (cfg : Default_config.config) rng_state + = + (* [adversarial_ints] could return a non-distinct list, + so the returned [key] may be bound in the [map] in a low probability. *) + let n = + Base_samplers.sample_in_interval rng_state ~range:cfg.sampler.set_size + in + let keys = adversarial_ints rng_state cfg n in + let key, keys = + match keys with [] -> assert false | x :: xs -> (x, xs) + in + let map = + List.fold_left + (fun map i -> Script_map.update i (Some ()) map) + (Script_map.empty int) + keys + in + (key, map) + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEmpty_map + ~stack_type:(unit @$ bot) + ~kinstr:(IEmpty_map (dummy_loc, unit, Some unit, halt)) + () + + (* + let map_map_code = + IMap_map + ( dummy_loc, + ICdr (dummy_loc, halt_unitunit), + halt ) + *) + + let map_map_code () = + IMap_map + ( dummy_loc, + Some (map int unit), + IFailwith (dummy_loc, cpair int unit), + halt ) + + let () = + (* + Map_map (nonempty case) -> + (List.rev (map_fold nonempty_map)) -> + KMap_enter_body (nonempty case) -> + fail (early interruption) + *) + simple_benchmark + ~name:Interpreter_workload.N_IMap_map + ~intercept_stack: + (let map = Script_map.empty int in + (map, ((), eos))) + ~stack_type:(map int unit @$ unit @$ bot) + ~kinstr:(map_map_code ()) + () ; + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_IMap_map + ~stack_type:(map int unit @$ unit @$ bot) + ~kinstr:(map_map_code ()) + () ; + register_time_alloc_codegen_model (Instr_name N_IMap_map) + + let kmap_iter_code = + IMap_iter (dummy_loc, Some (cpair int unit), IDrop (dummy_loc, halt), halt) + + let () = + (* + IMap_iter (nonempty case) -> + (List.rev (map_fold (nonempty))) -> + IIter (nonempty case) -> + ... + *) + simple_benchmark + ~name:Interpreter_workload.N_IMap_iter + ~intercept_stack: + (let map = Script_map.empty int in + (map, ((), eos))) + ~stack_type:(map int unit @$ unit @$ bot) + ~kinstr:kmap_iter_code + () ; + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_IMap_iter + ~stack_type:(map int unit @$ unit @$ bot) + ~kinstr:kmap_iter_code + () ; + register_time_alloc_codegen_model (Instr_name N_IMap_iter) + + let () = + (* + IMap_mem -> + (map_mem) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMap_mem + ~stack_type:(int @$ map int unit @$ unit @$ bot) + ~kinstr:(IMap_mem (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_map.empty int in + (Script_int.zero, (map, ((), eos)))) + ~alloc_intercept:false + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_map_and_key_in_map cfg rng_state in + (key, (map, ((), eos)))) + () + + let () = + (* + IMap_get -> + (map_get) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMap_get + ~stack_type:(int @$ map int unit @$ unit @$ bot) + ~kinstr:(IMap_get (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_map.empty int in + (Script_int.zero, (map, ((), eos)))) + ~alloc_intercept:false + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_map_and_key_in_map cfg rng_state in + (key, (map, ((), eos)))) + () + + let () = + (* + IMap_update -> + (map_update) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMap_update + ~stack_type:(int @$ option unit @$ map int unit @$ bot) + ~kinstr:(IMap_update (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_map.empty int in + (Script_int.zero, (None, (map, eos)))) + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_map_and_key_not_in_map cfg rng_state in + (key, (Some (), (map, eos)))) + () + + let () = + (* + IMap_get_and_update -> + (map_update) -> + (map_get) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMap_get_and_update + ~stack_type:(int @$ option unit @$ map int unit @$ bot) + ~kinstr:(IMap_get_and_update (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_map.empty int in + (Script_int.zero, (None, (map, eos)))) + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_map_and_key_not_in_map cfg rng_state in + (key, (Some (), (map, eos)))) + () + + let () = + (* + IMap_size -> + (map_update) -> + (map_get) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMap_size + ~stack_type:(map int unit @$ bot) + ~kinstr:(IMap_size (dummy_loc, halt)) + ~stack_sampler:(fun _cfg _rng_state -> + let map = Script_map.empty int in + fun () -> (map, eos)) + () + end + + module Big_maps = struct + let generate_big_map_and_key_in_map (cfg : Default_config.config) rng_state + = + let open Lwt_result_syntax in + let n = + Base_samplers.sample_in_interval rng_state ~range:cfg.sampler.set_size + in + let keys = adversarial_ints rng_state cfg n in + let key, keys = + match keys with [] -> assert false | hd :: tl -> (hd, tl) + in + let big_map = + raise_if_error + (Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let big_map = Script_big_map.empty int unit_t in + let* big_map, _ = + let*! result = + List.fold_left_es + (fun (bm, ctxt_acc) k -> + Script_big_map.update ctxt_acc k (Some ()) bm) + (big_map, ctxt) + keys + in + Lwt.return (Environment.wrap_tzresult result) + in + return big_map)) + in + (key, big_map) + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEmpty_big_map + ~stack_type:(unit @$ bot) + ~kinstr:(IEmpty_big_map (dummy_loc, unit, unit, halt)) + () + + let () = + (* + IBig_map_mem -> + (update context with gas) + (big_map_mem) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IBig_map_mem + ~stack_type:(int @$ big_map int unit @$ unit @$ bot) + ~kinstr:(IBig_map_mem (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_big_map.empty int unit in + (Script_int.zero, (map, ((), eos)))) + ~alloc_intercept:false + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_big_map_and_key_in_map cfg rng_state in + (key, (map, ((), eos)))) + () + + let () = + (* + IBig_map_get -> + (big_map_get) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IBig_map_get + ~stack_type:(int @$ big_map int unit @$ unit @$ bot) + ~kinstr:(IBig_map_get (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_big_map.empty int unit in + (Script_int.zero, (map, ((), eos)))) + ~alloc_intercept:false + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_big_map_and_key_in_map cfg rng_state in + (key, (map, ((), eos)))) + () + + let () = + (* + IBig_map_update -> + (big_map_update) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IBig_map_update + ~stack_type:(int @$ option unit @$ big_map int unit @$ bot) + ~kinstr:(IBig_map_update (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_big_map.empty int unit in + (Script_int.zero, (None, (map, eos)))) + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_big_map_and_key_in_map cfg rng_state in + (key, (Some (), (map, eos)))) + () + + let () = + (* + IBig_map_get_and_update -> + (big_map_update) -> + (big_map_get) -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IBig_map_get_and_update + ~stack_type:(int @$ option unit @$ big_map int unit @$ bot) + ~kinstr:(IBig_map_get_and_update (dummy_loc, halt)) + ~intercept_stack: + (let map = Script_big_map.empty int unit in + (Script_int.zero, (None, (map, eos)))) + ~stack_sampler:(fun cfg rng_state () -> + let key, map = generate_big_map_and_key_in_map cfg rng_state in + (key, (Some (), (map, eos)))) + () + end + + module Strings = struct + open Script_string + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IConcat_string + ~intercept_stack:(Script_list.empty, eos) + ~stack_type:(list string @$ bot) + ~kinstr:(IConcat_string (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IConcat_string_pair + ~intercept_stack:(empty, (empty, eos)) + ~stack_type:(string @$ string @$ bot) + ~kinstr:(IConcat_string_pair (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ISlice_string + ~stack_type:(nat @$ nat @$ string @$ bot) + ~kinstr:(ISlice_string (dummy_loc, halt)) + ~intercept_stack: + (let z = Script_int.zero_n in + (z, (z, (empty, eos)))) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let string = + Samplers.Random_value.value Script_typed_ir.string_t rng_state + in + let len = nat_of_positive_int (length string) in + (* worst case: offset = 0 *) + (nat_of_positive_int 0, (len, (string, eos)))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IString_size + ~stack_type:(string @$ bot) + ~kinstr:(IString_size (dummy_loc, halt)) + () + end + + module Bytes = struct + (* Copy of [String] modulo renaming string to bytes. *) + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IConcat_bytes + ~intercept_stack:(Script_list.empty, eos) + ~stack_type:(list bytes @$ bot) + ~kinstr:(IConcat_bytes (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IConcat_bytes_pair + ~intercept_stack:(Bytes.empty, (Bytes.empty, eos)) + ~stack_type:(bytes @$ bytes @$ bot) + ~kinstr:(IConcat_bytes_pair (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ISlice_bytes + ~stack_type:(nat @$ nat @$ bytes @$ bot) + ~kinstr:(ISlice_bytes (dummy_loc, halt)) + ~intercept_stack: + (let z = Script_int.zero_n in + (z, (z, (Bytes.empty, eos)))) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let bytes = + Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + let len = nat_of_positive_int (Bytes.length bytes) in + (* worst case: offset = 0 *) + (nat_of_positive_int 0, (len, (bytes, eos)))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IBytes_size + ~stack_type:(bytes @$ bot) + ~kinstr:(IBytes_size (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAnd_bytes + ~intercept_stack:(Bytes.empty, (Bytes.empty, eos)) + ~stack_type:(bytes @$ bytes @$ bot) + ~kinstr:(IAnd_bytes (dummy_loc, halt)) + () + + let stack_sampler_for_or_and_xor_on_bytes cfg rng_state = + let _, (module Samplers) = + make_default_samplers cfg.Default_config.sampler + in + fun () -> + (* We benchmark the worst cases: when the two bytes have + the same length *) + let bytes1 = + Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + let bytes2 = + Bytes.init (Bytes.length bytes1) (fun _ -> + Char.chr (Random.State.int rng_state 256)) + in + (bytes1, (bytes2, eos)) + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IOr_bytes + ~intercept_stack:(Bytes.empty, (Bytes.empty, eos)) + ~stack_type:(bytes @$ bytes @$ bot) + ~kinstr:(IOr_bytes (dummy_loc, halt)) + ~stack_sampler:stack_sampler_for_or_and_xor_on_bytes + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IXor_bytes + ~intercept_stack:(Bytes.empty, (Bytes.empty, eos)) + ~stack_type:(bytes @$ bytes @$ bot) + ~kinstr:(IXor_bytes (dummy_loc, halt)) + ~stack_sampler:stack_sampler_for_or_and_xor_on_bytes + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INot_bytes + ~intercept_stack:(Bytes.empty, eos) + ~stack_type:(bytes @$ bot) + ~kinstr:(INot_bytes (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ILsl_bytes + ~intercept_stack:(Bytes.empty, (Script_int.one_n, eos)) + ~stack_type:(bytes @$ nat @$ bot) + ~kinstr:(ILsl_bytes (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let bytes = + Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + (* Avoid [n mod 8 = 0] which runs faster than the others. *) + let n = + (* 0-63999 without multiples of 8 *) + let n = Random.State.int rng_state 56000 in + (n / 7 * 8) + (n mod 7) + 1 + in + let shift = Script_int.(abs (of_int n)) in + (bytes, (shift, eos))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ILsr_bytes + ~intercept_stack:(Bytes.empty, (Script_int.one_n, eos)) + ~stack_type:(bytes @$ nat @$ bot) + ~kinstr:(ILsr_bytes (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let bytes = + Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + (* No need of samples of shift > bytes * 8 which are equivalent with + the case of shift = bytes * 8 where LSR returns empty bytes immediately *) + (* Avoid [n mod 8 = 0] which runs faster than the others. *) + let n = + let n = + Random.State.int rng_state ((Bytes.length bytes * 7) + 1) + in + (n / 7 * 8) + (n mod 7) + 1 + in + let shift = Script_int.(abs (of_int n)) in + (bytes, (shift, eos))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IBytes_nat + ~stack_type:(nat @$ bot) + ~kinstr:(IBytes_nat (dummy_loc, halt)) + ~intercept_stack:(Script_int.one_n, eos) + (* Avoid the optimized case of 0 *) + ~stack_sampler:(fun cfg rng_state -> + let base_parameters = + {cfg.sampler.base_parameters with int_size = {min = 0; max = 4096}} + in + let sampler = {cfg.sampler with base_parameters} in + let _, (module Samplers) = make_default_samplers sampler in + fun () -> + let nat = + Samplers.Random_value.value Script_typed_ir.nat_t rng_state + in + (nat, eos)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_INat_bytes + ~stack_type:(bytes @$ bot) + ~kinstr:(INat_bytes (dummy_loc, halt)) + ~intercept_stack:(Bytes.empty, eos) + ~stack_sampler:(fun cfg rng_state -> + let base_parameters = + { + cfg.sampler.base_parameters with + bytes_size = {min = 0; max = 4096}; + } + in + let sampler = {cfg.sampler with base_parameters} in + let _, (module Samplers) = make_default_samplers sampler in + fun () -> + let bytes = + Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + (bytes, eos)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IBytes_int + ~stack_type:(int @$ bot) + ~kinstr:(IBytes_int (dummy_loc, halt)) + ~intercept_stack:(Script_int.one, eos) + (* Avoid the optimized case of 0 *) + ~stack_sampler:(fun cfg rng_state -> + let base_parameters = + {cfg.sampler.base_parameters with int_size = {min = 0; max = 4096}} + in + let sampler = {cfg.sampler with base_parameters} in + let _, (module Samplers) = make_default_samplers sampler in + fun () -> + let int = + Samplers.Random_value.value Script_typed_ir.int_t rng_state + in + (int, eos)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IInt_bytes + ~stack_type:(bytes @$ bot) + ~kinstr:(IInt_bytes (dummy_loc, halt)) + ~intercept_stack:(Bytes.empty, eos) + ~stack_sampler:(fun cfg rng_state -> + let base_parameters = + { + cfg.sampler.base_parameters with + bytes_size = {min = 0; max = 4096}; + } + in + let sampler = {cfg.sampler with base_parameters} in + let _, (module Samplers) = make_default_samplers sampler in + fun () -> + let bytes = + Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + (bytes, eos)) + () + end + + module Timestamps = struct + let zero_timestamp = Script_timestamp.of_zint Z.zero + + let zero_int = Script_int.zero + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAdd_seconds_to_timestamp + ~intercept_stack:(zero_int, (zero_timestamp, eos)) + ~stack_type:(int @$ timestamp @$ bot) + ~kinstr:(IAdd_seconds_to_timestamp (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAdd_timestamp_to_seconds + ~intercept_stack:(zero_timestamp, (zero_int, eos)) + ~stack_type:(timestamp @$ int @$ bot) + ~kinstr:(IAdd_timestamp_to_seconds (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISub_timestamp_seconds + ~intercept_stack:(zero_timestamp, (zero_int, eos)) + ~stack_type:(timestamp @$ int @$ bot) + ~kinstr:(ISub_timestamp_seconds (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IDiff_timestamps + ~intercept_stack:(zero_timestamp, (zero_timestamp, eos)) + ~stack_type:(timestamp @$ timestamp @$ bot) + ~kinstr:(IDiff_timestamps (dummy_loc, halt)) + () + end + + module Tez = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAdd_tez + ~stack_type:(mutez @$ mutez @$ bot) + ~kinstr:(IAdd_tez (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ISub_tez + ~stack_type:(mutez @$ mutez @$ bot) + ~kinstr:(ISub_tez (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = + make_default_samplers cfg.Default_config.sampler + in + fun () -> + let a = Samplers.Random_value.value mutez rng_state in + let b = + match Alpha_context.Tez.(a /? 2L) with + | Error _ -> assert false + | Ok x -> x + in + (a, (b, eos))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ISub_tez_legacy + ~stack_type:(mutez @$ mutez @$ bot) + ~kinstr:(ISub_tez_legacy (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = + make_default_samplers cfg.Default_config.sampler + in + fun () -> + let a = Samplers.Random_value.value mutez rng_state in + let b = + match Alpha_context.Tez.(a /? 2L) with + | Error _ -> assert false + | Ok x -> x + in + (a, (b, eos))) + () + + let sample_tez_nat (module Samplers : Michelson_samplers.S) rng_state = + let mutez = Samplers.Random_value.value mutez rng_state in + let mutez_int64 = Alpha_context.Tez.to_mutez mutez in + let int64 = Int64.(div max_int (mul mutez_int64 2L)) in + let nat = + match Script_int.(is_nat (of_int64 int64)) with + | None -> assert false + | Some nat -> nat + in + (mutez, nat) + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMul_teznat + ~stack_type:(mutez @$ nat @$ bot) + ~kinstr:(IMul_teznat (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, samplers = make_default_samplers cfg.sampler in + fun () -> + let mutez, nat = sample_tez_nat samplers rng_state in + (mutez, (nat, eos))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IMul_nattez + ~stack_type:(nat @$ mutez @$ bot) + ~kinstr:(IMul_nattez (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, samplers = make_default_samplers cfg.sampler in + fun () -> + let mutez, nat = sample_tez_nat samplers rng_state in + (nat, (mutez, eos))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IEdiv_teznat + ~stack_type:(mutez @$ nat @$ bot) + ~kinstr:(IEdiv_teznat (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, samplers = make_default_samplers cfg.sampler in + fun () -> + let mutez, nat = sample_tez_nat samplers rng_state in + (mutez, (nat, eos))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEdiv_tez + ~stack_type:(mutez @$ mutez @$ bot) + ~kinstr:(IEdiv_tez (dummy_loc, halt)) + () + end + + module Booleans = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IOr + ~stack_type:(bool @$ bool @$ bot) + ~kinstr:(IOr (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAnd + ~stack_type:(bool @$ bool @$ bot) + ~kinstr:(IAnd (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IXor + ~stack_type:(bool @$ bool @$ bot) + ~kinstr:(IXor (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INot + ~stack_type:(bool @$ bot) + ~kinstr:(INot (dummy_loc, halt)) + () + end + + module Integers = struct + let zero = Script_int.zero + + let zero_n = Script_int.zero_n + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IIs_nat + ~stack_type:(int @$ bot) + ~kinstr:(IIs_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INeg + ~intercept_stack:(zero, eos) + ~stack_type:(int @$ bot) + ~kinstr:(INeg (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IAbs_int + ~stack_type:(int @$ bot) + ~kinstr:(IAbs_int (dummy_loc, halt)) + ~intercept_stack:(zero, eos) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let x = Samplers.Michelson_base.nat rng_state in + let neg_x = Script_int.neg x in + (neg_x, eos)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IInt_nat + ~stack_type:(nat @$ bot) + ~kinstr:(IInt_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAdd_int + ~intercept_stack:(zero, (zero, eos)) + ~stack_type:(int @$ int @$ bot) + ~kinstr:(IAdd_int (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAdd_nat + ~intercept_stack:(zero_n, (zero_n, eos)) + ~stack_type:(nat @$ nat @$ bot) + ~kinstr:(IAdd_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISub_int + ~intercept_stack:(zero, (zero, eos)) + ~stack_type:(int @$ int @$ bot) + ~kinstr:(ISub_int (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IMul_int + ~intercept_stack:(zero, (zero, eos)) + ~stack_type:(int @$ int @$ bot) + ~kinstr:(IMul_int (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IMul_nat + ~intercept_stack:(zero_n, (zero, eos)) + ~stack_type:(nat @$ int @$ bot) + ~kinstr:(IMul_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IEdiv_int + ~intercept_stack:(zero, (zero, eos)) + ~stack_type:(int @$ int @$ bot) + ~kinstr:(IEdiv_int (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + (* When x > 0 and size(x) < size(y), EDIV x y evaluates to (0,x) and nothing is allocated. + The following sampler avoids such cases that lead to underestimation. *) + let x = Script_int.neg @@ Samplers.Michelson_base.nat rng_state in + let y = Samplers.Michelson_base.int rng_state in + (x, (y, eos))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEdiv_nat + ~intercept_stack:(zero_n, (zero, eos)) + ~stack_type:(nat @$ int @$ bot) + ~kinstr:(IEdiv_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ILsl_nat + ~intercept_stack:(zero_n, (zero_n, eos)) + ~stack_type:(nat @$ nat @$ bot) + ~kinstr:(ILsl_nat (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let x = Samplers.Michelson_base.nat rng_state in + (* shift must be in [0;256]: 1 byte max *) + let shift = + Script_int.(abs (of_int (Random.State.int rng_state 256))) + in + (x, (shift, eos))) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ILsr_nat + ~intercept_stack:(zero_n, (zero_n, eos)) + ~stack_type:(nat @$ nat @$ bot) + ~kinstr:(ILsr_nat (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let x = Samplers.Michelson_base.nat rng_state in + (* shift must be in [0;256]: 1 byte max *) + let shift = + Script_int.(abs (of_int (Random.State.int rng_state 256))) + in + (x, (shift, eos))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IOr_nat + ~intercept_stack:(zero_n, (zero_n, eos)) + ~stack_type:(nat @$ nat @$ bot) + ~kinstr:(IOr_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAnd_nat + ~intercept_stack:(zero_n, (zero_n, eos)) + ~stack_type:(nat @$ nat @$ bot) + ~kinstr:(IAnd_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IAnd_int_nat + ~intercept_stack:(zero, (zero_n, eos)) + ~stack_type:(int @$ nat @$ bot) + ~kinstr:(IAnd_int_nat (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + (* The worst case is size(and(x,y)) = size(y) when x < 0. *) + let x = Script_int.neg @@ Samplers.Michelson_base.nat rng_state in + let y = Samplers.Michelson_base.nat rng_state in + (x, (y, eos))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IXor_nat + ~intercept_stack:(zero_n, (zero_n, eos)) + ~stack_type:(nat @$ nat @$ bot) + ~kinstr:(IXor_nat (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INot_int + ~intercept_stack:(zero, eos) + ~stack_type:(int @$ bot) + ~kinstr:(INot_int (dummy_loc, halt)) + () + end + + module Control = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IIf + ~stack_type:(bool @$ unit @$ bot) + ~kinstr: + (IIf + { + loc = dummy_loc; + branch_if_true = halt; + branch_if_false = halt; + k = halt; + }) + () + + let () = + let push_false = IPush (dummy_loc, bool, false, halt) in + (* The case true is on top of stack + ILoop -> + IPush false -> + IHalt + *) + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_ILoop_in + ~stack:(true, eos) + ~stack_type:(bool @$ bot) + ~kinstr:(ILoop (dummy_loc, push_false, halt)) + () ; + (* The case false is on top of stack + ILoop -> + IHalt + *) + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_ILoop_out + ~stack:(false, eos) + ~stack_type:(bool @$ bot) + ~kinstr:(ILoop (dummy_loc, push_false, halt)) + () + + let () = + let model = + Interpreter_model.Models.max_branching_model + ~case_0:"in_const" + ~case_1:"out_const" + "N_ILoop" + in + register_model_for_code_generation model + + let () = + let cons_r = ICons_right (dummy_loc, unit, halt) in + (* + ILoop_left -> + ICons_right -> + IHalt + *) + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_ILoop_left_in + ~stack:(L (), eos) + ~stack_type:(cor unit unit @$ bot) + ~kinstr:(ILoop_left (dummy_loc, cons_r, halt)) + () ; + (* + ILoop_left -> + IHalt + *) + time_alloc_benchmark_with_fixed_stack + ~name:Interpreter_workload.N_ILoop_left_out + ~stack:(R (), eos) + ~stack_type:(cor unit unit @$ bot) + ~kinstr:(ILoop_left (dummy_loc, cons_r, halt)) + () + + let () = + let model = + Interpreter_model.Models.max_branching_model + ~case_0:"in_const" + ~case_1:"out_const" + "N_ILoop_left" + in + register_model_for_code_generation model + + let () = + (* + IDip -> + IHalt -> + IPush -> + IHalt + *) + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IDip + ~stack_type:(unit @$ unit @$ bot) + ~kinstr:(IDip (dummy_loc, halt, Some unit, halt)) + () + + let dummy_lambda = + let open Script_typed_ir in + let descr = + { + kloc = dummy_loc; + kbef = unit @$ bot; + kaft = unit @$ bot; + kinstr = halt; + } + in + Lam (descr, Micheline.Int (dummy_loc, Z.zero)) + + let dummy_lambda_rec = + let open Script_typed_ir in + let descr = + { + kloc = dummy_loc; + kbef = unit @$ lambda unit unit @$ bot; + kaft = unit @$ bot; + kinstr = + IDrop + (dummy_loc, IDrop (dummy_loc, IPush (dummy_loc, unit, (), halt))); + } + in + LamRec (descr, Micheline.Int (dummy_loc, Z.zero)) + + let () = + (* + IExec -> + (switch to in-context gas-counting) -> + interp lambda code -> + IHalt + *) + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IExec + ~stack_type:(unit @$ lambda unit unit @$ bot) + ~kinstr:(IExec (dummy_loc, Some (unit @$ bot), halt)) + ~stack_sampler:(fun _cfg rng_state () -> + if Base_samplers.uniform_bool rng_state then ((), (dummy_lambda, eos)) + else ((), (dummy_lambda_rec, eos))) + () + + let () = + (* + IApply -> + unparse unit -> + unparse unit_ty -> + construct term -> + IHalt + *) + let dummy_lambda_pair = + let open Script_typed_ir in + let descr = + { + kloc = dummy_loc; + kbef = cpair unit unit @$ bot; + kaft = unit @$ bot; + kinstr = ICdr (dummy_loc, halt); + } + in + Lam (descr, Micheline.Int (dummy_loc, Z.zero)) + in + let dummy_lambda_pair_rec = + let open Script_typed_ir in + let descr = + { + kloc = dummy_loc; + kbef = cpair unit unit @$ lambda (cpair unit unit) unit @$ bot; + kaft = unit @$ bot; + kinstr = + IDrop + (dummy_loc, IDrop (dummy_loc, IPush (dummy_loc, unit, (), halt))); + } + in + LamRec (descr, Micheline.Int (dummy_loc, Z.zero)) + in + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_IApply + ~stack_type:(unit @$ lambda (cpair unit unit) unit @$ bot) + ~kinstr:(IApply (dummy_loc, unit, halt)) + ~stack_sampler:(fun _cfg rng_state () -> + if Base_samplers.uniform_bool rng_state then + ((), (dummy_lambda_pair, eos)) + else ((), (dummy_lambda_pair_rec, eos))) + () + + let () = + (* + ILambda -> + IHalt + *) + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ILambda_lam + ~stack_type:(unit @$ bot) + ~kinstr:(ILambda (dummy_loc, dummy_lambda, halt)) + () + + let () = + (* + ILambda (rec) -> + IHalt + *) + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ILambda_lamrec + ~stack_type:(unit @$ bot) + ~kinstr:(ILambda (dummy_loc, dummy_lambda_rec, halt)) + () + + let () = + let model = + Interpreter_model.Models.max_branching_model + ~case_0:"lam_const" + ~case_1:"lamrec_const" + "N_ILambda" + in + register_model_for_code_generation model + + let () = + (* + IFailwith -> + (unparse_data Unit) -> + (strip_locations) -> + fail + *) + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IFailwith + ~amplification:100 + ~stack_type:(unit @$ bot) + ~kinstr:(IFailwith (dummy_loc, unit)) + () + end + + module Comparison = struct + let () = + benchmark + ~name:Interpreter_workload.N_ICompare + ~kinstr_and_stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let size = + Base_samplers.sample_in_interval + rng_state + ~range:cfg.compare.type_size + in + let (Script_ir_translator.Ex_comparable_ty ty) = + Samplers.Random_type.m_comparable_type ~size rng_state + in + let value = Samplers.Random_value.comparable ty rng_state in + let kinstr = ICompare (dummy_loc, ty, halt) in + Ex_stack_and_kinstr + { + stack = (value, (value, eos)); + stack_type = ty @$ ty @$ bot; + kinstr; + }) + () + + let () = + benchmark + ~name:Interpreter_workload.N_ICompare + ~salt:"_intercepts" + ~kinstr_and_stack_sampler:(fun cfg rng_state -> + (* Sample from values whose [size_of_comparable_value] is 1. *) + (* [unit] and [bool] are excluded since they are relatively quick. *) + let sampler = + { + cfg.sampler with + base_parameters = + { + int_size = {min = 1; max = 1}; + string_size = {min = 1; max = 1}; + bytes_size = {min = 1; max = 1}; + }; + } + in + let _, (module Samplers) = make_default_samplers sampler in + fun () -> + let ty : Script_ir_translator.ex_comparable_ty = + match Random.State.int rng_state 4 with + | 0 -> Ex_comparable_ty String_t + | 1 -> Ex_comparable_ty Bytes_t + | 2 -> Ex_comparable_ty Int_t + | 3 -> Ex_comparable_ty Nat_t + | _ -> assert false + in + let (Ex_comparable_ty ty) = ty in + let value = Samplers.Random_value.comparable ty rng_state in + let kinstr = ICompare (dummy_loc, ty, halt) in + Ex_stack_and_kinstr + { + stack = (value, (value, eos)); + stack_type = ty @$ ty @$ bot; + kinstr; + }) + () + + let () = + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_ICompare + ~stack_type:(string @$ string @$ bot) + ~kinstr:(ICompare (dummy_loc, String_t, halt)) + () + + let () = register_time_alloc_codegen_model (Instr_name N_ICompare) + end + + module Comparators = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEq + ~stack_type:(int @$ bot) + ~kinstr:(IEq (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INeq + ~stack_type:(int @$ bot) + ~kinstr:(INeq (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ILt + ~stack_type:(int @$ bot) + ~kinstr:(ILt (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IGt + ~stack_type:(int @$ bot) + ~kinstr:(IGt (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ILe + ~stack_type:(int @$ bot) + ~kinstr:(ILe (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IGe + ~stack_type:(int @$ bot) + ~kinstr:(IGe (dummy_loc, halt)) + () + end + + module Proto = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAddress + ~stack_type:(contract unit @$ bot) + ~kinstr:(IAddress (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IContract + ~stack_type:(address @$ bot) + ~kinstr: + (IContract (dummy_loc, unit, Alpha_context.Entrypoint.default, halt)) + () + + let () = + simple_time_alloc_benchmark_with_stack_sampler + ~name:Interpreter_workload.N_ITransfer_tokens + ~stack_type:(unit @$ mutez @$ contract unit @$ bot) + ~kinstr:(ITransfer_tokens (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + fun () -> + let contract = + Samplers.Random_value.value (contract unit) rng_state + in + let amount = + match contract with + | Typed_implicit _ | Typed_originated _ -> + Samplers.Random_value.value mutez rng_state + | Typed_sc_rollup _ -> Alpha_context.Tez.zero + in + ((), (amount, (contract, eos)))) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IImplicit_account + ~stack_type:(key_hash @$ bot) + ~kinstr:(IImplicit_account (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ICreate_contract + ~stack_type:(option key_hash @$ mutez @$ unit @$ bot) + ~kinstr: + (ICreate_contract + { + loc = dummy_loc; + storage_type = unit; + code = Micheline.(strip_locations @@ Seq (0, [])); + k = halt; + }) + () + + let () = + let name = + match Protocol.Script_string.of_string "view" with + | Ok s -> s + | Error _ -> assert false + in + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IView + ~stack_type:(unit @$ address @$ bot) + ~kinstr: + (IView + ( dummy_loc, + View_signature {name; input_ty = unit; output_ty = unit}, + Some bot, + halt )) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISet_delegate + ~stack_type:(option key_hash @$ bot) + ~kinstr:(ISet_delegate (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_INow + ~stack_type:(unit @$ bot) + ~kinstr:(INow (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IMin_block_time + ~stack_type:bot + ~kinstr:(IMin_block_time (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IBalance + ~stack_type:(unit @$ bot) + ~kinstr:(IBalance (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ILevel + ~stack_type:(unit @$ bot) + ~kinstr:(ILevel (dummy_loc, halt)) + () + + let name_of_algo = function + | Signature.Ed25519 -> Interpreter_workload.N_ICheck_signature_ed25519 + | Signature.Secp256k1 -> Interpreter_workload.N_ICheck_signature_secp256k1 + | Signature.P256 -> Interpreter_workload.N_ICheck_signature_p256 + | Signature.Bls -> Interpreter_workload.N_ICheck_signature_bls + + let check_signature (algo : Signature.algo) ~benchmark_type ~for_intercept = + benchmark_with_stack_sampler + ~benchmark_type + ~intercept:for_intercept + ~name:(name_of_algo algo) + ~stack_type:(public_key @$ signature @$ bytes @$ bot) + ~kinstr:(ICheck_signature (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let (module Crypto_samplers), (module Samplers) = + make_default_samplers ~algo:(`Algo algo) cfg.Default_config.sampler + in + fun () -> + let _pkh, pk, sk = Crypto_samplers.all rng_state in + let unsigned_message = + if for_intercept then Environment.Bytes.empty + else Samplers.Random_value.value Script_typed_ir.bytes_t rng_state + in + let signed_message = Signature.sign sk unsigned_message in + let signed_message = Script_signature.make signed_message in + (pk, (signed_message, (unsigned_message, eos)))) + () + + let check_signature algo = + check_signature algo ~benchmark_type:Time ~for_intercept:true ; + check_signature algo ~benchmark_type:Time ~for_intercept:false ; + check_signature algo ~benchmark_type:Alloc ~for_intercept:false ; + register_time_alloc_codegen_model (Instr_name (name_of_algo algo)) + + let () = check_signature Signature.Ed25519 + + let () = check_signature Signature.Secp256k1 + + let () = check_signature Signature.P256 + + let () = check_signature Signature.Bls + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IHash_key + ~stack_type:(public_key @$ bot) + ~kinstr:(IHash_key (dummy_loc, halt)) + () + + let () = + time_alloc_benchmark + ~name:Interpreter_workload.N_IPack + ~kinstr_and_stack_sampler:(fun _cfg _rng_state -> + let kinstr = IPack (dummy_loc, unit, halt) in + fun () -> + Ex_stack_and_kinstr + {stack = ((), eos); stack_type = unit @$ bot; kinstr}) + () + + let () = + let open Lwt_result_syntax in + time_alloc_benchmark + ~name:Interpreter_workload.N_IUnpack + ~kinstr_and_stack_sampler:(fun _cfg rng_state -> + let b = + raise_if_error + (Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let* bytes, _ = + let*! result = + Script_ir_translator.pack_data ctxt unit () + in + Lwt.return (Environment.wrap_tzresult result) + in + return bytes)) + in + let kinstr = IUnpack (dummy_loc, unit, halt) in + fun () -> + Ex_stack_and_kinstr + {stack = (b, eos); stack_type = bytes @$ bot; kinstr}) + () + + let () = + simple_benchmark + ~benchmark_type:Time + ~name:Interpreter_workload.N_IBlake2b + ~intercept_stack:(Environment.Bytes.empty, eos) + ~stack_type:(bytes @$ bot) + ~kinstr:(IBlake2b (dummy_loc, halt)) + () ; + (* no intercept for alloc *) + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_IBlake2b + ~stack_type:(bytes @$ bot) + ~kinstr:(IBlake2b (dummy_loc, halt)) + () ; + register_time_alloc_codegen_model (Instr_name N_IBlake2b) + + let () = + simple_benchmark + ~benchmark_type:Time + ~name:Interpreter_workload.N_ISha256 + ~intercept_stack:(Environment.Bytes.empty, eos) + ~stack_type:(bytes @$ bot) + ~kinstr:(ISha256 (dummy_loc, halt)) + () ; + (* no intercept for alloc *) + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_ISha256 + ~stack_type:(bytes @$ bot) + ~kinstr:(ISha256 (dummy_loc, halt)) + () ; + register_time_alloc_codegen_model (Instr_name N_ISha256) + + let () = + simple_benchmark + ~benchmark_type:Time + ~name:Interpreter_workload.N_ISha512 + ~intercept_stack:(Environment.Bytes.empty, eos) + ~stack_type:(bytes @$ bot) + ~kinstr:(ISha512 (dummy_loc, halt)) + () ; + (* no intercept for alloc *) + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_ISha512 + ~stack_type:(bytes @$ bot) + ~kinstr:(ISha512 (dummy_loc, halt)) + () ; + register_time_alloc_codegen_model (Instr_name N_ISha512) + + let () = + simple_benchmark + ~benchmark_type:Time + ~name:Interpreter_workload.N_IKeccak + ~intercept_stack:(Environment.Bytes.empty, eos) + ~stack_type:(bytes @$ bot) + ~kinstr:(IKeccak (dummy_loc, halt)) + () ; + (* no intercept for alloc *) + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_IKeccak + ~stack_type:(bytes @$ bot) + ~kinstr:(IKeccak (dummy_loc, halt)) + () ; + register_time_alloc_codegen_model (Instr_name N_IKeccak) + + let () = + simple_benchmark + ~benchmark_type:Time + ~name:Interpreter_workload.N_ISha3 + ~intercept_stack:(Environment.Bytes.empty, eos) + ~stack_type:(bytes @$ bot) + ~kinstr:(ISha3 (dummy_loc, halt)) + () ; + (* no intercept for alloc *) + simple_benchmark + ~benchmark_type:Alloc + ~name:Interpreter_workload.N_ISha3 + ~stack_type:(bytes @$ bot) + ~kinstr:(ISha3 (dummy_loc, halt)) + () ; + register_time_alloc_codegen_model (Instr_name N_ISha3) + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISource + ~stack_type:(unit @$ bot) + ~kinstr:(ISource (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISender + ~stack_type:(unit @$ bot) + ~kinstr:(ISender (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISelf + ~stack_type:(unit @$ bot) + ~kinstr: + (ISelf (dummy_loc, unit, Alpha_context.Entrypoint.default, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISelf_address + ~stack_type:(unit @$ bot) + ~kinstr:(ISelf_address (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IAmount + ~stack_type:(unit @$ bot) + ~kinstr:(IAmount (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IChainId + ~stack_type:(unit @$ bot) + ~kinstr:(IChainId (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IVoting_power + ~stack_type:(key_hash @$ bot) + ~kinstr:(IVoting_power (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ITotal_voting_power + ~stack_type:(unit @$ bot) + ~kinstr:(ITotal_voting_power (dummy_loc, halt)) + () + end + + let () = + let memo_size = + match Alpha_context.Sapling.Memo_size.parse_z Z.zero with + | Error _ -> assert false + | Ok sz -> sz + in + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ISapling_empty_state + ~stack_type:(unit @$ bot) + ~kinstr:(ISapling_empty_state (dummy_loc, memo_size, halt)) + () + + module type Type_transaction = sig + val type_transaction : Sapling_generation.type_transaction + + val suffix : string + end + + module Register_Sapling_benchmark (Type_transaction : Type_transaction) = + struct + let is_empty = + match Type_transaction.type_transaction with Empty -> true | _ -> false + + let () = + (* Note that memo_size is hardcoded to 0 in module [Sapling_generation]. *) + let memo_size = + match Alpha_context.Sapling.Memo_size.parse_z Z.zero with + | Error _ -> assert false + | Ok sz -> sz + in + let module B (BenchmarkType : sig + val value : benchmark_type + end) : Benchmark.S = struct + let info, name = + info_and_name + ~benchmark_type:BenchmarkType.value + ~intercept:is_empty + ("ISapling_verify_update_" ^ Type_transaction.suffix) + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + include Default_config + include Default_boilerplate + + let models = + Interpreter_model.make_model + BenchmarkType.value + (Instr_name Interpreter_workload.N_ISapling_verify_update) + + let stack_type = + let spl_state = sapling_state memo_size in + let spl_tx = sapling_transaction memo_size in + spl_tx @$ spl_state @$ bot + + let kinstr = ISapling_verify_update (dummy_loc, halt) + + let prepare_sapling_execution_environment sapling_forge_rng_seed + sapling_transition = + let open Lwt_result_syntax in + let sapling_forge_rng_state = + Random.State.make + @@ Option.fold + ~none:Sapling_generation.shared_seed + ~some:(fun seed -> [|seed|]) + sapling_forge_rng_seed + in + (* Prepare context. We _must_ reuse the same seed as the one used for + the context when generating the transactions. This ensures that the + bootstrap account match and that the transactions can be replayed. *) + let result = + Lwt_main.run + (let* ctxt, step_constants = + Execution_context.make ~rng_state:sapling_forge_rng_state () + in + (* Prepare a sapling state able to replay the transition. *) + let* _, _, _, _, ctxt, state_id = + Sapling_generation.prepare_seeded_state sapling_transition ctxt + in + let* state, ctxt = + let*! result = + Alpha_context.Sapling.( + state_from_id ctxt (Id.parse_z state_id)) + in + Lwt.return (Environment.wrap_tzresult result) + in + return (ctxt, state, step_constants)) + in + match result with + | Ok r -> r + | Error _ -> + Format.eprintf + "Error in prepare_sapling_execution_environment, aborting@." ; + Stdlib.failwith "prepare_sapling_execution_environment" + + let create_benchmarks ~rng_state ~bench_num (config : config) = + ignore rng_state ; + match config.sapling with + | {sapling_txs_file; seed} -> + let transitions = + Sapling_generation.load + ~filename:sapling_txs_file + Type_transaction.type_transaction + in + let length = List.length transitions in + if length < bench_num && not is_empty then + Format.eprintf + "ISapling_verify_update: warning, only %d available \ + transactions (requested %d)@." + length + bench_num ; + let transitions = + List.take_n (min bench_num length) transitions + in + List.map + (fun (_, transition) () -> + let ctxt, state, step_constants = + prepare_sapling_execution_environment seed transition + in + let address = + Alpha_context.Contract.( + to_b58check (Originated step_constants.self)) + in + let chain_id = + Environment.Chain_id.to_b58check step_constants.chain_id + in + let anti_replay = address ^ chain_id in + (* Checks that the transaction is correct*) + let () = + match + Sapling_validator.verify_update + (Sapling_generation.alpha_to_raw ctxt) + (Obj.magic state) + transition.sapling_tx + anti_replay + |> Lwt_main.run + with + | Ok (_, Some _) -> () + | Ok (_, None) -> + Stdlib.failwith "benchmarked transaction is incorrect" + | _ -> assert false + in + let stack_instr = + Ex_stack_and_kinstr + { + stack = (transition.sapling_tx, (state, eos)); + stack_type; + kinstr; + } + in + benchmark_from_kinstr_and_stack + BenchmarkType.value + ctxt + step_constants + stack_instr) + transitions + end in + Registration_helpers.register + (module B (struct + let value = Time + end)) ; + Registration_helpers.register + (module B (struct + let value = Alloc + end)) ; + register_time_alloc_codegen_model + (Instr_name Interpreter_workload.N_ISapling_verify_update) + end + + module Sapling_empty = struct + let module A = Register_Sapling_benchmark (struct + let type_transaction = Sapling_generation.Empty + + let suffix = "empty" + end) in + () + end + + module Sapling_non_empty = struct + let module A = Register_Sapling_benchmark (struct + let type_transaction = Sapling_generation.Non_empty + + let suffix = "non_empty" + end) in + () + end + + (* when benchmarking, compile bls12-381-unix without ADX, see + https://gitlab.com/dannywillems/ocaml-bls12-381/-/blob/71d0b4d467fbfaa6452d702fcc408d7a70916a80/README.md#install + *) + module Bls12_381 = struct + let check () = + if not Bls12_381.built_with_blst_portable then ( + Format.eprintf + "BLS must be built without ADX to run the BLS benchmarks. Try \ + compiling again after setting the environment variable \ + BLST_PORTABLE. Aborting.@." ; + Stdlib.failwith "bls_not_built_with_blst_portable") + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IAdd_bls12_381_g1 + ~stack_type:(bls12_381_g1 @$ bls12_381_g1 @$ bot) + ~kinstr:(IAdd_bls12_381_g1 (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IAdd_bls12_381_g2 + ~stack_type:(bls12_381_g2 @$ bls12_381_g2 @$ bot) + ~kinstr:(IAdd_bls12_381_g2 (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IAdd_bls12_381_fr + ~stack_type:(bls12_381_fr @$ bls12_381_fr @$ bot) + ~kinstr:(IAdd_bls12_381_fr (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_g1 + ~stack_type:(bls12_381_g1 @$ bls12_381_fr @$ bot) + ~kinstr:(IMul_bls12_381_g1 (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_g2 + ~stack_type:(bls12_381_g2 @$ bls12_381_fr @$ bot) + ~kinstr:(IMul_bls12_381_g2 (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_fr + ~stack_type:(bls12_381_fr @$ bls12_381_fr @$ bot) + ~kinstr:(IMul_bls12_381_fr (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_z_fr + ~stack_type:(bls12_381_fr @$ int @$ bot) + ~kinstr:(IMul_bls12_381_z_fr (dummy_loc, halt)) + () + + let () = + benchmark_with_stack_sampler + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_z_fr + ~intercept:true + ~stack_type:(bls12_381_fr @$ int @$ bot) + ~kinstr:(IMul_bls12_381_z_fr (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + let fr_sampler = Samplers.Random_value.value bls12_381_fr in + let zero = Script_int.zero in + fun () -> (fr_sampler rng_state, (zero, eos))) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_fr_z + ~stack_type:(int @$ bls12_381_fr @$ bot) + ~kinstr:(IMul_bls12_381_fr_z (dummy_loc, halt)) + () + + let () = + benchmark_with_stack_sampler + ~check + ~name:Interpreter_workload.N_IMul_bls12_381_fr_z + ~intercept:true + ~stack_type:(int @$ bls12_381_fr @$ bot) + ~kinstr:(IMul_bls12_381_fr_z (dummy_loc, halt)) + ~stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + let fr_sampler = Samplers.Random_value.value bls12_381_fr in + let zero = Script_int.zero in + fun () -> (zero, (fr_sampler rng_state, eos))) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_IInt_bls12_381_z_fr + ~stack_type:(bls12_381_fr @$ bot) + ~kinstr:(IInt_bls12_381_fr (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_INeg_bls12_381_g1 + ~stack_type:(bls12_381_g1 @$ bot) + ~kinstr:(INeg_bls12_381_g1 (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_INeg_bls12_381_g2 + ~stack_type:(bls12_381_g2 @$ bot) + ~kinstr:(INeg_bls12_381_g2 (dummy_loc, halt)) + () + + let () = + simple_time_alloc_benchmark + ~check + ~name:Interpreter_workload.N_INeg_bls12_381_fr + ~stack_type:(bls12_381_fr @$ bot) + ~kinstr:(INeg_bls12_381_fr (dummy_loc, halt)) + () + + let () = + let (Ty_ex_c p) = pair bls12_381_g1 bls12_381_g2 in + simple_benchmark + ~benchmark_type:Time + ~check + ~name:Interpreter_workload.N_IPairing_check_bls12_381 + ~intercept_stack:(Script_list.empty, eos) + ~stack_type:(list p @$ bot) + ~kinstr:(IPairing_check_bls12_381 (dummy_loc, halt)) + () ; + (* no intercept for alloc *) + simple_benchmark + ~benchmark_type:Alloc + ~check + ~name:Interpreter_workload.N_IPairing_check_bls12_381 + ~stack_type:(list p @$ bot) + ~kinstr:(IPairing_check_bls12_381 (dummy_loc, halt)) + () ; + register_time_alloc_codegen_model (Instr_name N_IPairing_check_bls12_381) + end + + module Tickets = struct + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_ITicket + ~stack_type:(unit @$ nat @$ bot) + ~kinstr:(ITicket (dummy_loc, Some unit, halt)) + () + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IRead_ticket + ~stack_type:(ticket unit @$ bot) + ~kinstr:(IRead_ticket (dummy_loc, Some unit, halt)) + () + + let split_ticket_instr = ISplit_ticket (dummy_loc, halt) + + let stack_type = ticket unit @$ cpair nat nat @$ bot + + let () = + let one = Script_int.one_n in + let ticket = + { + ticketer = + Alpha_context.Contract.Implicit + Environment.Signature.Public_key_hash.zero; + contents = (); + amount = Ticket_amount.(add one one); + } + in + benchmark_with_fixed_stack + ~intercept:true + ~name:Interpreter_workload.N_ISplit_ticket + ~stack_type + ~stack:(ticket, ((one, one), eos)) + ~kinstr:split_ticket_instr + () + + let () = + time_and_alloc (fun benchmark_type -> + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_ISplit_ticket + ~kinstr_and_stack_sampler:(fun config rng_state -> + let _, (module Samplers) = + make_default_samplers config.Default_config.sampler + in + fun () -> + let x_amount = + Script_int.succ_n @@ Samplers.Random_value.value nat rng_state + in + let y_amount = + Script_int.succ_n @@ Samplers.Random_value.value nat rng_state + in + let amount = Script_int.add_n x_amount y_amount in + let amount = + (* this is safe because x_amount > 0 and y_amount > 0 *) + WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_n amount + in + let ticket = + Samplers.Random_value.value (ticket unit) rng_state + in + let ticket = {ticket with amount} in + Ex_stack_and_kinstr + { + stack = (ticket, ((x_amount, y_amount), eos)); + stack_type; + kinstr = split_ticket_instr; + }) + ()) ; + register_time_alloc_codegen_model (Instr_name N_ISplit_ticket) + + let join_tickets_instr = IJoin_tickets (dummy_loc, string, halt) + + let ticket_str = ticket string + + let stack_type = + let (Ty_ex_c p) = pair ticket_str ticket_str in + p @$ bot + + let () = + benchmark + ~intercept:true + ~name:Interpreter_workload.N_IJoin_tickets + ~kinstr_and_stack_sampler:(fun config rng_state -> + let _, (module Samplers) = + make_default_samplers config.Default_config.sampler + in + fun () -> + let ticket = + Samplers.Random_value.value (ticket string) rng_state + in + let ticket = + { + ticket with + contents = Script_string.empty; + amount = Ticket_amount.one; + } + in + Ex_stack_and_kinstr + { + stack = ((ticket, ticket), eos); + stack_type; + kinstr = join_tickets_instr; + }) + () + + let () = + time_and_alloc (fun benchmark_type -> + benchmark + ~benchmark_type + ~name:Interpreter_workload.N_IJoin_tickets + ~kinstr_and_stack_sampler:(fun config rng_state -> + let _, (module Samplers) = + make_default_samplers config.Default_config.sampler + in + fun () -> + let ticket = + Samplers.Random_value.value (ticket string) rng_state + in + let alt_amount = + let amount = Samplers.Random_value.value nat rng_state in + let open Ticket_amount in + match of_n amount with + | Some amount -> add amount one + | None -> one + in + let ticket' = {ticket with amount = alt_amount} in + Ex_stack_and_kinstr + { + stack = ((ticket, ticket'), eos); + stack_type; + kinstr = join_tickets_instr; + }) + ()) ; + register_time_alloc_codegen_model (Instr_name N_IJoin_tickets) + end + + module Timelock = struct + let name = Interpreter_workload.N_IOpen_chest + + let stack_type = + Michelson_types.chest_key @$ Michelson_types.chest @$ nat @$ bot + + let kinstr = IOpen_chest (dummy_loc, halt) + + let resulting_stack chest chest_key time = + let chest = Script_timelock.make_chest chest in + let chest_key = Script_timelock.make_chest_key chest_key in + ( chest_key, + ( chest, + ( Script_int.is_nat (Script_int.of_int time) + |> WithExceptions.Option.get ~loc:"Timelock:gas benchmarks", + eos ) ) ) + + let () = + benchmark_with_stack_sampler + ~intercept:true + ~name + ~kinstr + ~stack_type + ~stack_sampler:(fun _ rng_state () -> + let time = 1 in + let chest, chest_key = + Timelock_samplers.chest_sampler ~plaintext_size:1 ~time ~rng_state + in + resulting_stack chest chest_key time) + () + + let () = + time_and_alloc @@ fun benchmark_type -> + benchmark_with_stack_sampler + ~benchmark_type + ~name + ~kinstr + ~stack_type + ~stack_sampler:(fun _ rng_state () -> + let log_time = + (* Chest generation takes too long time for [log_time > 20] *) + Base_samplers.sample_in_interval + ~range:{min = 0; max = 20} + rng_state + in + let time = Int.shift_left 1 log_time in + let plaintext_size = + Base_samplers.sample_in_interval + ~range:{min = 1; max = 10000} + rng_state + in + + let chest, chest_key = + Timelock_samplers.chest_sampler ~plaintext_size ~time ~rng_state + in + resulting_stack chest chest_key time) + () + + let () = register_time_alloc_codegen_model (Instr_name name) + end + + module Continuations = struct + let () = + (* + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KNil + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KNil in + let stack = eos in + let stack_type = bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KCons -> step + KHalt -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KCons + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KCons (halt, KNil) in + let stack = ((), eos) in + let stack_type = unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KReturn -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KReturn + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KReturn (eos, Some (unit @$ bot), KNil) in + let stack = ((), eos) in + let stack_type = unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KView_exit -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KView_exit + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let open Script_typed_ir in + let open Alpha_context in + let step_constants = + { + sender = Contract (Implicit Signature.Public_key_hash.zero); + payer = Signature.Public_key_hash.zero; + self = Contract_hash.zero; + amount = Tez.zero; + balance = Tez.zero; + chain_id = Chain_id.zero; + now = Script_timestamp.of_zint Z.zero; + level = Script_int.zero_n; + } + in + let cont = KView_exit (step_constants, KNil) in + let stack = ((), eos) in + let stack_type = unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KLoop_in -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KLoop_in + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KLoop_in (IPush (dummy_loc, bool, false, halt), KNil) in + let stack = (false, ((), eos)) in + let stack_type = bool @$ unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KLoop_in_left -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KLoop_in_left + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = + KLoop_in_left (ICons_right (dummy_loc, unit, halt), KNil) + in + let stack = (R (), eos) in + let stack_type = cor unit unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KUndip -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KUndip + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KUndip ((), Some unit, KNil) in + let stack = eos in + let stack_type = bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KIter (empty case) -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KIter_empty + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KIter (IDrop (dummy_loc, halt), Some unit, [], KNil) in + let stack = ((), eos) in + let stack_type = unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + (* + KIter (nonempty case) -> step + KDrop -> step + KHalt -> next + KIter (empty case) -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KIter_nonempty + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let cont = KIter (IDrop (dummy_loc, halt), Some unit, [()], KNil) in + let stack = ((), eos) in + let stack_type = unit @$ bot in + fun () -> Ex_stack_and_cont {stack; cont; stack_type}) + () + + let () = + let model = + Interpreter_model.Models.max_branching_model + ~case_0:"empty_const" + ~case_1:"nonempty_const" + "N_KIter" + in + register_model_for_code_generation model + + let () = + (* + KList_enter_body ([()], bot accumulator case) -> step + KHalt -> next + KList_exit_body ([], []) -> + KList_enter_body ([], [()] -> + List.rev singleton + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KList_enter_body + ~salt:"_singleton_list" + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let kbody = halt in + fun () -> + let cont = + KList_enter_body + (kbody, [()], Script_list.empty, Some (list unit), 1, KNil) + in + Ex_stack_and_cont + {stack = ((), eos); stack_type = unit @$ bot; cont}) + () + + let () = + (* + KList_enter_body (empty list, nonempty accumulator case) -> + {List.rev n elements} -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KList_enter_body + ~salt:"_terminal" + ~cont_and_stack_sampler:(fun cfg rng_state -> + let _, (module Samplers) = make_default_samplers cfg.sampler in + let kbody = halt in + fun () -> + let ys = Samplers.Random_value.value (list unit) rng_state in + let cont = + KList_enter_body (kbody, [], ys, Some (list unit), ys.length, KNil) + in + Ex_stack_and_cont + {stack = ((), eos); stack_type = unit @$ bot; cont}) + () + + let () = + (* + KList_enter_body (empty list, bot accumulator case) -> + {List.rev singleton} -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~intercept:true + ~name:Interpreter_workload.N_KList_enter_body + ~salt:"_terminal" + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let kbody = halt in + fun () -> + let cont = + KList_enter_body + (kbody, [], Script_list.empty, Some (list unit), 1, KNil) + in + Ex_stack_and_cont + {stack = ((), eos); stack_type = unit @$ bot; cont}) + () + + let () = + (* + KList_exit_body (empty list) -> next + KList_enter_body -> + {List.rev 1 element} -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~intercept:true + ~name:Interpreter_workload.N_KList_exit_body + ~salt:"_terminal" + ~cont_and_stack_sampler:(fun _cfg _rng_state -> + let kbody = halt in + let cont = + KList_exit_body + (kbody, [], Script_list.empty, Some (list unit), 1, KNil) + in + fun () -> + Ex_stack_and_cont + {stack = ((), ((), eos)); stack_type = unit @$ unit @$ bot; cont}) + () + + let stack_type = cpair int unit @$ unit @$ bot + + let map_enter_body_code = + let kbody = ICdr (dummy_loc, halt) in + fun accu -> + KMap_enter_body + (kbody, accu, Script_map.empty int, Some (map int unit), KNil) + + let () = + (* + KMap_enter_body (empty case) -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KMap_enter_body + ~salt:"_empty" + ~cont_and_stack_sampler:(fun _cfg _rng_state () -> + Ex_stack_and_cont + { + stack = ((), eos); + stack_type = unit @$ bot; + cont = map_enter_body_code []; + }) + () + + let () = + (* + KMap_enter_body (singleton case) -> step + KCdr -> step + KHalt -> next + KMap_exit_body -> next + (map_update) + KMap_enter_body (empty case) -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KMap_enter_body + ~salt:"_singleton" + ~cont_and_stack_sampler:(fun _cfg _rng_state () -> + Ex_stack_and_cont + { + stack = ((), eos); + stack_type = unit @$ bot; + cont = map_enter_body_code [(Script_int.zero, ())]; + }) + () + + let () = + (* + KMap_exit_body -> + (map_update) -> next + KMap_enter_body (empty case) -> next + KNil + *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KMap_exit_body + ~cont_and_stack_sampler:(fun cfg rng_state -> + let kbody = ICdr (dummy_loc, halt) in + fun () -> + let ty = map int unit in + let key, map = Maps.generate_map_and_key_not_in_map cfg rng_state in + let cont = KMap_exit_body (kbody, [], map, key, Some ty, KNil) in + Ex_stack_and_cont + {stack = ((), ((), eos)); stack_type = unit @$ unit @$ bot; cont}) + () + + let () = + (* KMap_head -> KNil *) + continuation_time_alloc_benchmark + ~amplification:100 + ~name:Interpreter_workload.N_KMap_head + ~cont_and_stack_sampler:(fun _cfg _rng_state () -> + let cont = KMap_head (Option.some, KNil) in + Ex_stack_and_cont + {stack = ((), ((), eos)); stack_type = unit @$ unit @$ bot; cont}) + () + end + + let () = + simple_time_alloc_benchmark + ~name:Interpreter_workload.N_IEmit + ~stack_type:(unit_t @$ bot) + ~kinstr: + (IEmit + { + ty = unit_t; + k = halt; + loc = dummy_loc; + tag = Entrypoint_repr.default; + unparsed_ty = Script_repr.unit; + }) + () +end diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_model.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_model.ml new file mode 100644 index 000000000000..0100cd5898be --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_model.ml @@ -0,0 +1,851 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let ns = Namespace.make Registration_helpers.ns "interpreter" + +let fv s = Free_variable.of_namespace (ns s) + +(* ------------------------------------------------------------------------- *) + +let trace_error expected given = + let open Interpreter_workload in + let exp = string_of_instr_or_cont expected in + let given = string_of_instr_or_cont given in + let msg = + Format.asprintf + "Interpreter_model: trace error, expected %s, given %s" + exp + given + in + Stdlib.failwith msg + +let arity_error instr expected given = + let open Interpreter_workload in + let s = string_of_instr_or_cont instr in + let msg = + Format.asprintf + "Interpreter_model: arity error (%s), expected %d, given %a" + s + expected + Interpreter_workload.pp_args + given + in + Stdlib.failwith msg + +(* ------------------------------------------------------------------------- *) + +let arity_to_int : type a b c. (a, b, c) Model.arity -> int = + fun arity -> + let rec aux : type x y z. int -> (x, y, z) Model.arity -> int = + fun i -> function + | Model.Zero_arity -> i + | Succ_arity arity -> aux (i + 1) arity + in + aux 0 arity + +let model_with_conv : + type a. + Interpreter_workload.instr_or_cont_name -> + a Model.model -> + Interpreter_workload.ir_sized_step Model.t = + fun instr model -> + let open Interpreter_workload in + let module M = (val model) in + let module I = Model.Instantiate (Costlang.Void) (M) in + let arity_init = I.arity in + let rec make_args : + type x y z. arg list -> arg list -> (x, y, z) Model.arity -> z = + fun args_init args arity -> + match (args, arity) with + | [], Zero_arity -> () + | {arg; _} :: l, Succ_arity arity -> (arg, make_args args_init l arity) + | _ -> arity_error instr (arity_to_int arity_init) args_init + in + let conv {name; args} = + if name = instr then make_args args args arity_init + else trace_error instr name + in + Model.make ~conv model + +let sf = Format.asprintf + +let division_cost name = + let const = fv (sf "%s_const" name) in + let size1_coeff = fv (sf "%s_size1_coeff" name) in + let q_coeff = fv (sf "%s_q_coeff" name) in + let q_size2_coeff = fv (sf "%s_q_size2_coeff" name) in + let module M = struct + type arg_type = int * (int * unit) + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + (* Actual [ediv] implementation uses different algorithms + depending on the size of the arguments. + Ideally, the cost function should be the combination of + multiple affine functions branching on the arguments, + but the current model fits with only one affine function for simplicity. + For more discussion, see https://gitlab.com/tezos/tezos/-/issues/5480 *) + let model = + lam ~name:"size1" @@ fun size1 -> + lam ~name:"size2" @@ fun size2 -> + (* Note that [q] is guaranteed to be non-negative because we use + saturated subtraction. When [size1 < size2], the model evaluates to + [const] as expected. *) + let_ ~name:"q" (sat_sub size1 size2) @@ fun q -> + (free ~name:q_size2_coeff * q * size2) + + (free ~name:size1_coeff * size1) + + (free ~name:q_coeff * q) + + free ~name:const + end + + let name = ns name + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + +let ediv_nat_alloc name = + let const = fv (sf "%s_const" name) in + let coeff1 = fv (sf "%s_coeff1" name) in + let coeff2 = fv (sf "%s_coeff2" name) in + let module M = struct + type arg_type = int * (int * unit) + + let name = ns name + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun size1 -> + lam ~name:"size2" @@ fun size2 -> + if_ + (lt size2 size1) + ((free ~name:coeff1 * size1) + (free ~name:coeff2 * size2)) + (int 0) + + free ~name:const + end + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + +let get_mem_alloc_const_model name = + let const = fv (sf "%s_const" name) in + let module M = struct + type arg_type = int * (int * unit) + + let name = ns name + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun (_size1 : size repr) -> + lam ~name:"size2" @@ fun (_size1 : size repr) -> free ~name:const + end + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + +let update_alloc_model name = + let const = fv (sf "%s_const" name) in + let coeff = fv (sf "%s_coeff" name) in + let module M = struct + type arg_type = int * (int * unit) + + let name = ns name + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun (_size1 : size repr) -> + lam ~name:"size2" @@ fun size2 -> + (free ~name:coeff * log2 (int 1 + size2)) + free ~name:const + end + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + +let addlogadd name = + let const = fv (sf "%s_const" name) in + let coeff = fv (sf "%s_coeff" name) in + let module M = struct + type arg_type = int * (int * unit) + + let name = ns name + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun size1 -> + lam ~name:"size2" @@ fun size2 -> + let_ ~name:"a" (size1 + size2) @@ fun a -> + (free ~name:coeff * (a * log2 (int 1 + a))) + free ~name:const + end + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + +let name_of_instr_or_cont instr_or_cont = + Interpreter_workload.string_of_instr_or_cont instr_or_cont + +module Models = struct + let const1_model name = + (* For constant-time instructions *) + Model.unknown_const1 ~name:(ns name) ~const:(fv (sf "%s_const" name)) + + let const1_skip1_model name = + (* For constant-time instructions *) + Model.unknown_const1_skip1 ~name:(ns name) ~const:(fv (sf "%s_const" name)) + + let const1_skip2_model name = + (* For constant-time instructions *) + Model.unknown_const1_skip2 ~name:(ns name) ~const:(fv (sf "%s_const" name)) + + let affine_model name = + (* For instructions with cost function + [\lambda size. const + coeff * size] *) + Model.affine + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + + let affine_offset_model name ~offset = + (* For instructions with cost function + [\lambda size. const + coeff * (size - offset)] *) + Model.affine_offset + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + ~offset + + let break_model name break = + Model.breakdown + ~name:(ns name) + ~coeff1:(fv (sf "%s_coeff1" name)) + ~coeff2:(fv (sf "%s_coeff2" name)) + ~break + + let break_model_2 name break1 break2 = + Model.breakdown2 + ~name:(ns name) + ~coeff1:(fv (sf "%s_coeff1" name)) + ~coeff2:(fv (sf "%s_coeff2" name)) + ~coeff3:(fv (sf "%s_coeff3" name)) + ~break1 + ~break2 + + let break_model_2_const name break1 break2 = + Model.breakdown2_const + ~name:(ns name) + ~coeff1:(fv (sf "%s_coeff1" name)) + ~coeff2:(fv (sf "%s_coeff2" name)) + ~coeff3:(fv (sf "%s_coeff3" name)) + ~const:(fv (sf "%s_const" name)) + ~break1 + ~break2 + + let break_model_2_const_offset name break1 break2 ~offset = + Model.breakdown2_const_offset + ~name:(ns name) + ~coeff1:(fv (sf "%s_coeff1" name)) + ~coeff2:(fv (sf "%s_coeff2" name)) + ~coeff3:(fv (sf "%s_coeff3" name)) + ~const:(fv (sf "%s_const" name)) + ~break1 + ~break2 + ~offset + + let nlogm_model name = + (* For instructions with cost function + [\lambda size1. \lambda size2. const + coeff * size1 log2(size2)] *) + Model.nlogm + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + + let concat_model name = + Model.bilinear_affine + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff1:(fv (sf "%s_total_bytes" name)) + ~coeff2:(fv (sf "%s_list_length" name)) + + let bilinear_affine_model name = + Model.bilinear_affine + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff1:(fv (sf "%s_coeff1" name)) + ~coeff2:(fv (sf "%s_coeff2" name)) + + let affine_skip1_model name = + Model.affine_skip1 + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + + let linear_sum_model name = + Model.linear_sum + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + + let linear_max_model name = + (* For instructions with cost function + [\lambda size1. \lambda size2. const + coeff * max(size1,size2)] *) + Model.linear_max + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + + let linear_min_model name = + (* For instructions with cost function + [\lambda size1. \lambda size2. const + coeff * min(size1,size2)] *) + Model.linear_min + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + + let linear_min_offset_model name ~offset = + (* For instructions with cost function + [\lambda size1. \lambda size2. const + coeff * (min(size1,size2) - offset)] *) + Model.linear_min_offset + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff:(fv (sf "%s_coeff" name)) + ~offset + + let pack_model name = + Model.trilinear + ~name:(ns name) + ~coeff1:(fv (sf "%s_micheline_nodes" name)) + ~coeff2:(fv (sf "%s_micheline_int_bytes" name)) + ~coeff3:(fv (sf "%s_micheline_string_bytes" name)) + + let open_chest_model name = + let module M = struct + type arg_type = int * (int * unit) + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun size1 -> + lam ~name:"size2" @@ fun size2 -> + free ~name:(fv (sf "%s_const" name)) + + free ~name:(fv (sf "%s_log_time_coeff" name)) + * sat_sub size1 (int 1) + + (free ~name:(fv (sf "%s_plaintext_coeff" name)) * size2) + end + + let name = ns name + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + + let verify_update_model name = + Model.bilinear_affine + ~name:(ns name) + ~intercept:(fv (sf "%s_const" name)) + ~coeff1:(fv (sf "%s_inputs" name)) + ~coeff2:(fv (sf "%s_outputs" name)) + + let list_enter_body_model name = + let module M = struct + type arg_type = int * (int * unit) + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size_xs" @@ fun size_xs -> + lam ~name:"size_ys" @@ fun size_ys -> + if_ + (eq size_xs (int 0)) + (free ~name:(fv (sf "%s_const" name)) + + (free ~name:(fv (sf "%s_coeff" name)) * size_ys)) + (free ~name:(fv (sf "%s_iter" name))) + end + + let name = ns name + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + + let branching_model ~case_0 ~case_1 name = + let module M = struct + type arg_type = int * unit + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size + + let arity = Model.arity_1 + + let model = + lam ~name:"size" @@ fun size -> + if_ + (eq size (int 0)) + (free ~name:(fv (sf "%s_%s" name case_0))) + (free ~name:(fv (sf "%s_%s" name case_1))) + end + + let name = ns name + end in + (module M : Model.Model_impl with type arg_type = int * unit) + + let empty_branch_model name = + branching_model ~case_0:"empty" ~case_1:"nonempty" name + + let max_branching_model ~case_0 ~case_1 name = + let module M = struct + type arg_type = unit + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size + + let arity = Model.arity_0 + + let model = + max + (free ~name:(fv (sf "%s_%s" name case_0))) + (free ~name:(fv (sf "%s_%s" name case_1))) + end + + let name = ns name + end in + (module M : Model.Model_impl with type arg_type = unit) + + let lambda_model name = + (* branch whether lambda is rec or nonrec *) + branching_model ~case_0:"lam" ~case_1:"lamrec" name + + let join_tickets_model name = + let module M = struct + type arg_type = int * (int * (int * (int * unit))) + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size -> size -> size + + let arity = Model.Succ_arity Model.arity_3 + + let model = + lam ~name:"content_size_x" @@ fun content_size_x -> + lam ~name:"content_size_y" @@ fun content_size_y -> + lam ~name:"amount_size_x" @@ fun amount_size_x -> + lam ~name:"amount_size_y" @@ fun amount_size_y -> + free ~name:(fv (sf "%s_const" name)) + + free ~name:(fv (sf "%s_compare_coeff" name)) + * min content_size_x content_size_y + + free ~name:(fv (sf "%s_add_coeff" name)) + * max amount_size_x amount_size_y + end + + let name = ns name + end in + (module M : Model.Model_impl + with type arg_type = int * (int * (int * (int * unit)))) + + let join_tickets_alloc_model name = + let module M = struct + type arg_type = int * (int * (int * (int * unit))) + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size -> size -> size + + let arity = Model.Succ_arity Model.arity_3 + + let model = + lam ~name:"content_size_x" @@ fun (_ : size repr) -> + lam ~name:"content_size_y" @@ fun (_ : size repr) -> + lam ~name:"amount_size_x" @@ fun amount_size_x -> + lam ~name:"amount_size_y" @@ fun amount_size_y -> + free ~name:(fv (sf "%s_const" name)) + + free ~name:(fv (sf "%s_add_coeff" name)) + * max amount_size_x amount_size_y + end + + let name = ns name + end in + (module M : Model.Model_impl + with type arg_type = int * (int * (int * (int * unit)))) + + (* Almost [Model.bilinear_affine] but the intercept is not at 0s + but size1=0 and size2=1 *) + let lsl_bytes_model name = + let intercept = fv (sf "%s_const" name) in + let coeff1 = fv (sf "%s_bytes" name) in + let coeff2 = fv (sf "%s_shift" name) in + let module M = struct + type arg_type = int * (int * unit) + + let name = ns name + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun size1 -> + lam ~name:"size2" @@ fun size2 -> + free ~name:intercept + + (free ~name:coeff1 * size1) + + (free ~name:coeff2 * sat_sub size2 (int 1)) + end + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) + + (* The intercept is not at 0s but size1=0 and size2=1 *) + let lsr_bytes_model name = + let const = fv (sf "%s_const" name) in + let coeff = fv (sf "%s_coeff" name) in + let module M = struct + type arg_type = int * (int * unit) + + let takes_saturation_reprs = false + + module Def (X : Costlang.S) = struct + open X + + type model_type = size -> size -> size + + let arity = Model.arity_2 + + let model = + lam ~name:"size1" @@ fun size1 -> + lam ~name:"size2" @@ fun size2 -> + (* Note that [q] is guaranteed to be non-negative because we use + saturated subtraction. When [size1 < size2], the model evaluates to + [const] as expected. *) + let_ ~name:"q" (sat_sub size1 (size2 * float 0.125)) @@ fun q -> + free ~name:const + (free ~name:coeff * q) + end + + let name = ns name + end in + (module M : Model.Model_impl with type arg_type = int * (int * unit)) +end + +type ir_model = + | TimeModel : 'a Model.model -> ir_model + | TimeAllocModel : { + name : Namespace.t; (* name for synthesized model *) + time : 'a Model.model; + alloc : 'a Model.model; + } + -> ir_model + +let ir_model instr_or_cont = + let open Interpreter_workload in + let open Models in + let name = name_of_instr_or_cont instr_or_cont in + let m2 name (time, alloc) = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6072 + Change naming convention. + The current naming convention is for backward compatibility. + When we finally switch to the time-allocation model, + "_synthesized" should be removed and the time model should be qualified with "_time" + *) + TimeAllocModel + { + name = ns (name ^ "_synthesized"); + time = time name; + alloc = alloc (name ^ "_alloc"); + } + in + match instr_or_cont with + | Instr_name instr -> ( + match instr with + | N_IDrop | N_IDup | N_ISwap | N_IPush | N_IUnit | N_ICons_pair | N_ICar + | N_ICdr | N_ICons_some | N_ICons_none | N_IIf_none | N_ILeft | N_IRight + | N_IIf_left | N_ICons_list | N_INil | N_IIf_cons | N_IEmpty_set + | N_IEmpty_map | N_IEmpty_big_map | N_IOr | N_IAnd | N_IXor | N_INot + | N_IIf | N_ILoop_in | N_ILoop_out | N_ILoop_left_in | N_ILoop_left_out + | N_IDip | N_IExec | N_IView | N_IFailwith | N_IAddress + | N_ICreate_contract | N_ISet_delegate | N_INow | N_IMin_block_time + | N_IBalance | N_IHash_key | N_IUnpack | N_ISource | N_ISender | N_ISelf + | N_IAmount | N_IChainId | N_ILevel | N_ISelf_address | N_INever + | N_IUnpair | N_IVoting_power | N_ITotal_voting_power | N_IList_size + | N_ISet_size | N_IMap_size | N_ISapling_empty_state -> + (const1_model, const1_model) |> m2 name + | N_ISet_mem | N_IMap_mem | N_IMap_get | N_IBig_map_mem | N_IBig_map_get + -> + (nlogm_model, get_mem_alloc_const_model) |> m2 name + | N_ISet_update | N_IMap_update | N_IBig_map_update + | N_IMap_get_and_update | N_IBig_map_get_and_update -> + (nlogm_model, update_alloc_model) |> m2 name + | N_IConcat_string -> (concat_model, concat_model) |> m2 name + | N_IConcat_string_pair -> (linear_sum_model, linear_sum_model) |> m2 name + | N_ISlice_string -> (affine_model, affine_model) |> m2 name + | N_IString_size -> (const1_model, const1_model) |> m2 name + | N_IConcat_bytes -> (concat_model, concat_model) |> m2 name + | N_IConcat_bytes_pair -> (linear_sum_model, linear_sum_model) |> m2 name + | N_ISlice_bytes -> (affine_model, affine_model) |> m2 name + | N_IBytes_size -> (const1_model, const1_model) |> m2 name + | N_IOr_bytes -> (linear_max_model, linear_max_model) |> m2 name + | N_IAnd_bytes -> (linear_min_model, linear_min_model) |> m2 name + | N_IXor_bytes -> (linear_max_model, linear_max_model) |> m2 name + | N_INot_bytes -> (affine_model, affine_model) |> m2 name + | N_ILsl_bytes -> (lsl_bytes_model, lsl_bytes_model) |> m2 name + | N_ILsr_bytes -> (lsr_bytes_model, lsr_bytes_model) |> m2 name + | N_IBytes_nat | N_INat_bytes | N_IBytes_int | N_IInt_bytes -> + (affine_model, affine_model) |> m2 name + | N_IAdd_seconds_to_timestamp | N_IAdd_timestamp_to_seconds + | N_ISub_timestamp_seconds | N_IDiff_timestamps -> + (linear_max_model, linear_max_model) |> m2 name + | N_IAdd_tez | N_ISub_tez | N_ISub_tez_legacy | N_IEdiv_tez + | N_IMul_teznat | N_IMul_nattez | N_IEdiv_teznat -> + (const1_model, const1_model) |> m2 name + | N_IIs_nat -> (const1_model, const1_model) |> m2 name + | N_INeg -> (affine_model, affine_model) |> m2 name + | N_IAbs_int -> (affine_model, affine_model) |> m2 name + | N_IInt_nat -> (const1_model, const1_model) |> m2 name + | N_IAdd_int -> (linear_max_model, linear_max_model) |> m2 name + | N_IAdd_nat -> (linear_max_model, linear_max_model) |> m2 name + | N_ISub_int -> (linear_max_model, linear_max_model) |> m2 name + | N_IMul_int -> (addlogadd, linear_sum_model) |> m2 name + | N_IMul_nat -> (addlogadd, linear_sum_model) |> m2 name + | N_IEdiv_int -> (division_cost, linear_max_model) |> m2 name + | N_IEdiv_nat -> (division_cost, ediv_nat_alloc) |> m2 name + | N_ILsl_nat -> + (* The interpreter limits the amount of shfit to 256 *) + (affine_model, affine_model) |> m2 name + | N_ILsr_nat -> (affine_model, affine_model) |> m2 name + | N_IOr_nat -> (linear_max_model, linear_max_model) |> m2 name + | N_IAnd_nat -> (linear_min_model, linear_min_model) |> m2 name + | N_IAnd_int_nat -> (linear_min_model, affine_skip1_model) |> m2 name + | N_IXor_nat -> (linear_max_model, linear_max_model) |> m2 name + | N_INot_int -> (affine_model, affine_model) |> m2 name + | N_ICompare -> + (linear_min_offset_model ~offset:1, const1_skip2_model) |> m2 name + | N_IEq | N_INeq | N_ILt | N_IGt | N_ILe | N_IGe -> + (const1_model, const1_model) |> m2 name + | N_IPack -> (pack_model, pack_model) |> m2 name + | N_IBlake2b | N_ISha256 | N_ISha512 | N_IKeccak | N_ISha3 -> + (affine_model, const1_skip1_model) |> m2 name + | N_ICheck_signature_ed25519 | N_ICheck_signature_secp256k1 + | N_ICheck_signature_p256 | N_ICheck_signature_bls -> + (affine_model, const1_skip1_model) |> m2 name + | N_IContract | N_ITransfer_tokens | N_IImplicit_account -> + (const1_model, const1_model) |> m2 name + (* The following two instructions are expected to have an affine model. However, + we observe 3 affine parts, on [0;300], [300;400] and [400;\inf[. *) + | N_IDupN -> + ( (fun name -> break_model_2_const_offset name 300 400 ~offset:1), + fun name -> break_model_2_const_offset name 300 400 ~offset:1 ) + |> m2 name + | N_IDropN -> + ( (fun name -> break_model_2_const name 300 400), + fun name -> break_model_2_const name 300 400 ) + |> m2 name + | N_IDig | N_IDug | N_IDipN -> (affine_model, affine_model) |> m2 name + | N_IAdd_bls12_381_g1 | N_IAdd_bls12_381_g2 | N_IAdd_bls12_381_fr + | N_IMul_bls12_381_g1 | N_IMul_bls12_381_g2 | N_IMul_bls12_381_fr + | N_INeg_bls12_381_g1 | N_INeg_bls12_381_g2 | N_INeg_bls12_381_fr + | N_IInt_bls12_381_z_fr -> + (const1_model, const1_model) |> m2 name + | N_IMul_bls12_381_fr_z | N_IMul_bls12_381_z_fr + | N_IPairing_check_bls12_381 -> + (affine_model, const1_skip1_model) |> m2 name + | N_IComb | N_IUncomb -> + (affine_offset_model ~offset:2, affine_model) |> m2 name + | N_IComb_get | N_IComb_set -> (affine_model, affine_model) |> m2 name + | N_ITicket | N_IRead_ticket -> (const1_model, const1_model) |> m2 name + | N_ISplit_ticket -> (linear_max_model, const1_skip2_model) |> m2 name + | N_IJoin_tickets -> + (join_tickets_model, join_tickets_alloc_model) |> m2 name + | N_ISapling_verify_update -> + (verify_update_model, verify_update_model) |> m2 name + | N_IList_map -> (const1_model, const1_model) |> m2 name + | N_IList_iter | N_IIter -> (const1_model, const1_model) |> m2 name + | N_IMap_map -> (affine_model, const1_skip1_model) |> m2 name + | N_IMap_iter -> (affine_model, const1_skip1_model) |> m2 name + | N_ISet_iter -> (affine_model, const1_skip1_model) |> m2 name + | N_IHalt -> (const1_model, const1_model) |> m2 name + | N_IApply -> (lambda_model, lambda_model) |> m2 name + | N_ILambda_lam | N_ILambda_lamrec | N_ILog -> + (const1_model, const1_model) |> m2 name + | N_IOpen_chest -> (open_chest_model, open_chest_model) |> m2 name + | N_IEmit | N_IOpt_map_none | N_IOpt_map_some -> + (const1_model, const1_model) |> m2 name) + | Cont_name cont -> ( + match cont with + | N_KNil | N_KCons | N_KReturn | N_KView_exit | N_KMap_head | N_KUndip + | N_KLoop_in | N_KLoop_in_left | N_KIter_empty | N_KIter_nonempty -> + (const1_model, const1_model) |> m2 name + | N_KList_enter_body -> + (list_enter_body_model, list_enter_body_model) |> m2 name + | N_KList_exit_body -> (const1_model, const1_model) |> m2 name + | N_KMap_enter_body -> (empty_branch_model, empty_branch_model) |> m2 name + | N_KMap_exit_body -> (nlogm_model, update_alloc_model) |> m2 name + | N_KLog -> (const1_model, const1_model) |> m2 name) + +module SynthesizeTimeAlloc : Model.Binary_operation = struct + module Def (X : Costlang.S) = struct + let op time alloc = X.(max time alloc) + end +end + +let pack_time_model = function + | TimeModel m -> Model.Model m + | TimeAllocModel {time; _} -> Model.Model time + +let pack_alloc_model = function + | TimeModel _ -> assert false + | TimeAllocModel {alloc; _} -> Model.Model alloc + +let pack_time_alloc_model = function + | TimeModel _ -> assert false + | TimeAllocModel {name; time; alloc} -> + Model.Model + (Model.synthesize + ~name + ~binop:(module SynthesizeTimeAlloc) + ~x_label:"time" + ~x_model:time + ~y_label:"alloc" + ~y_model:alloc) + +let amplification_loop_iteration = fv "amplification_loop_iteration" + +let amplification_loop_model = + Model.make + ~conv:(fun iterations -> (iterations, ())) + (Model.linear + ~name:(ns "amplification_loop_model") + ~coeff:amplification_loop_iteration) + +(* The following model stitches together the per-instruction models and + adds a term corresponding to the amplification (if needed). *) +let interpreter_model ?amplification pack_model sub_model = + Model.make_aggregated + ~model:(fun trace -> + let module Def (X : Costlang.S) = struct + type t = X.size X.repr + + let applied = + let initial = + match amplification with + | None -> X.int 0 + | Some amplification_factor -> + let (module Amplification_applied) = + Model.apply amplification_loop_model amplification_factor + in + let module Amplification_result = Amplification_applied (X) in + Amplification_result.applied + in + List.fold_left + (fun (acc : X.size X.repr) instr_trace -> + let name = instr_trace.Interpreter_workload.name in + let (Model.Model model) = pack_model (ir_model name) in + let (module Applied_instr) = + Model.apply (model_with_conv name model) instr_trace + in + let module R = Applied_instr (X) in + X.(acc + R.applied)) + initial + trace + end in + ((module Def) : Model.applied)) + ~sub_models:[pack_model sub_model] + +type benchmark_type = Registration_helpers.benchmark_type = Time | Alloc + +let make_time_model ?amplification instr_name = + let ir_model = ir_model instr_name in + [("interpreter", interpreter_model ?amplification pack_time_model ir_model)] + +let make_alloc_model instr_name = + let ir_model = ir_model instr_name in + [("interpreter", interpreter_model pack_alloc_model ir_model)] + +let make_model ?amplification benchmark_type instr_name = + match benchmark_type with + | Time -> make_time_model ?amplification instr_name + | Alloc -> + (* amplification wouldn't make sense, + because the measurement resolution doesn't matter for the allocation *) + assert (amplification = None) ; + make_alloc_model instr_name + +let make_time_alloc_codegen_model instr_name = + pack_time_alloc_model (ir_model instr_name) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_workload.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_workload.ml new file mode 100644 index 000000000000..c7c16d355f91 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/interpreter_workload.ml @@ -0,0 +1,1717 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module Size = Gas_input_size + +(* ------------------------------------------------------------------------- *) + +type id = string + +let pp_id = Format.pp_print_string + +let equal_id = String.equal + +(* ------------------------------------------------------------------------- *) +(* Names of IR instructions together with sizes of their operands as + encountered during evaluation. *) + +type instruction_name = + (* stack ops *) + | N_IDrop + | N_IDup + | N_ISwap + | N_IPush + | N_IUnit + (* pairs *) + | N_ICons_pair + | N_ICar + | N_ICdr + | N_IUnpair + (* options *) + | N_ICons_some + | N_ICons_none + | N_IIf_none + | N_IOpt_map_none + | N_IOpt_map_some + (* ors *) + | N_ILeft + | N_IRight + | N_IIf_left + (* lists *) + | N_ICons_list + | N_INil + | N_IIf_cons + | N_IList_map + | N_IList_iter + | N_IIter + | N_IList_size + (* sets *) + | N_IEmpty_set + | N_ISet_iter + | N_ISet_mem + | N_ISet_update + | N_ISet_size + (* maps *) + | N_IEmpty_map + | N_IMap_map + | N_IMap_iter + | N_IMap_mem + | N_IMap_get + | N_IMap_update + | N_IMap_get_and_update + | N_IMap_size + (* big maps *) + | N_IEmpty_big_map + | N_IBig_map_mem + | N_IBig_map_get + | N_IBig_map_update + | N_IBig_map_get_and_update + (* string operations *) + | N_IConcat_string + | N_IConcat_string_pair + | N_ISlice_string + | N_IString_size + (* bytes operations *) + | N_IConcat_bytes + | N_IConcat_bytes_pair + | N_ISlice_bytes + | N_IBytes_size + | N_IOr_bytes + | N_IAnd_bytes + | N_IXor_bytes + | N_INot_bytes + | N_ILsl_bytes + | N_ILsr_bytes + | N_IBytes_nat + | N_INat_bytes + | N_IBytes_int + | N_IInt_bytes + (* timestamp operations *) + | N_IAdd_seconds_to_timestamp + | N_IAdd_timestamp_to_seconds + | N_ISub_timestamp_seconds + | N_IDiff_timestamps + (* currency operations *) + | N_IAdd_tez + | N_ISub_tez + | N_ISub_tez_legacy + | N_IMul_teznat + | N_IMul_nattez + | N_IEdiv_teznat + | N_IEdiv_tez + (* boolean operations - assumed O(1) *) + | N_IOr + | N_IAnd + | N_IXor + | N_INot + (* integer operations *) + | N_IIs_nat + | N_INeg + | N_IAbs_int + | N_IInt_nat + | N_IAdd_int + | N_IAdd_nat + | N_ISub_int + | N_IMul_int + | N_IMul_nat + | N_IEdiv_int + | N_IEdiv_nat + | N_ILsl_nat + | N_ILsr_nat + | N_IOr_nat + | N_IAnd_nat + | N_IAnd_int_nat + | N_IXor_nat + | N_INot_int + (* control *) + | N_IIf + | N_ILoop_in + | N_ILoop_out + | N_ILoop_left_in + | N_ILoop_left_out + | N_IDip + | N_IExec + | N_IApply + | N_ILambda_lam + | N_ILambda_lamrec + | N_IFailwith + (* comparison, warning: ad-hoc polymorphic instruction *) + | N_ICompare + (* comparators *) + | N_IEq + | N_INeq + | N_ILt + | N_IGt + | N_ILe + | N_IGe + (* protocol *) + | N_IAddress + | N_IContract + | N_ITransfer_tokens + | N_IImplicit_account + | N_ICreate_contract + | N_ISet_delegate + (* time *) + | N_INow + | N_IMin_block_time + (* other *) + | N_IBalance + | N_ILevel + | N_IView + (* We specialize the check-signature instruction for each crypto scheme. *) + | N_ICheck_signature_ed25519 + | N_ICheck_signature_secp256k1 + | N_ICheck_signature_p256 + | N_ICheck_signature_bls + | N_IHash_key + | N_IPack + | N_IUnpack + | N_IBlake2b + | N_ISha256 + | N_ISha512 + | N_ISource + | N_ISender + | N_ISelf + | N_ISelf_address + | N_IAmount + | N_ISapling_empty_state + | N_ISapling_verify_update + | N_IDig + | N_IDug + | N_IDipN + | N_IDropN + | N_IChainId + | N_INever + | N_IVoting_power + | N_ITotal_voting_power + | N_IKeccak + | N_ISha3 + (* Elliptic curves *) + | N_IAdd_bls12_381_g1 + | N_IAdd_bls12_381_g2 + | N_IAdd_bls12_381_fr + | N_IMul_bls12_381_g1 + | N_IMul_bls12_381_g2 + | N_IMul_bls12_381_fr + | N_INeg_bls12_381_g1 + | N_INeg_bls12_381_g2 + | N_INeg_bls12_381_fr + | N_IMul_bls12_381_fr_z + | N_IMul_bls12_381_z_fr + | N_IInt_bls12_381_z_fr + | N_IPairing_check_bls12_381 + (* Combs *) + | N_IComb + | N_IUncomb + | N_IComb_get + | N_IComb_set + | N_IDupN + (* Tickets *) + | N_ITicket + | N_IRead_ticket + | N_ISplit_ticket + | N_IJoin_tickets + (* Misc *) + | N_IHalt + | N_ILog + (* Timelock*) + | N_IOpen_chest + (* Event *) + | N_IEmit + +type continuation_name = + | N_KNil + | N_KCons + | N_KReturn + | N_KView_exit + | N_KMap_head + | N_KUndip + | N_KLoop_in + | N_KLoop_in_left + | N_KIter_empty + | N_KIter_nonempty + | N_KList_enter_body + | N_KList_exit_body + | N_KMap_enter_body + | N_KMap_exit_body + | N_KLog + +and instr_or_cont_name = + | Instr_name of instruction_name + | Cont_name of continuation_name + +(* ------------------------------------------------------------------------- *) +(* Code that ought to be auto-generated *) + +let string_of_instruction_name : instruction_name -> string = + fun ir -> + match ir with + | N_IDrop -> "N_IDrop" + | N_IDup -> "N_IDup" + | N_ISwap -> "N_ISwap" + | N_IPush -> "N_IPush" + | N_IUnit -> "N_IUnit" + | N_ICons_pair -> "N_ICons_pair" + | N_ICar -> "N_ICar" + | N_ICdr -> "N_ICdr" + | N_ICons_some -> "N_ICons_some" + | N_ICons_none -> "N_ICons_none" + | N_IIf_none -> "N_IIf_none" + | N_IOpt_map_none -> "N_IOpt_map_none" + | N_IOpt_map_some -> "N_IOpt_map_some" + | N_ILeft -> "N_ILeft" + | N_IRight -> "N_IRight" + | N_IIf_left -> "N_IIf_left" + | N_ICons_list -> "N_ICons_list" + | N_INil -> "N_INil" + | N_IIf_cons -> "N_IIf_cons" + | N_IList_map -> "N_IList_map" + | N_IList_iter -> "N_IList_iter" + | N_IIter -> "N_IIter" + | N_IList_size -> "N_IList_size" + | N_IEmpty_set -> "N_IEmpty_set" + | N_ISet_iter -> "N_ISet_iter" + | N_ISet_mem -> "N_ISet_mem" + | N_ISet_update -> "N_ISet_update" + | N_ISet_size -> "N_ISet_size" + | N_IEmpty_map -> "N_IEmpty_map" + | N_IMap_map -> "N_IMap_map" + | N_IMap_iter -> "N_IMap_iter" + | N_IMap_mem -> "N_IMap_mem" + | N_IMap_get -> "N_IMap_get" + | N_IMap_update -> "N_IMap_update" + | N_IMap_size -> "N_IMap_size" + | N_IEmpty_big_map -> "N_IEmpty_big_map" + | N_IBig_map_mem -> "N_IBig_map_mem" + | N_IBig_map_get -> "N_IBig_map_get" + | N_IBig_map_update -> "N_IBig_map_update" + | N_IConcat_string -> "N_IConcat_string" + | N_IConcat_string_pair -> "N_IConcat_string_pair" + | N_ISlice_string -> "N_ISlice_string" + | N_IString_size -> "N_IString_size" + | N_IConcat_bytes -> "N_IConcat_bytes" + | N_IConcat_bytes_pair -> "N_IConcat_bytes_pair" + | N_ISlice_bytes -> "N_ISlice_bytes" + | N_IBytes_size -> "N_IBytes_size" + | N_IOr_bytes -> "N_IOr_bytes" + | N_IAnd_bytes -> "N_IAnd_bytes" + | N_IXor_bytes -> "N_IXor_bytes" + | N_INot_bytes -> "N_INot_bytes" + | N_ILsl_bytes -> "N_ILsl_bytes" + | N_ILsr_bytes -> "N_ILsr_bytes" + | N_IBytes_nat -> "N_IBytes_nat" + | N_INat_bytes -> "N_INat_bytes" + | N_IBytes_int -> "N_IBytes_int" + | N_IInt_bytes -> "N_IInt_bytes" + | N_IAdd_seconds_to_timestamp -> "N_IAdd_seconds_to_timestamp" + | N_IAdd_timestamp_to_seconds -> "N_IAdd_timestamp_to_seconds" + | N_ISub_timestamp_seconds -> "N_ISub_timestamp_seconds" + | N_IDiff_timestamps -> "N_IDiff_timestamps" + | N_IAdd_tez -> "N_IAdd_tez" + | N_ISub_tez -> "N_ISub_tez" + | N_ISub_tez_legacy -> "N_ISub_tez_legacy" + | N_IMul_teznat -> "N_IMul_teznat" + | N_IMul_nattez -> "N_IMul_nattez" + | N_IEdiv_teznat -> "N_IEdiv_teznat" + | N_IEdiv_tez -> "N_IEdiv_tez" + | N_IOr -> "N_IOr" + | N_IAnd -> "N_IAnd" + | N_IXor -> "N_IXor" + | N_INot -> "N_INot" + | N_IIs_nat -> "N_IIs_nat" + | N_INeg -> "N_INeg" + | N_IAbs_int -> "N_IAbs_int" + | N_IInt_nat -> "N_IInt_nat" + | N_IAdd_int -> "N_IAdd_int" + | N_IAdd_nat -> "N_IAdd_nat" + | N_ISub_int -> "N_ISub_int" + | N_IMul_int -> "N_IMul_int" + | N_IMul_nat -> "N_IMul_nat" + | N_IEdiv_int -> "N_IEdiv_int" + | N_IEdiv_nat -> "N_IEdiv_nat" + | N_ILsl_nat -> "N_ILsl_nat" + | N_ILsr_nat -> "N_ILsr_nat" + | N_IOr_nat -> "N_IOr_nat" + | N_IAnd_nat -> "N_IAnd_nat" + | N_IAnd_int_nat -> "N_IAnd_int_nat" + | N_IXor_nat -> "N_IXor_nat" + | N_INot_int -> "N_INot_int" + | N_IIf -> "N_IIf" + | N_ILoop_in -> "N_ILoop_in" + | N_ILoop_out -> "N_ILoop_out" + | N_ILoop_left_in -> "N_ILoop_left_in" + | N_ILoop_left_out -> "N_ILoop_left_out" + | N_IDip -> "N_IDip" + | N_IExec -> "N_IExec" + | N_IApply -> "N_IApply" + | N_ILambda_lam -> "N_ILambda_lam" + | N_ILambda_lamrec -> "N_ILambda_lamrec" + | N_IFailwith -> "N_IFailwith" + | N_ICompare -> "N_ICompare" + | N_IEq -> "N_IEq" + | N_INeq -> "N_INeq" + | N_ILt -> "N_ILt" + | N_IGt -> "N_IGt" + | N_ILe -> "N_ILe" + | N_IGe -> "N_IGe" + | N_IAddress -> "N_IAddress" + | N_IContract -> "N_IContract" + | N_ITransfer_tokens -> "N_ITransfer_tokens" + | N_IImplicit_account -> "N_IImplicit_account" + | N_ICreate_contract -> "N_ICreate_contract" + | N_ISet_delegate -> "N_ISet_delegate" + | N_INow -> "N_INow" + | N_IMin_block_time -> "N_IMin_block_time" + | N_IBalance -> "N_IBalance" + | N_ICheck_signature_ed25519 -> "N_ICheck_signature_ed25519" + | N_ICheck_signature_secp256k1 -> "N_ICheck_signature_secp256k1" + | N_ICheck_signature_p256 -> "N_ICheck_signature_p256" + | N_ICheck_signature_bls -> "N_ICheck_signature_bls" + | N_IHash_key -> "N_IHash_key" + | N_IPack -> "N_IPack" + | N_IUnpack -> "N_IUnpack" + | N_IBlake2b -> "N_IBlake2b" + | N_ISha256 -> "N_ISha256" + | N_ISha512 -> "N_ISha512" + | N_ISource -> "N_ISource" + | N_ISender -> "N_ISender" + | N_ISelf -> "N_ISelf" + | N_IAmount -> "N_IAmount" + | N_IDig -> "N_IDig" + | N_IDug -> "N_IDug" + | N_IDipN -> "N_IDipN" + | N_IDropN -> "N_IDropN" + | N_IDupN -> "N_IDupN" + | N_IChainId -> "N_IChainId" + | N_ILevel -> "N_ILevel" + | N_IView -> "N_IView" + | N_ISelf_address -> "N_ISelf_address" + | N_INever -> "N_INever" + | N_IUnpair -> "N_IUnpair" + | N_IVoting_power -> "N_IVoting_power" + | N_ITotal_voting_power -> "N_ITotal_voting_power" + | N_IKeccak -> "N_IKeccak" + | N_ISha3 -> "N_ISha3" + | N_IAdd_bls12_381_g1 -> "N_IAdd_bls12_381_g1" + | N_IAdd_bls12_381_g2 -> "N_IAdd_bls12_381_g2" + | N_IAdd_bls12_381_fr -> "N_IAdd_bls12_381_fr" + | N_IMul_bls12_381_g1 -> "N_IMul_bls12_381_g1" + | N_IMul_bls12_381_g2 -> "N_IMul_bls12_381_g2" + | N_IMul_bls12_381_fr -> "N_IMul_bls12_381_fr" + | N_INeg_bls12_381_g1 -> "N_INeg_bls12_381_g1" + | N_INeg_bls12_381_g2 -> "N_INeg_bls12_381_g2" + | N_INeg_bls12_381_fr -> "N_INeg_bls12_381_fr" + | N_IPairing_check_bls12_381 -> "N_IPairing_check_bls12_381" + | N_IMul_bls12_381_fr_z -> "N_IMul_bls12_381_fr_z" + | N_IMul_bls12_381_z_fr -> "N_IMul_bls12_381_z_fr" + | N_IInt_bls12_381_z_fr -> "N_IInt_bls12_381_z_fr" + | N_IComb -> "N_IComb" + | N_IUncomb -> "N_IUncomb" + | N_IComb_get -> "N_IComb_get" + | N_IComb_set -> "N_IComb_set" + | N_ITicket -> "N_ITicket" + | N_IRead_ticket -> "N_IRead_ticket" + | N_ISplit_ticket -> "N_ISplit_ticket" + | N_IJoin_tickets -> "N_IJoin_tickets" + | N_ISapling_empty_state -> "N_ISapling_empty_state" + | N_ISapling_verify_update -> "N_ISapling_verify_update" + | N_IMap_get_and_update -> "N_IMap_get_and_update" + | N_IBig_map_get_and_update -> "N_IBig_map_get_and_update" + | N_IHalt -> "N_IHalt" + | N_ILog -> "N_ILog" + | N_IOpen_chest -> "N_IOpen_chest" + | N_IEmit -> "N_IEmit" + +let string_of_continuation_name : continuation_name -> string = + fun c -> + match c with + | N_KNil -> "N_KNil" + | N_KCons -> "N_KCons" + | N_KReturn -> "N_KReturn" + | N_KView_exit -> "N_KView_exit" + | N_KMap_head -> "N_KMap_head" + | N_KUndip -> "N_KUndip" + | N_KLoop_in -> "N_KLoop_in" + | N_KLoop_in_left -> "N_KLoop_in_left" + | N_KIter_empty -> "N_KIter_empty" + | N_KIter_nonempty -> "N_KIter_nonempty" + | N_KList_enter_body -> "N_KList_enter_body" + | N_KList_exit_body -> "N_KList_exit_body" + | N_KMap_enter_body -> "N_KMap_enter_body" + | N_KMap_exit_body -> "N_KMap_exit_body" + | N_KLog -> "N_KLog" + +let string_of_instr_or_cont name = + match name with + | Instr_name instr_name -> string_of_instruction_name instr_name + | Cont_name cont_name -> string_of_continuation_name cont_name + +(* ------------------------------------------------------------------------- *) + +type args = arg list + +and arg = {name : id; arg : Size.t} + +let nullary : args = [] + +let unary xn x : args = [{name = xn; arg = x}] + +let binary xn x yn y : args = {name = xn; arg = x} :: unary yn y + +let ternary xn x yn y zn z : args = {name = xn; arg = x} :: binary yn y zn z + +let quaternary wn w xn x yn y zn z : args = + {name = wn; arg = w} :: ternary xn x yn y zn z + +let pp_arg fmtr {name; arg} = Format.fprintf fmtr "%s = %a" name Size.pp arg + +let pp_args fmtr args = + Format.pp_print_list + ~pp_sep:(fun fmtr () -> Format.fprintf fmtr ";") + pp_arg + fmtr + args + +type ir_sized_step = {name : instr_or_cont_name; args : args} + +type t = ir_sized_step list + +let ir_sized_step instr_name args = {name = Instr_name instr_name; args} + +let cont_sized_step cont_name args = {name = Cont_name cont_name; args} + +(* ------------------------------------------------------------------------- *) + +(* Changing the ordering breaks the workload file compatibility *) +let all_instructions = + [ + N_IDrop; + N_IDup; + N_ISwap; + N_IPush; + N_ICons_pair; + N_ICar; + N_ICdr; + N_ICons_some; + N_ICons_none; + N_IIf_none; + N_IOpt_map_none; + N_IOpt_map_some; + N_ILeft; + N_IRight; + N_IIf_left; + N_ICons_list; + N_INil; + N_IIf_cons; + N_IList_map; + N_IList_iter; + N_IIter; + N_IList_size; + N_IEmpty_set; + N_ISet_iter; + N_ISet_mem; + N_ISet_update; + N_ISet_size; + N_IEmpty_map; + N_IMap_map; + N_IMap_iter; + N_IMap_mem; + N_IMap_get; + N_IMap_update; + N_IMap_size; + N_IEmpty_big_map; + N_IBig_map_mem; + N_IBig_map_get; + N_IBig_map_update; + N_IConcat_string; + N_IConcat_string_pair; + N_ISlice_string; + N_IString_size; + N_IConcat_bytes; + N_IConcat_bytes_pair; + N_ISlice_bytes; + N_IBytes_size; + N_IBytes_nat; + N_INat_bytes; + N_IBytes_int; + N_IInt_bytes; + N_IAdd_seconds_to_timestamp; + N_IAdd_timestamp_to_seconds; + N_ISub_timestamp_seconds; + N_IDiff_timestamps; + N_IAdd_tez; + N_ISub_tez; + N_ISub_tez_legacy; + N_IMul_teznat; + N_IMul_nattez; + N_IEdiv_teznat; + N_IEdiv_tez; + N_IOr; + N_IAnd; + N_IXor; + N_INot; + N_IIs_nat; + N_INeg; + N_IAbs_int; + N_IInt_nat; + N_IAdd_int; + N_IAdd_nat; + N_ISub_int; + N_IMul_int; + N_IMul_nat; + N_IEdiv_int; + N_IEdiv_nat; + N_ILsl_nat; + N_ILsr_nat; + N_IOr_nat; + N_IAnd_nat; + N_IAnd_int_nat; + N_IXor_nat; + N_INot_int; + N_IIf; + N_ILoop_in; + N_ILoop_out; + N_ILoop_left_in; + N_ILoop_left_out; + N_IDip; + N_IExec; + N_IApply; + N_ILambda_lam; + N_ILambda_lamrec; + N_IFailwith; + N_ICompare; + N_IEq; + N_INeq; + N_ILt; + N_IGt; + N_ILe; + N_IGe; + N_IAddress; + N_IContract; + N_ITransfer_tokens; + N_IImplicit_account; + N_ICreate_contract; + N_ISet_delegate; + N_INow; + N_IMin_block_time; + N_IBalance; + N_ICheck_signature_ed25519; + N_ICheck_signature_secp256k1; + N_ICheck_signature_p256; + N_ICheck_signature_bls; + N_IHash_key; + N_IPack; + N_IUnpack; + N_IBlake2b; + N_ISha256; + N_ISha512; + N_ISource; + N_ISender; + N_ISelf; + N_IAmount; + N_IDig; + N_IDug; + N_IDipN; + N_IDropN; + N_IDupN; + N_IChainId; + N_ILevel; + N_IView; + N_ISelf_address; + N_INever; + N_IUnpair; + N_IVoting_power; + N_ITotal_voting_power; + N_IKeccak; + N_ISha3; + N_IAdd_bls12_381_g1; + N_IAdd_bls12_381_g2; + N_IAdd_bls12_381_fr; + N_IMul_bls12_381_g1; + N_IMul_bls12_381_g2; + N_IMul_bls12_381_fr; + N_INeg_bls12_381_g1; + N_INeg_bls12_381_g2; + N_INeg_bls12_381_fr; + N_IPairing_check_bls12_381; + N_IMul_bls12_381_fr_z; + N_IMul_bls12_381_z_fr; + N_IInt_bls12_381_z_fr; + N_IComb; + N_IUncomb; + N_IComb_get; + N_IComb_set; + N_ITicket; + N_IRead_ticket; + N_ISplit_ticket; + N_IJoin_tickets; + N_ISapling_empty_state; + N_ISapling_verify_update; + N_IMap_get_and_update; + N_IBig_map_get_and_update; + N_IHalt; + N_ILog; + N_IOpen_chest; + N_IEmit; + N_ILsl_bytes; + N_ILsr_bytes; + N_IOr_bytes; + N_IAnd_bytes; + N_IXor_bytes; + N_INot_bytes; + N_IUnit; + ] + +(* Changing the ordering breaks the workload file compatibility *) +let all_continuations = + [ + N_KNil; + N_KCons; + N_KReturn; + N_KView_exit; + N_KMap_head; + N_KUndip; + N_KLoop_in; + N_KLoop_in_left; + N_KIter_empty; + N_KIter_nonempty; + N_KList_enter_body; + N_KList_exit_body; + N_KMap_enter_body; + N_KMap_exit_body; + N_KLog; + ] + +let instruction_name_encoding = + let open Data_encoding in + def "instruction_name_encoding" + @@ string_enum + (List.map + (fun instr_name -> + (string_of_instruction_name instr_name, instr_name)) + all_instructions) + +let continuation_name_encoding = + let open Data_encoding in + def "continuation_name_encoding" + @@ string_enum + (List.map + (fun cont_name -> (string_of_continuation_name cont_name, cont_name)) + all_continuations) + +let args_encoding = + let open Data_encoding in + def "args_encoding" + @@ list + (conv + (fun {name; arg} -> (name, arg)) + (fun (name, arg) -> {name; arg}) + (tup2 string Size.encoding)) + +let instr_or_cont_name_encoding = + let open Data_encoding in + def "instr_or_cont_name" + @@ union + [ + case + ~title:"instr_name" + (Tag 0) + instruction_name_encoding + (function Instr_name name -> Some name | _ -> None) + (fun name -> Instr_name name); + case + ~title:"cont_name" + (Tag 1) + continuation_name_encoding + (function Cont_name name -> Some name | _ -> None) + (fun name -> Cont_name name); + ] + +let ir_sized_step_encoding = + let open Data_encoding in + def "ir_sized_step_encoding" + @@ conv + (fun {name; args} -> (name, args)) + (fun (name, args) -> {name; args}) + (tup2 instr_or_cont_name_encoding args_encoding) + +let encoding = + let open Data_encoding in + def "interpreter_trace_encoding" @@ list ir_sized_step_encoding + +(* ------------------------------------------------------------------------- *) + +module Instructions = struct + let drop = ir_sized_step N_IDrop nullary + + let dup = ir_sized_step N_IDup nullary + + let swap = ir_sized_step N_ISwap nullary + + let push = ir_sized_step N_IPush nullary + + let unit = ir_sized_step N_IUnit nullary + + let cons_pair = ir_sized_step N_ICons_pair nullary + + let car = ir_sized_step N_ICar nullary + + let cdr = ir_sized_step N_ICdr nullary + + let cons_some = ir_sized_step N_ICons_some nullary + + let cons_none = ir_sized_step N_ICons_none nullary + + let if_none = ir_sized_step N_IIf_none nullary + + let opt_map ~is_some = + if is_some then ir_sized_step N_IOpt_map_some nullary + else ir_sized_step N_IOpt_map_none nullary + + let left = ir_sized_step N_ILeft nullary + + let right = ir_sized_step N_IRight nullary + + let if_left = ir_sized_step N_IIf_left nullary + + let cons_list = ir_sized_step N_ICons_list nullary + + let nil = ir_sized_step N_INil nullary + + let if_cons = ir_sized_step N_IIf_cons nullary + + let list_map = ir_sized_step N_IList_map nullary + + let list_iter = ir_sized_step N_IList_iter nullary + + let iter = ir_sized_step N_IIter nullary + + let list_size _list = ir_sized_step N_IList_size nullary + + let empty_set = ir_sized_step N_IEmpty_set nullary + + let set_iter set = ir_sized_step N_ISet_iter (unary "set" set) + + let set_mem elt set = ir_sized_step N_ISet_mem (binary "elt" elt "set" set) + + let set_update elt set = + ir_sized_step N_ISet_update (binary "elt" elt "set" set) + + let set_size _set = ir_sized_step N_ISet_size nullary + + let empty_map = ir_sized_step N_IEmpty_map nullary + + let map_map map = ir_sized_step N_IMap_map (unary "map" map) + + let map_iter map = ir_sized_step N_IMap_iter (unary "map" map) + + let map_mem key map = ir_sized_step N_IMap_mem (binary "key" key "map" map) + + let map_get key map = ir_sized_step N_IMap_get (binary "key" key "map" map) + + let map_update key map = + ir_sized_step N_IMap_update (binary "key" key "map" map) + + let map_size _map = ir_sized_step N_IMap_size nullary + + let empty_big_map = ir_sized_step N_IEmpty_big_map nullary + + let big_map_mem key big_map = + ir_sized_step N_IBig_map_mem (binary "key" key "big_map" big_map) + + let big_map_get key big_map = + ir_sized_step N_IBig_map_get (binary "key" key "big_map" big_map) + + let big_map_update key big_map = + ir_sized_step N_IBig_map_update (binary "key" key "big_map" big_map) + + let big_map_get_and_update key big_map = + ir_sized_step N_IBig_map_get_and_update (binary "key" key "big_map" big_map) + + let concat_string total_bytes list = + ir_sized_step + N_IConcat_string + (binary "total_bytes" total_bytes "list" list) + + let concat_string_pair str1 str2 = + ir_sized_step N_IConcat_string_pair (binary "str1" str1 "str2" str2) + + let slice_string string = + ir_sized_step N_ISlice_string (unary "string" string) + + let string_size _string = ir_sized_step N_IString_size nullary + + let concat_bytes total_bytes list = + ir_sized_step N_IConcat_bytes (binary "total_bytes" total_bytes "list" list) + + let concat_bytes_pair str1 str2 = + ir_sized_step N_IConcat_bytes_pair (binary "str1" str1 "str2" str2) + + let slice_bytes bytes = ir_sized_step N_ISlice_bytes (unary "bytes" bytes) + + let bytes_size = ir_sized_step N_IBytes_size nullary + + let lsl_bytes bytes shift = + ir_sized_step N_ILsl_bytes (binary "bytes" bytes "shift" shift) + + let lsr_bytes bytes shift = + ir_sized_step N_ILsr_bytes (binary "bytes" bytes "shift" shift) + + let or_bytes bytes1 bytes2 = + ir_sized_step N_IOr_bytes (binary "bytes1" bytes1 "bytes2" bytes2) + + let and_bytes bytes1 bytes2 = + ir_sized_step N_IAnd_bytes (binary "bytes1" bytes1 "bytes2" bytes2) + + let xor_bytes bytes1 bytes2 = + ir_sized_step N_IXor_bytes (binary "bytes1" bytes1 "bytes2" bytes2) + + let not_bytes bytes = ir_sized_step N_INot_bytes (unary "bytes" bytes) + + let bytes_nat nat = ir_sized_step N_IBytes_nat (unary "nat" nat) + + let nat_bytes bytes = ir_sized_step N_INat_bytes (unary "bytes" bytes) + + let bytes_int int = ir_sized_step N_IBytes_int (unary "int" int) + + let int_bytes bytes = ir_sized_step N_IInt_bytes (unary "bytes" bytes) + + let add_seconds_to_timestamp seconds tstamp = + ir_sized_step + N_IAdd_seconds_to_timestamp + (binary "seconds" seconds "tstamp" tstamp) + + let add_timestamp_to_seconds tstamp seconds = + ir_sized_step + N_IAdd_timestamp_to_seconds + (binary "tstamp" tstamp "seconds" seconds) + + let sub_timestamp_seconds tstamp seconds = + ir_sized_step + N_ISub_timestamp_seconds + (binary "tstamp" tstamp "seconds" seconds) + + let diff_timestamps tstamp1 tstamp2 = + ir_sized_step + N_IDiff_timestamps + (binary "tstamp1" tstamp1 "tstamp2" tstamp2) + + let add_tez _tez1 _tez2 = ir_sized_step N_IAdd_tez nullary + + let sub_tez _tez1 _tez2 = ir_sized_step N_ISub_tez nullary + + let sub_tez_legacy _tez1 _tez2 = ir_sized_step N_ISub_tez_legacy nullary + + let mul_teznat _tez _nat = ir_sized_step N_IMul_teznat nullary + + let mul_nattez _nat _tez = ir_sized_step N_IMul_nattez nullary + + let ediv_teznat _tez _nat = ir_sized_step N_IEdiv_teznat nullary + + let ediv_tez _tez1 _tez2 = ir_sized_step N_IEdiv_tez nullary + + let or_ = ir_sized_step N_IOr nullary + + let and_ = ir_sized_step N_IAnd nullary + + let xor_ = ir_sized_step N_IXor nullary + + let not_ = ir_sized_step N_INot nullary + + let is_nat _int = ir_sized_step N_IIs_nat nullary + + let neg int = ir_sized_step N_INeg (unary "int" int) + + let abs_int int = ir_sized_step N_IAbs_int (unary "int" int) + + let int_nat _nat = ir_sized_step N_IInt_nat nullary + + let add_int int1 int2 = + ir_sized_step N_IAdd_int (binary "int1" int1 "int2" int2) + + let add_nat nat1 nat2 = + ir_sized_step N_IAdd_nat (binary "nat1" nat1 "nat2" nat2) + + let sub_int int1 int2 = + ir_sized_step N_ISub_int (binary "int1" int1 "int2" int2) + + let mul_int int1 int2 = + ir_sized_step N_IMul_int (binary "int1" int1 "int2" int2) + + let mul_nat nat int = ir_sized_step N_IMul_nat (binary "nat" nat "int" int) + + let ediv_int int1 int2 = + ir_sized_step N_IEdiv_int (binary "int1" int1 "int2" int2) + + let ediv_nat nat int = ir_sized_step N_IEdiv_nat (binary "nat" nat "int" int) + + let lsl_nat nat1 _shift = ir_sized_step N_ILsl_nat (unary "nat" nat1) + + let lsr_nat nat1 _shift = ir_sized_step N_ILsr_nat (unary "nat" nat1) + + let or_nat nat1 nat2 = + ir_sized_step N_IOr_nat (binary "nat1" nat1 "nat2" nat2) + + let and_nat nat1 nat2 = + ir_sized_step N_IAnd_nat (binary "nat1" nat1 "nat2" nat2) + + let and_int_nat int nat = + ir_sized_step N_IAnd_int_nat (binary "int" int "nat" nat) + + let xor_nat nat1 nat2 = + ir_sized_step N_IXor_nat (binary "nat1" nat1 "nat2" nat2) + + let not_int int = ir_sized_step N_INot_int (unary "int" int) + + let if_ = ir_sized_step N_IIf nullary + + let loop bool = + if bool then ir_sized_step N_ILoop_in nullary + else ir_sized_step N_ILoop_out nullary + + let loop_left or_ = + if or_ then ir_sized_step N_ILoop_left_in nullary + else ir_sized_step N_ILoop_left_out nullary + + let dip = ir_sized_step N_IDip nullary + + let exec = ir_sized_step N_IExec nullary + + let apply ~(rec_flag : bool) = + ir_sized_step N_IApply (unary "rec" (if rec_flag then 1 else 0)) + + let lambda ~(rec_flag : bool) = + if rec_flag then ir_sized_step N_ILambda_lamrec nullary + else ir_sized_step N_ILambda_lam nullary + + let failwith_ = ir_sized_step N_IFailwith nullary + + let compare arg1 arg2 = + ir_sized_step N_ICompare (binary "arg1" arg1 "arg2" arg2) + + let eq = ir_sized_step N_IEq nullary + + let neq = ir_sized_step N_INeq nullary + + let lt = ir_sized_step N_ILt nullary + + let gt = ir_sized_step N_IGt nullary + + let le = ir_sized_step N_ILe nullary + + let ge = ir_sized_step N_IGe nullary + + let address = ir_sized_step N_IAddress nullary + + let contract = ir_sized_step N_IContract nullary + + let transfer_tokens = ir_sized_step N_ITransfer_tokens nullary + + let implicit_account = ir_sized_step N_IImplicit_account nullary + + let create_contract = ir_sized_step N_ICreate_contract nullary + + let set_delegate = ir_sized_step N_ISet_delegate nullary + + let now = ir_sized_step N_INow nullary + + let min_block_time = ir_sized_step N_IMin_block_time nullary + + let balance = ir_sized_step N_IBalance nullary + + let check_signature_ed25519 _pk _signature message = + ir_sized_step N_ICheck_signature_ed25519 (unary "message" message) + + let check_signature_secp256k1 _pk _signature message = + ir_sized_step N_ICheck_signature_secp256k1 (unary "message" message) + + let check_signature_p256 _pk _signature message = + ir_sized_step N_ICheck_signature_p256 (unary "message" message) + + let check_signature_bls _pk _signature message = + ir_sized_step N_ICheck_signature_bls (unary "message" message) + + let hash_key = ir_sized_step N_IHash_key nullary + + let pack (micheline_size : Size.micheline_size) = + ir_sized_step + N_IPack + (ternary + "micheline_nodes" + micheline_size.traversal + "micheline_int_bytes" + micheline_size.int_bytes + "micheline_string_bytes" + micheline_size.string_bytes) + + let unpack = ir_sized_step N_IUnpack nullary + + let blake2b bytes = ir_sized_step N_IBlake2b (unary "bytes" bytes) + + let sha256 bytes = ir_sized_step N_ISha256 (unary "bytes" bytes) + + let sha512 bytes = ir_sized_step N_ISha512 (unary "bytes" bytes) + + let source = ir_sized_step N_ISource nullary + + let sender = ir_sized_step N_ISender nullary + + let self = ir_sized_step N_ISelf nullary + + let amount = ir_sized_step N_IAmount nullary + + let dig depth = ir_sized_step N_IDig (unary "depth" depth) + + let dug depth = ir_sized_step N_IDug (unary "depth" depth) + + let dipn depth = ir_sized_step N_IDipN (unary "depth" depth) + + let dropn depth = ir_sized_step N_IDropN (unary "depth" depth) + + let dupn depth = ir_sized_step N_IDupN (unary "depth" depth) + + let chain_id = ir_sized_step N_IChainId nullary + + let level = ir_sized_step N_ILevel nullary + + let view = ir_sized_step N_IView nullary + + let self_address = ir_sized_step N_ISelf_address nullary + + let never = ir_sized_step N_INever nullary + + let unpair = ir_sized_step N_IUnpair nullary + + let voting_power = ir_sized_step N_IVoting_power nullary + + let total_voting_power = ir_sized_step N_ITotal_voting_power nullary + + let keccak bytes = ir_sized_step N_IKeccak (unary "bytes" bytes) + + let sha3 bytes = ir_sized_step N_ISha3 (unary "bytes" bytes) + + let add_bls12_381_g1 = ir_sized_step N_IAdd_bls12_381_g1 nullary + + let add_bls12_381_g2 = ir_sized_step N_IAdd_bls12_381_g2 nullary + + let add_bls12_381_fr = ir_sized_step N_IAdd_bls12_381_fr nullary + + let mul_bls12_381_g1 = ir_sized_step N_IMul_bls12_381_g1 nullary + + let mul_bls12_381_g2 = ir_sized_step N_IMul_bls12_381_g2 nullary + + let mul_bls12_381_fr = ir_sized_step N_IMul_bls12_381_fr nullary + + let neg_bls12_381_g1 = ir_sized_step N_INeg_bls12_381_g1 nullary + + let neg_bls12_381_g2 = ir_sized_step N_INeg_bls12_381_g2 nullary + + let neg_bls12_381_fr = ir_sized_step N_INeg_bls12_381_fr nullary + + let pairing_check_bls12_381 length = + ir_sized_step N_IPairing_check_bls12_381 (unary "length" length) + + let mul_bls12_381_fr_z nat = + ir_sized_step N_IMul_bls12_381_fr_z (unary "nat" nat) + + let mul_bls12_381_z_fr nat = + ir_sized_step N_IMul_bls12_381_z_fr (unary "nat" nat) + + let int_bls12_381_z_fr = ir_sized_step N_IInt_bls12_381_z_fr nullary + + let comb depth = ir_sized_step N_IComb (unary "depth" depth) + + let uncomb depth = ir_sized_step N_IUncomb (unary "depth" depth) + + let comb_get key = ir_sized_step N_IComb_get (unary "key" key) + + let comb_set key = ir_sized_step N_IComb_set (unary "key" key) + + let ticket = ir_sized_step N_ITicket nullary + + let read_ticket = ir_sized_step N_IRead_ticket nullary + + let split_ticket nat1 nat2 = + ir_sized_step N_ISplit_ticket (binary "nat1" nat1 "nat2" nat2) + + let join_tickets size1 size2 size3 size4 = + ir_sized_step + N_IJoin_tickets + (quaternary + "contents1" + size1 + "contents2" + size2 + "amount1" + size3 + "amount2" + size4) + + let sapling_empty_state = ir_sized_step N_ISapling_empty_state nullary + + let sapling_verify_update inputs outputs _bound_data _state = + ir_sized_step + N_ISapling_verify_update + (binary "inputs" inputs "outputs" outputs) + + let map_get_and_update key_size map_size = + ir_sized_step + N_IMap_get_and_update + (binary "key_size" key_size "map_size" map_size) + + let halt = ir_sized_step N_IHalt nullary + + let log = ir_sized_step N_ILog nullary + + let open_chest log_time size = + ir_sized_step N_IOpen_chest (binary "log_time" log_time "size" size) + + (** cost model for the EMIT instruction *) + let emit = ir_sized_step N_IEmit nullary +end + +module Control = struct + let nil = cont_sized_step N_KNil nullary + + let cons = cont_sized_step N_KCons nullary + + let return = cont_sized_step N_KReturn nullary + + let view_exit = cont_sized_step N_KView_exit nullary + + let map_head = cont_sized_step N_KMap_head nullary + + let undip = cont_sized_step N_KUndip nullary + + let loop_in = cont_sized_step N_KLoop_in nullary + + let loop_in_left = cont_sized_step N_KLoop_in_left nullary + + let iter size = + if size = 0 then cont_sized_step N_KIter_empty nullary + else cont_sized_step N_KIter_nonempty nullary + + let list_enter_body xs_size ys_size = + cont_sized_step + N_KList_enter_body + (binary "xs_size" xs_size "ys_size" ys_size) + + let list_exit_body = cont_sized_step N_KList_exit_body nullary + + let map_enter_body size = + cont_sized_step N_KMap_enter_body (unary "size" size) + + let map_exit_body key_size map_size = + cont_sized_step N_KMap_exit_body (binary "key" key_size "map" map_size) + + let log = cont_sized_step N_KLog nullary +end + +(* ------------------------------------------------------------------------- *) + +open Script_typed_ir + +let extract_compare_sized_step : + type a. a comparable_ty -> a -> a -> ir_sized_step = + fun comparable_ty x y -> + Instructions.compare + (Size.size_of_comparable_value comparable_ty x) + (Size.size_of_comparable_value comparable_ty y) + +let extract_ir_sized_step : + type bef_top bef res_top res. + Alpha_context.t -> + (bef_top, bef, res_top, res) Script_typed_ir.kinstr -> + bef_top * bef -> + ir_sized_step = + fun ctxt instr stack -> + let open Script_typed_ir in + match (instr, stack) with + | IDrop (_, _), _ -> Instructions.drop + | IDup (_, _), _ -> Instructions.dup + | ISwap (_, _), _ -> Instructions.swap + | IPush (_, _, _, _), _ -> Instructions.push + | IUnit (_, _), _ -> Instructions.unit + | ICons_pair (_, _), _ -> Instructions.cons_pair + | ICar (_, _), _ -> Instructions.car + | ICdr (_, _), _ -> Instructions.cdr + | IUnpair (_, _), _ -> Instructions.unpair + | ICons_some (_, _), _ -> Instructions.cons_some + | ICons_none (_, _, _), _ -> Instructions.cons_none + | IIf_none _, _ -> Instructions.if_none + | IOpt_map _, (opt, _) -> + let is_some = match opt with None -> false | Some _ -> true in + Instructions.opt_map ~is_some + | ICons_left (_, _, _), _ -> Instructions.left + | ICons_right (_, _, _), _ -> Instructions.right + | IIf_left _, _ -> Instructions.if_left + | ICons_list (_, _), _ -> Instructions.cons_list + | INil (_, _, _), _ -> Instructions.nil + | IIf_cons _, _ -> Instructions.if_cons + | IList_iter (_, _, _, _), _ -> Instructions.list_iter + | IList_map (_, _, _, _), _ -> Instructions.list_map + | IList_size (_, _), (list, _) -> Instructions.list_size (Size.list list) + | IEmpty_set (_, _, _), _ -> Instructions.empty_set + | ISet_iter _, (set, _) -> Instructions.set_iter (Size.set set) + | ISet_mem (_, _), (v, (set, _)) -> + let (module S) = Script_set.get set in + let sz = S.OPS.elt_size v in + Instructions.set_mem sz (Size.set set) + | ISet_update (_, _), (v, (_flag, (set, _))) -> + let (module S) = Script_set.get set in + let sz = S.OPS.elt_size v in + Instructions.set_update sz (Size.set set) + | ISet_size (_, _), (set, _) -> Instructions.set_size (Size.set set) + | IEmpty_map (_, _, _, _), _ -> Instructions.empty_map + | IMap_map _, (map, _) -> Instructions.map_map (Size.map map) + | IMap_iter _, (map, _) -> Instructions.map_iter (Size.map map) + | IMap_mem (_, _), (v, (map, _)) -> + let (module Map) = Script_map.get_module map in + let key_size = Map.OPS.key_size v in + Instructions.map_mem key_size (Size.map map) + | IMap_get (_, _), (v, (map, _)) -> + let (module Map) = Script_map.get_module map in + let key_size = Map.OPS.key_size v in + Instructions.map_get key_size (Size.map map) + | IMap_update (_, _), (v, (_elt_opt, (map, _))) -> + let (module Map) = Script_map.get_module map in + let key_size = Map.OPS.key_size v in + Instructions.map_update key_size (Size.map map) + | IMap_get_and_update (_, _), (v, (_elt_opt, (map, _))) -> + let (module Map) = Script_map.get_module map in + let key_size = Map.OPS.key_size v in + Instructions.map_get_and_update key_size (Size.map map) + | IMap_size (_, _), (map, _) -> Instructions.map_size (Size.map map) + | IEmpty_big_map (_, _, _, _), _ -> Instructions.empty_big_map + | IBig_map_mem (_, _), (v, (Big_map {diff = {size; _}; key_type; _}, _)) -> + let key_size = Size.size_of_comparable_value key_type v in + Instructions.big_map_mem key_size (Size.of_int size) + | IBig_map_get (_, _), (v, (Big_map {diff = {size; _}; key_type; _}, _)) -> + let key_size = Size.size_of_comparable_value key_type v in + Instructions.big_map_get key_size (Size.of_int size) + | ( IBig_map_update (_, _), + (v, (_, (Big_map {diff = {size; _}; key_type; _}, _))) ) -> + let key_size = Size.size_of_comparable_value key_type v in + Instructions.big_map_update key_size (Size.of_int size) + | ( IBig_map_get_and_update (_, _), + (v, (_, (Big_map {diff = {size; _}; key_type; _}, _))) ) -> + let key_size = Size.size_of_comparable_value key_type v in + Instructions.big_map_get_and_update key_size (Size.of_int size) + | IConcat_string (_, _), (ss, _) -> + let list_size = Size.list ss in + let total_bytes = + List.fold_left + (fun x s -> Size.(add x (script_string s))) + Size.zero + ss.elements + in + Instructions.concat_string list_size total_bytes + | IConcat_string_pair (_, _), (s1, (s2, _)) -> + Instructions.concat_string_pair + (Size.script_string s1) + (Size.script_string s2) + | ISlice_string (_, _), (_off, (_len, (s, _))) -> + Instructions.slice_string (Size.script_string s) + | IString_size (_, _), (s, _) -> + Instructions.string_size (Size.script_string s) + | IConcat_bytes (_, _), (ss, _) -> + let list_size = Size.list ss in + let total_bytes = + List.fold_left (fun x s -> Size.(add x (bytes s))) Size.zero ss.elements + in + Instructions.concat_bytes list_size total_bytes + | IConcat_bytes_pair (_, _), (s1, (s2, _)) -> + Instructions.concat_bytes_pair (Size.bytes s1) (Size.bytes s2) + | ISlice_bytes (_, _), (_off, (_len, (s, _))) -> + Instructions.slice_bytes (Size.bytes s) + | IBytes_size (_, _), _ -> Instructions.bytes_size + | IBytes_nat (_, _), (n, _) -> Instructions.bytes_nat (Size.integer n) + | INat_bytes (_, _), (b, _) -> Instructions.nat_bytes (Size.bytes b) + | IBytes_int (_, _), (n, _) -> Instructions.bytes_int (Size.integer n) + | IInt_bytes (_, _), (b, _) -> Instructions.int_bytes (Size.bytes b) + | IAdd_seconds_to_timestamp (_, _), (s, (t, _)) -> + Instructions.add_seconds_to_timestamp (Size.timestamp t) (Size.integer s) + | IAdd_timestamp_to_seconds (_, _), (t, (s, _)) -> + Instructions.add_timestamp_to_seconds (Size.timestamp t) (Size.integer s) + | ISub_timestamp_seconds (_, _), (t, (s, _)) -> + Instructions.sub_timestamp_seconds (Size.timestamp t) (Size.integer s) + | IDiff_timestamps (_, _), (t1, (t2, _)) -> + Instructions.diff_timestamps (Size.timestamp t1) (Size.timestamp t2) + | IAdd_tez (_, _), (x, (y, _)) -> + Instructions.add_tez (Size.mutez x) (Size.mutez y) + | ISub_tez (_, _), (x, (y, _)) -> + Instructions.sub_tez (Size.mutez x) (Size.mutez y) + | ISub_tez_legacy (_, _), (x, (y, _)) -> + Instructions.sub_tez_legacy (Size.mutez x) (Size.mutez y) + | IMul_teznat (_, _), (x, (y, _)) -> + Instructions.mul_teznat (Size.mutez x) (Size.integer y) + | IMul_nattez (_, _), (x, (y, _)) -> + Instructions.mul_nattez (Size.integer x) (Size.mutez y) + | IEdiv_teznat (_, _), (x, (y, _)) -> + Instructions.ediv_teznat (Size.mutez x) (Size.integer y) + | IEdiv_tez (_, _), (x, (y, _)) -> + Instructions.ediv_tez (Size.mutez x) (Size.mutez y) + | IOr (_, _), _ -> Instructions.or_ + | IAnd (_, _), _ -> Instructions.and_ + | IXor (_, _), _ -> Instructions.xor_ + | INot (_, _), _ -> Instructions.not_ + | IIs_nat (_, _), (x, _) -> Instructions.is_nat (Size.integer x) + | INeg (_, _), (x, _) -> Instructions.neg (Size.integer x) + | IAbs_int (_, _), (x, _) -> Instructions.abs_int (Size.integer x) + | IInt_nat (_, _), (x, _) -> Instructions.int_nat (Size.integer x) + | IAdd_int (_, _), (x, (y, _)) -> + Instructions.add_int (Size.integer x) (Size.integer y) + | IAdd_nat (_, _), (x, (y, _)) -> + Instructions.add_nat (Size.integer x) (Size.integer y) + | ISub_int (_, _), (x, (y, _)) -> + Instructions.sub_int (Size.integer x) (Size.integer y) + | IMul_int (_, _), (x, (y, _)) -> + Instructions.mul_int (Size.integer x) (Size.integer y) + | IMul_nat (_, _), (x, (y, _)) -> + Instructions.mul_nat (Size.integer x) (Size.integer y) + | IEdiv_int (_, _), (x, (y, _)) -> + Instructions.ediv_int (Size.integer x) (Size.integer y) + | IEdiv_nat (_, _), (x, (y, _)) -> + Instructions.ediv_nat (Size.integer x) (Size.integer y) + | ILsl_nat (_, _), (x, (y, _)) -> + Instructions.lsl_nat (Size.integer x) (Size.integer y) + | ILsr_nat (_, _), (x, (y, _)) -> + Instructions.lsr_nat (Size.integer x) (Size.integer y) + | IOr_nat (_, _), (x, (y, _)) -> + Instructions.or_nat (Size.integer x) (Size.integer y) + | IAnd_nat (_, _), (x, (y, _)) -> + Instructions.and_nat (Size.integer x) (Size.integer y) + | IAnd_int_nat (_, _), (x, (y, _)) -> + Instructions.and_int_nat (Size.integer x) (Size.integer y) + | IXor_nat (_, _), (x, (y, _)) -> + Instructions.xor_nat (Size.integer x) (Size.integer y) + | INot_int (_, _), (x, _) -> Instructions.not_int (Size.integer x) + | IIf _, _ -> Instructions.if_ + | ILoop (_, _, _), (b, _) -> Instructions.loop b + | ILoop_left (_, _, _), (or_, _) -> + let or_ = match or_ with L _ -> true | R _ -> false in + Instructions.loop_left or_ + | IDip (_, _, _, _), _ -> Instructions.dip + | IExec (_, _, _), _ -> Instructions.exec + | IApply (_, _, _), (_, (l, _)) -> + let rec_flag = match l with Lam _ -> false | LamRec _ -> true in + Instructions.apply ~rec_flag + | ILambda (_, l, _), _ -> + let rec_flag = match l with Lam _ -> false | LamRec _ -> true in + Instructions.lambda ~rec_flag + | IFailwith (_, _), _ -> Instructions.failwith_ + | ICompare (_, cmp_ty, _), (a, (b, _)) -> + extract_compare_sized_step cmp_ty a b + | IEq (_, _), _ -> Instructions.eq + | INeq (_, _), _ -> Instructions.neq + | ILt (_, _), _ -> Instructions.lt + | IGt (_, _), _ -> Instructions.gt + | ILe (_, _), _ -> Instructions.le + | IGe (_, _), _ -> Instructions.ge + | IAddress (_, _), _ -> Instructions.address + | IContract (_, _, _, _), _ -> Instructions.contract + | ITransfer_tokens (_, _), _ -> Instructions.transfer_tokens + | IView (_, _, _, _), _ -> Instructions.view + | IImplicit_account (_, _), _ -> Instructions.implicit_account + | ICreate_contract _, _ -> Instructions.create_contract + | ISet_delegate (_, _), _ -> Instructions.set_delegate + | INow (_, _), _ -> Instructions.now + | IBalance (_, _), _ -> Instructions.balance + | ILevel (_, _), _ -> Instructions.level + | ICheck_signature (_, _), (public_key, (_signature, (message, _))) -> ( + match public_key with + | Signature.Ed25519 pk -> + let pk = Size.of_int (Signature.Ed25519.Public_key.size pk) in + let signature = Size.of_int Signature.Ed25519.size in + let message = Size.bytes message in + Instructions.check_signature_ed25519 pk signature message + | Signature.Secp256k1 pk -> + let pk = Size.of_int (Signature.Secp256k1.Public_key.size pk) in + let signature = Size.of_int Signature.Secp256k1.size in + let message = Size.bytes message in + Instructions.check_signature_secp256k1 pk signature message + | Signature.P256 pk -> + let pk = Size.of_int (Signature.P256.Public_key.size pk) in + let signature = Size.of_int Signature.P256.size in + let message = Size.bytes message in + Instructions.check_signature_p256 pk signature message + | Signature.Bls pk -> + let pk = Size.of_int (Signature.Bls.Public_key.size pk) in + let signature = Size.of_int Signature.Bls.size in + let message = Size.bytes message in + Instructions.check_signature_bls pk signature message) + | IHash_key (_, _), _ -> Instructions.hash_key + | IPack (_, ty, _), (v, _) -> ( + let script_res = + Lwt_main.run (Script_ir_translator.unparse_data ctxt Optimized ty v) + in + match script_res with + | Ok (node, _ctxt) -> + Instructions.pack (Size.of_micheline (Micheline.root node)) + | Error _ -> Stdlib.failwith "IPack workload: could not unparse") + | IUnpack (_, _, _), _ -> Instructions.unpack + | IBlake2b (_, _), (bytes, _) -> Instructions.blake2b (Size.bytes bytes) + | ISha256 (_, _), (bytes, _) -> Instructions.sha256 (Size.bytes bytes) + | ISha512 (_, _), (bytes, _) -> Instructions.sha512 (Size.bytes bytes) + | ISource (_, _), _ -> Instructions.source + | ISender (_, _), _ -> Instructions.sender + | ISelf (_, _, _, _), _ -> Instructions.self + | ISelf_address (_, _), _ -> Instructions.self_address + | IAmount (_, _), _ -> Instructions.amount + | ISapling_empty_state (_, _, _), _ -> Instructions.sapling_empty_state + | ISapling_verify_update (_, _), (transaction, (_state, _)) -> + let inputs = Size.sapling_transaction_inputs transaction in + let outputs = Size.sapling_transaction_outputs transaction in + let bound_data = Size.sapling_transaction_bound_data transaction in + let state = Size.zero in + Instructions.sapling_verify_update inputs outputs bound_data state + | ISapling_verify_update_deprecated (_, _), (transaction, (_state, _)) -> + let inputs = List.length transaction.inputs in + let outputs = List.length transaction.outputs in + let bound_data = Size.zero in + let state = Size.zero in + Instructions.sapling_verify_update inputs outputs bound_data state + | IDig (_, n, _, _), _ -> Instructions.dig (Size.of_int n) + | IDug (_, n, _, _), _ -> Instructions.dug (Size.of_int n) + | IDipn (_, n, _, _, _), _ -> Instructions.dipn (Size.of_int n) + | IDropn (_, n, _, _), _ -> Instructions.dropn (Size.of_int n) + | IChainId (_, _), _ -> Instructions.chain_id + | INever _, _ -> . + | IVoting_power (_, _), _ -> Instructions.voting_power + | ITotal_voting_power (_, _), _ -> Instructions.total_voting_power + | IKeccak (_, _), (bytes, _) -> Instructions.keccak (Size.bytes bytes) + | ISha3 (_, _), (bytes, _) -> Instructions.sha3 (Size.bytes bytes) + | IAdd_bls12_381_g1 (_, _), _ -> Instructions.add_bls12_381_g1 + | IAdd_bls12_381_g2 (_, _), _ -> Instructions.add_bls12_381_g2 + | IAdd_bls12_381_fr (_, _), _ -> Instructions.add_bls12_381_fr + | IMul_bls12_381_g1 (_, _), _ -> Instructions.mul_bls12_381_g1 + | IMul_bls12_381_g2 (_, _), _ -> Instructions.mul_bls12_381_g2 + | IMul_bls12_381_fr (_, _), _ -> Instructions.mul_bls12_381_fr + | IMul_bls12_381_z_fr (_, _), (_fr, (z, _)) -> + Instructions.mul_bls12_381_z_fr (Size.integer z) + | IMul_bls12_381_fr_z (_, _), (z, _) -> + Instructions.mul_bls12_381_fr_z (Size.integer z) + | IInt_bls12_381_fr (_, _), _ -> Instructions.int_bls12_381_z_fr + | INeg_bls12_381_g1 (_, _), _ -> Instructions.neg_bls12_381_g1 + | INeg_bls12_381_g2 (_, _), _ -> Instructions.neg_bls12_381_g2 + | INeg_bls12_381_fr (_, _), _ -> Instructions.neg_bls12_381_fr + | IPairing_check_bls12_381 (_, _), (list, _) -> + Instructions.pairing_check_bls12_381 (Size.list list) + | IComb (_, n, _, _), _ -> Instructions.comb (Size.of_int n) + | IUncomb (_, n, _, _), _ -> Instructions.uncomb (Size.of_int n) + | IComb_get (_, n, _, _), _ -> Instructions.comb_get (Size.of_int n) + | IComb_set (_, n, _, _), _ -> Instructions.comb_set (Size.of_int n) + | IDup_n (_, n, _, _), _ -> Instructions.dupn (Size.of_int n) + | ITicket (_, _, _), _ | ITicket_deprecated (_, _, _), _ -> + Instructions.ticket + | IRead_ticket (_, _, _), _ -> Instructions.read_ticket + | ISplit_ticket (_, _), (_ticket, ((amount_a, amount_b), _)) -> + Instructions.split_ticket (Size.integer amount_a) (Size.integer amount_b) + | IJoin_tickets (_, cmp_ty, _), ((ticket1, ticket2), _) -> + let size1 = Size.size_of_comparable_value cmp_ty ticket1.contents in + let size2 = Size.size_of_comparable_value cmp_ty ticket2.contents in + let tez1 = Size.integer (ticket1.amount :> Script_int.n Script_int.num) in + let tez2 = Size.integer (ticket2.amount :> Script_int.n Script_int.num) in + Instructions.join_tickets size1 size2 tez1 tez2 + | IHalt _, _ -> Instructions.halt + | ILog _, _ -> Instructions.log + | IOpen_chest (_, _), (_, (chest, (time, _))) -> + let plaintext_size = + Script_timelock.get_plaintext_size chest - 1 |> Size.of_int + in + let log_time = Z.log2 Z.(one + Script_int.to_zint time) |> Size.of_int in + Instructions.open_chest log_time plaintext_size + | IMin_block_time _, _ -> Instructions.min_block_time + | IEmit _, _ -> Instructions.emit + | ILsl_bytes (_, _), (x, (y, _)) -> + let y = + match Script_int.to_int y with + | Some y -> y + | None -> (* overflow *) assert false + in + Instructions.lsl_bytes (Size.bytes x) y + | ILsr_bytes (_, _), (x, (y, _)) -> + let y = + match Script_int.to_int y with + | Some y -> y + | None -> (* overflow *) assert false + in + Instructions.lsr_bytes (Size.bytes x) y + | IOr_bytes (_, _), (x, (y, _)) -> + Instructions.or_bytes (Size.bytes x) (Size.bytes y) + | IAnd_bytes (_, _), (x, (y, _)) -> + Instructions.and_bytes (Size.bytes x) (Size.bytes y) + | IXor_bytes (_, _), (x, (y, _)) -> + Instructions.xor_bytes (Size.bytes x) (Size.bytes y) + | INot_bytes (_, _), (x, _) -> Instructions.not_bytes (Size.bytes x) + +let extract_control_trace (type bef_top bef aft_top aft) + (cont : (bef_top, bef, aft_top, aft) Script_typed_ir.continuation) = + match cont with + | KNil -> Control.nil + | KCons _ -> Control.cons + | KReturn _ -> Control.return + | KMap_head (_, _) -> Control.map_head + | KUndip _ -> Control.undip + | KLoop_in _ -> Control.loop_in + | KLoop_in_left _ -> Control.loop_in_left + | KIter (_, _, xs, _) -> Control.iter (Size.of_int (List.length xs)) + | KList_enter_body (_, xs, ys, _, _, _) -> + Control.list_enter_body + (Size.of_int (List.length xs)) + (Size.of_int (Script_list.length ys)) + | KList_exit_body (_, _, _, _, _, _) -> Control.list_exit_body + | KMap_enter_body (_, xs, _, _, _) -> + Control.map_enter_body (Size.of_int (List.length xs)) + | KMap_exit_body (_, _, map, k, _, _) -> + let (module Map) = Script_map.get_module map in + let key_size = Map.OPS.key_size k in + Control.map_exit_body key_size (Size.map map) + | KView_exit _ -> Control.view_exit + | KLog _ -> Control.log + +(** [Stop_bench] gets raised when a [IFailwith] would be the next instruction. + This allows us to recover the full execution trace, including the trace of + the [IFailwith]. + + The actual benchmark will follow the same execution branch, but instead will + raise an [error] which will be ignored. Thus it is safe to end a benchmark + with [IFailwith], but timings are expected to be different from ending with + [IHalt]. This means that, if we choose to include this behavior in any + benchmark, [IFailwith] must be benched. *) +exception Stop_bench + +let extract_deps (type bef_top bef aft_top aft) ctxt step_constants + (sty : (bef_top, bef) Script_typed_ir.stack_ty) + (kinstr : (bef_top, bef, aft_top, aft) Script_typed_ir.kinstr) + (stack : bef_top * bef) = + let trace = ref [] in + (* Logger definition *) + let logger = + Script_interpreter_logging.make + (module struct + let log_interp _instr _ctxt _log _stack_ty _stack = () + + let log_entry : + type a s b f. (a, s, b, f, a, s) Script_typed_ir.logging_function = + fun kinstr ctxt _loc _stack_ty stack -> + trace := extract_ir_sized_step ctxt kinstr stack :: !trace ; + match kinstr with IFailwith _ -> raise Stop_bench | _ -> () + + let log_control kont = trace := extract_control_trace kont :: !trace + + let log_exit _instr _ctxt _log _stack_ty _stack = () + + let get_log () = Environment.Error_monad.return_none + end) + in + try + let res = + Lwt_main.run + (Script_interpreter.Internals.kstep + (Some logger) + ctxt + step_constants + sty + kinstr + (fst stack) + (snd stack)) + in + match Environment.wrap_tzresult res with + | Error errs -> + Format.eprintf "%a@." Error_monad.pp_print_trace errs ; + raise (Failure "Interpreter_workload.extract_deps: error in step") + | Ok (_aft_top, _aft, _ctxt) -> + (* ((aft_top, aft), List.rev !trace, ctxt) *) + List.rev !trace + with Stop_bench -> List.rev !trace + +let extract_deps_continuation (type bef_top bef aft_top aft) ctxt step_constants + (stack_type : (bef_top, bef) stack_ty) + (cont : (bef_top, bef, aft_top, aft) Script_typed_ir.continuation) + (stack : bef_top * bef) = + let trace = ref [] in + (* Logger definition *) + let logger = + Script_interpreter_logging.make + (module struct + let log_interp _instr _ctxt _log _stack_ty _stack = () + + let log_entry : + type a s b f. (a, s, b, f, a, s) Script_typed_ir.logging_function = + fun kinstr ctxt _loc _stack_ty stack -> + trace := extract_ir_sized_step ctxt kinstr stack :: !trace ; + match kinstr with IFailwith _ -> raise Stop_bench | _ -> () + + let log_control kont = trace := extract_control_trace kont :: !trace + + let log_exit _instr _ctxt _log _stack_ty _stack = () + + let get_log () = Environment.Error_monad.return_none + end) + in + try + let res = + let _gas_counter, outdated_ctxt = + Local_gas_counter.local_gas_counter_and_outdated_context ctxt + in + Lwt_main.run + (Script_interpreter.Internals.next + (Some logger) + (outdated_ctxt, step_constants) + (Local_gas_counter 0xFF_FF_FF_FF) + stack_type + cont + (fst stack) + (snd stack)) + in + match Environment.wrap_tzresult res with + | Error errs -> + Format.eprintf "%a@." Error_monad.pp_print_trace errs ; + raise (Failure "Interpreter_workload.extract_deps: error in step") + | Ok (_aft_top, _aft, _outdated_ctxt, _gas) -> + (* ((aft_top, aft), List.rev !trace, outdated_ctxt, gas) *) + List.rev !trace + with Stop_bench -> List.rev !trace + +let sized_step_to_sparse_vec {name; args} = + let s = string_of_instr_or_cont name in + match args with + | [] -> Sparse_vec.String.of_list [(s, float_of_int 1)] + | _ -> + List.fold_left + (fun acc {name; arg} -> + Sparse_vec.String.( + add acc (of_list [(s ^ "_" ^ name, float_of_int (Size.to_int arg))]))) + Sparse_vec.String.zero + args + +let trace_to_sparse_vec trace = + List.fold_left + (fun acc step -> Sparse_vec.String.add acc (sized_step_to_sparse_vec step)) + Sparse_vec.String.zero + trace diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_commands.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_commands.ml new file mode 100644 index 000000000000..b53daf1b8e5b --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_commands.ml @@ -0,0 +1,213 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Michelson_generation + +let group = + { + Tezos_clic.name = "Michelson generation"; + title = "Command for generating random Michelson code and data"; + } + +module Michelson_concat_cmd = struct + let handler () file1 file2 file3 () = + let open Lwt_result_syntax in + let trace1 = Michelson_mcmc_samplers.load ~filename:file1 in + let trace2 = Michelson_mcmc_samplers.load ~filename:file2 in + let terms = trace1 @ trace2 in + let l1 = List.length trace1 in + let l2 = List.length trace2 in + Format.eprintf + "Loaded %d terms from %s, %d terms from %s, total %d@." + l1 + file1 + l2 + file2 + (l1 + l2) ; + Michelson_mcmc_samplers.save ~filename:file3 ~terms ; + return_unit + + let params = + Tezos_clic.( + prefixes [Protocol.name; "michelson"; "concat"; "files"] + @@ string ~name:"FILENAME" ~desc:"First file" + @@ prefixes ["and"] + @@ string ~name:"FILENAME" ~desc:"Second file" + @@ prefixes ["into"] + @@ string ~name:"FILENAME" ~desc:"Target file" + @@ stop) + + let command = + Tezos_clic.command + ~group + ~desc:"Michelson generation" + Tezos_clic.no_options + params + handler +end + +let () = Registration.add_command Michelson_concat_cmd.command + +module Michelson_gen_cmd = struct + let lift_opt f opt_arg state = + match opt_arg with None -> state | Some arg -> f arg state + + let handler (min_size, max_size, burn_in, seed) terms_count terms_kind + filename () = + let open Lwt_result_syntax in + let default = Michelson_generation.default_generator_config in + let min = Option.value ~default:default.target_size.min min_size in + let max = Option.value ~default:default.target_size.max max_size in + let burn_in_multiplier = + Option.value ~default:default.burn_in_multiplier burn_in + in + let rng_state = + match seed with + | None -> + Format.eprintf "Self-initialization of PRNG@." ; + let state = Random.State.make_self_init () in + Format.(eprintf "PRNG state hash: %d@." (Hashtbl.hash state)) ; + state + | Some seed -> + Format.eprintf "PRNG initialized with seed %d@." seed ; + Random.State.make [|seed|] + in + let cfg = + {Michelson_generation.target_size = {min; max}; burn_in_multiplier} + in + let terms_count = + match int_of_string terms_count with + | exception Failure _ -> + Format.eprintf "TERMS-COUNT must be an integer, exiting@." ; + exit 1 + | terms_count -> + if terms_count <= 0 then ( + Format.eprintf "TERMS-COUNT must be strictly positive, exiting@." ; + exit 1) + else terms_count + in + let progress = + Benchmark_helpers.make_progress_printer + Format.err_formatter + terms_count + "Generating term" + in + let terms = + match terms_kind with + | "data" -> + Stdlib.List.init terms_count (fun _i -> + progress () ; + Michelson_mcmc_samplers.Data + (Michelson_generation.make_data_sampler rng_state cfg)) + | "code" -> + Stdlib.List.init terms_count (fun _i -> + progress () ; + Michelson_mcmc_samplers.Code + (Michelson_generation.make_code_sampler rng_state cfg)) + | _ -> + Format.eprintf "Term kind must be either \"data\" or \"code\"@." ; + exit 1 + in + Michelson_mcmc_samplers.save ~filename ~terms ; + return_unit + + let min_size_arg = + let open Lwt_result_syntax in + let min_size = + Tezos_clic.parameter (fun (_ : unit) parsed -> + try return (int_of_string parsed) + with _ -> + Format.eprintf "Error while parsing --min-size argument.@." ; + exit 1) + in + Tezos_clic.arg + ~doc:"Lower bound for target size of terms" + ~long:"min-size" + ~placeholder:"int" + min_size + + let max_size_arg = + let open Lwt_result_syntax in + let max_size = + Tezos_clic.parameter (fun (_ : unit) parsed -> + try return (int_of_string parsed) + with _ -> + Format.eprintf "Error while parsing --max-size argument.@." ; + exit 1) + in + Tezos_clic.arg + ~doc:"Lower bound for target size of terms" + ~long:"max-size" + ~placeholder:"int" + max_size + + let burn_in_arg = + let open Lwt_result_syntax in + let target_size = + Tezos_clic.parameter (fun (_ : unit) parsed -> + try return (int_of_string parsed) + with _ -> + Format.eprintf "Error while parsing --burn-in argument.@." ; + exit 1) + in + Tezos_clic.arg + ~doc:"Burn-in multiplier" + ~long:"burn-in" + ~placeholder:"int" + target_size + + let seed_arg = + let open Lwt_result_syntax in + let seed = + Tezos_clic.parameter (fun (_ : unit) parsed -> + try return (int_of_string parsed) + with _ -> + Format.eprintf "Error while parsing --seed argument.@." ; + exit 1) + in + Tezos_clic.arg ~doc:"RNG seed" ~long:"seed" ~placeholder:"int" seed + + let options = Tezos_clic.args4 min_size_arg max_size_arg burn_in_arg seed_arg + + let params = + Tezos_clic.( + prefixes [Protocol.name; "michelson"; "generate"] + @@ string ~name:"TERMS-COUNT" ~desc:"Number of terms to generate" + @@ prefixes ["terms"; "of"; "kind"] + @@ string ~name:"{data|code}" ~desc:"Kind of term to generate" + @@ prefixes ["in"] + @@ string ~name:"FILENAME" ~desc:"File where to save Michelson terms" + @@ stop) + + let command = + Tezos_clic.command + ~group + ~desc:"Michelson generation" + options + params + handler +end + +let () = Registration.add_command Michelson_gen_cmd.command diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.ml new file mode 100644 index 000000000000..d1422930010a --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.ml @@ -0,0 +1,113 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type generator_config = { + target_size : Base_samplers.range; + burn_in_multiplier : int; +} + +let default_generator_config = + {target_size = {Base_samplers.min = 100; max = 1000}; burn_in_multiplier = 5} + +let generator_config_encoding = + let open Data_encoding in + conv + (fun {target_size; burn_in_multiplier} -> (target_size, burn_in_multiplier)) + (fun (target_size, burn_in_multiplier) -> {target_size; burn_in_multiplier}) + (obj2 + (req "target_size" Base_samplers.range_encoding) + (req "burn_in_multiplier" int31)) + +(* ----------------------------------------------------------------------- *) + +(* ----------------------------------------------------------------------- *) + +module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct + let size = 16 + + let algo = `Default +end) + +module Samplers = + Michelson_samplers.Make + (struct + let parameters = + { + Michelson_samplers.base_parameters = + { + int_size = {min = 8; max = 32}; + string_size = {min = 8; max = 128}; + bytes_size = {min = 8; max = 128}; + }; + list_size = {min = 0; max = 1000}; + set_size = {min = 0; max = 1000}; + map_size = {min = 0; max = 1000}; + } + end) + (Crypto_samplers) + +module Michelson_base_samplers = Samplers.Michelson_base + +(* ----------------------------------------------------------------------- *) + +let make_data_sampler rng_state config = + let target_size = + Base_samplers.sample_in_interval rng_state ~range:config.target_size + in + let module Data = + Michelson_mcmc_samplers.Make_data_sampler + (Michelson_base_samplers) + (Crypto_samplers) + (struct + let rng_state = rng_state + + let target_size = target_size + + let verbosity = `Silent + end) + in + let burn_in = target_size * config.burn_in_multiplier in + let generator = Data.generator ~burn_in rng_state in + generator rng_state + +let make_code_sampler rng_state config = + let target_size = + Base_samplers.sample_in_interval rng_state ~range:config.target_size + in + let module Code = + Michelson_mcmc_samplers.Make_code_sampler + (Michelson_base_samplers) + (Crypto_samplers) + (struct + let rng_state = rng_state + + let target_size = target_size + + let verbosity = `Silent + end) + in + let burn_in = target_size * config.burn_in_multiplier in + let generator = Code.generator ~burn_in rng_state in + generator rng_state diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.mli b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.mli new file mode 100644 index 000000000000..89868e6f58b1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_generation.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {2 Wrappers around some Michelson generators and related helpers} *) + +(** [generator_config] specifies some parameters to the + {!Tezos_benchmark_alpha.Michelson_mcmc_samplers} Michelson code and data generators. *) +type generator_config = { + target_size : Base_samplers.range; + (** The target size of the terms, in number of nodes, is sampled uniformly + in [target_size]. *) + burn_in_multiplier : int; + (** The generators are based on a Markov chain, which must be + "heated-up" until it reaches its stationary state. A prefix of samples + are therefore thrown away: this is called the {e burn-in} phase. + The number of thrown away terms is proportional to [burn_in_multiplier] + and [target_size]. *) +} + +(** Default configuration for the generators. *) +val default_generator_config : generator_config + +val generator_config_encoding : generator_config Data_encoding.t + +(** Samplers *) + +(** [make_data_sampler] constructs a Michelson data sampler based on the + infrastructure available in {!Tezos_benchmark_alpha.Michelson_mcmc_samplers}. *) +val make_data_sampler : + Random.State.t -> generator_config -> Michelson_mcmc_samplers.michelson_data + +(** [make_code_sampler] constructs a Michelson code sampler based on the + infrastructure available in {!Tezos_benchmark_alpha.Michelson_mcmc_samplers}. *) +val make_code_sampler : + Random.State.t -> generator_config -> Michelson_mcmc_samplers.michelson_code + +(** [Samplers] is an instance of the direct-style (non-MCMC based) samplers + implemented in {!Tezos_benchmark_alpha.Michelson_samplers}. *) +module Samplers : Michelson_samplers.S diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_types.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_types.ml new file mode 100644 index 000000000000..74a49958dbfe --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/michelson_types.ml @@ -0,0 +1,130 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Script_typed_ir + +[@@@ocaml.warning "-32"] + +let ( @$ ) x y = Item_t (x, y) + +let bot = Bot_t + +let unit = unit_t + +(* the type of integers *) +let int = int_t + +(* the type of naturals *) +let nat = nat_t + +(* the type of strings *) +let string = string_t + +(* the type of bytes *) +let bytes = bytes_t + +(* the type of booleans *) +let bool = bool_t + +(* the type of mutez *) +let mutez = mutez_t + +(* the type of public key *) +let public_key = key_t + +(* the type of key hashes *) +let key_hash = key_hash_t + +(* the type of signatures *) +let signature = signature_t + +(* the type of addresses *) +let address = address_t + +(* the type of chain ids *) +let chain_id = chain_id_t + +(* the type of timestamps *) +let timestamp = timestamp_t + +(* list type constructor *) +let list x = match list_t (-1) x with Error _ -> assert false | Ok t -> t + +(* option type constructor *) +let option x = match option_t (-1) x with Error _ -> assert false | Ok t -> t + +(* map type constructor*) +let map k v = match map_t (-1) k v with Error _ -> assert false | Ok t -> t + +(* map type constructor*) +let big_map k v = + match big_map_t (-1) k v with Error _ -> assert false | Ok t -> t + +(* set type constructor*) +let set k = match set_t (-1) k with Error _ -> assert false | Ok t -> t + +(* pair type constructor*) +let pair k1 k2 = + match pair_t (-1) k1 k2 with Error _ -> assert false | Ok t -> t + +(* comparable pair type constructor *) +let cpair k1 k2 = + match comparable_pair_t (-1) k1 k2 with Error _ -> assert false | Ok t -> t + +(* or type constructor*) +let or_ k1 k2 = match or_t (-1) k1 k2 with Error _ -> assert false | Ok t -> t + +(* comparable or type constructor *) +let cor k1 k2 = + match comparable_or_t (-1) k1 k2 with Error _ -> assert false | Ok t -> t + +let lambda x y = + match lambda_t (-1) x y with Error _ -> assert false | Ok t -> t + +let contract arg_ty = + match contract_t (-1) arg_ty with Error _ -> assert false | Ok t -> t + +let operation = operation_t + +let sapling_state memo_size = sapling_state_t ~memo_size + +let sapling_transaction memo_size = sapling_transaction_t ~memo_size + +let sapling_transaction_deprecated memo_size = + sapling_transaction_deprecated_t ~memo_size + +let bls12_381_g1 = bls12_381_g1_t + +let bls12_381_g2 = bls12_381_g2_t + +let bls12_381_fr = bls12_381_fr_t + +let ticket ty = + match ticket_t (-1) ty with Error _ -> assert false | Ok t -> t + +let chest_key = chest_key_t + +let chest = chest_t diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/registration_helpers.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/registration_helpers.ml new file mode 100644 index 000000000000..51056b6746e0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/registration_helpers.ml @@ -0,0 +1,58 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let ns = Namespace.root + +let adjust_tags tags = Tags.common :: tags + +type benchmark_type = Time | Alloc + +let register ?(benchmark_type = Time) ((module Bench) : Benchmark.t) = + let module B : Benchmark.S = struct + include Bench + + let tags = adjust_tags tags + end in + Registration.register ~add_timer:(benchmark_type = Time) (module B) + +let register_simple ?(benchmark_type = Time) (module Bench : Benchmark.Simple) = + let module B = struct + include Bench + + let tags = adjust_tags tags + end in + Registration.register_simple ~add_timer:(benchmark_type = Time) (module B) + +let register_simple_with_num ?(benchmark_type = Time) + (module Bench : Benchmark.Simple_with_num) = + let module B = struct + include Bench + + let tags = adjust_tags tags + end in + Registration.register_simple_with_num + ~add_timer:(benchmark_type = Time) + (module B) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_benchmarks.ml new file mode 100644 index 000000000000..a11db0599a25 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_benchmarks.ml @@ -0,0 +1,171 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module Size = Gas_input_size + +let ns = Namespace.make Registration_helpers.ns "sapling" + +let fv s = Free_variable.of_namespace (ns s) + +module Apply_diff_bench : Benchmark.S = struct + include Interpreter_benchmarks.Default_config + include Interpreter_benchmarks.Default_boilerplate + + let name = ns "SAPLING_APPLY_DIFF" + + let info = "Benchmarking SAPLING_APPLY_DIFF" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "sapling_storage" + + let tags = ["sapling"] + + let diff_from_tx (tx : Alpha_context.Sapling.transaction) = + let open Environment.Sapling.UTXO in + let commitments_and_ciphertexts = + List.map (fun x -> (x.cm, x.ciphertext)) tx.outputs + in + { + Protocol.Sapling_repr.commitments_and_ciphertexts; + nullifiers = List.map (fun (x : input) -> x.nf) tx.inputs; + } + + type workload = {nb_input : int; nb_output : int; nb_cm : int; nb_nf : int} + + let workload_encoding : workload Data_encoding.t = + let open Data_encoding in + def "diff_arg_encoding" + @@ conv + (fun {nb_input; nb_output; nb_cm; nb_nf} -> + (nb_input, nb_output, nb_cm, nb_nf)) + (fun (nb_input, nb_output, nb_cm, nb_nf) -> + {nb_input; nb_output; nb_cm; nb_nf}) + (tup4 Size.encoding Size.encoding Size.encoding Size.encoding) + + let workload_to_vector {nb_input; nb_output; nb_cm = _; nb_nf = _} = + let l = + [ + ("nb_input", float_of_int nb_input); + ("nb_output", float_of_int nb_output); + ] + in + Sparse_vec.String.of_list l + + let model = + Model.make + ~conv:(fun {nb_input; nb_output; _} -> (nb_input, (nb_output, ()))) + (Model.bilinear_affine + ~name + ~intercept:(fv "apply_diff_const") + ~coeff1:(fv "apply_diff_inputs") + ~coeff2:(fv "apply_diff_outputs")) + + let models = [("apply_diff", model)] + + let benchmark_apply_diff seed sapling_transition () = + let open Lwt_result_syntax in + let sapling_forge_rng_state = + Random.State.make + @@ Option.fold + ~none:Sapling_generation.shared_seed + ~some:(fun seed -> [|seed|]) + seed + in + Lwt_main.run + (let* ctxt, step_constants = + Execution_context.make ~rng_state:sapling_forge_rng_state () + in + let* _, _, _, _, ctxt, state_id = + Sapling_generation.prepare_seeded_state sapling_transition ctxt + in + let external_state_id = Alpha_context.Sapling.Id.parse_z state_id in + let internal_state_id = + Lazy_storage_kind.Sapling_state.Id.parse_z state_id + in + let* state, ctxt = + let*! result = + Alpha_context.Sapling.(state_from_id ctxt external_state_id) + in + Lwt.return (Environment.wrap_tzresult result) + in + Format.eprintf "state hash: %d@." (Hashtbl.hash state.diff) ; + Format.eprintf + "tx hash: %d@." + (Hashtbl.hash sapling_transition.sapling_tx) ; + let address = Contract_hash.to_b58check step_constants.self in + let chain_id = + Environment.Chain_id.to_b58check step_constants.chain_id + in + let anti_replay = address ^ chain_id in + Format.eprintf "anti-replay: %s@." anti_replay ; + let diff = diff_from_tx sapling_transition.sapling_tx in + let closure () = + ignore + (Lwt_main.run + (Sapling_generation.apply_diff ctxt internal_state_id diff)) + in + let workload = + { + nb_input = List.length sapling_transition.sapling_tx.inputs; + nb_output = List.length sapling_transition.sapling_tx.outputs; + nb_cm = Int64.to_int sapling_transition.commitment_count; + nb_nf = Int64.to_int sapling_transition.nullifier_count; + } + in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> + Format.eprintf + "Runner.benchmarkable_from_instr_str:\n%a@." + (Format.pp_print_list Error_monad.pp) + errs ; + exit 1 + + let create_benchmarks ~rng_state ~bench_num config = + ignore rng_state ; + match config.sapling with + | {sapling_txs_file; seed} -> + let transitions = + Sapling_generation.load + ~filename:sapling_txs_file + Sapling_generation.Non_empty + in + let length = List.length transitions in + if length < bench_num then + Format.eprintf + "KSapling_verify_update: warning, only %d available transactions \ + (requested %d)@." + length + bench_num ; + let transitions = List.take_n (min bench_num length) transitions in + List.map + (fun (_filename, tx) -> benchmark_apply_diff seed tx) + transitions +end + +let () = Registration_helpers.register (module Apply_diff_bench) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_commands.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_commands.ml new file mode 100644 index 000000000000..8700b7ccd5a4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_commands.ml @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Sapling_gen_cmd = struct + let lift_opt f opt_arg state = + match opt_arg with None -> state | Some arg -> f arg state + + (* ----------------------------------------------------------------------- *) + (* Handling options for the "generate sapling transactions" command *) + + (* Generic max-%s argument *) + let max name = + let open Lwt_result_syntax in + Tezos_clic.arg + ~doc:(Printf.sprintf "Maximum number of %s" name) + ~long:(Printf.sprintf "max-%s" name) + ~placeholder:"integer" + (Tezos_clic.parameter (fun (_ : unit) parsed -> + match int_of_string parsed with + | exception Failure _ -> + Format.eprintf + "Ill-formatted --max-%s option (expected integer), exiting@." + name ; + exit 1 + | res when res < 0 -> + Format.eprintf + "--max-%s should be a positive integer, exiting@." + name ; + exit 1 + | res -> return res)) + + (* Integer argument --seed *) + let seed_arg = + let open Lwt_result_syntax in + let seed = + Tezos_clic.parameter (fun (_ : unit) parsed -> + try return (int_of_string parsed) + with _ -> + Format.eprintf "Error while parsing --seed argument.@." ; + exit 1) + in + Tezos_clic.arg ~doc:"RNG seed" ~long:"seed" ~placeholder:"int" seed + + let positive_param = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun _ s -> + match int_of_string_opt s with + | Some i when i > 0 -> return i + | _ -> failwith "Parameter should be a positive integer literal") + + open Sapling_generation + + let set_max_inputs max_inputs options = {options with max_inputs} + + let set_max_outputs max_outputs options = {options with max_outputs} + + let set_max_nullifiers max_nullifiers options = {options with max_nullifiers} + + let set_max_additional_commitments max_additional_commitments options = + {options with max_additional_commitments} + + let set_seed seed (options : sapling_gen_options) = + {options with seed = Some seed} + + let sapling_handler + (max_inputs, max_outputs, max_nullifiers, max_additional_commitments, seed) + tx_count save_to () = + let open Lwt_result_syntax in + let sapling_gen_options = + default_sapling_gen_options + |> lift_opt set_max_inputs max_inputs + |> lift_opt set_max_outputs max_outputs + |> lift_opt set_max_nullifiers max_nullifiers + |> lift_opt set_max_additional_commitments max_additional_commitments + |> lift_opt set_seed seed + in + generate save_to tx_count sapling_gen_options ; + return_unit + + let options = + Tezos_clic.args5 + (max "inputs") + (max "outputs") + (max "nullifiers") + (max "additional-commitments") + seed_arg + + let params = + Tezos_clic.( + prefixes [Protocol.name; "sapling"; "generate"] + @@ param + ~name:"SAPLING-TX-COUNT" + ~desc:"Number of sapling transactions to generate" + positive_param + @@ prefixes ["transactions"; "in"] + @@ string + ~name:"SAPLING-TX-FILE" + ~desc:"File containing sapling transactions" + @@ stop) + + let group = + { + Tezos_clic.name = "Sapling tx generation"; + title = "Command for generating random sapling transactions"; + } + + let command = + Tezos_clic.command + ~group + ~desc:"Sapling transaction generation" + options + params + sapling_handler +end + +let () = Registration.add_command Sapling_gen_cmd.command diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_generation.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_generation.ml new file mode 100644 index 000000000000..1cfdcd91d55a --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/sapling_generation.ml @@ -0,0 +1,608 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(* ------------------------------------------------------------------------- *) +type sapling_gen_options = { + max_inputs : int; + max_outputs : int; + max_nullifiers : int; + max_additional_commitments : int; + seed : int option; +} + +let default_sapling_gen_options = + { + max_inputs = 100; + max_outputs = 100; + max_nullifiers = 100; + max_additional_commitments = 50; + seed = None; + } + +(* ------------------------------------------------------------------------- *) +(* Evil incantations *) + +(* We have to break the protocol abstraction boundary quite often in this + module. Props to whoever finds a way to avoid these calls. *) + +let alpha_to_raw (x : Alpha_context.t) : Raw_context.t = Obj.magic x + +let raw_to_alpha (x : Raw_context.t) : Alpha_context.t = Obj.magic x + +(* ------------------------------------------------------------------------- *) +(* Helpers *) + +(* sample a random permutation of [0 ; ... ; n-1] *) +let fisher_yates n state = + let a = Array.init n (fun i -> i) in + for i = 0 to Array.length a - 1 do + let j = Random.State.int state (i + 1) in + let tmp = a.(j) in + a.(j) <- a.(i) ; + a.(i) <- tmp + done ; + a + +(* sample a random injection of [0 ; ... ; m-1 ] in [0 ; ... ; n - 1] *) +let random_injection m n state = + if m > n then invalid_arg "random_injection" + else + let a = fisher_yates n state in + Array.sub a 0 m + +(* ------------------------------------------------------------------------- *) +(* Sapling generation *) + +(* Sapling state spec + sapling transaction valid for that state. *) +type sapling_transition = { + state_seed : int64; + nullifier_count : int64; + commitment_count : int64; + sapling_tx : Alpha_context.Sapling.transaction; +} + +type forge_info = { + rcm : Tezos_sapling.Core.Client.Rcm.t; + position : int64; + amount : int64; + address : Tezos_sapling.Core.Client.Viewing_key.address; + nf : Tezos_sapling.Core.Client.Nullifier.t; +} + +let random_amount state sum = + Random.State.int64 + state + (Int64.sub Tezos_sapling.Core.Validator.UTXO.max_amount sum) + +let reverse diff = + Protocol.Sapling_repr. + { + diff with + commitments_and_ciphertexts = List.rev diff.commitments_and_ciphertexts; + } + +let pp_rpc_diff fmtr (diff : Protocol.Sapling_repr.diff) = + let json = + Data_encoding.Json.construct Protocol.Sapling_repr.diff_encoding diff + in + Format.fprintf fmtr "%a" Data_encoding.Json.pp json + +let random_bytes state size = + Bytes.init size (fun _ -> Char.chr (Random.State.int state 256)) + +let rec gen_rcm state = + let rcm = + Data_encoding.Binary.of_bytes_exn + Tezos_sapling.Core.Client.Rcm.encoding + (random_bytes state 32) + in + try + Tezos_sapling.Core.Client.Rcm.assert_valid rcm ; + rcm + with _ -> gen_rcm state + +(* Adds a commitment, ciphertext, cv to an rpc_diff *) +let add_input diff vk index position sum state = + let open Lwt_result_syntax in + let rcm = gen_rcm state in + let amount = random_amount state sum in + let new_idx, address = + Tezos_sapling.Core.Client.Viewing_key.new_address vk index + in + let cv = + Tezos_sapling.Core.Client.CV.of_bytes (random_bytes state 32) + |> WithExceptions.Option.get ~loc:__LOC__ + in + let ciphertext, cm = + Tezos_sapling.Core.Client.Forge.Output.to_ciphertext + Tezos_sapling.Core.Client.Forge.Output. + {address; amount; memo = Bytes.empty} + cv + vk + rcm + (Tezos_sapling.Core.Client.DH.esk_random ()) + in + let nf = + Tezos_sapling.Core.Client.Nullifier.compute address vk ~amount rcm ~position + in + let diff = + Protocol.Sapling_repr. + { + diff with + commitments_and_ciphertexts = + (cm, ciphertext) :: diff.commitments_and_ciphertexts; + } + in + return (diff, {rcm; position; amount; address; nf}, new_idx) + +let generate_commitments ~vk ~nb_input ~nb_cm ~nb_nf ~diff ~index state = + let open Lwt_result_syntax in + let inj = random_injection nb_input nb_cm state in + let use_for_input i = Array.exists (fun k -> k = i) inj in + let rec loop i cm_index nb_nf diff to_forge sum = + if i = nb_cm then return (reverse diff, to_forge) + else if use_for_input i then + (* create commitment for input *) + let* diff, forge_info, next_index = + add_input diff vk cm_index (Int64.of_int i) sum state + in + let sum = Int64.add sum forge_info.amount in + loop (i + 1) next_index nb_nf diff (forge_info :: to_forge) sum + else + (* create commitment (not for input) *) + let* diff, {nf; _}, next_index = + add_input diff vk cm_index (Int64.of_int i) sum state + in + (* can we use a nullifier? *) + if nb_nf = 0 then (* No. *) + loop (i + 1) next_index nb_nf diff to_forge sum + else + (* Yes! Grab it. *) + let diff = + Protocol.Sapling_repr.{diff with nullifiers = nf :: diff.nullifiers} + in + loop (i + 1) next_index (nb_nf - 1) diff to_forge sum + in + loop 0 index nb_nf diff [] 0L + +(* Add roots to the storage. One cm has to be added for every root. *) +let rec add_root nb_root ctxt id vk index size diff state = + let open Lwt_result_syntax in + if nb_root > 0 then + let* diff_to_add, {position = size; _}, new_idx = + add_input Protocol.Sapling_storage.empty_diff vk index size 0L state + in + let* ctxt, _ = + let*! result = Protocol.Sapling_storage.apply_diff ctxt id diff_to_add in + Lwt.return (Environment.wrap_tzresult result) + in + (* We call it nb_root -1 because one root is already present*) + add_root + (nb_root - 1) + ctxt + id + vk + new_idx + (Int64.succ size) + Protocol.Sapling_repr. + { + diff with + commitments_and_ciphertexts = + diff.commitments_and_ciphertexts + @ diff_to_add.commitments_and_ciphertexts; + } + state + else return (ctxt, diff) + +(* Compute a state as an OCaml object to compute the witness *) +let state_from_rpc_diff rpc_diff = + Tezos_sapling.Storage.add + (Tezos_sapling.Storage.empty ~memo_size:0) + rpc_diff.Protocol.Sapling_repr.commitments_and_ciphertexts + +(* Create an (unspendable) output from a proving context and a vk *) +let output proving_ctx vk sum state = + let address = Tezos_sapling.Core.Client.Viewing_key.dummy_address () in + let amount = random_amount state sum in + let rcm = Tezos_sapling.Core.Client.Rcm.random () in + let esk = Tezos_sapling.Core.Client.DH.esk_random () in + let cv_o, proof_o = + Tezos_sapling.Core.Client.Proving.output_proof + proving_ctx + esk + address + rcm + ~amount + in + let ciphertext, cm = + Tezos_sapling.Core.Client.Forge.Output.to_ciphertext + Tezos_sapling.Core.Client.Forge.Output. + {address; amount; memo = Bytes.empty} + cv_o + vk + rcm + esk + in + (Tezos_sapling.Core.Validator.UTXO.{cm; proof_o; ciphertext}, amount) + +(* Returns a list of outputs and the sum of their amount *) +let outputs nb_output proving_ctx vk state = + let rec aux output_amount list_outputs nb_output sum = + match nb_output with + | 0 -> (output_amount, list_outputs) + | nb_output -> + let output, amount = output proving_ctx vk sum state in + assert ( + Int64.compare + amount + (Int64.sub + Int64.max_int + Tezos_sapling.Core.Validator.UTXO.max_amount) + < 0) ; + aux + (Int64.add output_amount amount) + (output :: list_outputs) + (nb_output - 1) + (Int64.add sum amount) + in + aux 0L [] nb_output 0L + +(* Create the list of inputs. To use once the merkle tree is completed. *) +let make_inputs to_forge local_state proving_ctx sk vk root anti_replay = + let open Lwt_result_syntax in + List.map_ep + (fun {rcm; position; amount; address; nf} -> + let witness = Tezos_sapling.Storage.get_witness local_state position in + let ar = Tezos_sapling.Core.Client.Proving.ar_random () in + let cv, rk, proof = + Tezos_sapling.Core.Client.Proving.spend_proof + proving_ctx + vk + sk + address + rcm + ar + ~amount + ~root + ~witness + in + let signature = + Tezos_sapling.Core.Client.Proving.spend_sig + sk + ar + cv + nf + rk + proof + anti_replay + in + return + Tezos_sapling.Core.Validator.UTXO. + {cv; nf; rk; proof_i = proof; signature}) + to_forge + +let init_fresh_sapling_state ctxt = + let open Lwt_result_syntax in + let* ctxt, id = + Protocol.Lazy_storage_diff.fresh + Protocol.Lazy_storage_kind.Sapling_state + ~temporary:false + ctxt + in + let* ctxt = + Protocol.Sapling_storage.init ctxt id ~memo_size:0 + (* TODO CHECK *) + in + return (ctxt, id) + +let generate_spending_and_viewing_keys state = + let sk = + Tezos_sapling.Core.Client.Spending_key.of_seed (random_bytes state 32) + in + let vk = Tezos_sapling.Core.Client.Viewing_key.of_sk sk in + (sk, vk) + +let prepare_seeded_state_internal ~(nb_input : int) ~(nb_nf : int) + ~(nb_cm : int) (ctxt : Raw_context.t) (state : Random.State.t) : + (Sapling_repr.diff + * forge_info list + * Tezos_sapling.Core.Client.Spending_key.t + * Tezos_sapling.Core.Client.Viewing_key.t + * Raw_context.t + * Protocol.Lazy_storage_kind.Sapling_state.Id.t) + tzresult + Lwt.t = + let open Lwt_result_syntax in + let* ctxt, id = + let*! result = init_fresh_sapling_state ctxt in + Lwt.return (Environment.wrap_tzresult result) + in + let index_start = Tezos_sapling.Core.Client.Viewing_key.default_index in + let sk, vk = generate_spending_and_viewing_keys state in + let* diff, to_forge = + generate_commitments + ~vk + ~nb_input + ~nb_cm + ~nb_nf + ~diff:Protocol.Sapling_storage.empty_diff + ~index:index_start + state + in + let* ctxt, _size = + let*! result = Protocol.Sapling_storage.apply_diff ctxt id (reverse diff) in + Lwt.return (Environment.wrap_tzresult result) + in + return (diff, to_forge, sk, vk, ctxt, id) + +let prepare_seeded_state + {state_seed; nullifier_count; commitment_count; sapling_tx} ctxt = + let open Lwt_result_syntax in + let rng_state = Random.State.make [|Int64.to_int state_seed|] in + let* diff, forge_info, spending_key, viewing_key, raw_ctxt, raw_id = + prepare_seeded_state_internal + ~nb_input:(List.length sapling_tx.inputs) + ~nb_nf:(Int64.to_int nullifier_count) + ~nb_cm:(Int64.to_int commitment_count) + (alpha_to_raw ctxt) + rng_state + in + let id = Protocol.Lazy_storage_kind.Sapling_state.Id.unparse_to_z raw_id in + return (diff, forge_info, spending_key, viewing_key, raw_to_alpha raw_ctxt, id) + +let generate ~(nb_input : int) ~(nb_output : int) ~(nb_nf : int) ~(nb_cm : int) + ~(anti_replay : string) ~ctxt state = + let open Lwt_result_syntax in + assert (nb_input <= nb_cm) ; + assert (nb_nf <= nb_cm - nb_input) ; + let* diff, to_forge, sk, vk, ctxt, id = + prepare_seeded_state_internal ~nb_input ~nb_nf ~nb_cm ctxt state + in + let local_state = state_from_rpc_diff diff in + let root = Tezos_sapling.Storage.get_root local_state in + let* transaction = + Tezos_sapling.Core.Client.Proving.with_proving_ctx (fun proving_ctx -> + let* inputs = + make_inputs to_forge local_state proving_ctx sk vk root anti_replay + in + let output_amount, outputs = outputs nb_output proving_ctx vk state in + let input_amount = + List.fold_left + (fun sum {amount; _} -> + assert ( + Int64.compare + sum + (Int64.sub + Int64.max_int + Tezos_sapling.Core.Validator.UTXO.max_amount) + < 0) ; + Int64.add sum amount) + 0L + to_forge + in + let balance = Int64.sub input_amount output_amount in + let bound_data = + (* The bound data are benched separately so we add + empty bound data*) + "" + in + let binding_sig = + Tezos_sapling.Core.Client.Proving.make_binding_sig + proving_ctx + inputs + outputs + ~balance + ~bound_data + anti_replay + in + let transaction = + Tezos_sapling.Core.Validator.UTXO. + {inputs; outputs; binding_sig; balance; root; bound_data} + in + return transaction) + in + assert (Compare.List_length_with.(transaction.inputs = nb_input)) ; + assert (Compare.List_length_with.(transaction.outputs = nb_output)) ; + return (transaction, (ctxt, id)) + +(* ------------------------------------------------------------------------- *) +(* Nicely packaging sapling generation for snoop *) + +let sapling_transition_encoding = + let open Data_encoding in + conv + (fun {state_seed; nullifier_count; commitment_count; sapling_tx} -> + (state_seed, nullifier_count, commitment_count, sapling_tx)) + (fun (state_seed, nullifier_count, commitment_count, sapling_tx) -> + {state_seed; nullifier_count; commitment_count; sapling_tx}) + (obj4 + (req "state_seed" int64) + (req "nullifier_count" int64) + (req "commitment_count" int64) + (req "sapling_tx" Alpha_context.Sapling.transaction_encoding)) + +let sapling_dataset_encoding = Data_encoding.list sapling_transition_encoding + +let save ~filename ~txs = + let str = + match Data_encoding.Binary.to_string sapling_dataset_encoding txs with + | Error err -> + Format.eprintf + "Sapling_generation.save: encoding failed (%a); exiting@." + Data_encoding.Binary.pp_write_error + err ; + exit 1 + | Ok res -> res + in + ignore (* TODO handle error *) + (Lwt_main.run @@ Tezos_stdlib_unix.Lwt_utils_unix.create_file filename str) + +let load_file filename = + let open Lwt_syntax in + Lwt_main.run + @@ let* str = Tezos_stdlib_unix.Lwt_utils_unix.read_file filename in + Format.eprintf "Sapling_generation.load: loaded %s@." filename ; + match Data_encoding.Binary.of_string sapling_dataset_encoding str with + | Ok result -> + let result = List.map (fun tx -> (filename, tx)) result in + return result + | Error err -> + Format.eprintf + "Sapling_generation.load: can't load file (%a); exiting@." + Data_encoding.Binary.pp_read_error + err ; + exit 1 + +let get_all_sapling_data_files directory = + let is_sapling_data file = + let regexp = Str.regexp ".*\\.sapling" in + Str.string_match regexp file 0 + in + let lift file = directory ^ "/" ^ file in + let handle = Unix.opendir directory in + let rec loop acc = + match Unix.readdir handle with + | file -> if is_sapling_data file then loop (lift file :: acc) else loop acc + | exception End_of_file -> + Unix.closedir handle ; + acc + in + loop [] + +type type_transaction = Empty | Non_empty + +let load ~filename type_transaction = + if not (Sys.file_exists filename) then ( + Format.eprintf "Sapling_generation.load: file does not exist@." ; + Stdlib.failwith "Sapling_generation.load") + else if Sys.is_directory filename then + let () = + Format.eprintf + "Sapling_generation.load: loading all *.sapling files from directory \ + %s@." + filename + in + let files = get_all_sapling_data_files filename in + List.concat_map load_file files + |> List.filter (fun (_str, transac) -> + match type_transaction with + | Empty -> + List.is_empty transac.sapling_tx.outputs + && List.is_empty transac.sapling_tx.inputs + | Non_empty -> + (not (List.is_empty transac.sapling_tx.outputs)) + || not (List.is_empty transac.sapling_tx.inputs)) + else load_file filename + +let shared_seed = [|9798798; 217861209; 876786|] + +let generate (save_to : string) (tx_count : int) + (sapling_gen_options : sapling_gen_options) = + let open Lwt_result_syntax in + let result = + Lwt_main.run + (let { + max_inputs; + max_outputs; + max_nullifiers; + max_additional_commitments; + seed; + } = + sapling_gen_options + in + let rng_state = + (* /!\ This must match the seed used at benchmark time, + defined in Runner.benchmark_sapling. /!\ *) + Random.State.make + @@ Option.fold ~none:shared_seed ~some:(fun seed -> [|seed|]) seed + in + let* ctxt, step_constants = Execution_context.make ~rng_state () in + let address = Contract_hash.to_b58check step_constants.self in + let chain_id = + Environment.Chain_id.to_b58check step_constants.chain_id + in + let anti_replay = address ^ chain_id in + let ctxt = alpha_to_raw ctxt in + (match sapling_gen_options.seed with + | None -> Random.self_init () + | Some seed -> Random.init seed) ; + let seeds = + Stdlib.List.init tx_count (fun i -> (i, Random.int 0x3FFFFFFF)) + in + let rec loop seeds acc = + match seeds with + | [] -> return acc + | (i, seed) :: tl -> + let nb_input = + if max_inputs = 0 then 0 else 1 + Random.int max_inputs + in + let nb_output = + if max_outputs = 0 then 0 else 1 + Random.int max_outputs + in + let nb_nf = 1 + Random.int max_nullifiers in + let nb_cm = + nb_input + nb_nf + Random.int max_additional_commitments + in + let () = + Format.eprintf "@." ; + Format.eprintf "generating sapling tx %i/%d@." (i + 1) tx_count ; + Format.eprintf "saving to file %s@." save_to ; + Format.eprintf "nb_input = %d@." nb_input ; + Format.eprintf "nb_output = %d@." nb_output ; + Format.eprintf "nb_nf = %d@." nb_nf ; + Format.eprintf "nb_cm = %d@." nb_cm ; + Format.eprintf "anti_replay = %s@." anti_replay + in + let state = Random.State.make [|seed|] in + let* tx, (_ctxt, _state_id) = + generate + ~nb_input + ~nb_output + ~nb_nf + ~nb_cm + ~anti_replay + ~ctxt + state + in + let result = + { + state_seed = Int64.of_int seed; + nullifier_count = Int64.of_int nb_nf; + commitment_count = Int64.of_int nb_cm; + sapling_tx = Obj.magic tx; + } + in + loop tl (result :: acc) + in + loop seeds []) + in + match result with Ok txs -> save ~filename:save_to ~txs | Error _ -> () + +let apply_diff ctxt id diff = + let open Lwt_result_syntax in + let* ctxt, size = Sapling_storage.apply_diff (alpha_to_raw ctxt) id diff in + return (raw_to_alpha ctxt, size) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/sc_rollup_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/sc_rollup_benchmarks.ml new file mode 100644 index 000000000000..ccc9d2b88996 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/sc_rollup_benchmarks.ml @@ -0,0 +1,707 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let ns = Namespace.make Registration_helpers.ns "sc_rollup" + +let fv s = Free_variable.of_namespace (ns s) + +let ( -- ) min max : Base_samplers.range = {min; max} + +(** This section contains preliminary definitions for building a pvm state from + scratch. *) +module Pvm_state_generator = struct + module Context = Tezos_context_memory.Context_binary + + module Wasm_context = struct + type Tezos_tree_encoding.tree_instance += Tree of Context.tree + + module Tree = struct + include Context.Tree + + type tree = Context.tree + + type t = Context.t + + type key = string list + + type value = bytes + + let select = function + | Tree t -> t + | _ -> raise Tezos_tree_encoding.Incorrect_tree_type + + let wrap t = Tree t + end + + type tree = Context.tree + + type proof = Context.Proof.tree Context.Proof.t + + let verify_proof p f = + Lwt.map Result.to_option (Context.verify_tree_proof p f) + + let produce_proof context tree step = + let open Lwt_syntax in + let* context = Context.add_tree context [] tree in + let* _hash = Context.commit ~time:Time.Protocol.epoch context in + let index = Context.index context in + match Context.Tree.kinded_key tree with + | Some k -> + let* p = Context.produce_tree_proof index k step in + return_some p + | None -> return_none + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> + Sc_rollup_repr.State_hash.context_hash_to_state_hash hash + + let proof_before proof = + kinded_hash_to_state_hash proof.Context.Proof.before + + let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + + let proof_encoding = + let module Proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding + in + Proof_encoding.V2.Tree2.tree_proof_encoding + end + + let make_transaction value text contract = + let entrypoint = Entrypoint_repr.default in + let destination : Contract_hash.t = + Contract_hash.of_bytes_exn @@ Bytes.of_string contract + in + let open Tezos_micheline.Micheline in + let open Michelson_v1_primitives in + let unparsed_parameters = + strip_locations + @@ Prim + ( 0, + I_TICKET, + [ + Prim + (0, I_PAIR, [Int (0, Z.of_int32 value); String (1, text)], []); + ], + [] ) + in + Sc_rollup_outbox_message_repr.{unparsed_parameters; entrypoint; destination} + + let make_transactions ~rng_state ~max = + let open Base_samplers in + let n = sample_in_interval ~range:(0 -- max) rng_state in + Stdlib.List.init n (fun _ -> + let contract = uniform_string ~nbytes:20 rng_state in + let value = + Int32.of_int @@ sample_in_interval ~range:(-1000 -- 1000) rng_state + in + let text = string ~size:(0 -- 40) rng_state in + make_transaction value text contract) + + let make_outbox_message ~nb_transactions ~rng_state = + let transactions = make_transactions ~rng_state ~max:nb_transactions in + Sc_rollup_outbox_message_repr.Atomic_transaction_batch {transactions} + + let dummy_context = + let dummy = Context.init "/tmp" in + Context.empty @@ Lwt_main.run dummy + + let empty_tree = Context.Tree.empty dummy_context + + (* Build a pvm state from scratch. *) + let build_pvm_state rng_state ~nb_inbox_messages ~input_payload_size + ~nb_output_buffer_levels ~output_buffer_size ~nb_transactions ~tree_depth + ~tree_branching_factor = + let open Lwt_result_syntax in + let random_key () = + Base_samplers.readable_ascii_string ~size:(5 -- 5) rng_state + in + (* [gen_tree] Generates a tree for the given depth and branching factor. + This function is witten in CPS to avoid [stack-overflow] errors when + branching factor is 1 and tree depth is big. *) + let gen_tree () = + let bottom_tree = + let tree = empty_tree in + let key = [random_key ()] in + let value = Bytes.empty in + Context.Tree.add tree key value + in + let rec gen_tree tree_depth kont = + if tree_depth = 0 then kont bottom_tree + else + gen_tree + (tree_depth - 1) + (let rec kont' nb_subtrees acc_subtrees subtree = + let*! subtree in + let acc_subtrees = subtree :: acc_subtrees in + let nb_subtrees = nb_subtrees + 1 in + if nb_subtrees = tree_branching_factor then + let tree = empty_tree in + kont + @@ List.fold_left_s + (fun tree subtree -> + let key = [random_key ()] in + Context.Tree.add_tree tree key subtree) + tree + acc_subtrees + else gen_tree (tree_depth - 1) (kont' nb_subtrees acc_subtrees) + in + kont' 0 []) + in + gen_tree tree_depth Fun.id + in + (* Add trees of junk data in the [durable] and [wasm] parts + of the storage. *) + let*! durable_junk_tree = gen_tree () in + let*! wasm_junk_tree = gen_tree () in + let tree = empty_tree in + let*! tree = Context.Tree.add_tree tree ["durable"] durable_junk_tree in + let*! tree = Context.Tree.add_tree tree ["wasm"] wasm_junk_tree in + (* Create an output buffers and fill it with random batches of + transactions. *) + let open Tezos_webassembly_interpreter in + let open Tezos_scoru_wasm in + let module Index_Vector = Lazy_vector.Mutable.ZVector in + let module Level_Map = Lazy_map.Mutable.LwtInt32Map in + let output = + Level_Map.create + ~produce_value:(fun _ -> + Lwt.return @@ Index_Vector.create (Z.of_int output_buffer_size)) + () + in + let*! () = + let open Sc_rollup_outbox_message_repr in + List.iter_s + (fun l -> + let*! outbox = Level_Map.get (Int32.of_int l) output in + Lwt.return + @@ List.iter + (fun i -> + let out = make_outbox_message ~nb_transactions ~rng_state in + let outbox_message = + Data_encoding.Binary.to_bytes_exn encoding out + in + Index_Vector.set (Z.of_int i) outbox_message outbox) + Misc.(0 --> (output_buffer_size - 1))) + Misc.(0 --> (nb_output_buffer_levels - 1)) + in + let output = Output_buffer.Internal_for_tests.make output in + (* Create the input buffer. *) + let input = Index_Vector.create (Z.of_int nb_inbox_messages) in + let make_input_message (message_counter : int) : Input_buffer.message = + let open Base_samplers in + let random_payload () = + uniform_bytes ~nbytes:input_payload_size rng_state + in + { + raw_level = Int32.of_int message_counter; + message_counter = Z.of_int message_counter; + payload = random_payload (); + } + in + let () = + List.iter + (fun counter -> + Index_Vector.set (Z.of_int counter) (make_input_message counter) input) + Misc.(0 --> (nb_inbox_messages - 1)) + in + (* Encode the buffers and update the state of the pvm. *) + let buffers = Eval.{input; output} in + let buffers_encoding = Wasm_pvm.durable_buffers_encoding in + let module Tree_encoding_runner = + Tezos_tree_encoding.Runner.Make (Wasm_context.Tree) in + let*! tree = + Tree_encoding_runner.encode + (Tezos_tree_encoding.option buffers_encoding) + (Some buffers) + tree + in + Lwt.return (dummy_context, output, tree) + + let select_output ~output_buffer ~nb_output_buffer_levels ~output_buffer_size + rng_state = + let open Lwt_result_syntax in + let open Base_samplers in + (* Pick a level. *) + let outbox_level = + Int32.of_int + @@ sample_in_interval + ~range:(0 -- (nb_output_buffer_levels - 1)) + rng_state + in + (* Pick a message. *) + let message_index = + Z.of_int + @@ sample_in_interval ~range:(0 -- (output_buffer_size - 1)) rng_state + in + let*! bytes_output_message = + Tezos_webassembly_interpreter.Output_buffer.get_message + output_buffer + {outbox_level; message_index} + in + let message = + Data_encoding.Binary.of_bytes_exn + Sc_rollup_outbox_message_repr.encoding + bytes_output_message + in + let*? outbox_level = + Environment.wrap_tzresult @@ Raw_level_repr.of_int32 outbox_level + in + (* Produce an output proof for the picked message, and return the proof + and its length. *) + return Sc_rollup_PVM_sig.{outbox_level; message_index; message} +end + +(** This benchmark estimates the cost of verifying an output proof for the + Wasm PVM. + The inferred cost model is [c1 + c2 * proof_length]. *) +module Sc_rollup_verify_output_proof_benchmark = struct + open Pvm_state_generator + module Full_Wasm = + Sc_rollup_wasm.V2_0_0.Make (Environment.Wasm_2_0_0.Make) (Wasm_context) + + (* Benchmark starts here. *) + + let name = ns "Sc_rollup_verify_output_proof_benchmark" + + let info = "Estimating the cost of verifying an output proof" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "sc_rollup" + + let group = Benchmarks_proto.Benchmark.Group "sc_rollup" + + let tags = ["sc_rollup"] + + type config = { + nb_inbox_messages : int; + input_payload_size : int; + nb_output_buffer_levels : int; + output_buffer_size : int; + nb_transactions : int; + tree_depth : int; + tree_branching_factor : int; + } + + let config_encoding = + let open Data_encoding in + conv + (fun { + nb_inbox_messages; + input_payload_size; + nb_output_buffer_levels; + output_buffer_size; + nb_transactions; + tree_depth; + tree_branching_factor; + } -> + ( nb_inbox_messages, + input_payload_size, + nb_output_buffer_levels, + output_buffer_size, + nb_transactions, + tree_depth, + tree_branching_factor )) + (fun ( nb_inbox_messages, + input_payload_size, + nb_output_buffer_levels, + output_buffer_size, + nb_transactions, + tree_depth, + tree_branching_factor ) -> + { + nb_inbox_messages : int; + input_payload_size : int; + nb_output_buffer_levels; + output_buffer_size; + nb_transactions; + tree_depth; + tree_branching_factor; + }) + (obj7 + (req "nb_inbox_messages" int31) + (req "input_payload_size" int31) + (req "nb_output_buffer_levels" int31) + (req "output_buffer_size" int31) + (req "nb_transactions" int31) + (req "tree_depth" int31) + (req "tree_branching_factor" int31)) + + (** The actual config used to generate the more accurate model in + [sc_rollup_costs.ml] is : + [{ + nb_inbox_messages = 1000; + input_payload_size = 4096; + nb_output_buffer_levels = 10_000; + output_buffer_size = 100; + nb_transactions = 50; + tree_depth = 10; + tree_branching_factor = 4; + }] + With the config above, the benchmark takes more than an hour. The default + config is lighter and takes a few minutes. + + The table below shows benchmarking results for different tree depths and + number of outbox levels of the pvm state. The branching factor of the + generated "junk" trees in this benchmark is 4 (i.e for a depth of 10 the + generated tree contains more than 1_000_000 nodes). A tree depth of more + than 10 or a number of outbox levels of more than 10000 reaches the + memory limit of a laptop with 16Gb of memory. All proofs generated by + these benchmarks are below 10kb. + + +-----------+---------------+-------------------------+-----------------+ + | Junk tree | Number of | Inferred model | Gas cost for a | + | depth | outbox levels | | proof 10kb long | + +-----------+---------------+-------------------------+-----------------+ + | 5 | 1000 | 7.907*size + 99291.292 | 178361 | + +-----------+---------------+-------------------------+-----------------+ + | 6 | 2000 | 9.510*size + 99516.012 | 194616 | + +-----------+---------------+-------------------------+-----------------+ + | 7 | 4000 | 11.383*size + 95445.175 | 209275 | + +-----------+---------------+-------------------------+-----------------+ + | 8 | 6000 | 11.316*size + 100760.29 | 213920 | + +-----------+---------------+-------------------------+-----------------+ + | 9 | 8000 | 11.227*size + 98748.490 | 211018 | + +-----------+---------------+-------------------------+-----------------+ + | 10 | 10000 | 11.680*size + 98707.082 | 215507 | + +-----------+---------------+-------------------------+-----------------+ + + The [nb_transactions] parameter is the max number of transactions in an + outbox message, it is set at 50 because a message with 50 transactions + approches the max size of an outbox message. Hence, this allows to + benchmark for various proof lengths. The [nb_inbox_messages] parameter is + set to correspond to the max number of messages in an inbox. And the + [input_payload_size] parameter is set to the biggest possible size of an + input message. These two parameters impact the number of nodes in the pvm + state and are stored in the "input" part of the state. We add data in this + "input" part because of its proximity with the "output" part in the pvm + state. *) + let default_config = + { + nb_inbox_messages = 1000; + input_payload_size = 4096; + nb_output_buffer_levels = 10_000; + output_buffer_size = 100; + nb_transactions = 50; + tree_depth = 10; + tree_branching_factor = 4; + } + + type workload = {proof_length : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {proof_length} -> proof_length) + (fun proof_length -> {proof_length}) + (obj1 (req "proof_length" int31)) + + let workload_to_vector {proof_length} = + Sparse_vec.String.of_list [("proof_length", float_of_int proof_length)] + + let model = + let open Benchmarks_proto in + Model.make ~conv:(fun {proof_length} -> (proof_length, ())) Model.affine + + let pvm_state = ref None + + let create_benchmark ~rng_state conf = + let nb_output_buffer_levels = conf.nb_output_buffer_levels in + let output_buffer_size = conf.output_buffer_size in + let prepare_benchmark_scenario () = + let open Lwt_result_syntax in + (* Build [pvm_state] and save it to be used for all benchmarks. The state + is large enough for each benchmark to be relatively random. *) + let*! context, output_buffer, initial_tree = + match !pvm_state with + | None -> + let res = + build_pvm_state + rng_state + ~nb_inbox_messages:conf.nb_inbox_messages + ~input_payload_size:conf.input_payload_size + ~nb_output_buffer_levels:conf.nb_output_buffer_levels + ~output_buffer_size:conf.output_buffer_size + ~nb_transactions:conf.nb_transactions + ~tree_depth:conf.tree_depth + ~tree_branching_factor:conf.tree_branching_factor + in + pvm_state := Some res ; + res + | Some pvm_state -> pvm_state + in + (* Select an output. *) + let* output = + select_output + ~output_buffer + ~nb_output_buffer_levels + ~output_buffer_size + rng_state + in + (* produce an output proof, and also return the length of its encoding.*) + let*! pf = Full_Wasm.produce_output_proof context initial_tree output in + match pf with + | Ok proof -> + let proof_length = + Data_encoding.Binary.length Full_Wasm.output_proof_encoding proof + in + return (proof, proof_length) + | Error _ -> assert false + in + + let output_proof, proof_length = + match Lwt_main.run @@ prepare_benchmark_scenario () with + | Ok (proof, len) -> (proof, len) + | Error _ -> assert false + in + let workload = {proof_length} in + + let closure () = + ignore (Lwt_main.run @@ Full_Wasm.verify_output_proof output_proof) + in + Generator.Plain {workload; closure} +end + +(** This benchmark estimates the cost of verifying an output proof for the + Wasm PVM. + The inferred cost model is [c1 + c2 * proof_length]. *) +module Sc_rollup_deserialize_output_proof_benchmark = struct + open Pvm_state_generator + open Benchmarks_proto + module Full_Wasm = + Sc_rollup_wasm.V2_0_0.Make (Environment.Wasm_2_0_0.Make) (Wasm_context) + + (* Benchmark starts here. *) + + let name = ns "Sc_rollup_deserialize_output_proof_benchmark" + + let info = "Estimating the cost of deserializing an output proof" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "sc_rollup" + + let group = Benchmarks_proto.Benchmark.Group "sc_rollup" + + let tags = ["sc_rollup"] + + type config = { + nb_output_buffer_levels : int; + output_buffer_size : int; + nb_transactions : int; + tree_depth : int; + } + + let config_encoding = + let open Data_encoding in + conv + (fun { + nb_output_buffer_levels; + output_buffer_size; + nb_transactions; + tree_depth; + } -> + ( nb_output_buffer_levels, + output_buffer_size, + nb_transactions, + tree_depth )) + (fun ( nb_output_buffer_levels, + output_buffer_size, + nb_transactions, + tree_depth ) -> + { + nb_output_buffer_levels; + output_buffer_size; + nb_transactions; + tree_depth; + }) + (obj4 + (req "nb_output_buffer_levels" int31) + (req "output_buffer_size" int31) + (req "nb_transactions" int31) + (req "tree_depth" int31)) + + let default_config = + { + nb_output_buffer_levels = 10_000; + output_buffer_size = 100; + nb_transactions = 50; + tree_depth = 10; + } + + type workload = {proof_length : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {proof_length} -> proof_length) + (fun proof_length -> {proof_length}) + (obj1 (req "proof_length" int31)) + + let workload_to_vector {proof_length} = + Sparse_vec.String.of_list [("proof_length", float_of_int proof_length)] + + let model = + let open Benchmarks_proto in + Model.make ~conv:(fun {proof_length} -> (proof_length, ())) Model.affine + + let pvm_state = ref None + + let create_benchmark ~rng_state conf = + let prepared_benchmark_scenario = + let nb_output_buffer_levels = conf.nb_output_buffer_levels in + let output_buffer_size = conf.output_buffer_size in + let tree_depth = conf.tree_depth in + let open Lwt_result_syntax in + (* Build [pvm_state] and save it to be used for all benchmarks. The state + is large enough for each benchmark to be relatively random. *) + let*! context, output_buffer, initial_tree = + match !pvm_state with + | Some pvm_state -> pvm_state + | None -> + let res = + build_pvm_state + rng_state + ~nb_inbox_messages:0 + ~input_payload_size:0 + ~nb_output_buffer_levels + ~output_buffer_size + ~nb_transactions:conf.nb_transactions + ~tree_depth + ~tree_branching_factor:2 + in + pvm_state := Some res ; + res + in + (* Select an output. *) + let* output = + select_output + ~output_buffer + ~nb_output_buffer_levels + ~output_buffer_size + rng_state + in + (* Produce an output proof, and return its encoding and the length of the + encoding. *) + let*! pf = Full_Wasm.produce_output_proof context initial_tree output in + match pf with + | Ok proof -> + let encoded_proof = + Data_encoding.Binary.to_bytes_exn + Full_Wasm.output_proof_encoding + proof + in + let proof_length = Bytes.length encoded_proof in + return (encoded_proof, proof_length) + | Error _ -> assert false + in + + let encoded_proof, proof_length = + prepared_benchmark_scenario |> Lwt_main.run + |> WithExceptions.Result.get_ok ~loc:__LOC__ + in + let workload = {proof_length} in + + let closure () = + ignore + (Data_encoding.Binary.of_bytes_exn + Full_Wasm.output_proof_encoding + encoded_proof) + in + Generator.Plain {workload; closure} +end + +(** This benchmark estimates the cost of installing a boot sector. *) +module Sc_rollup_install_boot_sector_benchmark = struct + open Pvm_state_generator + module Full_Wasm = + Sc_rollup_wasm.V2_0_0.Make (Environment.Wasm_2_0_0.Make) (Wasm_context) + + (* Benchmark starts here. *) + + let name = ns "Sc_rollup_install_boot_sector_benchmark" + + let group = Benchmarks_proto.Benchmark.Group "sc_rollup" + + let info = "Estimating the cost of installing a boot sector." + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "sc_rollup" + + let tags = ["sc_rollup"] + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = {boot_sector_length : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {boot_sector_length} -> boot_sector_length) + (fun boot_sector_length -> {boot_sector_length}) + (obj1 (req "boot_sector_length" int31)) + + let workload_to_vector {boot_sector_length} = + Sparse_vec.String.of_list + [("boot_sector_length", float_of_int boot_sector_length)] + + let model = + let open Benchmarks_proto in + Model.make + ~conv:(fun {boot_sector_length} -> (boot_sector_length, ())) + Model.affine + + let create_benchmark ~rng_state _conf = + let open Base_samplers in + let max_boot_sector_size = 32 * 1024 in + let boot_sector_length = + sample_in_interval ~range:(0 -- (max_boot_sector_size - 1)) rng_state + in + let workload = {boot_sector_length} in + let boot_sector = uniform_string ~nbytes:boot_sector_length rng_state in + let state = empty_tree in + + let closure () = ignore (Full_Wasm.install_boot_sector state boot_sector) in + Generator.Plain {workload; closure} +end + +let () = + Benchmarks_proto.Registration.register + (module Sc_rollup_verify_output_proof_benchmark) + +let () = + Benchmarks_proto.Registration.register + (module Sc_rollup_deserialize_output_proof_benchmark) + +let () = + Benchmarks_proto.Registration.register + (module Sc_rollup_install_boot_sector_benchmark) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/script_repr_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/script_repr_benchmarks.ml new file mode 100644 index 000000000000..95cc1621b5e0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/script_repr_benchmarks.ml @@ -0,0 +1,139 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Benchmarks_proto + +let ns = Namespace.make Registration.ns "script_repr" + +let fv s = Free_variable.of_namespace (ns s) + +(** {2 [Script_repr] benchmarks} *) + +module Script_repr_shared_config = struct + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = {micheline_nodes : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {micheline_nodes} -> micheline_nodes) + (fun micheline_nodes -> {micheline_nodes}) + (obj1 (req "micheline_nodes" int31)) + + let tags = [Tags.translator] + + let workload_to_vector {micheline_nodes} = + Sparse_vec.String.of_list [("nodes", float_of_int micheline_nodes)] +end + +module Sampler = Micheline_sampler.Make (struct + type prim = Michelson_v1_primitives.prim + + (* The runtime of the functions in [Script_repr] do not depend on the primitives. *) + let sample_prim : Michelson_v1_primitives.prim Base_samplers.sampler = + fun _rng_state -> I_ADD + + let sample_annots : string list Base_samplers.sampler = fun _rng_state -> [] + + let sample_string = Base_samplers.uniform_string ~nbytes:4 + + let sample_bytes = Base_samplers.uniform_bytes ~nbytes:4 + + let sample_z = Base_samplers.int ~size:{min = 1; max = 8} + + let width_function = Micheline_sampler.reasonable_width_function +end) + +module Micheline_nodes_benchmark : Benchmark.S = struct + include Script_repr_shared_config + + let name = ns "MICHELINE_NODES" + + let info = + "Benchmarking the time it takes to compute the number of nodes of a \ + Micheline term" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_repr" + + let group = Benchmark.Group "size_translator_model" + + let model = + Model.make + ~conv:(function {micheline_nodes} -> (micheline_nodes, ())) + (Model.affine + ~intercept:(fv (Format.asprintf "%s_const" (Namespace.basename name))) + ~coeff: + (fv + (Format.asprintf "%s_ns_per_node_coeff" (Namespace.basename name)))) + + let micheline_nodes_benchmark node = + let nodes = Script_repr.micheline_nodes node in + let workload = {micheline_nodes = nodes} in + let closure () = ignore (Script_repr.micheline_nodes node) in + Generator.Plain {workload; closure} + + let create_benchmark ~rng_state _cfg = + let term = Sampler.sample rng_state in + micheline_nodes_benchmark term +end + +let () = Registration.register (module Micheline_nodes_benchmark) + +module Script_repr_strip_annotations : Benchmark.S = struct + include Script_repr_shared_config + + let name = ns "strip_annotations" + + let info = "Benchmarking Script_repr.strip_annotations" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_repr" + + let group = Benchmark.Group "strip_annotations_model" + + let model = + Model.( + make + ~conv:(fun {micheline_nodes} -> (micheline_nodes, ())) + (linear ~coeff:(fv "nodes"))) + + let create_benchmark ~rng_state () = + let node = Sampler.sample rng_state in + let closure () = ignore @@ Script_repr.strip_annotations node in + let micheline_nodes = Script_repr.micheline_nodes node in + Generator.Plain {workload = {micheline_nodes}; closure} +end + +let () = Registration.register (module Script_repr_strip_annotations) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/script_typed_ir_size_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/script_typed_ir_size_benchmarks.ml new file mode 100644 index 000000000000..4c47caea5fdf --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/script_typed_ir_size_benchmarks.ml @@ -0,0 +1,305 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Benchmarks_proto + +let ns = Namespace.make Registration.ns "script_typed_ir_size" + +let fv s = Free_variable.of_namespace (ns s) + +(** {2 [Script_typed_ir_size]-related benchmarks} *) + +(** Benchmarking {!Script_typed_ir_size.value_size}. *) + +let local_model_name = "script_typed_ir_size" + +let strict = Script_ir_translator_config.make ~legacy:false () + +module Size_benchmarks_shared_config = struct + include Translator_benchmarks.Config + + type workload = {size : int} + + let workload_encoding : workload Data_encoding.t = + let open Data_encoding in + def "size_encoding" + @@ conv (fun {size} -> size) (fun size -> {size}) (obj1 (req "size" int31)) + + let workload_to_vector {size} = + Sparse_vec.String.of_list [("size", float_of_int size)] + + let tags = [Tags.translator] + + let size_based_model ~name = + let basename = Namespace.basename name in + let intercept_variable = fv (Format.asprintf "%s_const" basename) in + let coeff_variable = fv (Format.asprintf "%s_size_coeff" basename) in + Model.make + ~name + ~conv:(function {size} -> (size, ())) + (Model.affine ~intercept:intercept_variable ~coeff:coeff_variable) +end + +module Value_size_benchmark : Tezos_benchmark.Benchmark.S = struct + include Size_benchmarks_shared_config + + let name = ns "VALUE_SIZE" + + let models = + let model = size_based_model ~name in + [(local_model_name, model)] + + let info = "Benchmarking Script_typed_ir_size.value_size" + + let purpose = Benchmark.Generate_code "script_typed_ir_size" + + let module_filename = __FILE__ + + let value_size_benchmark rng_state (node : Protocol.Script_repr.expr) + (michelson_type : Script_repr.expr) = + let open Lwt_result_syntax in + (* FIXME: cleanup and factorize this code between translator benches and these ones. *) + let open Translator_benchmarks in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ex_ty = Type_helpers.michelson_type_to_ex_ty michelson_type ctxt in + match ex_ty with + | Script_typed_ir.Ex_ty ty -> ( + match + Lwt_main.run + (Script_ir_translator.parse_data + ctxt + ~elab_conf:strict + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ty + (Micheline.root node)) + with + | Error _ | (exception _) -> + bad_data name node michelson_type In_protocol + | Ok (value, _) -> + let open Script_typed_ir_size in + let open Cache_memory_helpers in + let size = Nodes.(to_int (fst (value_size ty value))) in + let workload = {size} in + let closure () = ignore (value_size ty value) in + return (Generator.Plain {workload; closure}))) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let make_bench rng_state cfg () = + let Michelson_mcmc_samplers.{term; typ} = + Michelson_generation.make_data_sampler rng_state cfg.generator_config + in + value_size_benchmark rng_state term typ + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.filter_map + (function + | Michelson_mcmc_samplers.Data {term; typ} -> + Some (fun () -> value_size_benchmark rng_state term typ) + | _ -> None) + terms + | None -> + Format.eprintf "No michelson_terms_file given, generating on-the-fly@." ; + List.repeat bench_num (make_bench rng_state config) +end + +let () = Registration_helpers.register (module Value_size_benchmark) + +(** Benchmarking {!Script_typed_ir_size.ty_size}. *) + +module Type_size_benchmark : Benchmark.S = struct + include Size_benchmarks_shared_config + + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + let name = ns "TYPE_SIZE" + + let info = + "Benchmarking the time it takes to compute Script_typed_ir_size.ty_size" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_typed_ir_size" + + let group = Benchmark.Group local_model_name + + let model = size_based_model + + let type_size_benchmark (Script_typed_ir.Ex_ty ty) = + let open Script_typed_ir_size.Internal_for_tests in + let open Cache_memory_helpers in + let size = Nodes.(to_int (fst (ty_size ty))) in + let workload = {size} in + let closure () = ignore (ty_size ty) in + Generator.Plain {workload; closure} + + let create_benchmark ~rng_state _cfg = + (* The [size] here is a parameter to the random sampler and does not + match the [size] returned by [type_size]. *) + let size = + Base_samplers.sample_in_interval ~range:{min = 1; max = 1000} rng_state + in + let ex_ty = + Michelson_generation.Samplers.Random_type.m_type ~size () rng_state + in + type_size_benchmark ex_ty +end + +let () = Registration.register (module Type_size_benchmark) + +(** Benchmarking {!Script_typed_ir_size.kinstr_size}. *) + +module Kinstr_size_benchmark : Tezos_benchmark.Benchmark.S = struct + include Size_benchmarks_shared_config + + let name = ns "KINSTR_SIZE" + + let models = [(local_model_name, size_based_model ~name)] + + let info = "Benchmarking Script_typed_ir_size.kinstr_size" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_typed_ir_size" + + let kinstr_size_benchmark rng_state (expr : Protocol.Script_repr.expr) + (stack : Script_repr.expr list) = + let open Lwt_result_syntax in + (* FIXME: cleanup and factorize this code between translator benches and these ones. *) + let open Translator_benchmarks in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ex_stack_ty = + Type_helpers.michelson_type_list_to_ex_stack_ty stack ctxt + in + let (Script_ir_translator.Ex_stack_ty bef) = ex_stack_ty in + let node = Micheline.root expr in + match + Lwt_main.run + (Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf:strict + node + bef) + with + | Error _ | (exception _) -> bad_code name expr stack In_protocol + | Ok (Failed {descr}, _) -> + let kdescr = Script_ir_translator.close_descr (descr Bot_t) in + let kinstr = kdescr.kinstr in + let open Script_typed_ir_size.Internal_for_tests in + let workload = + let open Cache_memory_helpers in + {size = Nodes.to_int @@ fst @@ kinstr_size kinstr} + in + let closure () = ignore (kinstr_size kinstr) in + return (Generator.Plain {workload; closure}) + | Ok (Typed descr, _) -> + let kdescr = Script_ir_translator.close_descr descr in + let kinstr = kdescr.kinstr in + let open Script_typed_ir_size.Internal_for_tests in + let workload = + let open Cache_memory_helpers in + {size = Nodes.to_int @@ fst @@ kinstr_size kinstr} + in + let closure () = ignore (kinstr_size kinstr) in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let make_bench rng_state cfg () = + let Michelson_mcmc_samplers.{term; bef; aft = _} = + Michelson_generation.make_code_sampler rng_state cfg.generator_config + in + kinstr_size_benchmark rng_state term bef + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.filter_map + (function + | Michelson_mcmc_samplers.Code {term; bef; aft = _} -> + Some (fun () -> kinstr_size_benchmark rng_state term bef) + | _ -> None) + terms + | None -> + Format.eprintf "No michelson_terms_file given, generating on-the-fly@." ; + List.repeat bench_num (make_bench rng_state config) +end + +let () = Registration_helpers.register (module Kinstr_size_benchmark) + +module Node_size_benchmark : Benchmark.S = struct + include Script_repr_benchmarks.Script_repr_shared_config + + let name = ns "NODE_SIZE" + + let info = + "Benchmarking the time it takes to compute Script_typed_ir_size.node_size" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "script_typed_ir_size" + + let group = Benchmark.Group local_model_name + + let model = + Model.make + ~conv:(function {micheline_nodes} -> (micheline_nodes, ())) + (Model.affine + ~intercept:(fv (Format.asprintf "%s_const" (Namespace.basename name))) + ~coeff: + (fv + (Format.asprintf "%s_ns_per_node_coeff" (Namespace.basename name)))) + + let micheline_nodes_benchmark node = + let open Cache_memory_helpers in + let nodes = Nodes.to_int @@ fst @@ node_size node in + let workload = {micheline_nodes = nodes} in + let closure () = ignore (Script_typed_ir_size.node_size node) in + Generator.Plain {workload; closure} + + let create_benchmark ~rng_state _cfg = + let term = Script_repr_benchmarks.Sampler.sample rng_state in + micheline_nodes_benchmark term +end + +let () = Registration.register (module Node_size_benchmark) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/skip_list_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/skip_list_benchmarks.ml new file mode 100644 index 000000000000..3c802550f70d --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/skip_list_benchmarks.ml @@ -0,0 +1,188 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides benchmarks for skip list operations for basis = 4. *) + +open Protocol +open Benchmarks_proto + +module Skip_list = Skip_list.Make (struct + (** The benchmarks must be run again if [basis] is changed. *) + let basis = 4 +end) + +let ns = Namespace.make Registration.ns "skip_list" + +let fv s = Free_variable.of_namespace (ns s) + +(** Benchmark for the [Skip_list_repr.next] function. It is used for estimating + the parameters for [Skip_list_cost_model.model_next]. *) +module Next : Benchmark.S = struct + let purpose = Benchmark.Generate_code "skip_list" + + include Skip_list + + let name = ns "next" + + let info = "Benchmark for Skip_list_repr.next" + + let tags = ["skip_list"] + + type config = {max_items : int} + + let default_config = {max_items = 10000} + + let module_filename = __FILE__ + + let group = Benchmark.Group "skip_list" + + let config_encoding = + let open Data_encoding in + conv (fun {max_items} -> max_items) (fun max_items -> {max_items}) int31 + + type workload = int + + let workload_encoding = Data_encoding.int31 + + let workload_to_vector len = + Sparse_vec.String.of_list [("len", float_of_int @@ len)] + + let model = + Model.make ~conv:(fun x -> (x, ())) Model.logn ~takes_saturation_reprs:true + + let create_skip_list_of_len len = + let rec go n cell = + if n = 0 then cell + else go (pred n) @@ next ~prev_cell:cell ~prev_cell_ptr:() () + in + go len (genesis ()) + + let create_benchmark ~rng_state ({max_items} : config) = + let workload = + (* Since the model we want to infer is logarithmic in + the length, we sample the logarithm of the length + (and not the length itself) uniformly in an interval. *) + let logmax = log (float_of_int max_items) in + let loglen = + Base_samplers.sample_float_in_interval ~min:0. ~max:logmax rng_state + in + int_of_float (exp loglen) + in + let prev_cell = create_skip_list_of_len workload in + let prev_cell_ptr = () in + let closure () = ignore (next ~prev_cell ~prev_cell_ptr ()) in + Generator.Plain {workload; closure} +end + +(** Benchmark for the [Sc_rollup_inbox_repr.hash_skip_list_cell] + function. It is used for estimating the parameters for + [Skip_list_cost_model.model_hash_cell]. The model estimates hashing + a skip_list cell content and all its back pointers. *) +module Hash_cell : Benchmark.S = struct + let purpose = Benchmark.Generate_code "skip_list" + + let name = ns "hash_cell" + + let info = "Estimating the costs of hashing a skip list cell" + + let tags = ["skip_list"] + + let module_filename = __FILE__ + + let group = Benchmark.Group "skip_list" + + include Skip_list + module Hash = Sc_rollup_inbox_repr.Hash + + let hash merkelized = + let payload_hash = Skip_list.content merkelized in + let back_pointers_hashes = Skip_list.back_pointers merkelized in + Hash.to_bytes payload_hash :: List.map Hash.to_bytes back_pointers_hashes + |> Hash.hash_bytes + + type config = {max_index : int} + + let config_encoding = + let open Data_encoding in + conv + (fun {max_index} -> max_index) + (fun max_index -> {max_index}) + (obj1 (req "max_index" int31)) + + let default_config = {max_index = 65536} + + type workload = {nb_backpointers : int} + + let workload_encoding = + let open Data_encoding in + conv + (fun {nb_backpointers} -> nb_backpointers) + (fun nb_backpointers -> {nb_backpointers}) + (obj1 (req "max_nb_backpointers" int31)) + + let workload_to_vector {nb_backpointers} = + Sparse_vec.String.of_list + [("nb_backpointers", float_of_int nb_backpointers)] + + let model = + Model.make + ~takes_saturation_reprs:true + ~conv:(fun {nb_backpointers} -> (nb_backpointers, ())) + Model.affine + + let create_benchmark ~rng_state conf = + (* Since the model we want to infer is logarithmic in + the length, we sample the logarithm of the length + (and not the length itself) uniformly in an interval. *) + let skip_list_loglen = + let logmax = log (float_of_int conf.max_index) in + Base_samplers.sample_float_in_interval ~min:0. ~max:logmax rng_state + in + let skip_list_len = int_of_float (exp skip_list_loglen) in + let random_hash () = + Hash.hash_string + [Base_samplers.string ~size:{min = 32; max = 32} rng_state] + in + let cell = + let rec repeat n cell = + if n = 0 then cell + else + let prev_cell = cell and prev_cell_ptr = hash cell in + repeat + (n - 1) + (Skip_list.next ~prev_cell ~prev_cell_ptr (random_hash ())) + in + repeat skip_list_len (Skip_list.genesis (random_hash ())) + in + let nb_backpointers = List.length (Skip_list.back_pointers cell) in + let workload = {nb_backpointers} in + let closure () = ignore (hash cell) in + Generator.Plain {workload; closure} +end + +let () = Registration.register (module Next) + +let () = Registration.register (module Hash_cell) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/storage_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/storage_benchmarks.ml new file mode 100644 index 000000000000..20c151605222 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/storage_benchmarks.ml @@ -0,0 +1,253 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {2 [Storage_functors] benchmarks} + + This module registers a benchmark [List_key_values_benchmark]. Its result + is used to fill in the corresponding value, [list_key_values_step] + defined in [Storage_costs]. + *) + +open Tezos_benchmark +open Benchmarks_proto +open Storage_functors +open Protocol + +let ns = Namespace.make Registration_helpers.ns "storage" + +let fv s = Free_variable.of_namespace (ns s) + +(** Creates a dummy raw-context value. *) +let default_raw_context () = + let open Lwt_result_syntax in + let initial_account = Account.new_account () in + let bootstrap_account = + Account.make_bootstrap_account + ~balance:(Alpha_context.Tez.of_mutez_exn 100_000_000_000L) + initial_account + in + let* constants, _, _ = Block.prepare_initial_context_params () in + let parameters = + Default_parameters.parameters_of_constants + ~bootstrap_accounts:[bootstrap_account] + ~commitments:[] + constants + in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + let protocol_param_key = ["protocol_parameters"] in + let*! context = + Tezos_protocol_environment.Context.( + let empty = Tezos_protocol_environment.Memory_context.empty in + let*! ctxt = add empty ["version"] (Bytes.of_string "genesis") in + add ctxt protocol_param_key proto_params) + in + let typecheck_smart_contract ctxt script_repr = + return ((script_repr, None), ctxt) + in + let typecheck_smart_rollup ctxt _script_repr = Result_syntax.return ctxt in + + let*! e = + Init_storage.prepare_first_block + Chain_id.zero + context + ~level:0l + ~timestamp:(Time.Protocol.of_seconds 1643125688L) + ~predecessor:Block_hash.zero + ~typecheck_smart_contract + ~typecheck_smart_rollup + in + Lwt.return (Environment.wrap_tzresult e) + +module String = struct + type t = string + + let encoding = Data_encoding.string +end + +module Int32 = struct + type t = int32 + + let encoding = Data_encoding.int32 + + module Index = struct + type t = int + + let path_length = 1 + + let to_path c l = string_of_int c :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [c] -> int_of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } + end +end + +module Root_raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["benchmark_storage_functors"] + end) + +module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Root_raw_context) + (struct + let name = ["index"] + end)) + (Int32.Index) + +module Table = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["table_for_list_key_values"] + end)) + (Int32.Index) + (struct + type t = string + + let encoding = Data_encoding.string + end) + +module List_key_values_benchmark_boilerplate = struct + type config = {max_size : int} + + let name = ns "List_key_values" + + let info = "List key values" + + let config_encoding = + let open Data_encoding in + conv + (fun {max_size} -> max_size) + (fun max_size -> {max_size}) + (obj1 (req "max_size" int31)) + + let default_config = {max_size = 100_000} + + type workload = {size : int} + + let tags = ["big_map"] + + let workload_encoding = + let open Data_encoding in + conv (fun {size} -> size) (fun size -> {size}) (obj1 (req "size" int31)) + + let workload_to_vector {size} = + Sparse_vec.String.of_list [("size", float_of_int size)] + + let group = Benchmark.Group "storage_costs" + + let model = + Model.make + ~conv:(fun {size} -> (size, ())) + (Model.affine + ~intercept:(fv "list_key_values_intercept") + ~coeff:(fv "list_key_values_step")) +end + +module List_key_values_benchmark = struct + include List_key_values_benchmark_boilerplate + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "storage" + + let create_benchmark ~rng_state {max_size} = + let open Lwt_result_syntax in + let wrap m = + let*! result = m in + Lwt.return (Environment.wrap_tzresult result) + in + let size = + Base_samplers.sample_in_interval + ~range:{min = 1; max = max_size} + rng_state + in + let ctxt = + let fill_table = + let open Lwt_result_syntax in + let* ctxt = default_raw_context () in + List.fold_left_es + (fun ctxt (key, value) -> + let* ctxt, _, _ = wrap @@ Table.add ctxt key value in + return ctxt) + ctxt + (Stdlib.List.init size (fun key -> (key, string_of_int key))) + in + match Lwt_main.run fill_table with Ok ctxt -> ctxt | _ -> assert false + in + let workload = {size} in + let closure () = + (* We pass length [0] so that none of the steps of the fold over the + key-value pairs load any values. That is isolate the cost of iterating + over the tree without loading values. *) + Table.list_key_values ~length:0 ctxt |> Lwt_main.run |> ignore + in + Generator.Plain {workload; closure} +end + +module List_key_values_benchmark_intercept = struct + include List_key_values_benchmark_boilerplate + + let name = Namespace.make ns (Namespace.basename name) "intercept" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "storage" + + let create_benchmark ~rng_state:_ _config = + let ctxt = + match Lwt_main.run (default_raw_context ()) with + | Ok ctxt -> ctxt + | _ -> assert false + in + let workload = {size = 0} in + let closure () = + (* We pass length [0] so that none of the steps of the fold over the + key-value pairs load any values. That is isolate the cost of iterating + over the tree without loading values. *) + Table.list_key_values ~length:0 ctxt |> Lwt_main.run |> ignore + in + Generator.Plain {workload; closure} +end + +let () = Registration.register (module List_key_values_benchmark) + +let () = Registration.register (module List_key_values_benchmark_intercept) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/tags.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/tags.ml new file mode 100644 index 000000000000..e5aca30e639a --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/tags.ml @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let interpreter = "interpreter" + +let translator = "translator" + +let encoding = "encoding" + +let cache = "cache" + +let common = Protocol.name diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/ticket_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/ticket_benchmarks.ml new file mode 100644 index 000000000000..ae9c472dd3b7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/ticket_benchmarks.ml @@ -0,0 +1,293 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Benchmarks_proto +open Alpha_context + +let ns = Namespace.make Registration.ns "tickets" + +let fv s = Free_variable.of_namespace (ns s) + +module Ticket_type_shared = struct + type config = {max_size : int} + + let default_config = {max_size = Constants_repr.michelson_maximum_type_size} + + let config_encoding = + let open Data_encoding in + conv + (fun {max_size} -> max_size) + (fun max_size -> {max_size}) + (obj1 (req "max_size" int31)) + + type workload = {nodes : int} + + let workload_encoding = + let open Data_encoding in + conv + (function {nodes} -> nodes) + (fun nodes -> {nodes}) + (obj1 (req "nodes" int31)) + + let workload_to_vector {nodes} = + Sparse_vec.String.of_list [("nodes", float_of_int nodes)] + + let tags = ["tickets"] +end + +exception + Ticket_benchmark_error of { + benchmark_name : Namespace.t; + trace : Tezos_base.TzPervasives.tztrace; + } + +(** A benchmark for {!Ticket_costs.Constants.cost_compare_ticket_hash}. *) +module Compare_ticket_hash_benchmark : Benchmark.S = struct + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = unit + + let tags = ["tickets"] + + let workload_encoding = Data_encoding.unit + + let workload_to_vector () = Sparse_vec.String.of_list [] + + let name = ns "COMPARE_TICKET_HASH" + + let info = "Compare cost for Ticket_hash" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "ticket" + + let group = Benchmark.Group "tickets" + + let model = + Model.make + ~conv:(fun () -> ()) + (Model.unknown_const1 ~const:(fv "compare_ticket_hash")) + + let create_benchmark ~rng_state _conf = + let bytes = Base_samplers.bytes rng_state ~size:{min = 1; max = 64} in + let hash = + Ticket_hash.of_script_expr_hash @@ Script_expr_hash.hash_bytes [bytes] + in + let hash2 = + Ticket_hash.of_script_expr_hash @@ Script_expr_hash.hash_bytes [bytes] + in + let workload = () in + let closure () = ignore (Ticket_hash.compare hash hash2) in + Generator.Plain {workload; closure} +end + +let () = Registration.register (module Compare_ticket_hash_benchmark) + +(** A benchmark for {!Ticket_costs.Constants.cost_compare_key_contract}. + + In this benchmark we only compare originated contracts; we never use + implicit contracts. This is justified partly by the fact that + currently the carbonated maps only use originated contracts as keys. + In addition, while developing this benchmark the implicit contracts were + also tested and gave almost identical timings. *) +module Compare_key_contract_benchmark : Benchmark.S = struct + type config = unit + + let config_encoding = Data_encoding.unit + + let default_config = () + + type workload = unit + + let workload_encoding = Data_encoding.unit + + let workload_to_vector () = Sparse_vec.String.of_list [] + + let tags = ["tickets"] + + let name = ns "COMPARE_CONTRACT" + + let info = "Compare cost for Contracts" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "ticket" + + let group = Benchmark.Group "tickets" + + let model = + Model.make + ~conv:(fun () -> ()) + (Model.unknown_const1 ~const:(fv "compare_contract")) + + let create_benchmark ~rng_state _conf = + let bytes = Base_samplers.bytes rng_state ~size:{min = 32; max = 64} in + let branch = Block_hash.hash_bytes [bytes] in + let op_hash = Operation.hash_raw {shell = {branch}; proto = bytes} in + let nonce = Origination_nonce.Internal_for_tests.initial op_hash in + let contract = Contract.Internal_for_tests.originated_contract nonce in + let contract2 = Contract.Internal_for_tests.originated_contract nonce in + let workload = () in + let closure () = ignore (Contract.compare contract contract2) in + Generator.Plain {workload; closure} +end + +let () = Registration.register (module Compare_key_contract_benchmark) + +(* A simple ticket type for use in the benchmarks. *) +let ticket_ty = + let open Script_typed_ir in + WithExceptions.Result.get_ok ~loc:__LOC__ (ticket_t (-1) int_t) + +(* A dummy type generator, sampling linear terms of a given size. + The generator always returns types of the shape: + + [pair int_or_ticket (pair int_or_ticket (pair int_or_ticket ...))] + + This is a worst case type for [type_has_tickets], though nested + ors, nested maps or nested lists would be just as bad. *) +let rec dummy_type_generator ~rng_state size = + let open Script_typed_ir in + let ticket_or_int = + if Base_samplers.uniform_bool rng_state then Ex_ty ticket_ty + else Ex_ty int_t + in + if size <= 1 then ticket_or_int + else + match (ticket_or_int, dummy_type_generator ~rng_state (size - 3)) with + | Ex_ty l, Ex_ty r -> ( + match pair_t (-1) l r with + | Error _ -> assert false + | Ok (Ty_ex_c t) -> Ex_ty t) + +(** A benchmark for {!Ticket_costs.Constants.cost_has_tickets_of_ty}. *) +module Has_tickets_type_benchmark : Benchmark.S = struct + include Ticket_type_shared + + let name = ns "TYPE_HAS_TICKETS" + + let info = "Benchmarking type_has_tickets" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "ticket" + + let group = Benchmark.Group "tickets" + + let make_bench_helper rng_state config () = + let open Result_syntax in + let* ctxt, _ = Lwt_main.run (Execution_context.make ~rng_state ()) in + let ctxt = Gas_helpers.set_limit ctxt in + let size = Random.State.int rng_state config.max_size in + let (Ex_ty ty) = dummy_type_generator ~rng_state size in + let nodes = + let size = Script_typed_ir.ty_size ty in + Saturation_repr.to_int @@ Script_typed_ir.Type_size.to_int size + in + let workload = {nodes} in + let closure () = ignore (Ticket_scanner.type_has_tickets ctxt ty) in + return (Generator.Plain {workload; closure}) + + let create_benchmark ~rng_state config = + match make_bench_helper rng_state config () with + | Ok closure -> closure + | Error trace -> + raise (Ticket_benchmark_error {benchmark_name = name; trace}) + + let model = + Model.make + ~takes_saturation_reprs:true + ~conv:(function {nodes} -> (nodes, ())) + Model.affine +end + +let () = Registration.register (module Has_tickets_type_benchmark) + +let ticket_sampler rng_state = + let seed = Base_samplers.uniform_bytes ~nbytes:32 rng_state in + let pkh, _, _ = Signature.generate_key ~algo:Signature.Ed25519 ~seed () in + let ticketer = Alpha_context.Contract.Implicit pkh in + Script_typed_ir. + {ticketer; contents = Script_int.zero; amount = Ticket_amount.one} + +(** A benchmark for {!Ticket_costs.Constants.cost_collect_tickets_step}. *) +module Collect_tickets_benchmark : Benchmark.S = struct + include Ticket_type_shared + + let name = ns "COLLECT_TICKETS_STEP" + + let info = "Benchmarking tickets_of_value" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "ticket" + + let group = Benchmark.Group "tickets" + + let make_bench_helper rng_state config () = + let open Script_typed_ir in + let open Result_syntax in + let* ctxt, _ = Lwt_main.run (Execution_context.make ~rng_state ()) in + let ctxt = Gas_helpers.set_limit ctxt in + let ty = + match list_t (-1) ticket_ty with Error _ -> assert false | Ok t -> t + in + let _, elements = + Structure_samplers.list + ~range:{min = 0; max = config.max_size} + ~sampler:ticket_sampler + rng_state + in + let boxed_ticket_list = Script_list.of_list elements in + Environment.wrap_tzresult + @@ let* has_tickets, ctxt = Ticket_scanner.type_has_tickets ctxt ty in + let workload = {nodes = Script_list.length boxed_ticket_list} in + let closure () = + ignore + (Lwt_main.run + (Ticket_scanner.tickets_of_value + ctxt + ~include_lazy:true + has_tickets + boxed_ticket_list)) + in + return (Generator.Plain {workload; closure}) + + let create_benchmark ~rng_state config = + match make_bench_helper rng_state config () with + | Ok closure -> closure + | Error trace -> + raise (Ticket_benchmark_error {benchmark_name = name; trace}) + + let model = Model.make ~conv:(function {nodes} -> (nodes, ())) Model.affine +end + +let () = Registration.register (module Collect_tickets_benchmark) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/translator_benchmarks.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/translator_benchmarks.ml new file mode 100644 index 000000000000..1151346729b5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/translator_benchmarks.ml @@ -0,0 +1,833 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +module Encodings = +Tezos_shell_benchmarks.Encoding_benchmarks_helpers.Make (struct + let file = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" +end) + +let group = Benchmark.Group "script_ir_translator" + +module Size = Gas_input_size + +let ns = Translator_model.ns + +let fv = Translator_model.fv + +(** {2 [Script_ir_translator] benchmarks} *) + +module Config = struct + type config = { + generator_config : Michelson_generation.generator_config; + michelson_terms_file : string option; + } + + let default_config = + { + generator_config = Michelson_generation.default_generator_config; + michelson_terms_file = None; + } + + let config_encoding = + let open Data_encoding in + conv + (fun {generator_config; michelson_terms_file} -> + (generator_config, michelson_terms_file)) + (fun (generator_config, michelson_terms_file) -> + {generator_config; michelson_terms_file}) + (obj2 + (req "generator_config" Michelson_generation.generator_config_encoding) + (req "michelson_terms_file" (option string))) +end + +module Default_boilerplate = struct + type workload = Translator_workload.t + + let workload_encoding = Translator_workload.encoding + + let workload_to_vector = Translator_workload.workload_to_sparse_vec + + let tags = [Tags.translator] + + let make_models t_kind code_or_data = + [ + ("gas_model", Translator_model.gas_based_model t_kind code_or_data); + ("size_model", Translator_model.size_based_model t_kind code_or_data); + ] +end + +(* ----------------------------------------------------------------------- *) +(* Error handling *) + +type phase = Workload_production | In_protocol | Global + +type error_kind = + | Global_error of { + benchmark_name : Namespace.t; + workload : Tezos_base.TzPervasives.tztrace; + } + | Bad_data of { + benchmark_name : Namespace.t; + micheline : Alpha_context.Script.expr; + expected_type : Alpha_context.Script.expr; + phase : phase; + } + | Bad_code of { + benchmark_name : Namespace.t; + micheline : Alpha_context.Script.expr; + expected_stack_type : Alpha_context.Script.expr list; + phase : phase; + } + +let pp_phase fmtr (phase : phase) = + match phase with + | Workload_production -> Format.fprintf fmtr "workload production" + | In_protocol -> Format.fprintf fmtr "in protocol" + | Global -> Format.fprintf fmtr "global" + +let report_michelson_errors fmtr errs = + Michelson_v1_error_reporter.report_errors + ~details:true + ~show_source:true + fmtr + errs + +let make_printable node = + Micheline_printer.printable Michelson_v1_primitives.string_of_prim node + +let pp_error_kind fmtr (error_kind : error_kind) = + match error_kind with + | Global_error {benchmark_name; workload} -> + Format.open_vbox 1 ; + Format.fprintf fmtr "Global error:@," ; + Format.fprintf fmtr "benchmark = %a@," Namespace.pp benchmark_name ; + Format.fprintf fmtr "workload:@," ; + report_michelson_errors fmtr workload ; + Format.close_box () + | Bad_data {benchmark_name; micheline; expected_type; phase} -> + Format.open_vbox 1 ; + Format.fprintf fmtr "Bad data:@," ; + Format.fprintf fmtr "benchmark = %a@," Namespace.pp benchmark_name ; + Format.fprintf + fmtr + "expression = @[%a@]@," + Micheline_printer.print_expr + (make_printable micheline) ; + Format.fprintf + fmtr + "expected type = @[%a@]@," + Micheline_printer.print_expr + (make_printable expected_type) ; + Format.fprintf fmtr "phase = %a@," pp_phase phase ; + Format.close_box () + | Bad_code {benchmark_name; micheline; expected_stack_type; phase} -> + Format.open_vbox 1 ; + Format.fprintf fmtr "Bad code:@," ; + Format.fprintf fmtr "benchmark = %a@," Namespace.pp benchmark_name ; + Format.fprintf + fmtr + "expression = @[%a@]@," + Micheline_printer.print_expr + (make_printable micheline) ; + Format.fprintf + fmtr + "expected stack = @[%a@]@," + (Format.pp_print_list + ~pp_sep:(fun fmtr () -> Format.fprintf fmtr "::") + (fun fmtr node -> + let printable = make_printable node in + Format.fprintf fmtr "%a" Micheline_printer.print_expr printable)) + expected_stack_type ; + Format.fprintf fmtr "phase = %a@," pp_phase phase ; + Format.close_box () + +exception Translator_benchmark_error of error_kind + +let () = + Printexc.register_printer (function + | Translator_benchmark_error err -> + Some (Format.asprintf "%a" pp_error_kind err) + | _ -> None) + +let global_error benchmark_name workload = + raise (Translator_benchmark_error (Global_error {benchmark_name; workload})) + +let bad_data benchmark_name micheline expected_type phase = + raise + (Translator_benchmark_error + (Bad_data {benchmark_name; micheline; expected_type; phase})) + +let bad_code benchmark_name micheline expected_stack_type phase = + raise + (Translator_benchmark_error + (Bad_code {benchmark_name; micheline; expected_stack_type; phase})) + +(* ----------------------------------------------------------------------- *) +(* Typechecking data (Micheline data -> typed data) *) + +let strict = Script_ir_translator_config.make ~legacy:false () + +module Typechecking_data : Benchmark.S = struct + include Config + include Default_boilerplate + + let models = make_models Translator_workload.Parsing Translator_workload.Data + + let name = ns "TYPECHECKING_DATA" + + let info = "Benchmarking typechecking of data" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let typechecking_data_benchmark rng_state (node : Protocol.Script_repr.expr) + (michelson_type : Script_repr.expr) = + let open Lwt_result_syntax in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ex_ty = Type_helpers.michelson_type_to_ex_ty michelson_type ctxt in + let workload = + match + Translator_workload.data_typechecker_workload + ctxt + Translator_workload.Parsing + (Micheline.root node) + ex_ty + with + | None -> bad_data name node michelson_type Workload_production + | Some workload -> workload + in + match ex_ty with + | Script_typed_ir.Ex_ty ty -> + let closure () = + match + Lwt_main.run + (Script_ir_translator.parse_data + ctxt + ~elab_conf:strict + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ty + (Micheline.root node)) + with + | Error _ | (exception _) -> + bad_data name node michelson_type In_protocol + | Ok _ -> () + in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let make_bench rng_state cfg () = + let Michelson_mcmc_samplers.{term; typ} = + Michelson_generation.make_data_sampler rng_state cfg.generator_config + in + typechecking_data_benchmark rng_state term typ + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.filter_map + (function + | Michelson_mcmc_samplers.Data {term; typ} -> + Some (fun () -> typechecking_data_benchmark rng_state term typ) + | _ -> None) + terms + | None -> + Format.eprintf "No michelson_terms_file given, generating on-the-fly@." ; + List.repeat bench_num (make_bench rng_state config) +end + +let () = + Benchmarks_proto.Registration.register_as_simple_with_num + ~group + (module Typechecking_data) + +module Unparsing_data : Benchmark.S = struct + include Config + include Default_boilerplate + + let models = + make_models Translator_workload.Unparsing Translator_workload.Data + + let name = ns "UNPARSING_DATA" + + let info = "Benchmarking unparsing of data" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let unparsing_data_benchmark rng_state (node : Protocol.Script_repr.expr) + (michelson_type : Protocol.Script_repr.expr) = + let open Lwt_result_syntax in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ex_ty = Type_helpers.michelson_type_to_ex_ty michelson_type ctxt in + let workload = + match + Translator_workload.data_typechecker_workload + ctxt + Translator_workload.Unparsing + (Micheline.root node) + ex_ty + with + | None -> bad_data name node michelson_type Workload_production + | Some workload -> workload + in + match ex_ty with + | Script_typed_ir.Ex_ty ty -> + let* typed, ctxt = + let*! result = + Script_ir_translator.parse_data + ctxt + ~elab_conf:strict + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ty + (Micheline.root node) + in + Lwt.return (Environment.wrap_tzresult result) + in + let closure () = + match + Lwt_main.run + (Script_ir_translator.Internal_for_benchmarking.unparse_data + ~stack_depth:0 + ctxt + Script_ir_unparser.Optimized + ty + typed) + with + | Error _ | (exception _) -> + bad_data name node michelson_type In_protocol + | Ok _ -> () + in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let make_bench rng_state cfg () = + let Michelson_mcmc_samplers.{term; typ} = + Michelson_generation.make_data_sampler rng_state cfg.generator_config + in + unparsing_data_benchmark rng_state term typ + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.filter_map + (function + | Michelson_mcmc_samplers.Data {term; typ} -> + Some (fun () -> unparsing_data_benchmark rng_state term typ) + | _ -> None) + terms + | None -> + Format.eprintf "No michelson_terms_file given, generating on-the-fly@." ; + List.repeat bench_num (make_bench rng_state config) +end + +let () = + Benchmarks_proto.Registration.register_as_simple_with_num + ~group + (module Unparsing_data) + +module Typechecking_code : Benchmark.S = struct + include Config + include Default_boilerplate + + let models = make_models Translator_workload.Parsing Translator_workload.Code + + let name = ns "TYPECHECKING_CODE" + + let info = "Benchmarking typechecking of code" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let typechecking_code_benchmark rng_state (node : Protocol.Script_repr.expr) + (stack : Script_repr.expr list) = + let open Lwt_result_syntax in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ex_stack_ty = + Type_helpers.michelson_type_list_to_ex_stack_ty stack ctxt + in + let workload = + match + Translator_workload.code_typechecker_workload + ctxt + Translator_workload.Parsing + (Micheline.root node) + ex_stack_ty + with + | None -> bad_code name node stack Workload_production + | Some workload -> workload + in + let (Script_ir_translator.Ex_stack_ty bef) = ex_stack_ty in + let closure () = + let result = + Lwt_main.run + (Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf:strict + (Micheline.root node) + bef) + in + match Environment.wrap_tzresult result with + | Error errs -> + Format.eprintf "%a@." Error_monad.pp_print_trace errs ; + bad_code name node stack In_protocol + | Ok _ -> () + in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let make_bench rng_state (cfg : Config.config) () = + let open Michelson_generation in + let Michelson_mcmc_samplers.{term; bef; aft = _} = + make_code_sampler rng_state cfg.generator_config + in + typechecking_code_benchmark rng_state term bef + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.filter_map + (function + | Michelson_mcmc_samplers.Code {term; bef; aft = _} -> + Some (fun () -> typechecking_code_benchmark rng_state term bef) + | _ -> None) + terms + | None -> + Format.eprintf "No michelson_terms_file given, generating on-the-fly@." ; + List.repeat bench_num (make_bench rng_state config) +end + +let () = + Benchmarks_proto.Registration.register_as_simple_with_num + ~group + (module Typechecking_code) + +module Unparsing_code : Benchmark.S = struct + include Config + include Default_boilerplate + + let models = + make_models Translator_workload.Unparsing Translator_workload.Code + + let name = ns "UNPARSING_CODE" + + let info = "Benchmarking unparsing of code" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let unparsing_code_benchmark rng_state (node : Protocol.Script_repr.expr) + (stack : Script_repr.expr list) = + let open Lwt_result_syntax in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ex_stack_ty = + Type_helpers.michelson_type_list_to_ex_stack_ty stack ctxt + in + let workload = + match + Translator_workload.code_typechecker_workload + ctxt + Translator_workload.Unparsing + (Micheline.root node) + ex_stack_ty + with + | None -> bad_code name node stack Workload_production + | Some workload -> workload + in + let (Script_ir_translator.Ex_stack_ty bef) = ex_stack_ty in + (* We parse the code just to check it is well-typed. *) + let* _typed, ctxt = + let*! result = + Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf:strict + (Micheline.root node) + bef + in + Lwt.return (Environment.wrap_tzresult result) + in + let closure () = + let result = + Lwt_main.run + (Script_ir_translator.Internal_for_benchmarking.unparse_code + ~stack_depth:0 + ctxt + Optimized + (Micheline.root node)) + in + match Environment.wrap_tzresult result with + | Error errs -> + Format.eprintf "%a@." Error_monad.pp_print_trace errs ; + bad_code name node stack In_protocol + | Ok _ -> () + in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let make_bench rng_state (cfg : Config.config) () = + let open Michelson_generation in + let Michelson_mcmc_samplers.{term; bef; aft = _} = + make_code_sampler rng_state cfg.generator_config + in + unparsing_code_benchmark rng_state term bef + + let create_benchmarks ~rng_state ~bench_num config = + match config.michelson_terms_file with + | Some file -> + Format.eprintf "Loading terms from %s@." file ; + let terms = Michelson_mcmc_samplers.load ~filename:file in + List.filter_map + (function + | Michelson_mcmc_samplers.Code {term; bef; aft = _} -> + Some (fun () -> unparsing_code_benchmark rng_state term bef) + | _ -> None) + terms + | None -> List.repeat bench_num (make_bench rng_state config) +end + +let () = + Benchmarks_proto.Registration.register_as_simple_with_num + ~group + (module Unparsing_code) + +let rec check_printable_ascii v i = + if Compare.Int.(i < 0) then true + else + match v.[i] with + | '\n' | '\x20' .. '\x7E' -> check_printable_ascii v (i - 1) + | _ -> false + +let check_printable_benchmark = + let open Tezos_shell_benchmarks.Encoding_benchmarks_helpers in + let open Encodings in + linear_shared + ~name:"CHECK_PRINTABLE" + ~generator:(fun rng_state -> + let open Base_samplers in + let string = + readable_ascii_string rng_state ~size:{min = 1; max = 1024} + in + (string, {Shared_linear.bytes = String.length string})) + ~make_bench:(fun generator () -> + let generated, workload = generator () in + let closure () = + ignore (check_printable_ascii generated (String.length generated - 1)) + in + Generator.Plain {workload; closure}) + () + +let () = Registration_helpers.register_simple_with_num check_printable_benchmark + +open Benchmarks_proto + +module Ty_eq : Benchmark.S = struct + type config = {max_size : int} + + let config_encoding = + let open Data_encoding in + conv + (fun {max_size} -> max_size) + (fun max_size -> {max_size}) + (obj1 (req "max_size" int31)) + + let default_config = {max_size = 64} + + type workload = Ty_eq_workload of {nodes : int; consumed : Size.t} + + let workload_encoding = + let open Data_encoding in + conv + (function Ty_eq_workload {nodes; consumed} -> (nodes, consumed)) + (fun (nodes, consumed) -> Ty_eq_workload {nodes; consumed}) + (obj2 (req "nodes" int31) (req "consumed" int31)) + + let workload_to_vector = function + | Ty_eq_workload {nodes; consumed} -> + Sparse_vec.String.of_list + [("nodes", float_of_int nodes); ("consumed", float_of_int consumed)] + + let name = ns "TY_EQ" + + let info = "Benchmarking equating types" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let tags = [Tags.translator] + + let group = Benchmark.Group "size_translator_model" + + let model = + Model.make + ~takes_saturation_reprs:true + ~conv:(function Ty_eq_workload {nodes; _} -> (nodes, ())) + Model.affine + + let ty_eq_benchmark rng_state nodes (ty : Script_typed_ir.ex_ty) = + let open Lwt_result_syntax in + Lwt_main.run + (let* ctxt, _ = Execution_context.make ~rng_state () in + let ctxt = Gas_helpers.set_limit ctxt in + match ty with + | Ex_ty ty -> + let dummy_loc = 0 in + let*? _, ctxt' = + Environment.wrap_tzresult + (Gas_monad.run + ctxt + (Script_ir_translator.ty_eq + ~error_details:(Informative dummy_loc) + ty + ty)) + in + let consumed = Alpha_context.Gas.consumed ~since:ctxt ~until:ctxt' in + let workload = + Ty_eq_workload + {nodes; consumed = Z.to_int (Gas_helpers.fp_to_z consumed)} + in + let closure () = + ignore + (Gas_monad.run ctxt + @@ Script_ir_translator.ty_eq + ~error_details:(Informative dummy_loc) + ty + ty) + in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let create_benchmark ~rng_state (cfg : config) = + let nodes = + Base_samplers.( + sample_in_interval ~range:{min = 1; max = cfg.max_size} rng_state) + in + let ty = + Michelson_generation.Samplers.Random_type.m_type ~size:nodes () rng_state + in + ty_eq_benchmark rng_state nodes ty +end + +let () = Registration.register (module Ty_eq) + +(* A dummy type generator, sampling linear terms of a given size. + The generator always returns types of the shape: + + [pair unit (pair unit (pair unit ...))] + + This structure is the worse-case of the unparsing function for types because + an extra test is performed to determine if the comb type needs to be folded. +*) +let rec dummy_type_generator size = + let open Script_typed_ir in + if size <= 1 then Ex_ty unit_t + else + match dummy_type_generator (size - 2) with + | Ex_ty r -> ( + let l = unit_t in + match pair_t (-1) l r with + | Error _ -> assert false + | Ok (Ty_ex_c t) -> Ex_ty t) + +(* A dummy comparable type generator, sampling linear terms of a given size. *) +let rec dummy_comparable_type_generator size = + let open Script_ir_translator in + let open Script_typed_ir in + if size <= 0 then Ex_comparable_ty unit_t + else + match dummy_comparable_type_generator (size - 2) with + | Ex_comparable_ty r -> + let l = unit_t in + Ex_comparable_ty + (match comparable_pair_t (-1) l r with + | Error _ -> assert false + | Ok t -> t) + +module Parse_type_shared = struct + type config = {max_size : int} + + let default_config = {max_size = Constants_repr.michelson_maximum_type_size} + + let config_encoding = + let open Data_encoding in + conv + (fun {max_size} -> max_size) + (fun max_size -> {max_size}) + (obj1 (req "max_size" int31)) + + type workload = Type_workload of {nodes : int; consumed : Size.t} + + let workload_encoding = + let open Data_encoding in + conv + (function Type_workload {nodes; consumed} -> (nodes, consumed)) + (fun (nodes, consumed) -> Type_workload {nodes; consumed}) + (obj2 (req "nodes" int31) (req "consumed" int31)) + + let workload_to_vector = function + | Type_workload {nodes; consumed} -> + Sparse_vec.String.of_list + [("nodes", float_of_int nodes); ("consumed", float_of_int consumed)] + + let tags = [Tags.translator] +end + +let parse_ty ctxt node = + Script_ir_translator.parse_ty + ctxt + ~legacy:true + ~allow_lazy_storage:true + ~allow_operation:true + ~allow_contract:true + ~allow_ticket:true + node + +let unparse_ty ctxt ty = Script_ir_unparser.unparse_ty ~loc:(-1) ctxt ty + +module Parse_type_benchmark : Benchmark.S = struct + include Parse_type_shared + + let name = ns "PARSE_TYPE" + + let info = "Benchmarking parse_ty" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let group = Benchmark.Group "size_translator_model" + + let create_benchmark ~rng_state config = + let open Result_syntax in + (let* ctxt, _ = Lwt_main.run (Execution_context.make ~rng_state ()) in + let ctxt = Gas_helpers.set_limit ctxt in + let size = Random.State.int rng_state config.max_size in + let ty = dummy_type_generator size in + match ty with + | Ex_ty ty -> + let* unparsed, _ = Environment.wrap_tzresult @@ unparse_ty ctxt ty in + let* _, ctxt' = Environment.wrap_tzresult @@ parse_ty ctxt unparsed in + let consumed = + Z.to_int + (Gas_helpers.fp_to_z + (Alpha_context.Gas.consumed ~since:ctxt ~until:ctxt')) + in + let nodes = + let x = Script_typed_ir.ty_size ty in + Saturation_repr.to_int @@ Script_typed_ir.Type_size.to_int x + in + let workload = Type_workload {nodes; consumed} in + let closure () = ignore (parse_ty ctxt unparsed) in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let model = + Model.make + ~conv:(function Type_workload {nodes; consumed = _} -> (nodes, ())) + Model.affine +end + +let () = Registration.register (module Parse_type_benchmark) + +module Unparse_type_benchmark : Benchmark.S = struct + include Parse_type_shared + + let name = ns "UNPARSE_TYPE" + + let info = "Benchmarking unparse_ty" + + let module_filename = __FILE__ + + let purpose = Benchmark.Generate_code "michelson_v1_gas" + + let group = Benchmark.Group "size_translator_model" + + let create_benchmark ~rng_state config = + let open Result_syntax in + (let* ctxt, _ = Lwt_main.run (Execution_context.make ~rng_state ()) in + let ctxt = Gas_helpers.set_limit ctxt in + let size = Random.State.int rng_state config.max_size in + let ty = dummy_type_generator size in + match ty with + | Ex_ty ty -> + let* _, ctxt' = Environment.wrap_tzresult @@ unparse_ty ctxt ty in + let consumed = + Z.to_int + (Gas_helpers.fp_to_z + (Alpha_context.Gas.consumed ~since:ctxt ~until:ctxt')) + in + let nodes = + let x = Script_typed_ir.ty_size ty in + Saturation_repr.to_int @@ Script_typed_ir.Type_size.to_int x + in + let workload = Type_workload {nodes; consumed} in + let closure () = ignore (unparse_ty ctxt ty) in + return (Generator.Plain {workload; closure})) + |> function + | Ok closure -> closure + | Error errs -> global_error name errs + + let model = + Model.make + ~takes_saturation_reprs:true + ~conv:(function Type_workload {nodes; consumed = _} -> (nodes, ())) + Model.affine +end + +let () = Registration.register (module Unparse_type_benchmark) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/translator_model.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/translator_model.ml new file mode 100644 index 000000000000..457437f58ae2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/translator_model.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let ns = Namespace.make Registration_helpers.ns "translator" + +let fv s = Free_variable.of_namespace (ns s) + +let gas_full t_kind code_or_data = + let name = + Format.asprintf + "%a_%a_gas" + Translator_workload.pp_kind + t_kind + Translator_workload.pp_code_or_data + code_or_data + in + let intercept = fv (Format.asprintf "%s_const" name) in + let coeff = fv (Format.asprintf "%s_coeff" name) in + Model.affine ~name:(ns name) ~intercept ~coeff + +let size_full t_kind code_or_data = + let name = + Format.asprintf + "%a_%a_size" + Translator_workload.pp_kind + t_kind + Translator_workload.pp_code_or_data + code_or_data + in + let coeff1 = fv (Format.asprintf "%s_traversal" name) in + let coeff2 = fv (Format.asprintf "%s_int_bytes" name) in + let coeff3 = fv (Format.asprintf "%s_string_bytes" name) in + Model.trilinear ~name:(ns name) ~coeff1 ~coeff2 ~coeff3 + +let gas_based_model t_kind code_or_data = + Model.make + ~conv:(function + | Translator_workload.Typechecker_workload {consumed; _} -> (consumed, ())) + (gas_full t_kind code_or_data) + +let size_based_model t_kind code_or_data = + Model.make + ~conv:(function + | Translator_workload.Typechecker_workload {micheline_size; _} -> ( + match micheline_size with + | {traversal; int_bytes; string_bytes} -> + (traversal, (int_bytes, (string_bytes, ()))))) + (size_full t_kind code_or_data) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/translator_workload.ml b/src/proto_020_PsParisC/lib_benchmarks_proto/translator_workload.ml new file mode 100644 index 000000000000..177ff05f08ba --- /dev/null +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/translator_workload.ml @@ -0,0 +1,193 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Size = Protocol.Gas_input_size + +type kind = Parsing | Unparsing + +type code_or_data = Code | Data + +type t = + | Typechecker_workload of { + t_kind : kind; + code_or_data : code_or_data; + micheline_size : Size.micheline_size; + consumed : Size.t; + } + +let kind_encoding : kind Data_encoding.t = + let open Data_encoding in + def "kind_encoding" + @@ string_enum [("parsing", Parsing); ("unparsing", Unparsing)] + +let code_or_data_encoding : code_or_data Data_encoding.t = + let open Data_encoding in + def "code_or_data_encoding" @@ string_enum [("code", Code); ("data", Data)] + +let encoding : t Data_encoding.t = + let open Data_encoding in + def "translator_trace_encoding" + @@ conv + (function + | Typechecker_workload {t_kind; code_or_data; micheline_size; consumed} + -> + (t_kind, code_or_data, micheline_size, consumed)) + (fun (t_kind, code_or_data, micheline_size, consumed) -> + Typechecker_workload {t_kind; code_or_data; micheline_size; consumed}) + (tup4 + kind_encoding + code_or_data_encoding + Size.micheline_size_encoding + Size.encoding) + +let pp_kind fmtr (kind : kind) = + match kind with + | Parsing -> Format.pp_print_string fmtr "Parsing" + | Unparsing -> Format.pp_print_string fmtr "Unparsing" + +let pp_code_or_data fmtr (x : code_or_data) = + match x with + | Code -> Format.pp_print_string fmtr "Code" + | Data -> Format.pp_print_string fmtr "Data" + +let pp fmtr (trace : t) = + match trace with + | Typechecker_workload {t_kind; code_or_data; micheline_size; consumed} -> + Format.fprintf + fmtr + "typechecker_trace { %a; %a; %a; %a }" + pp_kind + t_kind + pp_code_or_data + code_or_data + Size.pp_micheline_size + micheline_size + Size.pp + consumed + +let workload_to_sparse_vec (trace : t) = + let name, {Size.traversal; int_bytes; string_bytes}, consumed = + match trace with + | Typechecker_workload {t_kind; code_or_data; micheline_size; consumed} -> + let name = + Format.asprintf "%a_%a" pp_kind t_kind pp_code_or_data code_or_data + in + (name, micheline_size, consumed) + in + let n s = name ^ "_" ^ s in + let vars = + [ + (n "traversal", float_of_int (Size.to_int traversal)); + (n "int_bytes", float_of_int (Size.to_int int_bytes)); + (n "string_bytes", float_of_int (Size.to_int string_bytes)); + (n "gas", float_of_int (Size.to_int consumed)); + ] + in + Sparse_vec.String.of_list vars + +let data_typechecker_workload ctxt t_kind micheline_node ex_ty = + let open Lwt_syntax in + let open Protocol in + match ex_ty with + | Script_typed_ir.Ex_ty ty -> + let ctxt = Gas_helpers.set_limit ctxt in + Lwt_main.run + (let* res = + Script_ir_translator.parse_data + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:false ()) + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ty + micheline_node + |> Lwt.map Environment.wrap_tzresult + in + match res with + | Ok (_res, ctxt_after) -> + let micheline_size = Size.of_micheline micheline_node in + let consumed = + Alpha_context.Gas.consumed ~since:ctxt ~until:ctxt_after + in + let trace = + Typechecker_workload + { + t_kind; + code_or_data = Data; + micheline_size; + consumed = + Size.of_int (Z.to_int (Gas_helpers.fp_to_z consumed)); + } + in + return_some trace + | Error errors -> + Michelson_v1_error_reporter.report_errors + ~details:true + ~show_source:true + Format.err_formatter + errors ; + Format.eprintf "@." ; + return_none) + +let code_typechecker_workload (ctxt : Protocol.Alpha_context.context) + (t_kind : kind) (code : Protocol.Alpha_context.Script.node) + (bef : Protocol.Script_ir_translator.ex_stack_ty) = + let open Lwt_syntax in + let open Protocol in + let ctxt = Gas_helpers.set_limit ctxt in + let (Script_ir_translator.Ex_stack_ty stack_ty) = bef in + Lwt_main.run + (let* res = + Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:false ()) + code + stack_ty + |> Lwt.map Environment.wrap_tzresult + in + match res with + | Ok (_res, ctxt_after) -> + let micheline_size = Size.of_micheline code in + let consumed = + Alpha_context.Gas.consumed ~since:ctxt ~until:ctxt_after + in + let trace = + Typechecker_workload + { + t_kind; + code_or_data = Code; + micheline_size; + consumed = Size.of_int (Z.to_int (Gas_helpers.fp_to_z consumed)); + } + in + return_some trace + | Error errs -> + Michelson_v1_error_reporter.report_errors + ~details:true + ~show_source:true + Format.err_formatter + errs ; + Format.eprintf "@." ; + return_none) diff --git a/src/proto_020_PsParisC/lib_client/annotated_manager_operation.ml b/src/proto_020_PsParisC/lib_client/annotated_manager_operation.ml new file mode 100644 index 000000000000..57cb813ca9f0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/annotated_manager_operation.ml @@ -0,0 +1,139 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018-2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type _ t = + | Manager_info : { + source : Alpha_context.public_key_hash option; + fee : Tez.t Limit.t; + gas_limit : Gas.Arith.integral Limit.t; + storage_limit : Z.t Limit.t; + counter : Manager_counter.t option; + operation : 'kind manager_operation; + } + -> 'kind t + +type packed = Annotated_manager_operation : 'kind t -> packed + +type _ annotated_list = + | Single_manager : 'kind t -> 'kind annotated_list + | Cons_manager : + 'kind t * 'rest annotated_list + -> ('kind * 'rest) annotated_list + +type packed_annotated_list = + | Manager_list : 'kind annotated_list -> packed_annotated_list + +let rec manager_to_list = function + | Manager_list (Single_manager o) -> [Annotated_manager_operation o] + | Manager_list (Cons_manager (o, os)) -> + Annotated_manager_operation o :: manager_to_list (Manager_list os) + +let rec manager_of_list = function + | [] -> assert false + | [Annotated_manager_operation o] -> Manager_list (Single_manager o) + | Annotated_manager_operation o :: os -> + let (Manager_list os) = manager_of_list os in + Manager_list (Cons_manager (o, os)) + +let join_fee fee operation = + let open Result_syntax in + let (Manager_info c) = operation in + let* fee = Limit.join ~where:__LOC__ Tez.equal fee c.fee in + return (Manager_info {c with fee}) + +let set_fee fee (Manager_info c) = Manager_info {c with fee} + +let join_gas_limit gas_limit operation = + let open Result_syntax in + let (Manager_info c) = operation in + let* gas_limit = + Limit.join ~where:__LOC__ Gas.Arith.equal gas_limit c.gas_limit + in + return (Manager_info {c with gas_limit}) + +let set_gas_limit gas_limit (Manager_info c) = Manager_info {c with gas_limit} + +let join_storage_limit storage_limit (Manager_info c) = + let open Result_syntax in + let* storage_limit = + Limit.join ~where:__LOC__ Z.equal storage_limit c.storage_limit + in + return (Manager_info {c with storage_limit}) + +let set_storage_limit storage_limit (Manager_info c) = + Manager_info {c with storage_limit} + +let set_counter counter (Manager_info c) = + match c.counter with + | Some _ -> error_with "set_counter_annot: already set" + | None -> Ok (Manager_info {c with counter = Some counter}) + +let set_source source (Manager_info c) = + match c.source with + | Some _ -> error_with "set_source_annot: already set" + | None -> Ok (Manager_info {c with source = Some source}) + +let manager_from_annotated operation = + let open Result_syntax in + let (Manager_info {source; fee; gas_limit; storage_limit; counter; operation}) + = + operation + in + let* fee = Limit.get ~when_unknown:"unknown fee" fee in + let* gas_limit = Limit.get ~when_unknown:"unknown gas limit" gas_limit in + let* storage_limit = + Limit.get ~when_unknown:"unknown storage limit" storage_limit + in + let* source = + Option.fold + ~some:return + ~none:(error_with "manager_from_annotated: source not set") + source + in + let* counter = + Option.fold + ~some:return + ~none:(error_with "manager_from_annotated: counter not set") + counter + in + return + @@ Manager_operation + {source; fee; counter; gas_limit; storage_limit; operation} + +let rec manager_list_from_annotated : + type kind. kind annotated_list -> kind Kind.manager contents_list tzresult = + let open Result_syntax in + function + | Single_manager operation -> + let* op = manager_from_annotated operation in + return (Single op) + | Cons_manager (operation, rest) -> + let* rest = manager_list_from_annotated rest in + let* op = manager_from_annotated operation in + return (Cons (op, rest)) diff --git a/src/proto_020_PsParisC/lib_client/annotated_manager_operation.mli b/src/proto_020_PsParisC/lib_client/annotated_manager_operation.mli new file mode 100644 index 000000000000..0fc7a472f842 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/annotated_manager_operation.mli @@ -0,0 +1,98 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Annotated manager operations are wrappers used to accumulate information + (especially about limits) on the operation prior to the injection. *) + +open Protocol +open Alpha_context + +type _ t = + | Manager_info : { + source : Alpha_context.public_key_hash option; + fee : Tez.t Limit.t; + gas_limit : Gas.Arith.integral Limit.t; + storage_limit : Z.t Limit.t; + counter : Manager_counter.t option; + operation : 'kind manager_operation; + } + -> 'kind t + +type packed = Annotated_manager_operation : 'kind t -> packed + +(** The [annotated_list] type helps making + [contents_list] from a list of [manager_operation]s. + Its construction mimics [contents_list] in order to keep + consistent types when calling [inject_manager_operation] + and [inject_operation].*) +type _ annotated_list = + | Single_manager : 'kind t -> 'kind annotated_list + | Cons_manager : + 'kind t * 'rest annotated_list + -> ('kind * 'rest) annotated_list + +type packed_annotated_list = + | Manager_list : 'kind annotated_list -> packed_annotated_list + +(** Convert a list of annotated operations to a list of packed annotated + operations *) +val manager_to_list : packed_annotated_list -> packed list + +(** Converse of [manager_to_list] *) +val manager_of_list : packed list -> packed_annotated_list + +(** [join_fee fee op] updates [op.fee] to [Limit.join op.fee fee] and + fails if the join fails *) +val join_fee : Tez.t Limit.t -> 'a t -> 'a t tzresult + +(** [set_fee fee op] updates [op.fee] to [fee] *) +val set_fee : Tez.t Limit.t -> 'a t -> 'a t + +(** See [join_fee] *) +val join_gas_limit : Gas.Arith.integral Limit.t -> 'a t -> 'a t tzresult + +(** See [set_fee] *) +val set_gas_limit : Gas.Arith.integral Limit.t -> 'a t -> 'a t + +(** See [join_fee] *) +val join_storage_limit : Z.t Limit.t -> 'a t -> 'a t tzresult + +(** See [set_fee] *) +val set_storage_limit : Z.t Limit.t -> 'a t -> 'a t + +(** Set the counter of the annotated operation. Fail if the counter + is already set. *) +val set_counter : Manager_counter.t -> 'a t -> 'a t tzresult + +(** Set the source of the operation. Fail if the source is already set. *) +val set_source : public_key_hash -> 'a t -> 'a t tzresult + +(** Convert an annotated manager operation to a proper manager operation. + Fail if some fields in the annotated operation are not set. *) +val manager_from_annotated : 'a t -> 'a Kind.manager contents tzresult + +val manager_list_from_annotated : + 'kind annotated_list -> 'kind Kind.manager contents_list tzresult diff --git a/src/proto_020_PsParisC/lib_client/client_proto_args.ml b/src/proto_020_PsParisC/lib_client/client_proto_args.ml new file mode 100644 index 000000000000..94dd6df6bccb --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_args.ml @@ -0,0 +1,1089 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context + +type error += Bad_tez_arg of string * string (* Arg_name * value *) + +type error += Bad_max_priority of string + +type error += Bad_minimal_fees of string + +type error += Bad_max_waiting_time of string + +type error += Bad_preserved_levels of string + +type error += Forbidden_Negative_int of string + +let () = + register_error_kind + `Permanent + ~id:"badTezArg" + ~title:"Bad Tez Arg" + ~description:"Invalid \xEA\x9C\xA9 notation in parameter." + ~pp:(fun ppf (arg_name, literal) -> + Format.fprintf + ppf + "Invalid \xEA\x9C\xA9 notation in parameter %s: '%s'" + arg_name + literal) + Data_encoding.(obj2 (req "parameter" string) (req "literal" string)) + (function + | Bad_tez_arg (parameter, literal) -> Some (parameter, literal) + | _ -> None) + (fun (parameter, literal) -> Bad_tez_arg (parameter, literal)) ; + register_error_kind + `Permanent + ~id:"badMaxPriorityArg" + ~title:"Bad -max-priority arg" + ~description:"invalid priority in -max-priority" + ~pp:(fun ppf literal -> + Format.fprintf ppf "invalid priority '%s' in -max-priority" literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_max_priority parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_max_priority parameter) ; + register_error_kind + `Permanent + ~id:"badMinimalFeesArg" + ~title:"Bad -minimal-fees arg" + ~description:"invalid fee threshold in -fee-threshold" + ~pp:(fun ppf literal -> + Format.fprintf ppf "invalid minimal fees '%s'" literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_minimal_fees parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_minimal_fees parameter) ; + register_error_kind + `Permanent + ~id:"badMaxWaitingTimeArg" + ~title:"Bad -max-waiting-time arg" + ~description:"invalid duration in -max-waiting-time" + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for -max-waiting-time. Expected an integer, but \ + given '%s'" + literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_max_waiting_time parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_max_waiting_time parameter) ; + register_error_kind + `Permanent + ~id:"badPreservedLevelsArg" + ~title:"Bad -preserved-levels arg" + ~description:"invalid number of levels in -preserved-levels" + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for -preserved_levels. Expected a positive \ + integer, but given '%s'" + literal) + Data_encoding.(obj1 (req "parameter" string)) + (function Bad_preserved_levels parameter -> Some parameter | _ -> None) + (fun parameter -> Bad_preserved_levels parameter) ; + register_error_kind + `Permanent + ~id:"ForbiddenNegativeInt" + ~title:"Forbidden negative int" + ~description:"invalid number, must a non negative natural " + Data_encoding.(obj1 (req "invalid_natural" string)) + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for natural. Expected a non negative integer, but \ + given '%s'" + literal) + (function Forbidden_Negative_int str -> Some str | _ -> None) + (fun str -> Forbidden_Negative_int str) + +let string_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun _ x -> return x) + +let int_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) p -> + try return (int_of_string p) with _ -> cctxt#error "Cannot read int") + +let z_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) p -> + try return (Z.of_string p) with _ -> cctxt#error "Cannot read integer") + +let uri_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun _ x -> return (Uri.of_string x)) + +let bytes_of_prefixed_string (cctxt : #Client_context.full) s = + let open Lwt_result_syntax in + match + if String.length s < 2 || s.[0] <> '0' || s.[1] <> 'x' then None + else Hex.to_bytes (`Hex (String.sub s 2 (String.length s - 2))) + with + | Some s -> return s + | None -> + cctxt#error + "Invalid bytes, expecting hexadecimal notation (e.g. 0x1234abcd)" + +let bytes_parameter = Tezos_clic.parameter bytes_of_prefixed_string + +type 'a file_or_text = File of {path : string; content : 'a} | Text of 'a + +let content_of_file_or_text = function + | File {content; _} | Text content -> content + +let parse_file ~from_text ~read_file ~path = + let open Lwt_result_syntax in + let* content = read_file path in + from_text content + +let file_or_text ~from_text ~read_file = + let open Lwt_result_syntax in + Client_aliases.parse_alternatives + [ + ( "file", + fun path -> + let* content = parse_file ~from_text ~read_file ~path in + return (File {path; content}) ); + ( "text", + fun text -> + let* content = from_text text in + return (Text content) ); + ] + +let file_or_text_with_origin_parameter ~from_text () = + Tezos_clic.parameter (fun (cctxt : #Client_context.full) -> + file_or_text ~from_text:(from_text cctxt) ~read_file:cctxt#read_file) + +let file_or_text_parameter ~from_text () = + file_or_text_with_origin_parameter ~from_text () + |> Tezos_clic.map_parameter ~f:content_of_file_or_text + +let json_with_origin_parameter = + let open Lwt_result_syntax in + let from_text (cctxt : #Client_context.full) s = + match Data_encoding.Json.from_string s with + | Ok json -> return json + | Error err -> + cctxt#error "'%s' is not a valid JSON-encoded value: %s" s err + in + file_or_text_with_origin_parameter ~from_text () + +let json_parameter = + Tezos_clic.map_parameter ~f:content_of_file_or_text json_with_origin_parameter + +let data_parameter = + let from_text (_cctxt : #Client_context.full) input = + Lwt.return @@ Tezos_micheline.Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression input + in + file_or_text_parameter ~from_text () + +let safe_decode_json (cctxt : #Client_context.full) ~name + ?(pp_error = fun _json fmt exn -> Data_encoding.Json.print_error fmt exn) + encoding json = + let open Lwt_result_syntax in + match Data_encoding.Json.destruct encoding json with + | exception (Data_encoding.Json.Cannot_destruct _ as exn) -> + cctxt#error + "@[could not decode %s JSON:@,%a@]" + name + (pp_error json) + exn + | exception ((Stack_overflow | Out_of_memory) as exc) -> raise exc + | exception exc -> + cctxt#error "could not decode json (%s)" (Printexc.to_string exc) + | expr -> return expr + +let json_encoded_with_origin_parameter ~name ?pp_error encoding = + let open Lwt_result_syntax in + Tezos_clic.map_es_parameter + ~f:(fun (cctxt : #Client_context.full) json_with_origin -> + match json_with_origin with + | File {path; content} -> + let+ content = + safe_decode_json ~name ?pp_error cctxt encoding content + in + File {path; content} + | Text content -> + let+ content = safe_decode_json ~name cctxt encoding content in + Text content) + json_with_origin_parameter + +let json_encoded_parameter ~name ?pp_error encoding = + Tezos_clic.map_parameter + ~f:content_of_file_or_text + (json_encoded_with_origin_parameter ~name ?pp_error encoding) + +let json_encoded_param ~name ~desc ?pp_error encoding = + Tezos_clic.param ~name ~desc (json_encoded_parameter ~name ?pp_error encoding) + +let binary_encoded_parameter ~name encoding = + let open Lwt_result_syntax in + let from_text (cctxt : #Client_context.full) s = + match Data_encoding.Binary.of_bytes_opt encoding (Bytes.of_string s) with + | None -> cctxt#error "Invalid %s parameter" name + | Some x -> return x + in + file_or_text_parameter ~from_text () + +let parse_micheline_parameter source = + Lwt.return @@ Tezos_micheline.Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.expand_expression source + +let micheline_parameter = + Tezos_clic.parameter (fun (_ : full) source -> + parse_micheline_parameter source) + +let entrypoint_parameter = + Tezos_clic.parameter (fun _ str -> + Lwt.return @@ Environment.wrap_tzresult @@ Entrypoint.of_string_lax str) + +let init_arg = + Tezos_clic.default_arg + ~long:"init" + ~placeholder:"data" + ~doc:"initial value of the contract's storage" + ~default:"Unit" + string_parameter + +let other_contracts_parameter = + Tezos_clic.parameter (fun _ source -> + let open Lwt_result_syntax in + let* parsed = parse_micheline_parameter source in + let*? l = Michelson_v1_stack.parse_other_contracts parsed in + return l) + +let other_contracts_arg = + Tezos_clic.arg + ~doc: + {|types and addresses of extra contracts, formatted as {Contract "KT1..." ; Contract "KT1..." ; ...}|} + ~long:"other-contracts" + ~placeholder:"contracts" + other_contracts_parameter + +let extra_big_maps_parameter = + Tezos_clic.parameter (fun _ source -> + let open Lwt_result_syntax in + let* parsed = parse_micheline_parameter source in + let*? l = Michelson_v1_stack.parse_extra_big_maps parsed in + return l) + +let extra_big_maps_arg = + Tezos_clic.arg + ~doc: + {|identifier and content of extra big maps, formatted as {Big_map {Elt ; Elt ; ...}}|} + ~long:"extra-big-maps" + ~placeholder:"big maps" + extra_big_maps_parameter + +let global_constant_param ~name ~desc next = + Tezos_clic.param ~name ~desc string_parameter next + +let arg_arg = + Tezos_clic.arg + ~long:"arg" + ~placeholder:"data" + ~doc:"argument passed to the contract's script, if needed" + string_parameter + +let default_arg_arg = + Tezos_clic.arg + ~long:"default-arg" + ~placeholder:"data" + ~doc:"default argument passed to each contract's script, if needed" + string_parameter + +let delegate_arg = + Client_keys.Public_key_hash.source_arg + ~long:"delegate" + ~placeholder:"address" + ~doc:"delegate of the contract\nMust be a known address." + () + +let source_arg = + Tezos_clic.arg + ~long:"source" + ~placeholder:"address" + ~doc:"source of the deposits to be paid\nMust be a known address." + string_parameter + +let entrypoint_arg = + Tezos_clic.arg + ~long:"entrypoint" + ~placeholder:"name" + ~doc:"entrypoint of the smart contract" + entrypoint_parameter + +let default_entrypoint_arg = + Tezos_clic.arg + ~long:"default-entrypoint" + ~placeholder:"name" + ~doc:"default entrypoint of the smart contracts" + entrypoint_parameter + +let force_switch = + Tezos_clic.switch + ~long:"force" + ~short:'f' + ~doc: + "disables the node's injection checks\n\ + Force the injection of branch-invalid operation or force the injection \ + of block without a fitness greater than the current head." + () + +let minimal_timestamp_switch = + Tezos_clic.switch + ~long:"minimal-timestamp" + ~doc: + "Use the minimal timestamp instead of the current date as timestamp of \ + the baked block." + () + +let tez_format = + "Text format: `DDDDDDD.DDDDDD`.\n\ + Tez and mutez and separated by a period sign. Trailing and pending zeroes \ + are allowed." + +let tez_parameter param = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun _ s -> + match Tez.of_string s with + | Some tez -> return tez + | None -> tzfail (Bad_tez_arg (param, s))) + +let everything_tez_parameter param = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun _ s -> + match s with + | "everything" -> return Tez.max_mutez + | _ -> tzfail (Bad_tez_arg (param, s))) + +let everything_or_tez_parameter param = + Tezos_clic.compose_parameters + (tez_parameter param) + (everything_tez_parameter param) + +let tez_arg ~default ~parameter ~doc = + Tezos_clic.default_arg + ~long:parameter + ~placeholder:"amount" + ~doc + ~default + (tez_parameter ("--" ^ parameter)) + +let tez_opt_arg ~parameter ~doc = + Tezos_clic.arg + ~long:parameter + ~placeholder:"amount" + ~doc + (tez_parameter ("--" ^ parameter)) + +let tez_param ~name ~desc next = + Tezos_clic.param + ~name + ~desc:(desc ^ " in \xEA\x9C\xA9\n" ^ tez_format) + (tez_parameter name) + next + +let everything_or_tez_param ~name ~desc next = + Tezos_clic.param + ~name + ~desc:(desc ^ " in \xEA\x9C\xA9 (or everything)\n" ^ tez_format) + (everything_or_tez_parameter name) + next + +let non_negative_z_parser (cctxt : #Client_context.io) s = + match Z.of_string s with + | exception Invalid_argument _ -> cctxt#error "Expected number" + | v when Compare.Z.(v < Z.zero) -> + cctxt#error "Invalid number, must be a non negative number." + | v -> Lwt_result_syntax.return v + +let non_negative_z_parameter () = Tezos_clic.parameter non_negative_z_parser + +let non_negative_z_param ~name ~desc next = + Tezos_clic.param ~name ~desc (non_negative_z_parameter ()) next + +let counter_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + match Manager_counter.Internal_for_injection.of_string s with + | None -> cctxt#error "Invalid counter, must be a non-negative number." + | Some c -> return c) + +let non_negative_parser (cctxt : #Client_context.io) s = + let open Lwt_result_syntax in + match int_of_string_opt s with + | Some i when i >= 0 -> return i + | _ -> cctxt#error "Parameter should be a non-negative integer literal" + +let non_negative_parameter () = Tezos_clic.parameter non_negative_parser + +let non_negative_param ~name ~desc next = + Tezos_clic.param ~name ~desc (non_negative_parameter ()) next + +let positive_int_parser (cctxt : #Client_context.io) s = + let open Lwt_result_syntax in + match int_of_string_opt s with + | Some i when i > 0 -> return i + | _ -> cctxt#error "Parameter should be a positive integer literal" + +let positive_int_parameter () = Tezos_clic.parameter positive_int_parser + +let positive_int_param ~name ~desc next = + Tezos_clic.param ~name ~desc (positive_int_parameter ()) next + +let fee_arg = + Tezos_clic.arg + ~long:"fee" + ~placeholder:"amount" + ~doc:"fee in \xEA\x9C\xA9 to pay to the baker" + (tez_parameter "--fee") + +let default_fee_arg = + Tezos_clic.arg + ~long:"default-fee" + ~placeholder:"amount" + ~doc:"default fee in \xEA\x9C\xA9 to pay to the baker for each transaction" + (tez_parameter "--default-fee") + +let level_kind = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + match Option.bind (Script_int.of_string s) Script_int.is_nat with + | Some n -> return n + | None -> cctxt#error "invalid level (must be a positive number)") + +let level_arg = + Tezos_clic.arg + ~long:"level" + ~placeholder:"level" + ~doc:"Set the level to be returned by the LEVEL instruction" + level_kind + +let raw_level_parser (cctxt : #Client_context.io) s = + match Int32.of_string_opt s with + | Some i when i >= 0l -> + Lwt.return @@ Environment.wrap_tzresult (Raw_level.of_int32 i) + | _ -> + cctxt#error + "'%s' is not a valid level (should be a non-negative int32 value)" + s + +let raw_level_parameter () = Tezos_clic.parameter raw_level_parser + +let raw_level_param ~name ~desc next = + Tezos_clic.param ~name ~desc (raw_level_parameter ()) next + +let timestamp_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + match Script_timestamp.of_string s with + | Some time -> return time + | None -> + cctxt#error + "invalid timestamp, must be either a RFC 3339 string or a number \ + of seconds since epoch.") + +let now_arg = + Tezos_clic.arg + ~long:"now" + ~placeholder:"timestamp" + ~doc: + "Set the timestamp to be returned by the NOW instruction. Allowed format \ + are RFC 3339 (YYYY-MM-DDTHH:MM:SSZ) or number of seconds since epoch." + timestamp_parameter + +let gas_limit_kind = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + try + let v = Z.of_string s in + return (Gas.Arith.integral_exn v) + with _ -> cctxt#error "invalid gas limit (must be a positive number)") + +let gas_limit_arg = + Tezos_clic.arg + ~long:"gas-limit" + ~short:'G' + ~placeholder:"amount" + ~doc: + "Set the gas limit of the transaction instead of letting the client \ + decide based on a simulation" + gas_limit_kind + +let default_gas_limit_arg = + Tezos_clic.arg + ~long:"default-gas-limit" + ~short:'G' + ~placeholder:"amount" + ~doc: + "Set the default gas limit for each transaction instead of letting the \ + client decide based on a simulation" + gas_limit_kind + +let safety_guard_arg = + Tezos_clic.arg + ~long:"safety-guard" + ~placeholder:"extra_gas" + ~doc: + "Amount of gas to add to value computed by simulation. The gas safety \ + guard allows operations that consume a little more gas than expected to \ + be successful" + gas_limit_kind + +let run_gas_limit_arg = + Tezos_clic.arg + ~long:"gas" + ~short:'G' + ~doc:"Initial quantity of gas for typechecking and execution" + ~placeholder:"gas" + gas_limit_kind + +let unlimited_gas_arg = + Tezos_clic.switch + ~long:"unlimited-gas" + ~doc:"Allows interpretation with virtually unlimited gas" + () + +let storage_limit_kind = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + try + let v = Z.of_string s in + assert (Compare.Z.(v >= Z.zero)) ; + return v + with _ -> + cctxt#error "invalid storage limit (must be a positive number of bytes)") + +let storage_limit_arg = + Tezos_clic.arg + ~long:"storage-limit" + ~short:'S' + ~placeholder:"amount" + ~doc: + "Set the storage limit of the transaction instead of letting the client \ + decide based on a simulation" + storage_limit_kind + +let default_storage_limit_arg = + Tezos_clic.arg + ~long:"default-storage-limit" + ~short:'S' + ~placeholder:"amount" + ~doc: + "Set the default storage limit for each transaction instead of letting \ + the client decide based on a simulation" + storage_limit_kind + +let counter_arg = + Tezos_clic.arg + ~long:"counter" + ~short:'C' + ~placeholder:"counter" + ~doc:"Set the counter to be used by the transaction" + counter_parameter + +let max_priority_arg = + let open Lwt_result_syntax in + Tezos_clic.arg + ~long:"max-priority" + ~placeholder:"slot" + ~doc:"maximum allowed baking slot" + (Tezos_clic.parameter (fun _ s -> + try return (int_of_string s) with _ -> tzfail (Bad_max_priority s))) + +let timelock_locked_value_arg = + Tezos_clic.arg + ~long:"timelock-locked-valuec" + ~placeholder:"timelock-locked" + ~doc:"Timelock RSA group modulus" + string_parameter + +let default_minimal_fees = + match Tez.of_mutez 100L with None -> assert false | Some t -> t + +let default_minimal_nanotez_per_gas_unit = Q.of_int 100 + +let default_minimal_nanotez_per_byte = Q.of_int 1000 + +let minimal_fees_arg = + let open Lwt_result_syntax in + Tezos_clic.default_arg + ~long:"minimal-fees" + ~placeholder:"amount" + ~doc:"exclude operations with fees lower than this threshold (in tez)" + ~default:(Tez.to_string default_minimal_fees) + (Tezos_clic.parameter (fun _ s -> + match Tez.of_string s with + | Some t -> return t + | None -> tzfail (Bad_minimal_fees s))) + +let minimal_nanotez_per_gas_unit_arg = + let open Lwt_result_syntax in + Tezos_clic.default_arg + ~long:"minimal-nanotez-per-gas-unit" + ~placeholder:"amount" + ~doc: + "exclude operations with fees per gas lower than this threshold (in \ + nanotez)" + ~default:(Q.to_string default_minimal_nanotez_per_gas_unit) + (Tezos_clic.parameter (fun _ s -> + try return (Q.of_string s) with _ -> tzfail (Bad_minimal_fees s))) + +let minimal_nanotez_per_byte_arg = + let open Lwt_result_syntax in + Tezos_clic.default_arg + ~long:"minimal-nanotez-per-byte" + ~placeholder:"amount" + ~default:(Q.to_string default_minimal_nanotez_per_byte) + ~doc: + "exclude operations with fees per byte lower than this threshold (in \ + nanotez)" + (Tezos_clic.parameter (fun _ s -> + try return (Q.of_string s) with _ -> tzfail (Bad_minimal_fees s))) + +let replace_by_fees_arg = + Tezos_clic.switch + ~long:"replace" + ~doc: + "Replace an existing pending transaction from the same source, if any, \ + with another one with higher fees. There are no guarantees that the \ + first operation will not be included or that the second one will be. \ + But, only one of the operations at most will end in a block (in \ + precheck mode)." + () + +let successor_level_arg = + Tezos_clic.switch + ~long:"simulate-successor-level" + ~doc:"Make the simulate on the successor level of the current head." + () + +let preserved_levels_arg = + let open Lwt_result_syntax in + Tezos_clic.default_arg + ~long:"preserved-levels" + ~placeholder:"threshold" + ~doc:"Number of effective levels kept in the accuser's memory" + ~default:"200" + (Tezos_clic.parameter (fun _ s -> + try + let preserved_levels = int_of_string s in + if preserved_levels < 0 then tzfail (Bad_preserved_levels s) + else return preserved_levels + with _ -> tzfail (Bad_preserved_levels s))) + +let no_print_source_flag = + Tezos_clic.switch + ~long:"no-print-source" + ~short:'q' + ~doc: + "don't print the source code\n\ + If an error is encountered, the client will print the contract's source \ + code by default.\n\ + This option disables this behaviour." + () + +let no_confirmation = + Tezos_clic.switch + ~long:"no-confirmation" + ~doc:"don't print wait for the operation to be confirmed." + () + +let signature_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + match Signature.of_b58check_opt s with + | Some s -> return s + | None -> cctxt#error "Not given a valid signature") + +let unparsing_mode_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter + ~autocomplete:(fun _cctxt -> + return ["Readable"; "Optimized"; "Optimized_legacy"]) + (fun (cctxt : #Client_context.full) s -> + match s with + | "Readable" -> return Script_ir_unparser.Readable + | "Optimized" -> return Script_ir_unparser.Optimized + | "Optimized_legacy" -> return Script_ir_unparser.Optimized_legacy + | _ -> cctxt#error "Unknown unparsing mode %s" s) + +let unparsing_mode_arg ~default = + Tezos_clic.default_arg + ~long:"unparsing-mode" + ~placeholder:"mode" + ~doc: + "Unparsing mode to use\n\ + One of \"Readable\", \"Optimized\", or \"Optimized_legacy\".\n\ + This option affects the way the values of the following Michelson types \ + are represented:\n\ + - timestamp: the Readable representation is a RFC3339 string, the \ + Optimized and Optimized_legacy representations are the number of \ + seconds since Epoch\n\ + - key, signature, key_hash, address, contract, chain_id: the Readable \ + representation is a Base58Check string, the Optimized and \ + Optimized_legacy representations are byte sequences\n\ + - nested pairs: in Readable mode, the Pair constructor is used even \ + with arity bigger than 2 such as in Pair 0 1 2; in Optimized_legacy \ + mode, the Pair constructor is always use with arity 2 such as in Pair 0 \ + (Pair 1 2); in Optimized mode, a sequence is used if there are at least \ + 4 elements and the behavior is the same as in Optimized_legacy mode \ + otherwise.\n" + ~default + unparsing_mode_parameter + +let enforce_indentation_flag = + Tezos_clic.switch + ~long:"enforce-indentation" + ~doc: + "Check that the Micheline expression passed to this command is \ + well-indented." + () + +let display_names_flag = + Tezos_clic.switch + ~long:"display-names" + ~doc:"Print names of scripts passed to this command" + () + +let fixed_point_parameter = + let open Lwt_result_syntax in + let rec remove_trailing_zeroes ~decimals ~right i = + if i < decimals then Some (String.sub right 0 decimals) + else if right.[i] <> '0' then None + else (remove_trailing_zeroes [@ocaml.tailcall]) ~decimals ~right (i - 1) + in + let parse ~decimals p = + let open Option_syntax in + let* left, right = + match String.split_on_char '.' p with + | [left; right] -> Some (left, right) + | [left] -> Some (left, "") + | _ -> None + in + let* right = + if String.length right > decimals then + remove_trailing_zeroes ~decimals ~right (String.length right - 1) + else Some (right ^ String.make (decimals - String.length right) '0') + in + int_of_string_opt (left ^ right) + in + let parse ~decimals p = + if decimals >= 2 && String.length p > 0 && p.[String.length p - 1] = '%' + then parse ~decimals:(decimals - 2) (String.sub p 0 (String.length p - 1)) + else parse ~decimals p + in + fun ~decimals -> + if decimals < 0 then + raise (Invalid_argument "fixed_point_parameter: negative decimals") + else fun ~name -> + Tezos_clic.parameter (fun (cctxt : #Client_context.full) p -> + match parse ~decimals p with + | Some res -> return res + | None -> + cctxt#error + "Cannot read %s parameter: expecting a fixed point number with \ + at most %d decimals, or a fixed point number with at most %d \ + decimals followed by a %% sign." + name + decimals + (decimals - 2)) + +let limit_of_staking_over_baking_millionth_arg = + Tezos_clic.arg + ~long:"limit-of-staking-over-baking" + ~placeholder:"limit" + ~doc: + "Limits the total amount of stake for the source's delegators as a \ + proportion of the source's own stake. Any amount exceeding this limit \ + is considered as delegation in the stake of the delegate. The value \ + should be between 0 and 5 (default 0 if not set). If this parameter is \ + 0, as is the default, any staking operation from the source's \ + delegators are forbidden and will fail (unstaking operations are still \ + allowed)." + ((* TODO #6162: should we check it's between 0 and 5 million? *) + fixed_point_parameter + ~decimals:6 + ~name:"limit of staking over baking") + +let edge_of_baking_over_staking_billionth_arg = + Tezos_clic.arg + ~long:"edge-of-baking-over-staking" + ~placeholder:"edge" + ~doc: + "Sets the portion of the delegate's stakers rewards that goes to the \ + delegate. This edge, taken from the staker's rewards, is accrued to the \ + delegate's own frozen balance. This value must be between 0 and 1 (e.g. \ + 0.05 for the delegate to receive 5% of the staker's rewards). Default \ + value is 1 (delegate receives all staker's rewards)." + ((* TODO #6162: check it's between 0 and 1 billion *) + fixed_point_parameter + ~decimals:9 + ~name:"edge of baking over staking") + +module Sc_rollup_params = struct + let rollup_kind_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) name -> + match Sc_rollup.Kind.of_string name with + | None -> + cctxt#error + "Parameter '%s' is not a valid rollup name (must be one of %s)" + name + (String.concat ", " Sc_rollup.Kind.(List.map to_string all)) + | Some k -> return k) + + let boot_sector_parameter = + let open Lwt_result_syntax in + let from_text (cctxt : #Client_context.full) s = + return (fun (Sc_rollup.PVM.Packed (module R)) -> + R.parse_boot_sector s |> function + | None -> cctxt#error "Invalid kernel" + | Some boot_sector -> return boot_sector) + in + file_or_text_parameter ~from_text () + + let messages_parameter = + let open Lwt_result_syntax in + let from_json (cctxt : #Client_context.full) text = + try + match Ezjsonm.from_string text with + | `A messages -> return (`Json (`A (`String "raw" :: messages))) + | _ -> cctxt#error "Expecting a list of string" + with Ezjsonm.Parse_error _ -> + cctxt#error "Given text is not valid JSON: '%s'" text + in + let from_json_hex (cctxt : #Client_context.full) text = + try + match Ezjsonm.from_string text with + | `A messages -> return (`Json (`A (`String "hex" :: messages))) + | _ -> cctxt#error "Expecting a list of hex-encoded string" + with Ezjsonm.Parse_error _ -> + cctxt#error "Given text is not valid JSON: '%s'" text + in + let from_bin_file (cctxt : #Client_context.full) path = + let* bin = cctxt#read_file path in + return (`Bin bin) + in + let from_json_file (cctxt : #Client_context.full) path = + let* json_string = cctxt#read_file path in + from_json cctxt json_string + in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) p -> + Client_aliases.parse_alternatives + [ + ("text", from_json cctxt); + ("hex", from_json_hex cctxt); + ("file", from_json_file cctxt); + ("bin", from_bin_file cctxt); + ] + p) + + let commitment_hash_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) commitment_hash -> + match Sc_rollup.Commitment.Hash.of_b58check_opt commitment_hash with + | None -> + cctxt#error + "Parameter '%s' is not a valid B58-encoded rollup commitment hash" + commitment_hash + | Some hash -> return hash) + + let unchecked_payload_parameter = + let open Lwt_result_syntax in + file_or_text_parameter ~from_text:(fun _cctxt -> return) () + + let compressed_state_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) state_hash -> + match Sc_rollup.State_hash.of_b58check_opt state_hash with + | None -> + cctxt#error + "Parameter '%s' is not a valid B58-encoded compressed state" + state_hash + | Some hash -> return hash) + + let number_of_ticks_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) nb_of_ticks -> + match Int64.of_string_opt nb_of_ticks with + | Some nb_of_ticks -> ( + match Sc_rollup.Number_of_ticks.of_value nb_of_ticks with + | None -> + cctxt#error + "Parameter '%Ld' is out of bounds, it should be between %Ld \ + and %Ld" + nb_of_ticks + Sc_rollup.Number_of_ticks.min_value + Sc_rollup.Number_of_ticks.max_value + | Some nb_of_ticks -> return nb_of_ticks) + | None -> + cctxt#error "'%s' is not valid, should be a int64 value" nb_of_ticks) + + let whitelist = + json_encoded_parameter + ~name:"Whitelist for private rollups" + Sc_rollup.Whitelist.encoding +end + +let whitelist_arg = + Tezos_clic.arg + ~long:"whitelist" + ~short:'W' + ~placeholder:"whitelist" + ~doc: + "Whitelist for private rollups. Members of the whitelist are stakers \ + that are allowed to publish commitments." + Sc_rollup_params.whitelist + +module Zk_rollup_params = struct + let address_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + match Zk_rollup.Address.of_b58check_opt s with + | Some c -> return c + | None -> cctxt#error "Parameter '%s' is an invalid Epoxy address" s) + + let plonk_public_parameters_parameter = + binary_encoded_parameter + ~name:"PlonK public" + Plonk.Main_protocol.verifier_public_parameters_encoding + + let update_parameter = + binary_encoded_parameter ~name:"Epoxy Update" Zk_rollup.Update.encoding + + let operations_parameter = + binary_encoded_parameter + ~name:"Epoxy Operations" + Data_encoding.( + list + @@ tup2 Zk_rollup.Operation.encoding (option Zk_rollup.Ticket.encoding)) + + let state_parameter = + binary_encoded_parameter ~name:"Epoxy State" Zk_rollup.State.encoding + + let circuits_info_parameter = + binary_encoded_parameter + ~name:"Epoxy Circuits_info map" + Zk_rollup.Account.circuits_info_encoding +end + +module Dal = struct + let commitment_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun (cctxt : #Client_context.full) commitment_hash -> + match Dal_slot_repr.Commitment.of_b58check_opt commitment_hash with + | None -> + cctxt#error + "Parameter '%s' is not a valid B58-encoded DAL commitment" + commitment_hash + | Some commitment -> return commitment) + + let commitment_proof_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter + (fun (cctxt : #Client_context.full) commitment_proof_hex -> + match Hex.to_string (`Hex commitment_proof_hex) with + | None -> + cctxt#error + "Commitment proof parameter '%s' is not a valid hexadecimal \ + string" + commitment_proof_hex + | Some commitment_proof_bin -> ( + match + Data_encoding.Binary.of_string_opt + Dal_slot_repr.Commitment_proof.encoding + commitment_proof_bin + with + | None -> + cctxt#error + "Commitment proof parameter '%s' is not a valid DAL \ + commitment proof" + commitment_proof_hex + | Some commitment_proof -> return commitment_proof)) +end + +let fee_parameter_args = + let open Tezos_clic in + let open Lwt_result_syntax in + let force_low_fee_arg = + switch + ~long:"force-low-fee" + ~doc:"Don't check that the fee is lower than the estimated default value" + () + in + let fee_cap_arg = + default_arg + ~long:"fee-cap" + ~placeholder:"amount" + ~default:"1.0" + ~doc:"Set the fee cap" + (parameter (fun (cctxt : #Client_context.full) s -> + match Tez.of_string s with + | Some t -> return t + | None -> cctxt#error "Bad fee cap")) + in + let burn_cap_arg = + default_arg + ~long:"burn-cap" + ~placeholder:"amount" + ~default:"0" + ~doc:"Set the burn cap" + (parameter (fun (cctxt : #Client_context.full) s -> + match Tez.of_string s with + | Some t -> return t + | None -> cctxt#error "Bad burn cap")) + in + Tezos_clic.map_arg + ~f: + (fun _cctxt + ( minimal_fees, + minimal_nanotez_per_byte, + minimal_nanotez_per_gas_unit, + force_low_fee, + fee_cap, + burn_cap ) -> + return + { + Injection.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee; + fee_cap; + burn_cap; + }) + (Tezos_clic.aggregate + (Tezos_clic.args6 + minimal_fees_arg + minimal_nanotez_per_byte_arg + minimal_nanotez_per_gas_unit_arg + force_low_fee_arg + fee_cap_arg + burn_cap_arg)) diff --git a/src/proto_020_PsParisC/lib_client/client_proto_args.mli b/src/proto_020_PsParisC/lib_client/client_proto_args.mli new file mode 100644 index 000000000000..fa48997ec56f --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_args.mli @@ -0,0 +1,303 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +val entrypoint_parameter : (Entrypoint.t, full) Tezos_clic.parameter + +val init_arg : (string, full) Tezos_clic.arg + +val fee_arg : (Tez.t option, full) Tezos_clic.arg + +val default_fee_arg : (Tez.t option, full) Tezos_clic.arg + +val counter_arg : (Manager_counter.t option, full) Tezos_clic.arg + +val gas_limit_arg : (Gas.Arith.integral option, full) Tezos_clic.arg + +val safety_guard_arg : (Gas.Arith.integral option, full) Tezos_clic.arg + +val default_gas_limit_arg : (Gas.Arith.integral option, full) Tezos_clic.arg + +val run_gas_limit_arg : (Gas.Arith.integral option, full) Tezos_clic.arg + +val unlimited_gas_arg : (bool, full) Tezos_clic.arg + +val storage_limit_arg : (Z.t option, full) Tezos_clic.arg + +val default_storage_limit_arg : (Z.t option, full) Tezos_clic.arg + +val arg_arg : (string option, full) Tezos_clic.arg + +val default_arg_arg : (string option, full) Tezos_clic.arg + +val source_arg : (string option, full) Tezos_clic.arg + +val entrypoint_arg : (Entrypoint.t option, full) Tezos_clic.arg + +val default_entrypoint_arg : (Entrypoint.t option, full) Tezos_clic.arg + +val delegate_arg : (Signature.Public_key_hash.t option, full) Tezos_clic.arg + +val max_priority_arg : (int option, full) Tezos_clic.arg + +val minimal_fees_arg : (Tez.t, full) Tezos_clic.arg + +val minimal_nanotez_per_gas_unit_arg : (Q.t, full) Tezos_clic.arg + +val minimal_nanotez_per_byte_arg : (Q.t, full) Tezos_clic.arg + +val replace_by_fees_arg : (bool, full) Tezos_clic.arg + +val successor_level_arg : (bool, full) Tezos_clic.arg + +val force_switch : (bool, full) Tezos_clic.arg + +val minimal_timestamp_switch : (bool, full) Tezos_clic.arg + +val preserved_levels_arg : (int, full) Tezos_clic.arg + +val no_print_source_flag : (bool, full) Tezos_clic.arg + +val no_confirmation : (bool, full) Tezos_clic.arg + +val timelock_locked_value_arg : (string option, full) Tezos_clic.arg + +val tez_arg : + default:string -> + parameter:string -> + doc:string -> + (Tez.t, full) Tezos_clic.arg + +val tez_opt_arg : + parameter:string -> doc:string -> (Tez.t option, full) Tezos_clic.arg + +val tez_param : + name:string -> + desc:string -> + ('a, full) Tezos_clic.params -> + (Tez.t -> 'a, full) Tezos_clic.params + +val everything_or_tez_param : + name:string -> + desc:string -> + ('a, full) Tezos_clic.params -> + (Tez.t -> 'a, full) Tezos_clic.params + +val non_negative_z_parameter : + unit -> (Z.t, #Client_context.io) Tezos_clic.parameter + +val non_negative_z_param : + name:string -> + desc:string -> + ('a, (#Client_context.io as 'b)) Tezos_clic.params -> + (Z.t -> 'a, 'b) Tezos_clic.params + +val non_negative_parameter : + unit -> (int, #Client_context.io) Tezos_clic.parameter + +val non_negative_param : + name:string -> + desc:string -> + ('a, (#Client_context.io as 'b)) Tezos_clic.params -> + (int -> 'a, 'b) Tezos_clic.params + +val positive_int_parameter : + unit -> (int, #Client_context.io) Tezos_clic.parameter + +val positive_int_param : + name:string -> + desc:string -> + ('a, (#Client_context.io as 'b)) Tezos_clic.params -> + (int -> 'a, 'b) Tezos_clic.params + +val global_constant_param : + name:string -> + desc:string -> + ('a, full) Tezos_clic.params -> + (string -> 'a, full) Tezos_clic.params + +val signature_parameter : (Signature.t, full) Tezos_clic.parameter + +val int_parameter : (int, full) Tezos_clic.parameter + +val z_parameter : (Z.t, full) Tezos_clic.parameter + +val uri_parameter : (Uri.t, full) Tezos_clic.parameter + +val string_parameter : (string, full) Tezos_clic.parameter + +val bytes_of_prefixed_string : full -> string -> Bytes.t tzresult Lwt.t + +val bytes_parameter : (Bytes.t, full) Tezos_clic.parameter + +type 'a file_or_text = File of {path : string; content : 'a} | Text of 'a + +val content_of_file_or_text : 'a file_or_text -> 'a + +val file_or_text : + from_text:(string -> 'a tzresult Lwt.t) -> + read_file:(string -> string tzresult Lwt.t) -> + string -> + 'a file_or_text tzresult Lwt.t + +val file_or_text_with_origin_parameter : + from_text:(full -> string -> 'a tzresult Lwt.t) -> + unit -> + ('a file_or_text, full) Tezos_clic.parameter + +val file_or_text_parameter : + from_text:(full -> string -> 'a tzresult Lwt.t) -> + unit -> + ('a, full) Tezos_clic.parameter + +val json_with_origin_parameter : + (Data_encoding.Json.t file_or_text, full) Tezos_clic.parameter + +val safe_decode_json : + full -> + name:string -> + ?pp_error:(Data_encoding.json -> Format.formatter -> exn -> unit) -> + 'a Data_encoding.t -> + Data_encoding.json -> + 'a tzresult Lwt.t + +val json_encoded_with_origin_parameter : + name:string -> + ?pp_error:(Data_encoding.json -> Format.formatter -> exn -> unit) -> + 'a Data_encoding.t -> + ('a file_or_text, full) Tezos_clic.parameter + +val json_encoded_parameter : + name:string -> + ?pp_error:(Data_encoding.json -> Format.formatter -> exn -> unit) -> + 'a Data_encoding.t -> + ('a, full) Tezos_clic.parameter + +val json_encoded_param : + name:string -> + desc:string -> + ?pp_error:(Data_encoding.json -> Format.formatter -> exn -> unit) -> + 'b Data_encoding.t -> + ('a, full) Tezos_clic.params -> + ('b -> 'a, full) Tezos_clic.params + +val json_parameter : (Data_encoding.Json.t, full) Tezos_clic.parameter + +val data_parameter : (Michelson_v1_parser.parsed, full) Tezos_clic.parameter + +val raw_level_parameter : + unit -> (Raw_level.t, #Client_context.io) Tezos_clic.parameter + +val raw_level_param : + name:string -> + desc:string -> + ('a, (#Client_context.io as 'b)) Tezos_clic.params -> + (Raw_level.t -> 'a, 'b) Tezos_clic.params + +val micheline_parameter : + (string Michelson_v1_parser.parser_result, full) Tezos_clic.parameter + +val unparsing_mode_arg : + default:string -> (Script_ir_unparser.unparsing_mode, full) Tezos_clic.arg + +val enforce_indentation_flag : (bool, full) Tezos_clic.arg + +val display_names_flag : (bool, full) Tezos_clic.arg + +val level_arg : (Script_int.n Script_int.num option, full) Tezos_clic.arg + +val now_arg : (Script_timestamp.t option, full) Tezos_clic.arg + +val limit_of_staking_over_baking_millionth_arg : + (int option, full) Tezos_clic.arg + +val edge_of_baking_over_staking_billionth_arg : + (int option, full) Tezos_clic.arg + +val other_contracts_arg : + (RPC.Scripts.S.other_contract_description list option, full) Tezos_clic.arg + +val extra_big_maps_arg : + (RPC.Scripts.S.extra_big_map_description list option, full) Tezos_clic.arg + +module Sc_rollup_params : sig + val rollup_kind_parameter : (Sc_rollup.Kind.t, full) Tezos_clic.parameter + + val boot_sector_parameter : + (Sc_rollup.PVM.t -> string tzresult Lwt.t, full) Tezos_clic.parameter + + val messages_parameter : + ([`Bin of string | `Json of Data_encoding.json], full) Tezos_clic.parameter + + val commitment_hash_parameter : + (Sc_rollup.Commitment.Hash.t, full) Tezos_clic.parameter + + val unchecked_payload_parameter : (string, full) Tezos_clic.parameter + + val compressed_state_parameter : + (Sc_rollup.State_hash.t, full) Tezos_clic.parameter + + val number_of_ticks_parameter : + (Sc_rollup.Number_of_ticks.t, full) Tezos_clic.parameter + + val whitelist : (Sc_rollup.Whitelist.t, full) Tezos_clic.parameter +end + +val whitelist_arg : (Sc_rollup.Whitelist.t option, full) Tezos_clic.arg + +module Zk_rollup_params : sig + val address_parameter : (Zk_rollup.t, full) Tezos_clic.parameter + + val plonk_public_parameters_parameter : + (Plonk.Main_protocol.verifier_public_parameters, full) Tezos_clic.parameter + + val update_parameter : (Zk_rollup.Update.t, full) Tezos_clic.parameter + + val operations_parameter : + ( (Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list, + full ) + Tezos_clic.parameter + + val state_parameter : (Zk_rollup.State.t, full) Tezos_clic.parameter + + val circuits_info_parameter : + ( [`Fee | `Private | `Public] Zk_rollup.Account.SMap.t, + full ) + Tezos_clic.parameter +end + +module Dal : sig + val commitment_parameter : + (Dal_slot_repr.Commitment.t, full) Tezos_clic.parameter + + val commitment_proof_parameter : + (Dal_slot_repr.Commitment_proof.t, full) Tezos_clic.parameter +end + +val fee_parameter_args : (Injection.fee_parameter, full) Tezos_clic.arg diff --git a/src/proto_020_PsParisC/lib_client/client_proto_context.ml b/src/proto_020_PsParisC/lib_client/client_proto_context.ml new file mode 100644 index 000000000000..9a071294f152 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_context.ml @@ -0,0 +1,1505 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2024 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context +open Tezos_micheline +open Client_proto_contracts +open Client_keys + +let get_balance (rpc : #rpc_context) ~chain ~block contract = + Alpha_services.Contract.balance rpc (chain, block) contract + +let get_staked_balance (rpc : #rpc_context) ~chain ~block contract = + Alpha_services.Contract.staked_balance rpc (chain, block) contract + +let get_full_balance (rpc : #rpc_context) ~chain ~block contract = + Alpha_services.Contract.full_balance rpc (chain, block) contract + +let get_storage (rpc : #rpc_context) ~chain ~block ~unparsing_mode contract = + Plugin.RPC.Contract.get_storage_normalized + rpc + (chain, block) + ~unparsing_mode + ~contract + +let get_used_storage_space (rpc : #rpc_context) ~chain ~block contract = + Plugin.RPC.Contract.get_used_storage_space rpc (chain, block) ~contract + +let get_paid_storage_space (rpc : #rpc_context) ~chain ~block contract = + Plugin.RPC.Contract.get_paid_storage_space rpc (chain, block) ~contract + +let get_big_map_value (rpc : #rpc_context) ~chain ~block ~unparsing_mode id key + = + Plugin.RPC.Big_map.big_map_get_normalized + rpc + (chain, block) + ~unparsing_mode + id + key + +let get_contract_big_map_value (rpc : #rpc_context) ~chain ~block contract key = + Alpha_services.Contract.contract_big_map_get_opt + rpc + (chain, block) + contract + key + +let get_script (rpc : #rpc_context) ~chain ~block ~unparsing_mode + ~normalize_types contract = + Plugin.RPC.Contract.get_script_normalized + rpc + (chain, block) + ~unparsing_mode + ~normalize_types + ~contract + +let get_script_hash (rpc : #rpc_context) ~chain ~block contract = + let open Lwt_result_syntax in + let* script_opt = + Alpha_services.Contract.script_opt rpc (chain, block) contract + in + Option.map_es + (fun {Script.code; storage = _} -> + let*? code = Environment.wrap_tzresult @@ Script_repr.force_decode code in + let bytes = Data_encoding.Binary.to_bytes_exn Script.expr_encoding code in + let hash = Script_expr_hash.hash_bytes [bytes] in + return hash) + script_opt + +let get_contract_ticket_balance (rpc : #rpc_context) ~chain ~block contract key + = + Plugin.RPC.Contract.get_ticket_balance rpc (chain, block) contract key + +let get_contract_all_ticket_balances (rpc : #rpc_context) ~chain ~block contract + = + Plugin.RPC.Contract.get_all_ticket_balances rpc (chain, block) contract + +let ticket_balances_encoding = Plugin.RPC.Contract.ticket_balances_encoding + +let get_frozen_deposits_limit (rpc : #rpc_context) ~chain ~block delegate = + Alpha_services.Delegate.frozen_deposits_limit rpc (chain, block) delegate + +let parse_expression arg = + Lwt.return + (Micheline_parser.no_parsing_error + (Michelson_v1_parser.parse_expression arg)) + +let parse_arg_transfer arg = + let open Lwt_result_syntax in + match arg with + | Some arg -> + let* {expanded = arg; _} = parse_expression arg in + return (Script.lazy_expr arg) + | None -> return Script.unit_parameter + +let build_transaction_operation ~amount ~parameters + ?(entrypoint = Entrypoint.default) ?fee ?gas_limit ?storage_limit + destination = + let operation = Transaction {amount; parameters; destination; entrypoint} in + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + operation + +let transfer_with_script (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?(force = false) ?branch ?successor_level + ~source ~src_pk ~src_sk ~destination ?(entrypoint = Entrypoint.default) + ~parameters ~amount ?fee ?gas_limit ?safety_guard ?storage_limit ?counter + ~fee_parameter ?replace_by_fees () = + let open Lwt_result_syntax in + let contents = + build_transaction_operation + ~amount + ~parameters + ~entrypoint + ?fee + ?gas_limit + ?storage_limit + destination + in + let contents = Annotated_manager_operation.Single_manager contents in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~force + ?safety_guard + ?branch + ?successor_level + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ?counter + ?replace_by_fees + ~src_pk + ~src_sk + ~fee_parameter + contents + in + let*? contracts = Injection.originated_contracts ~force result in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return ((oph, op, result), contracts) + +let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?(force = false) ?branch ?successor_level + ~source ~src_pk ~src_sk ~destination ?entrypoint ?arg ~amount ?fee + ?gas_limit ?safety_guard ?storage_limit ?counter ~fee_parameter + ?replace_by_fees () = + let open Lwt_result_syntax in + let* parameters = parse_arg_transfer arg in + transfer_with_script + (cctxt : #full) + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~force + ?branch + ?successor_level + ~source + ~src_pk + ~src_sk + ~destination + ?entrypoint + ~parameters + ~amount + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + ?replace_by_fees + () + +let build_reveal_operation ?fee ?gas_limit ?storage_limit pk = + let operation = Reveal pk in + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + operation + +let reveal cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing ?branch + ~source ~src_pk ~src_sk ?fee ~fee_parameter () = + let open Lwt_result_syntax in + let contents = + Annotated_manager_operation.Single_manager + (build_reveal_operation ?fee ~storage_limit:Z.zero src_pk) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk + ~fee_parameter + contents + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let build_delegate_operation ?fee ?gas_limit ?storage_limit delegate_opt = + let operation = Delegation delegate_opt in + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + operation + +let delegate_contract cctxt ~chain ~block ?branch ?confirmations ?dry_run + ?verbose_signing ?simulation ~source ~src_pk ~src_sk ?fee ~fee_parameter + delegate_opt = + let open Lwt_result_syntax in + let operation = + Annotated_manager_operation.Single_manager + (build_delegate_operation ?fee delegate_opt) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?branch + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let list_contract_labels cctxt ~chain ~block = + let open Lwt_result_syntax in + let* contracts = Alpha_services.Contract.list cctxt (chain, block) in + let* result = + List.rev_map_es + (fun h -> + let* nm = + match (h : Contract.t) with + | Implicit m -> ( + let* nm_opt = Public_key_hash.rev_find cctxt m in + match nm_opt with + | None -> return "" + | Some nm -> ( + let* contract_opt = Raw_contract_alias.find_opt cctxt nm in + match contract_opt with + | None -> return (" (known as " ^ nm ^ ")") + | Some _ -> return (" (known as key:" ^ nm ^ ")"))) + | Originated _ -> ( + let* nm_opt = Raw_contract_alias.rev_find cctxt h in + match nm_opt with + | None -> return "" + | Some nm -> return (" (known as " ^ nm ^ ")")) + in + let kind = + match h with Implicit _ -> " (implicit)" | Originated _ -> "" + in + let h_b58 = Contract.to_b58check h in + return (nm, h_b58, kind)) + contracts + in + return (List.rev result) + +let message_added_contract (cctxt : #full) name = + cctxt#message "Contract memorized as %s." name + +let set_delegate cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing + ?simulation ?fee contract ~src_pk ~manager_sk ~fee_parameter opt_delegate = + delegate_contract + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~source:contract + ~src_pk + ~src_sk:manager_sk + ?fee + ~fee_parameter + opt_delegate + +let build_update_consensus_key ?fee ?gas_limit ?storage_limit consensus_pk = + let operation = Update_consensus_key consensus_pk in + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + operation + +let register_as_delegate cctxt ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?fee ~manager_sk ~fee_parameter ?consensus_pk src_pk = + let open Lwt_result_syntax in + let source = Signature.Public_key.hash src_pk in + let delegate_op = build_delegate_operation ?fee (Some source) in + match consensus_pk with + | None -> ( + let operation = Annotated_manager_operation.Single_manager delegate_op in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return ((oph, op, result), None)) + | Some consensus_pk -> ( + let operation = + Annotated_manager_operation.Cons_manager + ( delegate_op, + Annotated_manager_operation.Single_manager + (build_update_consensus_key ?fee consensus_pk) ) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~successor_level:true + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result + (Manager_operation _, Manager_operation_result _) -> + . + | Apply_results.Cons_and_result + ( (Manager_operation _ as op1), + res1, + Single_and_result ((Manager_operation _ as op2), res2) ) -> + return ((oph, op1, res1), Some (op2, res2))) + +let update_consensus_key cctxt ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ~consensus_pk ~manager_sk ~fee_parameter + src_pk = + let open Lwt_result_syntax in + let source = Signature.Public_key.hash src_pk in + let operation = build_update_consensus_key ?fee consensus_pk in + let operation = Annotated_manager_operation.Single_manager operation in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~successor_level:true + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let drain_delegate cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing + ?simulation ~consensus_sk ~consensus_pkh ?(destination = consensus_pkh) + ~delegate () = + let open Lwt_result_syntax in + let operation = + Single + (Drain_delegate {consensus_key = consensus_pkh; delegate; destination}) + in + let* oph, op, result = + Injection.inject_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~src_sk:consensus_sk + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Drain_delegate _ as op), result) -> + return (oph, op, result) + +let set_deposits_limit cctxt ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee contract ~src_pk ~manager_sk + ~fee_parameter limit_opt = + let open Lwt_result_syntax in + let operation = Set_deposits_limit limit_opt in + let operation = + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + operation + in + let operation = Annotated_manager_operation.Single_manager operation in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~source:contract + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let increase_paid_storage cctxt ~chain ~block ?force ?dry_run ?verbose_signing + ?fee ?confirmations ?simulation ~source ~destination ~src_pk ~manager_sk + ~fee_parameter ~amount_in_bytes () = + let open Lwt_result_syntax in + let operation = Increase_paid_storage {amount_in_bytes; destination} in + let operation = + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + operation + in + let operation = Annotated_manager_operation.Single_manager operation in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?force + ?dry_run + ?verbose_signing + ?simulation + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let save_contract ~force cctxt alias_name contract = + let open Lwt_result_syntax in + let* () = Raw_contract_alias.add ~force cctxt alias_name contract in + let*! () = message_added_contract cctxt alias_name in + return_unit + +let build_origination_operation ?fee ?gas_limit ?storage_limit ~initial_storage + ~code ~delegate ~balance () = + (* With the change of making implicit accounts delegatable, the following + 3 arguments are being defaulted before they can be safely removed. *) + let open Lwt_result_syntax in + let result = Michelson_v1_parser.parse_expression initial_storage in + let*? {Michelson_v1_parser.expanded = storage; _} = + Micheline_parser.no_parsing_error result + in + let code = Script.lazy_expr code and storage = Script.lazy_expr storage in + let origination = + Origination {delegate; script = {code; storage}; credit = balance} + in + return + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + origination) + +let originate_contract (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?branch ?fee ?gas_limit ?safety_guard ?storage_limit + ~delegate ~initial_storage ~balance ~source ~src_pk ~src_sk ~code + ~fee_parameter () = + let open Lwt_result_syntax in + let* origination = + build_origination_operation + ?fee + ?gas_limit + ?storage_limit + ~initial_storage + ~code + ~delegate + ~balance + () + in + let origination = Annotated_manager_operation.Single_manager origination in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?branch + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + origination + in + let res = + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + (oph, op, result) + in + let*? contracts = Injection.originated_contracts ~force:false result in + match contracts with + | [contract] -> return (res, Contract.Originated contract) + | contracts -> + failwith + "The origination introduced %d contracts instead of one." + (List.length contracts) + +let michelson_expression_of_string str = + let open Result_syntax in + let* {Michelson_v1_parser.expanded = v; _} = + Michelson_v1_parser.parse_expression str + |> Micheline_parser.no_parsing_error + in + return (Script.lazy_expr v) + +let build_register_global_constant ?fee ?gas_limit ?storage_limit value = + let open Result_syntax in + let* value = michelson_expression_of_string value in + let op = Register_global_constant {value} in + return + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + op) + +let register_global_constant (cctxt : #full) ~chain ~block ?confirmations + ?dry_run ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard + ?storage_limit ?counter ~source ~src_pk ~src_sk ~fee_parameter ~constant () + = + let open Lwt_result_syntax in + let*? op = + build_register_global_constant ?fee ?storage_limit ?gas_limit constant + in + let op = Annotated_manager_operation.Single_manager op in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +type activation_key = { + pkh : Signature.Ed25519.Public_key_hash.t; + amount : Tez.t; + activation_code : Blinded_public_key_hash.activation_code; + mnemonic : string list; + password : string; + email : string; +} + +let raw_activation_key_encoding = + let open Data_encoding in + obj6 + (req "pkh" Signature.Ed25519.Public_key_hash.encoding) + (req "amount" Tez.encoding) + (req "activation_code" Blinded_public_key_hash.activation_code_encoding) + (req "mnemonic" (list string)) + (req "password" string) + (req "email" string) + +let activation_key_encoding = + (* Hack: allow compatibility with older encoding *) + let open Data_encoding in + conv + (fun {pkh; amount; activation_code; mnemonic; password; email} -> + (pkh, amount, activation_code, mnemonic, password, email)) + (fun (pkh, amount, activation_code, mnemonic, password, email) -> + {pkh; amount; activation_code; mnemonic; password; email}) + @@ splitted + ~binary:raw_activation_key_encoding + ~json: + (union + [ + case + ~title:"Activation" + Json_only + raw_activation_key_encoding + (fun x -> Some x) + (fun x -> x); + case + ~title:"Deprecated_activation" + Json_only + (obj6 + (req "pkh" Signature.Ed25519.Public_key_hash.encoding) + (req "amount" Tez.encoding) + (req + "secret" + Blinded_public_key_hash.activation_code_encoding) + (req "mnemonic" (list string)) + (req "password" string) + (req "email" string)) + (fun _ -> None) + (fun x -> x); + ]) + +type batch_transfer_operation = { + destination : string; + fee : string option; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; + amount : string; + arg : string option; + entrypoint : Entrypoint.t option; +} + +let batch_transfer_operation_encoding = + let open Data_encoding in + conv + (fun {destination; fee; gas_limit; storage_limit; amount; arg; entrypoint} -> + (destination, fee, gas_limit, storage_limit, amount, arg, entrypoint)) + (fun (destination, fee, gas_limit, storage_limit, amount, arg, entrypoint) -> + {destination; fee; gas_limit; storage_limit; amount; arg; entrypoint}) + (obj7 + (req "destination" string) + (opt "fee" string) + (opt "gas-limit" Gas.Arith.n_integral_encoding) + (opt "storage-limit" z) + (req "amount" string) + (opt "arg" string) + (opt "entrypoint" Entrypoint.simple_encoding)) + +let read_key key = + let open Lwt_result_syntax in + match Bip39.of_words key.mnemonic with + | None -> failwith "" + | Some t -> + (* TODO: unicode normalization (NFKD)... *) + let passphrase = + Bytes.(cat (of_string key.email) (of_string key.password)) + in + let sk = Bip39.to_seed ~passphrase t in + let sk = Bytes.sub sk 0 32 in + let sk : Signature.Secret_key.t = + Ed25519 + (Data_encoding.Binary.of_bytes_exn + Signature.Ed25519.Secret_key.encoding + sk) + in + let pk = Signature.Secret_key.to_public_key sk in + let pkh = Signature.Public_key.hash pk in + return (pkh, pk, sk) + +let inject_activate_operation cctxt ~chain ~block ?confirmations ?dry_run alias + pkh activation_code = + let contents = Single (Activate_account {id = pkh; activation_code}) in + let open Lwt_result_syntax in + let* oph, op, result = + Injection.inject_operation + cctxt + ?confirmations + ?dry_run + ~chain + ~block + contents + in + let* () = + match confirmations with + | None -> return_unit + | Some _confirmations -> + let* balance = + Alpha_services.Contract.balance + cctxt + (chain, block) + (Contract.Implicit (Ed25519 pkh)) + in + let*! () = + cctxt#message + "Account %s (%a) activated with %s%a." + alias + Signature.Ed25519.Public_key_hash.pp + pkh + Operation_result.tez_sym + Tez.pp + balance + in + return_unit + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Activate_account _ as op), result) -> + return (oph, op, result) + +let activate_account (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?(encrypted = false) ?force key name = + let open Lwt_result_syntax in + let* pkh, pk, sk = read_key key in + let* () = + fail_unless + (Signature.Public_key_hash.equal pkh (Ed25519 key.pkh)) + (error_of_fmt + "@[Inconsistent activation key:@ Computed pkh: %a@ Embedded pkh: \ + %a @]" + Signature.Public_key_hash.pp + pkh + Signature.Ed25519.Public_key_hash.pp + key.pkh) + in + let pk = Signature.Of_V1.public_key pk in + let sk = Signature.Of_V1.secret_key sk in + let*? pk_uri = Tezos_signer_backends.Unencrypted.make_pk pk in + let* sk_uri = + if encrypted then + Tezos_signer_backends.Encrypted.prompt_twice_and_encrypt cctxt sk + else + let*? sk_uri = Tezos_signer_backends.Unencrypted.make_sk sk in + return sk_uri + in + let* () = Client_keys.register_key cctxt ?force (pkh, pk_uri, sk_uri) name in + inject_activate_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + name + key.pkh + key.activation_code + +let activate_existing_account (cctxt : #full) ~chain ~block ?confirmations + ?dry_run alias activation_code = + let open Lwt_result_syntax in + let* keys_opt = Client_keys.alias_keys cctxt alias in + match keys_opt with + | Some (Ed25519 pkh, _, _) -> + inject_activate_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + alias + pkh + activation_code + | Some _ -> failwith "Only Ed25519 accounts can be activated" + | None -> failwith "Unknown account" + +type period_info = { + current_period_kind : Voting_period.kind; + position : Int32.t; + remaining : Int32.t; + current_proposal : Protocol_hash.t option; +} + +type ballots_info = { + current_quorum : Int32.t; + participation : Int32.t; + supermajority : Int64.t; + ballots : Vote.ballots; +} + +let get_ballots_info (cctxt : #full) ~chain ~block = + (* Get the next level, not the current *) + let open Lwt_result_syntax in + let cb = (chain, block) in + let* ballots = Alpha_services.Voting.ballots cctxt cb in + let* current_quorum = Alpha_services.Voting.current_quorum cctxt cb in + let* max_participation = Alpha_services.Voting.total_voting_power cctxt cb in + let all_votes = Int64.(add (add ballots.yay ballots.nay) ballots.pass) in + let participation = + Z.( + to_int32 + (div + (mul (of_int64 all_votes) (of_int 100_00)) + (of_int64 max_participation))) + in + let supermajority = Int64.(div (mul 8L (add ballots.yay ballots.nay)) 10L) in + return {current_quorum; participation; supermajority; ballots} + +let get_period_info ?(successor = false) (cctxt : #full) ~chain ~block = + let open Lwt_result_syntax in + let cb = (chain, block) in + let* voting_period = + if successor then Alpha_services.Voting.successor_period cctxt cb + else Alpha_services.Voting.current_period cctxt cb + in + let* current_proposal = Alpha_services.Voting.current_proposal cctxt cb in + return + { + current_period_kind = voting_period.voting_period.kind; + position = voting_period.position; + remaining = voting_period.remaining; + current_proposal; + } + +let get_proposals (cctxt : #full) ~chain ~block = + let cb = (chain, block) in + Alpha_services.Voting.proposals cctxt cb + +let submit_proposals ?dry_run ?verbose_signing (cctxt : #full) ~chain ~block + ?confirmations ~src_sk source proposals = + let open Lwt_result_syntax in + let* {voting_period = {index; _}; _} = + Alpha_services.Voting.successor_period cctxt (chain, block) + in + let contents = Single (Proposals {source; period = index; proposals}) in + Injection.inject_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ~src_sk + contents + ?verbose_signing + +let submit_ballot ?dry_run ?verbose_signing (cctxt : #full) ~chain ~block + ?confirmations ~src_sk source proposal ballot = + (* The user must provide the proposal explicitly to make himself sure + for what he is voting. *) + let open Lwt_result_syntax in + let* {voting_period = {index; _}; _} = + Alpha_services.Voting.successor_period cctxt (chain, block) + in + let contents = Single (Ballot {source; period = index; proposal; ballot}) in + Injection.inject_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ~src_sk + contents + ?verbose_signing + +let pp_operation formatter (a : Alpha_block_services.operation) = + match (a.receipt, a.protocol_data) with + | Receipt (Apply_results.Operation_metadata omd), Operation_data od -> ( + match Apply_results.kind_equal_list od.contents omd.contents with + | Some Apply_results.Eq -> + Operation_result.pp_operation_result + formatter + (od.contents, omd.contents) + | None -> Stdlib.failwith "Unexpected result.") + | Empty, _ -> + Stdlib.failwith + "Pruned metadata: the operation receipt was removed accordingly to the \ + node's history mode." + | Too_large, _ -> Stdlib.failwith "Too large metadata." + | _ -> Stdlib.failwith "Unexpected result." + +let get_operation_from_block (cctxt : #full) ~chain predecessors operation_hash + = + let open Lwt_result_syntax in + let* block_opt = + Client_confirmations.lookup_operation_in_previous_blocks + cctxt + ~chain + ~predecessors + operation_hash + in + match block_opt with + | None -> return_none + | Some (block, i, j) -> + let*! () = + cctxt#message + "Operation found in block: %a (pass: %d, offset: %d)" + Block_hash.pp + block + i + j + in + let* op' = + Protocol_client_context.Alpha_block_services.Operations.operation + cctxt + ~chain + ~block:(`Hash (block, 0)) + i + j + in + return_some op' + +let display_receipt_for_operation (cctxt : #full) ~chain ?(predecessors = 10) + operation_hash = + let open Lwt_result_syntax in + let* operation_opt = + get_operation_from_block cctxt ~chain predecessors operation_hash + in + match operation_opt with + | None -> failwith "Couldn't find operation" + | Some op -> + let*! () = cctxt#message "%a" pp_operation op in + return_unit + +let cached_contracts cctxt ~chain ~block = + let cb = (chain, block) in + Alpha_services.Cache.cached_contracts cctxt cb + +let contract_rank cctxt ~chain ~block contract = + let cb = (chain, block) in + Alpha_services.Cache.contract_rank cctxt cb contract + +let contract_cache_size cctxt ~chain ~block = + let cb = (chain, block) in + Alpha_services.Cache.contract_cache_size cctxt cb + +let contract_cache_size_limit cctxt ~chain ~block = + let cb = (chain, block) in + Alpha_services.Cache.contract_cache_size_limit cctxt cb + +let transfer_ticket (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~src_pk ~src_sk ~fee_parameter ~contents ~ty ~ticketer + ~amount ~destination ~entrypoint () = + let open Lwt_result_syntax in + let* {expanded; _} = parse_expression contents in + let contents = Script.lazy_expr expanded in + let* {expanded; _} = parse_expression ty in + let ty = Script.lazy_expr expanded in + let operation : + Kind.transfer_ticket Annotated_manager_operation.annotated_list = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Transfer_ticket + {contents; ty; ticketer; amount; destination; entrypoint})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~successor_level:true + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + operation + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_originate (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ?whitelist ~source ~kind ~boot_sector ~parameters_ty ~src_pk + ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_add_messages (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~messages ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_add_messages {messages})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_cement (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~rollup ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_cement {rollup})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_publish (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~rollup ~commitment ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_publish {rollup; commitment})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_execute_outbox_message (cctxt : #full) ~chain ~block + ?confirmations ?dry_run ?verbose_signing ?simulation ?fee ?gas_limit + ?safety_guard ?storage_limit ?counter ~source ~rollup ~cemented_commitment + ~output_proof ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_recover_bond (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~src_pk ~src_sk ~fee_parameter ~sc_rollup ~staker () = + let open Lwt_result_syntax in + let contents : + Kind.sc_rollup_recover_bond Annotated_manager_operation.annotated_list = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_recover_bond {sc_rollup; staker})) + in + (* TODO/Fixme: https://gitlab.com/tezos/tezos/-/issues/2609 + Decide if we should enforce ~successor_level:true for simulation. + See https://gitlab.com/tezos/tezos/-/merge_requests/5395#note_958326685 *) + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + contents + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_refute (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~rollup ~refutation ~opponent ~src_pk ~src_sk + ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_refute {rollup; refutation; opponent})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let sc_rollup_timeout (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~rollup ~alice ~bob ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let stakers = Sc_rollup.Game.Index.make alice bob in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Sc_rollup_timeout {rollup; stakers})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let get_smart_rollup_ticket_balance (rpc : #rpc_context) ~chain ~block contract + key = + Plugin.RPC.Sc_rollup.get_ticket_balance rpc (chain, block) contract key + +let zk_rollup_originate (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~public_parameters ~circuits_info ~init_state ~nb_ops + ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let zk_rollup_publish (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~zk_rollup ~ops ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Zk_rollup_publish {zk_rollup; ops})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let zk_rollup_update (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~zk_rollup ~update ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let op = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Zk_rollup_update {zk_rollup; update})) + in + let* oph, _, op, result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + op + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + +let dal_publish (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~source ~slot_header ~src_pk ~src_sk ~fee_parameter () = + let open Lwt_result_syntax in + let* oph, _, op, result = + Annotated_manager_operation.Single_manager + (Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + (Dal_publish_commitment slot_header)) + |> Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?counter + ~source + ~fee:(Limit.of_option fee) + ~storage_limit:(Limit.of_option storage_limit) + ~gas_limit:(Limit.of_option gas_limit) + ?safety_guard + ~src_pk + ~src_sk + ~fee_parameter + ~successor_level:true + in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) diff --git a/src/proto_020_PsParisC/lib_client/client_proto_context.mli b/src/proto_020_PsParisC/lib_client/client_proto_context.mli new file mode 100644 index 000000000000..cf4b7046e68f --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_context.mli @@ -0,0 +1,1018 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2024 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Calls {!Tezos_protocol_alpha.Protocol.Contract_services.list}. *) +val list_contract_labels : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + (string * string * string) list tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Contract.get_storage_normalized}. *) +val get_storage : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + unparsing_mode:Script_ir_unparser.unparsing_mode -> + Contract_hash.t -> + Script.expr option tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Contract.get_used_storage_space}. *) +val get_used_storage_space : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + Z.t option tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Contract.get_paid_storage_space}. *) +val get_paid_storage_space : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + Z.t option tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Contract_services.contract_big_map_get_opt}. *) +val get_contract_big_map_value : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + Script.expr * Script.expr -> + Script.expr option tzresult Lwt.t + +(** Calls {!Injection.prepare_manager_operation} + with [Register_global_constant constant] as operation. *) +val register_global_constant : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:Signature.public_key_hash -> + src_pk:Signature.public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + constant:string -> + unit -> + (Kind.register_global_constant Kind.manager Injection.result, tztrace) result + Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Big_map.big_map_get_normalized}. *) +val get_big_map_value : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + unparsing_mode:Script_ir_unparser.unparsing_mode -> + Big_map.Id.t -> + Script_expr_hash.t -> + Script.expr tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Contract.get_script_normalized}. *) +val get_script : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + unparsing_mode:Script_ir_unparser.unparsing_mode -> + normalize_types:bool -> + Contract_hash.t -> + Script.t option tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Contract_services.script_opt}. *) +val get_script_hash : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + Script_expr_hash.t option tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Contract_services.val-balance}. *) +val get_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Tez.t tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Contract_services.val-staked_balance}. *) +val get_staked_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Tez.t option tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Contract_services.val-full_balance}. *) +val get_full_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Tez.t tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Contract.get_ticket_balance}. *) +val get_contract_ticket_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + Ticket_token.unparsed_token -> + Z.t tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Contract.get_all_ticket_balances}. *) +val get_contract_all_ticket_balances : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + (Ticket_token.unparsed_token * Z.t) list tzresult Lwt.t + +val ticket_balances_encoding : + (Ticket_token.unparsed_token * Z.t) list Data_encoding.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Delegate_services.val-frozen_deposits_limit}. *) +val get_frozen_deposits_limit : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Signature.Public_key_hash.t -> + Tez.t option tzresult Lwt.t + +(** Calls {!Injection.prepare_manager_operation} + with {!Alpha_context.Delegation} [delegate_opt] as operation. *) +val build_delegate_operation : + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + public_key_hash option -> + Kind.delegation Annotated_manager_operation.t + +(** Calls {!Injection.inject_manager_operation} + with {!Annotated_manager_operation.Single_manager} [build_delegate_operation ?fee opt_delegate] + as operation. *) +val set_delegate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + public_key_hash -> + src_pk:public_key -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + public_key_hash option -> + Kind.delegation Kind.manager Injection.result tzresult Lwt.t + +val update_consensus_key : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + consensus_pk:Signature.public_key -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + Signature.public_key -> + Kind.update_consensus_key Kind.manager Injection.result tzresult Lwt.t + +val drain_delegate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + consensus_sk:Client_keys.sk_uri -> + consensus_pkh:Signature.public_key_hash -> + ?destination:Signature.public_key_hash -> + delegate:Signature.public_key_hash -> + unit -> + Kind.drain_delegate Injection.result tzresult Lwt.t + +(** Calls {!Injection.inject_manager_operation} + with {!Annotated_manager_operation.Single_manager} {!Alpha_context.Set_deposits_limit} [limit_opt] + as operation. *) +val set_deposits_limit : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + public_key_hash -> + src_pk:public_key -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + Tez.t option -> + Kind.set_deposits_limit Kind.manager Injection.result tzresult Lwt.t + +(** Calls {!Injection.inject_manager_operation} + with {!Annotated_manager_operation.Single_manager} {!Alpha_context.Increase_paid_storage} + [{amount_in_bytes; destination}] as operation. *) +val increase_paid_storage : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?force:bool -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?fee:Tez.t -> + ?confirmations:int -> + ?simulation:bool -> + source:public_key_hash -> + destination:Contract_hash.t -> + src_pk:public_key -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + amount_in_bytes:Z.t -> + unit -> + Kind.increase_paid_storage Kind.manager Injection.result tzresult Lwt.t + +(** Same as {!set_delegate} but the [~source] argument of {!Injection.inject_manager_operation} + is {!Signature.Public_key.hash} [src_pk]. *) +val register_as_delegate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?fee:Tez.t -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + ?consensus_pk:public_key -> + public_key -> + (Kind.delegation Kind.manager Injection.result + * (Kind.update_consensus_key Kind.manager contents + * Kind.update_consensus_key Kind.manager Apply_results.contents_result) + option) + tzresult + Lwt.t + +(** Calls {!Raw_contract_alias.add}. *) +val save_contract : + force:bool -> + #Protocol_client_context.full -> + string -> + Contract.t -> + unit tzresult Lwt.t + +(** Injects the origination of a script into the context. + See {!Injection.inject_manager_operation} for the injection, and + {!Protocol.Alpha_context.Origination} for the origination parameters. *) +val originate_contract : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + delegate:public_key_hash option -> + initial_storage:string -> + balance:Tez.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + code:Script.expr -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.origination Kind.manager Injection.result * Contract.t) tzresult Lwt.t + +(** Calls {!Michelson_v1_parser.parse_expression arg}. *) +val parse_arg_transfer : string option -> Script.lazy_expr tzresult Lwt.t + +(** Calls {!Injection.prepare_manager_operation} + with {!Alpha_context.Transaction} [{amount;parameters;destinations;entrypoint}] + as operation. *) +val build_transaction_operation : + amount:Tez.t -> + parameters:Script.lazy_expr -> + ?entrypoint:Entrypoint.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + Contract.t -> + Kind.transaction Annotated_manager_operation.t + +(** Same as {!transfer}, but takes parameters as {!Script.lazy_expr} instead of + a raw string. This can be useful for commands that elaborate Micheline parameters, + such as Multisigs or FA1.2 operations. *) +val transfer_with_script : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?force:bool -> + ?branch:int -> + ?successor_level:bool -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + destination:Contract.t -> + ?entrypoint:Entrypoint.t -> + parameters:Script.lazy_expr -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + fee_parameter:Injection.fee_parameter -> + ?replace_by_fees:bool -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t + +(** Calls {!Injection.inject_manager_operation} + with {!Annotated_manager_operation.Single_manager} + [build_transaction_operation + ~amount ~parameters ~entrypoint ?fee ?gas_limit ?storage_limit destination] + as contents. *) +val transfer : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?force:bool -> + ?branch:int -> + ?successor_level:bool -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + destination:Contract.t -> + ?entrypoint:Entrypoint.t -> + ?arg:string -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + fee_parameter:Injection.fee_parameter -> + ?replace_by_fees:bool -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t + +(** Calls {!Injection.prepare_manager_operation} with [Reveal pk] as [operation] *) +val build_reveal_operation : + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + public_key -> + Kind.reveal Annotated_manager_operation.t + +(** Calls {!Injection.inject_manager_operation} + with {!Annotated_manager_operation.Single_manager} + [build_reveal_operation ?fee ~storage_limit:Z.zero src_pk] + as contents. *) +val reveal : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + ?fee:Tez.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + Kind.reveal Kind.manager Injection.result tzresult Lwt.t + +type activation_key = { + pkh : Signature.Ed25519.Public_key_hash.t; + amount : Tez.t; + activation_code : Blinded_public_key_hash.activation_code; + mnemonic : string list; + password : string; + email : string; +} + +val activation_key_encoding : activation_key Data_encoding.t + +type batch_transfer_operation = { + destination : string; + fee : string option; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; + amount : string; + arg : string option; + entrypoint : Entrypoint.t option; +} + +val batch_transfer_operation_encoding : batch_transfer_operation Data_encoding.t + +(** Activate an account, by calling {!Injection.inject_operation}. *) +val activate_account : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?encrypted:bool -> + ?force:bool -> + activation_key -> + string -> + Kind.activate_account Injection.result tzresult Lwt.t + +(** Activate an existing account, + by calling {!Injection.inject_operation} with [activation code]. + It fails if the account is unknown or if the account is not [Signature.Ed25519]. *) +val activate_existing_account : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + string -> + Blinded_public_key_hash.activation_code -> + Kind.activate_account Injection.result tzresult Lwt.t + +type period_info = { + current_period_kind : Voting_period.kind; + position : Int32.t; + remaining : Int32.t; + current_proposal : Protocol_hash.t option; +} + +type ballots_info = { + current_quorum : Int32.t; + participation : Int32.t; + supermajority : Int64.t; + ballots : Vote.ballots; +} + +(** [get_period_info ~successor cctx ~chain ~block] returns the successor [period_info] if [successor], + it returns the current [period_info] otherwise. + This function uses {!Tezos_protocol_alpha.Protocol.Voting_services.successor_period} if [successor], + otherwise it calls {!Tezos_protocol_alpha.Protocol.Voting_services.current_period}. + In any case, it also uses {!Tezos_protocol_alpha.Protocol.Voting_services.current_proposal} +*) +val get_period_info : + ?successor:bool -> + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + period_info tzresult Lwt.t + +(** [get_ballots_info cctx ~chain ~block] returns the [ballots_info]. + It calls {!Tezos_protocol_alpha.Protocol.Voting_services.ballots}, + {!Tezos_protocol_alpha.Protocol.Voting_services.current_quorum} + and {!Tezos_protocol_alpha.Protocol.Voting_services.total_voting_power}. +*) +val get_ballots_info : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ballots_info tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Voting_services.proposals} *) +val get_proposals : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Int64.t Environment.Protocol_hash.Map.t tzresult Lwt.t + +(** Calls {!Injection.inject_operation} + where [contents] is {!Alpha_context.Single} [(Proposals {source; period = index; proposals})] + with [index] the result of {!Alpha_services.Voting.successor_period} *) +val submit_proposals : + ?dry_run:bool -> + ?verbose_signing:bool -> + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + src_sk:Client_keys.sk_uri -> + public_key_hash -> + Protocol_hash.t list -> + Kind.proposals Injection.result_list tzresult Lwt.t + +(** Calls {!Injection.inject_operation} + where [contents] is {!Alpha_context.Single} [(Ballot {source; period = index; proposals})] + with [index] the result of {!Alpha_services.Voting.successor_period} *) +val submit_ballot : + ?dry_run:bool -> + ?verbose_signing:bool -> + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + src_sk:Client_keys.sk_uri -> + public_key_hash -> + Protocol_hash.t -> + Vote.ballot -> + Kind.ballot Injection.result_list tzresult Lwt.t + +(** lookup an operation in [predecessors] previous blocks, and print the + receipt if found *) +val display_receipt_for_operation : + #Protocol_client_context.full -> + chain:Block_services.chain -> + ?predecessors:int -> + Operation_list_hash.elt -> + unit tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Alpha_services.Cache.cached_contracts} *) +val cached_contracts : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + (Contract_hash.t * int) list tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Alpha_services.Cache.contract_rank} *) +val contract_rank : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + int option tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Alpha_services.Cache.contract_cache_size} *) +val contract_cache_size : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + int tzresult Lwt.t + +(** Calls {!Tezos_protocol_alpha.Protocol.Alpha_services.Cache.contract_cache_size_limit} *) +val contract_cache_size_limit : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + int tzresult Lwt.t + +val transfer_ticket : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:Signature.public_key_hash -> + src_pk:Signature.public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + contents:string -> + ty:string -> + ticketer:Contract.t -> + amount:Ticket_amount.t -> + destination:Contract.t -> + entrypoint:Entrypoint.t -> + unit -> + (Operation_hash.t + * Kind.transfer_ticket Kind.manager contents + * Kind.transfer_ticket Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup origination operation using + {!Injection.inject_operation}. + + Originates a smart rollup of [kind] with the [boot_sector] using + [paramaters_ty]. Generates a unique smart rollup address returned + in the operation's receipt. + + This is the only entry-point to create a smart rollup. +*) +val sc_rollup_originate : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + ?whitelist:Sc_rollup.Whitelist.t -> + source:public_key_hash -> + kind:Sc_rollup.Kind.t -> + boot_sector:string -> + parameters_ty:Script.lazy_expr -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_originate Kind.manager contents + * Kind.sc_rollup_originate Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup add messages operation using + {!Injection.inject_operation}. + + Adds external messages to the smart rollup inbox shared with all + smart rollups. +*) +val sc_rollup_add_messages : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + messages:string list -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_add_messages Kind.manager contents + * Kind.sc_rollup_add_messages Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup cement commitment operation using + {!Injection.inject_operation}. + + Cements a [commitment] for the smart rollup [rollup]. The commitment + now becomes unrefutable and we can execute outbox messages for the + committed PVM state (see {!sc_rollup_execute_outbox_message}). +*) +val sc_rollup_cement : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + rollup:Alpha_context.Sc_rollup.t -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_cement Kind.manager contents + * Kind.sc_rollup_cement Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup publish commitment operation using + {!Injection.inject_operation}. + + Publishes a [commitment] to announces the PVM state at the end of + a commitment period and the number of ticks executed. + If it is the first time [src_pk] publishes a commitment, a bond + is frozen. +*) +val sc_rollup_publish : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + rollup:Alpha_context.Sc_rollup.t -> + commitment:Alpha_context.Sc_rollup.Commitment.t -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_publish Kind.manager contents + * Kind.sc_rollup_publish Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup execute outbox message operation using + {!Injection.inject_operation}. + + Executes [output_proof] on the PVM commited state from the + [cemented_commitment]. Allows to perform L2->L1 communication. +*) +val sc_rollup_execute_outbox_message : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + rollup:Sc_rollup.t -> + cemented_commitment:Sc_rollup.Commitment.Hash.t -> + output_proof:string -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_execute_outbox_message Kind.manager contents + * Kind.sc_rollup_execute_outbox_message Kind.manager + Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup recover bond operation using + {!Injection.inject_operation}. + + Allows to recover the bond frozen by the operation {!sc_rollup_publish} + of [src_pk], if the commitment is no longer subject to refutations. +*) +val sc_rollup_recover_bond : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:Signature.public_key_hash -> + src_pk:Signature.public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + sc_rollup:Sc_rollup.t -> + staker:public_key_hash -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_recover_bond Kind.manager contents + * Kind.sc_rollup_recover_bond Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup refutation operation using + {!Injection.inject_operation}. + + Either start a refutation game between [src_pk] and [oppononent] or + plays a move in an existing refutation game. +*) +val sc_rollup_refute : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + rollup:Alpha_context.Sc_rollup.t -> + refutation:Alpha_context.Sc_rollup.Game.refutation -> + opponent:Alpha_context.Sc_rollup.Staker.t -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_refute Kind.manager contents + * Kind.sc_rollup_refute Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Injects a smart-contract rollup timeout operation using + {!Injection.inject_operation}. + + Timeouts the absent player from the refutation game between [alice] + and [bob]. +*) +val sc_rollup_timeout : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + rollup:Alpha_context.Sc_rollup.t -> + alice:Alpha_context.Sc_rollup.Staker.t -> + bob:Alpha_context.Sc_rollup.Staker.t -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.sc_rollup_timeout Kind.manager contents + * Kind.sc_rollup_timeout Kind.manager Apply_results.contents_result) + tzresult + Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Sc_rollup.get_ticket_balance}. *) +val get_smart_rollup_ticket_balance : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Sc_rollup.t -> + Ticket_token.unparsed_token -> + Z.t tzresult Lwt.t + +val zk_rollup_originate : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + public_parameters:Environment.Plonk.public_parameters -> + circuits_info:[`Fee | `Private | `Public] Zk_rollup.Account.SMap.t -> + init_state:Bls12_381.Fr.t array -> + nb_ops:int -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + ( Operation_hash.t + * Kind.zk_rollup_origination Kind.manager contents + * Kind.zk_rollup_origination Kind.manager Apply_results.contents_result, + tztrace ) + result + Lwt.t + +val zk_rollup_publish : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + zk_rollup:Zk_rollup.t -> + ops:(Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + ( Operation_hash.t + * Kind.zk_rollup_publish Kind.manager contents + * Kind.zk_rollup_publish Kind.manager Apply_results.contents_result, + tztrace ) + result + Lwt.t + +val zk_rollup_update : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + zk_rollup:Zk_rollup.t -> + update:Zk_rollup.Update.t -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + ( Operation_hash.t + * Kind.zk_rollup_update Kind.manager contents + * Kind.zk_rollup_update Kind.manager Apply_results.contents_result, + tztrace ) + result + Lwt.t + +(** Injects a DAL publish commitment operation using + {!Injection.inject_operation}. +*) +val dal_publish : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + source:public_key_hash -> + slot_header:Alpha_context.Dal.Operations.Publish_commitment.t -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Operation_hash.t + * Kind.dal_publish_commitment Kind.manager contents + * Kind.dal_publish_commitment Kind.manager Apply_results.contents_result) + tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_contracts.ml b/src/proto_020_PsParisC/lib_client/client_proto_contracts.ml new file mode 100644 index 000000000000..0b880123c786 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_contracts.ml @@ -0,0 +1,263 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2024 Trilitech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Contract_entity = struct + include Contract (* t, Compare, encoding *) + + let of_source s = + Contract.of_b58check s |> Environment.wrap_tzresult + |> record_trace_eval (fun () -> error_of_fmt "bad contract notation") + |> Lwt.return + + let to_source s = + let open Lwt_result_syntax in + return (Contract.to_b58check s) + + let name = "contract" +end + +module Raw_contract_alias = Client_aliases.Alias (Contract_entity) + +module Originated_contract_alias = struct + let find cctxt s = + let open Lwt_result_syntax in + let* contract_opt = Raw_contract_alias.find_opt cctxt s in + match contract_opt with + | Some (Contract.Originated v) -> return v + | Some (Implicit _) -> failwith "contract %s is an implicit account" s + | None -> failwith "no contract named %s" s + + let of_literal s = + let open Lwt_result_syntax in + let*! contract_opt = Contract_entity.of_source s in + match contract_opt with + | Ok (Contract.Originated v) -> return v + | Ok (Implicit _) -> failwith "contract %s is an implicit account" s + | Error _ as err -> Lwt.return err + + let find_destination cctxt s = + let open Lwt_result_syntax in + match String.split ~limit:1 ':' s with + | ["alias"; alias] -> find cctxt alias + | ["text"; text] -> of_literal text + | _ -> ( + let*! contract_hash_opt = of_literal s in + match contract_hash_opt with + | Ok _ as ok_v -> Lwt.return ok_v + | Error k_errs -> ( + let*! contract_hash_opt = find cctxt s in + Lwt.return + @@ + match contract_hash_opt with + | Ok _ as ok_v -> ok_v + | Error c_errs -> Error (c_errs @ k_errs))) + + let destination_parameter () = + Tezos_clic.parameter + ~autocomplete:Raw_contract_alias.autocomplete + find_destination + + let destination_param ?(name = "dst") ?(desc = "destination contract") next = + let desc = + String.concat + "\n" + [ + desc; + "Can be a literal or an alias (autodetected in order).\n\ + Use 'text:' or 'alias:' to force."; + ] + in + Tezos_clic.param ~name ~desc (destination_parameter ()) next + + let destination_arg ?(name = "dst") ?(doc = "destination contract") () = + let doc = + String.concat + "\n" + [ + doc; + "Can be a literal or an alias (autodetected in order).\n\ + Use 'text:' or 'alias:' to force."; + ] + in + Tezos_clic.arg ~long:name ~doc ~placeholder:name (destination_parameter ()) +end + +module Contract_alias = struct + let find cctxt s = + let open Lwt_result_syntax in + let* contract_opt = Raw_contract_alias.find_opt cctxt s in + match contract_opt with + | Some v -> return v + | None -> ( + let* pkh_opt = Client_keys.Public_key_hash.find_opt cctxt s in + match pkh_opt with + | Some v -> return (Contract.Implicit v) + | None -> failwith "no contract or key named %s" s) + + let find_key cctxt name = + let open Lwt_result_syntax in + let* v = Client_keys.Public_key_hash.find cctxt name in + return (Contract.Implicit v) + + let rev_find cctxt (c : Contract.t) = + let open Lwt_result_syntax in + match c with + | Implicit hash -> ( + let* str_opt = Client_keys.Public_key_hash.rev_find cctxt hash in + match str_opt with + | Some name -> return_some ("key:" ^ name) + | None -> return_none) + | Originated _ -> Raw_contract_alias.rev_find cctxt c + + let get_contract cctxt s = + match String.split ~limit:1 ':' s with + | ["key"; key] -> find_key cctxt key + | _ -> find cctxt s + + let autocomplete cctxt = + let open Lwt_result_syntax in + let* keys = Client_keys.Public_key_hash.autocomplete cctxt in + let* contracts = Raw_contract_alias.autocomplete cctxt in + return (List.map (( ^ ) "key:") keys @ contracts) + + let alias_param ?(name = "name") ?(desc = "existing contract alias") next = + let desc = + desc ^ "\n" + ^ "Can be a contract alias or a key alias (autodetected in order).\n\ + Use 'key:' to force the later." + in + Tezos_clic.(param ~name ~desc (parameter ~autocomplete get_contract) next) + + let find_destination cctxt s = + let open Lwt_result_syntax in + match String.split ~limit:1 ':' s with + | ["alias"; alias] -> find cctxt alias + | ["key"; text] -> + let* v = Client_keys.Public_key_hash.find cctxt text in + return (Contract.Implicit v) + | ["text"; text] -> Contract_entity.of_source text + | _ -> ( + let*! contract_opt = Contract_entity.of_source s in + match contract_opt with + | Ok v -> return v + | Error c_errs -> ( + let*! contract_opt = find cctxt s in + match contract_opt with + | Ok v -> return v + | Error k_errs -> Lwt.return_error (c_errs @ k_errs))) + + let destination_parameter () = + let open Lwt_result_syntax in + Tezos_clic.parameter + ~autocomplete:(fun cctxt -> + let* list1 = autocomplete cctxt in + let* list2 = Client_keys.Public_key_hash.autocomplete cctxt in + return (list1 @ list2)) + find_destination + + let destination_param ?(name = "dst") ?(desc = "destination contract") next = + let desc = + String.concat + "\n" + [ + desc; + "Can be a literal, an alias, or a key (autodetected in order).\n\ + Use 'text:', 'alias:', 'key:' to force."; + ] + in + Tezos_clic.param ~name ~desc (destination_parameter ()) next + + let destination_arg ?(name = "dst") ?(doc = "destination contract") () = + let doc = + String.concat + "\n" + [ + doc; + "Can be a literal, an alias, or a key (autodetected in order).\n\ + Use 'text:', 'alias:', 'key:' to force."; + ] + in + Tezos_clic.arg ~long:name ~doc ~placeholder:name (destination_parameter ()) + + let name cctxt contract = + let open Lwt_result_syntax in + let* str_opt = rev_find cctxt contract in + match str_opt with + | None -> return (Contract.to_b58check contract) + | Some name -> return name +end + +module Destination_alias = struct + let contract_parameter () = + Tezos_clic.map_parameter + ~f:(fun c -> Destination.Contract c) + (Contract_alias.destination_parameter ()) + + let smart_rollup_parameter () = + Tezos_clic.map_parameter + ~f:(fun sc -> Destination.Sc_rollup sc) + (Smart_rollup_alias.Address.parameter ()) + + let destination_parameter () = + Tezos_clic.compose_parameters + (contract_parameter ()) + (smart_rollup_parameter ()) + + let destination_param ?(name = "dst") ?(desc = "destination address") next = + let desc = + String.concat + "\n" + [ + desc; + "Can be a literal, an alias, or a key (autodetected in order).\n\ + Use 'text:', 'alias:', 'key:' to force."; + ] + in + Tezos_clic.param ~name ~desc (destination_parameter ()) next +end + +let list_contracts cctxt = + let open Lwt_result_syntax in + let* raw_contracts = Raw_contract_alias.load cctxt in + let contracts = List.map (fun (n, v) -> ("", n, v)) raw_contracts in + let* keys = Client_keys.Public_key_hash.load cctxt in + (* List accounts (implicit contracts of identities) *) + let* accounts = + List.map_es + (fun (n, v) -> + let* mem = Raw_contract_alias.mem cctxt n in + let p = if mem then "key:" else "" in + let v' = Contract.Implicit v in + return (p, n, v')) + keys + in + return (contracts @ accounts) + +let get_delegate cctxt ~chain ~block source = + Alpha_services.Contract.delegate_opt cctxt (chain, block) source diff --git a/src/proto_020_PsParisC/lib_client/client_proto_contracts.mli b/src/proto_020_PsParisC/lib_client/client_proto_contracts.mli new file mode 100644 index 000000000000..a342408ec37e --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_contracts.mli @@ -0,0 +1,108 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2024 Trilitech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Raw_contract_alias : Client_aliases.Alias with type t = Contract.t + +(** Like [Contract_alias] below but restricted to originated contracts. *) +module Originated_contract_alias : sig + val find_destination : + #Client_context.wallet -> string -> Contract_hash.t tzresult Lwt.t + + val destination_param : + ?name:string -> + ?desc:string -> + ('a, (#Client_context.wallet as 'wallet)) Tezos_clic.params -> + (Contract_hash.t -> 'a, 'wallet) Tezos_clic.params + + val destination_arg : + ?name:string -> + ?doc:string -> + unit -> + (Contract_hash.t option, #Client_context.wallet) Tezos_clic.arg +end + +module Contract_alias : sig + val get_contract : + #Client_context.wallet -> string -> Contract.t tzresult Lwt.t + + val alias_param : + ?name:string -> + ?desc:string -> + ('a, (#Client_context.wallet as 'wallet)) Tezos_clic.params -> + (Contract.t -> 'a, 'wallet) Tezos_clic.params + + val find_destination : + #Client_context.wallet -> string -> Contract.t tzresult Lwt.t + + val destination_param : + ?name:string -> + ?desc:string -> + ('a, (#Client_context.wallet as 'wallet)) Tezos_clic.params -> + (Contract.t -> 'a, 'wallet) Tezos_clic.params + + val destination_arg : + ?name:string -> + ?doc:string -> + unit -> + (Contract.t option, #Client_context.wallet) Tezos_clic.arg + + val rev_find : + #Client_context.wallet -> Contract.t -> string option tzresult Lwt.t + + val name : #Client_context.wallet -> Contract.t -> string tzresult Lwt.t + + val autocomplete : #Client_context.wallet -> string list tzresult Lwt.t +end + +module Destination_alias : sig + val destination_parameter : + unit -> (Destination.t, #Client_context.wallet) Tezos_clic.parameter + + val destination_param : + ?name:string -> + ?desc:string -> + ('a, (#Client_context.wallet as 'wallet)) Tezos_clic.params -> + (Destination.t -> 'a, 'wallet) Tezos_clic.params +end + +(** [list_contracts cctxt] returns the concatenation of [contracts] and [accounts] + where [contracts] is the result of [Raw_contract_alias.load cctxt] + and [accounts] the list of accounts (implicit contracts of identities) +*) +val list_contracts : + #Client_context.wallet -> + (string * string * Raw_contract_alias.t) list tzresult Lwt.t + +(** Calls {!Alpha_services.Contract.delegate_opt} *) +val get_delegate : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract.t -> + public_key_hash option tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_fa12.ml b/src/proto_020_PsParisC/lib_client/client_proto_fa12.ml new file mode 100644 index 000000000000..31292feb0800 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_fa12.ml @@ -0,0 +1,1023 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context +open Tezos_micheline + +type error += Contract_has_no_script of Contract_hash.t + +type error += Contract_has_no_storage of Contract.t + +type error += Entrypoint_mismatch of string * (Script.expr * Script.expr) option + +type error += Action_unwrapping_error of string * Script.expr + +type error += Not_a_viewable_entrypoint of Entrypoint.t + +type error += Not_an_entrypoint of Script.expr + +type error += Not_enough_balance of Z.t * Z.t + +type error += Not_enough_allowance of Z.t * Z.t + +type error += Unsafe_allowance_change of Z.t + +type error += Unexpected_error of Script.location * Script.expr + +let entrypoint_mismatch_explanation ppf (name, ty) = + match ty with + | None -> Format.fprintf ppf "Entrypoint %s is missing" name + | Some (ty, expected) -> + Format.fprintf + ppf + "Entrypoint \"%s\" has type @[%a@], but should have type @[%a@]" + name + Michelson_v1_printer.print_expr + ty + Michelson_v1_printer.print_expr + expected + +let () = + register_error_kind + `Permanent + ~id:"fa12ContractHasNoScript" + ~title:"The given contract is not a smart contract" + ~description:"An FA1.2 command has referenced a scriptless contract." + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "Contract %a is not a smart contract, it has no script." + Contract_hash.pp + contract) + Data_encoding.(obj1 (req "contract" Contract.originated_encoding)) + (function Contract_has_no_script c -> Some c | _ -> None) + (fun c -> Contract_has_no_script c) ; + register_error_kind + `Permanent + ~id:"fa12ContractHasNoStorage" + ~title:"The given contract has no storage" + ~description: + "An FA1.2 command made a call on a contract that has no storage." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract %a has no storage." Contract.pp contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Contract_has_no_storage c -> Some c | _ -> None) + (fun c -> Contract_has_no_storage c) ; + register_error_kind + `Permanent + ~id:"entrypointMismatch" + ~title:"The given contract does not implement the FA1.2 interface" + ~description: + "An FA1.2 command has referenced a smart contract whose script does not \ + implement at least one FA1.2 entrypoint, or with an incompatible type. \ + See TZIP-7 \ + (https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-7/tzip-7.md) \ + for documentation on FA1.2." + ~pp:(fun ppf (name, ty) -> + Format.fprintf + ppf + "Not a supported FA1.2 contract.@\n%a." + entrypoint_mismatch_explanation + (name, ty)) + Data_encoding.( + obj2 + (req "name" string) + (req "type" (option (tup2 Script.expr_encoding Script.expr_encoding)))) + (function Entrypoint_mismatch (n, t) -> Some (n, t) | _ -> None) + (fun (n, t) -> Entrypoint_mismatch (n, t)) ; + register_error_kind + `Permanent + ~id:"actionUnwrappingError" + ~title:"The argument is not for an FA1.2 parameter" + ~description: + "The argument's type does not correspond to that of the corresponding \ + FA1.2 entrypoint." + ~pp:(fun ppf (entrypoint, expr) -> + Format.fprintf + ppf + "Not a supported FA1.2 entrypoint argument.@\nEntrypoint: %s@\n%a." + entrypoint + Michelson_v1_printer.print_expr + expr) + Data_encoding.( + obj2 (req "entrypoint" string) (req "expr" Script.expr_encoding)) + (function Action_unwrapping_error (s, e) -> Some (s, e) | _ -> None) + (fun (s, e) -> Action_unwrapping_error (s, e)) ; + register_error_kind + `Permanent + ~id:"notAViewableEntrypoint" + ~title:"The entrypoint is not viewable" + ~description: + "A transaction made a call on an entrypoint expecting it to implement \ + the 'view' type." + ~pp:(fun ppf entrypoint -> + Format.fprintf + ppf + "Entrypoint %a is not viewable." + Entrypoint.pp + entrypoint) + Data_encoding.(obj1 (req "entrypoint" Entrypoint.simple_encoding)) + (function Not_a_viewable_entrypoint e -> Some e | _ -> None) + (fun e -> Not_a_viewable_entrypoint e) ; + register_error_kind + `Permanent + ~id:"notAnEntrypoint" + ~title:"The expression is not for an entrypoint" + ~description: + "The parameter value of the contract call refers to a non-existing \ + entrypoint." + ~pp:(fun ppf param -> + Format.fprintf + ppf + "Not a parameter for an entrypoint.@\n%a." + Michelson_v1_printer.print_expr + param) + Data_encoding.(obj1 (req "param" Script.expr_encoding)) + (function Not_an_entrypoint e -> Some e | _ -> None) + (fun e -> Not_an_entrypoint e) ; + register_error_kind + `Permanent + ~id:"notEnoughBalance" + ~title:"The sender does not have enough balance" + ~description: + "An FA1.2 transfer failed because the sender does not have enough \ + balance." + ~pp:(fun ppf (required, present) -> + Format.fprintf + ppf + "Not enough balance.@\nRequired: %a.@\nPresent: %a." + Z.pp_print + required + Z.pp_print + present) + Data_encoding.(obj2 (req "present" n) (req "required" n)) + (function Not_enough_balance (p, r) -> Some (p, r) | _ -> None) + (fun (p, r) -> Not_enough_balance (p, r)) ; + register_error_kind + `Permanent + ~id:"notEnoughAllowance" + ~title:"The sender does not have enough allowance" + ~description: + "An FA1.2 transfer failed because the receiver does not have enough \ + allowance to ask for a transfer from the sender." + ~pp:(fun ppf (required, present) -> + Format.fprintf + ppf + "Not enough allowance.@\nRequired: %a.@\nPresent: %a." + Z.pp_print + required + Z.pp_print + present) + Data_encoding.(obj2 (req "present" n) (req "required" n)) + (function Not_enough_allowance (p, r) -> Some (p, r) | _ -> None) + (fun (p, r) -> Not_enough_allowance (p, r)) ; + register_error_kind + `Permanent + ~id:"unsafeAllowanceChange" + ~title:"The allowance change is unsafe" + ~description: + "An FA1.2 non-zero allowance change failed because the current allowance \ + is non-zero. For more explanation on why such allowance change is \ + unsafe, please look at TZIP-7 \ + (https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-7/tzip-7.md#approve)." + ~pp:(fun ppf previous -> + Format.fprintf + ppf + "Unsafe allowance change@\nPrevious: %a." + Z.pp_print + previous) + Data_encoding.(obj1 (req "previous" n)) + (function Unsafe_allowance_change p -> Some p | _ -> None) + (fun p -> Unsafe_allowance_change p) ; + register_error_kind + `Permanent + ~id:"fa12UnexpectedError" + ~title:"Unexpected error during FA1.2 contract interpretation" + ~description: + "An unexpected Michelson error was reached during the interpretation of \ + an FA1.2 contract." + ~pp:(fun ppf (loc, expr) -> + Format.fprintf + ppf + "An unexpected error was reached at location %d with: %a." + loc + Michelson_v1_printer.print_expr + expr) + Data_encoding.( + obj2 + (req "location" Script.location_encoding) + (req "value" Script.expr_encoding)) + (function Unexpected_error (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Unexpected_error (loc, expr)) + +let callback_encoding = + Data_encoding.( + conv + (fun (c, e) -> (c, Option.value ~default:"" e)) + (fun (c, e) -> (c, if String.equal e "" then None else Some e)) + (tup2 Contract.encoding Variable.string)) + +(** Michelson combinators *) + +let pair ~loc a b = Micheline.Prim (loc, Script.D_Pair, [a; b], []) + +let nat ~loc i = Micheline.Int (loc, i) + +let unit ~loc = Micheline.Prim (loc, Script.D_Unit, [], []) + +let bytes ~loc b = Micheline.Bytes (loc, b) + +let address ~loc addr = + bytes ~loc (Data_encoding.Binary.to_bytes_exn Contract.encoding addr) + +let callback ~loc ?entrypoint addr = + bytes + ~loc + (Data_encoding.Binary.to_bytes_exn callback_encoding (addr, entrypoint)) + +(** Types *) + +(** Michelson type combinators: produce a Michelson node of the + expected type, and a function to check another node is + syntactically equivalent. *) +type type_eq_combinator = Script.node * (Script.node -> bool) + +(** [t_pair ~loc l] takes a list of types and respective equivalence + check functions, and returns a type of n-ary pair of such types and + a function checking syntactical equivalence with another node. *) +let t_pair ~loc l : type_eq_combinator = + let values, are_ty = List.split l in + let is_pair p = + match p with + | Micheline.Prim (_, Script.T_pair, l, _) -> ( + let res = + List.for_all2 + ~when_different_lengths:() + (fun is_ty v -> is_ty v) + are_ty + l + in + match res with Ok b -> b | Error () -> false) + | _ -> false + in + (Micheline.Prim (loc, Script.T_pair, values, []), is_pair) + +(** [t_unit ~loc] returns a Micheline node for the `unit` type, and + a function checking another node is syntactically equivalent. *) +let t_unit ~loc : type_eq_combinator = + let is_unit p = + match p with Micheline.Prim (_, Script.T_unit, [], _) -> true | _ -> false + in + (Micheline.Prim (loc, Script.T_unit, [], []), is_unit) + +(** [t_nat ~loc] returns a Micheline node for the `nat` type, and + a function checking another node is syntactically equivalent. *) +let t_nat ~loc : type_eq_combinator = + let is_nat p = + match p with Micheline.Prim (_, Script.T_nat, [], _) -> true | _ -> false + in + (Micheline.Prim (loc, Script.T_nat, [], []), is_nat) + +(** [t_address ~loc] returns a Micheline node for the `address` + type, and a function checking another node is syntactically + equivalent. *) +let t_address ~loc : type_eq_combinator = + let is_address p = + match p with + | Micheline.Prim (_, Script.T_address, [], _) -> true + | _ -> false + in + (Micheline.Prim (loc, Script.T_address, [], []), is_address) + +(** [t_contract ~loc (c, is_c)] takes a node representing a Michelson + type and its own syntactical equivalence checker, and returns a + Micheline node for the type `contract c`, and a function checking + another node is syntactically equivalent. *) +let t_contract ~loc (a, is_a) : type_eq_combinator = + let is_contract c = + match c with + | Micheline.Prim (_, Script.T_contract, [a], _) -> is_a a + | _ -> false + in + (Micheline.Prim (loc, Script.T_contract, [a], []), is_contract) + +(** [t_view ~loc a b] takes two node [a] and [b] and their syntactical + equivalence checking functions, and returns a Micheline node for + the `view a b` type, and a function checking another node is + syntactically equivalent. The view type is defined by + [TZIP4](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-4/tzip-4.md). + *) +let t_view ~loc a b : type_eq_combinator = t_pair ~loc [a; t_contract ~loc b] + +(** * Actions *) + +(** Corresponds to + [TZIP7](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-7/tzip-7.md) + entrypoints. *) + +(** A callback from a view can be on a specific entrypoint of the + contract, or the default one if not specified. *) +type callback_contract = Contract.t * string option + +type action = + | Transfer of Contract.t * Contract.t * Z.t + | Approve of Contract.t * Z.t + | Get_allowance of Contract.t * Contract.t * callback_contract + | Get_balance of Contract.t * callback_contract + | Get_total_supply of callback_contract + +let print_callback_contract ppf (c, etp) = + Format.fprintf + ppf + "%a%s" + Contract.pp + c + (match etp with None | Some "" -> "" | Some etp -> "%" ^ etp) + +let print_action ppf = function + | Transfer (src, dst, amount) -> + Format.fprintf + ppf + "Transfer (%a, %a, %a)" + Contract.pp + src + Contract.pp + dst + Z.pp_print + amount + | Approve (addr, amount) -> + Format.fprintf ppf "Approve (%a, %a)" Contract.pp addr Z.pp_print amount + | Get_allowance (src, dst, callback) -> + Format.fprintf + ppf + "Get_allowance (%a, %a, %a)" + Contract.pp + src + Contract.pp + dst + print_callback_contract + callback + | Get_balance (addr, callback) -> + Format.fprintf + ppf + "Get_balance (%a, %a)" + Contract.pp + addr + print_callback_contract + callback + | Get_total_supply callback -> + Format.fprintf + ppf + "Get_total_supply (%a)" + print_callback_contract + callback + +let transfer_encoding = + Data_encoding.( + case + ~title:"transfer" + (Tag 0) + (obj3 + (req "transfer_source" Contract.encoding) + (req "transfer_destination" Contract.encoding) + (req "transfer_amount" n)) + (function + | Transfer (src, dst, amount) -> Some (src, dst, amount) | _ -> None) + (fun (src, dst, amount) -> Transfer (src, dst, amount))) + +let approve_encoding = + Data_encoding.( + case + ~title:"approve" + (Tag 1) + (obj2 (req "approve_address" Contract.encoding) (req "approve_amount" n)) + (function Approve (addr, amount) -> Some (addr, amount) | _ -> None) + (fun (addr, amount) -> Approve (addr, amount))) + +let getBalance_encoding = + Data_encoding.( + case + ~title:"getBalance" + (Tag 2) + (obj2 + (req "getBalance_address" Contract.encoding) + (req "getBalance_callback" callback_encoding)) + (function + | Get_balance (addr, callback) -> Some (addr, callback) | _ -> None) + (fun (addr, callback) -> Get_balance (addr, callback))) + +let getAllowance_encoding = + Data_encoding.( + case + ~title:"getAllowance" + (Tag 3) + (obj3 + (req "getAllowance_source" Contract.encoding) + (req "getAllowance_destination" Contract.encoding) + (req "getAllowance_callback" callback_encoding)) + (function + | Get_allowance (src, dst, callback) -> Some (src, dst, callback) + | _ -> None) + (fun (src, dst, callback) -> Get_allowance (src, dst, callback))) + +let getTotalSupply_encoding = + Data_encoding.( + case + ~title:"getTotalSupply" + (Tag 4) + (obj1 (req "getTotalSupply_callback" callback_encoding)) + (function Get_total_supply callback -> Some callback | _ -> None) + (fun callback -> Get_total_supply callback)) + +let action_encoding = + Data_encoding.union + [ + transfer_encoding; + approve_encoding; + getBalance_encoding; + getAllowance_encoding; + getTotalSupply_encoding; + ] + +let transfer_type ~loc = + t_pair ~loc [t_address ~loc; t_address ~loc; t_nat ~loc] + +let approve_type ~loc = t_pair ~loc [t_address ~loc; t_nat ~loc] + +let getAllowance_type ~loc = + t_view ~loc (t_pair ~loc [t_address ~loc; t_address ~loc]) (t_nat ~loc) + +let getBalance_type ~loc = t_view ~loc (t_address ~loc) (t_nat ~loc) + +let getTotalSupply_type ~loc = t_view ~loc (t_unit ~loc) (t_nat ~loc) + +let standard_entrypoints = + let loc = -1 in + [ + ("transfer", transfer_type ~loc); + ("approve", approve_type ~loc); + ("getAllowance", getAllowance_type ~loc); + ("getBalance", getBalance_type ~loc); + ("getTotalSupply", getTotalSupply_type ~loc); + ] + +let view_input ~loc action = + match action with + | Get_allowance (source, destination, _) -> + pair ~loc (address ~loc source) (address ~loc destination) + | Get_balance (addr, _) -> address ~loc addr + | Get_total_supply _ -> unit ~loc + | _ -> unit ~loc + +let action_to_expr ~loc action = + match action with + | Transfer (source, destination, amount) -> + pair + ~loc + (address ~loc source) + (pair ~loc (address ~loc destination) (nat ~loc amount)) + | Approve (addr, amount) -> pair ~loc (address ~loc addr) (nat ~loc amount) + | Get_allowance (_, _, (cb, entrypoint)) -> + let input = view_input ~loc action in + pair ~loc input (callback ~loc ?entrypoint cb) + | Get_balance (_, (cb, entrypoint)) -> + let input = view_input ~loc action in + pair ~loc input (callback ~loc ?entrypoint cb) + | Get_total_supply (cb, entrypoint) -> + let input = view_input ~loc action in + pair ~loc input (callback ~loc ?entrypoint cb) + +let parse_address error = + let open Result_syntax in + function + | Micheline.Bytes (_, b) -> + return @@ Data_encoding.Binary.of_bytes_exn Contract.encoding b + | String (_, s) -> ( + match Contract.of_b58check s with Ok c -> return c | Error _ -> error ()) + | _ -> error () + +let parse_callback error expr = + let of_b58_check (c, entrypoint) = + match Contract.of_b58check c with + | Ok c -> Ok (c, entrypoint) + | Error _ -> error () + in + match expr with + | Micheline.Bytes (_, b) -> ( + match Data_encoding.Binary.of_bytes callback_encoding b with + | Ok (c, entrypoint) -> Ok (c, entrypoint) + | Error _ -> error ()) + | String (_, s) -> ( + match String.index_opt s '%' with + | None -> of_b58_check (s, None) + | Some pos -> ( + let len = String.length s - pos - 1 in + let name = String.sub s (pos + 1) len in + match (String.sub s 0 pos, name) with + | addr, "default" -> of_b58_check (addr, None) + | addr, name -> of_b58_check (addr, Some name))) + | _ -> error () + +let action_of_expr ~entrypoint expr = + let open Result_syntax in + let open Micheline in + let error () = + tzfail + (Action_unwrapping_error (entrypoint, Micheline.strip_locations expr)) + in + match (entrypoint, expr) with + (* Transfer operation before comb pairs. *) + | ( "transfer", + Prim + ( _, + Script.D_Pair, + [ + ((Bytes (_, _) | String (_, _)) as source); + Prim + ( _, + Script.D_Pair, + [ + ((Bytes (_, _) | String (_, _)) as destination); + Int (_, amount); + ], + _ ); + ], + _ ) ) + (* Transfer operation since Edo comb pairs are now directly interpreted as a + tuple of 3 elements instead of a pair inside a pair. *) + | ( "transfer", + Prim + ( _, + Script.D_Pair, + [ + ((Bytes (_, _) | String (_, _)) as source); + ((Bytes (_, _) | String (_, _)) as destination); + Int (_, amount); + ], + _ ) ) -> + let* source = parse_address error source in + let* destination = parse_address error destination in + return (Transfer (source, destination, amount)) + | ( "approve", + Prim + ( _, + Script.D_Pair, + [((Bytes (_, _) | String (_, _)) as addr); Int (_, amount)], + _ ) ) -> + let* addr = parse_address error addr in + return (Approve (addr, amount)) + | ( "getBalance", + Prim + ( _, + Script.D_Pair, + [ + ((Bytes (_, _) | String (_, _)) as addr); + ((Bytes (_, _) | String (_, _)) as cb); + ], + _ ) ) -> + let* addr = parse_address error addr in + let* callback = parse_callback error cb in + return (Get_balance (addr, callback)) + | ( "getAllowance", + Prim + ( _, + Script.D_Pair, + [ + Prim + ( _, + Script.D_Pair, + [ + ((Bytes (_, _) | String (_, _)) as source); + ((Bytes (_, _) | String (_, _)) as destination); + ], + _ ); + ((Bytes (_, _) | String (_, _)) as contract); + ], + _ ) ) -> + let* source = parse_address error source in + let* destination = parse_address error destination in + let* callback = parse_callback error contract in + return (Get_allowance (source, destination, callback)) + | ( "getTotalSupply", + Prim + ( _, + Script.D_Pair, + [ + Prim (_, Script.D_Unit, [], _); + ((Bytes (_, _) | String (_, _)) as contract); + ], + _ ) ) -> + let* callback = parse_callback error contract in + return (Get_total_supply callback) + | _ -> error () + +let find_entrypoint_in_annot error annots expr = + match List.find_opt (fun annot -> annot.[0] = '%') annots with + | Some entrypoint -> + action_of_expr + ~entrypoint:(String.sub entrypoint 1 (String.length entrypoint - 1)) + expr + | None -> error () + +let derive_action expr t_param = + let error () = + Result_syntax.tzfail (Not_an_entrypoint (Micheline.strip_locations expr)) + in + let rec derive expr t_param = + match (expr, t_param) with + | ( Micheline.Prim (_, Script.D_Left, [left], _), + Micheline.Prim (_, Script.T_or, [t_left; _], _) ) -> + derive left t_left + | ( Micheline.Prim (_, Script.D_Right, [right], _), + Micheline.Prim (_, Script.T_or, [_; t_right], _) ) -> + derive right t_right + | _, Micheline.Prim (_, _, _, annots) -> + find_entrypoint_in_annot error annots expr + | _ -> error () + in + derive expr t_param + +let extract_parameter contract = + let open Result_syntax in + function + | Micheline.Seq (_, l) -> ( + List.filter_map + (function + | Micheline.Prim (_, Script.K_parameter, [param], _) -> Some param + | _ -> None) + l + |> function + | param :: _ -> return param + | _ -> tzfail (Contract_has_no_script contract)) + | _ -> tzfail (Contract_has_no_script contract) + +let get_contract_parameter cctxt ~chain ~block contract = + let open Lwt_result_syntax in + let* script_opt = + Client_proto_context.get_script + cctxt + ~chain + ~block + contract + ~unparsing_mode:Optimized + ~normalize_types:true + in + match script_opt with + | None -> tzfail (Contract_has_no_script contract) + | Some {code; _} -> ( + match Script_repr.force_decode code with + | Error _ -> tzfail (Contract_has_no_script contract) + | Ok code -> Lwt.return (extract_parameter contract (Micheline.root code)) + ) + +let convert_wrapped_parameter_into_action cctxt ~chain ~block contract param = + let open Lwt_result_syntax in + let* parameter = get_contract_parameter cctxt ~chain ~block contract in + Lwt.return (derive_action param parameter) + +let check_entrypoint entrypoints (name, (expected_ty, check)) = + let open Result_syntax in + match List.assoc_opt ~equal:String.equal name entrypoints with + | None -> tzfail (Entrypoint_mismatch (name, None)) + | Some ty -> + if not (check (Micheline.root ty)) then + tzfail + (Entrypoint_mismatch + (name, Some (ty, Micheline.strip_locations expected_ty))) + else return_unit + +let action_to_entrypoint = + let transfer = Entrypoint.of_string_strict_exn "transfer" in + let approve = Entrypoint.of_string_strict_exn "approve" in + let get_allowance = Entrypoint.of_string_strict_exn "getAllowance" in + let get_balance = Entrypoint.of_string_strict_exn "getBalance" in + let get_total_supply = Entrypoint.of_string_strict_exn "getTotalSupply" in + function + | Transfer (_, _, _) -> transfer + | Approve (_, _) -> approve + | Get_allowance (_, _, _) -> get_allowance + | Get_balance (_, _) -> get_balance + | Get_total_supply _ -> get_total_supply + +let contract_has_fa12_interface : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + contract:Contract_hash.t -> + unit -> + unit tzresult Lwt.t = + let open Lwt_result_syntax in + fun cctxt ~chain ~block ~contract () -> + let* entrypoints = + Michelson_v1_entrypoints.list_contract_entrypoints + cctxt + ~chain + ~block + ~contract + ~normalize_types:true + in + let*? () = + List.iter_e (check_entrypoint entrypoints) standard_entrypoints + in + return_unit + +let translate_action_to_argument action = + let entrypoint = action_to_entrypoint action in + let expr = + Micheline.strip_locations (action_to_expr ~loc:() action) + |> Script.lazy_expr + in + (entrypoint, expr) + +let parse_error = + let open Micheline in + function + | ( "NotEnoughBalance", + Prim (_, Script.D_Pair, [Int (_, required); Int (_, present)], _) ) -> + Some (Not_enough_balance (required, present)) + | ( "NotEnoughAllowance", + Prim (_, Script.D_Pair, [Int (_, required); Int (_, present)], _) ) -> + Some (Not_enough_allowance (required, present)) + | "UnsafeAllowanceChange", Int (_, previous) -> + Some (Unsafe_allowance_change previous) + | _ -> None + +let extract_error trace = + let open Micheline in + TzTrace.fold + (fun _ error -> + match error with + | Environment.Ecoproto_error (Script_interpreter.Reject (loc, param, _)) + -> ( + match root param with + | Prim (_, Script.D_Pair, [String (_, error); res], _) -> + parse_error (error, res) + | _ -> Some (Unexpected_error (loc, param))) + | _ -> None) + None + trace + +let call_contract (cctxt : #Protocol_client_context.full) ~chain ~block + ?confirmations ?dry_run ?verbose_signing ?branch ~source ~src_pk ~src_sk + ~contract ~action ~tez_amount ?fee ?gas_limit ?safety_guard ?storage_limit + ?counter ~fee_parameter () = + let open Lwt_result_syntax in + let* () = contract_has_fa12_interface cctxt ~chain ~block ~contract () in + let entrypoint, parameters = translate_action_to_argument action in + let*! result = + Client_proto_context.transfer_with_script + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?branch + ~source + ~src_pk + ~src_sk + ~destination:(Originated contract) + ~parameters + ~amount:tez_amount + ~entrypoint + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + ?verbose_signing + () + in + match result with + | Ok res -> return res + | Error trace -> ( + match extract_error trace with + | None -> Lwt.return (Error trace) + | Some error -> tzfail error) + +type token_transfer = { + token_contract : string; + destination : string; + amount : Z.t; + tez_amount : string option; + fee : string option; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; +} + +let token_transfer_encoding = + let open Data_encoding in + conv + (fun { + token_contract; + destination; + amount; + tez_amount; + fee; + gas_limit; + storage_limit; + } -> + ( token_contract, + destination, + amount, + tez_amount, + fee, + gas_limit, + storage_limit )) + (fun ( token_contract, + destination, + amount, + tez_amount, + fee, + gas_limit, + storage_limit ) -> + { + token_contract; + destination; + amount; + tez_amount; + fee; + gas_limit; + storage_limit; + }) + (obj7 + (req "token_contract" string) + (req "destination" string) + (req "amount" z) + (opt "tez-amount" string) + (opt "fee" string) + (opt "gas-limit" Gas.Arith.n_integral_encoding) + (opt "storage-limit" z)) + +let tez_of_string_exn index field s = + match Tez.of_string s with + | Some t -> Ok t + | None -> + error_with + "Invalid %s notation at entry %i, field \"%s\": %s" + Operation_result.tez_sym + index + field + s + +let tez_of_opt_string_exn index field s = + Option.map_e (tez_of_string_exn index field) s + +let build_transaction_operation ?(tez_amount = Tez.zero) ?fee ?gas_limit + ?storage_limit token action = + let entrypoint = action_to_entrypoint action in + let parameters = + Script.lazy_expr (Micheline.strip_locations (action_to_expr ~loc:() action)) + in + let operation = + Transaction + {amount = tez_amount; parameters; destination = token; entrypoint} + in + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + operation + +let prepare_single_token_transfer cctxt ?default_fee ?default_gas_limit + ?default_storage_limit ~chain ~block src index transfer = + let open Lwt_result_syntax in + let* token = + Client_proto_contracts.Originated_contract_alias.find_destination + cctxt + transfer.token_contract + in + let* () = + contract_has_fa12_interface cctxt ~chain ~block ~contract:token () + in + let* dest = + Client_proto_contracts.Contract_alias.find_destination + cctxt + transfer.destination + in + let*? tez_amount = + tez_of_opt_string_exn index "tez_amount" transfer.tez_amount + in + let*? transfer_fee = tez_of_opt_string_exn index "fee" transfer.fee in + let fee = Option.either transfer_fee default_fee in + let gas_limit = Option.either transfer.gas_limit default_gas_limit in + let storage_limit = + Option.either transfer.storage_limit default_storage_limit + in + let action = Transfer (src, dest, transfer.amount) in + let operation = + build_transaction_operation + ?tez_amount + ?fee + ?gas_limit + ?storage_limit + (Originated token) + action + in + return (Annotated_manager_operation.Annotated_manager_operation operation) + +let inject_token_transfer_batch (cctxt : #Protocol_client_context.full) ~chain + ~block ?confirmations ?dry_run ?verbose_signing ~sender ~source ~src_pk + ~src_sk ~token_transfers ~fee_parameter ?counter ?default_fee + ?default_gas_limit ?default_storage_limit ?safety_guard () = + let open Lwt_result_syntax in + let* contents = + List.mapi_ep + (prepare_single_token_transfer + cctxt + ?default_fee + ?default_gas_limit + ?default_storage_limit + ~chain + ~block + sender) + token_transfers + in + let (Manager_list contents) = + Annotated_manager_operation.manager_of_list contents + in + let*! result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~source + ~fee:(Limit.of_option default_fee) + ~gas_limit:(Limit.of_option default_gas_limit) + ~storage_limit:(Limit.of_option default_storage_limit) + ?safety_guard + ?counter + ~src_pk + ~src_sk + ~fee_parameter + contents + in + match result with + | Ok _ -> return_unit + | Error trace -> ( + match extract_error trace with + | None -> Lwt.return (Error trace) + | Some error -> tzfail error) + +let is_viewable_action action = + let open Lwt_result_syntax in + match action with + | Get_balance (_, _) | Get_allowance (_, _, _) | Get_total_supply _ -> + return_unit + | _ -> tzfail (Not_a_viewable_entrypoint (action_to_entrypoint action)) + +let run_view_action (cctxt : #Protocol_client_context.full) ~chain ~block + ~sender ~contract ~action ~payer ~gas ~unparsing_mode () = + let open Lwt_result_syntax in + let* () = is_viewable_action action in + let* () = contract_has_fa12_interface cctxt ~chain ~block ~contract () in + let entrypoint = action_to_entrypoint action in + let input = Micheline.strip_locations (view_input ~loc:() action) in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + Plugin.RPC.Scripts.run_tzip4_view + cctxt + (chain, block) + ~contract + ~input + ~chain_id + ~sender + ~payer + ~gas + ~entrypoint + ~unparsing_mode + ~now:None + ~level:None + ~other_contracts:None + ~extra_big_maps:None + +let () = + Data_encoding.( + Registration.register + @@ def (Protocol.name ^ ".fa1.2.token_transfer") token_transfer_encoding) diff --git a/src/proto_020_PsParisC/lib_client/client_proto_fa12.mli b/src/proto_020_PsParisC/lib_client/client_proto_fa12.mli new file mode 100644 index 000000000000..d6711bace871 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_fa12.mli @@ -0,0 +1,164 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [Client_proto_fa12] implements built-in support for the + {{:https://gitlab.com/tzip/tzip/-/blob/master/proposals/tzip-7/tzip-7.md} + FA1.2} standard. This module features functions to check whether a + contract implements the standard interface and to interact with + such contracts using high-level [actions] that model the entrypoint + calls. + + This module also provides functions to unwrap [Micheline] values + into [actions], which can be useful for indexers or applications + using this module to interpret transactions on FA1.2 contracts as + FA1.2 operations. *) + +open Protocol +open Alpha_context +open Protocol_client_context + +(** A callback contract is represented by an address and a possible + entrypoint on which the transaction is done. *) +type callback_contract = Contract.t * string option + +type action = + | Transfer of Contract.t * Contract.t * Z.t + | Approve of Contract.t * Z.t + | Get_allowance of Contract.t * Contract.t * callback_contract + | Get_balance of Contract.t * callback_contract + | Get_total_supply of callback_contract + +val print_action : Format.formatter -> action -> unit + +val action_encoding : action Data_encoding.encoding + +val action_to_expr : + loc:'loc -> action -> ('loc, Script.prim) Tezos_micheline.Micheline.node + +val action_of_expr : + entrypoint:string -> + (_, Script.prim) Tezos_micheline.Micheline.node -> + action tzresult + +(** [convert_wrapped_parameter_into_action cctxt ~chain ~block + ~contract parameter] converts a wrapped FA1.2 contract [parameter] + into the corresponding FA1.2 [action]. + + That is, it takes a contract parameter on the form [C_1 .. (C_n + ... ))] where [C_1 ... C_n] is a sequence of + [Left]/[Right] constructors. It finds the entrypoint corresponding + to that path in [contract]'s interface. The result of the function + is the [] applied to the [action] + corresponding to that entrypoint. *) +val convert_wrapped_parameter_into_action : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Contract_hash.t -> + Script.node -> + action tzresult Lwt.t + +(** Check whether a contract has an FA1.2 interface. *) +val contract_has_fa12_interface : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + contract:Contract_hash.t -> + unit -> + unit tzresult Lwt.t + +val call_contract : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + contract:Contract_hash.t -> + action:action -> + tez_amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t + +(** Single transfer operation. *) +type token_transfer = { + token_contract : string; + destination : string; + amount : Z.t; + tez_amount : string option; + fee : string option; + gas_limit : Gas.Arith.integral option; + storage_limit : Z.t option; +} + +val token_transfer_encoding : token_transfer Data_encoding.t + +(** Inject a batch of token transfers. *) +val inject_token_transfer_batch : + full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + sender:Contract.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + token_transfers:token_transfer list -> + fee_parameter:Injection.fee_parameter -> + ?counter:Manager_counter.t -> + ?default_fee:Tez.t -> + ?default_gas_limit:Gas.Arith.integral -> + ?default_storage_limit:Z.t -> + ?safety_guard:Gas.Arith.integral -> + unit -> + unit tzresult Lwt.t + +(** Run the action without injecting it. Only for views. *) +val run_view_action : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + sender:Contract.t option -> + contract:Contract_hash.t -> + action:action -> + payer:Signature.public_key_hash option -> + gas:Gas.Arith.integral option -> + unparsing_mode:Script_ir_unparser.unparsing_mode -> + unit -> + Script.expr tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_multisig.ml b/src/proto_020_PsParisC/lib_client/client_proto_multisig.ml new file mode 100644 index 000000000000..8ae16dfcecbf --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_multisig.ml @@ -0,0 +1,1283 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context +open Michelson_v1_helpers + +type error += Contract_has_no_script of Contract_hash.t + +type error += Not_a_supported_multisig_contract of Script_expr_hash.t + +type error += Contract_has_no_storage of Contract_hash.t + +type error += Contract_has_unexpected_storage of Contract_hash.t + +type error += Invalid_signature of signature + +type error += Not_enough_signatures of int * int + +type error += Action_deserialisation_error of Script.expr + +type error += Bytes_deserialisation_error of Bytes.t + +type error += Bad_deserialized_contract of (Contract_hash.t * Contract_hash.t) + +type error += Bad_deserialized_counter of {received : Z.t; expected : Z.t} + +type error += Non_positive_threshold of int + +type error += Threshold_too_high of int * int + +type error += Unsupported_feature_generic_call of Script.expr + +type error += Unsupported_feature_generic_call_ty of Script.expr + +type error += Unsupported_feature_lambda of string + +type error += + | Ill_typed_argument of Contract.t * Entrypoint.t * Script.expr * Script.expr + +type error += Ill_typed_lambda of Script.expr * Script.expr + +let () = + register_error_kind + `Permanent + ~id:"contractHasNoScript" + ~title: + "The given contract is not a multisig contract because it has no script" + ~description: + "A multisig command has referenced a scriptless smart contract instead \ + of a multisig smart contract." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract has no script %a." Contract_hash.pp contract) + Data_encoding.(obj1 (req "contract" Contract.originated_encoding)) + (function Contract_has_no_script c -> Some c | _ -> None) + (fun c -> Contract_has_no_script c) ; + register_error_kind + `Permanent + ~id:"notASupportedMultisigContract" + ~title:"The given contract is not one of the supported contracts" + ~description: + "A multisig command has referenced a smart contract whose script is not \ + one of the known multisig contract scripts." + ~pp:(fun ppf hash -> + Format.fprintf + ppf + "Not a supported multisig contract.@\n\ + The hash of this script is %a, it was not found among in the list of \ + known multisig script hashes." + Script_expr_hash.pp + hash) + Data_encoding.(obj1 (req "hash" Script_expr_hash.encoding)) + (function Not_a_supported_multisig_contract h -> Some h | _ -> None) + (fun h -> Not_a_supported_multisig_contract h) ; + register_error_kind + `Permanent + ~id:"contractHasNoStorage" + ~title: + "The given contract is not a multisig contract because it has no storage" + ~description: + "A multisig command has referenced a smart contract without storage \ + instead of a multisig smart contract." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract has no storage %a." Contract_hash.pp contract) + Data_encoding.(obj1 (req "contract" Contract.originated_encoding)) + (function Contract_has_no_storage c -> Some c | _ -> None) + (fun c -> Contract_has_no_storage c) ; + register_error_kind + `Permanent + ~id:"contractHasUnexpectedStorage" + ~title: + "The storage of the given contract is not of the shape expected for a \ + multisig contract" + ~description: + "A multisig command has referenced a smart contract whose storage is of \ + a different shape than the expected one." + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "Contract has unexpected storage %a." + Contract_hash.pp + contract) + Data_encoding.(obj1 (req "contract" Contract.originated_encoding)) + (function Contract_has_unexpected_storage c -> Some c | _ -> None) + (fun c -> Contract_has_unexpected_storage c) ; + register_error_kind + `Permanent + ~id:"invalidSignature" + ~title: + "The following signature did not match a public key in the given \ + multisig contract" + ~description: + "A signature was given for a multisig contract that matched none of the \ + public keys of the contract signers" + ~pp:(fun ppf s -> + Format.fprintf ppf "Invalid signature %s." (Signature.to_b58check s)) + Data_encoding.(obj1 (req "invalid_signature" Signature.encoding)) + (function Invalid_signature s -> Some s | _ -> None) + (fun s -> Invalid_signature s) ; + register_error_kind + `Permanent + ~id:"notEnoughSignatures" + ~title:"Not enough signatures were provided for this multisig action" + ~description: + "To run an action on a multisig contract, you should provide at least as \ + many signatures as indicated by the threshold stored in the multisig \ + contract." + ~pp:(fun ppf (threshold, nsigs) -> + Format.fprintf + ppf + "Not enough signatures: only %d signatures were given but the \ + threshold is currently %d" + nsigs + threshold) + Data_encoding.(obj1 (req "threshold_nsigs" (tup2 int31 int31))) + (function + | Not_enough_signatures (threshold, nsigs) -> Some (threshold, nsigs) + | _ -> None) + (fun (threshold, nsigs) -> Not_enough_signatures (threshold, nsigs)) ; + register_error_kind + `Permanent + ~id:"actionDeserialisation" + ~title:"The expression is not a valid multisig action" + ~description: + "When trying to deserialise an action from a sequence of bytes, we got \ + an expression that does not correspond to a known multisig action" + ~pp:(fun ppf e -> + Format.fprintf + ppf + "Action deserialisation error %a." + Michelson_v1_printer.print_expr + e) + Data_encoding.(obj1 (req "expr" Script.expr_encoding)) + (function Action_deserialisation_error e -> Some e | _ -> None) + (fun e -> Action_deserialisation_error e) ; + register_error_kind + `Permanent + ~id:"bytesDeserialisation" + ~title:"The byte sequence is not a valid multisig action" + ~description: + "When trying to deserialise an action from a sequence of bytes, we got \ + an error" + ~pp:(fun ppf b -> + Format.fprintf ppf "Bytes deserialisation error %s." (Bytes.to_string b)) + Data_encoding.(obj1 (req "expr" bytes)) + (function Bytes_deserialisation_error b -> Some b | _ -> None) + (fun b -> Bytes_deserialisation_error b) ; + register_error_kind + `Permanent + ~id:"badDeserializedContract" + ~title:"The byte sequence is not for the given multisig contract" + ~description: + "When trying to deserialise an action from a sequence of bytes, we got \ + an action for another multisig contract" + ~pp:(fun ppf (received, expected) -> + Format.fprintf + ppf + "Bad deserialized contract, received %a expected %a." + Contract_hash.pp + received + Contract_hash.pp + expected) + Data_encoding.( + obj1 + (req + "received_expected" + (tup2 Contract.originated_encoding Contract.originated_encoding))) + (function Bad_deserialized_contract b -> Some b | _ -> None) + (fun b -> Bad_deserialized_contract b) ; + register_error_kind + `Permanent + ~id:"Bad deserialized counter" + ~title:"Deserialized counter does not match the stored one" + ~description: + "The byte sequence references a multisig counter that does not match the \ + one currently stored in the given multisig contract" + ~pp:(fun ppf (received, expected) -> + Format.fprintf + ppf + "Bad deserialized counter, received %d expected %d." + received + expected) + Data_encoding.(obj1 (req "received_expected" (tup2 int31 int31))) + (function + | Bad_deserialized_counter {received; expected} -> + Some (Z.to_int received, Z.to_int expected) + | _ -> None) + (fun (received, expected) -> + Bad_deserialized_counter + {received = Z.of_int received; expected = Z.of_int expected}) ; + register_error_kind + `Permanent + ~id:"thresholdTooHigh" + ~title:"Given threshold is too high" + ~description: + "The given threshold is higher than the number of keys, this would lead \ + to a frozen multisig contract" + ~pp:(fun ppf (threshold, nkeys) -> + Format.fprintf + ppf + "Threshold too high: %d expected at most %d." + threshold + nkeys) + Data_encoding.(obj1 (req "received_expected" (tup2 int31 int31))) + (function Threshold_too_high (c1, c2) -> Some (c1, c2) | _ -> None) + (fun (c1, c2) -> Threshold_too_high (c1, c2)) ; + register_error_kind + `Permanent + ~id:"nonPositiveThreshold" + ~title:"Given threshold is not positive" + ~description:"A multisig threshold should be a positive number" + ~pp:(fun ppf threshold -> + Format.fprintf ppf "Multisig threshold %d should be positive." threshold) + Data_encoding.(obj1 (req "threshold" int31)) + (function Non_positive_threshold t -> Some t | _ -> None) + (fun t -> Non_positive_threshold t) ; + register_error_kind + `Permanent + ~id:"unsupportedGenericMultisigFeature" + ~title:"Unsupported multisig feature: generic call" + ~description: + "This multisig contract does not feature calling contracts with arguments" + ~pp:(fun ppf arg -> + Format.fprintf + ppf + "This multisig contract can only transfer tokens to contracts of type \ + unit; calling a contract with argument %a is not supported." + Michelson_v1_printer.print_expr + arg) + Data_encoding.(obj1 (req "arg" Script.expr_encoding)) + (function Unsupported_feature_generic_call arg -> Some arg | _ -> None) + (fun arg -> Unsupported_feature_generic_call arg) ; + register_error_kind + `Permanent + ~id:"unsupportedGenericMultisigFeatureTy" + ~title:"Unsupported multisig feature: generic call to non-unit entrypoint" + ~description: + "This multisig contract does not feature calling contracts with arguments" + ~pp:(fun ppf ty -> + Format.fprintf + ppf + "This multisig contract can only transfer tokens to contracts of type \ + unit; calling a contract of type %a is not supported." + Michelson_v1_printer.print_expr + ty) + Data_encoding.(obj1 (req "ty" Script.expr_encoding)) + (function Unsupported_feature_generic_call_ty ty -> Some ty | _ -> None) + (fun ty -> Unsupported_feature_generic_call_ty ty) ; + register_error_kind + `Permanent + ~id:"unsupportedGenericMultisigLambda" + ~title:"Unsupported multisig feature: running lambda" + ~description:"This multisig contract does not feature running lambdas" + ~pp:(fun ppf lam -> + Format.fprintf + ppf + "This multisig contract has a fixed set of actions, it cannot run the \ + following lambda: %s." + lam) + Data_encoding.(obj1 (req "lam" string)) + (function Unsupported_feature_lambda lam -> Some lam | _ -> None) + (fun lam -> Unsupported_feature_lambda lam) ; + register_error_kind + `Permanent + ~id:"illTypedArgumentForMultisig" + ~title:"Ill-typed argument in multi-signed transfer" + ~description: + "The provided argument for a transfer from a multisig contract is \ + ill-typed" + ~pp:(fun ppf (destination, entrypoint, parameter_ty, parameter) -> + Format.fprintf + ppf + "The entrypoint %a of contract %a called from a multisig contract is \ + of type %a; the provided parameter %a is ill-typed." + Entrypoint.pp + entrypoint + Contract.pp + destination + Michelson_v1_printer.print_expr + parameter_ty + Michelson_v1_printer.print_expr + parameter) + Data_encoding.( + obj4 + (req "destination" Contract.encoding) + (req "entrypoint" Entrypoint.simple_encoding) + (req "parameter_ty" Script.expr_encoding) + (req "parameter" Script.expr_encoding)) + (function + | Ill_typed_argument (destination, entrypoint, parameter_ty, parameter) -> + Some (destination, entrypoint, parameter_ty, parameter) + | _ -> None) + (fun (destination, entrypoint, parameter_ty, parameter) -> + Ill_typed_argument (destination, entrypoint, parameter_ty, parameter)) ; + register_error_kind + `Permanent + ~id:"illTypedLambdaForMultisig" + ~title:"Ill-typed lambda for multi-signed transfer" + ~description: + "The provided lambda for a transfer from a multisig contract is ill-typed" + ~pp:(fun ppf (lam, exp) -> + Format.fprintf + ppf + "The provided lambda %a for multisig contract is ill-typed; %a is \ + expected." + Michelson_v1_printer.print_expr + lam + Michelson_v1_printer.print_expr + exp) + Data_encoding.( + obj2 (req "lam" Script.expr_encoding) (req "exp" Script.expr_encoding)) + (function Ill_typed_lambda (lam, exp) -> Some (lam, exp) | _ -> None) + (fun (lam, exp) -> Ill_typed_lambda (lam, exp)) + +(* The multisig contract script written by Arthur Breitman + https://github.com/murbard/smart-contracts/blob/abdb582d8f1fe7ba7eb15975867d8862cb70acfe/multisig/michelson/generic.tz *) +let multisig_script_string = + {| +parameter (or (unit %default) + (pair %main + (pair :payload + (nat %counter) # counter, used to prevent replay attacks + (or :action # payload to sign, represents the requested action + (lambda %operation unit (list operation)) + (pair %change_keys # change the keys controlling the multisig + (nat %threshold) # new threshold + (list %keys key)))) # new list of keys + (list %sigs (option signature)))); # signatures + +storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))) ; + +code + { + UNPAIR ; + IF_LEFT + { # Default entry point: do nothing + # This entry point can be used to send tokens to this contract + DROP ; NIL operation ; PAIR } + { # Main entry point + # Assert no token was sent: + # to send tokens, the default entry point should be used + PUSH mutez 0 ; AMOUNT ; ASSERT_CMPEQ ; + SWAP ; DUP ; DIP { SWAP } ; + DIP + { + UNPAIR ; + # pair the payload with the current contract address, to ensure signatures + # can't be replayed across different contracts if a key is reused. + DUP ; SELF ; ADDRESS ; CHAIN_ID ; PAIR ; PAIR ; + PACK ; # form the binary payload that we expect to be signed + DIP { UNPAIR @counter ; DIP { SWAP } } ; SWAP + } ; + + # Check that the counters match + UNPAIR @stored_counter; DIP { SWAP }; + ASSERT_CMPEQ ; + + # Compute the number of valid signatures + DIP { SWAP } ; UNPAIR @threshold @keys; + DIP + { + # Running count of valid signatures + PUSH @valid nat 0; SWAP ; + ITER + { + DIP { SWAP } ; SWAP ; + IF_CONS + { + IF_SOME + { SWAP ; + DIP + { + SWAP ; DIP 2 { DUP 2 } ; + # Checks signatures, fails if invalid + { DUP 3; DIP {CHECK_SIGNATURE}; SWAP; IF {DROP} {FAILWITH} }; + PUSH nat 1 ; ADD @valid } } + { SWAP ; DROP } + } + { + # There were fewer signatures in the list + # than keys. Not all signatures must be present, but + # they should be marked as absent using the option type. + FAIL + } ; + SWAP + } + } ; + # Assert that the threshold is less than or equal to the + # number of valid signatures. + ASSERT_CMPLE ; + # Assert no unchecked signature remains + IF_CONS {FAIL} {} ; + DROP ; + + # Increment counter and place in storage + DIP { UNPAIR ; PUSH nat 1 ; ADD @new_counter ; PAIR} ; + + # We have now handled the signature verification part, + # produce the operation requested by the signers. + IF_LEFT + { # Get operation + UNIT ; EXEC + } + { + # Change set of signatures + DIP { CAR } ; SWAP ; PAIR ; NIL operation + }; + PAIR } + } +|} + +(* Client_proto_context.originate expects the contract script as a Script.expr *) +let multisig_script : Script.expr = + Michelson_v1_parser.parse_toplevel ?check:(Some true) multisig_script_string + |> Tezos_micheline.Micheline_parser.no_parsing_error + |> function + | Error _ -> + assert false + (* This is a top level assertion, it is asserted when the client's process runs. *) + | Ok parsing_result -> parsing_result.Michelson_v1_parser.expanded + +let multisig_script_hash = + let bytes = + Data_encoding.Binary.to_bytes_exn Script.expr_encoding multisig_script + in + Script_expr_hash.hash_bytes [bytes] + +(* The previous multisig script is the only one that the client can + originate but the client knows how to interact with several + versions of the multisig contract. For each version, the description + indicates which features are available and how to interact with + the contract. *) + +type multisig_contract_description = { + hash : Script_expr_hash.t; + (* The hash of the contract script *) + requires_chain_id : bool; + (* The signatures should contain the chain identifier *) + main_entrypoint : Entrypoint.t option; + (* name of the main entrypoint of the multisig contract, None means use the default entrypoint *) + generic : bool; + (* False means that the contract uses a custom action type, true + means that the contract expects the action as a (lambda unit + (list operation)). *) +} + +let entrypoint_main = Entrypoint.of_string_strict_exn "main" + +(* List of known multisig contracts hashes with their kinds *) +let known_multisig_contracts : multisig_contract_description list = + [ + { + (* First supported version of the generic multisig contract. Supports incoming + transfers from unauthenticated senders and outgoing transfers of + arbitrary operation lists. + + See docs/user/multisig.rst for more details. *) + hash = multisig_script_hash; + requires_chain_id = true; + main_entrypoint = Some entrypoint_main; + generic = true; + }; + { + (* Fourth supported version of the legacy multisig contract. This script is + functionally equivalent to the third version but uses the [DUP 2] + instruction introduced in Edo instead of the macro for [DIG 2; DUP; DUG 3]. *) + hash = + Script_expr_hash.of_b58check_exn + "exprutz4BVGJ3Qms6qjmqvUF8sEk27H1cfqhRT17qpTdhEs5hEjbWm"; + requires_chain_id = true; + main_entrypoint = None; + generic = false; + }; + { + (* Third supported version of the legacy multisig contract. This script is + functionally equivalent to the second version but uses the [DIP 2] + instruction introduced in Babylon instead of the [DIIP] macro. *) + hash = + Script_expr_hash.of_b58check_exn + "exprumpS39YZd26Cn4kyKUK5ezTR3at838iGWg7i6uETv8enDeAnfb"; + requires_chain_id = true; + main_entrypoint = None; + generic = false; + }; + { + (* Second supported version of the legacy multisig contract. This script + is the one resulting from the stitching of the Babylon protocol, the + only difference with the first version is that the chain id is part of + the data to sign. *) + hash = + Script_expr_hash.of_b58check_exn + "exprtw1v4KvQN414oEXdGuA1U3eQizuCdS8cipx8QGK8TbNLRwc3qL"; + requires_chain_id = true; + main_entrypoint = None; + generic = false; + }; + { + (* First supported version of the legacy multisig contract. This script should not + be used anymore because it is subject to a small replay attack: when + the test chain is forked both instances have the same address and + counter so whatever happens on the test chain can be replayed on the + main chain. The script has been fixed during the activation of the + Babylon protocol. *) + hash = + Script_expr_hash.of_b58check_exn + "expru4Ju9kf6MQ216FxUEsb9P6j8UhkPtsFcYP8r9XhQSRb47FZGfM"; + requires_chain_id = false; + main_entrypoint = None; + generic = false; + }; + ] + +let known_multisig_hashes = + List.map (fun descr -> descr.hash) known_multisig_contracts + +let check_multisig_script_hash hash : + multisig_contract_description tzresult Lwt.t = + let open Lwt_result_syntax in + match + List.find_opt + (fun d -> Script_expr_hash.(d.hash = hash)) + known_multisig_contracts + with + | None -> tzfail (Not_a_supported_multisig_contract hash) + | Some d -> return d + +(* Returns [Ok ()] if [~contract] is an originated contract whose code + is [multisig_script] *) +let check_multisig_contract (cctxt : #Protocol_client_context.full) ~chain + ~block contract = + let open Lwt_result_syntax in + let* hash_opt = + Client_proto_context.get_script_hash cctxt ~chain ~block contract + in + match hash_opt with + | None -> tzfail (Contract_has_no_script contract) + | Some hash -> check_multisig_script_hash hash + +(* Some Michelson building functions, specific to the needs of the multisig + interface.*) + +(* The type of the lambdas consumed by the generic script *) +let lambda_action_t ~loc = lambda_t ~loc (unit_t ~loc) (operations_t ~loc) + +(* Conversion functions from common types to Script_expr using the optimized representation *) +let mutez ~loc (amount : Tez.t) = int ~loc (Z.of_int64 (Tez.to_mutez amount)) + +let optimized_key_hash ~loc (key_hash : Signature.Public_key_hash.t) = + bytes + ~loc + (Data_encoding.Binary.to_bytes_exn + Signature.Public_key_hash.encoding + key_hash) + +let optimized_address ~loc ~(address : Contract.t) ~(entrypoint : Entrypoint.t) + = + bytes + ~loc + (Data_encoding.Binary.to_bytes_exn + Data_encoding.(tup2 Contract.encoding Entrypoint.value_encoding) + (address, entrypoint)) + +let optimized_key ~loc (key : Signature.Public_key.t) = + bytes + ~loc + (Data_encoding.Binary.to_bytes_exn Signature.Public_key.encoding key) + +(** * Actions *) + +type multisig_action = + | Transfer of { + amount : Tez.t; + destination : Contract.t; + entrypoint : Entrypoint.t; + parameter_type : Script.expr; + parameter : Script.expr; + } + | Change_delegate of public_key_hash option + | Lambda of Script.expr + | Change_keys of Z.t * public_key list + +let action_to_expr_generic ~loc = + let open Result_syntax in + function + | Transfer {amount; destination; entrypoint; parameter_type; parameter} -> ( + match destination with + | Implicit destination -> + let* a = + lambda_from_string + @@ Managed_contract.build_lambda_for_transfer_to_implicit + ~destination + ~amount + in + return @@ left ~loc a + | Originated destination -> + let* a = + lambda_from_string + @@ Managed_contract.build_lambda_for_transfer_to_originated + ~destination + ~entrypoint + ~parameter_type + ~parameter + ~amount + in + return @@ left ~loc a) + | Lambda code -> return Tezos_micheline.Micheline.(left ~loc (root code)) + | Change_delegate delegate -> + let* a = + lambda_from_string + @@ Managed_contract.build_lambda_for_set_delegate ~delegate + in + return @@ left ~loc a + | Change_keys (threshold, keys) -> + let optimized_keys = seq ~loc (List.map (optimized_key ~loc) keys) in + let expr = right ~loc (pair ~loc (int ~loc threshold) optimized_keys) in + return expr + +let action_to_expr_legacy ~loc = + let open Result_syntax in + function + | Transfer {amount; destination; entrypoint; parameter_type; parameter} -> + if parameter <> Tezos_micheline.Micheline.strip_locations (unit ~loc:()) + then tzfail @@ Unsupported_feature_generic_call parameter + else if + parameter_type + <> Tezos_micheline.Micheline.strip_locations (unit_t ~loc:()) + then tzfail @@ Unsupported_feature_generic_call_ty parameter_type + else + return + @@ left + ~loc + (pair + ~loc + (mutez ~loc amount) + (optimized_address ~loc ~address:destination ~entrypoint)) + | Lambda _ -> tzfail @@ Unsupported_feature_lambda "" + | Change_delegate delegate -> + let delegate_opt = + match delegate with + | None -> none ~loc () + | Some delegate -> some ~loc (optimized_key_hash ~loc delegate) + in + return @@ right ~loc (left ~loc delegate_opt) + | Change_keys (threshold, keys) -> + let optimized_keys = seq ~loc (List.map (optimized_key ~loc) keys) in + let expr = right ~loc (pair ~loc (int ~loc threshold) optimized_keys) in + return (right ~loc expr) + +let action_to_expr ~loc ~generic action = + if generic then action_to_expr_generic ~loc action + else action_to_expr_legacy ~loc action + +let action_of_expr_generic e = + let open Lwt_result_syntax in + let fail () = + tzfail + (Action_deserialisation_error + (Tezos_micheline.Micheline.strip_locations e)) + in + match e with + | Tezos_micheline.Micheline.Prim (_, Script.D_Left, [lam], []) -> + return (Lambda (Tezos_micheline.Micheline.strip_locations lam)) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Int (_, threshold); + Tezos_micheline.Micheline.Seq (_, key_bytes); + ], + [] ); + ], + [] ) -> + let* keys = + List.map_es + (function + | Tezos_micheline.Micheline.Bytes (_, s) -> + return + @@ Data_encoding.Binary.of_bytes_exn + Signature.Public_key.encoding + s + | _ -> fail ()) + key_bytes + in + return (Change_keys (threshold, keys)) + | _ -> fail () + +let action_of_expr_not_generic e = + let open Lwt_result_syntax in + let fail () = + tzfail + (Action_deserialisation_error + (Tezos_micheline.Micheline.strip_locations e)) + in + match e with + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Left, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Int (_, i); + Tezos_micheline.Micheline.Bytes (_, s); + ], + [] ); + ], + [] ) -> ( + match Tez.of_mutez (Z.to_int64 i) with + | None -> fail () + | Some amount -> + return + @@ Transfer + { + amount; + destination = + Data_encoding.Binary.of_bytes_exn Contract.encoding s; + entrypoint = Entrypoint.default; + parameter_type = + Tezos_micheline.Micheline.strip_locations @@ unit_t ~loc:(); + parameter = + Tezos_micheline.Micheline.strip_locations @@ unit ~loc:(); + }) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Left, + [Tezos_micheline.Micheline.Prim (_, Script.D_None, [], [])], + [] ); + ], + [] ) -> + return (Change_delegate None) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Left, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Some, + [Tezos_micheline.Micheline.Bytes (_, s)], + [] ); + ], + [] ); + ], + [] ) -> + return + @@ Change_delegate + (Some + (Data_encoding.Binary.of_bytes_exn + Signature.Public_key_hash.encoding + s)) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Right, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Int (_, threshold); + Tezos_micheline.Micheline.Seq (_, key_bytes); + ], + [] ); + ], + [] ); + ], + [] ) -> + let* keys = + List.map_es + (function + | Tezos_micheline.Micheline.Bytes (_, s) -> + return + @@ Data_encoding.Binary.of_bytes_exn + Signature.Public_key.encoding + s + | _ -> fail ()) + key_bytes + in + return (Change_keys (threshold, keys)) + | _ -> fail () + +let action_of_expr ~generic = + if generic then action_of_expr_generic else action_of_expr_not_generic + +type key_list = Signature.Public_key.t list + +(* The relevant information that we can get about a multisig smart contract *) +type multisig_contract_information = { + counter : Z.t; + threshold : Z.t; + keys : key_list; +} + +let multisig_get_information (cctxt : #Protocol_client_context.full) ~chain + ~block contract = + let open Client_proto_context in + let open Tezos_micheline.Micheline in + let open Lwt_result_syntax in + let* storage_opt = + get_storage cctxt ~chain ~block ~unparsing_mode:Readable contract + in + match storage_opt with + | None -> tzfail (Contract_has_no_storage contract) + | Some storage -> ( + match root storage with + | Prim + ( _, + D_Pair, + [Int (_, counter); Int (_, threshold); Seq (_, key_nodes)], + _ ) -> + let* keys = + List.map_es + (function + | String (_, key_str) -> + return @@ Signature.Public_key.of_b58check_exn key_str + | _ -> tzfail (Contract_has_unexpected_storage contract)) + key_nodes + in + return {counter; threshold; keys} + | _ -> tzfail (Contract_has_unexpected_storage contract)) + +let multisig_create_storage ~counter ~threshold ~keys () : + Script.expr tzresult Lwt.t = + let open Tezos_micheline.Micheline in + let open Lwt_result_syntax in + let loc = Tezos_micheline.Micheline_parser.location_zero in + let* l = + List.map_es + (fun key -> + let key_str = Signature.Public_key.to_b58check key in + return (String (loc, key_str))) + keys + in + return @@ strip_locations + @@ pair ~loc (int ~loc counter) (pair ~loc (int ~loc threshold) (seq ~loc l)) + +(* Client_proto_context.originate expects the initial storage as a string *) +let multisig_storage_string ~counter ~threshold ~keys () = + let open Lwt_result_syntax in + let* expr = multisig_create_storage ~counter ~threshold ~keys () in + return @@ Format.asprintf "%a" Michelson_v1_printer.print_expr expr + +let multisig_create_param ~counter ~generic ~action ~optional_signatures () : + Script.expr tzresult Lwt.t = + let open Tezos_micheline.Micheline in + let open Lwt_result_syntax in + let loc = 0 in + let* l = + List.map_es + (fun sig_opt -> + match sig_opt with + | None -> return @@ none ~loc () + | Some signature -> + return @@ some ~loc (String (loc, Signature.to_b58check signature))) + optional_signatures + in + let*? expr = action_to_expr ~loc ~generic action in + return @@ strip_locations + @@ pair ~loc (pair ~loc (int ~loc counter) expr) (Seq (loc, l)) + +let multisig_param ~counter ~action ~optional_signatures ~generic () = + let open Lwt_result_syntax in + let* expr = + multisig_create_param ~counter ~action ~optional_signatures ~generic () + in + return @@ Script.lazy_expr expr + +let get_contract_address_maybe_chain_id ~descr ~loc ~chain_id contract = + let address = + bytes ~loc (Data_encoding.Binary.to_bytes_exn Contract.encoding contract) + in + if descr.requires_chain_id then + let chain_id_bytes = + bytes ~loc (Data_encoding.Binary.to_bytes_exn Chain_id.encoding chain_id) + in + pair ~loc chain_id_bytes address + else address + +let multisig_bytes ~counter ~action ~contract ~chain_id ~descr () = + let open Lwt_result_syntax in + let loc = 0 in + let*? expr = action_to_expr ~loc ~generic:descr.generic action in + let triple = + pair + ~loc + (get_contract_address_maybe_chain_id ~descr ~loc ~chain_id contract) + (pair ~loc (int ~loc counter) expr) + in + let bytes = + Data_encoding.Binary.to_bytes_exn Script.expr_encoding + @@ Tezos_micheline.Micheline.strip_locations @@ triple + in + return @@ Bytes.cat (Bytes.of_string "\005") bytes + +let check_threshold ~threshold ~keys () = + let open Lwt_result_syntax in + let threshold = Z.to_int threshold in + if Compare.List_length_with.(keys < threshold) then + tzfail (Threshold_too_high (threshold, List.length keys)) + else if Compare.Int.(threshold <= 0) then + tzfail (Non_positive_threshold threshold) + else return_unit + +let originate_multisig (cctxt : #Protocol_client_context.full) ~chain ~block + ?confirmations ?dry_run ?branch ?fee ?gas_limit ?safety_guard ?storage_limit + ?verbose_signing ~delegate ~threshold ~keys ~balance ~source ~src_pk ~src_sk + ~fee_parameter () = + let open Lwt_result_syntax in + let* initial_storage = + multisig_storage_string ~counter:Z.zero ~threshold ~keys () + in + let* () = check_threshold ~threshold ~keys () in + Client_proto_context.originate_contract + cctxt + ~chain + ~block + ?branch + ?confirmations + ?dry_run + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?verbose_signing + ~delegate + ~initial_storage + ~balance + ~source + ~src_pk + ~src_sk + ~code:multisig_script + ~fee_parameter + () + +type multisig_prepared_action = { + bytes : Bytes.t; + threshold : Z.t; + keys : public_key list; + counter : Z.t; + entrypoint : Entrypoint.t option; + generic : bool; +} + +let check_parameter_type (cctxt : #Protocol_client_context.full) ~gas ~legacy + ~destination ~entrypoint ~parameter_type ~parameter () = + let open Lwt_result_syntax in + let* _ = + trace + (Ill_typed_argument (destination, entrypoint, parameter_type, parameter)) + @@ Plugin.RPC.Scripts.typecheck_data + cctxt + (cctxt#chain, cctxt#block) + ~data:parameter + ~ty:parameter_type + ~gas + ~legacy + in + return_unit + +let check_action (cctxt : #Protocol_client_context.full) ~action ~balance ~gas + ~legacy () = + let open Lwt_result_syntax in + match action with + | Change_keys (threshold, keys) -> + let* () = check_threshold ~threshold ~keys () in + return_unit + | Transfer {amount; destination; entrypoint; parameter_type; parameter} -> + let* () = + check_parameter_type + cctxt + ~destination + ~entrypoint + ~parameter_type + ~parameter + ~gas:None + ~legacy:false + () + in + if Tez.(amount > balance) then + (* This is warning only because the contract can be filled + before sending the signatures or even in the same + transaction *) + Format.eprintf + "Transferred amount is bigger than current multisig balance" ; + return_unit + | Lambda code -> + let action_t = + Tezos_micheline.Micheline.strip_locations (lambda_action_t ~loc:()) + in + let* _remaining_gas = + trace (Ill_typed_lambda (code, action_t)) + @@ Plugin.RPC.Scripts.typecheck_data + cctxt + (cctxt#chain, cctxt#block) + ~data:code + ~ty:action_t + ~gas + ~legacy + in + return_unit + | _ -> return_unit + +let prepare_multisig_transaction (cctxt : #Protocol_client_context.full) ~chain + ~block ~multisig_contract ~action () = + let open Lwt_result_syntax in + let contract = multisig_contract in + let* descr = check_multisig_contract cctxt ~chain ~block contract in + let* {counter; threshold; keys} = + multisig_get_information cctxt ~chain ~block contract + in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + let contract = Contract.Originated contract in + let* bytes = multisig_bytes ~counter ~action ~contract ~descr ~chain_id () in + let* balance = + Client_proto_context.get_balance + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + let* () = check_action cctxt ~action ~balance ~gas:None ~legacy:false () in + return + { + bytes; + threshold; + keys; + counter; + entrypoint = descr.main_entrypoint; + generic = descr.generic; + } + +let check_multisig_signatures ~bytes ~threshold ~keys signatures = + let open Lwt_result_syntax in + let key_array = Array.of_list keys in + let nkeys = Array.length key_array in + let opt_sigs_arr = Array.make nkeys None in + let matching_key_found = ref false in + let check_signature_against_key_number signature i key = + if Signature.check key signature bytes then ( + matching_key_found := true ; + opt_sigs_arr.(i) <- Some signature) + in + let* () = + List.iter_ep + (fun signature -> + matching_key_found := false ; + List.iteri (check_signature_against_key_number signature) keys ; + fail_unless !matching_key_found (Invalid_signature signature)) + signatures + in + let opt_sigs = Array.to_list opt_sigs_arr in + let signature_count = + List.fold_left + (fun n sig_opt -> match sig_opt with Some _ -> n + 1 | None -> n) + 0 + opt_sigs + in + let threshold_int = Z.to_int threshold in + if signature_count >= threshold_int then return opt_sigs + else tzfail (Not_enough_signatures (threshold_int, signature_count)) + +let call_multisig (cctxt : #Protocol_client_context.full) ~chain ~block + ?confirmations ?dry_run ?verbose_signing ?branch ~source ~src_pk ~src_sk + ~multisig_contract ~action ~signatures ~amount ?fee ?gas_limit ?safety_guard + ?storage_limit ?counter ~fee_parameter () = + let open Lwt_result_syntax in + let* {bytes; threshold; keys; counter = stored_counter; entrypoint; generic} = + prepare_multisig_transaction + cctxt + ~chain + ~block + ~multisig_contract + ~action + () + in + let* optional_signatures = + check_multisig_signatures ~bytes ~threshold ~keys signatures + in + let* parameters = + multisig_param + ~counter:stored_counter + ~action + ~optional_signatures + ~generic + () + in + Client_proto_context.transfer_with_script + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?branch + ~source + ~src_pk + ~src_sk + ~destination:(Originated multisig_contract) + ?entrypoint + ~parameters + ~amount + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + ?verbose_signing + () + +let action_of_bytes ~multisig_contract ~stored_counter ~descr ~chain_id bytes = + let open Lwt_result_syntax in + if + Compare.Int.(Bytes.length bytes >= 1) + && Compare.Int.(TzEndian.get_uint8 bytes 0 = 0x05) + then + let nbytes = Bytes.sub bytes 1 (Bytes.length bytes - 1) in + match Data_encoding.Binary.of_bytes_opt Script.expr_encoding nbytes with + | None -> tzfail (Bytes_deserialisation_error bytes) + | Some e -> ( + match Tezos_micheline.Micheline.root e with + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Bytes (_, contract_bytes); + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [Tezos_micheline.Micheline.Int (_, counter); e], + [] ); + ], + [] ) + when not descr.requires_chain_id -> + let contract = + Data_encoding.Binary.of_bytes_exn + Contract.originated_encoding + contract_bytes + in + if counter = stored_counter then + if Contract_hash.(multisig_contract = contract) then + action_of_expr ~generic:descr.generic e + else + tzfail (Bad_deserialized_contract (contract, multisig_contract)) + else + tzfail + (Bad_deserialized_counter + {received = counter; expected = stored_counter}) + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Bytes (_, chain_id_bytes); + Tezos_micheline.Micheline.Bytes (_, contract_bytes); + ], + [] ); + Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [Tezos_micheline.Micheline.Int (_, counter); e], + [] ); + ], + [] ) + when descr.requires_chain_id -> + let contract = + Data_encoding.Binary.of_bytes_exn + Contract.originated_encoding + contract_bytes + in + let cid = + Data_encoding.Binary.of_bytes_exn Chain_id.encoding chain_id_bytes + in + if counter = stored_counter then + if multisig_contract = contract && chain_id = cid then + action_of_expr ~generic:descr.generic e + else + tzfail (Bad_deserialized_contract (contract, multisig_contract)) + else + tzfail + (Bad_deserialized_counter + {received = counter; expected = stored_counter}) + | _ -> tzfail (Bytes_deserialisation_error bytes)) + else tzfail (Bytes_deserialisation_error bytes) + +let call_multisig_on_bytes (cctxt : #Protocol_client_context.full) ~chain ~block + ?confirmations ?dry_run ?verbose_signing ?branch ~source ~src_pk ~src_sk + ~multisig_contract ~bytes ~signatures ~amount ?fee ?gas_limit ?safety_guard + ?storage_limit ?counter ~fee_parameter () = + let open Lwt_result_syntax in + let* info = multisig_get_information cctxt ~chain ~block multisig_contract in + let* descr = check_multisig_contract cctxt ~chain ~block multisig_contract in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + let* action = + action_of_bytes + ~multisig_contract + ~stored_counter:info.counter + ~chain_id + ~descr + bytes + in + call_multisig + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?branch + ~source + ~src_pk + ~src_sk + ~multisig_contract + ~action + ~signatures + ~amount + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + ?verbose_signing + () diff --git a/src/proto_020_PsParisC/lib_client/client_proto_multisig.mli b/src/proto_020_PsParisC/lib_client/client_proto_multisig.mli new file mode 100644 index 000000000000..c40f6c6f38c1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_multisig.mli @@ -0,0 +1,155 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +(* The script of the recommended version of the multisig contract. + This is the script originated by [originate_multisig]. *) +val multisig_script : Script.expr + +(* A description of the possible actions that a multisig contract can run. *) +type multisig_action = + | Transfer of { + amount : Tez.t; + destination : Contract.t; + entrypoint : Entrypoint.t; + parameter_type : Script.expr; + parameter : Script.expr; + } + | Change_delegate of public_key_hash option + | Lambda of Script.expr + | Change_keys of Z.t * public_key list + +(* A prepared action is the byte sequence that needs to be signed to run the + action together with some data that can be useful for the user and to call + the multisig contracts once enough signatures are provided. *) +type multisig_prepared_action = { + (* The sequence of bytes to be signed. *) + bytes : Bytes.t; + (* Information reported to the user so that she knows who can sign and how + many signatures are required. *) + threshold : Z.t; + keys : public_key list; + (* Information needed to execute the action ones enough signatures have been + gathered. *) + counter : Z.t; + entrypoint : Entrypoint.t option; + generic : bool; +} + +(* The client will refuse to interact with a multisig contract if the hash of + its script is not in this list. *) +val known_multisig_hashes : Script_expr_hash.t list + +(* Originate a new multisig contract *) +val originate_multisig : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?branch:int -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?verbose_signing:bool -> + delegate:public_key_hash option -> + threshold:Z.t -> + keys:public_key list -> + balance:Tez.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.origination Kind.manager Injection.result * Contract.t) tzresult Lwt.t + +(* Prepare an action, see [multisig_prepared_action]. *) +val prepare_multisig_transaction : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + multisig_contract:Contract_hash.t -> + action:multisig_action -> + unit -> + multisig_prepared_action tzresult Lwt.t + +(* Call a multisig contract, requesting it to run an action. *) +val call_multisig : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + multisig_contract:Contract_hash.t -> + action:multisig_action -> + signatures:Signature.t list -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t + +(* Same as [call_multisig] but the action to be performed is reconstructed from + the byte sequence that was signed. *) +val call_multisig_on_bytes : + full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + multisig_contract:Contract_hash.t -> + bytes:Bytes.t -> + signatures:Signature.t list -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_programs.ml b/src/proto_020_PsParisC/lib_client/client_proto_programs.ml new file mode 100644 index 000000000000..24d2dd25b3aa --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_programs.ml @@ -0,0 +1,551 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Michelson_v1_printer + +module Program = Client_aliases.Alias (struct + type t = Michelson_v1_parser.parsed Micheline_parser.parsing_result + + include Compare.Make (struct + type nonrec t = t + + let compare = Micheline_parser.compare Michelson_v1_parser.compare_parsed + end) + + let encoding = + Data_encoding.conv + (fun ({Michelson_v1_parser.source; _}, _) -> source) + (fun source -> Michelson_v1_parser.parse_toplevel source) + Data_encoding.string + + let of_source source = + let open Lwt_result_syntax in + return (Michelson_v1_parser.parse_toplevel source) + + let to_source ({Michelson_v1_parser.source; _}, _) = + let open Lwt_result_syntax in + return source + + let name = "script" +end) + +let print_errors ?parsed (cctxt : #Protocol_client_context.full) errs + ~show_source = + let open Lwt_result_syntax in + let parsed = Option.map Michelson_v1_parser.unrecognize_prims parsed in + let*! errs = + Michelson_v1_error_reporter.enrich_runtime_errors + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~parsed + errs + in + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ?parsed + ~show_source) + errs + in + let*! () = cctxt#error "error running script" in + return_unit + +let print_view_result (cctxt : #Protocol_client_context.full) = + let open Lwt_result_syntax in + function + | Ok expr -> + let*! () = cctxt#message "%a" print_expr expr in + return_unit + | Error errs -> print_errors cctxt ~show_source:false errs + +let print_run_result (cctxt : Protocol_client_context.full) ~show_source ~parsed + = + let open Lwt_result_syntax in + function + | Ok (storage, operations, maybe_lazy_storage_diff) -> + let* operations = + List.map_es + (Operation_result.normalize_internal_operation cctxt Readable) + operations + in + let*! () = + cctxt#message + "@[@[storage@,\ + %a@]@,\ + @[emitted operations@,\ + %a@]@,\ + @[big_map diff@,\ + %a@]@]@." + print_expr + storage + (Format.pp_print_list Operation_result.pp_internal_operation) + operations + (fun ppf -> function + | None -> () + | Some diff -> print_big_map_diff ppf diff) + maybe_lazy_storage_diff + in + return_unit + | Error errs -> print_errors cctxt errs ~show_source ~parsed + +let print_trace_result (cctxt : #Client_context.printer) ~show_source ~parsed = + let open Lwt_result_syntax in + function + | Ok (storage, operations, trace, maybe_lazy_storage_diff) -> + let*! () = + cctxt#message + "@[@[storage@,\ + %a@]@,\ + @[emitted operations@,\ + %a@]@,\ + @[big_map diff@,\ + %a@]@,\ + @[trace@,\ + %a@]@]@." + print_expr + storage + (Format.pp_print_list Operation_result.pp_internal_operation) + operations + (fun ppf -> function + | None -> () + | Some diff -> print_big_map_diff ppf diff) + maybe_lazy_storage_diff + print_execution_trace + trace + in + return_unit + | Error errs -> print_errors cctxt errs ~show_source ~parsed + +let print_run_instr_result (cctxt : #Client_context.printer) ~show_source + ~parsed = + let open Lwt_result_syntax in + function + | Ok (stack, gas) -> + let*! () = + cctxt#message + "@[@[Result@,%a@]@,@[Gas remaining: %a@]@]@." + Michelson_v1_printer.print_typed_stack + stack + Alpha_context.Gas.pp + gas + in + return_unit + | Error errs -> print_errors cctxt errs ~show_source ~parsed + +type simulation_params = { + input : Michelson_v1_parser.parsed; + unparsing_mode : Script_ir_unparser.unparsing_mode; + now : Script_timestamp.t option; + level : Script_int.n Script_int.num option; + sender : Contract.t option; + payer : Signature.public_key_hash option; + gas : Gas.Arith.integral option; + other_contracts : RPC.Scripts.S.other_contract_description list option; + extra_big_maps : RPC.Scripts.S.extra_big_map_description list option; +} + +type run_view_params = { + shared_params : simulation_params; + contract : Contract_hash.t; + entrypoint : Entrypoint.t; +} + +type run_script_view_params = { + shared_params : simulation_params; + contract : Contract_hash.t; + view : string; + unlimited_gas : bool; +} + +type run_params = { + shared_params : simulation_params; + amount : Tez.t option; + balance : Tez.t option; + program : Michelson_v1_parser.parsed; + storage : Michelson_v1_parser.parsed; + entrypoint : Entrypoint.t option; + self : Contract_hash.t option; +} + +type run_instr_params = { + shared_params : simulation_params; + amount : Tez.t; + balance : Tez.t option; + stack : (Script.expr * Script.expr) list; + self : Contract_hash.t option; + parameter : Script.expr option; + legacy : bool; +} + +let run_view (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block (params : run_view_params) = + let open Lwt_result_syntax in + let { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + contract; + entrypoint; + } = + params + in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + Plugin.RPC.Scripts.run_tzip4_view + cctxt + (chain, block) + ~gas + ~contract + ~entrypoint + ~input:input.expanded + ~chain_id + ~sender + ~payer + ~unparsing_mode + ~now + ~level + ~other_contracts + ~extra_big_maps + +let run_script_view (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block (params : run_script_view_params) = + let open Lwt_result_syntax in + let { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + contract; + view; + unlimited_gas; + } = + params + in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + Plugin.RPC.Scripts.run_script_view + cctxt + (chain, block) + ~gas + ~contract + ~view + ~input:input.expanded + ~unlimited_gas + ~chain_id + ~sender + ~payer + ~unparsing_mode + ~now + ~level + ~other_contracts + ~extra_big_maps + +let run (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block (params : run_params) = + let open Lwt_result_syntax in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + let { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + program; + amount; + balance; + storage; + entrypoint; + self; + } = + params + in + let amount = Option.value ~default:Tez.fifty_cents amount in + let entrypoint = Option.value ~default:Entrypoint.default entrypoint in + Plugin.RPC.Scripts.run_code + cctxt + (chain, block) + ~gas + ~entrypoint + ~unparsing_mode:(Some unparsing_mode) + ~script:program.expanded + ~storage:storage.expanded + ~input:input.expanded + ~amount + ~balance + ~chain_id + ~sender + ~payer + ~self + ~now + ~level + ~other_contracts + ~extra_big_maps + +let trace (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block (params : run_params) = + let open Lwt_result_syntax in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + let { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + program; + amount; + balance; + storage; + entrypoint; + self; + } = + params + in + let amount = Option.value ~default:Tez.fifty_cents amount in + let entrypoint = Option.value ~default:Entrypoint.default entrypoint in + Plugin.RPC.Scripts.trace_code + cctxt + (chain, block) + ~gas + ~entrypoint + ~unparsing_mode:(Some unparsing_mode) + ~script:program.expanded + ~storage:storage.expanded + ~input:input.expanded + ~amount + ~balance + ~chain_id + ~sender + ~payer + ~self + ~now + ~level + ~other_contracts + ~extra_big_maps + +let run_instr (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block (params : run_instr_params) = + let open Lwt_result_syntax in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + let {shared_params; amount; balance; stack; self; parameter; legacy} = + params + in + let { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + } = + shared_params + in + Plugin.RPC.Scripts.run_instr + ~gas + ~legacy + ~input:stack + ~code:input.expanded + ~chain_id + ~now + ~level + ~unparsing_mode:(Some unparsing_mode) + ~source:payer + ~sender + ~self + ~parameter + ~amount + ~balance + ~other_contracts + ~extra_big_maps + cctxt + (chain, block) + +let typecheck_data cctxt ~(chain : Chain_services.chain) ~block ~gas ~legacy + ~(data : Michelson_v1_parser.parsed) ~(ty : Michelson_v1_parser.parsed) () = + Plugin.RPC.Scripts.typecheck_data + cctxt + (chain, block) + ~gas + ~legacy + ~data:data.expanded + ~ty:ty.expanded + +let typecheck_program cctxt ~(chain : Chain_services.chain) ~block ~gas ~legacy + ~show_types (program : Michelson_v1_parser.parsed) = + Plugin.RPC.Scripts.typecheck_code + cctxt + (chain, block) + ~gas + ~legacy + ~script:program.expanded + ~show_types + +let script_size cctxt ~(chain : Chain_services.chain) ~block ~gas ~legacy + ~(program : Michelson_v1_parser.parsed) + ~(storage : Michelson_v1_parser.parsed) () = + Plugin.RPC.Scripts.script_size + cctxt + (chain, block) + ~gas + ~legacy + ~script:program.expanded + ~storage:storage.expanded + +let print_typecheck_result ~emacs ~show_types ~print_source_on_error + ~display_names ~name program res (cctxt : #Client_context.printer) = + let open Lwt_result_syntax in + if emacs then + let type_map, errs, _gas = + match res with + | Ok (type_map, gas) -> (type_map, [], Some gas) + | Error + (Environment.Ecoproto_error + (Script_tc_errors.Ill_typed_contract (_, type_map)) + :: _ as errs) -> + (type_map, errs, None) + | Error errs -> ([], errs, None) + in + let*! () = + cctxt#message + "(@[(types . %a)@ (errors . %a)@])" + Michelson_v1_emacs.print_type_map + (program, type_map) + Michelson_v1_emacs.report_errors + (program, errs) + in + return_unit + else + match res with + | Ok (type_map, gas) -> + let program = Michelson_v1_printer.inject_types type_map program in + let*! () = + cctxt#message + "@[Well typed (Gas remaining: %a)\t%t@]" + Gas.pp + gas + (fun fmt -> if display_names then Format.pp_print_string fmt name) + in + if show_types then + let*! () = cctxt#message "%a" Micheline_printer.print_expr program in + return_unit + else return_unit + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:show_types + ~show_source:print_source_on_error + ~parsed:(Michelson_v1_parser.unrecognize_prims program)) + errs + in + cctxt#error "script %S is ill-typed" name + +let entrypoint_type cctxt ~(chain : Chain_services.chain) ~block + (program : Michelson_v1_parser.parsed) ~entrypoint = + Michelson_v1_entrypoints.script_entrypoint_type + cctxt + ~chain + ~block + program.expanded + ~entrypoint + +let print_entrypoint_type (cctxt : #Client_context.printer) ~emacs ?script_name + ~show_source ~parsed ~entrypoint ty = + Michelson_v1_entrypoints.print_entrypoint_type + cctxt + ~entrypoint + ~emacs + ?script_name + ~on_errors:(print_errors cctxt ~show_source ~parsed) + ty + +let list_entrypoints cctxt ~(chain : Chain_services.chain) ~block + (program : Michelson_v1_parser.parsed) = + Michelson_v1_entrypoints.list_entrypoints cctxt ~chain ~block program.expanded + +let print_entrypoints_list (cctxt : #Client_context.printer) ~emacs ?script_name + ~show_source ~parsed ty = + Michelson_v1_entrypoints.print_entrypoints_list + cctxt + ~emacs + ?script_name + ~on_errors:(print_errors cctxt ~show_source ~parsed) + ty + +let list_unreachables cctxt ~(chain : Chain_services.chain) ~block + (program : Michelson_v1_parser.parsed) = + Michelson_v1_entrypoints.list_unreachables + cctxt + ~chain + ~block + program.expanded + +let print_unreachables (cctxt : #Client_context.printer) ~emacs ?script_name + ~show_source ~parsed ty = + Michelson_v1_entrypoints.print_unreachables + cctxt + ~emacs + ?script_name + ~on_errors:(print_errors cctxt ~show_source ~parsed) + ty diff --git a/src/proto_020_PsParisC/lib_client/client_proto_programs.mli b/src/proto_020_PsParisC/lib_client/client_proto_programs.mli new file mode 100644 index 000000000000..eb7593fdc204 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_programs.mli @@ -0,0 +1,266 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +module Program : + Client_aliases.Alias + with type t = Michelson_v1_parser.parsed Micheline_parser.parsing_result + +(* Parameters shared by both simulations (views, and contracts). *) +type simulation_params = { + input : Michelson_v1_parser.parsed; + unparsing_mode : Script_ir_unparser.unparsing_mode; + now : Script_timestamp.t option; + level : Script_int.n Script_int.num option; + sender : Contract.t option; + payer : Signature.public_key_hash option; + gas : Gas.Arith.integral option; + other_contracts : RPC.Scripts.S.other_contract_description list option; + extra_big_maps : RPC.Scripts.S.extra_big_map_description list option; +} + +(* Parameters specific to simulations of TZIP4 views *) +type run_view_params = { + shared_params : simulation_params; + contract : Contract_hash.t; + entrypoint : Entrypoint.t; +} + +(* Parameters specific to simulations of Michelson views *) +type run_script_view_params = { + shared_params : simulation_params; + contract : Contract_hash.t; + view : string; + unlimited_gas : bool; +} + +(* Parameters specific to simulations of contract calls *) +type run_params = { + shared_params : simulation_params; + amount : Tez.t option; + balance : Tez.t option; + program : Michelson_v1_parser.parsed; + storage : Michelson_v1_parser.parsed; + entrypoint : Entrypoint.t option; + self : Contract_hash.t option; +} + +(* Parameters specific to simulations of single steps *) +type run_instr_params = { + shared_params : simulation_params; + amount : Tez.t; + balance : Tez.t option; + stack : (Script.expr * Script.expr) list; + self : Contract_hash.t option; + parameter : Script.expr option; + legacy : bool; +} + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.run_tzip4_view} *) +val run_view : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + run_view_params -> + Script.expr tzresult Lwt.t + +(** [run_script_view cctxt ~chain ~block params] + executes {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.run_script_view}, + the RPC to run a Michelson view offchain and returns its value. + *) +val run_script_view : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + run_script_view_params -> + Script.expr tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.run_code} *) +val run : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + run_params -> + (Script.expr + * Apply_internal_results.packed_internal_operation list + * Lazy_storage.diffs option) + tzresult + Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.trace_code} *) +val trace : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + run_params -> + (Script.expr + * Apply_internal_results.packed_internal_operation list + * Script_typed_ir.execution_trace + * Lazy_storage.diffs option) + tzresult + Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.run_instr} *) +val run_instr : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + run_instr_params -> + ((Script.expr * Script.expr) list * Gas.t) tzresult Lwt.t + +val print_view_result : + #Protocol_client_context.full -> + Script_repr.expr tzresult -> + unit tzresult Lwt.t + +val print_run_result : + Protocol_client_context.full -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + (Script_repr.expr + * Apply_internal_results.packed_internal_operation list + * Lazy_storage.diffs option) + tzresult -> + unit tzresult Lwt.t + +val print_trace_result : + #Protocol_client_context.full -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + (Script_repr.expr + * Apply_internal_results.packed_internal_operation list + * Script_typed_ir.execution_trace + * Lazy_storage.diffs option) + tzresult -> + unit tzresult Lwt.t + +val print_run_instr_result : + #Protocol_client_context.full -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + ((Script.expr * Script.expr) list * Gas.t) tzresult -> + unit tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.typecheck_data} *) +val typecheck_data : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + gas:Gas.Arith.integral option -> + legacy:bool -> + data:Michelson_v1_parser.parsed -> + ty:Michelson_v1_parser.parsed -> + unit -> + Gas.t tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.typecheck_code} *) +val typecheck_program : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + gas:Gas.Arith.integral option -> + legacy:bool -> + show_types:bool -> + Michelson_v1_parser.parsed -> + (Script_tc_errors.type_map * Gas.t) tzresult Lwt.t + +val print_typecheck_result : + emacs:bool -> + show_types:bool -> + print_source_on_error:bool -> + display_names:bool -> + name:string -> + Michelson_v1_parser.parsed -> + (Script_tc_errors.type_map * Gas.t) tzresult -> + #Client_context.printer -> + unit tzresult Lwt.t + +(** Calls {!Tezos_protocol_plugin_alpha.Plugin.RPC.Scripts.script_size} *) +val script_size : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + gas:Gas.Arith.integral option -> + legacy:bool -> + program:Michelson_v1_parser.parsed -> + storage:Michelson_v1_parser.parsed -> + unit -> + int tzresult Lwt.t + +val entrypoint_type : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Michelson_v1_parser.parsed -> + entrypoint:Entrypoint.t -> + Script.expr option tzresult Lwt.t + +val print_entrypoint_type : + #Protocol_client_context.full -> + emacs:bool -> + ?script_name:string -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + entrypoint:Entrypoint.t -> + Script_repr.expr option tzresult -> + unit tzresult Lwt.t + +(** Calls {!Michelson_v1_entrypoints.list_entrypoints} *) +val list_entrypoints : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Michelson_v1_parser.parsed -> + (string * Script.expr) list tzresult Lwt.t + +val print_entrypoints_list : + #Protocol_client_context.full -> + emacs:bool -> + ?script_name:string -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + (string * Script.expr) list tzresult -> + unit tzresult Lwt.t + +val list_unreachables : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + Michelson_v1_parser.parsed -> + Michelson_v1_primitives.prim list list tzresult Lwt.t + +(** Calls {!Michelson_v1_entrypoints.print_unreachables} *) +val print_unreachables : + #Protocol_client_context.full -> + emacs:bool -> + ?script_name:string -> + show_source:bool -> + parsed:Michelson_v1_parser.parsed -> + Michelson_v1_primitives.prim list list tzresult -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_rollups.ml b/src/proto_020_PsParisC/lib_client/client_proto_rollups.ml new file mode 100644 index 000000000000..06e6c0917903 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_rollups.ml @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module EpoxyEntity = struct + include Zk_rollup.Address + + let of_source s = + let open Lwt_result_syntax in + let* rollup = + match Zk_rollup.Address.of_b58check_opt s with + | None -> tzfail @@ error_of_fmt "bad epoxy notation" + | Some rollup -> return rollup + in + return rollup + + let to_source rollup = + let open Lwt_result_syntax in + return (Zk_rollup.Address.to_b58check rollup) + + let name = "epoxy" +end + +module Epoxy_alias = Client_aliases.Alias (EpoxyEntity) diff --git a/src/proto_020_PsParisC/lib_client/client_proto_rollups.mli b/src/proto_020_PsParisC/lib_client/client_proto_rollups.mli new file mode 100644 index 000000000000..e6211d8e879a --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_rollups.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Epoxy_alias : Client_aliases.Alias with type t = Zk_rollup.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_tzt.ml b/src/proto_020_PsParisC/lib_client/client_proto_tzt.ml new file mode 100644 index 000000000000..1b2c2c4a2a1b --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_tzt.ml @@ -0,0 +1,178 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +type unit_test_with_source = { + source : string; + parsed : string Michelson_v1_parser.parser_result; +} + +let convert_error trace = + let open Result_syntax in + let open Micheline in + function + | Script_interpreter.Reject (_loc, value, _trace) -> + let value = Michelson_v1_primitives.strings_of_prims value in + return (Prim (0, "Failed", [root value], [])) + | Tez_repr.Addition_overflow _ | Tez_repr.Multiplication_overflow _ + | Script_interpreter.Overflow _ -> + return (Prim (0, "Overflow", [], [])) + | Tez_repr.Subtraction_underflow (a, b) -> + return + (Prim + ( 0, + "MutezUnderflow", + [ + Int (0, Z.of_int64 @@ Tez_repr.to_mutez a); + Int (0, Z.of_int64 @@ Tez_repr.to_mutez b); + ], + [] )) + | Tez_repr.Negative_multiplicator _ -> return (Prim (0, "NegMul", [], [])) + | Tez_repr.Invalid_divisor _ -> return (Prim (0, "InvalidDivisor", [], [])) + | Raw_context.Operation_quota_exceeded | Raw_context.Block_quota_exceeded -> + return (Prim (0, "Gas_exhaustion", [], [])) + | _ -> + return + (Prim + ( 0, + "StaticError", + [String (0, Format.asprintf "%a" Error_monad.pp_print_trace trace)], + [] )) + +let convert_trace = function + | Environment.Ecoproto_error err :: _ as trace -> convert_error trace err + | _ -> assert false + +let match_output ~got ~expected = + let open Result_syntax in + let open Micheline in + let rec match_pattern pattern expression = + match (pattern, expression) with + (* Wildcard *) + | Prim (_, "_", [], []), _ -> true + (* Int *) + | Int (_p_loc, p), Int (_e_loc, e) -> Z.equal p e + | Int _, _ | _, Int _ -> false + (* String *) + | String (_p_loc, p), String (_e_loc, e) -> Compare.String.(p = e) + | String _, _ | _, String _ -> false + (* Bytes *) + | Bytes (_p_loc, p), Bytes (_e_loc, e) -> Compare.Bytes.(p = e) + | Bytes _, _ | _, Bytes _ -> false + (* Seq *) + | Seq (_p_loc, p), Seq (_e_loc, e) -> ( + match List.for_all2 ~when_different_lengths:() match_pattern p e with + | Ok b -> b + | Error () -> false) + | Seq _, _ | _, Seq _ -> false + (* Prim *) + | ( Prim (_p_loc, p_prim, p_args, p_annots), + Prim (_e_loc, e_prim, e_args, e_annots) ) -> ( + Compare.String.(p_prim = "_" || p_prim = e_prim) + && (match + List.for_all2 + ~when_different_lengths:() + match_pattern + p_args + e_args + with + | Ok b -> b + | Error () -> false) + && + match + List.for_all2 + ~when_different_lengths:() + Compare.String.( = ) + p_annots + e_annots + with + | Ok b -> b + | Error () -> false) + in + if match_pattern expected got then return_unit + else + let pp fmt e = + Micheline_printer.print_expr_unwrapped + fmt + (Micheline_printer.printable Fun.id (Micheline.strip_locations e)) + in + (* TODO: proper error instead of failwith *) + error_with "Got output: %a@.Expected: %a@." pp got pp expected + +let run_unit_test (cctxt : #Protocol_client_context.rpc_context) + ~(chain : Chain_services.chain) ~block ~(test : unit_test_with_source) () = + let open Lwt_result_syntax in + let*? ut = Michelson_v1_stack.parse_unit_test test.parsed in + let all_contracts = + let other_contracts = + Option.value ~default:[] ut.optional.other_contracts + in + match (ut.optional.self, ut.optional.parameter) with + | Some self, Some param -> + RPC.Scripts.S.{address = self; ty = param} :: other_contracts + | None, _ | Some _, None -> other_contracts + in + let* chain_id = + match ut.optional.chain_id with + | Some chain_id -> return chain_id + | None -> Chain_services.chain_id cctxt ~chain () + in + let amount = Option.value ~default:Tez.zero ut.optional.amount in + let*! res = + match ut.output with + | Micheline.Seq _ as stack -> + let*? stack = Michelson_v1_stack.parse_stack ~node:stack test.parsed in + let* stack = + Plugin.RPC.Scripts.normalize_stack + cctxt + (chain, block) + ~stack + ~unparsing_mode:Readable + ~legacy:true + ~other_contracts:(Some all_contracts) + ~extra_big_maps:ut.optional.extra_big_maps + in + return (Michelson_v1_printer.unparse_stack 0 stack) + | expected_output -> return expected_output + in + (* Wildcard patterns in output stack is incompatible with output stack normalization. + When the output stack contains a wildcard pattern, the normalization is expected + to fail. To support wildcard patterns, we silently skip output stack normalization + when it fails. *) + let expected_output = match res with Ok x -> x | Error _ -> ut.output in + let*! res = + Plugin.RPC.Scripts.run_instr + ~legacy:true + ~gas:None + ~input:ut.input + ~code:ut.code + ~now:ut.optional.now + ~level:ut.optional.level + ~sender:ut.optional.sender + ~source:ut.optional.source + ~chain_id + ~self:ut.optional.self + ~parameter:ut.optional.parameter + ~amount + ~balance:ut.optional.balance + ~other_contracts:(Some all_contracts) + ~extra_big_maps:ut.optional.extra_big_maps + ~unparsing_mode:None + cctxt + (chain, block) + in + let*? output = + match res with + | Ok (output, _gas) -> + Result_syntax.return (Michelson_v1_printer.unparse_stack 0 output) + | Error err -> convert_trace err + in + let*? () = match_output ~expected:expected_output ~got:output in + return_unit diff --git a/src/proto_020_PsParisC/lib_client/client_proto_tzt.mli b/src/proto_020_PsParisC/lib_client/client_proto_tzt.mli new file mode 100644 index 000000000000..0d4c9998059c --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_tzt.mli @@ -0,0 +1,19 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(*****************************************************************************) + +type unit_test_with_source = { + source : string; + parsed : string Michelson_v1_parser.parser_result; +} + +val run_unit_test : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + test:unit_test_with_source -> + unit -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/client_proto_utils.ml b/src/proto_020_PsParisC/lib_client/client_proto_utils.ml new file mode 100644 index 000000000000..897103203366 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_utils.ml @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +let to_json_and_bytes branch message = + let op = + ( Environment.Operation.{branch}, + Contents_list (Single (Failing_noop message)) ) + in + let encoding = Operation.unsigned_encoding in + ( Data_encoding.Json.construct encoding op, + Data_encoding.Binary.to_bytes_exn encoding op ) + +let sign_message (cctxt : #full) ~src_sk ~block ~message = + let open Lwt_result_syntax in + let json, bytes = to_json_and_bytes block message in + let*! () = + cctxt#message "signed content: @[%a@]" Data_encoding.Json.pp json + in + Client_keys.sign cctxt ~watermark:Signature.Generic_operation src_sk bytes + +let check_message (cctxt : #full) ~block ~key_locator ~quiet ~message ~signature + = + let open Lwt_result_syntax in + let json, bytes = to_json_and_bytes block message in + let*! () = + if quiet then Lwt.return_unit + else cctxt#message "checked content: @[%a@]" Data_encoding.Json.pp json + in + Client_keys.check + ~watermark:Signature.Generic_operation + key_locator + signature + bytes diff --git a/src/proto_020_PsParisC/lib_client/client_proto_utils.mli b/src/proto_020_PsParisC/lib_client/client_proto_utils.mli new file mode 100644 index 000000000000..c535e4b24ecb --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/client_proto_utils.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val sign_message : + #Protocol_client_context.full -> + src_sk:Client_keys.sk_uri -> + block:Block_hash.t -> + message:string -> + Signature.t tzresult Lwt.t + +val check_message : + #Protocol_client_context.full -> + block:Block_hash.t -> + key_locator:Client_keys.pk_uri -> + quiet:bool -> + message:string -> + signature:Signature.t -> + bool tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/dune b/src/proto_020_PsParisC/lib_client/dune new file mode 100644 index 000000000000..2e5d4d9b209e --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/dune @@ -0,0 +1,35 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_client_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.client) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + octez-shell-libs.shell-services + octez-shell-libs.client-base + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.protocol.lifted + octez-shell-libs.mockup-registration + octez-shell-libs.proxy + octez-shell-libs.signer-backends + octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-019-PtParisB.parameters + octez-libs.rpc + octez-protocol-019-PtParisB-libs.smart-rollup + uri) + (inline_tests (flags -verbose) (modes native)) + (preprocess (pps ppx_expect)) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB_lifted + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_smart_rollup_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_client/injection.ml b/src/proto_020_PsParisC/lib_client/injection.ml new file mode 100644 index 000000000000..2fa804d9bea3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/injection.ml @@ -0,0 +1,1619 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results +open Apply_operation_result +open Apply_internal_results +open Protocol_client_context + +let get_branch (rpc_config : #Protocol_client_context.full) ~chain + ~(block : Block_services.block) branch = + (* The default branch is set to HEAD~2, because with Tenderbake the + same transaction may be included again in another block candidate + at the same level, so the operation branch should not point to + the current head. It's not a good idea if it points to the head's + predecessor as well, as the predecessor hash may still change + because of potential reorgs (only the predecessor payload is + finalized, not the whole block). *) + let open Lwt_result_syntax in + let branch = Option.value ~default:0 branch in + let* block = + (* TODO export parameter *) + match block with + | `Head 0 -> + (* Default client's block value: we branch to head's grandfather *) + return (`Head (2 + branch)) + | `Head n -> return (`Head (n + branch)) + | `Hash (h, n) -> return (`Hash (h, n + branch)) + | `Alias (a, n) -> return (`Alias (a, n)) + | `Genesis -> return `Genesis + | `Level i -> return (`Level i) + in + let* hash = Shell_services.Blocks.hash rpc_config ~chain ~block () in + let* chain_id = Shell_services.Chain.chain_id rpc_config ~chain () in + return (chain_id, hash) + +type 'kind preapply_result = + Operation_hash.t * 'kind operation * 'kind operation_metadata + +type 'kind result_list = + Operation_hash.t * 'kind contents_list * 'kind contents_result_list + +type 'kind result = Operation_hash.t * 'kind contents * 'kind contents_result + +let get_manager_operation_gas_and_fee (contents : packed_contents_list) = + let l = Operation.to_list contents in + List.fold_left + (fun acc -> function + | Contents (Manager_operation {fee; gas_limit; _}) -> ( + match acc with + | Error _ as e -> e + | Ok (total_fee, total_gas) -> ( + match Tez.(total_fee +? fee) with + | Ok total_fee -> Ok (total_fee, Gas.Arith.add total_gas gas_limit) + | Error _ as e -> e)) + | _ -> acc) + (Ok (Tez.zero, Gas.Arith.zero)) + l + +type fee_parameter = { + minimal_fees : Tez.t; + minimal_nanotez_per_byte : Q.t; + minimal_nanotez_per_gas_unit : Q.t; + force_low_fee : bool; + fee_cap : Tez.t; + burn_cap : Tez.t; +} + +(* Rounding up (see Z.cdiv) *) +let z_mutez_of_q_nanotez (ntz : Q.t) = + let q_mutez = Q.div ntz (Q.of_int 1000) in + Z.cdiv q_mutez.Q.num q_mutez.Q.den + +let check_fees : + type t. + #Protocol_client_context.full -> + fee_parameter -> + t contents_list -> + int -> + unit Lwt.t = + let open Lwt_result_syntax in + fun cctxt config op size -> + match Contents_list op |> get_manager_operation_gas_and_fee with + | Error _ -> assert false (* FIXME *) + | Ok (fee, gas) -> + if Tez.compare fee config.fee_cap > 0 then + let*! () = + cctxt#error + "The proposed fee (%s%a) are higher than the configured fee cap \ + (%s%a).@\n\ + \ Use `--fee-cap %a` to emit this operation anyway." + Operation_result.tez_sym + Tez.pp + fee + Operation_result.tez_sym + Tez.pp + config.fee_cap + Tez.pp + fee + in + exit 1 + else + let fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez fee)) (Q.of_int 1000) + in + let minimal_fees_in_nanotez = + Q.mul + (Q.of_int64 (Tez.to_mutez config.minimal_fees)) + (Q.of_int 1000) + in + let minimal_fees_for_gas_in_nanotez = + Q.mul + config.minimal_nanotez_per_gas_unit + (Q.of_bigint (Gas.Arith.integral_to_z gas)) + in + let minimal_fees_for_size_in_nanotez = + Q.mul config.minimal_nanotez_per_byte (Q.of_int size) + in + let estimated_fees_in_nanotez = + Q.add + minimal_fees_in_nanotez + (Q.add + minimal_fees_for_gas_in_nanotez + minimal_fees_for_size_in_nanotez) + in + let estimated_fees_in_mutez = + z_mutez_of_q_nanotez estimated_fees_in_nanotez + in + let estimated_fees = + match Tez.of_mutez (Z.to_int64 estimated_fees_in_mutez) with + | None -> assert false + | Some fee -> fee + in + if + (not config.force_low_fee) + && Q.compare fees_in_nanotez estimated_fees_in_nanotez < 0 + then + let*! () = + cctxt#error + "The proposed fee (%s%a) are lower than the fee that baker \ + expect by default (%s%a).@\n\ + \ Use `--force-low-fee` to emit this operation anyway." + Operation_result.tez_sym + Tez.pp + fee + Operation_result.tez_sym + Tez.pp + estimated_fees + in + exit 1 + else Lwt.return_unit + +let print_for_verbose_signing ppf ~watermark ~bytes ~branch ~contents = + let open Format in + pp_open_vbox ppf 0 ; + let item f = + pp_open_hovbox ppf 4 ; + pp_print_string ppf " * " ; + f ppf () ; + pp_close_box ppf () ; + pp_print_cut ppf () + in + let hash_pp l = + fprintf + ppf + "%s" + (Tezos_crypto.Base58.raw_encode + Tezos_crypto.Blake2B.(hash_bytes l |> to_string)) + in + item (fun ppf () -> + pp_print_text ppf "Branch: " ; + Block_hash.pp ppf branch) ; + item (fun ppf () -> + fprintf + ppf + "Watermark: `%a` (0x%s)" + Signature.pp_watermark + watermark + (Hex.of_bytes (Signature.bytes_of_watermark watermark) |> Hex.show)) ; + item (fun ppf () -> + pp_print_text ppf "Operation bytes: " ; + TzString.fold_left (* We split the bytes into lines for display: *) + (fun n c -> + pp_print_char ppf c ; + if + n < 72 + (* is the email-body standard width, ideal for copy-pasting. *) + then n + 1 + else ( + pp_print_space ppf () ; + 0)) + 0 + (Hex.of_bytes bytes |> Hex.show) + |> ignore) ; + item (fun ppf () -> + pp_print_text ppf "Blake 2B Hash (raw): " ; + hash_pp [bytes]) ; + item (fun ppf () -> + pp_print_text + ppf + "Blake 2B Hash (ledger-style, with operation watermark): " ; + hash_pp [Signature.bytes_of_watermark watermark; bytes]) ; + let json = + Data_encoding.Json.construct + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + item (fun ppf () -> + pp_print_text ppf "JSON encoding: " ; + Data_encoding.Json.pp ppf json) ; + pp_close_box ppf () + +let preapply (type t) (cctxt : #Protocol_client_context.full) ~chain ~block + ?(verbose_signing = false) ?fee_parameter ?branch ?src_sk + (contents : t contents_list) = + let open Lwt_result_syntax in + let* _chain_id, branch = get_branch cctxt ~chain ~block branch in + let bytes = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + let* signature = + match src_sk with + | None -> return_none + | Some src_sk -> + let watermark = + match contents with + (* TODO-TB sign endorsement? *) + | _ -> Signature.Generic_operation + in + let*! () = + if verbose_signing then + cctxt#message + "Pre-signature information (verbose signing):@.%t%!" + (print_for_verbose_signing ~watermark ~bytes ~branch ~contents) + else Lwt.return_unit + in + let* signature = Client_keys.sign cctxt ~watermark src_sk bytes in + return_some signature + in + let op : _ Operation.t = + {shell = {branch}; protocol_data = {contents; signature}} + in + let oph = Operation.hash op in + let packed_op = + {shell = {branch}; protocol_data = Operation_data {contents; signature}} + in + let size = Data_encoding.Binary.length Operation.encoding packed_op in + let*! () = + match fee_parameter with + | Some fee_parameter -> check_fees cctxt fee_parameter contents size + | None -> Lwt.return_unit + in + let* operations_opt = + Protocol_client_context.Alpha_block_services.Helpers.Preapply.operations + cctxt + ~chain + ~block + [Operation.pack op] + in + match operations_opt with + | [(Operation_data op', Operation_metadata result)] -> ( + match + ( Operation.equal op {shell = {branch}; protocol_data = op'}, + Apply_results.kind_equal_list contents result.contents ) + with + | Some Operation.Eq, Some Apply_results.Eq -> + return ((oph, op, result) : t preapply_result) + | _ -> failwith "Unexpected result") + | _ -> failwith "Unexpected result" + +let simulate (type t) (cctxt : #Protocol_client_context.full) ~chain ~block + ?(successor_level = false) ?branch + ?(latency = Plugin.RPC.default_operation_inclusion_latency) + (contents : t contents_list) = + let open Lwt_result_syntax in + let* _chain_id, branch = get_branch cctxt ~chain ~block branch in + let op : _ Operation.t = + {shell = {branch}; protocol_data = {contents; signature = None}} + in + let oph = Operation.hash op in + let* chain_id = Chain_services.chain_id cctxt ~chain () in + let* operations_opt = + Plugin.RPC.Scripts.simulate_operation + cctxt + (chain, block) + ~successor_level + ~op:(Operation.pack op) + ~chain_id + ~latency + in + match operations_opt with + | Operation_data op', Operation_metadata result -> ( + match + ( Operation.equal op {shell = {branch}; protocol_data = op'}, + Apply_results.kind_equal_list contents result.contents ) + with + | Some Operation.Eq, Some Apply_results.Eq -> + return ((oph, op, result) : t preapply_result) + | _ -> failwith "Unexpected result") + | _ -> failwith "Unexpected result" + +let estimated_gas_single (type kind) + (Manager_operation_result {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let open Result_syntax in + let consumed_gas (type kind) (result : kind manager_operation_result) = + match result with + | Applied res | Backtracked (res, _) -> ( + match res with + | Transaction_result + ( Transaction_to_contract_result {consumed_gas; _} + | Transaction_to_sc_rollup_result {consumed_gas; _} + | Transaction_to_zk_rollup_result {consumed_gas; _} ) + | Origination_result {consumed_gas; _} + | Reveal_result {consumed_gas} + | Delegation_result {consumed_gas; _} + | Register_global_constant_result {consumed_gas; _} + | Set_deposits_limit_result {consumed_gas} + | Update_consensus_key_result {consumed_gas; _} + | Increase_paid_storage_result {consumed_gas; _} + | Transfer_ticket_result {consumed_gas; _} + | Dal_publish_commitment_result {consumed_gas; _} + | Sc_rollup_originate_result {consumed_gas; _} + | Sc_rollup_add_messages_result {consumed_gas; _} + | Sc_rollup_cement_result {consumed_gas; _} + | Sc_rollup_publish_result {consumed_gas; _} + | Sc_rollup_refute_result {consumed_gas; _} + | Sc_rollup_timeout_result {consumed_gas; _} + | Sc_rollup_execute_outbox_message_result {consumed_gas; _} + | Sc_rollup_recover_bond_result {consumed_gas; _} -> + Ok consumed_gas + | Zk_rollup_origination_result {consumed_gas; _} -> Ok consumed_gas + | Zk_rollup_publish_result {consumed_gas; _} -> Ok consumed_gas + | Zk_rollup_update_result {consumed_gas; _} -> Ok consumed_gas) + | Skipped _ -> + error_with "Cannot estimate gas of skipped operation" + (* There must be another error for this to happen, and it should not + surface (the force mode catches it). *) + | Failed (_, errs) -> Error (Environment.wrap_tztrace errs) + in + let internal_consumed_gas (type kind) + (result : kind internal_operation_result) = + match result with + | Applied res | Backtracked (res, _) -> ( + match res with + | ITransaction_result + ( Transaction_to_contract_result {consumed_gas; _} + | Transaction_to_sc_rollup_result {consumed_gas; _} + | Transaction_to_zk_rollup_result {consumed_gas; _} ) + | IOrigination_result {consumed_gas; _} + | IDelegation_result {consumed_gas; _} + | IEvent_result {consumed_gas} -> + Ok consumed_gas) + | Skipped _ -> + Ok Gas.Arith.zero (* there must be another error for this to happen *) + | Failed (_, errs) -> Error (Environment.wrap_tztrace errs) + in + let* gas = consumed_gas operation_result in + List.fold_left_e + (fun acc (Internal_operation_result (_, r)) -> + let* gas = internal_consumed_gas r in + Ok (Gas.Arith.add acc gas)) + gas + internal_operation_results + +let estimated_storage_single (type kind) ~origination_size + (Manager_operation_result {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let open Result_syntax in + let storage_size_diff (type kind) (result : kind manager_operation_result) = + match result with + | Applied res | Backtracked (res, _) -> ( + match res with + | Transaction_result + (Transaction_to_contract_result + {paid_storage_size_diff; allocated_destination_contract; _}) -> + if allocated_destination_contract then + Ok (Z.add paid_storage_size_diff origination_size) + else Ok paid_storage_size_diff + | Origination_result {paid_storage_size_diff; _} -> + Ok (Z.add paid_storage_size_diff origination_size) + | Register_global_constant_result {size_of_constant; _} -> + Ok size_of_constant + | Update_consensus_key_result _ -> Ok Z.zero + | Sc_rollup_execute_outbox_message_result {paid_storage_size_diff; _} + | Transfer_ticket_result {paid_storage_size_diff; _} + | Zk_rollup_publish_result {paid_storage_size_diff; _} + | Zk_rollup_update_result {paid_storage_size_diff; _} + | Transaction_result + (Transaction_to_zk_rollup_result {paid_storage_size_diff; _}) -> + Ok paid_storage_size_diff + | Sc_rollup_originate_result {size; _} -> Ok size + | Zk_rollup_origination_result {storage_size; _} -> Ok storage_size + | Transaction_result (Transaction_to_sc_rollup_result _) + | Reveal_result _ | Delegation_result _ | Set_deposits_limit_result _ + | Increase_paid_storage_result _ | Dal_publish_commitment_result _ + | Sc_rollup_add_messages_result _ + (* The following Sc_rollup operations have zero storage cost because we + consider them to be paid in the stake deposit. + + TODO: https://gitlab.com/tezos/tezos/-/issues/2686 + Document why this is safe. + *) + | Sc_rollup_cement_result _ | Sc_rollup_publish_result _ + | Sc_rollup_refute_result _ | Sc_rollup_timeout_result _ + | Sc_rollup_recover_bond_result _ -> + Ok Z.zero) + | Skipped _ -> + error_with "Cannot estimate storage of skipped operation" + (* There must be another error for this to happen, and it should not + surface (the force mode catches it). *) + | Failed (_, errs) -> Error (Environment.wrap_tztrace errs) + in + let internal_storage_size_diff (type kind) + (result : kind internal_operation_result) = + match result with + | Applied res | Backtracked (res, _) -> ( + match res with + | ITransaction_result + (Transaction_to_contract_result + {paid_storage_size_diff; allocated_destination_contract; _}) -> + if allocated_destination_contract then + Ok (Z.add paid_storage_size_diff origination_size) + else Ok paid_storage_size_diff + | IOrigination_result {paid_storage_size_diff; _} -> + Ok (Z.add paid_storage_size_diff origination_size) + | ITransaction_result + (Transaction_to_zk_rollup_result {paid_storage_size_diff; _}) -> + Ok paid_storage_size_diff + | ITransaction_result (Transaction_to_sc_rollup_result _) + | IDelegation_result _ | IEvent_result _ -> + Ok Z.zero) + | Skipped _ -> + Ok Z.zero (* there must be another error for this to happen *) + | Failed (_, errs) -> Error (Environment.wrap_tztrace errs) + in + let* storage = storage_size_diff operation_result in + List.fold_left_e + (fun acc (Internal_operation_result (_, r)) -> + let* storage = internal_storage_size_diff r in + Ok (Z.add acc storage)) + storage + internal_operation_results + +let estimated_storage ~origination_size res = + let open Result_syntax in + let rec estimated_storage : type kind. kind contents_result_list -> _ = + function + | Single_result (Manager_operation_result _ as res) -> + estimated_storage_single ~origination_size res + | Single_result _ -> Ok Z.zero + | Cons_result (res, rest) -> + let* storage1 = estimated_storage_single ~origination_size res in + let* storage2 = estimated_storage rest in + Ok (Z.add storage1 storage2) + in + let* diff = estimated_storage res in + Ok (Z.max Z.zero diff) + +let originated_contracts_single (type kind) + (Manager_operation_result {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let open Result_syntax in + let originated_contracts (type kind) (result : kind manager_operation_result) + = + match result with + | Applied res | Backtracked (res, _) -> ( + match res with + | Transaction_result + (Transaction_to_contract_result {originated_contracts; _}) + | Origination_result {originated_contracts; _} -> + Ok originated_contracts + | Transaction_result + ( Transaction_to_sc_rollup_result _ + | Transaction_to_zk_rollup_result _ ) + | Register_global_constant_result _ | Reveal_result _ + | Delegation_result _ | Set_deposits_limit_result _ + | Update_consensus_key_result _ | Increase_paid_storage_result _ + | Transfer_ticket_result _ | Dal_publish_commitment_result _ + | Sc_rollup_originate_result _ | Sc_rollup_add_messages_result _ + | Sc_rollup_cement_result _ | Sc_rollup_publish_result _ + | Sc_rollup_refute_result _ | Sc_rollup_timeout_result _ + | Sc_rollup_execute_outbox_message_result _ + | Sc_rollup_recover_bond_result _ | Zk_rollup_origination_result _ + | Zk_rollup_publish_result _ | Zk_rollup_update_result _ -> + return_nil) + | Skipped _ -> + error_with "Cannot know originated contracts of skipped operation" + (* There must be another error for this to happen, and it should not + surface (the force mode catches it). *) + | Failed (_, errs) -> Error (Environment.wrap_tztrace errs) + in + let internal_originated_contracts (type kind) + (result : kind internal_operation_result) = + match result with + | Applied res | Backtracked (res, _) -> ( + match res with + | ITransaction_result + (Transaction_to_contract_result {originated_contracts; _}) + | IOrigination_result {originated_contracts; _} -> + Ok originated_contracts + | ITransaction_result + ( Transaction_to_sc_rollup_result _ + | Transaction_to_zk_rollup_result _ ) + | IDelegation_result _ | IEvent_result _ -> + return_nil) + | Skipped _ -> + return_nil (* there must be another error for this to happen *) + | Failed (_, errs) -> Error (Environment.wrap_tztrace errs) + in + let* contracts = originated_contracts operation_result in + let contracts = List.rev contracts in + List.fold_left_e + (fun acc (Internal_operation_result (_, r)) -> + let* contracts = internal_originated_contracts r in + Ok (List.rev_append contracts acc)) + contracts + internal_operation_results + +let rec originated_contracts : type kind. kind contents_result_list -> _ = + let open Result_syntax in + function + | Single_result (Manager_operation_result _ as res) -> + let* l = originated_contracts_single res in + return @@ List.rev l + | Single_result _ -> return_nil + | Cons_result (res, rest) -> + let* contracts1 = originated_contracts_single res in + let* contracts2 = originated_contracts rest in + Ok (List.rev_append contracts1 contracts2) + +let estimated_storage_single ~force ~origination_size result = + match estimated_storage_single ~origination_size result with + | Error _ when force -> Ok Z.zero + | res -> res + +let estimated_storage ~force ~origination_size result = + match estimated_storage ~origination_size result with + | Error _ when force -> Ok Z.zero + | res -> res + +(* When --force is used, we don't want [originated_contracts] to fail as + it would stop the client before the injection of the operation. *) +let originated_contracts ~force results = + match originated_contracts results with + | Error _ when force -> Result_syntax.return_nil + | e -> e + +let detect_script_failure : type kind. kind operation_metadata -> _ = + let open Result_syntax in + let rec detect_script_failure : type kind. kind contents_result_list -> _ = + let detect_script_failure_single (type kind) + (Manager_operation_result + {operation_result; internal_operation_results; _} : + kind Kind.manager contents_result) = + let detect_script_failure (type kind) + (result : (kind, _, _) operation_result) = + match result with + | Applied _ -> return_unit + | Skipped _ -> assert false + | Backtracked (_, None) -> + (* there must be another error for this to happen *) + return_unit + | Backtracked (_, Some errs) -> + record_trace + (error_of_fmt "The transfer simulation failed.") + (Error (Environment.wrap_tztrace errs)) + | Failed (_, errs) -> + record_trace + (error_of_fmt "The transfer simulation failed.") + (Error (Environment.wrap_tztrace errs)) + in + let* () = detect_script_failure operation_result in + List.iter_e + (fun (Internal_operation_result (_, r)) -> detect_script_failure r) + internal_operation_results + in + function + | Single_result (Manager_operation_result _ as res) -> + detect_script_failure_single res + | Single_result _ -> return_unit + | Cons_result (res, rest) -> + let* () = detect_script_failure_single res in + detect_script_failure rest + in + fun {contents} -> detect_script_failure contents + +let signature_size_of_algo : Signature.algo -> int = function + | Ed25519 -> Signature.Ed25519.size + | Secp256k1 -> Signature.Secp256k1.size + | P256 -> Signature.P256.size + | Bls -> + (* BLS signatures in operations are encoded with 2 extra bytes: a [ff] + prefix and a tag [03]. *) + Signature.Bls.size + 2 + +(* This value is used as a safety guard for gas limit. *) +let default_safety_guard = Gas.Arith.(integral_of_int_exn 100) + +(* + + {2 High-level description of the automatic gas patching algorithm} + + When the user wants to inject a list of operations, some of which + might have unspecified gas, fees or storage limit, the client + performs a {e simulation} to estimate those limits and assign + sensible values to them. + + The simulation works as follows: + 1. limits are assigned to dummy, high values to ensure that the operations + can be simulated + - 1.a) when a list of operations is partially specified, the algorithm + allocates to each unspecified operation an equal portion of the + maximum gas per block minus the gas consumed by the operations that + do specify their limit + 2. the algorithm retrieves the effectively consumed gas and storage from the + receipt + 3. the algorithm assigns slight over-approximations to the operation + 4. a default fee is computed and set + +*) + +let may_patch_limits (type kind) (cctxt : #Protocol_client_context.full) + ~fee_parameter ~signature_algo ~chain ~block ?successor_level ?branch + ?(force = false) ?(simulation = false) ?safety_guard + (annotated_contents : kind Annotated_manager_operation.annotated_list) : + kind Kind.manager contents_list tzresult Lwt.t = + let open Lwt_result_syntax in + let* () = + Tezos_client_base.Client_confirmations.wait_for_bootstrapped cctxt + in + let* { + parametric = + { + hard_gas_limit_per_operation; + hard_gas_limit_per_block; + hard_storage_limit_per_operation; + origination_size; + cost_per_byte; + _; + }; + _; + } = + Alpha_services.Constants.all cctxt (chain, block) + in + let user_gas_limit_needs_patching user_gas_limit = + Limit.fold user_gas_limit ~unknown:true ~known:(fun user_gas_limit -> + Gas.Arith.( + user_gas_limit < zero || hard_gas_limit_per_operation < user_gas_limit)) + in + let user_storage_limit_needs_patching user_storage_limit = + Limit.fold + user_storage_limit + ~unknown:true + ~known:(fun user_storage_limit -> + Z.Compare.( + user_storage_limit < Z.zero + || hard_storage_limit_per_operation < user_storage_limit)) + in + let gas_patching_stats (Annotated_manager_operation.Manager_info c) + need_patching gas_consumed = + if user_gas_limit_needs_patching c.gas_limit then + (need_patching + 1, gas_consumed) + else + ( need_patching, + Gas.Arith.add + gas_consumed + (Limit.value ~when_unknown:Gas.Arith.zero c.gas_limit) ) + in + let rec gas_patching_stats_list : + type kind. + kind Annotated_manager_operation.annotated_list -> + int -> + Gas.Arith.integral -> + int * Gas.Arith.integral = + fun op need_patching gas_consumed -> + match op with + | Single_manager minfo -> + gas_patching_stats minfo need_patching gas_consumed + | Cons_manager (minfo, rest) -> + let need_patching, gas_consumed = + gas_patching_stats minfo need_patching gas_consumed + in + gas_patching_stats_list rest need_patching gas_consumed + in + let gas_limit_per_patched_op = + let need_gas_patching, gas_consumed = + gas_patching_stats_list annotated_contents 0 Gas.Arith.zero + in + if need_gas_patching = 0 then hard_gas_limit_per_operation + else + let remaining_gas = Gas.Arith.sub hard_gas_limit_per_block gas_consumed in + let average_per_operation_gas = + Gas.Arith.integral_exn + @@ Z.div + (Gas.Arith.integral_to_z remaining_gas) + (Z.of_int need_gas_patching) + in + Gas.Arith.min hard_gas_limit_per_operation average_per_operation_gas + in + let may_need_patching_single : + type kind. + kind Annotated_manager_operation.t -> + kind Annotated_manager_operation.t option = + fun op -> + match op with + | Manager_info c -> + let needs_patching = + Limit.is_unknown c.fee + || user_gas_limit_needs_patching c.gas_limit + || user_storage_limit_needs_patching c.storage_limit + in + if not needs_patching then None + else + (* Set limits for simulation purposes *) + let gas_limit = + if user_gas_limit_needs_patching c.gas_limit then + Limit.known gas_limit_per_patched_op + else c.gas_limit + in + let storage_limit = + if user_storage_limit_needs_patching c.storage_limit then + Limit.known hard_storage_limit_per_operation + else c.storage_limit + in + let fee = Limit.value ~when_unknown:Tez.zero c.fee in + Some + (Manager_info + {c with gas_limit; storage_limit; fee = Limit.known fee}) + in + let may_need_patching ops = + let rec loop : + type kind. + kind Annotated_manager_operation.annotated_list -> + kind Annotated_manager_operation.annotated_list option = function + | Single_manager annotated_op -> + Option.map (fun op -> Annotated_manager_operation.Single_manager op) + @@ may_need_patching_single annotated_op + | Cons_manager (annotated_op, rest) -> ( + let annotated_op_opt = may_need_patching_single annotated_op in + let rest_opt = loop rest in + match (annotated_op_opt, rest_opt) with + | None, None -> None + | _ -> + let op = Option.value ~default:annotated_op annotated_op_opt in + let rest = Option.value ~default:rest rest_opt in + Some (Cons_manager (op, rest))) + in + loop ops + in + (* + The recursion here handles the case where an increased fee might increase the + size of the operation, and so require a recalculation of the gas costs. + Rationale for termination: + - the fee for size increases linearly with the size of the operation. + - however, when the size of the operation increase to make space for an + increased fee, the amount of new fee that can be added without increasing + the size of the block again increases exponentially. + - hence, there will eventually be a increase of size that will fit any new + fee without having to increase the size of the operation again. + *) + let rec patch_fee : type kind. first:bool -> kind contents -> kind contents = + fun ~first -> function + | Manager_operation c as op -> ( + let size = + if first then + (WithExceptions.Option.get ~loc:__LOC__ + @@ Data_encoding.Binary.fixed_length + Tezos_base.Operation.shell_header_encoding) + + Data_encoding.Binary.length + Operation.contents_encoding + (Contents op) + + signature_size_of_algo signature_algo + else + Data_encoding.Binary.length + Operation.contents_encoding + (Contents op) + in + let minimal_fees_in_nanotez = + Q.mul + (Q.of_int64 (Tez.to_mutez fee_parameter.minimal_fees)) + (Q.of_int 1000) + in + let minimal_fees_for_gas_in_nanotez = + Q.mul + fee_parameter.minimal_nanotez_per_gas_unit + (Q.of_bigint @@ Gas.Arith.integral_to_z c.gas_limit) + in + let minimal_fees_for_size_in_nanotez = + Q.mul fee_parameter.minimal_nanotez_per_byte (Q.of_int size) + in + let fees_in_nanotez = + Q.add minimal_fees_in_nanotez + @@ Q.add + minimal_fees_for_gas_in_nanotez + minimal_fees_for_size_in_nanotez + in + let fees_in_mutez = z_mutez_of_q_nanotez fees_in_nanotez in + match Tez.of_mutez (Z.to_int64 fees_in_mutez) with + | None -> assert false + | Some fee -> + if Tez.(fee <= c.fee) then op + else patch_fee ~first (Manager_operation {c with fee})) + | c -> c + in + let patch : + type kind. + first:bool -> + kind Annotated_manager_operation.t * kind Kind.manager contents_result -> + kind Kind.manager contents tzresult Lwt.t = + fun ~first -> function + | (Manager_info c as op), (Manager_operation_result _ as result) -> + let* op = + if user_gas_limit_needs_patching c.gas_limit then + let*! gas = Lwt.return (estimated_gas_single result) in + match gas with + | Error _ when force -> + (* When doing a simulation, set gas to the maximum possible value + so as to not change the error. When force injecting a failing + operation, set gas to zero to not pay fees for this + operation. *) + let gas = + if simulation then gas_limit_per_patched_op + else Gas.Arith.zero + in + return + (Annotated_manager_operation.set_gas_limit + (Limit.known gas) + op) + | Error _ as res -> Lwt.return res + | Ok gas -> + if Gas.Arith.(gas = zero) then + let*! () = cctxt#message "Estimated gas: none" in + return + (Annotated_manager_operation.set_gas_limit + (Limit.known Gas.Arith.zero) + op) + else + let default_safety_guard = + match c.operation with + | Transaction {destination = Implicit _; _} + | Reveal _ | Delegation _ | Set_deposits_limit _ + | Increase_paid_storage _ -> + Gas.Arith.zero + | _ -> default_safety_guard + in + let safety_guard = + Option.value safety_guard ~default:default_safety_guard + in + let*! () = + cctxt#message + "Estimated gas: %a units (will add %a for safety)" + Gas.Arith.pp + gas + Gas.Arith.pp + safety_guard + in + let safe_gas = Gas.Arith.(add (ceil gas) safety_guard) in + let patched_gas = + Gas.Arith.min safe_gas hard_gas_limit_per_operation + in + return + (Annotated_manager_operation.set_gas_limit + (Limit.known patched_gas) + op) + else return op + in + let* op = + if user_storage_limit_needs_patching c.storage_limit then + let*? storage = + estimated_storage_single + ~origination_size:(Z.of_int origination_size) + ~force + result + in + if Z.equal storage Z.zero then + let*! () = cctxt#message "Estimated storage: no bytes added" in + return + (Annotated_manager_operation.set_storage_limit + (Limit.known Z.zero) + op) + else + let*! () = + cctxt#message + "Estimated storage: %s bytes added (will add 20 for safety)" + (Z.to_string storage) + in + let storage_limit = + Z.min + (Z.add storage (Z.of_int 20)) + hard_storage_limit_per_operation + in + return + (Annotated_manager_operation.set_storage_limit + (Limit.known storage_limit) + op) + else return op + in + if Limit.is_unknown c.fee then + (* Setting a dummy fee is required for converting to manager op *) + let op = + Annotated_manager_operation.set_fee (Limit.known Tez.zero) op + in + let*? cm = Annotated_manager_operation.manager_from_annotated op in + return (patch_fee ~first cm) + else Lwt.return (Annotated_manager_operation.manager_from_annotated op) + in + let rec patch_list : + type kind. + bool -> + kind Annotated_manager_operation.annotated_list -> + kind Kind.manager contents_result_list -> + kind Kind.manager contents_list tzresult Lwt.t = + fun first annotated_list result_list -> + match (annotated_list, result_list) with + | Single_manager annotated, Single_result res -> + let* op = patch ~first (annotated, res) in + return (Single op) + | Cons_manager (annotated, annotated_rest), Cons_result (res, res_rest) -> + let* op = patch ~first (annotated, res) in + let* rest = patch_list false annotated_rest res_rest in + return (Cons (op, rest)) + | _ -> assert false + in + match may_need_patching annotated_contents with + | Some annotated_for_simulation -> + let*? contents_for_simulation = + Annotated_manager_operation.manager_list_from_annotated + annotated_for_simulation + in + let* _, _, result = + simulate + cctxt + ~chain + ~block + ?successor_level + ?branch + contents_for_simulation + in + let* () = + match detect_script_failure result with + | Ok () -> return_unit + | Error _ -> + let*! () = + cctxt#message + "@[This simulation failed:@,%a@]" + Operation_result.pp_operation_result + (contents_for_simulation, result.contents) + in + return_unit + in + let* () = + let*? storage = + estimated_storage + ~origination_size:(Z.of_int origination_size) + ~force + result.contents + in + let*? burn = + Environment.wrap_tzresult Tez.(cost_per_byte *? Z.to_int64 storage) + in + if Tez.(burn > fee_parameter.burn_cap) then + let*! () = + cctxt#error + "The operation will burn %s%a which is higher than the \ + configured burn cap (%s%a).@\n\ + \ Use `--burn-cap %a` to emit this operation." + Operation_result.tez_sym + Tez.pp + burn + Operation_result.tez_sym + Tez.pp + fee_parameter.burn_cap + Tez.pp + burn + in + exit 1 + else return_unit + in + patch_list true annotated_contents result.contents + | None -> + Lwt.return + (Annotated_manager_operation.manager_list_from_annotated + annotated_contents) + +let tenderbake_finality_confirmations = 1 + +let tenderbake_adjust_confirmations (cctxt : #Client_context.full) = + let open Lwt_result_syntax in + function + | None -> Lwt.return_none + | Some cli_confirmations -> + if cli_confirmations > tenderbake_finality_confirmations then + let*! () = + cctxt#message + "Tenderbake needs at most %d confirmations for finality (%d \ + given). Using %d confirmations." + tenderbake_finality_confirmations + cli_confirmations + tenderbake_finality_confirmations + in + Lwt.return_some tenderbake_finality_confirmations + else Lwt.return_some cli_confirmations + +(* For Tenderbake we restrain the interval of confirmations to be [0, + tenderbake_finality_confirmations] + + Any value greater than the tenderbake_finality_confirmations is treated as if it + were tenderbake_finality_confirmations. +*) +let inject_operation_internal (type kind) cctxt ~chain ~block ?confirmations + ?(dry_run = false) ?(simulation = false) ?(force = false) ?successor_level + ?branch ?src_sk ?verbose_signing ?fee_parameter + (contents : kind contents_list) = + let open Lwt_result_syntax in + let* _oph, op, result = + if simulation then + simulate cctxt ~chain ~block ?successor_level ?branch contents + else + preapply + cctxt + ~chain + ~block + ?fee_parameter + ?verbose_signing + ?branch + ?src_sk + contents + in + let* () = + match detect_script_failure result with + | Ok () -> return_unit + | Error _ as res -> + let*! () = + cctxt#message + "@[This simulation failed (force = %b):@,%a@]" + force + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents) + in + if force then return_unit else Lwt.return res + in + let bytes = + Data_encoding.Binary.to_bytes_exn Operation.encoding (Operation.pack op) + in + if dry_run || simulation then + let oph = Operation_hash.hash_bytes [bytes] in + let*! () = + cctxt#message + "@[Operation: 0x%a@,Operation hash is '%a'@]" + Hex.pp + (Hex.of_bytes bytes) + Operation_hash.pp + oph + in + let*! () = + cctxt#message + "@[Simulation result:@,%a@]" + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents) + in + return (oph, op, result.contents) + else + let* oph = Shell_services.Injection.operation cctxt ~chain bytes in + let*! () = cctxt#message "Operation successfully injected in the node." in + let*! () = cctxt#message "Operation hash is '%a'" Operation_hash.pp oph in + (* Adjust user-provided confirmations with respect to Alpha protocol finality properties *) + let*! confirmations = tenderbake_adjust_confirmations cctxt confirmations in + let* result = + match confirmations with + | None -> + let*! () = + cctxt#message + "@[NOT waiting for the operation to be included.@,\ + Use command@,\ + \ octez-client wait for %a to be included --confirmations %d \ + --branch %a@,\ + and/or an external block explorer to make sure that it has been \ + included.@]" + Operation_hash.pp + oph + tenderbake_finality_confirmations + Block_hash.pp + op.shell.branch + in + return result + | Some confirmations -> ( + let*! () = + cctxt#message "Waiting for the operation to be included..." + in + let* h, i, j = + Client_confirmations.wait_for_operation_inclusion + ~branch:op.shell.branch + ~confirmations + cctxt + ~chain + oph + in + let* op' = + Alpha_block_services.Operations.operation + cctxt + ~chain + ~block:(`Hash (h, 0)) + i + j + in + match op'.receipt with + | Empty -> failwith "Internal error: pruned metadata." + | Too_large -> failwith "Internal error: too large metadata." + | Receipt No_operation_metadata -> + let*! () = + cctxt#message + "The operation metadata was not stored because it was too \ + big, thus the failure to display the receipt." + in + failwith "Internal error: unexpected receipt." + | Receipt (Operation_metadata receipt) -> ( + match Apply_results.kind_equal_list contents receipt.contents with + | Some Apply_results.Eq -> + return (receipt : kind operation_metadata) + | None -> failwith "Internal error: unexpected receipt.")) + in + let*! () = + cctxt#message + "@[This sequence of operations was run:@,%a@]" + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents) + in + let*? contracts = originated_contracts result.contents ~force in + let*! () = + List.iter_s + (fun c -> + cctxt#message "New contract %a originated." Contract_hash.pp c) + contracts + in + let*! () = + match confirmations with + | None -> Lwt.return_unit + | Some number -> + if number >= tenderbake_finality_confirmations then + cctxt#message + "The operation was included in a block %d blocks ago." + number + else + cctxt#message + "@[The operation has only been included %d blocks ago.@,\ + We recommend to wait more.@,\ + Use command@,\ + \ octez-client wait for %a to be included --confirmations %d \ + --branch %a@,\ + and/or an external block explorer.@]" + number + Operation_hash.pp + oph + tenderbake_finality_confirmations + Block_hash.pp + op.shell.branch + in + return (oph, op, result.contents) + +let inject_operation (type kind) cctxt ~chain ~block ?confirmations + ?(dry_run = false) ?(simulation = false) ?successor_level ?branch ?src_sk + ?verbose_signing ?fee_parameter (contents : kind contents_list) = + let open Lwt_result_syntax in + let* () = + Tezos_client_base.Client_confirmations.wait_for_bootstrapped cctxt + in + let* oph, op, result = + inject_operation_internal + cctxt + ~chain + ~block + ?confirmations + ~dry_run + ~simulation + ?successor_level + ?branch + ?src_sk + ?verbose_signing + ?fee_parameter + (contents : kind contents_list) + in + return (oph, op.protocol_data.contents, result) + +let prepare_manager_operation ~fee ~gas_limit ~storage_limit operation = + Annotated_manager_operation.Manager_info + {source = None; fee; gas_limit; storage_limit; counter = None; operation} + +let reveal_error_message = + "Requested operation requires to perform a public key revelation beforehand.\n\ + This cannot be done automatically when a custom fee or storage limit is \ + given.\n\ + If you wish to use a custom fee or storage limit, please first perform the \ + reveal operation separately using the dedicated command.\n\ + Otherwise, please do not specify custom fee or storage parameters." + +let reveal_error (cctxt : #Protocol_client_context.full) = + cctxt#error "%s" reveal_error_message + +(* This function first gets the pending operations in the prevalidator. Then, + it filters those that have an applied status from the given src. *) +let pending_applied_operations_of_source (cctxt : #full) chain src : + packed_contents_list list Lwt.t = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2273 + Be able to get pending/validated operation of an implicit account. + *) + let open Lwt_result_syntax in + let*! ops_opt = + Alpha_block_services.Mempool.pending_operations cctxt ~chain () + in + match ops_opt with + | Error e -> + let*! () = + cctxt#error + "Error while fetching pending operations: %a@." + Error_monad.pp_print_trace + e + in + exit 1 + | Ok ops -> + Lwt.return + @@ List.fold_left + (fun acc (_oph, {protocol_data = Operation_data {contents; _}; _}) -> + match contents with + | Single (Manager_operation {source; _} as _op) + when Signature.Public_key_hash.equal source src -> + Contents_list contents :: acc + | Cons (Manager_operation {source; _}, _rest) as _op + when Signature.Public_key_hash.equal source src -> + Contents_list contents :: acc + | _ -> acc) + [] + ops.Alpha_block_services.Mempool.validated + +(* Given the gas and fee of an applied operation in the mempool, and the + estimated gas of a new operation to inject, this function returns + the amount of fee to put in the new operation to be able to replace + the one already in the mempool *) +let compute_replacement_fees = + let open Lwt_result_syntax in + let q_fee_from_tez f = Tez.to_mutez f |> Z.of_int64 |> Q.of_bigint in + let q_gas g = Gas.Arith.integral_to_z g |> Q.of_bigint in + fun (cctxt : #full) old_op_fee old_op_gas new_op_gas -> + (* convert quantities to rationals *) + let old_op_fee = q_fee_from_tez old_op_fee in + let old_op_gas = q_gas old_op_gas in + let new_op_gas = q_gas new_op_gas in + + (* compute the fee / gas ratio of the old operation *) + let old_op_ratio = Q.div old_op_fee old_op_gas in + + (* compute the equivalent (proportional) in fees of the new operation using + the old operation's ratio *) + let proportional_fee = Q.mul old_op_ratio new_op_gas in + + (* Fees cannot be smaller than estimated fees of the old or new op *) + let max_fee = Q.max proportional_fee old_op_fee in + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2274 + Get the factor 1.05% from the plugin via an RPC *) + let repl_q_fee = Q.mul max_fee (Q.make (Z.of_int 105) (Z.of_int 100)) in + let repl_z_fee = Z.cdiv (Q.num repl_q_fee) (Q.den repl_q_fee) in + try + match Z.to_int64 repl_z_fee |> Tez.of_mutez with + | Some replacement_fee -> Lwt.return replacement_fee + | None -> + let*! () = + cctxt#error "Tez underflow while computing replacement fee@." + in + exit 1 + with Z.Overflow -> + let*! () = cctxt#error "Tez overflow while computing replacement fee@." in + exit 1 + +(* Given an operation to inject whose gas and fee are set, and the amount + of fee the operation should pay to replace an existing applied operation + in the mempool, this function computes the delta "replacement fee - + operation's fee" and adds it to the operation. *) +let bump_manager_op_fee = + (* Internal function to bump the fee of a manager operation by a delta *) + let open Lwt_result_syntax in + let bump_manager (cctxt : #full) delta = function + | Manager_operation + {source; fee; counter; operation; gas_limit; storage_limit} -> + let* fee = + match Tez.( +? ) fee delta with + | Error _ -> + let* () = + cctxt#error "Tez overflow while computing replacement fee@." + in + exit 1 + | Ok new_fee -> return new_fee + in + return + @@ Manager_operation + {source; fee; counter; operation; gas_limit; storage_limit} + in + fun (type kind) + (cctxt : #full) + (contents : kind Kind.manager contents_list) + new_fee + replacement_fee + ~user_fee -> + (* We compute delta replacement_fee - new_fee *) + match Tez.sub_opt replacement_fee new_fee with + | None -> + (* This can happen for instance if the user provided fee with + command-line that are higher than the replacement threshold *) + Lwt.return_ok contents + | Some delta -> + if Tez.equal delta Tez.zero then + (* This can happen for instance if the user provided fee with + command-line that are equal to the replacement threshold *) + Lwt.return_ok contents + else if Limit.is_unknown user_fee then + match contents with + | Single (Manager_operation _ as op) -> + (* We add the delta to the op in case it's a Single *) + let* op = bump_manager (cctxt : #full) delta op in + Lwt.return_ok @@ Single op + | Cons ((Manager_operation _ as op), rest) -> + (* We add the delta to the first op in case it's a batch *) + let* op = bump_manager (cctxt : #full) delta op in + Lwt.return_ok @@ Cons (op, rest) + else + let* () = + cctxt#error + "The fee provided by the user is lower than the expected \ + replacement fee. Threshold is %a but got %a.@." + Tez.pp + replacement_fee + Tez.pp + new_fee + (* New fee in this case correspond to provided user fee *) + in + exit 1 + +(* Bump the fee of the given operation whose fee have been computed by + simulation, to be able to replace an existing applied operation in the + mempool from the same source *) +let replace_operation (type kind) (cctxt : #full) chain source + (contents : kind Kind.manager contents_list) ~user_fee : + kind Kind.manager contents_list tzresult Lwt.t = + let open Lwt_result_syntax in + let exit_err ~is_new_op e = + let* () = + cctxt#error + "Unexpected error while getting gas and fees of user's %s operation.@.\n\ + Error: %a@." + (if is_new_op then "new" else "old") + Error_monad.pp_print_trace + (Environment.wrap_tztrace e) + in + exit 1 + in + match Contents_list contents |> get_manager_operation_gas_and_fee with + | Error e -> exit_err ~is_new_op:true e + | Ok (new_op_fee, new_op_gas) -> ( + let*! contents_list = + pending_applied_operations_of_source cctxt chain source + in + match contents_list with + | [] -> + let*! () = + cctxt#error + "Cannot replace! No validated manager operation found for %a in \ + mempool@." + Signature.Public_key_hash.pp + source + in + exit 1 + | _ :: _ :: _ as l -> + let*! () = + cctxt#error + "More than one validated manager operation found for %a in \ + mempool. Found %d operations.@." + Signature.Public_key_hash.pp + source + (List.length l) + in + exit 1 + | [old_contents] -> ( + get_manager_operation_gas_and_fee old_contents |> function + | Error e -> exit_err ~is_new_op:false e + | Ok (old_op_fee, old_op_gas) -> + let*! delta = + compute_replacement_fees cctxt old_op_fee old_op_gas new_op_gas + in + bump_manager_op_fee cctxt contents new_op_fee ~user_fee delta)) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2276 + https://gitlab.com/tezos/tezos/-/issues/2276 *) +let may_replace_operation (type kind) (cctxt : #full) chain from + ~replace_by_fees ~user_fee (contents : kind Kind.manager contents_list) : + kind Kind.manager contents_list tzresult Lwt.t = + if replace_by_fees then replace_operation cctxt chain from contents ~user_fee + else (* No replace by fees requested *) + Lwt.return_ok contents + +let apply_specified_options counter op source fee gas_limit storage_limit = + let open Result_syntax in + let* op = Annotated_manager_operation.set_source source op in + let* op = Annotated_manager_operation.set_counter counter op in + let* op = Annotated_manager_operation.join_fee fee op in + let* op = Annotated_manager_operation.join_gas_limit gas_limit op in + Annotated_manager_operation.join_storage_limit storage_limit op + +let rec build_contents : + type kind. + Manager_counter.t -> + kind Annotated_manager_operation.annotated_list -> + public_key_hash -> + Tez.t Limit.t -> + Gas.Arith.integral Limit.t -> + Z.t Limit.t -> + kind Annotated_manager_operation.annotated_list tzresult = + let open Result_syntax in + fun counter op source fee gas_limit storage_limit -> + match op with + | Single_manager op -> + let* op = + apply_specified_options counter op source fee gas_limit storage_limit + in + return (Annotated_manager_operation.Single_manager op) + | Cons_manager (op, rest) -> + let* op = + apply_specified_options counter op source fee gas_limit storage_limit + in + let* rest = + build_contents + (Manager_counter.succ counter) + rest + source + fee + gas_limit + storage_limit + in + return (Annotated_manager_operation.Cons_manager (op, rest)) + +let inject_manager_operation cctxt ~chain ~block ?successor_level ?branch + ?confirmations ?dry_run ?verbose_signing ?simulation ?force ?safety_guard + ~source ~(src_pk : public_key) ~src_sk ~fee ~gas_limit ~storage_limit + ?counter ?(replace_by_fees = false) ~fee_parameter (type kind) + (operations : kind Annotated_manager_operation.annotated_list) : + (Operation_hash.t + * packed_operation + * kind Kind.manager contents_list + * kind Kind.manager contents_result_list) + tzresult + Lwt.t = + let open Lwt_result_syntax in + let* counter = + match counter with + | None -> + let* pcounter = + Alpha_services.Contract.counter cctxt (chain, block) source + in + let counter = Manager_counter.succ pcounter in + return counter + | Some counter -> return counter + in + let* key = Alpha_services.Contract.manager_key cctxt (chain, block) source in + (* [has_reveal] assumes that a Reveal operation only appears as the first of a batch *) + let has_reveal : + type kind. kind Annotated_manager_operation.annotated_list -> bool = + function + | Single_manager (Manager_info {operation = Reveal _; _}) -> true + | Cons_manager (Manager_info {operation = Reveal _; _}, _) -> true + | _ -> false + in + let signature_algo = + match src_pk with + | Ed25519 _ -> Signature.Ed25519 + | Secp256k1 _ -> Secp256k1 + | P256 _ -> P256 + | Bls _ -> Bls + in + match key with + | None when not (has_reveal operations) -> ( + let* () = + if not (Limit.is_unknown fee && Limit.is_unknown storage_limit) then + reveal_error cctxt + else return_unit + in + let reveal = + prepare_manager_operation + ~fee:Limit.unknown + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + (Reveal src_pk) + in + let*? reveal = Annotated_manager_operation.set_source source reveal in + let*? reveal = Annotated_manager_operation.set_counter counter reveal in + let*? rest = + build_contents + (Manager_counter.succ counter) + operations + source + fee + gas_limit + storage_limit + in + let contents = Annotated_manager_operation.Cons_manager (reveal, rest) in + let* contents = + let* contents = + may_patch_limits + cctxt + ~fee_parameter + ~signature_algo + ~chain + ~block + ?force + ?simulation + ?safety_guard + ?successor_level + ?branch + contents + in + (may_replace_operation + cctxt + chain + source + ~replace_by_fees + ~user_fee:fee) + contents + in + let* oph, op, result = + inject_operation_internal + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?simulation + ?force + ~fee_parameter + ?verbose_signing + ?successor_level + ?branch + ~src_sk + contents + in + match pack_contents_list op.protocol_data.contents result with + | Cons_and_result (_, _, rest) -> + let second_op, second_result = unpack_contents_list rest in + return (oph, Operation.pack op, second_op, second_result) + | _ -> assert false) + | Some _ when has_reveal operations -> + failwith "The manager key was previously revealed." + | _ -> + let*? contents = + build_contents counter operations source fee gas_limit storage_limit + in + let* contents = + let* contents = + may_patch_limits + cctxt + ~fee_parameter + ~signature_algo + ~chain + ~block + ?force + ?simulation + ?safety_guard + ?successor_level + ?branch + contents + in + (may_replace_operation + cctxt + chain + source + ~replace_by_fees + ~user_fee:fee) + contents + in + let* oph, op, result = + inject_operation_internal + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?force + ~fee_parameter + ?successor_level + ?branch + ~src_sk + contents + in + return (oph, Operation.pack op, op.protocol_data.contents, result) diff --git a/src/proto_020_PsParisC/lib_client/injection.mli b/src/proto_020_PsParisC/lib_client/injection.mli new file mode 100644 index 000000000000..f0ce1449c37f --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/injection.mli @@ -0,0 +1,128 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results + +type 'kind preapply_result = + Operation_hash.t * 'kind operation * 'kind operation_metadata + +type fee_parameter = { + minimal_fees : Tez.t; + minimal_nanotez_per_byte : Q.t; + minimal_nanotez_per_gas_unit : Q.t; + force_low_fee : bool; + fee_cap : Tez.t; + burn_cap : Tez.t; +} + +val preapply : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?verbose_signing:bool -> + ?fee_parameter:fee_parameter -> + ?branch:int -> + ?src_sk:Client_keys.sk_uri -> + 'kind contents_list -> + 'kind preapply_result tzresult Lwt.t + +(** Perform simulation of the given operations and return the corresponding + [preapply_result]s. *) +val simulate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?successor_level:bool -> + ?branch:int -> + ?latency:int -> + 'kind contents_list -> + 'kind preapply_result tzresult Lwt.t + +type 'kind result_list = + Operation_hash.t * 'kind contents_list * 'kind contents_result_list + +(** /!\ [inject_operation] does not perform automatic patching of + gas, storage and fees; use [inject_manager_operation] to inject + manager operations. *) +val inject_operation : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?simulation:bool -> + ?successor_level:bool -> + ?branch:int -> + ?src_sk:Client_keys.sk_uri -> + ?verbose_signing:bool -> + ?fee_parameter:fee_parameter -> + 'kind contents_list -> + 'kind result_list tzresult Lwt.t + +type 'kind result = Operation_hash.t * 'kind contents * 'kind contents_result + +val prepare_manager_operation : + fee:Tez.t Limit.t -> + gas_limit:Gas.Arith.integral Limit.t -> + storage_limit:Z.t Limit.t -> + 'kind manager_operation -> + 'kind Annotated_manager_operation.t + +val inject_manager_operation : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?successor_level:bool -> + ?branch:int -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?force:bool -> + ?safety_guard:Gas.Arith.integral -> + source:Signature.Public_key_hash.t -> + src_pk:Signature.public_key -> + src_sk:Client_keys.sk_uri -> + fee:Tez.t Limit.t -> + gas_limit:Gas.Arith.integral Limit.t -> + storage_limit:Z.t Limit.t -> + ?counter:Manager_counter.t -> + ?replace_by_fees:bool -> + fee_parameter:fee_parameter -> + 'kind Annotated_manager_operation.annotated_list -> + (Operation_hash.t + * packed_operation + * 'kind Kind.manager contents_list + * 'kind Kind.manager contents_result_list) + tzresult + Lwt.t + +(** Collects the addresses of all contracts originated by a batch of operations + by looking at the operation results. Fails if an operation in the batch is + failed unless [force] is given. *) +val originated_contracts : + force:bool -> 'kind contents_result_list -> Contract_hash.t list tzresult diff --git a/src/proto_020_PsParisC/lib_client/light.ml b/src/proto_020_PsParisC/lib_client/light.ml new file mode 100644 index 000000000000..ebdf0142f7c8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/light.ml @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Proof = Tezos_context_sigs.Context.Proof_types + +module M : Tezos_proxy.Light_proto.PROTO_RPCS = struct + let merkle_tree (pgi : Tezos_proxy.Proxy.proxy_getter_input) key leaf_kind = + Protocol_client_context.Alpha_block_services.Context.merkle_tree + pgi.rpc_context + ~chain:pgi.chain + ~block:pgi.block + ~holey: + (match leaf_kind with Proof.Hole -> true | Proof.Raw_context -> false) + key +end diff --git a/src/proto_020_PsParisC/lib_client/limit.ml b/src/proto_020_PsParisC/lib_client/limit.ml new file mode 100644 index 000000000000..711c2631ecda --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/limit.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type 'a t = 'a option + +let unknown = None + +let known x = Some x + +let of_option = Fun.id + +let is_unknown = Option.is_none + +let join (type a) ~where eq (l1 : a t) (l2 : a t) = + match (l1, l2) with + | None, None -> Result.return_none + | Some x, None | None, Some x -> Result.return_some x + | Some x, Some y -> + if eq x y then Result.return_some x + else error_with "Limit.join: error (%s)" where + +let%expect_test "join" = + let pp_print_err fmt = function + | Result.Error _ -> Format.pp_print_string fmt "error" + | Ok x -> + Format.( + pp_print_option + ~none:(fun fmt () -> pp_print_string fmt "None") + pp_print_bool) + fmt + x + in + let print x = Format.fprintf Format.std_formatter "%a" pp_print_err x in + print (join ~where:__LOC__ Bool.equal (Some true) (Some true)) ; + [%expect {| true |}] ; + print (join ~where:__LOC__ Bool.equal None None) ; + [%expect {| None |}] ; + print (join ~where:__LOC__ Bool.equal None (Some true)) ; + [%expect {| true |}] ; + print (join ~where:__LOC__ Bool.equal (Some true) None) ; + [%expect {| true |}] ; + print (join ~where:__LOC__ Bool.equal (Some true) (Some false)) ; + [%expect {| error |}] + +let get ~when_unknown = function + | None -> error_with "Limit.get: %s" when_unknown + | Some x -> Ok x + +let%expect_test "get" = + let pp_print_err fmt = function + | Result.Error _ -> Format.fprintf fmt "error" + | Ok b -> Format.pp_print_bool fmt b + in + let print x = Format.fprintf Format.std_formatter "%a" pp_print_err x in + print (get ~when_unknown:"" (Some true)) ; + [%expect {| true |}] ; + print (get ~when_unknown:"" None) ; + [%expect {| error |}] + +let fold ~unknown ~known x = match x with None -> unknown | Some x -> known x + +let value ~when_unknown = function None -> when_unknown | Some x -> x diff --git a/src/proto_020_PsParisC/lib_client/limit.mli b/src/proto_020_PsParisC/lib_client/limit.mli new file mode 100644 index 000000000000..3ce610e3450c --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/limit.mli @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This helper module allows to handle partially specified limits during the + injection process. *) + +(** A value of type ['a t] is either [unknown] of [known]. *) +type 'a t + +val unknown : 'a t + +val known : 'a -> 'a t + +val of_option : 'a option -> 'a t + +val is_unknown : 'a t -> bool + +(** [join ~where eq x y] computes the order-theoretic union of [x] and [y]. + If both [x] and [y] are not [Unknown], the function fails iff their + contents are not equal according to [eq]. *) +val join : where:string -> ('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t tzresult + +val fold : unknown:'a -> known:('b -> 'a) -> 'b t -> 'a + +val get : when_unknown:string -> 'a t -> 'a tzresult + +val value : when_unknown:'a -> 'a t -> 'a diff --git a/src/proto_020_PsParisC/lib_client/managed_contract.ml b/src/proto_020_PsParisC/lib_client/managed_contract.ml new file mode 100644 index 000000000000..bdbc615ae12b --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/managed_contract.ml @@ -0,0 +1,362 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context +open Protocol_client_context +open Tezos_micheline + +let return_single_manager_result (oph, _, op, result) = + let open Lwt_result_syntax in + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + | _ -> assert false + +let check_smart_contract (cctxt : #full) opt_res some = + Option.fold ~none:(cctxt#error "This is not a smart contract.") ~some opt_res + +let get_contract_manager (cctxt : #full) contract = + let open Micheline in + let open Michelson_v1_primitives in + let open Lwt_result_syntax in + let* storage = + Client_proto_context.get_storage + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~unparsing_mode:Optimized + contract + in + check_smart_contract cctxt storage @@ fun storage -> + match root storage with + | Prim (_, D_Pair, Bytes (_, bytes) :: _, _) | Bytes (_, bytes) -> ( + match + Data_encoding.Binary.of_bytes_opt + Signature.Public_key_hash.encoding + bytes + with + | Some k -> return k + | None -> + cctxt#error + "Cannot find a manager key in contracts storage (decoding bytes \ + failed).\n\ + Transfer from scripted contract are currently only supported for \ + \"manager\" contract.") + | Prim (_, D_Pair, String (_, value) :: _, _) | String (_, value) -> ( + match Signature.Public_key_hash.of_b58check_opt value with + | Some k -> return k + | None -> + cctxt#error + "Cannot find a manager key in contracts storage (\"%s\" is not a \ + valid key).\n\ + Transfer from scripted contract are currently only supported for \ + \"manager\" contract." + value) + | _raw_storage -> + cctxt#error + "Cannot find a manager key in contracts storage (wrong storage format \ + : @[%a@]).\n\ + Transfer from scripted contract are currently only supported for \ + \"manager\" contract." + Michelson_v1_printer.print_expr + storage + +let parse code = + let open Lwt_result_syntax in + let parsed_exp = Michelson_v1_parser.parse_expression code in + let*? {expanded; _} = Micheline_parser.no_parsing_error parsed_exp in + return (Script.lazy_expr expanded) + +let build_lambda_for_set_delegate ~delegate = + match delegate with + | Some delegate -> + let (`Hex delegate) = Signature.Public_key_hash.to_hex delegate in + Format.asprintf + "{ DROP ; NIL operation ; PUSH key_hash 0x%s ; SOME ; SET_DELEGATE ; \ + CONS }" + delegate + | None -> "{ DROP ; NIL operation ; NONE key_hash ; SET_DELEGATE ; CONS }" + +let entrypoint_do = Entrypoint.do_ + +let entrypoint_set_delegate = Entrypoint.set_delegate + +let entrypoint_remove_delegate = Entrypoint.remove_delegate + +let build_delegate_operation (cctxt : #full) ~chain ~block ?fee + contract (* the KT1 to delegate *) + (delegate : Signature.public_key_hash option) = + let open Lwt_result_syntax in + let entrypoint = entrypoint_do in + let* expr_opt = + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain + ~block + ~contract + ~entrypoint + ~normalize_types:true + in + let* parameters, entrypoint = + match expr_opt with + | Some _ -> + (* there is a "do" entrypoint (we could check its type here)*) + let* param = parse @@ build_lambda_for_set_delegate ~delegate in + return (param, entrypoint) + | None -> ( + (* there is no "do" entrypoint trying "set/remove_delegate" *) + let entrypoint = + match delegate with + | Some _ -> entrypoint_set_delegate + | None -> entrypoint_remove_delegate + in + let* expr_opt = + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain + ~block + ~contract + ~entrypoint + ~normalize_types:true + in + match expr_opt with + | Some _ -> + (* there is a "set/remove_delegate" entrypoint *) + let delegate_data = + match delegate with + | Some delegate -> + let (`Hex delegate) = + Signature.Public_key_hash.to_hex delegate + in + "0x" ^ delegate + | None -> "Unit" + in + let* param = parse delegate_data in + return (param, entrypoint) + | None -> + cctxt#error + "Cannot find a %%do or %%set_delegate entrypoint in contract@.") + in + return + (Client_proto_context.build_transaction_operation + ~amount:Tez.zero + ~parameters + ~entrypoint + ?fee + (Originated contract)) + +let set_delegate (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?branch ~fee_parameter ?fee ~source ~src_pk + ~src_sk contract (* the KT1 to delegate *) + (delegate : Signature.public_key_hash option) = + let open Lwt_result_syntax in + let* operation = + build_delegate_operation cctxt ~chain ~block ?fee contract delegate + in + let operation = Annotated_manager_operation.Single_manager operation in + let* result = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ?branch + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:(Limit.known Z.zero) + ~src_pk + ~src_sk + ~fee_parameter + operation + in + return_single_manager_result result + +let d_unit = + Micheline.strip_locations (Prim (0, Michelson_v1_primitives.D_Unit, [], [])) + +let t_unit = + Micheline.strip_locations (Prim (0, Michelson_v1_primitives.T_unit, [], [])) + +let build_lambda_for_transfer_to_implicit ~destination ~amount = + let (`Hex destination) = Signature.Public_key_hash.to_hex destination in + Format.asprintf + "{ DROP ; NIL operation ;PUSH key_hash 0x%s; IMPLICIT_ACCOUNT;PUSH mutez \ + %Ld ;UNIT;TRANSFER_TOKENS ; CONS }" + destination + (Tez.to_mutez amount) + +let build_lambda_for_transfer_to_originated ~destination ~entrypoint ~amount + ~parameter_type ~parameter = + let destination = + Data_encoding.Binary.to_bytes_exn Contract.originated_encoding destination + in + let amount = Tez.to_mutez amount in + let (`Hex destination) = Hex.of_bytes destination in + let entrypoint = Entrypoint.to_address_suffix entrypoint in + if parameter_type = t_unit then + Format.asprintf + "{ DROP ; NIL operation ;PUSH address 0x%s; CONTRACT %s %a; \ + ASSERT_SOME;PUSH mutez %Ld ;UNIT;TRANSFER_TOKENS ; CONS }" + destination + entrypoint + Michelson_v1_printer.print_expr + parameter_type + amount + else + Format.asprintf + "{ DROP ; NIL operation ;PUSH address 0x%s; CONTRACT %s %a; \ + ASSERT_SOME;PUSH mutez %Ld ;PUSH %a %a;TRANSFER_TOKENS ; CONS }" + destination + entrypoint + Michelson_v1_printer.print_expr + parameter_type + amount + Michelson_v1_printer.print_expr + parameter_type + Michelson_v1_printer.print_expr + parameter + +let build_transaction_operation (cctxt : #full) ~chain ~block ~contract + ~(destination : Contract.t) ?(entrypoint = Entrypoint.default) ?arg ~amount + ?fee ?gas_limit ?storage_limit () = + let open Lwt_result_syntax in + let* lambda = + match destination with + | Implicit destination when Entrypoint.is_default entrypoint -> + return @@ build_lambda_for_transfer_to_implicit ~destination ~amount + | Implicit _ -> + cctxt#error + "Implicit accounts have no entrypoints. (targeted entrypoint %%%a on \ + contract %a)" + Entrypoint.pp + entrypoint + Contract.pp + destination + | Originated destination -> + let* parameter_type = + let* expr_opt = + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain + ~block + ~contract:destination + ~entrypoint + ~normalize_types:true + in + match expr_opt with + | None -> + cctxt#error + "Contract %a has no entrypoint named %a" + Contract_hash.pp + destination + Entrypoint.pp + entrypoint + | Some parameter_type -> return parameter_type + in + let* parameter = + match arg with + | Some arg -> + let* {expanded = arg; _} = + Lwt.return @@ Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression arg + in + return_some arg + | None -> return_none + in + let parameter = Option.value ~default:d_unit parameter in + return + @@ build_lambda_for_transfer_to_originated + ~destination + ~entrypoint + ~amount + ~parameter_type + ~parameter + in + let* parameters = parse lambda in + let entrypoint = entrypoint_do in + return + (Client_proto_context.build_transaction_operation + ~amount:Tez.zero + ~parameters + ~entrypoint + ?fee + ?gas_limit + ?storage_limit + contract) + +let transfer (cctxt : #full) ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?(force = false) ?branch ~source ~src_pk + ~src_sk ~contract ~destination ?(entrypoint = Entrypoint.default) ?arg + ~amount ?fee ?gas_limit ?safety_guard ?storage_limit ?counter ~fee_parameter + () : + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t = + let open Lwt_result_syntax in + let* operation = + build_transaction_operation + cctxt + ~chain + ~block + ~contract + ~destination + ~entrypoint + ?arg + ~amount + ?fee + ?gas_limit + ?storage_limit + () + in + let operation = Annotated_manager_operation.Single_manager operation in + let* ((_, _, _, result) as res) = + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~force + ?branch + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ?safety_guard + ?counter + ~src_pk + ~src_sk + ~fee_parameter + operation + in + let*? contracts = Injection.originated_contracts ~force result in + let* res = return_single_manager_result res in + return (res, contracts) diff --git a/src/proto_020_PsParisC/lib_client/managed_contract.mli b/src/proto_020_PsParisC/lib_client/managed_contract.mli new file mode 100644 index 000000000000..20d722b3a7eb --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/managed_contract.mli @@ -0,0 +1,136 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context +open Protocol_client_context + +(** [check_smart_contract cctxt opt_value f_value] returns an error if + [opt_value] is [None], and [f_value value] if [opt_value = Some value]. + It can typically be used when [opt_value] is [None] for implicit accounts + and [Some _] for smart contracts, as the message in the raised error is that + a smart contract is expected. *) +val check_smart_contract : #full -> 'a option -> ('a -> 'b Lwt.t) -> 'b Lwt.t + +(** Retrieve the manager key in a contract storage. + The storage has to be of type `pair key_hash 'a`. +*) +val get_contract_manager : + #full -> Contract_hash.t -> public_key_hash tzresult Lwt.t + +(** Builds a delegation operation ready for injection *) +val build_delegate_operation : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?fee:Tez.t -> + Contract_hash.t -> + public_key_hash option -> + Kind.transaction Annotated_manager_operation.t tzresult Lwt.t + +(** Set the delegate of a manageable contract. + For a contract with a `do`entrypoint, it builds the lambda that set + the provided delegate. + `~source` has to be the registered manager of the contract. +*) +val set_delegate : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?branch:int -> + fee_parameter:Injection.fee_parameter -> + ?fee:Tez.t -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + Contract_hash.t -> + public_key_hash option -> + Kind.transaction Kind.manager Injection.result tzresult Lwt.t + +(** Builds a transaction operation ready for injection *) +val build_transaction_operation : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Contract.t -> + destination:Contract.t -> + ?entrypoint:Entrypoint.t -> + ?arg:string -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?storage_limit:Z.t -> + unit -> + Kind.transaction Annotated_manager_operation.t tzresult Lwt.t + +(** Perform a transfer on behalf of a managed contract . + For a contract with a `do`entrypoint, it builds the lambda that + does the requested operation. + `~source` has to be the registered manager of the contract. +*) +val transfer : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + block:Block_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?force:bool -> + ?branch:int -> + source:public_key_hash -> + src_pk:public_key -> + src_sk:Client_keys.sk_uri -> + contract:Contract.t -> + destination:Contract.t -> + ?entrypoint:Entrypoint.t -> + ?arg:string -> + amount:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:Gas.Arith.integral -> + ?safety_guard:Gas.Arith.integral -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + fee_parameter:Injection.fee_parameter -> + unit -> + (Kind.transaction Kind.manager Injection.result * Contract_hash.t list) + tzresult + Lwt.t + +val build_lambda_for_set_delegate : delegate:public_key_hash option -> string + +val build_lambda_for_transfer_to_implicit : + destination:public_key_hash -> amount:Tez.t -> string + +val build_lambda_for_transfer_to_originated : + destination:Contract_hash.t -> + entrypoint:Entrypoint.t -> + amount:Tez.t -> + parameter_type:Script.expr -> + parameter:Script.expr -> + string diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_emacs.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_emacs.ml new file mode 100644 index 000000000000..4de1ae254250 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_emacs.ml @@ -0,0 +1,230 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Tezos_micheline +open Micheline + +let print_expr ppf expr = + let print_annot ppf = function + | [] -> () + | annots -> Format.fprintf ppf " %s" (String.concat " " annots) + in + let rec print_expr ppf = function + | Int (_, value) -> Format.fprintf ppf "%s" (Z.to_string value) + | String (_, value) -> Micheline_printer.print_string ppf value + | Bytes (_, value) -> Format.fprintf ppf "0x%a" Hex.pp (Hex.of_bytes value) + | Seq (_, items) -> + Format.fprintf + ppf + "(seq %a)" + (Format.pp_print_list ~pp_sep:Format.pp_print_space print_expr) + items + | Prim (_, name, [], []) -> Format.fprintf ppf "%s" name + | Prim (_, name, items, annot) -> + Format.fprintf + ppf + "(%s%a%s%a)" + name + print_annot + annot + (if items = [] then "" else " ") + (Format.pp_print_list ~pp_sep:Format.pp_print_space print_expr) + items + in + let root = root (Michelson_v1_primitives.strings_of_prims expr) in + Format.fprintf ppf "@[%a@]" print_expr root + +let print_annot_expr ppf expr = Format.fprintf ppf "(%a)" print_expr expr + +open Micheline_parser +open Script_tc_errors + +let print_type_map ppf (parsed, type_map) = + let rec print_expr_types ppf = function + | Seq (loc, []) + | Prim (loc, _, [], _) + | Int (loc, _) + | Bytes (loc, _) + | String (loc, _) -> + print_item ppf loc + | Seq (loc, items) | Prim (loc, _, items, _) -> + print_item ppf loc ; + List.iter (print_expr_types ppf) items + and print_stack ppf items = + Format.fprintf + ppf + "(%a)" + (Format.pp_print_list ~pp_sep:Format.pp_print_space print_annot_expr) + items + and print_item ppf loc = + (let ( >?? ) = Option.bind in + List.assoc ~equal:Int.equal loc parsed.Michelson_v1_parser.expansion_table + >?? fun ({start = {point = s; _}; stop = {point = e; _}}, locs) -> + let locs = List.sort Stdlib.compare locs in + List.hd locs >?? fun hd_loc -> + List.assoc ~equal:Int.equal hd_loc type_map >?? fun (bef, aft) -> + Some (s, e, bef, aft)) + |> Option.iter (fun (s, e, bef, aft) -> + Format.fprintf + ppf + "(@[%d %d %a %a@])@," + s + e + print_stack + bef + print_stack + aft) + in + Format.fprintf ppf "(@[%a@])" print_expr_types (root parsed.unexpanded) + +let first_error_location errs = + let rec find = function + | [] -> 0 + | ( Unexpected_annotation loc + | Ill_formed_type (_, _, loc) + | Invalid_arity (loc, _, _, _) + | Invalid_seq_arity (loc, _, _) + | Invalid_namespace (loc, _, _, _) + | Invalid_primitive (loc, _, _) + | Invalid_kind (loc, _, _) + | Invalid_never_expr loc + | Fail_not_in_tail_position loc + | Undefined_binop (loc, _, _, _) + | Undefined_unop (loc, _, _) + | Bad_return (loc, _, _) + | Bad_stack (loc, _, _, _) + | Unmatched_branches (loc, _, _) + | Invalid_constant (loc, _, _) + | Invalid_syntactic_constant (loc, _, _) + | Invalid_contract (loc, _) + | Comparable_type_expected (loc, _) + | Michelson_v1_primitives.Invalid_primitive_name (_, loc) ) + :: _ -> + loc + | _ :: rest -> find rest + in + find errs + +let report_errors ppf (parsed, errs) = + let eco, out = + List.fold_left + (fun (eco, out) -> function + | Environment.Ecoproto_error err -> (err :: eco, out) + | err -> (eco, err :: out)) + ([], []) + errs + in + let eco, out = (List.rev eco, List.rev out) in + Format.fprintf + ppf + "(@[%a@,%a@])" + (fun ppf errs -> + let find_location loc = + let oloc = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc + ~equal:Int.equal + loc + parsed.Michelson_v1_parser.unexpansion_table + in + fst + (WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc ~equal:Int.equal oloc parsed.expansion_table) + in + match errs with + | top :: errs -> + let errs, loc = + ( List.map (fun e -> Environment.Ecoproto_error e) (top :: errs), + match top with + | Ill_typed_contract (expr, _) | Ill_typed_data (_, expr, _) -> + if expr = parsed.expanded then + find_location (first_error_location (top :: errs)) + else find_location 0 + | Michelson_v1_primitives.Invalid_primitive_name (expr, loc) -> + if + Micheline.strip_locations + (Michelson_v1_macros.unexpand_rec (Micheline.root expr)) + = parsed.Michelson_v1_parser.unexpanded + then find_location loc + else find_location 0 + | _ -> find_location 0 ) + in + let message = + Format.asprintf + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ~parsed:(Michelson_v1_parser.unrecognize_prims parsed)) + errs + in + let {start = {point = s; _}; stop = {point = e; _}} = loc in + Format.fprintf ppf "(%d %d %S)" (s + 1) (e + 1) message + | [] -> ()) + eco + (Format.pp_print_list (fun ppf err -> + let find_location loc = + let oloc = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc + ~equal:Int.equal + loc + parsed.Michelson_v1_parser.unexpansion_table + in + fst + (WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc ~equal:Int.equal oloc parsed.expansion_table) + in + let loc = + match err with + | Invalid_utf8_sequence (point, _) + | Unexpected_character (point, _) + | Undefined_escape_sequence (point, _) + | Missing_break_after_number point -> + {start = point; stop = point} + | Unterminated_string loc + | Unterminated_integer loc + | Unterminated_comment loc + | Invalid_hex_bytes loc + | Unclosed {loc; _} + | Unexpected {loc; _} + | Extra {loc; _} -> + loc + | Misaligned node -> location node + | _ -> find_location 0 + in + let message = + Format.asprintf + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ~parsed:(Michelson_v1_parser.unrecognize_prims parsed)) + [err] + in + let {start = {point = s; _}; stop = {point = e; _}} = loc in + Format.fprintf ppf "(%d %d %S)" (s + 1) (e + 1) message)) + out diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_emacs.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_emacs.mli new file mode 100644 index 000000000000..6694308d4b02 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_emacs.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val print_expr : Format.formatter -> Script.expr -> unit + +val print_type_map : + Format.formatter -> + Michelson_v1_parser.parsed * Script_tc_errors.type_map -> + unit + +val report_errors : + Format.formatter -> + Michelson_v1_parser.parsed * Error_monad.error list -> + unit diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.ml new file mode 100644 index 000000000000..026827f63ddc --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.ml @@ -0,0 +1,287 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Protocol_client_context +open Alpha_context + +type error += Contract_without_code of Contract.t + +let () = + register_error_kind + `Permanent + ~id:"contractWithoutCode" + ~title:"The given contract has no code" + ~description: + "Attempt to get the code of a contract failed because it has nocode. No \ + scriptless contract should remain." + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract has no code %a." Contract.pp contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Contract_without_code c -> Some c | _ -> None) + (fun c -> Contract_without_code c) + +let print_errors (cctxt : #Client_context.printer) errs = + let open Lwt_result_syntax in + let*! () = cctxt#error "%a" Error_monad.pp_print_trace errs in + return_unit + +let script_entrypoint_type cctxt ~(chain : Chain_services.chain) ~block + (program : Script.expr) ~entrypoint = + let open Lwt_result_syntax in + let*! ty_opt = + Plugin.RPC.Scripts.entrypoint_type + cctxt + (chain, block) + ~script:program + ~entrypoint + in + match ty_opt with + | Ok ty -> return_some ty + | Error + (Environment.Ecoproto_error (Script_tc_errors.No_such_entrypoint _) :: _) + -> + return_none + | Error _ as err -> Lwt.return err + +let contract_entrypoint_type cctxt ~(chain : Chain_services.chain) ~block + ~contract ~entrypoint ~normalize_types = + let open Lwt_result_syntax in + let*! ty_opt = + Alpha_services.Contract.entrypoint_type + cctxt + (chain, block) + contract + entrypoint + ~normalize_types + in + match ty_opt with + | Ok ty -> return_some ty + | Error (Tezos_rpc.Context.Not_found _ :: _) -> return_none + | Error _ as err -> Lwt.return err + +let print_entrypoint_type (cctxt : #Client_context.printer) + ?(on_errors = print_errors cctxt) ~emacs ?contract ?script_name ~entrypoint + = + let open Lwt_result_syntax in + function + | Ok (Some ty) -> + let*! () = + if emacs then + cctxt#message + "@[((entrypoint . %a) (type . %a))@]@." + Entrypoint.pp + entrypoint + Michelson_v1_emacs.print_expr + ty + else + cctxt#message + "@[Entrypoint %a: %a@]@." + Entrypoint.pp + entrypoint + Michelson_v1_printer.print_expr + ty + in + return_unit + | Ok None -> + let*! () = + cctxt#message + "@[No entrypoint named %a%a%a@]@." + Entrypoint.pp + entrypoint + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for contract %a" Contract_hash.pp)) + contract + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for script %s")) + script_name + in + return_unit + | Error errs -> on_errors errs + +let list_contract_unreachables_and_entrypoints cctxt ~chain ~block ~contract + ~normalize_types = + Alpha_services.Contract.list_entrypoints + cctxt + (chain, block) + contract + ~normalize_types + +let list_contract_unreachables cctxt ~chain ~block ~contract = + let open Lwt_result_syntax in + let normalize_types = + (* no need to normalize types as typed entrypoints are ignored *) + false + in + let* unreachables, _types_entrypoints = + list_contract_unreachables_and_entrypoints + cctxt + ~chain + ~block + ~contract + ~normalize_types + in + return unreachables + +let list_contract_entrypoints cctxt ~chain ~block ~contract ~normalize_types = + let open Lwt_result_syntax in + let* _, entrypoints = + list_contract_unreachables_and_entrypoints + cctxt + ~chain + ~block + ~contract + ~normalize_types + in + if not @@ List.mem_assoc ~equal:String.equal "default" entrypoints then + let*! ty_opt = + contract_entrypoint_type + cctxt + ~chain + ~block + ~contract + ~entrypoint:Entrypoint.default + ~normalize_types + in + match ty_opt with + | Ok (Some ty) -> return (("default", ty) :: entrypoints) + | Ok None -> return entrypoints + | Error _ as err -> Lwt.return err + else return entrypoints + +let list_unreachables cctxt ~chain ~block (program : Script.expr) = + let open Lwt_result_syntax in + let* unreachables, _ = + Plugin.RPC.Scripts.list_entrypoints cctxt (chain, block) ~script:program + in + return unreachables + +let list_entrypoints cctxt ~chain ~block (program : Script.expr) = + let open Lwt_result_syntax in + let* _, entrypoints = + Plugin.RPC.Scripts.list_entrypoints cctxt (chain, block) ~script:program + in + if not @@ List.mem_assoc ~equal:String.equal "default" entrypoints then + let*! ty_opt = + script_entrypoint_type + cctxt + ~chain + ~block + program + ~entrypoint:Entrypoint.default + in + match ty_opt with + | Ok (Some ty) -> return (("default", ty) :: entrypoints) + | Ok None -> return entrypoints + | Error _ as err -> Lwt.return err + else return entrypoints + +let print_entrypoints_list (cctxt : #Client_context.printer) + ?(on_errors = print_errors cctxt) ~emacs ?contract ?script_name = + let open Lwt_result_syntax in + function + | Ok entrypoint_list -> + let*! () = + if emacs then + cctxt#message + "@[(@[%a@])@." + (Format.pp_print_list + ~pp_sep:Format.pp_print_cut + (fun ppf (entrypoint, ty) -> + Format.fprintf + ppf + "@[( ( entrypoint . %s ) ( type . @[%a@]))@]" + entrypoint + Michelson_v1_emacs.print_expr + ty)) + entrypoint_list + else + cctxt#message + "@[Entrypoints%a%a: @,%a@]@." + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for contract %a" Contract_hash.pp)) + contract + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " for script %s")) + script_name + (Format.pp_print_list + ~pp_sep:Format.pp_print_cut + (fun ppf (entrypoint, ty) -> + Format.fprintf + ppf + "@[%s: @[%a@]@]" + entrypoint + Michelson_v1_printer.print_expr + ty)) + entrypoint_list + in + return_unit + | Error errs -> on_errors errs + +let print_unreachables (cctxt : #Client_context.printer) + ?(on_errors = print_errors cctxt) ~emacs ?contract ?script_name = + let open Lwt_result_syntax in + function + | Ok unreachable -> + let*! () = + if emacs then + cctxt#message + "@[(@[%a@])@." + (Format.pp_print_list ~pp_sep:Format.pp_print_cut (fun ppf path -> + Format.fprintf + ppf + "@[( unreachable-path . %a )@]" + (Format.pp_print_list + ~pp_sep:Format.pp_print_space + (fun ppf prim -> + Format.pp_print_string ppf + @@ Michelson_v1_primitives.string_of_prim prim)) + path)) + unreachable + else + match unreachable with + | [] -> cctxt#message "@[None.@]@." + | _ -> + cctxt#message + "@[Unreachable paths in the argument%a%a: @[%a@]@." + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " of contract %a" Contract_hash.pp)) + contract + (Format.pp_print_option (fun ppf -> + Format.fprintf ppf " of script %s")) + script_name + (Format.pp_print_list ~pp_sep:Format.pp_print_cut (fun ppf -> + Format.fprintf + ppf + "@[ %a @]" + (Format.pp_print_list + ~pp_sep:(fun ppf _ -> Format.pp_print_string ppf "/") + (fun ppf prim -> + Format.pp_print_string ppf + @@ Michelson_v1_primitives.string_of_prim prim)))) + unreachable + in + return_unit + | Error errs -> on_errors errs diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.mli new file mode 100644 index 000000000000..9c59d1dd72c3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_entrypoints.mli @@ -0,0 +1,110 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Returns [Some type] if the contract has an entrypoint of type [type]. None if it does not exist. *) +val script_entrypoint_type : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + Alpha_context.Script.expr -> + entrypoint:Alpha_context.Entrypoint.t -> + Alpha_context.Script.expr option tzresult Lwt.t + +(** Returns [Some type] if the script has an entrypoint of type [type]. None if it does not exist. *) +val contract_entrypoint_type : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Contract_hash.t -> + entrypoint:Alpha_context.Entrypoint.t -> + normalize_types:bool -> + Alpha_context.Script.expr option tzresult Lwt.t + +val print_entrypoint_type : + #Client_context.printer -> + ?on_errors:(error list -> unit tzresult Lwt.t) -> + emacs:bool -> + ?contract:Contract_hash.t -> + ?script_name:string -> + entrypoint:Alpha_context.Entrypoint.t -> + Alpha_context.Script.expr option tzresult -> + unit tzresult Lwt.t + +(** List paths of unreachable parameters. + Only useful to test the stitching, as no such parameter should be + allowed in originated contracts. *) +val list_contract_unreachables : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Contract_hash.t -> + Michelson_v1_primitives.prim list list tzresult Lwt.t + +val list_unreachables : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + Alpha_context.Script.expr -> + Michelson_v1_primitives.prim list list tzresult Lwt.t + +val print_unreachables : + #Client_context.printer -> + ?on_errors:(error list -> unit tzresult Lwt.t) -> + emacs:bool -> + ?contract:Contract_hash.t -> + ?script_name:string -> + Michelson_v1_primitives.prim list list tzresult -> + unit tzresult Lwt.t + +(** List the contract entrypoints with their types. + If their is no explicit default, th type of default entrypoint will still be given. +*) +val list_contract_entrypoints : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + contract:Contract_hash.t -> + normalize_types:bool -> + (string * Alpha_context.Script.expr) list tzresult Lwt.t + +(** List the script entrypoints with their types. *) +val list_entrypoints : + #Protocol_client_context.rpc_context -> + chain:Chain_services.chain -> + block:Block_services.block -> + Alpha_context.Script.expr -> + (string * Alpha_context.Script.expr) list tzresult Lwt.t + +(** Print the contract entrypoints with their types. *) +val print_entrypoints_list : + #Client_context.printer -> + ?on_errors:(error list -> unit tzresult Lwt.t) -> + emacs:bool -> + ?contract:Contract_hash.t -> + ?script_name:string -> + (string * Alpha_context.Script.expr) list tzresult -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.ml new file mode 100644 index 000000000000..b13825d560ab --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.ml @@ -0,0 +1,857 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Script_tc_errors +open Script_interpreter +open Michelson_v1_printer + +let print_ty ppf ty = Michelson_v1_printer.print_expr_unwrapped ppf ty + +let print_stack_ty ?(depth = max_int) ppf s = + let rec loop depth ppf = function + | [] -> () + | _ when depth <= 0 -> Format.fprintf ppf "..." + | [last] -> print_ty ppf last + | last :: rest -> + Format.fprintf ppf "%a@ :@ %a" print_ty last (loop (depth - 1)) rest + in + match s with + | [] -> Format.fprintf ppf "[]" + | sty -> Format.fprintf ppf "@[[ %a ]@]" (loop depth) sty + +let rec print_enumeration ppf = function + | [single] -> Format.fprintf ppf "%a" Format.pp_print_text single + | [prev; last] -> + Format.fprintf + ppf + "%a@ or@ %a" + Format.pp_print_text + prev + Format.pp_print_text + last + | first :: rest -> + Format.fprintf + ppf + "%a,@ %a" + Format.pp_print_text + first + print_enumeration + rest + | [] -> assert false + +let collect_error_locations errs = + let rec collect acc = function + | Environment.Ecoproto_error + ( Ill_formed_type (_, _, _) + | No_such_entrypoint _ | Duplicate_entrypoint _ + | Unreachable_entrypoint _ | Tx_rollup_invalid_ticket_amount _ + | Runtime_contract_error _ + | Michelson_v1_primitives.Invalid_primitive_name (_, _) + | Ill_typed_data (_, _, _) + | Ill_typed_contract (_, _) ) + :: _ + | [] -> + acc + | Environment.Ecoproto_error + ( Invalid_arity (loc, _, _, _) + | Invalid_seq_arity (loc, _, _) + | Unexpected_annotation loc + | Ungrouped_annotations loc + | Type_too_large (loc, _) + | Invalid_namespace (loc, _, _, _) + | Invalid_primitive (loc, _, _) + | Invalid_kind (loc, _, _) + | Invalid_never_expr loc + | Duplicate_field (loc, _) + | Unexpected_lazy_storage loc + | Unexpected_operation loc + | Fail_not_in_tail_position loc + | Undefined_binop (loc, _, _, _) + | Undefined_unop (loc, _, _) + | Bad_return (loc, _, _) + | Bad_stack (loc, _, _, _) + | Unmatched_branches (loc, _, _) + | Forbidden_instr_in_context (loc, _, _) + | Invalid_constant (loc, _, _) + | Invalid_syntactic_constant (loc, _, _) + | Invalid_contract (loc, _) + | Comparable_type_expected (loc, _) + | Overflow (loc, _) + | Reject (loc, _, _) + | Pair_bad_argument loc + | Unpair_bad_argument loc + | Dup_n_bad_argument loc ) + :: rest -> + collect (loc :: acc) rest + | _ :: rest -> collect acc rest + in + collect [] errs + +let string_of_context_desc = function + | Script_tc_errors.Lambda -> "lambda" + | Script_tc_errors.View -> "view" + +(* Error raised while fetching the script of a contract for error reporting when the script is not found. *) +type error += Fetch_script_not_found_meta_error of Contract_hash.t + +(* Errors raised while fetching the script of a contract for error reporting. *) +type error += Fetch_script_meta_error of error trace + +let fetch_script (cctxt : #Protocol_client_context.rpc_context) ~chain ~block + contract = + let open Lwt_result_syntax in + let* script_opt = + Plugin.RPC.Contract.get_script_normalized + cctxt + (chain, block) + ~unparsing_mode:Readable + ~normalize_types:true + ~contract + in + match script_opt with + | None -> tzfail (Fetch_script_not_found_meta_error contract) + | Some {code; storage = _} -> + Lwt.return @@ Environment.wrap_tzresult @@ Script_repr.force_decode code + +type error += + | Rich_runtime_contract_error of + Contract_hash.t * string Michelson_v1_parser.parser_result + +let enrich_runtime_errors cctxt ~chain ~block ~parsed = + let open Lwt_result_syntax in + List.map_s (function + | Environment.Ecoproto_error (Runtime_contract_error contract) -> ( + (* If we know the script already, we don't fetch it *) + match parsed with + | Some parsed -> + Lwt.return (Rich_runtime_contract_error (contract, parsed)) + | None -> ( + let*! script_opt = fetch_script cctxt ~chain ~block contract in + Lwt.return + @@ + match script_opt with + | Ok script -> + let parsed = + Michelson_v1_parser.unrecognize_prims + @@ Michelson_v1_printer.unparse_toplevel script + in + Rich_runtime_contract_error (contract, parsed) + | Error err -> Fetch_script_meta_error err)) + | e -> Lwt.return e) + +let report_errors ~details ~show_source + ?(parsed : string Michelson_v1_parser.parser_result option) ppf errs = + let rec print_trace locations errs = + let print_loc ppf loc = + match locations loc with + | None -> Format.fprintf ppf "At (unshown) location %d, " loc + | Some loc -> + Format.fprintf + ppf + "%s,@ " + (String.capitalize_ascii + (Format.asprintf "%a" Micheline_parser.print_location loc)) + in + let parsed_locations parsed loc = + let ( >?? ) = Option.bind in + List.assoc + ~equal:Int.equal + loc + parsed.Michelson_v1_parser.unexpansion_table + >?? fun oloc -> + List.assoc ~equal:Int.equal oloc parsed.expansion_table + >?? fun (ploc, _) -> Some ploc + in + let print_source ppf (parsed, _hilights) (* TODO *) = + let lines = String.split_on_char '\n' parsed.Michelson_v1_parser.source in + let cols = String.length (string_of_int (List.length lines)) in + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list (fun ppf (i, l) -> + Format.fprintf ppf "%0*d: %s" cols i l)) + (List.rev_mapi (fun i x -> (i + 1, x)) lines |> List.rev) + in + match errs with + | [] -> () + | Michelson_v1_stack.Wrong_stack_item loc_node :: rest -> + Format.fprintf + ppf + "@[%a,@ wrong syntax for a stack element, expecting something \ + of the following shape: Stack_elt ; got %a.@]" + Michelson_v1_stack.print_localized_node_location + loc_node + Michelson_v1_stack.print_localized_node + loc_node ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Michelson_v1_stack.Wrong_stack loc_node :: rest -> + Format.fprintf + ppf + "@[%a,@ wrong syntax for stack, expecting a sequence of \ + elements of the following shape: Stack_elt ; got %a.@]" + Michelson_v1_stack.print_localized_node_location + loc_node + Michelson_v1_stack.print_localized_node + loc_node ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error + (Michelson_v1_primitives.Invalid_primitive_name (expr, loc)) + :: rest -> + let parsed = + match parsed with + | Some parsed -> + if + Micheline.strip_locations + (Michelson_v1_macros.unexpand_rec (Micheline.root expr)) + = parsed.Michelson_v1_parser.unexpanded + then parsed + else Michelson_v1_printer.unparse_invalid expr + | None -> Michelson_v1_printer.unparse_invalid expr + in + let hilights = loc :: collect_error_locations rest in + if show_source then + Format.fprintf + ppf + "@[@[Invalid primitive:@ %a@]@]" + print_source + (parsed, hilights) + else Format.fprintf ppf "Invalid primitive." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (Ill_typed_data (name, expr, ty)) :: rest -> + let parsed = + match parsed with + | Some parsed + when Michelson_v1_primitives.strings_of_prims expr + = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_parser.unrecognize_prims + @@ Michelson_v1_printer.unparse_expression expr + in + let hilights = collect_error_locations rest in + Format.fprintf + ppf + "@[@[Ill typed %adata:@ %a@]@ @[is not an \ + expression of type@ %a@]@]" + (fun ppf -> function + | None -> () + | Some s -> Format.fprintf ppf "%s " s) + name + print_source + (parsed, hilights) + print_ty + ty ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (No_such_entrypoint entrypoint) :: rest -> + Format.fprintf + ppf + "Contract has no entrypoint named %a" + Entrypoint.pp + entrypoint ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Duplicate_entrypoint entrypoint) :: rest -> + Format.fprintf + ppf + "Contract has two entrypoints named %a" + Entrypoint.pp + entrypoint ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unreachable_entrypoint path) :: rest -> + let path = + String.concat + "/" + (List.map Michelson_v1_primitives.string_of_prim path) + in + Format.fprintf ppf "Entrypoint at path %s is not reachable" path ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Tx_rollup_bad_deposit_parameter (loc, expr)) + :: rest -> + Format.fprintf + ppf + "@[%aTrying to call the deposit entrypoint of a transaction \ + rollup with an ill-formed parameter:@ %a@]" + print_loc + loc + print_expr + expr ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Tx_rollup_invalid_ticket_amount amount) + :: rest -> + Format.fprintf + ppf + "Amount of tickets to deposit to a transaction rollup needs to fit \ + in a 64-bit integer, but %a is too big" + Z.pp_print + amount ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Ill_formed_type (_, expr, loc)) :: rest -> + let parsed = + match parsed with + | Some parsed + when Michelson_v1_primitives.strings_of_prims expr + = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_parser.unrecognize_prims + @@ Michelson_v1_printer.unparse_expression expr + in + let hilights = loc :: collect_error_locations errs in + if show_source then + Format.fprintf + ppf + "@[%aill formed type:@ %a@]" + print_loc + loc + print_source + (parsed, hilights) + else Format.fprintf ppf "Ill formed type." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (Ill_typed_contract (expr, type_map)) :: rest + -> + let parsed = + match parsed with + | Some parsed + when (not details) + && Michelson_v1_primitives.strings_of_prims expr + = parsed.Michelson_v1_parser.expanded -> + parsed + | Some _ | None -> + Michelson_v1_parser.unrecognize_prims + @@ Michelson_v1_printer.unparse_toplevel ~type_map expr + in + let hilights = collect_error_locations rest in + if show_source then + Format.fprintf + ppf + "@[Ill typed contract:@, %a@]" + print_source + (parsed, hilights) + else Format.fprintf ppf "Ill typed contract." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error + Validate_errors.Manager.Gas_quota_exceeded_init_deserialize + :: rest -> + Format.fprintf + ppf + "@[Not enough gas to deserialize the operation.@,\ + Injecting such a transaction could have you banned from mempools.@]" ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Deprecated_instruction prim) :: rest -> + Format.fprintf + ppf + "@[Use of deprecated instruction: %s@]" + (Michelson_v1_primitives.string_of_prim prim) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Cannot_serialize_storage :: rest -> + Format.fprintf + ppf + "Cannot serialize the resulting storage value within the provided \ + gas bounds." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Missing_field prim) :: rest -> + Format.fprintf + ppf + "@[Missing contract field: %s@]" + (Michelson_v1_primitives.string_of_prim prim) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Duplicate_field (loc, prim)) :: rest -> + Format.fprintf + ppf + "@[%aduplicate contract field: %s@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim prim) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unexpected_lazy_storage loc) :: rest -> + Format.fprintf + ppf + "%abig_map or sapling_state type not expected here" + print_loc + loc ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unexpected_operation loc) :: rest -> + Format.fprintf + ppf + "%aoperation type forbidden in parameter, storage and constants" + print_loc + loc ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Unexpected_contract loc) :: rest -> + Format.fprintf + ppf + "%acontract type forbidden in storage and constants" + print_loc + loc ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error (Runtime_contract_error contract) :: rest -> + Format.fprintf + ppf + "@[Runtime error in unknown contract %a@]" + Contract_hash.pp + contract ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Rich_runtime_contract_error (contract, parsed) :: rest -> + let hilights = collect_error_locations rest in + Format.fprintf + ppf + "@[Runtime error in contract %a:@ %a@]" + Contract_hash.pp + contract + print_source + (parsed, hilights) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace (parsed_locations parsed) rest + | Environment.Ecoproto_error (Apply.Internal_operation_replay op) :: rest -> + Format.fprintf + ppf + "@[Internal operation replay attempt:@,%a@]" + Operation_result.pp_internal_operation + op ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Gas.Gas_limit_too_high :: rest -> + Format.fprintf + ppf + "Gas limit for the operation is out of the protocol hard bounds." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Gas.Block_quota_exceeded :: rest -> + Format.fprintf + ppf + "Gas limit for the block exceeded during typechecking or execution." ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Gas.Operation_quota_exceeded :: rest -> + Format.fprintf + ppf + "@[Gas limit exceeded during typechecking or execution.@,\ + Try again with a higher gas limit.@]" ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | Environment.Ecoproto_error Fees.Operation_quota_exceeded :: rest -> + Format.fprintf + ppf + "@[Storage limit exceeded during typechecking or execution.@,\ + Try again with a higher storage limit.@]" ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | [Environment.Ecoproto_error (Script_interpreter.Bad_contract_parameter c)] + -> + Format.fprintf + ppf + "@[Account %a is not a smart contract, it does not take \ + arguments.@,\ + The `-arg' flag should not be used when transferring to an \ + account.@]" + Contract.pp + c + | Environment.Ecoproto_error err :: rest -> + (match err with + | Bad_contract_parameter c -> + Format.fprintf + ppf + "Invalid argument passed to contract %a." + Contract.pp + c + | Invalid_arity (loc, name, exp, got) -> + Format.fprintf + ppf + "%aprimitive %s expects %d arguments but is given %d." + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + exp + got + | Invalid_seq_arity (loc, exp, got) -> + Format.fprintf + ppf + "%asequence expects at least %d elements but is given %d." + print_loc + loc + exp + got + | Invalid_namespace (loc, name, exp, got) -> + let human_namespace = function + | Michelson_v1_primitives.Instr_namespace -> ("an", "instruction") + | Type_namespace -> ("a", "type name") + | Constant_namespace -> ("a", "constant constructor") + | Keyword_namespace -> ("a", "keyword") + | Constant_hash_namespace -> ("a", "constant hash") + in + Format.fprintf + ppf + "@[%aunexpected %s %s, only %s %s can be used here." + print_loc + loc + (snd (human_namespace got)) + (Michelson_v1_primitives.string_of_prim name) + (fst (human_namespace exp)) + (snd (human_namespace exp)) + | Invalid_primitive (loc, exp, got) -> + Format.fprintf + ppf + "@[%ainvalid primitive %s, only %a can be used here." + print_loc + loc + (Michelson_v1_primitives.string_of_prim got) + print_enumeration + (List.map Michelson_v1_primitives.string_of_prim exp) + | Invalid_kind (loc, exp, got) -> + let human_kind = function + | Seq_kind -> ("a", "sequence") + | Prim_kind -> ("a", "primitive") + | Int_kind -> ("an", "int") + | String_kind -> ("a", "string") + | Bytes_kind -> ("a", "byte sequence") + in + Format.fprintf + ppf + "@[%aunexpected %s, only@ %a@ can be used here." + print_loc + loc + (snd (human_kind got)) + print_enumeration + (List.map + (fun k -> + let a, n = human_kind k in + a ^ " " ^ n) + exp) + | Invalid_never_expr loc -> + Format.fprintf + ppf + "@[%athis expression should have type never but type never has \ + no inhabitant." + print_loc + loc + | Duplicate_map_keys (_, expr) -> + Format.fprintf + ppf + "@[Map literals cannot contain duplicate keys, however a \ + duplicate key was found:@ @[%a@]" + print_expr + expr + | Unordered_map_keys (_, expr) -> + Format.fprintf + ppf + "@[Keys in a map literal must be in strictly ascending \ + order, but they were unordered in literal:@ @[%a@]" + print_expr + expr + | Duplicate_set_values (_, expr) -> + Format.fprintf + ppf + "@[Set literals cannot contain duplicate values, however a \ + duplicate value was found:@ @[%a@]" + print_expr + expr + | Unordered_set_values (_, expr) -> + Format.fprintf + ppf + "@[Values in a set literal must be in strictly ascending \ + order, but they were unordered in literal:@ @[%a@]" + print_expr + expr + | Fail_not_in_tail_position loc -> + Format.fprintf + ppf + "%aThe FAIL instruction must appear in a tail position." + print_loc + loc + | Undefined_binop (loc, name, tya, tyb) -> + Format.fprintf + ppf + "@[@[%aoperator %s is undefined between@ %a@]@ \ + @[and@ %a.@]@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + print_ty + tya + print_ty + tyb + | Undefined_unop (loc, name, ty) -> + Format.fprintf + ppf + "@[@[%aoperator %s is undefined on@ %a@]@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + print_ty + ty + | Bad_return (loc, got, exp) -> + Format.fprintf + ppf + "@[%awrong stack type at end of body:@,\ + - @[expected return stack type:@ %a,@]@,\ + - @[actual stack type:@ %a.@]@]" + print_loc + loc + (fun ppf -> print_stack_ty ppf) + [exp] + (fun ppf -> print_stack_ty ppf) + got + | Bad_stack (loc, name, depth, sty) -> + Format.fprintf + ppf + "@[%awrong stack type for instruction %s:@ %a.@]" + print_loc + loc + (Michelson_v1_primitives.string_of_prim name) + (print_stack_ty ~depth) + sty + | Unmatched_branches (loc, sta, stb) -> + Format.fprintf + ppf + "@[%atwo branches don't end with the same stack type:@,\ + - @[first stack type:@ %a,@]@,\ + - @[other stack type:@ %a.@]@]" + print_loc + loc + (fun ppf -> print_stack_ty ppf) + sta + (fun ppf -> print_stack_ty ppf) + stb + | Bad_view_name loc -> + Format.fprintf + ppf + "@[%athe name of view should be of type string @]" + print_loc + loc + | Duplicated_view_name loc -> + Format.fprintf + ppf + "@[%athe name of view in toplevel should be unique @]" + print_loc + loc + | Ill_typed_view {loc; actual; expected} -> + Format.fprintf + ppf + "@[%athe return of a view block did not match the expected \ + type.@,\ + - @[resulted view stack type:@ %a,@]@,\ + - @[expected view stack type:@ %a.@]@]" + print_loc + loc + (fun ppf -> print_stack_ty ppf) + actual + (fun ppf -> print_stack_ty ppf) + expected + | View_name_too_long name -> + Format.fprintf + ppf + "@[ A view name, \"%s\", exceeds the maximum length of 31 \ + characters." + name + | Inconsistent_type_sizes (size1, size2) -> + Format.fprintf + ppf + "@[The two types have different sizes, the first one is of \ + size %d while the other one is of size %d@]" + size1 + size2 + | Unexpected_annotation loc -> + Format.fprintf ppf "@[%aunexpected annotation." print_loc loc + | Ungrouped_annotations loc -> + Format.fprintf + ppf + "@[%aAnnotations of the same kind must be grouped." + print_loc + loc + | Type_too_large (loc, maximum_size) -> + Format.fprintf + ppf + "@[%atype exceeded maximum type size (%d)." + print_loc + loc + maximum_size + | Pair_bad_argument loc -> + Format.fprintf + ppf + "%aPAIR expects an argument of at least 2." + print_loc + loc + | Unpair_bad_argument loc -> + Format.fprintf + ppf + "%aUNPAIR expects an argument of at least 2." + print_loc + loc + | Dup_n_bad_argument loc -> + Format.fprintf + ppf + "%aDUP n expects an argument of at least 1 (passed 0)." + print_loc + loc + | Forbidden_instr_in_context (loc, ctxt, prim) -> + Format.fprintf + ppf + "%aThe %s instruction cannot appear in a %s." + print_loc + loc + (Michelson_v1_primitives.string_of_prim prim) + (string_of_context_desc ctxt) + | Non_dupable_type (loc, ty) -> + Format.fprintf + ppf + "%atype %a cannot be used here because it is not duplicable. \ + Only duplicable types can be used with the DUP instruction and \ + as view inputs and outputs." + print_loc + loc + print_ty + ty + | Unexpected_ticket loc -> + Format.fprintf + ppf + "%aTicket in unauthorized position (type error)." + print_loc + loc + | Bad_stack_length -> Format.fprintf ppf "Bad stack length." + | Bad_stack_item lvl -> Format.fprintf ppf "Bad stack item %d." lvl + | Unexpected_forged_value loc -> + Format.fprintf ppf "%aUnexpected forged value." print_loc loc + | Invalid_constant (loc, got, exp) -> + Format.fprintf + ppf + "@[@[%avalue@ %a@]@ @[is invalid for type@ \ + %a.@]@]" + print_loc + loc + print_expr + got + print_ty + exp + | Invalid_syntactic_constant (loc, got, exp) -> + Format.fprintf + ppf + "@[@[%avalue@ %a@]@ @[is invalid, expected@ \ + %s@]@]" + print_loc + loc + print_expr + got + exp + | Invalid_contract (loc, contract) -> + Format.fprintf + ppf + "%ainvalid contract %a." + print_loc + loc + Contract.pp + contract + | Comparable_type_expected (loc, ty) -> + Format.fprintf ppf "%acomparable type expected." print_loc loc ; + Format.fprintf + ppf + "@[@[Type@ %a@]@ is not comparable.@]" + print_ty + ty + | Inconsistent_types (loc, tya, tyb) -> + Format.fprintf + ppf + "@[@[%aType@ %a@]@ @[is not compatible with \ + type@ %a.@]@]" + print_loc + loc + print_ty + tya + print_ty + tyb + | Reject (loc, v, trace) -> + Format.fprintf + ppf + "%ascript reached FAILWITH instruction@ @[with@ %a@]%a" + print_loc + loc + print_expr + v + (fun ppf -> function + | None -> () + | Some trace -> + Format.fprintf + ppf + "@,@[trace@,%a@]" + print_execution_trace + trace) + trace + | Overflow (loc, trace) -> + Format.fprintf + ppf + "%aunexpected arithmetic overflow%a" + print_loc + loc + (fun ppf -> function + | None -> () + | Some trace -> + Format.fprintf + ppf + "@,@[trace@,%a@]" + print_execution_trace + trace) + trace + | Unexpected_implicit_account_parameters_type (loc, expr) -> + Format.fprintf + ppf + "@[@[%aExpression@ %a@]@ @[is not \ + acceptable as a handle to an implicit account, whose parameters \ + type can only be unit or ticket .@]@]" + print_loc + loc + print_expr + expr + | err -> Format.fprintf ppf "%a" Environment.Error_monad.pp err) ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + | err :: rest -> + Format.fprintf ppf "%a" Error_monad.pp err ; + if rest <> [] then Format.fprintf ppf "@," ; + print_trace locations rest + in + Format.fprintf ppf "@[" ; + print_trace (fun _ -> None) errs ; + Format.fprintf ppf "@]" diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.mli new file mode 100644 index 000000000000..f221b25ca972 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_error_reporter.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val enrich_runtime_errors : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + block:Shell_services.block -> + parsed:string Michelson_v1_parser.parser_result option -> + Error_monad.error list -> + Error_monad.error list Lwt.t + +val report_errors : + details:bool -> + show_source:bool -> + ?parsed:string Michelson_v1_parser.parser_result -> + Format.formatter -> + Error_monad.error list -> + unit diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_helpers.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_helpers.ml new file mode 100644 index 000000000000..c70d0890eaf1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_helpers.ml @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Generic Michelson building functions *) + +open Tezos_micheline.Micheline +open Protocol.Alpha_context.Script + +let seq ~loc l = Seq (loc, l) + +let pair ~loc a b = Prim (loc, D_Pair, [a; b], []) + +let none ~loc () = Prim (loc, D_None, [], []) + +let some ~loc a = Prim (loc, D_Some, [a], []) + +let left ~loc a = Prim (loc, D_Left, [a], []) + +let right ~loc b = Prim (loc, D_Right, [b], []) + +let int ~loc i = Int (loc, i) + +let bytes ~loc s = Bytes (loc, s) + +let unit_t ~loc = Prim (loc, T_unit, [], []) + +let unit ~loc = Prim (loc, D_Unit, [], []) + +let lambda_from_string code = + let open Result_syntax in + let* parsed = + Tezos_micheline.Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression code + in + return @@ root Michelson_v1_parser.(parsed.expanded) + +let lambda_t ~loc param res = Prim (loc, T_lambda, [param; res], []) + +let operation_t ~loc = Prim (loc, T_operation, [], []) + +let operations_t ~loc = Prim (loc, T_list, [operation_t ~loc], []) diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_macros.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_macros.ml new file mode 100644 index 000000000000..873605d174db --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_macros.ml @@ -0,0 +1,1571 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Tezos_micheline +open Micheline +module IntMap = Map.Make (Compare.Int) + +type 'l node = ('l, string) Micheline.node + +type error += Unexpected_macro_annotation of string + +type error += Sequence_expected of string + +type error += Invalid_arity of string * int * int + +let rec check_letters str i j f = + i > j || (f str.[i] && check_letters str (i + 1) j f) + +let expand_caddadr original = + let open Result_syntax in + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len > 3 + && str.[0] = 'C' + && str.[len - 1] = 'R' + && check_letters str 1 (len - 2) (function + | 'A' | 'D' -> true + | _ -> false) + then + let* () = + match args with + | [] -> return_unit + | _ :: _ -> tzfail (Invalid_arity (str, List.length args, 0)) + in + let path_annot = + List.filter (function "@%" | "@%%" -> true | _ -> false) annot + in + let rec parse i acc = + if i = 0 then Seq (loc, acc) + else + let annot = if i = len - 2 then annot else path_annot in + match str.[i] with + | 'A' -> parse (i - 1) (Prim (loc, "CAR", [], annot) :: acc) + | 'D' -> parse (i - 1) (Prim (loc, "CDR", [], annot) :: acc) + | _ -> assert false + in + return_some (parse (len - 2) []) + else return_none + | _ -> return_none + +let expand_carn original = + let open Result_syntax in + match original with + | Prim (loc, "CAR", [Int (loc2, n)], annot) -> + return_some + (Seq + ( loc, + [ + Prim + (loc, "GET", [Int (loc2, Z.(of_int 1 + (n * of_int 2)))], annot); + ] )) + | _ -> return_none + +let expand_cdrn original = + let open Result_syntax in + match original with + | Prim (loc, "CDR", [Int (loc2, n)], annot) -> + return_some + (Seq (loc, [Prim (loc, "GET", [Int (loc2, Z.(n * of_int 2))], annot)])) + | _ -> return_none + +let extract_field_annots annot = + List.partition + (fun a -> + match a.[0] with + | '%' -> true + | _ -> false + | exception Invalid_argument _ -> false) + annot + +let expand_set_caddadr original = + let open Result_syntax in + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len >= 7 + && String.sub str 0 5 = "SET_C" + && str.[len - 1] = 'R' + && check_letters str 5 (len - 2) (function + | 'A' | 'D' -> true + | _ -> false) + then + let* () = + match args with + | [] -> return_unit + | _ :: _ -> tzfail (Invalid_arity (str, List.length args, 0)) + in + let* field_annot, annot = + match extract_field_annots annot with + | [], annot -> return (None, annot) + | [f], annot -> return (Some f, annot) + | _, _ -> tzfail (Unexpected_macro_annotation str) + in + let rec parse i acc = + if i = 4 then acc + else + let annot = if i = 5 then annot else [] in + match str.[i] with + | 'A' -> + let acc = + Seq + ( loc, + [ + Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CAR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CDR", [], ["@%%"]); + Prim (loc, "SWAP", [], []); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot); + ] ) + in + parse (i - 1) acc + | 'D' -> + let acc = + Seq + ( loc, + [ + Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CDR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CAR", [], ["@%%"]); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot); + ] ) + in + parse (i - 1) acc + | _ -> assert false + in + match str.[len - 2] with + | 'A' -> + let access_check = + match field_annot with + | None -> [] + | Some f -> + [ + Prim (loc, "DUP", [], []); + Prim (loc, "CAR", [], [f]); + Prim (loc, "DROP", [], []); + ] + in + let encoding = + [Prim (loc, "CDR", [], ["@%%"]); Prim (loc, "SWAP", [], [])] + in + let pair = + [ + Prim + ( loc, + "PAIR", + [], + [Option.value field_annot ~default:"%"; "%@"] ); + ] + in + let init = Seq (loc, access_check @ encoding @ pair) in + return_some (parse (len - 3) init) + | 'D' -> + let access_check = + match field_annot with + | None -> [] + | Some f -> + [ + Prim (loc, "DUP", [], []); + Prim (loc, "CDR", [], [f]); + Prim (loc, "DROP", [], []); + ] + in + let encoding = [Prim (loc, "CAR", [], ["@%%"])] in + let pair = + [ + Prim + ( loc, + "PAIR", + [], + ["%@"; Option.value field_annot ~default:"%"] ); + ] + in + let init = Seq (loc, access_check @ encoding @ pair) in + return_some (parse (len - 3) init) + | _ -> assert false + else return_none + | _ -> return_none + +let expand_map_caddadr original = + let open Result_syntax in + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len >= 7 + && String.sub str 0 5 = "MAP_C" + && str.[len - 1] = 'R' + && check_letters str 5 (len - 2) (function + | 'A' | 'D' -> true + | _ -> false) + then + let* code = + match args with + | [(Seq _ as code)] -> return code + | [_] -> tzfail (Sequence_expected str) + | [] | _ :: _ :: _ -> + tzfail (Invalid_arity (str, List.length args, 1)) + in + let* field_annot, annot = + match extract_field_annots annot with + | [], annot -> return (None, annot) + | [f], annot -> return (Some f, annot) + | _, _ -> tzfail (Unexpected_macro_annotation str) + in + let rec parse i acc = + if i = 4 then acc + else + let annot = if i = 5 then annot else [] in + match str.[i] with + | 'A' -> + let acc = + Seq + ( loc, + [ + Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CAR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CDR", [], ["@%%"]); + Prim (loc, "SWAP", [], []); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot); + ] ) + in + parse (i - 1) acc + | 'D' -> + let acc = + Seq + ( loc, + [ + Prim (loc, "DUP", [], []); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CDR", [], ["@%%"]); acc])], + [] ); + Prim (loc, "CAR", [], ["@%%"]); + Prim (loc, "PAIR", [], "%@" :: "%@" :: annot); + ] ) + in + parse (i - 1) acc + | _ -> assert false + in + let cr_annot = + match field_annot with + | None -> [] + | Some f -> ["@" ^ String.sub f 1 (String.length f - 1)] + in + match str.[len - 2] with + | 'A' -> + let init = + Seq + ( loc, + [ + Prim (loc, "DUP", [], []); + Prim (loc, "CDR", [], ["@%%"]); + Prim + ( loc, + "DIP", + [Seq (loc, [Prim (loc, "CAR", [], cr_annot); code])], + [] ); + Prim (loc, "SWAP", [], []); + Prim + ( loc, + "PAIR", + [], + [Option.value field_annot ~default:"%"; "%@"] ); + ] ) + in + return_some (parse (len - 3) init) + | 'D' -> + let init = + Seq + ( loc, + [ + Prim (loc, "DUP", [], []); + Prim (loc, "CDR", [], cr_annot); + code; + Prim (loc, "SWAP", [], []); + Prim (loc, "CAR", [], ["@%%"]); + Prim + ( loc, + "PAIR", + [], + ["%@"; Option.value field_annot ~default:"%"] ); + ] ) + in + return_some (parse (len - 3) init) + | _ -> assert false + else return_none + | _ -> return_none + +exception Not_a_roman + +let decimal_of_roman roman = + (* http://rosettacode.org/wiki/Roman_numerals/Decode#OCaml *) + let arabic = ref 0 in + let lastval = ref 0 in + for i = String.length roman - 1 downto 0 do + let n = + match roman.[i] with + | 'M' -> 1000 + | 'D' -> 500 + | 'C' -> 100 + | 'L' -> 50 + | 'X' -> 10 + | 'V' -> 5 + | 'I' -> 1 + | _ -> raise_notrace Not_a_roman + in + if Compare.Int.(n < !lastval) then arabic := !arabic - n + else arabic := !arabic + n ; + lastval := n + done ; + !arabic + +let dip ~loc ?(annot = []) depth instr = + assert (depth >= 0) ; + if depth = 1 then Prim (loc, "DIP", [instr], annot) + else Prim (loc, "DIP", [Int (loc, Z.of_int depth); instr], annot) + +let expand_deprecated_dxiiivp original = + let open Result_syntax in + (* transparently expands deprecated macro [DI...IP] to instruction [DIP n] *) + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if len > 3 && str.[0] = 'D' && str.[len - 1] = 'P' then + try + let depth = decimal_of_roman (String.sub str 1 (len - 2)) in + match args with + | [(Seq (_, _) as arg)] -> + let expanded = dip ~loc ~annot depth arg in + Format.eprintf + "Warning: Use of deprecated macro %a. This macro will soon be \ + removed, please use the %a instruction instead.@." + Micheline_printer.print_expr_unwrapped + (Micheline_printer.printable + Fun.id + (Micheline.strip_locations original)) + Micheline_printer.print_expr_unwrapped + (Micheline_printer.printable + Fun.id + (Micheline.strip_locations expanded)) ; + return_some expanded + | [_] -> tzfail (Sequence_expected str) + | [] | _ :: _ :: _ -> + tzfail (Invalid_arity (str, List.length args, 1)) + with Not_a_roman -> return_none + else return_none + | _ -> return_none + +exception Not_a_pair + +type pair_item = A | I | P of int * pair_item * pair_item + +let parse_pair_substr str ~len start = + let rec parse ?left i = + if i = len - 1 then raise_notrace Not_a_pair + else if str.[i] = 'P' then + let next_i, l = parse ~left:true (i + 1) in + let next_i, r = parse ~left:false next_i in + (next_i, P (i, l, r)) + else if str.[i] = 'A' && left = Some true then (i + 1, A) + else if str.[i] = 'I' && left <> Some true then (i + 1, I) + else raise_notrace Not_a_pair + in + let last, ast = parse start in + if last <> len - 1 then raise_notrace Not_a_pair else ast + +let unparse_pair_item ast = + let rec unparse ast acc = + match ast with + | P (_, l, r) -> unparse r (unparse l ("P" :: acc)) + | A -> "A" :: acc + | I -> "I" :: acc + in + List.rev ("R" :: unparse ast []) |> String.concat "" + +let pappaiir_annots_pos ast annot = + let rec find_annots_pos p_pos ast annots acc = + match (ast, annots) with + | _, [] -> (annots, acc) + | P (i, left, right), _ -> + let annots, acc = find_annots_pos i left annots acc in + find_annots_pos i right annots acc + | A, a :: annots -> + let pos = + match IntMap.find p_pos acc with + | None -> ([a], []) + | Some (_, cdr) -> ([a], cdr) + in + (annots, IntMap.add p_pos pos acc) + | I, a :: annots -> + let pos = + match IntMap.find p_pos acc with + | None -> ([], [a]) + | Some (car, _) -> (car, [a]) + in + (annots, IntMap.add p_pos pos acc) + in + snd (find_annots_pos 0 ast annot IntMap.empty) + +let expand_pappaiir original = + let open Result_syntax in + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len > 4 + && str.[0] = 'P' + && str.[len - 1] = 'R' + && check_letters str 1 (len - 2) (function + | 'P' | 'A' | 'I' -> true + | _ -> false) + then + try + let field_annots, annot = extract_field_annots annot in + let ast = parse_pair_substr str ~len 0 in + let field_annots_pos = pappaiir_annots_pos ast field_annots in + let rec parse p (depth, acc) = + match p with + | P (i, left, right) -> + let annot = + match (i, IntMap.find i field_annots_pos) with + | 0, None -> annot + | _, None -> [] + | 0, Some ([], cdr_annot) -> ("%" :: cdr_annot) @ annot + | _, Some ([], cdr_annot) -> "%" :: cdr_annot + | 0, Some (car_annot, cdr_annot) -> + car_annot @ cdr_annot @ annot + | _, Some (car_annot, cdr_annot) -> car_annot @ cdr_annot + in + let acc = + if depth = 0 then Prim (loc, "PAIR", [], annot) :: acc + else + dip ~loc depth (Seq (loc, [Prim (loc, "PAIR", [], annot)])) + :: acc + in + (depth, acc) |> parse left |> parse right + | A | I -> (depth + 1, acc) + in + let _, expanded = parse ast (0, []) in + let* () = + match args with + | [] -> return_unit + | _ :: _ -> tzfail (Invalid_arity (str, List.length args, 0)) + in + return_some (Seq (loc, expanded)) + with Not_a_pair -> return_none + else return_none + | _ -> return_none + +let expand_unpappaiir original = + let open Result_syntax in + match original with + | Prim (loc, str, args, _annot) -> + let len = String.length str in + if + len > 6 + && String.sub str 0 3 = "UNP" + && str.[len - 1] = 'R' + && check_letters str 3 (len - 2) (function + | 'P' | 'A' | 'I' -> true + | _ -> false) + then + try + let unpair = Prim (loc, "UNPAIR", [], []) in + let ast = parse_pair_substr str ~len 2 in + let rec parse p (depth, acc) = + match p with + | P (_i, left, right) -> + let acc = + if depth = 0 then unpair :: acc + else dip ~loc depth (Seq (loc, [unpair])) :: acc + in + (depth, acc) |> parse left |> parse right + | A | I -> (depth + 1, acc) + in + let _, rev_expanded = parse ast (0, []) in + let expanded = Seq (loc, List.rev rev_expanded) in + let* () = + match args with + | [] -> return_unit + | _ :: _ -> tzfail (Invalid_arity (str, List.length args, 0)) + in + return_some expanded + with Not_a_pair -> return_none + else return_none + | _ -> return_none + +exception Not_a_dup + +let expand_deprecated_duuuuup original = + (* transparently expands deprecated macro [DU...UP] to [{ DUP n }] *) + let open Result_syntax in + match original with + | Prim (loc, str, args, annot) -> + let len = String.length str in + if + len > 3 + && str.[0] = 'D' + && str.[len - 1] = 'P' + && check_letters str 1 (len - 2) (( = ) 'U') + then + let* () = + match args with + | [] -> return_unit + | _ :: _ -> tzfail (Invalid_arity (str, List.length args, 0)) + in + try + let rec parse i = + if i = 1 then + Prim (loc, "DUP", [Int (loc, Z.of_int (len - 2))], annot) + else if str.[i] = 'U' then parse (i - 1) + else raise_notrace Not_a_dup + in + let expanded = parse (len - 2) in + Format.eprintf + "Warning: Use of deprecated macro %a. This macro will soon be \ + removed, please use the %a instruction instead.@." + Micheline_printer.print_expr_unwrapped + (Micheline_printer.printable + Fun.id + (Micheline.strip_locations original)) + Micheline_printer.print_expr_unwrapped + (Micheline_printer.printable + Fun.id + (Micheline.strip_locations expanded)) ; + return_some expanded + with Not_a_dup -> return_none + else return_none + | _ -> return_none + +let expand_compare original = + let open Result_syntax in + let cmp loc is annot = + let is = + match List.rev_map (fun i -> Prim (loc, i, [], [])) is with + | Prim (loc, i, args, _) :: r -> List.rev (Prim (loc, i, args, annot) :: r) + | is -> List.rev is + in + return_some (Seq (loc, is)) + in + let ifcmp loc is l r annot = + let is = + List.map (fun i -> Prim (loc, i, [], [])) is + @ [Prim (loc, "IF", [l; r], annot)] + in + return_some (Seq (loc, is)) + in + match original with + | Prim (loc, "CMPEQ", [], annot) -> cmp loc ["COMPARE"; "EQ"] annot + | Prim (loc, "CMPNEQ", [], annot) -> cmp loc ["COMPARE"; "NEQ"] annot + | Prim (loc, "CMPLT", [], annot) -> cmp loc ["COMPARE"; "LT"] annot + | Prim (loc, "CMPGT", [], annot) -> cmp loc ["COMPARE"; "GT"] annot + | Prim (loc, "CMPLE", [], annot) -> cmp loc ["COMPARE"; "LE"] annot + | Prim (loc, "CMPGE", [], annot) -> cmp loc ["COMPARE"; "GE"] annot + | Prim + ( _, + (("CMPEQ" | "CMPNEQ" | "CMPLT" | "CMPGT" | "CMPLE" | "CMPGE") as str), + args, + [] ) -> + tzfail (Invalid_arity (str, List.length args, 0)) + | Prim (loc, "IFCMPEQ", [l; r], annot) -> + ifcmp loc ["COMPARE"; "EQ"] l r annot + | Prim (loc, "IFCMPNEQ", [l; r], annot) -> + ifcmp loc ["COMPARE"; "NEQ"] l r annot + | Prim (loc, "IFCMPLT", [l; r], annot) -> + ifcmp loc ["COMPARE"; "LT"] l r annot + | Prim (loc, "IFCMPGT", [l; r], annot) -> + ifcmp loc ["COMPARE"; "GT"] l r annot + | Prim (loc, "IFCMPLE", [l; r], annot) -> + ifcmp loc ["COMPARE"; "LE"] l r annot + | Prim (loc, "IFCMPGE", [l; r], annot) -> + ifcmp loc ["COMPARE"; "GE"] l r annot + | Prim (loc, "IFEQ", [l; r], annot) -> ifcmp loc ["EQ"] l r annot + | Prim (loc, "IFNEQ", [l; r], annot) -> ifcmp loc ["NEQ"] l r annot + | Prim (loc, "IFLT", [l; r], annot) -> ifcmp loc ["LT"] l r annot + | Prim (loc, "IFGT", [l; r], annot) -> ifcmp loc ["GT"] l r annot + | Prim (loc, "IFLE", [l; r], annot) -> ifcmp loc ["LE"] l r annot + | Prim (loc, "IFGE", [l; r], annot) -> ifcmp loc ["GE"] l r annot + | Prim + ( _, + (( "IFCMPEQ" | "IFCMPNEQ" | "IFCMPLT" | "IFCMPGT" | "IFCMPLE" + | "IFCMPGE" | "IFEQ" | "IFNEQ" | "IFLT" | "IFGT" | "IFLE" | "IFGE" ) as + str), + args, + [] ) -> + tzfail (Invalid_arity (str, List.length args, 2)) + | Prim + ( _, + (( "IFCMPEQ" | "IFCMPNEQ" | "IFCMPLT" | "IFCMPGT" | "IFCMPLE" + | "IFCMPGE" | "IFEQ" | "IFNEQ" | "IFLT" | "IFGT" | "IFLE" | "IFGE" ) as + str), + [], + _ :: _ ) -> + tzfail (Unexpected_macro_annotation str) + | _ -> return_none + +let expand_asserts original = + let open Result_syntax in + let may_rename loc = function + | [] -> Seq (loc, []) + | annot -> Seq (loc, [Prim (loc, "RENAME", [], annot)]) + in + let fail_false ?(annot = []) loc = + [may_rename loc annot; Seq (loc, [Prim (loc, "FAIL", [], [])])] + in + let fail_true ?(annot = []) loc = + [Seq (loc, [Prim (loc, "FAIL", [], [])]); may_rename loc annot] + in + match original with + | Prim (loc, "ASSERT", [], []) -> + return_some (Seq (loc, [Prim (loc, "IF", fail_false loc, [])])) + | Prim (loc, "ASSERT_NONE", [], []) -> + return_some (Seq (loc, [Prim (loc, "IF_NONE", fail_false loc, [])])) + | Prim (loc, "ASSERT_SOME", [], annot) -> + return_some (Seq (loc, [Prim (loc, "IF_NONE", fail_true ~annot loc, [])])) + | Prim (loc, "ASSERT_LEFT", [], annot) -> + return_some + (Seq (loc, [Prim (loc, "IF_LEFT", fail_false ~annot loc, [])])) + | Prim (loc, "ASSERT_RIGHT", [], annot) -> + return_some (Seq (loc, [Prim (loc, "IF_LEFT", fail_true ~annot loc, [])])) + | Prim + ( _, + (( "ASSERT" | "ASSERT_NONE" | "ASSERT_SOME" | "ASSERT_LEFT" + | "ASSERT_RIGHT" ) as str), + args, + [] ) -> + tzfail (Invalid_arity (str, List.length args, 0)) + | Prim (_, (("ASSERT" | "ASSERT_NONE") as str), [], _ :: _) -> + tzfail (Unexpected_macro_annotation str) + | Prim (loc, s, args, annot) + when String.(length s > 7 && equal (sub s 0 7) "ASSERT_") -> ( + let* () = + match args with + | [] -> return_unit + | _ :: _ -> tzfail (Invalid_arity (s, List.length args, 0)) + in + let* () = + match annot with + | _ :: _ -> tzfail (Unexpected_macro_annotation s) + | [] -> return_unit + in + let remaining = String.(sub s 7 (length s - 7)) in + let remaining_prim = Prim (loc, remaining, [], []) in + match remaining with + | "EQ" | "NEQ" | "LT" | "LE" | "GE" | "GT" -> + return_some + (Seq (loc, [remaining_prim; Prim (loc, "IF", fail_false loc, [])])) + | _ -> ( + let* seq_opt = expand_compare remaining_prim in + match seq_opt with + | None -> return_none + | Some seq -> + return + @@ Some (Seq (loc, [seq; Prim (loc, "IF", fail_false loc, [])])))) + | _ -> return_none + +let expand_if_some = + let open Result_syntax in + function + | Prim (loc, "IF_SOME", [right; left], annot) -> + return_some (Seq (loc, [Prim (loc, "IF_NONE", [left; right], annot)])) + | Prim (_, "IF_SOME", args, _annot) -> + tzfail (Invalid_arity ("IF_SOME", List.length args, 2)) + | _ -> return_none + +let expand_if_right = + let open Result_syntax in + function + | Prim (loc, "IF_RIGHT", [right; left], annot) -> + return_some (Seq (loc, [Prim (loc, "IF_LEFT", [left; right], annot)])) + | Prim (_, "IF_RIGHT", args, _annot) -> + tzfail (Invalid_arity ("IF_RIGHT", List.length args, 2)) + | _ -> return_none + +let expand_fail = + let open Result_syntax in + function + | Prim (loc, "FAIL", [], []) -> + return_some + (Seq (loc, [Prim (loc, "UNIT", [], []); Prim (loc, "FAILWITH", [], [])])) + | _ -> return_none + +let expand original = + let open Result_syntax in + let rec try_expansions = function + | [] -> return original + | expander :: expanders -> ( + let* rewritten_opt = expander original in + match rewritten_opt with + | None -> try_expansions expanders + | Some rewritten -> return rewritten) + in + try_expansions + [ + expand_carn; + expand_cdrn; + expand_caddadr; + expand_set_caddadr; + expand_map_caddadr; + expand_deprecated_dxiiivp; + (* expand_paaiair ; *) + expand_pappaiir; + (* expand_unpaaiair ; *) + expand_unpappaiir; + expand_deprecated_duuuuup; + expand_compare; + expand_asserts; + expand_if_some; + expand_if_right; + expand_fail; + ] + +let expand_rec expr = + let rec error_map (expanded, errors) f = function + | [] -> (List.rev expanded, List.rev errors) + | hd :: tl -> + let new_expanded, new_errors = f hd in + error_map + (new_expanded :: expanded, List.rev_append new_errors errors) + f + tl + in + let error_map = error_map ([], []) in + let rec expand_rec expr = + match expand expr with + | Ok expanded -> ( + match expanded with + | Seq (loc, items) -> + let items, errors = error_map expand_rec items in + (Seq (loc, items), errors) + | Prim (loc, name, args, annot) -> + let args, errors = error_map expand_rec args in + (Prim (loc, name, args, annot), errors) + | (Int _ | String _ | Bytes _) as atom -> (atom, [])) + | Error errors -> (expr, errors) + in + expand_rec expr + +let unexpand_carn_and_cdrn expanded = + match expanded with + | Seq (loc, [Prim (_, "GET", [Int (locn, n)], annot)]) -> + let half, parity = Z.ediv_rem n (Z.of_int 2) in + if Z.(parity = zero) then + Some (Prim (loc, "CDR", [Int (locn, half)], annot)) + else Some (Prim (loc, "CAR", [Int (locn, half)], annot)) + | _ -> None + +let unexpand_caddadr expanded = + let rec rsteps acc = function + | [] -> Some acc + | Prim (_, "CAR", [], []) :: rest -> rsteps ("A" :: acc) rest + | Prim (_, "CDR", [], []) :: rest -> rsteps ("D" :: acc) rest + | _ -> None + in + match expanded with + | Seq (loc, (Prim (_, "CAR", [], []) :: _ as nodes)) + | Seq (loc, (Prim (_, "CDR", [], []) :: _ as nodes)) -> ( + match rsteps [] nodes with + | Some steps -> + let name = String.concat "" ("C" :: List.rev ("R" :: steps)) in + Some (Prim (loc, name, [], [])) + | None -> None) + | _ -> None + +let unexpand_set_caddadr expanded = + let rec steps acc annots = function + | Seq + ( loc, + [ + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], _); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "A" :: acc, annots) + | Seq + ( loc, + [ + Prim (_, "DUP", [], []); + Prim (_, "CAR", [], [field_annot]); + Prim (_, "DROP", [], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "A" :: acc, field_annot :: annots) + | Seq (loc, [Prim (_, "CAR", [], _); Prim (_, "PAIR", [], _)]) -> + Some (loc, "D" :: acc, annots) + | Seq + ( loc, + [ + Prim (_, "DUP", [], []); + Prim (_, "CDR", [], [field_annot]); + Prim (_, "DROP", [], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "D" :: acc, field_annot :: annots) + | Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CAR", [], _); sub])], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "PAIR", [], pair_annots); + ] ) -> + let _, pair_annots = extract_field_annots pair_annots in + steps ("A" :: acc) (List.rev_append pair_annots annots) sub + | Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], _); sub])], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], pair_annots); + ] ) -> + let _, pair_annots = extract_field_annots pair_annots in + steps ("D" :: acc) (List.rev_append pair_annots annots) sub + | _ -> None + in + match steps [] [] expanded with + | Some (loc, steps, annots) -> + let name = String.concat "" ("SET_C" :: List.rev ("R" :: steps)) in + Some (Prim (loc, name, [], List.rev annots)) + | None -> None + +let unexpand_map_caddadr expanded = + let rec steps acc annots = function + | Seq + ( loc, + [ + Prim (_, "DUP", [], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CAR", [], []); code])], []); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "A" :: acc, annots, code) + | Seq + ( loc, + [ + Prim (_, "DUP", [], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim + ( _, + "DIP", + [Seq (_, [Prim (_, "CAR", [], [field_annot]); code])], + [] ); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "A" :: acc, field_annot :: annots, code) + | Seq + ( loc, + [ + Prim (_, "DUP", [], []); + Prim (_, "CDR", [], []); + code; + Prim (_, "SWAP", [], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "D" :: acc, annots, code) + | Seq + ( loc, + [ + Prim (_, "DUP", [], []); + Prim (_, "CDR", [], [field_annot]); + code; + Prim (_, "SWAP", [], []); + Prim (_, "CAR", [], _); + Prim (_, "PAIR", [], _); + ] ) -> + Some (loc, "D" :: acc, field_annot :: annots, code) + | Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CAR", [], _); sub])], []); + Prim (_, "CDR", [], _); + Prim (_, "SWAP", [], []); + Prim (_, "PAIR", [], pair_annots); + ] ) -> + let _, pair_annots = extract_field_annots pair_annots in + steps ("A" :: acc) (List.rev_append pair_annots annots) sub + | Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], []); sub])], []); + Prim (_, "CAR", [], []); + Prim (_, "PAIR", [], pair_annots); + ] ) -> + let _, pair_annots = extract_field_annots pair_annots in + steps ("D" :: acc) (List.rev_append pair_annots annots) sub + | _ -> None + in + match steps [] [] expanded with + | Some (loc, steps, annots, code) -> + let name = String.concat "" ("MAP_C" :: List.rev ("R" :: steps)) in + Some (Prim (loc, name, [code], List.rev annots)) + | None -> None + +let unexpand_deprecated_dxiiivp expanded = + (* transparently turn the old expansion of deprecated [DI...IP] to [DIP n] *) + match expanded with + | Seq + ( loc, + [Prim (_, "DIP", [(Seq (_, [Prim (_, "DIP", [_], [])]) as sub)], [])] ) + -> + let rec count acc = function + | Seq (_, [Prim (_, "DIP", [sub], [])]) -> count (acc + 1) sub + | sub -> (acc, sub) + in + let depth, sub = count 1 sub in + Some (Prim (loc, "DIP", [Int (loc, Z.of_int depth); sub], [])) + | _ -> None + +let unexpand_dupn expanded = + match expanded with + | Seq + ( loc, + [ + Prim + (_, "DIP", [Int (_, np); Seq (_, [Prim (_, "DUP", [], annot)])], []); + Prim (_, "DIG", [Int (nloc, ng)], []); + ] ) + when Z.equal np (Z.pred ng) -> + Some (Prim (loc, "DUP", [Int (nloc, ng)], annot)) + | _ -> None + +let unexpand_deprecated_duuuuup expanded = + (* transparently turn the old expansion of deprecated [DU...UP] to [DUP n] *) + let rec expand n = function + | Seq (loc, [Prim (nloc, "DUP", [], annot)]) -> + if n = 1 then None + else Some (Prim (loc, "DUP", [Int (nloc, Z.of_int n)], annot)) + | Seq (_, [Prim (_, "DIP", [expanded'], []); Prim (_, "SWAP", [], [])]) -> + expand (n + 1) expanded' + | _ -> None + in + expand 1 expanded + +let rec normalize_pair_item ?(right = false) = function + | P (i, a, b) -> + P (i, normalize_pair_item a, normalize_pair_item ~right:true b) + | A when right -> I + | A -> A + | I -> I + +let unexpand_pappaiir expanded = + match expanded with + | Seq (_, [Prim (_, "PAIR", [], [])]) -> Some expanded + | Seq (loc, (_ :: _ as nodes)) -> ( + let rec exec stack nodes = + match (nodes, stack) with + | [], _ -> stack + (* support new expansion using [DIP n] *) + | ( Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, + a :: rstack ) + when Z.to_int n > 1 -> + exec + (a + :: exec + rstack + [ + Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []); + ]) + rest + | Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, a :: rstack + when Z.to_int n = 1 -> + exec (a :: exec rstack sub) rest + | Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, [] + when Z.to_int n > 1 -> + exec + (A + :: exec + [] + [ + Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []); + ]) + rest + | Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, [] + when Z.to_int n = 1 -> + exec (A :: exec [] sub) rest + (* support old expansion using [DIP] *) + | Prim (_, "DIP", [Seq (_, sub)], []) :: rest, a :: rstack -> + exec (a :: exec rstack sub) rest + | Prim (_, "DIP", [Seq (_, sub)], []) :: rest, [] -> + exec (A :: exec [] sub) rest + | Prim (_, "PAIR", [], []) :: rest, a :: b :: rstack -> + exec (P (0, a, b) :: rstack) rest + | Prim (_, "PAIR", [], []) :: rest, [a] -> exec [P (0, a, I)] rest + | Prim (_, "PAIR", [], []) :: rest, [] -> exec [P (0, A, I)] rest + | _ -> raise_notrace Not_a_pair + in + match exec [] nodes with + | [] -> None + | res :: _ -> + let res = normalize_pair_item res in + let name = unparse_pair_item res in + Some (Prim (loc, name, [], [])) + | exception Not_a_pair -> None) + | _ -> None + +let unexpand_unpappaiir expanded = + match expanded with + | Seq (loc, (_ :: _ as nodes)) -> ( + let rec exec stack nodes = + match (nodes, stack) with + | [], _ -> stack + (* support new expansion using [DIP n] *) + | ( Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, + a :: rstack ) + when Z.to_int n > 1 -> + exec + (a + :: exec + rstack + [ + Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []); + ]) + rest + | Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, a :: rstack + when Z.to_int n = 1 -> + exec (a :: exec rstack sub) rest + | Prim (ploc, "DIP", [Int (loc, n); Seq (sloc, sub)], []) :: rest, [] + when Z.to_int n > 1 -> + exec + (A + :: exec + [] + [ + Prim + (ploc, "DIP", [Int (loc, Z.pred n); Seq (sloc, sub)], []); + ]) + rest + | Prim (_, "DIP", [Int (_, n); Seq (_, sub)], []) :: rest, [] + when Z.to_int n = 1 -> + exec (A :: exec [] sub) rest + (* support old expansion using [DIP] *) + | Prim (_, "DIP", [Seq (_, sub)], []) :: rest, a :: rstack -> + exec (a :: exec rstack sub) rest + | Prim (_, "DIP", [Seq (_, sub)], []) :: rest, [] -> + exec (A :: exec [] sub) rest + | ( Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "CAR", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], [])])], []); + ] ) + :: rest, + a :: b :: rstack ) -> + exec (P (0, a, b) :: rstack) rest + | ( Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "CAR", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], [])])], []); + ] ) + :: rest, + [a] ) -> + exec [P (0, a, I)] rest + | ( Seq + ( _, + [ + Prim (_, "DUP", [], []); + Prim (_, "CAR", [], []); + Prim (_, "DIP", [Seq (_, [Prim (_, "CDR", [], [])])], []); + ] ) + :: rest, + [] ) -> + exec [P (0, A, I)] rest + | _ -> raise_notrace Not_a_pair + in + match exec [] (List.rev nodes) with + | [] -> None + | res :: _ -> + let res = normalize_pair_item res in + let name = "UN" ^ unparse_pair_item res in + Some (Prim (loc, name, [], [])) + | exception Not_a_pair -> None) + | _ -> None + +let unexpand_compare expanded = + match expanded with + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "EQ", [], annot)]) -> + Some (Prim (loc, "CMPEQ", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "NEQ", [], annot)]) -> + Some (Prim (loc, "CMPNEQ", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "LT", [], annot)]) -> + Some (Prim (loc, "CMPLT", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "GT", [], annot)]) -> + Some (Prim (loc, "CMPGT", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "LE", [], annot)]) -> + Some (Prim (loc, "CMPLE", [], annot)) + | Seq (loc, [Prim (_, "COMPARE", [], _); Prim (_, "GE", [], annot)]) -> + Some (Prim (loc, "CMPGE", [], annot)) + | Seq + ( loc, + [ + Prim (_, "COMPARE", [], _); + Prim (_, "EQ", [], _); + Prim (_, "IF", args, annot); + ] ) -> + Some (Prim (loc, "IFCMPEQ", args, annot)) + | Seq + ( loc, + [ + Prim (_, "COMPARE", [], _); + Prim (_, "NEQ", [], _); + Prim (_, "IF", args, annot); + ] ) -> + Some (Prim (loc, "IFCMPNEQ", args, annot)) + | Seq + ( loc, + [ + Prim (_, "COMPARE", [], _); + Prim (_, "LT", [], _); + Prim (_, "IF", args, annot); + ] ) -> + Some (Prim (loc, "IFCMPLT", args, annot)) + | Seq + ( loc, + [ + Prim (_, "COMPARE", [], _); + Prim (_, "GT", [], _); + Prim (_, "IF", args, annot); + ] ) -> + Some (Prim (loc, "IFCMPGT", args, annot)) + | Seq + ( loc, + [ + Prim (_, "COMPARE", [], _); + Prim (_, "LE", [], _); + Prim (_, "IF", args, annot); + ] ) -> + Some (Prim (loc, "IFCMPLE", args, annot)) + | Seq + ( loc, + [ + Prim (_, "COMPARE", [], _); + Prim (_, "GE", [], _); + Prim (_, "IF", args, annot); + ] ) -> + Some (Prim (loc, "IFCMPGE", args, annot)) + | Seq (loc, [Prim (_, "EQ", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFEQ", args, annot)) + | Seq (loc, [Prim (_, "NEQ", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFNEQ", args, annot)) + | Seq (loc, [Prim (_, "LT", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFLT", args, annot)) + | Seq (loc, [Prim (_, "GT", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFGT", args, annot)) + | Seq (loc, [Prim (_, "LE", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFLE", args, annot)) + | Seq (loc, [Prim (_, "GE", [], _); Prim (_, "IF", args, annot)]) -> + Some (Prim (loc, "IFGE", args, annot)) + | _ -> None + +let unexpand_asserts expanded = + match expanded with + | Seq + ( loc, + [ + Prim + ( _, + "IF", + [ + Seq (_, []); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT", [], [])) + | Seq + ( loc, + [ + Seq (_, [Prim (_, "COMPARE", [], []); Prim (_, comparison, [], [])]); + Prim + ( _, + "IF", + [ + Seq (_, []); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_CMP" ^ comparison, [], [])) + | Seq + ( loc, + [ + Prim (_, comparison, [], []); + Prim + ( _, + "IF", + [ + Seq (_, []); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_" ^ comparison, [], [])) + | Seq + ( loc, + [ + Prim + ( _, + "IF_NONE", + [ + Seq (_, [Prim (_, "RENAME", [], annot)]); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_NONE", [], annot)) + | Seq + ( loc, + [ + Prim + ( _, + "IF_NONE", + [ + Seq (_, []); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_NONE", [], [])) + | Seq + ( loc, + [ + Prim + ( _, + "IF_NONE", + [ + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + Seq (_, []); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_SOME", [], [])) + | Seq + ( loc, + [ + Prim + ( _, + "IF_NONE", + [ + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + Seq (_, [Prim (_, "RENAME", [], annot)]); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_SOME", [], annot)) + | Seq + ( loc, + [ + Prim + ( _, + "IF_LEFT", + [ + Seq (_, []); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_LEFT", [], [])) + | Seq + ( loc, + [ + Prim + ( _, + "IF_LEFT", + [ + Seq (_, [Prim (_, "RENAME", [], annot)]); + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_LEFT", [], annot)) + | Seq + ( loc, + [ + Prim + ( _, + "IF_LEFT", + [ + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + Seq (_, []); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_RIGHT", [], [])) + | Seq + ( loc, + [ + Prim + ( _, + "IF_LEFT", + [ + Seq + ( _, + [ + Seq + ( _, + [ + Prim (_, "UNIT", [], []); + Prim (_, "FAILWITH", [], []); + ] ); + ] ); + Seq (_, [Prim (_, "RENAME", [], annot)]); + ], + [] ); + ] ) -> + Some (Prim (loc, "ASSERT_RIGHT", [], annot)) + | _ -> None + +let unexpand_if_some = function + | Seq (loc, [Prim (_, "IF_NONE", [left; right], annot)]) -> + Some (Prim (loc, "IF_SOME", [right; left], annot)) + | _ -> None + +let unexpand_if_right = function + | Seq (loc, [Prim (_, "IF_LEFT", [left; right], annot)]) -> + Some (Prim (loc, "IF_RIGHT", [right; left], annot)) + | _ -> None + +let unexpand_fail = function + | Seq (loc, [Prim (_, "UNIT", [], []); Prim (_, "FAILWITH", [], [])]) -> + Some (Prim (loc, "FAIL", [], [])) + | _ -> None + +let unexpand original = + let try_unexpansions unexpanders = + Option.value + ~default:original + (List.fold_left + (fun acc f -> Option.either_f acc (fun () -> f original)) + None + unexpanders) + in + try_unexpansions + [ + unexpand_asserts; + unexpand_carn_and_cdrn; + unexpand_caddadr; + unexpand_set_caddadr; + unexpand_map_caddadr; + unexpand_deprecated_dxiiivp; + unexpand_pappaiir; + unexpand_unpappaiir; + unexpand_deprecated_duuuuup; + unexpand_dupn; + unexpand_compare; + unexpand_if_some; + unexpand_if_right; + unexpand_fail; + ] + +(* + If an argument of Prim is a sequence, we do not want to unexpand + its root in case the source already contains an expanded macro. In + which case unexpansion would remove surrounding braces and generate + ill-formed code. + + For example, DIIP { DIP { DUP }; SWAP } is not unexpandable but + DIIP {{ DIP { DUP }; SWAP }} (note the double braces) is unexpanded + to DIIP { DUUP }. + + unexpand_rec_but_root is the same as unexpand_rec but does not try + to unexpand at root *) + +let rec unexpand_rec expr = unexpand_rec_but_root (unexpand expr) + +and unexpand_rec_but_root = function + | Seq (loc, items) -> Seq (loc, List.map unexpand_rec items) + | Prim (loc, name, args, annot) -> + Prim (loc, name, List.map unexpand_rec_but_root args, annot) + | (Int _ | String _ | Bytes _) as atom -> atom + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"michelson.macros.unexpected_annotation" + ~title:"Unexpected annotation" + ~description: + "A macro had an annotation, but no annotation was permitted on this \ + macro." + ~pp:(fun ppf -> Format.fprintf ppf "Unexpected annotation on macro %s.") + (obj1 (req "macro_name" string)) + (function Unexpected_macro_annotation str -> Some str | _ -> None) + (fun s -> Unexpected_macro_annotation s) ; + register_error_kind + `Permanent + ~id:"michelson.macros.sequence_expected" + ~title:"Macro expects a sequence" + ~description:"An macro expects a sequence, but a sequence was not provided" + ~pp:(fun ppf name -> + Format.fprintf + ppf + "Macro %s expects a sequence, but did not receive one." + name) + (obj1 (req "macro_name" string)) + (function Sequence_expected name -> Some name | _ -> None) + (fun name -> Sequence_expected name) ; + register_error_kind + `Permanent + ~id:"michelson.macros.bas_arity" + ~title:"Wrong number of arguments to macro" + ~description:"A wrong number of arguments was provided to a macro" + ~pp:(fun ppf (name, got, exp) -> + Format.fprintf + ppf + "Macro %s expects %d arguments, was given %d." + name + exp + got) + (obj3 + (req "macro_name" string) + (req "given_number_of_arguments" uint16) + (req "expected_number_of_arguments" uint16)) + (function + | Invalid_arity (name, got, exp) -> Some (name, got, exp) | _ -> None) + (fun (name, got, exp) -> Invalid_arity (name, got, exp)) diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_macros.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_macros.mli new file mode 100644 index 000000000000..352a59b00a9e --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_macros.mli @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_micheline + +type 'l node = ('l, string) Micheline.node + +type error += Unexpected_macro_annotation of string + +type error += Sequence_expected of string + +type error += Invalid_arity of string * int * int + +val expand : 'l node -> 'l node tzresult + +val expand_rec : 'l node -> 'l node * error list + +val expand_caddadr : 'l node -> 'l node option tzresult + +val expand_set_caddadr : 'l node -> 'l node option tzresult + +val expand_map_caddadr : 'l node -> 'l node option tzresult + +val expand_deprecated_dxiiivp : 'l node -> 'l node option tzresult + +val expand_pappaiir : 'l node -> 'l node option tzresult + +val expand_deprecated_duuuuup : 'l node -> 'l node option tzresult + +val expand_compare : 'l node -> 'l node option tzresult + +val expand_asserts : 'l node -> 'l node option tzresult + +val expand_unpappaiir : 'l node -> 'l node option tzresult + +val expand_if_some : 'l node -> 'l node option tzresult + +val expand_if_right : 'l node -> 'l node option tzresult + +val unexpand : 'l node -> 'l node + +val unexpand_rec : 'l node -> 'l node + +val unexpand_caddadr : 'l node -> 'l node option + +val unexpand_set_caddadr : 'l node -> 'l node option + +val unexpand_map_caddadr : 'l node -> 'l node option + +val unexpand_deprecated_dxiiivp : 'l node -> 'l node option + +val unexpand_pappaiir : 'l node -> 'l node option + +val unexpand_deprecated_duuuuup : 'l node -> 'l node option + +val unexpand_compare : 'l node -> 'l node option + +val unexpand_asserts : 'l node -> 'l node option + +val unexpand_unpappaiir : 'l node -> 'l node option + +val unexpand_if_some : 'l node -> 'l node option + +val unexpand_if_right : 'l node -> 'l node option diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_parser.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_parser.ml new file mode 100644 index 000000000000..4016dbcad9fe --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_parser.ml @@ -0,0 +1,133 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Tezos_micheline +open Micheline_parser +open Micheline + +type 'prim parser_result = { + source : string; + unexpanded : string canonical; + expanded : 'prim canonical; + expansion_table : (int * (Micheline_parser.location * int list)) list; + unexpansion_table : (int * int) list; +} + +type parsed = Michelson_v1_primitives.prim parser_result + +let compare_parsed = Stdlib.compare + +(* Unexpanded toplevel expression should be a sequence *) +let expand_all source ast errors = + let unexpanded, loc_table = extract_locations ast in + let expanded, expansion_errors = + Michelson_v1_macros.expand_rec (root unexpanded) + in + let expanded, unexpansion_table = extract_locations expanded in + let expansion_table = + let sorted = + List.sort (fun (_, a) (_, b) -> Stdlib.compare a b) unexpansion_table + in + let grouped = + let rec group = function + | acc, [] -> acc + | [], (u, e) :: r -> group ([(e, [u])], r) + | ((pe, us) :: racc as acc), (u, e) :: r -> + if e = pe then group ((e, u :: us) :: racc, r) + else group ((e, [u]) :: acc, r) + in + group ([], sorted) + in + match + List.map2 + ~when_different_lengths:() + (fun (l, ploc) (l', elocs) -> + assert (l = l') ; + (l, (ploc, elocs))) + (List.sort Stdlib.compare loc_table) + (List.sort Stdlib.compare grouped) + with + | Ok v -> v + | Error () -> invalid_arg "Michelson_v1_parser.expand_all" + in + ( {source; unexpanded; expanded; expansion_table; unexpansion_table}, + errors @ expansion_errors ) + +let expand_all_and_recognize_prims source ast errors = + let parsed, errors = expand_all source ast errors in + match Michelson_v1_primitives.prims_of_strings parsed.expanded with + | Ok expanded -> ({parsed with expanded}, errors) + | Error errs -> + let errs = Environment.wrap_tztrace errs in + let expanded = Micheline.strip_locations (Seq ((), [])) in + ({parsed with expanded}, errors @ errs) + +type micheline_parser = Toplevel | Expression + +type 'prim prim_type = + | Michelson_prim : Michelson_v1_primitives.prim prim_type + | String : string prim_type + +let parse (type prim) micheline_parser (prim_type : prim prim_type) ?check + source = + let tokens, lexing_errors = Micheline_parser.tokenize source in + let ast, parsing_errors = + match micheline_parser with + | Toplevel -> + let asts, parsing_errors = + Micheline_parser.parse_toplevel ?check tokens + in + let start = min_point asts and stop = max_point asts in + (Seq ({start; stop}, asts), parsing_errors) + | Expression -> Micheline_parser.parse_expression ?check tokens + in + let expand : + string -> + (location, string) Micheline.node -> + error trace -> + prim parser_result Micheline_parser.parsing_result = + match prim_type with + | Michelson_prim -> expand_all_and_recognize_prims + | String -> expand_all + in + expand source ast (lexing_errors @ parsing_errors) + +let parse_toplevel = parse Toplevel Michelson_prim + +let expand_toplevel = parse Toplevel String + +let parse_expression = parse Expression Michelson_prim + +let expand_expression = parse Expression String + +let expand_all_and_recognize_prims ~source ~original = + expand_all_and_recognize_prims source original [] + +let unrecognize_prims parsed = + { + parsed with + expanded = Michelson_v1_primitives.strings_of_prims parsed.expanded; + } diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_parser.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_parser.mli new file mode 100644 index 000000000000..f4b914a6ea1c --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_parser.mli @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Tezos_micheline + +(** The result of parsing and expanding a Michelson V1 script or data. *) +type 'prim parser_result = { + source : string; (** The original source code. *) + unexpanded : string Micheline.canonical; + (** Original expression with macros. *) + expanded : 'prim Micheline.canonical; + (** Expression with macros fully expanded. *) + expansion_table : (int * (Micheline_parser.location * int list)) list; + (** Associates unexpanded nodes to their parsing locations and + the nodes expanded from it in the expanded expression. *) + unexpansion_table : (int * int) list; + (** Associates an expanded node to its source in the unexpanded + expression. *) +} + +type parsed = Michelson_v1_primitives.prim parser_result + +val compare_parsed : parsed -> parsed -> int + +val parse_toplevel : + ?check:bool -> string -> parsed Micheline_parser.parsing_result + +(** Same as [parse_toplevel] but skips the final step (recognizing the + primitives). *) +val expand_toplevel : + ?check:bool -> string -> string parser_result Micheline_parser.parsing_result + +val parse_expression : + ?check:bool -> string -> parsed Micheline_parser.parsing_result + +(** Same as [parse_expression] but skips the final step (recognizing the + primitives). *) +val expand_expression : + ?check:bool -> string -> string parser_result Micheline_parser.parsing_result + +val expand_all_and_recognize_prims : + source:string -> + original:Micheline_parser.node -> + parsed Micheline_parser.parsing_result + +val unrecognize_prims : parsed -> string parser_result diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_printer.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_printer.ml new file mode 100644 index 000000000000..6b4086c46a5c --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_printer.ml @@ -0,0 +1,239 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline +open Micheline +open Micheline_printer + +let anon = {comment = None} + +let node_of_expr loc expr = + expr |> Michelson_v1_primitives.strings_of_prims + |> Micheline.inject_locations (fun _ -> loc) + +let node_of_stack_elt loc (ty, x) = + let ty = node_of_expr loc ty in + let x = node_of_expr loc x in + Micheline.Prim (loc, "Stack_elt", [ty; x], []) + +let unparse_stack loc l = Micheline.Seq (loc, List.map (node_of_stack_elt loc) l) + +let print_typed_stack out l = print_expr out (unparse_stack anon l) + +let print_expr ppf expr = print_expr ppf (node_of_expr anon expr) + +let print_expr_unwrapped ppf expr = + print_expr_unwrapped ppf (node_of_expr anon expr) + +let print_stack ppf = function + | [] -> Format.fprintf ppf "[]" + | more -> + Format.fprintf + ppf + "@[[ %a ]@]" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf "@ : ") + print_expr_unwrapped) + more + +let print_execution_trace ppf (trace : Script_typed_ir.execution_trace) = + Format.pp_print_list + (fun ppf (loc, gas, stack) -> + Format.fprintf + ppf + "- @[location: %d (just consumed gas: %a)@,[ @[%a ]@]@]" + loc + Gas.Arith.pp + gas + (Format.pp_print_list (fun ppf e -> + Format.fprintf ppf "@[%a@]" print_expr e)) + stack) + ppf + trace + +let print_big_map_diff ppf lazy_storage_diff = + let diff = + Contract.Legacy_big_map_diff.of_lazy_storage_diff lazy_storage_diff + in + let pp_map ppf id = + if Compare.Z.(id < Z.zero) then + Format.fprintf ppf "temp(%s)" (Z.to_string (Z.neg id)) + else Format.fprintf ppf "map(%s)" (Z.to_string id) + in + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list ~pp_sep:Format.pp_print_space (fun ppf -> function + | Contract.Legacy_big_map_diff.Clear id -> + Format.fprintf ppf "Clear %a" pp_map id + | Contract.Legacy_big_map_diff.Alloc {big_map; key_type; value_type} -> + Format.fprintf + ppf + "New %a of type (big_map %a %a)" + pp_map + big_map + print_expr + key_type + print_expr + value_type + | Contract.Legacy_big_map_diff.Copy {src; dst} -> + Format.fprintf ppf "Copy %a to %a" pp_map src pp_map dst + | Contract.Legacy_big_map_diff.Update {big_map; diff_key; diff_value; _} + -> + Format.fprintf + ppf + "%s %a[%a]%a" + (match diff_value with None -> "Unset" | Some _ -> "Set") + pp_map + big_map + print_expr + diff_key + (fun ppf -> function + | None -> () + | Some x -> Format.fprintf ppf " to %a" print_expr x) + diff_value)) + (diff :> Contract.Legacy_big_map_diff.item list) + +let inject_types type_map parsed = + let rec inject_expr = function + | Seq (loc, items) -> + Seq (inject_loc `before loc, List.map inject_expr items) + | Prim (loc, name, items, annot) -> + Prim (inject_loc `after loc, name, List.map inject_expr items, annot) + | Int (loc, value) -> Int (inject_loc `after loc, value) + | String (loc, value) -> String (inject_loc `after loc, value) + | Bytes (loc, value) -> Bytes (inject_loc `after loc, value) + and inject_loc which loc = + let comment = + let ( >?? ) = Option.bind in + List.assoc ~equal:Int.equal loc parsed.Michelson_v1_parser.expansion_table + >?? fun (_, locs) -> + let locs = List.sort compare locs in + List.hd locs >?? fun head_loc -> + List.assoc ~equal:Int.equal head_loc type_map >?? fun (bef, aft) -> + let stack = match which with `before -> bef | `after -> aft in + Some (Format.asprintf "%a" print_stack stack) + in + {comment} + in + inject_expr (root parsed.unexpanded) + +let unparse ?type_map parse expanded = + let source = + match type_map with + | Some type_map -> + let unexpanded, unexpansion_table = + expanded |> Michelson_v1_primitives.strings_of_prims |> root + |> Michelson_v1_macros.unexpand_rec |> Micheline.extract_locations + in + let rec inject_expr = function + | Seq (loc, items) -> + Seq (inject_loc `before loc, List.map inject_expr items) + | Prim (loc, name, items, annot) -> + Prim + (inject_loc `after loc, name, List.map inject_expr items, annot) + | Int (loc, value) -> Int (inject_loc `after loc, value) + | String (loc, value) -> String (inject_loc `after loc, value) + | Bytes (loc, value) -> Bytes (inject_loc `after loc, value) + and inject_loc which loc = + let comment = + let ( >?? ) = Option.bind in + List.assoc ~equal:Int.equal loc unexpansion_table >?? fun loc -> + List.assoc ~equal:Int.equal loc type_map >?? fun (bef, aft) -> + let stack = match which with `before -> bef | `after -> aft in + Some (Format.asprintf "%a" print_stack stack) + in + {comment} + in + unexpanded |> root |> inject_expr + |> Format.asprintf "%a" Micheline_printer.print_expr + | None -> + expanded |> Michelson_v1_primitives.strings_of_prims |> root + |> Michelson_v1_macros.unexpand_rec |> Micheline.strip_locations + |> Micheline_printer.printable (fun n -> n) + |> Format.asprintf "%a" Micheline_printer.print_expr + in + match parse source with + | res, [] -> res + | _, _ :: _ -> Stdlib.failwith "Michelson_v1_printer.unparse" + +let unparse_toplevel ?type_map = + unparse ?type_map Michelson_v1_parser.parse_toplevel + +let unparse_expression = unparse Michelson_v1_parser.parse_expression + +let unparse_invalid expanded = + let source = + expanded |> root |> Michelson_v1_macros.unexpand_rec + |> Micheline.strip_locations + |> Micheline_printer.printable (fun n -> n) + |> Format.asprintf "%a" Micheline_printer.print_expr_unwrapped + in + fst (Michelson_v1_parser.expand_toplevel source) + +let ocaml_constructor_of_prim prim = + (* Assuming all the prim constructor prefixes match the + [[Michelson_v1_primitives.namespace]]. *) + let prefix = + Michelson_v1_primitives.(namespace prim |> string_of_namespace) + in + Format.asprintf "%s_%s" prefix @@ Michelson_v1_primitives.string_of_prim prim + +let micheline_string_of_expression ~zero_loc expression = + let string_of_list : string list -> string = + fun xs -> String.concat "; " xs |> Format.asprintf "[%s]" + in + let show_loc loc = if zero_loc then 0 else loc in + let rec string_of_node = function + | Int (loc, i) -> + let z = + match Z.to_int i with + | 0 -> "Z.zero" + | 1 -> "Z.one" + | i -> Format.asprintf "Z.of_int %d" i + in + Format.asprintf "Int (%d, %s)" (show_loc loc) z + | String (loc, s) -> Format.asprintf "String (%d, \"%s\")" (show_loc loc) s + | Bytes (loc, b) -> + Format.asprintf + "Bytes (%d, Bytes.of_string \"%s\")" + (show_loc loc) + Bytes.(escaped b |> to_string) + | Prim (loc, prim, nodes, annot) -> + Format.asprintf + "Prim (%d, %s, %s, %s)" + (show_loc loc) + (ocaml_constructor_of_prim prim) + (string_of_list @@ List.map string_of_node nodes) + (string_of_list @@ List.map (Format.asprintf "\"%s\"") annot) + | Seq (loc, nodes) -> + Format.asprintf + "Seq (%d, %s)" + (show_loc loc) + (string_of_list @@ List.map string_of_node nodes) + in + string_of_node (root expression) diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_printer.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_printer.mli new file mode 100644 index 000000000000..f70b423c058f --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_printer.mli @@ -0,0 +1,72 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +val print_expr : Format.formatter -> Script_repr.expr -> unit + +val print_expr_unwrapped : Format.formatter -> Script_repr.expr -> unit + +val unparse_stack : + 'location -> + (Script_repr.expr * Script_repr.expr) list -> + ('location, string) Micheline.node + +val print_typed_stack : + Format.formatter -> (Script_repr.expr * Script_repr.expr) list -> unit + +val print_execution_trace : + Format.formatter -> Script_typed_ir.execution_trace -> unit + +val print_big_map_diff : Format.formatter -> Lazy_storage.diffs -> unit + +(** Insert the type map returned by the typechecker as comments in a + printable Micheline AST. *) +val inject_types : + Script_tc_errors.type_map -> + Michelson_v1_parser.parsed -> + Micheline_printer.node + +(** Unexpand the macros and produce the result of parsing an + intermediate pretty printed source. Useful when working with + contracts extracted from the blockchain and not local files. *) +val unparse_toplevel : + ?type_map:Script_tc_errors.type_map -> + Script.expr -> + Michelson_v1_parser.parsed + +val unparse_expression : Script.expr -> Michelson_v1_parser.parsed + +(** Unexpand the macros and produce the result of parsing an + intermediate pretty printed source. Works on generic trees,for + programs that fail to be converted to a specific script version. *) +val unparse_invalid : + string Micheline.canonical -> string Michelson_v1_parser.parser_result + +val ocaml_constructor_of_prim : Michelson_v1_primitives.prim -> string + +val micheline_string_of_expression : zero_loc:bool -> Script.expr -> string diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_stack.ml b/src/proto_020_PsParisC/lib_client/michelson_v1_stack.ml new file mode 100644 index 000000000000..00dad07eec4e --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_stack.ml @@ -0,0 +1,663 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_micheline +open Protocol +open Alpha_context + +type localized_node = { + parser_loc : Micheline_parser.location option; + canonical_loc : Micheline.canonical_location; + node : string Micheline.canonical; +} + +let print_localized_node_location fmt localized_node = + match localized_node.parser_loc with + | Some parser_loc -> + Format.fprintf + fmt + "%s" + (Format.kasprintf + String.capitalize_ascii + "%a" + Micheline_parser.print_location + parser_loc) + | None -> Format.fprintf fmt "At position %d" localized_node.canonical_loc + +let print_localized_node fmt localized_node = + Micheline_printer.print_expr_unwrapped + fmt + (Micheline_printer.printable Fun.id localized_node.node) + +let localize_node ~(parsed : string Michelson_v1_parser.parser_result) + (n : (Micheline.canonical_location, string) Micheline.node) : localized_node + = + let canonical_loc = Micheline.location n in + let parser_loc = + let open Option_syntax in + let* oloc = + List.assoc ~equal:Int.equal canonical_loc parsed.unexpansion_table + in + let+ ploc, _ = List.assoc ~equal:Int.equal oloc parsed.expansion_table in + ploc + in + {parser_loc; canonical_loc; node = Micheline.strip_locations n} + +let localized_node_encoding : localized_node Data_encoding.t = + Data_encoding.( + conv + (fun {parser_loc; canonical_loc; node} -> + (parser_loc, canonical_loc, node)) + (fun (parser_loc, canonical_loc, node) -> + {parser_loc; canonical_loc; node}) + (obj3 + (req "parser_location" (option Micheline_parser.location_encoding)) + (req + "canonical_location" + Micheline_encoding.canonical_location_encoding) + (req + "node" + (Micheline_encoding.canonical_encoding + ~variant:"alpha_client" + Data_encoding.string)))) + +type error += + | Wrong_stack_item of localized_node + | Wrong_stack of localized_node + | Wrong_other_contracts_item of localized_node + | Wrong_other_contracts of localized_node + | Wrong_extra_big_maps_item of localized_node + | Wrong_extra_big_maps of localized_node + | Invalid_address_for_smart_contract of string + | Duplicated_tzt_top_prim of string * localized_node + | Wrong_tzt_top_prim_arity of string * localized_node * int + | Unknown_tzt_top_prim of string * localized_node + | Missing_mandatory_tzt_top_prim of string + | Invalid_format_for_tzt_top_prim of string * localized_node + | Invalid_tzt_toplevel of localized_node + +let () = + Protocol_client_context.register_error_kind + `Permanent + ~id:"michelson.stack.wrong_stack_item" + ~title:"Wrong stack item" + ~description:"Failed to parse an item in a typed stack." + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Unexpected format for an item in a typed stack. Expected: \ + Stack_elt ; got %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Wrong_stack_item node -> Some node | _ -> None) + (fun node -> Wrong_stack_item node) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"michelson.stack.wrong_stack" + ~title:"Wrong stack" + ~description:"Failed to parse a typed stack." + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Unexpected format for a typed stack. Expected a sequence of \ + Stack_elt ; got %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Wrong_stack node -> Some node | _ -> None) + (fun node -> Wrong_stack node) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"michelson.wrong_other_contracts_item" + ~title:"Wrong description of an other contract" + ~description:"Failed to parse an item in a description of other contracts." + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Unexpected format for an item in a description of other \ + contracts. Expected: Contract
; got %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Wrong_other_contracts_item node -> Some node | _ -> None) + (fun node -> Wrong_other_contracts_item node) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"michelson.wrong_other_contracts" + ~title:"Wrong description of a list of other contracts" + ~description:"Failed to parse a description of other contracts." + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Unexpected format for a description of other contracts. Expected \ + a sequence of Contract
; got %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Wrong_other_contracts node -> Some node | _ -> None) + (fun node -> Wrong_other_contracts node) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"michelson.wrong_extra_big_maps_item" + ~title:"Wrong description of an extra big map" + ~description:"Failed to parse an item in a description of extra big maps." + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Unexpected format for an item in a description of extra big \ + maps. Expected: Big_map ; \ + got %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Wrong_extra_big_maps_item node -> Some node | _ -> None) + (fun node -> Wrong_extra_big_maps_item node) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"michelson.wrong_extra_big_maps" + ~title:"Wrong description of a list of extra big maps" + ~description:"Failed to parse a description of extra big maps." + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Unexpected format for a description of extra big maps. Expected \ + a sequence of Big_map ; got \ + %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Wrong_extra_big_maps node -> Some node | _ -> None) + (fun node -> Wrong_extra_big_maps node) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"InvalidAddressForSmartContract" + ~title:"Invalid address for smart contract" + ~description: + "Invalid input, expected a smart contract address in base58 check \ + notation (KT1...)" + Data_encoding.(obj1 (req "invalid_address" string)) + ~pp:(fun ppf literal -> + Format.fprintf + ppf + "Bad argument value for a smart contract address. Expected an address \ + in base58 checked notation starting with 'KT1', but given '%s'" + literal) + (function Invalid_address_for_smart_contract str -> Some str | _ -> None) + (fun str -> Invalid_address_for_smart_contract str) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"tzt.wrong_toplevel_arity" + ~title:"Wrong arity for a TZT toplevel primitive" + ~description:"A known toplevel TZT primitive was used with a bad arity." + ~pp:(fun ppf (prim, node, arity) -> + Format.fprintf + ppf + "%a,@ Wrong arity for TZT toplevel primitive %s, expected %d \ + arguments, got %a" + print_localized_node_location + node + prim + arity + print_localized_node + node) + Data_encoding.( + obj3 + (req "prim" string) + (req "node" localized_node_encoding) + (req "arity" int16)) + (function + | Wrong_tzt_top_prim_arity (prim, node, arity) -> Some (prim, node, arity) + | _ -> None) + (fun (prim, node, arity) -> Wrong_tzt_top_prim_arity (prim, node, arity)) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"tzt.duplicated_toplevel" + ~title:"Duplicated TZT toplevel primitive" + ~description:"A toplevel TZT primitive was used several times." + ~pp:(fun ppf (prim, node) -> + Format.fprintf + ppf + "%a,@ The TZT toplevel primitive %s, cannot be used because it has \ + already been used. A TZT toplevel primitive can only be used once per \ + unit test." + print_localized_node_location + node + prim) + Data_encoding.( + obj2 (req "prim" string) (req "node" localized_node_encoding)) + (function + | Duplicated_tzt_top_prim (prim, node) -> Some (prim, node) | _ -> None) + (fun (prim, node) -> Duplicated_tzt_top_prim (prim, node)) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"tzt.unknown_toplevel" + ~title:"Unknown TZT toplevel primitive" + ~description:"A toplevel TZT primitive was unknown." + ~pp:(fun ppf (prim, node) -> + Format.fprintf + ppf + "%a,@ The TZT toplevel primitive %s is unknown." + print_localized_node_location + node + prim) + Data_encoding.( + obj2 (req "prim" string) (req "node" localized_node_encoding)) + (function + | Unknown_tzt_top_prim (prim, node) -> Some (prim, node) | _ -> None) + (fun (prim, node) -> Unknown_tzt_top_prim (prim, node)) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"tzt.missing_mandatory" + ~title:"Missing TZT mandatory toplevel primitive" + ~description:"A mandatory toplevel TZT primitive was missing." + ~pp:(fun ppf prim -> + Format.fprintf + ppf + "The mandatory TZT toplevel primitive %s is missing." + prim) + Data_encoding.(obj1 (req "prim" string)) + (function Missing_mandatory_tzt_top_prim prim -> Some prim | _ -> None) + (fun prim -> Missing_mandatory_tzt_top_prim prim) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"tzt.invalid_format" + ~title:"Invalid format for a TZT toplevel primitive" + ~description:"Invalid format for a TZT toplevel primitive" + ~pp:(fun ppf (prim, node) -> + Format.fprintf + ppf + "%a,@ Invalid format for TZT toplevel primitive %s." + print_localized_node_location + node + prim) + Data_encoding.( + obj2 (req "prim" string) (req "node" localized_node_encoding)) + (function + | Invalid_format_for_tzt_top_prim (prim, node) -> Some (prim, node) + | _ -> None) + (fun (prim, node) -> Invalid_format_for_tzt_top_prim (prim, node)) ; + Protocol_client_context.register_error_kind + `Permanent + ~id:"tzt.invalid_toplevel" + ~title:"Invalid format for TZT toplevel entry" + ~description:"Invalid format for a TZT toplevel entry" + ~pp:(fun ppf node -> + Format.fprintf + ppf + "%a,@ Invalid format for TZT toplevel entry, expected a sequence of \ + primitive applications, got %a." + print_localized_node_location + node + print_localized_node + node) + localized_node_encoding + (function Invalid_tzt_toplevel node -> Some node | _ -> None) + (fun node -> Invalid_tzt_toplevel node) + +let parse_expression (node : (_, string) Micheline.node) = + Environment.wrap_tzresult + @@ Michelson_v1_primitives.prims_of_strings (Micheline.strip_locations node) + +let parse_stack_item ~parsed = + let open Result_syntax in + function + | Micheline.Prim (_loc, "Stack_elt", [ty; v], _annot) -> + let* ty = parse_expression ty in + let* v = parse_expression v in + return (ty, v) + | e -> tzfail (Wrong_stack_item (localize_node ~parsed e)) + +let parse_other_contract_item ~parsed = + let open Result_syntax in + function + | Micheline.Prim (_loc, "Contract", [address; ty], _annot) as e -> + let* address = parse_expression address in + let* address = + match Micheline.root address with + | Micheline.String (_loc, s) -> ( + match Environment.Base58.decode s with + | Some (Contract_hash.Data h) -> return h + | Some _ | None -> tzfail (Invalid_address_for_smart_contract s)) + | _ -> tzfail (Wrong_other_contracts_item (localize_node ~parsed e)) + in + let* ty = parse_expression ty in + return RPC.Scripts.S.{address; ty} + | e -> tzfail (Wrong_other_contracts_item (localize_node ~parsed e)) + +let parse_extra_big_map_item ~parsed = + let open Result_syntax in + function + | Micheline.Prim (_loc, "Big_map", [id; kty; vty; items], _annot) as e -> + let* id = parse_expression id in + let* id = + match Micheline.root id with + | Micheline.Int (_loc, id) -> return (Big_map.Id.parse_z id) + | _ -> tzfail (Wrong_other_contracts_item (localize_node ~parsed e)) + in + let* kty = parse_expression kty in + let* vty = parse_expression vty in + let* items = parse_expression items in + return RPC.Scripts.S.{id; kty; vty; items} + | e -> tzfail (Wrong_extra_big_maps_item (localize_node ~parsed e)) + +let parse_sequence ?node ~(parsed : string Michelson_v1_parser.parser_result) + ~error parse_item = + let node = Option.value ~default:(Micheline.root parsed.expanded) node in + let error () = error (localize_node ~parsed node) in + match node with + | Micheline.Seq (_loc, l) -> + record_trace_eval error @@ List.map_e (parse_item ~parsed) l + | _ -> Result_syntax.tzfail (error ()) + +let parse_stack ?node parsed = + parse_sequence + ?node + ~parsed + ~error:(fun node -> Wrong_stack node) + parse_stack_item + +let parse_other_contracts ?node parsed = + parse_sequence + ?node + ~parsed + ~error:(fun node -> Wrong_other_contracts node) + parse_other_contract_item + +let parse_extra_big_maps ?node parsed = + parse_sequence + ?node + ~parsed + ~error:(fun node -> Wrong_extra_big_maps node) + parse_extra_big_map_item + +type unit_test_optional = { + now : Script_timestamp.t option; + level : Script_int.n Script_int.num option; + sender : Contract.t option; + source : Signature.public_key_hash option; + chain_id : Chain_id.t option; + self : Contract_hash.t option; + parameter : Script.expr option; + amount : Tez.t option; + balance : Tez.t option; + other_contracts : RPC.Scripts.S.other_contract_description list option; + extra_big_maps : RPC.Scripts.S.extra_big_map_description list option; +} + +type unit_test = { + input : (Script.expr * Script.expr) list; + code : Script.expr; + output : (Micheline.canonical_location, string) Micheline.node; + optional : unit_test_optional; +} + +(* Same as unit_test but all fields are optional. Used only during + parsing. *) +type temp_unit_test = { + temp_input : (Script.expr * Script.expr) list option; + temp_code : Script.expr option; + temp_output : (Micheline.canonical_location, string) Micheline.node option; + temp_optional : unit_test_optional; +} + +(* Same as Option.value_fe but takes an error instead of a trace. *) +let value_fe_err opt ~error = + Option.value_fe opt ~error:(fun () -> TzTrace.make (error ())) + +(* TODO: #6678 + Reuse protocol elaboration functions from the + Script_ir_translator module instead of duplicating them here. *) +let parse_mutez node ~error = + let mutez_opt = + match node with + | Micheline.Int (_loc, z) -> Tez.of_mutez (Z.to_int64 z) + | _ -> None + in + value_fe_err mutez_opt ~error + +let parse_chain_id node ~error = + match node with + | Micheline.String (_loc, s) -> + record_trace_eval error @@ Chain_id.of_b58check s + | Bytes (_loc, b) -> + value_fe_err ~error + @@ Data_encoding.Binary.of_bytes_opt Chain_id.encoding b + | _ -> Result_syntax.tzfail @@ error () + +let parse_timestamp node ~error = + value_fe_err ~error + @@ + match node with + | Micheline.String (_loc, s) -> Script_timestamp.of_string s + | Int (_loc, z) -> Some (Script_timestamp.of_zint z) + | _ -> None + +let parse_nat node ~error = + value_fe_err ~error + @@ + match node with + | Micheline.Int (_loc, z) -> Script_int.(is_nat (of_zint z)) + | _ -> None + +let parse_key_hash node ~error = + match node with + | Micheline.String (_loc, s) -> + record_trace_eval error @@ Signature.Public_key_hash.of_b58check s + | Bytes (_loc, b) -> + value_fe_err ~error + @@ Data_encoding.Binary.of_bytes_opt Signature.Public_key_hash.encoding b + | _ -> Result_syntax.tzfail @@ error () + +let parse_address node ~error = + match node with + | Micheline.String (_loc, s) -> + record_trace_eval error @@ Environment.wrap_tzresult + @@ Contract.of_b58check s + | Bytes (_loc, b) -> + value_fe_err ~error + @@ Data_encoding.Binary.of_bytes_opt Contract.encoding b + | _ -> Result_syntax.tzfail @@ error () + +let parse_contract_hash node ~error = + value_fe_err ~error + @@ + match node with + | Micheline.String (_loc, s) -> Contract_hash.of_b58check_opt s + | Bytes (_loc, b) -> + Data_encoding.Binary.of_bytes_opt Contract_hash.encoding b + | _ -> None + +let parse_unit_test (parsed : string Michelson_v1_parser.parser_result) = + let open Result_syntax in + let open Micheline in + let rec parse ut = function + | [] -> return ut + | (Prim (_loc, prim, [arg], _annots) as e) :: l -> ( + let check_duplicated = function + | None -> return_unit + | Some _ -> + tzfail (Duplicated_tzt_top_prim (prim, localize_node ~parsed e)) + in + let invalid_format () = + Invalid_format_for_tzt_top_prim (prim, localize_node ~parsed e) + in + let trace_invalid_format res = record_trace_eval invalid_format res in + match prim with + | "input" -> + let* () = check_duplicated ut.temp_input in + let* items = trace_invalid_format @@ parse_stack ~node:arg parsed in + parse {ut with temp_input = Some items} l + | "output" -> + let* () = check_duplicated ut.temp_output in + parse {ut with temp_output = Some arg} l + | "code" -> + let* () = check_duplicated ut.temp_code in + let* c = trace_invalid_format @@ parse_expression arg in + parse {ut with temp_code = Some c} l + | "amount" -> + let* () = check_duplicated ut.temp_optional.amount in + let* t = parse_mutez arg ~error:invalid_format in + parse + {ut with temp_optional = {ut.temp_optional with amount = Some t}} + l + | "balance" -> + let* () = check_duplicated ut.temp_optional.balance in + let* t = parse_mutez arg ~error:invalid_format in + parse + {ut with temp_optional = {ut.temp_optional with balance = Some t}} + l + | "chain_id" -> + let* () = check_duplicated ut.temp_optional.chain_id in + let* chain_id = parse_chain_id arg ~error:invalid_format in + parse + { + ut with + temp_optional = {ut.temp_optional with chain_id = Some chain_id}; + } + l + | "now" -> + let* () = check_duplicated ut.temp_optional.now in + let* time = parse_timestamp arg ~error:invalid_format in + parse + {ut with temp_optional = {ut.temp_optional with now = Some time}} + l + | "level" -> + let* () = check_duplicated ut.temp_optional.level in + let* level = parse_nat arg ~error:invalid_format in + parse + { + ut with + temp_optional = {ut.temp_optional with level = Some level}; + } + l + | "sender" -> + let* () = check_duplicated ut.temp_optional.sender in + let* addr = parse_address arg ~error:invalid_format in + parse + { + ut with + temp_optional = {ut.temp_optional with sender = Some addr}; + } + l + | "source" -> + let* () = check_duplicated ut.temp_optional.source in + let* addr = parse_key_hash arg ~error:invalid_format in + parse + { + ut with + temp_optional = {ut.temp_optional with source = Some addr}; + } + l + | "self" -> + let* () = check_duplicated ut.temp_optional.self in + let* addr = parse_contract_hash arg ~error:invalid_format in + parse + {ut with temp_optional = {ut.temp_optional with self = Some addr}} + l + | "parameter" -> + let* () = check_duplicated ut.temp_optional.parameter in + let* ty = parse_expression arg in + parse + { + ut with + temp_optional = {ut.temp_optional with parameter = Some ty}; + } + l + | "other_contracts" -> + let* () = check_duplicated ut.temp_optional.other_contracts in + let* items = parse_other_contracts ~node:arg parsed in + parse + { + ut with + temp_optional = + {ut.temp_optional with other_contracts = Some items}; + } + l + | "big_maps" -> + let* () = check_duplicated ut.temp_optional.extra_big_maps in + let* items = parse_extra_big_maps ~node:arg parsed in + parse + { + ut with + temp_optional = + {ut.temp_optional with extra_big_maps = Some items}; + } + l + | _ -> tzfail @@ Unknown_tzt_top_prim (prim, localize_node ~parsed e)) + | (Prim (_loc, prim, ([] | _ :: _ :: _), _annots) as e) :: _ -> + tzfail @@ Wrong_tzt_top_prim_arity (prim, localize_node ~parsed e, 1) + | ((Seq _ | Int _ | String _ | Bytes _) as e) :: _ -> + tzfail @@ Invalid_tzt_toplevel (localize_node ~parsed e) + in + let nodes = + match Micheline.root parsed.expanded with + | Seq (_, nodes) -> nodes + | node -> [node] + in + let* ut = + parse + { + temp_input = None; + temp_code = None; + temp_output = None; + temp_optional = + { + now = None; + level = None; + sender = None; + source = None; + chain_id = None; + self = None; + parameter = None; + amount = None; + balance = None; + other_contracts = None; + extra_big_maps = None; + }; + } + nodes + in + let check_mandatory opt prim = + Option.value_e + opt + ~error:(TzTrace.make @@ Missing_mandatory_tzt_top_prim prim) + in + let* input = check_mandatory ut.temp_input "input" in + let* code = check_mandatory ut.temp_code "code" in + let* output = check_mandatory ut.temp_output "output" in + return {input; code; output; optional = ut.temp_optional} diff --git a/src/proto_020_PsParisC/lib_client/michelson_v1_stack.mli b/src/proto_020_PsParisC/lib_client/michelson_v1_stack.mli new file mode 100644 index 000000000000..8408ea9004d8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/michelson_v1_stack.mli @@ -0,0 +1,68 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(*****************************************************************************) + +open Tezos_micheline +open Protocol +open Alpha_context + +type localized_node + +type error += + | Wrong_stack_item of localized_node + | Wrong_stack of localized_node + | Wrong_other_contracts_item of localized_node + | Wrong_other_contracts of localized_node + | Wrong_extra_big_maps_item of localized_node + | Wrong_extra_big_maps of localized_node + | Invalid_address_for_smart_contract of string + | Duplicated_tzt_top_prim of string * localized_node + | Wrong_tzt_top_prim_arity of string * localized_node * int + | Unknown_tzt_top_prim of string * localized_node + | Missing_mandatory_tzt_top_prim of string + +val print_localized_node_location : Format.formatter -> localized_node -> unit + +val print_localized_node : Format.formatter -> localized_node -> unit + +val parse_stack : + ?node:(Micheline.canonical_location, string) Micheline.node -> + string Michelson_v1_parser.parser_result -> + (Script.expr * Script.expr) list tzresult + +val parse_other_contracts : + ?node:(Micheline.canonical_location, string) Micheline.node -> + string Michelson_v1_parser.parser_result -> + RPC.Scripts.S.other_contract_description list tzresult + +val parse_extra_big_maps : + ?node:(Micheline.canonical_location, string) Micheline.node -> + string Michelson_v1_parser.parser_result -> + RPC.Scripts.S.extra_big_map_description list tzresult + +type unit_test_optional = { + now : Script_timestamp.t option; + level : Script_int.n Script_int.num option; + sender : Contract.t option; + source : Signature.public_key_hash option; + chain_id : Chain_id.t option; + self : Contract_hash.t option; + parameter : Script.expr option; + amount : Tez.t option; + balance : Tez.t option; + other_contracts : RPC.Scripts.S.other_contract_description list option; + extra_big_maps : RPC.Scripts.S.extra_big_map_description list option; +} + +type unit_test = { + input : (Script.expr * Script.expr) list; + code : Script.expr; + output : (Micheline.canonical_location, string) Micheline.node; + optional : unit_test_optional; +} + +val parse_unit_test : + string Michelson_v1_parser.parser_result -> unit_test tzresult diff --git a/src/proto_020_PsParisC/lib_client/mockup.ml b/src/proto_020_PsParisC/lib_client/mockup.ml new file mode 100644 index 000000000000..d9b140c6c6fc --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/mockup.ml @@ -0,0 +1,652 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(* ------------------------------------------------------------------------- *) +(* Mockup protocol parameters *) + +(** Protocol constants overriding logic. *) +module Protocol_constants_overrides = struct + (** Equivalent of [Constants.parametric] with additionally [chain_id] and [timestamp]. *) + type t = { + parametric : Constants.Parametric.t; + chain_id : Chain_id.t option; + timestamp : Time.Protocol.t option; + } + + let encoding = + let open Data_encoding in + conv + (fun {parametric; chain_id; timestamp} -> + (parametric, (chain_id, timestamp))) + (fun (parametric, (chain_id, timestamp)) -> + {parametric; chain_id; timestamp}) + (merge_objs + Constants.Parametric.encoding + (obj2 + (opt "chain_id" Chain_id.encoding) + (opt "initial_timestamp" Time.Protocol.encoding))) + + let default_value (cctxt : Tezos_client_base.Client_context.full) : + t tzresult Lwt.t = + let open Lwt_result_syntax in + let cpctxt = new Protocol_client_context.wrap_full cctxt in + let* {parametric; _} = + Protocol.Constants_services.all cpctxt (cpctxt#chain, cpctxt#block) + in + let to_chain_id_opt = function `Hash c -> Some c | _ -> None in + let* header = + Shell_services.Blocks.Header.shell_header + cpctxt + ~chain:cpctxt#chain + ~block:cpctxt#block + () + in + return + { + parametric; + chain_id = to_chain_id_opt cpctxt#chain; + timestamp = Some header.timestamp; + } +end + +module Parsed_account = struct + type t = {name : string; sk_uri : Client_keys.sk_uri; amount : Tez.t} + + let pp ppf account = + let open Format in + let format_amount ppf value = fprintf ppf "amount:%a" Tez.pp value in + fprintf + ppf + "@[name:%s@,sk_uri:%s@,%a@]" + account.name + (Uri.to_string (account.sk_uri :> Uri.t)) + format_amount + account.amount + + let encoding = + let open Data_encoding in + conv + (fun p -> (p.name, p.sk_uri, p.amount)) + (fun (name, sk_uri, amount) -> {name; sk_uri; amount}) + (obj3 + (req "name" string) + (req "sk_uri" Client_keys.Secret_key.encoding) + (req "amount" Tez.encoding)) + + let to_bootstrap_account repr = + let open Lwt_result_syntax in + let* pk_uri = Tezos_client_base.Client_keys.neuterize repr.sk_uri in + let* public_key = Tezos_client_base.Client_keys.public_key pk_uri in + let public_key_hash = Signature.Public_key.hash public_key in + return + Parameters. + { + public_key_hash; + public_key = Some public_key; + amount = repr.amount; + delegate_to = None; + consensus_key = None; + } + + let default_to_json (cctxt : Tezos_client_base.Client_context.full) : + string tzresult Lwt.t = + let open Lwt_result_syntax in + let rpc_context = new Protocol_client_context.wrap_full cctxt in + let wallet = (cctxt :> Client_context.wallet) in + let parsed_account_reprs = ref [] in + let errors = ref [] in + let* all_keys = Client_keys.list_keys wallet in + let*! () = + List.iter_s + (function + | name, pkh, _pk_opt, Some sk_uri -> ( + let contract = Contract.Implicit pkh in + let*! tz_balance = + Client_proto_context.get_balance + rpc_context + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + match tz_balance with + | Ok balance -> ( + let tez_repr = Tez.of_mutez @@ Tez.to_mutez balance in + match tez_repr with + | None -> + (* we're reading the wallet, it's content MUST be valid *) + assert false + | Some amount -> + parsed_account_reprs := + {name; sk_uri; amount} :: !parsed_account_reprs ; + Lwt.return_unit) + | Error err -> + errors := err :: !errors ; + Lwt.return_unit) + | _ -> Lwt.return_unit) + all_keys + in + match !errors with + | [] -> + let json = + Data_encoding.Json.construct + (Data_encoding.list encoding) + !parsed_account_reprs + in + return @@ Data_encoding.Json.to_string json + | errs -> Lwt.return_error @@ List.concat errs +end + +module Bootstrap_account = struct + let encoding : Parameters.bootstrap_account Data_encoding.t = + let open Data_encoding in + let open Parameters in + conv + (fun {public_key_hash; public_key; amount; delegate_to; consensus_key} -> + (public_key_hash, public_key, amount, delegate_to, consensus_key)) + (fun (public_key_hash, public_key, amount, delegate_to, consensus_key) -> + {public_key_hash; public_key; amount; delegate_to; consensus_key}) + (obj5 + (req "public_key_hash" Signature.Public_key_hash.encoding) + (opt "public_key" Signature.Public_key.encoding) + (req "amount" Tez.encoding) + (opt "delegate_to" Signature.Public_key_hash.encoding) + (opt "consensus_key" Signature.Public_key.encoding)) +end + +module Bootstrap_contract = struct + let encoding : Parameters.bootstrap_contract Data_encoding.t = + let open Data_encoding in + let open Parameters in + conv + (fun {delegate; amount; script; hash} -> (delegate, amount, script, hash)) + (fun (delegate, amount, script, hash) -> {delegate; amount; script; hash}) + (obj4 + (opt "delegate" Signature.Public_key_hash.encoding) + (req "amount" Tez.encoding) + (req "script" Script.encoding) + (opt "hash" Contract_hash.encoding)) +end + +module Protocol_parameters = struct + type t = { + initial_timestamp : Time.Protocol.t; + bootstrap_accounts : Parameters.bootstrap_account list; + bootstrap_contracts : Parameters.bootstrap_contract list; + constants : Constants.Parametric.t; + } + + let encoding : t Data_encoding.t = + let open Data_encoding in + conv + (fun p -> + ( p.initial_timestamp, + p.bootstrap_accounts, + p.bootstrap_contracts, + p.constants )) + (fun ( initial_timestamp, + bootstrap_accounts, + bootstrap_contracts, + constants ) -> + {initial_timestamp; bootstrap_accounts; bootstrap_contracts; constants}) + (obj4 + (req "initial_timestamp" Time.Protocol.encoding) + (req "bootstrap_accounts" (list Bootstrap_account.encoding)) + (req "bootstrap_contracts" (list Bootstrap_contract.encoding)) + (req "constants" Constants.Parametric.encoding)) + + let default_value : t = + let parameters = + Default_parameters.parameters_of_constants + Default_parameters.constants_sandbox + in + { + initial_timestamp = Time.Protocol.epoch; + bootstrap_accounts = parameters.bootstrap_accounts; + bootstrap_contracts = parameters.bootstrap_contracts; + constants = parameters.constants; + } +end + +(* This encoding extends [Protocol_constants_overrides.encoding] to allow + reading json files as produced by lib_parameters. *) +let lib_parameters_json_encoding = + Data_encoding.( + merge_objs + (obj2 + (opt "bootstrap_accounts" (list Parameters.bootstrap_account_encoding)) + (opt "commitments" (list Commitment.encoding))) + Protocol_constants_overrides.encoding) + +(* ------------------------------------------------------------------------- *) +(* Blocks *) + +type block = { + hash : Block_hash.t; + header : Block_header.t; + operations : Operation.packed list; + context : Environment.Context.t; +} + +module Forge = struct + let default_proof_of_work_nonce = + Bytes.create Constants.proof_of_work_nonce_size + + let make_shell ~level ~predecessor ~timestamp ~fitness ~operations_hash = + (* We initialize the [proto_level] at 1 in order to be able to + mimick a transition block in the baker. The baker distinguishes + the first block of a protocol by comparing a block and its + predecessor's proto level. If there is a difference, it must + mean that the block is a transition one. If we start at 0, we + cannot "hack" a transition block by decrementing the genesis + predecessor's protocol level because protocol levels are + encoded as uint8. *) + let proto_level = 1 in + Tezos_base.Block_header. + { + level; + predecessor; + timestamp; + fitness; + operations_hash; + proto_level; + validation_passes = 0; + context = Context_hash.zero; + } +end + +(* ------------------------------------------------------------------------- *) +(* RPC context *) +let genesis_block_hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + +let attestation_branch_data_encoding = + let open Data_encoding in + conv + (fun (block_hash, block_payload_hash) -> (block_hash, block_payload_hash)) + (fun (block_hash, block_payload_hash) -> (block_hash, block_payload_hash)) + (obj2 + (req "block_hash" Block_hash.encoding) + (req "block_payload_hash" Protocol.Block_payload_hash.encoding)) + +let initial_context chain_id (header : Block_header.shell_header) + ({bootstrap_accounts; bootstrap_contracts; constants; _} : + Protocol_parameters.t) = + let open Lwt_result_syntax in + let parameters = + Default_parameters.parameters_of_constants + ~bootstrap_accounts + ~bootstrap_contracts + ~commitments:[] + constants + in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + let*! ctxt = + Tezos_protocol_environment.Context.( + let empty = Tezos_protocol_environment.Memory_context.empty in + let*! ctxt = add empty ["version"] (Bytes.of_string "genesis") in + add ctxt ["protocol_parameters"] proto_params) + in + let*! ctxt = Environment.Updater.activate ctxt Protocol.hash in + let* {context; _} = + let*! r = Protocol.Main.init chain_id ctxt header in + Lwt.return (Environment.wrap_tzresult r) + in + let ({ + timestamp = predecessor_timestamp; + level = predecessor_level; + fitness = predecessor_fitness; + _; + } + : Block_header.shell_header) = + header + in + let timestamp = Time.System.to_protocol (Time.System.now ()) in + (* + + We need to forge a predecessor hash to pass it to [value_of_key]. + This initial context is used for RPC, hence this piece of + information is not important and does not have to be meaningful + + *) + let predecessor = + Tezos_base.Block_header.hash {shell = header; protocol_data = Bytes.empty} + in + let* value_of_key = + let*! r = + Protocol.Main.value_of_key + ~chain_id + ~predecessor_context:context + ~predecessor_timestamp + ~predecessor_level + ~predecessor_fitness + ~predecessor + ~timestamp + in + Lwt.return (Environment.wrap_tzresult r) + in + (* + In the mockup mode, reactivity is important and there are + no constraints to be consistent with other nodes. For this + reason, the mockup mode loads the cache lazily. + See {!Environment_context.source_of_cache}. + *) + let* context = + Tezos_protocol_environment.Context.load_cache + predecessor + context + `Lazy + (fun key -> + let*! r = value_of_key key in + Lwt.return (Environment.wrap_tzresult r)) + in + return context + +let mem_init : + cctxt:Tezos_client_base.Client_context.printer -> + parameters:Protocol_parameters.t -> + constants_overrides_json:Data_encoding.json option -> + bootstrap_accounts_json:Data_encoding.json option -> + Tezos_mockup_registration.Registration.mockup_context tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~cctxt ~parameters ~constants_overrides_json ~bootstrap_accounts_json -> + let hash = genesis_block_hash in + (* Need to read this Json file before since timestamp modification may be in + there *) + let override_protocol_parameters + (constants_overrides_json : Data_encoding.json option) + (parameters : Protocol_parameters.t) : + Protocol_constants_overrides.t tzresult Lwt.t = + (* [merge_objects v1 v2] recursively overrides [v1] with [v2], and + point-wise if [v1] and [v2] are objects. + + If [v1] and [v2] are objects, then the resulting value is an object where + - each field that is only present in either v1 and v2 is copied as is. + however, if the value in [v2] is explicitly [Some `Null], then the field is + absent in the result. + - if a field is present in both [v1] and [v2], then its value in the + result is merge recursively. *) + let rec merge_objects (v1 : Data_encoding.Json.t) + (v2 : Data_encoding.Json.t) : Data_encoding.Json.t = + match (v1, v2) with + | `O fs1, `O fs2 -> + let fields = + let tbl = String.Hashtbl.of_seq (List.to_seq fs1) in + List.iter + (fun (k2, v2) -> + match (String.Hashtbl.find_opt tbl k2, v2) with + | _, `Null -> String.Hashtbl.remove tbl k2 + | Some v1, v2 -> + String.Hashtbl.replace tbl k2 (merge_objects v1 v2) + | None, v2 -> String.Hashtbl.add tbl k2 v2) + fs2 ; + List.of_seq (String.Hashtbl.to_seq tbl) + in + `O fields + | _, v2 -> v2 + in + match constants_overrides_json with + | Some json -> + let parameters_json = + Data_encoding.Json.construct + Constants.Parametric.encoding + parameters.constants + in + let parameters_overriden = merge_objects parameters_json json in + let* protocol_overrides = + match + Data_encoding.Json.destruct + lib_parameters_json_encoding + parameters_overriden + with + | _, x -> return x + | exception error -> + failwith + "cannot read protocol constants overrides: %a" + (Data_encoding.Json.print_error ?print_unknown:None) + error + in + let fields_with_override = match json with `O fs -> fs | _ -> [] in + let field_pp ppf (name, value) = + Format.fprintf ppf "@[%s: %a@]" name Data_encoding.Json.pp value + in + let*! () = + if fields_with_override <> [] then + cctxt#message + "@[mockup client uses protocol overrides:@,%a@]@?" + (Format.pp_print_list field_pp) + fields_with_override + else Lwt.return_unit + in + return protocol_overrides + | None -> + return + Protocol_constants_overrides. + { + parametric = parameters.constants; + timestamp = None; + chain_id = None; + } + in + let* (protocol_overrides : Protocol_constants_overrides.t) = + override_protocol_parameters constants_overrides_json parameters + in + let chain_id = + Tezos_mockup_registration.Mockup_args.Chain_id.choose + ~from_config_file:protocol_overrides.chain_id + in + let default = parameters.initial_timestamp in + let timestamp = Option.value ~default protocol_overrides.timestamp in + let*! () = + if not @@ Time.Protocol.equal default timestamp then + cctxt#message + "@[initial_timestamp: %a@]" + Time.Protocol.pp_hum + timestamp + else Lwt.return_unit + in + let fitness = + Protocol.Alpha_context.( + Fitness.create_without_locked_round + ~level:Raw_level.root + ~predecessor_round:Round.zero + ~round:Round.zero + |> Fitness.to_raw) + in + let shell_header = + Forge.make_shell + ~level:0l + ~predecessor:hash + ~timestamp + ~fitness + ~operations_hash:Operation_list_list_hash.zero + in + let* bootstrap_accounts_custom = + match bootstrap_accounts_json with + | None -> return_none + | Some json -> ( + match + Data_encoding.Json.destruct + (Data_encoding.list Parsed_account.encoding) + json + with + | accounts -> + let*! () = + cctxt#message + "@[mockup client uses custom bootstrap accounts:@]" + in + let open Format in + let*! () = + cctxt#message + "@[%a@]" + (pp_print_list + ~pp_sep:(fun ppf () -> fprintf ppf ";@ ") + Parsed_account.pp) + accounts + in + let* bootstrap_accounts = + List.map_es Parsed_account.to_bootstrap_account accounts + in + return_some bootstrap_accounts + | exception error -> + failwith + "cannot read definitions of bootstrap accounts: %a" + (Data_encoding.Json.print_error ?print_unknown:None) + error) + in + let* context = + initial_context + chain_id + shell_header + { + parameters with + bootstrap_accounts = + Option.value + ~default:parameters.bootstrap_accounts + bootstrap_accounts_custom; + constants = protocol_overrides.parametric; + } + in + let protocol_data = + let payload_hash = + Protocol.Block_payload_hash.hash_bytes + [ + Block_hash.to_bytes hash; + Operation_list_hash.(to_bytes @@ compute []); + ] + in + let open Protocol.Alpha_context.Block_header in + let _, _, sk = Signature.generate_key () in + let proof_of_work_nonce = + Bytes.create Protocol.Alpha_context.Constants.proof_of_work_nonce_size + in + let contents = + { + payload_round = Round.zero; + payload_hash; + seed_nonce_hash = None; + proof_of_work_nonce; + (* following Baking_configuration.per_block_votes in lib_delegate *) + per_block_votes = + { + liquidity_baking_vote = Per_block_votes.Per_block_vote_pass; + adaptive_issuance_vote = Per_block_votes.Per_block_vote_pass; + }; + } + in + let unsigned_bytes = + Data_encoding.Binary.to_bytes_exn + Block_header.unsigned_encoding + (shell_header, contents) + in + let signature = + Signature.sign + ~watermark: + Protocol.Alpha_context.Block_header.( + to_watermark (Block_header chain_id)) + sk + unsigned_bytes + in + Data_encoding.Binary.to_bytes_exn + Protocol.block_header_data_encoding + {contents; signature} + in + return + Tezos_mockup_registration.Registration_intf. + { + chain = chain_id; + rpc_context = + Tezos_protocol_environment. + {block_hash = hash; block_header = shell_header; context}; + protocol_data; + } + +let migrate : + Tezos_mockup_registration.Registration.mockup_context -> + Tezos_mockup_registration.Registration.mockup_context tzresult Lwt.t = + let open Lwt_result_syntax in + fun {chain; rpc_context; protocol_data} -> + let Tezos_protocol_environment.{block_hash; context; block_header} = + rpc_context + in + let*! context = Environment.Updater.activate context Protocol.hash in + let* {context; _} = + let*! r = Protocol.Main.init chain context block_header in + Lwt.return (Environment.wrap_tzresult r) + in + let rpc_context = + Tezos_protocol_environment.{block_hash; block_header; context} + in + return + Tezos_mockup_registration.Registration_intf. + {chain; rpc_context; protocol_data} + +(* ------------------------------------------------------------------------- *) +(* Register mockup *) + +module M : + Tezos_mockup_registration.Registration_intf.MOCKUP + with module Protocol = Lifted_protocol = struct + type parameters = Protocol_parameters.t + + type protocol_constants = Protocol_constants_overrides.t + + let parameters_encoding = Protocol_parameters.encoding + + let default_parameters = Protocol_parameters.default_value + + let protocol_constants_encoding = Protocol_constants_overrides.encoding + + let default_protocol_constants = Protocol_constants_overrides.default_value + + let default_bootstrap_accounts = Parsed_account.default_to_json + + let protocol_hash = Protocol.hash + + module Protocol = Lifted_protocol + module Block_services = Protocol_client_context.Alpha_block_services + + let directory = Plugin.RPC.rpc_services + + let init ~cctxt ~parameters ~constants_overrides_json ~bootstrap_accounts_json + = + mem_init + ~cctxt:(cctxt :> Tezos_client_base.Client_context.printer) + ~parameters + ~constants_overrides_json + ~bootstrap_accounts_json + + let migrate = migrate +end + +let () = + Tezos_mockup_registration.Registration.register_mockup_environment (module M) diff --git a/src/proto_020_PsParisC/lib_client/operation_result.ml b/src/proto_020_PsParisC/lib_client/operation_result.ml new file mode 100644 index 000000000000..811bdc1fc4f4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/operation_result.ml @@ -0,0 +1,1143 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results +open Apply_operation_result +open Apply_internal_results + +let tez_sym = "\xEA\x9C\xA9" + +let pp_micheline_expr ppf expr = + Format.fprintf ppf "@[%a@]" Michelson_v1_printer.print_expr expr + +let pp_micheline_from_lazy_expr ppf expr = + let expr = + WithExceptions.Option.to_exn + ~none:(Failure "ill-serialized micheline expression") + (Data_encoding.force_decode expr) + in + pp_micheline_expr ppf expr + +let normalize_internal_operation cctxt unparsing_mode + (Internal_operation {operation; sender; nonce}) = + let open Lwt_result_syntax in + let normalize_op (type kind) : + kind internal_operation_contents -> + kind internal_operation_contents tzresult Lwt.t = function + | Event {ty; tag; payload} -> + let+ payload = + Plugin.RPC.Scripts.normalize_data + cctxt + (cctxt#chain, cctxt#block) + ~legacy:true + ~data:payload + ~ty + ~unparsing_mode + ~other_contracts:None + ~extra_big_maps:None + in + Event {ty; tag; payload} + | op -> return op + in + let+ operation = normalize_op operation in + Internal_operation {operation; sender; nonce} + +let pp_internal_operation ppf (Internal_operation {operation; sender; _}) = + (* For now, try to use the same format as in [pp_manager_operation_content]. *) + Format.fprintf ppf "@[Internal " ; + (match operation with + | Transaction {destination; amount; parameters; entrypoint} -> + Format.fprintf + ppf + "Transaction:@,Amount: %s%a@,From: %a@,To: %a" + tez_sym + Tez.pp + amount + Destination.pp + sender + Destination.pp + destination ; + if not (Entrypoint.is_default entrypoint) then + Format.fprintf ppf "@,Entrypoint: %a" Entrypoint.pp entrypoint ; + if not (Script_repr.is_unit_parameter parameters) then + Format.fprintf + ppf + "@,Parameter: %a" + pp_micheline_from_lazy_expr + parameters + | Origination {delegate; credit; script = {code; storage}} -> ( + Format.fprintf + ppf + "Origination:@,From: %a@,Credit: %s%a" + Destination.pp + sender + tez_sym + Tez.pp + credit ; + let code = + WithExceptions.Option.to_exn + ~none:(Failure "ill-serialized code") + (Data_encoding.force_decode code) + in + let {Michelson_v1_parser.source; _} = + Michelson_v1_printer.unparse_toplevel code + in + Format.fprintf + ppf + "@,@[Script:@ @[%a@]@,@[Initial storage:@ %a@]@]" + Format.pp_print_text + source + pp_micheline_from_lazy_expr + storage ; + match delegate with + | None -> Format.fprintf ppf "@,No delegate for this contract" + | Some delegate -> + Format.fprintf + ppf + "@,Delegate: %a" + Signature.Public_key_hash.pp + delegate) + | Delegation delegate_opt -> ( + Format.fprintf ppf "Delegation:@,Contract: %a@,To: " Destination.pp sender ; + match delegate_opt with + | None -> Format.pp_print_string ppf "nobody" + | Some delegate -> Signature.Public_key_hash.pp ppf delegate) + | Event {ty; tag; payload} -> + Format.fprintf + ppf + "Event:@,From: %a@,Type: %a" + Destination.pp + sender + pp_micheline_expr + ty ; + if not (Entrypoint.is_default tag) then + Format.fprintf ppf "@,Tag: %a" Entrypoint.pp tag ; + Format.fprintf ppf "@,Payload: %a" pp_micheline_expr payload) ; + Format.fprintf ppf "@]" + +let pp_manager_operation_content (type kind) source ppf + (operation : kind manager_operation) = + (* For now, try to keep formatting in sync with [pp_internal_operation]. *) + match operation with + | Transaction {destination; amount; parameters; entrypoint} -> + Format.fprintf + ppf + "Transaction:@,Amount: %s%a@,From: %a@,To: %a" + tez_sym + Tez.pp + amount + Contract.pp + source + Contract.pp + destination ; + if not (Entrypoint.is_default entrypoint) then + Format.fprintf ppf "@,Entrypoint: %a" Entrypoint.pp entrypoint ; + if not (Script_repr.is_unit_parameter parameters) then + Format.fprintf + ppf + "@,Parameter: %a" + pp_micheline_from_lazy_expr + parameters + | Origination {delegate; credit; script = {code; storage}} -> ( + Format.fprintf + ppf + "Origination:@,From: %a@,Credit: %s%a" + Contract.pp + source + tez_sym + Tez.pp + credit ; + let code = + WithExceptions.Option.to_exn + ~none:(Failure "ill-serialized code") + (Data_encoding.force_decode code) + in + let {Michelson_v1_parser.source; _} = + Michelson_v1_printer.unparse_toplevel code + in + Format.fprintf + ppf + "@,@[Script:@ @[%a@]@,@[Initial storage:@ %a@]" + Format.pp_print_text + source + pp_micheline_from_lazy_expr + storage ; + match delegate with + | None -> Format.fprintf ppf "@,No delegate for this contract" + | Some delegate -> + Format.fprintf + ppf + "@,Delegate: %a" + Signature.Public_key_hash.pp + delegate) + | Reveal key -> + Format.fprintf + ppf + "Revelation of manager public key:@,Contract: %a@,Key: %a" + Contract.pp + source + Signature.Public_key.pp + key + | Delegation delegate_opt -> ( + Format.fprintf ppf "Delegation:@,Contract: %a@,To: " Contract.pp source ; + match delegate_opt with + | None -> Format.pp_print_string ppf "nobody" + | Some delegate -> Signature.Public_key_hash.pp ppf delegate) + | Register_global_constant {value} -> + Format.fprintf + ppf + "Register Global:@,Value: %a" + pp_micheline_from_lazy_expr + value + | Set_deposits_limit limit_opt -> ( + Format.fprintf + ppf + "Set deposits limit:@,Delegate: %a@," + Contract.pp + source ; + match limit_opt with + | None -> Format.pp_print_string ppf "Unlimited deposits" + | Some limit -> Format.fprintf ppf "Limit: %a" Tez.pp limit) + | Increase_paid_storage {amount_in_bytes; destination} -> + Format.fprintf + ppf + "Increase paid storage:@,Increased size: %a bytes@,From: %a@,To: %a" + Z.pp_print + amount_in_bytes + Contract.pp + source + Contract_hash.pp + destination + | Update_consensus_key pk -> + Format.fprintf + ppf + "Update_consensus_key:@,Public key hash: %a" + Signature.Public_key_hash.pp + (Signature.Public_key.hash pk) + | Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint} -> + Format.fprintf + ppf + "Transfer tickets:@,\ + Ticket content: %a@,\ + Ticket content type: %a@,\ + Ticket ticketer: %a@,\ + Ticket amount: %a@,\ + Destination: %a%a@,\ + From: %a" + pp_micheline_from_lazy_expr + contents + pp_micheline_from_lazy_expr + ty + Contract.pp + ticketer + Z.pp_print + Script_int.(to_zint (amount :> n num)) + Contract.pp + destination + (fun ppf entrypoint -> + if not (Entrypoint.is_default entrypoint) then + Format.fprintf ppf "@,Entrypoint: %a" Entrypoint.pp entrypoint) + entrypoint + Contract.pp + source + | Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist} -> + Format.fprintf + ppf + "Smart rollup origination:@,\ + Kind: %a@,\ + Parameter type: %a@,\ + Kernel Blake2B hash: '%a'%a" + Sc_rollup.Kind.pp + kind + pp_micheline_from_lazy_expr + parameters_ty + Tezos_crypto.Blake2B.pp + (Tezos_crypto.Blake2B.hash_string [boot_sector]) + Format.( + pp_print_option (fun ppf -> + fprintf ppf "@,Whitelist: %a" Sc_rollup.Whitelist.pp)) + whitelist + | Sc_rollup_add_messages {messages = _} -> + Format.pp_print_string ppf "Smart rollup messages submission:" + | Sc_rollup_cement {rollup} -> + Format.fprintf + ppf + "Smart rollup commitment cementing:@,Address: %a" + Sc_rollup.Address.pp + rollup + | Sc_rollup_publish {rollup; commitment} -> + Format.fprintf + ppf + "Smart rollup commitment publishing:@,\ + Address: %a@,\ + @[Commitment:@,\ + %a@]" + Sc_rollup.Address.pp + rollup + Sc_rollup.Commitment.pp + commitment + | Sc_rollup_refute {rollup; opponent; refutation} -> + Format.fprintf + ppf + "Smart rollup refutation move:@,Address: %a@,Staker: %a@,Refutation: %a" + Sc_rollup.Address.pp + rollup + Sc_rollup.Staker.pp + opponent + Sc_rollup.Game.pp_refutation + refutation + | Sc_rollup_timeout {rollup; stakers = {alice; bob}} -> + Format.fprintf + ppf + "Smart rollup refutation timeout:@,\ + Address: %a@,\ + First staker (Alice): %a@,\ + Second staker (Bob): %a" + Sc_rollup.Address.pp + rollup + Sc_rollup.Staker.pp + alice + Sc_rollup.Staker.pp + bob + | Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof = _} -> + Format.fprintf + ppf + "Smart rollup output message execution:@,\ + Address: %a@,\ + Cemented commitment: %a" + Sc_rollup.Address.pp + rollup + Sc_rollup.Commitment.Hash.pp + cemented_commitment + | Sc_rollup_recover_bond {sc_rollup; staker} -> + Format.fprintf + ppf + "Smart rollup bond retrieval:@,Address: %a@,Staker: %a" + Sc_rollup.Address.pp + sc_rollup + Signature.Public_key_hash.pp + staker + | Dal_publish_commitment operation -> + Format.fprintf + ppf + "Data availability slot header publishing:@,Slot: %a" + Dal.Operations.Publish_commitment.pp + operation + | Zk_rollup_origination _ -> + Format.fprintf ppf "Epoxy origination:@,From: %a" Contract.pp source + | Zk_rollup_publish _ -> + Format.fprintf ppf "Epoxy publish:@,From: %a" Contract.pp source + | Zk_rollup_update _ -> + Format.fprintf ppf "Epoxy update:@,From: %a" Contract.pp source + +let pp_balance_updates ppf balance_updates = + let open Receipt in + (* For dry runs, the baker's key is zero + (tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU). Instead of printing this + key hash, we want to make the result more informative. *) + let pp_baker ppf baker = + if Signature.Public_key_hash.equal baker Signature.Public_key_hash.zero then + Format.fprintf ppf "the baker who will include this operation" + else Signature.Public_key_hash.pp ppf baker + in + let pp_unstaked_frozen_staker ppf (staker : Receipt.unstaked_frozen_staker) = + match staker with + | Single (contract, delegate) -> + Format.fprintf + ppf + "%a delegated to %a" + Contract.pp + contract + pp_baker + delegate + | Shared delegate -> + Format.fprintf ppf "shared between delegators of %a" pp_baker delegate + in + let pp_frozen_staker ppf (staker : Receipt.frozen_staker) = + match staker with + | Baker baker -> pp_baker ppf baker + | Baker_edge baker -> + Format.fprintf ppf "baker edge %a" Signature.Public_key_hash.pp baker + | Single_staker {staker; delegate} -> + Format.fprintf + ppf + "%a delegated to %a" + Contract.pp + staker + pp_baker + delegate + | Shared_between_stakers {delegate} -> + Format.fprintf ppf "shared between delegators of %a" pp_baker delegate + in + let pp_update token ppf = function + | Credited amount -> Format.fprintf ppf "+%a" (Token.pp token) amount + | Debited amount -> Format.fprintf ppf "-%a" (Token.pp token) amount + in + let balance_updates = + List.map + (fun (Balance_update_item (balance, update, origin)) -> + let token = token_of_balance balance in + let balance = + match balance with + | Contract c -> Format.asprintf "%a" Contract.pp c + | Block_fees -> "payload fees(the block proposer)" + | Deposits staker -> + Format.asprintf "deposits(%a)" pp_frozen_staker staker + | Unstaked_deposits (staker, cycle) -> + Format.asprintf + "unstaked_deposits(%a,%a)" + pp_unstaked_frozen_staker + staker + Cycle.pp + cycle + | Nonce_revelation_rewards -> "nonce revelation rewards" + | Attesting_rewards -> "attesting rewards" + | Baking_rewards -> "baking rewards" + | Baking_bonuses -> "baking bonuses" + | Storage_fees -> "storage fees" + | Double_signing_punishments -> "double signing punishments" + | Lost_attesting_rewards (pkh, p, r) -> + let reason = + match (p, r) with + | false, false -> "" + | false, true -> ",revelation" + | true, false -> ",participation" + | true, true -> ",participation,revelation" + in + Format.asprintf "lost attesting rewards(%a%s)" pp_baker pkh reason + | Liquidity_baking_subsidies -> "liquidity baking subsidies" + | Burned -> "burned" + | Commitments bpkh -> + Format.asprintf "commitment(%a)" Blinded_public_key_hash.pp bpkh + | Bootstrap -> "bootstrap" + | Invoice -> "invoices" + | Initial_commitments -> "initial commitments" + | Minted -> "minted" + | Frozen_bonds (contract, bond_id) -> + Format.asprintf + "Frozen_bonds(%a,%a)" + Contract.pp + contract + Bond_id.pp + bond_id + | Sc_rollup_refutation_punishments -> + "smart rollup refutation punishments" + | Sc_rollup_refutation_rewards -> "smart rollup refutation rewards" + | Staking_delegator_numerator {delegator} -> + Format.asprintf + "staking delegator numerator(%a)" + Contract.pp + delegator + | Staking_delegate_denominator {delegate} -> + Format.asprintf + "staking delegate denominator(%a)" + Signature.Public_key_hash.pp + delegate + in + let balance = + match origin with + | Block_application -> balance + | Protocol_migration -> Format.asprintf "migration %s" balance + | Subsidy -> Format.asprintf "subsidy %s" balance + | Simulation -> Format.asprintf "simulation %s" balance + | Delayed_operation {operation_hash} -> + Format.asprintf + "delayed operation(%a) %s" + Operation_hash.pp + operation_hash + balance + in + let update = Format.asprintf "%a" (pp_update token) update in + (balance, update)) + balance_updates + in + let column_size = + List.fold_left + (fun acc (balance, _) -> Compare.Int.max acc (String.length balance)) + 0 + balance_updates + in + let pp_one ppf (balance, update) = + let to_fill = column_size + 3 - String.length balance in + let filler = String.make to_fill '.' in + Format.fprintf ppf "%s %s %s" balance filler update + in + match balance_updates with + | [] -> () + | balance_updates -> + Format.fprintf + ppf + "@,@[Balance updates:@,%a@]" + (Format.pp_print_list pp_one) + balance_updates + +let pp_ticket_receipt ppf ticket_receipt = + let open Ticket_receipt in + let pp_amount ppf amount = + Format.fprintf + ppf + "%s%a" + (if Z.(zero < amount) then "+" else "") + Z.pp_print + amount + in + let pp_account_update ppf {account; amount} = + Format.fprintf ppf "%a ... %a" Destination.pp account pp_amount amount + in + let pp_account_updates ppf updates = + Format.fprintf + ppf + "@[Account updates:@,%a@]" + (Format.pp_print_list pp_account_update) + updates + in + let pp_item ppf {ticket_token; updates} = + let Ticket_token.{ticketer; contents_type; contents} = ticket_token in + Format.fprintf + ppf + "Ticketer: %a@,Content type: %a@,Content: %a@,%a" + Contract.pp + ticketer + Michelson_v1_printer.print_expr + contents_type + Michelson_v1_printer.print_expr + contents + pp_account_updates + updates + in + match ticket_receipt with + | [] -> () + | ticket_updates -> + Format.fprintf + ppf + "@,@[Ticket updates:@,%a@]" + (Format.pp_print_list pp_item) + ticket_updates + +let pp_whitelist_update ppf whitelist_update = + let open Format in + fprintf + ppf + "@,%a" + Sc_rollup.Whitelist.( + fun ppf -> function + | Public -> pp_print_string ppf "Rollup is now public" + | Private whitelist -> fprintf ppf "New whitelist: %a" pp whitelist) + whitelist_update + +let pp_slot_header ppf slot_header = + Format.fprintf ppf "@,@[%a@]" Dal.Slot.Header.pp slot_header + +let pp_consumed_gas ppf consumed_gas = + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas + +let pp_paid_storage_size_diff ppf paid_storage_size_diff = + if paid_storage_size_diff <> Z.zero then + Format.fprintf + ppf + "@,Paid storage size diff: %s bytes" + (Z.to_string paid_storage_size_diff) + +let pp_storage_size ppf storage_size = + if storage_size <> Z.zero then + Format.fprintf ppf "@,Storage size: %s bytes" (Z.to_string storage_size) + +let pp_lazy_storage_diff ppf = function + | None -> () + | Some lazy_storage_diff -> ( + let big_map_diff = + Contract.Legacy_big_map_diff.of_lazy_storage_diff lazy_storage_diff + in + match (big_map_diff :> Contract.Legacy_big_map_diff.item list) with + | [] -> () + | _ :: _ -> + (* TODO: print all lazy storage diff *) + Format.fprintf + ppf + "@,@[Updated big_maps:@ %a@]" + Michelson_v1_printer.print_big_map_diff + lazy_storage_diff) + +let pp_origination_result ppf + { + lazy_storage_diff; + balance_updates; + consumed_gas; + originated_contracts; + storage_size; + paid_storage_size_diff; + } = + (match originated_contracts with + | [] -> () + | contracts -> + Format.fprintf + ppf + "@,@[Originated contracts:@,%a@]" + (Format.pp_print_list Contract_hash.pp) + contracts) ; + pp_storage_size ppf storage_size ; + pp_lazy_storage_diff ppf lazy_storage_diff ; + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates + +let pp_transaction_result ppf = function + | Transaction_to_contract_result + { + balance_updates; + ticket_receipt; + consumed_gas; + storage; + originated_contracts; + storage_size; + paid_storage_size_diff; + lazy_storage_diff; + allocated_destination_contract = _; + } -> + (match originated_contracts with + | [] -> () + | contracts -> + Format.fprintf + ppf + "@,@[Originated contracts:@,%a@]" + (Format.pp_print_list Contract_hash.pp) + contracts) ; + (match storage with + | None -> () + | Some expr -> + Format.fprintf + ppf + "@,@[Updated storage:@ %a@]" + Michelson_v1_printer.print_expr + expr) ; + pp_lazy_storage_diff ppf lazy_storage_diff ; + pp_storage_size ppf storage_size ; + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates ; + pp_ticket_receipt ppf ticket_receipt + | Transaction_to_sc_rollup_result {consumed_gas; ticket_receipt} -> + pp_consumed_gas ppf consumed_gas ; + pp_ticket_receipt ppf ticket_receipt + | Transaction_to_zk_rollup_result + {balance_updates; consumed_gas; ticket_hash; paid_storage_size_diff} -> + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates ; + Format.fprintf ppf "@,Ticket hash: %a" Ticket_hash.pp ticket_hash ; + pp_paid_storage_size_diff ppf paid_storage_size_diff + +let pp_operation_result ~operation_name pp_operation_result ppf = function + | Skipped _ -> Format.fprintf ppf "This operation was skipped." + | Failed (_, _errs) -> Format.fprintf ppf "This operation FAILED." + | Applied op_res -> + Format.fprintf + ppf + "This %s was successfully applied" + (operation_name op_res) ; + pp_operation_result ppf op_res + | Backtracked (op_res, _errs) -> + Format.fprintf + ppf + "This %s was BACKTRACKED, its expected effects were NOT applied." + (operation_name op_res) ; + pp_operation_result ppf op_res + +let pp_manager_operation_contents_result ppf op_result = + let pp_register_global_constant_result + (Register_global_constant_result + {balance_updates; consumed_gas; size_of_constant; global_address}) = + (match balance_updates with + | [] -> + (* Not possible - register global constant operation always returns + balance updates. *) + assert false + | balance_updates -> pp_balance_updates ppf balance_updates) ; + pp_consumed_gas ppf consumed_gas ; + pp_storage_size ppf size_of_constant ; + Format.fprintf ppf "@,Global address: %a" Script_expr_hash.pp global_address + in + let pp_increase_paid_storage_result + (Increase_paid_storage_result {consumed_gas; balance_updates}) = + pp_balance_updates ppf balance_updates ; + pp_consumed_gas ppf consumed_gas + in + let pp_transfer_ticket_result + (Transfer_ticket_result + {balance_updates; ticket_receipt; consumed_gas; paid_storage_size_diff}) + = + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_ticket_receipt ppf ticket_receipt ; + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates + in + let pp_dal_publish_commitment_result + (Dal_publish_commitment_result {slot_header; consumed_gas}) = + pp_slot_header ppf slot_header ; + pp_consumed_gas ppf consumed_gas + in + let pp_sc_rollup_originate_result + (Sc_rollup_originate_result + {address; genesis_commitment_hash; consumed_gas; size; balance_updates}) + = + pp_consumed_gas ppf consumed_gas ; + pp_storage_size ppf size ; + Format.fprintf ppf "@,Address: %a" Sc_rollup.Address.pp address ; + Format.fprintf + ppf + "@,Genesis commitment hash: %a" + Sc_rollup.Commitment.Hash.pp + genesis_commitment_hash ; + pp_balance_updates ppf balance_updates + in + let pp_sc_rollup_add_messages_result + (Sc_rollup_add_messages_result {consumed_gas}) = + pp_consumed_gas ppf consumed_gas + in + let pp_sc_rollup_cement_result + (Sc_rollup_cement_result {consumed_gas; inbox_level; commitment_hash}) = + pp_consumed_gas ppf consumed_gas ; + Format.fprintf + ppf + "@,Inbox level: %a@,Commitment hash: %a" + Raw_level.pp + inbox_level + Sc_rollup.Commitment.Hash.pp + commitment_hash + in + let pp_sc_rollup_publish_result + (Sc_rollup_publish_result + {consumed_gas; staked_hash; published_at_level; balance_updates}) = + pp_consumed_gas ppf consumed_gas ; + Format.fprintf + ppf + "@,Hash of commit: %a" + Sc_rollup.Commitment.Hash.pp + staked_hash ; + Format.fprintf + ppf + "@,Commitment published at level: %a" + Raw_level.pp + published_at_level ; + pp_balance_updates ppf balance_updates + in + let pp_sc_rollup_refute_result + (Sc_rollup_refute_result {consumed_gas; game_status; balance_updates}) = + pp_consumed_gas ppf consumed_gas ; + Format.fprintf + ppf + "@,Refutation game status: %a" + Sc_rollup.Game.pp_status + game_status ; + pp_balance_updates ppf balance_updates + in + let pp_sc_rollup_timeout_result + (Sc_rollup_timeout_result {consumed_gas; game_status; balance_updates}) = + pp_consumed_gas ppf consumed_gas ; + Format.fprintf + ppf + "@,Refutation game status: %a" + Sc_rollup.Game.pp_status + game_status ; + pp_balance_updates ppf balance_updates + in + let pp_sc_rollup_execute_outbox_message_result + (Sc_rollup_execute_outbox_message_result + { + balance_updates; + ticket_receipt; + whitelist_update; + consumed_gas; + paid_storage_size_diff; + }) = + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates ; + pp_ticket_receipt ppf ticket_receipt ; + Format.pp_print_option pp_whitelist_update ppf whitelist_update + in + let pp_sc_rollup_recover_bond_result + (Sc_rollup_recover_bond_result {balance_updates; consumed_gas}) = + pp_balance_updates ppf balance_updates ; + pp_consumed_gas ppf consumed_gas + in + let pp_zk_rollup_origination_result + (Zk_rollup_origination_result + {consumed_gas; originated_zk_rollup; storage_size; balance_updates}) = + pp_consumed_gas ppf consumed_gas ; + pp_storage_size ppf storage_size ; + Format.fprintf ppf "@,Address: %a" Zk_rollup.Address.pp originated_zk_rollup ; + pp_balance_updates ppf balance_updates + in + let pp_zk_rollup_publish_result + (Zk_rollup_publish_result + {balance_updates; consumed_gas; paid_storage_size_diff}) = + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates + in + let pp_zk_rollup_update_result + (Zk_rollup_update_result + {balance_updates; consumed_gas; paid_storage_size_diff}) = + pp_consumed_gas ppf consumed_gas ; + pp_paid_storage_size_diff ppf paid_storage_size_diff ; + pp_balance_updates ppf balance_updates + in + + let manager_operation_name (type kind) + (result : kind successful_manager_operation_result) = + match result with + | Reveal_result _ -> "revelation" + | Transaction_result _ -> "transaction" + | Origination_result _ -> "origination" + | Delegation_result _ -> "delegation" + | Register_global_constant_result _ -> "global constant registration" + | Set_deposits_limit_result _ -> "deposits limit modification" + | Update_consensus_key_result _ -> "consensus key update" + | Increase_paid_storage_result _ -> "paid storage increase" + | Transfer_ticket_result _ -> "tickets transfer" + | Sc_rollup_originate_result _ -> "smart rollup origination" + | Sc_rollup_add_messages_result _ -> "smart rollup messages submission" + | Sc_rollup_cement_result _ -> "smart rollup commitment cementing" + | Sc_rollup_publish_result _ -> "smart rollup commitment publishing" + | Sc_rollup_refute_result _ -> "smart rollup refutation move" + | Sc_rollup_timeout_result _ -> "smart rollup refutation timeout" + | Sc_rollup_execute_outbox_message_result _ -> + "smart output message execution" + | Sc_rollup_recover_bond_result _ -> "smart rollup bond retrieval" + | Dal_publish_commitment_result _ -> + "data availability slot header publishing" + | Zk_rollup_origination_result _ -> "epoxy originate" + | Zk_rollup_publish_result _ -> "epoxy publish" + | Zk_rollup_update_result _ -> "epoxy update" + in + let pp_manager_operation_contents_result (type kind) ppf + (result : kind successful_manager_operation_result) = + match result with + | Reveal_result {consumed_gas} -> pp_consumed_gas ppf consumed_gas + | Delegation_result {consumed_gas; balance_updates} -> + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates + | Set_deposits_limit_result {consumed_gas} -> + pp_consumed_gas ppf consumed_gas + | Update_consensus_key_result {consumed_gas} -> + pp_consumed_gas ppf consumed_gas + | Transaction_result tx -> pp_transaction_result ppf tx + | Origination_result op_res -> pp_origination_result ppf op_res + | Register_global_constant_result _ as op -> + pp_register_global_constant_result op + | Increase_paid_storage_result _ as op -> pp_increase_paid_storage_result op + | Transfer_ticket_result _ as op -> pp_transfer_ticket_result op + | Sc_rollup_originate_result _ as op -> pp_sc_rollup_originate_result op + | Sc_rollup_add_messages_result _ as op -> + pp_sc_rollup_add_messages_result op + | Sc_rollup_cement_result _ as op -> pp_sc_rollup_cement_result op + | Sc_rollup_publish_result _ as op -> pp_sc_rollup_publish_result op + | Sc_rollup_refute_result _ as op -> pp_sc_rollup_refute_result op + | Sc_rollup_timeout_result _ as op -> pp_sc_rollup_timeout_result op + | Sc_rollup_execute_outbox_message_result _ as op -> + pp_sc_rollup_execute_outbox_message_result op + | Sc_rollup_recover_bond_result _ as op -> + pp_sc_rollup_recover_bond_result op + | Dal_publish_commitment_result _ as op -> + pp_dal_publish_commitment_result op + | Zk_rollup_origination_result _ as op -> pp_zk_rollup_origination_result op + | Zk_rollup_publish_result _ as op -> pp_zk_rollup_publish_result op + | Zk_rollup_update_result _ as op -> pp_zk_rollup_update_result op + in + pp_operation_result + ~operation_name:manager_operation_name + pp_manager_operation_contents_result + ppf + op_result + +let pp_internal_operation_and_result ppf (Internal_operation_result (op, res)) = + let internal_operation_name (type kind) : + kind successful_internal_operation_result -> string = function + | ITransaction_result _ -> "transaction" + | IOrigination_result _ -> "origination" + | IDelegation_result _ -> "delegation" + | IEvent_result _ -> "event" + in + let pp_internal_operation_result (type kind) ppf + (result : kind successful_internal_operation_result) = + match result with + | ITransaction_result tx -> pp_transaction_result ppf tx + | IOrigination_result op_res -> pp_origination_result ppf op_res + | IDelegation_result {consumed_gas; balance_updates} -> + pp_consumed_gas ppf consumed_gas ; + pp_balance_updates ppf balance_updates + | IEvent_result {consumed_gas} -> pp_consumed_gas ppf consumed_gas + in + Format.fprintf + ppf + "@[%a@,%a@]" + pp_internal_operation + (Internal_operation op) + (pp_operation_result + ~operation_name:internal_operation_name + pp_internal_operation_result) + res + +let pp_internal_operation_results_list ppf = function + | [] -> () + | _ :: _ as internal_operation_results -> + Format.fprintf + ppf + "@,@[Internal operations:@,%a@]" + (Format.pp_print_list pp_internal_operation_and_result) + internal_operation_results + +let pp_manager_operation_result ppf + ( Manager_operation + {source; fee; operation; counter; gas_limit; storage_limit}, + Manager_operation_result + {balance_updates; operation_result; internal_operation_results} ) = + Format.fprintf ppf "@[Manager signed operations:" ; + Format.fprintf ppf "@,From: %a" Signature.Public_key_hash.pp source ; + Format.fprintf ppf "@,Fee to the baker: %s%a" tez_sym Tez.pp fee ; + Format.fprintf ppf "@,Expected counter: %a" Manager_counter.pp counter ; + Format.fprintf ppf "@,Gas limit: %a" Gas.Arith.pp_integral gas_limit ; + Format.fprintf ppf "@,Storage limit: %a bytes" Z.pp_print storage_limit ; + pp_balance_updates ppf balance_updates ; + Format.fprintf + ppf + "@,@[%a@,%a%a@]" + (pp_manager_operation_content (Contract.Implicit source)) + operation + pp_manager_operation_contents_result + operation_result + pp_internal_operation_results_list + internal_operation_results ; + Format.fprintf ppf "@]" + +let pp_contents_and_result : + type kind. Format.formatter -> kind contents * kind contents_result -> unit + = + let pp_forbidden ppf forbidden = + match forbidden with + | None -> () + | Some forbidden_delegate -> + Format.fprintf + ppf + " Forbidden delegate: %a@," + Signature.Public_key_hash.pp + forbidden_delegate + in + fun ppf -> function + | Seed_nonce_revelation {level; nonce}, Seed_nonce_revelation_result bus -> + Format.fprintf + ppf + "@[Seed nonce revelation:@,\ + Level: %a@,\ + Nonce (hash): %a@,\ + Balance updates:@,\ + %a@]" + Raw_level.pp + level + Nonce_hash.pp + (Nonce.hash nonce) + pp_balance_updates + bus + | Vdf_revelation {solution}, Vdf_revelation_result bus -> + Format.fprintf + ppf + "@[Vdf revelation:@,Solution: %a@,Balance updates:@,%a@]" + Seed.pp_solution + solution + pp_balance_updates + bus + | ( Double_baking_evidence {bh1; bh2}, + Double_baking_evidence_result {forbidden_delegate; balance_updates} ) -> + Format.fprintf + ppf + "@[Double baking evidence:@,\ + Exhibit A: %a@,\ + Exhibit B: %a@,\ + %aBalance updates:@,\ + %a@]" + Block_hash.pp + (Block_header.hash bh1) + Block_hash.pp + (Block_header.hash bh2) + pp_forbidden + forbidden_delegate + pp_balance_updates + balance_updates + | ( Preattestation {level; _}, + Preattestation_result + {balance_updates; delegate; consensus_key; consensus_power} ) -> + Format.fprintf + ppf + "@[Preattestation:@,\ + Level: %a@,\ + Balance updates:%a@,\ + Delegate: %a@,\ + Consensus Power: %d@]" + Raw_level.pp + level + pp_balance_updates + balance_updates + Consensus_key.pp + {delegate; consensus_pkh = consensus_key} + consensus_power + | ( Attestation {consensus_content = {level; _}; dal_content = _}, + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} ) -> + Format.fprintf + ppf + "@[Attestation:@,\ + Level: %a@,\ + Balance updates:%a@,\ + Delegate: %a@,\ + Consensus Power: %d@]" + Raw_level.pp + level + pp_balance_updates + balance_updates + Consensus_key.pp + {delegate; consensus_pkh = consensus_key} + consensus_power + | ( Double_attestation_evidence {op1; op2}, + Double_attestation_evidence_result {forbidden_delegate; balance_updates} + ) -> + Format.fprintf + ppf + "@[Double attestation evidence:@,\ + Exhibit A: %a@,\ + Exhibit B: %a@,\ + %aBalance updates:@,\ + \ %a@]" + Operation_hash.pp + (Operation.hash op1) + Operation_hash.pp + (Operation.hash op2) + pp_forbidden + forbidden_delegate + pp_balance_updates + balance_updates + | ( Double_preattestation_evidence {op1; op2}, + Double_preattestation_evidence_result + {forbidden_delegate; balance_updates} ) -> + Format.fprintf + ppf + "@[Double preattestation evidence:@,\ + Exhibit A: %a@,\ + Exhibit B: %a@,\ + %aBalance updates:@,\ + \ %a@]" + Operation_hash.pp + (Operation.hash op1) + Operation_hash.pp + (Operation.hash op2) + pp_forbidden + forbidden_delegate + pp_balance_updates + balance_updates + | Activate_account {id; _}, Activate_account_result bus -> + Format.fprintf + ppf + "@[Genesis account activation:@,\ + Account: %a@,\ + Balance updates:@,\ + \ %a@]" + Signature.Ed25519.Public_key_hash.pp + id + pp_balance_updates + bus + | Proposals {source; period; proposals}, Proposals_result -> + Format.fprintf + ppf + "@[Proposals:@,\ + From: %a@,\ + Period: %ld@,\ + Protocols:@,\ + \ @[%a@]@]" + Signature.Public_key_hash.pp + source + period + (Format.pp_print_list Protocol_hash.pp) + proposals + | Ballot {source; period; proposal; ballot}, Ballot_result -> + Format.fprintf + ppf + "@[Ballot:@,From: %a@,Period: %ld@,Protocol: %a@,Vote: %a@]" + Signature.Public_key_hash.pp + source + period + Protocol_hash.pp + proposal + Data_encoding.Json.pp + (Data_encoding.Json.construct Vote.ballot_encoding ballot) + | ( Drain_delegate {consensus_key; delegate; destination}, + Drain_delegate_result {balance_updates; allocated_destination_contract} + ) -> + Format.fprintf + ppf + "@[Drain delegate:@,\ + Consensus key hash: %a@,\ + Delegate: %a@,\ + Destination: %a%s%a@]" + Signature.Public_key_hash.pp + consensus_key + Signature.Public_key_hash.pp + delegate + Signature.Public_key_hash.pp + destination + (if allocated_destination_contract then " (allocated)" else "") + pp_balance_updates + balance_updates + | Failing_noop _arbitrary, _ -> + (* the Failing_noop operation always fails and can't have result *) + . + | (Manager_operation _ as op), (Manager_operation_result _ as res) -> + pp_manager_operation_result ppf (op, res) + +let rec pp_contents_and_result_list : + type kind. Format.formatter -> kind contents_and_result_list -> unit = + fun ppf -> function + | Single_and_result (op, res) -> pp_contents_and_result ppf (op, res) + | Cons_and_result + ((Manager_operation _ as op), (Manager_operation_result _ as res), rest) + -> + Format.fprintf + ppf + "%a@,%a" + pp_manager_operation_result + (op, res) + pp_contents_and_result_list + rest + +let pp_operation_result ppf + ((op, res) : 'kind contents_list * 'kind contents_result_list) = + let contents_and_result_list = Apply_results.pack_contents_list op res in + Format.fprintf + ppf + "@[%a@]@." + pp_contents_and_result_list + contents_and_result_list diff --git a/src/proto_020_PsParisC/lib_client/operation_result.mli b/src/proto_020_PsParisC/lib_client/operation_result.mli new file mode 100644 index 000000000000..aed12835b740 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/operation_result.mli @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +val tez_sym : string + +val normalize_internal_operation : + Protocol_client_context.full -> + Script_ir_unparser.unparsing_mode -> + Apply_internal_results.packed_internal_operation -> + Apply_internal_results.packed_internal_operation tzresult Lwt.t + +val pp_internal_operation : + Format.formatter -> Apply_internal_results.packed_internal_operation -> unit + +val pp_operation_result : + Format.formatter -> + 'kind contents_list * 'kind Apply_results.contents_result_list -> + unit diff --git a/src/proto_020_PsParisC/lib_client/protocol_client_context.ml b/src/proto_020_PsParisC/lib_client/protocol_client_context.ml new file mode 100644 index 000000000000..a69a908b37e5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/protocol_client_context.ml @@ -0,0 +1,337 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Alpha_block_services = + Block_services.Make (Lifted_protocol) (Lifted_protocol) + +(** Client RPC context *) +class type rpc_context = + object + inherit Tezos_rpc.Context.generic + + inherit + [Shell_services.chain * Shell_services.block] Environment.RPC_context + .simple + end + +(** The class [wrap_rpc_context] is a wrapper class used by the proxy + mode clients. From a general-purpose Tezos_rpc.Context.generic [t], the + class is augmented with shell services to provide RPC calls that + are protocol-dependent. *) +class wrap_rpc_context (t : Tezos_rpc.Context.generic) : rpc_context = + object + method base : Uri.t = t#base + + method generic_media_type_call = t#generic_media_type_call + + method call_service + : 'm 'p 'q 'i 'o. + (([< Resto.meth] as 'm), unit, 'p, 'q, 'i, 'o) Tezos_rpc.Service.t -> + 'p -> + 'q -> + 'i -> + 'o tzresult Lwt.t = + t#call_service + + method call_streamed_service + : 'm 'p 'q 'i 'o. + (([< Resto.meth] as 'm), unit, 'p, 'q, 'i, 'o) Tezos_rpc.Service.t -> + on_chunk:('o -> unit) -> + on_close:(unit -> unit) -> + 'p -> + 'q -> + 'i -> + (unit -> unit) tzresult Lwt.t = + t#call_streamed_service + + (** Abstracts variables and in protocol RPCs + prefixed by "/chains//blocks//...". *) + inherit + [Shell_services.chain, Shell_services.block] Environment.proto_rpc_context + (t :> Tezos_rpc.Context.t) + Shell_services.Blocks.path + end + +(** The class type [full] allows to create contexts that are + explicitly used by low-level shell functions, while containing + various information (I/O services, RPCs...). Then, depending on the + usage, the type may be coerced into one of its following ascendants + to serve for explicit operations on blocks, chain or daemon for + instance. *) +class type full = + object + (** The class Client_context.full provides I/O services for the + client, the wallet, etc. *) + inherit Client_context.full + + (** Base interface provided to call RPCs, i.e., communication + with the node. A client context is defined by mapping all + RPCs protocol-generic to a specific protocol. *) + inherit + [Shell_services.chain * Shell_services.block] Environment.RPC_context + .simple + + (** Protocol RPCs exposed through the environment (using + an additional chainpath). *) + inherit + [Shell_services.chain, Shell_services.block] Environment.proto_rpc_context + end + +(** From a [Client_context.full], the class allows to call RPCs from + the node and those defined by the protocol. *) +class wrap_full (t : Client_context.full) : full = + object + inherit Client_context.proxy_context t + + inherit + [Shell_services.chain, Shell_services.block] Environment.proto_rpc_context + (t :> Tezos_rpc.Context.t) + Shell_services.Blocks.path + end + +let register_error_kind category ~id ~title ~description ?pp encoding from_error + to_error = + let id = "client." ^ Protocol.name ^ "." ^ id in + register_error_kind + category + ~id + ~title + ~description + ?pp + encoding + from_error + to_error + +(** Initialization calls that run on start-up. Register the various + protocol encodings. *) +let () = + let open Data_encoding.Registration in + register Protocol.Alpha_context.Lazy_storage.encoding ; + register ~pp:Protocol.Alpha_context.Fitness.pp + @@ Protocol.Alpha_context.Fitness.encoding ; + (* These encodings are missing a def field which we add before registering them. + These defs should be moved inside their encodings in the protocol code. *) + let def id ids ?title ?description encoding = + Data_encoding.def + (String.concat "." (Protocol.name :: id :: ids)) + ?title + ?description + encoding + in + register @@ def "parameters" [] Protocol.Parameters_repr.encoding ; + register ~pp:Protocol.Alpha_context.Tez.pp + @@ def "tez" [] Protocol.Alpha_context.Tez.encoding ; + register ~pp:Protocol.Alpha_context.Timestamp.pp + @@ def "timestamp" [] Protocol.Alpha_context.Timestamp.encoding ; + register ~pp:Protocol.Alpha_context.Raw_level.pp + @@ def "raw_level" [] Protocol.Alpha_context.Raw_level.encoding ; + register @@ def "vote" ["ballot"] Protocol.Alpha_context.Vote.ballot_encoding ; + register + @@ def "vote" ["ballots"] Protocol.Alpha_context.Vote.ballots_encoding ; + register + @@ def "vote" ["listings"] Protocol.Alpha_context.Vote.listings_encoding ; + register @@ def "seed" [] Protocol.Alpha_context.Seed.seed_encoding ; + register ~pp:Protocol.Alpha_context.Gas.pp + @@ def "gas" [] Protocol.Alpha_context.Gas.encoding ; + register ~pp:Protocol.Alpha_context.Gas.pp_cost + @@ def "gas" ["cost"] Protocol.Alpha_context.Gas.cost_encoding ; + register @@ def "script" [] Protocol.Alpha_context.Script.encoding ; + register @@ def "script" ["expr"] Protocol.Alpha_context.Script.expr_encoding ; + register @@ def "script" ["prim"] Protocol.Alpha_context.Script.prim_encoding ; + register + @@ def "script" ["lazy_expr"] Protocol.Alpha_context.Script.lazy_expr_encoding ; + register + @@ def "script" ["loc"] Protocol.Alpha_context.Script.location_encoding ; + register ~pp:Protocol.Alpha_context.Contract.pp + @@ def "contract" [] Protocol.Alpha_context.Contract.encoding ; + register + @@ def + "unstaked_frozen_staker" + [] + Protocol.Unstaked_frozen_staker_repr.encoding ; + register @@ def "frozen_staker" [] Protocol.Frozen_staker_repr.encoding ; + register + @@ def + "receipt" + ["balance_updates"] + Protocol.Alpha_context.Receipt.balance_updates_encoding ; + register ~pp:Protocol.Alpha_context.Level.pp_full + @@ def "level" [] Protocol.Alpha_context.Level.encoding ; + register @@ def "operation" [] Protocol.Alpha_context.Operation.encoding ; + (* https://gitlab.com/tezos/tezos/-/issues/5528 + We register legacy encoding, but only during the transition period until + the endorsement kind will be completely removed. *) + register + @@ def + "operation_with_legacy_attestation_name" + [] + Protocol.Alpha_context.Operation.encoding_with_legacy_attestation_name ; + register + @@ def + "operation" + ["contents"] + Protocol.Alpha_context.Operation.contents_encoding ; + register + @@ def + "operation" + ["contents_list"] + Protocol.Alpha_context.Operation.contents_list_encoding ; + register + @@ def + "operation" + ["protocol_data"] + Protocol.Alpha_context.Operation.protocol_data_encoding ; + register + @@ def "operation" ["raw"] Protocol.Alpha_context.Operation.raw_encoding ; + register + @@ def + "operation" + ["internal"] + Protocol.Apply_internal_results.internal_operation_encoding ; + register + @@ def + "operation" + ["unsigned"] + Protocol.Alpha_context.Operation.unsigned_encoding ; + (* https://gitlab.com/tezos/tezos/-/issues/5528 + We register legacy encoding, but only during the transition period until + the endorsement kind will be completely removed. *) + register + @@ def + "operation_with_legacy_attestation_name" + ["unsigned"] + Protocol.Alpha_context.Operation + .unsigned_encoding_with_legacy_attestation_name ; + register ~pp:Protocol.Alpha_context.Period.pp + @@ def "period" [] Protocol.Alpha_context.Period.encoding ; + register ~pp:Protocol.Alpha_context.Cycle.pp + @@ def "cycle" [] Protocol.Alpha_context.Cycle.encoding ; + register @@ def "constants" [] Protocol.Alpha_context.Constants.encoding ; + register + @@ def "constants" ["fixed"] Protocol.Alpha_context.Constants.fixed_encoding ; + register + @@ def + "constants" + ["parametric"] + Protocol.Alpha_context.Constants.Parametric.encoding ; + register @@ def "nonce" [] Protocol.Alpha_context.Nonce.encoding ; + register @@ def "block_header" [] Protocol.Alpha_context.Block_header.encoding ; + register + @@ def + "block_header" + ["unsigned"] + Protocol.Alpha_context.Block_header.unsigned_encoding ; + register + @@ def "block_header" ["raw"] Protocol.Alpha_context.Block_header.raw_encoding ; + register + @@ def + "block_header" + ["contents"] + Protocol.Alpha_context.Block_header.contents_encoding ; + register + @@ def + "block_header" + ["shell_header"] + Protocol.Alpha_context.Block_header.shell_header_encoding ; + register + @@ def + "block_header" + ["protocol_data"] + Protocol.Alpha_context.Block_header.protocol_data_encoding ; + register ~pp:Protocol.Alpha_context.Voting_period.pp + @@ def "voting_period" [] Protocol.Alpha_context.Voting_period.encoding ; + register + @@ def + "voting_period" + ["kind"] + Protocol.Alpha_context.Voting_period.kind_encoding ; + register ~pp:Protocol.Alpha_context.Sc_rollup.Address.pp + @@ def + "smart_rollup" + ["address"] + Protocol.Alpha_context.Sc_rollup.Address.encoding ; + register ~pp:Protocol.Alpha_context.Sc_rollup.Kind.pp + @@ def "smart_rollup" ["kind"] Protocol.Alpha_context.Sc_rollup.Kind.encoding ; + register ~pp:Protocol.Alpha_context.Sc_rollup.Whitelist.pp + @@ def + "smart_rollup" + ["whitelist"] + Protocol.Alpha_context.Sc_rollup.Whitelist.encoding ; + register ~pp:Protocol.Alpha_context.Sc_rollup.Metadata.pp + @@ def + "smart_rollup" + ["metadata"] + Protocol.Alpha_context.Sc_rollup.Metadata.encoding ; + register + @@ def + "smart_rollup" + ["inbox"] + Protocol.Alpha_context.Sc_rollup.Inbox.encoding ; + register + @@ def + "smart_rollup" + ["inbox"; "message"] + Protocol.Alpha_context.Sc_rollup.Inbox_message.encoding ; + register + @@ def + "smart_rollup" + ["reveal"] + Protocol.Alpha_context.Sc_rollup.reveal_encoding ; + register + @@ def + "smart_rollup" + ["outbox"; "message"] + Protocol.Alpha_context.Sc_rollup.Outbox.Message.encoding ; + register + @@ def + "smart_rollup" + ["output"] + Protocol.Alpha_context.Sc_rollup.output_encoding ; + register + @@ def + "smart_rollup" + ["wasm_2_0_0"; "output"; "proof"] + Protocol.Alpha_context.Sc_rollup.Wasm_2_0_0PVM.Protocol_implementation + .output_proof_encoding ; + register + @@ def + "smart_rollup" + ["commmitment"] + Protocol.Alpha_context.Sc_rollup.Commitment.encoding ; + register + @@ def + "smart_rollup" + ["proof"] + Protocol.Alpha_context.Sc_rollup.Proof.encoding ; + register + @@ def "smart_rollup" ["game"] Protocol.Alpha_context.Sc_rollup.Game.encoding ; + register + @@ def + "errors" + [] + ~description: + "The full list of RPC errors would be too long to include.It is\n\ + available through the RPC `/errors` (GET)." + error_encoding diff --git a/src/proto_020_PsParisC/lib_client/proxy.ml b/src/proto_020_PsParisC/lib_client/proxy.ml new file mode 100644 index 000000000000..7df741021ab0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/proxy.ml @@ -0,0 +1,181 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module ProtoRpc : Tezos_proxy.Proxy_proto.PROTO_RPC = struct + (** Split done only when the mode is [Tezos_proxy.Proxy.server]. Getting + an entire big map at once is useful for dapp developers that + iterate a lot on big maps and that use proxy servers in their + internal infra. *) + let split_server key = + match key with + (* matches paths like: + big_maps/index/i/contents/tail *) + | "big_maps" :: "index" :: i :: "contents" :: tail -> + Some (["big_maps"; "index"; i; "contents"], tail) + | _ -> None + + (** Split that is always done, no matter the mode *) + let split_always key = + match key with + (* matches paths like: + contracts/index/000002298c03ed7d454a101eb7022bc95f7e5f41ac78/tail *) + | "contracts" :: "index" :: i :: tail -> + Some (["contracts"; "index"; i], tail) + | "cycle" :: i :: tail -> Some (["cycle"; i], tail) + (* matches paths like: + rolls/owner/snapshot/19/1/tail *) + | "rolls" :: "owner" :: "snapshot" :: i :: j :: tail -> + Some (["rolls"; "owner"; "snapshot"; i; j], tail) + | "v1" :: tail -> Some (["v1"], tail) + | _ -> None + + let split_key (mode : Tezos_proxy.Proxy.mode) + (key : Tezos_protocol_environment.Proxy_context.M.key) : + (Tezos_protocol_environment.Proxy_context.M.key + * Tezos_protocol_environment.Proxy_context.M.key) + option = + match split_always key with + | Some _ as res -> + res (* No need to inspect the mode, this split is always done *) + | None -> ( + match mode with + | Client -> + (* There are strictly less splits in Client mode: return immediately *) + None + | Server -> split_server key) + + let failure_is_permanent = function + | ["pending_migration_balance_updates"] + | ["pending_migration_operation_results"] -> + true + | _ -> false + + let do_rpc (pgi : Tezos_proxy.Proxy.proxy_getter_input) + (key : Tezos_protocol_environment.Proxy_context.M.key) = + let open Lwt_result_syntax in + let chain = pgi.chain in + let block = pgi.block in + let*! () = + Tezos_proxy.Logger.emit + Tezos_proxy.Logger.proxy_block_rpc + ( Tezos_shell_services.Block_services.chain_to_string chain, + Tezos_shell_services.Block_services.to_string block, + key ) + in + let* (raw_context : Tezos_context_sigs.Context.Proof_types.raw_context) = + Protocol_client_context.Alpha_block_services.Context.read + pgi.rpc_context + ~chain + ~block + key + in + let*! () = + Tezos_proxy.Logger.emit Tezos_proxy.Logger.tree_received + @@ Int64.of_int (Tezos_proxy.Proxy_getter.raw_context_size raw_context) + in + return raw_context +end + +let initial_context (ctx : Tezos_proxy.Proxy_getter.rpc_context_args) + (hash : Context_hash.t) : + Tezos_protocol_environment.Context.t tzresult Lwt.t = + let open Lwt_result_syntax in + let*! () = + Tezos_proxy.Logger.emit + Tezos_proxy.Logger.proxy_getter_created + ( Tezos_shell_services.Block_services.chain_to_string ctx.chain, + Tezos_shell_services.Block_services.to_string ctx.block ) + in + let p_rpc = (module ProtoRpc : Tezos_proxy.Proxy_proto.PROTO_RPC) in + let* (module ProxyDelegation) = + Tezos_proxy.Proxy_getter.make_delegate ctx p_rpc hash + in + let empty = + Tezos_protocol_environment.Proxy_context.empty + @@ Some (module ProxyDelegation) + in + let version_value = "paris_019" in + let*! ctxt = + Tezos_protocol_environment.Context.add + empty + ["version"] + (Bytes.of_string version_value) + in + (* There is something fundamentally strange here. The purpose of the + proxy mode is to fetch pieces of data that are missing. Hence, + there is no need to initialize the context properly. It is + sufficient that the proxy client is connected to a node with a + valid context. However, this makes the assumption that any + interaction with the context is pure: Only the Irmin context can + be modified. The cache breaks this since initializing the cache + changes the Irmin context but also loads values into memory. If + the cache is not initialized, then any cache access will fail. + Hence, the initialization is done here. This means that the + caller needs to maintain a cache on its own. But I suspect this + is not wanted: The cache of the proxied node should be used + instead. *) + let cache_layout = + (* The order matters, be careful to maintain it correctly. *) + Default_parameters. + [ + constants_mainnet.cache_script_size; + constants_mainnet.cache_stake_distribution_cycles; + constants_mainnet.cache_sampler_state_cycles; + ] + in + Lwt_result.ok + (Tezos_protocol_environment.Context.Cache.set_cache_layout + ctxt + cache_layout) + +let round_durations (rpc_context : Tezos_rpc.Context.generic) + (chain : Tezos_shell_services.Block_services.chain) + (block : Tezos_shell_services.Block_services.block) = + let open Protocol in + let open Lwt_result_syntax in + let rpc_context = new Protocol_client_context.wrap_rpc_context rpc_context in + let* constants = Constants_services.all rpc_context (chain, block) in + (* Return the duration of block 0 *) + return + @@ Some + (Alpha_context.Period.to_seconds + constants.parametric.minimal_block_delay) + +let () = + let open Tezos_proxy.Registration in + let module M : Proxy_sig = struct + module Protocol = Lifted_protocol + + let protocol_hash = Protocol.hash + + let directory = Plugin.RPC.rpc_services + + let initial_context = initial_context + + let time_between_blocks = round_durations + + include Light.M + end in + register_proxy_context (module M) diff --git a/src/proto_020_PsParisC/lib_client/test/dune b/src/proto_020_PsParisC/lib_client/test/dune new file mode 100644 index 000000000000..6986c7c033ea --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/test/dune @@ -0,0 +1,54 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_client_test_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-libs.micheline + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.protocol + octez-libs.base-test-helpers + octez-libs.test-helpers + octez-alcotezt + qcheck-alcotest) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_micheline + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_base_test_helpers + -open Tezos_test_helpers + -open Octez_alcotezt) + (modules + test_michelson_v1_macros + test_client_proto_contracts + test_client_proto_context + test_proxy)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_client_test_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package octez-protocol-019-PtParisB-libs) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_client/test/test_client_proto_context.ml b/src/proto_020_PsParisC/lib_client/test/test_client_proto_context.ml new file mode 100644 index 000000000000..d8dc119e6f2e --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/test/test_client_proto_context.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Testing + ------- + Component: Client + Invocation: dune exec src/proto_020_PsParisC/lib_client/test/main.exe \ + -- --file test_client_proto_context.ml + Subject: Tests roundtrips of batch_transfer_operation_encoding +*) + +open Protocol +open Alpha_context +open Qcheck2_helpers + +let binary_roundtrip ?pp encoding t = + let b = Data_encoding.Binary.to_bytes_exn encoding t in + let actual = Data_encoding.Binary.of_bytes_exn encoding b in + qcheck_eq' ?pp ~expected:t ~actual () + +let gen_batch_transfer_operation_encoding = + let open QCheck2.Gen in + let gen_z = sized @@ fun n -> map Z.of_bits (string_size (return n)) in + let gen_gas_arith_integral = + map Gas.Arith.integral_of_int_exn (int_range 0 (Int.div Int.max_int 1000)) + in + let* destination = string in + let* fee = opt string in + let* gas_limit = opt gen_gas_arith_integral in + let* storage_limit = opt gen_z in + let* amount = string in + let* arg = opt string in + let* entrypoint = opt (string_size (1 -- 31)) in + let entrypoint = Option.map Entrypoint.of_string_strict_exn entrypoint in + return + Client_proto_context. + {destination; fee; gas_limit; storage_limit; amount; arg; entrypoint} + +let tests = + [ + QCheck2.Test.make + ~name:"test_batch_transfer_operation_encoding_roundtrip" + gen_batch_transfer_operation_encoding + (binary_roundtrip Client_proto_context.batch_transfer_operation_encoding); + ] + +let () = Alcotest.run ~__FILE__ Protocol.name [("Encodings", qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_client/test/test_client_proto_contracts.ml b/src/proto_020_PsParisC/lib_client/test/test_client_proto_contracts.ml new file mode 100644 index 000000000000..e04f94e3efeb --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/test/test_client_proto_contracts.ml @@ -0,0 +1,105 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Client + Invocation: dune exec src/proto_020_PsParisC/lib_client/test/main.exe \ + -- --file test_client_proto_contracts.ml + Subject: Unit tests for Client_proto_contracts +*) + +(** [mock_wallet entities] is a mock of the + [Tezos_client_base.Client_context.wallet] class that only + implements the [load] method. This methods returns a key-value + association as given by the json string [entities] that should have + the form: ["[{"name": "alias", "value": "key" }, <...>]"]. *) +class mock_wallet (entities : string) : Tezos_client_base.Client_context.wallet + = + object + method load_passwords = None + + method read_file _path = failwith "mock_wallet:read_file" + + method get_base_dir = "" + + method with_lock : type a. (unit -> a Lwt.t) -> a Lwt.t = fun _f -> _f () + + method load : type a. + string -> default:a -> a Data_encoding.encoding -> a tzresult Lwt.t = + let open Lwt_result_syntax in + fun _alias_name ~default:_default _encoding -> + let json = (Ezjsonm.from_string entities :> Data_encoding.json) in + return @@ Data_encoding.Json.destruct _encoding json + + method write : type a. + string -> a -> a Data_encoding.encoding -> unit tzresult Lwt.t = + fun _alias_name _list _encoding -> failwith "mock_wallet:write" + + method last_modification_time : string -> float option tzresult Lwt.t = + fun _ -> Lwt_result_syntax.return_none + end + +(** + Test. + Tests different lookups of + [Client_proto_contracts.Contract_alias.find_destination]. +*) +let test_find_destination _ = + let open Lwt_result_syntax in + let bootstrap1 = "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" in + let wallet_json = + Format.asprintf {| [{"name": "test_alias", "value": "%s" }] |} bootstrap1 + in + let w = new mock_wallet wallet_json in + let test msg key exp_source = + let* contract = + Client_proto_contracts.Contract_alias.find_destination w key + in + let* source = + Client_proto_contracts.Raw_contract_alias.to_source contract + in + (* Alcotest equality assertion *) + Alcotest.(check string msg source exp_source) ; + return_unit + in + let* () = + test "Expected alias:test_alias = bootstrap1" "alias:test_alias" bootstrap1 + in + let* () = + test "Expected key:test_alias = bootstrap1" "key:test_alias" bootstrap1 + in + let* () = test "Expected bootstrap1 = bootstrap1" bootstrap1 bootstrap1 in + test "Expected test_alias bootstrap1" "test_alias" bootstrap1 + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [ + ( "client_proto_contracts", + [Tztest.tztest "test_find_destination" `Quick test_find_destination] ); + ] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_client/test/test_michelson_v1_macros.ml b/src/proto_020_PsParisC/lib_client/test/test_michelson_v1_macros.ml new file mode 100644 index 000000000000..a2bfd15fb081 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/test/test_michelson_v1_macros.ml @@ -0,0 +1,1374 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Client + Invocation: dune exec src/proto_020_PsParisC/lib_client/test/main.exe \ + -- --file test_michelson_v1_macros.ml + Dependencies: src/proto_alpha/lib_client/test/assert.ml + Subject: Expansion and unexpansion of Micheline terms. +*) + +open Protocol +module Assert = Assert + +let pp ppf expr = + expr + |> Micheline_printer.printable (fun s -> s) + |> Format.fprintf ppf "%a" Micheline_printer.print_expr + +let to_string e = Format.asprintf "%a" pp e +(* expands : expression with macros fully expanded *) + +let assert_expands + (original : (Micheline_parser.location, string) Micheline.node) + (expanded : (Micheline_parser.location, string) Micheline.node) = + let {Michelson_v1_parser.expanded = expansion; _}, errors = + let source = to_string (Micheline.strip_locations original) in + Michelson_v1_parser.expand_all_and_recognize_prims ~source ~original + in + match errors with + | [] -> + Assert.equal + ~pp + (Michelson_v1_primitives.strings_of_prims expansion) + (Micheline.strip_locations expanded) ; + Ok () + | errors -> Error errors + +(****************************************************************************) + +open Micheline + +let zero_loc = Micheline_parser.location_zero + +let left_branch = Seq (zero_loc, [Prim (zero_loc, "SWAP", [], [])]) + +let right_branch = Seq (zero_loc, []) + +(***************************************************************************) +(* Test expands *) +(***************************************************************************) + +(** [prim_name] is the syntactic sugar to be expanded, while [compare_name] + is syntactic atom. *) +let assert_compare_macro prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []); + ] )) + +(** Expand "COMP{EQ|NEQ|LT|GT|LE|GE}" + into "COMPARE ; {EQ|NEQ|LT|GT|LE|GE}". +*) +let test_compare_marco_expansion () = + let open Result_syntax in + let* () = assert_compare_macro "CMPEQ" "EQ" in + let* () = assert_compare_macro "CMPNEQ" "NEQ" in + let* () = assert_compare_macro "CMPLT" "LT" in + let* () = assert_compare_macro "CMPGT" "GT" in + let* () = assert_compare_macro "CMPLE" "LE" in + assert_compare_macro "CMPGE" "GE" + +let assert_if_macro prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [left_branch; right_branch], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", [left_branch; right_branch], []); + ] )) + +(** Expand "IF{EQ|NEQ|LT|GT|LE|GE}" + into "{EQ|NEQ|LT|GT|LE|GE} ; IF" +*) +let test_if_compare_macros_expansion () = + let open Result_syntax in + let* () = assert_if_macro "IFEQ" "EQ" in + let* () = assert_if_macro "IFNEQ" "NEQ" in + let* () = assert_if_macro "IFLT" "LT" in + let* () = assert_if_macro "IFGT" "GT" in + let* () = assert_if_macro "IFLE" "LE" in + assert_if_macro "IFGE" "GE" + +let assert_if_cmp_macros prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [left_branch; right_branch], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", [left_branch; right_branch], []); + ] )) + +(** Expand "IF{EQ|NEQ|LT|GT|LE|GE}" + into "{EQ|NEQ|LT|GT|LE|GE} ; IF" +*) +let test_if_cmp_macros_expansion () = + let open Result_syntax in + let* () = assert_if_cmp_macros "IFCMPEQ" "EQ" in + let* () = assert_if_cmp_macros "IFCMPNEQ" "NEQ" in + let* () = assert_if_cmp_macros "IFCMPLT" "LT" in + let* () = assert_if_cmp_macros "IFCMPGT" "GT" in + let* () = assert_if_cmp_macros "IFCMPLE" "LE" in + assert_if_cmp_macros "IFCMPGE" "GE" + +(****************************************************************************) +(* Fail *) + +(** Expand "FAIL" + into "UNIT ; FAILWITH" +*) +let test_fail_expansion () = + assert_expands + (Prim (zero_loc, "FAIL", [], [])) + (Seq + ( zero_loc, + [Prim (zero_loc, "UNIT", [], []); Prim (zero_loc, "FAILWITH", [], [])] + )) + +(**********************************************************************) +(* assertion *) + +let seq_unit_failwith = + Seq + ( zero_loc, + [Prim (zero_loc, "UNIT", [], []); Prim (zero_loc, "FAILWITH", [], [])] ) + +(* {} {FAIL} *) +let fail_false = [Seq (zero_loc, []); Seq (zero_loc, [seq_unit_failwith])] + +(* {FAIL} {} *) +let fail_true = [Seq (zero_loc, [seq_unit_failwith]); Seq (zero_loc, [])] + +(** Expand "ASSERT" + into "IF {} {FAIL}" +*) +let test_assert_expansion () = + assert_expands + (Prim (zero_loc, "ASSERT", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF", fail_false, [])])) + +let assert_assert_if_compare prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", fail_false, []); + ] )) + +(** Expand "ASSERT_{EQ|NEQ|LT|GT|LE|GE}" + into "{EQ|NEQ|LT|GT|LE|GE} ; IF {} {FAIL}" +*) +let test_assert_if () = + let open Result_syntax in + let* () = assert_assert_if_compare "ASSERT_EQ" "EQ" in + let* () = assert_assert_if_compare "ASSERT_NEQ" "NEQ" in + let* () = assert_assert_if_compare "ASSERT_LT" "LT" in + let* () = assert_assert_if_compare "ASSERT_LE" "LE" in + let* () = assert_assert_if_compare "ASSERT_GT" "GT" in + assert_assert_if_compare "ASSERT_GE" "GE" + +let assert_cmp_if prim_name compare_name = + assert_expands + (Prim (zero_loc, prim_name, [], [])) + (Seq + ( zero_loc, + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []); + ] ); + Prim (zero_loc, "IF", fail_false, []); + ] )) + +(** Expand "ASSERT_CMP{EQ|NEQ|LT|GT|LE|GE}" + into "COMPARE ; {EQ|NEQ|LT|GT|LE|GE} ; IF {} {FAIL}" +*) +let test_assert_cmp_if () = + let open Result_syntax in + let* () = assert_cmp_if "ASSERT_CMPEQ" "EQ" in + let* () = assert_cmp_if "ASSERT_CMPNEQ" "NEQ" in + let* () = assert_cmp_if "ASSERT_CMPLT" "LT" in + let* () = assert_cmp_if "ASSERT_CMPLE" "LE" in + let* () = assert_cmp_if "ASSERT_CMPGT" "GT" in + assert_cmp_if "ASSERT_CMPGE" "GE" + +(* The work of merge request !628 + > ASSERT_LEFT @x => IF_LEFT {RENAME @x} {FAIL} + > ASSERT_RIGHT @x => IF_LEFT {FAIL} {RENAME @x} + > ASSERT_SOME @x => IF_NONE {FAIL} {RENAME @x} +*) + +let may_rename annot = Seq (zero_loc, [Prim (zero_loc, "RENAME", [], annot)]) + +let fail_false_may_rename = + [ + may_rename ["@annot"]; + Seq + ( zero_loc, + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "UNIT", [], []); + Prim (zero_loc, "FAILWITH", [], []); + ] ); + ] ); + ] + +let fail_true_may_rename = + [ + Seq + ( zero_loc, + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "UNIT", [], []); + Prim (zero_loc, "FAILWITH", [], []); + ] ); + ] ); + may_rename ["@annot"]; + ] + +(** Expand "ASSERT_SOME @annot" + into "IF_NONE { } {UNIT;FAILWITH}" + using variable annotation "@annot" +*) +let test_assert_some_annot () = + assert_expands + (Prim (zero_loc, "ASSERT_SOME", [], ["@annot"])) + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true_may_rename, [])])) + +(** Expand "ASSERT_SOME" + into "IF_NONE { UNIT;FAILWITH } { }" +*) +let test_assert_some () = + assert_expands + (Prim (zero_loc, "ASSERT_SOME", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true, [])])) + +(** Expand "ASSERT_LEFT @annot" + into "IF_LEFT { } {UNIT;FAILWITH}" + using variable annotation "@annot" +*) +let test_assert_left_annot () = + assert_expands + (Prim (zero_loc, "ASSERT_LEFT", [], ["@annot"])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false_may_rename, [])])) + +(** Expand "ASSERT_LEFT" + into "IF_LEFT { } {UNIT;FAILWITH}" +*) +let test_assert_left () = + assert_expands + (Prim (zero_loc, "ASSERT_LEFT", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false, [])])) + +(** Expand "ASSERT_RIGHT @annot" + into "IF_LEFT {UNIT;FAILWITH} { }" + using variable annotation "@annot" +*) +let test_assert_right_annot () = + assert_expands + (Prim (zero_loc, "ASSERT_RIGHT", [], ["@annot"])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true_may_rename, [])])) + +(** Expand "ASSERT_RIGHT" + into "IF_LEFT {UNIT;FAILWITH} { }" +*) +let test_assert_right () = + assert_expands + (Prim (zero_loc, "ASSERT_RIGHT", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true, [])])) + +(** Expand "ASSERT_NONE" + into "IF_NONE { } { UNIT;FAILWITH }" +*) +let test_assert_none () = + assert_expands + (Prim (zero_loc, "ASSERT_NONE", [], [])) + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_false, [])])) + +(***********************************************************************) +(*Syntactic Conveniences*) + +(* diip *) + +(** Expand "DIP" into "DIP". + Expand "DIIIIIIIIP" into "DIP 8". + Expand "DIIP" into "DIP 2". +*) +let test_diip () = + let open Result_syntax in + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + let* () = + assert_expands + (Prim (zero_loc, "DIP", [code], [])) + (Prim (zero_loc, "DIP", [code], [])) + in + let* () = + assert_expands + (Prim (zero_loc, "DIIIIIIIIP", [code], [])) + (Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 8); code], [])) + in + assert_expands + (Prim (zero_loc, "DIIP", [code], [])) + (Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], [])) + +(* pair *) + +(** Expand "PAIR" + into "PAIR" +*) +let test_pair () = + assert_expands + (Prim (zero_loc, "PAIR", [], [])) + (Prim (zero_loc, "PAIR", [], [])) + +(** Expand "PAPPAIIR" + into "DIP {PAIR}; DIP {PAIR}; PAIR" +*) +let test_pappaiir () = + let pair = Prim (zero_loc, "PAIR", [], []) in + assert_expands + (Prim (zero_loc, "PAPPAIIR", [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DIP", [Seq (zero_loc, [pair])], []); + Prim (zero_loc, "DIP", [Seq (zero_loc, [pair])], []); + pair; + ] )) + +(* unpair *) + +(** Expand "UNPAIR" + into "DUP ; CAR ; DIP {CDR}" +*) +let test_unpair () = + assert_expands + (Prim (zero_loc, "UNPAIR", [], [])) + (Prim (zero_loc, "UNPAIR", [], [])) + +(* duup *) + +(** Expand "DUUP" + into "DIP {DUP} ; SWAP" +*) +let test_duup () = + assert_expands + (Prim (zero_loc, "DUUP", [], [])) + (Prim (zero_loc, "DUP", [Int (zero_loc, Z.of_int 2)], [])) + +(* car/cdr *) + +(** Expand "CAR" into "CAR" + Expand "CDR" into "CDR" + Expand "CADR" into "CAR ; CDR" + Expand "CDAR" into "CDR ; CAR" +*) +let test_caddadr_expansion () = + let open Result_syntax in + let car = Prim (zero_loc, "CAR", [], []) in + let* () = assert_expands (Prim (zero_loc, "CAR", [], [])) car in + let cdr = Prim (zero_loc, "CDR", [], []) in + let* () = assert_expands (Prim (zero_loc, "CDR", [], [])) cdr in + let* () = + assert_expands + (Prim (zero_loc, "CADR", [], [])) + (Seq (zero_loc, [car; cdr])) + in + assert_expands (Prim (zero_loc, "CDAR", [], [])) (Seq (zero_loc, [cdr; car])) + +let test_carn_cdrn_expansion () = + let open Result_syntax in + let car n = Prim (zero_loc, "CAR", [Int (zero_loc, Z.of_int n)], []) in + let cdr n = Prim (zero_loc, "CDR", [Int (zero_loc, Z.of_int n)], []) in + let get n = + Seq (zero_loc, [Prim (zero_loc, "GET", [Int (zero_loc, Z.of_int n)], [])]) + in + let* () = + let* () = assert_expands (cdr 0) (get 0) in + let* () = assert_expands (car 0) (get 1) in + let* () = assert_expands (cdr 1) (get 2) in + assert_expands (car 1) (get 3) + in + assert_expands (cdr 2) (get 4) + +(* if_some *) + +(** Expand "IF_SOME { 1 } { 2 }" + into "IF_NONE { 2 } { 1 }" +*) +let test_if_some () = + assert_expands + (Prim (zero_loc, "IF_SOME", [right_branch; left_branch], [])) + (Seq + (zero_loc, [Prim (zero_loc, "IF_NONE", [left_branch; right_branch], [])])) + +(*set_caddadr*) + +(** Expand "SET_CAR" + into "CDR; SWAP; PAIR" +*) +let test_set_car_expansion () = + assert_expands + (Prim (zero_loc, "SET_CAR", [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]); + ] )) + +(** Expand "SET_CDR" + into "CAR; PAIR" +*) +let test_set_cdr_expansion () = + assert_expands + (Prim (zero_loc, "SET_CDR", [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] )) + +(** Expand "SET_CADR" + into "DUP; DIP {CAR; { CAR; PAIR }}; CDR; SWAP; PAIR" +*) +let test_set_cadr_expansion () = + let set_car = + Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] ) + in + assert_expands + (Prim (zero_loc, "SET_CADR", [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); set_car])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + +(** Expand "SET_CDAR" + into "DUP; DIP {CDR; { CDR; SWAP; PAIR }}; CAR; PAIR" +*) +let test_set_cdar_expansion () = + let set_cdr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]); + ] ) + in + assert_expands + (Prim (zero_loc, "SET_CDAR", [], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); set_cdr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + +(* TO BE CHANGE IN THE DOCUMENTATION: @MR!791 + FROM: + > MAP_CAR code => DUP ; CDR ; DIP { CAR ; code } ; SWAP ; PAIR + TO: + > MAP_CAR code => DUP ; CDR ; DIP { CAR ; {code} } ; SWAP ; PAIR +*) + +(** Expand "MAP_CAR {CAR}" + into "DUP; CDR; DIP {CAR; CAR}; SWAP; PAIR" +*) +let test_map_car () = + (* code is a sequence *) + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_expands + (Prim (zero_loc, "MAP_CAR", [code], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], []); code])], + [] ); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]); + ] )) + +(** Expand "MAP_CDR {CAR}" + into "DUP; CDR; CAR; SWAP; CAR; PAIR" +*) +let test_map_cdr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_expands + (Prim (zero_loc, "MAP_CDR", [code], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] )) + +(** Expand "MAP_CAADR {CAR}" + into "DUP; + DIP { CAR; + DUP; + DIP { CAR; + DUP; + CDR; + CAR; + SWAP; + CAR; + PAIR + } + CDR; + SWAP; + PAIR + }; + CDR; + SWAP; + PAIR" +*) +let test_map_caadr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + let map_cdr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] ) + in + let map_cadr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] ) + in + assert_expands + (Prim (zero_loc, "MAP_CAADR", [code], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cadr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + +(** Expand "MAP_CDADR" + into "DUP; + DIP { CDR; + DUP; + DIP { CAR; + DUP; + CDR; + CAR; + SWAP; + CAR; + PAIR + }; + CDR; + CAR; + PAIR + }; + CAR; + PAIR" +*) +let test_map_cdadr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + let map_cdr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] ) + in + let map_cadr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] ) + in + assert_expands + (Prim (zero_loc, "MAP_CDADR", [code], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); map_cadr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + +(****************************************************************************) +(* Unexpand tests *) +(****************************************************************************) + +(** Asserts that unexpanding the expression [original] conforms with + the canonical form of [ex]. + [unparse.Michelson_v1_parser.unexpanded] contains the original + expression with macros *) +let assert_unexpansion original ex = + let {Michelson_v1_parser.expanded; _}, errors = + let source = to_string (Micheline.strip_locations original) in + Michelson_v1_parser.expand_all_and_recognize_prims ~source ~original + in + let unparse = Michelson_v1_printer.unparse_expression expanded in + match errors with + | [] -> + Assert.equal + ~pp + unparse.Michelson_v1_parser.unexpanded + (Micheline.strip_locations ex) ; + Ok () + | _ :: _ -> Error errors + +(** Unexpanding "UNIT; FAILWITH" + yields "FAIL" +*) +let test_unexpand_fail () = + assert_unexpansion + (Seq + ( zero_loc, + [Prim (zero_loc, "UNIT", [], []); Prim (zero_loc, "FAILWITH", [], [])] + )) + (Prim (zero_loc, "FAIL", [], [])) + +(** Unexpanding "IF_LEFT { 1 } { 2 }" + yields "IF_RIGHT { 2 } { 1 }" +*) +let test_unexpand_if_right () = + assert_unexpansion + (Seq + (zero_loc, [Prim (zero_loc, "IF_LEFT", [left_branch; right_branch], [])])) + (Prim (zero_loc, "IF_RIGHT", [right_branch; left_branch], [])) + +(** IF_NONE + Unexpanding "IF_NONE { 1 } { 2 }" + yields "IF_SOME { 2 } { 1 }" +*) +let test_unexpand_if_some () = + assert_unexpansion + (Seq + (zero_loc, [Prim (zero_loc, "IF_NONE", [left_branch; right_branch], [])])) + (Prim (zero_loc, "IF_SOME", [right_branch; left_branch], [])) + +(** Unexpanding "IF {} { UNIT; FAILWITH }" + yields "ASSERT" +*) +let test_unexpand_assert () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF", fail_false, [])])) + (Prim (zero_loc, "ASSERT", [], [])) + +let assert_unexpansion_assert_if_compare compare_name prim_name = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, compare_name, [], []); + Prim (zero_loc, "IF", fail_false, []); + ] )) + (Prim (zero_loc, prim_name, [], [])) + +(** Unexpanding "{EQ|NEQ|LT|LE|GT|GE} ; IF {} {FAIL}" + yields "ASSERT_{EQ|NEQ|LT|LE|GT|GE}" +*) +let test_unexpand_assert_if () = + let open Result_syntax in + let* () = + let* () = assert_unexpansion_assert_if_compare "EQ" "ASSERT_EQ" in + let* () = assert_unexpansion_assert_if_compare "NEQ" "ASSERT_NEQ" in + let* () = assert_unexpansion_assert_if_compare "LT" "ASSERT_LT" in + let* () = assert_unexpansion_assert_if_compare "LE" "ASSERT_LE" in + assert_unexpansion_assert_if_compare "GT" "ASSERT_GT" + in + assert_unexpansion_assert_if_compare "GE" "ASSERT_GE" + +let assert_unexpansion_assert_cmp_if_compare compare_name prim_name = + assert_unexpansion + (Seq + ( zero_loc, + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "COMPARE", [], []); + Prim (zero_loc, compare_name, [], []); + ] ); + Prim (zero_loc, "IF", fail_false, []); + ] )) + (Prim (zero_loc, prim_name, [], [])) + +(** Unexpanding "COMPARE; {EQ|NEQ|LT|LE|GT|GE}; IF {} {FAIL}" + yields "ASSERT_CMP{EQ|NEQ|LT|LE|GT|GE}" +*) +let test_unexpansion_assert_cmp_if () = + let open Result_syntax in + let* () = assert_unexpansion_assert_cmp_if_compare "EQ" "ASSERT_CMPEQ" in + let* () = assert_unexpansion_assert_cmp_if_compare "NEQ" "ASSERT_CMPNEQ" in + let* () = assert_unexpansion_assert_cmp_if_compare "LT" "ASSERT_CMPLT" in + let* () = assert_unexpansion_assert_cmp_if_compare "LE" "ASSERT_CMPLE" in + let* () = assert_unexpansion_assert_cmp_if_compare "GT" "ASSERT_CMPGT" in + assert_unexpansion_assert_cmp_if_compare "GE" "ASSERT_CMPGE" + +(** Unexpanding "IF_NONE { FAIL } { RENAME @annot }" + yields "ASSERT_SOME @annot" +*) +let test_unexpand_assert_some_annot () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true_may_rename, [])])) + (Prim (zero_loc, "ASSERT_SOME", [], ["@annot"])) + +(** Unexpanding "IF_LEFT { RENAME @annot } { FAIL }" + yields "ASSERT_LEFT @annot" +*) +let test_unexpand_assert_left_annot () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false_may_rename, [])])) + (Prim (zero_loc, "ASSERT_LEFT", [], ["@annot"])) + +(** Unexpanding "IF_LEFT { FAIL } { RENAME @annot }" + yields "ASSERT_RIGHT @annot" +*) +let test_unexpand_assert_right_annot () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true_may_rename, [])])) + (Prim (zero_loc, "ASSERT_RIGHT", [], ["@annot"])) + +(** Unexpanding "IF_NONE {} { FAIL }" + yields "ASSERT_NONE" +*) +let test_unexpand_assert_none () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_false, [])])) + (Prim (zero_loc, "ASSERT_NONE", [], [])) + +(** Unexpanding "IF_NONE { FAIL } {}" + yields "ASSERT_SOME" +*) +let test_unexpand_assert_some () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_NONE", fail_true, [])])) + (Prim (zero_loc, "ASSERT_SOME", [], [])) + +(** Unexpanding "IF_LEFT {} { FAIL }" + yields "ASSERT_LEFT" +*) +let test_unexpand_assert_left () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_false, [])])) + (Prim (zero_loc, "ASSERT_LEFT", [], [])) + +(** Unexpanding "IF_LEFT { FAIL } {}" + yields "ASSERT_RIGHT" +*) +let test_unexpand_assert_right () = + assert_unexpansion + (Seq (zero_loc, [Prim (zero_loc, "IF_LEFT", fail_true, [])])) + (Prim (zero_loc, "ASSERT_RIGHT", [], [])) + +(** Unexpanding "DUP; CAR; DIP { CDR }" + yields "UNPAIR" +*) +let test_unexpand_unpair () = + assert_unexpansion + (Prim (zero_loc, "UNPAIR", [], [])) + (Prim (zero_loc, "UNPAIR", [], [])) + +(** Unexpanding "PAIR" + yields "PAIR" +*) +let test_unexpand_pair () = + assert_unexpansion + (Prim (zero_loc, "PAIR", [], [])) + (Prim (zero_loc, "PAIR", [], [])) + +(** Unexpanding "DIP { PAIR }; DIP { PAIR }; PAIR" + yields "PAPPAIIR" +*) +let test_unexpand_pappaiir () = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "PAIR", [], [])])], + [] ); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "PAIR", [], [])])], + [] ); + Prim (zero_loc, "PAIR", [], []); + ] )) + (Prim (zero_loc, "PAPPAIIR", [], [])) + +(** Unexpanding "DIP { DUP }; SWAP" + yields "DUP 2" +*) +let test_unexpand_duup () = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "DUP", [], [])])], + [] ); + Prim (zero_loc, "SWAP", [], []); + ] )) + (Prim (zero_loc, "DUP", [Int (zero_loc, Z.of_int 2)], [])) + +(** Unexpanding "CAR" yields "CAR" + Unexpanding "CDR" yields "CDR" + Unexpanding "CAR; CDR" yields "CADR" + Unexpanding "CDR; CAR" yields "CDAR" +*) +let test_unexpand_caddadr () = + let open Result_syntax in + let car = Prim (zero_loc, "CAR", [], []) in + let cdr = Prim (zero_loc, "CDR", [], []) in + let* () = assert_unexpansion (Seq (zero_loc, [car])) car in + let* () = assert_unexpansion (Seq (zero_loc, [cdr])) cdr in + let* () = + assert_unexpansion + (Seq (zero_loc, [car; cdr])) + (Prim (zero_loc, "CADR", [], [])) + in + assert_unexpansion + (Seq (zero_loc, [cdr; car])) + (Prim (zero_loc, "CDAR", [], [])) + +let test_unexpand_carn_cdrn () = + let open Result_syntax in + let car n = Prim (zero_loc, "CAR", [Int (zero_loc, Z.of_int n)], []) in + let cdr n = Prim (zero_loc, "CDR", [Int (zero_loc, Z.of_int n)], []) in + let get n = + Seq (zero_loc, [Prim (zero_loc, "GET", [Int (zero_loc, Z.of_int n)], [])]) + in + let* () = assert_unexpansion (get 0) (cdr 0) in + let* () = assert_unexpansion (get 1) (car 0) in + let* () = assert_unexpansion (get 2) (cdr 1) in + let* () = assert_unexpansion (get 3) (car 1) in + assert_unexpansion (get 4) (cdr 2) + +(** Unexpanding "CDR; SWAP; PAIR" + yields "SET_CAR" +*) +let test_unexpand_set_car () = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]); + ] )) + (Prim (zero_loc, "SET_CAR", [], [])) + +(** Unexpanding "CAR; PAIR" + yields "SET_CDR" +*) +let test_unexpand_set_cdr () = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] )) + (Prim (zero_loc, "SET_CDR", [], [])) + +(** Unexpanding "DUP; CAR; DROP; CDR; SWAP; PAIR" + yields "SET_CAR" +*) +let test_unexpand_set_car_annot () = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CAR", [], ["%@"]); + Prim (zero_loc, "DROP", [], []); + Prim (zero_loc, "CDR", [], []); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], []); + ] )) + (Prim (zero_loc, "SET_CAR", [], ["%@"])) + +(** Unexpanding "DUP; CDR; DROP; CAR; PAIR" + yields "SET_CDR" +*) +let test_unexpand_set_cdr_annot () = + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], ["%@"]); + Prim (zero_loc, "DROP", [], []); + Prim (zero_loc, "CAR", [], []); + Prim (zero_loc, "PAIR", [], []); + ] )) + (Prim (zero_loc, "SET_CDR", [], ["%@"])) + +(** Unexpanding "DUP; DIP { CAR; CAR; PAIR }; CDR; SWAP; PAIR" + yields "SET_CADR" +*) +let test_unexpand_set_cadr () = + let set_car = + Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] ) + in + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); set_car])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + (Prim (zero_loc, "SET_CADR", [], [])) + +let test_unexpand_set_cdar () = + let set_cdr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]); + ] ) + in + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); set_cdr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + (Prim (zero_loc, "SET_CDAR", [], [])) + +(* FIXME: Seq()(Prim): does not parse, raise an error unparse *) +let test_unexpand_map_car () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_unexpansion + (Prim (zero_loc, "MAP_CAR", [code], [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim + ( zero_loc, + "DIP", + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], []); + Prim (zero_loc, "CAR", [], []); + ] ); + ], + [] ); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%"; "%@"]); + ] )) + +(***********************************************************************) +(*BUG: the test with MAP_CDR or any map with "D" inside fail *) + +let _test_unexpand_map_cdr () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + code; + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], []); + Prim (zero_loc, "PAIR", [], []); + ] )) + (Prim (zero_loc, "MAP_CDR", [code], [])) + +let _test_unexpand_map_caadr () = + let code = [Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])])] in + let map_cdr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], ["@%%"]); + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] ); + ] ); + ], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] ) + in + assert_unexpansion + (Prim (zero_loc, "MAP_CAAR", code, [])) + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CAR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + +let _test_unexpand_map_cdadr () = + let code = [Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])])] in + let map_cdr = + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [ + Seq + ( zero_loc, + [ + Prim (zero_loc, "CAR", [], ["@%%"]); + Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim (zero_loc, "CDR", [], []); + Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%"]); + ] ); + ] ); + ], + [] ); + Prim (zero_loc, "CDR", [], ["@%%"]); + Prim (zero_loc, "SWAP", [], []); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] ) + in + assert_unexpansion + (Seq + ( zero_loc, + [ + Prim (zero_loc, "DUP", [], []); + Prim + ( zero_loc, + "DIP", + [Seq (zero_loc, [Prim (zero_loc, "CDR", [], ["@%%"]); map_cdr])], + [] ); + Prim (zero_loc, "CAR", [], ["@%%"]); + Prim (zero_loc, "PAIR", [], ["%@"; "%@"]); + ] )) + (Prim (zero_loc, "MAP_CDADR", code, [])) + +let test_unexpand_diip () = + let code = Seq (zero_loc, [Prim (zero_loc, "CAR", [], [])]) in + assert_unexpansion + (Prim (zero_loc, "DIIP", [code], [])) + (Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], [])) + +(** Unexpanding "DIP { DIP { DIP { DUP }; SWAP" + yields "DIIP { DIP { DUP }; SWAP }" +*) +let test_unexpand_diip_duup1 () = + let single code = Seq (zero_loc, [code]) in + let cst str = Prim (zero_loc, str, [], []) in + let app str code = Prim (zero_loc, str, [code], []) in + let dip = app "DIP" in + let diip code = + Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], []) + in + let dup = cst "DUP" in + let swap = cst "SWAP" in + let dip_dup_swap = Seq (zero_loc, [dip (single dup); swap]) in + assert_unexpansion + (* { DIP { DIP { DIP { DUP }; SWAP }}} *) + (single (dip (single (dip dip_dup_swap)))) + (* DIIP { DIP { DUP }; SWAP } *) + (diip dip_dup_swap) + +(** Unexpanding "DIP { DIP {{ DIP { DUP }; SWAP" + yields "DIIP { DUUP }" +*) +let test_unexpand_diip_duup2 () = + let single code = Seq (zero_loc, [code]) in + let cst str = Prim (zero_loc, str, [], []) in + let app str code = Prim (zero_loc, str, [code], []) in + let dip = app "DIP" in + let diip code = + Prim (zero_loc, "DIP", [Int (zero_loc, Z.of_int 2); code], []) + in + let dup = cst "DUP" in + let duup = Prim (zero_loc, "DUP", [Int (zero_loc, Z.of_int 2)], []) in + let swap = cst "SWAP" in + let dip_dup_swap = Seq (zero_loc, [dip (single dup); swap]) in + assert_unexpansion + (* { DIP { DIP {{ DIP { DUP }; SWAP }}}} *) + (single (dip (single (dip (single dip_dup_swap))))) + (* DIIP { DUUP } *) + (diip (single duup)) + +(*****************************************************************************) +(* Test *) +(*****************************************************************************) + +let tests = + [ + (*compare*) + ("compare expansion", fun _ -> Lwt.return (test_compare_marco_expansion ())); + ( "if compare expansion", + fun _ -> Lwt.return (test_if_compare_macros_expansion ()) ); + ( "if compare expansion: IFCMP", + fun _ -> Lwt.return (test_if_cmp_macros_expansion ()) ); + (*fail*) + ("fail expansion", fun _ -> Lwt.return (test_fail_expansion ())); + (*assertion*) + ("assert expansion", fun _ -> Lwt.return (test_assert_expansion ())); + ("assert if expansion", fun _ -> Lwt.return (test_assert_if ())); + ("assert cmpif expansion", fun _ -> Lwt.return (test_assert_cmp_if ())); + ("assert none expansion", fun _ -> Lwt.return (test_assert_none ())); + ("assert some expansion", fun _ -> Lwt.return (test_assert_some ())); + ("assert left expansion", fun _ -> Lwt.return (test_assert_left ())); + ("assert right expansion", fun _ -> Lwt.return (test_assert_right ())); + ( "assert some annot expansion", + fun _ -> Lwt.return (test_assert_some_annot ()) ); + ( "assert left annot expansion", + fun _ -> Lwt.return (test_assert_left_annot ()) ); + ( "assert right annot expansion", + fun _ -> Lwt.return (test_assert_right_annot ()) ); + (*syntactic conveniences*) + ("diip expansion", fun _ -> Lwt.return (test_diip ())); + ("duup expansion", fun _ -> Lwt.return (test_duup ())); + ("pair expansion", fun _ -> Lwt.return (test_pair ())); + ("pappaiir expansion", fun _ -> Lwt.return (test_pappaiir ())); + ("unpair expansion", fun _ -> Lwt.return (test_unpair ())); + ("caddadr expansion", fun _ -> Lwt.return (test_caddadr_expansion ())); + ( "carn and cdrn expansion", + fun _ -> Lwt.return (test_carn_cdrn_expansion ()) ); + ("if_some expansion", fun _ -> Lwt.return (test_if_some ())); + ("set_car expansion", fun _ -> Lwt.return (test_set_car_expansion ())); + ("set_cdr expansion", fun _ -> Lwt.return (test_set_cdr_expansion ())); + ("set_cadr expansion", fun _ -> Lwt.return (test_set_cadr_expansion ())); + ("set_cdar expansion", fun _ -> Lwt.return (test_set_cdar_expansion ())); + ("map_car expansion", fun _ -> Lwt.return (test_map_car ())); + ("map_cdr expansion", fun _ -> Lwt.return (test_map_cdr ())); + ("map_caadr expansion", fun _ -> Lwt.return (test_map_caadr ())); + ("map_cdadr expansion", fun _ -> Lwt.return (test_map_cdadr ())); + (*Unexpand*) + ("fail unexpansion", fun _ -> Lwt.return (test_unexpand_fail ())); + ("if_right unexpansion", fun _ -> Lwt.return (test_unexpand_if_right ())); + ("if_some unexpansion", fun _ -> Lwt.return (test_unexpand_if_some ())); + ("assert unexpansion", fun _ -> Lwt.return (test_unexpand_assert ())); + ("assert_if unexpansion", fun _ -> Lwt.return (test_unexpand_assert_if ())); + ( "assert_cmp_if unexpansion", + fun _ -> Lwt.return (test_unexpansion_assert_cmp_if ()) ); + ( "assert_none unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_none ()) ); + ( "assert_some unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_some ()) ); + ( "assert_left unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_left ()) ); + ( "assert_right unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_right ()) ); + ( "assert_some annot unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_some_annot ()) ); + ( "assert_left annot unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_left_annot ()) ); + ( "assert_right annot unexpansion", + fun _ -> Lwt.return (test_unexpand_assert_right_annot ()) ); + ("unpair unexpansion", fun _ -> Lwt.return (test_unexpand_unpair ())); + ("pair unexpansion", fun _ -> Lwt.return (test_unexpand_pair ())); + ("pappaiir unexpansion", fun _ -> Lwt.return (test_unexpand_pappaiir ())); + ("duup unexpansion", fun _ -> Lwt.return (test_unexpand_duup ())); + ("caddadr unexpansion", fun _ -> Lwt.return (test_unexpand_caddadr ())); + ( "carn and cdrn unexpansion", + fun _ -> Lwt.return (test_unexpand_carn_cdrn ()) ); + ("set_car unexpansion", fun _ -> Lwt.return (test_unexpand_set_car ())); + ("set_cdr unexpansion", fun _ -> Lwt.return (test_unexpand_set_cdr ())); + ("set_cdar unexpansion", fun _ -> Lwt.return (test_unexpand_set_cdar ())); + ("set_cadr unexpansion", fun _ -> Lwt.return (test_unexpand_set_cadr ())); + ( "set_car annot unexpansion", + fun _ -> Lwt.return (test_unexpand_set_car_annot ()) ); + ( "set_cdr annot unexpansion", + fun _ -> Lwt.return (test_unexpand_set_cdr_annot ()) ); + ("map_car unexpansion", fun _ -> Lwt.return (test_unexpand_map_car ())); + ("diip unexpansion", fun _ -> Lwt.return (test_unexpand_diip ())); + ("diip_duup1 unexpansion", fun _ -> Lwt.return (test_unexpand_diip_duup1 ())); + ("diip_duup2 unexpansion", fun _ -> Lwt.return (test_unexpand_diip_duup2 ())) + (***********************************************************************) + (*BUG + the function in Michelson_v1_macros.unexpand_map_caddadr + failed to test the case with the character "D". + It returns an empty {} for the expand *) + (*"diip unexpansion", (fun _ -> Lwt.return (test_unexpand_diip ())) ;*) + (*"map_cdr unexpansion", (fun _ -> Lwt.return (test_unexpand_map_cdr ())) ;*) + (*"map_caadr unexpansion", (fun _ -> Lwt.return (test_unexpand_map_caadr ())) ;*) + (*"map_cdadr unexpansion", (fun _ -> Lwt.return (test_unexpand_map_cdadr ())) ;*); + ] + +let wrap (n, f) = + Alcotest_lwt.test_case n `Quick (fun _ () -> + let open Lwt_syntax in + let* res = f () in + match res with + | Ok () -> return_unit + | Error error -> + Format.kasprintf Stdlib.failwith "%a" pp_print_trace error) + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("micheline v1 macros", List.map wrap tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_client/test/test_proxy.ml b/src/proto_020_PsParisC/lib_client/test/test_proxy.ml new file mode 100644 index 000000000000..684ac3ef7ca9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client/test/test_proxy.ml @@ -0,0 +1,90 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Client + Invocation: dune exec src/proto_020_PsParisC/lib_client/test/main.exe \ + -- --file test_proxy.ml + Subject: Test of --mode proxy and tezos-proxy-server heuristic +*) + +let proxy_mode_gen = QCheck2.Gen.oneofl Tezos_proxy.Proxy.[Client; Server] + +let key_gen = + (* Segments taken from the implementation of split_key in src/proto_alpha/lib_client/proxy.ml *) + let keys = + QCheck2.Gen.oneofl + [ + "big_maps"; + "index"; + "contents"; + "contracts"; + "cycle"; + "cycle"; + "rolls"; + "owner"; + "snapshot"; + "v1"; + ] + |> QCheck2.Gen.list + in + QCheck2.Gen.frequency QCheck2.Gen.[(9, keys); (1, list string)] + +(** Whether [t1] is a prefix of [t2] *) +let rec is_prefix t1 t2 = + match (t1, t2) with + | [], _ -> true + | _, [] -> false + | x1 :: rest1, x2 :: rest2 when x1 = x2 -> is_prefix rest1 rest2 + | _ -> false + +let test_split_key = + let fmt = + let pp_sep fmt () = Format.fprintf fmt "/" in + Format.pp_print_list ~pp_sep Format.pp_print_string + in + QCheck2.Test.make + ~name:"[fst (split_key s)] is a prefix of [s]" + QCheck2.Gen.(pair proxy_mode_gen key_gen) + @@ fun (mode, key) -> + match Proxy.ProtoRpc.split_key mode key with + | None -> true + | Some (shorter, _) -> + if is_prefix shorter key then true + else + QCheck2.Test.fail_reportf + "Expected result of split_key to be a prefix of the input key. But \ + %a is not a prefix of %a." + fmt + shorter + fmt + key + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [("proxy", Qcheck2_helpers.qcheck_wrap [test_split_key])] diff --git a/src/proto_020_PsParisC/lib_client_commands/alpha_commands_registration.ml b/src/proto_020_PsParisC/lib_client_commands/alpha_commands_registration.ml new file mode 100644 index 000000000000..500108e385c6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/alpha_commands_registration.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash @@ fun network -> + List.map (Tezos_clic.map_command (new Protocol_client_context.wrap_full)) + @@ Client_proto_programs_commands.commands () + @ Client_proto_contracts_commands.commands () + @ Client_proto_context_commands.commands network () + @ Client_proto_multisig_commands.commands () + @ Client_proto_mockup_commands.commands () + @ Client_sapling_commands.commands () + @ Client_proto_utils_commands.commands () + @ Client_proto_stresstest_commands.commands network () + @ Client_proto_fa12_commands.commands () diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_context_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_context_commands.ml new file mode 100644 index 000000000000..f73387073244 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_context_commands.ml @@ -0,0 +1,3801 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2022-2024 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Client_proto_context +open Client_proto_contracts +open Client_proto_rollups +open Client_keys +open Client_proto_args + +let get_timelock_filename path prefix enc obj = + let add_path r n = r ^ "/" ^ n in + let bin = Data_encoding.Binary.to_bytes_exn enc obj in + let hex = Tezos_crypto.Blake2B.(hash_bytes [bin] |> to_hex) |> Hex.show in + let name = prefix ^ "_" ^ hex in + add_path path name + +let write_encoding filepath enc data = + let str = Data_encoding.Binary.to_string_exn enc data in + Lwt_utils_unix.create_file filepath str + +let read_encoding ?(buffer_size = 32768) path enc = + let open Lwt_result_syntax in + let*! file = Lwt_unix.(openfile path [O_RDONLY; O_NONBLOCK; O_CLOEXEC] 0) in + let buffer = Bytes.create buffer_size in + let*! nb_bytes_read = Lwt_unix.read file buffer 0 buffer_size in + let*! () = Lwt_unix.close file in + let buffer = + if nb_bytes_read = 0 then buffer else Bytes.sub buffer 0 nb_bytes_read + in + Data_encoding.Binary.of_bytes_exn enc buffer |> return + +let save_zk_rollup ~force (cctxt : #Client_context.full) alias_name rollup = + let open Lwt_result_syntax in + let* () = Epoxy_alias.add ~force cctxt alias_name rollup in + let*! () = cctxt#message "Epoxy rollup memorized as %s" alias_name in + return_unit + +let encrypted_switch = + Tezos_clic.switch ~long:"encrypted" ~doc:"encrypt the key on-disk" () + +let normalize_types_switch = + Tezos_clic.switch + ~long:"normalize-types" + ~doc: + "Whether types should be normalized (annotations removed, combs \ + flattened) or kept as they appeared in the original script." + () + +let report_michelson_errors ?(no_print_source = false) ~msg + (cctxt : #Client_context.full) = + let open Lwt_syntax in + function + | Error errs -> + let* errs = + Michelson_v1_error_reporter.enrich_runtime_errors + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~parsed:None + errs + in + let* () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~show_source:(not no_print_source) + ?parsed:None) + errs + in + let* () = cctxt#error "%s" msg in + return_none + | Ok data -> return_some data + +let block_hash_param = + Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + try Lwt_result_syntax.return (Block_hash.of_b58check_exn s) + with _ -> cctxt#error "Parameter '%s' is an invalid block hash" s) + +let group = + { + Tezos_clic.name = "context"; + title = "Block contextual commands (see option -block)"; + } + +let alphanet = {Tezos_clic.name = "alphanet"; title = "Alphanet only commands"} + +let binary_description = + {Tezos_clic.name = "description"; title = "Binary Description"} + +let tez_of_string_exn (cctxt : #Client_context.full) index field s = + let open Lwt_result_syntax in + match Tez.of_string s with + | Some t -> return t + | None -> + cctxt#error + "Invalid \xEA\x9C\xA9 notation at entry %i, field \"%s\": %s" + index + field + s + +let tez_of_opt_string_exn (cctxt : #Client_context.full) index field s = + Option.map_es (tez_of_string_exn cctxt index field) s + +let check_smart_contract = Managed_contract.check_smart_contract + +let commands_ro () = + let open Tezos_clic in + [ + command + ~group + ~desc:"Access the timestamp of the block." + (args1 + (switch ~doc:"output time in seconds" ~short:'s' ~long:"seconds" ())) + (fixed ["get"; "timestamp"]) + (fun seconds (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* {timestamp = v; _} = + Shell_services.Blocks.Header.shell_header + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + () + in + let*! () = + if seconds then cctxt#message "%Ld" (Time.Protocol.to_seconds v) + else cctxt#message "%s" (Time.Protocol.to_notation v) + in + return_unit); + command + ~group + ~desc:"Lists all non empty contracts of the block." + no_options + (fixed ["list"; "contracts"]) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* contracts = + list_contract_labels cctxt ~chain:cctxt#chain ~block:cctxt#block + in + let*! () = + List.iter_s + (fun (alias, hash, kind) -> cctxt#message "%s%s%s" hash kind alias) + contracts + in + return_unit); + command + ~group + ~desc:"Lists cached contracts and their age in LRU ordering." + no_options + (prefixes ["list"; "cached"; "contracts"] @@ stop) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* keys = + cached_contracts cctxt ~chain:cctxt#chain ~block:cctxt#block + in + let*! () = + List.iter_s + (fun (key, size) -> cctxt#message "%a %d" Contract_hash.pp key size) + keys + in + return_unit); + command + ~group + ~desc:"Get the key rank of a cache key." + no_options + (prefixes ["get"; "cached"; "contract"; "rank"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* rank = + contract_rank cctxt ~chain:cctxt#chain ~block:cctxt#block contract + in + let*! () = + match rank with + | None -> cctxt#error "Invalid contract: %a" Contract_hash.pp contract + | Some rank -> cctxt#message "%d" rank + in + return_unit); + command + ~group + ~desc:"Get cache contract size." + no_options + (prefixes ["get"; "cache"; "contract"; "size"] @@ stop) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* t = + contract_cache_size cctxt ~chain:cctxt#chain ~block:cctxt#block + in + let*! () = cctxt#message "%d" t in + return_unit); + command + ~group + ~desc:"Get cache contract size limit." + no_options + (prefixes ["get"; "cache"; "contract"; "size"; "limit"] @@ stop) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* t = + contract_cache_size_limit cctxt ~chain:cctxt#chain ~block:cctxt#block + in + let*! () = cctxt#message "%d" t in + return_unit); + command + ~group + ~desc:"Get the liquid balance of a contract." + no_options + (prefixes ["get"; "balance"; "for"] + @@ Contract_alias.destination_param ~name:"src" ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* amount = + get_balance cctxt ~chain:cctxt#chain ~block:cctxt#block contract + in + let*! () = + cctxt#answer "%a %s" Tez.pp amount Operation_result.tez_sym + in + return_unit); + command + ~group + ~desc:"Get the staked balance of a contract." + no_options + (prefixes ["get"; "staked"; "balance"; "for"] + @@ Contract_alias.destination_param ~name:"src" ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* amount = + get_staked_balance + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + let amount = Option.value ~default:Tez.zero amount in + let*! () = + cctxt#answer "%a %s" Tez.pp amount Operation_result.tez_sym + in + return_unit); + command + ~group + ~desc:"Get the full balance of a contract." + no_options + (prefixes ["get"; "full"; "balance"; "for"] + @@ Contract_alias.destination_param ~name:"src" ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* amount = + get_full_balance cctxt ~chain:cctxt#chain ~block:cctxt#block contract + in + let*! () = + cctxt#answer "%a %s" Tez.pp amount Operation_result.tez_sym + in + return_unit); + command + ~group + ~desc:"Get the storage of a contract." + (args1 (unparsing_mode_arg ~default:"Readable")) + (prefixes ["get"; "contract"; "storage"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun unparsing_mode contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* v = + get_storage + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~unparsing_mode + contract + in + check_smart_contract cctxt v @@ fun storage -> + let*! () = + cctxt#answer "%a" Michelson_v1_printer.print_expr_unwrapped storage + in + return_unit); + command + ~group + ~desc:"Get the used storage space of a contract." + no_options + (prefixes ["get"; "contract"; "used"; "storage"; "space"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* used_space = + get_used_storage_space + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + check_smart_contract cctxt used_space @@ fun used_space -> + let*! () = cctxt#answer "%a" Z.pp_print used_space in + return_unit); + command + ~group + ~desc:"Get the paid storage space of a contract." + no_options + (prefixes ["get"; "contract"; "paid"; "storage"; "space"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* paid_space = + get_paid_storage_space + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + check_smart_contract cctxt paid_space @@ fun paid_space -> + let*! () = cctxt#answer "%a" Z.pp_print paid_space in + return_unit); + command + ~group + ~desc: + "Get the value associated to a key in the big map storage of a \ + contract (deprecated)." + no_options + (prefixes ["get"; "big"; "map"; "value"; "for"] + @@ Tezos_clic.param ~name:"key" ~desc:"the key to look for" data_parameter + @@ prefixes ["of"; "type"] + @@ Tezos_clic.param ~name:"type" ~desc:"type of the key" data_parameter + @@ prefix "in" + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun () key key_type contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* v = + get_contract_big_map_value + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + (key.expanded, key_type.expanded) + in + match v with + | None -> cctxt#error "No value associated to this key." + | Some value -> + let*! () = + cctxt#answer "%a" Michelson_v1_printer.print_expr_unwrapped value + in + return_unit); + command + ~group + ~desc:"Get a value in a big map." + (args1 (unparsing_mode_arg ~default:"Readable")) + (prefixes ["get"; "element"] + @@ Tezos_clic.param + ~name:"key" + ~desc:"the key to look for" + (Tezos_clic.parameter (fun _ s -> + Lwt_result_syntax.return (Script_expr_hash.of_b58check_exn s))) + @@ prefixes ["of"; "big"; "map"] + @@ Tezos_clic.param + ~name:"big_map" + ~desc:"identifier of the big_map" + int_parameter + @@ stop) + (fun unparsing_mode key id (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* value = + get_big_map_value + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~unparsing_mode + (Big_map.Id.parse_z (Z.of_int id)) + key + in + let*! () = + cctxt#answer "%a" Michelson_v1_printer.print_expr_unwrapped value + in + return_unit); + command + ~group + ~desc:"Get the code of a contract." + (args2 (unparsing_mode_arg ~default:"Readable") normalize_types_switch) + (prefixes ["get"; "contract"; "code"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun (unparsing_mode, normalize_types) + contract + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* v = + get_script + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~unparsing_mode + ~normalize_types + contract + in + check_smart_contract cctxt v @@ fun {code; storage = _} -> + match Script_repr.force_decode code with + | Error errs -> cctxt#error "%a" Environment.Error_monad.pp_trace errs + | Ok code -> + let {Michelson_v1_parser.source; _} = + Michelson_v1_printer.unparse_toplevel code + in + let*! () = cctxt#answer "%s" source in + return_unit); + command + ~group + ~desc:"Get the `BLAKE2B` script hash of a contract." + no_options + (prefixes ["get"; "contract"; "script"; "hash"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_syntax in + let* r = + get_script_hash cctxt ~chain:cctxt#chain ~block:cctxt#block contract + in + match r with + | Error errs -> cctxt#error "%a" pp_print_trace errs + | Ok hash -> + check_smart_contract cctxt hash @@ fun hash -> + let* () = cctxt#answer "%a" Script_expr_hash.pp hash in + return_ok_unit); + command + ~group + ~desc:"Get the type of an entrypoint of a contract." + (args1 normalize_types_switch) + (prefixes ["get"; "contract"; "entrypoint"; "type"; "of"] + @@ Tezos_clic.param + ~name:"entrypoint" + ~desc:"the entrypoint to describe" + entrypoint_parameter + @@ prefixes ["for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun normalize_types + entrypoint + contract + (cctxt : Protocol_client_context.full) -> + let open Lwt_syntax in + let* t = + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~entrypoint + ~normalize_types + in + Michelson_v1_entrypoints.print_entrypoint_type + cctxt + ~emacs:false + ~contract + ~entrypoint + t); + command + ~group + ~desc:"Get the entrypoint list of a contract." + (args1 normalize_types_switch) + (prefixes ["get"; "contract"; "entrypoints"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun normalize_types contract (cctxt : Protocol_client_context.full) -> + let open Lwt_syntax in + let* es = + Michelson_v1_entrypoints.list_contract_entrypoints + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~normalize_types + in + Michelson_v1_entrypoints.print_entrypoints_list + cctxt + ~emacs:false + ~contract + es); + command + ~group + ~desc:"Get the list of unreachable paths in a contract's parameter type." + no_options + (prefixes ["get"; "contract"; "unreachable"; "paths"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_syntax in + let* u = + Michelson_v1_entrypoints.list_contract_unreachables + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + in + Michelson_v1_entrypoints.print_unreachables + cctxt + ~emacs:false + ~contract + u); + command + ~group + ~desc:"Get the delegate of a contract." + no_options + (prefixes ["get"; "delegate"; "for"] + @@ Contract_alias.destination_param ~name:"src" ~desc:"source contract" + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* v = + Client_proto_contracts.get_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + match v with + | None -> + let*! () = cctxt#message "none" in + return_unit + | Some delegate -> + let* mn = Public_key_hash.rev_find cctxt delegate in + let* m = Public_key_hash.to_source delegate in + let*! () = + cctxt#message + "%s (%s)" + m + (match mn with None -> "unknown" | Some n -> "known as " ^ n) + in + return_unit); + command + ~group + ~desc: + "Get contract's balance of ticket with specified ticketer, content \ + type, and content." + no_options + (prefixes ["get"; "ticket"; "balance"; "for"] + @@ Destination_alias.destination_param ~name:"src" ~desc:"Source address." + @@ prefixes ["with"; "ticketer"] + @@ Contract_alias.destination_param + ~name:"ticketer" + ~desc:"Ticketer contract of the ticket." + @@ prefixes ["and"; "type"] + @@ Tezos_clic.param + ~name:"ticket content type" + ~desc:"Type of the content of the ticket." + data_parameter + @@ prefixes ["and"; "content"] + @@ Tezos_clic.param + ~name:"ticket content" + ~desc:"Content of the ticket." + data_parameter + @@ stop) + (fun () destination ticketer content_type content cctxt -> + let open Lwt_result_syntax in + let* balance = + match destination with + | Contract contract -> + get_contract_ticket_balance + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + Ticket_token. + { + ticketer; + contents_type = content_type.expanded; + contents = content.expanded; + } + | Sc_rollup smart_rollup -> + get_smart_rollup_ticket_balance + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + smart_rollup + Ticket_token. + { + ticketer; + contents_type = content_type.expanded; + contents = content.expanded; + } + | _ -> + cctxt#error + "Invalid address, must be a contract or smart rollup address" + in + let*! () = cctxt#answer "%a" Z.pp_print balance in + return_unit); + command + ~group + ~desc:"Get the complete list of tickets owned by a given contract." + no_options + (prefixes ["get"; "all"; "ticket"; "balances"; "for"] + @@ Originated_contract_alias.destination_param + ~name:"src" + ~desc:"Source contract." + @@ stop) + (fun () contract (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* ticket_balances = + get_contract_all_ticket_balances + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + contract + in + let pp_ticket_balance ppf + (Ticket_token.{ticketer; contents_type; contents}, amount) = + Format.fprintf + ppf + "@[Ticketer: %a@,Content type: %a@,Content: %a@,Amount: %a@]" + Contract.pp + ticketer + Michelson_v1_printer.print_expr + contents_type + Michelson_v1_printer.print_expr + contents + Z.pp_print + amount + in + let*! () = + cctxt#answer + "%a" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt "@.@.") + pp_ticket_balance) + ticket_balances + in + return_unit); + command + ~desc:"Get receipt for past operation" + (args1 + (default_arg + ~long:"check-previous" + ~placeholder:"num_blocks" + ~doc:"number of previous blocks to check" + ~default:"10" + (non_negative_parameter ()))) + (prefixes ["get"; "receipt"; "for"] + @@ param + ~name:"operation" + ~desc:"Operation to be looked up" + (parameter (fun (cctxt : #Client_context.full) x -> + match Operation_hash.of_b58check_opt x with + | None -> cctxt#error "Invalid operation hash: '%s'" x + | Some hash -> Lwt_result_syntax.return hash)) + @@ stop) + (fun predecessors operation_hash (ctxt : Protocol_client_context.full) -> + display_receipt_for_operation + ctxt + ~chain:ctxt#chain + ~predecessors + operation_hash); + command + ~group + ~desc:"Summarize the current voting period" + no_options + (fixed ["show"; "voting"; "period"]) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* info = + get_period_info ~chain:cctxt#chain ~block:cctxt#block cctxt + in + let*! () = + cctxt#message + "Current period: %a\nBlocks remaining until end of period: %ld" + Data_encoding.Json.pp + (Data_encoding.Json.construct + Alpha_context.Voting_period.kind_encoding + info.current_period_kind) + info.remaining + in + let* known_protos = Shell_services.Protocol.list cctxt in + let* props = + get_proposals ~chain:cctxt#chain ~block:cctxt#block cctxt + in + let ranks = + Environment.Protocol_hash.Map.bindings props + |> List.sort (fun (_, v1) (_, v2) -> Int64.(compare v2 v1)) + in + let print_proposal = function + | None -> + cctxt#message "The current proposal has already been cleared." + (* The proposal is cleared on the last block of adoption period, and + also on the last block of the exploration and promotion + periods when the proposal is not approved *) + | Some proposal -> + cctxt#message "Current proposal: %a" Protocol_hash.pp proposal + in + match info.current_period_kind with + | Proposal -> + (* the current proposals are cleared on the last block of the + proposal period *) + let*! () = + if info.remaining <> 0l then + cctxt#answer + "Current proposals:%t" + Format.( + fun ppf -> + pp_print_cut ppf () ; + pp_open_vbox ppf 0 ; + List.iter + (fun (p, w) -> + fprintf + ppf + "* %a %a %s (%sknown by the node)@." + Protocol_hash.pp + p + Tez.pp + (Tez.of_mutez_exn w) + Operation_result.tez_sym + (if + List.mem ~equal:Protocol_hash.equal p known_protos + then "" + else "not ")) + ranks ; + pp_close_box ppf ()) + else cctxt#message "The proposals have already been cleared." + in + return_unit + | Exploration | Promotion -> + let*! () = print_proposal info.current_proposal in + (* the ballots are cleared on the last block of these periods *) + if info.remaining <> 0l then + let* ballots_info = + get_ballots_info ~chain:cctxt#chain ~block:cctxt#block cctxt + in + let*! () = + cctxt#answer + "@[Ballots:@,\ + \ Yay: %a %s@,\ + \ Nay: %a %s@,\ + \ Pass: %a %s@,\ + Current participation %.2f%%, necessary quorum %.2f%%@,\ + Current in favor %a %s, needed supermajority %a %s@]" + Tez.pp + (Tez.of_mutez_exn ballots_info.ballots.yay) + Operation_result.tez_sym + Tez.pp + (Tez.of_mutez_exn ballots_info.ballots.nay) + Operation_result.tez_sym + Tez.pp + (Tez.of_mutez_exn ballots_info.ballots.pass) + Operation_result.tez_sym + (Int32.to_float ballots_info.participation /. 100.) + (Int32.to_float ballots_info.current_quorum /. 100.) + Tez.pp + (Tez.of_mutez_exn ballots_info.ballots.yay) + Operation_result.tez_sym + Tez.pp + (Tez.of_mutez_exn ballots_info.supermajority) + Operation_result.tez_sym + in + return_unit + else + let*! () = + cctxt#message "The ballots have already been cleared." + in + return_unit + | Cooldown -> + let*! () = print_proposal info.current_proposal in + return_unit + | Adoption -> + let*! () = print_proposal info.current_proposal in + return_unit); + command + ~group:binary_description + ~desc:"Describe unsigned block header" + no_options + (fixed ["describe"; "unsigned"; "block"; "header"]) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let*! () = + cctxt#message + "%a" + Data_encoding.Binary_schema.pp + (Data_encoding.Binary.describe + Alpha_context.Block_header.unsigned_encoding) + in + return_unit); + command + ~group:binary_description + ~desc:"Describe unsigned operation" + no_options + (fixed ["describe"; "unsigned"; "operation"]) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let*! () = + cctxt#message + "%a" + Data_encoding.Binary_schema.pp + (Data_encoding.Binary.describe + Alpha_context.Operation.unsigned_encoding) + in + return_unit); + command + ~group + ~desc:"Get the frozen deposits limit of a delegate." + no_options + (prefixes ["get"; "deposits"; "limit"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source delegate" + @@ stop) + (fun () delegate (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* deposit = + get_frozen_deposits_limit + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + delegate + in + let*! () = + match deposit with + | None -> cctxt#answer "unlimited" + | Some limit -> + cctxt#answer "%a %s" Tez.pp limit Operation_result.tez_sym + in + return_unit); + ] + +(* ----------------------------------------------------------------------------*) +(* After the activation of a new version of the protocol, the older protocols + are only kept in the code base to replay the history of the chain and to query + old states. + + The commands that are not useful anymore in the old protocols are removed, + this is called protocol freezing. The commands below are those that can be + removed during protocol freezing. + + The rule of thumb to know if a command should be kept at freezing is that all + commands that modify the state of the chain should be removed and conversely + all commands that are used to query the context should be kept. For this + reason, we call read-only (or RO for short) the commands that are kept and + read-write (or RW for short) the commands that are removed. + + There are some exceptions to this rule however, for example the command + "octez-client wait for to be included" is classified as RW despite having + no effect on the context because it has no use case once all RW commands are + removed. + + Keeping this in mind, the developer should decide where to add a new command. + At the end of the file, RO and RW commands are concatenated into one list that + is then exported in the mli file. *) +(* ----------------------------------------------------------------------------*) + +let dry_run_switch = + Tezos_clic.switch + ~long:"dry-run" + ~short:'D' + ~doc:"don't inject the operation, just display it" + () + +let verbose_signing_switch = + Tezos_clic.switch + ~long:"verbose-signing" + ~doc:"display extra information before signing the operation" + () + +let simulate_switch = + Tezos_clic.switch + ~long:"simulation" + ~doc: + "Simulate the execution of the command, without needing any signatures." + () + +let force_switch = + Tezos_clic.switch + ~long:"force" + ~doc: + "Inject the operation even if the simulation results in a failure. This \ + switch requires --gas-limit, --storage-limit, and --fee." + () + +let transfer_command amount (source : Contract.t) destination + (cctxt : #Client_context.printer) + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level ) = + let open Lwt_result_syntax in + (* When --force is used we want to inject the transfer even if it fails. + In that case we cannot rely on simulation to compute limits and fees + so we require the corresponding options to be set. *) + let check_force_dependency name = function + | None -> + cctxt#error + "When the --force switch is used, the %s option is required." + name + | _ -> Lwt.return_unit + in + let*! () = + if force && not simulation then + let*! () = check_force_dependency "--gas-limit" gas_limit in + let*! () = check_force_dependency "--storage-limit" storage_limit in + check_force_dependency "--fee" fee + else Lwt.return_unit + in + let*! r = + match source with + | Originated contract_hash -> + let contract = source in + let* source = + Managed_contract.get_contract_manager cctxt contract_hash + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + Managed_contract.transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~simulation + ~force + ~fee_parameter + ?fee + ~contract + ~source + ~src_pk + ~src_sk + ~destination + ?entrypoint + ?arg + ~amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + | Implicit source -> + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~simulation + ~force + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~destination + ?entrypoint + ?arg + ~amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~replace_by_fees + ~successor_level + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + r + in + return_unit + +let prepare_batch_operation cctxt ?arg ?fee ?gas_limit ?storage_limit + ?entrypoint (source : Contract.t) index batch = + let open Lwt_result_syntax in + let* destination = + Client_proto_contracts.Contract_alias.find_destination + cctxt + batch.destination + in + let* amount = tez_of_string_exn cctxt index "amount" batch.amount in + let* batch_fee = tez_of_opt_string_exn cctxt index "fee" batch.fee in + let fee = Option.either batch_fee fee in + let arg = Option.either batch.arg arg in + let gas_limit = Option.either batch.gas_limit gas_limit in + let storage_limit = Option.either batch.storage_limit storage_limit in + let entrypoint = Option.either batch.entrypoint entrypoint in + let* parameters = parse_arg_transfer arg in + let* operation = + match source with + | Originated _ -> + Managed_contract.build_transaction_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract:source + ~destination + ?entrypoint + ?arg + ~amount + ?fee + ?gas_limit + ?storage_limit + () + | Implicit _ -> + return + (build_transaction_operation + ~amount + ~parameters + ?entrypoint + ?fee + ?gas_limit + ?storage_limit + destination) + in + return (Annotated_manager_operation.Annotated_manager_operation operation) + +let commands_network network () = + let open Tezos_clic in + match network with + | Some `Testnet | None -> + [ + command + ~group + ~desc:"Register and activate an Alphanet/Zeronet faucet account." + (args2 (Secret_key.force_switch ()) encrypted_switch) + (prefixes ["activate"; "account"] + @@ Secret_key.fresh_alias_param @@ prefixes ["with"] + @@ Client_proto_args.json_encoded_param + ~name:"activation_key" + ~desc: + "Activate an Alphanet/Zeronet faucet account from the JSON \ + (file or directly inlined)." + Client_proto_context.activation_key_encoding + @@ stop) + (fun (force, encrypted) name activation_key cctxt -> + let open Lwt_result_syntax in + let* name = Secret_key.of_fresh cctxt force name in + let* _res = + activate_account + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~encrypted + ~force + activation_key + name + in + return_unit); + ] + | Some `Mainnet -> + [ + command + ~group + ~desc:"Activate a fundraiser account." + (args1 dry_run_switch) + (prefixes ["activate"; "fundraiser"; "account"] + @@ Public_key_hash.alias_param @@ prefixes ["with"] + @@ param + ~name:"code" + (Tezos_clic.parameter (fun (cctxt : #Client_context.full) code -> + match + Blinded_public_key_hash.activation_code_of_hex code + with + | Some c -> Lwt_result_syntax.return c + | None -> cctxt#error "Hexadecimal parsing failure")) + ~desc:"Activation code obtained from the Tezos foundation." + @@ stop) + (fun dry_run (name, _pkh) code cctxt -> + let open Lwt_result_syntax in + let* _res = + activate_existing_account + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + name + code + in + return_unit); + ] + +let commands_rw () = + let open Client_proto_programs in + let open Tezos_micheline in + let open Tezos_clic in + [ + command + ~group + ~desc:"Set the delegate of a contract." + (args5 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args) + (prefixes ["set"; "delegate"; "for"] + @@ Contract_alias.destination_param ~name:"src" ~desc:"source contract" + @@ prefix "to" + @@ Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the contract" + @@ stop) + (fun (fee, dry_run, verbose_signing, simulation, fee_parameter) + contract + delegate + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + match contract with + | Originated contract -> + let* source = + Managed_contract.get_contract_manager cctxt contract + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + Managed_contract.set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~simulation + ~fee_parameter + ?fee + ~source + ~src_pk + ~src_sk + contract + (Some delegate) + in + let*! (_ : + (Operation_hash.t + * _ contents + * _ Apply_results.contents_result) + option) = + report_michelson_errors + ~no_print_source:true + ~msg:"Setting delegate through entrypoints failed." + cctxt + errors + in + return_unit + | Implicit mgr -> + let* _, src_pk, manager_sk = Client_keys.get_key cctxt mgr in + let* (_ : _ Injection.result) = + set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~simulation + ~fee_parameter + ?fee + mgr + (Some delegate) + ~src_pk + ~manager_sk + in + return_unit); + command + ~group + ~desc:"Withdraw the delegate from a contract." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["withdraw"; "delegate"; "from"] + @@ Contract_alias.destination_param ~name:"src" ~desc:"source contract" + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) + contract + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + match contract with + | Originated contract -> + let* source = + Managed_contract.get_contract_manager cctxt contract + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + Managed_contract.set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ?fee + ~source + ~src_pk + ~src_sk + contract + None + in + let*! (_ : _ Injection.result option) = + report_michelson_errors + ~no_print_source:true + ~msg:"Withdrawing delegate through entrypoints failed." + cctxt + errors + in + return_unit + | Implicit mgr -> + let* _, src_pk, manager_sk = Client_keys.get_key cctxt mgr in + let*! (_ : _ Injection.result tzresult) = + set_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + mgr + None + ?fee + ~src_pk + ~manager_sk + in + return_unit); + command + ~group + ~desc:"Launch a smart contract on the blockchain." + (args11 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + delegate_arg + (Client_keys.force_switch ()) + init_arg + no_print_source_flag + fee_parameter_args) + (prefixes ["originate"; "contract"] + @@ Raw_contract_alias.fresh_alias_param + ~name:"new" + ~desc:"name of the new contract" + @@ prefix "transferring" + @@ tez_param ~name:"qty" ~desc:"amount taken from source" + @@ prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "running" + @@ Program.source_param + ~name:"prg" + ~desc: + "script of the account\n\ + Combine with -init if the storage type is not unit." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + delegate, + force, + initial_storage, + no_print_source, + fee_parameter ) + alias_name + balance + source + program + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* alias_name = Raw_contract_alias.of_fresh cctxt force alias_name in + let* {expanded = code; _} = + Lwt.return (Micheline_parser.no_parsing_error program) + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + originate_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ~delegate + ~initial_storage + ~balance + ~source + ~src_pk + ~src_sk + ~code + ~fee_parameter + () + in + let*! o = + report_michelson_errors + ~no_print_source + ~msg:"origination simulation failed" + cctxt + errors + in + match o with + | None -> return_unit + | Some (_res, contract) -> + if dry_run then return_unit + else save_contract ~force cctxt alias_name contract); + command + ~group + ~desc: + "Execute multiple transfers from a single source account.\n\ + If one of the transfers fails, none of them get executed." + (args14 + default_fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + default_gas_limit_arg + safety_guard_arg + default_storage_limit_arg + counter_arg + default_arg_arg + no_print_source_flag + fee_parameter_args + default_entrypoint_arg + replace_by_fees_arg) + (prefixes ["multiple"; "transfers"; "from"] + @@ Contract_alias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "using" + @@ json_encoded_param + ~name:"transfers.json" + ~desc: + "List of operations originating from the source contract in JSON \ + format (from a file or directly inlined). The input JSON must be \ + an array of objects of the form: '[ {\"destination\": dst, \ + \"amount\": qty (, : ...) } (, ...) ]', where an \ + optional can either be \"fee\", \"gas-limit\", \ + \"storage-limit\", \"arg\", or \"entrypoint\"." + ~pp_error:(fun json fmt exn -> + match (json, exn) with + | `A lj, Data_encoding.Json.Cannot_destruct ([`Index n], exn) -> + Format.fprintf + fmt + "Invalid transfer at index %i: %a %a" + n + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + (Format.pp_print_option Data_encoding.Json.pp) + (List.nth_opt lj n) + | _, (Data_encoding.Json.Cannot_destruct _ as exn) -> + Format.fprintf + fmt + "Invalid transfer file: %a %a" + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + Data_encoding.Json.pp + json + | _, exn -> raise exn + (* this case can't happen because only `Cannot_destruct` error are + given to this pp *)) + (Data_encoding.list + Client_proto_context.batch_transfer_operation_encoding) + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees ) + source + operations + cctxt -> + (* When --force is used we want to inject the transfer even if it fails. + In that case we cannot rely on simulation to compute limits and fees + so we require the corresponding options to be set. *) + let open Lwt_result_syntax in + let check_force_dependency name = function + | None -> + cctxt#error + "When the --force switch is used, the %s option is required." + name + | _ -> Lwt.return_unit + in + let*! () = + if force && not simulation then + let*! () = check_force_dependency "--gas-limit" gas_limit in + let*! () = check_force_dependency "--storage-limit" storage_limit in + check_force_dependency "--fee" fee + else Lwt.return_unit + in + let prepare i = + prepare_batch_operation + cctxt + ?arg + ?fee + ?gas_limit + ?storage_limit + ?entrypoint + source + i + in + match operations with + | [] -> cctxt#error "Empty operation list" + | operations -> + let* source = + match source with + | Originated contract -> + Managed_contract.get_contract_manager cctxt contract + | Implicit source -> return source + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* contents = List.mapi_ep prepare operations in + let (Manager_list contents) = + Annotated_manager_operation.manager_of_list contents + in + let*! errors = + Injection.inject_manager_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~simulation + ~force + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ?safety_guard + ?counter + ~src_pk + ~src_sk + ~replace_by_fees + ~fee_parameter + contents + in + let*! (_ : + (Operation_hash.t + * packed_operation + * _ contents_list + * _ Apply_results.contents_result_list) + option) = + report_michelson_errors + ~no_print_source + ~msg:"multiple transfers simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Execute an Epoxy origination operation.\n" + (args14 + force_switch + default_fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + default_gas_limit_arg + safety_guard_arg + default_storage_limit_arg + counter_arg + default_arg_arg + no_print_source_flag + fee_parameter_args + default_entrypoint_arg + replace_by_fees_arg) + (prefixes ["originate"; "epoxy"] + @@ Epoxy_alias.fresh_alias_param + ~name:"epoxy" + ~desc:"Fresh name for an Epoxy rollup" + @@ prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "public_parameters" + @@ param + ~name:"public_parameters" + ~desc:"public_parameters" + Zk_rollup_params.plonk_public_parameters_parameter + @@ prefix "init_state" + @@ param + ~name:"init_state" + ~desc:"init_state" + Zk_rollup_params.state_parameter + @@ prefix "circuits_info" + @@ param + ~name:"circuits_info" + ~desc:"circuits_info" + Zk_rollup_params.circuits_info_parameter + @@ prefix "nb_ops" + @@ param ~name:"nb_ops" ~desc:"nb_ops" int_parameter + @@ stop) + (fun ( force, + fee, + dry_run, + verbose_signing, + simulation, + gas_limit, + safety_guard, + storage_limit, + counter, + _arg, + _no_print_source, + fee_parameter, + _entrypoint, + _replace_by_fees ) + alias + source + public_parameters + init_state + circuits_info + nb_ops + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _, _, res = + zk_rollup_originate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~public_parameters + ~circuits_info + ~init_state + ~nb_ops + () + in + let*? res = + match res with + | Apply_results.Manager_operation_result + { + operation_result = + Apply_operation_result.Applied + (Apply_results.Zk_rollup_origination_result + {originated_zk_rollup; _}); + _; + } -> + Ok originated_zk_rollup + | _ -> error_with "Epoxy rollup was not correctly originated" + in + let* alias_name = Epoxy_alias.of_fresh cctxt force alias in + save_zk_rollup ~force cctxt alias_name res); + command + ~group + ~desc:"Execute an Epoxy publish operation.\n" + (args13 + default_fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + default_gas_limit_arg + safety_guard_arg + default_storage_limit_arg + counter_arg + default_arg_arg + no_print_source_flag + fee_parameter_args + default_entrypoint_arg + replace_by_fees_arg) + (prefixes ["epoxy"; "publish"; "from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "rollup" + @@ param ~name:"rollup" ~desc:"rollup" Zk_rollup_params.address_parameter + @@ prefix "ops" + @@ param ~name:"ops" ~desc:"ops" Zk_rollup_params.operations_parameter + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + gas_limit, + safety_guard, + storage_limit, + counter, + _arg, + _no_print_source, + fee_parameter, + _entrypoint, + _replace_by_fees ) + source + zk_rollup + ops + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + zk_rollup_publish + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~zk_rollup + ~ops + () + in + return_unit); + command + ~group + ~desc:"Execute an Epoxy update operation.\n" + (args13 + default_fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + default_gas_limit_arg + safety_guard_arg + default_storage_limit_arg + counter_arg + default_arg_arg + no_print_source_flag + fee_parameter_args + default_entrypoint_arg + replace_by_fees_arg) + (prefixes ["epoxy"; "update"; "from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "rollup" + @@ param ~name:"rollup" ~desc:"rollup" Zk_rollup_params.address_parameter + @@ prefix "update" + @@ param ~name:"update" ~desc:"update" Zk_rollup_params.update_parameter + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + gas_limit, + safety_guard, + storage_limit, + counter, + _arg, + _no_print_source, + fee_parameter, + _entrypoint, + _replace_by_fees ) + source + zk_rollup + update + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + zk_rollup_update + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~zk_rollup + ~update + () + in + return_unit); + command + ~group + ~desc:"Transfer tokens / call a smart contract." + (args15 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + arg_arg + no_print_source_flag + fee_parameter_args + entrypoint_arg + replace_by_fees_arg + successor_level_arg) + (prefixes ["transfer"] + @@ tez_param ~name:"qty" ~desc:"amount taken from source" + @@ prefix "from" + @@ Contract_alias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefix "to" + @@ Contract_alias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level ) + amount + source + destination + cctxt -> + transfer_command + amount + source + destination + cctxt + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level )); + command + ~group + ~desc:"Register a global constant" + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args + storage_limit_arg + counter_arg) + (prefixes ["register"; "global"; "constant"] + @@ global_constant_param + ~name:"expression" + ~desc: + "Michelson expression to register. Note the value is not \ + typechecked before registration." + @@ prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the account registering the global constant" + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + fee_parameter, + storage_limit, + counter ) + global_constant_str + source + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + register_global_constant + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~constant:global_constant_str + () + in + let*! (_ : _ Injection.result option) = + report_michelson_errors + ~no_print_source:false + ~msg:"register global constant simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Call a smart contract (same as 'transfer 0')." + (args15 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + arg_arg + no_print_source_flag + fee_parameter_args + entrypoint_arg + replace_by_fees_arg + successor_level_arg) + (prefixes ["call"] + @@ Contract_alias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ prefix "from" + @@ Contract_alias.destination_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level ) + destination + source + cctxt -> + let amount = Tez.zero in + transfer_command + amount + source + destination + cctxt + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level )); + command + ~group + ~desc: + "Stake the given amount for the source. The source must be a delegator \ + to be allowed to stake." + (args13 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + replace_by_fees_arg + successor_level_arg) + (prefix "stake" + @@ tez_param ~name:"qty" ~desc:"amount staked from source" + @@ prefix "for" + @@ Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter, + replace_by_fees, + successor_level ) + amount + source + cctxt -> + let contract = Contract.Implicit source in + let arg = None in + let entrypoint = Some Entrypoint.stake in + (* TODO #6162 + (unless --force) + - check contract is delegated + - check amount is positive + - check contract is a baker if AI is not enabled *) + transfer_command + amount + contract + contract + cctxt + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level )); + command + ~group + ~desc: + "Unstake the given amount. If \"everything\" is given as amount, \ + unstakes everything from the staking balance. Unstaked tez remains \ + frozen for a set amount of cycles (the slashing period) after the \ + operation. Once this period is over, the operation \"finalize \ + unstake\" must be called for the funds to appear in the liquid \ + balance." + (args13 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + replace_by_fees_arg + successor_level_arg) + (prefix "unstake" + @@ everything_or_tez_param + ~name:"qty" + ~desc:"amount to unstake from source" + @@ prefix "for" + @@ Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter, + replace_by_fees, + successor_level ) + amount + source + cctxt -> + let contract = Contract.Implicit source in + let entrypoint = Some Entrypoint.unstake in + (* TODO #6162 + (unless --force) + - check contract is delegated + - check contract has stake + - check amount is positive + - check contract is a baker if AI is not enabled + - print a warning if effective stake is lower *) + transfer_command + amount + contract + contract + cctxt + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + None, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level )); + command + ~group + ~desc: + "Transfer all the finalizable unstaked funds of the source to their \ + liquid balance." + (args13 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + replace_by_fees_arg + successor_level_arg) + (prefixes ["finalize"; "unstake"] + @@ prefix "for" + @@ Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter, + replace_by_fees, + successor_level ) + source + cctxt -> + let contract = Contract.Implicit source in + let arg = None in + let amount = Tez.zero in + let entrypoint = Some Entrypoint.finalize_unstake in + (* TODO #6162 + (unless --force) + - check contract has finalizable unstake requests + *) + transfer_command + amount + contract + contract + cctxt + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level )); + command + ~group + ~desc:"Set delegate parameters" + (args15 + limit_of_staking_over_baking_millionth_arg + edge_of_baking_over_staking_billionth_arg + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + force_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + replace_by_fees_arg + successor_level_arg) + (prefixes ["set"; "delegate"; "parameters"; "for"] + @@ Public_key_hash.source_param ~name:"src" ~desc:"name of the delegate" + @@ stop) + (fun ( limit_of_staking_over_baking_millionth_opt, + edge_of_baking_over_staking_billionth_opt, + fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter, + replace_by_fees, + successor_level ) + source + cctxt -> + let open Lwt_result_syntax in + let* limit_of_staking_over_baking_millionth = + match limit_of_staking_over_baking_millionth_opt with + | None -> + cctxt#error + "The --limit-of-staking-over-baking argument is mandatory" + | Some x -> return x + in + let* edge_of_baking_over_staking_billionth = + match edge_of_baking_over_staking_billionth_opt with + | None -> + cctxt#error + "The --edge-of-baking-over-staking argument is mandatory" + | Some x -> return x + in + let contract = Contract.Implicit source in + let arg = + (* Is there a better way? *) + Some + (Format.sprintf + "Pair %d %d Unit" + limit_of_staking_over_baking_millionth + edge_of_baking_over_staking_billionth) + in + let amount = Tez.zero in + let entrypoint = Some Entrypoint.set_delegate_parameters in + (* TODO #6162 + (unless --force) + - check contract is a baker + *) + transfer_command + amount + contract + contract + cctxt + ( fee, + dry_run, + verbose_signing, + simulation, + force, + gas_limit, + safety_guard, + storage_limit, + counter, + arg, + no_print_source, + fee_parameter, + entrypoint, + replace_by_fees, + successor_level )); + command + ~group + ~desc:"Reveal the public key of the contract manager." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["reveal"; "key"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) source cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + reveal + cctxt + ~dry_run + ~verbose_signing + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~source + ?fee + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + command + ~group + ~desc:"Register the public key hash as a delegate." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["register"; "key"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["as"; "delegate"] + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) src_pkh cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt src_pkh in + let*! r = + register_as_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~fee_parameter + ~verbose_signing + ?fee + ~manager_sk:src_sk + src_pk + in + match r with + | Ok _ -> return_unit + | Error + [ + Environment.Ecoproto_error + Delegate_storage.Contract.Active_delegate; + ] -> + let*! () = cctxt#message "Delegate already activated." in + return_unit + | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Register the public key hash as a delegate." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["register"; "key"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["as"; "delegate"; "with"; "consensus"; "key"] + @@ Public_key.source_param ~name:"key" ~desc:"the consensus key" + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) + src_pkh + (name_pk, consensus_pk) + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt src_pkh in + let* consensus_pk = + match consensus_pk with + | Some pk -> return pk + | None -> Client_keys.public_key name_pk + in + let*! r = + register_as_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~fee_parameter + ~verbose_signing + ?fee + ~manager_sk:src_sk + ~consensus_pk + src_pk + in + match r with + | Ok _ -> return_unit + | Error + [ + Environment.Ecoproto_error + Delegate_storage.Contract.Active_delegate; + ] -> + let*! () = cctxt#message "Delegate already activated." in + return_unit + | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Update the consensus key of a delegate." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["set"; "consensus"; "key"; "for"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["to"] + @@ Public_key.source_param ~name:"key" ~desc:"the consensus key" + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) + delegate_pkh + (name_pk, consensus_pk) + cctxt -> + let open Lwt_result_syntax in + let* _, delegate_pk, delegate_sk = + Client_keys.get_key cctxt delegate_pkh + in + let* consensus_pk = + match consensus_pk with + | Some pk -> return pk + | None -> Client_keys.public_key name_pk + in + let*! r = + update_consensus_key + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~fee_parameter + ~verbose_signing + ?fee + ~consensus_pk + ~manager_sk:delegate_sk + delegate_pk + in + match r with Ok _ -> return_unit | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Drain all funds from a delegate." + (args2 dry_run_switch verbose_signing_switch) + (prefixes ["drain"; "delegate"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["to"] + @@ Public_key_hash.source_param ~name:"dest" ~desc:"the consensus key" + @@ stop) + (fun (dry_run, verbose_signing) delegate_pkh consensus_pkh cctxt -> + let open Lwt_result_syntax in + let* _, _consensus_pk, consensus_sk = + Client_keys.get_key cctxt consensus_pkh + in + let*! r = + drain_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~consensus_pkh + ~consensus_sk + ~delegate:delegate_pkh + () + in + match r with Ok _ -> return_unit | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Drain all funds from a delegate." + (args2 dry_run_switch verbose_signing_switch) + (prefixes ["drain"; "delegate"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["to"] + @@ Public_key_hash.source_param ~name:"dest" ~desc:"the destination key" + @@ prefixes ["with"] + @@ Public_key_hash.source_param + ~name:"consensus_key" + ~desc:"the consensus key" + @@ stop) + (fun (dry_run, verbose_signing) + delegate_pkh + destination_pkh + consensus_pkh + cctxt -> + let open Lwt_result_syntax in + let* _, _consensus_pk, consensus_sk = + Client_keys.get_key cctxt consensus_pkh + in + let*! r = + drain_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~consensus_pkh + ~consensus_sk + ~destination:destination_pkh + ~delegate:delegate_pkh + () + in + match r with Ok _ -> return_unit | Error el -> Lwt.return_error el); + command + ~desc:"Wait until an operation is included in a block" + (args3 + (default_arg + ~long:"confirmations" + ~placeholder:"num_blocks" + ~doc: + "wait until 'N' additional blocks after the operation appears in \ + the considered chain" + ~default:"0" + (non_negative_parameter ())) + (default_arg + ~long:"check-previous" + ~placeholder:"num_blocks" + ~doc:"number of previous blocks to check" + ~default:"10" + (non_negative_parameter ())) + (arg + ~long:"branch" + ~placeholder:"block_hash" + ~doc: + "hash of the oldest block where we should look for the operation" + block_hash_param)) + (prefixes ["wait"; "for"] + @@ param + ~name:"operation" + ~desc:"Operation to be included" + (parameter (fun (cctxt : #Client_context.full) x -> + match Operation_hash.of_b58check_opt x with + | None -> cctxt#error "Invalid operation hash: '%s'" x + | Some hash -> Lwt_result_syntax.return hash)) + @@ prefixes ["to"; "be"; "included"] + @@ stop) + (fun (confirmations, predecessors, branch) + operation_hash + (ctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* (_ : Block_hash.t * int * int) = + Client_confirmations.wait_for_operation_inclusion + ctxt + ~chain:ctxt#chain + ~confirmations + ~predecessors + ?branch + operation_hash + in + return_unit); + command + ~group + ~desc:"Submit protocol proposals" + (args3 + dry_run_switch + verbose_signing_switch + (switch + ~doc: + "Do not fail when the checks that try to prevent the user from \ + shooting themselves in the foot do fail." + ~long:"force" + ())) + (prefixes ["submit"; "proposals"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"delegate" + ~desc:"the delegate who makes the proposal" + @@ seq_of_param + (param + ~name:"proposal" + ~desc:"the protocol hash proposal to be submitted" + (parameter (fun (cctxt : #Client_context.full) x -> + match Protocol_hash.of_b58check_opt x with + | None -> cctxt#error "Invalid proposal hash: '%s'" x + | Some hash -> Lwt_result_syntax.return hash)))) + (fun (dry_run, verbose_signing, force) + src_pkh + proposals + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* src_name, _src_pk, src_sk = Client_keys.get_key cctxt src_pkh in + let* info = + get_period_info + (* Find period info of the successor, because the operation will + be injected on the next block at the earliest *) + ~successor:true + ~chain:cctxt#chain + ~block:cctxt#block + cctxt + in + let*! () = + match info.current_period_kind with + | Proposal -> Lwt.return_unit + | _ -> + (if force then cctxt#warning else cctxt#error) + "Not in a proposal period" + in + let* known_protos = Shell_services.Protocol.list cctxt in + let* known_proposals = + get_proposals ~chain:cctxt#chain ~block:cctxt#block cctxt + in + let* has_voting_power = + let*! r = + Alpha_services.Delegate.voting_power + cctxt + (cctxt#chain, cctxt#block) + src_pkh + in + match r with + | Ok voting_power -> return (voting_power <> 0L) + | Error + (Environment.Ecoproto_error (Delegate_services.Not_registered _) + :: _) -> + return false + | Error _ as err -> Lwt.return err + in + (* for a proposal to be valid it must either a protocol that was already + proposed by somebody else or a protocol known by the node, because + the user is the first proposer and just injected it with + tezos-admin-client *) + let check_proposals proposals : bool tzresult Lwt.t = + let errors = ref [] in + let error ppf = + Format.kasprintf (fun s -> errors := s :: !errors) ppf + in + if proposals = [] then error "Empty proposal list." ; + if + Compare.List_length_with.( + proposals > Constants.max_proposals_per_delegate) + then + error + "Too many proposals: %d > %d." + (List.length proposals) + Constants.max_proposals_per_delegate ; + (match + Base.List.find_all_dups ~compare:Protocol_hash.compare proposals + with + | [] -> () + | dups -> + error + "There %s: %a." + (if Compare.List_length_with.(dups = 1) then + "is a duplicate proposal" + else "are duplicate proposals") + Format.( + pp_print_list + ~pp_sep:(fun ppf () -> pp_print_string ppf ", ") + Protocol_hash.pp) + dups) ; + List.iter + (fun (p : Protocol_hash.t) -> + if + List.mem ~equal:Protocol_hash.equal p known_protos + || Environment.Protocol_hash.Map.mem p known_proposals + then () + else + error "Protocol %a is not a known proposal." Protocol_hash.pp p) + proposals ; + if not has_voting_power then + error + "Public-key-hash `%a` from account `%s` does not appear to have \ + voting rights." + Signature.Public_key_hash.pp + src_pkh + src_name ; + if !errors <> [] then + let*! () = + cctxt#message + "There %s with the submission:%t" + (if Compare.List_length_with.(!errors = 1) then "is an issue" + else "are issues") + Format.( + fun ppf -> + pp_print_cut ppf () ; + pp_open_vbox ppf 0 ; + List.iter + (fun msg -> + pp_open_hovbox ppf 2 ; + pp_print_string ppf "* " ; + pp_print_text ppf msg ; + pp_close_box ppf () ; + pp_print_cut ppf ()) + !errors ; + pp_close_box ppf ()) + in + return_false + else return_true + in + let* all_valid = check_proposals proposals in + let*! () = + if all_valid then cctxt#message "All proposals are valid." + else if force then + cctxt#message + "Some proposals are not valid, but `--force` was used." + else cctxt#error "Submission failed because of invalid proposals." + in + let*! r = + submit_proposals + ~dry_run + ~verbose_signing + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~src_sk + src_pkh + proposals + in + match r with + | Ok _res -> return_unit + | Error errs -> + let*! () = + match errs with + | [ + Unregistered_error + (`O [("kind", `String "generic"); ("error", `String msg)]); + ] -> + cctxt#message + "Error:@[@.%a@]" + Format.pp_print_text + (String.split_on_char ' ' msg + |> List.filter (function "" | "\n" -> false | _ -> true) + |> String.concat " " + |> String.map (function '\n' | '\t' -> ' ' | c -> c)) + | el -> cctxt#message "Error:@ %a" pp_print_trace el + in + cctxt#error "Failed to submit proposals"); + command + ~group + ~desc:"Submit a ballot" + (args3 + verbose_signing_switch + dry_run_switch + (switch + ~doc: + "Do not fail when the checks that try to prevent the user from \ + shooting themselves in the foot do fail." + ~long:"force" + ())) + (prefixes ["submit"; "ballot"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"delegate" + ~desc:"the delegate who votes" + @@ param + ~name:"proposal" + ~desc:"the protocol hash proposal to vote for" + (parameter (fun (cctxt : #Client_context.full) x -> + match Protocol_hash.of_b58check_opt x with + | None -> cctxt#error "Invalid proposal hash: '%s'" x + | Some hash -> Lwt_result_syntax.return hash)) + @@ param + ~name:"ballot" + ~desc: + "the ballot value (yea, nay, or pass; yay is a deprecated synonym \ + for yea)" + (parameter + ~autocomplete:(fun _ -> + Lwt_result_syntax.return ["yea"; "nay"; "pass"]) + (fun (cctxt : #Client_context.full) s -> + let open Lwt_result_syntax in + (* We should have [Vote.of_string]. *) + match String.lowercase_ascii s with + | "yay" | "yea" -> return Vote.Yay + | "nay" -> return Vote.Nay + | "pass" -> return Vote.Pass + | s -> cctxt#error "Invalid ballot: '%s'" s)) + @@ stop) + (fun (verbose_signing, dry_run, force) + src_pkh + proposal + ballot + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* src_name, _src_pk, src_sk = Client_keys.get_key cctxt src_pkh in + let* info = + get_period_info + (* Find period info of the successor, because the operation will + be injected on the next block at the earliest *) + ~successor:true + ~chain:cctxt#chain + ~block:cctxt#block + cctxt + in + let* current_proposal = + Alpha_services.Voting.current_proposal cctxt (cctxt#chain, cctxt#block) + in + let* () = + match (info.current_period_kind, current_proposal) with + | (Exploration | Promotion), Some current_proposal -> + if Protocol_hash.equal proposal current_proposal then return_unit + else + let*! () = + (if force then cctxt#warning else cctxt#error) + "Unexpected proposal, expected: %a" + Protocol_hash.pp + current_proposal + in + return_unit + | _ -> + let*! () = + (if force then cctxt#warning else cctxt#error) + "Not in Exploration or Promotion period" + in + return_unit + in + let* has_voting_power = + let*! r = + Alpha_services.Delegate.voting_power + cctxt + (cctxt#chain, cctxt#block) + src_pkh + in + match r with + | Ok voting_power -> return (voting_power <> 0L) + | Error + (Environment.Ecoproto_error (Delegate_services.Not_registered _) + :: _) -> + return false + | Error _ as err -> Lwt.return err + in + let*! () = + if has_voting_power then Lwt.return_unit + else + (if force then cctxt#warning else cctxt#error) + "Public-key-hash `%a` from account `%s` does not appear to have \ + voting rights." + Signature.Public_key_hash.pp + src_pkh + src_name + in + let* _res = + submit_ballot + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~src_sk + src_pkh + ~verbose_signing + ~dry_run + proposal + ballot + in + return_unit); + command + ~group + ~desc:"Set the deposits limit of a registered delegate." + (args5 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args) + (prefixes ["set"; "deposits"; "limit"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source contract" + @@ prefix "to" + @@ tez_param + ~name:"deposits limit" + ~desc:"the maximum amount of frozen deposits" + @@ stop) + (fun (fee, dry_run, verbose_signing, simulation, fee_parameter) + mgr + limit + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, manager_sk = Client_keys.get_key cctxt mgr in + let* (_ : _ Injection.result) = + set_deposits_limit + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~simulation + ~fee_parameter + ?fee + mgr + ~src_pk + ~manager_sk + (Some limit) + in + return_unit); + command + ~group + ~desc:"Remove the deposits limit of a registered delegate." + (args5 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args) + (prefixes ["unset"; "deposits"; "limit"; "for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source contract" + @@ stop) + (fun (fee, dry_run, verbose_signing, simulation, fee_parameter) + mgr + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, manager_sk = Client_keys.get_key cctxt mgr in + let* (_ : _ Injection.result) = + set_deposits_limit + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~simulation + ~fee_parameter + ?fee + mgr + ~src_pk + ~manager_sk + None + in + return_unit); + command + ~group + ~desc:"Increase the paid storage of a smart contract." + (args6 + force_switch + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args) + (prefixes ["increase"; "the"; "paid"; "storage"; "of"] + @@ Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"name of the smart contract" + @@ prefix "by" + @@ non_negative_z_param ~name:"amount" ~desc:"amount of increase in bytes" + @@ prefixes ["bytes"; "from"] + @@ Public_key_hash.source_param + ~name:"payer" + ~desc:"payer of the storage increase" + @@ stop) + (fun (force, fee, dry_run, verbose_signing, simulation, fee_parameter) + contract + amount_in_bytes + payer + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, manager_sk = Client_keys.get_key cctxt payer in + let* (_ : _ Injection.result) = + increase_paid_storage + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~force + ~dry_run + ~verbose_signing + ?fee + ?confirmations:cctxt#confirmations + ~simulation + ~source:payer + ~src_pk + ~manager_sk + ~destination:contract + ~fee_parameter + ~amount_in_bytes + () + in + return_unit); + command + ~group + ~desc: + "Transfer tickets from an implicit account to a contract or another \ + implicit account." + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args + storage_limit_arg + counter_arg) + (prefix "transfer" + @@ non_negative_z_param ~name:"qty" ~desc:"Amount of tickets to transfer." + @@ prefixes ["tickets"; "from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"tickets owner" + ~desc:"Implicit account owning the tickets." + @@ prefix "to" + @@ Contract_alias.destination_param + ~name:"recipient contract" + ~desc:"Contract receiving the tickets." + @@ prefixes ["with"; "entrypoint"] + @@ Tezos_clic.param + ~name:"entrypoint" + ~desc: + "Entrypoint to use on the receiving contract or implicit account. \ + Needs to be \"default\" for implicit account destinations." + entrypoint_parameter + @@ prefixes ["and"; "contents"] + @@ Tezos_clic.param + ~name:"tickets content" + ~desc:"Content of the tickets." + Client_proto_args.string_parameter + @@ prefixes ["and"; "type"] + @@ Tezos_clic.param + ~name:"tickets type" + ~desc:"Type of the tickets." + Client_proto_args.string_parameter + @@ prefixes ["and"; "ticketer"] + @@ Contract_alias.destination_param + ~name:"tickets ticketer" + ~desc:"Ticketer contract of the tickets." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + fee_parameter, + storage_limit, + counter ) + amount + source + destination + entrypoint + contents + ty + ticketer + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + match Ticket_amount.of_zint amount with + | Some amount -> + let* _res = + transfer_ticket + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~contents + ~ty + ~ticketer + ~amount + ~destination + ~entrypoint + () + in + return_unit + | None -> cctxt#error "ticket quantity should not be zero or negative"); + command + ~group + ~desc:"Originate a new smart rollup." + (args9 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args + storage_limit_arg + counter_arg + (Client_keys.force_switch ()) + whitelist_arg) + (prefixes ["originate"; "smart"; "rollup"] + @@ Smart_rollup_alias.Address.fresh_alias_param + ~name:"alias" + ~desc:"name of the new smart rollup" + @@ prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"Name of the account originating the smart rollup." + @@ prefixes ["of"; "kind"] + @@ param + ~name:"smart_rollup_kind" + ~desc:"Kind of the smart rollup to be originated." + Sc_rollup_params.rollup_kind_parameter + @@ prefixes ["of"; "type"] + @@ param + ~name:"parameters_type" + ~desc: + "The interface of the smart rollup including its entrypoints and \ + their signatures." + data_parameter + @@ prefixes ["with"; "kernel"] + @@ param + ~name:"kernel" + ~desc:"The kernel for the smart rollup." + Sc_rollup_params.boot_sector_parameter + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + fee_parameter, + storage_limit, + counter, + force, + whitelist ) + alias + source + kind + parameters_ty + boot_sector + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let (Packed (module R) as pvm) = Sc_rollup.Kind.pvm_of kind in + let Michelson_v1_parser.{expanded; _} = parameters_ty in + let parameters_ty = Script.lazy_expr expanded in + let* boot_sector = boot_sector pvm in + let* _, _, res = + sc_rollup_originate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~kind + ~boot_sector + ~parameters_ty + ?whitelist + () + in + match res with + | Apply_results.Manager_operation_result + { + operation_result = + Apply_operation_result.Applied + (Apply_results.Sc_rollup_originate_result + {address = rollup_address; _}); + _; + } -> + if dry_run then return_unit + else + let* alias = + Smart_rollup_alias.Address.of_fresh cctxt force alias + in + let* () = + Smart_rollup_alias.Address.add ~force cctxt alias rollup_address + in + let*! () = + cctxt#message + {|Smart rollup %a memorized as "%s"|} + Sc_rollup.Address.pp + rollup_address + alias + in + return_unit + | _ -> return_unit); + command + ~group + ~desc:"Send one or more messages to a smart rollup." + (args9 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg) + (prefixes ["send"; "smart"; "rollup"; "message"] + @@ param + ~name:"messages" + ~desc: + "The message(s) to be sent to the rollup (syntax: \ + bin:|text:|hex:|file:)." + Sc_rollup_params.messages_parameter + @@ prefixes ["from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"Name of the source contract." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + fee_parameter, + gas_limit, + safety_guard, + storage_limit, + counter ) + messages + source + cctxt -> + let open Lwt_result_syntax in + let* messages = + match messages with + | `Bin message -> return [message] + | `Json messages -> ( + match Data_encoding.(Json.destruct (list string) messages) with + | exception _ -> + cctxt#error + "Could not read list of messages (expected list of bytes)" + | "raw" :: messages -> return messages + | "hex" :: messages -> + let* messages = + List.map_es + (fun message -> + match Hex.to_string (`Hex message) with + | None -> + cctxt#error + "'%s' is not a valid hex encoded message" + message + | Some msg -> return [msg]) + messages + in + return @@ List.flatten messages + | _messages -> assert false) + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + sc_rollup_add_messages + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?dry_run:(Some dry_run) + ?verbose_signing:(Some verbose_signing) + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~messages + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + command + ~group + ~desc:"Publish a commitment for a smart rollup" + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + storage_limit_arg + counter_arg + fee_parameter_args) + (prefixes ["publish"; "commitment"] + @@ prefixes ["from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"Name of the source contract." + @@ prefixes ["for"; "smart"; "rollup"] + @@ Smart_rollup_alias.Address.param + ~desc: + "The address of the smart rollup where the commitment will be \ + published." + @@ prefixes ["with"; "compressed"; "state"] + @@ param + ~name:"compressed_state" + ~desc:"The compressed state of the smart rollup for the commitment." + Sc_rollup_params.compressed_state_parameter + @@ prefixes ["at"; "inbox"; "level"] + @@ param + ~name:"inbox_level" + ~desc:"The inbox level for the commitment." + (raw_level_parameter ()) + @@ prefixes ["and"; "predecessor"] + @@ param + ~name:"predecessor" + ~desc:"The hash of the commitment's predecessor" + Sc_rollup_params.commitment_hash_parameter + @@ prefixes ["and"; "number"; "of"; "ticks"] + @@ param + ~name:"number_of_ticks" + ~desc:"The number of ticks for the commitment." + Sc_rollup_params.number_of_ticks_parameter + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + storage_limit, + counter, + fee_parameter ) + source + rollup + compressed_state + inbox_level + predecessor + number_of_ticks + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let commitment : Alpha_context.Sc_rollup.Commitment.t = + {compressed_state; inbox_level; predecessor; number_of_ticks} + in + let* _res = + sc_rollup_publish + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~rollup + ~commitment + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + command + ~group + ~desc:"Cement a commitment for a smart rollup." + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + storage_limit_arg + counter_arg + fee_parameter_args) + (prefixes ["cement"; "commitment"] + @@ prefixes ["from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"Name of the source contract." + @@ prefixes ["for"; "smart"; "rollup"] + @@ Smart_rollup_alias.Address.param + ~desc: + "The address of the smart rollup of which the commitment will be \ + cemented." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + storage_limit, + counter, + fee_parameter ) + source + rollup + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + sc_rollup_cement + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~rollup + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + command + ~group + ~desc:"Timeout a staker from dispute on a smart rollup." + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + storage_limit_arg + counter_arg + fee_parameter_args) + (prefixes ["timeout"; "dispute"; "on"; "smart"; "rollup"] + @@ Smart_rollup_alias.Address.param + ~desc: + "The address of the smart rollup where the staker of the dispute \ + has timed-out." + @@ prefixes ["with"] + @@ Client_keys.Public_key_hash.source_param + ~name:"staker1" + ~desc:"The staker that has timed out." + @@ prefixes ["against"] + @@ Client_keys.Public_key_hash.source_param + ~name:"staker2" + ~desc:"The opponent of this staker." + @@ prefixes ["from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"Name of the source contract." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + storage_limit, + counter, + fee_parameter ) + rollup + staker1 + staker2 + source + cctxt -> + let open Lwt_result_syntax in + let* games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, cctxt#block) + rollup + staker1 + in + let* alice, bob = + let* answer = + List.find_es + (fun (_, alice, bob) -> + let stakers = Sc_rollup.Game.Index.make staker1 staker2 in + return + Signature.Public_key_hash.( + alice = stakers.alice && bob = stakers.bob)) + games + in + match answer with + | None -> + cctxt#error + "Couldn't find an ongoing dispute for this staker on this \ + rollup." + | Some (_, alice, bob) -> return (alice, bob) + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + sc_rollup_timeout + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~rollup + ~alice + ~bob + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + command + ~group + ~desc:"List originated smart rollups." + no_options + (prefixes ["list"; "smart"; "rollups"] @@ stop) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* rollups = + Plugin.RPC.Sc_rollup.list cctxt (cctxt#chain, cctxt#block) + in + let*! () = + List.iter_s + (fun addr -> + cctxt#message "%s" (Sc_rollup.Address.to_b58check addr)) + rollups + in + return_unit); + command + ~group + ~desc: + "Execute a message from a smart rollup's outbox of a cemented \ + commitment." + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args + storage_limit_arg + counter_arg) + (prefixes ["execute"; "outbox"; "message"; "of"; "smart"; "rollup"] + @@ Smart_rollup_alias.Address.param + ~desc:"The address of the smart rollup where the message resides." + @@ prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"source" + ~desc:"The account used for executing the outbox message." + @@ prefixes ["for"; "commitment"; "hash"] + @@ param + ~name:"cemented commitment" + ~desc:"The hash of the cemented commitment of the rollup." + Sc_rollup_params.commitment_hash_parameter + @@ prefixes ["and"; "output"; "proof"] + @@ param + ~name:"output proof" + ~desc: + "The output proof containing the outbox level, index and message." + bytes_parameter + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + fee_parameter, + storage_limit, + counter ) + rollup + source + cemented_commitment + output_proof + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + sc_rollup_execute_outbox_message + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~rollup + ~cemented_commitment + ~output_proof:(Bytes.to_string output_proof) + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + command + ~group + ~desc:"Recover commitment bond from a smart rollup." + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + fee_parameter_args + storage_limit_arg + counter_arg) + (prefixes ["recover"; "bond"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"staker" + ~desc:"The implicit account that owns the frozen bond." + @@ prefixes ["for"; "smart"; "rollup"] + @@ Smart_rollup_alias.Address.param + ~desc:"The address of the smart rollup of the bond." + @@ prefixes ["from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"The implicit account that triggers the operation." + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + fee_parameter, + storage_limit, + counter ) + staker + sc_rollup + source + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* _res = + sc_rollup_recover_bond + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~src_pk + ~src_sk + ~fee_parameter + ~sc_rollup + ~staker + () + in + return_unit); + command + ~group + ~desc:"Precompute timelock tuple." + (args1 timelock_locked_value_arg) + (prefixes ["timelock"; "precompute"] + @@ prefix "for" + @@ param ~name:"time" ~desc:" timelock difficulty" int_parameter + @@ prefix "in" + @@ param ~name:"file" ~desc:" updates dir" string_parameter + @@ stop) + (fun locked (time : int) (timelock_path : string) cctxt -> + let open Lwt_result_syntax in + let open Tezos_crypto.Timelock in + let* locked_value = + match locked with + | None -> return_none + | Some l -> + let locked_option = to_locked_value_opt l in + if Option.is_none locked_option then + let*! () = + cctxt#warning + "%s" + "Locked value not in RSA group, using its residue." + in + return_some @@ to_locked_value_unsafe l + else return locked_option + in + let _ = + precompute_timelock + ~locked_value + ~precompute_path:(Some timelock_path) + ~time + () + in + let*! () = + cctxt#message "%s" "Timelock tuple precomputed and saved locally." + in + return_unit); + command + ~group + ~desc:"Generate timelock chest." + no_options + (prefixes ["timelock"; "create"] + @@ prefix "for" + @@ param ~name:"time" ~desc:" timelock difficulty" int_parameter + @@ prefix "with" + @@ param ~name:"payload" ~desc:" timelock message" bytes_parameter + @@ prefix "in" + @@ param ~name:"file" ~desc:" updates dir" string_parameter + @@ stop) + (fun () (time : int) (payload : bytes) (timelock_path : string) cctxt -> + let open Lwt_result_syntax in + let open Tezos_crypto.Timelock in + let chest, chest_key = + create_chest_and_chest_key + ~precompute_path:(Some timelock_path) + ~payload + ~time + () + in + let chest_name = + get_timelock_filename timelock_path "time_chest" chest_encoding chest + in + let chest_key_name = + get_timelock_filename + timelock_path + "time_key_create" + chest_encoding + chest + in + let*! () = write_encoding chest_name chest_encoding chest in + let*! () = write_encoding chest_key_name chest_key_encoding chest_key in + let*! () = + cctxt#message "%s" "Timelock chest and chest_key computed." + in + return_unit); + command + ~group + ~desc:"Open timelock chest." + no_options + (prefixes ["timelock"; "open"] + @@ prefix "for" + @@ param ~name:"time" ~desc:" timelock difficulty" int_parameter + @@ prefix "chest" + @@ param ~name:"chest" ~desc:" timelock chest" string_parameter + @@ prefix "in" + @@ param ~name:"file" ~desc:" updates dir" string_parameter + @@ stop) + (fun () (time : int) (chest_path : string) (timelock_path : string) cctxt -> + let open Lwt_result_syntax in + let open Tezos_crypto.Timelock in + let* chest = read_encoding chest_path chest_encoding in + let chest_key = create_chest_key chest ~time in + let chest_key_name = + get_timelock_filename + timelock_path + "time_key_open" + chest_encoding + chest + in + let*! () = write_encoding chest_key_name chest_key_encoding chest_key in + let*! () = cctxt#message "%s" "Timelock chest_key computed." in + return_unit); + command + ~group + ~desc:"Verify timelock chest." + no_options + (prefixes ["timelock"; "verify"] + @@ prefix "for" + @@ param ~name:"time" ~desc:" timelock difficulty" int_parameter + @@ prefix "chest" + @@ param ~name:"chest" ~desc:" timelock chest" string_parameter + @@ prefix "chest_key" + @@ param ~name:"chest_key" ~desc:" timelock chest's key" string_parameter + @@ stop) + (fun () (time : int) (chest_path : string) (chest_key_path : string) cctxt -> + let open Lwt_result_syntax in + let open Tezos_crypto.Timelock in + let* chest = read_encoding chest_path chest_encoding in + let* chest_key = read_encoding chest_key_path chest_key_encoding in + let result = open_chest chest chest_key ~time in + let*! () = + match result with + | Correct msg -> + let m = Hex.of_bytes msg |> Hex.show in + cctxt#message "Timelock chest verified, message is: %s" m + | Bogus_opening -> + cctxt#error "Error opening: incorrect proof or unlocked value." + in + return_unit); + command + ~group + ~desc:"Publish a DAL commitment on L1 for the given slot index" + (args7 + fee_arg + dry_run_switch + verbose_signing_switch + simulate_switch + storage_limit_arg + counter_arg + fee_parameter_args) + (prefixes ["publish"; "dal"; "commitment"] + @@ param + ~name:"commitment" + ~desc:"The DAL commitment to publish." + Dal.commitment_parameter + @@ prefixes ["from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"Name of the source contract." + @@ prefixes ["for"; "slot"] + @@ param + ~name:"DAL slot index" + ~desc:"The index of the DAL slot." + int_parameter + @@ prefixes ["with"; "proof"] + @@ param + ~name:"commitment proof" + ~desc:"The proof of the DAL commitment to publish." + Dal.commitment_proof_parameter + @@ stop) + (fun ( fee, + dry_run, + verbose_signing, + simulation, + storage_limit, + counter, + fee_parameter ) + commitment + source + slot_index + commitment_proof + cctxt -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* {parametric = {dal = {number_of_slots; _}; _}; _} = + Alpha_services.Constants.all cctxt (cctxt#chain, `Head 0) + in + let* slot_index = + match + Alpha_context.Dal.Slot_index.of_int ~number_of_slots slot_index + with + | Ok i -> return i + | Error err -> + cctxt#error + "Bad slot index: %a. A slot index should be in the interval \ + [0;%d]." + Environment.Error_monad.pp_trace + err + (number_of_slots - 1) + in + let slot_header = + Alpha_context.Dal.Operations.Publish_commitment. + {slot_index; commitment; commitment_proof} + in + let* _res = + dal_publish + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~dry_run + ~verbose_signing + ?fee + ?storage_limit + ?counter + ?confirmations:cctxt#confirmations + ~simulation + ~source + ~slot_header + ~src_pk + ~src_sk + ~fee_parameter + () + in + return_unit); + ] + +let commands network () = + commands_rw () @ commands_network network () @ commands_ro () diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_contracts_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_contracts_commands.ml new file mode 100644 index 000000000000..56b7bd6b0399 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_contracts_commands.ml @@ -0,0 +1,98 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Client_proto_contracts + +let group = + { + Tezos_clic.name = "contracts"; + title = "Commands for managing the record of known contracts"; + } + +let commands () = + let open Tezos_clic in + [ + command + ~group + ~desc:"Add a contract to the wallet." + (args1 (Raw_contract_alias.force_switch ())) + (prefixes ["remember"; "contract"] + @@ Raw_contract_alias.fresh_alias_param @@ Raw_contract_alias.source_param + @@ stop) + (fun force name hash cctxt -> + let open Lwt_result_syntax in + let* name = Raw_contract_alias.of_fresh cctxt force name in + Raw_contract_alias.add ~force cctxt name hash); + command + ~group + ~desc:"Remove a contract from the wallet." + no_options + (prefixes ["forget"; "contract"] @@ Raw_contract_alias.alias_param @@ stop) + (fun () (name, _) cctxt -> Raw_contract_alias.del cctxt name); + command + ~group + ~desc:"Lists all known contracts in the wallet." + no_options + (fixed ["list"; "known"; "contracts"]) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* contracts = list_contracts cctxt in + let*! () = + List.iter_s + (fun (prefix, alias, contract) -> + cctxt#message + "%s%s: %s" + prefix + alias + (Contract.to_b58check contract)) + contracts + in + return_unit); + command + ~group + ~desc:"Forget the entire wallet of known contracts." + (args1 (Raw_contract_alias.force_switch ())) + (fixed ["forget"; "all"; "contracts"]) + (fun force cctxt -> + let open Lwt_result_syntax in + let* () = + fail_unless + force + (error_of_fmt "this can only used with option -force") + in + Raw_contract_alias.set cctxt []); + command + ~group + ~desc:"Display a contract from the wallet." + no_options + (prefixes ["show"; "known"; "contract"] + @@ Raw_contract_alias.alias_param @@ stop) + (fun () (_, contract) (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let*! () = cctxt#message "%a\n%!" Contract.pp contract in + return_unit); + ] diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_fa12_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_fa12_commands.ml new file mode 100644 index 000000000000..1fc0301f70c5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_fa12_commands.ml @@ -0,0 +1,709 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Client_proto_args + +let group = + { + Tezos_clic.name = "tokens"; + title = "Commands for managing FA1.2-compatible smart contracts"; + } + +let alias_param = Client_proto_contracts.Contract_alias.destination_param + +let implicit_alias_param = Client_keys.Public_key_hash.source_param + +let token_contract_param () = + Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"name or address of the FA1.2-compatible contract" + +let from_implicit_param () = + implicit_alias_param ~name:"from" ~desc:"name or address of the sender" + +let from_param () = + alias_param ~name:"from" ~desc:"name or address of the sender" + +let to_param () = alias_param ~name:"to" ~desc:"name or address of the receiver" + +let amount_param () = + Tezos_clic.param + ~name:"amount" + ~desc:"number of tokens" + (Tezos_clic.parameter (fun (cctxt : #Client_context.full) s -> + try + let v = Z.of_string s in + assert (Compare.Z.(v >= Z.zero)) ; + Lwt_result_syntax.return v + with _ -> + cctxt#error "invalid amount (must be a non-negative number)")) + +let tez_amount_arg = + tez_arg ~default:"0" ~parameter:"tez-amount" ~doc:"amount in \xEA\x9C\xA9" + +let implicit_as_arg = + Client_keys.Public_key_hash.source_arg + ~long:"as" + ~doc:"name or address of the caller of the contract" + () + +let payer_arg = + Client_keys.Public_key_hash.source_arg + ~long:"payer" + ~doc:"name of the payer (i.e. SOURCE) contract for the transaction" + () + +let callback_entrypoint_arg = + Tezos_clic.arg + ~doc:"Entrypoint the view should use to callback to" + ~long:"callback-entrypoint" + ~placeholder:"name" + string_parameter + +let contract_call_options = + Tezos_clic.args10 + tez_amount_arg + fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + +let contract_view_options = + Tezos_clic.args11 + callback_entrypoint_arg + tez_amount_arg + fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + +let view_options = + Tezos_clic.args3 + run_gas_limit_arg + payer_arg + (unparsing_mode_arg ~default:"Readable") + +let dummy_callback = Contract.Implicit Signature.Public_key_hash.zero + +let get_contract_caller_keys (cctxt : #Client_context.full) source = + let open Lwt_result_syntax in + let* _, caller_pk, caller_sk = Client_keys.get_key cctxt source in + return (source, caller_pk, caller_sk) + +let commands_ro () : #Protocol_client_context.full Tezos_clic.command list = + Tezos_clic. + [ + command + ~group + ~desc:"Check that a contract is FA1.2-compatible." + no_options + (prefixes ["check"; "contract"] + @@ token_contract_param () + @@ prefixes ["implements"; "fa1.2"] + @@ stop) + (fun () contract (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _ = + Client_proto_fa12.contract_has_fa12_interface + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + () + in + Format.printf + "Contract %a has an FA1.2 interface.\n%!" + Contract_hash.pp + contract ; + return_unit); + command + ~group + ~desc:"Ask for an address's balance offchain" + view_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () + @@ prefixes ["get"; "balance"; "for"] + @@ alias_param + ~name:"from" + ~desc: + "name or address of the account to lookup (also the source \ + contract)" + @@ stop) + (fun (gas, payer, unparsing_mode) + contract + addr + (cctxt : #Protocol_client_context.full) -> + let open Lwt_syntax in + let action = + Client_proto_fa12.Get_balance (addr, (dummy_callback, None)) + in + let* res = + Client_proto_fa12.run_view_action + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ~sender:(Some addr) + ~gas + ~payer + ~unparsing_mode + () + in + Client_proto_programs.print_view_result cctxt res); + command + ~group + ~desc:"Ask for an address's allowance offchain" + view_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () + @@ prefixes ["get"; "allowance"; "on"] + @@ alias_param + ~name:"owner" + ~desc:"name or address of the account giving the allowance" + @@ prefix "as" + @@ alias_param + ~name:"operator" + ~desc:"name or address of the account receiving the allowance" + @@ stop) + (fun (gas, payer, unparsing_mode) + contract + sender + destination + (cctxt : #Protocol_client_context.full) -> + let open Lwt_syntax in + let action = + Client_proto_fa12.Get_allowance + (sender, destination, (dummy_callback, None)) + in + let* res = + Client_proto_fa12.run_view_action + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ~sender:(Some sender) + ~gas + ~payer + ~unparsing_mode + () + in + Client_proto_programs.print_view_result cctxt res); + command + ~group + ~desc:"Ask for the contract's total token supply offchain" + view_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () + @@ prefixes ["get"; "total"; "supply"] + @@ stop) + (fun (gas, payer, unparsing_mode) + contract + (cctxt : #Protocol_client_context.full) -> + let open Lwt_syntax in + let action = + Client_proto_fa12.Get_total_supply (dummy_callback, None) + in + let* res = + Client_proto_fa12.run_view_action + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~sender:None + ~contract + ~action + ~gas + ~payer + ~unparsing_mode + () + in + Client_proto_programs.print_view_result cctxt res); + command + ~group + ~desc:"Ask for an address's balance using a callback contract" + contract_view_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () + @@ prefixes ["get"; "balance"; "for"] + @@ implicit_alias_param + ~name:"from" + ~desc: + "name or address of the account to lookup (also the source \ + contract)" + @@ prefixes ["callback"; "on"] + @@ alias_param + ~name:"callback" + ~desc:"name or address of the callback contract" + @@ stop) + (fun ( callback_entrypoint, + tez_amount, + fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + contract + addr + callback + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* source, src_pk, src_sk = get_contract_caller_keys cctxt addr in + let action = + Client_proto_fa12.Get_balance + (Implicit addr, (callback, callback_entrypoint)) + in + let*! errors = + Client_proto_fa12.call_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ~source + ~src_pk + ~src_sk + ~tez_amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + () + in + let*! _ = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Ask for an address's allowance using a callback contract" + contract_view_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () + @@ prefixes ["get"; "allowance"; "on"] + @@ implicit_alias_param + ~name:"from" + ~desc:"name or address of the account giving the allowance" + @@ prefix "as" + @@ alias_param + ~name:"to" + ~desc:"name or address of the account receiving the allowance" + @@ prefixes ["callback"; "on"] + @@ alias_param + ~name:"callback" + ~desc:"name or address of the callback contract" + @@ stop) + (fun ( callback_entrypoint, + tez_amount, + fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + contract + src + dst + callback + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* source, src_pk, src_sk = get_contract_caller_keys cctxt src in + let action = + Client_proto_fa12.Get_allowance + (Implicit src, dst, (callback, callback_entrypoint)) + in + let*! errors = + Client_proto_fa12.call_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ~source + ~src_pk + ~src_sk + ~tez_amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + () + in + let*! _ = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc: + "Ask for a contract's total token supply using a callback contract" + contract_view_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () + @@ prefixes ["get"; "total"; "supply"; "as"] + @@ implicit_alias_param + ~name:"from" + ~desc:"name or address of the source account" + @@ prefixes ["callback"; "on"] + @@ alias_param + ~name:"callback" + ~desc:"name or address of the callback contract" + @@ stop) + (fun ( callback_entrypoint, + tez_amount, + fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + contract + addr + callback + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* source, src_pk, src_sk = get_contract_caller_keys cctxt addr in + let action = + Client_proto_fa12.Get_total_supply (callback, callback_entrypoint) + in + let*! errors = + Client_proto_fa12.call_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ~source + ~src_pk + ~src_sk + ~tez_amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + () + in + let*! _ = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + ] + +let commands_rw () : #Protocol_client_context.full Tezos_clic.command list = + let open Client_proto_args in + Tezos_clic. + [ + command + ~group + ~desc:"Transfer tokens between two given accounts" + (Tezos_clic.args11 + implicit_as_arg + tez_amount_arg + fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + gas_limit_arg + safety_guard_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args) + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () @@ prefix "transfer" @@ amount_param () + @@ prefix "from" @@ from_implicit_param () @@ prefix "to" @@ to_param () + @@ stop) + (fun ( as_address, + tez_amount, + fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + contract + amount + src + dst + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let caller = Option.value ~default:src as_address in + let* source, caller_pk, caller_sk = + get_contract_caller_keys cctxt caller + in + let action = Client_proto_fa12.Transfer (Implicit src, dst, amount) in + let*! errors = + Client_proto_fa12.call_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ~source + ~src_pk:caller_pk + ~src_sk:caller_sk + ~tez_amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + () + in + let*! _ = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Allow account to transfer an amount of token" + contract_call_options + (prefixes ["from"; "fa1.2"; "contract"] + @@ token_contract_param () @@ prefix "as" + @@ implicit_alias_param ~name:"as" ~desc:"name or address of the sender" + @@ prefix "approve" @@ amount_param () @@ prefix "from" + @@ alias_param + ~name:"from" + ~desc:"name or address to approve withdrawal" + @@ stop) + (fun ( tez_amount, + fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + contract + source + amount + dst + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* source, src_pk, src_sk = get_contract_caller_keys cctxt source in + let action = Client_proto_fa12.Approve (dst, amount) in + let*! errors = + Client_proto_fa12.call_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~action + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ?fee + ~source + ~src_pk + ~src_sk + ~tez_amount + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + ~fee_parameter + () + in + let*! _ = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc: + "Execute multiple token transfers from a single source account. If \ + one of the token transfers fails, none of them are executed." + (args10 + default_fee_arg + implicit_as_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + default_gas_limit_arg + safety_guard_arg + default_storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args) + (prefixes ["multiple"; "fa1.2"; "transfers"; "from"] + @@ implicit_alias_param + ~name:"src" + ~desc:"name or address of the source of the transfers" + @@ prefix "using" + @@ json_encoded_param + ~name:"transfers" + ~desc: + (Format.sprintf + "List of token transfers to inject from the source contract \ + in JSON format (as a file or string). The JSON must be an \ + array of objects of the form: '[ {\"token_contract\": \ + address or alias, \"destination\": address or alias, \ + \"amount\": non-negative integer (, : ...) } \ + (, ...) ]', where an optional can either be \ + \"tez-amount\", \"fee\", \"gas-limit\" or \ + \"storage-limit\". The complete schema can be inspected via \ + `tezos-codec describe %s.fa1.2.token_transfer json schema`." + Protocol.name) + ~pp_error:(fun json fmt exn -> + match (json, exn) with + | `A lj, Data_encoding.Json.Cannot_destruct ([`Index n], exn) -> + Format.fprintf + fmt + "Invalid transfer at index %i: %a %a" + n + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + (Format.pp_print_option Data_encoding.Json.pp) + (List.nth_opt lj n) + | _, (Data_encoding.Json.Cannot_destruct _ as exn) -> + Format.fprintf + fmt + "Invalid transfer file: %a %a" + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + Data_encoding.Json.pp + json + | _, exn -> raise exn + (* this case can't happen because only `Cannot_destruct` error are + given to this pp *)) + (Data_encoding.list Client_proto_fa12.token_transfer_encoding) + @@ stop) + (fun ( fee, + as_address, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + src + operations + cctxt -> + let open Lwt_result_syntax in + let caller = Option.value ~default:src as_address in + match operations with + | [] -> cctxt#error "Empty operation list" + | operations -> + let* source, src_pk, src_sk = + get_contract_caller_keys cctxt caller + in + let*! errors = + Client_proto_fa12.inject_token_transfer_batch + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~sender:(Implicit src) + ~source + ~src_pk + ~src_sk + ~token_transfers:operations + ~fee_parameter + ?counter + ?default_fee:fee + ?default_gas_limit:gas_limit + ?default_storage_limit:storage_limit + ?safety_guard + () + in + let*! _ = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"multiple transfers simulation failed" + cctxt + errors + in + return_unit); + ] + +let commands () = commands_ro () @ commands_rw () diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.ml new file mode 100644 index 000000000000..9fedcd62fc61 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.ml @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let protocol_constants_arg = + Tezos_clic.arg + ~doc:"a JSON file that contains protocol constants to set." + ~long:"protocol-constants" + ~placeholder:"path" + (Tezos_clic.parameter (fun _ x -> Lwt_result_syntax.return x)) + +let bootstrap_accounts_arg = + Tezos_clic.arg + ~doc: + "a JSON file that contains definitions of bootstrap accounts to create." + ~long:"bootstrap-accounts" + ~placeholder:"path" + (Tezos_clic.parameter (fun _ x -> Lwt_result_syntax.return x)) + +let asynchronous_flag = + Tezos_clic.switch + ~long:"asynchronous" + ~doc:"put operations in mempool and require baking to include in the chain" + () + +let load_json_file (cctxt : Protocol_client_context.full) json_file = + let open Lwt_result_syntax in + match json_file with + | None -> return_none + | Some filename -> + let* json_string = cctxt#read_file filename in + return_some (Ezjsonm.from_string json_string :> Data_encoding.json) + +let create_mockup_command_handler + (constants_overrides_file, bootstrap_accounts_file, asynchronous) + (cctxt : Protocol_client_context.full) = + let open Lwt_result_syntax in + let* constants_overrides_json = + load_json_file cctxt constants_overrides_file + in + let* bootstrap_accounts_json = load_json_file cctxt bootstrap_accounts_file in + let* () = + Tezos_mockup.Persistence.create_mockup + ~cctxt:(cctxt :> Tezos_client_base.Client_context.full) + ~protocol_hash:Protocol.hash + ~constants_overrides_json + ~bootstrap_accounts_json + ~asynchronous + in + Tezos_mockup_commands.Mockup_wallet.populate cctxt bootstrap_accounts_file + +let create_mockup_command : Protocol_client_context.full Tezos_clic.command = + let open Tezos_clic in + command + ~group:Tezos_mockup_commands.Mockup_commands.group + ~desc:"Create a mockup environment." + (args3 protocol_constants_arg bootstrap_accounts_arg asynchronous_flag) + (prefixes ["create"; "mockup"] @@ stop) + create_mockup_command_handler + +let commands () = [create_mockup_command] diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.mli b/src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.mli new file mode 100644 index 000000000000..711637eadd30 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_mockup_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.ml new file mode 100644 index 000000000000..9cad48a8f8dc --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.ml @@ -0,0 +1,1063 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Client_proto_args +open Tezos_micheline + +let group = + { + Tezos_clic.name = "multisig"; + title = "Commands for managing a multisig smart contract"; + } + +let threshold_param () = + Tezos_clic.param + ~name:"threshold" + ~desc:"Number of required signatures" + Client_proto_args.int_parameter + +let public_key_param () = + Client_keys.Public_key.source_param + ~name:"key" + ~desc:"Each signer of the multisig contract" + +let secret_key_param () = + Client_keys.Secret_key.source_param + ~name:"key" + ~desc: + "Secret key corresponding to one of the public keys stored on the \ + multisig contract" + +let signature_param () = + Tezos_clic.param + ~name:"signature" + ~desc:"Each signer of the multisig contract" + Client_proto_args.signature_parameter + +let lambda_param () = + Tezos_clic.param + ~name:"lambda" + ~desc:"the lambda to execute, of type lambda unit (list operation)" + string_parameter + +let bytes_only_switch = + Tezos_clic.switch + ~long:"bytes-only" + ~doc:"return only the byte sequence to be signed" + () + +let bytes_param ~name ~desc = + Tezos_clic.param ~name ~desc Client_proto_args.bytes_parameter + +let transfer_options = + Tezos_clic.args11 + Client_proto_args.fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + Client_proto_args.gas_limit_arg + Client_proto_args.safety_guard_arg + Client_proto_args.storage_limit_arg + Client_proto_args.counter_arg + Client_proto_args.arg_arg + Client_proto_args.no_print_source_flag + Client_proto_args.fee_parameter_args + Client_proto_args.entrypoint_arg + +let non_transfer_options = + Tezos_clic.args9 + Client_proto_args.fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_context_commands.verbose_signing_switch + Client_proto_args.gas_limit_arg + Client_proto_args.safety_guard_arg + Client_proto_args.storage_limit_arg + Client_proto_args.counter_arg + Client_proto_args.no_print_source_flag + Client_proto_args.fee_parameter_args + +let prepare_command_display prepared_command bytes_only = + if bytes_only then + Format.printf + "0x%a@." + Hex.pp + (Hex.of_bytes prepared_command.Client_proto_multisig.bytes) + else + Format.printf + "%a@.%a@.%a@.%a@." + (fun ppf x -> + Format.fprintf ppf "Bytes to sign: '0x%a'" Hex.pp (Hex.of_bytes x)) + prepared_command.Client_proto_multisig.bytes + (fun ppf x -> + Format.fprintf + ppf + "Blake 2B Hash: '%s'" + (Tezos_crypto.Base58.raw_encode + Tezos_crypto.Blake2B.(hash_bytes [x] |> to_string))) + prepared_command.Client_proto_multisig.bytes + (fun ppf z -> + Format.fprintf + ppf + "Threshold (number of signatures required): %s" + (Z.to_string z)) + prepared_command.Client_proto_multisig.threshold + (fun ppf -> + Format.fprintf + ppf + "@[<2>Public keys of the signers:@ %a@]" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf "@ ") + Signature.Public_key.pp)) + prepared_command.Client_proto_multisig.keys + +let get_parameter_type (cctxt : #Protocol_client_context.full) + ~(destination : Contract.t) ~entrypoint = + let open Lwt_result_syntax in + match destination with + | Implicit _ -> + let open Micheline in + return @@ strip_locations @@ Prim (0, Script.T_unit, [], []) + | Originated contract -> ( + let* o = + Michelson_v1_entrypoints.contract_entrypoint_type + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~contract + ~entrypoint + ~normalize_types:true + in + match o with + | None -> + cctxt#error + "Contract %a has no entrypoint named %a" + Contract_hash.pp + contract + Entrypoint.pp + entrypoint + | Some parameter_type -> return parameter_type) + +let commands_ro () : #Protocol_client_context.full Tezos_clic.command list = + Tezos_clic. + [ + command + ~group + ~desc:"Show the hashes of the supported multisig contracts." + no_options + (fixed ["show"; "supported"; "multisig"; "hashes"]) + (fun () _cctxt -> + Format.printf "Hashes of supported multisig contracts:@." ; + List.iter + (fun h -> Format.printf "%a@." Script_expr_hash.pp h) + Client_proto_multisig.known_multisig_hashes ; + Lwt_result_syntax.return_unit); + command + ~group + ~desc:"Show the script of the recommended multisig contract." + no_options + (fixed ["show"; "multisig"; "script"]) + (fun () _cctxt -> + let {Michelson_v1_parser.source; _} = + Michelson_v1_printer.unparse_toplevel + Client_proto_multisig.multisig_script + in + Format.printf "%s@." source ; + Lwt_result_syntax.return_unit); + ] + +let commands_rw () : #Protocol_client_context.full Tezos_clic.command list = + Tezos_clic. + [ + command + ~group + ~desc:"Originate a new multisig contract." + (args10 + Client_proto_args.fee_arg + Client_proto_context_commands.dry_run_switch + Client_proto_args.gas_limit_arg + Client_proto_args.safety_guard_arg + Client_proto_args.storage_limit_arg + Client_proto_args.delegate_arg + (Client_keys.force_switch ()) + Client_proto_args.no_print_source_flag + Client_proto_args.fee_parameter_args + Client_proto_context_commands.verbose_signing_switch) + (prefixes ["deploy"; "multisig"] + @@ Client_proto_contracts.Raw_contract_alias.fresh_alias_param + ~name:"new_multisig" + ~desc:"name of the new multisig contract" + @@ prefix "transferring" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from source" + @@ prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ prefixes ["with"; "threshold"] + @@ threshold_param () + @@ prefixes ["on"; "public"; "keys"] + @@ seq_of_param (public_key_param ())) + (fun ( fee, + dry_run, + gas_limit, + safety_guard, + storage_limit, + delegate, + force, + no_print_source, + fee_parameter, + verbose_signing ) + alias_name + balance + source + threshold + keys + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* alias_name = + Client_proto_contracts.Raw_contract_alias.of_fresh + cctxt + force + alias_name + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* keys = + List.map_es (fun (pk_uri, _) -> Client_keys.public_key pk_uri) keys + in + let*! errors = + Client_proto_multisig.originate_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ?fee + ?gas_limit + ?safety_guard + ?storage_limit + ~verbose_signing + ~delegate + ~threshold:(Z.of_int threshold) + ~keys + ~balance + ~source + ~src_pk + ~src_sk + ~fee_parameter + () + in + let*! o = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"multisig origination simulation failed" + cctxt + errors + in + unless dry_run @@ fun () -> + Option.iter_es + (fun (_res, contract) -> + Client_proto_context.save_contract + ~force + cctxt + alias_name + contract) + o); + command + ~group + ~desc:"Sign a transaction for a multisig contract." + (args2 arg_arg entrypoint_arg) + (prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefix "transferring" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from source" + @@ prefix "to" + @@ Client_proto_contracts.Contract_alias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop) + (fun (parameter, entrypoint) + multisig_contract + amount + destination + sk + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let entrypoint = + Option.value ~default:Entrypoint.default entrypoint + in + let parameter = Option.value ~default:"Unit" parameter in + let*? {expanded = parameter; _} = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression parameter + in + let* parameter_type = + get_parameter_type cctxt ~destination ~entrypoint + in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Transfer + {amount; destination; entrypoint; parameter_type; parameter}) + () + in + let* signature = Client_keys.sign cctxt sk prepared_command.bytes in + Format.printf "%a@." Signature.pp signature ; + return_unit); + command + ~group + ~desc:"Sign a lambda for a generic multisig contract." + no_options + (prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["running"; "lambda"] + @@ lambda_param () + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop) + (fun () + multisig_contract + lambda + sk + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let*? {expanded = lambda; _} = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression lambda + in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Lambda lambda) + () + in + let* signature = Client_keys.sign cctxt sk prepared_command.bytes in + Format.printf "%a@." Signature.pp signature ; + return_unit); + command + ~group + ~desc:"Sign a delegate change for a multisig contract." + no_options + (prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["setting"; "delegate"; "to"] + @@ Client_keys.Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the new multisig contract" + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop) + (fun () + multisig_contract + delegate + sk + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate (Some delegate)) + () + in + let* signature = Client_keys.sign cctxt sk prepared_command.bytes in + Format.printf "%a@." Signature.pp signature ; + return_unit); + command + ~group + ~desc:"Sign a delegate withdraw for a multisig contract." + no_options + (prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["withdrawing"; "delegate"] + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () @@ stop) + (fun () multisig_contract sk (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate None) + () + in + let* signature = Client_keys.sign cctxt sk prepared_command.bytes in + Format.printf "%a@." Signature.pp signature ; + return_unit); + command + ~group + ~desc: + "Sign a change of public keys and threshold for a multisig contract." + no_options + (prefixes ["sign"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["using"; "secret"; "key"] + @@ secret_key_param () + @@ prefixes ["setting"; "threshold"; "to"] + @@ threshold_param () + @@ prefixes ["and"; "public"; "keys"; "to"] + @@ seq_of_param (public_key_param ())) + (fun () + multisig_contract + sk + new_threshold + new_keys + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* keys = + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + new_keys + in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Change_keys (Z.of_int new_threshold, keys)) + () + in + let* signature = Client_keys.sign cctxt sk prepared_command.bytes in + Format.printf "%a@." Signature.pp signature ; + return_unit); + command + ~group + ~desc:"Transfer tokens using a multisig contract." + transfer_options + (prefixes ["from"; "multisig"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name/literal of the multisig contract" + @@ prefix "transfer" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from the multisig contract" + @@ prefix "to" + @@ Client_proto_contracts.Contract_alias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ())) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + parameter, + no_print_source, + fee_parameter, + entrypoint ) + multisig_contract + amount + destination + source + signatures + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let entrypoint = + Option.value ~default:Entrypoint.default entrypoint + in + let parameter = Option.value ~default:"Unit" parameter in + let*? {expanded = parameter; _} = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression parameter + in + let* parameter_type = + get_parameter_type cctxt ~destination ~entrypoint + in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action: + (Client_proto_multisig.Transfer + {amount; destination; entrypoint; parameter_type; parameter}) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Run a lambda on a generic multisig contract." + non_transfer_options + (prefixes ["from"; "multisig"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name/literal of the multisig contract" + @@ prefixes ["run"; "lambda"] + @@ lambda_param () + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ())) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + multisig_contract + lambda + source + signatures + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*? {expanded = lambda; _} = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression lambda + in + let*! errors = + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action:(Client_proto_multisig.Lambda lambda) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Change the delegate of a multisig contract." + non_transfer_options + (prefixes ["set"; "delegate"; "of"; "multisig"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefix "to" + @@ Client_keys.Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the new multisig contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ())) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + multisig_contract + delegate + source + signatures + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate (Some delegate)) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Withdraw the delegate of a multisig contract." + non_transfer_options + (prefixes ["withdraw"; "delegate"; "of"; "multisig"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ())) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + multisig_contract + source + signatures + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate None) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc:"Change public keys and threshold for a multisig contract." + non_transfer_options + (prefixes ["set"; "threshold"; "of"; "multisig"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["to"] @@ threshold_param () + @@ prefixes ["and"; "public"; "keys"; "to"] + @@ non_terminal_seq (public_key_param ()) ~suffix:["on"; "behalf"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ())) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + multisig_contract + new_threshold + new_keys + source + signatures + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let* keys = + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + new_keys + in + let*! errors = + Client_proto_multisig.call_multisig + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~action: + (Client_proto_multisig.Change_keys (Z.of_int new_threshold, keys)) + ~signatures + ~amount:Tez.zero + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + (* This command is no longer necessary as Tezos_clic now supports non terminal + lists of parameters, however, it is kept for compatibility. *) + command + ~group + ~desc: + "Run a transaction described by a sequence of bytes on a multisig \ + contract." + non_transfer_options + (prefixes ["run"; "transaction"] + @@ bytes_param + ~name:"bytes" + ~desc: + "the sequence of bytes to deserialize as a multisig action, can \ + be obtained by one of the \"prepare multisig transaction\" \ + commands" + @@ prefixes ["on"; "multisig"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["on"; "behalf"; "of"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"source calling the multisig contract" + @@ prefixes ["with"; "signatures"] + @@ seq_of_param (signature_param ())) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + safety_guard, + storage_limit, + counter, + no_print_source, + fee_parameter ) + bytes + multisig_contract + source + signatures + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let*! errors = + Client_proto_multisig.call_multisig_on_bytes + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~fee_parameter + ~source + ?fee + ~src_pk + ~src_sk + ~multisig_contract + ~bytes + ~signatures + ~amount:Tez.zero + ?gas_limit + ?safety_guard + ?storage_limit + ?counter + () + in + let*! (_ : (_ Injection.result * Contract_hash.t list) option) = + Client_proto_context_commands.report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for a \ + multisigned transfer." + (args3 bytes_only_switch arg_arg entrypoint_arg) + (prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefix "transferring" + @@ Client_proto_args.tez_param + ~name:"qty" + ~desc:"amount taken from source" + @@ prefix "to" + @@ Client_proto_contracts.Contract_alias.destination_param + ~name:"dst" + ~desc:"name/literal of the destination contract" + @@ stop) + (fun (bytes_only, parameter, entrypoint) + multisig_contract + amount + destination + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let entrypoint = + Option.value ~default:Entrypoint.default entrypoint + in + let parameter = Option.value ~default:"Unit" parameter in + let*? {expanded = parameter; _} = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression parameter + in + let* parameter_type = + get_parameter_type cctxt ~destination ~entrypoint + in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Transfer + {amount; destination; entrypoint; parameter_type; parameter}) + () + in + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for a \ + multisigned lambda execution in a generic multisig contract." + (args1 bytes_only_switch) + (prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["running"; "lambda"] + @@ lambda_param () @@ stop) + (fun bytes_only + multisig_contract + lambda + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let*? {expanded = lambda; _} = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression lambda + in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Lambda lambda) + () + in + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for a \ + multisigned delegate change." + (args1 bytes_only_switch) + (prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["setting"; "delegate"; "to"] + @@ Client_keys.Public_key_hash.source_param + ~name:"dlgt" + ~desc:"new delegate of the new multisig contract" + @@ stop) + (fun bytes_only + multisig_contract + new_delegate + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Change_delegate (Some new_delegate)) + () + in + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for a \ + multisigned delegate withdraw." + (args1 bytes_only_switch) + (prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["withdrawing"; "delegate"] + @@ stop) + (fun bytes_only + multisig_contract + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action:(Client_proto_multisig.Change_delegate None) + () + in + return @@ prepare_command_display prepared_command bytes_only); + command + ~group + ~desc: + "Display the threshold, public keys, and byte sequence to sign for a \ + multisigned change of keys and threshold." + (args1 bytes_only_switch) + (prefixes ["prepare"; "multisig"; "transaction"; "on"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"multisig" + ~desc:"name or address of the originated multisig contract" + @@ prefixes ["setting"; "threshold"; "to"] + @@ threshold_param () + @@ prefixes ["and"; "public"; "keys"; "to"] + @@ seq_of_param (public_key_param ())) + (fun bytes_only + multisig_contract + new_threshold + new_keys + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* keys = + List.map_es + (fun (pk_uri, _) -> Client_keys.public_key pk_uri) + new_keys + in + let* prepared_command = + Client_proto_multisig.prepare_multisig_transaction + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~multisig_contract + ~action: + (Client_proto_multisig.Change_keys (Z.of_int new_threshold, keys)) + () + in + return @@ prepare_command_display prepared_command bytes_only); + ] + +let commands () = commands_ro () @ commands_rw () diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.mli b/src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.mli new file mode 100644 index 000000000000..7cd3668e789d --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_multisig_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.ml new file mode 100644 index 000000000000..e6b159dc5f61 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.ml @@ -0,0 +1,1535 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let group = + { + Tezos_clic.name = "scripts"; + title = "Commands for managing the library of known scripts"; + } + +open Tezos_micheline +open Client_proto_programs +open Client_proto_args +open Client_proto_contracts + +let commands () = + let open Tezos_clic in + let show_types_switch = + switch + ~long:"details" + ~short:'v' + ~doc:"show the types of each instruction" + () + in + let emacs_mode_switch = + switch + ~long:"emacs" + ?short:None + ~doc:"output in `michelson-mode.el` compatible format" + () + in + let trace_stack_switch = + switch ~long:"trace-stack" ~doc:"show the stack after each step" () + in + let zero_loc_switch = + switch ~short:'z' ~long:"zero-loc" ~doc:"replace location with \"0\"" () + in + let legacy_switch = + switch + ~long:"legacy" + ~doc:"typecheck in legacy mode as if the data was taken from the chain" + () + in + let amount_arg = + Client_proto_args.tez_arg + ~parameter:"amount" + ~doc:"amount of the transfer in \xEA\x9C\xA9" + ~default:"0.05" + in + let source_arg = + Contract_alias.destination_arg + ~name:"source" + ~doc:"name of the source (i.e. SENDER) contract for the transaction" + () + in + let payer_arg = + Client_keys.Public_key_hash.source_arg + ~long:"payer" + ~doc:"name of the payer (i.e. SOURCE) contract for the transaction" + () + in + let self_arg = + Originated_contract_alias.destination_arg + ~name:"self-address" + ~doc:"address of the contract (i.e. SELF_ADDRESS) for the transaction" + () + in + let balance_arg = + Client_proto_args.tez_opt_arg + ~parameter:"balance" + ~doc:"balance of run contract in \xEA\x9C\xA9" + in + let now_arg = Client_proto_args.now_arg in + let level_arg = Client_proto_args.level_arg in + let resolve_max_gas cctxt block = + let open Lwt_result_syntax in + function + | None -> + let* {parametric = {hard_gas_limit_per_operation; _}; _} = + Alpha_services.Constants.all cctxt (cctxt#chain, block) + in + return hard_gas_limit_per_operation + | Some gas -> return gas + in + let parse_expr expr = + Lwt.return @@ Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression expr + in + let data_type_arg = + arg + ~doc:"the given data will be type-checked against this type" + ~short:'t' + ~long:"type" + ~placeholder:"unit" + data_parameter + in + let bytes_parameter ~name ~desc = + param ~name ~desc Client_proto_args.bytes_parameter + in + let signature_parameter = + parameter (fun (cctxt : #Client_context.full) s -> + match Signature.of_b58check_opt s with + | Some s -> Lwt_result_syntax.return s + | None -> cctxt#error "Not given a valid signature") + in + let convert_input_format_param = + let open Lwt_result_syntax in + param + ~name:"input_format" + ~desc:"format of the input for conversion" + (parameter + ~autocomplete:(fun _ -> return ["michelson"; "json"; "binary"]) + (fun (cctxt : #Client_context.full) s -> + match String.lowercase_ascii s with + | "michelson" -> return `Michelson + | "json" -> return `JSON + | "binary" -> return `Binary + | _ -> + cctxt#error + "invalid input format, expecting one of \"michelson\", \ + \"json\" or \"binary\".")) + in + let convert_output_format_param = + let open Lwt_result_syntax in + param + ~name:"output_format" + ~desc:"format of the conversion output" + (parameter + ~autocomplete:(fun _ -> + return ["michelson"; "json"; "binary"; "ocaml"]) + (fun (cctxt : #Client_context.full) s -> + match String.lowercase_ascii s with + | "michelson" -> return `Michelson + | "json" -> return `JSON + | "binary" -> return `Binary + | "ocaml" -> return `OCaml + | _ -> + cctxt#error + "invalid output format, expecting one of \"michelson\", \ + \"json\", \"binary\" or \"ocaml\".")) + in + let file_or_literal_with_origin_param () = + param + ~name:"source" + ~desc:"literal or a path to a file" + (Client_proto_args.file_or_text_with_origin_parameter + ~from_text:(fun _cctxt s -> Lwt_result_syntax.return s) + ()) + in + let file_or_literal_param () = + param + ~name:"source" + ~desc:"literal or a path to a file" + (Client_proto_args.file_or_text_parameter + ~from_text:(fun _cctx s -> Lwt_result_syntax.return s) + ()) + in + let stack_param () = + param + ~name:"stack" + ~desc: + "a Michelson stack in the following format: {Stack_elt ; \ + ...; Stack_elt }, where each is a Michelson \ + value of type . The topmost element of the stack is ." + micheline_parameter + in + let handle_parsing_error label (cctxt : Protocol_client_context.full) + (emacs_mode, no_print_source) program body = + let open Lwt_result_syntax in + match program with + | program, [] -> body program + | res_with_errors when emacs_mode -> + let*! () = + cctxt#message + "(@[(%s . ())@ (errors . %a)@])" + label + Michelson_v1_emacs.report_errors + res_with_errors + in + return_unit + | parsed, errors -> + let*! () = + cctxt#message + "%a" + (fun ppf () -> + Michelson_v1_error_reporter.report_errors + ~details:(not no_print_source) + ~parsed:(Michelson_v1_parser.unrecognize_prims parsed) + ~show_source:(not no_print_source) + ppf + errors) + () + in + cctxt#error "syntax error in program" + in + [ + command + ~group + ~desc:"Lists all scripts in the library." + no_options + (fixed ["list"; "known"; "scripts"]) + (fun () (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* list = Program.load cctxt in + let*! () = List.iter_s (fun (n, _) -> cctxt#message "%s" n) list in + return_unit); + command + ~group + ~desc:"Add a script to the library." + (args1 (Program.force_switch ())) + (prefixes ["remember"; "script"] + @@ Program.fresh_alias_param @@ Program.source_param @@ stop) + (fun force name hash cctxt -> + let open Lwt_result_syntax in + let* name = Program.of_fresh cctxt force name in + Program.add ~force cctxt name hash); + command + ~group + ~desc:"Remove a script from the library." + no_options + (prefixes ["forget"; "script"] @@ Program.alias_param @@ stop) + (fun () (name, _) cctxt -> Program.del cctxt name); + command + ~group + ~desc:"Display a script from the library." + no_options + (prefixes ["show"; "known"; "script"] @@ Program.alias_param @@ stop) + (fun () (_, program) (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* source = Program.to_source program in + let*! () = cctxt#message "%s\n" source in + return_unit); + command + ~group + ~desc:"Ask the node to run a script." + (args14 + trace_stack_switch + amount_arg + balance_arg + source_arg + payer_arg + self_arg + no_print_source_flag + run_gas_limit_arg + entrypoint_arg + (unparsing_mode_arg ~default:"Readable") + now_arg + level_arg + other_contracts_arg + extra_big_maps_arg) + (prefixes ["run"; "script"] + @@ Program.source_param + @@ prefixes ["on"; "storage"] + @@ param ~name:"storage" ~desc:"the storage data" data_parameter + @@ prefixes ["and"; "input"] + @@ param ~name:"input" ~desc:"the input data" data_parameter + @@ stop) + (fun ( trace_exec, + amount, + balance, + sender, + payer, + self, + no_print_source, + gas, + entrypoint, + unparsing_mode, + now, + level, + other_contracts, + extra_big_maps ) + program + storage + input + cctxt -> + let open Lwt_result_syntax in + let*? program = Micheline_parser.no_parsing_error program in + let show_source = not no_print_source in + if trace_exec then + let*! res = + trace + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + { + amount = Some amount; + balance; + program; + storage; + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + entrypoint; + self; + } + in + print_trace_result cctxt ~show_source ~parsed:program res + else + let*! res = + run + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + { + amount = Some amount; + balance; + program; + storage; + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + entrypoint; + self; + } + in + print_run_result cctxt ~show_source ~parsed:program res); + command + ~group + ~desc: + "Ask the node to run a Michelson instruction or a sequence of \ + Michelson instructions on a stack." + (args12 + amount_arg + balance_arg + source_arg + payer_arg + self_arg + run_gas_limit_arg + (unparsing_mode_arg ~default:"Readable") + now_arg + level_arg + other_contracts_arg + extra_big_maps_arg + legacy_switch) + (prefixes ["run"; "michelson"; "code"] + @@ Program.source_param + @@ prefixes ["on"; "stack"] + @@ stack_param () @@ stop) + (fun ( amount, + balance, + sender, + payer, + self, + gas, + unparsing_mode, + now, + level, + other_contracts, + extra_big_maps, + legacy ) + program + stack + cctxt -> + let open Lwt_result_syntax in + let*? program = Micheline_parser.no_parsing_error program in + let*? stack = Michelson_v1_stack.parse_stack stack in + let*! res = + run_instr + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + { + stack; + shared_params = + { + input = program; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + amount; + balance; + self; + parameter = None; + legacy; + } + in + print_run_instr_result cctxt ~show_source:false ~parsed:program res); + command + ~group + ~desc:"Ask the node to compute the size of a script." + (args4 + emacs_mode_switch + no_print_source_flag + run_gas_limit_arg + legacy_switch) + (prefixes ["compute"; "size"; "for"; "script"] + @@ Program.source_param + @@ prefixes ["on"; "storage"] + @@ param ~name:"storage" ~desc:"the storage data" data_parameter + @@ stop) + (fun (emacs_mode, no_print_source, original_gas, legacy) + program + storage + cctxt -> + let open Lwt_result_syntax in + let setup = (emacs_mode, no_print_source) in + let* original_gas = resolve_max_gas cctxt cctxt#block original_gas in + handle_parsing_error "size" cctxt setup program @@ fun program -> + let* code_size = + script_size + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~gas:(Some original_gas) + ~legacy + ~program + ~storage + () + in + let*! () = cctxt#message "%d" code_size in + return_unit); + command + ~group + ~desc:"Ask the node to run Michelson unit tests from files or literals" + no_options + (prefixes ["run"; "unit"; "tests"; "from"] + @@ seq_of_param + @@ file_or_literal_with_origin_param ()) + (fun () tests (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + match tests with + | [] -> + let*! () = + cctxt#warning "No test file was specified on the command line" + in + return_unit + | _ :: _ -> + let*! ( (_number_of_literals : int), + number_of_seen_tests, + number_of_passed_tests, + errors ) = + List.fold_left_s + (fun (i, number_of_seen_tests, number_of_passed_tests, error_acc) + content_with_origin -> + let name, i = + match content_with_origin with + | Client_proto_args.File {path; _} -> (path, i) + | Text _ -> + let i = i + 1 in + ("Literal script " ^ string_of_int i, i) + in + let source = + Client_proto_args.content_of_file_or_text + content_with_origin + in + let parsed, parsing_errors = + Michelson_v1_parser.expand_toplevel source + in + let*! res = + let open Client_proto_tzt in + let*? (test : unit_test_with_source) = + Micheline_parser.no_parsing_error + ({source; parsed}, parsing_errors) + in + run_unit_test + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~test + () + in + match res with + | Ok () -> + Lwt.return + ( i, + number_of_seen_tests + 1, + number_of_passed_tests + 1, + error_acc ) + | Error err -> + Lwt.return + ( i, + number_of_seen_tests + 1, + number_of_passed_tests, + (name, parsed, err) :: error_acc )) + (0, 0, 0, []) + tests + in + let number_of_failed_tests = + number_of_seen_tests - number_of_passed_tests + in + let print_result () = + cctxt#message + "Test results: Passed:%d Failed:%d Total:%d" + number_of_passed_tests + number_of_failed_tests + number_of_seen_tests + in + if number_of_failed_tests > 0 then + let*! () = + List.iter_s + (fun (name, parsed, errs) -> + let*! errs = + Michelson_v1_error_reporter.enrich_runtime_errors + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~parsed:(Some parsed) + errs + in + cctxt#message + "%s:@.%a" + name + (Michelson_v1_error_reporter.report_errors + ~details:true + ~parsed + ~show_source:true) + errs) + errors + in + let*! () = print_result () in + let*! () = cctxt#error "Some tests have failed" in + return_unit + else + let*! () = print_result () in + let*! () = cctxt#message "All tests have passed" in + return_unit); + command + ~group + ~desc:"Ask the node to typecheck one or several scripts." + (args6 + show_types_switch + emacs_mode_switch + no_print_source_flag + run_gas_limit_arg + legacy_switch + display_names_flag) + (prefixes ["typecheck"; "script"] + @@ seq_of_param + @@ file_or_literal_with_origin_param ()) + (fun ( show_types, + emacs_mode, + no_print_source, + original_gas, + legacy, + display_names ) + expr_strings + cctxt -> + let open Lwt_result_syntax in + let setup = (emacs_mode, no_print_source) in + match expr_strings with + | [] -> + let*! () = + cctxt#warning "No scripts were specified on the command line" + in + return_unit + | _ :: _ -> + let* _number_of_literal_scripts = + List.fold_left_es + (fun i content_with_origin -> + let expr_string = + Client_proto_args.content_of_file_or_text + content_with_origin + in + let program = + Michelson_v1_parser.parse_toplevel expr_string + in + let name, i = + match content_with_origin with + | Client_proto_args.File {path; _} -> (path, i) + | Text _ -> + let i = i + 1 in + ("Literal script " ^ string_of_int i, i) + in + let* () = + handle_parsing_error "types" cctxt setup program + @@ fun program -> + let* original_gas = + resolve_max_gas cctxt cctxt#block original_gas + in + let*! res = + typecheck_program + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~gas:(Some original_gas) + ~legacy + ~show_types + program + in + print_typecheck_result + ~emacs:emacs_mode + ~show_types + ~print_source_on_error:(not no_print_source) + ~display_names + ~name + program + res + cctxt + in + return i) + 0 + expr_strings + in + return_unit); + command + ~group + ~desc:"Ask the node to typecheck a data expression." + (args3 no_print_source_flag run_gas_limit_arg legacy_switch) + (prefixes ["typecheck"; "data"] + @@ param ~name:"data" ~desc:"the data to typecheck" data_parameter + @@ prefixes ["against"; "type"] + @@ param ~name:"type" ~desc:"the expected type" data_parameter + @@ stop) + (fun (no_print_source, custom_gas, legacy) data ty cctxt -> + let open Lwt_result_syntax in + let* original_gas = resolve_max_gas cctxt cctxt#block custom_gas in + let*! r = + Client_proto_programs.typecheck_data + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~gas:(Some original_gas) + ~legacy + ~data + ~ty + () + in + match r with + | Ok gas -> + let*! () = + cctxt#message + "@[Well typed@,Gas remaining: %a@]" + Alpha_context.Gas.pp + gas + in + return_unit + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:(not no_print_source) + ?parsed:None) + errs + in + cctxt#error "ill-typed data"); + command + ~group + ~desc: + "Ask the node to pack a data expression.\n\ + The returned hash is the same as what Michelson instruction `PACK` \ + would have produced.\n\ + Also displays the result of hashing this packed data with `BLAKE2B`, \ + `SHA256` or `SHA512` instruction." + (args2 run_gas_limit_arg (Tezos_clic_unix.Scriptable.clic_arg ())) + (prefixes ["hash"; "data"] + @@ param ~name:"data" ~desc:"the data to hash" data_parameter + @@ prefixes ["of"; "type"] + @@ param ~name:"type" ~desc:"type of the data" data_parameter + @@ stop) + (fun (custom_gas, scriptable) data typ cctxt -> + let open Lwt_result_syntax in + let* original_gas = resolve_max_gas cctxt cctxt#block custom_gas in + let*! r = + Plugin.RPC.Scripts.pack_data + cctxt + (cctxt#chain, cctxt#block) + ~gas:(Some original_gas) + ~data:data.expanded + ~ty:typ.expanded + in + match r with + | Ok (bytes, remaining_gas) -> + let hash = Script_expr_hash.hash_bytes [bytes] in + let name_value_rows = + Format. + [ + ( "Raw packed data", + asprintf "0x%a" Hex.pp (Hex.of_bytes bytes) ); + ( "Script-expression-ID-Hash", + asprintf "%a" Script_expr_hash.pp hash ); + ( "Raw Script-expression-ID-Hash", + asprintf + "0x%a" + Hex.pp + (Hex.of_bytes (Script_expr_hash.to_bytes hash)) ); + ( "Ledger Blake2b hash", + Tezos_crypto.Base58.raw_encode + Tezos_crypto.Blake2B.(hash_bytes [bytes] |> to_string) ); + ( "Raw Sha256 hash", + asprintf + "0x%a" + Hex.pp + (Hex.of_bytes (Environment.Raw_hashes.sha256 bytes)) ); + ( "Raw Sha512 hash", + asprintf + "0x%a" + Hex.pp + (Hex.of_bytes (Environment.Raw_hashes.sha512 bytes)) ); + ( "Gas remaining", + asprintf "%a" Alpha_context.Gas.pp remaining_gas ); + ] + in + Tezos_clic_unix.Scriptable.output + scriptable + ~for_human:(fun () -> + let*! () = + List.iter_s + (fun (name, value) -> cctxt#message "%s: %s" name value) + name_value_rows + in + return_unit) + ~for_script:(fun () -> + name_value_rows |> List.map (fun (name, value) -> [name; value])) + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + in + cctxt#error "ill-formed data"); + command + ~group + ~desc:"Ask the node to hash a Michelson script with `BLAKE2B`." + (args3 + enforce_indentation_flag + display_names_flag + (Tezos_clic_unix.Scriptable.clic_arg ())) + (prefixes ["hash"; "script"] + @@ seq_of_param + @@ file_or_literal_with_origin_param ()) + (fun (check, display_names, scriptable) + expr_strings + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + match expr_strings with + | [] -> + let*! () = + cctxt#warning "No scripts were specified on the command line" + in + return_unit + | _ :: _ -> + let* hash_name_rows_rev, _number_of_literal_scripts = + List.fold_left_es + (fun (l, i) content_with_origin -> + let expr_string = + Client_proto_args.content_of_file_or_text + content_with_origin + in + let program = + Michelson_v1_parser.parse_toplevel ~check expr_string + in + let*? program = Micheline_parser.no_parsing_error program in + let code = program.expanded in + let bytes = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Script.expr_encoding + code + in + let hash = + Format.asprintf + "%a" + Script_expr_hash.pp + (Script_expr_hash.hash_bytes [bytes]) + in + let name, i = + match content_with_origin with + | Client_proto_args.File {path; _} -> (path, i) + | Text _ -> + let i = i + 1 in + ("Literal script " ^ string_of_int i, i) + in + return ((hash, name) :: l, i)) + ([], 0) + expr_strings + in + let hash_name_rows = List.rev hash_name_rows_rev in + Tezos_clic_unix.Scriptable.output + scriptable + ~for_human:(fun () -> + let*! () = + List.iter_s + (fun (hash, name) -> + if display_names then cctxt#answer "%s\t%s" hash name + else cctxt#answer "%s" hash) + hash_name_rows + in + return_unit) + ~for_script:(fun () -> + List.map + (fun (hash, name) -> + if display_names then [hash; name] else [hash]) + hash_name_rows)); + command + ~group + ~desc: + "Parse a byte sequence (in hexadecimal notation) as a data expression, \ + as per Michelson instruction `UNPACK`." + no_options + (prefixes ["unpack"; "michelson"; "data"] + @@ bytes_parameter ~name:"bytes" ~desc:"the packed data to parse" + @@ stop) + (fun () bytes cctxt -> + let open Lwt_result_syntax in + let* () = + if Bytes.get bytes 0 != '\005' then + cctxt#error + "Not a piece of packed Michelson data (must start with `0x05`)" + else return_unit + in + (* Remove first byte *) + let bytes = Bytes.sub bytes 1 (Bytes.length bytes - 1) in + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Script.expr_encoding + bytes + with + | None -> cctxt#error "Could not decode bytes" + | Some expr -> + let*! () = + cctxt#message "%a" Michelson_v1_printer.print_expr_unwrapped expr + in + return_unit); + command + ~group + ~desc:"Ask the node to normalize a script." + (args1 (unparsing_mode_arg ~default:"Readable")) + (prefixes ["normalize"; "script"] @@ Program.source_param @@ stop) + (fun unparsing_mode program cctxt -> + let open Lwt_result_syntax in + let*? program = Micheline_parser.no_parsing_error program in + let*! r = + Plugin.RPC.Scripts.normalize_script + cctxt + (cctxt#chain, cctxt#block) + ~script:program.expanded + ~unparsing_mode + in + match r with + | Ok program -> + let*! () = + cctxt#message + "%a" + (fun ppf () : unit -> + Michelson_v1_printer.print_expr_unwrapped ppf program) + () + in + return_unit + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + in + cctxt#error "ill-typed script"); + command + ~group + ~desc:"Ask the node to normalize a data expression." + (args4 + (unparsing_mode_arg ~default:"Readable") + legacy_switch + other_contracts_arg + extra_big_maps_arg) + (prefixes ["normalize"; "data"] + @@ param + ~name:"data" + ~desc:"the data expression to normalize" + data_parameter + @@ prefixes ["of"; "type"] + @@ param ~name:"type" ~desc:"type of the data expression" data_parameter + @@ stop) + (fun (unparsing_mode, legacy, other_contracts, extra_big_maps) + data + typ + cctxt -> + let open Lwt_result_syntax in + let*! r = + Plugin.RPC.Scripts.normalize_data + cctxt + (cctxt#chain, cctxt#block) + ~legacy + ~data:data.expanded + ~ty:typ.expanded + ~unparsing_mode + ~other_contracts + ~extra_big_maps + in + match r with + | Ok expr -> + let*! () = + cctxt#message "%a" Michelson_v1_printer.print_expr_unwrapped expr + in + return_unit + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + in + cctxt#error "ill-typed data expression"); + command + ~group + ~desc:"Ask the node to normalize a typed Michelson stack." + (args4 + (unparsing_mode_arg ~default:"Readable") + legacy_switch + other_contracts_arg + extra_big_maps_arg) + (prefixes ["normalize"; "stack"] @@ stack_param () @@ stop) + (fun (unparsing_mode, legacy, other_contracts, extra_big_maps) stack cctxt -> + let open Lwt_result_syntax in + let*? stack = Michelson_v1_stack.parse_stack stack in + let*! r = + Plugin.RPC.Scripts.normalize_stack + cctxt + (cctxt#chain, cctxt#block) + ~legacy + ~stack + ~unparsing_mode + ~other_contracts + ~extra_big_maps + in + match r with + | Ok expr -> + let*! () = + cctxt#message "%a" Michelson_v1_printer.print_typed_stack expr + in + return_unit + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + in + cctxt#error "ill-typed stack"); + command + ~group + ~desc:"Ask the node to normalize a type." + no_options + (prefixes ["normalize"; "type"] + @@ param + ~name:"typ" + ~desc:"the Michelson type to normalize" + data_parameter + @@ stop) + (fun () typ cctxt -> + let open Lwt_result_syntax in + let*! r = + Plugin.RPC.Scripts.normalize_type + cctxt + (cctxt#chain, cctxt#block) + ~ty:typ.expanded + in + match r with + | Ok expr -> + let*! () = + cctxt#message "%a" Michelson_v1_printer.print_expr_unwrapped expr + in + return_unit + | Error errs -> + let*! () = + cctxt#warning + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + in + cctxt#error "ill-formed type"); + command + ~group + ~desc: + "Sign a raw sequence of bytes and display it using the format expected \ + by Michelson instruction `CHECK_SIGNATURE`." + no_options + (prefixes ["sign"; "bytes"] + @@ bytes_parameter ~name:"data" ~desc:"the raw data to sign" + @@ prefixes ["for"] @@ Client_keys.Secret_key.source_param @@ stop) + (fun () bytes sk cctxt -> + let open Lwt_result_syntax in + let* signature = Client_keys.sign cctxt sk bytes in + let*! () = cctxt#message "Signature: %a" Signature.pp signature in + return_unit); + command + ~group + ~desc: + "Check the signature of a byte sequence as per Michelson instruction \ + `CHECK_SIGNATURE`." + (args1 (switch ~doc:"Use only exit codes" ~short:'q' ~long:"quiet" ())) + (prefixes ["check"; "that"; "bytes"] + @@ bytes_parameter ~name:"bytes" ~desc:"the signed data" + @@ prefixes ["were"; "signed"; "by"] + @@ Client_keys.Public_key.alias_param ~name:"key" + @@ prefixes ["to"; "produce"] + @@ param + ~name:"signature" + ~desc:"the signature to check" + signature_parameter + @@ stop) + (fun quiet + bytes + (_, (key_locator, _)) + signature + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* check = Client_keys.check key_locator signature bytes in + if check then + if quiet then return_unit + else + let*! () = cctxt#message "Signature check successful." in + return_unit + else cctxt#error "invalid signature"); + command + ~group + ~desc:"Ask the type of an entrypoint of a script." + (args2 emacs_mode_switch no_print_source_flag) + (prefixes ["get"; "script"; "entrypoint"; "type"; "of"] + @@ param + ~name:"entrypoint" + ~desc:"the entrypoint to describe" + entrypoint_parameter + @@ prefixes ["for"] @@ Program.source_param @@ stop) + (fun ((emacs_mode, no_print_source) as setup) entrypoint program cctxt -> + let open Lwt_syntax in + handle_parsing_error "entrypoint" cctxt setup program @@ fun program -> + let* entrypoint_type = + entrypoint_type + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + program + ~entrypoint + in + print_entrypoint_type + ~emacs:emacs_mode + ~show_source:(not no_print_source) + ~parsed:program + ~entrypoint + cctxt + entrypoint_type); + command + ~group + ~desc:"Ask the node to list the entrypoints of a script." + (args2 emacs_mode_switch no_print_source_flag) + (prefixes ["get"; "script"; "entrypoints"; "for"] + @@ Program.source_param @@ stop) + (fun ((emacs_mode, no_print_source) as setup) program cctxt -> + let open Lwt_syntax in + handle_parsing_error "entrypoints" cctxt setup program @@ fun program -> + let* entrypoints = + list_entrypoints cctxt ~chain:cctxt#chain ~block:cctxt#block program + in + print_entrypoints_list + ~emacs:emacs_mode + ~show_source:(not no_print_source) + ~parsed:program + cctxt + entrypoints); + command + ~group + ~desc: + "Ask the node to list the unreachable paths in a script's parameter \ + type." + (args2 emacs_mode_switch no_print_source_flag) + (prefixes ["get"; "script"; "unreachable"; "paths"; "for"] + @@ Program.source_param @@ stop) + (fun ((emacs_mode, no_print_source) as setup) program cctxt -> + let open Lwt_syntax in + handle_parsing_error "entrypoints" cctxt setup program @@ fun program -> + let* entrypoints = + list_unreachables cctxt ~chain:cctxt#chain ~block:cctxt#block program + in + print_unreachables + ~emacs:emacs_mode + ~show_source:(not no_print_source) + ~parsed:program + cctxt + entrypoints); + command + ~group + ~desc:"Ask the node to expand the Michelson macros in a script." + no_options + (prefixes ["expand"; "macros"; "in"] @@ Program.source_param @@ stop) + (fun () program (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let*? program = Micheline_parser.no_parsing_error program in + let*! () = + cctxt#message + "%a" + (fun ppf () : unit -> + Michelson_v1_printer.print_expr_unwrapped ppf program.expanded) + () + in + return_unit); + command + ~desc: + "Conversion of Michelson script from Micheline, JSON or binary to \ + Micheline, JSON, binary or OCaml" + (args3 zero_loc_switch legacy_switch enforce_indentation_flag) + (prefixes ["convert"; "script"] + @@ file_or_literal_with_origin_param () + @@ prefix "from" @@ convert_input_format_param @@ prefix "to" + @@ convert_output_format_param @@ stop) + (fun (zero_loc, legacy, check) + content_with_origin + from_format + to_format + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let expr_string = + Client_proto_args.content_of_file_or_text content_with_origin + in + let name = + match content_with_origin with + | Client_proto_args.File {path; _} -> path + | Text _ -> "Literal script" + in + let* (expression : Alpha_context.Script.expr) = + match from_format with + | `Michelson -> + let program = + Michelson_v1_parser.parse_toplevel ~check expr_string + in + let*? program = Micheline_parser.no_parsing_error program in + let* () = + let*! r = + typecheck_program + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~legacy + ~show_types:true + ~gas:None + program + in + match r with + | Error _ as res -> + print_typecheck_result + ~emacs:false + ~show_types:true + ~print_source_on_error:true + ~display_names:false + ~name + program + res + cctxt + | Ok _ -> return_unit + in + return program.expanded + | `JSON -> ( + match Data_encoding.Json.from_string expr_string with + | Error err -> cctxt#error "%s" err + | Ok json -> + safe_decode_json + ~name:"script" + cctxt + Alpha_context.Script.expr_encoding + json) + | `Binary -> ( + let* bytes = bytes_of_prefixed_string cctxt expr_string in + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Script.expr_encoding + bytes + with + | None -> cctxt#error "Could not decode bytes" + | Some expr -> return expr) + in + let output = + match to_format with + | `Michelson -> + Micheline_printer.printable + Michelson_v1_primitives.string_of_prim + expression + |> Format.asprintf "%a" Micheline_printer.print_expr + | `JSON -> + Data_encoding.Json.( + construct Alpha_context.Script.expr_encoding expression + |> to_string) + | `Binary -> + Format.asprintf + "0x%s" + (Data_encoding.Binary.( + to_bytes_exn Alpha_context.Script.expr_encoding expression) + |> Hex.of_bytes |> Hex.show) + | `OCaml -> + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc + expression + in + let*! () = cctxt#message "%s" output in + return_unit); + command + ~desc: + "Conversion of Micheline expression from Micheline, JSON or binary to \ + Micheline, JSON, binary or OCaml" + (args2 zero_loc_switch data_type_arg) + (prefixes ["convert"; "data"] + @@ file_or_literal_param () @@ prefix "from" @@ convert_input_format_param + @@ prefix "to" @@ convert_output_format_param @@ stop) + (fun (zero_loc, data_ty) + data_string + from_format + to_format + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let micheline_of_expr expr = + Micheline_printer.printable + Michelson_v1_primitives.string_of_prim + expr + |> Format.asprintf "%a" Micheline_printer.print_expr + in + let typecheck_parsed ~data ~ty = + let*! r = + Client_proto_programs.typecheck_data + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~data + ~ty + ~gas:None + ~legacy:false + () + in + match r with + | Error errs -> + cctxt#error + "%a" + (Michelson_v1_error_reporter.report_errors + ~details:false + ~show_source:false + ?parsed:None) + errs + | Ok _gas -> return data.expanded + in + let typecheck_expr ~expr ~ty = + let data_string = micheline_of_expr expr in + let* data = parse_expr data_string in + typecheck_parsed ~data ~ty + in + let* (expression : Alpha_context.Script.expr) = + match from_format with + | `Michelson -> ( + let* data = parse_expr data_string in + match data_ty with + | Some ty -> typecheck_parsed ~data ~ty + | None -> return data.expanded) + | `JSON -> ( + match Data_encoding.Json.from_string data_string with + | Error err -> cctxt#error "%s" err + | Ok json -> ( + let* expr = + safe_decode_json + ~name:"script" + cctxt + Alpha_context.Script.expr_encoding + json + in + match data_ty with + | None -> return expr + | Some ty -> typecheck_expr ~expr ~ty)) + | `Binary -> ( + let* bytes = bytes_of_prefixed_string cctxt data_string in + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Script.expr_encoding + bytes + with + | None -> cctxt#error "Could not decode bytes" + | Some expr -> ( + match data_ty with + | None -> return expr + | Some ty -> typecheck_expr ~expr ~ty)) + in + let output = + match to_format with + | `Michelson -> micheline_of_expr expression + | `JSON -> + Data_encoding.Json.( + construct Alpha_context.Script.expr_encoding expression + |> to_string) + | `Binary -> + Format.asprintf + "0x%s" + (Data_encoding.Binary.( + to_bytes_exn Alpha_context.Script.expr_encoding expression) + |> Hex.of_bytes |> Hex.show) + | `OCaml -> + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc + expression + in + let*! () = cctxt#message "%s" output in + return_unit); + command + ~group + ~desc:"Ask the node to run a TZIP-4 view." + (args8 + source_arg + payer_arg + run_gas_limit_arg + (unparsing_mode_arg ~default:"Readable") + now_arg + level_arg + other_contracts_arg + extra_big_maps_arg) + (prefixes ["run"; "tzip4"; "view"] + @@ param + ~name:"entrypoint" + ~desc:"the name of the view" + entrypoint_parameter + @@ prefixes ["on"; "contract"] + @@ Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"viewed contract" + @@ prefixes ["with"; "input"] + @@ param ~name:"input" ~desc:"the input data" data_parameter + @@ stop) + (fun ( sender, + payer, + gas, + unparsing_mode, + now, + level, + other_contracts, + extra_big_maps ) + entrypoint + contract + input + cctxt -> + let open Lwt_result_syntax in + let*! res = + Client_proto_programs.run_view + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + contract; + entrypoint; + } + in + print_view_result cctxt res); + command + ~group + ~desc:"Ask the node to run a Michelson view with Unit as input." + (args9 + source_arg + payer_arg + run_gas_limit_arg + unlimited_gas_arg + (unparsing_mode_arg ~default:"Readable") + now_arg + level_arg + other_contracts_arg + extra_big_maps_arg) + (prefixes ["run"; "view"] + @@ param ~name:"view" ~desc:"the name of the view" string_parameter + @@ prefixes ["on"; "contract"] + @@ Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"the contract containing the view" + @@ stop) + (fun ( sender, + payer, + gas, + unlimited_gas, + unparsing_mode, + now, + level, + other_contracts, + extra_big_maps ) + view + contract + cctxt -> + let open Lwt_result_syntax in + let*? input = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression "Unit" + in + let*! res = + Client_proto_programs.run_script_view + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + contract; + view; + unlimited_gas; + } + in + print_view_result cctxt res); + command + ~group + ~desc:"Ask the node to run a Michelson view." + (args9 + source_arg + payer_arg + run_gas_limit_arg + unlimited_gas_arg + (unparsing_mode_arg ~default:"Readable") + now_arg + level_arg + other_contracts_arg + extra_big_maps_arg) + (prefixes ["run"; "view"] + @@ param ~name:"view" ~desc:"the name of the view" string_parameter + @@ prefixes ["on"; "contract"] + @@ Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"the contract containing the view" + @@ prefixes ["with"; "input"] + @@ param + ~name:"input" + ~desc:"the argument provided to the view" + data_parameter + @@ stop) + (fun ( sender, + payer, + gas, + unlimited_gas, + unparsing_mode, + now, + level, + other_contracts, + extra_big_maps ) + view + contract + input + cctxt -> + let open Lwt_result_syntax in + let*! res = + Client_proto_programs.run_script_view + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + { + shared_params = + { + input; + unparsing_mode; + now; + level; + sender; + payer; + gas; + other_contracts; + extra_big_maps; + }; + contract; + view; + unlimited_gas; + } + in + print_view_result cctxt res); + ] diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.mli b/src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.mli new file mode 100644 index 000000000000..4cfc1bea7d2b --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_programs_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml new file mode 100644 index 000000000000..a058c4c30f15 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml @@ -0,0 +1,1929 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +module Smart_contracts = Client_proto_stresstest_contracts + +type transfer_strategy = + | Fixed_amount of {mutez : Tez.t} (** Amount to transfer *) + | Evaporation of {fraction : float} + (** Maximum fraction of current wealth to transfer. + Minimum amount is 1 mutez regardless of total wealth. *) + +type limit = + | Abs of int (** Absolute level at which we should stop *) + | Rel of int (** Relative number of levels before stopping *) + +type parameters = { + seed : int; + fresh_probability : float; + (** Per-transfer probability that the destination will be fresh *) + tps : float; (** Transaction per seconds target *) + strategy : transfer_strategy; + regular_transfer_fee : Tez.t; + (** fees for each transfer (except for transfers to smart contracts), in mutez *) + regular_transfer_gas_limit : Gas.Arith.integral; + (** gas limit per operation (except for transfers to smart contracts) *) + storage_limit : Z.t; (** storage limit per operation *) + account_creation_storage : Z.t; + (** upper bound on bytes consumed when creating a tz1 account *) + total_transfers : int option; + (** total number of transfers to perform; unbounded if None *) + level_limit : limit option; + (** total number of levels during which the stresstest is run; unbounded if None *) + smart_contracts : Smart_contracts.t; + (** An opaque type that stores all the information that is necessary for + efficient sampling of smart contract calls. *) +} + +type origin = Explicit | Wallet_pkh | Wallet_alias of string + +type source = { + pkh : public_key_hash; + pk : public_key; + sk : Signature.secret_key; +} + +type source_with_uri = { + pkh : public_key_hash; + pk : public_key; + pk_uri : Client_keys.pk_uri; + sk : Signature.secret_key; + sk_uri : Client_keys.sk_uri; +} + +type input_source = + | Explicit of source + | Wallet_alias of string + | Wallet_pkh of public_key_hash + +type source_origin = {source : source; origin : origin} + +(** Destination of a call: either an implicit contract or an originated one + with all the necessary data (entrypoint and the argument). *) +type destination = + | Implicit of Signature.Public_key_hash.t + | Originated of Smart_contracts.invocation_parameters + +type transfer = { + src : source; + dst : destination; + fee : Tez.t; + gas_limit : Gas.Arith.integral; + amount : Tez.t; + counter : Manager_counter.t option; + fresh_dst : bool; +} + +type state = { + rng_state : Random.State.t; + current_head_on_start : Block_hash.t; + mutable pool : source_origin list; + mutable pool_size : int; + mutable shuffled_pool : source list; + mutable revealed : Signature.Public_key_hash.Set.t; + mutable last_block : Block_hash.t; + mutable last_level : int; + mutable target_block : Block_hash.t; + (** The block on top of which we are injecting transactions (HEAD~2). *) + new_block_condition : unit Lwt_condition.t; + injected_operations : Operation_hash.t list Block_hash.Table.t; +} + +(** Cost estimations for every kind of transaction used in the stress test. + *) +type transaction_costs = { + regular : Gas.Arith.integral; (** Cost of a regular transaction. *) + smart_contracts : (string * Gas.Arith.integral) list; + (** Cost of a smart contract call (per contract alias). *) +} + +type verbosity = Notice | Info | Debug + +let verbosity = ref Notice + +let log level msg = + match (level, !verbosity) with + | Notice, _ | Info, Info | Info, Debug | Debug, Debug -> msg () + | _ -> Lwt.return_unit + +let pp_sep ppf () = Format.fprintf ppf ",@ " + +let default_parameters = + { + seed = 0x533D; + fresh_probability = 0.001; + tps = 5.0; + strategy = Fixed_amount {mutez = Tez.one}; + regular_transfer_fee = Tez.of_mutez_exn 2_000L; + regular_transfer_gas_limit = Gas.Arith.integral_of_int_exn 1_600; + (* [gas_limit] corresponds to a slight overapproximation of the + gas needed to inject an operation. It was obtained by simulating + the operation using the client. *) + storage_limit = Z.zero; + account_creation_storage = Z.of_int 300; + (* [account_creation_storage] corresponds to a slight overapproximation + of the storage consumed when allocating a new implicit account. + It was obtained by simulating the operation using the client. *) + total_transfers = None; + level_limit = None; + smart_contracts = Smart_contracts.no_contracts; + } + +let input_source_encoding = + let open Data_encoding in + union + [ + case + ~title:"explicit" + (Tag 0) + (obj3 + (req "pkh" Signature.Public_key_hash.encoding) + (req "pk" Signature.Public_key.encoding) + (req "sk" Signature.Secret_key.encoding)) + (function Explicit {pkh; pk; sk} -> Some (pkh, pk, sk) | _ -> None) + (fun (pkh, pk, sk) -> Explicit {pkh; pk; sk}); + case + ~title:"alias" + (Tag 1) + (obj1 (req "alias" Data_encoding.string)) + (function Wallet_alias alias -> Some alias | _ -> None) + (fun alias -> Wallet_alias alias); + case + ~title:"pkh" + (Tag 2) + (obj1 (req "pkh" Signature.Public_key_hash.encoding)) + (function Wallet_pkh pkh -> Some pkh | _ -> None) + (fun pkh -> Wallet_pkh pkh); + ] + +let injected_operations_encoding = + let open Data_encoding in + list + (obj2 + (req "block_hash_when_injected" Block_hash.encoding) + (req "operation_hashes" (list Operation_hash.encoding))) + +let transaction_costs_encoding = + let open Data_encoding in + conv + (fun {regular; smart_contracts} -> (regular, smart_contracts)) + (fun (regular, smart_contracts) -> {regular; smart_contracts}) + (obj2 + (req "regular" Gas.Arith.n_integral_encoding) + (req "smart_contracts" (assoc Gas.Arith.n_integral_encoding))) + +let destination_to_contract dst = + match dst with + | Implicit x -> Contract.Implicit x + | Originated x -> x.destination + +let parse_strategy s = + match String.split ~limit:1 ':' s with + | ["fixed"; parameter] -> ( + match int_of_string parameter with + | exception _ -> Error "invalid integer literal" + | mutez when mutez <= 0 -> Error "negative amount" + | mutez -> ( + match Tez.of_mutez (Int64.of_int mutez) with + | None -> Error "invalid mutez" + | Some mutez -> Ok (Fixed_amount {mutez}))) + | ["evaporation"; parameter] -> ( + match float_of_string parameter with + | exception _ -> Error "invalid float literal" + | fraction when fraction < 0.0 || fraction > 1.0 -> + Error "invalid evaporation rate" + | fraction -> Ok (Evaporation {fraction})) + | _ -> Error "invalid argument" + +(** This command uses two different data structures for sources: + - The in-output files one, + - The normalized one. + + The data structure used for in-output files does not directly contain the + data required to forge operations. For efficiency purposes, the sources are + converted into a normalized data structure that contains all the required + data to forge operations and the format originally used to be able to + revert this conversion. *) + +(** [normalize_source cctxt src] converts [src] from in-output data structure + to normalized one. If the conversion fails, [None] is returned and a + warning message is printed in [cctxt]. + + Only unencrypted and encrypted sources from the wallet of [cctxt] are + supported. *) +let normalize_source cctxt = + let open Lwt_syntax in + let sk_of_sk_uri sk_uri = + match + Signature.Secret_key.of_b58check + (Uri.path (sk_uri : Client_keys.sk_uri :> Uri.t)) + with + | Ok sk -> Lwt.return_some sk + | Error _ -> + let+ r = Tezos_signer_backends.Encrypted.decrypt cctxt sk_uri in + let sk = Option.of_result r in + Option.bind sk Signature.Of_V_latest.secret_key + in + let key_from_alias alias = + let warning msg alias = + let* () = cctxt#warning msg alias in + return_none + in + let* key = + let* r = Client_keys.alias_keys cctxt alias in + match r with + | Error _ | Ok None -> + warning "Alias \"%s\" not found in the wallet" alias + | Ok (Some (_, None, _)) | Ok (Some (_, _, None)) -> + warning + "Alias \"%s\" does not contain public or secret key and could not \ + be used for stresstest" + alias + | Ok (Some (pkh, Some pk, Some sk_uri)) -> ( + let* o = sk_of_sk_uri sk_uri in + match o with + | None -> + warning + "Cannot extract the secret key form the alias \"%s\" of the \ + wallet" + alias + | Some sk -> + Lwt.return_some + {source = {pkh; pk; sk}; origin = Wallet_alias alias}) + in + match key with + | None -> warning "Source given as alias \"%s\" ignored" alias + | key -> Lwt.return key + in + let key_from_wallet pkh = + let warning msg pkh = + let* () = cctxt#warning msg Signature.Public_key_hash.pp pkh in + return_none + in + let* key = + let* r = Client_keys.get_key cctxt pkh in + match r with + | Error _ -> warning "Pkh \"%a\" not found in the wallet" pkh + | Ok (alias, pk, sk_uri) -> ( + let* o = sk_of_sk_uri sk_uri in + match o with + | None -> + let* () = + cctxt#warning + "Cannot extract the secret key form the pkh \"%a\" (alias: \ + \"%s\") of the wallet" + Signature.Public_key_hash.pp + pkh + alias + in + Lwt.return_none + | Some sk -> + Lwt.return_some {source = {pkh; pk; sk}; origin = Wallet_pkh}) + in + match key with + | None -> warning "Source given as pkh \"%a\" ignored" pkh + | key -> Lwt.return key + in + function + | Explicit source -> Lwt.return_some {source; origin = Explicit} + | Wallet_alias alias -> key_from_alias alias + | Wallet_pkh pkh -> key_from_wallet pkh + +(** [unnormalize_source src_org] converts [src_org] from normalized data + structure to in-output one. *) +let unnormalize_source src_org = + match src_org.origin with + | Explicit -> Explicit src_org.source + | Wallet_pkh -> Wallet_pkh src_org.source.pkh + | Wallet_alias alias -> Wallet_alias alias + +(** Samples from [state.pool]. Used to generate the destination of a + transfer. *) +let sample_any_source_from_pool state = + let idx = Random.State.int state.rng_state state.pool_size in + match List.nth state.pool idx with + | None -> assert false + | Some src_org -> Lwt.return src_org.source + +(** Takes and returns a source from [state.shuffled_pool]. Waits for a + new block if no source is available. *) +let rec get_source_from_shuffled_pool state + (cctxt : Protocol_client_context.full) = + let open Lwt_syntax in + match state.shuffled_pool with + | source :: l -> + state.shuffled_pool <- l ; + let* () = + log Debug (fun () -> + cctxt#message + "sample_transfer: %d unused sources for the block next to %a" + (List.length l) + Block_hash.pp + state.last_block) + in + Lwt.return source + | [] -> + let* () = + cctxt#message + "all available sources have been used for block next to %a" + Block_hash.pp + state.last_block + in + let* () = Lwt_condition.wait state.new_block_condition in + get_source_from_shuffled_pool state cctxt + +let random_seed rng = + Bytes.init 32 (fun _ -> Char.chr (Random.State.int rng 256)) + +let generate_fresh_source state = + let seed = random_seed state.rng_state in + let pkh, pk, sk = Signature.generate_key ~seed () in + let fresh = {source = {pkh; pk; sk}; origin = Explicit} in + state.pool <- fresh :: state.pool ; + state.pool_size <- state.pool_size + 1 ; + fresh.source + +(* [heads_iter cctxt f] calls [f head] each time there is a new head received + by the streamed RPC /monitor/heads/main and returns [promise, stopper]. + [promise] resolved when the stream is closed. [stopper ()] closes the + stream. *) +let heads_iter (cctxt : Protocol_client_context.full) + (f : Block_hash.t * Tezos_base.Block_header.t -> unit tzresult Lwt.t) : + (unit tzresult Lwt.t * Tezos_rpc.Context.stopper) tzresult Lwt.t = + let open Lwt_result_syntax in + let* heads_stream, stopper = Shell_services.Monitor.heads cctxt `Main in + let rec loop () : unit tzresult Lwt.t = + let*! block_hash_and_header = Lwt_stream.get heads_stream in + match block_hash_and_header with + | None -> cctxt#error "unexpected end of block stream@." + | Some ((new_block_hash, _block_header) as block_hash_and_header) -> + Lwt.catch + (fun () -> + let*! () = + log Debug (fun () -> + cctxt#message + "heads_iter: new block received %a@." + Block_hash.pp + new_block_hash) + in + let* protocols = + Shell_services.Blocks.protocols + cctxt + ~block:(`Hash (new_block_hash, 0)) + () + in + if Protocol_hash.(protocols.current_protocol = Protocol.hash) then + let* () = f block_hash_and_header in + loop () + else + let*! () = + log Debug (fun () -> + cctxt#message + "heads_iter: new block on protocol %a. Stopping \ + iteration.@." + Protocol_hash.pp + protocols.current_protocol) + in + return_unit) + (fun exn -> + cctxt#error + "An exception occurred on a function bound on new heads : %s@." + (Printexc.to_string exn)) + in + let promise = loop () in + let*! () = + log Debug (fun () -> + cctxt#message + "head iteration for proto %a stopped@." + Protocol_hash.pp + Protocol.hash) + in + return (promise, stopper) + +let sample_smart_contracts smart_contracts rng_state = + let smart_contract = + Smart_contracts.select smart_contracts (Random.State.float rng_state 1.0) + in + Option.map + (fun invocation_parameters -> + ( Originated invocation_parameters, + invocation_parameters.fee, + invocation_parameters.gas_limit )) + smart_contract + +(* We perform rejection sampling of valid sources. + We could maintain a local cache of existing contracts with sufficient balance. *) +let rec sample_transfer (cctxt : Protocol_client_context.full) chain block + (parameters : parameters) (state : state) = + let open Lwt_result_syntax in + let*! src = get_source_from_shuffled_pool state cctxt in + let* tez = + Alpha_services.Contract.balance + cctxt + (chain, block) + (Contract.Implicit src.pkh) + in + if Tez.(tez = zero) then + let*! () = + log Debug (fun () -> + cctxt#message + "sample_transfer: invalid balance %a" + Signature.Public_key_hash.pp + src.pkh) + in + (* Sampled source has zero balance: the transfer that created that + address was not included yet. Retry *) + sample_transfer cctxt chain block parameters state + else + let fresh = + Random.State.float state.rng_state 1.0 < parameters.fresh_probability + in + let* dst, fee, gas_limit = + match + sample_smart_contracts parameters.smart_contracts state.rng_state + with + | None -> + let*! dest = + if fresh then Lwt.return (generate_fresh_source state) + else sample_any_source_from_pool state + in + return + ( Implicit dest.pkh, + parameters.regular_transfer_fee, + parameters.regular_transfer_gas_limit ) + | Some v -> return v + in + let amount = + match parameters.strategy with + | Fixed_amount {mutez} -> mutez + | Evaporation {fraction} -> + let mutez = Int64.to_float (Tez.to_mutez tez) in + let max_fraction = Int64.of_float (mutez *. fraction) in + let amount = + if max_fraction = 0L then 1L + else max 1L (Random.State.int64 state.rng_state max_fraction) + in + Tez.of_mutez_exn amount + in + return {src; dst; fee; gas_limit; amount; counter = None; fresh_dst = fresh} + +let inject_contents (cctxt : Protocol_client_context.full) branch sk contents = + let bytes = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + let signature = + Some (Signature.sign ~watermark:Signature.Generic_operation sk bytes) + in + let op : _ Operation.t = + {shell = {branch}; protocol_data = {contents; signature}} + in + let bytes = + Data_encoding.Binary.to_bytes_exn Operation.encoding (Operation.pack op) + in + Shell_services.Injection.operation cctxt bytes + +(* counter _must_ be set before calling this function *) +let manager_op_of_transfer parameters + {src; dst; fee; gas_limit; amount; counter; fresh_dst} = + let source = src.pkh in + let storage_limit = + if fresh_dst then + Z.add parameters.account_creation_storage parameters.storage_limit + else parameters.storage_limit + in + let operation = + let parameters = + let open Tezos_micheline in + Script.lazy_expr + (match dst with + | Implicit _ -> + Micheline.strip_locations + (Prim (0, Michelson_v1_primitives.D_Unit, [], [])) + | Originated x -> x.arg) + in + let entrypoint = + match dst with + | Implicit _ -> Entrypoint.default + | Originated x -> x.entrypoint + in + let destination = destination_to_contract dst in + Transaction {amount; parameters; entrypoint; destination} + in + match counter with + | None -> assert false + | Some counter -> + Manager_operation + {source; fee; counter; operation; gas_limit; storage_limit} + +let cost_of_manager_operation = Gas.Arith.integral_of_int_exn 1_000 + +let inject_transfer (cctxt : Protocol_client_context.full) parameters state + transfer = + let open Lwt_result_syntax in + let* branch = Shell_services.Blocks.hash cctxt () in + let* current_counter = + Alpha_services.Contract.counter cctxt (`Main, `Head 0) transfer.src.pkh + in + let* already_revealed = + if Signature.Public_key_hash.Set.mem transfer.src.pkh state.revealed then + return true + else ( + (* Either the [manager_key] RPC tells us the key is already + revealed, or we immediately inject a reveal operation: in any + case the key is revealed in the end. *) + state.revealed <- + Signature.Public_key_hash.Set.add transfer.src.pkh state.revealed ; + let* pk_opt = + Alpha_services.Contract.manager_key + cctxt + (`Main, `Head 0) + transfer.src.pkh + in + return (Option.is_some pk_opt)) + in + let*! r = + if not already_revealed then + let reveal_counter = Manager_counter.succ current_counter in + let transf_counter = Manager_counter.succ reveal_counter in + let reveal = + Manager_operation + { + source = transfer.src.pkh; + fee = Tez.zero; + counter = reveal_counter; + gas_limit = cost_of_manager_operation; + storage_limit = Z.zero; + operation = Reveal transfer.src.pk; + } + in + let manager_op = + manager_op_of_transfer + parameters + {transfer with counter = Some transf_counter} + in + let list = Cons (reveal, Single manager_op) in + let*! () = + log Info (fun () -> + cctxt#message + "injecting reveal+transfer from %a (counters=%a,%a) to %a" + Signature.Public_key_hash.pp + transfer.src.pkh + Manager_counter.pp + reveal_counter + Manager_counter.pp + transf_counter + Contract.pp + (destination_to_contract transfer.dst)) + in + (* NB: regardless of our best efforts to keep track of counters, injection can fail with + "counter in the future" if a block switch happens in between the moment we + get the branch and the moment we inject, and the new block does not include + all the operations we injected. *) + inject_contents cctxt state.target_block transfer.src.sk list + else + let transf_counter = Manager_counter.succ current_counter in + let manager_op = + manager_op_of_transfer + parameters + {transfer with counter = Some transf_counter} + in + let list = Single manager_op in + let*! () = + log Info (fun () -> + cctxt#message + "injecting transfer from %a (counter=%a) to %a" + Signature.Public_key_hash.pp + transfer.src.pkh + Manager_counter.pp + transf_counter + Contract.pp + (destination_to_contract transfer.dst)) + in + (* See comment above. *) + inject_contents cctxt state.target_block transfer.src.sk list + in + match r with + | Ok op_hash -> + let*! () = + log Debug (fun () -> + cctxt#message + "inject_transfer: op injected %a" + Operation_hash.pp + op_hash) + in + let ops = + Option.value + ~default:[] + (Block_hash.Table.find state.injected_operations branch) + in + Block_hash.Table.replace state.injected_operations branch (op_hash :: ops) ; + return_unit + | Error e -> + let*! () = + log Debug (fun () -> + cctxt#message + "inject_transfer: error, op not injected: %a" + Error_monad.pp_print_trace + e) + in + return_unit + +let save_injected_operations (cctxt : Protocol_client_context.full) state = + let open Lwt_syntax in + let json = + Data_encoding.Json.construct + injected_operations_encoding + (Block_hash.Table.fold + (fun k v acc -> (k, v) :: acc) + state.injected_operations + []) + in + let path = + Filename.temp_file "client-stresstest-injected_operations-" ".json" + in + let* () = cctxt#message "writing injected operations in file %s" path in + let* r = Lwt_utils_unix.Json.write_file path json in + match r with + | Error e -> + cctxt#message + "could not write injected operations json file: %a" + Error_monad.pp_print_trace + e + | Ok _ -> Lwt.return_unit + +let stat_on_exit (cctxt : Protocol_client_context.full) state = + let open Lwt_result_syntax in + let ratio_injected_included_op () = + let* current_head_on_exit = Shell_services.Blocks.hash cctxt () in + let inter_cardinal s1 s2 = + Operation_hash.Set.cardinal + (Operation_hash.Set.inter + (Operation_hash.Set.of_list s1) + (Operation_hash.Set.of_list s2)) + in + let get_included_ops older_block = + let rec get_included_ops block acc_included_ops = + if block = older_block then return acc_included_ops + else + let* included_ops = + Shell_services.Chain.Blocks.Operation_hashes + .operation_hashes_in_pass + cctxt + ~chain:`Main + ~block:(`Hash (block, 0)) + 3 + in + let* bs = + Shell_services.Blocks.list + cctxt + ~chain:`Main + ~heads:[block] + ~length:2 + () + in + match bs with + | [[current; predecessor]] when current = block -> + get_included_ops + predecessor + (List.append acc_included_ops included_ops) + | _ -> cctxt#error "Error while computing stats: invalid block list" + in + get_included_ops current_head_on_exit [] + in + let injected_ops = + Block_hash.Table.fold + (fun k l acc -> + (* The operations injected during the last block are ignored because + they should not be currently included. *) + if current_head_on_exit <> k then List.append acc l else acc) + state.injected_operations + [] + in + let* included_ops = get_included_ops state.current_head_on_start in + let included_ops_count = inter_cardinal injected_ops included_ops in + let*! () = + log Debug (fun () -> + cctxt#message + "injected : [%a]@.included: [%a]" + (Format.pp_print_list ~pp_sep Operation_hash.pp) + injected_ops + (Format.pp_print_list ~pp_sep Operation_hash.pp) + included_ops) + in + let injected_ops_count = List.length injected_ops in + let*! () = + cctxt#message + "%s of the injected operations have been included (%d injected, %d \ + included). Note that the operations injected during the last block \ + are ignored because they should not be currently included." + (if Int.equal injected_ops_count 0 then "N/A" + else + Format.sprintf "%d%%" (included_ops_count * 100 / injected_ops_count)) + injected_ops_count + included_ops_count + in + return_unit + in + ratio_injected_included_op () + +let launch (cctxt : Protocol_client_context.full) (parameters : parameters) + state save_pool_callback = + let injected = ref 0 in + let target_level = + match parameters.level_limit with + | None -> None + | Some (Abs target) -> Some target + | Some (Rel offset) -> Some (state.last_level + offset) + in + let dt = 1. /. parameters.tps in + let terminated () = + let open Lwt_syntax in + if + match parameters.total_transfers with + | None -> false + | Some bound -> bound <= !injected + then + let* () = + cctxt#message + "Stopping after %d injections (target %a)." + !injected + Format.(pp_print_option pp_print_int) + parameters.total_transfers + in + Lwt.return_true + else + match target_level with + | None -> Lwt.return_false + | Some target -> + if target <= state.last_level then + let* () = + cctxt#message + "Stopping at level %d (target level: %d)." + state.last_level + target + in + Lwt.return_true + else Lwt.return_false + in + + let rec loop () = + let open Lwt_result_syntax in + let*! terminated = terminated () in + if terminated then + let*! () = save_pool_callback () in + let*! () = save_injected_operations cctxt state in + stat_on_exit cctxt state + else + let start = Mtime_clock.counter () in + let*! () = + log Debug (fun () -> + cctxt#message "launch.loop: invoke sample_transfer") + in + let* transfer = + sample_transfer cctxt cctxt#chain cctxt#block parameters state + in + let*! () = + log Debug (fun () -> + cctxt#message "launch.loop: invoke inject_transfer") + in + let* () = inject_transfer cctxt parameters state transfer in + incr injected ; + let elapsed = Time.Monotonic.Span.to_float_s (Mtime_clock.count start) in + let remaining = dt -. elapsed in + let*! () = + if remaining <= 0.0 then + cctxt#warning + "warning: tps target could not be reached, consider using a lower \ + value for --tps" + else Lwt_unix.sleep remaining + in + loop () + in + let on_new_head : + Block_hash.t * Tezos_base.Block_header.t -> unit tzresult Lwt.t = + (* Because of how Tenderbake works the target block should stay 2 + blocks in the past because this guarantees that we are targeting a + block that is decided. *) + let open Lwt_result_syntax in + let update_target_block () = + let* target_block = + Shell_services.Blocks.hash cctxt ~block:(`Head 2) () + in + state.target_block <- target_block ; + return_unit + in + fun (new_block_hash, new_block_header) -> + let* () = update_target_block () in + if not (Block_hash.equal new_block_hash state.last_block) then ( + state.last_block <- new_block_hash ; + state.last_level <- Int32.to_int new_block_header.shell.level ; + state.shuffled_pool <- + List.shuffle + ~rng:state.rng_state + (List.map (fun src_org -> src_org.source) state.pool)) ; + Lwt_condition.broadcast state.new_block_condition () ; + return_unit + in + let open Lwt_result_syntax in + let* heads_iteration, stopper = heads_iter cctxt on_new_head in + (* The head iteration stops at protocol change. *) + let* () = Lwt.pick [loop (); heads_iteration] in + (match Lwt.state heads_iteration with Lwt.Return _ -> () | _ -> stopper ()) ; + return_unit + +let group = + Tezos_clic. + {name = "stresstest"; title = "Commands for stress-testing the network"} + +let input_source_list_encoding = Data_encoding.list input_source_encoding + +let pool_source_param = + Client_proto_args.json_encoded_with_origin_parameter + ~name:"input source list" + input_source_list_encoding + +let seed_arg = + let open Tezos_clic in + arg + ~long:"seed" + ~placeholder:"int" + ~doc:"random seed" + (parameter (fun (cctxt : Protocol_client_context.full) s -> + match int_of_string s with + | exception _ -> + cctxt#error + "While parsing --seed: could not convert argument to int" + | i -> Lwt_result_syntax.return i)) + +let tps_arg = + let open Tezos_clic in + arg + ~long:"tps" + ~placeholder:"float" + ~doc:"transactions per seconds target" + (parameter (fun (cctxt : Protocol_client_context.full) s -> + match float_of_string s with + | exception _ -> + cctxt#error + "While parsing --tps: could not convert argument to float" + | f when f < 0.0 -> + cctxt#error "While parsing --tps: negative argument" + | f -> Lwt_result_syntax.return f)) + +let fresh_probability_arg = + let open Tezos_clic in + arg + ~long:"fresh-probability" + ~placeholder:"float in [0;1]" + ~doc: + (Format.sprintf + "Probability for each transaction's destination to be a fresh \ + account. The default value is %g. This new account may then be used \ + as source or destination of subsequent transactions, just like the \ + accounts that were initially provided to the command. Note that when \ + [--single-op-per-pkh-per-block] is set, the new account will not be \ + used as source until the head changes." + default_parameters.fresh_probability) + (parameter (fun (cctxt : Protocol_client_context.full) s -> + match float_of_string s with + | exception _ -> + cctxt#error + "While parsing --fresh-probability: could not convert argument \ + to float" + | f when f < 0.0 || f > 1.0 -> + cctxt#error "While parsing --fresh-probability: invalid argument" + | f -> Lwt_result_syntax.return f)) + +let smart_contract_parameters_arg = + let open Tezos_clic in + arg + ~long:"smart-contract-parameters" + ~placeholder:"JSON file with smart contract parameters" + ~doc: + (Format.sprintf + "A JSON object that maps smart contract aliases to objects with three \ + fields: probability in [0;1], invocation_fee, and \ + invocation_gas_limit.") + (Client_proto_args.json_encoded_parameter + ~name:"smart contract" + Smart_contracts.contract_parameters_collection_encoding) + +let strategy_arg = + let open Tezos_clic in + arg + ~long:"strategy" + ~placeholder:"fixed:mutez | evaporation:[0;1]" + ~doc:"wealth redistribution strategy" + (parameter (fun (cctxt : Protocol_client_context.full) s -> + match parse_strategy s with + | Error msg -> cctxt#error "While parsing --strategy: %s" msg + | Ok strategy -> Lwt_result_syntax.return strategy)) + +let gas_limit_arg = + let open Tezos_clic in + let gas_limit_kind = + parameter (fun (cctxt : #Client_context.full) s -> + try + let v = Z.of_string s in + Lwt_result_syntax.return (Gas.Arith.integral_exn v) + with _ -> cctxt#error "invalid gas limit (must be a positive number)") + in + arg + ~long:"gas-limit" + ~short:'G' + ~placeholder:"amount" + ~doc: + (Format.asprintf + "Set the gas limit of the transaction instead of using the default \ + value of %a" + Gas.Arith.pp_integral + default_parameters.regular_transfer_gas_limit) + gas_limit_kind + +let storage_limit_arg = + let open Tezos_clic in + let storage_limit_kind = + parameter (fun (cctxt : #Client_context.full) s -> + try + let v = Z.of_string s in + assert (Compare.Z.(v >= Z.zero)) ; + Lwt_result_syntax.return v + with _ -> + cctxt#error + "invalid storage limit (must be a positive number of bytes)") + in + arg + ~long:"storage-limit" + ~short:'S' + ~placeholder:"amount" + ~doc: + (Format.asprintf + "Set the storage limit of the transaction instead of using the \ + default value of %a" + Z.pp_print + default_parameters.storage_limit) + storage_limit_kind + +let transfers_arg = + let open Tezos_clic in + arg + ~long:"transfers" + ~placeholder:"integer" + ~doc:"total number of transfers to perform, unbounded if not specified" + (parameter (fun (cctxt : Protocol_client_context.full) s -> + match int_of_string s with + | exception _ -> + cctxt#error "While parsing --transfers: invalid integer literal" + | i when i <= 0 -> + cctxt#error "While parsing --transfers: negative integer" + | i -> Lwt_result_syntax.return i)) + +let level_limit_arg = + let open Tezos_clic in + arg + ~long:"level-limit" + ~placeholder:"integer | +integer" + ~doc: + "Level at which the stresstest will stop (if prefixed by '+', the level \ + is relative to the current head)" + (parameter (fun (cctxt : Protocol_client_context.full) s -> + let open Lwt_result_syntax in + match int_of_string s with + | exception _ -> + cctxt#error "While parsing --levels: invalid integer literal" + | i when i <= 0 -> + cctxt#error "While parsing --levels: negative integer or zero" + | i -> if String.get s 0 = '+' then return (Rel i) else return (Abs i))) + +let verbose_arg = + Tezos_clic.switch + ~long:"verbose" + ~short:'v' + ~doc:"Display detailed logs of the injected operations" + () + +let debug_arg = + Tezos_clic.switch ~long:"debug" ~short:'V' ~doc:"Display debug logs" () + +let set_option opt f x = Option.fold ~none:x ~some:(f x) opt + +let save_pool_callback (cctxt : Protocol_client_context.full) pool_source state + = + let json = + Data_encoding.Json.construct + input_source_list_encoding + (List.map unnormalize_source state.pool) + in + let catch_write_error = function + | Error e -> + cctxt#message + "could not write back json file: %a" + Error_monad.pp_print_trace + e + | Ok () -> Lwt.return_unit + in + let open Lwt_syntax in + match pool_source with + | Client_proto_args.Text _ -> + (* If the initial pool was given directly as json, save pool to + a temp file. *) + let path = Filename.temp_file "client-stresstest-pool-" ".json" in + let* () = cctxt#message "writing back address pool in file %s" path in + let* r = Lwt_utils_unix.Json.write_file path json in + catch_write_error r + | File {path; _} -> + (* If the pool specification was a json file, save pool to + the same file. *) + let* () = cctxt#message "writing back address pool in file %s" path in + let* r = Lwt_utils_unix.Json.write_file path json in + catch_write_error r + +let generate_random_transactions = + let open Tezos_clic in + command + ~group + ~desc:"Generate random transactions" + (args12 + seed_arg + tps_arg + fresh_probability_arg + smart_contract_parameters_arg + strategy_arg + Client_proto_args.fee_arg + gas_limit_arg + storage_limit_arg + transfers_arg + level_limit_arg + verbose_arg + debug_arg) + (prefixes ["stresstest"; "transfer"; "using"] + @@ param + ~name:"sources.json" + ~desc: + {|List of accounts from which to perform transfers in JSON format. The input JSON must be an array of objects of the form {"pkh":"","pk":"","sk":""} or {"alias":""} or {"pkh":""} with the pkh, pk and sk encoded in B58 form."|} + pool_source_param + @@ stop) + (fun ( seed, + tps, + freshp, + smart_contract_parameters, + strat, + fee, + gas_limit, + storage_limit, + transfers, + level_limit, + verbose_flag, + debug_flag ) + pool_source + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + (verbosity := + match (debug_flag, verbose_flag) with + | true, _ -> Debug + | false, true -> Info + | false, false -> Notice) ; + let* smart_contracts = + Smart_contracts.init + cctxt + (Option.value ~default:[] smart_contract_parameters) + in + let parameters = + {default_parameters with smart_contracts} + |> set_option seed (fun parameter seed -> {parameter with seed}) + |> set_option tps (fun parameter tps -> {parameter with tps}) + |> set_option freshp (fun parameter fresh_probability -> + {parameter with fresh_probability}) + |> set_option strat (fun parameter strategy -> + {parameter with strategy}) + |> set_option fee (fun parameter regular_transfer_fee -> + {parameter with regular_transfer_fee}) + |> set_option gas_limit (fun parameter regular_transfer_gas_limit -> + {parameter with regular_transfer_gas_limit}) + |> set_option storage_limit (fun parameter storage_limit -> + {parameter with storage_limit}) + |> set_option transfers (fun parameter transfers -> + {parameter with total_transfers = Some transfers}) + |> set_option level_limit (fun parameter level_limit -> + {parameter with level_limit = Some level_limit}) + in + match Client_proto_args.content_of_file_or_text pool_source with + | [] -> cctxt#error "It is required to provide sources" + | sources -> + let*! () = + log Info (fun () -> cctxt#message "starting to normalize sources") + in + let*! sources = List.filter_map_s (normalize_source cctxt) sources in + let*! () = + log Info (fun () -> + cctxt#message "all sources have been normalized") + in + let sources = + List.sort_uniq + (fun src1 src2 -> + Signature.Secret_key.compare src1.source.sk src2.source.sk) + sources + in + let rng_state = Random.State.make [|parameters.seed|] in + let* current_head_on_start = Shell_services.Blocks.hash cctxt () in + let* header_on_start = + Shell_services.Blocks.Header.shell_header cctxt () + in + let* () = + if header_on_start.level <= 2l then + cctxt#error + "The level of the head (%a) needs to be greater than 2 and is \ + actually %ld." + Block_hash.pp + current_head_on_start + header_on_start.level + else return_unit + in + let* current_target_block = + Shell_services.Blocks.hash cctxt ~block:(`Head 2) () + in + let state = + { + rng_state; + current_head_on_start; + pool = sources; + pool_size = List.length sources; + shuffled_pool = + List.shuffle + ~rng:rng_state + (List.map (fun src_org -> src_org.source) sources); + revealed = Signature.Public_key_hash.Set.empty; + last_block = current_head_on_start; + last_level = Int32.to_int header_on_start.level; + target_block = current_target_block; + new_block_condition = Lwt_condition.create (); + injected_operations = Block_hash.Table.create 1023; + } + in + let exit_callback_id = + Lwt_exit.register_clean_up_callback ~loc:__LOC__ (fun _retcode -> + let*! r = stat_on_exit cctxt state in + match r with + | Ok () -> Lwt.return_unit + | Error e -> + cctxt#message "Error: %a" Error_monad.pp_print_trace e) + in + let save_pool () = save_pool_callback cctxt pool_source state in + (* Register a callback for saving the pool when the tool is interrupted + through ctrl-c *) + let exit_callback_id = + Lwt_exit.register_clean_up_callback + ~loc:__LOC__ + ~after:[exit_callback_id] + (fun _retcode -> save_pool ()) + in + let save_injected_operations () = + save_injected_operations cctxt state + in + ignore + (Lwt_exit.register_clean_up_callback + ~loc:__LOC__ + ~after:[exit_callback_id] + (fun _retcode -> save_injected_operations ())) ; + launch cctxt parameters state save_pool) + +let estimate_transaction_cost ?smart_contracts + (cctxt : Protocol_client_context.full) : Gas.Arith.integral tzresult Lwt.t = + let open Lwt_result_syntax in + let*! src = normalize_source cctxt (Wallet_alias "bootstrap1") in + let*! dst = normalize_source cctxt (Wallet_alias "bootstrap2") in + let rng_state = Random.State.make [|default_parameters.seed|] in + let* src, dst = + match (src, dst) with + | Some src, Some dst -> return (src, dst) + | _ -> + cctxt#error + "Cannot find bootstrap1 or bootstrap2 accounts in the wallet." + in + let chain = cctxt#chain in + let block = cctxt#block in + let selected_smart_contract = + Option.bind smart_contracts (fun smart_contracts -> + sample_smart_contracts smart_contracts rng_state) + in + let dst, fee, gas_limit = + Option.value + selected_smart_contract + ~default: + ( Implicit dst.source.pkh, + default_parameters.regular_transfer_fee, + default_parameters.regular_transfer_gas_limit ) + in + let* current_counter = + Alpha_services.Contract.counter cctxt (chain, block) src.source.pkh + in + let transf_counter = Manager_counter.succ current_counter in + let transfer = + { + src = src.source; + dst; + fee; + gas_limit; + amount = Tez.of_mutez_exn (Int64.of_int 1); + counter = Some transf_counter; + fresh_dst = false; + } + in + let manager_op = + manager_op_of_transfer + { + default_parameters with + regular_transfer_gas_limit = + Default_parameters.constants_mainnet.hard_gas_limit_per_operation; + } + transfer + in + let* _oph, op, result = + Injection.simulate cctxt ~chain ~block (Single manager_op) + in + match result.contents with + | Single_result (Manager_operation_result {operation_result; _}) -> ( + match operation_result with + | Applied + (Transaction_result + (Transaction_to_contract_result {consumed_gas; _})) -> + return (Gas.Arith.ceil consumed_gas) + | _ -> + (match operation_result with + | Failed (_, errors) -> + Error_monad.pp_print_trace + Format.err_formatter + (Environment.wrap_tztrace errors) + | _ -> assert false) ; + cctxt#error + "@[Simulation result:@,%a@]" + Operation_result.pp_operation_result + (op.protocol_data.contents, result.contents)) + +let estimate_transaction_costs : Protocol_client_context.full Tezos_clic.command + = + let open Tezos_clic in + command + ~group + ~desc:"Output gas estimations for transactions that stresstest uses" + no_options + (prefixes ["stresstest"; "estimate"; "gas"] @@ stop) + (fun () cctxt -> + let open Lwt_result_syntax in + let* regular = estimate_transaction_cost cctxt in + let* smart_contracts = + Smart_contracts.with_every_known_smart_contract + cctxt + (fun smart_contracts -> + estimate_transaction_cost ~smart_contracts cctxt) + in + let transaction_costs : transaction_costs = {regular; smart_contracts} in + let json = + Data_encoding.Json.construct + transaction_costs_encoding + transaction_costs + in + Format.printf "%a" Data_encoding.Json.pp json ; + return_unit) + +(* Returns a list of transfers from each element of [sources]. *) +let generate_transfers ~sources ~amount ~parameters ~entrypoint ~fee ~gas_limit + ~storage_limit = + List.map + (fun dst -> + let destination = Contract.Implicit dst.pkh in + let transfer = + Client_proto_context.build_transaction_operation + ~amount + ~parameters + ~entrypoint + ~fee + ~gas_limit + ~storage_limit + destination + in + Annotated_manager_operation.Annotated_manager_operation transfer) + sources + +(* Returns a list of reveals from each element of [sources]. *) +let generate_reveals ~sources ~fee ~gas_limit ~storage_limit = + List.map + (fun dst -> + let reveal = + Client_proto_context.build_reveal_operation + ~fee + ~gas_limit + ~storage_limit + dst.pk + in + (dst, Annotated_manager_operation.Annotated_manager_operation reveal)) + sources + +(* Given a list of [sources], it returns + - a list of batches of transfers where each batch has a maximum of + [batch_size] operation, for each element of [sources], + - a list of reveals, for each element of [sources]. + + [sources] is the list of "starter" accounts, used to fund all + accounts in a exponential way. +*) +let generate_starter_ops ~sources ~amount ~batch_size = + let fee = Tez.of_mutez_exn 1_000L in + let gas_limit = Gas.Arith.integral_of_int_exn 1_040 in + let storage_limit = Z.of_int 257 in + let parameters = + let open Tezos_micheline in + Script.lazy_expr + (Micheline.strip_locations + (Prim (0, Michelson_v1_primitives.D_Unit, [], []))) + in + let entrypoint = Entrypoint.default in + let txs_ops = + generate_transfers + ~sources + ~amount + ~parameters + ~entrypoint + ~fee + ~gas_limit + ~storage_limit + in + let reveal_ops = generate_reveals ~sources ~fee ~gas_limit ~storage_limit in + let rec split n acc = function + | [] -> acc + | l -> + let current, next = List.rev_split_n n l in + let batch = Annotated_manager_operation.manager_of_list current in + split n (batch :: acc) next + in + (* Split the list of transfers into N batches containing a maximum + of [batch_size] operations. *) + let txs_batch_l = split batch_size [] txs_ops in + (txs_batch_l, reveal_ops) + +(* Returns a list of list of batch. A list of batch consists of N + batches, depending on the number of [starter_sources]. The top + level list can be seen a block partition, so that the 1M + restriction is ensured. *) +let generate_account_funding_batches (starter_sources : source_with_uri list) + (empty_accounts : source_with_uri list) ~batch_size ~amount = + let open Lwt_result_syntax in + let nb_sources = List.length starter_sources in + let fee = Tez.of_mutez_exn 1_000L in + let gas_limit = Gas.Arith.integral_of_int_exn 1_040 in + let storage_limit = Z.of_int 257 in + let parameters = + let open Tezos_micheline in + Script.lazy_expr + (Micheline.strip_locations + (Prim (0, Michelson_v1_primitives.D_Unit, [], []))) + in + let entrypoint = Entrypoint.default in + let to_batch candidates emiters = + (* For each [emiters], it generates [batch_size] transactions from + it, and to [batch_size] candidates.*) + let rec aux acc (candidates : source_with_uri list) + (emiters : source_with_uri list) = + match emiters with + | [] -> return acc + | source :: next_sources -> + let current, next_candidates = + List.rev_split_n batch_size candidates + in + let txs = + generate_transfers + ~sources:current + ~amount + ~parameters + ~entrypoint + ~fee + ~gas_limit + ~storage_limit + in + let batch = Annotated_manager_operation.manager_of_list txs in + (*Avoid the generation of empty batches*) + if next_candidates = [] then return ((source, batch) :: acc) + else aux ((source, batch) :: acc) next_candidates next_sources + in + aux [] candidates emiters + in + let rec aux acc = function + | [] -> return acc + | empty_accounts -> + let candidates, rest = + List.rev_split_n (batch_size * nb_sources) empty_accounts + in + let* batch = to_batch candidates starter_sources in + aux (batch :: acc) rest + in + let* res = aux [] empty_accounts in + return res + +(* Loads a wallet by reading directly the files to speed up things. *) +let load_wallet cctxt ~source_pkh = + let open Lwt_result_syntax in + let* keys = Client_keys.get_keys cctxt in + (* Convert loaded and filter identities. We want to ban activator + and bootstrap<1-5> in sandbox, as well as the "faucet source" on + test networks. *) + let to_ban = + ["activator"; "bootstrap"] + @ WithExceptions.Result.get_ok + ~loc:__LOC__ + (List.init ~when_negative_length:"error" 5 (fun i -> + Format.sprintf "bootstrap%d" (i + 1))) + in + let rec aux acc = function + | [] -> return acc + | (alias, pkh, _, _) :: tl + when List.exists (String.equal alias) to_ban + || Signature.Public_key_hash.equal pkh source_pkh -> + aux acc tl + | (_, pkh, pk, sk_uri) :: tl -> + let* pk_uri = Client_keys.neuterize sk_uri in + let payload = + Uri.path (sk_uri : Tezos_signer_backends.Unencrypted.sk_uri :> Uri.t) + in + let sk = Signature.Secret_key.of_b58check_exn payload in + aux ({pkh; pk; pk_uri; sk; sk_uri} :: acc) tl + in + aux [] keys + +let source_key_arg = + let open Tezos_clic in + param + ~name:"source_key_arg" + ~desc: + "Source key public key hash from which the tokens will be transferred to \ + start the funding." + (parameter (fun (cctxt : #Client_context.full) s -> + let r = Signature.Public_key_hash.of_b58check s in + match r with + | Ok pkh -> Lwt_result_syntax.return pkh + | Error e -> + cctxt#error + "Cannot read public key hash: %a" + Error_monad.pp_print_trace + e)) + +let batch_size_arg = + let open Tezos_clic in + default_arg + ~long:"batch-size" + ~placeholder:"integer" + ~doc: + "Maximum number of operations that can be put into a single batch (250 \ + by default)" + ~default:"250" + (parameter (fun (cctxt : #Client_context.full) s -> + match int_of_string_opt s with + | Some i when i > 0 -> Lwt_result_syntax.return i + | Some _ -> cctxt#error "Integer must be positive." + | None -> cctxt#error "Cannot read integer")) + +let batches_per_block_arg = + let open Tezos_clic in + default_arg + ~long:"batches-per-block" + ~placeholder:"integer" + ~doc: + "Maximum number of batches that can be put into a single block (100 by \ + default)" + ~default:"100" + (parameter (fun (cctxt : #Client_context.full) s -> + match int_of_string_opt s with + | Some i when i > 0 -> Lwt_result_syntax.return i + | Some _ -> cctxt#error "Integer must be positive." + | None -> cctxt#error "Cannot read integer")) + +let initial_amount_arg = + let open Tezos_clic in + default_arg + ~long:"initial-amount" + ~placeholder:"integer" + ~doc: + "Number of token, in μtz, that will be funded on each of the accounts to \ + fund (1 by default)" + ~default:"1_000_000" + (parameter (fun (cctxt : #Client_context.full) s -> + match Int64.of_string_opt s with + | Some i when i > 0L -> ( + try Lwt_result_syntax.return (Tez.of_mutez_exn i) + with e -> + cctxt#error "Cannot convert to Tez.t:%s" (Printexc.to_string e)) + | Some _ -> cctxt#error "Integer must be positive." + | None -> cctxt#error "Cannot read integer")) + +(* Monitors the node's head to inject transaction batches. *) +let inject_batched_txs cctxt (source_pkh, source_pk, source_sk) + ~(starter_batch : Annotated_manager_operation.packed_annotated_list list) + ~fee ~gas_limit ~storage_limit ~fee_parameter batches_per_block = + let open Lwt_result_syntax in + let chain = cctxt#chain in + let* heads_stream, stop = Shell_services.Monitor.heads cctxt chain in + let rec aux stream + (sources_ops : Annotated_manager_operation.packed_annotated_list list) = + let*! v = Lwt_stream.get stream in + match v with + | Some (_block_hash, _) -> ( + match sources_ops with + | [] -> + stop () ; + return [] + | sources_ops -> + let now, next = List.rev_split_n batches_per_block sources_ops in + let* () = + List.iter_ep + (fun batch -> + let (Annotated_manager_operation.Manager_list contents) = + batch + in + let* _results = + Injection.inject_manager_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run:false + ~verbose_signing:false + ~simulation:false + ~force:false + ~source:source_pkh + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ~src_pk:source_pk + ~src_sk:source_sk + ~replace_by_fees:false + ~fee_parameter + contents + in + return_unit) + now + in + aux stream next) + | None -> + let*! () = Lwt_unix.sleep 0.5 in + aux stream sources_ops + in + let* _ = aux heads_stream starter_batch in + return_unit + +(* Monitors the node's head to inject reveal batches. *) +let inject_batched_reveals cctxt + ~(starter_reveals : + (source_with_uri * Annotated_manager_operation.packed) list) ~fee + ~gas_limit ~storage_limit ~fee_parameter batches_per_block = + let open Lwt_result_syntax in + let chain = cctxt#chain in + let* heads_stream, stop = Shell_services.Monitor.heads cctxt chain in + let rec aux stream + (sources_ops : + (source_with_uri * Annotated_manager_operation.packed) list) = + let*! v = Lwt_stream.get stream in + match v with + | Some (_block_hash, _) -> ( + match sources_ops with + | [] -> + stop () ; + return [] + | sources_ops -> + let now, next = List.rev_split_n batches_per_block sources_ops in + let* () = + List.iter_ep + (fun (source, op) -> + let (Annotated_manager_operation.Manager_list contents) = + Annotated_manager_operation.manager_of_list [op] + in + let* _ = + Injection.inject_manager_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run:false + ~verbose_signing:false + ~simulation:false + ~force:false + ~source:source.pkh + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ~src_pk:source.pk + ~src_sk:source.sk_uri + ~replace_by_fees:false + ~fee_parameter + contents + in + return_unit) + now + in + aux stream next) + | None -> + let*! () = Lwt_unix.sleep 0.5 in + aux stream sources_ops + in + let* _ = aux heads_stream starter_reveals in + return_unit + +(* Monitors the node's head to inject transaction batches. *) +let inject_funding_batches cctxt + ~(funding_batches : + (source_with_uri * Annotated_manager_operation.packed_annotated_list) + list + list) ~fee ~gas_limit ~storage_limit ~fee_parameter batches_per_block = + let open Lwt_result_syntax in + let chain = cctxt#chain in + let* heads_stream, stop = Shell_services.Monitor.heads cctxt chain in + let rec aux stream + (sources_ops : + (source_with_uri * Annotated_manager_operation.packed_annotated_list) + list + list) = + let*! v = Lwt_stream.get stream in + match v with + | Some (_block_hash, _) -> ( + match sources_ops with + | [] -> + stop () ; + return [] + | block_ops :: tl -> + let now, next = List.rev_split_n batches_per_block block_ops in + let* () = + List.iter_ep + (fun (source, batch) -> + let (Annotated_manager_operation.Manager_list contents) = + batch + in + let* _results = + Injection.inject_manager_operation + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run:false + ~verbose_signing:false + ~simulation:false + ~force:false + ~source:source.pkh + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + ~src_pk:source.pk + ~src_sk:source.sk_uri + ~replace_by_fees:false + ~fee_parameter + contents + in + return_unit) + now + in + if next = [] then aux stream tl else aux stream (next :: tl)) + | None -> + let*! () = Lwt_unix.sleep 0.5 in + aux stream sources_ops + in + let* _ = aux heads_stream funding_batches in + return_unit + +(* This command aims to fund accounts to be used in pair with the + stresstest transfer command. To do so, it will proceed in the + following steps: + - takes all the identities found in a given wallet, + - chooses [batch_size] identities as starters , + - funds the starters with some funds (using source account), + - reveal the starters (using source account), + - makes and injects batches so that the starters uses their funds to + fund the [nb_identities - nb_starters] remaining accounts. + + These steps allows to minimize the number of + transfers/operations/blocks to fund many accounts. + + As parameters, it is possible to chose: + - batch_size: number of operations into a single batch, + - batches_per_block: number of batches/operations per block, + - initial_amount: number of token distributed to each accounts. + It also allows to define additional parameters, such as fee, gas + and storage limit. +*) +let fund_accounts_from_source : Protocol_client_context.full Tezos_clic.command + = + let open Tezos_clic in + command + ~group + ~desc:"Funds all the given accounts" + (args7 + batch_size_arg + batches_per_block_arg + initial_amount_arg + Client_proto_args.default_fee_arg + Client_proto_args.default_gas_limit_arg + Client_proto_args.default_storage_limit_arg + Client_proto_args.fee_parameter_args) + (prefixes ["stresstest"; "fund"; "accounts"; "from"] + @@ source_key_arg @@ stop) + (fun ( batch_size, + batches_per_block, + initial_amount, + fee, + gas_limit, + storage_limit, + fee_parameter ) + source_pkh + (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* source_pk, source_sk = + let* _, src_pk, src_sk = Client_keys.get_key cctxt source_pkh in + return (src_pk, src_sk) + in + let*! () = log Notice (fun () -> cctxt#message "@.") in + let*! () = + log Notice (fun () -> + cctxt#message + "Starting funding from %a with parameters:@.- batch_size %d@.- \ + batches_per_block %d@.- initial_amount %a@." + Signature.Public_key_hash.pp + source_pkh + batch_size + batches_per_block + Tez.pp + initial_amount) + in + (* All generated sources *) + let* new_sources = load_wallet cctxt ~source_pkh in + (* Starter sources used to initiate the "exponential" + funding. *) + let nb_starters = + let l = List.length new_sources in + (l / batch_size) + if l mod batch_size = 0 then 0 else 1 + in + let starter_sources, empty_accounts = + List.rev_split_n nb_starters new_sources + in + let*! () = + log Notice (fun () -> + cctxt#message + "Funding %d accounts using %d starters@." + (List.length new_sources) + nb_starters) + in + (* Initial amount that is sent to starters to allow them to fund + other accounts. This is an over approximation. *) + let starter_initial_amount = + (* over approximation of the max number of operation that a + starter may inject. We add one to leave the starter account + with it's own initial amount. *) + let max_nb_transfers = batch_size + 1 in + (* Fees are: reveal + max_nb_transfers * manager_fees + = reveal + max_nb_transfers * (storage_fees + tx fees) + = 0.001tz + max_nb_transfers * (0.06425tz + 0.001tz) + =~ max_nb_transfers * 0.1 tz *) + let fees_approx = Tez.of_mutez_exn 100_000L in + let amount = + WithExceptions.Result.get_ok + ~loc:__LOC__ + Tez.(initial_amount +? fees_approx) + in + Tez.mul_exn amount max_nb_transfers + in + let*! () = + log Notice (fun () -> + cctxt#message + "Sending %a tz to starter accounts@." + Tez.pp + starter_initial_amount) + in + let* source_balance = + Alpha_services.Contract.balance + cctxt + (cctxt#chain, cctxt#block) + (Contract.Implicit source_pkh) + in + let* () = + let req_balance = Tez.mul_exn starter_initial_amount nb_starters in + if Tez.(source_balance < req_balance) then + cctxt#error + "Not enough funds to init starter accounts: %a are needed, only %a \ + is available on %a@." + Tez.pp + source_balance + Tez.pp + req_balance + Signature.Public_key_hash.pp + source_pkh + else + let*! () = + log Notice (fun () -> + cctxt#message + "Transfering %a tz from %a (out of %a)@." + Tez.pp + req_balance + Signature.Public_key_hash.pp + source_pkh + Tez.pp + source_balance) + in + return_unit + in + let*! () = + log Notice (fun () -> + cctxt#message "Generating starter transactions and reveals@.") + in + let starter_batch, starter_reveals = + generate_starter_ops + ~sources:starter_sources + ~amount:starter_initial_amount + ~batch_size + in + (* Inject generated batches and reveals for the starters. *) + let*! () = + log Notice (fun () -> + cctxt#message "Injecting starter transfer batches@.") + in + let* () = + inject_batched_txs + cctxt + (source_pkh, source_pk, source_sk) + ~starter_batch + ~fee + ~gas_limit + ~storage_limit + ~fee_parameter + batches_per_block + in + let*! () = + log Notice (fun () -> + cctxt#message "Injecting starter reveal batches@.") + in + let* () = + inject_batched_reveals + cctxt + ~starter_reveals + ~fee + ~gas_limit + ~storage_limit + ~fee_parameter + batches_per_block + in + let*! () = + log Notice (fun () -> cctxt#message "Generating funding batches@.") + in + let* funding_batches = + generate_account_funding_batches + starter_sources + empty_accounts + ~batch_size + ~amount:initial_amount + in + let*! () = + log Notice (fun () -> cctxt#message "Injecting funding batches@.") + in + let* () = + inject_funding_batches + cctxt + ~funding_batches + ~fee + ~gas_limit + ~storage_limit + ~fee_parameter + batches_per_block + in + let*! () = log Notice (fun () -> cctxt#message "Done.@.") in + return_unit) + +let commands = + [ + generate_random_transactions; + estimate_transaction_costs; + Smart_contracts.originate_command; + fund_accounts_from_source; + ] + +let commands network () = + match network with Some `Mainnet -> [] | Some `Testnet | None -> commands diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.mli b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.mli new file mode 100644 index 000000000000..c272f2c4a642 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : + [`Mainnet | `Testnet] option -> + unit -> + Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.ml new file mode 100644 index 000000000000..15a92d49b811 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.ml @@ -0,0 +1,258 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type contract_parameters = { + probability : float; + invocation_fee : Tez.t; + invocation_gas_limit : Gas.Arith.integral; +} + +let contract_parameters_encoding = + let open Data_encoding in + conv + (fun {probability; invocation_fee; invocation_gas_limit} -> + (probability, invocation_fee, invocation_gas_limit)) + (fun (probability, invocation_fee, invocation_gas_limit) -> + {probability; invocation_fee; invocation_gas_limit}) + (obj3 + (req "probability" float) + (req "invocation_fee" Tez.encoding) + (req "invocation_gas_limit" Gas.Arith.n_integral_encoding)) + +let contract_parameters_collection_encoding = + let open Data_encoding in + assoc contract_parameters_encoding + +(** Internal representation of a supported smart contract. *) +type smart_contract = { + alias : string; (** Human-readable alias of the contract *) + mainnet_address : string; (** Address this contract has on Mainnet *) + initial_storage : string; (** Initial storage (used for origination) *) + origination_fee_cap : Tez.t; (** Origination fee cap *) + origination_burn_cap : Tez.t; (** Origination burn cap *) + code : Script.expr; (** Code of the smart contract *) + invocation_arg : Script.expr; + (** Argument for invocations during the stress test *) + invocation_entrypoint : Entrypoint_repr.t; + (** Entrypoint for invocations during the stress test *) +} + +type t = (contract_parameters * Contract.t * smart_contract) list + +let no_contracts = [] + +let parse_michelson_expr_exn expr = + let open Tezos_micheline in + match + Micheline_parser.no_parsing_error + (Michelson_v1_parser.parse_expression expr) + with + | Ok x -> x.expanded + | Error _ -> Stdlib.failwith "parse_michelson_expr_exn" + +let parse_michelson_toplevel_exn expr = + let open Tezos_micheline in + match + Micheline_parser.no_parsing_error + (Michelson_v1_parser.parse_toplevel ?check:(Some true) expr) + with + | Ok x -> x.expanded + | Error _ -> Stdlib.failwith "parse_michelson_toplevel_exn" + +let hic_et_nunc = + { + alias = "hic_et_nunc"; + mainnet_address = "KT1RJ6PbjHpwc3M5rw5s2Nbmefwbuwbdxton"; + initial_storage = + {| (Pair (Pair "tz1invkmrRJev6TvH9CvhpLN4auk4cik8G5Y" (Pair 1 {Elt (Pair "tz1invkmrRJev6TvH9CvhpLN4auk4cik8G5Y" 0) 1}))(Pair (Pair {} {})(Pair False {Elt 0 (Pair 0 {})}))) +|}; + code = + parse_michelson_toplevel_exn + {| + storage ( pair ( pair ( address %administrator ) ( pair ( nat %all_tokens ) ( big_map %ledger ( pair address nat ) nat ) ) ) ( pair ( pair ( big_map %metadata string bytes ) ( big_map %operators ( pair ( address %owner ) ( pair ( address %operator ) ( nat %token_id ) ) ) unit ) ) ( pair ( bool %paused ) ( big_map %token_metadata nat ( pair ( nat %token_id ) ( map %token_info string bytes ) ) ) ) ) ) ; + parameter (or (or (or (pair %balance_of (list %requests (pair (address %owner) (nat %token_id))) (contract %callback (list (pair (pair %request (address %owner) (nat %token_id)) (nat %balance))))) (list %hDAO_batch (pair (nat %amount) (address %to_)))) (or (pair %mint (pair (address %address) (nat %amount)) (pair (nat %token_id) (map %token_info string bytes))) (address %set_administrator))) (or (or (bool %set_pause) (pair %token_metadata (list %token_ids nat) (lambda %handler (list (pair (nat %token_id) (map %token_info string bytes)))unit))) (or (list %transfer (pair (address %from_) (list %txs (pair (address %to_) (pair (nat %token_id) (nat %amount)))))) (list %update_Hunitoperators (or (pair %add_operator (address %owner) (pair (address %operator) (nat %token_id))) (pair %remove_operator (address %owner) (pair (address %operator) (nat %token_id)))))))); + code { DUP ; CDR ; SWAP ; CAR ; IF_LEFT { IF_LEFT { IF_LEFT { SWAP ; DUP ; DUG 2 ; CDR ; CDR ; CAR ; IF { PUSH int 722 ; FAILWITH } {} ; DUP ; CAR ; MAP { DIG 2 ; DUP ; DUG 3 ; CDR ; CDR ; CDR ; SWAP ; DUP ; DUG 2 ; CDR ; MEM ; IF {} { PUSH string "FA2_TOKEN_UNDEFINED" ; FAILWITH } ; DIG 2 ; DUP ; DUG 3 ; CAR ; CDR ; CDR ; SWAP ; DUP ; CDR ; SWAP ; DUP ; DUG 3 ; CAR ; PAIR ; MEM ; IF { DIG 2 ; DUP ; DUG 3 ; CAR ; CDR ; CDR ; SWAP ; DUP ; CDR ; SWAP ; DUP ; DUG 3 ; CAR ; PAIR ; GET ; IF_NONE { PUSH int 729 ; FAILWITH } {} ; SWAP ; PAIR %request %balance } { PUSH nat 0 ; SWAP ; PAIR %request %balance } } ; NIL operation ; DIG 2 ; CDR ; PUSH mutez 0 ; DIG 3 ; TRANSFER_TOKENS ; CONS } { SWAP ; DUP ; DUG 2 ; CAR ; CAR ; SENDER ; COMPARE ; EQ ; IF {} { PUSH int 776 ; FAILWITH } ; DUP ; ITER { DIG 2 ; DUP ; DUG 3 ; CAR ; CDR ; CDR ; PUSH nat 0 ; DIG 2 ; DUP ; DUG 3 ; CDR ; PAIR ; MEM ; IF { DIG 2 ; DUP ; DUG 3 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DUP ; PUSH nat 0 ; DIG 6 ; DUP ; DUG 7 ; CDR ; PAIR ; DUP ; DUG 2 ; GET ; IF_NONE { PUSH int 781 ; FAILWITH } { DROP } ; DIG 5 ; DUP ; DUG 6 ; CAR ; DIG 8 ; CAR ; CDR ; CDR ; PUSH nat 0 ; DIG 8 ; CDR ; PAIR ; GET ; IF_NONE { PUSH int 781 ; FAILWITH } {} ; ADD ; SOME ; SWAP ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; SWAP } { DIG 2 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DIG 4 ; DUP ; DUG 5 ; CAR ; SOME ; PUSH nat 0 ; DIG 6 ; CDR ; PAIR ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; SWAP } ; SWAP ; DUP ; DUG 2 ; CDR ; CDR ; CDR ; PUSH nat 0 ; MEM ; IF {} { SWAP ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; EMPTY_MAP string bytes ; PUSH string "ipfs://QmSVsfwH8es7Ur2eqto9hVpcd2dfWASmEaNxTPpcymuJzg" ; PACK ; SOME ; PUSH string "" ; UPDATE ; PUSH nat 0 ; PAIR %token_id %token_info ; SOME ; PUSH nat 0 ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; SWAP ; PAIR ; SWAP } } ; DROP ; NIL operation } } { IF_LEFT { SWAP ; DUP ; DUG 2 ; CAR ; CAR ; SENDER ; COMPARE ; NEQ ; IF {} { PUSH int 820 ; FAILWITH } ; SWAP ; DUP ; DUG 2 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; CDR ; DIG 4 ; CAR ; CDR ; CAR ; DUP ; PUSH nat 1 ; DIG 6 ; DUP ; DUG 7 ; CDR ; CAR ; ADD ; DUP ; DUG 2 ; COMPARE ; LE ; IF { DROP } { SWAP ; DROP } ; PAIR ; SWAP ; PAIR ; PAIR ; DUP ; DUG 2 ; CAR ; CDR ; CDR ; SWAP ; DUP ; CDR ; CAR ; SWAP ; DUP ; DUG 3 ; CAR ; CAR ; PAIR ; MEM ; IF { SWAP ; DUP ; DUG 2 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DUP ; DIG 5 ; DUP ; CDR ; CAR ; SWAP ; DUP ; DUG 7 ; CAR ; CAR ; PAIR ; DUP ; DUG 2 ; GET ; IF_NONE { PUSH int 832 ; FAILWITH } { DROP } ; DIG 5 ; DUP ; DUG 6 ; CAR ; CDR ; DIG 7 ; CAR ; CDR ; CDR ; DIG 7 ; DUP ; CDR ; CAR ; SWAP ; DUP ; DUG 9 ; CAR ; CAR ; PAIR ; GET ; IF_NONE { PUSH int 832 ; FAILWITH } {} ; ADD ; SOME ; SWAP ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; SWAP } { SWAP ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DIG 4 ; DUP ; DUG 5 ; CAR ; CDR ; SOME ; DIG 5 ; DUP ; CDR ; CAR ; SWAP ; DUP ; DUG 7 ; CAR ; CAR ; PAIR ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; SWAP } ; SWAP ; DUP ; DUG 2 ; CDR ; CDR ; CDR ; SWAP ; DUP ; DUG 2 ; CDR ; CAR ; MEM ; IF { DROP } { SWAP ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DIG 4 ; DUP ; CDR ; CDR ; SWAP ; DUP ; DUG 6 ; CDR ; CAR ; PAIR %token_id %token_info ; SOME ; DIG 5 ; CDR ; CAR ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; SWAP ; PAIR } } { SWAP ; DUP ; DUG 2 ; CAR ; CAR ; SENDER ; COMPARE ; EQ ; IF {} { PUSH int 805 ; FAILWITH } ; SWAP ; DUP ; CDR ; SWAP ; CAR ; CDR ; DIG 2 ; PAIR ; PAIR } ; NIL operation } } { IF_LEFT { IF_LEFT { SWAP ; DUP ; DUG 2 ; CAR ; CAR ; SENDER ; COMPARE ; EQ ; IF {} { PUSH int 814 ; FAILWITH } ; SWAP ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; CDR ; DIG 3 ; PAIR ; SWAP ; PAIR ; SWAP ; PAIR } { SWAP ; DUP ; DUG 2 ; CDR ; CDR ; CAR ; IF { PUSH int 855 ; FAILWITH } {} ; DUP ; CDR ; SWAP ; DUP ; DUG 2 ; CAR ; MAP { DIG 3 ; DUP ; DUG 4 ; CDR ; CDR ; CDR ; SWAP ; GET ; IF_NONE { PUSH int 865 ; FAILWITH } {} } ; DIG 2 ; DROP ; EXEC ; DROP } } { IF_LEFT { SWAP ; DUP ; DUG 2 ; CDR ; CDR ; CAR ; IF { PUSH int 679 ; FAILWITH } {} ; DUP ; ITER { DUP ; CDR ; ITER { DIG 3 ; DUP ; DUG 4 ; CAR ; CAR ; SENDER ; COMPARE ; NEQ ; IF { PUSH bool True } { SENDER ; DIG 2 ; DUP ; DUG 3 ; CAR ; COMPARE ; EQ } ; IF { PUSH bool True } { DIG 3 ; DUP ; DUG 4 ; CDR ; CAR ; CDR ; SWAP ; DUP ; DUG 2 ; CDR ; CAR ; SENDER ; PAIR %operator %token_id ; DIG 3 ; DUP ; DUG 4 ; CAR ; PAIR %owner ; MEM } ; IF {} { PUSH string "FA2_NOT_OPERATOR" ; FAILWITH } ; DIG 3 ; DUP ; DUG 4 ; CDR ; CDR ; CDR ; SWAP ; DUP ; DUG 2 ; CDR ; CAR ; MEM ; IF {} { PUSH string "FA2_TOKEN_UNDEFINED" ; FAILWITH } ; DUP ; CDR ; CDR ; PUSH nat 0 ; COMPARE ; LT ; IF { DUP ; CDR ; CDR ; DIG 4 ; DUP ; DUG 5 ; CAR ; CDR ; CDR ; DIG 2 ; DUP ; DUG 3 ; CDR ; CAR ; DIG 4 ; DUP ; DUG 5 ; CAR ; PAIR ; GET ; IF_NONE { PUSH int 706 ; FAILWITH } {} ; COMPARE ; GE ; IF {} { PUSH string "FA2_INSUFFICIENT_BALANCE" ; FAILWITH } ; DIG 3 ; DUP ; DUG 4 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DUP ; DIG 5 ; DUP ; DUG 6 ; CDR ; CAR ; DIG 7 ; DUP ; DUG 8 ; CAR ; PAIR ; DUP ; DUG 2 ; GET ; IF_NONE { PUSH int 710 ; FAILWITH } { DROP } ; DIG 5 ; DUP ; DUG 6 ; CDR ; CDR ; DIG 9 ; CAR ; CDR ; CDR ; DIG 7 ; DUP ; DUG 8 ; CDR ; CAR ; DIG 9 ; DUP ; DUG 10 ; CAR ; PAIR ; GET ; IF_NONE { PUSH int 710 ; FAILWITH } {} ; SUB ; ISNAT ; IF_NONE { PUSH int 710 ; FAILWITH } {} ; SOME ; SWAP ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; DUP ; DUG 4 ; CAR ; CDR ; CDR ; SWAP ; DUP ; CDR ; CAR ; SWAP ; DUP ; DUG 3 ; CAR ; PAIR ; MEM ; IF { DIG 3 ; DUP ; DUG 4 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DUP ; DIG 5 ; DUP ; CDR ; CAR ; SWAP ; DUP ; DUG 7 ; CAR ; PAIR ; DUP ; DUG 2 ; GET ; IF_NONE { PUSH int 713 ; FAILWITH } { DROP } ; DIG 5 ; DUP ; DUG 6 ; CDR ; CDR ; DIG 9 ; CAR ; CDR ; CDR ; DIG 7 ; DUP ; CDR ; CAR ; SWAP ; CAR ; PAIR ; GET ; IF_NONE { PUSH int 713 ; FAILWITH } {} ; ADD ; SOME ; SWAP ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; DUG 2 } { DIG 3 ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; DUP ; CAR ; SWAP ; CDR ; DIG 4 ; DUP ; DUG 5 ; CDR ; CDR ; SOME ; DIG 5 ; DUP ; CDR ; CAR ; SWAP ; CAR ; PAIR ; UPDATE ; SWAP ; PAIR ; SWAP ; PAIR ; PAIR ; DUG 2 } } { DROP } } ; DROP } ; DROP } { DUP ; ITER { IF_LEFT { DUP ; CAR ; SENDER ; COMPARE ; EQ ; IF { PUSH bool True } { DIG 2 ; DUP ; DUG 3 ; CAR ; CAR ; SENDER ; COMPARE ; EQ } ; IF {} { PUSH int 758 ; FAILWITH } ; DIG 2 ; DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; PUSH ( option unit ) ( Some Unit ) ; DIG 5 ; DUP ; CDR ; CDR ; SWAP ; DUP ; DUG 7 ; CDR ; CAR ; PAIR %operator %token_id ; DIG 6 ; CAR ; PAIR %owner ; UPDATE ; SWAP ; PAIR ; PAIR ; SWAP ; PAIR ; SWAP } { DUP ; CAR ; SENDER ; COMPARE ; EQ ; IF { PUSH bool True } { DIG 2 ; DUP ; DUG 3 ; CAR ; CAR ; SENDER ; COMPARE ; EQ } ; IF {} { PUSH int 765 ; FAILWITH } ; DIG 2 ; DUP ; CAR ; SWAP ; CDR ; DUP ; CDR ; SWAP ; CAR ; DUP ; CAR ; SWAP ; CDR ; NONE unit ; DIG 5 ; DUP ; CDR ; CDR ; SWAP ; DUP ; DUG 7 ; CDR ; CAR ; PAIR %operator %token_id ; DIG 6 ; CAR ; PAIR %owner ; UPDATE ; SWAP ; PAIR ; PAIR ; SWAP ; PAIR ; SWAP } } ; DROP } } ; NIL operation } ; PAIR} + |}; + origination_fee_cap = Tez.of_mutez_exn 5_000L; + origination_burn_cap = Tez.of_mutez_exn 1_500_000L; + invocation_arg = + parse_michelson_expr_exn + {|{ Pair "tz1invkmrRJev6TvH9CvhpLN4auk4cik8G5Y" { Pair "tz1invkmrRJev6TvH9CvhpLN4auk4cik8G5Y" ( Pair 0 1 ) } } |}; + invocation_entrypoint = Entrypoint_repr.of_string_strict_exn "transfer"; + } + +(** This is the list of all supported smart contracts. If you wish to add + support for a new smart contract all you need to do is to extend this + list. *) +let all_contracts = [hic_et_nunc] + +let init (cctxt : Protocol_client_context.full) + (contract_parameters : (string * contract_parameters) list) : + t tzresult Lwt.t = + let open Lwt_result_syntax in + let sum_of_probabilities = + List.fold_left + (fun acc (_, {probability; _}) -> acc +. probability) + 0.0 + contract_parameters + in + let* () = + if sum_of_probabilities > 1.0 then + failwith "sum of smart contract call probabilities is greater than 1.0!" + else return_unit + in + let init_one (alias, params) = + let* contract = + Client_proto_contracts.Contract_alias.get_contract cctxt alias + in + let* smart_contract = + match List.find (fun x -> String.equal alias x.alias) all_contracts with + | None -> failwith "unknown smart contract alias: %s" alias + | Some x -> return x + in + return (params, contract, smart_contract) + in + List.map_es init_one contract_parameters + +type invocation_parameters = { + destination : Contract.t; + entrypoint : Entrypoint_repr.t; + arg : Script.expr; + fee : Tez.t; + gas_limit : Gas.Arith.integral; +} + +let select (smart_contracts : t) (q : float) : invocation_parameters option = + let rec go xs0 x = + match xs0 with + | [] -> None + | (params, contract, smart_contract) :: xs1 -> + if x < params.probability then + Some + { + destination = contract; + entrypoint = smart_contract.invocation_entrypoint; + arg = smart_contract.invocation_arg; + fee = params.invocation_fee; + gas_limit = params.invocation_gas_limit; + } + else go xs1 (x -. params.probability) + in + go smart_contracts q + +let originate_command = + let open Tezos_clic in + let open Client_proto_context in + let open Client_proto_context_commands in + command + ~group + ~desc:"Originate all supported smart contracts for use in the stresstest." + no_options + (prefixes ["stresstest"; "originate"; "smart"; "contracts"; "from"] + @@ Client_keys.Public_key_hash.source_param + ~name:"src" + ~desc:"name of the source contract" + @@ stop) + (fun () source (cctxt : Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* _, src_pk, src_sk = Client_keys.get_key cctxt source in + let originate_one (scontract : smart_contract) = + let fee_parameter = + { + Injection.minimal_fees = Tez.of_mutez_exn 100L; + minimal_nanotez_per_byte = Q.of_int 1000; + minimal_nanotez_per_gas_unit = Q.of_int 100; + force_low_fee = false; + fee_cap = scontract.origination_fee_cap; + burn_cap = scontract.origination_burn_cap; + } + in + let*! errors = + originate_contract + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~delegate:None + ~initial_storage:scontract.initial_storage + ~balance:Tez.zero (* initial balance *) + ~source + ~src_pk + ~src_sk + ~code:scontract.code + ~fee_parameter + () + in + let*! r = + report_michelson_errors + ~no_print_source:true + ~msg:"origination simulation failed" + cctxt + errors + in + match r with + | None -> return_unit + | Some (_res, contract) -> + save_contract ~force:false cctxt scontract.alias contract + in + List.iter_es originate_one all_contracts) + +let with_every_known_smart_contract cctxt callback = + let open Lwt_result_syntax in + let items = + List.map + (fun x -> + ( x.alias, + { + probability = 0.0; + invocation_fee = Tez.zero; + invocation_gas_limit = + Default_parameters.constants_mainnet.hard_gas_limit_per_operation; + } )) + all_contracts + in + let* smart_contracts = init cctxt items in + let rec go xs0 = + match xs0 with + | [] -> return [] + | (contract_parameters, contract, smart_contract) :: xs1 -> + let* r = + callback + [ + ( {contract_parameters with probability = 1.0}, + contract, + smart_contract ); + ] + in + let* rs = go xs1 in + return ((smart_contract.alias, r) :: rs) + in + go smart_contracts + +let mainnet_address_to_alias address = + List.find (fun x -> String.equal x.mainnet_address address) all_contracts + |> Option.map (fun x -> x.alias) diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.mli b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.mli new file mode 100644 index 000000000000..774cf49f383a --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_contracts.mli @@ -0,0 +1,88 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** The information that the user has to provide for every smart contract + they want to call during the stress test. *) +type contract_parameters = { + probability : float; (** The probability of calling this smart contract *) + invocation_fee : Tez.t; + (** Fee to use for invocations during the stress test *) + invocation_gas_limit : Gas.Arith.integral; + (** Gas limit to use for invocations during the stress test *) +} + +(** Encoding of [contract_parameters]. *) +val contract_parameters_encoding : contract_parameters Data_encoding.t + +(** Contract parameters collection encoding. *) +val contract_parameters_collection_encoding : + (string * contract_parameters) list Data_encoding.t + +(** An opaque type that stores all the information that is necessary for + efficient sampling of smart contract calls. *) +type t + +(** A value with no smart contracts. *) +val no_contracts : t + +(** Convert a map of probabilities per smart contract alias to a [t] value. + *) +val init : + Protocol_client_context.full -> + (string * contract_parameters) list -> + t tzresult Lwt.t + +(** All information that is necessary for performing a smart contract call + during the stress test. *) +type invocation_parameters = { + destination : Contract.t; + entrypoint : Entrypoint_repr.t; + arg : Script.expr; + fee : Tez.t; + gas_limit : Gas.Arith.integral; +} + +(** Given [t] initialized earlier and a [float] in [0;1], decide + which smart contract is going to be chosen for the next call, if any. *) +val select : t -> float -> invocation_parameters option + +(** A ready-to-use command that originates all supported smart contracts. *) +val originate_command : Protocol_client_context.full Tezos_clic.command + +(** Call the callback function once per supported smart contract by passing + it [t] that only selects that smart contract. Collect the + results and pair them with the respective smart contract aliases. This + is used for e.g. gas estimations. *) +val with_every_known_smart_contract : + Protocol_client_context.full -> + (t -> 'a tzresult Lwt.t) -> + (string * 'a) list tzresult Lwt.t + +(** Return the alias that corresponds to the smart contract address on the + Mainnet. Return [None] if the given address is not supported. *) +val mainnet_address_to_alias : string -> string option diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.ml new file mode 100644 index 000000000000..609d7806a0ee --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.ml @@ -0,0 +1,179 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Client_proto_utils + +let group = {Tezos_clic.name = "utilities"; title = "Utility Commands"} + +let unsigned_block_header_param = + let open Tezos_clic in + param + ~name:"unsigned block header" + ~desc:"A hex or JSON encoded unsigned block header" + @@ parameter (fun (cctxt : #Client_context.full) s -> + let open Lwt_result_syntax in + let bytes_opt = `Hex s |> Hex.to_bytes in + let enc = Protocol.Alpha_context.Block_header.unsigned_encoding in + Option.bind bytes_opt (Data_encoding.Binary.of_bytes_opt enc) + |> function + | Some s -> return s + | None -> ( + let open Data_encoding.Json in + let error = + "Cannot decode unsigned block header: is it valid JSON or \ + hexadecimal?" + in + from_string s |> function + | Error _ -> cctxt#error "%s" error + | Ok json -> ( + try destruct enc json |> return + with _ -> cctxt#error "%s" error))) + +let commands () = + let open Tezos_clic in + let string_param ~name ~desc = + param ~name ~desc Client_proto_args.string_parameter + in + let block_arg = + default_arg + ~long:"branch" + ~short:'b' + ~placeholder:"hash|tag" + ~doc: + "Block hash used to create the no-op operation to sign (possible tags \ + are 'head' and 'genesis'). Defaults to 'genesis'. Note that the the \ + genesis block hash is network-dependent." + ~default:(Block_services.to_string `Genesis) + (Client_config.block_parameter ()) + in + [ + command + ~group + ~desc: + "Sign a message and display it using the failing_noop operation. This \ + operation is not executable in the protocol. Please note that \ + signing/checking an arbitrary message in itself is not sufficient to \ + verify a key ownership" + (args1 block_arg) + (prefixes ["sign"; "message"] + @@ string_param ~name:"message" ~desc:"message to sign" + @@ prefixes ["for"] + @@ Client_keys.Secret_key.source_param + ~name:"src" + ~desc:"name of the signer contract" + @@ stop) + (fun block_head message src_sk cctxt -> + let open Lwt_result_syntax in + let* block = + Shell_services.Blocks.hash + cctxt + ~chain:cctxt#chain + ~block:block_head + () + in + let* signature = sign_message cctxt ~src_sk ~block ~message in + let*! () = cctxt#message "Signature: %a" Signature.pp signature in + return_unit); + command + ~group + ~desc: + "Check the signature of an arbitrary message using the failing_noop \ + operation. Please note that signing/checking an arbitrary message in \ + itself is not sufficient to verify a key ownership." + (args2 + block_arg + (switch ~doc:"Use only exit codes" ~short:'q' ~long:"quiet" ())) + (prefixes ["check"; "that"; "message"] + @@ string_param ~name:"message" ~desc:"signed message" + @@ prefixes ["was"; "signed"; "by"] + @@ Client_keys.Public_key.source_param + ~name:"signer" + ~desc:"name of the signer contract" + @@ prefixes ["to"; "produce"] + @@ param + ~name:"signature" + ~desc:"the signature to check" + Client_proto_args.signature_parameter + @@ stop) + (fun (block_head, quiet) + message + (key_locator, _) + signature + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let* block = + Shell_services.Blocks.hash + cctxt + ~chain:cctxt#chain + ~block:block_head + () + in + let* check = + check_message cctxt ~key_locator ~block ~quiet ~message ~signature + in + if check then + if quiet then return_unit + else + let*! () = cctxt#message "Signature check successful" in + return_unit + else cctxt#error "invalid signature"); + command + ~group + ~desc: + "Sign an arbitrary unsigned block header for a given delegate and \ + return the signed block." + no_options + (prefixes ["sign"; "block"] + @@ unsigned_block_header_param @@ prefixes ["for"] + @@ Client_keys.Public_key_hash.source_param + ~name:"delegate" + ~desc:"signing delegate" + @@ stop) + (fun () + unsigned_block_header + delegate + (cctxt : #Protocol_client_context.full) -> + let open Lwt_result_syntax in + let unsigned_header = + Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Block_header.unsigned_encoding + unsigned_block_header + in + let* chain_id = + Shell_services.Chain.chain_id cctxt ~chain:cctxt#chain () + in + let* _, _, sk = Client_keys.get_key cctxt delegate in + let* s = + Client_keys.sign + cctxt + ~watermark: + (Protocol.Alpha_context.Block_header.to_watermark + (Block_header chain_id)) + sk + unsigned_header + in + let*! () = cctxt#message "%a" Hex.pp (Signature.to_hex s) in + return_unit); + ] diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.mli b/src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.mli new file mode 100644 index 000000000000..110ad45cdffd --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_utils_commands.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_client_commands/dune b/src/proto_020_PsParisC/lib_client_commands/dune new file mode 100644 index 000000000000..ed33aaddf65c --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_commands/dune @@ -0,0 +1,72 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_client_019_PtParisB_commands) + (public_name octez-protocol-019-PtParisB-libs.client.commands) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.parameters + octez-libs.stdlib-unix + octez-proto-libs.protocol-environment + octez-shell-libs.shell-services + octez-shell-libs.mockup + octez-shell-libs.mockup-registration + octez-shell-libs.mockup-commands + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-libs.rpc + octez-shell-libs.client-base-unix + octez-protocol-019-PtParisB-libs.plugin + uri) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_stdlib_unix + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_client_base_unix + -open Tezos_protocol_plugin_019_PtParisB) + (modules (:standard \ alpha_commands_registration))) + +(library + (name tezos_client_019_PtParisB_commands_registration) + (public_name octez-protocol-019-PtParisB-libs.client.commands-registration) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.parameters + octez-proto-libs.protocol-environment + octez-shell-libs.shell-services + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-protocol-019-PtParisB-libs.client.commands + octez-protocol-019-PtParisB-libs.client.sapling + octez-libs.rpc + octez-protocol-019-PtParisB-libs.plugin) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_client_019_PtParisB_commands + -open Tezos_client_sapling_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB) + (modules alpha_commands_registration)) diff --git a/src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.ml b/src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.ml new file mode 100644 index 000000000000..9f4732e89ce2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.ml @@ -0,0 +1,788 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Client_keys +open Tezos_sapling.Core.Client + +let json_switch = Tezos_clic.switch ~long:"json" ~doc:"Use JSON format" () + +let save_json_to_file json file = + let output_channel = open_out_bin file in + let ppf = Format.formatter_of_out_channel output_channel in + Data_encoding.Json.pp ppf json ; + Format.pp_print_flush ppf () ; + close_out output_channel + +let group = + { + Tezos_clic.name = "sapling"; + title = "Commands for working with Sapling transactions"; + } + +let keys_of_implicit_account cctxt source = + let open Lwt_result_syntax in + let* _, pk, sk = Client_keys.get_key cctxt source in + return (pk, sk) + +let viewing_key_of_string s = + let exception Unknown_sapling_address in + let encoding = Viewing_key.address_b58check_encoding in + WithExceptions.Option.to_exn + ~none:Unknown_sapling_address + (Tezos_crypto.Base58.simple_decode encoding s) + +(** All signatures are done with an anti-replay string. + In Tezos' protocol this string is set to be chain_id + KT1. **) +let anti_replay cctxt contract = + let open Lwt_result_syntax in + let* chain_id = + Tezos_shell_services.Chain_services.chain_id cctxt ~chain:cctxt#chain () + in + let address = Protocol.Contract_hash.to_b58check contract in + let chain_id = Chain_id.to_b58check chain_id in + return (address ^ chain_id) + +(** The shielded tez contract expects the recipient pkh encoded in Micheline + in the bound_data of an unshield operation. *) +let bound_data_of_public_key_hash cctxt dst = + let open Lwt_result_syntax in + let open Tezos_micheline in + let open Protocol.Michelson_v1_primitives in + let pkh_bytes = + Data_encoding.Binary.to_bytes_exn Signature.Public_key_hash.encoding dst + in + let micheline_bytes = Micheline.(Bytes (0, pkh_bytes) |> strip_locations) in + let micheline_pkh_type = + Micheline.(Prim (0, T_key_hash, [], []) |> strip_locations) + in + let* bound_data, _ = + Plugin.RPC.Scripts.pack_data + cctxt + (cctxt#chain, cctxt#block) + ~gas:None + ~data:micheline_bytes + ~ty:micheline_pkh_type + in + return (Bytes.to_string bound_data) + +let do_unshield cctxt contract src_name stez dst = + let open Lwt_result_syntax in + let* anti_replay = anti_replay cctxt contract in + let* src, _, backdst = Wallet.new_address cctxt src_name None in + let* contract_state = Context.Client_state.sync_and_scan cctxt contract in + let* bound_data = bound_data_of_public_key_hash cctxt dst in + Lwt.return + @@ Context.unshield ~src ~bound_data ~backdst stez contract_state anti_replay + +let do_shield cctxt ?message contract utez dst = + let open Lwt_result_syntax in + let* anti_replay = anti_replay cctxt contract in + let* contract_state = Context.Client_state.sync_and_scan cctxt contract in + let dst = viewing_key_of_string dst in + Context.shield cctxt ~dst ?message utez contract_state anti_replay + +let do_sapling_transfer cctxt ?message contract src_name amount dst = + let open Lwt_result_syntax in + let* anti_replay = anti_replay cctxt contract in + let* src, _, backdst = Wallet.new_address cctxt src_name None in + let* contract_state = Context.Client_state.sync_and_scan cctxt contract in + let dst = viewing_key_of_string dst in + Context.transfer + cctxt + ~src + ~dst + ~backdst + ?message + amount + contract_state + anti_replay + +let message_arg = + let open Lwt_result_syntax in + let open Tezos_clic in + arg + ~long:"message" + ~placeholder:"" + ~doc:"Message for Sapling transaction" + (parameter (fun _ x -> return @@ Bytes.of_string x)) + +let memo_size_arg = + let open Lwt_result_syntax in + let open Tezos_clic in + arg + ~long:"memo-size" + ~placeholder:"memo-size" + ~doc:"Expected length for message of Sapling transaction" + (parameter (fun _ s -> + match + let i = int_of_string s in + assert (i >= 0 && i <= 65535) ; + i + with + | i -> return i + | exception _ -> + failwith "invalid memo-size (must be between 0 and 65535)")) + +let shield_cmd = + let open Lwt_result_syntax in + let open Client_proto_args in + let open Client_proto_context_commands in + let open Client_proto_contracts in + Tezos_clic.command + ~group + ~desc:"Shield tokens from an implicit account to a Sapling address." + (Tezos_clic.args9 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + message_arg) + (Tezos_clic.prefixes ["sapling"; "shield"] + @@ tez_param + ~name:"qty" + ~desc:"Amount taken from transparent wallet of source." + @@ Tezos_clic.prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"src-tz" + ~desc:"Transparent source account." + @@ Tezos_clic.prefix "to" + @@ Tezos_clic.string ~name:"dst-sap" ~desc:"Sapling address of destination." + @@ Tezos_clic.prefix "using" + @@ Originated_contract_alias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ Tezos_clic.stop) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + fee_parameter, + message ) + amount + source + sapling_dst + contract_dst + cctxt -> + let* src_pk, src_sk = keys_of_implicit_account cctxt source in + let open Context in + let*! () = + cctxt#warning + "Shielding %a from %a to %s@ entails a loss of privacy@." + Tez.pp + amount + Signature.Public_key_hash.pp + source + sapling_dst + in + let* sapling_input = + do_shield cctxt ?message contract_dst amount sapling_dst + in + let arg = sapling_transaction_as_arg sapling_input in + let*! errors = + Client_proto_context.transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~fee_parameter + ~amount + ~src_pk + ~src_sk + ~destination:(Originated contract_dst) + ~source + ~arg + ?confirmations:cctxt#confirmations + ?fee + ~dry_run + ~verbose_signing + ?gas_limit + ?storage_limit + ?counter + () + in + let*! (_ : _ option) = + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit) + +let unshield_cmd = + let open Lwt_result_syntax in + let open Client_proto_args in + let open Client_proto_context_commands in + let open Client_proto_contracts in + Tezos_clic.command + ~group + ~desc:"Unshield tokens from a Sapling address to an implicit account." + (Tezos_clic.args8 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args) + (Tezos_clic.prefixes ["sapling"; "unshield"] + @@ tez_param + ~name:"qty" + ~desc:"Amount taken from shielded wallet of source." + @@ Tezos_clic.prefix "from" + @@ Sapling_key.alias_param + ~name:"src-sap" + ~desc:"Sapling account of source." + @@ Tezos_clic.prefix "to" + @@ Client_keys.Public_key_hash.source_param + ~name:"dst-tz" + ~desc:"Transparent destination account." + @@ Tezos_clic.prefix "using" + @@ Originated_contract_alias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ Tezos_clic.stop) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + fee_parameter ) + amount + (name, _sapling_uri) + source + contract_dst + cctxt -> + let open Context in + let stez = Shielded_tez.of_tez amount in + let*! () = + cctxt#warning + "Unshielding %a from %s to %a@ entails a loss of privacy@." + Shielded_tez.pp + stez + name + Signature.Public_key_hash.pp + source + in + let* src_pk, src_sk = keys_of_implicit_account cctxt source in + let* sapling_input = do_unshield cctxt contract_dst name stez source in + let arg = sapling_transaction_as_arg sapling_input in + let*! errors = + Client_proto_context.transfer + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ~fee_parameter + ~amount:Tez.zero + ~src_sk + ~src_pk + ~destination:(Originated contract_dst) + ~source + ~arg + ?confirmations:cctxt#confirmations + ?fee + ~dry_run + ~verbose_signing + ?gas_limit + ?storage_limit + ?counter + () + in + let*! (_ : _ option) = + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit) + +(* Default name for Sapling transaction file *) +let sapling_transaction_file = "sapling_transaction" + +let file_arg default_filename = + let open Lwt_result_syntax in + let open Tezos_clic in + arg + ~long:"file" + ~placeholder:default_filename + ~doc:"file name" + (parameter (fun _ x -> return x)) + +(** Shielded transaction are first forged and printed in a file. + Then they are submitted with the next command. **) +let forge_shielded_cmd = + let open Lwt_result_syntax in + let open Client_proto_args in + let open Client_proto_context_commands in + let open Client_proto_contracts in + Tezos_clic.command + ~group + ~desc:"Forge a sapling transaction and save it to a file." + (Tezos_clic.args11 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + message_arg + (file_arg sapling_transaction_file) + json_switch) + (Tezos_clic.prefixes ["sapling"; "forge"; "transaction"] + @@ tez_param + ~name:"qty" + ~desc:"Amount taken from shielded wallet of source." + @@ Tezos_clic.prefix "from" + @@ Sapling_key.alias_param + ~name:"src-sap" + ~desc:"Sapling account of source." + @@ Tezos_clic.prefix "to" + @@ Tezos_clic.string ~name:"dst-sap" ~desc:"Sapling address of destination." + @@ Tezos_clic.prefix "using" + @@ Originated_contract_alias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ Tezos_clic.stop) + (fun ( _fee, + _dry_run, + _verbose_signing, + _gas_limit, + _storage_limit, + _counter, + _no_print_source, + _fee_parameter, + message, + file, + use_json_format ) + amount + (name, _sapling_uri) + destination + contract_dst + cctxt -> + let open Context in + let stez = Shielded_tez.of_tez amount in + let* transaction = + do_sapling_transfer cctxt ?message contract_dst name stez destination + in + let file = Option.value ~default:sapling_transaction_file file in + let*! () = cctxt#message "Writing transaction to %s@." file in + (if use_json_format then + save_json_to_file + (Data_encoding.Json.construct UTXO.transaction_encoding transaction) + file + else + let bytes = + Hex.of_bytes + (Data_encoding.Binary.to_bytes_exn + UTXO.transaction_encoding + transaction) + in + let file = open_out_bin file in + Printf.fprintf file "0x%s" (Hex.show bytes) ; + close_out file) ; + return_unit) + +let submit_shielded_cmd = + let open Lwt_result_syntax in + let open Client_proto_context_commands in + let open Client_proto_args in + let open Client_proto_contracts in + Tezos_clic.command + ~group + ~desc:"Submit a forged sapling transaction." + (Tezos_clic.args9 + fee_arg + dry_run_switch + verbose_signing_switch + gas_limit_arg + storage_limit_arg + counter_arg + no_print_source_flag + fee_parameter_args + json_switch) + (Tezos_clic.prefixes ["sapling"; "submit"] + (* TODO: Add a dedicated abstracted Tezos_clic element to parse filenames, + potentially using Sys.file_exists *) + @@ Tezos_clic.string + ~name:"file" + ~desc:"Filename of the forged transaction." + @@ Tezos_clic.prefix "from" + @@ Client_keys.Public_key_hash.source_param + ~name:"alias-tz" + ~desc:"Transparent account paying the fees." + @@ Tezos_clic.prefix "using" + @@ Originated_contract_alias.destination_param + ~name:"sapling contract" + ~desc:"Smart contract to submit this transaction to." + @@ Tezos_clic.stop) + (fun ( fee, + dry_run, + verbose_signing, + gas_limit, + storage_limit, + counter, + no_print_source, + fee_parameter, + use_json_format ) + filename + source + destination + (cctxt : Protocol_client_context.full) -> + let*! () = + cctxt#message + "Reading forge transaction from file %s -- sending it to %a@." + filename + Protocol.Contract_hash.pp + destination + in + let open Context in + let* transaction = + if use_json_format then + let* json = Lwt_utils_unix.Json.read_file filename in + return @@ Data_encoding.Json.destruct UTXO.transaction_encoding json + else + let*! hex = Lwt_utils_unix.read_file filename in + let hex = + (* remove 0x *) + String.sub hex 2 (String.length hex - 2) + in + return + @@ Data_encoding.Binary.of_bytes_exn + UTXO.transaction_encoding + Hex.(to_bytes_exn (`Hex hex)) + in + let contract_input = sapling_transaction_as_arg transaction in + let chain = cctxt#chain and block = cctxt#block in + let* src_pk, src_sk = keys_of_implicit_account cctxt source in + let*! errors = + Client_proto_context.transfer + cctxt + ~chain + ~block + ~fee_parameter + ~amount:Tez.zero + ~src_pk + ~src_sk + ~destination:(Originated destination) + ~source + ~arg:contract_input + ?confirmations:cctxt#confirmations + ?fee + ~dry_run + ~verbose_signing + ?gas_limit + ?storage_limit + ?counter + () + in + let*! (_ : _ option) = + report_michelson_errors + ~no_print_source + ~msg:"transfer simulation failed" + cctxt + errors + in + return_unit) + +let for_contract_arg = + Client_proto_contracts.Originated_contract_alias.destination_arg + ~name:"for-contract" + ~doc:"name of the contract to associate new key with" + () + +let unencrypted_switch () = + Tezos_clic.switch + ~long:"unencrypted" + ~doc:"Do not encrypt the key on-disk (for testing and debugging)." + () + +let generate_key_cmd = + let open Lwt_result_syntax in + Tezos_clic.command + ~group + ~desc:"Generate a new sapling key." + (Tezos_clic.args2 (Sapling_key.force_switch ()) (unencrypted_switch ())) + (Tezos_clic.prefixes ["sapling"; "gen"; "key"] + @@ Sapling_key.fresh_alias_param @@ Tezos_clic.stop) + (fun (force, unencrypted) name (cctxt : Protocol_client_context.full) -> + let* name = Sapling_key.of_fresh cctxt force name in + let mnemonic = Mnemonic.new_random in + let*! () = + cctxt#message + "It is important to save this mnemonic in a secure place:@\n\ + @\n\ + %a@\n\ + @\n\ + The mnemonic can be used to recover your spending key.@." + Mnemonic.words_pp + (Bip39.to_words mnemonic) + in + let* _vk = Wallet.register cctxt ~force ~unencrypted mnemonic name in + return_unit) + +let use_key_for_contract_cmd = + let open Lwt_result_syntax in + Tezos_clic.command + ~group + ~desc:"Use a sapling key for a contract." + (Tezos_clic.args1 memo_size_arg) + (Tezos_clic.prefixes ["sapling"; "use"; "key"] + @@ Sapling_key.alias_param + ~name:"sapling-key" + ~desc:"Sapling key to use for the contract." + @@ Tezos_clic.prefixes ["for"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"Contract the key will be used on." + @@ Tezos_clic.stop) + (fun default_memo_size + (name, _sapling_uri) + contract + (cctxt : Protocol_client_context.full) -> + let* vk = Wallet.find_vk cctxt name in + Context.Client_state.register + cctxt + ~default_memo_size + ~force:false + contract + vk) + +let import_key_cmd = + let open Lwt_result_syntax in + Tezos_clic.command + ~group + ~desc:"Restore a sapling key from mnemonic." + (Tezos_clic.args3 + (Sapling_key.force_switch ()) + (unencrypted_switch ()) + (Tezos_clic.arg + ~long:"mnemonic" + ~placeholder:"mnemonic" + ~doc:"Mnemonic as an option, only used for testing and debugging." + Client_proto_args.string_parameter)) + (Tezos_clic.prefixes ["sapling"; "import"; "key"] + @@ Sapling_key.fresh_alias_param @@ Tezos_clic.stop) + (fun (force, unencrypted, mnemonic_opt) + fresh_name + (cctxt : Protocol_client_context.full) -> + let* words = + match mnemonic_opt with + | None -> + let rec loop_words (acc : string list) i = + if i > 23 then return (List.rev acc) + else + let* word_raw = cctxt#prompt_password "Enter word %d: " i in + let word = Bytes.to_string word_raw in + match Bip39.index_of_word word with + | None -> loop_words acc i + | Some _ -> loop_words (word :: acc) (succ i) + in + loop_words [] 0 + | Some mnemonic -> return (String.split_on_char ' ' mnemonic) + in + match Bip39.of_words words with + | None -> failwith "Not a valid mnemonic" + | Some mnemonic -> + let* name = Sapling_key.of_fresh cctxt force fresh_name in + let* _ = Wallet.register cctxt ~force ~unencrypted mnemonic name in + return_unit) + +let commands () = + let open Lwt_result_syntax in + let child_index_param = + Tezos_clic.param + ~name:"child-index" + ~desc:"Index of the child to derive." + Client_proto_args.int_parameter + in + let index_arg = + Tezos_clic.arg + ~doc:"index of the address to generate" + ~long:"address-index" + ~placeholder:"idx" + Client_proto_args.int_parameter + in + [ + generate_key_cmd; + use_key_for_contract_cmd; + import_key_cmd; + Tezos_clic.command + ~group + ~desc:"Derive a key from an existing one using zip32." + (Tezos_clic.args4 + (Sapling_key.force_switch ()) + for_contract_arg + (unencrypted_switch ()) + memo_size_arg) + (Tezos_clic.prefixes ["sapling"; "derive"; "key"] + @@ Sapling_key.fresh_alias_param @@ Tezos_clic.prefix "from" + @@ Sapling_key.alias_param + @@ Tezos_clic.prefixes ["at"; "index"] + @@ child_index_param @@ Tezos_clic.stop) + (fun (force, contract_opt, unencrypted, default_memo_size) + fresh_name + (existing_name, _existing_uri) + child_index + (cctxt : Protocol_client_context.full) -> + let* new_name = Sapling_key.of_fresh cctxt force fresh_name in + let* path, vk = + Wallet.derive + cctxt + ~force + ~unencrypted + existing_name + new_name + child_index + in + let*! () = + cctxt#message + "Derived new key %s from %s with path %s@." + new_name + existing_name + path + in + (* TODO must pass contract address for now *) + let contract = WithExceptions.Option.get ~loc:__LOC__ contract_opt in + Context.Client_state.register + cctxt + ~default_memo_size + ~force + contract + vk); + Tezos_clic.command + ~group + ~desc:"Generate an address for a key referenced by alias." + (Tezos_clic.args1 index_arg) + (Tezos_clic.prefixes ["sapling"; "gen"; "address"] + @@ Sapling_key.alias_param @@ Tezos_clic.stop) + (fun index_opt (name, _sapling_uri) (cctxt : Protocol_client_context.full) -> + let* _, corrected_index, address = + Wallet.new_address cctxt name index_opt + in + let address_b58 = + Tezos_crypto.Base58.simple_encode + Viewing_key.address_b58check_encoding + address + in + let*! () = + cctxt#message + "Generated address:@.%s@.at index %Ld" + address_b58 + (Viewing_key.index_to_int64 corrected_index) + in + return_unit); + Tezos_clic.command + ~group + ~desc:"Save a sapling viewing key in a JSON file." + Tezos_clic.no_options + (Tezos_clic.prefixes ["sapling"; "export"; "key"] + @@ Sapling_key.alias_param @@ Tezos_clic.prefix "in" + @@ Tezos_clic.param + ~name:"file" + ~desc:"Filename." + Client_proto_args.string_parameter + @@ Tezos_clic.stop) + (fun () (name, _sapling_uri) file (cctxt : Protocol_client_context.full) -> + let* vk_json = Wallet.export_vk cctxt name in + return (save_json_to_file vk_json file)); + Tezos_clic.command + ~group + ~desc:"Get balance associated with given sapling key and contract" + (Tezos_clic.args1 + (Tezos_clic.switch + ~doc:"Print the collection of non-spent inputs." + ~short:'v' + ~long:"verbose" + ())) + (Tezos_clic.prefixes ["sapling"; "get"; "balance"; "for"] + @@ Sapling_key.alias_param + ~name:"sapling-key" + ~desc:"Sapling key we get balance for." + @@ Tezos_clic.prefixes ["in"; "contract"] + @@ Client_proto_contracts.Originated_contract_alias.destination_param + ~name:"contract" + ~desc:"Contract we get balance from." + @@ Tezos_clic.stop) + (fun verbose + (name, _sapling_uri) + contract + (cctxt : Protocol_client_context.full) -> + let*! vk_opt = Wallet.find_vk cctxt name in + match vk_opt with + | Error _ -> cctxt#error "Account %s not found" name + | Ok vk -> ( + let* contract_state = + Context.Client_state.sync_and_scan cctxt contract + in + Context.Contract_state.find_account vk contract_state |> function + | None -> cctxt#error "Account %s not found" name + | Some account -> + let*! () = + if verbose then + cctxt#answer + "@[Received Sapling transactions for %s@,@[%a@]@]" + name + Context.Account.pp_unspent + account + else Lwt.return_unit + in + let*! () = + cctxt#answer + "Total Sapling funds %a%s" + Context.Shielded_tez.pp + (Context.Account.balance account) + Operation_result.tez_sym + in + return_unit)); + Tezos_clic.command + ~group + ~desc:"List sapling keys." + Tezos_clic.no_options + (Tezos_clic.fixed ["sapling"; "list"; "keys"]) + (fun () (cctxt : Protocol_client_context.full) -> + let* l = Sapling_key.load cctxt in + let*! () = + List.iter_s + (fun (s, _) -> cctxt#message "%s" s) + (List.sort (fun (s1, _) (s2, _) -> String.compare s1 s2) l) + in + return_unit); + shield_cmd; + unshield_cmd; + forge_shielded_cmd; + submit_shielded_cmd; + ] diff --git a/src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.mli b/src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.mli new file mode 100644 index 000000000000..ad7275224007 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/client_sapling_commands.mli @@ -0,0 +1,8 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2019-2020 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +val commands : unit -> Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_client_sapling/context.ml b/src/proto_020_PsParisC/lib_client_sapling/context.ml new file mode 100644 index 000000000000..86bfca88e8e5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/context.ml @@ -0,0 +1,538 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_sapling.Core.Client + +let _ = Random.self_init () + +module Tez = Protocol.Alpha_context.Tez + +module Shielded_tez : sig + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val of_mutez : int64 -> t option + + val to_mutez : t -> int64 + + val of_tez : Tez.t -> t + + val ( +? ) : t -> t -> t tzresult + + val ( -? ) : t -> t -> t tzresult +end = struct + include Tez + + let ( +? ) a b = a +? b |> Environment.wrap_tzresult + + let ( -? ) a b = a -? b |> Environment.wrap_tzresult + + let of_tez t = + let i = Tez.to_mutez t in + assert (UTXO.valid_amount i) ; + WithExceptions.Option.get ~loc:__LOC__ @@ of_mutez i +end + +let sapling_transaction_as_arg t = + let pp_michelson ppf t = + let open Tezos_micheline in + let list_of_transactions_expr = + let transaction_expr = + Micheline.Bytes + (0, Data_encoding.Binary.to_bytes_exn UTXO.transaction_encoding t) + in + Micheline.strip_locations @@ Micheline.Seq (0, [transaction_expr]) + in + Michelson_v1_printer.print_expr ppf list_of_transactions_expr + in + Format.asprintf "%a" pp_michelson t + +(** The inputs and outputs are shuffled to prevent meta-data analysis. **) +module Shuffle = struct + let list l = + let a = Array.of_list l in + let len = Array.length a in + for i = len downto 2 do + let idx = Random.int i in + let swp_idx = i - 1 in + let tmp = a.(swp_idx) in + a.(swp_idx) <- a.(idx) ; + a.(idx) <- tmp + done ; + Array.to_list a + + let pair x y = if Random.bool () then [y; x] else [x; y] +end + +type error += Balance_too_low of Shielded_tez.t * Shielded_tez.t + +let register_error_kind category ~id ~title ~description ?pp encoding from_error + to_error = + let id = "client_sapling." ^ Protocol.name ^ "." ^ id in + register_error_kind + category + ~id + ~title + ~description + ?pp + encoding + from_error + to_error + +let () = + register_error_kind + `Temporary + ~id:"balance_too_low" + ~title:"Balance too low" + ~description:"The sender contract does not have enough tokens." + ~pp:(fun ppf (balance, amount) -> + Format.fprintf + ppf + "@[Balance too low (%a) to spend %a@]" + Shielded_tez.pp + balance + Shielded_tez.pp + amount) + Data_encoding.( + obj2 + (req "actual_balance" Shielded_tez.encoding) + (req "amount" Shielded_tez.encoding)) + (function + | Balance_too_low (balance, amount) -> Some (balance, amount) | _ -> None) + (fun (balance, amount) -> Balance_too_low (balance, amount)) + +module Storage = Tezos_sapling.Storage +module F = Tezos_sapling.Forge + +module Input_set = struct + include Set.Make (F.Input) + + let to_list = elements + + let pp_f pp i = + Format.fprintf + pp + "@[%s %Ld@]" + (Tezos_crypto.Base58.simple_encode + Viewing_key.address_b58check_encoding + (F.Input.address i)) + (F.Input.amount i) +end + +module Account = struct + type t = { + vk : Viewing_key.t; + unspents : Input_set.t; + balance : Shielded_tez.t; + } + + let encoding = + let open Data_encoding in + conv + (fun cs -> (cs.vk, Input_set.to_list cs.unspents, cs.balance)) + (fun (vk, unspents, balance) -> + {vk; unspents = Input_set.of_list unspents; balance}) + (obj3 + (req "vk" Viewing_key.encoding) + (req "unspents" (list F.Input.encoding)) + (req "balance" Shielded_tez.encoding)) + + let create vk = {vk; unspents = Input_set.empty; balance = Shielded_tez.zero} + + let balance c = c.balance + + let add_unspent c input = + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Shielded_tez.of_mutez (F.Input.amount input) + in + match Shielded_tez.(c.balance +? amount) with + | Error _ -> assert false (* overflow *) + | Ok balance -> + let unspents = Input_set.add input c.unspents in + {c with balance; unspents} + + let remove_unspent c input = + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Shielded_tez.of_mutez (F.Input.amount input) + in + match Shielded_tez.(c.balance -? amount) with + | Error _ -> assert false (* negative balance *) + | Ok balance -> + let unspents = Input_set.remove input c.unspents in + {c with balance; unspents} + + let filter_spent account storage = + Input_set.fold + (fun input acc -> + if F.Input.is_spent input storage account.vk then + remove_unspent acc input + else acc) + account.unspents + account + + let pick_input c = + let ( >?| ) x f = Option.map f x in + Input_set.choose c.unspents >?| fun unspent -> + let c = remove_unspent c unspent in + (unspent, c) + + let pp_unspent : Format.formatter -> t -> unit = + fun ppf a -> + (Format.pp_print_list ~pp_sep:Format.pp_print_cut Input_set.pp_f ppf) + (Input_set.elements a.unspents) +end + +module Contract_state = struct + module Accounts = struct + include Set.Make (struct + type t = Account.t + + let compare a b = + let open Account in + Bytes.compare (Viewing_key.to_bytes a.vk) (Viewing_key.to_bytes b.vk) + end) + + let replace a set = add a (remove a set) + + let find vk accounts = find (Account.create vk) accounts + end + + let accounts_encoding = + let open Data_encoding in + conv + Accounts.elements + (List.fold_left (fun m e -> Accounts.add e m) Accounts.empty) + (list Account.encoding) + + type t = {accounts : Accounts.t; storage : Storage.state} + + let encoding = + let open Data_encoding in + conv + (fun t -> (t.accounts, t.storage)) + (fun (accounts, storage) -> {accounts; storage}) + (obj2 + (req "accounts" accounts_encoding) + (req "storage" Storage.state_encoding)) + + let empty ~memo_size = + {accounts = Accounts.empty; storage = Storage.empty ~memo_size} + + let find_account vk contract_state = Accounts.find vk contract_state.accounts + + let init ~force vk state = + let open Lwt_result_syntax in + Accounts.find vk state.accounts |> function + | None -> + let accounts = Accounts.add (Account.create vk) state.accounts in + return {state with accounts} + | Some _ -> + if force then + let accounts = Accounts.add (Account.create vk) state.accounts in + return {state with accounts} + else failwith "vk already present" + + let add_unspent vk input accounts = + let account = + Accounts.find vk accounts |> WithExceptions.Option.get ~loc:__LOC__ + in + let account = Account.add_unspent account input in + Accounts.replace account accounts + + (** Scan the Sapling storage of a smart contract and update the accounts of + all known viewing keys for that contract *) + let scan state storage = + (* remove newly spent inputs *) + let accounts = + Accounts.map + (fun account -> Account.filter_spent account storage) + state.accounts + in + (* get all the vks that need to be scanned for *) + let vks = + Accounts.fold (fun account acc -> Account.(account.vk) :: acc) accounts [] + in + let size, _ = Storage.size storage in + let rec aux pos accounts = + if pos < size then + (* try to decrypt each inputs with all vks *) + List.fold_left + (fun acc vk -> + match F.Input.get storage pos vk with + | None -> acc + | Some input -> (vk, input) :: acc) + [] + vks + |> function + | [] -> aux (Int64.succ pos) accounts + | [(vk, (_message, forge_input))] -> + let is_spent = F.Input.is_spent forge_input storage vk in + if is_spent then aux (Int64.succ pos) accounts + else aux (Int64.succ pos) (add_unspent vk forge_input accounts) + | _ -> assert false (* got more than one decrypting key *) + else accounts + in + let current_size, _ = Storage.size state.storage in + let accounts = aux current_size accounts in + {accounts; storage} + + (** Update the Sapling storage of a smart contract using a diff, checking that + the resulting Merkle tree has a root equal to the one in the diff. *) + let update_storage contract_state (root, diff) = + let open Protocol.Alpha_context.Sapling in + let storage = + Tezos_sapling.Storage.add + contract_state.storage + diff.commitments_and_ciphertexts + in + let computed_root = Storage.get_root storage in + if computed_root <> root then + Stdlib.failwith "Commitment tree inconsistent wrt to node." + else + let storage = + List.fold_left + (fun s nf -> Storage.add_nullifier s nf) + storage + diff.nullifiers + in + scan contract_state storage +end + +module Client_state = struct + module Map = Map.Make (Protocol.Contract_hash) + + type t = Contract_state.t Map.t + + let encoding = + let open Data_encoding in + conv + Map.bindings + (List.fold_left (fun m (k, v) -> Map.add k v m) Map.empty) + (list + (obj2 + (req "contract" Protocol.Alpha_context.Contract.originated_encoding) + (req "state" Contract_state.encoding))) + + let filename = "sapling_state" + + let load (cctxt : #Client_context.wallet) = + cctxt#load filename ~default:Map.empty encoding + + let write (cctxt : #Client_context.wallet) t = cctxt#write filename t encoding + + let get_or_init ~default_memo_size contract client_state = + let open Lwt_result_syntax in + Map.find contract client_state |> function + | None -> ( + match default_memo_size with + | None -> + failwith + "Unknown memo size for contract %s and none was provided in \ + options" + @@ Protocol.Contract_hash.to_b58check contract + | Some memo_size -> + let contract_state = Contract_state.empty ~memo_size in + let client_state = Map.add contract contract_state client_state in + return (contract_state, client_state)) + | Some contract_state -> return (contract_state, client_state) + + let register cctxt ~force ~default_memo_size contract vk = + let open Lwt_result_syntax in + let* client_state = load cctxt in + let* contract_state, client_state = + get_or_init ~default_memo_size contract client_state + in + let* contract_state = Contract_state.init ~force vk contract_state in + let client_state = Map.add contract contract_state client_state in + write cctxt client_state + + let find (cctxt : #Client_context.full) contract state = + let open Lwt_result_syntax in + Map.find contract state |> function + | None -> + cctxt#error + "Contract %s not found" + (Protocol.Contract_hash.to_b58check contract) + | Some v -> return v + + (** Call the node RPC to obtain the storage diff of a contract *) + let get_diff cctxt contract offset_commitment offset_nullifier = + Protocol.Alpha_services.Contract.single_sapling_get_diff + cctxt + (cctxt#chain, cctxt#block) + contract + ~offset_commitment + ~offset_nullifier + () + + let sync_and_scan cctxt contract = + let open Lwt_result_syntax in + let* state = load cctxt in + let* contract_state = find cctxt contract state in + let cm_pos, nf_pos = Storage.size contract_state.storage in + let* diff = get_diff cctxt contract cm_pos nf_pos in + let contract_state = Contract_state.update_storage contract_state diff in + let state = Map.add contract contract_state state in + let* () = write cctxt state in + return contract_state +end + +(** Truncate or pad the message to fit the memo_size *) +let adjust_message_length (cctxt : #Client_context.full) ?message memo_size = + let open Lwt_syntax in + match message with + | None -> + let+ () = + cctxt#warning + "no message provided, adding a zeroes filled message of the required \ + length: %d " + memo_size + in + Bytes.make memo_size '\000' + | Some message -> + let message_length = Bytes.length message in + if message_length = memo_size then return message + else if message_length > memo_size then + let+ () = + cctxt#warning + "Your message is too long (%d bytes) and will therefore be \ + truncated to %d bytes" + message_length + memo_size + in + Bytes.sub message 0 memo_size + else + let+ () = + cctxt#warning + "Your message is too short (%d bytes) and will therefore be \ + right-padded with zero bytes to reach a %d-byte length" + message_length + memo_size + in + Bytes.cat message (Bytes.make (memo_size - message_length) '\000') + +let create_payment ~message dst amount = + let amount = Shielded_tez.to_mutez amount in + F.make_output dst amount message + +(** Return a list of inputs belonging to an account sufficient to cover an + amount, together with the change remaining. *) +let get_shielded_amount amount account = + let open Result_syntax in + let balance = Account.balance account in + let+ () = + error_unless (balance >= amount) (Balance_too_low (balance, amount)) + in + let to_pay = Shielded_tez.to_mutez amount in + let inputs_to_spend = [] in + let rec loop to_pay chosen_inputs account = + if Int64.(compare to_pay zero) > 0 then + Account.pick_input account |> function + | None -> + Stdlib.failwith "Not enough inputs" (* TODO raise a proper error *) + | Some (next_in, account) -> + let next_val = F.Input.amount next_in in + let rest_to_pay = Int64.sub to_pay next_val in + loop rest_to_pay (next_in :: chosen_inputs) account + else + let change = + WithExceptions.Option.get ~loc:__LOC__ + @@ Shielded_tez.of_mutez @@ Int64.abs to_pay + in + (chosen_inputs, change) + in + loop to_pay inputs_to_spend account + +let create_payback ~memo_size address amount = + let plaintext_message = Bytes.make memo_size '\000' in + let amount = Shielded_tez.to_mutez amount in + F.make_output address amount plaintext_message + +(* The caller should check that the account exists already *) +let unshield ~src ~bound_data ~backdst amount (state : Contract_state.t) + anti_replay = + let open Result_syntax in + let vk = Viewing_key.of_sk src in + let account = + Contract_state.find_account vk state + |> WithExceptions.Option.get ~loc:__LOC__ + in + let+ inputs, change = get_shielded_amount amount account in + let memo_size = Storage.get_memo_size state.storage in + let payback = create_payback ~memo_size backdst change in + F.forge_transaction + (Shuffle.list inputs) + [payback] + src + anti_replay + ~bound_data + state.storage + +let shield cctxt ~dst ?message amount (state : Contract_state.t) anti_replay = + let open Lwt_result_syntax in + let shielded_amount = Shielded_tez.of_tez amount in + let memo_size = Storage.get_memo_size Contract_state.(state.storage) in + let*! message = adjust_message_length cctxt ?message memo_size in + let payment = create_payment ~message dst shielded_amount in + let negative_amount = Int64.neg (Tez.to_mutez amount) in + return + @@ F.forge_shield_transaction + [payment] + negative_amount + anti_replay + ~bound_data:"" + Contract_state.(state.storage) + +(* The caller should check that the account exists already *) +let transfer cctxt ~src ~dst ~backdst ?message amount (state : Contract_state.t) + anti_replay = + let open Lwt_result_syntax in + let vk = Viewing_key.of_sk src in + let account = + Contract_state.find_account vk state + |> WithExceptions.Option.get ~loc:__LOC__ + in + let memo_size = Storage.get_memo_size state.storage in + let*! message = adjust_message_length cctxt ?message memo_size in + let*? inputs, change = get_shielded_amount amount account in + let payment = create_payment ~message dst amount in + let payback = create_payback ~memo_size backdst change in + let sapling_transaction = + F.forge_transaction + (Shuffle.list inputs) + (Shuffle.pair payback payment) + src + anti_replay + ~bound_data:"" + state.storage + in + return sapling_transaction diff --git a/src/proto_020_PsParisC/lib_client_sapling/context.mli b/src/proto_020_PsParisC/lib_client_sapling/context.mli new file mode 100644 index 000000000000..fdec0b0f8150 --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/context.mli @@ -0,0 +1,132 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2019-2020 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** + This module allows the creation of Sapling transactions: shield, unshield and + transfer. + Because Sapling uses an UTXO model, it is necessary for the client to + maintain locally the set of unspent outputs for each viewing key, for each + smart contract. This operation is called scanning. + This local cache is updated downloading from the node only the difference + from the last scanned state. +*) + +open Tezos_sapling.Core.Client + +module Tez : module type of Protocol.Alpha_context.Tez + +(** This module is used to represent any shielded token to avoid confusing it + with Tez. *) +module Shielded_tez : sig + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val of_mutez : int64 -> t option + + val to_mutez : t -> int64 + + val of_tez : Tez.t -> t + + val ( +? ) : t -> t -> t tzresult +end + +(** Convert a Sapling transaction to a suitable argument for the Smart Contract. *) +val sapling_transaction_as_arg : UTXO.transaction -> string + +(** Account corresponding to a contract and a viewing key *) +module Account : sig + type t + + val balance : t -> Shielded_tez.t + + val pp_unspent : Format.formatter -> t -> unit +end + +(** State of a contract, potentially involving several viewing keys *) +module Contract_state : sig + type t + + val find_account : Viewing_key.t -> t -> Account.t option +end + +module Client_state : sig + type t + + val find : + Protocol_client_context.full -> + Protocol.Contract_hash.t -> + t -> + Contract_state.t tzresult Lwt.t + + val register : + Protocol_client_context.full -> + force:bool -> + default_memo_size:int option -> + Protocol.Contract_hash.t -> + Viewing_key.t -> + unit tzresult Lwt.t + + (** Synchronise our local state with the blockchain's. + The state must be recent enough to craft correct transactions. + The limit enforced by the protocol if 120 blocks. + Also scans, ie. checks for incoming payments and add + them to our balance. + **) + val sync_and_scan : + Protocol_client_context.full -> + Protocol.Contract_hash.t -> + Contract_state.t tzresult Lwt.t +end + +(** [shield ~message ~dst tez cstate anti-replay] returns a transaction + shielding [tez] tez to a sapling address [dst] using a sapling + storage [cstate] and the anti-replay string. *) +val shield : + #Client_context.full -> + dst:Viewing_key.address -> + ?message:bytes -> + Tez.t -> + Contract_state.t -> + string -> + UTXO.transaction tzresult Lwt.t + +(** [unshield ~src_name ~src ~dst ~backdst stez cstate storage] returns + a transaction unshielding [stez] shielded tokens from a sapling wallet + [src] to a transparent tezos address [dst], sending the change back to + [backdst] and using a Sapling storage [cstate] and a anti-replay string. + The transaction is refused if there is an insufficient amount of shielded + tez in the wallet [src], the error is raised with [src_name]. + *) +val unshield : + src:Spending_key.t -> + bound_data:string -> + backdst:Viewing_key.address -> + Shielded_tez.t -> + Contract_state.t -> + string -> + UTXO.transaction tzresult + +(** [transfer ~message ~src ~dst ~backdst amount cstate anti-replay] creates a + Sapling transaction of [amount] shielded tez from Sapling wallet [src] to + Sapling address [dst], sending the change to [backdst], using a Sapling + storage [cstate] and a anti-replay string. + [~message] is a message that will be uploaded encrypted on chain. *) +val transfer : + #Client_context.full -> + src:Spending_key.t -> + dst:Viewing_key.address -> + backdst:Viewing_key.address -> + ?message:bytes -> + Shielded_tez.t -> + Contract_state.t -> + string -> + UTXO.transaction tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_client_sapling/dune b/src/proto_020_PsParisC/lib_client_sapling/dune new file mode 100644 index 000000000000..0de513f3320b --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/dune @@ -0,0 +1,28 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_client_sapling_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.client.sapling) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + octez-libs.crypto + octez-libs.stdlib-unix + octez-shell-libs.client-base + octez-shell-libs.signer-backends + octez-protocol-019-PtParisB-libs.client + octez-protocol-019-PtParisB-libs.client.commands + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.plugin) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_stdlib_unix + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_client_019_PtParisB_commands + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_client_sapling/wallet.ml b/src/proto_020_PsParisC/lib_client_sapling/wallet.ml new file mode 100644 index 000000000000..2a27915d4c2d --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/wallet.ml @@ -0,0 +1,112 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Client_keys +open Tezos_sapling.Core.Client + +(* Transform a spending key to an uri, encrypted or not. *) +let to_uri unencrypted cctxt sapling_key = + let open Lwt_result_syntax in + if unencrypted then + let*? sapling_uri = + Tezos_signer_backends.Unencrypted.make_sapling_key sapling_key + in + return sapling_uri + else Tezos_signer_backends.Encrypted.encrypt_sapling_key cctxt sapling_key + +(** Transform an uri into a spending key, asking for a password if the uri was + encrypted. *) +let from_uri (cctxt : #Client_context.full) uri = + Tezos_signer_backends.Encrypted.decrypt_sapling_key cctxt uri + +let register (cctxt : #Client_context.full) ?(force = false) + ?(unencrypted = false) mnemonic name = + let open Lwt_result_syntax in + let sk = Spending_key.of_seed @@ Mnemonic.to_32_bytes mnemonic in + let* sk_uri = to_uri unencrypted cctxt sk in + let key = + { + sk = sk_uri; + path = [Spending_key.child_index sk]; + address_index = Viewing_key.default_index; + } + in + let* () = Sapling_key.add ~force cctxt name key in + return @@ Viewing_key.of_sk sk + +let derive (cctxt : #Client_context.full) ?(force = false) + ?(unencrypted = false) src_name dst_name child_index = + let open Lwt_result_syntax in + let* k = Sapling_key.find cctxt src_name in + let* src_sk = from_uri cctxt k.sk in + let child_index = Int32.of_int child_index in + let dst_sk = Spending_key.derive_key src_sk child_index in + let* dst_sk_uri = to_uri unencrypted cctxt dst_sk in + let dst_key = + { + sk = dst_sk_uri; + path = child_index :: k.path; + address_index = Viewing_key.default_index; + } + in + (* TODO check this force *) + let _ = force in + let* () = Sapling_key.add ~force:true cctxt dst_name dst_key in + let path = + String.concat "/" (List.map Int32.to_string (List.rev dst_key.path)) + in + return (path, Viewing_key.of_sk dst_sk) + +let find_vk cctxt name = + let open Lwt_result_syntax in + let* k = Sapling_key.find cctxt name in + let* sk = from_uri cctxt k.sk in + return (Viewing_key.of_sk sk) + +let new_address (cctxt : #Client_context.full) name index_opt = + let open Lwt_result_syntax in + let* k = Sapling_key.find cctxt name in + let index = + match index_opt with + | None -> k.address_index + | Some i -> Viewing_key.index_of_int64 (Int64.of_int i) + in + let* sk = from_uri cctxt k.sk in + let* vk = return (Viewing_key.of_sk sk) in + (* Viewing_key.new_address finds the smallest index greater or equal to + [index] that generates a correct address. *) + let corrected_index, address = Viewing_key.new_address vk index in + let* () = + Sapling_key.update + cctxt + name + {k with address_index = Viewing_key.index_succ corrected_index} + in + return (sk, corrected_index, address) + +let export_vk cctxt name = + let open Lwt_result_syntax in + let* vk = find_vk cctxt name in + return (Data_encoding.Json.construct Viewing_key.encoding vk) diff --git a/src/proto_020_PsParisC/lib_client_sapling/wallet.mli b/src/proto_020_PsParisC/lib_client_sapling/wallet.mli new file mode 100644 index 000000000000..4fab3b06469b --- /dev/null +++ b/src/proto_020_PsParisC/lib_client_sapling/wallet.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2019-2020 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Tezos_sapling.Core.Client + +(** Add to the wallet a new spending key derived from a mnemonic and identified + by an alias. The wallet is updated and the corresponding viewing key is + returned. + If [force] it will overwrite an existing alias. *) +val register : + #Client_context.full -> + ?force:bool -> + ?unencrypted:bool -> + Bip39.t -> + string -> + Viewing_key.t tzresult Lwt.t + +(** [derive parent child index] derives a key with alias [child] from an + existing key with alias [parent] at [index] using ZIP32. + If a new index is required the state of the wallet is updated. + The path and viewing key corresponding to the generated key are returned. *) +val derive : + #Client_context.full -> + ?force:bool -> + ?unencrypted:bool -> + string -> + string -> + int -> + (string * Viewing_key.t) tzresult Lwt.t + +val find_vk : #Client_context.full -> string -> Viewing_key.t tzresult Lwt.t + +(** Generate a new address. + If an optional index is provided, try to derive the address at this index, + otherwise use the first viable one. + Not all indexes correspond to a valid address so successive ones are tried. + Once a valid index is found it is recorded in the wallet. + Return also the corresponding sk and vk to avoid asking the user multiple + times for the description password. *) +val new_address : + #Client_context.full -> + string -> + int option -> + (Spending_key.t * Viewing_key.index * Viewing_key.address) tzresult Lwt.t + +val export_vk : + #Client_context.full -> string -> Data_encoding.Json.json tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_dac_plugin/dac_plugin_registration.ml b/src/proto_020_PsParisC/lib_dac_plugin/dac_plugin_registration.ml new file mode 100644 index 000000000000..735e96fc78c1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dac_plugin/dac_plugin_registration.ml @@ -0,0 +1,106 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech, *) +(* Copyright (c) 2023 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Make (Mapper : sig + val of_bytes : bytes -> Dac_plugin.hash +end) : Dac_plugin.T = struct + let to_bytes = Dac_plugin.hash_to_bytes + + let to_reveal_hash dac_hash = + dac_hash |> to_bytes + |> Data_encoding.Binary.of_bytes_exn Protocol.Sc_rollup_reveal_hash.encoding + + let of_reveal_hash reveal_hash = + reveal_hash + |> Data_encoding.Binary.to_bytes_exn Protocol.Sc_rollup_reveal_hash.encoding + |> Mapper.of_bytes + + let of_hex hex = + Protocol.Sc_rollup_reveal_hash.of_hex hex |> Option.map of_reveal_hash + + let to_hex hash = to_reveal_hash hash |> Protocol.Sc_rollup_reveal_hash.to_hex + + let encoding = + let binary = + Data_encoding.conv + to_reveal_hash + of_reveal_hash + Protocol.Sc_rollup_reveal_hash.encoding + in + Data_encoding.( + (* Hexifies the hash when encoding in json. *) + splitted + ~binary + ~json: + (conv_with_guard + to_hex + (fun str -> + Result.of_option ~error:"Not a valid hash" (of_hex str)) + (string' Plain))) + + let equal h1 h2 = + Protocol.Sc_rollup_reveal_hash.equal (to_reveal_hash h1) (to_reveal_hash h2) + + let dac_hash_to_proto_supported_hashes = function + | Dac_plugin.Blake2B -> Protocol.Sc_rollup_reveal_hash.Blake2B + + let proto_to_dac_hash_supported_hashes = function + | Protocol.Sc_rollup_reveal_hash.Blake2B -> Dac_plugin.Blake2B + + let hash_string ~(scheme : Dac_plugin.supported_hashes) ?key strings = + Protocol.Sc_rollup_reveal_hash.hash_string + ~scheme:(dac_hash_to_proto_supported_hashes scheme) + ?key + strings + |> of_reveal_hash + + let hash_bytes ~(scheme : Dac_plugin.supported_hashes) ?key bytes = + Protocol.Sc_rollup_reveal_hash.hash_bytes + ~scheme:(dac_hash_to_proto_supported_hashes scheme) + ?key + bytes + |> of_reveal_hash + + let scheme_of_hash hash = + to_reveal_hash hash |> Protocol.Sc_rollup_reveal_hash.scheme_of_hash + |> proto_to_dac_hash_supported_hashes + + let size ~scheme = + Protocol.Sc_rollup_reveal_hash.size + ~scheme:(dac_hash_to_proto_supported_hashes scheme) + + module Proto = Registerer.Registered +end + +let make_plugin : (bytes -> Dac_plugin.hash) -> (module Dac_plugin.T) = + fun of_bytes -> + let module Plugin = Make (struct + let of_bytes = of_bytes + end) in + (module Plugin) + +let () = Dac_plugin.register make_plugin diff --git a/src/proto_020_PsParisC/lib_dac_plugin/dune b/src/proto_020_PsParisC/lib_dac_plugin/dune new file mode 100644 index 000000000000..b468f4bb4f1d --- /dev/null +++ b/src/proto_020_PsParisC/lib_dac_plugin/dune @@ -0,0 +1,29 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_dac_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.dac) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-protocol-compiler.registerer + octez-libs.stdlib-unix + tezos-dac-lib + tezos-dac-client-lib + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.embedded-protocol + tezos-protocol-019-PtParisB.protocol) + (inline_tests (flags -verbose) (modes native)) + (preprocess (pps ppx_expect)) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_registerer + -open Tezos_stdlib_unix + -open Tezos_dac_lib + -open Tezos_dac_client_lib + -open Tezos_client_019_PtParisB + -open Tezos_embedded_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_dac_plugin/test/dune b/src/proto_020_PsParisC/lib_dac_plugin/test/dune new file mode 100644 index 000000000000..59768ef3b524 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dac_plugin/test/dune @@ -0,0 +1,51 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_dac_plugin_test_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-protocol-019-PtParisB-libs.dac + tezos-protocol-019-PtParisB.protocol + octez-libs.base-test-helpers + octez-protocol-019-PtParisB-libs.test-helpers + tezos-dac-lib + tezos_dac_node_lib + octez-alcotezt) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_dac_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_base_test_helpers + -open Tezos_019_PtParisB_test_helpers + -open Tezos_dac_lib + -open Tezos_dac_node_lib + -open Octez_alcotezt) + (modules test_dac_pages_encoding test_dac_plugin_registration test_helpers)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_dac_plugin_test_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package octez-protocol-019-PtParisB-libs) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_pages_encoding.ml b/src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_pages_encoding.ml new file mode 100644 index 000000000000..5260c7cef14c --- /dev/null +++ b/src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_pages_encoding.ml @@ -0,0 +1,648 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022-2023 Trili Tech *) +(* Copyright (c) 2023 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Dal_node Slot_frame_encoding + Invocation: dune exec src/proto_020_PsParisC/lib_dac_plugin/test/main.exe \ + -- --file test_dac_pages_encoding.ml + Subject: Tests for the SCORU storage module +*) + +(** DAC/FIXME: https://gitlab.com/tezos/tezos/-/issues/4021 + Add tests to check actual (sequences of) bytes in serialized pages. *) + +(* Tests are run against a mock storage backend where a Hash-indexed/Bytes-valued Map + is used to simulate adding and retrieving files to a directory. +*) + +(** TODO: https://gitlab.com/tezos/tezos/-/issues/4855 + Move tests to libdac_node/test +*) +let dac_plugin = Stdlib.Option.get (Dac_plugin.get Protocol.hash) + +module Hashes_map = Map.Make (struct + type t = Dac_plugin.hash + + let compare h1 h2 = Dac_plugin.raw_compare h1 h2 +end) + +type hashes_map = bytes Hashes_map.t + +let long_payload = + (* Inferno, Canto I (Dante Alighieri). Size in bytes: 5226. *) + {|Nel mezzo del cammin di nostra vita +mi ritrovai per una selva oscura +ché la diritta via era smarrita. +Ahi quanto a dir qual era è cosa dura +esta selva selvaggia e aspra e forte +che nel pensier rinova la paura! +Tant’è amara che poco è più morte; +ma per trattar del ben ch’i’ vi trovai, +dirò de l’altre cose ch’i’ v’ho scorte. +Io non so ben ridir com’i’ v’intrai, +tant’era pien di sonno a quel punto +che la verace via abbandonai. +Ma poi ch’i’ fui al piè d’un colle giunto, +là dove terminava quella valle +che m’avea di paura il cor compunto, +guardai in alto, e vidi le sue spalle +vestite già de’ raggi del pianeta +che mena dritto altrui per ogne calle. +Allor fu la paura un poco queta +che nel lago del cor m’era durata +la notte ch’i’ passai con tanta pieta. +E come quei che con lena affannata +uscito fuor del pelago a la riva +si volge a l’acqua perigliosa e guata, +così l’animo mio, ch’ancor fuggiva, +si volse a retro a rimirar lo passo +che non lasciò già mai persona viva. +Poi ch’èi posato un poco il corpo lasso, +ripresi via per la piaggia diserta, +sì che ’l piè fermo sempre era ’l più basso. +Ed ecco, quasi al cominciar de l’erta, +una lonza leggera e presta molto, +che di pel macolato era coverta; +e non mi si partia dinanzi al volto, +anzi ’mpediva tanto il mio cammino, +ch’i’ fui per ritornar più volte vòlto. +Temp’era dal principio del mattino, +e ’l sol montava ’n sù con quelle stelle +ch’eran con lui quando l’amor divino +mosse di prima quelle cose belle; +sì ch’a bene sperar m’era cagione +di quella fiera a la gaetta pelle +l’ora del tempo e la dolce stagione; +ma non sì che paura non mi desse +la vista che m’apparve d’un leone. +Questi parea che contra me venisse +con la test’alta e con rabbiosa fame, +sì che parea che l’aere ne tremesse. +Ed una lupa, che di tutte brame +sembiava carca ne la sua magrezza, +e molte genti fé già viver grame, +questa mi porse tanto di gravezza +con la paura ch’uscia di sua vista, +ch’io perdei la speranza de l’altezza. +E qual è quei che volontieri acquista, +e giugne ’l tempo che perder lo face, +che ’n tutt’i suoi pensier piange e s’attrista; +tal mi fece la bestia sanza pace, +che, venendomi ’ncontro, a poco a poco +mi ripigneva là dove ’l sol tace. +Mentre ch’i’ rovinava in basso loco, +dinanzi a li occhi mi si fu offerto +chi per lungo silenzio parea fioco. +Quando vidi costui nel gran diserto, +«Miserere di me», gridai a lui, +«qual che tu sii, od ombra od omo certo!». +Rispuosemi: «Non omo, omo già fui, +e li parenti miei furon lombardi, +mantoani per patria ambedui. +Nacqui sub Iulio, ancor che fosse tardi, +e vissi a Roma sotto ’l buono Augusto +nel tempo de li dèi falsi e bugiardi. +Poeta fui, e cantai di quel giusto +figliuol d’Anchise che venne di Troia, +poi che ’l superbo Ilión fu combusto. +Ma tu perché ritorni a tanta noia? +perché non sali il dilettoso monte +ch’è principio e cagion di tutta gioia?». +«Or se’ tu quel Virgilio e quella fonte +che spandi di parlar sì largo fiume?», +rispuos’io lui con vergognosa fronte. +«O de li altri poeti onore e lume +vagliami ’l lungo studio e ’l grande amore +che m’ha fatto cercar lo tuo volume. +Tu se’ lo mio maestro e ’l mio autore; +tu se’ solo colui da cu’ io tolsi +lo bello stilo che m’ha fatto onore. +Vedi la bestia per cu’ io mi volsi: +aiutami da lei, famoso saggio, +ch’ella mi fa tremar le vene e i polsi». +«A te convien tenere altro viaggio», +rispuose poi che lagrimar mi vide, +«se vuo’ campar d’esto loco selvaggio: +ché questa bestia, per la qual tu gride, +non lascia altrui passar per la sua via, +ma tanto lo ’mpedisce che l’uccide; +e ha natura sì malvagia e ria, +che mai non empie la bramosa voglia, +e dopo ’l pasto ha più fame che pria. +Molti son li animali a cui s’ammoglia, +e più saranno ancora, infin che ’l veltro +verrà, che la farà morir con doglia. +Questi non ciberà terra né peltro, +ma sapienza, amore e virtute, +e sua nazion sarà tra feltro e feltro. +Di quella umile Italia fia salute +per cui morì la vergine Cammilla, +Eurialo e Turno e Niso di ferute. +Questi la caccerà per ogne villa, +fin che l’avrà rimessa ne lo ’nferno, +là onde ’nvidia prima dipartilla. +Ond’io per lo tuo me’ penso e discerno +che tu mi segui, e io sarò tua guida, +e trarrotti di qui per loco etterno, +ove udirai le disperate strida, +vedrai li antichi spiriti dolenti, +ch’a la seconda morte ciascun grida; +e vederai color che son contenti +nel foco, perché speran di venire +quando che sia a le beate genti. +A le quai poi se tu vorrai salire, +anima fia a ciò più di me degna: +con lei ti lascerò nel mio partire; +ché quello imperador che là sù regna, +perch’i’ fu’ ribellante a la sua legge, +non vuol che ’n sua città per me si vegna. +In tutte parti impera e quivi regge; +quivi è la sua città e l’alto seggio: +oh felice colui cu’ ivi elegge!». +E io a lui: «Poeta, io ti richeggio +per quello Dio che tu non conoscesti, +acciò ch’io fugga questo male e peggio, +che tu mi meni là dov’or dicesti, +sì ch’io veggia la porta di san Pietro +e color cui tu fai cotanto mesti». +Allor si mosse, e io li tenni dietro.|} + +module Hashes_map_backend = struct + type t = bytes Hashes_map.t ref + + type configuration = unit + + type hash = Dac_plugin.hash + + let init () = ref Hashes_map.empty + + type error += Page_is_missing of Dac_plugin.raw_hash + + let save (_plugin : Dac_plugin.t) t ~(hash : Dac_plugin.hash) ~content = + let open Lwt_result_syntax in + let () = t := Hashes_map.add hash content !t in + return () + + let mem (_plugin : Dac_plugin.t) t (hash : Dac_plugin.hash) = + Lwt_result_syntax.return @@ Hashes_map.mem hash !t + + let load (_plugin : Dac_plugin.t) t hash = + let open Lwt_result_syntax in + let bytes = Hashes_map.find hash !t in + match bytes with + | None -> tzfail @@ Page_is_missing (Dac_plugin.hash_to_raw hash) + | Some bytes -> return bytes + + let number_of_pages t = List.length @@ Hashes_map.bindings !t +end + +(* Page store implementation that uses two in-memory stores (p1, p2). + Data is loaded from (p2) if present in such a store, otherwise it + is fetched from (p1) and, if the contents of the page are valid + with respect to the hash provided, then it is saved to p2. + Otherwise, an error is returned. +*) + +module With_hash_check : + Page_store.S with type configuration = unit and type t = Hashes_map_backend.t = + Page_store.Internal_for_tests.With_data_integrity_check (Hashes_map_backend) + +module Double_hash_map_backend : + Page_store.S + with type configuration = Hashes_map_backend.t * Hashes_map_backend.t = + Page_store.Internal_for_tests.With_remote_fetch + (struct + type remote_context = Hashes_map_backend.t + + let fetch = Hashes_map_backend.load + end) + (With_hash_check) + +let assert_equal_bytes ~loc msg a b = + Assert.equal ~loc Bytes.equal msg String.pp_bytes_hex a b + +let assert_fails_with ~loc k expected_err = + let open Lwt_result_syntax in + let*! res = k in + Assert.error ~loc res (( = ) expected_err) + +module Merkle_tree = struct + open Pages_encoding.Merkle_tree + + module Make_V0_for_test (C : Pages_encoding.CONFIG) (S : Page_store.S) = + struct + module Buffered = + Internal_for_tests.Make_buffered + (S) + (struct + let content_version = 0 + + let hashes_version = 0 + end) + (C) + + include Internal_for_tests.Make (Buffered) + end + + module V0 = struct + let test_serialization_fails_with ~loc ~max_page_size ~payload ~error = + let open + Make_V0_for_test + (struct + let max_page_size = max_page_size + end) + (Hashes_map_backend) in + let page_store = Hashes_map_backend.init () in + let serialize_payload = + serialize_payload dac_plugin ~page_store payload + in + assert_fails_with ~loc serialize_payload error + + let test_serialization_roundtrip ?expect_num_of_pages ~loc ~max_page_size + payload = + let open + Make_V0_for_test + (struct + let max_page_size = max_page_size + end) + (Hashes_map_backend) in + let page_store = Hashes_map_backend.init () in + let open Lwt_result_syntax in + let* hash = serialize_payload dac_plugin ~page_store payload in + let* retrieved_payload = + deserialize_payload dac_plugin ~page_store hash + in + let* () = + match expect_num_of_pages with + | Some expected -> + let actual = Hashes_map_backend.number_of_pages page_store in + Assert.equal_int ~loc actual expected + | None -> return_unit + in + assert_equal_bytes + ~loc + "Deserialized payload do not match with original" + payload + retrieved_payload + + (* We use 50 bytes as the size of a page. Of these, 5 bytes are used for + the preamble, which leaves 45 bytes of space for storing hashes in a + page. The overall size of a hash is 33 bytes (32 bytes for the inner hash + plus 1 byte for the tag identifying the hashing scheme of the hash), + therefore only floor(45/33) = 1 hashes can be stored for each page. + Because the serialization process requires a page size that can contain + at least two hashes, the serialization of any content will fail in this case. + *) + let serialize_one_hash_per_page_fails () = + let payload = + List.repeat 195 (Bytes.of_string "a") |> Bytes.concat Bytes.empty + in + test_serialization_fails_with + ~loc:__LOC__ + ~max_page_size:50 + ~payload + ~error:(Pages_encoding.Merkle_tree_branching_factor_not_high_enough 1) + + let serialize_empty_payload_fails () = + (* Limit the number of hashes stored per page to 2. Because hashes + have a fixed size of 33 bytes (32 bytes for inner hash and 1 byte for + hashing sheme tag of the hash), and 5 bytes are used for the preamble, + we need 33 * 2 + 5 = 71 bytes to store two hashes in a page. We round + this value to 80. *) + test_serialization_fails_with + ~loc:__LOC__ + ~max_page_size:80 + ~payload:Bytes.empty + ~error:Pages_encoding.Payload_cannot_be_empty + + let one_page_roundtrip () = + (* Limit the number of hashes stored per page to 2. Because hashes + have a fixed size of 33 bytes (32 bytes for inner hash and 1 byte for + hashing sheme tag of the hash), and 5 bytes are used for the preamble, + we need 33 * 2 + 5 = 71 bytes to store two hashes in a page. We round + this value to 80. *) + let max_page_size = 80 in + let payload = Bytes.of_string "Hello payload" in + test_serialization_roundtrip + ~expect_num_of_pages:1 + ~loc:__LOC__ + ~max_page_size + payload + + let multiple_pages_roundtrip_heterogeneous_payload () = + (* Each page in tests contains at most 80 bytes, of which 5 are reserved + for the page prefix. This leaves 75 bytes to store the payload to be + serialized in a page. It also means that a `Hashes` page can contain + at most 2 hashes of size 33 bytes each (32 bytes for inner hash and 1 + byte for hashing sheme tag of the hash). If we try to serialize a + payload between 151 and 225 bytes (included), then the serialized + payload should be spread among a total of 6 pages. Of these, + 225/75 = 3 pages are used to store the payload, ceil(3/2) = 2 pages + are used for storing the 3 hashes of the 3 payload pages, and + ceil(2/2) = 1 page is used for storing the 2 hashes of the previous + pages. *) + let max_page_size = 80 in + let payload = + Bytes.of_string + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do \ + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim \ + ad minim veniam, quis nostrud exercitation ullamco" + in + test_serialization_roundtrip + ~expect_num_of_pages:6 + ~loc:__LOC__ + ~max_page_size + payload + + let deserialization_of_corrupt_data_with_hash_integrity_check_fails () = + let open Lwt_result_syntax in + let module Page_size = struct + let max_page_size = 80 + end in + let module Mock_remote_codec = + Make_V0_for_test (Page_size) (Hashes_map_backend) + in + let module Mock_synch_codec = + Make_V0_for_test + (struct + let max_page_size = 80 + end) + (Double_hash_map_backend) + in + let mock_remote_store = Hashes_map_backend.init () in + let mock_local_store = Hashes_map_backend.init () in + let page_store = + Double_hash_map_backend.init (mock_remote_store, mock_local_store) + in + let payload = + Bytes.of_string "This is a payload that will be tampered later on" + in + let corrupt_payload = + Bytes.of_string "This is the payload that has been tampered with" + in + let* root_hash = + Mock_remote_codec.serialize_payload + dac_plugin + ~page_store:mock_remote_store + payload + in + (* We save the corrupt payload in the store and then retrieve it again, + to be sure that the content corresponds to a valid page. Then we + update the content of the original (non corrupt) payload in the store + to the (serialized) corrupt payload. *) + let* root_hash_of_corrupt_payload = + Mock_remote_codec.serialize_payload + dac_plugin + ~page_store:mock_remote_store + corrupt_payload + in + let* serialised_corrupt_payload = + Hashes_map_backend.load + dac_plugin + mock_remote_store + root_hash_of_corrupt_payload + in + let* () = + Hashes_map_backend.save + dac_plugin + mock_remote_store + ~hash:root_hash + ~content:serialised_corrupt_payload + in + let* () = + assert_fails_with + ~loc:__LOC__ + (Mock_synch_codec.deserialize_payload + dac_plugin + ~page_store + root_hash) + (Page_store.Incorrect_page_hash + { + expected = Dac_plugin.hash_to_raw root_hash; + actual = Dac_plugin.hash_to_raw root_hash_of_corrupt_payload; + }) + in + (* Check that pages have not been copied from the remote mock store + to the local one. *) + Assert.equal_int + ~loc:__LOC__ + (Hashes_map_backend.number_of_pages mock_local_store) + 0 + + let multiple_pages_roundtrip_homogeneous_payload () = + (* Each page in tests contains at most 80 bytes, of which 5 are reserved + for the page prefix. This leaves 75 bytes to store the content to be + serialized in a page. It also means that a `Hashes` page can contain + at most 2 hashes of size 33 bytes each (32 bytes for inner hash and 1 + byte for hashing sheme tag of the hash). If we try to serialize a + payload of 225 repetitions of the same character, then only one + payload page will be produced. However, the hash of this page will be + repeated three times across two pages represent nodes of the Merkle + tree. Finally, another page will be used for storing the Merkle tree + root page, which contains the two hashes of the Merkle tree nodes + above. In total, the serialization should be spread among 4 pages. *) + let max_page_size = 80 in + let payload = + List.repeat 225 (Bytes.of_string "a") |> Bytes.concat Bytes.empty + in + test_serialization_roundtrip + ~expect_num_of_pages:4 + ~loc:__LOC__ + ~max_page_size + payload + + let multiple_pages_roundtrip_do_not_exceed_page_size () = + (* Check that a bug related to the size of hashes has been fixed. + Before the bug was fixed: the `Sc_rollup.Reveal_hash` module borrowed + the size function from the underlying hash module, meaning that it + would return `31` for the size, rather than the actual hash size + which is `32`. For a page that is exactly `98` bytes long, this would + mean that the serialization algorithm will compute the number of + hashes per page to be `(98-5)/31 = 3`, but the actual hash pages will + have size `32 * 3 + 5 = 101` bytes. This will cause the check on a page + size to fail, when serializing a page. With 98 bytes per page, 93 + bytes will be reserved for the payload in content pages. + Before the patch was applied, trying to + serialize a payload of `93 * 3 = 279` bytes with a page size of + 98 bytes would have caused to try to serialize a page containing + 3 hashes of 32 bytes each, resulting in a page of `101 bytes` and + causing the serialization to fail. + *) + let max_page_size = 98 in + (* 279 bytes of payload *) + let payload = + Bytes.of_string + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do \ + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim \ + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut \ + aliquip ex ea commodo consequat. Duis aute irure dolor in \ + reprehenderit in volup" + in + test_serialization_roundtrip ~loc:__LOC__ ~max_page_size payload + + let long_content_roundtrip () = + (* To ensure that the serialization and deserialization process work as + expected, we test a roundtrip for a reasonably long text. We also + increase the page size to allow for more than two hashes in a page. *) + (* The page size is set to 150. Of these, 5 bytes are used for the page + preamble, and the reset will contain hashes which are 32 bytes long + each. The number of hashes that can fit into a page is + floor((150 - 5)/32) = 4. *) + let max_page_size = 150 in + let payload = Bytes.of_string long_payload in + test_serialization_roundtrip ~loc:__LOC__ ~max_page_size payload + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4608 + Define helper function that calculates expected number of pages given the + payload and use it for PBT expected number of pages given payload *) + module PBT = struct + module Generators = struct + open QCheck2.Gen + + (* Serialization requires [~max_page_size] that guarantees at least two + hashes per page. In orher words, we need at least 71 bytes in total since + 5 bytes is used as a preamble and each hash is 32 bytes long and uses + aditional 1 byte for the tag used to identify the version scheme: + 5 + 2 (32 + 1) = 71 *) + let gen_max_page_size = int_range 71 10_000 + + let gen_non_empty_payload = bytes_size (int_range 1 10_000) + + let gen_non_empty_payloads = + list_size (int_range 1 100) gen_non_empty_payload + + let max_page_size_with_non_empty_payload = + pair gen_max_page_size gen_non_empty_payload + + let max_page_size_with_non_empty_payloads = + pair gen_max_page_size gen_non_empty_payloads + end + + (** [serialization_roundtrip_pbt (max_page_size, payload)] tests + serialization scheme logic of [Pages_encoding.Merkle_tree.V0] + by varying [max_page_size] and [payload] (arbitrary byte + sequence). *) + let serialization_roundtrip_pbt (max_page_size, payload) = + test_serialization_roundtrip ~loc:__LOC__ ~max_page_size payload + + (** [merkle_tree_make_buffered_roundtrip_pbt (max_page_size, messages)] + tests [Pages_encoding.Merkle_tree.Make_buffered] functor. + It takes a pair [max_page_size] and [messages] (a list of non-empty + byte sequances).Buffered payload handler is instantiated with given + [max_page_size] and messages are serialized by adding them one by one + in the order specified by [messages] sequence. Finally, we finalize + serialization, which results in single preimage hash. To test the + correctness we deserialize the original payload via beforementioned + preimage hash. If initial serialization was correct, the obtained + payload is equal to the result of of concatenating messages from + original [messages] sequence. + *) + let merkle_tree_make_buffered_roundtrip_pbt (max_page_size, messages) = + let open Lwt_result_syntax in + let page_store = Hashes_map_backend.init () in + let open + Make_V0_for_test + (struct + let max_page_size = max_page_size + end) + (Hashes_map_backend) in + let payload_handler = Buffered.empty () in + let add_message message = + Buffered.add dac_plugin ~page_store payload_handler message + in + let* () = List.iter_es add_message messages in + let* hash = Buffered.finalize dac_plugin ~page_store payload_handler in + let* retrieved_payload = + deserialize_payload dac_plugin ~page_store hash + in + let expected_retrieved_payload = Bytes.concat Bytes.empty messages in + assert_equal_bytes + ~loc:__LOC__ + "Deserialized payload do not match with original" + expected_retrieved_payload + retrieved_payload + end + end +end + +let tests = + [ + Tztest.tztest + "Storing only one hash per page causes serialization to fail (Merkle \ + tree, v0)" + `Quick + Merkle_tree.V0.serialize_one_hash_per_page_fails; + Tztest.tztest + "Serializing empty payload returns an error (Merkle tree, v0)" + `Quick + Merkle_tree.V0.serialize_empty_payload_fails; + Tztest.tztest + "Contents fitting in one page can be retrieved after being saved (Merkle \ + tree, v0)" + `Quick + Merkle_tree.V0.one_page_roundtrip; + Tztest.tztest + "Contents fitting in more pages can be retrieved after being saved - no \ + repeated pages (Merkle tree, V0)" + `Quick + Merkle_tree.V0.multiple_pages_roundtrip_heterogeneous_payload; + Tztest.tztest + "Contents fitting in more pages can be retrieved after being saved - \ + repeated pages (Merkle tree, V0)" + `Quick + Merkle_tree.V0.multiple_pages_roundtrip_homogeneous_payload; + Tztest.tztest + "Serialization and deserialization of very long content is correct." + `Quick + Merkle_tree.V0.long_content_roundtrip; + Tztest.tztest + "Hashes pages are not larger than expected" + `Quick + Merkle_tree.V0.multiple_pages_roundtrip_do_not_exceed_page_size; + Tztest.tztest + "Deserialization with integrity check fails if page contents are corrupt" + `Quick + Merkle_tree.V0 + .deserialization_of_corrupt_data_with_hash_integrity_check_fails; + Tztest.tztest_qcheck2 + ~name:"PBT for merkle_tree_V0 serialization/deserialization roundtrip" + Merkle_tree.V0.PBT.Generators.max_page_size_with_non_empty_payload + Merkle_tree.V0.PBT.serialization_roundtrip_pbt; + Tztest.tztest_qcheck2 + ~name: + "PBT for [Merkle_tree.Make_buffered] functor via \ + serialization/deserialization roundtrip" + Merkle_tree.V0.PBT.Generators.max_page_size_with_non_empty_payloads + Merkle_tree.V0.PBT.merkle_tree_make_buffered_roundtrip_pbt; + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [Test_helpers.Unit_test.spec "Dac_pages_encoding.ml" tests] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_plugin_registration.ml b/src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_plugin_registration.ml new file mode 100644 index 000000000000..51160799fde0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dac_plugin/test/test_dac_plugin_registration.ml @@ -0,0 +1,159 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Lib_dac_node Dac_hash + Invocation: dune exec src/proto_020_PsParisC/lib_dac_plugin/test/main.exe \ + -- --file test_dac_plugin_registration.ml + Subject: Tests for the interoperability between Dac hash + and given protocol hash +*) + +module Protocol_reveal_hash = Protocol.Sc_rollup_reveal_hash + +let dac_plugin = Stdlib.Option.get (Dac_plugin.get Protocol.hash) + +module P = (val dac_plugin) + +(* Hash copied from + https://gitlab.com/tezos/tezos/-/blob/master/tezt/tests/dac.ml#L331 *) +let reveal_hash = + Stdlib.Option.get + @@ Protocol_reveal_hash.of_hex + "00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6" + +let assert_equal_bytes ~loc msg = + Assert.equal ~loc Bytes.equal msg String.pp_bytes_hex + +let test_dac_hash_bin_encoding_roundtrip_with_reveal_hash () = + let open Lwt_result_syntax in + let to_bytes e a = + Stdlib.Result.get_ok @@ Data_encoding.Binary.to_bytes e a + in + let from_bytes e a = + Stdlib.Result.get_ok @@ Data_encoding.Binary.of_bytes e a + in + let reveal_hash_bytes = to_bytes Protocol_reveal_hash.encoding reveal_hash in + let dac_hash = from_bytes P.encoding reveal_hash_bytes in + let dac_hash_bytes = to_bytes P.encoding dac_hash in + let reveal_hash_decoded = + from_bytes Protocol_reveal_hash.encoding dac_hash_bytes + in + let* () = + assert_equal_bytes + ~loc:__LOC__ + "Encoded bytes are not equal" + reveal_hash_bytes + dac_hash_bytes + in + Assert.equal + ~loc:__LOC__ + Protocol_reveal_hash.equal + "Roundtrip hash is not equal" + Protocol_reveal_hash.pp + reveal_hash + reveal_hash_decoded + +let test_dac_hash_hex_roundtrip_with_reveal_hash () = + let reveal_hash_hex = Protocol_reveal_hash.to_hex reveal_hash in + let dac_hash = Stdlib.Option.get @@ P.of_hex reveal_hash_hex in + let dac_hash_hex = P.to_hex dac_hash in + Assert.equal_string ~loc:__LOC__ reveal_hash_hex dac_hash_hex + +let test_dac_hash_hash_bytes_with_reveal_hash () = + let payload = Bytes.of_string "Hello world" in + let dac_hash = P.hash_bytes ~scheme:Blake2B [payload] in + let dac_hash = + Stdlib.Result.get_ok @@ Data_encoding.Binary.to_bytes P.encoding dac_hash + in + let reveal_hash = Protocol_reveal_hash.hash_bytes ~scheme:Blake2B [payload] in + let reveal_hash = + Stdlib.Result.get_ok + @@ Data_encoding.Binary.to_bytes Protocol_reveal_hash.encoding reveal_hash + in + assert_equal_bytes + ~loc:__LOC__ + "Encoded bytes are not equal" + reveal_hash + dac_hash + +let test_dac_hash_hash_string_with_reveal_hash () = + let payload = "Hello world" in + let dac_hash = P.hash_string ~scheme:Blake2B [payload] in + let dac_hash = + Stdlib.Result.get_ok @@ Data_encoding.Binary.to_bytes P.encoding dac_hash + in + let reveal_hash = + Protocol_reveal_hash.hash_string ~scheme:Blake2B [payload] + in + let reveal_hash = + Stdlib.Result.get_ok + @@ Data_encoding.Binary.to_bytes Protocol_reveal_hash.encoding reveal_hash + in + assert_equal_bytes + ~loc:__LOC__ + "Encoded bytes are not equal" + reveal_hash + dac_hash + +let test_json_encoding_is_hexified () = + let payload = Bytes.of_string "Hello world" in + let dac_hash = P.hash_bytes ~scheme:Blake2B [payload] in + let dac_hash_json = Data_encoding.Json.construct P.encoding dac_hash in + let dac_hash_json_string = Data_encoding.Json.to_string dac_hash_json in + let dac_hash_hex_string = P.to_hex dac_hash in + Assert.equal_string ~loc:__LOC__ dac_hash_hex_string dac_hash_json_string + +let tests = + [ + Tztest.tztest + "Binary encoding roundtrip test between Dac hash and reveal hash" + `Quick + test_dac_hash_bin_encoding_roundtrip_with_reveal_hash; + Tztest.tztest + "Hex encoding roundtrip test between Dac hash and reveal hash" + `Quick + test_dac_hash_hex_roundtrip_with_reveal_hash; + Tztest.tztest + "Hash bytes should be equal between Dac hash and reveal hash" + `Quick + test_dac_hash_hash_bytes_with_reveal_hash; + Tztest.tztest + "Hash string should be equal between Dac hash and reveal hash" + `Quick + test_dac_hash_hash_string_with_reveal_hash; + Tztest.tztest + "Json encoded hash string should be a hex string" + `Quick + test_dac_hash_hash_string_with_reveal_hash; + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [Test_helpers.Unit_test.spec "Dac_plugin_registration.ml" tests] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_dac_plugin/test/test_helpers.ml b/src/proto_020_PsParisC/lib_dac_plugin/test/test_helpers.ml new file mode 100644 index 000000000000..832d0dd725a9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dac_plugin/test/test_helpers.ml @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Unit_test : sig + (** + * Example: [spec "Dac_pages_encoding.ml" Test_dac_pages_encoding.tests] + * Unit tests needs tag in log (like "[UNIT] some test description here...") + * This function handles such meta data *) + val spec : + string -> + unit Alcotest_lwt.test_case list -> + string * unit Alcotest_lwt.test_case list + + (** Tests with description string without [Unit] are skipped *) + val _skip : + string -> + unit Alcotest_lwt.test_case list -> + string * unit Alcotest_lwt.test_case list +end = struct + let spec unit_name test_cases = ("[Unit] " ^ unit_name, test_cases) + + let _skip unit_name test_cases = ("[SKIPPED] " ^ unit_name, test_cases) +end diff --git a/src/proto_020_PsParisC/lib_dal/RPC_directory.ml b/src/proto_020_PsParisC/lib_dal/RPC_directory.ml new file mode 100644 index 000000000000..11f377b4fd68 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/RPC_directory.ml @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2024 Functori, *) +(* SPDX-FileCopyrightText: 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +module Dal_proto_services = Dal_services +open Protocol + +module Skip_list_handlers = struct + let cell (rpc_context, cell_hash) () () = + let open Lwt_result_syntax in + let hash = + Dal_proto_types.Skip_list_hash.of_proto + Alpha_context.Dal.Slots_history.Pointer_hash.encoding + cell_hash + in + let* cell = Skip_list_cells_store.find rpc_context hash in + return + @@ Dal_proto_types.Skip_list_cell.to_proto + Alpha_context.Dal.Slots_history.encoding + cell +end + +let add_service registerer subst service handler directory = + registerer directory (subst service) handler + +let register_commitments_history ctxt directory = + directory + |> add_service + Tezos_rpc.Directory.register + Tezos_rpc.Service.subst1 + Dal_proto_services.Commitments_history.hash_content + Skip_list_handlers.cell + |> Tezos_rpc.Directory.map (fun _prefix -> Lwt.return ctxt) + +let directory (rpc_ctxt : Skip_list_cells_store.t) = + register_commitments_history rpc_ctxt Tezos_rpc.Directory.empty diff --git a/src/proto_020_PsParisC/lib_dal/RPC_directory.mli b/src/proto_020_PsParisC/lib_dal/RPC_directory.mli new file mode 100644 index 000000000000..3e5940728daf --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/RPC_directory.mli @@ -0,0 +1,10 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2024 Functori, *) +(* SPDX-FileCopyrightText: 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** The RPCs directory of the protocol part of DAL nodes. *) +val directory : Skip_list_cells_store.t -> unit Environment.RPC_directory.t diff --git a/src/proto_020_PsParisC/lib_dal/dal_plugin_registration.ml b/src/proto_020_PsParisC/lib_dal/dal_plugin_registration.ml new file mode 100644 index 000000000000..ffb037f36253 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_plugin_registration.ml @@ -0,0 +1,280 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let wrap = Environment.wrap_tzresult + +module Plugin = struct + module Proto = Registerer.Registered + + type block_info = Protocol_client_context.Alpha_block_services.block_info + + let parametric_constants chain block ctxt = + let cpctxt = new Protocol_client_context.wrap_rpc_context ctxt in + Protocol.Constants_services.parametric cpctxt (chain, block) + + let get_constants chain block ctxt = + let open Lwt_result_syntax in + let* parametric = parametric_constants chain block ctxt in + let { + Constants.Parametric.feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + } = + parametric.dal + in + return + { + Dal_plugin.feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + sc_rollup_challenge_window_in_blocks = + parametric.sc_rollup.challenge_window_in_blocks; + commitment_period_in_blocks = + parametric.sc_rollup.commitment_period_in_blocks; + dal_attested_slots_validity_lag = + parametric.sc_rollup.reveal_activation_level + .dal_attested_slots_validity_lag; + } + + let block_info ?chain ?block ~metadata ctxt = + let cpctxt = new Protocol_client_context.wrap_rpc_context ctxt in + Protocol_client_context.Alpha_block_services.info + cpctxt + ?chain + ?block + ~metadata + () + + let block_shell_header (block_info : block_info) = block_info.header.shell + + let get_round fitness = + let open Result_syntax in + let* round = Fitness.round_from_raw fitness |> wrap in + return @@ Round.to_int32 round + + (* Turn the given value of type {!Protocol.Apply_operation_result.operation_result} + into a value of type {!Dal_plugin.operation_application_result}. *) + let status_of_result = function + | Protocol.Apply_operation_result.Applied _ -> Dal_plugin.Succeeded + | _ -> Dal_plugin.Failed + + let get_published_slot_headers (block : block_info) = + let open Lwt_result_syntax in + let open Protocol.Alpha_context in + let apply_internal acc ~source:_ _op _res = acc in + let apply (type kind) acc ~source:_ (op : kind manager_operation) + (result : (kind, _, _) Protocol.Apply_operation_result.operation_result) + = + match op with + | Dal_publish_commitment operation -> + (operation.slot_index, operation.commitment, status_of_result result) + :: acc + | _ -> acc + in + Layer1_services.( + process_manager_operations [] block.operations {apply; apply_internal}) + |> List.map_es (fun (slot_index, commitment, status) -> + let published_level = block.header.shell.level in + let slot_index = Dal.Slot_index.to_int slot_index in + return Dal_plugin.({published_level; slot_index; commitment}, status)) + + let get_committee ctxt ~level = + let open Lwt_result_syntax in + let cpctxt = new Protocol_client_context.wrap_rpc_context ctxt in + let*? level = Raw_level.of_int32 level |> wrap in + let+ pkh_to_shards = + Plugin.RPC.Dal.dal_shards cpctxt (`Main, `Head 0) ~level () + in + List.fold_left + (fun acc ({delegate; indexes} : Plugin.RPC.Dal.S.shards_assignment) -> + Signature.Public_key_hash.Map.add delegate indexes acc) + Signature.Public_key_hash.Map.empty + pkh_to_shards + + let attested_slot_headers (block : block_info) ~number_of_slots = + let open Result_syntax in + let* metadata = + Option.to_result + block.metadata + ~none: + (TzTrace.make @@ Layer1_services.Cannot_read_block_metadata block.hash) + in + let confirmed_slots = metadata.protocol_data.dal_attestation in + let* all_slots = + Dal.Slot_index.slots_range + ~number_of_slots + ~lower:0 + ~upper:(number_of_slots - 1) + |> wrap + in + List.filter (Dal.Attestation.is_attested confirmed_slots) all_slots + |> Dal.Slot_index.to_int_list |> return + + (* Section of helpers for Skip lists *) + + module Skip_list = struct + type cell = Dal.Slots_history.t + + type hash = Dal.Slots_history.Pointer_hash.t + + let cell_encoding = Dal.Slots_history.encoding + + let hash_encoding = Dal.Slots_history.Pointer_hash.encoding + + let cell_equal = Dal.Slots_history.equal + + let hash_equal = Dal.Slots_history.Pointer_hash.equal + + let cell_hash = Dal.Slots_history.hash + + (* + This function mimics what the protocol does in + {!Dal_slot_storage.finalize_pending_slot_headers}. Given a block_info and + an RPC context, this function computes the cells produced by the DAL skip + list during the level L of block_info using: + + - The information telling which slot headers were waiting for attestation + at level [L - attestation_lag]; + + - The bitset of attested slots at level [L] in the block's metadata. + + The ordering of the elements in the returned list is not relevant. + *) + let cells_of_level (block_info : block_info) ctxt = + let open Lwt_result_syntax in + (* 0. Let's call [level] the block's level. *) + let level = block_info.header.shell.level in + let* dal_constants = get_constants `Main (`Level level) ctxt in + let published_level = + Int32.sub level (Int32.of_int dal_constants.attestation_lag) + in + (* 1. Before it's possible to attest the slots at the first published + levels, the list of cells is empty. *) + if published_level <= 1l then return [] + else + let* publication_level_dal_constants = + (* published_level - 1 is positive. *) + get_constants `Main (`Level (Int32.pred published_level)) ctxt + in + (* Is DAL activated at at published_level - 1 *) + if not publication_level_dal_constants.feature_enable then return [] + else + let cpctxt = new Protocol_client_context.wrap_rpc_context ctxt in + (* 2. We retrieve the slot headers published at level [level - + attestation_lag] from the context. *) + let* published_slot_headers = + Plugin.RPC.Dal.dal_published_slot_headers + cpctxt + (`Main, `Level published_level) + () + in + let*? published_level = + Raw_level.of_int32 published_level |> Environment.wrap_tzresult + in + (* 3. We retrieve the last cell of the DAL skip list from the context, + if any. It's the one stored in the context at [level - 1]. If no cell + is stored yet, we return the genesis cell. *) + let* previous_cell = + let* previous_cell_opt = + (* Should not be negative as attestation_lag > 0. *) + let prev_level = Int32.pred level in + Plugin.RPC.Dal.dal_commitments_history + cpctxt + (`Main, `Level prev_level) + in + return + @@ Option.value previous_cell_opt ~default:Dal.Slots_history.genesis + in + (* 4. We retrieve the bitset of attested slots at level [level]. *) + let* attested_slots = + let*? metadata = + Option.to_result + block_info.metadata + ~none: + (TzTrace.make + @@ Layer1_services.Cannot_read_block_metadata block_info.hash) + in + return metadata.protocol_data.dal_attestation + in + let is_slot_attested slot = + Dal.Attestation.is_attested + attested_slots + slot.Dal.Slot.Header.id.index + in + (* 5. We filter the list of slot headers published at [level - + attestation_lag] and keep only those attested at level [level]. *) + let attested_slot_headers, _attested_slots_bitset = + Dal.Slot.compute_attested_slot_headers + ~is_slot_attested + published_slot_headers + in + (* 6. Starting from the [previous_cell], we insert the successive cells + of level [level] in the skip list thanks to function + {!add_confirmed_slot_headers}. The function is fed with an empty + history cache, so the returned [cache] contains exactly the cells + produced for this [level]. *) + let*? _last_cell, cache = + let capacity = + Int64.of_int + @@ max + publication_level_dal_constants.number_of_slots + dal_constants.number_of_slots + in + Dal.Slots_history.add_confirmed_slot_headers + previous_cell + (Dal.Slots_history.History_cache.empty ~capacity) + published_level + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + + Not resilient to DAL parameters change. *) + ~number_of_slots:dal_constants.number_of_slots + attested_slot_headers + |> Environment.wrap_tzresult + in + (* 7. We finally export and return the cells alongside their hashes as a + list. *) + let last_cells = + let open Dal.Slots_history.History_cache in + view cache |> Map.bindings + in + return last_cells + end + + module RPC = struct + let directory skip_list_cells_store = + RPC_directory.directory skip_list_cells_store + end +end + +let () = Dal_plugin.register (module Plugin) diff --git a/src/proto_020_PsParisC/lib_dal/dal_proto_client.ml b/src/proto_020_PsParisC/lib_dal/dal_proto_client.ml new file mode 100644 index 000000000000..f63d03caaa77 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_proto_client.ml @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2024 Functori, *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type cctxt = Dal_node_client.cctxt + +let get_commitments_history_hash_content (cctxt : cctxt) hash = + cctxt#call_service + (Tezos_rpc.Service.prefix + Tezos_rpc.Path.(root / "plugin") + Dal_services.Commitments_history.hash_content) + ((), hash) + () + () diff --git a/src/proto_020_PsParisC/lib_dal/dal_proto_client.mli b/src/proto_020_PsParisC/lib_dal/dal_proto_client.mli new file mode 100644 index 000000000000..96c2cd4ffe42 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_proto_client.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2024 Functori, *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val get_commitments_history_hash_content : + Dal_node_client.cctxt -> + Dal_plugin_registration.Plugin.Skip_list.hash -> + Dal_plugin_registration.Plugin.Skip_list.cell tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_dal/dal_services.ml b/src/proto_020_PsParisC/lib_dal/dal_services.ml new file mode 100644 index 000000000000..03b5c528e17f --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_services.ml @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2024 Functori, *) +(* SPDX-FileCopyrightText: 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context +open Tezos_rpc + +type 'rpc service = + ('meth, 'prefix, 'params, 'query, 'input, 'output) Service.service + constraint + 'rpc = + < meth : 'meth + ; prefix : 'prefix + ; params : 'params + ; query : 'query + ; input : 'input + ; output : 'output > + +module Commitments_history = struct + let cell_hash_arg : Dal.Slots_history.Pointer_hash.t Arg.t = + Arg.make + ~descr:"The hash of a DAL skip list cell" + ~name:"skip_list_cell_hash" + ~construct:Dal.Slots_history.Pointer_hash.to_b58check + ~destruct:(fun h -> + match Dal.Slots_history.Pointer_hash.of_b58check_opt h with + | Some b -> Ok b + | None -> Error "Cannot parse skip list cell hash") + () + + let hash_content : + < meth : [`GET] + ; input : unit + ; output : Dal.Slots_history.t + ; prefix : unit + ; params : unit * Dal.Slots_history.Pointer_hash.t + ; query : unit > + service = + Service.get_service + ~description:"Returns the DAL skip list cell of the given hash" + ~query:Query.empty + ~output:Dal.Slots_history.encoding + Path.(open_root / "commitments_history" / "hash" /: cell_hash_arg) +end diff --git a/src/proto_020_PsParisC/lib_dal/dal_services.mli b/src/proto_020_PsParisC/lib_dal/dal_services.mli new file mode 100644 index 000000000000..61f8ae00466c --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_services.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2024 Functori, *) +(* SPDX-FileCopyrightText: 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +type 'rpc service = + ('meth, 'prefix, 'params, 'query, 'input, 'output) Tezos_rpc.Service.service + constraint + 'rpc = + < meth : 'meth + ; prefix : 'prefix + ; params : 'params + ; query : 'query + ; input : 'input + ; output : 'output > + +module Commitments_history : sig + (** Service for returning the skip list cell of the given hash. *) + val hash_content : + < meth : [`GET] + ; input : unit + ; output : Dal.Slots_history.t + ; prefix : unit + ; params : unit * Dal.Slots_history.Pointer_hash.t + ; query : unit > + service +end diff --git a/src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.ml b/src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.ml new file mode 100644 index 000000000000..f89360351623 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.ml @@ -0,0 +1,257 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context + +type error += + | Slot_size_is_too_big of {actual_size : int; max_size : int} + | Wrong_slot_frame_version of {expected : int; provided : int} + | Could_not_deserialize_slot + +let () = + register_error_kind + `Permanent + ~id:"slot_size_is_too_big" + ~title:"Slot size is too big" + ~description:"Slot cannot fit in maximum size" + ~pp:(fun ppf (actual_size, max_size) -> + Format.fprintf + ppf + "Actual size: %d, Maximum size: %d" + actual_size + max_size) + Data_encoding.(obj2 (req "actual_size" int31) (req "maximum_size" int31)) + (function + | Slot_size_is_too_big {actual_size; max_size} -> + Some (actual_size, max_size) + | _ -> None) + (fun (actual_size, max_size) -> + Slot_size_is_too_big {actual_size; max_size}) ; + register_error_kind + `Permanent + ~id:"wrong_slot_frame_version" + ~title:"Wrong slot frame version" + ~description:"Wrong slot frame version" + ~pp:(fun ppf (expected, provided) -> + Format.fprintf + ppf + "Version expected: %d, Version provided: %d" + expected + provided) + Data_encoding.( + obj2 (req "version_expected" uint8) (req "version_provided" uint8)) + (function + | Wrong_slot_frame_version {expected; provided} -> + Some (expected, provided) + | _ -> None) + (fun (expected, provided) -> Wrong_slot_frame_version {expected; provided}) ; + register_error_kind + `Permanent + ~id:"could_not_deserialize_slot" + ~title:"Slot could not be deserialized" + ~description:"Error when recovering slot contents from binary" + ~pp:(fun ppf () -> + Format.fprintf ppf "Error when recovering slot contents from binary") + Data_encoding.(unit) + (function Could_not_deserialize_slot -> Some () | _ -> None) + (fun () -> Could_not_deserialize_slot) + +type version = int + +type message = string + +module Rollups_map = Map.Make (Sc_rollup.Address) + +type t = message list Rollups_map.t + +module type Slot_version = sig + val version_prefix : version + + val expected_slot_size : t -> int + + val serialize : max_size:int -> t -> string tzresult Lwt.t + + val deserialize : max_size:int -> string -> t tzresult Lwt.t +end + +let version_encoding = Data_encoding.uint8 + +module V0 = struct + let version_prefix = 0 + + (* Binary representation of string uses 4 bytes as a header, + containing the string length. This conforms to the specification + given for messages. *) + let message_encoding = Data_encoding.string + + (* Binary representation of lists uses 4 bytes as a header, containing + the length of the list in bytes. This conforms to the + specification given for messages frames. *) + let messages_frame_encoding = Data_encoding.(list message_encoding) + + (* Binary representation of lists uses 4 bytes as a header, containing + the size of the encoded list contents in bytes. + `all_messages_frame_encoding` encodes not only the encoded messages + frames, but also the 4 bytes containing the length of all messages + frames that separate the rollups frame from the messages frame. + *) + let all_messages_frames_encoding = + Data_encoding.(list messages_frame_encoding) + + (* Binary representation of a [Sc_rollup.Address.t] uses 20 bytes, + while the encoding of a [int32] uses 4 bytes. These are + concatenated together by `rollup_offset_entry_encoding`. *) + let rollup_offset_entry_encoding = + Data_encoding.(tup2 Sc_rollup.Address.encoding int32) + + (* Binary representation of lists uses 4 bytes as a header, containing + the size of the encoded list contents in bytes. + the size in bytes of the rollups frame. containing + the length of the list in bytes. Thus the rollups_frame_encoding + conforms to the specification given*) + let rollups_frame_encoding = Data_encoding.(list rollup_offset_entry_encoding) + + let slot_encoding ~max_size = + Data_encoding.( + check_size max_size + @@ tup3 + version_encoding + rollups_frame_encoding + all_messages_frames_encoding) + + module Internal = struct + let size_of_opt size = match size with None -> assert false | Some n -> n + + let message_size = Data_encoding.Binary.length message_encoding + + let messages_frame_size = + Data_encoding.Binary.length messages_frame_encoding + + let all_messages_frames_size = + Data_encoding.Binary.length all_messages_frames_encoding + + let frame_prefix_size = + size_of_opt Data_encoding.(Binary.fixed_length int32) + + let frame_version_size = + size_of_opt Data_encoding.(Binary.fixed_length uint8) + + let rollup_entry_size = + size_of_opt + @@ Data_encoding.Binary.fixed_length rollup_offset_entry_encoding + + let rollups_frame_size number_of_rollups = + (rollup_entry_size * number_of_rollups) + frame_prefix_size + end + + let expected_slot_size all_rollups_messages = + let bindings = Rollups_map.bindings all_rollups_messages in + let number_of_rollups = bindings |> List.length in + let messages = List.map snd bindings in + Internal.( + frame_version_size + + rollups_frame_size number_of_rollups + + all_messages_frames_size messages) + + let serialize ~max_size all_rollups_messages = + let open Lwt_result_syntax in + let first_messages_frame_offset = + Internal.( + frame_version_size + + rollups_frame_size + (Rollups_map.bindings all_rollups_messages |> List.length) + + frame_prefix_size) + in + let rev_rollups_frame, rev_messages_frames, expected_slot_size = + Rollups_map.fold + (fun rollup messages (rollups_frame, messages_frames, next_offset) -> + let rollups_frame = + (rollup, Int32.of_int next_offset) :: rollups_frame + in + let messages_frames = messages :: messages_frames in + let next_offset = + next_offset + Internal.messages_frame_size messages + in + (rollups_frame, messages_frames, next_offset)) + all_rollups_messages + ([], [], first_messages_frame_offset) + in + let* () = + fail_unless + (expected_slot_size <= max_size) + (Slot_size_is_too_big {actual_size = expected_slot_size; max_size}) + in + let rollups_frame = List.rev rev_rollups_frame in + let messages_frames = List.rev rev_messages_frames in + let*? result = + Data_encoding.Binary.to_string + (slot_encoding ~max_size) + (version_prefix, rollups_frame, messages_frames) + |> Result.map_error (fun _ -> assert false) + in + return result + + (* Deserialization of slot contents will be done by WASM PVM kernels, as + per #3374. However, we should still provide a function to + deserialize the contents of a slot, as other components other than the + PVM kernel may need to inspect it. *) + let deserialize ~max_size serialized = + let open Lwt_result_syntax in + let actual_size = String.length serialized in + let* () = + fail_unless + (actual_size <= max_size) + (Slot_size_is_too_big {actual_size; max_size}) + in + let version_prefix, rollups_frame, messages_frames = + Data_encoding.Binary.of_string_exn (slot_encoding ~max_size) serialized + in + let* () = + fail_when + (version_prefix <> 0) + (Wrong_slot_frame_version {expected = 0; provided = version_prefix}) + in + let* () = + fail_when + (List.compare_length_with messages_frames @@ List.length rollups_frame + <> 0) + Could_not_deserialize_slot + in + let*? deserialized = + List.map2 + ~when_different_lengths:[] + (fun (rollup, _offset) messages -> (rollup, messages)) + rollups_frame + messages_frames + |> Result.map_error (fun _ -> [Could_not_deserialize_slot]) + |> Result.map (fun rollups_with_messages -> + Rollups_map.add_seq + (List.to_seq rollups_with_messages) + Rollups_map.empty) + in + return deserialized +end diff --git a/src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.mli b/src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.mli new file mode 100644 index 000000000000..2b6134c2b089 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dal_slot_frame_encoding.mli @@ -0,0 +1,182 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Library for encoding messages from distinct rollups into a slot. This + library contains encoding and decoding functions for different versions of + the slot-frame encoding. Currently, only one version, V0, exists. As the + structure of slot-frame progresses, new versions will be added. *) + +open Protocol +open Alpha_context + +type error += + | Slot_size_is_too_big of {actual_size : int; max_size : int} + | Wrong_slot_frame_version of {expected : int; provided : int} + | Could_not_deserialize_slot + +type version = int + +module Rollups_map : Map.S with type key = Sc_rollup.Address.t + +type message = string + +(* The type that will be used to serialize and deserialize a slot into a + slot-frame. It consists of a map from rollup addresses to list of + messages. *) +type t = message list Rollups_map.t + +(* Common interface for all slot versions. *) +module type Slot_version = sig + (* [version_prefix] denotes the version of the slot-frame encoding. + It must be a value between 0 and 255, and two different slot-frame + econdings cannot have the same version prefix. *) + val version_prefix : version + + (* [expected_slot_size rollups_messages] returns the value of the + size (in bytes) of a slot-frame that includes all the messages + in [rollups_messages]. It must satisfy the following property: + `expected_slot_size rollups_messages = + String.length @@ serialize rollups_messages`. + *) + val expected_slot_size : t -> int + + (* [serialize ~max_size rollups_messages] returns the encoding + of [rollups_messages] as a string, provided that the result + does not occupy more then [~max_size] byted. + When it succeeds, it must satisfy the following property: + `deserialize ~max_size @@ serialize ~max_size rollups_messages = + rollups_messages` + + May fail with: + {ul + {li [Slot_size_is_too_big {actual_size; max_size}] if the encoding of the + slot would take [actual_size] bytes, where `actual_size > max_size`} + } + *) + val serialize : max_size:int -> t -> string tzresult Lwt.t + + (* [deserialize ~max_size slot_frame] returns the rollup-address indexed map + of messages whose encoding corresponds to [slot_frame], as long as the + [slot_frame] does not occupy more then [~max_size] bytes, and [slot_frame] + contains the correct version_prefix, i.e. the first byte [slot_frame] + is set to `\000`. When it succeeds, it must satisfy the following property: + `serialize ~max_size @@ deserialize ~max_size slot_frame = + slot_frame` + + May fail with: + {ul + {li [Slot_size_is_too_big {actual_size; max_size}] if + [String.length slot_frame = actual_size], where + `actual_size > max_size`. + } + {li [Wrong_slot_frame_version of {expected; provided = 0}] if the first + byte of [slot_frame] is set to the binary encoding of [expected]. + } + {li [Could_not_deserialize_slot] if [slot_frame] does not correspond to + the serialization of a valid rollup-address indexed map of messages. + } + } + *) + val deserialize : max_size:int -> string -> t tzresult Lwt.t +end + +(*'V0' version of the slot-frame encoding. + Suppose that we want to include messages from rollups `r_1, ..., r_n`. + Specifically, for `i=1, ..., n`, suppose that rollup `r_i` wants to include + an arbitrary number j of messages `[m_{i,1}; ... m_{i, j} ]` into the slot. + The number of messages j to be included in a slot may be different for each + rollup. The encoded slot will consist of a string where: + {ul + {li The first byte contains the slot-frame version, currently set to `0x00`,} + {li The next `n * 24 + 4` bytes contain the `rollups-frame`, which contains + the information about where the messages for the rollups + `r_1, .., r_n` are stored. Specifically, the first 4 bytes denote the + length (in bytes) of the remaining part of the rollups-frame, which is + `n * 24`. This is followed by `n` entries of `24` bytes each. For each + entry, the first `20` bytes contain the encoded address of the rollup + node, while the other `4` contain the offset - from the start of the + slot - to the start of the rollup's messages-frame (described next). + } + {li The `4` bytes following the rollups frame contain the length of the + rest of the encoded slot, } + {li Next, there are n messages-frames, one for each rollup. For + `i = 1, ..., n`, the size of the i-th messages-frame is + `4 * n_i + (\sum_{j=1}^{n_i} |m_{i, j}|) + 4` bytes. The first four + bytes denote the length of the messages-frame. Then we have the + sequence of the encoded messages `m_{i,1}, ..., m_{i, j}`. The encoded + message `m_{i,j}` consists of 4 bytes representing `|m_{i,j}|`, + followed by `m_{i,j}` itself. + } + } + + As an example, suppose that we have two rollups `r1` and `r2`. For + simplicity, let's assume that the binary represenation of `r1` and `r2` are + `ROLLUP_ADDRESS_1XXXX` and `ROLLUP_ADDRESS_2YYYY`. Suppose that we want to + include in the slot messages [["hello"; "world"]] from `r1`, and messages + [["CAFEBABE"; "CAFEDEAD"]] from `r2` (in this order). The overall encoded + frame will be + "\000 + \000\000\000\048 + ROLLUP_ADDRESS_1XXXX\000\000\000\057 + ROLLUP_ADDRESS_2YYYY\000\000\000\079 + \000\000\000\050 + \000\000\000\018\000\000\000\005hello\000\000\000\005world + \000\000\000\024\000\000\000\008CAFEBABE\000\000\000\008CAFEDEAD". +*) +module V0 : sig + include Slot_version + + (* Functions used internally by the V0 version of the slot. These functions + are exposed so that they can be used in tests. This is necessary as we + will have implementations of the deserialization for the slot functions in + different programming languages. Checking the values returned by these + functions in tests will serve as documentation for developers wanting to + implement their own version of the V0 slot-frame deserialization. *) + module Internal : sig + (* [messages_size message] returns the size in bytes that [message] + would take in a slot-frame. *) + val message_size : message -> int + + (* [messages_frame_size messages] returns the size in bytes that the + encoding of messages as a messages frame would take in a slot-frame. *) + val messages_frame_size : message list -> int + + (* [all_messages_frame all_messages] returns the size in bytes + that the encoding of [all_messages] would take in a slot-frame. + This value includes the 4 bytes that separate the rollups-frame + from the rest of the slot frame in the encoding. *) + val all_messages_frames_size : message list list -> int + + (* [rollup_entry_size] returns the size in bytes + that one rollup would take in the rollups-frame. + *) + val rollup_entry_size : int + + (* [rollups_frame_size number_of_rollups] returns the size + in bytes that the rollups-frame would take in a slot-frame, + if the latter contains messages for [number_of_rollups] rollups. *) + val rollups_frame_size : int -> int + end +end diff --git a/src/proto_020_PsParisC/lib_dal/dune b/src/proto_020_PsParisC/lib_dal/dune new file mode 100644 index 000000000000..d981d929769f --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/dune @@ -0,0 +1,31 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_dal_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.dal) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-protocol-compiler.registerer + octez-libs.stdlib-unix + tezos-dal-node-lib + octez-protocol-019-PtParisB-libs.client + octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-019-PtParisB.embedded-protocol + octez-protocol-019-PtParisB-libs.layer2-utils + tezos-protocol-019-PtParisB.protocol) + (inline_tests (flags -verbose) (modes native)) + (preprocess (pps ppx_expect)) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_registerer + -open Tezos_stdlib_unix + -open Tezos_dal_node_lib + -open Tezos_client_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_embedded_protocol_019_PtParisB + -open Tezos_layer2_utils_019_PtParisB + -open Tezos_protocol_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_dal/test/dune b/src/proto_020_PsParisC/lib_dal/test/dune new file mode 100644 index 000000000000..acfc24d2bde2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/test/dune @@ -0,0 +1,47 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_dal_test_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-protocol-019-PtParisB-libs.dal + tezos-protocol-019-PtParisB.protocol + octez-libs.base-test-helpers + octez-protocol-019-PtParisB-libs.test-helpers + octez-alcotezt) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_dal_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_base_test_helpers + -open Tezos_019_PtParisB_test_helpers + -open Octez_alcotezt) + (modules test_dal_slot_frame_encoding test_helpers)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_dal_test_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package octez-protocol-019-PtParisB-libs) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_dal/test/test_dal_slot_frame_encoding.ml b/src/proto_020_PsParisC/lib_dal/test/test_dal_slot_frame_encoding.ml new file mode 100644 index 000000000000..c337cb2a4be0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/test/test_dal_slot_frame_encoding.ml @@ -0,0 +1,420 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Dal_node Slot_frame_encoding + Invocation: dune exec src/proto_020_PsParisC/lib_dal/test/main.exe \ + -- --file test_dal_slot_frame_encoding.ml + Subject: Tests for the SCORU storage module +*) + +(* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3421 + Property based tests to check basic invariants of slot-frame encoding V0. *) + +open Protocol +open Alpha_context +module Rollup_messages_map = Dal_slot_frame_encoding.Rollups_map +module V0 = Dal_slot_frame_encoding.V0 + +(* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3339 + Fetch this value from protocol default constants *) +let max_size = 1_048_576 + +let assert_fails_with ~loc k expected_err = + let open Lwt_result_syntax in + let*! res = k in + Assert.error ~loc res (( = ) expected_err) + +module Compare_list_string = Compare.List (String) +module Compare_list_list_string = Compare.List (Compare_list_string) +module Compare_list_rollup = Compare.List (Sc_rollup.Address) + +let assert_equal_bytes ~loc msg = + Assert.equal ~loc Bytes.equal msg String.pp_bytes_hex + +let assert_equal_list_string ~loc msg = + Assert.equal + ~loc + Compare_list_string.equal + msg + (Format.pp_print_list Format.pp_print_string) + +let assert_equal_list_list_string ~loc msg = + Assert.equal + ~loc + Compare_list_list_string.equal + msg + (Format.pp_print_list (Format.pp_print_list Format.pp_print_string)) + +let assert_equal_list_rollups ~loc msg = + Assert.equal + ~loc + Compare_list_rollup.equal + msg + (Format.pp_print_list Sc_rollup.Address.pp) + +let sc_rollup_1 = + Sc_rollup.Address.of_b58check_exn "sr1BAwv191dVYeZg44ZxVy8dFwfRQKW6bSqc" + +let sc_rollup_2 = + Sc_rollup.Address.of_b58check_exn "sr1Fq8fPi2NjhWUXtcXBggbL6zFjZctGkmso" + +let slot_frame_encoding_size_correct_single_v0 () = + let open Lwt_result_syntax in + let messages_rollup_1 = + ["hello"; "is"; "it"; "me"; "you"; "are"; "looking"; "for"] + in + (* One rollup with offset should take 24 bytes *) + let entry_size = V0.Internal.rollup_entry_size in + let* () = Assert.equal_int ~loc:__LOC__ entry_size 24 in + (* 1 byte for version *) + let expected_version_size = 1 in + (* 20 bytes for one rollup address + 4 bytes of offset + 4 bytes for frame length = 28 bytes *) + let computed_rollups_frame_size = V0.Internal.rollups_frame_size 1 in + let expected_rollups_frame_size = 28 in + let* () = + Assert.equal_int + ~loc:__LOC__ + computed_rollups_frame_size + expected_rollups_frame_size + in + (*27 bytes total messages + + 4 * 8 = 32 bytes message length prefixes + + 4 bytes list length prefix + + 63 bytes for messages frame *) + let computed_messages_frame_size = + V0.Internal.messages_frame_size messages_rollup_1 + in + let expected_messages_frame_size = 63 in + let* () = + Assert.equal_int + ~loc:__LOC__ + computed_messages_frame_size + expected_messages_frame_size + in + (* 4 bytes of list length prefix + + 63 bytes of messages_frame_size = 67 bytes for all messages frames *) + let computed_all_messages_frames_size = + V0.Internal.all_messages_frames_size [messages_rollup_1] + in + let expected_all_messages_frames_size = 4 + expected_messages_frame_size in + let* () = + Assert.equal_int + ~loc:__LOC__ + computed_all_messages_frames_size + expected_all_messages_frames_size + in + let expected_size = + expected_version_size + expected_rollups_frame_size + + expected_all_messages_frames_size + in + let map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + in + let computed_size = V0.expected_slot_size map in + Assert.equal_int ~loc:__LOC__ expected_size computed_size + +let slot_frame_encoding_size_correct_multiple_v0 () = + let open Lwt_result_syntax in + let messages_rollup_1 = ["Summer"; "loving"; "had"; "me"; "a"; "blast"] in + let messages_rollup_2 = ["Summer"; "loving"; "happened"; "so"; "fast"] in + (* 1 byte for version *) + let expected_version_size = 1 in + (* 24 * 2 = 48 bytes for two rollup entries + + 4 bytes for frame length prefix = 52 bytes + *) + let computed_rollups_frame_size = V0.Internal.rollups_frame_size 2 in + let expected_rollups_frame_size = 52 in + let* () = + Assert.equal_int + ~loc:__LOC__ + computed_rollups_frame_size + expected_rollups_frame_size + in + (* Frame 1: + 6 + 6 + 3 + 2 + 1 + 5 = 23 bytes for messages + + 4 * 6 = 24 bytes for message length prefix for 6 messages + + 4 bytes for message frame prefix = + 51 bytes for the messages frame for rollup1. + Frame 2: + 6 + 6 + 8 + 2 + 4 = 26 bytes for messages + + 4 * 5 = 20 bytes for message length prefix for 6 messages + + 4 bytes for message frame prefix = + 50 bytes for the messages frame for rollup2. + Messages frame length: + 51 bytes for rollup1 messages frame + + 50 bytes for rollup2 messages frame + + 4 bytes prefix length for all messages frames = + 105 bytes + *) + let computed_all_messages_frames_size = + V0.Internal.all_messages_frames_size [messages_rollup_1; messages_rollup_2] + in + let expected_all_messages_frames_size = 105 in + let* () = + Assert.equal_int + ~loc:__LOC__ + computed_all_messages_frames_size + expected_all_messages_frames_size + in + let expected_size = + expected_version_size + expected_rollups_frame_size + + expected_all_messages_frames_size + in + let map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + |> Rollup_messages_map.add sc_rollup_2 messages_rollup_2 + in + let computed_size = V0.expected_slot_size map in + Assert.equal_int ~loc:__LOC__ expected_size computed_size + +let slot_frame_encoding_decoding_correct_single_v0 () = + let open Lwt_result_syntax in + let messages_rollup_1 = + ["hello"; "is"; "it"; "me"; "you"; "are"; "looking"; "for"] + in + let messages_map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + in + let* serialized = V0.serialize ~max_size messages_map in + let* () = + Assert.equal_int + ~loc:__LOC__ + (String.length serialized) + (V0.expected_slot_size messages_map) + in + let* deserialized = V0.deserialize ~max_size serialized in + let rollups_with_messages = Rollup_messages_map.bindings deserialized in + let* () = + assert_equal_list_rollups + ~loc:__LOC__ + "Deserialized rollups are different from originals" + [sc_rollup_1] + (List.map fst rollups_with_messages) + in + assert_equal_list_list_string + ~loc:__LOC__ + "Messages frames are different from originals" + [messages_rollup_1] + (List.map snd rollups_with_messages) + +let slot_frame_encoding_decoding_correct_multiple_v0 () = + let open Lwt_result_syntax in + let messages_rollup_1 = ["Summer"; "loving"; "had"; "me"; "a"; "blast"] in + let messages_rollup_2 = ["Summer"; "loving"; "happened"; "so"; "fast"] in + let messages_map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + |> Rollup_messages_map.add sc_rollup_2 messages_rollup_2 + in + let* serialized = V0.serialize ~max_size messages_map in + let* () = + Assert.equal_int + ~loc:__LOC__ + (String.length serialized) + (V0.expected_slot_size messages_map) + in + let* deserialized = V0.deserialize ~max_size serialized in + let rollups_with_messages = Rollup_messages_map.bindings deserialized in + let* () = + assert_equal_list_rollups + ~loc:__LOC__ + "Deserialized rollups are different from originals" + [sc_rollup_1; sc_rollup_2] + (List.map fst rollups_with_messages) + in + assert_equal_list_list_string + ~loc:__LOC__ + "Messages frames are different from originals" + [messages_rollup_1; messages_rollup_2] + (List.map snd rollups_with_messages) + +let slot_frame_encoding_fails_if_too_big () = + let messages_rollup_1 = ["Summer"; "loving"; "had"; "me"; "a"; "blast"] in + let messages_rollup_2 = ["Summer"; "loving"; "happened"; "so"; "fast"] in + let messages_map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + |> Rollup_messages_map.add sc_rollup_2 messages_rollup_2 + in + let actual_size = V0.expected_slot_size messages_map in + let max_size = actual_size - 1 in + assert_fails_with + ~loc:__LOC__ + (V0.serialize ~max_size messages_map) + (Dal_slot_frame_encoding.Slot_size_is_too_big {actual_size; max_size}) + +let slot_frame_decoding_fails_if_too_big () = + let open Lwt_result_syntax in + let messages_rollup_1 = ["Summer"; "loving"; "had"; "me"; "a"; "blast"] in + let messages_rollup_2 = ["Summer"; "loving"; "happened"; "so"; "fast"] in + let messages_map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + |> Rollup_messages_map.add sc_rollup_2 messages_rollup_2 + in + let actual_size = V0.expected_slot_size messages_map in + let* serialized = V0.serialize ~max_size:actual_size messages_map in + let max_size = actual_size - 1 in + assert_fails_with + ~loc:__LOC__ + (V0.deserialize ~max_size serialized) + (Dal_slot_frame_encoding.Slot_size_is_too_big {actual_size; max_size}) + +let slot_frame_decoding_fails_if_wrong_version () = + let open Lwt_result_syntax in + let messages_rollup_1 = ["Summer"; "loving"; "had"; "me"; "a"; "blast"] in + let messages_rollup_2 = ["Summer"; "loving"; "happened"; "so"; "fast"] in + let messages_map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + |> Rollup_messages_map.add sc_rollup_2 messages_rollup_2 + in + let* serialized = + Dal_slot_frame_encoding.V0.serialize ~max_size messages_map + in + let serialized_wrong_version = + "\001" ^ String.sub serialized 1 (String.length serialized - 1) + in + assert_fails_with + ~loc:__LOC__ + (V0.deserialize ~max_size serialized_wrong_version) + (Dal_slot_frame_encoding.Wrong_slot_frame_version + {expected = 0; provided = 1}) + +let slot_frame_encoding_correct_offsets () = + let open Lwt_result_syntax in + let messages_rollup_1 = ["hello"; "world"] in + let messages_rollup_2 = ["CAFEBABE"; "CAFEDEAD"] in + let messages_map = + Rollup_messages_map.empty + |> Rollup_messages_map.add sc_rollup_1 messages_rollup_1 + |> Rollup_messages_map.add sc_rollup_2 messages_rollup_2 + in + let* serialized = V0.serialize ~max_size messages_map in + (* the value of the offset that denotes where the messages frame for + sc_rollup_1 starts can be found at offset 25 until 29 (excluded): + 1 byte for version + + 4 bytes for rollups frame prefix + + 20 bytes for rollup address = 25. + *) + let first_offset = + String.sub serialized 25 4 |> Data_encoding.(Binary.of_string_exn int32) + in + (* the value of the offset should be 57l: + 1 byte for version number + 4 bytes for rollups frame prefix + + 2 * 24 bytes for rollups frame + + 4 bytes for messages frames prefix = 57. *) + let* () = Assert.equal_int32 ~loc:__LOC__ first_offset 57l in + (* The length of the first messages frame should be 22 bytes: + 4 bytes for the messages frame prefix + + 4 + 5 bytes for the encoding of the message "hello" + + 4 + 5 bytes for the encoding of the message "world" = 22. + *) + let first_messages_frame = + Data_encoding.(Binary.of_string_exn @@ list string) + @@ String.sub serialized 57 22 + in + let* () = + assert_equal_list_string + ~loc:__LOC__ + "Messages frame for sc_rollup_1 is not as expected" + first_messages_frame + ["hello"; "world"] + in + (* The value of the offset that denotes where the messages frame for + sc_rollup_2 STARTS can be found at bytes 49 until 53 (excluded): + 29 offset where the entry for sc_rollup_2 starts + + 20 bytes for the encoding of sc_rollup_2 = 49. + *) + let second_offset = + String.sub serialized 49 4 |> Data_encoding.(Binary.of_string_exn int32) + in + (* the value of the second offset should be 79 + 57 offset where the messages frame for sc_rollup_1 starts + + 22 bytes length of the first messages frame = 79 + *) + let* () = Assert.equal_int32 ~loc:__LOC__ second_offset 79l in + (* The length of the first messages frame should be 28: + 4 bytes for the messages frame prefix + + 4 + 8 bytes for the encoding of the message "CAFEBABE" + + 4 + 8 bytes for the encoding of the message "CAFEDEAD" = 28 + *) + let second_messages_frame = + Data_encoding.(Binary.of_string_exn @@ list string) + @@ String.sub serialized 79 28 + in + assert_equal_list_string + ~loc:__LOC__ + "Messages frame for sc_rollup_1 is not as expected" + second_messages_frame + ["CAFEBABE"; "CAFEDEAD"] + +let tests = + [ + Tztest.tztest + "Encoded slot has expected size (V0, 1 rollup)" + `Quick + slot_frame_encoding_size_correct_single_v0; + Tztest.tztest + "Encoded slot has expected size (V0, 2 rollups)" + `Quick + slot_frame_encoding_size_correct_multiple_v0; + Tztest.tztest + "Encoded slot can be decoded (V0, 1 rollup)" + `Quick + slot_frame_encoding_decoding_correct_single_v0; + Tztest.tztest + "Encoded slot can be decoded (V0, 2 rollups)" + `Quick + slot_frame_encoding_decoding_correct_multiple_v0; + Tztest.tztest + "Encoding of a slot over maximum size fails (V0)" + `Quick + slot_frame_encoding_fails_if_too_big; + Tztest.tztest + "Offsets of messages frames are correct (V0)" + `Quick + slot_frame_encoding_correct_offsets; + Tztest.tztest + "Slot decoding fails when slot size is too big (V0)" + `Quick + slot_frame_decoding_fails_if_too_big; + Tztest.tztest + "Slot decoding fails when first byte has wrong version (V0)" + `Quick + slot_frame_decoding_fails_if_wrong_version; + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [Test_helpers.Unit_test.spec "Slot_framing_protocol.ml" tests] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_dal/test/test_helpers.ml b/src/proto_020_PsParisC/lib_dal/test/test_helpers.ml new file mode 100644 index 000000000000..4c0437a54c22 --- /dev/null +++ b/src/proto_020_PsParisC/lib_dal/test/test_helpers.ml @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Unit_test : sig + (** + * Example: [spec "Slot_framing_protocol.ml" Test_dal_slot_frame_encoding.test_cases] + * Unit tests needs tag in log (like "[UNIT] some test description here...") + * This function handles such meta data *) + val spec : + string -> + unit Alcotest_lwt.test_case list -> + string * unit Alcotest_lwt.test_case list + + (** Tests with description string without [Unit] are skipped *) + val _skip : + string -> + unit Alcotest_lwt.test_case list -> + string * unit Alcotest_lwt.test_case list +end = struct + let spec unit_name test_cases = ("[Unit] " ^ unit_name, test_cases) + + let _skip unit_name test_cases = ("[SKIPPED] " ^ unit_name, test_cases) +end diff --git a/src/proto_020_PsParisC/lib_delegate/abstract_context_index.ml b/src/proto_020_PsParisC/lib_delegate/abstract_context_index.ml new file mode 100644 index 000000000000..2e54f32fdc13 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/abstract_context_index.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + sync_fun : unit -> unit Lwt.t; + checkout_fun : + Context_hash.t -> Tezos_protocol_environment.Context.t option Lwt.t; + finalize_fun : unit -> unit Lwt.t; +} + +let abstract index = + { + sync_fun = (fun () -> Context.sync index); + checkout_fun = Shell_context.checkout index; + finalize_fun = (fun () -> Context.close index); + } diff --git a/src/proto_020_PsParisC/lib_delegate/abstract_context_index.mli b/src/proto_020_PsParisC/lib_delegate/abstract_context_index.mli new file mode 100644 index 000000000000..5a280d04ac57 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/abstract_context_index.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + sync_fun : unit -> unit Lwt.t; + checkout_fun : + Context_hash.t -> Tezos_protocol_environment.Context.t option Lwt.t; + finalize_fun : unit -> unit Lwt.t; +} + +val abstract : Context.index -> t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_actions.ml b/src/proto_020_PsParisC/lib_delegate/baking_actions.ml new file mode 100644 index 000000000000..ac14fd994eae --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_actions.ml @@ -0,0 +1,1006 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_state +module Events = Baking_events.Actions + +module Operations_source = struct + type error += + | Failed_operations_fetch of { + path : string; + reason : string; + details : Data_encoding.json option; + } + + let operations_encoding = + Data_encoding.(list (dynamic_size Operation.encoding)) + + let retrieve = + let open Lwt_result_syntax in + function + | None -> Lwt.return_none + | Some operations -> ( + let fail reason details = + let path = + match operations with + | Baking_configuration.Operations_source.Local {filename} -> + filename + | Baking_configuration.Operations_source.Remote {uri; _} -> + Uri.to_string uri + in + tzfail (Failed_operations_fetch {path; reason; details}) + in + let decode_operations json = + protect + ~on_error:(fun _ -> + fail "cannot decode the received JSON into operations" (Some json)) + (fun () -> + return (Data_encoding.Json.destruct operations_encoding json)) + in + match operations with + | Baking_configuration.Operations_source.Local {filename} -> + if Sys.file_exists filename then + let*! result = + Tezos_stdlib_unix.Lwt_utils_unix.Json.read_file filename + in + match result with + | Error _ -> + let*! () = Events.(emit invalid_json_file filename) in + Lwt.return_none + | Ok json -> ( + let*! operations = decode_operations json in + match operations with + | Ok operations -> Lwt.return_some operations + | Error errs -> + let*! () = Events.(emit cannot_fetch_operations errs) in + Lwt.return_none) + else + let*! () = Events.(emit no_operations_found_in_file filename) in + Lwt.return_none + | Baking_configuration.Operations_source.Remote {uri; http_headers} -> ( + let*! operations_opt = + let* result = + with_timeout + (Systime_os.sleep (Time.System.Span.of_seconds_exn 5.)) + (fun _ -> + Tezos_rpc_http_client_unix.RPC_client_unix + .generic_media_type_call + ~accept:[Media_type.json] + ?headers:http_headers + `GET + uri) + in + let* rest = + match result with + | `Json json -> return json + | _ -> fail "json not returned" None + in + let* json = + match rest with + | `Ok json -> return json + | `Unauthorized json -> fail "unauthorized request" json + | `Gone json -> fail "gone" json + | `Error json -> fail "error" json + | `Not_found json -> fail "not found" json + | `Forbidden json -> fail "forbidden" json + | `Conflict json -> fail "conflict" json + in + decode_operations json + in + match operations_opt with + | Ok operations -> Lwt.return_some operations + | Error errs -> + let*! () = Events.(emit cannot_fetch_operations errs) in + Lwt.return_none)) +end + +type action = + | Do_nothing + | Prepare_block of {block_to_bake : block_to_bake} + | Prepare_preattestations of {preattestations : unsigned_consensus_vote_batch} + | Prepare_attestations of {attestations : unsigned_consensus_vote_batch} + | Prepare_consensus_votes of { + preattestations : unsigned_consensus_vote_batch; + attestations : unsigned_consensus_vote_batch; + } + | Inject_block of { + prepared_block : prepared_block; + force_injection : bool; + asynchronous : bool; + } + | Inject_preattestation of {signed_preattestation : signed_consensus_vote} + | Inject_attestations of {signed_attestations : signed_consensus_vote_batch} + | Update_to_level of level_update + | Synchronize_round of round_update + | Watch_prequorum + | Watch_quorum + +and level_update = { + new_level_proposal : proposal; + compute_new_state : + current_round:Round.t -> + delegate_slots:delegate_slots -> + next_level_delegate_slots:delegate_slots -> + (state * action) Lwt.t; +} + +and round_update = { + new_round_proposal : proposal; + handle_proposal : state -> (state * action) Lwt.t; +} + +type t = action + +let pp_action fmt = function + | Do_nothing -> Format.fprintf fmt "do nothing" + | Prepare_block _ -> Format.fprintf fmt "prepare block" + | Prepare_preattestations _ -> Format.fprintf fmt "prepare preattestations" + | Prepare_attestations _ -> Format.fprintf fmt "prepare attestations" + | Prepare_consensus_votes _ -> Format.fprintf fmt "prepare consensus votes" + | Inject_block _ -> Format.fprintf fmt "inject block" + | Inject_preattestation _ -> Format.fprintf fmt "inject preattestation" + | Inject_attestations _ -> Format.fprintf fmt "inject multiple attestations" + | Update_to_level _ -> Format.fprintf fmt "update to level" + | Synchronize_round _ -> Format.fprintf fmt "synchronize round" + | Watch_prequorum -> Format.fprintf fmt "watch prequorum" + | Watch_quorum -> Format.fprintf fmt "watch quorum" + +let generate_seed_nonce_hash config delegate level = + let open Lwt_result_syntax in + if level.Level.expected_commitment then + let* seed_nonce = + Baking_nonces.generate_seed_nonce config delegate level.level + in + return_some seed_nonce + else return_none + +let sign_block_header global_state proposer unsigned_block_header = + let open Lwt_result_syntax in + let cctxt = global_state.cctxt in + let chain_id = global_state.chain_id in + let force = global_state.config.force in + let {Block_header.shell; protocol_data = {contents; _}} = + unsigned_block_header + in + let unsigned_header = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Block_header.unsigned_encoding + (shell, contents) + in + let level = shell.level in + let*? round = Baking_state.round_of_shell_header shell in + let open Baking_highwatermarks in + let* result = + cctxt#with_lock (fun () -> + let block_location = + Baking_files.resolve_location ~chain_id `Highwatermarks + in + let* may_sign = + may_sign_block + cctxt + block_location + ~delegate:proposer.public_key_hash + ~level + ~round + in + match may_sign with + | true -> + let* () = + record_block + cctxt + block_location + ~delegate:proposer.public_key_hash + ~level + ~round + in + return_true + | false -> + let*! () = Events.(emit potential_double_baking (level, round)) in + return force) + in + match result with + | false -> tzfail (Block_previously_baked {level; round}) + | true -> + let* signature = + Client_keys.sign + cctxt + proposer.secret_key_uri + ~watermark:Block_header.(to_watermark (Block_header chain_id)) + unsigned_header + in + return {Block_header.shell; protocol_data = {contents; signature}} + +let prepare_block (global_state : global_state) (block_to_bake : block_to_bake) + = + let open Lwt_result_syntax in + let { + predecessor; + round; + delegate = (consensus_key, _) as delegate; + kind; + force_apply; + } = + block_to_bake + in + let*! () = + Events.( + emit + prepare_forging_block + (Int32.succ predecessor.shell.level, round, delegate)) + in + let cctxt = global_state.cctxt in + let chain_id = global_state.chain_id in + let simulation_mode = global_state.validation_mode in + let round_durations = global_state.round_durations in + let*? timestamp = + Environment.wrap_tzresult + (Round.timestamp_of_round + round_durations + ~predecessor_timestamp:predecessor.shell.timestamp + ~predecessor_round:predecessor.round + ~round) + in + let external_operation_source = global_state.config.extra_operations in + let*! extern_ops = Operations_source.retrieve external_operation_source in + let simulation_kind, payload_round = + match kind with + | Fresh pool -> + let pool = + let node_pool = Operation_pool.Prioritized.of_pool pool in + match extern_ops with + | None -> node_pool + | Some ops -> + Operation_pool.Prioritized.merge_external_operations node_pool ops + in + (Block_forge.Filter pool, round) + | Reproposal {consensus_operations; payload_hash; payload_round; payload} -> + ( Block_forge.Apply + { + ordered_pool = + Operation_pool.ordered_pool_of_payload + ~consensus_operations + payload; + payload_hash; + }, + payload_round ) + in + let*! () = + Events.( + emit forging_block (Int32.succ predecessor.shell.level, round, delegate)) + in + let* injection_level = + Plugin.RPC.current_level + cctxt + ~offset:1l + (`Hash global_state.chain_id, `Hash (predecessor.hash, 0)) + in + let* seed_nonce_opt = + generate_seed_nonce_hash + global_state.config.Baking_configuration.nonce + consensus_key + injection_level + in + let seed_nonce_hash = Option.map fst seed_nonce_opt in + let user_activated_upgrades = global_state.config.user_activated_upgrades in + (* Set liquidity_baking_toggle_vote for this block *) + let { + Baking_configuration.vote_file; + liquidity_baking_vote; + adaptive_issuance_vote; + } = + global_state.config.per_block_votes + in + (* Prioritize reading from the [vote_file] if it exists. *) + let*! {liquidity_baking_vote; adaptive_issuance_vote} = + let default = + Protocol.Alpha_context.Per_block_votes. + {liquidity_baking_vote; adaptive_issuance_vote} + in + match vote_file with + | Some per_block_vote_file -> + Per_block_vote_file.read_per_block_votes_no_fail + ~default + ~per_block_vote_file + | None -> Lwt.return default + in + let*! () = + Events.(emit vote_for_liquidity_baking_toggle) liquidity_baking_vote + in + let*! () = Events.(emit vote_for_adaptive_issuance) adaptive_issuance_vote in + let chain = `Hash global_state.chain_id in + let pred_block = `Hash (predecessor.hash, 0) in + let* pred_resulting_context_hash = + Shell_services.Blocks.resulting_context_hash + cctxt + ~chain + ~block:pred_block + () + in + let* pred_live_blocks = + Chain_services.Blocks.live_blocks cctxt ~chain ~block:pred_block () + in + let* {unsigned_block_header; operations} = + Block_forge.forge + cctxt + ~chain_id + ~pred_info:predecessor + ~pred_live_blocks + ~pred_resulting_context_hash + ~timestamp + ~round + ~seed_nonce_hash + ~payload_round + ~liquidity_baking_toggle_vote:liquidity_baking_vote + ~adaptive_issuance_vote + ~user_activated_upgrades + ~force_apply + global_state.config.fees + simulation_mode + simulation_kind + global_state.constants.parametric + in + let* signed_block_header = + sign_block_header global_state consensus_key unsigned_block_header + in + let* () = + match seed_nonce_opt with + | None -> + (* Nothing to do *) + return_unit + | Some (_, nonce) -> + let block_hash = Block_header.hash signed_block_header in + Baking_nonces.register_nonce + cctxt + ~chain_id + block_hash + nonce + ~cycle:injection_level.cycle + ~level:injection_level.level + ~round + in + let baking_votes = + {Per_block_votes.liquidity_baking_vote; adaptive_issuance_vote} + in + return {signed_block_header; round; delegate; operations; baking_votes} + +let only_if_dal_feature_enabled = + let no_dal_node_warning_counter = ref 0 in + fun state ~default_value f -> + let open Lwt_result_syntax in + let open Constants in + let Parametric.{dal = {feature_enable; _}; _} = + state.global_state.constants.parametric + in + if feature_enable then + match state.global_state.dal_node_rpc_ctxt with + | None -> + incr no_dal_node_warning_counter ; + let*! () = + if !no_dal_node_warning_counter mod 10 = 1 then + Events.(emit no_dal_node ()) + else Lwt.return_unit + in + return default_value + | Some ctxt -> f ctxt + else return default_value + +let may_get_dal_content state consensus_vote = + let open Lwt_result_syntax in + let {delegate = (consensus_key, _) as delegate; vote_consensus_content; _} = + consensus_vote + in + let level, round = + ( Raw_level.to_int32 vote_consensus_content.level, + vote_consensus_content.round ) + in + let compute_dal_rpc_timeout state = + (* We set the timeout to a certain percent of the remaining time till the + end of the round. *) + let default = 0.2 in + match compute_next_round_time state with + | None -> (* corner case; we pick some small default value *) default + | Some (timestamp, _next_round) -> ( + let ts = Time.System.of_protocol_opt timestamp in + match ts with + | None -> default + | Some ts -> + let now = Time.System.now () in + let diff = Ptime.diff ts now |> Ptime.Span.to_float_s in + if diff < 0. then + (* We could output a warning, as this should not happen. *) + default + else diff *. 0.1) + in + only_if_dal_feature_enabled + state + ~default_value:None + (fun dal_node_rpc_ctxt -> + let attested_level = Int32.succ level in + let lag = state.global_state.constants.parametric.dal.attestation_lag in + if Int32.sub attested_level (Int32.of_int lag) < 1l then return_none + else + let timeout = compute_dal_rpc_timeout state in + let*! result = + Lwt.pick + [ + (let*! () = Lwt_unix.sleep timeout in + Lwt.return `RPC_timeout); + (let*! tz_res = + Node_rpc.get_attestable_slots + dal_node_rpc_ctxt + consensus_key.public_key_hash + ~attested_level + in + Lwt.return (`RPC_result tz_res)); + ] + in + match result with + | `RPC_timeout -> + let*! () = + Events.( + emit failed_to_get_dal_attestations_in_time (delegate, timeout)) + in + return_none + | `RPC_result (Error errs) -> + let*! () = + Events.(emit failed_to_get_dal_attestations (delegate, errs)) + in + return_none + | `RPC_result (Ok res) -> ( + match res with + | Tezos_dal_node_services.Types.Not_in_committee -> return_none + | Attestable_slots {slots = attestation_flags; published_level} -> + let number_of_slots = + state.global_state.constants.parametric.dal.number_of_slots + in + let dal_attestation = + List.fold_left_i + (fun i acc flag -> + match Dal.Slot_index.of_int_opt ~number_of_slots i with + | Some index when flag -> Dal.Attestation.commit acc index + | None | Some _ -> acc) + Dal.Attestation.empty + attestation_flags + in + let*! () = + let bitset_int = Bitset.to_z (dal_attestation :> Bitset.t) in + Events.( + emit + attach_dal_attestation + (delegate, bitset_int, published_level, level, round)) + in + return_some {attestation = dal_attestation})) + +let is_authorized (global_state : global_state) highwatermarks consensus_vote = + let {delegate = consensus_key, _; vote_consensus_content; _} = + consensus_vote + in + let level, round = + ( Raw_level.to_int32 vote_consensus_content.level, + vote_consensus_content.round ) + in + let may_sign = + match consensus_vote.vote_kind with + | Preattestation -> + Baking_highwatermarks.may_sign_preattestation + highwatermarks + ~delegate:consensus_key.public_key_hash + ~level + ~round + | Attestation -> + Baking_highwatermarks.may_sign_attestation + highwatermarks + ~delegate:consensus_key.public_key_hash + ~level + ~round + in + may_sign || global_state.config.force + +let authorized_consensus_votes global_state + (unsigned_consensus_vote_batch : unsigned_consensus_vote_batch) = + let open Lwt_result_syntax in + (* Hypothesis: all consensus votes have the same round and level *) + let { + batch_kind; + batch_content = ({level; round; _} : batch_content); + batch_branch = _; + unsigned_consensus_votes; + } = + unsigned_consensus_vote_batch + in + let level = Raw_level.to_int32 level in + let cctxt = global_state.cctxt in + let chain_id = global_state.chain_id in + let block_location = + Baking_files.resolve_location ~chain_id `Highwatermarks + in + (* Filter all operations that don't satisfy the highwatermark and + record the ones that do. *) + let* authorized_votes, unauthorized_votes = + cctxt#with_lock (fun () -> + let* highwatermarks = Baking_highwatermarks.load cctxt block_location in + let authorized_votes, unauthorized_votes = + List.partition + (fun consensus_vote -> + is_authorized global_state highwatermarks consensus_vote) + unsigned_consensus_votes + in + (* Record all consensus votes new highwatermarks as one batch *) + let delegates = + List.map + (fun {delegate = ck, _; _} -> ck.public_key_hash) + authorized_votes + in + let record_all_consensus_vote = + match batch_kind with + | Preattestation -> Baking_highwatermarks.record_all_preattestations + | Attestation -> Baking_highwatermarks.record_all_attestations + in + (* We exit the client's lock as soon as this function returns *) + let* () = + record_all_consensus_vote + highwatermarks + cctxt + block_location + ~delegates + ~level + ~round + in + return (authorized_votes, unauthorized_votes)) + in + let*! () = + List.iter_s + (fun {vote_kind; delegate; _} -> + let error = + match vote_kind with + | Preattestation -> + Baking_highwatermarks.Block_previously_preattested {round; level} + | Attestation -> + Baking_highwatermarks.Block_previously_attested {round; level} + in + Events.( + emit + skipping_consensus_vote + (vote_kind, delegate, level, round, [error]))) + unauthorized_votes + in + return authorized_votes + +let forge_and_sign_consensus_vote global_state ~branch unsigned_consensus_vote : + signed_consensus_vote tzresult Lwt.t = + let open Lwt_result_syntax in + let cctxt = global_state.cctxt in + let chain_id = global_state.chain_id in + let {vote_kind; vote_consensus_content; delegate = ck, _; dal_content} = + unsigned_consensus_vote + in + let shell = {Tezos_base.Operation.branch} in + let watermark = + match vote_kind with + | Preattestation -> Operation.(to_watermark (Preattestation chain_id)) + | Attestation -> Operation.(to_watermark (Attestation chain_id)) + in + let (Contents_list contents) = + match vote_kind with + | Preattestation -> + Contents_list (Single (Preattestation vote_consensus_content)) + | Attestation -> + Contents_list + (Single + (Attestation + {consensus_content = vote_consensus_content; dal_content})) + in + let unsigned_operation = (shell, Contents_list contents) in + let unsigned_operation_bytes = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + unsigned_operation + in + let sk_uri = ck.secret_key_uri in + let* signature = + Client_keys.sign cctxt ~watermark sk_uri unsigned_operation_bytes + in + let protocol_data = Operation_data {contents; signature = Some signature} in + let signed_operation : Operation.packed = {shell; protocol_data} in + return {unsigned_consensus_vote; signed_operation} + +let sign_consensus_votes (global_state : global_state) + ({batch_kind; batch_content; batch_branch; _} as + unsigned_consensus_vote_batch : + unsigned_consensus_vote_batch) = + let open Lwt_result_syntax in + let* authorized_consensus_votes = + authorized_consensus_votes global_state unsigned_consensus_vote_batch + in + let* signed_consensus_votes = + List.filter_map_es + (fun ({delegate; vote_kind; vote_consensus_content; _} as + unsigned_consensus_vote) -> + let*! () = Events.(emit signing_consensus_vote (vote_kind, delegate)) in + let*! signed_consensus_vote_r = + forge_and_sign_consensus_vote + global_state + ~branch:batch_branch + unsigned_consensus_vote + in + match signed_consensus_vote_r with + | Error err -> + let level, round = + ( Raw_level.to_int32 vote_consensus_content.level, + vote_consensus_content.round ) + in + let*! () = + Events.( + emit + skipping_consensus_vote + (vote_kind, delegate, level, round, err)) + in + return_none + | Ok signed_consensus_vote -> return_some signed_consensus_vote) + authorized_consensus_votes + in + let*? signed_consensus_vote_batch = + make_signed_consensus_vote_batch + batch_kind + batch_content + ~batch_branch + signed_consensus_votes + in + return signed_consensus_vote_batch + +let inject_consensus_vote state (signed_consensus_vote : signed_consensus_vote) + = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + let chain_id = state.global_state.chain_id in + let unsigned_consensus_vote = signed_consensus_vote.unsigned_consensus_vote in + let delegate = unsigned_consensus_vote.delegate in + let vote_consensus_content = unsigned_consensus_vote.vote_consensus_content in + let level, round = + ( Raw_level.to_int32 vote_consensus_content.level, + vote_consensus_content.round ) + in + protect + ~on_error:(fun err -> + let*! () = + Events.( + emit + failed_to_inject_consensus_vote + (unsigned_consensus_vote.vote_kind, delegate, err)) + in + return_unit) + (fun () -> + let* oph = + Node_rpc.inject_operation + cctxt + ~chain:(`Hash chain_id) + signed_consensus_vote.signed_operation + in + let*! () = + Events.( + emit + consensus_vote_injected + (unsigned_consensus_vote.vote_kind, oph, delegate, level, round)) + in + return_unit) + +let inject_consensus_votes state signed_consensus_vote_batch = + List.iter_ep + (inject_consensus_vote state) + signed_consensus_vote_batch.signed_consensus_votes + +let inject_block ?(force_injection = false) ?(asynchronous = true) state + prepared_block = + let open Lwt_result_syntax in + let {signed_block_header; round; delegate; operations; baking_votes} = + prepared_block + in + (* Cache last per-block votes to use in case of vote file errors *) + let new_state = + { + state with + global_state = + { + state.global_state with + config = + { + state.global_state.config with + per_block_votes = + { + state.global_state.config.per_block_votes with + liquidity_baking_vote = baking_votes.liquidity_baking_vote; + adaptive_issuance_vote = baking_votes.adaptive_issuance_vote; + }; + }; + }; + } + in + let inject_block () = + let*! () = + Events.( + emit injecting_block (signed_block_header.shell.level, round, delegate)) + in + let* bh = + Node_rpc.inject_block + state.global_state.cctxt + ~force:state.global_state.config.force + ~chain:(`Hash state.global_state.chain_id) + signed_block_header + operations + in + let*! () = + Events.( + emit + block_injected + (bh, signed_block_header.shell.level, round, delegate)) + in + return_unit + in + let now = Time.System.now () in + let block_time = + Time.System.of_protocol_exn signed_block_header.shell.timestamp + in + (* Blocks might be ready before their actual timestamp: when this + happens, we wait asynchronously until our clock reaches the + block's timestamp before injecting. *) + let* () = + let delay = Ptime.diff block_time now in + if Ptime.Span.(compare delay zero < 0) || force_injection then + inject_block () + else + let*! () = + Events.( + emit + delayed_block_injection + (delay, signed_block_header.shell.level, round, delegate)) + in + let t = + let*! _ = + protect + ~on_error:(fun err -> + let*! () = + Events.( + emit + block_injection_failed + (Block_header.hash signed_block_header, err)) + in + return_unit) + (fun () -> + let*! () = Lwt_unix.sleep (Ptime.Span.to_float_s delay) in + inject_block ()) + in + Lwt.return_unit + in + let*! () = + if asynchronous then ( + Lwt.dont_wait (fun () -> t) (fun _exn -> ()) ; + Lwt.return_unit) + else t + in + return_unit + in + return new_state + +let prepare_waiting_for_quorum state = + let consensus_threshold = + state.global_state.constants.parametric.consensus_threshold + in + let get_slot_voting_power ~slot = + Delegate_slots.voting_power state.level_state.delegate_slots ~slot + in + let latest_proposal = state.level_state.latest_proposal.block in + (* assert (latest_proposal.block.round = state.round_state.current_round) ; *) + let candidate = + { + Operation_worker.hash = latest_proposal.hash; + round_watched = latest_proposal.round; + payload_hash_watched = latest_proposal.payload_hash; + } + in + (consensus_threshold, get_slot_voting_power, candidate) + +let start_waiting_for_preattestation_quorum state = + let consensus_threshold, get_slot_voting_power, candidate = + prepare_waiting_for_quorum state + in + let operation_worker = state.global_state.operation_worker in + Operation_worker.monitor_preattestation_quorum + operation_worker + ~consensus_threshold + ~get_slot_voting_power + candidate + +let start_waiting_for_attestation_quorum state = + let consensus_threshold, get_slot_voting_power, candidate = + prepare_waiting_for_quorum state + in + let operation_worker = state.global_state.operation_worker in + Operation_worker.monitor_attestation_quorum + operation_worker + ~consensus_threshold + ~get_slot_voting_power + candidate + +let compute_round proposal round_durations = + let open Protocol in + let open Baking_state in + let timestamp = Time.System.now () |> Time.System.to_protocol in + let predecessor_block = proposal.predecessor in + Environment.wrap_tzresult + @@ Alpha_context.Round.round_of_timestamp + round_durations + ~predecessor_timestamp:predecessor_block.shell.timestamp + ~predecessor_round:predecessor_block.round + ~timestamp + +let update_to_level state level_update = + let open Lwt_result_syntax in + let {new_level_proposal; compute_new_state} = level_update in + let cctxt = state.global_state.cctxt in + let delegates = state.global_state.delegates in + let new_level = new_level_proposal.block.shell.level in + let chain = `Hash state.global_state.chain_id in + (* Sync the context to clean-up potential GC artifacts *) + let*! () = + match state.global_state.validation_mode with + | Node -> Lwt.return_unit + | Local index -> index.sync_fun () + in + let* delegate_slots = + if Int32.(new_level = succ state.level_state.current_level) then + return state.level_state.next_level_delegate_slots + else + Baking_state.compute_delegate_slots + cctxt + delegates + ~level:new_level + ~chain + in + let* next_level_delegate_slots = + Baking_state.compute_delegate_slots + cctxt + delegates + ~level:(Int32.succ new_level) + ~chain + in + let round_durations = state.global_state.round_durations in + let*? current_round = compute_round new_level_proposal round_durations in + let*! new_state = + compute_new_state ~current_round ~delegate_slots ~next_level_delegate_slots + in + return new_state + +let synchronize_round state {new_round_proposal; handle_proposal} = + let open Lwt_result_syntax in + let*! () = + Events.(emit synchronizing_round new_round_proposal.predecessor.hash) + in + let round_durations = state.global_state.round_durations in + let*? current_round = compute_round new_round_proposal round_durations in + if Round.(current_round < new_round_proposal.block.round) then + (* impossible *) + failwith + "synchronize_round: current round (%a) is behind the new proposal's \ + round (%a)" + Round.pp + current_round + Round.pp + new_round_proposal.block.round + else + let new_round_state = + { + current_round; + current_phase = Idle; + delayed_quorum = None; + early_attestations = []; + awaiting_unlocking_pqc = false; + } + in + let new_state = {state with round_state = new_round_state} in + let*! new_state = handle_proposal new_state in + return new_state + +let prepare_block_request state block_to_bake = + let open Lwt_result_syntax in + let request = Forge_and_sign_block block_to_bake in + state.global_state.forge_worker_hooks.push_request request ; + return state + +let prepare_preattestations_request state unsigned_preattestations = + let open Lwt_result_syntax in + let request = Forge_and_sign_preattestations {unsigned_preattestations} in + state.global_state.forge_worker_hooks.push_request request ; + return state + +let prepare_attestations_request state unsigned_attestations = + let open Lwt_result_syntax in + let*! unsigned_attestations_with_dal = + dal_content_map_p (may_get_dal_content state) unsigned_attestations + in + let request = + Forge_and_sign_attestations + {unsigned_attestations = unsigned_attestations_with_dal} + in + state.global_state.forge_worker_hooks.push_request request ; + return state + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4539 + Avoid updating the state here. + (See also comment in {!State_transitions.step}.) + + TODO: https://gitlab.com/tezos/tezos/-/issues/4538 + Improve/clarify when the state is recorded. +*) +let rec perform_action state (action : action) = + let open Lwt_result_syntax in + match action with + | Do_nothing -> return state + | Prepare_block {block_to_bake} -> prepare_block_request state block_to_bake + | Prepare_preattestations {preattestations} -> + let* new_state = prepare_preattestations_request state preattestations in + (* We wait for preattestations to trigger the [Prequorum_reached] + event *) + perform_action new_state Watch_prequorum + | Prepare_attestations {attestations} -> + let* new_state = prepare_attestations_request state attestations in + (* We wait for attestations to trigger the [Quorum_reached] + event *) + perform_action new_state Watch_quorum + | Prepare_consensus_votes {preattestations; attestations} -> + let* state = prepare_preattestations_request state preattestations in + let* state = prepare_attestations_request state attestations in + (* We wait for preattestations to trigger the [Prequorum_reached] + event *) + perform_action state Watch_prequorum + | Inject_block {prepared_block; force_injection; asynchronous} -> + let* new_state = + inject_block ~force_injection ~asynchronous state prepared_block + in + return new_state + | Inject_preattestation {signed_preattestation} -> + let* () = inject_consensus_vote state signed_preattestation in + (* Here, we do not need to wait for the prequorum, it has + already been triggered by the + [Prepare_(preattestation|consensus_votes)] action *) + return state + | Inject_attestations {signed_attestations} -> + let* () = inject_consensus_votes state signed_attestations in + (* We wait for attestations to trigger the [Quorum_reached] + event *) + perform_action state Watch_quorum + | Update_to_level level_update -> + let* new_state, new_action = update_to_level state level_update in + perform_action new_state new_action + | Synchronize_round round_update -> + let* new_state, new_action = synchronize_round state round_update in + perform_action new_state new_action + | Watch_prequorum -> + let*! () = start_waiting_for_preattestation_quorum state in + return state + | Watch_quorum -> + let*! () = start_waiting_for_attestation_quorum state in + return state diff --git a/src/proto_020_PsParisC/lib_delegate/baking_actions.mli b/src/proto_020_PsParisC/lib_delegate/baking_actions.mli new file mode 100644 index 000000000000..f5e1c7e9ee30 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_actions.mli @@ -0,0 +1,118 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_state + +type action = + | Do_nothing + | Prepare_block of {block_to_bake : block_to_bake} + | Prepare_preattestations of {preattestations : unsigned_consensus_vote_batch} + | Prepare_attestations of {attestations : unsigned_consensus_vote_batch} + | Prepare_consensus_votes of { + preattestations : unsigned_consensus_vote_batch; + attestations : unsigned_consensus_vote_batch; + } + | Inject_block of { + prepared_block : prepared_block; + force_injection : bool; + asynchronous : bool; + } + | Inject_preattestation of {signed_preattestation : signed_consensus_vote} + | Inject_attestations of {signed_attestations : signed_consensus_vote_batch} + | Update_to_level of level_update + | Synchronize_round of round_update + | Watch_prequorum + | Watch_quorum + +and level_update = { + new_level_proposal : proposal; + compute_new_state : + current_round:Round.t -> + delegate_slots:delegate_slots -> + next_level_delegate_slots:delegate_slots -> + (state * action) Lwt.t; +} + +and round_update = { + new_round_proposal : proposal; + handle_proposal : state -> (state * action) Lwt.t; +} + +type t = action + +val pp_action : Format.formatter -> action -> unit + +val generate_seed_nonce_hash : + Baking_configuration.nonce_config -> + consensus_key -> + Level.t -> + (Nonce_hash.t * Nonce.t) option tzresult Lwt.t + +val prepare_block : + global_state -> block_to_bake -> prepared_block tzresult Lwt.t + +val inject_block : + ?force_injection:bool -> + ?asynchronous:bool -> + state -> + prepared_block -> + state tzresult Lwt.t + +val may_get_dal_content : + state -> unsigned_consensus_vote -> dal_content option tzresult Lwt.t + +val authorized_consensus_votes : + global_state -> + unsigned_consensus_vote_batch -> + unsigned_consensus_vote list tzresult Lwt.t + +val forge_and_sign_consensus_vote : + global_state -> + branch:Block_hash.t -> + unsigned_consensus_vote -> + signed_consensus_vote tzresult Lwt.t + +val sign_consensus_votes : + global_state -> + unsigned_consensus_vote_batch -> + signed_consensus_vote_batch tzresult Lwt.t + +val inject_consensus_votes : + state -> signed_consensus_vote_batch -> unit tzresult Lwt.t + +val prepare_waiting_for_quorum : + state -> int * (slot:Slot.t -> int option) * Operation_worker.candidate + +val start_waiting_for_preattestation_quorum : state -> unit Lwt.t + +val start_waiting_for_attestation_quorum : state -> unit Lwt.t + +val update_to_level : state -> level_update -> (state * t) tzresult Lwt.t + +val compute_round : proposal -> Round.round_durations -> Round.t tzresult + +val perform_action : state -> t -> state tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_cache.ml b/src/proto_020_PsParisC/lib_delegate/baking_cache.ml new file mode 100644 index 000000000000..2af2842c7777 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_cache.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Cache structures used to memoize costly RPCs/computations. *) + +open Protocol.Alpha_context + +type round = Round.t + +module Block_cache = + Aches.Vache.Map (Aches.Vache.LRU_Precise) (Aches.Vache.Strong) (Block_hash) + +(** The [Timestamp_of_round_tbl] module allows to create memoization tables + to store function calls of [Round.timestamp_of_round]. *) +module Timestamp_of_round_cache = + Aches.Vache.Map (Aches.Vache.LRU_Precise) (Aches.Vache.Strong) + (struct + (* The type of keys is a tuple that corresponds to the arguments + of [Round.timestamp_of_round]. *) + type t = Timestamp.time * round * round + + let hash k = Hashtbl.hash k + + let equal (ts, r1, r2) (ts', r1', r2') = + Timestamp.(ts = ts') && Round.(r1 = r1') && Round.(r2 = r2') + end) + +module Round_cache_key = struct + type ts_interval = Timestamp.time * Timestamp.time + + (** The values that are intended to be used here are the + arguments are: predecessor_timestamp * predecessor_round * + timestamp_interval *) + type t = { + predecessor_timestamp : Timestamp.time; + predecessor_round : round; + time_interval : ts_interval; + } + + let hash {predecessor_timestamp; predecessor_round; _} = + Stdlib.Hashtbl.hash (predecessor_timestamp, predecessor_round) + + let equal + { + predecessor_timestamp = pred_t; + predecessor_round = pred_r; + time_interval = t_beg, t_end; + } + { + predecessor_timestamp = pred_t'; + predecessor_round = pred_r'; + time_interval = t_beg', t_end'; + } = + Timestamp.(pred_t = pred_t') + && Round.(pred_r = pred_r') + && Timestamp.(t_beg' <= t_beg) + && Timestamp.(t_end < t_end') +end + +module Round_timestamp_interval_cache = + Aches.Vache.Map (Aches.Vache.LRU_Precise) (Aches.Vache.Strong) + (Round_cache_key) diff --git a/src/proto_020_PsParisC/lib_delegate/baking_commands.ml b/src/proto_020_PsParisC/lib_delegate/baking_commands.ml new file mode 100644 index 000000000000..0615a9075f28 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_commands.ml @@ -0,0 +1,716 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Client_proto_args +open Baking_errors + +let pidfile_arg = + let open Lwt_result_syntax in + Tezos_clic.arg + ~doc:"write process id in file" + ~short:'P' + ~long:"pidfile" + ~placeholder:"filename" + (Tezos_clic.parameter (fun _ s -> return s)) + +let may_lock_pidfile pidfile_opt f = + match pidfile_opt with + | None -> f () + | Some pidfile -> + Lwt_lock_file.try_with_lock + ~when_locked:(fun () -> + failwith "Failed to create the pidfile: %s" pidfile) + ~filename:pidfile + f + +let http_headers_env_variable = + "TEZOS_CLIENT_REMOTE_OPERATIONS_POOL_HTTP_HEADERS" + +let http_headers = + match Sys.getenv_opt http_headers_env_variable with + | None -> None + | Some contents -> + let lines = String.split_on_char '\n' contents in + Some + (List.fold_left + (fun acc line -> + match String.index_opt line ':' with + | None -> + invalid_arg + (Printf.sprintf + "Http headers: invalid %s environment variable, missing \ + colon" + http_headers_env_variable) + | Some pos -> + let header = String.trim (String.sub line 0 pos) in + let header = String.lowercase_ascii header in + if header <> "host" then + invalid_arg + (Printf.sprintf + "Http headers: invalid %s environment variable, only \ + 'host' headers are supported" + http_headers_env_variable) ; + let value = + String.trim + (String.sub line (pos + 1) (String.length line - pos - 1)) + in + (header, value) :: acc) + [] + lines) + +let operations_arg = + Tezos_clic.arg + ~long:"operations-pool" + ~placeholder:"file|uri" + ~doc: + (Printf.sprintf + "When specified, the baker will try to fetch operations from this \ + file (or uri) and to include retrieved operations in the block. The \ + expected format of the contents is a list of operations [ \ + alpha.operation ]. Environment variable '%s' may also be specified \ + to add headers to the requests (only 'host' headers are supported). \ + If the resource cannot be retrieved, e.g., if the file is absent, \ + unreadable, or the web service returns a 404 error, the resource is \ + simply ignored." + http_headers_env_variable) + (Tezos_clic.map_parameter + ~f:(fun uri -> + let open Baking_configuration in + match Uri.scheme uri with + | Some "http" | Some "https" -> + Operations_source.(Remote {uri; http_headers}) + | None | Some _ -> + (* acts as if it were file even though it might no be *) + Operations_source.(Local {filename = Uri.to_string uri})) + uri_parameter) + +let context_path_arg = + Tezos_clic.arg + ~long:"context" + ~placeholder:"path" + ~doc: + "When specified, the client will read in the local context at the \ + provided path in order to build the block, instead of relying on the \ + 'preapply' RPC." + string_parameter + +let force_apply_switch_arg = + Tezos_clic.switch + ~long:"force-apply" + ~doc:"Force the baker to not only validate but also apply operations." + () + +let attestation_force_switch_arg = + Tezos_clic.switch + ~long:"force" + ~short:'f' + ~doc: + "Disable consistency, injection and double signature checks for \ + (pre)attestations." + () + +let do_not_monitor_node_mempool_arg = + Tezos_clic.switch + ~long:"ignore-node-mempool" + ~doc: + "Ignore mempool operations from the node and do not subsequently monitor \ + them. Use in conjunction with --operations option to restrict the \ + observed operations to those of the mempool file." + () + +let keep_alive_arg = + Tezos_clic.switch + ~doc: + "Keep the daemon process alive: when the connection with the node is \ + lost, the daemon periodically tries to reach it." + ~short:'K' + ~long:"keep-alive" + () + +let per_block_vote_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter + ~autocomplete:(fun _ctxt -> return ["on"; "off"; "pass"]) + (let open Protocol.Alpha_context.Per_block_votes in + fun _ctxt -> function + | "on" -> return Per_block_vote_on + | "off" -> return Per_block_vote_off + | "pass" -> return Per_block_vote_pass + | s -> + failwith + "unexpected vote: %s, expected either \"on\", \"off\", or \"pass\"." + s) + +let liquidity_baking_toggle_vote_arg = + Tezos_clic.arg + ~doc: + "Vote to continue or end the liquidity baking subsidy. The possible \ + values for this option are: \"off\" to request ending the subsidy, \ + \"on\" to request continuing or restarting the subsidy, and \"pass\" to \ + abstain. Note that this \"option\" is mandatory!" + ~long:"liquidity-baking-toggle-vote" + ~placeholder:"vote" + per_block_vote_parameter + +let adaptive_issuance_vote_arg = + Tezos_clic.arg + ~doc: + "Vote to adopt or not the adaptive issuance feature. The possible values \ + for this option are: \"off\" to request not activating it, \"on\" to \ + request activating it, and \"pass\" to abstain. If you do not vote, \ + default value is \"pass\"." + ~long:"adaptive-issuance-vote" + ~placeholder:"vote" + per_block_vote_parameter + +let state_recorder_switch_arg = + let open Lwt_result_syntax in + let open Baking_configuration in + Tezos_clic.map_arg + ~f:(fun _cctxt flag -> if flag then return Filesystem else return Memory) + (Tezos_clic.switch + ~long:"record-state" + ~doc: + "If record-state flag is set, the baker saves all its internal \ + consensus state in the filesystem, otherwise just in memory." + ()) + +let get_delegates (cctxt : Protocol_client_context.full) + (pkhs : Signature.public_key_hash list) = + let open Lwt_result_syntax in + let proj_delegate (alias, public_key_hash, public_key, secret_key_uri) = + { + Baking_state.alias = Some alias; + public_key_hash; + public_key; + secret_key_uri; + } + in + let* delegates = + if pkhs = [] then + let* keys = Client_keys.get_keys cctxt in + List.map proj_delegate keys |> return + else + List.map_es + (fun pkh -> + let* result = Client_keys.get_key cctxt pkh in + match result with + | alias, pk, sk_uri -> return (proj_delegate (alias, pkh, pk, sk_uri))) + pkhs + in + let* () = + Tezos_signer_backends.Encrypted.decrypt_list + cctxt + (List.filter_map + (function + | {Baking_state.alias = Some alias; _} -> Some alias | _ -> None) + delegates) + in + let delegates_no_duplicates = List.sort_uniq compare delegates in + let*! () = + if List.compare_lengths delegates delegates_no_duplicates <> 0 then + cctxt#warning + "Warning: the list of public key hash aliases contains duplicate \ + hashes, which are ignored" + else Lwt.return_unit + in + return delegates_no_duplicates + +let sources_param = + Tezos_clic.seq_of_param + (Client_keys.Public_key_hash.source_param + ~name:"baker" + ~desc: + "name of the delegate owning the attestation/baking right or name of \ + the consensus key signing on the delegate's behalf") + +let endpoint_arg = + let open Lwt_result_syntax in + Tezos_clic.arg + ~long:"dal-node" + ~placeholder:"uri" + ~doc:"endpoint of the DAL node, e.g. 'http://localhost:8933'" + (Tezos_clic.parameter (fun _ s -> return @@ Uri.of_string s)) + +let block_count_arg = + Tezos_clic.default_arg + ~long:"count" + ~short:'n' + ~placeholder:"block count" + ~doc:"number of blocks to bake" + ~default:"1" + @@ Client_proto_args.positive_int_parameter () + +let delegate_commands () : Protocol_client_context.full Tezos_clic.command list + = + let open Lwt_result_syntax in + let open Tezos_clic in + let group = + {name = "delegate.client"; title = "Tenderbake client commands"} + in + [ + command + ~group + ~desc:"Benchmark the proof of work challenge resolution" + (args2 + (default_arg + ~doc:"Proof of work threshold" + ~long:"threshold" + ~placeholder:"int" + ~default: + (Int64.to_string + Default_parameters.constants_mainnet.proof_of_work_threshold) + (parameter (fun (cctxt : Protocol_client_context.full) x -> + try return (Int64.of_string x) + with _ -> cctxt#error "Expect an integer"))) + (arg + ~doc:"Random seed" + ~long:"seed" + ~placeholder:"int" + (parameter (fun (cctxt : Protocol_client_context.full) x -> + try return (int_of_string x) + with _ -> cctxt#error "Expect an integer")))) + (prefix "bench" + @@ param + ~name:"nb_draw" + ~desc:"number of draws" + (parameter (fun (cctxt : Protocol_client_context.full) x -> + match int_of_string x with + | x when x >= 1 -> return x + | _ | (exception _) -> + cctxt#error "Expect a strictly positive integer")) + @@ fixed ["baking"; "PoW"; "challenges"]) + (fun (proof_of_work_threshold, seed) nb_draw cctxt -> + let open Lwt_result_syntax in + let*! () = + cctxt#message + "Running %d iterations of proof-of-work challenge..." + nb_draw + in + let rstate = + match seed with + | None -> Random.State.make_self_init () + | Some s -> Random.State.make [|s|] + in + let* all = + List.map_es + (fun i -> + let level = Int32.of_int (Random.State.int rstate (1 lsl 29)) in + let shell_header = + Tezos_base.Block_header. + { + level; + proto_level = 1; + (* uint8 *) + predecessor = Tezos_crypto.Hashed.Block_hash.zero; + timestamp = Time.Protocol.epoch; + validation_passes = 3; + (* uint8 *) + operations_hash = + Tezos_crypto.Hashed.Operation_list_list_hash.zero; + fitness = []; + context = Tezos_crypto.Hashed.Context_hash.zero; + } + in + let now = Time.System.now () in + let* _ = + Baking_pow.mine + ~proof_of_work_threshold + shell_header + (fun proof_of_work_nonce -> + Protocol.Alpha_context. + { + Block_header.payload_hash = + Protocol.Block_payload_hash.zero; + payload_round = Round.zero; + seed_nonce_hash = None; + proof_of_work_nonce; + per_block_votes = + { + liquidity_baking_vote = Per_block_vote_pass; + adaptive_issuance_vote = Per_block_vote_pass; + }; + }) + in + let _then = Time.System.now () in + let x = Ptime.diff _then now in + let*! () = cctxt#message "%d/%d: %a" i nb_draw Ptime.Span.pp x in + return x) + (1 -- nb_draw) + in + let sum = List.fold_left Ptime.Span.add Ptime.Span.zero all in + let base, tail = Stdlib.List.(hd all, tl all) in + let max = + List.fold_left + (fun x y -> if Ptime.Span.compare x y > 0 then x else y) + base + tail + in + let min = + List.fold_left + (fun x y -> if Ptime.Span.compare x y <= 0 then x else y) + base + tail + in + let div = Ptime.Span.to_float_s sum /. float (List.length all) in + let*! () = + cctxt#message + "%d runs: min: %a, max: %a, average: %a" + nb_draw + Ptime.Span.pp + min + Ptime.Span.pp + max + (Format.pp_print_option Ptime.Span.pp) + (Ptime.Span.of_float_s div) + in + return_unit); + command + ~group + ~desc:"Forge and inject block using the delegates' rights." + (args13 + minimal_fees_arg + minimal_nanotez_per_gas_unit_arg + minimal_nanotez_per_byte_arg + minimal_timestamp_switch + force_apply_switch_arg + force_switch + operations_arg + context_path_arg + adaptive_issuance_vote_arg + do_not_monitor_node_mempool_arg + endpoint_arg + block_count_arg + state_recorder_switch_arg) + (prefixes ["bake"; "for"] @@ sources_param) + (fun ( minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + minimal_timestamp, + force_apply, + force, + extra_operations, + context_path, + adaptive_issuance_vote, + do_not_monitor_node_mempool, + dal_node_endpoint, + block_count, + state_recorder ) + pkhs + cctxt -> + let* delegates = get_delegates cctxt pkhs in + Baking_lib.bake + cctxt + ~minimal_nanotez_per_gas_unit + ~minimal_timestamp + ~minimal_nanotez_per_byte + ~minimal_fees + ~force_apply + ~force + ~monitor_node_mempool:(not do_not_monitor_node_mempool) + ?extra_operations + ?context_path + ?dal_node_endpoint + ~count:block_count + ?votes: + (Option.map + (fun adaptive_issuance_vote -> + { + Baking_configuration.default_votes_config with + adaptive_issuance_vote; + }) + adaptive_issuance_vote) + ~state_recorder + delegates); + command + ~group + ~desc:"Forge and inject an attestation operation." + (args1 attestation_force_switch_arg) + (prefixes ["attest"; "for"] @@ sources_param) + (fun force pkhs cctxt -> + let* delegates = get_delegates cctxt pkhs in + Baking_lib.attest ~force cctxt delegates); + command + ~group + ~desc: + "Deprecated, use **attest for** instead. Forge and inject an \ + attestation operation." + (args1 attestation_force_switch_arg) + (prefixes ["endorse"; "for"] @@ sources_param) + (fun force pkhs cctxt -> + let* delegates = get_delegates cctxt pkhs in + Baking_lib.attest ~force cctxt delegates); + command + ~group + ~desc:"Forge and inject a preattestation operation." + (args1 attestation_force_switch_arg) + (prefixes ["preattest"; "for"] @@ sources_param) + (fun force pkhs cctxt -> + let* delegates = get_delegates cctxt pkhs in + Baking_lib.preattest ~force cctxt delegates); + command + ~group + ~desc: + "Deprecated, use **preattest for** instead. Forge and inject a \ + preattestation operation." + (args1 attestation_force_switch_arg) + (prefixes ["preendorse"; "for"] @@ sources_param) + (fun force pkhs cctxt -> + let* delegates = get_delegates cctxt pkhs in + Baking_lib.preattest ~force cctxt delegates); + command + ~group + ~desc:"Send a Tenderbake proposal" + (args9 + minimal_fees_arg + minimal_nanotez_per_gas_unit_arg + minimal_nanotez_per_byte_arg + minimal_timestamp_switch + force_apply_switch_arg + force_switch + operations_arg + context_path_arg + state_recorder_switch_arg) + (prefixes ["propose"; "for"] @@ sources_param) + (fun ( minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + minimal_timestamp, + force_apply, + force, + extra_operations, + context_path, + state_recorder ) + sources + cctxt -> + let* delegates = get_delegates cctxt sources in + Baking_lib.propose + cctxt + ~minimal_nanotez_per_gas_unit + ~minimal_timestamp + ~minimal_nanotez_per_byte + ~minimal_fees + ~force_apply + ~force + ?extra_operations + ?context_path + ~state_recorder + delegates); + ] + +let directory_parameter = + let open Lwt_result_syntax in + Tezos_clic.parameter (fun _ p -> + let*! exists = Lwt_utils_unix.dir_exists p in + if not exists then failwith "Directory doesn't exist: '%s'" p + else return p) + +let per_block_vote_file_arg = + Tezos_clic.arg + ~doc:"read per block votes as json file" + ~short:'V' + ~long:"votefile" + ~placeholder:"filename" + (Tezos_clic.parameter (fun (_cctxt : Protocol_client_context.full) file -> + let open Lwt_result_syntax in + let* file_exists = + protect + ~on_error:(fun _ -> tzfail (Block_vote_file_not_found file)) + (fun () -> + let*! b = Lwt_unix.file_exists file in + return b) + in + if file_exists then return file + else tzfail (Block_vote_file_not_found file))) + +let pre_emptive_forge_time_arg = + Tezos_clic.arg + ~long:"pre-emptive-forge-time" + ~placeholder:"seconds" + ~doc: + "Sets the pre-emptive forge time optimization, in seconds. When set, the \ + baker, if it is the next level round 0 proposer, will start forging \ + after quorum has been reached in the current level while idly waiting \ + for it to end. When it is its time to propose, the baker will inject \ + the pre-emptively forged block immediately, allowing more time for the \ + network to reach quorum on it. Operators should note that the higher \ + this value `t`, the lower the operation inclusion window (specifically \ + `block_time - t`) which may lead to lower baking rewards. Defaults to \ + 15/% of block time. Set to 0 to ignore pre-emptive forging." + (Tezos_clic.parameter (fun _ s -> + try Lwt_result_syntax.return (Q.of_string s) + with _ -> failwith "pre-emptive-forge-time expected int or float.")) + +let lookup_default_vote_file_path (cctxt : Protocol_client_context.full) = + let open Lwt_syntax in + let default_filename = Per_block_vote_file.default_vote_json_filename in + let file_exists path = + Lwt.catch (fun () -> Lwt_unix.file_exists path) (fun _ -> return_false) + in + let when_s pred x g = + let* b = pred x in + if b then return_some x else g () + in + (* Check in current working directory *) + when_s file_exists default_filename @@ fun () -> + (* Check in the baker directory *) + let base_dir_file = Filename.Infix.(cctxt#get_base_dir // default_filename) in + when_s file_exists base_dir_file @@ fun () -> return_none + +type baking_mode = Local of {local_data_dir_path : string} | Remote + +let baker_args = + Tezos_clic.args13 + pidfile_arg + minimal_fees_arg + minimal_nanotez_per_gas_unit_arg + minimal_nanotez_per_byte_arg + force_apply_switch_arg + keep_alive_arg + liquidity_baking_toggle_vote_arg + adaptive_issuance_vote_arg + per_block_vote_file_arg + operations_arg + endpoint_arg + state_recorder_switch_arg + pre_emptive_forge_time_arg + +let run_baker + ( pidfile, + minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + force_apply, + keep_alive, + liquidity_baking_vote, + adaptive_issuance_vote, + per_block_vote_file, + extra_operations, + dal_node_endpoint, + state_recorder, + pre_emptive_forge_time ) baking_mode sources cctxt = + let open Lwt_result_syntax in + may_lock_pidfile pidfile @@ fun () -> + let*! per_block_vote_file = + if per_block_vote_file = None then + (* If the votes file was not explicitly given, we + look into default locations. *) + lookup_default_vote_file_path cctxt + else Lwt.return per_block_vote_file + in + (* We don't let the user run the baker without providing some + option (CLI, file path, or file in default location) for + the per-block votes. *) + let* votes = + Per_block_vote_file.load_per_block_votes_config + ~default_liquidity_baking_vote:liquidity_baking_vote + ~default_adaptive_issuance_vote:adaptive_issuance_vote + ~per_block_vote_file + in + let* delegates = get_delegates cctxt sources in + let context_path = + match baking_mode with + | Local {local_data_dir_path} -> + Some Filename.Infix.(local_data_dir_path // "context") + | Remote -> None + in + Client_daemon.Baker.run + cctxt + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + ~votes + ?extra_operations + ?dal_node_endpoint + ?pre_emptive_forge_time + ~force_apply + ~chain:cctxt#chain + ?context_path + ~keep_alive + ~state_recorder + delegates + +let baker_commands () : Protocol_client_context.full Tezos_clic.command list = + let open Tezos_clic in + let group = + { + Tezos_clic.name = "delegate.baker"; + title = "Commands related to the baker daemon."; + } + in + [ + command + ~group + ~desc:"Launch the baker daemon." + baker_args + (prefixes ["run"; "with"; "local"; "node"] + @@ param + ~name:"node_data_path" + ~desc:"Path to the node data directory (e.g. $HOME/.tezos-node)" + directory_parameter + @@ sources_param) + (fun args local_data_dir_path sources cctxt -> + let baking_mode = Local {local_data_dir_path} in + run_baker args baking_mode sources cctxt); + command + ~group + ~desc:"Launch the baker daemon using RPCs only." + baker_args + (prefixes ["run"; "remotely"] @@ sources_param) + (fun args sources cctxt -> + let baking_mode = Remote in + run_baker args baking_mode sources cctxt); + command + ~group + ~desc:"Launch the VDF daemon" + (args2 pidfile_arg keep_alive_arg) + (prefixes ["run"; "vdf"] @@ stop) + (fun (pidfile, keep_alive) cctxt -> + may_lock_pidfile pidfile @@ fun () -> + Client_daemon.VDF.run cctxt ~chain:cctxt#chain ~keep_alive); + ] + +let accuser_commands () = + let open Tezos_clic in + let group = + { + Tezos_clic.name = "delegate.accuser"; + title = "Commands related to the accuser daemon."; + } + in + [ + command + ~group + ~desc:"Launch the accuser daemon" + (args3 pidfile_arg Client_proto_args.preserved_levels_arg keep_alive_arg) + (prefixes ["run"] @@ stop) + (fun (pidfile, preserved_levels, keep_alive) cctxt -> + may_lock_pidfile pidfile @@ fun () -> + Client_daemon.Accuser.run + cctxt + ~chain:cctxt#chain + ~preserved_levels + ~keep_alive); + ] diff --git a/src/proto_020_PsParisC/lib_delegate/baking_commands.mli b/src/proto_020_PsParisC/lib_delegate/baking_commands.mli new file mode 100644 index 000000000000..02e2819da4b9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_commands.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val delegate_commands : + unit -> Protocol_client_context.full Tezos_clic.command list + +val baker_commands : + unit -> Protocol_client_context.full Tezos_clic.command list + +val accuser_commands : + unit -> Protocol_client_context.full Tezos_clic.command list diff --git a/src/proto_020_PsParisC/lib_delegate/baking_commands_registration.ml b/src/proto_020_PsParisC/lib_delegate/baking_commands_registration.ml new file mode 100644 index 000000000000..7a1b3cd90c68 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_commands_registration.ml @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let () = + Client_commands.register Protocol.hash @@ fun _network -> + List.map (Tezos_clic.map_command (new Protocol_client_context.wrap_full)) + @@ Baking_commands.delegate_commands () diff --git a/src/proto_020_PsParisC/lib_delegate/baking_configuration.ml b/src/proto_020_PsParisC/lib_delegate/baking_configuration.ml new file mode 100644 index 000000000000..60f1570fb218 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_configuration.ml @@ -0,0 +1,367 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Operations_source = struct + type t = + | Local of {filename : string} + | Remote of {uri : Uri.t; http_headers : (string * string) list option} + + let pp ppf = function + | Local {filename} -> Format.pp_print_string ppf filename + | Remote {uri; _} -> Format.fprintf ppf "%a" Uri.pp uri + + let encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + (Tag 1) + ~title:"Local" + (obj2 (req "filename" string) (req "kind" (constant "Local"))) + (function Local {filename} -> Some (filename, ()) | _ -> None) + (fun (filename, ()) -> Local {filename}); + case + (Tag 2) + ~title:"Remote" + (obj3 + (req "uri" string) + (opt "http_headers" (list (tup2 string string))) + (req "kind" (constant "Remote"))) + (function + | Remote {uri; http_headers} -> + Some (Uri.to_string uri, http_headers, ()) + | _ -> None) + (fun (uri_str, http_headers, ()) -> + Remote {uri = Uri.of_string uri_str; http_headers}); + ] +end + +open Protocol.Alpha_context + +type fees_config = { + minimal_fees : Tez.t; + minimal_nanotez_per_gas_unit : Q.t; + minimal_nanotez_per_byte : Q.t; +} + +type validation_config = + | Local of {context_path : string} + | Node + | ContextIndex of Abstract_context_index.t + +type nonce_config = Deterministic | Random + +type state_recorder_config = Filesystem | Memory + +type per_block_votes_config = { + vote_file : string option; + liquidity_baking_vote : Protocol.Alpha_context.Per_block_votes.per_block_vote; + adaptive_issuance_vote : Protocol.Alpha_context.Per_block_votes.per_block_vote; +} + +type t = { + fees : fees_config; + nonce : nonce_config; + validation : validation_config; + retries_on_failure : int; + user_activated_upgrades : (int32 * Protocol_hash.t) list; + per_block_votes : per_block_votes_config; + force_apply : bool; + force : bool; + state_recorder : state_recorder_config; + extra_operations : Operations_source.t option; + dal_node_endpoint : Uri.t option; + pre_emptive_forge_time : Time.System.Span.t; +} + +let default_fees_config = + { + minimal_fees = + (match Tez.of_mutez 100L with None -> assert false | Some t -> t); + minimal_nanotez_per_gas_unit = Q.of_int 100; + minimal_nanotez_per_byte = Q.of_int 1000; + } + +let default_validation_config = Node + +(* Unclear if determinist nonces, and more importantly, if + [supports_deterministic_nonces] is supported. *) +let default_nonce_config = Random + +let default_retries_on_failure_config = 5 + +let default_user_activated_upgrades = [] + +let default_votes_config = + { + vote_file = None; + liquidity_baking_vote = + Protocol.Alpha_context.Per_block_votes.Per_block_vote_pass; + adaptive_issuance_vote = + Protocol.Alpha_context.Per_block_votes.Per_block_vote_pass; + } + +let default_force = false + +let default_force_apply = false + +let default_state_recorder_config = Memory + +let default_extra_operations = None + +let default_pre_emptive_forge_time = Time.System.Span.of_seconds_exn 0. + +let default_config = + { + fees = default_fees_config; + nonce = default_nonce_config; + validation = default_validation_config; + retries_on_failure = default_retries_on_failure_config; + user_activated_upgrades = default_user_activated_upgrades; + per_block_votes = default_votes_config; + force_apply = default_force_apply; + force = default_force; + state_recorder = default_state_recorder_config; + extra_operations = default_extra_operations; + dal_node_endpoint = None; + pre_emptive_forge_time = default_pre_emptive_forge_time; + } + +let make ?(minimal_fees = default_fees_config.minimal_fees) + ?(minimal_nanotez_per_gas_unit = + default_fees_config.minimal_nanotez_per_gas_unit) + ?(minimal_nanotez_per_byte = default_fees_config.minimal_nanotez_per_byte) + ?(nonce = default_nonce_config) ?context_path + ?(retries_on_failure = default_retries_on_failure_config) + ?(user_activated_upgrades = default_user_activated_upgrades) + ?(votes = default_votes_config) ?(force_apply = default_force_apply) + ?(force = default_force) ?(state_recorder = default_state_recorder_config) + ?extra_operations ?dal_node_endpoint + ?(pre_emptive_forge_time = default_pre_emptive_forge_time) () = + let fees = + {minimal_fees; minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte} + in + let validation = + match context_path with + | None -> Node + | Some context_path -> Local {context_path} + in + { + fees; + validation; + nonce; + retries_on_failure; + user_activated_upgrades; + per_block_votes = votes; + force_apply; + force; + state_recorder; + extra_operations; + dal_node_endpoint; + pre_emptive_forge_time; + } + +let fees_config_encoding : fees_config Data_encoding.t = + let open Data_encoding in + let q_encoding = + conv (fun q -> Q.to_string q) (fun s -> Q.of_string s) string + in + conv + (fun {minimal_fees; minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte} -> + (minimal_fees, minimal_nanotez_per_gas_unit, minimal_nanotez_per_byte)) + (fun (minimal_fees, minimal_nanotez_per_gas_unit, minimal_nanotez_per_byte) -> + {minimal_fees; minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte}) + (obj3 + (req "minimal_fees" Tez.encoding) + (req "minimal_nanotez_per_gas_unit" q_encoding) + (req "minimal_nanotez_per_byte" q_encoding)) + +let validation_config_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Local" + (Tag 0) + (obj1 (req "local" string)) + (function Local {context_path} -> Some context_path | _ -> None) + (fun context_path -> Local {context_path}); + case + ~title:"Node" + (Tag 1) + (constant "node") + (function Node -> Some () | _ -> None) + (fun () -> Node); + ] + +let nonce_config_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Deterministic" + (Tag 0) + (constant "deterministic") + (function Deterministic -> Some () | _ -> None) + (fun () -> Deterministic); + case + ~title:"Random" + (Tag 1) + (constant "Random") + (function Random -> Some () | _ -> None) + (fun () -> Random); + ] + +let retries_on_failure_config_encoding = Data_encoding.int31 + +let user_activate_upgrades_config_encoding = + let open Data_encoding in + list (tup2 int32 Protocol_hash.encoding) + +let liquidity_baking_toggle_vote_config_encoding = + Protocol.Alpha_context.Per_block_votes.liquidity_baking_vote_encoding + +let adaptive_issuance_vote_config_encoding = + Protocol.Alpha_context.Per_block_votes.adaptive_issuance_vote_encoding + +let per_block_votes_config_encoding = + let open Data_encoding in + def (String.concat "." [Protocol.name; "per_block_votes_config"]) + @@ conv + (fun {vote_file; liquidity_baking_vote; adaptive_issuance_vote} -> + (vote_file, liquidity_baking_vote, adaptive_issuance_vote)) + (fun (vote_file, liquidity_baking_vote, adaptive_issuance_vote) -> + {vote_file; liquidity_baking_vote; adaptive_issuance_vote}) + (obj3 + (opt "per_block_vote_file" string) + (req + "liquidity_baking_vote" + liquidity_baking_toggle_vote_config_encoding) + (req "adaptive_issuance_vote" adaptive_issuance_vote_config_encoding)) + +let force_config_encoding = Data_encoding.bool + +let force_apply_config_encoding = Data_encoding.bool + +let state_recorder_config_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Filesystem" + (Tag 0) + (constant "filesystem") + (function Filesystem -> Some () | _ -> None) + (fun () -> Filesystem); + case + ~title:"Memory" + (Tag 1) + (constant "memory") + (function Memory -> Some () | _ -> None) + (fun () -> Memory); + ] + +let encoding : t Data_encoding.t = + let open Data_encoding in + def + (String.concat "." [Protocol.name; "baking_configuration"]) + ~title:"Baking configuration" + ~description:"Baking configuration" + @@ conv + (fun { + fees; + validation; + nonce; + retries_on_failure; + user_activated_upgrades; + per_block_votes; + force_apply; + force; + state_recorder; + extra_operations; + dal_node_endpoint; + pre_emptive_forge_time; + } -> + ( ( fees, + validation, + nonce, + retries_on_failure, + user_activated_upgrades, + per_block_votes, + force_apply, + force, + state_recorder, + pre_emptive_forge_time ), + (extra_operations, dal_node_endpoint) )) + (fun ( ( fees, + validation, + nonce, + retries_on_failure, + user_activated_upgrades, + per_block_votes, + force_apply, + force, + state_recorder, + pre_emptive_forge_time ), + (extra_operations, dal_node_endpoint) ) -> + { + fees; + validation; + nonce; + retries_on_failure; + user_activated_upgrades; + per_block_votes; + force_apply; + force; + state_recorder; + extra_operations; + dal_node_endpoint; + pre_emptive_forge_time; + }) + (merge_objs + (obj10 + (req "fees" fees_config_encoding) + (req "validation" validation_config_encoding) + (req "nonce" nonce_config_encoding) + (req "retries_on_failure" retries_on_failure_config_encoding) + (req + "user_activated_upgrades" + user_activate_upgrades_config_encoding) + (req "votes" per_block_votes_config_encoding) + (req "force_apply" force_apply_config_encoding) + (req "force" force_config_encoding) + (req "state_recorder" state_recorder_config_encoding) + (req "pre_emptive_forge_time" Time.System.Span.encoding)) + (obj2 + (opt "extra_operations" Operations_source.encoding) + (opt "dal_node_endpoint" Tezos_rpc.Encoding.uri_encoding))) + +let pp fmt t = + let json = Data_encoding.Json.construct encoding t in + Format.fprintf fmt "%a" Data_encoding.Json.pp json diff --git a/src/proto_020_PsParisC/lib_delegate/baking_configuration.mli b/src/proto_020_PsParisC/lib_delegate/baking_configuration.mli new file mode 100644 index 000000000000..d7345dacc9a2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_configuration.mli @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +(** {1 Operations_source abstraction} *) +module Operations_source : sig + type t = + | Local of {filename : string} + (** local mempool resource located in [filename] *) + | Remote of {uri : Uri.t; http_headers : (string * string) list option} + (** remote resource located a [uri], with additional [http_headers] + parameters *) + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +type fees_config = { + minimal_fees : Protocol.Alpha_context.Tez.t; + minimal_nanotez_per_gas_unit : Q.t; + minimal_nanotez_per_byte : Q.t; +} + +type validation_config = + | Local of {context_path : string} + | Node + | ContextIndex of Abstract_context_index.t + +type nonce_config = Deterministic | Random + +type state_recorder_config = Filesystem | Memory + +type per_block_votes_config = { + vote_file : string option; + liquidity_baking_vote : Protocol.Alpha_context.Per_block_votes.per_block_vote; + adaptive_issuance_vote : Protocol.Alpha_context.Per_block_votes.per_block_vote; +} + +type t = { + fees : fees_config; + nonce : nonce_config; + validation : validation_config; + retries_on_failure : int; + user_activated_upgrades : (int32 * Protocol_hash.t) list; + per_block_votes : per_block_votes_config; + force_apply : bool; + force : bool; + state_recorder : state_recorder_config; + extra_operations : Operations_source.t option; + dal_node_endpoint : Uri.t option; + pre_emptive_forge_time : Time.System.Span.t; +} + +val default_fees_config : fees_config + +val default_validation_config : validation_config + +val default_nonce_config : nonce_config + +val default_retries_on_failure_config : int + +val default_user_activated_upgrades : (int32 * Protocol_hash.t) list + +val default_votes_config : per_block_votes_config + +val default_force_apply : bool + +val default_force : bool + +val default_state_recorder_config : state_recorder_config + +val default_extra_operations : Operations_source.t option + +val default_pre_emptive_forge_time : Time.System.Span.t + +val default_config : t + +val make : + ?minimal_fees:Protocol.Alpha_context.Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?nonce:nonce_config -> + ?context_path:string -> + ?retries_on_failure:int -> + ?user_activated_upgrades:(int32 * Protocol_hash.t) list -> + ?votes:per_block_votes_config -> + ?force_apply:bool -> + ?force:bool -> + ?state_recorder:state_recorder_config -> + ?extra_operations:Operations_source.t -> + ?dal_node_endpoint:Uri.t -> + ?pre_emptive_forge_time:Time.System.Span.t -> + unit -> + t + +val fees_config_encoding : fees_config Data_encoding.t + +val validation_config_encoding : validation_config Data_encoding.t + +val nonce_config_encoding : nonce_config Data_encoding.t + +val retries_on_failure_config_encoding : int Data_encoding.t + +val user_activate_upgrades_config_encoding : + (int32 * Protocol_hash.t) list Data_encoding.t + +val liquidity_baking_toggle_vote_config_encoding : + Protocol.Alpha_context.Per_block_votes.per_block_vote Data_encoding.t + +val adaptive_issuance_vote_config_encoding : + Protocol.Alpha_context.Per_block_votes.per_block_vote Data_encoding.t + +val per_block_votes_config_encoding : per_block_votes_config Data_encoding.t + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit diff --git a/src/proto_020_PsParisC/lib_delegate/baking_errors.ml b/src/proto_020_PsParisC/lib_delegate/baking_errors.ml new file mode 100644 index 000000000000..537462a771e3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_errors.ml @@ -0,0 +1,251 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Node_connection_lost + +type error += Cannot_load_local_file of string + +type error += Broken_locked_values_invariant + +let register_error_kind category ~id ~title ~description ~pp encoding from_error + to_error = + Error_monad.register_error_kind + category + ~id:(String.concat "." ["baker"; Protocol.name; id]) + ~title + ~description + ~pp + encoding + from_error + to_error + +let () = + register_error_kind + `Temporary + ~id:"Baking_scheduling.node_connection_lost" + ~title:"Node connection lost" + ~description:"The connection with the node was lost." + ~pp:(fun fmt () -> Format.fprintf fmt "Lost connection with the node") + Data_encoding.empty + (function Node_connection_lost -> Some () | _ -> None) + (fun () -> Node_connection_lost) ; + register_error_kind + `Temporary + ~id:"Baking_scheduling.cannot_load_local_file" + ~title:"Cannot load local file" + ~description:"Cannot load local file." + ~pp:(fun fmt filename -> + Format.fprintf fmt "Cannot load the local file %s" filename) + Data_encoding.(obj1 (req "file" string)) + (function Cannot_load_local_file s -> Some s | _ -> None) + (fun s -> Cannot_load_local_file s) ; + register_error_kind + `Permanent + ~id:"Baking_state.broken_locked_values_invariant" + ~title:"Broken locked values invariant" + ~description: + "The expected consistency invariant on locked values does not hold" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The expected consistency invariant on locked values does not hold") + Data_encoding.unit + (function Broken_locked_values_invariant -> Some () | _ -> None) + (fun () -> Broken_locked_values_invariant) + +type error += Block_vote_file_not_found of string + +type error += Block_vote_file_invalid of string + +type error += Block_vote_file_wrong_content of string + +type error += Block_vote_file_missing_liquidity_baking_toggle_vote of string + +type error += Missing_vote_on_startup + +let () = + register_error_kind + `Permanent + ~id:"Per_block_vote_file.block_vote_file_not_found" + ~title: + "The provided block vote file path does not point to an existing file." + ~description: + "A block vote file path was provided on the command line but the path \ + does not point to an existing file." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "@[The provided block vote file path \"%s\" does not point to an \ + existing file.@]" + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function + | Block_vote_file_not_found file_path -> Some file_path | _ -> None) + (fun file_path -> Block_vote_file_not_found file_path) ; + register_error_kind + `Permanent + ~id:"Per_block_vote_file.block_vote_file_invalid" + ~title: + "The provided block vote file path does not point to a valid JSON file." + ~description: + "A block vote file path was provided on the command line but the path \ + does not point to a valid JSON file." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "@[The provided block vote file path \"%s\" does not point to a valid \ + JSON file. The file exists but its content is not valid JSON.@]" + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function Block_vote_file_invalid file_path -> Some file_path | _ -> None) + (fun file_path -> Block_vote_file_invalid file_path) ; + register_error_kind + `Permanent + ~id:"Per_block_vote_file.block_vote_file_wrong_content" + ~title:"The content of the provided block vote file is unexpected." + ~description: + "The block vote file is valid JSON but its content is not the expected \ + one." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "@[The provided block vote file \"%s\" is a valid JSON file but its \ + content is unexpected. Expecting a JSON file containing \ + '{\"liquidity_baking_toggle_vote\": value1, \ + \"adaptive_issuance_vote\": value2}' or '{\"adaptive_issuance_vote\": \ + value1, \"liquidity_baking_toggle_vote\": value2}', where value1 is \ + one of \"on\", \"off\", or \"pass\" and value2 is one of \"on\", \ + \"off\", or \"pass\", or '{\"liquidity_baking_toggle_vote\": value}' \ + where value is one of \"on\", \"off\", or \"pass\".@]" + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function + | Block_vote_file_wrong_content file_path -> Some file_path | _ -> None) + (fun file_path -> Block_vote_file_wrong_content file_path) ; + register_error_kind + `Permanent + ~id: + "Per_block_vote_file.block_vote_file_missing_liquidity_baking_toggle_vote" + ~title: + "In the provided block vote file, no entry for liquidity baking toggle \ + vote was found" + ~description: + "In the provided block vote file, no entry for liquidity baking toggle \ + vote was found." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "@[In the provided block vote file \"%s\", the \ + \"liquidity_baking_toggle_vote\" field is missing. Expecting a JSON \ + file containing '{\"liquidity_baking_toggle_vote\": value1, \ + \"adaptive_issuance_vote\": value2}' or '{\"adaptive_issuance_vote\": \ + value1, \"liquidity_baking_toggle_vote\": value2}', where value1 is \ + one of \"on\", \"off\", or \"pass\" and value2 is one of \"on\", \ + \"off\", or \"pass\", or '{\"liquidity_baking_toggle_vote\": value}' \ + where value is one of \"on\", \"off\", or \"pass\".@]" + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function + | Block_vote_file_missing_liquidity_baking_toggle_vote file_path -> + Some file_path + | _ -> None) + (fun file_path -> + Block_vote_file_missing_liquidity_baking_toggle_vote file_path) ; + register_error_kind + `Permanent + ~id:"Per_block_vote_file.missing_vote_on_startup" + ~title:"Missing vote on startup" + ~description: + "No CLI flag, file path, or votes file in default location provided on \ + startup" + ~pp:(fun fmt () -> + Format.fprintf + fmt + "Missing liquidity baking toggle vote, please use either the \ + --liquidity-baking-toggle-vote option, or the --votefile option or a \ + votes file in the default location: per_block_votes.json in the \ + current working directory or in the baker directory.") + Data_encoding.empty + (function Missing_vote_on_startup -> Some () | _ -> None) + (fun () -> Missing_vote_on_startup) + +type error += Failed_to_checkout_context + +type error += Invalid_context + +let () = + register_error_kind + `Permanent + ~id:"Client_baking_simulator.failed_to_checkout_context" + ~title:"Failed to checkout context" + ~description:"The given context hash does not exist in the context." + ~pp:(fun ppf () -> Format.fprintf ppf "Failed to checkout the context") + Data_encoding.unit + (function Failed_to_checkout_context -> Some () | _ -> None) + (fun () -> Failed_to_checkout_context) ; + register_error_kind + `Permanent + ~id:"Client_baking_simulator.invalid_context" + ~title:"Invalid context" + ~description:"Occurs when the context is inconsistent." + ~pp:(fun ppf () -> Format.fprintf ppf "The given context is invalid.") + Data_encoding.unit + (function Invalid_context -> Some () | _ -> None) + (fun () -> Invalid_context) + +type error += + | Unexpected_empty_block_list of { + chain : string; + block_hash : Block_hash.t; + length : int; + } + +let () = + register_error_kind + `Permanent + ~id:"Client_baking_blocks.unexpected_empty_block_list" + ~title:"Unexpected empty blocklist" + ~description: + "The block list retrieved by Shell_services.Blocks.list is empty" + ~pp:(fun ppf (chain, block_hash, length) -> + Format.fprintf + ppf + "Unexpected empty block list retrieved from chain %s at block %a, \ + length %d" + chain + Block_hash.pp + block_hash + length) + Data_encoding.( + obj3 + (req "chain" string) + (req "block_hash" Block_hash.encoding) + (req "length" int31)) + (function + | Unexpected_empty_block_list {chain; block_hash; length} -> + Some (chain, block_hash, length) + | _ -> None) + (fun (chain, block_hash, length) -> + Unexpected_empty_block_list {chain; block_hash; length}) diff --git a/src/proto_020_PsParisC/lib_delegate/baking_events.ml b/src/proto_020_PsParisC/lib_delegate/baking_events.ml new file mode 100644 index 000000000000..6a5cb7612c77 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_events.ml @@ -0,0 +1,1178 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let section = [Protocol.name; "baker"] + +let pp_int32 fmt n = Format.fprintf fmt "%ld" n + +let pp_int64 fmt n = Format.fprintf fmt "%Ld" n + +module State_transitions = struct + include Internal_event.Simple + + let section = section @ ["transitions"] + + let new_valid_proposal = + declare_3 + ~section + ~name:"new_valid_proposal" + ~level:Notice + ~msg:"received new proposal {block} at level {level}, round {round}" + ~pp1:Block_hash.pp + ("block", Block_hash.encoding) + ~pp2:pp_int32 + ("level", Data_encoding.int32) + ~pp3:Round.pp + ("round", Round.encoding) + + let new_head = + declare_3 + ~section + ~name:"new_head" + ~level:Notice + ~msg:"received new head {block} at level {level}, round {round}" + ~pp1:Block_hash.pp + ("block", Block_hash.encoding) + ~pp2:pp_int32 + ("level", Data_encoding.int32) + ~pp3:Round.pp + ("round", Round.encoding) + + let new_head_with_increasing_level = + declare_0 + ~section + ~name:"new_head_with_increasing_level" + ~level:Info + ~msg:"received new head with level increasing" + () + + let new_forge_event = + let open Baking_state in + declare_1 + ~section + ~name:"new_forge_event" + ~level:Notice + ~msg:"received new forge event: {event}" + ~pp1:pp_forge_event + ("event", forge_event_encoding) + + let no_proposal_slot = + declare_3 + ~section + ~name:"no_proposal_slot" + ~level:Info + ~msg: + "end of round {current_round}; no proposal slot at level {level}, \ + round {next_round}" + ~pp1:Round.pp + ("current_round", Round.encoding) + ~pp2:pp_int32 + ("level", Data_encoding.int32) + ~pp3:Round.pp + ("next_round", Round.encoding) + + let proposal_slot = + declare_4 + ~section + ~name:"proposal_slot" + ~level:Info + ~msg: + "end of round {current_round}; proposal slot at level {level}, round \ + {next_round} for {delegate}" + ~pp1:Round.pp + ("current_round", Round.encoding) + ~pp2:pp_int32 + ("level", Data_encoding.int32) + ~pp3:Round.pp + ("next_round", Round.encoding) + ~pp4:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let new_head_while_waiting_for_qc = + declare_0 + ~section + ~name:"new_head_while_waiting_for_qc" + ~level:Info + ~msg:"received new head while waiting for a quorum" + () + + let applied_expected_proposal_received = + declare_1 + ~section + ~name:"applied_expected_proposal_received" + ~level:Info + ~msg:"received the expected application notice for {proposal}" + ~pp1:Block_hash.pp + ("proposal", Block_hash.encoding) + + let unexpected_new_head_while_waiting_for_application = + declare_0 + ~section + ~name:"unexpected_new_head_while_waiting_for_application" + ~level:Info + ~msg:"received new head while waiting for another proposal's application" + () + + let new_valid_proposal_while_waiting_for_qc = + declare_0 + ~section + ~name:"new_valid_proposal_while_waiting_for_qc" + ~level:Info + ~msg:"received new valid proposal while waiting for a quorum" + () + + let valid_proposal_received_after_application = + declare_0 + ~section + ~name:"valid_proposal_received_after_application" + ~level:Info + ~msg:"received valid proposal for a block already applied" + () + + let unexpected_proposal_round = + declare_2 + ~section + ~name:"unexpected_proposal_round" + ~level:Info + ~msg: + "unexpected proposal round, expected: {expected_round}, got: \ + {proposal_round}" + ~pp1:Round.pp + ("expected_round", Round.encoding) + ~pp2:Round.pp + ("proposal_round", Round.encoding) + + let proposal_for_round_already_seen = + declare_3 + ~section + ~name:"proposal_for_round_already_seen" + ~level:Warning + ~msg: + "proposal {new_proposal} for current round ({current_round}) has \ + already been seen {previous_proposal}" + ~pp1:Block_hash.pp + ("new_proposal", Block_hash.encoding) + ~pp2:Round.pp + ("current_round", Round.encoding) + ~pp3:Block_hash.pp + ("previous_proposal", Block_hash.encoding) + + let updating_latest_proposal = + declare_1 + ~section + ~name:"updating_latest_proposal" + ~msg:"updating latest proposal to {block_hash}" + ~level:Info + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let baker_is_ahead_of_node = + declare_2 + ~section + ~name:"baker_is_ahead" + ~level:Info + ~msg: + "baker (level: {baker_level}) is ahead of the node (level: \ + {node_level})" + ~pp1:pp_int32 + ("baker_level", Data_encoding.int32) + ~pp2:pp_int32 + ("node_level", Data_encoding.int32) + + let new_proposal_is_on_another_branch = + declare_2 + ~section + ~name:"new_proposal_is_on_another_branch" + ~level:Info + ~msg: + "received a proposal on another branch - current: current \ + pred{current_branch}, new pred {new_branch}" + ~pp1:Block_hash.pp + ("current_branch", Block_hash.encoding) + ~pp2:Block_hash.pp + ("new_branch", Block_hash.encoding) + + let switching_branch = + declare_0 + ~section + ~name:"switching_branch" + ~level:Info + ~msg:"switching branch" + () + + let branch_proposal_has_better_fitness = + declare_0 + ~section + ~name:"branch_proposal_has_better_fitness" + ~level:Info + ~msg:"different branch proposal has a better fitness than us" + () + + let branch_proposal_has_no_prequorum = + declare_0 + ~section + ~name:"branch_proposal_has_no_prequorum" + ~level:Info + ~msg:"different branch proposal has no prequorum but we do" + () + + let branch_proposal_has_lower_prequorum = + declare_0 + ~section + ~name:"branch_proposal_has_lower_prequorum" + ~level:Info + ~msg:"different branch proposal has a lower prequorum than us" + () + + let branch_proposal_has_better_prequorum = + declare_0 + ~section + ~name:"branch_proposal_has_better_prequorum" + ~level:Info + ~msg:"different branch proposal has a better prequorum" + () + + let branch_proposal_has_same_prequorum = + declare_0 + ~section + ~name:"branch_proposal_has_same_prequorum" + ~level:Error + ~msg:"different branch proposal has the same prequorum" + () + + let attempting_preattest_proposal = + declare_1 + ~section + ~name:"attempting_preattest_proposal" + ~level:Info + ~msg:"attempting to preattest proposal {block_hash}" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let attempting_vote_proposal = + declare_1 + ~section + ~name:"attempting_vote_proposal" + ~level:Info + ~msg:"attempting to vote for proposal {block_hash}" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let skipping_invalid_proposal = + declare_0 + ~section + ~name:"skipping_invalid_proposal" + ~level:Info + ~msg:"invalid proposal, skipping" + () + + let outdated_proposal = + declare_1 + ~section + ~name:"outdated_proposal" + ~level:Debug + ~msg:"outdated proposal {block_hash}" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let preparing_fresh_block = + declare_2 + ~section + ~name:"preparing_fresh_block" + ~level:Info + ~msg:"preparing fresh block for {delegate} at round {round}" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:Round.pp + ("round", Round.encoding) + + let no_attestable_payload_fresh_block = + declare_0 + ~section + ~name:"no_attestable_payload_fresh_block" + ~level:Info + ~msg:"no attestable payload, proposing fresh block" + () + + let repropose_block = + declare_1 + ~section + ~name:"repropose_block" + ~level:Info + ~msg:"repropose block with payload {payload}" + ~pp1:Block_payload_hash.pp + ("payload", Block_payload_hash.encoding) + + let unexpected_prequorum_received = + declare_2 + ~section + ~name:"unexpected_prequorum_received" + ~level:Info + ~msg: + "unexpected prequorum received for {received_hash} instead of \ + {expected_hash}" + ~pp1:Block_hash.pp + ("received_hash", Block_hash.encoding) + ~pp2:Block_hash.pp + ("expected_hash", Block_hash.encoding) + + let unexpected_quorum_received = + declare_2 + ~section + ~name:"unexpected_quorum_received" + ~level:Info + ~msg: + "unexpected quorum received for {received_hash} instead of \ + {expected_hash}" + ~pp1:Block_hash.pp + ("received_hash", Block_hash.encoding) + ~pp2:Block_hash.pp + ("expected_hash", Block_hash.encoding) + + let step_current_phase = + declare_2 + ~section + ~name:"step_current_phase" + ~level:Debug + ~msg:"automaton step: current phase {phase}, event {event}" + ~pp1:Baking_state.pp_phase + ("phase", Baking_state.phase_encoding) + ~pp2:Baking_state.pp_event + ("event", Baking_state.event_encoding) + + let discarding_attestation = + declare_3 + ~section + ~name:"discarding_attestation" + ~level:Info + ~msg: + "discarding outdated attestation for {delegate} at level {level}, \ + round {round}" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:pp_int32 + ("level", Data_encoding.int32) + ~pp3:Round.pp + ("round", Round.encoding) +end + +module Node_rpc = struct + include Internal_event.Simple + + let section = section @ ["rpc"] + + let error_while_monitoring_heads = + declare_1 + ~section + ~name:"error_while_monitoring_heads" + ~level:Error + ~msg:"error while monitoring heads {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let error_while_monitoring_valid_proposals = + declare_1 + ~section + ~name:"error_while_monitoring_valid_proposals" + ~level:Error + ~msg:"error while monitoring valid proposals {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) +end + +module Scheduling = struct + include Internal_event.Simple + + let section = section @ ["scheduling"] + + let error_while_baking = + declare_1 + ~section + ~name:"error_while_baking" + ~level:Warning + ~msg:"error while baking {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let waiting_for_new_head = + declare_0 + ~section + ~name:"waiting_for_new_head" + ~level:Info + ~msg:"no possible timeout, waiting for a new head to arrive..." + () + + let compute_next_timeout_elected_block = + declare_2 + ~section + ~name:"compute_next_timeout_elected_block" + ~level:Debug + ~msg: + "found an elected block at level {level}, round {round}... checking \ + baking rights" + ~pp1:pp_int32 + ("level", Data_encoding.int32) + ~pp2:Round.pp + ("round", Round.encoding) + + let proposal_already_injected = + declare_0 + ~section + ~name:"proposal_already_injected" + ~level:Debug + ~msg:"proposal already injected for next level, skipping..." + () + + let next_potential_slot = + declare_4 + ~section + ~name:"next_potential_slot" + ~level:Info + ~msg: + "next potential slot for level {level} is at round {round} at \ + {timestamp} for {delegate}" + ~pp1:pp_int32 + ("level", Data_encoding.int32) + ~pp2:Round.pp + ("round", Round.encoding) + ~pp3:Timestamp.pp + ("timestamp", Timestamp.encoding) + ~pp4:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let waiting_end_of_round = + declare_3 + ~section + ~name:"waiting_end_of_round" + ~level:Info + ~msg:"waiting {timespan} until end of round {round} at {timestamp}" + ~pp1:Ptime.Span.pp + ("timespan", Time.System.Span.encoding) + ~pp2:pp_int32 + ("round", Data_encoding.int32) + ~pp3:Timestamp.pp + ("timestamp", Timestamp.encoding) + + let waiting_delayed_end_of_round = + declare_4 + ~section + ~name:"waiting_delayed_end_of_round" + ~level:Info + ~msg: + "waiting {timespan} until {timestamp} (end of round {round} plus \ + {delay}s delay)" + ~pp1:Ptime.Span.pp + ("timespan", Time.System.Span.encoding) + ~pp2:pp_int32 + ("round", Data_encoding.int32) + ~pp3:Timestamp.pp + ("timestamp", Timestamp.encoding) + ~pp4:pp_int64 + ("delay", Data_encoding.int64) + + let waiting_time_to_bake = + declare_2 + ~section + ~name:"waiting_time_to_bake" + ~level:Info + ~msg:"waiting {timespan} until it's time to bake at {timestamp}" + ~pp1:Ptime.Span.pp + ("timespan", Time.System.Span.encoding) + ~pp2:Timestamp.pp + ("timestamp", Timestamp.encoding) + + let no_need_to_wait_for_proposal = + declare_0 + ~section + ~name:"no_need_to_wait_for_proposal" + ~level:Info + ~msg:"no need to wait to propose a block" + () + + let state_synchronized_to_round = + declare_1 + ~section + ~name:"state_synchronized_to_round" + ~level:Debug + ~msg:"state synchronized to round {round}" + ~pp1:Round.pp + ("round", Round.encoding) + + let proposal_in_the_future = + declare_1 + ~section + ~name:"proposal_in_the_future" + ~level:Debug + ~msg:"received proposal in the future {block_hash}" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let process_proposal_in_the_future = + declare_1 + ~section + ~name:"process_proposal_in_the_future" + ~level:Debug + ~msg:"process proposal received in the future with hash {block_hash}" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let waiting_to_forge_block = + declare_2 + ~section + ~name:"waiting_to_forge_block" + ~level:Info + ~msg:"waiting {timespan} until it's time to forge block at {timestamp}" + ~pp1:Ptime.Span.pp + ("timespan", Time.System.Span.encoding) + ~pp2:Timestamp.pp + ("timestamp", Timestamp.encoding) + + let no_need_to_wait_to_forge_block = + declare_0 + ~section + ~name:"no_need_to_wait_to_forge_block" + ~level:Info + ~msg:"no need to wait to forge a block" + () + + let first_baker_of_next_level = + declare_0 + ~section + ~name:"first_baker_of_next_level" + ~level:Info + ~msg: + "first baker of next level found among delegates. pre-emptively \ + forging block." + () +end + +module Lib = struct + include Internal_event.Simple + + let section = section @ ["lib"] + + let attempting_to_vote_for_proposal = + declare_2 + ~section + ~name:"attempting_preattest_proposal" + ~level:Debug + ~msg:"attempting to {action} proposal {proposal}" + ("action", Baking_state.consensus_vote_kind_encoding) + ~pp1: + (fun fmt -> function + | Baking_state.Preattestation -> Format.fprintf fmt "preattest" + | Attestation -> Format.fprintf fmt "attest") + ("proposal", Baking_state.proposal_encoding) + ~pp2:Baking_state.pp_proposal +end + +module Actions = struct + include Internal_event.Simple + + let section = section @ ["actions"] + + let skipping_consensus_vote = + declare_5 + ~section + ~name:"skipping_consensus_vote" + ~level:Error + ~msg: + "unable to sign {vote_kind} for {delegate} at level {level}, round \ + {round} -- {trace}" + ~pp1:Baking_state.pp_consensus_vote_kind + ("vote_kind", Baking_state.consensus_vote_kind_encoding) + ~pp2:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp3:pp_int32 + ("level", Data_encoding.int32) + ~pp4:Round.pp + ("round", Round.encoding) + ~pp5:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let failed_to_get_dal_attestations = + declare_2 + ~section + ~name:"failed_to_get_attestations" + ~level:Error + ~msg:"unable to get DAL attestation for {delegate} -- {trace}" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let failed_to_get_dal_attestations_in_time = + declare_2 + ~section + ~name:"failed_to_get_attestations_in_time" + ~level:Error + ~msg: + "unable to get DAL attestation for {delegate} within the {timeout}s \ + timeout" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:Format.pp_print_float + ("timeout", Data_encoding.float) + + let failed_to_inject_consensus_vote = + declare_3 + ~section + ~name:"failed_to_inject_consensus_vote" + ~level:Error + ~msg:"failed to inject {vote_kind} for {delegate} -- {trace}" + ~pp1:Baking_state.pp_consensus_vote_kind + ("vote_kind", Baking_state.consensus_vote_kind_encoding) + ~pp2:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp3:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let failed_to_forge_block = + declare_2 + ~section + ~name:"failed_to_forge_block" + ~level:Error + ~msg:"failed to forge block for {delegate} -- {trace}" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let potential_double_baking = + declare_2 + ~section + ~name:"potential_double_baking" + ~level:Warning + ~msg:"potential double baking detected at level {level}, round {round}" + ~pp1:pp_int32 + ~pp2:Round.pp + ("level", Data_encoding.int32) + ("round", Round.encoding) + + let consensus_vote_injected = + declare_5 + ~section + ~name:"consensus_vote_injected" + ~level:Notice + ~msg: + "injected {vote_kind} {ophash} for {delegate} for level {level}, round \ + {round}" + ~pp1:Baking_state.pp_consensus_vote_kind + ("vote_kind", Baking_state.consensus_vote_kind_encoding) + ~pp2:Operation_hash.pp + ("ophash", Operation_hash.encoding) + ~pp3:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp4:pp_int32 + ("level", Data_encoding.int32) + ~pp5:Round.pp + ("round", Round.encoding) + + let attach_dal_attestation = + declare_5 + ~section + ~name:"attach_dal_attestation" + ~level:Notice + ~msg: + "ready to attach DAL attestation for level {attestation_level}, round \ + {round}, with bitset {bitset} for {delegate} to attest slots \ + published at level {published_level}" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:Z.pp_print + ("bitset", Data_encoding.n) + ("published_level", Data_encoding.int32) + ("attestation_level", Data_encoding.int32) + ("round", Round.encoding) + + let synchronizing_round = + declare_1 + ~section + ~name:"synchronizing_round" + ~level:Info + ~msg:"synchronizing round after block {block}" + ~pp1:Block_hash.pp + ("block", Block_hash.encoding) + + let prepare_forging_block = + declare_3 + ~section + ~name:"prepare_forging_block" + ~level:Debug + ~msg: + "prepare forging block at level {level}, round {round} for {delegate}" + ~pp1:pp_int32 + ~pp2:Round.pp + ~pp3:Baking_state.pp_consensus_key_and_delegate + ("level", Data_encoding.int32) + ("round", Round.encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let forging_block = + declare_3 + ~section + ~name:"forging_block" + ~level:Info + ~msg:"forging block at level {level}, round {round} for {delegate}" + ~pp1:pp_int32 + ~pp2:Round.pp + ~pp3:Baking_state.pp_consensus_key_and_delegate + ("level", Data_encoding.int32) + ("round", Round.encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let delayed_block_injection = + declare_4 + ~section + ~name:"delayed_block_injection" + ~level:Debug + ~msg: + "waiting {delay} before injecting block at level {level}, round \ + {round} for {delegate}" + ("delay", Time.System.Span.encoding) + ~pp1:Time.System.Span.pp_hum + ("level", Data_encoding.int32) + ~pp2:pp_int32 + ("round", Round.encoding) + ~pp3:Round.pp + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp4:Baking_state.pp_consensus_key_and_delegate + + let injecting_block = + declare_3 + ~section + ~name:"injecting_block" + ~level:Debug + ~msg:"injecting block at level {level}, round {round} for {delegate}" + ~pp1:pp_int32 + ~pp2:Round.pp + ~pp3:Baking_state.pp_consensus_key_and_delegate + ("level", Data_encoding.int32) + ("round", Round.encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let block_injected = + declare_4 + ~section + ~name:"block_injected" + ~level:Notice + ~msg: + "block {block} at level {level}, round {round} injected for {delegate}" + ~pp1:Block_hash.pp + ~pp2:pp_int32 + ~pp3:Round.pp + ~pp4:Baking_state.pp_consensus_key_and_delegate + ("block", Block_hash.encoding) + ("level", Data_encoding.int32) + ("round", Round.encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let block_injection_failed = + declare_2 + ~section + ~name:"block_injection_failed" + ~level:Error + ~msg:"failed to inject block {block_hash} -- {trace}" + ("block_hash", Block_hash.encoding) + ~pp1:Block_hash.pp + ("trace", Error_monad.trace_encoding) + ~pp2:Error_monad.pp_print_trace + + let signing_consensus_vote = + declare_2 + ~section + ~name:"signing_consensus_vote" + ~level:Info + ~msg:"signing {vote_kind} for {delegate}" + ~pp1:Baking_state.pp_consensus_vote_kind + ("vote_kind", Baking_state.consensus_vote_kind_encoding) + ~pp2:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + + let invalid_json_file = + declare_1 + ~section + ~name:"invalid_json_file" + ~level:Warning + ~msg:"{filename} is not a valid JSON file" + ("filename", Data_encoding.string) + + let no_operations_found_in_file = + declare_1 + ~section + ~name:"no_operations_found_in_file" + ~level:Warning + ~msg:"no operations found in file {filename}" + ("filename", Data_encoding.string) + + let cannot_fetch_operations = + declare_1 + ~section + ~name:"cannot_fetch_operations" + ~level:Error + ~msg:"cannot fetch operations: {errs}" + ("errs", Error_monad.(TzTrace.encoding error_encoding)) + + let vote_for_liquidity_baking_toggle = + declare_1 + ~section + ~name:"vote_for_liquidity_baking_toggle" + ~level:Notice + ~msg:"Voting {value} for liquidity baking toggle vote" + ( "value", + Protocol.Alpha_context.Per_block_votes.liquidity_baking_vote_encoding ) + + let vote_for_adaptive_issuance = + declare_1 + ~section + ~name:"vote_for_adaptive_issuance" + ~level:Notice + ~msg:"Voting {value} for adaptive issuance vote" + ( "value", + Protocol.Alpha_context.Per_block_votes.adaptive_issuance_vote_encoding + ) + + let no_dal_node = + declare_0 + ~section + ~name:"no_dal_node" + ~level:Notice + ~msg: + "DAL feature enabled, but no DAL node specified: cannot fetch \ + attestations" + () +end + +module VDF = struct + include Internal_event.Simple + + let section = section @ ["vdf"] + + let vdf_revelation_injected = + declare_3 + ~section + ~name:"vdf_revelation_injected" + ~level:Notice + ~msg: + "Injected VDF revelation for cycle {cycle} (chain {chain} with \ + operation {ophash})" + ~pp1:pp_int32 + ("cycle", Data_encoding.int32) + ~pp2:Format.pp_print_string + ("chain", Data_encoding.string) + ~pp3:Operation_hash.pp + ("ophash", Operation_hash.encoding) + + let vdf_daemon_error = + declare_2 + ~section + ~name:"vdf_daemon_error" + ~level:Error + ~msg:"{worker}: error while running VDF daemon: {errors}" + ~pp1:Format.pp_print_string + ("worker", Data_encoding.string) + ~pp2:pp_print_top_error_of_trace + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + + let vdf_daemon_connection_lost = + declare_1 + ~section + ~name:"vdf_daemon_connection_lost" + ~level:Error + ~msg:"Connection to node lost, VDF daemon {worker} exiting" + ~pp1:Format.pp_print_string + ("worker", Data_encoding.string) + + let vdf_daemon_cannot_kill_computation = + declare_1 + ~section + ~name:"vdf_daemon_cannot_kill_computation" + ~level:Error + ~msg:"Error when killining running computation: {error}" + ~pp1:Format.pp_print_string + ("error", Data_encoding.string) + + let vdf_info = + declare_1 + ~section + ~name:"vdf_internal" + ~level:Notice + ~msg:"{msg}" + ~pp1:Format.pp_print_string + ("msg", Data_encoding.string) +end + +module Nonces = struct + include Internal_event.Simple + + let section = section @ ["nonces"] + + let found_nonce_to_reveal = + declare_2 + ~section + ~name:"found_nonce_to_reveal" + ~level:Notice + ~msg:"found nonce to reveal for block {block}, level {level}" + ~pp1:Block_hash.pp + ("block", Block_hash.encoding) + ~pp2:Raw_level.pp + ("level", Raw_level.encoding) + + let revealing_nonce = + declare_3 + ~section + ~name:"revealing_nonce" + ~level:Notice + ~msg: + "revealing nonce of level {level} (chain {chain} with operation \ + {ophash})" + ~pp1:pp_int32 + ("level", Data_encoding.int32) + ~pp2:Format.pp_print_string + ("chain", Data_encoding.string) + ~pp3:Operation_hash.pp + ("ophash", Operation_hash.encoding) + + let cannot_fetch_chain_head_level = + declare_0 + ~section + ~name:"cannot_fetch_chain_head_level" + ~level:Error + ~msg:"cannot fetch chain head level, aborting nonces filtering" + () + + let incoherent_nonce = + declare_1 + ~section + ~name:"incoherent_nonce" + ~level:Error + ~msg:"incoherent nonce for level {level}" + ~pp1:(fun fmt -> Format.fprintf fmt "%a" Raw_level.pp) + ("level", Raw_level.encoding) + + let cannot_read_nonces = + declare_1 + ~section + ~name:"cannot_read_nonces" + ~level:Error + ~msg:"cannot read nonces {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let cannot_retrieve_unrevealed_nonces = + declare_1 + ~section + ~name:"cannot_retrieve_unrevealed_nonces" + ~level:Error + ~msg:"cannot retrieve unrevealed nonces {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let cannot_inject_nonces = + declare_1 + ~section + ~name:"cannot_inject_nonces" + ~level:Error + ~msg:"cannot inject nonces {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let cant_retrieve_block_header_for_nonce = + declare_2 + ~section + ~name:"cant_retrieve_block_header_for_nonce" + ~level:Warning + ~msg:"cannot retrieve block header {header} associated with nonce {trace}" + ("header", Data_encoding.string) + ~pp2:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let registering_nonce = + declare_1 + ~section + ~name:"registering_nonce" + ~level:Info + ~msg:"registering nonce for block {block}" + ~pp1:Block_hash.pp + ("block", Block_hash.encoding) + + let nothing_to_reveal = + declare_1 + ~section + ~name:"nothing_to_reveal" + ~level:Info + ~msg:"nothing to reveal for block {block}" + ~pp1:Block_hash.pp + ("block", Block_hash.encoding) + + let revelation_worker_started = + declare_0 + ~section + ~name:"revelation_worker_started" + ~level:Info + ~msg:"revelation worker started" + () + + let success_migrate_nonces = + declare_0 + ~section + ~name:"success_migrate_nonces" + ~level:Notice + ~msg:"successfully migrated nonces: legacy nonces are safe to delete" + () + + let ignore_failed_nonce_migration = + declare_1 + ~section + ~name:"ignore_failed_nonce_migration" + ~level:Warning + ~msg: + "There is not enough block history to complete the migration. Try \ + starting from an older snapshot or providing more block history. The \ + nonces from the following blocks will not be migrated:\n\ + {failed} " + ~pp1:(Format.pp_print_list Block_hash.pp) + ("failed", Data_encoding.list Block_hash.encoding) + + let outdated_nonce = + declare_1 + ~section + ~name:"outdated_nonce" + ~level:Info + ~msg:"outdated nonce for block {block_hash} is safe to delete" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let unexpected_nonce = + declare_1 + ~section + ~name:"unexpected_nonce" + ~level:Info + ~msg:"unexpected nonce for block {block_hash} is safe to delete" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) + + let revealed_nonce = + declare_1 + ~section + ~name:"revealed_nonce" + ~level:Info + ~msg:"revealed nonce for block {block_hash} is safe to delete" + ~pp1:Block_hash.pp + ("block_hash", Block_hash.encoding) +end + +module Per_block_votes = struct + include Internal_event.Simple + + let reading_per_block_votes = + declare_1 + ~section + ~name:"reading_per_block_votes" + ~level:Notice + ~msg:"reading votes file: {path}" + ("path", Data_encoding.string) + + let liquidity_baking_toggle_vote = + declare_1 + ~section + ~name:"read_liquidity_baking_toggle_vote" + ~level:Notice + ~msg:"read liquidity baking toggle vote = {value}" + ( "value", + Protocol.Alpha_context.Per_block_votes.liquidity_baking_vote_encoding ) + + let per_block_vote_file_fail = + declare_1 + ~section + ~name:"per_block_vote_file_error" + ~level:Error + ~msg:"Error reading the block vote file: {errors}" + ~pp1:pp_print_top_error_of_trace + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + + let adaptive_issuance_vote = + declare_1 + ~section + ~name:"read_adaptive_issuance_vote" + ~level:Notice + ~msg:"read adaptive issuance vote = {value}" + ( "value", + Protocol.Alpha_context.Per_block_votes.adaptive_issuance_vote_encoding + ) +end + +module Selection = struct + include Internal_event.Simple + + let section = section @ ["operation_selection"] + + let invalid_operation_filtered = + declare_2 + ~section + ~name:"invalid_operation_filtered" + ~level:Warning + ~msg:"filtered invalid operation {op}: {errors}" + ~pp1:Operation_hash.pp + ("op", Operation_hash.encoding) + ~pp2:pp_print_top_error_of_trace + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + + let cannot_serialize_operation_metadata = + declare_1 + ~section + ~name:"cannot_serialize_operation_metadata" + ~level:Warning + ~msg:"cannot serialize operation {op} metadata" + ~pp1:Operation_hash.pp + ("op", Operation_hash.encoding) +end + +module Forge_worker = struct + include Internal_event.Simple + + let section = section @ ["forge_worker"] + + let error_while_processing_forge_request = + declare_1 + ~section + ~name:"error_while_processing_forge_request" + ~level:Warning + ~msg:"error while processing forge request: {errors}" + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + ~pp1:pp_print_top_error_of_trace + + let error_while_authorizing_consensus_votes = + declare_1 + ~section + ~name:"error_while_authorizing_consensus_votes" + ~level:Error + ~msg:"error while authorizing consensus votes: {errors}" + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + ~pp1:pp_print_top_error_of_trace +end diff --git a/src/proto_020_PsParisC/lib_delegate/baking_files.ml b/src/proto_020_PsParisC/lib_delegate/baking_files.ml new file mode 100644 index 000000000000..8b27b6668f89 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_files.ml @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type _ location = string + +type nonce_types = [`Legacy_nonce | `Stateful_nonce | `Orphaned_nonce] + +let resolve_location ~chain_id (kind : 'a) : 'a location = + let basename = + match kind with + | `Highwatermarks -> "highwatermark" + | `State -> "baker_state" + | `Legacy_nonce -> "nonce" + | `Stateful_nonce -> "stateful_nonce" + | `Orphaned_nonce -> "orphaned_nonce" + in + Format.asprintf "%a_%s" Chain_id.pp_short chain_id basename + +let filename x = x diff --git a/src/proto_020_PsParisC/lib_delegate/baking_files.mli b/src/proto_020_PsParisC/lib_delegate/baking_files.mli new file mode 100644 index 000000000000..ce58b7e66d2c --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_files.mli @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type _ location + +type nonce_types = [`Legacy_nonce | `Stateful_nonce | `Orphaned_nonce] + +val resolve_location : + chain_id:Chain_id.t -> + ([< `Highwatermarks | `State | nonce_types] as 'kind) -> + 'kind location + +val filename : [< `Highwatermarks | `State | nonce_types] location -> string diff --git a/src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.ml b/src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.ml new file mode 100644 index 000000000000..e9227a5d6f1a --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.ml @@ -0,0 +1,264 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol.Alpha_context + +type highwatermark = {round : Round.t; level : int32} + +let highwatermark_encoding : highwatermark Data_encoding.t = + let open Data_encoding in + conv + (fun {round; level} -> (round, level)) + (fun (round, level) -> {round; level}) + (obj2 + (req "round" Protocol.Alpha_context.Round.encoding) + (req "level" int32)) + +let pp_highwatermark fmt {round; level} = + Format.fprintf fmt "level: %ld, round: %a" level Round.pp round + +type error += Block_previously_baked of highwatermark + +type error += Block_previously_preattested of highwatermark + +type error += Block_previously_attested of highwatermark + +let () = + register_error_kind + `Permanent + ~id:"highwatermarks.block_previously_baked" + ~title:"Block previously baked" + ~description:"Trying to bake a block at a level previously baked" + ~pp:(fun ppf highwatermark -> + Format.fprintf + ppf + "A block with a higher watermark than the current one (%a) was \ + previously baked." + pp_highwatermark + highwatermark) + highwatermark_encoding + (function + | Block_previously_baked highwatermark -> Some highwatermark | _ -> None) + (fun highwatermark -> Block_previously_baked highwatermark) ; + register_error_kind + `Permanent + ~id:"highwatermarks.block_previously_preattested" + ~title:"Block previously preattested" + ~description:"Trying to preattest a block at a level previously preattested" + ~pp:(fun ppf highwatermark -> + Format.fprintf + ppf + "A preattestation with a higher watermark than the current one (%a) \ + was already produced." + pp_highwatermark + highwatermark) + highwatermark_encoding + (function + | Block_previously_preattested highwatermark -> Some highwatermark + | _ -> None) + (fun highwatermark -> Block_previously_preattested highwatermark) ; + register_error_kind + `Permanent + ~id:"highwatermarks.block_previously_attested" + ~title:"Block previously attested" + ~description:"Trying to attest a block at a level previously attested" + ~pp:(fun ppf highwatermark -> + Format.fprintf + ppf + "An attestation with a higher watermark than the current one (%a) was \ + already produced." + pp_highwatermark + highwatermark) + highwatermark_encoding + (function + | Block_previously_attested highwatermark -> Some highwatermark + | _ -> None) + (fun highwatermark -> Block_previously_attested highwatermark) + +module DelegateMap = Map.Make (struct + type t = Signature.Public_key_hash.t + + let compare = Signature.Public_key_hash.compare +end) + +let highwatermark_delegate_map_encoding = + let open Data_encoding in + conv + DelegateMap.bindings + DelegateMap.( + fun l -> List.fold_left (fun map (k, v) -> add k v map) empty l) + (list + (obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "highwatermark" highwatermark_encoding))) + +type highwatermarks = { + blocks : highwatermark DelegateMap.t; + preattestations : highwatermark DelegateMap.t; + attestations : highwatermark DelegateMap.t; +} + +type t = highwatermarks + +let encoding = + let open Data_encoding in + conv + (fun {blocks; preattestations; attestations} -> + (blocks, preattestations, attestations)) + (fun (blocks, preattestations, attestations) -> + {blocks; preattestations; attestations}) + (obj3 + (req "blocks" highwatermark_delegate_map_encoding) + (req "preattestations" highwatermark_delegate_map_encoding) + (req "attestations" highwatermark_delegate_map_encoding)) + +let empty = + { + blocks = DelegateMap.empty; + preattestations = DelegateMap.empty; + attestations = DelegateMap.empty; + } + +(* We do not lock these functions. The caller will be already locked. *) +let load (cctxt : #Protocol_client_context.full) location : t tzresult Lwt.t = + protect (fun () -> + cctxt#load (Baking_files.filename location) encoding ~default:empty) + +let save_highwatermarks (cctxt : #Protocol_client_context.full) filename + highwatermarks : unit tzresult Lwt.t = + protect (fun () -> + (* TODO: improve the backend so we don't write partial informations *) + cctxt#write filename highwatermarks encoding) + +let may_sign highwatermarks ~delegate ~level ~round = + match DelegateMap.find delegate highwatermarks with + | None -> true + | Some highwatermark -> + if Compare.Int32.(highwatermark.level < level) then true + else if Compare.Int32.(highwatermark.level = level) then + Round.(highwatermark.round < round) + else false + +let may_sign_block cctxt (location : [`Highwatermarks] Baking_files.location) + ~delegate ~level ~round = + let open Lwt_result_syntax in + let* all_highwatermarks = load cctxt location in + return @@ may_sign all_highwatermarks.blocks ~delegate ~level ~round + +let may_sign_preattestation all_highwatermarks ~delegate ~level ~round = + may_sign all_highwatermarks.preattestations ~delegate ~level ~round + +let may_sign_attestation all_highwatermarks ~delegate ~level ~round = + may_sign all_highwatermarks.attestations ~delegate ~level ~round + +let record map ~delegate ~new_level ~new_round = + DelegateMap.update + delegate + (function + | None -> Some {level = new_level; round = new_round} + | Some ({level; round} as prev) -> + if Compare.Int32.(new_level > level) then + Some {level = new_level; round = new_round} + else if Compare.Int32.(new_level = level) then + if Round.(new_round > round) then + Some {level = new_level; round = new_round} + else Some prev + else Some prev) + map + +let record_block (cctxt : #Protocol_client_context.full) location ~delegate + ~level ~round = + let open Lwt_result_syntax in + let filename = Baking_files.filename location in + let* highwatermarks = load cctxt location in + let new_blocks = + record highwatermarks.blocks ~delegate ~new_level:level ~new_round:round + in + save_highwatermarks cctxt filename {highwatermarks with blocks = new_blocks} + +let record_preattestation (cctxt : #Protocol_client_context.full) location + ~delegate ~level ~round = + let open Lwt_result_syntax in + let filename = Baking_files.filename location in + let* highwatermarks = load cctxt location in + let new_preattestations = + record + highwatermarks.preattestations + ~delegate + ~new_level:level + ~new_round:round + in + save_highwatermarks + cctxt + filename + {highwatermarks with preattestations = new_preattestations} + +let record_attestation (cctxt : #Protocol_client_context.full) location + ~delegate ~level ~round = + let open Lwt_result_syntax in + let filename = Baking_files.filename location in + let* highwatermarks = load cctxt location in + let new_attestations = + record + highwatermarks.attestations + ~delegate + ~new_level:level + ~new_round:round + in + save_highwatermarks + cctxt + filename + {highwatermarks with attestations = new_attestations} + +let record_all_preattestations all_highwatermarks cctxt location ~delegates + ~level ~round = + let new_preattestations = + List.fold_left + (fun map delegate -> + record map ~delegate ~new_level:level ~new_round:round) + all_highwatermarks.preattestations + delegates + in + let filename = Baking_files.filename location in + save_highwatermarks + cctxt + filename + {all_highwatermarks with preattestations = new_preattestations} + +let record_all_attestations all_highwatermarks cctxt location ~delegates ~level + ~round = + let new_attestations = + List.fold_left + (fun map delegate -> + record map ~delegate ~new_level:level ~new_round:round) + all_highwatermarks.attestations + delegates + in + let filename = Baking_files.filename location in + save_highwatermarks + cctxt + filename + {all_highwatermarks with attestations = new_attestations} diff --git a/src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.mli b/src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.mli new file mode 100644 index 000000000000..64b3bc50853d --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_highwatermarks.mli @@ -0,0 +1,105 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +type highwatermark = {round : Round.t; level : int32} + +type error += Block_previously_baked of highwatermark + +type error += Block_previously_preattested of highwatermark + +type error += Block_previously_attested of highwatermark + +type t + +val load : + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + t tzresult Lwt.t + +val may_sign_block : + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + delegate:Signature.public_key_hash -> + level:int32 -> + round:Round.t -> + bool tzresult Lwt.t + +val may_sign_preattestation : + t -> + delegate:Signature.public_key_hash -> + level:int32 -> + round:Round.t -> + bool + +val may_sign_attestation : + t -> + delegate:Signature.public_key_hash -> + level:int32 -> + round:Round.t -> + bool + +val record_block : + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + delegate:Signature.public_key_hash -> + level:int32 -> + round:Round.t -> + unit tzresult Lwt.t + +val record_preattestation : + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + delegate:Signature.public_key_hash -> + level:int32 -> + round:Round.t -> + unit tzresult Lwt.t + +val record_attestation : + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + delegate:Signature.public_key_hash -> + level:int32 -> + round:Round.t -> + unit tzresult Lwt.t + +val record_all_preattestations : + t -> + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + delegates:public_key_hash list -> + level:int32 -> + round:Round.t -> + unit tzresult Lwt.t + +val record_all_attestations : + t -> + #Protocol_client_context.full -> + [`Highwatermarks] Baking_files.location -> + delegates:public_key_hash list -> + level:int32 -> + round:Round.t -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_lib.ml b/src/proto_020_PsParisC/lib_delegate/baking_lib.ml new file mode 100644 index 000000000000..a1b6473a23bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_lib.ml @@ -0,0 +1,767 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_state + +let create_state cctxt ?synchronize ?monitor_node_mempool ~config + ~current_proposal delegates = + let open Lwt_result_syntax in + let chain = cctxt#chain in + let monitor_node_operations = monitor_node_mempool in + let*! operation_worker = + Operation_worker.create ?monitor_node_operations cctxt + in + Baking_scheduling.create_initial_state + cctxt + ?synchronize + ~chain + config + operation_worker + ~current_proposal + delegates + +let get_current_proposal cctxt ?cache () = + let open Lwt_result_syntax in + let* block_stream, _block_stream_stopper = + Node_rpc.monitor_heads cctxt ?cache ~chain:cctxt#chain () + in + let*! current_head = Lwt_stream.peek block_stream in + match current_head with + | Some current_head -> return (block_stream, current_head) + | None -> failwith "head stream unexpectedly ended" + +module Events = Baking_events.Lib + +let preattest (cctxt : Protocol_client_context.full) ?(force = false) delegates + = + let open State_transitions in + let open Lwt_result_syntax in + let cache = Baking_cache.Block_cache.create 10 in + let* _, current_proposal = get_current_proposal cctxt ~cache () in + let config = Baking_configuration.make ~force () in + let* state = create_state cctxt ~config ~current_proposal delegates in + let proposal = state.level_state.latest_proposal in + let*! () = + Events.( + emit + attempting_to_vote_for_proposal + (Preattestation, state.level_state.latest_proposal)) + in + let* () = + if force then return_unit + else + let*! proposal_acceptance = + is_acceptable_proposal_for_current_level state proposal + in + match proposal_acceptance with + | Invalid -> cctxt#error "Cannot preattest an invalid proposal" + | Outdated_proposal -> cctxt#error "Cannot preattest an outdated proposal" + | Valid_proposal -> return_unit + in + let consensus_batch = + make_consensus_vote_batch state proposal Preattestation + in + let*! () = + cctxt#message + "@[Preattesting for:@ %a@]" + Format.( + pp_print_list + ~pp_sep:pp_print_space + Baking_state.pp_consensus_key_and_delegate) + (List.map + (fun ({delegate; _} : unsigned_consensus_vote) -> delegate) + consensus_batch.unsigned_consensus_votes) + in + let* signed_consensus_batch = + Baking_actions.sign_consensus_votes state.global_state consensus_batch + in + Baking_actions.inject_consensus_votes state signed_consensus_batch + +let attest (cctxt : Protocol_client_context.full) ?(force = false) delegates = + let open State_transitions in + let open Lwt_result_syntax in + let cache = Baking_cache.Block_cache.create 10 in + let* _, current_proposal = get_current_proposal cctxt ~cache () in + let config = Baking_configuration.make ~force () in + let* state = create_state cctxt ~config ~current_proposal delegates in + let proposal = state.level_state.latest_proposal in + let*! () = + Events.( + emit + attempting_to_vote_for_proposal + (Attestation, state.level_state.latest_proposal)) + in + let* () = + if force then return_unit + else + let*! proposal_acceptance = + is_acceptable_proposal_for_current_level state proposal + in + match proposal_acceptance with + | Invalid -> cctxt#error "Cannot attest an invalid proposal" + | Outdated_proposal -> cctxt#error "Cannot attest an outdated proposal" + | Valid_proposal -> return_unit + in + let consensus_batch = make_consensus_vote_batch state proposal Attestation in + let*! () = + cctxt#message + "@[Attesting for:@ %a@]" + Format.( + pp_print_list + ~pp_sep:pp_print_space + Baking_state.pp_consensus_key_and_delegate) + (List.map + (fun ({delegate; _} : unsigned_consensus_vote) -> delegate) + consensus_batch.unsigned_consensus_votes) + in + let* signed_consensus_batch = + Baking_actions.sign_consensus_votes state.global_state consensus_batch + in + let* () = + Baking_state.may_record_new_state ~previous_state:state ~new_state:state + in + Baking_actions.inject_consensus_votes state signed_consensus_batch + +let do_action (state, action) = + let open Lwt_result_syntax in + let* new_state = Baking_actions.perform_action state action in + let* () = + Baking_state.may_record_new_state ~previous_state:state ~new_state + in + return new_state + +let bake_at_next_level_event state = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + let*! baking_time = + Baking_scheduling.compute_next_potential_baking_time_at_next_level state + in + match baking_time with + | None -> cctxt#error "No baking slot found for the delegates" + | Some (timestamp, round) -> + let*! () = + cctxt#message + "Waiting until %a for round %a" + Timestamp.pp + timestamp + Round.pp + round + in + let*! () = + Option.value + ~default:Lwt.return_unit + (Baking_scheduling.sleep_until timestamp) + in + return + (Baking_state.Timeout + (Time_to_prepare_next_level_block {at_round = round})) + +let bake_at_next_level state = + let open Lwt_result_syntax in + let* event = bake_at_next_level_event state in + let*! state, action = State_transitions.step state event in + match action with + | Prepare_block {block_to_bake} -> + let* prepared_block = + Baking_actions.prepare_block state.global_state block_to_bake + in + let* new_state = + do_action + ( state, + Inject_block + {prepared_block; force_injection = false; asynchronous = false} ) + in + return new_state + | _ -> assert false + +(* Simulate the end of the current round to bootstrap the automaton + or attest the block if necessary *) +let first_automaton_event state = + match state.level_state.elected_block with + | None -> Lwt.return (Baking_scheduling.compute_bootstrap_event state) + | Some _elected_block -> + (* If there is an elected block we can directly bake at next + level after waiting its date *) + bake_at_next_level_event state + +let attestations_attesting_power state attestations = + let get_attestation_voting_power {slot; _} = + match + Delegate_slots.voting_power state.level_state.delegate_slots ~slot + with + | None -> 0 (* cannot happen *) + | Some attesting_power -> attesting_power + in + List.sort_uniq compare attestations + |> List.fold_left + (fun power attestation -> + power + get_attestation_voting_power attestation) + 0 + +let generic_attesting_power (filter : packed_operation list -> 'a list) + (extract : 'a -> consensus_content) state = + let current_mempool = + Operation_worker.get_current_operations state.global_state.operation_worker + in + let latest_proposal = state.level_state.latest_proposal in + let block_round = latest_proposal.block.round in + let shell_level = latest_proposal.block.shell.level in + let attestations = + filter (Operation_pool.Operation_set.elements current_mempool.consensus) + in + let attestations_in_mempool = + List.filter_map + (fun v -> + let consensus_content = extract v in + if + Round.(consensus_content.round = block_round) + && Compare.Int32.( + Raw_level.to_int32 consensus_content.level = shell_level) + then Some consensus_content + else None) + attestations + in + let power = attestations_attesting_power state attestations_in_mempool in + (power, attestations) + +let state_attesting_power = + generic_attesting_power + Operation_pool.filter_attestations + (fun + ({ + protocol_data = + { + contents = Single (Attestation {consensus_content; dal_content = _}); + _; + }; + _; + } : + Kind.attestation operation) + -> consensus_content) + +let propose_at_next_level ~minimal_timestamp state = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + assert (Option.is_some state.level_state.elected_block) ; + if minimal_timestamp then + let* minimal_round, delegate = + match + Baking_scheduling.first_potential_round_at_next_level + state + ~earliest_round:Round.zero + with + | None -> cctxt#error "No potential baking slot for the given delegates." + | Some first_potential_round -> return first_potential_round + in + let pool = + Operation_worker.get_current_operations + state.global_state.operation_worker + in + let kind = Fresh pool in + let block_to_bake = + { + predecessor = state.level_state.latest_proposal.block; + round = minimal_round; + delegate; + kind; + force_apply = state.global_state.config.force_apply; + } + in + let* prepared_block = + Baking_actions.prepare_block state.global_state block_to_bake + in + let* state = + do_action + ( state, + Inject_block + { + prepared_block; + force_injection = minimal_timestamp; + asynchronous = false; + } ) + in + let*! () = + cctxt#message + "Proposed block at round %a on top of %a " + Round.pp + block_to_bake.round + Block_hash.pp + block_to_bake.predecessor.hash + in + return state + else + let* state = bake_at_next_level state in + let*! () = cctxt#message "Proposal injected" in + return state + +let attestation_quorum state = + let power, attestations = state_attesting_power state in + if + Compare.Int.( + power >= state.global_state.constants.parametric.consensus_threshold) + then Some (power, attestations) + else None + +(* Here's the sketch of the algorithm: + Do I have an attestation quorum for the current block or an elected block? + - Yes :: wait and propose at next level + - No :: + Is the current proposal at the right round? + - Yes :: fail propose + - No :: + Is there a preattestation quorum or does the last proposal contain a prequorum? + - Yes :: repropose block with right payload and preattestations for current round + - No :: repropose fresh block for current round *) +let propose (cctxt : Protocol_client_context.full) ?minimal_fees + ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?force_apply + ?(force = false) ?(minimal_timestamp = false) ?extra_operations + ?context_path ?state_recorder delegates = + let open Lwt_result_syntax in + let cache = Baking_cache.Block_cache.create 10 in + let* _block_stream, current_proposal = get_current_proposal cctxt ~cache () in + let config = + Baking_configuration.make + ?minimal_fees + ?minimal_nanotez_per_gas_unit + ?minimal_nanotez_per_byte + ?context_path + ?force_apply + ~force + ?extra_operations + ?state_recorder + () + in + let* state = create_state cctxt ~config ~current_proposal delegates in + (* Make sure the operation worker is populated to avoid empty blocks + being proposed. *) + let* () = + Operation_worker.retrieve_pending_operations + cctxt + state.global_state.operation_worker + in + let* _ = + match state.level_state.elected_block with + | Some _ -> propose_at_next_level ~minimal_timestamp state + | None -> ( + match attestation_quorum state with + | Some (_voting_power, attestation_qc) -> + let state = + { + state with + round_state = + { + state.round_state with + current_phase = Baking_state.Awaiting_attestations; + }; + } + in + let latest_proposal = state.level_state.latest_proposal.block in + let candidate = + { + Operation_worker.hash = latest_proposal.hash; + round_watched = latest_proposal.round; + payload_hash_watched = latest_proposal.payload_hash; + } + in + let* state = + let*! action = + State_transitions.step + state + (Baking_state.Quorum_reached (candidate, attestation_qc)) + in + do_action action + (* this will register the elected block *) + in + propose_at_next_level ~minimal_timestamp state + | None -> ( + let*? event = Baking_scheduling.compute_bootstrap_event state in + let*! state, _action = State_transitions.step state event in + let latest_proposal = state.level_state.latest_proposal in + let open State_transitions in + let round = state.round_state.current_round in + let*! proposal_acceptance = + is_acceptable_proposal_for_current_level state latest_proposal + in + match proposal_acceptance with + | Invalid | Outdated_proposal -> ( + match round_proposer state ~level:`Current round with + | Some {consensus_key_and_delegate; _} -> + let*! action = + State_transitions.propose_block_action + state + consensus_key_and_delegate + round + ~last_proposal:state.level_state.latest_proposal + in + let* state = + match action with + | Prepare_block {block_to_bake} -> + let* prepared_block = + Baking_actions.prepare_block + state.global_state + block_to_bake + in + let* state = + do_action + ( state, + Inject_block + { + prepared_block; + force_injection = force; + asynchronous = false; + } ) + in + return state + | Inject_block {prepared_block; _} -> + let* state = + do_action + ( state, + Inject_block + { + prepared_block; + force_injection = force; + asynchronous = false; + } ) + in + return state + | _ -> assert false + in + let*! () = + cctxt#message + "Reproposed block at level %ld on round %a" + state.level_state.current_level + Round.pp + state.round_state.current_round + in + return state + | None -> cctxt#error "No slots for current round") + | Valid_proposal -> + cctxt#error + "Cannot propose: there's already a valid proposal for the \ + current round %a" + Round.pp + round)) + in + return_unit + +let repropose (cctxt : Protocol_client_context.full) ?(force = false) + ?force_round delegates = + let open Lwt_result_syntax in + let open Baking_state in + let cache = Baking_cache.Block_cache.create 10 in + let* _block_stream, current_proposal = get_current_proposal cctxt ~cache () in + let config = Baking_configuration.make ~force () in + let* state = create_state cctxt ~config ~current_proposal delegates in + (* Make sure the operation worker is populated to avoid empty blocks + being proposed. *) + let*? event = Baking_scheduling.compute_bootstrap_event state in + let*! state, _action = State_transitions.step state event in + let latest_proposal = state.level_state.latest_proposal in + let open State_transitions in + let round = + match force_round with + | Some x -> x + | None -> state.round_state.current_round + in + let*! proposal_validity = + is_acceptable_proposal_for_current_level state latest_proposal + in + match proposal_validity with + | Invalid | Outdated_proposal -> ( + match Baking_state.round_proposer state ~level:`Current round with + | Some {consensus_key_and_delegate; _} -> + let*! action = + State_transitions.propose_block_action + state + consensus_key_and_delegate + round + ~last_proposal:state.level_state.latest_proposal + in + let* signed_block = + match action with + | Prepare_block {block_to_bake} -> + let* signed_block = + Baking_actions.prepare_block state.global_state block_to_bake + in + let* _state = + do_action + ( state, + Inject_block + { + prepared_block = signed_block; + force_injection = force; + asynchronous = false; + } ) + in + return signed_block + | _ -> assert false + in + let*! () = + cctxt#message + "Reproposed block at level %ld on round %a" + signed_block.signed_block_header.shell.level + Round.pp + signed_block.round + in + return_unit + | None -> cctxt#error "No slots for current round") + | Valid_proposal -> + cctxt#error + "Cannot propose: there's already a valid proposal for the current \ + round %a" + Round.pp + round + +let bake_using_automaton ~count config state heads_stream = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + let* initial_event = first_automaton_event state in + let current_level = state.level_state.latest_proposal.block.shell.level in + let forge_event_stream = + state.global_state.forge_worker_hooks.get_forge_event_stream () + in + let loop_state = + Baking_scheduling.create_loop_state + ~heads_stream + ~forge_event_stream + state.global_state.operation_worker + in + let stop_on_next_level_block = function + | New_head_proposal proposal -> + Compare.Int32.( + proposal.block.shell.level >= Int32.(add current_level (of_int count))) + | _ -> false + in + let* event_opt = + Baking_scheduling.automaton_loop + ~stop_on_event:stop_on_next_level_block + ~config + ~on_error:(fun err -> Lwt.return (Error err)) + loop_state + state + initial_event + in + match event_opt with + | Some (New_head_proposal proposal) -> + let*! () = + cctxt#message + "Last injected block: %a (level %ld)" + Block_hash.pp + proposal.block.hash + proposal.block.shell.level + in + return_unit + | _ -> cctxt#error "Baking loop unexpectedly ended" + +(* attest the latest proposal and bake with it *) +let rec baking_minimal_timestamp ~count state + (block_stream : proposal Lwt_stream.t) = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + let latest_proposal = state.level_state.latest_proposal in + let own_attestations = + State_transitions.make_consensus_vote_batch + state + latest_proposal + Attestation + in + let current_mempool = + Operation_worker.get_current_operations state.global_state.operation_worker + in + let attestations_in_mempool = + Operation_pool.( + filter_attestations (Operation_set.elements current_mempool.consensus)) + |> List.filter_map + (fun + ({ + protocol_data = + {contents = Single (Attestation {consensus_content; _}); _}; + _; + } : + Kind.attestation operation) + -> + if + Round.(consensus_content.round = latest_proposal.block.round) + && Compare.Int32.( + Raw_level.to_int32 consensus_content.level + = latest_proposal.block.shell.level) + then Some consensus_content + else None) + in + let total_voting_power = + List.fold_left + (fun attestations own -> + own.Baking_state.vote_consensus_content :: attestations) + attestations_in_mempool + own_attestations.unsigned_consensus_votes + |> attestations_attesting_power state + in + let consensus_threshold = + state.global_state.constants.parametric.consensus_threshold + in + let* () = + if Compare.Int.(total_voting_power < consensus_threshold) then + cctxt#error + "Delegates do not have enough voting power. Only %d is available while \ + %d is required." + total_voting_power + consensus_threshold + else return_unit + in + let* minimal_round, delegate = + match + Baking_scheduling.first_potential_round_at_next_level + state + ~earliest_round:Round.zero + with + | None -> cctxt#error "No potential baking slot for the given delegates." + | Some first_potential_round -> return first_potential_round + in + let* signed_attestations = + let*! own_attestations_with_dal = + dal_content_map_p + (Baking_actions.may_get_dal_content state) + own_attestations + in + Baking_actions.sign_consensus_votes + state.global_state + own_attestations_with_dal + in + let pool = + Operation_pool.add_operations + current_mempool + (List.map + (fun signed_consensus -> signed_consensus.signed_operation) + signed_attestations.signed_consensus_votes) + in + let kind = Fresh pool in + let block_to_bake = + { + predecessor = latest_proposal.block; + round = minimal_round; + delegate; + kind; + force_apply = state.global_state.config.force_apply; + } + in + let* prepared_block = + Baking_actions.prepare_block state.global_state block_to_bake + in + let* new_state = + do_action + ( state, + Inject_block + {prepared_block; force_injection = true; asynchronous = false} ) + in + let*! () = cctxt#message "Injected block at minimal timestamp" in + if count <= 1 then return_unit + else + let*! () = + let attestation_level = Int32.succ latest_proposal.block.shell.level in + Lwt_stream.junk_while_s + (fun proposal -> + Lwt.return + Compare.Int32.( + proposal.Baking_state.block.shell.level <> attestation_level)) + block_stream + in + let*! next_level_proposal = + let*! r = Lwt_stream.get block_stream in + match r with + | None -> cctxt#error "Stream unexpectedly ended" + | Some b -> Lwt.return b + in + let*! new_state, action = + State_transitions.step new_state (New_head_proposal next_level_proposal) + in + let* new_state = + match action with + | Update_to_level update -> + let* new_state, _preattest_action = + Baking_actions.update_to_level new_state update + in + return + { + new_state with + round_state = + { + Baking_state.current_round = Round.zero; + current_phase = Idle; + delayed_quorum = None; + early_attestations = []; + awaiting_unlocking_pqc = false; + }; + } + | _ -> + (* Algorithmically, this will always be an update_to_level + action. *) + assert false + in + baking_minimal_timestamp ~count:(pred count) new_state block_stream + +let bake (cctxt : Protocol_client_context.full) ?minimal_fees + ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?force_apply ?force + ?(minimal_timestamp = false) ?extra_operations + ?(monitor_node_mempool = true) ?context_path ?dal_node_endpoint ?(count = 1) + ?votes ?state_recorder delegates = + let open Lwt_result_syntax in + let config = + Baking_configuration.make + ?minimal_fees + ?minimal_nanotez_per_gas_unit + ?minimal_nanotez_per_byte + ?context_path + ?force_apply + ?force + ?extra_operations + ?dal_node_endpoint + ?votes + ?state_recorder + () + in + let cache = Baking_cache.Block_cache.create 10 in + let* block_stream, current_proposal = get_current_proposal cctxt ~cache () in + let* state = + create_state + cctxt + ~monitor_node_mempool + ~synchronize:(not minimal_timestamp) + ~config + ~current_proposal + delegates + in + let* () = + when_ monitor_node_mempool (fun () -> + (* Make sure the operation worker is populated to avoid empty + blocks being baked *) + Operation_worker.retrieve_pending_operations + cctxt + state.global_state.operation_worker) + in + if not minimal_timestamp then + bake_using_automaton ~count config state block_stream + else baking_minimal_timestamp ~count state block_stream diff --git a/src/proto_020_PsParisC/lib_delegate/baking_lib.mli b/src/proto_020_PsParisC/lib_delegate/baking_lib.mli new file mode 100644 index 000000000000..6805daf9ae17 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_lib.mli @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +(** {1 API} *) + +val bake : + Protocol_client_context.full -> + ?minimal_fees:Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?force_apply:bool -> + ?force:bool -> + ?minimal_timestamp:bool -> + ?extra_operations:Baking_configuration.Operations_source.t -> + ?monitor_node_mempool:bool -> + ?context_path:string -> + ?dal_node_endpoint:Uri.t -> + (* Number of baked blocks. Defaults to 1. *) + ?count:int -> + ?votes:Baking_configuration.per_block_votes_config -> + ?state_recorder:Baking_configuration.state_recorder_config -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t + +val preattest : + Protocol_client_context.full -> + ?force:bool -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t + +val attest : + Protocol_client_context.full -> + ?force:bool -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t + +val propose : + Protocol_client_context.full -> + ?minimal_fees:Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?force_apply:bool -> + ?force:bool -> + ?minimal_timestamp:bool -> + ?extra_operations:Baking_configuration.Operations_source.t -> + ?context_path:string -> + ?state_recorder:Baking_configuration.state_recorder_config -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t + +(** [repropose] tries to bake a new block proposal on the same level + as the current head. If provided, the proposal will use the + [force_round] argument as its reproposal round, otherwise the + current tenderbake round will be used. *) +val repropose : + Protocol_client_context.full -> + ?force:bool -> + ?force_round:Round.t -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_nonces.ml b/src/proto_020_PsParisC/lib_delegate/baking_nonces.ml new file mode 100644 index 000000000000..6fd910f17f57 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_nonces.ml @@ -0,0 +1,588 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2024 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +module Events = Baking_events.Nonces + +type state = { + cctxt : Protocol_client_context.full; + chain : Chain_services.chain; + constants : Constants.t; + config : Baking_configuration.nonce_config; + legacy_location : [`Legacy_nonce] Baking_files.location; + stateful_location : [`Stateful_nonce] Baking_files.location; + orphaned_location : [`Orphaned_nonce] Baking_files.location; + mutable last_predecessor : Block_hash.t; +} + +type t = state + +(** [nonce_state] tracks the current state of committed nonces. It is used to + optimise nonce processing by further reducing queries for nonce metadata. *) +type nonce_state = + | Committed + (** [Committed] is initial state and signals that the nonce was committed at + some cycle: + - If baker in current cycle: do nothing + - If baker in cycle + 1: + - If block with commitment is part of the + cannonical chain: then transition to injected + - else: safe to delete + - If current cycle > cycle + 1: too stale, so safe to delete *) + | Revealed of Raw_level.t + (** [Revealed] signals that the nonce revelation operation was injected at + [injected_level] + - At each level, get the last finalized block (level - 2) + - If the revelation operation found in that block: nonce is safe to + delete + - If not found: + - If pass `re_injection_threshold`: + - consider revelation operation lost, so re-inject + - transition to injected with updated level + - If pass `nonce_revelation_threshold`: + - missed out revelation operation, so delete + - else: do nothing *) + +type nonce_data = { + nonce : Nonce.t; + nonce_hash : Nonce_hash.t; + block_hash : Block_hash.t; (* Keep around for legacy purposes *) + cycle : Cycle.t; + level : Raw_level.t; + round : Round.t option; + nonce_state : nonce_state; +} + +type nonces = nonce_data Nonce_hash.Map.t + +let empty = Nonce_hash.Map.empty + +let legacy_empty = Block_hash.Map.empty + +let reinjection_threshold = 2l + +let nonce_state_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Committed" + (constant "committed") + (function Committed -> Some () | _ -> None) + (fun () -> Committed); + case + (Tag 1) + ~title:"Revealed" + (obj1 (req "injection_level" Raw_level.encoding)) + (function + | Revealed injection_level -> Some injection_level | _ -> None) + (fun injection_level -> Revealed injection_level); + ] + +let nonce_data_encoding = + let open Data_encoding in + def "nonce_data" + @@ conv + (fun {nonce; nonce_hash; block_hash; cycle; level; round; nonce_state} -> + (nonce, nonce_hash, block_hash, cycle, level, round, nonce_state)) + (fun (nonce, nonce_hash, block_hash, cycle, level, round, nonce_state) -> + {nonce; nonce_hash; block_hash; cycle; level; round; nonce_state}) + (obj7 + (req "nonce" Nonce.encoding) + (req "hash" Nonce_hash.encoding) + (req "block" Block_hash.encoding) + (req "cycle" Cycle.encoding) + (req "level" Raw_level.encoding) + (opt "round" Round.encoding) + (req "state" nonce_state_encoding)) + +let legacy_encoding = + let open Data_encoding in + def "legacy_seed_nonce" + @@ conv + (fun m -> + Block_hash.Map.fold (fun hash nonce acc -> (hash, nonce) :: acc) m []) + (fun l -> + List.fold_left + (fun map (hash, nonce) -> Block_hash.Map.add hash nonce map) + Block_hash.Map.empty + l) + @@ list (obj2 (req "block" Block_hash.encoding) (req "nonce" Nonce.encoding)) + +let encoding = + let open Data_encoding in + def "seed_nonce" + @@ conv + (fun m -> + Nonce_hash.Map.fold + (fun _hash nonce_data acc -> nonce_data :: acc) + m + []) + (fun l -> + List.fold_left + (fun map data -> Nonce_hash.Map.add data.nonce_hash data map) + Nonce_hash.Map.empty + l) + @@ list nonce_data_encoding + +let load (wallet : #Client_context.wallet) + ~(stateful_location : [`Stateful_nonce] Baking_files.location) = + let location = Baking_files.filename stateful_location in + wallet#load location ~default:empty encoding + +let save (wallet : #Client_context.wallet) + ~(legacy_location : [`Legacy_nonce] Baking_files.location) + ~(stateful_location : [`Stateful_nonce] Baking_files.location) + ~(orphaned_location : [`Orphaned_nonce] Baking_files.location) nonces = + let open Lwt_result_syntax in + let legacy_location = Baking_files.filename legacy_location in + let stateful_location = Baking_files.filename stateful_location in + let orphaned_location = Baking_files.filename orphaned_location in + (* We always write in both files *) + let* () = wallet#write stateful_location nonces encoding in + (* Merge current nonces and orphaned nonces (if exists) before writing to + legacy nonce file *) + let* orphaned_nonces = + wallet#load orphaned_location ~default:legacy_empty legacy_encoding + in + let legacy_nonces = + Nonce_hash.Map.fold + (fun _ {nonce; block_hash; _} legacy_nonces -> + Block_hash.Map.add block_hash nonce legacy_nonces) + nonces + orphaned_nonces + in + wallet#write legacy_location legacy_nonces legacy_encoding + +let add nonces nonce = Nonce_hash.Map.add nonce.nonce_hash nonce nonces + +let is_outdated constants committed_cycle current_cycle = + let {Constants.parametric = {consensus_rights_delay; _}; _} = constants in + Int32.sub (Cycle.to_int32 current_cycle) (Cycle.to_int32 committed_cycle) + > Int32.of_int consensus_rights_delay + +(** [try_migrate_legacy_nonces] makes a best effort to migrate nonces in the legacy format + to new format. Legacy nonces that cannot be migrated are dropped. No updates to the legacy + file are made *) +let try_migrate_legacy_nonces state = + let { + cctxt; + chain; + legacy_location; + stateful_location; + orphaned_location; + constants; + _; + } = + state + in + let migrate () = + let open Lwt_result_syntax in + let legacy_location = Baking_files.filename legacy_location in + let* legacy_nonces = + cctxt#load legacy_location ~default:legacy_empty legacy_encoding + in + let new_location = Baking_files.filename stateful_location in + let* nonces = cctxt#load new_location ~default:empty encoding in + let* {cycle = current_cycle; _} = + Plugin.RPC.current_level cctxt (chain, `Head 0) + in + let*! nonces, failed_migration = + Block_hash.Map.fold_s + (fun block_hash nonce (existing_nonces, failed_migration) -> + let*! updated_nonces = + if Nonce_hash.Map.mem (Nonce.hash nonce) existing_nonces then + (* Current nonce already exists in the new format, no migration needed. *) + return existing_nonces + else + let* {cycle = nonce_cycle; level = nonce_level; _} = + Plugin.RPC.current_level cctxt (chain, `Hash (block_hash, 0)) + in + match is_outdated constants nonce_cycle current_cycle with + | true -> + let*! () = Events.(emit outdated_nonce block_hash) in + return existing_nonces + | false -> ( + let* nonce_info = + Alpha_services.Nonce.get cctxt (chain, `Head 0) nonce_level + in + match nonce_info with + | Missing nonce_hash when Nonce.check_hash nonce nonce_hash -> + (* If a nonce is found locally but revelation not in context, + assume that it is [Committed] and not already [Revealed]. + In the case that it is already in mempool, the mempool + will reject the operation. *) + let data = + { + nonce; + nonce_hash = Nonce.hash nonce; + block_hash; + cycle = nonce_cycle; + level = nonce_level; + round = None; + nonce_state = Committed; + } + in + return + (Nonce_hash.Map.add + data.nonce_hash + data + existing_nonces) + | Missing _nonce_hash -> + let*! () = Events.(emit unexpected_nonce block_hash) in + return existing_nonces + | Revealed _nonce_hash -> + let*! () = Events.(emit revealed_nonce block_hash) in + return existing_nonces + | Forgotten -> return existing_nonces) + in + Lwt.return + (match updated_nonces with + | Ok updated_nonces -> (updated_nonces, failed_migration) + | Error _ -> + ( existing_nonces, + Block_hash.Map.add block_hash nonce failed_migration ))) + legacy_nonces + (nonces, legacy_empty) + in + let* () = cctxt#write new_location nonces encoding in + let+ () = + if Block_hash.Map.is_empty failed_migration then return_unit + else + let orphaned_location = Baking_files.filename orphaned_location in + state.cctxt#write orphaned_location failed_migration legacy_encoding + in + failed_migration + in + let open Lwt_syntax in + let* res = migrate () in + match res with + | Ok failed_migration when Block_hash.Map.is_empty failed_migration -> + Events.(emit success_migrate_nonces ()) + | Ok failed_migration -> + let failed_block_hashes = + Block_hash.Map.fold + (fun block_hash _ acc -> block_hash :: acc) + failed_migration + [] + in + Events.(emit ignore_failed_nonce_migration failed_block_hashes) + | Error _ -> return_unit + +(** [partition_unrevealed_nonces state nonces current_cycle current_level] partitions + nonces into 2 groups: + - nonces that need to be re/revealed + - nonces that are live + Nonces that are not relevant can be dropped. +*) +let partition_unrevealed_nonces {cctxt; chain; _} nonces current_cycle + current_level = + let open Lwt_result_syntax in + match Cycle.pred current_cycle with + | None -> + (* This will be [None] iff [current_cycle = 0] which only + occurs during genesis. *) + return (empty, nonces) + | Some previous_cycle -> + (* Partition nonces into nonces that need to be re/injected and + those that do not. *) + Nonce_hash.Map.fold_es + (fun _hash nonce_data (nonces_to_reveal, live) -> + let {nonce_hash; cycle; level; nonce_state; _} = nonce_data in + match cycle with + | cycle when Cycle.(cycle = previous_cycle) -> ( + (* Only process nonces that are part of previous cycle. *) + let+ nonce_info = + Alpha_services.Nonce.get cctxt (chain, `Head 0) level + in + match (nonce_state, nonce_info) with + | Committed, Missing expected_nonce_hash + when Nonce_hash.(nonce_hash = expected_nonce_hash) -> + (* Nonce was committed and block is part of main chain *) + (add nonces_to_reveal nonce_data, live) + | Committed, _ -> + (* Nonce was committed but block is not part of main chain *) + (nonces_to_reveal, live) + | Revealed injection_level, Missing expected_nonce_hash + when Nonce_hash.(nonce_hash = expected_nonce_hash) -> + if + Raw_level.diff current_level injection_level + > reinjection_threshold + then + (* [reinjection_threshold] levels have passed since nonce revelation + was injected. It might have been lost so reinject. *) + (add nonces_to_reveal nonce_data, live) + else + (* We are waiting for nonce revelation to be included. *) + (nonces_to_reveal, add live nonce_data) + | Revealed _injection_level, Missing _ + | Revealed _injection_level, Forgotten + | Revealed _injection_level, Revealed _ -> + (nonces_to_reveal, live)) + | cycle when Cycle.(cycle = current_cycle) -> + (* Nothing to do if nonce was committed as part of current + cycle. *) + return (nonces_to_reveal, add live nonce_data) + | _ -> + (* Nonces not part of current or previous cycles are orphaned and can + be dropped. *) + return (nonces_to_reveal, live)) + nonces + (empty, empty) + +(* Nonce creation *) + +let generate_seed_nonce (nonce_config : Baking_configuration.nonce_config) + (delegate : Baking_state.consensus_key) level = + let open Lwt_result_syntax in + let* nonce = + match nonce_config with + | Deterministic -> + let data = Data_encoding.Binary.to_bytes_exn Raw_level.encoding level in + let* nonce = + Client_keys.deterministic_nonce delegate.secret_key_uri data + in + return (Data_encoding.Binary.of_bytes_exn Nonce.encoding nonce) + | Random -> ( + match + Nonce.of_bytes (Tezos_crypto.Rand.generate Constants.nonce_length) + with + | Error _errs -> assert false + | Ok nonce -> return nonce) + in + return (Nonce.hash nonce, nonce) + +let register_nonce (cctxt : #Protocol_client_context.full) ~chain_id block_hash + nonce ~cycle ~level ~round = + let open Lwt_result_syntax in + let*! () = Events.(emit registering_nonce block_hash) in + (* Register the nonce *) + let legacy_location = Baking_files.resolve_location ~chain_id `Legacy_nonce in + let stateful_location = + Baking_files.resolve_location ~chain_id `Stateful_nonce + in + let orphaned_location = + Baking_files.resolve_location ~chain_id `Orphaned_nonce + in + cctxt#with_lock @@ fun () -> + let* nonces = load cctxt ~stateful_location in + let nonces = + add + nonces + { + nonce; + nonce_hash = Nonce.hash nonce; + block_hash; + cycle; + level; + round = Some round; + nonce_state = Committed; + } + in + let* () = + save cctxt ~legacy_location ~stateful_location nonces ~orphaned_location + in + return_unit + +(** [inject_seed_nonce_revelation cctxt ~chain ~block ~branch nonces] forges one + [Seed_nonce_revelation] operation per each nonce to be revealed, together with + a signature and then injects these operations. *) +let inject_seed_nonce_revelation (cctxt : #Protocol_client_context.full) ~chain + ~block ~branch nonces = + let open Lwt_result_syntax in + match nonces with + | [] -> + let*! () = Events.(emit nothing_to_reveal branch) in + return_unit + | _ -> + List.iter_es + (fun (level, nonce) -> + let* bytes = + Plugin.RPC.Forge.seed_nonce_revelation + cctxt + (chain, block) + ~branch + ~level + ~nonce + () + in + let bytes = Signature.concat bytes Signature.zero in + let* oph = + Shell_services.Injection.operation ~async:true cctxt ~chain bytes + in + let*! () = + Events.( + emit + revealing_nonce + (Raw_level.to_int32 level, Chain_services.to_string chain, oph)) + in + return_unit) + nonces + +(** [reveal_potential_nonces state new_proposal] updates the internal [state] + of the worker each time a proposal with a new predecessor is received; this means + revealing the necessary nonces. *) +let reveal_potential_nonces state new_proposal = + let open Lwt_result_syntax in + let { + cctxt; + chain; + legacy_location; + stateful_location; + orphaned_location; + last_predecessor; + _; + } = + state + in + let new_predecessor_hash = new_proposal.Baking_state.predecessor.hash in + if + Block_hash.(last_predecessor <> new_predecessor_hash) + && not (Baking_state.is_first_block_in_protocol new_proposal) + then ( + (* only try revealing nonces when the proposal's predecessor is a new one *) + state.last_predecessor <- new_predecessor_hash ; + let block = `Head 0 in + let branch = new_predecessor_hash in + (* improve concurrency *) + cctxt#with_lock @@ fun () -> + let*! nonces = load cctxt ~stateful_location in + match nonces with + | Error err -> + let*! () = Events.(emit cannot_read_nonces err) in + return_unit + | Ok nonces -> ( + let* {cycle; level; _} = + Plugin.RPC.current_level cctxt (chain, `Head 0) + in + let*! partitioned_nonces = + partition_unrevealed_nonces state nonces cycle level + in + match partitioned_nonces with + | Error err -> + let*! () = Events.(emit cannot_retrieve_unrevealed_nonces err) in + return_unit + | Ok (nonces_to_reveal, live_nonces) -> ( + if Nonce_hash.Map.is_empty nonces_to_reveal then return_unit + else + let prepared_nonces = + Nonce_hash.Map.fold + (fun _ {level; nonce; _} acc -> (level, nonce) :: acc) + nonces_to_reveal + [] + in + let*! result = + inject_seed_nonce_revelation + cctxt + ~chain + ~block + ~branch + prepared_nonces + in + match result with + | Error err -> + let*! () = Events.(emit cannot_inject_nonces err) in + return_unit + | Ok () -> + let updated_nonces = + let nonce_with_new_states = + Nonce_hash.Map.map + (fun nonce_data -> + {nonce_data with nonce_state = Revealed level}) + nonces_to_reveal + in + Nonce_hash.Map.fold + (fun hash nonce acc -> Nonce_hash.Map.add hash nonce acc) + nonce_with_new_states + live_nonces + in + let* () = + save + cctxt + ~legacy_location + ~stateful_location + ~orphaned_location + updated_nonces + in + return_unit))) + else return_unit + +(* We suppose that the block stream is cloned by the caller *) +let start_revelation_worker cctxt config chain_id constants block_stream = + let open Lwt_syntax in + let legacy_location = Baking_files.resolve_location ~chain_id `Legacy_nonce in + let stateful_location = + Baking_files.resolve_location ~chain_id `Stateful_nonce + in + let chain = `Hash chain_id in + let canceler = Lwt_canceler.create () in + let should_shutdown = ref false in + let state = + { + cctxt; + chain; + constants; + config; + legacy_location; + stateful_location; + orphaned_location = + Baking_files.resolve_location ~chain_id `Orphaned_nonce; + last_predecessor = Block_hash.zero; + } + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7110 + Enshrine `stateful_hash_nonces` as the main nonce file + format. + *) + let* () = try_migrate_legacy_nonces state in + let rec worker_loop () = + Lwt_canceler.on_cancel canceler (fun () -> + should_shutdown := true ; + Lwt.return_unit) ; + let* new_proposal = Lwt_stream.get block_stream in + match new_proposal with + | None -> + (* The head stream closed meaning that the connection + with the node was interrupted: exit *) + return_unit + | Some new_proposal -> + if !should_shutdown then return_unit + else + let* _ = reveal_potential_nonces state new_proposal in + worker_loop () + in + Lwt.dont_wait + (fun () -> + Lwt.finalize + (fun () -> + let* () = Events.(emit revelation_worker_started ()) in + let* () = worker_loop () in + (* never ending loop *) Lwt.return_unit) + (fun () -> (* TODO *) Lwt.return_unit)) + (fun _exn -> ()) ; + Lwt.return canceler diff --git a/src/proto_020_PsParisC/lib_delegate/baking_nonces.mli b/src/proto_020_PsParisC/lib_delegate/baking_nonces.mli new file mode 100644 index 000000000000..4e8f2ce78877 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_nonces.mli @@ -0,0 +1,79 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2024 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type state + +type t = state + +(** [nonces] is a hash map corresponding to the data which can be found in the + file from [nonces_location] *) +type nonces + +(** [load wallet location] loads the file corresponding to [location] and + returns a data structure containing the stored information. *) +val load : + #Client_context.wallet -> + stateful_location:[`Stateful_nonce] Baking_files.location -> + nonces tzresult Lwt.t + +(** [generate_seed_nonce nonce_config delegate level] computes a nonce via a + [Deterministic] or [Random] approach, depending on the [nonce_config] + argument; the deterministic case uses as parameters [delegate] and [level]. *) +val generate_seed_nonce : + Baking_configuration.nonce_config -> + Baking_state.consensus_key -> + Raw_level.t -> + (Nonce_hash.t * Nonce.t) tzresult Lwt.t + +(** [register_nonce cctxt ~chain_id block_hash nonce ~cycle ~level ~round] updates + the contents from the nonces file located using [cctxt] and [~chain_id] by + adding a new entry or replacing an existing one of the form + [block_hash] : [nonce] * [~cycle] * [~level] * [~round]. *) +val register_nonce : + #Protocol_client_context.full -> + chain_id:Chain_id.t -> + Block_hash.t -> + Nonce.t -> + cycle:Cycle.t -> + level:Raw_level.t -> + round:Round.t -> + unit tzresult Lwt.t + +(** [start_revelation_worker cctxt config chain_id constants block_stream] + represents the continuous process of receiving new proposal from [block_stream] + and applying them to the internal state created from [cctxt], [config], + [chain_id] and [constants]; each new proposal can produce a nonce, to be stored + in a nonce file location, facilitating the nonce revelation process. *) +val start_revelation_worker : + Protocol_client_context.full -> + Baking_configuration.nonce_config -> + Chain_id.t -> + Constants.t -> + Baking_state.proposal Lwt_stream.t -> + Lwt_canceler.t Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_pow.ml b/src/proto_020_PsParisC/lib_delegate/baking_pow.ml new file mode 100644 index 000000000000..d4b61b89bd6c --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_pow.ml @@ -0,0 +1,134 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let default_constant = "\x00\x00\x00\x05" + +let with_version_constant = + let commit_hash = + match + Hex.to_string (`Hex Tezos_version_value.Current_git_info.commit_hash) + with + | None -> Tezos_version_value.Current_git_info.commit_hash + | Some s -> s + in + if String.length commit_hash >= 4 then String.sub commit_hash 0 4 + else default_constant + +let with_version_constant_len = String.length with_version_constant + +let proof_of_work_nonce = + let out = + Bytes.make Alpha_context.Constants.proof_of_work_nonce_size '\000' + in + let () = + Bytes.blit_string with_version_constant 0 out 0 with_version_constant_len + in + out + +(* [proof_of_work_nonce] will be modified in place so we make a clean copy to expose to the outside *) +let empty_proof_of_work_nonce = Bytes.copy proof_of_work_nonce + +let max_z_len = + Alpha_context.Constants.proof_of_work_nonce_size - with_version_constant_len + +(* Make a string of zeros to restore [proof_of_work_nonce] to its original value in 1 operation *) +let zeros = String.make max_z_len '\000' + +let mine ~proof_of_work_threshold shell builder = + let open Lwt_result_syntax in + match + Option.bind + (Data_encoding.Binary.fixed_length Block_payload_hash.encoding) + (fun payload -> + Option.map + (fun round -> + let shell = + Data_encoding.Binary.length + Block_header.shell_header_encoding + shell + in + shell + payload + round + with_version_constant_len) + (Data_encoding.Binary.fixed_length Round_repr.encoding)) + (* Where to put the proof of work value is in the bytes of the encoded header *) + with + | None -> failwith "Cannot compute block header offset" + | Some offset -> + let () = + (* Restore proof_of_work_nonce to its original value. *) + Bytes.blit_string + zeros + 0 + proof_of_work_nonce + with_version_constant_len + max_z_len + in + (* Build the binary of the block header with 0 as proof of work and compute its hash. *) + let block_0 = builder proof_of_work_nonce in + let block_header = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Block_header.encoding + Alpha_context.Block_header. + { + shell; + protocol_data = {contents = block_0; signature = Signature.zero}; + } + in + let block_hash = Block_header.hash_raw block_header in + let block_hash_bytes = Block_hash.to_bytes block_hash in + (* The loop edits [block_header] and [block_hash] (by editing its subpart [block_hash_bytes]!) in place. *) + let rec loop z = + let z_len = (Z.numbits z + 7) / 8 in + if z_len > max_z_len then + failwith + "Client_baking_pow.mine: couldn't find nonce for required proof of \ + work" + else ( + Bytes.blit_string (Z.to_bits z) 0 block_header offset z_len ; + (if Hacl_star.AutoConfig2.(has_feature VEC256) then + Hacl_star.Hacl.Blake2b_256.Noalloc.hash + else Hacl_star.Hacl.Blake2b_32.Noalloc.hash) + ~key:Bytes.empty + ~msg:block_header + ~digest:block_hash_bytes ; + if + Alpha_context.Block_header.Proof_of_work.check_hash + block_hash + proof_of_work_threshold + then + let () = + Bytes.blit_string + (Z.to_bits z) + 0 + proof_of_work_nonce + with_version_constant_len + z_len + in + let block = builder proof_of_work_nonce in + return block + else loop (Z.succ z)) + in + loop Z.zero diff --git a/src/proto_020_PsParisC/lib_delegate/baking_pow.mli b/src/proto_020_PsParisC/lib_delegate/baking_pow.mli new file mode 100644 index 000000000000..ad5975c9190c --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_pow.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** A null proof-of-work nonce. This should only be used to nonsensical blocks + of the correct size and shape. *) +val empty_proof_of_work_nonce : Bytes.t + +(** [mine ~proof_of_work_threshold chain block header builder] returns a block with a valid + proof-of-work nonce. The function [builder], provided by the caller, is used + to make the block. All the internal logic of generating nonces and checking + for the proof-of-work threshold is handled by [mine]. *) +val mine : + proof_of_work_threshold:int64 -> + Block_header.shell_header -> + (Bytes.t -> Alpha_context.Block_header.contents) -> + Alpha_context.Block_header.contents tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_scheduling.ml b/src/proto_020_PsParisC/lib_delegate/baking_scheduling.ml new file mode 100644 index 000000000000..39784b2cd9c7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_scheduling.ml @@ -0,0 +1,1036 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context +module Events = Baking_events.Scheduling +open Baking_state + +type loop_state = { + heads_stream : Baking_state.proposal Lwt_stream.t; + get_valid_blocks_stream : Baking_state.proposal Lwt_stream.t Lwt.t; + qc_stream : Operation_worker.event Lwt_stream.t; + forge_event_stream : forge_event Lwt_stream.t; + future_block_stream : + [`New_future_head of proposal | `New_future_valid_proposal of proposal] + Lwt_stream.t; + push_future_block : + [`New_future_head of proposal | `New_future_valid_proposal of proposal] -> + unit; + mutable last_get_head_event : + [`New_head_proposal of proposal option] Lwt.t option; + mutable last_get_valid_block_event : + [`New_valid_proposal of proposal option] Lwt.t option; + mutable last_future_block_event : + [`New_future_head of proposal | `New_future_valid_proposal of proposal] + Lwt.t + option; + mutable last_get_qc_event : + [`QC_reached of Operation_worker.event option] Lwt.t option; + mutable last_forge_event : + [`New_forge_event of forge_event option] Lwt.t option; +} + +type events = + [ `New_future_head of proposal + | `New_future_valid_proposal of proposal + | `New_valid_proposal of proposal option + | `New_head_proposal of proposal option + | `QC_reached of Operation_worker.event option + | `New_forge_event of forge_event option + | `Termination + | `Timeout of timeout_kind ] + Lwt.t + +let create_loop_state ?get_valid_blocks_stream ~heads_stream ~forge_event_stream + operation_worker = + let future_block_stream, push_future_block = Lwt_stream.create () in + let get_valid_blocks_stream = + match get_valid_blocks_stream with + | None -> Lwt.return (Lwt_stream.create () |> fst) + | Some vbs_t -> vbs_t + in + { + heads_stream; + get_valid_blocks_stream; + qc_stream = Operation_worker.get_quorum_event_stream operation_worker; + forge_event_stream; + future_block_stream; + push_future_block = (fun x -> push_future_block (Some x)); + last_get_head_event = None; + last_get_valid_block_event = None; + last_future_block_event = None; + last_get_qc_event = None; + last_forge_event = None; + } + +let find_in_known_round_intervals known_round_intervals ~predecessor_timestamp + ~predecessor_round ~now = + let open Baking_cache in + Round_timestamp_interval_cache.( + find_opt + known_round_intervals + {predecessor_timestamp; predecessor_round; time_interval = (now, now)}) + +let sleep_until_ptime ptime = + let delay = Ptime.diff ptime (Time.System.now ()) in + if Ptime.Span.compare delay Ptime.Span.zero < 0 then None + else Some (Lwt_unix.sleep (Ptime.Span.to_float_s delay)) + +(** The function is blocking until it is [time]. *) +let sleep_until time = + (* Sleeping is a system op, baking is a protocol op, this is where we convert *) + let time = Time.System.of_protocol_exn time in + sleep_until_ptime time + +(* Only allocate once the termination promise *) +let terminated = + let open Lwt_syntax in + let+ _ = Lwt_exit.clean_up_starts in + `Termination + +let rec wait_next_event ~timeout loop_state = + let open Lwt_result_syntax in + (* TODO? should we prioritize head events/timeouts to resynchronize if needs be ? *) + let get_head_event () = + (* n.b. we should also consume the available elements in the + block_stream before starting baking. *) + match loop_state.last_get_head_event with + | None -> + let t = + let*! e = Lwt_stream.get loop_state.heads_stream in + Lwt.return (`New_head_proposal e) + in + loop_state.last_get_head_event <- Some t ; + t + | Some t -> t + in + let get_valid_block_event () = + match loop_state.last_get_valid_block_event with + | None -> + let t = + let*! valid_blocks_stream = loop_state.get_valid_blocks_stream in + let*! e = Lwt_stream.get valid_blocks_stream in + Lwt.return (`New_valid_proposal e) + in + loop_state.last_get_valid_block_event <- Some t ; + t + | Some t -> t + in + let get_future_block_event () = + (* n.b. we should also consume the available elements in the + block_stream before starting baking. *) + match loop_state.last_future_block_event with + | None -> + let t = + let*! future_proposal = + Lwt_stream.get loop_state.future_block_stream + in + Lwt.return + @@ + match future_proposal with + | None -> + (* unreachable, we never close the stream *) + assert false + | Some future_proposal -> future_proposal + in + loop_state.last_future_block_event <- Some t ; + t + | Some t -> t + in + let get_qc_event () = + match loop_state.last_get_qc_event with + | None -> + let t = + let*! e = Lwt_stream.get loop_state.qc_stream in + Lwt.return (`QC_reached e) + in + loop_state.last_get_qc_event <- Some t ; + t + | Some t -> t + in + let get_forge_event () = + match loop_state.last_forge_event with + | None -> + let t = + let*! e = Lwt_stream.get loop_state.forge_event_stream in + Lwt.return (`New_forge_event e) + in + loop_state.last_forge_event <- Some t ; + t + | Some t -> t + in + (* event construction *) + let open Baking_state in + let*! result = + Lwt.choose + [ + terminated; + (get_head_event () :> events); + (get_valid_block_event () :> events); + (get_future_block_event () :> events); + (get_qc_event () :> events); + (get_forge_event () :> events); + (timeout :> events); + ] + in + match result with + (* event matching *) + | `Termination -> + (* Exit the loop *) + return_none + | `New_valid_proposal None -> + (* Node connection lost *) + loop_state.last_get_valid_block_event <- None ; + tzfail Baking_errors.Node_connection_lost + | `New_head_proposal None -> + (* Node connection lost *) + loop_state.last_get_head_event <- None ; + tzfail Baking_errors.Node_connection_lost + | `QC_reached None -> + (* Not supposed to happen: exit the loop *) + loop_state.last_get_qc_event <- None ; + return_none + | `New_forge_event None -> + (* Not supposed to happen: exit the loop *) + loop_state.last_forge_event <- None ; + return_none + | `New_valid_proposal (Some proposal) -> ( + loop_state.last_get_valid_block_event <- None ; + (* Is the block in the future? *) + match sleep_until proposal.block.shell.timestamp with + | Some waiter -> + (* If so, wait until its timestamp is reached before advertising it *) + let*! () = Events.(emit proposal_in_the_future proposal.block.hash) in + Lwt.dont_wait + (fun () -> + let*! () = waiter in + loop_state.push_future_block (`New_future_valid_proposal proposal) ; + Lwt.return_unit) + (fun _exn -> ()) ; + wait_next_event ~timeout loop_state + | None -> return_some (New_valid_proposal proposal)) + | `New_head_proposal (Some proposal) -> ( + loop_state.last_get_head_event <- None ; + (* Is the block in the future? *) + match sleep_until proposal.block.shell.timestamp with + | Some waiter -> + (* If so, wait until its timestamp is reached before advertising it *) + let*! () = Events.(emit proposal_in_the_future proposal.block.hash) in + Lwt.dont_wait + (fun () -> + let*! () = waiter in + loop_state.push_future_block (`New_future_head proposal) ; + Lwt.return_unit) + (fun _exn -> ()) ; + wait_next_event ~timeout loop_state + | None -> return_some (New_head_proposal proposal)) + | `New_future_head proposal -> + let*! () = + Events.(emit process_proposal_in_the_future proposal.block.hash) + in + loop_state.last_future_block_event <- None ; + return_some (New_head_proposal proposal) + | `New_future_valid_proposal proposal -> + let*! () = + Events.(emit process_proposal_in_the_future proposal.block.hash) + in + loop_state.last_future_block_event <- None ; + return_some (New_valid_proposal proposal) + | `QC_reached + (Some (Operation_worker.Prequorum_reached (candidate, preattestation_qc))) + -> + loop_state.last_get_qc_event <- None ; + return_some (Prequorum_reached (candidate, preattestation_qc)) + | `QC_reached + (Some (Operation_worker.Quorum_reached (candidate, attestation_qc))) -> + loop_state.last_get_qc_event <- None ; + return_some (Quorum_reached (candidate, attestation_qc)) + | `New_forge_event (Some event) -> + loop_state.last_forge_event <- None ; + return_some (New_forge_event event) + | `Timeout e -> return_some (Timeout e) + +let rec first_own_round_in_range delegate_slots ~committee_size ~included_min + ~excluded_max = + if included_min >= excluded_max then None + else + match Round.of_int included_min with + | Error _ -> + (* Should not happen because in practice, [included_min] is + non-negative and not big enough to overflow as an Int32. *) + None + | Ok round -> ( + match Round.to_slot round ~committee_size with + | Error _ -> + (* Impossible because [Round.of_int] builds a sound round. *) None + | Ok slot -> ( + match Delegate_slots.own_slot_owner delegate_slots ~slot with + | Some {consensus_key_and_delegate; _} -> + Some (round, consensus_key_and_delegate) + | None -> + first_own_round_in_range + delegate_slots + ~committee_size + ~included_min:(included_min + 1) + ~excluded_max)) + +let first_potential_round_at_next_level state ~earliest_round = + match Round.to_int earliest_round with + | Error _ -> None + | Ok earliest_round -> + let committee_size = + state.global_state.constants.parametric.consensus_committee_size + in + first_own_round_in_range + state.level_state.next_level_delegate_slots + ~committee_size + ~included_min:earliest_round + ~excluded_max:(earliest_round + committee_size) +(* If no own round is found between [earliest_round] included and + [earliest_round + committee_size] excluded, then we can stop + searching, because baking slots repeat themselves modulo the + [committee_size]. *) + +(** From the current [state], the function returns an optional + association pair, which consists of the next baking timestamp and + its baking round. In that case, an elected block must exist. *) +let compute_next_potential_baking_time_at_next_level state = + let open Lwt_syntax in + let open Protocol.Alpha_context in + let open Baking_state in + match state.level_state.elected_block with + | None -> return_none + | Some elected_block -> ( + let* () = + Events.( + emit + compute_next_timeout_elected_block + ( elected_block.proposal.block.shell.level, + elected_block.proposal.block.round )) + in + (* Do we have baking rights for the next level ? *) + (* Determine the round for the next level *) + let predecessor_timestamp = + elected_block.proposal.block.shell.timestamp + in + let predecessor_round = elected_block.proposal.block.round in + let now = Time.System.now () |> Time.System.to_protocol in + (* Lookup the next slot information if already stored in the + memoization table [Round_timestamp_interval_tbl]. *) + match + find_in_known_round_intervals + state.global_state.cache.round_timestamps + ~predecessor_timestamp + ~predecessor_round + ~now + with + | Some (first_potential_baking_time, first_potential_round, delegate) -> ( + (* Check if we already have proposed something at next + level *) + match state.level_state.next_level_proposed_round with + | Some proposed_round + when Round.(proposed_round >= first_potential_round) -> + let* () = Events.(emit proposal_already_injected ()) in + return_none + | None | Some _ -> + let* () = + Events.( + emit + next_potential_slot + ( Int32.succ state.level_state.current_level, + first_potential_round, + first_potential_baking_time, + delegate )) + in + return_some (first_potential_baking_time, first_potential_round)) + | None -> ( + let round_durations = state.global_state.round_durations in + (* Compute the timestamp at which the new level will start at + round 0.*) + Round.timestamp_of_round + round_durations + ~predecessor_timestamp + ~predecessor_round + ~round:Round.zero + |> function + | Error _ -> return_none + | Ok min_possible_time -> ( + (* If this timestamp exists and is not yet outdated, the + earliest round to bake is thereby 0. Otherwise, we + compute the round from the current timestamp. This + possibly means the baker has been late. *) + (if Time.Protocol.(now < min_possible_time) then Ok Round.zero + else + Environment.wrap_tzresult + @@ Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round + ~timestamp:now) + |> function + | Error _ -> return_none + | Ok earliest_round -> ( + (* There does not necessarily exists a slot that is + equal to [earliest_round]. We must find the earliest + slot after this value for which a validator is + designated to propose. *) + match + first_potential_round_at_next_level state ~earliest_round + with + | None -> return_none + | Some (first_potential_round, delegate) -> ( + (* Check if we already have proposed something at next + level. If so, we can skip. Otherwise, we recompute + the timestamp for the + [first_potential_round]. Finally, from this + [first_potential_baking_time], we can return. *) + match state.level_state.next_level_proposed_round with + | Some proposed_round + when Round.(proposed_round >= first_potential_round) -> + let* () = + Events.(emit proposal_already_injected ()) + in + return_none + | None | Some _ -> ( + timestamp_of_round + state + ~predecessor_timestamp + ~predecessor_round + ~round:first_potential_round + |> function + | Error _ -> return_none + | Ok first_potential_baking_time -> + let* () = + Events.( + emit + next_potential_slot + ( Int32.succ state.level_state.current_level, + first_potential_round, + first_potential_baking_time, + delegate )) + in + (* memoize this *) + let () = + let this_round_duration = + Round.round_duration + round_durations + first_potential_round + in + let end_first_potential_baking_time = + Timestamp.( + first_potential_baking_time + +? this_round_duration) + |> function + | Ok x -> x + | Error _ -> assert false + in + Baking_cache.( + Round_timestamp_interval_cache.replace + state.global_state.cache.round_timestamps + { + predecessor_timestamp; + predecessor_round; + time_interval = + ( first_potential_baking_time, + end_first_potential_baking_time ); + } + ( first_potential_baking_time, + first_potential_round, + delegate )) + in + return_some + ( first_potential_baking_time, + first_potential_round ))))))) + +(** From the current [state], the function returns an Lwt promise that + fulfills once the nearest timeout is expired and at which the state + machine will react. + + Both subfunctions [wait_baking_time] and [wait_end_of_round] are + using the blocking function + [Baking_scheduling.sleep_until]. However, this call is binded into + a Lwt promise. Hence, it just won't get fulfilled until sleep time + has elapsed. Once the promise is fulfilled, + [Baking_scheduling.wait_next_event] handles with [Lwt.choose] to + react and trigger event [Timeout]. *) +let compute_next_timeout state : Baking_state.timeout_kind Lwt.t tzresult Lwt.t + = + let open Lwt_result_syntax in + (* FIXME: this function (may) try to instantly repropose a block *) + let open Baking_state in + let wait_end_of_round ?(delta = 0L) (next_round_time, next_round) = + let next_time = Time.Protocol.add next_round_time delta in + let now = Time.System.now () in + let delay = Ptime.diff (Time.System.of_protocol_exn next_time) now in + let current_round = Int32.pred @@ Round.to_int32 next_round in + let*! () = + if delta = 0L then + Events.(emit waiting_end_of_round (delay, current_round, next_time)) + else + Events.( + emit + waiting_delayed_end_of_round + (delay, current_round, next_time, delta)) + in + let end_of_round = + Lwt.return + @@ End_of_round {ending_round = state.round_state.current_round} + in + match sleep_until next_time with + | None -> return end_of_round + | Some t -> + return + (let*! () = t in + end_of_round) + in + let wait_baking_time_next_level (next_baking_time, next_baking_round) = + let now = Time.System.now () in + let delay = Ptime.diff (Time.System.of_protocol_exn next_baking_time) now in + match sleep_until next_baking_time with + | None -> + let*! () = Events.(emit no_need_to_wait_for_proposal ()) in + return + (Lwt.return + (Time_to_prepare_next_level_block {at_round = next_baking_round})) + | Some t -> + let*! () = + Events.(emit waiting_time_to_bake (delay, next_baking_time)) + in + return + (let*! () = t in + Lwt.return + (Time_to_prepare_next_level_block {at_round = next_baking_round})) + in + let delay_next_round_timeout next_round = + (* we only delay if it's our turn to bake *) + match round_proposer state ~level:`Current (snd next_round) with + | Some _ -> + let delta = + state.global_state.constants.parametric.minimal_block_delay + |> Period.to_seconds + |> fun d -> Int64.div d 5L + in + (* NB: this means 6 seconds delay, if the first round duration is + 30. *) + wait_end_of_round ~delta next_round + | None -> wait_end_of_round next_round + in + let should_wait_to_forge_block (_next_baking_time, next_baking_round) = + Option.is_some state.level_state.elected_block + && Round.equal next_baking_round Round.zero + in + let waiting_to_forge_block (next_baking_time, next_baking_round) = + let*! () = Events.(emit first_baker_of_next_level ()) in + let now = Time.System.now () in + let next_baking_ptime = Time.System.of_protocol_exn next_baking_time in + let pre_emptive_forge_time = + state.global_state.config.pre_emptive_forge_time + in + let next_forging_ptime = + match Ptime.sub_span next_baking_ptime pre_emptive_forge_time with + | Some ptime -> ptime + | None -> + (* This branch can only be reached if the Ptime operations above + fail. In practice, it should be unreachable. *) + assert false + in + let delay = Ptime.diff next_forging_ptime now in + match sleep_until_ptime next_forging_ptime with + | None -> + let*! () = Events.(emit no_need_to_wait_to_forge_block ()) in + return + (Lwt.return + (Time_to_prepare_next_level_block {at_round = next_baking_round})) + | Some t -> + let*! () = + Events.( + emit + waiting_to_forge_block + (delay, Time.System.to_protocol next_forging_ptime)) + in + return + (let*! () = t in + Lwt.return + (Time_to_prepare_next_level_block {at_round = next_baking_round})) + in + (* TODO: re-use what has been done in round_synchronizer.ml *) + (* Compute the timestamp of the next possible round. *) + let next_round = compute_next_round_time state in + let*! next_baking = compute_next_potential_baking_time_at_next_level state in + match (next_round, next_baking) with + | None, None -> + let*! () = Events.(emit waiting_for_new_head ()) in + return + (let*! () = Lwt_utils.never_ending () in + assert false) + (* We have no slot at the next level in the near future, we will + patiently wait for the next round. *) + | Some next_round, None -> ( + (* If there is an elected block, then we make the assumption + that the bakers at the next level have also received an + attestation quorum, and we delay a bit injecting at the next + round, so that there are not two blocks injected at the same + time. *) + match state.level_state.elected_block with + | None -> wait_end_of_round next_round + | Some _elected_block -> delay_next_round_timeout next_round) + (* There is no timestamp for a successor round but there is for a + future baking slot. If we are the next level baker at round 0, + quorum has been reached for this level, and no block being forged, + we will wait to forge, otherwise we will wait to bake *) + | None, Some next_baking -> + if should_wait_to_forge_block next_baking then + waiting_to_forge_block next_baking + else wait_baking_time_next_level next_baking + (* We choose the earliest timestamp between waiting to bake and + waiting for the next round. *) + | ( Some ((next_round_time, next_round) as next_round_info), + Some ((next_baking_time, _) as next_baking) ) -> + (* If we can bake at the next level before the end of the next + round, then do so. This is because the proposed block will have + a smaller timestamp than the earliest block at next level built + on top of the proposal made at the next round (at the current + level). *) + let round_durations = state.global_state.round_durations in + let next_round_duration = + Round.round_duration round_durations next_round |> Period.to_seconds + in + if + Time.Protocol.( + next_baking_time < add next_round_time next_round_duration) + then + if should_wait_to_forge_block next_baking then + waiting_to_forge_block next_baking + else wait_baking_time_next_level next_baking + else + (* same observation is in the [(Some next_round, None)] case *) + delay_next_round_timeout next_round_info + +(* initialises attestable_payload with the PQC included in the latest block + if there is one and if it's more recent than the one loaded from disk + if any *) +let may_initialise_with_latest_proposal_pqc state = + let open Lwt_result_syntax in + let p = state.level_state.latest_proposal in + match p.block.prequorum with + | None -> return state + | Some pqc -> ( + match state.level_state.attestable_payload with + | Some ep when ep.prequorum.round >= pqc.round -> + (*do not change the attestable_payload loaded from disk if it's + more recent *) + return state + | Some _ | None -> + return + { + state with + level_state = + { + state.level_state with + attestable_payload = Some {prequorum = pqc; proposal = p}; + }; + }) + +let create_round_durations constants = + let first_round_duration = + constants.Constants.parametric.minimal_block_delay + in + let delay_increment_per_round = + constants.parametric.delay_increment_per_round + in + Environment.wrap_tzresult + (Round.Durations.create ~first_round_duration ~delay_increment_per_round) + +let create_dal_node_rpc_ctxt endpoint = + let open Tezos_rpc_http_client_unix in + let rpc_config = + {Tezos_rpc_http_client_unix.RPC_client_unix.default_config with endpoint} + in + let media_types = + Tezos_rpc_http.Media_type.Command_line.of_command_line rpc_config.media_type + in + new RPC_client_unix.http_ctxt rpc_config media_types + +let create_initial_state cctxt ?(synchronize = true) ~chain config + operation_worker ~(current_proposal : Baking_state.proposal) ?constants + delegates = + let open Lwt_result_syntax in + (* FIXME? consider saved attestable value *) + let open Protocol in + let open Baking_state in + let* chain_id = Shell_services.Chain.chain_id cctxt ~chain () in + let* constants = + match constants with + | Some c -> return c + | None -> Alpha_services.Constants.all cctxt (`Hash chain_id, `Head 0) + in + let*? round_durations = create_round_durations constants in + let* validation_mode = + Baking_state.( + match config.Baking_configuration.validation with + | Node -> return Node + | Local {context_path} -> + let* index = Baking_simulator.load_context ~context_path in + return (Local index) + | ContextIndex index -> return (Local index)) + in + let cache = Baking_state.create_cache () in + let global_state = + { + cctxt; + chain_id; + config; + constants; + round_durations; + operation_worker; + forge_worker_hooks = + { + push_request = (fun _ -> assert false); + get_forge_event_stream = (fun _ -> assert false); + cancel_all_pending_tasks = (fun _ -> assert false); + }; + validation_mode; + delegates; + cache; + dal_node_rpc_ctxt = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4674 + Treat case when no endpoint was given and DAL is enabled *) + Option.map create_dal_node_rpc_ctxt config.dal_node_endpoint; + } + in + (* Trick to provide the global state to the forge worker without + introducing a circular dependency. *) + let forge_worker = Forge_worker.start global_state in + global_state.forge_worker_hooks <- + { + push_request = Forge_worker.push_request forge_worker; + get_forge_event_stream = + (fun () -> Forge_worker.get_event_stream forge_worker); + cancel_all_pending_tasks = + (fun () -> Forge_worker.cancel_all_pending_tasks forge_worker); + } ; + let chain = `Hash chain_id in + let current_level = current_proposal.block.shell.level in + let* delegate_slots = + Baking_state.compute_delegate_slots + cctxt + delegates + ~level:current_level + ~chain + in + let* next_level_delegate_slots = + Baking_state.compute_delegate_slots + cctxt + delegates + ~level:(Int32.succ current_level) + ~chain + in + let elected_block = + if Baking_state.is_first_block_in_protocol current_proposal then + (* If the last block is a protocol transition, we admit it as a + final block *) + Some {proposal = current_proposal; attestation_qc = []} + else None + in + let level_state = + { + current_level = current_proposal.block.shell.level; + latest_proposal = current_proposal; + is_latest_proposal_applied = + true (* this proposal is expected to be the current head *); + locked_round = None; + attestable_payload = None; + elected_block; + delegate_slots; + next_level_delegate_slots; + next_level_proposed_round = None; + } + in + let* round_state = + if synchronize then + let*? round_durations = create_round_durations constants in + let*? current_round = + Baking_actions.compute_round current_proposal round_durations + in + return + { + current_round; + current_phase = Idle; + delayed_quorum = None; + early_attestations = []; + awaiting_unlocking_pqc = false; + } + else + return + { + Baking_state.current_round = Round.zero; + current_phase = Idle; + delayed_quorum = None; + early_attestations = []; + awaiting_unlocking_pqc = false; + } + in + let state = {global_state; level_state; round_state} in + (* Try loading locked round and attestable round from disk *) + let* state = Baking_state.may_load_attestable_data state in + may_initialise_with_latest_proposal_pqc state + +let compute_bootstrap_event state = + let open Result_syntax in + let open Baking_state in + (* Check if we are in the current round *) + if + Round.( + state.level_state.latest_proposal.block.round + = state.round_state.current_round) + then + (* If so, then trigger the new proposal event to possibly preattest *) + return @@ Baking_state.New_head_proposal state.level_state.latest_proposal + else + (* Otherwise, trigger the end of round to check whether we + need to propose at this level or not *) + let* ending_round = + Environment.wrap_tzresult @@ Round.pred state.round_state.current_round + in + return @@ Baking_state.Timeout (End_of_round {ending_round}) + +let rec automaton_loop ?(stop_on_event = fun _ -> false) ~config ~on_error + loop_state state event = + let open Lwt_result_syntax in + let state_recorder ~new_state = + match config.Baking_configuration.state_recorder with + | Baking_configuration.Filesystem -> + Baking_state.may_record_new_state ~previous_state:state ~new_state + | Baking_configuration.Memory -> return_unit + in + let*! state', action = State_transitions.step state event in + let* state'' = + let*! state_res = + let* state'' = Baking_actions.perform_action state' action in + let* () = may_record_new_state ~previous_state:state ~new_state:state'' in + return state'' + in + match state_res with + | Ok state'' -> return state'' + | Error error -> + let* () = on_error error in + (* Still try to record the intermediate state; ignore potential + errors. *) + let*! _ = state_recorder ~new_state:state' in + return state' + in + let* next_timeout = compute_next_timeout state'' in + let* event_opt = + wait_next_event + ~timeout: + (let*! e = next_timeout in + Lwt.return (`Timeout e)) + loop_state + in + match event_opt with + | None -> + (* Termination *) + return_none + | Some event -> + if stop_on_event event then return_some event + else + automaton_loop ~stop_on_event ~config ~on_error loop_state state'' event + +let perform_sanity_check cctxt ~chain_id = + let open Lwt_result_syntax in + let open Baking_errors in + let prefix_base_dir f = Filename.Infix.(cctxt#get_base_dir // f) in + let stateful_location = + Baking_files.resolve_location ~chain_id `Stateful_nonce + in + let* _ = + Baking_nonces.load cctxt ~stateful_location + |> trace + (Cannot_load_local_file + (prefix_base_dir (Baking_files.filename stateful_location) ^ "s")) + in + let highwatermarks_location = + Baking_files.resolve_location ~chain_id `Highwatermarks + in + let* _ = + Baking_highwatermarks.load cctxt highwatermarks_location + |> trace + (Cannot_load_local_file + (prefix_base_dir (Baking_files.filename highwatermarks_location) + ^ "s")) + in + let state_location = Baking_files.resolve_location ~chain_id `State in + let* _ = + Baking_state.load_attestable_data cctxt state_location + |> trace + (Cannot_load_local_file + (prefix_base_dir (Baking_files.filename state_location))) + in + return_unit + +let rec retry (cctxt : #Protocol_client_context.full) ?max_delay ~delay ~factor + ~tries ?(msg = "Connection failed. ") f x = + let open Lwt_result_syntax in + let*! result = f x in + match result with + | Ok _ as r -> Lwt.return r + | Error + (RPC_client_errors.Request_failed {error = Connection_failed _; _} :: _) + as err + when tries > 0 -> ( + let*! () = cctxt#message "%sRetrying in %.2f seconds..." msg delay in + let*! result = + Lwt.pick + [ + (let*! () = Lwt_unix.sleep delay in + Lwt.return `Continue); + (let*! _ = Lwt_exit.clean_up_starts in + Lwt.return `Killed); + ] + in + match result with + | `Killed -> Lwt.return err + | `Continue -> + let next_delay = delay *. factor in + let delay = + Option.fold + ~none:next_delay + ~some:(fun max_delay -> Float.min next_delay max_delay) + max_delay + in + retry cctxt ?max_delay ~delay ~factor ~msg ~tries:(tries - 1) f x) + | Error _ as err -> Lwt.return err + +let register_dal_profiles cctxt dal_node_rpc_ctxt delegates = + Option.iter_es + (fun dal_ctxt -> + retry + cctxt + ~max_delay:2. + ~delay:1. + ~factor:2. + ~tries:max_int + ~msg:"Failed to register profiles, DAL node is not reachable. " + (fun () -> Node_rpc.register_dal_profiles dal_ctxt delegates) + ()) + dal_node_rpc_ctxt + +let run cctxt ?canceler ?(stop_on_event = fun _ -> false) + ?(on_error = fun _ -> Lwt_result_syntax.return_unit) ?constants ~chain + config delegates = + let open Lwt_result_syntax in + let* chain_id = Shell_services.Chain.chain_id cctxt ~chain () in + let* () = perform_sanity_check cctxt ~chain_id in + let cache = Baking_cache.Block_cache.create 10 in + let* heads_stream, _block_stream_stopper = + Node_rpc.monitor_heads cctxt ~cache ~chain () + in + let* current_proposal = + let*! proposal = Lwt_stream.get heads_stream in + match proposal with + | Some current_head -> return current_head + | None -> failwith "head stream unexpectedly ended" + in + let*! operation_worker = Operation_worker.create cctxt in + Option.iter + (fun canceler -> + Lwt_canceler.on_cancel canceler (fun () -> + let*! _ = Operation_worker.shutdown_worker operation_worker in + Lwt.return_unit)) + canceler ; + let* initial_state = + create_initial_state + cctxt + ~chain + config + operation_worker + ~current_proposal + ?constants + delegates + in + let _promise = + register_dal_profiles + cctxt + initial_state.global_state.dal_node_rpc_ctxt + delegates + in + let cloned_block_stream = Lwt_stream.clone heads_stream in + let*! revelation_worker_canceler = + Baking_nonces.start_revelation_worker + cctxt + initial_state.global_state.config.nonce + initial_state.global_state.chain_id + initial_state.global_state.constants + cloned_block_stream + in + Option.iter + (fun canceler -> + Lwt_canceler.on_cancel canceler (fun () -> + let*! _ = Lwt_canceler.cancel revelation_worker_canceler in + Lwt.return_unit)) + canceler ; + (* FIXME: currently, the client streamed RPC call will hold until at + least one element is present in the stream. This is fixed by: + https://gitlab.com/nomadic-labs/resto/-/merge_requests/50. Until + then, we await the promise completion of the RPC call later + on. *) + let get_valid_blocks_stream = + let*! vbs = Node_rpc.monitor_valid_proposals cctxt ~cache ~chain () in + match vbs with + | Error _ -> Stdlib.failwith "Failed to get the validated blocks stream" + | Ok (vbs, _) -> Lwt.return vbs + in + let forge_event_stream = + initial_state.global_state.forge_worker_hooks.get_forge_event_stream () + in + let loop_state = + create_loop_state + ~get_valid_blocks_stream + ~forge_event_stream + ~heads_stream + initial_state.global_state.operation_worker + in + let on_error err = + let*! () = Events.(emit error_while_baking err) in + (* TODO? retry a bounded number of time *) + (* let retries = config.Baking_configuration.retries_on_failure in *) + on_error err + in + let*? initial_event = compute_bootstrap_event initial_state in + protect + ~on_error:(fun err -> + let*! _ = Option.iter_es Lwt_canceler.cancel canceler in + Lwt.return_error err) + (fun () -> + let* _ignored_event = + automaton_loop + ~stop_on_event + ~config + ~on_error + loop_state + initial_state + initial_event + in + return_unit) diff --git a/src/proto_020_PsParisC/lib_delegate/baking_scheduling.mli b/src/proto_020_PsParisC/lib_delegate/baking_scheduling.mli new file mode 100644 index 000000000000..948cc995a19a --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_scheduling.mli @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Baking_state +open Protocol.Alpha_context + +type loop_state + +val create_loop_state : + ?get_valid_blocks_stream:proposal Lwt_stream.t Lwt.t -> + heads_stream:proposal Lwt_stream.t -> + forge_event_stream:forge_event Lwt_stream.t -> + Operation_worker.t -> + loop_state + +val sleep_until : Time.Protocol.t -> unit Lwt.t option + +(** [retry ctxt ~delay ?max_delay ~factor ~tries ?msg f x] retries applying [f + x] [tries] until it succeeds or returns an error different from + [Connection_failed], at most [tries] number of times. After each try it + waits for a number of seconds, but not more than [max_delay], if given. The + wait time between tries is given by the initial [delay], multiplied by + [factor] at each subsequent try. At each failure, [msg] together with the + current delay is printed using [ctxt#message].*) +val retry : + #Protocol_client_context.full -> + ?max_delay:float -> + delay:float -> + factor:float -> + tries:int -> + ?msg:string -> + ('a -> 'b tzresult Lwt.t) -> + 'a -> + 'b tzresult Lwt.t + +(** An event monitor using the streams in [loop_state] (to create + promises) and a timeout promise [timeout]. The function reacts to a + promise being fulfilled by firing an event [Baking_state.event]. *) +val wait_next_event : + timeout:[`Timeout of timeout_kind] Lwt.t -> + loop_state -> + (event option, error trace) result Lwt.t + +(** Returns the first round at the next level, at or after + [earliest_round], whose baking slot belongs to one of our own + delegates; also returns the corresponding delegate. Or returns + [None] if no such round exists. *) +val first_potential_round_at_next_level : + state -> + earliest_round:Round.t -> + (Round.t * consensus_key_and_delegate) option + +val compute_next_potential_baking_time_at_next_level : + state -> (Time.Protocol.t * Round.t) option Lwt.t + +val compute_next_timeout : state -> timeout_kind Lwt.t tzresult Lwt.t + +val create_initial_state : + Protocol_client_context.full -> + ?synchronize:bool -> + chain:Chain_services.chain -> + Baking_configuration.t -> + Operation_worker.t -> + current_proposal:proposal -> + ?constants:Constants.t -> + consensus_key list -> + state tzresult Lwt.t + +val compute_bootstrap_event : state -> event tzresult + +val automaton_loop : + ?stop_on_event:(event -> bool) -> + config:Baking_configuration.t -> + on_error:(tztrace -> (unit, tztrace) result Lwt.t) -> + loop_state -> + state -> + event -> + event option tzresult Lwt.t + +val run : + Protocol_client_context.full -> + ?canceler:Lwt_canceler.t -> + ?stop_on_event:(event -> bool) -> + ?on_error:(tztrace -> unit tzresult Lwt.t) -> + ?constants:Constants.t -> + chain:Chain_services.chain -> + Baking_configuration.t -> + consensus_key list -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_simulator.ml b/src/proto_020_PsParisC/lib_delegate/baking_simulator.ml new file mode 100644 index 000000000000..4184b4033f0d --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_simulator.ml @@ -0,0 +1,172 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_errors + +type incremental = { + predecessor : Baking_state.block_info; + context : Tezos_protocol_environment.Context.t; + state : Protocol.validation_state * Protocol.application_state option; + rev_operations : Operation.packed list; + header : Tezos_base.Block_header.shell_header; +} + +let load_context ~context_path = + let open Lwt_result_syntax in + protect (fun () -> + let*! index = Context.init ~readonly:true context_path in + return (Abstract_context_index.abstract index)) + +let check_context_consistency (abstract_index : Abstract_context_index.t) + context_hash = + let open Lwt_result_syntax in + protect (fun () -> + (* Hypothesis : the version key exists *) + let version_key = ["version"] in + let*! context_opt = abstract_index.checkout_fun context_hash in + match context_opt with + | None -> tzfail Failed_to_checkout_context + | Some context -> ( + let*! result = Context_ops.mem context version_key in + match result with + | true -> return_unit + | false -> tzfail Invalid_context)) + +let begin_construction ~timestamp ~protocol_data ~force_apply + ~pred_resulting_context_hash (abstract_index : Abstract_context_index.t) + pred_block chain_id = + let open Lwt_result_syntax in + protect (fun () -> + let {Baking_state.shell = pred_shell; hash = pred_hash; _} = pred_block in + let*! context_opt = + abstract_index.checkout_fun pred_resulting_context_hash + in + match context_opt with + | None -> tzfail Failed_to_checkout_context + | Some context -> + let header : Tezos_base.Block_header.shell_header = + Tezos_base.Block_header. + { + predecessor = pred_hash; + proto_level = pred_shell.proto_level; + validation_passes = 0; + fitness = pred_shell.fitness; + timestamp; + level = pred_shell.level; + context = Context_hash.zero (* fake context hash *); + operations_hash = + Operation_list_list_hash.zero (* fake op hash *); + } + in + let mode = + Lifted_protocol.Construction + { + predecessor_hash = pred_hash; + timestamp; + block_header_data = protocol_data; + } + in + let* validation_state = + Lifted_protocol.begin_validation + context + chain_id + mode + ~predecessor:pred_shell + ~cache:`Lazy + in + let* application_state = + if force_apply then + let* application_state = + Lifted_protocol.begin_application + context + chain_id + mode + ~predecessor:pred_shell + ~cache:`Lazy + in + return_some application_state + else return_none + in + let state = (validation_state, application_state) in + return + { + predecessor = pred_block; + context; + state; + rev_operations = []; + header; + }) + +let ( let** ) x k = + let open Lwt_result_syntax in + let*! x in + let*? x = Environment.wrap_tzresult x in + k x + +let add_operation st (op : Operation.packed) = + let open Lwt_result_syntax in + protect (fun () -> + let validation_state, application_state = st.state in + let oph = Operation.hash_packed op in + let** validation_state = + Protocol.validate_operation + ~check_signature:false + (* We assume that the operation has already been validated in the + node, therefore the signature has already been checked, but we + still need to validate it again because the context may be + different. *) + validation_state + oph + op + in + let** application_state, receipt = + match application_state with + | Some application_state -> + let* application_state, receipt = + Protocol.apply_operation application_state oph op + in + return (Some application_state, Some receipt) + | None -> return (None, None) + in + let state = (validation_state, application_state) in + return ({st with state; rev_operations = op :: st.rev_operations}, receipt)) + +let finalize_construction inc = + let open Lwt_result_syntax in + protect (fun () -> + let validation_state, application_state = inc.state in + let** () = Protocol.finalize_validation validation_state in + let** result = + match application_state with + | Some application_state -> + let* result = + Protocol.finalize_application application_state (Some inc.header) + in + return_some result + | None -> return_none + in + return result) diff --git a/src/proto_020_PsParisC/lib_delegate/baking_simulator.mli b/src/proto_020_PsParisC/lib_delegate/baking_simulator.mli new file mode 100644 index 000000000000..c5155ac45ee0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_simulator.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type incremental = { + predecessor : Baking_state.block_info; + context : Tezos_protocol_environment.Context.t; + state : validation_state * application_state option; + rev_operations : Operation.packed list; + header : Tezos_base.Block_header.shell_header; +} + +val load_context : + context_path:string -> Abstract_context_index.t tzresult Lwt.t + +(** Make sure that the given context is consistent by trying to read in it *) +val check_context_consistency : + Abstract_context_index.t -> Context_hash.t -> unit tzresult Lwt.t + +(** [begin_construction ~timestamp ~protocol_data ~force_apply abstract_context + predecessor chain_id] creates a new [incremental] value with an empty + operation list. A [context] is recovered from the [abstract_index] and the + resulting_context_hash from [predecessor]. This context is used to create a + [validation_state] and an [application_state] (if [force_apply] is set). A + partial [shell_header] is created from [predecessor] information and + [timestamp]. *) +val begin_construction : + timestamp:Time.Protocol.t -> + protocol_data:block_header_data -> + force_apply:bool -> + pred_resulting_context_hash:Context_hash.t -> + Abstract_context_index.t -> + Baking_state.block_info -> + Chain_id.t -> + incremental tzresult Lwt.t + +(** [add_operation incremental op] validates [op] in + [incremental.validation_state] without checking its signature. Indeed, the + operation has already been validated in the node so it has a correct + signature. We still need to validate it again because the context may be + different. [op] is also applied if [incremental] has been created with + [force_apply] set. This function returns an [incremental] with updated + operations list and [validation_state] (and [application_state]). *) +val add_operation : + incremental -> + Operation.packed -> + (incremental * operation_receipt option) tzresult Lwt.t + +(** [finalize_construction incremental] calls the [finalize_validation] of the + protocol on the [validation_state] from [incremental]. If [incremental] has + been created with [force_apply] set, [finalize_application] is also called + and its results returned. *) +val finalize_construction : + incremental -> + (Tezos_protocol_environment.validation_result * block_header_metadata) option + tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/baking_state.ml b/src/proto_020_PsParisC/lib_delegate/baking_state.ml new file mode 100644 index 000000000000..fb1384c1c727 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_state.ml @@ -0,0 +1,1392 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_errors + +(** A consensus key (aka, a validator) is identified by its alias name, its + public key, its public key hash, and its secret key. *) +type consensus_key = { + alias : string option; + public_key : Signature.Public_key.t; + public_key_hash : Signature.Public_key_hash.t; + secret_key_uri : Client_keys.sk_uri; +} + +let consensus_key_encoding = + let open Data_encoding in + conv + (fun {alias; public_key; public_key_hash; secret_key_uri} -> + ( alias, + public_key, + public_key_hash, + Uri.to_string (secret_key_uri :> Uri.t) )) + (fun (alias, public_key, public_key_hash, secret_key_uri) -> + { + alias; + public_key; + public_key_hash; + secret_key_uri = + (match Client_keys.make_sk_uri (Uri.of_string secret_key_uri) with + | Ok sk -> sk + | Error e -> Format.kasprintf Stdlib.failwith "%a" pp_print_trace e); + }) + (obj4 + (req "alias" (option string)) + (req "public_key" Signature.Public_key.encoding) + (req "public_key_hash" Signature.Public_key_hash.encoding) + (req "secret_key_uri" string)) + +let pp_consensus_key fmt {alias; public_key_hash; _} = + match alias with + | None -> Format.fprintf fmt "%a" Signature.Public_key_hash.pp public_key_hash + | Some alias -> + Format.fprintf + fmt + "%s (%a)" + alias + Signature.Public_key_hash.pp + public_key_hash + +type consensus_key_and_delegate = consensus_key * Signature.Public_key_hash.t + +let consensus_key_and_delegate_encoding = + let open Data_encoding in + merge_objs + consensus_key_encoding + (obj1 (req "delegate" Signature.Public_key_hash.encoding)) + +let pp_consensus_key_and_delegate fmt (consensus_key, delegate) = + if Signature.Public_key_hash.equal consensus_key.public_key_hash delegate then + pp_consensus_key fmt consensus_key + else + Format.fprintf + fmt + "%a@,on behalf of %a" + pp_consensus_key + consensus_key + Signature.Public_key_hash.pp + delegate + +type validation_mode = Node | Local of Abstract_context_index.t + +type prequorum = { + level : int32; + round : Round.t; + block_payload_hash : Block_payload_hash.t; + preattestations : Kind.preattestation operation list; +} + +type block_info = { + hash : Block_hash.t; + shell : Block_header.shell_header; + payload_hash : Block_payload_hash.t; + payload_round : Round.t; + round : Round.t; + prequorum : prequorum option; + quorum : Kind.attestation operation list; + payload : Operation_pool.payload; +} + +type cache = { + known_timestamps : Timestamp.time Baking_cache.Timestamp_of_round_cache.t; + round_timestamps : + (Timestamp.time * Round.t * consensus_key_and_delegate) + Baking_cache.Round_timestamp_interval_cache.t; +} + +let prequorum_encoding = + let open Data_encoding in + conv + (fun {level; round; block_payload_hash; preattestations} -> + (level, round, block_payload_hash, List.map Operation.pack preattestations)) + (fun (level, round, block_payload_hash, preattestations) -> + { + level; + round; + block_payload_hash; + preattestations = + List.filter_map Operation_pool.unpack_preattestation preattestations; + }) + (obj4 + (req "level" int32) + (req "round" Round.encoding) + (req "block_payload_hash" Block_payload_hash.encoding) + (req "preattestations" (list (dynamic_size Operation.encoding)))) + +let block_info_encoding = + let open Data_encoding in + conv + (fun { + hash; + shell; + payload_hash; + payload_round; + round; + prequorum; + quorum; + payload; + } -> + ( hash, + shell, + payload_hash, + payload_round, + round, + prequorum, + List.map Operation.pack quorum, + payload )) + (fun ( hash, + shell, + payload_hash, + payload_round, + round, + prequorum, + quorum, + payload ) -> + { + hash; + shell; + payload_hash; + payload_round; + round; + prequorum; + quorum = List.filter_map Operation_pool.unpack_attestation quorum; + payload; + }) + (obj8 + (req "hash" Block_hash.encoding) + (req "shell" Block_header.shell_header_encoding) + (req "payload_hash" Block_payload_hash.encoding) + (req "payload_round" Round.encoding) + (req "round" Round.encoding) + (req "prequorum" (option prequorum_encoding)) + (req "quorum" (list (dynamic_size Operation.encoding))) + (req "payload" Operation_pool.payload_encoding)) + +let round_of_shell_header shell_header = + let open Result_syntax in + let* fitness = + Environment.wrap_tzresult + @@ Fitness.from_raw shell_header.Tezos_base.Block_header.fitness + in + return (Fitness.round fitness) + +module SlotMap : Map.S with type key = Slot.t = Map.Make (Slot) + +type delegate_slot = { + consensus_key_and_delegate : consensus_key_and_delegate; + first_slot : Slot.t; + attesting_power : int; +} + +module Delegate_slots = struct + (* Note that we also use the delegate slots as proposal slots. *) + type t = { + own_delegates : delegate_slot list; + own_delegate_slots : delegate_slot SlotMap.t; + (* This map cannot have as keys just the first slot of delegates, + because it is used in [round_proposer] for which we need all slots, + as the round can be arbitrary. *) + all_delegate_voting_power : int SlotMap.t; + (* This is a map having as keys the first slot of all delegates, and as + values their attesting power. + This map contains just the first slot for a delegate, because it is + only used in [slot_voting_power] which is about (pre)attestations, + not proposals. Indeed, only (pre)attestations that use the delegate's + first slot are valid for inclusion in a block and count toward the + (pre)quorum. Note that the baker might receive nominally valid + non-first-slot operations from the mempool because this check is + skipped in the mempool to increase its speed; the baker can and + should ignore such operations. *) + } + + let own_delegates slots = slots.own_delegates + + let own_slot_owner slots ~slot = SlotMap.find slot slots.own_delegate_slots + + let voting_power slots ~slot = + SlotMap.find slot slots.all_delegate_voting_power +end + +type delegate_slots = Delegate_slots.t + +type proposal = {block : block_info; predecessor : block_info} + +let proposal_encoding = + let open Data_encoding in + conv + (fun {block; predecessor} -> (block, predecessor)) + (fun (block, predecessor) -> {block; predecessor}) + (obj2 + (req "block" block_info_encoding) + (req "predecessor" block_info_encoding)) + +let is_first_block_in_protocol {block; predecessor; _} = + Compare.Int.(block.shell.proto_level <> predecessor.shell.proto_level) + +type locked_round = {payload_hash : Block_payload_hash.t; round : Round.t} + +let locked_round_encoding = + let open Data_encoding in + conv + (fun {payload_hash; round} -> (payload_hash, round)) + (fun (payload_hash, round) -> {payload_hash; round}) + (obj2 + (req "payload_hash" Block_payload_hash.encoding) + (req "round" Round.encoding)) + +type attestable_payload = {proposal : proposal; prequorum : prequorum} + +let attestable_payload_encoding = + let open Data_encoding in + conv + (fun {proposal; prequorum} -> (proposal, prequorum)) + (fun (proposal, prequorum) -> {proposal; prequorum}) + (obj2 + (req "proposal" proposal_encoding) + (req "prequorum" prequorum_encoding)) + +type elected_block = { + proposal : proposal; + attestation_qc : Kind.attestation Operation.t list; +} + +type prepared_block = { + signed_block_header : block_header; + round : Round.t; + delegate : consensus_key_and_delegate; + operations : Tezos_base.Operation.t list list; + baking_votes : Per_block_votes_repr.per_block_votes; +} + +(* The fields {current_level}, {delegate_slots}, {next_level_delegate_slots}, + {next_level_proposed_round} are updated only when we receive a block at a + different level than {current_level}. Note that this means that there is + always a {latest_proposal}, which may be our own baked block. *) +type level_state = { + current_level : int32; + latest_proposal : proposal; + is_latest_proposal_applied : bool; + (* Last proposal received where we injected an attestation (thus we + have seen 2f+1 preattestations) *) + locked_round : locked_round option; + (* Latest payload where we've seen a proposal reach 2f+1 preattestations *) + attestable_payload : attestable_payload option; + (* Block for which we've seen 2f+1 attestations and that we may bake onto *) + elected_block : elected_block option; + delegate_slots : delegate_slots; + next_level_delegate_slots : delegate_slots; + next_level_proposed_round : Round.t option; +} + +type phase = + | Idle + | Awaiting_preattestations + | Awaiting_attestations + | Awaiting_application + +let phase_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Idle" + (Tag 0) + (constant "Idle") + (function Idle -> Some () | _ -> None) + (fun () -> Idle); + case + ~title:"Awaiting_preattestations" + (Tag 1) + (constant "Awaiting_preattestations") + (function Awaiting_preattestations -> Some () | _ -> None) + (fun () -> Awaiting_preattestations); + case + ~title:"Awaiting_application" + (Tag 2) + (constant "Awaiting_application") + (function Awaiting_application -> Some () | _ -> None) + (fun () -> Awaiting_application); + case + ~title:"Awaiting_attestationss" + (Tag 3) + (constant "Awaiting_attestationss") + (function Awaiting_attestations -> Some () | _ -> None) + (fun () -> Awaiting_attestations); + ] + +type block_kind = + | Fresh of Operation_pool.pool + | Reproposal of { + consensus_operations : packed_operation list; + payload_hash : Block_payload_hash.t; + payload_round : Round.t; + payload : Operation_pool.payload; + } + +type block_to_bake = { + predecessor : block_info; + round : Round.t; + delegate : consensus_key_and_delegate; + kind : block_kind; + force_apply : bool; +} + +type consensus_vote_kind = Attestation | Preattestation + +let consensus_vote_kind_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"preattestation" + unit + (function Preattestation -> Some () | _ -> None) + (fun () -> Preattestation); + case + (Tag 1) + ~title:"attestation" + unit + (function Attestation -> Some () | _ -> None) + (fun () -> Attestation); + ] + +let pp_consensus_vote_kind fmt = function + | Attestation -> Format.fprintf fmt "attestation" + | Preattestation -> Format.fprintf fmt "preattestation" + +type unsigned_consensus_vote = { + vote_kind : consensus_vote_kind; + vote_consensus_content : consensus_content; + delegate : consensus_key_and_delegate; + dal_content : dal_content option; +} + +type batch_content = { + level : Raw_level.t; + round : Round.t; + block_payload_hash : Block_payload_hash.t; +} + +type unsigned_consensus_vote_batch = { + batch_kind : consensus_vote_kind; + batch_content : batch_content; + batch_branch : Block_hash.t; + unsigned_consensus_votes : unsigned_consensus_vote list; +} + +let make_unsigned_consensus_vote_batch kind + ({level; round; block_payload_hash} as batch_content) ~batch_branch + delegates_and_slots = + let unsigned_consensus_votes = + List.map + (fun (delegate, slot) -> + let consensus_content = {level; round; slot; block_payload_hash} in + { + vote_kind = kind; + vote_consensus_content = consensus_content; + delegate; + dal_content = None; + }) + delegates_and_slots + in + {batch_kind = kind; batch_branch; batch_content; unsigned_consensus_votes} + +let dal_content_map_p f unsigned_consensus_vote_batch = + let open Lwt_syntax in + let* patched_unsigned_consensus_votes = + List.map_p + (fun unsigned_consensus_vote -> + let fallback_case = + { + unsigned_consensus_vote with + dal_content = Some {attestation = Dal.Attestation.empty}; + } + in + Lwt.catch + (fun () -> + let* dal_content = f unsigned_consensus_vote in + match dal_content with + | Ok dal_content -> + return {unsigned_consensus_vote with dal_content} + | Error _ -> return fallback_case) + (fun _exn -> return fallback_case)) + unsigned_consensus_vote_batch.unsigned_consensus_votes + in + return + { + unsigned_consensus_vote_batch with + unsigned_consensus_votes = patched_unsigned_consensus_votes; + } + +type signed_consensus_vote = { + unsigned_consensus_vote : unsigned_consensus_vote; + signed_operation : packed_operation; +} + +type signed_consensus_vote_batch = { + batch_kind : consensus_vote_kind; + batch_content : batch_content; + batch_branch : Block_hash.t; + signed_consensus_votes : signed_consensus_vote list; +} + +type error += Mismatch_signed_consensus_vote_in_batch + +let () = + register_error_kind + `Permanent + ~id:"Baking_state.mismatch_signed_consensus_vote_in_batch" + ~title:"Mismatch signed consensus vote in batch" + ~description:"Consensus votes mismatch while creating a batch." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "There are batched consensus votes which are not of the same kind or \ + do not have the same consensus content as the rest.") + Data_encoding.unit + (function Mismatch_signed_consensus_vote_in_batch -> Some () | _ -> None) + (fun () -> Mismatch_signed_consensus_vote_in_batch) + +let make_signed_consensus_vote_batch batch_kind (batch_content : batch_content) + ~batch_branch signed_consensus_votes = + let open Result_syntax in + let* () = + List.iter_e + (fun {unsigned_consensus_vote; signed_operation = _} -> + error_when + (unsigned_consensus_vote.vote_kind <> batch_kind + || Raw_level.( + unsigned_consensus_vote.vote_consensus_content.level + <> batch_content.level) + || Round.( + unsigned_consensus_vote.vote_consensus_content.round + <> batch_content.round) + || Block_payload_hash.( + unsigned_consensus_vote.vote_consensus_content.block_payload_hash + <> batch_content.block_payload_hash)) + Mismatch_signed_consensus_vote_in_batch) + signed_consensus_votes + in + return {batch_kind; batch_content; batch_branch; signed_consensus_votes} + +let make_singleton_consensus_vote_batch + (signed_consensus_vote : signed_consensus_vote) = + let {unsigned_consensus_vote; _} = signed_consensus_vote in + let batch_content = + { + level = unsigned_consensus_vote.vote_consensus_content.level; + round = unsigned_consensus_vote.vote_consensus_content.round; + block_payload_hash = + unsigned_consensus_vote.vote_consensus_content.block_payload_hash; + } + in + { + batch_kind = unsigned_consensus_vote.vote_kind; + batch_content; + batch_branch = signed_consensus_vote.signed_operation.shell.branch; + signed_consensus_votes = [signed_consensus_vote]; + } + +type round_state = { + current_round : Round.t; + current_phase : phase; + delayed_quorum : Kind.attestation operation list option; + early_attestations : signed_consensus_vote list; + awaiting_unlocking_pqc : bool; +} + +type forge_event = + | Block_ready of prepared_block + | Preattestation_ready of signed_consensus_vote + | Attestation_ready of signed_consensus_vote + +type forge_request = + | Forge_and_sign_block of block_to_bake + | Forge_and_sign_preattestations of { + unsigned_preattestations : unsigned_consensus_vote_batch; + } + | Forge_and_sign_attestations of { + unsigned_attestations : unsigned_consensus_vote_batch; + } + +type forge_worker_hooks = { + push_request : forge_request -> unit; + get_forge_event_stream : unit -> forge_event Lwt_stream.t; + cancel_all_pending_tasks : unit -> unit; +} + +type global_state = { + (* client context *) + cctxt : Protocol_client_context.full; + (* chain id *) + chain_id : Chain_id.t; + (* baker configuration *) + config : Baking_configuration.t; + (* protocol constants *) + constants : Constants.t; + (* round durations *) + round_durations : Round.round_durations; + (* worker that monitor and aggregates new operations *) + operation_worker : Operation_worker.t; + (* hooks to the consensus and block forge worker *) + mutable forge_worker_hooks : forge_worker_hooks; + (* the validation mode used by the baker*) + validation_mode : validation_mode; + (* the delegates on behalf of which the baker is running *) + delegates : consensus_key list; + cache : cache; + dal_node_rpc_ctxt : Tezos_rpc.Context.generic option; +} + +type state = { + global_state : global_state; + level_state : level_state; + round_state : round_state; +} + +type t = state + +let update_current_phase state new_phase = + {state with round_state = {state.round_state with current_phase = new_phase}} + +type timeout_kind = + | End_of_round of {ending_round : Round.t} + | Time_to_prepare_next_level_block of {at_round : Round.t} + +let timeout_kind_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"End_of_round" + (obj2 + (req "kind" (constant "End_of_round")) + (req "round" Round.encoding)) + (function + | End_of_round {ending_round} -> Some ((), ending_round) | _ -> None) + (fun ((), ending_round) -> End_of_round {ending_round}); + case + (Tag 1) + ~title:"Time_to_prepare_next_level_block" + (obj2 + (req "kind" (constant "Time_to_prepare_next_level_block")) + (req "round" Round.encoding)) + (function + | Time_to_prepare_next_level_block {at_round} -> Some ((), at_round) + | _ -> None) + (fun ((), at_round) -> Time_to_prepare_next_level_block {at_round}); + ] + +type event = + | New_valid_proposal of proposal + | New_head_proposal of proposal + | Prequorum_reached of + Operation_worker.candidate * Kind.preattestation operation list + | Quorum_reached of + Operation_worker.candidate * Kind.attestation operation list + | New_forge_event of forge_event + | Timeout of timeout_kind + +let event_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"New_valid_proposal" + (tup2 (constant "New_valid_proposal") proposal_encoding) + (function New_valid_proposal p -> Some ((), p) | _ -> None) + (fun ((), p) -> New_valid_proposal p); + case + (Tag 1) + ~title:"New_head_proposal" + (tup2 (constant "New_head_proposal") proposal_encoding) + (function New_head_proposal p -> Some ((), p) | _ -> None) + (fun ((), p) -> New_head_proposal p); + case + (Tag 2) + ~title:"Prequorum_reached" + (tup3 + (constant "Prequorum_reached") + Operation_worker.candidate_encoding + (Data_encoding.list (dynamic_size Operation.encoding))) + (function + | Prequorum_reached (candidate, ops) -> + Some ((), candidate, List.map Operation.pack ops) + | _ -> None) + (fun ((), candidate, ops) -> + Prequorum_reached + (candidate, Operation_pool.filter_preattestations ops)); + case + (Tag 3) + ~title:"Quorum_reached" + (tup3 + (constant "Quorum_reached") + Operation_worker.candidate_encoding + (Data_encoding.list (dynamic_size Operation.encoding))) + (function + | Quorum_reached (candidate, ops) -> + Some ((), candidate, List.map Operation.pack ops) + | _ -> None) + (fun ((), candidate, ops) -> + Quorum_reached (candidate, Operation_pool.filter_attestations ops)); + case + (Tag 4) + ~title:"Timeout" + (tup2 (constant "Timeout") timeout_kind_encoding) + (function Timeout tk -> Some ((), tk) | _ -> None) + (fun ((), tk) -> Timeout tk); + ] + +let vote_kind_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Preattestation" + unit + (function Preattestation -> Some () | _ -> None) + (fun () -> Preattestation); + case + (Tag 1) + ~title:"Attestation" + unit + (function Attestation -> Some () | _ -> None) + (fun () -> Attestation); + ] + +let unsigned_consensus_vote_encoding = + let open Data_encoding in + let dal_content_encoding : dal_content encoding = + conv + (fun {attestation} -> attestation) + (fun attestation -> {attestation}) + Dal.Attestation.encoding + in + conv + (fun {vote_kind; vote_consensus_content; delegate; dal_content} -> + (vote_kind, vote_consensus_content, delegate, dal_content)) + (fun (vote_kind, vote_consensus_content, delegate, dal_content) -> + {vote_kind; vote_consensus_content; delegate; dal_content}) + (obj4 + (req "vote_kind" vote_kind_encoding) + (req "vote_consensus_content" consensus_content_encoding) + (req "delegate" consensus_key_and_delegate_encoding) + (opt "dal_content" dal_content_encoding)) + +let signed_consensus_vote_encoding = + let open Data_encoding in + conv + (fun {unsigned_consensus_vote; signed_operation} -> + (unsigned_consensus_vote, signed_operation)) + (fun (unsigned_consensus_vote, signed_operation) -> + {unsigned_consensus_vote; signed_operation}) + (obj2 + (req "unsigned_consensus_vote" unsigned_consensus_vote_encoding) + (req "signed_operation" (dynamic_size Operation.encoding))) + +let forge_event_encoding = + let open Data_encoding in + let prepared_block_encoding = + conv + (fun {signed_block_header; round; delegate; operations; baking_votes} -> + (signed_block_header, round, delegate, operations, baking_votes)) + (fun (signed_block_header, round, delegate, operations, baking_votes) -> + {signed_block_header; round; delegate; operations; baking_votes}) + (obj5 + (req "header" (dynamic_size Block_header.encoding)) + (req "round" Round.encoding) + (req "delegate" consensus_key_and_delegate_encoding) + (req + "operations" + (list (list (dynamic_size Tezos_base.Operation.encoding)))) + (req "baking_votes" Per_block_votes.per_block_votes_encoding)) + in + union + [ + case + (Tag 0) + ~title:"Block_ready" + (obj1 (req "signed_block" prepared_block_encoding)) + (function + | Block_ready prepared_block -> Some prepared_block | _ -> None) + (fun prepared_block -> Block_ready prepared_block); + case + (Tag 1) + ~title:"Preattestation_ready" + (obj1 (req "signed_preattestation" signed_consensus_vote_encoding)) + (function + | Preattestation_ready signed_preattestation -> + Some signed_preattestation + | _ -> None) + (fun signed_preattestation -> + Preattestation_ready signed_preattestation); + case + (Tag 2) + ~title:"Attestation_ready" + (obj1 (req "signed_attestation" signed_consensus_vote_encoding)) + (function + | Attestation_ready signed_attestation -> Some signed_attestation + | _ -> None) + (fun signed_attestation -> Attestation_ready signed_attestation); + ] + +(* Disk state *) + +module Events = struct + include Internal_event.Simple + + let section = [Protocol.name; "baker"; "disk"] + + let incompatible_stored_state = + declare_0 + ~section + ~name:"incompatible_stored_state" + ~level:Warning + ~msg:"found an outdated or corrupted baking state: discarding it" + () +end + +type state_data = { + level_data : int32; + locked_round_data : locked_round option; + attestable_payload_data : attestable_payload option; +} + +let state_data_encoding = + let open Data_encoding in + conv + (fun {level_data; locked_round_data; attestable_payload_data} -> + (level_data, locked_round_data, attestable_payload_data)) + (fun (level_data, locked_round_data, attestable_payload_data) -> + {level_data; locked_round_data; attestable_payload_data}) + (obj3 + (req "level" int32) + (req "locked_round" (option locked_round_encoding)) + (req "attestable_payload" (option attestable_payload_encoding))) + +let record_state (state : state) = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + let location = + Baking_files.resolve_location ~chain_id:state.global_state.chain_id `State + in + let filename = + Filename.Infix.(cctxt#get_base_dir // Baking_files.filename location) + in + protect @@ fun () -> + cctxt#with_lock @@ fun () -> + let level_data = state.level_state.current_level in + let locked_round_data = state.level_state.locked_round in + let attestable_payload_data = state.level_state.attestable_payload in + let bytes = + Data_encoding.Binary.to_bytes_exn + state_data_encoding + {level_data; locked_round_data; attestable_payload_data} + in + let filename_tmp = filename ^ "_tmp" in + let*! () = + Lwt_io.with_file + ~flags:[Unix.O_CREAT; O_WRONLY; O_TRUNC; O_CLOEXEC; O_SYNC] + ~mode:Output + filename_tmp + (fun channel -> + Lwt_io.write_from_exactly channel bytes 0 (Bytes.length bytes)) + in + let*! () = Lwt_unix.rename filename_tmp filename in + return_unit + +let may_record_new_state ~previous_state ~new_state = + let open Lwt_result_syntax in + if new_state.global_state.config.state_recorder = Baking_configuration.Memory + then return_unit + else + let { + current_level = previous_current_level; + locked_round = previous_locked_round; + attestable_payload = previous_attestable_payload; + _; + } = + previous_state.level_state + in + let { + current_level = new_current_level; + locked_round = new_locked_round; + attestable_payload = new_attestable_payload; + _; + } = + new_state.level_state + in + let is_new_state_consistent = + Compare.Int32.(new_current_level > previous_current_level) + || new_current_level = previous_current_level + && + if Compare.Int32.(new_current_level = previous_current_level) then + let is_new_locked_round_consistent = + match (new_locked_round, previous_locked_round) with + | None, None -> true + | Some _, None -> true + | None, Some _ -> false + | Some new_locked_round, Some previous_locked_round -> + Round.(new_locked_round.round >= previous_locked_round.round) + in + let is_new_attestable_payload_consistent = + match (new_attestable_payload, previous_attestable_payload) with + | None, None -> true + | Some _, None -> true + | None, Some _ -> false + | Some new_attestable_payload, Some previous_attestable_payload -> + Round.( + new_attestable_payload.proposal.block.round + >= previous_attestable_payload.proposal.block.round) + in + is_new_locked_round_consistent + && is_new_attestable_payload_consistent + else true + in + let* () = + fail_unless is_new_state_consistent Broken_locked_values_invariant + in + let has_not_changed = + previous_state.level_state.current_level + == new_state.level_state.current_level + && previous_state.level_state.locked_round + == new_state.level_state.locked_round + && previous_state.level_state.attestable_payload + == new_state.level_state.attestable_payload + in + if has_not_changed then return_unit else record_state new_state + +let load_attestable_data cctxt location = + let open Lwt_result_syntax in + protect (fun () -> + let filename = + Filename.Infix.(cctxt#get_base_dir // Baking_files.filename location) + in + let*! exists = Lwt_unix.file_exists filename in + match exists with + | false -> return_none + | true -> + Lwt_io.with_file + ~flags:[Unix.O_EXCL; O_RDONLY; O_CLOEXEC] + ~mode:Input + filename + (fun channel -> + let*! str = Lwt_io.read channel in + match + Data_encoding.Binary.of_string_opt state_data_encoding str + with + | Some state_data -> return_some state_data + | None -> + (* The stored state format is incompatible: discard it. *) + let*! () = Events.(emit incompatible_stored_state ()) in + return_none)) + +let may_load_attestable_data state = + let open Lwt_result_syntax in + let cctxt = state.global_state.cctxt in + let chain_id = state.global_state.chain_id in + let location = Baking_files.resolve_location ~chain_id `State in + protect ~on_error:(fun _ -> return state) @@ fun () -> + cctxt#with_lock @@ fun () -> + let* attestable_data_opt = load_attestable_data cctxt location in + match attestable_data_opt with + | None -> return state + | Some {level_data; locked_round_data; attestable_payload_data} -> + if Compare.Int32.(state.level_state.current_level = level_data) then + let loaded_level_state = + { + state.level_state with + locked_round = locked_round_data; + attestable_payload = attestable_payload_data; + } + in + return {state with level_state = loaded_level_state} + else return state + +(* Helpers *) + +module DelegateSet = struct + include Set.Make (struct + type t = consensus_key + + let compare {public_key_hash = pkh; _} {public_key_hash = pkh'; _} = + Signature.Public_key_hash.compare pkh pkh' + end) + + let find_pkh pkh s = + let exception Found of elt in + try + iter + (fun ({public_key_hash; _} as delegate) -> + if Signature.Public_key_hash.equal pkh public_key_hash then + raise (Found delegate) + else ()) + s ; + None + with Found d -> Some d +end + +let delegate_slots attesting_rights delegates = + let own_delegates = DelegateSet.of_list delegates in + let own_delegate_first_slots, own_delegate_slots, all_delegate_voting_power = + List.fold_left + (fun (own_list, own_map, all_map) slot -> + let {Plugin.RPC.Validators.consensus_key; delegate; slots; _} = slot in + let first_slot = Stdlib.List.hd slots in + let attesting_power = List.length slots in + let all_map = SlotMap.add first_slot attesting_power all_map in + let own_list, own_map = + match DelegateSet.find_pkh consensus_key own_delegates with + | Some consensus_key -> + let attesting_slot = + { + consensus_key_and_delegate = (consensus_key, delegate); + first_slot; + attesting_power; + } + in + ( attesting_slot :: own_list, + List.fold_left + (fun own_map slot -> SlotMap.add slot attesting_slot own_map) + own_map + slots ) + | None -> (own_list, own_map) + in + (own_list, own_map, all_map)) + ([], SlotMap.empty, SlotMap.empty) + attesting_rights + in + Delegate_slots. + { + own_delegates = own_delegate_first_slots; + own_delegate_slots; + all_delegate_voting_power; + } + +let compute_delegate_slots (cctxt : Protocol_client_context.full) + ?(block = `Head 0) ~level ~chain delegates = + let open Lwt_result_syntax in + let*? level = Environment.wrap_tzresult (Raw_level.of_int32 level) in + let* attesting_rights = + Plugin.RPC.Validators.get cctxt (chain, block) ~levels:[level] + in + delegate_slots attesting_rights delegates |> return + +let round_proposer state ~level round = + let slots = + match level with + | `Current -> state.level_state.delegate_slots + | `Next -> state.level_state.next_level_delegate_slots + in + let committee_size = + state.global_state.constants.parametric.consensus_committee_size + in + Round.to_slot round ~committee_size |> function + | Error _ -> None + | Ok slot -> Delegate_slots.own_slot_owner slots ~slot + +let cache_size_limit = 100 + +let create_cache () = + let open Baking_cache in + { + known_timestamps = Timestamp_of_round_cache.create cache_size_limit; + round_timestamps = Round_timestamp_interval_cache.create cache_size_limit; + } + +(** Memoization wrapper for [Round.timestamp_of_round]. *) +let timestamp_of_round state ~predecessor_timestamp ~predecessor_round ~round = + let open Result_syntax in + let open Baking_cache in + let known_timestamps = state.global_state.cache.known_timestamps in + match + Timestamp_of_round_cache.find_opt + known_timestamps + (predecessor_timestamp, predecessor_round, round) + with + (* Compute and register the timestamp if not already existing. *) + | None -> + let* ts = + Environment.wrap_tzresult + @@ Protocol.Alpha_context.Round.timestamp_of_round + state.global_state.round_durations + ~predecessor_timestamp + ~predecessor_round + ~round + in + Timestamp_of_round_cache.replace + known_timestamps + (predecessor_timestamp, predecessor_round, round) + ts ; + return ts + (* If it already exists, just fetch from the memoization table. *) + | Some ts -> return ts + +let compute_next_round_time state = + let proposal = + match state.level_state.attestable_payload with + | None -> state.level_state.latest_proposal + | Some {proposal; _} -> proposal + in + if is_first_block_in_protocol proposal then None + else + match state.level_state.next_level_proposed_round with + | Some _proposed_round -> + (* TODO? do something, if we don't, we won't be able to + repropose a block at next level. *) + None + | None -> ( + let predecessor_timestamp = proposal.predecessor.shell.timestamp in + let predecessor_round = proposal.predecessor.round in + let next_round = Round.succ state.round_state.current_round in + match + timestamp_of_round + state + ~predecessor_timestamp + ~predecessor_round + ~round:next_round + with + | Ok timestamp -> Some (timestamp, next_round) + | _ -> assert false) + +(* Pretty-printers *) + +let pp_validation_mode fmt = function + | Node -> Format.fprintf fmt "node" + | Local _ -> Format.fprintf fmt "local" + +let pp_global_state fmt {chain_id; config; validation_mode; delegates; _} = + Format.fprintf + fmt + "@[Global state:@ chain_id: %a@ @[config:@ %a@]@ \ + validation_mode: %a@ @[delegates:@ %a@]@]" + Chain_id.pp + chain_id + Baking_configuration.pp + config + pp_validation_mode + validation_mode + Format.(pp_print_list pp_consensus_key) + delegates + +let pp_option pp fmt = function + | None -> Format.fprintf fmt "none" + | Some v -> Format.fprintf fmt "%a" pp v + +let pp_prequorum fmt {level; round; block_payload_hash; preattestations} = + Format.fprintf + fmt + "level: %ld, round: %a, payload_hash: %a, preattestations: %d" + level + Round.pp + round + Block_payload_hash.pp_short + block_payload_hash + (List.length preattestations) + +let pp_block_info fmt + { + hash; + shell; + payload_hash; + round; + prequorum; + quorum; + payload; + payload_round; + } = + Format.fprintf + fmt + "@[Block:@ hash: %a@ payload_hash: %a@ level: %ld@ round: %a@ \ + prequorum: %a@ quorum: %d attestations@ payload: %a@ payload round: %a@]" + Block_hash.pp + hash + Block_payload_hash.pp_short + payload_hash + shell.level + Round.pp + round + (pp_option pp_prequorum) + prequorum + (List.length quorum) + Operation_pool.pp_payload + payload + Round.pp + payload_round + +let pp_proposal fmt {block; _} = pp_block_info fmt block + +let pp_locked_round fmt ({payload_hash; round} : locked_round) = + Format.fprintf + fmt + "payload hash: %a, round: %a" + Block_payload_hash.pp_short + payload_hash + Round.pp + round + +let pp_attestable_payload fmt {proposal; prequorum} = + Format.fprintf + fmt + "proposal: %a, prequorum: %a" + Block_hash.pp + proposal.block.hash + pp_prequorum + prequorum + +let pp_elected_block fmt {proposal; attestation_qc} = + Format.fprintf + fmt + "@[%a@ nb quorum attestations: %d@]" + pp_block_info + proposal.block + (List.length attestation_qc) + +let pp_delegate_slot fmt + {consensus_key_and_delegate; first_slot; attesting_power} = + Format.fprintf + fmt + "slots: @[first_slot: %a@],@ delegate: %a,@ attesting_power: %d" + Slot.pp + first_slot + pp_consensus_key_and_delegate + consensus_key_and_delegate + attesting_power + +(* this type is only used below for pretty-printing *) +type delegate_slots_for_pp = { + attester : consensus_key_and_delegate; + all_slots : Slot.t list; +} + +let delegate_slots_for_pp delegate_slot_map = + SlotMap.fold + (fun slot {consensus_key_and_delegate; first_slot; attesting_power = _} acc -> + match SlotMap.find first_slot acc with + | None -> + SlotMap.add + first_slot + {attester = consensus_key_and_delegate; all_slots = [slot]} + acc + | Some {attester; all_slots} -> + SlotMap.add first_slot {attester; all_slots = slot :: all_slots} acc) + delegate_slot_map + SlotMap.empty + |> SlotMap.map (fun {attester; all_slots} -> + {attester; all_slots = List.rev all_slots}) + +let pp_delegate_slots fmt Delegate_slots.{own_delegate_slots; _} = + Format.fprintf + fmt + "@[%a@]" + Format.( + pp_print_list + ~pp_sep:pp_print_cut + (fun fmt (_first_slot, {attester; all_slots}) -> + Format.fprintf + fmt + "attester: %a, power: %d, first 10 slots: %a" + pp_consensus_key_and_delegate + attester + (List.length all_slots) + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.pp_print_string fmt ",") + Slot.pp) + (List.filteri (fun i _ -> i < 10) all_slots))) + (SlotMap.bindings (delegate_slots_for_pp own_delegate_slots)) + +let pp_prepared_block fmt + {signed_block_header; delegate = consensus_key_and_delegate; _} = + Format.fprintf + fmt + "predecessor block hash: %a, payload hash: %a, level: %ld, delegate: %a" + Block_hash.pp + signed_block_header.shell.predecessor + Block_payload_hash.pp_short + signed_block_header.protocol_data.contents.payload_hash + signed_block_header.shell.level + pp_consensus_key_and_delegate + consensus_key_and_delegate + +let pp_level_state fmt + { + current_level; + latest_proposal; + is_latest_proposal_applied; + locked_round; + attestable_payload; + elected_block; + delegate_slots; + next_level_delegate_slots; + next_level_proposed_round; + } = + Format.fprintf + fmt + "@[Level state:@ current level: %ld@ @[proposal (applied:%b):@ \ + %a@]@ locked round: %a@ attestable payload: %a@ elected block: %a@ @[own delegate slots:@ %a@]@ @[next level own delegate slots:@ %a@]@ \ + next level proposed round: %a@]" + current_level + is_latest_proposal_applied + pp_proposal + latest_proposal + (pp_option pp_locked_round) + locked_round + (pp_option pp_attestable_payload) + attestable_payload + (pp_option pp_elected_block) + elected_block + pp_delegate_slots + delegate_slots + pp_delegate_slots + next_level_delegate_slots + (pp_option Round.pp) + next_level_proposed_round + +let pp_phase fmt = function + | Idle -> Format.fprintf fmt "idle" + | Awaiting_preattestations -> Format.fprintf fmt "awaiting preattestations" + | Awaiting_application -> Format.fprintf fmt "awaiting application" + | Awaiting_attestations -> Format.fprintf fmt "awaiting attestations" + +let pp_round_state fmt + { + current_round; + current_phase; + delayed_quorum; + early_attestations; + awaiting_unlocking_pqc; + } = + Format.fprintf + fmt + "@[Round state:@ round: %a,@ phase: %a,@ delayed quorum: %a,@ early \ + attestations: %d,@ awaiting unlocking pqc: %b@]" + Round.pp + current_round + pp_phase + current_phase + (pp_option Format.pp_print_int) + (Option.map List.length delayed_quorum) + (List.length early_attestations) + awaiting_unlocking_pqc + +let pp fmt {global_state; level_state; round_state} = + Format.fprintf + fmt + "@[State:@ %a@ %a@ %a@]" + pp_global_state + global_state + pp_level_state + level_state + pp_round_state + round_state + +let pp_timeout_kind fmt = function + | End_of_round {ending_round} -> + Format.fprintf fmt "end of round %a" Round.pp ending_round + | Time_to_prepare_next_level_block {at_round} -> + Format.fprintf + fmt + "time to prepare next level block at round %a" + Round.pp + at_round + +let pp_forge_event fmt = + let open Format in + let pp_signed_consensus_vote fmt {unsigned_consensus_vote; _} = + fprintf + fmt + "for delegate %a at level %ld (round %a)" + pp_consensus_key_and_delegate + unsigned_consensus_vote.delegate + (Raw_level.to_int32 unsigned_consensus_vote.vote_consensus_content.level) + Round.pp + unsigned_consensus_vote.vote_consensus_content.round + in + function + | Block_ready {signed_block_header; round; delegate; _} -> + fprintf + fmt + "block ready for delegate: %a at level %ld (round: %a)" + pp_consensus_key_and_delegate + delegate + signed_block_header.shell.level + Round.pp + round + | Preattestation_ready signed_preattestation -> + fprintf + fmt + "preattestation ready %a" + pp_signed_consensus_vote + signed_preattestation + | Attestation_ready signed_attestation -> + fprintf + fmt + "attestation ready %a" + pp_signed_consensus_vote + signed_attestation + +let pp_event fmt = function + | New_valid_proposal proposal -> + Format.fprintf + fmt + "new valid proposal received: %a" + pp_block_info + proposal.block + | New_head_proposal proposal -> + Format.fprintf + fmt + "new head proposal received: %a" + pp_block_info + proposal.block + | Prequorum_reached (candidate, preattestations) -> + Format.fprintf + fmt + "prequorum reached with %d preattestations for %a at round %a" + (List.length preattestations) + Block_hash.pp + candidate.Operation_worker.hash + Round.pp + candidate.round_watched + | Quorum_reached (candidate, attestations) -> + Format.fprintf + fmt + "quorum reached with %d attestations for %a at round %a" + (List.length attestations) + Block_hash.pp + candidate.Operation_worker.hash + Round.pp + candidate.round_watched + | New_forge_event forge_event -> + Format.fprintf fmt "new forge event: %a" pp_forge_event forge_event + | Timeout kind -> + Format.fprintf fmt "timeout reached: %a" pp_timeout_kind kind diff --git a/src/proto_020_PsParisC/lib_delegate/baking_state.mli b/src/proto_020_PsParisC/lib_delegate/baking_state.mli new file mode 100644 index 000000000000..689b85c0b009 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_state.mli @@ -0,0 +1,412 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type consensus_key = { + alias : string option; + public_key : Signature.public_key; + public_key_hash : Signature.public_key_hash; + secret_key_uri : Client_keys.sk_uri; +} + +val consensus_key_encoding : consensus_key Data_encoding.t + +val pp_consensus_key : Format.formatter -> consensus_key -> unit + +type consensus_key_and_delegate = consensus_key * Signature.Public_key_hash.t + +val consensus_key_and_delegate_encoding : + consensus_key_and_delegate Data_encoding.t + +val pp_consensus_key_and_delegate : + Format.formatter -> consensus_key_and_delegate -> unit + +(** The validation mode specifies whether the baker (filters and) validates + mempool operations via an RPC to the node, or if it does so "locally", by + using the context. *) +type validation_mode = Node | Local of Abstract_context_index.t + +type prequorum = { + level : int32; + round : Round.t; + block_payload_hash : Block_payload_hash.t; + preattestations : Kind.preattestation operation list; +} + +type block_info = { + hash : Block_hash.t; + shell : Block_header.shell_header; + payload_hash : Block_payload_hash.t; + payload_round : Round.t; + round : Round.t; + prequorum : prequorum option; + quorum : Kind.attestation operation list; + payload : Operation_pool.payload; +} + +type cache = { + known_timestamps : Timestamp.time Baking_cache.Timestamp_of_round_cache.t; + round_timestamps : + (Timestamp.time * Round.t * consensus_key_and_delegate) + Baking_cache.Round_timestamp_interval_cache.t; +} + +type block_kind = + | Fresh of Operation_pool.pool + | Reproposal of { + consensus_operations : packed_operation list; + payload_hash : Block_payload_hash.t; + payload_round : Round.t; + payload : Operation_pool.payload; + } + +type block_to_bake = { + predecessor : block_info; + round : Round.t; + delegate : consensus_key_and_delegate; + kind : block_kind; + force_apply : bool; + (** if true, while baking the block, try and apply the block and its + operations instead of only validating them. this can be permanently + set using the [--force-apply] flag (see [force_apply_switch_arg] in + [baking_commands.ml]). *) +} + +val block_info_encoding : block_info Data_encoding.t + +val round_of_shell_header : Block_header.shell_header -> Round.t tzresult + +module SlotMap : Map.S with type key = Slot.t + +(** A delegate slot consists of the delegate's consensus key, its public key + hash, its first slot, and its attesting power at some level. *) +type delegate_slot = { + consensus_key_and_delegate : consensus_key_and_delegate; + first_slot : Slot.t; + attesting_power : int; +} + +module Delegate_slots : sig + (** Information regarding the slot distribution at some level. *) + type t + + (** Returns the list of our own delegates that have at least a slot. There are + no duplicates, the associated slot is the first one. *) + val own_delegates : t -> delegate_slot list + + (** Returns, among our *own* delegates, the delegate (together with its + first attesting slot) that owns the given slot, if any (even if the + given slot is not the delegate's first slot). *) + val own_slot_owner : t -> slot:Slot.t -> delegate_slot option + + (** Returns the voting power of the delegate whose first slot is the given + slot. Returns [None] if the slot is not the first slot of any delegate. *) + val voting_power : t -> slot:Slot.t -> int option +end + +type delegate_slots = Delegate_slots.t + +type proposal = {block : block_info; predecessor : block_info} + +val proposal_encoding : proposal Data_encoding.t + +(** Identify the first block of the protocol, ie. the block that + activates the current protocol. + + This block should be baked by the baker of the previous protocol + (that's why this same block is also referred to as the last block + of the previous protocol). It is always considered final and + therefore is not attested.*) +val is_first_block_in_protocol : proposal -> bool + +type locked_round = {payload_hash : Block_payload_hash.t; round : Round.t} + +val locked_round_encoding : locked_round Data_encoding.t + +type attestable_payload = {proposal : proposal; prequorum : prequorum} + +val attestable_payload_encoding : attestable_payload Data_encoding.t + +type elected_block = { + proposal : proposal; + attestation_qc : Kind.attestation operation list; +} + +type prepared_block = { + signed_block_header : block_header; + round : Round.t; + delegate : consensus_key_and_delegate; + operations : Tezos_base.Operation.t list list; + baking_votes : Per_block_votes_repr.per_block_votes; +} + +type consensus_vote_kind = Attestation | Preattestation + +val pp_consensus_vote_kind : Format.formatter -> consensus_vote_kind -> unit + +val consensus_vote_kind_encoding : consensus_vote_kind Data_encoding.t + +type unsigned_consensus_vote = { + vote_kind : consensus_vote_kind; + vote_consensus_content : consensus_content; + delegate : consensus_key_and_delegate; + dal_content : dal_content option; +} + +type signed_consensus_vote = { + unsigned_consensus_vote : unsigned_consensus_vote; + signed_operation : packed_operation; +} + +type batch_content = { + level : Raw_level.t; + round : Round.t; + block_payload_hash : Block_payload_hash.t; +} + +type unsigned_consensus_vote_batch = private { + batch_kind : consensus_vote_kind; + batch_content : batch_content; + batch_branch : Block_hash.t; + unsigned_consensus_votes : unsigned_consensus_vote list; +} + +val make_unsigned_consensus_vote_batch : + consensus_vote_kind -> + batch_content -> + batch_branch:Block_hash.t -> + (consensus_key_and_delegate * Slot.t) list -> + unsigned_consensus_vote_batch + +val dal_content_map_p : + (unsigned_consensus_vote -> dal_content option tzresult Lwt.t) -> + unsigned_consensus_vote_batch -> + unsigned_consensus_vote_batch Lwt.t + +type signed_consensus_vote_batch = private { + batch_kind : consensus_vote_kind; + batch_content : batch_content; + batch_branch : Block_hash.t; + signed_consensus_votes : signed_consensus_vote list; +} + +type error += Mismatch_signed_consensus_vote_in_batch + +val make_signed_consensus_vote_batch : + consensus_vote_kind -> + batch_content -> + batch_branch:Block_hash.t -> + signed_consensus_vote list -> + signed_consensus_vote_batch tzresult + +val make_singleton_consensus_vote_batch : + signed_consensus_vote -> signed_consensus_vote_batch + +type level_state = { + current_level : int32; + latest_proposal : proposal; + is_latest_proposal_applied : bool; + locked_round : locked_round option; + attestable_payload : attestable_payload option; + elected_block : elected_block option; + delegate_slots : delegate_slots; + next_level_delegate_slots : delegate_slots; + next_level_proposed_round : Round.t option; +} + +type phase = + | Idle + | Awaiting_preattestations + | Awaiting_attestations + | Awaiting_application + +val phase_encoding : phase Data_encoding.t + +type round_state = { + current_round : Round.t; + current_phase : phase; + delayed_quorum : Kind.attestation operation list option; + early_attestations : signed_consensus_vote list; + awaiting_unlocking_pqc : bool; +} + +(** [forge_event] type used to return the result of a task completion + in the forge worker. *) +type forge_event = + | Block_ready of prepared_block + | Preattestation_ready of signed_consensus_vote + | Attestation_ready of signed_consensus_vote + +(** [forge_request] type used to push a concurrent forging task in the + forge worker. *) +type forge_request = + | Forge_and_sign_block of block_to_bake + | Forge_and_sign_preattestations of { + unsigned_preattestations : unsigned_consensus_vote_batch; + } + | Forge_and_sign_attestations of { + unsigned_attestations : unsigned_consensus_vote_batch; + } + +(** [forge_worker_hooks] type that allows interactions with the forge + worker. Hooks are needed in order to break a circular dependency. *) +type forge_worker_hooks = { + push_request : forge_request -> unit; + get_forge_event_stream : unit -> forge_event Lwt_stream.t; + cancel_all_pending_tasks : unit -> unit; +} + +type global_state = { + cctxt : Protocol_client_context.full; + chain_id : Chain_id.t; + config : Baking_configuration.t; + constants : Constants.t; + round_durations : Round.round_durations; + operation_worker : Operation_worker.t; + mutable forge_worker_hooks : forge_worker_hooks; + validation_mode : validation_mode; + delegates : consensus_key list; + cache : cache; + dal_node_rpc_ctxt : Tezos_rpc.Context.generic option; +} + +type state = { + global_state : global_state; + level_state : level_state; + round_state : round_state; +} + +type t = state + +val update_current_phase : t -> phase -> t + +(** Returns, among our *own* delegates, the delegate (and its attesting slot) + that has a proposer slot at the given round and the current or next level, + if any. *) +val round_proposer : + state -> level:[`Current | `Next] -> Round.t -> delegate_slot option + +type timeout_kind = + | End_of_round of {ending_round : Round.t} + | Time_to_prepare_next_level_block of {at_round : Round.t} + +val timeout_kind_encoding : timeout_kind Data_encoding.t + +type event = + | New_valid_proposal of proposal + | New_head_proposal of proposal + | Prequorum_reached of + Operation_worker.candidate * Kind.preattestation operation list + | Quorum_reached of + Operation_worker.candidate * Kind.attestation operation list + | New_forge_event of forge_event + | Timeout of timeout_kind + +val event_encoding : event Data_encoding.t + +val forge_event_encoding : forge_event Data_encoding.t + +type state_data = { + level_data : int32; + locked_round_data : locked_round option; + attestable_payload_data : attestable_payload option; +} + +val state_data_encoding : state_data Data_encoding.t + +val record_state : t -> unit tzresult Lwt.t + +val may_record_new_state : + previous_state:t -> new_state:t -> unit tzresult Lwt.t + +val load_attestable_data : + Protocol_client_context.full -> + [`State] Baking_files.location -> + state_data option tzresult Lwt.t + +val may_load_attestable_data : t -> t tzresult Lwt.t + +(** @param block default to [`Head 0]*) +val compute_delegate_slots : + Protocol_client_context.full -> + ?block:Block_services.block -> + level:int32 -> + chain:Shell_services.chain -> + consensus_key list -> + delegate_slots tzresult Lwt.t + +val create_cache : unit -> cache + +(** Memoization wrapper for [Round.timestamp_of_round]. *) +val timestamp_of_round : + state -> + predecessor_timestamp:Time.Protocol.t -> + predecessor_round:Round.t -> + round:Round.t -> + Time.Protocol.t tzresult + +(** From the current [state], the function returns an optional + association pair, which consists of the next round timestamp and its + round. *) +val compute_next_round_time : state -> (Time.Protocol.t * Round.t) option + +val pp_validation_mode : Format.formatter -> validation_mode -> unit + +val pp_global_state : Format.formatter -> global_state -> unit + +val pp_option : + (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit + +val pp_block_info : Format.formatter -> block_info -> unit + +val pp_proposal : Format.formatter -> proposal -> unit + +val pp_locked_round : Format.formatter -> locked_round -> unit + +val pp_attestable_payload : Format.formatter -> attestable_payload -> unit + +val pp_elected_block : Format.formatter -> elected_block -> unit + +val pp_delegate_slot : Format.formatter -> delegate_slot -> unit + +val pp_delegate_slots : Format.formatter -> delegate_slots -> unit + +val pp_prepared_block : Format.formatter -> prepared_block -> unit + +val pp_level_state : Format.formatter -> level_state -> unit + +val pp_phase : Format.formatter -> phase -> unit + +val pp_round_state : Format.formatter -> round_state -> unit + +val pp : Format.formatter -> t -> unit + +val pp_timeout_kind : Format.formatter -> timeout_kind -> unit + +val pp_event : Format.formatter -> event -> unit + +val pp_forge_event : Format.formatter -> forge_event -> unit diff --git a/src/proto_020_PsParisC/lib_delegate/baking_vdf.ml b/src/proto_020_PsParisC/lib_delegate/baking_vdf.ml new file mode 100644 index 000000000000..003e3115c125 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_vdf.ml @@ -0,0 +1,503 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Client_baking_blocks +module Events = Baking_events.VDF + +type vdf_solution = Seed_repr.vdf_solution + +type vdf_setup = Seed_repr.vdf_setup + +type forked_process = {pid : int; ch_in : Lwt_io.input_channel} + +type status = + | Not_started + | Started of vdf_setup * forked_process + | Finished of vdf_setup * vdf_solution + | Injected + | Invalid + +type 'a state = { + cctxt : Protocol_client_context.full; + constants : Constants.t; + mutable block_stream : (block_info, 'a) result Lwt_stream.t; + mutable stream_stopper : Tezos_rpc.Context.stopper option; + mutable cycle : Cycle.t option; + mutable computation_status : status; +} + +let init_block_stream_with_stopper cctxt chain = + Client_baking_blocks.monitor_heads + cctxt + ~next_protocols:(Some [Protocol.hash]) + chain + +let stop_block_stream state = + Option.iter + (fun stopper -> + stopper () ; + state.stream_stopper <- None) + state.stream_stopper + +let emit_with_level msg level = + let level_i32 = Raw_level.to_int32 level in + Events.(emit vdf_info) (Printf.sprintf "%s (level %ld)" msg level_i32) + +let emit_revelation_not_injected cycle = + let open Lwt_result_syntax in + let*! () = + Events.(emit vdf_info) + (Printf.sprintf + "VDF revelation was NOT injected for cycle %ld" + (Cycle.to_int32 cycle)) + in + return_unit + +let log_errors_and_continue ~name p = + let open Lwt_syntax in + let* p in + match p with + | Ok () -> return_unit + | Error errs -> Events.(emit vdf_daemon_error) (name, errs) + +let get_seed_computation cctxt chain_id hash = + let chain = `Hash chain_id in + let block = `Hash (hash, 0) in + Alpha_services.Seed_computation.get cctxt (chain, block) + +let get_level_info cctxt level = + let open Lwt_result_syntax in + let level = Raw_level.to_int32 level in + let* {protocol_data = {level_info; _}; _} = + Protocol_client_context.Alpha_block_services.metadata + cctxt + ~chain:cctxt#chain + ~block:(`Level level) + () + in + return level_info + +let is_in_nonce_revelation_stage constants (level : Level.t) = + let open Lwt_result_syntax in + let {Constants.parametric = {nonce_revelation_threshold; _}; _} = constants in + return + (Vdf_helpers.is_in_nonce_revelation_stage + ~nonce_revelation_threshold + ~level) + +(* Checks if the VDF setup saved in the state is equal to the one computed + from a seed *) +let eq_vdf_setup vdf_setup seed_discriminant seed_challenge = + let open Environment.Vdf in + let saved_discriminant, saved_challenge = vdf_setup in + let discriminant, challenge = + Seed.generate_vdf_setup ~seed_discriminant ~seed_challenge + in + Bytes.equal + (discriminant_to_bytes discriminant) + (discriminant_to_bytes saved_discriminant) + && Bytes.equal + (challenge_to_bytes challenge) + (challenge_to_bytes saved_challenge) + +(* Forge the VDF revelation operation and inject it if: + * - it is correct wrt the VDF setup for the current cycle + * - we are still in the VDF revelation stage + * If successful or if the seed no longer needs to be injected, + * update the computation status. *) +let inject_vdf_revelation cctxt state setup solution chain_id hash + (level_info : Level.t) = + let open Lwt_result_syntax in + let chain = `Hash chain_id in + let block = `Hash (hash, 0) in + let level = level_info.level in + let* seed_computation = get_seed_computation cctxt chain_id hash in + match seed_computation with + | Vdf_revelation_stage {seed_discriminant; seed_challenge} -> + if eq_vdf_setup setup seed_discriminant seed_challenge then ( + let* op_bytes = + Plugin.RPC.Forge.vdf_revelation + cctxt + (chain, block) + ~branch:hash + ~solution + () + in + let op_bytes = Tezos_crypto.Signature.V_latest.(concat op_bytes zero) in + let* op_hash = + Shell_services.Injection.operation cctxt ~chain op_bytes + in + (* If injection is successful, update the status to [Injected]. *) + state.computation_status <- Injected ; + let*! () = + Events.(emit vdf_revelation_injected) + ( Cycle.to_int32 level_info.cycle, + Chain_services.to_string chain, + op_hash ) + in + return_unit) + else ( + (* The VDF setup saved in the state is different from the one computed + * from the on-chain seed. In practice this would indicate a bug, since + * it would either mean that the cycle has changed and we have not + * detected it or that the VDF setup changed mid-cycle. *) + state.computation_status <- Invalid ; + let*! () = + emit_with_level "Error injecting VDF: setup has been updated" level + in + return_unit) + | Nonce_revelation_stage -> + state.computation_status <- Not_started ; + let*! () = emit_with_level "Not injecting VDF: new cycle started" level in + return_unit + | Computation_finished -> + state.computation_status <- Injected ; + let*! () = emit_with_level "Not injecting VDF: already injected" level in + return_unit + +(* Launch the heavy VDF computation as a separate process. This is done in order + * to not block the main process, allowing it to continue monitoring blocks and + * to cancel or restart the VDF computation if needed. *) +let fork_vdf_computation state ((discriminant, challenge) as setup) level = + let open Lwt_syntax in + let ch_in, forked_out = Lwt_io.pipe () in + match Lwt_unix.fork () with + | 0 -> ( + (* In the forked process, try to compute the VDF solution, write it + * to [forked_out], then exit. *) + let* () = Lwt_io.close ch_in in + let solution = + Environment.Vdf.prove + discriminant + challenge + state.constants.parametric.vdf_difficulty + in + match + Data_encoding.Binary.to_bytes Seed.vdf_solution_encoding solution + with + | Ok encoded -> + let* () = Lwt_io.write_value forked_out encoded in + exit 0 + | Error _ -> + let* () = Events.(emit vdf_info) "Error encoding VDF solution" in + exit 1) + | pid -> + (* In the main process, change the computation status to [Started], + record the forked process data, and continue. *) + let* () = Lwt_io.close forked_out in + state.computation_status <- Started (setup, {pid; ch_in}) ; + let* () = + emit_with_level + (Printf.sprintf "Started to compute VDF, pid: %d" pid) + level + in + return_unit + +(* Check whether the VDF computation process has exited and read the result. + * Update the computation status accordingly. *) +let get_vdf_solution_if_ready cctxt state proc setup chain_id hash + (level_info : Level.t) = + let open Lwt_result_syntax in + let level = level_info.level in + let*! status = Lwt_unix.waitpid [WNOHANG] proc.pid in + match status with + | 0, _ -> + (* If the process is still running, continue *) + let*! () = emit_with_level "Skipping, VDF computation launched" level in + return_unit + | _, WEXITED 0 -> ( + (* If the process has exited normally, read the solution, update + * the status to [Finished], and attempt to inject the VDF + * revelation. *) + let*! encoded_solution = Lwt_io.read_value proc.ch_in in + match + Data_encoding.Binary.of_bytes + Seed.vdf_solution_encoding + encoded_solution + with + | Ok solution -> + let*! () = Lwt_io.close proc.ch_in in + state.computation_status <- Finished (setup, solution) ; + let*! () = emit_with_level "Finished VDF computation" level in + inject_vdf_revelation + cctxt + state + setup + solution + chain_id + hash + level_info + | Error _ -> + let*! () = Events.(emit vdf_info) "Error decoding VDF solution" in + state.computation_status <- Not_started ; + return_unit) + | _, WEXITED _ | _, WSIGNALED _ | _, WSTOPPED _ -> + (* If process has exited abnormally, reset the computation status to + * [Not_started] and continue *) + state.computation_status <- Not_started ; + let*! () = + Events.(emit vdf_info) "VDF computation process exited abnormally" + in + return_unit + +let kill_forked_process {pid; _} = + let open Lwt_syntax in + let* () = + match Unix.kill pid Sys.sigterm with + | () -> + Events.(emit vdf_info) + (Printf.sprintf + "Sent SIGTERM to VDF computation process (pid %d)" + pid) + | exception Unix.Unix_error (err, _, _) -> + let msg = Printf.sprintf "%s (pid %d)" (Unix.error_message err) pid in + Events.(emit vdf_daemon_cannot_kill_computation) msg + in + let* pid, status = Lwt_unix.waitpid [] pid in + let status = + match status with + | WEXITED n -> Printf.sprintf "WEXITED %d" n + | WSIGNALED n -> Printf.sprintf "WSIGNALED %d" n + | WSTOPPED n -> Printf.sprintf "WSTOPPED %d" n + in + Events.(emit vdf_info) + (Printf.sprintf + "Exit status for child VDF computation process %d: %s" + pid + status) + +(* Kill the VDF computation process if one was launched. *) +let maybe_kill_running_vdf_computation state = + let open Lwt_syntax in + match state.computation_status with + | Started (_, proc) -> + let* () = kill_forked_process proc in + return_unit + | _ -> return_unit + +(* Checks if the cycle of the last processed block is different from the cycle + * of the block at [level_info]. *) +let check_new_cycle state (level_info : Level.t) = + let open Lwt_result_syntax in + let current_cycle = level_info.cycle in + match state.cycle with + | None -> + (* First processed block, initialise [state.cycle] *) + state.cycle <- Some current_cycle ; + return_unit + | Some cycle -> + if Cycle.(cycle < current_cycle) then ( + (* The cycle of this block is different from the cycle of the last + * processed block. Emit an event if the VDF for the previous cycle + * has not been injected, kill any running VDF computation, and + * reset the computation status. *) + let* () = + match state.computation_status with + | Injected -> return_unit + | Started ((_ : vdf_setup), proc) -> + let*! () = kill_forked_process proc in + emit_revelation_not_injected cycle + | Not_started | Finished _ | Invalid -> + emit_revelation_not_injected cycle + in + state.cycle <- Some current_cycle ; + state.computation_status <- Not_started ; + return_unit) + else return_unit + +(* The daemon's main job is to launch the VDF computation as soon as it + * can (i.e., when the nonce revelation stage ends) and to inject + * the VDF solution as soon as it finishes computing it. + * Additionally, it must cancel a running VDF computation if its result + * is no longer required and restart a computation if it failed. + * The daemon processes the stream of blocks and monitors both + * the level of the head within a cycle and the [Seed_computation] RPC. + * The core of this function is a pattern match on the product of + * [seed_computation] (the on-chain status of the seed computation) + * and [state.computation_status] (the internal status of the daemon). + * + * [seed_computation] is reset at the beginning of a cycle to + * [Nonce_revelation_stage], mirroring the on-chain change of the computation + * status. No action is taken while in this state. + * After [nonce_revelation_threshold] blocks, the status becomes + * [Vdf_revelation_stage]. A call to the RPC confirms this and provides the seed + * required to launch the VDF computation. + * If a VDF revelation operation is injected before the end of the cycle, + * the status is updated to [Computation_finished]. If a VDF computation is + * running at that point (i.e., another daemon injected first), + * it is canceled. *) +let process_new_block (cctxt : #Protocol_client_context.full) state + {hash; chain_id; protocol; next_protocol; level; _} = + let open Lwt_result_syntax in + if Protocol_hash.(protocol <> next_protocol) then + (* If the protocol has changed, emit an event on every new block and take + * no further action. It is expected that the daemon corresponding to + * the new protocol is used instead. *) + let*! () = Delegate_events.Denunciator.(emit protocol_change_detected) () in + return_unit + else + let* level_info = get_level_info cctxt level in + (* If head is in a new cycle record it in [state.cycle] and reset + * [state.computation_status] to [Not_started]. *) + let* () = check_new_cycle state level_info in + (* If the chain is in the nonce revelation stage, there is nothing to do. *) + let* out = is_in_nonce_revelation_stage state.constants level_info in + if out then + let*! () = + emit_with_level "Skipping, still in nonce revelation stage" level + in + return_unit + else + (* Enter main loop if we are not in the nonce revelation stage and + * the expected protocol has been activated. *) + match state.computation_status with + | Not_started -> ( + let* seed_computation = get_seed_computation cctxt chain_id hash in + match seed_computation with + | Vdf_revelation_stage {seed_discriminant; seed_challenge} -> + (* The chain is in the VDF revelation stage and the computation + * has not been started, so it is started here, in a separate + * process. The computation status is updated to [Started]. *) + let setup = + Seed.generate_vdf_setup ~seed_discriminant ~seed_challenge + in + let*! () = fork_vdf_computation state setup level in + return_unit + | Computation_finished -> + let*! () = + emit_with_level + "Skipping, VDF solution has already been injected" + level + in + return_unit + | Nonce_revelation_stage -> + (* At this point the chain cannot be in the nonce revelation + * stage. This is checked in [is_in_nonce_revelation_stage]. *) + assert false) + | Started (setup, proc) -> ( + let* seed_computation = get_seed_computation cctxt chain_id hash in + match seed_computation with + | Vdf_revelation_stage _ -> + (* The chain is in the VDF computation stage and we have + * previously started the computation. Check whether it is + * finished and, if so, update the computation status to + * [Finished] and immediately inject the solution. *) + let* () = + get_vdf_solution_if_ready + cctxt + state + proc + setup + chain_id + hash + level_info + in + return_unit + | Computation_finished -> + (* The chain is no longer in the VDF revelation stage because + * the solution has already been injected: abort the running + * computation. *) + let*! () = kill_forked_process proc in + let*! () = + emit_with_level + "VDF solution already injected, aborting VDF computation" + level + in + state.computation_status <- Injected ; + return_unit + | Nonce_revelation_stage -> + (* At this point the chain cannot be in the nonce revelation + * stage. This is checked in [is_in_nonce_revelation_stage]. *) + assert false) + | Finished (setup, solution) -> + (* VDF solution computed, but not injected. We are only in this case + * if the first attempt to inject, right after getting the solution, + * was unsuccessful. While the chain is in the VDF revelation stage, + * and the solution has not been injected (computation status is + * [Finished]), we try to inject. If successful, the computation + * status is updated to [Injected]. *) + inject_vdf_revelation + cctxt + state + setup + solution + chain_id + hash + level_info + | Injected -> + let*! () = + emit_with_level "Skipping, VDF solution already injected" level + in + return_unit + | Invalid -> + let*! () = emit_with_level "Skipping, failed to compute VDF" level in + return_unit + +let start_vdf_worker (cctxt : Protocol_client_context.full) ~canceler constants + chain = + let open Lwt_result_syntax in + let* block_stream, stream_stopper = + init_block_stream_with_stopper cctxt chain + in + let state = + { + cctxt; + constants; + block_stream; + stream_stopper = Some stream_stopper; + cycle = None; + computation_status = Not_started; + } + in + Lwt_canceler.on_cancel canceler (fun () -> + let*! () = maybe_kill_running_vdf_computation state in + stop_block_stream state ; + Lwt.return_unit) ; + let rec worker_loop () = + let*! b = + Lwt.choose + [ + (let*! _ = Lwt_exit.clean_up_starts in + Lwt.return `Termination); + (let*! e = Lwt_stream.get state.block_stream in + Lwt.return (`Block e)); + ] + in + match b with + | `Termination -> return_unit + | `Block (None | Some (Error _)) -> + (* Exit when the node is unavailable *) + stop_block_stream state ; + let*! () = Events.(emit vdf_daemon_connection_lost) name in + tzfail Baking_errors.Node_connection_lost + | `Block (Some (Ok bi)) -> + let*! () = + log_errors_and_continue ~name @@ process_new_block cctxt state bi + in + worker_loop () + in + worker_loop () diff --git a/src/proto_020_PsParisC/lib_delegate/baking_vdf.mli b/src/proto_020_PsParisC/lib_delegate/baking_vdf.mli new file mode 100644 index 000000000000..84751f723af8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/baking_vdf.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +val start_vdf_worker : + Protocol_client_context.full -> + canceler:Lwt_canceler.t -> + Constants.t -> + Chain_services.chain -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/block_forge.ml b/src/proto_020_PsParisC/lib_delegate/block_forge.ml new file mode 100644 index 000000000000..7338ce67d0db --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/block_forge.ml @@ -0,0 +1,511 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type unsigned_block = { + unsigned_block_header : Block_header.t; + operations : Tezos_base.Operation.t list list; +} + +type simulation_kind = + | Filter of Operation_pool.Prioritized.t + | Apply of { + ordered_pool : Operation_pool.ordered_pool; + payload_hash : Block_payload_hash.t; + } + +(* [forge_faked_protocol_data ?payload_hash ~payload_round ~seed_nonce_hash + ~liquidity_baking_toggle_vote ~adaptive_issuance_vote] forges a fake [block_header_data] with + [payload_hash] ([zero] by default), [payload_round], [seed_nonce_hash], + [liquidity_baking_toggle_vote] and with an empty [proof_of_work_nonce] and a + dummy [signature]. *) +let forge_faked_protocol_data ?(payload_hash = Block_payload_hash.zero) + ~payload_round ~seed_nonce_hash ~liquidity_baking_toggle_vote + ~adaptive_issuance_vote () = + Block_header. + { + contents = + { + payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce = Baking_pow.empty_proof_of_work_nonce; + per_block_votes = + { + liquidity_baking_vote = liquidity_baking_toggle_vote; + adaptive_issuance_vote; + }; + }; + signature = Signature.zero; + } + +let convert_operation (op : packed_operation) : Tezos_base.Operation.t = + { + shell = op.shell; + proto = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Operation.protocol_data_encoding + op.protocol_data; + } + +(* [finalize_block_header] updates the [shell_header] that was created + with dummy fields at the beginning of the block construction. It + increments the [level] and sets the actual [operations_hash], + [fitness], [validation_passes], and [context] (the predecessor + resulting context hash). + + When the operations from the block have been applied, the [fitness] + is simply retrieved from the [validation_result]. Otherwise, the + [fitness] is computed from the [round] and [locked_round] + arguments. *) +let finalize_block_header ~shell_header ~validation_result ~operations_hash + ~(pred_info : Baking_state.block_info) ~pred_resulting_context_hash ~round + ~locked_round = + let open Lwt_result_syntax in + let* fitness = + match validation_result with + | Some {Tezos_protocol_environment.fitness; _} -> return fitness + | None -> + let*? level = + Environment.wrap_tzresult @@ Raw_level.of_int32 + @@ Int32.succ shell_header.Tezos_base.Block_header.level + in + let*? fitness = + Environment.wrap_tzresult + @@ Fitness.create + ~level + ~round + ~predecessor_round:pred_info.round + ~locked_round + in + return (Fitness.to_raw fitness) + in + let validation_passes = List.length Main.validation_passes in + let header = + Tezos_base.Block_header. + { + shell_header with + level = Int32.succ shell_header.level; + validation_passes; + operations_hash; + fitness; + context = pred_resulting_context_hash; + } + in + return header + +let retain_live_operations_only ~live_blocks operation_pool = + Operation_pool.Prioritized.filter + (fun ({shell; _} : packed_operation) -> + Block_hash.Set.mem shell.branch live_blocks) + operation_pool + +(* [check_protocol_changed] checks whether the protocol will change with the current + block. This function returns true if the block is the last of an [adoption] + period. It can also return true if an [user_activated_upgrades] is given. *) +let check_protocol_changed ~user_activated_upgrades ~level + ~(validation_result : Tezos_protocol_environment.validation_result option) + ~(incremental : Baking_simulator.incremental) = + let open Lwt_result_syntax in + match + Tezos_base.Block_header.get_forced_protocol_upgrade + ~user_activated_upgrades + ~level + with + | None -> ( + match validation_result with + | None -> ( + let context = Validate.get_initial_ctxt (fst incremental.state) in + let* voting_period = + Lwt.map + Environment.wrap_tzresult + (Voting_period.get_current context) + in + match voting_period.kind with + | Voting_period.Proposal | Exploration | Cooldown | Promotion -> + return_false + | Adoption -> + Lwt.map + Environment.wrap_tzresult + (Voting_period.is_last_block context)) + | Some validation_result -> + let*! next_protocol = + Context_ops.get_protocol validation_result.context + in + return Protocol_hash.(Protocol.hash <> next_protocol)) + | Some next_protocol -> return Protocol_hash.(Protocol.hash <> next_protocol) + +(* [filter_via_node] filters operations using + {!Operation_selection.filter_operations_without_simulation} and then applies + them in a block via {!Node_rpc.preapply_block}. [filter_via_node] returns a + [shell_header], the list of operations that have been applied in the block + and the [payload_hash] corresponding to these operations. *) +let filter_via_node ~chain_id ~fees_config ~hard_gas_limit_per_block + ~faked_protocol_data ~timestamp ~(pred_info : Baking_state.block_info) + ~payload_round ~operation_pool cctxt = + let open Lwt_result_syntax in + let chain = `Hash chain_id in + let filtered_operations = + Operation_selection.filter_operations_without_simulation + fees_config + ~hard_gas_limit_per_block + operation_pool + in + let* shell_header, preapply_result = + Node_rpc.preapply_block + cctxt + ~chain + ~head:pred_info.hash + ~timestamp + ~protocol_data:faked_protocol_data + filtered_operations + in + (* only retain valid operations *) + let operations = + List.map (fun l -> List.map snd l.Preapply_result.applied) preapply_result + in + let payload_hash = + let operation_hashes = + Stdlib.List.tl operations |> List.flatten + |> List.map Tezos_base.Operation.hash + in + Block_payload.hash + ~predecessor_hash:shell_header.predecessor + ~payload_round + operation_hashes + in + return (shell_header, operations, payload_hash) + +(* [filter_with_context] filters operations using a local context via + {!Operation_selection.filter_operations_with_simulation} and a fresh state + from {!Baking_simulator.begin_construction}. [finalize_block_header] is then + called and a [shell_header], the list of operations and the corresponding + [payload_hash] are returned. If the block is a transition block, + [filter_via_node] is called to return these values. *) +let filter_with_context ~chain_id ~fees_config ~hard_gas_limit_per_block + ~faked_protocol_data ~user_activated_upgrades ~timestamp + ~(pred_info : Baking_state.block_info) ~pred_resulting_context_hash + ~force_apply ~round ~context_index ~payload_round ~operation_pool cctxt = + let open Lwt_result_syntax in + let* incremental = + Baking_simulator.begin_construction + ~timestamp + ~protocol_data:faked_protocol_data + ~force_apply + ~pred_resulting_context_hash + context_index + pred_info + chain_id + in + let* {Operation_selection.operations; validation_result; operations_hash; _} = + Operation_selection.filter_operations_with_simulation + incremental + fees_config + ~hard_gas_limit_per_block + operation_pool + in + let* changed = + check_protocol_changed + ~level:(Int32.succ pred_info.shell.level) + ~user_activated_upgrades + ~validation_result + ~incremental + in + if changed then + (* Fallback to processing via node, which knows both old and new protocol. *) + filter_via_node + ~chain_id + ~fees_config + ~hard_gas_limit_per_block + ~faked_protocol_data + ~timestamp + ~pred_info + ~payload_round + ~operation_pool + cctxt + else + let* shell_header = + finalize_block_header + ~shell_header:incremental.header + ~validation_result + ~operations_hash + ~pred_info + ~pred_resulting_context_hash + ~round + ~locked_round:None + in + let operations = List.map (List.map convert_operation) operations in + let payload_hash = + let operation_hashes = + Stdlib.List.tl operations |> List.flatten + |> List.map Tezos_base.Operation.hash + in + Block_payload.hash + ~predecessor_hash:shell_header.predecessor + ~payload_round + operation_hashes + in + return (shell_header, operations, payload_hash) + +(* [apply_via_node] applies already filtered and validated operations in a block + via {!Node_rpc.preapply_block}. A [shell_header] is recovered from this call + and returned alongside of the list of operations and the payload_hash. *) +let apply_via_node ~chain_id ~faked_protocol_data ~timestamp + ~(pred_info : Baking_state.block_info) ~ordered_pool ~payload_hash cctxt = + let open Lwt_result_syntax in + let chain = `Hash chain_id in + let operations = Operation_pool.ordered_to_list_list ordered_pool in + let* shell_header, _preapply_result = + Node_rpc.preapply_block + cctxt + ~chain + ~head:pred_info.hash + ~timestamp + ~protocol_data:faked_protocol_data + operations + in + let operations = List.map (List.map convert_operation) operations in + return (shell_header, operations, payload_hash) + +(* [apply_with_context] is similar to [filter_with_context] but filters + consensus operations only from an [ordered_pool] via + {!Operation_selection.filter_consensus_operations_only}. *) +let apply_with_context ~chain_id ~faked_protocol_data ~user_activated_upgrades + ~timestamp ~(pred_info : Baking_state.block_info) + ~pred_resulting_context_hash ~force_apply ~round ~ordered_pool + ~context_index ~payload_hash cctxt = + let open Lwt_result_syntax in + let* incremental = + Baking_simulator.begin_construction + ~timestamp + ~protocol_data:faked_protocol_data + ~force_apply + ~pred_resulting_context_hash + context_index + pred_info + chain_id + in + (* We still need to filter attestations. Two attestations could be + referring to the same slot. *) + let* incremental, ordered_pool = + Operation_selection.filter_consensus_operations_only + incremental + ordered_pool + in + let operations = Operation_pool.ordered_to_list_list ordered_pool in + let operations_hash = + Operation_list_list_hash.compute + (List.map + (fun sl -> + Operation_list_hash.compute (List.map Operation.hash_packed sl)) + operations) + in + (* We need to compute the final [operations_hash] before + finalizing the block because it will be used in the cache's nonce. *) + let incremental = + {incremental with header = {incremental.header with operations_hash}} + in + let* validation_result = Baking_simulator.finalize_construction incremental in + let validation_result = Option.map fst validation_result in + let* changed = + check_protocol_changed + ~level:(Int32.succ pred_info.shell.level) + ~user_activated_upgrades + ~validation_result + ~incremental + in + if changed then + (* Fallback to processing via node, which knows both old and new protocol. *) + apply_via_node + ~chain_id + ~faked_protocol_data + ~timestamp + ~pred_info + ~ordered_pool + ~payload_hash + cctxt + else + let locked_round_when_no_validation_result = + (* [locked_round] will not be used in [finalize_block_header] if there is + a [validation_result] *) + if Option.is_some validation_result then None + else + List.find_map + (fun {protocol_data = Operation_data protocol_data; _} -> + match protocol_data.contents with + | Single (Preattestation {round; _}) -> Some round + | _ -> None) + (Option.value (List.hd operations) ~default:[]) + in + let* shell_header = + finalize_block_header + ~shell_header:incremental.header + ~validation_result + ~operations_hash + ~pred_info + ~pred_resulting_context_hash + ~round + ~locked_round:locked_round_when_no_validation_result + in + let operations = List.map (List.map convert_operation) operations in + return (shell_header, operations, payload_hash) + +(* [forge] a new [unsigned_block] in accordance with [simulation_kind] and + [simulation_mode] *) +let forge (cctxt : #Protocol_client_context.full) ~chain_id + ~(pred_info : Baking_state.block_info) ~pred_resulting_context_hash + ~pred_live_blocks ~timestamp ~round ~liquidity_baking_toggle_vote + ~adaptive_issuance_vote ~user_activated_upgrades fees_config ~force_apply + ~seed_nonce_hash ~payload_round simulation_mode simulation_kind constants = + let open Lwt_result_syntax in + let hard_gas_limit_per_block = + constants.Constants.Parametric.hard_gas_limit_per_block + in + let simulation_kind = + match simulation_kind with + | Filter operation_pool -> + (* We cannot include operations that are not live with respect + to our predecessor otherwise the node would reject the block. *) + let filtered_pool = + retain_live_operations_only + ~live_blocks:pred_live_blocks + operation_pool + in + Filter filtered_pool + | Apply _ as x -> x + in + let* shell_header, operations, payload_hash = + match (simulation_mode, simulation_kind) with + | Baking_state.Node, Filter operation_pool -> + let faked_protocol_data = + forge_faked_protocol_data + ~payload_round + ~seed_nonce_hash + ~liquidity_baking_toggle_vote + ~adaptive_issuance_vote + () + in + filter_via_node + ~chain_id + ~faked_protocol_data + ~fees_config + ~hard_gas_limit_per_block + ~timestamp + ~pred_info + ~payload_round + ~operation_pool + cctxt + | Node, Apply {ordered_pool; payload_hash} -> + let faked_protocol_data = + forge_faked_protocol_data + ~payload_hash + ~payload_round + ~seed_nonce_hash + ~liquidity_baking_toggle_vote + ~adaptive_issuance_vote + () + in + apply_via_node + ~chain_id + ~faked_protocol_data + ~timestamp + ~pred_info + ~ordered_pool + ~payload_hash + cctxt + | Local context_index, Filter operation_pool -> + let faked_protocol_data = + forge_faked_protocol_data + ~payload_round + ~seed_nonce_hash + ~liquidity_baking_toggle_vote + ~adaptive_issuance_vote + () + in + filter_with_context + ~chain_id + ~faked_protocol_data + ~fees_config + ~hard_gas_limit_per_block + ~user_activated_upgrades + ~timestamp + ~pred_info + ~pred_resulting_context_hash + ~force_apply + ~round + ~context_index + ~payload_round + ~operation_pool + cctxt + | Local context_index, Apply {ordered_pool; payload_hash} -> + let faked_protocol_data = + forge_faked_protocol_data + ~payload_hash + ~payload_round + ~seed_nonce_hash + ~liquidity_baking_toggle_vote + ~adaptive_issuance_vote + () + in + apply_with_context + ~chain_id + ~faked_protocol_data + ~user_activated_upgrades + ~timestamp + ~pred_info + ~pred_resulting_context_hash + ~force_apply + ~round + ~ordered_pool + ~context_index + ~payload_hash + cctxt + in + let* contents = + Baking_pow.mine + ~proof_of_work_threshold:constants.proof_of_work_threshold + shell_header + (fun proof_of_work_nonce -> + { + Block_header.payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce; + per_block_votes = + { + liquidity_baking_vote = liquidity_baking_toggle_vote; + adaptive_issuance_vote; + }; + }) + in + let unsigned_block_header = + { + Block_header.shell = shell_header; + protocol_data = {contents; signature = Signature.zero}; + } + in + return {unsigned_block_header; operations} diff --git a/src/proto_020_PsParisC/lib_delegate/block_forge.mli b/src/proto_020_PsParisC/lib_delegate/block_forge.mli new file mode 100644 index 000000000000..e85bc5f1fc61 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/block_forge.mli @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type unsigned_block = { + unsigned_block_header : Block_header.t; + operations : Tezos_base.Operation.t list list; +} + +(** The simulation kind specifies whether the baker should first filter (and + then apply) the provided operations, or just apply them. The former case is + used for fresh proposals, while the latter for re-proposals (of an already + proposed payload). *) +type simulation_kind = + | Filter of Operation_pool.Prioritized.t + | Apply of { + ordered_pool : Operation_pool.ordered_pool; + payload_hash : Block_payload_hash.t; + } + +val forge : + #Protocol_client_context.full -> + chain_id:Chain_id.t -> + pred_info:Baking_state.block_info -> + pred_resulting_context_hash:Context_hash.t -> + pred_live_blocks:Block_hash.Set.t -> + timestamp:Time.Protocol.t -> + round:Round.t -> + liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + adaptive_issuance_vote:Per_block_votes.per_block_vote -> + user_activated_upgrades:User_activated.upgrades -> + Baking_configuration.fees_config -> + force_apply:bool -> + seed_nonce_hash:Nonce_hash.t option -> + payload_round:Round.t -> + Baking_state.validation_mode -> + simulation_kind -> + Constants.Parametric.t -> + unsigned_block tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/client_baking_blocks.ml b/src/proto_020_PsParisC/lib_delegate/client_baking_blocks.ml new file mode 100644 index 000000000000..ece92bc3bb67 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_baking_blocks.ml @@ -0,0 +1,217 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_errors + +type block_info = { + hash : Block_hash.t; + chain_id : Chain_id.t; + predecessor : Block_hash.t; + fitness : Bytes.t list; + timestamp : Time.Protocol.t; + protocol : Protocol_hash.t; + next_protocol : Protocol_hash.t; + proto_level : int; + level : Raw_level.t; + context : Context_hash.t; +} + +let raw_info cctxt ?(chain = `Main) hash shell_header = + let open Lwt_result_syntax in + let block = `Hash (hash, 0) in + let* chain_id = Shell_services.Chain.chain_id cctxt ~chain () in + let* {current_protocol = protocol; next_protocol} = + Shell_services.Blocks.protocols cctxt ~chain ~block () + in + let { + Tezos_base.Block_header.predecessor; + fitness; + timestamp; + level; + context; + proto_level; + _; + } = + shell_header + in + match Raw_level.of_int32 level with + | Ok level -> + return + { + hash; + chain_id; + predecessor; + fitness; + timestamp; + protocol; + next_protocol; + proto_level; + level; + context; + } + | Error _ -> failwith "Cannot convert level into int32" + +let info cctxt ?(chain = `Main) block = + let open Lwt_result_syntax in + let* hash = Shell_services.Blocks.hash cctxt ~chain ~block () in + let* shell_header = + Shell_services.Blocks.Header.shell_header cctxt ~chain ~block () + in + raw_info cctxt ~chain hash shell_header + +module Block_seen_event = struct + type t = { + hash : Block_hash.t; + header : Tezos_base.Block_header.t; + occurrence : [`Valid_blocks of Chain_id.t | `Heads]; + } + + let make hash header occurrence = {hash; header; occurrence} + + module Definition = struct + let section = None + + let name = "block-seen-" ^ Protocol.name + + type nonrec t = t + + let encoding = + let open Data_encoding in + let v0_encoding = + conv + (function {hash; header; occurrence} -> (hash, occurrence, header)) + (fun (hash, occurrence, header) -> make hash header occurrence) + (obj3 + (req "hash" Block_hash.encoding) + (* Occurrence has to come before header, because: + (Invalid_argument + "Cannot merge two objects when the left element is of + variable length and the right one of dynamic + length. You should use the reverse order, or wrap the + second one with Data_encoding.dynamic_size.") *) + (req + "occurrence" + (union + [ + case + ~title:"heads" + (Tag 0) + (obj1 (req "occurrence-kind" (constant "heads"))) + (function `Heads -> Some () | _ -> None) + (fun () -> `Heads); + case + ~title:"valid-blocks" + (Tag 1) + (obj2 + (req "occurrence-kind" (constant "valid-blocks")) + (req "chain-id" Chain_id.encoding)) + (function + | `Valid_blocks ch -> Some ((), ch) | _ -> None) + (fun ((), ch) -> `Valid_blocks ch); + ])) + (req "header" Tezos_base.Block_header.encoding)) + in + With_version.(encoding ~name (first_version v0_encoding)) + + let pp ~all_fields:_ ~block:_ ppf {hash; _} = + Format.fprintf ppf "Saw block %a" Block_hash.pp_short hash + + let doc = "Block observed while monitoring a blockchain." + + let level = Internal_event.Info + end + + module Event = Internal_event.Make (Definition) +end + +let monitor_applied_blocks cctxt ?chains ?protocols ~next_protocols () = + let open Lwt_result_syntax in + let* block_stream, stop = + Monitor_services.applied_blocks cctxt ?chains ?protocols ?next_protocols () + in + return + ( Lwt_stream.map_s + (fun (chain, block, header, _ops) -> + let* () = + Block_seen_event.( + Event.emit (make block header (`Valid_blocks chain))) + in + raw_info + cctxt + ~chain:(`Hash chain) + block + header.Tezos_base.Block_header.shell) + block_stream, + stop ) + +let monitor_heads cctxt ~next_protocols chain = + let open Lwt_result_syntax in + let* block_stream, stop = + Monitor_services.heads cctxt ?next_protocols chain + in + return + ( Lwt_stream.map_s + (fun (block, ({Tezos_base.Block_header.shell; _} as header)) -> + let* () = Block_seen_event.(Event.emit (make block header `Heads)) in + raw_info cctxt ~chain block shell) + block_stream, + stop ) + +let blocks_from_current_cycle cctxt ?(chain = `Main) block ?(offset = 0l) () = + let open Lwt_result_syntax in + let* hash = Shell_services.Blocks.hash cctxt ~chain ~block () in + let* {level; _} = + Shell_services.Blocks.Header.shell_header cctxt ~chain ~block () + in + let*! result = + Plugin.RPC.levels_in_current_cycle cctxt ~offset (chain, block) + in + match result with + | Error (Tezos_rpc.Context.Not_found _ :: _) -> return_nil + | Error _ as err -> Lwt.return err + | Ok (first, last) -> + let length = Int32.to_int (Int32.sub level (Raw_level.to_int32 first)) in + let* head = + let* list = + Shell_services.Blocks.list cctxt ~chain ~heads:[hash] ~length () + in + match list with + | hd :: _ -> return hd + | [] -> + tzfail + (Unexpected_empty_block_list + { + chain = Block_services.chain_to_string chain; + block_hash = hash; + length; + }) + in + let blocks = + List.drop_n (length - Int32.to_int (Raw_level.diff last first)) head + in + if Int32.equal level (Raw_level.to_int32 last) then return (hash :: blocks) + else return blocks diff --git a/src/proto_020_PsParisC/lib_delegate/client_baking_blocks.mli b/src/proto_020_PsParisC/lib_delegate/client_baking_blocks.mli new file mode 100644 index 000000000000..8426c19b8994 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_baking_blocks.mli @@ -0,0 +1,68 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type block_info = { + hash : Block_hash.t; + chain_id : Chain_id.t; + predecessor : Block_hash.t; + fitness : Bytes.t list; + timestamp : Time.Protocol.t; + protocol : Protocol_hash.t; + next_protocol : Protocol_hash.t; + proto_level : int; + level : Raw_level.t; + context : Context_hash.t; +} + +val info : + #Protocol_client_context.rpc_context -> + ?chain:Chain_services.chain -> + Block_services.block -> + block_info tzresult Lwt.t + +val monitor_applied_blocks : + #Protocol_client_context.rpc_context -> + ?chains:Chain_services.chain list -> + ?protocols:Protocol_hash.t list -> + next_protocols:Protocol_hash.t list option -> + unit -> + (block_info tzresult Lwt_stream.t * Tezos_rpc.Context.stopper) tzresult Lwt.t + +val monitor_heads : + #Protocol_client_context.rpc_context -> + next_protocols:Protocol_hash.t list option -> + Chain_services.chain -> + (block_info tzresult Lwt_stream.t * Tezos_rpc.Context.stopper) tzresult Lwt.t + +val blocks_from_current_cycle : + #Protocol_client_context.rpc_context -> + ?chain:Chain_services.chain -> + Block_services.block -> + ?offset:int32 -> + unit -> + Block_hash.t list tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.ml b/src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.ml new file mode 100644 index 000000000000..7ffdd3e924c0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.ml @@ -0,0 +1,639 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context +open Client_baking_blocks +module Events = Delegate_events.Denunciator +module B_Events = Delegate_events.Baking_scheduling + +module HLevel = Hashtbl.Make (struct + type t = Chain_id.t * Raw_level.t * Round.t + + let equal (c, l, r) (c', l', r') = + Chain_id.equal c c' && Raw_level.equal l l' && Round.equal r r' + + let hash (c, lvl, r) = Hashtbl.hash (c, lvl, r) +end) + +(* Blocks are associated to the delegates who baked them *) +module Delegate_map = Signature.Public_key_hash.Map + +module Validators_cache = + Aches.Vache.Map (Aches.Vache.FIFO_Precise) (Aches.Vache.Strong) + (struct + type t = Raw_level.t + + let equal = Raw_level.equal + + let hash = Hashtbl.hash + end) + +(* type of operations stream, as returned by monitor_operations RPC *) +type ops_stream = + ((Operation_hash.t * packed_operation) * error trace option) list Lwt_stream.t + +type 'kind recorded_consensus = + | No_operation_seen + | Operation_seen of { + operation : 'kind operation; + previously_denounced_oph : Operation_hash.t option; + } + +type recorded_consensus_operations = { + attestation : Kind.attestation recorded_consensus; + preattestation : Kind.preattestation recorded_consensus; +} + +type 'a state = { + (* Validators rights for the last preserved levels *) + validators_rights : public_key_hash Slot.Map.t Validators_cache.t; + (* Consensus operations seen so far *) + consensus_operations_table : + recorded_consensus_operations Delegate_map.t HLevel.t; + (* Blocks received so far *) + blocks_table : Block_hash.t Delegate_map.t HLevel.t; + (* Maximum delta of level to register *) + preserved_levels : int; + (* Highest level seen in a block *) + mutable highest_level_encountered : Raw_level.t; + (* This constant allows to set at which frequency (expressed in blocks levels) + the tables above are cleaned. Cleaning the table means removing information + stored about old levels up to + 'highest_level_encountered - preserved_levels'. + *) + clean_frequency : int; + (* the decreasing cleaning countdown for the next cleaning *) + mutable cleaning_countdown : int; + (* stream of all valid blocks *) + blocks_stream : (block_info, 'a) result Lwt_stream.t; + (* operations stream. Reset on new heads flush *) + mutable ops_stream : ops_stream; + (* operatons stream stopper. Used when a q new *) + mutable ops_stream_stopper : unit -> unit; +} + +let create_state ~preserved_levels blocks_stream ops_stream ops_stream_stopper = + let clean_frequency = max 1 (preserved_levels / 10) in + let validators_rights = Validators_cache.create (preserved_levels + 2) in + (* We keep rights for [preserved_levels] in the past, and 2 levels in the + future from [highest_level_encountered] *) + Lwt.return + { + validators_rights; + consensus_operations_table = HLevel.create preserved_levels; + blocks_table = HLevel.create preserved_levels; + preserved_levels; + highest_level_encountered = Raw_level.root (* 0l *); + clean_frequency; + cleaning_countdown = clean_frequency; + blocks_stream; + ops_stream; + ops_stream_stopper; + } + +(* We choose a previous offset (5 blocks from head) to ensure that the + injected operation is branched from a valid + predecessor. Denunciation operations can be emitted when the + consensus is under attack and may occur so you want to inject the + operation from a block which is considered "final". *) +let get_block_offset level = + let open Lwt_syntax in + match Raw_level.of_int32 5l with + | Ok min_level -> + let offset = Raw_level.diff level min_level in + if Compare.Int32.(offset >= 0l) then return (`Head 5) + else + (* offset < 0l *) + let negative_offset = Int32.to_int offset in + (* We cannot inject at at level 0 : this is the genesis + level. We inject starting from level 1 thus the '- 1'. *) + return (`Head (5 + negative_offset - 1)) + | Error errs -> + let* () = + Events.(emit invalid_level_conversion) (Environment.wrap_tztrace errs) + in + return (`Head 0) + +let get_payload_hash (type kind) (op_kind : kind consensus_operation_type) + (op : kind Operation.t) = + match (op_kind, op.protocol_data.contents) with + | Preattestation, Single (Preattestation consensus_content) + | Attestation, Single (Attestation {consensus_content; _}) -> + consensus_content.block_payload_hash + +let get_slot (type kind) (op_kind : kind consensus_operation_type) + (op : kind Operation.t) = + match (op_kind, op.protocol_data.contents) with + | Preattestation, Single (Preattestation consensus_content) + | Attestation, Single (Attestation {consensus_content; _}) -> + consensus_content.slot + +let double_consensus_op_evidence (type kind) : + kind consensus_operation_type -> + #Protocol_client_context.full -> + 'a -> + branch:Block_hash.t -> + op1:kind Alpha_context.operation -> + op2:kind Alpha_context.operation -> + unit -> + bytes Environment.Error_monad.shell_tzresult Lwt.t = function + | Attestation -> Plugin.RPC.Forge.double_attestation_evidence + | Preattestation -> Plugin.RPC.Forge.double_preattestation_evidence + +let lookup_recorded_consensus (type kind) consensus_key + (op_kind : kind consensus_operation_type) map : kind recorded_consensus = + match Delegate_map.find consensus_key map with + | None -> No_operation_seen + | Some {attestation; preattestation} -> ( + match op_kind with + | Attestation -> attestation + | Preattestation -> preattestation) + +let add_consensus_operation (type kind) consensus_key + (op_kind : kind consensus_operation_type) + (recorded_operation : kind recorded_consensus) map = + Delegate_map.update + consensus_key + (fun x -> + let record = + Option.value + ~default: + { + attestation = No_operation_seen; + preattestation = No_operation_seen; + } + x + in + match op_kind with + | Attestation -> Some {record with attestation = recorded_operation} + | Preattestation -> Some {record with preattestation = recorded_operation}) + map + +let get_validator_rights state cctxt level = + let open Lwt_result_syntax in + match Validators_cache.find_opt state.validators_rights level with + | None -> + let* validators = + Plugin.RPC.Validators.get cctxt (cctxt#chain, `Head 0) ~levels:[level] + in + let validators = + List.fold_left + (fun acc ({consensus_key; slots; _} : RPC.Validators.t) -> + List.fold_left + (fun acc slot -> Slot.Map.add slot consensus_key acc) + acc + slots) + Slot.Map.empty + validators + in + Validators_cache.replace state.validators_rights level validators ; + return validators + | Some t -> return t + +let process_consensus_op (type kind) state cctxt + (op_kind : kind consensus_operation_type) (new_op : kind Operation.t) + chain_id level round slot = + let open Lwt_result_syntax in + let diff = Raw_level.diff state.highest_level_encountered level in + if Int32.(diff > of_int state.preserved_levels) then + (* We do not handle operations older than [preserved_levels] *) + let*! () = + Events.(emit consensus_operation_too_old) (Operation.hash new_op) + in + return_unit + else if diff < -2l then + (* We do not handle operations too far in the future *) + let*! () = + Events.(emit consensus_operation_too_far_in_future) + (Operation.hash new_op) + in + return_unit + else + let* attesting_rights = get_validator_rights state cctxt level in + match Slot.Map.find slot attesting_rights with + | None -> + (* We do not handle operations that do not have a valid slot *) + return_unit + | Some consensus_key -> ( + let round_map = + Option.value ~default:Delegate_map.empty + @@ HLevel.find + state.consensus_operations_table + (chain_id, level, round) + in + match lookup_recorded_consensus consensus_key op_kind round_map with + | No_operation_seen -> + return + @@ HLevel.add + state.consensus_operations_table + (chain_id, level, round) + (add_consensus_operation + consensus_key + op_kind + (Operation_seen + {operation = new_op; previously_denounced_oph = None}) + round_map) + | Operation_seen {operation = existing_op; previously_denounced_oph} + when Block_payload_hash.( + get_payload_hash op_kind existing_op + <> get_payload_hash op_kind new_op) + || Slot.(get_slot op_kind existing_op <> slot) + || Block_hash.(existing_op.shell.branch <> new_op.shell.branch) + -> + (* Same level, round, and delegate, and: + different payload hash OR different slot OR different branch *) + let new_op_hash, existing_op_hash = + (Operation.hash new_op, Operation.hash existing_op) + in + let op1, op2 = + if Operation_hash.(new_op_hash < existing_op_hash) then + (new_op, existing_op) + else (existing_op, new_op) + in + let*! block = get_block_offset level in + let chain = `Hash chain_id in + let* block_hash = + Alpha_block_services.hash cctxt ~chain ~block () + in + let* bytes = + double_consensus_op_evidence + op_kind + cctxt + (`Hash chain_id, block) + ~branch:block_hash + ~op1 + ~op2 + () + in + let bytes = Signature.concat bytes Signature.zero in + let double_op_detected, double_op_denounced = + Events.( + match op_kind with + | Attestation -> + (double_attestation_detected, double_attestation_denounced) + | Preattestation -> + ( double_preattestation_detected, + double_preattestation_denounced )) + in + let*! () = + Events.(emit double_op_detected) (new_op_hash, existing_op_hash) + in + let* op_hash = + Shell_services.Injection.private_operation cctxt ~chain bytes + in + let*! () = + match previously_denounced_oph with + | Some oph -> Events.(emit double_consensus_already_denounced) oph + | None -> Lwt.return_unit + in + HLevel.replace + state.consensus_operations_table + (chain_id, level, round) + (add_consensus_operation + consensus_key + op_kind + (Operation_seen + { + operation = new_op; + previously_denounced_oph = Some op_hash; + }) + round_map) ; + let*! () = Events.(emit double_op_denounced) (op_hash, bytes) in + return_unit + | _ -> return_unit) + +let process_operations (cctxt : #Protocol_client_context.full) state + (attestations : 'a list) ~packed_op chain_id = + let open Lwt_result_syntax in + List.iter_es + (fun op -> + let {shell; protocol_data; _} = packed_op op in + match protocol_data with + | Operation_data + ({contents = Single (Preattestation {round; slot; level; _}); _} as + protocol_data) -> + let new_preattestation : Kind.preattestation Alpha_context.operation = + {shell; protocol_data} + in + process_consensus_op + state + cctxt + Preattestation + new_preattestation + chain_id + level + round + slot + | Operation_data + ({ + contents = + Single + (Attestation {consensus_content = {round; slot; level; _}; _}); + _; + } as protocol_data) -> + let new_attestation : Kind.attestation Alpha_context.operation = + {shell; protocol_data} + in + process_consensus_op + state + cctxt + Attestation + new_attestation + chain_id + level + round + slot + | _ -> + (* not a consensus operation *) + return_unit) + attestations + +let context_block_header cctxt ~chain b_hash = + let open Lwt_result_syntax in + let* ({shell; protocol_data; _} : Alpha_block_services.block_header) = + Alpha_block_services.header cctxt ~chain ~block:(`Hash (b_hash, 0)) () + in + return {Alpha_context.Block_header.shell; protocol_data} + +let process_block (cctxt : #Protocol_client_context.full) state + (header : Alpha_block_services.block_info) = + let open Lwt_result_syntax in + match header with + | {hash; metadata = None; _} -> + let*! () = Events.(emit unexpected_pruned_block) hash in + return_unit + | { + Alpha_block_services.chain_id; + hash = new_hash; + metadata = Some {protocol_data = {baker; level_info = {level; _}; _}; _}; + header = {shell = {fitness; _}; _}; + _; + } -> ( + let fitness = Fitness.from_raw fitness in + let*? round = + match fitness with + | Ok fitness -> Ok (Fitness.round fitness) + | Error errs -> Error (Environment.wrap_tztrace errs) + in + let chain = `Hash chain_id in + let map = + Option.value ~default:Delegate_map.empty + @@ HLevel.find state.blocks_table (chain_id, level, round) + in + match Delegate_map.find baker.delegate map with + | None -> + return + @@ HLevel.add + state.blocks_table + (chain_id, level, round) + (Delegate_map.add baker.delegate new_hash map) + | Some existing_hash when Block_hash.(existing_hash = new_hash) -> + (* This case should never happen *) + let*! () = Events.(emit double_baking_but_not) () in + return + @@ HLevel.replace + state.blocks_table + (chain_id, level, round) + (Delegate_map.add baker.delegate new_hash map) + | Some existing_hash -> + (* If a previous block made by this pkh is found for + the same (level, round) we inject a double_baking_evidence *) + let* bh1 = context_block_header cctxt ~chain existing_hash in + let* bh2 = context_block_header cctxt ~chain new_hash in + let hash1 = Block_header.hash bh1 in + let hash2 = Block_header.hash bh2 in + let bh1, bh2 = + if Block_hash.(hash1 < hash2) then (bh1, bh2) else (bh2, bh1) + in + (* If the blocks are on different chains then skip it *) + let*! block = get_block_offset level in + let* block_hash = Alpha_block_services.hash cctxt ~chain ~block () in + let* bytes = + Plugin.RPC.Forge.double_baking_evidence + cctxt + (chain, block) + ~branch:block_hash + ~bh1 + ~bh2 + () + in + let bytes = Signature.concat bytes Signature.zero in + let*! () = Events.(emit double_baking_detected) () in + let* op_hash = + Shell_services.Injection.operation cctxt ~chain bytes + in + let*! () = Events.(emit double_baking_denounced) (op_hash, bytes) in + return + @@ HLevel.replace + state.blocks_table + (chain_id, level, round) + (Delegate_map.add baker.delegate new_hash map)) + +(* Remove levels that are lower than the + [highest_level_encountered] minus [preserved_levels] *) +let cleanup_old_operations state = + state.cleaning_countdown <- state.cleaning_countdown - 1 ; + if state.cleaning_countdown < 0 then ( + (* It's time to remove old levels *) + state.cleaning_countdown <- state.clean_frequency ; + let highest_level_encountered = + Int32.to_int (Raw_level.to_int32 state.highest_level_encountered) + in + let diff = highest_level_encountered - state.preserved_levels in + let threshold = + if diff < 0 then Raw_level.root + else + Raw_level.of_int32 (Int32.of_int diff) |> function + | Ok threshold -> threshold + | Error _ -> Raw_level.root + in + let filter hmap = + HLevel.filter_map_inplace + (fun (_, level, _) x -> + if Raw_level.(level < threshold) then None else Some x) + hmap + in + filter state.consensus_operations_table ; + filter state.blocks_table) + +(* Each new block is processed : + - Check that every baker injected a proposal only once at the block's level and round + - Check that every baker (pre)attested only once at the block's level and round +*) +let process_new_block (cctxt : #Protocol_client_context.full) state + {hash; chain_id; level; protocol; next_protocol; _} = + let open Lwt_result_syntax in + if Protocol_hash.(protocol <> next_protocol) then + let*! () = Events.(emit protocol_change_detected) () in + return_unit + else + let*! () = Events.(emit accuser_saw_block) (level, hash) in + let chain = `Hash chain_id in + let block = `Hash (hash, 0) in + state.highest_level_encountered <- + Raw_level.max level state.highest_level_encountered ; + (* Processing blocks *) + let* () = + let*! block_info = Alpha_block_services.info cctxt ~chain ~block () in + match block_info with + | Ok block_info -> ( + let* () = process_block cctxt state block_info in + (* Processing (pre)attestations in the block *) + match block_info.operations with + | consensus_ops :: _ -> + let packed_op {Alpha_block_services.shell; protocol_data; _} = + {shell; protocol_data} + in + process_operations cctxt state consensus_ops ~packed_op chain_id + | _ -> + (* Should not happen as a block should contain 4 lists of + operations, the first list being dedicated to consensus + operations. *) + let*! () = Events.(emit fetch_operations_error hash) in + return_unit) + | Error errs -> + let*! () = Events.(emit accuser_block_error) (hash, errs) in + return_unit + in + cleanup_old_operations state ; + return_unit + +let process_new_block cctxt state bi = + let open Lwt_syntax in + let* result = process_new_block cctxt state bi in + match result with + | Ok () -> + let* () = Events.(emit accuser_processed_block) bi.hash in + return_unit + | Error errs -> + let* () = Events.(emit accuser_block_error) (bi.hash, errs) in + return_unit + +let log_errors_and_continue ~name p = + let open Lwt_syntax in + let* result = p in + match result with + | Ok () -> return_unit + | Error errs -> B_Events.(emit daemon_error) (name, errs) + +let start_ops_monitor cctxt = + Alpha_block_services.Mempool.monitor_operations + cctxt + ~chain:cctxt#chain + ~validated:true + ~branch_delayed:true + ~branch_refused:false + ~refused:false + ~outdated:false + () + +let create (cctxt : #Protocol_client_context.full) ?canceler ~preserved_levels + valid_blocks_stream = + let open Lwt_result_syntax in + let*! () = B_Events.(emit daemon_setup) name in + let* ops_stream, ops_stream_stopper = start_ops_monitor cctxt in + let*! state = + create_state + ~preserved_levels + valid_blocks_stream + ops_stream + ops_stream_stopper + in + Option.iter + (fun canceler -> + Lwt_canceler.on_cancel canceler (fun () -> + state.ops_stream_stopper () ; + Lwt.return_unit)) + canceler ; + let last_get_block = ref None in + let get_block () = + match !last_get_block with + | None -> + let t = + let*! e = Lwt_stream.get state.blocks_stream in + Lwt.return (`Block e) + in + last_get_block := Some t ; + t + | Some t -> t + in + let last_get_ops = ref None in + let get_ops () = + match !last_get_ops with + | None -> + let t = + let*! e = Lwt_stream.get state.ops_stream in + Lwt.return (`Operations e) + in + last_get_ops := Some t ; + t + | Some t -> t + in + let* chain_id = Chain_services.chain_id cctxt () in + (* main loop *) + (* Only allocate once the termination promise *) + let terminated = + let*! _ = Lwt_exit.clean_up_starts in + Lwt.return `Termination + in + let rec worker_loop () = + let*! result = Lwt.choose [terminated; get_block (); get_ops ()] in + match result with + (* event matching *) + | `Termination -> return_unit + | `Block (None | Some (Error _)) -> + (* exit when the node is unavailable *) + last_get_block := None ; + let*! () = B_Events.(emit daemon_connection_lost) name in + tzfail Baking_errors.Node_connection_lost + | `Block (Some (Ok bi)) -> + last_get_block := None ; + let*! () = process_new_block cctxt state bi in + worker_loop () + | `Operations None -> + (* restart a new operations monitor stream *) + last_get_ops := None ; + state.ops_stream_stopper () ; + let* ops_stream, ops_stream_stopper = start_ops_monitor cctxt in + state.ops_stream <- ops_stream ; + state.ops_stream_stopper <- ops_stream_stopper ; + worker_loop () + | `Operations (Some ops) -> + last_get_ops := None ; + let*! () = + log_errors_and_continue ~name + @@ process_operations + cctxt + state + ops + ~packed_op:(fun ((_h, op), _errl) -> op) + chain_id + in + worker_loop () + in + let*! () = B_Events.(emit daemon_start) name in + worker_loop () diff --git a/src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.mli b/src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.mli new file mode 100644 index 000000000000..46e784d132b4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_baking_denunciation.mli @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val create : + #Protocol_client_context.full -> + ?canceler:Lwt_canceler.t -> + preserved_levels:int -> + Client_baking_blocks.block_info tzresult Lwt_stream.t -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.ml b/src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.ml new file mode 100644 index 000000000000..f34bf9da1c20 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.ml @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Events = Delegate_events.Baking_scheduling + +let sleep_until time = + (* Sleeping is a system op, baking is a protocol op, this is where we convert *) + let time = Time.System.of_protocol_exn time in + let delay = Ptime.diff time (Time.System.now ()) in + if Ptime.Span.compare delay Ptime.Span.zero < 0 then None + else Some (Lwt_unix.sleep (Ptime.Span.to_float_s delay)) diff --git a/src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.mli b/src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.mli new file mode 100644 index 000000000000..ae4a323ca1cc --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_baking_scheduling.mli @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val sleep_until : Time.Protocol.t -> unit Lwt.t option + +(* val wait_for_first_event : + * name:string -> 'event tzresult Lwt_stream.t -> 'event Lwt.t + * + * val main : + * name:string -> + * cctxt:(#Protocol_client_context.full as 'a) -> + * stream:'event tzresult Lwt_stream.t -> + * state_maker:('event -> 'state tzresult Lwt.t) -> + * pre_loop:('a -> 'state -> 'event -> unit tzresult Lwt.t) -> + * compute_timeout:('state -> 'timesup Lwt.t) -> + * timeout_k:('a -> 'state -> 'timesup -> unit tzresult Lwt.t) -> + * event_k:('a -> 'state -> 'event -> unit tzresult Lwt.t) -> + * finalizer:('state -> unit Lwt.t) -> + * unit tzresult Lwt.t *) + +(** [main ~name ~cctxt ~stream ~state_maker ~pre_loop ~timeout_maker ~timeout_k + ~event_k] is an infinitely running loop that + monitors new events arriving on [stream]. The loop exits when the + [stream] gives an error. + + The function [pre_loop] is called before the loop starts. + + The loop maintains a state (of type ['state]) initialized by [state_maker] + and passed to the callbacks [timeout_maker] (used to set up waking-up + timeouts), [timeout_k] (when a computed timeout happens), and [event_k] + (when a new event arrives on the stream). +*) diff --git a/src/proto_020_PsParisC/lib_delegate/client_daemon.ml b/src/proto_020_PsParisC/lib_delegate/client_daemon.ml new file mode 100644 index 000000000000..2c7d29d0124e --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_daemon.ml @@ -0,0 +1,229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let rec retry_on_disconnection (cctxt : #Protocol_client_context.full) f = + let open Lwt_result_syntax in + let*! result = f () in + match result with + | Ok () -> return_unit + | Error (Baking_errors.Node_connection_lost :: _) -> + let*! () = + cctxt#warning + "Lost connection with the node. Retrying to establish connection..." + in + (* Wait forever when the node stops responding... *) + let* () = + Client_confirmations.wait_for_bootstrapped + ~retry: + (Baking_scheduling.retry + cctxt + ~max_delay:10. + ~delay:1. + ~factor:1.5 + ~tries:max_int) + cctxt + in + retry_on_disconnection cctxt f + | Error err -> + cctxt#error "Unexpected error: %a. Exiting..." pp_print_trace err + +let await_protocol_start (cctxt : #Protocol_client_context.full) ~chain = + let open Lwt_result_syntax in + let*! () = + cctxt#message "Waiting for protocol %s to start..." Protocol.name + in + Node_rpc.await_protocol_activation cctxt ~chain () + +module Baker = struct + let run (cctxt : Protocol_client_context.full) ?minimal_fees + ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?votes + ?extra_operations ?dal_node_endpoint ?pre_emptive_forge_time ?force_apply + ?context_path ?state_recorder ~chain ~keep_alive delegates = + let open Lwt_result_syntax in + let process () = + let* user_activated_upgrades = + Config_services.user_activated_upgrades cctxt + in + let* constants = + let* chain_id = + Shell_services.Chain.chain_id cctxt ~chain:cctxt#chain () + in + Protocol.Alpha_services.Constants.all cctxt (`Hash chain_id, `Head 0) + in + let block_time_s = + Int64.to_float + (Protocol.Alpha_context.Period.to_seconds + constants.parametric.minimal_block_delay) + in + let* pre_emptive_forge_time = + match Option.map Q.to_float pre_emptive_forge_time with + | Some t -> + if t >= block_time_s then + failwith + "pre-emptive-forge-time must be less than current block time \ + (<= %f seconds)" + block_time_s + else return t + | None -> return (Float.mul 0.15 block_time_s) + in + let*! () = + if pre_emptive_forge_time <> 0. then + cctxt#message + "pre-emptive-forge-time optimization set to %fs. Operation \ + inclusion window is ~%fs. Caution: Setting this too high may \ + result in reduced block proposal rewards." + pre_emptive_forge_time + (Float.sub block_time_s pre_emptive_forge_time) + else Lwt.return_unit + in + let pre_emptive_forge_time = + Time.System.Span.of_seconds_exn pre_emptive_forge_time + in + let config = + Baking_configuration.make + ?minimal_fees + ?minimal_nanotez_per_gas_unit + ?minimal_nanotez_per_byte + ?votes + ?extra_operations + ?dal_node_endpoint + ~pre_emptive_forge_time + ?force_apply + ?context_path + ~user_activated_upgrades + ?state_recorder + () + in + let*! () = + cctxt#message + "Baker %a (%s) for %a started." + Tezos_version.Version.pp_simple + Tezos_version_value.Current_git_info.octez_version + Tezos_version_value.Current_git_info.abbreviated_commit_hash + Protocol_hash.pp_short + Protocol.hash + in + let canceler = Lwt_canceler.create () in + let _ = + Lwt_exit.register_clean_up_callback ~loc:__LOC__ (fun _ -> + let*! () = cctxt#message "Shutting down the baker..." in + let*! _ = Lwt_canceler.cancel canceler in + Lwt.return_unit) + in + let* () = + let* dal_config = Node_rpc.fetch_dal_config cctxt in + let*? () = Cryptobox.Config.init_verifier_dal dal_config in + return_unit + in + let consumer = Protocol_logging.make_log_message_consumer () in + Lifted_protocol.set_log_message_consumer consumer ; + Baking_scheduling.run cctxt ~canceler ~chain ~constants config delegates + in + let* () = + Client_confirmations.wait_for_bootstrapped + ~retry:(Baking_scheduling.retry cctxt ~delay:1. ~factor:1.5 ~tries:5) + cctxt + in + let* () = await_protocol_start cctxt ~chain in + if keep_alive then retry_on_disconnection cctxt process else process () +end + +module Accuser = struct + let run (cctxt : #Protocol_client_context.full) ~chain ~preserved_levels + ~keep_alive = + let open Lwt_result_syntax in + let process () = + let*! () = + cctxt#message + "Accuser %a (%s) for %a started." + Tezos_version.Version.pp_simple + Tezos_version_value.Current_git_info.octez_version + Tezos_version_value.Current_git_info.abbreviated_commit_hash + Protocol_hash.pp_short + Protocol.hash + in + let* valid_blocks_stream, _ = + Client_baking_blocks.monitor_applied_blocks + ~next_protocols:(Some [Protocol.hash]) + cctxt + ~chains:[chain] + () + in + let canceler = Lwt_canceler.create () in + let _ = + Lwt_exit.register_clean_up_callback ~loc:__LOC__ (fun _ -> + let*! () = cctxt#message "Shutting down the accuser..." in + let*! _ = Lwt_canceler.cancel canceler in + Lwt.return_unit) + in + Client_baking_denunciation.create + cctxt + ~canceler + ~preserved_levels + valid_blocks_stream + in + let* () = + Client_confirmations.wait_for_bootstrapped + ~retry:(Baking_scheduling.retry cctxt ~delay:1. ~factor:1.5 ~tries:5) + cctxt + in + let* () = await_protocol_start cctxt ~chain in + if keep_alive then retry_on_disconnection cctxt process else process () +end + +module VDF = struct + let run (cctxt : Protocol_client_context.full) ~chain ~keep_alive = + let open Lwt_result_syntax in + let process () = + let*! () = + cctxt#message + "VDF daemon %a (%s) for %a started." + Tezos_version.Version.pp_simple + Tezos_version_value.Current_git_info.octez_version + Tezos_version_value.Current_git_info.abbreviated_commit_hash + Protocol_hash.pp_short + Protocol.hash + in + let* chain_id = Shell_services.Chain.chain_id cctxt ~chain () in + let* constants = + Protocol.Alpha_services.Constants.all cctxt (`Hash chain_id, `Head 0) + in + let canceler = Lwt_canceler.create () in + let _ = + Lwt_exit.register_clean_up_callback ~loc:__LOC__ (fun _ -> + let*! () = cctxt#message "Shutting down the VDF daemon..." in + let*! _ = Lwt_canceler.cancel canceler in + Lwt.return_unit) + in + Baking_vdf.start_vdf_worker cctxt ~canceler constants chain + in + let* () = + Client_confirmations.wait_for_bootstrapped + ~retry:(Baking_scheduling.retry cctxt ~delay:1. ~factor:1.5 ~tries:5) + cctxt + in + let* () = await_protocol_start cctxt ~chain in + if keep_alive then retry_on_disconnection cctxt process else process () +end diff --git a/src/proto_020_PsParisC/lib_delegate/client_daemon.mli b/src/proto_020_PsParisC/lib_delegate/client_daemon.mli new file mode 100644 index 000000000000..26ffe9a04863 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/client_daemon.mli @@ -0,0 +1,67 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Daemons directly supported by lib_delegate *) + +(** {1 Baker daemon} *) +module Baker : sig + val run : + Protocol_client_context.full -> + ?minimal_fees:Protocol.Alpha_context.Tez.t -> + ?minimal_nanotez_per_gas_unit:Q.t -> + ?minimal_nanotez_per_byte:Q.t -> + ?votes:Baking_configuration.per_block_votes_config -> + ?extra_operations:Baking_configuration.Operations_source.t -> + ?dal_node_endpoint:Uri.t -> + ?pre_emptive_forge_time:Q.t -> + ?force_apply:bool -> + ?context_path:string -> + ?state_recorder:Baking_configuration.state_recorder_config -> + chain:Shell_services.chain -> + keep_alive:bool -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t +end + +(** {1 Accuser daemon} *) + +module Accuser : sig + val run : + #Protocol_client_context.full -> + chain:Chain_services.chain -> + preserved_levels:int -> + keep_alive:bool -> + unit tzresult Lwt.t +end + +(** {1 VDF computation daemon} *) + +module VDF : sig + val run : + Protocol_client_context.full -> + chain:Chain_services.chain -> + keep_alive:bool -> + unit tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_delegate/delegate_events.ml b/src/proto_020_PsParisC/lib_delegate/delegate_events.ml new file mode 100644 index 000000000000..1a2efd1bcc41 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/delegate_events.ml @@ -0,0 +1,250 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let level = Internal_event.Notice + +(* Ignore the value in the output. *) +let pp_ignore fmt _ = Format.pp_print_string fmt "" + +module Denunciator = struct + include Internal_event.Simple + + let section = [Protocol.name; "delegate"; "denunciation"] + + let invalid_level_conversion = + declare_1 + ~section + ~level:Error + ~name:"invalid_level_conversion" + ~msg:"invalid level conversion: {errors}" + ~pp1:pp_print_top_error_of_trace + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + + let double_attestation_detected = + declare_2 + ~section + ~level + ~name:"double_attestation_detected" + ~msg:"double attestation detected" + ("existing_attestation", Operation_hash.encoding) + ("new_attestation", Operation_hash.encoding) + + let double_attestation_denounced = + declare_2 + ~section + ~level + ~name:"double_attestation_denounced" + ~msg:"double attestation evidence injected: {hash}" + ("hash", Operation_hash.encoding) + ~pp2:pp_ignore + ("bytes", Data_encoding.bytes) + + let double_preattestation_detected = + declare_2 + ~section + ~level + ~name:"double_preattestation_detected" + ~msg:"double preattestation detected" + ("existing_preattestation", Operation_hash.encoding) + ("new_preattestation", Operation_hash.encoding) + + let double_preattestation_denounced = + declare_2 + ~section + ~level + ~name:"double_preattestation_denounced" + ~msg:"double preattestation evidence injected: {hash}" + ("hash", Operation_hash.encoding) + ~pp2:pp_ignore + ("bytes", Data_encoding.bytes) + + let double_consensus_already_denounced = + declare_1 + ~section + ~level:Debug + ~name:"double_consensus_already_denounced" + ~msg:"double consensus operation already denounced in {hash}" + ("hash", Operation_hash.encoding) + + let consensus_operation_too_old = + declare_1 + ~section + ~level:Debug + ~name:"consensus_operation_too_old" + ~msg:"operation {hash} is too old to be handled" + ("hash", Operation_hash.encoding) + + let consensus_operation_too_far_in_future = + declare_1 + ~section + ~level:Debug + ~name:"consensus_operation_too_far_in_future" + ~msg:"operation {hash} too far in the future" + ("hash", Operation_hash.encoding) + + let inconsistent_attestation = + declare_1 + ~section + ~level:Error + ~name:"inconsistent_attestation" + ~msg:"inconsistent attestation found {hash}" + ("hash", Operation_hash.encoding) + + let unexpected_pruned_block = + declare_1 + ~section + ~level:Error + ~name:"unexpected_pruned_block" + ~msg:"unexpected pruned block: {hash}" + ("hash", Block_hash.encoding) + + let double_baking_but_not = + declare_0 + ~section + ~level:Debug + ~name:"double_baking_but_not" + ~msg:"double baking detected but block hashes are equivalent; skipping" + () + + let double_baking_detected = + declare_0 + ~section + ~level + ~name:"double_baking_detected" + ~msg:"double baking detected" + () + + let double_baking_denounced = + declare_2 + ~section + ~level + ~name:"double_baking_denounced" + ~msg:"double baking evidence injected {hash}" + ("hash", Operation_hash.encoding) + ~pp2:pp_ignore + ("bytes", Data_encoding.bytes) + + let protocol_change_detected = + declare_0 + ~section + ~level:Error + ~name:"protocol_change_detected" + ~msg:"protocol changing detected; skipping the block" + () + + let accuser_saw_block = + declare_2 + ~section + ~level:Debug + ~name:"accuser_saw_block" + ~msg:"block level: {level}" + ("level", Alpha_context.Raw_level.encoding) + ("hash", Block_hash.encoding) + + let fetch_operations_error = + declare_1 + ~section + ~level:Error + ~name:"fetch_operations_error" + ~msg:"error while fetching operations of block {hash}" + ("hash", Block_hash.encoding) + ~pp1:Block_hash.pp + + let accuser_processed_block = + declare_1 + ~section + ~level + ~name:"accuser_processed_block" + ~msg:"block {hash} registered" + ("hash", Block_hash.encoding) + + let accuser_block_error = + declare_2 + ~section + ~level:Error + ~name:"accuser_block_error" + ~msg:"error while processing block {hash} {errors}" + ~pp2:pp_print_top_error_of_trace + ("hash", Block_hash.encoding) + ("errors", Error_monad.(TzTrace.encoding error_encoding)) +end + +module Baking_scheduling = struct + include Internal_event.Simple + + let section = [Protocol.name; "delegate"; "baking-scheduling"] + + let cannot_fetch_event = + declare_1 + ~section + ~level:Info + ~name:"cannot_fetch_event" + ~msg:"{worker}: can't fetch the current event; waiting for new event" + ("worker", Data_encoding.string) + + let daemon_error = + declare_2 + ~section + ~level:Error + ~name:"daemon_error" + ~msg:"{worker}: error while baking: {errors}" + ~pp2:pp_print_top_error_of_trace + ("worker", Data_encoding.string) + ("errors", Error_monad.(TzTrace.encoding error_encoding)) + + let daemon_setup = + declare_1 + ~section + ~level:Info + ~name:"daemon_setup" + ~msg:"setting up before the {worker} can start" + ("worker", Data_encoding.string) + + let daemon_connection_lost = + declare_1 + ~section + ~level:Error + ~name:"daemon_connection_lost" + ~msg:"connection to node lost, {worker} exiting" + ("worker", Data_encoding.string) + + let daemon_wakeup = + declare_1 + ~section + ~level:Debug + ~name:"daemon_wakeup" + ~msg:"waking up for {worker}" + ("worker", Data_encoding.string) + + let daemon_start = + declare_1 + ~section + ~level:Info + ~name:"daemon_start" + ~msg:"starting {worker} daemon" + ("worker", Data_encoding.string) +end diff --git a/src/proto_020_PsParisC/lib_delegate/dune b/src/proto_020_PsParisC/lib_delegate/dune new file mode 100644 index 000000000000..718f8d67e25c --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/dune @@ -0,0 +1,111 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_baking_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.baking) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.clic + octez-version.value + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.protocol.lifted + octez-protocol-019-PtParisB-libs.plugin + octez-proto-libs.protocol-environment + octez-shell-libs.shell-services + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-libs.stdlib + octez-libs.stdlib-unix + octez-shell-libs.shell-context + octez-libs.tezos-context + octez-libs.tezos-context.memory + octez-libs.rpc-http-client-unix + octez-shell-libs.context-ops + octez-libs.rpc + octez-libs.rpc-http + octez-libs.crypto-dal + tezos-dal-node-services + lwt-canceler + lwt-exit + uri) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB_lifted + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_stdlib + -open Tezos_stdlib_unix + -open Tezos_shell_context + -open Tezos_context + -open Tezos_context_ops + -open Tezos_rpc_http + -open Tezos_crypto_dal) + (modules (:standard \ Baking_commands Baking_commands_registration))) + +(library + (name tezos_baking_019_PtParisB_commands) + (public_name octez-protocol-019-PtParisB-libs.baking-commands) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.parameters + octez-libs.stdlib-unix + octez-proto-libs.protocol-environment + octez-shell-libs.shell-services + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-protocol-019-PtParisB-libs.baking + octez-libs.rpc + uri) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_stdlib_unix + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_baking_019_PtParisB) + (modules Baking_commands)) + +(library + (name tezos_baking_019_PtParisB_commands_registration) + (public_name octez-protocol-019-PtParisB-libs.baking-commands.registration) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-proto-libs.protocol-environment + octez-shell-libs.shell-services + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-protocol-019-PtParisB-libs.baking + octez-protocol-019-PtParisB-libs.baking-commands + octez-libs.rpc) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_shell_services + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_baking_019_PtParisB + -open Tezos_baking_019_PtParisB_commands) + (modules Baking_commands_registration)) diff --git a/src/proto_020_PsParisC/lib_delegate/forge_worker.ml b/src/proto_020_PsParisC/lib_delegate/forge_worker.ml new file mode 100644 index 000000000000..013700f2f515 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/forge_worker.ml @@ -0,0 +1,238 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Baking_state +open Protocol +open Alpha_context + +module Events = struct + include Baking_events.Forge_worker + include Baking_events.Actions +end + +module Delegate_signing_queue = struct + type t = { + delegate : consensus_key_and_delegate; + task_stream : (unit -> unit Lwt.t) Lwt_stream.t; + push : (unit -> unit Lwt.t) option -> unit; + worker : unit Lwt.t; + } + + let start_delegate_worker_queue task_stream = + let open Lwt_syntax in + let rec loop () = + let* task = Lwt_stream.get task_stream in + match task with + | None -> (* End of stream *) return_unit + | Some task -> + let* () = task () in + loop () + in + loop () + + let create delegate = + let task_stream, push = Lwt_stream.create () in + let worker = start_delegate_worker_queue task_stream in + {delegate; task_stream; push; worker} + + let cancel_pending_tasks state = Lwt_stream.junk_old state.task_stream + + let wait_all_tasks_and_close state = + state.push None ; + state.worker + + let cancel_all_tasks_and_close state = + let open Lwt_syntax in + let* () = cancel_pending_tasks state in + wait_all_tasks_and_close state + + let push_task ~(on_error : tztrace -> unit Lwt.t) + (f : unit -> unit tzresult Lwt.t) state = + let open Lwt_result_syntax in + let task () = + let*! r = + protect + ~on_error:(fun trace -> + let*! () = on_error trace in + return_unit) + (fun () -> f ()) + in + match r with Error _err -> assert false | Ok () -> Lwt.return_unit + in + state.push (Some task) +end + +type worker = { + push_task : forge_request option -> unit; + push_event : forge_event option -> unit; + event_stream : forge_event Lwt_stream.t; + delegate_signing_queues : + Delegate_signing_queue.t Signature.Public_key_hash.Table.t; +} + +type t = worker + +let push_request state request = state.push_task (Some request) + +let get_event_stream state = state.event_stream + +let cancel_all_pending_tasks {delegate_signing_queues; _} = + Lwt.dont_wait + (fun () -> + Signature.Public_key_hash.Table.iter_p + (fun _ queue -> Delegate_signing_queue.cancel_pending_tasks queue) + delegate_signing_queues) + (fun _exn -> ()) + +let shutdown state = + let open Lwt_syntax in + let* () = + Signature.Public_key_hash.Table.iter_p + (fun _ queue -> Delegate_signing_queue.cancel_all_tasks_and_close queue) + state.delegate_signing_queues + in + state.push_task None ; + return_unit + +let get_or_create_queue worker delegate = + match + Signature.Public_key_hash.Table.find_opt + worker.delegate_signing_queues + (fst delegate).public_key_hash + with + | None -> + let queue = Delegate_signing_queue.create delegate in + Signature.Public_key_hash.Table.add + worker.delegate_signing_queues + (fst delegate).public_key_hash + queue ; + queue + | Some queue -> queue + +let handle_forge_block worker baking_state (block_to_bake : block_to_bake) = + let open Lwt_result_syntax in + let task () = + let* prepared_block = + Baking_actions.prepare_block baking_state block_to_bake + in + worker.push_event (Some (Block_ready prepared_block)) ; + return_unit + in + let queue = get_or_create_queue worker block_to_bake.delegate in + Delegate_signing_queue.push_task + ~on_error:(fun err -> + let*! () = + Events.(emit failed_to_forge_block (block_to_bake.delegate, err)) + in + Lwt.return_unit) + task + queue + +let handle_forge_consensus_votes worker baking_state + (unsigned_consensus_votes : unsigned_consensus_vote_batch) = + let open Lwt_result_syntax in + let batch_branch = unsigned_consensus_votes.batch_branch in + let task + ({vote_consensus_content; vote_kind; delegate; dal_content = _} as + unsigned_consensus_vote) = + let*! signed_consensus_vote_r = + Baking_actions.forge_and_sign_consensus_vote + baking_state + ~branch:batch_branch + unsigned_consensus_vote + in + match signed_consensus_vote_r with + | Error err -> + let level, round = + ( Raw_level.to_int32 vote_consensus_content.level, + vote_consensus_content.round ) + in + let*! () = + Events.( + emit skipping_consensus_vote (vote_kind, delegate, level, round, err)) + in + fail err + | Ok signed_consensus_vote -> ( + match vote_kind with + | Preattestation -> + worker.push_event + (Some (Preattestation_ready signed_consensus_vote)) ; + return_unit + | Attestation -> + worker.push_event (Some (Attestation_ready signed_consensus_vote)) ; + return_unit) + in + let* (authorized_consensus_votes : unsigned_consensus_vote list) = + protect + ~on_error:(fun err -> + let*! () = Events.(emit error_while_authorizing_consensus_votes err) in + return_nil) + (fun () -> + Baking_actions.authorized_consensus_votes + baking_state + unsigned_consensus_votes) + in + List.iter + (fun unsigned_preattestation -> + let queue = get_or_create_queue worker unsigned_preattestation.delegate in + Delegate_signing_queue.push_task + ~on_error:(fun _err -> Lwt.return_unit) + (fun () -> task unsigned_preattestation) + queue) + authorized_consensus_votes ; + return_unit + +let start (baking_state : Baking_state.global_state) = + let open Lwt_result_syntax in + let task_stream, push_task = Lwt_stream.create () in + let event_stream, push_event = Lwt_stream.create () in + let delegate_signing_queues = Signature.Public_key_hash.Table.create 13 in + let state : worker = + {push_task; push_event; event_stream; delegate_signing_queues} + in + let rec worker_loop () = + let*! (forge_request_opt : forge_request option) = + Lwt_stream.get task_stream + in + let process_request = function + | Forge_and_sign_block block_to_bake -> + handle_forge_block state baking_state block_to_bake ; + return_unit + | Forge_and_sign_preattestations {unsigned_preattestations} -> + handle_forge_consensus_votes + state + baking_state + unsigned_preattestations + | Forge_and_sign_attestations {unsigned_attestations} -> + handle_forge_consensus_votes state baking_state unsigned_attestations + in + match forge_request_opt with + | None -> (* Shutdown called *) return_unit + | Some request -> + let*! result = process_request request in + let*! () = + match result with + | Ok () -> Lwt.return_unit + | Error errs -> + let*! () = + Events.(emit error_while_processing_forge_request errs) + in + Lwt.return_unit + in + worker_loop () + in + Lwt.dont_wait + (fun () -> + Lwt.finalize + (fun () -> + let*! _r = worker_loop () in + Lwt.return_unit) + (fun () -> + let () = Lwt.dont_wait (fun () -> shutdown state) (fun _exn -> ()) in + Lwt.return_unit)) + (fun _exn -> ()) ; + state diff --git a/src/proto_020_PsParisC/lib_delegate/forge_worker.mli b/src/proto_020_PsParisC/lib_delegate/forge_worker.mli new file mode 100644 index 000000000000..61f417587718 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/forge_worker.mli @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Concurrent worker for consensus operations and block forging *) + +(** + {2 Description} + + This component allows the concurrent production of consensus + operations and blocks. It's meant to be used by pushing specific + requests as tasks and waiting for their completions on a dedicated + event stream. + + Block forging implies the retrieval of current operations and context + validation (and application if needed) and then producing a + signature. For consensus operations, the heavy work is mostly on + producing a signature. Signatures are expected to be concurrent in + order not to block the main execution thread. + + {2 Concurrency} + + Each task is associated to a delegate. This worker is designed to + work concurrently on each delegate's tasks. However, if a request + is pushed for a delegate while an existing one is active, this new + request will be enqueued and only be executed after the completion + of the first one. Hence, only one request may be active per + delegate at any time. + + {2 Cancellation} + + It is possible to cancel all pending tasks but it is not possible + to cancel each delegate's active tasks. This is explained by the + fact that we do not have control over the different signers scheme + and, in particular, some are not cancellable at all (e.g., + ledger). +*) + +open Baking_state + +(** Worker type *) +type worker + +type t = worker + +(** [push_request worker request] pushes the [request] to the worker + to be treated. Each [forge_request] is associated to a specific + delegate. The request will be treated whenever the delegate's + associated queue is available. If, the delegate's queue did not + previously exist, it will be created. *) +val push_request : worker -> forge_request -> unit + +(** [get_event_stream worker] returns the worker's stream of events + onto which tasks completion results are pushed. *) +val get_event_stream : worker -> forge_event Lwt_stream.t + +(** [cancel_all_pending_tasks worker] cancels all the worker's + delegate queues pending tasks. *) +val cancel_all_pending_tasks : worker -> unit + +(** [shutdown worker] triggers the [worker] shutdown. This function + cancels all pending tasks but still waits for each active one to + complete. *) +val shutdown : worker -> unit Lwt.t + +(** [start global_state] creates and runs a worker based on a baker's + [global_state]. *) +val start : global_state -> worker diff --git a/src/proto_020_PsParisC/lib_delegate/node_rpc.ml b/src/proto_020_PsParisC/lib_delegate/node_rpc.ml new file mode 100644 index 000000000000..9e9da81a51f3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/node_rpc.ml @@ -0,0 +1,312 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_cache +open Baking_state +module Block_services = Block_services.Make (Protocol) (Protocol) +module Events = Baking_events.Node_rpc + +let inject_block cctxt ?(force = false) ~chain signed_block_header operations = + let signed_shell_header_bytes = + Data_encoding.Binary.to_bytes_exn Block_header.encoding signed_block_header + in + Shell_services.Injection.block + ~async:true + cctxt + ~chain + ~force + signed_shell_header_bytes + operations + +let inject_operation cctxt ~chain operation = + let encoded_op = + Data_encoding.Binary.to_bytes_exn Operation.encoding operation + in + Shell_services.Injection.operation cctxt ~async:true ~chain encoded_op + +let preapply_block cctxt ~chain ~head ~timestamp ~protocol_data operations = + Block_services.Helpers.Preapply.block + cctxt + ~chain + ~timestamp + ~block:(`Hash (head, 0)) + operations + ~protocol_data + +let extract_prequorum preattestations = + match preattestations with + | h :: _ -> + let ({protocol_data = {contents = Single (Preattestation content); _}; _}) + = + (h : Kind.preattestation Operation.t) + in + Some + { + level = Raw_level.to_int32 content.level; + round = content.round; + block_payload_hash = content.block_payload_hash; + preattestations; + } + | _ -> None + +let info_of_header_and_ops ~in_protocol block_hash block_header operations = + let open Result_syntax in + let shell = block_header.Tezos_base.Block_header.shell in + let dummy_payload_hash = Block_payload_hash.zero in + let* round = + Environment.wrap_tzresult @@ Fitness.round_from_raw shell.fitness + in + let payload_hash, payload_round, prequorum, quorum, payload = + if not in_protocol then + (* The first block in the protocol is baked using the previous + protocol, the encodings might change. The baker's logic is to + consider final the first block of a new protocol and not + attest it. Therefore, we do not need to have the correct + values here. *) + (dummy_payload_hash, Round.zero, None, [], Operation_pool.empty_payload) + else + let payload_hash, payload_round = + match + Data_encoding.Binary.of_bytes_opt + Protocol.block_header_data_encoding + block_header.protocol_data + with + | Some {contents = {payload_hash; payload_round; _}; _} -> + (payload_hash, payload_round) + | None -> assert false + in + let preattestations, quorum, payload = + WithExceptions.Option.get + ~loc:__LOC__ + (Operation_pool.extract_operations_of_list_list operations) + in + let prequorum = Option.bind preattestations extract_prequorum in + (payload_hash, payload_round, prequorum, quorum, payload) + in + return + { + hash = block_hash; + shell; + payload_hash; + payload_round; + round; + prequorum; + quorum; + payload; + } + +let compute_block_info cctxt ~in_protocol ?operations ~chain block_hash + block_header = + let open Lwt_result_syntax in + let* operations = + match operations with + | None when not in_protocol -> return_nil + | None -> + let open Protocol_client_context in + let* operations = + Alpha_block_services.Operations.operations + cctxt + ~chain + ~block:(`Hash (block_hash, 0)) + () + in + let packed_operations = + List.map + (fun l -> + List.map + (fun {Alpha_block_services.shell; protocol_data; _} -> + {Alpha_context.shell; protocol_data}) + l) + operations + in + return packed_operations + | Some operations -> + let parse_op (raw_op : Tezos_base.Operation.t) = + let protocol_data = + Data_encoding.Binary.of_bytes_exn + Operation.protocol_data_encoding + raw_op.proto + in + {shell = raw_op.shell; protocol_data} + in + protect @@ fun () -> return (List.map (List.map parse_op) operations) + in + let*? block_info = + info_of_header_and_ops ~in_protocol block_hash block_header operations + in + return block_info + +let proposal cctxt ?(cache : block_info Block_cache.t option) ?operations ~chain + block_hash (block_header : Tezos_base.Block_header.t) = + let open Lwt_result_syntax in + let predecessor_hash = block_header.shell.predecessor in + let pred_block = `Hash (predecessor_hash, 0) in + let predecessor_opt = + Option.bind cache (fun cache -> Block_cache.find_opt cache predecessor_hash) + in + let* is_proposal_in_protocol, predecessor = + match predecessor_opt with + | Some predecessor -> + return + ( predecessor.shell.proto_level = block_header.shell.proto_level, + predecessor ) + | None -> + let* { + current_protocol = pred_current_protocol; + next_protocol = pred_next_protocol; + } = + Shell_services.Blocks.protocols cctxt ~chain ~block:pred_block () + in + let is_proposal_in_protocol = + Protocol_hash.(pred_next_protocol = Protocol.hash) + in + let* predecessor = + let in_protocol = + Protocol_hash.(pred_current_protocol = Protocol.hash) + in + let* raw_header_b = + Shell_services.Blocks.raw_header cctxt ~chain ~block:pred_block () + in + let predecessor_header = + Data_encoding.Binary.of_bytes_exn + Tezos_base.Block_header.encoding + raw_header_b + in + compute_block_info + cctxt + ~in_protocol + ~chain + predecessor_hash + predecessor_header + in + Option.iter + (fun cache -> Block_cache.replace cache predecessor_hash predecessor) + cache ; + return (is_proposal_in_protocol, predecessor) + in + let block_opt = + Option.bind cache (fun cache -> Block_cache.find_opt cache block_hash) + in + let* block = + match block_opt with + | Some pi -> return pi + | None -> + let* pi = + compute_block_info + cctxt + ~in_protocol:is_proposal_in_protocol + ?operations + ~chain + block_hash + block_header + in + Option.iter (fun cache -> Block_cache.replace cache block_hash pi) cache ; + return pi + in + return {block; predecessor} + +let proposal cctxt ?cache ?operations ~chain block_hash block_header = + protect @@ fun () -> + proposal cctxt ?cache ?operations ~chain block_hash block_header + +let monitor_valid_proposals cctxt ~chain ?cache () = + let open Lwt_result_syntax in + let next_protocols = [Protocol.hash] in + let* block_stream, stopper = + Monitor_services.validated_blocks cctxt ~chains:[chain] ~next_protocols () + in + let stream = + let map (_chain_id, block_hash, block_header, operations) = + let*! map_result = + proposal cctxt ?cache ~operations ~chain block_hash block_header + in + match map_result with + | Ok proposal -> Lwt.return_some proposal + | Error err -> + let*! () = Events.(emit error_while_monitoring_valid_proposals err) in + Lwt.return_none + in + Lwt_stream.filter_map_s map block_stream + in + return (stream, stopper) + +let monitor_heads cctxt ~chain ?cache () = + let open Lwt_result_syntax in + let next_protocols = [Protocol.hash] in + let* block_stream, stopper = + Monitor_services.heads cctxt ~next_protocols chain + in + let stream = + let map (block_hash, block_header) = + let*! map_result = proposal cctxt ?cache ~chain block_hash block_header in + match map_result with + | Ok proposal -> Lwt.return_some proposal + | Error err -> + let*! () = Events.(emit error_while_monitoring_heads err) in + Lwt.return_none + in + Lwt_stream.filter_map_s map block_stream + in + return (stream, stopper) + +let await_protocol_activation cctxt ~chain () = + let open Lwt_result_syntax in + let* block_stream, stop = + Monitor_services.heads cctxt ~next_protocols:[Protocol.hash] chain + in + let*! _ = Lwt_stream.get block_stream in + stop () ; + return_unit + +let fetch_dal_config cctxt = + let open Lwt_syntax in + let* r = Config_services.dal_config cctxt in + match r with + | Error e -> return_error e + | Ok dal_config -> return_ok dal_config + +let get_attestable_slots dal_node_rpc_ctxt pkh ~attested_level = + Tezos_rpc.Context.make_call + Tezos_dal_node_services.Services.get_attestable_slots + dal_node_rpc_ctxt + (((), pkh), attested_level) + () + () + +let register_dal_profiles dal_node_rpc_ctxt delegates = + let profiles = + List.map + (fun consensus_key -> + Tezos_dal_node_services.Types.Attester consensus_key.public_key_hash) + delegates + in + Tezos_rpc.Context.make_call + Tezos_dal_node_services.Services.patch_profiles + dal_node_rpc_ctxt + () + () + profiles diff --git a/src/proto_020_PsParisC/lib_delegate/node_rpc.mli b/src/proto_020_PsParisC/lib_delegate/node_rpc.mli new file mode 100644 index 000000000000..9cc43ca07a5e --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/node_rpc.mli @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Inject a block. + + @param force defaults to [false] + @return block hash of the newly injected block +*) +val inject_block : + #Protocol_client_context.full -> + ?force:bool -> + chain:Shell_services.chain -> + Block_header.t -> + Tezos_base.Operation.t list list -> + Block_hash.t tzresult Lwt.t + +(** Inject an operation. + + @return operation hash of the newly injected operation +*) +val inject_operation : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + packed_operation -> + Operation_hash.t tzresult Lwt.t + +(** Preapply a block using the node validation mechanism.*) +val preapply_block : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + head:Block_hash.t -> + timestamp:Time.Protocol.t -> + protocol_data:Protocol.block_header_data -> + packed_operation list list -> + (Tezos_base.Block_header.shell_header * error Preapply_result.t list) tzresult + Lwt.t + +(** Monitor validated blocks/proposals from the node. *) +val monitor_valid_proposals : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + ?cache:Baking_state.block_info Baking_cache.Block_cache.t -> + unit -> + (Baking_state.proposal Lwt_stream.t * (unit -> unit)) tzresult Lwt.t + +(** Monitor heads from the node. *) +val monitor_heads : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + ?cache:Baking_state.block_info Baking_cache.Block_cache.t -> + unit -> + (Baking_state.proposal Lwt_stream.t * (unit -> unit)) tzresult Lwt.t + +(** Await the current protocol to be activated. *) +val await_protocol_activation : + #Protocol_client_context.rpc_context -> + chain:Shell_services.chain -> + unit -> + unit tzresult Lwt.t + +val fetch_dal_config : + #Protocol_client_context.rpc_context -> Cryptobox.Config.t tzresult Lwt.t + +(** [get_attestable_slots ctxt pkh ~level] calls the DAL node RPC + GET /profiles//attested_levels//attestable_slots *) +val get_attestable_slots : + Tezos_rpc.Context.generic -> + public_key_hash -> + attested_level:int32 -> + Tezos_dal_node_services.Types.attestable_slots tzresult Lwt.t + +(** [register_dal_profiles ctxt delegates] calls the DAL node RPC PATCH + /profiles/ to register each profile corresponding to a delegate in + [delegates]. *) +val register_dal_profiles : + Tezos_rpc.Context.generic -> + Baking_state.consensus_key list -> + unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/operation_pool.ml b/src/proto_020_PsParisC/lib_delegate/operation_pool.ml new file mode 100644 index 000000000000..c6cf50c36bbe --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/operation_pool.ml @@ -0,0 +1,402 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(* Should we use a better ordering ? *) + +type 'collection t = { + consensus : 'collection; + votes : 'collection; + anonymous : 'collection; + managers : 'collection; +} + +let compare_op op1 op2 = + try Stdlib.compare op1 op2 + with _ -> + (* FIXME some operations (e.g. tx_rollup_rejection) pack + functional values which could raise an exception. In this + specific case, we default to comparing their hashes. *) + Operation_hash.compare + (Alpha_context.Operation.hash_packed op1) + (Alpha_context.Operation.hash_packed op2) + +module Prioritized_operation = struct + (* Higher priority operations will be included first *) + type t = Prioritized of int * packed_operation | Low of packed_operation + + let extern ?(priority = 1) op = Prioritized (priority, op) + + let node op = Low op + + let packed = function Prioritized (_, op) | Low op -> op + + let compare_priority t1 t2 = + match (t1, t2) with + | Prioritized _, Low _ -> 1 + | Low _, Prioritized _ -> -1 + | Low _, Low _ -> 0 + | Prioritized (p0, _), Prioritized (p1, _) -> Compare.Int.compare p0 p1 + + let compare a b = + let c = compare_priority a b in + if c <> 0 then c else compare_op (packed a) (packed b) +end + +module Operation_set = Set.Make (struct + type t = packed_operation + + let compare = compare_op +end) + +module Prioritized_operation_set = struct + include Set.Make (struct + type t = Prioritized_operation.t + + let compare = Prioritized_operation.compare + end) + + let operations set = elements set |> List.map Prioritized_operation.packed +end + +(* TODO refine this: unpack operations *) +type pool = Operation_set.t t + +(* TODO refine this: unpack operations *) +type ordered_pool = packed_operation list t + +let ordered_pool_encoding = + let open Data_encoding in + conv + (fun {consensus; votes; anonymous; managers} -> + (consensus, votes, anonymous, managers)) + (fun (consensus, votes, anonymous, managers) -> + {consensus; votes; anonymous; managers}) + (obj4 + (req "ordered_consensus" (list (dynamic_size Operation.encoding))) + (req "ordered_votes" (list (dynamic_size Operation.encoding))) + (req "ordered_anonymouns" (list (dynamic_size Operation.encoding))) + (req "ordered_managers" (list (dynamic_size Operation.encoding)))) + +type payload = { + votes_payload : packed_operation list; + anonymous_payload : packed_operation list; + managers_payload : packed_operation list; +} + +let empty_payload = + {votes_payload = []; anonymous_payload = []; managers_payload = []} + +let payload_encoding = + let open Data_encoding in + conv + (fun {votes_payload; anonymous_payload; managers_payload} -> + (votes_payload, anonymous_payload, managers_payload)) + (fun (votes_payload, anonymous_payload, managers_payload) -> + {votes_payload; anonymous_payload; managers_payload}) + (obj3 + (req "votes_payload" (list (dynamic_size Operation.encoding))) + (req "anonymous_payload" (list (dynamic_size Operation.encoding))) + (req "managers_payload" (list (dynamic_size Operation.encoding)))) + +let pp_payload fmt {votes_payload; anonymous_payload; managers_payload} = + Format.fprintf + fmt + "[votes: %d, anonymous: %d, managers: %d]" + (List.length votes_payload) + (List.length anonymous_payload) + (List.length managers_payload) + +let empty = + { + consensus = Operation_set.empty; + votes = Operation_set.empty; + anonymous = Operation_set.empty; + managers = Operation_set.empty; + } + +let empty_ordered = {consensus = []; votes = []; anonymous = []; managers = []} + +let pp_pool fmt {consensus; votes; anonymous; managers} = + Format.fprintf + fmt + "[consensus: %d, votes: %d, anonymous: %d, managers: %d]" + (Operation_set.cardinal consensus) + (Operation_set.cardinal votes) + (Operation_set.cardinal anonymous) + (Operation_set.cardinal managers) + +let pp_ordered_pool fmt {consensus; votes; anonymous; managers} = + Format.fprintf + fmt + "[consensus: %d, votes: %d, anonymous: %d, managers: %d]" + (List.length consensus) + (List.length votes) + (List.length anonymous) + (List.length managers) + +let classify op = + (* Hypothesis: acceptable passes on an ill-formed operation returns + None. *) + let pass = Main.acceptable_pass op in + match pass with + | None -> `Bad + | Some pass -> + let open Operation_repr in + if pass = consensus_pass then `Consensus + (* TODO filter outdated consensus ops ? *) + else if pass = voting_pass then `Votes + else if pass = anonymous_pass then `Anonymous + else if pass = manager_pass then `Managers + else `Bad + +let add_operation_to_pool add classify pool operation = + match classify operation with + | `Consensus -> + let consensus = add operation pool.consensus in + {pool with consensus} + | `Votes -> + let votes = add operation pool.votes in + {pool with votes} + | `Anonymous -> + let anonymous = add operation pool.anonymous in + {pool with anonymous} + | `Managers -> + let managers = add operation pool.managers in + {pool with managers} + | `Bad -> pool + +let add_operation = add_operation_to_pool Operation_set.add classify + +let add_operations pool ops = List.fold_left add_operation pool ops + +type consensus_filter = { + level : int32; + round : Round.t; + payload_hash : Block_payload_hash.t; +} + +(** From a pool of operations [operation_pool], the function filters + out the attestations that are different from the [current_level], + the [current_round] or the optional [current_block_payload_hash], + as well as preattestations. *) +let filter_with_relevant_consensus_ops ~(attestation_filter : consensus_filter) + ~(preattestation_filter : consensus_filter option) operation_set = + Operation_set.filter + (fun {protocol_data; _} -> + match (protocol_data, preattestation_filter) with + (* 1a. Remove preattestations. *) + | Operation_data {contents = Single (Preattestation _); _}, None -> false + (* 1b. Filter preattestations. *) + | ( Operation_data + { + contents = + Single (Preattestation {level; round; block_payload_hash; _}); + _; + }, + Some + {level = level'; round = round'; payload_hash = block_payload_hash'} + ) -> + Compare.Int32.(Raw_level.to_int32 level = level') + && Round.(round = round') + && Block_payload_hash.(block_payload_hash = block_payload_hash') + (* 2. Filter attestations. *) + | ( Operation_data + { + contents = + Single + (Attestation + { + consensus_content = {level; round; block_payload_hash; _}; + dal_content = _; + }); + _; + }, + _ ) -> + Compare.Int32.(Raw_level.to_int32 level = attestation_filter.level) + && Round.(round = attestation_filter.round) + && Block_payload_hash.( + block_payload_hash = attestation_filter.payload_hash) + (* 3. Preserve all non-consensus operations. *) + | _ -> true) + operation_set + +let unpack_preattestation packed_preattestation = + let {shell; protocol_data = Operation_data data} = packed_preattestation in + match data with + | {contents = Single (Preattestation _); _} -> + Some ({shell; protocol_data = data} : Kind.preattestation Operation.t) + | _ -> None + +let unpack_attestation packed_attestation = + let {shell; protocol_data = Operation_data data} = packed_attestation in + match data with + | {contents = Single (Attestation _); _} -> + Some ({shell; protocol_data = data} : Kind.attestation Operation.t) + | _ -> None + +let filter_preattestations ops = + List.filter_map + (function + | { + shell = {branch}; + protocol_data = + Operation_data + ({contents = Single (Preattestation _); _} as content); + _; + } -> + Some + ({shell = {branch}; protocol_data = content} + : Kind.preattestation operation) + | _ -> None) + ops + +let filter_attestations ops = + List.filter_map + (function + | { + shell = {branch}; + protocol_data = + Operation_data ({contents = Single (Attestation _); _} as content); + _; + } -> + Some + ({shell = {branch}; protocol_data = content} + : Kind.attestation operation) + | _ -> None) + ops + +let ordered_to_list_list {consensus; votes; anonymous; managers} = + [consensus; votes; anonymous; managers] + +let ordered_of_list_list = function + | [consensus; votes; anonymous; managers] -> + Some {consensus; votes; anonymous; managers} + | _ -> None + +let payload_of_ordered_pool {votes; anonymous; managers; _} = + { + votes_payload = votes; + anonymous_payload = anonymous; + managers_payload = managers; + } + +let ordered_pool_of_payload ~consensus_operations + {votes_payload; anonymous_payload; managers_payload} = + { + consensus = consensus_operations; + votes = votes_payload; + anonymous = anonymous_payload; + managers = managers_payload; + } + +let extract_operations_of_list_list = function + | [consensus; votes_payload; anonymous_payload; managers_payload] -> + let preattestations, attestations = + List.fold_left + (fun ( (preattestations : Kind.preattestation Operation.t list), + (attestations : Kind.attestation Operation.t list) ) + packed_op -> + let {shell; protocol_data = Operation_data data} = packed_op in + match data with + | {contents = Single (Preattestation _); _} -> + ({shell; protocol_data = data} :: preattestations, attestations) + | {contents = Single (Attestation _); _} -> + (preattestations, {shell; protocol_data = data} :: attestations) + | _ -> + (* unreachable *) + (preattestations, attestations)) + ([], []) + consensus + (* N.b. the order doesn't matter *) + in + let preattestations = + if preattestations = [] then None else Some preattestations + in + let payload = {votes_payload; anonymous_payload; managers_payload} in + Some (preattestations, attestations, payload) + | _ -> None + +let filter_pool p {consensus; votes; anonymous; managers} = + { + consensus = Operation_set.filter p consensus; + votes = Operation_set.filter p votes; + anonymous = Operation_set.filter p anonymous; + managers = Operation_set.filter p managers; + } + +module Prioritized = struct + type nonrec t = Prioritized_operation_set.t t + + let of_operation_set (operation_set : Operation_set.t) = + Operation_set.fold + (fun elt set -> + Prioritized_operation_set.add (Prioritized_operation.node elt) set) + operation_set + Prioritized_operation_set.empty + + let of_pool (pool : pool) : t = + { + consensus = of_operation_set pool.consensus; + votes = of_operation_set pool.votes; + anonymous = of_operation_set pool.anonymous; + managers = of_operation_set pool.managers; + } + + let add_operation = + add_operation_to_pool Prioritized_operation_set.add (fun op -> + classify (Prioritized_operation.packed op)) + + let add_external_operation pool priority operation = + add_operation pool (Prioritized_operation.extern ~priority operation) + + let add_operations prioritized_pool operations = + List.fold_left add_operation prioritized_pool operations + + (* [merge_external_operations] considers that the list of operation + represents an ordererd list of operation with the head having the highest + prioritiy. + *) + let merge_external_operations pool + (external_operations : packed_operation list) = + List.fold_left_i + (fun i pool op -> add_external_operation pool (-i) op) + pool + external_operations + + let filter p {consensus; votes; anonymous; managers} = + let filter = + Prioritized_operation_set.filter (fun pop -> + p (Prioritized_operation.packed pop)) + in + { + consensus = filter consensus; + votes = filter votes; + anonymous = filter anonymous; + managers = filter managers; + } +end diff --git a/src/proto_020_PsParisC/lib_delegate/operation_pool.mli b/src/proto_020_PsParisC/lib_delegate/operation_pool.mli new file mode 100644 index 000000000000..a7159f557254 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/operation_pool.mli @@ -0,0 +1,168 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Operation_set : Set.S with type elt = packed_operation + +(** Generic base type for pools *) +type 'collection t = { + consensus : 'collection; + votes : 'collection; + anonymous : 'collection; + managers : 'collection; +} + +(** A pool of operations for a single origin, or undifferenciated origin, + typically used for operations coming from the node *) +type pool = Operation_set.t t + +(** A pool of operations for a single origin, or undifferenciated origin, + typically used for operations coming from the node *) + +(** on pool *) +val empty : pool + +val pp_pool : Format.formatter -> pool -> unit + +val filter_pool : (packed_operation -> bool) -> pool -> pool + +val add_operation : pool -> packed_operation -> pool + +val add_operations : pool -> packed_operation list -> pool + +(** {2 Ordered pool of operations} *) +type ordered_pool = packed_operation list t + +val ordered_pool_encoding : ordered_pool Data_encoding.t + +val empty_ordered : ordered_pool + +val pp_ordered_pool : Format.formatter -> ordered_pool -> unit + +type payload = { + votes_payload : packed_operation list; + anonymous_payload : packed_operation list; + managers_payload : packed_operation list; +} + +val empty_payload : payload + +val payload_encoding : payload Data_encoding.t + +val pp_payload : Format.formatter -> payload -> unit + +val payload_of_ordered_pool : ordered_pool -> payload + +val ordered_pool_of_payload : + consensus_operations:packed_operation list -> payload -> ordered_pool + +type consensus_filter = { + level : int32; + round : Round.t; + payload_hash : Block_payload_hash.t; +} + +val filter_with_relevant_consensus_ops : + attestation_filter:consensus_filter -> + preattestation_filter:consensus_filter option -> + Operation_set.t -> + Operation_set.t + +val unpack_preattestation : + packed_operation -> Kind.preattestation operation option + +val unpack_attestation : packed_operation -> Kind.attestation operation option + +val filter_preattestations : + packed_operation list -> Kind.preattestation operation list + +val filter_attestations : + packed_operation list -> Kind.attestation operation list + +val ordered_to_list_list : ordered_pool -> packed_operation list list + +val ordered_of_list_list : packed_operation list list -> ordered_pool option + +(** [preattestation] <> None => (List.length preattestations > 0) *) +val extract_operations_of_list_list : + packed_operation list list -> + (Kind.preattestation operation list option + * Kind.attestation operation list + * payload) + option + +module Prioritized_operation : sig + type t + + (** prioritize operations coming from an external source (file, uri, ...). + An operation with higher [priority] (aka a bigger integer) will be + included before others with lower [priority]. *) + val extern : ?priority:int -> packed_operation -> t + + (** prioritize operations coming from a node *) + val node : packed_operation -> t + + (** [packed t] retrieves the [packed_operation] wrapped inside [t] *) + val packed : t -> packed_operation + + (** [compare_priority o1 o2] compares whether [o1] has higher priority than [o2] *) + val compare_priority : t -> t -> int + + (** [compare] is [compare_priority] when non-zero. This is suitable to + construct sets of prioritized operations **) + val compare : t -> t -> int +end + +module Prioritized_operation_set : sig + include Set.S with type elt = Prioritized_operation.t + + (** [operations set] is [elements set |> List.map Prioritized_operation.packed]*) + val operations : t -> packed_operation list +end + +(** Pool of prioritized operations *) +module Prioritized : sig + (** Same record fields as [type pool], but with a different set base *) + type nonrec t = Prioritized_operation_set.t t + + (** [of_pool pool] transforms [pool] into a prioritized pool of operations of + low priority. *) + val of_pool : pool -> t + + (** [merge_external_operations ?initial_priority pool extern_ops] creates a prioritized pool + from a [pool] and [extern_ops] coming from an external source, which we + prioritize. + + Priorities for these operations is given according to the order of the + list. The first element of the list has highest priority. + *) + val merge_external_operations : t -> packed_operation list -> t + + val filter : (packed_operation -> bool) -> t -> t + + val add_operations : t -> Prioritized_operation.t list -> t +end diff --git a/src/proto_020_PsParisC/lib_delegate/operation_selection.ml b/src/proto_020_PsParisC/lib_delegate/operation_selection.ml new file mode 100644 index 000000000000..d83f7c55369a --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/operation_selection.ml @@ -0,0 +1,417 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Operation_pool +module Events = Baking_events.Selection + +let quota = Main.validation_passes + +let consensus_quota = Stdlib.List.nth quota Operation_repr.consensus_pass + +let votes_quota = Stdlib.List.nth quota Operation_repr.voting_pass + +let anonymous_quota = Stdlib.List.nth quota Operation_repr.anonymous_pass + +let managers_quota = Stdlib.List.nth quota Operation_repr.manager_pass + +type prioritized_manager = { + op : Prioritized_operation.t; + size : int; + fee : Tez.t; + gas : Fixed_point_repr.integral_tag Gas.Arith.t; + weight : Q.t; + source : public_key_hash; + counter : Manager_counter.t; +} + +module PrioritizedManagerSet = Set.Make (struct + type t = prioritized_manager + + (* We order the operations by their weights except if they belong + to the same manager, if they do, we order them by their + counter. *) + let compare {source; counter; weight; op; _} + {source = source'; counter = counter'; weight = weight'; op = op'; _} = + (* Be careful with the [compare] *) + let cmp_src = Signature.Public_key_hash.compare source source' in + if cmp_src = 0 then + (* we want the smallest counter first *) + let c = Manager_counter.compare counter counter' in + if c <> 0 then c + else + let c = Prioritized_operation.compare_priority op' op in + if c <> 0 then c else Q.compare weight' weight + (* if same counter, biggest weight first *) + else + let c = Prioritized_operation.compare_priority op' op in + if c <> 0 then c + else + (* We want the biggest weight first *) + let c = Q.compare weight' weight in + if c <> 0 then c else cmp_src +end) + +(* Note: This weight is also used by the plugin and the prevalidator to sort + operations in the pending mempool. + See {!Tezos_protocol_plugin_alpha.Plugin.Mempool.weight_manager_operation}. *) +let prioritize_manager ~max_size ~hard_gas_limit_per_block ~minimal_fees + ~minimal_nanotez_per_gas_unit ~minimal_nanotez_per_byte operation = + let open Result_syntax in + let op = Operation_pool.Prioritized_operation.packed operation in + let {protocol_data = Operation_data {contents; _}; _} = op in + let open Operation in + let l = to_list (Contents_list contents) in + List.fold_left_e + (fun ((first_source, first_counter, total_fee, total_gas) as acc) -> + function + | Contents (Manager_operation {source; counter; fee; gas_limit; _}) -> + let* total_fee = + Environment.wrap_tzresult @@ Tez.(total_fee +? fee) + in + (* There is only one unique source per packed transaction *) + let first_source = Option.value ~default:source first_source in + (* We only care about the first counter *) + let first_counter = Option.value ~default:counter first_counter in + return + ( Some first_source, + Some first_counter, + total_fee, + Gas.Arith.add total_gas gas_limit ) + | _ -> return acc) + (None, None, Tez.zero, Gas.Arith.zero) + l + |> function + | Ok (Some source, Some counter, fee, gas) -> + if Tez.(fee < minimal_fees) then None + else + let size = Data_encoding.Binary.length Operation.encoding op in + let size_f = Q.of_int size in + let gas_f = Q.of_bigint (Gas.Arith.integral_to_z gas) in + let fee_f = Q.of_int64 (Tez.to_mutez fee) in + let size_ratio = Q.(size_f / Q.of_int max_size) in + let gas_ratio = + Q.( + gas_f + / Q.of_bigint (Gas.Arith.integral_to_z hard_gas_limit_per_block)) + in + let weight = Q.(fee_f / max size_ratio gas_ratio) in + let fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez fee)) (Q.of_int 1000) + in + let enough_fees_for_gas = + let minimal_fees_in_nanotez = + Q.mul + minimal_nanotez_per_gas_unit + (Q.of_bigint @@ Gas.Arith.integral_to_z gas) + in + Q.compare minimal_fees_in_nanotez fees_in_nanotez <= 0 + in + let enough_fees_for_size = + let minimal_fees_in_nanotez = + Q.mul minimal_nanotez_per_byte (Q.of_int size) + in + Q.compare minimal_fees_in_nanotez fees_in_nanotez <= 0 + in + if enough_fees_for_size && enough_fees_for_gas then + Some {op = operation; size; weight; fee; gas; source; counter} + else None + | _ -> None + +let prioritize_managers ~hard_gas_limit_per_block ~minimal_fees + ~minimal_nanotez_per_gas_unit ~minimal_nanotez_per_byte managers = + Prioritized_operation_set.fold + (fun op acc -> + match + prioritize_manager + ~max_size:managers_quota.max_size + ~hard_gas_limit_per_block + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + op + with + | None -> acc + | Some w_op -> PrioritizedManagerSet.add w_op acc) + managers + PrioritizedManagerSet.empty + +(** Simulation *) + +type simulation_result = { + validation_result : Tezos_protocol_environment.validation_result option; + block_header_metadata : block_header_metadata option; + operations : packed_operation list list; + operations_hash : Operation_list_list_hash.t; +} + +let validate_operation inc op = + let open Lwt_syntax in + let* result = Baking_simulator.add_operation inc op in + match result with + | Error errs -> + let* () = + Events.(emit invalid_operation_filtered) (Operation.hash_packed op, errs) + in + return_none + | Ok (resulting_state, None) -> + (* No receipt if force_apply is not set *) + return_some resulting_state + | Ok (resulting_state, Some receipt) -> ( + (* Check that the metadata are serializable/deserializable *) + let encoding_result = + let enc = Protocol.operation_receipt_encoding in + Option.bind + (Data_encoding.Binary.to_bytes_opt enc receipt) + (Data_encoding.Binary.of_bytes_opt enc) + in + match encoding_result with + | None -> + let* () = + Events.(emit cannot_serialize_operation_metadata) + (Operation.hash_packed op) + in + return_none + | Some _b -> return_some resulting_state) + +let filter_valid_operations_up_to_quota inc (ops, quota) = + let open Lwt_syntax in + let {Tezos_protocol_environment.max_size; max_op} = quota in + let exception Full of (Baking_simulator.incremental * packed_operation list) + in + try + let* inc, _, _, l = + List.fold_left_s + (fun (inc, curr_size, nb_ops, acc) op -> + let op_size = + Data_encoding.Binary.length Alpha_context.Operation.encoding op + in + let new_size = curr_size + op_size in + if new_size > max_size then return (inc, curr_size, nb_ops, acc) + else ( + Option.iter + (fun max_op -> + if max_op = nb_ops + 1 then raise (Full (inc, acc))) + max_op ; + let* inc'_opt = validate_operation inc op in + match inc'_opt with + | None -> return (inc, curr_size, nb_ops, acc) + | Some inc' -> return (inc', new_size, nb_ops + 1, op :: acc))) + (inc, 0, 0, []) + ops + in + return (inc, List.rev l) + with Full (inc, l) -> return (inc, List.rev l) + +let filter_valid_managers_up_to_quota inc ~hard_gas_limit_per_block (ops, quota) + = + let open Lwt_syntax in + let {Tezos_protocol_environment.max_size; max_op} = quota in + let rec loop (inc, curr_size, nb_ops, remaining_gas, acc) = function + | [] -> return (inc, List.rev acc) + | {op; size = op_size; gas = op_gas; _} :: l -> ( + match max_op with + | Some max_op when max_op = nb_ops + 1 -> return (inc, List.rev acc) + | None | Some _ -> ( + if Gas.Arith.(remaining_gas < op_gas) then + (* If the remaining available gas is lower than the + considered operation's gas, we ignore this operation. *) + loop (inc, curr_size, nb_ops, remaining_gas, acc) l + else + let new_size = curr_size + op_size in + if new_size > max_size then + (* We ignore the operation if summing its size to the + size of managers operations already validated is + greater than the quota. *) + loop (inc, curr_size, nb_ops, remaining_gas, acc) l + else + let packed_op = Prioritized_operation.packed op in + let* inc'_opt = validate_operation inc packed_op in + match inc'_opt with + | None -> loop (inc, curr_size, nb_ops, remaining_gas, acc) l + | Some inc' -> + let new_remaining_gas = + Gas.Arith.sub remaining_gas op_gas + in + loop + ( inc', + new_size, + succ nb_ops, + new_remaining_gas, + packed_op :: acc ) + l)) + in + loop (inc, 0, 0, hard_gas_limit_per_block, []) ops + +let filter_operations_with_simulation initial_inc fees_config + ~hard_gas_limit_per_block {consensus; votes; anonymous; managers} = + let open Lwt_result_syntax in + let { + Baking_configuration.minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + } = + fees_config + in + let*! inc, consensus = + filter_valid_operations_up_to_quota + initial_inc + (Prioritized_operation_set.operations consensus, consensus_quota) + in + let*! inc, votes = + filter_valid_operations_up_to_quota + inc + (Prioritized_operation_set.operations votes, votes_quota) + in + let*! inc, anonymous = + filter_valid_operations_up_to_quota + inc + (Prioritized_operation_set.operations anonymous, anonymous_quota) + in + (* Sort the managers *) + let prioritized_managers = + prioritize_managers + ~hard_gas_limit_per_block + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + managers + in + let*! inc, managers = + filter_valid_managers_up_to_quota + inc + ~hard_gas_limit_per_block + (PrioritizedManagerSet.elements prioritized_managers, managers_quota) + in + let operations = [consensus; votes; anonymous; managers] in + let operations_hash = + Operation_list_list_hash.compute + (List.map + (fun sl -> + Operation_list_hash.compute (List.map Operation.hash_packed sl)) + operations) + in + let inc = {inc with header = {inc.header with operations_hash}} in + let* result = Baking_simulator.finalize_construction inc in + match result with + | Some (validation_result, block_header_metadata) -> + return + { + validation_result = Some validation_result; + block_header_metadata = Some block_header_metadata; + operations; + operations_hash; + } + | None -> + return + { + validation_result = None; + block_header_metadata = None; + operations; + operations_hash; + } + +let filter_valid_operations_up_to_quota_without_simulation (ops, quota) = + let {Tezos_protocol_environment.max_size; max_op} = quota in + let exception Full of packed_operation list in + try + List.fold_left + (fun (curr_size, nb_ops, acc) op -> + let op_size = + Data_encoding.Binary.length Alpha_context.Operation.encoding op + in + let new_size = curr_size + op_size in + if new_size > max_size then (curr_size, nb_ops, acc) + else ( + Option.iter + (fun max_op -> if max_op = nb_ops + 1 then raise (Full acc)) + max_op ; + (new_size, nb_ops + 1, op :: acc))) + (0, 0, []) + ops + |> fun (_, _, l) -> List.rev l + with Full l -> List.rev l + +let filter_operations_without_simulation fees_config ~hard_gas_limit_per_block + {consensus; votes; anonymous; managers} = + let consensus = + filter_valid_operations_up_to_quota_without_simulation + (Prioritized_operation_set.operations consensus, consensus_quota) + in + let votes = + filter_valid_operations_up_to_quota_without_simulation + (Prioritized_operation_set.operations votes, votes_quota) + in + let anonymous = + filter_valid_operations_up_to_quota_without_simulation + (Prioritized_operation_set.operations anonymous, anonymous_quota) + in + let { + Baking_configuration.minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + } = + fees_config + in + (* Sort the managers *) + let prioritized_managers = + prioritize_managers + ~hard_gas_limit_per_block + ~minimal_fees + ~minimal_nanotez_per_gas_unit + ~minimal_nanotez_per_byte + managers + in + let managers = + filter_valid_operations_up_to_quota_without_simulation + ( PrioritizedManagerSet.elements prioritized_managers + |> List.map (fun {op; _} -> Prioritized_operation.packed op), + managers_quota ) + in + let operations = [consensus; votes; anonymous; managers] in + operations + +let filter_consensus_operations_only inc + ({consensus; votes; anonymous; managers} as ordered_pool) = + let open Lwt_result_syntax in + let*! incremental, filtered_consensus = + filter_valid_operations_up_to_quota inc (consensus, consensus_quota) + in + let payload = Operation_pool.payload_of_ordered_pool ordered_pool in + let* incremental = + List.fold_left_es + (fun inc op -> + let* inc, _ = Baking_simulator.add_operation inc op in + return inc) + incremental + (List.flatten [votes; anonymous; managers]) + in + let filtered_pool = + Operation_pool.ordered_pool_of_payload + ~consensus_operations:filtered_consensus + payload + in + return (incremental, filtered_pool) diff --git a/src/proto_020_PsParisC/lib_delegate/operation_selection.mli b/src/proto_020_PsParisC/lib_delegate/operation_selection.mli new file mode 100644 index 000000000000..d83fd0dda258 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/operation_selection.mli @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_protocol_environment + +type simulation_result = { + validation_result : validation_result option; + block_header_metadata : Apply_results.block_metadata option; + operations : packed_operation list list; + operations_hash : Operation_list_list_hash.t; +} + +(** [filter_operations_with_simulation incremental fees_config + ~hard_gas_limit_per_block ops] tries to validate prioritized operations (and + apply them if [incremental] has been initialised with an + [application_state]) and filter them regarding the quota of each validation + pass. Manager operations are prioritized based on a weight computed from + their fees/gas/bytes. [filter_operations_with_simulation] function returns a + [simulation_result], containing the validated operation, their resulting + [operations_hash], optional [validation_result] and [block_header_metadata] + if the operations were applied. *) +val filter_operations_with_simulation : + Baking_simulator.incremental -> + Baking_configuration.fees_config -> + hard_gas_limit_per_block:Gas.Arith.integral -> + Operation_pool.Prioritized.t -> + simulation_result tzresult Lwt.t + +(** [filter_operations_without_simulation fees_config ~hard_gas_limit_per_block + ops] is similar to [filter_operations_with_simulation] but does not validate + (and apply) operations from [ops] and returns only the operations instead of + a [simulation_result]. + + Hypothesis: operations from [ops] have previously been validated. *) +val filter_operations_without_simulation : + Baking_configuration.fees_config -> + hard_gas_limit_per_block:Gas.Arith.integral -> + Operation_pool.Prioritized.t -> + packed_operation list list + +(** [filter_consensus_operations_only incremental ops] is similar to + [filter_operations_with_simulation] but only filters consensus operations + from [ops]. *) +val filter_consensus_operations_only : + Baking_simulator.incremental -> + Operation_pool.ordered_pool -> + (Baking_simulator.incremental * Operation_pool.ordered_pool) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/operation_worker.ml b/src/proto_020_PsParisC/lib_delegate/operation_worker.ml new file mode 100644 index 000000000000..42d91d24e545 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/operation_worker.ml @@ -0,0 +1,643 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context +open Protocol +open Alpha_context + +module Events = struct + include Internal_event.Simple + + let section = [Protocol.name; "baker"; "operation_worker"] + + let pp_int = Format.pp_print_int + + let loop_failed = + declare_1 + ~section + ~name:"loop_failed" + ~level:Error + ~msg:"loop failed with {trace}" + ~pp1:Error_monad.pp_print_trace + ("trace", Error_monad.trace_encoding) + + let ended = + declare_1 + ~section + ~name:"ended" + ~level:Error + ~msg:"ended with error {stacktrace}" + ("stacktrace", Data_encoding.string) + + let pqc_reached = + declare_2 + ~section + ~name:"pqc_reached" + ~level:Debug + ~msg: + "prequorum reached (voting power: {voting_power}, {preattestations} \ + preattestations)" + ~pp1:pp_int + ("voting_power", Data_encoding.int31) + ~pp2:pp_int + ("preattestations", Data_encoding.int31) + + let preattestations_received = + declare_4 + ~section + ~name:"preattestations_received" + ~level:Debug + ~msg: + "received {count} preattestations (power: {delta_power}) (total voting \ + power: {voting_power}, {preattestations} preattestations)" + ~pp1:pp_int + ("count", Data_encoding.int31) + ~pp2:pp_int + ("delta_power", Data_encoding.int31) + ~pp3:pp_int + ("voting_power", Data_encoding.int31) + ~pp4:pp_int + ("preattestations", Data_encoding.int31) + + let qc_reached = + declare_2 + ~section + ~name:"qc_reached" + ~level:Debug + ~msg: + "quorum reached (voting power: {voting_power}, {attestations} \ + attestations)" + ~pp1:pp_int + ("voting_power", Data_encoding.int31) + ~pp2:pp_int + ("attestations", Data_encoding.int31) + + let attestations_received = + declare_4 + ~section + ~name:"attestations_received" + ~level:Debug + ~msg: + "received {count} attestations (power: {delta_power}) (total voting \ + power: {voting_power}, {attestations} attestations)" + ~pp1:pp_int + ("count", Data_encoding.int31) + ~pp2:pp_int + ("delta_power", Data_encoding.int31) + ~pp3:pp_int + ("voting_power", Data_encoding.int31) + ~pp4:pp_int + ("attestations", Data_encoding.int31) + + let starting_new_monitoring = + declare_0 + ~section + ~name:"starting_new_monitoring" + ~level:Debug + ~msg:"starting new monitoring" + () + + let end_of_stream = + declare_0 + ~section + ~name:"end_of_stream" + ~level:Debug + ~msg:"end of stream" + () + + (* info messages *) + let shutting_down = + declare_0 + ~section + ~name:"shutting_down" + ~level:Info + ~msg:"shutting down operation worker" + () +end + +type candidate = { + hash : Block_hash.t; + round_watched : Round.t; + payload_hash_watched : Block_payload_hash.t; +} + +let candidate_encoding = + let open Data_encoding in + conv + (fun {hash; round_watched; payload_hash_watched} -> + (hash, round_watched, payload_hash_watched)) + (fun (hash, round_watched, payload_hash_watched) -> + {hash; round_watched; payload_hash_watched}) + (obj3 + (req "hash" Block_hash.encoding) + (req "round_watched" Round.encoding) + (req "payload_hash_watched" Block_payload_hash.encoding)) + +type event = + | Prequorum_reached of candidate * Kind.preattestation operation list + | Quorum_reached of candidate * Kind.attestation operation list + +let compare_consensus_contents (op1 : consensus_content) + (op2 : consensus_content) = + Compare.or_else (Raw_level.compare op1.level op2.level) @@ fun () -> + Compare.or_else (Round.compare op1.round op2.round) @@ fun () -> + Compare.or_else (Slot.compare op1.slot op2.slot) @@ fun () -> + Block_payload_hash.compare op1.block_payload_hash op2.block_payload_hash + +module Preattestation_set = Set.Make (struct + type t = Kind.preattestation operation + + let compare + ({protocol_data = {contents = Single (Preattestation op1); _}; shell = _} : + t) + ({protocol_data = {contents = Single (Preattestation op2); _}; shell = _} : + t) = + compare_consensus_contents op1 op2 +end) + +module Attestation_set = Set.Make (struct + type t = Kind.attestation operation + + let compare + ({ + protocol_data = + { + contents = + Single (Attestation {consensus_content = op1; dal_content = _}); + _; + }; + shell = _; + } : + t) + ({ + protocol_data = + { + contents = + Single (Attestation {consensus_content = op2; dal_content = _}); + _; + }; + shell = _; + } : + t) = + (* We do not consider the DAL content (therefore two attestations with the + same consensus content but different DAL content are considered equal), + in order to correctly count the voting power. Note however that there + should be no such operations in the mempool in the first place. *) + compare_consensus_contents op1 op2 +end) + +type pqc_watched = { + candidate_watched : candidate; + get_slot_voting_power : slot:Slot.t -> int option; + consensus_threshold : int; + mutable current_voting_power : int; + mutable preattestations_received : Preattestation_set.t; + mutable preattestations_count : int; +} + +type qc_watched = { + candidate_watched : candidate; + get_slot_voting_power : slot:Slot.t -> int option; + consensus_threshold : int; + mutable current_voting_power : int; + mutable attestations_received : Attestation_set.t; + mutable attestations_count : int; +} + +type watch_kind = Pqc_watch of pqc_watched | Qc_watch of qc_watched + +type quorum_event_stream = { + stream : event Lwt_stream.t; + push : event option -> unit; +} + +type t = { + mutable operation_pool : Operation_pool.pool; + mutable canceler : Lwt_canceler.t; + mutable proposal_watched : watch_kind option; + qc_event_stream : quorum_event_stream; + lock : Lwt_mutex.t; + monitor_node_operations : bool; (* Keep on monitoring node operations *) +} + +let monitor_operations (cctxt : #Protocol_client_context.full) = + let open Lwt_result_syntax in + let* operation_stream, stream_stopper = + Alpha_block_services.Mempool.monitor_operations + cctxt + ~chain:cctxt#chain + ~validated:true + ~branch_delayed:true + ~branch_refused:false + ~refused:false + () + in + let operation_stream = + Lwt_stream.map + (fun ops -> List.map (fun ((_, op), _) -> op) ops) + operation_stream + in + let* shell_header = + Shell_services.Blocks.Header.shell_header + cctxt + ~chain:cctxt#chain + ~block:(`Head 0) + () + in + let round = + match Fitness.(round_from_raw shell_header.fitness) with + | Ok r -> r + | Error _ -> Round.zero + in + return ((shell_header.level, round), operation_stream, stream_stopper) + +let make_initial_state ?(monitor_node_operations = true) () = + let qc_event_stream = + let stream, push = Lwt_stream.create () in + {stream; push} + in + let canceler = Lwt_canceler.create () in + let operation_pool = Operation_pool.empty in + let lock = Lwt_mutex.create () in + { + operation_pool; + canceler; + proposal_watched = None; + qc_event_stream; + lock; + monitor_node_operations; + } + +let is_valid_consensus_content (candidate : candidate) consensus_content = + let {hash = _; round_watched; payload_hash_watched} = candidate in + Round.equal consensus_content.round round_watched + && Block_payload_hash.equal + consensus_content.block_payload_hash + payload_hash_watched + +let cancel_monitoring state = state.proposal_watched <- None + +let reset_monitoring state = + Lwt_mutex.with_lock state.lock @@ fun () -> + match state.proposal_watched with + | None -> Lwt.return_unit + | Some (Pqc_watch pqc_watched) -> + pqc_watched.current_voting_power <- 0 ; + pqc_watched.preattestations_count <- 0 ; + pqc_watched.preattestations_received <- Preattestation_set.empty ; + Lwt.return_unit + | Some (Qc_watch qc_watched) -> + qc_watched.current_voting_power <- 0 ; + qc_watched.attestations_count <- 0 ; + qc_watched.attestations_received <- Attestation_set.empty ; + Lwt.return_unit + +let update_monitoring ?(should_lock = true) state ops = + let open Lwt_syntax in + (if should_lock then Lwt_mutex.with_lock state.lock else fun f -> f ()) + @@ fun () -> + (* If no block is watched, don't do anything *) + match state.proposal_watched with + | None -> return_unit + | Some + (Pqc_watch + ({ + candidate_watched; + get_slot_voting_power; + consensus_threshold; + preattestations_received; + _; + } as proposal_watched)) -> + let preattestations = Operation_pool.filter_preattestations ops in + let preattestations = + List.filter + (fun new_preattestation -> + not + (Preattestation_set.mem + new_preattestation + preattestations_received)) + preattestations + in + let preattestations_count, voting_power = + List.fold_left + (fun (count, power) (op : Kind.preattestation Operation.t) -> + let { + shell = _; + protocol_data = + {contents = Single (Preattestation consensus_content); _}; + _; + } = + op + in + if is_valid_consensus_content candidate_watched consensus_content + then + match get_slot_voting_power ~slot:consensus_content.slot with + | Some op_power -> + proposal_watched.preattestations_received <- + Preattestation_set.add + op + proposal_watched.preattestations_received ; + (succ count, power + op_power) + | None -> + (* preattestations that do not use the first slot of a + delegate are not added to the quorum *) + (count, power) + else (count, power)) + (0, 0) + preattestations + in + proposal_watched.current_voting_power <- + proposal_watched.current_voting_power + voting_power ; + proposal_watched.preattestations_count <- + proposal_watched.preattestations_count + preattestations_count ; + if proposal_watched.current_voting_power >= consensus_threshold then ( + let* () = + Events.( + emit + pqc_reached + ( proposal_watched.current_voting_power, + proposal_watched.preattestations_count )) + in + state.qc_event_stream.push + (Some + (Prequorum_reached + ( candidate_watched, + Preattestation_set.elements + proposal_watched.preattestations_received ))) ; + (* Once the event has been emitted, we cancel the monitoring *) + cancel_monitoring state ; + return_unit) + else + Events.( + emit + preattestations_received + ( preattestations_count, + voting_power, + proposal_watched.current_voting_power, + proposal_watched.preattestations_count )) + | Some + (Qc_watch + ({ + candidate_watched; + get_slot_voting_power; + consensus_threshold; + attestations_received; + _; + } as proposal_watched)) -> + let attestations = Operation_pool.filter_attestations ops in + let attestations = + List.filter + (fun new_attestation -> + not (Attestation_set.mem new_attestation attestations_received)) + attestations + in + let attestations_count, voting_power = + List.fold_left + (fun (count, power) (op : Kind.attestation Operation.t) -> + let { + shell = _; + protocol_data = + {contents = Single (Attestation {consensus_content; _}); _}; + _; + } = + op + in + if is_valid_consensus_content candidate_watched consensus_content + then + match get_slot_voting_power ~slot:consensus_content.slot with + | Some op_power -> + proposal_watched.attestations_received <- + Attestation_set.add + op + proposal_watched.attestations_received ; + (succ count, power + op_power) + | None -> + (* attestations that do not use the first slot of a delegate + are not added to the quorum *) + (count, power) + else (count, power)) + (0, 0) + attestations + in + proposal_watched.current_voting_power <- + proposal_watched.current_voting_power + voting_power ; + proposal_watched.attestations_count <- + proposal_watched.attestations_count + attestations_count ; + if proposal_watched.current_voting_power >= consensus_threshold then ( + let* () = + Events.( + emit + qc_reached + ( proposal_watched.current_voting_power, + proposal_watched.attestations_count )) + in + state.qc_event_stream.push + (Some + (Quorum_reached + ( candidate_watched, + Attestation_set.elements + proposal_watched.attestations_received ))) ; + (* Once the event has been emitted, we cancel the monitoring *) + cancel_monitoring state ; + return_unit) + else + Events.( + emit + attestations_received + ( attestations_count, + voting_power, + proposal_watched.current_voting_power, + proposal_watched.attestations_count )) + +let monitor_quorum state new_proposal_watched = + Lwt_mutex.with_lock state.lock @@ fun () -> + (* if a previous monitoring was registered, we cancel it *) + if state.proposal_watched <> None then cancel_monitoring state ; + state.proposal_watched <- new_proposal_watched ; + let current_consensus_operations = + Operation_pool.Operation_set.elements state.operation_pool.consensus + in + (* initialize with the currently present consensus operations *) + update_monitoring ~should_lock:false state current_consensus_operations + +let monitor_preattestation_quorum state ~consensus_threshold + ~get_slot_voting_power candidate_watched = + let new_proposal = + Some + (Pqc_watch + { + candidate_watched; + get_slot_voting_power; + consensus_threshold; + current_voting_power = 0; + preattestations_received = Preattestation_set.empty; + preattestations_count = 0; + }) + in + monitor_quorum state new_proposal + +let monitor_attestation_quorum state ~consensus_threshold ~get_slot_voting_power + candidate_watched = + let new_proposal = + Some + (Qc_watch + { + candidate_watched; + get_slot_voting_power; + consensus_threshold; + current_voting_power = 0; + attestations_received = Attestation_set.empty; + attestations_count = 0; + }) + in + monitor_quorum state new_proposal + +let shutdown_worker state = + let open Lwt_result_syntax in + let*! () = Events.(emit shutting_down ()) in + Lwt_canceler.cancel state.canceler + +(* Each time a new head is received, the operation_pool field of the state is + cleaned/reset by this function. Instead of emptying it completely, we keep + the attestations of at most 5 rounds and 1 level in the past, to be able to + include as much attestations as possible in the next block if this baker is + the proposer. This allows to handle the following situations: + + - The baker observes an EQC for (L, R), but a proposal arrived for (L, R+1). + After the flush, extra attestations on top of (L, R) are 'Branch_refused', + and are not re-sent by the node. If the baker proposes at (L+1, 1), he should + be able to include these extra attestations. Hence the cache for old rounds. + + - The baker receives a head at (L+1, 0) on top of (L, 0), but this head + didn't reach consensus. If the baker who proposes at (L+1, 1) observed some + extra attestations for (L, 0) that are not included in (L+1, 0), he may want + to add them. But these attestations become 'Outdated' in the mempool once + (L+1, 0) is received. Hence the cache for previous level. +*) +let update_operations_pool state (head_level, head_round) = + let attestations = + let head_round_i32 = Round.to_int32 head_round in + let head_level_i32 = head_level in + Operation_pool.Operation_set.filter + (function + | { + protocol_data = + Operation_data + { + contents = + Single + (Attestation {consensus_content = {round; level; _}; _}); + _; + }; + _; + } -> + let round_i32 = Round.to_int32 round in + let level_i32 = Raw_level.to_int32 level in + let delta_round = Int32.sub head_round_i32 round_i32 in + let delta_level = Int32.sub head_level_i32 level_i32 in + (* Only retain attestations that are maximum 5 rounds old and + 1 level in the last *) + Compare.Int32.(delta_round <= 5l && delta_level <= 1l) + | _ -> false) + state.operation_pool.consensus + in + let operation_pool = {Operation_pool.empty with consensus = attestations} in + state.operation_pool <- operation_pool + +let create ?(monitor_node_operations = true) + (cctxt : #Protocol_client_context.full) = + let open Lwt_syntax in + let state = make_initial_state ~monitor_node_operations () in + (* TODO should we continue forever ? *) + let rec worker_loop () = + let* result = monitor_operations cctxt in + match result with + | Error err -> Events.(emit loop_failed err) + | Ok (head, operation_stream, op_stream_stopper) -> + let* () = Events.(emit starting_new_monitoring ()) in + state.canceler <- Lwt_canceler.create () ; + Lwt_canceler.on_cancel state.canceler (fun () -> + op_stream_stopper () ; + cancel_monitoring state ; + return_unit) ; + update_operations_pool state head ; + let rec loop () = + let* ops = Lwt_stream.get operation_stream in + match ops with + | None -> + (* When the stream closes, it means a new head has been set, + we reset the monitoring and flush current operations *) + let* () = Events.(emit end_of_stream ()) in + op_stream_stopper () ; + let* () = reset_monitoring state in + worker_loop () + | Some ops -> + state.operation_pool <- + Operation_pool.add_operations state.operation_pool ops ; + let* () = update_monitoring state ops in + loop () + in + loop () + in + Lwt.dont_wait + (fun () -> + Lwt.finalize + (fun () -> + if state.monitor_node_operations then worker_loop () else return_unit) + (fun () -> + let* _ = shutdown_worker state in + return_unit)) + (fun exn -> + Events.(emit__dont_wait__use_with_care ended (Printexc.to_string exn))) ; + return state + +let retrieve_pending_operations cctxt state = + let open Lwt_result_syntax in + let open Protocol_client_context in + let* pending_mempool = + Alpha_block_services.Mempool.pending_operations + cctxt + ~chain:cctxt#chain + ~validated:true + ~branch_delayed:true + ~branch_refused:false + ~refused:false + ~outdated:false + () + in + state.operation_pool <- + Operation_pool.add_operations state.operation_pool + @@ List.rev_map snd pending_mempool.validated ; + state.operation_pool <- + Operation_pool.add_operations + state.operation_pool + (List.rev_map + (fun (_, (op, _)) -> op) + (Operation_hash.Map.bindings pending_mempool.branch_delayed)) ; + return_unit + +let get_current_operations state = state.operation_pool + +let get_quorum_event_stream state = state.qc_event_stream.stream diff --git a/src/proto_020_PsParisC/lib_delegate/operation_worker.mli b/src/proto_020_PsParisC/lib_delegate/operation_worker.mli new file mode 100644 index 000000000000..348fe9b25a86 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/operation_worker.mli @@ -0,0 +1,88 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Launch processes to gather operations from the mempool and make them + available for the baker. *) + +open Protocol +open Alpha_context + +(** {1 Datatypes}*) + +type t + +type candidate = { + hash : Block_hash.t; + round_watched : Round.t; + payload_hash_watched : Block_payload_hash.t; +} + +val candidate_encoding : candidate Data_encoding.t + +type event = + | Prequorum_reached of candidate * Kind.preattestation operation list + | Quorum_reached of candidate * Kind.attestation operation list + +(** {1 Constructors}*) + +(** [create ?monitor_node_operations cctxt] creates a monitoring process to + fetch operations for the baker to process. + + @param monitor_node_operations monitor operations on the node (defaults: + [true]). Set [monitor_node_operations] to [false] to only consider + externally provided (non-node) operations. *) +val create : + ?monitor_node_operations:bool -> #Protocol_client_context.full -> t Lwt.t + +(** {1 Utilities} *) + +val retrieve_pending_operations : + #Protocol_client_context.full -> t -> unit tzresult Lwt.t + +(** {1 Accessors}*) + +val get_current_operations : t -> Operation_pool.pool + +val get_quorum_event_stream : t -> event Lwt_stream.t + +(** {1 Observers} *) + +val monitor_preattestation_quorum : + t -> + consensus_threshold:int -> + get_slot_voting_power:(slot:Slot.t -> int option) -> + candidate -> + unit Lwt.t + +val monitor_attestation_quorum : + t -> + consensus_threshold:int -> + get_slot_voting_power:(slot:Slot.t -> int option) -> + candidate -> + unit Lwt.t + +val cancel_monitoring : t -> unit + +val shutdown_worker : t -> (unit, exn list) result Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/per_block_vote_file.ml b/src/proto_020_PsParisC/lib_delegate/per_block_vote_file.ml new file mode 100644 index 000000000000..fb903bde0422 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/per_block_vote_file.ml @@ -0,0 +1,154 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Baking_errors +module Events = Baking_events.Per_block_votes + +let default_vote_json_filename = "per_block_votes.json" + +type per_block_votes = { + liquidity_baking_toggle_vote : + Protocol.Alpha_context.Per_block_votes.per_block_vote; + adaptive_issuance_vote_opt : + Protocol.Alpha_context.Per_block_votes.per_block_vote option; +} + +let vote_file_content_encoding = + let open Data_encoding in + def (String.concat "." [Protocol.name; "vote_file_content"]) + @@ conv + (fun {liquidity_baking_toggle_vote; adaptive_issuance_vote_opt} -> + (liquidity_baking_toggle_vote, adaptive_issuance_vote_opt)) + (fun (liquidity_baking_toggle_vote, adaptive_issuance_vote_opt) -> + {liquidity_baking_toggle_vote; adaptive_issuance_vote_opt}) + (obj2 + (req + "liquidity_baking_toggle_vote" + Protocol.Alpha_context.Per_block_votes + .liquidity_baking_vote_encoding) + (opt + "adaptive_issuance_vote" + Protocol.Alpha_context.Per_block_votes + .adaptive_issuance_vote_encoding)) + +let check_file_exists file = + let open Lwt_result_syntax in + let*! file_exists = + Lwt.catch (fun () -> Lwt_unix.file_exists file) (fun _ -> Lwt.return_false) + in + if file_exists then return_unit else tzfail (Block_vote_file_not_found file) + +let read_per_block_votes ~per_block_vote_file : 'a tzresult Lwt.t = + let open Lwt_result_syntax in + let*! () = Events.(emit reading_per_block_votes) per_block_vote_file in + let* () = check_file_exists per_block_vote_file in + let* votes_json = + trace + (Block_vote_file_invalid per_block_vote_file) + (Lwt_utils_unix.Json.read_file per_block_vote_file) + in + let* votes = + trace + (Block_vote_file_wrong_content per_block_vote_file) + (protect (fun () -> + return + (Data_encoding.Json.destruct vote_file_content_encoding votes_json))) + in + return votes + +let read_per_block_votes_no_fail ~default ~per_block_vote_file = + let open Lwt_syntax in + let* result = read_per_block_votes ~per_block_vote_file in + match result with + | Error errs -> + let* () = Events.(emit per_block_vote_file_fail) errs in + return default + | Ok + { + liquidity_baking_toggle_vote; + adaptive_issuance_vote_opt = Some adaptive_issuance_vote; + } -> + return + Protocol.Alpha_context.Per_block_votes. + { + liquidity_baking_vote = liquidity_baking_toggle_vote; + adaptive_issuance_vote; + } + | Ok {liquidity_baking_toggle_vote; adaptive_issuance_vote_opt = None} -> + return {default with liquidity_baking_vote = liquidity_baking_toggle_vote} + +let load_per_block_votes_config ~default_liquidity_baking_vote + ~default_adaptive_issuance_vote ~per_block_vote_file : + Baking_configuration.per_block_votes_config tzresult Lwt.t = + let open Lwt_result_syntax in + (* If a vote file is given, it takes priority. Otherwise, we expect + per-block vote arguments to be passed. *) + let default_adaptive_issuance_vote = + (* Unlike the vote for liquidity baking, the vote for adaptive + issuance is not mandatory. *) + match default_adaptive_issuance_vote with + | None -> Protocol.Alpha_context.Per_block_votes.Per_block_vote_pass + | Some default_adaptive_issuance_vote -> default_adaptive_issuance_vote + in + let* config = + match (per_block_vote_file, default_liquidity_baking_vote) with + | None, None -> tzfail Missing_vote_on_startup + | None, Some liquidity_baking_vote -> + return + { + Baking_configuration.vote_file = None; + liquidity_baking_vote; + adaptive_issuance_vote = default_adaptive_issuance_vote; + } + | Some per_block_vote_file, _ -> ( + let*! (res : _ tzresult) = read_per_block_votes ~per_block_vote_file in + match res with + | Ok + { + liquidity_baking_toggle_vote = liquidity_baking_vote; + adaptive_issuance_vote_opt; + } -> + let adaptive_issuance_vote = + Option.value + ~default:default_adaptive_issuance_vote + adaptive_issuance_vote_opt + in + return + { + Baking_configuration.vote_file = Some per_block_vote_file; + liquidity_baking_vote; + adaptive_issuance_vote; + } + | Error errs -> + let*! () = Events.(emit per_block_vote_file_fail) errs in + tzfail Missing_vote_on_startup) + in + let*! () = + Events.(emit liquidity_baking_toggle_vote) config.liquidity_baking_vote + in + let*! () = + Events.(emit adaptive_issuance_vote) config.adaptive_issuance_vote + in + return config diff --git a/src/proto_020_PsParisC/lib_delegate/per_block_vote_file.mli b/src/proto_020_PsParisC/lib_delegate/per_block_vote_file.mli new file mode 100644 index 000000000000..5347f30a6ce8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/per_block_vote_file.mli @@ -0,0 +1,77 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module is used to load the baker's per block votes + configurations. When a file is given as configuration, its content + is expected to be a valid JSON matching the following examples: + - {v {"liquidity_baking_toggle_vote": "on"} v} + - {v {"liquidity_baking_toggle_vote": "off"} v} + - {v {"liquidity_baking_toggle_vote": "pass"} v} + - {v {"adaptive_issuance_vote": "on"} v} + - {v {"adaptive_issuance_vote": "off"} v} + - {v {"adaptive_issuance_vote": "pass"} v} + - {v {"liquidity_baking_toggle_vote": "on","adaptive_issuance_vote": "on"} v} + - {v {"liquidity_baking_toggle_vote": "on","adaptive_issuance_vote": "off"} v} + - {v {"liquidity_baking_toggle_vote": "on","adaptive_issuance_vote": "pass"} v} + - {v {"liquidity_baking_toggle_vote": "off","adaptive_issuance_vote": "on"} v} + - {v {"liquidity_baking_toggle_vote": "off","adaptive_issuance_vote": "off"} v} + - {v {"liquidity_baking_toggle_vote": "off","adaptive_issuance_vote": "pass"} v} + - {v {"liquidity_baking_toggle_vote": "pass","adaptive_issuance_vote": "on"} v} + - {v {"liquidity_baking_toggle_vote": "pass","adaptive_issuance_vote": "off"} v} + - {v {"liquidity_baking_toggle_vote": "pass","adaptive_issuance_vote": "pass"} v} + + Moreover, in order to handle dynamic voting (i.e. change the + baker's vote without having to restart it), each time a block is + being built, the baker will try and read the vote file present in + the config in order to check for updated votes. +*) + +open Protocol.Alpha_context + +(** Default vote file name that should be looked up when the baker + starts. *) +val default_vote_json_filename : string + +(** Reads the content of [per_block_vote_file] and returns the votes. If + any error occurs (e.g. Non-existing file, unparsable content, + etc.), given default values will be used to fill the gaps. *) +val read_per_block_votes_no_fail : + default:Per_block_votes.per_block_votes -> + per_block_vote_file:string -> + Per_block_votes.per_block_votes Lwt.t + +(** Load a configuration of per-block votes. Liquidity baking toggle + vote is mandatory, it has to come from either the per-block vote + file [per_block_vote_file] or from + [default_liquidity_baking_vote]. If a vote cannot be determined + from those values, this function fails. Adaptive issuance feature + vote is optional. Priority is given to the values in the + [per_block_vote_file] file for all votes at the time of the block + (the file is freshly read each time). *) +val load_per_block_votes_config : + default_liquidity_baking_vote:Per_block_votes.per_block_vote option -> + default_adaptive_issuance_vote:Per_block_votes.per_block_vote option -> + per_block_vote_file:string option -> + Baking_configuration.per_block_votes_config tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/state_transitions.ml b/src/proto_020_PsParisC/lib_delegate/state_transitions.ml new file mode 100644 index 000000000000..efba1fd1d252 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/state_transitions.ml @@ -0,0 +1,1088 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Baking_state +open Baking_actions +module Events = Baking_events.State_transitions + +let do_nothing state = Lwt.return (state, Do_nothing) + +type proposal_acceptance = Invalid | Outdated_proposal | Valid_proposal + +let is_acceptable_proposal_for_current_level state + (proposal : Baking_state.proposal) = + let open Lwt_syntax in + let current_round = state.round_state.current_round in + if Round.(current_round < proposal.block.round) then + let* () = + Events.( + emit unexpected_proposal_round (current_round, proposal.block.round)) + in + return Invalid + else if Round.(current_round > proposal.block.round) then + return Outdated_proposal + else + (* current_round = proposal.round *) + let previous_proposal = state.level_state.latest_proposal in + if + Round.(proposal.block.round = previous_proposal.block.round) + && Block_hash.(proposal.block.hash <> previous_proposal.block.hash) + && Block_hash.( + proposal.predecessor.hash = previous_proposal.predecessor.hash) + then + (* An existing proposal was found at the same round: the + proposal is bad and should be punished by the accuser *) + let* () = + Events.( + emit + proposal_for_round_already_seen + (proposal.block.hash, current_round, previous_proposal.block.hash)) + in + return Invalid + else + (* current_round = proposal.block.round ∧ + proposal.block.round <> previous_proposal.block.round + => + proposal.block.round > previous_proposal.block.round + + The proposal has the expected round and the previous proposal + is a predecessor therefore the proposal is valid *) + return Valid_proposal + +let make_consensus_vote_batch state proposal kind = + let level = + Raw_level.of_int32 state.level_state.current_level |> function + | Ok l -> l + | _ -> assert false + in + let round = proposal.block.round in + let block_payload_hash = proposal.block.payload_hash in + let batch_content = {level; round; block_payload_hash} in + let delegates_and_slots = + List.map + (fun delegate_slot -> + (delegate_slot.consensus_key_and_delegate, delegate_slot.first_slot)) + (Delegate_slots.own_delegates state.level_state.delegate_slots) + in + (* The branch is the latest finalized block. *) + let batch_branch = state.level_state.latest_proposal.predecessor.hash in + Baking_state.make_unsigned_consensus_vote_batch + kind + batch_content + ~batch_branch + delegates_and_slots + +(* If we do not have any slots, we won't inject any operation but we + will still participate to determine an elected block *) +let prepare_preattest_action state proposal = + let preattestations : unsigned_consensus_vote_batch = + make_consensus_vote_batch state proposal Baking_state.Preattestation + in + Prepare_preattestations {preattestations} + +let prepare_consensus_votes_action state proposal = + let preattestations : unsigned_consensus_vote_batch = + make_consensus_vote_batch state proposal Baking_state.Preattestation + in + let attestations : unsigned_consensus_vote_batch = + make_consensus_vote_batch state proposal Baking_state.Attestation + in + Prepare_consensus_votes {preattestations; attestations} + +let update_proposal ~is_proposal_applied state proposal = + let open Lwt_syntax in + let* () = Events.(emit updating_latest_proposal proposal.block.hash) in + let prev_proposal = state.level_state.latest_proposal in + let is_latest_proposal_applied = + (* mark as applied if it is indeed applied or if this specific proposal was + already marked as applied *) + is_proposal_applied + || prev_proposal.block.hash = proposal.block.hash + && state.level_state.is_latest_proposal_applied + in + let new_level_state = + { + state.level_state with + is_latest_proposal_applied; + latest_proposal = proposal; + } + in + return {state with level_state = new_level_state} + +let may_update_proposal ~is_proposal_applied state (proposal : proposal) = + assert ( + Compare.Int32.( + state.level_state.latest_proposal.block.shell.level + = proposal.block.shell.level)) ; + if + Round.(state.level_state.latest_proposal.block.round < proposal.block.round) + then update_proposal ~is_proposal_applied state proposal + else Lwt.return state + +let preattest state proposal = + let open Lwt_syntax in + if Baking_state.is_first_block_in_protocol proposal then + (* We do not preattest the first transition block *) + let new_state = update_current_phase state Idle in + return (new_state, Do_nothing) + else + let* () = Events.(emit attempting_preattest_proposal proposal.block.hash) in + let new_state = + (* We have detected a new proposal that needs to be preattested. + We switch to the `Awaiting_preattestations` phase. *) + update_current_phase state Awaiting_preattestations + in + (* Here, we do not cancel pending signatures as it is already done + in [handle_proposal]. *) + return (new_state, prepare_preattest_action state proposal) + +let prepare_consensus_votes state proposal = + let open Lwt_syntax in + if Baking_state.is_first_block_in_protocol proposal then + (* We do not vote for the first transition block *) + let new_state = update_current_phase state Idle in + return (new_state, Do_nothing) + else + let* () = Events.(emit attempting_vote_proposal proposal.block.hash) in + let new_state = + (* We have detected a new proposal that needs to be voted for. + We switch to the `Awaiting_preattestations` phase. *) + update_current_phase state Awaiting_preattestations + in + return (new_state, prepare_consensus_votes_action state proposal) + +let extract_pqc state (new_proposal : proposal) = + match new_proposal.block.prequorum with + | None -> None + | Some pqc -> + let add_voting_power acc (op : Kind.preattestation Operation.t) = + let open Protocol.Alpha_context.Operation in + let { + shell = _; + protocol_data = {contents = Single (Preattestation {slot; _}); _}; + _; + } = + op + in + match + Delegate_slots.voting_power state.level_state.delegate_slots ~slot + with + | None -> + (* cannot happen if the map is correctly populated *) + acc + | Some attesting_power -> acc + attesting_power + in + let voting_power = + List.fold_left add_voting_power 0 pqc.preattestations + in + let consensus_threshold = + state.global_state.constants.parametric.consensus_threshold + in + if Compare.Int.(voting_power >= consensus_threshold) then + Some (pqc.preattestations, pqc.round) + else None + +let may_update_attestable_payload_with_internal_pqc state + (new_proposal : proposal) = + match + (new_proposal.block.prequorum, state.level_state.attestable_payload) + with + | None, _ -> + (* The proposal does not contain a PQC: no need to update *) + state + | Some {round = new_round; _}, Some {prequorum = {round = old_round; _}; _} + when Round.(new_round < old_round) -> + (* The proposal pqc is outdated, do not update *) + state + | Some better_prequorum, _ -> + assert ( + Block_payload_hash.( + better_prequorum.block_payload_hash = new_proposal.block.payload_hash)) ; + assert ( + Compare.Int32.(better_prequorum.level = new_proposal.block.shell.level)) ; + let new_attestable_payload = + Some {proposal = new_proposal; prequorum = better_prequorum} + in + let new_level_state = + {state.level_state with attestable_payload = new_attestable_payload} + in + {state with level_state = new_level_state} + +let has_already_been_handled state new_proposal = + let current_proposal = state.level_state.latest_proposal in + Block_hash.(current_proposal.block.hash = new_proposal.block.hash) + && state.level_state.is_latest_proposal_applied + +let mark_awaiting_pqc state = + let new_round_state = + {state.round_state with awaiting_unlocking_pqc = true} + in + let new_state = {state with round_state = new_round_state} in + new_state + +let rec handle_proposal ~is_proposal_applied state (new_proposal : proposal) = + let open Lwt_syntax in + (* We need to avoid to send votes if we are in phases where consensus + votes are already being forged. This is needed to avoid switching + back from Awaiting_attestations to Awaiting_preattestations. + Hypothesis: a fresh round's initial phase is Idle *) + let may_vote state proposal = + match state.round_state.current_phase with + | Idle -> + (* We prioritize the new and meaningful consensus vote signing + by cancelling all pending forge and signing tasks. In this + current context, preattesting means that it is now too late + to include outdated consensus votes and blocks. However, + active forge requests are still processed until + completion. *) + state.global_state.forge_worker_hooks.cancel_all_pending_tasks () ; + prepare_consensus_votes state proposal + | _ -> do_nothing state + in + let current_level = state.level_state.current_level in + let new_proposal_level = new_proposal.block.shell.level in + let current_proposal = state.level_state.latest_proposal in + if + is_proposal_applied + && Block_hash.(current_proposal.block.hash = new_proposal.block.hash) + then + let new_level_state = + {state.level_state with is_latest_proposal_applied = true} + in + let new_state = {state with level_state = new_level_state} in + do_nothing new_state + else if Compare.Int32.(current_level > new_proposal_level) then + (* The baker is ahead, a reorg may have happened. Do nothing: + wait for the node to send us the branch's head. This new head + should have a fitness that is greater than our current + proposal and thus, its level should be at least the same as + our current proposal's level. *) + let* () = + Events.(emit baker_is_ahead_of_node (current_level, new_proposal_level)) + in + do_nothing state + else if Compare.Int32.(current_level = new_proposal_level) then + if + (* The received head is a new proposal for the current level: + let's check if it's a valid one for us. *) + Block_hash.( + current_proposal.predecessor.hash <> new_proposal.predecessor.hash) + then + let* () = + Events.( + emit + new_proposal_is_on_another_branch + (current_proposal.predecessor.hash, new_proposal.predecessor.hash)) + in + may_switch_branch ~is_proposal_applied state new_proposal + else + let* proposal_acceptance = + is_acceptable_proposal_for_current_level state new_proposal + in + match proposal_acceptance with + | Invalid -> + (* The proposal is invalid: we ignore it *) + let* () = Events.(emit skipping_invalid_proposal ()) in + do_nothing state + | Outdated_proposal -> + (* Check whether we need to update our attestable payload *) + let state = + may_update_attestable_payload_with_internal_pqc state new_proposal + in + (* The proposal is outdated: we update to be able to extract + its included attestations but we do not attest it *) + let* () = Events.(emit outdated_proposal new_proposal.block.hash) in + let* state = + may_update_proposal ~is_proposal_applied state new_proposal + in + do_nothing state + | Valid_proposal -> ( + (* Valid_proposal => proposal.round = current_round *) + (* Check whether we need to update our attestable payload *) + let new_state = + may_update_attestable_payload_with_internal_pqc state new_proposal + in + let* new_state = + may_update_proposal ~is_proposal_applied new_state new_proposal + in + (* We invalidate early attestations *) + let new_round_state = + {new_state.round_state with early_attestations = []} + in + let new_state = {new_state with round_state = new_round_state} in + (* The proposal is valid but maybe we already locked on a payload *) + match new_state.level_state.locked_round with + | Some locked_round -> ( + if + Block_payload_hash.( + locked_round.payload_hash = new_proposal.block.payload_hash) + then + (* when the new head has the same payload as our + [locked_round], we accept it and vote for it *) + may_vote new_state new_proposal + else + (* The payload is different *) + match new_proposal.block.prequorum with + | Some {round; _} when Round.(locked_round.round < round) -> + (* This PQC is above our locked_round, we can and vote for it *) + may_vote new_state new_proposal + | _ -> + (* We shouldn't vote for proposal, but we + should at least watch (pre)quorums events on it + but only when it is applied otherwise we await + for the proposal to be applied. *) + let new_state = mark_awaiting_pqc new_state in + let new_state = + update_current_phase new_state Awaiting_preattestations + in + return (new_state, Watch_prequorum)) + | None -> + (* Otherwise, we did not lock on any payload, thus we can + vote for it it *) + may_vote new_state new_proposal) + else + (* Last case: new_proposal_level > current_level *) + (* Possible scenarios: + - we received a block for a next level + - we received our own block + This is where we update our [level_state] (and our [round_state]) *) + let* () = Events.(emit new_head_with_increasing_level ()) in + let new_level = new_proposal.block.shell.level in + let compute_new_state ~current_round ~delegate_slots + ~next_level_delegate_slots = + let round_state = + { + current_round; + current_phase = Idle; + delayed_quorum = None; + early_attestations = []; + awaiting_unlocking_pqc = false; + } + in + let level_state = + { + current_level = new_level; + latest_proposal = new_proposal; + is_latest_proposal_applied = is_proposal_applied; + (* Unlock values *) + locked_round = None; + attestable_payload = None; + elected_block = None; + delegate_slots; + next_level_delegate_slots; + next_level_proposed_round = None; + } + in + (* recursive call with the up-to-date state to handle the new + level proposals *) + handle_proposal + ~is_proposal_applied + {state with level_state; round_state} + new_proposal + in + let action = + Update_to_level {new_level_proposal = new_proposal; compute_new_state} + in + return (state, action) + +and may_switch_branch ~is_proposal_applied state new_proposal = + let open Lwt_syntax in + let switch_branch state = + let* () = Events.(emit switching_branch ()) in + (* If we are on a different branch, we also need to update our + [round_state] accordingly. + The recursive call to [handle_proposal] cannot end up + with an invalid proposal as it's on a different branch, thus + there is no need to backtrack to the former state as the new + proposal must end up being the new [latest_proposal]. That's + why we update it here. *) + let round_update = + { + Baking_actions.new_round_proposal = new_proposal; + handle_proposal = + (fun state -> handle_proposal ~is_proposal_applied state new_proposal); + } + in + let* new_state = update_proposal ~is_proposal_applied state new_proposal in + (* TODO if the branch proposal is outdated, we should + trigger an [End_of_round] to participate *) + return (new_state, Synchronize_round round_update) + in + let current_attestable_payload = state.level_state.attestable_payload in + match (current_attestable_payload, new_proposal.block.prequorum) with + | None, Some _ | None, None -> + let* () = Events.(emit branch_proposal_has_better_fitness ()) in + (* The new branch contains a PQC (and we do not) or a better + fitness, we switch. *) + switch_branch state + | Some _, None -> + (* We have a better PQC, we don't switch as we are able to + propose a better chain if we stay on our current one. *) + let* () = Events.(emit branch_proposal_has_no_prequorum ()) in + do_nothing state + | Some {prequorum = current_pqc; _}, Some new_pqc -> + if Round.(current_pqc.round > new_pqc.round) then + let* () = Events.(emit branch_proposal_has_lower_prequorum ()) in + (* The other's branch PQC is lower than ours, do not + switch *) + do_nothing state + else if Round.(current_pqc.round < new_pqc.round) then + let* () = Events.(emit branch_proposal_has_better_prequorum ()) in + (* Their PQC is better than ours: we switch *) + switch_branch state + else + (* current_pqc.round = new_pqc *) + (* There is a PQC on two branches with the same round and + the same level but not the same predecessor : it's + impossible unless if there was some double-baking. This + shouldn't happen but do nothing anyway. *) + let* () = Events.(emit branch_proposal_has_same_prequorum ()) in + do_nothing state + +(* Create a fresh block proposal containing the current operations of the + mempool in [state] and the additional [attestations] for [delegate] at round + [round]. *) +let prepare_block_to_bake ~attestations ?last_proposal + ~(predecessor : block_info) state delegate round = + (* The block to bake embeds the operations gathered by the + worker. However, consensus operations that are not relevant for + this block are filtered out. In the case of proposing a new fresh + block, the block is supposed to carry only attestations for the + previous level. *) + let open Lwt_syntax in + let operation_pool = + (* 1. Fetch operations from the mempool. *) + let current_mempool = + let pool = + Operation_worker.get_current_operations + state.global_state.operation_worker + in + (* Considered the operations in the previous proposal as well *) + match last_proposal with + | Some proposal -> + let { + Operation_pool.votes_payload; + anonymous_payload; + managers_payload; + } = + proposal.payload + in + List.fold_left + Operation_pool.add_operations + pool + [votes_payload; anonymous_payload; managers_payload] + | None -> pool + in + (* 2. Filter and only retain relevant attestations. *) + let relevant_consensus_operations = + let attestation_filter = + { + Operation_pool.level = predecessor.shell.level; + round = predecessor.round; + payload_hash = predecessor.payload_hash; + } + in + Operation_pool.filter_with_relevant_consensus_ops + ~attestation_filter + ~preattestation_filter:None + current_mempool.consensus + in + let filtered_mempool = + {current_mempool with consensus = relevant_consensus_operations} + in + (* 3. Add the additional given [attestations]. + N.b. this is a set: there won't be duplicates *) + Operation_pool.add_operations + filtered_mempool + (List.map Operation.pack attestations) + in + let kind = Fresh operation_pool in + let* () = Events.(emit preparing_fresh_block (delegate, round)) in + let force_apply = + state.global_state.config.force_apply || Round.(round <> zero) + (* This is used as a safety net by applying blocks on round > 0, in case + validation-only did not produce a correct round-0 block. *) + in + let block_to_bake : block_to_bake = + {predecessor; round; delegate; kind; force_apply} + in + return (Prepare_block {block_to_bake}) + +(** Create an inject action that will inject either a fresh block or the pre-emptively + forged block if it exists. *) +let propose_fresh_block_action ~attestations ?last_proposal + ~(predecessor : block_info) state delegate round = + (* TODO check if there is a trace where we could not have updated the level *) + prepare_block_to_bake + ~attestations + ?last_proposal + ~predecessor + state + delegate + round + +let propose_block_action state delegate round ~last_proposal = + let open Lwt_syntax in + (* Possible cases: + 1. There was a proposal but the PQC was not reached. + 2. There was a proposal and the PQC was reached. We repropose the + [attestable_payload] if it exists, not the [locked_round] as it + may be older. *) + match state.level_state.attestable_payload with + | None -> + let* () = Events.(emit no_attestable_payload_fresh_block ()) in + (* For case 1, we may re-inject with the same payload or a fresh + one. We make the choice of baking a fresh one: the previous + proposal may have been rejected because the block may have been + valid but may be considered "bad" (censored operations, empty + block, etc.) by the other validators. *) + (* Invariant: there is no locked round if there is no attestable + payload *) + assert (state.level_state.locked_round = None) ; + let attestations_in_last_proposal = last_proposal.block.quorum in + propose_fresh_block_action + ~attestations:attestations_in_last_proposal + state + ~last_proposal:last_proposal.block + ~predecessor:last_proposal.predecessor + delegate + round + | Some {proposal; prequorum} -> + let* () = Events.(emit repropose_block proposal.block.payload_hash) in + (* For case 2, we re-inject the same block as [attestable_round] + but we may add some left-overs attestations. Therefore, the + operations we need to include are: + - the proposal's included attestations + - the potential missing new attestations for the + previous block + - the PQC of the attestable payload *) + let consensus_operations = + (* Fetch preattestations and attestations from the mempool + (that could be missing from the proposal), filter, then add + consensus operations of the proposal itself, and convert + into [packed_operation trace]. *) + let mempool_consensus_operations = + (Operation_worker.get_current_operations + state.global_state.operation_worker) + .consensus + in + let all_consensus_operations = + (* Add the proposal and pqc consensus operations to the + mempool *) + List.fold_left + (fun set op -> Operation_pool.Operation_set.add op set) + mempool_consensus_operations + (List.map Operation.pack proposal.block.quorum + @ List.map Operation.pack prequorum.preattestations) + in + let attestation_filter = + { + Operation_pool.level = proposal.predecessor.shell.level; + round = proposal.predecessor.round; + payload_hash = proposal.predecessor.payload_hash; + } + in + let preattestation_filter = + Some + { + Operation_pool.level = prequorum.level; + round = prequorum.round; + payload_hash = prequorum.block_payload_hash; + } + in + Operation_pool.( + filter_with_relevant_consensus_ops + ~attestation_filter + ~preattestation_filter + all_consensus_operations + |> Operation_set.elements) + in + let payload_hash = proposal.block.payload_hash in + let payload_round = proposal.block.payload_round in + let payload = proposal.block.payload in + let kind = + Reproposal {consensus_operations; payload_hash; payload_round; payload} + in + let force_apply = + true + (* This is used as a safety net by applying blocks on round > 0, in case + validation-only did not produce a correct round-0 block. *) + in + let block_to_bake = + {predecessor = proposal.predecessor; round; delegate; kind; force_apply} + in + return (Prepare_block {block_to_bake}) + +let end_of_round state current_round = + let open Lwt_syntax in + let new_round = Round.succ current_round in + (* We initialize the round's phase to Idle for the [handle_proposal] + transition to trigger the preattestation action. *) + let new_round_state = + { + current_round = new_round; + current_phase = Idle; + delayed_quorum = None; + early_attestations = []; + awaiting_unlocking_pqc = false; + } + in + let new_state = {state with round_state = new_round_state} in + (* we need to check if we need to bake for this round or not *) + match + round_proposer new_state ~level:`Current new_state.round_state.current_round + with + | None -> + let* () = + Events.( + emit + no_proposal_slot + (current_round, state.level_state.current_level, new_round)) + in + (* We don't have any delegate that may propose a new block for + this round -- We will wait for preattestations when the next + level block arrive. Meanwhile, we are idle *) + let new_state = update_current_phase new_state Idle in + do_nothing new_state + | Some {consensus_key_and_delegate; _} -> + let latest_proposal = state.level_state.latest_proposal in + if Baking_state.is_first_block_in_protocol latest_proposal then + (* Do not inject a block for the previous protocol! (Let the + baker of the previous protocol do it.) *) + do_nothing new_state + else + let* () = + Events.( + emit + proposal_slot + ( current_round, + state.level_state.current_level, + new_round, + consensus_key_and_delegate )) + in + (* We have a delegate, we need to determine what to inject *) + let* action = + propose_block_action + new_state + consensus_key_and_delegate + new_round + ~last_proposal:state.level_state.latest_proposal + in + return (new_state, action) + +let time_to_prepare_next_level_block state at_round = + let open Lwt_syntax in + (* It is now time to update the state level *) + (* We need to keep track for which block we have 2f+1 *attestations*, that is, + which will become the new predecessor_block *) + (* Invariant: attestable_round >= round(elected block) >= locked_round *) + let round_proposer_opt = round_proposer state ~level:`Next at_round in + match (state.level_state.elected_block, round_proposer_opt) with + | None, _ | _, None -> + (* Unreachable: the [Time_to_prepare_next_level_block] event can only be + triggered when we have a slot and an elected block *) + assert false + | Some elected_block, Some {consensus_key_and_delegate; _} -> + let attestations = elected_block.attestation_qc in + let new_level_state = + {state.level_state with next_level_proposed_round = Some at_round} + in + let new_state = {state with level_state = new_level_state} in + let* action = + propose_fresh_block_action + ~attestations + ~predecessor:elected_block.proposal.block + new_state + consensus_key_and_delegate + at_round + in + return (new_state, action) + +let update_locked_round state round payload_hash = + let locked_round = Some {payload_hash; round} in + let new_level_state = {state.level_state with locked_round} in + {state with level_state = new_level_state} + +let prepare_attest_action state proposal = + let attestations : unsigned_consensus_vote_batch = + make_consensus_vote_batch state proposal Baking_state.Attestation + in + Prepare_attestations {attestations} + +let inject_early_arrived_attestations state = + let early_attestations = state.round_state.early_attestations in + match early_attestations with + | [] -> Lwt.return (state, Watch_quorum) + | first_signed_attestation :: _ as unbatched_signed_attestations -> ( + let new_round_state = {state.round_state with early_attestations = []} in + let new_state = {state with round_state = new_round_state} in + let batch_branch = state.level_state.latest_proposal.predecessor.hash in + let batch_content = + let vote_consensus_content = + first_signed_attestation.unsigned_consensus_vote + .vote_consensus_content + in + { + level = vote_consensus_content.level; + round = vote_consensus_content.round; + block_payload_hash = vote_consensus_content.block_payload_hash; + } + in + make_signed_consensus_vote_batch + Attestation + batch_content + ~batch_branch + unbatched_signed_attestations + |> function + | Ok signed_attestations -> + Lwt.return (new_state, Inject_attestations {signed_attestations}) + | Error _err -> (* Unreachable *) do_nothing new_state) + +let prequorum_reached_when_awaiting_preattestations state candidate + preattestations = + let open Lwt_syntax in + let latest_proposal = state.level_state.latest_proposal in + if Block_hash.(candidate.Operation_worker.hash <> latest_proposal.block.hash) + then + let* () = + Events.( + emit + unexpected_prequorum_received + (candidate.hash, latest_proposal.block.hash)) + in + do_nothing state + else + let prequorum = + { + level = latest_proposal.block.shell.level; + round = latest_proposal.block.round; + block_payload_hash = latest_proposal.block.payload_hash; + preattestations + (* preattestations may be nil when [consensus_threshold] is 0 *); + } + in + let new_attestable_payload = {proposal = latest_proposal; prequorum} in + let new_level_state = + let level_state_with_new_payload = + { + state.level_state with + attestable_payload = Some new_attestable_payload; + } + in + match state.level_state.attestable_payload with + | None -> level_state_with_new_payload + | Some attestable_payload -> + if + Round.( + attestable_payload.prequorum.round + < new_attestable_payload.prequorum.round) + then level_state_with_new_payload + else state.level_state + in + let new_state = {state with level_state = new_level_state} in + let new_state = + update_locked_round + new_state + latest_proposal.block.round + latest_proposal.block.payload_hash + in + let new_state = update_current_phase new_state Awaiting_attestations in + if new_state.round_state.awaiting_unlocking_pqc then + (* We were locked and did not trigger preemptive + consensus votes: we need to start attesting now. *) + return (new_state, prepare_attest_action new_state latest_proposal) + else + (* We already triggered preemptive attestation forging, we + either have those already or we are waiting for them. *) + inject_early_arrived_attestations new_state + +let quorum_reached_when_waiting_attestations state candidate attestation_qc = + let open Lwt_syntax in + let latest_proposal = state.level_state.latest_proposal in + let is_latest_proposal_applied = + state.level_state.is_latest_proposal_applied + in + if Block_hash.(candidate.Operation_worker.hash <> latest_proposal.block.hash) + then + let* () = + Events.( + emit + unexpected_quorum_received + (candidate.hash, latest_proposal.block.hash)) + in + do_nothing state + else + let new_round_state, new_level_state = + match state.level_state.elected_block with + | None when is_latest_proposal_applied -> + (* The elected proposal has been applied. Record the elected block + and transition to the Idle phase, as there is nothing left to do. + *) + let elected_block = + Some {proposal = latest_proposal; attestation_qc} + in + let new_level_state = {state.level_state with elected_block} in + let new_round_state = {state.round_state with current_phase = Idle} in + (new_round_state, new_level_state) + | None -> + (* A quorum has been reached, but the elected proposal has not been + applied yet by the node. Transition in the `Awaiting_application` + phase, and do not save the elected block in the state. Instead, + keep track that an early quorum has been reached at this round. + This avoids the proposer of a block at the next level to inject a + proposal before the node has been applied the proposal elected at + the current level. *) + let new_round_state = + { + state.round_state with + current_phase = Awaiting_application; + delayed_quorum = Some attestation_qc; + } + in + (new_round_state, state.level_state) + | Some _ -> + (* If we already have an elected block, do not update it: the + earlier, the better. We do not need to record the quorum either, + as this won't be used to elect a new block. *) + (state.round_state, state.level_state) + in + let new_state = + {state with round_state = new_round_state; level_state = new_level_state} + in + do_nothing new_state + +let handle_expected_applied_proposal (state : Baking_state.t) = + let new_level_state = + {state.level_state with is_latest_proposal_applied = true} + in + (* This code is triggered only when in the `Awaiting_application`phase, which + in turn is reached only if a quorum has been met but the + block has not been applied by the node. As a consequence, the only + thing that is left to do at this stage is to update the elected block + and transition to the Idle phase, as there is nothing left to do. *) + let new_state = {state with level_state = new_level_state} in + let new_state = + match new_state.level_state.elected_block with + | None -> + (* We do not have an elected block for this level. We need to update it. *) + let latest_proposal = state.level_state.latest_proposal in + let attestation_qc = + match state.round_state.delayed_quorum with + | None -> assert false + | Some attestation_qc -> attestation_qc + in + let elected_block = Some {proposal = latest_proposal; attestation_qc} in + let new_level_state = {state.level_state with elected_block} in + {state with level_state = new_level_state} + | Some _ -> + (* We already have an elected block at this level. We do not need to update + it. The earlier, the better. *) + new_state + in + let new_state = update_current_phase new_state Idle in + do_nothing new_state + +let handle_arriving_attestation state signed_attestation = + let open Lwt_syntax in + let { + vote_consensus_content = + { + level; + round = att_round; + block_payload_hash = att_payload_hash; + slot = _; + }; + delegate; + _; + } = + signed_attestation.unsigned_consensus_vote + in + let att_level = Raw_level.to_int32 level in + let attestation_matches_proposal = + let {payload_hash; round = block_round; shell; _} = + state.level_state.latest_proposal.block + in + Block_payload_hash.(att_payload_hash = payload_hash) + && Round.(att_round = block_round) + && Compare.Int32.(shell.level = att_level) + in + if not attestation_matches_proposal then + let* () = + Events.(emit discarding_attestation (delegate, att_level, att_round)) + in + do_nothing state + else + match state.round_state.current_phase with + | Awaiting_preattestations -> + (* An attestation is ready for injection but the prequorum has + not been reached yet: we save them until then. *) + let new_round_state = + { + state.round_state with + early_attestations = + signed_attestation :: state.round_state.early_attestations; + } + in + let new_state = {state with round_state = new_round_state} in + do_nothing new_state + | Idle | Awaiting_attestations | Awaiting_application -> + (* For these three phases, we have necessarily already reached the + prequorum: we are safe to inject. *) + let signed_attestations = + make_singleton_consensus_vote_batch signed_attestation + in + Lwt.return (state, Inject_attestations {signed_attestations}) + +let handle_forge_event state forge_event = + match forge_event with + | Block_ready prepared_block -> + Lwt.return + ( state, + Inject_block + {prepared_block; force_injection = false; asynchronous = true} ) + | Preattestation_ready signed_preattestation -> + Lwt.return (state, Inject_preattestation {signed_preattestation}) + | Attestation_ready signed_attestation -> + handle_arriving_attestation state signed_attestation + +(* Hypothesis: + - The state is not to be modified outside this module + (NB: there are exceptions in Baking_actions: the corner cases + [update_to_level] and [synchronize_round] and + the hack used by [inject_block]) + + - new_proposal's received blocks are expected to belong to our current + round + + - [Prequorum_reached] can only be received when we've seen a new head + + - [Quorum_reached] can only be received when we've seen a + [Prequorum_reached] *) +let step (state : Baking_state.t) (event : Baking_state.event) : + (Baking_state.t * Baking_actions.t) Lwt.t = + let open Lwt_syntax in + let phase = state.round_state.current_phase in + let* () = Events.(emit step_current_phase (phase, event)) in + match (phase, event) with + (* Handle timeouts *) + | _, Timeout (End_of_round {ending_round}) -> + (* If the round is ending, stop everything currently going on and + increment the round. *) + end_of_round state ending_round + | _, Timeout (Time_to_prepare_next_level_block {at_round}) -> + (* If it is time to bake the next level, stop everything currently + going on and propose the next level block *) + time_to_prepare_next_level_block state at_round + | Idle, New_head_proposal proposal -> + let* () = + Events.( + emit + new_head + ( proposal.block.hash, + proposal.block.shell.level, + proposal.block.round )) + in + handle_proposal ~is_proposal_applied:true state proposal + | Awaiting_application, New_head_proposal proposal -> + if + Block_hash.( + state.level_state.latest_proposal.block.hash <> proposal.block.hash) + then + let* () = + Events.( + emit + new_head + ( proposal.block.hash, + proposal.block.shell.level, + proposal.block.round )) + in + let* () = + Events.(emit unexpected_new_head_while_waiting_for_application ()) + in + handle_proposal ~is_proposal_applied:true state proposal + else + let* () = + Events.(emit applied_expected_proposal_received proposal.block.hash) + in + handle_expected_applied_proposal state + | Awaiting_attestations, New_head_proposal proposal + | Awaiting_preattestations, New_head_proposal proposal -> + let* () = + Events.( + emit + new_head + ( proposal.block.hash, + proposal.block.shell.level, + proposal.block.round )) + in + let* () = Events.(emit new_head_while_waiting_for_qc ()) in + handle_proposal ~is_proposal_applied:true state proposal + | Idle, New_valid_proposal proposal -> + let* () = + Events.( + emit + new_valid_proposal + ( proposal.block.hash, + proposal.block.shell.level, + proposal.block.round )) + in + handle_proposal ~is_proposal_applied:false state proposal + | _, New_forge_event (forge_event : forge_event) -> + let* () = Events.(emit new_forge_event forge_event) in + handle_forge_event state forge_event + | Awaiting_application, New_valid_proposal proposal + | Awaiting_attestations, New_valid_proposal proposal + | Awaiting_preattestations, New_valid_proposal proposal -> + let* () = + Events.( + emit + new_valid_proposal + ( proposal.block.hash, + proposal.block.shell.level, + proposal.block.round )) + in + if has_already_been_handled state proposal then + let* () = Events.(emit valid_proposal_received_after_application ()) in + do_nothing state + else + let* () = Events.(emit new_valid_proposal_while_waiting_for_qc ()) in + handle_proposal ~is_proposal_applied:false state proposal + | Awaiting_preattestations, Prequorum_reached (candidate, preattestation_qc) + -> + prequorum_reached_when_awaiting_preattestations + state + candidate + preattestation_qc + | Awaiting_attestations, Quorum_reached (candidate, attestation_qc) -> + quorum_reached_when_waiting_attestations state candidate attestation_qc + (* Unreachable cases *) + | Idle, (Prequorum_reached _ | Quorum_reached _) + | Awaiting_preattestations, Quorum_reached _ + | (Awaiting_application | Awaiting_attestations), Prequorum_reached _ + | Awaiting_application, Quorum_reached _ -> + (* This cannot/should not happen *) + do_nothing state diff --git a/src/proto_020_PsParisC/lib_delegate/state_transitions.mli b/src/proto_020_PsParisC/lib_delegate/state_transitions.mli new file mode 100644 index 000000000000..bb2cf360fd02 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/state_transitions.mli @@ -0,0 +1,90 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module, and in particular the {!step} function, modifies the automaton + state, while {!Baking_actions} performs potentially failing side-effects. *) + +open Protocol +open Alpha_context +open Baking_state +open Baking_actions + +val do_nothing : state -> (state * action) Lwt.t + +type proposal_acceptance = Invalid | Outdated_proposal | Valid_proposal + +val is_acceptable_proposal_for_current_level : + state -> proposal -> proposal_acceptance Lwt.t + +val make_consensus_vote_batch : + state -> proposal -> consensus_vote_kind -> unsigned_consensus_vote_batch + +val may_update_proposal : + is_proposal_applied:bool -> state -> proposal -> state Lwt.t + +val preattest : state -> proposal -> (state * action) Lwt.t + +val extract_pqc : + state -> proposal -> (Kind.preattestation operation list * Round.t) option + +val handle_proposal : + is_proposal_applied:bool -> state -> proposal -> (state * action) Lwt.t + +(** Propose a block at the start of the given round for the given delegate, + given that there was already a proposal at the current level, the last one + being [last_proposal]. *) +val propose_block_action : + state -> + consensus_key_and_delegate -> + Round.t -> + last_proposal:proposal -> + action Lwt.t + +(** Increase the current round and propose at the new round (same + level), if the baker has a proposer slot. *) +val end_of_round : state -> Round.t -> (state * action) Lwt.t + +(** Propose for the first time at a level at the given round. There was no + previous proposal at the current level. *) +val time_to_prepare_next_level_block : + state -> Round.t -> (state * action) Lwt.t + +val update_locked_round : state -> Round.t -> Block_payload_hash.t -> state + +val prepare_attest_action : state -> proposal -> action + +val prequorum_reached_when_awaiting_preattestations : + state -> + Operation_worker.candidate -> + Kind.preattestation operation list -> + (state * action) Lwt.t + +val quorum_reached_when_waiting_attestations : + state -> + Operation_worker.candidate -> + Kind.attestation operation list -> + (state * action) Lwt.t + +val step : state -> event -> (state * action) Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/test/README.md b/src/proto_020_PsParisC/lib_delegate/test/README.md new file mode 100644 index 000000000000..7fd4de1c2ee5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/README.md @@ -0,0 +1,127 @@ +# Testing Tenderbake via mockup-based simulations + +This test suite contains tests that check the baker. A notable feature that +distinguishes these tests from simple unit tests is that the baker is +examined as a whole with all its components working together. We do not run +a node, instead, we run a mockup node that allows us to create an illusion +for the baker that it talks to a real node. Thus, we have full control of +how the mockup node behaves, how the proposals and operations propagate, and +what the baker sees when it calls RPCs. + +Pros: + +* Integrates naturally with the existing testing setup and CI. No external + binaries or setup needed. +* Fast. The round time is currently constant and equal to 3 seconds. 2 + second was also tried, but that resulted in deviations from expected + behavior in about 10% of cases. Upon closer inspection it was found out + that round timeouts happen before a key event in the scenario. Supposedly, + this depends on the time the test is started as all other parameters are + set and deterministic. Switching 3 seconds solved the issue. +* Uses the same code as the baker, so people who are familiar with the + existing Tezos will benefit from their knowledge. +* Various assertions and checks can be expressed to ensure that the scenario + in question progresses exactly as it supposed to. +* Many details of how the baker sees the world can be tightly controlled. + +Cons: + +* Hard to see the logic of the scenario because it has to be written as a + collection of hooks. + +## Running the tests + +The tests can be run like this from the `src/proto_alpha/lib_delegate/test`: + +``` +$ dune exec ./main.exe -- -v +``` + +## Writing a test + +See the examples in `test_scenario.ml` for inspiration. Start writing a +scenario by deciding how many bakers you need and how many delegates each of +them will have (see the docs for `Mockup_simulator.run`): + +```ocaml + let open Mockup_simulator in + run [(3, (module Default_hooks)); (2, (module Default_hooks))] +``` + +* Set `debug` to `true` in `Mockup_simulator.default_config` and pass it to + `Mockup_simulator.run`. When `debug` is enabled baker logs will be printed. + This is the main instrument for observing what happens in the scenario. +* Consider setting `timeout` to an appropriate value. By default it is 10 + seconds, which should be fine for short scenarios, but may be insufficient + for longer ones. Timeout is a safety mechanism that prevents scenarios + from hanging and non-termination. +* It is also possible to control round durations, but it recommended to + use at least 3 seconds (the default). +* Finally, proposal slots can be controlled with the `delegate_selection` + field. The nested lists specify slot owners per level and + round. Note that if not provided, a seed nonce will be bruteforced + to obtain the desired delegate selection. + + +```ocaml + let open Mockup_simulator in + let config = + { + default_config with + debug = true; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap3); + (1l, bootstrap4); + (2l, bootstrap2); + (3l, bootstrap1); + ] ); + ( 2l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ]; + timeout = 15; + } + in + run ~config [(3, (module Default_hooks)); (2, (module Default_hooks))] +``` + +Note that delegate selection affects both (pre-)attesting and voting power. +Delegates that do not have proposer slots will not be able to (pre-)attest. +Voting power of delegates who have proposer slots will be proportional to +the number of slots they have. + +Next step is writing hook modules per baker that control its mockup mode and +execute assertions. In most cases there is no need to implement all hooks, +so the `Default_hooks` module can be reused, e.g.: + +```ocaml + let module Hooks : Mockup_simulator.Hooks = struct + include Mockup_simulator.Default_hooks + + let stop_on_event = function + | Baking_state.New_proposal {block; _} -> + (* Stop the node as soon as we receive a proposal with a level + higher than 5. *) + block.shell.level > 5l + | _ -> false + end in +``` + +Other hooks can be used to implement assertions using `failwith` and to set +mutable variable to track progress of a scenario. + +### Termination + +A scenario runs till all bakers terminate or till the scenario times out. A +baker can terminate successfully or unsuccessfully. Successful termination +happens when `stop_on_event` returns `true`. Unsuccessful termination occurs +when any of the hooks executes `failwith`. If at least one baker fails its +error message propagates and is displayed by the testing framework +(Alcotest). diff --git a/src/proto_020_PsParisC/lib_delegate/test/dune b/src/proto_020_PsParisC/lib_delegate/test/dune new file mode 100644 index 000000000000..699a5fa07970 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/dune @@ -0,0 +1,56 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_delegate_test_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-libs.test-helpers + octez-libs.micheline + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.protocol + octez-libs.base-test-helpers + octez-protocol-019-PtParisB-libs.bakings.mockup-simulator + octez-protocol-019-PtParisB-libs.baking + tezos-protocol-019-PtParisB.parameters + octez-libs.crypto + octez-libs.event-logging-test-helpers + uri) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_test_helpers + -open Tezos_micheline + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_base_test_helpers + -open Tezos_019_PtParisB_mockup_simulator + -open Tezos_baking_019_PtParisB + -open Tezos_event_logging_test_helpers) + (modules test_scenario)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_delegate_test_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package octez-protocol-019-PtParisB-libs) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/broadcast_services.ml b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/broadcast_services.ml new file mode 100644 index 000000000000..1a8c0a3ad8f3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/broadcast_services.ml @@ -0,0 +1,85 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module S = struct + open Data_encoding + + let path = Tezos_rpc.Path.(root / "broadcast") + + let dests_query = + let open Tezos_rpc.Query in + query (fun dests -> + object + method dests = dests + end) + |+ multi_field "dests" Tezos_rpc.Arg.int (fun t -> t#dests) + |> seal + + (* copied from lib_shell_services/injection_services.ml *) + let block_param = + obj2 + (req "block" (dynamic_size Block_header.encoding)) + (req + "operations" + (list (dynamic_size (list (dynamic_size Operation.encoding))))) + + let block = + Tezos_rpc.Service.post_service + ~description:"Broadcast a block." + ~query:dests_query + ~input:block_param + ~output:unit + Tezos_rpc.Path.(path / "block") + + let operation = + Tezos_rpc.Service.post_service + ~description:"Broadcast an operation." + ~query:dests_query + ~input:Alpha_context.Operation.encoding + ~output:unit + Tezos_rpc.Path.(path / "operation") +end + +open Tezos_rpc.Context + +let block ctxt ?(dests = []) raw operations = + make_call + S.block + ctxt + () + (object + method dests = dests + end) + (raw, operations) + +let operation ctxt ?(dests = []) operation = + make_call + S.operation + ctxt + () + (object + method dests = dests + end) + operation diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune new file mode 100644 index 000000000000..5a3b2c975dc2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune @@ -0,0 +1,33 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_019_PtParisB_mockup_simulator) + (public_name octez-protocol-019-PtParisB-libs.bakings.mockup-simulator) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-commands + octez-protocol-019-PtParisB-libs.baking + octez-libs.stdlib-unix + octez-shell-libs.client-base-unix + tezos-protocol-019-PtParisB.parameters + octez-shell-libs.mockup + octez-shell-libs.mockup-proxy + octez-shell-libs.mockup-commands + octez-protocol-019-PtParisB-libs.baking.tenderbrute + tezt.core) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB.Protocol + -open Tezos_client_019_PtParisB + -open Tezos_client_commands + -open Tezos_baking_019_PtParisB + -open Tezos_stdlib_unix + -open Tezos_client_base_unix + -open Tezos_protocol_019_PtParisB_parameters + -open Tenderbrute_019_PtParisB + -open Tezt_core)) diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_client_context.ml b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_client_context.ml new file mode 100644 index 000000000000..7a9741e31b4c --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_client_context.ml @@ -0,0 +1,177 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Tezos_client_base + +let logger = + let log _channel msg = Lwt_fmt.printf "%s@." msg in + new Client_context.simple_printer log + +class dummy_prompter : Client_context.prompter = + object + method prompt : type a. (a, string tzresult) Client_context.lwt_format -> a + = + fun _msg -> assert false + + method prompt_password : type a. + (a, Bytes.t tzresult) Client_context.lwt_format -> a = + fun _msg -> assert false + + method multiple_password_retries = false + end + +let log _channel msg = + print_endline msg ; + Lwt.return_unit + +class faked_ctxt (hooks : Faked_services.hooks) (chain_id : Chain_id.t) : + Tezos_rpc.Context.generic = + let local_ctxt = + let module Services = Faked_services.Make ((val hooks)) in + Tezos_mockup_proxy.RPC_client.local_ctxt (Services.directory chain_id) + in + object + method base = local_ctxt#base + + method generic_media_type_call meth ?body uri = + local_ctxt#generic_media_type_call meth ?body uri + + method call_service + : 'm 'p 'q 'i 'o. + (([< Resto.meth] as 'm), unit, 'p, 'q, 'i, 'o) Tezos_rpc.Service.t -> + 'p -> + 'q -> + 'i -> + 'o tzresult Lwt.t = + fun service params query body -> + local_ctxt#call_service service params query body + + method call_streamed_service + : 'm 'p 'q 'i 'o. + (([< Resto.meth] as 'm), unit, 'p, 'q, 'i, 'o) Tezos_rpc.Service.t -> + on_chunk:('o -> unit) -> + on_close:(unit -> unit) -> + 'p -> + 'q -> + 'i -> + (unit -> unit) tzresult Lwt.t = + fun service ~on_chunk ~on_close params query body -> + local_ctxt#call_streamed_service + service + ~on_chunk + ~on_close + params + query + body + end + +class faked_wallet ~base_dir ~filesystem : Client_context.wallet = + object (self) + method load_passwords = None + + method read_file fname = + let open Lwt_result_syntax in + match String.Hashtbl.find filesystem fname with + | None -> failwith "faked_wallet: cannot read file (%s)" fname + | Some (content, _mtime) -> return content + + method private filename alias_name = + Filename.concat + base_dir + (String.map (function ' ' -> '_' | c -> c) alias_name ^ "s") + + val lock_mutex = Lwt_mutex.create () + + method with_lock : type a. (unit -> a Lwt.t) -> a Lwt.t = + fun f -> Lwt_mutex.with_lock lock_mutex f + + method get_base_dir = base_dir + + method load : type a. + string -> default:a -> a Data_encoding.encoding -> a tzresult Lwt.t = + let open Lwt_result_syntax in + fun alias_name ~default encoding -> + let filename = self#filename alias_name in + if not (String.Hashtbl.mem filesystem filename) then return default + else + let* content = self#read_file filename in + let json = (Ezjsonm.from_string content :> Data_encoding.json) in + match Data_encoding.Json.destruct encoding json with + | exception e -> + failwith + "did not understand the %s alias file %s : %s" + alias_name + filename + (Printexc.to_string e) + | data -> return data + + method write : type a. + string -> a -> a Data_encoding.encoding -> unit tzresult Lwt.t = + let open Lwt_result_syntax in + fun alias_name list encoding -> + let filename = self#filename alias_name in + let json = Data_encoding.Json.construct encoding list in + let str = Ezjsonm.value_to_string (json :> Ezjsonm.value) in + String.Hashtbl.replace + filesystem + filename + (str, Some (Ptime.to_float_s (Ptime_clock.now ()))) ; + return_unit + + method last_modification_time : string -> float option tzresult Lwt.t = + let open Lwt_result_syntax in + fun alias_name -> + let filename = self#filename alias_name in + let file = String.Hashtbl.find_opt filesystem filename in + match file with + | None -> return_none + | Some (_content, mtime) -> return mtime + end + +class faked_io_wallet ~base_dir ~filesystem : Client_context.io_wallet = + object + inherit Client_context.simple_printer log + + inherit dummy_prompter + + inherit faked_wallet ~base_dir ~filesystem + end + +class unix_faked ~base_dir ~filesystem ~chain_id ~hooks : Client_context.full = + object + inherit faked_io_wallet ~base_dir ~filesystem + + inherit faked_ctxt hooks chain_id + + inherit Client_context_unix.unix_ui + + method chain = `Hash chain_id + + method block = `Head 0 + + method confirmations = None + + method verbose_rpc_error_diagnostics = false + end diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_daemon.ml b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_daemon.ml new file mode 100644 index 000000000000..86967abcaa36 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_daemon.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +module Baker = struct + let run ~(cctxt : #Protocol_client_context.full) ~stop_on_event ~chain_id + ~(context_index : Abstract_context_index.t) ~delegates = + let open Lwt_result_syntax in + let chain = `Hash chain_id in + let baking_configuration = + let open Baking_configuration in + { + default_config with + validation = ContextIndex context_index; + state_recorder = Memory; + } + in + (* By default errors are simply printed but the baker won't stop + because of them. This is not what we want for testing. Here we force + the baker to terminate unsuccessfully if an error occurs. *) + let canceler = Lwt_canceler.create () in + let on_error (err : error trace) = + let*! (_ : (unit, exn trace) result) = Lwt_canceler.cancel canceler in + Format.printf "%a" Error_monad.pp_print_trace err ; + Lwt_exit.exit_and_raise 1 + in + Baking_scheduling.run + cctxt + ~canceler + ~stop_on_event + ~on_error + ~chain + baking_configuration + delegates +end diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_services.ml b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_services.ml new file mode 100644 index 000000000000..95acc55de629 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/faked_services.ml @@ -0,0 +1,373 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Tezos_shell_services +module Directory = Tezos_rpc.Directory +module Chain_services = Tezos_shell_services.Chain_services +module Block_services = Tezos_shell_services.Block_services +module Block_services_alpha = Protocol_client_context.Alpha_block_services + +module type Mocked_services_hooks = sig + type mempool = Mockup.M.Block_services.Mempool.t + + (** The baker relies on this stream to be notified of new + valid blocks. *) + val monitor_validated_blocks : + unit -> + (Chain_id.t * Block_hash.t * Block_header.t * Operation.t list list) + Tezos_rpc.Answer.stream + + (** The baker relies on this stream to be notified of new + heads. *) + val monitor_heads : + unit -> (Block_hash.t * Block_header.t) Tezos_rpc.Answer.stream + + (** Returns current and next protocol for a block. *) + val protocols : + Block_services.block -> Block_services.protocols tzresult Lwt.t + + (** [raw_header] returns the byte encoded block header of the block + associated to the given block specification. *) + val raw_header : Block_services.block -> bytes tzresult Lwt.t + + (** [header] returns the block header of the block associated to the given + block specification. *) + val header : + Block_services.block -> Mockup.M.Block_services.block_header tzresult Lwt.t + + (** [resulting_context_hash] returns the context resulting hash of the given block. *) + val resulting_context_hash : + Block_services.block -> Context_hash.t tzresult Lwt.t + + (** [operations] returns all operations included in the block. *) + val operations : + Block_services.block -> + Mockup.M.Block_services.operation list list tzresult Lwt.t + + (** [inject_block_callback] is called when an RPC is performed on + [Tezos_shell_services.Injection_services.S.block], after checking that + the block header can be deserialized. *) + val inject_block : + Block_hash.t -> + Block_header.t -> + Operation.t trace trace -> + unit tzresult Lwt.t + + (** [inject_operation] is used by the baker (or the client) to inject + operations, including attestations. *) + val inject_operation : Operation.t -> Operation_hash.t tzresult Lwt.t + + (** [pending_operations] returns the current contents of the mempool. It + is used by the baker to fetch operations to potentially include in the + block being baked. These operations might include attestations. If + there aren't enough attestations, the baker waits on + [monitor_operations]. *) + val pending_operations : unit -> mempool Lwt.t + + (** Return a stream of list of operations. Used by the baker to wait on + attestations. Invariant: the stream becomes empty when the node changes + head. *) + val monitor_operations : + version:Block_services.version -> + validated:bool -> + branch_delayed:bool -> + branch_refused:bool -> + refused:bool -> + (Block_services.version + * ((Operation_hash.t * Mockup.M.Protocol.operation) * error trace option) + list) + Tezos_rpc.Answer.stream + + (** Lists block hashes from the chain, up to the last checkpoint, sorted + with decreasing fitness. Without arguments it returns the head of the + chain. Optional arguments allow to return the list of predecessors of a + given block or of a set of blocks. *) + val list_blocks : + heads:Block_hash.t list -> + length:int option -> + min_date:Time.Protocol.t option -> + Block_hash.t list list tzresult Lwt.t + + (** List the ancestors of the given block which, if referred to as + the branch in an operation header, are recent enough for that + operation to be included in the current block. *) + val live_blocks : Block_services.block -> Block_hash.Set.t tzresult Lwt.t + + (** [rpc_context_callback] is used in the implementations of several + RPCs (see local_services.ml). It should correspond to the + rpc_context constructed from the context at the requested block. *) + val rpc_context_callback : + Block_services.block -> + Tezos_protocol_environment.rpc_context tzresult Lwt.t + + (** Return raw protocol data as a block. *) + val raw_protocol_data : Block_services.block -> Bytes.t tzresult Lwt.t + + (** Broadcast block manually to nodes [dests] (given by their + number, starting from 0). If [dests] is not provided, broadcast + to all nodes. *) + val broadcast_block : + ?dests:int list -> + Block_hash.t -> + Block_header.t -> + Operation.t trace trace -> + unit tzresult Lwt.t + + (** Broadcast operation manually to nodes [dests] (given by their + number, starting from 0). If [dests] is not provided, broadcast + to all nodes. *) + val broadcast_operation : + ?dests:int list -> Alpha_context.packed_operation -> unit tzresult Lwt.t + + (** Simulate waiting for the node to be bootstrapped. Because the + simulated node is already bootstrapped, returns the current head + immediately. *) + val monitor_bootstrapped : + unit -> (Block_hash.t * Time.Protocol.t) Tezos_rpc.Answer.stream +end + +type hooks = (module Mocked_services_hooks) + +module Make (Hooks : Mocked_services_hooks) = struct + let monitor_validated_blocks = + Directory.gen_register0 + Directory.empty + Monitor_services.S.validated_blocks + (fun _next_protocol _ -> + Tezos_rpc.Answer.return_stream (Hooks.monitor_validated_blocks ())) + + let monitor_heads = + Directory.gen_register1 + Directory.empty + Monitor_services.S.heads + (fun _chain _next_protocol () -> + Tezos_rpc.Answer.return_stream (Hooks.monitor_heads ())) + + let monitor_bootstrapped = + Directory.gen_register0 + Directory.empty + Monitor_services.S.bootstrapped + (fun () () -> + Tezos_rpc.Answer.return_stream (Hooks.monitor_bootstrapped ())) + + let protocols = + let path = + let open Tezos_rpc.Path in + prefix Block_services.chain_path Block_services.path + in + let service = + Tezos_rpc.Service.prefix path Block_services.Empty.S.protocols + in + Directory.register Directory.empty service (fun (_, block) () () -> + Hooks.protocols block) + + let raw_header = + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Mockup.M.Block_services.S.raw_header + (fun (((), _chain), block) _ _ -> Hooks.raw_header block) + + let header = + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Mockup.M.Block_services.S.header + (fun (((), _chain), block) _ _ -> Hooks.header block) + + let resulting_context_hash = + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Mockup.M.Block_services.S.resulting_context_hash + (fun (((), _chain), block) _ _ -> Hooks.resulting_context_hash block) + + let operations = + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Mockup.M.Block_services.S.Operations.operations + (fun (((), _chain), block) q () -> + let open Lwt_result_syntax in + let* ops = Hooks.operations block in + return (q#version, ops)) + + let hash = + let open Lwt_result_syntax in + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Block_services.Empty.S.hash + (fun (((), _chain), block) () () -> + let* x = Hooks.header block in + return x.hash) + + let shell_header = + let open Lwt_result_syntax in + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Mockup.M.Block_services.S.Header.shell_header + (fun (((), _chain), block) _ _ -> + let* x = Hooks.header block in + return x.shell) + + let chain chain_id = + let open Lwt_result_syntax in + Directory.prefix + Chain_services.path + (Directory.register + Directory.empty + Chain_services.S.chain_id + (fun _chain () () -> return chain_id)) + + let inject_block = + let open Lwt_result_syntax in + Directory.register + Directory.empty + Injection_services.S.block + (fun () _chain (bytes, operations) -> + match Block_header.of_bytes bytes with + | None -> failwith "faked_services.inject_block: can't deserialize" + | Some block_header -> + let block_hash = Block_hash.hash_bytes [bytes] in + let* () = Hooks.inject_block block_hash block_header operations in + return block_hash) + + let inject_operation = + Directory.register + Directory.empty + Injection_services.S.operation + (fun () _chain bytes -> + match Data_encoding.Binary.of_bytes_opt Operation.encoding bytes with + | None -> failwith "faked_services.inject_operation: can't deserialize" + | Some operation -> Hooks.inject_operation operation) + + let broadcast_block = + Directory.register + Directory.empty + Broadcast_services.S.block + (fun () dests (block_header, operations) -> + let bytes = Block_header.to_bytes block_header in + let block_hash = Block_hash.hash_bytes [bytes] in + let dests = match dests#dests with [] -> None | dests -> Some dests in + Hooks.broadcast_block ?dests block_hash block_header operations) + + let broadcast_operation = + Directory.register + Directory.empty + Broadcast_services.S.operation + (fun () dests operation -> + let dests = match dests#dests with [] -> None | dests -> Some dests in + Hooks.broadcast_operation ?dests operation) + + let pending_operations = + let open Lwt_syntax in + Directory.gen_register + Directory.empty + (Mockup.M.Block_services.S.Mempool.pending_operations + @@ Block_services.mempool_path Block_services.chain_path) + (fun ((), _chain) params () -> + let* mempool = Hooks.pending_operations () in + Tezos_rpc.Answer.return (params#version, mempool)) + + let monitor_operations = + Directory.gen_register + Directory.empty + (Block_services_alpha.S.Mempool.monitor_operations + @@ Block_services.mempool_path Block_services.chain_path) + (fun ((), _chain) flags () -> + let stream = + Hooks.monitor_operations + ~version:flags#version + ~validated:flags#validated + ~branch_delayed:flags#branch_delayed + ~branch_refused:flags#branch_refused + ~refused:flags#refused + in + Tezos_rpc.Answer.return_stream stream) + + let list_blocks = + Directory.prefix + Chain_services.path + (Directory.register + Directory.empty + Chain_services.S.Blocks.list + (fun ((), _chain) flags () -> + Hooks.list_blocks + ~heads:flags#heads + ~length:flags#length + ~min_date:flags#min_date)) + + let live_blocks = + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Block_services.Empty.S.live_blocks + (fun (_, block) _ () -> Hooks.live_blocks block) + + let raw_protocol_data = + Directory.prefix + (Tezos_rpc.Path.prefix Chain_services.path Block_services.path) + @@ Directory.register + Directory.empty + Block_services.Empty.S.Header.raw_protocol_data + (fun (_, block) () () -> Hooks.raw_protocol_data block) + + let shell_directory chain_id = + List.fold_left + Directory.merge + Directory.empty + [ + monitor_validated_blocks; + monitor_heads; + protocols; + raw_header; + header; + operations; + hash; + shell_header; + resulting_context_hash; + chain chain_id; + inject_block; + inject_operation; + monitor_operations; + list_blocks; + live_blocks; + raw_protocol_data; + broadcast_block; + broadcast_operation; + monitor_bootstrapped; + ] + + let directory chain_id = + let open Lwt_syntax in + let proto_directory = + Directory.prefix + Chain_services.path + (Directory.prefix + Block_services.path + (Directory.map + (fun (((), _chain), block) -> + let* result = Hooks.rpc_context_callback block in + match result with + | Error _ -> assert false + | Ok rpc_context -> Lwt.return rpc_context) + Mockup.M.directory)) + in + let base = Directory.merge (shell_directory chain_id) proto_directory in + Tezos_rpc.Directory.register_describe_directory_service + base + Tezos_rpc.Service.description_service +end diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.ml b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.ml new file mode 100644 index 000000000000..6f14bb589d44 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.ml @@ -0,0 +1,1565 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type block = { + rpc_context : Tezos_protocol_environment.rpc_context; + protocol_data : Protocol.Alpha_context.Block_header.protocol_data; + raw_protocol_data : Bytes.t; + operations : Mockup.M.Block_services.operation list list; + resulting_context_hash : Context_hash.t; +} + +type chain = block list + +(** As new blocks and operations are received they are pushed to an Lwt_pipe + wrapped into this type. *) +type broadcast = + | Broadcast_block of Block_hash.t * Block_header.t * Operation.t list list + | Broadcast_op of Operation_hash.t * Alpha_context.packed_operation + +(** The state of a mockup node. *) +type state = { + instance_index : int; + (** Index of this node. Indices go from 0 to N-1 where N is the total + number of bakers in the simulation. *) + live_depth : int; + (** How many blocks (counting from the head into the past) are considered live? *) + mutable chain : chain; (** The chain as seen by this fake "node". *) + mutable mempool : (Operation_hash.t * Mockup.M.Protocol.operation) list; + (** Mempool of this fake "node". *) + chain_table : chain Block_hash.Table.t; + (** The chain table of this fake "node". It maps from block hashes to + blocks. *) + global_chain_table : block Block_hash.Table.t; + (** The global chain table that allows us to look up blocks that may be + missing in [chain_table], i.e. not known to this particular node. This + is used to find unknown predecessors. The real node can ask about an + unknown block and receive it on request, this is supposed to emulate + that functionality. *) + ctxt_table : Tezos_protocol_environment.rpc_context Context_hash.Table.t; + (** The context table allows us to look up rpc_context by its hash. *) + validated_blocks_pipe : + (Block_hash.t * Block_header.t * Operation.t list list) Lwt_pipe.Unbounded.t; + (** [validated_blocks_pipe] is used to implement the + [monitor_validated_blocks] RPC. *) + heads_pipe : (Block_hash.t * Block_header.t) Lwt_pipe.Unbounded.t; + (** [heads_pipe] is used to implement the [monitor_heads] + RPC. *) + mutable operations_stream : + (Operation_hash.t * Mockup.M.Protocol.operation) list Lwt_stream.t; + mutable operations_stream_push : + (Operation_hash.t * Mockup.M.Protocol.operation) list option -> unit; + (** [operations_pipe] is used to implement the [operations_pipe] RPC. *) + mutable streaming_operations : bool; + (** A helper flag used to implement the monitor operations RPC. *) + broadcast_pipes : broadcast Lwt_pipe.Unbounded.t list; + (** Broadcast pipes per node. *) + genesis_block_true_hash : Block_hash.t; + (** True hash of the genesis + block as calculated by the + [Block_header.hash] function. *) +} + +let accounts = Mockup.Protocol_parameters.default_value.bootstrap_accounts + +let chain_id = Chain_id.of_string_exn "main" + +let genesis_block_hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + +let genesis_predecessor_block_hash = Block_hash.zero + +type propagation = Block | Pass | Delay of float + +type propagation_vector = propagation list + +module type Hooks = sig + val on_inject_block : + level:int32 -> + round:int32 -> + block_hash:Block_hash.t -> + block_header:Block_header.t -> + operations:Operation.t list list -> + protocol_data:Alpha_context.Block_header.protocol_data -> + (Block_hash.t * Block_header.t * Operation.t list list * propagation_vector) + tzresult + Lwt.t + + val on_inject_operation : + op_hash:Operation_hash.t -> + op:Alpha_context.packed_operation -> + (Operation_hash.t * Alpha_context.packed_operation * propagation_vector) + tzresult + Lwt.t + + val on_new_validated_block : + block_hash:Block_hash.t -> + block_header:Block_header.t -> + operations:Operation.t list list -> + (Block_hash.t * Block_header.t * Operation.t list list) option Lwt.t + + val on_new_head : + block_hash:Block_hash.t -> + block_header:Block_header.t -> + (Block_hash.t * Block_header.t) option Lwt.t + + val on_new_operation : + Operation_hash.t * Alpha_context.packed_operation -> + (Operation_hash.t * Alpha_context.packed_operation) option Lwt.t + + val check_block_before_processing : + level:int32 -> + round:int32 -> + block_hash:Block_hash.t -> + block_header:Block_header.t -> + protocol_data:Alpha_context.Block_header.protocol_data -> + unit tzresult Lwt.t + + val check_chain_after_processing : + level:int32 -> round:int32 -> chain:chain -> unit tzresult Lwt.t + + val check_mempool_after_processing : + mempool:(Operation_hash.t * Mockup.M.Protocol.operation) list -> + unit tzresult Lwt.t + + val stop_on_event : Baking_state.event -> bool + + val on_start_baker : + baker_position:int -> + delegates:Baking_state.consensus_key list -> + cctxt:Protocol_client_context.full -> + unit Lwt.t + + val check_chain_on_success : chain:chain -> unit tzresult Lwt.t +end + +(** Return a series of blocks starting from the block with the given + identifier. *) +let locate_blocks (state : state) + (block : Tezos_shell_services.Block_services.block) : + block list tzresult Lwt.t = + let open Lwt_result_syntax in + match block with + | `Hash (hash, rel) -> ( + match Block_hash.Table.find state.chain_table hash with + | None -> + failwith "locate_blocks: can't find the block %a" Block_hash.pp hash + | Some chain0 -> + let _, chain = List.split_n rel chain0 in + return chain) + | `Head rel -> + let _, chain = List.split_n rel state.chain in + return chain + | `Level _ -> failwith "locate_blocks: `Level block spec not handled" + | `Genesis -> failwith "locate_blocks: `Genesis block spec net handled" + | `Alias _ -> failwith "locate_blocks: `Alias block spec not handled" + +(** Similar to [locate_blocks], but only returns the first block. *) +let locate_block (state : state) + (block : Tezos_shell_services.Block_services.block) : block tzresult Lwt.t = + let open Lwt_result_syntax in + let* blocks = locate_blocks state block in + match blocks with + | [] -> failwith "locate_block: can't find the block" + | x :: _ -> return x + +(** Return the collection of live blocks for a given block identifier. *) +let live_blocks (state : state) block = + let open Lwt_result_syntax in + let* chain = locate_blocks state block in + let segment, _ = List.split_n state.live_depth chain in + return + (List.fold_left + (fun set ({rpc_context; _} : block) -> + let hash = rpc_context.Tezos_protocol_environment.block_hash in + Block_hash.Set.add hash set) + (Block_hash.Set.of_list + [state.genesis_block_true_hash; genesis_predecessor_block_hash]) + segment) + +(** Extract the round number from raw fitness. *) +let round_from_raw_fitness raw_fitness = + let open Lwt_result_syntax in + match Protocol.Alpha_context.Fitness.from_raw raw_fitness with + | Ok fitness -> + return + (Alpha_context.Round.to_int32 + (Protocol.Alpha_context.Fitness.round fitness)) + | Error _ -> failwith "round_from_raw_fitness: cannot parse fitness" + +(** Extract level from a block header. *) +let get_block_level (block_header : Block_header.t) = + let open Lwt_result_syntax in + return block_header.shell.level + +(** Extract round from a block header. *) +let get_block_round (block_header : Block_header.t) = + round_from_raw_fitness block_header.shell.fitness + +(** Parse protocol data. *) +let parse_protocol_data (protocol_data : Bytes.t) = + let open Lwt_result_syntax in + match + Data_encoding.Binary.of_bytes_opt + Protocol.Alpha_context.Block_header.protocol_data_encoding + protocol_data + with + | None -> failwith "can't parse protocol data of a block" + | Some parsed_protocol_data -> return parsed_protocol_data + +(** Broadcast an operation or block according to the given propagation + vector. *) +let handle_propagation msg propagation_vector broadcast_pipes = + let open Lwt_result_syntax in + let*! () = + List.iter_s + (fun (propagation, pipe) -> + match propagation with + | Block -> Lwt.return_unit + | Pass -> + Lwt_pipe.Unbounded.push pipe msg ; + Lwt.return_unit + | Delay s -> + Lwt.dont_wait + (fun () -> + let*! () = Lwt_unix.sleep s in + Lwt_pipe.Unbounded.push pipe msg ; + Lwt.return_unit) + (fun _exn -> ()) ; + Lwt.return_unit) + (List.combine_drop propagation_vector broadcast_pipes) + in + return_unit + +(** Use the [user_hooks] to produce a module of functions that will perform + the heavy lifting for the RPC implementations. *) +let make_mocked_services_hooks (state : state) (user_hooks : (module Hooks)) : + Faked_services.hooks = + let open Lwt_result_syntax in + let module User_hooks = (val user_hooks : Hooks) in + let module Impl : Faked_services.Mocked_services_hooks = struct + type mempool = Mockup.M.Block_services.Mempool.t + + let monitor_validated_blocks () = + let next () = + let rec pop_until_ok () = + let*! block_hash, block_header, operations = + Lwt_pipe.Unbounded.pop state.validated_blocks_pipe + in + let*! result = + User_hooks.on_new_validated_block + ~block_hash + ~block_header + ~operations + in + match result with + | None -> pop_until_ok () + | Some (hash, head, operations) -> + Lwt.return_some (chain_id, hash, head, operations) + in + pop_until_ok () + in + let shutdown () = () in + Tezos_rpc.Answer.{next; shutdown} + + let monitor_heads () = + let next () = + let rec pop_until_ok () = + let*! block_hash, block_header = + Lwt_pipe.Unbounded.pop state.heads_pipe + in + (* Sleep a 0.1s to simulate a block application delay *) + let*! () = Lwt_unix.sleep 0.1 in + let*! head_opt = User_hooks.on_new_head ~block_hash ~block_header in + match head_opt with + | None -> pop_until_ok () + | Some head -> Lwt.return_some head + in + pop_until_ok () + in + let shutdown () = () in + Tezos_rpc.Answer.{next; shutdown} + + let monitor_bootstrapped () = + let first_run = ref true in + let next () = + if !first_run then ( + first_run := false ; + let b = match state.chain with [] -> assert false | b :: _ -> b in + let head_hash = b.rpc_context.block_hash in + let timestamp = b.rpc_context.block_header.timestamp in + Lwt.return_some (head_hash, timestamp)) + else Lwt.return_none + in + let shutdown () = () in + Tezos_rpc.Answer.{next; shutdown} + + let protocols (block : Tezos_shell_services.Block_services.block) = + let* x = locate_block state block in + let hash = x.rpc_context.block_hash in + let is_predecessor_of_genesis = + match block with + | `Hash (requested_hash, rel) -> + Int.equal rel 0 + && Block_hash.equal requested_hash genesis_predecessor_block_hash + | _ -> false + in + (* It is important to tell the baker that the genesis block is not in + the alpha protocol (we use Protocol_hash.zero). This will make the + baker not try to propose alternatives to that block and just accept + it as final in that Protocol_hash.zero protocol. The same for + predecessor of genesis, it should be in Protocol_hash.zero. *) + return + Tezos_shell_services.Block_services. + { + current_protocol = + (if + Block_hash.equal hash genesis_block_hash + || is_predecessor_of_genesis + then Protocol_hash.zero + else Protocol.hash); + next_protocol = + (if is_predecessor_of_genesis then Protocol_hash.zero + else Protocol.hash); + } + + let may_lie_on_proto_level block x = + (* As for ../protocols, the baker distinguishes activation + blocks from "normal" blocks by comparing the [proto_level] of + the shell header and its predecessor. If the predecessor's + one is different, it must mean that we are considering an + activation block and must not attest. Here, we do a bit of + hacking in order to return a different proto_level for the + predecessor of the genesis block which is considered as the + current protocol activation block. To perfectly mimic what is + supposed to happen, the first mocked up block created should + be made in the genesis protocol, however, it is not what's + done in the mockup mode. *) + let is_predecessor_of_genesis = + match block with + | `Hash (requested_hash, rel) -> + Int.equal rel 0 + && Block_hash.equal requested_hash genesis_predecessor_block_hash + | _ -> false + in + if is_predecessor_of_genesis then + { + x.rpc_context.block_header with + proto_level = pred x.rpc_context.block_header.proto_level; + } + else x.rpc_context.block_header + + let raw_header (block : Tezos_shell_services.Block_services.block) : + bytes tzresult Lwt.t = + let* x = locate_block state block in + let shell = may_lie_on_proto_level block x in + let protocol_data = + Data_encoding.Binary.to_bytes_exn + Protocol.block_header_data_encoding + x.protocol_data + in + return + (Data_encoding.Binary.to_bytes_exn + Tezos_base.Block_header.encoding + {shell; protocol_data}) + + let header (block : Tezos_shell_services.Block_services.block) : + Mockup.M.Block_services.block_header tzresult Lwt.t = + let* x = locate_block state block in + let shell = may_lie_on_proto_level block x in + return + { + Mockup.M.Block_services.hash = x.rpc_context.block_hash; + chain_id; + shell; + protocol_data = x.protocol_data; + } + + let resulting_context_hash + (block : Tezos_shell_services.Block_services.block) : + Context_hash.t tzresult Lwt.t = + let* x = locate_block state block in + return x.resulting_context_hash + + let operations block = + let* x = locate_block state block in + return x.operations + + let inject_block block_hash (block_header : Block_header.t) operations = + let* protocol_data = parse_protocol_data block_header.protocol_data in + let* level = get_block_level block_header in + let* round = get_block_round block_header in + let* block_hash1, block_header1, operations1, propagation_vector = + User_hooks.on_inject_block + ~level + ~round + ~block_hash + ~block_header + ~operations + ~protocol_data + in + handle_propagation + (Broadcast_block (block_hash1, block_header1, operations1)) + propagation_vector + state.broadcast_pipes + + let all_pipes_or_select = function + | None -> return state.broadcast_pipes + | Some l -> + List.map_es + (fun n -> + match List.nth_opt state.broadcast_pipes n with + | None -> + failwith + "Node number %d is out of range (max is %d)" + n + (List.length state.broadcast_pipes - 1) + | Some pipe -> return pipe) + l + + let broadcast_block ?dests block_hash (block_header : Block_header.t) + operations = + let* pipes = all_pipes_or_select dests in + let*! () = + List.iter_s + (fun pipe -> + Lwt_pipe.Unbounded.push + pipe + (Broadcast_block (block_hash, block_header, operations)) ; + Lwt.return_unit) + pipes + in + return_unit + + let inject_operation (Operation.{shell; proto} as op) = + let op_hash = Operation.hash op in + let proto_op_opt = + Data_encoding.Binary.of_bytes Protocol.operation_data_encoding proto + in + match proto_op_opt with + | Error _ -> failwith "inject_operation: cannot parse operation" + | Ok protocol_data -> + let op : Protocol.Alpha_context.packed_operation = + {shell; protocol_data} + in + let* op_hash1, op1, propagation_vector = + User_hooks.on_inject_operation ~op_hash ~op + in + let* () = + handle_propagation + (Broadcast_op (op_hash1, op1)) + propagation_vector + state.broadcast_pipes + in + return op_hash1 + + let broadcast_operation ?dests + (op : Protocol.Alpha_context.packed_operation) = + let* pipes = all_pipes_or_select dests in + let op_hash = Alpha_context.Operation.hash_packed op in + let*! () = + List.iter_s + (fun pipe -> + Lwt_pipe.Unbounded.push pipe (Broadcast_op (op_hash, op)) ; + Lwt.return_unit) + pipes + in + return_unit + + let pending_operations () = + let ops = state.mempool in + Lwt.return + Mockup.M.Block_services.Mempool. + { + validated = ops; + refused = Operation_hash.Map.empty; + outdated = Operation_hash.Map.empty; + branch_refused = Operation_hash.Map.empty; + branch_delayed = Operation_hash.Map.empty; + unprocessed = Operation_hash.Map.empty; + } + + let monitor_operations ~version ~validated ~branch_delayed ~branch_refused + ~refused = + ignore validated ; + ignore branch_delayed ; + ignore branch_refused ; + ignore refused ; + let streamed = ref false in + state.streaming_operations <- true ; + let next () = + let rec loop () = + let*! ops_opt = Lwt_stream.get state.operations_stream in + match ops_opt with + | None when !streamed -> Lwt.return_none + | None -> + streamed := true ; + Lwt.return_some (version, []) + | Some ops -> ( + let*! result = + List.filter_map_s User_hooks.on_new_operation ops + in + match result with + | [] -> loop () + | l -> Lwt.return_some (version, List.map (fun x -> (x, None)) l)) + in + loop () + in + let shutdown () = () in + Tezos_rpc.Answer.{next; shutdown} + + let rpc_context_callback block = + let* x = locate_block state block in + return x.rpc_context + + let list_blocks ~heads ~length ~min_date:_ = + let compare_block_fitnesses block0 block1 = + Fitness.compare + block0.rpc_context.block_header.fitness + block1.rpc_context.block_header.fitness + in + let hash_of_block block = block.rpc_context.block_hash in + let lookup_head head = + let* xs = locate_blocks state (`Hash (head, 0)) in + let segment = + match length with None -> xs | Some n -> List.take_n n xs + in + return + (List.map hash_of_block (List.sort compare_block_fitnesses segment)) + in + List.map_es lookup_head heads + + let live_blocks block = live_blocks state block + + let raw_protocol_data block = + let* x = locate_block state block in + return x.raw_protocol_data + end in + (module Impl) + +(** Return the current head. *) +let head {chain; _} = + let open Lwt_result_syntax in + match List.hd chain with + | None -> failwith "mockup_simulator.ml: empty chain" + | Some hd -> return hd + +(** Clear from the mempool operations whose branch does not point to + a live block with respect to the current head. *) +let clear_mempool state = + let open Lwt_result_syntax in + let* head = head state in + let included_ops_hashes = + List.map + (fun (op : Mockup.M.Block_services.operation) -> op.hash) + (List.flatten head.operations) + in + let* live_set = live_blocks state (`Head 0) in + let mempool = + List.filter + (fun (_oph, (op : Mockup.M.Protocol.operation)) -> + let included_in_head = + List.mem + ~equal:Operation_hash.equal + (Alpha_context.Operation.hash_packed op) + included_ops_hashes + in + Block_hash.Set.mem op.shell.branch live_set && not included_in_head) + state.mempool + in + state.mempool <- mempool ; + return_unit + +let begin_validation_and_application ctxt chain_id mode ~predecessor ~cache = + let open Lwt_result_syntax in + let* validation_state = + Mockup.M.Protocol.begin_validation ctxt chain_id mode ~predecessor ~cache + in + let* application_state = + Mockup.M.Protocol.begin_application ctxt chain_id mode ~predecessor ~cache + in + return (validation_state, application_state) + +let validate_and_apply_operation (validation_state, application_state) oph op = + let open Lwt_result_syntax in + let* validation_state = + Mockup.M.Protocol.validate_operation validation_state oph op + in + let* application_state, receipt = + Mockup.M.Protocol.apply_operation application_state oph op + in + return ((validation_state, application_state), receipt) + +let finalize_validation_and_application (validation_state, application_state) + shell_header = + let open Lwt_result_syntax in + let* () = Mockup.M.Protocol.finalize_validation validation_state in + Mockup.M.Protocol.finalize_application application_state shell_header + +(** Apply a block to the given [rpc_context]. *) +let reconstruct_context (rpc_context : Tezos_protocol_environment.rpc_context) + (operations : Operation.t list list) (block_header : Block_header.t) = + let open Lwt_result_syntax in + let predecessor = rpc_context.block_header in + let predecessor_context = rpc_context.context in + let* protocol_data = parse_protocol_data block_header.protocol_data in + let* state = + begin_validation_and_application + predecessor_context + chain_id + (Application {shell = block_header.shell; protocol_data}) + ~predecessor + ~cache:`Lazy + in + let i = ref 0 in + let* state, _ = + List.fold_left_es + (List.fold_left_es (fun (state, results) op -> + incr i ; + let oph = Operation.hash op in + let operation_data = + Data_encoding.Binary.of_bytes_exn + Mockup.M.Protocol.operation_data_encoding + op.Operation.proto + in + let op = + { + Mockup.M.Protocol.shell = op.shell; + protocol_data = operation_data; + } + in + let* state, receipt = validate_and_apply_operation state oph op in + return (state, receipt :: results))) + (state, []) + operations + in + finalize_validation_and_application state None + +(** Process an incoming block. If validation succeeds: + - update the current head to this new block + - cleanup outdated operations + - cleanup listener table + Note that this implementation does not handle concurrent branches. *) +let rec process_block state block_hash (block_header : Block_header.t) + operations = + let open Lwt_result_syntax in + let get_predecessor () = + let predecessor_hash = block_header.Block_header.shell.predecessor in + let* head = head state in + match Block_hash.Table.find state.chain_table predecessor_hash with + | None | Some [] -> ( + (* Even if the predecessor is not known locally, it might be known by + some node in the network. The code below "requests" information + about the block by its hash. *) + match + Block_hash.Table.find state.global_chain_table predecessor_hash + with + | None -> failwith "get_predecessor: unknown predecessor block" + | Some predecessor -> + let predecessor_block_header = + Block_header. + { + shell = predecessor.rpc_context.block_header; + protocol_data = predecessor.raw_protocol_data; + } + in + let predecessor_ops = + List.map + (fun xs -> + List.map + (fun (op : Mockup.M.Block_services.operation) -> + Operation. + { + shell = op.shell; + proto = + Data_encoding.Binary.to_bytes_exn + Protocol.operation_data_encoding + op.protocol_data; + }) + xs) + predecessor.operations + in + (* If the block is found, apply it before proceeding. *) + let* () = + process_block + state + predecessor.rpc_context.block_hash + predecessor_block_header + predecessor_ops + in + return predecessor) + | Some (predecessor :: _) -> + if + Int32.sub + head.rpc_context.block_header.level + predecessor.rpc_context.block_header.level + <= 2l + then return predecessor + else failwith "get_predecessor: the predecessor block is too old" + in + match Block_hash.Table.find state.chain_table block_hash with + | Some _ -> + (* The block is already known. *) + return_unit + | None -> + let* predecessor = get_predecessor () in + let* head = head state in + let* {context; message; _}, _ = + reconstruct_context predecessor.rpc_context operations block_header + in + let resulting_context_hash = + Tezos_context_ops.Context_ops.hash + ~time:block_header.shell.timestamp + ?message + context + in + let rpc_context = + Tezos_protocol_environment. + {context; block_hash; block_header = block_header.shell} + in + let operations = + List.map + (fun pass -> + List.map + (fun (Operation.{shell; proto} as op) -> + let hash : Operation_hash.t = Operation.hash op in + let protocol_data : Alpha_context.packed_protocol_data = + Data_encoding.Binary.of_bytes_exn + Protocol.operation_data_encoding + proto + in + { + Mockup.M.Block_services.chain_id; + hash; + shell; + protocol_data; + receipt = Empty; + }) + pass) + operations + in + let* protocol_data = parse_protocol_data block_header.protocol_data in + let new_block = + { + rpc_context; + protocol_data; + raw_protocol_data = block_header.protocol_data; + operations; + resulting_context_hash; + } + in + let predecessor_hash = block_header.Block_header.shell.predecessor in + let tail = + Block_hash.Table.find state.chain_table predecessor_hash + |> WithExceptions.Option.get ~loc:__LOC__ + in + let new_chain = new_block :: tail in + Block_hash.Table.replace state.chain_table block_hash new_chain ; + Block_hash.Table.replace state.global_chain_table block_hash new_block ; + Context_hash.Table.replace + state.ctxt_table + resulting_context_hash + rpc_context ; + if + Fitness.( + block_header.shell.fitness > head.rpc_context.block_header.fitness) + then ( + state.chain <- new_chain ; + let* () = clear_mempool state in + (* The head changed: notify that the stream ended. *) + state.operations_stream_push None ; + state.streaming_operations <- false ; + (* Instanciate a new stream *) + let operations_stream, operations_stream_push = Lwt_stream.create () in + state.operations_stream <- operations_stream ; + state.operations_stream_push <- operations_stream_push ; + state.operations_stream_push (Some state.mempool) ; + return_unit) + else return_unit + +(** This process listens to broadcast block and operations and incorporates + them in the context of the fake node. *) +let rec listener ~(user_hooks : (module Hooks)) ~state ~broadcast_pipe = + let open Lwt_result_syntax in + let module User_hooks = (val user_hooks : Hooks) in + let*! result = Lwt_pipe.Unbounded.pop broadcast_pipe in + match result with + | Broadcast_op (operation_hash, packed_operation) -> + let* () = + if + List.mem_assoc + ~equal:Operation_hash.equal + operation_hash + state.mempool + then return_unit + else ( + state.mempool <- (operation_hash, packed_operation) :: state.mempool ; + state.operations_stream_push + (Some [(operation_hash, packed_operation)]) ; + User_hooks.check_mempool_after_processing ~mempool:state.mempool) + in + listener ~user_hooks ~state ~broadcast_pipe + | Broadcast_block (block_hash, block_header, operations) -> + let* level = get_block_level block_header in + let* round = get_block_round block_header in + let* protocol_data = parse_protocol_data block_header.protocol_data in + let* () = + User_hooks.check_block_before_processing + ~level + ~round + ~block_hash + ~block_header + ~protocol_data + in + let* () = process_block state block_hash block_header operations in + let* () = + User_hooks.check_chain_after_processing ~level ~round ~chain:state.chain + in + Lwt_pipe.Unbounded.push + state.validated_blocks_pipe + (block_hash, block_header, operations) ; + Lwt_pipe.Unbounded.push state.heads_pipe (block_hash, block_header) ; + listener ~user_hooks ~state ~broadcast_pipe + +(** Create a fake node state. *) +let create_fake_node_state ~i ~live_depth + ~(genesis_block : Block_header.t * Tezos_protocol_environment.rpc_context) + ~global_chain_table ~broadcast_pipes = + let open Lwt_result_syntax in + let block_header0, rpc_context0 = genesis_block in + let* protocol_data = parse_protocol_data block_header0.protocol_data in + let genesis0 = + { + rpc_context = rpc_context0; + protocol_data; + raw_protocol_data = block_header0.protocol_data; + operations = [[]; []; []; []]; + resulting_context_hash = block_header0.shell.context; + } + in + let chain0 = [genesis0] in + let validated_blocks_pipe = Lwt_pipe.Unbounded.create () in + let heads_pipe = Lwt_pipe.Unbounded.create () in + let operations_stream, operations_stream_push = Lwt_stream.create () in + let genesis_block_true_hash = + Block_header.hash + { + shell = rpc_context0.block_header; + protocol_data = block_header0.protocol_data; + } + in + (* Only push genesis block as a new head, not a valid block: it is + the shell's semantics to not advertise "transition" blocks. *) + Lwt_pipe.Unbounded.push heads_pipe (rpc_context0.block_hash, block_header0) ; + return + { + instance_index = i; + live_depth; + mempool = []; + chain = chain0; + chain_table = + Block_hash.Table.of_seq + (List.to_seq + [ + (rpc_context0.block_hash, chain0); + (genesis_block_true_hash, chain0); + (genesis_predecessor_block_hash, chain0); + ]); + global_chain_table; + ctxt_table = + Context_hash.Table.of_seq + (List.to_seq + [ + ( rpc_context0.Tezos_protocol_environment.block_header + .Block_header.context, + rpc_context0 ); + ]); + validated_blocks_pipe; + heads_pipe; + operations_stream; + operations_stream_push; + streaming_operations = false; + broadcast_pipes; + genesis_block_true_hash; + } + +class tezt_printer : Tezos_client_base.Client_context.printer = + let open Tezos_client_base in + let open Client_context in + let wrap_tezt_log : (_ format4 -> _) -> _ format4 -> _ = + fun f x -> + Format.kasprintf + (fun msg -> + f "%s" msg ; + Lwt.return_unit) + x + in + object + method error : type a b. (a, b) lwt_format -> a = + Format.kasprintf (fun msg -> Lwt.fail (Failure msg)) + + method warning : type a. (a, unit) lwt_format -> a = + wrap_tezt_log Tezt_core.Log.warn + + method message : type a. (a, unit) lwt_format -> a = + wrap_tezt_log (fun x -> Tezt_core.Log.info x) + + method answer : type a. (a, unit) lwt_format -> a = + wrap_tezt_log (fun x -> Tezt_core.Log.info x) + + method log : type a. string -> (a, unit) lwt_format -> a = + fun _log_output -> wrap_tezt_log (fun x -> Tezt_core.Log.info x) + end + +(** Start baker process. *) +let baker_process ~(delegates : Baking_state.consensus_key list) ~base_dir + ~(genesis_block : Block_header.t * Tezos_protocol_environment.rpc_context) + ~i ~global_chain_table ~broadcast_pipes ~(user_hooks : (module Hooks)) = + let open Lwt_result_syntax in + let broadcast_pipe = + List.nth broadcast_pipes i |> WithExceptions.Option.get ~loc:__LOC__ + in + let* state = + create_fake_node_state + ~i + ~live_depth:60 + ~genesis_block + ~global_chain_table + ~broadcast_pipes + in + let filesystem = String.Hashtbl.create 10 in + let wallet = new Faked_client_context.faked_io_wallet ~base_dir ~filesystem in + let cctxt = + let hooks = make_mocked_services_hooks state user_hooks in + new Protocol_client_context.wrap_full + (new Faked_client_context.unix_faked + ~base_dir + ~filesystem + ~chain_id + ~hooks) + in + let module User_hooks = (val user_hooks : Hooks) in + let*! () = User_hooks.on_start_baker ~baker_position:i ~delegates ~cctxt in + let* () = + List.iter_es + (fun ({alias; public_key; public_key_hash; secret_key_uri} : + Baking_state.consensus_key) -> + let open Tezos_client_base in + let name = alias |> WithExceptions.Option.get ~loc:__LOC__ in + let* public_key_uri = Client_keys.neuterize secret_key_uri in + Client_keys.register_key + wallet + ~force:false + (public_key_hash, public_key_uri, secret_key_uri) + ~public_key + name) + delegates + in + let context_index = + let open Abstract_context_index in + { + sync_fun = Lwt.return; + checkout_fun = + (fun hash -> + Context_hash.Table.find state.ctxt_table hash + |> Option.map (fun Tezos_protocol_environment.{context; _} -> context) + |> Lwt.return); + finalize_fun = Lwt.return; + } + in + let module User_hooks = (val user_hooks : Hooks) in + let listener_process () = listener ~user_hooks ~state ~broadcast_pipe in + let stop_on_event event = User_hooks.stop_on_event event in + let baker_process () = + Faked_daemon.Baker.run + ~cctxt + ~stop_on_event + ~chain_id + ~context_index + ~delegates + in + let* () = Lwt.pick [listener_process (); baker_process ()] in + User_hooks.check_chain_on_success ~chain:state.chain + +let genesis_protocol_data (baker_sk : Signature.secret_key) + (predecessor_hash : Block_hash.t) (block_header : Block_header.shell_header) + : Bytes.t = + let proof_of_work_nonce = + Bytes.create Protocol.Alpha_context.Constants.proof_of_work_nonce_size + in + let payload_hash = + Protocol.Alpha_context.Block_payload.hash + ~predecessor_hash + ~payload_round:Alpha_context.Round.zero + [] + in + let per_block_votes = + { + Protocol.Per_block_votes_repr.liquidity_baking_vote = + Baking_configuration.default_votes_config + .Baking_configuration.liquidity_baking_vote; + adaptive_issuance_vote = + Baking_configuration.default_votes_config + .Baking_configuration.adaptive_issuance_vote; + } + in + let contents = + Protocol.Alpha_context.Block_header. + { + payload_hash; + payload_round = Alpha_context.Round.zero; + proof_of_work_nonce; + seed_nonce_hash = None; + per_block_votes; + } + in + let unsigned_header = + Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Block_header.unsigned_encoding + (block_header, contents) + in + let signature = + Signature.sign + ~watermark: + Alpha_context.Block_header.(to_watermark (Block_header chain_id)) + baker_sk + unsigned_header + in + Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Block_header.protocol_data_encoding + {contents; signature} + +(** Figure out who should be the signer for the genesis block. *) +let deduce_baker_sk + (accounts_with_secrets : + (Protocol.Alpha_context.Parameters.bootstrap_account + * Tezos_mockup_commands.Mockup_wallet.bootstrap_secret) + list) (total_accounts : int) (level : int) : + Signature.secret_key tzresult Lwt.t = + let open Lwt_result_syntax in + let* baker_index = + match (total_accounts, level) with + | _, 0 -> return 0 (* apparently this doesn't really matter *) + | _ -> + failwith + "cannot deduce baker for a genesis block, total accounts = %d, level \ + = %d" + total_accounts + level + in + let _, secret = + List.nth accounts_with_secrets baker_index + |> WithExceptions.Option.get ~loc:__LOC__ + in + let secret_key = + Signature.Secret_key.of_b58check_exn (Uri.path (secret.sk_uri :> Uri.t)) + in + return secret_key + +(** Generate the two initial genesis blocks. *) +let make_genesis_context ~delegate_selection ~initial_seed ~round0 ~round1 + ~consensus_committee_size ~consensus_threshold accounts_with_secrets + (total_accounts : int) = + let open Lwt_result_syntax in + let default_constants = Mockup.Protocol_parameters.default_value.constants in + let round_durations = + let open Alpha_context in + Stdlib.Option.get + (Round.Durations.create_opt + ~first_round_duration:(Period.of_seconds_exn round0) + ~delay_increment_per_round: + (Period.of_seconds_exn (Int64.sub round1 round0))) + in + let constants = + { + default_constants with + initial_seed; + consensus_committee_size; + consensus_threshold; + minimal_block_delay = Alpha_context.Period.of_seconds_exn (max 1L round0); + delay_increment_per_round = + Alpha_context.Period.of_seconds_exn Int64.(max 1L (sub round1 round0)); + } + in + let from_bootstrap_account i + ( (account : Protocol.Alpha_context.Parameters.bootstrap_account), + (secret : Tezos_mockup_commands.Mockup_wallet.bootstrap_secret) ) : + Mockup.Parsed_account.t = + { + name = Format.sprintf "bootstrap%d" (i + 1); + sk_uri = secret.sk_uri; + amount = account.amount; + } + in + let bootstrap_accounts = + Data_encoding.Json.construct + (Data_encoding.list Mockup.Parsed_account.encoding) + (List.mapi from_bootstrap_account accounts_with_secrets) + in + let*? delegate_selection = + let open Result_syntax in + List.map_e + (fun (level, round_delegates) -> + let* level = Raw_level_repr.of_int32 level in + let+ round_delegates = + List.map_e + (fun (round, delegate) -> + let+ round = Round_repr.of_int32 round in + (round, delegate)) + round_delegates + in + (level, round_delegates)) + delegate_selection + |> Environment.wrap_tzresult + in + let cctxt = new tezt_printer in + let* initial_seed = + match (delegate_selection, constants.initial_seed) with + | [], seed_opt -> return seed_opt + | selection, (Some _ as seed) -> ( + let*! () = cctxt#message "Checking provided seed." in + let* result = + Tenderbrute.check_seed + ~bootstrap_accounts_json:bootstrap_accounts + ~parameters: + Mockup.Protocol_parameters.{default_value with constants} + ~seed + selection + in + match result with + | true -> return seed + | false -> + failwith "Provided initial seed does not match delegate selection") + | _, None -> + let*! () = cctxt#message "No initial seed provided, bruteforcing." in + Tenderbrute.bruteforce + ~max:100_000_000_000 + ~bootstrap_accounts_json:bootstrap_accounts + ~parameters:Mockup.Protocol_parameters.{default_value with constants} + delegate_selection + in + let*! () = + match initial_seed with + | None -> Lwt.return_unit + | _ when initial_seed = constants.initial_seed -> Lwt.return_unit + | Some seed -> + cctxt#warning + "Bruteforced seed is %a, please save into your test." + State_hash.pp + seed + in + let constants = {constants with initial_seed} in + let common_parameters = + Mockup.Protocol_parameters.{default_value with constants} + in + let make_block0 initial_timestamp = + let parameters = {common_parameters with initial_timestamp} in + let reencoded_parameters = + Data_encoding.Binary.of_bytes_exn Mockup.M.parameters_encoding + @@ Data_encoding.Binary.to_bytes_exn + Mockup.Protocol_parameters.encoding + parameters + in + let* {chain = _; rpc_context = rpc_context0; protocol_data = _} = + Mockup.M.init + ~cctxt + ~parameters:reencoded_parameters + ~constants_overrides_json:None + ~bootstrap_accounts_json:(Some bootstrap_accounts) + in + let block_header0 = + { + rpc_context0.block_header with + predecessor = genesis_predecessor_block_hash; + } + in + let rpc_context = {rpc_context0 with block_header = block_header0} in + let* baker_sk = deduce_baker_sk accounts_with_secrets total_accounts 0 in + let protocol_data = + genesis_protocol_data + baker_sk + genesis_predecessor_block_hash + rpc_context.block_header + in + let block_header = + Block_header.{shell = rpc_context.block_header; protocol_data} + in + return (block_header, rpc_context) + in + let level0_round0_duration = + Protocol.Alpha_context.Round.round_duration + round_durations + Alpha_context.Round.zero + in + let timestamp0 = + Time.Protocol.of_seconds + Int64.( + sub + (of_float (Unix.time ())) + (Alpha_context.Period.to_seconds level0_round0_duration)) + in + make_block0 timestamp0 + +(** By default, propagate every message everywhere. *) +let default_propagation_vector = List.repeat 5 Pass + +module Default_hooks : Hooks = struct + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + let open Lwt_result_syntax in + return (block_hash, block_header, operations, default_propagation_vector) + + let on_inject_operation ~op_hash ~op = + let open Lwt_result_syntax in + return (op_hash, op, default_propagation_vector) + + let on_new_validated_block ~block_hash ~block_header ~operations = + Lwt.return_some (block_hash, block_header, operations) + + let on_new_head ~block_hash ~block_header = + Lwt.return_some (block_hash, block_header) + + let on_new_operation x = Lwt.return_some x + + let check_block_before_processing ~level:_ ~round:_ ~block_hash:_ + ~block_header:_ ~protocol_data:_ = + Lwt_result_syntax.return_unit + + let check_chain_after_processing ~level:_ ~round:_ ~chain:_ = + Lwt_result_syntax.return_unit + + let check_mempool_after_processing ~mempool:_ = Lwt_result_syntax.return_unit + + let stop_on_event _ = false + + let on_start_baker ~baker_position:_ ~delegates:_ ~cctxt:_ = Lwt.return_unit + + let check_chain_on_success ~chain:_ = Lwt_result_syntax.return_unit +end + +type config = { + round0 : int64; + round1 : int64; + timeout : int; + delegate_selection : (int32 * (int32 * Signature.public_key_hash) list) list; + initial_seed : State_hash.t option; + consensus_committee_size : int; + consensus_threshold : int; +} + +let default_config = + { + round0 = 2L; + (* Rounds should be long enough for the bakers to + exchange all the necessary messages. *) + round1 = 3L (* No real need to increase round durations. *); + timeout = 30; + delegate_selection = []; + initial_seed = None; + consensus_committee_size = + Default_parameters.constants_mainnet.consensus_committee_size; + consensus_threshold = + Default_parameters.constants_mainnet.consensus_threshold; + } + +let make_baking_delegate + ( (account : Alpha_context.Parameters.bootstrap_account), + (secret : Tezos_mockup_commands.Mockup_wallet.bootstrap_secret) ) : + Baking_state.consensus_key = + Baking_state. + { + alias = Some secret.name; + public_key = account.public_key |> WithExceptions.Option.get ~loc:__LOC__; + public_key_hash = account.public_key_hash; + secret_key_uri = secret.sk_uri; + } + +let run ?(config = default_config) bakers_spec = + let open Lwt_result_syntax in + Tezos_client_base.Client_keys.register_signer + (module Tezos_signer_backends.Unencrypted) ; + let total_accounts = + List.fold_left (fun acc (n, _) -> acc + n) 0 bakers_spec + in + if total_accounts = 0 then + failwith "the simulation should use at least one delegate" + else if total_accounts > 5 then + failwith "only up to 5 bootstrap accounts are available" + else + let total_bakers = List.length bakers_spec in + let* broadcast_pipes = + List.init ~when_negative_length:() total_bakers (fun _ -> + Lwt_pipe.Unbounded.create ()) + |> function + | Error () -> failwith "impossible: negative length of the baker spec" + | Ok xs -> return xs + in + let global_chain_table = Block_hash.Table.create 10 in + let* bootstrap_secrets = + Tezos_mockup_commands.Mockup_wallet.default_bootstrap_accounts + in + let accounts_with_secrets = + List.combine_drop (List.take_n total_accounts accounts) bootstrap_secrets + in + let all_delegates = List.map make_baking_delegate accounts_with_secrets in + let* genesis_block = + make_genesis_context + ~delegate_selection:config.delegate_selection + ~initial_seed:config.initial_seed + ~round0:config.round0 + ~round1:config.round1 + ~consensus_committee_size:config.consensus_committee_size + ~consensus_threshold:config.consensus_threshold + accounts_with_secrets + total_accounts + in + let take_third (_, _, x) = x in + let timeout_process () = + let*! () = Lwt_unix.sleep (Float.of_int config.timeout) in + failwith "the test is taking longer than %d seconds@." config.timeout + in + Lwt.pick + [ + timeout_process (); + Lwt_result_syntax.tzjoin + (take_third + (List.fold_left + (fun (i, delegates_acc, ms) (n, user_hooks) -> + let delegates, leftover_delegates = + List.split_n n delegates_acc + in + let m = + baker_process + ~delegates + ~base_dir:"dummy" + ~genesis_block + ~i + ~global_chain_table + ~broadcast_pipes + ~user_hooks + in + (i + 1, leftover_delegates, m :: ms)) + (0, all_delegates, []) + bakers_spec)); + ] + +let get_account_pk i = + match List.nth accounts i with + | None -> assert false + | Some acc -> acc.public_key |> WithExceptions.Option.get ~loc:__LOC__ + +let bootstrap1 = get_account_pk 0 + +let bootstrap2 = get_account_pk 1 + +let bootstrap3 = get_account_pk 2 + +let bootstrap4 = get_account_pk 3 + +let bootstrap5 = get_account_pk 4 + +let check_block_signature ~block_hash ~(block_header : Block_header.t) + ~public_key = + let open Lwt_result_syntax in + let (protocol_data : Protocol.Alpha_context.Block_header.protocol_data) = + Data_encoding.Binary.of_bytes_exn + Protocol.Alpha_context.Block_header.protocol_data_encoding + block_header.protocol_data + in + let unsigned_header = + Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Block_header.unsigned_encoding + (block_header.shell, protocol_data.contents) + in + if + Signature.check + ~watermark: + Alpha_context.Block_header.(to_watermark (Block_header chain_id)) + public_key + protocol_data.signature + unsigned_header + then return_unit + else + failwith + "unexpected signature for %a; tried with %a@." + Block_hash.pp + block_hash + Signature.Public_key.pp + public_key + +type op_predicate = + Operation_hash.t -> Alpha_context.packed_operation -> bool tzresult Lwt.t + +let mempool_count_ops ~mempool ~predicate = + let open Lwt_result_syntax in + let* results = + List.map_es (fun (op_hash, op) -> predicate op_hash op) mempool + in + return + (List.fold_left + (fun acc result -> if result then acc + 1 else acc) + 0 + results) + +let mempool_has_op ~mempool ~predicate = + let open Lwt_result_syntax in + let* n = mempool_count_ops ~mempool ~predicate in + return (n > 0) + +let mempool_has_op_ref ~mempool ~predicate ~var = + let open Lwt_result_syntax in + let* result = mempool_has_op ~mempool ~predicate in + if result then var := true ; + return_unit + +let op_is_signed_by ~public_key (op_hash : Operation_hash.t) + (op : Alpha_context.packed_operation) = + let open Lwt_result_syntax in + match op.protocol_data with + | Operation_data d -> ( + let* watermark = + match d.contents with + | Single op_contents -> + return + (match op_contents with + | Attestation _ -> + Alpha_context.Operation.to_watermark (Attestation chain_id) + | Preattestation _ -> + Alpha_context.Operation.to_watermark (Preattestation chain_id) + | _ -> Signature.Generic_operation) + | _ -> failwith "unexpected contents in %a@." Operation_hash.pp op_hash + in + match d.signature with + | None -> + failwith + "did not find a signature for op %a@." + Operation_hash.pp + op_hash + | Some signature -> + let unsigned_operation_bytes = + Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Operation.unsigned_encoding + (op.shell, Contents_list d.contents) + in + return + (Signature.check + ~watermark + public_key + signature + unsigned_operation_bytes)) + +let op_is_preattestation ?level ?round (op_hash : Operation_hash.t) + (op : Alpha_context.packed_operation) = + let open Lwt_result_syntax in + match op.protocol_data with + | Operation_data d -> ( + match d.contents with + | Single op_contents -> ( + match op_contents with + | Preattestation consensus_content -> + let right_level = + match level with + | None -> true + | Some expected_level -> + Int32.equal + (Alpha_context.Raw_level.to_int32 consensus_content.level) + expected_level + in + let right_round = + match round with + | None -> true + | Some expected_round -> + Int32.equal + (Alpha_context.Round.to_int32 consensus_content.round) + expected_round + in + return (right_level && right_round) + | _ -> return_false) + | _ -> failwith "unexpected contents in %a@." Operation_hash.pp op_hash) + +let op_is_attestation ?level ?round (op_hash : Operation_hash.t) + (op : Alpha_context.packed_operation) = + let open Lwt_result_syntax in + match op.protocol_data with + | Operation_data d -> ( + match d.contents with + | Single op_contents -> ( + match op_contents with + | Attestation {consensus_content; _} -> + let right_level = + match level with + | None -> true + | Some expected_level -> + Int32.equal + (Alpha_context.Raw_level.to_int32 consensus_content.level) + expected_level + in + let right_round = + match round with + | None -> true + | Some expected_round -> + Int32.equal + (Alpha_context.Round.to_int32 consensus_content.round) + expected_round + in + return (right_level && right_round) + | _ -> return_false) + | _ -> failwith "unexpected contents in %a@." Operation_hash.pp op_hash) + +let op_is_both f g op_hash op = + let open Lwt_result_syntax in + let* f_result = f op_hash op in + if f_result then g op_hash op else return_false + +let save_proposal_payload + ~(protocol_data : Alpha_context.Block_header.protocol_data) ~var = + let open Lwt_result_syntax in + var := + Some + (protocol_data.contents.payload_hash, protocol_data.contents.payload_round) ; + return_unit + +let verify_payload_hash + ~(protocol_data : Alpha_context.Block_header.protocol_data) + ~original_proposal ~message = + let open Lwt_result_syntax in + match !original_proposal with + | None -> + failwith + "verify_payload_hash: expected to have observed a proposal by now" + | Some (original_hash, original_round) -> + if + Protocol.Block_payload_hash.equal + original_hash + protocol_data.contents.payload_hash + && Protocol.Alpha_context.Round.equal + original_round + protocol_data.contents.payload_round + then return_unit + else failwith "verify_payload_hash: %s" message + +let get_block_round block = + round_from_raw_fitness block.rpc_context.block_header.fitness diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.mli b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.mli new file mode 100644 index 000000000000..e02ec3519701 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/mockup_simulator.mli @@ -0,0 +1,253 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Representation of a block in the simulator. *) +type block = { + rpc_context : Tezos_protocol_environment.rpc_context; + protocol_data : Protocol.Alpha_context.Block_header.protocol_data; + raw_protocol_data : Bytes.t; + operations : Mockup.M.Block_services.operation list list; + resulting_context_hash : Context_hash.t; +} + +(** Chain is a list of blocks. *) +type chain = block list + +(** How an operation or block should propagate through the network. *) +type propagation = + | Block (** Block the operation/block, it'll never be delivered. *) + | Pass (** Pass the operation/block as is. *) + | Delay of float + (** Delay the operation/block for the given number of seconds. *) + +(** Values of this type specify to which bakers a block or operation should + be delivered. *) +type propagation_vector = propagation list + +(** The way to control behavior of a mockup node. *) +module type Hooks = sig + (** This function is called on injection of a block by a particular baker. + It allows us to inspect, change, or discard the block. Calling the + injection RPC and actually updating the state of the mockup node are + two different operations. Normally the first entails the latter, but + not always. In particular, the [propagation_vector] controls what + bakers will see and incorporate the block. *) + val on_inject_block : + level:int32 -> + round:int32 -> + block_hash:Block_hash.t -> + block_header:Block_header.t -> + operations:Operation.t list list -> + protocol_data:Alpha_context.Block_header.protocol_data -> + (Block_hash.t * Block_header.t * Operation.t list list * propagation_vector) + tzresult + Lwt.t + + (** This function is called on injection of an operation. It is similar + to [on_inject_block], which see. *) + val on_inject_operation : + op_hash:Operation_hash.t -> + op:Alpha_context.packed_operation -> + (Operation_hash.t * Alpha_context.packed_operation * propagation_vector) + tzresult + Lwt.t + + (** This is called when a new validated block is going to be sent as + the response to a "monitor validated blocks" RPC call. Returning + [None] here terminates the process for the baker. *) + val on_new_validated_block : + block_hash:Block_hash.t -> + block_header:Block_header.t -> + operations:Operation.t list list -> + (Block_hash.t * Block_header.t * Operation.t list list) option Lwt.t + + (** This is called when a new head is going to be sent as the response to + a "monitor heads" RPC call. Returning [None] here terminates the + process for the baker. *) + val on_new_head : + block_hash:Block_hash.t -> + block_header:Block_header.t -> + (Block_hash.t * Block_header.t) option Lwt.t + + (** This is called when a new operation is going to be sent as the + response to a "monitor operations" RPC call. Returning [None] here + indicates that the node has advanced to the next level. *) + val on_new_operation : + Operation_hash.t * Alpha_context.packed_operation -> + (Operation_hash.t * Alpha_context.packed_operation) option Lwt.t + + (** Check a block before processing it in the mockup. *) + val check_block_before_processing : + level:int32 -> + round:int32 -> + block_hash:Block_hash.t -> + block_header:Block_header.t -> + protocol_data:Alpha_context.Block_header.protocol_data -> + unit tzresult Lwt.t + + (** Check the chain after processing a proposal. *) + val check_chain_after_processing : + level:int32 -> round:int32 -> chain:chain -> unit tzresult Lwt.t + + (** Check operations in the mempool after injecting an operation. *) + val check_mempool_after_processing : + mempool:(Operation_hash.t * Mockup.M.Protocol.operation) list -> + unit tzresult Lwt.t + + (** This hook is used to decide when the baker is supposed to shut down. + It is triggered by receiving an event. *) + val stop_on_event : Baking_state.event -> bool + + (** This hook is used to gather information on the baker when it is + started (usually recording for later use). The first argument + [baker_position], is the position of the baker in the list of + bakers that were started for this run. *) + val on_start_baker : + baker_position:int -> + delegates:Baking_state.consensus_key list -> + cctxt:Protocol_client_context.full -> + unit Lwt.t + + (** Check to run on the chain upon successful termination. *) + val check_chain_on_success : chain:chain -> unit tzresult Lwt.t +end + +(** The default hook implementation. *) +module Default_hooks : Hooks + +(** Simulation configuration. *) +type config = { + round0 : int64; (** Duration of the round 0 in seconds. *) + round1 : int64; (** Duration of the round 1 in seconds. *) + timeout : int; + (** Maximal duration of the test. If the test takes + longer to terminate it'll be aborted with an + error. *) + delegate_selection : (int32 * (int32 * Signature.public_key_hash) list) list; + (** Desired selection of delegates per level/round *) + initial_seed : State_hash.t option; + (** Optional initial seed for protocol (used to control delegate selection) *) + consensus_committee_size : int; + (** Size of the committee for tenderbake in number of slots *) + consensus_threshold : int; + (** Threshold, in number of slots, for the quorum to be considered + reached. Should be [2 * consensus_committee_size / 3 + 1] in + usual setting for tenderbake. *) +} + +(** Default configuration. *) +val default_config : config + +(** [run spec] runs a simulation according to the [spec]. Elements of [spec] + describe bakers: how many delegate each baker has and how it behaves. The + total number of delegates cannot exceed 5 for now (it is easy to increase + this limit). The delegates are assigned in order, gradually exhausting + the standard bootstrap accounts. For example, if the first baker has 3 + delegates and the second one has 2 delegates, we have the following + distribution of bootstrap accounts: + + Baker no. 1: bootstrap1, bootstrap2, bootstrap3 + + Baker no. 2: bootstrap4, bootstrap5 + + A simulation continues till all nodes finish either with an error or + successfully. If at least one node finishes with an error, it propagates + to the final result. *) +val run : ?config:config -> (int * (module Hooks)) list -> unit tzresult Lwt.t + +val bootstrap1 : Signature.public_key + +val bootstrap2 : Signature.public_key + +val bootstrap3 : Signature.public_key + +val bootstrap4 : Signature.public_key + +val bootstrap5 : Signature.public_key + +(** Check if a block header is signed by a given delegate. *) +val check_block_signature : + block_hash:Block_hash.t -> + block_header:Block_header.t -> + public_key:Signature.public_key -> + unit tzresult Lwt.t + +(** A shortcut type for predicates on operations. *) +type op_predicate = + Operation_hash.t -> Alpha_context.packed_operation -> bool tzresult Lwt.t + +(** Count the number of operations in the mempool that satisfy the given + predicate. *) +val mempool_count_ops : + mempool:(Operation_hash.t * Mockup.M.Protocol.operation) list -> + predicate:op_predicate -> + int tzresult Lwt.t + +(** Check if the mempool has at least one operation that satisfies the given + predicate. *) +val mempool_has_op : + mempool:(Operation_hash.t * Mockup.M.Protocol.operation) list -> + predicate:op_predicate -> + bool tzresult Lwt.t + +(** Similar to [mempool_has_op] but instead of returning a [bool] it sets + the given [bool ref]. *) +val mempool_has_op_ref : + mempool:(Operation_hash.t * Mockup.M.Protocol.operation) list -> + predicate:op_predicate -> + var:bool ref -> + unit tzresult Lwt.t + +(** Check if an operation is signed by the given delegate. *) +val op_is_signed_by : public_key:Signature.public_key -> op_predicate + +(** Check that an operation is a preattestation. *) +val op_is_preattestation : ?level:int32 -> ?round:int32 -> op_predicate + +(** Check that an operation is an attestation. *) +val op_is_attestation : ?level:int32 -> ?round:int32 -> op_predicate + +(** Combine two predicates. *) +val op_is_both : op_predicate -> op_predicate -> op_predicate + +(** Set the given variable to save payload hash and payload round. *) +val save_proposal_payload : + protocol_data:Alpha_context.Block_header.protocol_data -> + var:(Block_payload_hash.t * Alpha_context.Round.t) option ref -> + unit tzresult Lwt.t + +(** Check that payload hashes match, fail if it is not the case. *) +val verify_payload_hash : + protocol_data:Alpha_context.Block_header.protocol_data -> + original_proposal:(Block_payload_hash.t * Alpha_context.Round.t) option ref -> + message:string -> + unit tzresult Lwt.t + +(** Parse protocol data. *) +val parse_protocol_data : + Bytes.t -> Alpha_context.Block_header.protocol_data tzresult Lwt.t + +(** Get round of a block. *) +val get_block_round : block -> int32 tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune new file mode 100644 index 000000000000..e9661434fc68 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune @@ -0,0 +1,23 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executable + (name tenderbrute_main) + (libraries + octez-libs.base + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.baking.tenderbrute) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp) + (-linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_base + -open Tezos_client_base + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tenderbrute_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune new file mode 100644 index 000000000000..945584a1c651 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune @@ -0,0 +1,21 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tenderbrute_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.baking.tenderbrute) + (libraries + data-encoding + octez-libs.base + octez-libs.base.unix + tezos-protocol-019-PtParisB.protocol + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.client) + (flags + (:standard) + -open Data_encoding + -open Tezos_base.TzPervasives + -open Tezos_base + -open Tezos_protocol_019_PtParisB + -open Tezos_client_base + -open Tezos_client_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.ml b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.ml new file mode 100644 index 000000000000..3feb1ddcf025 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.ml @@ -0,0 +1,229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +type delegate_selection = + (Raw_level_repr.t * (Round_repr.t * Signature.public_key_hash) list) list + +module LevelRoundMap = Map.Make (struct + type t = Level_repr.t * Round_repr.t + + let compare (l1, r1) (l2, r2) = + Stdlib.compare + (Raw_level_repr.to_int32 l1.Level_repr.level, Round_repr.to_int32 r1) + (Raw_level_repr.to_int32 l2.Level_repr.level, Round_repr.to_int32 r2) +end) + +let _ = Client_keys.register_signer (module Tezos_signer_backends.Unencrypted) + +(* Initialize a context in memory with the Mockup *) +let init_context ?constants_overrides_json ?bootstrap_accounts_json parameters = + let open Lwt_result_syntax in + let parameters = + Data_encoding.Binary.of_bytes_exn Mockup.M.parameters_encoding + @@ Data_encoding.Binary.to_bytes_exn + Mockup.Protocol_parameters.encoding + parameters + in + let* mockup_init = + Mockup.M.init + ~cctxt:Client_context.null_printer + ~parameters + ~constants_overrides_json + ~bootstrap_accounts_json + in + let ctxt = mockup_init.rpc_context.context in + let timestamp = Time.Protocol.of_seconds 0L in + (* The timestamp is irrelevant for the rights *) + let*! result = + Raw_context.prepare + ctxt + ~level:1l + ~predecessor_timestamp:timestamp + ~timestamp + ~adaptive_issuance_enable:false + in + Lwt.return @@ Environment.wrap_tzresult result + +(* Change the initial seed for the first preserved cycles. This suppose that the + seeds for these cycles are already set, which is the case because this + function is always called after {!init_context}. *) +let change_seed ?initial_seed ctxt = + let open Lwt_result_syntax in + let delay = Constants_storage.consensus_rights_delay ctxt in + let+ (_ : int), ctxt = + List.fold_left_es + (fun (c, ctxt) seed -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in + let* ctxt = Storage.Seed.For_cycle.remove_existing ctxt cycle in + let+ ctxt = Storage.Seed.For_cycle.init ctxt cycle seed in + (c + 1, ctxt)) + (0, ctxt) + (Seed_repr.initial_seeds ?initial_seed (delay + 2)) + in + ctxt + +let init ?constants_overrides_json ?bootstrap_accounts_json parameters = + let open Lwt_result_syntax in + let* ctxt = + init_context ?constants_overrides_json ?bootstrap_accounts_json parameters + in + let blocks_per_cycle = Constants_storage.blocks_per_cycle ctxt in + let blocks_per_commitment = Constants_storage.blocks_per_commitment ctxt in + let cycle_eras = + [ + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn 0l; + first_cycle = Cycle_repr.root; + blocks_per_cycle; + blocks_per_commitment; + }; + ] + in + let*? cycle_eras = + Level_repr.create_cycle_eras cycle_eras |> Environment.wrap_tzresult + in + return (ctxt, cycle_eras) + +(* Check if the given selection correponds to the baking rights assigned by the + protocol (with the initial seeds registered in the context). Returns [true] + when the selection is the one of the protocol or [false] otherwise. *) +let check ctxt ~selection = + let open Lwt_result_syntax in + Lwt.catch + (fun () -> + let* _ctxt = + LevelRoundMap.fold_es + (fun (level, round) delegate ctxt -> + let* ctxt, _, pk = + let*! result = + Delegate_sampler.baking_rights_owner ctxt level ~round + in + Lwt.return @@ Environment.wrap_tzresult result + in + if not (Signature.Public_key_hash.equal delegate pk.delegate) then + raise Exit + else return ctxt) + selection + ctxt + in + return_true) + (function Exit -> return_false | e -> Lwt.reraise e) + +(* Create random 32 bytes *) +let rnd_bytes32 () = + let b1 = Random.int64 Int64.max_int in + let b2 = Random.int64 Int64.max_int in + let b3 = Random.int64 Int64.max_int in + let b4 = Random.int64 Int64.max_int in + let b = Bytes.make 32 '\000' in + TzEndian.set_int64 b 0 b1 ; + TzEndian.set_int64 b 8 b2 ; + TzEndian.set_int64 b 16 b3 ; + TzEndian.set_int64 b 24 b4 ; + b + +let mk_selection_map cycle_eras selection = + List.fold_left + (fun acc (level, round_delegates) -> + let level = Level_repr.level_from_raw ~cycle_eras level in + List.fold_left + (fun acc (round, delegate) -> + if LevelRoundMap.mem (level, round) acc then + Stdlib.failwith "Duplicate level/round" ; + LevelRoundMap.add (level, round) delegate acc) + acc + round_delegates) + LevelRoundMap.empty + selection + +(* Bruteforce an initial seed nonce for the desired delegate selection *) +let bruteforce ?(show_progress = false) ?(random_seed = 0) ?max + ?(parameters = Mockup.Protocol_parameters.default_value) + ?constants_overrides_json ?bootstrap_accounts_json selection = + let open Lwt_result_syntax in + Random.init random_seed ; + let* ctxt, cycle_eras = + init ?constants_overrides_json ?bootstrap_accounts_json parameters + in + let selection = mk_selection_map cycle_eras selection in + let last_nb_chars = ref 0 in + let frames = + [| + "( ● )"; + "( ● )"; + "( ● )"; + "( ● )"; + "( ●)"; + "( ● )"; + "( ● )"; + "( ● )"; + "( ● )"; + "(● )"; + |] + in + let nframes = Array.length frames in + let frame n = frames.(n mod nframes) in + let rec loop n = + if show_progress && n <> 0 && n mod 10_000 = 0 then ( + Format.eprintf "%s" (String.make !last_nb_chars '\b') ; + let s = frame (n / 10_000) ^ " " ^ string_of_int n in + last_nb_chars := String.length s ; + Format.eprintf "%s%!" s) ; + match max with + | Some max when n > max -> failwith "Did not find seed nonce" + | _ -> ( + let initial_seed = + if n = 0 then None + else Some (State_hash.of_bytes_exn (rnd_bytes32 ())) + in + let* ctxt = + let*! result = change_seed ?initial_seed ctxt in + Lwt.return @@ Environment.wrap_tzresult result + in + let* result = check ctxt ~selection in + match result with + | true -> + Format.eprintf "%s%!" (String.make !last_nb_chars '\b') ; + return initial_seed + | false -> loop (n + 1)) + in + loop 0 + +(* Check that an initial seed corresonds to the desired delegate selection *) +let check_seed ?(parameters = Mockup.Protocol_parameters.default_value) + ?constants_overrides_json ?bootstrap_accounts_json ~seed selection = + let open Lwt_result_syntax in + let* ctxt, cycle_eras = + init ?constants_overrides_json ?bootstrap_accounts_json parameters + in + let selection = mk_selection_map cycle_eras selection in + let* ctxt = + let*! result = change_seed ?initial_seed:seed ctxt in + Lwt.return @@ Environment.wrap_tzresult result + in + check ctxt ~selection diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.mli b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.mli new file mode 100644 index 000000000000..7b6915d2cfd2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/tenderbrute.mli @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** The type of desired delegate selection. For each level, and each round, + one can provide a public key hash that would be the proposer. All non- + specified level and rounds are not constrained. *) +type delegate_selection = + (Raw_level_repr.t * (Round_repr.t * Signature.public_key_hash) list) list + +(** Brute-force an initial seed nonce for the desired delegate selection. + When found, the seed nonce is returned as a byte sequence of size 32. If + no nonce is necessary to obtain the desired selection, [None] is returned + (there won't be any brute-forcing then). + + {b Note}: When using this function in your tests, take care of saving the + nonce once it is found locallty (in this case call {!check_seed_nonce} to + ensure it yields the desired selection) to avoid unnecessary computation + (in particular this function should not be called in the CI). + + @param show_progress if [true], display a spinner and the number of iterations + on the output (stderr) while [brutefore] is running. + @param random_seed initialize OCaml's random number generator with this seed + (by default [0]). This is useful to spawn multiple bruteforce in + parallel or on multiple machines. + @param constants_overrides_json JSON representation of some constants that are + to be overwritten for the in-memory context. The most useful change is to + set the size of cycles (which directly impacts the attribution of rights) or + the committee size with {i e.g.} + {[ { "blocks_per_cycle" : 8, "consensus_committee_size" : 25 } ]} + @param bootstrap_accounts_json JSON representation of bootstrap accounts of + the form: + {[ + [ { "name" : "bootstrap1" + "sk_uri": "unencrypted:edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh", + "amount": "3000000000000" }, + ...] + ]} + @param parameters parameters of the protocol (optional). + @param selection is the desired delegate selection. See {!delegate_selection}. + *) +val bruteforce : + ?show_progress:bool -> + ?random_seed:int -> + ?max:int -> + ?parameters:Mockup.Protocol_parameters.t -> + ?constants_overrides_json:json -> + ?bootstrap_accounts_json:json -> + delegate_selection -> + State_hash.t option tzresult Lwt.t + +(** Check that an initial seed nonce yields to the desired delegate selection. + See {!bruteforce} for the arguments. *) +val check_seed : + ?parameters:Mockup.Protocol_parameters.t -> + ?constants_overrides_json:json -> + ?bootstrap_accounts_json:json -> + seed:State_hash.t option -> + delegate_selection -> + bool tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/tenderbrute_main.ml b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/tenderbrute_main.ml new file mode 100644 index 000000000000..8d44cecef2c9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/tenderbrute_main.ml @@ -0,0 +1,187 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let bootstrap_accounts = ref None + +let constants_overrides = ref None + +let selection = ref [] + +let max = ref None + +let random_seed = ref None + +let report_err res = + match res with + | Error e -> + Format.eprintf "\n%a@." Error_monad.pp_print_trace e ; + exit 2 + | Ok res -> res + +let delegate_encoding = + let open Data_encoding in + union + [ + case + ~title:"Public key hash" + (Tag 0) + Signature.Public_key_hash.encoding + (function `Pkh p -> Some p | _ -> None) + (fun p -> `Pkh p); + case + ~title:"Alias" + (Tag 1) + string + (function `Alias a -> Some a | _ -> None) + (fun a -> `Alias a); + ] + +let selection_encoding = + let open Data_encoding in + list + (tup2 + Raw_level_repr.encoding + (list (tup2 Round_repr.encoding delegate_encoding))) + +let mk_bootstrap_aliases bootstrap_accounts_json = + let open Lwt_result_syntax in + let parameters = Mockup.Protocol_parameters.default_value in + let open Alpha_context.Parameters in + match bootstrap_accounts_json with + | None -> + List.mapi + (fun i a -> (Format.sprintf "bootstrap%d" i, a.public_key_hash)) + parameters.bootstrap_accounts + |> return + | Some j -> + let open Data_encoding in + let accounts = Json.destruct (list Mockup.Parsed_account.encoding) j in + List.map_ep + (fun a -> + let+ acc = Mockup.Parsed_account.to_bootstrap_account a in + (a.name, acc.public_key_hash)) + accounts + +let selection_to_pkhs bootstrap_accounts_json selection = + let open Lwt_result_syntax in + let+ bootstrap_aliases = mk_bootstrap_aliases bootstrap_accounts_json in + List.map + (fun (level, l) -> + ( level, + List.map + (fun (round, d) -> + ( round, + match d with + | `Pkh d -> d + | `Alias a -> ( + match List.assoc ~equal:String.equal a bootstrap_aliases with + | None -> Stdlib.failwith @@ "Unknown alias " ^ a + | Some d -> d) )) + l )) + selection + +let parse_json_or_file s = + let open Lwt_syntax in + let+ json_opt = Tezos_stdlib_unix.Lwt_utils_unix.Json.read_file s in + match json_opt with + | Ok json -> Ok json + | Error errs -> ( + match Data_encoding.Json.from_string s with + | Ok json -> Ok json + | Error e -> Error (Exn (Failure e) :: errs)) + +let set_selection s = + let open Lwt_syntax in + Lwt_main.run + (let+ json = + let+ json = parse_json_or_file s in + report_err json + in + selection := Data_encoding.Json.destruct selection_encoding json) + +let main () = + let open Lwt_result_syntax in + let thread = + let* bootstrap_accounts_json = + match !bootstrap_accounts with + | None -> return_none + | Some read -> + let+ json = read in + Option.some json + in + let* constants_overrides_json = + match !constants_overrides with + | None -> return_none + | Some read -> + let+ json = read in + Option.some json + in + let* selection = selection_to_pkhs bootstrap_accounts_json !selection in + Tenderbrute.bruteforce + ~show_progress:true + ?max:!max + ?random_seed:!random_seed + ?bootstrap_accounts_json + ?constants_overrides_json + selection + in + Lwt_main.run + (let*! seed = + let*! result = thread in + Lwt.return @@ report_err result + in + let seed_str = + match seed with None -> "None" | Some s -> State_hash.to_b58check s + in + Lwt.return @@ Format.printf "%s@." seed_str) + +let specs = + [ + ( "--max", + Arg.Int (fun m -> max := Some m), + " set maximum number of tries to " ); + ( "--random-seed", + Arg.Int (fun i -> random_seed := Some i), + " initialize the random generator with (useful to spawn mutliple \ + instances)" ); + ( "--constants-overrides", + Arg.String (fun s -> constants_overrides := Some (parse_json_or_file s)), + " set overrides for constants in protocol parameters (e.g. \ + blocks_per_cycle)" ); + ( "--bootstrap-accounts", + Arg.String (fun s -> bootstrap_accounts := Some (parse_json_or_file s)), + " set bootstrap accounts of protocol" ); + ] + +let usage = + Format.sprintf + {|usage: %s '[[1, [[0, "tz1..."], [1, "tz1..."]]], [2, [[0, "tz1..."]]]]'|} + Sys.argv.(0) + +let () = + Arg.parse (Arg.align specs) set_selection usage ; + main () diff --git a/src/proto_020_PsParisC/lib_delegate/test/test_scenario.ml b/src/proto_020_PsParisC/lib_delegate/test/test_scenario.ml new file mode 100644 index 000000000000..a5f2f3a5ce7c --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/test/test_scenario.ml @@ -0,0 +1,1986 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(* Testing + ------- + Component: Protocol, delegate + Invocation: dune exec src/proto_020_PsParisC/lib_delegate/test/main.exe \ + -- --file test_scenario.ml + Subject: Test different scenario for delegate +*) + +open Mockup_simulator + +let bootstrap1 = Signature.Public_key.hash bootstrap1 + +let bootstrap2 = Signature.Public_key.hash bootstrap2 + +let bootstrap3 = Signature.Public_key.hash bootstrap3 + +let bootstrap4 = Signature.Public_key.hash bootstrap4 + +let bootstrap5 = Signature.Public_key.hash bootstrap5 + +let some_seed s = Some (Protocol.State_hash.of_b58check_exn s) + +(* + +Test that the chain reaches the 5th level. + +*) + +let test_level_5 () = + let open Lwt_result_syntax in + let level_to_reach = 5l in + let module Hooks : Hooks = struct + include Default_hooks + + let stop_on_event = function + | Baking_state.New_head_proposal {block; _} -> + (* Stop the node as soon as we receive a proposal with a level + higher than [level_to_reach]. *) + block.shell.level > level_to_reach + | _ -> false + + let check_chain_on_success ~chain = + (* Make sure that all decided blocks have been decided at round 0. *) + let round_is_zero block = + let level = block.rpc_context.block_header.level in + let* round = get_block_round block in + if Int32.equal round 0l then return_unit + else failwith "block at level %ld was selected at round %ld" level round + in + List.iter_es round_is_zero chain + end in + (* Here we start two bakers, one with 3 delegates (bootstrap1, bootstrap2, + bootstrap3) and the other with 2 delegates (bootstrap4, bootstrap5). + The simulation continues till both nodes stop, see [stop_on_event] + above. *) + let config = + { + default_config with + timeout = Int32.to_int level_to_reach * 3 * 2; + round0 = 2L; + round1 = 3L; + } + in + run ~config [(3, (module Hooks)); (2, (module Hooks))] + +let test_preattest_on_valid () = + let open Lwt_result_syntax in + let level_to_reach = 2l in + let round_to_reach = 1l in + let module Hooks : Hooks = struct + include Default_hooks + + let on_new_head ~block_hash ~block_header = + (* Stop notifying heads on the level to reach, only notify that + it has been validated *) + if block_header.Block_header.shell.level < level_to_reach then + Lwt.return_some (block_hash, block_header) + else Lwt.return_none + + let seen_candidate = ref None + + let pqc_noticed = ref false + + let qc_noticed = ref false + + let stop_on_event = function + | Baking_state.Prequorum_reached (candidate, _) -> + (* Register the PQC notice. *) + (match !seen_candidate with + | Some seen_candidate + when Block_hash.(candidate.hash = seen_candidate) -> + pqc_noticed := true + | _ -> ()) ; + false + | Baking_state.Quorum_reached (candidate, _) -> + (* Because attestations are sent regardless of whether + a head has been applied, we can expect a quorum to + be received regardless of a head not being produced. *) + (match !seen_candidate with + | Some seen_candidate + when Block_hash.(candidate.hash = seen_candidate) -> + qc_noticed := true + | _ -> ()) ; + false + | New_head_proposal {block; _} -> + (* Ensure that we never notice a new head at the level where + we are not supposed to. *) + if block.shell.level = level_to_reach then + Stdlib.failwith "Unexpected new head event" + else false + | New_valid_proposal {block; _} -> + (* Register the seen valid proposal candidate. *) + if + block.shell.level = level_to_reach + && Protocol.Alpha_context.Round.to_int32 block.round = 0l + then seen_candidate := Some block.hash ; + (* Stop the node when we reach level 2 / round 2. *) + block.shell.level = level_to_reach + && Protocol.Alpha_context.Round.to_int32 block.round >= round_to_reach + | _ -> false + + let check_chain_on_success ~chain:_ = + assert (!seen_candidate <> None) ; + assert !pqc_noticed ; + assert !qc_noticed ; + return_unit + end in + let config = {default_config with timeout = 10} in + run ~config [(1, (module Hooks))] + +let test_reset_delayed_pqc () = + let open Lwt_syntax in + let module Hooks : Hooks = struct + include Default_hooks + + let should_wait = ref true + + let trigger = ref false + + let on_new_operation x = + let* () = + if !should_wait then Lwt_unix.sleep 0.5 else Lwt_unix.sleep 0.2 + in + if !trigger then ( + trigger := false ; + Lwt.return_none) + else Lwt.return_some x + + let on_new_head ~block_hash ~(block_header : Block_header.t) = + let block_round = + match + Protocol.Alpha_context.Fitness.round_from_raw + block_header.shell.fitness + with + | Error _ -> assert false + | Ok x -> x + in + if + block_header.Block_header.shell.level = 1l + && Protocol.Alpha_context.Round.(block_round = zero) + then ( + let* () = Lwt_unix.sleep 1. in + should_wait := false ; + trigger := true ; + Lwt.return_some (block_hash, block_header)) + else Lwt.return_some (block_hash, block_header) + + let stop_on_event = function + | Baking_state.New_valid_proposal {block; _} -> + let is_high_round = + let open Protocol.Alpha_context.Round in + match of_int 5 with + | Ok high_round -> block.round = high_round + | _ -> assert false + in + (block.shell.level = 1l && is_high_round) || block.shell.level > 1l + | _ -> false + + let check_chain_on_success ~chain = + let head = Stdlib.List.hd chain in + if head.rpc_context.block_header.level = 1l then failwith "baker is stuck" + else return_ok_unit + end in + let config = {default_config with round0 = 2L; round1 = 3L; timeout = 50} in + run ~config [(1, (module Hooks))] + +(* + +Scenario T1 + +1. Node A proposes at the round 0. +2. Both node A and node B preattest. +3. Node A stops. +4. Node B attests in the round 0 and locks. No decision is taken at the + round 0 because A did not attest. +5. We check that in round 1 (the next slot for B), B proposes the same + value as A proposed in the round 0, not a new proposal. +*) + +let test_scenario_t1 () = + let open Lwt_result_syntax in + let original_proposal = ref None in + let a_preattested = ref false in + let b_preattested = ref false in + let b_attested = ref false in + let b_reproposed = ref false in + (* Here we use custom hooks to make each node/baker behave according to + its role in the scenario. *) + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let check_mempool_after_processing ~mempool = + mempool_has_op_ref + ~mempool + ~predicate: + (op_is_both + (op_is_signed_by ~public_key:Mockup_simulator.bootstrap1) + (op_is_preattestation ~level:1l ~round:0l)) + ~var:a_preattested + + let stop_on_event _ = !a_preattested + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let check_block_before_processing ~level ~round ~block_hash ~block_header + ~(protocol_data : Protocol.Alpha_context.Block_header.protocol_data) = + let* () = + match (!b_attested, level, round) with + | false, 1l, 0l -> + (* If any of the checks fails the whole scenario will fail. *) + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap1 + in + save_proposal_payload ~protocol_data ~var:original_proposal + | true, 1l, 1l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap2 + in + let* () = + verify_payload_hash + ~protocol_data + ~original_proposal + ~message:"a new block proposed instead of reproposal" + in + b_reproposed := true ; + return_unit + | _ -> failwith "unexpected level = %ld / round = %ld" level round + in + return_unit + + let check_mempool_after_processing ~mempool = + let* () = + mempool_has_op_ref + ~mempool + ~predicate: + (op_is_both + (op_is_signed_by ~public_key:Mockup_simulator.bootstrap2) + (op_is_preattestation ~level:1l ~round:0l)) + ~var:b_preattested + in + mempool_has_op_ref + ~mempool + ~predicate: + (op_is_both + (op_is_signed_by ~public_key:Mockup_simulator.bootstrap2) + (op_is_preattestation ~level:1l ~round:0l)) + ~var:b_attested + + let stop_on_event _ = !b_reproposed + end in + let config = + { + default_config with + initial_seed = None; + delegate_selection = [(1l, [(0l, bootstrap1); (1l, bootstrap2)])]; + } + in + run ~config [(1, (module Node_a_hooks)); (1, (module Node_b_hooks))] + +(* + +Scenario T2 + +1. Node A should propose at the round 0, but it is dead. +2. Node B waits til it has its proposal slot at round 1 and proposes then. + +*) + +let test_scenario_t2 () = + let open Lwt_result_syntax in + let b_proposed = ref false in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let stop_on_event _ = true (* Node A stops immediately. *) + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let check_block_before_processing ~level ~round ~block_hash ~block_header + ~protocol_data:_ = + (* Here we test that the only block that B observes is its own + proposal for level 1 at round 1. *) + match (level, round) with + | 1l, 1l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap2 + in + b_proposed := true ; + return_unit + | _ -> failwith "unexpected level = %ld / round = %ld" level round + + let stop_on_event _ = + (* Stop as soon as B has proposed. This ends the test. *) + !b_proposed + end in + let config = + { + default_config with + initial_seed = None; + delegate_selection = [(1l, [(0l, bootstrap1); (1l, bootstrap2)])]; + } + in + run ~config [(1, (module Node_a_hooks)); (1, (module Node_b_hooks))] + +(* + +Scenario T3 + +1. There are four nodes: A, B, C, and D. +2. C is the proposer at the round 0. It sends the proposal, which is + received by all bakers except for D. +3. Due to how the messages propagate, only B sees 3 preattestations. It + attests and locks. Other nodes all see fewer than 3 preattestations. + + A -> A and B + B -> B + C -> C and B + +4. D proposes at the round 1. Its message reaches 3 nodes, including B. + + D -> D, B, C + +5. B does not preattest because it is locked. +6. No decision is taken at the round 1. +7. B proposes at the round 2. There are no more problems with propagation of + messages, so a decision is reached. + +*) + +let test_scenario_t3 () = + let open Lwt_result_syntax in + let b_observed_pqc = ref false in + let original_proposal = ref None in + let we_are_done = ref false in + let stop_on_event0 _ = !we_are_done in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_operation ~op_hash ~op = + if !b_observed_pqc then return (op_hash, op, [Pass; Pass; Pass; Pass]) + else + let* is_preattestation = + op_is_preattestation ~level:1l ~round:0l op_hash op + in + if is_preattestation then + return (op_hash, op, [Pass; Pass; Block; Block]) + else failwith "unexpected operation from the node D" + + let stop_on_event = stop_on_event0 + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~(protocol_data : Protocol.Alpha_context.Block_header.protocol_data) = + match (level, round) with + | 1l, 2l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap2 + in + we_are_done := true ; + let* () = + verify_payload_hash + ~protocol_data + ~original_proposal + ~message:"a new block proposed instead of reproposal" + in + return (block_hash, block_header, operations, [Pass; Pass; Pass; Pass]) + | _ -> + failwith + "unexpected injection on the node B, level = %ld / round = %ld" + level + round + + let on_inject_operation ~op_hash ~op = + if !b_observed_pqc then return (op_hash, op, [Pass; Pass; Pass; Pass]) + else + let* is_preattestation = + op_is_preattestation ~level:1l ~round:0l op_hash op + in + if is_preattestation then + return (op_hash, op, [Block; Pass; Block; Block]) + else failwith "unexpected operation from the node B" + + let check_mempool_after_processing ~mempool = + let predicate op_hash op = + op_is_preattestation ~level:1l ~round:0l op_hash op + in + let* n = mempool_count_ops ~mempool ~predicate in + if n > 3 then + failwith "B received too many preattestations, expected to see only 3" + else if n = 3 then ( + b_observed_pqc := true ; + return_unit) + else return_unit + + let stop_on_event = stop_on_event0 + end in + let module Node_c_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~(protocol_data : Protocol.Alpha_context.Block_header.protocol_data) = + match (level, round) with + | 1l, 0l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap3 + in + let* () = + save_proposal_payload ~protocol_data ~var:original_proposal + in + return + (block_hash, block_header, operations, [Pass; Pass; Pass; Block]) + | _ -> + failwith + "unexpected injection on the node C, level = %ld / round = %ld" + level + round + + let on_inject_operation ~op_hash ~op = + if !b_observed_pqc then return (op_hash, op, [Pass; Pass; Pass; Pass]) + else + let* is_preattestation = + op_is_preattestation ~level:1l ~round:0l op_hash op + in + if is_preattestation then + return (op_hash, op, [Block; Pass; Pass; Block]) + else failwith "unexpected operation from the node C" + + let stop_on_event = stop_on_event0 + end in + let module Node_d_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + match (level, round) with + | 1l, 1l -> + return + (block_hash, block_header, operations, [Block; Pass; Pass; Pass]) + | _ -> + failwith + "unexpected injection on the node D, level = %ld / round = %ld" + level + round + + let on_inject_operation ~op_hash ~op = + if !b_observed_pqc then return (op_hash, op, [Pass; Pass; Pass; Pass]) + else return (op_hash, op, [Block; Block; Block; Block]) + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngFtAUcm1EneHCCrxxSWAaxSukwEhSPvpTnFjVdKLEjgkapUy1pP"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap3); + (1l, bootstrap4); + (2l, bootstrap2); + (3l, bootstrap1); + ] ); + ( 2l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ]; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Node_b_hooks)); + (1, (module Node_c_hooks)); + (1, (module Node_d_hooks)); + ] + +(* Scenario T4 + + 1. There are two nodes A B: + A can propose at level 1, round 0 and level 2, round 1 + B can propose at level 1, round 1 and level 2, round 0 + 4. Node A proposes at level 1, round 0, + 5. Both nodes preattest the proposal at level 1, round 0, + 6. Both nodes attest the proposal at level 1, round 0, + 7. Only A receives the block application at level 1, round 0, + 8. B does not propose at level 2, round 0, + 9. A proposes at level 2, round 1. + Predecessor hash is block at level 1, round 0. +*) + +let test_scenario_t4 () = + let open Lwt_result_syntax in + let level_to_reach = 4l in + let a_proposal_level_1 = ref None in + let a_proposal_level_2_predecessor = ref None in + let b_attested_level_1 = ref false in + let b_proposed_level_2 = ref false in + + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> + block.shell.level >= level_to_reach + | _ -> false + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + let () = + match (level, round) with + | 1l, 0l -> a_proposal_level_1 := Some block_hash + | 2l, 1l -> + a_proposal_level_2_predecessor := + Some block_header.Block_header.shell.predecessor + | _ -> () + in + return (block_hash, block_header, operations, [Pass; Pass]) + + let stop_on_event = stop_on_event0 + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_new_head ~block_hash ~block_header = + (* Stop notifying heads to node B for block proposed at level 1, round 0. *) + match !a_proposal_level_1 with + | Some a_proposal_level_1_block_hash + when Block_hash.(a_proposal_level_1_block_hash = block_hash) -> + Lwt.return_none + | _ -> Lwt.return_some (block_hash, block_header) + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + let () = + match (level, round) with + | 2l, 0l -> b_proposed_level_2 := true + | _ -> () + in + return (block_hash, block_header, operations, [Pass; Pass]) + + let on_inject_operation ~op_hash ~op = + let* is_attestation = op_is_attestation ~level:1l ~round:0l op_hash op in + if is_attestation then b_attested_level_1 := true ; + + return (op_hash, op, [Pass; Pass; Pass; Pass]) + + let check_chain_on_success ~chain:_ = + if not !b_attested_level_1 then + failwith "Node B did not attest proposal at level 1, round 0" + else if + not + @@ Option.equal + Block_hash.equal + !a_proposal_level_2_predecessor + !a_proposal_level_1 + then + failwith + "Invalid predecessor block for A's proposal at level 2: proposal had \ + predecessor %a, expected %a\n" + (Format.pp_print_option Block_hash.pp_short) + !a_proposal_level_1 + (Format.pp_print_option Block_hash.pp_short) + !a_proposal_level_2_predecessor + else return_unit + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngG9pS9mbDWnz6YLUFrd8sbb9KMUzfAUMpSpnxNHY9BFnSB8L3zq"; + delegate_selection = + [ + (1l, [(0l, bootstrap1); (1l, bootstrap2)]); + (2l, [(0l, bootstrap2); (1l, bootstrap1)]); + ]; + } + in + run ~config [(1, (module Node_a_hooks)); (1, (module Node_b_hooks))] + +(* + +Scenario F1 + +1. Node C (bootstrap3) proposes at level 1 round 0, its proposal reaches all + nodes. +2. Propagation of preattestations happens in such a way that only Node A + (bootstrap1) observes PQC: + + A -> A + B -> B and A + C -> C and A + D -> D and A + + Node A locks. + +3. At the level 1 round 1 node D (bootstrap4) proposes. Propagation of + messages is normal. + +4. Node A (bootstrap1) should propose at level 2 round 0. + +*) + +let test_scenario_f1 () = + let open Lwt_result_syntax in + let c_proposed_l1_r0 = ref false in + let d_proposed_l1_r1 = ref false in + let a_proposed_l2_r0 = ref false in + let stop_on_event0 _ = !a_proposed_l2_r0 in + let pass = + (* This is to be sure that the proposal for round r arrives while + the baker is in round r, and not in round r-1. (See related + issue: + https://gitlab.com/tezos/tezos/-/issues/4143). Otherwise, the + test does not perform as expected. *) + Delay 0.5 + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + match (!c_proposed_l1_r0, !d_proposed_l1_r1, level, round) with + | true, true, 2l, 0l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap1 + in + let* () = + a_proposed_l2_r0 := true ; + return_unit + in + return (block_hash, block_header, operations, [pass; pass; pass; pass]) + | _ -> + failwith + "unexpected injection on the node A, level = %ld / round = %ld" + level + round + + let on_inject_operation ~op_hash ~op = + match (!c_proposed_l1_r0, !d_proposed_l1_r1) with + | true, false -> return (op_hash, op, [Pass; Block; Block; Block]) + | _ -> return (op_hash, op, [Pass; Pass; Pass; Pass]) + + let stop_on_event = stop_on_event0 + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_inject_operation ~op_hash ~op = + match (!c_proposed_l1_r0, !d_proposed_l1_r1) with + | true, false -> return (op_hash, op, [Pass; Pass; Block; Block]) + | _ -> return (op_hash, op, [Pass; Pass; Pass; Pass]) + + let stop_on_event = stop_on_event0 + end in + let module Node_c_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + match (!c_proposed_l1_r0, !d_proposed_l1_r1, level, round) with + | false, false, 1l, 0l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap3 + in + let* () = + c_proposed_l1_r0 := true ; + return_unit + in + return (block_hash, block_header, operations, [pass; pass; pass; pass]) + | _ -> + failwith + "unexpected injection on the node C, level = %ld / round = %ld" + level + round + + let on_inject_operation ~op_hash ~op = + match (!c_proposed_l1_r0, !d_proposed_l1_r1) with + | true, false -> return (op_hash, op, [Pass; Block; Pass; Block]) + | _ -> return (op_hash, op, [Pass; Pass; Pass; Pass]) + + let stop_on_event = stop_on_event0 + end in + let module Node_d_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + match (!d_proposed_l1_r1, level, round) with + | false, 1l, 1l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap4 + in + let* () = + d_proposed_l1_r1 := true ; + return_unit + in + return (block_hash, block_header, operations, [pass; pass; pass; pass]) + | _ -> + failwith + "unexpected injection on the node D, level = %ld / round = %ld" + level + round + + let on_inject_operation ~op_hash ~op = + match (!c_proposed_l1_r0, !d_proposed_l1_r1) with + | true, false -> return (op_hash, op, [Pass; Block; Block; Pass]) + | _ -> return (op_hash, op, [Pass; Pass; Pass; Pass]) + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGohKUZjXzv69sxvDqAYRd4XPDQSxDoEpP72znu2jduBuhcYiSE"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap3); + (1l, bootstrap4); + (2l, bootstrap1); + (3l, bootstrap2); + ] ); + ( 2l, + [ + (0l, bootstrap1); + (1l, bootstrap4); + (2l, bootstrap2); + (3l, bootstrap3); + ] ); + ]; + timeout = 30; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Node_b_hooks)); + (1, (module Node_c_hooks)); + (1, (module Node_d_hooks)); + ] + +(* + +Scenario F2 + +1. There are four nodes: A, B, C, and D. +2. A proposes at 1.0 and observes EQC. +3. A has the slot at 2.0 but somehow it doesn't propose or its proposal is lost. +4. B, C, and D have the rounds 1, 2, and 3 respectively, but they also do not propose. +5. A should still propose at 2.4. + +*) + +let test_scenario_f2 () = + let open Lwt_result_syntax in + let proposal_2_4_observed = ref false in + let module Hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + let propagation_vector = + match (level, round) with + | 1l, 0l -> [Pass; Pass; Pass; Pass] + | 2l, 0l -> [Pass; Block; Block; Block] + | 2l, 4l -> + proposal_2_4_observed := true ; + [Pass; Pass; Pass; Pass] + | _ -> [Block; Block; Block; Block] + in + return (block_hash, block_header, operations, propagation_vector) + + let stop_on_event _ = !proposal_2_4_observed + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGPSm87ZqWxJmZu7rewiLiyKY72ffCQQvxDuWmFBw59dWAL5VTB"; + delegate_selection = + [ + (1l, [(0l, bootstrap1)]); + ( 2l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + (4l, bootstrap1); + ] ); + ]; + timeout = 60; + round0 = 2L; + round1 = 3L; + } + in + run + ~config + [ + (1, (module Hooks)); + (1, (module Hooks)); + (1, (module Hooks)); + (1, (module Hooks)); + ] + +(* + +Scenario M1 + +1. Four nodes start, each with 1 delegate. +2. As soon as 2nd level is proposed all communication between nodes becomes + impossible. +3. The situation continues for 5 seconds. +4. After communication is resumed the bakers must continue making progress. + +*) + +let test_scenario_m1 () = + let open Lwt_result_syntax in + let observed_level2_timestamp = ref None in + let network_down_sec = 5. in + let module Hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + let propagation_vector = + match !observed_level2_timestamp with + | None -> + if Compare.Int32.(level >= 2l) then ( + observed_level2_timestamp := Some (Unix.time ()) ; + [Pass; Pass; Pass; Pass]) + else [Pass; Pass; Pass; Pass] + | Some level2_observed -> + if Unix.time () -. level2_observed < network_down_sec then + [Block; Block; Block; Block] + else [Pass; Pass; Pass; Pass] + in + return (block_hash, block_header, operations, propagation_vector) + + let on_inject_operation ~op_hash ~op = + let propagation_vector = + match !observed_level2_timestamp with + | None -> [Pass; Pass; Pass; Pass] + | Some level2_observed -> + if Unix.time () -. level2_observed < network_down_sec then + [Block; Block; Block; Block] + else [Pass; Pass; Pass; Pass] + in + return (op_hash, op, propagation_vector) + + let stop_on_event = function + | Baking_state.New_head_proposal {block; _} -> block.shell.level > 4l + | _ -> false + end in + let config = {default_config with timeout = 60} in + run + ~config + [ + (1, (module Hooks)); + (1, (module Hooks)); + (1, (module Hooks)); + (1, (module Hooks)); + ] + +(* + +Scenario M2 + +1. Five nodes start (single delegate per node). +2. They decide level 1. +3. However, the node that has the slot for level 2 round 0 is not there + to participate. +4. We check that the chain continues advancing despite that. + +*) + +let test_scenario_m2 () = + let module Normal_node : Hooks = struct + include Default_hooks + + let stop_on_event = function + | Baking_state.New_head_proposal {block; _} -> block.shell.level > 5l + | _ -> false + end in + let module Missing_node : Hooks = struct + include Default_hooks + + let stop_on_event _ = true (* stop immediately *) + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGo77zNC59bYiQMk2M14aDZZu4KXG8BV1C8pi7afjJ7cXyqB3M1"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ( 2l, + [ + (0l, bootstrap5); + (1l, bootstrap1); + (2l, bootstrap2); + (3l, bootstrap3); + (4l, bootstrap4); + ] ); + ]; + round0 = 2L; + round1 = 3L; + timeout = 60; + } + in + run + ~config + [ + (1, (module Normal_node)); + (1, (module Normal_node)); + (1, (module Normal_node)); + (1, (module Normal_node)); + (1, (module Missing_node)); + ] + +(* + +Scenario M3 + +1. There are four nodes: A, B, C, and D. +2. A and B propose in turns. Messages from A reach every node, but messages + from other nodes only go to A. +3. The chain should not make progress. Since we have both bootstrap1 and + bootstrap2 in delegate selection they have equal voting power. Therefore + it is necessary to have 2 votes for prequorums (which is achieved when A + is proposing) and 2 votes for quorums (impossible because B has no way to + obtain PQC and thus cannot send attestations). + +*) + +let test_scenario_m3 () = + let open Lwt_result_syntax in + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> + block.shell.level = 1l + && Protocol.Alpha_context.Round.to_int32 block.round = 6l + | _ -> false + in + + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let stop_on_event = stop_on_event0 + end in + let module Other_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + return (block_hash, block_header, operations, [Pass; Block; Block; Block]) + + let on_inject_operation ~op_hash ~op = + return (op_hash, op, [Pass; Block; Block; Block]) + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGaxNJcwEVJLgQXmnN8KN5skn6fhU4Awtu8zVDKViTd5gsfT51M"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap1); + (3l, bootstrap2); + (4l, bootstrap1); + (5l, bootstrap2); + (6l, bootstrap1); + ] ); + ]; + round0 = 2L; + round1 = 3L; + timeout = 60; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Other_hooks)); + (1, (module Other_hooks)); + (1, (module Other_hooks)); + ] + +(* + +Scenario M4 + +1. There are four bakers: A, B, C, and D. +2. A proposes at level 1 round 0. Its proposal reaches A, B, C, and D, but + with a delay of 0.5 seconds. +3. 3 votes are enough for consensus, because voting powers of all delegates + are equal. Preattestations propagate freely, however attestations from C + are blocked. +4. Check that at level 1 round 0 quorum is reached (from the point of view + of A). This means that D sends an attestation despite receiving + preattestations before the proposal. + +*) + +let test_scenario_m4 () = + let open Lwt_result_syntax in + let a_observed_qc = ref false in + let stop_on_event0 _ = !a_observed_qc in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + match (level, round) with + | 1l, 0l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap1 + in + return + (block_hash, block_header, operations, [Pass; Pass; Pass; Delay 0.5]) + | _ -> + failwith + "unexpected injection on the node A, level = %ld / round = %ld" + level + round + + let check_mempool_after_processing ~mempool = + let predicate op_hash op = + op_is_attestation ~level:1l ~round:0l op_hash op + in + let* n = mempool_count_ops ~mempool ~predicate in + if n > 3 then + failwith "A received too many attestations, expected to see only 3" + else if n = 3 then ( + a_observed_qc := true ; + return_unit) + else return_unit + + let stop_on_event = stop_on_event0 + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let stop_on_event = stop_on_event0 + end in + let module Node_c_hooks : Hooks = struct + include Default_hooks + + let on_inject_operation ~op_hash ~op = + let* is_attestation = op_is_attestation ~level:1l ~round:0l op_hash op in + return + ( op_hash, + op, + if is_attestation then [Block; Block; Block; Block] + else [Pass; Pass; Pass; Pass] ) + + let stop_on_event = stop_on_event0 + end in + let module Node_d_hooks : Hooks = struct + include Default_hooks + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGJmwLi7kPvGwV2LR3kjNQ6xamGPCZ9ooep9QcafbqRXZhYEciT"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ]; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Node_b_hooks)); + (1, (module Node_c_hooks)); + (1, (module Node_d_hooks)); + ] + +(* + +Scenario M5 + +1. There are four bakers: A, B, C, and D. +2. A proposes at level 1 round 0. Its proposal reaches A, B, C, and D, but with + a delay of 1 second. There are no problems with propagation of + preattestations and attestations. +3. At the level 1 all four bakers have proposer slots, however we block possible + proposals from B and C at higher rounds. +4. Check that D proposes at the level 2 round 0, which means that it has + observed QC. + +*) + +let test_scenario_m5 () = + let open Lwt_result_syntax in + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> block.shell.level >= 2l + | _ -> false + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + match (level, round) with + | 1l, 0l -> + let* () = + check_block_signature + ~block_hash + ~block_header + ~public_key:Mockup_simulator.bootstrap1 + in + return + (block_hash, block_header, operations, [Pass; Pass; Pass; Delay 1.0]) + | _ -> + failwith + "unexpected injection on the node A, level = %ld / round = %ld" + level + round + + let stop_on_event = stop_on_event0 + end in + let module Other_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + return (block_hash, block_header, operations, [Block; Block; Block; Block]) + + let stop_on_event = stop_on_event0 + end in + let module Node_d_hooks : Hooks = struct + include Default_hooks + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGJmwLi7kPvGwV2LR3kjNQ6xamGPCZ9ooep9QcafbqRXZhYEciT"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ]; + round0 = 3L; + round1 = 4L; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Other_hooks)); + (1, (module Other_hooks)); + (1, (module Node_d_hooks)); + ] + +(* + +Scenario M6 + +1. There are four bakers: A, B, C, and D. +2. A proposes at level 1 round 0. Its proposal reaches all nodes, and they + observe PQC. Only A observes a QC. +3. At level 1 round 1 it is B's turn to propose. Since it has observed the + PQC, it reproposes A's proposal. A does not see it. +4. B observes PQC and QC for its proposal. +5. A proposes at level 2 round 0. No one sees the proposal. +6. B proposes at level 2 round 1. A sees B's proposal and switches its branch. +7. We wait 2 more levels before checking A's chain to verify that it has + adopted B's proposal. + +*) + +let test_scenario_m6 () = + let open Lwt_result_syntax in + let b_proposal_2_1 = ref None in + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> block.shell.level > 4l + | _ -> false + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + let propagation_vector = + match (level, round) with + | 2l, 0l -> [Pass; Block; Block; Block] + | _ -> [Pass; Pass; Pass; Pass] + in + return (block_hash, block_header, operations, propagation_vector) + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + return + ( op_hash, + op, + if is_a10_attestation then [Pass; Block; Block; Block] + else [Pass; Pass; Pass; Pass] ) + + let stop_on_event = stop_on_event0 + + let check_chain_on_success ~chain = + match List.nth (List.rev chain) 2 with + | None -> failwith "Node A has empty chain" + | Some (block : block) -> + verify_payload_hash + ~protocol_data:block.protocol_data + ~original_proposal:b_proposal_2_1 + ~message:"A did not switch to B's proposal (level 2, round 1)" + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data = + let* propagation_vector = + match (level, round) with + | 1l, 1l -> return [Block; Delay 0.1; Delay 0.1; Delay 0.1] + | 2l, 1l -> + let* () = + save_proposal_payload ~protocol_data ~var:b_proposal_2_1 + in + return [Pass; Pass; Pass; Pass] + | _ -> return [Pass; Pass; Pass; Pass] + in + return (block_hash, block_header, operations, propagation_vector) + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + return + ( op_hash, + op, + if is_a10_attestation then [Pass; Block; Block; Block] + else [Pass; Pass; Pass; Pass] ) + + let stop_on_event = stop_on_event0 + end in + let module Other_node : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + return (block_hash, block_header, operations, [Pass; Pass; Pass; Pass]) + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + return + ( op_hash, + op, + if is_a10_attestation then [Pass; Block; Block; Block] + else [Pass; Pass; Pass; Pass] ) + + let stop_on_event = stop_on_event0 + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGnwG2gApiRzo1kdbCgQheqtZroUsAjsJzyw2RBbtg3gtTeMQ9F"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ( 2l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ]; + timeout = 60; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Node_b_hooks)); + (1, (module Other_node)); + (1, (module Other_node)); + ] + +(* + +Scenario M7 + +The same as M6, but: + +5. B proposes at level 2 round 0 (A does not see the proposal). +6. A proposes at 2.1. B switches to A's branch when it receives 2.1. +7. We wait 2 more levels before checking everyone's chain to verify that + A's proposal has been selected. + +*) + +let test_scenario_m7 () = + let open Lwt_result_syntax in + let a_proposal_2_1 = ref None in + let c_received_2_1 = ref false in + let d_received_2_1 = ref false in + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> block.shell.level > 4l + | _ -> false + in + let check_chain_on_success0 node_label ~chain = + match List.nth (List.rev chain) 2 with + | None -> failwith "Node %s has empty chain" node_label + | Some (block : block) -> + verify_payload_hash + ~protocol_data:block.protocol_data + ~original_proposal:a_proposal_2_1 + ~message: + (Format.sprintf + "%s did not switch to A's proposal (level 2, round 1)" + node_label) + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data = + let* () = + match (level, round) with + | 2l, 1l -> save_proposal_payload ~protocol_data ~var:a_proposal_2_1 + | _ -> return_unit + in + return (block_hash, block_header, operations, [Pass; Pass; Pass; Pass]) + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + return + ( op_hash, + op, + if is_a10_attestation then [Pass; Block; Block; Block] + else [Pass; Pass; Pass; Pass] ) + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "A" + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + let* propagation_vector = + match (level, round) with + | 1l, 1l -> return [Block; Delay 0.1; Delay 0.1; Delay 0.1] + | 2l, 0l -> return [Block; Pass; Pass; Pass] + | _ -> return [Pass; Pass; Pass; Pass] + in + return (block_hash, block_header, operations, propagation_vector) + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + let* level2_preattestation = op_is_preattestation ~level:2l op_hash op in + let* level2_attestation = op_is_attestation ~level:2l op_hash op in + let propagation_vector = + match + (is_a10_attestation, level2_preattestation, level2_attestation) + with + | true, _, _ -> [Pass; Block; Block; Block] + | _, true, _ | _, _, true -> [Block; Block; Block; Block] + | _, _, _ -> [Pass; Pass; Pass; Pass] + in + return (op_hash, op, propagation_vector) + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "B" + end in + let module Node_c_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + let propagation_vector = + if !c_received_2_1 then [Pass; Pass; Pass; Pass] + else [Block; Block; Block; Block] + in + return (block_hash, block_header, operations, propagation_vector) + + let check_chain_after_processing ~level ~round ~chain:_ = + match (level, round) with + | 2l, 1l -> + c_received_2_1 := true ; + return_unit + | _ -> return_unit + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + let* level2_preattestation = op_is_preattestation ~level:2l op_hash op in + let* level2_attestation = op_is_attestation ~level:2l op_hash op in + let propagation_vector = + match + ( is_a10_attestation, + !c_received_2_1, + level2_preattestation, + level2_attestation ) + with + | true, _, _, _ -> [Pass; Block; Block; Block] + | _, false, true, _ | _, false, _, true -> [Block; Block; Block; Block] + | _, _, _, _ -> [Pass; Pass; Pass; Pass] + in + return (op_hash, op, propagation_vector) + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "C" + end in + let module Node_d_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + let propagation_vector = + if !d_received_2_1 then [Pass; Pass; Pass; Pass] + else [Block; Block; Block; Block] + in + return (block_hash, block_header, operations, propagation_vector) + + let check_chain_after_processing ~level ~round ~chain:_ = + match (level, round) with + | 2l, 1l -> + d_received_2_1 := true ; + return_unit + | _ -> return_unit + + let on_inject_operation ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + let* level2_preattestation = op_is_preattestation ~level:2l op_hash op in + let* level2_attestation = op_is_attestation ~level:2l op_hash op in + let propagation_vector = + match + ( is_a10_attestation, + !d_received_2_1, + level2_preattestation, + level2_attestation ) + with + | true, _, _, _ -> [Pass; Block; Block; Block] + | _, false, true, _ | _, false, _, true -> [Block; Block; Block; Block] + | _, _, _, _ -> [Pass; Pass; Pass; Pass] + in + return (op_hash, op, propagation_vector) + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "D" + end in + let config = + { + default_config with + initial_seed = + some_seed "rngGJ7ReXwsjWuzpeqCgHAjudFwJtxdYz44Genz1FnyJ8R226hoKh"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ( 2l, + [ + (0l, bootstrap2); + (1l, bootstrap1); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ]; + timeout = 60; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Node_b_hooks)); + (1, (module Node_c_hooks)); + (1, (module Node_d_hooks)); + ] + +(* + +Scenario M8 + +5. B proposes at 2.0 and observes PQC but not QC. +6. C re-proposes at 2.1 and similarly observes PQC but not QC. +7. A proposes at 2.2. B, C, and D do not switch to A's branch; moreover A + switches to their branch when it receives the next proposal (2.3). This + happens because B, C, and D have PQC despite A having a higher round (2 > 1). +8. We wait 2 more levels before checking everyone's chain to verify that + B's proposal has been selected. + +*) + +let test_scenario_m8 () = + let open Lwt_result_syntax in + let b_proposal_2_0 = ref None in + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> block.shell.level > 4l + | _ -> false + in + let on_inject_operation0 ~op_hash ~op = + let* is_a10_attestation = + op_is_attestation ~level:1l ~round:0l op_hash op + in + let* is_b20_attestation = + op_is_attestation ~level:2l ~round:0l op_hash op + in + let* is_c21_attestation = + op_is_attestation ~level:2l ~round:1l op_hash op + in + let propagation_vector = + if is_a10_attestation then [Pass; Block; Block; Block] + else if is_b20_attestation || is_c21_attestation then + [Block; Block; Block; Block] + else [Pass; Pass; Pass; Pass] + in + return (op_hash, op, propagation_vector) + in + let check_chain_on_success0 node_label ~chain = + match List.nth (List.rev chain) 2 with + | None -> failwith "Node %s has empty chain" node_label + | Some (block : block) -> + verify_payload_hash + ~protocol_data:block.protocol_data + ~original_proposal:b_proposal_2_0 + ~message: + (Format.sprintf + "%s did not switch to B's proposal (level 2, round 0)" + node_label) + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + return (block_hash, block_header, operations, [Pass; Pass; Pass; Pass]) + + let on_inject_operation = on_inject_operation0 + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "A" + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data = + let* propagation_vector = + match (level, round) with + | 1l, 1l -> return [Block; Delay 0.1; Delay 0.1; Delay 0.1] + | 2l, 0l -> + let* () = + save_proposal_payload ~protocol_data ~var:b_proposal_2_0 + in + return [Block; Pass; Pass; Pass] + | _ -> return [Pass; Pass; Pass; Pass] + in + return (block_hash, block_header, operations, propagation_vector) + + let on_inject_operation = on_inject_operation0 + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "B" + end in + let module Node_c_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level ~round ~block_hash ~block_header ~operations + ~protocol_data:_ = + let propagation_vector = + match (level, round) with + | 2l, 1l -> [Block; Pass; Pass; Pass] + | _ -> [Pass; Pass; Pass; Pass] + in + return (block_hash, block_header, operations, propagation_vector) + + let on_inject_operation = on_inject_operation0 + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "C" + end in + let module Node_d_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + return (block_hash, block_header, operations, [Pass; Pass; Pass; Pass]) + + let on_inject_operation = on_inject_operation0 + + let stop_on_event = stop_on_event0 + + let check_chain_on_success = check_chain_on_success0 "D" + end in + let config = + { + default_config with + initial_seed = + some_seed "rngFy2zFmgg25SXrE6aawqQVhD1kdw9eCCRxc843RLQjz5MZ6MGER"; + delegate_selection = + [ + ( 1l, + [ + (0l, bootstrap1); + (1l, bootstrap2); + (2l, bootstrap3); + (3l, bootstrap4); + ] ); + ( 2l, + [ + (0l, bootstrap2); + (1l, bootstrap3); + (2l, bootstrap1); + (3l, bootstrap4); + ] ); + ]; + timeout = 60; + } + in + run + ~config + [ + (1, (module Node_a_hooks)); + (1, (module Node_b_hooks)); + (1, (module Node_c_hooks)); + (1, (module Node_d_hooks)); + ] + +let compute_expected_injection_time config latest_proposal at_round = + let latest_proposal_block_time = + Option.value + ~default:Time.Protocol.epoch + (Option.map + (fun b -> b.Baking_state.shell.Block_header.timestamp) + latest_proposal) + in + let round = Protocol.Alpha_context.Round.to_int32 at_round in + let expected_delay = + Int64.of_int + @@ + match round with + | 0l -> 0 + | 1l -> Int64.to_int config.round0 + | n -> + Int64.to_int config.round0 + + Int32.(to_int (mul (pred n) (Int64.to_int32 config.round1))) + in + Time.Protocol.(add latest_proposal_block_time expected_delay) + |> Time.System.of_protocol_exn + +(* + Scenario M9 + + Two nodes: A, B + + 1. L1 - A proposes and reaches QC. + 2. L1 - When QC is reached, observe that B emits time to prepare + event before the beginning of the round. + 3. L2 - A observes the block from B and ends. + +*) +let test_scenario_m9 () = + let stop_level = Int32.of_int 2 in + let node_b_qc = ref false in + let node_b_level = ref Int32.zero in + let bh : Block_hash.t option ref = ref None in + let stop_on_event0 = function + | Baking_state.New_head_proposal {block; _} -> + block.shell.level >= stop_level + | _ -> false + in + let config = + { + default_config with + delegate_selection = [(1l, [(0l, bootstrap1)]); (2l, [(0l, bootstrap2)])]; + round0 = 3L; + round1 = 4L; + } + in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let raise_error : string option ref = ref None + + let block_round block_header = + let open Block_header in + match + Protocol.Alpha_context.Fitness.round_from_raw block_header.shell.fitness + with + | Error _ -> assert false + | Ok x -> x + + let on_new_head ~block_hash ~block_header = + let open Block_header in + let block_round = block_round block_header in + let level = block_header.shell.level in + let is_round0 = + Protocol.Alpha_context.Round.equal + block_round + Protocol.Alpha_context.Round.zero + in + match level with + | 2l -> + raise_error := + if + is_round0 + && not (Block_hash.equal block_hash (Stdlib.Option.get !bh)) + then Some "Block hash was not equal" + else if not is_round0 then + Some "Level 2 expected to have a block at round 0" + else None ; + Lwt.return @@ Some (block_hash, block_header) + | _ -> Lwt.return @@ Some (block_hash, block_header) + + let stop_on_event = stop_on_event0 + + let check_chain_on_success ~chain:_ = + match !raise_error with + | Some err -> Stdlib.failwith err + | _ -> Lwt_result_syntax.return_unit + end in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let on_inject_block ~level:_ ~round:_ ~block_hash ~block_header ~operations + ~protocol_data:_ = + bh := Some block_hash ; + Lwt_result_syntax.return + (block_hash, block_header, operations, [Pass; Pass]) + + let latest_proposal : Baking_state.block_info option ref = ref None + + let stop_on_event = function + | Baking_state.Quorum_reached _ when !node_b_level = 1l -> + node_b_qc := true ; + false + | Baking_state.Timeout timeout when !node_b_level = 1l -> ( + match timeout with + | Time_to_prepare_next_level_block {at_round} -> + let expected_injection_time = + compute_expected_injection_time config !latest_proposal at_round + in + (* We should bake before the block's expected timestamp *) + if Time.System.(expected_injection_time >= now ()) then + Stdlib.failwith + "bootstrap2 was expected to prepare the block before its \ + timestamp@." ; + if !node_b_qc then false + else + Stdlib.failwith "time to prepare emitted without observing qc" + | End_of_round _ -> + Stdlib.failwith "End of round timeout not expected") + | Baking_state.New_valid_proposal {block; _} -> + latest_proposal := Some block ; + node_b_level := block.shell.level ; + false + | event -> stop_on_event0 event + end in + run ~config [(1, (module Node_a_hooks)); (1, (module Node_b_hooks))] + +(* + Scenario M10 + + Two nodes : A, B + + 1. Node A is the proposer at level 1, round 0, but is dead + 2. Node B proposes at level 1, round 1, therefore the + Time_to_prepare_next_level_block was not called before its + timestamp. +*) +let test_scenario_m10 () = + let stop_level = 1l in + let stop_round = Protocol.Alpha_context.Round.(succ zero) in + let module Node_a_hooks : Hooks = struct + include Default_hooks + + let stop_on_event _ = true (* Node A stops immediately. *) + end in + let config = + { + default_config with + round0 = 3L; + round1 = 4L; + delegate_selection = [(1l, [(0l, bootstrap1); (1l, bootstrap2)])]; + } + in + let module Node_b_hooks : Hooks = struct + include Default_hooks + + let latest_proposal : Baking_state.block_info option ref = ref None + + let stop_on_event = function + | Baking_state.Timeout (Time_to_prepare_next_level_block {at_round}) -> + let expected_injection_time = + compute_expected_injection_time config !latest_proposal at_round + in + let current_time = Time.System.now () in + if Time.System.(current_time < expected_injection_time) then + Stdlib.failwith + "bootstrap2 was not supposed to prepare a block before the block \ + expected injection time" ; + false + (* When we get to level = 1, round = 1, the time to prepare timeout should + not have been called *) + | Baking_state.New_head_proposal {block; _} -> + latest_proposal := Some block ; + let block_round = block.round in + block.shell.level >= stop_level && block_round = stop_round + | _ -> false + end in + run ~config [(1, (module Node_a_hooks)); (1, (module Node_b_hooks))] + +let () = + let open Lwt_result_syntax in + (* Activate a sink to record baker's events *) + let t = lazy (Tezt_sink.activate ()) in + let proto_name = + String.lowercase_ascii Protocol.name + |> String.map (function '-' -> '_' | x -> x) + in + let register_test (title, test) = + Test.register + ~__FILE__ + ~title + ~tags:[proto_name; "baker"; "mockup"; Tag.time_sensitive] + @@ fun () -> + let*! () = Lazy.force t in + let*! r = test () in + match r with + | Ok () -> unit + | Error errs -> Test.fail ~__LOC__ "%a" pp_print_trace errs + in + List.iter + register_test + [ + (Protocol.name ^ ": reaches level 5", test_level_5); + ( Protocol.name ^ ": cannot progress without new head", + test_preattest_on_valid ); + (Protocol.name ^ ": reset delayed pqc", test_reset_delayed_pqc); + (Protocol.name ^ ": scenario t1", test_scenario_t1); + (Protocol.name ^ ": scenario t2", test_scenario_t2); + (Protocol.name ^ ": scenario t3", test_scenario_t3); + (Protocol.name ^ ": scenario t4", test_scenario_t4); + (Protocol.name ^ ": scenario f1", test_scenario_f1); + (Protocol.name ^ ": scenario f2", test_scenario_f2); + (Protocol.name ^ ": scenario m1", test_scenario_m1); + (Protocol.name ^ ": scenario m2", test_scenario_m2); + (Protocol.name ^ ": scenario m3", test_scenario_m3); + (Protocol.name ^ ": scenario m4", test_scenario_m4); + (Protocol.name ^ ": scenario m5", test_scenario_m5); + (Protocol.name ^ ": scenario m6", test_scenario_m6); + (Protocol.name ^ ": scenario m7", test_scenario_m7); + (Protocol.name ^ ": scenario m8", test_scenario_m8); + (Protocol.name ^ ": scenario m9", test_scenario_m9); + (Protocol.name ^ ": scenario m10", test_scenario_m10); + ] diff --git a/src/proto_020_PsParisC/lib_delegate/vdf_helpers.ml b/src/proto_020_PsParisC/lib_delegate/vdf_helpers.ml new file mode 100644 index 000000000000..b3fe451bc1d5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/vdf_helpers.ml @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +let is_in_nonce_revelation_stage ~nonce_revelation_threshold ~(level : Level.t) + = + let cycle_position = level.cycle_position in + Int32.compare cycle_position nonce_revelation_threshold < 0 diff --git a/src/proto_020_PsParisC/lib_delegate/vdf_helpers.mli b/src/proto_020_PsParisC/lib_delegate/vdf_helpers.mli new file mode 100644 index 000000000000..1000c59bece0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_delegate/vdf_helpers.mli @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +(** [is_in_nonce_revelation_stage ~nonce_revelation_threshold ~level] checks + whether [level] is part of the nonce revelation stage of its cycle, which + is defined as the first [nonce_revelation_threshold] blocks of every cycle. + It is used to avoid calling the [Seed_computation] RPC on blocks which are + part of the nonce revelation stage. + *) +val is_in_nonce_revelation_stage : + nonce_revelation_threshold:int32 -> level:Level.t -> bool diff --git a/src/proto_020_PsParisC/lib_injector/dune b/src/proto_020_PsParisC/lib_injector/dune new file mode 100644 index 000000000000..6f6bba969ac9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_injector/dune @@ -0,0 +1,23 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name octez_injector_PtParisB) + (package tezos-injector-019-PtParisB) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-injector + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-base + octez-protocol-019-PtParisB-libs.plugin) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Octez_injector + -open Tezos_client_019_PtParisB + -open Tezos_client_base + -open Tezos_protocol_plugin_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_injector/injector_plugin.ml b/src/proto_020_PsParisC/lib_injector/injector_plugin.ml new file mode 100644 index 000000000000..6c02ee34ba4f --- /dev/null +++ b/src/proto_020_PsParisC/lib_injector/injector_plugin.ml @@ -0,0 +1,442 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context +open Injector_common +open Injector_sigs +open Injector_server +open Injector_server_operation +module Block_cache = + Aches_lwt.Lache.Make_result + (Aches.Rache.Transfer (Aches.Rache.LRU) (Block_hash)) + +module Proto_client = struct + open Tezos_micheline + + type operation = Injector_server_operation.t + + type state = Injector_server.state + + type unsigned_operation = + Tezos_base.Operation.shell_header * packed_contents_list + + let max_operation_data_length = Constants.max_operation_data_length + + let manager_pass = Operation_repr.manager_pass + + let to_manager_operation : t -> packed_manager_operation = function + | Transaction {amount; destination; parameters} -> + let destination = + Contract.of_b58check destination + |> WithExceptions.Result.to_exn_f ~error:(fun _trace -> + Stdlib.failwith + "Injector_plugin.to_manager_operation: invalid destination") + in + let entrypoint, parameters = + match parameters with + | Some {entrypoint; value} -> + let entrypoint = + Entrypoint.of_string_lax entrypoint + |> WithExceptions.Result.to_exn_f ~error:(fun _trace -> + Stdlib.failwith + "Injector_plugin.to_manager_operation: invalid \ + entrypoint") + in + let expr = + Michelson_v1_parser.parse_expression value + |> Micheline_parser.no_parsing_error + |> WithExceptions.Result.to_exn_f ~error:(fun _trace -> + Stdlib.failwith + "Injector_plugin.to_manager_operation: invalid \ + parameters") + in + (entrypoint, Script.lazy_expr expr.expanded) + | None -> (Entrypoint.default, Script.unit_parameter) + in + Manager + (Transaction + { + amount = Tez.of_mutez_exn amount; + destination; + parameters; + entrypoint; + }) + + let of_manager_operation : type kind. kind manager_operation -> t option = + function + | Transaction {amount; parameters; entrypoint; destination} -> + Option.bind (Data_encoding.force_decode parameters) (fun parameters -> + Some + (Transaction + { + amount = Tez.to_mutez amount; + destination = Contract.to_b58check destination; + parameters = + Some + { + value = + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc:true + parameters; + entrypoint = Entrypoint.to_string entrypoint; + }; + })) + | _ -> None + + let manager_operation_size (Manager operation) = + let contents = + Manager_operation + { + source = Signature.Public_key_hash.zero; + operation; + fee = Tez.zero; + counter = Manager_counter.Internal_for_tests.of_int 0; + gas_limit = Gas.Arith.zero; + storage_limit = Z.zero; + } + in + Data_encoding.Binary.length Operation.contents_encoding (Contents contents) + + let operation_size op = manager_operation_size (to_manager_operation op) + + (* The operation size overhead is an upper bound (in practice) of the overhead + that will be added to a manager operation. To compute it we can use any + manager operation (here a revelation), add an overhead with upper bounds as + values (for the fees, limits, counters, etc.) and compare the encoded + operations with respect to their size. + NOTE: This information is only used to pre-select operations from the + injector queue as a candidate batch. *) + let operation_size_overhead = + let dummy_operation = + Reveal + (Signature.Public_key.of_b58check_exn + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") + in + let dummy_contents = + Manager_operation + { + source = Signature.Public_key_hash.zero; + operation = dummy_operation; + fee = Tez.of_mutez_exn 3_000_000L; + counter = Manager_counter.Internal_for_tests.of_int 500_000; + gas_limit = Gas.Arith.integral_of_int_exn 500_000; + storage_limit = Z.of_int 500_000; + } + in + let dummy_size = + Data_encoding.Binary.length + Operation.contents_encoding + (Contents dummy_contents) + in + dummy_size - manager_operation_size (Manager dummy_operation) + + let manager_operation_result_status (type kind) + (op_result : kind Apply_results.manager_operation_result) : + operation_status = + match op_result with + | Applied _ -> Successful + | Backtracked (_, None) -> Unsuccessful Backtracked + | Skipped _ -> Unsuccessful Skipped + | Backtracked (_, Some err) + (* Backtracked because internal operation failed *) + | Failed (_, err) -> + Unsuccessful (Failed (Environment.wrap_tztrace err)) + + let operation_result_status (type kind) + (op_result : kind Apply_results.contents_result) : operation_status = + match op_result with + | Preattestation_result _ -> Successful + | Attestation_result _ -> Successful + | Seed_nonce_revelation_result _ -> Successful + | Vdf_revelation_result _ -> Successful + | Double_attestation_evidence_result _ -> Successful + | Double_preattestation_evidence_result _ -> Successful + | Double_baking_evidence_result _ -> Successful + | Activate_account_result _ -> Successful + | Proposals_result -> Successful + | Ballot_result -> Successful + | Drain_delegate_result _ -> Successful + | Manager_operation_result {operation_result; _} -> + manager_operation_result_status operation_result + + let operation_contents_status (type kind) + (contents : kind Apply_results.contents_result_list) ~index : + operation_status tzresult = + let rec rec_status : + type kind. int -> kind Apply_results.contents_result_list -> _ = + fun n -> function + | Apply_results.Single_result _ when n <> 0 -> + error_with "No operation with index %d" index + | Single_result result -> Ok (operation_result_status result) + | Cons_result (result, _rest) when n = 0 -> + Ok (operation_result_status result) + | Cons_result (_result, rest) -> rec_status (n - 1) rest + in + rec_status index contents + + let operation_status_of_receipt (operation : Protocol.operation_receipt) + ~index : operation_status tzresult = + match (operation : _) with + | No_operation_metadata -> + error_with "Cannot find operation status because metadata is missing" + | Operation_metadata {contents} -> operation_contents_status contents ~index + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6339 *) + (* Don't make multiple calls to [operations_in_pass] RPC *) + let get_block_operations = + let ops_cache = Block_cache.create 32 in + fun cctxt block_hash -> + Block_cache.bind_or_put + ops_cache + block_hash + (fun block_hash -> + let open Lwt_result_syntax in + let+ operations = + Alpha_block_services.Operations.operations_in_pass + cctxt + ~chain:cctxt#chain + ~block:(`Hash (block_hash, 0)) + ~metadata:`Always + manager_pass + in + List.fold_left + (fun acc (op : Alpha_block_services.operation) -> + Operation_hash.Map.add op.hash op acc) + Operation_hash.Map.empty + operations) + Lwt.return + + let operation_status (node_ctxt : state) block_hash operation_hash ~index = + let open Lwt_result_syntax in + let* operations = get_block_operations node_ctxt.cctxt block_hash in + match Operation_hash.Map.find_opt operation_hash operations with + | None -> return_none + | Some operation -> ( + match operation.receipt with + | Empty -> + failwith "Cannot find operation status because metadata is empty" + | Too_large -> + failwith + "Cannot find operation status because metadata is too large" + | Receipt receipt -> + let*? status = operation_status_of_receipt receipt ~index in + return_some status) + + let dummy_sk_uri = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Tezos_signer_backends.Unencrypted.make_sk + @@ Signature.Secret_key.of_b58check_exn + "edsk3UqeiQWXX7NFEY1wUs6J1t2ez5aQ3hEWdqX5Jr5edZiGLW8nZr" + + let simulate_operations cctxt ~force ~source ~src_pk ~successor_level + ~fee_parameter ?safety_guard operations = + let open Lwt_result_syntax in + let fee_parameter : Injection.fee_parameter = + { + minimal_fees = Tez.of_mutez_exn fee_parameter.minimal_fees.mutez; + minimal_nanotez_per_byte = fee_parameter.minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit = + fee_parameter.minimal_nanotez_per_gas_unit; + force_low_fee = fee_parameter.force_low_fee; + fee_cap = Tez.of_mutez_exn fee_parameter.fee_cap.mutez; + burn_cap = Tez.of_mutez_exn fee_parameter.burn_cap.mutez; + } + in + let open Annotated_manager_operation in + let annotated_operations = + List.map + (fun operation -> + let (Manager operation) = to_manager_operation operation in + Annotated_manager_operation + (Injection.prepare_manager_operation + ~fee:Limit.unknown + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + operation)) + operations + in + let (Manager_list annot_op) = + Annotated_manager_operation.manager_of_list annotated_operations + in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let safety_guard = Option.map Gas.Arith.integral_of_int_exn safety_guard in + let*! simulation_result = + Injection.inject_manager_operation + cctxt + ~simulation:true (* Only simulation here *) + ~force + ~chain:cctxt#chain + ~block:(`Head 0) + ~source + ~src_pk + ~src_sk:dummy_sk_uri + (* Use dummy secret key as it is not used by simulation *) + ~successor_level + ~fee:Limit.unknown + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ?safety_guard + ~fee_parameter + annot_op + in + match simulation_result with + | Error trace -> + let exceeds_quota = + TzTrace.fold + (fun exceeds -> function + | Environment.Ecoproto_error + (Gas.Block_quota_exceeded | Gas.Operation_quota_exceeded) -> + true + | _ -> exceeds) + false + trace + in + fail (if exceeds_quota then `Exceeds_quotas trace else `TzError trace) + | Ok (_oph, packed_op, _contents, results) -> + let nb_ops = List.length operations in + let results = Apply_results.to_list (Contents_result_list results) in + (* packed_op can have reveal operations added automatically. *) + let start_index = List.length results - nb_ops in + (* remove extra reveal operations *) + let operations_statuses = + List.fold_left_i + (fun index_in_batch acc (Apply_results.Contents_result result) -> + if index_in_batch < start_index then acc + else + {index_in_batch; status = operation_result_status result} :: acc) + [] + results + |> List.rev + in + let unsigned_operation = + let {shell; protocol_data = Operation_data {contents; signature = _}} + = + packed_op + in + (shell, Contents_list contents) + in + return {operations_statuses; unsigned_operation} + + let sign_operation cctxt src_sk + ((shell, Contents_list contents) as unsigned_op) = + let open Lwt_result_syntax in + let unsigned_bytes = + Data_encoding.Binary.to_bytes_exn Operation.unsigned_encoding unsigned_op + in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let+ signature = + Client_keys.sign + cctxt + ~watermark:Signature.Generic_operation + src_sk + unsigned_bytes + in + let op : packed_operation = + { + shell; + protocol_data = Operation_data {contents; signature = Some signature}; + } + in + Data_encoding.Binary.to_bytes_exn Operation.encoding op + + let time_until_next_block {minimal_block_delay; delay_increment_per_round; _} + (header : Tezos_base.Block_header.shell_header option) = + let open Result_syntax in + match header with + | None -> minimal_block_delay |> Int64.to_int |> Ptime.Span.of_int_s + | Some header -> + let minimal_block_delay = Period.of_seconds_exn minimal_block_delay in + let delay_increment_per_round = + Period.of_seconds_exn delay_increment_per_round + in + let next_level_timestamp = + let* durations = + Round.Durations.create + ~first_round_duration:minimal_block_delay + ~delay_increment_per_round + in + let* predecessor_round = Fitness.round_from_raw header.fitness in + Round.timestamp_of_round + durations + ~predecessor_timestamp:header.timestamp + ~predecessor_round + ~round:Round.zero + in + let next_level_timestamp = + Result.value + next_level_timestamp + ~default: + (WithExceptions.Result.get_ok + ~loc:__LOC__ + Timestamp.(header.timestamp +? minimal_block_delay)) + in + Ptime.diff + (Time.System.of_protocol_exn next_level_timestamp) + (Time.System.now ()) + + let check_fee_parameters {fee_parameters; _} = + let check_value purpose name compare to_string mempool_default value = + if compare mempool_default value > 0 then + error_with + "Bad configuration fee_parameter.%s for %s. It must be at least %s \ + for operations of the injector to be propagated." + name + (Configuration.string_of_purpose purpose) + (to_string mempool_default) + else Ok () + in + let check purpose + { + minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee = _; + fee_cap = _; + burn_cap = _; + } = + let open Result_syntax in + let+ () = + check_value + purpose + "minimal_fees" + Int64.compare + Int64.to_string + (Protocol.Alpha_context.Tez.to_mutez + Plugin.Mempool.default_minimal_fees) + minimal_fees.mutez + and+ () = + check_value + purpose + "minimal_nanotez_per_byte" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_byte + minimal_nanotez_per_byte + and+ () = + check_value + purpose + "minimal_nanotez_per_gas_unit" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_gas_unit + minimal_nanotez_per_gas_unit + in + () + in + check Transaction fee_parameters + + let checks state = check_fee_parameters state +end + +let () = register_proto_client Protocol.hash (module Proto_client) diff --git a/src/proto_020_PsParisC/lib_layer2_utils/dune b/src/proto_020_PsParisC/lib_layer2_utils/dune new file mode 100644 index 000000000000..d721314a5de4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_layer2_utils/dune @@ -0,0 +1,19 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_layer2_utils_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.layer2-utils) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client) + (inline_tests (flags -verbose) (modes native)) + (preprocess (pps ppx_expect)) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_layer2_utils/layer1_services.ml b/src/proto_020_PsParisC/lib_layer2_utils/layer1_services.ml new file mode 100644 index 000000000000..64f23841d330 --- /dev/null +++ b/src/proto_020_PsParisC/lib_layer2_utils/layer1_services.ml @@ -0,0 +1,148 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results +open Protocol_client_context +open Alpha_block_services + +type error += Cannot_read_block_metadata of Block_hash.t + +let () = + register_error_kind + ~id:"cannot_read_receipt_of_block" + ~title:"Cannot read receipt of block from L1" + ~description:"The receipt of a block could not be read." + ~pp:(fun ppf hash -> + Format.fprintf + ppf + "Could not read block receipt for block with hash %a." + Block_hash.pp + hash) + `Temporary + Data_encoding.(obj1 (req "hash" Block_hash.encoding)) + (function Cannot_read_block_metadata hash -> Some hash | _ -> None) + (fun hash -> Cannot_read_block_metadata hash) + +type 'accu successful_operation_processor = { + apply : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind manager_operation -> + 'kind Apply_results.successful_manager_operation_result -> + 'accu; + apply_internal : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind Apply_internal_results.internal_operation -> + 'kind Apply_internal_results.successful_internal_operation_result -> + 'accu; +} + +type 'accu operation_processor = { + apply : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind manager_operation -> + 'kind Apply_results.manager_operation_result -> + 'accu; + apply_internal : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind Apply_internal_results.internal_operation -> + 'kind Apply_internal_results.internal_operation_result -> + 'accu; +} + +let process_manager_operations operations accu f = + let rec on_operation_and_result : + type kind. _ -> kind Apply_results.contents_and_result_list -> _ = + fun accu -> function + | Single_and_result + ( Manager_operation {operation; source; _}, + Manager_operation_result + {operation_result; internal_operation_results; _} ) -> + let accu = f.apply accu ~source operation operation_result in + on_internal_operations accu source internal_operation_results + | Single_and_result (_, _) -> accu + | Cons_and_result + ( Manager_operation {operation; source; _}, + Manager_operation_result + {operation_result; internal_operation_results; _}, + rest ) -> + let accu = f.apply accu ~source operation operation_result in + let accu = + on_internal_operations accu source internal_operation_results + in + on_operation_and_result accu rest + and on_internal_operations accu source internal_operation_results = + let open Apply_internal_results in + List.fold_left + (fun accu (Internal_operation_result (operation, result)) -> + f.apply_internal accu ~source operation result) + accu + internal_operation_results + in + let process_contents accu + ({protocol_data = Operation_data {contents; _}; receipt; _} : operation) = + match receipt with + | Empty | Too_large | Receipt No_operation_metadata -> + (* This should case should not happen between [operations] is supposed + to be retrieved with `force_metadata:true` and assuming that the + tezos node is running in archive mode. *) + assert false + | Receipt (Operation_metadata {contents = results; _}) -> ( + match Apply_results.kind_equal_list contents results with + | Some Eq -> + on_operation_and_result accu + @@ Apply_results.pack_contents_list contents results + | None -> + (* Should not happen *) + assert false) + in + let process_operations = List.fold_left process_contents in + List.fold_left process_operations operations accu + +let process_applied_manager_operations operations accu + (f : _ successful_operation_processor) = + let apply (type kind) accu ~source (operation : kind manager_operation) + (result : kind Apply_results.manager_operation_result) = + match result with + | Applied result -> f.apply accu ~source operation result + | _ -> accu + in + let apply_internal (type kind) accu ~source + (operation : kind Apply_internal_results.internal_operation) + (result : kind Apply_internal_results.internal_operation_result) = + match result with + | Applied result -> f.apply_internal accu ~source operation result + | _ -> accu + in + process_manager_operations operations accu {apply; apply_internal} diff --git a/src/proto_020_PsParisC/lib_layer2_utils/layer1_services.mli b/src/proto_020_PsParisC/lib_layer2_utils/layer1_services.mli new file mode 100644 index 000000000000..4cb30e48b0a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_layer2_utils/layer1_services.mli @@ -0,0 +1,76 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Protocol_client_context.Alpha_block_services + +type error += Cannot_read_block_metadata of Block_hash.t + +type 'accu successful_operation_processor = { + apply : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind manager_operation -> + 'kind Apply_results.successful_manager_operation_result -> + 'accu; + apply_internal : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind Apply_internal_results.internal_operation -> + 'kind Apply_internal_results.successful_internal_operation_result -> + 'accu; +} + +type 'accu operation_processor = { + apply : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind manager_operation -> + 'kind Apply_results.manager_operation_result -> + 'accu; + apply_internal : + 'kind. + 'accu -> + source:public_key_hash -> + 'kind Apply_internal_results.internal_operation -> + 'kind Apply_internal_results.internal_operation_result -> + 'accu; +} + +(** [process_manager_operations accu operations operator] folds over the list of + manager operations in [operations] applying [operator] to transform [accu] + along the way. *) +val process_manager_operations : + 'a -> operation list list -> 'a operation_processor -> 'a + +(** [process_applied_manager_operations accu operations operator] folds over the + list of applied manager operations in [operations] applying [operator] to + transform [accu] along the way. *) +val process_applied_manager_operations : + 'a -> operation list list -> 'a successful_operation_processor -> 'a diff --git a/src/proto_020_PsParisC/lib_parameters/default_parameters.ml b/src/proto_020_PsParisC/lib_parameters/default_parameters.ml new file mode 100644 index 000000000000..a5afdaa30d69 --- /dev/null +++ b/src/proto_020_PsParisC/lib_parameters/default_parameters.ml @@ -0,0 +1,486 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +let seconds_in_a_day = 60 * 60 * 24 + +let seconds_in_a_week = seconds_in_a_day * 7 + +let make_sc_rollup_parameter ~dal_activation_level + ~dal_attested_slots_validity_lag block_time = + (* Maximum number of outbox messages per level. + + WARNING: changing this value impacts the storage size a rollup has to + pay for at origination time. *) + let max_outbox_messages_per_level = 100 in + + (* The commitment period in blocks is about 15 minutes. *) + let commitment_period_in_blocks = 60 * 15 / block_time in + + (* The challenge window is about two weeks. WARNING: changing this + value also impacts [sc_rollup_max_active_outbox_levels]. See + below. *) + let challenge_window_in_blocks = seconds_in_a_week * 2 / block_time in + + (* Number of active levels kept for executing outbox messages. + + WARNING: Changing this value impacts the storage charge for + applying messages from the outbox. It also requires migration for + remapping existing active outbox levels to new indices. *) + let max_active_outbox_levels = Int32.of_int challenge_window_in_blocks in + + (* The timeout period is about a week. It suffers from the same + risk of censorship as {!sc_rollup_challenge_windows_in_blocks} so + we use the same value. *) + let timeout_period_in_blocks = seconds_in_a_week / block_time in + + (* We want to allow a max lookahead in blocks of 4 weeks, so the + rollup can still move forward even if its impossible to cement + commitments. + + As there is a challenge window of 2 weeks, and because the maximum + duration of a game is 2 weeks, the hypothetical maximum time + to cement a block is a month. + + Be careful, this constant has an impact of the maximum cost of + a rollup on the storage: + [maximum_cost_in_storage = + (sc_rollup_max_lookahead_in_blocks / commitment_period) * + max_commitment_storage_size_in_bytes * + cost_per_byte] + + With the current values: + [maximum_cost_in_storage = 348.3 tez] + *) + let max_lookahead_in_blocks = + let seconds_in_a_month = Int32.of_int (seconds_in_a_day * 30) in + let block_time = Int32.of_int block_time in + Int32.div seconds_in_a_month block_time + in + Constants.Parametric. + { + arith_pvm_enable = false; + (* The following value is chosen to prevent spam. *) + origination_size = 6_314; + challenge_window_in_blocks; + commitment_period_in_blocks; + stake_amount = Tez.of_mutez_exn 10_000_000_000L; + max_lookahead_in_blocks; + max_active_outbox_levels; + max_outbox_messages_per_level; + (* The default number of required sections in a dissection *) + number_of_sections_in_dissection = 32; + timeout_period_in_blocks; + (* We store multiple cemented commitments because we want to + allow the execution of outbox messages against cemented + commitments that are older than the last cemented commitment. + The execution of an outbox message is a manager operation, + and manager operations are kept in the mempool for one + hour. Hence we only need to ensure that an outbox message can + be validated against a cemented commitment produced in the + last hour. If we assume that the rollup is operating without + issues, that is no commitments are being refuted and + commitments are published and cemented regularly by one + rollup node, we can expect commitments to be cemented + approximately every 15 minutes, or equivalently we can expect + 5 commitments to be published in one hour (at minutes 0, 15, + 30, 45 and 60). Therefore, we need to keep 5 cemented + commitments to guarantee that the execution of an outbox + operation can always be validated against a cemented + commitment while it is in the mempool. *) + max_number_of_stored_cemented_commitments = 5; + max_number_of_parallel_games = 32; + reveal_activation_level = + { + raw_data = {blake2B = Raw_level.root}; + metadata = Raw_level.root; + dal_page = dal_activation_level; + dal_parameters = dal_activation_level; + dal_attested_slots_validity_lag; + }; + private_enable = true; + riscv_pvm_enable = false; + } + +let default_cryptobox_parameters = + { + Dal.page_size = 3967; + slot_size = 126_944; + redundancy_factor = 8; + number_of_shards = 512; + } + +let default_dal = + Constants.Parametric. + { + feature_enable = true; + incentives_enable = false; + number_of_slots = 32; + attestation_lag = 8; + attestation_threshold = 66; + cryptobox_parameters = default_cryptobox_parameters; + } + +let constants_mainnet : Constants.Parametric.t = + let block_time = 10 in + let consensus_committee_size = 7000 in + let Constants.Generated. + { + consensus_threshold; + issuance_weights = + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + }; + max_slashing_threshold; + } = + Constants.Generated.generate ~consensus_committee_size + in + let dal_activation_level = + if default_dal.feature_enable then Raw_level.succ Raw_level.root + else + (* Deactivate the reveal if the dal is not enabled. *) + (* https://gitlab.com/tezos/tezos/-/issues/5968 + Encoding error with Raw_level + + We set the activation level to [pred max_int] to deactivate + the feature. The [pred] is needed to not trigger an encoding + exception with the value [Int32.int_min] (see tezt/tests/mockup.ml). *) + Raw_level.of_int32_exn Int32.(pred max_int) + in + let dal_attested_slots_validity_lag = + (* A rollup node shouldn't import a page of an attested slot whose attested + level is too far in the past w.r.t. the current level. Importation window + is fixed to 241_920 levels below. It is the number of blocks produced + during 28 days (4 weeks) with a block time of 10 seconds. *) + 241_920 + in + let sc_rollup = + make_sc_rollup_parameter + ~dal_activation_level + ~dal_attested_slots_validity_lag + block_time + in + { + consensus_rights_delay = 2; + blocks_preservation_cycles = 1; + delegate_parameters_activation_delay = 5; + blocks_per_cycle = 24576l; + blocks_per_commitment = 192l; + nonce_revelation_threshold = 768l; + cycles_per_voting_period = 5l; + hard_gas_limit_per_operation = Gas.Arith.(integral_of_int_exn 1_040_000); + hard_gas_limit_per_block = Gas.Arith.(integral_of_int_exn 1_733_333); + (* When reducing blocks time, consider adapting this constant so + the block production's overhead is not too important. *) + proof_of_work_threshold = Int64.(sub (shift_left 1L 48) 1L); + minimal_stake = Tez.(mul_exn one 6_000); + minimal_frozen_stake = Tez.(mul_exn one 600); + (* VDF's difficulty must be a multiple of `nonce_revelation_threshold` times + the block time. At the moment it is equal to 8B = 8000 * 5 * .2M with + - 8000 ~= 768 * 10 that is nonce_revelation_threshold * block time + - .2M ~= number of modular squaring per second on benchmark machine + with 2.8GHz CPU + - 5: security factor (strictly higher than the ratio between highest CPU + clock rate and benchmark machine that is 8.43/2.8 ~= 3 *) + vdf_difficulty = 8_000_000_000L; + origination_size = 257; + issuance_weights = + { + base_total_issued_per_minute; + (* 80.007812 tez/minute *) + baking_reward_fixed_portion_weight; + (* 1/4th of total block rewards *) + baking_reward_bonus_weight; + (* all bonus rewards = fixed rewards *) + attesting_reward_weight; + (* all baking rewards = all attesting rewards *) + seed_nonce_revelation_tip_weight; + (* 1/20480 of block rewards *) + vdf_revelation_tip_weight; + (* 1/20480 of block rewards *) + }; + hard_storage_limit_per_operation = Z.of_int 60_000; + cost_per_byte = Tez.of_mutez_exn 250L; + quorum_min = 20_00l; + quorum_max = 70_00l; + min_proposal_quorum = 5_00l; + liquidity_baking_subsidy = Tez.(mul_exn one 5); + (* 1/2 window size of 2000 blocks with precision of 1_000_000 + for integer computation *) + liquidity_baking_toggle_ema_threshold = 1_000_000_000l; + (* The rationale behind the value of this constant is that an + operation should be considered alive for about one hour: + + minimal_block_delay * max_operations_time_to_live = 3600 + + The unit for this value is a block. + *) + max_operations_time_to_live = 360; + minimal_block_delay = Period.of_seconds_exn (Int64.of_int block_time); + delay_increment_per_round = Period.of_seconds_exn 5L; + consensus_committee_size; + consensus_threshold; + (* 4667 slots *) + minimal_participation_ratio = {numerator = 2; denominator = 3}; + limit_of_delegation_over_baking = 9; + percentage_of_frozen_deposits_slashed_per_double_baking = + Protocol.Percentage.p5; + percentage_of_frozen_deposits_slashed_per_double_attestation = + Protocol.Percentage.p50; + max_slashing_per_block = Protocol.Percentage.p100; + max_slashing_threshold; + (* The `testnet_dictator` should absolutely be None on mainnet *) + testnet_dictator = None; + initial_seed = None; + (* A cache for contract source code and storage. Its size has been + chosen not too exceed 100 000 000 bytes. *) + cache_script_size = 100_000_000; + (* A cache for the stake distribution for all cycles stored at any + moment: consensus_rights_delay + max_slashing_period + 1 = 8 currently. *) + cache_stake_distribution_cycles = 8; + (* One for the sampler state for all cycles stored at any moment (as above). *) + cache_sampler_state_cycles = 8; + dal = default_dal; + sc_rollup; + zk_rollup = + { + enable = false; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3726 + The following constants need to be refined. *) + origination_size = 4_000; + min_pending_to_process = 10; + max_ticket_payload_size = 2_048; + }; + adaptive_issuance = + { + global_limit_of_staking_over_baking = 5; + edge_of_staking_over_delegation = 2; + launch_ema_threshold = 0l; + adaptive_rewards_params = + { + issuance_ratio_final_min = Q.(0_25 // 100_00); + issuance_ratio_final_max = Q.(10 // 100); + issuance_ratio_initial_min = Q.(45 // 1000); + issuance_ratio_initial_max = Q.(55 // 1000); + initial_period = 10; + transition_period = 50; + max_bonus = + Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn + Q.(5 // 100); + (* 0.01% per 1% per day *) + growth_rate = Q.(1 // 100); + center_dz = Q.(1 // 2); + radius_dz = Q.(1 // 50); + }; + activation_vote_enable = true; + autostaking_enable = true; + force_activation = false; + ns_enable = true; + }; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6668 + Enable once at least the following is done: + - Split [allow_forged] into [allow_tickets] and [allow_lazy_storage_id]: #2964 + - Introduce a new Ticket constructor in Michelson: #6643 *) + direct_ticket_spending_enable = false; + } + +let constants_sandbox = + let consensus_committee_size = 256 in + let block_time = 1 in + let Constants.Generated. + {max_slashing_threshold; consensus_threshold = _; issuance_weights} = + Constants.Generated.generate ~consensus_committee_size + in + { + constants_mainnet with + dal = + Constants.Parametric. + { + constants_mainnet.dal with + number_of_slots = 16; + cryptobox_parameters = + {default_cryptobox_parameters with number_of_shards = 256}; + }; + issuance_weights; + blocks_preservation_cycles = 1; + consensus_rights_delay = 2; + delegate_parameters_activation_delay = 2; + blocks_per_cycle = 8l; + blocks_per_commitment = 4l; + nonce_revelation_threshold = 4l; + cycles_per_voting_period = 8l; + proof_of_work_threshold = Int64.(sub (shift_left 1L 62) 1L); + vdf_difficulty = 50_000L; + minimal_block_delay = Period.of_seconds_exn (Int64.of_int block_time); + delay_increment_per_round = Period.one_second; + consensus_committee_size = 256; + consensus_threshold = 0; + max_slashing_threshold; + limit_of_delegation_over_baking = 19; + max_operations_time_to_live = 8; + } + +let constants_test = + let consensus_committee_size = 67 in + let Constants.Generated. + {max_slashing_threshold = _; consensus_threshold; issuance_weights} = + Constants.Generated.generate ~consensus_committee_size + in + { + constants_mainnet with + dal = + Constants.Parametric. + { + constants_mainnet.dal with + number_of_slots = 8; + cryptobox_parameters = + { + default_cryptobox_parameters with + redundancy_factor = 2; + number_of_shards = 64; + }; + }; + issuance_weights; + consensus_rights_delay = 2; + delegate_parameters_activation_delay = 3; + blocks_preservation_cycles = 1; + blocks_per_cycle = 12l; + blocks_per_commitment = 4l; + nonce_revelation_threshold = 4l; + cycles_per_voting_period = 2l; + proof_of_work_threshold = + Int64.(sub (shift_left 1L 62) 1L) (* 1/4 of nonces are accepted *); + vdf_difficulty = 50_000L; + consensus_committee_size; + consensus_threshold (* 17 slots *); + limit_of_delegation_over_baking = + 19 + (* Not 9 so that multiplication by a percentage and + divisions by a limit do not easily get intermingled. *); + max_operations_time_to_live = 8; + (* This has the same slashing behaviour as before P *) + max_slashing_per_block = Protocol.Percentage.p50; + max_slashing_threshold = 1; + } + +let test_commitments = + lazy + (List.map + (fun (bpkh, amount) -> + let blinded_public_key_hash = + Protocol.Blinded_public_key_hash.of_b58check_exn bpkh + in + let amount = Protocol.Alpha_context.Tez.of_mutez_exn amount in + {Protocol.Alpha_context.Commitment.blinded_public_key_hash; amount}) + [ + ("btz1bRL4X5BWo2Fj4EsBdUwexXqgTf75uf1qa", 23932454669343L); + ("btz1SxjV1syBgftgKy721czKi3arVkVwYUFSv", 72954577464032L); + ("btz1LtoNCjiW23txBTenALaf5H6NKF1L3c1gw", 217487035428348L); + ("btz1SUd3mMhEBcWudrn8u361MVAec4WYCcFoy", 4092742372031L); + ("btz1MvBXf4orko1tsGmzkjLbpYSgnwUjEe81r", 17590039016550L); + ("btz1LoDZ3zsjgG3k3cqTpUMc9bsXbchu9qMXT", 26322312350555L); + ("btz1RMfq456hFV5AeDiZcQuZhoMv2dMpb9hpP", 244951387881443L); + ("btz1Y9roTh4A7PsMBkp8AgdVFrqUDNaBE59y1", 80065050465525L); + ("btz1Q1N2ePwhVw5ED3aaRVek6EBzYs1GDkSVD", 3569618927693L); + ("btz1VFFVsVMYHd5WfaDTAt92BeQYGK8Ri4eLy", 9034781424478L); + ]) + +let bootstrap_accounts_strings = + [ + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"; + "edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9"; + "edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV"; + "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU"; + "edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n"; + ] + +let bootstrap_balance = Tez.of_mutez_exn 4_000_000_000_000L + +let compute_accounts = + List.map (fun s -> + let public_key = Signature.Public_key.of_b58check_exn s in + let public_key_hash = Signature.Public_key.hash public_key in + Parameters. + { + public_key_hash; + public_key = Some public_key; + amount = bootstrap_balance; + delegate_to = None; + consensus_key = None; + }) + +let bootstrap_accounts = compute_accounts bootstrap_accounts_strings + +let make_bootstrap_account (pkh, pk, amount, delegate_to, consensus_key) = + Parameters. + { + public_key_hash = pkh; + public_key = Some pk; + amount; + delegate_to; + consensus_key; + } + +let parameters_of_constants ?(bootstrap_accounts = bootstrap_accounts) + ?(bootstrap_contracts = []) ?(bootstrap_smart_rollups = []) + ?(commitments = []) constants = + Parameters. + { + bootstrap_accounts; + bootstrap_contracts; + bootstrap_smart_rollups; + commitments; + constants; + security_deposit_ramp_up_cycles = None; + no_reward_cycles = None; + } + +module Protocol_parameters_overrides = struct + type t = {parameters : Parameters.t; chain_id : Chain_id.t option} + + let encoding = + let open Data_encoding in + conv + (fun {parameters; chain_id} -> (parameters, chain_id)) + (fun (parameters, chain_id) -> {parameters; chain_id}) + (merge_objs Parameters.encoding (obj1 (opt "chain_id" Chain_id.encoding))) +end + +let json_of_parameters ?chain_id parameters = + Data_encoding.Json.construct + Protocol_parameters_overrides.encoding + Protocol_parameters_overrides.{parameters; chain_id} + +module Internal_for_tests = struct + let make_sc_rollup_parameter = make_sc_rollup_parameter +end diff --git a/src/proto_020_PsParisC/lib_parameters/default_parameters.mli b/src/proto_020_PsParisC/lib_parameters/default_parameters.mli new file mode 100644 index 000000000000..0dd084324d2b --- /dev/null +++ b/src/proto_020_PsParisC/lib_parameters/default_parameters.mli @@ -0,0 +1,62 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +val constants_mainnet : Constants.Parametric.t + +val constants_sandbox : Constants.Parametric.t + +val constants_test : Constants.Parametric.t + +val test_commitments : Commitment.t list lazy_t + +val make_bootstrap_account : + Signature.public_key_hash + * Signature.public_key + * Tez.t + * Signature.public_key_hash option + * Signature.public_key option -> + Parameters.bootstrap_account + +val parameters_of_constants : + ?bootstrap_accounts:Parameters.bootstrap_account list -> + ?bootstrap_contracts:Parameters.bootstrap_contract list -> + ?bootstrap_smart_rollups:Parameters.bootstrap_smart_rollup list -> + ?commitments:Commitment.t list -> + Constants.Parametric.t -> + Parameters.t + +val json_of_parameters : + ?chain_id:Chain_id.t -> Parameters.t -> Data_encoding.json + +module Internal_for_tests : sig + val make_sc_rollup_parameter : + dal_activation_level:Raw_level.t -> + dal_attested_slots_validity_lag:int -> + int -> + Constants.Parametric.sc_rollup +end diff --git a/src/proto_020_PsParisC/lib_parameters/dune b/src/proto_020_PsParisC/lib_parameters/dune new file mode 100644 index 000000000000..cd12c132259a --- /dev/null +++ b/src/proto_020_PsParisC/lib_parameters/dune @@ -0,0 +1,61 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_protocol_019_PtParisB_parameters) + (public_name tezos-protocol-019-PtParisB.parameters) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-proto-libs.protocol-environment + tezos-protocol-019-PtParisB.protocol) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB) + (modules (:standard \ gen))) + +(executable + (name gen) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.parameters + tezos-protocol-019-PtParisB.protocol) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp) + (-linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_019_PtParisB) + (modules gen)) + +(rule + (targets sandbox-parameters.json) + (deps gen.exe) + (action (run %{deps} --sandbox))) + +(rule + (targets test-parameters.json) + (deps gen.exe) + (action (run %{deps} --test))) + +(rule + (targets mainnet-parameters.json) + (deps gen.exe) + (action (run %{deps} --mainnet))) + +(rule + (targets mainnet-with-chain-id-parameters.json) + (deps gen.exe) + (action (run %{deps} --mainnet-with-chain-id))) + +(install + (package tezos-protocol-019-PtParisB) + (section lib) + (files + sandbox-parameters.json test-parameters.json mainnet-parameters.json + mainnet-with-chain-id-parameters.json)) diff --git a/src/proto_020_PsParisC/lib_parameters/gen.ml b/src/proto_020_PsParisC/lib_parameters/gen.ml new file mode 100644 index 000000000000..68b50088d635 --- /dev/null +++ b/src/proto_020_PsParisC/lib_parameters/gen.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Prints the json encoding of the parametric constants of protocol alpha. + $ dune utop src/proto_alpha/lib_protocol/test/helpers/ constants.ml +*) + +let () = + let print_usage_and_fail s = + Printf.eprintf + "Usage: %s [ --sandbox | --test | --mainnet | --mainnet-with-chain-id ]" + Sys.argv.(0) ; + raise (Invalid_argument s) + in + let dump ?chain_id parameters file = + let str = + Data_encoding.Json.to_string + (Default_parameters.json_of_parameters ?chain_id parameters) + in + let fd = open_out file in + output_string fd str ; + close_out fd + in + if Array.length Sys.argv < 2 then print_usage_and_fail "" + else + match Sys.argv.(1) with + | "--sandbox" -> + dump + Default_parameters.(parameters_of_constants constants_sandbox) + "sandbox-parameters.json" + | "--test" -> + dump + Default_parameters.( + parameters_of_constants + ~commitments:(Lazy.force test_commitments) + constants_sandbox) + "test-parameters.json" + | "--mainnet" -> + dump + Default_parameters.(parameters_of_constants constants_mainnet) + "mainnet-parameters.json" + | "--mainnet-with-chain-id" -> + dump + ~chain_id:Protocol.Alpha_context.Constants.mainnet_id + Default_parameters.(parameters_of_constants constants_mainnet) + "mainnet-with-chain-id-parameters.json" + | s -> print_usage_and_fail s diff --git a/src/proto_020_PsParisC/lib_plugin/RPC.ml b/src/proto_020_PsParisC/lib_plugin/RPC.ml new file mode 100644 index 000000000000..9183748aa6d7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/RPC.ml @@ -0,0 +1,4473 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Environment +open Alpha_context + +type version = Version_0 | Version_1 + +let string_of_version = function Version_0 -> "0" | Version_1 -> "1" + +let version_of_string = function + | "0" -> Ok Version_0 + | "1" -> Ok Version_1 + | _ -> Error "Cannot parse version (supported versions \"0\" and \"1\")" + +let default_operations_version = Version_1 + +let version_arg = + let open RPC_arg in + make + ~descr: + "Supported RPC versions are version '1' (default) that will output \ + \"attestation\" in the \"kind\" field and version '0' (deprecated) that \ + will output \"endorsement\"" + ~name:"version" + ~destruct:version_of_string + ~construct:string_of_version + () + +(* This function creates an encoding that use the [latest_encoding] in binary + and that can use [latest_encoding] and any [old_encodings] in JSON. The + version value is only used to decide which encoding to use in JSON. *) +let encoding_versioning ~encoding_name ~latest_encoding ~old_encodings = + let open Data_encoding in + let make_case ~version ~encoding = + case + ~title: + (Format.sprintf + "%s_encoding_v%s" + encoding_name + (string_of_version version)) + Json_only + encoding + (function v, value when v == version -> Some value | _v, _value -> None) + (fun value -> (version, value)) + in + let latest_version, latest_encoding = latest_encoding in + splitted + ~binary: + (conv + (fun (_, value) -> value) + (fun value -> (latest_version, value)) + latest_encoding) + ~json: + (union + (make_case ~version:latest_version ~encoding:latest_encoding + :: List.map + (fun (version, encoding) -> make_case ~version ~encoding) + old_encodings)) + +(** The assumed number of blocks between operation-creation time and + the actual time when the operation is included in a block. *) +let default_operation_inclusion_latency = 3 + +let path = RPC_path.(open_root / "helpers") + +let elab_conf = + Script_ir_translator_config.make + ~keep_extra_types_for_interpreter_logging:true + +module Registration = struct + let patched_services = + ref (RPC_directory.empty : Updater.rpc_context RPC_directory.t) + + let register0_fullctxt ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.register ~chunked !patched_services s (fun ctxt q i -> + let* ctxt = Services_registration.rpc_init ctxt `Head_level in + f ctxt q i) + + let register0 ~chunked s f = + register0_fullctxt ~chunked s (fun {context; _} -> f context) + + let register0_fullctxt_successor_level ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.register ~chunked !patched_services s (fun ctxt q i -> + let mode = + if q#successor_level then `Successor_level else `Head_level + in + let* ctxt = Services_registration.rpc_init ctxt mode in + f ctxt q i) + + let register0_successor_level ~chunked s f = + register0_fullctxt_successor_level ~chunked s (fun {context; _} -> + f context) + + let register0_noctxt ~chunked s f = + patched_services := + RPC_directory.register ~chunked !patched_services s (fun _ q i -> f q i) + + let opt_register0_fullctxt ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.opt_register ~chunked !patched_services s (fun ctxt q i -> + let* ctxt = Services_registration.rpc_init ctxt `Head_level in + f ctxt q i) + + let opt_register0 ~chunked s f = + opt_register0_fullctxt ~chunked s (fun {context; _} -> f context) + + let register1_fullctxt ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.register + ~chunked + !patched_services + s + (fun (ctxt, arg) q i -> + let* ctxt = Services_registration.rpc_init ctxt `Head_level in + f ctxt arg q i) + + let opt_register1_fullctxt ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.opt_register + ~chunked + !patched_services + s + (fun (ctxt, arg) q i -> + let* ctxt = Services_registration.rpc_init ctxt `Head_level in + f ctxt arg q i) + + let register1 ~chunked s f = + register1_fullctxt ~chunked s (fun {context; _} x -> f context x) + + let opt_register1 ~chunked s f = + opt_register1_fullctxt ~chunked s (fun {context; _} x -> f context x) + + let register2_fullctxt ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.register + ~chunked + !patched_services + s + (fun ((ctxt, arg1), arg2) q i -> + let* ctxt = Services_registration.rpc_init ctxt `Head_level in + f ctxt arg1 arg2 q i) + + let register2 ~chunked s f = + register2_fullctxt ~chunked s (fun {context; _} a1 a2 q i -> + f context a1 a2 q i) + + let register3_fullctxt ~chunked s f = + let open Lwt_result_syntax in + patched_services := + RPC_directory.register + ~chunked + !patched_services + s + (fun (((ctxt, arg1), arg2), arg3) q i -> + let* ctxt = Services_registration.rpc_init ctxt `Head_level in + f ctxt arg1 arg2 arg3 q i) + + let register3 ~chunked s f = + register3_fullctxt ~chunked s (fun {context; _} a1 a2 a3 q i -> + f context a1 a2 a3 q i) +end + +let unparsing_mode_encoding = + let open Script_ir_unparser in + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + (Tag 0) + ~title:"Readable" + (constant "Readable") + (function Readable -> Some () | Optimized | Optimized_legacy -> None) + (fun () -> Readable); + case + (Tag 1) + ~title:"Optimized" + (constant "Optimized") + (function Optimized -> Some () | Readable | Optimized_legacy -> None) + (fun () -> Optimized); + case + (Tag 2) + ~title:"Optimized_legacy" + (constant "Optimized_legacy") + (function Optimized_legacy -> Some () | Readable | Optimized -> None) + (fun () -> Optimized_legacy); + ] + +module Scripts = struct + module S = struct + open Data_encoding + + let path = RPC_path.(path / "scripts") + + type other_contract_description = { + address : Contract_hash.t; + ty : Script.expr; + } + + let other_contracts_encoding = + list + (conv + (fun {address; ty} -> (address, ty)) + (fun (address, ty) -> {address; ty}) + (obj2 + (req "address" Contract_hash.encoding) + (req "type" Script.expr_encoding))) + + type extra_big_map_description = { + id : Big_map.Id.t; + kty : Script.expr; + vty : Script.expr; + items : Script.expr; + } + + let extra_big_maps_encoding = + list + (conv + (fun {id; kty; vty; items} -> (id, kty, vty, items)) + (fun (id, kty, vty, items) -> {id; kty; vty; items}) + (obj4 + (req "id" Big_map.Id.encoding) + (req "key_type" Script.expr_encoding) + (req "val_type" Script.expr_encoding) + (req "map_literal" Script.expr_encoding))) + + let run_code_input_encoding = + merge_objs + (obj10 + (req "script" Script.expr_encoding) + (req "storage" Script.expr_encoding) + (req "input" Script.expr_encoding) + (req "amount" Tez.encoding) + (opt "balance" Tez.encoding) + (req "chain_id" Chain_id.encoding) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/710 + Rename the "source" field into "sender" *) + (opt "source" Contract.encoding) + (opt "payer" Contract.implicit_encoding) + (opt "self" Contract.originated_encoding) + (dft "entrypoint" Entrypoint.simple_encoding Entrypoint.default)) + (obj6 + (opt "unparsing_mode" unparsing_mode_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (opt "now" Script_timestamp.encoding) + (opt "level" Script_int.n_encoding) + (opt "other_contracts" other_contracts_encoding) + (opt "extra_big_maps" extra_big_maps_encoding)) + + let run_code_output_encoding = + conv + (fun (storage, operations, lazy_storage_diff) -> + (storage, operations, lazy_storage_diff)) + (fun (storage, operations, lazy_storage_diff) -> + (storage, operations, lazy_storage_diff)) + (obj3 + (req "storage" Script.expr_encoding) + (req + "operations" + (list Apply_internal_results.internal_operation_encoding)) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + + let trace_code_input_encoding = run_code_input_encoding + + let trace_encoding : Script_typed_ir.execution_trace encoding = + def "scripted.trace" @@ list + @@ obj3 + (req "location" Script.location_encoding) + (req "gas" Gas.Arith.z_fp_encoding) + (req "stack" (list Script.expr_encoding)) + + let trace_code_output_encoding = + conv + (fun (storage, operations, trace, lazy_storage_diff) -> + (storage, operations, trace, lazy_storage_diff)) + (fun (storage, operations, trace, lazy_storage_diff) -> + (storage, operations, trace, lazy_storage_diff)) + (obj4 + (req "storage" Script.expr_encoding) + (req + "operations" + (list Apply_internal_results.internal_operation_encoding)) + (req "trace" trace_encoding) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + + let stack_encoding = + list + (obj2 + (req "type" Script.expr_encoding) + (req "val" Script.expr_encoding)) + + let run_instr_input_encoding = + merge_objs + (obj10 + (req "input" stack_encoding) + (req "code" Script.expr_encoding) + (req "chain_id" Chain_id.encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (opt "now" Script_timestamp.encoding) + (opt "level" Script_int.n_encoding) + (opt "sender" Contract.encoding) + (opt "source" Contract.implicit_encoding) + (opt "self" Contract.originated_encoding) + (opt "parameter" Script.expr_encoding)) + (obj6 + (req "amount" Tez.encoding) + (opt "balance" Tez.encoding) + (opt "other_contracts" other_contracts_encoding) + (opt "big_maps" extra_big_maps_encoding) + (opt "unparsing_mode" unparsing_mode_encoding) + (dft "legacy" bool false)) + + let run_instr_output_encoding = + obj2 (req "output" stack_encoding) (req "gas" Gas.encoding) + + let run_tzip4_view_encoding = + let open Data_encoding in + merge_objs + (obj10 + (req "contract" Contract.originated_encoding) + (req "entrypoint" Entrypoint.simple_encoding) + (req "input" Script.expr_encoding) + (req "chain_id" Chain_id.encoding) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/710 + Rename the "source" field into "sender" *) + (opt "source" Contract.encoding) + (opt "payer" Contract.implicit_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (req "unparsing_mode" unparsing_mode_encoding) + (opt "now" Script_timestamp.encoding) + (opt "level" Script_int.n_encoding)) + (obj2 + (opt "other_contracts" other_contracts_encoding) + (opt "extra_big_maps" extra_big_maps_encoding)) + + let run_script_view_encoding = + let open Data_encoding in + merge_objs + (obj10 + (req "contract" Contract.originated_encoding) + (req "view" (string Plain)) + (req "input" Script.expr_encoding) + (dft "unlimited_gas" bool false) + (req "chain_id" Chain_id.encoding) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/710 + Rename the "source" field into "sender" *) + (opt "source" Contract.encoding) + (opt "payer" Contract.implicit_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (req "unparsing_mode" unparsing_mode_encoding) + (opt "now" Script_timestamp.encoding)) + (obj3 + (opt "level" Script_int.n_encoding) + (opt "other_contracts" other_contracts_encoding) + (opt "extra_big_maps" extra_big_maps_encoding)) + + let normalize_stack_input_encoding = + obj5 + (req "input" stack_encoding) + (req "unparsing_mode" unparsing_mode_encoding) + (dft "legacy" bool false) + (opt "other_contracts" other_contracts_encoding) + (opt "extra_big_maps" extra_big_maps_encoding) + + let normalize_stack_output_encoding = obj1 (req "output" stack_encoding) + + let run_code = + RPC_service.post_service + ~description:"Run a Michelson script in the current context" + ~query:RPC_query.empty + ~input:run_code_input_encoding + ~output:run_code_output_encoding + RPC_path.(path / "run_code") + + let trace_code = + RPC_service.post_service + ~description: + "Run a Michelson script in the current context, keeping a trace" + ~query:RPC_query.empty + ~input:trace_code_input_encoding + ~output:trace_code_output_encoding + RPC_path.(path / "trace_code") + + let run_tzip4_view = + RPC_service.post_service + ~description: + "Simulate a call to a view following the TZIP-4 standard. See \ + https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-4/tzip-4.md#view-entrypoints." + ~input:run_tzip4_view_encoding + ~output:(obj1 (req "data" Script.expr_encoding)) + ~query:RPC_query.empty + (* This path should be deprecated in the future *) + RPC_path.(path / "run_view") + + let run_script_view = + RPC_service.post_service + ~description:"Simulate a call to a michelson view" + ~input:run_script_view_encoding + ~output:(obj1 (req "data" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(path / "run_script_view") + + let run_instr = + RPC_service.post_service + ~description:"Run a single Michelson instruction" + ~query:RPC_query.empty + ~input:run_instr_input_encoding + ~output:run_instr_output_encoding + RPC_path.(path / "run_instruction") + + let typecheck_code = + RPC_service.post_service + ~description:"Typecheck a piece of code in the current context" + ~query:RPC_query.empty + ~input: + (obj4 + (req "program" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (dft "legacy" bool false) + (dft "show_types" bool true)) + ~output: + (obj2 + (req "type_map" Script_tc_errors_registration.type_map_enc) + (req "gas" Gas.encoding)) + RPC_path.(path / "typecheck_code") + + let script_size = + RPC_service.post_service + ~description:"Compute the size of a script in the current context" + ~query:RPC_query.empty + ~input: + (obj4 + (req "program" Script.expr_encoding) + (req "storage" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (dft "legacy" bool false)) + ~output:(obj1 (req "script_size" int31)) + RPC_path.(path / "script_size") + + let typecheck_data = + RPC_service.post_service + ~description: + "Check that some data expression is well formed and of a given type \ + in the current context" + ~query:RPC_query.empty + ~input: + (obj4 + (req "data" Script.expr_encoding) + (req "type" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding) + (dft "legacy" bool false)) + ~output:(obj1 (req "gas" Gas.encoding)) + RPC_path.(path / "typecheck_data") + + let pack_data = + RPC_service.post_service + ~description: + "Computes the serialized version of some data expression using the \ + same algorithm as script instruction PACK" + ~input: + (obj3 + (req "data" Script.expr_encoding) + (req "type" Script.expr_encoding) + (opt "gas" Gas.Arith.z_integral_encoding)) + ~output:(obj2 (req "packed" (bytes Hex)) (req "gas" Gas.encoding)) + ~query:RPC_query.empty + RPC_path.(path / "pack_data") + + let normalize_data = + RPC_service.post_service + ~description: + "Normalizes some data expression using the requested unparsing mode" + ~input: + (obj6 + (req "data" Script.expr_encoding) + (req "type" Script.expr_encoding) + (req "unparsing_mode" unparsing_mode_encoding) + (dft "legacy" bool false) + (opt "other_contracts" other_contracts_encoding) + (opt "extra_big_maps" extra_big_maps_encoding)) + ~output:(obj1 (req "normalized" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(path / "normalize_data") + + let normalize_stack = + RPC_service.post_service + ~description: + "Normalize a Michelson stack using the requested unparsing mode" + ~query:RPC_query.empty + ~input:normalize_stack_input_encoding + ~output:normalize_stack_output_encoding + RPC_path.(path / "normalize_stack") + + let normalize_script = + RPC_service.post_service + ~description: + "Normalizes a Michelson script using the requested unparsing mode" + ~input: + (obj2 + (req "script" Script.expr_encoding) + (req "unparsing_mode" unparsing_mode_encoding)) + ~output:(obj1 (req "normalized" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(path / "normalize_script") + + let normalize_type = + RPC_service.post_service + ~description: + "Normalizes some Michelson type by expanding `pair a b c` as `pair a \ + (pair b c)" + ~input:(obj1 (req "type" Script.expr_encoding)) + ~output:(obj1 (req "normalized" Script.expr_encoding)) + ~query:RPC_query.empty + RPC_path.(path / "normalize_type") + + let run_operation_query = + let open RPC_query in + query (fun version -> + object + method version = version + end) + |+ field "version" version_arg default_operations_version (fun t -> + t#version) + |> seal + + let operations_encodings = + union + [ + case + ~title:"operations_encoding" + (Tag 0) + Operation.encoding + Option.some + Fun.id; + case + ~title:"operations_encoding_with_legacy_attestation_name" + Json_only + Operation.encoding_with_legacy_attestation_name + Option.some + Fun.id; + ] + + let run_operation_output_encoding = + encoding_versioning + ~encoding_name:"run_operation_output" + ~latest_encoding: + (Version_1, Apply_results.operation_data_and_metadata_encoding) + ~old_encodings: + [ + ( Version_0, + Apply_results + .operation_data_and_metadata_encoding_with_legacy_attestation_name + ); + ] + + let run_operation = + RPC_service.post_service + ~description: + "Run an operation with the context of the given block and without \ + signature checks. Return the operation application result, \ + including the consumed gas. This RPC does not support consensus \ + operations." + ~query:run_operation_query + ~input: + (obj2 + (req "operation" operations_encodings) + (req "chain_id" Chain_id.encoding)) + ~output:run_operation_output_encoding + RPC_path.(path / "run_operation") + + let simulate_query = + let open RPC_query in + query (fun version successor_level -> + object + method version = version + + method successor_level = successor_level + end) + |+ field "version" version_arg default_operations_version (fun t -> + t#version) + |+ flag + ~descr: + "If true, the simulation is done on the successor level of the \ + current context." + "successor_level" + (fun t -> t#successor_level) + |> seal + + let simulate_operation = + RPC_service.post_service + ~description: + "Simulate running an operation at some future moment (based on the \ + number of blocks given in the `latency` argument), and return the \ + operation application result. The result is the same as \ + run_operation except for the consumed gas, which depends on the \ + contents of the cache at that future moment. This RPC estimates \ + future gas consumption by trying to predict the state of the cache \ + using some heuristics." + ~query:simulate_query + ~input: + (obj4 + (opt "blocks_before_activation" int32) + (req "operation" operations_encodings) + (req "chain_id" Chain_id.encoding) + (dft "latency" int16 default_operation_inclusion_latency)) + ~output:run_operation_output_encoding + RPC_path.(path / "simulate_operation") + + let entrypoint_type = + RPC_service.post_service + ~description:"Return the type of the given entrypoint" + ~query:RPC_query.empty + ~input: + (obj2 + (req "script" Script.expr_encoding) + (dft "entrypoint" Entrypoint.simple_encoding Entrypoint.default)) + ~output:(obj1 (req "entrypoint_type" Script.expr_encoding)) + RPC_path.(path / "entrypoint") + + let list_entrypoints = + RPC_service.post_service + ~description:"Return the list of entrypoints of the given script" + ~query:RPC_query.empty + ~input:(obj1 (req "script" Script.expr_encoding)) + ~output: + (obj2 + (dft + "unreachable" + (Data_encoding.list + (obj1 + (req + "path" + (Data_encoding.list + Michelson_v1_primitives.prim_encoding)))) + []) + (req "entrypoints" (assoc Script.expr_encoding))) + RPC_path.(path / "entrypoints") + end + + module type UNPARSING_MODE = sig + val unparsing_mode : Script_ir_unparser.unparsing_mode + end + + module Traced_interpreter (Unparsing_mode : UNPARSING_MODE) = struct + type log_element = + | Log : + context + * Script.location + * ('a * 's) + * ('a, 's) Script_typed_ir.stack_ty + -> log_element + + let unparse_stack ctxt (stack, stack_ty) = + let open Lwt_result_syntax in + (* We drop the gas limit as this function is only used for debugging/errors. *) + let ctxt = Gas.set_unlimited ctxt in + let rec unparse_stack : + type a s. + (a, s) Script_typed_ir.stack_ty * (a * s) -> + Script.expr list Environment.Error_monad.tzresult Lwt.t = function + | Bot_t, (EmptyCell, EmptyCell) -> return_nil + | Item_t (ty, rest_ty), (v, rest) -> + let* data, _ctxt = + Script_ir_translator.unparse_data + ctxt + Unparsing_mode.unparsing_mode + ty + v + in + let+ rest = unparse_stack (rest_ty, rest) in + data :: rest + in + unparse_stack (stack_ty, stack) + + let trace_logger ctxt : Script_typed_ir.logger = + let open Lwt_result_syntax in + Script_interpreter_logging.make + (module struct + let log : log_element list ref = ref [] + + let log_interp _ ctxt loc sty stack = + log := Log (ctxt, loc, stack, sty) :: !log + + let log_entry _ _ctxt _loc _sty _stack = () + + let log_exit _ ctxt loc sty stack = + log := Log (ctxt, loc, stack, sty) :: !log + + let log_control _ = () + + let get_log () = + let+ _ctxt, res = + List.fold_left_es + (fun (old_ctxt, l) (Log (ctxt, loc, stack, stack_ty)) -> + let consumed_gas = Gas.consumed ~since:old_ctxt ~until:ctxt in + let+ stack = + Environment.Error_monad.trace + Plugin_errors.Cannot_serialize_log + (unparse_stack ctxt (stack, stack_ty)) + in + (ctxt, (loc, consumed_gas, stack) :: l)) + (ctxt, []) + (List.rev !log) + in + Some (List.rev res) + end) + + let execute ctxt step_constants ~script ~entrypoint ~parameter = + let open Lwt_result_syntax in + let logger = trace_logger ctxt in + let* res = + Script_interpreter.execute + ~logger + ~cached_script:None + ctxt + Unparsing_mode.unparsing_mode + step_constants + ~script + ~entrypoint + ~parameter + ~internal:true + in + let+ trace = logger.get_log () in + let trace = Option.value ~default:[] trace in + (res, trace) + end + + let typecheck_data : + legacy:bool -> + context -> + Script.expr * Script.expr -> + context Environment.Error_monad.tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~legacy ctxt (data, exp_ty) -> + let*? Ex_ty exp_ty, ctxt = + Environment.Error_monad.record_trace + (Script_tc_errors.Ill_formed_type (None, exp_ty, 0)) + (Script_ir_translator.parse_passable_ty + ctxt + ~legacy + (Micheline.root exp_ty)) + in + let+ _, ctxt = + Environment.Error_monad.trace_eval + (fun () -> + let exp_ty = Script_ir_unparser.serialize_ty_for_error exp_ty in + Script_tc_errors.Ill_typed_data (None, data, exp_ty)) + (let allow_forged_tickets = true in + let allow_forged_lazy_storage_id = + true + (* Safe since we ignore the value afterwards. *) + in + Script_ir_translator.parse_data + ctxt + ~elab_conf:(elab_conf ~legacy ()) + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + exp_ty + (Micheline.root data)) + in + ctxt + + module Unparse_types = struct + (* Same as the unparsing functions for types in Script_ir_translator but + does not consume gas and never folds (pair a (pair b c)) *) + + open Micheline + open Michelson_v1_primitives + open Script_typed_ir + + let unparse_memo_size ~loc memo_size = + let z = Alpha_context.Sapling.Memo_size.unparse_to_z memo_size in + Int (loc, z) + + let rec unparse_ty : + type a ac loc. + loc:loc -> (a, ac) ty -> (loc, Script.prim) Micheline.node = + fun ~loc ty -> + let return (name, args, annot) = Prim (loc, name, args, annot) in + match ty with + | Unit_t -> return (T_unit, [], []) + | Int_t -> return (T_int, [], []) + | Nat_t -> return (T_nat, [], []) + | Signature_t -> return (T_signature, [], []) + | String_t -> return (T_string, [], []) + | Bytes_t -> return (T_bytes, [], []) + | Mutez_t -> return (T_mutez, [], []) + | Bool_t -> return (T_bool, [], []) + | Key_hash_t -> return (T_key_hash, [], []) + | Key_t -> return (T_key, [], []) + | Timestamp_t -> return (T_timestamp, [], []) + | Address_t -> return (T_address, [], []) + | Operation_t -> return (T_operation, [], []) + | Chain_id_t -> return (T_chain_id, [], []) + | Never_t -> return (T_never, [], []) + | Bls12_381_g1_t -> return (T_bls12_381_g1, [], []) + | Bls12_381_g2_t -> return (T_bls12_381_g2, [], []) + | Bls12_381_fr_t -> return (T_bls12_381_fr, [], []) + | Contract_t (ut, _meta) -> + let t = unparse_ty ~loc ut in + return (T_contract, [t], []) + | Pair_t (utl, utr, _meta, _) -> + let annot = [] in + let tl = unparse_ty ~loc utl in + let tr = unparse_ty ~loc utr in + return (T_pair, [tl; tr], annot) + | Or_t (utl, utr, _meta, _) -> + let annot = [] in + let tl = unparse_ty ~loc utl in + let tr = unparse_ty ~loc utr in + return (T_or, [tl; tr], annot) + | Lambda_t (uta, utr, _meta) -> + let ta = unparse_ty ~loc uta in + let tr = unparse_ty ~loc utr in + return (T_lambda, [ta; tr], []) + | Option_t (ut, _meta, _) -> + let annot = [] in + let ut = unparse_ty ~loc ut in + return (T_option, [ut], annot) + | List_t (ut, _meta) -> + let t = unparse_ty ~loc ut in + return (T_list, [t], []) + | Ticket_t (ut, _meta) -> + let t = unparse_ty ~loc ut in + return (T_ticket, [t], []) + | Set_t (ut, _meta) -> + let t = unparse_ty ~loc ut in + return (T_set, [t], []) + | Map_t (uta, utr, _meta) -> + let ta = unparse_ty ~loc uta in + let tr = unparse_ty ~loc utr in + return (T_map, [ta; tr], []) + | Big_map_t (uta, utr, _meta) -> + let ta = unparse_ty ~loc uta in + let tr = unparse_ty ~loc utr in + return (T_big_map, [ta; tr], []) + | Sapling_transaction_t memo_size -> + return (T_sapling_transaction, [unparse_memo_size ~loc memo_size], []) + | Sapling_transaction_deprecated_t memo_size -> + return + ( T_sapling_transaction_deprecated, + [unparse_memo_size ~loc memo_size], + [] ) + | Sapling_state_t memo_size -> + return (T_sapling_state, [unparse_memo_size ~loc memo_size], []) + | Chest_t -> return (T_chest, [], []) + | Chest_key_t -> return (T_chest_key, [], []) + end + + module Normalize_stack = struct + type ex_stack = + | Ex_stack : ('a, 's) Script_typed_ir.stack_ty * 'a * 's -> ex_stack + + let rec parse_stack : + context -> + legacy:bool -> + (Script.node * Script.node) list -> + (ex_stack * context) Environment.Error_monad.tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt ~legacy l -> + match l with + | [] -> return (Ex_stack (Bot_t, EmptyCell, EmptyCell), ctxt) + | (ty_node, data_node) :: l -> + let*? Ex_ty ty, ctxt = + Script_ir_translator.parse_ty + ctxt + ~legacy + ~allow_lazy_storage:true + ~allow_operation:true + ~allow_contract:true + ~allow_ticket:true + ty_node + in + let elab_conf = elab_conf ~legacy () in + let* x, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + ty + data_node + in + let+ Ex_stack (sty, y, st), ctxt = parse_stack ctxt ~legacy l in + (Ex_stack (Item_t (ty, sty), x, (y, st)), ctxt) + + let rec unparse_stack : + type a s. + context -> + Script_ir_unparser.unparsing_mode -> + (a, s) Script_typed_ir.stack_ty -> + a -> + s -> + ((Script.expr * Script.expr) list * context) + Environment.Error_monad.tzresult + Lwt.t = + let open Lwt_result_syntax in + let loc = Micheline.dummy_location in + fun ctxt unparsing_mode sty x st -> + match (sty, x, st) with + | Bot_t, EmptyCell, EmptyCell -> return ([], ctxt) + | Item_t (ty, sty), x, (y, st) -> + let*? ty_node, ctxt = Script_ir_unparser.unparse_ty ~loc ctxt ty in + let* data_node, ctxt = + Script_ir_translator.unparse_data ctxt unparsing_mode ty x + in + let+ l, ctxt = unparse_stack ctxt unparsing_mode sty y st in + ((Micheline.strip_locations ty_node, data_node) :: l, ctxt) + end + + let rec pp_instr_name : + type a b c d. + Format.formatter -> (a, b, c, d) Script_typed_ir.kinstr -> unit = + let open Script_typed_ir in + let open Format in + fun fmt -> function + | IDrop _ -> pp_print_string fmt "DROP" + | IDup _ -> pp_print_string fmt "DUP" + | ISwap _ -> pp_print_string fmt "SWAP" + | IPush _ -> pp_print_string fmt "PUSH" + | IUnit _ -> pp_print_string fmt "UNIT" + | ICons_pair _ -> pp_print_string fmt "PAIR" + | ICar _ -> pp_print_string fmt "CAR" + | ICdr _ -> pp_print_string fmt "CDR" + | IUnpair _ -> pp_print_string fmt "UNPAIR" + | ICons_some _ -> pp_print_string fmt "SOME" + | ICons_none _ -> pp_print_string fmt "NONE" + | IIf_none _ -> pp_print_string fmt "IF_NONE" + | IOpt_map _ -> pp_print_string fmt "MAP" + | ICons_left _ -> pp_print_string fmt "LEFT" + | ICons_right _ -> pp_print_string fmt "RIGHT" + | IIf_left _ -> pp_print_string fmt "IF_LEFT" + | ICons_list _ -> pp_print_string fmt "CONS" + | INil _ -> pp_print_string fmt "NIL" + | IIf_cons _ -> pp_print_string fmt "IF_CONS" + | IList_map _ -> pp_print_string fmt "MAP" + | IList_iter _ -> pp_print_string fmt "ITER" + | IList_size _ -> pp_print_string fmt "SIZE" + | IEmpty_set _ -> pp_print_string fmt "EMPTY_SET" + | ISet_iter _ -> pp_print_string fmt "ITER" + | ISet_mem _ -> pp_print_string fmt "MEM" + | ISet_update _ -> pp_print_string fmt "UPDATE" + | ISet_size _ -> pp_print_string fmt "SIZE" + | IEmpty_map _ -> pp_print_string fmt "EMPTY_MAP" + | IMap_map _ -> pp_print_string fmt "MAP" + | IMap_iter _ -> pp_print_string fmt "ITER" + | IMap_mem _ -> pp_print_string fmt "MEM" + | IMap_get _ -> pp_print_string fmt "GET" + | IMap_update _ -> pp_print_string fmt "UPDATE" + | IMap_get_and_update _ -> pp_print_string fmt "GET_AND_UPDATE" + | IMap_size _ -> pp_print_string fmt "SIZE" + | IEmpty_big_map _ -> pp_print_string fmt "EMPTY_BIG_MAP" + | IBig_map_mem _ -> pp_print_string fmt "MEM" + | IBig_map_get _ -> pp_print_string fmt "GET" + | IBig_map_update _ -> pp_print_string fmt "UPDATE" + | IBig_map_get_and_update _ -> pp_print_string fmt "GET_AND_UPDATE" + | IConcat_string _ -> pp_print_string fmt "CONCAT" + | IConcat_string_pair _ -> pp_print_string fmt "CONCAT" + | ISlice_string _ -> pp_print_string fmt "SLICE" + | IString_size _ -> pp_print_string fmt "SIZE" + | IConcat_bytes _ -> pp_print_string fmt "CONCAT" + | IConcat_bytes_pair _ -> pp_print_string fmt "CONCAT" + | ISlice_bytes _ -> pp_print_string fmt "SLICE" + | IBytes_size _ -> pp_print_string fmt "SIZE" + | IBytes_nat _ -> pp_print_string fmt "BYTES" + | INat_bytes _ -> pp_print_string fmt "NAT" + | IBytes_int _ -> pp_print_string fmt "BYTES" + | IInt_bytes _ -> pp_print_string fmt "INT" + | IAdd_seconds_to_timestamp _ -> pp_print_string fmt "ADD" + | IAdd_timestamp_to_seconds _ -> pp_print_string fmt "ADD" + | ISub_timestamp_seconds _ -> pp_print_string fmt "SUB" + | IDiff_timestamps _ -> pp_print_string fmt "DIFF" + | IAdd_tez _ -> pp_print_string fmt "ADD" + | ISub_tez _ -> pp_print_string fmt "SUB_MUTEZ" + | ISub_tez_legacy _ -> pp_print_string fmt "SUB" + | IMul_teznat _ | IMul_nattez _ -> pp_print_string fmt "MUL" + | IEdiv_teznat _ -> pp_print_string fmt "EDIV" + | IEdiv_tez _ -> pp_print_string fmt "EDIV" + | IOr _ -> pp_print_string fmt "OR" + | IAnd _ -> pp_print_string fmt "AND" + | IXor _ -> pp_print_string fmt "XOR" + | INot _ -> pp_print_string fmt "NOT" + | IIs_nat _ -> pp_print_string fmt "ISNAT" + | INeg _ -> pp_print_string fmt "NEG" + | IAbs_int _ -> pp_print_string fmt "ABS" + | IInt_nat _ -> pp_print_string fmt "INT" + | IAdd_int _ | IAdd_nat _ -> pp_print_string fmt "ADD" + | ISub_int _ -> pp_print_string fmt "SUB" + | IMul_int _ | IMul_nat _ -> pp_print_string fmt "MUL" + | IEdiv_int _ | IEdiv_nat _ -> pp_print_string fmt "EDIV" + | ILsl_nat _ -> pp_print_string fmt "LSL" + | ILsl_bytes _ -> pp_print_string fmt "LSL" + | ILsr_nat _ -> pp_print_string fmt "LSR" + | ILsr_bytes _ -> pp_print_string fmt "LSR" + | IOr_nat _ -> pp_print_string fmt "OR" + | IOr_bytes _ -> pp_print_string fmt "OR" + | IAnd_nat _ -> pp_print_string fmt "AND" + | IAnd_int_nat _ -> pp_print_string fmt "AND" + | IAnd_bytes _ -> pp_print_string fmt "AND" + | IXor_nat _ -> pp_print_string fmt "XOR" + | IXor_bytes _ -> pp_print_string fmt "XOR" + | INot_int _ -> pp_print_string fmt "NOT" + | INot_bytes _ -> pp_print_string fmt "NOT" + | IIf _ -> pp_print_string fmt "IF" + | ILoop _ -> pp_print_string fmt "LOOP" + | ILoop_left _ -> pp_print_string fmt "LOOP_LEFT" + | IDip _ -> pp_print_string fmt "DIP" + | IExec _ -> pp_print_string fmt "EXEC" + | IApply _ -> pp_print_string fmt "APPLY" + | ILambda (_, Lam _, _) -> pp_print_string fmt "LAMBDA" + | ILambda (_, LamRec _, _) -> pp_print_string fmt "LAMBDA_REC" + | IFailwith _ -> pp_print_string fmt "FAILWITH" + | ICompare _ -> pp_print_string fmt "COMPARE" + | IEq _ -> pp_print_string fmt "EQ" + | INeq _ -> pp_print_string fmt "NEQ" + | ILt _ -> pp_print_string fmt "LT" + | IGt _ -> pp_print_string fmt "GT" + | ILe _ -> pp_print_string fmt "LE" + | IGe _ -> pp_print_string fmt "GE" + | IAddress _ -> pp_print_string fmt "ADDRESS" + | IContract _ -> pp_print_string fmt "CONTACT" + | IView _ -> pp_print_string fmt "VIEW" + | ITransfer_tokens _ -> pp_print_string fmt "TRANSFER_TOKENS" + | IImplicit_account _ -> pp_print_string fmt "IMPLICIT_ACCOUNT" + | ICreate_contract _ -> pp_print_string fmt "CREATE_CONTRACT" + | ISet_delegate _ -> pp_print_string fmt "SET_DELEGATE" + | INow _ -> pp_print_string fmt "NOW" + | IMin_block_time _ -> pp_print_string fmt "MIN_BLOCK_TIME" + | IBalance _ -> pp_print_string fmt "BALANCE" + | ILevel _ -> pp_print_string fmt "LEVEL" + | ICheck_signature _ -> pp_print_string fmt "CHECK_SIGNATURE" + | IHash_key _ -> pp_print_string fmt "HASH_KEY" + | IPack _ -> pp_print_string fmt "PACK" + | IBlake2b _ -> pp_print_string fmt "BLAKE2B" + | ISha3 _ -> pp_print_string fmt "SHA3" + | ISha256 _ -> pp_print_string fmt "SHA256" + | ISha512 _ -> pp_print_string fmt "SHA512" + | IUnpack _ -> pp_print_string fmt "UNPACK" + | ISource _ -> pp_print_string fmt "SOURCE" + | ISender _ -> pp_print_string fmt "SENDER" + | ISelf _ -> pp_print_string fmt "SELF" + | ISelf_address _ -> pp_print_string fmt "SELF_ADDRESS" + | IAmount _ -> pp_print_string fmt "AMOUNT" + | ISapling_empty_state _ -> pp_print_string fmt "SAPLING_EMPTY_STATE" + | ISapling_verify_update _ | ISapling_verify_update_deprecated _ -> + pp_print_string fmt "SAPLING_VERIFY_UPDATE" + | IDig _ -> pp_print_string fmt "DIG" + | IDug _ -> pp_print_string fmt "DUG" + | IDipn _ -> pp_print_string fmt "DIP" + | IDropn _ -> pp_print_string fmt "DROP" + | IChainId _ -> pp_print_string fmt "CHAIN_ID" + | INever _ -> pp_print_string fmt "NEVER" + | IVoting_power _ -> pp_print_string fmt "VOTING_POWER" + | ITotal_voting_power _ -> pp_print_string fmt "TOTAL_VOTING_POWER" + | IKeccak _ -> pp_print_string fmt "KECCAK" + | IAdd_bls12_381_g1 _ | IAdd_bls12_381_g2 _ | IAdd_bls12_381_fr _ -> + pp_print_string fmt "ADD" + | IMul_bls12_381_g1 _ | IMul_bls12_381_g2 _ | IMul_bls12_381_fr _ + | IMul_bls12_381_z_fr _ | IMul_bls12_381_fr_z _ -> + pp_print_string fmt "MUL" + | IInt_bls12_381_fr _ -> pp_print_string fmt "INT" + | INeg_bls12_381_g1 _ | INeg_bls12_381_g2 _ | INeg_bls12_381_fr _ -> + pp_print_string fmt "NEG" + | IPairing_check_bls12_381 _ -> pp_print_string fmt "PAIRING_CHECK" + | IComb _ -> pp_print_string fmt "PAIR" + | IUncomb _ -> pp_print_string fmt "UNPAIR" + | IComb_get _ -> pp_print_string fmt "GET" + | IComb_set _ -> pp_print_string fmt "UPDATE" + | IDup_n _ -> pp_print_string fmt "DUP" + | ITicket _ -> pp_print_string fmt "TICKET" + | ITicket_deprecated _ -> pp_print_string fmt "TICKET_DEPRECATED" + | IRead_ticket _ -> pp_print_string fmt "READ_TICKET" + | ISplit_ticket _ -> pp_print_string fmt "SPLIT_TICKET" + | IJoin_tickets _ -> pp_print_string fmt "JOIN_TICKETS" + | IOpen_chest _ -> pp_print_string fmt "OPEN_CHEST" + | IEmit _ -> pp_print_string fmt "EMIT" + | IHalt _ -> pp_print_string fmt "[halt]" + | ILog (_, _, _, _, instr) -> + Format.fprintf fmt "log/%a" pp_instr_name instr + + type Environment.Error_monad.error += + | Run_operation_does_not_support_consensus_operations + + let () = + let description = + "The run_operation RPC does not support consensus operations." + in + Environment.Error_monad.register_error_kind + `Permanent + ~id:"run_operation_does_not_support_consensus_operations" + ~title:"Run operation does not support consensus operations" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function + | Run_operation_does_not_support_consensus_operations -> Some () + | _ -> None) + (fun () -> Run_operation_does_not_support_consensus_operations) + + (** Validate and apply the operation but skip signature checks; do + not support consensus operations. + + Return the unchanged operation protocol data, and the operation + receipt ie. metadata containing balance updates, consumed gas, + application success or failure, etc. *) + let run_operation_service rpc_ctxt params (packed_operation, chain_id) = + let open Lwt_result_syntax in + let {Services_registration.context; block_header; _} = rpc_ctxt in + let*? () = + match packed_operation.protocol_data with + | Operation_data {contents = Single (Preattestation _); _} + | Operation_data {contents = Single (Attestation _); _} -> + Environment.Error_monad.Result_syntax.tzfail + Run_operation_does_not_support_consensus_operations + | _ -> Result_syntax.return_unit + in + let oph = Operation.hash_packed packed_operation in + let validity_state = Validate.begin_no_predecessor_info context chain_id in + let* _validate_operation_state = + Validate.validate_operation + ~check_signature:false + validity_state + oph + packed_operation + in + let application_mode = + Apply.Partial_construction {predecessor_fitness = block_header.fitness} + in + let application_state = + Apply. + { + ctxt = context; + chain_id; + mode = application_mode; + op_count = 0; + migration_balance_updates = []; + liquidity_baking_toggle_ema = + Per_block_votes.Liquidity_baking_toggle_EMA.zero; + adaptive_issuance_vote_ema = + Per_block_votes.Adaptive_issuance_launch_EMA.zero; + adaptive_issuance_launch_cycle = None; + implicit_operations_results = []; + } + in + let* _ctxt, op_metadata = + Apply.apply_operation application_state oph packed_operation + in + return (params#version, (packed_operation.protocol_data, op_metadata)) + + (* + + The execution of an operation depends on the state of the + cache. In particular, gas consumption is usually impacted by + cache hits and misses. + + Unfortunately, the state of the cache is different between the + context at operation-creation time and the context when is + included in a block. + + Therefore, the simulation tries to predict the state of the + cache in a [time_in_blocks] assumed to be close to the inclusion + time of the operation. + + *) + let simulate_operation_service rpc_ctxt params + (blocks_before_activation, op, chain_id, time_in_blocks) = + let open Lwt_result_syntax in + let {Services_registration.context; _} = rpc_ctxt in + let* context = + Cache.Admin.future_cache_expectation + context + ~time_in_blocks + ?blocks_before_activation + in + run_operation_service + {rpc_ctxt with context} + (object + method version = params#version + end) + (op, chain_id) + + let default_from_context ctxt get = + let open Lwt_result_syntax in + function None -> get ctxt | Some x -> return x + + (* A convenience type for return values of [ensure_contracts_exist] below. *) + type run_code_config = { + balance : Tez.t; + self : Contract_hash.t; + payer : Signature.public_key_hash; + sender : Contract.t; + } + + (* 4_000_000 ꜩ *) + let default_balance = Tez.of_mutez_exn 4_000_000_000_000L + + let register () = + let open Lwt_result_syntax in + let originate_dummy_contract ctxt script balance = + let ctxt = Origination_nonce.init ctxt Operation_hash.zero in + let*? ctxt, dummy_contract_hash = + Contract.fresh_contract_from_current_nonce ctxt + in + let dummy_contract = Contract.Originated dummy_contract_hash in + let* ctxt = + Contract.raw_originate + ctxt + ~prepaid_bootstrap_storage:false + dummy_contract_hash + ~script:(script, None) + in + let+ ctxt, _ = + Token.transfer + ~origin:Simulation + ctxt + `Minted + (`Contract dummy_contract) + balance + in + (ctxt, dummy_contract_hash) + in + let originate_dummy_contracts ctxt = + List.fold_left_es + (fun ctxt {S.address; ty} -> + Contract.raw_originate + ctxt + ~prepaid_bootstrap_storage:false + address + (* We reuse the default script from View_helpers because + the purpose is the same; we only care about having a + script declaring the correct parameter type but we will + never actually run the script. *) + ~script:(View_helpers.make_tzip4_viewer_script ty, None)) + ctxt + in + let initialize_big_maps ctxt big_maps = + let* ctxt, (big_map_diff : Lazy_storage.diffs) = + List.fold_left_es + (fun (ctxt, big_map_diff_tl) {S.id; kty; vty; items} -> + let open Script_ir_translator in + let items = Micheline.root items in + let init = + Lazy_storage.(Alloc Big_map.{key_type = kty; value_type = vty}) + in + let*? Ex_comparable_ty key_comparable_type, ctxt = + parse_comparable_ty ctxt (Micheline.root kty) + in + let*? Ex_ty value_type, ctxt = + parse_big_map_value_ty ctxt ~legacy:false (Micheline.root vty) + in + (* Typecheck the update seq to check that the values are well-typed and the keys are sorted *) + let*? map_ty = + Script_typed_ir.map_t (-1) key_comparable_type value_type + in + let* _, ctxt = + parse_data + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:false ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + map_ty + items + in + let items = + match items with + | Micheline.Seq (_, items) -> items + | _ -> assert false + in + (* Build a big_map_diff *) + let+ ctxt, updates = + List.fold_left_es + (fun (ctxt, acc) key_value -> + let open Micheline in + let key, value = + match key_value with + | Prim (_, Michelson_v1_primitives.D_Elt, [key; value], _) + -> + (key, value) + | _ -> assert false + in + let* k, ctxt = + parse_comparable_data ctxt key_comparable_type key + in + let+ key_hash, ctxt = hash_data ctxt key_comparable_type k in + let key = Micheline.strip_locations key in + let value = Some (Micheline.strip_locations value) in + (ctxt, Big_map.{key; key_hash; value} :: acc)) + (ctxt, []) + items + in + ( ctxt, + Lazy_storage.( + make Big_map id (Update {init; updates = List.rev updates})) + :: big_map_diff_tl )) + (ctxt, []) + big_maps + in + let+ ctxt, _size_change = Lazy_storage.apply ctxt big_map_diff in + ctxt + in + let sender_and_payer ~sender_opt ~payer_opt ~default_sender = + match (sender_opt, payer_opt) with + | None, None -> + (Contract.Originated default_sender, Signature.Public_key_hash.zero) + | Some c, None -> (c, Signature.Public_key_hash.zero) + | None, Some c -> (Contract.Implicit c, c) + | Some sender, Some payer -> (sender, payer) + in + let compute_step_constants ctxt ~balance ~amount ~chain_id ~sender_opt + ~payer_opt ~self ~now_opt ~level_opt = + let sender, payer = + sender_and_payer ~sender_opt ~payer_opt ~default_sender:self + in + let now = + match now_opt with None -> Script_timestamp.now ctxt | Some t -> t + in + let level = + match level_opt with + | None -> + (Level.current ctxt).level |> Raw_level.to_int32 + |> Script_int.of_int32 |> Script_int.abs + | Some z -> z + in + let open Script_interpreter in + let sender = Destination.Contract sender in + (ctxt, {sender; payer; self; amount; balance; chain_id; now; level}) + in + let configure_gas_and_step_constants ctxt ~script ~gas_opt ~balance ~amount + ~chain_id ~sender_opt ~payer_opt ~self_opt ~now_opt ~level_opt = + let gas = + match gas_opt with + | Some gas -> gas + | None -> Constants.hard_gas_limit_per_operation ctxt + in + let ctxt = Gas.set_limit ctxt gas in + let+ ctxt, self, balance = + match self_opt with + | None -> + let balance = Option.value ~default:default_balance balance in + let+ ctxt, addr = originate_dummy_contract ctxt script balance in + (ctxt, addr, balance) + | Some addr -> + let+ bal = + default_from_context + ctxt + (fun c -> Contract.get_balance c @@ Contract.Originated addr) + balance + in + (ctxt, addr, bal) + in + compute_step_constants + ctxt + ~balance + ~amount + ~chain_id + ~sender_opt + ~payer_opt + ~self + ~now_opt + ~level_opt + in + let script_entrypoint_type ctxt expr entrypoint = + let ctxt = Gas.set_unlimited ctxt in + let legacy = false in + let open Script_ir_translator in + let* {arg_type; _}, ctxt = parse_toplevel ctxt expr in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, _ = + parse_parameter_ty_and_entrypoints ctxt ~legacy arg_type + in + let*? r, _ctxt = + Gas_monad.run ctxt + @@ Script_ir_translator.find_entrypoint + ~error_details:(Informative ()) + arg_type + entrypoints + entrypoint + in + let*? (Ex_ty_cstr {original_type_expr; _}) = r in + return @@ Micheline.strip_locations original_type_expr + in + let script_view_type ctxt contract expr view = + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + let* {views; _}, _ = parse_toplevel ctxt expr in + let*? view_name = Script_string.of_string view in + match Script_map.get view_name views with + | None -> + Environment.Error_monad.tzfail + (View_helpers.View_not_found (contract, view)) + | Some Script_typed_ir.{input_ty; output_ty; _} -> + return (input_ty, output_ty) + in + Registration.register0 + ~chunked:true + S.run_code + (fun + ctxt + () + ( ( code, + storage, + parameter, + amount, + balance, + chain_id, + sender_opt, + payer_opt, + self_opt, + entrypoint ), + ( unparsing_mode, + gas_opt, + now_opt, + level_opt, + other_contracts, + extra_big_maps ) ) + -> + let unparsing_mode = Option.value ~default:Readable unparsing_mode in + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let storage = Script.lazy_expr storage in + let code = Script.lazy_expr code in + let* ctxt, step_constants = + configure_gas_and_step_constants + ctxt + ~script:{storage; code} + ~gas_opt + ~balance + ~amount + ~chain_id + ~sender_opt + ~payer_opt + ~self_opt + ~now_opt + ~level_opt + in + let+ ( { + script = _; + code_size = _; + Script_interpreter.storage; + operations; + lazy_storage_diff; + ticket_diffs = _; + ticket_receipt = _; + }, + _ ) = + Script_interpreter.execute + ctxt + unparsing_mode + step_constants + ~cached_script:None + ~script:{storage; code} + ~entrypoint + ~parameter + ~internal:true + in + ( storage, + Apply_internal_results.packed_internal_operations operations, + lazy_storage_diff )) ; + Registration.register0 + ~chunked:true + S.trace_code + (fun + ctxt + () + ( ( code, + storage, + parameter, + amount, + balance, + chain_id, + sender_opt, + payer_opt, + self_opt, + entrypoint ), + ( unparsing_mode, + gas_opt, + now_opt, + level_opt, + other_contracts, + extra_big_maps ) ) + -> + let unparsing_mode = Option.value ~default:Readable unparsing_mode in + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let storage = Script.lazy_expr storage in + let code = Script.lazy_expr code in + let* ctxt, step_constants = + configure_gas_and_step_constants + ctxt + ~script:{storage; code} + ~gas_opt + ~balance + ~amount + ~chain_id + ~sender_opt + ~payer_opt + ~self_opt + ~now_opt + ~level_opt + in + let module Unparsing_mode = struct + let unparsing_mode = unparsing_mode + end in + let module Interp = Traced_interpreter (Unparsing_mode) in + let+ ( ( { + script = _; + code_size = _; + Script_interpreter.storage; + operations; + lazy_storage_diff; + ticket_diffs = _; + ticket_receipt = _; + }, + _ctxt ), + trace ) = + Interp.execute + ctxt + step_constants + ~script:{storage; code} + ~entrypoint + ~parameter + in + ( storage, + Apply_internal_results.packed_internal_operations operations, + trace, + lazy_storage_diff )) ; + Registration.register0 + ~chunked:true + S.run_tzip4_view + (fun + ctxt + () + ( ( contract_hash, + entrypoint, + input, + chain_id, + sender_opt, + payer_opt, + gas, + unparsing_mode, + now_opt, + level_opt ), + (other_contracts, extra_big_maps) ) + -> + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let* ctxt, script_opt = Contract.get_script ctxt contract_hash in + let*? script = + Option.fold + ~some:Result_syntax.return + ~none: + (Environment.Error_monad.Result_syntax.tzfail + View_helpers.Viewed_contract_has_no_script) + script_opt + in + let*? decoded_script = Script_repr.(force_decode script.code) in + let* view_ty = script_entrypoint_type ctxt decoded_script entrypoint in + let*? ty = View_helpers.extract_view_output_type entrypoint view_ty in + let contract = Contract.Originated contract_hash in + let* balance = Contract.get_balance ctxt contract in + let* ctxt, viewer_contract = + Error_monad.trace View_helpers.View_callback_origination_failed + @@ originate_dummy_contract + ctxt + (View_helpers.make_tzip4_viewer_script ty) + Tez.zero + in + let ctxt, step_constants = + compute_step_constants + ctxt + ~balance + ~amount:Tez.zero + ~chain_id + ~sender_opt + ~payer_opt + ~self:contract_hash + ~now_opt + ~level_opt + in + let gas = + Option.value + ~default:(Constants.hard_gas_limit_per_operation ctxt) + gas + in + let ctxt = Gas.set_limit ctxt gas in + let parameter = + View_helpers.make_view_parameter + (Micheline.root input) + (Contract.Originated viewer_contract) + in + let* ( { + Script_interpreter.operations; + script = _; + code_size = _; + storage = _; + lazy_storage_diff = _; + ticket_diffs = _; + ticket_receipt = _; + }, + _ctxt ) = + Script_interpreter.execute + ctxt + unparsing_mode + step_constants + ~script + ~cached_script:None + ~entrypoint + ~parameter + ~internal:true + in + Lwt.return + (View_helpers.extract_parameter_from_operations + entrypoint + operations + viewer_contract)) ; + Registration.register0 + ~chunked:true + S.run_script_view + (fun + ctxt + () + ( ( contract_hash, + view, + input, + unlimited_gas, + chain_id, + sender_opt, + payer_opt, + gas, + unparsing_mode, + now_opt ), + (level_opt, other_contracts, extra_big_maps) ) + -> + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let* ctxt, script_opt = Contract.get_script ctxt contract_hash in + let*? script = + Option.fold + ~some:Result_syntax.return + ~none:(Error_monad.error View_helpers.Viewed_contract_has_no_script) + script_opt + in + let*? decoded_script = Script_repr.(force_decode script.code) in + let contract = Contract.Originated contract_hash in + let* input_ty, output_ty = + script_view_type ctxt contract_hash decoded_script view + in + let* balance = Contract.get_balance ctxt contract in + let ctxt, step_constants = + compute_step_constants + ctxt + ~balance + ~amount:Tez.zero + ~chain_id + ~sender_opt + ~payer_opt + ~self:contract_hash + ~now_opt + ~level_opt + in + (* Using [Gas.set_unlimited] won't work, since the interpreter doesn't + use this mode (see !4034#note_774734253) and still consumes gas. + Our best shot to emulate this is to use the maximum amount of + milligas possible which is represented by [2^62 - 1] according to + [Saturation_repr.saturated], which is [max_int]. *) + let max_gas = Gas.fp_of_milligas_int max_int in + let gas = + Option.value + ~default:(Constants.hard_gas_limit_per_operation ctxt) + gas + in + let ctxt = + if unlimited_gas then Gas.set_limit ctxt max_gas + else Gas.set_limit ctxt gas + in + let viewer_script = + View_helpers.make_michelson_viewer_script + contract + view + input + input_ty + output_ty + in + let parameter = + Micheline.(strip_locations (Prim (0, Script.D_Unit, [], []))) + in + let* ( { + Script_interpreter.operations = _; + script = _; + code_size = _; + storage; + lazy_storage_diff = _; + ticket_diffs = _; + ticket_receipt = _; + }, + _ctxt ) = + Script_interpreter.execute + ctxt + unparsing_mode + step_constants + ~script:viewer_script + ~cached_script:None + ~entrypoint:Entrypoint.default + ~parameter + ~internal:true + in + let*? value = View_helpers.extract_value_from_storage storage in + return (Micheline.strip_locations value)) ; + Registration.register0 + ~chunked:false + S.typecheck_code + (fun ctxt () (expr, maybe_gas, legacy, show_types) -> + let ctxt = + match maybe_gas with + | None -> Gas.set_unlimited ctxt + | Some gas -> Gas.set_limit ctxt gas + in + let+ res, ctxt = + Script_ir_translator.typecheck_code ~legacy ~show_types ctxt expr + in + (res, Gas.level ctxt)) ; + Registration.register0 + ~chunked:false + S.script_size + (fun ctxt () (expr, storage, maybe_gas, legacy) -> + let ctxt = + match maybe_gas with + | None -> Gas.set_unlimited ctxt + | Some gas -> Gas.set_limit ctxt gas + in + let elab_conf = elab_conf ~legacy () in + let code = Script.lazy_expr expr in + let* ( Ex_code + (Code + {code; arg_type; storage_type; views; entrypoints; code_size}), + ctxt ) = + Script_ir_translator.parse_code ~elab_conf ctxt ~code + in + let* storage, _ = + Script_ir_translator.parse_data + ~elab_conf + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + ctxt + storage_type + (Micheline.root storage) + in + let script = + Script_ir_translator.Ex_script + (Script + { + code; + arg_type; + storage_type; + views; + entrypoints; + code_size; + storage; + }) + in + let size, cost = Script_ir_translator.script_size script in + let*? _ctxt = Gas.consume ctxt cost in + return size) ; + + Registration.register0 + ~chunked:false + S.typecheck_data + (fun ctxt () (data, ty, maybe_gas, legacy) -> + let ctxt = + match maybe_gas with + | None -> Gas.set_unlimited ctxt + | Some gas -> Gas.set_limit ctxt gas + in + let+ ctxt = typecheck_data ~legacy ctxt (data, ty) in + Gas.level ctxt) ; + Registration.register0 + ~chunked:true + S.pack_data + (fun ctxt () (expr, typ, maybe_gas) -> + let open Script_ir_translator in + let ctxt = + match maybe_gas with + | None -> Gas.set_unlimited ctxt + | Some gas -> Gas.set_limit ctxt gas + in + let*? Ex_ty typ, ctxt = + parse_packable_ty ctxt ~legacy:true (Micheline.root typ) + in + let* data, ctxt = + parse_data + ctxt + ~elab_conf:(elab_conf ~legacy:true ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + typ + (Micheline.root expr) + in + let+ bytes, ctxt = Script_ir_translator.pack_data ctxt typ data in + (bytes, Gas.level ctxt)) ; + Registration.register0 + ~chunked:true + S.normalize_data + (fun + ctxt + () + (expr, typ, unparsing_mode, legacy, other_contracts, extra_big_maps) + -> + let open Script_ir_translator in + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let ctxt = Gas.set_unlimited ctxt in + let*? Ex_ty typ, ctxt = + Script_ir_translator.parse_any_ty ctxt ~legacy (Micheline.root typ) + in + let* data, ctxt = + parse_data + ctxt + ~elab_conf:(elab_conf ~legacy ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + typ + (Micheline.root expr) + in + let+ normalized, _ctxt = + Script_ir_translator.unparse_data ctxt unparsing_mode typ data + in + normalized) ; + Registration.register0 + ~chunked:true + S.normalize_stack + (fun + ctxt + () + (stack, unparsing_mode, legacy, other_contracts, extra_big_maps) + -> + let ctxt = Gas.set_unlimited ctxt in + let nodes = + List.map (fun (a, b) -> (Micheline.root a, Micheline.root b)) stack + in + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let* Normalize_stack.Ex_stack (st_ty, x, st), ctxt = + Normalize_stack.parse_stack ctxt ~legacy nodes + in + let+ normalized, _ctxt = + Normalize_stack.unparse_stack ctxt unparsing_mode st_ty x st + in + normalized) ; + Registration.register0 + ~chunked:true + S.normalize_script + (fun ctxt () (script, unparsing_mode) -> + let ctxt = Gas.set_unlimited ctxt in + let+ normalized, _ctxt = + Script_ir_translator.unparse_code + ctxt + unparsing_mode + (Micheline.root script) + in + normalized) ; + Registration.register0 ~chunked:true S.normalize_type (fun ctxt () typ -> + let open Script_typed_ir in + let ctxt = Gas.set_unlimited ctxt in + (* Unfortunately, Script_ir_translator.parse_any_ty is not exported *) + let*? Ex_ty typ, _ctxt = + Script_ir_translator.parse_ty + ctxt + ~legacy:true + ~allow_lazy_storage:true + ~allow_operation:true + ~allow_contract:true + ~allow_ticket:true + (Micheline.root typ) + in + let normalized = Unparse_types.unparse_ty ~loc:() typ in + return @@ Micheline.strip_locations normalized) ; + Registration.register0 + ~chunked:true + S.run_instr + (fun + ctxt + () + ( ( input, + code, + chain_id, + gas_opt, + now_opt, + level_opt, + sender_opt, + source_opt, + self_opt, + parameter_opt ), + ( amount, + balance, + other_contracts, + extra_big_maps, + unparsing_mode, + legacy ) ) + -> + let unparsing_mode = Option.value ~default:Readable unparsing_mode in + let other_contracts = Option.value ~default:[] other_contracts in + let* ctxt = originate_dummy_contracts ctxt other_contracts in + let extra_big_maps = Option.value ~default:[] extra_big_maps in + let* ctxt = initialize_big_maps ctxt extra_big_maps in + let parameter = + Option.value + ~default: + (Micheline.strip_locations + (Prim (0, Michelson_v1_primitives.T_unit, [], []))) + parameter_opt + in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, ctxt = + Script_ir_translator.parse_parameter_ty_and_entrypoints + ctxt + ~legacy + (Micheline.root parameter) + in + let* ctxt, step_constants = + configure_gas_and_step_constants + ctxt + ~script:(View_helpers.make_tzip4_viewer_script parameter) + ~gas_opt + ~balance + ~amount + ~chain_id + ~sender_opt + ~payer_opt:source_opt + ~self_opt + ~now_opt + ~level_opt + in + let input_nodes = + List.map (fun (a, b) -> (Micheline.root a, Micheline.root b)) input + in + let* Normalize_stack.Ex_stack (st_ty, x, st), ctxt = + Normalize_stack.parse_stack ctxt ~legacy input_nodes + in + let* j, ctxt = + Script_ir_translator.parse_instr + ~elab_conf:(Script_ir_translator_config.make ~legacy ()) + (Script_tc_context.toplevel + ~storage_type:Script_typed_ir.unit_t + ~param_type:arg_type + ~entrypoints) + ctxt + (Micheline.root code) + st_ty + in + match j with + | Failed {descr} -> ( + let impossible_stack_ty = + Script_typed_ir.(Item_t (never_t, Bot_t)) + in + let descr = descr impossible_stack_ty in + let descr = Script_ir_translator.close_descr descr in + let* absurd = + Script_interpreter.Internals.step_descr + None + ctxt + step_constants + descr + x + st + in + match absurd with _ -> .) + | Typed descr -> + let descr = Script_ir_translator.close_descr descr in + let* y, output_st, _ctxt = + Script_interpreter.Internals.step_descr + None + ctxt + step_constants + descr + x + st + in + let+ output, ctxt = + Normalize_stack.unparse_stack + ctxt + unparsing_mode + descr.kaft + y + output_st + in + (output, Gas.level ctxt)) ; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3364 + + Should [run_operation] be registered at successor level? *) + Registration.register0_fullctxt + ~chunked:true + S.run_operation + run_operation_service ; + Registration.register0_fullctxt_successor_level + ~chunked:true + S.simulate_operation + simulate_operation_service ; + Registration.register0 + ~chunked:true + S.entrypoint_type + (fun ctxt () (expr, entrypoint) -> + script_entrypoint_type ctxt expr entrypoint) ; + Registration.register0 ~chunked:true S.list_entrypoints (fun ctxt () expr -> + let ctxt = Gas.set_unlimited ctxt in + let legacy = false in + let open Script_ir_translator in + let* {arg_type; _}, ctxt = parse_toplevel ctxt expr in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, _ = + parse_parameter_ty_and_entrypoints ctxt ~legacy arg_type + in + return + @@ + let unreachable_entrypoint, map = + Script_ir_translator.list_entrypoints_uncarbonated + arg_type + entrypoints + in + ( unreachable_entrypoint, + Entrypoint.Map.fold + (fun entry (_ex_ty, original_type_expr) acc -> + ( Entrypoint.to_string entry, + Micheline.strip_locations original_type_expr ) + :: acc) + map + [] )) + + let run_code ~unparsing_mode ~gas ~entrypoint ~balance ~other_contracts + ~extra_big_maps ~script ~storage ~input ~amount ~chain_id ~sender ~payer + ~self ~now ~level ctxt block = + RPC_context.make_call0 + S.run_code + ctxt + block + () + ( ( script, + storage, + input, + amount, + balance, + chain_id, + sender, + payer, + self, + entrypoint ), + (unparsing_mode, gas, now, level, other_contracts, extra_big_maps) ) + + let trace_code ~unparsing_mode ~gas ~entrypoint ~balance ~other_contracts + ~extra_big_maps ~script ~storage ~input ~amount ~chain_id ~sender ~payer + ~self ~now ~level ctxt block = + RPC_context.make_call0 + S.trace_code + ctxt + block + () + ( ( script, + storage, + input, + amount, + balance, + chain_id, + sender, + payer, + self, + entrypoint ), + (unparsing_mode, gas, now, level, other_contracts, extra_big_maps) ) + + let run_tzip4_view ~gas ~other_contracts ~extra_big_maps ~contract ~entrypoint + ~input ~chain_id ~now ~level ~sender ~payer ~unparsing_mode ctxt block = + RPC_context.make_call0 + S.run_tzip4_view + ctxt + block + () + ( ( contract, + entrypoint, + input, + chain_id, + sender, + payer, + gas, + unparsing_mode, + now, + level ), + (other_contracts, extra_big_maps) ) + + (** [run_script_view] is an helper function to call the corresponding + RPC. *) + let run_script_view ~gas ~other_contracts ~extra_big_maps ~contract ~view + ~input ~unlimited_gas ~chain_id ~now ~level ~sender ~payer ~unparsing_mode + ctxt block = + RPC_context.make_call0 + S.run_script_view + ctxt + block + () + ( ( contract, + view, + input, + unlimited_gas, + chain_id, + sender, + payer, + gas, + unparsing_mode, + now ), + (level, other_contracts, extra_big_maps) ) + + let run_instr ~gas ~legacy ~input ~code ~chain_id ~now ~level ~unparsing_mode + ~source ~sender ~self ~parameter ~amount ~balance ~other_contracts + ~extra_big_maps ctxt block = + RPC_context.make_call0 + S.run_instr + ctxt + block + () + ( (input, code, chain_id, gas, now, level, sender, source, self, parameter), + ( amount, + balance, + other_contracts, + extra_big_maps, + unparsing_mode, + legacy ) ) + + let typecheck_code ~gas ~legacy ~script ~show_types ctxt block = + RPC_context.make_call0 + S.typecheck_code + ctxt + block + () + (script, gas, legacy, show_types) + + let script_size ~gas ~legacy ~script ~storage ctxt block = + RPC_context.make_call0 + S.script_size + ctxt + block + () + (script, storage, gas, legacy) + + let typecheck_data ~gas ~legacy ~data ~ty ctxt block = + RPC_context.make_call0 S.typecheck_data ctxt block () (data, ty, gas, legacy) + + let pack_data ~gas ~data ~ty ctxt block = + RPC_context.make_call0 S.pack_data ctxt block () (data, ty, gas) + + let normalize_data ~legacy ~other_contracts ~extra_big_maps ~data ~ty + ~unparsing_mode ctxt block = + RPC_context.make_call0 + S.normalize_data + ctxt + block + () + (data, ty, unparsing_mode, legacy, other_contracts, extra_big_maps) + + let normalize_stack ~legacy ~other_contracts ~extra_big_maps ~stack + ~unparsing_mode ctxt block = + RPC_context.make_call0 + S.normalize_stack + ctxt + block + () + (stack, unparsing_mode, legacy, other_contracts, extra_big_maps) + + let normalize_script ~script ~unparsing_mode ctxt block = + RPC_context.make_call0 + S.normalize_script + ctxt + block + () + (script, unparsing_mode) + + let normalize_type ~ty ctxt block = + RPC_context.make_call0 S.normalize_type ctxt block () ty + + let run_operation ~op ~chain_id ?(version = default_operations_version) ctxt + block = + let open Lwt_result_syntax in + let* (Version_0 | Version_1), run_operation = + RPC_context.make_call0 + S.run_operation + ctxt + block + (object + method version = version + end) + (op, chain_id) + in + return run_operation + + let simulate_operation ~op ~chain_id ~latency + ?(version = default_operations_version) ?(successor_level = false) + ?blocks_before_activation ctxt block = + let open Lwt_result_syntax in + let* (Version_0 | Version_1), simulate_operation = + RPC_context.make_call0 + S.simulate_operation + ctxt + block + (object + method version = version + + method successor_level = successor_level + end) + (blocks_before_activation, op, chain_id, latency) + in + return simulate_operation + + let entrypoint_type ~script ~entrypoint ctxt block = + RPC_context.make_call0 S.entrypoint_type ctxt block () (script, entrypoint) + + let list_entrypoints ctxt block ~script = + RPC_context.make_call0 S.list_entrypoints ctxt block () script +end + +module Contract = struct + let ticket_balances_encoding = + let open Data_encoding in + list + (merge_objs Ticket_token.unparsed_token_encoding (obj1 (req "amount" n))) + + module S = struct + let path = + (RPC_path.(open_root / "context" / "contracts") + : RPC_context.t RPC_path.context) + + let get_storage_normalized = + let open Data_encoding in + RPC_service.post_service + ~description: + "Access the data of the contract and normalize it using the \ + requested unparsing mode." + ~input:(obj1 (req "unparsing_mode" unparsing_mode_encoding)) + ~query:RPC_query.empty + ~output:(option Script.expr_encoding) + RPC_path.(path /: Contract.rpc_arg / "storage" / "normalized") + + let get_script_normalized = + let open Data_encoding in + RPC_service.post_service + ~description: + "Access the script of the contract and normalize it using the \ + requested unparsing mode." + ~input: + (obj2 + (req "unparsing_mode" unparsing_mode_encoding) + (dft "normalize_types" bool false)) + ~query:RPC_query.empty + ~output:(option Script.encoding) + RPC_path.(path /: Contract.rpc_arg / "script" / "normalized") + + let get_used_storage_space = + let open Data_encoding in + RPC_service.get_service + ~description:"Access the used storage space of the contract." + ~query:RPC_query.empty + ~output:(option z) + RPC_path.(path /: Contract.rpc_arg / "storage" / "used_space") + + let get_paid_storage_space = + let open Data_encoding in + RPC_service.get_service + ~description:"Access the paid storage space of the contract." + ~query:RPC_query.empty + ~output:(option z) + RPC_path.(path /: Contract.rpc_arg / "storage" / "paid_space") + + let ticket_balance = + let open Data_encoding in + RPC_service.post_service + ~description: + "Access the contract's balance of ticket with specified ticketer, \ + content type, and content." + ~query:RPC_query.empty + ~input:Ticket_token.unparsed_token_encoding + ~output:n + RPC_path.(path /: Contract.rpc_arg / "ticket_balance") + + let all_ticket_balances = + RPC_service.get_service + ~description: + "Access the complete list of tickets owned by the given contract by \ + scanning the contract's storage." + ~query:RPC_query.empty + ~output:ticket_balances_encoding + RPC_path.(path /: Contract.rpc_arg / "all_ticket_balances") + end + + let get_contract contract f = + let open Lwt_result_syntax in + match contract with + | Contract.Implicit _ -> return_none + | Contract.Originated contract -> f contract + + let register () = + let open Lwt_result_syntax in + (* Patched RPC: get_storage *) + Registration.register1 + ~chunked:true + S.get_storage_normalized + (fun ctxt contract () unparsing_mode -> + get_contract contract @@ fun contract -> + let* ctxt, script = Contract.get_script ctxt contract in + match script with + | None -> return_none + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + let* Ex_script (Script {storage; storage_type; _}), ctxt = + parse_script + ctxt + ~elab_conf:(elab_conf ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let+ storage, _ctxt = + unparse_data ctxt unparsing_mode storage_type storage + in + Some storage) ; + (* Patched RPC: get_script *) + Registration.register1 + ~chunked:true + S.get_script_normalized + (fun ctxt contract () (unparsing_mode, normalize_types) -> + get_contract contract @@ fun contract -> + let* ctxt, script = Contract.get_script ctxt contract in + match script with + | None -> return_none + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let+ script, _ctxt = + Script_ir_translator.parse_and_unparse_script_unaccounted + ctxt + ~legacy:true + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + unparsing_mode + ~normalize_types + script + in + Some script) ; + Registration.register1 + ~chunked:false + S.get_used_storage_space + (fun ctxt contract () () -> + get_contract contract @@ fun _ -> + let+ x = Contract.used_storage_space ctxt contract in + Some x) ; + Registration.register1 + ~chunked:false + S.get_paid_storage_space + (fun ctxt contract () () -> + get_contract contract @@ fun _ -> + let+ x = Contract.paid_storage_space ctxt contract in + Some x) ; + Registration.register1 + ~chunked:false + S.ticket_balance + (fun ctxt contract () Ticket_token.{ticketer; contents_type; contents} -> + let* ticket_hash, ctxt = + Ticket_balance_key.make + ctxt + ~owner:(Contract contract) + ~ticketer + ~contents_type:(Micheline.root contents_type) + ~contents:(Micheline.root contents) + in + let+ amount, _ctxt = Ticket_balance.get_balance ctxt ticket_hash in + Option.value amount ~default:Z.zero) ; + Registration.opt_register1 + ~chunked:false + S.all_ticket_balances + (fun ctxt contract () () -> + get_contract contract @@ fun contract -> + let* ctxt, script = Contract.get_script ctxt contract in + match script with + | None -> return_none + | Some script -> + let* Ex_script (Script {storage; storage_type; _}), ctxt = + Script_ir_translator.parse_script + ctxt + ~elab_conf:(elab_conf ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let*? has_tickets, ctxt = + Ticket_scanner.type_has_tickets ctxt storage_type + in + let* ticket_token_map, ctxt = + Ticket_accounting.ticket_balances_of_value + ctxt + ~include_lazy:true + has_tickets + storage + in + let+ ticket_balances, _ctxt = + Ticket_token_map.fold_es + ctxt + (fun ctxt acc ex_token amount -> + let+ unparsed_token, ctxt = + Ticket_token_unparser.unparse ctxt ex_token + in + ((unparsed_token, amount) :: acc, ctxt)) + [] + ticket_token_map + in + Some ticket_balances) + + let get_storage_normalized ctxt block ~contract ~unparsing_mode = + RPC_context.make_call1 + S.get_storage_normalized + ctxt + block + (Contract.Originated contract) + () + unparsing_mode + + let get_script_normalized ctxt block ~contract ~unparsing_mode + ~normalize_types = + RPC_context.make_call1 + S.get_script_normalized + ctxt + block + (Contract.Originated contract) + () + (unparsing_mode, normalize_types) + + let get_used_storage_space ctxt block ~contract = + RPC_context.make_call1 + S.get_used_storage_space + ctxt + block + (Contract.Originated contract) + () + () + + let get_paid_storage_space ctxt block ~contract = + RPC_context.make_call1 + S.get_paid_storage_space + ctxt + block + (Contract.Originated contract) + () + () + + let get_ticket_balance ctxt block contract key = + RPC_context.make_call1 S.ticket_balance ctxt block contract () key + + let get_all_ticket_balances ctxt block contract = + RPC_context.make_call1 + S.all_ticket_balances + ctxt + block + (Contract.Originated contract) + () + () +end + +module Big_map = struct + module S = struct + let path = + (RPC_path.(open_root / "context" / "big_maps") + : RPC_context.t RPC_path.context) + + let big_map_get_normalized = + let open Data_encoding in + RPC_service.post_service + ~description: + "Access the value associated with a key in a big map, normalize the \ + output using the requested unparsing mode." + ~query:RPC_query.empty + ~input:(obj1 (req "unparsing_mode" unparsing_mode_encoding)) + ~output:Script.expr_encoding + RPC_path.( + path /: Big_map.Id.rpc_arg /: Script_expr_hash.rpc_arg / "normalized") + end + + let register () = + let open Lwt_result_syntax in + Registration.register2 + ~chunked:true + S.big_map_get_normalized + (fun ctxt id key () unparsing_mode -> + let open Script_ir_translator in + let ctxt = Gas.set_unlimited ctxt in + let* ctxt, types = Big_map.exists ctxt id in + match types with + | None -> raise Not_found + | Some (_, value_type) -> ( + let*? Ex_ty value_type, ctxt = + parse_big_map_value_ty + ctxt + ~legacy:true + (Micheline.root value_type) + in + let* _ctxt, value = Big_map.get_opt ctxt id key in + match value with + | None -> raise Not_found + | Some value -> + let* value, ctxt = + parse_data + ctxt + ~elab_conf:(elab_conf ~legacy:true ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + value_type + (Micheline.root value) + in + let+ value, _ctxt = + unparse_data ctxt unparsing_mode value_type value + in + value)) + + let big_map_get_normalized ctxt block id key ~unparsing_mode = + RPC_context.make_call2 + S.big_map_get_normalized + ctxt + block + id + key + () + unparsing_mode +end + +module Sc_rollup = struct + open Data_encoding + + module S = struct + let prefix : RPC_context.t RPC_path.context = + RPC_path.(open_root / "context" / "smart_rollups") + + let path_sc_rollup : (RPC_context.t, RPC_context.t * Sc_rollup.t) RPC_path.t + = + RPC_path.(prefix / "smart_rollup" /: Sc_rollup.Address.rpc_arg) + + let path_sc_rollups : RPC_context.t RPC_path.context = + RPC_path.(prefix / "all") + + let kind = + RPC_service.get_service + ~description:"Kind of smart rollup" + ~query:RPC_query.empty + ~output:Sc_rollup.Kind.encoding + RPC_path.(path_sc_rollup / "kind") + + let genesis_info = + RPC_service.get_service + ~description: + "Genesis information (level and commitment hash) for a smart rollup" + ~query:RPC_query.empty + ~output:Sc_rollup.Commitment.genesis_info_encoding + RPC_path.(path_sc_rollup / "genesis_info") + + let last_cemented_commitment_hash_with_level = + RPC_service.get_service + ~description: + "Level and hash of the last cemented commitment for a smart rollup" + ~query:RPC_query.empty + ~output: + (obj2 + (req "hash" Sc_rollup.Commitment.Hash.encoding) + (req "level" Raw_level.encoding)) + RPC_path.(path_sc_rollup / "last_cemented_commitment_hash_with_level") + + let staked_on_commitment = + RPC_service.get_service + ~description: + "The newest commitment on which the operator has staked on for a \ + smart rollup. Note that is can return a commitment that is before \ + the last cemented one." + ~query:RPC_query.empty + ~output: + (option + (merge_objs + (obj1 (req "hash" Sc_rollup.Commitment.Hash.encoding)) + Sc_rollup.Commitment.encoding)) + RPC_path.( + path_sc_rollup / "staker" /: Sc_rollup.Staker.rpc_arg + / "staked_on_commitment") + + let commitment = + RPC_service.get_service + ~description:"Commitment for a smart rollup from its hash" + ~query:RPC_query.empty + ~output:Sc_rollup.Commitment.encoding + RPC_path.( + path_sc_rollup / "commitment" /: Sc_rollup.Commitment.Hash.rpc_arg) + + let dal_slot_subscriptions = + RPC_service.get_service + ~description: + "List of slot indices to which a rollup is subscribed to at a given \ + level" + ~query:RPC_query.empty + ~output:(Data_encoding.list Dal.Slot_index.encoding) + RPC_path.( + path_sc_rollup / "dal_slot_subscriptions" /: Raw_level.rpc_arg) + + let ongoing_refutation_games = + let output = + Sc_rollup.( + Data_encoding.( + list + (obj3 + (req "game" Game.encoding) + (req "alice" Staker.encoding) + (req "bob" Staker.encoding)))) + in + RPC_service.get_service + ~description:"Ongoing refutation games for a given staker" + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "staker" /: Sc_rollup.Staker.rpc_arg / "games") + + let commitments = + let output = + Data_encoding.(option (list Sc_rollup.Commitment.Hash.encoding)) + in + RPC_service.get_service + ~description: + "List of commitments associated to a rollup for a given inbox level" + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "inbox_level" /: Raw_level.rpc_arg / "commitments") + + let stakers_ids = + let output = Data_encoding.list Sc_rollup.Staker.Index.encoding in + RPC_service.get_service + ~description:"List of stakers indexes staking on a given commitment" + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "commitment" /: Sc_rollup.Commitment.Hash.rpc_arg + / "stakers_indexes") + + let staker_id = + let output = Sc_rollup.Staker.Index.encoding in + RPC_service.get_service + ~description: + "Staker index associated to a public key hash for a given rollup" + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "staker" /: Sc_rollup.Staker.rpc_arg / "index") + + let stakers = + let output = Data_encoding.list Sc_rollup.Staker.encoding in + RPC_service.get_service + ~description:"List of active stakers' public key hashes of a rollup" + ~query:RPC_query.empty + ~output + RPC_path.(path_sc_rollup / "stakers") + + let conflicts = + let output = + Sc_rollup.(Data_encoding.list Refutation_storage.conflict_encoding) + in + RPC_service.get_service + ~description:"List of stakers in conflict with the given staker" + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "staker" /: Sc_rollup.Staker.rpc_arg / "conflicts") + + let timeout = + let output = Data_encoding.option Sc_rollup.Game.timeout_encoding in + RPC_service.get_service + ~description:"Returns the timeout of players." + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "staker1" /: Sc_rollup.Staker.rpc_arg_staker1 + / "staker2" /: Sc_rollup.Staker.rpc_arg_staker2 / "timeout") + + let timeout_reached = + let output = Data_encoding.option Sc_rollup.Game.game_result_encoding in + RPC_service.get_service + ~description: + "Returns whether the timeout creates a result for the game." + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "staker1" /: Sc_rollup.Staker.rpc_arg_staker1 + / "staker2" /: Sc_rollup.Staker.rpc_arg_staker2 / "timeout_reached") + + let can_be_cemented = + let output = Data_encoding.bool in + RPC_service.get_service + ~description: + "Returns true if and only if the provided commitment can be cemented." + ~query:RPC_query.empty + ~output + RPC_path.( + path_sc_rollup / "commitment" /: Sc_rollup.Commitment.Hash.rpc_arg + / "can_be_cemented") + + let root = + RPC_service.get_service + ~description:"List of all originated smart rollups" + ~query:RPC_query.empty + ~output:(Data_encoding.list Sc_rollup.Address.encoding) + path_sc_rollups + + let inbox = + RPC_service.get_service + ~description:"Inbox for the smart rollups" + ~query:RPC_query.empty + ~output:Sc_rollup.Inbox.encoding + RPC_path.(path_sc_rollups / "inbox") + + let ticket_balance = + let open Data_encoding in + RPC_service.post_service + ~description: + "Access the smart rollup's balance of ticket with specified \ + ticketer, content type, and content." + ~query:RPC_query.empty + ~input:Ticket_token.unparsed_token_encoding + ~output:n + RPC_path.(path_sc_rollup / "ticket_balance") + + let whitelist = + RPC_service.get_service + ~description: + "Whitelist for private smart rollups. If the output is None then the \ + rollup is public." + ~query:RPC_query.empty + ~output:Data_encoding.(option Sc_rollup.Whitelist.encoding) + RPC_path.(path_sc_rollup / "whitelist") + + let last_whitelist_update = + RPC_service.get_service + ~description: + "Last whitelist update for private smart rollups. If the output is \ + None then the rollup is public." + ~query:RPC_query.empty + ~output: + Data_encoding.( + option Sc_rollup.Whitelist.last_whitelist_update_encoding) + RPC_path.(path_sc_rollup / "last_whitelist_update") + end + + let kind ctxt block sc_rollup_address = + RPC_context.make_call1 S.kind ctxt block sc_rollup_address () + + let register_inbox () = + let open Lwt_result_syntax in + Registration.register0 ~chunked:true S.inbox (fun ctxt () () -> + let+ inbox, _ctxt = Sc_rollup.Inbox.get_inbox ctxt in + inbox) + + let register_whitelist () = + Registration.register1 ~chunked:true S.whitelist (fun ctxt address () () -> + Sc_rollup.Whitelist.find_whitelist_uncarbonated ctxt address) + + let register_last_whitelist_update () = + let open Lwt_result_syntax in + Registration.register1 + ~chunked:true + S.last_whitelist_update + (fun ctxt address () () -> + let* ctxt, is_private = Sc_rollup.Whitelist.is_private ctxt address in + if is_private then + let* _ctxt, last_whitelist_update = + Sc_rollup.Whitelist.get_last_whitelist_update ctxt address + in + return_some last_whitelist_update + else return_none) + + let register_kind () = + let open Lwt_result_syntax in + Registration.opt_register1 ~chunked:true S.kind @@ fun ctxt address () () -> + let+ _ctxt, kind = Alpha_context.Sc_rollup.kind ctxt address in + Some kind + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2688 *) + let register_genesis_info () = + let open Lwt_result_syntax in + Registration.register1 ~chunked:true S.genesis_info + @@ fun ctxt address () () -> + let+ _ctxt, genesis_info = + Alpha_context.Sc_rollup.genesis_info ctxt address + in + genesis_info + + let register_last_cemented_commitment_hash_with_level () = + let open Lwt_result_syntax in + Registration.register1 + ~chunked:false + S.last_cemented_commitment_hash_with_level + @@ fun ctxt address () () -> + let+ last_cemented_commitment, level, _ctxt = + Alpha_context.Sc_rollup.Commitment + .last_cemented_commitment_hash_with_level + ctxt + address + in + (last_cemented_commitment, level) + + let register_staked_on_commitment () = + let open Lwt_result_syntax in + Registration.register2 ~chunked:false S.staked_on_commitment + @@ fun ctxt address staker () () -> + let* ctxt, commitment_hash = + Alpha_context.Sc_rollup.Stake_storage.find_staker ctxt address staker + in + match commitment_hash with + | None -> return_none + | Some commitment_hash -> + let+ commitment, _ctxt = + Alpha_context.Sc_rollup.Commitment.get_commitment + ctxt + address + commitment_hash + in + Some (commitment_hash, commitment) + + let register_commitment () = + let open Lwt_result_syntax in + Registration.register2 ~chunked:false S.commitment + @@ fun ctxt address commitment_hash () () -> + let+ commitment, _ = + Alpha_context.Sc_rollup.Commitment.get_commitment + ctxt + address + commitment_hash + in + commitment + + let register_root () = + Registration.register0 ~chunked:true S.root (fun context () () -> + Sc_rollup.list_unaccounted context) + + let register_ongoing_refutation_games () = + let open Lwt_result_syntax in + Registration.register2 + ~chunked:false + S.ongoing_refutation_games + (fun context rollup staker () () -> + let open Sc_rollup.Game.Index in + let open Sc_rollup.Refutation_storage in + let+ game, _ = get_ongoing_games_for_staker context rollup staker in + List.map (fun (game, index) -> (game, index.alice, index.bob)) game) + + let register_commitments () = + Registration.register2 + ~chunked:false + S.commitments + (fun context rollup inbox_level () () -> + Sc_rollup.Stake_storage.commitments_uncarbonated + context + ~rollup + ~inbox_level) + + let register_stakers_ids () = + Registration.register2 + ~chunked:false + S.stakers_ids + (fun context rollup commitment () () -> + Sc_rollup.Stake_storage.stakers_ids_uncarbonated + context + ~rollup + ~commitment) + + let register_staker_id () = + Registration.register2 + ~chunked:false + S.staker_id + (fun context rollup pkh () () -> + Sc_rollup.Stake_storage.staker_id_uncarbonated context ~rollup ~pkh) + + let register_stakers () = + let open Lwt_result_syntax in + Registration.register1 ~chunked:false S.stakers (fun context rollup () () -> + let*! stakers_pkhs = + Sc_rollup.Stake_storage.stakers_pkhs_uncarbonated context ~rollup + in + return stakers_pkhs) + + let register_conflicts () = + Registration.register2 + ~chunked:false + S.conflicts + (fun context rollup staker () () -> + Sc_rollup.Refutation_storage.conflicting_stakers_uncarbonated + context + rollup + staker) + + let register_timeout () = + let open Lwt_result_syntax in + Registration.register3 + ~chunked:false + S.timeout + (fun context rollup staker1 staker2 () () -> + let index = Sc_rollup.Game.Index.make staker1 staker2 in + let*! res = + Sc_rollup.Refutation_storage.get_timeout context rollup index + in + match res with + | Ok (timeout, _context) -> return_some timeout + | Error _ -> return_none) + + let register_timeout_reached () = + let open Lwt_result_syntax in + Registration.register3 + ~chunked:false + S.timeout_reached + (fun context rollup staker1 staker2 () () -> + let index = Sc_rollup.Game.Index.make staker1 staker2 in + let*! res = Sc_rollup.Refutation_storage.timeout context rollup index in + match res with + | Ok (game_result, _context) -> return_some game_result + | Error _ -> return_none) + + let register_can_be_cemented () = + let open Lwt_result_syntax in + Registration.register2 + ~chunked:false + S.can_be_cemented + (fun context rollup commitment_hash () () -> + let*! res = Sc_rollup.Stake_storage.cement_commitment context rollup in + match res with + | Ok (_context, _cemented_commitment, cemented_commitment_hash) + when Sc_rollup.Commitment.Hash.equal + commitment_hash + cemented_commitment_hash -> + return_true + | Ok _ | Error _ -> return_false) + + let register_ticket_balance () = + Registration.register1 + ~chunked:false + S.ticket_balance + (fun ctxt sc_rollup () Ticket_token.{ticketer; contents_type; contents} -> + let open Lwt_result_syntax in + let* ticket_hash, ctxt = + Ticket_balance_key.make + ctxt + ~owner:(Sc_rollup sc_rollup) + ~ticketer + ~contents_type:(Micheline.root contents_type) + ~contents:(Micheline.root contents) + in + let* amount, _ctxt = Ticket_balance.get_balance ctxt ticket_hash in + return @@ Option.value amount ~default:Z.zero) + + let register () = + register_kind () ; + register_inbox () ; + register_whitelist () ; + register_last_whitelist_update () ; + register_genesis_info () ; + register_last_cemented_commitment_hash_with_level () ; + register_staked_on_commitment () ; + register_commitment () ; + register_root () ; + register_ongoing_refutation_games () ; + register_commitments () ; + register_stakers_ids () ; + register_staker_id () ; + register_stakers () ; + register_conflicts () ; + register_timeout () ; + register_timeout_reached () ; + register_can_be_cemented () ; + register_ticket_balance () + + let list ctxt block = RPC_context.make_call0 S.root ctxt block () () + + let inbox ctxt block = RPC_context.make_call0 S.inbox ctxt block () () + + let whitelist ctxt block sc_rollup_address = + RPC_context.make_call1 S.whitelist ctxt block sc_rollup_address () () + + let last_whitelist_update ctxt block sc_rollup_address = + RPC_context.make_call1 + S.last_whitelist_update + ctxt + block + sc_rollup_address + () + () + + let genesis_info ctxt block sc_rollup_address = + RPC_context.make_call1 S.genesis_info ctxt block sc_rollup_address () () + + let last_cemented_commitment_hash_with_level ctxt block sc_rollup_address = + RPC_context.make_call1 + S.last_cemented_commitment_hash_with_level + ctxt + block + sc_rollup_address + () + () + + let staked_on_commitment ctxt block sc_rollup_address staker = + RPC_context.make_call2 + S.staked_on_commitment + ctxt + block + sc_rollup_address + staker + () + () + + let commitment ctxt block sc_rollup_address commitment_hash = + RPC_context.make_call2 + S.commitment + ctxt + block + sc_rollup_address + commitment_hash + () + () + + let ongoing_refutation_games ctxt block sc_rollup_address staker = + RPC_context.make_call2 + S.ongoing_refutation_games + ctxt + block + sc_rollup_address + staker + () + () + + let commitments ctxt rollup inbox_level = + RPC_context.make_call2 S.commitments ctxt rollup inbox_level + + let stakers_ids ctxt rollup commitment = + RPC_context.make_call2 S.stakers_ids ctxt rollup commitment + + let staker_id ctxt rollup pkh = + RPC_context.make_call2 S.staker_id ctxt rollup pkh + + let stakers ctxt rollup = RPC_context.make_call1 S.stakers ctxt rollup + + let conflicts ctxt block sc_rollup_address staker = + RPC_context.make_call2 S.conflicts ctxt block sc_rollup_address staker () () + + let timeout_reached ctxt block sc_rollup_address staker1 staker2 = + RPC_context.make_call3 + S.timeout_reached + ctxt + block + sc_rollup_address + staker1 + staker2 + () + () + + let can_be_cemented ctxt block sc_rollup_address commitment_hash = + RPC_context.make_call2 + S.can_be_cemented + ctxt + block + sc_rollup_address + commitment_hash + () + () + + let get_ticket_balance ctxt block sc_rollup key = + RPC_context.make_call1 S.ticket_balance ctxt block sc_rollup () key +end + +type Environment.Error_monad.error += + | Published_slot_headers_not_initialized of Raw_level.t + +let () = + Environment.Error_monad.register_error_kind + `Permanent + ~id:"published_slot_headers_not_initialized" + ~title:"The published slot headers bucket not initialized in the context" + ~description: + "The published slot headers bucket is not initialized in the context" + ~pp:(fun ppf level -> + Format.fprintf + ppf + "The published slot headers bucket is not initialized in the context \ + at level %a" + Raw_level.pp + level) + Data_encoding.(obj1 (req "level" Raw_level.encoding)) + (function + | Published_slot_headers_not_initialized level -> Some level | _ -> None) + (fun level -> Published_slot_headers_not_initialized level) + +module Dal = struct + let path : RPC_context.t RPC_path.context = + RPC_path.(open_root / "context" / "dal") + + module S = struct + let dal_commitments_history = + let output = Data_encoding.option Dal.Slots_history.encoding in + let query = RPC_query.(seal @@ query ()) in + RPC_service.get_service + ~description: + "Returns the (currently last) DAL skip list cell if DAL is enabled, \ + or [None] otherwise." + ~output + ~query + RPC_path.(path / "commitments_history") + + let level_query = + RPC_query.( + query (fun level -> level) + |+ opt_field "level" Raw_level.rpc_arg (fun t -> t) + |> seal) + + type shards_query = { + level : Raw_level.t option; + delegates : Signature.Public_key_hash.t list; + } + + let shards_query = + let open RPC_query in + query (fun level delegates -> {level; delegates}) + |+ opt_field "level" Raw_level.rpc_arg (fun t -> t.level) + |+ multi_field "delegates" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |> seal + + type shards_assignment = { + delegate : Signature.Public_key_hash.t; + indexes : int list; + } + + let shards_assignment_encoding = + let open Data_encoding in + conv + (fun {delegate; indexes} -> (delegate, indexes)) + (fun (delegate, indexes) -> {delegate; indexes}) + (obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "indexes" (list int16))) + + type shards_output = shards_assignment list + + let shards = + RPC_service.get_service + ~description: + "Get the shards assignment for a given level (the default is the \ + current level) and given delegates (the default is all delegates)" + ~query:shards_query + ~output:(Data_encoding.list shards_assignment_encoding) + RPC_path.(path / "shards") + + let published_slot_headers = + let output = Data_encoding.(list Dal.Slot.Header.encoding) in + RPC_service.get_service + ~description:"Get the published slots headers for the given level" + ~query:level_query + ~output + RPC_path.(path / "published_slot_headers") + end + + let register_dal_commitments_history () = + let open Lwt_result_syntax in + Registration.register0 + ~chunked:false + S.dal_commitments_history + (fun ctxt () () -> + if (Constants.parametric ctxt).dal.feature_enable then + let+ result = Dal.Slots_storage.get_slot_headers_history ctxt in + Option.some result + else return_none) + + let dal_commitments_history ctxt block = + RPC_context.make_call0 S.dal_commitments_history ctxt block () () + + let dal_shards ctxt block ?level ?(delegates = []) () = + RPC_context.make_call0 S.shards ctxt block {level; delegates} () + + let register_shards () = + Registration.register0 ~chunked:true S.shards @@ fun ctxt q () -> + let open Lwt_result_syntax in + let*? level_opt = + Option.map_e (Level.from_raw_with_offset ctxt ~offset:0l) q.level + in + let level = Option.value level_opt ~default:(Level.current ctxt) in + let* _ctxt, map = Dal_services.shards ctxt ~level in + let query_delegates = Signature.Public_key_hash.Set.of_list q.delegates in + let all_delegates = + Signature.Public_key_hash.Set.is_empty query_delegates + in + Signature.Public_key_hash.Map.fold + (fun delegate indexes acc -> + if + all_delegates + || Signature.Public_key_hash.Set.mem delegate query_delegates + then ({delegate; indexes} : S.shards_assignment) :: acc + else acc) + map + [] + |> return + + let dal_published_slot_headers ctxt block ?level () = + RPC_context.make_call0 S.published_slot_headers ctxt block level () + + let register_published_slot_headers () = + let open Lwt_result_syntax in + Registration.register0 ~chunked:true S.published_slot_headers + @@ fun ctxt level () -> + let level = Option.value level ~default:(Level.current ctxt).level in + let* result = Dal.Slot.find_slot_headers ctxt level in + match result with + | Some l -> return l + | None -> + Environment.Error_monad.tzfail + @@ Published_slot_headers_not_initialized level + + let register () = + register_dal_commitments_history () ; + register_shards () ; + register_published_slot_headers () +end + +module Forge = struct + module S = struct + open Data_encoding + + let path = RPC_path.(path / "forge") + + let operations_encoding = + union + [ + case + ~title:"operations_encoding" + (Tag 0) + Operation.unsigned_encoding + Option.some + Fun.id; + case + ~title:"operations_encoding_with_legacy_attestation_name" + Json_only + Operation.unsigned_encoding_with_legacy_attestation_name + Option.some + Fun.id; + ] + + let operations = + RPC_service.post_service + ~description:"Forge an operation" + ~query:RPC_query.empty + ~input:operations_encoding + ~output:(bytes Hex) + RPC_path.(path / "operations") + + let empty_proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '\000' + + let protocol_data = + RPC_service.post_service + ~description:"Forge the protocol-specific part of a block header" + ~query:RPC_query.empty + ~input: + (obj5 + (req "payload_hash" Block_payload_hash.encoding) + (req "payload_round" Round.encoding) + (opt "nonce_hash" Nonce_hash.encoding) + (dft + "proof_of_work_nonce" + (Fixed.bytes + Hex + Alpha_context.Constants.proof_of_work_nonce_size) + empty_proof_of_work_nonce) + Per_block_votes.( + dft + "per_block_votes" + per_block_votes_encoding + { + liquidity_baking_vote = Per_block_vote_pass; + adaptive_issuance_vote = Per_block_vote_pass; + })) + ~output:(obj1 (req "protocol_data" (bytes Hex))) + RPC_path.(path / "protocol_data") + end + + let register () = + let open Lwt_result_syntax in + Registration.register0_noctxt + ~chunked:true + S.operations + (fun () operation -> + return + (Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + operation)) ; + Registration.register0_noctxt + ~chunked:true + S.protocol_data + (fun + () + ( payload_hash, + payload_round, + seed_nonce_hash, + proof_of_work_nonce, + per_block_votes ) + -> + return + (Data_encoding.Binary.to_bytes_exn + Block_header.contents_encoding + { + payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce; + per_block_votes; + })) + + module Manager = struct + let operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee + ~gas_limit ~storage_limit operations = + let open Lwt_result_syntax in + let*! result = Contract_services.manager_key ctxt block source in + match result with + | Error _ as e -> Lwt.return e + | Ok revealed -> + let ops = + List.map + (fun (Manager operation) -> + Contents + (Manager_operation + {source; counter; operation; fee; gas_limit; storage_limit})) + operations + in + let ops = + match (sourcePubKey, revealed) with + | None, _ | _, Some _ -> ops + | Some pk, None -> + let operation = Reveal pk in + Contents + (Manager_operation + {source; counter; operation; fee; gas_limit; storage_limit}) + :: ops + in + let*? ops = Environment.wrap_tzresult @@ Operation.of_list ops in + RPC_context.make_call0 S.operations ctxt block () ({branch}, ops) + + let reveal ctxt block ~branch ~source ~sourcePubKey ~counter ~fee () = + operations + ctxt + block + ~branch + ~source + ~sourcePubKey + ~counter + ~fee + ~gas_limit:Gas.Arith.zero + ~storage_limit:Z.zero + [] + + let transaction ctxt block ~branch ~source ?sourcePubKey ~counter ~amount + ~destination ?(entrypoint = Entrypoint.default) ?parameters ~gas_limit + ~storage_limit ~fee () = + let parameters = + Option.fold + ~some:Script.lazy_expr + ~none:Script.unit_parameter + parameters + in + operations + ctxt + block + ~branch + ~source + ?sourcePubKey + ~counter + ~fee + ~gas_limit + ~storage_limit + [Manager (Transaction {amount; parameters; destination; entrypoint})] + + let origination ctxt block ~branch ~source ?sourcePubKey ~counter ~balance + ?delegatePubKey ~script ~gas_limit ~storage_limit ~fee () = + operations + ctxt + block + ~branch + ~source + ?sourcePubKey + ~counter + ~fee + ~gas_limit + ~storage_limit + [ + Manager + (Origination {delegate = delegatePubKey; script; credit = balance}); + ] + + let delegation ctxt block ~branch ~source ?sourcePubKey ~counter ~fee + delegate = + operations + ctxt + block + ~branch + ~source + ?sourcePubKey + ~counter + ~fee + ~gas_limit:Gas.Arith.zero + ~storage_limit:Z.zero + [Manager (Delegation delegate)] + end + + let operation ctxt block ~branch operation = + RPC_context.make_call0 + S.operations + ctxt + block + () + ({branch}, Contents_list (Single operation)) + + let attestation ctxt b ~branch ~consensus_content ?dal_content () = + operation ctxt b ~branch (Attestation {consensus_content; dal_content}) + + let proposals ctxt b ~branch ~source ~period ~proposals () = + operation ctxt b ~branch (Proposals {source; period; proposals}) + + let ballot ctxt b ~branch ~source ~period ~proposal ~ballot () = + operation ctxt b ~branch (Ballot {source; period; proposal; ballot}) + + let failing_noop ctxt b ~branch ~message () = + operation ctxt b ~branch (Failing_noop message) + + let seed_nonce_revelation ctxt block ~branch ~level ~nonce () = + operation ctxt block ~branch (Seed_nonce_revelation {level; nonce}) + + let vdf_revelation ctxt block ~branch ~solution () = + operation ctxt block ~branch (Vdf_revelation {solution}) + + let double_baking_evidence ctxt block ~branch ~bh1 ~bh2 () = + operation ctxt block ~branch (Double_baking_evidence {bh1; bh2}) + + let double_attestation_evidence ctxt block ~branch ~op1 ~op2 () = + operation ctxt block ~branch (Double_attestation_evidence {op1; op2}) + + let double_preattestation_evidence ctxt block ~branch ~op1 ~op2 () = + operation ctxt block ~branch (Double_preattestation_evidence {op1; op2}) + + let empty_proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '\000' + + let protocol_data ctxt block ?(payload_hash = Block_payload_hash.zero) + ?(payload_round = Round.zero) ?seed_nonce_hash + ?(proof_of_work_nonce = empty_proof_of_work_nonce) + ~liquidity_baking_toggle_vote ~adaptive_issuance_vote () = + RPC_context.make_call0 + S.protocol_data + ctxt + block + () + ( payload_hash, + payload_round, + seed_nonce_hash, + proof_of_work_nonce, + { + liquidity_baking_vote = liquidity_baking_toggle_vote; + adaptive_issuance_vote; + } ) +end + +module Parse = struct + module S = struct + open Data_encoding + + let path = RPC_path.(path / "parse") + + let operations_query = + let open RPC_query in + query (fun version -> + object + method version = version + end) + |+ field "version" version_arg default_operations_version (fun t -> + t#version) + |> seal + + let parse_operations_encoding = + encoding_versioning + ~encoding_name:"parse_operations" + ~latest_encoding:(Version_1, list (dynamic_size Operation.encoding)) + ~old_encodings: + [ + ( Version_0, + list + (dynamic_size Operation.encoding_with_legacy_attestation_name) + ); + ] + + let operations = + RPC_service.post_service + ~description:"Parse operations" + ~query:operations_query + ~input: + (obj2 + (req "operations" (list (dynamic_size Operation.raw_encoding))) + (opt "check_signature" bool)) + ~output:parse_operations_encoding + RPC_path.(path / "operations") + + let block = + RPC_service.post_service + ~description:"Parse a block" + ~query:RPC_query.empty + ~input:Block_header.raw_encoding + ~output:Block_header.protocol_data_encoding + RPC_path.(path / "block") + end + + let parse_protocol_data protocol_data = + match + Data_encoding.Binary.of_bytes_opt + Block_header.protocol_data_encoding + protocol_data + with + | None -> Stdlib.failwith "Cant_parse_protocol_data" + | Some protocol_data -> protocol_data + + let parse_operation (op : Operation.raw) = + let open Result_syntax in + match + Data_encoding.Binary.of_bytes_opt + Operation.protocol_data_encoding + op.proto + with + | Some protocol_data -> return {shell = op.shell; protocol_data} + | None -> Environment.Error_monad.error Plugin_errors.Cannot_parse_operation + + let register () = + let open Lwt_result_syntax in + Registration.register0 + ~chunked:true + S.operations + (fun _ctxt params (operations, check) -> + let* ops = + List.map_es + (fun raw -> + let*? op = parse_operation raw in + let () = + match check with + | Some true -> () + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/5702 + The signature of the parsed operation should be properly + checked *) + (* I.check_signature ctxt *) + (* op.protocol_data.signature op.shell op.protocol_data.contents *) + | Some false | None -> () + in + return op) + operations + in + let version = params#version in + return (version, ops)) ; + Registration.register0_noctxt ~chunked:false S.block (fun () raw_block -> + return @@ parse_protocol_data raw_block.protocol_data) + + let operations ctxt block ?(version = default_operations_version) ?check + operations = + let open Lwt_result_syntax in + let*! v = + RPC_context.make_call0 + S.operations + ctxt + block + (object + method version = version + end) + (operations, check) + in + match v with + | Error e -> tzfail e + | Ok ((Version_0 | Version_1), parse_operation) -> return parse_operation + + let block ctxt block shell protocol_data = + RPC_context.make_call0 + S.block + ctxt + block + () + ({shell; protocol_data} : Block_header.raw) +end + +(* Compute the estimated starting time of a [round] at a future + [level], given the head's level [current_level], timestamp + [current_timestamp], and round [current_round]. Assumes blocks at + intermediate levels are produced at round 0. *) +let estimated_time round_durations ~current_level ~current_round + ~current_timestamp ~level ~round = + let open Result_syntax in + if Level.(level <= current_level) then return_none + else + let* round_start_at_next_level = + Round.timestamp_of_round + round_durations + ~round + ~predecessor_timestamp:current_timestamp + ~predecessor_round:current_round + in + let step = Round.round_duration round_durations Round.zero in + let diff = Level.diff level current_level in + let* delay = Period.mult (Int32.pred diff) step in + let* timestamp = Timestamp.(round_start_at_next_level +? delay) in + return_some timestamp + +let requested_levels ~default_level ctxt cycles levels = + match (levels, cycles) with + | [], [] -> [default_level] + | levels, cycles -> + (* explicitly fail when requested levels or cycle are in the past... + or too far in the future... + TODO: https://gitlab.com/tezos/tezos/-/issues/2335 + this old comment (from version Alpha) conflicts with + the specification of the RPCs that use this code. + *) + List.sort_uniq + Level.compare + (List.rev_append + (List.rev_map (Level.from_raw ctxt) levels) + (List.concat_map (Level.levels_in_cycle ctxt) cycles)) + +module Baking_rights = struct + type t = { + level : Raw_level.t; + delegate : public_key_hash; + consensus_key : public_key_hash; + round : Round.t; + timestamp : Timestamp.t option; + } + + let encoding = + let open Data_encoding in + conv + (fun {level; delegate; consensus_key; round; timestamp} -> + (level, delegate, round, timestamp, consensus_key)) + (fun (level, delegate, round, timestamp, consensus_key) -> + {level; delegate; consensus_key; round; timestamp}) + (obj5 + (req "level" Raw_level.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "round" Round.encoding) + (opt "estimated_time" Timestamp.encoding) + (req "consensus_key" Signature.Public_key_hash.encoding)) + + let default_max_round = 64 + + module S = struct + open Data_encoding + + let path = RPC_path.(open_root / "helpers" / "baking_rights") + + type baking_rights_query = { + levels : Raw_level.t list; + cycle : Cycle.t option; + delegates : Signature.Public_key_hash.t list; + consensus_keys : Signature.Public_key_hash.t list; + max_round : int option; + all : bool; + } + + let baking_rights_query = + let open RPC_query in + query (fun levels cycle delegates consensus_keys max_round all -> + {levels; cycle; delegates; consensus_keys; max_round; all}) + |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) + |+ opt_field "cycle" Cycle.rpc_arg (fun t -> t.cycle) + |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |+ multi_field "consensus_key" Signature.Public_key_hash.rpc_arg (fun t -> + t.consensus_keys) + |+ opt_field "max_round" RPC_arg.uint (fun t -> t.max_round) + |+ flag "all" (fun t -> t.all) + |> seal + + let baking_rights = + RPC_service.get_service + ~description: + (Format.sprintf + "Retrieves the list of delegates allowed to bake a block.\n\ + By default, it gives the best baking opportunities (in terms of \ + rounds) for bakers that have at least one opportunity below the \ + %dth round for the next block.\n\ + Parameters `level` and `cycle` can be used to specify the \ + (valid) level(s) in the past or future at which the baking \ + rights have to be returned.\n\ + Parameter `delegate` can be used to restrict the results to the \ + given delegates. Parameter `consensus_key` can be used to \ + restrict the results to the given consensus_keys. If parameter \ + `all` is set, all the baking opportunities for each baker at \ + each level are returned, instead of just the first one.\n\ + Returns the list of baking opportunities up to round %d. Also \ + returns the minimal timestamps that correspond to these \ + opportunities. The timestamps are omitted for levels in the \ + past, and are only estimates for levels higher that the next \ + block's, based on the hypothesis that all predecessor blocks \ + were baked at the first round." + default_max_round + default_max_round) + ~query:baking_rights_query + ~output:(list encoding) + path + end + + let baking_rights_at_level ctxt max_round level = + let open Lwt_result_syntax in + let* current_round = Round.get ctxt in + let current_level = Level.current ctxt in + let current_timestamp = Timestamp.current ctxt in + let round_durations = Alpha_context.Constants.round_durations ctxt in + let rec loop ctxt acc round = + if Round.(round > max_round) then + (* returns the ctxt with an updated cache of slot holders *) + return (ctxt, List.rev acc) + else + let* ( ctxt, + _slot, + {Consensus_key.consensus_pkh; delegate; consensus_pk = _} ) = + Stake_distribution.baking_rights_owner ctxt level ~round + in + let*? timestamp = + estimated_time + round_durations + ~current_level + ~current_round + ~current_timestamp + ~level + ~round + in + let acc = + { + level = level.level; + delegate; + consensus_key = consensus_pkh; + round; + timestamp; + } + :: acc + in + loop ctxt acc (Round.succ round) + in + loop ctxt [] Round.zero + + let remove_duplicated_delegates rights = + List.rev @@ fst + @@ List.fold_left + (fun (acc, previous) r -> + if + Signature.Public_key_hash.Set.exists + (Signature.Public_key_hash.equal r.delegate) + previous + then (acc, previous) + else (r :: acc, Signature.Public_key_hash.Set.add r.delegate previous)) + ([], Signature.Public_key_hash.Set.empty) + rights + + let register () = + let open Lwt_result_syntax in + Registration.register0 ~chunked:true S.baking_rights (fun ctxt q () -> + let cycles = match q.cycle with None -> [] | Some cycle -> [cycle] in + let levels = + requested_levels + ~default_level:(Level.succ ctxt (Level.current ctxt)) + ctxt + cycles + q.levels + in + let*? max_round = + Round.of_int + (match q.max_round with + | None -> default_max_round + | Some max_round -> + Compare.Int.min + max_round + (Constants.consensus_committee_size ctxt)) + in + let+ _ctxt, rights = + List.fold_left_map_es + (fun ctxt l -> baking_rights_at_level ctxt max_round l) + ctxt + levels + in + let rights = + if q.all then List.concat rights + else List.concat_map remove_duplicated_delegates rights + in + let rights = + match q.delegates with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.delegate) + delegates + in + List.filter is_requested rights + in + let rights = + match q.consensus_keys with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.consensus_key) + delegates + in + List.filter is_requested rights + in + rights) + + let get ctxt ?(levels = []) ?cycle ?(delegates = []) ?(consensus_keys = []) + ?(all = false) ?max_round block = + RPC_context.make_call0 + S.baking_rights + ctxt + block + {levels; cycle; delegates; consensus_keys; max_round; all} + () +end + +module Attestation_rights = struct + type delegate_rights = { + delegate : Signature.Public_key_hash.t; + consensus_key : Signature.Public_key_hash.t; + first_slot : Slot.t; + attestation_power : int; + } + + type t = { + level : Raw_level.t; + delegates_rights : delegate_rights list; + estimated_time : Time.t option; + } + + let delegate_rights_encoding = + let open Data_encoding in + conv + (fun {delegate; consensus_key; first_slot; attestation_power} -> + (delegate, first_slot, attestation_power, consensus_key)) + (fun (delegate, first_slot, attestation_power, consensus_key) -> + {delegate; first_slot; attestation_power; consensus_key}) + (obj4 + (req "delegate" Signature.Public_key_hash.encoding) + (req "first_slot" Slot.encoding) + (req "attestation_power" uint16) + (req "consensus_key" Signature.Public_key_hash.encoding)) + + let encoding = + let open Data_encoding in + conv + (fun {level; delegates_rights; estimated_time} -> + (level, delegates_rights, estimated_time)) + (fun (level, delegates_rights, estimated_time) -> + {level; delegates_rights; estimated_time}) + (obj3 + (req "level" Raw_level.encoding) + (req "delegates" (list delegate_rights_encoding)) + (opt "estimated_time" Timestamp.encoding)) + + module S = struct + open Data_encoding + + let attestation_path = RPC_path.(path / "attestation_rights") + + type attestation_rights_query = { + levels : Raw_level.t list; + cycle : Cycle.t option; + delegates : Signature.Public_key_hash.t list; + consensus_keys : Signature.Public_key_hash.t list; + } + + let attestation_rights_query = + let open RPC_query in + query (fun levels cycle delegates consensus_keys -> + {levels; cycle; delegates; consensus_keys}) + |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) + |+ opt_field "cycle" Cycle.rpc_arg (fun t -> t.cycle) + |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |+ multi_field "consensus_key" Signature.Public_key_hash.rpc_arg (fun t -> + t.consensus_keys) + |> seal + + let attestation_rights = + RPC_service.get_service + ~description: + "Retrieves the delegates allowed to attest a block.\n\ + By default, it gives the attestation power for delegates that have \ + at least one attestation slot for the next block.\n\ + Parameters `level` and `cycle` can be used to specify the (valid) \ + level(s) in the past or future at which the attestation rights have \ + to be returned. Parameter `delegate` can be used to restrict the \ + results to the given delegates.\n\ + Parameter `consensus_key` can be used to restrict the results to \ + the given consensus_keys. \n\ + Returns the smallest attestation slots and the attestation power. \ + Also returns the minimal timestamp that corresponds to attestation \ + at the given level. The timestamps are omitted for levels in the \ + past, and are only estimates for levels higher that the next \ + block's, based on the hypothesis that all predecessor blocks were \ + baked at the first round." + ~query:attestation_rights_query + ~output:(list encoding) + attestation_path + end + + let attestation_rights_at_level ctxt level = + let open Lwt_result_syntax in + let* ctxt, rights = Baking.attesting_rights_by_first_slot ctxt level in + let* current_round = Round.get ctxt in + let current_level = Level.current ctxt in + let current_timestamp = Timestamp.current ctxt in + let round_durations = Alpha_context.Constants.round_durations ctxt in + let*? estimated_time = + estimated_time + round_durations + ~current_level + ~current_round + ~current_timestamp + ~level + ~round:Round.zero + in + let rights = + Slot.Map.fold + (fun first_slot + ( { + Consensus_key.delegate; + consensus_pk = _; + consensus_pkh = consensus_key; + }, + attestation_power, + _dal_power ) + acc -> + {delegate; consensus_key; first_slot; attestation_power} :: acc) + rights + [] + in + (* returns the ctxt with an updated cache of slot holders *) + return + (ctxt, {level = level.level; delegates_rights = rights; estimated_time}) + + let get_attestation_rights ctxt (q : S.attestation_rights_query) = + let open Lwt_result_syntax in + let cycles = match q.cycle with None -> [] | Some cycle -> [cycle] in + let levels = + requested_levels ~default_level:(Level.current ctxt) ctxt cycles q.levels + in + let+ _ctxt, rights_per_level = + List.fold_left_map_es attestation_rights_at_level ctxt levels + in + let rights_per_level = + match (q.consensus_keys, q.delegates) with + | [], [] -> rights_per_level + | _, _ -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.consensus_key) + q.consensus_keys + || List.exists + (Signature.Public_key_hash.equal p.delegate) + q.delegates + in + List.filter_map + (fun rights_at_level -> + match + List.filter is_requested rights_at_level.delegates_rights + with + | [] -> None + | delegates_rights -> Some {rights_at_level with delegates_rights}) + rights_per_level + in + rights_per_level + + let register () = + Registration.register0 ~chunked:true S.attestation_rights (fun ctxt q () -> + get_attestation_rights ctxt q) + + let get ctxt ?(levels = []) ?cycle ?(delegates = []) ?(consensus_keys = []) + block = + RPC_context.make_call0 + S.attestation_rights + ctxt + block + {levels; cycle; delegates; consensus_keys} + () +end + +module Validators = struct + type t = { + level : Raw_level.t; + delegate : Signature.Public_key_hash.t; + consensus_key : Signature.public_key_hash; + slots : Slot.t list; + } + + let encoding = + let open Data_encoding in + conv + (fun {level; delegate; consensus_key; slots} -> + (level, delegate, slots, consensus_key)) + (fun (level, delegate, slots, consensus_key) -> + {level; delegate; consensus_key; slots}) + (obj4 + (req "level" Raw_level.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "slots" (list Slot.encoding)) + (req "consensus_key" Signature.Public_key_hash.encoding)) + + module S = struct + open Data_encoding + + let path = RPC_path.(path / "validators") + + type validators_query = { + levels : Raw_level.t list; + delegates : Signature.Public_key_hash.t list; + consensus_keys : Signature.Public_key_hash.t list; + } + + let validators_query = + let open RPC_query in + query (fun levels delegates consensus_keys -> + {levels; delegates; consensus_keys}) + |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) + |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |+ multi_field "consensus_key" Signature.Public_key_hash.rpc_arg (fun t -> + t.consensus_keys) + |> seal + + let validators = + RPC_service.get_service + ~description: + "Retrieves the level, the attestation slots and the public key hash \ + of each delegate allowed to attest a block.\n\ + By default, it provides this information for the next level.\n\ + Parameter `level` can be used to specify the (valid) level(s) in \ + the past or future at which the attestation rights have to be \ + returned. Parameter `delegate` can be used to restrict the results \ + results to the given delegates. Parameter `consensus_key` can be \ + used to restrict the results to the given consensus_keys.\n" + ~query:validators_query + ~output:(list encoding) + path + end + + let add_attestation_slots_at_level (ctxt, acc) level = + let open Lwt_result_syntax in + let+ ctxt, rights = Baking.attesting_rights ctxt level in + ( ctxt, + Signature.Public_key_hash.Map.fold + (fun _pkh {Baking.delegate; consensus_key; slots} acc -> + {level = level.level; delegate; consensus_key; slots} :: acc) + rights + acc ) + + let register () = + let open Lwt_result_syntax in + Registration.register0 ~chunked:true S.validators (fun ctxt q () -> + let levels = + requested_levels ~default_level:(Level.current ctxt) ctxt [] q.levels + in + let+ _ctxt, rights = + List.fold_left_es + add_attestation_slots_at_level + (ctxt, []) + (List.rev levels) + in + let rights = + match q.delegates with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.delegate) + delegates + in + List.filter is_requested rights + in + let rights = + match q.consensus_keys with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.consensus_key) + delegates + in + List.filter is_requested rights + in + rights) + + let get ctxt ?(levels = []) ?(delegates = []) ?(consensus_keys = []) block = + RPC_context.make_call0 + S.validators + ctxt + block + {levels; delegates; consensus_keys} + () +end + +module Delegates = struct + let check_delegate_registered ctxt pkh = + let open Lwt_result_syntax in + let*! result = Delegate.registered ctxt pkh in + if result then return_unit + else Environment.Error_monad.tzfail (Delegate_services.Not_registered pkh) + + module S = struct + let path = + RPC_path.( + open_root / "context" / "delegates" /: Signature.Public_key_hash.rpc_arg) + + let info = + RPC_service.get_service + ~description:"Everything about a delegate." + ~query:RPC_query.empty + ~output:Delegate_services.info_encoding + path + + let delegated_balance = + RPC_service.get_service + ~description: + "Returns the sum (in mutez) of all balances of all the contracts \ + that delegate to a given delegate. This excludes the delegate's own \ + balance, its frozen deposits and its frozen bonds." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "delegated_balance") + end + + let unstake_requests ctxt pkh = + let open Lwt_result_syntax in + let* result = Unstake_requests.prepare_finalize_unstake ctxt pkh in + match result with + | None -> return_none + | Some {finalizable; unfinalizable} -> + let* unfinalizable = + Unstake_requests.For_RPC + .apply_slash_to_unstaked_unfinalizable_stored_requests + ctxt + unfinalizable + in + return_some Unstake_requests.{finalizable; unfinalizable} + + let overrided_delegated_balance ctxt pkh = + let open Lwt_result_syntax in + let* full_balance = Delegate.For_RPC.full_balance ctxt pkh in + let* unstake_requests = unstake_requests ctxt (Implicit pkh) in + let* unstake_requests_to_other_delegates = + match unstake_requests with + | None -> return Tez.zero + | Some {finalizable; unfinalizable} -> + let* finalizable_sum = + List.fold_left_es + (fun acc (delegate, _, (amount : Tez.t)) -> + if Signature.Public_key_hash.(delegate <> pkh) then + Lwt.return Tez.(acc +? amount) + else return acc) + Tez.zero + finalizable + in + let* unfinalizable_sum = + if Signature.Public_key_hash.(unfinalizable.delegate <> pkh) then + List.fold_left_es + (fun acc (_, (amount : Tez.t)) -> + Lwt.return Tez.(acc +? amount)) + Tez.zero + unfinalizable.requests + else return Tez.zero + in + Lwt.return Tez.(finalizable_sum +? unfinalizable_sum) + in + let* staking_balance = Delegate.For_RPC.staking_balance ctxt pkh in + let*? self_staking_balance = + Tez.(full_balance -? unstake_requests_to_other_delegates) + in + let*? sum = Tez.(staking_balance -? self_staking_balance) in + return sum + + let info ctxt pkh = + let open Lwt_result_syntax in + let open Delegate_services in + let* () = check_delegate_registered ctxt pkh in + let* full_balance = Delegate.For_RPC.full_balance ctxt pkh in + let* current_frozen_deposits = Delegate.current_frozen_deposits ctxt pkh in + let* frozen_deposits = Delegate.initial_frozen_deposits ctxt pkh in + let* staking_balance = Delegate.For_RPC.staking_balance ctxt pkh in + let* frozen_deposits_limit = Delegate.frozen_deposits_limit ctxt pkh in + let*! delegated_contracts = Delegate.delegated_contracts ctxt pkh in + let* delegated_balance = overrided_delegated_balance ctxt pkh in + let* min_delegated_in_current_cycle = + Delegate.For_RPC.min_delegated_in_current_cycle ctxt pkh + in + let* total_delegated_stake = + Staking_pseudotokens.For_RPC.get_frozen_deposits_staked_tez + ctxt + ~delegate:pkh + in + let* staking_denominator = + Staking_pseudotokens.For_RPC.get_frozen_deposits_pseudotokens + ctxt + ~delegate:pkh + in + let* deactivated = Delegate.deactivated ctxt pkh in + let* grace_period = Delegate.last_cycle_before_deactivation ctxt pkh in + let*! pending_denunciations = + Delegate.For_RPC.has_pending_denunciations ctxt pkh + in + let* voting_info = Vote.get_delegate_info ctxt pkh in + let* consensus_key = Delegate.Consensus_key.active_pubkey ctxt pkh in + let+ pendings = Delegate.Consensus_key.pending_updates ctxt pkh in + let pending_consensus_keys = + List.map (fun (cycle, pkh, _) -> (cycle, pkh)) pendings + in + { + full_balance; + current_frozen_deposits; + frozen_deposits; + staking_balance; + frozen_deposits_limit; + delegated_contracts; + delegated_balance; + min_delegated_in_current_cycle; + total_delegated_stake; + staking_denominator; + deactivated; + grace_period; + pending_denunciations; + voting_info; + active_consensus_key = consensus_key.consensus_pkh; + pending_consensus_keys; + } + + let register () = + let open Lwt_result_syntax in + Registration.register1 ~chunked:false S.info (fun ctxt pkh () () -> + info ctxt pkh) ; + Registration.register1 + ~chunked:false + S.delegated_balance + (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + overrided_delegated_balance ctxt pkh) + + let delegated_balance ctxt block pkh = + RPC_context.make_call1 S.delegated_balance ctxt block pkh () () + + let info ctxt block pkh = RPC_context.make_call1 S.info ctxt block pkh () () +end + +module Staking = struct + let path = + RPC_path.( + open_root / "context" / "delegates" /: Signature.Public_key_hash.rpc_arg) + + let stakers_encoding = + let open Data_encoding in + let staker_enconding = + obj2 + (req "staker" Alpha_context.Contract.implicit_encoding) + (req "frozen_deposits" Tez.encoding) + in + list staker_enconding + + module S = struct + let stakers = + RPC_service.get_service + ~description: + "Returns the list of accounts that stake to a given delegate \ + together with their share of the frozen deposits." + ~query:RPC_query.empty + ~output:stakers_encoding + RPC_path.(path / "stakers") + + let is_forbidden = + RPC_service.get_service + ~description: + "Returns true if the delegate is forbidden to participate in \ + consensus." + ~query:RPC_query.empty + ~output:Data_encoding.bool + RPC_path.(path / "is_forbidden") + end + + let contract_stake ctxt ~delegator_contract ~delegate = + let open Alpha_context in + let open Lwt_result_syntax in + let* staked_balance = + Staking_pseudotokens.For_RPC.staked_balance + ctxt + ~contract:delegator_contract + ~delegate + in + if not Tez.(staked_balance = zero) then + let delegator_pkh = + match delegator_contract with + | Contract.Implicit pkh -> pkh + | Contract.Originated _ -> assert false + (* Originated contracts cannot stake *) + in + return @@ Some (delegator_pkh, staked_balance) + else return_none + + let check_is_forbidden ctxt pkh = + let open Lwt_result_syntax in + return @@ Delegate.is_forbidden_delegate ctxt pkh + + let register () = + Registration.register1 ~chunked:false S.is_forbidden (fun ctxt pkh () () -> + check_is_forbidden ctxt pkh) ; + Registration.register1 ~chunked:true S.stakers (fun ctxt pkh () () -> + let open Lwt_result_syntax in + let* () = Delegates.check_delegate_registered ctxt pkh in + let*! delegators = Delegate.delegated_contracts ctxt pkh in + List.filter_map_es + (fun delegator_contract -> + contract_stake ctxt ~delegator_contract ~delegate:pkh) + delegators) + + let stakers ctxt block pkh = + RPC_context.make_call1 S.stakers ctxt block pkh () () +end + +module S = struct + open Data_encoding + + type level_query = {offset : int32} + + let level_query : level_query RPC_query.t = + let open RPC_query in + query (fun offset -> {offset}) + |+ field "offset" RPC_arg.int32 0l (fun t -> t.offset) + |> seal + + let current_level = + RPC_service.get_service + ~description: + "Returns the level of the interrogated block, or the one of a block \ + located `offset` blocks after it in the chain. For instance, the next \ + block if `offset` is 1. The offset cannot be negative." + ~query:level_query + ~output:Level.encoding + RPC_path.(path / "current_level") + + let levels_in_current_cycle = + RPC_service.get_service + ~description:"Levels of a cycle" + ~query:level_query + ~output: + (obj2 (req "first" Raw_level.encoding) (req "last" Raw_level.encoding)) + RPC_path.(path / "levels_in_current_cycle") + + let round = + RPC_service.get_service + ~description: + "Returns the round of the interrogated block, or the one of a block \ + located `offset` blocks after in the chain (or before when negative). \ + For instance, the next block if `offset` is 1." + ~query:RPC_query.empty + ~output:Round.encoding + RPC_path.(path / "round") +end + +type Environment.Error_monad.error += Negative_level_offset + +let () = + Environment.Error_monad.register_error_kind + `Permanent + ~id:"negative_level_offset" + ~title:"The specified level offset is negative" + ~description:"The specified level offset is negative" + ~pp:(fun ppf () -> + Format.fprintf ppf "The specified level offset should be positive.") + Data_encoding.unit + (function Negative_level_offset -> Some () | _ -> None) + (fun () -> Negative_level_offset) + +let register () = + let open Lwt_result_syntax in + Scripts.register () ; + Forge.register () ; + Parse.register () ; + Contract.register () ; + Big_map.register () ; + Baking_rights.register () ; + Attestation_rights.register () ; + Validators.register () ; + Sc_rollup.register () ; + Dal.register () ; + Staking.register () ; + Delegates.register () ; + Registration.register0 ~chunked:false S.current_level (fun ctxt q () -> + if q.offset < 0l then Environment.Error_monad.tzfail Negative_level_offset + else + Lwt.return + (Level.from_raw_with_offset + ctxt + ~offset:q.offset + (Level.current ctxt).level)) ; + Registration.opt_register0 + ~chunked:true + S.levels_in_current_cycle + (fun ctxt q () -> + let rev_levels = Level.levels_in_current_cycle ctxt ~offset:q.offset () in + match rev_levels with + | [] -> return_none + | [level] -> return_some (level.level, level.level) + | last :: default_first :: rest -> + (* The [rev_levels] list is reversed, the last level is the head *) + let first = List.last default_first rest in + return_some (first.level, last.level)) ; + Registration.register0 ~chunked:false S.round (fun ctxt () () -> + Round.get ctxt) + +let current_level ctxt ?(offset = 0l) block = + RPC_context.make_call0 S.current_level ctxt block {offset} () + +let levels_in_current_cycle ctxt ?(offset = 0l) block = + RPC_context.make_call0 S.levels_in_current_cycle ctxt block {offset} () + +let rpc_services = + register () ; + RPC_directory.merge + ~strategy:`Pick_right + rpc_services + !Registration.patched_services diff --git a/src/proto_020_PsParisC/lib_plugin/dune b/src/proto_020_PsParisC/lib_plugin/dune new file mode 100644 index 000000000000..f9f974d571fb --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/dune @@ -0,0 +1,36 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_protocol_plugin_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.plugin) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.smart-rollup) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_smart_rollup_019_PtParisB) + (modules (:standard \ Plugin_registerer))) + +(documentation (package octez-protocol-019-PtParisB-libs)) + +(library + (name tezos_protocol_plugin_019_PtParisB_registerer) + (public_name octez-protocol-019-PtParisB-libs.plugin-registerer) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.embedded-protocol + octez-protocol-019-PtParisB-libs.plugin + octez-shell-libs.validation) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_embedded_protocol_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_validation) + (modules Plugin_registerer)) diff --git a/src/proto_020_PsParisC/lib_plugin/index.mld b/src/proto_020_PsParisC/lib_plugin/index.mld new file mode 100644 index 000000000000..5df8df340496 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/index.mld @@ -0,0 +1,17 @@ +{0 Octez-protocol-019-PtParisB-libs: octez protocol 019-PtParisB libraries} + +This is a package containing some libraries related to the Tezos 019-PtParisB protocol. + +It contains the following libraries: + +- {{!module-Tezos_019_PtParisB_test_helpers}Tezos_019_PtParisB_test_helpers}: Protocol testing framework +- {{!module-Tezos_baking_019_PtParisB}Tezos_baking_019_PtParisB}: Base library for `tezos-baker/accuser` +- {{!module-Tezos_baking_019_PtParisB_commands}Tezos_baking_019_PtParisB_commands}: Protocol-specific commands for baking +- {{!module-Tezos_client_019_PtParisB}Tezos_client_019_PtParisB}: Protocol specific library for `octez-client` +- {{!module-Tezos_dac_019_PtParisB}Tezos_dac_019_PtParisB}: Protocol specific library for the Data availability Committee +- {{!module-Tezos_dal_019_PtParisB}Tezos_dal_019_PtParisB}: Protocol specific library for the Data availability Layer +- {{!module-Tezos_layer2_utils_019_PtParisB}Tezos_layer2_utils_019_PtParisB}: Protocol specific library for Layer 2 utils +- {{!module-Tezos_protocol_plugin_019_PtParisB}Tezos_protocol_plugin_019_PtParisB}: Protocol plugin +- {{!module-Tezos_protocol_plugin_019_PtParisB_registerer}Tezos_protocol_plugin_019_PtParisB_registerer}: Protocol plugin registerer +- {{!module-Tezos_smart_rollup_019_PtParisB}Tezos_smart_rollup_019_PtParisB}: Protocol specific library of helpers for `tezos-smart-rollup` +- {{!module-Tezos_smart_rollup_layer2_019_PtParisB}Tezos_smart_rollup_layer2_019_PtParisB}: Protocol specific library for `tezos-smart-rollup` diff --git a/src/proto_020_PsParisC/lib_plugin/mempool.ml b/src/proto_020_PsParisC/lib_plugin/mempool.ml new file mode 100644 index 000000000000..59db951878d8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/mempool.ml @@ -0,0 +1,793 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type nanotez = Q.t + +let nanotez_enc : nanotez Data_encoding.t = + let open Data_encoding in + def + "nanotez" + ~title:"A thousandth of a mutez" + ~description:"One thousand nanotez make a mutez (1 tez = 1e9 nanotez)" + (conv + (fun q -> (q.Q.num, q.Q.den)) + (fun (num, den) -> {Q.num; den}) + (tup2 z z)) + +let manager_op_replacement_factor_enc : Q.t Data_encoding.t = + let open Data_encoding in + def + "manager operation replacement factor" + ~title:"A manager operation's replacement factor" + ~description:"The fee and fee/gas ratio of an operation to replace another" + (conv + (fun q -> (q.Q.num, q.Q.den)) + (fun (num, den) -> {Q.num; den}) + (tup2 z z)) + +type config = { + minimal_fees : Tez.t; + minimal_nanotez_per_gas_unit : nanotez; + minimal_nanotez_per_byte : nanotez; + clock_drift : Period.t option; + replace_by_fee_factor : Q.t; + (** Factor by which the fee and fee/gas ratio of an old operation in + the mempool are both multiplied to determine the values that a new + operation must exceed in order to replace the old operation. See + the [better_fees_and_ratio] function further below. *) +} + +let default_minimal_fees = + match Tez.of_mutez 100L with None -> assert false | Some t -> t + +let default_minimal_nanotez_per_gas_unit = Q.of_int 100 + +let default_minimal_nanotez_per_byte = Q.of_int 1000 + +let managers_quota = + Stdlib.List.nth Main.validation_passes Operation_repr.manager_pass + +(* If the drift is not specified, it will be the duration of round zero. + It allows only to spam with one future round. + + /!\ Warning /!\ : current plugin implementation implies that this drift + cumulates with the accepted drift regarding the current head's timestamp. +*) +let default_config = + { + minimal_fees = default_minimal_fees; + minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; + clock_drift = None; + replace_by_fee_factor = + Q.make (Z.of_int 105) (Z.of_int 100) + (* Default value of [replace_by_fee_factor] is set to 5% *); + } + +let config_encoding : config Data_encoding.t = + let open Data_encoding in + conv + (fun { + minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + clock_drift; + replace_by_fee_factor; + } -> + ( minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + clock_drift, + replace_by_fee_factor )) + (fun ( minimal_fees, + minimal_nanotez_per_gas_unit, + minimal_nanotez_per_byte, + clock_drift, + replace_by_fee_factor ) -> + { + minimal_fees; + minimal_nanotez_per_gas_unit; + minimal_nanotez_per_byte; + clock_drift; + replace_by_fee_factor; + }) + (obj5 + (dft "minimal_fees" Tez.encoding default_config.minimal_fees) + (dft + "minimal_nanotez_per_gas_unit" + nanotez_enc + default_config.minimal_nanotez_per_gas_unit) + (dft + "minimal_nanotez_per_byte" + nanotez_enc + default_config.minimal_nanotez_per_byte) + (opt "clock_drift" Period.encoding) + (dft + "replace_by_fee_factor" + manager_op_replacement_factor_enc + default_config.replace_by_fee_factor)) + +(** Static information to store in the filter state. *) +type info = { + head : Block_header.shell_header; + round_durations : Round.round_durations; + hard_gas_limit_per_block : Gas.Arith.integral; + head_round : Round.t; + round_zero_duration : Period.t; + grandparent_level_start : Timestamp.t; +} + +let init_state_prototzresult ~head round_durations hard_gas_limit_per_block = + let open Lwt_result_syntax in + let*? head_round = + Alpha_context.Fitness.round_from_raw head.Tezos_base.Block_header.fitness + in + let round_zero_duration = Round.round_duration round_durations Round.zero in + let*? grandparent_round = + Alpha_context.Fitness.predecessor_round_from_raw head.fitness + in + let*? proposal_level_offset = + Round.level_offset_of_round + round_durations + ~round:Round.(succ grandparent_round) + in + let*? proposal_round_offset = + Round.level_offset_of_round round_durations ~round:head_round + in + let*? proposal_offset = + Period.(add proposal_level_offset proposal_round_offset) + in + let grandparent_level_start = Timestamp.(head.timestamp - proposal_offset) in + return + { + head; + round_durations; + hard_gas_limit_per_block; + head_round; + round_zero_duration; + grandparent_level_start; + } + +let init_state ~head round_durations hard_gas_limit_per_block = + Lwt.map + Environment.wrap_tzresult + (init_state_prototzresult ~head round_durations hard_gas_limit_per_block) + +let init context ~(head : Tezos_base.Block_header.shell_header) = + let open Lwt_result_syntax in + let* ( ctxt, + (_ : Receipt.balance_updates), + (_ : Migration.origination_result list) ) = + prepare + context + ~level:(Int32.succ head.level) + ~predecessor_timestamp:head.timestamp + ~timestamp:head.timestamp + |> Lwt.map Environment.wrap_tzresult + in + let round_durations = Constants.round_durations ctxt in + let hard_gas_limit_per_block = Constants.hard_gas_limit_per_block ctxt in + init_state ~head round_durations hard_gas_limit_per_block + +let flush old_info ~head = + (* To avoid the need to prepare a context as in [init], we retrieve + the [round_durations] from the previous state. Indeed, they are + only determined by the [minimal_block_delay] and + [delay_increment_per_round] constants (see + {!Raw_context.prepare}), and all the constants remain unchanged + during the lifetime of a protocol. As to + [hard_gas_limit_per_block], it is directly a protocol + constant. *) + init_state ~head old_info.round_durations old_info.hard_gas_limit_per_block + +let manager_prio p = `Low p + +let consensus_prio = `High + +let other_prio = `Medium + +let compute_manager_contents_fee_and_gas_limit contents = + let open Operation in + let l = to_list (Contents_list contents) in + List.fold_left + (fun acc -> function + | Contents (Manager_operation {fee; gas_limit; _}) -> ( + match acc with + | Error _ as e -> e + | Ok (total_fee, total_gas) -> ( + match Tez.(total_fee +? fee) with + | Ok total_fee -> Ok (total_fee, Gas.Arith.add total_gas gas_limit) + | Error _ as e -> e)) + | _ -> acc) + (Ok (Tez.zero, Gas.Arith.zero)) + l + +type Environment.Error_monad.error += Fees_too_low + +let () = + Environment.Error_monad.register_error_kind + `Permanent + ~id:"prefilter.fees_too_low" + ~title:"Operation fees are too low" + ~description:"Operation fees are too low" + ~pp:(fun ppf () -> Format.fprintf ppf "Operation fees are too low") + Data_encoding.unit + (function Fees_too_low -> Some () | _ -> None) + (fun () -> Fees_too_low) + +let size_of_operation op = + (WithExceptions.Option.get ~loc:__LOC__ + @@ Data_encoding.Binary.fixed_length + Tezos_base.Operation.shell_header_encoding) + + Data_encoding.Binary.length Operation.protocol_data_encoding op + +(** Returns the weight and resources consumption of an operation. The weight + corresponds to the one implemented by the baker, to decide which operations + to put in a block first (the code is largely duplicated). + See {!Tezos_baking_alpha.Operation_selection.weight_manager} *) +let weight_and_resources_manager_operation ~hard_gas_limit_per_block ?size ~fee + ~gas op = + let max_size = managers_quota.max_size in + let size = match size with None -> size_of_operation op | Some s -> s in + let size_f = Q.of_int size in + let gas_f = Q.of_bigint (Gas.Arith.integral_to_z gas) in + let fee_f = Q.of_int64 (Tez.to_mutez fee) in + let size_ratio = Q.(size_f / Q.of_int max_size) in + let gas_ratio = + Q.(gas_f / Q.of_bigint (Gas.Arith.integral_to_z hard_gas_limit_per_block)) + in + let resources = Q.max size_ratio gas_ratio in + (Q.(fee_f / resources), resources) + +let pre_filter_manager : + type t. + info -> + config -> + Operation.packed_protocol_data -> + t Kind.manager contents_list -> + [ `Passed_prefilter of Q.t list + | `Branch_refused of tztrace + | `Branch_delayed of tztrace + | `Refused of tztrace + | `Outdated of tztrace ] = + fun info config packed_op op -> + let size = size_of_operation packed_op in + let check_gas_and_fee fee gas_limit = + let fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez fee)) (Q.of_int 1000) + in + let minimal_fees_in_nanotez = + Q.mul (Q.of_int64 (Tez.to_mutez config.minimal_fees)) (Q.of_int 1000) + in + let minimal_fees_for_gas_in_nanotez = + Q.mul + config.minimal_nanotez_per_gas_unit + (Q.of_bigint @@ Gas.Arith.integral_to_z gas_limit) + in + let minimal_fees_for_size_in_nanotez = + Q.mul config.minimal_nanotez_per_byte (Q.of_int size) + in + if + Q.compare + fees_in_nanotez + (Q.add + minimal_fees_in_nanotez + (Q.add + minimal_fees_for_gas_in_nanotez + minimal_fees_for_size_in_nanotez)) + >= 0 + then `Fees_ok + else `Refused [Environment.wrap_tzerror Fees_too_low] + in + match compute_manager_contents_fee_and_gas_limit op with + | Error err -> `Refused (Environment.wrap_tztrace err) + | Ok (fee, gas_limit) -> ( + match check_gas_and_fee fee gas_limit with + | `Refused _ as err -> err + | `Fees_ok -> + let weight, _op_resources = + weight_and_resources_manager_operation + ~hard_gas_limit_per_block:info.hard_gas_limit_per_block + ~fee + ~gas:gas_limit + packed_op + in + `Passed_prefilter [weight]) + +type Environment.Error_monad.error += Wrong_operation + +let () = + Environment.Error_monad.register_error_kind + `Temporary + ~id:"prefilter.wrong_operation" + ~title:"Wrong operation" + ~description:"Failing_noop operations are not accepted in the mempool." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Failing_noop operations are not accepted in the mempool") + Data_encoding.unit + (function Wrong_operation -> Some () | _ -> None) + (fun () -> Wrong_operation) + +type Environment.Error_monad.error += Consensus_operation_in_far_future + +let () = + Environment.Error_monad.register_error_kind + `Branch + ~id:"prefilter.Consensus_operation_in_far_future" + ~title:"Consensus operation in far future" + ~description:"Consensus operation too far in the future are not accepted." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Consensus operation too far in the future are not accepted.") + Data_encoding.unit + (function Consensus_operation_in_far_future -> Some () | _ -> None) + (fun () -> Consensus_operation_in_far_future) + +(** {2 consensus operation filtering} + + In Tenderbake, we increased a lot the number of consensus + operations, therefore it seems necessary to be able to filter consensus + operations that could be produced by a Byzantine baker mis-using + its right to produce operations in future rounds or levels. + + We consider the situation where the head is at level [h_l], + round [h_r], and with timestamp [h_ts], with the predecessor of the head + being at round [hp_r]. + We receive at a time [now] a consensus operation for level [op_l] and + round [op_r]. + + A consensus operation is considered too far in the future, and therefore filtered, + if the earliest possible starting time of its round is greater than the + current time plus a safety margin of [config.clock_drift]. + + To consider potential level 2 reorgs, we first compute the expected + timestamp of round zero at previous level [hp0_ts], + + All ops at level p_l and round r' such that time(r') is greater than (now + drift) are + deemed too far in the future: + + h_r op_ts now+drift (h_l,r') + hp0_ts h_0 h_l | | | + +----+-----+---------+-------------------+--+-----+--------------+----------- + | | | | | | | + | h_ts h_r end time | now | earliest expected + | | | | time of round r' + |<----op_r rounds duration -------->| | + | + |<--------------- operations kept ---->|<-rejected----------... + | + |<-----------operations considered by the filter -----------... + + For an operation on a proposal at the next level, we consider the minimum + starting time of the operation's round, obtained by assuming that the proposal + at the next level was built on top of a proposal at round 0 for the current + level, itself based on a proposal at round 0 of previous level. + Operations on proposal with higher levels are treated similarly. + + All ops at the next level and round r' such that timestamp(r') > now+drift + are deemed too far in the future. + + r=0 r=1 h_r now now+drift (h_l+1,r') + hp0_ts h_0 h_l h_l | | | + +----+---- |-------+----+---------+----------+----------+---------- + | | | | | + | t0 | h_ts earliest expected + | | | | time of round r' + |<--- | earliest| | + | next level| | + | |<---------------------------------->| + round_offset(r') + + *) + +(** At a given level a consensus operation is acceptable if its earliest + expected timestamp, [op_earliest_ts] is below the current clock with an + accepted drift for the clock given by a configuration. *) +let acceptable ~drift ~op_earliest_ts ~now_timestamp = + let open Result_syntax in + Timestamp.( + let+ now_drifted = now_timestamp +? drift in + op_earliest_ts <= now_drifted) + +(** Check that an operation with the given [op_round], at level [op_level] + is likely to be correct, meaning it could have been produced before + now (+ the safety margin from configuration). + + Given an operation at level greater or equal than/to the current level, we + compute the expected timestamp of the operation's round. If the operation + is at a greater level, we assume that it is based on the proposal at round + zero of the current level. + + All operations whose (level, round) is lower than or equal to the current + head are deemed valid. + Note that in case where their is a high drift in the computer clock, they + might not have been considered valid by comparing their expected timestamp + to the clock. + + This is a stricter than necessary filter as it will reject operations that + could be valid in the current timeframe if the proposal they attest is + built over a predecessor of the current proposal that would be of lower + round than the current one. + + What can we do that would be smarter: get current head's predecessor round + and timestamp to compute the timestamp t0 of a predecessor that would have + been proposed at round 0. + + Timestamp of round at current level for an alternative head that would be + based on such proposal would be computed based on t0. + For level higher than current head, compute the round's earliest timestamp + if all proposal passed at round 0 starting from t0. + *) +let acceptable_op ~config ~round_durations ~round_zero_duration ~proposal_level + ~proposal_round ~proposal_timestamp + ~(proposal_predecessor_level_start : Timestamp.t) ~op_level ~op_round + ~now_timestamp = + let open Result_syntax in + if + Raw_level.(succ op_level < proposal_level) + || (op_level = proposal_level && op_round <= proposal_round) + then + (* Past and current round operations are not in the future *) + (* This case could be handled directly in `pre_filter_far_future_consensus_ops` + for a (slightly) better performance. *) + Ok true + else + (* If, by some tolerance on local clock drift, the timestamp of the + current head is itself in the future, we use this time instead of + now_timestamp *) + let now_timestamp = Timestamp.(max now_timestamp proposal_timestamp) in + (* Computing when the current level started. *) + let drift = Option.value ~default:round_zero_duration config.clock_drift in + (* We compute the earliest timestamp possible [op_earliest_ts] for the + operation's (level,round), as if all proposals were accepted at round 0 + since the previous level. *) + (* Invariant: [op_level + 1 >= proposal_level] *) + let level_offset = Raw_level.(diff (succ op_level) proposal_level) in + let* time_shift = Period.mult level_offset round_zero_duration in + let* earliest_op_level_start = + Timestamp.(proposal_predecessor_level_start +? time_shift) + in + (* computing the operations's round start from it's earliest + possible level start *) + let* op_earliest_ts = + Round.timestamp_of_another_round_same_level + round_durations + ~current_round:Round.zero + ~current_timestamp:earliest_op_level_start + ~considered_round:op_round + in + (* We finally check that the expected time of the operation is + acceptable *) + acceptable ~drift ~op_earliest_ts ~now_timestamp + +type level_and_round = {level : Raw_level.t; round : Round.t} + +let pre_filter_far_future_consensus_ops info config + ({level = op_level; round = op_round} : level_and_round) : bool Lwt.t = + let open Result_syntax in + let res = + let now_timestamp = Time.System.now () |> Time.System.to_protocol in + let* proposal_level = Raw_level.of_int32 info.head.level in + acceptable_op + ~config + ~round_durations:info.round_durations + ~round_zero_duration:info.round_zero_duration + ~proposal_level + ~proposal_round:info.head_round + ~proposal_timestamp:info.head.timestamp + ~proposal_predecessor_level_start:info.grandparent_level_start + ~op_level + ~op_round + ~now_timestamp + in + match res with Ok b -> Lwt.return b | Error _ -> Lwt.return_false + +let prefilter_consensus_operation info config level_and_round = + let open Lwt_syntax in + let* keep = pre_filter_far_future_consensus_ops info config level_and_round in + if keep then return (`Passed_prefilter consensus_prio) + else + return + (`Branch_refused + [Environment.wrap_tzerror Consensus_operation_in_far_future]) + +(** A quasi infinite amount of "valid" (pre)attestations could be + sent by a committee member, one for each possible round number. + + This filter rejects (pre)attestations that refer to a round + that could not have been reached within the time span between + the last head's timestamp and the current local clock. + + We add [config.clock_drift] time as a safety margin. + *) +let pre_filter info config + ({shell = _; protocol_data = Operation_data {contents; _} as op} : + Main.operation) = + let open Lwt_syntax in + let prefilter_manager_op manager_op = + return + @@ + match pre_filter_manager info config op manager_op with + | `Passed_prefilter prio -> `Passed_prefilter (manager_prio prio) + | (`Branch_refused _ | `Branch_delayed _ | `Refused _ | `Outdated _) as err + -> + err + in + match contents with + | Single (Failing_noop _) -> + return (`Refused [Environment.wrap_tzerror Wrong_operation]) + | Single (Preattestation consensus_content) + | Single (Attestation {consensus_content; dal_content = _}) -> + let level_and_round : level_and_round = + {level = consensus_content.level; round = consensus_content.round} + in + prefilter_consensus_operation info config level_and_round + | Single (Seed_nonce_revelation _) + | Single (Double_preattestation_evidence _) + | Single (Double_attestation_evidence _) + | Single (Double_baking_evidence _) + | Single (Activate_account _) + | Single (Proposals _) + | Single (Vdf_revelation _) + | Single (Drain_delegate _) + | Single (Ballot _) -> + return (`Passed_prefilter other_prio) + | Single (Manager_operation _) as op -> prefilter_manager_op op + | Cons (Manager_operation _, _) as op -> prefilter_manager_op op + +let syntactic_check _ = Lwt.return `Well_formed + +let is_manager_operation op = + match Operation.acceptable_pass op with + | Some pass -> Compare.Int.equal pass Operation_repr.manager_pass + | None -> false + +(* Should not fail on a valid manager operation. *) +let compute_fee_and_gas_limit {protocol_data = Operation_data data; _} = + compute_manager_contents_fee_and_gas_limit data.contents + +let gas_as_q gas = Gas.Arith.integral_to_z gas |> Q.of_bigint + +let fee_and_ratio_as_q fee gas = + let fee = Tez.to_mutez fee |> Z.of_int64 |> Q.of_bigint in + let gas = gas_as_q gas in + let ratio = Q.div fee gas in + (fee, ratio) + +let bumped_fee_and_ratio_as_q config fee gas = + let bump = Q.mul config.replace_by_fee_factor in + let fee, ratio = fee_and_ratio_as_q fee gas in + (bump fee, bump ratio) + +(** Determine whether the new manager operation is sufficiently better + than the old manager operation to replace it. Sufficiently better + means that the new operation's fee and fee/gas ratio are both + greater than or equal to the old operation's same metrics bumped by + the factor [config.replace_by_fee_factor]. *) +let better_fees_and_ratio config old_gas old_fee new_gas new_fee = + let bumped_old_fee, bumped_old_ratio = + bumped_fee_and_ratio_as_q config old_fee old_gas + in + let new_fee, new_ratio = fee_and_ratio_as_q new_fee new_gas in + Q.compare new_fee bumped_old_fee >= 0 + && Q.compare new_ratio bumped_old_ratio >= 0 + +(** [conflict_handler config] returns a conflict handler for + {!Mempool.add_operation} (see {!Mempool.conflict_handler}). + + - For non-manager operations, we select the greater operation + according to {!Operation.compare}. + + - A manager operation is replaced only when the new operation's + fee and fee/gas ratio both exceed the old operation's by at least a + factor of [config.replace_by_fee_factor] (see {!better_fees_and_ratio}). + + Precondition: both operations must be individually valid (because + of the call to {!Operation.compare}). *) +let conflict_handler config : Mempool.conflict_handler = + let open Result_syntax in + fun ~existing_operation ~new_operation -> + let (_ : Operation_hash.t), old_op = existing_operation in + let (_ : Operation_hash.t), new_op = new_operation in + if is_manager_operation old_op && is_manager_operation new_op then + let new_op_is_better = + let* old_fee, old_gas_limit = compute_fee_and_gas_limit old_op in + let* new_fee, new_gas_limit = compute_fee_and_gas_limit new_op in + return + (better_fees_and_ratio + config + old_gas_limit + old_fee + new_gas_limit + new_fee) + in + match new_op_is_better with + | Ok b when b -> `Replace + | Ok _ | Error _ -> `Keep + else if Operation.compare existing_operation new_operation < 0 then `Replace + else `Keep + +let int64_ceil_of_q q = + let n = Q.to_int64 q in + if Q.(equal q (of_int64 n)) then n else Int64.succ n + +(* Compute the minimal fee (expressed in mutez) that [candidate_op] + would need to have in order for the {!conflict_handler} to let it + replace [op_to_replace], when both operations are manager + operations. + + As specified in {!conflict_handler}, this means that [candidate_op] + with the returned fee needs to have both its fee and its fee/gas + ratio exceed (or match) [op_to_replace]'s same metrics bumped by + the {!config}'s [replace_by_fee_factor]. + + Return [None] when at least one operation is not a manager + operation. + + Also return [None] if both operations are manager operations but + there was an error while computing the needed fee. However, note + that this cannot happen when both manager operations have been + successfully validated by the protocol. *) +let fee_needed_to_replace_by_fee config ~op_to_replace ~candidate_op = + let open Result_syntax in + if is_manager_operation candidate_op && is_manager_operation op_to_replace + then + (let* _fee, candidate_gas = compute_fee_and_gas_limit candidate_op in + let* old_fee, old_gas = compute_fee_and_gas_limit op_to_replace in + if Gas.Arith.(old_gas = zero || candidate_gas = zero) then + (* This should not happen when both operations are valid. *) + return_none + else + let candidate_gas = gas_as_q candidate_gas in + let bumped_old_fee, bumped_old_ratio = + bumped_fee_and_ratio_as_q config old_fee old_gas + in + (* The new operation needs to exceed both the bumped fee and the + bumped ratio to make {!better_fees_and_ratio} return [true]. + (Having fee or ratio equal to its bumped counterpart is ok too, + hence the [ceil] in [int64_ceil_of_q].) *) + let fee_needed_for_fee = int64_ceil_of_q bumped_old_fee in + let fee_needed_for_ratio = + int64_ceil_of_q Q.(bumped_old_ratio * candidate_gas) + in + return_some (max fee_needed_for_fee fee_needed_for_ratio)) + |> Option.of_result |> Option.join + else None + +let find_manager {shell = _; protocol_data = Operation_data {contents; _}} = + match contents with + | Single (Manager_operation {source; _}) -> Some source + | Cons (Manager_operation {source; _}, _) -> Some source + | Single + ( Preattestation _ | Attestation _ | Proposals _ | Ballot _ + | Seed_nonce_revelation _ | Vdf_revelation _ | Double_baking_evidence _ + | Double_preattestation_evidence _ | Double_attestation_evidence _ + | Activate_account _ | Drain_delegate _ | Failing_noop _ ) -> + None + +(* The purpose of this module is to offer a version of + [fee_needed_to_replace_by_fee] where the caller doesn't need to + provide the [op_to_replace]. Instead, it needs to call + [Conflict_map.update] every time a new operation is added to the + mempool. This setup prevents the mempool plugin from exposing the + notion of manager operations and their source. *) +module Conflict_map = struct + (* The state consists in a map of all validated manager operations, + indexed by their source. + + Note that the protocol already enforces that there is at most one + operation per source. + + The state only tracks manager operations because other kinds of + operations don't have fees that we might adjust to change the + outcome of the {!conflict_handler}, so + [fee_needed_to_replace_by_fee] will always return [None] when + they are involved anyway. *) + type t = packed_operation Signature.Public_key_hash.Map.t + + let empty = Signature.Public_key_hash.Map.empty + + (* Remove all the [replacements] from the state, then add + [new_operation]. Non-manager operations are ignored. + + It is important to remove before adding: otherwise, we would + remove the newly added operation when it has the same manager as + one of the replacements. *) + let update conflict_map ~new_operation ~replacements = + let conflict_map = + List.fold_left + (fun conflict_map op -> + match find_manager op with + | Some manager -> + Signature.Public_key_hash.Map.remove manager conflict_map + | None -> (* Non-manager operation: ignore it. *) conflict_map) + conflict_map + replacements + in + match find_manager new_operation with + | Some manager -> + Signature.Public_key_hash.Map.add manager new_operation conflict_map + | None -> (* Non-manager operation: ignore it. *) conflict_map + + let fee_needed_to_replace_by_fee config ~candidate_op ~conflict_map = + match find_manager candidate_op with + | None -> (* Non-manager operation. *) None + | Some manager -> ( + match Signature.Public_key_hash.Map.find manager conflict_map with + | None -> + (* This can only happen when the pre-existing conflicting + operation is a [Drain_delegate], which cannot be replaced by a + manager operation regardless of the latter's fee. *) + None + | Some op_to_replace -> + fee_needed_to_replace_by_fee config ~candidate_op ~op_to_replace) +end + +let fee_needed_to_overtake ~op_to_overtake ~candidate_op = + let open Result_syntax in + if is_manager_operation candidate_op && is_manager_operation op_to_overtake + then + (let* _fee, candidate_gas = compute_fee_and_gas_limit candidate_op in + let* target_fee, target_gas = compute_fee_and_gas_limit op_to_overtake in + if Gas.Arith.(target_gas = zero || candidate_gas = zero) then + (* This should not happen when both operations are valid. *) + return_none + else + (* Compute the target ratio as in {!Operation_repr.weight_manager}. + We purposefully don't use {!fee_and_ratio_as_q} because the code + here needs to stay in sync with {!Operation_repr.weight_manager} + rather than {!better_fees_and_ratio}. *) + let target_fee = Q.of_int64 (Tez.to_mutez target_fee) in + let target_gas = Q.of_bigint (Gas.Arith.integral_to_z target_gas) in + let target_ratio = Q.(target_fee / target_gas) in + (* Compute the minimal fee needed to have a strictly greater ratio. *) + let candidate_gas = + Q.of_bigint (Gas.Arith.integral_to_z candidate_gas) + in + return_some (Int64.succ Q.(to_int64 (target_ratio * candidate_gas)))) + |> Option.of_result |> Option.join + else None + +module Internal_for_tests = struct + let default_config_with_clock_drift clock_drift = + {default_config with clock_drift} + + let default_config_with_replace_factor replace_by_fee_factor = + {default_config with replace_by_fee_factor} + + let get_clock_drift {clock_drift; _} = clock_drift + + let acceptable_op = acceptable_op + + let fee_needed_to_replace_by_fee = fee_needed_to_replace_by_fee +end diff --git a/src/proto_020_PsParisC/lib_plugin/mempool.mli b/src/proto_020_PsParisC/lib_plugin/mempool.mli new file mode 100644 index 000000000000..8157d174f705 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/mempool.mli @@ -0,0 +1,219 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Plugin for the shell mempool. It must include the signature + [FILTER.Mempool] from [lib_shell/shell_plugin.mli]. *) + +(** Settings for the {!pre_filter}: + - minimal fees to accept an operation (absolute, relative to the + gas limit, and relative to the byte size) + - clock drift for the prefiltering of consensus operations + + and for the {!conflict_handler}: + - replacement factor, that is, how much better a new manager + operation needs to be, in terms of both absolute fees and fee/gas + ratios, in order to replace an old conflicting manager operation. *) +type config + +(** Default parameters. *) +val default_config : config + +(** Encoding for {!config}. *) +val config_encoding : config Data_encoding.t + +(** Static information needed by {!pre_filter}. + + It depends on the [head] block upon which a mempool is built. *) +type info + +(** Create an {!info} based on the [head] block and the current + context. *) +val init : + Environment.Context.t -> + head:Block_header.shell_header -> + (info, tztrace) result Lwt.t + +(** Create a new {!info} based on the [head] block. + + Parts of the old {!info} (which may have been built on + a different block) are recycled, so that this function is more + efficient than {!init} and does not need an + {!Environment.Context.t} argument. *) +val flush : info -> head:Block_header.shell_header -> info tzresult Lwt.t + +(** Perform some syntactic checks on the operation. + + To be used mostly as an exceptional mechanism to prevent + ill-formed operations to block block application. + + Should be called before the {!pre_filter}, does not need a context. *) +val syntactic_check : + Protocol.Alpha_context.packed_operation -> [`Well_formed | `Ill_formed] Lwt.t + +(** Perform some preliminary checks on an operation. + + For manager operations, check that its fee, fee/gas ratio, and + fee/size ratio all meet the minimal requirements specified in the + {!config}. + + For consensus operations, check that it is possible for the + operation to have been produced before now (plus additional time + equal to the [clock_drift] from {!config}, as a safety margin). + Indeed, without this check, a baker could flood the network with + consensus operations for any future rounds or levels. The ml file + contains more detailled explanations with diagrams. *) +val pre_filter : + info -> + config -> + Protocol.Alpha_context.packed_operation -> + [ `Passed_prefilter of [`High | `Medium | `Low of Q.t list] + | `Branch_delayed of tztrace + | `Branch_refused of tztrace + | `Refused of tztrace + | `Outdated of tztrace ] + Lwt.t + +(** Return a conflict handler for {!Protocol.Mempool.add_operation} + (see {!Protocol.Mempool.conflict_handler}). + + For non-manager operations, select the greater operation according + to {!Protocol.Alpha_context.Operation.compare}. + + A manager operation is replaced only when the new operation's fee + and fee/gas ratio both exceed (or match) the old operation's metrics + multiplied by the [replace_by_fee] factor specified in the {!config}. + + Precondition: both operations must be individually valid (to be + able to call {!Protocol.Alpha_context.Operation.compare}). *) +val conflict_handler : config -> Protocol.Mempool.conflict_handler + +(** The purpose of this module is to provide the + [fee_needed_to_replace_by_fee] function. For this function to be + correct, the caller must maintain the state of type [t] by calling + [update] on each successfully validated operation and its induced + replacements. *) +module Conflict_map : sig + (** Internal state needed by [fee_needed_to_replace_by_fee]. *) + type t + + (** Initial state. *) + val empty : t + + (** Removes all the [replacements] from the state then adds + [new_operation]. *) + val update : + t -> + new_operation:Protocol.Alpha_context.packed_operation -> + replacements:Protocol.Alpha_context.packed_operation list -> + t + + (** This function should be called when + [Protocol.Mempool.add_operation] has returned [Unchanged]. This + means that the [candidate_op] has been rejected because there was + a conflict with an pre-existing operation and the + {!val-conflict_handler} has returned [`Keep]. When both + operations are manager operations, this function returns the + minimal fee (in mutez) that [candidate_op] would need in order to + win the conflict, i.e. make the {!val-conflict_handler} return + [`Replace] instead. Otherwise, it returns [None]. *) + val fee_needed_to_replace_by_fee : + config -> + candidate_op:Protocol.Alpha_context.packed_operation -> + conflict_map:t -> + int64 option +end + +(** Compute the minimal fee (expressed in mutez) that [candidate_op] would + need to have in order to be strictly greater than [op_to_overtake] + according to {!Protocol.Alpha_context.Operation.compare}, when both + operations are manager operations. + + Return [None] when at least one operation is not a manager operation. + + Also return [None] if both operations are manager operations but + there was an error while computing the needed fee. However, note + that this cannot happen when both manager operations have been + successfully validated by the protocol. *) +val fee_needed_to_overtake : + op_to_overtake:Protocol.Alpha_context.packed_operation -> + candidate_op:Protocol.Alpha_context.packed_operation -> + int64 option + +(** The following type, encoding, and default values are exported for + [bin_sc_rollup_node/configuration.ml]. *) + +(** An amount of fees in nanotez. *) +type nanotez = Q.t + +(** Encoding for {!nanotez}. *) +val nanotez_enc : nanotez Data_encoding.t + +(** Minimal absolute fees in {!default_config}. *) +val default_minimal_fees : Protocol.Alpha_context.Tez.t + +(** Minimal fee over gas_limit ratio in {!default_config}. *) +val default_minimal_nanotez_per_gas_unit : nanotez + +(** Minimal fee over byte size ratio in {!default_config}. *) +val default_minimal_nanotez_per_byte : nanotez + +module Internal_for_tests : sig + open Protocol.Alpha_context + + (** {!default_config} with a custom value for the [clock_drift] field. *) + val default_config_with_clock_drift : Period.t option -> config + + (** {!default_config} with a custom [replace_by_fee_factor]. *) + val default_config_with_replace_factor : nanotez -> config + + (** Return the [clock_drift] field of the given {!config}. *) + val get_clock_drift : config -> Period.t option + + (** The main auxiliary function for {!pre_filter} regarding + consensus operations. *) + val acceptable_op : + config:config -> + round_durations:Round.round_durations -> + round_zero_duration:Period.t -> + proposal_level:Raw_level.t -> + proposal_round:Round.t -> + proposal_timestamp:Timestamp.time -> + proposal_predecessor_level_start:Timestamp.time -> + op_level:Raw_level.t -> + op_round:Round.t -> + now_timestamp:Timestamp.time -> + bool Environment.Error_monad.tzresult + + (** The main component of + {!Conflict_map.fee_needed_to_replace_by_fee}. See comment in the + ml file. *) + val fee_needed_to_replace_by_fee : + config -> + op_to_replace:Protocol.Alpha_context.packed_operation -> + candidate_op:Protocol.Alpha_context.packed_operation -> + int64 option +end diff --git a/src/proto_020_PsParisC/lib_plugin/metrics_plugin.ml b/src/proto_020_PsParisC/lib_plugin/metrics_plugin.ml new file mode 100644 index 000000000000..5ec84ef99a03 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/metrics_plugin.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let update_metrics ~protocol_metadata (fitness : Tezos_base.Fitness.t) + update_metrics_callback = + let open Lwt_result_syntax in + let*! _ = + let*! (r : + ( unit, + Environment.Error_monad.error Environment.Error_monad.trace ) + result) = + let*? round = Alpha_context.Fitness.round_from_raw fitness in + let proto_metrics = + match + Data_encoding.Binary.of_bytes_opt + Protocol.block_header_metadata_encoding + protocol_metadata + with + | None -> + (* this is the case of the genesis block and the activation block + in a sandbox environment *) + None + | Some protocol_data -> + let cycle = + Int32.to_float (Cycle.to_int32 protocol_data.level_info.cycle) + in + let consumed_gas = + Z.to_float + (Gas.Arith.integral_to_z + (Gas.Arith.ceil protocol_data.consumed_gas)) + in + Some (cycle, consumed_gas) + in + match proto_metrics with + | Some (cycle, consumed_gas) -> + return + @@ update_metrics_callback + ~cycle + ~consumed_gas + ~round:(Int32.to_float (Round.to_int32 round)) + | None -> return_unit + in + Lwt.return @@ Environment.wrap_tzresult r + in + Lwt.return_unit diff --git a/src/proto_020_PsParisC/lib_plugin/plugin.ml b/src/proto_020_PsParisC/lib_plugin/plugin.ml new file mode 100644 index 000000000000..8fb75ce08aad --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/plugin.ml @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Mempool = Mempool +module View_helpers = View_helpers +module RPC = RPC +module Metrics = Metrics_plugin +module Script_interpreter_logging = Script_interpreter_logging diff --git a/src/proto_020_PsParisC/lib_plugin/plugin_errors.ml b/src/proto_020_PsParisC/lib_plugin/plugin_errors.ml new file mode 100644 index 000000000000..61179616fdd3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/plugin_errors.ml @@ -0,0 +1,62 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type Environment.Error_monad.error += Cannot_parse_operation (* `Branch *) + +type Environment.Error_monad.error += Cannot_serialize_log + +type Environment.Error_monad.error += Cannot_retrieve_predecessor_level + +let () = + Environment.Error_monad.register_error_kind + `Branch + ~id:"operation.cannot_parse" + ~title:"Cannot parse operation" + ~description:"The operation is ill-formed or for another protocol version" + ~pp:(fun ppf () -> Format.fprintf ppf "The operation cannot be parsed") + Data_encoding.unit + (function Cannot_parse_operation -> Some () | _ -> None) + (fun () -> Cannot_parse_operation) ; + (* Cannot serialize log *) + Environment.Error_monad.register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_log" + ~title:"Not enough gas to serialize execution trace" + ~description: + "Execution trace with stacks was to big to be serialized with the \ + provided gas" + Data_encoding.empty + (function Cannot_serialize_log -> Some () | _ -> None) + (fun () -> Cannot_serialize_log) ; + Environment.Error_monad.register_error_kind + `Temporary + ~id:"cannot_retrieve_predecessor_level" + ~title:"Cannot retrieve predecessor level" + ~description:"Cannot retrieve predecessor level." + Data_encoding.empty + (function Cannot_retrieve_predecessor_level -> Some () | _ -> None) + (fun () -> Cannot_retrieve_predecessor_level) diff --git a/src/proto_020_PsParisC/lib_plugin/plugin_registerer.ml b/src/proto_020_PsParisC/lib_plugin/plugin_registerer.ml new file mode 100644 index 000000000000..a34184865ed4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/plugin_registerer.ml @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Development. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Validation = struct + include Registerer.Registered + module Plugin = Plugin.Mempool +end + +module RPC = struct + module Proto = Registerer.Registered + include Plugin.RPC +end + +module Metrics = struct + include Plugin.Metrics + + let hash = Registerer.Registered.hash +end + +let () = Protocol_plugin.register_validation_plugin (module Validation) + +let () = Protocol_plugin.register_rpc (module RPC) + +let () = Protocol_plugin.register_metrics (module Metrics) diff --git a/src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.ml b/src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.ml new file mode 100644 index 000000000000..a6fa1d80bce2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.ml @@ -0,0 +1,2460 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Environment +open Error_monad +open Alpha_context +open Script_typed_ir + +module Stack_utils = struct + type kinstr_rewritek = { + apply : + 'b 'u 'r 'f. + ('b, 'u) stack_ty -> ('b, 'u, 'r, 'f) kinstr -> ('b, 'u, 'r, 'f) kinstr; + } + [@@ocaml.unboxed] + + (* An existential wrapper around failed [kinstr], whose final stack type + is hidden as it is irrelevant. *) + type ('a, 's) failed_kinstr_cast = {cast : 'b 'u. ('a, 's, 'b, 'u) kinstr} + [@@ocaml.unboxed] + + (* This is a view on a deconstructed [kinstr]. Its type parameters refer to + the type of the viewed [kinstr], while existentials inside describe types of + [kinstr]'s components. The [reconstruct] field in each record stores a + function which reconstructs the original instruction from its components. *) + type ('a, 's, 'r, 'f) ex_split_kinstr = + | Ex_split_kinstr : { + cont_init_stack : ('b, 'u) stack_ty; + continuation : ('b, 'u, 'r, 'f) kinstr; + reconstruct : ('b, 'u, 'r, 'f) kinstr -> ('a, 's, 'r, 'f) kinstr; + } + -> ('a, 's, 'r, 'f) ex_split_kinstr + | Ex_split_log : { + stack : ('a, 's) stack_ty; + continuation : ('a, 's, 'r, 'f) kinstr; + reconstruct : ('a, 's, 'r, 'f) kinstr -> ('a, 's, 'r, 'f) kinstr; + } + -> ('a, 's, 'r, 'f) ex_split_kinstr + | Ex_split_loop_may_fail : { + body_init_stack : ('b, 'u) stack_ty; + body : ('b, 'u, 'r, 'f) kinstr; + cont_init_stack : ('c, 'v) stack_ty; + continuation : ('c, 'v, 't, 'g) kinstr; + reconstruct : + ('b, 'u, 'r, 'f) kinstr -> + ('c, 'v, 't, 'g) kinstr -> + ('a, 's, 't, 'g) kinstr; + } + -> ('a, 's, 't, 'g) ex_split_kinstr + | Ex_split_loop_may_not_fail : { + body_init_stack : ('b, 'u) stack_ty; + body : ('b, 'u, 'r, 'f) kinstr; + continuation : ('c, 'v, 't, 'g) kinstr; + aft_body_stack_transform : + ('r, 'f) stack_ty -> ('c, 'v) stack_ty tzresult; + reconstruct : + ('b, 'u, 'r, 'f) kinstr -> + ('c, 'v, 't, 'g) kinstr -> + ('a, 's, 't, 'g) kinstr; + } + -> ('a, 's, 't, 'g) ex_split_kinstr + | Ex_split_if : { + left_init_stack : ('b, 'u) stack_ty; + left_branch : ('b, 'u, 'r, 'f) kinstr; + right_init_stack : ('c, 'v) stack_ty; + right_branch : ('c, 'v, 'r, 'f) kinstr; + continuation : ('r, 'f, 't, 'g) kinstr; + reconstruct : + ('b, 'u, 'r, 'f) kinstr -> + ('c, 'v, 'r, 'f) kinstr -> + ('r, 'f, 't, 'g) kinstr -> + ('a, 's, 't, 'g) kinstr; + } + -> ('a, 's, 't, 'g) ex_split_kinstr + | Ex_split_halt : Script.location -> ('a, 's, 'a, 's) ex_split_kinstr + | Ex_split_failwith : { + location : Script.location; + arg_ty : ('a, _) ty; + cast : ('a, 's) failed_kinstr_cast; + } + -> ('a, 's, 'r, 'f) ex_split_kinstr + + (** An existential container for an instruction paired with its + initial stack type. This is used internally to pack together + execution branches with different initial stack types but + the same final stack type (which we want to compute). *) + type ('r, 'f) ex_init_stack_ty = + | Ex_init_stack_ty : + ('a, 's) stack_ty * ('a, 's, 'r, 'f) kinstr + -> ('r, 'f) ex_init_stack_ty + + let rec stack_prefix_preservation_witness_split_input : + type a s b t c u d v. + (b, t, c, u, a, s, d, v) stack_prefix_preservation_witness -> + (a, s) stack_ty -> + (b, t) stack_ty = + fun w s -> + match (w, s) with + | KPrefix (_, _, w), Item_t (_, s) -> + stack_prefix_preservation_witness_split_input w s + | KRest, s -> s + + let rec stack_prefix_preservation_witness_split_output : + type a s b t c u d v. + (b, t, c, u, a, s, d, v) stack_prefix_preservation_witness -> + (c, u) stack_ty -> + (d, v) stack_ty = + fun w s -> + match (w, s) with + | KPrefix (_, a, w), s -> + Item_t (a, stack_prefix_preservation_witness_split_output w s) + | KRest, s -> s + + (* We apply this function to optional type information which must be present + if functions from this module were called. Use with care. *) + let assert_some = function None -> assert false | Some x -> x + + let kinstr_split : + type a s r f. + (a, s) stack_ty -> + (a, s, r, f) kinstr -> + (a, s, r, f) ex_split_kinstr tzresult = + let open Result_syntax in + fun s i -> + let dummy = Micheline.dummy_location in + match (i, s) with + | IDrop (loc, k), Item_t (_a, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDrop (loc, k)); + } + | IDup (loc, k), Item_t (a, s) -> + let s = Item_t (a, Item_t (a, s)) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDup (loc, k)); + } + | ISwap (loc, k), Item_t (a, Item_t (b, s)) -> + let s = Item_t (b, Item_t (a, s)) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISwap (loc, k)); + } + | IPush (loc, a, x, k), s -> + let s = Item_t (a, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IPush (loc, a, x, k)); + } + | IUnit (loc, k), s -> + let s = Item_t (unit_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IUnit (loc, k)); + } + | ICons_pair (loc, k), Item_t (a, Item_t (b, s)) -> + let+ (Ty_ex_c c) = pair_t dummy a b in + let s = Item_t (c, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICons_pair (loc, k)); + } + | ICar (loc, k), Item_t (Pair_t (a, _b, _meta, _), s) -> + let s = Item_t (a, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICar (loc, k)); + } + | ICdr (loc, k), Item_t (Pair_t (_a, b, _meta, _), s) -> + let s = Item_t (b, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICdr (loc, k)); + } + | IUnpair (loc, k), Item_t (Pair_t (a, b, _meta, _), s) -> + let s = Item_t (a, Item_t (b, s)) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IUnpair (loc, k)); + } + | ICons_some (loc, k), Item_t (a, s) -> + let+ o = option_t dummy a in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICons_some (loc, k)); + } + | ICons_none (loc, a, k), s -> + let+ o = option_t dummy a in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICons_none (loc, a, k)); + } + | ( IIf_none {loc; branch_if_none; branch_if_some; k}, + Item_t (Option_t (a, _meta, _), s) ) -> + return + @@ Ex_split_if + { + left_init_stack = s; + left_branch = branch_if_none; + right_init_stack = Item_t (a, s); + right_branch = branch_if_some; + continuation = k; + reconstruct = + (fun branch_if_none branch_if_some k -> + IIf_none {loc; branch_if_none; branch_if_some; k}); + } + | IOpt_map {loc; body; k}, Item_t (Option_t (a, _meta, _), s) -> + return + @@ Ex_split_loop_may_not_fail + { + body_init_stack = Item_t (a, s); + body; + continuation = k; + aft_body_stack_transform = + (function + | Item_t (b, s) -> + let+ o = option_t dummy b in + Item_t (o, s)); + reconstruct = (fun body k -> IOpt_map {loc; body; k}); + } + | ICons_left (loc, b, k), Item_t (a, s) -> + let+ (Ty_ex_c c) = or_t dummy a b in + let s = Item_t (c, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICons_left (loc, b, k)); + } + | ICons_right (loc, a, k), Item_t (b, s) -> + let+ (Ty_ex_c c) = or_t dummy a b in + let s = Item_t (c, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICons_right (loc, a, k)); + } + | ( IIf_left {loc; branch_if_left; branch_if_right; k}, + Item_t (Or_t (a, b, _meta, _), s) ) -> + return + @@ Ex_split_if + { + left_init_stack = Item_t (a, s); + left_branch = branch_if_left; + right_init_stack = Item_t (b, s); + right_branch = branch_if_right; + continuation = k; + reconstruct = + (fun branch_if_left branch_if_right k -> + IIf_left {loc; branch_if_left; branch_if_right; k}); + } + | ICons_list (loc, k), Item_t (_a, Item_t (l, s)) -> + let s = Item_t (l, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICons_list (loc, k)); + } + | INil (loc, a, k), s -> + let+ l = list_t dummy a in + let s = Item_t (l, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INil (loc, a, k)); + } + | ( IIf_cons {loc; branch_if_cons; branch_if_nil; k}, + Item_t ((List_t (a, _meta) as l), s) ) -> + return + @@ Ex_split_if + { + left_init_stack = Item_t (a, Item_t (l, s)); + left_branch = branch_if_cons; + right_init_stack = s; + right_branch = branch_if_nil; + continuation = k; + reconstruct = + (fun branch_if_cons branch_if_nil k -> + IIf_cons {loc; branch_if_cons; branch_if_nil; k}); + } + | IList_map (loc, body, ty, k), Item_t (List_t (a, _meta), s) -> + let s = Item_t (a, s) in + return + @@ Ex_split_loop_may_not_fail + { + body_init_stack = s; + body; + continuation = k; + aft_body_stack_transform = + (function + | Item_t (b, s) -> + let+ l = list_t dummy b in + Item_t (l, s)); + reconstruct = (fun body k -> IList_map (loc, body, ty, k)); + } + | IList_iter (loc, ty, body, k), Item_t (List_t (a, _meta), s) -> + return + @@ Ex_split_loop_may_fail + { + body_init_stack = Item_t (a, s); + body; + cont_init_stack = s; + continuation = k; + reconstruct = (fun body k -> IList_iter (loc, ty, body, k)); + } + | IList_size (loc, k), Item_t (_l, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IList_size (loc, k)); + } + | IEmpty_set (loc, a, k), s -> + let+ b = set_t dummy a in + let s = Item_t (b, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEmpty_set (loc, a, k)); + } + | ISet_iter (loc, a, body, k), Item_t (_b, s) -> + return + @@ Ex_split_loop_may_fail + { + body_init_stack = Item_t (assert_some a, s); + body; + cont_init_stack = s; + continuation = k; + reconstruct = (fun body k -> ISet_iter (loc, a, body, k)); + } + | ISet_mem (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISet_mem (loc, k)); + } + | ISet_update (loc, k), Item_t (_, Item_t (_, s)) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISet_update (loc, k)); + } + | ISet_size (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISet_size (loc, k)); + } + | IEmpty_map (loc, cty, vty, k), s -> + let+ m = map_t dummy cty (assert_some vty) in + let s = Item_t (m, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEmpty_map (loc, cty, vty, k)); + } + | IMap_map (loc, ty, body, k), Item_t (Map_t (kty, vty, _meta), s) -> + let (Map_t (key_ty, _, _)) = assert_some ty in + let+ (Ty_ex_c p) = pair_t dummy key_ty vty in + Ex_split_loop_may_not_fail + { + body_init_stack = Item_t (p, s); + body; + continuation = k; + aft_body_stack_transform = + (fun (Item_t (b, s)) -> + let+ m = map_t dummy kty b in + Item_t (m, s)); + reconstruct = (fun body k -> IMap_map (loc, ty, body, k)); + } + | IMap_iter (loc, kvty, body, k), Item_t (_, stack) -> + return + @@ Ex_split_loop_may_fail + { + body_init_stack = Item_t (assert_some kvty, stack); + body; + cont_init_stack = stack; + continuation = k; + reconstruct = (fun body k -> IMap_iter (loc, kvty, body, k)); + } + | IMap_mem (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMap_mem (loc, k)); + } + | IMap_get (loc, k), Item_t (_, Item_t (Map_t (_kty, vty, _meta), s)) -> + let+ o = option_t dummy vty in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMap_get (loc, k)); + } + | IMap_update (loc, k), Item_t (_, Item_t (_, s)) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMap_update (loc, k)); + } + | IMap_get_and_update (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMap_get_and_update (loc, k)); + } + | IMap_size (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMap_size (loc, k)); + } + | IEmpty_big_map (loc, cty, ty, k), s -> + let+ b = big_map_t dummy cty ty in + let s = Item_t (b, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEmpty_big_map (loc, cty, ty, k)); + } + | IBig_map_mem (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBig_map_mem (loc, k)); + } + | ( IBig_map_get (loc, k), + Item_t (_, Item_t (Big_map_t (_kty, vty, _meta), s)) ) -> + let+ o = option_t dummy vty in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBig_map_get (loc, k)); + } + | IBig_map_update (loc, k), Item_t (_, Item_t (_, s)) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBig_map_update (loc, k)); + } + | IBig_map_get_and_update (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBig_map_get_and_update (loc, k)); + } + | IConcat_string (loc, k), Item_t (_, s) -> + let s = Item_t (string_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IConcat_string (loc, k)); + } + | IConcat_string_pair (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IConcat_string_pair (loc, k)); + } + | ISlice_string (loc, k), Item_t (_, Item_t (_, Item_t (_, s))) -> + let s = Item_t (option_string_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISlice_string (loc, k)); + } + | IString_size (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IString_size (loc, k)); + } + | IConcat_bytes (loc, k), Item_t (_, s) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IConcat_bytes (loc, k)); + } + | IConcat_bytes_pair (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IConcat_bytes_pair (loc, k)); + } + | ISlice_bytes (loc, k), Item_t (_, Item_t (_, Item_t (_, s))) -> + let s = Item_t (option_bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISlice_bytes (loc, k)); + } + | IBytes_size (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBytes_size (loc, k)); + } + | ILsl_bytes (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILsl_bytes (loc, k)); + } + | ILsr_bytes (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILsr_bytes (loc, k)); + } + | IOr_bytes (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IOr_bytes (loc, k)); + } + | IAnd_bytes (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAnd_bytes (loc, k)); + } + | IXor_bytes (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IXor_bytes (loc, k)); + } + | INot_bytes (loc, k), Item_t (_, s) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INot_bytes (loc, k)); + } + | IBytes_nat (loc, k), Item_t (_, s) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBytes_nat (loc, k)); + } + | INat_bytes (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INat_bytes (loc, k)); + } + | IBytes_int (loc, k), Item_t (_, s) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBytes_int (loc, k)); + } + | IInt_bytes (loc, k), Item_t (_, s) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IInt_bytes (loc, k)); + } + | IAdd_seconds_to_timestamp (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_seconds_to_timestamp (loc, k)); + } + | IAdd_timestamp_to_seconds (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (timestamp_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_timestamp_to_seconds (loc, k)); + } + | ISub_timestamp_seconds (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (timestamp_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISub_timestamp_seconds (loc, k)); + } + | IDiff_timestamps (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDiff_timestamps (loc, k)); + } + | IAdd_tez (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_tez (loc, k)); + } + | ISub_tez (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (option_mutez_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISub_tez (loc, k)); + } + | ISub_tez_legacy (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISub_tez_legacy (loc, k)); + } + | IMul_teznat (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (mutez_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_teznat (loc, k)); + } + | IMul_nattez (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_nattez (loc, k)); + } + | IEdiv_teznat (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (option_pair_mutez_mutez_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEdiv_teznat (loc, k)); + } + | IEdiv_tez (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (option_pair_nat_mutez_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEdiv_tez (loc, k)); + } + | IOr (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IOr (loc, k)); + } + | IAnd (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAnd (loc, k)); + } + | IXor (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IXor (loc, k)); + } + | INot (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INot (loc, k)); + } + | IIs_nat (loc, k), Item_t (_, s) -> + let s = Item_t (option_nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IIs_nat (loc, k)); + } + | INeg (loc, k), Item_t (_, s) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INeg (loc, k)); + } + | IAbs_int (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAbs_int (loc, k)); + } + | IInt_nat (loc, k), Item_t (_, s) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IInt_nat (loc, k)); + } + | IAdd_int (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_int (loc, k)); + } + | IAdd_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_nat (loc, k)); + } + | ISub_int (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISub_int (loc, k)); + } + | IMul_int (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_int (loc, k)); + } + | IMul_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_nat (loc, k)); + } + | IEdiv_int (loc, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (option_pair_int_nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEdiv_int (loc, k)); + } + | IEdiv_nat (loc, k), Item_t (_, Item_t (a, s)) -> + let* (Ty_ex_c p) = pair_t dummy a nat_t in + let+ o = option_t dummy p in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEdiv_nat (loc, k)); + } + | ILsl_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILsl_nat (loc, k)); + } + | ILsr_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILsr_nat (loc, k)); + } + | IOr_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IOr_nat (loc, k)); + } + | IAnd_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAnd_nat (loc, k)); + } + | IAnd_int_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAnd_int_nat (loc, k)); + } + | IXor_nat (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IXor_nat (loc, k)); + } + | INot_int (loc, k), Item_t (_, s) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INot_int (loc, k)); + } + | IIf {loc; branch_if_true; branch_if_false; k}, Item_t (_, s) -> + return + @@ Ex_split_if + { + left_init_stack = s; + left_branch = branch_if_true; + right_init_stack = s; + right_branch = branch_if_false; + continuation = k; + reconstruct = + (fun branch_if_true branch_if_false k -> + IIf {loc; branch_if_true; branch_if_false; k}); + } + | ILoop (loc, body, k), Item_t (_, s) -> + return + @@ Ex_split_loop_may_fail + { + body_init_stack = s; + body; + cont_init_stack = s; + continuation = k; + reconstruct = (fun body k -> ILoop (loc, body, k)); + } + | ILoop_left (loc, kl, kr), Item_t (Or_t (a, b, _meta, _), s) -> + return + @@ Ex_split_loop_may_fail + { + body_init_stack = Item_t (a, s); + body = kl; + cont_init_stack = Item_t (b, s); + continuation = kr; + reconstruct = (fun kl kr -> ILoop_left (loc, kl, kr)); + } + | IDip (loc, body, ty, k), Item_t (a, s) -> + return + @@ Ex_split_loop_may_not_fail + { + body_init_stack = s; + body; + continuation = k; + aft_body_stack_transform = (fun s -> return (Item_t (a, s))); + reconstruct = (fun body k -> IDip (loc, body, ty, k)); + } + | IExec (loc, sty, k), Item_t (_, Item_t (Lambda_t (_, b, _meta), s)) -> + let s = Item_t (b, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IExec (loc, sty, k)); + } + | ( IApply (loc, ty, k), + Item_t (_, Item_t (Lambda_t (Pair_t (_, a, _, _), b, _), s)) ) -> + let+ l = lambda_t dummy a b in + let s = Item_t (l, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IApply (loc, ty, k)); + } + | ILambda (loc, (Lam (desc, _) as l), k), s -> + let (Item_t (a, Bot_t)) = desc.kbef in + let (Item_t (b, Bot_t)) = desc.kaft in + let+ lam = lambda_t dummy a b in + let s = Item_t (lam, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILambda (loc, l, k)); + } + | ILambda (loc, (LamRec (desc, _) as l), k), s -> + let (Item_t (a, Item_t (Lambda_t _, Bot_t))) = desc.kbef in + let (Item_t (b, Bot_t)) = desc.kaft in + let+ lam = lambda_t dummy a b in + let s = Item_t (lam, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILambda (loc, l, k)); + } + | IFailwith (location, arg_ty), _ -> + return + @@ Ex_split_failwith + {location; arg_ty; cast = {cast = IFailwith (location, arg_ty)}} + | ICompare (loc, ty, k), Item_t (_, Item_t (_, s)) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICompare (loc, ty, k)); + } + | IEq (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEq (loc, k)); + } + | INeq (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INeq (loc, k)); + } + | ILt (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILt (loc, k)); + } + | IGt (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IGt (loc, k)); + } + | ILe (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILe (loc, k)); + } + | IGe (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IGe (loc, k)); + } + | IAddress (loc, k), Item_t (_, s) -> + let s = Item_t (address_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAddress (loc, k)); + } + | IContract (loc, ty, code, k), Item_t (_, s) -> + let* c = contract_t dummy ty in + let+ o = option_t dummy c in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IContract (loc, ty, code, k)); + } + | ITransfer_tokens (loc, k), Item_t (_, Item_t (_, Item_t (_, s))) -> + let s = Item_t (operation_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ITransfer_tokens (loc, k)); + } + | ( IView (loc, (View_signature {output_ty; _} as view_signature), sty, k), + Item_t (_, Item_t (_, s)) ) -> + let+ b = option_t dummy output_ty in + let s = Item_t (b, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IView (loc, view_signature, sty, k)); + } + | IImplicit_account (loc, k), Item_t (_, s) -> + let s = Item_t (contract_unit_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IImplicit_account (loc, k)); + } + | ( ICreate_contract {loc; storage_type; code; k}, + Item_t (_, Item_t (_, Item_t (_, s))) ) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = Item_t (operation_t, Item_t (address_t, s)); + continuation = k; + reconstruct = + (fun k -> ICreate_contract {loc; storage_type; code; k}); + } + | ISet_delegate (loc, k), Item_t (_, s) -> + let s = Item_t (operation_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISet_delegate (loc, k)); + } + | INow (loc, k), s -> + let s = Item_t (timestamp_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INow (loc, k)); + } + | IBalance (loc, k), s -> + let s = Item_t (mutez_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBalance (loc, k)); + } + | ILevel (loc, k), s -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ILevel (loc, k)); + } + | ICheck_signature (loc, k), Item_t (_, Item_t (_, Item_t (_, s))) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ICheck_signature (loc, k)); + } + | IHash_key (loc, k), Item_t (_, s) -> + let s = Item_t (key_hash_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IHash_key (loc, k)); + } + | IPack (loc, ty, k), Item_t (_, s) -> + let s = Item_t (bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IPack (loc, ty, k)); + } + | IUnpack (loc, ty, k), Item_t (_, s) -> + let+ o = option_t dummy ty in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IUnpack (loc, ty, k)); + } + | IBlake2b (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IBlake2b (loc, k)); + } + | ISha256 (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISha256 (loc, k)); + } + | ISha512 (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISha512 (loc, k)); + } + | ISource (loc, k), s -> + let s = Item_t (address_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISource (loc, k)); + } + | ISender (loc, k), s -> + let s = Item_t (address_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISender (loc, k)); + } + | ISelf (loc, ty, ep, k), s -> + let+ c = contract_t dummy ty in + let s = Item_t (c, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISelf (loc, ty, ep, k)); + } + | ISelf_address (loc, k), s -> + let s = Item_t (address_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISelf_address (loc, k)); + } + | IAmount (loc, k), s -> + let s = Item_t (mutez_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAmount (loc, k)); + } + | ISapling_empty_state (loc, memo_size, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = Item_t (sapling_state_t ~memo_size, s); + continuation = k; + reconstruct = + (fun k -> ISapling_empty_state (loc, memo_size, k)); + } + | ( ISapling_verify_update_deprecated (loc, k), + Item_t (_, Item_t (state_ty, s)) ) -> + let* (Ty_ex_c pair_ty) = pair_t dummy int_t state_ty in + let+ ty = option_t dummy pair_ty in + Ex_split_kinstr + { + cont_init_stack = Item_t (ty, s); + continuation = k; + reconstruct = + (fun k -> ISapling_verify_update_deprecated (loc, k)); + } + | ISapling_verify_update (loc, k), Item_t (_, Item_t (state_ty, s)) -> + let* (Ty_ex_c int_state_ty) = pair_t dummy int_t state_ty in + let* (Ty_ex_c pair_ty) = pair_t dummy bytes_t int_state_ty in + let+ ty = option_t dummy pair_ty in + let s = Item_t (ty, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISapling_verify_update (loc, k)); + } + | IDig (loc, n, p, k), s -> + let (Item_t (b, s)) = + stack_prefix_preservation_witness_split_input p s + in + let s = stack_prefix_preservation_witness_split_output p s in + let s = Item_t (b, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDig (loc, n, p, k)); + } + | IDug (loc, n, p, k), Item_t (a, s) -> + let s = stack_prefix_preservation_witness_split_input p s in + let s = Item_t (a, s) in + let s = stack_prefix_preservation_witness_split_output p s in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDug (loc, n, p, k)); + } + | IDipn (loc, n, p, k1, k2), s -> + return + @@ Ex_split_loop_may_not_fail + { + body_init_stack = + stack_prefix_preservation_witness_split_input p s; + body = k1; + continuation = k2; + aft_body_stack_transform = + (fun s -> + return + @@ stack_prefix_preservation_witness_split_output p s); + reconstruct = (fun k1 k2 -> IDipn (loc, n, p, k1, k2)); + } + | IDropn (loc, n, p, k), s -> + let s = stack_prefix_preservation_witness_split_input p s in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDropn (loc, n, p, k)); + } + | IChainId (loc, k), s -> + let s = Item_t (chain_id_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IChainId (loc, k)); + } + | INever location, Item_t (arg_ty, _) -> + return + @@ Ex_split_failwith + {location; arg_ty; cast = {cast = INever location}} + | IVoting_power (loc, k), Item_t (_, s) -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IVoting_power (loc, k)); + } + | ITotal_voting_power (loc, k), s -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ITotal_voting_power (loc, k)); + } + | IKeccak (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IKeccak (loc, k)); + } + | ISha3 (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISha3 (loc, k)); + } + | IAdd_bls12_381_g1 (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_bls12_381_g1 (loc, k)); + } + | IAdd_bls12_381_g2 (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_bls12_381_g2 (loc, k)); + } + | IAdd_bls12_381_fr (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IAdd_bls12_381_fr (loc, k)); + } + | IMul_bls12_381_g1 (loc, k), Item_t (g1, Item_t (_, s)) -> + let s = Item_t (g1, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_bls12_381_g1 (loc, k)); + } + | IMul_bls12_381_g2 (loc, k), Item_t (g2, Item_t (_, s)) -> + let s = Item_t (g2, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_bls12_381_g2 (loc, k)); + } + | IMul_bls12_381_fr (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_bls12_381_fr (loc, k)); + } + | IMul_bls12_381_z_fr (loc, k), Item_t (fr, Item_t (_, s)) -> + let s = Item_t (fr, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_bls12_381_z_fr (loc, k)); + } + | IMul_bls12_381_fr_z (loc, k), Item_t (_, s) -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMul_bls12_381_fr_z (loc, k)); + } + | IInt_bls12_381_fr (loc, k), Item_t (_, s) -> + let s = Item_t (int_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IInt_bls12_381_fr (loc, k)); + } + | INeg_bls12_381_g1 (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INeg_bls12_381_g1 (loc, k)); + } + | INeg_bls12_381_g2 (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INeg_bls12_381_g2 (loc, k)); + } + | INeg_bls12_381_fr (loc, k), s -> + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> INeg_bls12_381_fr (loc, k)); + } + | IPairing_check_bls12_381 (loc, k), Item_t (_, s) -> + let s = Item_t (bool_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IPairing_check_bls12_381 (loc, k)); + } + | IComb (loc, n, p, k), s -> + let rec aux : + type a b s c d t. + (a, b * s) stack_ty -> + (a, b, s, c, d, t) comb_gadt_witness -> + (c, d * t) stack_ty tzresult = + fun s w -> + match (w, s) with + | Comb_one, s -> return s + | Comb_succ w, Item_t (a, s) -> + let* (Item_t (c, t)) = aux s w in + let+ (Ty_ex_c p) = pair_t dummy a c in + Item_t (p, t) + in + let+ s = aux s p in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IComb (loc, n, p, k)); + } + | IUncomb (loc, n, p, k), s -> + let rec aux : + type a b s c d t. + (a, b * s) stack_ty -> + (a, b, s, c, d, t) uncomb_gadt_witness -> + (c, d * t) stack_ty = + fun s w -> + match (w, s) with + | Uncomb_one, s -> s + | Uncomb_succ w, Item_t (Pair_t (a, b, _meta, _), s) -> + let s = aux (Item_t (b, s)) w in + Item_t (a, s) + in + let s = aux s p in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IUncomb (loc, n, p, k)); + } + | IComb_get (loc, n, p, k), Item_t (c, s) -> + let rec aux : + type c cc a. + (c, cc) ty -> (c, a) comb_get_gadt_witness -> a ty_ex_c = + fun c w -> + match (w, c) with + | Comb_get_zero, c -> Ty_ex_c c + | Comb_get_one, Pair_t (hd, _tl, _meta, _) -> Ty_ex_c hd + | Comb_get_plus_two w, Pair_t (_hd, tl, _meta, _) -> aux tl w + in + let s = + let (Ty_ex_c ty) = aux c p in + Item_t (ty, s) + in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IComb_get (loc, n, p, k)); + } + | IComb_set (loc, n, p, k), Item_t (a, Item_t (b, s)) -> + let rec aux : + type a b c ca cb. + (a, ca) ty -> + (b, cb) ty -> + (a, b, c) comb_set_gadt_witness -> + c ty_ex_c tzresult = + fun a b w -> + match (w, b) with + | Comb_set_zero, _ -> return (Ty_ex_c a) + | Comb_set_one, Pair_t (_hd, tl, _meta, _) -> pair_t dummy a tl + | Comb_set_plus_two w, Pair_t (hd, tl, _meta, _) -> + let* (Ty_ex_c c) = aux a tl w in + pair_t dummy hd c + in + let+ (Ty_ex_c c) = aux a b p in + let s = Item_t (c, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IComb_set (loc, n, p, k)); + } + | IDup_n (loc, n, p, k), s -> + let rec aux : + type a b s t. + (a, b * s) stack_ty -> + (a, b, s, t) dup_n_gadt_witness -> + t ty_ex_c = + fun s w -> + match (w, s) with + | Dup_n_succ w, Item_t (_, s) -> aux s w + | Dup_n_zero, Item_t (a, _) -> Ty_ex_c a + in + let s = + let (Ty_ex_c ty) = aux s p in + Item_t (ty, s) + in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IDup_n (loc, n, p, k)); + } + | ITicket (loc, cty, k), Item_t (_, Item_t (_, s)) -> + let* ty = ticket_t dummy (assert_some cty) in + let+ t = option_t loc ty in + let s = Item_t (t, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ITicket (loc, cty, k)); + } + | ITicket_deprecated (loc, cty, k), Item_t (_, Item_t (_, s)) -> + let+ t = ticket_t dummy (assert_some cty) in + let s = Item_t (t, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ITicket_deprecated (loc, cty, k)); + } + | IRead_ticket (loc, a, k), s -> + let* (Ty_ex_c p) = pair_t dummy (assert_some a) nat_t in + let+ (Ty_ex_c t) = pair_t dummy address_t p in + let s = Item_t (t, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IRead_ticket (loc, a, k)); + } + | ISplit_ticket (loc, k), Item_t (t, Item_t (_, s)) -> + let* (Ty_ex_c p) = pair_t dummy t t in + let+ o = option_t dummy p in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> ISplit_ticket (loc, k)); + } + | IJoin_tickets (loc, ty, k), Item_t (Pair_t (t, _t, _meta, _), s) -> + let+ o = option_t dummy t in + let s = Item_t (o, s) in + Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IJoin_tickets (loc, ty, k)); + } + | IOpen_chest (loc, k), Item_t (_, Item_t (_, Item_t (_, s))) -> + let s = Item_t (option_bytes_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IOpen_chest (loc, k)); + } + | IMin_block_time (loc, k), s -> + let s = Item_t (nat_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IMin_block_time (loc, k)); + } + | IEmit {loc; ty; unparsed_ty; tag; k}, Item_t (_, s) -> + let s = Item_t (operation_t, s) in + return + @@ Ex_split_kinstr + { + cont_init_stack = s; + continuation = k; + reconstruct = (fun k -> IEmit {loc; ty; unparsed_ty; tag; k}); + } + | IEmit _, Bot_t -> . + | IHalt loc, _s -> return @@ Ex_split_halt loc + | ILog (loc, _stack_ty, event, logger, continuation), stack -> + return + @@ Ex_split_log + { + stack; + continuation; + reconstruct = (fun k -> ILog (loc, s, event, logger, k)); + } + + (* [kinstr_final_stack_type sty instr] computes the stack type after + [instr] has been executed, assuming [sty] is the type of the stack + prior to execution. For the rare instructions which can return stacks + of any type ([FAILWITH] and [NEVER]), this function returns [None]. *) + let rec kinstr_final_stack_type : + type a s r f. + (a, s) stack_ty -> (a, s, r, f) kinstr -> (r, f) stack_ty option tzresult + = + let open Result_syntax in + fun s i -> + let* ex_split_kinstr = kinstr_split s i in + match ex_split_kinstr with + | Ex_split_kinstr {cont_init_stack; continuation; _} -> + kinstr_final_stack_type cont_init_stack continuation + | Ex_split_log {stack; continuation; _} -> + kinstr_final_stack_type stack continuation + | Ex_split_loop_may_fail {cont_init_stack; continuation; _} -> + kinstr_final_stack_type cont_init_stack continuation + | Ex_split_loop_may_not_fail + {body_init_stack; body; continuation; aft_body_stack_transform; _} + -> ( + let* sty = kinstr_final_stack_type body_init_stack body in + match sty with + | Some after_body -> + let* before_k = aft_body_stack_transform after_body in + kinstr_final_stack_type before_k continuation + | None -> return_none) + | Ex_split_if + { + left_init_stack; + left_branch; + right_init_stack; + right_branch; + continuation; + _; + } -> ( + let* sty = kinstr_final_stack_type left_init_stack left_branch in + match sty with + | Some after_branch_a -> + kinstr_final_stack_type after_branch_a continuation + | None -> ( + let* sty = + kinstr_final_stack_type right_init_stack right_branch + in + match sty with + | Some after_branch_b -> + kinstr_final_stack_type after_branch_b continuation + | None -> return_none)) + | Ex_split_halt _ -> return_some s + | Ex_split_failwith {cast = {cast = _}; _} -> return_none + + (* The same as [kinstr_final_stack_type], but selects from multiple + possible execution branches. If the first instr ends with FAILWITH, + it will try the next and so on. Note that all instructions must + result in the same stack type. *) + let rec branched_final_stack_type : + type r f. (r, f) ex_init_stack_ty list -> (r, f) stack_ty option tzresult + = + let open Result_syntax in + function + | [] -> return_none + | Ex_init_stack_ty (init_sty, branch) :: bs -> ( + let* sty = kinstr_final_stack_type init_sty branch in + match sty with + | Some _ as sty -> return sty + | None -> branched_final_stack_type bs) + + let kinstr_rewritek : + type a s r f. + (a, s) stack_ty -> + (a, s, r, f) kinstr -> + kinstr_rewritek -> + (a, s, r, f) kinstr tzresult = + let open Result_syntax in + fun s i f -> + let* ex_split_kinstr = kinstr_split s i in + match ex_split_kinstr with + | Ex_split_kinstr {cont_init_stack; continuation; reconstruct} -> + return @@ reconstruct (f.apply cont_init_stack continuation) + | Ex_split_log {continuation; reconstruct; _} -> + return @@ reconstruct continuation + | Ex_split_loop_may_fail + {body_init_stack; body; cont_init_stack; continuation; reconstruct} -> + return + @@ reconstruct + (f.apply body_init_stack body) + (f.apply cont_init_stack continuation) + | Ex_split_loop_may_not_fail + { + body_init_stack; + body; + continuation; + aft_body_stack_transform; + reconstruct; + } -> + let+ k = + let* sty = kinstr_final_stack_type body_init_stack body in + match sty with + | Some after_body -> + let+ before_k = aft_body_stack_transform after_body in + f.apply before_k continuation + | None -> return continuation + in + reconstruct (f.apply body_init_stack body) k + | Ex_split_if + { + left_init_stack; + left_branch; + right_init_stack; + right_branch; + continuation; + reconstruct; + } -> + let+ k = + let* sty = kinstr_final_stack_type left_init_stack left_branch in + match sty with + | Some after_left_branch -> + return @@ f.apply after_left_branch continuation + | None -> ( + let* sty = + kinstr_final_stack_type right_init_stack right_branch + in + match sty with + | Some after_right_branch -> + return @@ f.apply after_right_branch continuation + | None -> return continuation) + in + reconstruct + (f.apply left_init_stack left_branch) + (f.apply right_init_stack right_branch) + k + | Ex_split_halt loc -> return @@ IHalt loc + | Ex_split_failwith {location; arg_ty; _} -> + return @@ IFailwith (location, arg_ty) + + (** [instrument_cont logger sty] creates a function instrumenting + continuations starting from the stack type described by [sty]. + Instrumentation consists in wrapping inner continuations in + [KLog] continuation so that logging continues. *) + let instrument_cont : + type a b c d. + logger -> + (a, b) stack_ty -> + (a, b, c, d) continuation -> + (a, b, c, d) continuation = + fun logger sty -> function KLog _ as k -> k | k -> KLog (k, sty, logger) +end + +module type Logger_base = sig + val log_interp : ('a, 's, 'b, 'f, 'c, 'u) logging_function + + val log_entry : ('a, 's, 'b, 'f, 'a, 's) logging_function + + val log_control : ('a, 's, 'b, 'f) continuation -> unit + + val log_exit : ('a, 's, 'b, 'f, 'c, 'u) logging_function + + val get_log : unit -> execution_trace option tzresult Lwt.t +end + +module Logger (Base : Logger_base) = struct + open Stack_utils + open Local_gas_counter + open Script_interpreter_defs + open Script_interpreter.Internals.Raw + + (** [log_entry ctxt gas instr sty accu stack] simply calls the + [Base.log_entry] function with the appropriate arguments. *) + let log_entry ctxt gas k sty accu stack = + let ctxt = Local_gas_counter.update_context gas ctxt in + Base.log_entry k ctxt (kinstr_location k) sty (accu, stack) + + (** [log_exit ctxt gas loc instr sty accu stack] simply calls the + [Base.log_exit] function with the appropriate arguments. *) + let log_exit ctxt gas loc_prev k sty accu stack = + let ctxt = Local_gas_counter.update_context gas ctxt in + Base.log_exit k ctxt loc_prev sty (accu, stack) + + (** [log_control continuation] simply calls the [Base.log_control] + function with the appropriate arguments. *) + let log_control ks = Base.log_control ks + + (** [log_kinstr logger sty instr] returns [instr] prefixed by an + [ILog] instruction to log the first instruction in [instr]. *) + let log_kinstr logger sty i = + ILog (kinstr_location i, sty, LogEntry, logger, i) + + (* [log_next_kinstr logger i] instruments the next instruction of [i] + with [ILog] instructions to make sure it will be logged. + This instrumentation has a performance cost, but importantly, it is + only ever paid when logging is enabled. Otherwise, the possibility + to instrument the script is costless. + + Notice that the instrumentation breaks the sharing of continuations + that is normally enforced between branches of conditionals. This + has a performance cost. Anyway, the instrumentation allocates many + new [ILog] instructions and [KLog] continuations which makes + the execution of instrumented code significantly slower than + non-instrumented code. "Zero-cost logging" means that the normal + non-instrumented execution is not impacted by the ability to + instrument it, not that the logging itself has no cost. + *) + let log_next_kinstr logger sty i = + let apply sty k = + ILog + ( kinstr_location k, + sty, + LogExit (kinstr_location i), + logger, + log_kinstr logger sty k ) + in + kinstr_rewritek sty i {apply} + + (** [log_next_continuation logger sty cont] instruments the next + continuation in [cont] with [KLog] continuations to ensure + logging. + + This instrumentation has a performance cost, but importantly, it + is only ever paid when logging is enabled. Otherwise, the + possibility to instrument the script is costless. *) + let log_next_continuation : + type a b c d. + logger -> + (a, b) stack_ty -> + (a, b, c, d) continuation -> + (a, b, c, d) continuation tzresult = + let open Result_syntax in + fun logger stack_ty cont -> + let enable_log sty ki = log_kinstr logger sty ki in + match cont with + | KCons (ki, k) -> ( + let ki' = enable_log stack_ty ki in + let+ sty = kinstr_final_stack_type stack_ty ki in + match sty with + | None -> KCons (ki', k) + | Some sty -> KCons (ki', instrument_cont logger sty k)) + | KLoop_in (ki, k) -> + let (Item_t (Bool_t, sty)) = stack_ty in + return @@ KLoop_in (enable_log sty ki, instrument_cont logger sty k) + | KReturn (stack, sty, k) -> + let k' = instrument_cont logger (assert_some sty) k in + return @@ KReturn (stack, sty, k') + | KLoop_in_left (ki, k) -> + let (Item_t (Or_t (a_ty, b_ty, _, _), rest)) = stack_ty in + let ki' = enable_log (Item_t (a_ty, rest)) ki in + let k' = instrument_cont logger (Item_t (b_ty, rest)) k in + return @@ KLoop_in_left (ki', k') + | KUndip (x, ty, k) -> + let k' = + instrument_cont logger (Item_t (assert_some ty, stack_ty)) k + in + return @@ KUndip (x, ty, k') + | KIter (body, xty, xs, k) -> + let body' = enable_log (Item_t (assert_some xty, stack_ty)) body in + let k' = instrument_cont logger stack_ty k in + return @@ KIter (body', xty, xs, k') + | KList_enter_body (body, xs, ys, ty, len, k) -> + let k' = + instrument_cont logger (Item_t (assert_some ty, stack_ty)) k + in + return @@ KList_enter_body (body, xs, ys, ty, len, k') + | KList_exit_body (body, xs, ys, ty, len, k) -> + let (Item_t (_, sty)) = stack_ty in + let k' = instrument_cont logger (Item_t (assert_some ty, sty)) k in + return @@ KList_exit_body (body, xs, ys, ty, len, k') + | KMap_enter_body (body, xs, ys, ty, k) -> + let k' = + instrument_cont logger (Item_t (assert_some ty, stack_ty)) k + in + return @@ KMap_enter_body (body, xs, ys, ty, k') + | KMap_exit_body (body, xs, ys, yk, ty, k) -> + let (Item_t (_, sty)) = stack_ty in + let k' = instrument_cont logger (Item_t (assert_some ty, sty)) k in + return @@ KMap_exit_body (body, xs, ys, yk, ty, k') + | KMap_head (_, _) + | KView_exit (_, _) + | KLog _ (* This case should never happen. *) | KNil -> + return cont + + (* + + Zero-cost logging + ================= + + *) + + (* + + The following functions insert a logging instruction to continue + the logging process in the next execution steps. + + There is a special treatment of instructions that generate fresh + continuations: we pass a constructor as argument to their + evaluation rules so that they can instrument these fresh + continuations by themselves. + + This on-the-fly instrumentation of the execution allows zero-cost + logging since logging instructions are only introduced if an + initial logging continuation is pushed in the initial continuation + that starts the evaluation. + + *) + let ilog : + type a s b t r f. + logger -> logging_event -> (a, s) stack_ty -> (a, s, b, t, r, f) step_type + = + let open Lwt_result_syntax in + fun logger event sty ((ctxt, _) as g) old_gas k ks accu stack -> + (match (k, event) with + | ILog _, LogEntry -> () + | _, LogEntry -> log_entry ctxt old_gas k sty accu stack + | _, LogExit prev_loc -> log_exit ctxt old_gas prev_loc k sty accu stack) ; + let*? k = log_next_kinstr logger sty k in + (* We need to match on instructions that create continuations so + that we can instrument those continuations with [KLog] (see + comment above). For functions that don't do this, we simply call + [step], as they don't require any special treatment. *) + match consume_instr old_gas k accu stack with + | None -> tzfail Gas.Operation_quota_exceeded + | Some gas -> ( + match k with + | IIf_none {branch_if_none; branch_if_some; k; _} -> ( + let (Item_t (Option_t (ty, _, _), rest)) = sty in + let*? sty_opt = + branched_final_stack_type + [ + Ex_init_stack_ty (rest, branch_if_none); + Ex_init_stack_ty (Item_t (ty, rest), branch_if_some); + ] + in + let ks' = + match sty_opt with + | None -> KCons (k, ks) + | Some sty' -> instrument_cont logger sty' @@ KCons (k, ks) + in + match accu with + | None -> + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas branch_if_none ks' accu stack + | Some v -> + (step [@ocaml.tailcall]) g gas branch_if_some ks' v stack) + | IOpt_map {body; k; loc = _} -> ( + match accu with + | None -> (step [@ocaml.tailcall]) g gas k ks None stack + | Some v -> + let (Item_t (Option_t (ty, _, _), rest)) = sty in + let bsty = Item_t (ty, rest) in + let kmap_head = KMap_head (Option.some, KCons (k, ks)) in + let*? sty_opt = kinstr_final_stack_type bsty body in + let ks' = + match sty_opt with + | None -> kmap_head + | Some sty' -> instrument_cont logger sty' kmap_head + in + (step [@ocaml.tailcall]) g gas body ks' v stack) + | IIf_left {branch_if_left; branch_if_right; k; _} -> ( + let (Item_t (Or_t (lty, rty, _, _), rest)) = sty in + let*? sty_opt = + branched_final_stack_type + [ + Ex_init_stack_ty (Item_t (lty, rest), branch_if_left); + Ex_init_stack_ty (Item_t (rty, rest), branch_if_right); + ] + in + let k' = + match sty_opt with + | None -> KCons (k, ks) + | Some sty' -> instrument_cont logger sty' @@ KCons (k, ks) + in + match accu with + | L v -> (step [@ocaml.tailcall]) g gas branch_if_left k' v stack + | R v -> (step [@ocaml.tailcall]) g gas branch_if_right k' v stack + ) + | IIf_cons {branch_if_cons; branch_if_nil; k; _} -> ( + let (Item_t ((List_t (elty, _) as lty), rest)) = sty in + let*? sty' = + branched_final_stack_type + [ + Ex_init_stack_ty (rest, branch_if_nil); + Ex_init_stack_ty + (Item_t (elty, Item_t (lty, rest)), branch_if_cons); + ] + in + let k' = + match sty' with + | None -> KCons (k, ks) + | Some sty' -> instrument_cont logger sty' @@ KCons (k, ks) + in + match Script_list.uncons accu with + | None -> + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas branch_if_nil k' accu stack + | Some (hd, tl) -> + (step [@ocaml.tailcall]) g gas branch_if_cons k' hd (tl, stack) + ) + | IList_map (_, body, ty, k) -> + let (Item_t (_, sty')) = sty in + let instrument = instrument_cont logger sty' in + (ilist_map [@ocaml.tailcall]) + instrument + g + gas + body + k + ks + ty + accu + stack + | IList_iter (_, ty, body, k) -> + let (Item_t (_, sty')) = sty in + let instrument = instrument_cont logger sty' in + (ilist_iter [@ocaml.tailcall]) + instrument + g + gas + body + ty + k + ks + accu + stack + | ISet_iter (_, ty, body, k) -> + let (Item_t (_, rest)) = sty in + let instrument = instrument_cont logger rest in + (iset_iter [@ocaml.tailcall]) + instrument + g + gas + body + ty + k + ks + accu + stack + | IMap_map (_, ty, body, k) -> + let (Item_t (_, rest)) = sty in + let instrument = instrument_cont logger rest in + (imap_map [@ocaml.tailcall]) + instrument + g + gas + body + k + ks + ty + accu + stack + | IMap_iter (_, kvty, body, k) -> + let (Item_t (_, rest)) = sty in + let instrument = instrument_cont logger rest in + (imap_iter [@ocaml.tailcall]) + instrument + g + gas + body + kvty + k + ks + accu + stack + | IMul_teznat (loc, k) -> + (imul_teznat [@ocaml.tailcall]) + (Some logger) + g + gas + loc + k + ks + accu + stack + | IMul_nattez (loc, k) -> + (imul_nattez [@ocaml.tailcall]) + (Some logger) + g + gas + loc + k + ks + accu + stack + | ILsl_nat (loc, k) -> + (ilsl_nat [@ocaml.tailcall]) + (Some logger) + g + gas + loc + k + ks + accu + stack + | ILsr_nat (loc, k) -> + (ilsr_nat [@ocaml.tailcall]) + (Some logger) + g + gas + loc + k + ks + accu + stack + | IIf {branch_if_true; branch_if_false; k; _} -> + let (Item_t (Bool_t, rest)) = sty in + let*? sty' = + branched_final_stack_type + [ + Ex_init_stack_ty (rest, branch_if_true); + Ex_init_stack_ty (rest, branch_if_false); + ] + in + let k' = + match sty' with + | None -> KCons (k, ks) + | Some sty' -> instrument_cont logger sty' @@ KCons (k, ks) + in + let res, stack = stack in + if accu then + (step [@ocaml.tailcall]) g gas branch_if_true k' res stack + else (step [@ocaml.tailcall]) g gas branch_if_false k' res stack + | ILoop (_, body, k) -> + let ks = + instrument_cont logger sty @@ KLoop_in (body, KCons (k, ks)) + in + (next [@ocaml.tailcall]) g gas ks accu stack + | ILoop_left (_, bl, br) -> + let ks = + instrument_cont logger sty @@ KLoop_in_left (bl, KCons (br, ks)) + in + (next [@ocaml.tailcall]) g gas ks accu stack + | IDip (_, b, ty, k) -> + let (Item_t (_, rest)) = sty in + let*? rest' = kinstr_final_stack_type rest b in + let ign = accu in + let ks = + match rest' with + | None -> KUndip (ign, ty, KCons (k, ks)) + | Some rest' -> + instrument_cont + logger + rest' + (KUndip (ign, ty, KCons (k, ks))) + in + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas b ks accu stack + | IExec (_, stack_ty, k) -> + let (Item_t (_, Item_t (Lambda_t (_, ret, _), _))) = sty in + let sty' = Item_t (ret, Bot_t) in + let instrument = instrument_cont logger sty' in + iexec instrument (Some logger) g gas stack_ty k ks accu stack + | IFailwith (kloc, tv) -> + let {ifailwith} = ifailwith in + (ifailwith [@ocaml.tailcall]) (Some logger) g gas kloc tv accu + | IDipn (_, _n, n', b, k) -> + let accu, stack, ks = kundip n' accu stack (KCons (k, ks)) in + (step [@ocaml.tailcall]) g gas b ks accu stack + | IView + (_, (View_signature {output_ty; _} as view_signature), stack_ty, k) + -> + let sty' = Item_t (output_ty, Bot_t) in + let instrument = instrument_cont logger sty' in + (iview [@ocaml.tailcall]) + instrument + g + gas + view_signature + stack_ty + k + ks + accu + stack + | _ -> (step [@ocaml.tailcall]) g old_gas k ks accu stack) + [@@inline] + + let klog : + type a s r f. + logger -> + outdated_context * step_constants -> + local_gas_counter -> + (a, s) stack_ty -> + (a, s, r, f) continuation -> + (a, s, r, f) continuation -> + a -> + s -> + (r * f * outdated_context * local_gas_counter) tzresult Lwt.t = + let open Lwt_result_syntax in + fun logger g old_gas stack_ty k0 ks accu stack -> + let ty_for_logging_unsafe = function + (* This function is only called when logging is enabled. If + that's the case, the elaborator must have been called with + [logging_enabled] option, which ensures that this will not be + [None]. Realistically, it can happen that the [logging_enabled] + option was omitted, resulting in a crash here. But this is + acceptable, because logging is never enabled during block + validation, so the layer 1 is safe. *) + | None -> assert false + | Some ty -> ty + in + (match ks with KLog _ -> () | _ -> log_control ks) ; + match consume_control old_gas ks with + | None -> tzfail Gas.Operation_quota_exceeded + | Some gas -> ( + let*? continuation = log_next_continuation logger stack_ty ks in + match continuation with + | KCons (ki, k) -> (step [@ocaml.tailcall]) g gas ki k accu stack + | KLoop_in (ki, k) -> + (kloop_in [@ocaml.tailcall]) g gas k0 ki k accu stack + | KReturn (_, _, _) as k -> + (next [@ocaml.tailcall]) g old_gas k accu stack + | KLoop_in_left (ki, k) -> + (kloop_in_left [@ocaml.tailcall]) g gas k0 ki k accu stack + | KUndip (_, _, _) as k -> + (next [@ocaml.tailcall]) g old_gas k accu stack + | KIter (body, xty, xs, k) -> + let instrument = instrument_cont logger stack_ty in + (kiter [@ocaml.tailcall]) + instrument + g + gas + body + xty + xs + k + accu + stack + | KList_enter_body (body, xs, ys, ty_opt, len, k) -> + let instrument = + let ty = ty_for_logging_unsafe ty_opt in + let (List_t (vty, _)) = ty in + let sty = Item_t (vty, stack_ty) in + instrument_cont logger sty + in + (klist_enter [@ocaml.tailcall]) + instrument + g + gas + body + xs + ys + ty_opt + len + k + accu + stack + | KList_exit_body (body, xs, ys, ty_opt, len, k) -> + let (Item_t (_, rest)) = stack_ty in + let instrument = instrument_cont logger rest in + (klist_exit [@ocaml.tailcall]) + instrument + g + gas + body + xs + ys + ty_opt + len + k + accu + stack + | KMap_enter_body (body, xs, ys, ty_opt, k) -> + let instrument = + let ty = ty_for_logging_unsafe ty_opt in + let (Map_t (_, vty, _)) = ty in + let sty = Item_t (vty, stack_ty) in + instrument_cont logger sty + in + (kmap_enter [@ocaml.tailcall]) + instrument + g + gas + body + xs + ty_opt + ys + k + accu + stack + | KMap_exit_body (body, xs, ys, yk, ty_opt, k) -> + let (Item_t (_, rest)) = stack_ty in + let instrument = instrument_cont logger rest in + (kmap_exit [@ocaml.tailcall]) + instrument + g + gas + body + xs + ty_opt + ys + yk + k + accu + stack + | KMap_head (f, k) -> (next [@ocaml.tailcall]) g gas k (f accu) stack + | KView_exit (scs, k) -> + (next [@ocaml.tailcall]) (fst g, scs) gas k accu stack + | KLog _ as k -> + (* This case should never happen. *) + (next [@ocaml.tailcall]) g old_gas k accu stack + | KNil as k -> (next [@ocaml.tailcall]) g old_gas k accu stack) + [@@inline] +end + +let make (module Base : Logger_base) = + let module Logger = Logger (Base) in + let open Logger in + let open Base in + {log_interp; get_log; log_kinstr; klog; ilog} diff --git a/src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.mli b/src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.mli new file mode 100644 index 000000000000..0492bab3c312 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/script_interpreter_logging.mli @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Environment +open Error_monad +open Script_typed_ir + +module type Logger_base = sig + val log_interp : ('a, 's, 'b, 'f, 'c, 'u) logging_function + + val log_entry : ('a, 's, 'b, 'f, 'a, 's) logging_function + + val log_control : ('a, 's, 'b, 'f) continuation -> unit + + val log_exit : ('a, 's, 'b, 'f, 'c, 'u) logging_function + + val get_log : unit -> execution_trace option tzresult Lwt.t +end + +val make : (module Logger_base) -> logger diff --git a/src/proto_020_PsParisC/lib_plugin/test/dune b/src/proto_020_PsParisC/lib_plugin/test/dune new file mode 100644 index 000000000000..2f0d3d088fae --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/test/dune @@ -0,0 +1,62 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_plugin_test_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-libs.base-test-helpers + octez-libs.base.unix + octez-alcotezt + octez-libs.test-helpers + qcheck-alcotest + octez-libs.stdlib-unix + octez-libs.micheline + octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.parameters + octez-protocol-019-PtParisB-libs.test-helpers) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_base_test_helpers + -open Octez_alcotezt + -open Tezos_test_helpers + -open Tezos_micheline + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB.Protocol + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_019_PtParisB_test_helpers) + (modules + helpers + test_conflict_handler + test_consensus_filter + test_fee_needed_to_overtake + test_fee_needed_to_replace_by_fee)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_plugin_test_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package octez-protocol-019-PtParisB-libs) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_plugin/test/helpers.ml b/src/proto_020_PsParisC/lib_plugin/test/helpers.ml new file mode 100644 index 000000000000..cb44f4007624 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/test/helpers.ml @@ -0,0 +1,172 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** One-element list containing the Tezt tag of the local protocol, + e.g. "alpha", "nairobi", "mumbai", etc. *) +let proto_tags = Alcotezt_utils.is_proto_test __FILE__ + +(** Register a plugin test, with file-specific tags and prefix in title. *) +let register_test ~__FILE__ ~file_title ~file_tags ~title ~additional_tags = + Test.register + ~__FILE__ + ~title:(sf "%s/plugin: %s: %s" Protocol.name file_title title) + ~tags:(proto_tags @ ("plugin" :: (file_tags @ additional_tags))) + +(** Generator for a packed operation preceded by its hash. *) +let oph_and_op_gen = QCheck2.Gen.map snd Operation_generator.generate_operation + +(** Generator for a packed non-manager operation. *) +let non_manager_operation_gen = + Operation_generator.generate_non_manager_operation + +(** Generator for a packed manager operation. *) +let manager_operation_gen = + let open QCheck2.Gen in + let* batch_size = int_range 1 Operation_generator.max_batch_size in + Operation_generator.generate_manager_operation batch_size + +(** Generator for a packed manager operation with the specified + total fee and gas limit. *) +let manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas = + let open Alpha_context in + let open QCheck2.Gen in + let rec set_fee_and_gas : + type kind. _ -> _ -> kind contents_list -> kind contents_list t = + fun desired_total_fee desired_total_gas -> function + | Single (Manager_operation data) -> + let fee = Tez.of_mutez_exn (Int64.of_int desired_total_fee) in + let gas_limit = Gas.Arith.integral_of_int_exn desired_total_gas in + return (Single (Manager_operation {data with fee; gas_limit})) + | Cons (Manager_operation data, tail) -> + let* local_fee = + (* We generate some corner cases where some individual + operations in the batch have zero fees. *) + let* r = frequencyl [(7, `Random); (2, `Zero); (1, `All)] in + match r with + | `Random -> int_range 0 desired_total_fee + | `Zero -> return 0 + | `All -> return desired_total_fee + in + let* local_gas = int_range 0 desired_total_gas in + let fee = Tez.of_mutez_exn (Int64.of_int local_fee) in + let gas_limit = Gas.Arith.integral_of_int_exn local_gas in + let* tail = + set_fee_and_gas + (desired_total_fee - local_fee) + (desired_total_gas - local_gas) + tail + in + return (Cons (Manager_operation {data with fee; gas_limit}, tail)) + | Single _ -> + (* This function is only called on a manager operation. *) assert false + in + (* Generate a random manager operation. *) + let* batch_size = int_range 1 Operation_generator.max_batch_size in + let* op = Operation_generator.generate_manager_operation batch_size in + (* Modify its fee and gas to match the [fee_in_mutez] and [gas] inputs. *) + let {shell = _; protocol_data = Operation_data protocol_data} = op in + let* contents = set_fee_and_gas fee_in_mutez gas protocol_data.contents in + let protocol_data = {protocol_data with contents} in + let op = {op with protocol_data = Operation_data protocol_data} in + return (Operation.hash_packed op, op) + +(** Generate a packed manager operation with the specified total fee + and gas limit. *) +let generate_manager_op_with_fee_and_gas ~fee_in_mutez ~gas = + QCheck2.Gen.generate1 (manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas) + +(** Change the total fee of the packed operation [op] to [fee] (in mutez). + Also change its source to [source] if the argument is provided. + + Precondition: [op] must be a manager operation. *) +let set_fee_and_source fee ?source op = + let open Alpha_context in + let open QCheck2.Gen in + let rec set_fee_contents_list_gen : + type kind. int64 -> kind contents_list -> kind contents_list t = + fun desired_total_fee (* in mutez *) -> function + | Single (Manager_operation data) -> + let fee = Tez.of_mutez_exn desired_total_fee in + let contents = + match source with + | Some source -> Manager_operation {data with fee; source} + | None -> Manager_operation {data with fee} + in + return (Single contents) + | Cons (Manager_operation data, tail) -> + let* local_fee = + (* We generate some corner cases where some individual + operations in the batch have zero fees. *) + let* r = frequencyl [(7, `Random); (2, `Zero); (1, `All)] in + match r with + | `Random -> + let* n = int_range 0 (Int64.to_int desired_total_fee) in + return (Int64.of_int n) + | `Zero -> return 0L + | `All -> return desired_total_fee + in + let fee = Tez.of_mutez_exn local_fee in + let contents = + match source with + | Some source -> Manager_operation {data with fee; source} + | None -> Manager_operation {data with fee} + in + let* tail = + set_fee_contents_list_gen (Int64.sub desired_total_fee local_fee) tail + in + return (Cons (contents, tail)) + | Single _ -> (* see precondition: manager operation *) assert false + in + let {shell = _; protocol_data = Operation_data data} = op in + let contents = generate1 (set_fee_contents_list_gen fee data.contents) in + {op with protocol_data = Operation_data {data with contents}} + +let set_fee fee op = set_fee_and_source fee op + +(** Return an [Operation_hash.t] that is distinct from [different_from]. *) +let different_oph ~different_from = + if Operation_hash.(different_from = zero) then ( + let new_hash = Operation_hash.hash_string ["1"] in + assert (Operation_hash.(new_hash <> zero)) ; + new_hash) + else Operation_hash.zero + +(** List helpers *) + +let rec iter_neighbors f = function + | [] | [_] -> () + | x :: (y :: _ as l) -> + f x y ; + iter_neighbors f l + +let iter2_exn f l1 l2 = + match List.iter2 ~when_different_lengths:() f l1 l2 with + | Ok () -> () + | Error () -> + Test.fail + ~__LOC__ + "Lists have respective lengths %d and %d." + (List.length l1) + (List.length l2) diff --git a/src/proto_020_PsParisC/lib_plugin/test/test_conflict_handler.ml b/src/proto_020_PsParisC/lib_plugin/test/test_conflict_handler.ml new file mode 100644 index 000000000000..50d3d6a73dd8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/test/test_conflict_handler.ml @@ -0,0 +1,226 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Plugin.Mempool + Invocation: dune exec src/proto_020_PsParisC/lib_plugin/test/main.exe \ + -- --file test_conflict_handler.ml + Subject: Unit tests the Mempool.conflict_handler function of the plugin +*) + +let register_test = + Helpers.register_test + ~__FILE__ + ~file_title:"conflict_handler" + ~file_tags:["mempool"; "conflict_handler"] + +let pp_answer fmt = function + | `Keep -> Format.fprintf fmt "Keep" + | `Replace -> Format.fprintf fmt "Replace" + +let check_answer ?__LOC__ expected actual = + assert + (Qcheck2_helpers.qcheck_eq ~pp:pp_answer ?__LOC__ expected actual : bool) + +let is_manager_op ((_ : Operation_hash.t), op) = + (* This is implemented differently from + [Plugin.Mempool.is_manager_operation] (which relies on + [Alpha_context.Operation.acceptable_pass]), used in + [Plugin.Mempool.conflict_handler], to avoid the test being just a + copy of the code. *) + let {Alpha_context.protocol_data = Operation_data proto_data; _} = op in + match proto_data.contents with + | Single (Manager_operation _) | Cons (Manager_operation _, _) -> true + | _ -> false + +(** Test that when the operations are not both manager operations, the + conflict handler picks the higher operation according to + [Operation.compare]. *) +let () = + register_test + ~title:"non-manager operations" + ~additional_tags:["nonmanager"; "random"] + @@ fun () -> + let ops = + QCheck2.Gen.( + generate ~n:100 (pair Helpers.oph_and_op_gen Helpers.oph_and_op_gen)) + in + List.iter + (fun (op1, op2) -> + let answer = + Plugin.Mempool.conflict_handler + Plugin.Mempool.default_config + ~existing_operation:op1 + ~new_operation:op2 + in + if is_manager_op op1 && is_manager_op op2 then + (* When both operations are manager operations, the result is + complicated and depends on the [config]. Testing it here + would mean basically reimplementing + [conflict_handler]. Instead, we test this case in the + "manager operations" test below. *) + () + else if + (* When there is at least one non-manager operation, the + conflict handler defers to [Operation.compare]: the higher + operation is selected. *) + Alpha_context.Operation.compare op1 op2 >= 0 + then check_answer ~__LOC__ `Keep answer + else check_answer ~__LOC__ `Replace answer) + ops ; + unit + +let check_conflict_handler ~__LOC__ config ~old ~nw expected = + let answer = + Plugin.Mempool.conflict_handler + config + ~existing_operation:old + ~new_operation:nw + in + check_answer ~__LOC__ expected answer + +(** Test the semantics of the conflict handler on manager operations, + with either hand-picked or carefully generated fee and gas. *) +let () = + register_test + ~title:"manager operations" + ~additional_tags:["manager"; "random"] + @@ fun () -> + let make_op = Helpers.generate_manager_op_with_fee_and_gas in + + (* Test operations with specific fee and gas, using the default + configuration. This configuration replaces the old operation when + the new one is at least 5% better, in terms of both fees and + fee/gas ratios. *) + let default = Plugin.Mempool.default_config in + let ref_fee = 10_000_000 in + let ref_gas = 2100 in + (* Reference operation arbitrarily has 10 tez of fees and 2100 + gas. The gas is chosen to still give an integer when multiplied + by 100/105. *) + let old = make_op ~fee_in_mutez:ref_fee ~gas:ref_gas in + (* Operation with same fee and ratio. *) + let op_same = make_op ~fee_in_mutez:ref_fee ~gas:ref_gas in + check_conflict_handler ~__LOC__ default ~old ~nw:op_same `Keep ; + (* 5% better fee but same ratio (because gas is also 5% more). *) + let more5 = Q.make (Z.of_int 105) (Z.of_int 100) in + let fee_more5 = Q.(to_int (mul more5 (of_int ref_fee))) in + let gas_more5 = Q.(to_int (mul more5 (of_int ref_gas))) in + let op_fee5 = make_op ~fee_in_mutez:fee_more5 ~gas:gas_more5 in + check_conflict_handler ~__LOC__ default ~old ~nw:op_fee5 `Keep ; + (* 5% better ratio but same fee (because gas is multiplied by 100/105). *) + let less5 = Q.make (Z.of_int 100) (Z.of_int 105) in + let gas_less5 = Q.(to_int (mul less5 (of_int ref_gas))) in + let op_ratio5 = make_op ~fee_in_mutez:ref_fee ~gas:gas_less5 in + check_conflict_handler ~__LOC__ default ~old ~nw:op_ratio5 `Keep ; + (* Both 5% better fee and 5% better ratio. *) + let op_both5 = make_op ~fee_in_mutez:fee_more5 ~gas:ref_gas in + check_conflict_handler ~__LOC__ default ~old ~nw:op_both5 `Replace ; + + (* Config that requires 10% better fee and ratio to replace. *) + let config10 = + Plugin.Mempool.Internal_for_tests.default_config_with_replace_factor + (Q.make (Z.of_int 11) (Z.of_int 10)) + in + + check_conflict_handler ~__LOC__ config10 ~old ~nw:op_same `Keep ; + check_conflict_handler ~__LOC__ config10 ~old ~nw:op_fee5 `Keep ; + check_conflict_handler ~__LOC__ config10 ~old ~nw:op_ratio5 `Keep ; + check_conflict_handler ~__LOC__ config10 ~old ~nw:op_both5 `Keep ; + (* Config that replaces when the new op has at least as much fee and ratio. *) + let config0 = + Plugin.Mempool.Internal_for_tests.default_config_with_replace_factor Q.one + in + check_conflict_handler ~__LOC__ config0 ~old ~nw:op_same `Replace ; + check_conflict_handler ~__LOC__ config0 ~old ~nw:op_fee5 `Replace ; + check_conflict_handler ~__LOC__ config0 ~old ~nw:op_ratio5 `Replace ; + check_conflict_handler ~__LOC__ config0 ~old ~nw:op_both5 `Replace ; + (* This config does not replace when the new operation has worse + fees (even when the ratio is higher). *) + let op_less_fee = make_op ~fee_in_mutez:(ref_fee - 1) ~gas:(ref_gas - 1) in + check_conflict_handler ~__LOC__ default ~old ~nw:op_less_fee `Keep ; + (* This config does not replace either when the ratio is smaller. *) + let op_worse_ratio = make_op ~fee_in_mutez:ref_fee ~gas:(ref_gas + 1) in + check_conflict_handler ~__LOC__ default ~old ~nw:op_worse_ratio `Keep ; + + (* Generate random operations which do not have 5% better fees than + the reference [op]: they should not replace [op] when using the + default config. *) + let open QCheck2.Gen in + let repeat = 30 in + let max_gas = 5 * ref_gas in + let generator_not_5more_fee = + let* fee_in_mutez = int_range 0 (fee_more5 - 1) in + let* gas = int_range 0 max_gas in + Format.eprintf "op_not_fee5: fee = %d; gas = %d@." fee_in_mutez gas ; + Helpers.manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas + in + let ops_not_5more_fee = generate ~n:repeat generator_not_5more_fee in + List.iter + (fun nw -> check_conflict_handler ~__LOC__ default ~old ~nw `Keep) + ops_not_5more_fee ; + (* Generate random operations which do not have 5% better ratio than + the reference [op]: they should not replace [op] when using the + default config. *) + let ratio_5more = + Q.(mul more5 (make (Z.of_int ref_fee) (Z.of_int ref_gas))) + in + let generator_not_5more_ratio = + let* gas = int_range 0 max_gas in + let fee_for_5more_ratio = Q.(mul (of_int gas) ratio_5more) in + let fee_upper_bound = Q.to_int fee_for_5more_ratio - 1 in + let* fee_in_mutez = int_range 0 (max 0 fee_upper_bound) in + Format.eprintf "op_not_ratio5: fee = %d; gas = %d@." fee_in_mutez gas ; + Helpers.manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas + in + let ops_not_5more_ratio = generate ~n:repeat generator_not_5more_ratio in + List.iter + (fun nw -> check_conflict_handler ~__LOC__ default ~old ~nw `Keep) + ops_not_5more_ratio ; + (* Generate random operations which have both 5% higher fees and 5% + better ratio than the reference [op]: they should replace [op] + when using the default config. *) + let max_fee = + (* We use a significantly higher factor to define [max_fee] from + [ref_fee] than [max_gas] from [ref_gas]. Therefore, even if we + generate a gas equal to [max_gas], we can still generate a fee + that makes the ratio at least 5% better than the reference + operation's. *) + 10 * ref_fee + in + let generator_both_5more = + let* gas = int_range 0 max_gas in + let fee_for_5more_ratio = Q.(mul (of_int gas) ratio_5more) in + let fee_lower_bound = max fee_more5 (Q.to_int fee_for_5more_ratio + 1) in + let* fee_in_mutez = int_range fee_lower_bound max_fee in + Format.eprintf "op_both_better: fee = %d; gas = %d@." fee_in_mutez gas ; + Helpers.manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas + in + let ops_both_5more = generate ~n:repeat generator_both_5more in + List.iter + (fun nw -> check_conflict_handler ~__LOC__ default ~old ~nw `Replace) + ops_both_5more ; + Lwt.return_unit diff --git a/src/proto_020_PsParisC/lib_plugin/test/test_consensus_filter.ml b/src/proto_020_PsParisC/lib_plugin/test/test_consensus_filter.ml new file mode 100644 index 000000000000..9ae2a8854567 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/test/test_consensus_filter.ml @@ -0,0 +1,491 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Plugin.Mempool + Invocation: dune exec src/proto_020_PsParisC/lib_plugin/test/main.exe \ + -- --file test_consensus_filter.ml + Subject: Unit tests the Mempool consensus filter +*) + +open Qcheck2_helpers +open Alpha_context +open Plugin.Mempool.Internal_for_tests + +(** {2. Conversion helpers} *) + +let timestamp_of_int32 ts = Timestamp.of_seconds (Int64.of_int32 ts) + +(** Data Generators *) +module Generator = struct + open QCheck2.Gen + + let decorate ?(prefix = "") ?(suffix = "") printer d = + prefix ^ printer d ^ suffix + + let config = + let* drift_int_opt = opt small_nat in + let clock_drift = + Option.map + (fun drift_int -> Period.of_seconds_exn (Int64.of_int drift_int)) + drift_int_opt + in + return (default_config_with_clock_drift clock_drift) + + let print_config = + decorate ~prefix:"clock_drift " (fun config -> + Option.fold + ~none:"round_0 duration" + ~some:(fun drift -> Int64.to_string @@ Period.to_seconds drift) + (get_clock_drift config)) + + let of_result = Result.value_f ~default:(fun _ -> assert false) + + let small_nat_32 = + let+ small_nat in + Int32.of_int small_nat + + let small_signed_32 = + let+ small_signed_int in + Int32.of_int small_signed_int + + let dup gen = + let+ x = gen in + (x, x) + + let round = + let+ x = map (fun i32 -> Round.of_int32 i32) small_nat_32 in + of_result x + + let print_round = Format.asprintf "%a" Round.pp + + let same_rounds = dup round + + let level = + let+ x = map Raw_level.of_int32 small_nat_32 in + of_result x + + let print_level = Format.asprintf "%a" Raw_level.pp + + let same_levels = dup level + + let timestamp = + let+ i32 = int32 in + timestamp_of_int32 i32 + + let print_timestamp = Timestamp.to_notation + + let near_timestamps = + let+ i, diff = pair int32 small_signed_32 in + timestamp_of_int32 i |> fun ts1 -> + timestamp_of_int32 Int32.(add i diff) |> fun ts2 -> (ts1, ts2) + + let successive_timestamp = + let+ ts, (diff : int) = pair timestamp small_nat in + let x = + let open Result_syntax in + let* diff = Period.of_seconds (Int64.of_int diff) in + let* ts2 = Timestamp.(ts +? diff) in + Ok (ts, ts2) + in + of_result x + + let param_acceptable ?(rounds = pair round round) ?(levels = pair level level) + ?(timestamps = near_timestamps) () = + pair config (pair (pair rounds levels) timestamps) + + let print_param_acceptable = + let open QCheck2.Print in + let print_levels = pair print_level print_level in + let print_timestamps = pair print_timestamp print_timestamp in + let print_rounds = pair print_round print_round in + pair print_config (pair (pair print_rounds print_levels) print_timestamps) +end + +let assert_no_error d = match d with Error _ -> assert false | Ok d -> d + +(** Constants : + This could be generated but it would largely increase the search space. *) +let round_durations : Round.round_durations = + assert_no_error + @@ Round.Durations.create + ~first_round_duration:Period.(of_seconds_exn 4L) + ~delay_increment_per_round:Period.(of_seconds_exn 10L) + +let round_zero_duration = Round.round_duration round_durations Round.zero + +(** Don't allow test to fail *) +let no_error = function + | Ok b -> b + | Error errs -> + Format.printf + "test fail due to error : %a@." + Error_monad.pp_print_trace + (Environment.wrap_tztrace errs) ; + false + +(** Helper to compute *) +let durations round_durations start stop = + let open Result_syntax in + List.map_e + (fun round -> + let+ round = Round.of_int round in + Round.round_duration round_durations round |> Period.to_seconds) + Tezos_stdlib.Utils.Infix.(start -- stop) + +(** Expected timestamp for the begining of a round at same level that + the proposal. + + It has been developped before the Round.timestamp_of_round_same_level and has a + different implementation. + +*) +let timestamp_of_round round_durations ~proposal_timestamp ~proposal_round + ~round = + let open Result_syntax in + let* _rnd_dur, exp_ts = + let iproposal_round = Int32.to_int @@ Round.to_int32 proposal_round in + let iround = Int32.to_int @@ Round.to_int32 round in + if Round.(proposal_round = round) then + return (Period.zero, proposal_timestamp) + else if Round.(proposal_round < round) then + let* durations = durations round_durations iproposal_round (iround - 1) in + let* rounds_duration = + Period.of_seconds @@ List.fold_left Int64.add Int64.zero durations + in + let+ ts = Timestamp.(proposal_timestamp +? rounds_duration) in + (rounds_duration, ts) + else + let* durations = durations round_durations iround (iproposal_round - 1) in + List.fold_left Int64.add Int64.zero durations |> fun rounds_duration -> + Timestamp.of_seconds + @@ Int64.sub (Timestamp.to_seconds proposal_timestamp) rounds_duration + |> fun ts -> + let+ rounds_duration = Period.of_seconds rounds_duration in + (rounds_duration, ts) + in + return exp_ts + +let drift_of = + let r0_dur = Round.round_duration round_durations Round.zero in + fun clock_drift -> Option.value ~default:r0_dur clock_drift + +(** [max_ts] computes the upper bound on future timestamps given the + accepted round drift. +*) +let max_ts clock_drift prop_ts now = + Timestamp.(max prop_ts now +? drift_of clock_drift) + +let predecessor_start proposal_timestamp proposal_round grandparent_round = + let open Result_syntax in + assert_no_error + @@ let* proposal_level_offset = + Round.level_offset_of_round + round_durations + ~round:Round.(succ grandparent_round) + in + let* proposal_round_offset = + Round.level_offset_of_round round_durations ~round:proposal_round + in + let* proposal_offset = + Period.(add proposal_level_offset proposal_round_offset) + in + Ok Timestamp.(proposal_timestamp - proposal_offset) + +(** {2. Tests} *) + +(** Test past operations that are accepted whatever the current timestamp is: + strictly before the predecessor level or at the current level and with a + strictly lower round than the head. *) + +let test_acceptable_past_level = + let open QCheck2 in + Test.make + ~print:Generator.print_param_acceptable + ~name:"acceptable past op " + (Generator.param_acceptable ()) + (fun + ( config, + ( ((proposal_round, op_round), (proposal_level, op_level)), + (proposal_timestamp, now_timestamp) ) ) + -> + Raw_level.( + proposal_level > succ op_level + || (proposal_level = op_level && Round.(proposal_round > op_round))) + ==> no_error + @@ acceptable_op + ~config + ~round_durations + ~round_zero_duration + ~proposal_level + ~proposal_round + ~proposal_timestamp + ~proposal_predecessor_level_start: + (predecessor_start + proposal_timestamp + proposal_round + Round.zero) + ~op_level + ~op_round + ~now_timestamp) + +(** Test acceptable operations at current level, current round, i.e. on the + currently considered proposal *) +let test_acceptable_current_level_current_round = + let open QCheck2 in + Test.make + ~print:Generator.print_param_acceptable + ~name:"same round, same level " + Generator.(param_acceptable ~rounds:same_rounds ~levels:same_levels ()) + (fun ( config, + (((op_round, _), (_, op_level)), (proposal_timestamp, now_timestamp)) + ) -> + let proposal_level = op_level in + let proposal_round = op_round in + no_error + @@ acceptable_op + ~config + ~round_durations + ~round_zero_duration + ~proposal_level + ~proposal_round + ~proposal_timestamp + ~proposal_predecessor_level_start: + (predecessor_start proposal_timestamp proposal_round Round.zero) + ~op_level + ~op_round + ~now_timestamp) + +(** Test operations at same level, different round, with an acceptable expected + timestamp for the operation. *) +let test_acceptable_current_level = + let open Result_syntax in + let open QCheck2 in + Test.make + ~print:Generator.print_param_acceptable + ~name:"same level, different round, acceptable op" + Generator.(param_acceptable ~levels:same_levels ()) + (fun ( config, + ( ((proposal_round, op_round), (_, op_level)), + (proposal_timestamp, now_timestamp) ) ) -> + let proposal_level = op_level in + no_error + (let* expected_time = + timestamp_of_round + round_durations + ~proposal_timestamp + ~proposal_round + ~round:op_round + in + let* max_timestamp = + max_ts (get_clock_drift config) proposal_timestamp now_timestamp + in + return Timestamp.(expected_time <= max_timestamp)) + ==> no_error + @@ acceptable_op + ~config + ~round_durations + ~round_zero_duration + ~proposal_level + ~proposal_round + ~proposal_timestamp + ~proposal_predecessor_level_start: + (predecessor_start + proposal_timestamp + proposal_round + Round.zero) + ~op_level + ~op_round + ~now_timestamp) + +(** Test operations at same level, different round, with a too high expected + timestamp for the operation, and not at current round (which is always accepted). *) +let test_not_acceptable_current_level = + let open Result_syntax in + let open QCheck2 in + Test.make + ~print:Generator.print_param_acceptable + ~name:"same level, different round, too far" + Generator.(param_acceptable ~levels:same_levels ()) + (fun ( config, + ( ((proposal_round, op_round), (_, op_level)), + (proposal_timestamp, now_timestamp) ) ) -> + let proposal_level = op_level in + no_error + (let* expected_time = + timestamp_of_round + round_durations + ~proposal_timestamp + ~proposal_round + ~round:op_round + in + let* max_timestamp = + max_ts (get_clock_drift config) proposal_timestamp now_timestamp + in + return + Timestamp.( + expected_time > max_timestamp && Round.(proposal_round <> op_round))) + ==> no_error + (let+ result = + acceptable_op + ~config + ~round_durations + ~round_zero_duration + ~proposal_level + ~proposal_round + ~proposal_timestamp + ~proposal_predecessor_level_start: + (predecessor_start + proposal_timestamp + proposal_round + Round.zero) + ~op_level + ~op_round + ~now_timestamp + in + not result)) + +(** Test operations at next level, different round, with an acceptable timestamp for + the operation. *) +let test_acceptable_next_level = + let open Result_syntax in + let open QCheck2 in + Test.make + ~print:Generator.print_param_acceptable + ~name:"next level, acceptable op" + Generator.(param_acceptable ~levels:same_levels ()) + (fun ( config, + ( ((proposal_round, op_round), (proposal_level, _)), + (proposal_timestamp, now_timestamp) ) ) -> + let op_level = Raw_level.succ proposal_level in + no_error + (let* current_level_start = + timestamp_of_round + round_durations + ~proposal_timestamp + ~proposal_round + ~round:Round.zero + in + let* expected_time = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp:current_level_start + ~predecessor_round:Round.zero + ~round:op_round + in + let* max_timestamp = + max_ts (get_clock_drift config) proposal_timestamp now_timestamp + in + return Timestamp.(expected_time <= max_timestamp)) + ==> no_error + @@ acceptable_op + ~config + ~round_durations + ~round_zero_duration + ~proposal_level + ~proposal_round + ~proposal_timestamp + ~proposal_predecessor_level_start: + (predecessor_start + proposal_timestamp + proposal_round + Round.zero) + ~op_level + ~op_round + ~now_timestamp) + +(** Test operations at next level, different round, with a too high timestamp + for the operation. *) +let test_not_acceptable_next_level = + let open Result_syntax in + let open QCheck2 in + Test.make + ~print:Generator.print_param_acceptable + ~name:"next level, too far" + Generator.( + param_acceptable ~levels:same_levels ~timestamps:successive_timestamp ()) + (fun ( config, + ( ((proposal_round, op_round), (proposal_level, _)), + (proposal_timestamp, now_timestamp) ) ) -> + let op_level = Raw_level.succ proposal_level in + QCheck2.assume + @@ no_error + (let* current_level_start = + timestamp_of_round + round_durations + ~proposal_timestamp + ~proposal_round + ~round:Round.zero + in + let* expected_time = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp:current_level_start + ~predecessor_round:Round.zero + ~round:op_round + in + let* next_level_ts = + Timestamp.( + proposal_timestamp + +? Round.round_duration round_durations proposal_round) + in + let* max_timestamp = + max_ts (get_clock_drift config) next_level_ts now_timestamp + in + return Timestamp.(expected_time > max_timestamp)) ; + no_error + @@ let+ result = + acceptable_op + ~config + ~round_durations + ~round_zero_duration + ~proposal_level + ~proposal_round + ~proposal_timestamp + ~proposal_predecessor_level_start: + (predecessor_start proposal_timestamp proposal_round Round.zero) + ~op_level + ~op_round + ~now_timestamp + in + not result) + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [ + ( "pre_filter", + qcheck_wrap + [ + test_acceptable_past_level; + test_acceptable_current_level_current_round; + test_acceptable_current_level; + test_not_acceptable_current_level; + test_acceptable_next_level; + test_not_acceptable_next_level; + ] ); + ] diff --git a/src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_overtake.ml b/src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_overtake.ml new file mode 100644 index 000000000000..071559d497d8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_overtake.ml @@ -0,0 +1,178 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Plugin.Mempool + Invocation: dune exec src/proto_020_PsParisC/lib_plugin/test/main.exe \ + -- --file test_fee_needed_to_overtake.ml + Subject: Unit tests the Mempool.fee_needed_to_overtake + function of the plugin +*) + +let register_test = + Helpers.register_test + ~__FILE__ + ~file_title:"fee_needed_to_overtake" + ~file_tags:["mempool"; "fee_needed_to_overtake"] + +(** Test that [fee_needed_to_overtake] returns [None] when at least + one argument is a non-manager operation. *) +let () = + register_test + ~title:"non-manager operations" + ~additional_tags:["nonmanager"; "random"] + @@ fun () -> + let n = (* Number of non-manager operations to generate *) 30 in + let non_manager_ops = + QCheck2.Gen.generate ~n Helpers.non_manager_operation_gen + in + (* Test with two non-manager operations. *) + let test op_to_overtake candidate_op = + assert ( + Option.is_none + (Plugin.Mempool.fee_needed_to_overtake ~op_to_overtake ~candidate_op)) + in + Helpers.iter_neighbors test non_manager_ops ; + (* Test with one non-manager and one manager operation. *) + let manager_ops = QCheck2.Gen.generate ~n Helpers.manager_operation_gen in + let test_both op1 op2 = + test op1 op2 ; + test op2 op1 + in + Helpers.iter2_exn test_both non_manager_ops manager_ops ; + unit + +(** Check that {!Plugin.Mempool.fee_needed_to_overtake} correctly + returns the minimal fee with which [candidate_op] would be + guaranteed to be greater than [op_to_overtake]. + + Precondition: both operations are manager operations with respective + total fee and gas limit [fee_o], [gas_o] and [fee_c], [gas_c]. *) +let test_manager_ops (op_to_overtake, fee_o, gas_o) (candidate_op, fee_c, gas_c) + = + Log.debug + "Test op_to_overtake: {fee=%dmutez; gas=%d} and candidate_op: \ + {fee=%dmutez; gas=%d}" + fee_o + gas_o + fee_c + gas_c ; + let fee_needed = + WithExceptions.Option.get ~loc:__LOC__ + @@ Plugin.Mempool.fee_needed_to_overtake + ~op_to_overtake:(snd op_to_overtake) + ~candidate_op:(snd candidate_op) + in + Log.debug " --> fee_needed: %Ld" fee_needed ; + (* We need to ensure that in the operation comparisons below, the + hashes provided as first elements of the pairs are distinct. + Indeed, {!Alpha_context.Operation.compare} always returns 0 when + these hashes are equal, regardless of the operations themselves. *) + let fake_oph = Helpers.different_oph ~different_from:(fst op_to_overtake) in + (* We also set the source to {!Signature.Public_key_hash.zero} in + the operation that will be compared to [op_to_overtake], so that + if their weights (fee/gas ratio) are equal, then the former is + smaller (see [Operation_repr.compare_manager_weight]). *) + let source = Signature.Public_key_hash.zero in + let with_fee fee = + (fake_oph, Helpers.set_fee_and_source fee ~source (snd candidate_op)) + in + let fee_smaller = Int64.sub fee_needed 1L in + if Alpha_context.Operation.compare (with_fee fee_smaller) op_to_overtake > 0 + then + Test.fail + ~__LOC__ + "Adjusted candidate_op: {fee=%Ldmutez; gas=%d} with fee smaller than \ + fee_needed should be smaller than or equal to op_to_overtake: \ + {fee=%dmutez; gas=%d}" + fee_smaller + gas_c + fee_o + gas_o ; + if Alpha_context.Operation.compare (with_fee fee_needed) op_to_overtake <= 0 + then + Test.fail + ~__LOC__ + "Adjusted candidate_op: {fee=%Ldmutez; gas=%d} with fee_needed should be \ + greater than op_to_overtake: {fee=%dmutez; gas=%d}" + fee_needed + gas_c + fee_o + gas_o + +(** Test manager operations with hand-picked fee and gas. *) +let () = + register_test + ~title:"hand-picked fee and gas" + ~additional_tags:["manager"; "handpicked"] + @@ fun () -> + (* Various relative gas limits and fees: equal, off by one, + multiple/divisor, high ppcm, coprime, zero, one, much higher/lower, etc. *) + let fee_in_mutez_and_gas_list = + [ + (1000, 1000); + (500, 1000); + (1000, 1001); + (1000, 999); + (1000, 500); + (1000, 4000); + (1000, 1200); + (333, 777); + (11, 7); + (1000, 31); + (1000, 1); + (1, 100_000); + (1_000_000, 100_001); + (0, 10); + ] + in + let ops = + List.map + (fun (fee_in_mutez, gas) -> + let op = + Helpers.generate_manager_op_with_fee_and_gas ~fee_in_mutez ~gas + in + (op, fee_in_mutez, gas)) + fee_in_mutez_and_gas_list + in + List.iter (fun op -> List.iter (test_manager_ops op) ops) ops ; + unit + +(** Test manager operations with random fee and gas. *) +let () = + register_test + ~title:"random fee and gas" + ~additional_tags:["manager"; "random"] + @@ fun () -> + let gen = + let open QCheck2.Gen in + let* fee_in_mutez = int_range 0 100_000_000 in + let* gas = int_range 1 50_000_000 in + let* op = Helpers.manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas in + return (op, fee_in_mutez, gas) + in + Helpers.iter_neighbors test_manager_ops (QCheck2.Gen.generate ~n:100 gen) ; + unit diff --git a/src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_replace_by_fee.ml b/src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_replace_by_fee.ml new file mode 100644 index 000000000000..e2982c2cf83f --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/test/test_fee_needed_to_replace_by_fee.ml @@ -0,0 +1,210 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Plugin.Mempool + Invocation: dune exec src/proto_020_PsParisC/lib_plugin/test/main.exe \ + -- --file test_fee_needed_to_replace_by_fee.ml + Subject: Unit tests the fee_needed_to_replace_by_fee function + of the mempool plugin +*) + +let register_test = + Helpers.register_test + ~__FILE__ + ~file_title:"fee_needed_to_replace_by_fee" + ~file_tags:["mempool"; "fee_needed_to_replace_by_fee"] + +(** Test that [fee_needed_to_replace_by_fee] returns [None] when at least + one argument is a non-manager operation. *) +let () = + register_test + ~title:"non-manager operations" + ~additional_tags:["nonmanager"; "random"] + @@ fun () -> + let n = (* Number of non-manager operations to generate *) 30 in + let non_manager_ops = + QCheck2.Gen.generate ~n Helpers.non_manager_operation_gen + in + (* Test with two non-manager operations. *) + let test op_to_replace candidate_op = + assert ( + Option.is_none + (Plugin.Mempool.Internal_for_tests.fee_needed_to_replace_by_fee + Plugin.Mempool.default_config + ~op_to_replace + ~candidate_op)) + in + Helpers.iter_neighbors test non_manager_ops ; + (* Test with one non-manager and one manager operation. *) + let manager_ops = QCheck2.Gen.generate ~n Helpers.manager_operation_gen in + let test_both op1 op2 = + test op1 op2 ; + test op2 op1 + in + Helpers.iter2_exn test_both non_manager_ops manager_ops ; + unit + +(** Check that {!Plugin.Mempool.fee_needed_to_replace_by_fee} + correctly returns the minimal fee that [candidate_op] would need to + replace [op_to_replace] through {!Plugin.Mempool.conflict_handler}. + + Precondition: both operations are manager operations with respective + total fee and gas limit [fee_r], [gas_r] and [fee_c], [gas_c]. *) +let test_manager_ops config (op_to_replace, fee_r, gas_r) + (candidate_op, fee_c, gas_c) = + Log.debug + "Test op_to_replace: {fee=%dmutez; gas=%d} and candidate_op: {fee=%dmutez; \ + gas=%d}" + fee_r + gas_r + fee_c + gas_c ; + let fee_needed = + WithExceptions.Option.get ~loc:__LOC__ + @@ Plugin.Mempool.Internal_for_tests.fee_needed_to_replace_by_fee + config + ~op_to_replace:(snd op_to_replace) + ~candidate_op:(snd candidate_op) + in + Log.debug " --> fee_needed: %Ld" fee_needed ; + let with_fee fee = + (fst candidate_op, Helpers.set_fee fee (snd candidate_op)) + in + (if fee_needed > 0L then + let fee_smaller = Int64.pred fee_needed in + match + Plugin.Mempool.conflict_handler + config + ~existing_operation:op_to_replace + ~new_operation:(with_fee fee_smaller) + with + | `Keep -> () + | `Replace -> + Test.fail + ~__LOC__ + "Adjusted candidate_op: {fee=%Ldmutez; gas=%d} with fee smaller than \ + fee_needed should not be allowed to replace op_to_replace: \ + {fee=%dmutez; gas=%d}" + fee_smaller + gas_c + fee_r + gas_r) ; + match + Plugin.Mempool.conflict_handler + config + ~existing_operation:op_to_replace + ~new_operation:(with_fee fee_needed) + with + | `Keep -> + Test.fail + ~__LOC__ + "Adjusted candidate_op: {fee=%Ldmutez; gas=%d} with fee_needed should \ + replace op_to_replace: {fee=%dmutez; gas=%d}" + fee_needed + gas_c + fee_r + gas_r + | `Replace -> () + +(** Test manager operations with hand-picked fee and gas. *) +let () = + register_test + ~title:"hand-picked fee and gas" + ~additional_tags:["manager"; "handpicked"] + @@ fun () -> + let fee_in_mutez_and_gas_list = + [ + (* Various relative gas limits and fees: equal, off by one, + multiple/divisor, high ppcm, coprime, zero, one, much + higher/lower etc. *) + (1000, 1000); + (500, 1000); + (1000, 1001); + (1000, 999); + (1000, 500); + (1000, 4000); + (1000, 1200); + (333, 777); + (11, 7); + (1000, 31); + (1000, 1); + (1, 100_000); + (1_000_000, 100_001); + (0, 10); + (* Values such that fee or fee/gas, relative to (1000, 1000) that + appears above in the list, is close to the default + [replace_by_fee_factor] of 105/100 or its inverse. *) + (1050, 1000); + (1051, 1000); + (1049, 1000); + (1050, 1001); + (1050, 999); + (1000, 1050); + (1000, 1051); + (1000, 1049); + ] + in + let ops = + List.map + (fun (fee_in_mutez, gas) -> + let op = + Helpers.generate_manager_op_with_fee_and_gas ~fee_in_mutez ~gas + in + (op, fee_in_mutez, gas)) + fee_in_mutez_and_gas_list + in + List.iter + (fun op -> + List.iter (test_manager_ops Plugin.Mempool.default_config op) ops) + ops ; + unit + +(** Test manager operations with random fee and gas, and random config. *) +let () = + register_test + ~title:"random fee, gas, and config" + ~additional_tags:["manager"; "random"] + @@ fun () -> + let open QCheck2.Gen in + let gen = + let* fee_in_mutez = int_range 0 100_000_000 in + let* gas = int_range 1 50_000_000 in + let* op = Helpers.manager_op_with_fee_and_gas_gen ~fee_in_mutez ~gas in + return (op, fee_in_mutez, gas) + in + let gen_config = + let* num = int_range 0 1000 in + let* den = int_range 1 1000 in + return + (Plugin.Mempool.Internal_for_tests.default_config_with_replace_factor + (Q.of_ints num den)) + in + let test_manager_ops op_fee_gas1 op_fee_gas2 = + test_manager_ops (generate1 gen_config) op_fee_gas1 op_fee_gas2 + in + Helpers.iter_neighbors test_manager_ops (generate ~n:100 gen) ; + Lwt.return_unit diff --git a/src/proto_020_PsParisC/lib_plugin/view_helpers.ml b/src/proto_020_PsParisC/lib_plugin/view_helpers.ml new file mode 100644 index 000000000000..fc764c73a143 --- /dev/null +++ b/src/proto_020_PsParisC/lib_plugin/view_helpers.ml @@ -0,0 +1,293 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Nomadic Development. *) +(* Copyright (c) 2021-2022 Nomadic Labs, *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Tezos_micheline + +type Environment.Error_monad.error += Viewed_contract_has_no_script + +type Environment.Error_monad.error += View_callback_origination_failed + +type Environment.Error_monad.error += + | Illformed_view_type of Entrypoint.t * Script.expr + +type Environment.Error_monad.error += + | View_never_returns of Entrypoint.t * Contract_hash.t + +type Environment.Error_monad.error += + | View_unexpected_return of Entrypoint.t * Contract_hash.t + +type Environment.Error_monad.error += View_not_found of Contract_hash.t * string + +type Environment.Error_monad.error += Viewer_unexpected_storage + +let () = + Environment.Error_monad.register_error_kind + `Permanent + ~id:"viewedContractHasNoScript" + ~title:"Viewed contract has no script" + ~description:"A view was called on a contract with no script." + ~pp:(fun ppf () -> + Format.fprintf ppf "A view was called on a contract with no script.") + Data_encoding.(unit) + (function Viewed_contract_has_no_script -> Some () | _ -> None) + (fun () -> Viewed_contract_has_no_script) ; + Environment.Error_monad.register_error_kind + `Permanent + ~id:"viewCallbackOriginationFailed" + ~title:"View callback origination failed" + ~description:"View callback origination failed" + ~pp:(fun ppf () -> + Format.fprintf ppf "Error during origination of view callback contract.") + Data_encoding.(unit) + (function View_callback_origination_failed -> Some () | _ -> None) + (fun () -> View_callback_origination_failed) ; + Environment.Error_monad.register_error_kind + `Permanent + ~id:"illformedViewType" + ~title:"An entrypoint type is incompatible with TZIP-4 view type." + ~description:"An entrypoint type is incompatible with TZIP-4 view type." + ~pp:(fun ppf (entrypoint, typ) -> + Format.fprintf + ppf + "The view %a has type %a, it is not compatible with a TZIP-4 view type." + Entrypoint.pp + entrypoint + Micheline_printer.print_expr + (Micheline_printer.printable + (fun x -> x) + (Michelson_v1_primitives.strings_of_prims typ))) + Data_encoding.( + obj2 + (req "entrypoint" Entrypoint.simple_encoding) + (req "type" Script.expr_encoding)) + (function Illformed_view_type (etp, exp) -> Some (etp, exp) | _ -> None) + (fun (etp, exp) -> Illformed_view_type (etp, exp)) ; + Environment.Error_monad.register_error_kind + `Permanent + ~id:"viewNeverReturns" + ~title:"A view never returned a transaction to the given callback contract" + ~description: + "A view never initiated a transaction to the given callback contract." + ~pp:(fun ppf (entrypoint, callback) -> + Format.fprintf + ppf + "The view %a never initiated a transaction to the given callback \ + contract %a." + Entrypoint.pp + entrypoint + Contract_hash.pp + callback) + Data_encoding.( + obj2 + (req "entrypoint" Entrypoint.simple_encoding) + (req "callback" Contract.originated_encoding)) + (function View_never_returns (e, c) -> Some (e, c) | _ -> None) + (fun (e, c) -> View_never_returns (e, c)) ; + Environment.Error_monad.register_error_kind + `Permanent + ~id:"viewUnexpectedReturn" + ~title:"A view returned an unexpected list of operations" + ~description: + "A view initiated a list of operations while the TZIP-4 standard expects \ + only a transaction to the given callback contract." + ~pp:(fun ppf (entrypoint, callback) -> + Format.fprintf + ppf + "The view %a initiated a list of operations while the TZIP-4 standard \ + expects only a transaction to the given callback contract %a." + Entrypoint.pp + entrypoint + Contract_hash.pp + callback) + Data_encoding.( + obj2 + (req "entrypoint" Entrypoint.simple_encoding) + (req "callback" Contract.originated_encoding)) + (function View_unexpected_return (e, c) -> Some (e, c) | _ -> None) + (fun (e, c) -> View_unexpected_return (e, c)) ; + Environment.Error_monad.register_error_kind + `Permanent + ~id:"viewNotFound" + ~title:"A view could not be found" + ~description:"The contract does not have a view of the given name." + ~pp:(fun ppf (contract, name) -> + Format.fprintf + ppf + "The contract %a does not have a view named `%s`." + Contract_hash.pp + contract + name) + Data_encoding.( + obj2 (req "contract" Contract.originated_encoding) (req "view" string)) + (function View_not_found (k, n) -> Some (k, n) | _ -> None) + (fun (k, n) -> View_not_found (k, n)) ; + Environment.Error_monad.register_error_kind + `Permanent + ~id:"viewerUnexpectedStorage" + ~title:"A VIEW instruction returned an unexpected value" + ~description:"A VIEW instruction returned an unexpected value." + ~pp:(fun ppf () -> + Format.fprintf ppf "The simulated view returned an unexpected value.") + Data_encoding.unit + (function Viewer_unexpected_storage -> Some () | _ -> None) + (fun () -> Viewer_unexpected_storage) + +(* This script is actually never run, its usage is to ensure a + contract that has the type `contract ` is originated, which + will be required as callback of the view. *) +let make_tzip4_viewer_script ty : Script.t = + let loc = 0 in + let ty = Micheline.root ty in + let code = + Micheline.strip_locations + @@ Micheline.Seq + ( loc, + [ + Micheline.Prim (loc, Script.K_parameter, [ty], []); + Micheline.Prim + ( loc, + Script.K_storage, + [Micheline.Prim (loc, Script.T_unit, [], [])], + [] ); + Micheline.Prim + ( loc, + Script.K_code, + [Micheline.Prim (loc, Script.I_FAILWITH, [], [])], + [] ); + ] ) + in + let storage = + Micheline.strip_locations (Micheline.Prim (loc, Script.D_Unit, [], [])) + in + {code = Script.lazy_expr code; storage = Script.lazy_expr storage} + +let make_view_parameter input callback = + let loc = 0 in + Micheline.strip_locations + (Micheline.Prim + ( loc, + Script.D_Pair, + [ + input; + Micheline.Bytes + (loc, Data_encoding.Binary.to_bytes_exn Contract.encoding callback); + ], + [] )) + +let extract_view_output_type entrypoint ty = + match Micheline.root ty with + | Micheline.Prim + (_, Script.T_pair, [_; Micheline.Prim (_, Script.T_contract, [ty], _)], _) + -> + Ok (Micheline.strip_locations ty) + | _ -> Environment.Error_monad.error (Illformed_view_type (entrypoint, ty)) + +(* 'view' entrypoints returns their value by calling a callback contract, thus + the expected result is a unique internal transaction to this callback. *) +let extract_parameter_from_operations entrypoint operations callback = + let unexpected_return = + Environment.Error_monad.error + @@ View_unexpected_return (entrypoint, callback) + in + match operations with + | [ + Script_typed_ir.Internal_operation + { + operation = + Transaction_to_smart_contract + { + destination; + unparsed_parameters; + entrypoint = _; + amount = _; + parameters = _; + parameters_ty = _; + location = _; + }; + sender = _; + nonce = _; + }; + ] + when Contract_hash.equal destination callback -> + Ok unparsed_parameters + | [] -> + Environment.Error_monad.error (View_never_returns (entrypoint, callback)) + | _ -> unexpected_return + +(* [make_michelson_viewer_script contract view input input_ty output_ty] + generates a script that calls a view from a given contract, and stores the + result in its storage. *) +let make_michelson_viewer_script address view input input_ty output_ty : + Script.t = + let loc = 0 in + let address = Micheline.String (loc, Contract.to_b58check address) in + let push ty value = Micheline.Prim (loc, Script.I_PUSH, [ty; value], []) in + let storage_decl = Micheline.Prim (loc, Script.T_option, [output_ty], []) in + let body = + Micheline.Seq + ( loc, + [ + Micheline.Prim (loc, Script.I_DROP, [], []); + push (Micheline.Prim (loc, Script.T_address, [], [])) address; + push input_ty (Micheline.root input); + Micheline.Prim + (loc, Script.I_VIEW, [Micheline.String (loc, view); output_ty], []); + Micheline.Prim + ( loc, + Script.I_NIL, + [Micheline.Prim (loc, Script.T_operation, [], [])], + [] ); + Micheline.Prim (loc, Script.I_PAIR, [], []); + ] ) + in + let code = + Micheline.strip_locations + @@ Micheline.Seq + ( loc, + [ + Micheline.Prim + ( loc, + Script.K_parameter, + [Micheline.Prim (loc, Script.T_unit, [], [])], + [] ); + Micheline.Prim (loc, Script.K_storage, [storage_decl], []); + Micheline.Prim (loc, Script.K_code, [body], []); + ] ) + in + let storage = + Micheline.strip_locations (Micheline.Prim (loc, Script.D_None, [], [])) + in + {code = Script.lazy_expr code; storage = Script.lazy_expr storage} + +(* Extracts the value from the mock script generated by + [make_michelson_viewer_script]. *) +let extract_value_from_storage (storage : Script.expr) = + match Micheline.root storage with + | Micheline.Prim (_, Script.D_Some, [value], []) -> Ok value + | _ -> Environment.Error_monad.error @@ Viewer_unexpected_storage diff --git a/src/proto_020_PsParisC/lib_protocol/.ocamlformat-ignore b/src/proto_020_PsParisC/lib_protocol/.ocamlformat-ignore new file mode 100644 index 000000000000..d35d16ffaebe --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/.ocamlformat-ignore @@ -0,0 +1,486 @@ +adaptive_issuance_costs.ml +adaptive_issuance_costs.mli +adaptive_issuance_services.ml +adaptive_issuance_services.mli +adaptive_issuance_storage.ml +adaptive_issuance_storage.mli +alpha_context.ml +alpha_context.mli +alpha_services.ml +alpha_services.mli +already_denounced_storage.ml +already_denounced_storage.mli +amendment.ml +amendment.mli +apply.ml +apply.mli +apply_internal_results.ml +apply_internal_results.mli +apply_operation_result.ml +apply_operation_result.mli +apply_results.ml +apply_results.mli +baking.ml +baking.mli +bitset.ml +bitset.mli +blinded_public_key_hash.ml +blinded_public_key_hash.mli +block_header_repr.ml +block_header_repr.mli +block_payload_hash.ml +block_payload_hash.mli +block_payload_repr.ml +block_payload_repr.mli +bond_id_repr.ml +bond_id_repr.mli +bootstrap_storage.ml +bootstrap_storage.mli +bounded_history_repr.ml +bounded_history_repr.mli +cache_memory_helpers.ml +cache_repr.ml +cache_repr.mli +cache_repr_costs.ml +cache_repr_costs_generated.ml +carbonated_map.ml +carbonated_map.mli +carbonated_map_costs.ml +carbonated_map_costs.mli +carbonated_map_costs_generated.ml +commitment_repr.ml +commitment_repr.mli +commitment_storage.ml +commitment_storage.mli +constants_parametric_previous_repr.ml +constants_parametric_previous_repr.mli +constants_parametric_repr.ml +constants_parametric_repr.mli +constants_repr.ml +constants_repr.mli +constants_services.ml +constants_services.mli +constants_storage.ml +constants_storage.mli +context_binary_proof.ml +context_binary_proof.mli +contract_delegate_storage.ml +contract_delegate_storage.mli +contract_hash.ml +contract_hash.mli +contract_manager_storage.ml +contract_manager_storage.mli +contract_repr.ml +contract_repr.mli +contract_services.ml +contract_services.mli +contract_storage.ml +contract_storage.mli +cycle_repr.ml +cycle_repr.mli +dal_apply.ml +dal_apply.mli +dal_attestation_repr.ml +dal_attestation_repr.mli +dal_costs.ml +dal_costs_generated.ml +dal_costs_generated.mli +dal_errors_repr.ml +dal_operations_repr.ml +dal_operations_repr.mli +dal_services.ml +dal_services.mli +dal_slot_index_repr.ml +dal_slot_index_repr.mli +dal_slot_repr.ml +dal_slot_repr.mli +dal_slot_storage.ml +dal_slot_storage.mli +delegate_activation_storage.ml +delegate_activation_storage.mli +delegate_consensus_key.ml +delegate_consensus_key.mli +delegate_cycles.ml +delegate_cycles.mli +delegate_missed_attestations_storage.ml +delegate_missed_attestations_storage.mli +delegate_rewards.ml +delegate_rewards.mli +delegate_sampler.ml +delegate_sampler.mli +delegate_services.ml +delegate_services.mli +delegate_slashed_deposits_storage.ml +delegate_slashed_deposits_storage.mli +delegate_staking_parameters.ml +delegate_staking_parameters.mli +delegate_storage.ml +delegate_storage.mli +denunciations_repr.ml +denunciations_repr.mli +dependent_bool.ml +dependent_bool.mli +deposits_repr.ml +deposits_repr.mli +destination_repr.ml +destination_repr.mli +destination_storage.ml +destination_storage.mli +entrypoint_repr.ml +entrypoint_repr.mli +fees_storage.ml +fees_storage.mli +fitness_repr.ml +fitness_repr.mli +fixed_point_repr.ml +fixed_point_repr.mli +forbidden_delegates_storage.ml +forbidden_delegates_storage.mli +frozen_staker_repr.ml +frozen_staker_repr.mli +full_staking_balance_repr.ml +full_staking_balance_repr.mli +gas_comparable_input_size.ml +gas_comparable_input_size.mli +gas_input_size.ml +gas_input_size.mli +gas_limit_repr.ml +gas_limit_repr.mli +gas_monad.ml +gas_monad.mli +global_constants_costs.ml +global_constants_costs.mli +global_constants_costs_generated.ml +global_constants_storage.ml +global_constants_storage.mli +indexable.ml +indexable.mli +init_storage.ml +init_storage.mli +issuance_bonus_repr.ml +issuance_bonus_repr.mli +lazy_storage_diff.ml +lazy_storage_diff.mli +lazy_storage_kind.ml +lazy_storage_kind.mli +legacy_script_patches.ml +level_repr.ml +level_repr.mli +level_storage.ml +level_storage.mli +liquidity_baking_cpmm.ml +liquidity_baking_lqt.ml +liquidity_baking_migration.ml +liquidity_baking_migration.mli +liquidity_baking_storage.ml +liquidity_baking_storage.mli +local_gas_counter.ml +local_gas_counter.mli +main.ml +main.mli +manager_counter_repr.ml +manager_counter_repr.mli +manager_repr.ml +manager_repr.mli +mempool_validation.ml +mempool_validation.mli +merkle_list.ml +merkle_list.mli +michelson_v1_gas.ml +michelson_v1_gas.mli +michelson_v1_gas_costs.ml +michelson_v1_gas_costs_generated.ml +michelson_v1_primitives.ml +michelson_v1_primitives.mli +migration_repr.ml +migration_repr.mli +misbehaviour_repr.ml +misbehaviour_repr.mli +misc.ml +misc.mli +non_empty_string.ml +non_empty_string.mli +nonce_hash.ml +nonce_hash.mli +nonce_storage.ml +nonce_storage.mli +operation_costs.ml +operation_costs.mli +operation_repr.ml +operation_repr.mli +origination_nonce.ml +origination_nonce.mli +parameters_repr.ml +parameters_repr.mli +path_encoding.ml +path_encoding.mli +pending_denunciations_storage.ml +pending_denunciations_storage.mli +per_block_votes_repr.ml +per_block_votes_repr.mli +percentage.ml +percentage.mli +period_repr.ml +period_repr.mli +ratio_repr.ml +ratio_repr.mli +raw_context.ml +raw_context.mli +raw_context_intf.ml +raw_level_repr.ml +raw_level_repr.mli +receipt_repr.ml +receipt_repr.mli +round_repr.ml +round_repr.mli +sampler.ml +sampler.mli +sapling_repr.ml +sapling_services.ml +sapling_storage.ml +sapling_storage_costs.ml +sapling_storage_costs_generated.ml +sapling_validator.ml +saturation_repr.ml +saturation_repr.mli +sc_rollup_PVM_sig.ml +sc_rollup_arith.ml +sc_rollup_arith.mli +sc_rollup_commitment_repr.ml +sc_rollup_commitment_repr.mli +sc_rollup_commitment_storage.ml +sc_rollup_commitment_storage.mli +sc_rollup_costs.ml +sc_rollup_costs.mli +sc_rollup_costs_generated.ml +sc_rollup_dal_parameters_repr.ml +sc_rollup_dal_parameters_repr.mli +sc_rollup_data_version_sig.ml +sc_rollup_dissection_chunk_repr.ml +sc_rollup_dissection_chunk_repr.mli +sc_rollup_errors.ml +sc_rollup_game_repr.ml +sc_rollup_game_repr.mli +sc_rollup_inbox_merkelized_payload_hashes_repr.ml +sc_rollup_inbox_merkelized_payload_hashes_repr.mli +sc_rollup_inbox_message_repr.ml +sc_rollup_inbox_message_repr.mli +sc_rollup_inbox_repr.ml +sc_rollup_inbox_repr.mli +sc_rollup_inbox_storage.ml +sc_rollup_inbox_storage.mli +sc_rollup_machine_no_proofs.ml +sc_rollup_machine_no_proofs.mli +sc_rollup_management_protocol.ml +sc_rollup_management_protocol.mli +sc_rollup_metadata_repr.ml +sc_rollup_metadata_repr.mli +sc_rollup_operations.ml +sc_rollup_operations.mli +sc_rollup_outbox_message_repr.ml +sc_rollup_outbox_message_repr.mli +sc_rollup_outbox_storage.ml +sc_rollup_outbox_storage.mli +sc_rollup_proof_repr.ml +sc_rollup_proof_repr.mli +sc_rollup_refutation_storage.ml +sc_rollup_refutation_storage.mli +sc_rollup_repr.ml +sc_rollup_repr.mli +sc_rollup_reveal_hash.ml +sc_rollup_reveal_hash.mli +sc_rollup_riscv.ml +sc_rollup_riscv.mli +sc_rollup_stake_storage.ml +sc_rollup_stake_storage.mli +sc_rollup_staker_index_repr.ml +sc_rollup_staker_index_repr.mli +sc_rollup_staker_index_storage.ml +sc_rollup_staker_index_storage.mli +sc_rollup_storage.ml +sc_rollup_storage.mli +sc_rollup_tick_repr.ml +sc_rollup_tick_repr.mli +sc_rollup_wasm.ml +sc_rollup_wasm.mli +sc_rollup_whitelist_repr.ml +sc_rollup_whitelist_repr.mli +sc_rollup_whitelist_storage.ml +sc_rollup_whitelist_storage.mli +sc_rollups.ml +sc_rollups.mli +script_big_map.ml +script_big_map.mli +script_bytes.ml +script_bytes.mli +script_cache.ml +script_cache.mli +script_comparable.ml +script_comparable.mli +script_expr_hash.ml +script_expr_hash.mli +script_int.ml +script_int.mli +script_interpreter.ml +script_interpreter.mli +script_interpreter_defs.ml +script_ir_annot.ml +script_ir_annot.mli +script_ir_translator.ml +script_ir_translator.mli +script_ir_translator_config.ml +script_ir_unparser.ml +script_ir_unparser.mli +script_list.ml +script_list.mli +script_map.ml +script_map.mli +script_repr.ml +script_repr.mli +script_repr_costs.ml +script_repr_costs_generated.ml +script_set.ml +script_set.mli +script_string.ml +script_string.mli +script_tc_context.ml +script_tc_context.mli +script_tc_errors.ml +script_tc_errors_registration.ml +script_tc_errors_registration.mli +script_timestamp.ml +script_timestamp.mli +script_typed_ir.ml +script_typed_ir.mli +script_typed_ir_size.ml +script_typed_ir_size.mli +script_typed_ir_size_costs.ml +script_typed_ir_size_costs.mli +script_typed_ir_size_costs_generated.ml +seed_repr.ml +seed_repr.mli +seed_storage.ml +seed_storage.mli +services_registration.ml +services_registration.mli +shared_stake.ml +shared_stake.mli +skip_list_costs.ml +skip_list_costs.mli +skip_list_costs_generated.ml +slash_percentage.ml +slash_percentage.mli +slot_repr.ml +slot_repr.mli +stake_context.ml +stake_context.mli +stake_repr.ml +stake_repr.mli +stake_storage.ml +stake_storage.mli +staking.ml +staking.mli +staking_parameters_repr.ml +staking_parameters_repr.mli +staking_pseudotoken_repr.ml +staking_pseudotoken_repr.mli +staking_pseudotokens_storage.ml +staking_pseudotokens_storage.mli +state_hash.ml +state_hash.mli +storage.ml +storage.mli +storage_costs.ml +storage_costs.mli +storage_costs_generated.ml +storage_description.ml +storage_description.mli +storage_functors.ml +storage_functors.mli +storage_sigs.ml +tez_repr.ml +tez_repr.mli +ticket_accounting.ml +ticket_accounting.mli +ticket_amount.ml +ticket_amount.mli +ticket_balance_key.ml +ticket_balance_key.mli +ticket_costs.ml +ticket_costs.mli +ticket_costs_generated.ml +ticket_hash_builder.ml +ticket_hash_builder.mli +ticket_hash_repr.ml +ticket_hash_repr.mli +ticket_lazy_storage_diff.ml +ticket_lazy_storage_diff.mli +ticket_operations_diff.ml +ticket_operations_diff.mli +ticket_receipt.ml +ticket_receipt.mli +ticket_scanner.ml +ticket_scanner.mli +ticket_storage.ml +ticket_storage.mli +ticket_token.ml +ticket_token.mli +ticket_token_map.ml +ticket_token_map.mli +ticket_token_unparser.ml +ticket_token_unparser.mli +ticket_transfer.ml +ticket_transfer.mli +time_repr.ml +time_repr.mli +token.ml +token.mli +tx_rollup_l2_address.ml +tx_rollup_l2_address.mli +unstake_requests_storage.ml +unstake_requests_storage.mli +unstaked_frozen_deposits_repr.ml +unstaked_frozen_deposits_repr.mli +unstaked_frozen_deposits_storage.ml +unstaked_frozen_deposits_storage.mli +unstaked_frozen_staker_repr.ml +unstaked_frozen_staker_repr.mli +validate.ml +validate.mli +validate_errors.ml +validate_errors.mli +vote_repr.ml +vote_repr.mli +vote_storage.ml +vote_storage.mli +votes_EMA_repr.ml +votes_EMA_repr.mli +voting_period_repr.ml +voting_period_repr.mli +voting_period_storage.ml +voting_period_storage.mli +voting_services.ml +voting_services.mli +zk_rollup_account_repr.ml +zk_rollup_account_repr.mli +zk_rollup_apply.ml +zk_rollup_apply.mli +zk_rollup_circuit_public_inputs_repr.ml +zk_rollup_circuit_public_inputs_repr.mli +zk_rollup_errors.ml +zk_rollup_operation_repr.ml +zk_rollup_operation_repr.mli +zk_rollup_parameters.ml +zk_rollup_parameters.mli +zk_rollup_repr.ml +zk_rollup_repr.mli +zk_rollup_scalar.ml +zk_rollup_scalar.mli +zk_rollup_state_repr.ml +zk_rollup_state_repr.mli +zk_rollup_storage.ml +zk_rollup_storage.mli +zk_rollup_ticket_repr.ml +zk_rollup_ticket_repr.mli +zk_rollup_update_repr.ml +zk_rollup_update_repr.mli diff --git a/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL b/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL new file mode 100644 index 000000000000..d3e1bef8a58f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL @@ -0,0 +1,295 @@ +{ + "expected_env_version": 12, + "hash": "PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ", + "modules": [ + "Misc", + "Non_empty_string", + "Path_encoding", + "Storage_description", + "State_hash", + "Nonce_hash", + "Script_expr_hash", + "Origination_nonce", + "Contract_hash", + "Blinded_public_key_hash", + "Block_payload_hash", + "Sc_rollup_reveal_hash", + "Merkle_list", + "Bitset", + "Bounded_history_repr", + "Context_binary_proof", + "Ratio_repr", + "Percentage", + + + "Michelson_v1_primitives", + "Slot_repr", + "Cycle_repr", + "Tez_repr", + "Deposits_repr", + "Unstaked_frozen_deposits_repr", + "Staking_pseudotoken_repr", + "Period_repr", + "Time_repr", + "Round_repr", + "Block_payload_repr", + "Fixed_point_repr", + "Saturation_repr", + "Gas_limit_repr", + "Raw_level_repr", + "Issuance_bonus_repr", + "Constants_parametric_repr", + "Constants_parametric_previous_repr", + "Constants_repr", + "Fitness_repr", + "Level_repr", + "Script_repr_costs_generated", + "Script_repr_costs", + "Script_repr", + "Cache_memory_helpers", + "Seed_repr", + "Sampler", + "Voting_period_repr", + "Ticket_hash_repr", + "Manager_counter_repr", + "Contract_repr", + "Indexable", + "Entrypoint_repr", + + "Dal_slot_index_repr", + "Dal_slot_repr", + "Dal_attestation_repr", + + "Michelson_v1_gas_costs_generated", + "Michelson_v1_gas_costs", + + "Sc_rollup_repr", + "Sc_rollup_metadata_repr", + "Sc_rollup_dal_parameters_repr", + "Sc_rollup_tick_repr", + "Sc_rollup_inbox_message_repr", + "Sc_rollup_inbox_merkelized_payload_hashes_repr", + "Sc_rollup_whitelist_repr", + "Sc_rollup_outbox_message_repr", + "Sc_rollup_dissection_chunk_repr", + "Sc_rollup_PVM_sig", + "Sc_rollup_arith", + "Sc_rollup_wasm", + "Sc_rollup_riscv", + "Sc_rollup_machine_no_proofs", + "Sc_rollups", + "Sc_rollup_data_version_sig", + "Sc_rollup_inbox_repr", + "Sc_rollup_staker_index_repr", + "Sc_rollup_commitment_repr", + "Sc_rollup_proof_repr", + "Skip_list_costs_generated", + "Skip_list_costs", + "Sc_rollup_costs_generated", + "Sc_rollup_costs", + "Sc_rollup_game_repr", + "Tx_rollup_l2_address", + + "Dal_errors_repr", + "Dal_operations_repr", + "Dal_costs_generated", + "Dal_costs", + + "Zk_rollup_scalar", + "Zk_rollup_repr", + "Zk_rollup_state_repr", + "Zk_rollup_account_repr", + "Zk_rollup_ticket_repr", + "Zk_rollup_operation_repr", + "Zk_rollup_update_repr", + "Zk_rollup_circuit_public_inputs_repr", + + "Bond_id_repr", + "Vote_repr", + "Votes_EMA_repr", + "Per_block_votes_repr", + "Block_header_repr", + "Destination_repr", + "Script_int", + "Ticket_amount", + "Operation_repr", + "Manager_repr", + "Commitment_repr", + "Parameters_repr", + "Sapling_repr", + "Lazy_storage_kind", + "Full_staking_balance_repr", + "Unstaked_frozen_staker_repr", + "Frozen_staker_repr", + "Stake_repr", + "Receipt_repr", + "Migration_repr", + "Carbonated_map_costs_generated", + "Carbonated_map_costs", + "Carbonated_map", + "Staking_parameters_repr", + "Misbehaviour_repr", + "Denunciations_repr", + + "Raw_context_intf", + "Raw_context", + + "Storage_costs_generated", + "Storage_costs", + "Storage_sigs", + "Storage_functors", + "Storage", + + "Global_constants_costs_generated", + "Global_constants_costs", + "Ticket_hash_builder", + "Constants_storage", + "Level_storage", + "Nonce_storage", + "Seed_storage", + "Contract_manager_storage", + "Delegate_activation_storage", + "Sapling_storage_costs_generated", + "Sapling_storage_costs", + "Sapling_storage", + "Lazy_storage_diff", + "Commitment_storage", + "Voting_period_storage", + "Cache_repr_costs_generated", + "Cache_repr_costs", + "Cache_repr", + + "Zk_rollup_storage", + + "Stake_context", + "Contract_delegate_storage", + "Stake_storage", + "Unstaked_frozen_deposits_storage", + "Pending_denunciations_storage", + "Unstake_requests_storage", + "Staking_pseudotokens_storage", + + "Contract_storage", + "Token", + "Fees_storage", + "Adaptive_issuance_costs", + "Adaptive_issuance_storage", + "Delegate_staking_parameters", + "Shared_stake", + "Delegate_consensus_key", + "Delegate_storage", + "Delegate_sampler", + "Delegate_rewards", + "Delegate_missed_attestations_storage", + "Already_denounced_storage", + "Forbidden_delegates_storage", + "Slash_percentage", + "Delegate_slashed_deposits_storage", + "Staking", + "Delegate_cycles", + + "Vote_storage", + "Ticket_storage", + "Liquidity_baking_storage", + "Liquidity_baking_cpmm", + "Liquidity_baking_lqt", + "Liquidity_baking_migration", + + "Sc_rollup_errors", + "Sc_rollup_inbox_storage", + + "Legacy_script_patches", + "Sapling_validator", + + "Global_constants_storage", + "Sc_rollup_staker_index_storage", + "Sc_rollup_commitment_storage", + "Sc_rollup_outbox_storage", + "Sc_rollup_whitelist_storage", + "Sc_rollup_stake_storage", + "Sc_rollup_storage", + "Dal_slot_storage", + "Sc_rollup_refutation_storage", + "Zk_rollup_errors", + + "Bootstrap_storage", + "Init_storage", + + "Destination_storage", + + "Alpha_context", + "Script_string", + "Script_timestamp", + "Script_bytes", + + "Local_gas_counter", + "Script_tc_errors", + "Gas_monad", + "Script_ir_annot", + "Dependent_bool", + "Script_list", + "Script_typed_ir", + "Script_comparable", + "Gas_comparable_input_size", + "Script_set", + "Script_map", + "Gas_input_size", + "Script_typed_ir_size", + "Script_typed_ir_size_costs_generated", + "Script_typed_ir_size_costs", + "Michelson_v1_gas", + "Operation_costs", + "Script_tc_context", + "Ticket_token", + "Ticket_receipt", + "Apply_operation_result", + "Apply_internal_results", + "Apply_results", + "Script_ir_translator_config", + "Script_ir_unparser", + "Script_ir_translator", + "Script_big_map", + "Script_cache", + "Script_tc_errors_registration", + "Ticket_token_unparser", + "Ticket_costs_generated", + "Ticket_costs", + "Ticket_scanner", + "Ticket_balance_key", + "Ticket_lazy_storage_diff", + + "Zk_rollup_parameters", + + "Ticket_token_map", + "Ticket_operations_diff", + "Ticket_accounting", + "Ticket_transfer", + + "Script_interpreter_defs", + "Script_interpreter", + "Sc_rollup_management_protocol", + "Sc_rollup_operations", + + "Dal_apply", + "Zk_rollup_apply", + + "Baking", + "Validate_errors", + "Amendment", + "Validate", + "Mempool_validation", + "Apply", + + "Services_registration", + "Constants_services", + "Sapling_services", + "Contract_services", + "Delegate_services", + "Voting_services", + "Dal_services", + "Adaptive_issuance_services", + "Alpha_services", + + "Main" + ] +} diff --git a/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.ml b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.ml new file mode 100644 index 000000000000..a83188471de3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.ml @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module S = Saturation_repr + +let find_delegate_cost = 420_000 + +let allocated_cost = S.safe_int 210_000 + +let stake_cost = S.safe_int (find_delegate_cost + 2_100_000) + +let set_delegate_parameters_cost = S.safe_int (find_delegate_cost + 200_000) + +let prepare_finalize_unstake_cost = S.safe_int 940_000 + +let finalize_unstake_and_check_cost = S.safe_int 200_000 + +let request_unstake_cost = S.safe_int (find_delegate_cost + 2_300_000) + +let find_delegate_cost = S.safe_int find_delegate_cost diff --git a/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.mli b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.mli new file mode 100644 index 000000000000..8875abb86aa9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_costs.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines costs for the adaptive issuance operations. *) + +val find_delegate_cost : Gas_limit_repr.cost + +val allocated_cost : Gas_limit_repr.cost + +val stake_cost : Gas_limit_repr.cost + +val set_delegate_parameters_cost : Gas_limit_repr.cost + +val prepare_finalize_unstake_cost : Gas_limit_repr.cost + +val finalize_unstake_and_check_cost : Gas_limit_repr.cost + +val request_unstake_cost : Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.ml b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.ml new file mode 100644 index 000000000000..2907d0a2434f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.ml @@ -0,0 +1,307 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type expected_rewards = { + cycle : Cycle.t; + baking_reward_fixed_portion : Tez.t; + baking_reward_bonus_per_slot : Tez.t; + attesting_reward_per_slot : Tez.t; + seed_nonce_revelation_tip : Tez.t; + vdf_revelation_tip : Tez.t; +} + +let expected_rewards_encoding : expected_rewards Data_encoding.t = + let open Data_encoding in + conv + (fun { + cycle; + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + seed_nonce_revelation_tip; + vdf_revelation_tip; + } -> + ( cycle, + baking_reward_fixed_portion, + baking_reward_bonus_per_slot, + attesting_reward_per_slot, + seed_nonce_revelation_tip, + vdf_revelation_tip )) + (fun ( cycle, + baking_reward_fixed_portion, + baking_reward_bonus_per_slot, + attesting_reward_per_slot, + seed_nonce_revelation_tip, + vdf_revelation_tip ) -> + { + cycle; + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + seed_nonce_revelation_tip; + vdf_revelation_tip; + }) + (obj6 + (req "cycle" Cycle.encoding) + (req "baking_reward_fixed_portion" Tez.encoding) + (req "baking_reward_bonus_per_slot" Tez.encoding) + (req "attesting_reward_per_slot" Tez.encoding) + (req "seed_nonce_revelation_tip" Tez.encoding) + (req "vdf_revelation_tip" Tez.encoding)) + +module S = struct + open Data_encoding + + let q_encoding = + conv + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> Q.make num den) + (obj2 (req "numerator" n) (req "denominator" n)) + + let context_path = RPC_path.(open_root / "context") + + let path = RPC_path.(context_path / "issuance") + + let total_supply = + RPC_service.get_service + ~description:"Returns the total supply (in mutez) available on the chain" + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(context_path / "total_supply") + + let total_frozen_stake = + RPC_service.get_service + ~description:"Returns the total stake (in mutez) frozen on the chain" + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(context_path / "total_frozen_stake") + + let current_yearly_rate = + RPC_service.get_service + ~description: + "Returns the current expected maximum yearly issuance rate (in %)" + ~query:RPC_query.empty + ~output:(string Plain) + RPC_path.(path / "current_yearly_rate") + + let current_yearly_rate_exact = + RPC_service.get_service + ~description: + "Returns the current expected maximum yearly issuance rate (exact \ + quotient)" + ~query:RPC_query.empty + ~output:q_encoding + RPC_path.(path / "current_yearly_rate_exact") + + let current_yearly_rate_details = + RPC_service.get_service + ~description: + "Returns the static and dynamic parts of the current expected maximum \ + yearly issuance rate." + ~query:RPC_query.empty + ~output:(obj2 (req "static" q_encoding) (req "dynamic" q_encoding)) + RPC_path.(path / "current_yearly_rate_details") + + let current_issuance_per_minute = + RPC_service.get_service + ~description: + "Returns the current expected maximum issuance per minute (in mutez)" + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "issuance_per_minute") + + let launch_cycle = + RPC_service.get_service + ~description: + "Returns the cycle at which the launch of the Adaptive Issuance \ + feature is set to happen. A result of None means that the feature is \ + not yet set to launch." + ~query:RPC_query.empty + ~output:(Data_encoding.option Cycle.encoding) + RPC_path.(context_path / "adaptive_issuance_launch_cycle") + + let expected_issuance = + RPC_service.get_service + ~description: + "Returns the expected issued tez for the provided block and the next \ + 'consensus_rights_delay' cycles" + ~query:RPC_query.empty + ~output:(Data_encoding.list expected_rewards_encoding) + RPC_path.(path / "expected_issuance") +end + +let q_to_float_string q = + let offset = 1000 in + let unit = Z.div q.Q.num q.den in + let q = Q.(sub q (unit /// Z.one)) in + let q = Q.(mul q (offset // 1)) in + let dec = Z.div q.num q.den in + let padded_dec_string = Format.asprintf "%03d" (Z.to_int dec) in + Format.asprintf "%a.%s" Z.pp_print unit padded_dec_string + +let current_rewards_per_minute ctxt = + let open Lwt_result_syntax in + let base_total_issued_per_minute = + (Constants.issuance_weights ctxt).base_total_issued_per_minute + in + let q_base_total_issued_per_minute = + Tez.to_mutez base_total_issued_per_minute |> Q.of_int64 + in + let cycle = (Level.current ctxt).cycle in + let* f = Delegate.Rewards.For_RPC.get_reward_coeff ctxt ~cycle in + let f = Q.mul f q_base_total_issued_per_minute (* rewards per minute *) in + return f + +(* Does the reverse operations of [compute_coeff] in [adaptive_issuance_storage.ml] *) +let current_yearly_rate_value ~formatter ctxt = + let open Lwt_result_syntax in + let q_min_per_year = Q.of_int 525600 in + let* total_supply = Contract.get_total_supply ctxt in + let q_total_supply = Tez.to_mutez total_supply |> Q.of_int64 in + let* f = current_rewards_per_minute ctxt in + let f = Q.div f q_total_supply (* issuance rate per minute *) in + let f = Q.mul f q_min_per_year (* issuance rate per year *) in + (* transform into a string *) + let f = Q.(mul f (100 // 1)) in + return (formatter f) + +let collect_expected_rewards ~ctxt = + let open Lwt_result_syntax in + let open Delegate.Rewards in + let ctxt_cycle = (Level.current ctxt).cycle in + let csts = (Constants.all ctxt).parametric in + let reward_of_cycle cycle = + if Cycle.(cycle = ctxt_cycle) then + let*? baking_reward_fixed_portion = baking_reward_fixed_portion ctxt in + let*? baking_reward_bonus_per_slot = baking_reward_bonus_per_slot ctxt in + let*? attesting_reward_per_slot = attesting_reward_per_slot ctxt in + let*? seed_nonce_revelation_tip = seed_nonce_revelation_tip ctxt in + let*? vdf_revelation_tip = vdf_revelation_tip ctxt in + return + { + cycle; + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + seed_nonce_revelation_tip; + vdf_revelation_tip; + } + else + (* This coeff is correct only when applied to Cycle lesser than + [issuance_modification_delay] after the current context, otherwise the coeff will + not be set and thus we get the default values. *) + let open Delegate.Rewards.For_RPC in + let* coeff = get_reward_coeff ctxt ~cycle in + + let*? baking_reward_fixed_portion = + reward_from_constants + ~coeff + csts + ~reward_kind:Baking_reward_fixed_portion + in + let*? baking_reward_bonus_per_slot = + reward_from_constants + ~coeff + csts + ~reward_kind:Baking_reward_bonus_per_slot + in + let*? attesting_reward_per_slot = + reward_from_constants ~coeff csts ~reward_kind:Attesting_reward_per_slot + in + let*? seed_nonce_revelation_tip = + reward_from_constants ~coeff csts ~reward_kind:Seed_nonce_revelation_tip + in + let*? vdf_revelation_tip = + reward_from_constants ~coeff csts ~reward_kind:Vdf_revelation_tip + in + return + { + cycle; + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + seed_nonce_revelation_tip; + vdf_revelation_tip; + } + in + let queried_cycles = + Cycle.( + ctxt_cycle + ---> add ctxt_cycle (Constants.issuance_modification_delay ctxt)) + in + List.map_es reward_of_cycle queried_cycles + +let register () = + let open Services_registration in + let open Lwt_result_syntax in + register0 ~chunked:false S.total_supply (fun ctxt () () -> + Contract.get_total_supply ctxt) ; + register0 ~chunked:false S.total_frozen_stake (fun ctxt () () -> + let cycle = (Level.current ctxt).cycle in + Stake_distribution.get_total_frozen_stake ctxt cycle) ; + register0 ~chunked:false S.current_yearly_rate (fun ctxt () () -> + current_yearly_rate_value ~formatter:q_to_float_string ctxt) ; + register0 ~chunked:false S.current_yearly_rate_exact (fun ctxt () () -> + current_yearly_rate_value ~formatter:(fun x -> x) ctxt) ; + register0 ~chunked:false S.current_yearly_rate_details (fun ctxt () () -> + let* total = current_yearly_rate_value ~formatter:(fun x -> x) ctxt in + let cycle = Some (Level.current ctxt).cycle in + let* bonus = Delegate.Rewards.For_RPC.get_reward_bonus ctxt ~cycle in + let dynamic = (bonus :> Q.t) in + let static = Q.(total - dynamic) in + return (static, dynamic)) ; + register0 ~chunked:false S.current_issuance_per_minute (fun ctxt () () -> + let* f = current_rewards_per_minute ctxt in + return (Tez.of_mutez_exn (Q.to_int64 f))) ; + register0 ~chunked:false S.launch_cycle (fun ctxt () () -> + Adaptive_issuance.launch_cycle ctxt) ; + register0 ~chunked:false S.expected_issuance (fun ctxt () () -> + collect_expected_rewards ~ctxt) + +let total_supply ctxt block = + RPC_context.make_call0 S.total_supply ctxt block () () + +let total_frozen_stake ctxt block = + RPC_context.make_call0 S.total_frozen_stake ctxt block () () + +let current_yearly_rate ctxt block = + RPC_context.make_call0 S.current_yearly_rate ctxt block () () + +let current_yearly_rate_exact ctxt block = + RPC_context.make_call0 S.current_yearly_rate_exact ctxt block () () + +let current_yearly_rate_details ctxt block = + RPC_context.make_call0 S.current_yearly_rate_details ctxt block () () + +let current_issuance_per_minute ctxt block = + RPC_context.make_call0 S.current_issuance_per_minute ctxt block () () + +let launch_cycle ctxt block = + RPC_context.make_call0 S.launch_cycle ctxt block () () + +let expected_issuance ctxt block = + RPC_context.make_call0 S.expected_issuance ctxt block () () diff --git a/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.mli b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.mli new file mode 100644 index 000000000000..058845f9b80a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_services.mli @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type expected_rewards = { + cycle : Cycle.t; + baking_reward_fixed_portion : Tez.t; + baking_reward_bonus_per_slot : Tez.t; + attesting_reward_per_slot : Tez.t; + seed_nonce_revelation_tip : Tez.t; + vdf_revelation_tip : Tez.t; +} + +val expected_rewards_encoding : expected_rewards Data_encoding.t + +val total_supply : 'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t + +val total_frozen_stake : + 'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t + +val current_yearly_rate : + 'a #RPC_context.simple -> 'a -> string shell_tzresult Lwt.t + +val current_yearly_rate_exact : + 'a #RPC_context.simple -> 'a -> Q.t shell_tzresult Lwt.t + +val current_yearly_rate_details : + 'a #RPC_context.simple -> 'a -> (Q.t * Q.t) shell_tzresult Lwt.t + +val current_issuance_per_minute : + 'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t + +val launch_cycle : + 'a #RPC_context.simple -> 'a -> Cycle.t option shell_tzresult Lwt.t + +(** Returns the list of expected issued tez for the current cycle and for the next + [consensus_rights_delay] cycles. *) +val expected_issuance : + 'a #RPC_context.simple -> 'a -> expected_rewards list shell_tzresult Lwt.t + +val register : unit -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.ml b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.ml new file mode 100644 index 000000000000..f7f77fab71e0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.ml @@ -0,0 +1,397 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Default reward coefficient when AI is not in effect, chosen so that + rewards * coeff = rewards *) +let default_reward = Q.one + +(* Default bonus value *) +let default_bonus = Issuance_bonus_repr.zero + +(* Note: the reward and the bonus values are computed as rationals ([Q.t]) but + are stored as fixed-point values (see {!Issuance_bonus_repr}) so that the + stored representation does not grow unboundedly. *) + +type error += Undetermined_issuance_coeff_for_cycle of Cycle_repr.t + +let () = + let open Data_encoding in + let undetermined_issuance_coeff_for_cycle_description = + "Issuance coefficient is only determined for the current cycle and the \ + next [consensus_rights_delay] cycles to come. Requested cycle is not in \ + this window." + in + register_error_kind + `Permanent + ~id:"undetermined_issuance_coeff_for_cycle" + ~title:"Undetermined issuance coeff for cycle" + ~description:undetermined_issuance_coeff_for_cycle_description + ~pp:(fun ppf cycle -> + Format.fprintf + ppf + "%s (cycle %a)" + undetermined_issuance_coeff_for_cycle_description + Cycle_repr.pp + cycle) + (obj1 (req "Undetermined_issuance_coeff_for_cycle" Cycle_repr.encoding)) + (function + | Undetermined_issuance_coeff_for_cycle cycle -> Some cycle | _ -> None) + (fun cycle -> Undetermined_issuance_coeff_for_cycle cycle) + +let launch_cycle ctxt = Storage.Adaptive_issuance.Activation.get ctxt + +let check_determined_cycle ctxt cycle = + let ai_enable = Constants_storage.adaptive_issuance_enable ctxt in + if ai_enable then + let ctxt_cycle = (Raw_context.current_level ctxt).cycle in + let cycles_delay = Constants_storage.issuance_modification_delay ctxt in + fail_unless + Cycle_repr.(ctxt_cycle <= cycle && cycle <= add ctxt_cycle cycles_delay) + (Undetermined_issuance_coeff_for_cycle cycle) + else return_unit + +let get_reward_coeff ctxt ~cycle = + let open Lwt_result_syntax in + let* () = check_determined_cycle ctxt cycle in + let ai_enable = Constants_storage.adaptive_issuance_enable ctxt in + if ai_enable then + (* Even if AI is enabled, the storage can be empty: this is the case for + the first 5 cycles after AI is enabled *) + let* k_opt = Storage.Issuance_coeff.find ctxt cycle in + return (Option.value ~default:default_reward k_opt) + else return default_reward + +let get_reward_bonus ctxt ~cycle = + let open Lwt_result_syntax in + match cycle with + | None -> return default_bonus + | Some cycle -> + let ai_enable = Constants_storage.adaptive_issuance_enable ctxt in + if ai_enable then + let* k_opt = Storage.Issuance_bonus.find ctxt cycle in + return (Option.value ~default:default_bonus k_opt) + else return default_bonus + +let load_reward_coeff ctxt ~cycle = + let open Lwt_result_syntax in + let* new_reward = get_reward_coeff ctxt ~cycle in + let ctxt = + Raw_context.update_reward_coeff_for_current_cycle ctxt new_reward + in + return ctxt + +let truncate_reward_coeff ~issuance_ratio_min ~issuance_ratio_max f = + let f = Q.min f issuance_ratio_max in + let f = Q.max f issuance_ratio_min in + f + +let compute_extremum ~launch_cycle ~new_cycle ~initial_period ~transition_period + ~initial ~final = + match launch_cycle with + | None -> + (* This case shouldn't happen, but if it does this value is the most sensible *) + initial + | Some launch_cycle -> + let transition_period = transition_period + 1 in + assert (Compare.Int.(transition_period > 0)) ; + let t1 = Cycle_repr.add launch_cycle initial_period in + let t2 = Cycle_repr.add t1 transition_period in + if Cycle_repr.(new_cycle <= t1) then initial + else if Cycle_repr.(new_cycle >= t2) then final + else + let t = Cycle_repr.diff new_cycle t1 |> Q.of_int32 in + Q.(((final - initial) * t / of_int transition_period) + initial) + +let compute_min + ~(reward_params : Constants_parametric_repr.adaptive_rewards_params) = + let Constants_parametric_repr. + { + initial_period; + transition_period; + issuance_ratio_initial_min; + issuance_ratio_final_min; + _; + } = + reward_params + in + compute_extremum + ~initial_period + ~transition_period + ~initial:issuance_ratio_initial_min + ~final:issuance_ratio_final_min + +let compute_max + ~(reward_params : Constants_parametric_repr.adaptive_rewards_params) = + let Constants_parametric_repr. + { + initial_period; + transition_period; + issuance_ratio_initial_max; + issuance_ratio_final_max; + _; + } = + reward_params + in + compute_extremum + ~initial_period + ~transition_period + ~initial:issuance_ratio_initial_max + ~final:issuance_ratio_final_max + +let compute_reward_coeff_ratio_without_bonus = + let q_1600 = Q.of_int 1600 in + fun ~stake_ratio ~issuance_ratio_max ~issuance_ratio_min -> + let inv_f = Q.(mul (mul stake_ratio stake_ratio) q_1600) in + let f = Q.inv inv_f (* f = 1/1600 * (1/x)^2 = yearly issuance rate *) in + (* f is truncated so that 0.05% <= f <= 5% *) + truncate_reward_coeff ~issuance_ratio_min ~issuance_ratio_max f + +let compute_bonus ~issuance_ratio_max ~seconds_per_cycle ~stake_ratio + ~base_reward_coeff_ratio ~(previous_bonus : Issuance_bonus_repr.t) + ~reward_params = + let Constants_parametric_repr. + { + issuance_ratio_final_min = _; + issuance_ratio_final_max = _; + issuance_ratio_initial_min = _; + issuance_ratio_initial_max = _; + initial_period = _; + transition_period = _; + max_bonus; + growth_rate; + center_dz; + radius_dz; + } = + reward_params + in + let base_reward_coeff_dist_to_max = + Q.(issuance_ratio_max - base_reward_coeff_ratio) + in + (* The bonus reward is truncated between [0] and [max_bonus] *) + (* It is done in a way that the bonus does not increase if the coeff + would already be above the [reward_pct_max] *) + let max_new_bonus = + Compare.Q.min base_reward_coeff_dist_to_max (max_bonus :> Q.t) + in + (* [dist] is the distance from [stake_ratio] to [48%,52%] *) + let unsigned_dist = + Q.(max zero (abs (stake_ratio - center_dz) - radius_dz)) + in + let q_dist = + if Compare.Q.(stake_ratio >= center_dz) then Q.neg unsigned_dist + else unsigned_dist + in + let q_seconds_per_cycle = Q.of_int64 seconds_per_cycle in + let q_days_per_cycle = Q.div q_seconds_per_cycle (Q.of_int 86_400) in + let q_previous_bonus = (previous_bonus :> Q.t) in + let new_bonus = + Q.(add q_previous_bonus (mul q_dist (mul growth_rate q_days_per_cycle))) + in + let new_bonus = Q.max new_bonus Q.zero in + let new_bonus = Q.min new_bonus max_new_bonus in + Issuance_bonus_repr.of_Q ~max_bonus new_bonus + +let compute_coeff = + let q_min_per_year = Q.of_int 525600 in + fun ~issuance_ratio_max + ~issuance_ratio_min + ~base_total_issued_per_minute + ~base_reward_coeff_ratio + ~q_total_supply + ~(bonus : Issuance_bonus_repr.t) -> + if Tez_repr.(base_total_issued_per_minute = zero) then Q.one + else + let q_base_total_issued_per_minute = + Tez_repr.to_mutez base_total_issued_per_minute |> Q.of_int64 + in + let f = Q.add base_reward_coeff_ratio (bonus :> Q.t) in + let f = truncate_reward_coeff ~issuance_ratio_min ~issuance_ratio_max f in + let f = Q.div f q_min_per_year (* = issuance rate per minute *) in + let f = Q.mul f q_total_supply (* = issuance per minute *) in + Q.div f q_base_total_issued_per_minute + +let compute_and_store_reward_coeff_at_cycle_end ctxt ~new_cycle = + let open Lwt_result_syntax in + let ai_enable = Constants_storage.adaptive_issuance_enable ctxt in + if not ai_enable then return ctxt + else + let* launch_cycle = launch_cycle ctxt in + let reward_params = + Constants_storage.adaptive_issuance_rewards_params ctxt + in + let modification_delay = + Constants_storage.issuance_modification_delay ctxt + in + let for_cycle = Cycle_repr.add new_cycle modification_delay in + let before_for_cycle = Cycle_repr.pred for_cycle in + let* total_supply = Storage.Contract.Total_supply.get ctxt in + let* total_stake = Stake_storage.get_total_active_stake ctxt for_cycle in + let base_total_issued_per_minute = + (Constants_storage.issuance_weights ctxt).base_total_issued_per_minute + in + let total_frozen_stake = Stake_repr.get_frozen total_stake in + let* previous_bonus = get_reward_bonus ctxt ~cycle:before_for_cycle in + let blocks_per_cycle = + Constants_storage.blocks_per_cycle ctxt |> Int64.of_int32 + in + let minimal_block_delay = + Constants_storage.minimal_block_delay ctxt |> Period_repr.to_seconds + in + let seconds_per_cycle = Int64.mul blocks_per_cycle minimal_block_delay in + let q_total_supply = Tez_repr.to_mutez total_supply |> Q.of_int64 in + let q_total_frozen_stake = + Tez_repr.to_mutez total_frozen_stake |> Q.of_int64 + in + let stake_ratio = + Q.div q_total_frozen_stake q_total_supply (* = portion of frozen stake *) + in + let issuance_ratio_min = + compute_min ~launch_cycle ~new_cycle ~reward_params + in + let issuance_ratio_max = + compute_max ~launch_cycle ~new_cycle ~reward_params + in + let base_reward_coeff_ratio = + compute_reward_coeff_ratio_without_bonus + ~stake_ratio + ~issuance_ratio_max + ~issuance_ratio_min + in + let*? bonus = + compute_bonus + ~issuance_ratio_max + ~seconds_per_cycle + ~stake_ratio + ~base_reward_coeff_ratio + ~previous_bonus + ~reward_params + in + let coeff = + compute_coeff + ~issuance_ratio_max + ~issuance_ratio_min + ~base_total_issued_per_minute + ~base_reward_coeff_ratio + ~q_total_supply + ~bonus + in + let*! ctxt = Storage.Issuance_bonus.add ctxt for_cycle bonus in + let*! ctxt = Storage.Issuance_coeff.add ctxt for_cycle coeff in + return ctxt + +let clear_outdated_reward_data ctxt ~new_cycle = + let open Lwt_syntax in + match Cycle_repr.sub new_cycle 2 with + | None -> Lwt.return ctxt + | Some cycle -> + let* ctxt = Storage.Issuance_coeff.remove ctxt cycle in + Storage.Issuance_bonus.remove ctxt cycle + +let update_stored_rewards_at_cycle_end ctxt ~new_cycle = + let open Lwt_result_syntax in + let* ctxt = compute_and_store_reward_coeff_at_cycle_end ctxt ~new_cycle in + let*! ctxt = clear_outdated_reward_data ctxt ~new_cycle in + load_reward_coeff ctxt ~cycle:new_cycle + +let load_reward_coeff ctxt = + load_reward_coeff ctxt ~cycle:(Raw_context.current_level ctxt).cycle + +let init ctxt = + let open Lwt_result_syntax in + let* ctxt = Storage.Adaptive_issuance.Launch_ema.init ctxt 0l in + Storage.Adaptive_issuance.Activation.init ctxt None + +let activate ctxt ~cycle = + Storage.Adaptive_issuance.Activation.update ctxt (Some cycle) + +let set_adaptive_issuance_enable ctxt = + let open Lwt_result_syntax in + let+ enable = + let+ launch_cycle = launch_cycle ctxt in + match launch_cycle with + | None -> false + | Some launch_cycle -> + let current_cycle = (Level_storage.current ctxt).cycle in + Cycle_repr.(current_cycle >= launch_cycle) + in + if enable then Raw_context.set_adaptive_issuance_enable ctxt else ctxt + +let update_ema ctxt ~vote = + let open Lwt_result_syntax in + let* old_ema = Storage.Adaptive_issuance.Launch_ema.get ctxt in + let* old_ema = + Per_block_votes_repr.Adaptive_issuance_launch_EMA.of_int32 old_ema + in + let new_ema = + Per_block_votes_repr.compute_new_adaptive_issuance_ema + ~per_block_vote:vote + old_ema + in + let* ctxt = + Storage.Adaptive_issuance.Launch_ema.update + ctxt + (Per_block_votes_repr.Adaptive_issuance_launch_EMA.to_int32 new_ema) + in + let* launch_cycle = launch_cycle ctxt in + let open Constants_storage in + let+ ctxt, launch_cycle = + if + (not (adaptive_issuance_activation_vote_enable ctxt)) + || Per_block_votes_repr.Adaptive_issuance_launch_EMA.( + new_ema < adaptive_issuance_launch_ema_threshold ctxt) + then return (ctxt, launch_cycle) + else + match launch_cycle with + | Some _ -> + (* the feature is already set to launch, do nothing to avoid postponing it. *) + return (ctxt, launch_cycle) + | None -> + (* set the feature to activate in a few cycles *) + let current_cycle = (Level_storage.current ctxt).cycle in + let delay = adaptive_issuance_activation_delay ctxt in + let cycle = Cycle_repr.add current_cycle delay in + let+ ctxt = activate ctxt ~cycle in + (ctxt, Some cycle) + in + (ctxt, launch_cycle, new_ema) + +module For_RPC = struct + let get_reward_coeff = get_reward_coeff + + let get_reward_bonus = get_reward_bonus +end + +module Internal_for_tests = struct + let compute_reward_coeff_ratio_without_bonus = + compute_reward_coeff_ratio_without_bonus + + let compute_bonus = compute_bonus + + let compute_coeff = compute_coeff + + let compute_min = compute_min + + let compute_max = compute_max +end diff --git a/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.mli b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.mli new file mode 100644 index 000000000000..ac58aa860691 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/adaptive_issuance_storage.mli @@ -0,0 +1,132 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [set_adaptive_issuance_enable ctxt] sets the feature flag in the + in-memory part of the context if the adaptive issuance feature has + already launched. This means that the activation vote resulted in + an approbation from the stakeholders and this happened sufficiently + long ago. *) +val set_adaptive_issuance_enable : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** [load_reward_coeff ctxt] loads the current cycle's reward coeff from the + storage into the context *) +val load_reward_coeff : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** [update_stored_rewards_at_cycle_end ctxt ~new_cycle] updates + {!Storage.Issuance_coeff} with a new coefficient that will be applied + [consensus_rights_delay] cycles after the given [new_cycle]. This new coefficient + depends on the current {!Storage.Total_supply}, and the total active stake + for when this coefficient is computed. + + This function also removes obsolete values from {!Storage.Issuance_coeff}, + and stores the current cycle's coefficient in the context for faster + access. *) +val update_stored_rewards_at_cycle_end : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +(** [init ctxt] adds into the context an adaptive issuance vote EMA + at 0, and adaptive issuance launch cycle at None. *) +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** [update_ema ctxt ~vote] returns the new context with the new EMA *) +val update_ema : + Raw_context.t -> + vote:Per_block_votes_repr.per_block_vote -> + (Raw_context.t + * Cycle_repr.t option + * Per_block_votes_repr.Adaptive_issuance_launch_EMA.t) + tzresult + Lwt.t + +(** [launch_cycle ctxt] reads from the context the cycle at which + the adaptive issuance feature is set to activate. + + If this function returns [None], then it means the feature has not been + voted to be activated (yet). *) +val launch_cycle : Raw_context.t -> Cycle_repr.t option tzresult Lwt.t + +module For_RPC : sig + (** [get_reward_coeff ctxt cycle] reads the reward coeff for the given cycle + from the storage. + + Fails if the given cycle is not between [current_cycle] and + [current_cycle + consensus_rights_delay]. + + If adaptive issuance has not been activated, + then this function returns [Q.one]. + Used only for RPCs. To get the actual rewards, use [Delegate_rewards]. *) + val get_reward_coeff : + Raw_context.t -> cycle:Cycle_repr.t -> Q.t tzresult Lwt.t + + (** [get_reward_bonus ctxt cycle] reads the reward bonus for the given cycle + from the storage. If [cycle] is [None], returns 0. + + Returns 0 if the given cycle is not between [current_cycle] and + [current_cycle + consensus_rights_delay]. + + If adaptive issuance has not been activated, + then this function returns 0. + Used only for RPCs. To get the actual rewards, use [Delegate_rewards]. *) + val get_reward_bonus : + Raw_context.t -> + cycle:Cycle_repr.t option -> + Issuance_bonus_repr.t tzresult Lwt.t +end + +module Internal_for_tests : sig + (** Reward computation functions *) + val compute_reward_coeff_ratio_without_bonus : + stake_ratio:Q.t -> issuance_ratio_max:Q.t -> issuance_ratio_min:Q.t -> Q.t + + val compute_bonus : + issuance_ratio_max:Q.t -> + seconds_per_cycle:int64 -> + stake_ratio:Q.t -> + base_reward_coeff_ratio:Q.t -> + previous_bonus:Issuance_bonus_repr.t -> + reward_params:Constants_parametric_repr.adaptive_rewards_params -> + Issuance_bonus_repr.t tzresult + + val compute_coeff : + issuance_ratio_max:Q.t -> + issuance_ratio_min:Q.t -> + base_total_issued_per_minute:Tez_repr.t -> + base_reward_coeff_ratio:Q.t -> + q_total_supply:Q.t -> + bonus:Issuance_bonus_repr.t -> + Q.t + + val compute_min : + reward_params:Constants_parametric_repr.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> + Q.t + + val compute_max : + reward_params:Constants_parametric_repr.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> + Q.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/alpha_context.ml b/src/proto_020_PsParisC/lib_protocol/alpha_context.ml new file mode 100644 index 000000000000..6e5b48cc2a7e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/alpha_context.ml @@ -0,0 +1,776 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Raw_context.t + +type context = t + +module type BASIC_DATA = sig + type t + + include Compare.S with type t := t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +module Tez = Tez_repr +module Period = Period_repr + +module Timestamp = struct + include Time_repr + + let current = Raw_context.current_timestamp + + let predecessor = Raw_context.predecessor_timestamp +end + +module Slot = Slot_repr +module Sc_rollup_repr = Sc_rollup_repr + +module Sc_rollup = struct + module Tick = Sc_rollup_tick_repr + include Sc_rollup_repr + + module Whitelist = struct + include Sc_rollup_whitelist_storage + include Sc_rollup_whitelist_repr + end + + module Metadata = Sc_rollup_metadata_repr + module Dal_parameters = Sc_rollup_dal_parameters_repr + module Dissection_chunk = Sc_rollup_dissection_chunk_repr + include Sc_rollup_PVM_sig + module ArithPVM = Sc_rollup_arith + module Wasm_2_0_0PVM = Sc_rollup_wasm.V2_0_0 + module Riscv_PVM = Sc_rollup_riscv + + module Inbox_message = struct + include Sc_rollup_inbox_message_repr + + let protocol_migration_internal_message = + Raw_context.protocol_migration_internal_message + + let protocol_migration_serialized_message = + Raw_context.protocol_migration_serialized_message + end + + module Inbox_merkelized_payload_hashes = + Sc_rollup_inbox_merkelized_payload_hashes_repr + + module Staker = struct + include Sc_rollup_repr.Staker + module Index = Sc_rollup_staker_index_repr + end + + module Inbox = struct + include Sc_rollup_inbox_repr + include Sc_rollup_inbox_storage + + let genesis = + genesis + ~protocol_migration_message: + Inbox_message.protocol_migration_serialized_message + + let add_all_messages ~first_block = + add_all_messages + ~protocol_migration_message: + (if first_block then + Some Inbox_message.protocol_migration_internal_message + else None) + + module Internal_for_tests = struct + include Sc_rollup_inbox_repr.Internal_for_tests + end + end + + module Proof = Sc_rollup_proof_repr + module Game = Sc_rollup_game_repr + + module Commitment = struct + include Sc_rollup_commitment_repr + include Sc_rollup_commitment_storage + end + + module Stake_storage = struct + include Sc_rollup_stake_storage + end + + module Refutation_storage = Sc_rollup_refutation_storage + include Sc_rollup_storage + include Sc_rollups + + module Outbox = struct + include Sc_rollup_outbox_storage + module Message = Sc_rollup_outbox_message_repr + end + + module Errors = Sc_rollup_errors +end + +module Dal = struct + include Dal_slot_repr + include Raw_context.Dal + + module Slot_index = struct + include Dal_slot_index_repr + end + + module Attestation = struct + include Dal_attestation_repr + include Raw_context.Dal + end + + type slot_id = Dal_slot_repr.Header.id = { + published_level : Raw_level_repr.t; + index : Dal_slot_index_repr.t; + } + + module Page = struct + include Dal_slot_repr.Page + end + + module Slot = struct + include Dal_slot_repr + include Dal_slot_storage + include Raw_context.Dal + end + + module Operations = struct + include Dal_operations_repr + end + + module Slots_history = Dal_slot_repr.History + module Slots_storage = Dal_slot_storage +end + +module Dal_errors = Dal_errors_repr + +module Zk_rollup = struct + include Zk_rollup_repr + module State = Zk_rollup_state_repr + module Account = Zk_rollup_account_repr + module Operation = Zk_rollup_operation_repr + module Ticket = Zk_rollup_ticket_repr + module Errors = Zk_rollup_errors + module Circuit_public_inputs = Zk_rollup_circuit_public_inputs_repr + module Update = Zk_rollup_update_repr + include Zk_rollup_storage +end + +module Entrypoint = Entrypoint_repr +module Manager_counter = Manager_counter_repr +include Operation_repr + +module Operation = struct + type 'kind t = 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; + } + + type packed = packed_operation + + let unsigned_encoding = unsigned_operation_encoding + + let unsigned_encoding_with_legacy_attestation_name = + unsigned_operation_encoding_with_legacy_attestation_name + + include Operation_repr +end + +module Block_header = Block_header_repr + +module Vote = struct + include Vote_repr + include Vote_storage +end + +module Block_payload = struct + include Block_payload_repr +end + +module First_level_of_protocol = struct + let get = Storage.Tenderbake.First_level_of_protocol.get +end + +module Ratio = Ratio_repr + +module Raw_level = struct + include Raw_level_repr + + module Internal_for_tests = struct + let add = add + + let sub = sub + + let from_repr (level : raw_level) = level + + let to_repr (level : raw_level) = level + end +end + +module Cycle = Cycle_repr +module Fees = Fees_storage + +type public_key = Signature.Public_key.t + +type public_key_hash = Signature.Public_key_hash.t + +type signature = Signature.t + +module Constants = struct + include Constants_repr + include Constants_storage + module Parametric = Constants_parametric_repr + + let round_durations ctxt = Raw_context.round_durations ctxt + + let all ctxt = all_of_parametric (parametric ctxt) +end + +module Voting_period = struct + include Voting_period_repr + include Voting_period_storage +end + +module Round = struct + include Round_repr + module Durations = Durations + + type round_durations = Durations.t + + let pp_round_durations = Durations.pp + + let round_durations_encoding = Durations.encoding + + let round_duration = Round_repr.Durations.round_duration + + let update ctxt round = Storage.Block_round.update ctxt round + + let get ctxt = Storage.Block_round.get ctxt + + module Internal_for_tests = struct + include Internal_for_tests + + let from_repr (round : round) = round + + let to_repr (round : round) = round + end +end + +module Gas = struct + include Gas_limit_repr + + type error += Block_quota_exceeded = Raw_context.Block_quota_exceeded + + type error += Operation_quota_exceeded = Raw_context.Operation_quota_exceeded + + let set_limit = Raw_context.set_gas_limit + + let consume_limit_in_block = Raw_context.consume_gas_limit_in_block + + let set_unlimited = Raw_context.set_gas_unlimited + + let consume = Raw_context.consume_gas + + let consume_from available_gas cost = + let open Result_syntax in + match raw_consume available_gas cost with + | Some remaining_gas -> return remaining_gas + | None -> tzfail Operation_quota_exceeded + + let remaining_operation_gas = Raw_context.remaining_operation_gas + + let update_remaining_operation_gas = + Raw_context.update_remaining_operation_gas + + let reset_block_gas ctxt = + let gas = Arith.fp @@ Constants.hard_gas_limit_per_block ctxt in + Raw_context.update_remaining_block_gas ctxt gas + + let level = Raw_context.gas_level + + let consumed = Raw_context.gas_consumed + + let block_level = Raw_context.block_gas_level + + (* Necessary to inject costs for Storage_costs into Gas.cost *) + let cost_of_repr cost = cost +end + +module Script = struct + include Michelson_v1_primitives + include Script_repr + + type consume_deserialization_gas = Always | When_needed + + let force_decode_in_context ~consume_deserialization_gas ctxt lexpr = + let open Result_syntax in + let gas_cost = + match consume_deserialization_gas with + | Always -> Script_repr.stable_force_decode_cost lexpr + | When_needed -> Script_repr.force_decode_cost lexpr + in + let* ctxt = Raw_context.consume_gas ctxt gas_cost in + let+ v = Script_repr.force_decode lexpr in + (v, ctxt) + + let force_bytes_in_context ctxt lexpr = + let open Result_syntax in + let* ctxt = + Raw_context.consume_gas ctxt (Script_repr.force_bytes_cost lexpr) + in + let+ v = Script_repr.force_bytes lexpr in + (v, ctxt) + + let consume_decoding_gas available_gas lexpr = + let gas_cost = Script_repr.stable_force_decode_cost lexpr in + Gas.consume_from available_gas gas_cost +end + +module Level = struct + include Level_repr + include Level_storage +end + +module Lazy_storage = struct + module Kind = Lazy_storage_kind + module IdSet = Kind.IdSet + include Lazy_storage_diff +end + +module Origination_nonce = struct + let init = Raw_context.init_origination_nonce + + let unset = Raw_context.unset_origination_nonce + + module Internal_for_tests = Origination_nonce +end + +module Destination = struct + include Destination_repr + include Destination_storage +end + +module Contract = struct + include Contract_repr + include Contract_storage + + let is_manager_key_revealed = Contract_manager_storage.is_manager_key_revealed + + let check_public_key = Contract_manager_storage.check_public_key + + let reveal_manager_key = Contract_manager_storage.reveal_manager_key + + let get_manager_key = Contract_manager_storage.get_manager_key + + let is_delegate = Contract_delegate_storage.is_delegate + + type delegate_status = Contract_delegate_storage.delegate_status = + | Delegate + | Delegated of public_key_hash + | Undelegated + + let get_delegate_status = Contract_delegate_storage.get_delegate_status + + module For_RPC = struct + include Contract_storage.For_RPC + include Delegate_slashed_deposits_storage.For_RPC + end + + module Delegate = struct + let find = Contract_delegate_storage.find + + include Delegate_storage.Contract + end + + module Internal_for_tests = struct + include Contract_repr + include Contract_storage + end +end + +module Global_constants_storage = Global_constants_storage + +module Big_map = struct + module Big_map = Lazy_storage_kind.Big_map + + module Id = struct + type t = Big_map.Id.t + + let encoding = Big_map.Id.encoding + + let rpc_arg = Big_map.Id.rpc_arg + + let parse_z = Big_map.Id.parse_z + + let unparse_to_z = Big_map.Id.unparse_to_z + end + + let fresh ~temporary c = Lazy_storage.fresh Big_map ~temporary c + + let mem c m k = Storage.Big_map.Contents.mem (c, m) k + + let get_opt c m k = Storage.Big_map.Contents.find (c, m) k + + let list_key_values ?offset ?length c m = + Storage.Big_map.Contents.list_key_values ?offset ?length (c, m) + + let exists c id = + let open Lwt_result_syntax in + let*? c = Raw_context.consume_gas c (Gas_limit_repr.read_bytes_cost 0) in + let* kt = Storage.Big_map.Key_type.find c id in + match kt with + | None -> return (c, None) + | Some kt -> + let+ kv = Storage.Big_map.Value_type.get c id in + (c, Some (kt, kv)) + + type update = Big_map.update = { + key : Script_repr.expr; + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = Big_map.updates + + type alloc = Big_map.alloc = { + key_type : Script_repr.expr; + value_type : Script_repr.expr; + } +end + +module Sapling = struct + module Sapling_state = Lazy_storage_kind.Sapling_state + + module Id = struct + type t = Sapling_state.Id.t + + let encoding = Sapling_state.Id.encoding + + let rpc_arg = Sapling_state.Id.rpc_arg + + let parse_z = Sapling_state.Id.parse_z + + let unparse_to_z = Sapling_state.Id.unparse_to_z + end + + include Sapling_repr + include Sapling_storage + include Sapling_validator + + let fresh ~temporary c = Lazy_storage.fresh Sapling_state ~temporary c + + type updates = Sapling_state.updates + + type alloc = Sapling_state.alloc = {memo_size : Sapling_repr.Memo_size.t} + + module Legacy = struct + include Sapling.UTXO.Legacy + + let transaction_get_memo_size transaction = + match transaction.outputs with + | [] -> None + | {ciphertext; _} :: _ -> + (* Encoding ensures all ciphertexts have the same memo size. *) + Some (Sapling.Ciphertext.get_memo_size ciphertext) + + let transaction_in_memory_size transaction = + transaction_in_memory_size (cast transaction) + + let verify_update ctxt state transaction key = + verify_update ctxt state (cast transaction) key + end +end + +module Bond_id = struct + include Bond_id_repr + module Internal_for_tests = Contract_storage +end + +module Receipt = struct + type unstaked_frozen_staker = Unstaked_frozen_staker_repr.t = + | Single of Contract_repr.t * Signature.public_key_hash + | Shared of Signature.public_key_hash + + type frozen_staker = Frozen_staker_repr.t = private + | Baker of Signature.public_key_hash + | Single_staker of { + staker : Contract_repr.t; + delegate : Signature.public_key_hash; + } + | Shared_between_stakers of {delegate : Signature.public_key_hash} + | Baker_edge of Signature.public_key_hash + + let frozen_baker = Frozen_staker_repr.baker + + let frozen_baker_edge = Frozen_staker_repr.baker_edge + + let frozen_single_staker = Frozen_staker_repr.single_staker + + let frozen_shared_between_stakers = Frozen_staker_repr.shared_between_stakers + + include Receipt_repr +end + +module Consensus_key = Delegate_consensus_key +module Misbehaviour = Misbehaviour_repr + +module Delegate = struct + include Delegate_storage + include Delegate_missed_attestations_storage + include Delegate_slashed_deposits_storage + include Delegate_cycles + + let last_cycle_before_deactivation = + Delegate_activation_storage.last_cycle_before_deactivation + + let prepare_stake_distribution = Stake_storage.prepare_stake_distribution + + let check_not_tz4 = Contract_delegate_storage.check_not_tz4 + + let delegated_contracts = Contract_delegate_storage.delegated_contracts + + let deactivated = Delegate_activation_storage.is_inactive + + let is_forbidden_delegate = Forbidden_delegates_storage.is_forbidden + + let already_denounced = Already_denounced_storage.already_denounced + + module Consensus_key = Delegate_consensus_key + + module Rewards = struct + include Delegate_rewards + + module For_RPC = struct + include Delegate_rewards.For_RPC + include Adaptive_issuance_storage.For_RPC + end + + module Internal_for_tests = Adaptive_issuance_storage.Internal_for_tests + end + + module Staking_parameters = Delegate_staking_parameters + module Shared_stake = Shared_stake + + module For_RPC = struct + include Delegate_storage.For_RPC + include Delegate_slashed_deposits_storage.For_RPC + include Delegate_missed_attestations_storage.For_RPC + include Pending_denunciations_storage.For_RPC + + let pending_denunciations = Pending_denunciations_storage.find + + let has_pending_denunciations = + Pending_denunciations_storage.has_pending_denunciations + end +end + +module Stake_distribution = struct + let baking_rights_owner = Delegate_sampler.baking_rights_owner + + let slot_owner = Delegate_sampler.slot_owner + + let load_sampler_for_cycle = Delegate_sampler.load_sampler_for_cycle + + let get_total_frozen_stake ctxt cycle = + let open Lwt_result_syntax in + let* total_stake = Stake_storage.get_total_active_stake ctxt cycle in + return (Stake_repr.get_frozen total_stake) + + module For_RPC = Delegate_sampler.For_RPC + + module Internal_for_tests = struct + let get_selected_distribution = Stake_storage.get_selected_distribution + end +end + +module Staking = struct + include Staking + + let stake = stake ~for_next_cycle_use_only_after_slashing:false + + let request_unstake = + request_unstake ~for_next_cycle_use_only_after_slashing:false + + let finalize_unstake = + finalize_unstake ~for_next_cycle_use_only_after_slashing:false +end + +module Nonce = Nonce_storage + +module Seed = struct + include Seed_repr + include Seed_storage +end + +module Fitness = struct + type raw = Fitness.t + + include Fitness_repr +end + +module Bootstrap = Bootstrap_storage + +module Commitment = struct + include Commitment_repr + include Commitment_storage +end + +module Migration = Migration_repr + +module Consensus = struct + include Raw_context.Consensus + + let load_attestation_branch ctxt = + let open Lwt_result_syntax in + let* result = Storage.Tenderbake.Attestation_branch.find ctxt in + match result with + | Some attestation_branch -> + Raw_context.Consensus.set_attestation_branch ctxt attestation_branch + |> return + | None -> return ctxt + + let store_attestation_branch ctxt branch = + let ctxt = set_attestation_branch ctxt branch in + Storage.Tenderbake.Attestation_branch.add ctxt branch +end + +let prepare_first_block = Init_storage.prepare_first_block + +let prepare ctxt ~level ~predecessor_timestamp ~timestamp = + let open Lwt_result_syntax in + let* ctxt, balance_updates, origination_results = + Init_storage.prepare ctxt ~level ~predecessor_timestamp ~timestamp + in + let* ctxt = Consensus.load_attestation_branch ctxt in + let* ctxt = Forbidden_delegates_storage.load ctxt in + let* ctxt = Adaptive_issuance_storage.load_reward_coeff ctxt in + return (ctxt, balance_updates, origination_results) + +let finalize ?commit_message:message c fitness = + let context = Raw_context.recover c in + { + Updater.context; + fitness; + message; + max_operations_ttl = (Raw_context.constants c).max_operations_time_to_live; + last_finalized_block_level = + Raw_level.to_int32 (Level.last_finalized_block_level c); + last_preserved_block_level = + Raw_level.to_int32 (Level.last_preserved_block_level c); + } + +let current_context c = Raw_context.recover c + +let record_non_consensus_operation_hash = + Raw_context.record_non_consensus_operation_hash + +let non_consensus_operations = Raw_context.non_consensus_operations + +let record_dictator_proposal_seen = Raw_context.record_dictator_proposal_seen + +let dictator_proposal_seen = Raw_context.dictator_proposal_seen + +let activate = Raw_context.activate + +let reset_internal_nonce = Raw_context.reset_internal_nonce + +let fresh_internal_nonce = Raw_context.fresh_internal_nonce + +let record_internal_nonce = Raw_context.record_internal_nonce + +let internal_nonce_already_recorded = + Raw_context.internal_nonce_already_recorded + +let description = Raw_context.description + +module Parameters = Parameters_repr +module Votes_EMA = Votes_EMA_repr +module Per_block_votes = Per_block_votes_repr + +module Liquidity_baking = struct + include Liquidity_baking_storage +end + +module Adaptive_issuance = struct + include Adaptive_issuance_storage +end + +module Ticket_hash = struct + include Ticket_hash_repr + include Ticket_hash_builder +end + +module Ticket_balance = struct + include Ticket_storage +end + +module Token = Token +module Cache = Cache_repr + +module Unstake_requests = struct + include Unstake_requests_storage + + let prepare_finalize_unstake = + prepare_finalize_unstake ~for_next_cycle_use_only_after_slashing:false + + module For_RPC = struct + let apply_slash_to_unstaked_unfinalizable ctxt ~delegate ~requests = + Unstake_requests_storage.For_RPC.apply_slash_to_unstaked_unfinalizable + ctxt + {delegate; requests} + + let apply_slash_to_unstaked_unfinalizable_stored_requests ctxt + {delegate; requests} = + let open Lwt_result_syntax in + let* requests = + Unstake_requests_storage.For_RPC.apply_slash_to_unstaked_unfinalizable + ctxt + {delegate; requests} + in + return {delegate; requests} + end +end + +module Unstaked_frozen_deposits = Unstaked_frozen_deposits_storage + +module Staking_pseudotoken = struct + include Staking_pseudotoken_repr + module For_RPC = Staking_pseudotoken_repr + module Internal_for_tests = Staking_pseudotoken_repr +end + +module Staking_pseudotokens = struct + include Staking_pseudotokens_storage + module For_RPC = Staking_pseudotokens_storage.For_RPC +end + +module Internal_for_tests = struct + let to_raw x = x +end diff --git a/src/proto_020_PsParisC/lib_protocol/alpha_context.mli b/src/proto_020_PsParisC/lib_protocol/alpha_context.mli new file mode 100644 index 000000000000..e6ecfa1eec42 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/alpha_context.mli @@ -0,0 +1,5411 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** An [Alpha_context.t] is an immutable snapshot of the ledger state at some block + height, preserving + {{:https://tezos.gitlab.io/developer/entering_alpha.html#the-big-abstraction-barrier-alpha-context} + type-safety and invariants} of the ledger state. + + {2 Implementation} + + [Alpha_context.t] is a wrapper over [Raw_context.t], which in turn is a + wrapper around [Context.t] from the Protocol Environment. + + {2 Lifetime of an Alpha_context} + + - Creation, using [prepare] or [prepare_first_block] + + - Modification, using the operations defined in this signature + + - Finalization, using [finalize] + *) + +module type BASIC_DATA = sig + type t + + include Compare.S with type t := t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +type t + +type context = t + +type public_key = Signature.Public_key.t + +type public_key_hash = Signature.Public_key_hash.t + +type signature = Signature.t + +(** This module re-exports definitions from {!Slot_repr}. *) +module Slot : sig + type t + + type slot = t + + include Compare.S with type t := t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val succ : t -> t tzresult + + val to_int : t -> int + + val of_int_do_not_use_except_for_parameters : int -> t + + val encoding : t Data_encoding.encoding + + module Range : sig + type t + + val create : min:int -> count:int -> t tzresult + + val fold : ('a -> slot -> 'a) -> 'a -> t -> 'a + + val fold_es : + ('a -> slot -> 'a tzresult Lwt.t) -> 'a -> t -> 'a tzresult Lwt.t + + val rev_fold_es : + ('a -> slot -> 'a tzresult Lwt.t) -> 'a -> t -> 'a tzresult Lwt.t + end + + module Map : Map.S with type key = t + + module Set : Set.S with type elt = t + + module Internal_for_tests : sig + val of_int : int -> t tzresult + end +end + +(** This module re-exports definitions from {!Tez_repr}. *) +module Tez : sig + type repr + + type t = Tez_tag of repr [@@ocaml.unboxed] + + include BASIC_DATA with type t := t + + val zero : t + + val one_mutez : t + + val one_cent : t + + val fifty_cents : t + + val one : t + + val max_mutez : t + + val ( -? ) : t -> t -> t tzresult + + val sub_opt : t -> t -> t option + + val ( +? ) : t -> t -> t tzresult + + val ( *? ) : t -> int64 -> t tzresult + + val ( /? ) : t -> int64 -> t tzresult + + val of_string : string -> t option + + val to_string : t -> string + + val of_mutez : int64 -> t option + + val to_mutez : t -> int64 + + val of_mutez_exn : int64 -> t + + val mul_exn : t -> int -> t + + val div_exn : t -> int -> t +end + +(** This module re-exports definitions from {!Staking_pseudotoken_repr}. *) +module Staking_pseudotoken : sig + type t + + module For_RPC : sig + val encoding : t Data_encoding.encoding + end + + module Internal_for_tests : sig + val to_z : t -> Z.t + end +end + +(** This module re-exports definitions from {!Period_repr}. *) +module Period : sig + include BASIC_DATA + + type period = t + + val rpc_arg : period RPC_arg.arg + + val of_seconds : int64 -> period tzresult + + val of_seconds_exn : int64 -> period + + val to_seconds : period -> int64 + + val add : period -> period -> period tzresult + + val mult : int32 -> period -> period tzresult + + val zero : period + + val one_second : period + + val one_minute : period + + val one_hour : period + + val compare : period -> period -> int +end + +(** This module re-exports definitions from {!Time_repr}. *) +module Timestamp : sig + include BASIC_DATA with type t = Time.t + + type time = t + + val ( +? ) : time -> Period.t -> time tzresult + + val ( -? ) : time -> time -> Period.t tzresult + + val ( - ) : time -> Period.t -> time + + val of_notation : string -> time option + + val to_notation : time -> string + + val of_seconds : int64 -> time + + val to_seconds : time -> int64 + + val of_seconds_string : string -> time option + + val to_seconds_string : time -> string + + (** See {!Raw_context.current_timestamp}. *) + val current : context -> time + + (** See {!Raw_context.predecessor_timestamp}. *) + val predecessor : context -> time +end + +(** This module re-exports definitions from {!Ratio_repr}. *) +module Ratio : sig + type t = {numerator : int; denominator : int} + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +(** This module re-exports definitions from {!Raw_level_repr}. *) +module Raw_level : sig + include BASIC_DATA + + type raw_level = t + + val rpc_arg : raw_level RPC_arg.arg + + val diff : raw_level -> raw_level -> int32 + + val root : raw_level + + val succ : raw_level -> raw_level + + val pred : raw_level -> raw_level option + + val to_int32 : raw_level -> int32 + + val of_int32 : int32 -> raw_level tzresult + + val of_int32_exn : int32 -> raw_level + + module Set : Set.S with type elt = raw_level + + module Map : Map.S with type key = raw_level + + module Internal_for_tests : sig + val add : raw_level -> int -> raw_level + + val sub : raw_level -> int -> raw_level option + + val from_repr : Raw_level_repr.t -> raw_level + + val to_repr : raw_level -> Raw_level_repr.t + end +end + +(** This module re-exports definitions from {!Cycle_repr}. *) +module Cycle : sig + include BASIC_DATA + + type cycle = t + + val rpc_arg : cycle RPC_arg.arg + + val root : cycle + + val succ : cycle -> cycle + + val pred : cycle -> cycle option + + val add : cycle -> int -> cycle + + val sub : cycle -> int -> cycle option + + val to_int32 : cycle -> int32 + + val ( ---> ) : cycle -> cycle -> cycle list + + module Map : Map.S with type key = cycle +end + +(** This module re-exports definitions from {!Round_repr}. *) +module Round : sig + (* A round represents an iteration of the single-shot consensus algorithm. + This mostly simply re-exports [Round_repr]. See [Round_repr] for + additional documentation of this module *) + + type t + + val zero : t + + val succ : t -> t + + val pred : t -> t tzresult + + val to_int32 : t -> int32 + + val of_int32 : int32 -> t tzresult + + val of_int : int -> t tzresult + + val to_int : t -> int tzresult + + val to_slot : t -> committee_size:int -> Slot.t tzresult + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + + include Compare.S with type t := t + + module Map : Map.S with type key = t + + (** See {!Round_repr.Durations.t}. *) + type round_durations + + (** See {!Round_repr.Durations.pp}. *) + val pp_round_durations : Format.formatter -> round_durations -> unit + + (** See {!Round_repr.Durations.encoding}. *) + val round_durations_encoding : round_durations Data_encoding.t + + (** See {!Round_repr.Durations.round_duration}. *) + val round_duration : round_durations -> t -> Period.t + + module Durations : sig + val create : + first_round_duration:Period.t -> + delay_increment_per_round:Period.t -> + round_durations tzresult + + val create_opt : + first_round_duration:Period.t -> + delay_increment_per_round:Period.t -> + round_durations option + end + + val level_offset_of_round : round_durations -> round:t -> Period.t tzresult + + val timestamp_of_round : + round_durations -> + predecessor_timestamp:Time.t -> + predecessor_round:t -> + round:t -> + Time.t tzresult + + val timestamp_of_another_round_same_level : + round_durations -> + current_timestamp:Time.t -> + current_round:t -> + considered_round:t -> + Time.t tzresult + + val round_of_timestamp : + round_durations -> + predecessor_timestamp:Time.t -> + predecessor_round:t -> + timestamp:Time.t -> + t tzresult + + (* retrieve a round from the context *) + val get : context -> t tzresult Lwt.t + + (* store a round in context *) + val update : context -> t -> context tzresult Lwt.t + + module Internal_for_tests : sig + val from_repr : Round_repr.t -> t + + val to_repr : t -> Round_repr.t + end +end + +module Gas : sig + (** This module implements the gas subsystem of the context. + + Gas reflects the computational cost of each operation to limit + the cost of operations and, by extension, the cost of blocks. + + There are two gas quotas: one for operation and one for + block. For this reason, we maintain two gas levels -- one for + operations and another one for blocks -- that correspond to the + remaining amounts of gas, initialized with the quota + limits and decreased each time gas is consumed. + + *) + + module Arith : + Fixed_point_repr.Safe + with type 'a t = private Saturation_repr.may_saturate Saturation_repr.t + + (** For maintenance operations or for testing, gas can be + [Unaccounted]. Otherwise, the computation is [Limited] by the + [remaining] gas in the context. *) + type t = private Unaccounted | Limited of {remaining : Arith.fp} + + val encoding : t Data_encoding.encoding + + val pp : Format.formatter -> t -> unit + + (** [set_limit ctxt limit] returns a context with a given + [limit] level of gas allocated for an operation. *) + val set_limit : context -> 'a Arith.t -> context + + (** [set_unlimited] allows unlimited gas consumption. *) + val set_unlimited : context -> context + + (** [remaining_operation_gas ctxt] returns the current gas level in + the context [ctxt] for the current operation. If gas is + [Unaccounted], an arbitrary value will be returned. *) + val remaining_operation_gas : context -> Arith.fp + + (** [reset_block_gas ctxt] returns a context where the remaining gas + in the block is reset to the constant [hard_gas_limit_per_block], + i.e., as if no operations have been included in the block. + + /!\ Do not call this function unless you want to validate + operations on their own (like in the mempool). *) + val reset_block_gas : context -> context + + (** [level ctxt] is the current gas level in [ctxt] for the current + operation. *) + val level : context -> t + + (** [update_remaining_operation_gas ctxt remaining] sets the current + gas level for operations to [remaining]. *) + val update_remaining_operation_gas : context -> Arith.fp -> context + + (** [consumed since until] is the operation gas level difference + between context [since] and context [until]. This function + returns [Arith.zero] if any of the two contexts allows for an + unlimited gas consumption. This function also returns + [Arith.zero] if [since] has less gas than [until]. *) + val consumed : since:context -> until:context -> Arith.fp + + (** [block_level ctxt] returns the block gas level in context [ctxt]. *) + val block_level : context -> Arith.fp + + (** Costs are computed using a saturating arithmetic. See + {!Saturation_repr}. *) + type cost = Saturation_repr.may_saturate Saturation_repr.t + + val cost_encoding : cost Data_encoding.encoding + + val pp_cost : Format.formatter -> cost -> unit + + val pp_cost_as_gas : Format.formatter -> cost -> unit + + type error += Operation_quota_exceeded (* `Temporary *) + + (** [consume ctxt cost] subtracts [cost] to the current operation + gas level in [ctxt]. This operation may fail with + [Operation_quota_exceeded] if the operation gas level would + go below zero. *) + val consume : context -> cost -> context tzresult + + (** [consume_from available_gas cost] subtracts [cost] from + [available_gas] and returns the remaining gas. + + @return [Error Operation_quota_exceeded] if the remaining gas + would fall below [0]. *) + val consume_from : Arith.fp -> cost -> Arith.fp tzresult + + type error += Block_quota_exceeded (* `Temporary *) + + type error += Gas_limit_too_high (* `Permanent *) + + (** See {!Raw_context.consume_gas_limit_in_block}. *) + val consume_limit_in_block : context -> 'a Arith.t -> context tzresult + + (** Check that [gas_limit] is a valid operation gas limit: at most + [hard_gas_limit_per_operation] and nonnegative. + + @return [Error Gas_limit_too_high] if [gas_limit] is greater + than [hard_gas_limit_per_operation] or negative. *) + val check_gas_limit : + hard_gas_limit_per_operation:Arith.integral -> + gas_limit:Arith.integral -> + unit tzresult + + (** The cost of free operation is [0]. *) + val free : cost + + (** Convert a fixed-point amount of gas to a cost. *) + val cost_of_gas : 'a Arith.t -> cost + + (** Convert an amount of milligas expressed as an int to Arith.fp. *) + val fp_of_milligas_int : int -> Arith.fp + + (** [atomic_step_cost x] corresponds to [x] milliunit of gas. *) + val atomic_step_cost : _ Saturation_repr.t -> cost + + (** [step_cost x] corresponds to [x] units of gas. *) + val step_cost : _ Saturation_repr.t -> cost + + (** Cost of allocating qwords of storage. + [alloc_cost n] estimates the cost of allocating [n] qwords of storage. *) + val alloc_cost : _ Saturation_repr.t -> cost + + (** Cost of allocating bytes in the storage. + [alloc_bytes_cost b] estimates the cost of allocating [b] bytes of + storage. *) + val alloc_bytes_cost : int -> cost + + (** Cost of allocating bytes in the storage. + + [alloc_mbytes_cost b] estimates the cost of allocating [b] bytes of + storage and the cost of an header to describe these bytes. *) + val alloc_mbytes_cost : int -> cost + + (** Cost of reading the storage. + [read_bytes_cost n] estimates the cost of reading [n] bytes of storage. *) + val read_bytes_cost : int -> cost + + (** Cost of writing to storage. + [write_bytes_const n] estimates the cost of writing [n] bytes to the + storage. *) + val write_bytes_cost : int -> cost + + (** Multiply a cost by a factor. Both arguments are saturated arithmetic values, + so no negative numbers are involved. *) + val ( *@ ) : _ Saturation_repr.t -> cost -> cost + + (** Add two costs together. *) + val ( +@ ) : cost -> cost -> cost + + (** [cost_of_repr] is an internal operation needed to inject costs + for Storage_costs into Gas.cost. *) + val cost_of_repr : Gas_limit_repr.cost -> cost +end + +module Entrypoint : module type of Entrypoint_repr + +(** This module re-exports definitions from {!Script_repr} and + {!Michelson_v1_primitives}. *) +module Script : sig + type error += Lazy_script_decode + + type prim = Michelson_v1_primitives.prim = + | K_parameter + | K_storage + | K_code + | K_view + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | D_Ticket + | D_Lambda_rec + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_VIEW + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LAMBDA_REC + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_MIN_BLOCK_TIME + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SELF_ADDRESS + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SUB_MUTEZ + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE + | I_XOR + | I_ITER + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_DIG + | I_DUG + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_TICKET_DEPRECATED + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | I_OPEN_CHEST + | I_EMIT + | I_BYTES + | I_NAT + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_tx_rollup_l2_address + | T_sapling_transaction + | T_sapling_transaction_deprecated + | T_sapling_state + | T_chain_id + | T_never + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + | T_chest_key + | T_chest + | H_constant + + type location = Micheline.canonical_location + + type annot = Micheline.annot + + type expr = prim Micheline.canonical + + type lazy_expr = expr Data_encoding.lazy_t + + val lazy_expr : expr -> lazy_expr + + type 'location michelson_node = ('location, prim) Micheline.node + + type node = location michelson_node + + type t = {code : lazy_expr; storage : lazy_expr} + + val location_encoding : location Data_encoding.t + + val expr_encoding : expr Data_encoding.t + + val prim_encoding : prim Data_encoding.t + + val encoding : t Data_encoding.t + + val lazy_expr_encoding : lazy_expr Data_encoding.t + + val deserialization_cost_estimated_from_bytes : int -> Gas.cost + + val deserialized_cost : expr -> Gas.cost + + val micheline_serialization_cost : expr -> Gas.cost + + val bytes_node_cost : bytes -> Gas.cost + + (** Mode of deserialization gas consumption in {!force_decode}: + + - {!Always}: the gas is taken independently of the internal state of the + [lazy_expr] + - {!When_needed}: the gas is consumed only if the [lazy_expr] has never + been deserialized before. *) + type consume_deserialization_gas = Always | When_needed + + (** Decode an expression in the context after consuming the deserialization + gas cost (see {!consume_deserialization_gas}). *) + val force_decode_in_context : + consume_deserialization_gas:consume_deserialization_gas -> + context -> + lazy_expr -> + (expr * context) tzresult + + (** Decode an expression in the context after consuming the deserialization + gas cost. *) + val force_bytes_in_context : + context -> lazy_expr -> (bytes * context) tzresult + + (** [consume_decoding_gas available_gas lexpr] subtracts (a lower + bound on) the cost to deserialize [lexpr] from [available_gas]. + The cost does not depend on the internal state of the lazy_expr. + + @return [Error Operation_quota_exceeded] if the remaining gas + would fall below [0]. + + This mimics the gas consuming part of {!force_decode_in_context} + called with [consume_deserialization_gas:Always]. *) + val consume_decoding_gas : Gas.Arith.fp -> lazy_expr -> Gas.Arith.fp tzresult + + val unit_parameter : lazy_expr + + val is_unit : expr -> bool + + val strip_locations_cost : _ michelson_node -> Gas.cost + + val strip_annotations_cost : node -> Gas.cost + + val strip_annotations : node -> node +end + +(** This module re-exports definitions from {!Constants_repr} and + {!Constants_storage}. *) +module Constants : sig + (** Fixed constants *) + type fixed + + val fixed_encoding : fixed Data_encoding.t + + val mainnet_id : Chain_id.t + + val proof_of_work_nonce_size : int + + val nonce_length : int + + val max_anon_ops_per_block : int + + val max_operation_data_length : int + + val max_proposals_per_delegate : int + + val michelson_maximum_type_size : int + + val max_slashing_period : int + + val sc_rollup_message_size_limit : int + + val sc_rollup_max_number_of_messages_per_level : Z.t + + (** Constants parameterized by context. See {!Constants_parametric_repr}. *) + module Parametric : sig + type dal = { + feature_enable : bool; + incentives_enable : bool; + number_of_slots : int; + attestation_lag : int; + attestation_threshold : int; + cryptobox_parameters : Dal.parameters; + } + + val dal_encoding : dal Data_encoding.t + + type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level.t} + + type sc_rollup_reveal_activation_level = { + raw_data : sc_rollup_reveal_hashing_schemes; + metadata : Raw_level.t; + dal_page : Raw_level.t; + dal_parameters : Raw_level.t; + dal_attested_slots_validity_lag : int; + } + + type sc_rollup = { + arith_pvm_enable : bool; + origination_size : int; + challenge_window_in_blocks : int; + stake_amount : Tez.t; + commitment_period_in_blocks : int; + max_lookahead_in_blocks : int32; + max_active_outbox_levels : int32; + max_outbox_messages_per_level : int; + number_of_sections_in_dissection : int; + timeout_period_in_blocks : int; + max_number_of_stored_cemented_commitments : int; + max_number_of_parallel_games : int; + reveal_activation_level : sc_rollup_reveal_activation_level; + private_enable : bool; + riscv_pvm_enable : bool; + } + + type zk_rollup = { + enable : bool; + origination_size : int; + min_pending_to_process : int; + max_ticket_payload_size : int; + } + + type adaptive_rewards_params = { + issuance_ratio_final_min : Q.t; + issuance_ratio_final_max : Q.t; + issuance_ratio_initial_min : Q.t; + issuance_ratio_initial_max : Q.t; + initial_period : int; + transition_period : int; + max_bonus : Issuance_bonus_repr.max_bonus; + growth_rate : Q.t; + center_dz : Q.t; + radius_dz : Q.t; + } + + type adaptive_issuance = { + global_limit_of_staking_over_baking : int; + edge_of_staking_over_delegation : int; + launch_ema_threshold : int32; + adaptive_rewards_params : adaptive_rewards_params; + activation_vote_enable : bool; + autostaking_enable : bool; + force_activation : bool; + ns_enable : bool; + } + + type issuance_weights = { + base_total_issued_per_minute : Tez.t; + baking_reward_fixed_portion_weight : int; + baking_reward_bonus_weight : int; + attesting_reward_weight : int; + seed_nonce_revelation_tip_weight : int; + vdf_revelation_tip_weight : int; + } + + type t = { + consensus_rights_delay : int; + blocks_preservation_cycles : int; + delegate_parameters_activation_delay : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + nonce_revelation_threshold : int32; + cycles_per_voting_period : int32; + hard_gas_limit_per_operation : Gas.Arith.integral; + hard_gas_limit_per_block : Gas.Arith.integral; + proof_of_work_threshold : int64; + minimal_stake : Tez.t; + minimal_frozen_stake : Tez.t; + vdf_difficulty : int64; + origination_size : int; + issuance_weights : issuance_weights; + cost_per_byte : Tez.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + quorum_max : int32; + min_proposal_quorum : int32; + liquidity_baking_subsidy : Tez.t; + liquidity_baking_toggle_ema_threshold : int32; + max_operations_time_to_live : int; + minimal_block_delay : Period.t; + delay_increment_per_round : Period.t; + minimal_participation_ratio : Ratio.t; + consensus_committee_size : int; + consensus_threshold : int; + limit_of_delegation_over_baking : int; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : + Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; + testnet_dictator : public_key_hash option; + initial_seed : State_hash.t option; + cache_script_size : int; + cache_stake_distribution_cycles : int; + cache_sampler_state_cycles : int; + dal : dal; + sc_rollup : sc_rollup; + zk_rollup : zk_rollup; + adaptive_issuance : adaptive_issuance; + direct_ticket_spending_enable : bool; + } + + val encoding : t Data_encoding.t + + val update_sc_rollup_parameter : block_time:int -> sc_rollup -> sc_rollup + + module Internal_for_tests : sig + val sc_rollup_encoding : sc_rollup Data_encoding.t + end + end + + module Generated : sig + type t = { + consensus_threshold : int; + issuance_weights : Parametric.issuance_weights; + max_slashing_threshold : int; + } + + val generate : consensus_committee_size:int -> t + end + + val parametric : context -> Parametric.t + + val sc_rollup : context -> Parametric.sc_rollup + + val consensus_rights_delay : context -> int + + val blocks_preservation_cycles : context -> int + + val delegate_parameters_activation_delay : context -> int + + val slashable_deposits_period : context -> int + + val issuance_modification_delay : context -> int + + val blocks_per_cycle : context -> int32 + + val blocks_per_commitment : context -> int32 + + val nonce_revelation_threshold : context -> int32 + + val cycles_per_voting_period : context -> int32 + + val hard_gas_limit_per_operation : context -> Gas.Arith.integral + + val hard_gas_limit_per_block : context -> Gas.Arith.integral + + val cost_per_byte : context -> Tez.t + + val hard_storage_limit_per_operation : context -> Z.t + + val proof_of_work_threshold : context -> int64 + + val minimal_stake : context -> Tez.t + + val minimal_frozen_stake : context -> Tez.t + + val vdf_difficulty : context -> int64 + + val origination_size : context -> int + + val issuance_weights : context -> Parametric.issuance_weights + + val quorum_min : context -> int32 + + val quorum_max : context -> int32 + + val min_proposal_quorum : context -> int32 + + val liquidity_baking_toggle_ema_threshold : context -> int32 + + val minimal_block_delay : context -> Period.t + + val delay_increment_per_round : context -> Period.t + + (** See {!Raw_context.round_durations}. *) + val round_durations : context -> Round.round_durations + + val consensus_committee_size : context -> int + + val consensus_threshold : context -> int + + val minimal_participation_ratio : context -> Ratio.t + + val limit_of_delegation_over_baking : context -> int + + val percentage_of_frozen_deposits_slashed_per_double_baking : + context -> Percentage.t + + val percentage_of_frozen_deposits_slashed_per_double_attestation : + context -> Percentage.t + + val testnet_dictator : context -> public_key_hash option + + val sc_rollup_arith_pvm_enable : context -> bool + + val sc_rollup_riscv_pvm_enable : context -> bool + + val dal_enable : context -> bool + + val sc_rollup_origination_size : context -> int + + val sc_rollup_stake_amount : t -> Tez.t + + val sc_rollup_commitment_period_in_blocks : t -> int + + val sc_rollup_max_lookahead_in_blocks : t -> int32 + + val sc_rollup_max_active_outbox_levels : context -> int32 + + val sc_rollup_max_outbox_messages_per_level : context -> int + + val sc_rollup_number_of_sections_in_dissection : context -> int + + val max_number_of_stored_cemented_commitments : context -> int + + val sc_rollup_reveal_activation_level : + context -> Parametric.sc_rollup_reveal_activation_level + + val sc_rollup_private_enable : context -> bool + + val zk_rollup_enable : context -> bool + + val zk_rollup_min_pending_to_process : context -> int + + val adaptive_issuance_enable : context -> bool + + val zk_rollup_max_ticket_payload_size : context -> int + + val direct_ticket_spending_enable : context -> bool + + (** All constants: fixed and parametric *) + type t = private {fixed : fixed; parametric : Parametric.t} + + val all : context -> t + + val encoding : t Data_encoding.t +end + +(** See the definitions inside the module. *) +module Global_constants_storage : sig + type error += Expression_too_deep + + type error += Expression_already_registered + + (** A constant is the prim of the literal characters "constant". + A constant must have a single argument, being a string with a + well formed hash of a Micheline expression (i.e generated by + [Script_expr_hash.to_b58check]). *) + type error += Badly_formed_constant_expression + + type error += Nonexistent_global + + (** [get context hash] retrieves the Micheline value with the given hash. + + Fails with [Nonexistent_global] if no value is found at the given hash. + + Fails with [Storage_error Corrupted_data] if the deserialisation fails. + + Consumes [Gas_repr.read_bytes_cost ]. *) + val get : t -> Script_expr_hash.t -> (t * Script.expr) tzresult Lwt.t + + (** [register context value] Register a constant in the global table of constants, + returning the hash and storage bytes consumed. + + Does not type-check the Micheline code being registered, allow potentially + ill-typed Michelson values (see note at top of module in global_constants_storage.mli). + + The constant is stored unexpanded, but it is temporarily expanded at registration + time only to check the expanded version respects the following limits. + + Fails with [Expression_too_deep] if, after fully, expanding all constants, + the expression would contain too many nested levels, that is more than + [Constants_repr.max_allowed_global_constant_depth]. + + Fails with [Badly_formed_constant_expression] if constants are not + well-formed (see declaration of [Badly_formed_constant_expression]) or with + [Nonexistent_global] if a referenced constant does not exist in the table. + + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ] where size is the number + of bytes in the binary serialization provided by [Script.expr_encoding].*) + val register : + t -> Script.expr -> (t * Script_expr_hash.t * Z.t) tzresult Lwt.t + + (** [expand context expr] Replaces every constant in the + given Michelson expression with its value stored in the global table. + + The expansion is applied recursively so that the returned expression + contains no constant. + + Fails with [Badly_formed_constant_expression] if constants are not + well-formed (see declaration of [Badly_formed_constant_expression]) or + with [Nonexistent_global] if a referenced constant does not exist in + the table. *) + val expand : t -> Script.expr -> (t * Script.expr) tzresult Lwt.t + + (** This module discloses definitions that are only useful for tests and must + not be used otherwise. *) + module Internal_for_tests : sig + (** [node_too_large node] returns true if: + - The number of sub-nodes in the [node] + exceeds [Global_constants_storage.node_size_limit]. + - The sum of the bytes in String, Int, + and Bytes sub-nodes of [node] exceeds + [Global_constants_storage.bytes_size_limit]. + + Otherwise returns false. *) + val node_too_large : Script.node -> bool + + (** [bottom_up_fold_cps initial_accumulator node initial_k f] + folds [node] and all its sub-nodes if any, starting from + [initial_accumulator], using an initial continuation [initial_k]. + At each node, [f] is called to transform the continuation [k] into + the next one. This explicit manipulation of the continuation + is typically useful to short-circuit. + + Notice that a common source of bug is to forget to properly call the + continuation in `f`. *) + val bottom_up_fold_cps : + 'accumulator -> + 'loc Script.michelson_node -> + ('accumulator -> 'loc Script.michelson_node -> 'return) -> + ('accumulator -> + 'loc Script.michelson_node -> + ('accumulator -> 'loc Script.michelson_node -> 'return) -> + 'return) -> + 'return + + (** [expr_to_address_in_context context expr] converts [expr] + into a unique hash represented by a [Script_expr_hash.t]. + + Consumes gas corresponding to the cost of converting [expr] + to bytes and hashing the bytes. *) + val expr_to_address_in_context : + t -> Script.expr -> (t * Script_expr_hash.t) tzresult + end +end + +(** This module discloses definitions that are only useful for tests and must + not be used otherwise. *) +module Internal_for_tests : sig + val to_raw : context -> Raw_context.t +end + +(** This module re-exports definitions from {!Level_repr} and + {!Level_storage}. *) +module Level : sig + type t = private { + level : Raw_level.t; + level_position : int32; + cycle : Cycle.t; + cycle_position : int32; + expected_commitment : bool; + } + + include BASIC_DATA with type t := t + + val pp_full : Format.formatter -> t -> unit + + type level = t + + val root : context -> level + + val succ : context -> level -> level + + val pred : context -> level -> level option + + val from_raw : context -> Raw_level.t -> level + + (** Fails with [Negative_level_and_offset_sum] if the sum of the raw_level and the offset is negative. *) + val from_raw_with_offset : + context -> offset:int32 -> Raw_level.t -> level tzresult + + (** [add c level i] i must be positive *) + val add : context -> level -> int -> level + + (** [sub c level i] i must be positive *) + val sub : context -> level -> int -> level option + + val diff : level -> level -> int32 + + val current : context -> level + + val last_level_in_cycle : context -> Cycle.t -> level + + val levels_in_cycle : context -> Cycle.t -> level list + + val levels_in_current_cycle : context -> ?offset:int32 -> unit -> level list + + val last_preserved_block_level : context -> Raw_level.t + + val dawn_of_a_new_cycle : context -> Cycle.t option + + val may_compute_randao : context -> bool +end + +(** This module re-exports definitions from {!Fitness_repr}. *) +module Fitness : sig + type error += Invalid_fitness | Wrong_fitness | Outdated_fitness + + type raw = Fitness.t + + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val create : + level:Raw_level.t -> + locked_round:Round.t option -> + predecessor_round:Round.t -> + round:Round.t -> + t tzresult + + val create_without_locked_round : + level:Raw_level.t -> predecessor_round:Round.t -> round:Round.t -> t + + val to_raw : t -> raw + + val from_raw : raw -> t tzresult + + val round_from_raw : raw -> Round.t tzresult + + val predecessor_round_from_raw : raw -> Round.t tzresult + + (** See {!Fitness_repr.locked_round_from_raw}. *) + val locked_round_from_raw : raw -> Round.t option tzresult + + val level : t -> Raw_level.t + + val round : t -> Round.t + + val locked_round : t -> Round.t option + + val predecessor_round : t -> Round.t +end + +(** This module re-exports definitions from {!Nonce_storage}. *) +module Nonce : sig + type t + + type nonce = t + + val encoding : nonce Data_encoding.t + + type unrevealed = {nonce_hash : Nonce_hash.t; delegate : public_key_hash} + + val record_hash : context -> unrevealed -> context tzresult Lwt.t + + (** See {!Nonce_storage.check_unrevealed}. *) + val check_unrevealed : context -> Level.t -> nonce -> unit tzresult Lwt.t + + val reveal : context -> Level.t -> nonce -> context tzresult Lwt.t + + type status = Unrevealed of unrevealed | Revealed of nonce + + val get : context -> Level.t -> status tzresult Lwt.t + + val of_bytes : bytes -> nonce tzresult + + val hash : nonce -> Nonce_hash.t + + val check_hash : nonce -> Nonce_hash.t -> bool +end + +(** This module re-exports definitions from {!Seed_repr} and {!Seed_storage}. *) +module Seed : sig + type seed + + val seed_encoding : seed Data_encoding.t + + type vdf_solution = Vdf.result * Vdf.proof + + val vdf_solution_encoding : vdf_solution Data_encoding.t + + val pp_solution : Format.formatter -> vdf_solution -> unit + + type vdf_setup = Vdf.discriminant * Vdf.challenge + + type error += + | Unknown of {oldest : Cycle.t; cycle : Cycle.t; latest : Cycle.t} + | Already_accepted + | Unverified_vdf + | Too_early_revelation + + val generate_vdf_setup : + seed_discriminant:seed -> seed_challenge:seed -> vdf_setup + + (** See {!Seed_storage.check_vdf}. *) + val check_vdf : context -> vdf_solution -> unit tzresult Lwt.t + + (** See {!Seed_storage.update_seed}. *) + val update_seed : context -> vdf_solution -> context tzresult Lwt.t + + (** See {!Seed_repr.compare_vdf_solution}. *) + val compare_vdf_solution : vdf_solution -> vdf_solution -> int + + val compute_randao : context -> context tzresult Lwt.t + + (* RPC *) + type seed_computation_status = + | Nonce_revelation_stage + | Vdf_revelation_stage of {seed_discriminant : seed; seed_challenge : seed} + | Computation_finished + + val for_cycle : context -> Cycle.t -> seed tzresult Lwt.t + + val get_seed_computation_status : + context -> seed_computation_status tzresult Lwt.t +end + +(** Big maps are a data structure storing key-value associations, just like + regular maps, but here the whole content of the structure is not loaded in + memory when interacting with it. + They are thus suitable for a Michelson contract, for instance, when there are a + lot of bindings, but only a few items are accessed at each contract call. *) +module Big_map : sig + (** A big map is referenced in the storage by its identifier. *) + module Id : sig + type t = Lazy_storage_kind.Big_map.Id.t + + val encoding : t Data_encoding.t + + (** Big map argument for a RPC call. *) + val rpc_arg : t RPC_arg.arg + + (** In the protocol, to be used in parse_data only *) + val parse_z : Z.t -> t + + (** In the protocol, to be used in unparse_data only *) + val unparse_to_z : t -> Z.t + end + + (** Create a fresh big map in the context. *) + val fresh : temporary:bool -> context -> (context * Id.t) tzresult Lwt.t + + (** Carbonated membership of a key (from its hash) in a big map. *) + val mem : + context -> Id.t -> Script_expr_hash.t -> (context * bool) tzresult Lwt.t + + (** Carbonated retrieval of the value associated to a key (from its hash) in + a big map, if any. *) + val get_opt : + context -> + Id.t -> + Script_expr_hash.t -> + (context * Script.expr option) tzresult Lwt.t + + (** Carbonated retrieval of the key and value types of the bindings in a big + map referenced by its identifier, if this identifier is actually bound to a big map in the context. *) + val exists : + context -> + Id.t -> + (context * (Script.expr * Script.expr) option) tzresult Lwt.t + + (** [list_key_values ?offset ?length ctxt id] lists the key hash and value for + each entry in big map [id]. The first [offset] values are ignored (if + passed). Negative offsets are treated as [0]. There will be no more than + [length] values in the result list (if passed). Negative values are + treated as [0]. + + The returned {!context} takes into account gas consumption of traversing + the keys and loading values. *) + val list_key_values : + ?offset:int -> + ?length:int -> + context -> + Id.t -> + (context * (Script_expr_hash.t * Script.expr) list) tzresult Lwt.t + + (** The type of big map updates. When [value = None], the potential binding + associated to the [key] will be removed. *) + type update = { + key : Script_repr.expr; + (** The key is ignored by an update but is shown in the receipt. *) + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = update list + + (** The types of keys and values in a big map. *) + type alloc = {key_type : Script_repr.expr; value_type : Script_repr.expr} +end + +(** This module re-exports definitions from {!Sapling_repr}, {!Sapling_storage} + and {!Sapling_validator}. *) +module Sapling : sig + (** See {!Sapling_state.Id}. *) + module Id : sig + type t + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + val parse_z : Z.t -> t (* To be used in parse_data only *) + + val unparse_to_z : t -> Z.t (* To be used in unparse_data only *) + end + + (** Create a fresh sapling state in the context. *) + val fresh : temporary:bool -> context -> (context * Id.t) tzresult Lwt.t + + type diff = private { + commitments_and_ciphertexts : + (Sapling.Commitment.t * Sapling.Ciphertext.t) list; + nullifiers : Sapling.Nullifier.t list; + } + + val diff_encoding : diff Data_encoding.t + + module Memo_size : sig + type t + + val encoding : t Data_encoding.t + + val equal : t -> t -> bool + + val parse_z : Z.t -> (t, string) result + + val unparse_to_z : t -> Z.t + + val in_memory_size : t -> Cache_memory_helpers.sint + end + + type state = private {id : Id.t option; diff : diff; memo_size : Memo_size.t} + + (** + Returns a [state] with fields filled accordingly. + [id] should only be used by [extract_lazy_storage_updates]. + *) + val empty_state : ?id:Id.t -> memo_size:Memo_size.t -> unit -> state + + type transaction = Sapling.UTXO.transaction + + val transaction_encoding : transaction Data_encoding.t + + val transaction_get_memo_size : transaction -> Memo_size.t option + + (** + Tries to fetch a state from the storage. + *) + val state_from_id : context -> Id.t -> (state * context) tzresult Lwt.t + + val rpc_arg : Id.t RPC_arg.t + + type root = Sapling.Hash.t + + val root_encoding : root Data_encoding.t + + (* Function exposed as RPC. Returns the root and a diff of a state starting + from an optional offset which is zero by default. *) + val get_diff : + context -> + Id.t -> + ?offset_commitment:Int64.t -> + ?offset_nullifier:Int64.t -> + unit -> + (root * diff) tzresult Lwt.t + + val verify_update : + context -> + state -> + transaction -> + string -> + (context * (Int64.t * state) option) tzresult Lwt.t + + (** See {!Lazy_storage_kind.Sapling_state.alloc}. *) + type alloc = {memo_size : Memo_size.t} + + type updates = diff + + val transaction_in_memory_size : transaction -> Cache_memory_helpers.sint + + val diff_in_memory_size : diff -> Cache_memory_helpers.sint + + module Legacy : sig + type transaction = Sapling.UTXO.Legacy.transaction + + val transaction_encoding : transaction Data_encoding.t + + val transaction_get_memo_size : transaction -> Memo_size.t option + + val transaction_in_memory_size : + transaction -> Saturation_repr.may_saturate Saturation_repr.t + + val verify_update : + context -> + state -> + transaction -> + string -> + (context * (Int64.t * state) option) tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Lazy_storage_diff}. *) +module Lazy_storage : sig + (** This module re-exports definitions from {!Lazy_storage_kind}. *) + module Kind : sig + type ('id, 'alloc, 'updates) t = + | Big_map : (Big_map.Id.t, Big_map.alloc, Big_map.updates) t + | Sapling_state : (Sapling.Id.t, Sapling.alloc, Sapling.updates) t + end + + (** This module re-exports definitions from {!Lazy_storage_kind.IdSet}. *) + module IdSet : sig + type t + + type 'acc fold_f = {f : 'i 'a 'u. ('i, 'a, 'u) Kind.t -> 'i -> 'acc -> 'acc} + + val empty : t + + val mem : ('i, 'a, 'u) Kind.t -> 'i -> t -> bool + + val add : ('i, 'a, 'u) Kind.t -> 'i -> t -> t + + val diff : t -> t -> t + + val fold : ('i, 'a, 'u) Kind.t -> ('i -> 'acc -> 'acc) -> t -> 'acc -> 'acc + + val fold_all : 'acc fold_f -> t -> 'acc -> 'acc + end + + type ('id, 'alloc) init = Existing | Copy of {src : 'id} | Alloc of 'alloc + + type ('id, 'alloc, 'updates) diff = + | Remove + | Update of {init : ('id, 'alloc) init; updates : 'updates} + + type diffs_item = private + | Item : + ('i, 'a, 'u) Lazy_storage_kind.t * 'i * ('i, 'a, 'u) diff + -> diffs_item + + val make : ('i, 'a, 'u) Kind.t -> 'i -> ('i, 'a, 'u) diff -> diffs_item + + type diffs = diffs_item list + + val encoding : diffs Data_encoding.t + + val diffs_in_memory_size : diffs -> Cache_memory_helpers.nodes_and_size + + val cleanup_temporaries : context -> context Lwt.t + + val apply : t -> diffs -> (t * Z.t) tzresult Lwt.t +end + +(** See the definitions inside the module. *) +module Origination_nonce : sig + (** See {!Raw_context.init_origination_nonce}. *) + val init : context -> Operation_hash.t -> context + + (** See {!Raw_context.unset_origination_nonce}. *) + val unset : context -> context + + (** This module discloses definitions that are only useful for tests and must + not be used otherwise. See {!Origination_nonce}. *) + module Internal_for_tests : sig + type t + + val initial : Operation_hash.t -> t + + val incr : t -> t + end +end + +(** This module re-exports definitions from {!Ticket_hash_repr}. *) +module Ticket_hash : sig + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val of_script_expr_hash : Script_expr_hash.t -> t + + val to_b58check : t -> string + + val of_b58check_opt : string -> t option + + val of_b58check_exn : string -> t + + val of_bytes_exn : bytes -> t + + val of_bytes_opt : bytes -> t option + + val equal : t -> t -> bool + + val compare : t -> t -> int + + val make : + context -> + ticketer:Script.node -> + ty:Script.node -> + contents:Script.node -> + owner:Script.node -> + (t * context) tzresult + + (** This module discloses definitions that are only useful for tests and must + not be used otherwise. *) + module Internal_for_tests : sig + val make_uncarbonated : + ticketer:Script.node -> + ty:Script.node -> + contents:Script.node -> + owner:Script.node -> + t tzresult + end +end + +(** This module re-exports definitions from {!Manager_counter_repr}. *) +module Manager_counter : sig + include Compare.S + + val succ : t -> t + + val pp : Format.formatter -> t -> unit + + val encoding_for_RPCs : t Data_encoding.t + + module Internal_for_injection : sig + val of_string : string -> t option + end + + module Internal_for_tests : sig + val of_int : int -> t + + val to_int : t -> int + + val add : t -> int -> t + end +end + +(** This module re-exports definitions from {!Contract_repr} and + {!Contract_storage}. *) +module Contract : sig + type t = Implicit of public_key_hash | Originated of Contract_hash.t + + (** Functions related to contracts address. *) + + type error += Non_existing_contract of t + + include BASIC_DATA with type t := t + + val implicit_encoding : public_key_hash Data_encoding.t + + val originated_encoding : Contract_hash.t Data_encoding.t + + val in_memory_size : t -> Cache_memory_helpers.sint + + val rpc_arg : t RPC_arg.arg + + val to_b58check : t -> string + + val of_b58check : string -> t tzresult + + (** Functions related to contracts existence. *) + + val exists : context -> t -> bool Lwt.t + + val must_exist : context -> t -> unit tzresult Lwt.t + + val allocated : context -> t -> bool Lwt.t + + val must_be_allocated : context -> t -> unit tzresult Lwt.t + + val list : context -> t list Lwt.t + + (** Functions related to both implicit accounts and originated contracts. *) + + (** See {!Contract_storage.get_balance}. *) + val get_balance : context -> t -> Tez.t tzresult Lwt.t + + val get_balance_carbonated : context -> t -> (context * Tez.t) tzresult Lwt.t + + val get_frozen_bonds : context -> t -> Tez.t tzresult Lwt.t + + val get_balance_and_frozen_bonds : context -> t -> Tez.t tzresult Lwt.t + + (** Functions related to implicit accounts. *) + + (** See {!Contract_manager_storage.get_manager_key}. *) + val get_manager_key : + ?error:error -> context -> public_key_hash -> public_key tzresult Lwt.t + + (** See {!Contract_manager_storage.is_manager_key_revealed}. *) + val is_manager_key_revealed : + context -> public_key_hash -> bool tzresult Lwt.t + + (** See {!Contract_manager_storage.check_public_key}. *) + val check_public_key : public_key -> public_key_hash -> unit tzresult + + (** See {!Contract_manager_storage.reveal_manager_key}. *) + val reveal_manager_key : + ?check_consistency:bool -> + context -> + public_key_hash -> + public_key -> + context tzresult Lwt.t + + val get_counter : + context -> public_key_hash -> Manager_counter.t tzresult Lwt.t + + val increment_counter : context -> public_key_hash -> context tzresult Lwt.t + + val check_counter_increment : + context -> public_key_hash -> Manager_counter.t -> unit tzresult Lwt.t + + (** See {!Contract_storage.check_allocated_and_get_balance}. *) + val check_allocated_and_get_balance : + context -> public_key_hash -> Tez.t tzresult Lwt.t + + (** See {!Contract_storage.simulate_spending}. *) + val simulate_spending : + context -> + balance:Tez.t -> + amount:Tez.t -> + public_key_hash -> + (Tez.t * bool) tzresult Lwt.t + + (** Functions related to smart contracts. *) + + val get_script_code : + context -> + Contract_hash.t -> + (context * Script.lazy_expr option) tzresult Lwt.t + + val get_script : + context -> Contract_hash.t -> (context * Script.t option) tzresult Lwt.t + + val get_storage : + context -> Contract_hash.t -> (context * Script.expr option) tzresult Lwt.t + + val used_storage_space : context -> t -> Z.t tzresult Lwt.t + + val paid_storage_space : context -> t -> Z.t tzresult Lwt.t + + val increase_paid_storage : + context -> Contract_hash.t -> amount_in_bytes:Z.t -> context tzresult Lwt.t + + val fresh_contract_from_current_nonce : + context -> (context * Contract_hash.t) tzresult + + val originated_from_current_nonce : + since:context -> until:context -> Contract_hash.t list tzresult Lwt.t + + val update_script_storage : + context -> + Contract_hash.t -> + Script.expr -> + Lazy_storage.diffs option -> + context tzresult Lwt.t + + val raw_originate : + context -> + prepaid_bootstrap_storage:bool -> + Contract_hash.t -> + script:Script.t * Lazy_storage.diffs option -> + context tzresult Lwt.t + + (** See {!Contract_delegate_storage.is_delegate}. *) + val is_delegate : context -> public_key_hash -> bool tzresult Lwt.t + + (** See {!Contract_delegate_storage.delegate_status}. *) + type delegate_status = + | Delegate + | Delegated of Signature.Public_key_hash.t + | Undelegated + + (** See {!Contract_delegate_storage.get_delegate_status}. *) + val get_delegate_status : + context -> public_key_hash -> delegate_status tzresult Lwt.t + + val get_total_supply : context -> Tez.t tzresult Lwt.t + + module Legacy_big_map_diff : sig + type item = private + | Update of { + big_map : Z.t; + diff_key : Script.expr; + diff_key_hash : Script_expr_hash.t; + diff_value : Script.expr option; + } + | Clear of Z.t + | Copy of {src : Z.t; dst : Z.t} + | Alloc of { + big_map : Z.t; + key_type : Script.expr; + value_type : Script.expr; + } + + type t = private item list + + val of_lazy_storage_diff : Lazy_storage.diffs -> t + end + + (** Functions for handling the delegate of a contract.*) + module Delegate : sig + (** See {!Contract_delegate_storage.find}. *) + val find : context -> t -> public_key_hash option tzresult Lwt.t + + (** See {!Delegate_storage.Contract.init}. *) + val init : context -> t -> public_key_hash -> context tzresult Lwt.t + + (** See {!Delegate_storage.Contract.set}. *) + val set : context -> t -> public_key_hash option -> context tzresult Lwt.t + end + + (** This module discloses definitions that are only useful for tests and must + not be used otherwise. *) + module Internal_for_tests : sig + (** See {!Contract_repr.originated_contract}. *) + val originated_contract : Origination_nonce.Internal_for_tests.t -> t + + val paid_storage_space : context -> t -> Z.t tzresult Lwt.t + end + + (** Functions used exclusively for RPC calls *) + module For_RPC : sig + val get_staked_balance : context -> t -> Tez.t option tzresult Lwt.t + + val get_unstaked_frozen_balance : + context -> t -> Tez.t option tzresult Lwt.t + + val get_unstaked_finalizable_balance : + context -> t -> Tez.t option tzresult Lwt.t + + val get_full_balance : context -> t -> Tez.t tzresult Lwt.t + + (** [get_estimated_own_pending_slashed_amount ctxt contract] + returns the estimated own pending slashed amount of the given [contract] + according to the currently available denunciations. *) + val get_estimated_own_pending_slashed_amount : + context -> t -> Tez.t tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Bond_id_repr}. *) +module Bond_id : sig + type t = Sc_rollup_bond_id of Smart_rollup.Address.t + + val pp : Format.formatter -> t -> unit + + val compare : t -> t -> int + + (** This module discloses definitions that are only useful for tests and must + not be used otherwise. *) + module Internal_for_tests : sig + val fold_on_bond_ids : + context -> + Contract.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + end +end + +(** This module re-exports definitions from {!Zk_rollup_repr} and + {!Zk_rollup_storage}. *) +module Zk_rollup : sig + module Address : S.HASH + + type t = Address.t + + type scalar := Bls.Primitive.Fr.t + + val to_scalar : t -> scalar + + (** This module re-exports definitions from {!Zk_rollup_state_repr}. *) + module State : sig + type t = scalar array + + val encoding : t Data_encoding.t + end + + (** This module re-exports definitions from {!Zk_rollup_account_repr}. *) + module Account : sig + module SMap : Map.S with type key = string + + type static = { + public_parameters : Plonk.public_parameters; + state_length : int; + circuits_info : [`Public | `Private | `Fee] SMap.t; + nb_ops : int; + } + + type dynamic = { + state : State.t; + paid_l2_operations_storage_space : Z.t; + used_l2_operations_storage_space : Z.t; + } + + type t = {static : static; dynamic : dynamic} + + val encoding : t Data_encoding.t + + val circuits_info_encoding : + [`Public | `Private | `Fee] SMap.t Data_encoding.t + end + + (** This module re-exports definitions from {!Zk_rollup_operation_repr}. *) + module Operation : sig + type price = {id : Ticket_hash.t; amount : Z.t} + + type t = { + op_code : int; + price : price; + l1_dst : Signature.Public_key_hash.t; + rollup_id : Address.t; + payload : scalar array; + } + + val encoding : t Data_encoding.t + + val to_scalar_array : t -> scalar array + end + + module Ticket : sig + type t = {contents : Script.expr; ty : Script.expr; ticketer : Contract.t} + + val encoding : t Data_encoding.t + end + + module Circuit_public_inputs : sig + type pending_op_public_inputs = { + old_state : State.t; + new_state : State.t; + fee : scalar; + exit_validity : bool; + zk_rollup : t; + l2_op : Operation.t; + } + + type private_batch_public_inputs = { + old_state : State.t; + new_state : State.t; + fees : scalar; + zk_rollup : t; + } + + type fee_public_inputs = { + old_state : State.t; + new_state : State.t; + fees : scalar; + } + + type t = + | Pending_op of pending_op_public_inputs + | Private_batch of private_batch_public_inputs + | Fee of fee_public_inputs + + val to_scalar_array : t -> scalar array + end + + module Update : sig + type op_pi = {new_state : State.t; fee : scalar; exit_validity : bool} + + type private_inner_pi = {new_state : State.t; fees : scalar} + + type fee_pi = {new_state : State.t} + + type t = { + pending_pis : (string * op_pi) list; + private_pis : (string * private_inner_pi) list; + fee_pi : fee_pi; + proof : Plonk.proof; + } + + val encoding : t Data_encoding.t + end + + type pending_list = + | Empty of {next_index : int64} + | Pending of {next_index : int64; length : int} + + val pending_list_encoding : pending_list Data_encoding.t + + val in_memory_size : t -> Cache_memory_helpers.sint + + val originate : + context -> + Account.static -> + init_state:State.t -> + (context * Address.t * Z.t) tzresult Lwt.t + + val add_to_pending : + context -> + Address.t -> + (Operation.t * Ticket_hash.t option) list -> + (context * Z.t) tzresult Lwt.t + + val get_pending_length : + context -> Address.t -> (context * int) tzresult Lwt.t + + val get_prefix : + context -> + Address.t -> + int -> + (context * (Operation.t * Ticket_hash.t option) list) tzresult Lwt.t + + val update : + context -> + Address.t -> + pending_to_drop:int -> + new_account:Account.t -> + context tzresult Lwt.t + + val account : context -> t -> (context * Account.t) tzresult Lwt.t + + val pending_list : context -> t -> (context * pending_list) tzresult Lwt.t + + val pending_op : + context -> + t -> + Int64.t -> + (context * (Operation.t * Ticket_hash.t option)) tzresult Lwt.t + + val assert_exist : context -> t -> context tzresult Lwt.t + + val exists : context -> t -> (context * bool) tzresult Lwt.t + + module Errors : sig + type error += + | Deposit_as_external + | Invalid_deposit_amount + | Invalid_deposit_ticket + | Wrong_deposit_parameters + | Ticket_payload_size_limit_exceeded of { + payload_size : Saturation_repr.may_saturate Saturation_repr.t; + limit : int; + } + | Invalid_verification + | Invalid_circuit + | Inconsistent_state_update + | Pending_bound + end + + module Internal_for_tests : sig + val originated_zk_rollup : Origination_nonce.Internal_for_tests.t -> t + end +end + +(** This module re-exports definitions from {!Receipt_repr} and {!Staker_repr}. *) +module Receipt : sig + module Token : sig + type 'token t = + | Tez : Tez.t t + | Staking_pseudotoken : Staking_pseudotoken.t t + + val eq : + 'token1 t -> 'token2 t -> ('token1, 'token2) Equality_witness.eq option + + val add : 'token t -> 'token -> 'token -> 'token tzresult + + val pp : 'token t -> Format.formatter -> 'token -> unit + end + + type unstaked_frozen_staker = + | Single of Contract.t * Signature.public_key_hash + | Shared of Signature.public_key_hash + + type frozen_staker = private + | Baker of Signature.public_key_hash + | Single_staker of { + staker : Contract.t; + delegate : Signature.public_key_hash; + } + | Shared_between_stakers of {delegate : Signature.public_key_hash} + | Baker_edge of Signature.public_key_hash + + val frozen_baker : Signature.public_key_hash -> frozen_staker + + val frozen_baker_edge : Signature.public_key_hash -> frozen_staker + + val frozen_single_staker : + staker:Contract.t -> delegate:Signature.public_key_hash -> frozen_staker + + val frozen_shared_between_stakers : + delegate:Signature.public_key_hash -> frozen_staker + + type 'token balance = + | Contract : Contract.t -> Tez.t balance + | Block_fees : Tez.t balance + | Deposits : frozen_staker -> Tez.t balance + | Unstaked_deposits : unstaked_frozen_staker * Cycle.t -> Tez.t balance + | Nonce_revelation_rewards : Tez.t balance + | Attesting_rewards : Tez.t balance + | Baking_rewards : Tez.t balance + | Baking_bonuses : Tez.t balance + | Storage_fees : Tez.t balance + | Double_signing_punishments : Tez.t balance + | Lost_attesting_rewards : public_key_hash * bool * bool -> Tez.t balance + | Liquidity_baking_subsidies : Tez.t balance + | Burned : Tez.t balance + | Commitments : Blinded_public_key_hash.t -> Tez.t balance + | Bootstrap : Tez.t balance + | Invoice : Tez.t balance + | Initial_commitments : Tez.t balance + | Minted : Tez.t balance + | Frozen_bonds : Contract.t * Bond_id.t -> Tez.t balance + | Sc_rollup_refutation_punishments : Tez.t balance + | Sc_rollup_refutation_rewards : Tez.t balance + | Staking_delegator_numerator : { + delegator : Contract.t; + } + -> Staking_pseudotoken.t balance + | Staking_delegate_denominator : { + delegate : public_key_hash; + } + -> Staking_pseudotoken.t balance + + val token_of_balance : 'token balance -> 'token Token.t + + type 'token balance_update = Debited of 'token | Credited of 'token + + type update_origin = + | Block_application + | Protocol_migration + | Subsidy + | Simulation + | Delayed_operation of {operation_hash : Operation_hash.t} + + type balance_update_item = private + | Balance_update_item : + 'token balance * 'token balance_update * update_origin + -> balance_update_item + + val item : + 'token balance -> + 'token balance_update -> + update_origin -> + balance_update_item + + type balance_updates = balance_update_item list + + val balance_updates_encoding : balance_updates Data_encoding.t + + val balance_updates_encoding_with_legacy_attestation_name : + balance_updates Data_encoding.t +end + +(** This module re-exports definitions from {!Delegate_consensus_key}. *) +module Consensus_key : sig + type pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; + } + + type t = { + delegate : Signature.Public_key_hash.t; + consensus_pkh : Signature.Public_key_hash.t; + } + + val zero : t + + val pp : Format.formatter -> t -> unit + + val pkh : pk -> t +end + +(** This module re-exports definitions from {!Misbehaviour_repr}. *) +module Misbehaviour : sig + type kind = Double_baking | Double_attesting | Double_preattesting + + type t = {level : Raw_level.t; round : Round.t; kind : kind} + + val kind_encoding : kind Data_encoding.t + + val compare_kind : kind -> kind -> int +end + +(** This module re-exports definitions from {!Delegate_storage}, + {!Delegate_consensus_key}, {!Delegate_missed_attestations_storage}, + {!Delegate_slashed_deposits_storage}, {!Delegate_cycles}, + {!Delegate_rewards}, and {!Forbidden_delegates_storage}. *) +module Delegate : sig + val check_not_tz4 : Signature.public_key_hash -> unit tzresult + + val frozen_deposits_limit : + context -> public_key_hash -> Tez.t option tzresult Lwt.t + + val set_frozen_deposits_limit : + context -> public_key_hash -> Tez.t option -> context Lwt.t + + val fold : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(public_key_hash -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + val list : context -> public_key_hash list Lwt.t + + val drain : + context -> + delegate:public_key_hash -> + destination:public_key_hash -> + (context * bool * Tez.t * Receipt.balance_updates) tzresult Lwt.t + + val cycle_end : + context -> + Cycle.t -> + (context * Receipt.balance_updates * public_key_hash list) tzresult Lwt.t + + (** See {!Already_denounced_storage.already_denounced}. *) + val already_denounced : + context -> + public_key_hash -> + Level.t -> + Round.t -> + Misbehaviour.kind -> + bool tzresult Lwt.t + + type reward_and_burn = {reward : Tez.t; amount_to_burn : Tez.t} + + type punishing_amounts = { + staked : reward_and_burn; + unstaked : (Cycle.t * reward_and_burn) list; + } + + (** See {!Delegate_slashed_deposits_storage.punish_double_signing}. *) + val punish_double_signing : + context -> + operation_hash:Operation_hash.t -> + Misbehaviour.t -> + public_key_hash -> + Level.t -> + rewarded:public_key_hash -> + context tzresult Lwt.t + + type level_participation = Participated | Didn't_participate + + val record_baking_activity_and_pay_rewards_and_fees : + context -> + payload_producer:public_key_hash -> + block_producer:public_key_hash -> + baking_reward:Tez.t -> + reward_bonus:Tez.t option -> + (context * Receipt.balance_updates) tzresult Lwt.t + + val record_attesting_participation : + context -> + delegate:public_key_hash -> + participation:level_participation -> + attesting_power:int -> + context tzresult Lwt.t + + val current_frozen_deposits : + context -> public_key_hash -> Tez.t tzresult Lwt.t + + val initial_frozen_deposits : + context -> public_key_hash -> Tez.t tzresult Lwt.t + + (** See {!Contract_delegate_storage.delegated_contracts}. *) + val delegated_contracts : context -> public_key_hash -> Contract.t list Lwt.t + + val registered : context -> public_key_hash -> bool Lwt.t + + val deactivated : context -> public_key_hash -> bool tzresult Lwt.t + + (** See {!Forbidden_delegates_storage.is_forbidden}. *) + val is_forbidden_delegate : t -> public_key_hash -> bool + + (** See {!Delegate_activation_storage.last_cycle_before_deactivation}. *) + val last_cycle_before_deactivation : + context -> public_key_hash -> Cycle.t tzresult Lwt.t + + module Consensus_key : sig + val check_not_tz4 : Signature.public_key -> unit tzresult + + val active_pubkey : + context -> public_key_hash -> Consensus_key.pk tzresult Lwt.t + + val pending_updates : + context -> + public_key_hash -> + (Cycle.t * public_key_hash * public_key) list tzresult Lwt.t + + val register_update : + context -> public_key_hash -> public_key -> context tzresult Lwt.t + end + + (** See {!Stake_storage.prepare_stake_distribution}. *) + val prepare_stake_distribution : context -> context tzresult Lwt.t + + module Rewards : sig + val baking_reward_fixed_portion : t -> Tez.t tzresult + + val baking_reward_bonus_per_slot : t -> Tez.t tzresult + + val attesting_reward_per_slot : t -> Tez.t tzresult + + val liquidity_baking_subsidy : t -> Tez.t tzresult + + val seed_nonce_revelation_tip : t -> Tez.t tzresult + + val vdf_revelation_tip : t -> Tez.t tzresult + + module For_RPC : sig + type reward_kind = + | Baking_reward_fixed_portion + | Baking_reward_bonus_per_slot + | Attesting_reward_per_slot + | Seed_nonce_revelation_tip + | Vdf_revelation_tip + + (** [reward_from_constants ~coeff csts ~reward_kind] returns the amount of + rewards in {!Tez.t} for the given [reward_kind], according to the + given parameters in [csts]. The (optional) value [coeff] is a + multiplicative factor applied to the rewards (default = 1). + It verifies [reward_from_constants ~coeff csts ~reward_kind = + coeff * reward_from_constants csts ~reward_kind]. *) + val reward_from_constants : + ?coeff:Q.t -> + Constants.Parametric.t -> + reward_kind:reward_kind -> + Tez.t tzresult + + val liquidity_baking_subsidy_from_constants : + Constants.Parametric.t -> Tez.t tzresult + + (** [get_reward_coeff ctxt cycle] reads the reward coeff for the given cycle + from the storage. + Returns [Q.one] if the given cycle is not between [current_cycle] and + [current_cycle + consensus_rights_delay]. + If adaptive issuance has not been activated, or has been activated and the + given cycle is less than [consensus_rights_delay] after the activation cycle, + then this function returns [Q.one]. + Used only for RPCs. To get the actual rewards, use the reward functions + defined above. *) + val get_reward_coeff : t -> cycle:Cycle.t -> Q.t tzresult Lwt.t + + (** [get_reward_bonus ctxt cycle] reads the reward bonus for the given cycle + from the storage. If cycle is [None], returns 0. + + Returns 0 if the given cycle is not between [current_cycle] and + [current_cycle + consensus_rights_delay]. + + If adaptive issuance has not been activated, + then this function returns 0. + Used only for RPCs. To get the actual rewards, use [Delegate_rewards]. *) + val get_reward_bonus : + t -> cycle:Cycle.t option -> Issuance_bonus_repr.t tzresult Lwt.t + end + + module Internal_for_tests : sig + (** Reward computation functions *) + val compute_reward_coeff_ratio_without_bonus : + stake_ratio:Q.t -> + issuance_ratio_max:Q.t -> + issuance_ratio_min:Q.t -> + Q.t + + val compute_bonus : + issuance_ratio_max:Q.t -> + seconds_per_cycle:int64 -> + stake_ratio:Q.t -> + base_reward_coeff_ratio:Q.t -> + previous_bonus:Issuance_bonus_repr.t -> + reward_params:Constants.Parametric.adaptive_rewards_params -> + Issuance_bonus_repr.t tzresult + + val compute_coeff : + issuance_ratio_max:Q.t -> + issuance_ratio_min:Q.t -> + base_total_issued_per_minute:Tez_repr.t -> + base_reward_coeff_ratio:Q.t -> + q_total_supply:Q.t -> + bonus:Issuance_bonus_repr.t -> + Q.t + + val compute_min : + reward_params:Constants.Parametric.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> + Q.t + + val compute_max : + reward_params:Constants.Parametric.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> + Q.t + end + end + + module Staking_parameters : sig + val register_update : + context -> + Signature.Public_key_hash.t -> + Staking_parameters_repr.t -> + context tzresult Lwt.t + + val of_delegate : + context -> + Signature.Public_key_hash.t -> + Staking_parameters_repr.t tzresult Lwt.t + + val pending_updates : + context -> + Signature.Public_key_hash.t -> + (Cycle.t * Staking_parameters_repr.t) list tzresult Lwt.t + end + + module Shared_stake : sig + val pay_rewards : + context -> + ?active_stake:Stake_repr.t -> + source:[< Token.giver] -> + delegate:public_key_hash -> + Tez.t -> + (context * Receipt.balance_updates) tzresult Lwt.t + end + + (** The functions in this module are considered too costly to be used in + the protocol. + They are meant to be used only to answer RPC calls. *) + module For_RPC : sig + type participation_info = { + expected_cycle_activity : int; + minimal_cycle_activity : int; + missed_slots : int; + missed_levels : int; + remaining_allowed_missed_slots : int; + expected_attesting_rewards : Tez.t; + } + + val participation_info : + context -> public_key_hash -> participation_info tzresult Lwt.t + + (** Returns the full 'balance' of the implicit contract associated to a + given key, i.e. the sum of the spendable balance (given by [balance] or + [Contract_storage.get_balance]) and of the frozen balance of the + contract. + + The frozen balance is composed of all frozen bonds associated to the + contract (given by [Contract_storage.get_frozen_bonds]), all unstaked + frozen deposits, and of the fraction of the frozen deposits that + actually belongs to the delegate and not to its stakers. + + Only use this function for RPCs: this is expensive. *) + val full_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t + + val delegated_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t + + val staking_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t + + val min_delegated_in_current_cycle : + context -> public_key_hash -> (Tez.t * Level_repr.t option) tzresult Lwt.t + + val has_pending_denunciations : context -> public_key_hash -> bool Lwt.t + + val pending_denunciations : + context -> public_key_hash -> Denunciations_repr.t tzresult Lwt.t + + val pending_denunciations_list : + context -> (public_key_hash * Denunciations_repr.item) list Lwt.t + + (** [get_estimated_shared_pending_slashed_amount ctxt delegate] + returns the estimated shared pending slashed amount of the given [delegate] + according to the currently available denunciations. *) + val get_estimated_shared_pending_slashed_amount : + context -> public_key_hash -> Tez.t tzresult Lwt.t + end +end + +module Staking : sig + (** [stake ctxt ~sender ~delegate amount] add [amount] as [sender]'s stake + to [delegate]. *) + val stake : + context -> + amount:[`At_most of Tez.t | `Exactly of Tez.t] -> + sender:public_key_hash -> + delegate:public_key_hash -> + (context * Receipt.balance_updates) tzresult Lwt.t + + (** [request_unstake ctxt ~sender_contract ~delegate amount] records a request + from [sender_contract] to unstake [amount] from [delegate]. *) + val request_unstake : + context -> + sender_contract:Contract.t -> + delegate:public_key_hash -> + Tez.t -> + (context * Receipt.balance_updates) tzresult Lwt.t + + (** [finalize_unstake ctxt contract] performs the finalization of all unstake + requests from [contract] that can be finalized. + An unstake request can be finalized if it is old enough, specifically the + requested amount must not be at stake anymore and must not be slashable + anymore, i.e. after [consensus_rights_delay + max_slashing_period] after the + request. + Amounts are transferred from the [contract]'s delegate (at request time) + unstaked frozen deposits to [contract]'s spendable balance, minus slashing + the requested stake undergone in between. *) + val finalize_unstake : + context -> Contract.t -> (context * Receipt.balance_updates) tzresult Lwt.t + + (** Staking can be either automated or manual. If Adaptive Issuance is + enabled, staking must be manual. *) + type staking_automation = Auto_staking | Manual_staking + + val staking_automation : context -> staking_automation + + val check_manual_staking_allowed : context -> unit tzresult +end + +(** This module re-exports definitions from {!Voting_period_repr} and + {!Voting_period_storage}. *) +module Voting_period : sig + type kind = Proposal | Exploration | Cooldown | Promotion | Adoption + + val kind_encoding : kind Data_encoding.encoding + + val pp_kind : Format.formatter -> kind -> unit + + (* This type should be abstract *) + type voting_period = private { + index : int32; + kind : kind; + start_position : int32; + } + + type t = voting_period + + include BASIC_DATA with type t := t + + val encoding : voting_period Data_encoding.t + + val pp : Format.formatter -> voting_period -> unit + + val reset : context -> context tzresult Lwt.t + + val succ : context -> context tzresult Lwt.t + + val get_current : context -> voting_period tzresult Lwt.t + + val get_current_kind : context -> kind tzresult Lwt.t + + val is_last_block : context -> bool tzresult Lwt.t + + type info = {voting_period : t; position : int32; remaining : int32} + + val info_encoding : info Data_encoding.t + + val pp_info : Format.formatter -> info -> unit + + val get_rpc_current_info : context -> info tzresult Lwt.t + + val get_rpc_succ_info : context -> info tzresult Lwt.t + + module Testnet_dictator : sig + (** See {!Voting_period_storage.Testnet_dictator.overwrite_current_kind}. *) + val overwrite_current_kind : + context -> Chain_id.t -> Voting_period_repr.kind -> context tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Vote_repr} and {!Vote_storage}. *) +module Vote : sig + type proposal = Protocol_hash.t + + (** See {!Vote_storage.get_delegate_proposal_count}. *) + val get_delegate_proposal_count : + context -> public_key_hash -> int tzresult Lwt.t + + (** See {!Vote_storage.set_delegate_proposal_count}. *) + val set_delegate_proposal_count : + context -> public_key_hash -> int -> context Lwt.t + + (** See {!Vote_storage.has_proposed}. *) + val has_proposed : context -> public_key_hash -> proposal -> bool Lwt.t + + (** See {!Vote_storage.add_proposal}. *) + val add_proposal : context -> public_key_hash -> proposal -> context Lwt.t + + val get_proposals : context -> int64 Protocol_hash.Map.t tzresult Lwt.t + + val clear_proposals : context -> context Lwt.t + + val listings_encoding : (public_key_hash * int64) list Data_encoding.t + + val update_listings : context -> context tzresult Lwt.t + + val in_listings : context -> public_key_hash -> bool Lwt.t + + val get_listings : context -> (public_key_hash * int64) list Lwt.t + + type ballot = Yay | Nay | Pass + + val equal_ballot : ballot -> ballot -> bool + + val pp_ballot : Format.formatter -> ballot -> unit + + type delegate_info = { + voting_power : Int64.t option; + current_ballot : ballot option; + current_proposals : Protocol_hash.t list; + remaining_proposals : int; + } + + val pp_delegate_info : Format.formatter -> delegate_info -> unit + + val delegate_info_encoding : delegate_info Data_encoding.t + + val get_delegate_info : + context -> public_key_hash -> delegate_info tzresult Lwt.t + + val get_voting_power_free : context -> public_key_hash -> int64 tzresult Lwt.t + + val get_voting_power : + context -> public_key_hash -> (context * int64) tzresult Lwt.t + + val get_current_voting_power_free : + context -> public_key_hash -> int64 tzresult Lwt.t + + val get_total_voting_power_free : context -> int64 tzresult Lwt.t + + val get_total_voting_power : context -> (context * int64) tzresult Lwt.t + + val ballot_encoding : ballot Data_encoding.t + + type ballots = {yay : int64; nay : int64; pass : int64} + + (** See {!Vote_storage.ballots_zero}. *) + val ballots_zero : ballots + + (** See {!Vote_storage.ballots_encoding} *) + val ballots_encoding : ballots Data_encoding.t + + (** See {!Vote_storage.equal_ballots}. *) + val equal_ballots : ballots -> ballots -> bool + + (** See {!Vote_storage.pp_ballots}. *) + val pp_ballots : Format.formatter -> ballots -> unit + + val has_recorded_ballot : context -> public_key_hash -> bool Lwt.t + + val record_ballot : + context -> public_key_hash -> ballot -> context tzresult Lwt.t + + val get_ballots : context -> ballots tzresult Lwt.t + + val get_ballot_list : context -> (public_key_hash * ballot) list Lwt.t + + val clear_ballots : context -> context Lwt.t + + val get_current_quorum : context -> int32 tzresult Lwt.t + + val get_participation_ema : context -> int32 tzresult Lwt.t + + val set_participation_ema : context -> int32 -> context tzresult Lwt.t + + (** See {!Vote_storage.current_proposal_exists}. *) + val current_proposal_exists : context -> bool Lwt.t + + (** See {!Vote_storage.get_current_proposal}. *) + val get_current_proposal : context -> proposal tzresult Lwt.t + + (** See {!Vote_storage.find_current_proposal}. *) + val find_current_proposal : context -> proposal option tzresult Lwt.t + + (** See {!Vote_storage.init_current_proposal}. *) + val init_current_proposal : context -> proposal -> context tzresult Lwt.t + + (** See {!Vote_storage.clear_current_proposal}. *) + val clear_current_proposal : context -> context Lwt.t +end + +(** This module exposes definitions for the data-availability layer. *) +module Dal : sig + type parameters = Dal.parameters = { + redundancy_factor : int; + page_size : int; + slot_size : int; + number_of_shards : int; + } + + type cryptobox + + val make : context -> (context * cryptobox) tzresult + + val number_of_slots : context -> int + + val number_of_shards : context -> int + + (** This module re-exports definitions from {!Dal_slot_index_repr}. *) + module Slot_index : sig + type t + + val pp : Format.formatter -> t -> unit + + val zero : t + + val encoding : t Data_encoding.t + + val of_int_opt : number_of_slots:int -> int -> t option + + val of_int : number_of_slots:int -> int -> t tzresult + + val to_int : t -> int + + val to_int_list : t list -> int list + + val compare : t -> t -> int + + val equal : t -> t -> bool + + val slots_range : + number_of_slots:int -> lower:int -> upper:int -> t list tzresult + + val slots_range_opt : + number_of_slots:int -> lower:int -> upper:int -> t list option + + val check_is_in_range : number_of_slots:int -> t -> unit tzresult + end + + (** This module re-exports definitions from {!Dal_attestation_repr} and + {!Raw_context.Dal}. *) + module Attestation : sig + type t = private Bitset.t + + type shard_index = int + + module Shard_map : Map.S with type key = shard_index + + val encoding : t Data_encoding.t + + val empty : t + + val commit : t -> Slot_index.t -> t + + val is_attested : t -> Slot_index.t -> bool + + val occupied_size_in_bits : t -> int + + val expected_size_in_bits : max_index:Slot_index.t -> int + + val record_number_of_attested_shards : context -> t -> int -> context + end + + type slot_id = {published_level : Raw_level.t; index : Slot_index.t} + + module Page : sig + type content = bytes + + val pages_per_slot : parameters -> int + + module Index : sig + type t = int + + val encoding : int Data_encoding.t + + val pp : Format.formatter -> int -> unit + + val compare : int -> int -> int + + val equal : int -> int -> bool + + type error += Invalid_page_index of {given : int; min : int; max : int} + + val check_is_in_range : number_of_pages:int -> t -> unit tzresult + end + + type t = {slot_id : slot_id; page_index : Index.t} + + val content_encoding : content Data_encoding.t + + type proof = Dal.page_proof + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val equal : t -> t -> bool + end + + (** This module re-exports definitions from {!Dal_slot_repr}, + {!Dal_slot_storage} and {!Raw_context.Dal}. *) + module Slot : sig + (** This module re-exports definitions from {!Dal_slot_repr.Header}. *) + module Commitment : sig + type t = Dal.commitment + + val encoding : t Data_encoding.t + + val zero : t + end + + module Commitment_proof : sig + type t = Dal.commitment_proof + + val encoding : t Data_encoding.t + + val zero : t + end + + module Header : sig + type id = slot_id = {published_level : Raw_level.t; index : Slot_index.t} + + type t = {id : id; commitment : Commitment.t} + + val id_encoding : id Data_encoding.t + + val encoding : t Data_encoding.t + + val pp_id : Format.formatter -> id -> unit + + val pp : Format.formatter -> t -> unit + + val equal : t -> t -> bool + end + + val register_slot_header : context -> Header.t -> context tzresult + + val find_slot_headers : + context -> Raw_level.t -> Header.t list option tzresult Lwt.t + + val finalize_current_slot_headers : context -> context Lwt.t + + val finalize_pending_slot_headers : + context -> number_of_slots:int -> (context * Attestation.t) tzresult Lwt.t + + val compute_attested_slot_headers : + is_slot_attested:(Header.t -> bool) -> + Header.t list -> + Header.t list * Attestation.t + end + + module Operations : sig + module Publish_commitment : sig + type t = { + slot_index : Slot_index.t; + commitment : Slot.Commitment.t; + commitment_proof : Slot.Commitment_proof.t; + } + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val slot_header : + cryptobox:cryptobox -> + number_of_slots:int -> + current_level:Raw_level.t -> + t -> + Slot.Header.t tzresult + end + end + + module Slots_history : sig + type t + + module Pointer_hash : S.HASH + + type hash = Pointer_hash.t + + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3766 + Do we need to export this? *) + val genesis : t + + val equal : t -> t -> bool + + val encoding : t Data_encoding.t + + val hash : t -> hash + + module History_cache : + Bounded_history_repr.S with type key = hash and type value = t + + val add_confirmed_slot_headers_no_cache : + t -> + Raw_level.t -> + number_of_slots:int -> + Slot.Header.t list -> + t tzresult + + val add_confirmed_slot_headers : + t -> + History_cache.t -> + Raw_level.t -> + number_of_slots:int -> + Slot.Header.t list -> + (t * History_cache.t) tzresult + + type proof + end + + module Slots_storage : sig + val get_slot_headers_history : context -> Slots_history.t tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Dal_errors_repr}. *) +module Dal_errors : sig + (* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3168 + do not expose these errors and return them in functions + from Dal_slot_repr or Dal_attestation_repr. *) + type error += + | Dal_feature_disabled + | Dal_slot_index_above_hard_limit of {given : int; limit : int} + | Dal_publish_commitment_invalid_index of { + given : Dal.Slot_index.t; + maximum : Dal.Slot_index.t; + } + | Dal_publish_commitment_candidate_with_low_fees of {proposed_fees : Tez.t} + | Dal_attestation_size_limit_exceeded of {maximum_size : int; got : int} + | Dal_publish_commitment_duplicate of {slot_header : Dal.Slot.Header.t} + | Dal_publish_commitment_invalid_proof of { + commitment : Dal.Slot.Commitment.t; + commitment_proof : Dal.Slot.Commitment_proof.t; + } + | Dal_data_availibility_attester_not_in_committee of { + attester : Signature.Public_key_hash.t; + level : Raw_level.t; + slot : Slot.t; + } + | Dal_cryptobox_error of {explanation : string} +end + +(** This module re-exports definitions from {!Sc_rollup_storage} and + {!Sc_rollup_repr}. *) +module Sc_rollup : sig + (** See {!Sc_rollup_tick_repr}. *) + module Tick : sig + type t + + val initial : t + + val next : t -> t + + val jump : t -> Z.t -> t + + val distance : t -> t -> Z.t + + val of_int : int -> t option + + val to_int : t -> int option + + val of_z : Z.t -> t + + val to_z : t -> Z.t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + include Compare.S with type t := t + + module Map : Map.S with type key = t + end + + module Address : module type of struct + include Smart_rollup.Address + end + + type t = Smart_rollup.Address.t + + type rollup := t + + val in_memory_size : t -> Cache_memory_helpers.sint + + val must_exist : context -> t -> context tzresult Lwt.t + + module Whitelist : sig + type t = public_key_hash list + + val init : + context -> + Address.t -> + whitelist:t -> + origination_level:Raw_level.t -> + (context * Z.t) tzresult Lwt.t + + val is_private : context -> Address.t -> (context * bool) tzresult Lwt.t + + val find_whitelist_uncarbonated : + context -> Address.t -> t option tzresult Lwt.t + + val replace : + context -> Address.t -> whitelist:t -> (context * Z.t) tzresult Lwt.t + + val make_public : context -> Address.t -> (context * Z.t) tzresult Lwt.t + + val adjust_storage_space : + context -> + Address.t -> + new_storage_size:Z.t -> + (context * Z.t) tzresult Lwt.t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + type last_whitelist_update = { + message_index : Z.t; + outbox_level : Raw_level.t; + } + + val last_whitelist_update_encoding : last_whitelist_update Data_encoding.t + + val get_last_whitelist_update : + context -> + Sc_rollup_repr.t -> + (context * last_whitelist_update) tzresult Lwt.t + + val set_last_whitelist_update : + context -> + Sc_rollup_repr.t -> + last_whitelist_update -> + (context * Z.t) tzresult Lwt.t + + type update = Public | Private of t + + val update_encoding : update Data_encoding.t + end + + module Staker : sig + include S.SIGNATURE_PUBLIC_KEY_HASH with type t = public_key_hash + + val rpc_arg_staker1 : t RPC_arg.t + + val rpc_arg_staker2 : t RPC_arg.t + + module Index : sig + type t = private Z.t + + val encoding : t Data_encoding.t + end + end + + module State_hash : module type of struct + include Smart_rollup.State_hash + end + + (** See {!Sc_rollup_metadata_repr}. *) + module Metadata : sig + type t = {address : rollup; origination_level : Raw_level.t} + + val pp : Format.formatter -> t -> unit + + val equal : t -> t -> bool + + val encoding : t Data_encoding.t + end + + (** See {!Sc_rollup_dal_parameters_repr}. *) + module Dal_parameters : sig + type t = { + number_of_slots : int64; + attestation_lag : int64; + slot_size : int64; + page_size : int64; + } + + val pp : Format.formatter -> t -> unit + + val equal : t -> t -> bool + + val encoding : t Data_encoding.t + end + + (** See {!Sc_rollup_inbox_message_repr}. *) + module Inbox_message : sig + type internal_inbox_message = + | Transfer of { + payload : Script.expr; + sender : Contract_hash.t; + source : public_key_hash; + destination : t; + } + | Start_of_level + | End_of_level + | Info_per_level of { + predecessor_timestamp : Time.t; + predecessor : Block_hash.t; + } + | Protocol_migration of string + + val protocol_migration_internal_message : internal_inbox_message + + type t = Internal of internal_inbox_message | External of string + + type serialized = private string + + val protocol_migration_serialized_message : serialized + + val encoding : t Data_encoding.t + + val unsafe_of_string : string -> serialized + + val unsafe_to_string : serialized -> string + + val serialize : t -> serialized tzresult + + val deserialize : serialized -> t tzresult + + module Hash : S.HASH + + val hash_serialized_message : serialized -> Hash.t + end + + module Inbox_merkelized_payload_hashes : sig + module Hash : + S.HASH with type t = Smart_rollup.Merkelized_payload_hashes_hash.t + + type t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val equal : t -> t -> bool + + val hash : t -> Hash.t + + val get_payload_hash : t -> Inbox_message.Hash.t + + val get_index : t -> Z.t + + type merkelized_and_payload = { + merkelized : t; + payload : Inbox_message.serialized; + } + + module History : sig + include + Bounded_history_repr.S + with type key = Hash.t + and type value = merkelized_and_payload + + val no_history : t + end + + val genesis_no_history : Inbox_message.serialized -> t + + val genesis : + History.t -> Inbox_message.serialized -> (History.t * t) tzresult + + val add_payload : + History.t -> t -> Inbox_message.serialized -> (History.t * t) tzresult + + type proof = private t list + + val pp_proof : Format.formatter -> proof -> unit + + val proof_encoding : proof Data_encoding.t + + val produce_proof : + History.t -> index:Z.t -> t -> (merkelized_and_payload * proof) option + + val verify_proof : proof -> (t * t) tzresult + + module Internal_for_tests : sig + val find_predecessor_payload : History.t -> index:Z.t -> t -> t option + + val make_proof : t list -> proof + end + end + + type inbox_message = { + inbox_level : Raw_level.t; + message_counter : Z.t; + payload : Inbox_message.serialized; + } + + type reveal_data = + | Raw_data of string + | Metadata of Metadata.t + | Dal_page of Dal.Page.content option + | Dal_parameters of Dal_parameters.t + + type input = Inbox_message of inbox_message | Reveal of reveal_data + + val pp_inbox_message : Format.formatter -> inbox_message -> unit + + val inbox_message_equal : inbox_message -> inbox_message -> bool + + val pp_reveal_data : Format.formatter -> reveal_data -> unit + + val pp_input : Format.formatter -> input -> unit + + val input_equal : input -> input -> bool + + val input_encoding : input Data_encoding.t + + module Input_hash : S.HASH + + type reveal = + | Reveal_raw_data of Sc_rollup_reveal_hash.t + | Reveal_metadata + | Request_dal_page of Dal.Page.t + | Reveal_dal_parameters + + type is_reveal_enabled = current_block_level:Raw_level.t -> reveal -> bool + + val reveal_encoding : reveal Data_encoding.t + + val pp_reveal : Format.formatter -> reveal -> unit + + val is_reveal_enabled_predicate : + Constants.Parametric.sc_rollup_reveal_activation_level -> is_reveal_enabled + + type input_request = + | No_input_required + | Initial + | First_after of Raw_level.t * Z.t + | Needs_reveal of reveal + + val input_request_encoding : input_request Data_encoding.t + + val input_request_equal : input_request -> input_request -> bool + + val pp_input_request : Format.formatter -> input_request -> unit + + module Inbox : sig + module Skip_list : Skip_list.S + + module Hash : S.HASH with type t = Smart_rollup.Inbox_hash.t + + type level_proof = { + hash : Inbox_merkelized_payload_hashes.Hash.t; + level : Raw_level.t; + } + + type history_proof = (level_proof, Hash.t) Skip_list.cell + + type t = {level : Raw_level.t; old_levels_messages : history_proof} + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + + val equal : t -> t -> bool + + val inbox_level : t -> Raw_level.t + + val old_levels_messages : t -> history_proof + + val history_proof_encoding : history_proof Data_encoding.t + + val equal_history_proof : history_proof -> history_proof -> bool + + val pp_history_proof : Format.formatter -> history_proof -> unit + + val hash : t -> Hash.t + + val current_witness : t -> Inbox_merkelized_payload_hashes.Hash.t + + module History : + Bounded_history_repr.S + with type key = Hash.t + and type value = history_proof + + type serialized_proof + + val serialized_proof_encoding : serialized_proof Data_encoding.t + + val add_all_messages : + first_block:bool -> + predecessor_timestamp:Time.t -> + predecessor:Block_hash.t -> + History.t -> + t -> + Inbox_message.t list -> + (Inbox_merkelized_payload_hashes.History.t + * History.t + * t + * Inbox_merkelized_payload_hashes.t + * Inbox_message.t list) + tzresult + + val add_messages_no_history : + Inbox_message.serialized list -> + Inbox_merkelized_payload_hashes.t -> + Inbox_merkelized_payload_hashes.t tzresult + + val take_snapshot : t -> history_proof + + type proof + + val pp_proof : Format.formatter -> proof -> unit + + val to_serialized_proof : proof -> serialized_proof + + val of_serialized_proof : serialized_proof -> proof option + + val verify_proof : + Raw_level.t * Z.t -> + history_proof -> + proof -> + inbox_message option tzresult + + val produce_proof : + get_payloads_history: + (Inbox_merkelized_payload_hashes.Hash.t -> + Inbox_merkelized_payload_hashes.History.t Lwt.t) -> + get_history:(Hash.t -> history_proof option Lwt.t) -> + history_proof -> + Raw_level.t * Z.t -> + (proof * inbox_message option) tzresult Lwt.t + + val finalize_inbox_level_no_history : + t -> Inbox_merkelized_payload_hashes.t -> t + + val init_witness_no_history : Inbox_merkelized_payload_hashes.t + + val add_info_per_level_no_history : + predecessor_timestamp:Time.t -> + predecessor:Block_hash.t -> + Inbox_merkelized_payload_hashes.t -> + Inbox_merkelized_payload_hashes.t + + val genesis : + predecessor_timestamp:Time.t -> + predecessor:Block_hash.t -> + Raw_level.t -> + t + + module Internal_for_tests : sig + type inclusion_proof = history_proof list + + val pp_inclusion_proof : Format.formatter -> inclusion_proof -> unit + + val produce_inclusion_proof : + (Hash.t -> history_proof option Lwt.t) -> + history_proof -> + Raw_level.t -> + (inclusion_proof * history_proof) tzresult Lwt.t + + val verify_inclusion_proof : + inclusion_proof -> history_proof -> history_proof tzresult + + type payloads_proof = { + proof : Inbox_merkelized_payload_hashes.proof; + payload : Inbox_message.serialized option; + } + + val pp_payloads_proof : Format.formatter -> payloads_proof -> unit + + val produce_payloads_proof : + (Inbox_merkelized_payload_hashes.Hash.t -> + Inbox_merkelized_payload_hashes.History.t Lwt.t) -> + Inbox_merkelized_payload_hashes.Hash.t -> + index:Z.t -> + payloads_proof tzresult Lwt.t + + val verify_payloads_proof : + payloads_proof -> + Inbox_merkelized_payload_hashes.Hash.t -> + Z.t -> + Inbox_message.serialized option tzresult + + val serialized_proof_of_string : string -> serialized_proof + + type level_proof = { + hash : Inbox_merkelized_payload_hashes.Hash.t; + level : Raw_level_repr.t; + } + + val level_proof_of_history_proof : history_proof -> level_proof + + val expose_proof : proof -> inclusion_proof * payloads_proof + + val make_proof : inclusion_proof -> payloads_proof -> proof + end + + val add_external_messages : context -> string list -> context tzresult Lwt.t + + val add_deposit : + context -> + payload:Script.expr -> + sender:Contract_hash.t -> + source:public_key_hash -> + destination:rollup -> + context tzresult Lwt.t + + val finalize_inbox_level : context -> context tzresult Lwt.t + + val add_level_info : + predecessor:Block_hash.t -> context -> context tzresult Lwt.t + + val get_inbox : context -> (t * context) tzresult Lwt.t + end + + module Outbox : sig + (** See {!Sc_rollup_outbox_message_repr}. *) + module Message : sig + type transaction = { + unparsed_parameters : Script.expr; + destination : Contract_hash.t; + entrypoint : Entrypoint.t; + } + + type typed_transaction = { + unparsed_parameters : Script.expr; + unparsed_ty : Script.expr; + destination : Contract_hash.t; + entrypoint : Entrypoint.t; + } + + type t = + | Atomic_transaction_batch of {transactions : transaction list} + | Atomic_transaction_batch_typed of { + transactions : typed_transaction list; + } + | Whitelist_update of Whitelist.t option + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + + type serialized + + val unsafe_of_string : string -> serialized + + val unsafe_to_string : serialized -> string + + val deserialize : serialized -> t tzresult + + val serialize : t -> serialized tzresult + end + + val record_applied_message : + context -> + t -> + Raw_level.t -> + message_index:int -> + (Z.t * context) tzresult Lwt.t + end + + type output = { + outbox_level : Raw_level.t; + message_index : Z.t; + message : Outbox.Message.t; + } + + val output_encoding : output Data_encoding.t + + module Dissection_chunk : sig + type t = {state_hash : State_hash.t option; tick : Tick.t} + + val equal : t -> t -> bool + + val pp : Format.formatter -> t -> unit + + type error += + | Dissection_number_of_sections_mismatch of {expected : Z.t; given : Z.t} + | Dissection_invalid_number_of_sections of Z.t + | Dissection_start_hash_mismatch of { + expected : State_hash.t option; + given : State_hash.t option; + } + | Dissection_stop_hash_mismatch of State_hash.t option + | Dissection_edge_ticks_mismatch of { + dissection_start_tick : Tick.t; + dissection_stop_tick : Tick.t; + chunk_start_tick : Tick.t; + chunk_stop_tick : Tick.t; + } + | Dissection_ticks_not_increasing + | Dissection_invalid_distribution of Z.t + | Dissection_invalid_successive_states_shape + end + + module type Generic_pvm_context_sig = sig + module Tree : + Context.TREE with type key = string list and type value = bytes + + type tree = Tree.tree + + type proof + + val proof_encoding : proof Data_encoding.t + + val proof_before : proof -> Sc_rollup_repr.State_hash.t + + val proof_after : proof -> Sc_rollup_repr.State_hash.t + + val verify_proof : + proof -> (tree -> (tree * 'a) Lwt.t) -> (tree * 'a) option Lwt.t + + val produce_proof : + Tree.t -> tree -> (tree -> (tree * 'a) Lwt.t) -> (proof * 'a) option Lwt.t + end + + module PVM : sig + type boot_sector = string + + module type S = sig + val parse_boot_sector : string -> boot_sector option + + val pp_boot_sector : Format.formatter -> boot_sector -> unit + + type state + + val pp : state -> (Format.formatter -> unit -> unit) Lwt.t + + type context + + type hash = State_hash.t + + type proof + + val proof_encoding : proof Data_encoding.t + + val proof_start_state : proof -> hash + + val proof_stop_state : proof -> hash + + val state_hash : state -> hash Lwt.t + + val initial_state : empty:state -> state Lwt.t + + val install_boot_sector : state -> string -> state Lwt.t + + val is_input_state : + is_reveal_enabled:is_reveal_enabled -> state -> input_request Lwt.t + + val set_input : input -> state -> state Lwt.t + + val eval : state -> state Lwt.t + + val verify_proof : + is_reveal_enabled:is_reveal_enabled -> + input option -> + proof -> + input_request tzresult Lwt.t + + val produce_proof : + context -> + is_reveal_enabled:is_reveal_enabled -> + input option -> + state -> + proof tzresult Lwt.t + + type output_proof + + val output_proof_encoding : output_proof Data_encoding.t + + val output_of_output_proof : output_proof -> output + + val state_of_output_proof : output_proof -> State_hash.t + + val verify_output_proof : output_proof -> output tzresult Lwt.t + + val produce_output_proof : + context -> state -> output -> (output_proof, error) result Lwt.t + + val check_dissection : + default_number_of_sections:int -> + start_chunk:Dissection_chunk.t -> + stop_chunk:Dissection_chunk.t -> + Dissection_chunk.t list -> + unit tzresult + + val get_current_level : state -> Raw_level.t option Lwt.t + + module Internal_for_tests : sig + val insert_failure : state -> state Lwt.t + end + end + + type ('state, 'proof, 'output) implementation = + (module S + with type state = 'state + and type proof = 'proof + and type output_proof = 'output) + + type t = Packed : ('state, 'proof, 'output) implementation -> t + [@@unboxed] + end + + module Kind : sig + type t = Example_arith | Wasm_2_0_0 | Riscv + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val pvm_of : t -> PVM.t + + val all : t list + + val of_string : string -> t option + + val to_string : t -> string + + val equal : t -> t -> bool + end + + val genesis_state_hash_of : boot_sector:string -> Kind.t -> State_hash.t Lwt.t + + module ArithPVM : sig + module Make (C : Generic_pvm_context_sig) : sig + include + PVM.S + with type context = C.Tree.t + and type state = C.tree + and type proof = C.proof + + val get_tick : state -> Tick.t Lwt.t + + type status = + | Halted + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + | Parsing + | Evaluating + + val get_status : + is_reveal_enabled:is_reveal_enabled -> state -> status Lwt.t + + val get_outbox : Raw_level.t -> state -> output list Lwt.t + end + + module Protocol_implementation : + PVM.S + with type context = Context.t + and type state = Context.tree + and type proof = Context.Proof.tree Context.Proof.t + end + + module Wasm_2_0_0PVM : sig + val ticks_per_snapshot : Z.t + + val outbox_validity_period : int32 + + val outbox_message_limit : Z.t + + val well_known_reveal_preimage : string + + val well_known_reveal_hash : Sc_rollup_reveal_hash.t + + val decode_reveal : Wasm_2_0_0.reveal -> reveal + + module type Make_wasm = module type of Wasm_2_0_0.Make + + module Make (Wasm_backend : Make_wasm) (C : Generic_pvm_context_sig) : sig + include + PVM.S + with type context = C.Tree.t + and type state = C.tree + and type proof = C.proof + + val get_tick : state -> Tick.t Lwt.t + + type status = + | Computing + | Waiting_for_input_message + | Waiting_for_reveal of reveal + + val get_status : + is_reveal_enabled:is_reveal_enabled -> state -> status Lwt.t + + val get_outbox : Raw_level.t -> state -> output list Lwt.t + + val produce_proof : + context -> + is_reveal_enabled:is_reveal_enabled -> + input option -> + state -> + proof tzresult Lwt.t + end + + module Protocol_implementation : + PVM.S + with type context = Context.t + and type state = Context.tree + and type proof = Context.Proof.tree Context.Proof.t + end + + module Riscv_PVM : sig + module Protocol_implementation : + PVM.S + with type context = unit + and type state = Sc_rollup_riscv.minimal_state + and type proof = Sc_rollup_riscv.void + end + + module Number_of_ticks : sig + include Bounded.S with type ocaml_type := int64 + + val zero : t + end + + module Commitment : sig + module Hash : S.HASH with type t = Smart_rollup.Commitment_hash.t + + type t = { + compressed_state : State_hash.t; + inbox_level : Raw_level.t; + predecessor : Hash.t; + number_of_ticks : Number_of_ticks.t; + } + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val hash_uncarbonated : t -> Hash.t + + val hash : context -> t -> (context * Hash.t) tzresult + + val genesis_commitment : + origination_level:Raw_level.t -> genesis_state_hash:State_hash.t -> t + + type genesis_info = {level : Raw_level.t; commitment_hash : Hash.t} + + val genesis_info_encoding : genesis_info Data_encoding.t + + val get_commitment : + context -> rollup -> Hash.t -> (t * context) tzresult Lwt.t + + val last_cemented_commitment_hash_with_level : + context -> rollup -> (Hash.t * Raw_level.t * context) tzresult Lwt.t + + val check_if_commitments_are_related : + context -> + rollup -> + descendant:Hash.t -> + ancestor:Hash.t -> + (bool * context) tzresult Lwt.t + end + + val originate : + ?whitelist:Whitelist.t -> + context -> + kind:Kind.t -> + parameters_ty:Script.lazy_expr -> + genesis_commitment:Commitment.t -> + (t * Z.t * Commitment.Hash.t * context) tzresult Lwt.t + + val parameters_type : + context -> t -> (Script.lazy_expr option * context) tzresult Lwt.t + + val kind : context -> t -> (context * Kind.t) tzresult Lwt.t + + module Errors : sig + type error += Sc_rollup_does_not_exist of t + end + + module Proof : sig + type reveal_proof = + | Raw_data_proof of string + | Metadata_proof + | Dal_page_proof of { + page_id : Dal.Page.t; + proof : Dal.Slots_history.proof; + } + | Dal_parameters_proof + + type input_proof = + | Inbox_proof of { + level : Raw_level.t; + message_counter : Z.t; + proof : Inbox.serialized_proof; + } + | Reveal_proof of reveal_proof + | First_inbox_message + + type 'proof t = {pvm_step : 'proof; input_proof : input_proof option} + + type serialized = private string + + val serialize_pvm_step : + pvm:('state, 'proof, 'output) PVM.implementation -> + 'proof -> + serialized tzresult + + val unserialize_pvm_step : + pvm:('state, 'proof, 'output) PVM.implementation -> + serialized -> + 'proof tzresult + + val serialized_encoding : serialized Data_encoding.t + + val encoding : serialized t Data_encoding.t + + module type PVM_with_context_and_state = sig + include PVM.S + + val context : context + + val state : state + + val proof_encoding : proof Data_encoding.t + + val reveal : Sc_rollup_reveal_hash.t -> string option Lwt.t + + module Inbox_with_history : sig + val inbox : Inbox.history_proof + + val get_history : Inbox.Hash.t -> Inbox.history_proof option Lwt.t + + val get_payloads_history : + Inbox_merkelized_payload_hashes.Hash.t -> + Inbox_merkelized_payload_hashes.History.t Lwt.t + end + + module Dal_with_history : sig + val confirmed_slots_history : Dal.Slots_history.t + + val get_history : + Dal.Slots_history.hash -> Dal.Slots_history.t option Lwt.t + + val page_info : (Dal.Page.content * Dal.Page.proof) option + + val dal_parameters : Dal.parameters + + val dal_attestation_lag : int + + val dal_number_of_slots : int + + val dal_activation_level : Raw_level.t option + + val dal_attested_slots_validity_lag : int + end + end + + type error += Sc_rollup_proof_check of string + + val valid : + pvm:('state, 'proof, 'output) PVM.implementation -> + metadata:Metadata.t -> + Inbox.history_proof -> + Raw_level.t -> + Dal.Slots_history.t -> + Dal.parameters -> + dal_activation_level:Raw_level.t option -> + dal_attestation_lag:int -> + dal_number_of_slots:int -> + is_reveal_enabled:is_reveal_enabled -> + dal_attested_slots_validity_lag:int -> + 'proof t -> + (input option * input_request) tzresult Lwt.t + + val produce : + metadata:Metadata.t -> + (module PVM_with_context_and_state) -> + Raw_level.t -> + is_reveal_enabled:is_reveal_enabled -> + serialized t tzresult Lwt.t + + module Dal_helpers : sig + val import_level_is_valid : + dal_activation_level:Raw_level.t option -> + dal_attestation_lag:int -> + origination_level:Raw_level.t -> + commit_inbox_level:Raw_level.t -> + published_level:Raw_level.t -> + dal_attested_slots_validity_lag:int -> + bool + end + end + + module Game : sig + type player = Alice | Bob + + val player_equal : player -> player -> bool + + val player_encoding : player Data_encoding.t + + type dissection_chunk = Dissection_chunk.t + + type game_state = + | Dissecting of { + dissection : dissection_chunk list; + default_number_of_sections : int; + } + | Final_move of { + agreed_start_chunk : dissection_chunk; + refuted_stop_chunk : dissection_chunk; + } + + val game_state_encoding : game_state Data_encoding.t + + val game_state_equal : game_state -> game_state -> bool + + type t = { + turn : player; + inbox_snapshot : Inbox.history_proof; + dal_snapshot : Dal.Slots_history.t; + start_level : Raw_level.t; + inbox_level : Raw_level.t; + game_state : game_state; + } + + val pp_dissection : Format.formatter -> dissection_chunk list -> unit + + val pp : Format.formatter -> t -> unit + + module Index : sig + type t = private {alice : Staker.t; bob : Staker.t} + + val encoding : t Data_encoding.t + + val make : Staker.t -> Staker.t -> t + end + + val encoding : t Data_encoding.t + + val opponent : player -> player + + type step = + | Dissection of dissection_chunk list + | Proof of Proof.serialized Proof.t + + type refutation = + | Start of { + player_commitment_hash : Commitment.Hash.t; + opponent_commitment_hash : Commitment.Hash.t; + } + | Move of {choice : Tick.t; step : step} + + val refutation_encoding : refutation Data_encoding.t + + val pp_refutation : Format.formatter -> refutation -> unit + + type reason = Conflict_resolved | Timeout + + val pp_reason : Format.formatter -> reason -> unit + + val reason_encoding : reason Data_encoding.t + + type game_result = Loser of {reason : reason; loser : Staker.t} | Draw + + val pp_game_result : Format.formatter -> game_result -> unit + + val game_result_encoding : game_result Data_encoding.t + + type status = Ongoing | Ended of game_result + + val pp_status : Format.formatter -> status -> unit + + val status_encoding : status Data_encoding.t + + val initial : + Inbox.history_proof -> + Dal.Slots_history.t -> + start_level:Raw_level.t -> + parent_commitment:Commitment.t -> + defender_commitment:Commitment.t -> + refuter:Staker.t -> + defender:Staker.t -> + default_number_of_sections:int -> + t + + val play : + Kind.t -> + Dal.parameters -> + dal_activation_level:Raw_level.t option -> + dal_attestation_lag:int -> + dal_number_of_slots:int -> + stakers:Index.t -> + Metadata.t -> + t -> + step:step -> + choice:Tick.t -> + is_reveal_enabled:is_reveal_enabled -> + dal_attested_slots_validity_lag:int -> + (game_result, t) Either.t tzresult Lwt.t + + type timeout = {alice : int; bob : int; last_turn_level : Raw_level.t} + + val timeout_encoding : timeout Data_encoding.t + + type error += + | Dissection_choice_not_found of Tick.t + | Proof_unexpected_section_size of Z.t + | Proof_start_state_hash_mismatch of { + start_state_hash : State_hash.t option; + start_proof : State_hash.t; + } + | Proof_stop_state_hash_failed_to_refute of { + stop_state_hash : State_hash.t option; + stop_proof : State_hash.t option; + } + | Proof_stop_state_hash_failed_to_validate of { + stop_state_hash : State_hash.t option; + stop_proof : State_hash.t option; + } + | Dissecting_during_final_move + + module Internal_for_tests : sig + val check_dissection : + default_number_of_sections:int -> + start_chunk:dissection_chunk -> + stop_chunk:dissection_chunk -> + dissection_chunk list -> + unit tzresult + end + end + + module Stake_storage : sig + val find_staker : + context -> + t -> + Staker.t -> + (context * Commitment.Hash.t option) tzresult Lwt.t + + val publish_commitment : + context -> + t -> + Staker.t -> + Commitment.t -> + (Commitment.Hash.t * Raw_level.t * context * Receipt.balance_updates) + tzresult + Lwt.t + + val cement_commitment : + context -> + t -> + (context * Commitment.t * Commitment.Hash.t) tzresult Lwt.t + + val withdraw_stake : + context -> + t -> + Staker.t -> + (context * Receipt.balance_updates) tzresult Lwt.t + + val commitments_uncarbonated : + context -> + rollup:t -> + inbox_level:Raw_level.t -> + Commitment.Hash.t list option tzresult Lwt.t + + val stakers_ids_uncarbonated : + context -> + rollup:t -> + commitment:Commitment.Hash.t -> + Staker.Index.t list tzresult Lwt.t + + val staker_id_uncarbonated : + context -> + rollup:t -> + pkh:public_key_hash -> + Staker.Index.t tzresult Lwt.t + + val stakers_pkhs_uncarbonated : + context -> rollup:t -> public_key_hash list Lwt.t + end + + module Refutation_storage : sig + type point = {commitment : Commitment.t; hash : Commitment.Hash.t} + + type conflict_point = point * point + + type conflict = { + other : Staker.t; + their_commitment : Commitment.t; + our_commitment : Commitment.t; + parent_commitment : Commitment.Hash.t; + } + + val conflict_encoding : conflict Data_encoding.t + + val conflicting_stakers_uncarbonated : + context -> t -> Staker.t -> conflict list tzresult Lwt.t + + val get_ongoing_games_for_staker : + context -> + t -> + Staker.t -> + ((Game.t * Game.Index.t) list * context) tzresult Lwt.t + + val find_game : + context -> t -> Game.Index.t -> (context * Game.t option) tzresult Lwt.t + + val start_game : + context -> + t -> + player:public_key_hash * Commitment.Hash.t -> + opponent:public_key_hash * Commitment.Hash.t -> + context tzresult Lwt.t + + val game_move : + context -> + t -> + player:Staker.t -> + opponent:Staker.t -> + step:Game.step -> + choice:Tick.t -> + (Game.game_result option * context) tzresult Lwt.t + + val get_timeout : + context -> t -> Game.Index.t -> (Game.timeout * context) tzresult Lwt.t + + val timeout : + context -> + t -> + Game.Index.t -> + (Game.game_result * context) tzresult Lwt.t + + val apply_game_result : + context -> + t -> + Game.Index.t -> + Game.game_result -> + (Game.status * context * Receipt.balance_updates) tzresult Lwt.t + + module Internal_for_tests : sig + val get_conflict_point : + context -> + t -> + Staker.t -> + Staker.t -> + (conflict_point * context) tzresult Lwt.t + end + end + + val rpc_arg : t RPC_arg.t + + val list_unaccounted : context -> t list tzresult Lwt.t + + val genesis_info : + context -> rollup -> (context * Commitment.genesis_info) tzresult Lwt.t + + (** This module discloses definitions that are only useful for tests and + must not be used otherwise. *) + module Internal_for_tests : sig + val originated_sc_rollup : Origination_nonce.Internal_for_tests.t -> t + end +end + +(** This module re-exports definitions from {!Destination_repr}. *) +module Destination : sig + type t = + | Contract of Contract.t + | Sc_rollup of Sc_rollup.t + | Zk_rollup of Zk_rollup.t + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val compare : t -> t -> int + + val equal : t -> t -> bool + + val to_b58check : t -> string + + val of_b58check : string -> t tzresult + + val in_memory_size : t -> Cache_memory_helpers.sint + + val must_exist : context -> t -> context tzresult Lwt.t + + type error += Invalid_destination_b58check of string +end + +(** See {!Block_payload_repr}. *) +module Block_payload : sig + (** See {!Block_payload_repr.hash}. *) + val hash : + predecessor_hash:Block_hash.t -> + payload_round:Round.t -> + Operation_list_hash.elt list -> + Block_payload_hash.t +end + +(** This module re-exports definitions from {!Block_header_repr}. *) +module Block_header : sig + type contents = { + payload_hash : Block_payload_hash.t; + payload_round : Round.t; + seed_nonce_hash : Nonce_hash.t option; + proof_of_work_nonce : bytes; + per_block_votes : Per_block_votes_repr.per_block_votes; + } + + type protocol_data = {contents : contents; signature : signature} + + type t = {shell : Block_header.shell_header; protocol_data : protocol_data} + + type block_header = t + + type raw = Block_header.t + + type shell_header = Block_header.shell_header + + type block_watermark = Block_header of Chain_id.t + + val to_watermark : block_watermark -> Signature.watermark + + val of_watermark : Signature.watermark -> block_watermark option + + module Proof_of_work : sig + val check_hash : Block_hash.t -> int64 -> bool + + val check_header_proof_of_work_stamp : + shell_header -> contents -> int64 -> bool + + val check_proof_of_work_stamp : + proof_of_work_threshold:int64 -> block_header -> unit tzresult + end + + val raw : block_header -> raw + + val hash : block_header -> Block_hash.t + + val hash_raw : raw -> Block_hash.t + + val encoding : block_header Data_encoding.encoding + + val raw_encoding : raw Data_encoding.t + + val contents_encoding : contents Data_encoding.t + + val unsigned_encoding : (shell_header * contents) Data_encoding.t + + val protocol_data_encoding : protocol_data Data_encoding.encoding + + val shell_header_encoding : shell_header Data_encoding.encoding + + (** The maximum size of block headers in bytes *) + val max_header_length : int + + type error += Invalid_stamp + + val check_timestamp : + Round.round_durations -> + timestamp:Time.t -> + round:Round.t -> + predecessor_timestamp:Time.t -> + predecessor_round:Round.t -> + unit tzresult + + val check_signature : t -> Chain_id.t -> public_key -> unit tzresult + + val begin_validate_block_header : + block_header:t -> + chain_id:Chain_id.t -> + predecessor_timestamp:Time.t -> + predecessor_round:Round.t -> + fitness:Fitness.t -> + timestamp:Time.t -> + delegate_pk:public_key -> + round_durations:Round.round_durations -> + proof_of_work_threshold:int64 -> + expected_commitment:bool -> + unit tzresult +end + +(** This module re-exports definitions from {!Cache_repr}. *) +module Cache : sig + type size = int + + type index = int + + type cache_nonce + + module Admin : sig + type key + + type value + + val pp : Format.formatter -> context -> unit + + val sync : context -> cache_nonce -> context Lwt.t + + val future_cache_expectation : + ?blocks_before_activation:int32 -> + context -> + time_in_blocks:int -> + context tzresult Lwt.t + + val cache_size : context -> cache_index:int -> size option + + val cache_size_limit : context -> cache_index:int -> size option + + val value_of_key : + context -> Context.Cache.key -> Context.Cache.value tzresult Lwt.t + end + + type namespace = private string + + val create_namespace : string -> namespace + + type identifier = string + + module type CLIENT = sig + type cached_value + + val cache_index : index + + val namespace : namespace + + val value_of_identifier : + context -> identifier -> cached_value tzresult Lwt.t + end + + module type INTERFACE = sig + type cached_value + + val update : + context -> identifier -> (cached_value * size) option -> context tzresult + + val find : context -> identifier -> cached_value option tzresult Lwt.t + + val list_identifiers : context -> (string * int) list + + val identifier_rank : context -> string -> int option + + val size : context -> int + + val size_limit : context -> int + end + + val register_exn : + (module CLIENT with type cached_value = 'a) -> + (module INTERFACE with type cached_value = 'a) + + val cache_nonce_from_block_header : + Block_header.shell_header -> Block_header.contents -> cache_nonce +end + +(** This module re-exports definitions from {!Operation_repr.Kind}. *) +module Kind : sig + type preattestation_consensus_kind = Preattestation_consensus_kind + + type attestation_consensus_kind = Attestation_consensus_kind + + type 'a consensus = + | Preattestation_kind : preattestation_consensus_kind consensus + | Attestation_kind : attestation_consensus_kind consensus + + type preattestation = preattestation_consensus_kind consensus + + type attestation = attestation_consensus_kind consensus + + type seed_nonce_revelation = Seed_nonce_revelation_kind + + type vdf_revelation = Vdf_revelation_kind + + type 'a double_consensus_operation_evidence = + | Double_consensus_operation_evidence + + type double_attestation_evidence = + attestation_consensus_kind double_consensus_operation_evidence + + type double_preattestation_evidence = + preattestation_consensus_kind double_consensus_operation_evidence + + type double_baking_evidence = Double_baking_evidence_kind + + type activate_account = Activate_account_kind + + type proposals = Proposals_kind + + type ballot = Ballot_kind + + type reveal = Reveal_kind + + type transaction = Transaction_kind + + type origination = Origination_kind + + type delegation = Delegation_kind + + type event = Event_kind + + type set_deposits_limit = Set_deposits_limit_kind + + type increase_paid_storage = Increase_paid_storage_kind + + type update_consensus_key = Update_consensus_key_kind + + type drain_delegate = Drain_delegate_kind + + type failing_noop = Failing_noop_kind + + type register_global_constant = Register_global_constant_kind + + type transfer_ticket = Transfer_ticket_kind + + type dal_publish_commitment = Dal_publish_commitment_kind + + type sc_rollup_originate = Sc_rollup_originate_kind + + type sc_rollup_add_messages = Sc_rollup_add_messages_kind + + type sc_rollup_cement = Sc_rollup_cement_kind + + type sc_rollup_publish = Sc_rollup_publish_kind + + type sc_rollup_refute = Sc_rollup_refute_kind + + type sc_rollup_timeout = Sc_rollup_timeout_kind + + type sc_rollup_execute_outbox_message = + | Sc_rollup_execute_outbox_message_kind + + type sc_rollup_recover_bond = Sc_rollup_recover_bond_kind + + type zk_rollup_origination = Zk_rollup_origination_kind + + type zk_rollup_publish = Zk_rollup_publish_kind + + type zk_rollup_update = Zk_rollup_update_kind + + type 'a manager = + | Reveal_manager_kind : reveal manager + | Transaction_manager_kind : transaction manager + | Origination_manager_kind : origination manager + | Delegation_manager_kind : delegation manager + | Event_manager_kind : event manager + | Register_global_constant_manager_kind : register_global_constant manager + | Set_deposits_limit_manager_kind : set_deposits_limit manager + | Increase_paid_storage_manager_kind : increase_paid_storage manager + | Update_consensus_key_manager_kind : update_consensus_key manager + | Transfer_ticket_manager_kind : transfer_ticket manager + | Dal_publish_commitment_manager_kind : dal_publish_commitment manager + | Sc_rollup_originate_manager_kind : sc_rollup_originate manager + | Sc_rollup_add_messages_manager_kind : sc_rollup_add_messages manager + | Sc_rollup_cement_manager_kind : sc_rollup_cement manager + | Sc_rollup_publish_manager_kind : sc_rollup_publish manager + | Sc_rollup_refute_manager_kind : sc_rollup_refute manager + | Sc_rollup_timeout_manager_kind : sc_rollup_timeout manager + | Sc_rollup_execute_outbox_message_manager_kind + : sc_rollup_execute_outbox_message manager + | Sc_rollup_recover_bond_manager_kind : sc_rollup_recover_bond manager + | Zk_rollup_origination_manager_kind : zk_rollup_origination manager + | Zk_rollup_publish_manager_kind : zk_rollup_publish manager + | Zk_rollup_update_manager_kind : zk_rollup_update manager +end + +(** All the definitions below are re-exported from {!Operation_repr}. *) + +type 'a consensus_operation_type = + | Attestation : Kind.attestation consensus_operation_type + | Preattestation : Kind.preattestation consensus_operation_type + +type consensus_content = { + slot : Slot.t; + level : Raw_level.t; + (* The level is not required to validate an attestation when it corresponds + to the current payload, but if we want to filter attestations, we need + the level. *) + round : Round.t; + block_payload_hash : Block_payload_hash.t; +} + +val consensus_content_encoding : consensus_content Data_encoding.t + +val pp_consensus_content : Format.formatter -> consensus_content -> unit + +type dal_content = {attestation : Dal.Attestation.t} + +type 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; +} + +and 'kind protocol_data = { + contents : 'kind contents_list; + signature : signature option; +} + +and _ contents_list = + | Single : 'kind contents -> 'kind contents_list + | Cons : + 'kind Kind.manager contents * 'rest Kind.manager contents_list + -> ('kind * 'rest) Kind.manager contents_list + +and _ contents = + | Preattestation : consensus_content -> Kind.preattestation contents + | Attestation : { + consensus_content : consensus_content; + dal_content : dal_content option; + } + -> Kind.attestation contents + | Seed_nonce_revelation : { + level : Raw_level.t; + nonce : Nonce.t; + } + -> Kind.seed_nonce_revelation contents + | Vdf_revelation : { + solution : Seed.vdf_solution; + } + -> Kind.vdf_revelation contents + | Double_preattestation_evidence : { + op1 : Kind.preattestation operation; + op2 : Kind.preattestation operation; + } + -> Kind.double_preattestation_evidence contents + | Double_attestation_evidence : { + op1 : Kind.attestation operation; + op2 : Kind.attestation operation; + } + -> Kind.double_attestation_evidence contents + | Double_baking_evidence : { + bh1 : Block_header.t; + bh2 : Block_header.t; + } + -> Kind.double_baking_evidence contents + | Activate_account : { + id : Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + } + -> Kind.activate_account contents + | Proposals : { + source : public_key_hash; + period : int32; + proposals : Protocol_hash.t list; + } + -> Kind.proposals contents + | Ballot : { + source : public_key_hash; + period : int32; + proposal : Protocol_hash.t; + ballot : Vote.ballot; + } + -> Kind.ballot contents + | Drain_delegate : { + consensus_key : Signature.Public_key_hash.t; + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + -> Kind.drain_delegate contents + | Failing_noop : string -> Kind.failing_noop contents + | Manager_operation : { + source : public_key_hash; + fee : Tez.t; + counter : Manager_counter.t; + operation : 'kind manager_operation; + gas_limit : Gas.Arith.integral; + storage_limit : Z.t; + } + -> 'kind Kind.manager contents + +and _ manager_operation = + | Reveal : public_key -> Kind.reveal manager_operation + | Transaction : { + amount : Tez.t; + parameters : Script.lazy_expr; + entrypoint : Entrypoint.t; + destination : Contract.t; + } + -> Kind.transaction manager_operation + | Origination : { + delegate : public_key_hash option; + script : Script.t; + credit : Tez.t; + } + -> Kind.origination manager_operation + | Delegation : public_key_hash option -> Kind.delegation manager_operation + | Register_global_constant : { + value : Script.lazy_expr; + } + -> Kind.register_global_constant manager_operation + | Set_deposits_limit : + Tez.t option + -> Kind.set_deposits_limit manager_operation + | Increase_paid_storage : { + amount_in_bytes : Z.t; + destination : Contract_hash.t; + } + -> Kind.increase_paid_storage manager_operation + | Update_consensus_key : + Signature.Public_key.t + -> Kind.update_consensus_key manager_operation + | Transfer_ticket : { + contents : Script.lazy_expr; + ty : Script.lazy_expr; + ticketer : Contract.t; + amount : Ticket_amount.t; + destination : Contract.t; + entrypoint : Entrypoint.t; + } + -> Kind.transfer_ticket manager_operation + | Dal_publish_commitment : + Dal.Operations.Publish_commitment.t + -> Kind.dal_publish_commitment manager_operation + | Sc_rollup_originate : { + kind : Sc_rollup.Kind.t; + boot_sector : string; + parameters_ty : Script.lazy_expr; + whitelist : Sc_rollup.Whitelist.t option; + } + -> Kind.sc_rollup_originate manager_operation + | Sc_rollup_add_messages : { + messages : string list; + } + -> Kind.sc_rollup_add_messages manager_operation + | Sc_rollup_cement : { + rollup : Sc_rollup.t; + } + -> Kind.sc_rollup_cement manager_operation + | Sc_rollup_publish : { + rollup : Sc_rollup.t; + commitment : Sc_rollup.Commitment.t; + } + -> Kind.sc_rollup_publish manager_operation + | Sc_rollup_refute : { + rollup : Sc_rollup.t; + opponent : Sc_rollup.Staker.t; + refutation : Sc_rollup.Game.refutation; + } + -> Kind.sc_rollup_refute manager_operation + | Sc_rollup_timeout : { + rollup : Sc_rollup.t; + stakers : Sc_rollup.Game.Index.t; + } + -> Kind.sc_rollup_timeout manager_operation + | Sc_rollup_execute_outbox_message : { + rollup : Sc_rollup.t; + cemented_commitment : Sc_rollup.Commitment.Hash.t; + output_proof : string; + } + -> Kind.sc_rollup_execute_outbox_message manager_operation + | Sc_rollup_recover_bond : { + sc_rollup : Sc_rollup.t; + staker : Signature.Public_key_hash.t; + } + -> Kind.sc_rollup_recover_bond manager_operation + | Zk_rollup_origination : { + public_parameters : Plonk.public_parameters; + circuits_info : [`Public | `Private | `Fee] Zk_rollup.Account.SMap.t; + init_state : Zk_rollup.State.t; + nb_ops : int; + } + -> Kind.zk_rollup_origination manager_operation + | Zk_rollup_publish : { + zk_rollup : Zk_rollup.t; + ops : (Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list; + } + -> Kind.zk_rollup_publish manager_operation + | Zk_rollup_update : { + zk_rollup : Zk_rollup.t; + update : Zk_rollup.Update.t; + } + -> Kind.zk_rollup_update manager_operation + +type packed_manager_operation = + | Manager : 'kind manager_operation -> packed_manager_operation + +type packed_contents = Contents : 'kind contents -> packed_contents + +type packed_contents_list = + | Contents_list : 'kind contents_list -> packed_contents_list + +type packed_protocol_data = + | Operation_data : 'kind protocol_data -> packed_protocol_data + +type packed_operation = { + shell : Operation.shell_header; + protocol_data : packed_protocol_data; +} + +val manager_kind : 'kind manager_operation -> 'kind Kind.manager + +(** This module re-exports definitions from {!Operation_repr}. *) +module Operation : sig + type nonrec 'kind contents = 'kind contents + + type nonrec packed_contents = packed_contents + + val contents_encoding : packed_contents Data_encoding.t + + val contents_encoding_with_legacy_attestation_name : + packed_contents Data_encoding.t + + type nonrec 'kind protocol_data = 'kind protocol_data + + type nonrec packed_protocol_data = packed_protocol_data + + type consensus_watermark = + | Attestation of Chain_id.t + | Preattestation of Chain_id.t + + val to_watermark : consensus_watermark -> Signature.watermark + + val of_watermark : Signature.watermark -> consensus_watermark option + + val protocol_data_encoding : packed_protocol_data Data_encoding.t + + val protocol_data_encoding_with_legacy_attestation_name : + packed_protocol_data Data_encoding.t + + val unsigned_encoding : + (Operation.shell_header * packed_contents_list) Data_encoding.t + + val unsigned_encoding_with_legacy_attestation_name : + (Operation.shell_header * packed_contents_list) Data_encoding.t + + type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} + + val raw_encoding : raw Data_encoding.t + + val contents_list_encoding : packed_contents_list Data_encoding.t + + val contents_list_encoding_with_legacy_attestation_name : + packed_contents_list Data_encoding.t + + type 'kind t = 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; + } + + type nonrec packed = packed_operation + + val encoding : packed Data_encoding.t + + val encoding_with_legacy_attestation_name : packed Data_encoding.t + + val raw : _ operation -> raw + + val hash : _ operation -> Operation_hash.t + + val hash_raw : raw -> Operation_hash.t + + val hash_packed : packed_operation -> Operation_hash.t + + val acceptable_pass : packed_operation -> int option + + val compare_by_passes : packed_operation -> packed_operation -> int + + type error += Missing_signature (* `Permanent *) + + type error += Invalid_signature (* `Permanent *) + + val unsigned_operation_length : _ operation -> int + + val check_signature : public_key -> Chain_id.t -> _ operation -> unit tzresult + + val pack : 'kind operation -> packed_operation + + val compare : + Operation_hash.t * packed_operation -> + Operation_hash.t * packed_operation -> + int + + type ('a, 'b) eq = Eq : ('a, 'a) eq + + val equal : 'a operation -> 'b operation -> ('a, 'b) eq option + + module Encoding : sig + type 'b case = + | Case : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_contents -> 'b contents option; + proj : 'b contents -> 'a; + inj : 'a -> 'b contents; + } + -> 'b case + + val preendorsement_case : Kind.preattestation case + + val preattestation_case : Kind.preattestation case + + val endorsement_case : Kind.attestation case + + val attestation_case : Kind.attestation case + + val endorsement_with_dal_case : Kind.attestation case + + val attestation_with_dal_case : Kind.attestation case + + val seed_nonce_revelation_case : Kind.seed_nonce_revelation case + + val vdf_revelation_case : Kind.vdf_revelation case + + val double_preendorsement_evidence_case : + Kind.double_preattestation_evidence case + + val double_preattestation_evidence_case : + Kind.double_preattestation_evidence case + + val double_endorsement_evidence_case : Kind.double_attestation_evidence case + + val double_attestation_evidence_case : Kind.double_attestation_evidence case + + val double_baking_evidence_case : Kind.double_baking_evidence case + + val activate_account_case : Kind.activate_account case + + val proposals_case : Kind.proposals case + + val ballot_case : Kind.ballot case + + val drain_delegate_case : Kind.drain_delegate case + + val failing_noop_case : Kind.failing_noop case + + val reveal_case : Kind.reveal Kind.manager case + + val transaction_case : Kind.transaction Kind.manager case + + val origination_case : Kind.origination Kind.manager case + + val delegation_case : Kind.delegation Kind.manager case + + val update_consensus_key_case : Kind.update_consensus_key Kind.manager case + + val transfer_ticket_case : Kind.transfer_ticket Kind.manager case + + val dal_publish_commitment_case : + Kind.dal_publish_commitment Kind.manager case + + val register_global_constant_case : + Kind.register_global_constant Kind.manager case + + val set_deposits_limit_case : Kind.set_deposits_limit Kind.manager case + + val increase_paid_storage_case : + Kind.increase_paid_storage Kind.manager case + + val sc_rollup_originate_case : Kind.sc_rollup_originate Kind.manager case + + val sc_rollup_add_messages_case : + Kind.sc_rollup_add_messages Kind.manager case + + val sc_rollup_cement_case : Kind.sc_rollup_cement Kind.manager case + + val sc_rollup_publish_case : Kind.sc_rollup_publish Kind.manager case + + val sc_rollup_refute_case : Kind.sc_rollup_refute Kind.manager case + + val sc_rollup_timeout_case : Kind.sc_rollup_timeout Kind.manager case + + val sc_rollup_execute_outbox_message_case : + Kind.sc_rollup_execute_outbox_message Kind.manager case + + val sc_rollup_recover_bond_case : + Kind.sc_rollup_recover_bond Kind.manager case + + val zk_rollup_origination_case : + Kind.zk_rollup_origination Kind.manager case + + val zk_rollup_publish_case : Kind.zk_rollup_publish Kind.manager case + + val zk_rollup_update_case : Kind.zk_rollup_update Kind.manager case + + module Manager_operations : sig + type 'b case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_manager_operation -> 'kind manager_operation option; + proj : 'kind manager_operation -> 'a; + inj : 'a -> 'kind manager_operation; + } + -> 'kind case + + val reveal_case : Kind.reveal case + + val transaction_case : Kind.transaction case + + val origination_case : Kind.origination case + + val delegation_case : Kind.delegation case + + val update_consensus_key_tag : int + + val update_consensus_key_case : Kind.update_consensus_key case + + val register_global_constant_case : Kind.register_global_constant case + + val set_deposits_limit_case : Kind.set_deposits_limit case + + val increase_paid_storage_case : Kind.increase_paid_storage case + + val transfer_ticket_case : Kind.transfer_ticket case + + val dal_publish_commitment_case : Kind.dal_publish_commitment case + + val sc_rollup_originate_case : Kind.sc_rollup_originate case + + val sc_rollup_add_messages_case : Kind.sc_rollup_add_messages case + + val sc_rollup_cement_case : Kind.sc_rollup_cement case + + val sc_rollup_publish_case : Kind.sc_rollup_publish case + + val sc_rollup_refute_case : Kind.sc_rollup_refute case + + val sc_rollup_timeout_case : Kind.sc_rollup_timeout case + + val sc_rollup_execute_outbox_message_case : + Kind.sc_rollup_execute_outbox_message case + + val sc_rollup_recover_bond_case : Kind.sc_rollup_recover_bond case + + val zk_rollup_origination_case : Kind.zk_rollup_origination case + + val zk_rollup_publish_case : Kind.zk_rollup_publish case + + val zk_rollup_update_case : Kind.zk_rollup_update case + end + end + + val of_list : packed_contents list -> packed_contents_list tzresult + + val to_list : packed_contents_list -> packed_contents list +end + +(** This module re-exports definitions from {!Stake_storage}, + {!Delegate_storage} and {!Delegate}. *) +module Stake_distribution : sig + val baking_rights_owner : + context -> + Level.t -> + round:Round.t -> + (context * Slot.t * Consensus_key.pk) tzresult Lwt.t + + val slot_owner : + context -> Level.t -> Slot.t -> (context * Consensus_key.pk) tzresult Lwt.t + + (** See {!Delegate_sampler.load_sampler_for_cycle}. *) + val load_sampler_for_cycle : context -> Cycle.t -> context tzresult Lwt.t + + val get_total_frozen_stake : context -> Cycle.t -> Tez.t tzresult Lwt.t + + module For_RPC : sig + val delegate_current_baking_power : + context -> Signature.public_key_hash -> int64 tzresult Lwt.t + end + + module Internal_for_tests : sig + val get_selected_distribution : + context -> + Cycle.t -> + (Signature.public_key_hash * Stake_repr.t) list tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Commitment_repr} and, + {!Commitment_storage}. *) +module Commitment : sig + type t = {blinded_public_key_hash : Blinded_public_key_hash.t; amount : Tez.t} + + (** See {!Commitment_storage.exists}. *) + val exists : context -> Blinded_public_key_hash.t -> bool Lwt.t + + val encoding : t Data_encoding.t + + val fold : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Blinded_public_key_hash.t -> Tez_repr.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t +end + +(** This module re-exports definitions from {!Bootstrap_storage}. *) +module Bootstrap : sig + val cycle_end : context -> Cycle.t -> context tzresult Lwt.t +end + +(** This module re-exports definitions from {!Migration_repr}. *) +module Migration : sig + type origination_result = { + balance_updates : Receipt.balance_updates; + originated_contracts : Contract_hash.t list; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + } +end + +(** Create an [Alpha_context.t] from an untyped context (first block in the chain only). *) +val prepare_first_block : + Chain_id.t -> + Context.t -> + typecheck_smart_contract: + (context -> + Script.t -> + ((Script.t * Lazy_storage.diffs option) * context) tzresult Lwt.t) -> + typecheck_smart_rollup:(context -> Script.expr -> context tzresult) -> + level:Int32.t -> + timestamp:Time.t -> + predecessor:Block_hash.t -> + context tzresult Lwt.t + +(** Create an [Alpha_context.t] from an untyped context. *) +val prepare : + Context.t -> + level:Int32.t -> + predecessor_timestamp:Time.t -> + timestamp:Time.t -> + (context * Receipt.balance_updates * Migration.origination_result list) + tzresult + Lwt.t + +(** All the definitions below are re-exported from {!Raw_context}. *) + +val activate : context -> Protocol_hash.t -> context Lwt.t + +val reset_internal_nonce : context -> context + +val fresh_internal_nonce : context -> (context * int) tzresult + +val record_internal_nonce : context -> int -> context + +val internal_nonce_already_recorded : context -> int -> bool + +val description : context Storage_description.t + +val record_non_consensus_operation_hash : context -> Operation_hash.t -> context + +val non_consensus_operations : context -> Operation_hash.t list + +val record_dictator_proposal_seen : t -> t + +val dictator_proposal_seen : t -> bool + +(** Finalize an {{!t} [Alpha_context.t]}, producing a [validation_result]. + *) +val finalize : + ?commit_message:string -> context -> Fitness.raw -> Updater.validation_result + +(** Should only be used by [Main.current_context] to return a context usable for RPCs *) +val current_context : context -> Context.t + +(** This module re-exports definitions from {!Parameters_repr}. *) +module Parameters : sig + type bootstrap_account = { + public_key_hash : public_key_hash; + public_key : public_key option; + amount : Tez.t; + delegate_to : public_key_hash option; + consensus_key : public_key option; + } + + type bootstrap_contract = { + delegate : public_key_hash option; + amount : Tez.t; + script : Script.t; + hash : Contract_hash.t option; + } + + type bootstrap_smart_rollup = { + address : Sc_rollup.Address.t; + pvm_kind : Sc_rollup.Kind.t; + boot_sector : string; + parameters_ty : Script.lazy_expr; + whitelist : Sc_rollup.Whitelist.t option; + } + + type t = { + bootstrap_accounts : bootstrap_account list; + bootstrap_contracts : bootstrap_contract list; + bootstrap_smart_rollups : bootstrap_smart_rollup list; + commitments : Commitment.t list; + constants : Constants.Parametric.t; + security_deposit_ramp_up_cycles : int option; + no_reward_cycles : int option; + } + + val bootstrap_account_encoding : bootstrap_account Data_encoding.t + + val encoding : t Data_encoding.t +end + +(** This module re-exports definitions from {!Votes_EMA_repr} *) +module Votes_EMA : sig + module type T = sig + type t + + val of_int32 : Int32.t -> t tzresult Lwt.t + + val zero : t + + val to_int32 : t -> Int32.t + + val encoding : t Data_encoding.t + + val ( < ) : t -> Int32.t -> bool + + val update_ema_up : t -> t + + val update_ema_down : t -> t + end +end + +(** This module re-exports definitions from {!Per_block_votes_repr}. *) +module Per_block_votes : sig + type per_block_vote = Per_block_votes_repr.per_block_vote = + | Per_block_vote_on + | Per_block_vote_off + | Per_block_vote_pass + + type per_block_votes = Per_block_votes_repr.per_block_votes = { + liquidity_baking_vote : per_block_vote; + adaptive_issuance_vote : per_block_vote; + } + + val liquidity_baking_vote_encoding : per_block_vote Data_encoding.encoding + + val adaptive_issuance_vote_encoding : per_block_vote Data_encoding.encoding + + val per_block_votes_encoding : per_block_votes Data_encoding.encoding + + module Liquidity_baking_toggle_EMA : Votes_EMA.T + + module Adaptive_issuance_launch_EMA : Votes_EMA.T + + val compute_new_liquidity_baking_ema : + per_block_vote:per_block_vote -> + Liquidity_baking_toggle_EMA.t -> + Liquidity_baking_toggle_EMA.t + + val compute_new_adaptive_issuance_ema : + per_block_vote:per_block_vote -> + Adaptive_issuance_launch_EMA.t -> + Adaptive_issuance_launch_EMA.t +end + +(** This module re-exports definitions from {!Liquidity_baking_storage}. *) +module Liquidity_baking : sig + val get_cpmm_address : context -> Contract_hash.t tzresult Lwt.t + + val on_subsidy_allowed : + context -> + per_block_vote:Per_block_votes.per_block_vote -> + (context -> Contract_hash.t -> (context * 'a list) tzresult Lwt.t) -> + (context * 'a list * Per_block_votes.Liquidity_baking_toggle_EMA.t) tzresult + Lwt.t +end + +(** This module re-exports definitions from {!Adaptive_issuance_storage}. *) +module Adaptive_issuance : sig + val update_ema : + context -> + vote:Per_block_votes.per_block_vote -> + (context * Cycle.t option * Per_block_votes.Adaptive_issuance_launch_EMA.t) + tzresult + Lwt.t + + val launch_cycle : context -> Cycle.t option tzresult Lwt.t +end + +(** This module re-exports definitions from {!Ticket_storage}. *) +module Ticket_balance : sig + type error += + | Negative_ticket_balance of {key : Ticket_hash.t; balance : Z.t} + | Used_storage_space_underflow + + val adjust_balance : + context -> Ticket_hash.t -> delta:Z.t -> (Z.t * context) tzresult Lwt.t + + val adjust_storage_space : + context -> storage_diff:Z.t -> (Z.t * context) tzresult Lwt.t + + val get_balance : + context -> Ticket_hash.t -> (Z.t option * context) tzresult Lwt.t + + (** This module discloses definitions that are only useful for tests and + must not be used otherwise. *) + module Internal_for_tests : sig + val used_storage_space : context -> Z.t tzresult Lwt.t + + val paid_storage_space : context -> Z.t tzresult Lwt.t + end +end + +module First_level_of_protocol : sig + (** Get the level of the first block of this protocol. *) + val get : context -> Raw_level.t tzresult Lwt.t +end + +(** This module re-exports definitions from {!Raw_context.Consensus}. *) +module Consensus : sig + include + Raw_context.CONSENSUS + with type t := t + and type slot := Slot.t + and type 'a slot_map := 'a Slot.Map.t + and type slot_set := Slot.Set.t + and type round := Round.t + and type consensus_pk := Consensus_key.pk + + (** [store_attestation_branch context branch] sets the "attestation branch" + (see {!Storage.Tenderbake.Attestation_branch} to [branch] in both the disk + storage and RAM. *) + val store_attestation_branch : + context -> Block_hash.t * Block_payload_hash.t -> context Lwt.t +end + +(** This module re-exports definitions from {!Token}. *) +module Token : sig + type container = + [ `Contract of Contract.t + | `Collected_commitments of Blinded_public_key_hash.t + | `Frozen_deposits of Receipt.frozen_staker + | `Unstaked_frozen_deposits of Receipt.unstaked_frozen_staker * Cycle.t + | `Block_fees + | `Frozen_bonds of Contract.t * Bond_id.t ] + + type giver = + [ `Invoice + | `Bootstrap + | `Initial_commitments + | `Revelation_rewards + | `Attesting_rewards + | `Baking_rewards + | `Baking_bonuses + | `Minted + | `Liquidity_baking_subsidies + | `Sc_rollup_refutation_rewards + | container ] + + type receiver = + [ `Storage_fees + | `Double_signing_punishments + | `Lost_attesting_rewards of public_key_hash * bool * bool + | `Burned + | `Sc_rollup_refutation_punishments + | container ] + + val balance : + context -> + [< `Block_fees | `Collected_commitments of Blinded_public_key_hash.t] -> + (context * Tez.t) tzresult Lwt.t + + val transfer_n : + ?origin:Receipt.update_origin -> + context -> + ([< giver] * Tez.t) list -> + [< receiver] -> + (context * Receipt.balance_updates) tzresult Lwt.t + + val transfer : + ?origin:Receipt.update_origin -> + context -> + [< giver] -> + [< receiver] -> + Tez.t -> + (context * Receipt.balance_updates) tzresult Lwt.t + + module Internal_for_tests : sig + val allocated : context -> container -> (context * bool) tzresult Lwt.t + + type container_with_balance = + [ `Contract of Contract.t + | `Collected_commitments of Blinded_public_key_hash.t + | `Block_fees + | `Frozen_bonds of Contract.t * Bond_id.t ] + + val balance : + context -> [< container_with_balance] -> (context * Tez.t) tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Unstake_requests_storage}. *) +module Unstake_requests : sig + type finalizable = (public_key_hash * Cycle.t * Tez.t) list + + type stored_requests = private { + delegate : public_key_hash; + requests : (Cycle.t * Tez.t) list; + } + + type prepared_finalize_unstake = { + finalizable : finalizable; + unfinalizable : stored_requests; + } + + val prepared_finalize_unstake_encoding : + prepared_finalize_unstake Data_encoding.encoding + + val prepare_finalize_unstake : + context -> Contract.t -> prepared_finalize_unstake option tzresult Lwt.t + + module For_RPC : sig + val apply_slash_to_unstaked_unfinalizable : + context -> + delegate:public_key_hash -> + requests:(Cycle.t * Tez.t) list -> + (Cycle.t * Tez.t) list tzresult Lwt.t + + val apply_slash_to_unstaked_unfinalizable_stored_requests : + context -> stored_requests -> stored_requests tzresult Lwt.t + end +end + +module Unstaked_frozen_deposits : sig + val balance : context -> public_key_hash -> Cycle.t -> Tez.t tzresult Lwt.t +end + +(** This module re-exports definitions from {!Staking_pseudotokens_storage}. *) +module Staking_pseudotokens : sig + module For_RPC : sig + val staked_balance : + context -> + contract:Contract.t -> + delegate:public_key_hash -> + Tez.t tzresult Lwt.t + + val staking_pseudotokens_balance : + context -> delegator:Contract.t -> Staking_pseudotoken.t tzresult Lwt.t + + val get_frozen_deposits_pseudotokens : + context -> + delegate:Signature.public_key_hash -> + Staking_pseudotoken.t tzresult Lwt.t + + val get_frozen_deposits_staked_tez : + context -> delegate:Signature.public_key_hash -> Tez.t tzresult Lwt.t + end +end + +(** This module re-exports definitions from {!Fees_storage}. *) +module Fees : sig + val record_paid_storage_space : + context -> Contract_hash.t -> (context * Z.t * Z.t) tzresult Lwt.t + + val record_global_constant_storage_space : context -> Z.t -> context * Z.t + + val burn_storage_fees : + ?origin:Receipt.update_origin -> + context -> + storage_limit:Z.t -> + payer:Token.giver -> + Z.t -> + (context * Z.t * Receipt.balance_updates) tzresult Lwt.t + + val burn_storage_increase_fees : + ?origin:Receipt_repr.update_origin -> + context -> + payer:Token.giver -> + Z.t -> + (context * Receipt.balance_updates) tzresult Lwt.t + + val burn_origination_fees : + ?origin:Receipt.update_origin -> + context -> + storage_limit:Z.t -> + payer:Token.giver -> + (context * Z.t * Receipt.balance_updates) tzresult Lwt.t + + val burn_sc_rollup_origination_fees : + ?origin:Receipt.update_origin -> + context -> + storage_limit:Z.t -> + payer:Token.giver -> + Z.t -> + (context * Z.t * Receipt.balance_updates) tzresult Lwt.t + + val burn_zk_rollup_origination_fees : + ?origin:Receipt.update_origin -> + context -> + storage_limit:Z.t -> + payer:Token.giver -> + Z.t -> + (context * Z.t * Receipt.balance_updates) tzresult Lwt.t + + type error += Cannot_pay_storage_fee (* `Temporary *) + + type error += Operation_quota_exceeded (* `Temporary *) + + type error += Storage_limit_too_high (* `Permanent *) + + val check_storage_limit : context -> storage_limit:Z.t -> unit tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/alpha_services.ml b/src/proto_020_PsParisC/lib_protocol/alpha_services.ml new file mode 100644 index 000000000000..000d36a5f3fb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/alpha_services.ml @@ -0,0 +1,282 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = RPC_path.open_root + +module Seed_computation = struct + module S = struct + let seed_computation_status_encoding = + let open Seed in + Data_encoding.( + union + [ + case + (Tag 0) + ~title:"Nonce revelation stage" + (obj1 (req "nonce_revelation_stage" unit)) + (function Nonce_revelation_stage -> Some () | _ -> None) + (fun () -> Nonce_revelation_stage); + case + (Tag 1) + ~title:"VDF revelation stage" + (obj2 + (req "seed_discriminant" Seed.seed_encoding) + (req "seed_challenge" Seed.seed_encoding)) + (function + | Vdf_revelation_stage {seed_discriminant; seed_challenge} -> + Some (seed_discriminant, seed_challenge) + | _ -> None) + (fun (seed_discriminant, seed_challenge) -> + Vdf_revelation_stage {seed_discriminant; seed_challenge}); + case + (Tag 2) + ~title:"Computation finished" + (obj1 (req "computation_finished" unit)) + (function Computation_finished -> Some () | _ -> None) + (fun () -> Computation_finished); + ]) + + let seed_computation = + RPC_service.get_service + ~description:"Seed computation status" + ~query:RPC_query.empty + ~output:seed_computation_status_encoding + RPC_path.(custom_root / "context" / "seed_computation") + end + + let () = + let open Services_registration in + register0 ~chunked:false S.seed_computation (fun ctxt () () -> + Seed.get_seed_computation_status ctxt) + + let get ctxt block = + RPC_context.make_call0 S.seed_computation ctxt block () () +end + +module Seed = struct + module S = struct + open Data_encoding + + let seed = + RPC_service.post_service + ~description:"Seed of the cycle to which the block belongs." + ~query:RPC_query.empty + ~input:empty + ~output:Seed.seed_encoding + RPC_path.(custom_root / "context" / "seed") + end + + let () = + let open Services_registration in + register0 ~chunked:false S.seed (fun ctxt () () -> + let l = Level.current ctxt in + Seed.for_cycle ctxt l.cycle) + + let get ctxt block = RPC_context.make_call0 S.seed ctxt block () () +end + +module Nonce = struct + type info = Revealed of Nonce.t | Missing of Nonce_hash.t | Forgotten + + let info_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Revealed" + (obj1 (req "nonce" Nonce.encoding)) + (function Revealed nonce -> Some nonce | _ -> None) + (fun nonce -> Revealed nonce); + case + (Tag 1) + ~title:"Missing" + (obj1 (req "hash" Nonce_hash.encoding)) + (function Missing nonce -> Some nonce | _ -> None) + (fun nonce -> Missing nonce); + case + (Tag 2) + ~title:"Forgotten" + empty + (function Forgotten -> Some () | _ -> None) + (fun () -> Forgotten); + ] + + module S = struct + let get = + RPC_service.get_service + ~description:"Info about the nonce of a previous block." + ~query:RPC_query.empty + ~output:info_encoding + RPC_path.(custom_root / "context" / "nonces" /: Raw_level.rpc_arg) + end + + let register () = + let open Lwt_result_syntax in + let open Services_registration in + register1 ~chunked:false S.get (fun ctxt raw_level () () -> + let level = Level.from_raw ctxt raw_level in + let*! status = Nonce.get ctxt level in + match status with + | Ok (Revealed nonce) -> return (Revealed nonce) + | Ok (Unrevealed {nonce_hash; _}) -> return (Missing nonce_hash) + | Error _ -> return Forgotten) + + let get ctxt block level = RPC_context.make_call1 S.get ctxt block level () () +end + +module Contract = Contract_services +module Constants = Constants_services +module Delegate = Delegate_services +module Voting = Voting_services +module Sapling = Sapling_services +module Adaptive_issuance = Adaptive_issuance_services + +module Liquidity_baking = struct + module S = struct + let get_cpmm_address = + RPC_service.get_service + ~description:"Liquidity baking CPMM address" + ~query:RPC_query.empty + ~output:Alpha_context.Contract.originated_encoding + RPC_path.(custom_root / "context" / "liquidity_baking" / "cpmm_address") + end + + let register () = + let open Services_registration in + register0 ~chunked:false S.get_cpmm_address (fun ctxt () () -> + Alpha_context.Liquidity_baking.get_cpmm_address ctxt) + + let get_cpmm_address ctxt block = + RPC_context.make_call0 S.get_cpmm_address ctxt block () () +end + +module Cache = struct + module S = struct + let cached_contracts = + RPC_service.get_service + ~description:"Return the list of cached contracts" + ~query:RPC_query.empty + ~output:Data_encoding.(list @@ tup2 Contract_hash.encoding int31) + RPC_path.(custom_root / "context" / "cache" / "contracts" / "all") + + let contract_cache_size = + RPC_service.get_service + ~description:"Return the size of the contract cache" + ~query:RPC_query.empty + ~output:Data_encoding.int31 + RPC_path.(custom_root / "context" / "cache" / "contracts" / "size") + + let contract_cache_size_limit = + RPC_service.get_service + ~description:"Return the size limit of the contract cache" + ~query:RPC_query.empty + ~output:Data_encoding.int31 + RPC_path.( + custom_root / "context" / "cache" / "contracts" / "size_limit") + + let contract_rank = + RPC_service.post_service + ~description: + "Return the number of cached contracts older than the provided \ + contract" + ~query:RPC_query.empty + ~input:Alpha_context.Contract.originated_encoding + ~output:Data_encoding.(option int31) + RPC_path.(custom_root / "context" / "cache" / "contracts" / "rank") + end + + let register () = + let open Services_registration in + register0 ~chunked:true S.cached_contracts (fun ctxt () () -> + Script_cache.entries ctxt |> Lwt.return) ; + register0 ~chunked:false S.contract_cache_size (fun ctxt () () -> + Script_cache.size ctxt |> return) ; + register0 ~chunked:false S.contract_cache_size_limit (fun ctxt () () -> + Script_cache.size_limit ctxt |> return) ; + register0 ~chunked:false S.contract_rank (fun ctxt () contract -> + Script_cache.contract_rank ctxt contract |> return) + + let cached_contracts ctxt block = + RPC_context.make_call0 S.cached_contracts ctxt block () () + + let contract_cache_size ctxt block = + RPC_context.make_call0 S.contract_cache_size ctxt block () () + + let contract_cache_size_limit ctxt block = + RPC_context.make_call0 S.contract_cache_size_limit ctxt block () () + + let contract_rank ctxt block contract = + RPC_context.make_call0 S.contract_rank ctxt block () contract +end + +module Denunciations = struct + type denunciations_with_key = + Signature.Public_key_hash.t * Denunciations_repr.item + + let denunciations_with_key_encoding : denunciations_with_key Data_encoding.t = + let open Data_encoding in + merge_objs + (obj1 (req "slashed_delegate" Signature.Public_key_hash.encoding)) + Denunciations_repr.item_encoding + + module S = struct + let denunciations = + let open Data_encoding in + RPC_service.get_service + ~description: + "Returns the denunciations for misbehavior in the current cycle." + ~query:RPC_query.empty + ~output:(list denunciations_with_key_encoding) + RPC_path.(custom_root / "context" / "denunciations") + end + + let register () = + let open Services_registration in + let open Lwt_result_syntax in + register0 ~chunked:false S.denunciations (fun ctxt () () -> + let*! r = + Alpha_context.Delegate.For_RPC.pending_denunciations_list ctxt + in + return r) + + let denunciations ctxt block = + RPC_context.make_call0 S.denunciations ctxt block () () +end + +let register () = + Contract.register () ; + Constants.register () ; + Delegate.register () ; + Nonce.register () ; + Voting.register () ; + Sapling.register () ; + Liquidity_baking.register () ; + Cache.register () ; + Adaptive_issuance.register () ; + Denunciations.register () diff --git a/src/proto_020_PsParisC/lib_protocol/alpha_services.mli b/src/proto_020_PsParisC/lib_protocol/alpha_services.mli new file mode 100644 index 000000000000..049064397e29 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/alpha_services.mli @@ -0,0 +1,93 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This declares Protocol RPC services. + + Protocol RPC services are read-only, and support querying the state of the + ledger (including information such as existing contracts, delegation, + voting, and so on), at a given block height. + + This is a mostly internal module used from [rpc_services] in [Main]. + *) + +open Alpha_context + +module Seed_computation : sig + val get : + 'a #RPC_context.simple -> + 'a -> + Seed.seed_computation_status shell_tzresult Lwt.t +end + +module Seed : sig + val get : 'a #RPC_context.simple -> 'a -> Seed.seed shell_tzresult Lwt.t +end + +module Nonce : sig + type info = Revealed of Nonce.t | Missing of Nonce_hash.t | Forgotten + + val get : + 'a #RPC_context.simple -> 'a -> Raw_level.t -> info shell_tzresult Lwt.t +end + +module Contract = Contract_services +module Constants = Constants_services +module Delegate = Delegate_services +module Voting = Voting_services +module Sapling = Sapling_services + +module Liquidity_baking : sig + val get_cpmm_address : + 'a #RPC_context.simple -> 'a -> Contract_hash.t shell_tzresult Lwt.t +end + +module Cache : sig + val cached_contracts : + 'a #RPC_context.simple -> + 'a -> + (Contract_hash.t * int) list shell_tzresult Lwt.t + + val contract_cache_size : + 'a #RPC_context.simple -> 'a -> int shell_tzresult Lwt.t + + val contract_cache_size_limit : + 'a #RPC_context.simple -> 'a -> int shell_tzresult Lwt.t + + val contract_rank : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + int option shell_tzresult Lwt.t +end + +module Denunciations : sig + val denunciations : + 'a #RPC_context.simple -> + 'a -> + (public_key_hash * Denunciations_repr.item) list shell_tzresult Lwt.t +end + +val register : unit -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/already_denounced_storage.ml b/src/proto_020_PsParisC/lib_protocol/already_denounced_storage.ml new file mode 100644 index 000000000000..685aa851449f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/already_denounced_storage.ml @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(*****************************************************************************) + +let already_denounced_aux ctxt delegate (level : Level_repr.t) round kind = + let open Lwt_result_syntax in + let* denounced_opt = + Storage.Already_denounced.find + (ctxt, level.cycle) + ((level.level, round), delegate) + in + match (denounced_opt, (kind : Misbehaviour_repr.kind)) with + | None, _ -> return_false + | Some denounced, Double_preattesting -> + return denounced.for_double_preattesting + | Some denounced, Double_attesting -> return denounced.for_double_attesting + | Some denounced, Double_baking -> return denounced.for_double_baking + +let already_denounced ctxt delegate level round kind = + let open Lwt_result_syntax in + let* answer = already_denounced_aux ctxt delegate level round kind in + if answer || Round_repr.(round = zero) then return answer + else + let* first_level = Storage.Tenderbake.First_level_of_protocol.get ctxt in + if Raw_level_repr.(level.level >= first_level) then return answer + else + (* Exception related to the migration from Oxford to P: because + Oxford doesn't record the round of misbehaviours, all + misbehaviours present in the storage at stitching time got + assigned the round zero. So we also check with the round set + to zero in the specific case where a misbehaviour: + + - is old enough to have potentially been denounced during + Oxford (ie. its level is before the first level of P), + + - has a non-zero round (otherwise the new check is identical + to the previous one anyway), and + + - has not been found in the storage under its own round + (ie. [answer] is [false]). + + TODO #6957: This whole control flow should be removed from + protocol Q. *) + already_denounced_aux ctxt delegate level Round_repr.zero kind + +let add_denunciation ctxt delegate (level : Level_repr.t) round kind = + let open Lwt_result_syntax in + let* denounced_opt = + Storage.Already_denounced.find + (ctxt, level.cycle) + ((level.level, round), delegate) + in + let denounced = + Option.value denounced_opt ~default:Storage.default_denounced + in + let already_denounced = + match kind with + | Misbehaviour_repr.Double_baking -> denounced.for_double_baking + | Double_attesting -> denounced.for_double_attesting + | Double_preattesting -> denounced.for_double_preattesting + in + let*! ctxt = + if already_denounced then Lwt.return ctxt + else + Storage.Already_denounced.add + (ctxt, level.cycle) + ((level.level, round), delegate) + (match kind with + | Double_baking -> {denounced with for_double_baking = true} + | Double_attesting -> {denounced with for_double_attesting = true} + | Double_preattesting -> {denounced with for_double_preattesting = true}) + in + return (ctxt, already_denounced) + +let clear_outdated_cycle ctxt ~new_cycle = + match Cycle_repr.(sub new_cycle Constants_repr.max_slashing_period) with + | None -> Lwt.return ctxt + | Some outdated_cycle -> Storage.Already_denounced.clear (ctxt, outdated_cycle) diff --git a/src/proto_020_PsParisC/lib_protocol/already_denounced_storage.mli b/src/proto_020_PsParisC/lib_protocol/already_denounced_storage.mli new file mode 100644 index 000000000000..a7adfb5b049d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/already_denounced_storage.mli @@ -0,0 +1,62 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(*****************************************************************************) + +(** This module is responsible for ensuring that a delegate doesn't + get slashed twice for the same offense. To do so, it maintains the + {!Storage.Already_denounced} table, which tracks which + denunciations have already been seen in blocks. + + A denunciation is uniquely characterized by the delegate (the + culprit), the level and round of the duplicate block or + (pre)attestation, and the {!type-Misbehaviour_repr.kind} (double + baking/attesting/preattesting). + + Invariant: {!Storage.Already_denounced} is empty for cycles equal + to [current_cycle - max_slashing_period] or older. Indeed, such + denunciations are no longer allowed (see + [Anonymous.check_denunciation_age] in {!Validate}) so there is no + need to track them anymore. *) + +(** Returns true if the given delegate has already been denounced + for the given misbehaviour kind at the given level and round. *) +val already_denounced : + Raw_context.t -> + Signature.Public_key_hash.t -> + Level_repr.t -> + Round_repr.t -> + Misbehaviour_repr.kind -> + bool tzresult Lwt.t + +(** Records a denunciation in {!Storage.Already_denounced}. + + Returns a pair [(ctxt, already_denounced)], where + [already_denounced] is a boolean indicating whether the + denunciation was already recorded in the storage previously. + + When [already_denounced] is [true], the returned [ctxt] is + actually the unchanged context argument. + + Precondition: the given level should be more recent than + [current_cycle - max_slashing_period] in order to maintain the + invariant on the age of tracked denunciations. Fortunately, this + is already enforced in {!Validate} by + [Anonymous.check_denunciation_age]. *) +val add_denunciation : + Raw_context.t -> + Signature.public_key_hash -> + Level_repr.t -> + Round_repr.t -> + Misbehaviour_repr.kind -> + (Raw_context.t * bool) tzresult Lwt.t + +(** Clear {!Storage.Already_denounced} for the cycle [new_cycle - + max_slashing_period]. Indeed, denunciations on events which + happened during this cycle are no longer allowed anyway. *) +val clear_outdated_cycle : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/amendment.ml b/src/proto_020_PsParisC/lib_protocol/amendment.ml new file mode 100644 index 000000000000..f58534e2d058 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/amendment.ml @@ -0,0 +1,229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** Returns the proposal submitted by the most delegates. + Returns None in case of a tie, if proposal quorum is below required + minimum or if there are no proposals. *) +let select_winning_proposal ctxt = + let open Lwt_result_syntax in + let* proposals = Vote.get_proposals ctxt in + let merge proposal vote winners = + match winners with + | None -> Some ([proposal], vote) + | Some (winners, winners_vote) as previous -> + if Compare.Int64.(vote = winners_vote) then + Some (proposal :: winners, winners_vote) + else if Compare.Int64.(vote > winners_vote) then Some ([proposal], vote) + else previous + in + match Protocol_hash.Map.fold merge proposals None with + | Some ([proposal], vote) -> + let* max_vote = Vote.get_total_voting_power_free ctxt in + let min_proposal_quorum = + Z.of_int32 (Constants.min_proposal_quorum ctxt) + in + let min_vote_to_pass = + Z.( + to_int64 + (div (mul min_proposal_quorum (of_int64 max_vote)) (of_int 100_00))) + in + if Compare.Int64.(vote >= min_vote_to_pass) then return_some proposal + else return_none + | _ -> return_none + +(* in case of a tie, let's do nothing. *) + +(** A proposal is approved if it has supermajority and the participation reaches + the current quorum. + Supermajority means the yays are more 8/10 of casted votes. + The participation is the ratio of all received votes, including passes, with + respect to the number of possible votes. + The participation EMA (exponential moving average) uses the last + participation EMA and the current participation./ + The expected quorum is calculated using the last participation EMA, capped + by the min/max quorum protocol constants. *) +let approval_and_participation_ema (ballots : Vote.ballots) ~total_voting_power + ~participation_ema ~expected_quorum = + (* Note overflows: considering a maximum of 1e9 tokens (around 2^30), + hence 1e15 mutez (around 2^50) + In 'participation' a Z is used because in the worst case 'all_votes is + 1e15 and after the multiplication is 1e19 (around 2^64). + *) + let casted_votes = Int64.add ballots.yay ballots.nay in + let all_votes = Int64.add casted_votes ballots.pass in + let supermajority = Int64.div (Int64.mul 8L casted_votes) 10L in + let participation = + (* in centile of percentage *) + Z.( + to_int32 + (div + (mul (Z.of_int64 all_votes) (Z.of_int 100_00)) + (Z.of_int64 total_voting_power))) + in + let approval = + Compare.Int32.(participation >= expected_quorum) + && Compare.Int64.(ballots.yay >= supermajority) + in + let new_participation_ema = + Int32.(div (add (mul 8l participation_ema) (mul 2l participation)) 10l) + in + (approval, new_participation_ema) + +let get_approval_and_update_participation_ema ctxt = + let open Lwt_result_syntax in + let* ballots = Vote.get_ballots ctxt in + let* total_voting_power = Vote.get_total_voting_power_free ctxt in + let* participation_ema = Vote.get_participation_ema ctxt in + let* expected_quorum = Vote.get_current_quorum ctxt in + let*! ctxt = Vote.clear_ballots ctxt in + let approval, new_participation_ema = + approval_and_participation_ema + ballots + ~total_voting_power + ~participation_ema + ~expected_quorum + in + let+ ctxt = Vote.set_participation_ema ctxt new_participation_ema in + (ctxt, approval) + +(** Implements the state machine of the amendment procedure. Note that + [update_listings], that computes the vote weight of each delegate, is run at + the end of each voting period. This state-machine prepare the voting_period + for the next block. *) +let start_new_voting_period ctxt = + (* any change related to the storage in this function must probably + be replicated in `record_testnet_dictator_proposals` *) + let open Lwt_result_syntax in + let* kind = Voting_period.get_current_kind ctxt in + let* ctxt = + match kind with + | Proposal -> ( + let* proposal = select_winning_proposal ctxt in + let*! ctxt = Vote.clear_proposals ctxt in + match proposal with + | None -> Voting_period.reset ctxt + | Some proposal -> + let* ctxt = Vote.init_current_proposal ctxt proposal in + Voting_period.succ ctxt) + | Exploration -> + let* ctxt, approved = get_approval_and_update_participation_ema ctxt in + if approved then Voting_period.succ ctxt + else + let*! ctxt = Vote.clear_current_proposal ctxt in + Voting_period.reset ctxt + | Cooldown -> Voting_period.succ ctxt + | Promotion -> + let* ctxt, approved = get_approval_and_update_participation_ema ctxt in + if approved then Voting_period.succ ctxt + else + let*! ctxt = Vote.clear_current_proposal ctxt in + Voting_period.reset ctxt + | Adoption -> + let* proposal = Vote.get_current_proposal ctxt in + let*! ctxt = activate ctxt proposal in + let*! ctxt = Vote.clear_current_proposal ctxt in + Voting_period.reset ctxt + in + Vote.update_listings ctxt + +let may_start_new_voting_period ctxt = + let open Lwt_result_syntax in + let* is_last = Voting_period.is_last_block ctxt in + if is_last then start_new_voting_period ctxt else return ctxt + +(** {2 Application of voting operations} *) + +let get_testnet_dictator ctxt chain_id = + (* This function should always, ALWAYS, return None on mainnet!!!! *) + match Constants.testnet_dictator ctxt with + | Some pkh when Chain_id.(chain_id <> Constants.mainnet_id) -> Some pkh + | _ -> None + +let is_testnet_dictator ctxt chain_id delegate = + (* This function should always, ALWAYS, return false on mainnet!!!! *) + match get_testnet_dictator ctxt chain_id with + | Some pkh -> Signature.Public_key_hash.equal pkh delegate + | _ -> false + +(** Apply a [Proposals] operation from a registered dictator of a test + chain. This forcibly updates the voting period, changing the + current voting period kind and the current proposal if + applicable. Of course, there must never be such a dictator on + mainnet: see {!is_testnet_dictator}. *) +let apply_testnet_dictator_proposals ctxt chain_id proposals = + let open Lwt_result_syntax in + let*! ctxt = Vote.clear_ballots ctxt in + let*! ctxt = Vote.clear_proposals ctxt in + let*! ctxt = Vote.clear_current_proposal ctxt in + let ctxt = record_dictator_proposal_seen ctxt in + match proposals with + | [] -> + Voting_period.Testnet_dictator.overwrite_current_kind + ctxt + chain_id + Proposal + | [proposal] -> + let* ctxt = Vote.init_current_proposal ctxt proposal in + Voting_period.Testnet_dictator.overwrite_current_kind + ctxt + chain_id + Adoption + | _ :: _ :: _ -> + (* This case should not be possible if the operation has been + previously validated by {!Validate.validate_operation}. *) + tzfail Validate_errors.Voting.Testnet_dictator_multiple_proposals + +let apply_proposals ctxt chain_id (Proposals {source; period = _; proposals}) = + let open Lwt_result_syntax in + let* ctxt = + if is_testnet_dictator ctxt chain_id source then + apply_testnet_dictator_proposals ctxt chain_id proposals + else if dictator_proposal_seen ctxt then + (* Noop if dictator voted *) + return ctxt + else + let* count = Vote.get_delegate_proposal_count ctxt source in + let new_count = count + List.length proposals in + let*! ctxt = Vote.set_delegate_proposal_count ctxt source new_count in + let*! ctxt = + List.fold_left_s + (fun ctxt proposal -> Vote.add_proposal ctxt source proposal) + ctxt + proposals + in + return ctxt + in + return (ctxt, Apply_results.Single_result Proposals_result) + +let apply_ballot ctxt (Ballot {source; period = _; proposal = _; ballot}) = + let open Lwt_result_syntax in + let* ctxt = + if dictator_proposal_seen ctxt then (* Noop if dictator voted *) return ctxt + else Vote.record_ballot ctxt source ballot + in + return (ctxt, Apply_results.Single_result Ballot_result) diff --git a/src/proto_020_PsParisC/lib_protocol/amendment.mli b/src/proto_020_PsParisC/lib_protocol/amendment.mli new file mode 100644 index 000000000000..6bbc74d2f069 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/amendment.mli @@ -0,0 +1,133 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + Amendments and proposals. + + Only delegates having the minimal required stake take part in the amendment + procedure. It works as follows: + + - Proposal period: delegates can submit protocol amendment + proposals using the proposal operation. At the end of a proposal + period, the proposal with most supporters is selected and we move + to an exploration period. If there are no proposals, or a tie + between proposals, a new proposal period starts. + + - Exploration period: delegates can cast votes to test or not the + winning proposal using the ballot operation. At the end of an + exploration period if participation reaches the quorum and the + proposal has a supermajority in favor, we proceed to a cooldown + period. Otherwise we go back to a proposal period. In any case, if + there is enough participation the quorum is updated. + + - Cooldown period: business as usual for the main chain. This + period is only a time gap between exploration and promotion + periods intended to provide the community with extra time to + continue testing the new protocol proposal, and start adapting + their infrastructure in advance. At the end of the Cooldown + period we move to the Promotion period. + + - Promotion period: delegates can cast votes to promote or not the + proposal using the ballot operation. At the end of a promotion + period if participation reaches the quorum and the proposal has a + supermajority in favor, we move to an adoption period. Otherwise we + go back to a proposal period. In any case, if there is enough + participation the quorum is updated. + + - Adoption period: At the end of an adoption period, the proposal + is activated as the new protocol. + + The current protocol parameters are documented in + src/proto_alpha/lib_parameters/default_parameters.ml + + In practice, the real constants used are defined in the + migration code. In src/proto_alpha/lib_protocol/init_storage.ml, + function [prepare_first_block] introduces new constants and + redefines the existing ones. +*) + +open Alpha_context + +(** If at the end of a voting period, moves to the next one following + the state machine of the amendment procedure. *) +val may_start_new_voting_period : context -> context tzresult Lwt.t + +(** Return the registered testchain dictator, if any. This function will always + return None on mainnet. *) +val get_testnet_dictator : context -> Chain_id.t -> public_key_hash option + +(** Check whether the given public key hash corresponds to the + registered testchain dictator, if any. This function will always + return false on mainnet. *) +val is_testnet_dictator : context -> Chain_id.t -> public_key_hash -> bool + +(** {2 Application of voting operations} + + There are two kinds of voting operations: + + - Proposals: A delegate submits a list of protocol amendment + proposals. This operation is only accepted during a Proposal period + (see above). + + - Ballot: A delegate casts a vote for/against the current proposal + (or pass). This operation is only accepted during an Exploration + or Promotion period (see above). *) + +(** Update the [context] with the effects of a Proposals operation: + + - Its proposals are added to the source's recorded proposals. + + - The recorded proposal count of the source is increased by the + number of proposals in the operation. + + Note that a Proposals operation from a testnet dictator (which may + be set up when a test chain is initialized) has completely + different effects: + + - If the operation contains no proposal, then the current voting + period is immediately and forcibly set to a Proposal period. + + - If the operation contains exactly one proposal, then the current + voting period is immediately and forcibly set to an Adoption period + for this proposal. + + {!validate_proposals} must have been called beforehand, and is + responsible for ensuring that [apply_proposals] cannot fail. *) +val apply_proposals : + context -> + Chain_id.t -> + Kind.proposals contents -> + (context * Kind.proposals Apply_results.contents_result_list) tzresult Lwt.t + +(** Update the [context] with the effects of a Ballot operation: + + The couple (source of the operation, submitted ballot) is recorded. + + {!validate_ballot} must have been called beforehand, and is + responsible for ensuring that [apply_ballot] cannot fail. *) +val apply_ballot : + context -> + Kind.ballot contents -> + (context * Kind.ballot Apply_results.contents_result_list) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/apply.ml b/src/proto_020_PsParisC/lib_protocol/apply.ml new file mode 100644 index 000000000000..461cc5673b60 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply.ml @@ -0,0 +1,3229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Main Entry Points *) + +open Alpha_context + +type error += + | Faulty_validation_wrong_slot + | Set_deposits_limit_on_unregistered_delegate of Signature.Public_key_hash.t + | Set_deposits_limit_when_automated_staking_off + | Error_while_taking_fees + | Update_consensus_key_on_unregistered_delegate of Signature.Public_key_hash.t + | Empty_transaction of Contract.t + | Non_empty_transaction_from of Destination.t + | Internal_operation_replay of + Apply_internal_results.packed_internal_operation + | Multiple_revelation + | Invalid_transfer_to_sc_rollup + | Invalid_sender of Destination.t + | Invalid_self_transaction_destination + | Staking_for_delegator_while_external_staking_disabled + | Staking_to_delegate_that_refuses_external_staking + | Stake_modification_with_no_delegate_set + | Invalid_nonzero_transaction_amount of Tez.t + | Invalid_staking_parameters_sender + +let () = + let description = + "The consensus operation uses an invalid slot. This error should not \ + happen: the operation validation should have failed earlier." + in + register_error_kind + `Permanent + ~id:"operation.faulty_validation_wrong_slot" + ~title:"Faulty validation (wrong slot for consensus operation)" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Faulty_validation_wrong_slot -> Some () | _ -> None) + (fun () -> Faulty_validation_wrong_slot) ; + register_error_kind + `Temporary + ~id:"operation.set_deposits_limit_on_unregistered_delegate" + ~title:"Set deposits limit on an unregistered delegate" + ~description:"Cannot set deposits limit on an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot set a deposits limit on the unregistered delegate %a." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function + | Set_deposits_limit_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Set_deposits_limit_on_unregistered_delegate c) ; + + register_error_kind + `Temporary + ~id:"operation.set_deposits_limit_when_automated_staking_off" + ~title:"Set deposits limit when automated staking off" + ~description: + "Cannot set deposits limit when automated staking is off or Adaptive \ + Issuance is active." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Cannot set a deposits limit when automated staking off.") + Data_encoding.unit + (function + | Set_deposits_limit_when_automated_staking_off -> Some () | _ -> None) + (fun () -> Set_deposits_limit_when_automated_staking_off) ; + + let error_while_taking_fees_description = + "There was an error while taking the fees, which should not happen and \ + means that the operation's validation was faulty." + in + register_error_kind + `Permanent + ~id:"operation.error_while_taking_fees" + ~title:"Error while taking the fees of a manager operation" + ~description:error_while_taking_fees_description + ~pp:(fun ppf () -> + Format.fprintf ppf "%s" error_while_taking_fees_description) + Data_encoding.unit + (function Error_while_taking_fees -> Some () | _ -> None) + (fun () -> Error_while_taking_fees) ; + + register_error_kind + `Temporary + ~id:"operation.update_consensus_key_on_unregistered_delegate" + ~title:"Update consensus key on an unregistered delegate" + ~description:"Cannot update consensus key an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot update the consensus key on the unregistered delegate %a." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function + | Update_consensus_key_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Update_consensus_key_on_unregistered_delegate c) ; + register_error_kind + `Branch + ~id:"contract.empty_transaction" + ~title:"Empty transaction" + ~description:"Forbidden to credit 0ꜩ to a contract without code." + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "Transactions of 0ꜩ towards a contract without code are forbidden (%a)." + Contract.pp + contract) + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Empty_transaction c -> Some c | _ -> None) + (fun c -> Empty_transaction c) ; + register_error_kind + `Branch + ~id:"contract.non_empty_transaction_from_source" + ~title:"Unexpected non-empty transaction" + ~description:"This address cannot initiate non-empty transactions" + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "%a does not have a balance and cannot initiate non-empty transactions" + Destination.pp + contract) + Data_encoding.(obj1 (req "source" Destination.encoding)) + (function Non_empty_transaction_from c -> Some c | _ -> None) + (fun c -> Non_empty_transaction_from c) ; + + register_error_kind + `Permanent + ~id:"internal_operation_replay" + ~title:"Internal operation replay" + ~description:"An internal operation was emitted twice by a script" + ~pp:(fun ppf (Apply_internal_results.Internal_operation {nonce; _}) -> + Format.fprintf + ppf + "Internal operation %d was emitted twice by a script" + nonce) + Apply_internal_results.internal_operation_encoding + (function Internal_operation_replay op -> Some op | _ -> None) + (fun op -> Internal_operation_replay op) ; + register_error_kind + `Permanent + ~id:"block.multiple_revelation" + ~title:"Multiple revelations were included in a manager operation" + ~description: + "A manager operation should not contain more than one revelation" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Multiple revelations were included in a manager operation") + Data_encoding.empty + (function Multiple_revelation -> Some () | _ -> None) + (fun () -> Multiple_revelation) ; + register_error_kind + `Permanent + ~id:"operations.invalid_transfer_to_smart_rollup_from_implicit_account" + ~title:"Invalid transfer to smart rollup" + ~description:"Invalid transfer to smart rollup from implicit account" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Invalid sender for transfer operation to smart rollup. Only \ + originated accounts are allowed.") + Data_encoding.empty + (function Invalid_transfer_to_sc_rollup -> Some () | _ -> None) + (fun () -> Invalid_transfer_to_sc_rollup) ; + register_error_kind + `Permanent + ~id:"operations.invalid_sender" + ~title:"Invalid sender for an internal operation" + ~description: + "Invalid sender for an internal operation restricted to implicit and \ + originated accounts." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Invalid sender (%a) for this internal operation. Only implicit and \ + originated accounts are allowed" + Destination.pp + c) + Data_encoding.(obj1 (req "contract" Destination.encoding)) + (function Invalid_sender c -> Some c | _ -> None) + (fun c -> Invalid_sender c) ; + let invalid_self_transaction_destination_description = + "A pseudo-transaction destination must equal its sender." + in + register_error_kind + `Permanent + ~id:"operations.invalid_self_transaction_destination" + ~title:"Invalid destination for a pseudo-transaction" + ~description:invalid_self_transaction_destination_description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + invalid_self_transaction_destination_description) + Data_encoding.unit + (function Invalid_self_transaction_destination -> Some () | _ -> None) + (fun () -> Invalid_self_transaction_destination) ; + let staking_for_delegator_while_external_staking_disabled_description = + "As long as external staking is not enabled, staking operations are only \ + allowed from delegates." + in + register_error_kind + `Permanent + ~id:"operations.staking_for_delegator_while_external_staking_disabled" + ~title:"Staking for a delegator while external staking is disabled" + ~description: + staking_for_delegator_while_external_staking_disabled_description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + staking_for_delegator_while_external_staking_disabled_description) + Data_encoding.unit + (function + | Staking_for_delegator_while_external_staking_disabled -> Some () + | _ -> None) + (fun () -> Staking_for_delegator_while_external_staking_disabled) ; + let stake_modification_without_delegate_description = + "(Un)Stake operations are only allowed when delegate is set." + in + register_error_kind + `Permanent + ~id:"operations.stake_modification_with_no_delegate_set" + ~title:"(Un)staking without any delegate set" + ~description:stake_modification_without_delegate_description + ~pp:(fun ppf () -> + Format.pp_print_string ppf stake_modification_without_delegate_description) + Data_encoding.unit + (function Stake_modification_with_no_delegate_set -> Some () | _ -> None) + (fun () -> Stake_modification_with_no_delegate_set) ; + let staking_to_delegate_that_refuses_external_staking_description = + "The delegate currently does not accept staking operations from sources \ + other than itself: its `limit_of_staking_over_baking` parameter is set to \ + 0." + in + register_error_kind + `Permanent + ~id:"operations.staking_to_delegate_that_refuses_external_staking" + ~title:"Staking to delegate that does not accept external staking" + ~description:staking_to_delegate_that_refuses_external_staking_description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + staking_to_delegate_that_refuses_external_staking_description) + Data_encoding.unit + (function + | Staking_to_delegate_that_refuses_external_staking -> Some () | _ -> None) + (fun () -> Staking_to_delegate_that_refuses_external_staking) ; + register_error_kind + `Permanent + ~id:"operations.invalid_nonzero_transaction_amount" + ~title:"Invalid non-zero transaction amount" + ~description:"A transaction expected a zero-amount but got non-zero." + ~pp:(fun ppf amount -> + Format.fprintf + ppf + "A transaction expected a zero-amount but got %a." + Tez.pp + amount) + Data_encoding.(obj1 (req "amount" Tez.encoding)) + (function + | Invalid_nonzero_transaction_amount amount -> Some amount | _ -> None) + (fun amount -> Invalid_nonzero_transaction_amount amount) ; + register_error_kind + `Permanent + ~id:"operations.invalid_staking_parameters_sender" + ~title:"Invalid staking parameters sender" + ~description:"The staking parameters can only be set by delegates." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid staking parameters sender") + Data_encoding.empty + (function Invalid_staking_parameters_sender -> Some () | _ -> None) + (fun () -> Invalid_staking_parameters_sender) + +open Apply_results +open Apply_operation_result +open Apply_internal_results + +let update_script_storage_and_ticket_balances ctxt ~self_contract storage + lazy_storage_diff ticket_diffs operations = + let open Lwt_result_syntax in + let* ctxt = + Contract.update_script_storage ctxt self_contract storage lazy_storage_diff + in + let self_contract = Contract.Originated self_contract in + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract + ~ticket_diffs + operations + +let apply_delegation ~ctxt ~(sender : Contract.t) ~delegate ~before_operation = + let open Lwt_result_syntax in + let* ctxt, balance_updates = + match sender with + | Originated _ -> + (* Originated contracts have no stake (yet). *) + return (ctxt, []) + | Implicit sender_pkh -> ( + let* sender_delegate_status = + Contract.get_delegate_status ctxt sender_pkh + in + match sender_delegate_status with + | Undelegated | Delegate -> + (* No delegate before or re-activation: no unstake request added. *) + return (ctxt, []) + | Delegated delegate -> + (* [request_unstake] bounds to the actual stake. *) + Staking.request_unstake + ctxt + ~sender_contract:sender + ~delegate + Tez.max_mutez) + in + let+ ctxt = Contract.Delegate.set ctxt sender delegate in + (ctxt, Gas.consumed ~since:before_operation ~until:ctxt, balance_updates, []) + +type 'loc execution_arg = + | Typed_arg : 'loc * ('a, _) Script_typed_ir.ty * 'a -> 'loc execution_arg + | Untyped_arg : Script.expr -> _ execution_arg + +let apply_transaction_to_implicit ~ctxt ~sender ~amount ~pkh ~before_operation = + let contract = Contract.Implicit pkh in + let open Lwt_result_syntax in + (* Transfers of zero to implicit accounts are forbidden. *) + let*? () = error_when Tez.(amount = zero) (Empty_transaction contract) in + (* If the implicit contract is not yet allocated at this point then + the next transfer of tokens will allocate it. *) + let*! already_allocated = Contract.allocated ctxt contract in + let* ctxt, balance_updates = + Token.transfer ctxt (`Contract sender) (`Contract contract) amount + in + let result = + Transaction_to_contract_result + { + storage = None; + lazy_storage_diff = None; + balance_updates; + ticket_receipt = []; + originated_contracts = []; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract = not already_allocated; + } + in + return (ctxt, result, []) + +let apply_stake ~ctxt ~sender ~amount ~destination ~before_operation = + let open Lwt_result_syntax in + let contract = Contract.Implicit destination in + (* Staking of zero is forbidden. *) + let*? () = error_when Tez.(amount = zero) (Empty_transaction contract) in + let*? () = + error_unless + Signature.Public_key_hash.(sender = destination) + Invalid_self_transaction_destination + in + let*? ctxt = Gas.consume ctxt Adaptive_issuance_costs.stake_cost in + let* delegate_opt = Contract.Delegate.find ctxt contract in + match delegate_opt with + | None -> tzfail Stake_modification_with_no_delegate_set + | Some delegate -> + let allowed = + Signature.Public_key_hash.(delegate = sender) + || Constants.adaptive_issuance_enable ctxt + in + let*? () = + error_unless + allowed + Staking_for_delegator_while_external_staking_disabled + in + let* {limit_of_staking_over_baking_millionth; _} = + Delegate.Staking_parameters.of_delegate ctxt delegate + in + let forbidden = + Signature.Public_key_hash.(delegate <> sender) + && Compare.Int32.(limit_of_staking_over_baking_millionth = 0l) + in + let*? () = + error_when forbidden Staking_to_delegate_that_refuses_external_staking + in + let* ctxt, balance_updates = + Staking.stake ctxt ~amount:(`Exactly amount) ~sender ~delegate + in + (* Since [delegate] is an already existing delegate, it is already allocated. *) + let allocated_destination_contract = false in + let result = + Transaction_to_contract_result + { + storage = None; + lazy_storage_diff = None; + balance_updates; + ticket_receipt = []; + originated_contracts = []; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract; + } + in + return (ctxt, result, []) + +let apply_unstake ~ctxt ~sender ~amount ~destination ~before_operation = + let open Lwt_result_syntax in + let*? () = + error_unless + Signature.Public_key_hash.(sender = destination) + Invalid_self_transaction_destination + in + let sender_contract = Contract.Implicit sender in + let*? ctxt = Gas.consume ctxt Adaptive_issuance_costs.find_delegate_cost in + let* delegate_opt = Contract.Delegate.find ctxt sender_contract in + match delegate_opt with + | None -> tzfail Stake_modification_with_no_delegate_set + | Some delegate -> + let* ctxt, balance_updates = + Staking.request_unstake ctxt ~sender_contract ~delegate amount + in + let result = + Transaction_to_contract_result + { + storage = None; + lazy_storage_diff = None; + balance_updates; + ticket_receipt = []; + originated_contracts = []; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract = false; + } + in + return (ctxt, result, []) + +let apply_finalize_unstake ~ctxt ~sender ~amount ~destination ~before_operation + = + let open Lwt_result_syntax in + let*? () = + error_when Tez.(amount <> zero) (Invalid_nonzero_transaction_amount amount) + in + let*? () = + error_unless + Signature.Public_key_hash.(sender = destination) + Invalid_self_transaction_destination + in + let contract = Contract.Implicit sender in + let*? ctxt = Gas.consume ctxt Adaptive_issuance_costs.find_delegate_cost in + let*! already_allocated = Contract.allocated ctxt contract in + let* ctxt, balance_updates = Staking.finalize_unstake ctxt contract in + let result = + Transaction_to_contract_result + { + storage = None; + lazy_storage_diff = None; + balance_updates; + ticket_receipt = []; + originated_contracts = []; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract = not already_allocated; + } + in + return (ctxt, result, []) + +let apply_set_delegate_parameters ~ctxt ~sender ~destination + ~limit_of_staking_over_baking_millionth + ~edge_of_baking_over_staking_billionth ~before_operation = + let open Lwt_result_syntax in + let*? ctxt = + Gas.consume ctxt Adaptive_issuance_costs.set_delegate_parameters_cost + in + let*? () = + error_unless + Signature.Public_key_hash.(sender = destination) + Invalid_self_transaction_destination + in + let* is_delegate = Contract.is_delegate ctxt sender in + let*? () = error_unless is_delegate Invalid_staking_parameters_sender in + let*? t = + Staking_parameters_repr.make + ~limit_of_staking_over_baking_millionth + ~edge_of_baking_over_staking_billionth + in + let* ctxt = Delegate.Staking_parameters.register_update ctxt sender t in + let result = + Transaction_to_contract_result + { + storage = None; + lazy_storage_diff = None; + balance_updates = []; + ticket_receipt = []; + originated_contracts = []; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract = false; + } + in + return (ctxt, result, []) + +let transfer_from_any_address ctxt sender destination amount = + let open Lwt_result_syntax in + match sender with + | Destination.Contract sender -> + Token.transfer ctxt (`Contract sender) (`Contract destination) amount + | Destination.Sc_rollup _ | Destination.Zk_rollup _ -> + (* We do not allow transferring tez from rollups to other contracts. *) + let*? () = + error_unless Tez.(amount = zero) (Non_empty_transaction_from sender) + in + return (ctxt, []) + +let apply_transaction_to_implicit_with_ticket ~sender ~destination ~ty ~ticket + ~amount ~before_operation ctxt = + let open Lwt_result_syntax in + let destination = Contract.Implicit destination in + let*! already_allocated = Contract.allocated ctxt destination in + let ex_token, ticket_amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket + @@ Ticket_scanner.Ex_ticket (ty, ticket) + in + let* ticket_token, ctxt = Ticket_token_unparser.unparse ctxt ex_token in + let* ctxt, balance_updates = + transfer_from_any_address ctxt sender destination amount + in + let ticket_receipt = + Ticket_receipt. + [ + { + ticket_token; + updates = + [ + { + account = Destination.Contract destination; + amount = Script_int.(to_zint (ticket_amount :> n num)); + }; + ]; + }; + ] + in + return + ( ctxt, + Transaction_to_contract_result + { + storage = None; + lazy_storage_diff = None; + balance_updates; + ticket_receipt; + originated_contracts = []; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = Z.zero; + paid_storage_size_diff = Z.zero; + allocated_destination_contract = not already_allocated; + }, + [] ) + +let apply_transaction_to_smart_contract ~ctxt ~sender ~contract_hash ~amount + ~entrypoint ~before_operation ~payer ~chain_id ~internal ~parameter ~script + ~script_ir ~cache_key ?(paid_storage_diff_acc = Z.zero) + ?(ticket_receipt_acc = []) () = + let open Lwt_result_syntax in + let contract = Contract.Originated contract_hash in + (* We can assume the destination contract is already allocated at this point. + If the destination contract does not exist, [Script_cache.find], + which is called earlier, would have failed. *) + let* ctxt, balance_updates = + transfer_from_any_address ctxt sender contract amount + in + (* [Token.transfer], which is being called before, already loads this value into + the Irmin cache, so no need to burn gas for it. *) + let* balance = Contract.get_balance ctxt contract in + let now = Script_timestamp.now ctxt in + let level = + (Level.current ctxt).level |> Raw_level.to_int32 |> Script_int.of_int32 + |> Script_int.abs + in + let step_constants = + let open Script_interpreter in + {sender; payer; self = contract_hash; amount; chain_id; balance; now; level} + in + let execute = + match parameter with + | Untyped_arg parameter -> Script_interpreter.execute ~parameter + | Typed_arg (location, parameter_ty, parameter) -> + Script_interpreter.execute_with_typed_parameter + ~location + ~parameter_ty + ~parameter + in + let cached_script = Some script_ir in + let* ( { + script = updated_cached_script; + code_size = updated_size; + storage; + lazy_storage_diff; + operations; + ticket_diffs; + ticket_receipt; + }, + ctxt ) = + execute + ctxt + ~cached_script + Optimized + step_constants + ~script + ~entrypoint + ~internal + in + let* ticket_table_size_diff, ctxt = + update_script_storage_and_ticket_balances + ctxt + ~self_contract:contract_hash + storage + lazy_storage_diff + ticket_diffs + operations + in + let* ticket_paid_storage_diff, ctxt = + Ticket_balance.adjust_storage_space + ctxt + ~storage_diff:ticket_table_size_diff + in + let* ctxt, new_size, contract_paid_storage_size_diff = + Fees.record_paid_storage_space ctxt contract_hash + in + let* originated_contracts = + Contract.originated_from_current_nonce ~since:before_operation ~until:ctxt + in + let*? ctxt = + Script_cache.update + ctxt + cache_key + ({script with storage = Script.lazy_expr storage}, updated_cached_script) + updated_size + in + let result = + Transaction_to_contract_result + { + storage = Some storage; + lazy_storage_diff; + balance_updates; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6639 + Currently, if both [ticket_receipt_acc] and [ticket_receipt] contain updates + for the same ticket token, the token will appear in a non-optimal, but not wrong, + way in the ticket receipt. See description of #6639 for an example. *) + ticket_receipt = ticket_receipt_acc @ ticket_receipt; + originated_contracts; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = new_size; + paid_storage_size_diff = + Z.( + add + paid_storage_diff_acc + (add contract_paid_storage_size_diff ticket_paid_storage_diff)); + allocated_destination_contract = false; + } + in + return (ctxt, result, operations) + +let apply_origination ~ctxt ~storage_type ~storage ~unparsed_code + ~contract:contract_hash ~delegate ~sender ~credit ~before_operation = + let open Lwt_result_syntax in + let*? to_duplicate, ctxt = + Script_ir_translator.collect_lazy_storage ctxt storage_type storage + in + let to_update = Script_ir_translator.no_lazy_storage_id in + let* storage, lazy_storage_diff, ctxt = + Script_ir_translator.extract_lazy_storage_diff + ctxt + Optimized + storage_type + storage + ~to_duplicate + ~to_update + ~temporary:false + in + let* storage, ctxt = + Script_ir_translator.unparse_data ctxt Optimized storage_type storage + in + let storage = Script.lazy_expr storage in + (* Normalize code to avoid #843 *) + let* code, ctxt = + Script_ir_translator.unparse_code + ctxt + Optimized + (Micheline.root unparsed_code) + in + let code = Script.lazy_expr code in + let script = {Script.code; storage} in + let* ctxt = + Contract.raw_originate + ctxt + ~prepaid_bootstrap_storage:false + contract_hash + ~script:(script, lazy_storage_diff) + in + let contract = Contract.Originated contract_hash in + let* ctxt = + match delegate with + | None -> return ctxt + | Some delegate -> Contract.Delegate.init ctxt contract delegate + in + let* ctxt, balance_updates = + Token.transfer ctxt (`Contract sender) (`Contract contract) credit + in + let+ ctxt, size, paid_storage_size_diff = + Fees.record_paid_storage_space ctxt contract_hash + in + let result = + { + lazy_storage_diff; + balance_updates; + originated_contracts = [contract_hash]; + consumed_gas = Gas.consumed ~since:before_operation ~until:ctxt; + storage_size = size; + paid_storage_size_diff; + } + in + (ctxt, result, []) + +(** + + Retrieving the script of a contract from its address is costly + because it requires I/Os. For this reason, we put the corresponding + Micheline expression in the cache. + + Elaborating a Micheline node into the well-typed script abstract + syntax tree is also a costly operation. The result of this operation + is cached as well. + +*) + +let assert_sender_is_contract = + let open Result_syntax in + function + | Destination.Contract sender -> return sender + | sender -> tzfail (Invalid_sender sender) + +let find_contract_from_cache ctxt contract_hash = + let open Lwt_result_syntax in + let* ctxt, cache_key, script = Script_cache.find ctxt contract_hash in + match script with + | None -> tzfail (Contract.Non_existing_contract (Originated contract_hash)) + | Some (script, script_ir) -> return (ctxt, (cache_key, script, script_ir)) + +let apply_internal_operation_contents : + type kind. + context -> + payer:public_key_hash -> + sender:Destination.t -> + chain_id:Chain_id.t -> + kind Script_typed_ir.internal_operation_contents -> + (context + * kind successful_internal_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t = + let open Lwt_result_syntax in + fun ctxt_before_op ~payer ~sender ~chain_id operation -> + let* ctxt = Destination.must_exist ctxt_before_op sender in + (* There is no signature being checked for internal operations so in + this case the fixed cost is exactly + [Michelson_v1_gas.Cost_of.manager_operation]. *) + let*? ctxt = Gas.consume ctxt Michelson_v1_gas.Cost_of.manager_operation in + (* Note that [ctxt_before_op] will be used again later to compute + gas consumption and originations for the operation result (by + comparing it with the [ctxt] we will have at the end of the + application). *) + match operation with + | Transaction_to_implicit {destination = pkh; amount} -> + let*? sender = assert_sender_is_contract sender in + let+ ctxt, res, ops = + apply_transaction_to_implicit + ~ctxt + ~sender + ~amount + ~pkh + ~before_operation:ctxt_before_op + in + ( ctxt, + (ITransaction_result res : kind successful_internal_operation_result), + ops ) + | Transaction_to_implicit_with_ticket + { + destination; + ticket_ty = Script_typed_ir.Ticket_t (ty, _ty_metadata); + ticket; + amount; + unparsed_ticket = _; + } -> + let+ ctxt, res, ops = + apply_transaction_to_implicit_with_ticket + ~sender + ~destination + ~ty + ~ticket + ~amount + ~before_operation:ctxt_before_op + ctxt + in + ( ctxt, + (ITransaction_result res : kind successful_internal_operation_result), + ops ) + | Transaction_to_smart_contract + { + amount; + destination = contract_hash; + entrypoint; + location; + parameters_ty; + parameters = typed_parameters; + unparsed_parameters = _; + } -> + let* ctxt, (cache_key, script, script_ir) = + find_contract_from_cache ctxt contract_hash + in + let+ ctxt, res, ops = + apply_transaction_to_smart_contract + ~ctxt + ~sender + ~contract_hash + ~amount + ~entrypoint + ~before_operation:ctxt_before_op + ~payer + ~chain_id + ~internal:true + ~parameter:(Typed_arg (location, parameters_ty, typed_parameters)) + ~script + ~script_ir + ~cache_key + () + in + (ctxt, ITransaction_result res, ops) + | Transaction_to_sc_rollup + { + destination; + entrypoint = _; + parameters_ty; + parameters; + unparsed_parameters = payload; + } -> + let*? sender = + match sender with + | Destination.Contract (Originated hash) -> Ok hash + | _ -> Result_syntax.tzfail Invalid_transfer_to_sc_rollup + in + (* Adding the message to the inbox. Note that it is safe to ignore the + size diff since only its hash and meta data are stored in the context. + See #3232. *) + let* ctxt = + Sc_rollup.Inbox.add_deposit + ctxt + ~destination + ~payload + ~sender + ~source:payer + in + let*? has_tickets, ctxt = + Ticket_scanner.type_has_tickets ctxt parameters_ty + in + let* ticket_token_map, ctxt = + Ticket_accounting.ticket_balances_of_value + ctxt + ~include_lazy:true + has_tickets + parameters + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4354 + Factor out function for constructing a ticket receipt. + There are multiple places where we compute the receipt from a + ticket-token-map. We should factor out and reuse this logic. *) + let+ ticket_receipt, ctxt = + Ticket_token_map.fold_es + ctxt + (fun ctxt acc ex_token amount -> + let* ticket_token, ctxt = + Ticket_token_unparser.unparse ctxt ex_token + in + let item = + Ticket_receipt. + { + ticket_token; + updates = + [{account = Destination.Sc_rollup destination; amount}]; + } + in + return (item :: acc, ctxt)) + [] + ticket_token_map + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Transaction_to_sc_rollup_result {consumed_gas; ticket_receipt} + in + (ctxt, ITransaction_result result, []) + | Event {ty = _; unparsed_data = _; tag = _} -> + return + ( ctxt, + IEvent_result + {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt}, + [] ) + | Transaction_to_zk_rollup + {destination; unparsed_parameters = _; parameters_ty; parameters} -> + Zk_rollup_apply.transaction_to_zk_rollup + ~ctxt + ~parameters_ty + ~parameters + ~dst_rollup:destination + ~since:ctxt_before_op + | Origination + { + delegate; + code = unparsed_code; + unparsed_storage = _; + credit; + preorigination; + storage_type; + storage; + } -> + let*? sender = assert_sender_is_contract sender in + let+ ctxt, origination_result, ops = + apply_origination + ~ctxt + ~storage_type + ~storage + ~unparsed_code + ~contract:preorigination + ~delegate + ~sender + ~credit + ~before_operation:ctxt_before_op + in + (ctxt, IOrigination_result origination_result, ops) + | Delegation delegate -> + let*? sender = assert_sender_is_contract sender in + let+ ctxt, consumed_gas, balance_updates, ops = + apply_delegation + ~ctxt + ~sender + ~delegate + ~before_operation:ctxt_before_op + in + (ctxt, IDelegation_result {consumed_gas; balance_updates}, ops) + +let apply_manager_operation : + type kind. + context -> + source:public_key_hash -> + chain_id:Chain_id.t -> + consume_gas_for_sig_check:Gas.cost option -> + kind manager_operation -> + (context + * kind successful_manager_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t = + let open Lwt_result_syntax in + fun ctxt_before_op ~source ~chain_id ~consume_gas_for_sig_check operation -> + let source_contract = Contract.Implicit source in + (* See the comment above [fixed_gas_cost] in the + {!Validate.check_contents} function. *) + let fixed_gas_cost = + let manager_op_cost = Michelson_v1_gas.Cost_of.manager_operation in + match consume_gas_for_sig_check with + | None -> manager_op_cost + | Some gas_for_sig_check -> Gas.(manager_op_cost +@ gas_for_sig_check) + in + let*? ctxt = Gas.consume ctxt_before_op fixed_gas_cost in + (* Note that [ctxt_before_op] will be used again later to compute + gas consumption and originations for the operation result (by + comparing it with the [ctxt] we will have at the end of the + application). *) + let consume_deserialization_gas = + (* Note that we used to set this to [Script.When_needed] because + the deserialization gas was accounted for in the gas consumed + by precheck. However, we no longer have access to this precheck + gas, so we want to always consume the deserialization gas + again, independently of the internal state of the lazy_exprs in + the arguments. *) + Script.Always + in + match operation with + | Reveal pk -> + (* TODO #2603 + + Even if [precheck_manager_contents] has already asserted that + the implicit contract is allocated, we must re-do this check in + case the manager has been emptied while collecting fees. This + should be solved by forking out [validate_operation] from + [apply_operation]. *) + let* () = Contract.must_be_allocated ctxt source_contract in + (* TODO tezos/tezos#3070 + + We have already asserted the consistency of the supplied public + key during precheck, so we avoid re-checking that precondition + with [?check_consistency=false]. This optional parameter is + temporary, to avoid breaking compatibility with external legacy + usage of [Contract.reveal_manager_key]. However, the pattern of + using [Contract.check_public_key] and this usage of + [Contract.reveal_manager_key] should become the standard. *) + let* ctxt = + Contract.reveal_manager_key ~check_consistency:false ctxt source pk + in + return + ( ctxt, + (Reveal_result + {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt} + : kind successful_manager_operation_result), + [] ) + | Transaction {amount; parameters; destination = Implicit pkh; entrypoint} + -> + let*? parameters, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas + ctxt + parameters + in + let elab_conf = Script_ir_translator_config.make ~legacy:false () in + let+ ctxt, res, ops = + match Entrypoint.to_string entrypoint with + | "default" -> + let* () = + fail_unless + (Script.is_unit parameters) + (Script_interpreter.Bad_contract_parameter source_contract) + in + apply_transaction_to_implicit + ~ctxt + ~sender:source_contract + ~amount + ~pkh + ~before_operation:ctxt_before_op + | "stake" -> + let* () = + fail_unless + (Script.is_unit parameters) + (Script_interpreter.Bad_contract_parameter source_contract) + in + let*? () = Staking.check_manual_staking_allowed ctxt in + apply_stake + ~ctxt + ~sender:source + ~amount + ~destination:pkh + ~before_operation:ctxt_before_op + | "unstake" -> + let* () = + fail_unless + (Script.is_unit parameters) + (Script_interpreter.Bad_contract_parameter source_contract) + in + let*? () = Staking.check_manual_staking_allowed ctxt in + apply_unstake + ~ctxt + ~sender:source + ~amount + ~destination:pkh + ~before_operation:ctxt_before_op + | "finalize_unstake" -> + let* () = + fail_unless + (Script.is_unit parameters) + (Script_interpreter.Bad_contract_parameter source_contract) + in + apply_finalize_unstake + ~ctxt + ~sender:source + ~amount + ~destination:pkh + ~before_operation:ctxt_before_op + | "set_delegate_parameters" -> + let* ( ( limit_of_staking_over_baking_millionth, + (edge_of_baking_over_staking_billionth, ()) ), + ctxt ) = + Script_ir_translator.parse_data + ~elab_conf + ctxt + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + Script_typed_ir.pair_int_int_unit_t + (Micheline.root parameters) + in + apply_set_delegate_parameters + ~ctxt + ~sender:source + ~destination:pkh + ~limit_of_staking_over_baking_millionth: + (Script_int.to_zint limit_of_staking_over_baking_millionth) + ~edge_of_baking_over_staking_billionth: + (Script_int.to_zint edge_of_baking_over_staking_billionth) + ~before_operation:ctxt_before_op + | _ -> tzfail (Script_tc_errors.No_such_entrypoint entrypoint) + in + (ctxt, Transaction_result res, ops) + | Transaction + {amount; parameters; destination = Originated contract_hash; entrypoint} + -> + let*? parameters, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas + ctxt + parameters + in + let* ctxt, (cache_key, script, script_ir) = + find_contract_from_cache ctxt contract_hash + in + let+ ctxt, res, ops = + if not @@ Constants.direct_ticket_spending_enable ctxt then + apply_transaction_to_smart_contract + ~ctxt + ~sender:(Destination.Contract source_contract) + ~contract_hash + ~amount + ~entrypoint + ~before_operation:ctxt_before_op + ~payer:source + ~chain_id + ~internal:false + ~parameter:(Untyped_arg parameters) + ~script + ~script_ir + ~cache_key + () + else + let (Ex_script (Script {arg_type; entrypoints; _})) = script_ir in + let*? res, ctxt = + Gas_monad.run + ctxt + (Script_ir_translator.find_entrypoint + ~error_details:(Informative ()) + arg_type + entrypoints + entrypoint) + in + let*? (Ex_ty_cstr {ty = parameters_ty; _}) = res in + let* typed_arg, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:false + parameters_ty + (Micheline.root parameters) + in + let* ctxt, ticket_receipt, paid_storage_diff = + Ticket_transfer.transfer_tickets_in_parameters + ctxt + typed_arg + parameters_ty + ~source:(Contract source_contract) + ~dst:(Contract (Originated contract_hash)) + in + apply_transaction_to_smart_contract + ~ctxt + ~sender:(Destination.Contract source_contract) + ~contract_hash + ~amount + ~entrypoint + ~before_operation:ctxt_before_op + ~payer:source + ~chain_id + ~internal:false + ~parameter: + (Typed_arg (Micheline.dummy_location, parameters_ty, typed_arg)) + ~script + ~script_ir + ~cache_key + ~ticket_receipt_acc:ticket_receipt + ~paid_storage_diff_acc:paid_storage_diff + () + in + (ctxt, Transaction_result res, ops) + | Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint} + -> ( + match destination with + | Implicit _ -> + let*? () = + error_unless + Entrypoint.(entrypoint = default) + (Script_tc_errors.No_such_entrypoint entrypoint) + in + let* ctxt, ticket = + Ticket_transfer.parse_ticket + ~consume_deserialization_gas + ~ticketer + ~contents + ~ty + ctxt + in + let* ctxt, paid_storage_size_diff = + Ticket_transfer.transfer_ticket + ctxt + ~sender:(Contract source_contract) + ~dst:(Contract destination) + ticket + amount + in + let* ticket_token, ctxt = + Ticket_token_unparser.unparse ctxt ticket + in + let amount = Script_int.(to_zint (amount :> n num)) in + let ticket_receipt = + Ticket_receipt. + [ + { + ticket_token; + updates = + [ + { + account = Contract source_contract; + amount = Z.neg amount; + }; + {account = Contract destination; amount}; + ]; + }; + ] + in + return + ( ctxt, + Transfer_ticket_result + { + balance_updates = []; + ticket_receipt; + consumed_gas = + Gas.consumed ~since:ctxt_before_op ~until:ctxt; + paid_storage_size_diff; + }, + [] ) + | Originated destination_hash -> + let* ctxt, token, op = + Ticket_transfer.parse_ticket_and_operation + ~consume_deserialization_gas + ~ticketer + ~contents + ~ty + ~sender:(Destination.Contract source_contract) + ~destination:destination_hash + ~entrypoint + ~amount + ctxt + in + let* ctxt, paid_storage_size_diff = + Ticket_transfer.transfer_ticket + ctxt + ~sender:(Contract source_contract) + ~dst:(Contract destination) + token + amount + in + let* ticket_token, ctxt = + Ticket_token_unparser.unparse ctxt token + in + let amount = Script_int.(to_zint (amount :> n num)) in + let ticket_receipt = + Ticket_receipt. + [ + { + ticket_token; + updates = + [ + { + account = Contract source_contract; + amount = Z.neg amount; + } + (* The transfer of the ticket to [destination] is part of the internal operation [op]. *); + ]; + }; + ] + in + return + ( ctxt, + Transfer_ticket_result + { + balance_updates = []; + ticket_receipt; + consumed_gas = + Gas.consumed ~since:ctxt_before_op ~until:ctxt; + paid_storage_size_diff; + }, + [op] )) + | Origination {delegate; script; credit} -> + (* Internal originations have their address generated in the interpreter + so that the script can use it immediately. + The address of external originations is generated here. *) + let*? ctxt, contract = + Contract.fresh_contract_from_current_nonce ctxt + in + let*? _unparsed_storage, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas + ctxt + script.Script.storage + in + let*? unparsed_code, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas + ctxt + script.Script.code + in + let* Ex_script parsed_script, ctxt = + Script_ir_translator.parse_script + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + ~allow_forged_tickets_in_storage:false + ~allow_forged_lazy_storage_id_in_storage:false + script + in + let (Script {storage_type; views; storage; _}) = parsed_script in + let views_result = + Script_ir_translator.parse_views + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + storage_type + views + in + let* _typed_views, ctxt = + trace + (Script_tc_errors.Ill_typed_contract (unparsed_code, [])) + views_result + in + let+ ctxt, origination_result, ops = + apply_origination + ~ctxt + ~storage_type + ~storage + ~unparsed_code + ~contract + ~delegate + ~sender:source_contract + ~credit + ~before_operation:ctxt_before_op + in + (ctxt, Origination_result origination_result, ops) + | Delegation delegate -> + let+ ctxt, consumed_gas, balance_updates, ops = + apply_delegation + ~ctxt + ~sender:source_contract + ~delegate + ~before_operation:ctxt_before_op + in + (ctxt, Delegation_result {consumed_gas; balance_updates}, ops) + | Register_global_constant {value} -> + (* Decode the value and consume gas appropriately *) + let*? expr, ctxt = + Script.force_decode_in_context ~consume_deserialization_gas ctxt value + in + (* Set the key to the value in storage. *) + let* ctxt, address, size = + Global_constants_storage.register ctxt expr + in + (* The burn and the reporting of the burn are calculated differently. + + [Fees.record_global_constant_storage_space] does the actual burn + based on the size of the constant registered, and this causes a + change in account balance. + + On the other hand, the receipt is calculated + with the help of [Fees.cost_of_bytes], and is included in block metadata + and the client output. The receipt is also used during simulation, + letting the client automatically set an appropriate storage limit. + TODO : is this concern still honored by the token management + refactoring ? *) + let ctxt, paid_size = + Fees.record_global_constant_storage_space ctxt size + in + let result = + Register_global_constant_result + { + balance_updates = []; + consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt; + size_of_constant = paid_size; + global_address = address; + } + in + return (ctxt, result, []) + | Set_deposits_limit limit -> + let*! is_registered = Delegate.registered ctxt source in + let*? () = + error_unless + is_registered + (Set_deposits_limit_on_unregistered_delegate source) + in + let is_autostaking_enabled = + match Staking.staking_automation ctxt with + | Manual_staking -> false + | Auto_staking -> true + in + let*? () = + error_unless + is_autostaking_enabled + Set_deposits_limit_when_automated_staking_off + in + let*! ctxt = Delegate.set_frozen_deposits_limit ctxt source limit in + return + ( ctxt, + Set_deposits_limit_result + {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt}, + [] ) + | Increase_paid_storage {amount_in_bytes; destination} -> + let* ctxt = + Contract.increase_paid_storage ctxt destination ~amount_in_bytes + in + let payer = `Contract (Contract.Implicit source) in + let+ ctxt, storage_bus = + Fees.burn_storage_increase_fees ctxt ~payer amount_in_bytes + in + let result = + Increase_paid_storage_result + { + balance_updates = storage_bus; + consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt; + } + in + (ctxt, result, []) + | Update_consensus_key pk -> + let*! is_registered = Delegate.registered ctxt source in + let*? () = + error_unless + is_registered + (Update_consensus_key_on_unregistered_delegate source) + in + let* ctxt = Delegate.Consensus_key.register_update ctxt source pk in + return + ( ctxt, + Update_consensus_key_result + {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt}, + [] ) + | Dal_publish_commitment slot_header -> + let*? ctxt, slot_header = + Dal_apply.apply_publish_commitment ctxt slot_header + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Dal_publish_commitment_result {slot_header; consumed_gas} + in + return (ctxt, result, []) + | Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist} -> + let* {address; size; genesis_commitment_hash}, ctxt = + Sc_rollup_operations.originate + ctxt + ~kind + ~boot_sector + ~parameters_ty + ?whitelist + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Sc_rollup_originate_result + { + address; + genesis_commitment_hash; + consumed_gas; + size; + balance_updates = []; + } + in + return (ctxt, result, []) + | Sc_rollup_add_messages {messages} -> + let* ctxt = Sc_rollup.Inbox.add_external_messages ctxt messages in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = Sc_rollup_add_messages_result {consumed_gas} in + return (ctxt, result, []) + | Sc_rollup_cement {rollup} -> + let* ctxt, commitment, commitment_hash = + Sc_rollup.Stake_storage.cement_commitment ctxt rollup + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Sc_rollup_cement_result + { + consumed_gas; + inbox_level = commitment.inbox_level; + commitment_hash; + } + in + return (ctxt, result, []) + | Sc_rollup_publish {rollup; commitment} -> + let* staked_hash, published_at_level, ctxt, balance_updates = + Sc_rollup.Stake_storage.publish_commitment + ctxt + rollup + source + commitment + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Sc_rollup_publish_result + {staked_hash; consumed_gas; published_at_level; balance_updates} + in + return (ctxt, result, []) + | Sc_rollup_refute {rollup; opponent; refutation} -> + let open Sc_rollup.Refutation_storage in + let player = source in + let* game_result, ctxt = + match refutation with + | Start {player_commitment_hash; opponent_commitment_hash} -> + let* ctxt = + start_game + ctxt + rollup + ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash) + in + return (None, ctxt) + | Move {step; choice} -> + game_move ctxt rollup ~player ~opponent ~step ~choice + in + let* game_status, ctxt, balance_updates = + match game_result with + | None -> return (Sc_rollup.Game.Ongoing, ctxt, []) + | Some game_result -> + let stakers = Sc_rollup.Game.Index.make source opponent in + Sc_rollup.Refutation_storage.apply_game_result + ctxt + rollup + stakers + game_result + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Sc_rollup_refute_result {game_status; consumed_gas; balance_updates} + in + return (ctxt, result, []) + | Sc_rollup_timeout {rollup; stakers} -> + let* game_result, ctxt = + Sc_rollup.Refutation_storage.timeout ctxt rollup stakers + in + let* game_status, ctxt, balance_updates = + Sc_rollup.Refutation_storage.apply_game_result + ctxt + rollup + stakers + game_result + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Sc_rollup_timeout_result {game_status; consumed_gas; balance_updates} + in + return (ctxt, result, []) + | Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof} -> + let+ ( { + Sc_rollup_operations.paid_storage_size_diff; + ticket_receipt; + whitelist_update; + operations; + }, + ctxt ) = + Sc_rollup_operations.execute_outbox_message + ctxt + rollup + ~cemented_commitment + ~output_proof + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Sc_rollup_execute_outbox_message_result + { + paid_storage_size_diff; + ticket_receipt; + whitelist_update; + balance_updates = []; + consumed_gas; + } + in + (ctxt, result, operations) + | Sc_rollup_recover_bond {sc_rollup; staker} -> + let* ctxt, balance_updates = + Sc_rollup.Stake_storage.withdraw_stake ctxt sc_rollup staker + in + let result = + Sc_rollup_recover_bond_result + { + consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt; + balance_updates; + } + in + return (ctxt, result, []) + | Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops} -> + Zk_rollup_apply.originate + ~ctxt_before_op + ~ctxt + ~public_parameters + ~circuits_info + ~init_state + ~nb_ops + | Zk_rollup_publish {zk_rollup; ops} -> + Zk_rollup_apply.publish ~ctxt_before_op ~ctxt ~zk_rollup ~l2_ops:ops + | Zk_rollup_update {zk_rollup; update} -> + Zk_rollup_apply.update ~ctxt_before_op ~ctxt ~zk_rollup ~update + +type success_or_failure = Success of context | Failure + +let apply_internal_operations ctxt ~payer ~chain_id ops = + let open Lwt_syntax in + let rec apply ctxt applied worklist = + match worklist with + | [] -> Lwt.return (Success ctxt, List.rev applied) + | Script_typed_ir.Internal_operation ({sender; operation; nonce} as op) + :: rest -> ( + let* result = + if internal_nonce_already_recorded ctxt nonce then + let op_res = Apply_internal_results.internal_operation op in + tzfail (Internal_operation_replay (Internal_operation op_res)) + else + let ctxt = record_internal_nonce ctxt nonce in + apply_internal_operation_contents + ctxt + ~sender + ~payer + ~chain_id + operation + in + match result with + | Error errors -> + let result = + pack_internal_operation_result + op + (Failed (Script_typed_ir.manager_kind op.operation, errors)) + in + let skipped = + List.rev_map + (fun (Script_typed_ir.Internal_operation op) -> + pack_internal_operation_result + op + (Skipped (Script_typed_ir.manager_kind op.operation))) + rest + in + Lwt.return (Failure, List.rev (skipped @ (result :: applied))) + | Ok (ctxt, result, emitted) -> + apply + ctxt + (pack_internal_operation_result op (Applied result) :: applied) + (emitted @ rest)) + in + apply ctxt [] ops + +let burn_transaction_storage_fees ctxt trr ~storage_limit ~payer = + let open Lwt_result_syntax in + match trr with + | Transaction_to_contract_result payload -> + let consumed = payload.paid_storage_size_diff in + let* ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let* ctxt, storage_limit, origination_bus = + if payload.allocated_destination_contract then + Fees.burn_origination_fees ctxt ~storage_limit ~payer + else return (ctxt, storage_limit, []) + in + let balance_updates = + storage_bus @ payload.balance_updates @ origination_bus + in + return + ( ctxt, + storage_limit, + Transaction_to_contract_result + { + storage = payload.storage; + lazy_storage_diff = payload.lazy_storage_diff; + balance_updates; + ticket_receipt = payload.ticket_receipt; + originated_contracts = payload.originated_contracts; + consumed_gas = payload.consumed_gas; + storage_size = payload.storage_size; + paid_storage_size_diff = payload.paid_storage_size_diff; + allocated_destination_contract = + payload.allocated_destination_contract; + } ) + | Transaction_to_sc_rollup_result _ -> return (ctxt, storage_limit, trr) + | Transaction_to_zk_rollup_result payload -> + let consumed = payload.paid_storage_size_diff in + let* ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let balance_updates = storage_bus @ payload.balance_updates in + return + ( ctxt, + storage_limit, + Transaction_to_zk_rollup_result {payload with balance_updates} ) + +let burn_origination_storage_fees ctxt + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + } ~storage_limit ~payer = + let open Lwt_result_syntax in + let consumed = paid_storage_size_diff in + let* ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let* ctxt, storage_limit, origination_bus = + Fees.burn_origination_fees ctxt ~storage_limit ~payer + in + let balance_updates = storage_bus @ origination_bus @ balance_updates in + return + ( ctxt, + storage_limit, + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + } ) + +(** [burn_manager_storage_fees ctxt smopr storage_limit payer] burns the + storage fees associated to an external operation result [smopr]. + Returns an updated context, an updated storage limit with the space consumed + by the operation subtracted, and [smopr] with the relevant balance updates + included. *) +let burn_manager_storage_fees : + type kind. + context -> + kind successful_manager_operation_result -> + storage_limit:Z.t -> + payer:public_key_hash -> + (context * Z.t * kind successful_manager_operation_result) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt smopr ~storage_limit ~payer -> + let payer = `Contract (Contract.Implicit payer) in + match smopr with + | Transaction_result transaction_result -> + let+ ctxt, storage_limit, transaction_result = + burn_transaction_storage_fees + ctxt + transaction_result + ~storage_limit + ~payer + in + (ctxt, storage_limit, Transaction_result transaction_result) + | Origination_result origination_result -> + let+ ctxt, storage_limit, origination_result = + burn_origination_storage_fees + ctxt + origination_result + ~storage_limit + ~payer + in + (ctxt, storage_limit, Origination_result origination_result) + | Reveal_result _ | Delegation_result _ -> + return (ctxt, storage_limit, smopr) + | Register_global_constant_result payload -> + let consumed = payload.size_of_constant in + let+ ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let balance_updates = storage_bus @ payload.balance_updates in + ( ctxt, + storage_limit, + Register_global_constant_result + { + balance_updates; + consumed_gas = payload.consumed_gas; + size_of_constant = payload.size_of_constant; + global_address = payload.global_address; + } ) + | Set_deposits_limit_result _ | Update_consensus_key_result _ -> + return (ctxt, storage_limit, smopr) + | Increase_paid_storage_result _ -> return (ctxt, storage_limit, smopr) + | Transfer_ticket_result payload -> + let consumed = payload.paid_storage_size_diff in + let+ ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let balance_updates = payload.balance_updates @ storage_bus in + ( ctxt, + storage_limit, + Transfer_ticket_result {payload with balance_updates} ) + | Dal_publish_commitment_result _ -> return (ctxt, storage_limit, smopr) + | Sc_rollup_originate_result payload -> + let+ ctxt, storage_limit, balance_updates = + Fees.burn_sc_rollup_origination_fees + ctxt + ~storage_limit + ~payer + payload.size + in + let result = + Sc_rollup_originate_result {payload with balance_updates} + in + (ctxt, storage_limit, result) + | Sc_rollup_add_messages_result _ -> return (ctxt, storage_limit, smopr) + | Sc_rollup_cement_result _ -> return (ctxt, storage_limit, smopr) + | Sc_rollup_publish_result _ -> return (ctxt, storage_limit, smopr) + | Sc_rollup_refute_result _ -> return (ctxt, storage_limit, smopr) + | Sc_rollup_timeout_result _ -> return (ctxt, storage_limit, smopr) + | Sc_rollup_execute_outbox_message_result + ({paid_storage_size_diff; balance_updates; _} as payload) -> + let consumed = paid_storage_size_diff in + let+ ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let balance_updates = storage_bus @ balance_updates in + ( ctxt, + storage_limit, + Sc_rollup_execute_outbox_message_result {payload with balance_updates} + ) + | Sc_rollup_recover_bond_result _ -> return (ctxt, storage_limit, smopr) + | Zk_rollup_origination_result payload -> + let* ctxt, storage_limit, balance_updates = + Fees.burn_zk_rollup_origination_fees + ctxt + ~storage_limit + ~payer + payload.storage_size + in + let result = + Zk_rollup_origination_result {payload with balance_updates} + in + return (ctxt, storage_limit, result) + | Zk_rollup_publish_result payload -> + let consumed = payload.paid_storage_size_diff in + let+ ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let balance_updates = storage_bus @ payload.balance_updates in + ( ctxt, + storage_limit, + Zk_rollup_publish_result {payload with balance_updates} ) + | Zk_rollup_update_result + ({paid_storage_size_diff; balance_updates; _} as payload) -> + let consumed = paid_storage_size_diff in + let+ ctxt, storage_limit, storage_bus = + Fees.burn_storage_fees ctxt ~storage_limit ~payer consumed + in + let balance_updates = storage_bus @ balance_updates in + ( ctxt, + storage_limit, + Zk_rollup_update_result {payload with balance_updates} ) + +(** [burn_internal_storage_fees ctxt smopr storage_limit payer] burns the + storage fees associated to an internal operation result [smopr]. + Returns an updated context, an updated storage limit with the space consumed + by the operation subtracted, and [smopr] with the relevant balance updates + included. *) +let burn_internal_storage_fees : + type kind. + context -> + kind successful_internal_operation_result -> + storage_limit:Z.t -> + payer:public_key_hash -> + (context * Z.t * kind successful_internal_operation_result) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt smopr ~storage_limit ~payer -> + let payer = `Contract (Contract.Implicit payer) in + match smopr with + | ITransaction_result transaction_result -> + let+ ctxt, storage_limit, transaction_result = + burn_transaction_storage_fees + ctxt + transaction_result + ~storage_limit + ~payer + in + (ctxt, storage_limit, ITransaction_result transaction_result) + | IOrigination_result origination_result -> + let+ ctxt, storage_limit, origination_result = + burn_origination_storage_fees + ctxt + origination_result + ~storage_limit + ~payer + in + (ctxt, storage_limit, IOrigination_result origination_result) + | IDelegation_result _ -> return (ctxt, storage_limit, smopr) + | IEvent_result _ -> return (ctxt, storage_limit, smopr) + +let apply_manager_contents (type kind) ctxt chain_id ~consume_gas_for_sig_check + (op : kind Kind.manager contents) : + (success_or_failure + * kind manager_operation_result + * packed_internal_operation_result list) + Lwt.t = + let open Lwt_result_syntax in + let (Manager_operation {source; operation; gas_limit; storage_limit; _}) = + op + in + (* We do not expose the internal scaling to the users. Instead, we multiply + the specified gas limit by the internal scaling. *) + let ctxt = Gas.set_limit ctxt gas_limit in + let*! result = + apply_manager_operation + ctxt + ~source + ~chain_id + ~consume_gas_for_sig_check + operation + in + match result with + | Ok (ctxt, operation_results, internal_operations) -> ( + let*! result = + apply_internal_operations + ctxt + ~payer:source + ~chain_id + internal_operations + in + match result with + | Success ctxt, internal_operations_results -> ( + let*! result = + burn_manager_storage_fees + ctxt + operation_results + ~storage_limit + ~payer:source + in + match result with + | Ok (ctxt, storage_limit, operation_results) -> + let*! result = + List.fold_left_es + (fun (ctxt, storage_limit, res) imopr -> + let (Internal_operation_result (op, mopr)) = imopr in + match mopr with + | Applied smopr -> + let* ctxt, storage_limit, smopr = + burn_internal_storage_fees + ctxt + smopr + ~storage_limit + ~payer:source + in + let imopr = + Internal_operation_result (op, Applied smopr) + in + return (ctxt, storage_limit, imopr :: res) + | _ -> return (ctxt, storage_limit, imopr :: res)) + (ctxt, storage_limit, []) + internal_operations_results + in + Lwt.return + (match result with + | Ok (ctxt, _, internal_operations_results) -> + ( Success ctxt, + Applied operation_results, + List.rev internal_operations_results ) + | Error errors -> + ( Failure, + Backtracked (operation_results, Some errors), + internal_operations_results )) + | Error errors -> + Lwt.return + ( Failure, + Backtracked (operation_results, Some errors), + internal_operations_results )) + | Failure, internal_operations_results -> + Lwt.return + (Failure, Applied operation_results, internal_operations_results)) + | Error errors -> + Lwt.return (Failure, Failed (manager_kind operation, errors), []) + +(** An individual manager operation (either standalone or inside a + batch) together with the balance update corresponding to the + transfer of its fee. *) +type 'kind fees_updated_contents = { + contents : 'kind contents; + balance_updates : Receipt.balance_updates; +} + +type _ fees_updated_contents_list = + | FeesUpdatedSingle : + 'kind fees_updated_contents + -> 'kind fees_updated_contents_list + | FeesUpdatedCons : + 'kind Kind.manager fees_updated_contents + * 'rest Kind.manager fees_updated_contents_list + -> ('kind * 'rest) Kind.manager fees_updated_contents_list + +let rec mark_skipped : + type kind. + payload_producer:Consensus_key.t -> + Level.t -> + kind Kind.manager fees_updated_contents_list -> + kind Kind.manager contents_result_list = + fun ~payload_producer level fees_updated_contents_list -> + match fees_updated_contents_list with + | FeesUpdatedSingle + {contents = Manager_operation {operation; _}; balance_updates} -> + Single_result + (Manager_operation_result + { + balance_updates; + operation_result = Skipped (manager_kind operation); + internal_operation_results = []; + }) + | FeesUpdatedCons + ({contents = Manager_operation {operation; _}; balance_updates}, rest) -> + Cons_result + ( Manager_operation_result + { + balance_updates; + operation_result = Skipped (manager_kind operation); + internal_operation_results = []; + }, + mark_skipped ~payload_producer level rest ) + +(** Return balance updates for fees, and an updated context that + accounts for: + + - fees spending, + + - counter incrementation, + + - consumption of each operation's [gas_limit] from the available + block gas. + + The operation should already have been validated by + {!Validate.validate_operation}. The latter is responsible for ensuring that + the operation is solvable, i.e. its fees can be taken, i.e. + [take_fees] cannot return an error. *) +let take_fees ctxt contents_list = + let open Lwt_result_syntax in + let rec take_fees_rec : + type kind. + context -> + kind Kind.manager contents_list -> + (context * kind Kind.manager fees_updated_contents_list) tzresult Lwt.t = + fun ctxt contents_list -> + let contents_effects contents = + let (Manager_operation {source; fee; gas_limit; _}) = contents in + let*? ctxt = Gas.consume_limit_in_block ctxt gas_limit in + let* ctxt = Contract.increment_counter ctxt source in + let+ ctxt, balance_updates = + Token.transfer + ctxt + (`Contract (Contract.Implicit source)) + `Block_fees + fee + in + (ctxt, {contents; balance_updates}) + in + match contents_list with + | Single contents -> + let+ ctxt, fees_updated_contents = contents_effects contents in + (ctxt, FeesUpdatedSingle fees_updated_contents) + | Cons (contents, rest) -> + let* ctxt, fees_updated_contents = contents_effects contents in + let+ ctxt, result_rest = take_fees_rec ctxt rest in + (ctxt, FeesUpdatedCons (fees_updated_contents, result_rest)) + in + let*! result = take_fees_rec ctxt contents_list in + Lwt.return (record_trace Error_while_taking_fees result) + +let rec apply_manager_contents_list_rec : + type kind. + context -> + payload_producer:Consensus_key.t -> + Chain_id.t -> + consume_gas_for_sig_check:Gas.cost option -> + kind Kind.manager fees_updated_contents_list -> + (success_or_failure * kind Kind.manager contents_result_list) Lwt.t = + let open Lwt_syntax in + fun ctxt + ~payload_producer + chain_id + ~consume_gas_for_sig_check + fees_updated_contents_list -> + let level = Level.current ctxt in + match fees_updated_contents_list with + | FeesUpdatedSingle {contents = Manager_operation _ as op; balance_updates} + -> + let+ ctxt_result, operation_result, internal_operation_results = + apply_manager_contents ctxt chain_id ~consume_gas_for_sig_check op + in + let result = + Manager_operation_result + {balance_updates; operation_result; internal_operation_results} + in + (ctxt_result, Single_result result) + | FeesUpdatedCons + ({contents = Manager_operation _ as op; balance_updates}, rest) -> ( + let* result = + apply_manager_contents ctxt chain_id ~consume_gas_for_sig_check op + in + match result with + | Failure, operation_result, internal_operation_results -> + let result = + Manager_operation_result + {balance_updates; operation_result; internal_operation_results} + in + Lwt.return + ( Failure, + Cons_result (result, mark_skipped ~payload_producer level rest) + ) + | Success ctxt, operation_result, internal_operation_results -> + let result = + Manager_operation_result + {balance_updates; operation_result; internal_operation_results} + in + let+ ctxt_result, results = + apply_manager_contents_list_rec + ctxt + ~payload_producer + chain_id + ~consume_gas_for_sig_check:None + rest + in + (ctxt_result, Cons_result (result, results))) + +let mark_backtracked results = + let mark_results : + type kind. + kind Kind.manager contents_result -> kind Kind.manager contents_result = + fun results -> + let mark_manager_operation_result : + type kind. + kind manager_operation_result -> kind manager_operation_result = + function + | (Failed _ | Skipped _ | Backtracked _) as result -> result + | Applied result -> Backtracked (result, None) + in + let mark_internal_operation_result : + type kind. + kind internal_operation_result -> kind internal_operation_result = + function + | (Failed _ | Skipped _ | Backtracked _) as result -> result + | Applied result -> Backtracked (result, None) + in + let mark_internal_operation_results + (Internal_operation_result (kind, result)) = + Internal_operation_result (kind, mark_internal_operation_result result) + in + match results with + | Manager_operation_result op -> + Manager_operation_result + { + balance_updates = op.balance_updates; + operation_result = mark_manager_operation_result op.operation_result; + internal_operation_results = + List.map + mark_internal_operation_results + op.internal_operation_results; + } + in + let rec traverse_apply_results : + type kind. + kind Kind.manager contents_result_list -> + kind Kind.manager contents_result_list = function + | Single_result res -> Single_result (mark_results res) + | Cons_result (res, rest) -> + Cons_result (mark_results res, traverse_apply_results rest) + in + traverse_apply_results results + +type mode = + | Application of { + block_header : Block_header.t; + fitness : Fitness.t; + payload_producer : Consensus_key.t; + block_producer : Consensus_key.t; + predecessor_level : Level.t; + predecessor_round : Round.t; + } + | Full_construction of { + block_data_contents : Block_header.contents; + predecessor_hash : Block_hash.t; + payload_producer : Consensus_key.t; + block_producer : Consensus_key.t; + round : Round.t; + predecessor_level : Level.t; + predecessor_round : Round.t; + } + | Partial_construction of {predecessor_fitness : Fitness.raw} + +type application_state = { + ctxt : t; + chain_id : Chain_id.t; + mode : mode; + op_count : int; + migration_balance_updates : Receipt.balance_updates; + liquidity_baking_toggle_ema : Per_block_votes.Liquidity_baking_toggle_EMA.t; + adaptive_issuance_vote_ema : Per_block_votes.Adaptive_issuance_launch_EMA.t; + adaptive_issuance_launch_cycle : Cycle.t option; + implicit_operations_results : + Apply_results.packed_successful_manager_operation_result list; +} + +let record_operation (type kind) ctxt hash (operation : kind operation) : + context = + match operation.protocol_data.contents with + | Single (Preattestation _) -> ctxt + | Single (Attestation _) -> ctxt + | Single + ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ + | Vdf_revelation _ | Double_attestation_evidence _ + | Double_preattestation_evidence _ | Double_baking_evidence _ + | Activate_account _ | Drain_delegate _ | Manager_operation _ ) + | Cons (Manager_operation _, _) -> + record_non_consensus_operation_hash ctxt hash + +let find_in_slot_map slot slot_map = + let open Result_syntax in + match slot_map with + | None -> tzfail (Consensus.Slot_map_not_found {loc = __LOC__}) + | Some slot_map -> ( + match Slot.Map.find slot slot_map with + | None -> + (* This should not happen: operation validation should have failed. *) + tzfail Faulty_validation_wrong_slot + | Some (consensus_key, power, dal_power) -> + return (consensus_key, power, dal_power)) + +let record_preattestation ctxt (mode : mode) (content : consensus_content) : + (context * Kind.preattestation contents_result_list) tzresult Lwt.t = + let open Lwt_result_syntax in + let ctxt = + match mode with + | Full_construction _ -> ( + match Consensus.get_preattestations_quorum_round ctxt with + | None -> Consensus.set_preattestations_quorum_round ctxt content.round + | Some _ -> ctxt) + | Application _ | Partial_construction _ -> ctxt + in + let mk_preattestation_result ({delegate; consensus_pkh; _} : Consensus_key.pk) + consensus_power = + Single_result + (Preattestation_result + { + balance_updates = []; + delegate; + consensus_key = consensus_pkh; + consensus_power; + }) + in + match mode with + | Application _ | Full_construction _ -> + let*? consensus_key, power, _dal_power = + find_in_slot_map content.slot (Consensus.allowed_preattestations ctxt) + in + let*? ctxt = + Consensus.record_preattestation + ctxt + ~initial_slot:content.slot + ~power + content.round + in + return (ctxt, mk_preattestation_result consensus_key power) + | Partial_construction _ -> + (* In mempool mode, preattestations are allowed for various levels + and rounds. We do not record preattestations because we could get + false-positive conflicts for preattestations with the same slot + but different levels/rounds. We could record just preattestations + for the mempool head's level and round (the most usual + preattestations), but we don't need to, because there is no block + to finalize anyway in this mode. *) + let* ctxt, consensus_key = + let level = Level.from_raw ctxt content.level in + Stake_distribution.slot_owner ctxt level content.slot + in + return (ctxt, mk_preattestation_result consensus_key 0 (* Fake power. *)) + +let record_attestation ctxt (mode : mode) (consensus : consensus_content) + (dal : dal_content option) : + (context * Kind.attestation contents_result_list) tzresult Lwt.t = + let open Lwt_result_syntax in + let mk_attestation_result ({delegate; consensus_pkh; _} : Consensus_key.pk) + consensus_power = + Single_result + (Attestation_result + { + balance_updates = []; + delegate; + consensus_key = consensus_pkh; + consensus_power; + }) + in + match mode with + | Application _ | Full_construction _ -> + let*? consensus_key, power, dal_power = + find_in_slot_map consensus.slot (Consensus.allowed_attestations ctxt) + in + let*? ctxt = + Consensus.record_attestation ctxt ~initial_slot:consensus.slot ~power + in + let*? ctxt = + Option.fold + ~none:(Result_syntax.return ctxt) + ~some:(fun dal -> + Dal_apply.apply_attestation ctxt dal.attestation ~power:dal_power) + dal + in + return (ctxt, mk_attestation_result consensus_key power) + | Partial_construction _ -> + (* In mempool mode, attestations are allowed for various levels + and rounds. We do not record attestations because we could get + false-positive conflicts for attestations with the same slot + but different levels/rounds. We could record just attestations + for the predecessor's level and round (the most usual + attestations), but we don't need to, because there is no block + to finalize anyway in this mode. *) + let* ctxt, consensus_key = + let level = Level.from_raw ctxt consensus.level in + Stake_distribution.slot_owner ctxt level consensus.slot + in + return (ctxt, mk_attestation_result consensus_key 0 (* Fake power. *)) + +let apply_manager_contents_list ctxt ~payload_producer chain_id + ~gas_cost_for_sig_check fees_updated_contents_list = + let open Lwt_syntax in + let* ctxt_result, results = + apply_manager_contents_list_rec + ctxt + ~payload_producer + chain_id + ~consume_gas_for_sig_check:(Some gas_cost_for_sig_check) + fees_updated_contents_list + in + match ctxt_result with + | Failure -> Lwt.return (ctxt (* backtracked *), mark_backtracked results) + | Success ctxt -> + let+ ctxt = Lazy_storage.cleanup_temporaries ctxt in + (ctxt, results) + +let apply_manager_operations ctxt ~payload_producer chain_id ~mempool_mode + ~source ~operation contents_list = + let open Lwt_result_syntax in + let ctxt = if mempool_mode then Gas.reset_block_gas ctxt else ctxt in + let* ctxt, fees_updated_contents_list = take_fees ctxt contents_list in + let gas_cost_for_sig_check = + let algo = + Michelson_v1_gas.Cost_of.Interpreter.algo_of_public_key_hash source + in + Operation_costs.check_signature_cost algo operation + in + let*! ctxt, contents_result_list = + apply_manager_contents_list + ctxt + ~payload_producer + chain_id + ~gas_cost_for_sig_check + fees_updated_contents_list + in + return (ctxt, contents_result_list) + +let punish_delegate ctxt ~operation_hash delegate level misbehaviour mk_result + ~payload_producer = + let open Lwt_result_syntax in + let rewarded = payload_producer.Consensus_key.delegate in + let+ ctxt = + Delegate.punish_double_signing + ctxt + ~operation_hash + misbehaviour + delegate + level + ~rewarded + in + (ctxt, Single_result (mk_result (Some delegate) [])) + +let punish_double_attestation_or_preattestation (type kind) ctxt ~operation_hash + ~(op1 : kind Kind.consensus Operation.t) ~payload_producer : + (context + * kind Kind.double_consensus_operation_evidence contents_result_list) + tzresult + Lwt.t = + let open Lwt_result_syntax in + let mk_result forbidden_delegate (balance_updates : Receipt.balance_updates) : + kind Kind.double_consensus_operation_evidence contents_result = + match op1.protocol_data.contents with + | Single (Preattestation _) -> + Double_preattestation_evidence_result + {forbidden_delegate; balance_updates} + | Single (Attestation _) -> + Double_attestation_evidence_result {forbidden_delegate; balance_updates} + in + let {slot; level = raw_level; round; block_payload_hash = _}, kind = + match op1.protocol_data.contents with + | Single (Preattestation consensus_content) -> + (consensus_content, Misbehaviour.Double_preattesting) + | Single (Attestation {consensus_content; dal_content = _}) -> + (consensus_content, Misbehaviour.Double_attesting) + in + let level = Level.from_raw ctxt raw_level in + let* ctxt, consensus_pk1 = Stake_distribution.slot_owner ctxt level slot in + punish_delegate + ctxt + ~operation_hash + consensus_pk1.delegate + level + {level = raw_level; round; kind} + mk_result + ~payload_producer + +let punish_double_baking ctxt ~operation_hash (bh1 : Block_header.t) + ~payload_producer = + let open Lwt_result_syntax in + let*? bh1_fitness = Fitness.from_raw bh1.shell.fitness in + let round1 = Fitness.round bh1_fitness in + let*? raw_level = Raw_level.of_int32 bh1.shell.level in + let level = Level.from_raw ctxt raw_level in + let committee_size = Constants.consensus_committee_size ctxt in + let*? slot1 = Round.to_slot round1 ~committee_size in + let* ctxt, consensus_pk1 = Stake_distribution.slot_owner ctxt level slot1 in + punish_delegate + ctxt + ~operation_hash + consensus_pk1.delegate + level + {level = raw_level; round = round1; kind = Double_baking} + ~payload_producer + (fun forbidden_delegate balance_updates -> + Double_baking_evidence_result {forbidden_delegate; balance_updates}) + +let apply_contents_list (type kind) ctxt chain_id (mode : mode) + ~payload_producer ~operation ~operation_hash + (contents_list : kind contents_list) : + (context * kind contents_result_list) tzresult Lwt.t = + let open Lwt_result_syntax in + let mempool_mode = + match mode with + | Partial_construction _ -> true + | Full_construction _ | Application _ -> false + in + match contents_list with + | Single (Preattestation consensus_content) -> + record_preattestation ctxt mode consensus_content + | Single (Attestation {consensus_content; dal_content}) -> + record_attestation ctxt mode consensus_content dal_content + | Single (Seed_nonce_revelation {level; nonce}) -> + let level = Level.from_raw ctxt level in + let* ctxt = Nonce.reveal ctxt level nonce in + let*? tip = Delegate.Rewards.seed_nonce_revelation_tip ctxt in + let delegate = payload_producer.Consensus_key.delegate in + let+ ctxt, balance_updates = + Delegate.Shared_stake.pay_rewards + ctxt + ~source:`Revelation_rewards + ~delegate + tip + in + (ctxt, Single_result (Seed_nonce_revelation_result balance_updates)) + | Single (Vdf_revelation {solution}) -> + let* ctxt = Seed.update_seed ctxt solution in + let*? tip = Delegate.Rewards.vdf_revelation_tip ctxt in + let delegate = payload_producer.Consensus_key.delegate in + let+ ctxt, balance_updates = + Delegate.Shared_stake.pay_rewards + ctxt + ~source:`Revelation_rewards + ~delegate + tip + in + (ctxt, Single_result (Vdf_revelation_result balance_updates)) + | Single (Double_preattestation_evidence {op1; op2 = _}) -> + punish_double_attestation_or_preattestation + ctxt + ~operation_hash + ~op1 + ~payload_producer + | Single (Double_attestation_evidence {op1; op2 = _}) -> + punish_double_attestation_or_preattestation + ctxt + ~operation_hash + ~op1 + ~payload_producer + | Single (Double_baking_evidence {bh1; bh2 = _}) -> + punish_double_baking ctxt ~operation_hash bh1 ~payload_producer + | Single (Activate_account {id = pkh; activation_code}) -> + let blinded_pkh = + Blinded_public_key_hash.of_ed25519_pkh activation_code pkh + in + let sender = `Collected_commitments blinded_pkh in + let contract = Contract.Implicit (Signature.Ed25519 pkh) in + let* ctxt, amount = Token.balance ctxt sender in + let* ctxt, bupds = + Token.transfer ctxt sender (`Contract contract) amount + in + return (ctxt, Single_result (Activate_account_result bupds)) + | Single (Proposals _ as contents) -> + Amendment.apply_proposals ctxt chain_id contents + | Single (Ballot _ as contents) -> Amendment.apply_ballot ctxt contents + | Single (Drain_delegate {delegate; destination; consensus_key = _}) -> + let* ctxt, allocated_destination_contract, fees, drain_balance_updates = + Delegate.drain ctxt ~delegate ~destination + in + let* ctxt, fees_balance_updates = + Token.transfer + ctxt + (`Contract (Contract.Implicit delegate)) + (`Contract + (Contract.Implicit payload_producer.Consensus_key.delegate)) + fees + in + let balance_updates = drain_balance_updates @ fees_balance_updates in + return + ( ctxt, + Single_result + (Drain_delegate_result + {balance_updates; allocated_destination_contract}) ) + | Single (Failing_noop _) -> + (* This operation always fails. It should already have been + rejected by {!Validate.validate_operation}. *) + tzfail Validate_errors.Failing_noop_error + | Single (Manager_operation {source; _}) -> + apply_manager_operations + ctxt + ~payload_producer + chain_id + ~mempool_mode + ~source + ~operation + contents_list + | Cons (Manager_operation {source; _}, _) -> + apply_manager_operations + ctxt + ~payload_producer + chain_id + ~mempool_mode + ~source + ~operation + contents_list + +let apply_operation application_state operation_hash operation = + let open Lwt_result_syntax in + let apply_operation application_state packed_operation ~payload_producer = + let {shell; protocol_data = Operation_data unpacked_protocol_data} = + packed_operation + in + let operation : _ Operation.t = + {shell; protocol_data = unpacked_protocol_data} + in + let ctxt = Origination_nonce.init application_state.ctxt operation_hash in + let ctxt = record_operation ctxt operation_hash operation in + let* ctxt, result = + apply_contents_list + ctxt + application_state.chain_id + application_state.mode + ~payload_producer + ~operation + ~operation_hash + operation.protocol_data.contents + in + let ctxt = Gas.set_unlimited ctxt in + let ctxt = Origination_nonce.unset ctxt in + let op_count = succ application_state.op_count in + return + ( {application_state with ctxt; op_count}, + Operation_metadata {contents = result} ) + in + match application_state.mode with + | Application {payload_producer; _} -> + apply_operation application_state operation ~payload_producer + | Full_construction {payload_producer; _} -> + apply_operation application_state operation ~payload_producer + | Partial_construction _ -> + apply_operation + application_state + operation + ~payload_producer:Consensus_key.zero + +let may_start_new_cycle ctxt = + let open Lwt_result_syntax in + match Level.dawn_of_a_new_cycle ctxt with + | None -> return (ctxt, [], []) + | Some last_cycle -> + let* ctxt, balance_updates, deactivated = + Delegate.cycle_end ctxt last_cycle + in + let+ ctxt = Bootstrap.cycle_end ctxt last_cycle in + (ctxt, balance_updates, deactivated) + +let apply_liquidity_baking_subsidy ctxt ~per_block_vote = + let open Lwt_result_syntax in + Liquidity_baking.on_subsidy_allowed + ctxt + ~per_block_vote + (fun ctxt liquidity_baking_cpmm_contract_hash -> + let liquidity_baking_cpmm_contract = + Contract.Originated liquidity_baking_cpmm_contract_hash + in + let ctxt = + (* We set a gas limit of 1/20th the block limit, which is ~10x + actual usage here in Granada. Gas consumed is reported in + the Transaction receipt, but not counted towards the block + limit. The gas limit is reset to unlimited at the end of + this function.*) + Gas.set_limit + ctxt + (Gas.Arith.integral_exn + (Z.div + (Gas.Arith.integral_to_z + (Constants.hard_gas_limit_per_block ctxt)) + (Z.of_int 20))) + in + let backtracking_ctxt = ctxt in + let*! result = + let*? liquidity_baking_subsidy = + Delegate.Rewards.liquidity_baking_subsidy ctxt + in + (* credit liquidity baking subsidy to CPMM contract *) + let* ctxt, balance_updates = + Token.transfer + ~origin:Subsidy + ctxt + `Liquidity_baking_subsidies + (`Contract liquidity_baking_cpmm_contract) + liquidity_baking_subsidy + in + let* ctxt, cache_key, script = + Script_cache.find ctxt liquidity_baking_cpmm_contract_hash + in + match script with + | None -> + tzfail (Script_tc_errors.No_such_entrypoint Entrypoint.default) + | Some (script, script_ir) -> ( + (* Token.transfer which is being called above already loads this + value into the Irmin cache, so no need to burn gas for it. *) + let* balance = + Contract.get_balance ctxt liquidity_baking_cpmm_contract + in + let now = Script_timestamp.now ctxt in + let level = + (Level.current ctxt).level |> Raw_level.to_int32 + |> Script_int.of_int32 |> Script_int.abs + in + let step_constants = + let open Script_interpreter in + (* Using dummy values for source, payer, and chain_id + since they are not used within the CPMM default + entrypoint. *) + { + sender = Destination.Contract liquidity_baking_cpmm_contract; + payer = Signature.Public_key_hash.zero; + self = liquidity_baking_cpmm_contract_hash; + amount = liquidity_baking_subsidy; + balance; + chain_id = Chain_id.zero; + now; + level; + } + in + (* + Call CPPM default entrypoint with parameter Unit. + This is necessary for the CPMM's xtz_pool in storage to + increase since it cannot use BALANCE due to a transfer attack. + + Mimicks a transaction. + + There is no: + - storage burn (extra storage is free) + - fees (the operation is mandatory) + *) + let* ( { + script = updated_cached_script; + code_size = updated_size; + storage; + lazy_storage_diff; + operations; + ticket_diffs; + ticket_receipt; + }, + ctxt ) = + Script_interpreter.execute_with_typed_parameter + ctxt + Optimized + step_constants + ~script + ~parameter:() + ~parameter_ty:Unit_t + ~cached_script:(Some script_ir) + ~location:Micheline.dummy_location + ~entrypoint:Entrypoint.default + ~internal:false + in + match operations with + | _ :: _ -> + (* No internal operations are expected here. Something bad may be happening. *) + return (backtracking_ctxt, []) + | [] -> + (* update CPMM storage *) + let* ticket_table_size_diff, ctxt = + update_script_storage_and_ticket_balances + ctxt + ~self_contract:liquidity_baking_cpmm_contract_hash + storage + lazy_storage_diff + ticket_diffs + operations + in + let* ctxt, new_size, paid_storage_size_diff = + Fees.record_paid_storage_space + ctxt + liquidity_baking_cpmm_contract_hash + in + let* ticket_paid_storage_diff, ctxt = + Ticket_balance.adjust_storage_space + ctxt + ~storage_diff:ticket_table_size_diff + in + let consumed_gas = + Gas.consumed ~since:backtracking_ctxt ~until:ctxt + in + let*? ctxt = + Script_cache.update + ctxt + cache_key + ( {script with storage = Script.lazy_expr storage}, + updated_cached_script ) + updated_size + in + let result = + Transaction_result + (Transaction_to_contract_result + { + storage = Some storage; + lazy_storage_diff; + balance_updates; + ticket_receipt; + (* At this point in application the + origination nonce has not been initialized + so it's not possible to originate new + contracts. We've checked above that none + were originated. *) + originated_contracts = []; + consumed_gas; + storage_size = new_size; + paid_storage_size_diff = + Z.add paid_storage_size_diff ticket_paid_storage_diff; + allocated_destination_contract = false; + }) + in + let ctxt = Gas.set_unlimited ctxt in + return (ctxt, [Successful_manager_result result])) + in + return + (match result with + | Ok (ctxt, results) -> (ctxt, results) + | Error _ -> + (* Do not fail if something bad happens during CPMM contract call. *) + let ctxt = Gas.set_unlimited backtracking_ctxt in + (ctxt, []))) + +let are_attestations_required ctxt ~level = + let open Lwt_result_syntax in + let+ first_level = First_level_of_protocol.get ctxt in + (* NB: the first level is the level of the migration block. There + are no attestations for this block. Therefore the block at the + next level cannot contain attestations. *) + let level_position_in_protocol = Raw_level.diff level first_level in + Compare.Int32.(level_position_in_protocol > 1l) + +let record_attesting_participation ctxt = + match Consensus.allowed_attestations ctxt with + | None -> tzfail (Consensus.Slot_map_not_found {loc = __LOC__}) + | Some validators -> + Slot.Map.fold_es + (fun initial_slot + ((consensus_pk : Consensus_key.pk), power, _dal_power) + ctxt -> + let participation = + if Slot.Set.mem initial_slot (Consensus.attestations_seen ctxt) then + Delegate.Participated + else Delegate.Didn't_participate + in + Delegate.record_attesting_participation + ctxt + ~delegate:consensus_pk.delegate + ~participation + ~attesting_power:power) + validators + ctxt + +let begin_application ctxt chain_id ~migration_balance_updates + ~migration_operation_results ~(predecessor_fitness : Fitness.raw) + (block_header : Block_header.t) : application_state tzresult Lwt.t = + let open Lwt_result_syntax in + let*? fitness = Fitness.from_raw block_header.shell.fitness in + let level = block_header.shell.level in + let*? predecessor_round = Fitness.round_from_raw predecessor_fitness in + let*? predecessor_level = Raw_level.of_int32 (Int32.pred level) in + let predecessor_level = Level.from_raw ctxt predecessor_level in + let round = Fitness.round fitness in + let current_level = Level.current ctxt in + let* ctxt, _slot, block_producer = + Stake_distribution.baking_rights_owner ctxt current_level ~round + in + let* ctxt, _slot, payload_producer = + Stake_distribution.baking_rights_owner + ctxt + current_level + ~round:block_header.protocol_data.contents.payload_round + in + let per_block_vote = + block_header.Block_header.protocol_data.contents.per_block_votes + .liquidity_baking_vote + in + let* ctxt, liquidity_baking_operations_results, liquidity_baking_toggle_ema = + apply_liquidity_baking_subsidy ctxt ~per_block_vote + in + let* ctxt, adaptive_issuance_launch_cycle, adaptive_issuance_vote_ema = + let adaptive_issuance_vote = + block_header.Block_header.protocol_data.contents.per_block_votes + .adaptive_issuance_vote + in + Adaptive_issuance.update_ema ctxt ~vote:adaptive_issuance_vote + in + let* ctxt = + Sc_rollup.Inbox.add_level_info + ~predecessor:block_header.shell.predecessor + ctxt + in + let mode = + Application + { + block_header; + fitness; + predecessor_round; + predecessor_level; + payload_producer = Consensus_key.pkh payload_producer; + block_producer = Consensus_key.pkh block_producer; + } + in + return + { + mode; + chain_id; + ctxt; + op_count = 0; + migration_balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results = + Apply_results.pack_migration_operation_results + migration_operation_results + @ liquidity_baking_operations_results; + } + +let begin_full_construction ctxt chain_id ~migration_balance_updates + ~migration_operation_results ~predecessor_timestamp ~predecessor_level + ~predecessor_round ~predecessor_hash ~timestamp + (block_data_contents : Block_header.contents) = + let open Lwt_result_syntax in + let round_durations = Constants.round_durations ctxt in + let*? round = + Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round + ~timestamp + in + (* The attestation/preattestation validation rules for construction are the + same as for application. *) + let current_level = Level.current ctxt in + let* ctxt, _slot, block_producer = + Stake_distribution.baking_rights_owner ctxt current_level ~round + in + let* ctxt, _slot, payload_producer = + Stake_distribution.baking_rights_owner + ctxt + current_level + ~round:block_data_contents.payload_round + in + let per_block_vote = + block_data_contents.per_block_votes.liquidity_baking_vote + in + let* ctxt, liquidity_baking_operations_results, liquidity_baking_toggle_ema = + apply_liquidity_baking_subsidy ctxt ~per_block_vote + in + let* ctxt, adaptive_issuance_launch_cycle, adaptive_issuance_vote_ema = + let adaptive_issuance_vote = + block_data_contents.per_block_votes.adaptive_issuance_vote + in + Adaptive_issuance.update_ema ctxt ~vote:adaptive_issuance_vote + in + let* ctxt = + Sc_rollup.Inbox.add_level_info ~predecessor:predecessor_hash ctxt + in + let mode = + Full_construction + { + block_data_contents; + predecessor_hash; + payload_producer = Consensus_key.pkh payload_producer; + block_producer = Consensus_key.pkh block_producer; + round; + predecessor_round; + predecessor_level; + } + in + return + { + mode; + chain_id; + ctxt; + op_count = 0; + migration_balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results = + Apply_results.pack_migration_operation_results + migration_operation_results + @ liquidity_baking_operations_results; + } + +let begin_partial_construction ctxt chain_id ~migration_balance_updates + ~migration_operation_results ~predecessor_hash + ~(predecessor_fitness : Fitness.raw) : application_state tzresult Lwt.t = + let open Lwt_result_syntax in + let per_block_vote = Per_block_votes.Per_block_vote_pass in + let* ctxt, liquidity_baking_operations_results, liquidity_baking_toggle_ema = + apply_liquidity_baking_subsidy ctxt ~per_block_vote + in + let* ctxt, adaptive_issuance_launch_cycle, adaptive_issuance_vote_ema = + let adaptive_issuance_vote = Per_block_votes.Per_block_vote_pass in + Adaptive_issuance.update_ema ctxt ~vote:adaptive_issuance_vote + in + let* ctxt = + (* The mode [Partial_construction] is used in simulation. We try to + put a realistic value of the block's timestamp. Even though, it should + not have an impact on the simulation of the following smart rollup + operations. + *) + let predecessor = predecessor_hash in + Sc_rollup.Inbox.add_level_info ~predecessor ctxt + in + let mode = Partial_construction {predecessor_fitness} in + return + { + mode; + chain_id; + ctxt; + op_count = 0; + migration_balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results = + Apply_results.pack_migration_operation_results + migration_operation_results + @ liquidity_baking_operations_results; + } + +let finalize_application ctxt block_data_contents ~round ~predecessor_hash + ~liquidity_baking_toggle_ema ~adaptive_issuance_vote_ema + ~adaptive_issuance_launch_cycle ~implicit_operations_results + ~migration_balance_updates ~(block_producer : Consensus_key.t) + ~(payload_producer : Consensus_key.t) = + let open Lwt_result_syntax in + (* Compute consumed gas earlier, in case maintenance actions performed below + are carbonated. *) + let consumed_gas = + Gas.Arith.sub + (Gas.Arith.fp @@ Constants.hard_gas_limit_per_block ctxt) + (Gas.block_level ctxt) + in + let level = Level.current ctxt in + let attestation_power = Consensus.current_attestation_power ctxt in + let* required_attestations = + are_attestations_required ctxt ~level:level.level + in + let block_payload_hash = + Block_payload.hash + ~predecessor_hash + ~payload_round:block_data_contents.Block_header.payload_round + (non_consensus_operations ctxt) + in + (* from this point nothing should fail *) + (* We mark the attestation branch as the grand parent branch when + accessible. This will not be present before the first two blocks + of tenderbake. *) + (* We mark the current payload hash as the predecessor one => this + will only be accessed by the successor block now. *) + let*! ctxt = + Consensus.store_attestation_branch + ctxt + (predecessor_hash, block_payload_hash) + in + let* ctxt = Round.update ctxt round in + (* end of level *) + let* ctxt = + match block_data_contents.Block_header.seed_nonce_hash with + | None -> return ctxt + | Some nonce_hash -> + Nonce.record_hash ctxt {nonce_hash; delegate = block_producer.delegate} + in + let* ctxt, reward_bonus = + if required_attestations then + let* ctxt = record_attesting_participation ctxt in + let*? rewards_bonus = + Baking.bonus_baking_reward ctxt ~attestation_power + in + return (ctxt, Some rewards_bonus) + else return (ctxt, None) + in + let*? baking_reward = Delegate.Rewards.baking_reward_fixed_portion ctxt in + let* ctxt, baking_receipts = + Delegate.record_baking_activity_and_pay_rewards_and_fees + ctxt + ~payload_producer:payload_producer.delegate + ~block_producer:block_producer.delegate + ~baking_reward + ~reward_bonus + in + (* if end of nonce revelation period, compute seed *) + let* ctxt = + if Level.may_compute_randao ctxt then Seed.compute_randao ctxt + else return ctxt + in + let* ctxt, cycle_end_balance_updates, deactivated = + may_start_new_cycle ctxt + in + let* ctxt = Amendment.may_start_new_voting_period ctxt in + let* ctxt, dal_attestation = Dal_apply.finalisation ctxt in + let* ctxt = Sc_rollup.Inbox.finalize_inbox_level ctxt in + let balance_updates = + migration_balance_updates @ baking_receipts @ cycle_end_balance_updates + in + let+ voting_period_info = Voting_period.get_rpc_current_info ctxt in + let receipt = + Apply_results. + { + proposer = payload_producer; + baker = block_producer; + level_info = level; + voting_period_info; + nonce_hash = block_data_contents.seed_nonce_hash; + consumed_gas; + deactivated; + balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results; + dal_attestation; + } + in + (ctxt, receipt) + +type error += Missing_shell_header + +let () = + register_error_kind + `Permanent + ~id:"apply.missing_shell_header" + ~title:"Missing shell_header during finalisation of a block" + ~description: + "During finalisation of a block header in Application mode or Full \ + construction mode, a shell header should be provided so that a cache \ + nonce can be computed." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "No shell header provided during the finalisation of a block.") + Data_encoding.unit + (function Missing_shell_header -> Some () | _ -> None) + (fun () -> Missing_shell_header) + +let finalize_with_commit_message ctxt ~cache_nonce fitness round op_count = + let open Lwt_syntax in + let* ctxt = Cache.Admin.sync ctxt cache_nonce in + let raw_level = Raw_level.to_int32 (Level.current ctxt).level in + let commit_message = + Format.asprintf + "lvl %ld, fit:%a, round %a, %d ops" + raw_level + Fitness.pp + fitness + Round.pp + round + op_count + in + let validation_result = + finalize ~commit_message ctxt (Fitness.to_raw fitness) + in + return validation_result + +let finalize_block (application_state : application_state) shell_header_opt = + let open Lwt_result_syntax in + let { + ctxt; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results; + migration_balance_updates; + op_count; + _; + } = + application_state + in + match application_state.mode with + | Full_construction + { + block_data_contents; + predecessor_hash; + predecessor_level = _; + predecessor_round; + block_producer; + payload_producer; + round; + } -> + let*? (shell_header : Block_header.shell_header) = + Option.value_e + shell_header_opt + ~error:(Error_monad.trace_of_error Missing_shell_header) + in + let cache_nonce = + Cache.cache_nonce_from_block_header shell_header block_data_contents + in + let locked_round = + Option.map fst (Consensus.locked_round_evidence ctxt) + in + let level = (Level.current ctxt).level in + let*? fitness = + Fitness.create ~level ~round ~predecessor_round ~locked_round + in + let* ctxt, receipt = + finalize_application + ctxt + block_data_contents + ~round + ~predecessor_hash + ~liquidity_baking_toggle_ema + ~adaptive_issuance_vote_ema + ~adaptive_issuance_launch_cycle + ~implicit_operations_results + ~migration_balance_updates + ~block_producer + ~payload_producer + in + let*! result = + finalize_with_commit_message ctxt ~cache_nonce fitness round op_count + in + return (result, receipt) + | Partial_construction {predecessor_fitness; _} -> + (* Fake finalization to return a correct type, because there is no + block to finalize in mempool mode. If this changes in the + future, beware that consensus operations are not recorded by + {!record_preattestation} and {!record_attestation} in this mode. *) + let* voting_period_info = Voting_period.get_rpc_current_info ctxt in + let level_info = Level.current ctxt in + let result = finalize ctxt predecessor_fitness in + return + ( result, + Apply_results. + { + proposer = Consensus_key.zero; + baker = Consensus_key.zero; + level_info; + voting_period_info; + nonce_hash = None; + consumed_gas = Gas.Arith.zero; + deactivated = []; + balance_updates = migration_balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results; + dal_attestation = Dal.Attestation.empty; + } ) + | Application + { + fitness; + block_header = {shell; protocol_data}; + payload_producer; + block_producer; + _; + } -> + let round = Fitness.round fitness in + let cache_nonce = + Cache.cache_nonce_from_block_header shell protocol_data.contents + in + let* ctxt, receipt = + finalize_application + ctxt + protocol_data.contents + ~round + ~predecessor_hash:shell.predecessor + ~liquidity_baking_toggle_ema + ~adaptive_issuance_vote_ema + ~adaptive_issuance_launch_cycle + ~implicit_operations_results + ~migration_balance_updates + ~block_producer + ~payload_producer + in + let*! result = + finalize_with_commit_message ctxt ~cache_nonce fitness round op_count + in + return (result, receipt) + +let value_of_key ctxt k = Cache.Admin.value_of_key ctxt k + +module Internal_for_benchmark = struct + let take_fees ctxt batch = ignore (take_fees ctxt batch) +end diff --git a/src/proto_020_PsParisC/lib_protocol/apply.mli b/src/proto_020_PsParisC/lib_protocol/apply.mli new file mode 100644 index 000000000000..33b3c3920a64 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply.mli @@ -0,0 +1,166 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module supports advancing the ledger state by applying [operation]s. + + Each operation application takes and returns an [application_state], representing + the old and new state, respectively. + + The [Main] module provides wrappers for the functionality in this module, + satisfying the Protocol signature. + *) + +open Alpha_context + +type error += + | Internal_operation_replay of + Apply_internal_results.packed_internal_operation + | Empty_transaction of Contract.t + +type mode = + | Application of { + block_header : Block_header.t; + fitness : Fitness.t; + payload_producer : Consensus_key.t; + block_producer : Consensus_key.t; + predecessor_level : Level.t; + predecessor_round : Round.t; + } + | Full_construction of { + block_data_contents : Block_header.contents; + predecessor_hash : Block_hash.t; + payload_producer : Consensus_key.t; + block_producer : Consensus_key.t; + round : Round.t; + predecessor_level : Level.t; + predecessor_round : Round.t; + } + | Partial_construction of {predecessor_fitness : Fitness.raw} + (** This mode is mainly intended to be used by a mempool. *) + +type application_state = { + ctxt : context; + chain_id : Chain_id.t; + mode : mode; + op_count : int; + migration_balance_updates : Receipt.balance_updates; + liquidity_baking_toggle_ema : Per_block_votes.Liquidity_baking_toggle_EMA.t; + adaptive_issuance_vote_ema : Per_block_votes.Adaptive_issuance_launch_EMA.t; + adaptive_issuance_launch_cycle : Cycle.t option; + implicit_operations_results : + Apply_results.packed_successful_manager_operation_result list; +} + +(** Initialize an {!application_state} for the application of an + existing block. *) +val begin_application : + context -> + Chain_id.t -> + migration_balance_updates:Receipt.balance_updates -> + migration_operation_results:Migration.origination_result list -> + predecessor_fitness:Fitness.raw -> + Block_header.t -> + application_state tzresult Lwt.t + +(** Initialize an {!application_state} for the construction of a + fresh block. *) +val begin_full_construction : + context -> + Chain_id.t -> + migration_balance_updates:Receipt.balance_updates -> + migration_operation_results:Migration.origination_result list -> + predecessor_timestamp:Time.t -> + predecessor_level:Level.t -> + predecessor_round:Round.t -> + predecessor_hash:Block_hash.t -> + timestamp:Time.t -> + Block_header.contents -> + application_state tzresult Lwt.t + +(** Initialize an {!application_state} for the partial construction of + a block. This is similar to construction but less information is + required as this will not yield a final valid block. *) +val begin_partial_construction : + context -> + Chain_id.t -> + migration_balance_updates:Receipt.balance_updates -> + migration_operation_results:Migration.origination_result list -> + predecessor_hash:Block_hash.t -> + predecessor_fitness:Fitness.raw -> + application_state tzresult Lwt.t + +(** Apply an operation, i.e. update the given context in accordance + with the operation's semantic (or return an error if the operation + is not applicable). + + For non-manager operations, the application of a validated + operation should always fully succeed. + + For manager operations, the application has two stages. The first + stage consists in updating the context to: + + - take the fees; + + - increment the account's counter; + + - decrease of the available block gas by operation's [gas_limit]. + + These updates are mandatory. In particular, taking the fees is + critically important. The {!Validate} module is responsible for + ensuring that the operation is solvable, i.e. that fees can be + taken, i.e. that the first stage of manager operation application + cannot fail. If this stage fails nevertheless, the function returns + an error. + + The second stage of this function (still in the case of a manager + operation) consists in applying all the other effects, in + accordance with the semantic of the operation's kind. + + An error may happen during this second phase: in that case, the + function returns the context obtained at the end of the first + stage, and metadata that contain the error. This means that the + operation has no other effects than those described above during + the first phase. *) +val apply_operation : + application_state -> + Operation_hash.t -> + packed_operation -> + (application_state * Apply_results.packed_operation_metadata) tzresult Lwt.t + +(** Finalize the application of a block depending on its mode. *) +val finalize_block : + application_state -> + Block_header.shell_header option -> + (Updater.validation_result * Apply_results.block_metadata) tzresult Lwt.t + +(** [value_of_key ctxt k] builds a value identified by key [k] + so that it can be put into the cache. *) +val value_of_key : + context -> Context.Cache.key -> Context.Cache.value tzresult Lwt.t + +module Internal_for_benchmark : sig + val take_fees : context -> 'a Kind.manager contents_list -> unit +end diff --git a/src/proto_020_PsParisC/lib_protocol/apply_internal_results.ml b/src/proto_020_PsParisC/lib_protocol/apply_internal_results.ml new file mode 100644 index 000000000000..9f5989e5eb69 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply_internal_results.ml @@ -0,0 +1,694 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Data_encoding +open Apply_operation_result + +type 'kind internal_operation_contents = + | Transaction : { + amount : Tez.t; + parameters : Script.lazy_expr; + entrypoint : Entrypoint.t; + destination : Destination.t; + } + -> Kind.transaction internal_operation_contents + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script.t; + credit : Tez.t; + } + -> Kind.origination internal_operation_contents + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation internal_operation_contents + | Event : { + ty : Script.expr; + tag : Entrypoint.t; + payload : Script.expr; + } + -> Kind.event internal_operation_contents + +type packed_internal_operation_contents = + | Internal_operation_contents : + 'kind internal_operation_contents + -> packed_internal_operation_contents + +type 'kind internal_operation = { + sender : Destination.t; + operation : 'kind internal_operation_contents; + nonce : int; +} + +type packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation + +let internal_operation (type kind) + ({sender; operation; nonce} : kind Script_typed_ir.internal_operation) : + kind internal_operation = + let operation : kind internal_operation_contents = + match operation with + | Transaction_to_implicit {destination; amount} -> + Transaction + { + destination = Contract (Implicit destination); + amount; + entrypoint = Entrypoint.default; + parameters = Script.unit_parameter; + } + | Transaction_to_implicit_with_ticket + {destination; unparsed_ticket; amount; ticket_ty = _; ticket = _} -> + Transaction + { + destination = Contract (Implicit destination); + amount; + entrypoint = Entrypoint.default; + parameters = unparsed_ticket; + } + | Transaction_to_smart_contract + {destination; amount; entrypoint; unparsed_parameters; _} -> + Transaction + { + destination = Contract (Originated destination); + amount; + entrypoint; + parameters = Script.lazy_expr unparsed_parameters; + } + | Transaction_to_sc_rollup {destination; entrypoint; unparsed_parameters; _} + -> + Transaction + { + destination = Sc_rollup destination; + amount = Tez.zero; + entrypoint; + parameters = Script.lazy_expr unparsed_parameters; + } + | Event {ty; tag; unparsed_data} -> Event {ty; tag; payload = unparsed_data} + | Transaction_to_zk_rollup {destination; unparsed_parameters; _} -> + Transaction + { + destination = Zk_rollup destination; + amount = Tez.zero; + entrypoint = Entrypoint.deposit; + parameters = Script.lazy_expr unparsed_parameters; + } + | Origination {delegate; code; unparsed_storage; credit; _} -> + let script = + { + Script.code = Script.lazy_expr code; + storage = Script.lazy_expr unparsed_storage; + } + in + Origination {delegate; script; credit} + | Delegation delegate -> Delegation delegate + in + {sender; operation; nonce} + +let packed_internal_operation (Script_typed_ir.Internal_operation op) = + Internal_operation (internal_operation op) + +let packed_internal_operations = List.map packed_internal_operation + +type successful_transaction_result = + | Transaction_to_contract_result of { + storage : Script.expr option; + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + ticket_receipt : Ticket_receipt.t; + originated_contracts : Contract_hash.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + allocated_destination_contract : bool; + } + | Transaction_to_sc_rollup_result of { + consumed_gas : Gas.Arith.fp; + ticket_receipt : Ticket_receipt.t; + } + | Transaction_to_zk_rollup_result of { + ticket_hash : Ticket_hash.t; + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + +type successful_origination_result = { + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + originated_contracts : Contract_hash.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; +} + +(** Result of applying an internal operation. *) +type _ successful_internal_operation_result = + | ITransaction_result : + successful_transaction_result + -> Kind.transaction successful_internal_operation_result + | IOrigination_result : + successful_origination_result + -> Kind.origination successful_internal_operation_result + | IDelegation_result : { + consumed_gas : Gas.Arith.fp; + balance_updates : Receipt.balance_updates; + } + -> Kind.delegation successful_internal_operation_result + | IEvent_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.event successful_internal_operation_result + +type packed_successful_internal_operation_result = + | Successful_internal_operation_result : + 'kind successful_internal_operation_result + -> packed_successful_internal_operation_result + +type 'kind internal_operation_result = + ( 'kind, + 'kind Kind.manager, + 'kind successful_internal_operation_result ) + operation_result + +type packed_internal_operation_result = + | Internal_operation_result : + 'kind internal_operation * 'kind internal_operation_result + -> packed_internal_operation_result + +let pack_internal_operation_result (type kind) + (internal_op : kind Script_typed_ir.internal_operation) + (manager_op : kind internal_operation_result) = + let internal_op = internal_operation internal_op in + Internal_operation_result (internal_op, manager_op) + +type 'kind iselect = + packed_internal_operation_result -> + ('kind internal_operation * 'kind internal_operation_result) option + +module Internal_operation = struct + open Data_encoding + + type 'kind case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + iselect : 'kind iselect; + select : + packed_internal_operation_contents -> + 'kind internal_operation_contents option; + proj : 'kind internal_operation_contents -> 'a; + inj : 'a -> 'kind internal_operation_contents; + } + -> 'kind case + + let transaction_contract_variant_cases = + let case = function + | Tag tag -> + (* The tag was used by old variant. It have been removed in + protocol proposal O, it can be unblocked in the future. *) + let to_tx_rollup_reserved_tag = 1 in + assert (Compare.Int.(tag <> to_tx_rollup_reserved_tag)) ; + case (Tag tag) + | _ as c -> case c + in + union + [ + case + ~title:"To_contract" + (Tag 0) + (obj9 + (opt "storage" Script.expr_encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "ticket_receipt" Ticket_receipt.encoding []) + (dft "originated_contracts" (list Contract.originated_encoding) []) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero) + (dft "allocated_destination_contract" bool false) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + (function + | Transaction_to_contract_result + { + storage; + lazy_storage_diff; + balance_updates; + ticket_receipt; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + allocated_destination_contract; + } -> + Some + ( storage, + balance_updates, + ticket_receipt, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + allocated_destination_contract, + lazy_storage_diff ) + | _ -> None) + (fun ( storage, + balance_updates, + ticket_receipt, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + allocated_destination_contract, + lazy_storage_diff ) -> + Transaction_to_contract_result + { + storage; + lazy_storage_diff; + balance_updates; + ticket_receipt; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + allocated_destination_contract; + }); + case + ~title:"To_smart_rollup" + (Tag 2) + (obj2 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "ticket_receipt" Ticket_receipt.encoding)) + (function + | Transaction_to_sc_rollup_result {consumed_gas; ticket_receipt} -> + Some (consumed_gas, ticket_receipt) + | _ -> None) + (function + | consumed_gas, ticket_receipt -> + Transaction_to_sc_rollup_result {consumed_gas; ticket_receipt}); + ] + + let transaction_case = + MCase + { + (* This value should be changed with care: maybe receipts are read by + external tools such as indexers. *) + tag = 1; + name = "transaction"; + encoding = + obj3 + (req "amount" Tez.encoding) + (req "destination" Destination.encoding) + (opt + "parameters" + (obj2 + (req "entrypoint" Entrypoint.smart_encoding) + (req "value" Script.lazy_expr_encoding))); + iselect : Kind.transaction iselect = + (function + | Internal_operation_result + (({operation = Transaction _; _} as op), res) -> + Some (op, res) + | _ -> None); + select = + (function + | Internal_operation_contents (Transaction _ as op) -> Some op + | _ -> None); + proj = + (function + | Transaction {amount; destination; parameters; entrypoint} -> + let parameters = + if + Script_repr.is_unit_parameter parameters + && Entrypoint.is_default entrypoint + then None + else Some (entrypoint, parameters) + in + (amount, destination, parameters)); + inj = + (fun (amount, destination, parameters) -> + let entrypoint, parameters = + match parameters with + | None -> (Entrypoint.default, Script.unit_parameter) + | Some (entrypoint, value) -> (entrypoint, value) + in + Transaction {amount; destination; parameters; entrypoint}); + } + + let origination_case = + MCase + { + (* This value should be changed with care: maybe receipts are read by + external tools such as indexers. *) + tag = 2; + name = "origination"; + encoding = + obj3 + (req "balance" Tez.encoding) + (opt "delegate" Signature.Public_key_hash.encoding) + (req "script" Script.encoding); + iselect : Kind.origination iselect = + (function + | Internal_operation_result + (({operation = Origination _; _} as op), res) -> + Some (op, res) + | _ -> None); + select = + (function + | Internal_operation_contents (Origination _ as op) -> Some op + | _ -> None); + proj = + (function + | Origination {credit; delegate; script} -> (credit, delegate, script)); + inj = + (fun (credit, delegate, script) -> + Origination {credit; delegate; script}); + } + + let delegation_case = + MCase + { + (* This value should be changed with care: maybe receipts are read by + external tools such as indexers. *) + tag = 3; + name = "delegation"; + encoding = obj1 (opt "delegate" Signature.Public_key_hash.encoding); + iselect : Kind.delegation iselect = + (function + | Internal_operation_result + (({operation = Delegation _; _} as op), res) -> + Some (op, res) + | _ -> None); + select = + (function + | Internal_operation_contents (Delegation _ as op) -> Some op + | _ -> None); + proj = (function Delegation key -> key); + inj = (fun key -> Delegation key); + } + + let event_case = + MCase + { + (* This value should be changed with care: maybe receipts are read by + external tools such as indexers. *) + tag = 4; + name = "event"; + encoding = + obj3 + (req "type" Script.expr_encoding) + (opt "tag" Entrypoint.smart_encoding) + (opt "payload" Script.expr_encoding); + iselect : Kind.event iselect = + (function + | Internal_operation_result (({operation = Event _; _} as op), res) -> + Some (op, res) + | _ -> None); + select = + (function + | Internal_operation_contents (Event _ as op) -> Some op | _ -> None); + proj = + (function + | Event {ty; tag; payload} -> + let tag = if Entrypoint.is_default tag then None else Some tag in + let payload = + if Script_repr.is_unit payload then None else Some payload + in + (ty, tag, payload)); + inj = + (fun (ty, tag, payload) -> + let tag = Option.value ~default:Entrypoint.default tag in + let payload = Option.value ~default:Script_repr.unit payload in + Event {ty; tag; payload}); + } + + let case tag name args proj inj = + case + tag + ~title:(String.capitalize_ascii name) + (merge_objs (obj1 (req "kind" (constant name))) args) + (fun x -> match proj x with None -> None | Some x -> Some ((), x)) + (fun ((), x) -> inj x) + + let encoding = + let make (MCase {tag; name; encoding; iselect = _; select; proj; inj}) = + case + (Tag tag) + name + encoding + (fun o -> match select o with None -> None | Some o -> Some (proj o)) + (fun x -> Internal_operation_contents (inj x)) + in + union + ~tag_size:`Uint8 + [ + make transaction_case; + make origination_case; + make delegation_case; + make event_case; + ] +end + +let internal_operation_encoding : packed_internal_operation Data_encoding.t = + def "apply_internal_results.alpha.operation_result" + @@ conv + (fun (Internal_operation {sender; operation; nonce}) -> + ((sender, nonce), Internal_operation_contents operation)) + (fun ((sender, nonce), Internal_operation_contents operation) -> + Internal_operation {sender; operation; nonce}) + (merge_objs + (* TODO: https://gitlab.com/tezos/tezos/-/issues/710 + Rename the "source" field into "sender" *) + (obj2 (req "source" Destination.encoding) (req "nonce" uint16)) + Internal_operation.encoding) + +module Internal_operation_result = struct + type 'kind case = + | MCase : { + op_case : 'kind Internal_operation.case; + encoding : 'a Data_encoding.t; + kind : 'kind Kind.manager; + select : + packed_successful_internal_operation_result -> + 'kind successful_internal_operation_result option; + proj : 'kind successful_internal_operation_result -> 'a; + inj : 'a -> 'kind successful_internal_operation_result; + t : 'kind internal_operation_result Data_encoding.t; + } + -> 'kind case + + let make ~op_case ~encoding ~kind ~select ~proj ~inj = + let (Internal_operation.MCase {name; _}) = op_case in + let t = + def (Format.asprintf "operation.alpha.internal_operation_result.%s" name) + @@ union + ~tag_size:`Uint8 + [ + case + (Tag 0) + ~title:"Applied" + (merge_objs (obj1 (req "status" (constant "applied"))) encoding) + (fun o -> + match o with + | Skipped _ | Failed _ | Backtracked _ -> None + | Applied o -> ( + match select (Successful_internal_operation_result o) with + | None -> None + | Some o -> Some ((), proj o))) + (fun ((), x) -> Applied (inj x)); + case + (Tag 1) + ~title:"Failed" + (obj2 + (req "status" (constant "failed")) + (req "errors" trace_encoding)) + (function Failed (_, errs) -> Some ((), errs) | _ -> None) + (fun ((), errs) -> Failed (kind, errs)); + case + (Tag 2) + ~title:"Skipped" + (obj1 (req "status" (constant "skipped"))) + (function Skipped _ -> Some () | _ -> None) + (fun () -> Skipped kind); + case + (Tag 3) + ~title:"Backtracked" + (merge_objs + (obj2 + (req "status" (constant "backtracked")) + (opt "errors" trace_encoding)) + encoding) + (fun o -> + match o with + | Skipped _ | Failed _ | Applied _ -> None + | Backtracked (o, errs) -> ( + match select (Successful_internal_operation_result o) with + | None -> None + | Some o -> Some (((), errs), proj o))) + (fun (((), errs), x) -> Backtracked (inj x, errs)); + ] + in + MCase {op_case; encoding; kind; select; proj; inj; t} + + let transaction_case = + make + ~op_case:Internal_operation.transaction_case + ~encoding:Internal_operation.transaction_contract_variant_cases + ~select:(function + | Successful_internal_operation_result (ITransaction_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Transaction_manager_kind + ~proj:(function ITransaction_result x -> x) + ~inj:(fun x -> ITransaction_result x) + + let origination_case = + make + ~op_case:Internal_operation.origination_case + ~encoding: + (obj6 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "originated_contracts" (list Contract.originated_encoding) []) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + ~select:(function + | Successful_internal_operation_result (IOrigination_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | IOrigination_result + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + } -> + (* There used to be a [legacy_lazy_storage_diff] returned as the + first component of the tuple below, and the non-legacy one + returned as the last component. The legacy one has been removed, + but it was chosen to keep the non-legacy one at its position, + hence the order difference with regards to the record above. *) + ( balance_updates, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + lazy_storage_diff )) + ~kind:Kind.Origination_manager_kind + ~inj: + (fun ( balance_updates, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + lazy_storage_diff ) -> + IOrigination_result + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + }) + + let delegation_case = + make + ~op_case:Internal_operation.delegation_case + ~encoding: + Data_encoding.( + obj2 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "balance_updates" Receipt.balance_updates_encoding [])) + ~select:(function + | Successful_internal_operation_result (IDelegation_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Delegation_manager_kind + ~proj:(function + | IDelegation_result {consumed_gas; balance_updates} -> + (consumed_gas, balance_updates)) + ~inj:(fun (consumed_gas, balance_updates) -> + IDelegation_result {consumed_gas; balance_updates}) + + let event_case = + make + ~op_case:Internal_operation.event_case + ~encoding: + Data_encoding.( + obj1 (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_internal_operation_result (IEvent_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Event_manager_kind + ~proj:(function IEvent_result {consumed_gas} -> consumed_gas) + ~inj:(fun consumed_gas -> IEvent_result {consumed_gas}) +end + +let internal_operation_result_encoding : + packed_internal_operation_result Data_encoding.t = + let make (type kind) + (Internal_operation_result.MCase res_case : + kind Internal_operation_result.case) + (Internal_operation.MCase ires_case : kind Internal_operation.case) = + let (Internal_operation.MCase op_case) = res_case.op_case in + case + (Tag op_case.tag) + ~title:op_case.name + (* TODO: https://gitlab.com/tezos/tezos/-/issues/710 + Rename the "source" field into "sender" *) + (merge_objs + (obj3 + (req "kind" (constant op_case.name)) + (req "source" Destination.encoding) + (req "nonce" uint16)) + (merge_objs ires_case.encoding (obj1 (req "result" res_case.t)))) + (fun op -> + match ires_case.iselect op with + | Some (op, res) -> + Some (((), op.sender, op.nonce), (ires_case.proj op.operation, res)) + | None -> None) + (fun (((), sender, nonce), (op, res)) -> + let op = {sender; operation = ires_case.inj op; nonce} in + Internal_operation_result (op, res)) + in + def "apply_internal_results.alpha.operation_result" + @@ union + [ + make + Internal_operation_result.transaction_case + Internal_operation.transaction_case; + make + Internal_operation_result.origination_case + Internal_operation.origination_case; + make + Internal_operation_result.delegation_case + Internal_operation.delegation_case; + make Internal_operation_result.event_case Internal_operation.event_case; + ] diff --git a/src/proto_020_PsParisC/lib_protocol/apply_internal_results.mli b/src/proto_020_PsParisC/lib_protocol/apply_internal_results.mli new file mode 100644 index 000000000000..34cda974eca3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply_internal_results.mli @@ -0,0 +1,152 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Types representing results of applying an internal operation. + + These are used internally by [Apply]. +*) + +open Alpha_context + +(** [internal_operation_contents] are the internal operations as output in + receipts. + The type simply weakens {!Script_typed_ir.internal_operation_contents} so + that it is easier to define an encoding for it (i.e. we remove the typed + parameter). *) +type 'kind internal_operation_contents = + | Transaction : { + amount : Tez.t; + parameters : Script.lazy_expr; + entrypoint : Entrypoint.t; + destination : Destination.t; + } + -> Kind.transaction internal_operation_contents + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script.t; + credit : Tez.t; + } + -> Kind.origination internal_operation_contents + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation internal_operation_contents + | Event : { + ty : Script.expr; + tag : Entrypoint.t; + payload : Script.expr; + } + -> Kind.event internal_operation_contents + +type 'kind internal_operation = { + sender : Destination.t; + operation : 'kind internal_operation_contents; + nonce : int; +} + +type packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation + +val packed_internal_operation : + Script_typed_ir.packed_internal_operation -> packed_internal_operation + +val packed_internal_operations : + Script_typed_ir.packed_internal_operation list -> + packed_internal_operation list + +(** Result of applying an internal transaction. *) +type successful_transaction_result = + | Transaction_to_contract_result of { + storage : Script.expr option; + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + ticket_receipt : Ticket_receipt.t; + originated_contracts : Contract_hash.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; + allocated_destination_contract : bool; + } + | Transaction_to_sc_rollup_result of { + consumed_gas : Gas.Arith.fp; + ticket_receipt : Ticket_receipt.t; + } + | Transaction_to_zk_rollup_result of { + ticket_hash : Ticket_hash.t; + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + +(** Result of applying an internal origination. *) +type successful_origination_result = { + lazy_storage_diff : Lazy_storage.diffs option; + balance_updates : Receipt.balance_updates; + originated_contracts : Contract_hash.t list; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + paid_storage_size_diff : Z.t; +} + +(** Result of applying a {!Script_typed_ir.internal_operation_contents}. *) +type _ successful_internal_operation_result = + | ITransaction_result : + successful_transaction_result + -> Kind.transaction successful_internal_operation_result + | IOrigination_result : + successful_origination_result + -> Kind.origination successful_internal_operation_result + | IDelegation_result : { + consumed_gas : Gas.Arith.fp; + balance_updates : Receipt.balance_updates; + } + -> Kind.delegation successful_internal_operation_result + | IEvent_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.event successful_internal_operation_result + +type 'kind internal_operation_result = + ( 'kind, + 'kind Kind.manager, + 'kind successful_internal_operation_result ) + Apply_operation_result.operation_result + +type packed_internal_operation_result = + | Internal_operation_result : + 'kind internal_operation * 'kind internal_operation_result + -> packed_internal_operation_result + +val internal_operation : + 'kind Script_typed_ir.internal_operation -> 'kind internal_operation + +val pack_internal_operation_result : + 'kind Script_typed_ir.internal_operation -> + 'kind internal_operation_result -> + packed_internal_operation_result + +val internal_operation_encoding : packed_internal_operation Data_encoding.t + +val internal_operation_result_encoding : + packed_internal_operation_result Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/apply_operation_result.ml b/src/proto_020_PsParisC/lib_protocol/apply_operation_result.ml new file mode 100644 index 000000000000..d5763a4a8050 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply_operation_result.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Data_encoding + +type ('kind, 'manager, 'successful) operation_result = + | Applied of 'successful + | Backtracked of 'successful * error trace option + | Failed : + 'manager * error trace + -> ('kind, 'manager, 'successful) operation_result + | Skipped : 'manager -> ('kind, 'manager, 'successful) operation_result + +let error_encoding = + def + "error" + ~description: + "The full list of RPC errors would be too long to include.\n\ + It is available at RPC `/errors` (GET).\n\ + Errors specific to protocol Alpha have an id that starts with \ + `proto.alpha`." + @@ splitted + ~json: + (conv + (fun err -> + Data_encoding.Json.construct Error_monad.error_encoding err) + (fun json -> + Data_encoding.Json.destruct Error_monad.error_encoding json) + json) + ~binary:Error_monad.error_encoding + +let trace_encoding = make_trace_encoding error_encoding diff --git a/src/proto_020_PsParisC/lib_protocol/apply_operation_result.mli b/src/proto_020_PsParisC/lib_protocol/apply_operation_result.mli new file mode 100644 index 000000000000..e48842e3ca71 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply_operation_result.mli @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The result of an operation in the queue. [Skipped] ones should + always be at the tail, and after a single [Failed]. + * The ['kind] parameter is the operation kind (a transaction, an + origination, etc.). + * The ['manager] parameter is the type of manager kinds. + * The ['successful] parameter is the type of successful operations. + The ['kind] parameter is used to make the type a GADT, but ['manager] and + ['successful] are used to share [operation_result] between internal and + external operation results, and are instantiated for each case. *) +type ('kind, 'manager, 'successful) operation_result = + | Applied of 'successful + | Backtracked of 'successful * error trace option + | Failed : + 'manager * error trace + -> ('kind, 'manager, 'successful) operation_result + | Skipped : 'manager -> ('kind, 'manager, 'successful) operation_result + +val trace_encoding : error trace Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/apply_results.ml b/src/proto_020_PsParisC/lib_protocol/apply_results.ml new file mode 100644 index 000000000000..9d7a3ec6fe7b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply_results.ml @@ -0,0 +1,2849 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Data_encoding +open Apply_operation_result +open Apply_internal_results + +type successful_transaction_result = + Apply_internal_results.successful_transaction_result + +type successful_origination_result = + Apply_internal_results.successful_origination_result + +type _ successful_manager_operation_result = + | Reveal_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.reveal successful_manager_operation_result + | Transaction_result : + successful_transaction_result + -> Kind.transaction successful_manager_operation_result + | Origination_result : + successful_origination_result + -> Kind.origination successful_manager_operation_result + | Delegation_result : { + consumed_gas : Gas.Arith.fp; + balance_updates : Receipt.balance_updates; + } + -> Kind.delegation successful_manager_operation_result + | Register_global_constant_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + size_of_constant : Z.t; + global_address : Script_expr_hash.t; + } + -> Kind.register_global_constant successful_manager_operation_result + | Set_deposits_limit_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.set_deposits_limit successful_manager_operation_result + | Increase_paid_storage_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + } + -> Kind.increase_paid_storage successful_manager_operation_result + | Update_consensus_key_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.update_consensus_key successful_manager_operation_result + | Transfer_ticket_result : { + balance_updates : Receipt.balance_updates; + ticket_receipt : Ticket_receipt.t; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.transfer_ticket successful_manager_operation_result + | Dal_publish_commitment_result : { + slot_header : Dal.Slot.Header.t; + consumed_gas : Gas.Arith.fp; + } + -> Kind.dal_publish_commitment successful_manager_operation_result + | Sc_rollup_originate_result : { + balance_updates : Receipt.balance_updates; + address : Sc_rollup.Address.t; + genesis_commitment_hash : Sc_rollup.Commitment.Hash.t; + consumed_gas : Gas.Arith.fp; + size : Z.t; + } + -> Kind.sc_rollup_originate successful_manager_operation_result + | Sc_rollup_add_messages_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.sc_rollup_add_messages successful_manager_operation_result + | Sc_rollup_cement_result : { + consumed_gas : Gas.Arith.fp; + inbox_level : Raw_level.t; + commitment_hash : Sc_rollup.Commitment.Hash.t; + } + -> Kind.sc_rollup_cement successful_manager_operation_result + | Sc_rollup_publish_result : { + consumed_gas : Gas.Arith.fp; + staked_hash : Sc_rollup.Commitment.Hash.t; + published_at_level : Raw_level.t; + balance_updates : Receipt.balance_updates; + } + -> Kind.sc_rollup_publish successful_manager_operation_result + | Sc_rollup_refute_result : { + consumed_gas : Gas.Arith.fp; + game_status : Sc_rollup.Game.status; + balance_updates : Receipt.balance_updates; + } + -> Kind.sc_rollup_refute successful_manager_operation_result + | Sc_rollup_timeout_result : { + consumed_gas : Gas.Arith.fp; + game_status : Sc_rollup.Game.status; + balance_updates : Receipt.balance_updates; + } + -> Kind.sc_rollup_timeout successful_manager_operation_result + | Sc_rollup_execute_outbox_message_result : { + balance_updates : Receipt.balance_updates; + ticket_receipt : Ticket_receipt.t; + whitelist_update : Sc_rollup.Whitelist.update option; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.sc_rollup_execute_outbox_message + successful_manager_operation_result + | Sc_rollup_recover_bond_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + } + -> Kind.sc_rollup_recover_bond successful_manager_operation_result + | Zk_rollup_origination_result : { + balance_updates : Receipt.balance_updates; + originated_zk_rollup : Zk_rollup.t; + consumed_gas : Gas.Arith.fp; + storage_size : Z.t; + } + -> Kind.zk_rollup_origination successful_manager_operation_result + | Zk_rollup_publish_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.zk_rollup_publish successful_manager_operation_result + | Zk_rollup_update_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.zk_rollup_update successful_manager_operation_result + +let migration_origination_result_to_successful_manager_operation_result + ({ + balance_updates; + originated_contracts; + storage_size; + paid_storage_size_diff; + } : + Migration.origination_result) = + Origination_result + { + lazy_storage_diff = None; + balance_updates; + originated_contracts; + consumed_gas = Gas.Arith.zero; + storage_size; + paid_storage_size_diff; + } + +type packed_successful_manager_operation_result = + | Successful_manager_result : + 'kind successful_manager_operation_result + -> packed_successful_manager_operation_result + +let pack_migration_operation_results results = + List.map + (fun el -> + Successful_manager_result + (migration_origination_result_to_successful_manager_operation_result el)) + results + +type 'kind manager_operation_result = + ( 'kind, + 'kind Kind.manager, + 'kind successful_manager_operation_result ) + operation_result + +module Manager_result = struct + type 'kind case = + | MCase : { + op_case : 'kind Operation.Encoding.Manager_operations.case; + encoding : 'a Data_encoding.t; + kind : 'kind Kind.manager; + select : + packed_successful_manager_operation_result -> + 'kind successful_manager_operation_result option; + proj : 'kind successful_manager_operation_result -> 'a; + inj : 'a -> 'kind successful_manager_operation_result; + t : 'kind manager_operation_result Data_encoding.t; + } + -> 'kind case + + let make ~op_case ~encoding ~kind ~select ~proj ~inj = + let (Operation.Encoding.Manager_operations.MCase {name; _}) = op_case in + let t = + def (Format.asprintf "operation.alpha.operation_result.%s" name) + @@ union + ~tag_size:`Uint8 + [ + case + (Tag 0) + ~title:"Applied" + (merge_objs (obj1 (req "status" (constant "applied"))) encoding) + (fun o -> + match o with + | Skipped _ | Failed _ | Backtracked _ -> None + | Applied o -> ( + match select (Successful_manager_result o) with + | None -> None + | Some o -> Some ((), proj o))) + (fun ((), x) -> Applied (inj x)); + case + (Tag 1) + ~title:"Failed" + (obj2 + (req "status" (constant "failed")) + (req "errors" trace_encoding)) + (function Failed (_, errs) -> Some ((), errs) | _ -> None) + (fun ((), errs) -> Failed (kind, errs)); + case + (Tag 2) + ~title:"Skipped" + (obj1 (req "status" (constant "skipped"))) + (function Skipped _ -> Some () | _ -> None) + (fun () -> Skipped kind); + case + (Tag 3) + ~title:"Backtracked" + (merge_objs + (obj2 + (req "status" (constant "backtracked")) + (opt "errors" trace_encoding)) + encoding) + (fun o -> + match o with + | Skipped _ | Failed _ | Applied _ -> None + | Backtracked (o, errs) -> ( + match select (Successful_manager_result o) with + | None -> None + | Some o -> Some (((), errs), proj o))) + (fun (((), errs), x) -> Backtracked (inj x, errs)); + ] + in + MCase {op_case; encoding; kind; select; proj; inj; t} + + let reveal_case = + make + ~op_case:Operation.Encoding.Manager_operations.reveal_case + ~encoding: + Data_encoding.( + obj1 (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Reveal_result _ as op) -> Some op + | _ -> None) + ~kind:Kind.Reveal_manager_kind + ~proj:(function Reveal_result {consumed_gas} -> consumed_gas) + ~inj:(fun consumed_gas -> Reveal_result {consumed_gas}) + + let transaction_contract_variant_cases = + let case = function + | Tag tag -> + (* The tag was used by old variant. It have been removed in + protocol proposal O, it can be unblocked in the future. *) + let to_tx_rollup_reserved_tag = 1 in + assert (Compare.Int.(tag <> to_tx_rollup_reserved_tag)) ; + case (Tag tag) + | _ as c -> case c + in + union + [ + case + ~title:"To_contract" + (Tag 0) + (obj9 + (opt "storage" Script.expr_encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "ticket_updates" Ticket_receipt.encoding []) + (dft "originated_contracts" (list Contract.originated_encoding) []) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero) + (dft "allocated_destination_contract" bool false) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + (function + | Transaction_to_contract_result + { + storage; + lazy_storage_diff; + balance_updates; + ticket_receipt; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + allocated_destination_contract; + } -> + Some + ( storage, + balance_updates, + ticket_receipt, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + allocated_destination_contract, + lazy_storage_diff ) + | _ -> None) + (fun ( storage, + balance_updates, + ticket_receipt, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + allocated_destination_contract, + lazy_storage_diff ) -> + Transaction_to_contract_result + { + storage; + lazy_storage_diff; + balance_updates; + ticket_receipt; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + allocated_destination_contract; + }); + case + ~title:"To_smart_rollup" + (Tag 2) + (obj2 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "ticket_updates" Ticket_receipt.encoding)) + (function + | Transaction_to_sc_rollup_result {consumed_gas; ticket_receipt} -> + Some (consumed_gas, ticket_receipt) + | _ -> None) + (function + | consumed_gas, ticket_receipt -> + Transaction_to_sc_rollup_result {consumed_gas; ticket_receipt}); + ] + + let transaction_case = + make + ~op_case:Operation.Encoding.Manager_operations.transaction_case + ~encoding:transaction_contract_variant_cases + ~select:(function + | Successful_manager_result (Transaction_result _ as op) -> Some op + | _ -> None) + ~kind:Kind.Transaction_manager_kind + ~proj:(function Transaction_result x -> x) + ~inj:(fun x -> Transaction_result x) + + let origination_case = + make + ~op_case:Operation.Encoding.Manager_operations.origination_case + ~encoding: + (obj6 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "originated_contracts" (list Contract.originated_encoding) []) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero) + (opt "lazy_storage_diff" Lazy_storage.encoding)) + ~select:(function + | Successful_manager_result (Origination_result _ as op) -> Some op + | _ -> None) + ~proj:(function + | Origination_result + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + } -> + (* There used to be a [legacy_lazy_storage_diff] returned as the + first component of the tuple below, and the non-legacy one + returned as the last component. The legacy one has been removed, + but it was chosen to keep the non-legacy one at its position, + hence the order difference with regards to the record above. *) + ( balance_updates, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + lazy_storage_diff )) + ~kind:Kind.Origination_manager_kind + ~inj: + (fun ( balance_updates, + originated_contracts, + consumed_gas, + storage_size, + paid_storage_size_diff, + lazy_storage_diff ) -> + Origination_result + { + lazy_storage_diff; + balance_updates; + originated_contracts; + consumed_gas; + storage_size; + paid_storage_size_diff; + }) + + let register_global_constant_case = + make + ~op_case: + Operation.Encoding.Manager_operations.register_global_constant_case + ~encoding: + (obj4 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "storage_size" z Z.zero) + (req "global_address" Script_expr_hash.encoding)) + ~select:(function + | Successful_manager_result (Register_global_constant_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Register_global_constant_result + {balance_updates; consumed_gas; size_of_constant; global_address} -> + (balance_updates, consumed_gas, size_of_constant, global_address)) + ~kind:Kind.Register_global_constant_manager_kind + ~inj: + (fun (balance_updates, consumed_gas, size_of_constant, global_address) -> + Register_global_constant_result + {balance_updates; consumed_gas; size_of_constant; global_address}) + + let delegation_case = + make + ~op_case:Operation.Encoding.Manager_operations.delegation_case + ~encoding: + Data_encoding.( + obj2 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "balance_updates" Receipt.balance_updates_encoding [])) + ~select:(function + | Successful_manager_result (Delegation_result _ as op) -> Some op + | _ -> None) + ~kind:Kind.Delegation_manager_kind + ~proj:(function + | Delegation_result {consumed_gas; balance_updates} -> + (consumed_gas, balance_updates)) + ~inj:(fun (consumed_gas, balance_updates) -> + Delegation_result {consumed_gas; balance_updates}) + + let update_consensus_key_case = + make + ~op_case:Operation.Encoding.Manager_operations.update_consensus_key_case + ~encoding: + Data_encoding.( + obj1 (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Update_consensus_key_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Update_consensus_key_manager_kind + ~proj:(function + | Update_consensus_key_result {consumed_gas} -> consumed_gas) + ~inj:(fun consumed_gas -> Update_consensus_key_result {consumed_gas}) + + let set_deposits_limit_case = + make + ~op_case:Operation.Encoding.Manager_operations.set_deposits_limit_case + ~encoding: + Data_encoding.( + obj1 (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Set_deposits_limit_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Set_deposits_limit_manager_kind + ~proj:(function + | Set_deposits_limit_result {consumed_gas} -> consumed_gas) + ~inj:(fun consumed_gas -> Set_deposits_limit_result {consumed_gas}) + + let increase_paid_storage_case = + make + ~op_case:Operation.Encoding.Manager_operations.increase_paid_storage_case + ~encoding: + Data_encoding.( + obj2 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Increase_paid_storage_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Increase_paid_storage_manager_kind + ~proj:(function + | Increase_paid_storage_result {balance_updates; consumed_gas} -> + (balance_updates, consumed_gas)) + ~inj:(fun (balance_updates, consumed_gas) -> + Increase_paid_storage_result {balance_updates; consumed_gas}) + + let transfer_ticket_case = + make + ~op_case:Operation.Encoding.Manager_operations.transfer_ticket_case + ~encoding: + Data_encoding.( + obj4 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "ticket_updates" Ticket_receipt.encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "paid_storage_size_diff" z Z.zero)) + ~select:(function + | Successful_manager_result (Transfer_ticket_result _ as op) -> Some op + | _ -> None) + ~kind:Kind.Transfer_ticket_manager_kind + ~proj:(function + | Transfer_ticket_result + { + balance_updates; + ticket_receipt; + consumed_gas; + paid_storage_size_diff; + } -> + ( balance_updates, + ticket_receipt, + consumed_gas, + paid_storage_size_diff )) + ~inj: + (fun ( balance_updates, + ticket_receipt, + consumed_gas, + paid_storage_size_diff ) -> + Transfer_ticket_result + { + balance_updates; + ticket_receipt; + consumed_gas; + paid_storage_size_diff; + }) + + let dal_publish_commitment_case = + make + ~op_case:Operation.Encoding.Manager_operations.dal_publish_commitment_case + ~encoding: + (obj2 + (req "slot_header" Dal.Slot.Header.encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Dal_publish_commitment_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Dal_publish_commitment_result {slot_header; consumed_gas} -> + (slot_header, consumed_gas)) + ~kind:Kind.Dal_publish_commitment_manager_kind + ~inj:(fun (slot_header, consumed_gas) -> + Dal_publish_commitment_result {slot_header; consumed_gas}) + + let zk_rollup_origination_case = + make + ~op_case:Operation.Encoding.Manager_operations.zk_rollup_origination_case + ~encoding: + Data_encoding.( + obj4 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "originated_zk_rollup" Zk_rollup.Address.encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "size" z)) + ~select:(function + | Successful_manager_result (Zk_rollup_origination_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Zk_rollup_origination_manager_kind + ~proj:(function + | Zk_rollup_origination_result + {balance_updates; originated_zk_rollup; consumed_gas; storage_size} + -> + (balance_updates, originated_zk_rollup, consumed_gas, storage_size)) + ~inj: + (fun (balance_updates, originated_zk_rollup, consumed_gas, storage_size) -> + Zk_rollup_origination_result + {balance_updates; originated_zk_rollup; consumed_gas; storage_size}) + + let zk_rollup_publish_case = + make + ~op_case:Operation.Encoding.Manager_operations.zk_rollup_publish_case + ~encoding: + Data_encoding.( + obj3 + (req "balance_updates" Receipt.balance_updates_encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "size" z)) + ~select:(function + | Successful_manager_result (Zk_rollup_publish_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Zk_rollup_publish_manager_kind + ~proj:(function + | Zk_rollup_publish_result + {balance_updates; consumed_gas; paid_storage_size_diff} -> + (balance_updates, consumed_gas, paid_storage_size_diff)) + ~inj:(fun (balance_updates, consumed_gas, paid_storage_size_diff) -> + Zk_rollup_publish_result + {balance_updates; consumed_gas; paid_storage_size_diff}) + + let zk_rollup_update_case = + make + ~op_case:Operation.Encoding.Manager_operations.zk_rollup_update_case + ~encoding: + Data_encoding.( + obj3 + (req "balance_updates" Receipt.balance_updates_encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "paid_storage_size_diff" z Z.zero)) + ~select:(function + | Successful_manager_result (Zk_rollup_update_result _ as op) -> Some op + | _ -> None) + ~kind:Kind.Zk_rollup_update_manager_kind + ~proj:(function + | Zk_rollup_update_result + {balance_updates; consumed_gas; paid_storage_size_diff} -> + (balance_updates, consumed_gas, paid_storage_size_diff)) + ~inj:(fun (balance_updates, consumed_gas, paid_storage_size_diff) -> + Zk_rollup_update_result + {balance_updates; consumed_gas; paid_storage_size_diff}) + + let sc_rollup_originate_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_originate_case + ~encoding: + (obj5 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "address" Sc_rollup.Address.encoding) + (req "genesis_commitment_hash" Sc_rollup.Commitment.Hash.encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "size" z)) + ~select:(function + | Successful_manager_result (Sc_rollup_originate_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Sc_rollup_originate_result + { + balance_updates; + address; + genesis_commitment_hash; + consumed_gas; + size; + } -> + ( balance_updates, + address, + genesis_commitment_hash, + consumed_gas, + size )) + ~kind:Kind.Sc_rollup_originate_manager_kind + ~inj: + (fun ( balance_updates, + address, + genesis_commitment_hash, + consumed_gas, + size ) -> + Sc_rollup_originate_result + { + balance_updates; + address; + genesis_commitment_hash; + consumed_gas; + size; + }) + + let sc_rollup_add_messages_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_add_messages_case + ~encoding: + (obj1 (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Sc_rollup_add_messages_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Sc_rollup_add_messages_result {consumed_gas} -> consumed_gas) + ~kind:Kind.Sc_rollup_add_messages_manager_kind + ~inj:(fun consumed_gas -> Sc_rollup_add_messages_result {consumed_gas}) + + let sc_rollup_cement_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_cement_case + ~encoding: + (obj3 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "inbox_level" Raw_level.encoding) + (req "commitment_hash" Sc_rollup.Commitment.Hash.encoding)) + ~select:(function + | Successful_manager_result (Sc_rollup_cement_result _ as op) -> Some op + | _ -> None) + ~proj:(function + | Sc_rollup_cement_result {consumed_gas; inbox_level; commitment_hash} + -> + (consumed_gas, inbox_level, commitment_hash)) + ~kind:Kind.Sc_rollup_cement_manager_kind + ~inj:(fun (consumed_gas, inbox_level, commitment_hash) -> + Sc_rollup_cement_result {consumed_gas; inbox_level; commitment_hash}) + + let sc_rollup_publish_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_publish_case + ~encoding: + (obj4 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "staked_hash" Sc_rollup.Commitment.Hash.encoding) + (req "published_at_level" Raw_level.encoding) + (req "balance_updates" Receipt.balance_updates_encoding)) + ~select:(function + | Successful_manager_result (Sc_rollup_publish_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Sc_rollup_publish_result + {consumed_gas; staked_hash; published_at_level; balance_updates} -> + (consumed_gas, staked_hash, published_at_level, balance_updates)) + ~kind:Kind.Sc_rollup_publish_manager_kind + ~inj: + (fun (consumed_gas, staked_hash, published_at_level, balance_updates) -> + Sc_rollup_publish_result + {consumed_gas; staked_hash; published_at_level; balance_updates}) + + let sc_rollup_refute_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_refute_case + ~encoding: + Data_encoding.( + obj3 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "game_status" Sc_rollup.Game.status_encoding) + (req "balance_updates" Receipt.balance_updates_encoding)) + ~select:(function + | Successful_manager_result (Sc_rollup_refute_result _ as op) -> Some op + | _ -> None) + ~proj:(function + | Sc_rollup_refute_result {consumed_gas; game_status; balance_updates} + -> + (consumed_gas, game_status, balance_updates)) + ~kind:Kind.Sc_rollup_refute_manager_kind + ~inj:(fun (consumed_gas, game_status, balance_updates) -> + Sc_rollup_refute_result {consumed_gas; game_status; balance_updates}) + + let sc_rollup_timeout_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_timeout_case + ~encoding: + (obj3 + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (req "game_status" Sc_rollup.Game.status_encoding) + (req "balance_updates" Receipt.balance_updates_encoding)) + ~select:(function + | Successful_manager_result (Sc_rollup_timeout_result _ as op) -> + Some op + | _ -> None) + ~proj:(function + | Sc_rollup_timeout_result {consumed_gas; game_status; balance_updates} + -> + (consumed_gas, game_status, balance_updates)) + ~kind:Kind.Sc_rollup_timeout_manager_kind + ~inj:(fun (consumed_gas, game_status, balance_updates) -> + Sc_rollup_timeout_result {consumed_gas; game_status; balance_updates}) + + let sc_rollup_execute_outbox_message_case = + make + ~op_case: + Operation.Encoding.Manager_operations + .sc_rollup_execute_outbox_message_case + ~encoding: + Data_encoding.( + obj5 + (req "balance_updates" Receipt.balance_updates_encoding) + (req "ticket_updates" Ticket_receipt.encoding) + (opt "whitelist_update" Sc_rollup.Whitelist.update_encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero) + (dft "paid_storage_size_diff" z Z.zero)) + ~select:(function + | Successful_manager_result + (Sc_rollup_execute_outbox_message_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Sc_rollup_execute_outbox_message_manager_kind + ~proj:(function + | Sc_rollup_execute_outbox_message_result + { + balance_updates; + ticket_receipt; + whitelist_update; + consumed_gas; + paid_storage_size_diff; + } -> + ( balance_updates, + ticket_receipt, + whitelist_update, + consumed_gas, + paid_storage_size_diff )) + ~inj: + (fun ( balance_updates, + ticket_receipt, + whitelist_update, + consumed_gas, + paid_storage_size_diff ) -> + Sc_rollup_execute_outbox_message_result + { + balance_updates; + ticket_receipt; + whitelist_update; + consumed_gas; + paid_storage_size_diff; + }) + + let sc_rollup_recover_bond_case = + make + ~op_case:Operation.Encoding.Manager_operations.sc_rollup_recover_bond_case + ~encoding: + Data_encoding.( + obj2 + (req "balance_updates" Receipt.balance_updates_encoding) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Sc_rollup_recover_bond_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Sc_rollup_recover_bond_manager_kind + ~proj:(function + | Sc_rollup_recover_bond_result {balance_updates; consumed_gas} -> + (balance_updates, consumed_gas)) + ~inj:(fun (balance_updates, consumed_gas) -> + Sc_rollup_recover_bond_result {balance_updates; consumed_gas}) +end + +let successful_manager_operation_result_encoding : + packed_successful_manager_operation_result Data_encoding.t = + let make (type kind) + (Manager_result.MCase res_case : kind Manager_result.case) = + let (Operation.Encoding.Manager_operations.MCase op_case) = + res_case.op_case + in + case + (Tag op_case.tag) + ~title:op_case.name + (merge_objs (obj1 (req "kind" (constant op_case.name))) res_case.encoding) + (fun res -> + match res_case.select res with + | Some res -> Some ((), res_case.proj res) + | None -> None) + (fun ((), res) -> Successful_manager_result (res_case.inj res)) + in + def "operation.alpha.successful_manager_operation_result" + @@ union + [ + make Manager_result.reveal_case; + make Manager_result.transaction_case; + make Manager_result.origination_case; + make Manager_result.delegation_case; + make Manager_result.update_consensus_key_case; + make Manager_result.set_deposits_limit_case; + make Manager_result.increase_paid_storage_case; + make Manager_result.sc_rollup_originate_case; + ] + +type 'kind contents_result = + | Preattestation_result : { + balance_updates : Receipt.balance_updates; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + consensus_power : int; + } + -> Kind.preattestation contents_result + | Attestation_result : { + balance_updates : Receipt.balance_updates; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + consensus_power : int; + } + -> Kind.attestation contents_result + | Seed_nonce_revelation_result : + Receipt.balance_updates + -> Kind.seed_nonce_revelation contents_result + | Vdf_revelation_result : + Receipt.balance_updates + -> Kind.vdf_revelation contents_result + | Double_attestation_evidence_result : { + forbidden_delegate : Signature.public_key_hash option; + balance_updates : Receipt.balance_updates; + } + -> Kind.double_attestation_evidence contents_result + | Double_preattestation_evidence_result : { + forbidden_delegate : Signature.public_key_hash option; + balance_updates : Receipt.balance_updates; + } + -> Kind.double_preattestation_evidence contents_result + | Double_baking_evidence_result : { + forbidden_delegate : Signature.public_key_hash option; + balance_updates : Receipt.balance_updates; + } + -> Kind.double_baking_evidence contents_result + | Activate_account_result : + Receipt.balance_updates + -> Kind.activate_account contents_result + | Proposals_result : Kind.proposals contents_result + | Ballot_result : Kind.ballot contents_result + | Drain_delegate_result : { + balance_updates : Receipt.balance_updates; + allocated_destination_contract : bool; + } + -> Kind.drain_delegate contents_result + | Manager_operation_result : { + balance_updates : Receipt.balance_updates; + operation_result : 'kind manager_operation_result; + internal_operation_results : packed_internal_operation_result list; + } + -> 'kind Kind.manager contents_result + +type packed_contents_result = + | Contents_result : 'kind contents_result -> packed_contents_result + +type packed_contents_and_result = + | Contents_and_result : + 'kind Operation.contents * 'kind contents_result + -> packed_contents_and_result + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +let equal_manager_kind : + type a b. a Kind.manager -> b Kind.manager -> (a, b) eq option = + fun ka kb -> + match (ka, kb) with + | Kind.Reveal_manager_kind, Kind.Reveal_manager_kind -> Some Eq + | Kind.Reveal_manager_kind, _ -> None + | Kind.Transaction_manager_kind, Kind.Transaction_manager_kind -> Some Eq + | Kind.Transaction_manager_kind, _ -> None + | Kind.Origination_manager_kind, Kind.Origination_manager_kind -> Some Eq + | Kind.Origination_manager_kind, _ -> None + | Kind.Delegation_manager_kind, Kind.Delegation_manager_kind -> Some Eq + | Kind.Delegation_manager_kind, _ -> None + | ( Kind.Update_consensus_key_manager_kind, + Kind.Update_consensus_key_manager_kind ) -> + Some Eq + | Kind.Update_consensus_key_manager_kind, _ -> None + | ( Kind.Register_global_constant_manager_kind, + Kind.Register_global_constant_manager_kind ) -> + Some Eq + | Kind.Event_manager_kind, Kind.Event_manager_kind -> Some Eq + | Kind.Event_manager_kind, _ -> None + | Kind.Register_global_constant_manager_kind, _ -> None + | Kind.Set_deposits_limit_manager_kind, Kind.Set_deposits_limit_manager_kind + -> + Some Eq + | Kind.Set_deposits_limit_manager_kind, _ -> None + | ( Kind.Increase_paid_storage_manager_kind, + Kind.Increase_paid_storage_manager_kind ) -> + Some Eq + | Kind.Increase_paid_storage_manager_kind, _ -> None + | Kind.Transfer_ticket_manager_kind, Kind.Transfer_ticket_manager_kind -> + Some Eq + | Kind.Transfer_ticket_manager_kind, _ -> None + | ( Kind.Dal_publish_commitment_manager_kind, + Kind.Dal_publish_commitment_manager_kind ) -> + Some Eq + | Kind.Dal_publish_commitment_manager_kind, _ -> None + | Kind.Sc_rollup_originate_manager_kind, Kind.Sc_rollup_originate_manager_kind + -> + Some Eq + | Kind.Sc_rollup_originate_manager_kind, _ -> None + | ( Kind.Sc_rollup_add_messages_manager_kind, + Kind.Sc_rollup_add_messages_manager_kind ) -> + Some Eq + | Kind.Sc_rollup_add_messages_manager_kind, _ -> None + | Kind.Sc_rollup_cement_manager_kind, Kind.Sc_rollup_cement_manager_kind -> + Some Eq + | Kind.Sc_rollup_cement_manager_kind, _ -> None + | Kind.Sc_rollup_publish_manager_kind, Kind.Sc_rollup_publish_manager_kind -> + Some Eq + | Kind.Sc_rollup_publish_manager_kind, _ -> None + | Kind.Sc_rollup_refute_manager_kind, Kind.Sc_rollup_refute_manager_kind -> + Some Eq + | Kind.Sc_rollup_refute_manager_kind, _ -> None + | Kind.Sc_rollup_timeout_manager_kind, Kind.Sc_rollup_timeout_manager_kind -> + Some Eq + | Kind.Sc_rollup_timeout_manager_kind, _ -> None + | ( Kind.Sc_rollup_execute_outbox_message_manager_kind, + Kind.Sc_rollup_execute_outbox_message_manager_kind ) -> + Some Eq + | Kind.Sc_rollup_execute_outbox_message_manager_kind, _ -> None + | ( Kind.Sc_rollup_recover_bond_manager_kind, + Kind.Sc_rollup_recover_bond_manager_kind ) -> + Some Eq + | Kind.Sc_rollup_recover_bond_manager_kind, _ -> None + | ( Kind.Zk_rollup_origination_manager_kind, + Kind.Zk_rollup_origination_manager_kind ) -> + Some Eq + | Kind.Zk_rollup_origination_manager_kind, _ -> None + | Kind.Zk_rollup_publish_manager_kind, Kind.Zk_rollup_publish_manager_kind -> + Some Eq + | Kind.Zk_rollup_publish_manager_kind, _ -> None + | Kind.Zk_rollup_update_manager_kind, Kind.Zk_rollup_update_manager_kind -> + Some Eq + | Kind.Zk_rollup_update_manager_kind, _ -> None + +module Encoding = struct + let consensus_result_encoding power_name = + let open Data_encoding in + obj4 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (req "delegate" Signature.Public_key_hash.encoding) + (req (Format.asprintf "%s_power" power_name) int31) + (req "consensus_key" Signature.Public_key_hash.encoding) + + let consensus_result_encoding_legacy power_name = + consensus_result_encoding power_name + + let consensus_result_encoding = consensus_result_encoding "consensus" + + type case = + | Case : { + op_case : 'kind Operation.Encoding.case; + encoding : 'a Data_encoding.t; + select : packed_contents_result -> 'kind contents_result option; + mselect : + packed_contents_and_result -> + ('kind contents * 'kind contents_result) option; + proj : 'kind contents_result -> 'a; + inj : 'a -> 'kind contents_result; + } + -> case + + let tagged_case tag name args proj inj = + let open Data_encoding in + case + tag + ~title:(String.capitalize_ascii name) + (merge_objs (obj1 (req "kind" (constant name))) args) + (fun x -> match proj x with None -> None | Some x -> Some ((), x)) + (fun ((), x) -> inj x) + + let preendorsement_case = + Case + { + op_case = Operation.Encoding.preendorsement_case; + encoding = consensus_result_encoding_legacy "preendorsement"; + select = + (function + | Contents_result (Preattestation_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Preattestation _ as op), res) -> Some (op, res) + | _ -> None); + proj = + (function + | Preattestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Preattestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let preattestation_case = + Case + { + op_case = Operation.Encoding.preattestation_case; + encoding = consensus_result_encoding; + select = + (function + | Contents_result (Preattestation_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Preattestation _ as op), res) -> Some (op, res) + | _ -> None); + proj = + (function + | Preattestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Preattestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let endorsement_case = + Case + { + op_case = Operation.Encoding.endorsement_case; + encoding = consensus_result_encoding_legacy "endorsement"; + select = + (function + | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result + ((Attestation {dal_content = None; _} as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let attestation_case = + Case + { + op_case = Operation.Encoding.attestation_case; + encoding = consensus_result_encoding; + select = + (function + | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result + ((Attestation {dal_content = None; _} as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let endorsement_with_dal_case = + Case + { + op_case = Operation.Encoding.endorsement_with_dal_case; + encoding = consensus_result_encoding_legacy "endorsement"; + select = + (function + | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result + ((Attestation {dal_content = Some _; _} as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let attestation_with_dal_case = + Case + { + op_case = Operation.Encoding.attestation_with_dal_case; + encoding = consensus_result_encoding; + select = + (function + | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result + ((Attestation {dal_content = Some _; _} as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let seed_nonce_revelation_case = + Case + { + op_case = Operation.Encoding.seed_nonce_revelation_case; + encoding = + obj1 (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Seed_nonce_revelation_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Seed_nonce_revelation _ as op), res) -> + Some (op, res) + | _ -> None); + proj = (fun (Seed_nonce_revelation_result bus) -> bus); + inj = (fun bus -> Seed_nonce_revelation_result bus); + } + + let vdf_revelation_case = + Case + { + op_case = Operation.Encoding.vdf_revelation_case; + encoding = + obj1 (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Vdf_revelation_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Vdf_revelation _ as op), res) -> Some (op, res) + | _ -> None); + proj = (fun (Vdf_revelation_result bus) -> bus); + inj = (fun bus -> Vdf_revelation_result bus); + } + + let double_endorsement_evidence_case = + Case + { + op_case = Operation.Encoding.double_endorsement_evidence_case; + encoding = + obj2 + (opt "forbidden_delegate" Signature.Public_key_hash.encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Double_attestation_evidence_result _ as op) -> + Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Double_attestation_evidence _ as op), res) -> + Some (op, res) + | _ -> None); + proj = + (fun (Double_attestation_evidence_result + {forbidden_delegate; balance_updates}) -> + (forbidden_delegate, balance_updates)); + inj = + (fun (forbidden_delegate, balance_updates) -> + Double_attestation_evidence_result + {forbidden_delegate; balance_updates}); + } + + let double_attestation_evidence_case = + Case + { + op_case = Operation.Encoding.double_attestation_evidence_case; + encoding = + obj2 + (opt "forbidden_delegate" Signature.Public_key_hash.encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Double_attestation_evidence_result _ as op) -> + Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Double_attestation_evidence _ as op), res) -> + Some (op, res) + | _ -> None); + proj = + (fun (Double_attestation_evidence_result + {forbidden_delegate; balance_updates}) -> + (forbidden_delegate, balance_updates)); + inj = + (fun (forbidden_delegate, balance_updates) -> + Double_attestation_evidence_result + {forbidden_delegate; balance_updates}); + } + + let double_preendorsement_evidence_case = + Case + { + op_case = Operation.Encoding.double_preendorsement_evidence_case; + encoding = + obj2 + (opt "forbidden_delegate" Signature.Public_key_hash.encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Double_preattestation_evidence_result _ as op) -> + Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Double_preattestation_evidence _ as op), res) + -> + Some (op, res) + | _ -> None); + proj = + (fun (Double_preattestation_evidence_result + {forbidden_delegate; balance_updates}) -> + (forbidden_delegate, balance_updates)); + inj = + (fun (forbidden_delegate, balance_updates) -> + Double_preattestation_evidence_result + {forbidden_delegate; balance_updates}); + } + + let double_preattestation_evidence_case = + Case + { + op_case = Operation.Encoding.double_preattestation_evidence_case; + encoding = + obj2 + (opt "forbidden_delegate" Signature.Public_key_hash.encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Double_preattestation_evidence_result _ as op) -> + Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Double_preattestation_evidence _ as op), res) + -> + Some (op, res) + | _ -> None); + proj = + (fun (Double_preattestation_evidence_result + {forbidden_delegate; balance_updates}) -> + (forbidden_delegate, balance_updates)); + inj = + (fun (forbidden_delegate, balance_updates) -> + Double_preattestation_evidence_result + {forbidden_delegate; balance_updates}); + } + + let double_baking_evidence_case = + Case + { + op_case = Operation.Encoding.double_baking_evidence_case; + encoding = + obj2 + (opt "forbidden_delegate" Signature.Public_key_hash.encoding) + (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Double_baking_evidence_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Double_baking_evidence _ as op), res) -> + Some (op, res) + | _ -> None); + proj = + (fun (Double_baking_evidence_result + {forbidden_delegate; balance_updates}) -> + (forbidden_delegate, balance_updates)); + inj = + (fun (forbidden_delegate, balance_updates) -> + Double_baking_evidence_result {forbidden_delegate; balance_updates}); + } + + let activate_account_case = + Case + { + op_case = Operation.Encoding.activate_account_case; + encoding = + obj1 (dft "balance_updates" Receipt.balance_updates_encoding []); + select = + (function + | Contents_result (Activate_account_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Activate_account _ as op), res) -> + Some (op, res) + | _ -> None); + proj = (fun (Activate_account_result bus) -> bus); + inj = (fun bus -> Activate_account_result bus); + } + + let proposals_case = + Case + { + op_case = Operation.Encoding.proposals_case; + encoding = Data_encoding.empty; + select = + (function + | Contents_result (Proposals_result as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result ((Proposals _ as op), res) -> Some (op, res) + | _ -> None); + proj = (fun Proposals_result -> ()); + inj = (fun () -> Proposals_result); + } + + let ballot_case = + Case + { + op_case = Operation.Encoding.ballot_case; + encoding = Data_encoding.empty; + select = + (function + | Contents_result (Ballot_result as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result ((Ballot _ as op), res) -> Some (op, res) + | _ -> None); + proj = (fun Ballot_result -> ()); + inj = (fun () -> Ballot_result); + } + + let drain_delegate_case = + Case + { + op_case = Operation.Encoding.drain_delegate_case; + encoding = + Data_encoding.( + obj2 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "allocated_destination_contract" bool false)); + select = + (function + | Contents_result (Drain_delegate_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Drain_delegate _ as op), res) -> Some (op, res) + | _ -> None); + proj = + (function + | Drain_delegate_result + {balance_updates; allocated_destination_contract} -> + (balance_updates, allocated_destination_contract)); + inj = + (fun (balance_updates, allocated_destination_contract) -> + Drain_delegate_result + {balance_updates; allocated_destination_contract}); + } + + let make_manager_case (type kind) + (Operation.Encoding.Case op_case : + kind Kind.manager Operation.Encoding.case) + (Manager_result.MCase res_case : kind Manager_result.case) mselect = + Case + { + op_case = Operation.Encoding.Case op_case; + encoding = + obj3 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (req "operation_result" res_case.t) + (dft + "internal_operation_results" + (list internal_operation_result_encoding) + []); + select = + (function + | Contents_result + (Manager_operation_result + ({operation_result = Applied res; _} as op)) -> ( + match res_case.select (Successful_manager_result res) with + | Some res -> + Some + (Manager_operation_result + {op with operation_result = Applied res}) + | None -> None) + | Contents_result + (Manager_operation_result + ({operation_result = Backtracked (res, errs); _} as op)) -> ( + match res_case.select (Successful_manager_result res) with + | Some res -> + Some + (Manager_operation_result + {op with operation_result = Backtracked (res, errs)}) + | None -> None) + | Contents_result + (Manager_operation_result + ({operation_result = Skipped kind; _} as op)) -> ( + match equal_manager_kind kind res_case.kind with + | None -> None + | Some Eq -> + Some + (Manager_operation_result + {op with operation_result = Skipped kind})) + | Contents_result + (Manager_operation_result + ({operation_result = Failed (kind, errs); _} as op)) -> ( + match equal_manager_kind kind res_case.kind with + | None -> None + | Some Eq -> + Some + (Manager_operation_result + {op with operation_result = Failed (kind, errs)})) + | Contents_result (Preattestation_result _) -> None + | Contents_result (Attestation_result _) -> None + | Contents_result Ballot_result -> None + | Contents_result (Seed_nonce_revelation_result _) -> None + | Contents_result (Vdf_revelation_result _) -> None + | Contents_result (Double_attestation_evidence_result _) -> None + | Contents_result (Double_preattestation_evidence_result _) -> None + | Contents_result (Double_baking_evidence_result _) -> None + | Contents_result (Activate_account_result _) -> None + | Contents_result (Drain_delegate_result _) -> None + | Contents_result Proposals_result -> None); + mselect; + proj = + (fun (Manager_operation_result + { + balance_updates = bus; + operation_result = r; + internal_operation_results = rs; + }) -> + (bus, r, rs)); + inj = + (fun (bus, r, rs) -> + Manager_operation_result + { + balance_updates = bus; + operation_result = r; + internal_operation_results = rs; + }); + } + + let reveal_case = + make_manager_case + Operation.Encoding.reveal_case + Manager_result.reveal_case + (function + | Contents_and_result + ((Manager_operation {operation = Reveal _; _} as op), res) -> + Some (op, res) + | _ -> None) + + let transaction_case = + make_manager_case + Operation.Encoding.transaction_case + Manager_result.transaction_case + (function + | Contents_and_result + ((Manager_operation {operation = Transaction _; _} as op), res) -> + Some (op, res) + | _ -> None) + + let origination_case = + make_manager_case + Operation.Encoding.origination_case + Manager_result.origination_case + (function + | Contents_and_result + ((Manager_operation {operation = Origination _; _} as op), res) -> + Some (op, res) + | _ -> None) + + let delegation_case = + make_manager_case + Operation.Encoding.delegation_case + Manager_result.delegation_case + (function + | Contents_and_result + ((Manager_operation {operation = Delegation _; _} as op), res) -> + Some (op, res) + | _ -> None) + + let update_consensus_key_case = + make_manager_case + Operation.Encoding.update_consensus_key_case + Manager_result.update_consensus_key_case + (function + | Contents_and_result + ( (Manager_operation {operation = Update_consensus_key _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let register_global_constant_case = + make_manager_case + Operation.Encoding.register_global_constant_case + Manager_result.register_global_constant_case + (function + | Contents_and_result + ( (Manager_operation {operation = Register_global_constant _; _} as + op), + res ) -> + Some (op, res) + | _ -> None) + + let set_deposits_limit_case = + make_manager_case + Operation.Encoding.set_deposits_limit_case + Manager_result.set_deposits_limit_case + (function + | Contents_and_result + ( (Manager_operation {operation = Set_deposits_limit _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let increase_paid_storage_case = + make_manager_case + Operation.Encoding.increase_paid_storage_case + Manager_result.increase_paid_storage_case + (function + | Contents_and_result + ( (Manager_operation {operation = Increase_paid_storage _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let transfer_ticket_case = + make_manager_case + Operation.Encoding.transfer_ticket_case + Manager_result.transfer_ticket_case + (function + | Contents_and_result + ((Manager_operation {operation = Transfer_ticket _; _} as op), res) + -> + Some (op, res) + | _ -> None) + + let dal_publish_commitment_case = + make_manager_case + Operation.Encoding.dal_publish_commitment_case + Manager_result.dal_publish_commitment_case + (function + | Contents_and_result + ( (Manager_operation {operation = Dal_publish_commitment _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let sc_rollup_originate_case = + make_manager_case + Operation.Encoding.sc_rollup_originate_case + Manager_result.sc_rollup_originate_case + (function + | Contents_and_result + ( (Manager_operation {operation = Sc_rollup_originate _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let sc_rollup_add_messages_case = + make_manager_case + Operation.Encoding.sc_rollup_add_messages_case + Manager_result.sc_rollup_add_messages_case + (function + | Contents_and_result + ( (Manager_operation {operation = Sc_rollup_add_messages _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let sc_rollup_cement_case = + make_manager_case + Operation.Encoding.sc_rollup_cement_case + Manager_result.sc_rollup_cement_case + (function + | Contents_and_result + ((Manager_operation {operation = Sc_rollup_cement _; _} as op), res) + -> + Some (op, res) + | _ -> None) + + let sc_rollup_publish_case = + make_manager_case + Operation.Encoding.sc_rollup_publish_case + Manager_result.sc_rollup_publish_case + (function + | Contents_and_result + ((Manager_operation {operation = Sc_rollup_publish _; _} as op), res) + -> + Some (op, res) + | _ -> None) + + let sc_rollup_refute_case = + make_manager_case + Operation.Encoding.sc_rollup_refute_case + Manager_result.sc_rollup_refute_case + (function + | Contents_and_result + ((Manager_operation {operation = Sc_rollup_refute _; _} as op), res) + -> + Some (op, res) + | _ -> None) + + let sc_rollup_timeout_case = + make_manager_case + Operation.Encoding.sc_rollup_timeout_case + Manager_result.sc_rollup_timeout_case + (function + | Contents_and_result + ((Manager_operation {operation = Sc_rollup_timeout _; _} as op), res) + -> + Some (op, res) + | _ -> None) + + let sc_rollup_execute_outbox_message_case = + make_manager_case + Operation.Encoding.sc_rollup_execute_outbox_message_case + Manager_result.sc_rollup_execute_outbox_message_case + (function + | Contents_and_result + ( (Manager_operation + {operation = Sc_rollup_execute_outbox_message _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let sc_rollup_recover_bond_case = + make_manager_case + Operation.Encoding.sc_rollup_recover_bond_case + Manager_result.sc_rollup_recover_bond_case + (function + | Contents_and_result + ( (Manager_operation {operation = Sc_rollup_recover_bond _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let zk_rollup_origination_case = + make_manager_case + Operation.Encoding.zk_rollup_origination_case + Manager_result.zk_rollup_origination_case + (function + | Contents_and_result + ( (Manager_operation {operation = Zk_rollup_origination _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + + let zk_rollup_publish_case = + make_manager_case + Operation.Encoding.zk_rollup_publish_case + Manager_result.zk_rollup_publish_case + (function + | Contents_and_result + ((Manager_operation {operation = Zk_rollup_publish _; _} as op), res) + -> + Some (op, res) + | _ -> None) + + let zk_rollup_update_case = + make_manager_case + Operation.Encoding.zk_rollup_update_case + Manager_result.zk_rollup_update_case + (function + | Contents_and_result + ((Manager_operation {operation = Zk_rollup_update _; _} as op), res) + -> + Some (op, res) + | _ -> None) +end + +let common_cases = + let open Encoding in + [ + seed_nonce_revelation_case; + vdf_revelation_case; + double_baking_evidence_case; + activate_account_case; + proposals_case; + ballot_case; + drain_delegate_case; + reveal_case; + transaction_case; + origination_case; + delegation_case; + register_global_constant_case; + set_deposits_limit_case; + increase_paid_storage_case; + update_consensus_key_case; + transfer_ticket_case; + dal_publish_commitment_case; + sc_rollup_originate_case; + sc_rollup_add_messages_case; + sc_rollup_cement_case; + sc_rollup_publish_case; + sc_rollup_refute_case; + sc_rollup_timeout_case; + sc_rollup_execute_outbox_message_case; + sc_rollup_recover_bond_case; + zk_rollup_origination_case; + zk_rollup_publish_case; + zk_rollup_update_case; + ] + +let contents_cases = + let open Encoding in + attestation_case :: attestation_with_dal_case :: preattestation_case + :: double_attestation_evidence_case :: double_preattestation_evidence_case + :: common_cases + +let contents_cases_with_legacy_attestation_name = + let open Encoding in + endorsement_case :: endorsement_with_dal_case :: preendorsement_case + :: double_endorsement_evidence_case :: double_preendorsement_evidence_case + :: common_cases + +let make_contents_result + (Encoding.Case + { + op_case = Operation.Encoding.Case {tag; name; _}; + encoding; + mselect = _; + select; + proj; + inj; + }) = + let proj x = match select x with None -> None | Some x -> Some (proj x) in + let inj x = Contents_result (inj x) in + Encoding.tagged_case (Tag tag) name encoding proj inj + +let contents_result_encoding = + def "operation.alpha.contents_result" + @@ union (List.map make_contents_result contents_cases) + +let contents_result_encoding_with_legacy_attestation_name = + def "operation_with_legacy_attestation_name.alpha.contents_result" + @@ union + (List.map + make_contents_result + contents_cases_with_legacy_attestation_name) + +let make_contents_and_result + (Encoding.Case + { + op_case = Operation.Encoding.Case {tag; name; encoding; proj; inj; _}; + mselect; + encoding = meta_encoding; + proj = meta_proj; + inj = meta_inj; + _; + }) = + let proj c = + match mselect c with + | Some (op, res) -> Some (proj op, meta_proj res) + | _ -> None + in + let inj (op, res) = Contents_and_result (inj op, meta_inj res) in + let encoding = merge_objs encoding (obj1 (req "metadata" meta_encoding)) in + Encoding.tagged_case (Tag tag) name encoding proj inj + +let contents_and_result_encoding = + def "operation.alpha.operation_contents_and_result" + @@ union (List.map make_contents_and_result contents_cases) + +let contents_and_result_encoding_with_legacy_attestation_name = + def + "operation_with_legacy_attestation_name.alpha.operation_contents_and_result" + @@ union + (List.map + make_contents_and_result + contents_cases_with_legacy_attestation_name) + +type 'kind contents_result_list = + | Single_result : 'kind contents_result -> 'kind contents_result_list + | Cons_result : + 'kind Kind.manager contents_result + * 'rest Kind.manager contents_result_list + -> ('kind * 'rest) Kind.manager contents_result_list + +type packed_contents_result_list = + | Contents_result_list : + 'kind contents_result_list + -> packed_contents_result_list + +let contents_result_list_conv_with_guard = + let open Result_syntax in + let rec to_list = function + | Contents_result_list (Single_result o) -> [Contents_result o] + | Contents_result_list (Cons_result (o, os)) -> + Contents_result o :: to_list (Contents_result_list os) + in + let rec of_list = function + | [] -> Error "cannot decode empty operation result" + | [Contents_result o] -> Ok (Contents_result_list (Single_result o)) + | Contents_result o :: os -> ( + let* (Contents_result_list os) = of_list os in + match (o, os) with + | Manager_operation_result _, Single_result (Manager_operation_result _) + -> + Ok (Contents_result_list (Cons_result (o, os))) + | Manager_operation_result _, Cons_result _ -> + Ok (Contents_result_list (Cons_result (o, os))) + | _ -> Error "cannot decode ill-formed operation result") + in + conv_with_guard to_list of_list + +let contents_result_list_encoding = + def "operation.alpha.contents_list_result" + @@ contents_result_list_conv_with_guard (list contents_result_encoding) + +let contents_result_list_encoding_with_legacy_attestation_name = + def "operation_with_legacy_attestation_name.alpha.contents_list_result" + @@ contents_result_list_conv_with_guard + (list contents_result_encoding_with_legacy_attestation_name) + +type 'kind contents_and_result_list = + | Single_and_result : + 'kind Alpha_context.contents * 'kind contents_result + -> 'kind contents_and_result_list + | Cons_and_result : + 'kind Kind.manager Alpha_context.contents + * 'kind Kind.manager contents_result + * 'rest Kind.manager contents_and_result_list + -> ('kind * 'rest) Kind.manager contents_and_result_list + +type packed_contents_and_result_list = + | Contents_and_result_list : + 'kind contents_and_result_list + -> packed_contents_and_result_list + +let contents_and_result_conv_with_guard = + let open Result_syntax in + let rec to_list = function + | Contents_and_result_list (Single_and_result (op, res)) -> + [Contents_and_result (op, res)] + | Contents_and_result_list (Cons_and_result (op, res, rest)) -> + Contents_and_result (op, res) :: to_list (Contents_and_result_list rest) + in + let rec of_list = function + | [] -> Error "cannot decode empty combined operation result" + | [Contents_and_result (op, res)] -> + Ok (Contents_and_result_list (Single_and_result (op, res))) + | Contents_and_result (op, res) :: rest -> ( + let* (Contents_and_result_list rest) = of_list rest in + match (op, rest) with + | Manager_operation _, Single_and_result (Manager_operation _, _) -> + Ok (Contents_and_result_list (Cons_and_result (op, res, rest))) + | Manager_operation _, Cons_and_result (_, _, _) -> + Ok (Contents_and_result_list (Cons_and_result (op, res, rest))) + | _ -> Error "cannot decode ill-formed combined operation result") + in + conv_with_guard to_list of_list + +let contents_and_result_list_encoding = + contents_and_result_conv_with_guard + (Variable.list contents_and_result_encoding) + +let contents_and_result_list_encoding_with_legacy_attestation_name = + contents_and_result_conv_with_guard + (Variable.list contents_and_result_encoding_with_legacy_attestation_name) + +type 'kind operation_metadata = {contents : 'kind contents_result_list} + +type packed_operation_metadata = + | Operation_metadata : 'kind operation_metadata -> packed_operation_metadata + | No_operation_metadata : packed_operation_metadata + +let operation_metadata_encoding = + def "operation.alpha.result" + @@ union + [ + case + (Tag 0) + ~title:"Operation_metadata" + contents_result_list_encoding + (function + | Operation_metadata {contents} -> + Some (Contents_result_list contents) + | _ -> None) + (fun (Contents_result_list contents) -> + Operation_metadata {contents}); + case + (Tag 1) + ~title:"No_operation_metadata" + empty + (function No_operation_metadata -> Some () | _ -> None) + (fun () -> No_operation_metadata); + ] + +let operation_metadata_encoding_with_legacy_attestation_name = + def "operation_with_legacy_attestation_name.alpha.result" + @@ union + [ + case + (Tag 0) + ~title:"Operation_metadata" + contents_result_list_encoding_with_legacy_attestation_name + (function + | Operation_metadata {contents} -> + Some (Contents_result_list contents) + | _ -> None) + (fun (Contents_result_list contents) -> + Operation_metadata {contents}); + case + (Tag 1) + ~title:"No_operation_metadata" + empty + (function No_operation_metadata -> Some () | _ -> None) + (fun () -> No_operation_metadata); + ] + +let kind_equal : + type kind kind2. + kind contents -> kind2 contents_result -> (kind, kind2) eq option = + fun op res -> + match (op, res) with + | Attestation _, Attestation_result _ -> Some Eq + | Attestation _, _ -> None + | Preattestation _, Preattestation_result _ -> Some Eq + | Preattestation _, _ -> None + | Seed_nonce_revelation _, Seed_nonce_revelation_result _ -> Some Eq + | Seed_nonce_revelation _, _ -> None + | Vdf_revelation _, Vdf_revelation_result _ -> Some Eq + | Vdf_revelation _, _ -> None + | Double_preattestation_evidence _, Double_preattestation_evidence_result _ -> + Some Eq + | Double_preattestation_evidence _, _ -> None + | Double_attestation_evidence _, Double_attestation_evidence_result _ -> + Some Eq + | Double_attestation_evidence _, _ -> None + | Double_baking_evidence _, Double_baking_evidence_result _ -> Some Eq + | Double_baking_evidence _, _ -> None + | Activate_account _, Activate_account_result _ -> Some Eq + | Activate_account _, _ -> None + | Proposals _, Proposals_result -> Some Eq + | Proposals _, _ -> None + | Ballot _, Ballot_result -> Some Eq + | Ballot _, _ -> None + | Drain_delegate _, Drain_delegate_result _ -> Some Eq + | Drain_delegate _, _ -> None + | Failing_noop _, _ -> + (* the Failing_noop operation always fails and can't have result *) + None + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result {operation_result = Applied (Reveal_result _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result + {operation_result = Backtracked (Reveal_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result + { + operation_result = Failed (Alpha_context.Kind.Reveal_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Reveal _; _}, + Manager_operation_result + {operation_result = Skipped Alpha_context.Kind.Reveal_manager_kind; _} ) + -> + Some Eq + | Manager_operation {operation = Reveal _; _}, _ -> None + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + {operation_result = Applied (Transaction_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + {operation_result = Backtracked (Transaction_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Transaction_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Transaction _; _}, + Manager_operation_result + { + operation_result = Skipped Alpha_context.Kind.Transaction_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Transaction _; _}, _ -> None + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + {operation_result = Applied (Origination_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + {operation_result = Backtracked (Origination_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Origination_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Origination _; _}, + Manager_operation_result + { + operation_result = Skipped Alpha_context.Kind.Origination_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Origination _; _}, _ -> None + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + {operation_result = Applied (Delegation_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + {operation_result = Backtracked (Delegation_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Delegation_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Delegation _; _}, + Manager_operation_result + { + operation_result = Skipped Alpha_context.Kind.Delegation_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Delegation _; _}, _ -> None + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + {operation_result = Applied (Update_consensus_key_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + {operation_result = Backtracked (Update_consensus_key_result _, _); _} ) + -> + Some Eq + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Update_consensus_key_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Update_consensus_key_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Update_consensus_key _; _}, _ -> None + | ( Manager_operation {operation = Register_global_constant _; _}, + Manager_operation_result + {operation_result = Applied (Register_global_constant_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Register_global_constant _; _}, + Manager_operation_result + { + operation_result = Backtracked (Register_global_constant_result _, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Register_global_constant _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Register_global_constant_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Register_global_constant _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Register_global_constant_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Register_global_constant _; _}, _ -> None + | ( Manager_operation {operation = Set_deposits_limit _; _}, + Manager_operation_result + {operation_result = Applied (Set_deposits_limit_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Set_deposits_limit _; _}, + Manager_operation_result + {operation_result = Backtracked (Set_deposits_limit_result _, _); _} ) + -> + Some Eq + | ( Manager_operation {operation = Set_deposits_limit _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Set_deposits_limit_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Set_deposits_limit _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Set_deposits_limit_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Set_deposits_limit _; _}, _ -> None + | ( Manager_operation {operation = Increase_paid_storage _; _}, + Manager_operation_result + {operation_result = Applied (Increase_paid_storage_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Increase_paid_storage _; _}, + Manager_operation_result + {operation_result = Backtracked (Increase_paid_storage_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Increase_paid_storage _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Increase_paid_storage_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Increase_paid_storage _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Increase_paid_storage_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Increase_paid_storage _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_recover_bond _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_recover_bond_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_recover_bond _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_recover_bond_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_recover_bond _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_recover_bond_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_recover_bond _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_recover_bond_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_recover_bond _; _}, _ -> None + | ( Manager_operation {operation = Transfer_ticket _; _}, + Manager_operation_result + {operation_result = Applied (Transfer_ticket_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Transfer_ticket _; _}, + Manager_operation_result + {operation_result = Backtracked (Transfer_ticket_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Transfer_ticket _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Transfer_ticket_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Transfer_ticket _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Transfer_ticket_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Transfer_ticket _; _}, _ -> None + | ( Manager_operation {operation = Dal_publish_commitment _; _}, + Manager_operation_result + {operation_result = Applied (Dal_publish_commitment_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Dal_publish_commitment _; _}, + Manager_operation_result + {operation_result = Backtracked (Dal_publish_commitment_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Dal_publish_commitment _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Dal_publish_commitment_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Dal_publish_commitment _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Dal_publish_commitment_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Dal_publish_commitment _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_originate _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_originate_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_originate _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_originate_result _, _); _} ) + -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_originate _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_originate_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_originate _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_originate_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_originate _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_add_messages _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_add_messages_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_add_messages _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_add_messages_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_add_messages _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_add_messages_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_add_messages _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_add_messages_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_add_messages _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_cement _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_cement_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_cement _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_cement_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_cement _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_cement_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_cement _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_cement_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_cement _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_publish _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_publish_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_publish _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_publish_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_publish _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_publish_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_publish _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_publish_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_publish _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_refute _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_refute_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_refute _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_refute_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_refute _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_refute_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_refute _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_refute_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_refute _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_timeout _; _}, + Manager_operation_result + {operation_result = Applied (Sc_rollup_timeout_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_timeout _; _}, + Manager_operation_result + {operation_result = Backtracked (Sc_rollup_timeout_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_timeout _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Sc_rollup_timeout_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_timeout _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Sc_rollup_timeout_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_timeout _; _}, _ -> None + | ( Manager_operation {operation = Sc_rollup_execute_outbox_message _; _}, + Manager_operation_result + { + operation_result = Applied (Sc_rollup_execute_outbox_message_result _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_execute_outbox_message _; _}, + Manager_operation_result + { + operation_result = + Backtracked (Sc_rollup_execute_outbox_message_result _, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_execute_outbox_message _; _}, + Manager_operation_result + { + operation_result = + Failed + ( Alpha_context.Kind.Sc_rollup_execute_outbox_message_manager_kind, + _ ); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Sc_rollup_execute_outbox_message _; _}, + Manager_operation_result + { + operation_result = + Skipped + Alpha_context.Kind.Sc_rollup_execute_outbox_message_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Sc_rollup_execute_outbox_message _; _}, _ -> + None + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + {operation_result = Applied (Zk_rollup_origination_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + {operation_result = Backtracked (Zk_rollup_origination_result _, _); _} + ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Zk_rollup_origination_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_origination _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Zk_rollup_origination_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Zk_rollup_origination _; _}, _ -> None + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + {operation_result = Applied (Zk_rollup_publish_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + {operation_result = Backtracked (Zk_rollup_publish_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Zk_rollup_publish_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_publish _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Zk_rollup_publish_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Zk_rollup_publish _; _}, _ -> None + | ( Manager_operation {operation = Zk_rollup_update _; _}, + Manager_operation_result + {operation_result = Applied (Zk_rollup_update_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_update _; _}, + Manager_operation_result + {operation_result = Backtracked (Zk_rollup_update_result _, _); _} ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_update _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Zk_rollup_update_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Zk_rollup_update _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Zk_rollup_update_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Zk_rollup_update _; _}, _ -> None + +let rec kind_equal_list : + type kind kind2. + kind contents_list -> kind2 contents_result_list -> (kind, kind2) eq option + = + fun contents res -> + match (contents, res) with + | Single op, Single_result res -> ( + match kind_equal op res with None -> None | Some Eq -> Some Eq) + | Cons (op, ops), Cons_result (res, ress) -> ( + match kind_equal op res with + | None -> None + | Some Eq -> ( + match kind_equal_list ops ress with + | None -> None + | Some Eq -> Some Eq)) + | _ -> None + +let rec pack_contents_list : + type kind. + kind contents_list -> + kind contents_result_list -> + kind contents_and_result_list = + fun contents res -> + match (contents, res) with + | Single op, Single_result res -> Single_and_result (op, res) + | Cons (op, ops), Cons_result (res, ress) -> + Cons_and_result (op, res, pack_contents_list ops ress) + | ( Single (Manager_operation _), + Cons_result (Manager_operation_result _, Single_result _) ) -> + . + | ( Cons (_, _), + Single_result (Manager_operation_result {operation_result = Failed _; _}) + ) -> + . + | ( Cons (_, _), + Single_result (Manager_operation_result {operation_result = Skipped _; _}) + ) -> + . + | ( Cons (_, _), + Single_result (Manager_operation_result {operation_result = Applied _; _}) + ) -> + . + | ( Cons (_, _), + Single_result + (Manager_operation_result {operation_result = Backtracked _; _}) ) -> + . + | Single _, Cons_result _ -> . + +let rec unpack_contents_list : + type kind. + kind contents_and_result_list -> + kind contents_list * kind contents_result_list = function + | Single_and_result (op, res) -> (Single op, Single_result res) + | Cons_and_result (op, res, rest) -> + let ops, ress = unpack_contents_list rest in + (Cons (op, ops), Cons_result (res, ress)) + +let rec to_list = function + | Contents_result_list (Single_result o) -> [Contents_result o] + | Contents_result_list (Cons_result (o, os)) -> + Contents_result o :: to_list (Contents_result_list os) + +let operation_data_and_metadata_encoding = + def "operation.alpha.operation_with_metadata" + @@ union + [ + case + (Tag 0) + ~title:"Operation_with_metadata" + (obj2 + (req "contents" (dynamic_size contents_and_result_list_encoding)) + (opt "signature" Signature.encoding)) + (function + | Operation_data _, No_operation_metadata -> None + | Operation_data op, Operation_metadata res -> ( + match kind_equal_list op.contents res.contents with + | None -> + Pervasives.failwith + "cannot decode inconsistent combined operation result" + | Some Eq -> + Some + ( Contents_and_result_list + (pack_contents_list op.contents res.contents), + op.signature ))) + (fun (Contents_and_result_list contents, signature) -> + let op_contents, res_contents = unpack_contents_list contents in + ( Operation_data {contents = op_contents; signature}, + Operation_metadata {contents = res_contents} )); + case + (Tag 1) + ~title:"Operation_without_metadata" + (obj2 + (req "contents" (dynamic_size Operation.contents_list_encoding)) + (opt "signature" Signature.encoding)) + (function + | Operation_data op, No_operation_metadata -> + Some (Contents_list op.contents, op.signature) + | Operation_data _, Operation_metadata _ -> None) + (fun (Contents_list contents, signature) -> + (Operation_data {contents; signature}, No_operation_metadata)); + ] + +let operation_data_and_metadata_encoding_with_legacy_attestation_name = + def "operation_with_legacy_attestation_name.alpha.operation_with_metadata" + @@ union + [ + case + (Tag 0) + ~title:"Operation_with_metadata" + (obj2 + (req + "contents" + (dynamic_size + contents_and_result_list_encoding_with_legacy_attestation_name)) + (opt "signature" Signature.encoding)) + (function + | Operation_data _, No_operation_metadata -> None + | Operation_data op, Operation_metadata res -> ( + match kind_equal_list op.contents res.contents with + | None -> + Pervasives.failwith + "cannot decode inconsistent combined operation result" + | Some Eq -> + Some + ( Contents_and_result_list + (pack_contents_list op.contents res.contents), + op.signature ))) + (fun (Contents_and_result_list contents, signature) -> + let op_contents, res_contents = unpack_contents_list contents in + ( Operation_data {contents = op_contents; signature}, + Operation_metadata {contents = res_contents} )); + case + (Tag 1) + ~title:"Operation_without_metadata" + (obj2 + (req + "contents" + (dynamic_size + Operation + .contents_list_encoding_with_legacy_attestation_name)) + (opt "signature" Signature.encoding)) + (function + | Operation_data op, No_operation_metadata -> + Some (Contents_list op.contents, op.signature) + | Operation_data _, Operation_metadata _ -> None) + (fun (Contents_list contents, signature) -> + (Operation_data {contents; signature}, No_operation_metadata)); + ] + +type block_metadata = { + proposer : Consensus_key.t; + baker : Consensus_key.t; + level_info : Level.t; + voting_period_info : Voting_period.info; + nonce_hash : Nonce_hash.t option; + consumed_gas : Gas.Arith.fp; + deactivated : Signature.Public_key_hash.t list; + balance_updates : Receipt.balance_updates; + liquidity_baking_toggle_ema : Per_block_votes.Liquidity_baking_toggle_EMA.t; + adaptive_issuance_vote_ema : Per_block_votes.Adaptive_issuance_launch_EMA.t; + adaptive_issuance_launch_cycle : Cycle.t option; + implicit_operations_results : packed_successful_manager_operation_result list; + dal_attestation : Dal.Attestation.t; +} + +let block_metadata_encoding ~use_legacy_attestation_name = + let open Data_encoding in + def + (if use_legacy_attestation_name then + "block_header.alpha.metadata_with_legacy_attestation_name" + else "block_header.alpha.metadata") + @@ conv + (fun { + proposer = + {delegate = proposer; consensus_pkh = proposer_active_key}; + baker = {delegate = baker; consensus_pkh = baker_active_key}; + level_info; + voting_period_info; + nonce_hash; + consumed_gas; + deactivated; + balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results; + dal_attestation; + } -> + ( ( proposer, + baker, + level_info, + voting_period_info, + nonce_hash, + deactivated, + balance_updates, + liquidity_baking_toggle_ema, + adaptive_issuance_vote_ema, + adaptive_issuance_launch_cycle ), + ( implicit_operations_results, + proposer_active_key, + baker_active_key, + consumed_gas, + dal_attestation ) )) + (fun ( ( proposer, + baker, + level_info, + voting_period_info, + nonce_hash, + deactivated, + balance_updates, + liquidity_baking_toggle_ema, + adaptive_issuance_vote_ema, + adaptive_issuance_launch_cycle ), + ( implicit_operations_results, + proposer_active_key, + baker_active_key, + consumed_gas, + dal_attestation ) ) -> + { + proposer = {delegate = proposer; consensus_pkh = proposer_active_key}; + baker = {delegate = baker; consensus_pkh = baker_active_key}; + level_info; + voting_period_info; + nonce_hash; + consumed_gas; + deactivated; + balance_updates; + liquidity_baking_toggle_ema; + adaptive_issuance_vote_ema; + adaptive_issuance_launch_cycle; + implicit_operations_results; + dal_attestation; + }) + (merge_objs + (obj10 + (req "proposer" Signature.Public_key_hash.encoding) + (req "baker" Signature.Public_key_hash.encoding) + (req "level_info" Level.encoding) + (req "voting_period_info" Voting_period.info_encoding) + (req "nonce_hash" (option Nonce_hash.encoding)) + (req "deactivated" (list Signature.Public_key_hash.encoding)) + (dft + "balance_updates" + (if use_legacy_attestation_name then + Receipt.balance_updates_encoding_with_legacy_attestation_name + else Receipt.balance_updates_encoding) + []) + (req + "liquidity_baking_toggle_ema" + Per_block_votes.Liquidity_baking_toggle_EMA.encoding) + (req + "adaptive_issuance_vote_ema" + Per_block_votes.Adaptive_issuance_launch_EMA.encoding) + (opt "adaptive_issuance_activation_cycle" Cycle.encoding)) + (obj5 + (req + "implicit_operations_results" + (list successful_manager_operation_result_encoding)) + (req "proposer_consensus_key" Signature.Public_key_hash.encoding) + (req "baker_consensus_key" Signature.Public_key_hash.encoding) + (req "consumed_milligas" Gas.Arith.n_fp_encoding) + (req "dal_attestation" Dal.Attestation.encoding))) + +let block_metadata_encoding_with_legacy_attestation_name = + block_metadata_encoding ~use_legacy_attestation_name:true + +let block_metadata_encoding = + block_metadata_encoding ~use_legacy_attestation_name:false diff --git a/src/proto_020_PsParisC/lib_protocol/apply_results.mli b/src/proto_020_PsParisC/lib_protocol/apply_results.mli new file mode 100644 index 000000000000..8c60ad0d6c20 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/apply_results.mli @@ -0,0 +1,359 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Types representing results of applying an operation. + + These are used internally by [Apply], and can be used for experimenting + with protocol updates, by clients to print out a summary of the + operation at pre-injection simulation and at confirmation time, + and by block explorers. + *) + +open Alpha_context +open Apply_operation_result +open Apply_internal_results + +(** Result of applying a {!Operation.t}. Follows the same structure. *) +type 'kind operation_metadata = {contents : 'kind contents_result_list} + +and packed_operation_metadata = + | Operation_metadata : 'kind operation_metadata -> packed_operation_metadata + | No_operation_metadata : packed_operation_metadata + +(** Result of applying a {!Operation.contents_list}. Follows the same structure. *) +and 'kind contents_result_list = + | Single_result : 'kind contents_result -> 'kind contents_result_list + | Cons_result : + 'kind Kind.manager contents_result + * 'rest Kind.manager contents_result_list + -> ('kind * 'rest) Kind.manager contents_result_list + +and packed_contents_result_list = + | Contents_result_list : + 'kind contents_result_list + -> packed_contents_result_list + +(** Result of applying an {!Operation.contents}. Follows the same structure. *) +and 'kind contents_result = + | Preattestation_result : { + balance_updates : Receipt.balance_updates; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + consensus_power : int; + } + -> Kind.preattestation contents_result + | Attestation_result : { + balance_updates : Receipt.balance_updates; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + consensus_power : int; + } + -> Kind.attestation contents_result + | Seed_nonce_revelation_result : + Receipt.balance_updates + -> Kind.seed_nonce_revelation contents_result + | Vdf_revelation_result : + Receipt.balance_updates + -> Kind.vdf_revelation contents_result + | Double_attestation_evidence_result : { + forbidden_delegate : Signature.public_key_hash option; + balance_updates : Receipt.balance_updates; + } + -> Kind.double_attestation_evidence contents_result + | Double_preattestation_evidence_result : { + forbidden_delegate : Signature.public_key_hash option; + balance_updates : Receipt.balance_updates; + } + -> Kind.double_preattestation_evidence contents_result + | Double_baking_evidence_result : { + forbidden_delegate : Signature.public_key_hash option; + balance_updates : Receipt.balance_updates; + } + -> Kind.double_baking_evidence contents_result + | Activate_account_result : + Receipt.balance_updates + -> Kind.activate_account contents_result + | Proposals_result : Kind.proposals contents_result + | Ballot_result : Kind.ballot contents_result + | Drain_delegate_result : { + balance_updates : Receipt.balance_updates; + allocated_destination_contract : bool; + } + -> Kind.drain_delegate contents_result + | Manager_operation_result : { + balance_updates : Receipt.balance_updates; + operation_result : 'kind manager_operation_result; + internal_operation_results : packed_internal_operation_result list; + } + -> 'kind Kind.manager contents_result + +and packed_contents_result = + | Contents_result : 'kind contents_result -> packed_contents_result + +and 'kind manager_operation_result = + ( 'kind, + 'kind Kind.manager, + 'kind successful_manager_operation_result ) + operation_result + +(** Result of applying a transaction. *) +and successful_transaction_result = + Apply_internal_results.successful_transaction_result + +(** Result of applying an origination. *) +and successful_origination_result = + Apply_internal_results.successful_origination_result + +(** Result of applying an external {!manager_operation_content}. *) +and _ successful_manager_operation_result = + | Reveal_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.reveal successful_manager_operation_result + | Transaction_result : + successful_transaction_result + -> Kind.transaction successful_manager_operation_result + | Origination_result : + successful_origination_result + -> Kind.origination successful_manager_operation_result + | Delegation_result : { + consumed_gas : Gas.Arith.fp; + balance_updates : Receipt.balance_updates; + } + -> Kind.delegation successful_manager_operation_result + | Register_global_constant_result : { + (* The manager submitting the operation must pay + the cost of storage for the registered value. + We include the balance update here. *) + balance_updates : Receipt.balance_updates; + (* Gas consumed while validating and storing the registered + value. *) + consumed_gas : Gas.Arith.fp; + (* The size of the registered value in bytes. + Currently, this is simply the number of bytes in the binary + serialization of the Micheline value. *) + size_of_constant : Z.t; + (* The address of the newly registered value, being + the hash of its binary serialization. This could be + calulated on demand but we include it here in the + receipt for flexibility in the future. *) + global_address : Script_expr_hash.t; + } + -> Kind.register_global_constant successful_manager_operation_result + | Set_deposits_limit_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.set_deposits_limit successful_manager_operation_result + | Increase_paid_storage_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + } + -> Kind.increase_paid_storage successful_manager_operation_result + | Update_consensus_key_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.update_consensus_key successful_manager_operation_result + | Transfer_ticket_result : { + balance_updates : Receipt.balance_updates; + ticket_receipt : Ticket_receipt.t; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.transfer_ticket successful_manager_operation_result + | Dal_publish_commitment_result : { + slot_header : Dal.Slot.Header.t; + consumed_gas : Gas.Arith.fp; + } + -> Kind.dal_publish_commitment successful_manager_operation_result + | Sc_rollup_originate_result : { + balance_updates : Receipt.balance_updates; + address : Sc_rollup.Address.t; + genesis_commitment_hash : Sc_rollup.Commitment.Hash.t; + consumed_gas : Gas.Arith.fp; + size : Z.t; + } + -> Kind.sc_rollup_originate successful_manager_operation_result + | Sc_rollup_add_messages_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.sc_rollup_add_messages successful_manager_operation_result + | Sc_rollup_cement_result : { + consumed_gas : Gas.Arith.fp; + inbox_level : Raw_level.t; + commitment_hash : Sc_rollup.Commitment.Hash.t; + } + -> Kind.sc_rollup_cement successful_manager_operation_result + | Sc_rollup_publish_result : { + consumed_gas : Gas.Arith.fp; + staked_hash : Sc_rollup.Commitment.Hash.t; + published_at_level : Raw_level.t; + balance_updates : Receipt.balance_updates; + } + -> Kind.sc_rollup_publish successful_manager_operation_result + | Sc_rollup_refute_result : { + consumed_gas : Gas.Arith.fp; + game_status : Sc_rollup.Game.status; + balance_updates : Receipt.balance_updates; + } + -> Kind.sc_rollup_refute successful_manager_operation_result + | Sc_rollup_timeout_result : { + consumed_gas : Gas.Arith.fp; + game_status : Sc_rollup.Game.status; + balance_updates : Receipt.balance_updates; + } + -> Kind.sc_rollup_timeout successful_manager_operation_result + | Sc_rollup_execute_outbox_message_result : { + balance_updates : Receipt.balance_updates; + ticket_receipt : Ticket_receipt.t; + whitelist_update : Sc_rollup.Whitelist.update option; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.sc_rollup_execute_outbox_message + successful_manager_operation_result + | Sc_rollup_recover_bond_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + } + -> Kind.sc_rollup_recover_bond successful_manager_operation_result + | Zk_rollup_origination_result : { + balance_updates : Receipt.balance_updates; + originated_zk_rollup : Zk_rollup.t; + consumed_gas : Gas.Arith.fp; + (* Number of bytes allocated by the ZKRU origination. + Used to burn storage fees. *) + storage_size : Z.t; + } + -> Kind.zk_rollup_origination successful_manager_operation_result + | Zk_rollup_publish_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.zk_rollup_publish successful_manager_operation_result + | Zk_rollup_update_result : { + balance_updates : Receipt.balance_updates; + consumed_gas : Gas.Arith.fp; + paid_storage_size_diff : Z.t; + } + -> Kind.zk_rollup_update successful_manager_operation_result + +and packed_successful_manager_operation_result = + | Successful_manager_result : + 'kind successful_manager_operation_result + -> packed_successful_manager_operation_result + +val pack_migration_operation_results : + Migration.origination_result list -> + packed_successful_manager_operation_result list + +(** Serializer for {!packed_operation_result}. *) +val operation_metadata_encoding : packed_operation_metadata Data_encoding.t + +(** Operation metadata encoding that accepts legacy attestation name : + `endorsement` (and preendorsement, double__evidence) in JSON + + https://gitlab.com/tezos/tezos/-/issues/5531 + + This encoding is temporary and should be removed when the protocol no longer + accepts JSON endorsements kinds +*) +val operation_metadata_encoding_with_legacy_attestation_name : + packed_operation_metadata Data_encoding.t + +val operation_data_and_metadata_encoding : + (Operation.packed_protocol_data * packed_operation_metadata) Data_encoding.t + +(** Operation data and metadata encoding that accepts legacy attestation name : + `endorsement` (and preendorsement, double__evidence) in JSON + + https://gitlab.com/tezos/tezos/-/issues/5531 + + This encoding is temporary and should be removed when the protocol no longer + accepts JSON endorsements kinds +*) +val operation_data_and_metadata_encoding_with_legacy_attestation_name : + (Operation.packed_protocol_data * packed_operation_metadata) Data_encoding.t + +type 'kind contents_and_result_list = + | Single_and_result : + 'kind Alpha_context.contents * 'kind contents_result + -> 'kind contents_and_result_list + | Cons_and_result : + 'kind Kind.manager Alpha_context.contents + * 'kind Kind.manager contents_result + * 'rest Kind.manager contents_and_result_list + -> ('kind * 'rest) Kind.manager contents_and_result_list + +type packed_contents_and_result_list = + | Contents_and_result_list : + 'kind contents_and_result_list + -> packed_contents_and_result_list + +val contents_and_result_list_encoding : + packed_contents_and_result_list Data_encoding.t + +val contents_and_result_list_encoding_with_legacy_attestation_name : + packed_contents_and_result_list Data_encoding.t + +val pack_contents_list : + 'kind contents_list -> + 'kind contents_result_list -> + 'kind contents_and_result_list + +val unpack_contents_list : + 'kind contents_and_result_list -> + 'kind contents_list * 'kind contents_result_list + +val to_list : packed_contents_result_list -> packed_contents_result list + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +val kind_equal_list : + 'kind contents_list -> + 'kind2 contents_result_list -> + ('kind, 'kind2) eq option + +type block_metadata = { + proposer : Consensus_key.t; + baker : Consensus_key.t; + level_info : Level.t; + voting_period_info : Voting_period.info; + nonce_hash : Nonce_hash.t option; + consumed_gas : Gas.Arith.fp; + deactivated : Signature.Public_key_hash.t list; + balance_updates : Receipt.balance_updates; + liquidity_baking_toggle_ema : Per_block_votes.Liquidity_baking_toggle_EMA.t; + adaptive_issuance_vote_ema : Per_block_votes.Adaptive_issuance_launch_EMA.t; + adaptive_issuance_launch_cycle : Cycle.t option; + implicit_operations_results : packed_successful_manager_operation_result list; + dal_attestation : Dal.Attestation.t; +} + +val block_metadata_encoding_with_legacy_attestation_name : + block_metadata Data_encoding.encoding + +val block_metadata_encoding : block_metadata Data_encoding.encoding diff --git a/src/proto_020_PsParisC/lib_protocol/baking.ml b/src/proto_020_PsParisC/lib_protocol/baking.ml new file mode 100644 index 000000000000..7cc21c60edc0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/baking.ml @@ -0,0 +1,152 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += + | (* `Permanent *) + Insufficient_attestation_power of { + attestation_power : int; + consensus_threshold : int; + } + +let () = + register_error_kind + `Permanent + ~id:"baking.insufficient_attestation_power" + ~title:"Insufficient attestation power" + ~description: + "The attestation power is insufficient to satisfy the consensus \ + threshold." + ~pp:(fun ppf (attestation_power, consensus_threshold) -> + Format.fprintf + ppf + "The attestation power (%d) is insufficient to satisfy the consensus \ + threshold (%d)." + attestation_power + consensus_threshold) + Data_encoding.( + obj2 (req "attestation_power" int31) (req "consensus_threshold" int31)) + (function + | Insufficient_attestation_power {attestation_power; consensus_threshold} + -> + Some (attestation_power, consensus_threshold) + | _ -> None) + (fun (attestation_power, consensus_threshold) -> + Insufficient_attestation_power {attestation_power; consensus_threshold}) + +let bonus_baking_reward ctxt ~attestation_power = + let open Result_syntax in + let consensus_threshold = Constants.consensus_threshold ctxt in + let* baking_reward_bonus_per_slot = + Delegate.Rewards.baking_reward_bonus_per_slot ctxt + in + let extra_attestation_power = attestation_power - consensus_threshold in + let* () = + error_when + Compare.Int.(extra_attestation_power < 0) + (Insufficient_attestation_power {attestation_power; consensus_threshold}) + in + Tez.(baking_reward_bonus_per_slot *? Int64.of_int extra_attestation_power) + +type ordered_slots = { + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + slots : Slot.t list; +} + +(* Slots returned by this function are assumed by consumers to be in increasing + order, hence the use of [Slot.Range.rev_fold_es]. *) +let attesting_rights (ctxt : t) level = + let consensus_committee_size = Constants.consensus_committee_size ctxt in + let open Lwt_result_syntax in + let*? slots = Slot.Range.create ~min:0 ~count:consensus_committee_size in + Slot.Range.rev_fold_es + (fun (ctxt, map) slot -> + let* ctxt, consensus_pk = Stake_distribution.slot_owner ctxt level slot in + let map = + Signature.Public_key_hash.Map.update + consensus_pk.delegate + (function + | None -> + Some + { + delegate = consensus_pk.delegate; + consensus_key = consensus_pk.consensus_pkh; + slots = [slot]; + } + | Some slots -> Some {slots with slots = slot :: slots.slots}) + map + in + return (ctxt, map)) + (ctxt, Signature.Public_key_hash.Map.empty) + slots + +let attesting_rights_by_first_slot ctxt level = + let open Lwt_result_syntax in + let*? slots = + Slot.Range.create ~min:0 ~count:(Constants.consensus_committee_size ctxt) + in + let number_of_shards = Dal.number_of_shards ctxt in + let* ctxt, (_, slots_map) = + Slot.Range.fold_es + (fun (ctxt, (delegates_map, slots_map)) slot -> + let+ ctxt, consensus_pk = + Stake_distribution.slot_owner ctxt level slot + in + let initial_slot, delegates_map = + match + Signature.Public_key_hash.Map.find + consensus_pk.delegate + delegates_map + with + | None -> + ( slot, + Signature.Public_key_hash.Map.add + consensus_pk.delegate + slot + delegates_map ) + | Some initial_slot -> (initial_slot, delegates_map) + in + (* [slots_map]'keys are the minimal slots of delegates because + we fold on slots in increasing order *) + let in_dal_committee = + if Compare.Int.(Slot.to_int slot < number_of_shards) then 1 else 0 + in + let slots_map = + Slot.Map.update + initial_slot + (function + | None -> Some (consensus_pk, 1, in_dal_committee) + | Some (consensus_pk, count, dal_count) -> + Some (consensus_pk, count + 1, dal_count + in_dal_committee)) + slots_map + in + (ctxt, (delegates_map, slots_map))) + (ctxt, (Signature.Public_key_hash.Map.empty, Slot.Map.empty)) + slots + in + return (ctxt, slots_map) diff --git a/src/proto_020_PsParisC/lib_protocol/baking.mli b/src/proto_020_PsParisC/lib_protocol/baking.mli new file mode 100644 index 000000000000..0aeabf4f5731 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/baking.mli @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += + | (* `Permanent *) + Insufficient_attestation_power of { + attestation_power : int; + consensus_threshold : int; + } + +type ordered_slots = private { + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + slots : Slot.t list; +} + +(** For a given level computes who has the right to include an attestation in + the next block. + + @return map from delegates with such rights to their attesting slots, in + increasing order. + + This function is only used by the 'validators' RPC. *) +val attesting_rights : + context -> + Level.t -> + (context * ordered_slots Signature.Public_key_hash.Map.t) tzresult Lwt.t + +(** Computes attesting rights for a given level. + + @return map from allocated first slots to their owner's public key, consensus + attesting power, and DAL attesting power. *) +val attesting_rights_by_first_slot : + context -> + Level.t -> + (context * (Consensus_key.pk * int * int) Slot.Map.t) tzresult Lwt.t + +(** Computes the bonus baking reward depending on the attestation power. *) +val bonus_baking_reward : context -> attestation_power:int -> Tez.t tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/bitset.ml b/src/proto_020_PsParisC/lib_protocol/bitset.ml new file mode 100644 index 000000000000..f0de602a497f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bitset.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Z.t + +type error += Invalid_position of int + +let encoding = Data_encoding.z + +let empty = Z.zero + +let mem field pos = + let open Result_syntax in + let* () = error_when Compare.Int.(pos < 0) (Invalid_position pos) in + return @@ Z.testbit field pos + +let add field pos = + let open Result_syntax in + let* () = error_when Compare.Int.(pos < 0) (Invalid_position pos) in + return @@ Z.logor field Z.(shift_left one pos) + +let from_list positions = List.fold_left_e add empty positions + +let fill ~length = + let open Result_syntax in + let* () = error_when Compare.Int.(length < 0) (Invalid_position length) in + return Z.(pred (shift_left one length)) + +let inter = Z.logand + +let diff b1 b2 = Z.logand b1 (Z.lognot b2) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"bitfield_invalid_position" + ~title:"Invalid bitfield’s position" + ~description:"Bitfields does not accept negative positions" + (obj1 (req "position" int31)) + (function Invalid_position i -> Some i | _ -> None) + (fun i -> Invalid_position i) + +let occupied_size_in_bits = Z.numbits + +let hamming_weight = Z.popcount + +let to_z z = z diff --git a/src/proto_020_PsParisC/lib_protocol/bitset.mli b/src/proto_020_PsParisC/lib_protocol/bitset.mli new file mode 100644 index 000000000000..0854f6d5ce90 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bitset.mli @@ -0,0 +1,77 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A bitset is a compact structure to store a set of integers. *) +type t + +type error += Invalid_position of int + +val encoding : t Data_encoding.t + +(** A bitset encoding the empty set. *) +val empty : t + +(** [mem field i] returns [true] iff [i] has been added in [field]. + + This functions returns [Invalid_input i] if [i] is negative. *) +val mem : t -> int -> bool tzresult + +(** [add field i] returns a new bitset which contains [i] in + addition to the previous integers of [field]. + + This functions returns [Invalid_input i] if [i] is negative. *) +val add : t -> int -> t tzresult + +(** [from_list positions] folds [add] over the [positions] starting from [empty]. + This function returns [Invalid_input i] if [i] is negative and appears in + [positions]. *) +val from_list : int list -> t tzresult + +(** [fill ~length] is equivalent to setting all bits for positions in + [0, length - 1] to [one]. i.e., to [from_list (0 -- size -1)] or to + [(2 ^ length) - 1]. But it's more efficient than folding on individual + positions to set them. + + The function returns [Invalid_position length] if [length] is negative. +*) +val fill : length:int -> t tzresult + +(** [inter set_l set_r] returns [set] which is result of the + intersection of [set_l] and [set_r]. *) +val inter : t -> t -> t + +(** [diff set_l set_r] returns a [set] containing fiels in [set_l] + that are not in [set_r]. *) +val diff : t -> t -> t + +(** [occupied_size_in_bits bitset] returns the current number of bits + occupied by the [bitset]. *) +val occupied_size_in_bits : t -> int + +(** [hamming_weight bitset] returns the Hamming weight of [bitset]. *) +val hamming_weight : t -> int + +(** [to_z t] Returns the sum of powers of two of the given bitset. *) +val to_z : t -> Z.t diff --git a/src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.ml b/src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.ml new file mode 100644 index 000000000000..005e8d3d365b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.ml @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module H = + Blake2B.Make + (Base58) + (struct + let name = "Blinded public key hash" + + let title = "A blinded public key hash" + + let b58check_prefix = "\001\002\049\223" + + let size = Some Ed25519.Public_key_hash.size + end) + +module Index : Storage_description.INDEX with type t = H.t = struct + include H + include Path_encoding.Make_hex (H) +end + +include H + +let () = Base58.check_encoded_prefix b58check_encoding "btz1" 37 + +let of_ed25519_pkh activation_code pkh = + hash_bytes ~key:activation_code [Ed25519.Public_key_hash.to_bytes pkh] + +type activation_code = bytes + +let activation_code_size = Ed25519.Public_key_hash.size + +let activation_code_encoding = + Data_encoding.Fixed.(bytes Hex) activation_code_size + +let activation_code_of_hex h = + if Compare.Int.(String.length h <> activation_code_size * 2) then None + else Hex.to_bytes (`Hex h) diff --git a/src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.mli b/src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.mli new file mode 100644 index 000000000000..9be85a79d08d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/blinded_public_key_hash.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module handles hashes of implicit contract addresses used for + commitments in the origin block. + + This module is needed because for legal reasons, when the blockchain is + activated, the btz1 addresses of participants to the fundraising are not + listed directly but instead their hashes are listed, together with their + balances. Thus, the listed accounts can be activated and credited in the + activation block. *) + +include S.HASH + +type activation_code + +val activation_code_encoding : activation_code Data_encoding.t + +val of_ed25519_pkh : activation_code -> Ed25519.Public_key_hash.t -> t + +val activation_code_of_hex : string -> activation_code option + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_020_PsParisC/lib_protocol/block_header_repr.ml b/src/proto_020_PsParisC/lib_protocol/block_header_repr.ml new file mode 100644 index 000000000000..c56f721baf29 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/block_header_repr.ml @@ -0,0 +1,431 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Block header *) + +type contents = { + payload_hash : Block_payload_hash.t; + payload_round : Round_repr.t; + seed_nonce_hash : Nonce_hash.t option; + proof_of_work_nonce : bytes; + per_block_votes : Per_block_votes_repr.per_block_votes; +} + +type protocol_data = {contents : contents; signature : Signature.t} + +type t = {shell : Block_header.shell_header; protocol_data : protocol_data} + +type block_header = t + +type raw = Block_header.t + +type shell_header = Block_header.shell_header + +let raw_encoding = Block_header.encoding + +let shell_header_encoding = Block_header.shell_header_encoding + +type block_watermark = Block_header of Chain_id.t + +let bytes_of_block_watermark = function + | Block_header chain_id -> + Bytes.cat (Bytes.of_string "\x11") (Chain_id.to_bytes chain_id) + +let to_watermark b = Signature.Custom (bytes_of_block_watermark b) + +let of_watermark = function + | Signature.Custom b -> + if Compare.Int.(Bytes.length b > 0) then + match Bytes.get b 0 with + | '\x11' -> + Option.map + (fun chain_id -> Block_header chain_id) + (Chain_id.of_bytes_opt (Bytes.sub b 1 (Bytes.length b - 1))) + | _ -> None + else None + | _ -> None + +let contents_encoding = + let open Data_encoding in + let json = + conv + (fun { + payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce; + per_block_votes = {liquidity_baking_vote; adaptive_issuance_vote}; + } -> + ( payload_hash, + payload_round, + proof_of_work_nonce, + seed_nonce_hash, + liquidity_baking_vote, + adaptive_issuance_vote )) + (fun ( payload_hash, + payload_round, + proof_of_work_nonce, + seed_nonce_hash, + liquidity_baking_vote, + adaptive_issuance_vote ) -> + { + payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce; + per_block_votes = {liquidity_baking_vote; adaptive_issuance_vote}; + }) + (obj6 + (req "payload_hash" Block_payload_hash.encoding) + (req "payload_round" Round_repr.encoding) + (req + "proof_of_work_nonce" + (Fixed.bytes Hex Constants_repr.proof_of_work_nonce_size)) + (opt "seed_nonce_hash" Nonce_hash.encoding) + (req + "liquidity_baking_toggle_vote" + Per_block_votes_repr.liquidity_baking_vote_encoding) + (req + "adaptive_issuance_vote" + Per_block_votes_repr.adaptive_issuance_vote_encoding)) + in + let binary = + conv + (fun { + payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce; + per_block_votes; + } -> + ( payload_hash, + payload_round, + proof_of_work_nonce, + seed_nonce_hash, + per_block_votes )) + (fun ( payload_hash, + payload_round, + proof_of_work_nonce, + seed_nonce_hash, + per_block_votes ) -> + { + payload_hash; + payload_round; + seed_nonce_hash; + proof_of_work_nonce; + per_block_votes; + }) + (obj5 + (req "payload_hash" Block_payload_hash.encoding) + (req "payload_round" Round_repr.encoding) + (req + "proof_of_work_nonce" + (Fixed.bytes Hex Constants_repr.proof_of_work_nonce_size)) + (opt "seed_nonce_hash" Nonce_hash.encoding) + (req "per_block_votes" Per_block_votes_repr.per_block_votes_encoding)) + in + def "block_header.alpha.unsigned_contents" @@ splitted ~binary ~json + +let protocol_data_encoding = + let open Data_encoding in + def "block_header.alpha.signed_contents" + @@ conv + (fun {contents; signature} -> (contents, signature)) + (fun (contents, signature) -> {contents; signature}) + (merge_objs + contents_encoding + (obj1 (req "signature" Signature.encoding))) + +let raw {shell; protocol_data} = + let protocol_data = + Data_encoding.Binary.to_bytes_exn protocol_data_encoding protocol_data + in + {Block_header.shell; protocol_data} + +let unsigned_encoding = + let open Data_encoding in + merge_objs Block_header.shell_header_encoding contents_encoding + +let encoding = + let open Data_encoding in + def "block_header.alpha.full_header" + @@ conv + (fun {shell; protocol_data} -> (shell, protocol_data)) + (fun (shell, protocol_data) -> {shell; protocol_data}) + (merge_objs Block_header.shell_header_encoding protocol_data_encoding) + +(** Constants *) + +let max_header_length = + let fake_level = Raw_level_repr.root in + let fake_round = Round_repr.zero in + let fake_fitness = + Fitness_repr.create_without_locked_round + ~level:fake_level + ~predecessor_round:fake_round + ~round:fake_round + in + let fake_shell = + { + Block_header.level = 0l; + proto_level = 0; + predecessor = Block_hash.zero; + timestamp = Time.of_seconds 0L; + validation_passes = 0; + operations_hash = Operation_list_list_hash.zero; + fitness = Fitness_repr.to_raw fake_fitness; + context = Context_hash.zero; + } + and fake_contents = + { + payload_hash = Block_payload_hash.zero; + payload_round = Round_repr.zero; + proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '0'; + seed_nonce_hash = Some Nonce_hash.zero; + per_block_votes = + { + liquidity_baking_vote = Per_block_vote_pass; + adaptive_issuance_vote = Per_block_vote_pass; + }; + } + in + Data_encoding.Binary.length + encoding + { + shell = fake_shell; + protocol_data = {contents = fake_contents; signature = Signature.zero}; + } + +(** Header parsing entry point *) + +let hash_raw = Block_header.hash + +let hash {shell; protocol_data} = + Block_header.hash + { + shell; + protocol_data = + Data_encoding.Binary.to_bytes_exn protocol_data_encoding protocol_data; + } + +type error += + | (* Permanent *) + Invalid_block_signature of + Block_hash.t * Signature.Public_key_hash.t + | (* Permanent *) Invalid_stamp + | (* Permanent *) + Invalid_payload_round of { + payload_round : Round_repr.t; + round : Round_repr.t; + } + | (* Permanent *) Invalid_commitment of {expected : bool} + | (* Permanent *) Wrong_timestamp of Time.t * Time.t + +let () = + register_error_kind + `Permanent + ~id:"block_header.invalid_block_signature" + ~title:"Invalid block signature" + ~description:"A block was not signed with the expected private key." + ~pp:(fun ppf (block, pkh) -> + Format.fprintf + ppf + "Invalid signature for block %a. Expected: %a." + Block_hash.pp_short + block + Signature.Public_key_hash.pp_short + pkh) + Data_encoding.( + obj2 + (req "block" Block_hash.encoding) + (req "expected" Signature.Public_key_hash.encoding)) + (function + | Invalid_block_signature (block, pkh) -> Some (block, pkh) | _ -> None) + (fun (block, pkh) -> Invalid_block_signature (block, pkh)) ; + register_error_kind + `Permanent + ~id:"block_header.invalid_stamp" + ~title:"Insufficient block proof-of-work stamp" + ~description:"The block's proof-of-work stamp is insufficient" + ~pp:(fun ppf () -> Format.fprintf ppf "Insufficient proof-of-work stamp") + Data_encoding.empty + (function Invalid_stamp -> Some () | _ -> None) + (fun () -> Invalid_stamp) ; + register_error_kind + `Permanent + ~id:"block_header.invalid_payload_round" + ~title:"Invalid payload round" + ~description:"The given payload round is invalid." + ~pp:(fun ppf (payload_round, round) -> + Format.fprintf + ppf + "The provided payload round (%a) is after the block round (%a)." + Round_repr.pp + payload_round + Round_repr.pp + round) + Data_encoding.( + obj2 + (req "payload_round" Round_repr.encoding) + (req "round" Round_repr.encoding)) + (function + | Invalid_payload_round {payload_round; round} -> + Some (payload_round, round) + | _ -> None) + (fun (payload_round, round) -> Invalid_payload_round {payload_round; round}) ; + register_error_kind + `Permanent + ~id:"block_header.invalid_commitment" + ~title:"Invalid commitment in block header" + ~description:"The block header has invalid commitment." + ~pp:(fun ppf expected -> + if expected then + Format.fprintf ppf "Missing seed's nonce commitment in block header." + else + Format.fprintf ppf "Unexpected seed's nonce commitment in block header.") + Data_encoding.(obj1 (req "expected" bool)) + (function Invalid_commitment {expected} -> Some expected | _ -> None) + (fun expected -> Invalid_commitment {expected}) ; + register_error_kind + `Permanent + ~id:"block_header.wrong_timestamp" + ~title:"Wrong timestamp" + ~description:"Block timestamp not the expected one." + ~pp:(fun ppf (block_ts, expected_ts) -> + Format.fprintf + ppf + "Wrong timestamp: block timestamp (%a) not the expected one (%a)" + Time.pp_hum + block_ts + Time.pp_hum + expected_ts) + Data_encoding.( + obj2 + (req "block_timestamp" Time.encoding) + (req "expected_timestamp" Time.encoding)) + (function Wrong_timestamp (t1, t2) -> Some (t1, t2) | _ -> None) + (fun (t1, t2) -> Wrong_timestamp (t1, t2)) + +let check_signature (block : t) (chain_id : Chain_id.t) + (key : Signature.Public_key.t) = + let open Result_syntax in + let check_signature key ({shell; protocol_data = {contents; signature}} : t) = + let unsigned_header = + Data_encoding.Binary.to_bytes_exn unsigned_encoding (shell, contents) + in + Signature.check + ~watermark:(to_watermark (Block_header chain_id)) + key + signature + unsigned_header + in + if check_signature key block then return_unit + else + tzfail (Invalid_block_signature (hash block, Signature.Public_key.hash key)) + +let check_payload_round ~round ~payload_round = + error_when + Round_repr.(payload_round > round) + (Invalid_payload_round {payload_round; round}) + +let check_timestamp round_durations ~timestamp ~round ~predecessor_timestamp + ~predecessor_round = + let open Result_syntax in + let* expected_timestamp = + Round_repr.timestamp_of_round + round_durations + ~predecessor_timestamp + ~predecessor_round + ~round + in + if Time_repr.(expected_timestamp = timestamp) then return_unit + else tzfail (Wrong_timestamp (timestamp, expected_timestamp)) + +module Proof_of_work = struct + let check_hash hash stamp_threshold = + let bytes = Block_hash.to_bytes hash in + let word = TzEndian.get_int64 bytes 0 in + Compare.Uint64.(word <= stamp_threshold) + + let check_header_proof_of_work_stamp shell contents stamp_threshold = + let hash = + hash {shell; protocol_data = {contents; signature = Signature.zero}} + in + check_hash hash stamp_threshold + + let check_proof_of_work_stamp ~proof_of_work_threshold block = + let open Result_syntax in + if + check_header_proof_of_work_stamp + block.shell + block.protocol_data.contents + proof_of_work_threshold + then return_unit + else tzfail Invalid_stamp +end + +let begin_validate_block_header ~(block_header : t) ~(chain_id : Chain_id.t) + ~(predecessor_timestamp : Time.t) ~(predecessor_round : Round_repr.t) + ~(fitness : Fitness_repr.t) ~(timestamp : Time.t) + ~(delegate_pk : Signature.Public_key.t) + ~(round_durations : Round_repr.Durations.t) + ~(proof_of_work_threshold : int64) ~(expected_commitment : bool) = + let open Result_syntax in + (* Level relationship between current node and the predecessor is + done by the shell. We know that level is predecessor level + 1. + The predecessor block hash is guaranteed by the shell to be the + one in the shell header. The operations are guaranteed to + correspond to the shell_header.operations_hash by the shell *) + let {payload_round; seed_nonce_hash; _} = + block_header.protocol_data.contents + in + let raw_level = block_header.shell.level in + let* () = + Proof_of_work.check_proof_of_work_stamp + ~proof_of_work_threshold + block_header + in + let* level = Raw_level_repr.of_int32 raw_level in + let* () = check_signature block_header chain_id delegate_pk in + let round = Fitness_repr.round fitness in + let* () = check_payload_round ~round ~payload_round in + let* () = + check_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round + ~timestamp + ~round + in + let* () = + Fitness_repr.check_except_locked_round fitness ~level ~predecessor_round + in + let has_commitment = + match seed_nonce_hash with None -> false | Some _ -> true + in + error_unless + Compare.Bool.(has_commitment = expected_commitment) + (Invalid_commitment {expected = expected_commitment}) diff --git a/src/proto_020_PsParisC/lib_protocol/block_header_repr.mli b/src/proto_020_PsParisC/lib_protocol/block_header_repr.mli new file mode 100644 index 000000000000..f3600db1e159 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/block_header_repr.mli @@ -0,0 +1,115 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Representation of block headers. *) + +type contents = { + payload_hash : Block_payload_hash.t; + payload_round : Round_repr.t; + seed_nonce_hash : Nonce_hash.t option; + proof_of_work_nonce : bytes; + per_block_votes : Per_block_votes_repr.per_block_votes; +} + +type protocol_data = {contents : contents; signature : Signature.t} + +type t = {shell : Block_header.shell_header; protocol_data : protocol_data} + +type block_header = t + +type raw = Block_header.t + +type shell_header = Block_header.shell_header + +val raw : block_header -> raw + +val encoding : block_header Data_encoding.encoding + +val raw_encoding : raw Data_encoding.t + +val contents_encoding : contents Data_encoding.t + +val unsigned_encoding : (Block_header.shell_header * contents) Data_encoding.t + +val protocol_data_encoding : protocol_data Data_encoding.encoding + +val shell_header_encoding : shell_header Data_encoding.encoding + +type block_watermark = Block_header of Chain_id.t + +val to_watermark : block_watermark -> Signature.watermark + +val of_watermark : Signature.watermark -> block_watermark option + +(** The maximum size of block headers in bytes *) +val max_header_length : int + +val hash : block_header -> Block_hash.t + +val hash_raw : raw -> Block_hash.t + +type error += (* Permanent *) Invalid_stamp + +(** Checks if the header that would be built from the given components + is valid for the given difficulty. The signature is not passed as + it is does not impact the proof-of-work stamp. The stamp is checked + on the hash of a block header whose signature has been + zeroed-out. *) +module Proof_of_work : sig + val check_hash : Block_hash.t -> int64 -> bool + + val check_header_proof_of_work_stamp : + shell_header -> contents -> int64 -> bool + + val check_proof_of_work_stamp : + proof_of_work_threshold:int64 -> block_header -> unit tzresult +end + +(** [check_timestamp ctxt timestamp round predecessor_timestamp + predecessor_round] verifies that the block's timestamp and round + are coherent with the predecessor block's timestamp and + round. Fails with an error if that is not the case. *) +val check_timestamp : + Round_repr.Durations.t -> + timestamp:Time.t -> + round:Round_repr.t -> + predecessor_timestamp:Time.t -> + predecessor_round:Round_repr.t -> + unit tzresult + +val check_signature : t -> Chain_id.t -> Signature.Public_key.t -> unit tzresult + +val begin_validate_block_header : + block_header:t -> + chain_id:Chain_id.t -> + predecessor_timestamp:Time.t -> + predecessor_round:Round_repr.t -> + fitness:Fitness_repr.t -> + timestamp:Time.t -> + delegate_pk:Signature.public_key -> + round_durations:Round_repr.Durations.t -> + proof_of_work_threshold:int64 -> + expected_commitment:bool -> + unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/block_payload_hash.ml b/src/proto_020_PsParisC/lib_protocol/block_payload_hash.ml new file mode 100644 index 000000000000..724dec25f8b1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/block_payload_hash.ml @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* 32 *) +let prefix = "\001\106\242" (* vh(52) *) + +include + Blake2B.Make + (Base58) + (struct + let name = "value_hash" + + let title = "Hash of a consensus value" + + let b58check_prefix = prefix + + let size = None + end) + +let () = Base58.check_encoded_prefix b58check_encoding "vh" 52 diff --git a/src/proto_020_PsParisC/lib_protocol/block_payload_hash.mli b/src/proto_020_PsParisC/lib_protocol/block_payload_hash.mli new file mode 100644 index 000000000000..90280546e53c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/block_payload_hash.mli @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A specialized Blake2B implementation for hashing block's payloads. *) + +include S.HASH diff --git a/src/proto_020_PsParisC/lib_protocol/block_payload_repr.ml b/src/proto_020_PsParisC/lib_protocol/block_payload_repr.ml new file mode 100644 index 000000000000..1765e1612958 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/block_payload_repr.ml @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Value on which validators try to reach a consensus. + + Consensus at a given level is reached on a sequence of operations. However, + to differentiate between two blocks having the same sequence of operations, + assuming that could ever happen (for instance, two empty blocks), we also + include the hash of the block that precedes the block where these operations + should be included. *) + +let hash ~predecessor_hash ~payload_round operations = + let operations_hash = Operation_list_hash.compute operations in + let open Data_encoding in + let predecessor = Binary.to_bytes_exn Block_hash.encoding predecessor_hash in + let round = Binary.to_bytes_exn Round_repr.encoding payload_round in + let operations_hash = + Binary.to_bytes_exn Operation_list_hash.encoding operations_hash + in + Block_payload_hash.hash_bytes [predecessor; round; operations_hash] diff --git a/src/proto_020_PsParisC/lib_protocol/block_payload_repr.mli b/src/proto_020_PsParisC/lib_protocol/block_payload_repr.mli new file mode 100644 index 000000000000..8f65862e6f55 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/block_payload_repr.mli @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Value on which validators try to reach a consensus. + + Consensus at a given level is reached on a sequence of operations. However, + to differentiate between two blocks having the same sequence of operations, + assuming that could ever happen (for instance, two empty blocks), we also + include the hash of the block that precedes the block where these operations + should be included. *) + +(** Create a payload hash from the predecessor block hash, the first + round at which the payload was proposed, and the hashes of + non-consensus operations. *) +val hash : + predecessor_hash:Block_hash.t -> + payload_round:Round_repr.t -> + Operation_list_hash.elt list -> + Block_payload_hash.t diff --git a/src/proto_020_PsParisC/lib_protocol/bond_id_repr.ml b/src/proto_020_PsParisC/lib_protocol/bond_id_repr.ml new file mode 100644 index 000000000000..82d9f444c9e7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bond_id_repr.ml @@ -0,0 +1,119 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Sc_rollup_bond_id of Sc_rollup_repr.t + +include Compare.Make (struct + type nonrec t = t + + let compare id1 id2 = + match (id1, id2) with + | Sc_rollup_bond_id id1, Sc_rollup_bond_id id2 -> + Sc_rollup_repr.Address.compare id1 id2 +end) + +let encoding = + let open Data_encoding in + let case = function + | Tag tag -> + (* The tag was used by old variant. It have been removed in + protocol proposal O, it can be unblocked in the future. *) + let to_tx_rollup_reserved_tag = 0 in + assert (Compare.Int.(tag <> to_tx_rollup_reserved_tag)) ; + case (Tag tag) + | _ as c -> case c + in + def "bond_id" + @@ union + [ + case + (Tag 1) + ~title:"Smart_rollup_bond_id" + (obj1 (req "smart_rollup" Sc_rollup_repr.encoding)) + (function Sc_rollup_bond_id id -> Some id) + (fun id -> Sc_rollup_bond_id id); + ] + +let pp ppf = function Sc_rollup_bond_id id -> Sc_rollup_repr.pp ppf id + +let destruct id = + (* String.starts_with from the stdlib 4.14, with [unsafe_get] replaced by + [get], comparators replaced by their versions in [Compare.*]. *) + let starts_with ~prefix s = + let open String in + let len_s = length s and len_pre = length prefix in + let rec aux i = + if Compare.Int.(i = len_pre) then true + else if Compare.Char.(get s i <> get prefix i) then false + else aux (i + 1) + in + Compare.Int.(len_s >= len_pre) && aux 0 + in + if starts_with ~prefix:Sc_rollup_repr.Address.prefix id then + match Sc_rollup_repr.Address.of_b58check_opt id with + | Some id -> Ok (Sc_rollup_bond_id id) + | None -> Error "Cannot parse smart rollup id" + else Error "Cannot parse rollup id" + +let construct = function + | Sc_rollup_bond_id id -> Sc_rollup_repr.Address.to_b58check id + +let rpc_arg = + RPC_arg.make + ~descr:"A bond identifier." + ~name:"bond_id" + ~construct + ~destruct + () + +module Internal_for_test = struct + let destruct = destruct + + let construct = construct +end + +module Index = struct + type nonrec t = t + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + Option.bind + (Hex.to_bytes (`Hex key)) + (Data_encoding.Binary.of_bytes_opt encoding) + | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_020_PsParisC/lib_protocol/bond_id_repr.mli b/src/proto_020_PsParisC/lib_protocol/bond_id_repr.mli new file mode 100644 index 000000000000..d5e963bbc8be --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bond_id_repr.mli @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines identifiers for frozen bonds. *) + +type t = Sc_rollup_bond_id of Sc_rollup_repr.t + +val pp : Format.formatter -> t -> unit + +val encoding : t Data_encoding.t + +include Compare.S with type t := t + +module Internal_for_test : sig + val destruct : string -> (t, string) result + + val construct : t -> string +end + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_020_PsParisC/lib_protocol/bootstrap_storage.ml b/src/proto_020_PsParisC/lib_protocol/bootstrap_storage.ml new file mode 100644 index 000000000000..e445b02b6d58 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bootstrap_storage.ml @@ -0,0 +1,257 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Unrevealed_public_key of Signature.Public_key_hash.t + +let () = + register_error_kind + `Permanent + ~id:"bootstrap.unrevealed_public_key" + ~title:"Forbidden delegation from unrevealed public key" + ~description:"Tried to delegate from an unrevealed public key" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegation from an unrevealed public key (for %a) is forbidden." + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegator" Signature.Public_key_hash.encoding)) + (function Unrevealed_public_key pkh -> Some pkh | _ -> None) + (fun pkh -> Unrevealed_public_key pkh) + +let init_account (ctxt, balance_updates) + ({public_key_hash; public_key; amount; delegate_to; consensus_key} : + Parameters_repr.bootstrap_account) = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit public_key_hash in + let* ctxt, new_balance_updates = + Token.transfer + ~origin:Protocol_migration + ctxt + `Bootstrap + (`Contract contract) + amount + in + let+ ctxt, freeze_balance_updates = + match public_key with + | Some public_key -> ( + let* ctxt = + Contract_manager_storage.reveal_manager_key + ctxt + public_key_hash + public_key + in + let* ctxt = + Delegate_storage.Contract.set + ctxt + contract + (Some (Option.value ~default:public_key_hash delegate_to)) + in + let* ctxt = + match consensus_key with + | None -> return ctxt + | Some consensus_key -> + Delegate_consensus_key.init ctxt public_key_hash consensus_key + in + match delegate_to with + | Some delegate + when Signature.Public_key_hash.(delegate <> public_key_hash) -> + return (ctxt, []) + | _ -> + (* Self-delegated => contract is a delegate. + Freeze the largest amount of tokens to avoid over-delegation + according to the [limit_of_delegation_over_baking]. + This is necessary so that the network (in tests too) starts with + accounts with baking rights. *) + let limit_of_delegation_over_baking = + Constants_storage.limit_of_delegation_over_baking ctxt + in + let amount_to_freeze = + let minimal_to_bake = + let minimal_stake = Constants_storage.minimal_stake ctxt in + let minimal_frozen_stake = + Constants_storage.minimal_frozen_stake ctxt + in + Tez_repr.max minimal_stake minimal_frozen_stake + in + let minimal_to_not_be_overdelegated = + Tez_repr.div_exn amount (limit_of_delegation_over_baking + 1) + in + Tez_repr.( + min amount (max minimal_to_bake minimal_to_not_be_overdelegated)) + in + Token.transfer + ~origin:Protocol_migration + ctxt + (`Contract contract) + (`Frozen_deposits (Frozen_staker_repr.baker public_key_hash)) + amount_to_freeze) + | None -> + let* () = + fail_when + (Option.is_some delegate_to) + (Unrevealed_public_key public_key_hash) + in + return (ctxt, []) + in + (ctxt, freeze_balance_updates @ new_balance_updates @ balance_updates) + +let init_contract ~typecheck_smart_contract (ctxt, balance_updates) + ({delegate; amount; script; hash} : Parameters_repr.bootstrap_contract) = + let open Lwt_result_syntax in + let*? ctxt, contract_hash = + match hash with + | None -> Contract_storage.fresh_contract_from_current_nonce ctxt + | Some hash -> Result.return (ctxt, hash) + in + let* script, ctxt = typecheck_smart_contract ctxt script in + let* ctxt = + Contract_storage.raw_originate + ctxt + ~prepaid_bootstrap_storage:true + contract_hash + ~script + in + let contract = Contract_repr.Originated contract_hash in + let* ctxt = + match delegate with + | None -> return ctxt + | Some delegate -> Delegate_storage.Contract.init ctxt contract delegate + in + let origin = Receipt_repr.Protocol_migration in + let+ ctxt, new_balance_updates = + Token.transfer ~origin ctxt `Bootstrap (`Contract contract) amount + in + (ctxt, new_balance_updates @ balance_updates) + +let init_smart_rollup ~typecheck_smart_rollup ctxt + ({address; boot_sector; pvm_kind; parameters_ty; whitelist} : + Parameters_repr.bootstrap_smart_rollup) = + let open Lwt_result_syntax in + let*? ctxt = + let open Result_syntax in + let* parameters_ty = Script_repr.force_decode parameters_ty in + typecheck_smart_rollup ctxt parameters_ty + in + let*! genesis_hash = Sc_rollups.genesis_state_hash_of pvm_kind ~boot_sector in + let genesis_commitment : Sc_rollup_commitment_repr.t = + { + compressed_state = genesis_hash; + (* Level 0: Genesis block. + Level 1: Block on protocol genesis, that only activates protocols. + Level 2: First block on the activated protocol. + + Therefore we originate the rollup at level 2 so the rollup node + doesn't ask a block on a different protocol. + *) + inbox_level = Raw_level_repr.of_int32_exn 2l; + predecessor = Sc_rollup_commitment_repr.Hash.zero; + number_of_ticks = Sc_rollup_repr.Number_of_ticks.zero; + } + in + let* _, _, ctxt = + Sc_rollup_storage.raw_originate + ctxt + ~kind:pvm_kind + ~genesis_commitment + ~parameters_ty + ~address + ?whitelist + in + return ctxt + +let init ctxt ~typecheck_smart_contract ~typecheck_smart_rollup + ?no_reward_cycles accounts contracts smart_rollups = + let open Lwt_result_syntax in + let nonce = Operation_hash.hash_string ["Un festival de GADT."] in + let ctxt = Raw_context.init_origination_nonce ctxt nonce in + let* ctxt, balance_updates = + List.fold_left_es init_account (ctxt, []) accounts + in + let* ctxt, balance_updates = + List.fold_left_es + (init_contract ~typecheck_smart_contract) + (ctxt, balance_updates) + contracts + in + let* ctxt = + List.fold_left_es + (init_smart_rollup ~typecheck_smart_rollup) + ctxt + smart_rollups + in + let+ ctxt = + match no_reward_cycles with + | None -> return ctxt + | Some cycles -> + (* Store pending ramp ups. *) + let constants = Raw_context.constants ctxt in + (* Start without rewards *) + let*! ctxt = + Raw_context.patch_constants ctxt (fun c -> + { + c with + issuance_weights = + { + c.issuance_weights with + base_total_issued_per_minute = Tez_repr.zero; + }; + }) + in + (* Store the final reward. *) + Storage.Ramp_up.( + Rewards.init + ctxt + (Cycle_repr.of_int32_exn (Int32.of_int cycles)) + { + (* Hack: we store the rewards here *) + baking_reward_fixed_portion = + constants.issuance_weights.base_total_issued_per_minute; + baking_reward_bonus_per_slot = Tez_repr.zero; + attesting_reward_per_slot = Tez_repr.zero; + }) + in + (ctxt, balance_updates) + +let cycle_end ctxt last_cycle = + let open Lwt_result_syntax in + let next_cycle = Cycle_repr.succ last_cycle in + let* result = Storage.Ramp_up.Rewards.find ctxt next_cycle in + match result with + | None -> return ctxt + | Some Storage.Ramp_up.{baking_reward_fixed_portion; _} -> + let* ctxt = Storage.Ramp_up.Rewards.remove_existing ctxt next_cycle in + let*! ctxt = + Raw_context.patch_constants ctxt (fun c -> + { + c with + issuance_weights = + { + c.issuance_weights with + base_total_issued_per_minute = baking_reward_fixed_portion; + }; + }) + in + return ctxt diff --git a/src/proto_020_PsParisC/lib_protocol/bootstrap_storage.mli b/src/proto_020_PsParisC/lib_protocol/bootstrap_storage.mli new file mode 100644 index 000000000000..01366550da57 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bootstrap_storage.mli @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides functions that can be used in a private network to + delay initial rewarding, typically when waiting for more bakers to join the + network. *) + +val init : + Raw_context.t -> + typecheck_smart_contract: + (Raw_context.t -> + Script_repr.t -> + ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) tzresult + Lwt.t) -> + typecheck_smart_rollup: + (Raw_context.t -> Script_repr.expr -> Raw_context.t tzresult) -> + ?no_reward_cycles:int -> + Parameters_repr.bootstrap_account list -> + Parameters_repr.bootstrap_contract list -> + Parameters_repr.bootstrap_smart_rollup list -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +val cycle_end : Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/bounded_history_repr.ml b/src/proto_020_PsParisC/lib_protocol/bounded_history_repr.ml new file mode 100644 index 000000000000..b32d1d6d9f80 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bounded_history_repr.ml @@ -0,0 +1,287 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type NAME = sig + val name : string +end + +module type KEY = sig + type t + + val compare : t -> t -> int + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t +end + +module type VALUE = sig + type t + + val equal : t -> t -> bool + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t +end + +module type S = sig + type t + + type key + + type value + + module Map : Map.S with type key = key + + type view = value Map.t + + val empty : capacity:int64 -> t + + val view : t -> view + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + val find : key -> t -> value option + + type error += + | Key_bound_to_different_value of { + key : key; + existing_value : value; + given_value : value; + } + + val remember : key -> value -> t -> t tzresult + + module Internal_for_tests : sig + val empty : capacity:int64 -> next_index:int64 -> t + + val keys : t -> key list + end +end + +module Make (Name : NAME) (Key : KEY) (Value : VALUE) : + S with type key = Key.t and type value = Value.t = struct + type key = Key.t + + type value = Value.t + + module Int64_map = Map.Make (Int64) + module Map = Map.Make (Key) + + type view = value Map.t + + type t = { + events : value Map.t; + (** Values stored in the structure, indexes with the keys. *) + sequence : key Int64_map.t; + (** An additional map from int64 indexes to keys, to be able + to remove old entries when the structure is full. *) + capacity : int64; + (** The max number of the entries in the structure. Once the maximum size + is reached, older entries are deleted to free space for new ones. *) + next_index : int64; + (** The index to use for the next entry to add in the structure. *) + oldest_index : int64; + (** The oldest index of the (oldest) entry that has been added to the + data structure. If the structure is empty, [oldest_index] is + equal to [next_index]. *) + size : int64; + (** Counts the number of entries that are stored in history. It + satisfies the invariant: `0 <= size <= capacity` *) + } + + let view t = t.events + + let encoding : t Data_encoding.t = + let open Data_encoding in + let events_encoding = + Data_encoding.conv + Map.bindings + (fun l -> Map.add_seq (List.to_seq l) Map.empty) + Data_encoding.(list (tup2 Key.encoding Value.encoding)) + in + let sequence_encoding = + conv + Int64_map.bindings + (List.fold_left (fun m (k, v) -> Int64_map.add k v m) Int64_map.empty) + (list (tup2 int64 Key.encoding)) + in + conv + (fun {events; sequence; capacity; next_index; oldest_index; size} -> + (events, sequence, capacity, next_index, oldest_index, size)) + (fun (events, sequence, capacity, next_index, oldest_index, size) -> + {events; sequence; capacity; next_index; oldest_index; size}) + (obj6 + (req "events" events_encoding) + (req "sequence" sequence_encoding) + (req "capacity" int64) + (req "next_index" int64) + (req "oldest_index" int64) + (req "size" int64)) + + let pp fmt {events; sequence; capacity; size; oldest_index; next_index} = + Map.bindings events |> fun bindings -> + Int64_map.bindings sequence |> fun sequence_bindings -> + let pp_binding fmt (hash, history_proof) = + Format.fprintf fmt "@[%a -> %a@;@]" Key.pp hash Value.pp history_proof + in + let pp_sequence_binding fmt (counter, hash) = + Format.fprintf fmt "@[%s -> %a@;@]" (Int64.to_string counter) Key.pp hash + in + Format.fprintf + fmt + "@[History:@;\ + \ { capacity: %Ld;@;\ + \ current size: %Ld;@;\ + \ oldest index: %Ld;@;\ + \ next_index : %Ld;@;\ + \ bindings: %a;@;\ + \ sequence: %a; }@]" + capacity + size + oldest_index + next_index + (Format.pp_print_list pp_binding) + bindings + (Format.pp_print_list pp_sequence_binding) + sequence_bindings + + let empty ~capacity = + let next_index = 0L in + { + events = Map.empty; + sequence = Int64_map.empty; + capacity; + next_index; + oldest_index = next_index; + size = 0L; + } + + type error += + | Key_bound_to_different_value of { + key : key; + existing_value : value; + given_value : value; + } + + let () = + assert (not (String.equal Name.name "")) ; + register_error_kind + `Temporary + ~id: + (Format.sprintf + "Bounded_history_repr.%s.key_bound_to_different_value" + Name.name) + ~title:(Name.name ^ ": Key already bound to a different value.") + ~description: + (Name.name + ^ ": Remember called with a key that is already bound to a different\n\ + \ value.") + Data_encoding.( + obj3 + (req "key" Key.encoding) + (req "existing_value" Value.encoding) + (req "given_value" Value.encoding)) + (function + | Key_bound_to_different_value {key; existing_value; given_value} -> + Some (key, existing_value, given_value) + | _ -> None) + (fun (key, existing_value, given_value) -> + Key_bound_to_different_value {key; existing_value; given_value}) + + let remember key value t = + let open Result_syntax in + if Compare.Int64.(t.capacity <= 0L) then return t + else + match Map.find key t.events with + | Some value' when not (Value.equal value value') -> + tzfail + @@ Key_bound_to_different_value + {key; existing_value = value'; given_value = value} + | _ -> ( + let events = Map.add key value t.events in + let current_index = t.next_index in + let next_index = Int64.succ current_index in + let t = + { + events; + sequence = Int64_map.add current_index key t.sequence; + capacity = t.capacity; + next_index; + oldest_index = t.oldest_index; + size = Int64.succ t.size; + } + in + (* A negative size means that [t.capacity] is set to [Int64.max_int] + and that the structure is full, so adding a new entry makes the size + overflows. In this case, we remove an element in the else branch to + keep the size of the structure equal to [Int64.max_int] at most. *) + if Compare.Int64.(t.size > 0L && t.size <= t.capacity) then return t + else + let l = t.oldest_index in + match Int64_map.find l t.sequence with + | None -> + (* If t.size > t.capacity > 0, there is necessarily + an entry whose index is t.oldest_index in [sequence]. *) + assert false + | Some h -> + let sequence = Int64_map.remove l t.sequence in + let events = Map.remove h events in + return + { + next_index = t.next_index; + capacity = t.capacity; + size = t.capacity; + oldest_index = Int64.succ t.oldest_index; + sequence; + events; + }) + + let find key t = Map.find_opt key t.events + + module Internal_for_tests = struct + let empty ~capacity ~next_index = + {(empty ~capacity) with next_index; oldest_index = next_index} + + let keys {sequence; oldest_index; _} = + let l = Int64_map.bindings sequence in + (* All entries with an index greater than oldest_index are well ordered. + There are put in the [lp] list. Entries with an index smaller than + oldest_index are also well ordered, but they should come after + elements in [lp]. This happens in theory when the index reaches + max_int and then overflows. *) + let ln, lp = + List.partition_map + (fun (n, h) -> + if Compare.Int64.(n < oldest_index) then Left h else Right h) + l + in + (* do a tail recursive concatenation lp @ ln *) + List.rev_append (List.rev lp) ln + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/bounded_history_repr.mli b/src/proto_020_PsParisC/lib_protocol/bounded_history_repr.mli new file mode 100644 index 000000000000..5da12bf3a3f5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/bounded_history_repr.mli @@ -0,0 +1,125 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A bounded cache associating values to keys. + +This data structure is basically a bounded association table that stores +(a finite number of) given [(key, value)], with the following properties: +{ul +{li The insertion ordering is remembered / important. When the structure is full, + older entries are removed to insert new ones;} +{li Stored keys are unique in the data-structure.} +} +*) + +module type NAME = sig + val name : string +end + +(** The required interface for keys stored in the table. *) +module type KEY = sig + type t + + val compare : t -> t -> int + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t +end + +(** The required interface for values stored in the table. *) +module type VALUE = sig + type t + + val equal : t -> t -> bool + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t +end + +(** The exported interface of the data structure. *) +module type S = sig + type t + + type key + + module Map : Map.S with type key = key + + type value + + type view = value Map.t + + (** [empty ~capacity] returns a new table whose maximum capacity is given. *) + val empty : capacity:int64 -> t + + (** Export a view of the given bounded cache *) + val view : t -> view + + (** Encoding for values of type {!t} *) + val encoding : t Data_encoding.t + + (** Pretty-printer for values of type {!t} *) + val pp : Format.formatter -> t -> unit + + (** [find key t] returns [Some value] if there exists some [value] associated + to [key] in the table, and [None] otherwise. *) + val find : key -> t -> value option + + type error += + | Key_bound_to_different_value of { + key : key; + existing_value : value; + given_value : value; + } + + (** [remember key value t] inserts a new entry [(key |-> value)] in [t]. + + If [key] already exists in [t], its associated binding [value'] should + be equal to [value]. In this case, [t] is returned unchanged. Otherwise, + an error [Key_bound_to_different_value] is returned. + + If [key] is not already present in [t], the new binding (key |-> value) is + inserted in [t]. If the number of elements would exceed [t]'s capacity + after the insertion of the new binding, the oldest binding is removed + from [t]. + + The structure [t] is returned unchanged if its [capacity] is negative or + null. + *) + val remember : key -> value -> t -> t tzresult + + module Internal_for_tests : sig + (** A more flexible [empty] function for testing purpose. *) + val empty : capacity:int64 -> next_index:int64 -> t + + (** [keys t] returns the keys of the entries stored in [t] in the order of + their insertion. *) + val keys : t -> key list + end +end + +module Make (Name : NAME) (Key : KEY) (Value : VALUE) : + S with type key = Key.t and type value = Value.t diff --git a/src/proto_020_PsParisC/lib_protocol/cache_memory_helpers.ml b/src/proto_020_PsParisC/lib_protocol/cache_memory_helpers.ml new file mode 100644 index 000000000000..8422a05590bd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cache_memory_helpers.ml @@ -0,0 +1,183 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type SNodes = sig + type t = private int + + val zero : t + + val one : t [@@ocaml.warning "-32"] + + val succ : t -> t + + val add : t -> t -> t + + val to_int : t -> int +end + +(** The [Nodes] module is used to count the number of computation steps + performed when evaluating the size of the in-memory graph corresponding + to an OCaml value. + + In first approximation, the value of type [Nodes.t] threaded through + {!expr_size} below and through the module {!Script_typed_ir_size} + is meant to match the number of recursive calls in the [traverse] + functions of {!Script_typed_ir} and in that of {!node_size}. + + The assumption is that there's a bounded amount of work performed between + two such recursive calls, hence that the total work is bounded above + by something proportional to the [Nodes.t] accumulator. + + Computations on values of type [Nodes.t] do not overflow, as they + are bounded above by the number of nodes traversed when computing + an OCaml value. + *) +module Nodes : SNodes = struct + type t = int + + let zero = 0 + + let one = 1 + + let succ x = x + 1 + + let add x y = x + y + + let to_int x = x +end + +(** {2 Helpers to deal with computing the in-memory size of values} *) + +type sint = Saturation_repr.may_saturate Saturation_repr.t + +type nodes_and_size = Nodes.t * sint + +let ( !! ) = Saturation_repr.safe_int + +let ( +! ) = Saturation_repr.add + +let ( +? ) s x = Saturation_repr.add s !!x + +let ( *? ) s x = Saturation_repr.mul s !!x + +let ( ++ ) (n1, s1) (n2, s2) = (Nodes.add n1 n2, s1 +! s2) + +let zero = (Nodes.zero, !!0) + +let word_size = !!8 + +let header_size = word_size + +let int32_size = header_size +! word_size + +let int64_size = header_size +! (word_size *? 2) + +let h1w = header_size +! word_size + +let h2w = header_size +! (word_size *? 2) + +let h3w = header_size +! (word_size *? 3) + +let h4w = header_size +! (word_size *? 4) + +let h5w = header_size +! (word_size *? 5) + +let hh3w = (word_size *? 3) +! (header_size *? 2) + +let hh6w = (word_size *? 6) +! (header_size *? 2) + +let hh8w = (word_size *? 8) +! (header_size *? 2) + +let z_size z = + let numbits = Z.numbits z in + (* + Z does not seem to have a canonical representation of numbers. + Hence, even though we observed that 24 works in many cases we + sometimes meet numbers with a larger size, hence we use 32 instead + of 24 in the following formula. + *) + if Compare.Int.(numbits <= 62) then !!0 else (word_size *? Z.size z) +? 32 + +let string_size_gen len = header_size +? (len + (8 - (len mod 8))) + +let bytes_size b = string_size_gen (Bytes.length b) + +let string_size s = string_size_gen (String.length s) + +let blake2b_hash_size = h1w +! string_size_gen 20 + +let public_key_hash_in_memory_size = h1w +! blake2b_hash_size + +let ret_adding (nodes, size) added = (nodes, size +! added) + +let ret_succ_adding (nodes, size) added = (Nodes.succ nodes, size +! added) + +let ret_succ (nodes, size) = (Nodes.succ nodes, size) + +let option_size some x = + let some x = h1w +! some x in + Option.fold ~none:!!0 ~some x + +let option_size_vec some x = + let some x = ret_adding (some x) h1w in + Option.fold ~none:zero ~some x + +let list_cell_size elt_size = header_size +! word_size +! word_size +! elt_size + [@@ocaml.inline always] + +let list_fold_size elt_size list = + List.fold_left + (fun accu elt -> ret_succ_adding (accu ++ elt_size elt) h2w) + zero + list + +let boxed_tup2 x y = header_size +! word_size +! word_size +! x +! y + [@@ocaml.inline always] + +let node_size = + let open Micheline in + (* An OCaml list item occupies 3 words of memory: one for the (::) + constructor, one for the item itself (head) and one for the + remainder of the list (tail). *) + let list_size sns = word_size *? (List.length sns * 3) in + let annotation_size a = + List.fold_left + (fun accu s -> ret_succ_adding accu (h2w +! string_size s)) + zero + a + in + let internal_node_size = function + | Int (_, z) -> (Nodes.one, h2w +! z_size z) + | String (_, s) -> (Nodes.one, h2w +! string_size s) + | Bytes (_, s) -> (Nodes.one, h2w +! bytes_size s) + | Prim (_, _, args, a) -> + ret_succ_adding (annotation_size a) (list_size args +! h4w) + | Seq (_, terms) -> (Nodes.one, list_size terms +! h2w) + in + fun node -> + Script_repr.fold node zero @@ fun accu node -> + accu ++ internal_node_size node + +let expr_size expr = node_size (Micheline.root expr) diff --git a/src/proto_020_PsParisC/lib_protocol/cache_repr.ml b/src/proto_020_PsParisC/lib_protocol/cache_repr.ml new file mode 100644 index 000000000000..1b05444ffa17 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cache_repr.ml @@ -0,0 +1,322 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Cache_costs = struct + (* Computed by typing the contract + "{parameter unit; storage unit; code FAILWITH}" + and evaluating + [(8 * Obj.reachable_words (Obj.repr typed_script))] + where [typed_script] is of type [ex_script] *) + let minimal_size_of_typed_contract_in_bytes = 688 + + let approximate_cardinal bytes = + bytes / minimal_size_of_typed_contract_in_bytes + + (* Cost of calling [Environment_cache.update]. *) + let cache_update ~cache_size_in_bytes = + let approx_card = approximate_cardinal cache_size_in_bytes in + Cache_repr_costs.cache_update_cost approx_card + + (* Cost of calling [Environment_cache.find]. + This overapproximates [cache_find] slightly. *) + let cache_find = cache_update +end + +type index = int + +type size = int + +type identifier = string + +type namespace = string + +type cache_nonce = Bytes.t + +let compare_namespace = Compare.String.compare + +type internal_identifier = {namespace : namespace; id : identifier} + +let separator = '@' + +let sanitize namespace = + if String.contains namespace separator then + invalid_arg + (Format.asprintf + "Invalid cache namespace: '%s'. Character %c is forbidden." + namespace + separator) + else namespace + +let create_namespace = sanitize + +let string_of_internal_identifier {namespace; id} = + namespace ^ String.make 1 separator ^ id + +let internal_identifier_of_string raw = + match String.index_opt raw separator with + | None -> assert false + | Some index -> + { + (* We do not need to call sanitize here since we stop at the first '@' + from index 0. It is a guarantee that there is no '@' between 0 and + (index - 1 ). *) + namespace = String.sub raw 0 index; + id = + (let delim_idx = index + 1 in + String.sub raw delim_idx (String.length raw - delim_idx)); + } + +let internal_identifier_of_key key = + let raw = Raw_context.Cache.identifier_of_key key in + internal_identifier_of_string raw + +let key_of_internal_identifier ~cache_index identifier = + let raw = string_of_internal_identifier identifier in + Raw_context.Cache.key_of_identifier ~cache_index raw + +let make_key = + let namespaces = ref [] in + fun ~cache_index ~namespace -> + if List.mem ~equal:String.equal namespace !namespaces then + invalid_arg + (Format.sprintf "Cache key namespace %s already exist." namespace) + else ( + namespaces := namespace :: !namespaces ; + fun ~id -> + let identifier = {namespace; id} in + key_of_internal_identifier ~cache_index identifier) + +module NamespaceMap = Map.Make (struct + type t = namespace + + let compare = compare_namespace +end) + +type partial_key_handler = + Raw_context.t -> string -> Context.Cache.value tzresult Lwt.t + +let value_of_key_handlers : partial_key_handler NamespaceMap.t ref = + ref NamespaceMap.empty + +module Admin = struct + include Raw_context.Cache + + let future_cache_expectation ?blocks_before_activation ctxt ~time_in_blocks = + let open Lwt_result_syntax in + let time_in_blocks' = Int32.of_int time_in_blocks in + let blocks_per_voting_period = + Int32.( + mul + (Constants_storage.cycles_per_voting_period ctxt) + (Constants_storage.blocks_per_cycle ctxt)) + in + let* block_opt = + match blocks_before_activation with + | None -> Voting_period_storage.blocks_before_activation ctxt + | Some block -> return_some block + in + match block_opt with + | Some block + when Compare.Int32.( + (Compare.Int32.(block >= 0l) && block <= time_in_blocks') + || blocks_per_voting_period < time_in_blocks') -> + (* + + At each protocol activation, the cache is clear. + + For this reason, if the future block considered for the + prediction is after the activation, the predicted cache + is set to empty. That way, the predicted gas consumption + is guaranteed to be an overapproximation of the actual + gas consumption. + + This function implicitly assumes that [time_in_blocks] + is less than [blocks_per_voting_period]. (The default + value in the simulate_operation RPC is set to 3, and + therefore satisfies this condition.) As a defensive + protection, we clear the cache if this assumption is + not satisfied with user-provided values. Notice that + high user-provided values for [time_in_blocks] do not + make much sense as the cache prediction only works for + blocks in the short-term future. + + *) + return @@ Raw_context.Cache.clear ctxt + | _ -> + return + @@ Raw_context.Cache.future_cache_expectation ctxt ~time_in_blocks + + let list_keys context ~cache_index = + Raw_context.Cache.list_keys context ~cache_index + + let key_rank context key = Raw_context.Cache.key_rank context key + + let value_of_key ctxt key = + (* [value_of_key] is a maintenance operation: it is typically run + when a node reboots. For this reason, this operation is not + carbonated. *) + let ctxt = Raw_context.set_gas_unlimited ctxt in + let {namespace; id} = internal_identifier_of_key key in + match NamespaceMap.find namespace !value_of_key_handlers with + | Some value_of_key -> value_of_key ctxt id + | None -> + failwith + (Format.sprintf "No handler for key `%s%c%s'" namespace separator id) +end + +module type CLIENT = sig + val cache_index : int + + val namespace : namespace + + type cached_value + + val value_of_identifier : + Raw_context.t -> identifier -> cached_value tzresult Lwt.t +end + +module type INTERFACE = sig + type cached_value + + val update : + Raw_context.t -> + identifier -> + (cached_value * int) option -> + Raw_context.t tzresult + + val find : Raw_context.t -> identifier -> cached_value option tzresult Lwt.t + + val list_identifiers : Raw_context.t -> (identifier * int) list + + val identifier_rank : Raw_context.t -> identifier -> int option + + val size : Raw_context.t -> size + + val size_limit : Raw_context.t -> size +end + +let register_exn (type cvalue) + (module C : CLIENT with type cached_value = cvalue) : + (module INTERFACE with type cached_value = cvalue) = + let open Lwt_result_syntax in + if + Compare.Int.(C.cache_index < 0) + || Compare.Int.(Constants_repr.cache_layout_size <= C.cache_index) + then invalid_arg "Cache index is invalid" ; + let mk = make_key ~cache_index:C.cache_index ~namespace:C.namespace in + (module struct + type cached_value = C.cached_value + + type Admin.value += K of cached_value + + let () = + let voi ctxt i = + let* v = C.value_of_identifier ctxt i in + return (K v) + in + value_of_key_handlers := + NamespaceMap.add C.namespace voi !value_of_key_handlers + + let size ctxt = + Option.value ~default:max_int + @@ Admin.cache_size ctxt ~cache_index:C.cache_index + + let size_limit ctxt = + Option.value ~default:0 + @@ Admin.cache_size_limit ctxt ~cache_index:C.cache_index + + let update ctxt id v = + let open Result_syntax in + let cache_size_in_bytes = size ctxt in + let+ ctxt = + Raw_context.consume_gas + ctxt + (Cache_costs.cache_update ~cache_size_in_bytes) + in + let v = Option.map (fun (v, size) -> (K v, size)) v in + Admin.update ctxt (mk ~id) v + + let find ctxt id = + let cache_size_in_bytes = size ctxt in + let*? ctxt = + Raw_context.consume_gas + ctxt + (Cache_costs.cache_find ~cache_size_in_bytes) + in + let*! value_opt = Admin.find ctxt (mk ~id) in + match value_opt with + | None -> return_none + | Some (K v) -> return_some v + | _ -> + (* This execution path is impossible because all the keys of + C's namespace (which is unique to C) are constructed with + [K]. This [assert false] could have been pushed into the + environment in exchange for extra complexity. The + argument that justifies this [assert false] seems + simple enough to keep the current design though. *) + assert false + + let list_identifiers ctxt = + Admin.list_keys ctxt ~cache_index:C.cache_index |> function + | None -> + (* `cache_index` is valid. *) + assert false + | Some list -> + List.filter_map + (fun (key, age) -> + let {namespace; id} = internal_identifier_of_key key in + if String.equal namespace C.namespace then Some (id, age) + else None) + list + + let identifier_rank ctxt id = Admin.key_rank ctxt (mk ~id) + end) + +let cache_nonce_from_block_header (shell : Block_header.shell_header) contents : + cache_nonce = + let open Block_header_repr in + let shell : Block_header.shell_header = + { + level = 0l; + proto_level = 0; + predecessor = shell.predecessor; + timestamp = Time.of_seconds 0L; + validation_passes = 0; + operations_hash = shell.operations_hash; + fitness = []; + context = Context_hash.zero; + } + in + let contents = + { + contents with + payload_hash = Block_payload_hash.zero; + proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '0'; + } + in + let protocol_data = {signature = Signature.zero; contents} in + let x = {shell; protocol_data} in + Block_hash.to_bytes (hash x) diff --git a/src/proto_020_PsParisC/lib_protocol/cache_repr.mli b/src/proto_020_PsParisC/lib_protocol/cache_repr.mli new file mode 100644 index 000000000000..2d026d423601 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cache_repr.mli @@ -0,0 +1,244 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + + Frequently used data should be kept in memory and persisted along a + chain of blocks. The caching mechanism allows the economic protocol + to declare such data and to rely on a Least Recently Used strategy + to keep the cache size under a fixed limit. + + Take a look at {!Environment_cache} and {!Environment_context} + for additional implementation details about the protocol cache. + + The protocol has two main kinds of interaction with the cache: + + 1. It is responsible for setting up the cache with appropriate + parameter values and callbacks. It must also compute cache nonces + to give the shell enough information to properly synchronize the + in-memory cache with the block contexts and protocol upgrades. + A typical place where this happens is {!Apply}. + This aspect must be implemented using {!Cache.Admin}. + + 2. It can exploit the cache to retrieve, to insert, and to update + cached values from the in-memory cache. The basic idea is to + avoid recomputing values from scratch at each block when they are + frequently used. {!Script_cache} is an example of such usage. + This aspect must be implemented using {!Cache.Interface}. + + *) + +(** Size for subcaches and values of the cache. *) +type size = int + +(** Index type to index caches. *) +type index = int + +(** Type used to identifies the block that introduced new cache + entries *) +type cache_nonce + +(** + + The following module acts on the whole cache, not on a specific + sub-cache, unlike {!Interface}. It is used to administrate the + protocol cache, e.g., to maintain the cache in a consistent state + with respect to the chain. This module is typically used by + low-level layers of the protocol and by the shell. + +*) +module Admin : sig + (** A key uniquely identifies a cached [value] in some subcache. *) + type key + + (** Cached values. *) + type value + + (** [pp fmt ctxt] is a pretty printer for the [cache] of [ctxt]. *) + val pp : Format.formatter -> Raw_context.t -> unit + + (** [sync ctxt cache_nonce] updates the context with the domain of + the cache computed so far. Such function is expected to be called + at the end of the validation of a block, when there is no more + accesses to the cache. + + [cache_nonce] identifies the block that introduced new cache + entries. The nonce should identify uniquely the block which + modifies this value. It cannot be the block hash for circularity + reasons: The value of the nonce is stored onto the context and + consequently influences the context hash of the very same + block. Such nonce cannot be determined by the shell and its + computation is delegated to the economic protocol. *) + val sync : Raw_context.t -> cache_nonce -> Raw_context.t Lwt.t + + (** {3 Cache helpers for RPCs} *) + + (** [future_cache_expectation ?blocks_before_activation ctxt + ~time_in_blocks] returns [ctxt] except that the entries of the + caches that are presumably too old to still be in the caches in + [n_blocks] are removed. + + This function is based on a heuristic. The context maintains the + median of the number of removed entries: this number is multiplied + by `n_blocks` to determine the entries that are likely to be + removed in `n_blocks`. + + If [blocks_before_activation] is set to [Some n], + then the cache is considered empty if [0 <= n <= time_in_blocks]. + Otherwise, if [blocks_before_activation] is set to [None] and + if the voting period is the adoption, the cache is considered + empty if [blocks <= time_in_blocks remaining for adoption phase]. *) + val future_cache_expectation : + ?blocks_before_activation:int32 -> + Raw_context.t -> + time_in_blocks:int -> + Raw_context.t tzresult Lwt.t + + (** [cache_size ctxt ~cache_index] returns an overapproximation of + the size of the cache. Returns [None] if [cache_index] is + greater than the number of subcaches declared by the cache + layout. *) + val cache_size : Raw_context.t -> cache_index:int -> size option + + (** [cache_size_limit ctxt ~cache_index] returns the maximal size of + the cache indexed by [cache_index]. Returns [None] if + [cache_index] is greater than the number of subcaches declared + by the cache layout. *) + val cache_size_limit : Raw_context.t -> cache_index:int -> size option + + (** [value_of_key ctxt k] interprets the functions introduced by + [register] to construct a cacheable value for a key [k]. + + [value_of_key] is a maintenance operation: it is typically run + when a node reboots. For this reason, this operation is not + carbonated. *) + val value_of_key : + Raw_context.t -> Context.Cache.key -> Context.Cache.value tzresult Lwt.t +end + +(** A client uses a unique namespace (represented as a string + without '@') to avoid collision with the keys of other + clients. *) +type namespace = private string + +(** [create_namespace str] creates a valid namespace from [str] + + @raise Invalid_argument if [str] contains '@' + *) +val create_namespace : string -> namespace + +(** A key is fully determined by a namespace and an identifier. *) +type identifier = string + +(** + To use the cache, a client must implement the [CLIENT] + interface. + + *) +module type CLIENT = sig + (** The type of value to be stored in the cache. *) + type cached_value + + (** The client must declare the index of the subcache where its + values shall live. [cache_index] must be between [0] and + [List.length Constants_repr.cache_layout - 1]. *) + val cache_index : index + + (** The client must declare a namespace. This namespace must + be unique. Otherwise, the program stops. + A namespace cannot contain '@'. *) + val namespace : namespace + + (** [value_of_identifier id] builds the cached value identified by + [id]. This function is called when the subcache is loaded into + memory from the on-disk representation of its domain. + + An error during the execution of this function is fatal as + witnessed by its type: an error embedded in a [tzresult] is not + supposed to be caught by the protocol. *) + val value_of_identifier : + Raw_context.t -> identifier -> cached_value tzresult Lwt.t +end + +(** + + An [INTERFACE] to the subcache where keys live in a given [namespace]. + + *) +module type INTERFACE = sig + (** The type of value to be stored in the cache. *) + type cached_value + + (** [update ctxt i (Some (e, size))] returns a context where the + value [e] of given [size] is associated to identifier [i] in + the subcache. If [i] is already in the subcache, the cache + entry is updated. + + [update ctxt i None] removes [i] from the subcache. *) + val update : + Raw_context.t -> + identifier -> + (cached_value * size) option -> + Raw_context.t tzresult + + (** [find ctxt i = Some v] if [v] is the value associated to [i] + in the subcache. Returns [None] if there is no such value in + the subcache. This function is in the Lwt monad because if the + value may have not been constructed (see the lazy loading + mode in {!Environment_context}), it is constructed on the fly. *) + val find : Raw_context.t -> identifier -> cached_value option tzresult Lwt.t + + (** [list_identifiers ctxt] returns the list of the + identifiers of the cached values along with their respective + size. The returned list is sorted in terms of their age in the + cache, the oldest coming first. *) + val list_identifiers : Raw_context.t -> (string * int) list + + (** [identifier_rank ctxt identifier] returns the number of cached values + older than the one of [identifier]; or, [None] if the [identifier] has + no associated value in the subcache. *) + val identifier_rank : Raw_context.t -> string -> int option + + (** [size ctxt] returns an overapproximation of the subcache size. + Note that the size unit is subcache specific. *) + val size : Raw_context.t -> int + + (** [size_limit ctxt] returns the maximal size of the subcache. + Note that the size unit is subcache specific. *) + val size_limit : Raw_context.t -> int +end + +(** [register_exn client] produces an [Interface] specific to a + given [client]. This function can fail if [client] does not + respect the invariant declared in the documentation of + {!CLIENT}. *) +val register_exn : + (module CLIENT with type cached_value = 'a) -> + (module INTERFACE with type cached_value = 'a) + +(** [cache_nonce_from_block_header shell_header contents] computes a + {!cache_nonce} from the [shell_header] and its [contents]. *) +val cache_nonce_from_block_header : + Block_header_repr.shell_header -> Block_header_repr.contents -> cache_nonce diff --git a/src/proto_020_PsParisC/lib_protocol/cache_repr_costs.ml b/src/proto_020_PsParisC/lib_protocol/cache_repr_costs.ml new file mode 100644 index 000000000000..c65b65ddc7f0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cache_repr_costs.ml @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Cache_repr_costs_generated + +let cache_update_cost size = + cost_CACHE_UPDATE size |> Gas_limit_repr.atomic_step_cost diff --git a/src/proto_020_PsParisC/lib_protocol/cache_repr_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/cache_repr_costs_generated.ml new file mode 100644 index 000000000000..f2c3e5d9c88c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cache_repr_costs_generated.ml @@ -0,0 +1,16 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model cache/CACHE_UPDATE *) +(* fun size -> max 10 (600. + (43. * (log2 (1 + size)))) *) +let cost_CACHE_UPDATE size = + let size = S.safe_int size in + (log2 (size + S.safe_int 1) * S.safe_int 43) + S.safe_int 600 diff --git a/src/proto_020_PsParisC/lib_protocol/carbonated_map.ml b/src/proto_020_PsParisC/lib_protocol/carbonated_map.ml new file mode 100644 index 000000000000..966a3650366e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/carbonated_map.ml @@ -0,0 +1,244 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type S = sig + type 'a t + + type key + + type context + + val empty : 'a t + + val singleton : key -> 'a -> 'a t + + val size : 'a t -> int + + val find : context -> key -> 'a t -> ('a option * context) tzresult + + val update : + context -> + key -> + (context -> 'a option -> ('a option * context) tzresult) -> + 'a t -> + ('a t * context) tzresult + + val to_list : context -> 'a t -> ((key * 'a) list * context) tzresult + + val of_list : + context -> + merge_overlap:(context -> 'a -> 'a -> ('a * context) tzresult) -> + (key * 'a) list -> + ('a t * context) tzresult + + val merge : + context -> + merge_overlap:(context -> 'a -> 'a -> ('a * context) tzresult) -> + 'a t -> + 'a t -> + ('a t * context) tzresult + + val map_e : + context -> + (context -> key -> 'a -> ('b * context) tzresult) -> + 'a t -> + ('b t * context) tzresult + + val fold_e : + context -> + (context -> 'state -> key -> 'value -> ('state * context) tzresult) -> + 'state -> + 'value t -> + ('state * context) tzresult + + val fold_es : + context -> + (context -> 'state -> key -> 'value -> ('state * context) tzresult Lwt.t) -> + 'state -> + 'value t -> + ('state * context) tzresult Lwt.t +end + +module type GAS = sig + type context + + val consume : + context -> + Saturation_repr.may_saturate Saturation_repr.t -> + context tzresult +end + +module type COMPARABLE = sig + include Compare.COMPARABLE + + (** [compare_cost k] returns the cost of comparing the given key [k] with + another value of the same type. *) + val compare_cost : t -> Saturation_repr.may_saturate Saturation_repr.t +end + +module Make_builder (C : COMPARABLE) = struct + module M = Map.Make (C) + + type 'a t = {map : 'a M.t; size : int} + + module Make (G : GAS) : + S with type key = C.t and type context = G.context and type 'a t := 'a t = + struct + type key = C.t + + type context = G.context + + let empty = {map = M.empty; size = 0} + + let singleton key value = {map = M.singleton key value; size = 1} + + let size {size; _} = size + + let find_cost ~key ~size = + Carbonated_map_costs.find_cost + ~compare_key_cost:(C.compare_cost key) + ~size + + let update_cost ~key ~size = + Carbonated_map_costs.update_cost + ~compare_key_cost:(C.compare_cost key) + ~size + + let find ctxt key {map; size} = + let open Result_syntax in + let+ ctxt = G.consume ctxt (find_cost ~key ~size) in + (M.find key map, ctxt) + + let update ctxt key f {map; size} = + let open Result_syntax in + let find_cost = find_cost ~key ~size in + let update_cost = update_cost ~key ~size in + (* Consume gas for looking up the old value *) + let* ctxt = G.consume ctxt find_cost in + let old_val_opt = M.find key map in + (* The call to [f] must also account for gas *) + let* new_val_opt, ctxt = f ctxt old_val_opt in + match (old_val_opt, new_val_opt) with + | Some _, Some new_val -> + (* Consume gas for adding to the map *) + let+ ctxt = G.consume ctxt update_cost in + ({map = M.add key new_val map; size}, ctxt) + | Some _, None -> + (* Consume gas for removing from the map *) + let+ ctxt = G.consume ctxt update_cost in + ({map = M.remove key map; size = size - 1}, ctxt) + | None, Some new_val -> + (* Consume gas for adding to the map *) + let+ ctxt = G.consume ctxt update_cost in + ({map = M.add key new_val map; size = size + 1}, ctxt) + | None, None -> return ({map; size}, ctxt) + + let to_list ctxt {map; size} = + let open Result_syntax in + let+ ctxt = G.consume ctxt (Carbonated_map_costs.fold_cost ~size) in + (M.bindings map, ctxt) + + let add ctxt ~merge_overlap key value {map; size} = + let open Result_syntax in + (* Consume gas for looking up the element *) + let* ctxt = G.consume ctxt (find_cost ~key ~size) in + (* Consume gas for adding the element *) + let* ctxt = G.consume ctxt (update_cost ~key ~size) in + match M.find key map with + | Some old_val -> + (* Invoking [merge_overlap] must also account for gas *) + let+ new_value, ctxt = merge_overlap ctxt old_val value in + ({map = M.add key new_value map; size}, ctxt) + | None -> Ok ({map = M.add key value map; size = size + 1}, ctxt) + + let add_key_values_to_map ctxt ~merge_overlap map key_values = + let accum (map, ctxt) (key, value) = + add ctxt ~merge_overlap key value map + in + (* Gas is paid at each step of the fold. *) + List.fold_left_e accum (map, ctxt) key_values + + let of_list ctxt ~merge_overlap = + add_key_values_to_map ctxt ~merge_overlap empty + + let merge ctxt ~merge_overlap map1 {map; size} = + let open Result_syntax in + (* To be on the safe side, pay an upfront gas cost for traversing the + map. Each step of the fold is accounted for separately. + *) + let* ctxt = G.consume ctxt (Carbonated_map_costs.fold_cost ~size) in + M.fold_e + (fun key value (map, ctxt) -> add ctxt ~merge_overlap key value map) + map + (map1, ctxt) + + let fold_e ctxt f empty {map; size} = + let open Result_syntax in + let* ctxt = G.consume ctxt (Carbonated_map_costs.fold_cost ~size) in + M.fold_e + (fun key value (acc, ctxt) -> + (* Invoking [f] must also account for gas. *) + f ctxt acc key value) + map + (empty, ctxt) + + let fold_es ctxt f empty {map; size} = + let open Lwt_result_syntax in + let*? ctxt = G.consume ctxt (Carbonated_map_costs.fold_cost ~size) in + M.fold_es + (fun key value (acc, ctxt) -> + (* Invoking [f] must also account for gas. *) + f ctxt acc key value) + map + (empty, ctxt) + + let map_e ctxt f {map; size} = + let open Result_syntax in + (* We cannot use the standard map function because [f] also meters the gas + cost at each invocation. *) + let+ map, ctxt = + fold_e + ctxt + (fun ctxt map key value -> + (* Invoking [f] must also account for gas. *) + let* value, ctxt = f ctxt key value in + (* Consume gas for adding the element. *) + let+ ctxt = G.consume ctxt (update_cost ~key ~size) in + (M.add key value map, ctxt)) + M.empty + {map; size} + in + ({map; size}, ctxt) + end +end + +module Make (G : GAS) (C : COMPARABLE) : + S with type key = C.t and type context = G.context = struct + module M = Make_builder (C) + + type 'a t = 'a M.t + + include M.Make (G) +end diff --git a/src/proto_020_PsParisC/lib_protocol/carbonated_map.mli b/src/proto_020_PsParisC/lib_protocol/carbonated_map.mli new file mode 100644 index 000000000000..745a74514b7b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/carbonated_map.mli @@ -0,0 +1,167 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** An in-memory data-structure for a key-value map where all operations + account for gas costs. + *) + +module type S = sig + type 'a t + + (** The type of keys in the map. *) + type key + + (** The type used for the context. *) + type context + + (** [empty] an empty map. *) + val empty : 'a t + + (** [singleton k v] returns a map with a single key [k] and value [v] pair. *) + val singleton : key -> 'a -> 'a t + + (** [size m] returns the number of elements of the map [m] in constant time. *) + val size : 'a t -> int + + (** [find ctxt k m] looks up the value with key [k] in the given map [m] and + also consumes the gas associated with the lookup. The complexity is + logarithmic in the size of the map. *) + val find : context -> key -> 'a t -> ('a option * context) tzresult + + (** [update ctxt k f map] updates or adds the value of the key [k] using [f]. + The function accounts for the gas cost for finding the element. The updating + function [f] should also account for its own gas cost. The complexity is + logarithmic in the size of the map. *) + val update : + context -> + key -> + (context -> 'a option -> ('a option * context) tzresult) -> + 'a t -> + ('a t * context) tzresult + + (** [to_list m] transforms a map [m] into a list. It also accounts for the + gas cost for traversing the elements. The complexity is linear in the size + of the map. *) + val to_list : context -> 'a t -> ((key * 'a) list * context) tzresult + + (** [of_list ctxt ~merge_overlaps m] creates a map from a list of key-value + pairs. In case there are overlapping keys, their values are combined + using the [merge_overlap] function. The function accounts for gas for + traversing the elements. [merge_overlap] should account for its own gas + cost. The complexity is [n * log n] in the size of the list. + *) + val of_list : + context -> + merge_overlap:(context -> 'a -> 'a -> ('a * context) tzresult) -> + (key * 'a) list -> + ('a t * context) tzresult + + (** [merge ctxt ~merge_overlap m1 m2] merges the maps [m1] and [m2]. In case + there are overlapping keys, their values are combined using the + [merge_overlap] function. Gas costs for traversing all elements from both + maps are accounted for. [merge_overlap] should account for its own gas + cost. The complexity is [n * log n], where [n] + is [size m1 + size m2]. *) + val merge : + context -> + merge_overlap:(context -> 'a -> 'a -> ('a * context) tzresult) -> + 'a t -> + 'a t -> + ('a t * context) tzresult + + (** [map_e ctxt f m] maps over all key-value pairs in the map [m] using the + function [f]. It accounts for gas costs associated with traversing the + elements. The mapping function [f] should also account for its own gas + cost. The complexity is linear in the size of the map [m]. *) + val map_e : + context -> + (context -> key -> 'a -> ('b * context) tzresult) -> + 'a t -> + ('b t * context) tzresult + + (** [fold_e ctxt f z m] folds over the key-value pairs of the given map [m], + accumulating values using [f], with [z] as the initial state. The function + [f] must account for its own gas cost. The complexity is linear in the + size of the map [m]. *) + val fold_e : + context -> + (context -> 'state -> key -> 'value -> ('state * context) tzresult) -> + 'state -> + 'value t -> + ('state * context) tzresult + + (** Lwt-aware variant of {!fold_e}. *) + val fold_es : + context -> + (context -> 'state -> key -> 'value -> ('state * context) tzresult Lwt.t) -> + 'state -> + 'value t -> + ('state * context) tzresult Lwt.t +end + +(** This module is used to provide the function for consuming gas when + constructing carbonated maps. *) +module type GAS = sig + (* The context type. *) + type context + + (** [consume ctxt cost] returns a context where [cost] has been consumed. *) + val consume : + context -> + Saturation_repr.may_saturate Saturation_repr.t -> + context tzresult +end + +(** Standard [Compare.COMPARE] extended with a [compare_cost] function + specifying the cost for comparing values. *) +module type COMPARABLE = sig + include Compare.COMPARABLE + + (** [compare_cost k] returns the cost of comparing the given key [k] with + another value of the same type. *) + val compare_cost : t -> Saturation_repr.may_saturate Saturation_repr.t +end + +(** A functor for exposing the type of a carbonated map before + the carbonated make is created. This is useful in scenarios where + the map that will need to be carbonated is defined before the + gas consuming functions for the carbonation are available. + See for example [Raw_context]. +*) +module Make_builder (C : COMPARABLE) : sig + type 'a t + + module Make (G : GAS) : + S with type key = C.t and type context = G.context and type 'a t := 'a t +end + +(** A functor for building gas metered maps. When building a gas metered map via + [Make(G)(C)], [C] is a [COMPARABLE] required to construct a the map while + [G] is a module providing the gas consuming functions. The type of the + context on which the gas consuming function operates is + determined by [G.context]. +*) +module Make (G : GAS) (C : COMPARABLE) : + S with type key = C.t and type context = G.context diff --git a/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.ml b/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.ml new file mode 100644 index 000000000000..e92b5c968d77 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Carbonated_map_costs_generated +open S.Syntax + +type cost = Saturation_repr.may_saturate Saturation_repr.t + +(** Collect benchmark from [Carbonated_map_benchmarks.Find_benchmark]. + + The model is similar to the gas model as from [Michelson_v1_gas.map_get]. + The user is responsible for providing the [compare_key_cost] which depends + on the size of the [key]. See [Carbonated_map_benchmarks.Find_benchmark] for + an example. + The rational for the model is: + - [intercept] is for paying a fixed cost regardless of size. + - [compare_key_cost] is for the log2 of steps comparing keys + - [traversal_overhead] is for the overhead of log2 steps walking the tree + *) +let find_cost ~compare_key_cost ~size = + (* intercept: carbonated_map/find/intercept *) + let intercept = cost_find_intercept in + let size = S.safe_int size in + let compare_cost = log2 size * compare_key_cost in + (* traversal_overhead: carbonated_map/find/traversal_overhead *) + let traversal_overhead = log2 size * S.safe_int 2 in + intercept + compare_cost + traversal_overhead + +(** + Modelling the precise overhead of update compared with [find] is tricky. + The cost of [find] depends on the cost of comparing keys. When the tree + is recreated, after looking up the element, this cost is no longer a factor. + On the other hand, if the old map is no longer used, some nodes are going to + be garbage collected at a later stage which incurs an extra cost. + + We here use the same model as in [Michelson_v1_gas.map_update]. That is + providing an overestimate by doubling the cost of [find]. + *) +let update_cost ~compare_key_cost ~size = + S.safe_int 2 * find_cost ~compare_key_cost ~size + +(** Collect benchmark from [Carbonated_map_benchmarks.Fold_benchmark]. + + The cost of producing a list of elements is linear in the size of the map + and does not depend on the size of the elements nor keys. +*) +let fold_cost ~size = cost_fold size diff --git a/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.mli b/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.mli new file mode 100644 index 000000000000..c40a26465e8d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs.mli @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The type of the cost.*) +type cost = Saturation_repr.may_saturate Saturation_repr.t + +(** The [Carbonated_map_costs] module contains gas cost functions for + [Carbonated_map]. + *) + +(** [find_cost ~compare_key_cost ~size] returns the gas cost for looking up an + element from a map of size [size]. The user of this function is responsible + for providing a correct value of [compare_key_cost], representing the cost + of comparing elements with a given key. + *) +val find_cost : compare_key_cost:cost -> size:int -> cost + +(** [update_cost ~compare_key_cost ~size] returns the gas cost for updating an + element in a map of size [size]. The user of this function is responsible + for providing a correct value of [compare_key_cost], representing the cost + of comparing elements with a given key. *) +val update_cost : compare_key_cost:cost -> size:int -> cost + +(** [fold_cost ~size] returns the cost of folding over a list of size [size]. *) +val fold_cost : size:int -> cost diff --git a/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs_generated.ml new file mode 100644 index 000000000000..b81dfd903696 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/carbonated_map_costs_generated.ml @@ -0,0 +1,32 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model carbonated_map/compare_int *) +(* max 10 2.18333333333 *) +let cost_compare_int = S.safe_int 10 + +(* model carbonated_map/find *) +(* fun size -> + max 10 ((50. + ((log2 size) * 2.18333333333)) + ((log2 size) * 2.)) *) +let cost_find size = + let size = S.safe_int size in + let w1 = log2 size in + (w1 * S.safe_int 4) + (w1 lsr 3) + (w1 lsr 4) + S.safe_int 50 + +(* model carbonated_map/find_intercept *) +(* max 10 50. *) +let cost_find_intercept = S.safe_int 50 + +(* model carbonated_map/fold *) +(* fun size -> max 10 (50. + (24. * size)) *) +let cost_fold size = + let size = S.safe_int size in + (size * S.safe_int 24) + S.safe_int 50 diff --git a/src/proto_020_PsParisC/lib_protocol/commitment_repr.ml b/src/proto_020_PsParisC/lib_protocol/commitment_repr.ml new file mode 100644 index 000000000000..38f114120c35 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/commitment_repr.ml @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + blinded_public_key_hash : Blinded_public_key_hash.t; + amount : Tez_repr.t; +} + +let encoding = + let open Data_encoding in + conv + (fun {blinded_public_key_hash; amount} -> (blinded_public_key_hash, amount)) + (fun (blinded_public_key_hash, amount) -> {blinded_public_key_hash; amount}) + (tup2 Blinded_public_key_hash.encoding Tez_repr.encoding) diff --git a/src/proto_020_PsParisC/lib_protocol/commitment_repr.mli b/src/proto_020_PsParisC/lib_protocol/commitment_repr.mli new file mode 100644 index 000000000000..e9a5d5db3103 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/commitment_repr.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This type represents a commitment to an amount of tokens which can be claimed + by a fund raiser after the blockchain is deployed. *) +type t = { + blinded_public_key_hash : Blinded_public_key_hash.t; + amount : Tez_repr.t; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/commitment_storage.ml b/src/proto_020_PsParisC/lib_protocol/commitment_storage.ml new file mode 100644 index 000000000000..390411e55530 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/commitment_storage.ml @@ -0,0 +1,53 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let exists = Storage.Commitments.mem + +let committed_amount ctxt bpkh = + let open Lwt_result_syntax in + let+ balance = Storage.Commitments.find ctxt bpkh in + Option.value ~default:Tez_repr.zero balance + +let increase_commitment_only_call_from_token ctxt bpkh amount = + let open Lwt_result_syntax in + if Tez_repr.(amount = zero) then return ctxt + else + let* balance = committed_amount ctxt bpkh in + let*? new_balance = Tez_repr.(amount +? balance) in + let*! result = Storage.Commitments.add ctxt bpkh new_balance in + return result + +let decrease_commitment_only_call_from_token ctxt bpkh amount = + let open Lwt_result_syntax in + let* balance = committed_amount ctxt bpkh in + let*? new_balance = Tez_repr.(balance -? amount) in + let*! result = + if Tez_repr.(new_balance = Tez_repr.zero) then + Storage.Commitments.remove ctxt bpkh + else Storage.Commitments.add ctxt bpkh new_balance + in + return result + +let fold c = Storage.Commitments.fold c diff --git a/src/proto_020_PsParisC/lib_protocol/commitment_storage.mli b/src/proto_020_PsParisC/lib_protocol/commitment_storage.mli new file mode 100644 index 000000000000..9a1d7126e881 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/commitment_storage.mli @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [exists ctxt bpkh] returns true iff [bpkh] is associated to a non null + commitment. *) +val exists : Raw_context.t -> Blinded_public_key_hash.t -> bool Lwt.t + +(** [committed_amount ctxt bpkh] return the commitment associated to [bpkh], or + [Tez_repr.zero] if [bpkh] has no associated commitment. *) +val committed_amount : + Raw_context.t -> Blinded_public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +val increase_commitment_only_call_from_token : + Raw_context.t -> + Blinded_public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val decrease_commitment_only_call_from_token : + Raw_context.t -> + Blinded_public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val fold : + Raw_context.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Blinded_public_key_hash.t -> Tez_repr.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml new file mode 100644 index 000000000000..96b257e4cd1d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml @@ -0,0 +1,650 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type dal = { + feature_enable : bool; + number_of_slots : int; + attestation_lag : int; + attestation_threshold : int; + blocks_per_epoch : int32; + cryptobox_parameters : Dal.parameters; +} + +let dal_encoding = + let open Data_encoding in + conv + (fun { + feature_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + blocks_per_epoch; + } -> + ( ( feature_enable, + number_of_slots, + attestation_lag, + attestation_threshold, + blocks_per_epoch ), + cryptobox_parameters )) + (fun ( ( feature_enable, + number_of_slots, + attestation_lag, + attestation_threshold, + blocks_per_epoch ), + cryptobox_parameters ) -> + { + feature_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + blocks_per_epoch; + cryptobox_parameters; + }) + (merge_objs + (obj5 + (req "feature_enable" bool) + (req "number_of_slots" int16) + (req "attestation_lag" int16) + (req "attestation_threshold" int16) + (req "blocks_per_epoch" int32)) + Dal.parameters_encoding) + +(* The encoded representation of this type is stored in the context as + bytes. Changing the encoding, or the value of these constants from + the previous protocol may break the context migration, or (even + worse) yield an incorrect context after migration. + + If you change this encoding compared to `Constants_parametric_previous_repr.t`, + you should ensure that there is a proper migration of the constants + during context migration. See: `Raw_context.prepare_first_block` *) + +type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level_repr.t} + +type sc_rollup_reveal_activation_level = { + raw_data : sc_rollup_reveal_hashing_schemes; + metadata : Raw_level_repr.t; + dal_page : Raw_level_repr.t; + dal_parameters : Raw_level_repr.t; +} + +let sc_rollup_reveal_hashing_schemes_encoding = + let open Data_encoding in + conv + (fun t -> t.blake2B) + (fun blake2B -> {blake2B}) + (obj1 (req "Blake2B" Raw_level_repr.encoding)) + +let sc_rollup_reveal_activation_level_encoding : + sc_rollup_reveal_activation_level Data_encoding.t = + let open Data_encoding in + conv + (fun t -> (t.raw_data, t.metadata, t.dal_page, t.dal_parameters)) + (fun (raw_data, metadata, dal_page, dal_parameters) -> + {raw_data; metadata; dal_page; dal_parameters}) + (obj4 + (req "raw_data" sc_rollup_reveal_hashing_schemes_encoding) + (req "metadata" Raw_level_repr.encoding) + (req "dal_page" Raw_level_repr.encoding) + (req "dal_parameters" Raw_level_repr.encoding)) + +type sc_rollup = { + arith_pvm_enable : bool; + origination_size : int; + challenge_window_in_blocks : int; + stake_amount : Tez_repr.t; + commitment_period_in_blocks : int; + max_lookahead_in_blocks : int32; + max_active_outbox_levels : int32; + max_outbox_messages_per_level : int; + number_of_sections_in_dissection : int; + timeout_period_in_blocks : int; + max_number_of_stored_cemented_commitments : int; + max_number_of_parallel_games : int; + reveal_activation_level : sc_rollup_reveal_activation_level; + private_enable : bool; + riscv_pvm_enable : bool; +} + +type zk_rollup = { + enable : bool; + origination_size : int; + min_pending_to_process : int; + max_ticket_payload_size : int; +} + +type adaptive_rewards_params = { + issuance_ratio_min : Q.t; + issuance_ratio_max : Q.t; + max_bonus : Issuance_bonus_repr.max_bonus; + growth_rate : Q.t; + center_dz : Q.t; + radius_dz : Q.t; +} + +type adaptive_issuance = { + global_limit_of_staking_over_baking : int; + edge_of_staking_over_delegation : int; + launch_ema_threshold : int32; + adaptive_rewards_params : adaptive_rewards_params; + activation_vote_enable : bool; + autostaking_enable : bool; +} + +type issuance_weights = { + base_total_issued_per_minute : Tez_repr.t; + baking_reward_fixed_portion_weight : int; + baking_reward_bonus_weight : int; + attesting_reward_weight : int; + liquidity_baking_subsidy_weight : int; + seed_nonce_revelation_tip_weight : int; + vdf_revelation_tip_weight : int; +} + +type t = { + preserved_cycles : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + nonce_revelation_threshold : int32; + blocks_per_stake_snapshot : int32; + cycles_per_voting_period : int32; + hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; + hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; + proof_of_work_threshold : int64; + minimal_stake : Tez_repr.t; + minimal_frozen_stake : Tez_repr.t; + vdf_difficulty : int64; + origination_size : int; + issuance_weights : issuance_weights; + cost_per_byte : Tez_repr.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + quorum_max : int32; + min_proposal_quorum : int32; + liquidity_baking_toggle_ema_threshold : int32; + max_operations_time_to_live : int; + minimal_block_delay : Period_repr.t; + delay_increment_per_round : Period_repr.t; + minimal_participation_ratio : Ratio_repr.t; + consensus_committee_size : int; + consensus_threshold : int; + limit_of_delegation_over_baking : int; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + testnet_dictator : Signature.Public_key_hash.t option; + initial_seed : State_hash.t option; + (* If a new cache is added, please also modify the + [cache_layout_size] value. *) + cache_script_size : int; + cache_stake_distribution_cycles : int; + cache_sampler_state_cycles : int; + dal : dal; + sc_rollup : sc_rollup; + zk_rollup : zk_rollup; + adaptive_issuance : adaptive_issuance; +} + +let sc_rollup_encoding = + let open Data_encoding in + conv + (fun (c : sc_rollup) -> + ( ( c.arith_pvm_enable, + c.origination_size, + c.challenge_window_in_blocks, + c.stake_amount, + c.commitment_period_in_blocks, + c.max_lookahead_in_blocks, + c.max_active_outbox_levels, + c.max_outbox_messages_per_level ), + ( c.number_of_sections_in_dissection, + c.timeout_period_in_blocks, + c.max_number_of_stored_cemented_commitments, + c.max_number_of_parallel_games, + c.reveal_activation_level, + c.private_enable, + c.riscv_pvm_enable ) )) + (fun ( ( sc_rollup_arith_pvm_enable, + sc_rollup_origination_size, + sc_rollup_challenge_window_in_blocks, + sc_rollup_stake_amount, + sc_rollup_commitment_period_in_blocks, + sc_rollup_max_lookahead_in_blocks, + sc_rollup_max_active_outbox_levels, + sc_rollup_max_outbox_messages_per_level ), + ( sc_rollup_number_of_sections_in_dissection, + sc_rollup_timeout_period_in_blocks, + sc_rollup_max_number_of_cemented_commitments, + sc_rollup_max_number_of_parallel_games, + sc_rollup_reveal_activation_level, + sc_rollup_private_enable, + sc_rollup_riscv_pvm_enable ) ) -> + { + arith_pvm_enable = sc_rollup_arith_pvm_enable; + origination_size = sc_rollup_origination_size; + challenge_window_in_blocks = sc_rollup_challenge_window_in_blocks; + stake_amount = sc_rollup_stake_amount; + commitment_period_in_blocks = sc_rollup_commitment_period_in_blocks; + max_lookahead_in_blocks = sc_rollup_max_lookahead_in_blocks; + max_active_outbox_levels = sc_rollup_max_active_outbox_levels; + max_outbox_messages_per_level = sc_rollup_max_outbox_messages_per_level; + number_of_sections_in_dissection = + sc_rollup_number_of_sections_in_dissection; + timeout_period_in_blocks = sc_rollup_timeout_period_in_blocks; + max_number_of_stored_cemented_commitments = + sc_rollup_max_number_of_cemented_commitments; + max_number_of_parallel_games = sc_rollup_max_number_of_parallel_games; + reveal_activation_level = sc_rollup_reveal_activation_level; + private_enable = sc_rollup_private_enable; + riscv_pvm_enable = sc_rollup_riscv_pvm_enable; + }) + (merge_objs + (obj8 + (req "smart_rollup_arith_pvm_enable" bool) + (req "smart_rollup_origination_size" int31) + (req "smart_rollup_challenge_window_in_blocks" int31) + (req "smart_rollup_stake_amount" Tez_repr.encoding) + (req "smart_rollup_commitment_period_in_blocks" int31) + (req "smart_rollup_max_lookahead_in_blocks" int32) + (req "smart_rollup_max_active_outbox_levels" int32) + (req "smart_rollup_max_outbox_messages_per_level" int31)) + (obj7 + (req "smart_rollup_number_of_sections_in_dissection" uint8) + (req "smart_rollup_timeout_period_in_blocks" int31) + (req "smart_rollup_max_number_of_cemented_commitments" int31) + (req "smart_rollup_max_number_of_parallel_games" int31) + (req + "smart_rollup_reveal_activation_level" + sc_rollup_reveal_activation_level_encoding) + (req "smart_rollup_private_enable" bool) + (req "smart_rollup_riscv_pvm_enable" bool))) + +let zk_rollup_encoding = + let open Data_encoding in + conv + (fun ({ + enable; + origination_size; + min_pending_to_process; + max_ticket_payload_size; + } : + zk_rollup) -> + (enable, origination_size, min_pending_to_process, max_ticket_payload_size)) + (fun ( zk_rollup_enable, + zk_rollup_origination_size, + zk_rollup_min_pending_to_process, + zk_rollup_max_ticket_payload_size ) -> + { + enable = zk_rollup_enable; + origination_size = zk_rollup_origination_size; + min_pending_to_process = zk_rollup_min_pending_to_process; + max_ticket_payload_size = zk_rollup_max_ticket_payload_size; + }) + (obj4 + (req "zk_rollup_enable" bool) + (req "zk_rollup_origination_size" int31) + (req "zk_rollup_min_pending_to_process" int31) + (req "zk_rollup_max_ticket_payload_size" int31)) + +let extremum_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num > Z.zero && den > Z.zero) then Ok (Q.make num den) + else + Error + "Invalid Reward Extremum Parameter: only positive values allowed") + (obj2 (req "numerator" z) (req "denominator" z))) + +let center_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num >= Z.zero && den > Z.zero && num <= den) then + Ok (Q.make num den) + else + Error + "Invalid Reward Parameter: dead zone center can only be between 0 \ + and 1") + (obj2 (req "numerator" z) (req "denominator" z))) + +let radius_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num >= Z.zero && den > Z.zero) then Ok (Q.make num den) + else + Error + "Invalid Reward Parameter: dead zone radius must be non-negative") + (obj2 (req "numerator" z) (req "denominator" z))) + +let growth_rate_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num >= Z.zero && den > Z.zero) then Ok (Q.make num den) + else Error "Invalid Reward Parameter: growth rate must be non-negative") + (obj2 (req "numerator" z) (req "denominator" z))) + +let adaptive_rewards_params_encoding = + let open Data_encoding in + conv + (fun { + issuance_ratio_min; + issuance_ratio_max; + max_bonus; + growth_rate; + center_dz; + radius_dz; + } -> + ( issuance_ratio_min, + issuance_ratio_max, + max_bonus, + growth_rate, + center_dz, + radius_dz )) + (fun ( issuance_ratio_min, + issuance_ratio_max, + max_bonus, + growth_rate, + center_dz, + radius_dz ) -> + { + issuance_ratio_min; + issuance_ratio_max; + max_bonus; + growth_rate; + center_dz; + radius_dz; + }) + (obj6 + (req "issuance_ratio_min" extremum_encoding) + (req "issuance_ratio_max" extremum_encoding) + (req "max_bonus" Issuance_bonus_repr.max_bonus_encoding) + (req "growth_rate" growth_rate_encoding) + (req "center_dz" center_encoding) + (req "radius_dz" radius_encoding)) + +let adaptive_issuance_encoding = + let open Data_encoding in + conv + (fun { + global_limit_of_staking_over_baking; + edge_of_staking_over_delegation; + launch_ema_threshold; + adaptive_rewards_params; + activation_vote_enable; + autostaking_enable; + } -> + ( global_limit_of_staking_over_baking, + edge_of_staking_over_delegation, + launch_ema_threshold, + adaptive_rewards_params, + activation_vote_enable, + autostaking_enable )) + (fun ( global_limit_of_staking_over_baking, + edge_of_staking_over_delegation, + launch_ema_threshold, + adaptive_rewards_params, + activation_vote_enable, + autostaking_enable ) -> + { + global_limit_of_staking_over_baking; + edge_of_staking_over_delegation; + launch_ema_threshold; + adaptive_rewards_params; + activation_vote_enable; + autostaking_enable; + }) + (obj6 + (req "global_limit_of_staking_over_baking" uint8) + (req "edge_of_staking_over_delegation" uint8) + (req "adaptive_issuance_launch_ema_threshold" int32) + (req "adaptive_rewards_params" adaptive_rewards_params_encoding) + (req "adaptive_issuance_activation_vote_enable" bool) + (req "autostaking_enable" bool)) + +let issuance_weights_encoding = + let open Data_encoding in + conv + (fun ({ + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + liquidity_baking_subsidy_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } : + issuance_weights) -> + ( base_total_issued_per_minute, + baking_reward_fixed_portion_weight, + baking_reward_bonus_weight, + attesting_reward_weight, + liquidity_baking_subsidy_weight, + seed_nonce_revelation_tip_weight, + vdf_revelation_tip_weight )) + (fun ( base_total_issued_per_minute, + baking_reward_fixed_portion_weight, + baking_reward_bonus_weight, + attesting_reward_weight, + liquidity_baking_subsidy_weight, + seed_nonce_revelation_tip_weight, + vdf_revelation_tip_weight ) -> + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + liquidity_baking_subsidy_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + }) + (obj7 + (req "base_total_issued_per_minute" Tez_repr.encoding) + (req "baking_reward_fixed_portion_weight" int31) + (req "baking_reward_bonus_weight" int31) + (req "attesting_reward_weight" int31) + (req "liquidity_baking_subsidy_weight" int31) + (req "seed_nonce_revelation_tip_weight" int31) + (req "vdf_revelation_tip_weight" int31)) + +let encoding = + let open Data_encoding in + conv + (fun c -> + ( ( c.preserved_cycles, + c.blocks_per_cycle, + c.blocks_per_commitment, + c.nonce_revelation_threshold, + c.blocks_per_stake_snapshot, + c.cycles_per_voting_period, + c.hard_gas_limit_per_operation, + c.hard_gas_limit_per_block, + c.proof_of_work_threshold, + c.minimal_stake ), + ( ( c.minimal_frozen_stake, + c.vdf_difficulty, + c.origination_size, + c.issuance_weights, + c.cost_per_byte, + c.hard_storage_limit_per_operation, + c.quorum_min ), + ( ( c.quorum_max, + c.min_proposal_quorum, + c.liquidity_baking_toggle_ema_threshold, + c.max_operations_time_to_live, + c.minimal_block_delay, + c.delay_increment_per_round, + c.consensus_committee_size, + c.consensus_threshold ), + ( ( c.minimal_participation_ratio, + c.limit_of_delegation_over_baking, + c.percentage_of_frozen_deposits_slashed_per_double_baking, + c.percentage_of_frozen_deposits_slashed_per_double_attestation, + c.testnet_dictator, + c.initial_seed ), + ( ( c.cache_script_size, + c.cache_stake_distribution_cycles, + c.cache_sampler_state_cycles ), + (c.dal, ((c.sc_rollup, c.zk_rollup), c.adaptive_issuance)) ) ) + ) ) )) + (fun ( ( preserved_cycles, + blocks_per_cycle, + blocks_per_commitment, + nonce_revelation_threshold, + blocks_per_stake_snapshot, + cycles_per_voting_period, + hard_gas_limit_per_operation, + hard_gas_limit_per_block, + proof_of_work_threshold, + minimal_stake ), + ( ( minimal_frozen_stake, + vdf_difficulty, + origination_size, + issuance_weights, + cost_per_byte, + hard_storage_limit_per_operation, + quorum_min ), + ( ( quorum_max, + min_proposal_quorum, + liquidity_baking_toggle_ema_threshold, + max_operations_time_to_live, + minimal_block_delay, + delay_increment_per_round, + consensus_committee_size, + consensus_threshold ), + ( ( minimal_participation_ratio, + limit_of_delegation_over_baking, + percentage_of_frozen_deposits_slashed_per_double_baking, + percentage_of_frozen_deposits_slashed_per_double_attestation, + testnet_dictator, + initial_seed ), + ( ( cache_script_size, + cache_stake_distribution_cycles, + cache_sampler_state_cycles ), + (dal, ((sc_rollup, zk_rollup), adaptive_issuance)) ) ) ) ) ) -> + { + preserved_cycles; + blocks_per_cycle; + blocks_per_commitment; + nonce_revelation_threshold; + blocks_per_stake_snapshot; + cycles_per_voting_period; + hard_gas_limit_per_operation; + hard_gas_limit_per_block; + proof_of_work_threshold; + minimal_stake; + minimal_frozen_stake; + vdf_difficulty; + origination_size; + issuance_weights; + cost_per_byte; + hard_storage_limit_per_operation; + quorum_min; + quorum_max; + min_proposal_quorum; + liquidity_baking_toggle_ema_threshold; + max_operations_time_to_live; + minimal_block_delay; + delay_increment_per_round; + minimal_participation_ratio; + consensus_committee_size; + consensus_threshold; + limit_of_delegation_over_baking; + percentage_of_frozen_deposits_slashed_per_double_baking; + percentage_of_frozen_deposits_slashed_per_double_attestation; + testnet_dictator; + initial_seed; + cache_script_size; + cache_stake_distribution_cycles; + cache_sampler_state_cycles; + dal; + sc_rollup; + zk_rollup; + adaptive_issuance; + }) + (merge_objs + (obj10 + (req "preserved_cycles" uint8) + (req "blocks_per_cycle" int32) + (req "blocks_per_commitment" int32) + (req "nonce_revelation_threshold" int32) + (req "blocks_per_stake_snapshot" int32) + (req "cycles_per_voting_period" int32) + (req + "hard_gas_limit_per_operation" + Gas_limit_repr.Arith.z_integral_encoding) + (req + "hard_gas_limit_per_block" + Gas_limit_repr.Arith.z_integral_encoding) + (req "proof_of_work_threshold" int64) + (req "minimal_stake" Tez_repr.encoding)) + (merge_objs + (obj7 + (req "minimal_frozen_stake" Tez_repr.encoding) + (req "vdf_difficulty" int64) + (req "origination_size" int31) + (req "issuance_weights" issuance_weights_encoding) + (req "cost_per_byte" Tez_repr.encoding) + (req "hard_storage_limit_per_operation" z) + (req "quorum_min" int32)) + (merge_objs + (obj8 + (req "quorum_max" int32) + (req "min_proposal_quorum" int32) + (req "liquidity_baking_toggle_ema_threshold" int32) + (req "max_operations_time_to_live" int16) + (req "minimal_block_delay" Period_repr.encoding) + (req "delay_increment_per_round" Period_repr.encoding) + (req "consensus_committee_size" int31) + (req "consensus_threshold" int31)) + (merge_objs + (obj6 + (req "minimal_participation_ratio" Ratio_repr.encoding) + (req "limit_of_delegation_over_baking" uint8) + (req + "percentage_of_frozen_deposits_slashed_per_double_baking" + Percentage.encoding_legacy_in_o) + (req + "percentage_of_frozen_deposits_slashed_per_double_attestation" + Percentage.encoding_legacy_in_o) + (opt "testnet_dictator" Signature.Public_key_hash.encoding) + (opt "initial_seed" State_hash.encoding)) + (merge_objs + (obj3 + (req "cache_script_size" int31) + (req "cache_stake_distribution_cycles" int8) + (req "cache_sampler_state_cycles" int8)) + (merge_objs + (obj1 (req "dal_parametric" dal_encoding)) + (merge_objs + (merge_objs sc_rollup_encoding zk_rollup_encoding) + adaptive_issuance_encoding))))))) diff --git a/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli new file mode 100644 index 000000000000..3dc580b00222 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli @@ -0,0 +1,203 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type dal = { + feature_enable : bool; + number_of_slots : int; + attestation_lag : int; + attestation_threshold : int; + blocks_per_epoch : int32; + cryptobox_parameters : Dal.parameters; +} + +val dal_encoding : dal Data_encoding.t + +type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level_repr.t} + +(** Associates reveal kinds to their activation level. *) +type sc_rollup_reveal_activation_level = { + raw_data : sc_rollup_reveal_hashing_schemes; + metadata : Raw_level_repr.t; + dal_page : Raw_level_repr.t; + dal_parameters : Raw_level_repr.t; +} + +type sc_rollup = { + arith_pvm_enable : bool; + origination_size : int; + challenge_window_in_blocks : int; + stake_amount : Tez_repr.t; + (* The period with which commitments are made. *) + commitment_period_in_blocks : int; + (* The maximum depth of a staker's position - chosen alongside + [commitment_period_in_blocks] to prevent the cost + of a staker's commitments' storage being greater than their deposit. *) + max_lookahead_in_blocks : int32; + (* Maximum number of active outbox levels allowed. An outbox level is active + if it has an associated record of applied messages. *) + max_active_outbox_levels : int32; + max_outbox_messages_per_level : int; + (* The default number of required sections in a dissection *) + number_of_sections_in_dissection : int; + (* The timeout period for a player in a refutation game. + + Timeout logic is similar to a chess clock. Each player starts with the same + timeout = [timeout_period_in_blocks]. Each game move updates the timeout of + the current player by decreasing it by the amount of time she took to play, + i.e. number of blocks since the opponent last move. See + {!Sc_rollup_game_repr.timeout} and + {!Sc_rollup_refutation_storage.game_move} to see the implementation. + + Because of that [timeout_period_in_blocks] must be at least half the upper + bound number of blocks needed for a game to finish. This bound is + correlated to the maximum distance allowed between the first and last tick + of a dissection. For example, when the maximum distance allowed is half the + total distance [(last_tick - last_tick) / 2] then bound is [Log^2 + (Int64.max_int) + 2 = 65]. See {!Sc_rollup_game_repr.check_dissection} for + more information on the dissection logic. *) + timeout_period_in_blocks : int; + (* The maximum number of cemented commitments stored for a sc rollup. *) + max_number_of_stored_cemented_commitments : int; + (* The maximum number of parallel games played by a given staker. *) + max_number_of_parallel_games : int; + (* Activation's block level of reveal kinds. *) + reveal_activation_level : sc_rollup_reveal_activation_level; + (* Activates an updatable whitelist of stakers. Only keys in the whitelist are + allowed to stake and publish a commitment. *) + private_enable : bool; + (* Activates the RISC-V pvm. *) + riscv_pvm_enable : bool; +} + +type zk_rollup = { + enable : bool; + origination_size : int; + (* Minimum number of pending operations that can be processed by a ZKRU + update, if available. + If the length of the pending list is less than [min_pending_to_process], + then an update needs to process all pending operations to be valid. + That is, every update must process at least + [min(length pending_list, min_pending_to_process)] pending operations. *) + min_pending_to_process : int; + max_ticket_payload_size : int; +} + +type adaptive_rewards_params = { + issuance_ratio_min : (* Maximum yearly issuance rate *) Q.t; + issuance_ratio_max : (* Minimum yearly issuance rate *) Q.t; + max_bonus : (* Maximum issuance bonus value *) Issuance_bonus_repr.max_bonus; + growth_rate : (* Bonus value's growth rate *) Q.t; + center_dz : (* Center for bonus *) Q.t; + radius_dz : + (* Minimum distance from center required for non-zero growth *) Q.t; +} + +type adaptive_issuance = { + global_limit_of_staking_over_baking + (* Global maximum stake tokens taken into account per baking token. Each baker can set their own lower limit. *) : + int; + edge_of_staking_over_delegation : + (* Weight of staking over delegation. *) int; + launch_ema_threshold : (* Threshold of the activation vote *) int32; + adaptive_rewards_params : + (* Parameters for the reward mechanism *) adaptive_rewards_params; + activation_vote_enable : + (* If set to true, reaching the launch_ema_threshold in the adaptive + issuance activation vote triggers the activation of the adaptive + inflation feature; otherwise the activation vote has no effect. *) + bool; + autostaking_enable : + (* If set to true, a stake/unstake/finalize operation will be triggered for + all delegate at end of cycle. *) + bool; +} + +type issuance_weights = { + (* [base_total_issued_per_minute] is the total amount of rewards expected to + be distributed every minute *) + base_total_issued_per_minute : Tez_repr.t; + (* The following fields represent the "weights" of the respective reward kinds. + The actual reward values are computed proportionally from the other weights + as a portion of the [base_total_issued_per_minute]. See the module + {!Delegate_rewards} for more details *) + baking_reward_fixed_portion_weight : int; + baking_reward_bonus_weight : int; + attesting_reward_weight : int; + liquidity_baking_subsidy_weight : int; + seed_nonce_revelation_tip_weight : int; + vdf_revelation_tip_weight : int; +} + +type t = { + preserved_cycles : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + nonce_revelation_threshold : int32; + blocks_per_stake_snapshot : int32; + cycles_per_voting_period : int32; + hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; + hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; + proof_of_work_threshold : int64; + minimal_stake : Tez_repr.t; + minimal_frozen_stake : Tez_repr.t; + vdf_difficulty : int64; + origination_size : int; + issuance_weights : issuance_weights; + cost_per_byte : Tez_repr.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + (* in centile of a percentage *) + quorum_max : int32; + min_proposal_quorum : int32; + liquidity_baking_toggle_ema_threshold : int32; + max_operations_time_to_live : int; + minimal_block_delay : Period_repr.t; + delay_increment_per_round : Period_repr.t; + minimal_participation_ratio : Ratio_repr.t; + consensus_committee_size : int; + (* in slots *) + consensus_threshold : int; + (* in slots *) + limit_of_delegation_over_baking : int; + (* upper bound on the (delegated tz / own frozen tz) ratio *) + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + testnet_dictator : Signature.Public_key_hash.t option; + initial_seed : State_hash.t option; + cache_script_size : int; + (* in bytes *) + cache_stake_distribution_cycles : int; + (* in cycles *) + cache_sampler_state_cycles : int; + (* in cycles *) + dal : dal; + sc_rollup : sc_rollup; + zk_rollup : zk_rollup; + adaptive_issuance : adaptive_issuance; +} + +val encoding : t Data_encoding.encoding diff --git a/src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.ml b/src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.ml new file mode 100644 index 000000000000..db6a94845fea --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.ml @@ -0,0 +1,761 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type dal = { + feature_enable : bool; + incentives_enable : bool; + number_of_slots : int; + attestation_lag : int; + attestation_threshold : int; + cryptobox_parameters : Dal.parameters; +} + +let dal_encoding = + let open Data_encoding in + conv + (fun { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + } -> + ( ( feature_enable, + incentives_enable, + number_of_slots, + attestation_lag, + attestation_threshold ), + cryptobox_parameters )) + (fun ( ( feature_enable, + incentives_enable, + number_of_slots, + attestation_lag, + attestation_threshold ), + cryptobox_parameters ) -> + { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + }) + (merge_objs + (obj5 + (req "feature_enable" bool) + (req "incentives_enable" bool) + (req "number_of_slots" uint16) + (req "attestation_lag" uint8) + (req "attestation_threshold" uint8)) + Dal.parameters_encoding) + +(* The encoded representation of this type is stored in the context as + bytes. Changing the encoding, or the value of these constants from + the previous protocol may break the context migration, or (even + worse) yield an incorrect context after migration. + + If you change this encoding compared to `Constants_parametric_previous_repr.t`, + you should ensure that there is a proper migration of the constants + during context migration. See: `Raw_context.prepare_first_block` *) + +type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level_repr.t} + +type sc_rollup_reveal_activation_level = { + raw_data : sc_rollup_reveal_hashing_schemes; + metadata : Raw_level_repr.t; + dal_page : Raw_level_repr.t; + dal_parameters : Raw_level_repr.t; + (* Once a DAL slot is attested, a rollup can only import it within the range + of levels [attested_level; attested_level + + dal_attested_slots_validity_lag]. *) + (* Warning: the semantics of valid slots needs to be adapted if the + value of this parameter is changed in the future. + - If it is increased, some attested slots that were outdated with + the old value will become valid again. + - If it is decreased, some attested slots that were valid with + the old value will become outdated. + + In both cases, the status of slots before and after the value change is + different. Said otherwise, the validity of the slot may differ depending on + the time of the check, in particular it may be different in the following + two cases: (a) the slot is imported before the value upgrade, (2) a + refutation game targeting a page of that slot is started after the + upgrade. *) + dal_attested_slots_validity_lag : int; +} + +let sc_rollup_reveal_hashing_schemes_encoding = + let open Data_encoding in + conv + (fun t -> t.blake2B) + (fun blake2B -> {blake2B}) + (obj1 (req "Blake2B" Raw_level_repr.encoding)) + +let sc_rollup_reveal_activation_level_encoding : + sc_rollup_reveal_activation_level Data_encoding.t = + let open Data_encoding in + conv + (fun t -> + ( t.raw_data, + t.metadata, + t.dal_page, + t.dal_parameters, + t.dal_attested_slots_validity_lag )) + (fun ( raw_data, + metadata, + dal_page, + dal_parameters, + dal_attested_slots_validity_lag ) -> + { + raw_data; + metadata; + dal_page; + dal_parameters; + dal_attested_slots_validity_lag; + }) + (obj5 + (req "raw_data" sc_rollup_reveal_hashing_schemes_encoding) + (req "metadata" Raw_level_repr.encoding) + (req "dal_page" Raw_level_repr.encoding) + (req "dal_parameters" Raw_level_repr.encoding) + (req "dal_attested_slots_validity_lag" Data_encoding.int31)) + +type sc_rollup = { + arith_pvm_enable : bool; + origination_size : int; + challenge_window_in_blocks : int; + stake_amount : Tez_repr.t; + commitment_period_in_blocks : int; + max_lookahead_in_blocks : int32; + max_active_outbox_levels : int32; + max_outbox_messages_per_level : int; + number_of_sections_in_dissection : int; + timeout_period_in_blocks : int; + max_number_of_stored_cemented_commitments : int; + max_number_of_parallel_games : int; + reveal_activation_level : sc_rollup_reveal_activation_level; + private_enable : bool; + riscv_pvm_enable : bool; +} + +type zk_rollup = { + enable : bool; + origination_size : int; + min_pending_to_process : int; + max_ticket_payload_size : int; +} + +type adaptive_rewards_params = { + issuance_ratio_final_min : Q.t; + issuance_ratio_final_max : Q.t; + issuance_ratio_initial_min : Q.t; + issuance_ratio_initial_max : Q.t; + initial_period : int; + transition_period : int; + max_bonus : Issuance_bonus_repr.max_bonus; + growth_rate : Q.t; + center_dz : Q.t; + radius_dz : Q.t; +} + +type adaptive_issuance = { + global_limit_of_staking_over_baking : int; + edge_of_staking_over_delegation : int; + launch_ema_threshold : int32; + adaptive_rewards_params : adaptive_rewards_params; + activation_vote_enable : bool; + autostaking_enable : bool; + force_activation : bool; + ns_enable : bool; +} + +type issuance_weights = { + base_total_issued_per_minute : Tez_repr.t; + baking_reward_fixed_portion_weight : int; + baking_reward_bonus_weight : int; + attesting_reward_weight : int; + seed_nonce_revelation_tip_weight : int; + vdf_revelation_tip_weight : int; +} + +type t = { + consensus_rights_delay : int; + blocks_preservation_cycles : int; + delegate_parameters_activation_delay : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + nonce_revelation_threshold : int32; + cycles_per_voting_period : int32; + hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; + hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; + proof_of_work_threshold : int64; + minimal_stake : Tez_repr.t; + minimal_frozen_stake : Tez_repr.t; + vdf_difficulty : int64; + origination_size : int; + issuance_weights : issuance_weights; + cost_per_byte : Tez_repr.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + quorum_max : int32; + min_proposal_quorum : int32; + liquidity_baking_subsidy : Tez_repr.t; + liquidity_baking_toggle_ema_threshold : int32; + max_operations_time_to_live : int; + minimal_block_delay : Period_repr.t; + delay_increment_per_round : Period_repr.t; + minimal_participation_ratio : Ratio_repr.t; + consensus_committee_size : int; + consensus_threshold : int; + limit_of_delegation_over_baking : int; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; + testnet_dictator : Signature.Public_key_hash.t option; + initial_seed : State_hash.t option; + (* If a new cache is added, please also modify the + [cache_layout_size] value. *) + cache_script_size : int; + cache_stake_distribution_cycles : int; + cache_sampler_state_cycles : int; + dal : dal; + sc_rollup : sc_rollup; + zk_rollup : zk_rollup; + adaptive_issuance : adaptive_issuance; + direct_ticket_spending_enable : bool; +} + +let sc_rollup_encoding = + let open Data_encoding in + conv + (fun (c : sc_rollup) -> + ( ( c.arith_pvm_enable, + c.origination_size, + c.challenge_window_in_blocks, + c.stake_amount, + c.commitment_period_in_blocks, + c.max_lookahead_in_blocks, + c.max_active_outbox_levels, + c.max_outbox_messages_per_level ), + ( c.number_of_sections_in_dissection, + c.timeout_period_in_blocks, + c.max_number_of_stored_cemented_commitments, + c.max_number_of_parallel_games, + c.reveal_activation_level, + c.private_enable, + c.riscv_pvm_enable ) )) + (fun ( ( sc_rollup_arith_pvm_enable, + sc_rollup_origination_size, + sc_rollup_challenge_window_in_blocks, + sc_rollup_stake_amount, + sc_rollup_commitment_period_in_blocks, + sc_rollup_max_lookahead_in_blocks, + sc_rollup_max_active_outbox_levels, + sc_rollup_max_outbox_messages_per_level ), + ( sc_rollup_number_of_sections_in_dissection, + sc_rollup_timeout_period_in_blocks, + sc_rollup_max_number_of_cemented_commitments, + sc_rollup_max_number_of_parallel_games, + sc_rollup_reveal_activation_level, + sc_rollup_private_enable, + sc_rollup_riscv_pvm_enable ) ) -> + { + arith_pvm_enable = sc_rollup_arith_pvm_enable; + origination_size = sc_rollup_origination_size; + challenge_window_in_blocks = sc_rollup_challenge_window_in_blocks; + stake_amount = sc_rollup_stake_amount; + commitment_period_in_blocks = sc_rollup_commitment_period_in_blocks; + max_lookahead_in_blocks = sc_rollup_max_lookahead_in_blocks; + max_active_outbox_levels = sc_rollup_max_active_outbox_levels; + max_outbox_messages_per_level = sc_rollup_max_outbox_messages_per_level; + number_of_sections_in_dissection = + sc_rollup_number_of_sections_in_dissection; + timeout_period_in_blocks = sc_rollup_timeout_period_in_blocks; + max_number_of_stored_cemented_commitments = + sc_rollup_max_number_of_cemented_commitments; + max_number_of_parallel_games = sc_rollup_max_number_of_parallel_games; + reveal_activation_level = sc_rollup_reveal_activation_level; + private_enable = sc_rollup_private_enable; + riscv_pvm_enable = sc_rollup_riscv_pvm_enable; + }) + (merge_objs + (obj8 + (req "smart_rollup_arith_pvm_enable" bool) + (req "smart_rollup_origination_size" int31) + (req "smart_rollup_challenge_window_in_blocks" int31) + (req "smart_rollup_stake_amount" Tez_repr.encoding) + (req "smart_rollup_commitment_period_in_blocks" int31) + (req "smart_rollup_max_lookahead_in_blocks" int32) + (req "smart_rollup_max_active_outbox_levels" int32) + (req "smart_rollup_max_outbox_messages_per_level" int31)) + (obj7 + (req "smart_rollup_number_of_sections_in_dissection" uint8) + (req "smart_rollup_timeout_period_in_blocks" int31) + (req "smart_rollup_max_number_of_cemented_commitments" int31) + (req "smart_rollup_max_number_of_parallel_games" int31) + (req + "smart_rollup_reveal_activation_level" + sc_rollup_reveal_activation_level_encoding) + (req "smart_rollup_private_enable" bool) + (req "smart_rollup_riscv_pvm_enable" bool))) + +let zk_rollup_encoding = + let open Data_encoding in + conv + (fun ({ + enable; + origination_size; + min_pending_to_process; + max_ticket_payload_size; + } : + zk_rollup) -> + (enable, origination_size, min_pending_to_process, max_ticket_payload_size)) + (fun ( zk_rollup_enable, + zk_rollup_origination_size, + zk_rollup_min_pending_to_process, + zk_rollup_max_ticket_payload_size ) -> + { + enable = zk_rollup_enable; + origination_size = zk_rollup_origination_size; + min_pending_to_process = zk_rollup_min_pending_to_process; + max_ticket_payload_size = zk_rollup_max_ticket_payload_size; + }) + (obj4 + (req "zk_rollup_enable" bool) + (req "zk_rollup_origination_size" int31) + (req "zk_rollup_min_pending_to_process" int31) + (req "zk_rollup_max_ticket_payload_size" int31)) + +let extremum_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num > Z.zero && den > Z.zero) then Ok (Q.make num den) + else + Error + "Invalid Reward Extremum Parameter: only positive values allowed") + (obj2 (req "numerator" z) (req "denominator" z))) + +let center_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num >= Z.zero && den > Z.zero && num <= den) then + Ok (Q.make num den) + else + Error + "Invalid Reward Parameter: dead zone center can only be between 0 \ + and 1") + (obj2 (req "numerator" z) (req "denominator" z))) + +let radius_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num >= Z.zero && den > Z.zero) then Ok (Q.make num den) + else + Error + "Invalid Reward Parameter: dead zone radius must be non-negative") + (obj2 (req "numerator" z) (req "denominator" z))) + +let growth_rate_encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num >= Z.zero && den > Z.zero) then Ok (Q.make num den) + else Error "Invalid Reward Parameter: growth rate must be non-negative") + (obj2 (req "numerator" z) (req "denominator" z))) + +let adaptive_rewards_params_encoding = + let open Data_encoding in + conv + (fun { + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; + max_bonus; + growth_rate; + center_dz; + radius_dz; + } -> + ( issuance_ratio_final_min, + issuance_ratio_final_max, + issuance_ratio_initial_min, + issuance_ratio_initial_max, + initial_period, + transition_period, + max_bonus, + growth_rate, + center_dz, + radius_dz )) + (fun ( issuance_ratio_final_min, + issuance_ratio_final_max, + issuance_ratio_initial_min, + issuance_ratio_initial_max, + initial_period, + transition_period, + max_bonus, + growth_rate, + center_dz, + radius_dz ) -> + { + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; + max_bonus; + growth_rate; + center_dz; + radius_dz; + }) + (obj10 + (req "issuance_ratio_final_min" extremum_encoding) + (req "issuance_ratio_final_max" extremum_encoding) + (req "issuance_ratio_initial_min" extremum_encoding) + (req "issuance_ratio_initial_max" extremum_encoding) + (req "initial_period" uint8) + (req "transition_period" uint8) + (req "max_bonus" Issuance_bonus_repr.max_bonus_encoding) + (req "growth_rate" growth_rate_encoding) + (req "center_dz" center_encoding) + (req "radius_dz" radius_encoding)) + +let adaptive_issuance_encoding = + let open Data_encoding in + conv + (fun { + global_limit_of_staking_over_baking; + edge_of_staking_over_delegation; + launch_ema_threshold; + adaptive_rewards_params; + activation_vote_enable; + autostaking_enable; + force_activation; + ns_enable; + } -> + ( global_limit_of_staking_over_baking, + edge_of_staking_over_delegation, + launch_ema_threshold, + adaptive_rewards_params, + activation_vote_enable, + autostaking_enable, + force_activation, + ns_enable )) + (fun ( global_limit_of_staking_over_baking, + edge_of_staking_over_delegation, + launch_ema_threshold, + adaptive_rewards_params, + activation_vote_enable, + autostaking_enable, + force_activation, + ns_enable ) -> + { + global_limit_of_staking_over_baking; + edge_of_staking_over_delegation; + launch_ema_threshold; + adaptive_rewards_params; + activation_vote_enable; + autostaking_enable; + force_activation; + ns_enable; + }) + (obj8 + (req "global_limit_of_staking_over_baking" uint8) + (req "edge_of_staking_over_delegation" uint8) + (req "adaptive_issuance_launch_ema_threshold" int32) + (req "adaptive_rewards_params" adaptive_rewards_params_encoding) + (req "adaptive_issuance_activation_vote_enable" bool) + (req "autostaking_enable" bool) + (req "adaptive_issuance_force_activation" bool) + (req "ns_enable" bool)) + +let issuance_weights_encoding = + let open Data_encoding in + conv + (fun ({ + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } : + issuance_weights) -> + ( base_total_issued_per_minute, + baking_reward_fixed_portion_weight, + baking_reward_bonus_weight, + attesting_reward_weight, + seed_nonce_revelation_tip_weight, + vdf_revelation_tip_weight )) + (fun ( base_total_issued_per_minute, + baking_reward_fixed_portion_weight, + baking_reward_bonus_weight, + attesting_reward_weight, + seed_nonce_revelation_tip_weight, + vdf_revelation_tip_weight ) -> + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + }) + (obj6 + (req "base_total_issued_per_minute" Tez_repr.encoding) + (req "baking_reward_fixed_portion_weight" int31) + (req "baking_reward_bonus_weight" int31) + (req "attesting_reward_weight" int31) + (req "seed_nonce_revelation_tip_weight" int31) + (req "vdf_revelation_tip_weight" int31)) + +let encoding = + let open Data_encoding in + conv + (fun c -> + ( ( ( c.consensus_rights_delay, + c.blocks_preservation_cycles, + c.delegate_parameters_activation_delay ), + ( c.blocks_per_cycle, + c.blocks_per_commitment, + c.nonce_revelation_threshold, + c.cycles_per_voting_period, + c.hard_gas_limit_per_operation, + c.hard_gas_limit_per_block, + c.proof_of_work_threshold, + c.minimal_stake ) ), + ( ( c.minimal_frozen_stake, + c.vdf_difficulty, + c.origination_size, + c.issuance_weights, + c.cost_per_byte, + c.hard_storage_limit_per_operation, + c.quorum_min ), + ( ( c.quorum_max, + c.min_proposal_quorum, + c.liquidity_baking_subsidy, + c.liquidity_baking_toggle_ema_threshold, + c.max_operations_time_to_live, + c.minimal_block_delay, + c.delay_increment_per_round, + c.consensus_committee_size, + c.consensus_threshold ), + ( ( c.minimal_participation_ratio, + c.limit_of_delegation_over_baking, + c.percentage_of_frozen_deposits_slashed_per_double_baking, + c.percentage_of_frozen_deposits_slashed_per_double_attestation, + c.max_slashing_per_block, + c.max_slashing_threshold, + c.testnet_dictator, + c.initial_seed ), + ( ( c.cache_script_size, + c.cache_stake_distribution_cycles, + c.cache_sampler_state_cycles ), + ( c.dal, + ( (c.sc_rollup, c.zk_rollup), + (c.adaptive_issuance, c.direct_ticket_spending_enable) ) ) + ) ) ) ) )) + (fun ( ( ( consensus_rights_delay, + blocks_preservation_cycles, + delegate_parameters_activation_delay ), + ( blocks_per_cycle, + blocks_per_commitment, + nonce_revelation_threshold, + cycles_per_voting_period, + hard_gas_limit_per_operation, + hard_gas_limit_per_block, + proof_of_work_threshold, + minimal_stake ) ), + ( ( minimal_frozen_stake, + vdf_difficulty, + origination_size, + issuance_weights, + cost_per_byte, + hard_storage_limit_per_operation, + quorum_min ), + ( ( quorum_max, + min_proposal_quorum, + liquidity_baking_subsidy, + liquidity_baking_toggle_ema_threshold, + max_operations_time_to_live, + minimal_block_delay, + delay_increment_per_round, + consensus_committee_size, + consensus_threshold ), + ( ( minimal_participation_ratio, + limit_of_delegation_over_baking, + percentage_of_frozen_deposits_slashed_per_double_baking, + percentage_of_frozen_deposits_slashed_per_double_attestation, + max_slashing_per_block, + max_slashing_threshold, + testnet_dictator, + initial_seed ), + ( ( cache_script_size, + cache_stake_distribution_cycles, + cache_sampler_state_cycles ), + ( dal, + ( (sc_rollup, zk_rollup), + (adaptive_issuance, direct_ticket_spending_enable) ) ) ) + ) ) ) ) -> + { + consensus_rights_delay; + blocks_preservation_cycles; + delegate_parameters_activation_delay; + blocks_per_cycle; + blocks_per_commitment; + nonce_revelation_threshold; + cycles_per_voting_period; + hard_gas_limit_per_operation; + hard_gas_limit_per_block; + proof_of_work_threshold; + minimal_stake; + minimal_frozen_stake; + vdf_difficulty; + origination_size; + issuance_weights; + cost_per_byte; + hard_storage_limit_per_operation; + quorum_min; + quorum_max; + min_proposal_quorum; + liquidity_baking_subsidy; + liquidity_baking_toggle_ema_threshold; + max_operations_time_to_live; + minimal_block_delay; + delay_increment_per_round; + minimal_participation_ratio; + consensus_committee_size; + consensus_threshold; + limit_of_delegation_over_baking; + percentage_of_frozen_deposits_slashed_per_double_baking; + percentage_of_frozen_deposits_slashed_per_double_attestation; + max_slashing_per_block; + max_slashing_threshold; + testnet_dictator; + initial_seed; + cache_script_size; + cache_stake_distribution_cycles; + cache_sampler_state_cycles; + dal; + sc_rollup; + zk_rollup; + adaptive_issuance; + direct_ticket_spending_enable; + }) + (merge_objs + (merge_objs + (obj3 + (req "consensus_rights_delay" uint8) + (req "blocks_preservation_cycles" uint8) + (req "delegate_parameters_activation_delay" uint8)) + (obj8 + (req "blocks_per_cycle" int32) + (req "blocks_per_commitment" int32) + (req "nonce_revelation_threshold" int32) + (req "cycles_per_voting_period" int32) + (req + "hard_gas_limit_per_operation" + Gas_limit_repr.Arith.z_integral_encoding) + (req + "hard_gas_limit_per_block" + Gas_limit_repr.Arith.z_integral_encoding) + (req "proof_of_work_threshold" int64) + (req "minimal_stake" Tez_repr.encoding))) + (merge_objs + (obj7 + (req "minimal_frozen_stake" Tez_repr.encoding) + (req "vdf_difficulty" int64) + (req "origination_size" int31) + (req "issuance_weights" issuance_weights_encoding) + (req "cost_per_byte" Tez_repr.encoding) + (req "hard_storage_limit_per_operation" z) + (req "quorum_min" int32)) + (merge_objs + (obj9 + (req "quorum_max" int32) + (req "min_proposal_quorum" int32) + (req "liquidity_baking_subsidy" Tez_repr.encoding) + (req "liquidity_baking_toggle_ema_threshold" int32) + (req "max_operations_time_to_live" int16) + (req "minimal_block_delay" Period_repr.encoding) + (req "delay_increment_per_round" Period_repr.encoding) + (req "consensus_committee_size" int31) + (req "consensus_threshold" int31)) + (merge_objs + (obj8 + (req "minimal_participation_ratio" Ratio_repr.encoding) + (req "limit_of_delegation_over_baking" uint8) + (req + "percentage_of_frozen_deposits_slashed_per_double_baking" + Percentage.encoding) + (req + "percentage_of_frozen_deposits_slashed_per_double_attestation" + Percentage.encoding) + (req "max_slashing_per_block" Percentage.encoding) + (req "max_slashing_threshold" int31) + (opt "testnet_dictator" Signature.Public_key_hash.encoding) + (opt "initial_seed" State_hash.encoding)) + (merge_objs + (obj3 + (req "cache_script_size" int31) + (req "cache_stake_distribution_cycles" int8) + (req "cache_sampler_state_cycles" int8)) + (merge_objs + (obj1 (req "dal_parametric" dal_encoding)) + (merge_objs + (merge_objs sc_rollup_encoding zk_rollup_encoding) + (merge_objs + adaptive_issuance_encoding + (obj1 (req "direct_ticket_spending_enable" bool)))))))))) + +let update_sc_rollup_parameter ~block_time c = + let seconds_in_a_day = 60 * 60 * 24 in + let seconds_in_a_week = seconds_in_a_day * 7 in + { + c with + challenge_window_in_blocks = seconds_in_a_week * 2 / block_time; + (* Same as challenge_window_in_blocks *) + max_active_outbox_levels = Int32.of_int (seconds_in_a_week * 2 / block_time); + commitment_period_in_blocks = 60 * 15 / block_time; + max_lookahead_in_blocks = Int32.of_int (seconds_in_a_day * 30 / block_time); + timeout_period_in_blocks = seconds_in_a_week / block_time; + } + +module Internal_for_tests = struct + let sc_rollup_encoding = sc_rollup_encoding +end diff --git a/src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.mli b/src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.mli new file mode 100644 index 000000000000..37cf9a2168f2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_parametric_repr.mli @@ -0,0 +1,238 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type dal = { + feature_enable : bool; + incentives_enable : bool; + number_of_slots : int; + attestation_lag : int; + attestation_threshold : int; + cryptobox_parameters : Dal.parameters; +} + +val dal_encoding : dal Data_encoding.t + +type sc_rollup_reveal_hashing_schemes = {blake2B : Raw_level_repr.t} + +(** Associates reveal kinds to their activation level. *) +type sc_rollup_reveal_activation_level = { + raw_data : sc_rollup_reveal_hashing_schemes; + metadata : Raw_level_repr.t; + dal_page : Raw_level_repr.t; + dal_parameters : Raw_level_repr.t; + dal_attested_slots_validity_lag : int; +} + +type sc_rollup = { + arith_pvm_enable : bool; + origination_size : int; + challenge_window_in_blocks : int; + stake_amount : Tez_repr.t; + (* The period with which commitments are made. *) + commitment_period_in_blocks : int; + (* The maximum depth of a staker's position - chosen alongside + [commitment_period_in_blocks] to prevent the cost + of a staker's commitments' storage being greater than their deposit. *) + max_lookahead_in_blocks : int32; + (* Maximum number of active outbox levels allowed. An outbox level is active + if it has an associated record of applied messages. *) + max_active_outbox_levels : int32; + max_outbox_messages_per_level : int; + (* The default number of required sections in a dissection *) + number_of_sections_in_dissection : int; + (* The timeout period for a player in a refutation game. + + Timeout logic is similar to a chess clock. Each player starts with the same + timeout = [timeout_period_in_blocks]. Each game move updates the timeout of + the current player by decreasing it by the amount of time she took to play, + i.e. number of blocks since the opponent last move. See + {!Sc_rollup_game_repr.timeout} and + {!Sc_rollup_refutation_storage.game_move} to see the implementation. + + Because of that [timeout_period_in_blocks] must be at least half the upper + bound number of blocks needed for a game to finish. This bound is + correlated to the maximum distance allowed between the first and last tick + of a dissection. For example, when the maximum distance allowed is half the + total distance [(last_tick - last_tick) / 2] then bound is [Log^2 + (Int64.max_int) + 2 = 65]. See {!Sc_rollup_game_repr.check_dissection} for + more information on the dissection logic. *) + timeout_period_in_blocks : int; + (* The maximum number of cemented commitments stored for a sc rollup. *) + max_number_of_stored_cemented_commitments : int; + (* The maximum number of parallel games played by a given staker. *) + max_number_of_parallel_games : int; + (* Activation's block level of reveal kinds. *) + reveal_activation_level : sc_rollup_reveal_activation_level; + (* Activates an updatable whitelist of stakers. Only keys in the whitelist are + allowed to stake and publish a commitment. *) + private_enable : bool; + (* Activates the RISC-V pvm. *) + riscv_pvm_enable : bool; +} + +type zk_rollup = { + enable : bool; + origination_size : int; + (* Minimum number of pending operations that can be processed by a ZKRU + update, if available. + If the length of the pending list is less than [min_pending_to_process], + then an update needs to process all pending operations to be valid. + That is, every update must process at least + [min(length pending_list, min_pending_to_process)] pending operations. *) + min_pending_to_process : int; + max_ticket_payload_size : int; +} + +type adaptive_rewards_params = { + issuance_ratio_final_min : (* Minimum yearly issuance rate *) Q.t; + issuance_ratio_final_max : (* Maximum yearly issuance rate *) Q.t; + issuance_ratio_initial_min : + (* Minimum yearly issuance rate at adaptive issuance activation *) Q.t; + issuance_ratio_initial_max : + (* Maximum yearly issuance rate at adaptive issuance activation *) Q.t; + initial_period : + (* Period in cycles during which the minimum and maximum yearly + issuance rate values stay at their initial values *) + int; + transition_period : + (* Period in cycles during which the minimum and maximum yearly + issuance rate values decrease/increase until they reach their global values *) + int; + max_bonus : (* Maximum issuance bonus value *) Issuance_bonus_repr.max_bonus; + growth_rate : (* Bonus value's growth rate *) Q.t; + center_dz : (* Center for bonus *) Q.t; + radius_dz : + (* Minimum distance from center required for non-zero growth *) Q.t; +} + +type adaptive_issuance = { + global_limit_of_staking_over_baking + (* Global maximum stake tokens taken into account per baking token. Each baker can set their own lower limit. *) : + int; + edge_of_staking_over_delegation : + (* Weight of staking over delegation. *) int; + launch_ema_threshold : (* Threshold of the activation vote *) int32; + adaptive_rewards_params : + (* Parameters for the reward mechanism *) adaptive_rewards_params; + activation_vote_enable : + (* If set to true, reaching the launch_ema_threshold in the adaptive + issuance activation vote triggers the activation of the adaptive + inflation feature; otherwise the activation vote has no effect. *) + bool; + autostaking_enable : + (* If set to true, a stake/unstake/finalize operation will be triggered for + all delegate at end of cycle. *) + bool; + force_activation : + (* For testing purposes. If set to true, the adaptive issuance feature is + enabled without waiting to reach the launch_ema_threshold.*) + bool; + ns_enable : (* If set to true, enables the NS feature *) + bool; +} + +type issuance_weights = { + (* [base_total_issued_per_minute] is the total amount of rewards expected to + be distributed every minute *) + base_total_issued_per_minute : Tez_repr.t; + (* The following fields represent the "weights" of the respective reward kinds. + The actual reward values are computed proportionally from the other weights + as a portion of the [base_total_issued_per_minute]. See the module + {!Delegate_rewards} for more details *) + baking_reward_fixed_portion_weight : int; + baking_reward_bonus_weight : int; + attesting_reward_weight : int; + seed_nonce_revelation_tip_weight : int; + vdf_revelation_tip_weight : int; +} + +type t = { + (* Number of cycles after which computed consensus rights are used to actually + participate in the consensus *) + consensus_rights_delay : int; + (* Number of past cycles about which the protocol hints the shell that it should + keep them in its history. *) + blocks_preservation_cycles : int; + (* Number of cycles after which submitted delegate parameters are being + used. *) + delegate_parameters_activation_delay : int; + blocks_per_cycle : int32; + blocks_per_commitment : int32; + nonce_revelation_threshold : int32; + cycles_per_voting_period : int32; + hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; + hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; + proof_of_work_threshold : int64; + minimal_stake : Tez_repr.t; + minimal_frozen_stake : Tez_repr.t; + vdf_difficulty : int64; + origination_size : int; + issuance_weights : issuance_weights; + cost_per_byte : Tez_repr.t; + hard_storage_limit_per_operation : Z.t; + quorum_min : int32; + (* in centile of a percentage *) + quorum_max : int32; + min_proposal_quorum : int32; + liquidity_baking_subsidy : Tez_repr.t; + liquidity_baking_toggle_ema_threshold : int32; + max_operations_time_to_live : int; + minimal_block_delay : Period_repr.t; + delay_increment_per_round : Period_repr.t; + minimal_participation_ratio : Ratio_repr.t; + consensus_committee_size : int; + (* in slots *) + consensus_threshold : int; + (* in slots *) + limit_of_delegation_over_baking : int; + (* upper bound on the (delegated tz / own frozen tz) ratio *) + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; + testnet_dictator : Signature.Public_key_hash.t option; + initial_seed : State_hash.t option; + cache_script_size : int; + (* in bytes *) + cache_stake_distribution_cycles : int; + (* in cycles *) + cache_sampler_state_cycles : int; + (* in cycles *) + dal : dal; + sc_rollup : sc_rollup; + zk_rollup : zk_rollup; + adaptive_issuance : adaptive_issuance; + direct_ticket_spending_enable : bool; +} + +val encoding : t Data_encoding.encoding + +val update_sc_rollup_parameter : block_time:int -> sc_rollup -> sc_rollup + +module Internal_for_tests : sig + val sc_rollup_encoding : sc_rollup Data_encoding.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/constants_repr.ml b/src/proto_020_PsParisC/lib_protocol/constants_repr.ml new file mode 100644 index 000000000000..e483b98dd5d8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_repr.ml @@ -0,0 +1,389 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +let version_value = "paris_019" + +let version = "v1" + +let mainnet_id = Chain_id.of_b58check_exn "NetXdQprcVkpaWU" + +(* The fitness version number was: + - "\000" until and including proto 004 + - "\001" until and including proto 010 +*) +let fitness_version_number = "\002" + +let proof_of_work_nonce_size = 8 + +let nonce_length = 32 + +let max_anon_ops_per_block = 132 + +let max_proposals_per_delegate = 20 + +let max_operation_data_length = 32 * 1024 (* 32kB *) + +let max_micheline_node_count = 50_000 + +let max_micheline_bytes_limit = 50_000 + +let max_allowed_global_constant_depth = 10_000 + +(* In previous versions of the protocol, this + [michelson_maximum_type_size] limit was set to 1000 but + the contract input types (pair ) + were not checked. Both components, and + where however checked hence it was possible to build + types as big as 2001. *) +let michelson_maximum_type_size = 2001 + +(* This constant declares the number of subcaches used by the cache + mechanism (see {Context.Cache}). *) +let cache_layout_size = 3 + +let max_slashing_period = 2 + +(* The {!Sc_rollups.wrapped_proof_encoding} uses unbounded sub-encodings. + To avoid attacks through too large proofs and long decoding times on public + nodes, we put another layer of security by restricting the maximum_size + to [30Kb]. + + Even if the operation size limit is currently [32Kb] (see + {!Constants_repr.max_operation_data_length}) the node's mempool can still + be spammed with larger proofs before detecting that the operations are + indeed larger than the limit. + + By design, the proofs should be created and verified for a single tick + which should limit the number of read/writes in the Merkle tree, and thefore, + limit the total size of a proof. Thus, [30Kb] can be lowered once we + have empirically observed that a valid proof can not be that large. + + Note that an encoded proof that is [30Kb] might still be not included + in a valid L1 operation. The refutation operation also contains other + information such as an inbox proof. We only put here an upper bound + for the size. +*) +let sc_max_wrapped_proof_binary_size = 30_000 + +(* A limit on the size of the binary encoding of sc rollup messages. This limit + depends on the assumed overhead of the proof and metadata in a manager + operation justifying the existence of some chunk of data in the rollup state. + The value of this constant reflects the global constant of 4KB in the WASM + PVM specification chosen for the limit of chunks that are embedded in proofs. +*) +let sc_rollup_message_size_limit = 4_096 + +(** A limit on the number of messages per inbox level. + + Benchmarks have shown that proving the inclusion of the element at + index 0 in a skip list of [1_000_000] elements is ~=6Kb large. +*) +let sc_rollup_max_number_of_messages_per_level = Z.of_int 1_000_000 + +type fixed = unit + +let fixed_encoding = + let open Data_encoding in + conv + (fun () -> + ( ( proof_of_work_nonce_size, + nonce_length, + max_anon_ops_per_block, + max_operation_data_length, + max_proposals_per_delegate, + max_micheline_node_count, + max_micheline_bytes_limit, + max_allowed_global_constant_depth, + cache_layout_size, + michelson_maximum_type_size ), + ( max_slashing_period, + sc_max_wrapped_proof_binary_size, + sc_rollup_message_size_limit, + sc_rollup_max_number_of_messages_per_level ) )) + (fun ( ( _proof_of_work_nonce_size, + _nonce_length, + _max_anon_ops_per_block, + _max_operation_data_length, + _max_proposals_per_delegate, + _max_micheline_node_count, + _max_micheline_bytes_limit, + _max_allowed_global_constant_depth, + _cache_layout_size, + _michelson_maximum_type_size ), + ( _max_slashing_period, + _sc_max_wrapped_proof_binary_size, + _sc_rollup_message_size_limit, + _sc_rollup_number_of_messages_per_level ) ) -> ()) + (merge_objs + (obj10 + (req "proof_of_work_nonce_size" uint8) + (req "nonce_length" uint8) + (req "max_anon_ops_per_block" uint8) + (req "max_operation_data_length" int31) + (req "max_proposals_per_delegate" uint8) + (req "max_micheline_node_count" int31) + (req "max_micheline_bytes_limit" int31) + (req "max_allowed_global_constants_depth" int31) + (req "cache_layout_size" uint8) + (req "michelson_maximum_type_size" uint16)) + (obj4 + (req "max_slashing_period" uint8) + (req "smart_rollup_max_wrapped_proof_binary_size" int31) + (req "smart_rollup_message_size_limit" int31) + (req "smart_rollup_max_number_of_messages_per_level" n))) + +let fixed = () + +type t = {fixed : fixed; parametric : Constants_parametric_repr.t} + +let all_of_parametric parametric = {fixed; parametric} + +let encoding = + let open Data_encoding in + conv + (fun {fixed; parametric} -> (fixed, parametric)) + (fun (fixed, parametric) -> {fixed; parametric}) + (merge_objs fixed_encoding Constants_parametric_repr.encoding) + +type error += Invalid_protocol_constants of string (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"constants.invalid_protocol_constants" + ~title:"Invalid protocol constants" + ~description:"The provided protocol constants are not coherent." + ~pp:(fun ppf reason -> + Format.fprintf ppf "Invalid protocol constants: %s" reason) + Data_encoding.(obj1 (req "reason" @@ string Plain)) + (function Invalid_protocol_constants reason -> Some reason | _ -> None) + (fun reason -> Invalid_protocol_constants reason) + +let check_constants constants = + let open Result_syntax in + let open Constants_parametric_repr in + let* () = + error_unless + Period_repr.(constants.minimal_block_delay > zero) + (Invalid_protocol_constants + "The minimal block delay must be greater than zero") + in + let* () = + error_unless + Period_repr.(constants.delay_increment_per_round > zero) + (Invalid_protocol_constants + "The delay increment per round must be greater than zero") + in + let* () = + error_unless + Compare.Int.(constants.consensus_committee_size > 0) + (Invalid_protocol_constants + "The consensus committee size must be strictly greater than 0.") + in + let* () = + error_unless + Compare.Int.( + constants.consensus_threshold >= 0 + && constants.consensus_threshold <= constants.consensus_committee_size) + (Invalid_protocol_constants + "The consensus threshold must be greater than or equal to 0 and less \ + than or equal to the consensus commitee size.") + in + let* () = + error_unless + (let Ratio_repr.{numerator; denominator} = + constants.minimal_participation_ratio + in + Compare.Int.(numerator >= 0 && denominator > 0)) + (Invalid_protocol_constants + "The minimal participation ratio must be a non-negative valid ratio.") + in + let* () = + error_unless + Compare.Int.( + constants.minimal_participation_ratio.numerator + <= constants.minimal_participation_ratio.denominator) + (Invalid_protocol_constants + "The minimal participation ratio must be less than or equal to 100%.") + in + (* The [limit_of_delegation_over_baking] should be non-negative. *) + let* () = + error_unless + Compare.Int.(constants.limit_of_delegation_over_baking >= 0) + (Invalid_protocol_constants + "The delegation over baking limit must be greater than or equal to 0.") + in + let* () = + error_unless + Compare.Int32.( + constants.nonce_revelation_threshold > Int32.zero + && constants.nonce_revelation_threshold < constants.blocks_per_cycle) + (Invalid_protocol_constants + "The nonce revelation threshold must be strictly smaller than \ + blocks_per_cycle and strictly positive.") + in + let* () = + error_unless + Compare.Int64.( + let threshold = Int64.of_int32 constants.nonce_revelation_threshold in + let block = Period_repr.to_seconds constants.minimal_block_delay in + let ips = + (* We reduce the ips for short blocks_per_commitment so that we have + low difficulty during tests *) + if Compare.Int32.(constants.blocks_per_commitment > 32l) then + Int64.of_int 200_000 + else Int64.one + in + let factor = Int64.of_int 5 in + let difficulty = Int64.(mul (mul ips factor) (mul threshold block)) in + constants.vdf_difficulty > difficulty) + (Invalid_protocol_constants + "The VDF difficulty must be strictly greater than the product of the \ + nonce_revelation_threshold, the minimial_block_delay, a benchmark of \ + modulo squaring in class groups and a security threshold.") + in + let* () = + error_unless + Compare.Int.(constants.sc_rollup.origination_size >= 0) + (Invalid_protocol_constants + "The smart rollup origination size must be non-negative.") + in + let* () = + error_unless + Compare.Int.(constants.sc_rollup.challenge_window_in_blocks >= 0) + (Invalid_protocol_constants + "The smart rollup challenge window in blocks must be non-negative.") + in + let* () = + error_unless + Tez_repr.(constants.sc_rollup.stake_amount >= zero) + (Invalid_protocol_constants + "The smart rollup max stake amount must be non-negative.") + in + let* () = + error_unless + Compare.Int.(constants.sc_rollup.commitment_period_in_blocks > 0) + (Invalid_protocol_constants + "The smart rollup commitment period in blocks must be strictly \ + greater than 0.") + in + let* () = + error_unless + (let sc_rollup_max_lookahead_in_blocks = + constants.sc_rollup.max_lookahead_in_blocks + in + Compare.Int32.( + sc_rollup_max_lookahead_in_blocks + > Int32.of_int constants.sc_rollup.commitment_period_in_blocks + && (* Check that [smart_rollup_challenge_window_in_blocks < + smart_rollup_max_lookahead_in_blocks]. Otherwise committers would be + forced to commit at an artificially slow rate, affecting the + throughput of the rollup. *) + sc_rollup_max_lookahead_in_blocks + > Int32.of_int constants.sc_rollup.challenge_window_in_blocks)) + (Invalid_protocol_constants + "The smart rollup max lookahead in blocks must be greater than \ + [smart_rollup_commitment_period_in_blocks] and \ + [smart_rollup_challenge_window_in_blocks].") + in + let* () = + error_unless + Compare.Int.( + constants.dal.number_of_slots > 0 + && constants.dal.number_of_slots <= 256) + (Invalid_protocol_constants + "The number of data availability slot must be between 1 and 256") + in + let* () = + error_unless + Compare.Int.(constants.dal.attestation_lag > 1) + (Invalid_protocol_constants + "The attestation_lag must be strictly greater than 1, because only \ + slot headers in finalized blocks are attested.") + in + let* () = + error_unless + Compare.Int.( + constants.sc_rollup.max_number_of_stored_cemented_commitments > 0) + (Invalid_protocol_constants + "The number of maximum stored cemented commitments must be strictly \ + positive") + in + Result.return_unit + +module Generated = struct + type t = { + consensus_threshold : int; + issuance_weights : Constants_parametric_repr.issuance_weights; + max_slashing_threshold : int; + } + + let generate ~consensus_committee_size = + (* The weights are expressed in [(256 * 80)]th of the total + reward, because it is the smallest proportion used so far*) + (* let f = consensus_committee_size / 3 in *) + let max_slashing_threshold = (consensus_committee_size / 3) + 1 in + let consensus_threshold = (consensus_committee_size * 2 / 3) + 1 in + let bonus_committee_size = consensus_committee_size - consensus_threshold in + let base_total_issued_per_minute = Tez_repr.of_mutez_exn 80_007_812L in + let _reward_parts_whole = 20480 (* = 256 * 80 *) in + let reward_parts_half = 10240 (* = reward_parts_whole / 2 *) in + let reward_parts_quarter = 5120 (* = reward_parts_whole / 4 *) in + { + max_slashing_threshold; + consensus_threshold; + issuance_weights = + { + base_total_issued_per_minute; + (* 80.007812 tez/minute *) + baking_reward_fixed_portion_weight = + (* 1/4 or 1/2 *) + (if Compare.Int.(bonus_committee_size <= 0) then + (* a fortiori, consensus_committee_size < 4 *) + reward_parts_half + else reward_parts_quarter); + baking_reward_bonus_weight = + (* 1/4 or 0 *) + (if Compare.Int.(bonus_committee_size <= 0) then 0 + else reward_parts_quarter); + attesting_reward_weight = reward_parts_half; + (* 1/2 *) + (* All block (baking + attesting)rewards sum to 1 ( *256*80 ) *) + seed_nonce_revelation_tip_weight = 1; + (* 1/20480 *) + vdf_revelation_tip_weight = 1; + (* 1/20480 *) + }; + } +end + +let cache_layout p = + Constants_parametric_repr. + [ + p.cache_script_size; + p.cache_stake_distribution_cycles; + p.cache_sampler_state_cycles; + ] diff --git a/src/proto_020_PsParisC/lib_protocol/constants_repr.mli b/src/proto_020_PsParisC/lib_protocol/constants_repr.mli new file mode 100644 index 000000000000..29e20a85e38f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_repr.mli @@ -0,0 +1,142 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +val version_value : string + +val version : string + +val mainnet_id : Chain_id.t + +val fitness_version_number : string + +val proof_of_work_nonce_size : int + +val nonce_length : int + +val max_anon_ops_per_block : int + +val max_proposals_per_delegate : int + +val max_operation_data_length : int + +(** A global size limit on the size of Micheline expressions + after expansion. + + We want to prevent constants from being + used to create huge values that could potentially do damage + if ever printed or sent over the network. We arrived at this + number by finding the largest possible contract in terms of + number of nodes. The number of nodes is constrained by the + current "max_operation_data_length" (32768) to be ~10,000 ( + see "large_flat_contract.tz" in the tezt suite for the largest + contract with constants that can be originated). As a first + approximation, we set the node size limit to 5 times this amount. *) +val max_micheline_node_count : int + +(** Same as [max_micheline_node_count] but for limiting the combined + bytes of the strings, ints and bytes in a expanded Micheline + expression. *) +val max_micheline_bytes_limit : int + +(** Represents the maximum depth of an expression stored + in the table after all references to other constants have + (recursively) been expanded, where depth refers to the + nesting of [Prim] and/or [Seq] nodes. + + The size was chosen arbitrarily to match the typechecker + in [Script_ir_translator]. *) +val max_allowed_global_constant_depth : int + +(** A global size limit on the size of Michelson types. + + The size of a type is the number of nodes in its AST + representation. See [Script_typed_ir.TYPE_SIZE]. + *) +val michelson_maximum_type_size : int + +(** The max slashing period is the maximum number of cycles after which a + misbehaviour can be denounced, i.e. if a misbehaviour happened at cycle [c], + it will be rejected if it is denounced at cycle [c + max_slashing_period]. + Having [max_slashing_period] strictly smaller than 2 doesn't make sense. + Indeed, if a misbehaviour happens at the very last block of a cycle, it + couldn't be denounced. + [max_slashing_period = 2] leaves one cycle to denounce a misbehaviour in + the worst case, which is deemed enough. + Several parts of the codebase may use the fact that + [max_slashing_period = 2], so let's ensure it cannot be different. *) +val max_slashing_period : int + +(** A size limit for {!Sc_rollups.wrapped_proof} binary encoding. *) +val sc_max_wrapped_proof_binary_size : int + +(** A limit on the size of the binary encoding for sc rollup messages: + {!Sc_rollup_inbox_message_repr.t} and {!Sc_rollup_outbox_message_repr.t} +*) +val sc_rollup_message_size_limit : int + +(** A limit on the number of messages in a inbox level enforced in + {!Sc_rollup_inbox_repr.t}. *) +val sc_rollup_max_number_of_messages_per_level : Z.t + +type fixed + +val fixed_encoding : fixed Data_encoding.encoding + +type t = private {fixed : fixed; parametric : Constants_parametric_repr.t} + +val all_of_parametric : Constants_parametric_repr.t -> t + +val encoding : t Data_encoding.encoding + +type error += (* `Permanent *) Invalid_protocol_constants of string + +(** performs some consistency checks on the protocol parameters *) +val check_constants : Constants_parametric_repr.t -> unit tzresult + +module Generated : sig + type t = { + consensus_threshold : int; + issuance_weights : Constants_parametric_repr.issuance_weights; + max_slashing_threshold : int; + } + + (* This function is meant to be used just in lib_parameters and in the + migration code to be sure that the parameters are consistent. *) + val generate : consensus_committee_size:int -> t +end + +(** For each subcache, a size limit needs to be declared once. However, + depending how the protocol will be instantiated (sandboxed mode, + test network, ...) we may want to change this limit. For each + subcache, a parametric constant can be used to change the limit + (see {!parametric}). + + The number of subcaches and the limits for all those subcaches form + together what is called the [cache_layout]. *) +val cache_layout_size : int + +(** The [cache_layout] depends on parametric constants. *) +val cache_layout : Constants_parametric_repr.t -> int list diff --git a/src/proto_020_PsParisC/lib_protocol/constants_services.ml b/src/proto_020_PsParisC/lib_protocol/constants_services.ml new file mode 100644 index 000000000000..b28b1bac2e79 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_services.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = + (RPC_path.(open_root / "context" / "constants") + : RPC_context.t RPC_path.context) + +module S = struct + open Data_encoding + + let errors = + RPC_service.get_service + ~description:"Schema for all the RPC errors from this protocol version" + ~query:RPC_query.empty + ~output:json_schema + RPC_path.(custom_root / "errors") + + let all = + RPC_service.get_service + ~description:"All constants" + ~query:RPC_query.empty + ~output:Alpha_context.Constants.encoding + custom_root + + let parametric = + RPC_service.get_service + ~description:"Parametric constants" + ~query:RPC_query.empty + ~output:Alpha_context.Constants.Parametric.encoding + RPC_path.(custom_root / "parametric") +end + +let register () = + let open Services_registration in + register0_noctxt ~chunked:true S.errors (fun () () -> + return Data_encoding.Json.(schema error_encoding)) ; + register0 ~chunked:false S.all (fun ctxt () () -> + return @@ Constants.all ctxt) ; + register0 ~chunked:false S.parametric (fun ctxt () () -> + return @@ Constants.parametric ctxt) + +let errors ctxt block = RPC_context.make_call0 S.errors ctxt block () () + +let all ctxt block = RPC_context.make_call0 S.all ctxt block () () + +let parametric ctxt block = RPC_context.make_call0 S.parametric ctxt block () () diff --git a/src/proto_020_PsParisC/lib_protocol/constants_services.mli b/src/proto_020_PsParisC/lib_protocol/constants_services.mli new file mode 100644 index 000000000000..97294ab20ad2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_services.mli @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val errors : + 'a #RPC_context.simple -> 'a -> Data_encoding.json_schema shell_tzresult Lwt.t + +(** Returns all the constants of the protocol *) +val all : 'a #RPC_context.simple -> 'a -> Constants.t shell_tzresult Lwt.t + +(** Returns the parametric constants of the protocol *) +val parametric : + 'a #RPC_context.simple -> 'a -> Constants.Parametric.t shell_tzresult Lwt.t + +val register : unit -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/constants_storage.ml b/src/proto_020_PsParisC/lib_protocol/constants_storage.ml new file mode 100644 index 000000000000..aca507fd1ba3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_storage.ml @@ -0,0 +1,299 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let consensus_rights_delay c = + let constants = Raw_context.constants c in + constants.consensus_rights_delay + +let blocks_preservation_cycles c = + let constants = Raw_context.constants c in + constants.blocks_preservation_cycles + +let delegate_parameters_activation_delay c = + let constants = Raw_context.constants c in + constants.delegate_parameters_activation_delay + +(** Issuance modification delay: + number of cycles after which the issuance rate -- computed from current stake + over total supply -- will be used. + + We use consensus_rights_delay so that the issuance rate in one cycle + corresponds to the "active" staking rights. +*) +let issuance_modification_delay c = + let constants = Raw_context.constants c in + constants.consensus_rights_delay + +(** Adaptive Issuance activation delay: + After the e.m.a. of AI votes reaches the threshold, we wait for this delay + before effectively activating AI. +*) +let adaptive_issuance_activation_delay c = + let constants = Raw_context.constants c in + 1 + constants.consensus_rights_delay + Constants_repr.max_slashing_period + +(** Tolerated inactivity period for delegates before being deactivated. *) +let tolerated_inactivity_period c = + let constants = Raw_context.constants c in + 1 + constants.consensus_rights_delay + +(** Delay between consensus key declaration by the delegate and the cycle where + it has to be used to sign on behalf of the delegate. *) +let consensus_key_activation_delay c = + let constants = Raw_context.constants c in + constants.consensus_rights_delay + +(** Number of cycles during which a misbehavior of the delegate will induce a + slashing of the funds that are currently in its frozen deposits. *) +let slashable_deposits_period c = + let constants = Raw_context.constants c in + constants.consensus_rights_delay + +let blocks_per_cycle c = + let constants = Raw_context.constants c in + constants.blocks_per_cycle + +let blocks_per_commitment c = + let constants = Raw_context.constants c in + constants.blocks_per_commitment + +let nonce_revelation_threshold c = + let constants = Raw_context.constants c in + constants.nonce_revelation_threshold + +let cycles_per_voting_period c = + let constants = Raw_context.constants c in + constants.cycles_per_voting_period + +let hard_gas_limit_per_operation c = + let constants = Raw_context.constants c in + constants.hard_gas_limit_per_operation + +let hard_gas_limit_per_block c = + let constants = Raw_context.constants c in + constants.hard_gas_limit_per_block + +let cost_per_byte c = + let constants = Raw_context.constants c in + constants.cost_per_byte + +let hard_storage_limit_per_operation c = + let constants = Raw_context.constants c in + constants.hard_storage_limit_per_operation + +let proof_of_work_threshold c = + let constants = Raw_context.constants c in + constants.proof_of_work_threshold + +let minimal_stake c = + let constants = Raw_context.constants c in + constants.minimal_stake + +let minimal_frozen_stake c = + let constants = Raw_context.constants c in + constants.minimal_frozen_stake + +let vdf_difficulty c = + let constants = Raw_context.constants c in + constants.vdf_difficulty + +let origination_size c = + let constants = Raw_context.constants c in + constants.origination_size + +let issuance_weights c = + let constants = Raw_context.constants c in + constants.issuance_weights + +let quorum_min c = + let constants = Raw_context.constants c in + constants.quorum_min + +let quorum_max c = + let constants = Raw_context.constants c in + constants.quorum_max + +let min_proposal_quorum c = + let constants = Raw_context.constants c in + constants.min_proposal_quorum + +let liquidity_baking_toggle_ema_threshold c = + let constants = Raw_context.constants c in + constants.liquidity_baking_toggle_ema_threshold + +let parametric c = Raw_context.constants c + +let sc_rollup c = (Raw_context.constants c).sc_rollup + +let minimal_block_delay c = + let constants = Raw_context.constants c in + constants.minimal_block_delay + +let delay_increment_per_round c = + let constants = Raw_context.constants c in + constants.delay_increment_per_round + +let consensus_committee_size c = + let constants = Raw_context.constants c in + constants.consensus_committee_size + +let consensus_threshold c = + let constants = Raw_context.constants c in + constants.consensus_threshold + +let minimal_participation_ratio c = + let constants = Raw_context.constants c in + constants.minimal_participation_ratio + +let limit_of_delegation_over_baking c = + let constants = Raw_context.constants c in + constants.limit_of_delegation_over_baking + +let percentage_of_frozen_deposits_slashed_per_double_baking c = + let constants = Raw_context.constants c in + constants.percentage_of_frozen_deposits_slashed_per_double_baking + +let percentage_of_frozen_deposits_slashed_per_double_attestation c = + let constants = Raw_context.constants c in + constants.percentage_of_frozen_deposits_slashed_per_double_attestation + +let testnet_dictator c = + let constants = Raw_context.constants c in + constants.testnet_dictator + +let sc_rollup_arith_pvm_enable c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.arith_pvm_enable + +let sc_rollup_origination_size c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.origination_size + +let sc_rollup_challenge_window_in_blocks c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.challenge_window_in_blocks + +let sc_rollup_stake_amount c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.stake_amount + +let sc_rollup_commitment_period_in_blocks c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.commitment_period_in_blocks + +let sc_rollup_max_lookahead_in_blocks c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.max_lookahead_in_blocks + +let sc_rollup_max_active_outbox_levels c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.max_active_outbox_levels + +let sc_rollup_max_outbox_messages_per_level c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.max_outbox_messages_per_level + +let sc_rollup_number_of_sections_in_dissection c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.number_of_sections_in_dissection + +let sc_rollup_timeout_period_in_blocks c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.timeout_period_in_blocks + +let sc_rollup_max_number_of_parallel_games c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.max_number_of_parallel_games + +let max_number_of_stored_cemented_commitments c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.max_number_of_stored_cemented_commitments + +let sc_rollup_reveal_activation_level c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.reveal_activation_level + +let sc_rollup_private_enable c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.private_enable + +let sc_rollup_riscv_pvm_enable c = + let sc_rollup = Raw_context.sc_rollup c in + sc_rollup.riscv_pvm_enable + +let dal_number_of_slots c = + let constants = Raw_context.constants c in + constants.dal.number_of_slots + +let dal_enable c = + let constants = Raw_context.constants c in + constants.dal.feature_enable + +let zk_rollup_enable c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.enable + +let zk_rollup_min_pending_to_process c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.min_pending_to_process + +let zk_rollup_origination_size c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.origination_size + +let zk_rollup_max_ticket_payload_size c = + let zk_rollup = Raw_context.zk_rollup c in + zk_rollup.max_ticket_payload_size + +let adaptive_issuance c = (Raw_context.constants c).adaptive_issuance + +let adaptive_issuance_enable c = Raw_context.adaptive_issuance_enable c + +let adaptive_issuance_global_limit_of_staking_over_baking c = + (adaptive_issuance c).global_limit_of_staking_over_baking + +let adaptive_issuance_edge_of_staking_over_delegation c = + (adaptive_issuance c).edge_of_staking_over_delegation + +let adaptive_issuance_launch_ema_threshold c = + (adaptive_issuance c).launch_ema_threshold + +let adaptive_issuance_rewards_params c = + (adaptive_issuance c).adaptive_rewards_params + +let adaptive_issuance_activation_vote_enable c = + (adaptive_issuance c).activation_vote_enable + +let adaptive_issuance_autostaking_enable c = + (adaptive_issuance c).autostaking_enable + +let adaptive_issuance_force_activation c = + (adaptive_issuance c).force_activation + +let adaptive_issuance_ns_enable c = (adaptive_issuance c).ns_enable + +let direct_ticket_spending_enable c = + (Raw_context.constants c).direct_ticket_spending_enable diff --git a/src/proto_020_PsParisC/lib_protocol/constants_storage.mli b/src/proto_020_PsParisC/lib_protocol/constants_storage.mli new file mode 100644 index 000000000000..d64fe88584ec --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/constants_storage.mli @@ -0,0 +1,185 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides functions to extract the value of protocol parameters + from the context. + See {!Constant_repr.parametric} for more details about these values. *) + +val consensus_rights_delay : Raw_context.t -> int + +val blocks_preservation_cycles : Raw_context.t -> int + +val delegate_parameters_activation_delay : Raw_context.t -> int + +val blocks_per_cycle : Raw_context.t -> int32 + +val blocks_per_commitment : Raw_context.t -> int32 + +val nonce_revelation_threshold : Raw_context.t -> int32 + +val cycles_per_voting_period : Raw_context.t -> int32 + +val hard_gas_limit_per_operation : + Raw_context.t -> Gas_limit_repr.Arith.integral + +val hard_gas_limit_per_block : Raw_context.t -> Gas_limit_repr.Arith.integral + +val cost_per_byte : Raw_context.t -> Tez_repr.t + +val hard_storage_limit_per_operation : Raw_context.t -> Z.t + +val proof_of_work_threshold : Raw_context.t -> int64 + +val minimal_stake : Raw_context.t -> Tez_repr.t + +val minimal_frozen_stake : Raw_context.t -> Tez_repr.t + +val vdf_difficulty : Raw_context.t -> int64 + +val origination_size : Raw_context.t -> int + +val issuance_weights : + Raw_context.t -> Constants_parametric_repr.issuance_weights + +val quorum_min : Raw_context.t -> int32 + +val quorum_max : Raw_context.t -> int32 + +val min_proposal_quorum : Raw_context.t -> int32 + +val liquidity_baking_toggle_ema_threshold : Raw_context.t -> int32 + +val parametric : Raw_context.t -> Constants_parametric_repr.t + +val sc_rollup : Raw_context.t -> Constants_parametric_repr.sc_rollup + +val consensus_committee_size : Raw_context.t -> int + +val consensus_threshold : Raw_context.t -> int + +val minimal_participation_ratio : Raw_context.t -> Ratio_repr.t + +val limit_of_delegation_over_baking : Raw_context.t -> int + +val percentage_of_frozen_deposits_slashed_per_double_baking : + Raw_context.t -> Percentage.t + +val percentage_of_frozen_deposits_slashed_per_double_attestation : + Raw_context.t -> Percentage.t + +val testnet_dictator : Raw_context.t -> Signature.Public_key_hash.t option + +val minimal_block_delay : Raw_context.t -> Period_repr.t + +val delay_increment_per_round : Raw_context.t -> Period_repr.t + +val sc_rollup_arith_pvm_enable : Raw_context.t -> bool + +val sc_rollup_origination_size : Raw_context.t -> int + +val sc_rollup_challenge_window_in_blocks : Raw_context.t -> int + +val sc_rollup_stake_amount : Raw_context.t -> Tez_repr.t + +val sc_rollup_commitment_period_in_blocks : Raw_context.t -> int + +val sc_rollup_max_lookahead_in_blocks : Raw_context.t -> int32 + +val sc_rollup_max_active_outbox_levels : Raw_context.t -> int32 + +val sc_rollup_max_outbox_messages_per_level : Raw_context.t -> int + +val sc_rollup_number_of_sections_in_dissection : Raw_context.t -> int + +val sc_rollup_max_number_of_parallel_games : Raw_context.t -> int + +val sc_rollup_riscv_pvm_enable : Raw_context.t -> bool + +val max_number_of_stored_cemented_commitments : Raw_context.t -> int + +val sc_rollup_timeout_period_in_blocks : Raw_context.t -> int + +val sc_rollup_reveal_activation_level : + Raw_context.t -> Constants_parametric_repr.sc_rollup_reveal_activation_level + +val sc_rollup_private_enable : Raw_context.t -> bool + +val dal_number_of_slots : Raw_context.t -> int + +val dal_enable : Raw_context.t -> bool + +val zk_rollup_enable : Raw_context.t -> bool + +val zk_rollup_min_pending_to_process : Raw_context.t -> int + +val zk_rollup_origination_size : Raw_context.t -> int + +val zk_rollup_max_ticket_payload_size : Raw_context.t -> int + +val adaptive_issuance_enable : Raw_context.t -> bool + +val adaptive_issuance_global_limit_of_staking_over_baking : Raw_context.t -> int + +val adaptive_issuance_edge_of_staking_over_delegation : Raw_context.t -> int + +val adaptive_issuance_launch_ema_threshold : Raw_context.t -> int32 + +val adaptive_issuance_activation_vote_enable : Raw_context.t -> bool + +val adaptive_issuance_rewards_params : + Raw_context.t -> Constants_parametric_repr.adaptive_rewards_params + +val adaptive_issuance_autostaking_enable : Raw_context.t -> bool + +val adaptive_issuance_force_activation : Raw_context.t -> bool + +val adaptive_issuance_ns_enable : Raw_context.t -> bool + +val direct_ticket_spending_enable : Raw_context.t -> bool + +(** The following accessors are not actual parameters, but constants that + derive from the protocol parameter. *) + +(** Delay, in cycles, before the current state of the stake impacts the + issuance rate.*) +val issuance_modification_delay : Raw_context.t -> int + +(** Delay, in cycles, before activation of AI after the voting EMA threshold is + reached *) +val adaptive_issuance_activation_delay : Raw_context.t -> int + +(** Tolerated period of inactivity, in cycles, before a delegate is + deactivated *) +val tolerated_inactivity_period : Raw_context.t -> int + +(** Delay before the activation of a consensus key, in cycles *) +val consensus_key_activation_delay : Raw_context.t -> int + +(** Number of cycles during which a misbehavior of a delegate will induce a + slashing of the funds that are currently in its frozen deposit. *) + +val slashable_deposits_period : Raw_context.t -> int diff --git a/src/proto_020_PsParisC/lib_protocol/context_binary_proof.ml b/src/proto_020_PsParisC/lib_protocol/context_binary_proof.ml new file mode 100644 index 000000000000..18f243ec7446 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/context_binary_proof.ml @@ -0,0 +1,57 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Expected_binary_proof + +let () = + register_error_kind + `Permanent + ~id:"Expected_binary_proof" + ~title:"Expected binary proof" + ~description:"An invalid proof has been submitted" + Data_encoding.empty + (function Expected_binary_proof -> Some () | _ -> None) + (fun () -> Expected_binary_proof) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4386 Extracted and + adapted from {!Tezos_context_memory}. Ideally, this function should + be exported there. + + In a nutshell, the context library exposed by the environment is + implemented such that it can verify proofs generated by both + [Context] and [Context_binary], and the only thing that + differentiate these proofs from its perspective is the second bit + of the [version] field of the proof. + + To ensure we only consider proofs computed against a binary tree, + we check said bit. This prevents a 32-ary proof to be accepted by + the protocol in the case where a given key-value store has the same + hash with both [Context] and [Context_binary] (something that + happens when the tree contains only one entry). *) +let check_is_binary proof = + let extract_bit v mask = Compare.Int.(v land mask <> 0) in + let binary_mask = 0b10 in + let is_binary = extract_bit proof.Context.Proof.version binary_mask in + error_unless is_binary Expected_binary_proof diff --git a/src/proto_020_PsParisC/lib_protocol/context_binary_proof.mli b/src/proto_020_PsParisC/lib_protocol/context_binary_proof.mli new file mode 100644 index 000000000000..2a2f10fb349b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/context_binary_proof.mli @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Expected_binary_proof + +(** [is_binary proof] will fail if [proof] does not claim to be a + Merkle proof of a binary tree compatible with the one defined in + [Context_binary]. + + {b Note:} It is very important to systematically check this before + calling the [verify_proof] exposed in the protocol, since this + function does not discriminate between binary and 32-ary + proofs. *) +val check_is_binary : Context.Proof.tree Context.Proof.t -> unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.ml b/src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.ml new file mode 100644 index 000000000000..b04e33e81046 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.ml @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += (* `Permanent *) Forbidden_tz4_delegate of Bls.Public_key_hash.t + +let () = + register_error_kind + `Branch + ~id:"delegate.forbidden_tz4" + ~title:"Forbidden delegate" + ~description:"Delegates are forbidden to be tz4 (BLS) accounts." + ~pp:(fun ppf implicit -> + Format.fprintf + ppf + "The delegate %a is forbidden as it is a BLS public key hash." + Bls.Public_key_hash.pp + implicit) + Data_encoding.(obj1 (req "delegate" Bls.Public_key_hash.encoding)) + (function Forbidden_tz4_delegate d -> Some d | _ -> None) + (fun d -> Forbidden_tz4_delegate d) + +let check_not_tz4 : Signature.Public_key_hash.t -> unit tzresult = + let open Result_syntax in + function + | Bls tz4 -> tzfail (Forbidden_tz4_delegate tz4) + | Ed25519 _ | Secp256k1 _ | P256 _ -> return_unit + +let find = Storage.Contract.Delegate.find + +type delegate_status = + | Delegate + | Delegated of Signature.Public_key_hash.t + | Undelegated + +let get_delegate_status ctxt pkh = + let open Lwt_result_syntax in + let+ delegate = find ctxt (Contract_repr.Implicit pkh) in + match delegate with + | None -> Undelegated + | Some delegate when Signature.Public_key_hash.(delegate = pkh) -> Delegate + | Some delegate -> Delegated delegate + +let is_delegate ctxt pkh = + let open Lwt_result_syntax in + let+ find_res = get_delegate_status ctxt pkh in + match find_res with Delegate -> true | Delegated _ | Undelegated -> false + +let init ctxt contract delegate = + let open Lwt_result_syntax in + let*? () = check_not_tz4 delegate in + let* ctxt = Storage.Contract.Delegate.init ctxt contract delegate in + let delegate_contract = Contract_repr.Implicit delegate in + let*! ctxt = + Storage.Contract.Delegated.add (ctxt, delegate_contract) contract + in + return ctxt + +let unlink ctxt contract = + let open Lwt_result_syntax in + let* delegate_opt = Storage.Contract.Delegate.find ctxt contract in + match delegate_opt with + | None -> return ctxt + | Some delegate -> + let delegate_contract = Contract_repr.Implicit delegate in + let*! ctxt = + Storage.Contract.Delegated.remove (ctxt, delegate_contract) contract + in + return ctxt + +let delete ctxt contract = + let open Lwt_result_syntax in + let* ctxt = unlink ctxt contract in + let*! ctxt = Storage.Contract.Delegate.remove ctxt contract in + return ctxt + +let set ctxt contract delegate = + let open Lwt_result_syntax in + let*? () = check_not_tz4 delegate in + let* ctxt = unlink ctxt contract in + let*! ctxt = Storage.Contract.Delegate.add ctxt contract delegate in + let delegate_contract = Contract_repr.Implicit delegate in + let*! ctxt = + Storage.Contract.Delegated.add (ctxt, delegate_contract) contract + in + return ctxt + +let delegated_contracts ctxt delegate = + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Delegated.elements (ctxt, contract) diff --git a/src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.mli b/src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.mli new file mode 100644 index 000000000000..eeecd7367325 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_delegate_storage.mli @@ -0,0 +1,98 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module deals with the delegates of a contract. It is + responsible for maintaining the tables {!Storage.Contract.Delegate} + and {!Storage.Contract.Delegated}. *) + +type error += + | (* `Permanent *) + Forbidden_tz4_delegate of Bls.Public_key_hash.t + (** Delegates cannot be tz4 accounts (i.e. BLS public key hashes). This + error is returned when we try to register such a delegate. *) + +(** [check_not_tz4 pkh] checks that [pkh] is not a BLS address. *) +val check_not_tz4 : Signature.public_key_hash -> unit tzresult + +(** [find ctxt contract] returns the delegate associated to [contract], or [None] + if [contract] has no delegate. *) +val find : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option tzresult Lwt.t + +(** [is_delegate ctxt pkh] returns whether [pkh] is a delegate. *) +val is_delegate : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + +(** [delegate_status] describes whether an implicit account is a delegate, or if + it has a delegate (i.e. other than itself), or has no delegate. *) +type delegate_status = + | Delegate + | Delegated of Signature.Public_key_hash.t + | Undelegated + +(** [get_delegate_status ctxt pkh] returns the delegation status associated to + [pkh]. *) +val get_delegate_status : + Raw_context.t -> Signature.Public_key_hash.t -> delegate_status tzresult Lwt.t + +(** [init ctxt contract delegate] sets the [delegate] associated to [contract]. + + This function assumes that [contract] does not have a delegate already. *) +val init : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + +(** [unlink ctxt contract] removes [contract] from the list of contracts that + delegated to [find ctxt contract], i.e. the output of [delegated_contracts]. + This function does not affect the value of the expression + [find ctxt contract]. + + This function assumes that [contract] is allocated. *) +val unlink : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t + +(** [delete ctxt contract] behaves as [unlink ctxt contract], but in addition + removes the association of the [contract] to its current delegate, leaving + the former without delegate. + + This function assumes that [contract] is allocated. *) +val delete : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t + +(** [set ctxt contract delegate] updates the [delegate] associated to [contract]. + + This function assumes that [contract] is allocated and has a delegate. *) +val set : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + +(** [delegated_contracts ctxt delegate] returns the list of contracts (implicit + or originated) that delegated to [delegate]. *) +val delegated_contracts : + Raw_context.t -> Signature.Public_key_hash.t -> Contract_repr.t list Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/contract_hash.ml b/src/proto_020_PsParisC/lib_protocol/contract_hash.ml new file mode 100644 index 000000000000..8583c1839303 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_hash.ml @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* 20 *) +let contract_hash = "\002\090\121" (* KT1(36) *) + +module H = + Blake2B.Make + (Base58) + (struct + let name = "Contract_hash" + + let title = "A contract ID" + + let b58check_prefix = contract_hash + + let size = Some 20 + end) + +include H +include Path_encoding.Make_hex (H) + +let () = Base58.check_encoded_prefix b58check_encoding "KT1" 36 + +let of_nonce nonce = + let data = + Data_encoding.Binary.to_bytes_exn Origination_nonce.encoding nonce + in + hash_bytes [data] diff --git a/src/proto_020_PsParisC/lib_protocol/contract_hash.mli b/src/proto_020_PsParisC/lib_protocol/contract_hash.mli new file mode 100644 index 000000000000..45a9f23cdf32 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_hash.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A specialized Blake2B implementation for hashing contract identifiers. *) + +include S.HASH + +(** [of_nonce nonce] is the contract address originated from [nonce]. *) +val of_nonce : Origination_nonce.t -> t diff --git a/src/proto_020_PsParisC/lib_protocol/contract_manager_storage.ml b/src/proto_020_PsParisC/lib_protocol/contract_manager_storage.ml new file mode 100644 index 000000000000..5e02b09d1969 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_manager_storage.ml @@ -0,0 +1,173 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Branch *) Unrevealed_manager_key of Contract_repr.t + | (* `Permanent *) + Inconsistent_hash of { + public_key : Signature.Public_key.t; + expected_hash : Signature.Public_key_hash.t; + provided_hash : Signature.Public_key_hash.t; + } + | (* `Branch *) Previously_revealed_key of Contract_repr.t + | (* `Branch *) Missing_manager_contract of Contract_repr.t + +let () = + register_error_kind + `Branch + ~id:"contract.unrevealed_key" + ~title:"Manager operation precedes key revelation" + ~description: + "One tried to apply a manager operation without revealing the manager \ + public key" + ~pp:(fun ppf s -> + Format.fprintf + ppf + "Unrevealed manager key for contract %a." + Contract_repr.pp + s) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Unrevealed_manager_key s -> Some s | _ -> None) + (fun s -> Unrevealed_manager_key s) ; + register_error_kind + `Permanent + ~id:"contract.manager.inconsistent_hash" + ~title:"Inconsistent public key hash" + ~description: + "A revealed manager public key is inconsistent with the announced hash" + ~pp:(fun ppf (k, eh, ph) -> + Format.fprintf + ppf + "The hash of the manager public key %s is not %a as announced but %a" + (Signature.Public_key.to_b58check k) + Signature.Public_key_hash.pp + ph + Signature.Public_key_hash.pp + eh) + Data_encoding.( + obj3 + (req "public_key" Signature.Public_key.encoding) + (req "expected_hash" Signature.Public_key_hash.encoding) + (req "provided_hash" Signature.Public_key_hash.encoding)) + (function + | Inconsistent_hash {public_key; expected_hash; provided_hash} -> + Some (public_key, expected_hash, provided_hash) + | _ -> None) + (fun (public_key, expected_hash, provided_hash) -> + Inconsistent_hash {public_key; expected_hash; provided_hash}) ; + register_error_kind + `Branch + ~id:"contract.previously_revealed_key" + ~title:"Manager operation already revealed" + ~description:"One tried to reveal twice a manager public key" + ~pp:(fun ppf s -> + Format.fprintf + ppf + "Previously revealed manager key for contract %a." + Contract_repr.pp + s) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Previously_revealed_key s -> Some s | _ -> None) + (fun s -> Previously_revealed_key s) ; + register_error_kind + `Branch + ~id:"contract.missing_manager_contract" + ~title:"Missing manager contract" + ~description:"The manager contract is missing from the storage" + ~pp:(fun ppf s -> + Format.fprintf + ppf + "The contract %a is missing from the storage." + Contract_repr.pp + s) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Missing_manager_contract s -> Some s | _ -> None) + (fun s -> Missing_manager_contract s) + +let init = Storage.Contract.Manager.init + +let is_manager_key_revealed c manager = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit manager in + let* key_opt = Storage.Contract.Manager.find c contract in + match key_opt with + | None -> return_false + | Some (Manager_repr.Hash _) -> return_false + | Some (Manager_repr.Public_key _) -> return_true + +let check_public_key public_key expected_hash = + let provided_hash = Signature.Public_key.hash public_key in + error_unless + (Signature.Public_key_hash.equal provided_hash expected_hash) + (Inconsistent_hash {public_key; expected_hash; provided_hash}) + +let reveal_manager_key ?(check_consistency = true) c manager public_key = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit manager in + let* key_opt = Storage.Contract.Manager.get c contract in + match key_opt with + | Public_key _ -> tzfail (Previously_revealed_key contract) + | Hash expected_hash -> + (* Ensure that the manager is equal to the retrieved hash. *) + let*? () = + error_unless + (Signature.Public_key_hash.equal manager expected_hash) + (Inconsistent_hash + {public_key; expected_hash; provided_hash = manager}) + in + (* TODO tezos/tezos#3078 + + We keep the consistency check and the optional argument to + preserve the semantics of reveal_manager_key prior to + tezos/tezos!5182, when called outside the scope of + [apply_operation]. + + Inside appply.ml, it is used with + ?check_consistency=false. Ultimately this parameter should go + away, and the split check_publick_key / reveal_manager_key + pattern has to be exported to usage outside apply.ml *) + let* () = + when_ check_consistency (fun () -> + Lwt.return @@ check_public_key public_key expected_hash) + in + let pk = Manager_repr.Public_key public_key in + Storage.Contract.Manager.update c contract pk + +let get_manager_key ?error ctxt pkh = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit pkh in + let* key_opt = Storage.Contract.Manager.find ctxt contract in + match key_opt with + | None -> ( + match error with + | None -> tzfail (Missing_manager_contract contract) + | Some error -> tzfail error) + | Some (Manager_repr.Hash _) -> ( + match error with + | None -> tzfail (Unrevealed_manager_key contract) + | Some error -> tzfail error) + | Some (Manager_repr.Public_key pk) -> return pk + +let remove_existing = Storage.Contract.Manager.remove_existing diff --git a/src/proto_020_PsParisC/lib_protocol/contract_manager_storage.mli b/src/proto_020_PsParisC/lib_protocol/contract_manager_storage.mli new file mode 100644 index 000000000000..6c3f74941dc3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_manager_storage.mli @@ -0,0 +1,85 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Branch *) Unrevealed_manager_key of Contract_repr.t + | (* `Permanent *) + Inconsistent_hash of { + public_key : Signature.Public_key.t; + expected_hash : Signature.Public_key_hash.t; + provided_hash : Signature.Public_key_hash.t; + } + | (* `Branch *) Previously_revealed_key of Contract_repr.t + | (* `Branch *) Missing_manager_contract of Contract_repr.t + +(** [init ctxt contract manager] associates [manager] to [contract]. This + function is undefined if [contract] has already a manager associated to it. +*) +val init : + Raw_context.t -> + Contract_repr.t -> + Manager_repr.manager_key -> + Raw_context.t tzresult Lwt.t + +val is_manager_key_revealed : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + +(** [check_publick_key pk pkh] asserts that the provided [pk] is + consistent with the expected public key hash [pkh], otherwise + fails with an [Inconsistent_hash] error. *) +val check_public_key : + Signature.Public_key.t -> Signature.Public_key_hash.t -> unit tzresult + +(** [reveal_manager_key ?check_consistency ctxt manager pk] reveals + the public key [pk] for a given unrevealed [manager]. If the + optional [?check_consistency] flag is set (and it is set by + default), it will re-check the same consistency checks than + [check_public_key] above, otherwise it will assume [manager] is + indeed the hash of [pk]. It is expected to fail with + [Previously_revealed_key contract] if [manager] was already + revealed, and with [Inconsistent_hash] if the (unrevealed) [manager] + doesn't match the expected hash of the implicit contract associated + to [pk]. *) +val reveal_manager_key : + ?check_consistency:bool -> + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t -> + Raw_context.t tzresult Lwt.t + +(** [get_manager_key ?error ctxt pkh] returns the revealed manager key of the + contract represented by [pkh]. When [error] is not provided this function + fails with "get_manager_key" error if [pkh] does not have a manager, and + with [Unrevealed_manager_key] error if the manager has not revealed its key. + When [error] is provided, the function fails with the provided [error] in + both cases. *) +val get_manager_key : + ?error:error -> + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t tzresult Lwt.t + +val remove_existing : + Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/contract_repr.ml b/src/proto_020_PsParisC/lib_protocol/contract_repr.ml new file mode 100644 index 000000000000..a14775416b61 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_repr.ml @@ -0,0 +1,235 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = + | Implicit of Signature.Public_key_hash.t + | Originated of Contract_hash.t + +include Compare.Make (struct + type nonrec t = t + + let compare l1 l2 = + match (l1, l2) with + | Implicit pkh1, Implicit pkh2 -> + Signature.Public_key_hash.compare pkh1 pkh2 + | Originated h1, Originated h2 -> Contract_hash.compare h1 h2 + | Implicit _, Originated _ -> -1 + | Originated _, Implicit _ -> 1 +end) + +let in_memory_size = + let open Cache_memory_helpers in + function + | Implicit _ -> h1w +! public_key_hash_in_memory_size + | Originated _ -> h1w +! blake2b_hash_size + +type error += Invalid_contract_notation of string (* `Permanent *) + +let to_b58check = function + | Implicit pbk -> Signature.Public_key_hash.to_b58check pbk + | Originated h -> Contract_hash.to_b58check h + +let implicit_of_b58data : Base58.data -> Signature.public_key_hash option = + function + | Ed25519.Public_key_hash.Data h -> Some (Signature.Ed25519 h) + | Secp256k1.Public_key_hash.Data h -> Some (Signature.Secp256k1 h) + | P256.Public_key_hash.Data h -> Some (Signature.P256 h) + | Bls.Public_key_hash.Data h -> Some (Signature.Bls h) + | _ -> None + +let originated_of_b58data = function + | Contract_hash.Data h -> Some h + | _ -> None + +let contract_of_b58data data = + match implicit_of_b58data data with + | Some pkh -> Some (Implicit pkh) + | None -> ( + match originated_of_b58data data with + | Some contract_hash -> Some (Originated contract_hash) + | None -> None) + +let of_b58check_gen ~of_b58data s = + let open Result_syntax in + match Base58.decode s with + | Some data -> ( + match of_b58data data with + | Some c -> return c + | None -> tzfail (Invalid_contract_notation s)) + | None -> tzfail (Invalid_contract_notation s) + +let of_b58check = of_b58check_gen ~of_b58data:contract_of_b58data + +let pp ppf = function + | Implicit pbk -> Signature.Public_key_hash.pp ppf pbk + | Originated h -> Contract_hash.pp ppf h + +let pp_short ppf = function + | Implicit pbk -> Signature.Public_key_hash.pp_short ppf pbk + | Originated h -> Contract_hash.pp_short ppf h + +let implicit_case ~proj ~inj = + let open Data_encoding in + case (Tag 0) ~title:"Implicit" Signature.Public_key_hash.encoding proj inj + +let originated_case ~proj ~inj = + let open Data_encoding in + case + (Tag 1) + (Fixed.add_padding Contract_hash.encoding 1) + ~title:"Originated" + proj + inj + +let cases is_contract to_contract = + [ + implicit_case + ~proj:(fun k -> + match is_contract k with Some (Implicit k) -> Some k | _ -> None) + ~inj:(fun k -> to_contract (Implicit k)); + originated_case + ~proj:(fun k -> + match is_contract k with Some (Originated k) -> Some k | _ -> None) + ~inj:(fun k -> to_contract (Originated k)); + ] + +let encoding_gen ~id_extra ~title_extra ~can_be ~cases ~to_b58check ~of_b58data + = + let open Data_encoding in + def + ("contract_id" ^ id_extra) + ~title:("A contract handle" ^ title_extra) + ~description: + ("A contract notation as given to an RPC or inside scripts. Can be a \ + base58 " ^ can_be) + @@ splitted + ~binary:(union ~tag_size:`Uint8 @@ cases (fun x -> Some x) (fun x -> x)) + ~json: + (conv + to_b58check + (fun s -> + match of_b58check_gen ~of_b58data s with + | Ok s -> s + | Error _ -> + Json.cannot_destruct "Invalid contract notation %S." s) + (string Plain)) + +let encoding = + encoding_gen + ~id_extra:"" + ~title_extra:"" + ~can_be:"implicit contract hash or a base58 originated contract hash." + ~cases + ~to_b58check + ~of_b58data:contract_of_b58data + +let implicit_encoding = + encoding_gen + ~id_extra:".implicit" + ~title_extra:" -- implicit account" + ~can_be:"implicit contract hash." + ~cases:(fun proj inj -> [implicit_case ~proj ~inj]) + ~to_b58check:Signature.Public_key_hash.to_b58check + ~of_b58data:implicit_of_b58data + +let originated_encoding = + encoding_gen + ~id_extra:".originated" + ~title_extra:" -- originated account" + ~can_be:"originated contract hash." + ~cases:(fun proj inj -> [originated_case ~proj ~inj]) + ~to_b58check:Contract_hash.to_b58check + ~of_b58data:originated_of_b58data + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"contract.invalid_contract_notation" + ~title:"Invalid contract notation" + ~pp:(fun ppf x -> Format.fprintf ppf "Invalid contract notation %S" x) + ~description: + "A malformed contract notation was given to an RPC or in a script." + (obj1 (req "notation" (string Plain))) + (function Invalid_contract_notation loc -> Some loc | _ -> None) + (fun loc -> Invalid_contract_notation loc) + +let originated_contract nonce = Originated (Contract_hash.of_nonce nonce) + +let originated_contracts + ~since: + Origination_nonce.{origination_index = first; operation_hash = first_hash} + ~until: + (Origination_nonce.{origination_index = last; operation_hash = last_hash} + as origination_nonce) = + assert (Operation_hash.equal first_hash last_hash) ; + let rec contracts acc origination_index = + if Compare.Int32.(origination_index < first) then acc + else + let origination_nonce = {origination_nonce with origination_index} in + let acc = Contract_hash.of_nonce origination_nonce :: acc in + contracts acc (Int32.pred origination_index) + in + contracts [] (Int32.pred last) + +let rpc_arg = + let construct = to_b58check in + let destruct hash = + Result.map_error (fun _ -> "Cannot parse contract id") (of_b58check hash) + in + RPC_arg.make + ~descr:"A contract identifier encoded in b58check." + ~name:"contract_id" + ~construct + ~destruct + () + +module Index = struct + type nonrec t = t + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + Option.bind + (Hex.to_bytes (`Hex key)) + (Data_encoding.Binary.of_bytes_opt encoding) + | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end + +(* Renamed exports. *) + +let of_b58data = contract_of_b58data diff --git a/src/proto_020_PsParisC/lib_protocol/contract_repr.mli b/src/proto_020_PsParisC/lib_protocol/contract_repr.mli new file mode 100644 index 000000000000..cd07cae82ce9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_repr.mli @@ -0,0 +1,98 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines identifiers for two basic types of contracts. It also + specifies how to compute originated contract's hash from origination + nonce. *) + +(** A contract is simply an account on the blockchain ledger. There are two + types of contracts: + - implicit contracts represent accounts of users of the blockchain; + - originated are special accounts with a Michelson script attached to + them. Every time a transaction is sent to an originated account, its + associated script is run in order to trigger some action in response. + + An implicit account is identified by the hash of the public key which was + used to create it. The owner of the corresponding private key is the + holder of the account. An originated contract's hash is derived from its + origination nonce (see below). *) +type t = + | Implicit of Signature.Public_key_hash.t + | Originated of Contract_hash.t + +include Compare.S with type t := t + +val in_memory_size : t -> Cache_memory_helpers.sint + +(** {2 Originated contracts} *) + +(** [originated_contract nonce] is the contract address originated from [nonce]. +*) +val originated_contract : Origination_nonce.t -> t + +(** [originated_contracts ~since ~until] is the contract addresses originated + from [since] until [until]. The operation hash of nonce [since] and [until] + must be the same or it will fail with an [assert]. [since] < [until] or the + returned list is empty *) +val originated_contracts : + since:Origination_nonce.t -> until:Origination_nonce.t -> Contract_hash.t list + +(** {2 Human readable notation} *) + +type error += Invalid_contract_notation of string (* `Permanent *) + +val to_b58check : t -> string + +val of_b58check : string -> t tzresult + +val of_b58data : Base58.data -> t option + +val pp : Format.formatter -> t -> unit + +val pp_short : Format.formatter -> t -> unit + +(** {2 Serializers} *) + +val encoding : t Data_encoding.t + +(** [implicit_encoding] is an encoding for public key hashes that is + compatible with the [encoding] of contracts for implicit accounts. *) +val implicit_encoding : Signature.Public_key_hash.t Data_encoding.t + +(** [originated_encoding] is an encoding for contract hashes that is + compatible with the [encoding] of contracts for originated accounts. *) +val originated_encoding : Contract_hash.t Data_encoding.t + +(** [cases f g] exports the {!type-Data_encoding.case}s used to define + {!encoding}. + + The only reason why we export that is to let {!Destination_repr.encoding} + use it. This allows the latter to be compatible with {!encoding}, which + is of key importance for backward compatibility reasons. *) +val cases : ('a -> t option) -> (t -> 'a) -> 'a Data_encoding.case list + +val rpc_arg : t RPC_arg.arg + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_020_PsParisC/lib_protocol/contract_services.ml b/src/proto_020_PsParisC/lib_protocol/contract_services.ml new file mode 100644 index 000000000000..1b4e68cc0277 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_services.ml @@ -0,0 +1,843 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = + (RPC_path.(open_root / "context" / "contracts") + : RPC_context.t RPC_path.context) + +let big_map_root = + (RPC_path.(open_root / "context" / "big_maps") + : RPC_context.t RPC_path.context) + +type info = { + balance : Tez.t; + delegate : public_key_hash option; + counter : Manager_counter.t option; + script : Script.t option; +} + +let info_encoding = + let open Data_encoding in + conv + (fun {balance; delegate; script; counter} -> + (balance, delegate, script, counter)) + (fun (balance, delegate, script, counter) -> + {balance; delegate; script; counter}) + @@ obj4 + (req "balance" Tez.encoding) + (opt "delegate" Signature.Public_key_hash.encoding) + (opt "script" Script.encoding) + (opt "counter" Manager_counter.encoding_for_RPCs) + +let legacy = Script_ir_translator_config.make ~legacy:true () + +module S = struct + open Data_encoding + + let balance = + RPC_service.get_service + ~description: + "Access the spendable balance of a contract, excluding frozen bonds." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "balance") + + let frozen_bonds = + RPC_service.get_service + ~description:"Access the frozen bonds of a contract." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "frozen_bonds") + + let balance_and_frozen_bonds = + RPC_service.get_service + ~description: + "Access the sum of the spendable balance and frozen bonds of a \ + contract. This sum is part of the contract's stake, and it is exactly \ + the contract's stake if the contract is not a delegate." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "balance_and_frozen_bonds") + + let staked_balance = + RPC_service.get_service + ~description: + "Access the staked balance of a contract. Returns None if the contract \ + is originated, or neither delegated nor a delegate." + ~query:RPC_query.empty + ~output:(option Tez.encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "staked_balance") + + let staking_numerator = + RPC_service.get_service + ~description: + "Returns an abstract representation of the contract's \ + total_delegated_stake." + ~query:RPC_query.empty + ~output:Staking_pseudotoken.For_RPC.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "staking_numerator") + + let unstaked_frozen_balance = + RPC_service.get_service + ~description: + "Access the balance of a contract that was requested for an unstake \ + operation, but is still frozen for the duration of the slashing \ + period. Returns None if the contract is originated." + ~query:RPC_query.empty + ~output:(option Tez.encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "unstaked_frozen_balance") + + let unstaked_finalizable_balance = + RPC_service.get_service + ~description: + "Access the balance of a contract that was requested for an unstake \ + operation, and is no longer frozen, which means it will appear in the \ + spendable balance of the contract after any \ + stake/unstake/finalize_unstake operation. Returns None if the \ + contract is originated." + ~query:RPC_query.empty + ~output:(option Tez.encoding) + RPC_path.( + custom_root /: Contract.rpc_arg / "unstaked_finalizable_balance") + + let unstake_requests = + RPC_service.get_service + ~description: + "Access the unstake requests of the contract. The requests that appear \ + in the finalizable field can be finalized, which means that the \ + contract can transfer these (no longer frozen) funds to their \ + spendable balance with a [finalize_unstake] operation call. Returns \ + None if there is no unstake request pending." + ~query:RPC_query.empty + ~output:(option Unstake_requests.prepared_finalize_unstake_encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "unstake_requests") + + let full_balance = + RPC_service.get_service + ~description: + "Access the full balance of a contract, including frozen bonds and \ + stake." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "full_balance") + + let manager_key = + RPC_service.get_service + ~description:"Access the manager of an implicit contract." + ~query:RPC_query.empty + ~output:(option Signature.Public_key.encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "manager_key") + + let delegate = + RPC_service.get_service + ~description:"Access the delegate of a contract, if any." + ~query:RPC_query.empty + ~output:Signature.Public_key_hash.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "delegate") + + let counter = + RPC_service.get_service + ~description:"Access the counter of a contract, if any." + ~query:RPC_query.empty + ~output:Manager_counter.encoding_for_RPCs + RPC_path.(custom_root /: Contract.rpc_arg / "counter") + + let script = + RPC_service.get_service + ~description:"Access the code and data of the contract." + ~query:RPC_query.empty + ~output:Script.encoding + RPC_path.(custom_root /: Contract.rpc_arg / "script") + + let storage = + RPC_service.get_service + ~description:"Access the data of the contract." + ~query:RPC_query.empty + ~output:Script.expr_encoding + RPC_path.(custom_root /: Contract.rpc_arg / "storage") + + type normalize_types_query = {normalize_types : bool} + + let normalize_types_query : normalize_types_query RPC_query.t = + let open RPC_query in + query (fun normalize_types -> {normalize_types}) + |+ flag + ~descr: + "Whether types should be normalized (annotations removed, combs \ + flattened) or kept as they appeared in the original script." + "normalize_types" + (fun t -> t.normalize_types) + |> seal + + let entrypoint_type = + RPC_service.get_service + ~description:"Return the type of the given entrypoint of the contract" + ~query:normalize_types_query + ~output:Script.expr_encoding + RPC_path.( + custom_root /: Contract.rpc_arg / "entrypoints" /: Entrypoint.rpc_arg) + + let list_entrypoints = + RPC_service.get_service + ~description:"Return the list of entrypoints of the contract" + ~query:normalize_types_query + ~output: + (obj2 + (dft + "unreachable" + (Data_encoding.list + (obj1 + (req + "path" + (Data_encoding.list + Michelson_v1_primitives.prim_encoding)))) + []) + (req "entrypoints" (assoc Script.expr_encoding))) + RPC_path.(custom_root /: Contract.rpc_arg / "entrypoints") + + let contract_big_map_get_opt = + RPC_service.post_service + ~description: + "Access the value associated with a key in a big map of the contract \ + (deprecated)." + ~query:RPC_query.empty + ~input: + (obj2 + (req "key" Script.expr_encoding) + (req "type" Script.expr_encoding)) + ~output:(option Script.expr_encoding) + RPC_path.(custom_root /: Contract.rpc_arg / "big_map_get") + + let big_map_get = + RPC_service.get_service + ~description:"Access the value associated with a key in a big map." + ~query:RPC_query.empty + ~output:Script.expr_encoding + RPC_path.(big_map_root /: Big_map.Id.rpc_arg /: Script_expr_hash.rpc_arg) + + type big_map_get_all_query = {offset : int option; length : int option} + + let rpc_arg_uint : int RPC_arg.t = + let open Result_syntax in + let int_of_string s = + let* i = + int_of_string_opt s + |> Option.to_result + ~none:(Format.sprintf "Cannot parse integer value %s" s) + in + if Compare.Int.(i < 0) then + Error (Format.sprintf "Negative integer: %d" i) + else Ok i + in + RPC_arg.make + ~name:"uint" + ~descr:"A non-negative integer (greater than or equal to 0)." + ~destruct:int_of_string + ~construct:string_of_int + () + + let big_map_get_all_query : big_map_get_all_query RPC_query.t = + let open RPC_query in + query (fun offset length -> {offset; length}) + |+ opt_field + ~descr: + "Skip the first [offset] values. Useful in combination with \ + [length] for pagination." + "offset" + rpc_arg_uint + (fun t -> t.offset) + |+ opt_field + ~descr: + "Only retrieve [length] values. Useful in combination with [offset] \ + for pagination." + "length" + rpc_arg_uint + (fun t -> t.length) + |> seal + + let big_map_get_all = + RPC_service.get_service + ~description: + "Get the (optionally paginated) list of values in a big map. Order of \ + values is unspecified, but is guaranteed to be consistent." + ~query:big_map_get_all_query + ~output:(list Script.expr_encoding) + RPC_path.(big_map_root /: Big_map.Id.rpc_arg) + + let info = + RPC_service.get_service + ~description:"Access the complete status of a contract." + ~query:normalize_types_query + ~output:info_encoding + RPC_path.(custom_root /: Contract.rpc_arg) + + let list = + RPC_service.get_service + ~description: + "All existing contracts (excluding empty implicit contracts)." + ~query:RPC_query.empty + ~output:(list Contract.encoding) + custom_root + + let estimated_own_pending_slashed_amount = + RPC_service.get_service + ~description: + "Returns the estimated own pending slashed amount (in mutez) of a \ + given contract." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.( + custom_root /: Contract.rpc_arg / "estimated_own_pending_slashed_amount") + + module Sapling = struct + (* + Sapling: these RPCs are like Sapling RPCs (sapling_services.ml) + specialized for contracts containing a single sapling state. + *) + + let single_sapling_get_id ctxt contract_id = + let open Lwt_result_syntax in + let* ctxt, script = Contract.get_script ctxt contract_id in + match script with + | None -> return (None, ctxt) + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let*! tzresult = + Script_ir_translator.parse_script + ctxt + ~elab_conf:legacy + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let*? Ex_script (Script script), ctxt = tzresult in + Lwt.return + @@ Script_ir_translator.get_single_sapling_state + ctxt + script.storage_type + script.storage + + let make_service + Sapling_services.S.Args.{name; description; query; output; f} = + let open Lwt_result_syntax in + let name = "single_sapling_" ^ name in + let path = RPC_path.(custom_root /: Contract.rpc_arg / name) in + let service = RPC_service.get_service ~description ~query ~output path in + ( service, + fun ctxt contract_id q () -> + match (contract_id : Contract.t) with + | Implicit _ -> return_none + | Originated contract_id -> + let* sapling_id, ctxt = single_sapling_get_id ctxt contract_id in + Option.map_es (fun sapling_id -> f ctxt sapling_id q) sapling_id + ) + + let get_diff = make_service Sapling_services.S.Args.get_diff + + let register () = + let reg chunked (service, f) = + Services_registration.opt_register1 ~chunked service f + in + reg false get_diff + + let mk_call1 (service, _f) ctxt block id q = + RPC_context.make_call1 service ctxt block id q () + end +end + +let register () = + let open Lwt_result_syntax in + let open Services_registration in + register0 ~chunked:true S.list (fun ctxt () () -> + let*! result = Contract.list ctxt in + return result) ; + let register_field_gen ~filter_contract ~wrap_result ~chunked s f = + opt_register1 ~chunked s (fun ctxt contract () () -> + filter_contract contract @@ fun filtered_contract -> + let*! exists = Contract.exists ctxt contract in + match exists with + | true -> f ctxt filtered_contract |> wrap_result + | false -> return_none) + in + let register_field_with_query_gen ~filter_contract ~wrap_result ~chunked s f = + opt_register1 ~chunked s (fun ctxt contract query () -> + filter_contract contract @@ fun filtered_contract -> + let*! exists = Contract.exists ctxt contract in + match exists with + | true -> f ctxt filtered_contract query |> wrap_result + | false -> return_none) + in + let register_field s = + register_field_gen + ~filter_contract:(fun c k -> k c) + ~wrap_result:(fun res -> + let+ value = res in + Option.some value) + s + in + let register_field_with_query s = + register_field_with_query_gen + ~filter_contract:(fun c k -> k c) + ~wrap_result:(fun res -> + let+ value = res in + Option.some value) + s + in + let register_opt_field s = + register_field_gen + ~filter_contract:(fun c k -> k c) + ~wrap_result:(fun res -> res) + s + in + let register_originated_opt_field s = + register_field_gen + ~filter_contract:(fun c k -> + match (c : Contract.t) with + | Implicit _ -> return_none + | Originated c -> k c) + ~wrap_result:(fun res -> res) + s + in + let do_big_map_get ctxt id key = + let open Script_ir_translator in + let ctxt = Gas.set_unlimited ctxt in + let* ctxt, types = Big_map.exists ctxt id in + match types with + | None -> return_none + | Some (_, value_type) -> ( + let*? Ex_ty value_type, ctxt = + parse_big_map_value_ty ctxt ~legacy:true (Micheline.root value_type) + in + let* _ctxt, value = Big_map.get_opt ctxt id key in + match value with + | None -> return_none + | Some value -> + let* value, ctxt = + parse_data + ctxt + ~elab_conf:legacy + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + value_type + (Micheline.root value) + in + let+ value, _ctxt = unparse_data ctxt Readable value_type value in + Some value) + in + let do_big_map_get_all ?offset ?length ctxt id = + let open Script_ir_translator in + let ctxt = Gas.set_unlimited ctxt in + let* ctxt, types = Big_map.exists ctxt id in + match types with + | None -> raise Not_found + | Some (_, value_type) -> + let*? Ex_ty value_type, ctxt = + parse_big_map_value_ty ctxt ~legacy:true (Micheline.root value_type) + in + let* ctxt, key_values = + Big_map.list_key_values ?offset ?length ctxt id + in + let+ _ctxt, rev_values = + List.fold_left_s + (fun acc (_key_hash, value) -> + let*? ctxt, rev_values = acc in + let* value, ctxt = + parse_data + ctxt + ~elab_conf:legacy + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + value_type + (Micheline.root value) + in + let+ value, ctxt = unparse_data ctxt Readable value_type value in + (ctxt, value :: rev_values)) + (Ok (ctxt, [])) + key_values + in + List.rev rev_values + in + register_field ~chunked:false S.balance Contract.get_balance ; + register_field ~chunked:false S.frozen_bonds Contract.get_frozen_bonds ; + register_field + ~chunked:false + S.balance_and_frozen_bonds + Contract.get_balance_and_frozen_bonds ; + register_field + ~chunked:false + S.staked_balance + Contract.For_RPC.get_staked_balance ; + register_field ~chunked:false S.staking_numerator (fun ctxt delegator -> + Staking_pseudotokens.For_RPC.staking_pseudotokens_balance ctxt ~delegator) ; + register_field + ~chunked:false + S.unstaked_frozen_balance + Contract.For_RPC.get_unstaked_frozen_balance ; + register_field + ~chunked:false + S.unstaked_finalizable_balance + Contract.For_RPC.get_unstaked_finalizable_balance ; + register_field ~chunked:false S.full_balance Contract.For_RPC.get_full_balance ; + register1 ~chunked:false S.unstake_requests (fun ctxt contract () () -> + let* result = Unstake_requests.prepare_finalize_unstake ctxt contract in + match result with + | None -> return_none + | Some {finalizable; unfinalizable} -> + let* unfinalizable = + Unstake_requests.For_RPC + .apply_slash_to_unstaked_unfinalizable_stored_requests + ctxt + unfinalizable + in + return_some Unstake_requests.{finalizable; unfinalizable}) ; + opt_register1 ~chunked:false S.manager_key (fun ctxt contract () () -> + match contract with + | Originated _ -> return_none + | Implicit mgr -> ( + let* is_revealed = Contract.is_manager_key_revealed ctxt mgr in + match is_revealed with + | false -> return_some None + | true -> + let+ key = Contract.get_manager_key ctxt mgr in + Some (Some key))) ; + register_opt_field ~chunked:false S.delegate Contract.Delegate.find ; + opt_register1 ~chunked:false S.counter (fun ctxt contract () () -> + match contract with + | Originated _ -> return_none + | Implicit mgr -> + let+ counter = Contract.get_counter ctxt mgr in + Some counter) ; + register_originated_opt_field ~chunked:true S.script (fun c v -> + let+ _, v = Contract.get_script c v in + v) ; + register_originated_opt_field ~chunked:true S.storage (fun ctxt contract -> + let* ctxt, script = Contract.get_script ctxt contract in + match script with + | None -> return_none + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + let* Ex_script (Script {storage; storage_type; _}), ctxt = + parse_script + ctxt + ~elab_conf:legacy + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let+ storage, _ctxt = + unparse_data ctxt Readable storage_type storage + in + Some storage) ; + opt_register2 + ~chunked:true + S.entrypoint_type + (fun ctxt v entrypoint {normalize_types} () -> + match (v : Contract.t) with + | Implicit _ -> return_none + | Originated v -> ( + let* _, expr = Contract.get_script_code ctxt v in + match expr with + | None -> return_none + | Some expr -> ( + let ctxt = Gas.set_unlimited ctxt in + let legacy = true in + let open Script_ir_translator in + let*? expr, _ = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + expr + in + let* {arg_type; _}, ctxt = parse_toplevel ctxt expr in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, _ = + parse_parameter_ty_and_entrypoints ctxt ~legacy arg_type + in + let*? r, ctxt = + Gas_monad.run ctxt + @@ Script_ir_translator.find_entrypoint + ~error_details:(Informative ()) + arg_type + entrypoints + entrypoint + in + r |> function + | Ok (Ex_ty_cstr {ty; original_type_expr; _}) -> + if normalize_types then + let*? ty_node, _ctxt = + Script_ir_unparser.unparse_ty ~loc:() ctxt ty + in + return_some (Micheline.strip_locations ty_node) + else + return_some (Micheline.strip_locations original_type_expr) + | Error _ -> return_none))) ; + opt_register1 + ~chunked:true + S.list_entrypoints + (fun ctxt v {normalize_types} () -> + match (v : Contract.t) with + | Implicit _ -> return_none + | Originated v -> ( + let* _, expr = Contract.get_script_code ctxt v in + match expr with + | None -> return_none + | Some expr -> + let ctxt = Gas.set_unlimited ctxt in + let legacy = true in + let open Script_ir_translator in + let*? expr, _ = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + expr + in + let* {arg_type; _}, ctxt = parse_toplevel ctxt expr in + Lwt.return + (let open Result_syntax in + let* Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, _ + = + parse_parameter_ty_and_entrypoints ctxt ~legacy arg_type + in + let unreachable_entrypoint, map = + Script_ir_translator.list_entrypoints_uncarbonated + arg_type + entrypoints + in + let* entrypoint_types, _ctxt = + Entrypoint.Map.fold_e + (fun entry + (Script_typed_ir.Ex_ty ty, original_type_expr) + (acc, ctxt) -> + let* ty_expr, ctxt = + if normalize_types then + let* ty_node, ctxt = + Script_ir_unparser.unparse_ty ~loc:() ctxt ty + in + return (Micheline.strip_locations ty_node, ctxt) + else + return + (Micheline.strip_locations original_type_expr, ctxt) + in + return ((Entrypoint.to_string entry, ty_expr) :: acc, ctxt)) + map + ([], ctxt) + in + return_some (unreachable_entrypoint, entrypoint_types)))) ; + opt_register1 + ~chunked:true + S.contract_big_map_get_opt + (fun ctxt contract () (key, key_type) -> + match (contract : Contract.t) with + | Implicit _ -> return_none + | Originated contract -> ( + let* ctxt, script = Contract.get_script ctxt contract in + let key_type_node = Micheline.root key_type in + let*? Ex_comparable_ty key_type, ctxt = + Script_ir_translator.parse_comparable_ty ctxt key_type_node + in + let* key, ctxt = + Script_ir_translator.parse_comparable_data + ctxt + key_type + (Micheline.root key) + in + let* key, ctxt = + Script_ir_translator.hash_comparable_data ctxt key_type key + in + match script with + | None -> return_none + | Some script -> ( + let ctxt = Gas.set_unlimited ctxt in + let open Script_ir_translator in + let* Ex_script (Script script), ctxt = + parse_script + ctxt + ~elab_conf:legacy + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let*? ids, _ctxt = + Script_ir_translator.collect_lazy_storage + ctxt + script.storage_type + script.storage + in + match Script_ir_translator.list_of_big_map_ids ids with + | [] | _ :: _ :: _ -> return_some None + | [id] -> + let+ result = do_big_map_get ctxt id key in + Option.some result))) ; + opt_register2 ~chunked:true S.big_map_get (fun ctxt id key () () -> + do_big_map_get ctxt id key) ; + register1 ~chunked:true S.big_map_get_all (fun ctxt id {offset; length} () -> + do_big_map_get_all ?offset ?length ctxt id) ; + register_field_with_query + ~chunked:false + S.info + (fun ctxt contract {normalize_types} -> + let* balance = Contract.get_balance ctxt contract in + let* delegate = Contract.Delegate.find ctxt contract in + match contract with + | Implicit manager -> + let+ counter = Contract.get_counter ctxt manager in + {balance; delegate; script = None; counter = Some counter} + | Originated contract -> ( + let* ctxt, script = Contract.get_script ctxt contract in + match script with + | None -> return {balance; delegate; script = None; counter = None} + | Some script -> + let ctxt = Gas.set_unlimited ctxt in + let+ script, _ctxt = + Script_ir_translator.parse_and_unparse_script_unaccounted + ctxt + ~legacy:true + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + Readable + ~normalize_types + script + in + {balance; delegate; script = Some script; counter = None})) ; + register1 + ~chunked:false + S.estimated_own_pending_slashed_amount + (fun ctxt contract () () -> + Contract.For_RPC.get_estimated_own_pending_slashed_amount ctxt contract) ; + + S.Sapling.register () + +let list ctxt block = RPC_context.make_call0 S.list ctxt block () () + +let info ctxt block contract ~normalize_types = + RPC_context.make_call1 S.info ctxt block contract {normalize_types} () + +let balance ctxt block contract = + RPC_context.make_call1 S.balance ctxt block contract () () + +let frozen_bonds ctxt block contract = + RPC_context.make_call1 S.frozen_bonds ctxt block contract () () + +let balance_and_frozen_bonds ctxt block contract = + RPC_context.make_call1 S.balance_and_frozen_bonds ctxt block contract () () + +let staked_balance ctxt block contract = + RPC_context.make_call1 S.staked_balance ctxt block contract () () + +let staking_numerator ctxt block contract = + RPC_context.make_call1 S.staking_numerator ctxt block contract () () + +let unstaked_frozen_balance ctxt block contract = + RPC_context.make_call1 S.unstaked_frozen_balance ctxt block contract () () + +let unstaked_finalizable_balance ctxt block contract = + RPC_context.make_call1 + S.unstaked_finalizable_balance + ctxt + block + contract + () + () + +let unstake_requests ctxt block contract = + RPC_context.make_call1 S.unstake_requests ctxt block contract () () + +let full_balance ctxt block contract = + RPC_context.make_call1 S.full_balance ctxt block contract () () + +let manager_key ctxt block mgr = + RPC_context.make_call1 S.manager_key ctxt block (Contract.Implicit mgr) () () + +let delegate ctxt block contract = + RPC_context.make_call1 S.delegate ctxt block contract () () + +let delegate_opt ctxt block contract = + RPC_context.make_opt_call1 S.delegate ctxt block contract () () + +let counter ctxt block mgr = + RPC_context.make_call1 S.counter ctxt block (Contract.Implicit mgr) () () + +let script ctxt block contract = + let contract = Contract.Originated contract in + RPC_context.make_call1 S.script ctxt block contract () () + +let script_opt ctxt block contract = + let contract = Contract.Originated contract in + RPC_context.make_opt_call1 S.script ctxt block contract () () + +let storage ctxt block contract = + let contract = Contract.Originated contract in + RPC_context.make_call1 S.storage ctxt block contract () () + +let estimated_own_pending_slashed_amount ctxt block contract = + let contract = Contract.Implicit contract in + RPC_context.make_call1 + S.estimated_own_pending_slashed_amount + ctxt + block + contract + () + () + +let entrypoint_type ctxt block contract entrypoint ~normalize_types = + RPC_context.make_call2 + S.entrypoint_type + ctxt + block + (Contract.Originated contract) + entrypoint + {normalize_types} + () + +let list_entrypoints ctxt block contract ~normalize_types = + RPC_context.make_call1 + S.list_entrypoints + ctxt + block + (Contract.Originated contract) + {normalize_types} + () + +let storage_opt ctxt block contract = + let contract = Contract.Originated contract in + RPC_context.make_opt_call1 S.storage ctxt block contract () () + +let big_map_get ctxt block id key = + RPC_context.make_call2 S.big_map_get ctxt block id key () () + +let contract_big_map_get_opt ctxt block contract key = + let contract = Contract.Originated contract in + RPC_context.make_call1 S.contract_big_map_get_opt ctxt block contract () key + +let single_sapling_get_diff ctxt block id ?offset_commitment ?offset_nullifier + () = + S.Sapling.(mk_call1 get_diff) + ctxt + block + (Contract.Originated id) + Sapling_services.{offset_commitment; offset_nullifier} diff --git a/src/proto_020_PsParisC/lib_protocol/contract_services.mli b/src/proto_020_PsParisC/lib_protocol/contract_services.mli new file mode 100644 index 000000000000..ead26032367e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_services.mli @@ -0,0 +1,187 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines RPC services to access the information associated to + contracts (balance, delegate, script, etc.). +*) + +open Alpha_context + +val list : 'a #RPC_context.simple -> 'a -> Contract.t list shell_tzresult Lwt.t + +type info = { + balance : Tez.t; + delegate : public_key_hash option; + counter : Manager_counter.t option; + script : Script.t option; +} + +val info_encoding : info Data_encoding.t + +val info : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + normalize_types:bool -> + info shell_tzresult Lwt.t + +val balance : + 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t + +val frozen_bonds : + 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t + +val balance_and_frozen_bonds : + 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t + +val staked_balance : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Tez.t option shell_tzresult Lwt.t + +val staking_numerator : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Staking_pseudotoken.t shell_tzresult Lwt.t + +val unstaked_frozen_balance : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Tez.t option shell_tzresult Lwt.t + +val unstaked_finalizable_balance : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Tez.t option shell_tzresult Lwt.t + +val unstake_requests : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + Unstake_requests.prepared_finalize_unstake option shell_tzresult Lwt.t + +val full_balance : + 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t + +val manager_key : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + public_key option shell_tzresult Lwt.t + +val delegate : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + public_key_hash shell_tzresult Lwt.t + +val delegate_opt : + 'a #RPC_context.simple -> + 'a -> + Contract.t -> + public_key_hash option shell_tzresult Lwt.t + +val counter : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + Manager_counter.t shell_tzresult Lwt.t + +val script : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + Script.t shell_tzresult Lwt.t + +val script_opt : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + Script.t option shell_tzresult Lwt.t + +val storage : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + Script.expr shell_tzresult Lwt.t + +val entrypoint_type : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + Entrypoint.t -> + normalize_types:bool -> + Script.expr shell_tzresult Lwt.t + +val list_entrypoints : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + normalize_types:bool -> + (Michelson_v1_primitives.prim list list * (string * Script.expr) list) + shell_tzresult + Lwt.t + +val storage_opt : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + Script.expr option shell_tzresult Lwt.t + +val estimated_own_pending_slashed_amount : + 'a #RPC_context.simple -> + 'a -> + Signature.public_key_hash -> + Tez.t shell_tzresult Lwt.t + +val big_map_get : + 'a #RPC_context.simple -> + 'a -> + Big_map.Id.t -> + Script_expr_hash.t -> + Script.expr shell_tzresult Lwt.t + +val contract_big_map_get_opt : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + Script.expr * Script.expr -> + Script.expr option shell_tzresult Lwt.t + +val single_sapling_get_diff : + 'a #RPC_context.simple -> + 'a -> + Contract_hash.t -> + ?offset_commitment:int64 -> + ?offset_nullifier:int64 -> + unit -> + (Sapling.root * Sapling.diff) shell_tzresult Lwt.t + +val register : unit -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/contract_storage.ml b/src/proto_020_PsParisC/lib_protocol/contract_storage.ml new file mode 100644 index 000000000000..e5a1a2f78d25 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_storage.ml @@ -0,0 +1,939 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Temporary *) + Balance_too_low of Contract_repr.t * Tez_repr.t * Tez_repr.t + | (* `Temporary *) + Counter_in_the_past of { + contract : Contract_repr.t; + expected : Manager_counter_repr.t; + found : Manager_counter_repr.t; + } + | (* `Branch *) + Counter_in_the_future of { + contract : Contract_repr.t; + expected : Manager_counter_repr.t; + found : Manager_counter_repr.t; + } + | (* `Temporary *) + Non_existing_contract of Contract_repr.t + | (* `Branch *) + Empty_implicit_contract of Signature.Public_key_hash.t + | (* `Branch *) + Empty_implicit_delegated_contract of + Signature.Public_key_hash.t + | (* `Permanent *) + Inconsistent_public_key of + Signature.Public_key.t * Signature.Public_key.t + | (* `Permanent *) Failure of string + +type error += + | (* `Permanent *) + Frozen_bonds_must_be_spent_at_once of + Contract_repr.t * Bond_id_repr.t + +let () = + register_error_kind + `Temporary + ~id:"contract.balance_too_low" + ~title:"Balance too low" + ~description:"An operation tried to spend more tokens than the contract has" + ~pp:(fun ppf (c, b, a) -> + Format.fprintf + ppf + "Balance of contract %a too low (%a) to spend %a" + Contract_repr.pp + c + Tez_repr.pp + b + Tez_repr.pp + a) + Data_encoding.( + obj3 + (req "contract" Contract_repr.encoding) + (req "balance" Tez_repr.encoding) + (req "amount" Tez_repr.encoding)) + (function Balance_too_low (c, b, a) -> Some (c, b, a) | _ -> None) + (fun (c, b, a) -> Balance_too_low (c, b, a)) ; + register_error_kind + `Temporary + ~id:"contract.counter_in_the_future" + ~title:"Invalid counter (not yet reached) in a manager operation" + ~description:"An operation assumed a contract counter in the future" + ~pp:(fun ppf (contract, exp, found) -> + Format.fprintf + ppf + "Counter %a not yet reached for contract %a (expected %a)" + Manager_counter_repr.pp + found + Contract_repr.pp + contract + Manager_counter_repr.pp + exp) + Data_encoding.( + obj3 + (req "contract" Contract_repr.encoding) + (req "expected" Manager_counter_repr.encoding_for_errors) + (req "found" Manager_counter_repr.encoding_for_errors)) + (function + | Counter_in_the_future {contract; expected; found} -> + Some (contract, expected, found) + | _ -> None) + (fun (contract, expected, found) -> + Counter_in_the_future {contract; expected; found}) ; + register_error_kind + `Branch + ~id:"contract.counter_in_the_past" + ~title:"Invalid counter (already used) in a manager operation" + ~description:"An operation assumed a contract counter in the past" + ~pp:(fun ppf (contract, exp, found) -> + Format.fprintf + ppf + "Counter %a already used for contract %a (expected %a)" + Manager_counter_repr.pp + found + Contract_repr.pp + contract + Manager_counter_repr.pp + exp) + Data_encoding.( + obj3 + (req "contract" Contract_repr.encoding) + (req "expected" Manager_counter_repr.encoding_for_errors) + (req "found" Manager_counter_repr.encoding_for_errors)) + (function + | Counter_in_the_past {contract; expected; found} -> + Some (contract, expected, found) + | _ -> None) + (fun (contract, expected, found) -> + Counter_in_the_past {contract; expected; found}) ; + register_error_kind + `Temporary + ~id:"contract.non_existing_contract" + ~title:"Non existing contract" + ~description: + "A contract handle is not present in the context (either it never was or \ + it has been destroyed)" + ~pp:(fun ppf contract -> + Format.fprintf ppf "Contract %a does not exist" Contract_repr.pp contract) + Data_encoding.(obj1 (req "contract" Contract_repr.encoding)) + (function Non_existing_contract c -> Some c | _ -> None) + (fun c -> Non_existing_contract c) ; + register_error_kind + `Permanent + ~id:"contract.manager.inconsistent_public_key" + ~title:"Inconsistent public key" + ~description: + "A provided manager public key is different with the public key stored \ + in the contract" + ~pp:(fun ppf (eh, ph) -> + Format.fprintf + ppf + "Expected manager public key %s but %s was provided" + (Signature.Public_key.to_b58check ph) + (Signature.Public_key.to_b58check eh)) + Data_encoding.( + obj2 + (req "public_key" Signature.Public_key.encoding) + (req "expected_public_key" Signature.Public_key.encoding)) + (function Inconsistent_public_key (eh, ph) -> Some (eh, ph) | _ -> None) + (fun (eh, ph) -> Inconsistent_public_key (eh, ph)) ; + register_error_kind + `Permanent + ~id:"contract.failure" + ~title:"Contract storage failure" + ~description:"Unexpected contract storage error" + ~pp:(fun ppf s -> Format.fprintf ppf "Contract_storage.Failure %S" s) + Data_encoding.(obj1 (req "message" @@ string Plain)) + (function Failure s -> Some s | _ -> None) + (fun s -> Failure s) ; + register_error_kind + `Branch + ~id:"implicit.empty_implicit_contract" + ~title:"Empty implicit contract" + ~description: + "No manager operations are allowed on an empty implicit contract." + ~pp:(fun ppf implicit -> + Format.fprintf + ppf + "Empty implicit contract (%a)" + Signature.Public_key_hash.pp + implicit) + Data_encoding.(obj1 (req "implicit" Signature.Public_key_hash.encoding)) + (function Empty_implicit_contract c -> Some c | _ -> None) + (fun c -> Empty_implicit_contract c) ; + register_error_kind + `Branch + ~id:"implicit.empty_implicit_delegated_contract" + ~title:"Empty implicit delegated contract" + ~description:"Emptying an implicit delegated account is not allowed." + ~pp:(fun ppf implicit -> + Format.fprintf + ppf + "Emptying implicit delegated contract (%a)" + Signature.Public_key_hash.pp + implicit) + Data_encoding.(obj1 (req "implicit" Signature.Public_key_hash.encoding)) + (function Empty_implicit_delegated_contract c -> Some c | _ -> None) + (fun c -> Empty_implicit_delegated_contract c) ; + register_error_kind + `Permanent + ~id:"frozen_bonds.must_be_spent_at_once" + ~title:"Partial spending of frozen bonds" + ~description:"Frozen bonds must be spent at once." + ~pp:(fun ppf (contract, bond_id) -> + Format.fprintf + ppf + "The frozen funds for contract (%a) and bond (%a) are not allowed to \ + be partially withdrawn. The amount withdrawn must be equal to the \ + entire deposit for the said bond." + Contract_repr.pp + contract + Bond_id_repr.pp + bond_id) + Data_encoding.( + obj2 + (req "contract" Contract_repr.encoding) + (req "bond_id" Bond_id_repr.encoding)) + (function + | Frozen_bonds_must_be_spent_at_once (c, b) -> Some (c, b) | _ -> None) + (fun (c, b) -> Frozen_bonds_must_be_spent_at_once (c, b)) + +let failwith msg = tzfail (Failure msg) + +module Legacy_big_map_diff = struct + (* + Big_map_diff receipt as it was represented in 006 and earlier. + It is kept here for now for backward compatibility of tools. *) + + type item = + | Update of { + big_map : Z.t; + diff_key : Script_repr.expr; + diff_key_hash : Script_expr_hash.t; + diff_value : Script_repr.expr option; + } + | Clear of Z.t + | Copy of {src : Z.t; dst : Z.t} + | Alloc of { + big_map : Z.t; + key_type : Script_repr.expr; + value_type : Script_repr.expr; + } + + type t = item list + + let item_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"update" + (obj5 + (req "action" (constant "update")) + (req "big_map" z) + (req "key_hash" Script_expr_hash.encoding) + (req "key" Script_repr.expr_encoding) + (opt "value" Script_repr.expr_encoding)) + (function + | Update {big_map; diff_key_hash; diff_key; diff_value} -> + Some ((), big_map, diff_key_hash, diff_key, diff_value) + | _ -> None) + (fun ((), big_map, diff_key_hash, diff_key, diff_value) -> + Update {big_map; diff_key_hash; diff_key; diff_value}); + case + (Tag 1) + ~title:"remove" + (obj2 (req "action" (constant "remove")) (req "big_map" z)) + (function Clear big_map -> Some ((), big_map) | _ -> None) + (fun ((), big_map) -> Clear big_map); + case + (Tag 2) + ~title:"copy" + (obj3 + (req "action" (constant "copy")) + (req "source_big_map" z) + (req "destination_big_map" z)) + (function Copy {src; dst} -> Some ((), src, dst) | _ -> None) + (fun ((), src, dst) -> Copy {src; dst}); + case + (Tag 3) + ~title:"alloc" + (obj4 + (req "action" (constant "alloc")) + (req "big_map" z) + (req "key_type" Script_repr.expr_encoding) + (req "value_type" Script_repr.expr_encoding)) + (function + | Alloc {big_map; key_type; value_type} -> + Some ((), big_map, key_type, value_type) + | _ -> None) + (fun ((), big_map, key_type, value_type) -> + Alloc {big_map; key_type; value_type}); + ] + + let encoding = Data_encoding.list item_encoding + + let to_lazy_storage_diff legacy_diffs = + let rev_head (diffs : (_ * (_, _, _) Lazy_storage_diff.diff) list) = + match diffs with + | [] -> [] + | (_, Remove) :: _ -> diffs + | (id, Update {init; updates}) :: rest -> + (id, Update {init; updates = List.rev updates}) :: rest + in + (* Invariant: + Updates are collected one by one, in reverse order, on the head diff + item. So only and exactly the head diff item has its updates reversed. + *) + List.fold_left + (fun (new_diff : (_ * (_, _, _) Lazy_storage_diff.diff) list) item -> + match item with + | Clear id -> (id, Lazy_storage_diff.Remove) :: rev_head new_diff + | Copy {src; dst} -> + let src = + Lazy_storage_kind.Big_map.Id + .of_legacy_USE_ONLY_IN_Legacy_big_map_diff + src + in + (dst, Lazy_storage_diff.Update {init = Copy {src}; updates = []}) + :: rev_head new_diff + | Alloc {big_map; key_type; value_type} -> + ( big_map, + Lazy_storage_diff.( + Update + { + init = Alloc Lazy_storage_kind.Big_map.{key_type; value_type}; + updates = []; + }) ) + :: rev_head new_diff + | Update + { + big_map; + diff_key = key; + diff_key_hash = key_hash; + diff_value = value; + } -> ( + match new_diff with + | (id, diff) :: rest when Compare.Z.(id = big_map) -> + let diff = + match diff with + | Remove -> assert false + | Update {init; updates} -> + let updates = + Lazy_storage_kind.Big_map.{key; key_hash; value} + :: updates + in + Lazy_storage_diff.Update {init; updates} + in + (id, diff) :: rest + | new_diff -> + let updates = + [Lazy_storage_kind.Big_map.{key; key_hash; value}] + in + (big_map, Update {init = Existing; updates}) + :: rev_head new_diff)) + [] + legacy_diffs + |> rev_head + |> List.rev_map (fun (id, diff) -> + let id = + Lazy_storage_kind.Big_map.Id + .of_legacy_USE_ONLY_IN_Legacy_big_map_diff + id + in + Lazy_storage_diff.make Lazy_storage_kind.Big_map id diff) + + let of_lazy_storage_diff diffs = + List.fold_left + (fun legacy_diffs (Lazy_storage_diff.Item (kind, id, diff)) -> + let diffs = + match kind with + | Lazy_storage_kind.Big_map -> ( + let id = + Lazy_storage_kind.Big_map.Id + .to_legacy_USE_ONLY_IN_Legacy_big_map_diff + id + in + match diff with + | Remove -> [Clear id] + | Update {init; updates} -> ( + let updates = + List.rev_map + (fun {Lazy_storage_kind.Big_map.key; key_hash; value} -> + Update + { + big_map = id; + diff_key = key; + diff_key_hash = key_hash; + diff_value = value; + }) + updates + in + match init with + | Existing -> updates + | Copy {src} -> + let src = + Lazy_storage_kind.Big_map.Id + .to_legacy_USE_ONLY_IN_Legacy_big_map_diff + src + in + Copy {src; dst = id} :: updates + | Alloc {key_type; value_type} -> + Alloc {big_map = id; key_type; value_type} :: updates)) + | _ -> (* Not a Big_map *) [] + in + diffs :: legacy_diffs) + [] + diffs + |> List.rev |> List.flatten +end + +let update_script_lazy_storage c = function + | None -> return (c, Z.zero) + | Some diffs -> Lazy_storage_diff.apply c diffs + +let raw_originate c ~prepaid_bootstrap_storage + (* Free space for bootstrap contracts *) contract ~script = + let open Lwt_result_syntax in + let contract = Contract_repr.Originated contract in + let* c = Storage.Contract.Spendable_balance.init c contract Tez_repr.zero in + let {Script_repr.code; storage}, lazy_storage_diff = script in + let* c, code_size = Storage.Contract.Code.init c contract code in + let* c, storage_size = Storage.Contract.Storage.init c contract storage in + let* c, lazy_storage_size = update_script_lazy_storage c lazy_storage_diff in + let total_size = + Z.add (Z.add (Z.of_int code_size) (Z.of_int storage_size)) lazy_storage_size + in + assert (Compare.Z.(total_size >= Z.zero)) ; + let prepaid_bootstrap_storage = + if prepaid_bootstrap_storage then total_size else Z.zero + in + let* c = + Storage.Contract.Paid_storage_space.init + c + contract + prepaid_bootstrap_storage + in + Storage.Contract.Used_storage_space.init c contract total_size + +let create_implicit c manager ~balance = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit manager in + let* counter = Storage.Contract.Global_counter.get c in + let* c = Storage.Contract.Counter.init c contract counter in + let* c = Storage.Contract.Spendable_balance.init c contract balance in + Contract_manager_storage.init c contract (Manager_repr.Hash manager) + +let delete c contract = + let open Lwt_result_syntax in + match contract with + | Contract_repr.Originated _ -> + (* For non implicit contract Big_map should be cleared *) + failwith "Non implicit contracts cannot be removed" + | Implicit _ -> + (* Implicit contract do not have: [Code], [Storage], + [Paid_storage_space] and [Used_storage_space]. We do not need + to delete them. Futhermore, these storages space are + carbonated, thus, require gas to be deleted (even when they + do not exist). An implicit contract deletion should not cost + extra gas. *) + let* c = Contract_delegate_storage.unlink c contract in + let update local = + let* local = + Storage.Contract.Spendable_balance.Local.remove_existing local + in + let* local = Storage.Contract.Manager.Local.remove_existing local in + Storage.Contract.Counter.Local.remove_existing local + in + let+ c, () = + Storage.Contract.with_local_context c contract (fun local -> + let+ local = update local in + (local, ())) + in + c + +let allocated c contract = Storage.Contract.Spendable_balance.mem c contract + +let exists c contract = + match contract with + | Contract_repr.Implicit _ -> Lwt.return_true + | Originated _ -> allocated c contract + +let must_exist c contract = + let open Lwt_syntax in + let* exists_contract = exists c contract in + match exists_contract with + | true -> return_unit + | false -> tzfail (Non_existing_contract contract) + +let must_be_allocated c contract = + let open Lwt_syntax in + let* is_allocated = allocated c contract in + match is_allocated with + | true -> return_unit + | false -> ( + match contract with + | Implicit pkh -> tzfail (Empty_implicit_contract pkh) + | Originated _ -> tzfail (Non_existing_contract contract)) + +let list c = Storage.Contract.list c + +let fresh_contract_from_current_nonce c = + let open Result_syntax in + let+ c, nonce = Raw_context.increment_origination_nonce c in + (c, Contract_hash.of_nonce nonce) + +let originated_from_current_nonce ~since:ctxt_since ~until:ctxt_until = + let open Lwt_result_syntax in + let*? since = Raw_context.get_origination_nonce ctxt_since in + let*? until = Raw_context.get_origination_nonce ctxt_until in + let*! result = + List.filter_s + (fun contract -> exists ctxt_until (Contract_repr.Originated contract)) + (Contract_repr.originated_contracts ~since ~until) + in + return result + +let check_counter_increment c manager counter = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit manager in + let* contract_counter = Storage.Contract.Counter.get c contract in + let expected = Manager_counter_repr.succ contract_counter in + if Manager_counter_repr.(expected = counter) then return_unit + else if Manager_counter_repr.(expected > counter) then + tzfail (Counter_in_the_past {contract; expected; found = counter}) + else tzfail (Counter_in_the_future {contract; expected; found = counter}) + +let increment_counter c manager = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit manager in + let* global_counter = Storage.Contract.Global_counter.get c in + let* c = + Storage.Contract.Global_counter.update + c + (Manager_counter_repr.succ global_counter) + in + let* contract_counter = Storage.Contract.Counter.get c contract in + Storage.Contract.Counter.update + c + contract + (Manager_counter_repr.succ contract_counter) + +let get_script_code c contract_hash = + let contract = Contract_repr.Originated contract_hash in + Storage.Contract.Code.find c contract + +let get_script c contract_hash = + let open Lwt_result_syntax in + let contract = Contract_repr.Originated contract_hash in + let* c, code = Storage.Contract.Code.find c contract in + let* c, storage = Storage.Contract.Storage.find c contract in + match (code, storage) with + | None, None -> return (c, None) + | Some code, Some storage -> return (c, Some {Script_repr.code; storage}) + | None, Some _ | Some _, None -> failwith "get_script" + +let get_storage ctxt contract_hash = + let open Lwt_result_syntax in + let contract = Contract_repr.Originated contract_hash in + let* result = Storage.Contract.Storage.find ctxt contract in + match result with + | ctxt, None -> return (ctxt, None) + | ctxt, Some storage -> + let*? ctxt = + Raw_context.consume_gas ctxt (Script_repr.force_decode_cost storage) + in + let*? storage = Script_repr.force_decode storage in + return (ctxt, Some storage) + +let get_counter c manager = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit manager in + let* counter_opt = Storage.Contract.Counter.find c contract in + match counter_opt with + | None -> ( + match contract with + | Contract_repr.Implicit _ -> Storage.Contract.Global_counter.get c + | Originated _ -> failwith "get_counter") + | Some v -> return v + +let get_balance c contract = + let open Lwt_result_syntax in + let* balance_opt = Storage.Contract.Spendable_balance.find c contract in + match balance_opt with + | None -> ( + match contract with + | Implicit _ -> return Tez_repr.zero + | Originated _ -> failwith "get_balance") + | Some v -> return v + +let get_balance_carbonated c contract = + (* Reading an int64 from /contracts/index//balance *) + let open Lwt_result_syntax in + let*? c = + Raw_context.consume_gas + c + (Storage_costs.read_access ~path_length:4 ~read_bytes:8) + in + let* balance = get_balance c contract in + return (c, balance) + +let check_allocated_and_get_balance c pkh = + let open Lwt_result_syntax in + let* balance_opt = + Storage.Contract.Spendable_balance.find c (Contract_repr.Implicit pkh) + in + match balance_opt with + | None -> tzfail (Empty_implicit_contract pkh) + | Some balance -> return balance + +let update_script_storage c contract_hash storage lazy_storage_diff = + let open Lwt_result_syntax in + let contract = Contract_repr.Originated contract_hash in + let storage = Script_repr.lazy_expr storage in + let* c, lazy_storage_size_diff = + update_script_lazy_storage c lazy_storage_diff + in + let* c, size_diff = Storage.Contract.Storage.update c contract storage in + let* previous_size = Storage.Contract.Used_storage_space.get c contract in + let new_size = + Z.add previous_size (Z.add lazy_storage_size_diff (Z.of_int size_diff)) + in + Storage.Contract.Used_storage_space.update c contract new_size + +let spend_from_balance contract balance amount = + record_trace + (Balance_too_low (contract, balance, amount)) + Tez_repr.(balance -? amount) + +let check_emptiable c contract = + let open Lwt_result_syntax in + match contract with + | Contract_repr.Originated _ -> return_unit + | Implicit pkh -> ( + let* delegate = Contract_delegate_storage.find c contract in + match delegate with + | Some pkh' -> + if Signature.Public_key_hash.equal pkh pkh' then return_unit + else + (* Delegated implicit accounts cannot be emptied *) + tzfail (Empty_implicit_delegated_contract pkh) + | None -> return_unit) + +let spend_only_call_from_token c contract amount = + let open Lwt_result_syntax in + let* balance = Storage.Contract.Spendable_balance.find c contract in + let balance = Option.value balance ~default:Tez_repr.zero in + let*? new_balance = spend_from_balance contract balance amount in + let* c = Storage.Contract.Spendable_balance.update c contract new_balance in + let* c = Stake_storage.remove_contract_delegated_stake c contract amount in + let+ () = + when_ + Tez_repr.(new_balance <= Tez_repr.zero) + (fun () -> check_emptiable c contract) + in + c + +(* [Tez_repr.(amount <> zero)] is a precondition of this function. It ensures that + no entry associating a null balance to an implicit contract exists in the map + [Storage.Contract.Spendable_balance]. *) +let credit_only_call_from_token c contract amount = + let open Lwt_result_syntax in + let* balance_opt = Storage.Contract.Spendable_balance.find c contract in + match balance_opt with + | None -> ( + match contract with + | Originated _ -> tzfail (Non_existing_contract contract) + | Implicit manager -> create_implicit c manager ~balance:amount) + | Some balance -> + let*? balance = Tez_repr.(amount +? balance) in + let* c = Storage.Contract.Spendable_balance.update c contract balance in + Stake_storage.add_contract_delegated_stake c contract amount + +let init c = + let open Lwt_result_syntax in + let* c = Storage.Contract.Global_counter.init c Manager_counter_repr.init in + Lazy_storage_diff.init c + +let used_storage_space c contract = + let open Lwt_result_syntax in + let+ value = Storage.Contract.Used_storage_space.find c contract in + Option.value ~default:Z.zero value + +let paid_storage_space c contract = + let open Lwt_result_syntax in + let+ value = Storage.Contract.Paid_storage_space.find c contract in + Option.value ~default:Z.zero value + +let set_paid_storage_space_and_return_fees_to_pay c contract new_storage_space = + let open Lwt_result_syntax in + let* already_paid_space = + Storage.Contract.Paid_storage_space.get c contract + in + if Compare.Z.(already_paid_space >= new_storage_space) then return (Z.zero, c) + else + let to_pay = Z.sub new_storage_space already_paid_space in + let+ c = + Storage.Contract.Paid_storage_space.update c contract new_storage_space + in + (to_pay, c) + +let increase_paid_storage c contract_hash ~amount_in_bytes:storage_incr = + let open Lwt_result_syntax in + let contract = Contract_repr.Originated contract_hash in + let* already_paid_space = + Storage.Contract.Paid_storage_space.get c contract + in + let new_storage_space = Z.add already_paid_space storage_incr in + Storage.Contract.Paid_storage_space.update c contract new_storage_space + +let get_frozen_bonds ctxt contract = + let open Lwt_result_syntax in + let+ value = Storage.Contract.Total_frozen_bonds.find ctxt contract in + Option.value ~default:Tez_repr.zero value + +let get_balance_and_frozen_bonds ctxt contract = + let open Lwt_result_syntax in + let* balance = Storage.Contract.Spendable_balance.get ctxt contract in + let* total_bonds = get_frozen_bonds ctxt contract in + Lwt.return Tez_repr.(balance +? total_bonds) + +let bond_allocated ctxt contract bond_id = + Storage.Contract.Frozen_bonds.mem (ctxt, contract) bond_id + +let find_bond ctxt contract bond_id = + Storage.Contract.Frozen_bonds.find (ctxt, contract) bond_id + +(** PRE : [amount > 0], fulfilled by unique caller [Token.transfer]. *) +let spend_bond_only_call_from_token ctxt contract bond_id amount = + let open Lwt_result_syntax in + let* () = + fail_when Tez_repr.(amount = zero) (Failure "Expecting : [amount > 0]") + in + let* ctxt = + Stake_storage.remove_contract_delegated_stake ctxt contract amount + in + let* ctxt, frozen_bonds = + Storage.Contract.Frozen_bonds.get (ctxt, contract) bond_id + in + let*? () = + error_when + Tez_repr.(frozen_bonds <> amount) + (Frozen_bonds_must_be_spent_at_once (contract, bond_id)) + in + let* ctxt, _ = + Storage.Contract.Frozen_bonds.remove_existing (ctxt, contract) bond_id + in + let* total = Storage.Contract.Total_frozen_bonds.get ctxt contract in + let*? new_total = Tez_repr.(total -? amount) in + if Tez_repr.(new_total = zero) then + Storage.Contract.Total_frozen_bonds.remove_existing ctxt contract + else Storage.Contract.Total_frozen_bonds.update ctxt contract new_total + +(** PRE : [amount > 0], fulfilled by unique caller [Token.transfer]. *) +let credit_bond_only_call_from_token ctxt contract bond_id amount = + let open Lwt_result_syntax in + let* () = + fail_when Tez_repr.(amount = zero) (Failure "Expecting : [amount > 0]") + in + let* ctxt = Stake_storage.add_contract_delegated_stake ctxt contract amount in + let* ctxt, _ = + let* ctxt, frozen_bonds_opt = + Storage.Contract.Frozen_bonds.find (ctxt, contract) bond_id + in + match frozen_bonds_opt with + | None -> Storage.Contract.Frozen_bonds.init (ctxt, contract) bond_id amount + | Some frozen_bonds -> + let*? new_amount = Tez_repr.(frozen_bonds +? amount) in + Storage.Contract.Frozen_bonds.update (ctxt, contract) bond_id new_amount + in + let* total_opt = Storage.Contract.Total_frozen_bonds.find ctxt contract in + match total_opt with + | None -> Storage.Contract.Total_frozen_bonds.init ctxt contract amount + | Some total -> + let*? new_total = Tez_repr.(total +? amount) in + Storage.Contract.Total_frozen_bonds.update ctxt contract new_total + +let has_frozen_bonds ctxt contract = + let open Lwt_result_syntax in + let*! result = Storage.Contract.Total_frozen_bonds.mem ctxt contract in + return result + +let has_frozen_deposits ctxt contract = + let open Lwt_result_syntax in + let* pseudo = Storage.Contract.Staking_pseudotokens.find ctxt contract in + match pseudo with + | Some v when not Staking_pseudotoken_repr.(v = zero) -> return_true + | _ -> ( + let* requests = Storage.Contract.Unstake_requests.find ctxt contract in + match requests with + | None | Some {delegate = _; requests = []} -> return_false + | Some _ -> return_true) + +let fold_on_bond_ids ctxt contract = + Storage.Contract.fold_bond_ids (ctxt, contract) + +(** Indicate whether the given implicit contract should avoid deletion + when it is emptied. *) +let should_keep_empty_implicit_contract ctxt contract = + let open Lwt_result_syntax in + let* has_frozen_bonds = has_frozen_bonds ctxt contract in + let* has_frozen_deposits = has_frozen_deposits ctxt contract in + if has_frozen_bonds || has_frozen_deposits then return_true + else + (* full balance of contract is zero. *) + let* delegate_opt = Contract_delegate_storage.find ctxt contract in + match delegate_opt with + | Some _ -> + (* Here, we know that the contract delegates to itself. + Indeed, it does not delegate to a different one, because + the balance of such contracts cannot be zero (see + {!spend_only_call_from_token}), hence the stake of such + contracts cannot be zero either. *) + return_true + | None -> + (* Delete empty implicit contract. *) + return_false + +let ensure_deallocated_if_empty ctxt contract = + let open Lwt_result_syntax in + match contract with + | Contract_repr.Originated _ -> + return ctxt (* Never delete originated contracts *) + | Implicit _ -> ( + let* balance_opt = + Storage.Contract.Spendable_balance.find ctxt contract + in + match balance_opt with + | None -> + (* Nothing to do, contract is not allocated. *) + return ctxt + | Some balance -> + if Tez_repr.(balance <> zero) then return ctxt + else + let* keep_contract = + should_keep_empty_implicit_contract ctxt contract + in + if keep_contract then return ctxt else delete ctxt contract) + +let simulate_spending ctxt ~balance ~amount source = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit source in + let*? new_balance = spend_from_balance contract balance amount in + let* still_allocated = + if Tez_repr.(new_balance > zero) then return_true + else + let* () = check_emptiable ctxt contract in + should_keep_empty_implicit_contract ctxt contract + in + return (new_balance, still_allocated) + +let get_total_supply ctxt = Storage.Contract.Total_supply.get ctxt + +module For_RPC = struct + let get_staked_balance ctxt = + let open Lwt_result_syntax in + function + | Contract_repr.Originated _ -> return_none + | Implicit _ as contract -> ( + let* delegate_opt = Storage.Contract.Delegate.find ctxt contract in + match delegate_opt with + | None -> return_none + | Some delegate -> + let* own_frozen_deposits = + Staking_pseudotokens_storage.For_RPC.staked_balance + ctxt + ~delegate + ~contract + in + return (Some own_frozen_deposits)) + + let get_unstaked_balance ctxt = + let open Lwt_result_syntax in + function + | Contract_repr.Originated _ -> return_none + | Implicit _ as contract -> ( + let* result = + Unstake_requests_storage.prepare_finalize_unstake + ctxt + ~for_next_cycle_use_only_after_slashing:false + contract + in + match result with + | None -> return_some (Tez_repr.zero, Tez_repr.zero) + | Some {finalizable; unfinalizable} -> + let* unfinalizable_requests = + Unstake_requests_storage.For_RPC + .apply_slash_to_unstaked_unfinalizable + ctxt + unfinalizable + in + let*? sum_unfinalizable = + List.fold_left_e + (fun acc (_cycle, tz) -> Tez_repr.(acc +? tz)) + Tez_repr.zero + unfinalizable_requests + in + let*? sum_finalizable = + List.fold_left_e + (fun acc (_, _cycle, tz) -> Tez_repr.(acc +? tz)) + Tez_repr.zero + finalizable + in + return_some (sum_unfinalizable, sum_finalizable)) + + let get_unstaked_frozen_balance ctxt contract = + let open Lwt_result_syntax in + let* balance_opt = get_unstaked_balance ctxt contract in + match balance_opt with + | None -> return_none + | Some (amount, _) -> return_some amount + + let get_unstaked_finalizable_balance ctxt contract = + let open Lwt_result_syntax in + let* balance_opt = get_unstaked_balance ctxt contract in + match balance_opt with + | None -> return_none + | Some (_, amount) -> return_some amount + + let get_full_balance ctxt contract = + let open Lwt_result_syntax in + let* balance_n_frozen = get_balance_and_frozen_bonds ctxt contract in + let* s = get_staked_balance ctxt contract in + let staked = Option.value ~default:Tez_repr.zero s in + let* us = get_unstaked_balance ctxt contract in + let u_frozen, u_final = + Option.value ~default:(Tez_repr.zero, Tez_repr.zero) us + in + Tez_repr.( + let*? x = balance_n_frozen +? staked in + let*? y = u_frozen +? x in + let*? z = u_final +? y in + return z) +end diff --git a/src/proto_020_PsParisC/lib_protocol/contract_storage.mli b/src/proto_020_PsParisC/lib_protocol/contract_storage.mli new file mode 100644 index 000000000000..9635021e1739 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contract_storage.mli @@ -0,0 +1,343 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Low-level handlers of raw contexts for base operations on + contracts. *) + +type error += + | (* `Temporary *) + Balance_too_low of Contract_repr.t * Tez_repr.t * Tez_repr.t + | (* `Temporary *) + Counter_in_the_past of { + contract : Contract_repr.t; + expected : Manager_counter_repr.t; + found : Manager_counter_repr.t; + } + | (* `Branch *) + Counter_in_the_future of { + contract : Contract_repr.t; + expected : Manager_counter_repr.t; + found : Manager_counter_repr.t; + } + | (* `Temporary *) + Non_existing_contract of Contract_repr.t + | (* `Permanent *) + Inconsistent_public_key of + Signature.Public_key.t * Signature.Public_key.t + | (* `Permanent *) Failure of string + | (* `Branch *) + Empty_implicit_contract of Signature.Public_key_hash.t + | (* `Branch *) + Empty_implicit_delegated_contract of + Signature.Public_key_hash.t + +(** [allocated ctxt contract] returns [true] if and only if the + contract is stored in {!Storage.Contract.Spendable_balance}. *) +val allocated : Raw_context.t -> Contract_repr.t -> bool Lwt.t + +(** [exists ctxt contract] returns [true] if and only if either the + contract is implicit or it is (originated and) {!allocated}. *) +val exists : Raw_context.t -> Contract_repr.t -> bool Lwt.t + +(** [must_exist ctxt contract] fails with the [Non_existing_contract] error if + [exists ctxt contract] returns [false]. Even though this function is + gas-free, it is always called in a context where some gas consumption is + guaranteed whenever necessary. The first context is that of a transfer + operation, and in that case the base cost of a manager operation + ([Micheclson_v1_gas.Cost_of.manager_operation]) is consumed. The second + context is that of an activation operation, and in that case no gas needs to + be consumed since that operation is not a manager operation. *) +val must_exist : Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t + +(** [must_be_allocated ctxt contract] fails when the contract is not + allocated. It fails with [Non_existing_contract] if the contract is + originated, and it fails with [Empty_implicit_contract] if the + contract is implicit. *) +val must_be_allocated : Raw_context.t -> Contract_repr.t -> unit tzresult Lwt.t + +val list : Raw_context.t -> Contract_repr.t list Lwt.t + +val check_counter_increment : + Raw_context.t -> + Signature.Public_key_hash.t -> + Manager_counter_repr.t -> + unit tzresult Lwt.t + +val increment_counter : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t + +(** [get_balance ctxt contract] returns the balance of spendable tez owned by + [contract] given raw context [ctxt]. This does not include the contract's + frozen balances. *) +val get_balance : Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t + +val get_balance_carbonated : + Raw_context.t -> + Contract_repr.t -> + (Raw_context.t * Tez_repr.t) tzresult Lwt.t + +(** Return the balance of spendable tez owned by the Implicit contract + of the given [public_key_hash]. + + @return [Error Empty_implicit_contract] if the contract is not + allocated in {!Storage.Contract.Spendable_balance}. + + This function is a fusion of {!must_be_allocated} and + {!get_balance} for Implicit contracts exclusively. *) +val check_allocated_and_get_balance : + Raw_context.t -> Signature.public_key_hash -> Tez_repr.t tzresult Lwt.t + +val get_counter : + Raw_context.t -> + Signature.Public_key_hash.t -> + Manager_counter_repr.t tzresult Lwt.t + +val get_script_code : + Raw_context.t -> + Contract_hash.t -> + (Raw_context.t * Script_repr.lazy_expr option) tzresult Lwt.t + +val get_script : + Raw_context.t -> + Contract_hash.t -> + (Raw_context.t * Script_repr.t option) tzresult Lwt.t + +val get_storage : + Raw_context.t -> + Contract_hash.t -> + (Raw_context.t * Script_repr.expr option) tzresult Lwt.t + +module Legacy_big_map_diff : sig + type item = private + | Update of { + big_map : Z.t; + diff_key : Script_repr.expr; + diff_key_hash : Script_expr_hash.t; + diff_value : Script_repr.expr option; + } + | Clear of Z.t + | Copy of {src : Z.t; dst : Z.t} + | Alloc of { + big_map : Z.t; + key_type : Script_repr.expr; + value_type : Script_repr.expr; + } + + type t = item list + + val encoding : t Data_encoding.t + + val to_lazy_storage_diff : t -> Lazy_storage_diff.diffs + + val of_lazy_storage_diff : Lazy_storage_diff.diffs -> t +end + +val update_script_storage : + Raw_context.t -> + Contract_hash.t -> + Script_repr.expr -> + Lazy_storage_diff.diffs option -> + Raw_context.t tzresult Lwt.t + +val credit_only_call_from_token : + Raw_context.t -> Contract_repr.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t + +val spend_only_call_from_token : + Raw_context.t -> Contract_repr.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t + +(** [raw_originate ctxt ~prepaid_bootstrap_storage contract ~script] + originates the [contract] parameter. The [storage] space allocated by this + origination is considered to be free of charge or to have been already paid + for by the user, if and only if [prepaid_bootstrap_storage] is [true]. In + particular, the amount of space allocated by this origination will be part + of the consumed space to pay for returned by the next call to + [Fees_storage.record_paid_storage_space ctxt contract], if and only if + [prepaid_bootstrap_storage] is [false]. *) +val raw_originate : + Raw_context.t -> + prepaid_bootstrap_storage:bool -> + Contract_hash.t -> + script:Script_repr.t * Lazy_storage_diff.diffs option -> + Raw_context.t tzresult Lwt.t + +val fresh_contract_from_current_nonce : + Raw_context.t -> (Raw_context.t * Contract_hash.t) tzresult + +val originated_from_current_nonce : + since:Raw_context.t -> + until:Raw_context.t -> + Contract_hash.t list tzresult Lwt.t + +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val used_storage_space : Raw_context.t -> Contract_repr.t -> Z.t tzresult Lwt.t + +val paid_storage_space : Raw_context.t -> Contract_repr.t -> Z.t tzresult Lwt.t + +val set_paid_storage_space_and_return_fees_to_pay : + Raw_context.t -> + Contract_repr.t -> + Z.t -> + (Z.t * Raw_context.t) tzresult Lwt.t + +(** Enable a payer to increase the paid storage of a contract by some amount. *) +val increase_paid_storage : + Raw_context.t -> + Contract_hash.t -> + amount_in_bytes:Z.t -> + Raw_context.t tzresult Lwt.t + +(** [get_balance_and_frozen_bonds ctxt contract] returns the sum of the + (spendable) balance and the frozen bonds associated to [contract]. *) +val get_balance_and_frozen_bonds : + Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t + +(** This error is raised when [spend_bond_only_call_from_token] is called with + an amount that is not equal to the deposit associated to the given contract + and bond id. *) +type error += + | (* `Permanent *) + Frozen_bonds_must_be_spent_at_once of + Contract_repr.t * Bond_id_repr.t + +(** [bond_allocated ctxt contract bond_id] returns a new context because of an + access to carbonated data, and [true] if there is a bond associated to + [contract] and [bond_id], or [false] otherwise. *) +val bond_allocated : + Raw_context.t -> + Contract_repr.t -> + Bond_id_repr.t -> + (Raw_context.t * bool) tzresult Lwt.t + +(** [find_bond ctxt contract bond_id] returns a new context because of an access + to carbonated data, and the bond associated to [(contract, bond_id)] if + there is one, or [None] otherwise. *) +val find_bond : + Raw_context.t -> + Contract_repr.t -> + Bond_id_repr.t -> + (Raw_context.t * Tez_repr.t option) tzresult Lwt.t + +(** [spend_bond ctxt contract bond_id amount] withdraws the given [amount] from + the value of the bond associated to [contract] and [bond_id]. + + The argument [amount] is required to be strictly positive. + + @raise a [Storage_Error Missing_key] error when there is no bond associated + to [contract] and [bond_id]. + + @raise a [Frozen_bonds_must_be_spent_at_once (contract, bond_id)] + error when the amount is different from the bond associated to [contract] + and [bond_id]. *) +val spend_bond_only_call_from_token : + Raw_context.t -> + Contract_repr.t -> + Bond_id_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [credit_bond ctxt contract bond_id amount] adds the given [amount] to the + bond associated to [contract] and [bond_id]. If no bond exists, one whose + value is [amount] is created. + + The argument [amount] is required to be strictly positive. + + @raise a [Addition_overflow] error when + [(find ctxt contract bond_id) + amount > Int64.max_int]. *) +val credit_bond_only_call_from_token : + Raw_context.t -> + Contract_repr.t -> + Bond_id_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [has_frozen_bonds ctxt contract] returns [true] if there are frozen bonds + associated to [contract], and returns [false] otherwise. *) +val has_frozen_bonds : Raw_context.t -> Contract_repr.t -> bool tzresult Lwt.t + +(** [get_frozen_bonds ctxt contract] returns the total amount of bonds associated + to [contract]. *) +val get_frozen_bonds : + Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t + +(** [fold_on_bond_ids ctxt contract order init f] folds [f] on all bond + identifiers associated to [contract]. *) +val fold_on_bond_ids : + Raw_context.t -> + Contract_repr.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Bond_id_repr.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + +(** [ensure_deallocated_if_empty ctxt contract] de-allocates [contract] if its + full balance is zero, and it does not delegate. *) +val ensure_deallocated_if_empty : + Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t + +(** [simulate_spending ctxt ~balance ~amount source] removes [amount] + from [balance] as if it were the balance of the implicit contract + associated with [source]. It returns the resulting [new_balance], + and a boolean [still_allocated] that indicates whether this + contract would still exist. + + [still_allocated] is always [true] when [new_balance] is + positive. When [new_balance] is zero, it depends on the contract's + delegated status and frozen bonds (cf {!spend_only_call_from_token} + and {!ensure_deallocated_if_empty}). + + Note that this function does not retrieve the actual balance of + the contract, nor does it update or delete it. Indeed, its purpose + is to simulate the spending of fees when validating operations, + without actually spending them. + + @return [Error Balance_too_low] if [balance] is smaller than + [amount]. + + @return [Error Empty_implicit_delegated_contract] if [new_balance] + would be zero and the contract has a delegate that is not the + contract's own manager. *) +val simulate_spending : + Raw_context.t -> + balance:Tez_repr.t -> + amount:Tez_repr.t -> + Signature.public_key_hash -> + (Tez_repr.t * bool) tzresult Lwt.t + +val get_total_supply : Raw_context.t -> Tez_repr.t tzresult Lwt.t + +module For_RPC : sig + val get_staked_balance : + Raw_context.t -> Contract_repr.t -> Tez_repr.t option tzresult Lwt.t + + val get_unstaked_frozen_balance : + Raw_context.t -> Contract_repr.t -> Tez_repr.t option tzresult Lwt.t + + val get_unstaked_finalizable_balance : + Raw_context.t -> Contract_repr.t -> Tez_repr.t option tzresult Lwt.t + + val get_full_balance : + Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.bin b/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.bin new file mode 100644 index 000000000000..c4e455868ecb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.bin @@ -0,0 +1 @@ +0x02000011c405000764076407640865046e00000006256f776e6572076504620000000d256d696e4c71744d696e7465640765046200000013256d6178546f6b656e734465706f7369746564046b0000000925646561646c696e650000000d256164644c6971756964697479046c000000082564656661756c7407640865046e0000000325746f076504620000000a256c71744275726e65640765046a00000010256d696e58747a57697468647261776e0765046200000013256d696e546f6b656e7357697468647261776e046b0000000925646561646c696e65000000102572656d6f76654c69717569646974790865046e00000015256f7574707574446578746572436f6e74726163740765046200000010256d696e546f6b656e73426f756768740765046e0000000325746f076504620000000b25746f6b656e73536f6c64046b0000000925646561646c696e650000000d25746f6b656e546f546f6b656e07640865046e0000000325746f076504620000000b25746f6b656e73536f6c640765046a0000000d256d696e58747a426f75676874046b0000000925646561646c696e650000000b25746f6b656e546f58747a0865046e0000000325746f0765046200000010256d696e546f6b656e73426f75676874046b0000000925646561646c696e650000000b2578747a546f546f6b656e0501076504620000000a25746f6b656e506f6f6c0765046a000000082578747a506f6f6c0765046200000009256c7174546f74616c0765046e0000000d25746f6b656e41646472657373046e0000000b256c71744164647265737305020200000f7203210317034c0316072e02000009d1072e020000035a072e020000032603210317034c0316034c03210317034c0316034c03210317034c0316034c034003190328072c020000000c05200004074303620003032702000002ea0743036a000105700004032105710005031703160322072f0200000013074303680100000008444956206279203003270200000000031603130743036a0001034c0322072f02000000130743036801000000084449562062792030032702000000000316034c0321057100020570000603210571000703170317031605700002032105710003033a0322072f020000001307430368010000000844495620627920300327020000000003160570000205700006032105710007031605700003033a0322072f020000001307430368010000000844495620627920300327020000002a03210317034c03160743036200000570000203190325072c02000000000200000008074303620001031205700002034c0321057100020319032a072c020000000c05200005074303620004032702000001b60571000203210571000303190337072c020000000c0520000407430362000503270200000190057000030321057100040317031703170570000203210571000305700005032105710006031703170316031203420570000403210571000503170316034205700004032105710005031603420317034c032105710002057000050321057100060316031203420321031703170313057000060317031603120342034c03160342034c03490354034203480342034c032105710002034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d05700002033005700003034205700002032105710003034c03210317034c031605700002031703170317031706550765045b00000009257175616e74697479046e00000007257461726765740000000b256d696e744f724275726e072f020000000807430362000c032702000000000743036a000005700002057000030342034d05700002053d036d05700002031b05700002031b0342020000002803200321031703170313057000020321057100030317031603120342034c03160342053d036d0342020000066b072e020000038d03210317034c0316034c03210317034c0316034c03210317034c0316034c03210317034c0316034c034003190328072c020000000c05200005074303620003032702000003470743036a000003130319032a072c020000000c0520000507430362000a03270200000323057000040321057100050317031703160743036a000105700006032105710007031703160322072f0200000013074303680100000008444956206279203003270200000000031605700004032105710005033a0322072f020000001307430368010000000844495620627920300327020000000003160743036a0001034c033a0570000503210571000603170317031605700006032105710007031605700005032105710006033a0322072f02000000130743036801000000084449562062792030032702000000000316057000030570000203210571000303190337072c020000000c0520000607430362000b0327020000022e05700002034c03210571000203190337072c020000000c0520000507430362000d032702000002060570000203210571000305700005032105710006031703170316034b0356072f020000000807430362000e03270200000000034c032105710002057000060321057100070316034b0356072f020000000807430362000f03270200000000057000040743035b0000034b0348034205700006032105710007034c03210317034c031605700002031703170317031706550765045b00000009257175616e74697479046e00000007257461726765740000000b256d696e744f724275726e072f020000000807430362000c032702000000000743036a000005700002057000030342034d0570000305700005032105710006034203490354034205700006032105710007034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d05700004032105710005057000060555036c072f020000000807430362000903270200000000034c0743036c030b034d0570000603210571000703170317057000060570000703210571000803170316034b034205700006031603420321031703170317057000060342034c032105710002031703160342034c031603420317057000040342053d036d05700002031b05700002031b05700002031b034202000002d203210317034c0316034c03210317034c0316034c03210317034c0316034c03210317034c03160570000406550765046e0000000325746f0765046200000010256d696e546f6b656e73426f75676874046b0000000925646561646c696e650000000b2578747a546f546f6b656e072f020000000807430362001f032702000000000743036a000003130319032a072c020000000c0520000607430362000a0327020000022d05700002032105710003034003190328072c020000000c05200006074303620003032702000002050743036200a70f05700002032105710003033a0743036200a80f057000070321057100080316033a031205700006032105710007031703160743036200a70f05700004032105710005033a033a0322072f020000001307430368010000000844495620627920300327020000000003160743036200a80f0743036200a70f05700002032105710003033a0322072f02000000130743036801000000084449562062792030032702000000000316057000070321057100080317057000040321057100050570000903210571000a031603120342032103170317057000030321057100040570000a03170316034b0342034c031603420570000403490354034203480342034c032105710002034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d057000040570000303210571000405700006057000080342057000070342034d0570000305700004034b0743036e0100000024747a314b65326837734464616b484a5168385758345a3337326475314b4368736b7379550555036c072f020000000807430362000903270200000000034c0743036c030b034d05700003053d036d05700002031b05700002031b05700002031b0342020000058d072e02000002cc03210317034c0316034c03210317034c0316034c03210317034c0316034c034003190328072c020000000c05200004074303620003032702000002900743036a000003130319032a072c020000000c0520000407430362000a0327020000026c0743036200a70f05700002032105710003033a0743036200a80f057000050321057100060316033a03120743036a000105700005032105710006031703160322072f020000001307430368010000000844495620627920300327020000000003160743036200a70f05700004032105710005033a033a0322072f020000001307430368010000000844495620627920300327020000000003160743036a0001034c033a0743036200a80f0743036200a70f05700002032105710003033a0322072f0200000013074303680100000008444956206279203003270200000000031605700002034c03210571000203190337072c020000000a032007430362000803270200000000057000020321057100030349035403420348034205700005032105710006034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d034c032105710002057000050555036c072f020000000807430362000903270200000000034c0743036c030b034d0570000503210571000603170570000505700006032105710007031603120342032103170317057000050321057100060570000703170316034b0342034c031603420570000305700004034b0743036e0100000024747a314b65326837734464616b484a5168385758345a3337326475314b4368736b7379550555036c072f020000000807430362000903270200000000034c0743036c030b034d034c053d036d05700002031b05700002031b05700002031b034202000002b503210317034c0316034c03210317034c0316034c034003190328072c020000000c05200003074303620003032702000002830743036a000105700003032105710004031703160322072f0200000013074303680100000008444956206279203003270200000000031603130743036a0001034c0322072f020000001307430368010000000844495620627920300327020000000003160743036200a80f0743036200a70f05700002032105710003033a0322072f02000000130743036801000000084449562062792030032702000000000316032105700002034b03110743036200a70f05700002032105710003033a0743036200a80f05700004033a03120570000503210571000603160743036200a70f05700004032105710005033a033a0322072f0200000013074303680100000008444956206279203003270200000000031605700003034c03210571000203190337072c020000000a0320074303620012032702000000000321057000050321057100060316034b0356072f02000000080743036200130327020000000005700005032105710006031703170743036a000105700005033a05700006032105710007031703160312034205700005031603420317034c0342034c057000030342034903540342034c032105710002034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d0743036a000105700003033a0743036e0100000024747a314b65326837734464616b484a5168385758345a3337326475314b4368736b7379550555036c072f020000000807430362000903270200000000034c0743036c030b034d05700002053d036d05700002031b05700002031b0342 diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.mligo b/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.mligo new file mode 100644 index 000000000000..37213e25a216 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.mligo @@ -0,0 +1,388 @@ +// ============================================================================= +// Entrypoints +// ============================================================================= + +type add_liquidity = + [@layout:comb] + { owner : address ; + minLqtMinted : nat ; + maxTokensDeposited : nat ; + deadline : timestamp ; + } + +type remove_liquidity = + [@layout:comb] + { [@annot:to] to_ : address ; // recipient of the liquidity redemption + lqtBurned : nat ; // amount of lqt owned by sender to burn + minXtzWithdrawn : tez ; // minimum amount of tez to withdraw + minTokensWithdrawn : nat ; // minimum amount of tokens to whitdw + deadline : timestamp ; // the time before which the request must be completed + } + +type xtz_to_token = + [@layout:comb] + { [@annot:to] to_ : address ; + minTokensBought : nat ; + deadline : timestamp ; + } + +type token_to_xtz = + [@layout:comb] + { [@annot:to] to_ : address ; + tokensSold : nat ; + minXtzBought : tez ; + deadline : timestamp ; + } + +type token_to_token = + [@layout:comb] + { outputDexterContract : address ; + minTokensBought : nat ; + [@annot:to] to_ : address ; + tokensSold : nat ; + deadline : timestamp ; + } + +type entrypoint = +| AddLiquidity of add_liquidity +| RemoveLiquidity of remove_liquidity +| XtzToToken of xtz_to_token +| TokenToXtz of token_to_xtz +| Default of unit +| TokenToToken of token_to_token + + +// ============================================================================= +// Storage +// ============================================================================= + +type storage = + [@layout:comb] + { tokenPool : nat ; + xtzPool : tez ; + lqtTotal : nat ; + tokenAddress : address ; + lqtAddress : address ; + } + +// ============================================================================= +// Type Synonyms +// ============================================================================= + +type result = operation list * storage + +// FA1.2 +type token_contract_transfer = address * (address * nat) +type get_balance = address * (nat contract) + +// custom entrypoint for LQT FA1.2 +type mintOrBurn = + [@layout:comb] + { quantity : int ; + target : address } + +// ============================================================================= +// Error codes +// ============================================================================= + +[@inline] let error_TOKEN_CONTRACT_MUST_HAVE_A_TRANSFER_ENTRYPOINT = 0n +(* 1n *) +[@inline] let error_SELF_IS_UPDATING_TOKEN_POOL_MUST_BE_FALSE = 2n +[@inline] let error_THE_CURRENT_TIME_MUST_BE_LESS_THAN_THE_DEADLINE = 3n +[@inline] let error_MAX_TOKENS_DEPOSITED_MUST_BE_GREATER_THAN_OR_EQUAL_TO_TOKENS_DEPOSITED = 4n +[@inline] let error_LQT_MINTED_MUST_BE_GREATER_THAN_MIN_LQT_MINTED = 5n +(* 6n *) +(* 7n *) +[@inline] let error_XTZ_BOUGHT_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_XTZ_BOUGHT = 8n +[@inline] let error_INVALID_TO_ADDRESS = 9n +[@inline] let error_AMOUNT_MUST_BE_ZERO = 10n +[@inline] let error_THE_AMOUNT_OF_XTZ_WITHDRAWN_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_XTZ_WITHDRAWN = 11n +[@inline] let error_LQT_CONTRACT_MUST_HAVE_A_MINT_OR_BURN_ENTRYPOINT = 12n +[@inline] let error_THE_AMOUNT_OF_TOKENS_WITHDRAWN_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_TOKENS_WITHDRAWN = 13n +[@inline] let error_CANNOT_BURN_MORE_THAN_THE_TOTAL_AMOUNT_OF_LQT = 14n +[@inline] let error_TOKEN_POOL_MINUS_TOKENS_WITHDRAWN_IS_NEGATIVE = 15n +(* 16n *) +(* 17n *) +[@inline] let error_TOKENS_BOUGHT_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_TOKENS_BOUGHT = 18n +[@inline] let error_TOKEN_POOL_MINUS_TOKENS_BOUGHT_IS_NEGATIVE = 19n +[@inline] let error_ONLY_MANAGER_CAN_SET_BAKER = 20n +[@inline] let error_ONLY_MANAGER_CAN_SET_MANAGER = 21n +[@inline] let error_BAKER_PERMANENTLY_FROZEN = 22n +[@inline] let error_ONLY_MANAGER_CAN_SET_LQT_ADRESS = 23n +[@inline] let error_LQT_ADDRESS_ALREADY_SET = 24n +[@inline] let error_CALL_NOT_FROM_AN_IMPLICIT_ACCOUNT = 25n +(* 26n *) +(* 27n *) +#if FA2 +[@inline] let error_INVALID_FA2_TOKEN_CONTRACT_MISSING_BALANCE_OF = 28n +#else +[@inline] let error_INVALID_FA12_TOKEN_CONTRACT_MISSING_GETBALANCE = 28n +#endif +[@inline] let error_THIS_ENTRYPOINT_MAY_ONLY_BE_CALLED_BY_GETBALANCE_OF_TOKENADDRESS = 29n +(* 30n *) +[@inline] let error_INVALID_INTERMEDIATE_CONTRACT = 31n +[@inline] let error_INVALID_FA2_BALANCE_RESPONSE = 32n +[@inline] let error_UNEXPECTED_REENTRANCE_IN_UPDATE_TOKEN_POOL = 33n + + +// ============================================================================= +// Functions +// ============================================================================= + +[@inline] +let fee = 999n + +[@inline] let null_address = ("tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU" : address) + +(* this is slightly inefficient to inline, but, nice to have a clean stack for + the entrypoints for the Coq verification *) +[@inline] +let mutez_to_natural (a: tez) : nat = a / 1mutez + +[@inline] +let natural_to_mutez (a: nat): tez = a * 1mutez + +[@inline] +let is_a_nat (i : int) : nat option = Michelson.is_nat i + +let ceildiv (numerator : nat) (denominator : nat) : nat = + match (ediv numerator denominator) with + | None -> (failwith("DIV by 0") : nat) + | Some v -> let (q, r) = v in if r = 0n then q else q + 1n + +[@inline] +let mint_or_burn (storage : storage) (target : address) (quantity : int) : operation = + let lqt_admin : mintOrBurn contract = + match (Tezos.get_entrypoint_opt "%mintOrBurn" storage.lqtAddress : mintOrBurn contract option) with + | None -> (failwith error_LQT_CONTRACT_MUST_HAVE_A_MINT_OR_BURN_ENTRYPOINT : mintOrBurn contract) + | Some contract -> contract in + Tezos.transaction {quantity = quantity ; target = target} 0mutez lqt_admin + +[@inline] +let token_transfer (storage : storage) (from : address) (to_ : address) (token_amount : nat) : operation = + let token_contract: token_contract_transfer contract = + match (Tezos.get_entrypoint_opt "%transfer" storage.tokenAddress : token_contract_transfer contract option) with + | None -> (failwith error_TOKEN_CONTRACT_MUST_HAVE_A_TRANSFER_ENTRYPOINT : token_contract_transfer contract) + | Some contract -> contract in + Tezos.transaction (from, (to_, token_amount)) 0mutez token_contract + +[@inline] +let xtz_transfer (to_ : address) (amount_ : tez) : operation = + let to_contract : unit contract = + match (Tezos.get_contract_opt to_ : unit contract option) with + | None -> (failwith error_INVALID_TO_ADDRESS : unit contract) + | Some c -> c in + Tezos.transaction () amount_ to_contract + +// ============================================================================= +// Entrypoint Functions +// ============================================================================= + +// We assume the contract is originated with at least one liquidity +// provider set up already, so lqtTotal, xtzPool and tokenPool will +// always be positive after the initial setup, unless all liquidity is +// removed, at which point the contract is considered dead and stops working +// properly. (To prevent this, at least one address should keep at least a +// small amount of liquidity in the contract forever.) + +let add_liquidity (param : add_liquidity) (storage: storage) : result = + let { owner = owner ; + minLqtMinted = minLqtMinted ; + maxTokensDeposited = maxTokensDeposited ; + deadline = deadline } = param in + + if Tezos.now >= deadline then + (failwith error_THE_CURRENT_TIME_MUST_BE_LESS_THAN_THE_DEADLINE : result) + else + // the contract is initialized, use the existing exchange rate + // mints nothing if the contract has been emptied, but that's OK + let xtzPool : nat = mutez_to_natural storage.xtzPool in + let nat_amount : nat = mutez_to_natural Tezos.amount in + let lqt_minted : nat = nat_amount * storage.lqtTotal / xtzPool in + let tokens_deposited : nat = ceildiv (nat_amount * storage.tokenPool) xtzPool in + + if tokens_deposited > maxTokensDeposited then + (failwith error_MAX_TOKENS_DEPOSITED_MUST_BE_GREATER_THAN_OR_EQUAL_TO_TOKENS_DEPOSITED : result) + else if lqt_minted < minLqtMinted then + (failwith error_LQT_MINTED_MUST_BE_GREATER_THAN_MIN_LQT_MINTED : result) + else + let storage = {storage with + lqtTotal = storage.lqtTotal + lqt_minted ; + tokenPool = storage.tokenPool + tokens_deposited ; + xtzPool = storage.xtzPool + Tezos.amount} in + + // send tokens from sender to exchange + let op_token = token_transfer storage Tezos.sender Tezos.self_address tokens_deposited in + // mint lqt tokens for them + let op_lqt = mint_or_burn storage owner (int lqt_minted) in + ([op_token; op_lqt], storage) + +let remove_liquidity (param : remove_liquidity) (storage : storage) : result = + let { to_ = to_ ; + lqtBurned = lqtBurned ; + minXtzWithdrawn = minXtzWithdrawn ; + minTokensWithdrawn = minTokensWithdrawn ; + deadline = deadline } = param in + + if Tezos.now >= deadline then + (failwith error_THE_CURRENT_TIME_MUST_BE_LESS_THAN_THE_DEADLINE : result) + else if Tezos.amount > 0mutez then + (failwith error_AMOUNT_MUST_BE_ZERO : result) + else begin + let xtz_withdrawn : tez = natural_to_mutez ((lqtBurned * (mutez_to_natural storage.xtzPool)) / storage.lqtTotal) in + let tokens_withdrawn : nat = lqtBurned * storage.tokenPool / storage.lqtTotal in + + // Check that minimum withdrawal conditions are met + if xtz_withdrawn < minXtzWithdrawn then + (failwith error_THE_AMOUNT_OF_XTZ_WITHDRAWN_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_XTZ_WITHDRAWN : result) + else if tokens_withdrawn < minTokensWithdrawn then + (failwith error_THE_AMOUNT_OF_TOKENS_WITHDRAWN_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_TOKENS_WITHDRAWN : result) + // Proceed to form the operations and update the storage + else begin + // calculate lqtTotal, convert int to nat + let new_lqtTotal = match (is_a_nat ( storage.lqtTotal - lqtBurned)) with + // This check should be unecessary, the fa12 logic normally takes care of it + | None -> (failwith error_CANNOT_BURN_MORE_THAN_THE_TOTAL_AMOUNT_OF_LQT : nat) + | Some n -> n in + // Calculate tokenPool, convert int to nat + let new_tokenPool = match is_a_nat (storage.tokenPool - tokens_withdrawn) with + | None -> (failwith error_TOKEN_POOL_MINUS_TOKENS_WITHDRAWN_IS_NEGATIVE : nat) + | Some n -> n in + + let op_lqt = mint_or_burn storage Tezos.sender (0 - lqtBurned) in + let op_token = token_transfer storage Tezos.self_address to_ tokens_withdrawn in + let op_xtz = xtz_transfer to_ xtz_withdrawn in + let storage = {storage with xtzPool = storage.xtzPool - xtz_withdrawn ; lqtTotal = new_lqtTotal ; tokenPool = new_tokenPool} in + ([op_lqt; op_token; op_xtz], storage) + end + end + + +let xtz_to_token (param : xtz_to_token) (storage : storage) = + let { to_ = to_ ; + minTokensBought = minTokensBought ; + deadline = deadline } = param in + + if Tezos.now >= deadline then + (failwith error_THE_CURRENT_TIME_MUST_BE_LESS_THAN_THE_DEADLINE : result) + else begin + // we don't check that xtzPool > 0, because that is impossible + // unless all liquidity has been removed + let xtzPool = mutez_to_natural storage.xtzPool in + let nat_amount = mutez_to_natural Tezos.amount in + + let amount_net_burn = (nat_amount * 999n) / 1000n in + let burn_amount = abs (nat_amount - amount_net_burn) in + + let tokens_bought = + (let bought = (amount_net_burn * fee * storage.tokenPool) / (xtzPool * 1000n + (amount_net_burn * fee)) in + if bought < minTokensBought then + (failwith error_TOKENS_BOUGHT_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_TOKENS_BOUGHT : nat) + else + bought) + in + let new_tokenPool = (match is_nat (storage.tokenPool - tokens_bought) with + | None -> (failwith error_TOKEN_POOL_MINUS_TOKENS_BOUGHT_IS_NEGATIVE : nat) + | Some difference -> difference) in + + // update xtzPool + let storage = {storage with + xtzPool = storage.xtzPool + (natural_to_mutez amount_net_burn); + tokenPool = new_tokenPool } in + // send tokens_withdrawn to to address + // if tokens_bought is greater than storage.tokenPool, this will fail + let op = token_transfer storage Tezos.self_address to_ tokens_bought in + let op_burn = xtz_transfer null_address (natural_to_mutez burn_amount) in + ([ op ; op_burn], storage) + end + + +let token_to_xtz (param : token_to_xtz) (storage : storage) = + let { to_ = to_ ; + tokensSold = tokensSold ; + minXtzBought = minXtzBought ; + deadline = deadline } = param in + + if Tezos.now >= deadline then + (failwith error_THE_CURRENT_TIME_MUST_BE_LESS_THAN_THE_DEADLINE : result) + else if Tezos.amount > 0mutez then + (failwith error_AMOUNT_MUST_BE_ZERO : result) + else + // we don't check that tokenPool > 0, because that is impossible + // unless all liquidity has been removed + let xtz_bought = natural_to_mutez (((tokensSold * fee * (mutez_to_natural storage.xtzPool)) / (storage.tokenPool * 1000n + (tokensSold * fee)))) in + + let xtz_bought_net_burn = + let bought = (xtz_bought * 999n) / 1000n in + if bought < minXtzBought then (failwith error_XTZ_BOUGHT_MUST_BE_GREATER_THAN_OR_EQUAL_TO_MIN_XTZ_BOUGHT : tez) else bought in + + let op_token = token_transfer storage Tezos.sender Tezos.self_address tokensSold in + let op_tez = xtz_transfer to_ xtz_bought_net_burn in + let storage = {storage with tokenPool = storage.tokenPool + tokensSold ; + xtzPool = storage.xtzPool - xtz_bought } in + + let burn_amount = xtz_bought - xtz_bought_net_burn in + let op_burn = xtz_transfer null_address burn_amount in + ([op_token ; op_tez; op_burn], storage) + +// entrypoint to allow depositing funds +let default_ (storage : storage) : result = + // update xtzPool + let storage = {storage with xtzPool = storage.xtzPool + Tezos.amount } in + (([] : operation list), storage) + +let token_to_token (param : token_to_token) (storage : storage) : result = + let { outputDexterContract = outputDexterContract ; + minTokensBought = minTokensBought ; + to_ = to_ ; + tokensSold = tokensSold ; + deadline = deadline } = param in + + let outputDexterContract_contract: xtz_to_token contract = + (match (Tezos.get_entrypoint_opt "%xtzToToken" outputDexterContract : xtz_to_token contract option) with + | None -> (failwith error_INVALID_INTERMEDIATE_CONTRACT : xtz_to_token contract) + | Some c -> c) in + + if Tezos.amount > 0mutez then + (failwith error_AMOUNT_MUST_BE_ZERO : result) + else if Tezos.now >= deadline then + (failwith error_THE_CURRENT_TIME_MUST_BE_LESS_THAN_THE_DEADLINE : result) + else + // we don't check that tokenPool > 0, because that is impossible unless all liquidity has been removed + let xtz_bought = (tokensSold * fee * storage.xtzPool) / (storage.tokenPool * 1000n + (tokensSold * fee)) in + + let xtz_bought_net_burn = (xtz_bought * 999n) / 1000n in + + let storage = {storage with + tokenPool = storage.tokenPool + tokensSold ; + xtzPool = storage.xtzPool - xtz_bought } in + + let op1 = token_transfer storage Tezos.sender Tezos.self_address tokensSold in + let op2 = + Tezos.transaction + {to_ = to_; minTokensBought = minTokensBought; deadline = deadline} + xtz_bought_net_burn + outputDexterContract_contract in + + let burn_amount = xtz_bought - xtz_bought_net_burn in + let op_burn = xtz_transfer null_address burn_amount in + ([op1 ; op2; op_burn], storage) + +// ============================================================================= +// Main +// ============================================================================= + +let main ((entrypoint, storage) : entrypoint * storage) : result = + match entrypoint with + | AddLiquidity param -> + add_liquidity param storage + | RemoveLiquidity param -> + remove_liquidity param storage + | Default -> + default_ storage + | XtzToToken param -> + xtz_to_token param storage + | TokenToXtz param -> + token_to_xtz param storage + | TokenToToken param -> + token_to_token param storage \ No newline at end of file diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.tz b/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.tz new file mode 100644 index 000000000000..15a0819c52e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/cpmm.tz @@ -0,0 +1,929 @@ +{ parameter + (or (or (or (pair %addLiquidity + (address %owner) + (pair (nat %minLqtMinted) (pair (nat %maxTokensDeposited) (timestamp %deadline)))) + (unit %default)) + (or (pair %removeLiquidity + (address %to) + (pair (nat %lqtBurned) + (pair (mutez %minXtzWithdrawn) (pair (nat %minTokensWithdrawn) (timestamp %deadline))))) + (pair %tokenToToken + (address %outputDexterContract) + (pair (nat %minTokensBought) + (pair (address %to) (pair (nat %tokensSold) (timestamp %deadline))))))) + (or (pair %tokenToXtz + (address %to) + (pair (nat %tokensSold) (pair (mutez %minXtzBought) (timestamp %deadline)))) + (pair %xtzToToken (address %to) (pair (nat %minTokensBought) (timestamp %deadline))))) ; + storage + (pair (nat %tokenPool) + (pair (mutez %xtzPool) + (pair (nat %lqtTotal) (pair (address %tokenAddress) (address %lqtAddress))))) ; + code { DUP ; + CDR ; + SWAP ; + CAR ; + IF_LEFT + { IF_LEFT + { IF_LEFT + { DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + NOW ; + COMPARE ; + GE ; + IF { DROP 4 ; PUSH nat 3 ; FAILWITH } + { PUSH mutez 1 ; + DIG 4 ; + DUP ; + DUG 5 ; + CDR ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + AMOUNT ; + PUSH mutez 1 ; + SWAP ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + SWAP ; + DUP ; + DUG 2 ; + DIG 6 ; + DUP ; + DUG 7 ; + CDR ; + CDR ; + CAR ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 2 ; + DIG 6 ; + DUP ; + DUG 7 ; + CAR ; + DIG 3 ; + MUL ; + EDIV ; + IF_NONE + { PUSH string "DIV by 0" ; FAILWITH } + { DUP ; + CDR ; + SWAP ; + CAR ; + PUSH nat 0 ; + DIG 2 ; + COMPARE ; + EQ ; + IF {} { PUSH nat 1 ; ADD } } ; + DIG 2 ; + SWAP ; + DUP ; + DUG 2 ; + COMPARE ; + GT ; + IF { DROP 5 ; PUSH nat 4 ; FAILWITH } + { DUG 2 ; + DUP ; + DUG 3 ; + COMPARE ; + LT ; + IF { DROP 4 ; PUSH nat 5 ; FAILWITH } + { DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + CDR ; + CDR ; + DIG 2 ; + DUP ; + DUG 3 ; + DIG 5 ; + DUP ; + DUG 6 ; + CDR ; + CDR ; + CAR ; + ADD ; + PAIR ; + DIG 4 ; + DUP ; + DUG 5 ; + CDR ; + CAR ; + PAIR ; + DIG 4 ; + DUP ; + DUG 5 ; + CAR ; + PAIR ; + CDR ; + SWAP ; + DUP ; + DUG 2 ; + DIG 5 ; + DUP ; + DUG 6 ; + CAR ; + ADD ; + PAIR ; + DUP ; + CDR ; + CDR ; + AMOUNT ; + DIG 6 ; + CDR ; + CAR ; + ADD ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + SWAP ; + SELF ; + ADDRESS ; + PAIR ; + SENDER ; + PAIR ; + SWAP ; + DUP ; + DUG 2 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 3 ; + CDR ; + CDR ; + CDR ; + CAR ; + CONTRACT %transfer (pair address (pair address nat)) ; + IF_NONE { PUSH nat 0 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 3 ; + DIG 3 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + DIG 2 ; + INT ; + DIG 3 ; + PAIR ; + DIG 2 ; + DUP ; + DUG 3 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 2 ; + CDR ; + CDR ; + CDR ; + CDR ; + CONTRACT %mintOrBurn (pair (int %quantity) (address %target)) ; + IF_NONE { PUSH nat 12 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 2 ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + DIG 2 ; + NIL operation ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + PAIR } } } } + { DROP ; + DUP ; + CDR ; + CDR ; + AMOUNT ; + DIG 2 ; + DUP ; + DUG 3 ; + CDR ; + CAR ; + ADD ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + NIL operation ; + PAIR } } + { IF_LEFT + { DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + NOW ; + COMPARE ; + GE ; + IF { DROP 5 ; PUSH nat 3 ; FAILWITH } + { PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + GT ; + IF { DROP 5 ; PUSH nat 10 ; FAILWITH } + { DIG 4 ; + DUP ; + DUG 5 ; + CDR ; + CDR ; + CAR ; + PUSH mutez 1 ; + DIG 6 ; + DUP ; + DUG 7 ; + CDR ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 4 ; + DUP ; + DUG 5 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + PUSH mutez 1 ; + SWAP ; + MUL ; + DIG 5 ; + DUP ; + DUG 6 ; + CDR ; + CDR ; + CAR ; + DIG 6 ; + DUP ; + DUG 7 ; + CAR ; + DIG 5 ; + DUP ; + DUG 6 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 3 ; + DIG 2 ; + DUP ; + DUG 3 ; + COMPARE ; + LT ; + IF { DROP 6 ; PUSH nat 11 ; FAILWITH } + { DIG 2 ; + SWAP ; + DUP ; + DUG 2 ; + COMPARE ; + LT ; + IF { DROP 5 ; PUSH nat 13 ; FAILWITH } + { DIG 2 ; + DUP ; + DUG 3 ; + DIG 5 ; + DUP ; + DUG 6 ; + CDR ; + CDR ; + CAR ; + SUB ; + ISNAT ; + IF_NONE { PUSH nat 14 ; FAILWITH } {} ; + SWAP ; + DUP ; + DUG 2 ; + DIG 6 ; + DUP ; + DUG 7 ; + CAR ; + SUB ; + ISNAT ; + IF_NONE { PUSH nat 15 ; FAILWITH } {} ; + DIG 4 ; + PUSH int 0 ; + SUB ; + SENDER ; + PAIR ; + DIG 6 ; + DUP ; + DUG 7 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 2 ; + CDR ; + CDR ; + CDR ; + CDR ; + CONTRACT %mintOrBurn (pair (int %quantity) (address %target)) ; + IF_NONE { PUSH nat 12 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 2 ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + DIG 3 ; + DIG 5 ; + DUP ; + DUG 6 ; + PAIR ; + SELF ; + ADDRESS ; + PAIR ; + DIG 6 ; + DUP ; + DUG 7 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 3 ; + CDR ; + CDR ; + CDR ; + CAR ; + CONTRACT %transfer (pair address (pair address nat)) ; + IF_NONE { PUSH nat 0 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 3 ; + DIG 3 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + DIG 4 ; + DUP ; + DUG 5 ; + DIG 6 ; + CONTRACT unit ; + IF_NONE { PUSH nat 9 ; FAILWITH } {} ; + SWAP ; + PUSH unit Unit ; + TRANSFER_TOKENS ; + DIG 6 ; + DUP ; + DUG 7 ; + CDR ; + CDR ; + DIG 6 ; + DIG 7 ; + DUP ; + DUG 8 ; + CDR ; + CAR ; + SUB ; + PAIR ; + DIG 6 ; + CAR ; + PAIR ; + DUP ; + CDR ; + CDR ; + CDR ; + DIG 6 ; + PAIR ; + SWAP ; + DUP ; + DUG 2 ; + CDR ; + CAR ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + CDR ; + DIG 4 ; + PAIR ; + NIL operation ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + PAIR } } } } } + { DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 4 ; + CONTRACT %xtzToToken + (pair (address %to) (pair (nat %minTokensBought) (timestamp %deadline))) ; + IF_NONE { PUSH nat 31 ; FAILWITH } {} ; + PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + GT ; + IF { DROP 6 ; PUSH nat 10 ; FAILWITH } + { DIG 2 ; + DUP ; + DUG 3 ; + NOW ; + COMPARE ; + GE ; + IF { DROP 6 ; PUSH nat 3 ; FAILWITH } + { PUSH nat 999 ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + PUSH nat 1000 ; + DIG 7 ; + DUP ; + DUG 8 ; + CAR ; + MUL ; + ADD ; + DIG 6 ; + DUP ; + DUG 7 ; + CDR ; + CAR ; + PUSH nat 999 ; + DIG 4 ; + DUP ; + DUG 5 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + PUSH nat 1000 ; + PUSH nat 999 ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 7 ; + DUP ; + DUG 8 ; + CDR ; + DIG 4 ; + DUP ; + DUG 5 ; + DIG 9 ; + DUP ; + DUG 10 ; + CAR ; + ADD ; + PAIR ; + DUP ; + CDR ; + CDR ; + DIG 3 ; + DUP ; + DUG 4 ; + DIG 10 ; + CDR ; + CAR ; + SUB ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + DIG 4 ; + SELF ; + ADDRESS ; + PAIR ; + SENDER ; + PAIR ; + SWAP ; + DUP ; + DUG 2 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 3 ; + CDR ; + CDR ; + CDR ; + CAR ; + CONTRACT %transfer (pair address (pair address nat)) ; + IF_NONE { PUSH nat 0 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 3 ; + DIG 3 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + DIG 4 ; + DIG 3 ; + DUP ; + DUG 4 ; + DIG 6 ; + DIG 8 ; + PAIR ; + DIG 7 ; + PAIR ; + TRANSFER_TOKENS ; + DIG 3 ; + DIG 4 ; + SUB ; + PUSH address "tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU" ; + CONTRACT unit ; + IF_NONE { PUSH nat 9 ; FAILWITH } {} ; + SWAP ; + PUSH unit Unit ; + TRANSFER_TOKENS ; + DIG 3 ; + NIL operation ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + PAIR } } } } } + { IF_LEFT + { DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + NOW ; + COMPARE ; + GE ; + IF { DROP 4 ; PUSH nat 3 ; FAILWITH } + { PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + GT ; + IF { DROP 4 ; PUSH nat 10 ; FAILWITH } + { PUSH nat 999 ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + PUSH nat 1000 ; + DIG 5 ; + DUP ; + DUG 6 ; + CAR ; + MUL ; + ADD ; + PUSH mutez 1 ; + DIG 5 ; + DUP ; + DUG 6 ; + CDR ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + PUSH nat 999 ; + DIG 4 ; + DUP ; + DUG 5 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + PUSH mutez 1 ; + SWAP ; + MUL ; + PUSH nat 1000 ; + PUSH nat 999 ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 2 ; + SWAP ; + DUP ; + DUG 2 ; + COMPARE ; + LT ; + IF { DROP ; PUSH nat 8 ; FAILWITH } {} ; + DIG 2 ; + DUP ; + DUG 3 ; + SELF ; + ADDRESS ; + PAIR ; + SENDER ; + PAIR ; + DIG 5 ; + DUP ; + DUG 6 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 3 ; + CDR ; + CDR ; + CDR ; + CAR ; + CONTRACT %transfer (pair address (pair address nat)) ; + IF_NONE { PUSH nat 0 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 3 ; + DIG 3 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + SWAP ; + DUP ; + DUG 2 ; + DIG 5 ; + CONTRACT unit ; + IF_NONE { PUSH nat 9 ; FAILWITH } {} ; + SWAP ; + PUSH unit Unit ; + TRANSFER_TOKENS ; + DIG 5 ; + DUP ; + DUG 6 ; + CDR ; + DIG 5 ; + DIG 6 ; + DUP ; + DUG 7 ; + CAR ; + ADD ; + PAIR ; + DUP ; + CDR ; + CDR ; + DIG 5 ; + DUP ; + DUG 6 ; + DIG 7 ; + CDR ; + CAR ; + SUB ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + DIG 3 ; + DIG 4 ; + SUB ; + PUSH address "tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU" ; + CONTRACT unit ; + IF_NONE { PUSH nat 9 ; FAILWITH } {} ; + SWAP ; + PUSH unit Unit ; + TRANSFER_TOKENS ; + SWAP ; + NIL operation ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + PAIR } } } + { DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + NOW ; + COMPARE ; + GE ; + IF { DROP 3 ; PUSH nat 3 ; FAILWITH } + { PUSH mutez 1 ; + DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + CAR ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + AMOUNT ; + PUSH mutez 1 ; + SWAP ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + PUSH nat 1000 ; + PUSH nat 999 ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DUP ; + DIG 2 ; + SUB ; + ABS ; + PUSH nat 999 ; + DIG 2 ; + DUP ; + DUG 3 ; + MUL ; + PUSH nat 1000 ; + DIG 4 ; + MUL ; + ADD ; + DIG 5 ; + DUP ; + DUG 6 ; + CAR ; + PUSH nat 999 ; + DIG 4 ; + DUP ; + DUG 5 ; + MUL ; + MUL ; + EDIV ; + IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ; + CAR ; + DIG 3 ; + SWAP ; + DUP ; + DUG 2 ; + COMPARE ; + LT ; + IF { DROP ; PUSH nat 18 ; FAILWITH } {} ; + DUP ; + DIG 5 ; + DUP ; + DUG 6 ; + CAR ; + SUB ; + ISNAT ; + IF_NONE { PUSH nat 19 ; FAILWITH } {} ; + DIG 5 ; + DUP ; + DUG 6 ; + CDR ; + CDR ; + PUSH mutez 1 ; + DIG 5 ; + MUL ; + DIG 6 ; + DUP ; + DUG 7 ; + CDR ; + CAR ; + ADD ; + PAIR ; + DIG 5 ; + CAR ; + PAIR ; + CDR ; + SWAP ; + PAIR ; + SWAP ; + DIG 3 ; + PAIR ; + SELF ; + ADDRESS ; + PAIR ; + SWAP ; + DUP ; + DUG 2 ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + SWAP ; + DUP ; + CDR ; + SWAP ; + CAR ; + DIG 3 ; + CDR ; + CDR ; + CDR ; + CAR ; + CONTRACT %transfer (pair address (pair address nat)) ; + IF_NONE { PUSH nat 0 ; FAILWITH } {} ; + PUSH mutez 0 ; + DIG 3 ; + DIG 3 ; + PAIR ; + DIG 3 ; + PAIR ; + TRANSFER_TOKENS ; + PUSH mutez 1 ; + DIG 3 ; + MUL ; + PUSH address "tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU" ; + CONTRACT unit ; + IF_NONE { PUSH nat 9 ; FAILWITH } {} ; + SWAP ; + PUSH unit Unit ; + TRANSFER_TOKENS ; + DIG 2 ; + NIL operation ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + PAIR } } } } } + diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/lqt.bin b/src/proto_020_PsParisC/lib_protocol/contracts/lqt.bin new file mode 100644 index 000000000000..4fa01f58526f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/lqt.bin @@ -0,0 +1 @@ +0x020000070005000764076407640865046e00000008257370656e6465720462000000062576616c75650000000825617070726f766508650865046e00000006256f776e6572046e00000008257370656e646572000000082572657175657374065a0362000000092563616c6c6261636b0000000d25676574416c6c6f77616e636507640865046e00000006256f776e6572065a0362000000092563616c6c6261636b0000000b2567657442616c616e63650865046c000000082572657175657374065a0362000000092563616c6c6261636b0000000f25676574546f74616c537570706c7907640865045b00000009257175616e74697479046e00000007257461726765740000000b256d696e744f724275726e0865046e000000052566726f6d0765046e0000000325746f0462000000062576616c756500000009257472616e73666572050107650861036e03620000000725746f6b656e73076508610765046e00000006256f776e6572046e00000008257370656e64657203620000000b25616c6c6f77616e6365730765046e000000062561646d696e04620000000d25746f74616c5f737570706c7905020200000552032103170743036a000003130319033c072c020000001607430368010000000b446f6e7453656e6454657a03270200000000034c0316072e02000001b2072e0200000132072e02000000e2034c03210571000203170316034c0321057100020316034803420743036200000570000303210571000403170319032a07430362000005700003032105710004057000030321057100040329072f020000000607430362000002000000000319032a0314072c0200000020074303680100000015556e73616665416c6c6f77616e63654368616e676503270200000000057000030321057100040317031705700002057000030317074303620000034c03210571000203190325072c02000000060320053e0362020000000203460570000303500342034c03160342053d036d03420200000044034c032105700002053d036d034c03210571000203170743036a000005700004031703160570000403160329072f02000000060743036200000200000000034d031b03420200000074072e0200000042034c032105700002053d036d034c03210571000203170743036a00000570000403160570000403160329072f02000000060743036200000200000000034d031b03420200000026034c032105700002053d036d034c03170743036a000005700003031703170317034d031b0342020000035e072e020000013c034c03210571000203170317031603480319033c072c02000000140743036801000000094f6e6c7941646d696e03270200000000032103160570000203210571000303160570000203210571000303170329072f0200000006074303620000020000000003120356072f020000003607430368010000002b43616e6e6f74206275726e206d6f7265207468616e207468652074617267657427732062616c616e63652e03270200000000034c032105710002031605700003032105710004031703170317031203110570000303210571000403170570000403160743036200000570000403210571000503190325072c020000000a057000030320053e03620200000006057000030346057000040317035003420321057100020317031703160342034c032105710002031703160342034c03160342053d036d03420200000216034c03210571000203170316057000020321057100030316057000020321057100030316034803190325072c0200000002034c02000000a903480570000303210571000403160342057000030321057100040317031705700003032105710004057000020321057100030329072f02000000060743036200000200000000034b0356072f020000001d0743036801000000124e6f74456e6f756768416c6c6f77616e636503270200000000057000030743036200000570000203210571000303190325072c0200000008034c0320053e03620200000004034c03460570000203500570000203210571000303170317057000020321057100030570000403210571000503160329072f02000000060743036200000200000000034b0356072f020000001b0743036801000000104e6f74456e6f75676842616c616e636503270200000000057000020743036200000570000203210571000303190325072c0200000008034c0320053e03620200000004034c034605700003032105710004031603500570000203210571000303170317034c03210571000205700004032105710005031703160329072f020000000607430362000002000000000312034c0743036200000570000203210571000303190325072c0200000008034c0320053e03620200000004034c034605700003031703160350057000020317034c0342032103170317057000020342034c03160342053d036d0342 diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/lqt.mligo b/src/proto_020_PsParisC/lib_protocol/contracts/lqt.mligo new file mode 100644 index 000000000000..7c2fa5012d1e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/lqt.mligo @@ -0,0 +1,164 @@ +type transfer = + [@layout:comb] + { [@annot:from] address_from : address; + [@annot:to] address_to : address; + value : nat } + +type approve = + [@layout:comb] + { spender : address; + value : nat } + +type mintOrBurn = + [@layout:comb] + { quantity : int ; + target : address } + +type allowance_key = + [@layout:comb] + { owner : address; + spender : address } + +type getAllowance = + [@layout:comb] + { request : allowance_key; + callback : nat contract } + +type getBalance = + [@layout:comb] + { owner : address; + callback : nat contract } + +type getTotalSupply = + [@layout:comb] + { request : unit ; + callback : nat contract } + +type tokens = (address, nat) big_map +type allowances = (allowance_key, nat) big_map + +type storage = + [@layout:comb] + { tokens : tokens; + allowances : allowances; + admin : address; + total_supply : nat; + } + +type parameter = + | Transfer of transfer + | Approve of approve + | MintOrBurn of mintOrBurn + | GetAllowance of getAllowance + | GetBalance of getBalance + | GetTotalSupply of getTotalSupply + +type result = operation list * storage + +[@inline] +let maybe (n : nat) : nat option = + if n = 0n + then (None : nat option) + else Some n + +let transfer (param : transfer) (storage : storage) : result = + let allowances = storage.allowances in + let tokens = storage.tokens in + let allowances = + if Tezos.sender = param.address_from + then allowances + else + let allowance_key = { owner = param.address_from ; spender = Tezos.sender } in + let authorized_value = + match Big_map.find_opt allowance_key allowances with + | Some value -> value + | None -> 0n in + let authorized_value = + match is_nat (authorized_value - param.value) with + | None -> (failwith "NotEnoughAllowance" : nat) + | Some authorized_value -> authorized_value in + Big_map.update allowance_key (maybe authorized_value) allowances in + let tokens = + let from_balance = + match Big_map.find_opt param.address_from tokens with + | Some value -> value + | None -> 0n in + let from_balance = + match is_nat (from_balance - param.value) with + | None -> (failwith "NotEnoughBalance" : nat) + | Some from_balance -> from_balance in + Big_map.update param.address_from (maybe from_balance) tokens in + let tokens = + let to_balance = + match Big_map.find_opt param.address_to tokens with + | Some value -> value + | None -> 0n in + let to_balance = to_balance + param.value in + Big_map.update param.address_to (maybe to_balance) tokens in + (([] : operation list), { storage with tokens = tokens; allowances = allowances }) + +let approve (param : approve) (storage : storage) : result = + let allowances = storage.allowances in + let allowance_key = { owner = Tezos.sender ; spender = param.spender } in + let previous_value = + match Big_map.find_opt allowance_key allowances with + | Some value -> value + | None -> 0n in + begin + if previous_value > 0n && param.value > 0n + then (failwith "UnsafeAllowanceChange") + else (); + let allowances = Big_map.update allowance_key (maybe param.value) allowances in + (([] : operation list), { storage with allowances = allowances }) + end + +let mintOrBurn (param : mintOrBurn) (storage : storage) : result = + begin + if Tezos.sender <> storage.admin + then failwith "OnlyAdmin" + else (); + let tokens = storage.tokens in + let old_balance = + match Big_map.find_opt param.target tokens with + | None -> 0n + | Some bal -> bal in + let new_balance = + match is_nat (old_balance + param.quantity) with + | None -> (failwith "Cannot burn more than the target's balance." : nat) + | Some bal -> bal in + let tokens = Big_map.update param.target (maybe new_balance) storage.tokens in + let total_supply = abs (storage.total_supply + param.quantity) in + (([] : operation list), { storage with tokens = tokens ; total_supply = total_supply }) + end + +let getAllowance (param : getAllowance) (storage : storage) : operation list = + let value = + match Big_map.find_opt param.request storage.allowances with + | Some value -> value + | None -> 0n in + [Tezos.transaction value 0mutez param.callback] + +let getBalance (param : getBalance) (storage : storage) : operation list = + let value = + match Big_map.find_opt param.owner storage.tokens with + | Some value -> value + | None -> 0n in + [Tezos.transaction value 0mutez param.callback] + +let getTotalSupply (param : getTotalSupply) (storage : storage) : operation list = + let total = storage.total_supply in + [Tezos.transaction total 0mutez param.callback] + +let main (param, storage : parameter * storage) : result = + begin + if Tezos.amount <> 0mutez + then failwith "DontSendTez" + else (); + match param with + | Transfer param -> transfer param storage + | Approve param -> approve param storage + | MintOrBurn param -> mintOrBurn param storage + | GetAllowance param -> (getAllowance param storage, storage) + | GetBalance param -> (getBalance param storage, storage) + | GetTotalSupply param -> (getTotalSupply param storage, storage) + end diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/lqt.tz b/src/proto_020_PsParisC/lib_protocol/contracts/lqt.tz new file mode 100644 index 000000000000..d0f5f45fd05f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/lqt.tz @@ -0,0 +1,327 @@ +{ parameter + (or (or (or (pair %approve (address %spender) (nat %value)) + (pair %getAllowance + (pair %request (address %owner) (address %spender)) + (contract %callback nat))) + (or (pair %getBalance (address %owner) (contract %callback nat)) + (pair %getTotalSupply (unit %request) (contract %callback nat)))) + (or (pair %mintOrBurn (int %quantity) (address %target)) + (pair %transfer (address %from) (pair (address %to) (nat %value))))) ; + storage + (pair (big_map %tokens address nat) + (pair (big_map %allowances (pair (address %owner) (address %spender)) nat) + (pair (address %admin) (nat %total_supply)))) ; + code { DUP ; + CDR ; + PUSH mutez 0 ; + AMOUNT ; + COMPARE ; + NEQ ; + IF { PUSH string "DontSendTez" ; FAILWITH } {} ; + SWAP ; + CAR ; + IF_LEFT + { IF_LEFT + { IF_LEFT + { SWAP ; + DUP ; + DUG 2 ; + CDR ; + CAR ; + SWAP ; + DUP ; + DUG 2 ; + CAR ; + SENDER ; + PAIR ; + PUSH nat 0 ; + DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + COMPARE ; + GT ; + PUSH nat 0 ; + DIG 3 ; + DUP ; + DUG 4 ; + DIG 3 ; + DUP ; + DUG 4 ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + COMPARE ; + GT ; + AND ; + IF { PUSH string "UnsafeAllowanceChange" ; FAILWITH } {} ; + DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + CDR ; + DIG 2 ; + DIG 3 ; + CDR ; + PUSH nat 0 ; + SWAP ; + DUP ; + DUG 2 ; + COMPARE ; + EQ ; + IF { DROP ; NONE nat } { SOME } ; + DIG 3 ; + UPDATE ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + NIL operation ; + PAIR } + { SWAP ; + DUP ; + DIG 2 ; + NIL operation ; + SWAP ; + DUP ; + DUG 2 ; + CDR ; + PUSH mutez 0 ; + DIG 4 ; + CDR ; + CAR ; + DIG 4 ; + CAR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + TRANSFER_TOKENS ; + CONS ; + PAIR } } + { IF_LEFT + { SWAP ; + DUP ; + DIG 2 ; + NIL operation ; + SWAP ; + DUP ; + DUG 2 ; + CDR ; + PUSH mutez 0 ; + DIG 4 ; + CAR ; + DIG 4 ; + CAR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + TRANSFER_TOKENS ; + CONS ; + PAIR } + { SWAP ; + DUP ; + DIG 2 ; + NIL operation ; + SWAP ; + CDR ; + PUSH mutez 0 ; + DIG 3 ; + CDR ; + CDR ; + CDR ; + TRANSFER_TOKENS ; + CONS ; + PAIR } } } + { IF_LEFT + { SWAP ; + DUP ; + DUG 2 ; + CDR ; + CDR ; + CAR ; + SENDER ; + COMPARE ; + NEQ ; + IF { PUSH string "OnlyAdmin" ; FAILWITH } {} ; + DUP ; + CAR ; + DIG 2 ; + DUP ; + DUG 3 ; + CAR ; + DIG 2 ; + DUP ; + DUG 3 ; + CDR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + ADD ; + ISNAT ; + IF_NONE + { PUSH string "Cannot burn more than the target's balance." ; FAILWITH } + {} ; + SWAP ; + DUP ; + DUG 2 ; + CAR ; + DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + CDR ; + CDR ; + ADD ; + ABS ; + DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + DIG 4 ; + CAR ; + PUSH nat 0 ; + DIG 4 ; + DUP ; + DUG 5 ; + COMPARE ; + EQ ; + IF { DIG 3 ; DROP ; NONE nat } { DIG 3 ; SOME } ; + DIG 4 ; + CDR ; + UPDATE ; + PAIR ; + DUP ; + DUG 2 ; + CDR ; + CDR ; + CAR ; + PAIR ; + SWAP ; + DUP ; + DUG 2 ; + CDR ; + CAR ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + NIL operation ; + PAIR } + { SWAP ; + DUP ; + DUG 2 ; + CDR ; + CAR ; + DIG 2 ; + DUP ; + DUG 3 ; + CAR ; + DIG 2 ; + DUP ; + DUG 3 ; + CAR ; + SENDER ; + COMPARE ; + EQ ; + IF { SWAP } + { SENDER ; + DIG 3 ; + DUP ; + DUG 4 ; + CAR ; + PAIR ; + DIG 3 ; + DUP ; + DUG 4 ; + CDR ; + CDR ; + DIG 3 ; + DUP ; + DUG 4 ; + DIG 2 ; + DUP ; + DUG 3 ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + SUB ; + ISNAT ; + IF_NONE { PUSH string "NotEnoughAllowance" ; FAILWITH } {} ; + DIG 3 ; + PUSH nat 0 ; + DIG 2 ; + DUP ; + DUG 3 ; + COMPARE ; + EQ ; + IF { SWAP ; DROP ; NONE nat } { SWAP ; SOME } ; + DIG 2 ; + UPDATE } ; + DIG 2 ; + DUP ; + DUG 3 ; + CDR ; + CDR ; + DIG 2 ; + DUP ; + DUG 3 ; + DIG 4 ; + DUP ; + DUG 5 ; + CAR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + SUB ; + ISNAT ; + IF_NONE { PUSH string "NotEnoughBalance" ; FAILWITH } {} ; + DIG 2 ; + PUSH nat 0 ; + DIG 2 ; + DUP ; + DUG 3 ; + COMPARE ; + EQ ; + IF { SWAP ; DROP ; NONE nat } { SWAP ; SOME } ; + DIG 3 ; + DUP ; + DUG 4 ; + CAR ; + UPDATE ; + DIG 2 ; + DUP ; + DUG 3 ; + CDR ; + CDR ; + SWAP ; + DUP ; + DUG 2 ; + DIG 4 ; + DUP ; + DUG 5 ; + CDR ; + CAR ; + GET ; + IF_NONE { PUSH nat 0 } {} ; + ADD ; + SWAP ; + PUSH nat 0 ; + DIG 2 ; + DUP ; + DUG 3 ; + COMPARE ; + EQ ; + IF { SWAP ; DROP ; NONE nat } { SWAP ; SOME } ; + DIG 3 ; + CDR ; + CAR ; + UPDATE ; + DIG 2 ; + CDR ; + SWAP ; + PAIR ; + DUP ; + CDR ; + CDR ; + DIG 2 ; + PAIR ; + SWAP ; + CAR ; + PAIR ; + NIL operation ; + PAIR } } } } + diff --git a/src/proto_020_PsParisC/lib_protocol/contracts/timelock_flip.tz b/src/proto_020_PsParisC/lib_protocol/contracts/timelock_flip.tz new file mode 100644 index 000000000000..1d0c6cbe2c40 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/contracts/timelock_flip.tz @@ -0,0 +1,95 @@ +# This contract emulates a time constrained "guess who" game using timelocks. +# The goal of the game if for the challenger to guess which value was stored by +# the game initiator. The challenger only has one guess, and must submit it +# within 10 blocks of the game initialization. +# +# More particularly, the game relies on a timelock primitive using a difficulty +# set to 1_024 and a hardwritten threshold for guessing of 10 blocks. Beware, +# this contract is for education purpose only to demonstrate the use of +# timelock. In particular, the contract may not be secure, the game can be +# reinitialised at any time and the timelock difficulty and threshold values +# were chosen arbitrarily. +# +# Its storage consists of 4 values: the level and timelock chest, in which the +# value to guess is stored, set up at the game's initialization, the guess +# written in bytes, and the message to know the game status and result. +# +# The game unfolds as such: +# 1) Initilialising the game with a timelock chest: +# User A publishes a timelock chest to start a game, the contract +# initializes the storage's level to the current level and the guess and +# message to a hardcoded value (0xA0). +# 2) Submitting the guess: +# User B publishes a guess, the guess is saved if and only if the current +# level is lower than the contract's plus 10 blocks (else the game is blocked +# but the contract can be reinitialised with a new timelock chest at anytime), +# we also update the message to another hardcoded value (0xB0). +# Note the guess can be updated several times and that no verification is made +# on who is sending it. +# 3) Revealing the time-locked value: +# Finally, user A (or B) submits a chest_key. If the timelock opening is +# successful, the contract compares the guess to the timelock message. If the +# bytes are equal, the message is updated to 0x00 else 0x01. If the opening +# fails, the message is updated to 0x10. + +storage (pair (nat %level) chest (bytes %guess) (bytes %result)); +parameter ( or (chest %initialize_game) (or (bytes %guess) (chest_key %finish_game))); +code { UNPAIR 5; + IF_LEFT { # If we receive a chest, + # we reinitialise the storage + # with the new chest and current level. + DIP {DROP 4}; + PUSH bytes 0xA0; + DUP; + PAIR; + SWAP; + LEVEL; + PAIR 3} + { IF_LEFT { # If we receive a guess, + SWAP; + DUP; + PUSH nat 10; + ADD; + LEVEL; + COMPARE; + LE; + IF { # we store the guess if current level < stored level + 10 + DIP 2 {PUSH bytes 0xB0}; + DIP {PAIR; SWAP; PAIR}; + PAIR; + DIP {DROP 2}; + } + { # else we keep the storage unchanged. + SWAP; + DROP; + PAIR 4}; + } + { # If we receive a chest_key, + # we open the chest. + DIP 4 {DROP}; + DUP 3; + SWAP; + DIP 2 {PUSH nat 1024}; + OPEN_CHEST; + IF_SOME { # If the chest opens successfully, + # we compare the guess with the locked value. + DUP 4; + COMPARE; + EQ; + IF { # If they are equal we store 0x00 + PUSH bytes 0x00} + { # else we store 0x01 + PUSH bytes 0x01}} + { # We store 0x10 in case of failure + PUSH bytes 0x10}; + DIG 3; + PAIR; + DIG 2; + PAIR; + DIG 1; + PAIR; + }; + }; + NIL operation; + PAIR; + } \ No newline at end of file diff --git a/src/proto_020_PsParisC/lib_protocol/cycle_repr.ml b/src/proto_020_PsParisC/lib_protocol/cycle_repr.ml new file mode 100644 index 000000000000..b1a4b8bc6e0b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cycle_repr.ml @@ -0,0 +1,85 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = int32 + +type cycle = t + +let encoding = Data_encoding.int32 + +let rpc_arg = RPC_arg.like RPC_arg.uint31 ~descr:"A cycle integer" "block_cycle" + +let pp ppf cycle = Format.fprintf ppf "%ld" cycle + +include (Compare.Int32 : Compare.S with type t := t) + +module Map = Map.Make (Compare.Int32) + +let root = 0l + +let succ = Int32.succ + +let pred = function 0l -> None | i -> Some (Int32.pred i) + +let add c i = + assert (Compare.Int.(i >= 0)) ; + Int32.add c (Int32.of_int i) + +let sub c i = + assert (Compare.Int.(i >= 0)) ; + let r = Int32.sub c (Int32.of_int i) in + if Compare.Int32.(r < 0l) then None else Some r + +let diff = Int32.sub + +let to_int32 i = i + +let of_int32_exn l = + if Compare.Int32.(l >= 0l) then l else invalid_arg "Cycle_repr.of_int32_exn" + +let of_string_exn s = + let int32_opt = Int32.of_string_opt s in + match int32_opt with + | None -> invalid_arg "Cycle_repr.of_string_exn" + | Some int32 -> of_int32_exn int32 + +let ( ---> ) = Misc.( ---> ) + +module Index = struct + type t = cycle + + let path_length = 1 + + let to_path c l = Int32.to_string (to_int32 c) :: l + + let of_path = function [s] -> Int32.of_string_opt s | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_020_PsParisC/lib_protocol/cycle_repr.mli b/src/proto_020_PsParisC/lib_protocol/cycle_repr.mli new file mode 100644 index 000000000000..7ff7a730bb82 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/cycle_repr.mli @@ -0,0 +1,66 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides a type and functions to manipulate cycle numbers. + + Invariant: cycle numbers are always positive. *) + +type t + +type cycle = t + +include Compare.S with type t := t + +val encoding : cycle Data_encoding.t + +val rpc_arg : cycle RPC_arg.arg + +val pp : Format.formatter -> cycle -> unit + +val root : cycle + +val pred : cycle -> cycle option + +val add : cycle -> int -> cycle + +val sub : cycle -> int -> cycle option + +val succ : cycle -> cycle + +val diff : cycle -> cycle -> int32 + +(** a ---> b = [a; ...; b] *) +val ( ---> ) : cycle -> cycle -> cycle list + +val to_int32 : cycle -> int32 + +val of_int32_exn : int32 -> cycle + +val of_string_exn : string -> cycle + +module Map : Map.S with type key = cycle + +module Index : Storage_description.INDEX with type t = cycle diff --git a/src/proto_020_PsParisC/lib_protocol/dal_apply.ml b/src/proto_020_PsParisC/lib_protocol/dal_apply.ml new file mode 100644 index 000000000000..c3c5b1aa16fc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_apply.ml @@ -0,0 +1,132 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Every function of this file should check the feature flag. *) + +open Alpha_context +open Dal_errors + +let assert_dal_feature_enabled ctxt = + let open Constants in + let Parametric.{dal = {feature_enable; _}; _} = parametric ctxt in + error_unless Compare.Bool.(feature_enable = true) Dal_feature_disabled + +let only_if_dal_feature_enabled ctxt ~default f = + let open Constants in + let Parametric.{dal = {feature_enable; _}; _} = parametric ctxt in + if feature_enable then f ctxt else default ctxt + +let slot_of_int_e ~number_of_slots n = + let open Result_syntax in + match Dal.Slot_index.of_int_opt ~number_of_slots n with + | None -> + tzfail + @@ Dal_errors.Dal_slot_index_above_hard_limit + {given = n; limit = number_of_slots - 1} + | Some slot_index -> return slot_index + +(* Use this function to select the pkh used in the DAL committee. As long as an + epoch does not span across multiple cycles, we could use as well the pkh of + the consensus key. *) +let pkh_of_consensus_key (consensus_key : Consensus_key.pk) = + consensus_key.delegate + +let validate_attestation ctxt level slot consensus_key attestation = + let open Lwt_result_syntax in + let*? () = assert_dal_feature_enabled ctxt in + let number_of_slots = Dal.number_of_slots ctxt in + let*? max_index = number_of_slots - 1 |> slot_of_int_e ~number_of_slots in + let maximum_size = Dal.Attestation.expected_size_in_bits ~max_index in + let size = Dal.Attestation.occupied_size_in_bits attestation in + let*? () = + error_unless + Compare.Int.(size <= maximum_size) + (Dal_attestation_size_limit_exceeded {maximum_size; got = size}) + in + let number_of_shards = Dal.number_of_shards ctxt in + fail_when + Compare.Int.(Slot.to_int slot >= number_of_shards) + (let attester = pkh_of_consensus_key consensus_key in + Dal_data_availibility_attester_not_in_committee {attester; level; slot}) + +let apply_attestation ctxt attestation ~power = + let open Result_syntax in + let* () = assert_dal_feature_enabled ctxt in + return + (Dal.Attestation.record_number_of_attested_shards ctxt attestation power) + +(* This function should fail if we don't want the operation to be + propagated over the L1 gossip network. Because this is a manager + operation, there are already checks to ensure the source of + operation has enough fees. Among the various checks, there are + checks that cannot fail unless the source of the operation is + malicious (or if there is a bug). In that case, it is better to + ensure fees will be taken. *) +let validate_publish_commitment ctxt _operation = + assert_dal_feature_enabled ctxt + +let apply_publish_commitment ctxt operation = + let open Result_syntax in + let* ctxt = Gas.consume ctxt Dal_costs.cost_Dal_publish_commitment in + let number_of_slots = Dal.number_of_slots ctxt in + let* ctxt, cryptobox = Dal.make ctxt in + let current_level = (Level.current ctxt).level in + let* slot_header = + Dal.Operations.Publish_commitment.slot_header + ~cryptobox + ~number_of_slots + ~current_level + operation + in + let* ctxt = Dal.Slot.register_slot_header ctxt slot_header in + return (ctxt, slot_header) + +let finalisation ctxt = + let open Lwt_result_syntax in + only_if_dal_feature_enabled + ctxt + ~default:(fun ctxt -> return (ctxt, Dal.Attestation.empty)) + (fun ctxt -> + let*! ctxt = Dal.Slot.finalize_current_slot_headers ctxt in + (* The fact that slots confirmation is done at finalization is very + important for the assumptions made by the Dal refutation game. In fact: + - {!Dal.Slot.finalize_current_slot_headers} updates the Dal skip list + at block finalization, by inserting newly confirmed slots; + - {!Sc_rollup.Game.initial}, called when applying a manager operation + that starts a refutation game, makes a snapshot of the Dal skip list + to use it as a reference if the refutation proof involves a Dal input. + + If confirmed Dal slots are inserted into the skip list during operations + application, adapting how refutation games are made might be needed + to e.g., + - use the same snapshotted skip list as a reference by L1 and rollup-node; + - disallow proofs involving pages of slots that have been confirmed at the + level where the game started. + *) + let number_of_slots = (Constants.parametric ctxt).dal.number_of_slots in + let+ ctxt, attestation = + Dal.Slot.finalize_pending_slot_headers ctxt ~number_of_slots + in + (ctxt, attestation)) diff --git a/src/proto_020_PsParisC/lib_protocol/dal_apply.mli b/src/proto_020_PsParisC/lib_protocol/dal_apply.mli new file mode 100644 index 000000000000..55bd78051f1a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_apply.mli @@ -0,0 +1,72 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This modules handles all the validation/application/finalisation + of any operation related to the DAL. *) + +open Alpha_context + +(** [validate_attestation ctxt level slot consensus_key attestation] checks + whether the DAL attestation [attestation] emitted at given [level] by the + attester with the given [consensus_key] and given [slot] is valid. If an + [Error _] is returned, the [op] is not valid. The checks made are: + * the attestation size does not exceed the maximum; + * the delegate is in the DAL committee. + + These are checks done for the DAL part alone, checks on other fields of an + attestation (like level, round) are done by the caller. *) +val validate_attestation : + t -> + Raw_level.t -> + Slot.t -> + Consensus_key.pk -> + Dal.Attestation.t -> + unit tzresult Lwt.t + +(** [apply_attestation ctxt attestation] records in the context that the given + [attestation] was issued and the corresponding attester has the given + [power]. *) +val apply_attestation : t -> Dal.Attestation.t -> power:int -> t tzresult + +(** [validate_publish_commitment ctxt slot] ensures that [slot_header] is + valid and prevents an operation containing [slot_header] to be + refused on top of [ctxt]. If an [Error _] is returned, the [slot_header] + is not valid. *) +val validate_publish_commitment : + t -> Dal.Operations.Publish_commitment.t -> unit tzresult + +(** [apply_publish_commitment ctxt slot_header] applies the publication of + slot header [slot_header] on top of [ctxt]. Fails if the slot contains + already a slot header. *) +val apply_publish_commitment : + t -> Dal.Operations.Publish_commitment.t -> (t * Dal.Slot.Header.t) tzresult + +(** [finalisation ctxt] should be executed at block finalisation + time. A set of slots attested at level [ctxt.current_level - lag] + is returned encapsulated into the attestation data-structure. + + [lag] is a parametric constant specific to the data-availability + layer. *) +val finalisation : t -> (t * Dal.Attestation.t) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.ml b/src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.ml new file mode 100644 index 000000000000..920e04d7da5c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.ml @@ -0,0 +1,141 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3103 + + This may be a bit heavy in practice. We could also assume that in + practice, many bits in this bitfield will be set to one. Hence, we + could consider a better encoding which is smaller in the optimistic + case. For example: + + 1. When all the slots are attested, the encoding can be represented + in one bit. + + 2. Otherwise, we can pack slots by [8]. Have a header of [slots/8] + which is [1] if all the slots in this set are [1], [0] + otherwise. For all pack with a bit set to [0], we give the explicit + representation. Hence, if there are [256] slots, and [2] are not + attested, this representation will be of size [32] bits + [16] bits + = [48] bits which is better than [256] bits. *) + +(* A set of (attested) slot indexes. *) +type t = Bitset.t + +let encoding = Bitset.encoding + +let empty = Bitset.empty + +let is_attested t index = + let open Dal_slot_index_repr in + match Bitset.mem t (to_int index) with + | Ok b -> b + | Error _ -> + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3104 + + Should we do something here? *) + false + +let commit t index = + let open Dal_slot_index_repr in + match Bitset.add t (to_int index) with + | Ok t -> t + | Error _ -> + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3104 + + Should we do something here? *) + t + +let occupied_size_in_bits = Bitset.occupied_size_in_bits + +let expected_size_in_bits ~max_index = + (* We compute an encoding of the data-availability attestations + which is a (tight) upper bound of what we expect. *) + let open Bitset in + let open Dal_slot_index_repr in + match add empty @@ to_int max_index with + | Error _ -> (* Happens if max_index < 1 *) 0 + | Ok t -> occupied_size_in_bits t + +let number_of_attested_slots = Bitset.hamming_weight + +type shard_index = int + +module Shard_map = Map.Make (struct + type t = shard_index + + let compare = Compare.Int.compare +end) + +module Accountability = struct + type attested_slots = t + + module SlotMap = Map.Make (Compare.Int) + + type t = {number_of_attested_shards : int SlotMap.t; number_of_slots : int} + + let init ~number_of_slots = + {number_of_attested_shards = SlotMap.empty; number_of_slots} + + (* This function must be called at most once for a given attester; otherwise + the count will be flawed. *) + let record_number_of_attested_shards t baker_attested_slots + number_of_baker_shards = + let rec iter slot_index map = + if Compare.Int.(slot_index >= t.number_of_slots) then map + else + let map = + match Bitset.mem baker_attested_slots slot_index with + | Error _ -> + (* impossible, as [slot_index] is non-negative *) + map + | Ok true -> + (* slot is attested by baker *) + SlotMap.update + slot_index + (function + | None -> Some number_of_baker_shards + | Some old_number_of_attested_shards -> + Some + (old_number_of_attested_shards + number_of_baker_shards)) + map + | Ok false -> + (* slot is not attested by baker, nothing to update *) + map + in + iter (slot_index + 1) map + in + let number_of_attested_shards = iter 0 t.number_of_attested_shards in + {t with number_of_attested_shards} + + let is_slot_attested t ~threshold ~number_of_shards slot_index = + let index = Dal_slot_index_repr.to_int slot_index in + let number_of_attested_shards = + match SlotMap.find index t.number_of_attested_shards with + | None -> 0 + | Some v -> v + in + Compare.Int.( + number_of_attested_shards >= threshold * number_of_shards / 100) +end diff --git a/src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.mli b/src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.mli new file mode 100644 index 000000000000..a9edc93ac34c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_attestation_repr.mli @@ -0,0 +1,119 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Slot attestation representation for the data-availability layer. + + {1 Overview} + + For the data-availability layer, the layer 1 provides a list of + slots at every level (see {!Dal_slot_repr}). Slots are not posted + directly onto L1 blocks. Stakeholders, called attesters in this + context, can attest on the availability of the data via + attestation operations. + + The slot is uniformly split into shards. Each attester commits, + for every slot, on the availability of all shards they are assigned + to. + + This module encapsulates the representation of this commitment + that aims to be provided with attestation operations. To avoid + overloading the network, this representation should be compact. *) + +type t = private Bitset.t + +(** The size of the encoding is not bounded. However, the size of a DAL + attestation bitset is checked during validation of an attestation; and there + is a bound on the size of a generic operation. *) +val encoding : t Data_encoding.t + +(** [empty] returns an empty [slot_attestation] which commits that + every slot are unavailable. *) +val empty : t + +(** [is_attested slot_attestation ~index] returns [true] if the + [slot_attestation] commits that the slot at [index] is + available. *) +val is_attested : t -> Dal_slot_index_repr.t -> bool + +(** [commit slot_attestation index] commits into [slot_attestation] + that the slot [index] is available. *) +val commit : t -> Dal_slot_index_repr.t -> t + +(** [occupied_size_in_bits slot_attestation] returns the size in bits of an attestation. *) +val occupied_size_in_bits : t -> int + +(** [expected_size_in_bits ~max_index] returns the expected size (in + bits) of an attestation considering the maximum index for a slot is + [max_index]. *) +val expected_size_in_bits : max_index:Dal_slot_index_repr.t -> int + +(** [number_of_attested_slots slot_attestation] returns the number of attested + slots in an attestation. *) +val number_of_attested_slots : t -> int + +(** A shard_index aims to be a positive number. *) +type shard_index = int + +module Shard_map : Map.S with type key = shard_index + +(** This module is used to record the shard attestations. + + For each attester, a list of shards is associated. For each + attested slot (see {!type:t}) we record that those shards were + deemed available. + + This information will be used at the end of block finalisation to + have the protocol declaring whether the slot is available. *) +module Accountability : sig + type attested_slots = t + + (** The data-structure used to record the shards attestations. *) + type t + + (** DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3145 + + Consider using the [Bounded] module. In particular, change the + semantics of [is_slot_attested] accordingly. *) + + (** [init ~number_of_slots] initialises a new accountability data-structure + with [number_of_slots] slots and where for every slot, no shard is + available. *) + val init : number_of_slots:int -> t + + (** [record_number_of_attested_shards t slots number] records that, for all + slots declared available in [slots], the given [number] of shard indices + are deemed available. This function must be called at most once for a + given attester; otherwise the count will be flawed. *) + val record_number_of_attested_shards : t -> attested_slots -> int -> t + + (** [is_slot_attested t ~threshold ~number_of_shards slot] returns [true] if + the number of shards recorded in [t] for the [slot] is above the + [threshold] with respect to the total number of shards specified by + [number_of_shards]. Returns [false] otherwise or if the [index] is out of + the interval [0; number_of_slots - 1] where [number_of_slots] is the value + provided to the [init] function. *) + val is_slot_attested : + t -> threshold:int -> number_of_shards:int -> Dal_slot_index_repr.t -> bool +end diff --git a/src/proto_020_PsParisC/lib_protocol/dal_costs.ml b/src/proto_020_PsParisC/lib_protocol/dal_costs.ml new file mode 100644 index 000000000000..1ae36dbddd4a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_costs.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Dal_costs_generated diff --git a/src/proto_020_PsParisC/lib_protocol/dal_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/dal_costs_generated.ml new file mode 100644 index 000000000000..5e4e6d5cb4be --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_costs_generated.ml @@ -0,0 +1,14 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model dal/Dal_publish_commitment *) +(* max 10 1160000. *) +let cost_Dal_publish_commitment = S.safe_int 1160000 diff --git a/src/proto_020_PsParisC/lib_protocol/dal_costs_generated.mli b/src/proto_020_PsParisC/lib_protocol/dal_costs_generated.mli new file mode 100644 index 000000000000..341e8e8ffd1d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_costs_generated.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val cost_Dal_publish_commitment : Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/dal_errors_repr.ml b/src/proto_020_PsParisC/lib_protocol/dal_errors_repr.ml new file mode 100644 index 000000000000..585b9b6f78cc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_errors_repr.ml @@ -0,0 +1,248 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Dal_feature_disabled + | Dal_slot_index_above_hard_limit of {given : int; limit : int} + | Dal_publish_commitment_invalid_index of { + given : Dal_slot_index_repr.t; + maximum : Dal_slot_index_repr.t; + } + | Dal_publish_commitment_candidate_with_low_fees of { + proposed_fees : Tez_repr.t; + } + | Dal_attestation_size_limit_exceeded of {maximum_size : int; got : int} + | Dal_publish_commitment_duplicate of {slot_header : Dal_slot_repr.Header.t} + | Dal_publish_commitment_invalid_proof of { + commitment : Dal.commitment; + commitment_proof : Dal.commitment_proof; + } + | Dal_data_availibility_attester_not_in_committee of { + attester : Signature.Public_key_hash.t; + level : Raw_level_repr.t; + slot : Slot_repr.t; + } + | Dal_cryptobox_error of {explanation : string} + | Dal_register_invalid_slot_header of { + length : int; + slot_header : Dal_slot_repr.Header.t; + } + +let () = + let open Data_encoding in + let description = + "Data-availability layer will be enabled in a future proposal." + in + register_error_kind + `Permanent + ~id:"operation.dal_disabled" + ~title:"DAL is disabled" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Dal_feature_disabled -> Some () | _ -> None) + (fun () -> Dal_feature_disabled) ; + + let description = "Slot index above hard limit" in + register_error_kind + `Permanent + ~id:"dal_slot_index_negative_orabove_hard_limit" + ~title:"DAL slot index negative or above hard limit" + ~description + ~pp:(fun ppf (given, limit) -> + Format.fprintf + ppf + "%s (given %Ld): Maximum allowed %Ld." + description + given + limit) + (obj2 (req "given" Data_encoding.int64) (req "limit" Data_encoding.int64)) + (function + | Dal_slot_index_above_hard_limit {given; limit} -> + Some (Int64.of_int given, Int64.of_int limit) + | _ -> None) + (fun (given, limit) -> + Dal_slot_index_above_hard_limit + {given = Int64.to_int given; limit = Int64.to_int limit}) ; + let description = "Bad index for slot header" in + register_error_kind + `Permanent + ~id:"dal_publish_commitment_invalid_index" + ~title:"DAL slot header invalid index" + ~description + ~pp:(fun ppf (given, maximum) -> + Format.fprintf + ppf + "%s: Given %a. Maximum %a." + description + Dal_slot_index_repr.pp + given + Dal_slot_index_repr.pp + maximum) + (obj2 + (req "given" Dal_slot_index_repr.encoding) + (req "got" Dal_slot_index_repr.encoding)) + (function + | Dal_publish_commitment_invalid_index {given; maximum} -> + Some (given, maximum) + | _ -> None) + (fun (given, maximum) -> + Dal_publish_commitment_invalid_index {given; maximum}) ; + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3114 + Better error message *) + let description = "Slot header with too low fees" in + register_error_kind + `Permanent + ~id:"dal_publish_commitment_with_low_fees" + ~title:"DAL slot header with low fees" + ~description + ~pp:(fun ppf proposed -> + Format.fprintf + ppf + "%s: Proposed fees %a." + description + Tez_repr.pp + proposed) + (obj1 (req "proposed" Tez_repr.encoding)) + (function + | Dal_publish_commitment_candidate_with_low_fees {proposed_fees} -> + Some proposed_fees + | _ -> None) + (fun proposed_fees -> + Dal_publish_commitment_candidate_with_low_fees {proposed_fees}) ; + let description = "The attestation for data availability is a too big" in + register_error_kind + `Permanent + ~id:"dal_attestation_size_limit_exceeded" + ~title:"DAL attestation exceeded the limit" + ~description + ~pp:(fun ppf (maximum_size, got) -> + Format.fprintf + ppf + "%s: Maximum is %d. Got %d." + description + maximum_size + got) + (obj2 (req "maximum_size" int31) (req "got" int31)) + (function + | Dal_attestation_size_limit_exceeded {maximum_size; got} -> + Some (maximum_size, got) + | _ -> None) + (fun (maximum_size, got) -> + Dal_attestation_size_limit_exceeded {maximum_size; got}) ; + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3114 + Better error message. *) + let description = "A slot header for this slot was already proposed" in + register_error_kind + `Permanent + ~id:"dal_publish_commitment_duplicate" + ~title:"DAL publish slot header duplicate" + ~description + ~pp:(fun ppf _proposed -> Format.fprintf ppf "%s" description) + (obj1 (req "proposed" Dal_slot_repr.Header.encoding)) + (function + | Dal_publish_commitment_duplicate {slot_header} -> Some slot_header + | _ -> None) + (fun slot_header -> Dal_publish_commitment_duplicate {slot_header}) ; + let description = "The slot header's commitment proof does not check" in + register_error_kind + `Permanent + ~id:"dal_publish_commitment_invalid_proof" + ~title:"DAL publish slot header invalid proof" + ~description + ~pp:(fun ppf _proposed -> Format.fprintf ppf "%s" description) + (obj2 + (req "commitment" Dal.Commitment.encoding) + (req "commitment_proof" Dal.Commitment_proof.encoding)) + (function + | Dal_publish_commitment_invalid_proof {commitment; commitment_proof} -> + Some (commitment, commitment_proof) + | _ -> None) + (fun (commitment, commitment_proof) -> + Dal_publish_commitment_invalid_proof {commitment; commitment_proof}) ; + register_error_kind + `Permanent + ~id:"Dal_data_availibility_attester_not_in_committee" + ~title:"The attester is not part of the DAL committee for this level" + ~description:"The attester is not part of the DAL committee for this level" + ~pp:(fun ppf (attester, level, slot) -> + Format.fprintf + ppf + "The attester %a, with slot %a, is not part of the DAL committee for \ + the level %a." + Signature.Public_key_hash.pp + attester + Slot_repr.pp + slot + Raw_level_repr.pp + level) + Data_encoding.( + obj3 + (req "attester" Signature.Public_key_hash.encoding) + (req "level" Raw_level_repr.encoding) + (req "slot" Slot_repr.encoding)) + (function + | Dal_data_availibility_attester_not_in_committee {attester; level; slot} + -> + Some (attester, level, slot) + | _ -> None) + (fun (attester, level, slot) -> + Dal_data_availibility_attester_not_in_committee {attester; level; slot}) ; + register_error_kind + `Permanent + ~id:"dal_cryptobox_error" + ~title:"DAL cryptobox error" + ~description:"Error occurred while initialising the cryptobox" + ~pp:(fun ppf e -> + Format.fprintf ppf "DAL cryptobox initialisation error: %s" e) + (obj1 (req "error" (string Plain))) + (function + | Dal_cryptobox_error {explanation} -> Some explanation | _ -> None) + (fun explanation -> Dal_cryptobox_error {explanation}) ; + register_error_kind + `Permanent + ~id:"dal_register_invalid_slot" + ~title:"Dal register invalid slot" + ~description: + "Attempt to register a slot which is invalid (the index is out of \ + bounds)." + ~pp:(fun ppf (length, slot) -> + Format.fprintf + ppf + "The slot provided is invalid. Slot index should be between 0 and %d. \ + Found: %a." + length + Dal_slot_index_repr.pp + slot.Dal_slot_repr.Header.id.index) + Data_encoding.( + obj2 + (req "length" int31) + (req "slot_header" Dal_slot_repr.Header.encoding)) + (function + | Dal_register_invalid_slot_header {length; slot_header} -> + Some (length, slot_header) + | _ -> None) + (fun (length, slot_header) -> + Dal_register_invalid_slot_header {length; slot_header}) diff --git a/src/proto_020_PsParisC/lib_protocol/dal_operations_repr.ml b/src/proto_020_PsParisC/lib_protocol/dal_operations_repr.ml new file mode 100644 index 000000000000..fc9311f83bfc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_operations_repr.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Publish_commitment = struct + type t = { + slot_index : Dal_slot_index_repr.t; + commitment : Dal_slot_repr.Commitment.t; + commitment_proof : Dal_slot_repr.Commitment_proof.t; + } + + let encoding = + let open Data_encoding in + conv + (fun {slot_index; commitment; commitment_proof} -> + (slot_index, commitment, commitment_proof)) + (fun (slot_index, commitment, commitment_proof) -> + {slot_index; commitment; commitment_proof}) + (obj3 + (req "slot_index" Dal_slot_index_repr.encoding) + (req "commitment" Dal_slot_repr.Commitment.encoding) + (req "commitment_proof" Dal_slot_repr.Commitment_proof.encoding)) + + let pp fmt {slot_index; commitment; commitment_proof = _} = + Format.fprintf + fmt + "slot_index: %a, commitment: %a" + Dal_slot_index_repr.pp + slot_index + Dal.Commitment.pp + commitment + + let slot_header ~cryptobox ~number_of_slots ~current_level + ({slot_index; commitment; commitment_proof} as operation) = + let open Result_syntax in + let* max_slot_index = + Dal_slot_index_repr.of_int ~number_of_slots (number_of_slots - 1) + in + let* () = + error_unless + Compare.Int.( + Dal_slot_index_repr.compare slot_index max_slot_index <= 0 + && Dal_slot_index_repr.compare slot_index Dal_slot_index_repr.zero + >= 0) + (Dal_errors_repr.Dal_publish_commitment_invalid_index + {given = slot_index; maximum = max_slot_index}) + in + let* proof_ok = + Dal_slot_repr.Header.verify_commitment + cryptobox + operation.commitment + operation.commitment_proof + in + let* () = + error_unless + proof_ok + (Dal_errors_repr.Dal_publish_commitment_invalid_proof + {commitment; commitment_proof}) + in + return + Dal_slot_repr.Header. + {id = {published_level = current_level; index = slot_index}; commitment} +end diff --git a/src/proto_020_PsParisC/lib_protocol/dal_operations_repr.mli b/src/proto_020_PsParisC/lib_protocol/dal_operations_repr.mli new file mode 100644 index 000000000000..972f5749d9ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_operations_repr.mli @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {1 DAL operations} + + This module gathers the datatypes for the payloads of DAL operations. + + This module ensures the consistency with the internal + data-structures like [Dal_slot_index_repr.t]. *) + +module Publish_commitment : sig + (** A "publish slot header" operation contains + + - a [slot_index] which is the slot index associated with the + commitment. + + - a [commitment] which is a commitment to the slot data published + onto the DAL + + - a [commitment_proof] which aims to prove that the size + of the slot data does not exceed a limit set by the + protocol. *) + type t = { + slot_index : Dal_slot_index_repr.t; + commitment : Dal_slot_repr.Commitment.t; + commitment_proof : Dal_slot_repr.Commitment_proof.t; + } + + val encoding : t Data_encoding.t + + val pp : Format.formatter -> t -> unit + + (** [slot_header ~cryptobox ~number_of_slots ~current_level + operation] constructs a valid slot header. This function can fail + in the following cases: + + - The [published_level] is not equal to [current_level] + + - The [commitment_proof] is invalid + + - The [slot_index] is invalid *) + val slot_header : + cryptobox:Dal.t -> + number_of_slots:int -> + current_level:Raw_level_repr.t -> + t -> + Dal_slot_repr.Header.t tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/dal_services.ml b/src/proto_020_PsParisC/lib_protocol/dal_services.ml new file mode 100644 index 000000000000..1668c2f1b40a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_services.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let assert_dal_feature_enabled ctxt = + let open Constants in + let Parametric.{dal = {feature_enable; _}; _} = parametric ctxt in + error_unless + Compare.Bool.(feature_enable = true) + Dal_errors.Dal_feature_disabled + +(* Slots returned by this function are assumed by consumers to be in increasing + order, hence the use of [Slot.Range.rev_fold_es]. *) +let shards ctxt ~level = + let open Lwt_result_syntax in + let*? () = assert_dal_feature_enabled ctxt in + let number_of_shards = Dal.number_of_shards ctxt in + let*? slots = Slot.Range.create ~min:0 ~count:number_of_shards in + Slot.Range.rev_fold_es + (fun (ctxt, map) slot -> + let* ctxt, consensus_pk = Stake_distribution.slot_owner ctxt level slot in + let slot = Slot.to_int slot in + let map = + Signature.Public_key_hash.Map.update + consensus_pk.delegate + (function None -> Some [slot] | Some slots -> Some (slot :: slots)) + map + in + return (ctxt, map)) + (ctxt, Signature.Public_key_hash.Map.empty) + slots diff --git a/src/proto_020_PsParisC/lib_protocol/dal_services.mli b/src/proto_020_PsParisC/lib_protocol/dal_services.mli new file mode 100644 index 000000000000..25d8803106af --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_services.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [shards ctxt ~level] returns the DAL committee as a mapping from the public + key hash of members of the committee to the list of shard indexes associated + to that member. *) +val shards : + Alpha_context.t -> + level:Alpha_context.Level.t -> + (Alpha_context.t * int list Signature.Public_key_hash.Map.t) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.ml b/src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.ml new file mode 100644 index 000000000000..ce2abb9d0910 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.ml @@ -0,0 +1,90 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = int + +let encoding = Data_encoding.uint8 + +let pp = Format.pp_print_int + +let zero = 0 + +type error += Invalid_slot_index of {given : int; min : int; max : int} + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"dal_slot_index_repr.index.invalid_index" + ~title:"Invalid Dal slot index" + ~description:"The given index is out of range of representable slot indices" + ~pp:(fun ppf (given, min, max) -> + Format.fprintf + ppf + "The given index %d is out of range of representable slot indices [%d, \ + %d]" + given + min + max) + (obj3 (req "given" int31) (req "min" int31) (req "max" int31)) + (function + | Invalid_slot_index {given; min; max} -> Some (given, min, max) + | _ -> None) + (fun (given, min, max) -> Invalid_slot_index {given; min; max}) + +let check_is_in_range ~number_of_slots slot_index = + error_unless + Compare.Int.(slot_index >= zero && slot_index < number_of_slots) + (Invalid_slot_index + {given = slot_index; min = zero; max = number_of_slots - 1}) + +let of_int ~number_of_slots slot_index = + let open Result_syntax in + let* () = check_is_in_range ~number_of_slots slot_index in + return slot_index + +let of_int_opt ~number_of_slots slot_index = + Option.of_result @@ of_int ~number_of_slots slot_index + +let to_int slot_index = slot_index [@@ocaml.inline always] + +let to_int_list l = l [@@ocaml.inline always] + +include Compare.Make (struct + type nonrec t = t + + let compare = Compare.Int.compare +end) + +let slots_range ~number_of_slots ~lower ~upper = + let open Result_syntax in + let* () = check_is_in_range ~number_of_slots lower in + let* () = check_is_in_range ~number_of_slots upper in + return Misc.(lower --> upper) + +let slots_range_opt ~number_of_slots ~lower ~upper = + Option.of_result @@ slots_range ~number_of_slots ~lower ~upper + +let is_succ t ~succ = Compare.Int.(t + 1 = succ) diff --git a/src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.mli b/src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.mli new file mode 100644 index 000000000000..380825600d5a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_slot_index_repr.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {1 Slot index} + + A slot index is a possible value for a slot index with an upper + bound. If a choice is ever made to increase the size of available + slots in the protocol, we also need to change this module to + accommodate for higher values. *) +type t + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +val zero : t + +type error += Invalid_slot_index of {given : t; min : t; max : t} + +val check_is_in_range : number_of_slots:int -> t -> unit tzresult + +(** [of_int ~number_of_slots n] constructs a value of type {!t} from [n]. Returns + {!Invalid_slot_index} in case the given value is not in the interval + [[zero, number_of_slots-1]]. *) +val of_int : number_of_slots:int -> int -> t tzresult + +(** [of_int_opt ~number_of_slots n] constructs a value of type {!t} from [n]. Returns [None] + in case the given value is not in the interval [[zero, number_of_slots-1]]. *) +val of_int_opt : number_of_slots:int -> int -> t option + +val to_int : t -> int + +val to_int_list : t list -> int list + +(** [slots_range ~number_of_slots ~lower ~upper] returns the list of slots indexes between + [lower] and [upper]. + + If [lower] is negative or [upper] is bigger than or equal to [number_of_slots], the function + returns {!Invalid_slot_index}. *) +val slots_range : + number_of_slots:int -> lower:int -> upper:int -> t list tzresult + +(** [slots_range_opt ~number_of_slots ~lower ~upper] is similar to {!slots_range}, but return + [None] instead of an error. *) +val slots_range_opt : + number_of_slots:int -> lower:int -> upper:int -> t list option + +(** [is_succ elt ~succ] returns true if and only if elt + 1 = succ. *) +val is_succ : t -> succ:t -> bool + +include Compare.S with type t := t diff --git a/src/proto_020_PsParisC/lib_protocol/dal_slot_repr.ml b/src/proto_020_PsParisC/lib_protocol/dal_slot_repr.ml new file mode 100644 index 000000000000..c1d216aee885 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_slot_repr.ml @@ -0,0 +1,1079 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type parameters = Dal.parameters = { + redundancy_factor : int; + page_size : int; + slot_size : int; + number_of_shards : int; +} + +let parameters_encoding = Dal.parameters_encoding + +module Commitment = struct + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3389 + + It is not clear whether the size of the slot associated to the + commitment should be given here. *) + type t = Dal.commitment + + let equal = Dal.Commitment.equal + + let encoding = Dal.Commitment.encoding + + let pp = Dal.Commitment.pp + + let zero = Dal.Commitment.zero + + let of_b58check_opt = Dal.Commitment.of_b58check_opt +end + +module Commitment_proof = struct + type t = Dal.commitment_proof + + let encoding = Dal.Commitment_proof.encoding + + let zero = Dal.Commitment_proof.zero +end + +module Header = struct + type id = {published_level : Raw_level_repr.t; index : Dal_slot_index_repr.t} + + type t = {id : id; commitment : Commitment.t} + + let slot_id_equal {published_level; index} s2 = + Raw_level_repr.equal published_level s2.published_level + && Dal_slot_index_repr.equal index s2.index + + let equal {id; commitment} s2 = + slot_id_equal id s2.id && Commitment.equal commitment s2.commitment + + let id_encoding = + let open Data_encoding in + conv + (fun {published_level; index} -> (published_level, index)) + (fun (published_level, index) -> {published_level; index}) + (obj2 + (req "level" Raw_level_repr.encoding) + (req "index" Dal_slot_index_repr.encoding)) + + let encoding = + let open Data_encoding in + conv + (fun {id; commitment} -> (id, commitment)) + (fun (id, commitment) -> {id; commitment}) + (* A tag is added to ensure we can migrate from this encoding to + different version if we decide to change the encoding. *) + (union + [ + case + ~title:"v0" + (Tag 0) + (merge_objs + (obj1 (req "version" (constant "0"))) + (merge_objs + id_encoding + (obj1 (req "commitment" Commitment.encoding)))) + (fun x -> Some ((), x)) + (fun ((), x) -> x); + ]) + + let pp_id fmt {published_level; index} = + Format.fprintf + fmt + "published_level: %a, index: %a" + Raw_level_repr.pp + published_level + Dal_slot_index_repr.pp + index + + let pp fmt {id; commitment = c} = + Format.fprintf fmt "id:(%a), commitment: %a" pp_id id Commitment.pp c + + let verify_commitment cryptobox commitment proof = + Ok (Dal.verify_commitment cryptobox commitment proof) +end + +module Slot_index = Dal_slot_index_repr + +module Page = struct + type content = Bytes.t + + type slot_index = Dal_slot_index_repr.t + + let pages_per_slot = Dal.pages_per_slot + + module Index = struct + type t = int + + let zero = 0 + + let encoding = Data_encoding.int16 + + let pp = Format.pp_print_int + + let compare = Compare.Int.compare + + let equal = Compare.Int.equal + + type error += Invalid_page_index of {given : int; min : int; max : int} + + let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"dal_page_index_repr.index.invalid_index" + ~title:"Invalid Dal page index" + ~description: + "The given index is out of range of representable page indices" + ~pp:(fun ppf (given, min, max) -> + Format.fprintf + ppf + "The given index %d is out of range of representable page indices \ + [%d, %d]" + given + min + max) + (obj3 (req "given" int31) (req "min" int31) (req "max" int31)) + (function + | Invalid_page_index {given; min; max} -> Some (given, min, max) + | _ -> None) + (fun (given, min, max) -> Invalid_page_index {given; min; max}) + + let check_is_in_range ~number_of_pages page_id = + error_unless + Compare.Int.(0 <= page_id && page_id < number_of_pages) + (Invalid_page_index + {given = page_id; min = zero; max = number_of_pages - 1}) + end + + type t = {slot_id : Header.id; page_index : Index.t} + + type proof = Dal.page_proof + + let encoding = + let open Data_encoding in + conv + (fun {slot_id = {published_level; index}; page_index} -> + (published_level, index, page_index)) + (fun (published_level, index, page_index) -> + {slot_id = {published_level; index}; page_index}) + (obj3 + (req "published_level" Raw_level_repr.encoding) + (req "slot_index" Slot_index.encoding) + (req "page_index" Index.encoding)) + + let equal {slot_id; page_index} p = + Header.slot_id_equal slot_id p.slot_id + && Index.equal page_index p.page_index + + let proof_encoding = Dal.page_proof_encoding + + let content_encoding = Data_encoding.(bytes Hex) + + let pp fmt {slot_id = {published_level; index}; page_index} = + Format.fprintf + fmt + "(published_level: %a, slot_index: %a, page_index: %a)" + Raw_level_repr.pp + published_level + Slot_index.pp + index + Index.pp + page_index + + let pp_proof fmt proof = + Data_encoding.Json.pp + fmt + (Data_encoding.Json.construct proof_encoding proof) +end + +module Slot_market = struct + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3108 + + Think harder about this data structure and whether it can be + optimized. *) + + module Slot_index_map = Map.Make (Dal_slot_index_repr) + + type t = {length : int; slot_headers : Header.t Slot_index_map.t} + + let init ~length = + if Compare.Int.(length < 0) then + invalid_arg "Dal_slot_repr.Slot_market.init: length cannot be negative" ; + let slot_headers = Slot_index_map.empty in + {length; slot_headers} + + let length {length; _} = length + + let register t new_slot_header = + let open Header in + if + not + Compare.Int.( + 0 <= Dal_slot_index_repr.to_int new_slot_header.id.index + && Dal_slot_index_repr.to_int new_slot_header.id.index < t.length) + then None + else + let has_changed = ref false in + let update = function + | None -> + has_changed := true ; + Some new_slot_header + | Some x -> Some x + in + let slot_headers = + Slot_index_map.update new_slot_header.id.index update t.slot_headers + in + let t = {t with slot_headers} in + Some (t, !has_changed) + + let candidates t = + t.slot_headers |> Slot_index_map.to_seq |> Seq.map snd |> List.of_seq +end + +module History = struct + (* History is represented via a skip list. The content of the cell + is the hash of a merkle proof. *) + + module Content_prefix = struct + let (_prefix : string) = "dash1" + + (* 32 *) + let b58check_prefix = "\002\224\072\094\219" (* dash1(55) *) + + let size = Some 32 + + let name = "dal_skip_list_content" + + let title = "A hash to represent the content of a cell in the skip list" + end + + module Content_hash = Blake2B.Make (Base58) (Content_prefix) + + (* Pointers of the skip lists are used to encode the content and the + backpointers. *) + module Pointer_prefix = struct + let (_prefix : string) = "dask1" + + (* 32 *) + let b58check_prefix = "\002\224\072\115\035" (* dask1(55) *) + + let size = Some 32 + + let name = "dal_skip_list_pointer" + + let title = "A hash that represents the skip list pointers" + end + + module Pointer_hash = Blake2B.Make (Base58) (Pointer_prefix) + + module Skip_list_parameters = struct + let basis = 4 + end + + type error += Add_element_in_slots_skip_list_violates_ordering + + let () = + register_error_kind + `Temporary + ~id:"Dal_slot_repr.add_element_in_slots_skip_list_violates_ordering" + ~title:"Add an element in slots skip list that violates ordering" + ~description: + "Attempting to add an element on top of the Dal confirmed slots skip \ + list that violates the ordering." + Data_encoding.unit + (function + | Add_element_in_slots_skip_list_violates_ordering -> Some () + | _ -> None) + (fun () -> Add_element_in_slots_skip_list_violates_ordering) + + module Content = struct + (** Each cell of the skip list is either a slot header that has been + attested, or a published level and a slot index for which no slot header + is attested (so, no associated commitment). *) + type t = Unattested of Header.id | Attested of Header.t + + let content_id = function + | Unattested slot_id -> slot_id + | Attested {id; _} -> id + + let encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"unattested" + (Tag 0) + (merge_objs + (obj1 (req "kind" (constant "unattested"))) + Header.id_encoding) + (function + | Unattested slot_id -> Some ((), slot_id) | Attested _ -> None) + (fun ((), slot_id) -> Unattested slot_id); + case + ~title:"attested" + (Tag 1) + (merge_objs + (obj1 (req "kind" (constant "attested"))) + Header.encoding) + (function + | Unattested _ -> None + | Attested slot_header -> Some ((), slot_header)) + (fun ((), slot_header) -> Attested slot_header); + ] + + let equal t1 t2 = + match (t1, t2) with + | Unattested sid1, Unattested sid2 -> Header.slot_id_equal sid1 sid2 + | Attested sh1, Attested sh2 -> Header.equal sh1 sh2 + | Unattested _, _ | Attested _, _ -> false + + let zero, zero_level = + let zero_level = Raw_level_repr.root in + let zero_index = Dal_slot_index_repr.zero in + (Unattested {published_level = zero_level; index = zero_index}, zero_level) + + let pp fmt = function + | Unattested slot_id -> + Format.fprintf fmt "Unattested (%a)" Header.pp_id slot_id + | Attested slot_header -> + Format.fprintf fmt "Attested (%a)" Header.pp slot_header + end + + module Skip_list = struct + include Skip_list.Make (Skip_list_parameters) + + (** All Dal slot indices for all levels will be stored in a skip list + (with or without a commitment depending on attestation status of each + slot), where only the last cell is needed to be remembered in the L1 + context. The skip list is used in the proof phase of a refutation game + to verify whether a given slot is inserted as [Attested] or not in the + skip list. The skip list is supposed to be sorted, as its 'search' + function explicitly uses a given `compare` function during the list + traversal to quickly (in log(size)) reach the target slot header id. + Two cells compare in lexicographic ordering of their levels and slot indexes. + + Below, we redefine the [next] function (that allows adding elements + on top of the list) to enforce that the constructed skip list is + well-sorted. We also define a wrapper around the [search] function to + guarantee that it can only be called with the adequate compare function. + *) + let next ~prev_cell ~prev_cell_ptr ~number_of_slots elt = + let open Result_syntax in + let well_ordered = + (* For each cell we insert in the skip list, we ensure that it complies + with the following invariant: + - Either the published levels are successive (no gaps). In this case: + * The last inserted slot's index for the previous level is + [number_of_slots - 1]; + * The first inserted slot's index for the current level is 0 + - Or, levels are equal, but slot indices are successive. *) + let Header.{published_level = l1; index = i1} = + content prev_cell |> Content.content_id + in + let Header.{published_level = l2; index = i2} = + Content.content_id elt + in + (Raw_level_repr.equal l2 (Raw_level_repr.succ l1) + && Compare.Int.(Dal_slot_index_repr.to_int i1 = number_of_slots - 1) + && Compare.Int.(Dal_slot_index_repr.to_int i2 = 0)) + || Raw_level_repr.equal l2 l1 + && Dal_slot_index_repr.is_succ i1 ~succ:i2 + in + let* () = + error_unless + well_ordered + Add_element_in_slots_skip_list_violates_ordering + in + return @@ next ~prev_cell ~prev_cell_ptr elt + + let search = + let compare_with_slot_id (target_slot_id : Header.id) + (content : Content.t) = + let Header.{published_level = target_level; index = target_index} = + target_slot_id + in + let Header.{published_level; index} = Content.content_id content in + let c = Raw_level_repr.compare published_level target_level in + if Compare.Int.(c <> 0) then c + else Dal_slot_index_repr.compare index target_index + in + fun ~deref ~cell ~target_slot_id -> + Lwt.search ~deref ~cell ~compare:(compare_with_slot_id target_slot_id) + end + + module V1 = struct + type content = Content.t + + (* A pointer to a cell is the hash of its content and all the back + pointers. *) + type hash = Pointer_hash.t + + type history = (content, hash) Skip_list.cell + + type t = history + + let genesis, genesis_level = + (Skip_list.genesis Content.zero, Content.zero_level) + + let history_encoding = + let open Data_encoding in + (* The history_encoding is given as a union of two versions of the skip + list. The legacy case is only used to deserialize the skip list cells + which may appear in refutation games started on a previous version of + the protocol, before the activation of the DAL. In this case, the + snapshotted cells are always the genesis one and cannot be used by the + players so we deserialize it on the fly to the new representation of + the genesis cell. *) + union + ~tag_size:`Uint8 + [ + case + ~title:"dal_skip_list_legacy" + (Tag 0) + (obj2 + (req "kind" (constant "dal_skip_list_legacy")) + (req "skip_list" (Data_encoding.Fixed.bytes Hex 57))) + (fun _ -> None) + (fun ((), _) -> genesis); + case + ~title:"dal_skip_list" + (Tag 1) + (obj2 + (req "kind" (constant "dal_skip_list")) + (req + "skip_list" + (Skip_list.encoding Pointer_hash.encoding Content.encoding))) + (fun x -> Some ((), x)) + (fun ((), x) -> x); + ] + + let equal_history : history -> history -> bool = + Skip_list.equal Pointer_hash.equal Content.equal + + let encoding = history_encoding + + let equal : t -> t -> bool = equal_history + + let hash cell = + let current_slot = Skip_list.content cell in + let back_pointers_hashes = Skip_list.back_pointers cell in + Data_encoding.Binary.to_bytes_exn Content.encoding current_slot + :: List.map Pointer_hash.to_bytes back_pointers_hashes + |> Pointer_hash.hash_bytes + + let pp_history fmt (history : history) = + let history_hash = hash history in + Format.fprintf + fmt + "@[hash : %a@;%a@]" + Pointer_hash.pp + history_hash + (Skip_list.pp ~pp_content:Content.pp ~pp_ptr:Pointer_hash.pp) + history + + let pp = pp_history + + module History_cache = + Bounded_history_repr.Make + (struct + let name = "dal_slots_cache" + end) + (Pointer_hash) + (struct + type t = history + + let encoding = history_encoding + + let pp = pp_history + + let equal = equal_history + end) + + (* Insert a cell in the skip list [t] and the corresponding association [(hash(t), + t)] in the given [cache]. + + Note that if the given skip list contains the genesis cell, its content is + reset with the given content. This ensures the invariant that + there are no gaps in the successive cells of the list. *) + let add_cell (t, cache) next_cell_content ~number_of_slots = + let open Result_syntax in + let prev_cell_ptr = hash t in + let Header.{published_level; _} = + Skip_list.content t |> Content.content_id + in + let* new_head = + if Raw_level_repr.equal published_level genesis_level then + (* If this is the first real cell of DAL, replace dummy genesis. *) + return (Skip_list.genesis next_cell_content) + else + Skip_list.next + ~prev_cell:t + ~prev_cell_ptr + next_cell_content + ~number_of_slots + in + let new_head_hash = hash new_head in + let* cache = History_cache.remember new_head_hash new_head cache in + return (new_head, cache) + + (* Given a list [attested_slot_headers] of well-ordered (wrt slots indices) + (attested) slot headers, this function builds an extension [l] of + [attested_slot_headers] such that: + + - all elements in [attested_slot_headers] are in [l], + + - for every slot index i in [0, number_of_slots - 1] that doesn't appear + in [attested_slot_headers], an unattested slot id is inserted in [l], + + - [l] is well sorted wrt. slots indices. *) + let fill_slot_headers ~number_of_slots ~published_level + attested_slot_headers = + let open Result_syntax in + let module I = Dal_slot_index_repr in + let* all_indices = + I.slots_range ~number_of_slots ~lower:0 ~upper:(number_of_slots - 1) + in + let mk_unattested index = + Content.Unattested Header.{published_level; index} + in + (* Hypothesis: both lists are sorted in increasing order w.r.t. slots + indices. *) + let rec aux indices slots = + match (indices, slots) with + | _, [] -> List.map mk_unattested indices |> ok + | [], _s :: _ -> tzfail Add_element_in_slots_skip_list_violates_ordering + | i :: indices', s :: slots' -> + if I.(i = s.Header.id.index) then + let* res = aux indices' slots' in + Content.Attested s :: res |> ok + else if I.(i < s.Header.id.index) then + let* res = aux indices' slots in + mk_unattested i :: res |> ok + else + (* i > s.Header.id.index *) + tzfail Add_element_in_slots_skip_list_violates_ordering + in + aux all_indices attested_slot_headers + + (* Assuming a [number_of_slots] per L1 level, we will ensure below that we + insert exactly [number_of_slots] cells in the skip list per level. This + will simplify the shape of proofs and help bounding the history cache + required for their generation. *) + let add_confirmed_slot_headers (t : t) cache published_level + ~number_of_slots attested_slot_headers = + let open Result_syntax in + let* () = + List.iter_e + (fun slot_header -> + error_unless + Raw_level_repr.( + published_level = slot_header.Header.id.published_level) + Add_element_in_slots_skip_list_violates_ordering) + attested_slot_headers + in + let* slot_headers = + fill_slot_headers + ~number_of_slots + ~published_level + attested_slot_headers + in + List.fold_left_e (add_cell ~number_of_slots) (t, cache) slot_headers + + let add_confirmed_slot_headers_no_cache = + let empty_cache = History_cache.empty ~capacity:0L in + fun t published_level ~number_of_slots slots -> + let open Result_syntax in + let+ cell, (_ : History_cache.t) = + add_confirmed_slot_headers + t + empty_cache + published_level + ~number_of_slots + slots + in + cell + + (* Dal proofs section *) + + (** An inclusion proof is a sequence (list) of cells from the Dal skip list, + represented as [c1; c2; ...; cn], that encodes a minimal path from the + head [c1] (referred to as the "reference" or "snapshot" cell below) to a + target cell [cn]. Thanks to the back-pointers, it can be demonstrated + that the successive elements of the sequence are indeed cells of the + skip list. *) + type inclusion_proof = history list + + (** (See the documentation in the mli file to understand what we want to + prove in a refutation game involving Dal and why.) + + A Dal proof is an algebraic datatype with two cases, where we basically + prove that a Dal page is confirmed on L1 or not. Being 'not confirmed' + here includes the case where the slot's header is not published and the + case where the slot's header is published, but the attesters didn't + confirm the availability of its data. + + To produce a proof representation for a page (see function + {!produce_proof_repr} below), we assume given: + + - [page_id], identifies the page; + + - [slots_history], a current/recent cell of the slots history skip list. + Typically, it should be the skip list cell snapshotted when starting the + refutation game; + + - [get_history], a sufficiently large slots history cache, encoded as a + function from pointer hashes to their corresponding skip lists cells, to + navigate back through the successive cells of the skip list. The cache + should at least contain the cells starting from the published level of + the page ID for which we want to generate a proof. Indeed, inclusion + proofs encode paths through skip lists' cells where the head is the + reference/snapshot cell and the last element is the target cell inserted + at the level corresponding to the page's published level). Note that, the + case where the level of the page is far in the past (i.e. the skip list + was not populated yet) should be handled by the caller ; + + - [page_info], provides information for [page_id]. In case the page is + supposed to be confirmed, this argument should contain the page's + content and the proof that the page is part of the (confirmed) slot + whose ID is given in [page_id]. In case we want to show that the page is + not confirmed, the value [page_info] should be [None]. + + [dal_parameters] is used when verifying that/if the page is part of + the candidate slot (if any). *) + type proof_repr = + | Page_confirmed of { + target_cell : history; + (** [target_cell] is a cell whose content contains the slot to + which the page belongs to. *) + inc_proof : inclusion_proof; + (** [inc_proof] is a (minimal) path in the skip list that proves + cells inclusion. The head of the list is the [slots_history] + provided to produce the proof. The last cell's content is + the slot containing the page identified by [page_id], + that is: [target_cell]. *) + page_data : Page.content; + (** [page_data] is the content of the page. *) + page_proof : Page.proof; + (** [page_proof] is the proof that the page whose content is + [page_data] is actually the [page_id.page_index]th page of + the slot stored in [target_cell] and identified by + [page_id.slot_id]. *) + } (** The case where the slot's page is confirmed/attested on L1. *) + | Page_unconfirmed of {target_cell : history; inc_proof : inclusion_proof} + (** The case where the slot's page doesn't exist or is not confirmed + on L1. The fields are similar to {!Page_confirmed} case except + that we don't have a page data or proof to check. + + As said above, in case the level of the page is far in the past + (for instance, the skip list was not populated yet or the slots of + that level are not valid to be imported by the DAL anymore) should + be handled by the caller. In fact, the [proof_repr] type here only + covers levels where a new cell has been added to the skip list. *) + + let proof_repr_encoding = + let open Data_encoding in + let case_page_confirmed = + case + ~title:"confirmed dal page proof representation" + (Tag 0) + (obj5 + (req "kind" (constant "confirmed")) + (req "target_cell" history_encoding) + (req "inc_proof" (list history_encoding)) + (req "page_data" (bytes Hex)) + (req "page_proof" Page.proof_encoding)) + (function + | Page_confirmed {target_cell; inc_proof; page_data; page_proof} -> + Some ((), target_cell, inc_proof, page_data, page_proof) + | _ -> None) + (fun ((), target_cell, inc_proof, page_data, page_proof) -> + Page_confirmed {target_cell; inc_proof; page_data; page_proof}) + and case_page_unconfirmed = + case + ~title:"unconfirmed dal page proof representation" + (Tag 1) + (obj3 + (req "kind" (constant "unconfirmed")) + (req "target_cell" history_encoding) + (req "inc_proof" (list history_encoding))) + (function + | Page_unconfirmed {target_cell; inc_proof} -> + Some ((), target_cell, inc_proof) + | _ -> None) + (fun ((), target_cell, inc_proof) -> + Page_unconfirmed {target_cell; inc_proof}) + in + + union [case_page_confirmed; case_page_unconfirmed] + + (** Proof's type is set to bytes and not a structural datatype because + when a proof appears in a tezos operation or in an rpc, a user can not + reasonably understand the proof, thus it eases the work of people decoding + the proof by only supporting bytes and not the whole structured proof. *) + + type proof = bytes + + (** DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/4084 + DAL proof's encoding should be bounded *) + let proof_encoding = Data_encoding.(bytes Hex) + + type error += Dal_invalid_proof_serialization + + let () = + register_error_kind + `Permanent + ~id:"Dal_slot_repr.invalid_proof_serialization" + ~title:"Dal invalid proof serialization" + ~description:"Error occured during dal proof serialization" + Data_encoding.unit + (function Dal_invalid_proof_serialization -> Some () | _ -> None) + (fun () -> Dal_invalid_proof_serialization) + + let serialize_proof proof = + let open Result_syntax in + match Data_encoding.Binary.to_bytes_opt proof_repr_encoding proof with + | None -> tzfail Dal_invalid_proof_serialization + | Some serialized_proof -> return serialized_proof + + type error += Dal_invalid_proof_deserialization + + let () = + register_error_kind + `Permanent + ~id:"Dal_slot_repr.invalid_proof_deserialization" + ~title:"Dal invalid proof deserialization" + ~description:"Error occured during dal proof deserialization" + Data_encoding.unit + (function Dal_invalid_proof_deserialization -> Some () | _ -> None) + (fun () -> Dal_invalid_proof_deserialization) + + let deserialize_proof proof = + let open Result_syntax in + match Data_encoding.Binary.of_bytes_opt proof_repr_encoding proof with + | None -> tzfail Dal_invalid_proof_deserialization + | Some deserialized_proof -> return deserialized_proof + + let pp_inclusion_proof = Format.pp_print_list pp_history + + let pp_proof ~serialized fmt p = + if serialized then Format.pp_print_string fmt (Bytes.to_string p) + else + match deserialize_proof p with + | Error msg -> Error_monad.pp_trace fmt msg + | Ok proof -> ( + match proof with + | Page_confirmed {target_cell; inc_proof; page_data; page_proof} -> + Format.fprintf + fmt + "Page_confirmed (target_cell=%a, data=%s,@ \ + inc_proof:[size=%d |@ path=%a]@ page_proof:%a)" + pp_history + target_cell + (Bytes.to_string page_data) + (List.length inc_proof) + pp_inclusion_proof + inc_proof + Page.pp_proof + page_proof + | Page_unconfirmed {target_cell; inc_proof} -> + Format.fprintf + fmt + "Page_unconfirmed (target_cell = %a | inc_proof:[size=%d@ | \ + path=%a])" + pp_history + target_cell + (List.length inc_proof) + pp_inclusion_proof + inc_proof) + + type error += + | Dal_proof_error of string + | Unexpected_page_size of {expected_size : int; page_size : int} + + let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"dal_slot_repr.slots_history.dal_proof_error" + ~title:"Dal proof error" + ~description:"Error occurred during Dal proof production or validation" + ~pp:(fun ppf e -> Format.fprintf ppf "Dal proof error: %s" e) + (obj1 (req "error" (string Plain))) + (function Dal_proof_error e -> Some e | _ -> None) + (fun e -> Dal_proof_error e) + + let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"dal_slot_repr.slots_history.unexpected_page_size" + ~title:"Unexpected page size" + ~description: + "The size of the given page content doesn't match the expected one." + ~pp:(fun ppf (expected, size) -> + Format.fprintf + ppf + "The size of a Dal page is expected to be %d bytes. The given one \ + has %d" + expected + size) + (obj2 (req "expected_size" int16) (req "page_size" int16)) + (function + | Unexpected_page_size {expected_size; page_size} -> + Some (expected_size, page_size) + | _ -> None) + (fun (expected_size, page_size) -> + Unexpected_page_size {expected_size; page_size}) + + let dal_proof_error reason = Dal_proof_error reason + + let proof_error reason = error @@ dal_proof_error reason + + let check_page_proof dal_params proof data ({Page.page_index; _} as pid) + commitment = + let open Result_syntax in + let* dal = + match Dal.make dal_params with + | Ok dal -> return dal + | Error (`Fail s) -> proof_error s + in + let fail_with_error_msg what = + Format.kasprintf proof_error "%s (page id=%a)." what Page.pp pid + in + match Dal.verify_page dal commitment ~page_index data proof with + | Ok true -> return_unit + | Ok false -> + fail_with_error_msg + "Wrong page content for the given page index and slot commitment" + | Error `Segment_index_out_of_range -> + fail_with_error_msg "Segment_index_out_of_range" + | Error `Page_length_mismatch -> + tzfail + @@ Unexpected_page_size + { + expected_size = dal_params.page_size; + page_size = Bytes.length data; + } + + (** The [produce_proof_repr] function assumes that some invariants hold, such as: + - The DAL has been activated, + - The level of [page_id] is after the DAL activation level. + + Under these assumptions, we recall that we maintain an invariant + ensuring that we a have a cell per slot index in the skip list at every level + after DAL activation. *) + let produce_proof_repr dal_params page_id ~page_info ~get_history slots_hist + = + let open Lwt_result_syntax in + let Page.{slot_id = target_slot_id; page_index = _} = page_id in + (* We first search for the slots attested at level [published_level]. *) + let*! search_result = + Skip_list.search ~deref:get_history ~target_slot_id ~cell:slots_hist + in + (* The search should necessarily find a cell in the skip list (assuming + enough cache is given) under the assumptions made when calling + {!produce_proof_repr}. *) + match search_result.Skip_list.last_cell with + | Deref_returned_none -> + tzfail + @@ dal_proof_error + "Skip_list.search returned 'Deref_returned_none': Slots history \ + cache is ill-formed or has too few entries." + | No_exact_or_lower_ptr -> + tzfail + @@ dal_proof_error + "Skip_list.search returned 'No_exact_or_lower_ptr', while it is \ + initialized with a min elt (slot zero)." + | Nearest _ -> + (* This should not happen: there is one cell at each level + after DAL activation. The case where the page's level is before DAL + activation level should be handled by the caller + ({!Sc_refutation_proof.produce} in our case). *) + tzfail + @@ dal_proof_error + "Skip_list.search returned Nearest', while all given levels to \ + produce proofs are supposed to be in the skip list." + | Found target_cell -> ( + let inc_proof = List.rev search_result.Skip_list.rev_path in + match (page_info, Skip_list.content target_cell) with + | Some (page_data, page_proof), Attested {commitment; id = _} -> + (* The case where the slot to which the page is supposed to belong + is found and the page's information are given. *) + let*? () = + (* We check the page's proof against the commitment. *) + check_page_proof + dal_params + page_proof + page_data + page_id + commitment + in + (* All checks succeeded. We return a `Page_confirmed` proof. *) + return + ( Page_confirmed {target_cell; inc_proof; page_data; page_proof}, + Some page_data ) + | None, Unattested _ -> + (* The slot corresponding to the given page's index is not found in + the attested slots of the page's level, and no information is + given for that page. So, we produce a proof that the page is not + attested. *) + return (Page_unconfirmed {target_cell; inc_proof}, None) + | None, Attested _ -> + (* Mismatch: case where no page information are given, but the + slot is attested. *) + tzfail + @@ dal_proof_error + "The page ID's slot is confirmed, but no page content and \ + proof are provided." + | Some _, Unattested _ -> + (* Mismatch: case where page information are given, but the slot + is not attested. *) + tzfail + @@ dal_proof_error + "The page ID's slot is not confirmed, but page content and \ + proof are provided.") + + let produce_proof dal_params page_id ~page_info ~get_history slots_hist = + let open Lwt_result_syntax in + let* proof_repr, page_data = + produce_proof_repr dal_params page_id ~page_info ~get_history slots_hist + in + let*? serialized_proof = serialize_proof proof_repr in + return (serialized_proof, page_data) + + (* Given a starting cell [snapshot] and a (final) [target], this function + checks that the provided [inc_proof] encodes a minimal path from + [snapshot] to [target]. *) + let verify_inclusion_proof inc_proof ~src:snapshot ~dest:target = + let assoc = List.map (fun c -> (hash c, c)) inc_proof in + let path = List.split assoc |> fst in + let deref = + let open Map.Make (Pointer_hash) in + let map = of_seq (List.to_seq assoc) in + fun ptr -> find_opt ptr map + in + let snapshot_ptr = hash snapshot in + let target_ptr = hash target in + error_unless + (Skip_list.valid_back_path + ~equal_ptr:Pointer_hash.equal + ~deref + ~cell_ptr:snapshot_ptr + ~target_ptr + path) + (dal_proof_error "verify_proof_repr: invalid inclusion Dal proof.") + + let verify_proof_repr dal_params page_id snapshot proof = + let open Result_syntax in + let Page.{slot_id = Header.{published_level; index}; page_index = _} = + page_id + in + let* target_cell, inc_proof, page_proof_check = + match proof with + | Page_confirmed {target_cell; inc_proof; page_data; page_proof} -> + let page_proof_check = + Some + (fun commitment -> + (* We check that the page indeed belongs to the target slot at the + given page index. *) + let* () = + check_page_proof + dal_params + page_proof + page_data + page_id + commitment + in + (* If the check succeeds, we return the data/content of the + page. *) + return page_data) + in + return (target_cell, inc_proof, page_proof_check) + | Page_unconfirmed {target_cell; inc_proof} -> + return (target_cell, inc_proof, None) + in + let cell_content = Skip_list.content target_cell in + (* We check that the target cell has the same level and index than the + page we're about to prove. *) + let cell_id = Content.content_id cell_content in + let* () = + error_when + Raw_level_repr.(cell_id.published_level <> published_level) + (dal_proof_error "verify_proof_repr: published_level mismatch.") + in + let* () = + error_when + (not (Dal_slot_index_repr.equal cell_id.index index)) + (dal_proof_error "verify_proof_repr: slot index mismatch.") + in + (* We check that the given inclusion proof indeed links our L1 snapshot to + the target cell. *) + let* () = + verify_inclusion_proof inc_proof ~src:snapshot ~dest:target_cell + in + match (page_proof_check, cell_content) with + | None, Unattested _ -> return_none + | Some page_proof_check, Attested {commitment; _} -> + let* page_data = page_proof_check commitment in + return_some page_data + | Some _, Unattested _ -> + error + @@ dal_proof_error + "verify_proof_repr: the unconfirmation proof contains the \ + target slot." + | None, Attested _ -> + error + @@ dal_proof_error + "verify_proof_repr: the confirmation proof doesn't contain the \ + attested slot." + + let verify_proof dal_params page_id snapshot serialized_proof = + let open Result_syntax in + let* proof_repr = deserialize_proof serialized_proof in + verify_proof_repr dal_params page_id snapshot proof_repr + + module Internal_for_tests = struct + type cell_content = Content.t = + | Unattested of Header.id + | Attested of Header.t + + let content = Skip_list.content + + let proof_statement_is serialized_proof expected = + match deserialize_proof serialized_proof with + | Error _ -> false + | Ok proof -> ( + match (expected, proof) with + | `Confirmed, Page_confirmed _ | `Unconfirmed, Page_unconfirmed _ -> + true + | _ -> false) + end + end + + include V1 +end diff --git a/src/proto_020_PsParisC/lib_protocol/dal_slot_repr.mli b/src/proto_020_PsParisC/lib_protocol/dal_slot_repr.mli new file mode 100644 index 000000000000..40c8f94c91f0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_slot_repr.mli @@ -0,0 +1,388 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** To verify the proof of a page membership in its associated slot, the + Cryptobox module needs the following Dal parameters. These are part of the + protocol's parameters. See {!Dal.Config.default}. *) +type parameters = Dal.parameters = { + redundancy_factor : int; + page_size : int; + slot_size : int; + number_of_shards : int; +} + +(** An encoding for values of type {!parameters}. *) +val parameters_encoding : parameters Data_encoding.t + +(** Slot header representation for the data-availability layer. + + {1 Overview} + + For the data-availability layer, the L1 provides a list of slots + at every level. A slot is a blob of data that can be interpreted by + the users of the data-availability layer (such as SCORU). + + The purpose of the data-availability layer is to increase the + bandwidth of the layer 1 thanks to the distribution of "slots". A + slot is never posted directly onto the layer 1 blocks but on the + data-availability layer. The producer of a slot still has to post a + slot header onto the layer 1. A slot header is an abstract datatype + certifying that the corresponding slot has some maximum size + (provided by the layer 1). In other words, the whole data contained + into the slot cannot exceed some fixed size. This is to avoid + attacks where a slot header would be posted onto the layer 1 block, + declared available by the protocol, but actually the slot size + would be too large to be refuted a posteriori. + + The slot header can also be used to prove that a blob of data is a + portion of the initial slot. *) + +module Commitment : sig + (** A slot commitment is provided via the environment. *) + type t = Dal.commitment + + val encoding : t Data_encoding.t + + (** A dummy value for a commitment. This commitment does not + correspond to any valid pre-image. *) + val zero : t + + (** Attempt to convert the input representing a commitment encoded as a b58 + string. *) + val of_b58check_opt : string -> t option +end + +module Commitment_proof : sig + (** A slot commitment proof is provided via the environment. *) + type t = Dal.commitment_proof + + val encoding : t Data_encoding.t + + (** A dummy value for a commitment proof. *) + val zero : t +end + +module Header : sig + (** For Layer-1, a slot is identified by the level at which it is published + and the slot's index. *) + type id = {published_level : Raw_level_repr.t; index : Dal_slot_index_repr.t} + + (** For Layer-1, a slot is described by its slot {!type-id} and the + slot's commitment. *) + type t = {id : id; commitment : Commitment.t} + + (** encoding for values of type {!type-id}. *) + val id_encoding : id Data_encoding.t + + (** encoding for values of type {!t}. *) + val encoding : t Data_encoding.t + + (** pretty-printer for values of type {!type-id}. *) + val pp_id : Format.formatter -> id -> unit + + (** pretty-printer for values of type {!t}. *) + val pp : Format.formatter -> t -> unit + + (** equal function for values of type {!t}. *) + val equal : t -> t -> bool + + (** [verify_commitment cryptobox commitment commitment_proof] check + that for the given commitment, the commitment proof is correct + using the [cryptbox] primitives. *) + val verify_commitment : + Dal.t -> Commitment.t -> Commitment_proof.t -> bool tzresult +end + +(** A DAL slot is decomposed to a successive list of pages with fixed content + size. The size is chosen so that it's possible to inject a page in a Tezos + L1 operation if needed during the proof phase of a refutation game. +*) +module Page : sig + type content = Bytes.t + + type slot_index = Dal_slot_index_repr.t + + val pages_per_slot : Dal.parameters -> int + + module Index : sig + type t = int + + val zero : int + + val encoding : int Data_encoding.t + + val pp : Format.formatter -> int -> unit + + val compare : int -> int -> int + + val equal : int -> int -> bool + + type error += Invalid_page_index of {given : int; min : int; max : int} + + (** [is_in_range ~number_of_pages page_id] returns true if and only if the + provided [page_id] is within the bounds of allowed pages. *) + val check_is_in_range : number_of_pages:int -> int -> unit tzresult + end + + (** Encoding for page contents. *) + val content_encoding : content Data_encoding.t + + (** A page is identified by its slot ID and by its own index in the list + of pages of the slot. *) + type t = {slot_id : Header.id; page_index : Index.t} + + type proof = Dal.page_proof + + (** equal function for values of type {!t}. *) + val equal : t -> t -> bool + + (** encoding for values of type {!t}. *) + val encoding : t Data_encoding.t + + (** encoding for values of type {!proof}. *) + val proof_encoding : proof Data_encoding.t + + (** pretty-printer for values of type {!t}. *) + val pp : Format.formatter -> t -> unit +end + +(** Only one slot header is accepted per slot index. If two slots + headers are included into a block, the second one will fail. + + Consequently, we rely on the order of operations which is done + thanks to the fee market. + + This is encapsulated in the following module. *) +module Slot_market : sig + (** Represent the fee market for a list of slots. *) + type t + + (** [init ~length] encodes a list of [length] slots without + candidates. *) + val init : length:int -> t + + (** [length t] returns the [length] provided at initialisation time + (see {!val:init}). *) + val length : t -> int + + (** [register t index fees] updates the candidate associated to + index [index]. Returns [Some (_, true)] if the candidate is + registered. Returns [Some (_, false)] otherwise. Returns [None] + if the [index] is not in the interval [0;length] where [length] + is the value provided to the [init] function. *) + val register : t -> Header.t -> (t * bool) option + + (** [candidates t] returns a list of slot header candidates. *) + val candidates : t -> Header.t list +end + +(** This module provides an abstract data structure (type {!History.t}) that + represents a skip list used to store successive DAL slots confirmed/attested + on L1. There is one slot per cell in the skip list. The slots are sorted in + increasing order by level, and by slot index, for the slots of the same + level. + + This module also defines a bounded history cache (type + {!type-History.History_cache.t}) that allows to remember recent values of a + skip list of type {!History.t} (indexed by the skip lists' hashes). This + structure is meant to be maintained and used by the rollup node to produce + refutation proofs involving DAL slot inputs. + + Note on terminology: "confirmed slot" is another name for "attested slot". +*) +module History : sig + (** Abstract representation of a skip list specialized for + confirmed slot headers. *) + type t + + module Pointer_hash : S.HASH + + (** Type of hashes of history. *) + type hash = Pointer_hash.t + + (** Encoding of the datatype. *) + val encoding : t Data_encoding.t + + (** The genesis skip list that contains one dummy cell. This cell has + {!Raw_level_repr.root} as published level and no attested slots. Since Dal + is not necessarily activated in the genesis block (e.g. this will be the case + on mainnet), the skip list is reset at the first call to + {!add_confirmed_slot_headers} to enforce the invariant that there are no gaps + in the levels of the cells of the skip list. + + So, a skip list is initialized with this genesis cell. It's then replaced + with a growing (non-dummy) skip list as soon as a call to + {!add_confirmed_slot_headers} with a level bigger than + {!Raw_level_repr.root} is performed. This allows to activate Dal at any + level and having a contiguous skip list (w.r.t. L1 levels). This + representation allows to produce simpler proofs with a bounded history + cache. *) + val genesis : t + + (** Returns the hash of an history. *) + val hash : t -> hash + + (** The [History_cache.t] structure is basically a bounded lookup table of + {!t} skip lists. (See {!Bounded_history_repr.S}). In the L1 layer, the + capacity (bound) is set to zero (nothing is remembered). By contrast, + the rollup node uses a history cache with a (sufficiently) large capacity + to participate in all potential refutation games occurring during the + challenge period. Indeed, the successive recent skip-lists stored in + the cache are needed to produce proofs involving slots' pages. *) + module History_cache : + Bounded_history_repr.S with type key = hash and type value = t + + (** [add_confirmed_slots hist cache published_level ~number_of_slots + slot_headers] updates the given structure [hist] with the list of + [slot_headers]. The given [cache] is also updated to add successive values + of [cell] to it. + + + This function checks the following pre-conditions before updating the + list: + + - The given [published_level] should match all the levels of the slots in + [slot_headers], if any; + + - [published_level] is the successor the last inserted cell's level. + + - [slot_headers] is sorted in increasing order w.r.t. slots indices. + *) + val add_confirmed_slot_headers : + t -> + History_cache.t -> + Raw_level_repr.t -> + number_of_slots:int -> + Header.t list -> + (t * History_cache.t) tzresult + + (** Similiar to {!add_confirmed_slot_headers}, but no cache is provided or + updated. *) + val add_confirmed_slot_headers_no_cache : + t -> Raw_level_repr.t -> number_of_slots:int -> Header.t list -> t tzresult + + (** [equal a b] returns true iff a is equal to b. *) + val equal : t -> t -> bool + + val pp : Format.formatter -> t -> unit + + (** {1 Dal slots/pages proofs} *) + + (** When a SCORU kernel's inputs come from the DAL, they are provided as + pages' content for confirmed slots, or None in case the slot doesn't + exist or is not confirmed. + + In a refutation game involving an import tick of a Dal page input, a + honest user should be able to provide: + + - When the PVM is requesting a page of a confirmed slot: a proof that the + slot is confirmed, in addition to needed information to check that the + page (whose id and content are given) is part of the slot; + + - When the opponent pretends that the PVM is requesting a page of some + unconfirmed slot, but that slot is not published or not confirmed on L1: + a proof that the slot (whose id is given via the page's id) cannot be + confirmed on L1. + + See the documentation in the ml file for more technical details. *) + type proof + + (** Encoding for {!proof}. *) + val proof_encoding : proof Data_encoding.t + + (** Pretty-printer for {!proof}. If [serialized] is [false] it will print + the abstracted proof representation, otherwise if it's [true] it will + print the serialized version of the proof (i.e. a sequence of bytes). *) + val pp_proof : serialized:bool -> Format.formatter -> proof -> unit + + (** [produce_proof dal_parameters page_id page_info ~get_history slots_hist] + produces a proof that either: + - there exists a confirmed slot in the skip list that contains + the page identified by [page_id] whose data and slot inclusion proof + are given by [page_info], or + - there cannot exist a confirmed slot in the skip list (whose head is + given by [slots_hist]) containing the page identified by [page_id]. + + In the first case above, [page_info] should contain the page's content + and the proof that the page is part of the (confirmed) slot whose + id is given in [page_id]. In the second case, no page content or proof + should be provided, as they are not needed to construct a non-confirmation + proof. + + The function returns an error in case the slot is not confirmed but the + page's content and proof are given. It also fails if the slot is confirmed + but no or bad information about the page are provided. + + Note that, in case the level of the page is far in the past (the Dal skip + list was not populated yet or the slots of the associated level are not + valid anymore) should be handled by the caller. + + [dal_parameters] is used when verifying that/if the page is part of + the candidate slot (if any). + *) + val produce_proof : + parameters -> + Page.t -> + page_info:(Page.content * Page.proof) option -> + get_history:(hash -> t option Lwt.t) -> + t -> + (proof * Page.content option) tzresult Lwt.t + + (** [verify_proof dal_params page_id snapshot proof] verifies that the given + [proof] is a valid proof to show that either: + - the page identified by [page_id] belongs to a confirmed slot stored in + the skip list whose head is [snapshot], or + - there is not confirmed slot in the skip list (whose head is) [snapshot] + that could contain the page identified by [page_id]. + + [dal_parameters] is used when verifying that/if the page is part of + the candidate slot (if any). + *) + val verify_proof : + parameters -> Page.t -> t -> proof -> Page.content option tzresult + + type error += Add_element_in_slots_skip_list_violates_ordering + + type error += + | Dal_proof_error of string + | Unexpected_page_size of {expected_size : int; page_size : int} + + module Internal_for_tests : sig + (** The content of a cell in the DAL skip list. We don't store the slot + headers directly to refactor the common [published_level] and save + space. This is important for refutation proofs, as they have to fit in + an L1 operation. *) + type cell_content = Unattested of Header.id | Attested of Header.t + + (** Returns the content of the last cell in the given skip list. *) + val content : t -> cell_content + + (** [proof_statement_is serialized_proof expected] will return [true] if + the deserialized proof and the [expected] proof shape match and [false] + otherwise. + Note that it will also return [false] if deserialization fails. *) + val proof_statement_is : proof -> [`Confirmed | `Unconfirmed] -> bool + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/dal_slot_storage.ml b/src/proto_020_PsParisC/lib_protocol/dal_slot_storage.ml new file mode 100644 index 000000000000..944056b4f2b3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_slot_storage.ml @@ -0,0 +1,101 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let find_slot_headers ctxt level = Storage.Dal.Slot.Headers.find ctxt level + +let finalize_current_slot_headers ctxt = + Storage.Dal.Slot.Headers.add + ctxt + (Raw_context.current_level ctxt).level + (Raw_context.Dal.candidates ctxt) + +let compute_attested_slot_headers ~is_slot_attested seen_slot_headers = + let open Dal_slot_repr in + let fold_attested_slots (rev_attested_slot_headers, attestation) slot = + if is_slot_attested slot then + ( slot :: rev_attested_slot_headers, + Dal_attestation_repr.commit attestation slot.Header.id.index ) + else (rev_attested_slot_headers, attestation) + in + let rev_attested_slot_headers, bitset = + List.fold_left + fold_attested_slots + ([], Dal_attestation_repr.empty) + seen_slot_headers + in + (List.rev rev_attested_slot_headers, bitset) + +let get_slot_headers_history ctxt = + let open Lwt_result_syntax in + let+ slots_history = Storage.Dal.Slot.History.find ctxt in + match slots_history with + | None -> Dal_slot_repr.History.genesis + | Some slots_history -> slots_history + +let update_skip_list ctxt ~confirmed_slot_headers ~level_attested + ~number_of_slots = + let open Lwt_result_syntax in + let* slots_history = get_slot_headers_history ctxt in + let*? slots_history = + Dal_slot_repr.History.add_confirmed_slot_headers_no_cache + ~number_of_slots + slots_history + level_attested + confirmed_slot_headers + in + let*! ctxt = Storage.Dal.Slot.History.add ctxt slots_history in + return ctxt + +let finalize_pending_slot_headers ctxt ~number_of_slots = + let open Lwt_result_syntax in + let {Level_repr.level = raw_level; _} = Raw_context.current_level ctxt in + let Constants_parametric_repr.{dal; _} = Raw_context.constants ctxt in + match Raw_level_repr.(sub raw_level dal.attestation_lag) with + | None -> return (ctxt, Dal_attestation_repr.empty) + | Some level_attested -> + let* seen_slots = find_slot_headers ctxt level_attested in + let*! ctxt = Storage.Dal.Slot.Headers.remove ctxt level_attested in + let* ctxt, attestation, confirmed_slot_headers = + match seen_slots with + | None -> return (ctxt, Dal_attestation_repr.empty, []) + | Some seen_slots -> + let attested_slot_headers, attestation = + let is_slot_attested slot = + Raw_context.Dal.is_slot_index_attested + ctxt + slot.Dal_slot_repr.Header.id.index + in + compute_attested_slot_headers ~is_slot_attested seen_slots + in + return (ctxt, attestation, attested_slot_headers) + in + let* ctxt = + update_skip_list + ctxt + ~confirmed_slot_headers + ~level_attested + ~number_of_slots + in + return (ctxt, attestation) diff --git a/src/proto_020_PsParisC/lib_protocol/dal_slot_storage.mli b/src/proto_020_PsParisC/lib_protocol/dal_slot_storage.mli new file mode 100644 index 000000000000..4dc2d270fca3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dal_slot_storage.mli @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Storage management of slots for the data-availability layer. + + {1 Overview} + + This module is an interface for the slot storage for the layer 1. + + Depending on the current level of the context and the [attestation_lag] (a + constant given by the context), the status of the slot may differ: + + - For every level in the interval [current_level; current_level + + attestation_lag - 1] the slot is [Pending]. This means a slot header was + proposed but was not declared available yet. + + - For every level above [current_level + attestation_lag], the slot may be + [attested]. For any slot attested by the protocol (i.e. indices returned by + [finalize_pending_slots]), subscribers of the DAL should take into account + the corresponding slots. + + - For every level below [current_level - attestation_lag], there should not be + any slot in the storage. *) + +(** [find_slot_headers ctxt level] returns [Some slot_headers] where [slot_headers] + are pending slots at level [level]. [None] is returned if no + [slot_header] was registered at this level. The function fails if + the reading into the context fails. *) +val find_slot_headers : + Raw_context.t -> + Raw_level_repr.t -> + Dal_slot_repr.Header.t list option tzresult Lwt.t + +(** [finalize_current_slot_headers ctxt] finalizes the current slot + headers posted on this block and marks them as pending into the + context. *) +val finalize_current_slot_headers : Raw_context.t -> Raw_context.t Lwt.t + +(** [finalize_pending_slot_headers ctxt ~number_of_slots] finalizes pending slot + headers which are old enough (i.e. registered at level [current_level - + attestation_lag]). All slots marked as available are returned. All the + pending slots at [current_level - attestation_lag] level are removed from + the context. *) +val finalize_pending_slot_headers : + Raw_context.t -> + number_of_slots:int -> + (Raw_context.t * Dal_attestation_repr.t) tzresult Lwt.t + +(** [get_slot_headers_history ctxt] returns the current value of slots_history stored + in [ctxt], or Slots_history.genesis if no value is stored yet. *) +val get_slot_headers_history : + Raw_context.t -> Dal_slot_repr.History.t tzresult Lwt.t + +(** [compute_attested_slot_headers ~is_slot_attested published_slot_headers] + filter the given [published_slot_headers] and return the list of attested + slot headers and the corresponding bitset. *) +val compute_attested_slot_headers : + is_slot_attested:(Dal_slot_repr.Header.t -> bool) -> + Dal_slot_repr.Header.t list -> + Dal_slot_repr.Header.t list * Dal_attestation_repr.t diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.ml b/src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.ml new file mode 100644 index 000000000000..0f064f495520 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.ml @@ -0,0 +1,97 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let is_inactive ctxt delegate = + let open Lwt_result_syntax in + let*! inactive = + Storage.Contract.Inactive_delegate.mem + ctxt + (Contract_repr.Implicit delegate) + in + if inactive then Lwt.return_ok inactive + else + let+ cycle_opt = + Storage.Contract.Delegate_last_cycle_before_deactivation.find + ctxt + (Contract_repr.Implicit delegate) + in + match cycle_opt with + | Some last_active_cycle -> + let ({Level_repr.cycle = current_cycle; _} : Level_repr.t) = + Raw_context.current_level ctxt + in + Cycle_repr.(last_active_cycle < current_cycle) + | None -> + (* This case is only when called from `set_active`, when creating + a contract. *) + false + +let last_cycle_before_deactivation ctxt delegate = + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Delegate_last_cycle_before_deactivation.get ctxt contract + +let set_inactive ctxt delegate = + Storage.Contract.Inactive_delegate.add ctxt (Contract_repr.Implicit delegate) + +let set_active ctxt delegate = + let open Lwt_result_syntax in + let* inactive = is_inactive ctxt delegate in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let tolerance = Constants_storage.tolerated_inactivity_period ctxt in + let consensus_rights_delay = Constants_storage.consensus_rights_delay ctxt in + (* We allow a number of cycles before a delegate is deactivated as follows: + - if the delegate is active, we give it at least `tolerance` cycles + after the current cycle before to be deactivated. + - if the delegate is new or inactive, we give it additionally + `consensus_rights_delay` because the delegate needs this number of cycles to + receive rights, so `tolerance + consensus_rights_delay` in total. *) + let delegate_contract = Contract_repr.Implicit delegate in + let* current_last_active_cycle = + Storage.Contract.Delegate_last_cycle_before_deactivation.find + ctxt + delegate_contract + in + let last_active_cycle = + match current_last_active_cycle with + | None -> Cycle_repr.add current_cycle (tolerance + consensus_rights_delay) + | Some current_last_active_cycle -> + let delay = + if inactive then tolerance + consensus_rights_delay else tolerance + in + let updated = Cycle_repr.add current_cycle delay in + Cycle_repr.max current_last_active_cycle updated + in + let*! ctxt = + Storage.Contract.Delegate_last_cycle_before_deactivation.add + ctxt + delegate_contract + last_active_cycle + in + if not inactive then return (ctxt, inactive) + else + let*! ctxt = + Storage.Contract.Inactive_delegate.remove ctxt delegate_contract + in + return (ctxt, inactive) diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.mli b/src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.mli new file mode 100644 index 000000000000..390d37cbef2f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_activation_storage.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module deals with delegates' activity. Typically, the provided + functions can be used to deactivate a delegate that has not shown activity + for a certain number of cycles, and to reactivate it when appropriate. + + This module is responsible for maintaining the following tables: + - {!Storage.Contract.Inactive_delegate} + - {!Storage.Contract.Delegate_last_cycle_before_deactivation} *) + +val is_inactive : + Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + +(** [last_cycle_before_deactivation ctxt delegate] is the cycle at which + the delegate is scheduled to become inactive. *) +val last_cycle_before_deactivation : + Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t tzresult Lwt.t + +(** [set_inactive context delegate] adds [delegate] to the set of inactive + contracts. *) +val set_inactive : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t Lwt.t + +(** [set_active ctxt delegate] returns a pair [(new_ctxt, is_inactive)] where: + - [new_ctxt] is a new context, updated from [ctxt], where the [delegate]'s + last active cycle has been updated + - [is_inactive] represents the state of [delegate], prior to the update. + *) +val set_active : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Raw_context.t * bool) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.ml b/src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.ml new file mode 100644 index 000000000000..e08d7a6327fb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.ml @@ -0,0 +1,236 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Invalid_consensus_key_update_noop of Cycle_repr.t + | Invalid_consensus_key_update_active + | Invalid_consensus_key_update_tz4 of Bls.Public_key.t + +let () = + register_error_kind + `Permanent + ~id:"delegate.consensus_key.invalid_noop" + ~title:"Invalid key for consensus key update" + ~description:"Tried to update the consensus key with the active key" + ~pp:(fun ppf cycle -> + Format.fprintf + ppf + "Invalid key while updating a consensus key (already active since %a)." + Cycle_repr.pp + cycle) + Data_encoding.(obj1 (req "cycle" Cycle_repr.encoding)) + (function Invalid_consensus_key_update_noop c -> Some c | _ -> None) + (fun c -> Invalid_consensus_key_update_noop c) ; + register_error_kind + `Permanent + ~id:"delegate.consensus_key.active" + ~title:"Active consensus key" + ~description: + "The delegate consensus key is already used by another delegate" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The delegate consensus key is already used by another delegate") + Data_encoding.empty + (function Invalid_consensus_key_update_active -> Some () | _ -> None) + (fun () -> Invalid_consensus_key_update_active) ; + register_error_kind + `Permanent + ~id:"delegate.consensus_key.tz4" + ~title:"Consensus key cannot be a tz4" + ~description:"Consensus key cannot be a tz4 (BLS public key)." + ~pp:(fun ppf pk -> + Format.fprintf + ppf + "The consensus key %a is forbidden as it is a BLS public key." + Bls.Public_key_hash.pp + (Bls.Public_key.hash pk)) + Data_encoding.(obj1 (req "delegate_pk" Bls.Public_key.encoding)) + (function Invalid_consensus_key_update_tz4 pk -> Some pk | _ -> None) + (fun pk -> Invalid_consensus_key_update_tz4 pk) + +type pk = Raw_context.consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +type t = { + delegate : Signature.Public_key_hash.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +let pkh {delegate; consensus_pkh; consensus_pk = _} = {delegate; consensus_pkh} + +let zero = + { + consensus_pkh = Signature.Public_key_hash.zero; + delegate = Signature.Public_key_hash.zero; + } + +let pp ppf {delegate; consensus_pkh} = + Format.fprintf ppf "@[%a" Signature.Public_key_hash.pp delegate ; + if not (Signature.Public_key_hash.equal delegate consensus_pkh) then + Format.fprintf + ppf + "@,Active key: %a" + Signature.Public_key_hash.pp + consensus_pkh ; + Format.fprintf ppf "@]" + +(* Invariant: + No two delegates use the same active consensus key at a given time. + + To ensure that, {!Storage.Consensus_keys} contains keys that will be active + at cycle `current + consensus_rights_delay + 1`. +*) + +let check_unused ctxt pkh = + let open Lwt_result_syntax in + let*! is_active = Storage.Consensus_keys.mem ctxt pkh in + fail_when is_active Invalid_consensus_key_update_active + +let check_not_tz4 : Signature.Public_key.t -> unit tzresult = + let open Result_syntax in + function + | Bls pk -> tzfail (Invalid_consensus_key_update_tz4 pk) + | Ed25519 _ | Secp256k1 _ | P256 _ -> return_unit + +let set_unused = Storage.Consensus_keys.remove + +let set_used = Storage.Consensus_keys.add + +let init ctxt delegate pk = + let open Lwt_result_syntax in + let*? () = check_not_tz4 pk in + let pkh = Signature.Public_key.hash pk in + let* () = check_unused ctxt pkh in + let*! ctxt = set_used ctxt pkh in + Storage.Contract.Consensus_key.init ctxt (Contract_repr.Implicit delegate) pk + +let active_pubkey ctxt delegate = + let open Lwt_result_syntax in + let* pk = + Storage.Contract.Consensus_key.get ctxt (Contract_repr.Implicit delegate) + in + let pkh = Signature.Public_key.hash pk in + return {consensus_pk = pk; consensus_pkh = pkh; delegate} + +let active_key ctxt delegate = + let open Lwt_result_syntax in + let* pk = active_pubkey ctxt delegate in + return (pkh pk) + +let raw_pending_updates ctxt ?up_to_cycle delegate = + let open Lwt_result_syntax in + let relevant_cycles = + let level = Raw_context.current_level ctxt in + let first_cycle = Cycle_repr.succ level.cycle in + let last_cycle = + match up_to_cycle with + | None -> + let cycles_delay = + Constants_storage.consensus_key_activation_delay ctxt + in + Cycle_repr.add first_cycle cycles_delay + | Some cycle -> cycle + in + Cycle_repr.(first_cycle ---> last_cycle) + in + let delegate = Contract_repr.Implicit delegate in + List.filter_map_es + (fun cycle -> + let* pending_for_cycle = + Storage.Pending_consensus_keys.find (ctxt, cycle) delegate + in + pending_for_cycle |> Option.map (fun pk -> (cycle, pk)) |> return) + relevant_cycles + +let pending_updates ctxt delegate = + let open Lwt_result_syntax in + let* updates = raw_pending_updates ctxt delegate in + return + (List.map (fun (c, pk) -> (c, Signature.Public_key.hash pk, pk)) updates) + +let raw_active_pubkey_for_cycle ctxt delegate cycle = + let open Lwt_result_syntax in + let* pendings = raw_pending_updates ctxt ~up_to_cycle:cycle delegate in + let* active = active_pubkey ctxt delegate in + let current_cycle = (Raw_context.current_level ctxt).cycle in + match List.hd (List.rev pendings) with + | None -> return (current_cycle, active.consensus_pk) + | Some (cycle, pk) -> return (cycle, pk) + +let active_pubkey_for_cycle ctxt delegate cycle = + let open Lwt_result_syntax in + let+ _, consensus_pk = raw_active_pubkey_for_cycle ctxt delegate cycle in + { + consensus_pk; + consensus_pkh = Signature.Public_key.hash consensus_pk; + delegate; + } + +let register_update ctxt delegate pk = + let open Lwt_result_syntax in + let update_cycle = + let current_level = Raw_context.current_level ctxt in + let cycles_delay = Constants_storage.consensus_key_activation_delay ctxt in + Cycle_repr.add current_level.cycle (cycles_delay + 1) + in + let* () = + let* first_active_cycle, active_pubkey = + raw_active_pubkey_for_cycle ctxt delegate update_cycle + in + fail_when + Signature.Public_key.(pk = active_pubkey) + (Invalid_consensus_key_update_noop first_active_cycle) + in + let*? () = check_not_tz4 pk in + let pkh = Signature.Public_key.hash pk in + let* () = check_unused ctxt pkh in + let*! ctxt = set_used ctxt pkh in + let* {consensus_pkh = old_pkh; _} = + active_pubkey_for_cycle ctxt delegate update_cycle + in + let*! ctxt = set_unused ctxt old_pkh in + let*! ctxt = + Storage.Pending_consensus_keys.add + (ctxt, update_cycle) + (Contract_repr.Implicit delegate) + pk + in + return ctxt + +let activate ctxt ~new_cycle = + let open Lwt_syntax in + let* ctxt = + Storage.Pending_consensus_keys.fold + (ctxt, new_cycle) + ~order:`Undefined + ~init:ctxt + ~f:(fun delegate pk ctxt -> + Storage.Contract.Consensus_key.add ctxt delegate pk) + in + Storage.Pending_consensus_keys.clear (ctxt, new_cycle) diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.mli b/src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.mli new file mode 100644 index 000000000000..0e7ed066f4e5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_consensus_key.mli @@ -0,0 +1,97 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Management of a delegate's consensus key, the one used to sign + blocks and consensus operations. It is responsible for maintaining + the tables {!Storage.Consensus_keys}, + {!Storage.Contract.Consensus_key}, and + {!Storage.Contract.Pending_consensus_keys}. *) + +type error += + | Invalid_consensus_key_update_noop of Cycle_repr.t + | Invalid_consensus_key_update_active + | Invalid_consensus_key_update_tz4 of Bls.Public_key.t + +(** The public key of a consensus key and the associated delegate. *) +type pk = Raw_context.consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +(** The public key hash of a consensus key and the associated delegate. *) +type t = { + delegate : Signature.Public_key_hash.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +val zero : t + +val pp : Format.formatter -> t -> unit + +val pkh : pk -> t + +(** [check_not_tz4 pk] checks that [pk] is not a BLS address. *) +val check_not_tz4 : Signature.public_key -> unit tzresult + +(** Initialize the consensus key when registering a delegate. *) +val init : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t -> + Raw_context.t tzresult Lwt.t + +(** Returns the active consensus key for the current cycle. *) +val active_pubkey : + Raw_context.t -> Signature.Public_key_hash.t -> pk tzresult Lwt.t + +(** Returns the active consensus key for the current cycle. *) +val active_key : + Raw_context.t -> Signature.Public_key_hash.t -> t tzresult Lwt.t + +(** Returns the active consensus key for the given cycle. *) +val active_pubkey_for_cycle : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + pk tzresult Lwt.t + +(** Returns the list of pending consensus-key updates in upcoming cycles. *) +val pending_updates : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Cycle_repr.t * Signature.Public_key_hash.t * Signature.Public_key.t) list + tzresult + Lwt.t + +(** Register a consensus-key update. *) +val register_update : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t -> + Raw_context.t tzresult Lwt.t + +(** Activate consensus keys at the beginning of cycle [new_cycle]. *) +val activate : Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_cycles.ml b/src/proto_020_PsParisC/lib_protocol/delegate_cycles.ml new file mode 100644 index 000000000000..298137167432 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_cycles.ml @@ -0,0 +1,254 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let update_activity ctxt last_cycle = + let open Lwt_result_syntax in + let rights_delay = Constants_storage.consensus_rights_delay ctxt in + match Cycle_repr.sub last_cycle rights_delay with + | None -> + (* do not update activity in the first cycles of a network.*) + return (ctxt, []) + | Some _unfrozen_cycle -> + Stake_storage.fold_on_active_delegates_with_minimal_stake_s + ctxt + ~order:`Sorted + ~init:(Ok (ctxt, [])) + ~f:(fun delegate acc -> + let*? ctxt, deactivated = acc in + let* cycle = + Delegate_activation_storage.last_cycle_before_deactivation + ctxt + delegate + in + if Cycle_repr.(cycle <= last_cycle) then + let*! ctxt = Stake_storage.set_inactive ctxt delegate in + return (ctxt, delegate :: deactivated) + else return (ctxt, deactivated)) + +let delegate_has_revealed_nonces delegate unrevelead_nonces_set = + not (Signature.Public_key_hash.Set.mem delegate unrevelead_nonces_set) + +let distribute_attesting_rewards ctxt last_cycle unrevealed_nonces = + let open Lwt_result_syntax in + let*? attesting_reward_per_slot = + Delegate_rewards.attesting_reward_per_slot ctxt + in + let unrevealed_nonces_set = + List.fold_left + (fun set {Storage.Seed.nonce_hash = _; delegate} -> + Signature.Public_key_hash.Set.add delegate set) + Signature.Public_key_hash.Set.empty + unrevealed_nonces + in + let* total_active_stake = + Stake_storage.get_total_active_stake ctxt last_cycle + in + let total_active_stake_weight = + Stake_repr.staking_weight total_active_stake + in + let* delegates = Stake_storage.get_selected_distribution ctxt last_cycle in + List.fold_left_es + (fun (ctxt, balance_updates) (delegate, active_stake) -> + let* ctxt, sufficient_participation = + Delegate_missed_attestations_storage + .check_and_reset_delegate_participation + ctxt + delegate + in + let has_revealed_nonces = + delegate_has_revealed_nonces delegate unrevealed_nonces_set + in + let active_stake_weight = Stake_repr.staking_weight active_stake in + let expected_slots = + Delegate_missed_attestations_storage + .expected_slots_for_given_active_stake + ctxt + ~total_active_stake_weight + ~active_stake_weight + in + let rewards = Tez_repr.mul_exn attesting_reward_per_slot expected_slots in + if sufficient_participation && has_revealed_nonces then + (* Sufficient participation: we pay the rewards *) + let+ ctxt, payed_rewards_receipts = + Shared_stake.pay_rewards + ctxt + ~active_stake + ~source:`Attesting_rewards + ~delegate + rewards + in + (ctxt, payed_rewards_receipts @ balance_updates) + else + (* Insufficient participation or unrevealed nonce: no rewards *) + let+ ctxt, payed_rewards_receipts = + Token.transfer + ctxt + `Attesting_rewards + (`Lost_attesting_rewards + (delegate, not sufficient_participation, not has_revealed_nonces)) + rewards + in + (ctxt, payed_rewards_receipts @ balance_updates)) + (ctxt, []) + delegates + +let adjust_frozen_stakes ctxt ~deactivated_delegates : + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t = + let open Lwt_result_syntax in + (* Note: deactivated_delegates have just been removed from the set of + active delegates with minimal stake by [update_activity] so the two + following iterations are on disjoint sets of delegates. *) + let* ctxt, balance_updates = + Stake_storage.fold_on_active_delegates_with_minimal_stake_es + ctxt + ~order:`Undefined + ~init:(ctxt, []) + ~f:(fun delegate (ctxt, balance_updates) -> + let*! has_been_denounced = + Pending_denunciations_storage.has_pending_denunciations ctxt delegate + in + if has_been_denounced then return (ctxt, balance_updates) + (* we don't autostake on behalf of delegates who will be slashed *) + else + let* full_staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + let own_frozen = + Full_staking_balance_repr.own_frozen full_staking_balance + in + let*? optimal_frozen = + Stake_context.optimal_frozen_wrt_delegated_without_ai + ctxt + full_staking_balance + in + let* deposit_limit = + Delegate_storage.frozen_deposits_limit ctxt delegate + in + let optimal_frozen = + match deposit_limit with + | None -> optimal_frozen + | Some deposit_limit -> Tez_repr.min optimal_frozen deposit_limit + in + let* ctxt, new_balance_updates = + if Tez_repr.(optimal_frozen > own_frozen) then + let*? optimal_to_stake = + Tez_repr.(optimal_frozen -? own_frozen) + in + Staking.stake + ctxt + ~for_next_cycle_use_only_after_slashing:true + ~amount:(`At_most optimal_to_stake) + ~sender:delegate + ~delegate + else if Tez_repr.(optimal_frozen < own_frozen) then + let*? to_unstake = Tez_repr.(own_frozen -? optimal_frozen) in + Staking.request_unstake + ctxt + ~for_next_cycle_use_only_after_slashing:true + ~sender_contract:Contract_repr.(Implicit delegate) + ~delegate + to_unstake + else + Staking.finalize_unstake + ctxt + ~for_next_cycle_use_only_after_slashing:true + Contract_repr.(Implicit delegate) + in + return (ctxt, new_balance_updates @ balance_updates)) + in + List.fold_left_es + (fun (ctxt, balance_updates) delegate -> + let+ ctxt, new_balance_updates = + Staking.request_unstake + ctxt + ~for_next_cycle_use_only_after_slashing:true + ~sender_contract:(Implicit delegate) + ~delegate + Tez_repr.max_mutez + in + (ctxt, new_balance_updates @ balance_updates)) + (ctxt, balance_updates) + deactivated_delegates + +let cycle_end ctxt last_cycle = + let open Lwt_result_syntax in + (* attributing attesting rewards *) + let* ctxt, unrevealed_nonces = Seed_storage.cycle_end ctxt last_cycle in + let* ctxt, attesting_balance_updates = + distribute_attesting_rewards ctxt last_cycle unrevealed_nonces + in + (* Applying slashing related to expiring denunciations *) + let* ctxt, slashing_balance_updates = + Delegate_slashed_deposits_storage.apply_and_clear_denunciations ctxt + in + let new_cycle = Cycle_repr.add last_cycle 1 in + let*! ctxt = Already_denounced_storage.clear_outdated_cycle ctxt ~new_cycle in + (* Deactivating delegates which didn't participate to consensus for too long *) + let* ctxt, deactivated_delegates = update_activity ctxt last_cycle in + (* Applying autostaking. Do not move before slashing. Keep before rights + computation for optimising rights*) + let* ctxt, autostake_balance_updates = + match Staking.staking_automation ctxt with + | Manual_staking -> return (ctxt, []) + | Auto_staking -> adjust_frozen_stakes ctxt ~deactivated_delegates + in + (* Computing future staking rights *) + let* ctxt = + Delegate_sampler.select_new_distribution_at_cycle_end ctxt ~new_cycle + in + (* Activating consensus key for the cycle to come *) + let*! ctxt = Delegate_consensus_key.activate ctxt ~new_cycle in + (* trying to unforbid delegates for the cycle to come. *) + let* ctxt = + Forbidden_delegates_storage.update_at_cycle_end_after_slashing + ctxt + ~new_cycle + in + (* clear deprecated cycles data. *) + let* ctxt = Stake_storage.clear_at_cycle_end ctxt ~new_cycle in + let* ctxt = Delegate_sampler.clear_outdated_sampling_data ctxt ~new_cycle in + (* activate delegate parameters for the cycle to come. *) + let*! ctxt = Delegate_staking_parameters.activate ctxt ~new_cycle in + (* updating AI coefficient. It should remain after all balance changes of the + cycle-end operations *) + let* ctxt = + Adaptive_issuance_storage.update_stored_rewards_at_cycle_end ctxt ~new_cycle + in + let balance_updates = + slashing_balance_updates @ attesting_balance_updates + @ autostake_balance_updates + in + return (ctxt, balance_updates, deactivated_delegates) + +let init_first_cycles ctxt = + let consensus_rights_delay = Constants_storage.consensus_rights_delay ctxt in + List.fold_left_es + (fun ctxt c -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in + Delegate_sampler.select_distribution_for_cycle ctxt cycle) + ctxt + Misc.(0 --> consensus_rights_delay) diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_cycles.mli b/src/proto_020_PsParisC/lib_protocol/delegate_cycles.mli new file mode 100644 index 000000000000..c1ae98330556 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_cycles.mli @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Per-cycle management of delegates. *) + +(** Trigger the context maintenance at the end of cycle 'n', i.e.: + unfreeze the attesting rewards, potentially deactivate delegates. + Return the corresponding balances updates and the list of + deactivated delegates. *) +val cycle_end : + Raw_context.t -> + Cycle_repr.t -> + (Raw_context.t + * Receipt_repr.balance_updates + * Signature.Public_key_hash.t list) + tzresult + Lwt.t + +(** [init_first_cycles ctxt] computes and records the distribution of + the total active stake among active delegates. This concerns the total + active stake involved in the calculation of baking rights for all cycles + in the range [0, consensus_rights_delay]. It also freezes the deposits for all + the active delegates. *) +val init_first_cycles : Raw_context.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.ml b/src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.ml new file mode 100644 index 000000000000..75e22cc632c7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.ml @@ -0,0 +1,245 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let expected_slots_for_given_active_stake ctxt ~total_active_stake_weight + ~active_stake_weight = + let blocks_per_cycle = + Int32.to_int (Constants_storage.blocks_per_cycle ctxt) + in + let consensus_committee_size = + Constants_storage.consensus_committee_size ctxt + in + let number_of_attestations_per_cycle = + blocks_per_cycle * consensus_committee_size + in + Z.to_int + (Z.div + (Z.mul + (Z.of_int64 active_stake_weight) + (Z.of_int number_of_attestations_per_cycle)) + (Z.of_int64 total_active_stake_weight)) + +type level_participation = Participated | Didn't_participate + +(* Note that the participation for the last block of a cycle is + recorded in the next cycle. *) +let record_attesting_participation ctxt ~delegate ~participation + ~attesting_power = + let open Lwt_result_syntax in + match participation with + | Participated -> Stake_storage.set_active ctxt delegate + | Didn't_participate -> ( + let contract = Contract_repr.Implicit delegate in + let* result = Storage.Contract.Missed_attestations.find ctxt contract in + match result with + | Some {remaining_slots; missed_levels} -> + let remaining_slots = remaining_slots - attesting_power in + Storage.Contract.Missed_attestations.update + ctxt + contract + {remaining_slots; missed_levels = missed_levels + 1} + | None -> ( + let level = Level_storage.current ctxt in + let*? stake_distribution = + Raw_context.stake_distribution_for_current_cycle ctxt + in + match + Signature.Public_key_hash.Map.find delegate stake_distribution + with + | None -> + (* This happens when the block is the first one in a + cycle, and therefore the attestations are for the last + block of the previous cycle, and when the delegate does + not have an active stake at the current cycle; in this + case its participation is simply ignored. *) + assert (Compare.Int32.(level.cycle_position = 0l)) ; + return ctxt + | Some active_stake -> + let* total_active_stake = + Stake_storage.get_total_active_stake ctxt level.cycle + in + let expected_slots = + let active_stake_weight = + Stake_repr.staking_weight active_stake + in + let total_active_stake_weight = + Stake_repr.staking_weight total_active_stake + in + expected_slots_for_given_active_stake + ctxt + ~total_active_stake_weight + ~active_stake_weight + in + let Ratio_repr.{numerator; denominator} = + Constants_storage.minimal_participation_ratio ctxt + in + let minimal_activity = expected_slots * numerator / denominator in + let maximal_inactivity = expected_slots - minimal_activity in + let remaining_slots = maximal_inactivity - attesting_power in + Storage.Contract.Missed_attestations.init + ctxt + contract + {remaining_slots; missed_levels = 1})) + +let record_baking_activity_and_pay_rewards_and_fees ctxt ~payload_producer + ~block_producer ~baking_reward ~reward_bonus = + let open Lwt_result_syntax in + let* ctxt = Stake_storage.set_active ctxt payload_producer in + let* ctxt = + if not (Signature.Public_key_hash.equal payload_producer block_producer) + then Stake_storage.set_active ctxt block_producer + else return ctxt + in + let pay_payload_producer ctxt delegate = + let contract = Contract_repr.Implicit delegate in + let* ctxt, block_fees = Token.balance ctxt `Block_fees in + let* ctxt, balance_updates_block_fees = + Token.transfer ctxt `Block_fees (`Contract contract) block_fees + in + let+ ctxt, balance_updates_baking_rewards = + Shared_stake.pay_rewards + ctxt + ~source:`Baking_rewards + ~delegate + baking_reward + in + (ctxt, balance_updates_block_fees @ balance_updates_baking_rewards) + in + let pay_block_producer ctxt delegate bonus = + Shared_stake.pay_rewards ctxt ~source:`Baking_bonuses ~delegate bonus + in + let* ctxt, balance_updates_payload_producer = + pay_payload_producer ctxt payload_producer + in + let* ctxt, balance_updates_block_producer = + match reward_bonus with + | Some bonus -> pay_block_producer ctxt block_producer bonus + | None -> return (ctxt, []) + in + return + (ctxt, balance_updates_payload_producer @ balance_updates_block_producer) + +let check_and_reset_delegate_participation ctxt delegate = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit delegate in + let* missed = Storage.Contract.Missed_attestations.find ctxt contract in + match missed with + | None -> return (ctxt, true) + | Some missed_attestations -> + let*! ctxt = Storage.Contract.Missed_attestations.remove ctxt contract in + return (ctxt, Compare.Int.(missed_attestations.remaining_slots >= 0)) + +module For_RPC = struct + type participation_info = { + expected_cycle_activity : int; + minimal_cycle_activity : int; + missed_slots : int; + missed_levels : int; + remaining_allowed_missed_slots : int; + expected_attesting_rewards : Tez_repr.t; + } + + (* Inefficient, only for RPC *) + let participation_info ctxt delegate = + let open Lwt_result_syntax in + let level = Level_storage.current ctxt in + let* stake_distribution = + Stake_storage.get_selected_distribution ctxt level.cycle + in + match + List.assoc_opt + ~equal:Signature.Public_key_hash.equal + delegate + stake_distribution + with + | None -> + (* delegate does not have an active stake at the current cycle *) + return + { + expected_cycle_activity = 0; + minimal_cycle_activity = 0; + missed_slots = 0; + missed_levels = 0; + remaining_allowed_missed_slots = 0; + expected_attesting_rewards = Tez_repr.zero; + } + | Some active_stake -> + let* total_active_stake = + Stake_storage.get_total_active_stake ctxt level.cycle + in + let expected_cycle_activity = + let active_stake_weight = Stake_repr.staking_weight active_stake in + let total_active_stake_weight = + Stake_repr.staking_weight total_active_stake + in + expected_slots_for_given_active_stake + ctxt + ~total_active_stake_weight + ~active_stake_weight + in + let Ratio_repr.{numerator; denominator} = + Constants_storage.minimal_participation_ratio ctxt + in + let*? attesting_reward_per_slot = + Delegate_rewards.attesting_reward_per_slot ctxt + in + let minimal_cycle_activity = + expected_cycle_activity * numerator / denominator + in + let maximal_cycle_inactivity = + expected_cycle_activity - minimal_cycle_activity + in + let expected_attesting_rewards = + Tez_repr.mul_exn attesting_reward_per_slot expected_cycle_activity + in + let contract = Contract_repr.Implicit delegate in + let* missed_attestations = + Storage.Contract.Missed_attestations.find ctxt contract + in + let missed_slots, missed_levels, remaining_allowed_missed_slots = + match missed_attestations with + | None -> (0, 0, maximal_cycle_inactivity) + | Some {remaining_slots; missed_levels} -> + ( maximal_cycle_inactivity - remaining_slots, + missed_levels, + Compare.Int.max 0 remaining_slots ) + in + let expected_attesting_rewards = + match missed_attestations with + | Some r when Compare.Int.(r.remaining_slots < 0) -> Tez_repr.zero + | _ -> expected_attesting_rewards + in + return + { + expected_cycle_activity; + minimal_cycle_activity; + missed_slots; + missed_levels; + remaining_allowed_missed_slots; + expected_attesting_rewards; + } +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.mli b/src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.mli new file mode 100644 index 000000000000..6f343fd43438 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_missed_attestations_storage.mli @@ -0,0 +1,101 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This modules deals with delegates' participation in consensus. + + This module is responsible for maintaining the + {!Storage.Contract.Missed_attestations} table. *) + +val expected_slots_for_given_active_stake : + Raw_context.t -> + total_active_stake_weight:int64 -> + active_stake_weight:int64 -> + int + +type level_participation = Participated | Didn't_participate + +(** Record the participation of a delegate as a validator. *) +val record_attesting_participation : + Raw_context.t -> + delegate:Signature.Public_key_hash.t -> + participation:level_participation -> + attesting_power:int -> + Raw_context.t tzresult Lwt.t + +(** Sets the payload and block producer as active. Pays the baking + reward and the fees to the payload producer and the reward bonus to + the payload producer (if the reward_bonus is not None).*) +val record_baking_activity_and_pay_rewards_and_fees : + Raw_context.t -> + payload_producer:Signature.Public_key_hash.t -> + block_producer:Signature.Public_key_hash.t -> + baking_reward:Tez_repr.t -> + reward_bonus:Tez_repr.t option -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** Check that a delegate participated enough in the last cycle + (returns [true] if it did), and then reset the participation for + preparing the next cycle. *) +val check_and_reset_delegate_participation : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Raw_context.t * bool) tzresult Lwt.t + +module For_RPC : sig + (** Participation information. We denote by: + - "static" information that does not change during the cycle + - "dynamic" information that may change during the cycle *) + type participation_info = { + expected_cycle_activity : int; + (** The total expected slots to be attested in the cycle. (static) *) + minimal_cycle_activity : int; + (** The minimal attesting slots in the cycle to get attesting rewards. + (static) *) + missed_slots : int; + (** The number of missed attesting slots in the cycle. (dynamic) *) + missed_levels : int; + (** The number of missed attesting levels in the cycle. (dynamic) *) + remaining_allowed_missed_slots : int; + (** Remaining amount of attesting slots that can be missed in the + cycle before forfeiting the rewards. (dynamic) *) + expected_attesting_rewards : Tez_repr.t; + (** Attesting rewards that will be distributed at the end of the + cycle if activity at that point will be greater than the minimal + required. If the activity is already known to be below the + required minimum, then the rewards are zero. (dynamic) *) + } + + (** Only use this function for RPC: this is expensive. + + [delegate_participation_info] and [!val:check_delegate] forms the + implementation of RPC call "/context/delegates//participation". + *) + val participation_info : + Raw_context.t -> + Signature.Public_key_hash.t -> + participation_info tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_rewards.ml b/src/proto_020_PsParisC/lib_protocol/delegate_rewards.ml new file mode 100644 index 000000000000..c4d3458a05db --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_rewards.ml @@ -0,0 +1,162 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Sum weights for normalizing *) +let sum_weights + ({ + base_total_issued_per_minute = _; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } : + Constants_parametric_repr.issuance_weights) = + let r = baking_reward_fixed_portion_weight in + let r = baking_reward_bonus_weight + r in + let r = attesting_reward_weight + r in + let r = seed_nonce_revelation_tip_weight + r in + let r = vdf_revelation_tip_weight + r in + assert (Compare.Int.(r > 0)) ; + r + +(* [tez_from_weights] returns an amount of rewards in [Tez.t], + given a couple of parameters: + [rewards] describes all the possible rewards, as a record of weights + for each of them. It also gives the (maximum) amount of rewards per minute + expected on the chain + [weight] is one of those reward weights as described in [rewards] + [minimal_block_delay] is the minimum amount of time between two blocks. *) +let tez_from_weights + ~(issuance_weights : Constants_parametric_repr.issuance_weights) + ~(weight : int) ~(minimal_block_delay : Period_repr.t) = + let sum_weights = sum_weights issuance_weights in + let block_delay = minimal_block_delay |> Period_repr.to_seconds in + (* base_tez = issuance_weights.base_total_issued_per_minute + relative_weight = reward_weight / sum_weights + minute_per_block = block_delay (in seconds) / 60 + rewarded_tez = base_tez * relative_weight * blocks_per_minute *) + let num = Int64.(mul (of_int weight) block_delay) in + let den = Int64.of_int (sum_weights * 60) in + Tez_repr.mul_ratio + ~rounding:`Down + issuance_weights.base_total_issued_per_minute + ~num + ~den + +(* Bundling some functions inside a module so they can be exported as part + of `Internal_for_tests` further down. *) +module M = struct + type reward_kind = + | Baking_reward_fixed_portion + | Baking_reward_bonus_per_slot + | Attesting_reward_per_slot + | Seed_nonce_revelation_tip + | Vdf_revelation_tip + + let reward_from_constants ~(csts : Constants_parametric_repr.t) ~reward_kind + ~(coeff : Q.t) = + let open Result_syntax in + let issuance_weights = csts.issuance_weights in + let weight = + match reward_kind with + | Baking_reward_fixed_portion -> + issuance_weights.baking_reward_fixed_portion_weight + | Baking_reward_bonus_per_slot -> + issuance_weights.baking_reward_bonus_weight + | Attesting_reward_per_slot -> issuance_weights.attesting_reward_weight + | Seed_nonce_revelation_tip -> + (* Seed nonce revelation rewards are given every [blocks_per_commitment](=192)th block *) + let blocks_per_commitment = Int32.to_int csts.blocks_per_commitment in + issuance_weights.seed_nonce_revelation_tip_weight + * blocks_per_commitment + | Vdf_revelation_tip -> + (* Vdf revelation rewards are given every [blocks_per_commitment](=192)th block *) + let blocks_per_commitment = Int32.to_int csts.blocks_per_commitment in + issuance_weights.vdf_revelation_tip_weight * blocks_per_commitment + in + let minimal_block_delay = csts.minimal_block_delay in + let* rewards = + tez_from_weights ~issuance_weights ~weight ~minimal_block_delay + in + let base_rewards = + match reward_kind with + | Baking_reward_bonus_per_slot -> + let bonus_committee_size = + csts.consensus_committee_size - csts.consensus_threshold + in + if Compare.Int.(bonus_committee_size <= 0) then Tez_repr.zero + else Tez_repr.div_exn rewards bonus_committee_size + | Attesting_reward_per_slot -> + Tez_repr.div_exn rewards csts.consensus_committee_size + | _ -> rewards + in + Tez_repr.mul_q ~rounding:`Down base_rewards coeff + + let liquidity_baking_subsidy_from_constants + (constants : Constants_parametric_repr.t) = + let liquidity_baking_subsidy = constants.liquidity_baking_subsidy in + let minimal_block_delay = + constants.minimal_block_delay |> Period_repr.to_seconds |> Int64.to_int + in + Tez_repr.mul_q + ~rounding:`Down + liquidity_baking_subsidy + Q.(minimal_block_delay // 60) +end + +open M + +let reward_from_context ~ctxt ~reward_kind = + let csts = Raw_context.constants ctxt in + let coeff = Raw_context.reward_coeff_for_current_cycle ctxt in + reward_from_constants ~csts ~reward_kind ~coeff + +let baking_reward_fixed_portion ctxt = + reward_from_context ~ctxt ~reward_kind:Baking_reward_fixed_portion + +let baking_reward_bonus_per_slot ctxt = + reward_from_context ~ctxt ~reward_kind:Baking_reward_bonus_per_slot + +let attesting_reward_per_slot ctxt = + reward_from_context ~ctxt ~reward_kind:Attesting_reward_per_slot + +let liquidity_baking_subsidy ctxt = + let constants = Raw_context.constants ctxt in + liquidity_baking_subsidy_from_constants constants + +let seed_nonce_revelation_tip ctxt = + reward_from_context ~ctxt ~reward_kind:Seed_nonce_revelation_tip + +let vdf_revelation_tip ctxt = + reward_from_context ~ctxt ~reward_kind:Vdf_revelation_tip + +module For_RPC = struct + include M + + let reward_from_constants ?(coeff = Q.one) + (csts : Constants_parametric_repr.t) ~reward_kind = + reward_from_constants ~csts ~reward_kind ~coeff +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_rewards.mli b/src/proto_020_PsParisC/lib_protocol/delegate_rewards.mli new file mode 100644 index 000000000000..309143c31bba --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_rewards.mli @@ -0,0 +1,62 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* These functions return the amount of tez rewarded for each action *) + +val baking_reward_fixed_portion : Raw_context.t -> Tez_repr.t tzresult + +val baking_reward_bonus_per_slot : Raw_context.t -> Tez_repr.t tzresult + +val attesting_reward_per_slot : Raw_context.t -> Tez_repr.t tzresult + +val liquidity_baking_subsidy : Raw_context.t -> Tez_repr.t tzresult + +val seed_nonce_revelation_tip : Raw_context.t -> Tez_repr.t tzresult + +val vdf_revelation_tip : Raw_context.t -> Tez_repr.t tzresult + +module For_RPC : sig + type reward_kind = + | Baking_reward_fixed_portion + | Baking_reward_bonus_per_slot + | Attesting_reward_per_slot + | Seed_nonce_revelation_tip + | Vdf_revelation_tip + + (** [reward_from_constants ~coeff csts ~reward_kind] returns the amount of + rewards in {!Tez_repr.t} for the given [reward_kind], according to the + given parameters in [csts]. The (optional) value [coeff] is a + multiplicative factor applied to the rewards (default = 1). + It verifies [reward_from_constants ~coeff csts ~reward_kind = + coeff * reward_from_constants csts ~reward_kind].*) + val reward_from_constants : + ?coeff:Q.t -> + Constants_parametric_repr.t -> + reward_kind:reward_kind -> + Tez_repr.t tzresult + + val liquidity_baking_subsidy_from_constants : + Constants_parametric_repr.t -> Tez_repr.t tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_sampler.ml b/src/proto_020_PsParisC/lib_protocol/delegate_sampler.ml new file mode 100644 index 000000000000..76a140ee5d50 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_sampler.ml @@ -0,0 +1,289 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Delegate_sampler_state = struct + module Cache_client = struct + type cached_value = Delegate_consensus_key.pk Sampler.t + + let namespace = Cache_repr.create_namespace "sampler_state" + + let cache_index = 2 + + let value_of_identifier ctxt identifier = + let cycle = Cycle_repr.of_string_exn identifier in + Storage.Delegate_sampler_state.get ctxt cycle + end + + module Cache = (val Cache_repr.register_exn (module Cache_client)) + + let identifier_of_cycle cycle = Format.asprintf "%a" Cycle_repr.pp cycle + + let init ctxt cycle sampler_state = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let* ctxt = Storage.Delegate_sampler_state.init ctxt cycle sampler_state in + let size = 1 (* that's symbolic: 1 cycle = 1 entry *) in + let*? ctxt = Cache.update ctxt id (Some (sampler_state, size)) in + return ctxt + + let get ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let* v_opt = Cache.find ctxt id in + match v_opt with + | None -> Storage.Delegate_sampler_state.get ctxt cycle + | Some v -> return v + + let remove_existing ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let*? ctxt = Cache.update ctxt id None in + Storage.Delegate_sampler_state.remove_existing ctxt cycle + + let remove ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let*? ctxt = Cache.update ctxt id None in + let*! ctxt = Storage.Delegate_sampler_state.remove ctxt cycle in + return ctxt +end + +module Random = struct + (* [init_random_state] initialize a random sequence drawing state + that's unique for a given (seed, level, index) triple. Elements + from this sequence are drawn using [take_int64], updating the + state for the next draw. The initial state is the Blake2b hash of + the three randomness sources, and an offset set to zero + (indicating that zero bits of randomness have been + consumed). When drawing random elements, bits are extracted from + the state until exhaustion (256 bits), at which point the state + is rehashed and the offset reset to 0. *) + + let init_random_state seed level index = + ( Raw_hashes.blake2b + (Data_encoding.Binary.to_bytes_exn + Data_encoding.(tup3 Seed_repr.seed_encoding int32 int32) + (seed, level.Level_repr.cycle_position, Int32.of_int index)), + 0 ) + + let take_int64 bound state = + let drop_if_over = + (* This function draws random values in [0-(bound-1)] by drawing + in [0-(2^63-1)] (64-bit) and computing the value modulo + [bound]. For the application of [mod bound] to preserve + uniformity, the input space must be of the form + [0-(n*bound-1)]. We enforce this by rejecting 64-bit samples + above this limit (in which case, we draw a new 64-sample from + the sequence and try again). *) + Int64.sub Int64.max_int (Int64.rem Int64.max_int bound) + in + let rec loop (bytes, n) = + let consumed_bytes = 8 in + let state_size = Bytes.length bytes in + if Compare.Int.(n > state_size - consumed_bytes) then + loop (Raw_hashes.blake2b bytes, 0) + else + let r = TzEndian.get_int64 bytes n in + (* The absolute value of min_int is min_int. Also, every + positive integer is represented twice (positive and negative), + but zero is only represented once. We fix both problems at + once. *) + let r = if Compare.Int64.(r = Int64.min_int) then 0L else Int64.abs r in + if Compare.Int64.(r >= drop_if_over) then + loop (bytes, n + consumed_bytes) + else + let v = Int64.rem r bound in + (v, (bytes, n + consumed_bytes)) + in + loop state + + (** [sampler_for_cycle ctxt cycle] reads the sampler for [cycle] from + [ctxt] if it has been previously inited. Otherwise it initializes + the sampler and caches it in [ctxt] with + [Raw_context.set_sampler_for_cycle]. *) + let sampler_for_cycle ctxt cycle = + let open Lwt_result_syntax in + let read ctxt = + let* seed = Seed_storage.for_cycle ctxt cycle in + let+ state = Delegate_sampler_state.get ctxt cycle in + (seed, state) + in + Raw_context.sampler_for_cycle ~read ctxt cycle + + let owner c (level : Level_repr.t) offset = + let open Lwt_result_syntax in + let cycle = level.Level_repr.cycle in + let* c, seed, state = sampler_for_cycle c cycle in + let sample ~int_bound ~mass_bound = + let state = init_random_state seed level offset in + let i, state = take_int64 (Int64.of_int int_bound) state in + let elt, _ = take_int64 mass_bound state in + (Int64.to_int i, elt) + in + let pk = Sampler.sample state sample in + return (c, pk) +end + +let slot_owner c level slot = Random.owner c level (Slot_repr.to_int slot) + +let baking_rights_owner c (level : Level_repr.t) ~round = + let open Lwt_result_syntax in + let*? round = Round_repr.to_int round in + let consensus_committee_size = Constants_storage.consensus_committee_size c in + let*? slot = Slot_repr.of_int (round mod consensus_committee_size) in + let+ ctxt, pk = slot_owner c level slot in + (ctxt, slot, pk) + +let load_sampler_for_cycle ctxt cycle = + let open Lwt_result_syntax in + let* ctxt, (_ : Seed_repr.seed), (_ : Raw_context.consensus_pk Sampler.t) = + Random.sampler_for_cycle ctxt cycle + in + return ctxt + +let get_delegate_stake_from_staking_balance ctxt delegate staking_balance = + let open Lwt_result_syntax in + let* staking_parameters = + Delegate_staking_parameters.of_delegate ctxt delegate + in + Lwt.return + (Stake_context.apply_limits ctxt staking_parameters staking_balance) + +let get_stakes ctxt = + let open Lwt_result_syntax in + let minimal_frozen_stake = Constants_storage.minimal_frozen_stake ctxt in + let minimal_stake = Constants_storage.minimal_stake ctxt in + Stake_storage.fold_on_active_delegates_with_minimal_stake_es + ctxt + ~order:`Sorted + ~f:(fun delegate acc -> + let* staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + (* This function is called after slashing has been applied at cycle end, + hence there is no need to apply slashing on [staking_balance] as it + used to be when the value was taken from a snapshot. *) + if + Full_staking_balance_repr.has_minimal_frozen_stake + ~minimal_frozen_stake + staking_balance + then + let* stake_for_cycle = + get_delegate_stake_from_staking_balance ctxt delegate staking_balance + in + if + Stake_repr.has_minimal_stake_to_participate + ~minimal_stake + stake_for_cycle + then + let stakes, total_stake = acc in + let*? total_stake = Stake_repr.(total_stake +? stake_for_cycle) in + return ((delegate, stake_for_cycle) :: stakes, total_stake) + else return acc + else return acc) + ~init:([], Stake_repr.zero) + +let select_distribution_for_cycle ctxt cycle = + let open Lwt_result_syntax in + let* seed = Seed_storage.raw_for_cycle ctxt cycle in + let* stakes, total_stake = get_stakes ctxt in + let* ctxt = + Stake_storage.set_selected_distribution_for_cycle + ctxt + cycle + stakes + total_stake + in + let* stakes_pk = + List.fold_left_es + (fun acc (pkh, stake) -> + let+ pk = + Delegate_consensus_key.active_pubkey_for_cycle ctxt pkh cycle + in + (pk, Stake_repr.staking_weight stake) :: acc) + [] + stakes + in + let state = Sampler.create stakes_pk in + let* ctxt = Delegate_sampler_state.init ctxt cycle state in + (* pre-allocate the sampler *) + Lwt.return (Raw_context.init_sampler_for_cycle ctxt cycle seed state) + +let select_new_distribution_at_cycle_end ctxt ~new_cycle = + let consensus_rights_delay = Constants_storage.consensus_rights_delay ctxt in + let for_cycle = Cycle_repr.add new_cycle consensus_rights_delay in + select_distribution_for_cycle ctxt for_cycle + +let clear_outdated_sampling_data ctxt ~new_cycle = + let open Lwt_result_syntax in + match Cycle_repr.sub new_cycle Constants_repr.max_slashing_period with + | None -> return ctxt + | Some outdated_cycle -> + let* ctxt = Delegate_sampler_state.remove_existing ctxt outdated_cycle in + Seed_storage.remove_for_cycle ctxt outdated_cycle + +let cleanup_values_for_protocol_p ctxt ~preserved_cycles ~consensus_rights_delay + ~new_cycle = + let open Lwt_result_syntax in + assert (Compare.Int.(consensus_rights_delay <= preserved_cycles)) ; + if Compare.Int.(consensus_rights_delay = preserved_cycles) then return ctxt + else + let start_cycle = Cycle_repr.add new_cycle (consensus_rights_delay + 1) in + let end_cycle = Cycle_repr.add new_cycle preserved_cycles in + List.fold_left_es + Delegate_sampler_state.remove + ctxt + Cycle_repr.(start_cycle ---> end_cycle) + +let attesting_rights_count ctxt level = + let consensus_committee_size = + Constants_storage.consensus_committee_size ctxt + in + let open Lwt_result_syntax in + let*? slots = Slot_repr.Range.create ~min:0 ~count:consensus_committee_size in + Slot_repr.Range.fold_es + (fun (ctxt, map) slot -> + let* ctxt, consensus_pk = slot_owner ctxt level slot in + let map = + Signature.Public_key_hash.Map.update + consensus_pk.delegate + (function None -> Some 1 | Some slots_n -> Some (slots_n + 1)) + map + in + return (ctxt, map)) + (ctxt, Signature.Public_key_hash.Map.empty) + slots + +module For_RPC = struct + let delegate_current_baking_power ctxt delegate = + let open Lwt_result_syntax in + let* stake = Storage.Stake.Staking_balance.get ctxt delegate in + let* staking_parameters = + Delegate_staking_parameters.of_delegate ctxt delegate + in + Lwt.return @@ Stake_context.baking_weight ctxt staking_parameters stake +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_sampler.mli b/src/proto_020_PsParisC/lib_protocol/delegate_sampler.mli new file mode 100644 index 000000000000..6dd6001bdd96 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_sampler.mli @@ -0,0 +1,93 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module draws random values for a cycle based on the {!Seed_repr.seed} + associated that cycle. These random values are only delegates associated with + slots. + The selection of delegates is done by {i sampling} from a particular + distribution of the stake among the active delegates. + + This module is responsible for maintaining the table + {!Storage.Delegate_sampler_state}. *) + +(** Participation slots potentially associated to accounts. The + accounts that didn't place a deposit will be excluded from this + list. This function should only be used to compute the deposits to + freeze or initialize the protocol while stitching. RPCs can use this + function to predict an approximation of long term future slot + allocations. It shouldn't be used in the baker. *) +val slot_owner : + Raw_context.t -> + Level_repr.t -> + Slot_repr.t -> + (Raw_context.t * Delegate_consensus_key.pk) tzresult Lwt.t + +val baking_rights_owner : + Raw_context.t -> + Level_repr.t -> + round:Round_repr.round -> + (Raw_context.t * Slot_repr.t * Delegate_consensus_key.pk) tzresult Lwt.t + +(** [load_sampler_for_cycle ctxt cycle] caches the seeded stake + sampler for [cycle] in [ctxt]. If the sampler was already cached, + then [ctxt] is returned unchanged. + + This function has the same effect on [ctxt] as {!slot_owner} and + {!baking_rights_owner}. *) +val load_sampler_for_cycle : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val select_new_distribution_at_cycle_end : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val clear_outdated_sampling_data : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val select_distribution_for_cycle : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val cleanup_values_for_protocol_p : + Raw_context.t -> + preserved_cycles:int -> + consensus_rights_delay:int -> + new_cycle:Cycle_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [attesting_rights_count ctxt level] returns a map of the delegates to + their number of attestation slots for the given level. Fails if the + given level is in a cycle for which the seed is not in the storage *) +val attesting_rights_count : + Raw_context.t -> + Level_repr.t -> + (Raw_context.t * int Signature.Public_key_hash.Map.t) tzresult Lwt.t + +module For_RPC : sig + (** The baking power for a given delegate computed from its current + stake. *) + val delegate_current_baking_power : + Raw_context.t -> Signature.public_key_hash -> int64 tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_services.ml b/src/proto_020_PsParisC/lib_protocol/delegate_services.ml new file mode 100644 index 000000000000..e48962d5b718 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_services.ml @@ -0,0 +1,862 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Balance_rpc_non_delegate of public_key_hash + +type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t + +let () = + register_error_kind + `Temporary + ~id:"delegate.not_registered" + ~title:"Not a registered delegate" + ~description: + "The provided public key hash is not the address of a registered \ + delegate." + ~pp:(fun ppf pkh -> + Format.fprintf + ppf + "The provided public key hash (%a) is not the address of a registered \ + delegate. If you own this account and want to register it as a \ + delegate, use a delegation operation to delegate the account to \ + itself." + Signature.Public_key_hash.pp + pkh) + Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) + (function Not_registered pkh -> Some pkh | _ -> None) + (fun pkh -> Not_registered pkh) + +let () = + register_error_kind + `Temporary + ~id:"delegate_service.balance_rpc_on_non_delegate" + ~title:"Balance request for an unregistered delegate" + ~description:"The account whose balance was requested is not a delegate." + ~pp:(fun ppf pkh -> + Format.fprintf + ppf + "The implicit account (%a) whose balance was requested is not a \ + registered delegate. To get the balance of this account you can use \ + the ../context/contracts/%a/balance RPC." + Signature.Public_key_hash.pp + pkh + Signature.Public_key_hash.pp + pkh) + Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) + (function Balance_rpc_non_delegate pkh -> Some pkh | _ -> None) + (fun pkh -> Balance_rpc_non_delegate pkh) + +type consensus_key = { + consensus_key_pkh : Signature.Public_key_hash.t; + consensus_key_pk : Signature.Public_key.t; +} + +let consensus_key_encoding = + let open Data_encoding in + conv + (fun {consensus_key_pkh; consensus_key_pk} -> + (consensus_key_pkh, consensus_key_pk)) + (fun (consensus_key_pkh, consensus_key_pk) -> + {consensus_key_pkh; consensus_key_pk}) + (obj2 + (req "pkh" Signature.Public_key_hash.encoding) + (req "pk" Signature.Public_key.encoding)) + +type consensus_keys_info = { + active : consensus_key; + pendings : (Cycle.t * consensus_key) list; +} + +let consensus_key_info_encoding = + let open Data_encoding in + conv + (fun {active; pendings} -> (active, pendings)) + (fun (active, pendings) -> {active; pendings}) + (obj2 + (req "active" consensus_key_encoding) + (dft + "pendings" + (list + (merge_objs + (obj1 (req "cycle" Cycle.encoding)) + consensus_key_encoding)) + [])) + +let min_delegated_in_current_cycle_encoding = + let open Data_encoding in + conv + (fun (min_delegated, anchor) -> (min_delegated, anchor)) + (fun (min_delegated, anchor) -> (min_delegated, anchor)) + (obj2 (req "amount" Tez.encoding) (opt "level" Level_repr.encoding)) + +type info = { + full_balance : Tez.t; + current_frozen_deposits : Tez.t; + frozen_deposits : Tez.t; + staking_balance : Tez.t; + frozen_deposits_limit : Tez.t option; + delegated_contracts : Contract.t list; + delegated_balance : Tez.t; + min_delegated_in_current_cycle : Tez.t * Level_repr.t option; + total_delegated_stake : Tez.t; + staking_denominator : Staking_pseudotoken.t; + deactivated : bool; + grace_period : Cycle.t; + pending_denunciations : bool; + voting_info : Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; +} + +let info_encoding = + let open Data_encoding in + conv + (fun { + full_balance; + current_frozen_deposits; + frozen_deposits; + staking_balance; + frozen_deposits_limit; + delegated_contracts; + delegated_balance; + min_delegated_in_current_cycle; + total_delegated_stake; + staking_denominator; + deactivated; + grace_period; + pending_denunciations; + voting_info; + active_consensus_key; + pending_consensus_keys; + } -> + ( ( full_balance, + current_frozen_deposits, + frozen_deposits, + staking_balance, + frozen_deposits_limit, + delegated_contracts, + delegated_balance, + min_delegated_in_current_cycle, + deactivated, + grace_period ), + ( (pending_denunciations, total_delegated_stake, staking_denominator), + (voting_info, (active_consensus_key, pending_consensus_keys)) ) )) + (fun ( ( full_balance, + current_frozen_deposits, + frozen_deposits, + staking_balance, + frozen_deposits_limit, + delegated_contracts, + delegated_balance, + min_delegated_in_current_cycle, + deactivated, + grace_period ), + ( (pending_denunciations, total_delegated_stake, staking_denominator), + (voting_info, (active_consensus_key, pending_consensus_keys)) ) ) -> + { + full_balance; + current_frozen_deposits; + frozen_deposits; + staking_balance; + frozen_deposits_limit; + delegated_contracts; + delegated_balance; + min_delegated_in_current_cycle; + total_delegated_stake; + staking_denominator; + deactivated; + grace_period; + pending_denunciations; + voting_info; + active_consensus_key; + pending_consensus_keys; + }) + (merge_objs + (obj10 + (req "full_balance" Tez.encoding) + (req "current_frozen_deposits" Tez.encoding) + (req "frozen_deposits" Tez.encoding) + (req "staking_balance" Tez.encoding) + (opt "frozen_deposits_limit" Tez.encoding) + (req "delegated_contracts" (list Contract.encoding)) + (req "delegated_balance" Tez.encoding) + (req + "min_delegated_in_current_cycle" + min_delegated_in_current_cycle_encoding) + (req "deactivated" bool) + (req "grace_period" Cycle.encoding)) + (merge_objs + (obj3 + (req "pending_denunciations" bool) + (req "total_delegated_stake" Tez.encoding) + (req "staking_denominator" Staking_pseudotoken.For_RPC.encoding)) + (merge_objs + Vote.delegate_info_encoding + (obj2 + (req "active_consensus_key" Signature.Public_key_hash.encoding) + (dft + "pending_consensus_keys" + (list + (obj2 + (req "cycle" Cycle.encoding) + (req "pkh" Signature.Public_key_hash.encoding))) + []))))) + +let participation_info_encoding = + let open Data_encoding in + conv + (fun Delegate.For_RPC. + { + expected_cycle_activity; + minimal_cycle_activity; + missed_slots; + missed_levels; + remaining_allowed_missed_slots; + expected_attesting_rewards; + } -> + ( expected_cycle_activity, + minimal_cycle_activity, + missed_slots, + missed_levels, + remaining_allowed_missed_slots, + expected_attesting_rewards )) + (fun ( expected_cycle_activity, + minimal_cycle_activity, + missed_slots, + missed_levels, + remaining_allowed_missed_slots, + expected_attesting_rewards ) -> + { + expected_cycle_activity; + minimal_cycle_activity; + missed_slots; + missed_levels; + remaining_allowed_missed_slots; + expected_attesting_rewards; + }) + (obj6 + (req "expected_cycle_activity" int31) + (req "minimal_cycle_activity" int31) + (req "missed_slots" int31) + (req "missed_levels" int31) + (req "remaining_allowed_missed_slots" int31) + (req "expected_attesting_rewards" Tez.encoding)) + +type deposit_per_cycle = {cycle : Cycle.t; deposit : Tez.t} + +let deposit_per_cycle_encoding : deposit_per_cycle Data_encoding.t = + let open Data_encoding in + conv + (fun {cycle; deposit} -> (cycle, deposit)) + (fun (cycle, deposit) -> {cycle; deposit}) + (obj2 (req "cycle" Cycle.encoding) (req "deposit" Tez.encoding)) + +type pending_staking_parameters = Cycle.t * Staking_parameters_repr.t + +let pending_staking_parameters_encoding : + pending_staking_parameters Data_encoding.t = + let open Data_encoding in + obj2 + (req "cycle" Cycle.encoding) + (req "parameters" Staking_parameters_repr.encoding) + +module S = struct + let raw_path = RPC_path.(open_root / "context" / "delegates") + + open Data_encoding + + type list_query = { + active : bool; + inactive : bool; + with_minimal_stake : bool; + without_minimal_stake : bool; + } + + let list_query : list_query RPC_query.t = + let open RPC_query in + query (fun active inactive with_minimal_stake without_minimal_stake -> + {active; inactive; with_minimal_stake; without_minimal_stake}) + |+ flag "active" (fun t -> t.active) + |+ flag "inactive" (fun t -> t.inactive) + |+ flag "with_minimal_stake" (fun t -> t.with_minimal_stake) + |+ flag "without_minimal_stake" (fun t -> t.without_minimal_stake) + |> seal + + let list_delegate = + RPC_service.get_service + ~description: + "Lists all registered delegates by default. The arguments `active`, \ + `inactive`, `with_minimal_stake`, and `without_minimal_stake` allow \ + to enumerate only the delegates that are active, inactive, have at \ + least a minimal stake to participate in consensus and in governance, \ + or do not have such a minimal stake, respectively. Note, setting \ + these arguments to false has no effect." + ~query:list_query + ~output:(list Signature.Public_key_hash.encoding) + raw_path + + let path = RPC_path.(raw_path /: Signature.Public_key_hash.rpc_arg) + + let info = + RPC_service.get_service + ~description:"Everything about a delegate." + ~query:RPC_query.empty + ~output:info_encoding + path + + let full_balance = + RPC_service.get_service + ~description: + "Returns the full balance (in mutez) of a given delegate, including \ + the frozen deposits and the frozen bonds. It does not include its \ + delegated balance." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "full_balance") + + let current_frozen_deposits = + RPC_service.get_service + ~description: + "Returns the current amount of the frozen deposits (in mutez). That is \ + the frozen deposits at beginning of cycle plus rewards minus unstaked \ + and slashing. It doesn't count unstaked frozen deposits." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "current_frozen_deposits") + + let frozen_deposits = + RPC_service.get_service + ~description: + "Returns the amount (in mutez) frozen as a deposit at the time the \ + staking rights for the current cycle where computed." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "frozen_deposits") + + let unstaked_frozen_deposits = + RPC_service.get_service + ~description: + "Returns, for each cycle, the sum of unstaked-but-frozen deposits for \ + this cycle. Cycles go from the last unslashable cycle to the current \ + cycle." + ~query:RPC_query.empty + ~output:(Data_encoding.list deposit_per_cycle_encoding) + RPC_path.(path / "unstaked_frozen_deposits") + + let staking_balance = + RPC_service.get_service + ~description: + "Returns the total amount of tokens (in mutez) delegated to a given \ + delegate. This includes the balances of all the contracts that \ + delegate to it, but also the balance of the delegate itself, its \ + frozen deposits, and its frozen bonds." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "staking_balance") + + let frozen_deposits_limit = + RPC_service.get_service + ~description: + "Returns the frozen deposits limit for the given delegate or none if \ + no limit is set." + ~query:RPC_query.empty + ~output:(Data_encoding.option Tez.encoding) + RPC_path.(path / "frozen_deposits_limit") + + let delegated_contracts = + RPC_service.get_service + ~description: + "Returns the list of contracts that delegate to a given delegate." + ~query:RPC_query.empty + ~output:(list Contract.encoding) + RPC_path.(path / "delegated_contracts") + + let total_delegated_stake = + RPC_service.get_service + ~description: + "Returns the sum (in mutez) of all tokens staked by the delegators of \ + a given delegate. This excludes the delegate's own staked tokens." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "total_delegated_stake") + + let staking_denominator = + RPC_service.get_service + ~description: + "Returns an abstract representation of the total delegated stake." + ~query:RPC_query.empty + ~output:Staking_pseudotoken.For_RPC.encoding + RPC_path.(path / "staking_denominator") + + let delegated_balance = + RPC_service.get_service + ~description: + "Returns the sum (in mutez) of all balances of all the contracts that \ + delegate to a given delegate. This excludes the delegate's own \ + balance, its frozen deposits and its frozen bonds." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "delegated_balance") + + let min_delegated_in_current_cycle = + RPC_service.get_service + ~description: + "Returns the minimum of delegated tez (in mutez) over the current \ + cycle and the block level where this value was last updated (* Level \ + is `None` when decoding values from protocol O)." + ~query:RPC_query.empty + ~output:min_delegated_in_current_cycle_encoding + RPC_path.(path / "min_delegated_in_current_cycle") + + let deactivated = + RPC_service.get_service + ~description: + "Tells whether the delegate is currently tagged as deactivated or not." + ~query:RPC_query.empty + ~output:bool + RPC_path.(path / "deactivated") + + let grace_period = + RPC_service.get_service + ~description: + "Returns the cycle by the end of which the delegate might be \ + deactivated if she fails to execute any delegate action. A \ + deactivated delegate might be reactivated (without loosing any stake) \ + by simply re-registering as a delegate. For deactivated delegates, \ + this value contains the cycle at which they were deactivated." + ~query:RPC_query.empty + ~output:Cycle.encoding + RPC_path.(path / "grace_period") + + let current_voting_power = + RPC_service.get_service + ~description: + "The voting power of a given delegate, as computed from its current \ + stake." + ~query:RPC_query.empty + ~output:Data_encoding.int64 + RPC_path.(path / "current_voting_power") + + let voting_power = + RPC_service.get_service + ~description:"The voting power in the vote listings for a given delegate." + ~query:RPC_query.empty + ~output:Data_encoding.int64 + RPC_path.(path / "voting_power") + + let current_baking_power = + RPC_service.get_service + ~description: + "The baking power of a delegate, as computed from its current stake. \ + This value is not used for computing baking rights but only reflects \ + the baking power that the delegate would have if the cycle ended at \ + the current block." + ~query:RPC_query.empty + ~output:Data_encoding.int64 + RPC_path.(path / "current_baking_power") + + let voting_info = + RPC_service.get_service + ~description: + "Returns the delegate info (e.g. voting power) found in the listings \ + of the current voting period." + ~query:RPC_query.empty + ~output:Vote.delegate_info_encoding + RPC_path.(path / "voting_info") + + let consensus_key = + RPC_service.get_service + ~description: + "The active consensus key for a given delegate and the pending \ + consensus keys." + ~query:RPC_query.empty + ~output:consensus_key_info_encoding + RPC_path.(path / "consensus_key") + + let participation = + RPC_service.get_service + ~description: + "Returns cycle and level participation information. In particular this \ + indicates, in the field 'expected_cycle_activity', the number of \ + slots the delegate is expected to have in the cycle based on its \ + active stake. The field 'minimal_cycle_activity' indicates the \ + minimal attesting slots in the cycle required to get attesting \ + rewards. It is computed based on 'expected_cycle_activity. The fields \ + 'missed_slots' and 'missed_levels' indicate the number of missed \ + attesting slots and missed levels (for attesting) in the cycle so \ + far. 'missed_slots' indicates the number of missed attesting slots in \ + the cycle so far. The field 'remaining_allowed_missed_slots' \ + indicates the remaining amount of attesting slots that can be missed \ + in the cycle before forfeiting the rewards. Finally, \ + 'expected_attesting_rewards' indicates the attesting rewards that \ + will be distributed at the end of the cycle if activity at that point \ + will be greater than the minimal required; if the activity is already \ + known to be below the required minimum, then the rewards are zero." + ~query:RPC_query.empty + ~output:participation_info_encoding + RPC_path.(path / "participation") + + let active_staking_parameters = + RPC_service.get_service + ~description: + "Returns the currently active staking parameters for the given \ + delegate." + ~query:RPC_query.empty + ~output:Staking_parameters_repr.encoding + RPC_path.(path / "active_staking_parameters") + + let pending_staking_parameters = + RPC_service.get_service + ~description: + "Returns the pending values for the given delegate's staking \ + parameters." + ~query:RPC_query.empty + ~output:(list pending_staking_parameters_encoding) + RPC_path.(path / "pending_staking_parameters") + + let pending_denunciations = + RPC_service.get_service + ~description:"Returns the pending denunciations for the given delegate." + ~query:RPC_query.empty + ~output:(list Denunciations_repr.item_encoding) + RPC_path.(path / "denunciations") + + let estimated_shared_pending_slashed_amount = + RPC_service.get_service + ~description: + "Returns the estimated shared pending slashed amount (in mutez) of a \ + given delegate." + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "estimated_shared_pending_slashed_amount") +end + +let check_delegate_registered ctxt pkh = + let open Lwt_result_syntax in + let*! is_registered = Delegate.registered ctxt pkh in + match is_registered with + | true -> return_unit + | false -> tzfail (Not_registered pkh) + +let register () = + let open Services_registration in + let open Lwt_result_syntax in + register0 ~chunked:true S.list_delegate (fun ctxt q () -> + let*! delegates = Delegate.list ctxt in + let* delegates = + match q with + | {active = true; inactive = false; _} -> + List.filter_es + (fun pkh -> + let+ deactivated = Delegate.deactivated ctxt pkh in + not deactivated) + delegates + | {active = false; inactive = true; _} -> + List.filter_es (fun pkh -> Delegate.deactivated ctxt pkh) delegates + | {active = false; inactive = false; _} + (* This case is counter-intuitive, but it represents the default behavior, when no arguments are given *) + | {active = true; inactive = true; _} -> + return delegates + in + let minimal_stake = Constants.minimal_stake ctxt in + match q with + | {with_minimal_stake = true; without_minimal_stake = false; _} -> + List.filter_es + (fun pkh -> + let+ staking_balance = + Delegate.For_RPC.staking_balance ctxt pkh + in + Tez.(staking_balance >= minimal_stake)) + delegates + | {with_minimal_stake = false; without_minimal_stake = true; _} -> + List.filter_es + (fun pkh -> + let+ staking_balance = + Delegate.For_RPC.staking_balance ctxt pkh + in + Tez.(staking_balance < minimal_stake)) + delegates + | {with_minimal_stake = true; without_minimal_stake = true; _} + | {with_minimal_stake = false; without_minimal_stake = false; _} -> + return delegates) ; + register1 ~chunked:false S.info (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + let* full_balance = Delegate.For_RPC.full_balance ctxt pkh in + let* current_frozen_deposits = + Delegate.current_frozen_deposits ctxt pkh + in + let* frozen_deposits = Delegate.initial_frozen_deposits ctxt pkh in + let* staking_balance = Delegate.For_RPC.staking_balance ctxt pkh in + let* frozen_deposits_limit = Delegate.frozen_deposits_limit ctxt pkh in + let*! delegated_contracts = Delegate.delegated_contracts ctxt pkh in + let* delegated_balance = Delegate.For_RPC.delegated_balance ctxt pkh in + let* min_delegated_in_current_cycle = + Delegate.For_RPC.min_delegated_in_current_cycle ctxt pkh + in + let* total_delegated_stake = + Staking_pseudotokens.For_RPC.get_frozen_deposits_staked_tez + ctxt + ~delegate:pkh + in + let* staking_denominator = + Staking_pseudotokens.For_RPC.get_frozen_deposits_pseudotokens + ctxt + ~delegate:pkh + in + let* deactivated = Delegate.deactivated ctxt pkh in + let* grace_period = Delegate.last_cycle_before_deactivation ctxt pkh in + let*! pending_denunciations = + Delegate.For_RPC.has_pending_denunciations ctxt pkh + in + let* voting_info = Vote.get_delegate_info ctxt pkh in + let* consensus_key = Delegate.Consensus_key.active_pubkey ctxt pkh in + let+ pendings = Delegate.Consensus_key.pending_updates ctxt pkh in + let pending_consensus_keys = + List.map (fun (cycle, pkh, _) -> (cycle, pkh)) pendings + in + { + full_balance; + current_frozen_deposits; + frozen_deposits; + staking_balance; + frozen_deposits_limit; + delegated_contracts; + delegated_balance; + min_delegated_in_current_cycle; + total_delegated_stake; + staking_denominator; + deactivated; + grace_period; + pending_denunciations; + voting_info; + active_consensus_key = consensus_key.consensus_pkh; + pending_consensus_keys; + }) ; + register1 ~chunked:false S.full_balance (fun ctxt pkh () () -> + let* () = + trace + (Balance_rpc_non_delegate pkh) + (check_delegate_registered ctxt pkh) + in + Delegate.For_RPC.full_balance ctxt pkh) ; + register1 ~chunked:false S.current_frozen_deposits (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.current_frozen_deposits ctxt pkh) ; + register1 ~chunked:false S.frozen_deposits (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.initial_frozen_deposits ctxt pkh) ; + register1 ~chunked:false S.unstaked_frozen_deposits (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + let ctxt_cycle = (Alpha_context.Level.current ctxt).cycle in + let last_unslashable_cycle = + Option.value ~default:Cycle.root + @@ Cycle.sub + ctxt_cycle + (Constants.slashable_deposits_period ctxt + + Constants_repr.max_slashing_period) + in + let cycles = Cycle.(last_unslashable_cycle ---> ctxt_cycle) in + let* requests = + List.map_es + (fun cycle -> + let* deposit = Unstaked_frozen_deposits.balance ctxt pkh cycle in + return (cycle, deposit)) + cycles + in + let* slashed_requests = + Alpha_context.Unstake_requests.For_RPC + .apply_slash_to_unstaked_unfinalizable + ctxt + ~delegate:pkh + ~requests + in + List.map_es + (fun (cycle, deposit) -> return {cycle; deposit}) + slashed_requests) ; + register1 ~chunked:false S.staking_balance (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.For_RPC.staking_balance ctxt pkh) ; + register1 ~chunked:false S.frozen_deposits_limit (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.frozen_deposits_limit ctxt pkh) ; + register1 ~chunked:true S.delegated_contracts (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + let*! contracts = Delegate.delegated_contracts ctxt pkh in + return contracts) ; + register1 ~chunked:false S.delegated_balance (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.For_RPC.delegated_balance ctxt pkh) ; + register1 + ~chunked:false + S.min_delegated_in_current_cycle + (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.For_RPC.min_delegated_in_current_cycle ctxt pkh) ; + register1 ~chunked:false S.total_delegated_stake (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Staking_pseudotokens.For_RPC.get_frozen_deposits_staked_tez + ctxt + ~delegate:pkh) ; + register1 ~chunked:false S.staking_denominator (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Staking_pseudotokens.For_RPC.get_frozen_deposits_pseudotokens + ctxt + ~delegate:pkh) ; + register1 ~chunked:false S.deactivated (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.deactivated ctxt pkh) ; + register1 ~chunked:false S.grace_period (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.last_cycle_before_deactivation ctxt pkh) ; + register1 ~chunked:false S.current_voting_power (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Vote.get_current_voting_power_free ctxt pkh) ; + register1 ~chunked:false S.voting_power (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Vote.get_voting_power_free ctxt pkh) ; + register1 ~chunked:false S.current_baking_power (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Stake_distribution.For_RPC.delegate_current_baking_power ctxt pkh) ; + register1 ~chunked:false S.voting_info (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Vote.get_delegate_info ctxt pkh) ; + register1 ~chunked:false S.consensus_key (fun ctxt pkh () () -> + let* { + consensus_pk = consensus_key_pk; + consensus_pkh = consensus_key_pkh; + _; + } = + Delegate.Consensus_key.active_pubkey ctxt pkh + in + let* pendings = Delegate.Consensus_key.pending_updates ctxt pkh in + let pendings = + List.map + (fun (cycle, consensus_key_pkh, consensus_key_pk) -> + (cycle, {consensus_key_pk; consensus_key_pkh})) + pendings + in + return {active = {consensus_key_pk; consensus_key_pkh}; pendings}) ; + register1 ~chunked:false S.participation (fun ctxt pkh () () -> + let* () = check_delegate_registered ctxt pkh in + Delegate.For_RPC.participation_info ctxt pkh) ; + register1 ~chunked:false S.active_staking_parameters (fun ctxt pkh () () -> + Delegate.Staking_parameters.of_delegate ctxt pkh) ; + register1 ~chunked:false S.pending_staking_parameters (fun ctxt pkh () () -> + Delegate.Staking_parameters.pending_updates ctxt pkh) ; + register1 ~chunked:false S.pending_denunciations (fun ctxt pkh () () -> + Delegate.For_RPC.pending_denunciations ctxt pkh) ; + register1 + ~chunked:false + S.estimated_shared_pending_slashed_amount + (fun ctxt delegate () () -> + let* () = check_delegate_registered ctxt delegate in + Delegate.For_RPC.get_estimated_shared_pending_slashed_amount ctxt delegate) + +let list ctxt block ?(active = true) ?(inactive = false) + ?(with_minimal_stake = true) ?(without_minimal_stake = false) () = + RPC_context.make_call0 + S.list_delegate + ctxt + block + {active; inactive; with_minimal_stake; without_minimal_stake} + () + +let info ctxt block pkh = RPC_context.make_call1 S.info ctxt block pkh () () + +let full_balance ctxt block pkh = + RPC_context.make_call1 S.full_balance ctxt block pkh () () + +let current_frozen_deposits ctxt block pkh = + RPC_context.make_call1 S.current_frozen_deposits ctxt block pkh () () + +let frozen_deposits ctxt block pkh = + RPC_context.make_call1 S.frozen_deposits ctxt block pkh () () + +let unstaked_frozen_deposits ctxt block pkh = + RPC_context.make_call1 S.unstaked_frozen_deposits ctxt block pkh () () + +let staking_balance ctxt block pkh = + RPC_context.make_call1 S.staking_balance ctxt block pkh () () + +let frozen_deposits_limit ctxt block pkh = + RPC_context.make_call1 S.frozen_deposits_limit ctxt block pkh () () + +let delegated_contracts ctxt block pkh = + RPC_context.make_call1 S.delegated_contracts ctxt block pkh () () + +let delegated_balance ctxt block pkh = + RPC_context.make_call1 S.delegated_balance ctxt block pkh () () + +let total_delegated_stake ctxt block pkh = + RPC_context.make_call1 S.total_delegated_stake ctxt block pkh () () + +let staking_denominator ctxt block pkh = + RPC_context.make_call1 S.staking_denominator ctxt block pkh () () + +let deactivated ctxt block pkh = + RPC_context.make_call1 S.deactivated ctxt block pkh () () + +let grace_period ctxt block pkh = + RPC_context.make_call1 S.grace_period ctxt block pkh () () + +let voting_power ctxt block pkh = + RPC_context.make_call1 S.voting_power ctxt block pkh () () + +let current_voting_power ctxt block pkh = + RPC_context.make_call1 S.current_voting_power ctxt block pkh () () + +let current_baking_power ctxt block pkh = + RPC_context.make_call1 S.current_baking_power ctxt block pkh () () + +let voting_info ctxt block pkh = + RPC_context.make_call1 S.voting_info ctxt block pkh () () + +let consensus_key ctxt block pkh = + RPC_context.make_call1 S.consensus_key ctxt block pkh () () + +let participation ctxt block pkh = + RPC_context.make_call1 S.participation ctxt block pkh () () + +let active_staking_parameters ctxt block pkh = + RPC_context.make_call1 S.active_staking_parameters ctxt block pkh () () + +let pending_staking_parameters ctxt block pkh = + RPC_context.make_call1 S.pending_staking_parameters ctxt block pkh () () + +let pending_denunciations ctxt block pkh = + RPC_context.make_call1 S.pending_denunciations ctxt block pkh () () + +let estimated_shared_pending_slashed_amount ctxt block pkh = + RPC_context.make_call1 + S.estimated_shared_pending_slashed_amount + ctxt + block + pkh + () + () diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_services.mli b/src/proto_020_PsParisC/lib_protocol/delegate_services.mli new file mode 100644 index 000000000000..60b8df658ecf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_services.mli @@ -0,0 +1,204 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines RPC services to access the information associated to + delegates (who they are, their delegators, their different kinds of balances, their activity, etc.). +*) + +open Alpha_context + +type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t + +val list : + 'a #RPC_context.simple -> + 'a -> + ?active:bool -> + ?inactive:bool -> + ?with_minimal_stake:bool -> + ?without_minimal_stake:bool -> + unit -> + Signature.Public_key_hash.t list shell_tzresult Lwt.t + +type consensus_key = { + consensus_key_pkh : Signature.Public_key_hash.t; + consensus_key_pk : Signature.Public_key.t; +} + +type consensus_keys_info = { + active : consensus_key; + pendings : (Cycle.t * consensus_key) list; +} + +type info = { + full_balance : Tez.t; (** Balance + Frozen balance *) + current_frozen_deposits : Tez.t; + frozen_deposits : Tez.t; + staking_balance : Tez.t; + frozen_deposits_limit : Tez.t option; + delegated_contracts : Contract.t list; + delegated_balance : Tez.t; + min_delegated_in_current_cycle : Tez.t * Level_repr.t option; + total_delegated_stake : Tez.t; + staking_denominator : Staking_pseudotoken.t; + deactivated : bool; + grace_period : Cycle.t; + pending_denunciations : bool; + voting_info : Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; +} + +type deposit_per_cycle = {cycle : Cycle.t; deposit : Tez.t} + +val deposit_per_cycle_encoding : deposit_per_cycle Data_encoding.t + +val info_encoding : info Data_encoding.t + +val info : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + info shell_tzresult Lwt.t + +val full_balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val current_frozen_deposits : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val frozen_deposits : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val unstaked_frozen_deposits : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + deposit_per_cycle list shell_tzresult Lwt.t + +val staking_balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val frozen_deposits_limit : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t option shell_tzresult Lwt.t + +val delegated_contracts : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Contract.t list shell_tzresult Lwt.t + +val delegated_balance : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Tez.t shell_tzresult Lwt.t + +val total_delegated_stake : + 'a #RPC_context.simple -> 'a -> public_key_hash -> Tez.t shell_tzresult Lwt.t + +val staking_denominator : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + Staking_pseudotoken.t shell_tzresult Lwt.t + +val deactivated : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + bool shell_tzresult Lwt.t + +val grace_period : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + Cycle.t shell_tzresult Lwt.t + +val current_voting_power : + 'a #RPC_context.simple -> 'a -> public_key_hash -> int64 shell_tzresult Lwt.t + +val voting_power : + 'a #RPC_context.simple -> 'a -> public_key_hash -> int64 shell_tzresult Lwt.t + +val current_baking_power : + 'a #RPC_context.simple -> 'a -> public_key_hash -> int64 shell_tzresult Lwt.t + +val voting_info : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + Vote.delegate_info shell_tzresult Lwt.t + +val consensus_key : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + consensus_keys_info shell_tzresult Lwt.t + +val participation : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + Delegate.For_RPC.participation_info shell_tzresult Lwt.t + +val active_staking_parameters : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + Staking_parameters_repr.t shell_tzresult Lwt.t + +val pending_staking_parameters : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + (Cycle.t * Staking_parameters_repr.t) list shell_tzresult Lwt.t + +val pending_denunciations : + 'a #RPC_context.simple -> + 'a -> + public_key_hash -> + Denunciations_repr.t shell_tzresult Lwt.t + +val estimated_shared_pending_slashed_amount : + 'a #RPC_context.simple -> 'a -> public_key_hash -> Tez.t shell_tzresult Lwt.t + +val register : unit -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.ml b/src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.ml new file mode 100644 index 000000000000..59ceba6a2916 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.ml @@ -0,0 +1,613 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type reward_and_burn = {reward : Tez_repr.t; amount_to_burn : Tez_repr.t} + +type punishing_amounts = { + staked : reward_and_burn; + unstaked : (Cycle_repr.t * reward_and_burn) list; +} + +let record_denunciation ctxt ~operation_hash + (misbehaviour : Misbehaviour_repr.t) delegate ~rewarded = + let open Lwt_result_syntax in + let*! ctxt = Forbidden_delegates_storage.forbid ctxt delegate in + Pending_denunciations_storage.add_denunciation + ctxt + ~misbehaving_delegate:delegate + operation_hash + ~rewarded_delegate:rewarded + misbehaviour + +let punish_double_signing ctxt ~operation_hash misbehaviour delegate + (level : Level_repr.t) ~rewarded = + let open Lwt_result_syntax in + let* ctxt, was_already_denounced = + Already_denounced_storage.add_denunciation + ctxt + delegate + level + misbehaviour.Misbehaviour_repr.round + misbehaviour.kind + in + if was_already_denounced then + (* This can only happen in the very specific case where a delegate + has crafted at least three attestations (respectively + preattestations) on the same level and round but with three + different slots owned by this delegate. Indeed, this makes it + possible to have two denunciations about the same delegate, + level, round, and kind, but different slots. Such denunciations + are considered identical by {!Already_denounced_storage}, which + is good because the delegate shouldn't get slashed twice on the + same level, round, and kind. However, {!Validate}'s conflict + handler identifies denunciations via their slot rather than + delegate for technical reasons (because the slot is readily + available whereas retrieving the delegate requires a call to + {!Delegate_sampler.slot_owner} which is in Lwt and thus + incompatible with some signatures). Therefore, if these + denunciations (which differ only in their slots) are both + included in the same block, then they will both be successfully + validated, and then [was_already_denounced] will be [true] + during the application of the second one. + + In this unlikely scenario, we simply ignore the redundant + denunciation silently. Returning an error or raising an + exception here would cause the whole block application to fail, + which we don't want. *) + return ctxt + else record_denunciation ctxt ~operation_hash misbehaviour delegate ~rewarded + +(* Misbehaviour Map: orders denunciations for application. + See {!Misbehaviour_repr.compare} for the order on misbehaviours: + - by increasing level, then increasing round, then kind, ignoring the slot + - for the kind: double baking > double attesting > double preattesting *) +module MisMap = Map.Make (Misbehaviour_repr) + +let compute_punishing_amount slashing_percentage frozen_deposits = + let punish_value = + Tez_repr.mul_percentage + ~rounding:`Down + frozen_deposits.Deposits_repr.initial_amount + slashing_percentage + in + Tez_repr.min punish_value frozen_deposits.Deposits_repr.current_amount + +let split_reward_and_burn punishing_amount global_limit_of_staking_over_baking = + let open Result_syntax in + let global_limit_of_staking_over_baking_plus_two = + Int64.add (Int64.of_int global_limit_of_staking_over_baking) 2L + in + let* reward = + Tez_repr.(punishing_amount /? global_limit_of_staking_over_baking_plus_two) + in + let+ amount_to_burn = Tez_repr.(punishing_amount -? reward) in + {reward; amount_to_burn} + +let compute_reward_and_burn slashing_percentage frozen_deposits + global_limit_of_staking_over_baking = + let punishing_amount = + compute_punishing_amount slashing_percentage frozen_deposits + in + split_reward_and_burn punishing_amount global_limit_of_staking_over_baking + +let get_initial_frozen_deposits_of_misbehaviour_cycle ~current_cycle + ~misbehaviour_cycle = + let previous_cycle = + match Cycle_repr.pred current_cycle with + | None -> current_cycle + | Some previous_cycle -> previous_cycle + in + if Cycle_repr.equal current_cycle misbehaviour_cycle then + Delegate_storage.initial_frozen_deposits + else if Cycle_repr.equal previous_cycle misbehaviour_cycle then + Delegate_storage.initial_frozen_deposits_of_previous_cycle + else fun (_ : Raw_context.t) (_ : Signature.public_key_hash) -> + (* Denunciation applied too late. + We could assert false, but we can also be permissive + while keeping the same invariants. *) + return Tez_repr.zero + +let update_block_denunciations_map_with delegate denunciations initial_block_map + = + List.fold_left + (fun block_map denunciation -> + MisMap.update + denunciation.Denunciations_repr.misbehaviour + (function + | None -> + Some + (Signature.Public_key_hash.Map.singleton delegate denunciation) + | Some map -> + Some + (Signature.Public_key_hash.Map.update + delegate + (function + | None -> Some denunciation | Some old_d -> Some old_d) + map)) + block_map) + initial_block_map + denunciations + +(* Split denunciations into two groups: those to be applied, and those to be delayed. *) +let get_applicable_and_remaining_denunciations ctxt current_cycle = + Storage.Pending_denunciations.fold + ctxt + ~order:`Undefined + ~init:(MisMap.empty, []) + ~f:(fun delegate denunciations acc -> + let block_map, remaining_denunciations = acc in + (* Since the [max_slashing_period] is 2, and we want to apply denunciations at the + end of this period, we "delay" the current cycle's misbehaviour's denunciations, + while we apply the older denunciations. + Indeed, we apply denunciations in the cycle following the misbehaviour, so that + the time between the misbehaviour and the slashing is at most + [max_slashing_period = 2] cycles. *) + let denunciations_to_apply, denunciations_to_delay = + if not (Constants_storage.adaptive_issuance_ns_enable ctxt) then + (denunciations, []) + else + List.partition + (fun denunciation -> + let level = denunciation.Denunciations_repr.misbehaviour.level in + let misb_cycle = + (Level_repr.level_from_raw + ~cycle_eras:(Raw_context.cycle_eras ctxt) + level) + .cycle + in + Cycle_repr.(misb_cycle < current_cycle)) + denunciations + in + let new_block_map = + update_block_denunciations_map_with + delegate + denunciations_to_apply + block_map + in + let new_remaining_denunciations = + (delegate, denunciations_to_delay) :: remaining_denunciations + in + Lwt.return (new_block_map, new_remaining_denunciations)) + +let apply_block_denunciations ctxt current_cycle block_denunciations_map = + let slashable_deposits_period = + Constants_storage.slashable_deposits_period ctxt + in + let open Lwt_result_syntax in + let global_limit_of_staking_over_baking = + Constants_storage.adaptive_issuance_global_limit_of_staking_over_baking ctxt + in + MisMap.fold_es + (fun ({Misbehaviour_repr.level = raw_level; round = _; kind; _} as miskey) + denunciations_map + acc -> + let ctxt, balance_updates = acc in + let level = + Level_repr.level_from_raw + ~cycle_eras:(Raw_context.cycle_eras ctxt) + raw_level + in + let misbehaviour_cycle = level.cycle in + let denunciations = + Signature.Public_key_hash.Map.bindings denunciations_map + in + let denounced = List.map fst denunciations in + let* ctxt, slashing_percentage = + Slash_percentage.get ctxt ~kind ~level denounced + in + let+ ctxt, balance_updates = + List.fold_left_es + (fun (ctxt, balance_updates) + ( delegate, + Denunciations_repr.{operation_hash; rewarded; misbehaviour} ) -> + assert ( + Compare.Int.equal + (* This compare ignores the slot *) + (Misbehaviour_repr.compare miskey misbehaviour) + 0) ; + (* Validate ensures that [denunciations] contains [delegate] at most once *) + let delegate_contract = Contract_repr.Implicit delegate in + (* Oxford values *) + let* slash_history_opt_o = + Storage.Contract.Slashed_deposits__Oxford.find + ctxt + delegate_contract + in + let slash_history_o = + Option.value slash_history_opt_o ~default:[] + |> List.map (fun (a, b) -> (a, Percentage.convert_from_o_to_p b)) + in + + let* slash_history_opt = + Storage.Slashed_deposits.find ctxt delegate + in + let slash_history = Option.value slash_history_opt ~default:[] in + + (* Concatenate both, Oxford first *) + let slash_history = + List.fold_left + (fun acc (cycle, percentage) -> + Storage.Slashed_deposits_history.add cycle percentage acc) + slash_history_o + slash_history + in + + let*! ctxt = + Storage.Contract.Slashed_deposits__Oxford.remove + ctxt + delegate_contract + in + + let previous_total_slashing_percentage = + Storage.Slashed_deposits_history.get level.cycle slash_history + in + let slash_history = + Storage.Slashed_deposits_history.add + level.cycle + slashing_percentage + slash_history + in + let*! ctxt = + Storage.Slashed_deposits.add ctxt delegate slash_history + in + let new_total_slashing_percentage = + Storage.Slashed_deposits_history.get level.cycle slash_history + in + (* We do not slash above 100%: if the slashing percentage would + make the total sum of the slashing history above 100%, we rectify + it to reach exactly 100%. This also means that subsequent slashes + are effectively ignored (set to 0%) *) + let slashing_percentage = + Percentage.sub_bounded + new_total_slashing_percentage + previous_total_slashing_percentage + in + let* frozen_deposits = + let* initial_amount = + get_initial_frozen_deposits_of_misbehaviour_cycle + ~current_cycle + ~misbehaviour_cycle + ctxt + delegate + in + let* current_amount = + Delegate_storage.current_frozen_deposits ctxt delegate + in + return Deposits_repr.{initial_amount; current_amount} + in + let punishing_amount = + compute_punishing_amount slashing_percentage frozen_deposits + (* Ensures: [punishing_amount <= current_amount] + + where [current_amount = frozen_deposits.current_amount + = own_frozen + staked_frozen] + *) + in + let* {baker_part; stakers_part = _} = + Shared_stake.share + ~rounding:`Towards_baker + ctxt + delegate + punishing_amount + (* Ensures: + + - [baker_part + stakers_part = punishing_amount] + + - [baker_part / punishing_amount = own_frozen / (own_frozen + allowed_staked_frozen)] + + where [allowed_staked_frozen] is [staked_frozen] + capped by the delegate's [limit_of_staking_over_baking], + which notably means that [allowed_staked_frozen <= staked_frozen] + i.e. [own_frozen + allowed_staked_frozen <= own_frozen + staked_frozen = current_amount] + + Combining all of the above: + + [baker_part / punishing_amount >= own_frozen / current_amount] + + [(punishing_amount - stakers_part) / punishing_amount >= (current_amount - staked_frozen) / current_amount] + + [1 - (stakers_part / punishing_amount) >= 1 - (staked_frozen / current_amount)] + + [stakers_part / punishing_amount <= staked_frozen / current_amount] + + [stakers_part <= staked_frozen * punishing_amount / current_amount] + + Moreover, we know from above that [punishing_amount <= current_amount] so: + + [stakers_part <= staked_frozen] + *) + in + let* full_staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + let own_frozen = + Full_staking_balance_repr.own_frozen full_staking_balance + in + let actual_baker_part = Tez_repr.min baker_part own_frozen in + let*? actual_stakers_part = + Tez_repr.(punishing_amount -? actual_baker_part) + in + (* To avoid underflows, we need to guarantee that: + - [actual_baker_part <= own_frozen] and + - [actual_stakers_part <= staked_frozen] + + The [min] ensures that [actual_baker_part <= own_frozen]. + + For [actual_stakers_part], let's examine two cases + based on the [min]: + + - Case 1: [actual_baker_part = baker_part] + + [actual_stakers_part = punishing_amount - actual_baker_part + = punishing_amount - baker_part + = stakers_part + <= staked_frozen] as proven above + + - Case 2: [actual_baker_part = own_frozen] + + [actual_stakers_part = punishing_amount - actual_baker_part + = punishing_amount - own_frozen + <= current_amount - own_frozen + = own_frozen + staked_frozen - own_frozen + = staked_frozen] + *) + let*? {amount_to_burn = to_burn_baker; reward = to_reward_baker} = + split_reward_and_burn + actual_baker_part + global_limit_of_staking_over_baking + in + let*? {amount_to_burn = to_burn_stakers; reward = to_reward_stakers} + = + split_reward_and_burn + actual_stakers_part + global_limit_of_staking_over_baking + in + let giver_baker = + `Frozen_deposits (Frozen_staker_repr.baker delegate) + in + let giver_stakers = + `Frozen_deposits + (Frozen_staker_repr.shared_between_stakers ~delegate) + in + let init_to_burn = + [(giver_baker, to_burn_baker); (giver_stakers, to_burn_stakers)] + in + let init_to_reward = + [ + (giver_baker, to_reward_baker); + (giver_stakers, to_reward_stakers); + ] + in + let* to_burn, to_reward = + let oldest_slashable_cycle = + Cycle_repr.sub misbehaviour_cycle slashable_deposits_period + |> Option.value ~default:Cycle_repr.root + in + let slashable_cycles = + Cycle_repr.(oldest_slashable_cycle ---> misbehaviour_cycle) + in + List.fold_left_es + (fun (to_burn, to_reward) cycle -> + let* frozen_deposits = + Unstaked_frozen_deposits_storage.get ctxt delegate cycle + in + let*? {amount_to_burn; reward} = + compute_reward_and_burn + slashing_percentage + frozen_deposits + global_limit_of_staking_over_baking + in + let giver = + `Unstaked_frozen_deposits + (Unstaked_frozen_staker_repr.Shared delegate, cycle) + in + return + ( (giver, amount_to_burn) :: to_burn, + (giver, reward) :: to_reward )) + (init_to_burn, init_to_reward) + slashable_cycles + in + let origin = Receipt_repr.Delayed_operation {operation_hash} in + let* ctxt, punish_balance_updates = + Token.transfer_n ctxt ~origin to_burn `Double_signing_punishments + in + let+ ctxt, reward_balance_updates = + Token.transfer_n + ctxt + ~origin + to_reward + (`Contract (Contract_repr.Implicit rewarded)) + in + ( ctxt, + punish_balance_updates @ reward_balance_updates @ balance_updates + )) + (ctxt, balance_updates) + denunciations + in + (ctxt, balance_updates)) + block_denunciations_map + (ctxt, []) + +let apply_denunciations ctxt = + let open Lwt_result_syntax in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let*! applicable_denunciations_map, remaining_denunciations = + get_applicable_and_remaining_denunciations ctxt current_cycle + in + let* ctxt, balance_updates = + apply_block_denunciations ctxt current_cycle applicable_denunciations_map + in + return (ctxt, balance_updates, remaining_denunciations) + +let apply_and_clear_denunciations ctxt = + let open Lwt_result_syntax in + let* ctxt, balance_updates, remaining_denunciations = + apply_denunciations ctxt + in + (* Updates the storage to only contain the remaining denunciations *) + let*! ctxt = Pending_denunciations_storage.clear ctxt in + let*! ctxt = + List.fold_left_s + (fun ctxt (delegate, current_cycle_denunciations) -> + match current_cycle_denunciations with + | [] -> Lwt.return ctxt + | _ -> + Pending_denunciations_storage.set_denunciations + ctxt + delegate + current_cycle_denunciations) + ctxt + remaining_denunciations + in + return (ctxt, balance_updates) + +module For_RPC = struct + let get_pending_misbehaviour_map ctxt = + Storage.Pending_denunciations.fold + ctxt + ~order:`Undefined + ~init:MisMap.empty + ~f:(fun delegate denunciations block_map -> + let new_block_map = + update_block_denunciations_map_with delegate denunciations block_map + in + Lwt.return new_block_map) + + let get_estimated_punished_amount ctxt delegate = + let open Lwt_result_syntax in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let* denunciations = Storage.Pending_denunciations.find ctxt delegate in + match denunciations with + | None | Some [] -> return Tez_repr.zero + | Some denunciations -> + let*! pending_misbehaviour_map = get_pending_misbehaviour_map ctxt in + List.fold_left_es + (fun estimated_punishing_amount denunciation -> + let ({Misbehaviour_repr.level = raw_level; kind; _} as + misbehaviour_key) = + denunciation.Denunciations_repr.misbehaviour + in + match MisMap.find misbehaviour_key pending_misbehaviour_map with + | None -> + (* Should not happen as [pending_misbehaviour_map] has been created + using the bindings of [Storage.Pending_denunciations] and + [denunciation] belongs to [Storage.Pending_denunciations]. *) + return estimated_punishing_amount + | Some denunciations -> + let level = + Level_repr.level_from_raw + ~cycle_eras:(Raw_context.cycle_eras ctxt) + raw_level + in + let denounced_pkhs = + List.map + fst + (Signature.Public_key_hash.Map.bindings denunciations) + in + let* ctxt, slashing_percentage = + Slash_percentage.get ctxt ~kind ~level denounced_pkhs + in + let misbehaviour_cycle = level.cycle in + let* frozen_deposits = + let* initial_amount = + get_initial_frozen_deposits_of_misbehaviour_cycle + ~current_cycle + ~misbehaviour_cycle + ctxt + delegate + in + let* current_amount = + Delegate_storage.current_frozen_deposits ctxt delegate + in + return {Deposits_repr.initial_amount; current_amount} + in + let punishing_amount = + compute_punishing_amount slashing_percentage frozen_deposits + in + let new_estimated_punishing_amount = + Tez_repr.(punishing_amount +? estimated_punishing_amount) + in + Lwt.return new_estimated_punishing_amount) + Tez_repr.zero + denunciations + + let get_estimated_punished_share ctxt delegate = + let open Lwt_result_syntax in + let* estimated_punished_amount = + get_estimated_punished_amount ctxt delegate + in + Shared_stake.share + ~rounding:`Towards_baker + ctxt + delegate + estimated_punished_amount + + let get_estimated_shared_pending_slashed_amount ctxt delegate = + let open Lwt_result_syntax in + let* {baker_part; stakers_part} = + get_estimated_punished_share ctxt delegate + in + Lwt.return Tez_repr.(baker_part +? stakers_part) + + let get_delegate_estimated_own_pending_slashed_amount ctxt ~delegate = + let open Lwt_result_syntax in + let+ {baker_part; stakers_part = _} = + get_estimated_punished_share ctxt delegate + in + baker_part + + let get_estimated_own_pending_slashed_amount ctxt contract = + let open Lwt_result_syntax in + let* delegate_opt = Contract_delegate_storage.find ctxt contract in + match delegate_opt with + | None -> return Tez_repr.zero + | Some delegate -> + if Contract_repr.(equal (Contract_repr.Implicit delegate) contract) then + get_delegate_estimated_own_pending_slashed_amount ctxt ~delegate + else + let* {baker_part = _; stakers_part} = + get_estimated_punished_share ctxt delegate + in + let* num = + let+ staking_pseudotokens = + Staking_pseudotokens_storage.For_RPC.staking_pseudotokens_balance + ctxt + ~delegator:contract + in + Staking_pseudotoken_repr.to_int64 staking_pseudotokens + in + let* den = + let+ frozen_deposits_pseudotokens = + Staking_pseudotokens_storage.For_RPC + .get_frozen_deposits_pseudotokens + ctxt + ~delegate + in + Staking_pseudotoken_repr.to_int64 frozen_deposits_pseudotokens + in + Lwt.return (Tez_repr.mul_ratio ~rounding:`Up stakers_part ~num ~den) +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.mli b/src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.mli new file mode 100644 index 000000000000..02e0705ade68 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_slashed_deposits_storage.mli @@ -0,0 +1,102 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module handles the slashing of delegates for double signing. + + It is behind the {!Alpha_context} abstraction: some functions are + re-exported in {!Alpha_context.Delegate}. + + This module is responsible for maintaining the + {!Storage.Contract.Slashed_deposits} table. It also interacts + heavily with {!Pending_denunciations_storage}. +*) + +(** The [reward_and_burn] type embeds amounts involved when slashing a + delegate for double attesting or double baking. *) +type reward_and_burn = {reward : Tez_repr.t; amount_to_burn : Tez_repr.t} + +(** The [punishing_amounts] type embeds amounts involved when slashing a + delegate for double attesting or double baking. *) +type punishing_amounts = { + staked : reward_and_burn; + unstaked : (Cycle_repr.t * reward_and_burn) list; +} + +(** Record in the context that the given delegate is both marked for + slashing for the given misbehaviour, and forbidden from taking + part in the consensus process (baking/attesting). + + [operation_hash] corresponds to the denunciation that prompted + this punishment. The level argument is the level of the duplicate + blocks, or the level that the duplicate (pre)attestations point + to, **not** the level of the block that contains the denunciation. + + This function asserts that the delegate has not already been + denounced for the same misbehaviour at the same level. Indeed, if + this were the case, then the current denunciation operation should + have been rejected by {!Validate}. *) +val punish_double_signing : + Raw_context.t -> + operation_hash:Operation_hash.t -> + Misbehaviour_repr.t -> + Signature.Public_key_hash.t -> + Level_repr.t -> + rewarded:Signature.public_key_hash -> + Raw_context.t tzresult Lwt.t + +(** Applies pending denunciations in {!Storage.Pending_denunciations} + at the end of a cycle. The applicable denunciations are those that + point to a misbehavior whose max slashable period is ending. + (because [max_slashable_period = 2], the misbehavior must be + in the previous cycle). + + The denunciations are applied in chronological order of misbehaviour. + This function slashes the misbehaving bakers, by a proportion defined + in {!Slash_percentage}, and updates the respective + {!Storage.Contract.Slashed_deposits}. The applied denunciations are + removed from the storage. + + It returns the updated context, and all the balance updates, + which includes slashes for the bakers, the stakers, and the rewards + for the denouncers. +*) +val apply_and_clear_denunciations : + Raw_context.t -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +module For_RPC : sig + (** [get_estimated_shared_pending_slashed_amount ctxt delegate] + returns the estimated shared pending slashed amount of the given [delegate] + according to the currently available denunciations. *) + val get_estimated_shared_pending_slashed_amount : + Raw_context.t -> Signature.public_key_hash -> Tez_repr.t tzresult Lwt.t + + (** [get_estimated_own_pending_slashed_amount ctxt contract] + returns the estimated own pending slashed amount of the given [contract] + according to the currently available denunciations. *) + val get_estimated_own_pending_slashed_amount : + Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.ml b/src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.ml new file mode 100644 index 000000000000..f74aafccb109 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.ml @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let of_delegate ctxt delegate = + let open Lwt_result_syntax in + let* t = + Storage.Contract.Staking_parameters.find + ctxt + (Contract_repr.Implicit delegate) + in + match t with + | None -> return Staking_parameters_repr.default + | Some t -> return t + +let pending_updates ctxt delegate = + let contract = Contract_repr.Implicit delegate in + let activation_delay = + Constants_storage.delegate_parameters_activation_delay ctxt + in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let to_cycle = Cycle_repr.add current_cycle (activation_delay + 1) in + List.filter_map_es + (fun cycle -> + let open Lwt_result_syntax in + let+ param_opt = + Storage.Pending_staking_parameters.find (ctxt, cycle) contract + in + Option.map (fun param -> (cycle, param)) param_opt) + Cycle_repr.(current_cycle ---> to_cycle) + +let register_update ctxt delegate t = + let open Lwt_result_syntax in + let update_cycle = + let current_level = Raw_context.current_level ctxt in + let activation_delay = + Constants_storage.delegate_parameters_activation_delay ctxt + in + Cycle_repr.add current_level.cycle (activation_delay + 1) + in + let*! ctxt = + Storage.Pending_staking_parameters.add + (ctxt, update_cycle) + (Contract_repr.Implicit delegate) + t + in + return ctxt + +let activate ctxt ~new_cycle = + let open Lwt_syntax in + let* ctxt = + Storage.Pending_staking_parameters.fold + (ctxt, new_cycle) + ~order:`Undefined + ~init:ctxt + ~f:(fun delegate t ctxt -> + Storage.Contract.Staking_parameters.add ctxt delegate t) + in + Storage.Pending_staking_parameters.clear (ctxt, new_cycle) diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.mli b/src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.mli new file mode 100644 index 000000000000..6281f201f874 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_staking_parameters.mli @@ -0,0 +1,44 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val of_delegate : + Raw_context.t -> + Signature.Public_key_hash.t -> + Staking_parameters_repr.t tzresult Lwt.t + +val pending_updates : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Cycle_repr.t * Staking_parameters_repr.t) list tzresult Lwt.t + +val register_update : + Raw_context.t -> + Signature.Public_key_hash.t -> + Staking_parameters_repr.t -> + Raw_context.t tzresult Lwt.t + +(** Maintenance of staking parameters at the beginning of cycle [new_cycle]. + This function iterates on all registered delegates. *) +val activate : Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_storage.ml b/src/proto_020_PsParisC/lib_protocol/delegate_storage.ml new file mode 100644 index 000000000000..f978a854ecb8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_storage.ml @@ -0,0 +1,428 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + Some invariants: + + A contract is a delegate <=> + - it is registered (i.e. in the set {!Storage.Delegates.mem}), and + - its full staking balance is initialized. + + If a contract is a delegate then : + - it has no stake in another account, though it may (still) have unstake + requests from another contract. + + If a contract is not a delegate then: + - it has no *own* frozen stake (a.k.a. frozen deposits), + - it has no consensus key. + + Once a contract has become a delegate, it is so forever. There are no ways + to unregister. +*) + +type error += + | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t + +let () = + (* Unregistered delegate *) + register_error_kind + `Permanent + ~id:"contract.manager.unregistered_delegate" + ~title:"Unregistered delegate" + ~description:"A contract cannot be delegated to an unregistered delegate" + ~pp:(fun ppf k -> + Format.fprintf + ppf + "The provided public key (with hash %a) is not registered as valid \ + delegate key." + Signature.Public_key_hash.pp + k) + Data_encoding.(obj1 (req "hash" Signature.Public_key_hash.encoding)) + (function Unregistered_delegate k -> Some k | _ -> None) + (fun k -> Unregistered_delegate k) + +type error += No_previous_cycle + +let registered = Storage.Delegates.mem + +module Contract = struct + let init ctxt contract delegate = + let open Lwt_result_syntax in + let* known_delegate = + Contract_manager_storage.is_manager_key_revealed ctxt delegate + in + let*? () = error_unless known_delegate (Unregistered_delegate delegate) in + let*! is_registered = registered ctxt delegate in + let*? () = error_unless is_registered (Unregistered_delegate delegate) in + let* ctxt = Contract_delegate_storage.init ctxt contract delegate in + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds ctxt contract + in + Stake_storage.add_delegated_stake ctxt delegate balance_and_frozen_bonds + + type error += + | (* `Temporary *) Active_delegate + | (* `Permanent *) Empty_delegate_account of Signature.Public_key_hash.t + + let () = + register_error_kind + `Temporary + ~id:"delegate.already_active" + ~title:"Delegate already active" + ~description:"Useless delegate reactivation" + ~pp:(fun ppf () -> + Format.fprintf ppf "The delegate is still active, no need to refresh it") + Data_encoding.empty + (function Active_delegate -> Some () | _ -> None) + (fun () -> Active_delegate) ; + register_error_kind + `Permanent + ~id:"delegate.empty_delegate_account" + ~title:"Empty delegate account" + ~description: + "Cannot register a delegate when its implicit account is empty" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate registration is forbidden when the delegate\n\ + \ implicit account is empty (%a)" + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Empty_delegate_account c -> Some c | _ -> None) + (fun c -> Empty_delegate_account c) + + let set_self_delegate c delegate = + let open Lwt_result_syntax in + let*! is_registered = registered c delegate in + if is_registered then + let* () = + let* is_inactive = Delegate_activation_storage.is_inactive c delegate in + fail_unless is_inactive Active_delegate + in + Stake_storage.set_active c delegate + else + let contract = Contract_repr.Implicit delegate in + let* pk = + Contract_manager_storage.get_manager_key + c + ~error:(Unregistered_delegate delegate) + delegate + in + let* () = + let*! is_allocated = Contract_storage.allocated c contract in + fail_unless is_allocated (Empty_delegate_account delegate) + in + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds c contract + in + let* c = + Stake_storage.remove_contract_delegated_stake + c + contract + balance_and_frozen_bonds + in + let* c = Contract_delegate_storage.set c contract delegate in + let* c = + (* Initializes the full staking balance of [delegate]. *) + Stake_storage.initialize_delegate + c + delegate + ~delegated:balance_and_frozen_bonds + in + let*! c = Storage.Delegates.add c delegate in + let* c = Delegate_consensus_key.init c delegate pk in + let* c = Stake_storage.set_active c delegate in + return c + + type error += + | (* `Permanent *) No_deletion of Signature.Public_key_hash.t + | (* `Temporary *) Current_delegate + + let () = + register_error_kind + `Permanent + ~id:"delegate.no_deletion" + ~title:"Forbidden delegate deletion" + ~description:"Tried to unregister a delegate" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate deletion is forbidden (%a)" + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function No_deletion c -> Some c | _ -> None) + (fun c -> No_deletion c) ; + register_error_kind + `Temporary + ~id:"delegate.unchanged" + ~title:"Unchanged delegated" + ~description:"Contract already delegated to the given delegate" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The contract is already delegated to the same delegate") + Data_encoding.empty + (function Current_delegate -> Some () | _ -> None) + (fun () -> Current_delegate) + + let set_delegate c contract delegate = + let open Lwt_result_syntax in + let* () = + match contract with + | Contract_repr.Originated _ -> return_unit + | Implicit pkh -> + let*! is_registered = registered c pkh in + fail_when is_registered (No_deletion pkh) + in + let* () = + let* current_delegate = Contract_delegate_storage.find c contract in + match (delegate, current_delegate) with + | None, None -> + (* we don't fail in this case in order not to risk breaking + existing smart contracts. *) + return_unit + | Some delegate, Some current_delegate + when Signature.Public_key_hash.equal delegate current_delegate -> + tzfail Current_delegate + | _ -> return_unit + in + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds c contract + in + let* c = + Stake_storage.remove_contract_delegated_stake + c + contract + balance_and_frozen_bonds + in + match delegate with + | None -> + let* c = Contract_delegate_storage.delete c contract in + return c + | Some delegate -> + let* () = + let*! is_delegate_registered = registered c delegate in + fail_when + (not is_delegate_registered) + (Unregistered_delegate delegate) + in + let* c = Contract_delegate_storage.set c contract delegate in + let* c = + Stake_storage.add_delegated_stake c delegate balance_and_frozen_bonds + in + return c + + let set c contract delegate = + match (delegate, contract) with + | Some delegate, Contract_repr.Implicit source + when Signature.Public_key_hash.equal source delegate -> + set_self_delegate c delegate + | _ -> set_delegate c contract delegate +end + +let fold = Storage.Delegates.fold + +let list = Storage.Delegates.elements + +let initial_frozen_deposits ctxt delegate = + let open Lwt_result_syntax in + let* stake_opt = + match Raw_context.find_stake_distribution_for_current_cycle ctxt with + | Some distribution -> + return (Signature.Public_key_hash.Map.find delegate distribution) + | None -> + (* This branch happens when the stake distribution is not initialized in + [ctxt], e.g. when RPCs are called or operations are simulated. *) + let current_cycle = (Raw_context.current_level ctxt).cycle in + let+ stakes = + Stake_storage.get_selected_distribution ctxt current_cycle + in + List.assoc ~equal:Signature.Public_key_hash.equal delegate stakes + in + match stake_opt with + | None -> return Tez_repr.zero + | Some {frozen; weighted_delegated = _} -> return frozen + +let initial_frozen_deposits_of_previous_cycle ctxt delegate = + let open Lwt_result_syntax in + let current_cycle = (Raw_context.current_level ctxt).cycle in + match Cycle_repr.pred current_cycle with + | None -> tzfail No_previous_cycle + | Some previous_cycle -> ( + let+ stakes = + Stake_storage.get_selected_distribution ctxt previous_cycle + in + match + List.assoc ~equal:Signature.Public_key_hash.equal delegate stakes + with + | None -> Tez_repr.zero + | Some {frozen; weighted_delegated = _} -> frozen) + +let current_frozen_deposits ctxt delegate = + let open Lwt_result_syntax in + let* full_staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + Lwt.return (Full_staking_balance_repr.total_frozen full_staking_balance) + +let frozen_deposits_limit ctxt delegate = + Storage.Contract.Frozen_deposits_limit.find + ctxt + (Contract_repr.Implicit delegate) + +let set_frozen_deposits_limit ctxt delegate limit = + Storage.Contract.Frozen_deposits_limit.add_or_remove + ctxt + (Contract_repr.Implicit delegate) + limit + +let spendable_balance ctxt delegate = + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Spendable_balance.get ctxt contract + +let drain ctxt ~delegate ~destination = + let open Lwt_result_syntax in + let destination_contract = Contract_repr.Implicit destination in + let*! is_destination_allocated = + Contract_storage.allocated ctxt destination_contract + in + let delegate_contract = Contract_repr.Implicit delegate in + let* ctxt, _, balance_updates1 = + if not is_destination_allocated then + Fees_storage.burn_origination_fees + ctxt + ~storage_limit:(Z.of_int (Constants_storage.origination_size ctxt)) + ~payer:(`Contract delegate_contract) + else return (ctxt, Z.zero, []) + in + let* manager_balance = spendable_balance ctxt delegate in + let*? one_percent = Tez_repr.(manager_balance /? 100L) in + let fees = Tez_repr.(max one one_percent) in + let*? transferred = Tez_repr.(manager_balance -? fees) in + let* ctxt, balance_updates2 = + Token.transfer + ctxt + (`Contract delegate_contract) + (`Contract destination_contract) + transferred + in + return + ( ctxt, + not is_destination_allocated, + fees, + balance_updates1 @ balance_updates2 ) + +module For_RPC = struct + let full_balance ctxt delegate = + let open Lwt_result_syntax in + let* own_frozen_deposits = + Staking_pseudotokens_storage.For_RPC.staked_balance + ctxt + ~delegate + ~contract:(Contract_repr.Implicit delegate) + in + let* unstaked_frozen = + let* result = + Unstake_requests_storage.prepare_finalize_unstake + ctxt + ~for_next_cycle_use_only_after_slashing:false + (Contract_repr.Implicit delegate) + in + match result with + | None -> return Tez_repr.zero + | Some {finalizable; unfinalizable} -> + let* unfinalizable_requests = + Unstake_requests_storage.For_RPC + .apply_slash_to_unstaked_unfinalizable + ctxt + unfinalizable + in + let*? sum_unfinalizable = + List.fold_left_e + (fun acc (_cycle, tz) -> Tez_repr.(acc +? tz)) + Tez_repr.zero + unfinalizable_requests + in + let*? sum = + List.fold_left_e + (fun acc (_, _cycle, tz) -> Tez_repr.(acc +? tz)) + sum_unfinalizable + finalizable + in + return sum + in + let*? all_frozen = Tez_repr.(own_frozen_deposits +? unstaked_frozen) in + let delegate_contract = Contract_repr.Implicit delegate in + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds ctxt delegate_contract + in + let*? sum = Tez_repr.(all_frozen +? balance_and_frozen_bonds) in + return sum + + let staking_balance ctxt delegate = + let open Lwt_result_syntax in + let*! is_registered = registered ctxt delegate in + if is_registered then + Stake_storage.For_RPC.get_staking_balance ctxt delegate + else return Tez_repr.zero + + let min_delegated_in_current_cycle ctxt delegate = + let open Lwt_result_syntax in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let*! is_registered = registered ctxt delegate in + if is_registered then + let+ staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + let min_delegated = + Full_staking_balance_repr.min_delegated_in_cycle + ~current_cycle + staking_balance + in + let level_of_min_delegated = + match + Full_staking_balance_repr.Internal_for_tests_and_RPCs + .level_of_min_delegated + staking_balance + with + | None -> None + | Some level -> + if Cycle_repr.(level.cycle < current_cycle) then None + else Some level + in + (min_delegated, level_of_min_delegated) + else return (Tez_repr.zero, None) + + let delegated_balance ctxt delegate = + let open Lwt_result_syntax in + let* staking_balance = staking_balance ctxt delegate in + let* self_staking_balance = full_balance ctxt delegate in + let*? sum = Tez_repr.(staking_balance -? self_staking_balance) in + return sum +end diff --git a/src/proto_020_PsParisC/lib_protocol/delegate_storage.mli b/src/proto_020_PsParisC/lib_protocol/delegate_storage.mli new file mode 100644 index 000000000000..a5ef9fd9f9e2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/delegate_storage.mli @@ -0,0 +1,168 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module groups everything related to delegate registration. + For the invariants maintained, see the submodule {!Contract}. + + It also groups "trivial" getters/setters related to delegates. + + It is responsible for maintaining the following tables: + - {!Storage.Contract.Frozen_deposits_limit} + - {!Storage.Delegates} +*) + +type error += + | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t + +(** This module ensures the following invariants: + - registered delegates (i.e. those that appear in {!Storage.Delegates}) are + self-delegated, that is a delegate's implicit account delegates to itself + (i.e. {!Contract_delegate_storage.find} [delegate] returns [delegate]), + - registered delegates have their public keys revealed, + - registered delegates cannot change their delegation, + - stake is properly moved when changing delegation. +*) +module Contract : sig + type error += + | (* `Temporary *) Active_delegate + | (* `Permanent *) Empty_delegate_account of Signature.Public_key_hash.t + | (* `Permanent *) No_deletion of Signature.Public_key_hash.t + | (* `Temporary *) Current_delegate + + (** [init ctxt contract delegate] registers a delegate when + creating a contract. + + This functions assumes that [contract] is allocated. + + This function returns the {!Unregistered_delegate} error + if [contract] already has a delegate or + if [delegate] is not a registered delegate. *) + val init : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + + (** [set ctxt contract delegate_opt] allows to set the + delegate of a contract to [delegate] when [delegate_opt = Some delegate] + or to unset the delegate when [delegate_opt = None]. + When [delegate_opt = Some contract] (aka self-delegation), + the function also registers the contract as a delegate and + sets the delegate as {{!module:Delegate_activation_storage}active}. + + It returns the {!Unregistered_delegate} error when self-delegating and when the public key is not yet revealed. + It returns the {!Empty_delegate_account} error when self-delegating and the implicit account is not {{!Contract_storage.allocated}allocated}. + It returns the {!Active_delegate} error when self-delegating and the delegate is already active. + It returns the {!Unregistered_delegate} error when trying to set the delegate to an unregistered delegate. + It returns the {!Current_delegate} error when contract is already delegated to the same delegate. + It returns the {!No_deletion} error when trying to unset or change the delegate of a registered delegate. *) + val set : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option -> + Raw_context.t tzresult Lwt.t +end + +(** Has a delegate been registered in the delegate table? *) +val registered : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t + +(** Iterate on all registered delegates. *) +val fold : + Raw_context.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Signature.Public_key_hash.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + +(** List all registered delegates. *) +val list : Raw_context.t -> Signature.Public_key_hash.t list Lwt.t + +(** Returns a delegate's initial frozen deposits at the beginning of cycle. *) +val initial_frozen_deposits : + Raw_context.t -> Signature.public_key_hash -> Tez_repr.t tzresult Lwt.t + +(** Returns a delegate's initial frozen deposits at the beginning of the + previous cycle. + + Fails with [No_previous_cycle] if there is no previous cycle. *) +val initial_frozen_deposits_of_previous_cycle : + Raw_context.t -> Signature.public_key_hash -> Tez_repr.t tzresult Lwt.t + +(** Returns a delegate's current frozen deposits, which is the sum of + their own frozen funds and those of their stakers if applicable. *) +val current_frozen_deposits : + Raw_context.t -> Signature.public_key_hash -> Tez_repr.t tzresult Lwt.t + +val frozen_deposits_limit : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t option tzresult Lwt.t + +val set_frozen_deposits_limit : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t option -> + Raw_context.t Lwt.t + +val spendable_balance : + Raw_context.t -> Signature.public_key_hash -> Tez_repr.t tzresult Lwt.t + +val drain : + Raw_context.t -> + delegate:Signature.Public_key_hash.t -> + destination:Signature.Public_key_hash.t -> + (Raw_context.t * bool * Tez_repr.t * Receipt_repr.balance_updates) tzresult + Lwt.t + +(** The functions in this module are considered too costly to be used in + the protocol. + They are meant to be used only to answer RPC calls. +*) +module For_RPC : sig + (** Returns the full 'balance' of the implicit contract associated to + a given key, i.e. the sum of the spendable balance (given by [balance] or + [Contract_storage.get_balance]) and of the frozen balance. The frozen + balance is composed of all frozen bonds associated to the contract (given by + [Contract_storage.get_frozen_bonds]) and of the part of the frozen deposits + (given by [frozen_deposits]) that belongs to the delegate. + + Only use this function for RPCs: this is expensive. *) + val full_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + + (** Only use this function for RPCs: this is expensive. *) + val delegated_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + + val staking_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + + val min_delegated_in_current_cycle : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Tez_repr.t * Level_repr.t option) tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/denunciations_repr.ml b/src/proto_020_PsParisC/lib_protocol/denunciations_repr.ml new file mode 100644 index 000000000000..63b7aa6633d9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/denunciations_repr.ml @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type item = { + operation_hash : Operation_hash.t; + rewarded : Signature.public_key_hash; + misbehaviour : Misbehaviour_repr.t; +} + +let item_encoding = + let open Data_encoding in + conv + (fun {operation_hash; rewarded; misbehaviour} -> + (operation_hash, rewarded, misbehaviour)) + (fun (operation_hash, rewarded, misbehaviour) -> + {operation_hash; rewarded; misbehaviour}) + (obj3 + (req "operation_hash" Operation_hash.encoding) + (req "rewarded" Signature.Public_key_hash.encoding) + (req "misbehaviour" Misbehaviour_repr.encoding)) + +type t = item list + +let encoding = Data_encoding.list item_encoding + +let add operation_hash rewarded misbehaviour list = + list @ [{operation_hash; rewarded; misbehaviour}] diff --git a/src/proto_020_PsParisC/lib_protocol/denunciations_repr.mli b/src/proto_020_PsParisC/lib_protocol/denunciations_repr.mli new file mode 100644 index 000000000000..867529e7a1b2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/denunciations_repr.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Internal representation of a pending denunciation, meaning that a + denunciation operation has been observed in an applied block, but + the corresponding slashing has not happened yet. + + Note: the public key hash of the culprit doesn't appear in this + type because it is used as key to store the list of a culprit's + items (see type [t] below) in the context. *) +type item = { + operation_hash : Operation_hash.t; + rewarded : Signature.public_key_hash; + misbehaviour : Misbehaviour_repr.t; +} + +(** List of all pending denunciations about the same culprit. *) +type t = item list + +val item_encoding : item Data_encoding.t + +val encoding : t Data_encoding.t + +(** Append a new pending denunciation to the end of the given list. *) +val add : + Operation_hash.t -> Signature.public_key_hash -> Misbehaviour_repr.t -> t -> t diff --git a/src/proto_020_PsParisC/lib_protocol/dependent_bool.ml b/src/proto_020_PsParisC/lib_protocol/dependent_bool.ml new file mode 100644 index 000000000000..26d5bd7a9b5e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dependent_bool.ml @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type no = private DNo + +type yes = private DYes + +type _ dbool = No : no dbool | Yes : yes dbool + +type ('a, 'b, 'r) dand = + | NoNo : (no, no, no) dand + | NoYes : (no, yes, no) dand + | YesNo : (yes, no, no) dand + | YesYes : (yes, yes, yes) dand + +type ('a, 'b) ex_dand = Ex_dand : ('a, 'b, _) dand -> ('a, 'b) ex_dand +[@@unboxed] + +let dand : type a b. a dbool -> b dbool -> (a, b) ex_dand = + fun a b -> + match (a, b) with + | No, No -> Ex_dand NoNo + | No, Yes -> Ex_dand NoYes + | Yes, No -> Ex_dand YesNo + | Yes, Yes -> Ex_dand YesYes + +let dbool_of_dand : type a b r. (a, b, r) dand -> r dbool = function + | NoNo -> No + | NoYes -> No + | YesNo -> No + | YesYes -> Yes + +type (_, _) eq = Eq : ('a, 'a) eq + +let merge_dand : + type a b c1 c2. (a, b, c1) dand -> (a, b, c2) dand -> (c1, c2) eq = + fun w1 w2 -> + match (w1, w2) with + | NoNo, NoNo -> Eq + | NoYes, NoYes -> Eq + | YesNo, YesNo -> Eq + | YesYes, YesYes -> Eq diff --git a/src/proto_020_PsParisC/lib_protocol/dependent_bool.mli b/src/proto_020_PsParisC/lib_protocol/dependent_bool.mli new file mode 100644 index 000000000000..54416d9fd9c3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dependent_bool.mli @@ -0,0 +1,65 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Dependent booleans *) + +type no = private DNo + +type yes = private DYes + +(** + ['b dbool] is a boolean whose value depends on its type parameter ['b]. + [yes dbool] can only be [Yes]. [no dbool] can only be [No]. +*) +type _ dbool = No : no dbool | Yes : yes dbool + +(** + [('a, 'b, 'r) dand] is a witness of the logical conjunction of dependent + booleans. ['r] is the result of ['a] and ['b]. +*) +type ('a, 'b, 'r) dand = + | NoNo : (no, no, no) dand + | NoYes : (no, yes, no) dand + | YesNo : (yes, no, no) dand + | YesYes : (yes, yes, yes) dand + +type ('a, 'b) ex_dand = Ex_dand : ('a, 'b, _) dand -> ('a, 'b) ex_dand +[@@unboxed] + +(** Logical conjunction of dependent booleans. *) +val dand : 'a dbool -> 'b dbool -> ('a, 'b) ex_dand + +(** Result of the logical conjunction of dependent booleans. *) +val dbool_of_dand : ('a, 'b, 'r) dand -> 'r dbool + +(** Type equality witness. *) +type (_, _) eq = Eq : ('a, 'a) eq + +(** + [merge_dand] proves that the type [dand] represents a function, i.e. that + there is a unique ['r] such that [('a, 'b, 'r) dand] is inhabited for a + given ['a] and a given ['b]. +*) +val merge_dand : ('a, 'b, 'c1) dand -> ('a, 'b, 'c2) dand -> ('c1, 'c2) eq diff --git a/src/proto_020_PsParisC/lib_protocol/deposits_repr.ml b/src/proto_020_PsParisC/lib_protocol/deposits_repr.ml new file mode 100644 index 000000000000..aa725e93ec29 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/deposits_repr.ml @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = {initial_amount : Tez_repr.t; current_amount : Tez_repr.t} + +let encoding = + let open Data_encoding in + conv + (fun {initial_amount; current_amount} -> (initial_amount, current_amount)) + (fun (initial_amount, current_amount) -> {initial_amount; current_amount}) + (obj2 + (req "initial_amount" Tez_repr.encoding) + (req "actual_amount" Tez_repr.encoding)) + +let zero = {initial_amount = Tez_repr.zero; current_amount = Tez_repr.zero} + +let ( +? ) {initial_amount; current_amount} inc = + let open Result_syntax in + let* initial_amount = Tez_repr.(initial_amount +? inc) in + let+ current_amount = Tez_repr.(current_amount +? inc) in + {initial_amount; current_amount} + +let ( ++? ) {initial_amount = i1; current_amount = c1} + {initial_amount = i2; current_amount = c2} = + let open Result_syntax in + let* initial_amount = Tez_repr.(i1 +? i2) in + let+ current_amount = Tez_repr.(c1 +? c2) in + {initial_amount; current_amount} diff --git a/src/proto_020_PsParisC/lib_protocol/deposits_repr.mli b/src/proto_020_PsParisC/lib_protocol/deposits_repr.mli new file mode 100644 index 000000000000..781ff1fb38ed --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/deposits_repr.mli @@ -0,0 +1,44 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Type representing unstaked frozen deposits. + + [initial_amount] is the amount on which slashing should be based. + [current_amount] is the current amount after slashing has happened. + + There is a record per cycle. + + The [initial_amount] may be increased during the current cycle only, when + an unstake is requested. +*) +type t = {initial_amount : Tez_repr.t; current_amount : Tez_repr.t} + +val encoding : t Data_encoding.t + +val zero : t + +val ( +? ) : t -> Tez_repr.t -> t tzresult + +val ( ++? ) : t -> t -> t tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/destination_repr.ml b/src/proto_020_PsParisC/lib_protocol/destination_repr.ml new file mode 100644 index 000000000000..b2e2a865a1cc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/destination_repr.ml @@ -0,0 +1,159 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = + | Contract of Contract_repr.t + | Sc_rollup of Sc_rollup_repr.t + | Zk_rollup of Zk_rollup_repr.t + +(* If you add more cases to this type, please update the + [test_compare_destination] test in + [test/unit/test_destination_repr.ml] to ensure that the compare + function keeps its expected behavior to distinguish between + implicit accounts and smart contracts. *) + +include Compare.Make (struct + type nonrec t = t + + let compare l1 l2 = + match (l1, l2) with + | Contract k1, Contract k2 -> Contract_repr.compare k1 k2 + | Sc_rollup k1, Sc_rollup k2 -> Sc_rollup_repr.Address.compare k1 k2 + | Zk_rollup k1, Zk_rollup k2 -> Zk_rollup_repr.Address.compare k1 k2 + (* This function is used by the Michelson interpreter to compare + addresses. It is of significant importance to remember that in + Michelson, address comparison is used to distinguish between + KT1 and tz1. As a consequence, we want to preserve that [tz1 < + KT1 < others], which the two following lines ensure. The + wildcards are therefore here for a reason, and should not be + modified when new constructors are added to [t]. *) + | Contract _, _ -> -1 + | _, Contract _ -> 1 + | Sc_rollup _, _ -> -1 + | _, Sc_rollup _ -> 1 +end) + +let to_b58check = function + | Contract k -> Contract_repr.to_b58check k + | Sc_rollup k -> Sc_rollup_repr.Address.to_b58check k + | Zk_rollup k -> Zk_rollup_repr.Address.to_b58check k + +type error += Invalid_destination_b58check of string + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"destination_repr.invalid_b58check" + ~title:"Destination decoding failed" + ~description: + "Failed to read a valid destination from a b58check_encoding data" + (obj1 (req "input" (string Plain))) + (function Invalid_destination_b58check x -> Some x | _ -> None) + (fun x -> Invalid_destination_b58check x) + +let of_b58data data = + let decode_on_none decode wrap = function + | Some x -> Some x + | None -> Option.map wrap @@ decode data + in + None + |> decode_on_none Contract_repr.of_b58data (fun c -> Contract c) + |> decode_on_none Sc_rollup_repr.Address.of_b58data (fun s -> Sc_rollup s) + |> decode_on_none Zk_rollup_repr.Address.of_b58data (fun z -> Zk_rollup z) + +let of_b58check_opt s = Option.bind (Base58.decode s) of_b58data + +let of_b58check s = + let open Result_syntax in + match of_b58check_opt s with + | None -> tzfail (Invalid_destination_b58check s) + | Some dest -> return dest + +let encoding = + let open Data_encoding in + let case = function + | Tag tag -> + (* The tag was used by old variant. It have been removed in + protocol proposal O, it can be unblocked in the future. *) + let tx_rollup_address_reserved_tag = 2 in + assert (Compare.Int.(tag <> tx_rollup_address_reserved_tag)) ; + case (Tag tag) + | _ as c -> case c + in + def + "transaction_destination" + ~title:"A destination of a transaction" + ~description: + "A destination notation compatible with the contract notation as given \ + to an RPC or inside scripts. Can be a base58 implicit contract hash, a \ + base58 originated contract hash, a base58 originated transaction \ + rollup, or a base58 originated smart rollup." + @@ splitted + ~binary: + (union + ~tag_size:`Uint8 + (Contract_repr.cases + (function Contract x -> Some x | _ -> None) + (fun x -> Contract x) + @ [ + case + (Tag 3) + (Fixed.add_padding Sc_rollup_repr.Address.encoding 1) + ~title:"Smart_rollup" + (function Sc_rollup k -> Some k | _ -> None) + (fun k -> Sc_rollup k); + case + (Tag 4) + (Fixed.add_padding Zk_rollup_repr.Address.encoding 1) + ~title:"Zk_rollup" + (function Zk_rollup k -> Some k | _ -> None) + (fun k -> Zk_rollup k); + ])) + ~json: + (conv + to_b58check + (fun s -> + match of_b58check s with + | Ok s -> s + | Error _ -> + Data_encoding.Json.cannot_destruct + "Invalid destination notation.") + (string Plain)) + +let pp : Format.formatter -> t -> unit = + fun fmt -> function + | Contract k -> Contract_repr.pp fmt k + | Sc_rollup k -> Sc_rollup_repr.pp fmt k + | Zk_rollup k -> Zk_rollup_repr.Address.pp fmt k + +let in_memory_size = + let open Cache_memory_helpers in + function + | Contract k -> h1w +! Contract_repr.in_memory_size k + | Sc_rollup k -> h1w +! Sc_rollup_repr.in_memory_size k + | Zk_rollup k -> h1w +! Zk_rollup_repr.in_memory_size k diff --git a/src/proto_020_PsParisC/lib_protocol/destination_repr.mli b/src/proto_020_PsParisC/lib_protocol/destination_repr.mli new file mode 100644 index 000000000000..5407b3e28895 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/destination_repr.mli @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The type of the [destination] argument of the + {!Operation_repr.Transaction} manager operation. + + The introduction of this type allows to interact with emerging + layer-2 solutions using the API Tezos users and tooling + are already used to: contract calls to entrypoint. These solutions + cannot be integrated to {!Contract_repr.t} directly, because + values of this type are given a balance, which has an impact on + the delegation system. *) + +(** This type is a superset of the set of contracts ({!Contract_repr.t}). + + {b Note:} It is of key importance that the encoding of this type + remains compatible with {!Contract_repr.encoding}, for the + introduction to this type to remain transparent from the existing + tooling perspective. *) +type t = + | Contract of Contract_repr.t + | Sc_rollup of Sc_rollup_repr.t + | Zk_rollup of Zk_rollup_repr.t + +include Compare.S with type t := t + +val to_b58check : t -> string + +val of_b58check : string -> t tzresult + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +(** [in_memory_size contract] returns the number of bytes that are + allocated in the RAM for [contract]. *) +val in_memory_size : t -> Cache_memory_helpers.sint + +type error += Invalid_destination_b58check of string diff --git a/src/proto_020_PsParisC/lib_protocol/destination_storage.ml b/src/proto_020_PsParisC/lib_protocol/destination_storage.ml new file mode 100644 index 000000000000..ee92faf8e3ff --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/destination_storage.ml @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Destination_repr + +let must_exist ctxt = + let open Lwt_result_syntax in + function + | Contract k -> + let+ () = Contract_storage.must_exist ctxt k in + ctxt + | Sc_rollup sc -> Sc_rollup_storage.must_exist ctxt sc + | Zk_rollup zk -> Zk_rollup_storage.assert_exist ctxt zk diff --git a/src/proto_020_PsParisC/lib_protocol/destination_storage.mli b/src/proto_020_PsParisC/lib_protocol/destination_storage.mli new file mode 100644 index 000000000000..1c342a0e4d80 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/destination_storage.mli @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [must_exist ctxt dest] checks whether the given destination [dest] exists + in the context [ctxt]. If the destination exists, a new context is returned + with gas consumed for the lookup cost. If it does not exist, an error is + returned. *) +val must_exist : + Raw_context.t -> Destination_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/dune b/src/proto_020_PsParisC/lib_protocol/dune new file mode 100644 index 000000000000..97bb137338e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/dune @@ -0,0 +1,1186 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_protocol_environment_019_PtParisB) + (public_name tezos-protocol-019-PtParisB.protocol.environment) + (instrumentation (backend bisect_ppx)) + (libraries + octez-proto-libs.protocol-environment) + (library_flags (:standard -linkall)) + (modules Tezos_protocol_environment_019_PtParisB)) + +(rule + (targets tezos_protocol_environment_019_PtParisB.ml) + (action + (write-file + %{targets} + "module Name = struct let name = \"019-PtParisB\" end\ninclude Tezos_protocol_environment.V12.Make(Name)()\n"))) + +(library + (name tezos_raw_protocol_019_PtParisB) + (public_name tezos-protocol-019-PtParisB.protocol.raw) + (instrumentation (backend bisect_ppx)) + (libraries + tezos-protocol-019-PtParisB.protocol.environment) + (library_flags (:standard -linkall)) + (flags + (:standard) + -nostdlib + -nopervasives + -open Tezos_protocol_environment_019_PtParisB + -open Tezos_protocol_environment_019_PtParisB.Pervasives + -open Tezos_protocol_environment_019_PtParisB.Error_monad) + (modules + Misc + Non_empty_string + Path_encoding + Storage_description + State_hash + Nonce_hash + Script_expr_hash + Origination_nonce + Contract_hash + Blinded_public_key_hash + Block_payload_hash + Sc_rollup_reveal_hash + Merkle_list + Bitset + Bounded_history_repr + Context_binary_proof + Ratio_repr + Percentage + Michelson_v1_primitives + Slot_repr + Cycle_repr + Tez_repr + Deposits_repr + Unstaked_frozen_deposits_repr + Staking_pseudotoken_repr + Period_repr + Time_repr + Round_repr + Block_payload_repr + Fixed_point_repr + Saturation_repr + Gas_limit_repr + Raw_level_repr + Issuance_bonus_repr + Constants_parametric_repr + Constants_parametric_previous_repr + Constants_repr + Fitness_repr + Level_repr + Script_repr_costs_generated + Script_repr_costs + Script_repr + Cache_memory_helpers + Seed_repr + Sampler + Voting_period_repr + Ticket_hash_repr + Manager_counter_repr + Contract_repr + Indexable + Entrypoint_repr + Dal_slot_index_repr + Dal_slot_repr + Dal_attestation_repr + Michelson_v1_gas_costs_generated + Michelson_v1_gas_costs + Sc_rollup_repr + Sc_rollup_metadata_repr + Sc_rollup_dal_parameters_repr + Sc_rollup_tick_repr + Sc_rollup_inbox_message_repr + Sc_rollup_inbox_merkelized_payload_hashes_repr + Sc_rollup_whitelist_repr + Sc_rollup_outbox_message_repr + Sc_rollup_dissection_chunk_repr + Sc_rollup_PVM_sig + Sc_rollup_arith + Sc_rollup_wasm + Sc_rollup_riscv + Sc_rollup_machine_no_proofs + Sc_rollups + Sc_rollup_data_version_sig + Sc_rollup_inbox_repr + Sc_rollup_staker_index_repr + Sc_rollup_commitment_repr + Sc_rollup_proof_repr + Skip_list_costs_generated + Skip_list_costs + Sc_rollup_costs_generated + Sc_rollup_costs + Sc_rollup_game_repr + Tx_rollup_l2_address + Dal_errors_repr + Dal_operations_repr + Dal_costs_generated + Dal_costs + Zk_rollup_scalar + Zk_rollup_repr + Zk_rollup_state_repr + Zk_rollup_account_repr + Zk_rollup_ticket_repr + Zk_rollup_operation_repr + Zk_rollup_update_repr + Zk_rollup_circuit_public_inputs_repr + Bond_id_repr + Vote_repr + Votes_EMA_repr + Per_block_votes_repr + Block_header_repr + Destination_repr + Script_int + Ticket_amount + Operation_repr + Manager_repr + Commitment_repr + Parameters_repr + Sapling_repr + Lazy_storage_kind + Full_staking_balance_repr + Unstaked_frozen_staker_repr + Frozen_staker_repr + Stake_repr + Receipt_repr + Migration_repr + Carbonated_map_costs_generated + Carbonated_map_costs + Carbonated_map + Staking_parameters_repr + Misbehaviour_repr + Denunciations_repr + Raw_context_intf + Raw_context + Storage_costs_generated + Storage_costs + Storage_sigs + Storage_functors + Storage + Global_constants_costs_generated + Global_constants_costs + Ticket_hash_builder + Constants_storage + Level_storage + Nonce_storage + Seed_storage + Contract_manager_storage + Delegate_activation_storage + Sapling_storage_costs_generated + Sapling_storage_costs + Sapling_storage + Lazy_storage_diff + Commitment_storage + Voting_period_storage + Cache_repr_costs_generated + Cache_repr_costs + Cache_repr + Zk_rollup_storage + Stake_context + Contract_delegate_storage + Stake_storage + Unstaked_frozen_deposits_storage + Pending_denunciations_storage + Unstake_requests_storage + Staking_pseudotokens_storage + Contract_storage + Token + Fees_storage + Adaptive_issuance_costs + Adaptive_issuance_storage + Delegate_staking_parameters + Shared_stake + Delegate_consensus_key + Delegate_storage + Delegate_sampler + Delegate_rewards + Delegate_missed_attestations_storage + Already_denounced_storage + Forbidden_delegates_storage + Slash_percentage + Delegate_slashed_deposits_storage + Staking + Delegate_cycles + Vote_storage + Ticket_storage + Liquidity_baking_storage + Liquidity_baking_cpmm + Liquidity_baking_lqt + Liquidity_baking_migration + Sc_rollup_errors + Sc_rollup_inbox_storage + Legacy_script_patches + Sapling_validator + Global_constants_storage + Sc_rollup_staker_index_storage + Sc_rollup_commitment_storage + Sc_rollup_outbox_storage + Sc_rollup_whitelist_storage + Sc_rollup_stake_storage + Sc_rollup_storage + Dal_slot_storage + Sc_rollup_refutation_storage + Zk_rollup_errors + Bootstrap_storage + Init_storage + Destination_storage + Alpha_context + Script_string + Script_timestamp + Script_bytes + Local_gas_counter + Script_tc_errors + Gas_monad + Script_ir_annot + Dependent_bool + Script_list + Script_typed_ir + Script_comparable + Gas_comparable_input_size + Script_set + Script_map + Gas_input_size + Script_typed_ir_size + Script_typed_ir_size_costs_generated + Script_typed_ir_size_costs + Michelson_v1_gas + Operation_costs + Script_tc_context + Ticket_token + Ticket_receipt + Apply_operation_result + Apply_internal_results + Apply_results + Script_ir_translator_config + Script_ir_unparser + Script_ir_translator + Script_big_map + Script_cache + Script_tc_errors_registration + Ticket_token_unparser + Ticket_costs_generated + Ticket_costs + Ticket_scanner + Ticket_balance_key + Ticket_lazy_storage_diff + Zk_rollup_parameters + Ticket_token_map + Ticket_operations_diff + Ticket_accounting + Ticket_transfer + Script_interpreter_defs + Script_interpreter + Sc_rollup_management_protocol + Sc_rollup_operations + Dal_apply + Zk_rollup_apply + Baking + Validate_errors + Amendment + Validate + Mempool_validation + Apply + Services_registration + Constants_services + Sapling_services + Contract_services + Delegate_services + Voting_services + Dal_services + Adaptive_issuance_services + Alpha_services + Main)) + +(library + (name tezos_protocol_019_PtParisB) + (public_name tezos-protocol-019-PtParisB.protocol) + (instrumentation (backend bisect_ppx)) + (libraries + octez-proto-libs.protocol-environment + octez-proto-libs.protocol-environment.sigs + tezos-protocol-019-PtParisB.protocol.raw) + (flags + (:standard) + -nopervasives) + (modules Protocol Tezos_protocol_019_PtParisB)) + +(install + (package tezos-protocol-019-PtParisB) + (section lib) + (files (TEZOS_PROTOCOL as protocol/raw/TEZOS_PROTOCOL))) + +(rule + (targets protocol.ml) + (action + (write-file + %{targets} + "\nlet hash = Tezos_crypto.Hashed.Protocol_hash.of_b58check_exn \"PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ\"\nlet name = Tezos_protocol_environment_019_PtParisB.Name.name\ninclude Tezos_raw_protocol_019_PtParisB\ninclude Tezos_raw_protocol_019_PtParisB.Main\n"))) + +(rule + (targets tezos_protocol_019_PtParisB.ml) + (action + (write-file + %{targets} + "\nmodule Environment = Tezos_protocol_environment_019_PtParisB\nmodule Protocol = Protocol\n"))) + +(rule + (alias runtest_compile_protocol) + (deps + misc.ml misc.mli + non_empty_string.ml non_empty_string.mli + path_encoding.ml path_encoding.mli + storage_description.ml storage_description.mli + state_hash.ml state_hash.mli + nonce_hash.ml nonce_hash.mli + script_expr_hash.ml script_expr_hash.mli + origination_nonce.ml origination_nonce.mli + contract_hash.ml contract_hash.mli + blinded_public_key_hash.ml blinded_public_key_hash.mli + block_payload_hash.ml block_payload_hash.mli + sc_rollup_reveal_hash.ml sc_rollup_reveal_hash.mli + merkle_list.ml merkle_list.mli + bitset.ml bitset.mli + bounded_history_repr.ml bounded_history_repr.mli + context_binary_proof.ml context_binary_proof.mli + ratio_repr.ml ratio_repr.mli + percentage.ml percentage.mli + michelson_v1_primitives.ml michelson_v1_primitives.mli + slot_repr.ml slot_repr.mli + cycle_repr.ml cycle_repr.mli + tez_repr.ml tez_repr.mli + deposits_repr.ml deposits_repr.mli + unstaked_frozen_deposits_repr.ml unstaked_frozen_deposits_repr.mli + staking_pseudotoken_repr.ml staking_pseudotoken_repr.mli + period_repr.ml period_repr.mli + time_repr.ml time_repr.mli + round_repr.ml round_repr.mli + block_payload_repr.ml block_payload_repr.mli + fixed_point_repr.ml fixed_point_repr.mli + saturation_repr.ml saturation_repr.mli + gas_limit_repr.ml gas_limit_repr.mli + raw_level_repr.ml raw_level_repr.mli + issuance_bonus_repr.ml issuance_bonus_repr.mli + constants_parametric_repr.ml constants_parametric_repr.mli + constants_parametric_previous_repr.ml + constants_parametric_previous_repr.mli + constants_repr.ml constants_repr.mli + fitness_repr.ml fitness_repr.mli + level_repr.ml level_repr.mli + script_repr_costs_generated.ml + script_repr_costs.ml + script_repr.ml script_repr.mli + cache_memory_helpers.ml + seed_repr.ml seed_repr.mli + sampler.ml sampler.mli + voting_period_repr.ml voting_period_repr.mli + ticket_hash_repr.ml ticket_hash_repr.mli + manager_counter_repr.ml manager_counter_repr.mli + contract_repr.ml contract_repr.mli + indexable.ml indexable.mli + entrypoint_repr.ml entrypoint_repr.mli + dal_slot_index_repr.ml dal_slot_index_repr.mli + dal_slot_repr.ml dal_slot_repr.mli + dal_attestation_repr.ml dal_attestation_repr.mli + michelson_v1_gas_costs_generated.ml + michelson_v1_gas_costs.ml + sc_rollup_repr.ml sc_rollup_repr.mli + sc_rollup_metadata_repr.ml sc_rollup_metadata_repr.mli + sc_rollup_dal_parameters_repr.ml sc_rollup_dal_parameters_repr.mli + sc_rollup_tick_repr.ml sc_rollup_tick_repr.mli + sc_rollup_inbox_message_repr.ml sc_rollup_inbox_message_repr.mli + sc_rollup_inbox_merkelized_payload_hashes_repr.ml + sc_rollup_inbox_merkelized_payload_hashes_repr.mli + sc_rollup_whitelist_repr.ml sc_rollup_whitelist_repr.mli + sc_rollup_outbox_message_repr.ml sc_rollup_outbox_message_repr.mli + sc_rollup_dissection_chunk_repr.ml sc_rollup_dissection_chunk_repr.mli + sc_rollup_PVM_sig.ml + sc_rollup_arith.ml sc_rollup_arith.mli + sc_rollup_wasm.ml sc_rollup_wasm.mli + sc_rollup_riscv.ml sc_rollup_riscv.mli + sc_rollup_machine_no_proofs.ml sc_rollup_machine_no_proofs.mli + sc_rollups.ml sc_rollups.mli + sc_rollup_data_version_sig.ml + sc_rollup_inbox_repr.ml sc_rollup_inbox_repr.mli + sc_rollup_staker_index_repr.ml sc_rollup_staker_index_repr.mli + sc_rollup_commitment_repr.ml sc_rollup_commitment_repr.mli + sc_rollup_proof_repr.ml sc_rollup_proof_repr.mli + skip_list_costs_generated.ml + skip_list_costs.ml skip_list_costs.mli + sc_rollup_costs_generated.ml + sc_rollup_costs.ml sc_rollup_costs.mli + sc_rollup_game_repr.ml sc_rollup_game_repr.mli + tx_rollup_l2_address.ml tx_rollup_l2_address.mli + dal_errors_repr.ml + dal_operations_repr.ml dal_operations_repr.mli + dal_costs_generated.ml dal_costs_generated.mli + dal_costs.ml + zk_rollup_scalar.ml zk_rollup_scalar.mli + zk_rollup_repr.ml zk_rollup_repr.mli + zk_rollup_state_repr.ml zk_rollup_state_repr.mli + zk_rollup_account_repr.ml zk_rollup_account_repr.mli + zk_rollup_ticket_repr.ml zk_rollup_ticket_repr.mli + zk_rollup_operation_repr.ml zk_rollup_operation_repr.mli + zk_rollup_update_repr.ml zk_rollup_update_repr.mli + zk_rollup_circuit_public_inputs_repr.ml + zk_rollup_circuit_public_inputs_repr.mli + bond_id_repr.ml bond_id_repr.mli + vote_repr.ml vote_repr.mli + votes_EMA_repr.ml votes_EMA_repr.mli + per_block_votes_repr.ml per_block_votes_repr.mli + block_header_repr.ml block_header_repr.mli + destination_repr.ml destination_repr.mli + script_int.ml script_int.mli + ticket_amount.ml ticket_amount.mli + operation_repr.ml operation_repr.mli + manager_repr.ml manager_repr.mli + commitment_repr.ml commitment_repr.mli + parameters_repr.ml parameters_repr.mli + sapling_repr.ml + lazy_storage_kind.ml lazy_storage_kind.mli + full_staking_balance_repr.ml full_staking_balance_repr.mli + unstaked_frozen_staker_repr.ml unstaked_frozen_staker_repr.mli + frozen_staker_repr.ml frozen_staker_repr.mli + stake_repr.ml stake_repr.mli + receipt_repr.ml receipt_repr.mli + migration_repr.ml migration_repr.mli + carbonated_map_costs_generated.ml + carbonated_map_costs.ml carbonated_map_costs.mli + carbonated_map.ml carbonated_map.mli + staking_parameters_repr.ml staking_parameters_repr.mli + misbehaviour_repr.ml misbehaviour_repr.mli + denunciations_repr.ml denunciations_repr.mli + raw_context_intf.ml + raw_context.ml raw_context.mli + storage_costs_generated.ml + storage_costs.ml storage_costs.mli + storage_sigs.ml + storage_functors.ml storage_functors.mli + storage.ml storage.mli + global_constants_costs_generated.ml + global_constants_costs.ml global_constants_costs.mli + ticket_hash_builder.ml ticket_hash_builder.mli + constants_storage.ml constants_storage.mli + level_storage.ml level_storage.mli + nonce_storage.ml nonce_storage.mli + seed_storage.ml seed_storage.mli + contract_manager_storage.ml contract_manager_storage.mli + delegate_activation_storage.ml delegate_activation_storage.mli + sapling_storage_costs_generated.ml + sapling_storage_costs.ml + sapling_storage.ml + lazy_storage_diff.ml lazy_storage_diff.mli + commitment_storage.ml commitment_storage.mli + voting_period_storage.ml voting_period_storage.mli + cache_repr_costs_generated.ml + cache_repr_costs.ml + cache_repr.ml cache_repr.mli + zk_rollup_storage.ml zk_rollup_storage.mli + stake_context.ml stake_context.mli + contract_delegate_storage.ml contract_delegate_storage.mli + stake_storage.ml stake_storage.mli + unstaked_frozen_deposits_storage.ml unstaked_frozen_deposits_storage.mli + pending_denunciations_storage.ml pending_denunciations_storage.mli + unstake_requests_storage.ml unstake_requests_storage.mli + staking_pseudotokens_storage.ml staking_pseudotokens_storage.mli + contract_storage.ml contract_storage.mli + token.ml token.mli + fees_storage.ml fees_storage.mli + adaptive_issuance_costs.ml adaptive_issuance_costs.mli + adaptive_issuance_storage.ml adaptive_issuance_storage.mli + delegate_staking_parameters.ml delegate_staking_parameters.mli + shared_stake.ml shared_stake.mli + delegate_consensus_key.ml delegate_consensus_key.mli + delegate_storage.ml delegate_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_rewards.ml delegate_rewards.mli + delegate_missed_attestations_storage.ml + delegate_missed_attestations_storage.mli + already_denounced_storage.ml already_denounced_storage.mli + forbidden_delegates_storage.ml forbidden_delegates_storage.mli + slash_percentage.ml slash_percentage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + staking.ml staking.mli + delegate_cycles.ml delegate_cycles.mli + vote_storage.ml vote_storage.mli + ticket_storage.ml ticket_storage.mli + liquidity_baking_storage.ml liquidity_baking_storage.mli + liquidity_baking_cpmm.ml + liquidity_baking_lqt.ml + liquidity_baking_migration.ml liquidity_baking_migration.mli + sc_rollup_errors.ml + sc_rollup_inbox_storage.ml sc_rollup_inbox_storage.mli + legacy_script_patches.ml + sapling_validator.ml + global_constants_storage.ml global_constants_storage.mli + sc_rollup_staker_index_storage.ml sc_rollup_staker_index_storage.mli + sc_rollup_commitment_storage.ml sc_rollup_commitment_storage.mli + sc_rollup_outbox_storage.ml sc_rollup_outbox_storage.mli + sc_rollup_whitelist_storage.ml sc_rollup_whitelist_storage.mli + sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli + sc_rollup_storage.ml sc_rollup_storage.mli + dal_slot_storage.ml dal_slot_storage.mli + sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli + zk_rollup_errors.ml + bootstrap_storage.ml bootstrap_storage.mli + init_storage.ml init_storage.mli + destination_storage.ml destination_storage.mli + alpha_context.ml alpha_context.mli + script_string.ml script_string.mli + script_timestamp.ml script_timestamp.mli + script_bytes.ml script_bytes.mli + local_gas_counter.ml local_gas_counter.mli + script_tc_errors.ml + gas_monad.ml gas_monad.mli + script_ir_annot.ml script_ir_annot.mli + dependent_bool.ml dependent_bool.mli + script_list.ml script_list.mli + script_typed_ir.ml script_typed_ir.mli + script_comparable.ml script_comparable.mli + gas_comparable_input_size.ml gas_comparable_input_size.mli + script_set.ml script_set.mli + script_map.ml script_map.mli + gas_input_size.ml gas_input_size.mli + script_typed_ir_size.ml script_typed_ir_size.mli + script_typed_ir_size_costs_generated.ml + script_typed_ir_size_costs.ml script_typed_ir_size_costs.mli + michelson_v1_gas.ml michelson_v1_gas.mli + operation_costs.ml operation_costs.mli + script_tc_context.ml script_tc_context.mli + ticket_token.ml ticket_token.mli + ticket_receipt.ml ticket_receipt.mli + apply_operation_result.ml apply_operation_result.mli + apply_internal_results.ml apply_internal_results.mli + apply_results.ml apply_results.mli + script_ir_translator_config.ml + script_ir_unparser.ml script_ir_unparser.mli + script_ir_translator.ml script_ir_translator.mli + script_big_map.ml script_big_map.mli + script_cache.ml script_cache.mli + script_tc_errors_registration.ml script_tc_errors_registration.mli + ticket_token_unparser.ml ticket_token_unparser.mli + ticket_costs_generated.ml + ticket_costs.ml ticket_costs.mli + ticket_scanner.ml ticket_scanner.mli + ticket_balance_key.ml ticket_balance_key.mli + ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli + zk_rollup_parameters.ml zk_rollup_parameters.mli + ticket_token_map.ml ticket_token_map.mli + ticket_operations_diff.ml ticket_operations_diff.mli + ticket_accounting.ml ticket_accounting.mli + ticket_transfer.ml ticket_transfer.mli + script_interpreter_defs.ml + script_interpreter.ml script_interpreter.mli + sc_rollup_management_protocol.ml sc_rollup_management_protocol.mli + sc_rollup_operations.ml sc_rollup_operations.mli + dal_apply.ml dal_apply.mli + zk_rollup_apply.ml zk_rollup_apply.mli + baking.ml baking.mli + validate_errors.ml validate_errors.mli + amendment.ml amendment.mli + validate.ml validate.mli + mempool_validation.ml mempool_validation.mli + apply.ml apply.mli + services_registration.ml services_registration.mli + constants_services.ml constants_services.mli + sapling_services.ml + contract_services.ml contract_services.mli + delegate_services.ml delegate_services.mli + voting_services.ml voting_services.mli + dal_services.ml dal_services.mli + adaptive_issuance_services.ml adaptive_issuance_services.mli + alpha_services.ml alpha_services.mli + main.ml main.mli + (:src_dir TEZOS_PROTOCOL)) + (action (run %{bin:octez-protocol-compiler} -warn-error +a .))) + +(library + (name tezos_protocol_019_PtParisB_lifted) + (public_name tezos-protocol-019-PtParisB.protocol.lifted) + (instrumentation (backend bisect_ppx)) + (libraries + octez-proto-libs.protocol-environment + octez-proto-libs.protocol-environment.sigs + tezos-protocol-019-PtParisB.protocol) + (flags + (:standard) + -nopervasives + -open Tezos_protocol_019_PtParisB) + (modules Lifted_protocol)) + +(rule + (targets lifted_protocol.ml) + (action + (write-file + %{targets} + "\ninclude Environment.Lift (Protocol)\nlet hash = Protocol.hash\n"))) + +(library + (name tezos_protocol_019_PtParisB_functor) + (libraries + octez-proto-libs.protocol-environment + octez-proto-libs.protocol-environment.sigs) + (flags + (:standard) + -nopervasives) + (modules Functor)) + +(rule + (targets functor.ml) + (deps + misc.ml misc.mli + non_empty_string.ml non_empty_string.mli + path_encoding.ml path_encoding.mli + storage_description.ml storage_description.mli + state_hash.ml state_hash.mli + nonce_hash.ml nonce_hash.mli + script_expr_hash.ml script_expr_hash.mli + origination_nonce.ml origination_nonce.mli + contract_hash.ml contract_hash.mli + blinded_public_key_hash.ml blinded_public_key_hash.mli + block_payload_hash.ml block_payload_hash.mli + sc_rollup_reveal_hash.ml sc_rollup_reveal_hash.mli + merkle_list.ml merkle_list.mli + bitset.ml bitset.mli + bounded_history_repr.ml bounded_history_repr.mli + context_binary_proof.ml context_binary_proof.mli + ratio_repr.ml ratio_repr.mli + percentage.ml percentage.mli + michelson_v1_primitives.ml michelson_v1_primitives.mli + slot_repr.ml slot_repr.mli + cycle_repr.ml cycle_repr.mli + tez_repr.ml tez_repr.mli + deposits_repr.ml deposits_repr.mli + unstaked_frozen_deposits_repr.ml unstaked_frozen_deposits_repr.mli + staking_pseudotoken_repr.ml staking_pseudotoken_repr.mli + period_repr.ml period_repr.mli + time_repr.ml time_repr.mli + round_repr.ml round_repr.mli + block_payload_repr.ml block_payload_repr.mli + fixed_point_repr.ml fixed_point_repr.mli + saturation_repr.ml saturation_repr.mli + gas_limit_repr.ml gas_limit_repr.mli + raw_level_repr.ml raw_level_repr.mli + issuance_bonus_repr.ml issuance_bonus_repr.mli + constants_parametric_repr.ml constants_parametric_repr.mli + constants_parametric_previous_repr.ml + constants_parametric_previous_repr.mli + constants_repr.ml constants_repr.mli + fitness_repr.ml fitness_repr.mli + level_repr.ml level_repr.mli + script_repr_costs_generated.ml + script_repr_costs.ml + script_repr.ml script_repr.mli + cache_memory_helpers.ml + seed_repr.ml seed_repr.mli + sampler.ml sampler.mli + voting_period_repr.ml voting_period_repr.mli + ticket_hash_repr.ml ticket_hash_repr.mli + manager_counter_repr.ml manager_counter_repr.mli + contract_repr.ml contract_repr.mli + indexable.ml indexable.mli + entrypoint_repr.ml entrypoint_repr.mli + dal_slot_index_repr.ml dal_slot_index_repr.mli + dal_slot_repr.ml dal_slot_repr.mli + dal_attestation_repr.ml dal_attestation_repr.mli + michelson_v1_gas_costs_generated.ml + michelson_v1_gas_costs.ml + sc_rollup_repr.ml sc_rollup_repr.mli + sc_rollup_metadata_repr.ml sc_rollup_metadata_repr.mli + sc_rollup_dal_parameters_repr.ml sc_rollup_dal_parameters_repr.mli + sc_rollup_tick_repr.ml sc_rollup_tick_repr.mli + sc_rollup_inbox_message_repr.ml sc_rollup_inbox_message_repr.mli + sc_rollup_inbox_merkelized_payload_hashes_repr.ml + sc_rollup_inbox_merkelized_payload_hashes_repr.mli + sc_rollup_whitelist_repr.ml sc_rollup_whitelist_repr.mli + sc_rollup_outbox_message_repr.ml sc_rollup_outbox_message_repr.mli + sc_rollup_dissection_chunk_repr.ml sc_rollup_dissection_chunk_repr.mli + sc_rollup_PVM_sig.ml + sc_rollup_arith.ml sc_rollup_arith.mli + sc_rollup_wasm.ml sc_rollup_wasm.mli + sc_rollup_riscv.ml sc_rollup_riscv.mli + sc_rollup_machine_no_proofs.ml sc_rollup_machine_no_proofs.mli + sc_rollups.ml sc_rollups.mli + sc_rollup_data_version_sig.ml + sc_rollup_inbox_repr.ml sc_rollup_inbox_repr.mli + sc_rollup_staker_index_repr.ml sc_rollup_staker_index_repr.mli + sc_rollup_commitment_repr.ml sc_rollup_commitment_repr.mli + sc_rollup_proof_repr.ml sc_rollup_proof_repr.mli + skip_list_costs_generated.ml + skip_list_costs.ml skip_list_costs.mli + sc_rollup_costs_generated.ml + sc_rollup_costs.ml sc_rollup_costs.mli + sc_rollup_game_repr.ml sc_rollup_game_repr.mli + tx_rollup_l2_address.ml tx_rollup_l2_address.mli + dal_errors_repr.ml + dal_operations_repr.ml dal_operations_repr.mli + dal_costs_generated.ml dal_costs_generated.mli + dal_costs.ml + zk_rollup_scalar.ml zk_rollup_scalar.mli + zk_rollup_repr.ml zk_rollup_repr.mli + zk_rollup_state_repr.ml zk_rollup_state_repr.mli + zk_rollup_account_repr.ml zk_rollup_account_repr.mli + zk_rollup_ticket_repr.ml zk_rollup_ticket_repr.mli + zk_rollup_operation_repr.ml zk_rollup_operation_repr.mli + zk_rollup_update_repr.ml zk_rollup_update_repr.mli + zk_rollup_circuit_public_inputs_repr.ml + zk_rollup_circuit_public_inputs_repr.mli + bond_id_repr.ml bond_id_repr.mli + vote_repr.ml vote_repr.mli + votes_EMA_repr.ml votes_EMA_repr.mli + per_block_votes_repr.ml per_block_votes_repr.mli + block_header_repr.ml block_header_repr.mli + destination_repr.ml destination_repr.mli + script_int.ml script_int.mli + ticket_amount.ml ticket_amount.mli + operation_repr.ml operation_repr.mli + manager_repr.ml manager_repr.mli + commitment_repr.ml commitment_repr.mli + parameters_repr.ml parameters_repr.mli + sapling_repr.ml + lazy_storage_kind.ml lazy_storage_kind.mli + full_staking_balance_repr.ml full_staking_balance_repr.mli + unstaked_frozen_staker_repr.ml unstaked_frozen_staker_repr.mli + frozen_staker_repr.ml frozen_staker_repr.mli + stake_repr.ml stake_repr.mli + receipt_repr.ml receipt_repr.mli + migration_repr.ml migration_repr.mli + carbonated_map_costs_generated.ml + carbonated_map_costs.ml carbonated_map_costs.mli + carbonated_map.ml carbonated_map.mli + staking_parameters_repr.ml staking_parameters_repr.mli + misbehaviour_repr.ml misbehaviour_repr.mli + denunciations_repr.ml denunciations_repr.mli + raw_context_intf.ml + raw_context.ml raw_context.mli + storage_costs_generated.ml + storage_costs.ml storage_costs.mli + storage_sigs.ml + storage_functors.ml storage_functors.mli + storage.ml storage.mli + global_constants_costs_generated.ml + global_constants_costs.ml global_constants_costs.mli + ticket_hash_builder.ml ticket_hash_builder.mli + constants_storage.ml constants_storage.mli + level_storage.ml level_storage.mli + nonce_storage.ml nonce_storage.mli + seed_storage.ml seed_storage.mli + contract_manager_storage.ml contract_manager_storage.mli + delegate_activation_storage.ml delegate_activation_storage.mli + sapling_storage_costs_generated.ml + sapling_storage_costs.ml + sapling_storage.ml + lazy_storage_diff.ml lazy_storage_diff.mli + commitment_storage.ml commitment_storage.mli + voting_period_storage.ml voting_period_storage.mli + cache_repr_costs_generated.ml + cache_repr_costs.ml + cache_repr.ml cache_repr.mli + zk_rollup_storage.ml zk_rollup_storage.mli + stake_context.ml stake_context.mli + contract_delegate_storage.ml contract_delegate_storage.mli + stake_storage.ml stake_storage.mli + unstaked_frozen_deposits_storage.ml unstaked_frozen_deposits_storage.mli + pending_denunciations_storage.ml pending_denunciations_storage.mli + unstake_requests_storage.ml unstake_requests_storage.mli + staking_pseudotokens_storage.ml staking_pseudotokens_storage.mli + contract_storage.ml contract_storage.mli + token.ml token.mli + fees_storage.ml fees_storage.mli + adaptive_issuance_costs.ml adaptive_issuance_costs.mli + adaptive_issuance_storage.ml adaptive_issuance_storage.mli + delegate_staking_parameters.ml delegate_staking_parameters.mli + shared_stake.ml shared_stake.mli + delegate_consensus_key.ml delegate_consensus_key.mli + delegate_storage.ml delegate_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_rewards.ml delegate_rewards.mli + delegate_missed_attestations_storage.ml + delegate_missed_attestations_storage.mli + already_denounced_storage.ml already_denounced_storage.mli + forbidden_delegates_storage.ml forbidden_delegates_storage.mli + slash_percentage.ml slash_percentage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + staking.ml staking.mli + delegate_cycles.ml delegate_cycles.mli + vote_storage.ml vote_storage.mli + ticket_storage.ml ticket_storage.mli + liquidity_baking_storage.ml liquidity_baking_storage.mli + liquidity_baking_cpmm.ml + liquidity_baking_lqt.ml + liquidity_baking_migration.ml liquidity_baking_migration.mli + sc_rollup_errors.ml + sc_rollup_inbox_storage.ml sc_rollup_inbox_storage.mli + legacy_script_patches.ml + sapling_validator.ml + global_constants_storage.ml global_constants_storage.mli + sc_rollup_staker_index_storage.ml sc_rollup_staker_index_storage.mli + sc_rollup_commitment_storage.ml sc_rollup_commitment_storage.mli + sc_rollup_outbox_storage.ml sc_rollup_outbox_storage.mli + sc_rollup_whitelist_storage.ml sc_rollup_whitelist_storage.mli + sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli + sc_rollup_storage.ml sc_rollup_storage.mli + dal_slot_storage.ml dal_slot_storage.mli + sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli + zk_rollup_errors.ml + bootstrap_storage.ml bootstrap_storage.mli + init_storage.ml init_storage.mli + destination_storage.ml destination_storage.mli + alpha_context.ml alpha_context.mli + script_string.ml script_string.mli + script_timestamp.ml script_timestamp.mli + script_bytes.ml script_bytes.mli + local_gas_counter.ml local_gas_counter.mli + script_tc_errors.ml + gas_monad.ml gas_monad.mli + script_ir_annot.ml script_ir_annot.mli + dependent_bool.ml dependent_bool.mli + script_list.ml script_list.mli + script_typed_ir.ml script_typed_ir.mli + script_comparable.ml script_comparable.mli + gas_comparable_input_size.ml gas_comparable_input_size.mli + script_set.ml script_set.mli + script_map.ml script_map.mli + gas_input_size.ml gas_input_size.mli + script_typed_ir_size.ml script_typed_ir_size.mli + script_typed_ir_size_costs_generated.ml + script_typed_ir_size_costs.ml script_typed_ir_size_costs.mli + michelson_v1_gas.ml michelson_v1_gas.mli + operation_costs.ml operation_costs.mli + script_tc_context.ml script_tc_context.mli + ticket_token.ml ticket_token.mli + ticket_receipt.ml ticket_receipt.mli + apply_operation_result.ml apply_operation_result.mli + apply_internal_results.ml apply_internal_results.mli + apply_results.ml apply_results.mli + script_ir_translator_config.ml + script_ir_unparser.ml script_ir_unparser.mli + script_ir_translator.ml script_ir_translator.mli + script_big_map.ml script_big_map.mli + script_cache.ml script_cache.mli + script_tc_errors_registration.ml script_tc_errors_registration.mli + ticket_token_unparser.ml ticket_token_unparser.mli + ticket_costs_generated.ml + ticket_costs.ml ticket_costs.mli + ticket_scanner.ml ticket_scanner.mli + ticket_balance_key.ml ticket_balance_key.mli + ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli + zk_rollup_parameters.ml zk_rollup_parameters.mli + ticket_token_map.ml ticket_token_map.mli + ticket_operations_diff.ml ticket_operations_diff.mli + ticket_accounting.ml ticket_accounting.mli + ticket_transfer.ml ticket_transfer.mli + script_interpreter_defs.ml + script_interpreter.ml script_interpreter.mli + sc_rollup_management_protocol.ml sc_rollup_management_protocol.mli + sc_rollup_operations.ml sc_rollup_operations.mli + dal_apply.ml dal_apply.mli + zk_rollup_apply.ml zk_rollup_apply.mli + baking.ml baking.mli + validate_errors.ml validate_errors.mli + amendment.ml amendment.mli + validate.ml validate.mli + mempool_validation.ml mempool_validation.mli + apply.ml apply.mli + services_registration.ml services_registration.mli + constants_services.ml constants_services.mli + sapling_services.ml + contract_services.ml contract_services.mli + delegate_services.ml delegate_services.mli + voting_services.ml voting_services.mli + dal_services.ml dal_services.mli + adaptive_issuance_services.ml adaptive_issuance_services.mli + alpha_services.ml alpha_services.mli + main.ml main.mli (:src_dir TEZOS_PROTOCOL)) + (action + (with-stdout-to + %{targets} + (chdir + %{workspace_root} + (run %{bin:octez-protocol-compiler.octez-protocol-packer} %{src_dir}))))) + +(library + (name tezos_embedded_protocol_019_PtParisB) + (public_name tezos-protocol-019-PtParisB.embedded-protocol) + (instrumentation (backend bisect_ppx)) + (libraries + tezos-protocol-019-PtParisB.protocol + octez-shell-libs.protocol-updater + octez-proto-libs.protocol-environment) + (library_flags (:standard -linkall)) + (modules Registerer)) + +(rule + (targets registerer.ml) + (deps + misc.ml misc.mli + non_empty_string.ml non_empty_string.mli + path_encoding.ml path_encoding.mli + storage_description.ml storage_description.mli + state_hash.ml state_hash.mli + nonce_hash.ml nonce_hash.mli + script_expr_hash.ml script_expr_hash.mli + origination_nonce.ml origination_nonce.mli + contract_hash.ml contract_hash.mli + blinded_public_key_hash.ml blinded_public_key_hash.mli + block_payload_hash.ml block_payload_hash.mli + sc_rollup_reveal_hash.ml sc_rollup_reveal_hash.mli + merkle_list.ml merkle_list.mli + bitset.ml bitset.mli + bounded_history_repr.ml bounded_history_repr.mli + context_binary_proof.ml context_binary_proof.mli + ratio_repr.ml ratio_repr.mli + percentage.ml percentage.mli + michelson_v1_primitives.ml michelson_v1_primitives.mli + slot_repr.ml slot_repr.mli + cycle_repr.ml cycle_repr.mli + tez_repr.ml tez_repr.mli + deposits_repr.ml deposits_repr.mli + unstaked_frozen_deposits_repr.ml unstaked_frozen_deposits_repr.mli + staking_pseudotoken_repr.ml staking_pseudotoken_repr.mli + period_repr.ml period_repr.mli + time_repr.ml time_repr.mli + round_repr.ml round_repr.mli + block_payload_repr.ml block_payload_repr.mli + fixed_point_repr.ml fixed_point_repr.mli + saturation_repr.ml saturation_repr.mli + gas_limit_repr.ml gas_limit_repr.mli + raw_level_repr.ml raw_level_repr.mli + issuance_bonus_repr.ml issuance_bonus_repr.mli + constants_parametric_repr.ml constants_parametric_repr.mli + constants_parametric_previous_repr.ml + constants_parametric_previous_repr.mli + constants_repr.ml constants_repr.mli + fitness_repr.ml fitness_repr.mli + level_repr.ml level_repr.mli + script_repr_costs_generated.ml + script_repr_costs.ml + script_repr.ml script_repr.mli + cache_memory_helpers.ml + seed_repr.ml seed_repr.mli + sampler.ml sampler.mli + voting_period_repr.ml voting_period_repr.mli + ticket_hash_repr.ml ticket_hash_repr.mli + manager_counter_repr.ml manager_counter_repr.mli + contract_repr.ml contract_repr.mli + indexable.ml indexable.mli + entrypoint_repr.ml entrypoint_repr.mli + dal_slot_index_repr.ml dal_slot_index_repr.mli + dal_slot_repr.ml dal_slot_repr.mli + dal_attestation_repr.ml dal_attestation_repr.mli + michelson_v1_gas_costs_generated.ml + michelson_v1_gas_costs.ml + sc_rollup_repr.ml sc_rollup_repr.mli + sc_rollup_metadata_repr.ml sc_rollup_metadata_repr.mli + sc_rollup_dal_parameters_repr.ml sc_rollup_dal_parameters_repr.mli + sc_rollup_tick_repr.ml sc_rollup_tick_repr.mli + sc_rollup_inbox_message_repr.ml sc_rollup_inbox_message_repr.mli + sc_rollup_inbox_merkelized_payload_hashes_repr.ml + sc_rollup_inbox_merkelized_payload_hashes_repr.mli + sc_rollup_whitelist_repr.ml sc_rollup_whitelist_repr.mli + sc_rollup_outbox_message_repr.ml sc_rollup_outbox_message_repr.mli + sc_rollup_dissection_chunk_repr.ml sc_rollup_dissection_chunk_repr.mli + sc_rollup_PVM_sig.ml + sc_rollup_arith.ml sc_rollup_arith.mli + sc_rollup_wasm.ml sc_rollup_wasm.mli + sc_rollup_riscv.ml sc_rollup_riscv.mli + sc_rollup_machine_no_proofs.ml sc_rollup_machine_no_proofs.mli + sc_rollups.ml sc_rollups.mli + sc_rollup_data_version_sig.ml + sc_rollup_inbox_repr.ml sc_rollup_inbox_repr.mli + sc_rollup_staker_index_repr.ml sc_rollup_staker_index_repr.mli + sc_rollup_commitment_repr.ml sc_rollup_commitment_repr.mli + sc_rollup_proof_repr.ml sc_rollup_proof_repr.mli + skip_list_costs_generated.ml + skip_list_costs.ml skip_list_costs.mli + sc_rollup_costs_generated.ml + sc_rollup_costs.ml sc_rollup_costs.mli + sc_rollup_game_repr.ml sc_rollup_game_repr.mli + tx_rollup_l2_address.ml tx_rollup_l2_address.mli + dal_errors_repr.ml + dal_operations_repr.ml dal_operations_repr.mli + dal_costs_generated.ml dal_costs_generated.mli + dal_costs.ml + zk_rollup_scalar.ml zk_rollup_scalar.mli + zk_rollup_repr.ml zk_rollup_repr.mli + zk_rollup_state_repr.ml zk_rollup_state_repr.mli + zk_rollup_account_repr.ml zk_rollup_account_repr.mli + zk_rollup_ticket_repr.ml zk_rollup_ticket_repr.mli + zk_rollup_operation_repr.ml zk_rollup_operation_repr.mli + zk_rollup_update_repr.ml zk_rollup_update_repr.mli + zk_rollup_circuit_public_inputs_repr.ml + zk_rollup_circuit_public_inputs_repr.mli + bond_id_repr.ml bond_id_repr.mli + vote_repr.ml vote_repr.mli + votes_EMA_repr.ml votes_EMA_repr.mli + per_block_votes_repr.ml per_block_votes_repr.mli + block_header_repr.ml block_header_repr.mli + destination_repr.ml destination_repr.mli + script_int.ml script_int.mli + ticket_amount.ml ticket_amount.mli + operation_repr.ml operation_repr.mli + manager_repr.ml manager_repr.mli + commitment_repr.ml commitment_repr.mli + parameters_repr.ml parameters_repr.mli + sapling_repr.ml + lazy_storage_kind.ml lazy_storage_kind.mli + full_staking_balance_repr.ml full_staking_balance_repr.mli + unstaked_frozen_staker_repr.ml unstaked_frozen_staker_repr.mli + frozen_staker_repr.ml frozen_staker_repr.mli + stake_repr.ml stake_repr.mli + receipt_repr.ml receipt_repr.mli + migration_repr.ml migration_repr.mli + carbonated_map_costs_generated.ml + carbonated_map_costs.ml carbonated_map_costs.mli + carbonated_map.ml carbonated_map.mli + staking_parameters_repr.ml staking_parameters_repr.mli + misbehaviour_repr.ml misbehaviour_repr.mli + denunciations_repr.ml denunciations_repr.mli + raw_context_intf.ml + raw_context.ml raw_context.mli + storage_costs_generated.ml + storage_costs.ml storage_costs.mli + storage_sigs.ml + storage_functors.ml storage_functors.mli + storage.ml storage.mli + global_constants_costs_generated.ml + global_constants_costs.ml global_constants_costs.mli + ticket_hash_builder.ml ticket_hash_builder.mli + constants_storage.ml constants_storage.mli + level_storage.ml level_storage.mli + nonce_storage.ml nonce_storage.mli + seed_storage.ml seed_storage.mli + contract_manager_storage.ml contract_manager_storage.mli + delegate_activation_storage.ml delegate_activation_storage.mli + sapling_storage_costs_generated.ml + sapling_storage_costs.ml + sapling_storage.ml + lazy_storage_diff.ml lazy_storage_diff.mli + commitment_storage.ml commitment_storage.mli + voting_period_storage.ml voting_period_storage.mli + cache_repr_costs_generated.ml + cache_repr_costs.ml + cache_repr.ml cache_repr.mli + zk_rollup_storage.ml zk_rollup_storage.mli + stake_context.ml stake_context.mli + contract_delegate_storage.ml contract_delegate_storage.mli + stake_storage.ml stake_storage.mli + unstaked_frozen_deposits_storage.ml unstaked_frozen_deposits_storage.mli + pending_denunciations_storage.ml pending_denunciations_storage.mli + unstake_requests_storage.ml unstake_requests_storage.mli + staking_pseudotokens_storage.ml staking_pseudotokens_storage.mli + contract_storage.ml contract_storage.mli + token.ml token.mli + fees_storage.ml fees_storage.mli + adaptive_issuance_costs.ml adaptive_issuance_costs.mli + adaptive_issuance_storage.ml adaptive_issuance_storage.mli + delegate_staking_parameters.ml delegate_staking_parameters.mli + shared_stake.ml shared_stake.mli + delegate_consensus_key.ml delegate_consensus_key.mli + delegate_storage.ml delegate_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_rewards.ml delegate_rewards.mli + delegate_missed_attestations_storage.ml + delegate_missed_attestations_storage.mli + already_denounced_storage.ml already_denounced_storage.mli + forbidden_delegates_storage.ml forbidden_delegates_storage.mli + slash_percentage.ml slash_percentage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + staking.ml staking.mli + delegate_cycles.ml delegate_cycles.mli + vote_storage.ml vote_storage.mli + ticket_storage.ml ticket_storage.mli + liquidity_baking_storage.ml liquidity_baking_storage.mli + liquidity_baking_cpmm.ml + liquidity_baking_lqt.ml + liquidity_baking_migration.ml liquidity_baking_migration.mli + sc_rollup_errors.ml + sc_rollup_inbox_storage.ml sc_rollup_inbox_storage.mli + legacy_script_patches.ml + sapling_validator.ml + global_constants_storage.ml global_constants_storage.mli + sc_rollup_staker_index_storage.ml sc_rollup_staker_index_storage.mli + sc_rollup_commitment_storage.ml sc_rollup_commitment_storage.mli + sc_rollup_outbox_storage.ml sc_rollup_outbox_storage.mli + sc_rollup_whitelist_storage.ml sc_rollup_whitelist_storage.mli + sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli + sc_rollup_storage.ml sc_rollup_storage.mli + dal_slot_storage.ml dal_slot_storage.mli + sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli + zk_rollup_errors.ml + bootstrap_storage.ml bootstrap_storage.mli + init_storage.ml init_storage.mli + destination_storage.ml destination_storage.mli + alpha_context.ml alpha_context.mli + script_string.ml script_string.mli + script_timestamp.ml script_timestamp.mli + script_bytes.ml script_bytes.mli + local_gas_counter.ml local_gas_counter.mli + script_tc_errors.ml + gas_monad.ml gas_monad.mli + script_ir_annot.ml script_ir_annot.mli + dependent_bool.ml dependent_bool.mli + script_list.ml script_list.mli + script_typed_ir.ml script_typed_ir.mli + script_comparable.ml script_comparable.mli + gas_comparable_input_size.ml gas_comparable_input_size.mli + script_set.ml script_set.mli + script_map.ml script_map.mli + gas_input_size.ml gas_input_size.mli + script_typed_ir_size.ml script_typed_ir_size.mli + script_typed_ir_size_costs_generated.ml + script_typed_ir_size_costs.ml script_typed_ir_size_costs.mli + michelson_v1_gas.ml michelson_v1_gas.mli + operation_costs.ml operation_costs.mli + script_tc_context.ml script_tc_context.mli + ticket_token.ml ticket_token.mli + ticket_receipt.ml ticket_receipt.mli + apply_operation_result.ml apply_operation_result.mli + apply_internal_results.ml apply_internal_results.mli + apply_results.ml apply_results.mli + script_ir_translator_config.ml + script_ir_unparser.ml script_ir_unparser.mli + script_ir_translator.ml script_ir_translator.mli + script_big_map.ml script_big_map.mli + script_cache.ml script_cache.mli + script_tc_errors_registration.ml script_tc_errors_registration.mli + ticket_token_unparser.ml ticket_token_unparser.mli + ticket_costs_generated.ml + ticket_costs.ml ticket_costs.mli + ticket_scanner.ml ticket_scanner.mli + ticket_balance_key.ml ticket_balance_key.mli + ticket_lazy_storage_diff.ml ticket_lazy_storage_diff.mli + zk_rollup_parameters.ml zk_rollup_parameters.mli + ticket_token_map.ml ticket_token_map.mli + ticket_operations_diff.ml ticket_operations_diff.mli + ticket_accounting.ml ticket_accounting.mli + ticket_transfer.ml ticket_transfer.mli + script_interpreter_defs.ml + script_interpreter.ml script_interpreter.mli + sc_rollup_management_protocol.ml sc_rollup_management_protocol.mli + sc_rollup_operations.ml sc_rollup_operations.mli + dal_apply.ml dal_apply.mli + zk_rollup_apply.ml zk_rollup_apply.mli + baking.ml baking.mli + validate_errors.ml validate_errors.mli + amendment.ml amendment.mli + validate.ml validate.mli + mempool_validation.ml mempool_validation.mli + apply.ml apply.mli + services_registration.ml services_registration.mli + constants_services.ml constants_services.mli + sapling_services.ml + contract_services.ml contract_services.mli + delegate_services.ml delegate_services.mli + voting_services.ml voting_services.mli + dal_services.ml dal_services.mli + adaptive_issuance_services.ml adaptive_issuance_services.mli + alpha_services.ml alpha_services.mli + main.ml main.mli (:src_dir TEZOS_PROTOCOL)) + (action + (with-stdout-to + %{targets} + (chdir + %{workspace_root} + (run %{bin:octez-embedded-protocol-packer} %{src_dir} 019_PtParisB))))) diff --git a/src/proto_020_PsParisC/lib_protocol/entrypoint_repr.ml b/src/proto_020_PsParisC/lib_protocol/entrypoint_repr.ml new file mode 100644 index 000000000000..29fc395bb252 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/entrypoint_repr.ml @@ -0,0 +1,255 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Pre_entrypoint : sig + (** Invariants on the string: 1 <= length <= 31 *) + type t = private Non_empty_string.t + + val of_non_empty_string : Non_empty_string.t -> t option +end = struct + type t = Non_empty_string.t + + let of_non_empty_string (str : Non_empty_string.t) = + if Compare.Int.(String.length (str :> string) > 31) then None else Some str +end + +type t = Pre_entrypoint.t + +let compare (x : t) (y : t) = + Non_empty_string.compare (x :> Non_empty_string.t) (y :> Non_empty_string.t) + +let ( = ) (x : t) (y : t) = + Non_empty_string.( = ) (x :> Non_empty_string.t) (y :> Non_empty_string.t) + +type error += Name_too_long of string + +let () = + (* Entrypoint name too long *) + register_error_kind + `Permanent + ~id:"michelson_v1.entrypoint_name_too_long" + ~title:"Entrypoint name too long (type error)" + ~description: + "An entrypoint name exceeds the maximum length of 31 characters." + Data_encoding.(obj1 (req "name" @@ string Plain)) + (function Name_too_long entrypoint -> Some entrypoint | _ -> None) + (fun entrypoint -> Name_too_long entrypoint) + +type error += Unexpected_default of Script_repr.location + +let () = + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_default_entrypoint" + ~title: + "The annotation 'default' was encountered where an entrypoint is expected" + ~description: + "A node in the syntax tree was improperly annotated. An annotation used \ + to designate an entrypoint cannot be exactly 'default'." + Data_encoding.(obj1 (req "location" Script_repr.location_encoding)) + (function Unexpected_default loc -> Some loc | _ -> None) + (fun loc -> Unexpected_default loc) + +let default = + match + Pre_entrypoint.of_non_empty_string + @@ Non_empty_string.of_string_exn "default" + with + | None -> assert false + | Some res -> res + +let is_default name = name = default + +type of_string_result = + | Ok of t + | Too_long (** length > 31 *) + | Got_default + (** Got exactly "default", which can be an error in some cases or OK in others *) + +let of_non_empty_string (str : Non_empty_string.t) = + match Pre_entrypoint.of_non_empty_string str with + | None -> Too_long + | Some str -> if is_default str then Got_default else Ok str + +let of_string str = + match Non_empty_string.of_string str with + | None (* empty string *) -> + (* The empty string always means the default entrypoint *) + Ok default + | Some str -> of_non_empty_string str + +let of_string_strict ~loc str = + let open Result_syntax in + match of_string str with + | Too_long -> tzfail (Name_too_long str) + | Got_default -> tzfail (Unexpected_default loc) + | Ok name -> Ok name + +let of_string_strict' str = + match of_string str with + | Too_long -> Error "Entrypoint name too long" + | Got_default -> Error "Unexpected annotation: default" + | Ok name -> Ok name + +let of_string_strict_exn str = + match of_string_strict' str with Ok v -> v | Error err -> invalid_arg err + +let of_annot_strict ~loc a = + let open Result_syntax in + match of_non_empty_string a with + | Too_long -> tzfail (Name_too_long (a :> string)) + | Got_default -> tzfail (Unexpected_default loc) + | Ok name -> Ok name + +let of_annot_lax_opt a = + match of_non_empty_string a with + | Too_long -> None + | Got_default -> Some default + | Ok name -> Some name + +let of_string_lax_opt str = + match of_string str with + | Too_long -> None + | Got_default -> Some default + | Ok name -> Some name + +let of_string_lax str = + match of_string_lax_opt str with + | None -> Result_syntax.tzfail (Name_too_long str) + | Some name -> Ok name + +let of_annot_lax a = + match of_non_empty_string a with + | Too_long -> Result_syntax.tzfail (Name_too_long (a :> string)) + | Got_default -> Ok default + | Ok name -> Ok name + +let of_string_lax' str = + match of_string_lax_opt str with + | None -> Error ("Entrypoint name too long \"" ^ str ^ "\"") + | Some name -> Ok name + +let root = of_string_strict_exn "root" + +let do_ = of_string_strict_exn "do" + +let set_delegate = of_string_strict_exn "set_delegate" + +let remove_delegate = of_string_strict_exn "remove_delegate" + +let deposit = of_string_strict_exn "deposit" + +let stake = of_string_strict_exn "stake" + +let unstake = of_string_strict_exn "unstake" + +let finalize_unstake = of_string_strict_exn "finalize_unstake" + +let set_delegate_parameters = of_string_strict_exn "set_delegate_parameters" + +let is_deposit = ( = ) deposit + +let is_root = ( = ) root + +let to_non_empty_string (name : t) = (name :> Non_empty_string.t) + +let to_string (name : t) = (name :> string) + +let to_address_suffix (name : t) = + if is_default name then "" else "%" ^ (name :> string) + +let unparse_as_field_annot (name : t) = "%" ^ (name :> string) + +let of_string_lax_exn str = + match of_string_lax' str with Ok name -> name | Error err -> invalid_arg err + +let pp fmt (name : t) = Format.pp_print_string fmt (name :> string) + +let simple_encoding = + Data_encoding.conv_with_guard + (fun (name : t) -> (name :> string)) + of_string_lax' + Data_encoding.(string Plain) + +let value_encoding = + Data_encoding.conv_with_guard + (fun name -> if is_default name then "" else (name :> string)) + of_string_strict' + Data_encoding.Variable.(string Plain) + +let smart_encoding = + let open Data_encoding in + def + ~title:"entrypoint" + ~description:"Named entrypoint to a Michelson smart contract" + "entrypoint" + @@ + let builtin_case tag (name : Pre_entrypoint.t) = + case + (Tag tag) + ~title:(name :> string) + (constant (name :> string)) + (fun n -> if n = name then Some () else None) + (fun () -> name) + in + union + [ + builtin_case 0 default; + builtin_case 1 root; + builtin_case 2 do_; + builtin_case 3 set_delegate; + builtin_case 4 remove_delegate; + builtin_case 5 deposit; + builtin_case 6 stake; + builtin_case 7 unstake; + builtin_case 8 finalize_unstake; + builtin_case 9 set_delegate_parameters; + case + (Tag 255) + ~title:"named" + (Bounded.string Plain 31) + (fun (name : Pre_entrypoint.t) -> Some (name :> string)) + of_string_lax_exn; + ] + +let rpc_arg = + RPC_arg.make + ~descr:"A Michelson entrypoint (string of length < 32)" + ~name:"entrypoint" + ~construct:(fun (name : t) -> (name :> string)) + ~destruct:of_string_lax' + () + +let in_memory_size (name : t) = + Cache_memory_helpers.string_size_gen (String.length (name :> string)) + +module T = struct + type nonrec t = t + + let compare = compare +end + +module Set = Set.Make (T) +module Map = Map.Make (T) diff --git a/src/proto_020_PsParisC/lib_protocol/entrypoint_repr.mli b/src/proto_020_PsParisC/lib_protocol/entrypoint_repr.mli new file mode 100644 index 000000000000..2582bb42396f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/entrypoint_repr.mli @@ -0,0 +1,149 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** An entrypoint is a non-empty string of at most 31 characters *) +type t + +(** Total ordering of entrypoints *) +val compare : t -> t -> int + +(** Equality of entrypoints *) +val ( = ) : t -> t -> bool + +(** Default entrypoint "default" *) +val default : t + +(** Checks whether an entrypoint is the default entrypoint *) +val is_default : t -> bool + +(** Root entrypoint "root" *) +val root : t + +(** Checks whether an entrypoint is the root entrypoint *) +val is_root : t -> bool + +(** Entrypoint "do" *) +val do_ : t + +(** Entrypoint "set_delegate" *) +val set_delegate : t + +(** Entrypoint "remove_delegate" *) +val remove_delegate : t + +(** Deposit entrypoint "deposit" *) +val deposit : t + +(** Entrypoint "stake" *) +val stake : t + +(** Entrypoint "unstake" *) +val unstake : t + +(** Entrypoint "finalize_unstake" *) +val finalize_unstake : t + +(** Entrypoint "set_delegate_parameters" *) +val set_delegate_parameters : t + +(** Checks whether an entrypoint is the deposit entrypoint *) +val is_deposit : t -> bool + +(** Converts an annot to an entrypoint. + Returns an error if the string is too long or is "default". *) +val of_annot_strict : + loc:Script_repr.location -> Non_empty_string.t -> t tzresult + +(** Converts a string to an entrypoint. + Returns an error if the string is too long or is "default". + Converts "" to "default". *) +val of_string_strict : loc:Script_repr.location -> string -> t tzresult + +(** Converts a string to an entrypoint. + Fails with [Invalid_arg] if the string is too long or is "default". + Converts "" to "default". *) +val of_string_strict_exn : string -> t + +(** Converts an annot to an entrypoint. + Returns an error if the string is too long. + Accepts "default". *) +val of_annot_lax : Non_empty_string.t -> t tzresult + +(** Converts an annot to an entrypoint. + Returns [None] if the string is too long. + Accepts "default". *) +val of_annot_lax_opt : Non_empty_string.t -> t option + +(** Converts a string to an entrypoint. + Returns an error if the string is too long. + Accepts "default" and converts "" to "default". *) +val of_string_lax : string -> t tzresult + +(** Converts an entrypoint to a non-empty string. + "default" is kept as is. *) +val to_non_empty_string : t -> Non_empty_string.t + +(** Converts an entrypoint to a string. + "default" is kept as is. *) +val to_string : t -> string + +(** Converts an entrypoint to a string used as an address suffix. + For the default entrypoint, the result is the empty string. + Otherwise it is "%" followed by the entrypoint. *) +val to_address_suffix : t -> string + +(** Converts an entrypoint to a string used as a field annotation of a + parameter union type. It is "%" followed by the entrypoint. + The default entrypoint is converted to "%default". *) +val unparse_as_field_annot : t -> string + +(** Pretty-print an entrypoint *) +val pp : Format.formatter -> t -> unit + +(** An encoding of entrypoints reusing the lax semantics. + Decoding fails if the string is too long. "" is decoded into "default". + "default" is encoded into "default". *) +val simple_encoding : t Data_encoding.t + +(** An encoding of entrypoints reusing the strict semantics. + Decoding fails if the string is too long or is "default". + "" is decoded into "default". + "default" is encoded into "". *) +val value_encoding : t Data_encoding.t + +(** An optimized encoding of entrypoints, used for operations. *) +val smart_encoding : t Data_encoding.t + +(** Entrypoint RPC arg. *) +val rpc_arg : t RPC_arg.t + +(** In-memory size of an entrypoint *) +val in_memory_size : t -> Saturation_repr.may_saturate Saturation_repr.t + +(** Set of entrypoints *) +module Set : Set.S with type elt = t + +(** Map of entrypoints *) +module Map : Map.S with type key = t diff --git a/src/proto_020_PsParisC/lib_protocol/fees_storage.ml b/src/proto_020_PsParisC/lib_protocol/fees_storage.ml new file mode 100644 index 000000000000..05d0a1121408 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/fees_storage.ml @@ -0,0 +1,154 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Cannot_pay_storage_fee (* `Temporary *) + +type error += Negative_storage_input (* `Temporary *) + +type error += Operation_quota_exceeded (* `Temporary *) + +type error += Storage_limit_too_high (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Temporary + ~id:"contract.cannot_pay_storage_fee" + ~title:"Cannot pay storage fee" + ~description:"The storage fee is higher than the contract balance" + ~pp:(fun ppf () -> Format.fprintf ppf "Cannot pay storage fee") + Data_encoding.empty + (function Cannot_pay_storage_fee -> Some () | _ -> None) + (fun () -> Cannot_pay_storage_fee) ; + register_error_kind + `Temporary + ~id:"contract.negative_storage_input" + ~title:"Negative storage input" + ~description:"The storage amount asked for an operation is null or negative" + ~pp:(fun ppf () -> Format.fprintf ppf "Null or negative storage input") + Data_encoding.empty + (function Negative_storage_input -> Some () | _ -> None) + (fun () -> Negative_storage_input) ; + register_error_kind + `Temporary + ~id:"storage_exhausted.operation" + ~title:"Storage quota exceeded for the operation" + ~description: + "A script or one of its callee wrote more bytes than the operation said \ + it would" + Data_encoding.empty + (function Operation_quota_exceeded -> Some () | _ -> None) + (fun () -> Operation_quota_exceeded) ; + register_error_kind + `Permanent + ~id:"storage_limit_too_high" + ~title:"Storage limit out of protocol hard bounds" + ~description:"A transaction tried to exceed the hard limit on storage" + empty + (function Storage_limit_too_high -> Some () | _ -> None) + (fun () -> Storage_limit_too_high) + +let record_global_constant_storage_space context size = + (* Following the precedent of big_map, a key in the + global table of constants costs 65 bytes (see + [Lazy_storage_diff.Big_map.bytes_size_for_big_map_key])*) + let cost_of_key = Z.of_int 65 in + let to_be_paid = Z.add size cost_of_key in + (context, to_be_paid) + +let record_paid_storage_space ctxt contract_hash = + let open Lwt_result_syntax in + let contract = Contract_repr.Originated contract_hash in + (* Get the new size of the contract's storage. *) + let* new_storage_size = Contract_storage.used_storage_space ctxt contract in + let+ to_be_paid, c = + Contract_storage.set_paid_storage_space_and_return_fees_to_pay + ctxt + contract + new_storage_size + in + (c, new_storage_size, to_be_paid) + +let source_must_exist c src = + match src with + | `Contract src -> Contract_storage.must_exist c src + | _ -> return_unit + +let burn_storage_fees ?(origin = Receipt_repr.Block_application) c + ~storage_limit ~payer consumed = + let open Lwt_result_syntax in + let remaining = Z.sub storage_limit consumed in + if Compare.Z.(remaining < Z.zero) then tzfail Operation_quota_exceeded + else + let cost_per_byte = Constants_storage.cost_per_byte c in + let*? to_burn = Tez_repr.(cost_per_byte *? Z.to_int64 consumed) in + (* Burning the fees... *) + if Tez_repr.(to_burn = Tez_repr.zero) then + (* If the payer was deleted by transferring all its balance, and no space + was used, burning zero would fail *) + return (c, remaining, []) + else + trace + Cannot_pay_storage_fee + (let* () = source_must_exist c payer in + let+ ctxt, balance_updates = + Token.transfer ~origin c payer `Storage_fees to_burn + in + (ctxt, remaining, balance_updates)) + +let burn_storage_increase_fees ?(origin = Receipt_repr.Block_application) c + ~payer amount_in_bytes = + let open Lwt_result_syntax in + if Compare.Z.(amount_in_bytes <= Z.zero) then tzfail Negative_storage_input + else + let cost_per_byte = Constants_storage.cost_per_byte c in + let*? to_burn = Tez_repr.(cost_per_byte *? Z.to_int64 amount_in_bytes) in + (* Burning the fees... *) + trace + Cannot_pay_storage_fee + (let* () = source_must_exist c payer in + Token.transfer ~origin c payer `Storage_fees to_burn) + +let burn_origination_fees ?(origin = Receipt_repr.Block_application) c + ~storage_limit ~payer = + let origination_size = Constants_storage.origination_size c in + burn_storage_fees ~origin c ~storage_limit ~payer (Z.of_int origination_size) + +let burn_sc_rollup_origination_fees ?(origin = Receipt_repr.Block_application) c + ~storage_limit ~payer consumed = + burn_storage_fees ~origin c ~storage_limit ~payer consumed + +let burn_zk_rollup_origination_fees ?(origin = Receipt_repr.Block_application) c + ~storage_limit ~payer consumed = + burn_storage_fees ~origin c ~storage_limit ~payer consumed + +let check_storage_limit c ~storage_limit = + let open Result_syntax in + if + Compare.Z.( + storage_limit > (Raw_context.constants c).hard_storage_limit_per_operation) + || Compare.Z.(storage_limit < Z.zero) + then tzfail Storage_limit_too_high + else return_unit diff --git a/src/proto_020_PsParisC/lib_protocol/fees_storage.mli b/src/proto_020_PsParisC/lib_protocol/fees_storage.mli new file mode 100644 index 000000000000..4c20f790383b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/fees_storage.mli @@ -0,0 +1,116 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Cannot_pay_storage_fee (* `Temporary *) + +type error += Negative_storage_input (* `Temporary *) + +type error += Operation_quota_exceeded (* `Temporary *) + +type error += Storage_limit_too_high (* `Permanent *) + +(** [record_global_constant_storage_space ctxt size] records + paid storage space for registering a new global constant. + Cost is in bytes + 65 additional bytes for the key + hash of the expression. Returns new context and the cost. +*) +val record_global_constant_storage_space : + Raw_context.t -> Z.t -> Raw_context.t * Z.t + +(** [record_paid_storage_space ctxt contract] updates the amount of + storage consumed by the [contract]. This total size is considered + as accounted for as far as future payment is concerned. + + Returns a new context, the total space consumed by the [contract], + and the additional (and unpaid) space consumed since the last call + of this function on this [contract]. *) +val record_paid_storage_space : + Raw_context.t -> Contract_hash.t -> (Raw_context.t * Z.t * Z.t) tzresult Lwt.t + +(** [check_storage_limit ctxt ~storage_limit] raises the [Storage_limit_too_high] + error iff [storage_limit] is negative or greater the constant + [hard_storage_limit_per_operation]. *) +val check_storage_limit : Raw_context.t -> storage_limit:Z.t -> unit tzresult + +(** [burn_storage_fees ctxt ~storage_limit ~payer consumed] takes funds from the + [payer] to pay the cost of the [consumed] storage. This function has an + optional parameter [~origin] that allows to set the origin of returned + balance updates (by default the parameter is set to [Block_application]). + Returns an updated context, an updated storage limit equal to + [storage_limit - consumed], and the relevant balance updates. + Raises the [Operation_quota_exceeded] error if [storage_limit < consumed]. + Raises the [Cannot_pay_storage_fee] error if the funds from the [payer] are + not sufficient to pay the storage fees. *) +val burn_storage_fees : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + storage_limit:Z.t -> + payer:Token.giver -> + Z.t -> + (Raw_context.t * Z.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [burn_storage_increase_fees ctxt ~payer amount_in_bytes] takes funds from the + [payer] to pay the cost of the [amount_in_bytes] storage. This function has an + optional parameter [~origin] that allows to set the origin of returned + balance updates (by default the parameter is set to [Block_application]). + Returns an updated context and the relevant balance updates. + Raises the [Negative_storage_input] error if the amount_in_bytes is null or negative. + Raises the [Cannot_pay_storage_fee] error if the funds from the [payer] are + not sufficient to pay the storage fees. *) +val burn_storage_increase_fees : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + payer:Token.giver -> + Z.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** Calls [burn_storage_fees] with the parameter [consumed] mapped to the + constant [origination_size]. *) +val burn_origination_fees : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + storage_limit:Z.t -> + payer:Token.giver -> + (Raw_context.t * Z.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [burn_sc_rollup_origination_fees ~origin ctxt ~storage_limit ~payer consumed] + burns the storage fees for smart contract rollup creation fees. *) +val burn_sc_rollup_origination_fees : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + storage_limit:Z.t -> + payer:Token.giver -> + Z.t -> + (Raw_context.t * Z.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [burn_zk_rollup_origination_fees ~origin ctxt ~storage_limit ~payer consumed] + burns the storage fees for ZK rollup origination fees. *) +val burn_zk_rollup_origination_fees : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + storage_limit:Z.t -> + payer:Token.giver -> + Z.t -> + (Raw_context.t * Z.t * Receipt_repr.balance_updates) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/fitness_repr.ml b/src/proto_020_PsParisC/lib_protocol/fitness_repr.ml new file mode 100644 index 000000000000..892e9c102d47 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/fitness_repr.ml @@ -0,0 +1,308 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + level : Raw_level_repr.t; + locked_round : Round_repr.t option; + predecessor_round : Round_repr.t; + (* by convention, predecessor_round is 0 in case of protocol migration *) + round : Round_repr.t; +} + +let encoding = + let open Data_encoding in + let open Result_syntax in + def + "fitness" + (conv_with_guard + (fun {level; locked_round; predecessor_round; round} -> + (level, locked_round, predecessor_round, round)) + (fun (level, locked_round, predecessor_round, round) -> + match locked_round with + | None -> return {level; locked_round; predecessor_round; round} + | Some locked_round_val -> + if Round_repr.(round <= locked_round_val) then + Error "Locked round must be smaller than round." + else return {level; locked_round; predecessor_round; round}) + (obj4 + (req "level" Raw_level_repr.encoding) + (req "locked_round" (option Round_repr.encoding)) + (req "predecessor_round" Round_repr.encoding) + (req "round" Round_repr.encoding))) + +let pp ppf f = + let minus_sign = + if Round_repr.(f.predecessor_round = Round_repr.zero) then "" else "-" + in + let locked_round ppf locked_round = + match locked_round with + | None -> Format.pp_print_string ppf "unlocked" + | Some round -> Format.fprintf ppf "locked: %a" Round_repr.pp round + in + Format.fprintf + ppf + "(%a, %a, %s%a, %a)" + Raw_level_repr.pp + f.level + locked_round + f.locked_round + minus_sign + Round_repr.pp + f.predecessor_round + Round_repr.pp + f.round + +type error += + | (* `Permanent *) Invalid_fitness + | (* `Permanent *) Wrong_fitness + | (* `Permanent *) Outdated_fitness + | (* `Permanent *) + Locked_round_not_less_than_round of { + round : Round_repr.t; + locked_round : Round_repr.t; + } + +let () = + register_error_kind + `Permanent + ~id:"invalid_fitness" + ~title:"Invalid fitness" + ~description: + "Fitness representation should be exactly 4 times 4 bytes long." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid fitness") + Data_encoding.empty + (function Invalid_fitness -> Some () | _ -> None) + (fun () -> Invalid_fitness) ; + register_error_kind + `Permanent + ~id:"wrong_fitness" + ~title:"Wrong fitness" + ~description:"Wrong fitness." + ~pp:(fun ppf () -> Format.fprintf ppf "Wrong fitness.") + Data_encoding.empty + (function Wrong_fitness -> Some () | _ -> None) + (fun () -> Wrong_fitness) ; + register_error_kind + `Permanent + ~id:"outdated_fitness" + ~title:"Outdated fitness" + ~description:"Outdated fitness: referring to a previous version" + ~pp:(fun ppf () -> + Format.fprintf ppf "Outdated fitness: referring to a previous version.") + Data_encoding.empty + (function Outdated_fitness -> Some () | _ -> None) + (fun () -> Outdated_fitness) ; + register_error_kind + `Permanent + ~id:"locked_round_not_less_than_round" + ~title:"Locked round not smaller than round" + ~description:"The round is smaller than or equal to the locked round." + ~pp:(fun ppf (round, locked_round) -> + Format.fprintf + ppf + "Incorrect fitness: round %a is less than or equal to locked round %a." + Round_repr.pp + round + Round_repr.pp + locked_round) + Data_encoding.( + obj2 + (req "round" Round_repr.encoding) + (req "locked_round" Round_repr.encoding)) + (function + | Locked_round_not_less_than_round {round; locked_round} -> + Some (round, locked_round) + | _ -> None) + (fun (round, locked_round) -> + Locked_round_not_less_than_round {round; locked_round}) + +let create_without_locked_round ~level ~predecessor_round ~round = + {level; locked_round = None; predecessor_round; round} + +let create ~level ~locked_round ~predecessor_round ~round = + let open Result_syntax in + match locked_round with + | None -> return {level; locked_round; predecessor_round; round} + | Some locked_round_val -> + let* () = + error_when + Round_repr.(round <= locked_round_val) + (Locked_round_not_less_than_round + {round; locked_round = locked_round_val}) + in + return {level; locked_round; predecessor_round; round} + +let int32_to_bytes i = + let b = Bytes.make 4 '\000' in + TzEndian.set_int32 b 0 i ; + b + +let int32_of_bytes b = + let open Result_syntax in + if Compare.Int.(Bytes.length b <> 4) then tzfail Invalid_fitness + else return (TzEndian.get_int32 b 0) + +(* Locked round is an option. And we want None to be smaller than any other + value. The way the shell handles the order makes the empty Bytes smaller + than any other *) +let locked_round_to_bytes = function + | None -> Bytes.empty + | Some locked_round -> int32_to_bytes (Round_repr.to_int32 locked_round) + +let locked_round_of_bytes b = + let open Result_syntax in + match Bytes.length b with + | 0 -> return_none + | 4 -> + let* r = Round_repr.of_int32 (TzEndian.get_int32 b 0) in + return_some r + | _ -> tzfail Invalid_fitness + +let predecessor_round_of_bytes neg_predecessor_round = + let open Result_syntax in + let* neg_predecessor_round = int32_of_bytes neg_predecessor_round in + Round_repr.of_int32 @@ Int32.pred (Int32.neg neg_predecessor_round) + +let round_of_bytes round = + let open Result_syntax in + let* value = int32_of_bytes round in + Round_repr.of_int32 value + +let to_raw {level; locked_round; predecessor_round; round} = + [ + Bytes.of_string Constants_repr.fitness_version_number; + int32_to_bytes (Raw_level_repr.to_int32 level); + locked_round_to_bytes locked_round; + int32_to_bytes + (Int32.pred (Int32.neg (Round_repr.to_int32 predecessor_round))); + int32_to_bytes (Round_repr.to_int32 round); + ] + +let from_raw = + let open Result_syntax in + function + | [version; level; locked_round; neg_predecessor_round; round] + when Compare.String.( + Bytes.to_string version = Constants_repr.fitness_version_number) -> + let* level = + let* value = int32_of_bytes level in + Raw_level_repr.of_int32 value + in + let* locked_round = locked_round_of_bytes locked_round in + let* predecessor_round = + predecessor_round_of_bytes neg_predecessor_round + in + let* round = round_of_bytes round in + create ~level ~locked_round ~predecessor_round ~round + | [version; _] + when Compare.String.( + Bytes.to_string version < Constants_repr.fitness_version_number) -> + tzfail Outdated_fitness + | [] (* genesis fitness *) -> tzfail Outdated_fitness + | _ -> tzfail Invalid_fitness + +let round_from_raw = + let open Result_syntax in + function + | [version; _level; _locked_round; _neg_predecessor_round; round] + when Compare.String.( + Bytes.to_string version = Constants_repr.fitness_version_number) -> + round_of_bytes round + | [version; _] + when Compare.String.( + Bytes.to_string version < Constants_repr.fitness_version_number) -> + return Round_repr.zero + | [] (* genesis fitness *) -> return Round_repr.zero + | _ -> tzfail Invalid_fitness + +let predecessor_round_from_raw = + let open Result_syntax in + function + | [version; _level; _locked_round; neg_predecessor_round; _round] + when Compare.String.( + Bytes.to_string version = Constants_repr.fitness_version_number) -> + predecessor_round_of_bytes neg_predecessor_round + | [version; _] + when Compare.String.( + Bytes.to_string version < Constants_repr.fitness_version_number) -> + return Round_repr.zero + | [] (* genesis fitness *) -> return Round_repr.zero + | _ -> tzfail Invalid_fitness + +let locked_round_from_raw = + let open Result_syntax in + function + | [version; _level; locked_round; _neg_predecessor_round; _round] + when Compare.String.( + Bytes.to_string version = Constants_repr.fitness_version_number) -> + locked_round_of_bytes locked_round + | [version; _] + when Compare.String.( + Bytes.to_string version < Constants_repr.fitness_version_number) -> + return_none + | [] (* former genesis fitness *) -> return_none + | _ -> tzfail Invalid_fitness + +let check_except_locked_round fitness ~level ~predecessor_round = + let { + level = expected_level; + locked_round = _; + predecessor_round = expected_predecessor_round; + round = _; + } = + fitness + in + let correct = + Raw_level_repr.(level = expected_level) + && Round_repr.(predecessor_round = expected_predecessor_round) + in + error_unless correct Wrong_fitness + +let level fitness = fitness.level + +let round fitness = fitness.round + +let locked_round fitness = fitness.locked_round + +let predecessor_round fitness = fitness.predecessor_round + +module Internal_for_tests = struct + module ListInt32Compare = Compare.List (Compare.Int32) + + let compare f ff = + let unopt l = + match l with Some l -> Round_repr.to_int32 l | None -> -1l + in + let to_list {level; locked_round; predecessor_round; round} = + Int32. + [ + Raw_level_repr.to_int32 level; + unopt locked_round; + neg (Round_repr.to_int32 predecessor_round); + Round_repr.to_int32 round; + ] + in + ListInt32Compare.compare (to_list f) (to_list ff) +end diff --git a/src/proto_020_PsParisC/lib_protocol/fitness_repr.mli b/src/proto_020_PsParisC/lib_protocol/fitness_repr.mli new file mode 100644 index 000000000000..7cc5e5450154 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/fitness_repr.mli @@ -0,0 +1,96 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Permanent *) Invalid_fitness + | (* `Permanent *) Wrong_fitness + | (* `Permanent *) Outdated_fitness + | (* `Permanent *) + Locked_round_not_less_than_round of { + round : Round_repr.t; + locked_round : Round_repr.t; + } + +type t + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +val create : + level:Raw_level_repr.t -> + locked_round:Round_repr.t option -> + predecessor_round:Round_repr.t -> + round:Round_repr.t -> + t tzresult + +val create_without_locked_round : + level:Raw_level_repr.t -> + predecessor_round:Round_repr.t -> + round:Round_repr.t -> + t + +val to_raw : t -> Fitness.t + +(** Returns the corresponding protocol fitness if the shell fitness has + the expected version, given by + Constants_repr.fitness_version_number. If the fitness' version is + from a previous protocol version, then it raises an "outdated + fitness" error. If the fitness version is higher then + it raises an "invalid fitness" error. *) +val from_raw : Fitness.t -> t tzresult + +(** Returns the round from a raw fitness. If the fitness is from a + previous protocol, the returned value will be Round.zero. *) +val round_from_raw : Fitness.t -> Round_repr.t tzresult + +(** Returns the predecessor round from a raw fitness. If the fitness + is from a previous protocol, the returned value will be Round.zero. *) +val predecessor_round_from_raw : Fitness.t -> Round_repr.t tzresult + +(** Returns the locked round from a raw fitness. If the fitness is + from a previous version, the returned value will be None. *) +val locked_round_from_raw : Fitness.t -> Round_repr.t option tzresult + +(** Validate only the part of the fitness for which information are + available during begin_application *) +val check_except_locked_round : + t -> level:Raw_level_repr.t -> predecessor_round:Round_repr.t -> unit tzresult + +val level : t -> Raw_level_repr.t + +val round : t -> Round_repr.t + +val locked_round : t -> Round_repr.t option + +val predecessor_round : t -> Round_repr.t + +(**/**) + +module Internal_for_tests : sig + (** uses a lexicographic order relation for [level, locked_round, + -predecessor_round, round] *) + val compare : t -> t -> int +end diff --git a/src/proto_020_PsParisC/lib_protocol/fixed_point_repr.ml b/src/proto_020_PsParisC/lib_protocol/fixed_point_repr.ml new file mode 100644 index 000000000000..079c86443109 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/fixed_point_repr.ml @@ -0,0 +1,94 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type fp_tag (* Tag for fixed point computations *) + +type integral_tag (* Tag for integral computations *) + +module type Safe = sig + type 'a t + + type fp = fp_tag t + + type integral = integral_tag t + + val integral_exn : Z.t -> integral + + val integral_of_int_exn : int -> integral + + val integral_to_z : integral -> Z.t + + val zero : 'a t + + val add : 'a t -> 'a t -> 'a t + + val sub : 'a t -> 'a t -> 'a t + + val ceil : fp -> integral + + val floor : fp -> integral + + val fp : 'a t -> fp + + val ( = ) : 'a t -> 'b t -> bool + + val ( <> ) : 'a t -> 'b t -> bool + + val ( < ) : 'a t -> 'b t -> bool + + val ( <= ) : 'a t -> 'b t -> bool + + val ( >= ) : 'a t -> 'b t -> bool + + val ( > ) : 'a t -> 'b t -> bool + + val compare : 'a t -> 'b t -> int + + val equal : 'a t -> 'b t -> bool + + val max : 'a t -> 'a t -> 'a t + + val min : 'a t -> 'a t -> 'a t + + val pp : Format.formatter -> 'a t -> unit + + val pp_integral : Format.formatter -> integral -> unit + + val n_fp_encoding : fp Data_encoding.t + + val n_integral_encoding : integral Data_encoding.t + + val z_fp_encoding : fp Data_encoding.t + + val z_integral_encoding : integral Data_encoding.t +end + +module type Full = sig + type 'a t + + include Safe with type 'a t := 'a t + + val unsafe_fp : Z.t -> fp +end diff --git a/src/proto_020_PsParisC/lib_protocol/fixed_point_repr.mli b/src/proto_020_PsParisC/lib_protocol/fixed_point_repr.mli new file mode 100644 index 000000000000..a5f513fe4dbe --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/fixed_point_repr.mli @@ -0,0 +1,105 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines a standard signature for modules providing fixed-point + arithmetic. *) + +type fp_tag (* Tag for fixed point computations *) + +type integral_tag (* Tag for integral computations *) + +(** A signature for modules implementing a fixed-point arithmetic. + + Fixed-point types come in two flavours: + - integral (marked with [integral_tag]), behaving like integers; + - fp (marked with [fp_tag]), allowing for fractions. + + Such numbers represent standard arithmetic, rounding (converting fp + flavour to integral one) and comparisons (which can work across flavours). *) +module type Safe = sig + type 'a t + + type fp = fp_tag t + + type integral = integral_tag t + + val integral_exn : Z.t -> integral + + val integral_of_int_exn : int -> integral + + val integral_to_z : integral -> Z.t + + val zero : 'a t + + val add : 'a t -> 'a t -> 'a t + + val sub : 'a t -> 'a t -> 'a t + + val ceil : fp -> integral + + val floor : fp -> integral + + val fp : 'a t -> fp + + val ( = ) : 'a t -> 'b t -> bool + + val ( <> ) : 'a t -> 'b t -> bool + + val ( < ) : 'a t -> 'b t -> bool + + val ( <= ) : 'a t -> 'b t -> bool + + val ( >= ) : 'a t -> 'b t -> bool + + val ( > ) : 'a t -> 'b t -> bool + + val compare : 'a t -> 'b t -> int + + val equal : 'a t -> 'b t -> bool + + val max : 'a t -> 'a t -> 'a t + + val min : 'a t -> 'a t -> 'a t + + val pp : Format.formatter -> 'a t -> unit + + val pp_integral : Format.formatter -> integral -> unit + + val n_fp_encoding : fp Data_encoding.t + + val n_integral_encoding : integral Data_encoding.t + + val z_fp_encoding : fp Data_encoding.t + + val z_integral_encoding : integral Data_encoding.t +end + +module type Full = sig + type 'a t + + include Safe with type 'a t := 'a t + + val unsafe_fp : Z.t -> fp +end diff --git a/src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.ml b/src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.ml new file mode 100644 index 000000000000..b45185f28291 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.ml @@ -0,0 +1,116 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +let is_forbidden ctxt delegate = + let forbidden_delegates = Raw_context.Consensus.forbidden_delegates ctxt in + Signature.Public_key_hash.Set.mem delegate forbidden_delegates + +let forbid ctxt delegate = + let ctxt = Raw_context.Consensus.forbid_delegate ctxt delegate in + let new_forbidden_delegates = + Raw_context.Consensus.forbidden_delegates ctxt + in + Storage.Tenderbake.Forbidden_delegates.add ctxt new_forbidden_delegates + +let load ctxt = + let open Lwt_result_syntax in + let* forbidden_delegates_opt = + Storage.Tenderbake.Forbidden_delegates.find ctxt + in + let ctxt = + match forbidden_delegates_opt with + | Some forbidden_delegates -> + Raw_context.Consensus.set_forbidden_delegates ctxt forbidden_delegates + | None -> + Raw_context.Consensus.set_forbidden_delegates + ctxt + Signature.Public_key_hash.Set.empty + in + return ctxt + +let set_forbidden_delegates ctxt forbidden_delegates = + let open Lwt_syntax in + let* ctxt = + Storage.Tenderbake.Forbidden_delegates.add ctxt forbidden_delegates + in + let ctxt = + Raw_context.Consensus.set_forbidden_delegates ctxt forbidden_delegates + in + return ctxt + +let should_unforbid ctxt delegate ~selection_for_new_cycle = + let open Lwt_result_syntax in + (* A delegate who has pending denunciations for which slashing has + not been applied yet should stay forbidden, because their frozen + deposits are going to decrease by a yet unknown amount. *) + let*! has_pending_denunciations = + Pending_denunciations_storage.has_pending_denunciations ctxt delegate + in + if has_pending_denunciations then return_false + else + (* To get unforbidden, a delegate's current frozen deposits must + be high enough to insure the next cycle's baking rights. More + precisely, their [current_frozen_deposits] must at least match + [frozen], where: + + - [current_frozen_deposits] is the sum of the delegate's own + frozen funds and their stakers'; it doesn't necessarily observe + overstaking limits. + + - [frozen] is the frozen stake that was used in the past to + compute the baking rights for the new cycle. It includes past + frozen balances from the delegate and their stakers, but + excludes any overstaked funds (as enforced by + {!Stake_context.apply_limits}). *) + match + Signature.Public_key_hash.Map.find delegate selection_for_new_cycle + with + | None -> return_true + | Some {Stake_repr.frozen; _} -> + let* current_frozen_deposits = + Delegate_storage.current_frozen_deposits ctxt delegate + in + return Tez_repr.(current_frozen_deposits >= frozen) + +let update_at_cycle_end_after_slashing ctxt ~new_cycle = + let open Lwt_result_syntax in + let forbidden_delegates = Raw_context.Consensus.forbidden_delegates ctxt in + if Signature.Public_key_hash.Set.is_empty forbidden_delegates then return ctxt + else + let* selection_for_new_cycle = + Stake_storage.get_selected_distribution_as_map ctxt new_cycle + in + let* forbidden_delegates = + Signature.Public_key_hash.Set.fold_es + (fun delegate acc -> + let* should_unforbid = + should_unforbid ctxt delegate ~selection_for_new_cycle + in + if should_unforbid then + let old_forbidden = + match acc with + | `Unchanged -> forbidden_delegates + | `Changed forbidden_delegates -> forbidden_delegates + in + let new_forbidden = + Signature.Public_key_hash.Set.remove delegate old_forbidden + in + return (`Changed new_forbidden) + else return acc) + forbidden_delegates + `Unchanged + in + match forbidden_delegates with + | `Unchanged -> return ctxt + | `Changed forbidden_delegates -> + let*! ctxt = set_forbidden_delegates ctxt forbidden_delegates in + return ctxt + +let init_for_genesis ctxt = + Storage.Tenderbake.Forbidden_delegates.init + ctxt + Signature.Public_key_hash.Set.empty diff --git a/src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.mli b/src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.mli new file mode 100644 index 000000000000..9ed2747d152f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/forbidden_delegates_storage.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** This module maintains the storage related to forbidden delegates. + It is responsible for maintaining the + {!Storage.Tenderbake.Forbidden_delegates} table. +*) + +(** [is_forbidden ctxt delegate] returns [true] if the given [delegate] + is forbidden to bake or attest. *) +val is_forbidden : Raw_context.t -> Signature.Public_key_hash.t -> bool + +(** [forbid ctxt delegate] adds [delegate] to the set of forbidden + delegates. *) +val forbid : Raw_context.t -> Signature.public_key_hash -> Raw_context.t Lwt.t + +(** [load ctxt] reads from the storage the saved set of + forbidden delegates and sets the raw context's in-memory cached value. *) +val load : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Unforbids all delegates who + + - have no pending denunciations (for which slashing has yet to be + applied), and + + - have enough current frozen deposits to insure their previously + computed baking rights for [new_cycle]. + + This function should be called at the end of each cycle, after + having applied any slashings that were scheduled for the same + cycle end. *) +val update_at_cycle_end_after_slashing : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val init_for_genesis : Raw_context.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.ml b/src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.ml new file mode 100644 index 000000000000..d1c47db3e579 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.ml @@ -0,0 +1,109 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type t = + | Baker of Signature.public_key_hash + | Single_staker of { + staker : Contract_repr.t; + delegate : Signature.public_key_hash; + } + | Shared_between_stakers of {delegate : Signature.public_key_hash} + | Baker_edge of Signature.public_key_hash + +let baker pkh = Baker pkh + +let baker_edge pkh = Baker_edge pkh + +let single_staker ~staker ~delegate = + match (staker : Contract_repr.t) with + | Implicit pkh when Signature.Public_key_hash.(pkh = delegate) -> Baker pkh + | _ -> Single_staker {staker; delegate} + +let shared_between_stakers ~delegate = Shared_between_stakers {delegate} + +let encoding = + let open Data_encoding in + let single_tag = 0 in + let single_encoding = + obj2 + (req "contract" Contract_repr.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + in + let shared_tag = 1 in + let shared_encoding = + obj1 (req "delegate" Signature.Public_key_hash.encoding) + in + let baker_tag = 2 in + let baker_encoding = + obj1 (req "baker_own_stake" Signature.Public_key_hash.encoding) + in + let baker_edge_tag = 3 in + let baker_edge_encoding = + obj1 (req "baker_edge" Signature.Public_key_hash.encoding) + in + def + ~title:"frozen_staker" + ~description: + "Abstract notion of staker used in operation receipts for frozen \ + deposits, either a single staker or all the stakers delegating to some \ + delegate." + "frozen_staker" + @@ matching + (function + | Baker baker -> matched baker_tag baker_encoding baker + | Single_staker {staker; delegate} -> + matched single_tag single_encoding (staker, delegate) + | Shared_between_stakers {delegate} -> + matched shared_tag shared_encoding delegate + | Baker_edge baker -> matched baker_edge_tag baker_edge_encoding baker) + [ + case + ~title:"Single" + (Tag single_tag) + single_encoding + (function + | Single_staker {staker; delegate} -> Some (staker, delegate) + | _ -> None) + (fun (staker, delegate) -> single_staker ~staker ~delegate); + case + ~title:"Shared" + (Tag shared_tag) + shared_encoding + (function + | Shared_between_stakers {delegate} -> Some delegate | _ -> None) + (fun delegate -> Shared_between_stakers {delegate}); + case + ~title:"Baker" + (Tag baker_tag) + baker_encoding + (function Baker baker -> Some baker | _ -> None) + (fun baker -> Baker baker); + case + ~title:"Baker_edge" + (Tag baker_edge_tag) + baker_edge_encoding + (function Baker_edge baker -> Some baker | _ -> None) + (fun baker -> Baker_edge baker); + ] + +let compare sa sb = + match (sa, sb) with + | Baker ba, Baker bb -> Signature.Public_key_hash.compare ba bb + | Baker _, _ -> -1 + | _, Baker _ -> 1 + | ( Single_staker {staker = sa; delegate = da}, + Single_staker {staker = sb; delegate = db} ) -> + Compare.or_else (Contract_repr.compare sa sb) (fun () -> + Signature.Public_key_hash.compare da db) + | ( Shared_between_stakers {delegate = da}, + Shared_between_stakers {delegate = db} ) -> + Signature.Public_key_hash.compare da db + | Single_staker _, Shared_between_stakers _ -> -1 + | Shared_between_stakers _, Single_staker _ -> 1 + | Baker_edge ba, Baker_edge bb -> Signature.Public_key_hash.compare ba bb + | Baker_edge _, _ -> -1 + | _, Baker_edge _ -> 1 diff --git a/src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.mli b/src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.mli new file mode 100644 index 000000000000..5e13de5e3bad --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/frozen_staker_repr.mli @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Adding and removing stake can be done from/toward the funds + - a delegate directly stakes, + - one of its stakers stakes, + - all its stakers stakes at once, + - or from the edge a delegate may have on its stakers rewards. + We need to distinguish these cases to enforce the staking over baking + limit. *) +type t = private + | Baker of Signature.public_key_hash (** The baker itself. *) + | Single_staker of { + staker : Contract_repr.t; + delegate : Signature.public_key_hash; + } (** A single staker, cannot be the delegate. *) + | Shared_between_stakers of {delegate : Signature.public_key_hash} + (** The delegate's stakers simultaneously (delegate excluded). *) + | Baker_edge of Signature.public_key_hash + (** The baker edge over its stakers rewards. *) + +val baker : Signature.public_key_hash -> t + +val baker_edge : Signature.public_key_hash -> t + +val single_staker : + staker:Contract_repr.t -> delegate:Signature.public_key_hash -> t + +val shared_between_stakers : delegate:Signature.public_key_hash -> t + +val encoding : t Data_encoding.t + +val compare : t -> t -> int diff --git a/src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.ml b/src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.ml new file mode 100644 index 000000000000..bd4929ba1ddd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.ml @@ -0,0 +1,413 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** This module is responsible for the construction, observation and encoding of + full staking balances that are maintained to be used at cycle end to compute + staking rights. + + The module will handle a lazy migration starting at protocol P that adds two + new fields to the balance, the minimal delegated balance over the cycle and + the last level at which it has been modified. + As there is no trivial default value for Level_repr, the + level_of_min_delegated is optional but the module must preserve the + invariant that if a min_delegated_in_cycle has been stored, a level is + stored with it. +*) + +type t = { + own_frozen : Tez_repr.t; + staked_frozen : Tez_repr.t; + delegated : Tez_repr.t; + min_delegated_in_cycle : Tez_repr.t; + level_of_min_delegated : Level_repr.t option; +} + +let cycle_of_min_delegated (level_of_min_delegated : Level_repr.t option) = + match level_of_min_delegated with + | None -> Cycle_repr.root + | Some l -> l.cycle + +let init ~own_frozen ~staked_frozen ~delegated ~current_level = + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle = delegated; + level_of_min_delegated = Some current_level; + } + +let encoding = + let open Data_encoding in + (* This encoding is backward-compatible with the encoding used in Oxford, so + as to avoid a stitching in P. It will act as a lazy migration. + The case in which [added_in_p] is [None] happen only for pre-existing + values in the storage. + For them, using [(delegated, None)] and using Cycle_repr.root when no level + is set will behave correctly. *) + let added_in_p = + obj2 + (req "min_delegated_in_cycle" Tez_repr.encoding) + (req "level_of_min_delegated" (option Level_repr.encoding)) + in + conv + (fun { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } -> + ( own_frozen, + staked_frozen, + delegated, + Some (min_delegated_in_cycle, level_of_min_delegated) )) + (fun (own_frozen, staked_frozen, delegated, added_in_p_opt) -> + let min_delegated_in_cycle, level_of_min_delegated = + added_in_p_opt |> Option.value ~default:(delegated, None) + in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + }) + (obj4 + (req "own_frozen" Tez_repr.encoding) + (req "staked_frozen" Tez_repr.encoding) + (req "delegated" Tez_repr.encoding) + (varopt "min_delegated_in_cycle_and_level" added_in_p)) + +let voting_weight + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + let open Result_syntax in + let* frozen = Tez_repr.(own_frozen +? staked_frozen) in + let+ all = Tez_repr.(frozen +? delegated) in + Tez_repr.to_mutez all + +let apply_slashing ~percentage + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } = + let remaining_percentage = Percentage.neg percentage in + let own_frozen = + Tez_repr.mul_percentage ~rounding:`Down own_frozen remaining_percentage + in + let staked_frozen = + Tez_repr.mul_percentage ~rounding:`Down staked_frozen remaining_percentage + in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +let own_frozen + { + own_frozen; + staked_frozen = _; + delegated = _; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + own_frozen + +let staked_frozen + { + own_frozen = _; + staked_frozen; + delegated = _; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + staked_frozen + +let total_frozen + { + own_frozen; + staked_frozen; + delegated = _; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + Tez_repr.(own_frozen +? staked_frozen) + +let current_delegated + { + own_frozen = _; + staked_frozen = _; + delegated; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + delegated + +(* The minimum over the cycle is either: + - the current delegated value if it didn't change during the cycle, i.e. + [cycle_of_min_delegated] is not the current cycle; + - or the stored [min_delegated_in_cycle] otherwise. +*) +let min_delegated_in_cycle ~current_cycle + { + own_frozen = _; + staked_frozen = _; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } = + let cycle_of_min_delegated = cycle_of_min_delegated level_of_min_delegated in + if Cycle_repr.(cycle_of_min_delegated < current_cycle) then delegated + else ( + assert (Cycle_repr.(cycle_of_min_delegated = current_cycle)) ; + min_delegated_in_cycle) + +let current_total + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + let open Result_syntax in + let* total_frozen = Tez_repr.(own_frozen +? staked_frozen) in + Tez_repr.(total_frozen +? delegated) + +let allowed_staked_frozen ~adaptive_issuance_global_limit_of_staking_over_baking + ~delegate_limit_of_staking_over_baking_millionth + { + own_frozen; + staked_frozen; + delegated = _; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } = + let global_limit_of_staking_over_baking_millionth = + Int64.( + mul + 1_000_000L + (of_int adaptive_issuance_global_limit_of_staking_over_baking)) + in + let limit_of_staking_over_baking_millionth = + Compare.Int64.min + global_limit_of_staking_over_baking_millionth + (Int64.of_int32 delegate_limit_of_staking_over_baking_millionth) + in + match + Tez_repr.mul_ratio + ~rounding:`Down + own_frozen + ~num:limit_of_staking_over_baking_millionth + ~den:1_000_000L + with + | Ok max_allowed_staked_frozen -> + Tez_repr.min staked_frozen max_allowed_staked_frozen + | Error _max_allowed_staked_frozen_overflows -> staked_frozen + +let own_ratio ~adaptive_issuance_global_limit_of_staking_over_baking + ~delegate_limit_of_staking_over_baking_millionth + ({ + own_frozen; + staked_frozen = _; + delegated = _; + min_delegated_in_cycle = _; + level_of_min_delegated = _; + } as t) = + if Tez_repr.(own_frozen = zero) then (0L, 1L) + else + let allowed_staked_frozen = + allowed_staked_frozen + ~adaptive_issuance_global_limit_of_staking_over_baking + ~delegate_limit_of_staking_over_baking_millionth + t + in + if Tez_repr.(allowed_staked_frozen = zero) then (1L, 1L) + else + let own_frozen = Tez_repr.to_mutez own_frozen in + let allowed_staked_frozen = Tez_repr.to_mutez allowed_staked_frozen in + (own_frozen, Int64.add own_frozen allowed_staked_frozen) + +let has_minimal_frozen_stake ~minimal_frozen_stake full_staking_balance = + let own_frozen = own_frozen full_staking_balance in + Tez_repr.(own_frozen >= minimal_frozen_stake) + +(* The set of delegates to consider [Active_delegates_with_minimal_stake] is an + over-approximation of participating delegates. It is maintained by + {!Stake_storage}. + To avoid having to do any maintenance at cycle end, we have to rely on values + that do not change when crossing cycle boundaries: the current amount works, + the minimal in a given cycle wouldn't. *) +let has_minimal_stake_to_be_considered ~minimal_stake full_staking_balance = + match current_total full_staking_balance with + | Error _total_overflows -> + true + (* If the total overflows, we are definitely over the minimal stake. *) + | Ok staking_balance -> Tez_repr.(staking_balance >= minimal_stake) + +let remove_delegated ~(current_level : Level_repr.t) ~amount + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle = old_min_delegated_in_cycle; + level_of_min_delegated; + } = + let open Result_syntax in + let+ delegated = Tez_repr.(delegated -? amount) in + let cycle_of_min_delegated = cycle_of_min_delegated level_of_min_delegated in + let current_cycle = current_level.cycle in + let min_delegated_in_cycle, level_of_min_delegated = + if Cycle_repr.(cycle_of_min_delegated < current_cycle) then + (* after decrease *) (delegated, Some current_level) + else ( + assert (Cycle_repr.(cycle_of_min_delegated = current_cycle)) ; + let minimum = Tez_repr.min delegated old_min_delegated_in_cycle in + ( minimum, + if Tez_repr.(minimum = old_min_delegated_in_cycle) then + level_of_min_delegated + else Some current_level )) + in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +let remove_own_frozen ~amount + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } = + let open Result_syntax in + let+ own_frozen = Tez_repr.(own_frozen -? amount) in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +let remove_staked_frozen ~amount + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } = + let open Result_syntax in + let+ staked_frozen = Tez_repr.(staked_frozen -? amount) in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +let add_delegated ~(current_level : Level_repr.t) ~amount + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle = old_min_delegated_in_cycle; + level_of_min_delegated; + } = + let open Result_syntax in + let cycle_of_min_delegated = cycle_of_min_delegated level_of_min_delegated in + let current_cycle = current_level.cycle in + let min_delegated_in_cycle, level_of_min_delegated = + if Cycle_repr.(cycle_of_min_delegated < current_cycle) then + (* before increase *) (delegated, Some current_level) + else ( + assert (Cycle_repr.(cycle_of_min_delegated = current_cycle)) ; + (old_min_delegated_in_cycle, level_of_min_delegated)) + in + let+ delegated = Tez_repr.(delegated +? amount) in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +let add_own_frozen ~amount + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } = + let open Result_syntax in + let+ own_frozen = Tez_repr.(own_frozen +? amount) in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +let add_staked_frozen ~amount + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } = + let open Result_syntax in + let+ staked_frozen = Tez_repr.(staked_frozen +? amount) in + { + own_frozen; + staked_frozen; + delegated; + min_delegated_in_cycle; + level_of_min_delegated; + } + +module Internal_for_tests_and_RPCs = struct + let min_delegated_in_cycle + { + own_frozen = _; + staked_frozen = _; + delegated = _; + min_delegated_in_cycle; + level_of_min_delegated = _; + } = + min_delegated_in_cycle + + let level_of_min_delegated + { + own_frozen = _; + staked_frozen = _; + delegated = _; + min_delegated_in_cycle = _; + level_of_min_delegated; + } = + level_of_min_delegated +end diff --git a/src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.mli b/src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.mli new file mode 100644 index 000000000000..6c222c310f54 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/full_staking_balance_repr.mli @@ -0,0 +1,96 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type t + +val init : + own_frozen:Tez_repr.t -> + staked_frozen:Tez_repr.t -> + delegated:Tez_repr.t -> + current_level:Level_repr.t -> + t + +val encoding : t Data_encoding.t + +(** The weight of a delegate used for voting rights. *) +val voting_weight : t -> Int64.t tzresult + +val apply_slashing : percentage:Percentage.t -> t -> t + +(** The delegate's own frozen funds. *) +val own_frozen : t -> Tez_repr.t + +(** The total frozen funds from all external stakers. + + Does not take the [limit_of_staking_over_baking] into account. *) +val staked_frozen : t -> Tez_repr.t + +(** The total delegated funds from all delegators. + + Not adjusted considering overdelegation / overstaking. *) +val current_delegated : t -> Tez_repr.t + +val min_delegated_in_cycle : current_cycle:Cycle_repr.t -> t -> Tez_repr.t + +(** Sum of [own_frozen] and [staked_frozen]. *) +val total_frozen : t -> Tez_repr.t tzresult + +(** Sum of [own_frozen], [staked_frozen], and [current_delegated]. *) +val current_total : t -> Tez_repr.t tzresult + +(** The portion of {!staked_frozen} that actually counts as staking + when computing baking rights, considering both the global and the + delegate's [limit_of_staking_over_baking]. + + It is equal to the minimum of: + + - {!staked_frozen} + + - {!own_frozen} scaled by the delegate's [limit_of_staking_over_baking] + + - {!own_frozen} scaled by the global [limit_of_staking_over_baking] *) +val allowed_staked_frozen : + adaptive_issuance_global_limit_of_staking_over_baking:int -> + delegate_limit_of_staking_over_baking_millionth:int32 -> + t -> + Tez_repr.t + +(** Computes [(num, den)] representing the ratio of [own_frozen] over + [own_frozen + allowed_staked_frozen]. + + If [allowed_staked_frozen] is zero, returns [(1L, 1L)]. + + If [own_frozen] is zero, returns [(0L, 1L)]. *) +val own_ratio : + adaptive_issuance_global_limit_of_staking_over_baking:int -> + delegate_limit_of_staking_over_baking_millionth:int32 -> + t -> + int64 * int64 + +val has_minimal_frozen_stake : minimal_frozen_stake:Tez_repr.t -> t -> bool + +val has_minimal_stake_to_be_considered : minimal_stake:Tez_repr.t -> t -> bool + +val remove_delegated : + current_level:Level_repr.t -> amount:Tez_repr.t -> t -> t tzresult + +val remove_own_frozen : amount:Tez_repr.t -> t -> t tzresult + +val remove_staked_frozen : amount:Tez_repr.t -> t -> t tzresult + +val add_delegated : + current_level:Level_repr.t -> amount:Tez_repr.t -> t -> t tzresult + +val add_own_frozen : amount:Tez_repr.t -> t -> t tzresult + +val add_staked_frozen : amount:Tez_repr.t -> t -> t tzresult + +module Internal_for_tests_and_RPCs : sig + val min_delegated_in_cycle : t -> Tez_repr.t + + val level_of_min_delegated : t -> Level_repr.t option +end diff --git a/src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.ml b/src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.ml new file mode 100644 index 000000000000..1208dea6c273 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.ml @@ -0,0 +1,137 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = int + +type micheline_size = {traversal : t; int_bytes : t; string_bytes : t} + +(* ------------------------------------------------------------------------- *) +(* encoding *) + +let encoding : t Data_encoding.encoding = + let open Data_encoding in + conv (fun i -> Int64.of_int i) (fun l -> Int64.to_int l) int64 + +let micheline_size_encoding : micheline_size Data_encoding.encoding = + let open Data_encoding in + conv + (fun {traversal; int_bytes; string_bytes} -> + (traversal, int_bytes, string_bytes)) + (fun (traversal, int_bytes, string_bytes) -> + {traversal; int_bytes; string_bytes}) + (tup3 encoding encoding encoding) + +(* ------------------------------------------------------------------------- *) + +let zero = 0 + +let add = ( + ) + +let pp = Format.pp_print_int + +let pp_micheline_size fmtr {traversal; int_bytes; string_bytes} = + Format.fprintf + fmtr + "@[{ traversal = %a;@; int_bytes = %a;@; string_bytes = %a;@,}@]" + pp + traversal + pp + int_bytes + pp + string_bytes + +let to_int x = x + +let of_int x = x + +let unit : t = 1 + +let integer (i : 'a Script_int.num) : t = Z.numbits (Script_int.to_zint i) / 8 + +let string = String.length + +let script_string = Script_string.length + +let bytes (b : Bytes.t) : t = Bytes.length b + +let mutez (_tez : Alpha_context.Tez.t) : t = + (* Up to now, mutez are stored on 8 bytes (int64). *) + 8 + +let bool (_ : bool) : t = 1 + +let signature (signature : Script_typed_ir.Script_signature.t) : t = + Script_typed_ir.Script_signature.size signature + +let key_hash (_keyhash : Signature.public_key_hash) : t = + Signature.Public_key_hash.size + +let public_key (public_key : Signature.public_key) : t = + Signature.Public_key.size public_key + +let chain_id (_chain_id : Script_typed_ir.Script_chain_id.t) : t = + Script_typed_ir.Script_chain_id.size + +let address (addr : Script_typed_ir.address) : t = + let entrypoint = addr.entrypoint in + Signature.Public_key_hash.size + + String.length (Alpha_context.Entrypoint.to_string entrypoint) + +let timestamp (tstamp : Script_timestamp.t) : t = + Z.numbits (Script_timestamp.to_zint tstamp) / 8 + +let rec size_of_comparable_value : + type a. a Script_typed_ir.comparable_ty -> a -> t = + fun (type a) (wit : a Script_typed_ir.comparable_ty) (v : a) -> + match wit with + | Never_t -> ( match v with _ -> .) + | Unit_t -> unit + | Int_t -> integer v + | Nat_t -> integer v + | String_t -> script_string v + | Bytes_t -> bytes v + | Mutez_t -> mutez v + | Bool_t -> bool v + | Key_hash_t -> key_hash v + | Timestamp_t -> timestamp v + | Address_t -> address v + | Pair_t (leaf, node, _, YesYes) -> + let lv, rv = v in + let size = + size_of_comparable_value leaf lv + size_of_comparable_value node rv + in + size + 1 + | Or_t (left, right, _, YesYes) -> + let size = + match v with + | L v -> size_of_comparable_value left v + | R v -> size_of_comparable_value right v + in + size + 1 + | Option_t (ty, _, Yes) -> ( + match v with None -> 1 | Some x -> size_of_comparable_value ty x + 1) + | Signature_t -> signature v + | Key_t -> public_key v + | Chain_id_t -> chain_id v diff --git a/src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.mli b/src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.mli new file mode 100644 index 000000000000..37f974206545 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_comparable_input_size.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [Gas_input_size] includes the definitions for the different sizes used + in the gas models of the protocol. They do not always represent memory + sizes, but rather they can be seen as an information size. They are + tailored to the models that use them, and should not be used for anything + other than gas computation. + + [Gas_comparable_input_size] is the restriction of [Gas_input_size] to + comparable types. + *) + +type t = int + +type micheline_size = {traversal : t; int_bytes : t; string_bytes : t} + +(* ------------------------------------------------------------------------- *) +(* encoding *) + +val encoding : t Data_encoding.encoding + +val micheline_size_encoding : micheline_size Data_encoding.encoding + +(* ------------------------------------------------------------------------- *) + +val zero : t + +val add : t -> t -> t + +val pp : Format.formatter -> t -> unit + +val pp_micheline_size : Format.formatter -> micheline_size -> unit + +val to_int : t -> int + +val of_int : int -> t + +val integer : 'a Script_int.num -> t + +val string : string -> t + +val script_string : Script_string.t -> t + +val bytes : Bytes.t -> t + +val mutez : Alpha_context.Tez.t -> t + +val timestamp : Script_timestamp.t -> t + +val size_of_comparable_value : 'a Script_typed_ir.comparable_ty -> 'a -> t diff --git a/src/proto_020_PsParisC/lib_protocol/gas_input_size.ml b/src/proto_020_PsParisC/lib_protocol/gas_input_size.ml new file mode 100644 index 000000000000..d4105ef06ca1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_input_size.ml @@ -0,0 +1,79 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Gas_comparable_input_size + +let list (list : 'a Script_list.t) : t = list.Script_list.length + +let set (set : 'a Script_typed_ir.set) : t = + let res = Script_int.to_int (Script_set.size set) in + match res with None -> assert false | Some x -> x + +let map (map : ('a, 'b) Script_typed_ir.map) : t = + let res = Script_int.to_int (Script_map.size map) in + match res with None -> assert false | Some x -> x + +(* ------------------------------------------------------------------------- *) +(* Micheline/Michelson-related *) + +let micheline_zero = {traversal = 0; int_bytes = 0; string_bytes = 0} + +let ( ++ ) x y = + { + traversal = x.traversal + y.traversal; + int_bytes = x.int_bytes + y.int_bytes; + string_bytes = x.string_bytes + y.string_bytes; + } + +let node leaves = + let r = List.fold_left ( ++ ) micheline_zero leaves in + {r with traversal = r.traversal + 1} + +let rec of_micheline (x : ('a, 'b) Micheline.node) = + match x with + | Micheline.Int (_loc, z) -> + let int_bytes = integer (Script_int.of_zint z) in + {traversal = 1; int_bytes; string_bytes = 0} + | Micheline.String (_loc, s) -> + let string_bytes = String.length s in + {traversal = 1; int_bytes = 0; string_bytes} + | Micheline.Bytes (_loc, b) -> + let string_bytes = bytes b in + {traversal = 1; int_bytes = 0; string_bytes} + | Micheline.Prim (_loc, _prim, subterms, _annot) -> + node (List.map of_micheline subterms) + | Micheline.Seq (_loc, subterms) -> node (List.map of_micheline subterms) + +(* ------------------------------------------------------------------------- *) +(* Sapling-related *) + +let sapling_transaction_inputs : Alpha_context.Sapling.transaction -> t = + fun tx -> List.length tx.inputs + +let sapling_transaction_outputs : Alpha_context.Sapling.transaction -> t = + fun tx -> List.length tx.outputs + +let sapling_transaction_bound_data : Alpha_context.Sapling.transaction -> t = + fun tx -> String.length tx.bound_data diff --git a/src/proto_020_PsParisC/lib_protocol/gas_input_size.mli b/src/proto_020_PsParisC/lib_protocol/gas_input_size.mli new file mode 100644 index 000000000000..6d3ba74fa43f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_input_size.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [Gas_input_size] includes the definitions for the different sizes used + in the gas models of the protocol. They do not always represent memory + sizes, but rather they can be seen as an information size. They are + tailored to the models that use them, and should not be used for anything + other than gas computation. + *) + +include module type of Gas_comparable_input_size + +(* ------------------------------------------------------------------------- *) + +val list : 'a Script_list.t -> t + +val set : 'a Script_typed_ir.set -> t + +val map : ('a, 'b) Script_typed_ir.map -> t + +(* ------------------------------------------------------------------------- *) +(* Micheline/Michelson-related *) + +val of_micheline : ('a, 'b) Micheline.node -> micheline_size + +(* ------------------------------------------------------------------------- *) +(* Sapling-related *) + +val sapling_transaction_inputs : Alpha_context.Sapling.transaction -> t + +val sapling_transaction_outputs : Alpha_context.Sapling.transaction -> t + +val sapling_transaction_bound_data : Alpha_context.Sapling.transaction -> t diff --git a/src/proto_020_PsParisC/lib_protocol/gas_limit_repr.ml b/src/proto_020_PsParisC/lib_protocol/gas_limit_repr.ml new file mode 100644 index 000000000000..a6a8f428496a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_limit_repr.ml @@ -0,0 +1,239 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let decimals = 3 + +type fp_tag + +type integral_tag + +module S = Saturation_repr + +(* 1 gas unit *) +let scaling_factor = 1000 + +let mul_scaling_factor = S.mul_safe_of_int_exn scaling_factor + +module Arith = struct + type 'a t = S.may_saturate S.t + + type fp = fp_tag t + + type integral = integral_tag t + + let mul_scaling_factor = mul_scaling_factor + + let sub = S.sub + + let add = S.add + + let zero = S.zero + + let min = S.min + + let max = S.max + + let compare = S.compare + + let ( < ) = S.( < ) + + let ( <> ) = S.( <> ) + + let ( > ) = S.( > ) + + let ( <= ) = S.( <= ) + + let ( >= ) = S.( >= ) + + let ( = ) = S.( = ) + + let equal = S.equal + + let of_int_opt = S.of_int_opt + + let fatally_saturated_int i = + failwith (string_of_int i ^ " should not be saturated.") + + let fatally_saturated_z z = + failwith (Z.to_string z ^ " should not be saturated.") + + let integral_of_int_exn i = + S.( + match of_int_opt i with + | None -> fatally_saturated_int i + | Some i' -> + let r = scale_fast mul_scaling_factor i' in + if r = saturated then fatally_saturated_int i else r) + + let integral_exn z = + match Z.to_int z with + | i -> integral_of_int_exn i + | exception Z.Overflow -> fatally_saturated_z z + + let integral_to_z (i : integral) : Z.t = S.(to_z (ediv i mul_scaling_factor)) + + let ceil x = + let r = S.erem x mul_scaling_factor in + if r = zero then x else add x (sub mul_scaling_factor r) + + let floor x = sub x (S.erem x mul_scaling_factor) + + let fp x = x + + let pp fmtr fp = + let q = S.(ediv fp mul_scaling_factor |> to_int) in + let r = S.(erem fp mul_scaling_factor |> to_int) in + if Compare.Int.(r = 0) then Format.fprintf fmtr "%d" q + else Format.fprintf fmtr "%d.%0*d" q decimals r + + let pp_integral = pp + + let n_fp_encoding : fp Data_encoding.t = S.n_encoding + + let z_fp_encoding : fp Data_encoding.t = S.z_encoding + + let n_integral_encoding : integral Data_encoding.t = + Data_encoding.conv integral_to_z integral_exn Data_encoding.n + + let z_integral_encoding : integral Data_encoding.t = + Data_encoding.conv integral_to_z integral_exn Data_encoding.z + + let unsafe_fp x = + match of_int_opt (Z.to_int x) with + | Some int -> int + | None -> fatally_saturated_z x + + let sub_opt = S.sub_opt +end + +type t = Unaccounted | Limited of {remaining : Arith.fp} + +type cost = S.may_saturate S.t + +let encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Limited" + Arith.z_fp_encoding + (function Limited {remaining} -> Some remaining | _ -> None) + (fun remaining -> Limited {remaining}); + case + (Tag 1) + ~title:"Unaccounted" + (constant "unaccounted") + (function Unaccounted -> Some () | _ -> None) + (fun () -> Unaccounted); + ] + +let pp ppf = function + | Unaccounted -> Format.fprintf ppf "unaccounted" + | Limited {remaining} -> + Format.fprintf ppf "%a units remaining" Arith.pp remaining + +let cost_encoding = S.z_encoding + +let pp_cost fmt z = S.pp fmt z + +let pp_cost_as_gas fmt z = + Format.pp_print_int fmt (S.to_int (Arith.ceil z) / scaling_factor) + +(* 2 units of gas *) +let allocation_weight = + S.(mul_fast mul_scaling_factor (S.mul_safe_of_int_exn 2)) |> S.mul_safe_exn + +let step_weight = mul_scaling_factor + +(* 100 units of gas *) +let read_base_weight = + S.(mul_fast mul_scaling_factor (S.mul_safe_of_int_exn 100)) |> S.mul_safe_exn + +(* 160 units of gas *) +let write_base_weight = + S.(mul_fast mul_scaling_factor (S.mul_safe_of_int_exn 160)) |> S.mul_safe_exn + +(* 10 units of gas *) +let byte_read_weight = + S.(mul_fast mul_scaling_factor (S.mul_safe_of_int_exn 10)) |> S.mul_safe_exn + +(* 15 units of gas *) +let byte_written_weight = + S.(mul_fast mul_scaling_factor (S.mul_safe_of_int_exn 15)) |> S.mul_safe_exn + +let cost_to_milligas (cost : cost) : Arith.fp = cost + +let raw_consume gas_counter cost = + let gas = cost_to_milligas cost in + Arith.sub_opt gas_counter gas + +let alloc_cost n = + S.scale_fast allocation_weight S.(add n (S.mul_safe_of_int_exn 1)) + +let alloc_bytes_cost n = alloc_cost (S.safe_int ((n + 7) / 8)) + +let atomic_step_cost : 'a S.t -> cost = S.may_saturate + +let step_cost n = S.scale_fast step_weight n + +let free = S.zero + +let cost_of_gas (gas : 'a Arith.t) = (gas :> cost) + +let fp_of_milligas_int milligas = + (Saturation_repr.safe_int milligas :> Arith.fp) + +let read_bytes_cost n = + S.add read_base_weight (S.scale_fast byte_read_weight (S.safe_int n)) + +let write_bytes_cost n = + S.add write_base_weight (S.scale_fast byte_written_weight (S.safe_int n)) + +let ( +@ ) x y = S.add x y + +let ( *@ ) x y = S.mul x y + +let alloc_mbytes_cost n = + alloc_cost (S.mul_safe_of_int_exn 12) +@ alloc_bytes_cost n + +type error += Gas_limit_too_high (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"gas_limit_too_high" + ~title:"Gas limit out of protocol hard bounds" + ~description:"A transaction tried to exceed the hard limit on gas" + empty + (function Gas_limit_too_high -> Some () | _ -> None) + (fun () -> Gas_limit_too_high) + +let check_gas_limit ~(hard_gas_limit_per_operation : Arith.integral) + ~(gas_limit : Arith.integral) = + error_unless + Arith.(gas_limit <= hard_gas_limit_per_operation && gas_limit >= zero) + Gas_limit_too_high diff --git a/src/proto_020_PsParisC/lib_protocol/gas_limit_repr.mli b/src/proto_020_PsParisC/lib_protocol/gas_limit_repr.mli new file mode 100644 index 000000000000..891fd46f1c0b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_limit_repr.mli @@ -0,0 +1,130 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Internal representation of the gas limit available to the node baking a new + block. It should be proportional to the time and energy required to perform a + computation. + + This protects the bakers from performing exceedingly costly computations + while baking and also allows them to select cheaper-to-compute operations to + include in their blocks, as their reward for baking a block is not directly + related to the resources consumed by the machine performing the operation. + + It can be [Unaccounted] (unlimited) or [Limited] to some fixed-point value + (see [Fixed_point_repr] for the details). The value is represented with 3 + decimal places of precision. + + All computations on gas are performed in saturation arithmetic (see + [Saturation_repr]) bounded between [0] and [2 ^ 62 - 1]*) + +module Arith : + Fixed_point_repr.Full + with type 'a t = private Saturation_repr.may_saturate Saturation_repr.t + +type t = Unaccounted | Limited of {remaining : Arith.fp} + +val encoding : t Data_encoding.encoding + +val pp : Format.formatter -> t -> unit + +(** Represents a gas cost of an operation. The gas model is constructed such + that the cost of each operation is roughly proportional to the time required + to perform the operation. If the gas cost of an operation exceeds the + available limit, such an operation is rejected. This is especially meant to + protect bakers against DoS attacks. *) +type cost = Saturation_repr.may_saturate Saturation_repr.t + +val cost_encoding : cost Data_encoding.encoding + +val pp_cost : Format.formatter -> cost -> unit + +(** Print the gas cost as gas unit *) +val pp_cost_as_gas : Format.formatter -> cost -> unit + +(** Subtracts the cost from the current limit. Returns [None] if the limit + would fall below [0]. *) +val raw_consume : Arith.fp -> cost -> Arith.fp option + +(** The cost of free operation is [0]. *) +val free : cost + +(** Convert a fixed-point amount of gas to a cost. *) +val cost_of_gas : 'a Arith.t -> cost + +(** Convert an amount of milligas expressed as a value of type [int] to [Arith.fp]. *) +val fp_of_milligas_int : int -> Arith.fp + +(** [atomic_step_cost x] corresponds to [x] milliunit of gas. *) +val atomic_step_cost : _ Saturation_repr.t -> cost + +(** [step_cost x] corresponds to [x] units of gas. *) +val step_cost : _ Saturation_repr.t -> cost + +(** Cost of allocating qwords of storage. + + [alloc_cost n] estimates the cost of allocating [n] qwords of storage. *) +val alloc_cost : _ Saturation_repr.t -> cost + +(** Cost of allocating bytes in the storage. + + [alloc_bytes_cost b] estimates the cost of allocating [b] bytes of + storage. *) +val alloc_bytes_cost : int -> cost + +(** Cost of allocating bytes in the storage. + + [alloc_mbytes_cost b] estimates the cost of allocating [b] bytes of + storage and the cost of a header to describe these bytes. *) +val alloc_mbytes_cost : int -> cost + +(** Cost of reading the storage. + + [read_bytes_const n] estimates the cost of reading [n] bytes of storage. *) +val read_bytes_cost : int -> cost + +(** Cost of writing to storage. + + [write_bytes_const n] estimates the cost of writing [n] bytes to the + storage. *) +val write_bytes_cost : int -> cost + +(** Multiply a cost by a factor. Both arguments are saturated arithmetic values, + so no negative numbers are involved. *) +val ( *@ ) : _ Saturation_repr.t -> cost -> cost + +(** Add two costs together. *) +val ( +@ ) : cost -> cost -> cost + +(** Ill-formed [gas_limit]: see {!check_gas_limit}. *) +type error += Gas_limit_too_high (* `Permanent *) + +(** Check that [gas_limit] is well-formed, i.e. it is at most the + given [hard_gas_limit_per_operation], and it is nonnegative. + + @return [Error Gas_limit_too_high] otherwise. *) +val check_gas_limit : + hard_gas_limit_per_operation:Arith.integral -> + gas_limit:'a Arith.t -> + unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/gas_monad.ml b/src/proto_020_PsParisC/lib_protocol/gas_monad.ml new file mode 100644 index 000000000000..2938a881e457 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_monad.ml @@ -0,0 +1,127 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(* The outer option is for gas exhaustion. The inner [result] is for all other + errors. *) +type ('a, 'trace) t = + Local_gas_counter.local_gas_counter -> + (('a, 'trace) result * Local_gas_counter.local_gas_counter) option + +type ('a, 'trace) gas_monad = ('a, 'trace) t + +let of_result x gas = Some (x, gas) [@@ocaml.inline always] + +let return x = of_result (Ok x) [@@ocaml.inline always] + +let return_unit = return () + +(* Inlined [Option.bind] for performance. *) +let ( >>?? ) m f = match m with None -> None | Some x -> f x + [@@ocaml.inline always] + +let bind m f gas = + m gas >>?? fun (res, gas) -> + match res with Ok y -> f y gas | Error _ as err -> of_result err gas + [@@ocaml.inline always] + +let map f m gas = + let open Result_syntax in + m gas >>?? fun (x, gas) -> + of_result + (let+ x in + f x) + gas + [@@ocaml.inline always] + +let bind_result m f = bind (of_result m) f [@@ocaml.inline always] + +let bind_recover m f gas = m gas >>?? fun (x, gas) -> f x gas + [@@ocaml.inline always] + +let consume_gas cost gas = + match Local_gas_counter.consume_opt gas cost with + | None -> None + | Some gas -> Some (Ok (), gas) + +let run ctxt m = + let open Local_gas_counter in + let open Result_syntax in + match Gas.level ctxt with + | Gas.Unaccounted -> ( + match m (Local_gas_counter (Saturation_repr.saturated :> int)) with + | Some (res, _new_gas_counter) -> return (res, ctxt) + | None -> tzfail Gas.Operation_quota_exceeded) + | Limited {remaining = _} -> ( + let gas_counter, outdated_ctxt = + local_gas_counter_and_outdated_context ctxt + in + match m gas_counter with + | Some (res, new_gas_counter) -> + let ctxt = update_context new_gas_counter outdated_ctxt in + return (res, ctxt) + | None -> tzfail Gas.Operation_quota_exceeded) + +let record_trace_eval : + type error_trace error_context. + error_details:(error_context, error_trace) Script_tc_errors.error_details -> + (error_context -> error) -> + ('a, error_trace) t -> + ('a, error_trace) t = + fun ~error_details -> + match error_details with + | Fast -> fun _f m -> m + | Informative err_ctxt -> + fun f m gas -> + m gas >>?? fun (x, gas) -> + of_result (record_trace_eval (fun () -> f err_ctxt) x) gas + +let fail e = of_result (Error e) [@@ocaml.inline always] + +module Syntax = struct + let return = return + + let return_unit = return_unit + + let return_none = return None + + let return_some x = return (Some x) + + let return_nil = return [] + + let return_true = return true + + let return_false = return false + + let fail = fail + + let ( let* ) = bind + + let ( let+ ) m f = map f m + + let ( let*? ) = bind_result +end diff --git a/src/proto_020_PsParisC/lib_protocol/gas_monad.mli b/src/proto_020_PsParisC/lib_protocol/gas_monad.mli new file mode 100644 index 000000000000..5ee666d3e049 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_monad.mli @@ -0,0 +1,120 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This monad combines: + - a state monad where the state is the context + - two levels of error monad to distinguish gas exhaustion from other errors + + It is useful for backtracking on type checking errors without backtracking + the consumed gas. +*) +type ('a, 'trace) t + +(** Alias of [('a, 'trace) t] to avoid confusion when the module is open *) +type ('a, 'trace) gas_monad = ('a, 'trace) t + +(** [return x] returns a value in the gas-monad. *) +val return : 'a -> ('a, 'trace) t + +(** [map f m] maps over successful results of [m] using [f]. *) +val map : ('a -> 'b) -> ('a, 'trace) t -> ('b, 'trace) t + +(** [bind m f] binds successful results of [m] and feeds it to [f]. *) +val bind : ('a, 'trace) t -> ('a -> ('b, 'trace) t) -> ('b, 'trace) t + +(** [bind_recover m f] binds the result of [m] and feeds it to [f]. It's another + variant of [bind] that allows recovery from inner errors. *) +val bind_recover : + ('a, 'trace) t -> (('a, 'trace) result -> ('b, 'trace') t) -> ('b, 'trace') t + +(** [of_result r] is a gas-free embedding of the result [r] into the gas monad. *) +val of_result : ('a, 'trace) result -> ('a, 'trace) t + +(** [consume_gas c] consumes c amounts of gas. It's a wrapper around + [Gas.consume]. If that fails, the whole computation within the gas-monad + returns an error. See the {!Alpha_context.Gas} module for details.*) +val consume_gas : Alpha_context.Gas.cost -> (unit, 'trace) t + +(** [run ctxt m] runs [m] using the given context and returns the + result along with the new context with updated gas. If the given + context has [unlimited] mode enabled, through [Gas.set_unlimited], + no gas is consumed. *) +val run : + Alpha_context.context -> + ('a, 'trace) t -> + (('a, 'trace) result * Alpha_context.context) tzresult + +(** [record_trace_level ~error_details f m] returns a new gas-monad value that + when run, records trace levels using [f]. This function has no effect in + the case of a gas-exhaustion error or if [error_details] is [Fast]. *) +val record_trace_eval : + error_details:('error_context, 'error_trace) Script_tc_errors.error_details -> + ('error_context -> error) -> + ('a, 'error_trace) t -> + ('a, 'error_trace) t + +(** [fail e] is [return (Error e)] . *) +val fail : 'trace -> ('a, 'trace) t + +(** Syntax module for the {!Gas_monad}. This is intended to be opened locally in + functions. Within the scope of this module, the code can include binding + operators, leading to a [let]-style syntax. Similar to {!Lwt_result_syntax} + and other syntax modules. *) +module Syntax : sig + (** [return x] returns a value in the gas-monad. *) + val return : 'a -> ('a, 'trace) t + + (** [return_unit] is [return ()] . *) + val return_unit : (unit, 'trace) t + + (** [return_none] is [return None] . *) + val return_none : ('a option, 'trace) t + + (** [return_some x] is [return (Some x)] . *) + val return_some : 'a -> ('a option, 'trace) t + + (** [return_nil] is [return []] . *) + val return_nil : ('a list, 'trace) t + + (** [return_true] is [return true] . *) + val return_true : (bool, 'trace) t + + (** [return_false] is [return false] . *) + val return_false : (bool, 'trace) t + + (** [fail e] is [return (Error e)] . *) + val fail : 'trace -> ('a, 'trace) t + + (** [let*] is a binding operator alias for {!bind}. *) + val ( let* ) : ('a, 'trace) t -> ('a -> ('b, 'trace) t) -> ('b, 'trace) t + + (** [let+] is a binding operator alias for {!map}. *) + val ( let+ ) : ('a, 'trace) t -> ('a -> 'b) -> ('b, 'trace) t + + (** [let*?] is for binding the value from result-only expressions into the + gas-monad. *) + val ( let*? ) : + ('a, 'trace) result -> ('a -> ('b, 'trace) t) -> ('b, 'trace) t +end diff --git a/src/proto_020_PsParisC/lib_protocol/gas_parameters.json b/src/proto_020_PsParisC/lib_protocol/gas_parameters.json new file mode 100644 index 000000000000..67efe78dae4d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/gas_parameters.json @@ -0,0 +1,729 @@ +{ + "map": { + "bloomer/bloomer_add_const": 461.4500000000014, + "bloomer/bloomer_mem_const": 423.9300000000017, + "builtin/Timer_latency": 15.82333333333333, + "cache/CACHE_UPDATE/coeff": 43, + "cache/CACHE_UPDATE/intercept": 600, + "carbonated_map/compare_int": 2.183333333333339, + "carbonated_map/find/intercept": 50, + "carbonated_map/find/traversal_overhead": 2, + "carbonated_map/fold_const": 50, + "carbonated_map/fold_cost_per_item": 24, + "dal/publish_commitment_const": 1160000, + "encoding/B58CHECK_DECODING_CHAIN_ID_const": 1600, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_bls_const": 3600, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519_const": 3300, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_p256_const": 3300, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1_const": 3300, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_bls_const": 79000, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_ed25519_const": 4200, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_p256_const": 13450, + "encoding/B58CHECK_DECODING_PUBLIC_KEY_secp256k1_const": 9000, + "encoding/B58CHECK_DECODING_SECRET_KEY_bls_const": 4397.749999999982, + "encoding/B58CHECK_DECODING_SECRET_KEY_ed25519_const": 3953.750000000009, + "encoding/B58CHECK_DECODING_SECRET_KEY_p256_const": 3756.466666666679, + "encoding/B58CHECK_DECODING_SECRET_KEY_secp256k1_const": 3924.773333333343, + "encoding/B58CHECK_DECODING_SIGNATURE_bls_const": 6400, + "encoding/B58CHECK_DECODING_SIGNATURE_ed25519_const": 6400, + "encoding/B58CHECK_DECODING_SIGNATURE_p256_const": 6400, + "encoding/B58CHECK_DECODING_SIGNATURE_secp256k1_const": 6400, + "encoding/B58CHECK_ENCODING_CHAIN_ID_const": 1800, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_bls_const": 3200, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519_const": 3200, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256_const": 3200, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1_const": 3200, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_bls_const": 5900, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_ed25519_const": 4500, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_p256_const": 4550, + "encoding/B58CHECK_ENCODING_PUBLIC_KEY_secp256k1_const": 4950, + "encoding/B58CHECK_ENCODING_SECRET_KEY_bls_const": 3996.54000000001, + "encoding/B58CHECK_ENCODING_SECRET_KEY_ed25519_const": 4029.473333333342, + "encoding/B58CHECK_ENCODING_SECRET_KEY_p256_const": 4035.320000000008, + "encoding/B58CHECK_ENCODING_SECRET_KEY_secp256k1_const": 4440.856666666648, + "encoding/B58CHECK_ENCODING_SIGNATURE_bls_const": 8300, + "encoding/B58CHECK_ENCODING_SIGNATURE_ed25519_const": 8300, + "encoding/B58CHECK_ENCODING_SIGNATURE_p256_const": 8300, + "encoding/B58CHECK_ENCODING_SIGNATURE_secp256k1_const": 8300, + "encoding/BLS_FR_FROM_Z_const": 178.443333333333, + "encoding/BLS_FR_TO_Z_const": 82.89333333333309, + "encoding/CHECK_PRINTABLE_coeff": 10, + "encoding/CHECK_PRINTABLE_const": 14, + "encoding/DECODING_BLS_FR_const": 120, + "encoding/DECODING_BLS_G1_const": 54600, + "encoding/DECODING_BLS_G2_const": 69000, + "encoding/DECODING_CHAIN_ID_const": 50, + "encoding/DECODING_Chest_coeff": 0.03125, + "encoding/DECODING_Chest_const": 3750, + "encoding/DECODING_Chest_key_const": 9550, + "encoding/DECODING_INT_coeff": 13.31369369965978, + "encoding/DECODING_INT_const": 15.80000000000003, + "encoding/DECODING_MICHELINE_micheline_bytes": 20, + "encoding/DECODING_MICHELINE_micheline_int_bytes": 10, + "encoding/DECODING_MICHELINE_micheline_string_bytes": 10, + "encoding/DECODING_MICHELINE_micheline_traversal": 60, + "encoding/DECODING_NAT_coeff": 13.27753944359873, + "encoding/DECODING_NAT_const": 15.77000000000003, + "encoding/DECODING_PUBLIC_KEY_HASH_bls_const": 60, + "encoding/DECODING_PUBLIC_KEY_HASH_ed25519_const": 60, + "encoding/DECODING_PUBLIC_KEY_HASH_p256_const": 60, + "encoding/DECODING_PUBLIC_KEY_HASH_secp256k1_const": 60, + "encoding/DECODING_PUBLIC_KEY_bls_const": 74000, + "encoding/DECODING_PUBLIC_KEY_ed25519_const": 60, + "encoding/DECODING_PUBLIC_KEY_p256_const": 9550, + "encoding/DECODING_PUBLIC_KEY_secp256k1_const": 4900, + "encoding/DECODING_SECRET_KEY_bls_const": 204.2166666666664, + "encoding/DECODING_SECRET_KEY_ed25519_const": 63.93666666666646, + "encoding/DECODING_SECRET_KEY_p256_const": 77.66999999999977, + "encoding/DECODING_SECRET_KEY_secp256k1_const": 260.8766666666663, + "encoding/DECODING_SIGNATURE_bls_const": 40, + "encoding/DECODING_SIGNATURE_ed25519_const": 35, + "encoding/DECODING_SIGNATURE_p256_const": 35, + "encoding/DECODING_SIGNATURE_secp256k1_const": 35, + "encoding/DECODING_STRING_LIST_ADVERSARIAL_coeff": 16.62863595418259, + "encoding/DECODING_STRING_LIST_ADVERSARIAL_const": 0, + "encoding/DECODING_STRING_coeff": 0.05743526369887405, + "encoding/DECODING_STRING_const": 0, + "encoding/ENCODING_BLS_FR_const": 80, + "encoding/ENCODING_BLS_G1_const": 3200, + "encoding/ENCODING_BLS_G2_const": 3900, + "encoding/ENCODING_CHAIN_ID_const": 50, + "encoding/ENCODING_Chest_coeff": 0.09375, + "encoding/ENCODING_Chest_const": 6250, + "encoding/ENCODING_Chest_key_const": 15900, + "encoding/ENCODING_INT_coeff": 23.82659459342325, + "encoding/ENCODING_INT_const": 0, + "encoding/ENCODING_MICHELINE_micheline_bytes": 33, + "encoding/ENCODING_MICHELINE_micheline_int_bytes": 25, + "encoding/ENCODING_MICHELINE_micheline_string_bytes": 10, + "encoding/ENCODING_MICHELINE_micheline_traversal": 100, + "encoding/ENCODING_NAT_coeff": 23.4173929891917, + "encoding/ENCODING_NAT_const": 0, + "encoding/ENCODING_PUBLIC_KEY_HASH_bls_const": 80, + "encoding/ENCODING_PUBLIC_KEY_HASH_ed25519_const": 70, + "encoding/ENCODING_PUBLIC_KEY_HASH_p256_const": 70, + "encoding/ENCODING_PUBLIC_KEY_HASH_secp256k1_const": 70, + "encoding/ENCODING_PUBLIC_KEY_bls_const": 90, + "encoding/ENCODING_PUBLIC_KEY_ed25519_const": 80, + "encoding/ENCODING_PUBLIC_KEY_p256_const": 90, + "encoding/ENCODING_PUBLIC_KEY_secp256k1_const": 455, + "encoding/ENCODING_SECRET_KEY_bls_const": 72.52999999999977, + "encoding/ENCODING_SECRET_KEY_ed25519_const": 68.05999999999977, + "encoding/ENCODING_SECRET_KEY_p256_const": 72.35666666666644, + "encoding/ENCODING_SECRET_KEY_secp256k1_const": 67.53999999999978, + "encoding/ENCODING_SIGNATURE_bls_const": 55, + "encoding/ENCODING_SIGNATURE_ed25519_const": 45, + "encoding/ENCODING_SIGNATURE_p256_const": 45, + "encoding/ENCODING_SIGNATURE_secp256k1_const": 45, + "encoding/ENCODING_STRING_LIST_ADVERSARIAL_coeff": 8.42552074286036, + "encoding/ENCODING_STRING_LIST_ADVERSARIAL_const": 0, + "encoding/ENCODING_STRING_coeff": 0.126023131482347, + "encoding/ENCODING_STRING_const": 0, + "encoding/TIMESTAMP_READABLE_DECODING_coeff": 0.046875, + "encoding/TIMESTAMP_READABLE_DECODING_const": 105, + "encoding/TIMESTAMP_READABLE_ENCODING_const": 820, + "global_constants_storage/Script_expr_hash_of_b58check_opt/coeff": 0, + "global_constants_storage/Script_expr_hash_of_b58check_opt/intercept": 3171.423333333345, + "global_constants_storage/Set_add/coeff": 6.44399585036958, + "global_constants_storage/Set_elements/coeff": 3.273052670053711, + "global_constants_storage/expand_constant_branch/coeff": 4095, + "global_constants_storage/expand_no_constant_branch/coeff": 4.639474, + "global_constants_storage/expand_no_constant_branch/intercept": 100, + "global_constants_storage/expr_to_address_in_context/coeff": 1.25, + "interpreter/N_IAbs_int_alloc_coeff": 0.5002108452897347, + "interpreter/N_IAbs_int_alloc_const": 14.95234896451996, + "interpreter/N_IAbs_int_coeff": 0.5, + "interpreter/N_IAbs_int_const": 20, + "interpreter/N_IAdd_bls12_381_fr_alloc_const": 24, + "interpreter/N_IAdd_bls12_381_fr_const": 30, + "interpreter/N_IAdd_bls12_381_g1_alloc_const": 80, + "interpreter/N_IAdd_bls12_381_g1_const": 900, + "interpreter/N_IAdd_bls12_381_g2_alloc_const": 152, + "interpreter/N_IAdd_bls12_381_g2_const": 2470, + "interpreter/N_IAdd_int_alloc_coeff": 0.5002118599278188, + "interpreter/N_IAdd_int_alloc_const": 16.63713679538432, + "interpreter/N_IAdd_int_coeff": 0.5, + "interpreter/N_IAdd_int_const": 35, + "interpreter/N_IAdd_nat_alloc_coeff": 0.5002397432244102, + "interpreter/N_IAdd_nat_alloc_const": 17.7896408260724, + "interpreter/N_IAdd_nat_coeff": 0.5, + "interpreter/N_IAdd_nat_const": 35, + "interpreter/N_IAdd_seconds_to_timestamp_alloc_coeff": 0.5002118599278188, + "interpreter/N_IAdd_seconds_to_timestamp_alloc_const": 16.63713679538432, + "interpreter/N_IAdd_seconds_to_timestamp_coeff": 0.5, + "interpreter/N_IAdd_seconds_to_timestamp_const": 35, + "interpreter/N_IAdd_tez_alloc_const": 12, + "interpreter/N_IAdd_tez_const": 20, + "interpreter/N_IAdd_timestamp_to_seconds_alloc_coeff": 0.5002118599278188, + "interpreter/N_IAdd_timestamp_to_seconds_alloc_const": 16.63713679538432, + "interpreter/N_IAdd_timestamp_to_seconds_coeff": 0.5, + "interpreter/N_IAdd_timestamp_to_seconds_const": 35, + "interpreter/N_IAddress_alloc_const": 28, + "interpreter/N_IAddress_const": 10, + "interpreter/N_IAmount_alloc_const": 12, + "interpreter/N_IAmount_const": 10, + "interpreter/N_IAnd_alloc_const": 0, + "interpreter/N_IAnd_bytes_alloc_coeff": 0.4999723338027118, + "interpreter/N_IAnd_bytes_alloc_const": 11.0284526199539, + "interpreter/N_IAnd_bytes_coeff": 0.5, + "interpreter/N_IAnd_bytes_const": 35, + "interpreter/N_IAnd_const": 10, + "interpreter/N_IAnd_int_nat_alloc_coeff": 0.500213721395802, + "interpreter/N_IAnd_int_nat_alloc_const": 15.96580457667167, + "interpreter/N_IAnd_int_nat_coeff": 0.5, + "interpreter/N_IAnd_int_nat_const": 35, + "interpreter/N_IAnd_nat_alloc_coeff": 0.5002945009499573, + "interpreter/N_IAnd_nat_alloc_const": 15.92931977201025, + "interpreter/N_IAnd_nat_coeff": 0.5, + "interpreter/N_IAnd_nat_const": 35, + "interpreter/N_IApply_alloc_lam": 225.986577181208, + "interpreter/N_IApply_alloc_lamrec": 510.0132450331126, + "interpreter/N_IApply_lam": 140, + "interpreter/N_IApply_lamrec": 220, + "interpreter/N_IBalance_alloc_const": 12, + "interpreter/N_IBalance_const": 10, + "interpreter/N_IBig_map_get_alloc_const": 0, + "interpreter/N_IBig_map_get_and_update_alloc_coeff": 25.08466945297817, + "interpreter/N_IBig_map_get_and_update_alloc_const": 178.0352184252903, + "interpreter/N_IBig_map_get_and_update_coeff": 2.842646848581943, + "interpreter/N_IBig_map_get_and_update_const": 834.6338760079894, + "interpreter/N_IBig_map_get_coeff": 2.843415644317873, + "interpreter/N_IBig_map_get_const": 822.9305426746561, + "interpreter/N_IBig_map_mem_alloc_const": 0, + "interpreter/N_IBig_map_mem_coeff": 2.843652859797409, + "interpreter/N_IBig_map_mem_const": 824.7038760079895, + "interpreter/N_IBig_map_update_alloc_coeff": 25.08466945297817, + "interpreter/N_IBig_map_update_alloc_const": 166.0352184252903, + "interpreter/N_IBig_map_update_coeff": 3.161812799978645, + "interpreter/N_IBig_map_update_const": 816.0205426746561, + "interpreter/N_IBlake2b_alloc_const": 24, + "interpreter/N_IBlake2b_coeff": 1.125, + "interpreter/N_IBlake2b_const": 430, + "interpreter/N_IBytes_int_alloc_coeff": 0.4995024397671235, + "interpreter/N_IBytes_int_alloc_const": 10.39023132469788, + "interpreter/N_IBytes_int_coeff": 3, + "interpreter/N_IBytes_int_const": 90, + "interpreter/N_IBytes_nat_alloc_coeff": 0.4994352860923315, + "interpreter/N_IBytes_nat_alloc_const": 10.73118464919844, + "interpreter/N_IBytes_nat_coeff": 3, + "interpreter/N_IBytes_nat_const": 75, + "interpreter/N_IBytes_size_alloc_const": 0, + "interpreter/N_IBytes_size_const": 10, + "interpreter/N_ICar_alloc_const": 0, + "interpreter/N_ICar_const": 10, + "interpreter/N_ICdr_alloc_const": 0, + "interpreter/N_ICdr_const": 10, + "interpreter/N_IChainId_alloc_const": 20, + "interpreter/N_IChainId_const": 15, + "interpreter/N_ICheck_signature_bls_alloc_const": 0, + "interpreter/N_ICheck_signature_bls_coeff": 3, + "interpreter/N_ICheck_signature_bls_const": 1570000, + "interpreter/N_ICheck_signature_ed25519_alloc_const": 0, + "interpreter/N_ICheck_signature_ed25519_coeff": 1.125, + "interpreter/N_ICheck_signature_ed25519_const": 65800, + "interpreter/N_ICheck_signature_p256_alloc_const": 0, + "interpreter/N_ICheck_signature_p256_coeff": 1.125, + "interpreter/N_ICheck_signature_p256_const": 341000, + "interpreter/N_ICheck_signature_secp256k1_alloc_const": 0, + "interpreter/N_ICheck_signature_secp256k1_coeff": 1.125, + "interpreter/N_ICheck_signature_secp256k1_const": 51600, + "interpreter/N_IComb_alloc_coeff": 11.98235521489165, + "interpreter/N_IComb_alloc_const": 5.609495538132251, + "interpreter/N_IComb_coeff": 3.25, + "interpreter/N_IComb_const": 40, + "interpreter/N_IComb_get_alloc_coeff": 0, + "interpreter/N_IComb_get_alloc_const": 0, + "interpreter/N_IComb_get_coeff": 0.5625, + "interpreter/N_IComb_get_const": 20, + "interpreter/N_IComb_set_alloc_coeff": 6.006842112454512, + "interpreter/N_IComb_set_alloc_const": 5.979473662636465, + "interpreter/N_IComb_set_coeff": 1.28125, + "interpreter/N_IComb_set_const": 30, + "interpreter/N_ICompare_alloc_const": 0, + "interpreter/N_ICompare_coeff": 0.0234375, + "interpreter/N_ICompare_const": 35, + "interpreter/N_IConcat_bytes_alloc_const": 8.000026228575734, + "interpreter/N_IConcat_bytes_alloc_list_length": 0.4999999997438616, + "interpreter/N_IConcat_bytes_alloc_total_bytes": 0, + "interpreter/N_IConcat_bytes_const": 31.02720934132395, + "interpreter/N_IConcat_bytes_list_length": 0.08531904945967994, + "interpreter/N_IConcat_bytes_pair_alloc_coeff": 0.4999997615814209, + "interpreter/N_IConcat_bytes_pair_alloc_const": 8.00048828125, + "interpreter/N_IConcat_bytes_pair_coeff": 0.5, + "interpreter/N_IConcat_bytes_pair_const": 45, + "interpreter/N_IConcat_bytes_total_bytes": 0, + "interpreter/N_IConcat_string_alloc_const": 6.826297514415273, + "interpreter/N_IConcat_string_alloc_list_length": 0.5001146193833579, + "interpreter/N_IConcat_string_alloc_total_bytes": 0, + "interpreter/N_IConcat_string_const": 33.83720934132398, + "interpreter/N_IConcat_string_list_length": 0.08972387550704279, + "interpreter/N_IConcat_string_pair_alloc_coeff": 0.4999997615814209, + "interpreter/N_IConcat_string_pair_alloc_const": 8.00048828125, + "interpreter/N_IConcat_string_pair_coeff": 0.5, + "interpreter/N_IConcat_string_pair_const": 45, + "interpreter/N_IConcat_string_total_bytes": 0, + "interpreter/N_ICons_list_alloc_const": 24, + "interpreter/N_ICons_list_const": 10, + "interpreter/N_ICons_none_alloc_const": 12, + "interpreter/N_ICons_none_const": 10, + "interpreter/N_ICons_pair_alloc_const": 12, + "interpreter/N_ICons_pair_const": 10, + "interpreter/N_ICons_some_alloc_const": 8, + "interpreter/N_ICons_some_const": 10, + "interpreter/N_IContract_alloc_const": 16, + "interpreter/N_IContract_const": 30, + "interpreter/N_ICreate_contract_alloc_const": 196, + "interpreter/N_ICreate_contract_const": 60, + "interpreter/N_IDiff_timestamps_alloc_coeff": 0.5002119258364551, + "interpreter/N_IDiff_timestamps_alloc_const": 17.55013733057876, + "interpreter/N_IDiff_timestamps_coeff": 0.5, + "interpreter/N_IDiff_timestamps_const": 35, + "interpreter/N_IDig_alloc_coeff": 12.00596601704986, + "interpreter/N_IDig_alloc_const": 11.97613593180057, + "interpreter/N_IDig_coeff": 6.75, + "interpreter/N_IDig_const": 30, + "interpreter/N_IDipN_alloc_coeff": 11.99999721456731, + "interpreter/N_IDipN_alloc_const": 0.002835570476236171, + "interpreter/N_IDipN_coeff": 4, + "interpreter/N_IDipN_const": 15, + "interpreter/N_IDip_alloc_const": 0, + "interpreter/N_IDip_const": 10, + "interpreter/N_IDropN_alloc_coeff1": 0, + "interpreter/N_IDropN_alloc_coeff2": 0, + "interpreter/N_IDropN_alloc_coeff3": 0, + "interpreter/N_IDropN_alloc_const": 0, + "interpreter/N_IDropN_coeff1": 2.625, + "interpreter/N_IDropN_coeff2": 8.741624784215688, + "interpreter/N_IDropN_coeff3": 3.269942503929978, + "interpreter/N_IDropN_const": 30, + "interpreter/N_IDrop_alloc_const": 0, + "interpreter/N_IDrop_const": 10, + "interpreter/N_IDug_alloc_coeff": 12.00596601704986, + "interpreter/N_IDug_alloc_const": 11.97613593180057, + "interpreter/N_IDug_coeff": 6.75, + "interpreter/N_IDug_const": 35, + "interpreter/N_IDupN_alloc_coeff1": 0, + "interpreter/N_IDupN_alloc_coeff2": 0, + "interpreter/N_IDupN_alloc_coeff3": 0, + "interpreter/N_IDupN_alloc_const": 12, + "interpreter/N_IDupN_coeff1": 1.25, + "interpreter/N_IDupN_coeff2": 4.809443771596645, + "interpreter/N_IDupN_coeff3": 2.137595916463435, + "interpreter/N_IDupN_const": 20, + "interpreter/N_IDup_alloc_const": 12, + "interpreter/N_IDup_const": 10, + "interpreter/N_IEdiv_int_alloc_coeff": 0.5005722593934798, + "interpreter/N_IEdiv_int_alloc_const": 47.51671862136573, + "interpreter/N_IEdiv_int_const": 150, + "interpreter/N_IEdiv_int_q_coeff": 12, + "interpreter/N_IEdiv_int_q_size2_coeff": 0.0010986328125, + "interpreter/N_IEdiv_int_size1_coeff": 1.25, + "interpreter/N_IEdiv_nat_alloc_coeff1": 0.5006673159746435, + "interpreter/N_IEdiv_nat_alloc_coeff2": 0, + "interpreter/N_IEdiv_nat_alloc_const": 40.69299812563986, + "interpreter/N_IEdiv_nat_const": 150, + "interpreter/N_IEdiv_nat_q_coeff": 12, + "interpreter/N_IEdiv_nat_q_size2_coeff": 0.0010986328125, + "interpreter/N_IEdiv_nat_size1_coeff": 1.25, + "interpreter/N_IEdiv_tez_alloc_const": 32, + "interpreter/N_IEdiv_tez_const": 80, + "interpreter/N_IEdiv_teznat_alloc_const": 44, + "interpreter/N_IEdiv_teznat_const": 70, + "interpreter/N_IEmit_alloc_const": 124, + "interpreter/N_IEmit_const": 30, + "interpreter/N_IEmpty_big_map_alloc_const": 44, + "interpreter/N_IEmpty_big_map_const": 300, + "interpreter/N_IEmpty_map_alloc_const": 248, + "interpreter/N_IEmpty_map_const": 300, + "interpreter/N_IEmpty_set_alloc_const": 184, + "interpreter/N_IEmpty_set_const": 300, + "interpreter/N_IEq_alloc_const": 0, + "interpreter/N_IEq_const": 10, + "interpreter/N_IExec_alloc_const": 0, + "interpreter/N_IExec_const": 10, + "interpreter/N_IFailwith_alloc_const": 0, + "interpreter/N_IFailwith_const": 167.4551906586758, + "interpreter/N_IGe_alloc_const": 0, + "interpreter/N_IGe_const": 10, + "interpreter/N_IGt_alloc_const": 0, + "interpreter/N_IGt_const": 10, + "interpreter/N_IHalt_alloc_const": 0, + "interpreter/N_IHalt_const": 15, + "interpreter/N_IHash_key_alloc_const": 32, + "interpreter/N_IHash_key_const": 605, + "interpreter/N_IIf_alloc_const": 0, + "interpreter/N_IIf_cons_alloc_const": 0, + "interpreter/N_IIf_cons_const": 10, + "interpreter/N_IIf_const": 10, + "interpreter/N_IIf_left_alloc_const": 0, + "interpreter/N_IIf_left_const": 10, + "interpreter/N_IIf_none_alloc_const": 0, + "interpreter/N_IIf_none_const": 10, + "interpreter/N_IImplicit_account_alloc_const": 8, + "interpreter/N_IImplicit_account_const": 10, + "interpreter/N_IInt_bls12_381_z_fr_alloc_const": 28, + "interpreter/N_IInt_bls12_381_z_fr_const": 115, + "interpreter/N_IInt_bytes_alloc_coeff": 0.5050913657784812, + "interpreter/N_IInt_bytes_alloc_const": 15.37271585553797, + "interpreter/N_IInt_bytes_coeff": 2.5, + "interpreter/N_IInt_bytes_const": 20, + "interpreter/N_IInt_nat_alloc_const": 0, + "interpreter/N_IInt_nat_const": 10, + "interpreter/N_IIs_nat_alloc_const": 8, + "interpreter/N_IIs_nat_const": 10, + "interpreter/N_IJoin_tickets_add_coeff": 0.07889348241253691, + "interpreter/N_IJoin_tickets_alloc_add_coeff": 0.5001248813422734, + "interpreter/N_IJoin_tickets_alloc_const": 42.11379220630259, + "interpreter/N_IJoin_tickets_compare_coeff": 0, + "interpreter/N_IJoin_tickets_const": 88.17054267465751, + "interpreter/N_IKeccak_alloc_const": 24, + "interpreter/N_IKeccak_coeff": 8.25, + "interpreter/N_IKeccak_const": 1350, + "interpreter/N_ILambda_lam_alloc_const": 68, + "interpreter/N_ILambda_lam_const": 10, + "interpreter/N_ILambda_lamrec_alloc_const": 140, + "interpreter/N_ILambda_lamrec_const": 10, + "interpreter/N_ILe_alloc_const": 0, + "interpreter/N_ILe_const": 10, + "interpreter/N_ILeft_alloc_const": 8, + "interpreter/N_ILeft_const": 10, + "interpreter/N_ILevel_alloc_const": 12, + "interpreter/N_ILevel_const": 10, + "interpreter/N_IList_iter_alloc_const": 0, + "interpreter/N_IList_iter_const": 20, + "interpreter/N_IList_map_alloc_const": 1, + "interpreter/N_IList_map_const": 20, + "interpreter/N_IList_size_alloc_const": 0, + "interpreter/N_IList_size_const": 10, + "interpreter/N_ILoop_in_alloc_const": 0, + "interpreter/N_ILoop_in_const": 10, + "interpreter/N_ILoop_left_in_alloc_const": 0, + "interpreter/N_ILoop_left_in_const": 10, + "interpreter/N_ILoop_left_out_alloc_const": 0, + "interpreter/N_ILoop_left_out_const": 10, + "interpreter/N_ILoop_out_alloc_const": 0, + "interpreter/N_ILoop_out_const": 1.014518682647915, + "interpreter/N_ILsl_bytes_alloc_bytes": 0.5000144218618687, + "interpreter/N_ILsl_bytes_alloc_const": 11.7574383709798, + "interpreter/N_ILsl_bytes_alloc_shift": 0.06244269262228182, + "interpreter/N_ILsl_bytes_bytes": 0.75, + "interpreter/N_ILsl_bytes_const": 65, + "interpreter/N_ILsl_bytes_shift": 0.0625, + "interpreter/N_ILsl_nat_alloc_coeff": 0.5003556189284719, + "interpreter/N_ILsl_nat_alloc_const": 29.06401012653623, + "interpreter/N_ILsl_nat_coeff": 0.5, + "interpreter/N_ILsl_nat_const": 128, + "interpreter/N_ILsr_bytes_alloc_coeff": 0.4999745615169065, + "interpreter/N_ILsr_bytes_alloc_const": 11.17482221862883, + "interpreter/N_ILsr_bytes_coeff": 0.75, + "interpreter/N_ILsr_bytes_const": 55, + "interpreter/N_ILsr_nat_alloc_coeff": 0.5001766521663271, + "interpreter/N_ILsr_nat_alloc_const": 19.66930714463558, + "interpreter/N_ILsr_nat_coeff": 0.5, + "interpreter/N_ILsr_nat_const": 45, + "interpreter/N_ILt_alloc_const": 0, + "interpreter/N_ILt_const": 10, + "interpreter/N_IMap_get_alloc_const": 8, + "interpreter/N_IMap_get_and_update_alloc_coeff": 27.82756842494692, + "interpreter/N_IMap_get_and_update_alloc_const": 90.90633239395078, + "interpreter/N_IMap_get_and_update_coeff": 0.140625, + "interpreter/N_IMap_get_and_update_const": 75, + "interpreter/N_IMap_get_coeff": 0.046875, + "interpreter/N_IMap_get_const": 45, + "interpreter/N_IMap_iter_alloc_const": 0, + "interpreter/N_IMap_iter_coeff": 7.625, + "interpreter/N_IMap_iter_const": 50, + "interpreter/N_IMap_map_alloc_const": 0, + "interpreter/N_IMap_map_coeff": 8.5, + "interpreter/N_IMap_map_const": 40, + "interpreter/N_IMap_mem_alloc_const": 0, + "interpreter/N_IMap_mem_coeff": 0.046875, + "interpreter/N_IMap_mem_const": 45, + "interpreter/N_IMap_size_alloc_const": 0, + "interpreter/N_IMap_size_const": 10, + "interpreter/N_IMap_update_alloc_coeff": 27.82756842494692, + "interpreter/N_IMap_update_alloc_const": 78.90633239395078, + "interpreter/N_IMap_update_coeff": 0.09375, + "interpreter/N_IMap_update_const": 55, + "interpreter/N_IMin_block_time_alloc_const": 12, + "interpreter/N_IMin_block_time_const": 20, + "interpreter/N_IMul_bls12_381_fr_alloc_const": 24, + "interpreter/N_IMul_bls12_381_fr_const": 45, + "interpreter/N_IMul_bls12_381_fr_z_alloc_const": 24, + "interpreter/N_IMul_bls12_381_fr_z_coeff": 1.0625, + "interpreter/N_IMul_bls12_381_fr_z_const": 265, + "interpreter/N_IMul_bls12_381_g1_alloc_const": 80, + "interpreter/N_IMul_bls12_381_g1_const": 103000, + "interpreter/N_IMul_bls12_381_g2_alloc_const": 152, + "interpreter/N_IMul_bls12_381_g2_const": 220000, + "interpreter/N_IMul_bls12_381_z_fr_alloc_const": 24, + "interpreter/N_IMul_bls12_381_z_fr_coeff": 1.0625, + "interpreter/N_IMul_bls12_381_z_fr_const": 265, + "interpreter/N_IMul_int_alloc_coeff": 0.5001356125367915, + "interpreter/N_IMul_int_alloc_const": 16.92214128813066, + "interpreter/N_IMul_int_coeff": 0.8125, + "interpreter/N_IMul_int_const": 55, + "interpreter/N_IMul_nat_alloc_coeff": 0.5001390299014727, + "interpreter/N_IMul_nat_alloc_const": 15.21550913330429, + "interpreter/N_IMul_nat_coeff": 0.8125, + "interpreter/N_IMul_nat_const": 55, + "interpreter/N_IMul_nattez_alloc_const": 12, + "interpreter/N_IMul_nattez_const": 50, + "interpreter/N_IMul_teznat_alloc_const": 12, + "interpreter/N_IMul_teznat_const": 50, + "interpreter/N_INat_bytes_alloc_coeff": 0.5050218725109211, + "interpreter/N_INat_bytes_alloc_const": 15.37445318722697, + "interpreter/N_INat_bytes_coeff": 2.5, + "interpreter/N_INat_bytes_const": 45, + "interpreter/N_INeg_alloc_coeff": 0.5002070901154503, + "interpreter/N_INeg_alloc_const": 15.61232730387712, + "interpreter/N_INeg_bls12_381_fr_alloc_const": 24, + "interpreter/N_INeg_bls12_381_fr_const": 30, + "interpreter/N_INeg_bls12_381_g1_alloc_const": 80, + "interpreter/N_INeg_bls12_381_g1_const": 50, + "interpreter/N_INeg_bls12_381_g2_alloc_const": 152, + "interpreter/N_INeg_bls12_381_g2_const": 70, + "interpreter/N_INeg_coeff": 0.5, + "interpreter/N_INeg_const": 25, + "interpreter/N_INeq_alloc_const": 0, + "interpreter/N_INeq_const": 10, + "interpreter/N_INil_alloc_const": 12, + "interpreter/N_INil_const": 10, + "interpreter/N_INot_alloc_const": 0, + "interpreter/N_INot_bytes_alloc_coeff": 0.4999803425882123, + "interpreter/N_INot_bytes_alloc_const": 10.54933041992626, + "interpreter/N_INot_bytes_coeff": 0.5, + "interpreter/N_INot_bytes_const": 30, + "interpreter/N_INot_const": 10, + "interpreter/N_INot_int_alloc_coeff": 0.5002661355473995, + "interpreter/N_INot_int_alloc_const": 19.50179425526812, + "interpreter/N_INot_int_coeff": 0.5, + "interpreter/N_INot_int_const": 25, + "interpreter/N_INow_alloc_const": 12, + "interpreter/N_INow_const": 10, + "interpreter/N_IOpen_chest_alloc_const": 15.41815987555565, + "interpreter/N_IOpen_chest_alloc_log_time_coeff": 0.2526151265599721, + "interpreter/N_IOpen_chest_alloc_plaintext_coeff": 0.5006430596234637, + "interpreter/N_IOpen_chest_const": 919000, + "interpreter/N_IOpen_chest_log_time_coeff": 22528, + "interpreter/N_IOpen_chest_plaintext_coeff": 3.25, + "interpreter/N_IOpt_map_none_alloc_const": 0, + "interpreter/N_IOpt_map_none_const": 10, + "interpreter/N_IOpt_map_some_alloc_const": 0, + "interpreter/N_IOpt_map_some_const": 0, + "interpreter/N_IOr_alloc_const": 0, + "interpreter/N_IOr_bytes_alloc_coeff": 0.4999793216510297, + "interpreter/N_IOr_bytes_alloc_const": 10.68735823217867, + "interpreter/N_IOr_bytes_coeff": 0.5, + "interpreter/N_IOr_bytes_const": 35, + "interpreter/N_IOr_const": 10, + "interpreter/N_IOr_nat_alloc_coeff": 0.5001863388188887, + "interpreter/N_IOr_nat_alloc_const": 13.94787807963257, + "interpreter/N_IOr_nat_coeff": 0.5, + "interpreter/N_IOr_nat_const": 35, + "interpreter/N_IPack_alloc_micheline_nodes": 7, + "interpreter/N_IPack_micheline_nodes": 391.2538760079897, + "interpreter/N_IPairing_check_bls12_381_alloc_const": 0, + "interpreter/N_IPairing_check_bls12_381_coeff": 342500, + "interpreter/N_IPairing_check_bls12_381_const": 450000, + "interpreter/N_IPush_alloc_const": 12, + "interpreter/N_IPush_const": 10, + "interpreter/N_IRead_ticket_alloc_const": 56, + "interpreter/N_IRead_ticket_const": 10, + "interpreter/N_IRight_alloc_const": 8, + "interpreter/N_IRight_const": 10, + "interpreter/N_ISapling_empty_state_alloc_const": 28, + "interpreter/N_ISapling_empty_state_const": 300, + "interpreter/N_ISapling_verify_update_alloc_const": 50.73999999999999, + "interpreter/N_ISapling_verify_update_alloc_inputs": 12.0173040271309, + "interpreter/N_ISapling_verify_update_alloc_outputs": 24.01793242755705, + "interpreter/N_ISapling_verify_update_const": 432500, + "interpreter/N_ISapling_verify_update_inputs": 5740000, + "interpreter/N_ISapling_verify_update_outputs": 4636500, + "interpreter/N_ISelf_address_alloc_const": 64, + "interpreter/N_ISelf_address_const": 10, + "interpreter/N_ISelf_alloc_const": 52, + "interpreter/N_ISelf_const": 10, + "interpreter/N_ISender_alloc_const": 72, + "interpreter/N_ISender_const": 10, + "interpreter/N_ISet_delegate_alloc_const": 76, + "interpreter/N_ISet_delegate_const": 60, + "interpreter/N_ISet_iter_alloc_const": 0, + "interpreter/N_ISet_iter_coeff": 7.625, + "interpreter/N_ISet_iter_const": 50, + "interpreter/N_ISet_mem_alloc_const": 0, + "interpreter/N_ISet_mem_coeff": 0.0564536354585845, + "interpreter/N_ISet_mem_const": 39.38054267465736, + "interpreter/N_ISet_size_alloc_const": 0, + "interpreter/N_ISet_size_const": 10, + "interpreter/N_ISet_update_alloc_coeff": 21.74174580055838, + "interpreter/N_ISet_update_alloc_const": 77.62567378475259, + "interpreter/N_ISet_update_coeff": 0.1400362076631439, + "interpreter/N_ISet_update_const": 49.89054267465742, + "interpreter/N_ISha256_alloc_const": 24, + "interpreter/N_ISha256_coeff": 4.75, + "interpreter/N_ISha256_const": 600, + "interpreter/N_ISha3_alloc_const": 24, + "interpreter/N_ISha3_coeff": 8.25, + "interpreter/N_ISha3_const": 1350, + "interpreter/N_ISha512_alloc_const": 40, + "interpreter/N_ISha512_coeff": 3, + "interpreter/N_ISha512_const": 680, + "interpreter/N_ISlice_bytes_alloc_coeff": 0.5001602038592171, + "interpreter/N_ISlice_bytes_alloc_const": 14.61423286238869, + "interpreter/N_ISlice_bytes_coeff": 0.5, + "interpreter/N_ISlice_bytes_const": 25, + "interpreter/N_ISlice_string_alloc_coeff": 0.5001634896375161, + "interpreter/N_ISlice_string_alloc_const": 15.68609989596905, + "interpreter/N_ISlice_string_coeff": 0.5, + "interpreter/N_ISlice_string_const": 25, + "interpreter/N_ISource_alloc_const": 72, + "interpreter/N_ISource_const": 10, + "interpreter/N_ISplit_ticket_alloc_const": 52, + "interpreter/N_ISplit_ticket_coeff": 0.5, + "interpreter/N_ISplit_ticket_const": 40, + "interpreter/N_IString_size_alloc_const": 0, + "interpreter/N_IString_size_const": 15, + "interpreter/N_ISub_int_alloc_coeff": 0.5002119258364551, + "interpreter/N_ISub_int_alloc_const": 17.55013733057876, + "interpreter/N_ISub_int_coeff": 0.5, + "interpreter/N_ISub_int_const": 35, + "interpreter/N_ISub_tez_alloc_const": 20, + "interpreter/N_ISub_tez_const": 15, + "interpreter/N_ISub_tez_legacy_alloc_const": 12, + "interpreter/N_ISub_tez_legacy_const": 20, + "interpreter/N_ISub_timestamp_seconds_alloc_coeff": 0.5002119258364551, + "interpreter/N_ISub_timestamp_seconds_alloc_const": 17.55013733057876, + "interpreter/N_ISub_timestamp_seconds_coeff": 0.5, + "interpreter/N_ISub_timestamp_seconds_const": 35, + "interpreter/N_ISwap_alloc_const": 12, + "interpreter/N_ISwap_const": 10, + "interpreter/N_ITicket_alloc_const": 56, + "interpreter/N_ITicket_const": 10, + "interpreter/N_ITotal_voting_power_alloc_const": 12, + "interpreter/N_ITotal_voting_power_const": 450, + "interpreter/N_ITransfer_tokens_alloc_const": 120, + "interpreter/N_ITransfer_tokens_const": 60, + "interpreter/N_IUncomb_alloc_coeff": 11.98156142428547, + "interpreter/N_IUncomb_alloc_const": 6.309505684524993, + "interpreter/N_IUncomb_coeff": 4, + "interpreter/N_IUncomb_const": 30, + "interpreter/N_IUnit_alloc_const": 12, + "interpreter/N_IUnit_const": 10, + "interpreter/N_IUnpack_alloc_const": 8, + "interpreter/N_IUnpack_const": 278.7605426746565, + "interpreter/N_IUnpair_alloc_const": 12, + "interpreter/N_IUnpair_const": 10, + "interpreter/N_IView_alloc_const": 0, + "interpreter/N_IView_const": 1460, + "interpreter/N_IVoting_power_alloc_const": 0, + "interpreter/N_IVoting_power_const": 640, + "interpreter/N_IXor_alloc_const": 0, + "interpreter/N_IXor_bytes_alloc_coeff": 0.4999793216510297, + "interpreter/N_IXor_bytes_alloc_const": 10.68735823217867, + "interpreter/N_IXor_bytes_coeff": 0.5, + "interpreter/N_IXor_bytes_const": 40, + "interpreter/N_IXor_const": 15, + "interpreter/N_IXor_nat_alloc_coeff": 0.5001863388188887, + "interpreter/N_IXor_nat_alloc_const": 13.94787807963257, + "interpreter/N_IXor_nat_coeff": 0.5, + "interpreter/N_IXor_nat_const": 35, + "interpreter/N_KCons_alloc_const": 0, + "interpreter/N_KCons_const": 10, + "interpreter/N_KIter_empty_alloc_const": 0, + "interpreter/N_KIter_empty_const": 10, + "interpreter/N_KIter_nonempty_alloc_const": 0, + "interpreter/N_KIter_nonempty_const": 10, + "interpreter/N_KList_enter_body_alloc_coeff": 12.00147009441836, + "interpreter/N_KList_enter_body_alloc_const": 23, + "interpreter/N_KList_enter_body_alloc_iter": 0, + "interpreter/N_KList_enter_body_coeff": 1.8125, + "interpreter/N_KList_enter_body_const": 30, + "interpreter/N_KList_enter_body_iter": 30, + "interpreter/N_KList_exit_body_alloc_const": 0, + "interpreter/N_KList_exit_body_const": 10, + "interpreter/N_KLoop_in_alloc_const": 0, + "interpreter/N_KLoop_in_const": 10, + "interpreter/N_KLoop_in_left_alloc_const": 0, + "interpreter/N_KLoop_in_left_const": 10, + "interpreter/N_KMap_enter_body_alloc_empty": 11, + "interpreter/N_KMap_enter_body_alloc_nonempty": 0, + "interpreter/N_KMap_enter_body_empty": 10, + "interpreter/N_KMap_enter_body_nonempty": 80, + "interpreter/N_KMap_exit_body_alloc_coeff": 28.38778289353496, + "interpreter/N_KMap_exit_body_alloc_const": 74.40851017907384, + "interpreter/N_KMap_exit_body_coeff": 0.1149644278432145, + "interpreter/N_KMap_exit_body_const": 0, + "interpreter/N_KMap_head_alloc_const": 8, + "interpreter/N_KMap_head_const": 20, + "interpreter/N_KNil_alloc_const": 0, + "interpreter/N_KNil_const": 15, + "interpreter/N_KReturn_alloc_const": 0, + "interpreter/N_KReturn_const": 10, + "interpreter/N_KUndip_alloc_const": 12, + "interpreter/N_KUndip_const": 10, + "interpreter/N_KView_exit_alloc_const": 0, + "interpreter/N_KView_exit_const": 20, + "interpreter/amplification_loop_iteration": 0.3293093413239112, + "micheline/nodes": 51, + "misc/lwt_main_run": 49.40666666666652, + "sapling/apply_diff_const": 1300000, + "sapling/apply_diff_inputs": 5000, + "sapling/apply_diff_outputs": 55000, + "sc_rollup/Sc_rollup_deserialize_output_proof_benchmark/coeff": 6, + "sc_rollup/Sc_rollup_deserialize_output_proof_benchmark/intercept": 7100, + "sc_rollup/Sc_rollup_install_boot_sector_benchmark/coeff": 3.5, + "sc_rollup/Sc_rollup_install_boot_sector_benchmark/intercept": 13550, + "sc_rollup/Sc_rollup_verify_output_proof_benchmark/coeff": 7, + "sc_rollup/Sc_rollup_verify_output_proof_benchmark/intercept": 103450, + "script_repr/MICHELINE_NODES_const": 0, + "script_repr/MICHELINE_NODES_ns_per_node_coeff": 6.492852150095166, + "script_repr/nodes": 51, + "script_typed_ir_size/KINSTR_SIZE_const": 0, + "script_typed_ir_size/KINSTR_SIZE_size_coeff": 16.91072877942451, + "script_typed_ir_size/NODE_SIZE_const": 0, + "script_typed_ir_size/NODE_SIZE_ns_per_node_coeff": 25.39689742685013, + "script_typed_ir_size/TYPE_SIZE_const": 0, + "script_typed_ir_size/TYPE_SIZE_size_coeff": 16.22325067098085, + "script_typed_ir_size/VALUE_SIZE_const": 0, + "script_typed_ir_size/VALUE_SIZE_size_coeff": 19.56988810741499, + "skip_list/hash_cell/coeff": 57, + "skip_list/hash_cell/intercept": 250, + "skip_list/next/coeff": 19.2125537461, + "storage/list_key_values_intercept": 470, + "storage/list_key_values_step": 117, + "tickets/COLLECT_TICKETS_STEP/coeff": 80, + "tickets/COLLECT_TICKETS_STEP/intercept": 0, + "tickets/TYPE_HAS_TICKETS/coeff": 6, + "tickets/TYPE_HAS_TICKETS/intercept": 10, + "tickets/compare_contract": 10, + "tickets/compare_ticket_hash": 10, + "translator/PARSE_TYPE/coeff": 60, + "translator/PARSE_TYPE/intercept": 0, + "translator/Parsing_Code_gas_coeff": 0.8903912445671381, + "translator/Parsing_Code_gas_const": 0, + "translator/Parsing_Code_size_int_bytes": 0, + "translator/Parsing_Code_size_string_bytes": 0, + "translator/Parsing_Code_size_traversal": 187.3004589673066, + "translator/Parsing_Data_gas_coeff": 0.1429729867508994, + "translator/Parsing_Data_gas_const": 67277.39739401177, + "translator/Parsing_Data_size_int_bytes": 16.14268057774883, + "translator/Parsing_Data_size_string_bytes": 68.94873206863673, + "translator/Parsing_Data_size_traversal": 80.36344489900098, + "translator/TY_EQ/coeff": 21.8805791266, + "translator/TY_EQ/intercept": 31.1882471167, + "translator/UNPARSE_TYPE/coeff": 20, + "translator/UNPARSE_TYPE/intercept": 0, + "translator/Unparsing_Code_gas_coeff": 0.5923099246608585, + "translator/Unparsing_Code_gas_const": 0, + "translator/Unparsing_Code_size_int_bytes": 0, + "translator/Unparsing_Code_size_string_bytes": 0, + "translator/Unparsing_Code_size_traversal": 124.7264251200329, + "translator/Unparsing_Data_gas_coeff": 0.03386230569199927, + "translator/Unparsing_Data_gas_const": 31944.78653843506, + "translator/Unparsing_Data_size_int_bytes": 0, + "translator/Unparsing_Data_size_string_bytes": 0, + "translator/Unparsing_Data_size_traversal": 54.87066469329662 + }, + "scores_list": [] +} diff --git a/src/proto_020_PsParisC/lib_protocol/global_constants_costs.ml b/src/proto_020_PsParisC/lib_protocol/global_constants_costs.ml new file mode 100644 index 000000000000..a51f5613482b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/global_constants_costs.ml @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Global_constants_costs_generated +open S.Syntax + +(* generated code is not usable: the model lacks intercept *) +(* model global_constants_storage/expr_to_address_in_context *) +(* Approximating 200 + 1.266960 * number of bytes *) +let cost_expr_to_address_in_context size = + let v0 = S.safe_int size in + S.safe_int 200 + (v0 + (v0 lsr 2)) + +let expr_to_address_in_context_cost bytes = + cost_expr_to_address_in_context (Bytes.length bytes) + |> Gas_limit_repr.atomic_step_cost + +let expand_constants_branch_cost = + cost_expand_constant_branch 1 |> Gas_limit_repr.atomic_step_cost + +let expand_no_constants_branch_cost node = + cost_expand_no_constant_branch (Script_repr.micheline_nodes node) + |> Gas_limit_repr.atomic_step_cost diff --git a/src/proto_020_PsParisC/lib_protocol/global_constants_costs.mli b/src/proto_020_PsParisC/lib_protocol/global_constants_costs.mli new file mode 100644 index 000000000000..9f24e8b34d39 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/global_constants_costs.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Costs function for the global table of constants. *) + +(** Cost of calling [Global_constats_storage.expr_to_address_in_context]. *) +val expr_to_address_in_context_cost : bytes -> Gas_limit_repr.cost + +(** Step costs for [Global_constats_storage.expand_node]. *) +val expand_constants_branch_cost : Gas_limit_repr.cost + +val expand_no_constants_branch_cost : Script_repr.node -> Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/global_constants_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/global_constants_costs_generated.ml new file mode 100644 index 000000000000..13cb371b8a37 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/global_constants_costs_generated.ml @@ -0,0 +1,23 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model global_constants_storage/expand_constant_branch *) +(* fun size -> max 10 (4095. * size) *) +let cost_expand_constant_branch size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 4096) + +(* model global_constants_storage/expand_no_constant_branch *) +(* fun size -> max 10 (100. + (4.639474 * (size * (log2 (1 + size))))) *) +let cost_expand_no_constant_branch size = + let size = S.safe_int size in + let w3 = log2 (size + S.safe_int 1) * size in + (w3 * S.safe_int 4) + (w3 lsr 1) + (w3 lsr 2) + S.safe_int 100 diff --git a/src/proto_020_PsParisC/lib_protocol/global_constants_storage.ml b/src/proto_020_PsParisC/lib_protocol/global_constants_storage.ml new file mode 100644 index 000000000000..a7da8fca876d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/global_constants_storage.ml @@ -0,0 +1,289 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Micheline +open Michelson_v1_primitives + +(* + + See [expand] for an example. + + TODO: https://gitlab.com/tezos/tezos/-/issues/1609 + Move function to lib_micheline. + + On our next opportunity to update the environment, we + should move this function to lib_micheline. + +*) +let bottom_up_fold_cps initial_accumulator node initial_k f = + let rec traverse_node accu node k = + f accu node @@ fun accu node -> + match node with + | String _ | Int _ | Bytes _ -> k accu node + | Prim (loc, prim, args, annot) -> + (traverse_nodes [@ocaml.tailcall]) accu args (fun accu args -> + f accu (Prim (loc, prim, args, annot)) k) + | Seq (loc, elts) -> + (traverse_nodes [@ocaml.tailcall]) accu elts (fun accu elts -> + f accu (Seq (loc, elts)) k) + and traverse_nodes accu nodes k = + match nodes with + | [] -> k accu [] + | node :: nodes -> + (traverse_node [@ocaml.tailcall]) accu node (fun accu node -> + (traverse_nodes [@ocaml.tailcall]) accu nodes (fun accu nodes -> + k accu (node :: nodes))) + in + traverse_node initial_accumulator node initial_k + +module Gas_costs = Global_constants_costs +module Expr_hash_map = Map.Make (Script_expr_hash) + +type error += Expression_too_deep + +type error += Expression_already_registered + +type error += Badly_formed_constant_expression + +type error += Nonexistent_global + +type error += Expression_too_large + +let () = + let description = + "Attempted to register an expression that, after fully expanding all \ + referenced global constants, would result in too many levels of nesting." + in + register_error_kind + `Branch + ~id:"Expression_too_deep" + ~title:"Expression too deep" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Expression_too_deep -> Some () | _ -> None) + (fun () -> Expression_too_deep) ; + let description = + "Attempted to register an expression as global constant that has already \ + been registered." + in + register_error_kind + `Branch + ~id:"Expression_already_registered" + ~title:"Expression already registered" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Expression_already_registered -> Some () | _ -> None) + (fun () -> Expression_already_registered) ; + let description = + "Found a badly formed constant expression. The 'constant' primitive must \ + always be followed by a string of the hash of the expression it points \ + to." + in + register_error_kind + `Branch + ~id:"Badly_formed_constant_expression" + ~title:"Badly formed constant expression" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Badly_formed_constant_expression -> Some () | _ -> None) + (fun () -> Badly_formed_constant_expression) ; + let description = + "No registered global was found at the given hash in storage." + in + register_error_kind + `Branch + ~id:"Nonexistent_global" + ~title:"Tried to look up nonexistent global" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Nonexistent_global -> Some () | _ -> None) + (fun () -> Nonexistent_global) ; + let description = + "Encountered an expression that, after expanding all constants, is larger \ + than the expression size limit." + in + register_error_kind + `Branch + ~id:"Expression_too_large" + ~title:"Expression too large" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Expression_too_large -> Some () | _ -> None) + (fun () -> Expression_too_large) + +let get context hash = + let open Lwt_result_syntax in + let* context, value = Storage.Global_constants.Map.find context hash in + match value with + | None -> tzfail Nonexistent_global + | Some value -> return (context, value) + +let expr_to_address_in_context context expr = + let open Result_syntax in + let lexpr = Script_repr.lazy_expr expr in + let* context = + Raw_context.consume_gas context @@ Script_repr.force_bytes_cost lexpr + in + let* b = Script_repr.force_bytes lexpr in + let+ context = + Raw_context.consume_gas context + @@ Gas_costs.expr_to_address_in_context_cost b + in + (context, Script_expr_hash.hash_bytes [b]) + +let node_too_large node = + let node_size = Script_repr.Micheline_size.of_node node in + let nodes = Saturation_repr.to_int node_size.nodes in + let string_bytes = Saturation_repr.to_int node_size.string_bytes in + let z_bytes = Saturation_repr.to_int node_size.z_bytes in + Compare.Int.( + nodes > Constants_repr.max_micheline_node_count + || string_bytes + z_bytes > Constants_repr.max_micheline_bytes_limit) + +let expand_node context node = + (* We charge for traversing the top-level node at the beginning. + Inside the loop, we charge for traversing each new constant + that gets expanded. *) + let open Lwt_result_syntax in + let*? context = + Raw_context.consume_gas + context + (Gas_costs.expand_no_constants_branch_cost node) + in + let* context, node, did_expansion = + bottom_up_fold_cps + (* We carry a Boolean representing whether we + had to do any expansions or not. *) + (context, Expr_hash_map.empty, false) + node + (fun (context, _, did_expansion) node -> + return (context, node, did_expansion)) + (fun (context, map, did_expansion) node k -> + match node with + | Prim (_, H_constant, args, annot) -> ( + (* Charge for validating the b58check hash. *) + let*? context = + Raw_context.consume_gas + context + Gas_costs.expand_constants_branch_cost + in + match (args, annot) with + (* A constant Prim should always have a single String argument, + being a properly formatted hash. *) + | [String (_, address)], [] -> ( + match Script_expr_hash.of_b58check_opt address with + | None -> tzfail Badly_formed_constant_expression + | Some hash -> ( + match Expr_hash_map.find hash map with + | Some node -> + (* Charge traversing the newly retrieved node *) + let*? context = + Raw_context.consume_gas + context + (Gas_costs.expand_no_constants_branch_cost node) + in + k (context, map, true) node + | None -> + let* context, expr = get context hash in + (* Charge traversing the newly retrieved node *) + let node = root expr in + let*? context = + Raw_context.consume_gas + context + (Gas_costs.expand_no_constants_branch_cost node) + in + k (context, Expr_hash_map.add hash node map, true) node) + ) + | _ -> tzfail Badly_formed_constant_expression) + | Int _ | String _ | Bytes _ | Prim _ | Seq _ -> + k (context, map, did_expansion) node) + in + if did_expansion then + (* Gas charged during expansion is at least proportional to the size of the + resulting node so the execution time of [node_too_large] is already + covered. *) + if node_too_large node then tzfail Expression_too_large + else return (context, node) + else return (context, node) + +let expand context expr = + let open Lwt_result_syntax in + let+ context, node = expand_node context (root expr) in + (context, strip_locations node) + +(** Computes the maximum depth of a Micheline node. Fails + with [Expression_too_deep] if greater than + [max_allowed_global_constant_depth].*) +let check_depth node = + let rec advance node depth k = + if Compare.Int.(depth > Constants_repr.max_allowed_global_constant_depth) + then Result_syntax.tzfail Expression_too_deep + else + match node with + | Int _ | String _ | Bytes _ | Prim (_, _, [], _) | Seq (_, []) -> + (k [@tailcall]) (depth + 1) + | Prim (loc, _, hd :: tl, _) | Seq (loc, hd :: tl) -> + (advance [@tailcall]) hd (depth + 1) (fun dhd -> + (advance [@tailcall]) + (* Because [depth] doesn't care about the content + of the expression, we can safely throw away information + about primitives and replace them with the [Seq] constructor.*) + (Seq (loc, tl)) + depth + (fun dtl -> (k [@tailcall]) (Compare.Int.max dhd dtl))) + in + advance node 0 (fun x -> Ok x) + +let register context value = + (* To calculate the total depth, we first expand all constants + in the expression. This may fail with [Expression_too_large]. + + Though the stored expression is the unexpanded version. + *) + let open Lwt_result_syntax in + let* context, node = expand_node context (root value) in + (* We do not need to carbonate [check_depth]. [expand_node] and + [Storage.Global_constants.Map.init] are already carbonated + with gas at least proportional to the size of the expanded node + and the computation cost of [check_depth] is of the same order. *) + let*? (_depth : int) = check_depth node in + let*? context, key = expr_to_address_in_context context value in + let+ context, size = + trace Expression_already_registered + @@ Storage.Global_constants.Map.init context key value + in + (context, key, Z.of_int size) + +module Internal_for_tests = struct + let node_too_large = node_too_large + + let bottom_up_fold_cps = bottom_up_fold_cps + + let expr_to_address_in_context = expr_to_address_in_context +end diff --git a/src/proto_020_PsParisC/lib_protocol/global_constants_storage.mli b/src/proto_020_PsParisC/lib_protocol/global_constants_storage.mli new file mode 100644 index 000000000000..eb71374ade5b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/global_constants_storage.mli @@ -0,0 +1,150 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module represents access to a global table of constant + Micheline values. Users may register a Micheline value in the + table, paying the cost of storage. Once stored, scripts may + reference this value by its hash. + + Note: the table does not typecheck the values stored in it. + Instead, any place that uses constants must first call [expand] + before typechecking the code. This decision was made to make it as + easy as possible for users to register values to the table, and also + to allow maximum flexibility in the use of constants for different + parts of a Michelson script (code, types, data, etc.). *) + +type error += Expression_too_deep + +type error += Expression_already_registered + +(** A constant is the prim of the literal characters "constant". + A constant must have a single argument, being a string with a + well formed hash of a Micheline expression (i.e generated by + [Script_expr_hash.to_b58check]). *) +type error += Badly_formed_constant_expression + +type error += Nonexistent_global + +(** [get context hash] retrieves the Micheline value with the given hash. + + Fails with [Nonexistent_global] if no value is found at the given hash. + + Fails with [Storage_error Corrupted_data] if the deserialisation fails. + + Consumes [Gas_repr.read_bytes_cost ]. *) +val get : + Raw_context.t -> + Script_expr_hash.t -> + (Raw_context.t * Script_repr.expr) tzresult Lwt.t + +(** [register context value] registers a constant in the global table of constants, + returning the hash and storage bytes consumed. + + Does not type-check the Micheline code being registered, allow potentially + ill-typed Michelson values to be stored in the table (see note at top of module). + + The constant is stored unexpanded, but it is temporarily expanded at registration + time only to check the expanded version respects the following limits. + This also ensures there are no cyclic dependencies between constants. + + Fails with [Expression_too_deep] if, after fully expanding all constants, + the expression would have a depth greater than [Constant_repr.max_allowed_global_constant_depth]. + + Fails with [Badly_formed_constant_expression] if constants are not + well-formed (see declaration of [Badly_formed_constant_expression]) or with + [Nonexistent_global] if a referenced constant does not exist in the table. + + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ] where size is the number + of bytes in the binary serialization provided by [Script_repr.expr_encoding]. *) +val register : + Raw_context.t -> + Script_repr.expr -> + (Raw_context.t * Script_expr_hash.t * Z.t) tzresult Lwt.t + +(** [expand context expr] replaces every constant in the + given Michelson expression with its value stored in the global table. + + The expansion is applied recursively so that the returned expression + contains no constant. + + Fails with [Badly_formed_constant_expression] if constants are not + well-formed (see declaration of [Badly_formed_constant_expression]) or + with [Nonexistent_global] if a referenced constant does not exist in + the table. *) +val expand : + Raw_context.t -> + Script_repr.expr -> + (Raw_context.t * Script_repr.expr) tzresult Lwt.t + +module Internal_for_tests : sig + (** [node_too_large node] returns true if: + - The number of sub-nodes in the [node] + exceeds [Global_constants_storage.node_size_limit]. + - The sum of the bytes in String, Int, + and Bytes sub-nodes of [node] exceeds + [Global_constants_storage.bytes_size_limit]. + + Otherwise returns false. *) + val node_too_large : Script_repr.node -> bool + + (** [bottom_up_fold_cps initial_accumulator node initial_k f] + folds [node] and all its sub-nodes if any, starting from + [initial_accumulator], using an initial continuation [initial_k]. + At each node, [f] is called to transform the continuation [k] into + the next one. This explicit manipulation of the continuation + is typically useful to short-circuit. + + Notice that a common source of bug is to forget to properly call the + continuation in `f`. + + See [Global_constants_storage.expand] for an example. + + TODO: https://gitlab.com/tezos/tezos/-/issues/1609 + Move function to lib_micheline. + + On our next opportunity to update the environment, we + should move this function to lib_micheline. + *) + val bottom_up_fold_cps : + 'accumulator -> + 'loc Script_repr.michelson_node -> + ('accumulator -> 'loc Script_repr.michelson_node -> 'return) -> + ('accumulator -> + 'loc Script_repr.michelson_node -> + ('accumulator -> 'loc Script_repr.michelson_node -> 'return) -> + 'return) -> + 'return + + (* [expr_to_address_in_context context expr] converts [expr] + into a unique hash represented by a [Script_expr_hash.t]. + + Consumes gas corresponding to the cost of converting [expr] + to bytes and hashing the bytes. *) + val expr_to_address_in_context : + Raw_context.t -> + Script_repr.expr -> + (Raw_context.t * Script_expr_hash.t) tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/indexable.ml b/src/proto_020_PsParisC/lib_protocol/indexable.ml new file mode 100644 index 000000000000..9dd8b1bce48d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/indexable.ml @@ -0,0 +1,200 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type index_only = Index_only + +type value_only = Value_only + +type unknown = Unknown + +type (_, 'a) t = + | Value : 'a -> (value_only, 'a) t + | Hidden_value : 'a -> (unknown, 'a) t + | Index : int32 -> (index_only, 'a) t + | Hidden_index : int32 -> (unknown, 'a) t + +type error += Index_cannot_be_negative of int32 + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"indexable.index_cannot_be_negative" + ~title:"Index of values cannot be negative" + ~description:"A negative integer cannot be used as an index for a value." + ~pp:(fun ppf wrong_id -> + Format.fprintf + ppf + "%ld cannot be used as an index because it is negative." + wrong_id) + (obj1 (req "wrong_index" int32)) + (function Index_cannot_be_negative wrong_id -> Some wrong_id | _ -> None) + (fun wrong_id -> Index_cannot_be_negative wrong_id) + +type 'a value = (value_only, 'a) t + +type 'a index = (index_only, 'a) t + +type 'a either = (unknown, 'a) t + +let value : 'a -> 'a value = fun v -> Value v + +let from_value : 'a -> 'a either = fun v -> Hidden_value v + +let index : int32 -> 'a index tzresult = + let open Result_syntax in + fun i -> + if Compare.Int32.(0l <= i) then return (Index i) + else tzfail (Index_cannot_be_negative i) + +let from_index : int32 -> 'a either tzresult = + let open Result_syntax in + fun i -> + if Compare.Int32.(0l <= i) then return (Hidden_index i) + else tzfail (Index_cannot_be_negative i) + +let index_exn : int32 -> 'a index = + fun i -> + match index i with + | Ok x -> x + | Error _ -> raise (Invalid_argument "Indexable.index_exn") + +let from_index_exn : int32 -> 'a either = + fun i -> + match from_index i with + | Ok x -> x + | Error _ -> raise (Invalid_argument "Indexable.from_index_exn") + +let destruct : type state a. (state, a) t -> (a index, a) Either.t = function + | Hidden_value x | Value x -> Right x + | Hidden_index x | Index x -> Left (Index x) + +let forget : type state a. (state, a) t -> (unknown, a) t = function + | Hidden_value x | Value x -> Hidden_value x + | Hidden_index x | Index x -> Hidden_index x + +let to_int32 = function Index x -> x + +let to_value = function Value x -> x + +let is_value_e : error:'trace -> ('state, 'a) t -> ('a, 'trace) result = + fun ~error v -> match destruct v with Left _ -> Error error | Right v -> Ok v + +let compact val_encoding = + Data_encoding.Compact.( + conv + (function Hidden_index x -> Either.Left x | Hidden_value x -> Right x) + (function Left x -> Hidden_index x | Right x -> Hidden_value x) + @@ or_int32 ~int32_title:"index" ~alt_title:"value" val_encoding) + +let encoding : 'a Data_encoding.t -> 'a either Data_encoding.t = + fun val_encoding -> + Data_encoding.Compact.make ~tag_size:`Uint8 @@ compact val_encoding + +let pp : + type state a. + (Format.formatter -> a -> unit) -> Format.formatter -> (state, a) t -> unit + = + fun ppv fmt -> function + | Hidden_index x | Index x -> Format.(fprintf fmt "#%ld" x) + | Hidden_value x | Value x -> Format.(fprintf fmt "%a" ppv x) + +let in_memory_size : + type state a. + (a -> Cache_memory_helpers.sint) -> + (state, a) t -> + Cache_memory_helpers.sint = + fun ims -> + let open Cache_memory_helpers in + function + | Hidden_value x | Value x -> header_size +! word_size +! ims x + | Hidden_index _ | Index _ -> header_size +! word_size +! int32_size + +let size : type state a. (a -> int) -> (state, a) t -> int = + fun s -> function + | Hidden_value x | Value x -> 1 + s x + | Hidden_index _ | Index _ -> (* tag + int32 *) 1 + 4 + +let compare : + type state state' a. (a -> a -> int) -> (state, a) t -> (state', a) t -> int + = + fun c x y -> + match (x, y) with + | (Hidden_index x | Index x), (Hidden_index y | Index y) -> + Compare.Int32.compare x y + | (Hidden_value x | Value x), (Hidden_value y | Value y) -> c x y + | (Hidden_index _ | Index _), (Hidden_value _ | Value _) -> -1 + | (Hidden_value _ | Value _), (Hidden_index _ | Index _) -> 1 + +let compare_values c : 'a value -> 'a value -> int = + fun (Value x) (Value y) -> c x y + +let compare_indexes : 'a index -> 'a index -> int = + fun (Index x) (Index y) -> Compare.Int32.compare x y + +module type VALUE = sig + type t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int + + val pp : Format.formatter -> t -> unit +end + +module Make (V : VALUE) = struct + type nonrec 'state t = ('state, V.t) t + + type nonrec index = V.t index + + type nonrec value = V.t value + + type nonrec either = V.t either + + let value = value + + let index = index + + let index_exn = index_exn + + let compact = compact V.encoding + + let encoding = encoding V.encoding + + let index_encoding : index Data_encoding.t = + Data_encoding.( + conv (fun (Index x) -> x) (fun x -> Index x) Data_encoding.int32) + + let value_encoding : value Data_encoding.t = + Data_encoding.(conv (fun (Value x) -> x) (fun x -> Value x) V.encoding) + + let pp : Format.formatter -> 'state t -> unit = fun fmt x -> pp V.pp fmt x + + let compare_values = compare_values V.compare + + let compare_indexes = compare_indexes + + let compare : 'state t -> 'state' t -> int = fun x y -> compare V.compare x y +end diff --git a/src/proto_020_PsParisC/lib_protocol/indexable.mli b/src/proto_020_PsParisC/lib_protocol/indexable.mli new file mode 100644 index 000000000000..2cc2452658c7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/indexable.mli @@ -0,0 +1,197 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** In transaction rollups, some values can be replaced by indexes in + the messages sent from the layer-1 to the layer-2. + + This module provides various type-safe helpers to manipulate these + particular values. *) + +type value_only = Value_only + +type index_only = Index_only + +type unknown = Unknown + +(** An indexable value is a value which can be replaced by an + integer. The first type parameter determines whether or not this + replacement has happened already. *) +type (_, 'a) t = private + | Value : 'a -> (value_only, 'a) t + | Hidden_value : 'a -> (unknown, 'a) t + | Index : int32 -> (index_only, 'a) t + | Hidden_index : int32 -> (unknown, 'a) t + +(** The type of indexable values identified as not being indexes. *) +type 'a value = (value_only, 'a) t + +(** The type of indexable values identified as being indexes. *) +type 'a index = (index_only, 'a) t + +(** The type of indexable values whose content is still unknown. *) +type 'a either = (unknown, 'a) t + +(** [value v] wraps [v] into an indexable value identified as not + being an index. *) +val value : 'a -> 'a value + +(** [from_value v] wraps [v] into an indexable value, but forget about + the nature of the content of the result. *) +val from_value : 'a -> 'a either + +(** [index i] wraps [i] into an indexable value identified as being an + index. + + Returns the error [Index_cannot_be_negative] iff [i <= 0l]. *) +val index : int32 -> 'a index tzresult + +(** [from_index i] wraps [i] into an indexable value, but forget about the + nature of the content of the result. + + Returns the error [Index_cannot_be_negative] iff [i <= 0l]. *) +val from_index : int32 -> 'a either tzresult + +(** [index_exn i] wraps [i] into an indexable value identified as + being an index. + + @raise Invalid_argument iff [i <= 0l]. *) +val index_exn : int32 -> 'a index + +(** [from_index_exn i] wraps [i] into an indexable value, but forget + about the nature of the content of the result. + + @raise Invalid_argument iff [i <= 0l]. *) +val from_index_exn : int32 -> 'a either + +(** [compact val_encoding] is a combinator to derive a compact + encoding for an indexable value of type ['a] from an encoding for + ['a]. It uses two bits in the shared tag. [00] is used for indexes + fitting in one byte, [01] for indexes fitting in two bytes, [10] + for indexes fitting in four bytes, and [11] for the values of type + ['a]. *) +val compact : 'a Data_encoding.t -> (unknown, 'a) t Data_encoding.Compact.t + +val encoding : 'a Data_encoding.t -> (unknown, 'a) t Data_encoding.t + +val pp : + (Format.formatter -> 'a -> unit) -> Format.formatter -> ('state, 'a) t -> unit + +(** [destruct x] returns either the index or the (unwrapped) value + contained in [x]. + + {b Note:} If you want to manipulate a value of type {!type-value}, + you can use {!val-value}. *) +val destruct : ('state, 'a) t -> ('a index, 'a) Either.t + +(** [forget x] returns an indexable value whose kind of contents has + been forgotten. *) +val forget : ('state, 'a) t -> (unknown, 'a) t + +(** [to_int32 x] unwraps and returns the integer behind [x]. *) +val to_int32 : 'a index -> int32 + +(** [to_value x] unwraps and returns the value behind [x]. *) +val to_value : 'a value -> 'a + +(** [is_value_e err x] unwraps and returns the value behind [x], and + throws an [err] if [x] is an index. *) +val is_value_e : error:'trace -> ('state, 'a) t -> ('a, 'trace) result + +(** [in_memory_size a] returns the number of bytes allocated in RAM for [a]. *) +val in_memory_size : + ('a -> Cache_memory_helpers.sint) -> + ('state, 'a) t -> + Cache_memory_helpers.sint + +(** [size a] returns the number of bytes allocated in an inbox to store [a]. *) +val size : ('a -> int) -> ('state, 'a) t -> int + +(** [compare f x y] is a total order on indexable values, which + proceeds as follows. + + {ul {li If both [x] and [y] are a value, then use [f] to compare them.} + {li If both [x] and [y] are indexes, then uses the + [Int32.compare] function to compare them.} + {li Finally, if [x] and [y] have not the same kind, the logic + is that indexes are smaller than values.}} + + {b Note:} This can be dangerous, as you may end up comparing two + things that are equivalent (a value and its index) but declare + they are not equal. *) +val compare : ('a -> 'a -> int) -> ('state, 'a) t -> ('state', 'a) t -> int + +(** [compare_values f x y] compares the value [x] and [y] using [f], + and relies on the type system of OCaml to ensure that [x] and [y] + are indeed both values. *) +val compare_values : ('a -> 'a -> int) -> 'a value -> 'a value -> int + +(** [compare_indexes x y] compares the indexes [x] and [y], and relies + on the type system of OCaml to ensure that [x] and [y] are indeed + both indexes. *) +val compare_indexes : 'a index -> 'a index -> int + +module type VALUE = sig + type t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int + + val pp : Format.formatter -> t -> unit +end + +module Make (V : VALUE) : sig + type nonrec 'state t = ('state, V.t) t + + type nonrec index = V.t index + + type nonrec value = V.t value + + type nonrec either = V.t either + + val value : V.t -> value + + val index : int32 -> index tzresult + + val index_exn : int32 -> index + + val compact : either Data_encoding.Compact.t + + val encoding : either Data_encoding.t + + val index_encoding : index Data_encoding.t + + val value_encoding : value Data_encoding.t + + val compare : 'state t -> 'state' t -> int + + val compare_values : value -> value -> int + + val compare_indexes : index -> index -> int + + val pp : Format.formatter -> 'state t -> unit +end + +type error += Index_cannot_be_negative of int32 diff --git a/src/proto_020_PsParisC/lib_protocol/init_storage.ml b/src/proto_020_PsParisC/lib_protocol/init_storage.ml new file mode 100644 index 000000000000..020f518cf36d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/init_storage.ml @@ -0,0 +1,380 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* Copyright (c) 2021 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + To add invoices, you can use a helper function like this one: + +(** Invoice a contract at a given address with a given amount. Returns the + updated context and a balance update receipt (singleton list). The address + must be a valid base58 hash, otherwise this is no-op and returns an empty + receipts list. + + Do not fail if something goes wrong. +*) + +let invoice_contract ctxt ~address ~amount_mutez = + let open Lwt_result_syntax in + match Tez_repr.of_mutez amount_mutez with + | None -> Lwt.return (ctxt, []) + | Some amount -> ( + let*! result = + let*? recipient = Contract_repr.of_b58check address in + Token.transfer + ~origin:Protocol_migration + ctxt + `Invoice + (`Contract recipient) + amount + in + Lwt.return @@ match result with Ok res -> res | Error _ -> (ctxt, [])) +*) + +(* + To patch code of legacy contracts you can add a helper function here and call + it at the end of prepare_first_block. + + See !3730 for an example. +*) + +let patch_script ctxt (address, hash, patched_code) = + let open Lwt_result_syntax in + let*? contract = Contract_repr.of_b58check address in + let* ctxt, code_opt = Storage.Contract.Code.find ctxt contract in + Logging.log Notice "Patching %s... " address ; + match code_opt with + | Some old_code -> + let old_bin = Data_encoding.force_bytes old_code in + let old_hash = Script_expr_hash.hash_bytes [old_bin] in + if Script_expr_hash.equal old_hash hash then ( + let new_code = Script_repr.lazy_expr patched_code in + let* ctxt, size_diff = + Storage.Contract.Code.update ctxt contract new_code + in + Logging.log Notice "Contract %s successfully patched" address ; + let size_diff = Z.of_int size_diff in + let* prev_size = + Storage.Contract.Used_storage_space.get ctxt contract + in + let new_size = Z.add prev_size size_diff in + let* ctxt = + Storage.Contract.Used_storage_space.update ctxt contract new_size + in + if Z.(gt size_diff zero) then + let* prev_paid_size = + Storage.Contract.Paid_storage_space.get ctxt contract + in + let paid_size = Z.add prev_paid_size size_diff in + Storage.Contract.Paid_storage_space.update ctxt contract paid_size + else return ctxt) + else ( + Logging.log + Error + "Patching %s was skipped because its script does not have the \ + expected hash (expected: %a, found: %a)" + address + Script_expr_hash.pp + hash + Script_expr_hash.pp + old_hash ; + return ctxt) + | None -> + Logging.log + Error + "Patching %s was skipped because no script was found for it in the \ + context." + address ; + return ctxt + +let migrate_already_denounced_from_Oxford ctxt = + let open Lwt_syntax in + let migrate_cycle ctxt cycle = + let* ctxt = + Storage.Already_denounced__Oxford.fold + (ctxt, cycle) + ~order:`Undefined + ~init:ctxt + ~f:(fun (level, delegate) {for_double_attesting; for_double_baking} ctxt + -> + Storage.Already_denounced.add + (ctxt, cycle) + ((level, Round_repr.zero), delegate) + { + for_double_preattesting = for_double_attesting; + for_double_attesting; + for_double_baking; + }) + in + Storage.Already_denounced__Oxford.clear (ctxt, cycle) + in + (* Since the max_slashing_period is 2, denunciations are only + relevant if the misbehaviour happened in either the current cycle + or the previous cycle. *) + let current_cycle = (Level_storage.current ctxt).cycle in + let* ctxt = migrate_cycle ctxt current_cycle in + match Cycle_repr.pred current_cycle with + | None -> return ctxt + | Some previous_cycle -> migrate_cycle ctxt previous_cycle + +(* This removes snapshots and moves the current [staking_balance] one level + up. Same thing for active delegates with minimal stake but renames the key + at the same time. *) +let migrate_staking_balance_and_active_delegates_for_p ctxt = + let open Lwt_result_syntax in + let* staking_balance_tree = + Raw_context.get_tree ctxt ["staking_balance"; "current"] + in + let*! ctxt = + Raw_context.add_tree ctxt ["staking_balance"] staking_balance_tree + in + let* active_delegates_tree = + Raw_context.get_tree ctxt ["active_delegate_with_one_roll"; "current"] + in + let*! ctxt = Raw_context.remove ctxt ["active_delegate_with_one_roll"] in + let*! ctxt = + Raw_context.add_tree + ctxt + ["active_delegates_with_minimal_stake"] + active_delegates_tree + in + return ctxt + +(* This should clean most of the remaining fields [frozen_deposits]. + The field was removed in Oxford but cleaning it using [remove] was too + costly as it iterated over all contracts. + Instead we iterate over activate delegates. + If there are remaining [frozen_deposits] once P activates, they can still be + removed one by one in Q. *) +let clean_frozen_deposits_for_p ctxt = + let open Lwt_result_syntax in + let contracts_index = ["contracts"; "index"] in + let* contracts_tree = Raw_context.get_tree ctxt contracts_index in + let field = ["frozen_deposits"] in + let*! contracts_tree = + Storage.Stake.Active_delegates_with_minimal_stake.fold + ctxt + ~order:`Undefined + ~init:contracts_tree + ~f:(fun pkh contracts_tree -> + let path = Contract_repr.Index.to_path (Implicit pkh) field in + Raw_context.Tree.remove contracts_tree path) + in + Raw_context.update_tree ctxt contracts_index contracts_tree + +let cleanup_values_for_protocol_p ctxt + (previous_proto_constants : Constants_parametric_previous_repr.t option) + level = + let open Lwt_result_syntax in + let preserved_cycles = + let previous_proto_constants = + match previous_proto_constants with + | None -> + (* Shouldn't happen *) + failwith + "Internal error: cannot read previous protocol constants in \ + context." + | Some c -> c + in + previous_proto_constants.preserved_cycles + in + let consensus_rights_delay = Constants_storage.consensus_rights_delay ctxt in + let new_cycle = + let next_level = Raw_level_repr.succ level in + let cycle_eras = Raw_context.cycle_eras ctxt in + (Level_repr.level_from_raw ~cycle_eras next_level).cycle + in + let* ctxt = + Stake_storage.cleanup_values_for_protocol_p + ctxt + ~preserved_cycles + ~consensus_rights_delay + ~new_cycle + in + let* ctxt = + Delegate_sampler.cleanup_values_for_protocol_p + ctxt + ~preserved_cycles + ~consensus_rights_delay + ~new_cycle + in + return ctxt + +let reset_adaptive_issuance_ema_for_p ctxt = + Storage.Adaptive_issuance.Launch_ema.add ctxt 0l + +(** Updates the total supply with refined estimation at the activation + of P using measures from + https://gitlab.com/tezos/tezos/-/merge_requests/11978. + + Remove me in Q. *) +let update_total_supply_for_p chain_id ctxt = + let open Lwt_result_syntax in + (* We only update the total supply for mainnet. *) + if Chain_id.equal Constants_repr.mainnet_id chain_id then + let* current_total_supply = Storage.Contract.Total_supply.get ctxt in + let*? updated_total_supply = + Tez_repr.(current_total_supply +? of_mutez_exn 16458634911983L) + in + let*! ctxt = Storage.Contract.Total_supply.add ctxt updated_total_supply in + return ctxt + else return ctxt + +let prepare_first_block chain_id ctxt ~typecheck_smart_contract + ~typecheck_smart_rollup ~level ~timestamp ~predecessor = + let open Lwt_result_syntax in + let* previous_protocol, previous_proto_constants, ctxt = + Raw_context.prepare_first_block ~level ~timestamp chain_id ctxt + in + let parametric = Raw_context.constants ctxt in + let*! ctxt = + let*! ctxt = + Raw_context.Cache.set_cache_layout + ctxt + (Constants_repr.cache_layout parametric) + in + Lwt.return (Raw_context.Cache.clear ctxt) + in + let* ctxt, balance_updates = + match previous_protocol with + | Genesis param -> + (* This is the genesis protocol: initialise the state *) + let*? level = Raw_level_repr.of_int32 level in + let* ctxt = + Storage.Tenderbake.First_level_of_protocol.init ctxt level + in + let* ctxt = Forbidden_delegates_storage.init_for_genesis ctxt in + let*! ctxt = Storage.Contract.Total_supply.add ctxt Tez_repr.zero in + let* ctxt = Storage.Block_round.init ctxt Round_repr.zero in + let init_commitment (ctxt, balance_updates) + Commitment_repr.{blinded_public_key_hash; amount} = + let* ctxt, new_balance_updates = + Token.transfer + ctxt + `Initial_commitments + (`Collected_commitments blinded_public_key_hash) + amount + in + return (ctxt, new_balance_updates @ balance_updates) + in + let* ctxt, commitments_balance_updates = + List.fold_left_es init_commitment (ctxt, []) param.commitments + in + let* ctxt = + Seed_storage.init ?initial_seed:param.constants.initial_seed ctxt + in + let* ctxt = Contract_storage.init ctxt in + let* ctxt, bootstrap_balance_updates = + Bootstrap_storage.init + ctxt + ~typecheck_smart_contract + ~typecheck_smart_rollup + ?no_reward_cycles:param.no_reward_cycles + param.bootstrap_accounts + param.bootstrap_contracts + param.bootstrap_smart_rollups + in + let* ctxt = Delegate_cycles.init_first_cycles ctxt in + let* ctxt = + Vote_storage.init + ctxt + ~start_position:(Level_storage.current ctxt).level_position + in + let* ctxt = Vote_storage.update_listings ctxt in + (* Must be called after other originations since it unsets the origination nonce. *) + let* ctxt, operation_results = + Liquidity_baking_migration.init + ctxt + ~typecheck:typecheck_smart_contract + in + let* ctxt = + Storage.Pending_migration.Operation_results.init + ctxt + operation_results + in + let* ctxt = Sc_rollup_inbox_storage.init_inbox ~predecessor ctxt in + let* ctxt = Adaptive_issuance_storage.init ctxt in + return (ctxt, commitments_balance_updates @ bootstrap_balance_updates) + | Oxford_018 + (* Please update [next_protocol] and [previous_protocol] in + [tezt/lib_tezos/protocol.ml] when you update this value. *) -> + (* TODO (#2704): possibly handle attestations for migration block (in bakers); + if that is done, do not set Storage.Tenderbake.First_level_of_protocol. + /!\ this storage is also use to add the smart rollup + inbox migration message. see `sc_rollup_inbox_storage`. *) + let*? level = Raw_level_repr.of_int32 level in + let* ctxt = + Storage.Tenderbake.First_level_of_protocol.update ctxt level + in + (* Migration of refutation games needs to be kept for each protocol. *) + let* ctxt = + Sc_rollup_refutation_storage.migrate_clean_refutation_games ctxt + in + (* Adaptive Issuance-related migrations from Oxford to P. *) + (* We usually clear the table at the end of the cycle but the migration + can happen in the middle of the cycle, so we clear it here. + Possible consequence: the slashing history could be inconsistent with + the pending denunciations, i.e., there could be unstaked_frozen_deposits + that are not slashed whereas unstake_requests are slashed. *) + let*! ctxt = Pending_denunciations_storage.clear ctxt in + let*! ctxt = migrate_already_denounced_from_Oxford ctxt in + let* ctxt = migrate_staking_balance_and_active_delegates_for_p ctxt in + let* ctxt = clean_frozen_deposits_for_p ctxt in + let*! ctxt = Raw_context.remove ctxt ["last_snapshot"] in + let* ctxt = + cleanup_values_for_protocol_p ctxt previous_proto_constants level + in + let* ctxt = update_total_supply_for_p chain_id ctxt in + let*! ctxt = reset_adaptive_issuance_ema_for_p ctxt in + return (ctxt, []) + in + let* ctxt = + List.fold_left_es patch_script ctxt Legacy_script_patches.addresses_to_patch + in + let*? balance_updates = Receipt_repr.group_balance_updates balance_updates in + let*! ctxt = + Storage.Pending_migration.Balance_updates.add ctxt balance_updates + in + if Constants_storage.adaptive_issuance_force_activation ctxt then + let ctxt = Raw_context.set_adaptive_issuance_enable ctxt in + let* ctxt = + let current_cycle = (Level_storage.current ctxt).cycle in + Storage.Adaptive_issuance.Activation.update ctxt (Some current_cycle) + in + return ctxt + else return ctxt + +let prepare ctxt ~level ~predecessor_timestamp ~timestamp = + let open Lwt_result_syntax in + let* ctxt = + Raw_context.prepare + ~level + ~predecessor_timestamp + ~timestamp + ~adaptive_issuance_enable:false + ctxt + in + let* ctxt = Adaptive_issuance_storage.set_adaptive_issuance_enable ctxt in + Storage.Pending_migration.remove ctxt diff --git a/src/proto_020_PsParisC/lib_protocol/init_storage.mli b/src/proto_020_PsParisC/lib_protocol/init_storage.mli new file mode 100644 index 000000000000..35cef8c0e2cd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/init_storage.mli @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Functions to setup storage. Used by [Alpha_context.prepare]. + + If you have defined a new type of storage, you should add relevant + setups here. + *) + +(* This is the genesis protocol: initialise the state *) +val prepare_first_block : + Chain_id.t -> + Context.t -> + typecheck_smart_contract: + (Raw_context.t -> + Script_repr.t -> + ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) + Error_monad.tzresult + Lwt.t) -> + typecheck_smart_rollup: + (Raw_context.t -> Script_repr.expr -> Raw_context.t tzresult) -> + level:int32 -> + timestamp:Time.t -> + predecessor:Block_hash.t -> + (Raw_context.t, Error_monad.error Error_monad.trace) Pervasives.result Lwt.t + +val prepare : + Context.t -> + level:Int32.t -> + predecessor_timestamp:Time.t -> + timestamp:Time.t -> + (Raw_context.t + * Receipt_repr.balance_updates + * Migration_repr.origination_result list) + Error_monad.tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.ml b/src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.ml new file mode 100644 index 000000000000..204138251752 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.ml @@ -0,0 +1,66 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type t = Q.t + +type max_bonus = t + +(* Bonus will represent a fraction of the total supply, so its precision + should be in the order of magnitude of the total supply. *) +(* Order of magnitude of the total supply in mutez + Approximately 2^50 *) +let bonus_unit = Q.of_int64 1_000_000_000_000_000L + +let zero = Q.zero + +let check_bounds ~max_bonus q = Q.(q >= zero && q <= max_bonus) + [@@inline always] + +type error += Out_of_bounds_bonus + +let () = + Error_monad.register_error_kind + `Permanent + ~id:"out_of_bound_issuance_bonus" + ~title:"Out of bound issuance bonus" + ~description:"Computed issuance bonus is out of bound" + ~pp:(fun ppf () -> + Format.fprintf ppf "Computed issuance bonus is out of bound") + Data_encoding.unit + (function Out_of_bounds_bonus -> Some () | _ -> None) + (fun () -> Out_of_bounds_bonus) + +let of_Q ~max_bonus q = + let open Result_syntax in + if check_bounds ~max_bonus q then return q else tzfail Out_of_bounds_bonus + [@@inline always] + +let of_Q_unbounded q = if check_bounds ~max_bonus:Q.one q then Some q else None + +let of_int64_repr i = of_Q_unbounded Q.(div (of_int64 i) bonus_unit) + +let of_int64_repr_err i = + let open Result_syntax in + match of_int64_repr i with + | Some bonus -> return bonus + | None -> fail "Issuance bonus must be between 0 and 1" + +let to_int64_repr q = Q.(mul q bonus_unit |> to_int64) + +let encoding = + Data_encoding.conv_with_guard + to_int64_repr + of_int64_repr_err + Data_encoding.int64 + +let max_bonus_encoding = encoding + +let max_bonus_parameter_of_Q_exn q = + match of_Q_unbounded q with + | Some max_bonus -> max_bonus + | None -> + failwith "Invalid parameter: max_bonus parameter must be between 0 and 1" diff --git a/src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.mli b/src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.mli new file mode 100644 index 000000000000..0933e26ed793 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/issuance_bonus_repr.mli @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Issuance bonus. + + The issuance bonus is a rational but is stored as fixed point integer + to limit the serialized size as with Q we would have no control on the size + each component (numerator, denominator). + + It is expected to always be between 0 and the protocol's parametric + constant [max_bonus]. + The int64 encoding of the bonus is made such that the approximation + resulting of this encoding is negligible when the bonus is used in a + context where the total supply of the network is in the order of magnitude + of 2^50 mutez (10^15 mutez) +*) + +(** An issuance bonus is a rational between zero and some [max_bonus]. *) +type t = private Q.t + +(** A [max_bonus] is a value between zero and one. *) +type max_bonus = private t + +val zero : t + +val encoding : t Data_encoding.t + +val max_bonus_encoding : max_bonus Data_encoding.t + +(** Getting a bonus out of rational. + It will fail if the decoding doesn't provide a value that is valid wrt + protocol's parametric constants + *) +val of_Q : max_bonus:max_bonus -> Q.t -> t tzresult + +(** Use only to define the [max_bonus] parameter from [Default_parameters]. *) +val max_bonus_parameter_of_Q_exn : Q.t -> max_bonus diff --git a/src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.ml b/src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.ml new file mode 100644 index 000000000000..ef23bdffa61f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.ml @@ -0,0 +1,428 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +module type Next = sig + type id + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t +end + +module type Total_bytes = sig + type id + + val init : Raw_context.t -> id -> Z.t -> Raw_context.t tzresult Lwt.t + + val get : Raw_context.t -> id -> Z.t tzresult Lwt.t + + val update : Raw_context.t -> id -> Z.t -> Raw_context.t tzresult Lwt.t +end + +(** Operations to be defined on a lazy storage type. *) +module type OPS = sig + module Id : Lazy_storage_kind.ID + + type alloc + + type updates + + val title : string + + val alloc_encoding : alloc Data_encoding.t + + val updates_encoding : updates Data_encoding.t + + val alloc_in_memory_size : alloc -> Cache_memory_helpers.nodes_and_size + + val updates_in_memory_size : updates -> Cache_memory_helpers.nodes_and_size + + val bytes_size_for_empty : Z.t + + val alloc : Raw_context.t -> id:Id.t -> alloc -> Raw_context.t tzresult Lwt.t + + val apply_updates : + Raw_context.t -> id:Id.t -> updates -> (Raw_context.t * Z.t) tzresult Lwt.t + + module Next : Next with type id := Id.t + + module Total_bytes : Total_bytes with type id := Id.t + + (** Deep copy. *) + val copy : + Raw_context.t -> from:Id.t -> to_:Id.t -> Raw_context.t tzresult Lwt.t + + (** Deep deletion. *) + val remove : Raw_context.t -> Id.t -> Raw_context.t Lwt.t +end + +module Big_map = struct + include Lazy_storage_kind.Big_map + + let alloc_in_memory_size {key_type; value_type} = + let open Cache_memory_helpers in + ret_adding + (expr_size key_type ++ expr_size value_type) + (header_size +! (word_size *? 2)) + + let updates_in_memory_size updates = + let open Cache_memory_helpers in + let update_size {key; key_hash = _; value} = + ret_adding + (expr_size key ++ option_size_vec expr_size value) + (header_size +! (word_size *? 3) +? Script_expr_hash.size) + in + list_fold_size update_size updates + + let bytes_size_for_big_map_key = 65 + + let bytes_size_for_empty = + let bytes_size_for_big_map = 33 in + Z.of_int bytes_size_for_big_map + + let alloc ctxt ~id {key_type; value_type} = + (* Annotations are erased to allow sharing on [Copy]. The types from the + contract code are used, these ones are only used to make sure they are + compatible during transmissions between contracts, and only need to be + compatible, annotations notwithstanding. *) + let open Lwt_result_syntax in + let key_type = + Micheline.strip_locations + (Script_repr.strip_annotations (Micheline.root key_type)) + in + let value_type = + Micheline.strip_locations + (Script_repr.strip_annotations (Micheline.root value_type)) + in + let* ctxt = Storage.Big_map.Key_type.init ctxt id key_type in + Storage.Big_map.Value_type.init ctxt id value_type + + let apply_update ctxt ~id + { + key = _key_is_shown_only_on_the_receipt_in_print_big_map_diff; + key_hash; + value; + } = + let open Lwt_result_syntax in + match value with + | None -> + let+ ctxt, freed, existed = + Storage.Big_map.Contents.remove (ctxt, id) key_hash + in + let freed = + if existed then freed + bytes_size_for_big_map_key else freed + in + (ctxt, Z.of_int ~-freed) + | Some v -> + let+ ctxt, size_diff, existed = + Storage.Big_map.Contents.add (ctxt, id) key_hash v + in + let size_diff = + if existed then size_diff else size_diff + bytes_size_for_big_map_key + in + (ctxt, Z.of_int size_diff) + + let apply_updates ctxt ~id updates = + let open Lwt_result_syntax in + List.fold_left_es + (fun (ctxt, size) update -> + let+ ctxt, added_size = apply_update ctxt ~id update in + (ctxt, Z.add size added_size)) + (ctxt, Z.zero) + updates + + include Storage.Big_map +end + +type ('id, 'alloc, 'updates) ops = + (module OPS + with type Id.t = 'id + and type alloc = 'alloc + and type updates = 'updates) + +module Sapling_state = struct + include Lazy_storage_kind.Sapling_state + + let alloc_in_memory_size {memo_size = (_ : int)} = + let open Cache_memory_helpers in + (Nodes.zero, header_size +! word_size) + + let updates_in_memory_size update = + (Cache_memory_helpers.Nodes.zero, Sapling_repr.diff_in_memory_size update) + + let bytes_size_for_empty = Z.of_int 33 + + let alloc ctxt ~id {memo_size} = Sapling_storage.init ctxt id ~memo_size + + let apply_updates ctxt ~id updates = + Sapling_storage.apply_diff ctxt id updates + + include Storage.Sapling +end + +(* + To add a new lazy storage kind here, you only need to create a module similar + to [Big_map] above and add a case to [get_ops] below. +*) + +let get_ops : type i a u. (i, a, u) Lazy_storage_kind.t -> (i, a, u) ops = + function + | Big_map -> (module Big_map) + | Sapling_state -> (module Sapling_state) + +type ('id, 'alloc) init = Existing | Copy of {src : 'id} | Alloc of 'alloc + +type ('id, 'alloc, 'updates) diff = + | Remove + | Update of {init : ('id, 'alloc) init; updates : 'updates} + +let diff_encoding : type i a u. (i, a, u) ops -> (i, a, u) diff Data_encoding.t + = + fun (module OPS) -> + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"update" + (obj2 + (req "action" (constant "update")) + (req "updates" OPS.updates_encoding)) + (function + | Update {init = Existing; updates} -> Some ((), updates) | _ -> None) + (fun ((), updates) -> Update {init = Existing; updates}); + case + (Tag 1) + ~title:"remove" + (obj1 (req "action" (constant "remove"))) + (function Remove -> Some () | _ -> None) + (fun () -> Remove); + case + (Tag 2) + ~title:"copy" + (obj3 + (req "action" (constant "copy")) + (req "source" OPS.Id.encoding) + (req "updates" OPS.updates_encoding)) + (function + | Update {init = Copy {src}; updates} -> Some ((), src, updates) + | _ -> None) + (fun ((), src, updates) -> Update {init = Copy {src}; updates}); + case + (Tag 3) + ~title:"alloc" + (merge_objs + (obj2 + (req "action" (constant "alloc")) + (req "updates" OPS.updates_encoding)) + OPS.alloc_encoding) + (function + | Update {init = Alloc alloc; updates} -> Some (((), updates), alloc) + | _ -> None) + (fun (((), updates), alloc) -> Update {init = Alloc alloc; updates}); + ] + +let init_size : + type i a u. + (i, a, u) ops -> (i, a) init -> Cache_memory_helpers.nodes_and_size = + fun (module OPS) init -> + let open Cache_memory_helpers in + match init with + | Existing -> zero + | Copy {src = _id_is_a_Z_fitting_in_an_int_for_a_long_time} -> + (Nodes.zero, header_size +! word_size) + | Alloc alloc -> + ret_adding (OPS.alloc_in_memory_size alloc) (header_size +! word_size) + +let updates_size : + type i a u. (i, a, u) ops -> u -> Cache_memory_helpers.nodes_and_size = + fun (module OPS) updates -> OPS.updates_in_memory_size updates + +let diff_in_memory_size kind diff = + let open Cache_memory_helpers in + match diff with + | Remove -> zero + | Update {init; updates} -> + let ops = get_ops kind in + ret_adding (init_size ops init ++ updates_size ops updates) h2w + +(** + [apply_updates ctxt ops ~id init] applies the updates [updates] on lazy + storage [id] on storage context [ctxt] using operations [ops] and returns the + updated storage context and the added size in bytes (may be negative). +*) +let apply_updates : + type i a u. + Raw_context.t -> + (i, a, u) ops -> + id:i -> + u -> + (Raw_context.t * Z.t) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt (module OPS) ~id updates -> + let* ctxt, updates_size = OPS.apply_updates ctxt ~id updates in + if Z.(equal updates_size zero) then return (ctxt, updates_size) + else + let* size = OPS.Total_bytes.get ctxt id in + let+ ctxt = OPS.Total_bytes.update ctxt id (Z.add size updates_size) in + (ctxt, updates_size) + +(** + [apply_init ctxt ops ~id init] applies the initialization [init] on lazy + storage [id] on storage context [ctxt] using operations [ops] and returns the + updated storage context and the added size in bytes (may be negative). + + If [id] represents a temporary lazy storage, the added size may be wrong. +*) +let apply_init : + type i a u. + Raw_context.t -> + (i, a, u) ops -> + id:i -> + (i, a) init -> + (Raw_context.t * Z.t) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt (module OPS) ~id init -> + match init with + | Existing -> return (ctxt, Z.zero) + | Copy {src} -> + let* ctxt = OPS.copy ctxt ~from:src ~to_:id in + if OPS.Id.is_temp id then return (ctxt, Z.zero) + else + let+ copy_size = OPS.Total_bytes.get ctxt src in + (ctxt, Z.add copy_size OPS.bytes_size_for_empty) + | Alloc alloc -> + let* ctxt = OPS.Total_bytes.init ctxt id Z.zero in + let+ ctxt = OPS.alloc ctxt ~id alloc in + (ctxt, OPS.bytes_size_for_empty) + +(** + [apply_diff ctxt ops ~id diff] applies the diff [diff] on lazy storage [id] + on storage context [ctxt] using operations [ops] and returns the updated + storage context and the added size in bytes (may be negative). + + If [id] represents a temporary lazy storage, the added size may be wrong. +*) +let apply_diff : + type i a u. + Raw_context.t -> + (i, a, u) ops -> + id:i -> + (i, a, u) diff -> + (Raw_context.t * Z.t) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt ((module OPS) as ops) ~id diff -> + match diff with + | Remove -> + if OPS.Id.is_temp id then + let*! ctxt = OPS.remove ctxt id in + return (ctxt, Z.zero) + else + let* size = OPS.Total_bytes.get ctxt id in + let*! ctxt = OPS.remove ctxt id in + return (ctxt, Z.neg (Z.add size OPS.bytes_size_for_empty)) + | Update {init; updates} -> + let* ctxt, init_size = apply_init ctxt ops ~id init in + let* ctxt, updates_size = apply_updates ctxt ops ~id updates in + return (ctxt, Z.add init_size updates_size) + +type diffs_item = + | Item : + ('i, 'a, 'u) Lazy_storage_kind.t * 'i * ('i, 'a, 'u) diff + -> diffs_item + +let make : + type i a u. + (i, a, u) Lazy_storage_kind.t -> i -> (i, a, u) diff -> diffs_item = + fun k id diff -> Item (k, id, diff) + +let item_encoding = + let open Data_encoding in + union + @@ List.map + (fun (tag, Lazy_storage_kind.Ex_Kind k) -> + let ops = get_ops k in + let (module OPS) = ops in + let title = OPS.title in + case + (Tag tag) + ~title + (obj3 + (req "kind" (constant title)) + (req "id" OPS.Id.encoding) + (req "diff" (diff_encoding ops))) + (fun (Item (kind, id, diff)) -> + match Lazy_storage_kind.equal k kind with + | Eq -> Some ((), id, diff) + | Neq -> None) + (fun ((), id, diff) -> Item (k, id, diff))) + Lazy_storage_kind.all + +let item_in_memory_size + (Item + ( kind (* kinds are constant tags *), + _id_is_a_Z_fitting_in_an_int_for_a_long_time, + diff )) = + let open Cache_memory_helpers in + ret_adding (diff_in_memory_size kind diff) h3w + +type diffs = diffs_item list + +let diffs_in_memory_size diffs = + Cache_memory_helpers.list_fold_size item_in_memory_size diffs + +let encoding = + let open Data_encoding in + def "lazy_storage_diff" @@ list item_encoding + +let apply ctxt diffs = + let open Lwt_result_syntax in + List.fold_left_es + (fun (ctxt, total_size) (Item (k, id, diff)) -> + let ops = get_ops k in + let+ ctxt, added_size = apply_diff ctxt ops ~id diff in + let (module OPS) = ops in + ( ctxt, + if OPS.Id.is_temp id then total_size else Z.add total_size added_size )) + (ctxt, Z.zero) + diffs + +let fresh : + type i a u. + (i, a, u) Lazy_storage_kind.t -> + temporary:bool -> + Raw_context.t -> + (Raw_context.t * i) tzresult Lwt.t = + fun kind ~temporary ctxt -> + if temporary then + return + (Raw_context.fold_map_temporary_lazy_storage_ids ctxt (fun temp_ids -> + Lazy_storage_kind.Temp_ids.fresh kind temp_ids)) + else + let (module OPS) = get_ops kind in + OPS.Next.incr ctxt + +let init ctxt = + List.fold_left_es + (fun ctxt (_tag, Lazy_storage_kind.Ex_Kind k) -> + let (module OPS) = get_ops k in + OPS.Next.init ctxt) + ctxt + Lazy_storage_kind.all + +let cleanup_temporaries ctxt = + let open Lwt_syntax in + Raw_context.map_temporary_lazy_storage_ids_s ctxt (fun temp_ids -> + let+ ctxt = + List.fold_left_s + (fun ctxt (_tag, Lazy_storage_kind.Ex_Kind k) -> + let (module OPS) = get_ops k in + Lazy_storage_kind.Temp_ids.fold_s k OPS.remove temp_ids ctxt) + ctxt + Lazy_storage_kind.all + in + (ctxt, Lazy_storage_kind.Temp_ids.init)) diff --git a/src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.mli b/src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.mli new file mode 100644 index 000000000000..928117683ea2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/lazy_storage_diff.mli @@ -0,0 +1,53 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** + See [Lazy_storage_kind] for an introduction on lazy storage. + + This module defines operations on lazy storage types and diffs. +*) + +type ('id, 'alloc) init = Existing | Copy of {src : 'id} | Alloc of 'alloc + +type ('id, 'alloc, 'updates) diff = + | Remove + | Update of {init : ('id, 'alloc) init; updates : 'updates} + +(* Exposing this type is needed only for legacy big map diff. *) +type diffs_item = private + | Item : + ('i, 'a, 'u) Lazy_storage_kind.t * 'i * ('i, 'a, 'u) diff + -> diffs_item + +val make : + ('i, 'a, 'u) Lazy_storage_kind.t -> 'i -> ('i, 'a, 'u) diff -> diffs_item + +type diffs = diffs_item list + +val diffs_in_memory_size : diffs -> Cache_memory_helpers.nodes_and_size + +val encoding : diffs Data_encoding.t + +(** + The returned [Z.t] is the size added by the application of the diffs. +*) +val apply : Raw_context.t -> diffs -> (Raw_context.t * Z.t) tzresult Lwt.t + +val fresh : + ('id, _, _) Lazy_storage_kind.t -> + temporary:bool -> + Raw_context.t -> + (Raw_context.t * 'id) tzresult Lwt.t + +(** + Initializes the storage for all lazy storage kind. + This is useful for genesis only. + Protocol updates need to initialize new lazy storage kinds. +*) +val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val cleanup_temporaries : Raw_context.t -> Raw_context.t Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.ml b/src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.ml new file mode 100644 index 000000000000..59094d029334 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.ml @@ -0,0 +1,321 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type TEMP_ID = sig + type t + + val equal : t -> t -> bool + + val init : t + + val next : t -> t +end + +module type ID = sig + type t + + val compare : t -> t -> int + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + val init : t + + (** In the protocol, to be used in parse_data only *) + val parse_z : Z.t -> t + + (** In the protocol, to be used in unparse_data only *) + val unparse_to_z : t -> Z.t + + val next : t -> t + + val is_temp : t -> bool + + val of_legacy_USE_ONLY_IN_Legacy_big_map_diff : Z.t -> t + + val to_legacy_USE_ONLY_IN_Legacy_big_map_diff : t -> Z.t + + include Path_encoding.S with type t := t +end + +module type Title = sig + val title : string +end + +module type TitleWithId = sig + val title : string + + module Id : ID + + module Temp_id : TEMP_ID with type t = private Id.t + + module IdSet : Set.S with type elt = Id.t +end + +module MakeId (Title : Title) : TitleWithId = struct + let title = Title.title + + let title_words = String.map (function '_' -> ' ' | c -> c) title + + let rpc_arg_error = Format.sprintf "Cannot parse %s id" title_words + + let description = Format.sprintf "A %s identifier" title_words + + let name = title ^ "_id" + + let encoding_title = String.capitalize_ascii title_words ^ " identifier" + + module Id = struct + type t = Z.t + + let compare = Z.compare + + let encoding = + Data_encoding.def name ~title:encoding_title ~description Data_encoding.z + + let rpc_arg = + let construct = Z.to_string in + let destruct hash = + Result.catch_f (fun () -> Z.of_string hash) (fun _ -> rpc_arg_error) + in + RPC_arg.make ~descr:description ~name ~construct ~destruct () + + let init = Z.zero + + let parse_z (z : Z.t) : t = z + + let unparse_to_z (z : t) : Z.t = z + + let next = Z.succ + + let of_legacy_USE_ONLY_IN_Legacy_big_map_diff (z : Z.t) : t = z + + let to_legacy_USE_ONLY_IN_Legacy_big_map_diff (z : t) : Z.t = z + + let is_temp z = Compare.Z.(z < Z.zero) + + let path_length = 1 + + let to_path z l = Z.to_string z :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [z] -> Some (Z.of_string z) + end + + module Temp_id = struct + type t = Id.t + + let equal = Z.equal + + let init = Z.of_int ~-1 + + let next z = Z.sub z Z.one + end + + module IdSet = Set.Make (Id) +end + +module Big_map = struct + include MakeId (struct + let title = "big_map" + end) + + type alloc = {key_type : Script_repr.expr; value_type : Script_repr.expr} + + type update = { + key : Script_repr.expr; + (** The key is ignored by [apply_update] but is shown in the receipt, + as specified in [print_big_map_diff]. *) + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = update list + + let alloc_encoding = + let open Data_encoding in + conv + (fun {key_type; value_type} -> (key_type, value_type)) + (fun (key_type, value_type) -> {key_type; value_type}) + (obj2 + (req "key_type" Script_repr.expr_encoding) + (req "value_type" Script_repr.expr_encoding)) + + let update_encoding = + let open Data_encoding in + conv + (fun {key_hash; key; value} -> (key_hash, key, value)) + (fun (key_hash, key, value) -> {key_hash; key; value}) + (obj3 + (req "key_hash" Script_expr_hash.encoding) + (req "key" Script_repr.expr_encoding) + (opt "value" Script_repr.expr_encoding)) + + let updates_encoding = Data_encoding.list update_encoding +end + +module Sapling_state = struct + include MakeId (struct + let title = "sapling_state" + end) + + type alloc = {memo_size : Sapling_repr.Memo_size.t} + + type updates = Sapling_repr.diff + + let alloc_encoding = + let open Data_encoding in + conv + (fun {memo_size} -> memo_size) + (fun memo_size -> {memo_size}) + (obj1 (req "memo_size" Sapling_repr.Memo_size.encoding)) + + let updates_encoding = Sapling_repr.diff_encoding +end + +(* + When adding cases to this type, grep for [new lazy storage kind] in the code + for locations to update. + It must be: + - the value [all] right below, + - modules [Temp_ids], [IdSet] below, + - the rest should be guided by type errors. +*) +type ('id, 'alloc, 'updates) t = + | Big_map : (Big_map.Id.t, Big_map.alloc, Big_map.updates) t + | Sapling_state + : (Sapling_state.Id.t, Sapling_state.alloc, Sapling_state.updates) t + +type ex = Ex_Kind : (_, _, _) t -> ex + +(* /!\ Don't forget to add new lazy storage kinds here. /!\ *) +let all = [(0, Ex_Kind Big_map); (1, Ex_Kind Sapling_state)] + +type (_, _) cmp = Eq : ('a, 'a) cmp | Neq + +let equal : + type i1 a1 u1 i2 a2 u2. + (i1, a1, u1) t -> (i2, a2, u2) t -> (i1 * a1 * u1, i2 * a2 * u2) cmp = + fun k1 k2 -> + match (k1, k2) with + | Big_map, Big_map -> Eq + | Sapling_state, Sapling_state -> Eq + | Big_map, _ -> Neq + | _, Big_map -> Neq + +type ('i, 'a, 'u) kind = ('i, 'a, 'u) t + +module Temp_ids = struct + type t = { + big_map : Big_map.Temp_id.t; + sapling_state : Sapling_state.Temp_id.t; + } + + let init = + {big_map = Big_map.Temp_id.init; sapling_state = Sapling_state.Temp_id.init} + + let fresh : type i a u. (i, a, u) kind -> t -> t * i = + fun kind temp_ids -> + match kind with + | Big_map -> + let big_map = Big_map.Temp_id.next temp_ids.big_map in + ({temp_ids with big_map}, (temp_ids.big_map :> Big_map.Id.t)) + | Sapling_state -> + let sapling_state = Sapling_state.Temp_id.next temp_ids.sapling_state in + ( {temp_ids with sapling_state}, + (temp_ids.sapling_state :> Sapling_state.Id.t) ) + + let fold_s : + type i a u. + (i, a, u) kind -> ('acc -> i -> 'acc Lwt.t) -> t -> 'acc -> 'acc Lwt.t = + let open Lwt_syntax in + fun kind f temp_ids acc -> + let helper (type j) (module Temp_id : TEMP_ID with type t = j) ~last f = + let rec aux acc id = + if Temp_id.equal id last then Lwt.return acc + else + let* acc = f acc id in + aux acc (Temp_id.next id) + in + aux acc Temp_id.init + in + match kind with + | Big_map -> + helper + (module Big_map.Temp_id) + ~last:temp_ids.big_map + (fun acc temp_id -> f acc (temp_id :> i)) + | Sapling_state -> + helper + (module Sapling_state.Temp_id) + ~last:temp_ids.sapling_state + (fun acc temp_id -> f acc (temp_id :> i)) +end + +module IdSet = struct + type t = {big_map : Big_map.IdSet.t; sapling_state : Sapling_state.IdSet.t} + + type 'acc fold_f = {f : 'i 'a 'u. ('i, 'a, 'u) kind -> 'i -> 'acc -> 'acc} + + let empty = + {big_map = Big_map.IdSet.empty; sapling_state = Sapling_state.IdSet.empty} + + let mem (type i a u) (kind : (i, a, u) kind) (id : i) set = + match (kind, set) with + | Big_map, {big_map; _} -> Big_map.IdSet.mem id big_map + | Sapling_state, {sapling_state; _} -> + Sapling_state.IdSet.mem id sapling_state + + let add (type i a u) (kind : (i, a, u) kind) (id : i) set = + match (kind, set) with + | Big_map, {big_map; _} -> + let big_map = Big_map.IdSet.add id big_map in + {set with big_map} + | Sapling_state, {sapling_state; _} -> + let sapling_state = Sapling_state.IdSet.add id sapling_state in + {set with sapling_state} + + let diff set1 set2 = + let big_map = Big_map.IdSet.diff set1.big_map set2.big_map in + let sapling_state = + Sapling_state.IdSet.diff set1.sapling_state set2.sapling_state + in + {big_map; sapling_state} + + let fold (type i a u) (kind : (i, a, u) kind) (f : i -> 'acc -> 'acc) set + (acc : 'acc) = + match (kind, set) with + | Big_map, {big_map; _} -> Big_map.IdSet.fold f big_map acc + | Sapling_state, {sapling_state; _} -> + Sapling_state.IdSet.fold f sapling_state acc + + let fold_all f set acc = + List.fold_left + (fun acc (_, Ex_Kind kind) -> fold kind (f.f kind) set acc) + acc + all +end diff --git a/src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.mli b/src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.mli new file mode 100644 index 000000000000..eb23fb9545ad --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/lazy_storage_kind.mli @@ -0,0 +1,178 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + Lazy_storage offers a unified interface for specific Michelson datatype that + behave somewhat lazily, because they are intended to be quite big. + Instead of serializing/deserializing the whole value to/from the storage, + only an identifier is used. The identifier acts like a pointer. + When using the value in a Michelson script, some part of it may be read from + the storage, and a lightweight diff is computed. + The diff is effectively applied to the storage at the end of the execution. + + This module defines the different kinds of lazy storages and their basic + properties. See also [Lazy_storage_diff]. + + Lazy storage types are: + - Big_map +*) + +(** + Lazy storage ids are kept as abstract as possible to avoid mixing them up. + + Behind the scene they are [Z.t]s but, within the protocol, only [parse_data]/ + [unparse_data] are allowed convert from/to it. + + Temporary ids may be used to pass values between contracts that won't be kept + longer than the lifetime of the operation. + Behind the scene, temporary ids are negative [Z.t]s. +*) +module type ID = sig + type t + + val compare : t -> t -> int + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + (** Initial value for ids: zero. *) + val init : t + + (** In the protocol, to be used in parse_data only *) + val parse_z : Z.t -> t + + (** In the protocol, to be used in unparse_data only *) + val unparse_to_z : t -> Z.t + + val next : t -> t + + val is_temp : t -> bool + + (* To be removed once legacy big map diff is removed: *) + + val of_legacy_USE_ONLY_IN_Legacy_big_map_diff : Z.t -> t + + val to_legacy_USE_ONLY_IN_Legacy_big_map_diff : t -> Z.t + + (* To be used in storage: *) + + include Path_encoding.S with type t := t +end + +module Big_map : sig + val title : string + + module Id : ID + + type alloc = {key_type : Script_repr.expr; value_type : Script_repr.expr} + + type update = { + key : Script_repr.expr; + (** The key is ignored by [apply_update] but is shown in the receipt, + as specified in [print_big_map_diff]. *) + key_hash : Script_expr_hash.t; + value : Script_repr.expr option; + } + + type updates = update list + + val alloc_encoding : alloc Data_encoding.t + + val updates_encoding : updates Data_encoding.t +end + +module Sapling_state : sig + val title : string + + module Id : ID + + type alloc = {memo_size : Sapling_repr.Memo_size.t} + + type updates = Sapling_repr.diff + + val alloc_encoding : alloc Data_encoding.t + + val updates_encoding : updates Data_encoding.t +end + +(** + Kinds of lazy storage. + The GADT ensures operations are properly applied to the correct kind. + + ['id] the abstract type for the identifier of the kind. + ['alloc] is the type used to construct a new value. + ['updates] is the type used to update a value. +*) +type ('id, 'alloc, 'updates) t = + | Big_map : (Big_map.Id.t, Big_map.alloc, Big_map.updates) t + | Sapling_state + : (Sapling_state.Id.t, Sapling_state.alloc, Sapling_state.updates) t + +type ex = Ex_Kind : (_, _, _) t -> ex + +val all : (int * ex) list + +type (_, _) cmp = Eq : ('a, 'a) cmp | Neq + +val equal : + ('i1, 'a1, 'u1) t -> + ('i2, 'a2, 'u2) t -> + ('i1 * 'a1 * 'u1, 'i2 * 'a2 * 'u2) cmp + +type ('i, 'a, 'u) kind = ('i, 'a, 'u) t + +(** + Type to manage temporary ids. + Used only in the context. +*) +module Temp_ids : sig + type t + + val init : t + + val fresh : ('i, 'a, 'u) kind -> t -> t * 'i + + val fold_s : + ('i, 'a, 'u) kind -> ('acc -> 'i -> 'acc Lwt.t) -> t -> 'acc -> 'acc Lwt.t +end + +module IdSet : sig + type t + + type 'acc fold_f = {f : 'i 'a 'u. ('i, 'a, 'u) kind -> 'i -> 'acc -> 'acc} + + val empty : t + + val mem : ('i, 'a, 'u) kind -> 'i -> t -> bool + + val add : ('i, 'a, 'u) kind -> 'i -> t -> t + + val diff : t -> t -> t + + val fold : ('i, 'a, 'u) kind -> ('i -> 'acc -> 'acc) -> t -> 'acc -> 'acc + + val fold_all : 'acc fold_f -> t -> 'acc -> 'acc +end diff --git a/src/proto_020_PsParisC/lib_protocol/legacy_script_patches.ml b/src/proto_020_PsParisC/lib_protocol/legacy_script_patches.ml new file mode 100644 index 000000000000..de45c3d7fb9a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/legacy_script_patches.ml @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + addresses : string list; + hash : Script_expr_hash.t; + patched_code : Michelson_v1_primitives.prim Micheline.canonical; +} + +let script_hash {hash; _} = hash + +let code {patched_code; _} = patched_code + +let bin_expr_exn hex = + match + Option.bind + (Hex.to_bytes @@ `Hex hex) + (fun bytes -> + Data_encoding.Binary.of_bytes_opt Script_repr.expr_encoding bytes) + with + | Some expr -> expr + | None -> raise (Failure "Decoding script failed.") + +let patches = [] + +let addresses_to_patch = + List.concat_map + (fun {hash; patched_code; addresses} -> + List.map (fun addr -> (addr, hash, patched_code)) addresses) + patches diff --git a/src/proto_020_PsParisC/lib_protocol/level_repr.ml b/src/proto_020_PsParisC/lib_protocol/level_repr.ml new file mode 100644 index 000000000000..7805ce15cf2c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/level_repr.ml @@ -0,0 +1,367 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + level : Raw_level_repr.t; + level_position : int32; + cycle : Cycle_repr.t; + cycle_position : int32; + expected_commitment : bool; +} + +include Compare.Make (struct + type nonrec t = t + + let compare {level = l1; _} {level = l2; _} = Raw_level_repr.compare l1 l2 +end) + +type level = t + +let pp ppf {level; _} = Raw_level_repr.pp ppf level + +let pp_full ppf l = + Format.fprintf + ppf + "%a.%ld (cycle %a.%ld)" + Raw_level_repr.pp + l.level + l.level_position + Cycle_repr.pp + l.cycle + l.cycle_position + +let encoding = + let open Data_encoding in + conv + (fun {level; level_position; cycle; cycle_position; expected_commitment} -> + (level, level_position, cycle, cycle_position, expected_commitment)) + (fun (level, level_position, cycle, cycle_position, expected_commitment) -> + {level; level_position; cycle; cycle_position; expected_commitment}) + (obj5 + (req + "level" + ~description: + "The level of the block relative to genesis. This is also the \ + Shell's notion of level." + Raw_level_repr.encoding) + (req + "level_position" + ~description: + "The level of the block relative to the successor of the genesis \ + block. More precisely, it is the position of the block relative \ + to the block that starts the \"Alpha family\" of protocols, which \ + includes all protocols except Genesis (that is, from 001 \ + onwards)." + int32) + (req + "cycle" + ~description: + "The current cycle's number. Note that cycles are a \ + protocol-specific notion. As a result, the cycle number starts at \ + 0 with the first block of the Alpha family of protocols." + Cycle_repr.encoding) + (req + "cycle_position" + ~description: + "The current level of the block relative to the first block of the \ + current cycle." + int32) + (req + "expected_commitment" + ~description: + "Tells whether the baker of this block has to commit a seed nonce \ + hash." + bool)) + +let diff {level = l1; _} {level = l2; _} = + Int32.sub (Raw_level_repr.to_int32 l1) (Raw_level_repr.to_int32 l2) + +type cycle_era = { + first_level : Raw_level_repr.t; + first_cycle : Cycle_repr.t; + blocks_per_cycle : int32; + blocks_per_commitment : int32; +} + +type cycle_eras = cycle_era list + +type error += Invalid_cycle_eras + +let () = + register_error_kind + `Temporary + ~id:"level_repr.invalid_cycle_eras" + ~title:"Invalid cycle eras" + ~description: + "The cycles eras are not valid: empty list or non-decreasing first \ + levels or first cycles." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The cycles eras are not valid: empty list or non-decreasing first \ + levels or first cycles.") + Data_encoding.empty + (function Invalid_cycle_eras -> Some () | _ -> None) + (fun () -> Invalid_cycle_eras) + +let create_cycle_eras cycle_eras = + let open Result_syntax in + match cycle_eras with + | [] -> tzfail Invalid_cycle_eras + | newest_era :: older_eras -> + let rec aux {first_level; first_cycle; _} older_eras = + match older_eras with + | ({ + first_level = first_level_of_previous_era; + first_cycle = first_cycle_of_previous_era; + _; + } as previous_era) + :: even_older_eras -> + if + Raw_level_repr.(first_level > first_level_of_previous_era) + && Cycle_repr.(first_cycle > first_cycle_of_previous_era) + then aux previous_era even_older_eras + else tzfail Invalid_cycle_eras + | [] -> return_unit + in + let* () = aux newest_era older_eras in + return cycle_eras + +let add_cycle_era new_era cycle_eras = create_cycle_eras (new_era :: cycle_eras) + +let cycle_era_encoding = + let open Data_encoding in + conv + (fun {first_level; first_cycle; blocks_per_cycle; blocks_per_commitment} -> + (first_level, first_cycle, blocks_per_cycle, blocks_per_commitment)) + (fun (first_level, first_cycle, blocks_per_cycle, blocks_per_commitment) -> + {first_level; first_cycle; blocks_per_cycle; blocks_per_commitment}) + (obj4 + (req + "first_level" + ~description:"The first level of a new cycle era." + Raw_level_repr.encoding) + (req + "first_cycle" + ~description:"The first cycle of a new cycle era." + Cycle_repr.encoding) + (req + "blocks_per_cycle" + ~description: + "The value of the blocks_per_cycle constant used during the cycle \ + era starting with first_level." + int32) + (req + "blocks_per_commitment" + ~description: + "The value of the blocks_per_commitment constant used during the \ + cycle era starting with first_level." + int32)) + +let cycle_eras_encoding = + Data_encoding.conv_with_guard + (fun eras -> eras) + (fun eras -> + match create_cycle_eras eras with + | Ok eras -> Ok eras + | Error _ -> Error "Invalid cycle eras") + (Data_encoding.list cycle_era_encoding) + +let current_era = function [] -> assert false | cycle_era :: _ -> cycle_era + +let root_level cycle_eras = + let first_era = List.last_opt cycle_eras in + let first_era = + match first_era with + | Some first_era -> first_era + | None -> + (* {!create_cycle_eras} fails if the list is empty. + {!cycle_eras_encoding} uses {!create_cycle_eras} and so fails on empty + lists too. *) + assert false + in + { + level = first_era.first_level; + level_position = 0l; + cycle = Cycle_repr.root; + cycle_position = 0l; + expected_commitment = false; + } + +(* This function returns the cycle era to which [level] belongs. *) +let era_of_level ~cycle_eras level = + let rec aux = function + | ({first_level; _} as era) :: previous_eras -> + if Raw_level_repr.(level >= first_level) then era else aux previous_eras + | [] -> assert false + in + aux cycle_eras + +(* This function returns the cycle era to which [cycle] belongs. *) +let era_of_cycle ~cycle_eras cycle = + let rec aux = function + | ({first_cycle; _} as era) :: previous_eras -> + if Cycle_repr.(cycle >= first_cycle) then era else aux previous_eras + | [] -> assert false + in + aux cycle_eras + +(* precondition: [level] belongs to [era] *) +let level_from_raw_with_era era ~first_level_in_alpha_family level = + let {first_level; first_cycle; blocks_per_cycle; blocks_per_commitment} = + era + in + let level_position_in_era = Raw_level_repr.diff level first_level in + assert (Compare.Int32.(level_position_in_era >= 0l)) ; + let cycles_since_era_start = + Int32.div level_position_in_era blocks_per_cycle + in + let cycle = + Cycle_repr.add first_cycle (Int32.to_int cycles_since_era_start) + in + let cycle_position = Int32.rem level_position_in_era blocks_per_cycle in + let level_position = Raw_level_repr.diff level first_level_in_alpha_family in + let expected_commitment = + Compare.Int32.( + Int32.rem cycle_position blocks_per_commitment + = Int32.pred blocks_per_commitment) + in + {level; level_position; cycle; cycle_position; expected_commitment} + +let level_from_raw_aux_exn ~cycle_eras level = + let first_level_in_alpha_family = + match List.rev cycle_eras with + | [] -> assert false + | {first_level; _} :: _ -> first_level + in + let era = era_of_level ~cycle_eras level in + level_from_raw_with_era era ~first_level_in_alpha_family level + +let level_from_raw ~cycle_eras l = level_from_raw_aux_exn ~cycle_eras l + +type error += Level_not_in_alpha of Raw_level_repr.t + +let () = + register_error_kind + `Permanent + ~id:"level_not_in_alpha" + ~title:"Level not in Alpha family" + ~description:"Level not in Alpha family" + ~pp:(fun ppf level -> + Format.fprintf + ppf + "Level %a is not in the Alpha family of protocols." + Raw_level_repr.pp + level) + Data_encoding.(obj1 (req "level" Raw_level_repr.encoding)) + (function Level_not_in_alpha level -> Some level | _ -> None) + (fun level -> Level_not_in_alpha level) + +let level_from_raw_aux ~cycle_eras level = + let open Result_syntax in + let first_level_in_alpha_family = + match List.rev cycle_eras with + | [] -> assert false + | {first_level; _} :: _ -> first_level + in + let+ () = + error_when + Raw_level_repr.(level < first_level_in_alpha_family) + (Level_not_in_alpha level) + in + let era = era_of_level ~cycle_eras level in + level_from_raw_with_era era ~first_level_in_alpha_family level + +type error += Negative_level_and_offset_sum of int32 * int32 + +let () = + register_error_kind + `Permanent + ~id:"negative_level_and_offset_sum" + ~title:"Negative sum of level and offset" + ~description:"Negative sum of level and offset" + ~pp:(fun ppf (level, offset) -> + Format.fprintf + ppf + "Sum of level (%ld) and offset (%ld) is negative." + level + offset) + Data_encoding.(obj2 (req "level" int32) (req "offset" int32)) + (function + | Negative_level_and_offset_sum (level, offset) -> Some (level, offset) + | _ -> None) + (fun (level, offset) -> Negative_level_and_offset_sum (level, offset)) + +let level_from_raw_with_offset ~cycle_eras ~offset raw_level = + let res = Raw_level_repr.(of_int32 (Int32.add (to_int32 raw_level) offset)) in + match res with + | Ok level -> level_from_raw_aux ~cycle_eras level + | Error _ -> + Result_syntax.tzfail + (Negative_level_and_offset_sum + (Raw_level_repr.to_int32 raw_level, offset)) + +let first_level_in_cycle_from_eras ~cycle_eras cycle = + let first_level_in_alpha_family = + match List.rev cycle_eras with + | [] -> assert false + | {first_level; _} :: _ -> first_level + in + let era = era_of_cycle ~cycle_eras cycle in + let cycle_position = Cycle_repr.diff cycle era.first_cycle in + let offset = Int32.mul era.blocks_per_cycle cycle_position in + let first_level_in_cycle = + Raw_level_repr.(of_int32_exn (Int32.add (to_int32 era.first_level) offset)) + in + level_from_raw_with_era era ~first_level_in_alpha_family first_level_in_cycle + +let last_of_cycle ~cycle_eras level = + let era = era_of_level ~cycle_eras level.level in + Compare.Int32.(Int32.succ level.cycle_position = era.blocks_per_cycle) + +module Internal_for_tests = struct + let add_level level n = + let raw_level = level.level in + let new_raw_level = Raw_level_repr.add raw_level n in + {level with level = new_raw_level} + + let add_cycles ~blocks_per_cycle level n = + { + level with + cycle = Cycle_repr.add level.cycle n; + level = Raw_level_repr.add level.level (n * blocks_per_cycle); + level_position = + Int32.add level.level_position (Int32.of_int (n * blocks_per_cycle)); + } + + let root = + { + level = Raw_level_repr.root; + level_position = 0l; + cycle = Cycle_repr.root; + cycle_position = 0l; + expected_commitment = false; + } +end diff --git a/src/proto_020_PsParisC/lib_protocol/level_repr.mli b/src/proto_020_PsParisC/lib_protocol/level_repr.mli new file mode 100644 index 000000000000..7b208cd6ecf1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/level_repr.mli @@ -0,0 +1,123 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines the protocol representation of a level. Besides the "raw + level", which is the shell's notion of the level, this representation also + contains additional information, like the cycle the level belongs to. *) + +type t = private { + level : Raw_level_repr.t; + (** The level of the block relative to genesis. This + is also the Shell's notion of level. *) + level_position : int32; + (** The level of the block relative to the block that starts the + alpha family of protocols. *) + cycle : Cycle_repr.t; + (** The current cycle's number. Note that cycles are a protocol-specific + notion. As a result, the cycle number starts at 0 with the first block of + the first version of protocol alpha. *) + cycle_position : int32; + (** The current level of the block relative to the first block of the current + cycle. *) + expected_commitment : bool; +} + +type level = t + +include Compare.S with type t := level + +val encoding : level Data_encoding.t + +val pp : Format.formatter -> level -> unit + +val pp_full : Format.formatter -> level -> unit + +val diff : level -> level -> int32 + +(** A cycle era is a chunk of cycles having the same number of levels + per cycle and the same number of blocks per commitment. *) +type cycle_era = { + first_level : Raw_level_repr.t; (** The first level of a cycle era. *) + first_cycle : Cycle_repr.t; (** The first cycle of a cycle era. *) + blocks_per_cycle : int32; + (** The value of the blocks_per_cycle constant used during the cycle + era starting with first_level. *) + blocks_per_commitment : int32; + (** The value of the blocks_per_commitment constant used during the + cycle era starting with first_level. *) +} + +(** Stores the cycles eras of the Alpha family of protocols *) +type cycle_eras + +val cycle_eras_encoding : cycle_eras Data_encoding.t + +(** Preconditions on the input list of cycle eras: + - the list is not empty + - the first levels and the first cycles are decreasing, meaning that the + first era in the list is the current era, and the last era in the list + is the oldest era + Invariants: + - the first era therefore contains the same constants as in Constants + - the first level of an era is the first level of a cycle +*) +val create_cycle_eras : cycle_era list -> cycle_eras tzresult + +(** Add a new cycle era *) +val add_cycle_era : cycle_era -> cycle_eras -> cycle_eras tzresult + +(** Returns the current era *) +val current_era : cycle_eras -> cycle_era + +(** Returns the first level of the oldest era *) +val root_level : cycle_eras -> level + +(** Returns the annotated level corresponding to a raw level *) +val level_from_raw : cycle_eras:cycle_eras -> Raw_level_repr.t -> level + +(** Returns the annotated level corresponding to a raw level and an + offset. A positive offset corresponds to a higher level. + Fails with [Negative_level_and_offset_sum] if the sum of the raw_level and the offset is negative. + Fails with [Level_not_in_alpha] if the sum of the raw_level and the offset + is a level before the first level in the Alpha family of protocols. *) +val level_from_raw_with_offset : + cycle_eras:cycle_eras -> offset:int32 -> Raw_level_repr.t -> level tzresult + +(** Returns the first level of the given cycle. *) +val first_level_in_cycle_from_eras : + cycle_eras:cycle_eras -> Cycle_repr.t -> level + +(** Returns true if the given level is the last of a cycle. *) +val last_of_cycle : cycle_eras:cycle_eras -> level -> bool + +module Internal_for_tests : sig + val add_level : t -> int -> t + + val add_cycles : blocks_per_cycle:int -> t -> int -> t + + val root : t +end + +(**/**) diff --git a/src/proto_020_PsParisC/lib_protocol/level_storage.ml b/src/proto_020_PsParisC/lib_protocol/level_storage.ml new file mode 100644 index 000000000000..fcf9cd89eb09 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/level_storage.ml @@ -0,0 +1,129 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Level_repr + +let from_raw c l = + let cycle_eras = Raw_context.cycle_eras c in + Level_repr.level_from_raw ~cycle_eras l + +let from_raw_with_offset c ~offset l : Level_repr.t tzresult = + let cycle_eras = Raw_context.cycle_eras c in + Level_repr.level_from_raw_with_offset ~cycle_eras ~offset l + +let root c = Raw_context.cycle_eras c |> Level_repr.root_level + +let succ c (l : Level_repr.t) = from_raw c (Raw_level_repr.succ l.level) + +let pred c (l : Level_repr.t) = + (* This returns [None] rather than level zero when [l] is level one + because {!from_raw} raises an exception when called on zero + (because [Level_repr.era_of_level] cannot find level zero's era). *) + match Raw_level_repr.pred_dontreturnzero l.Level_repr.level with + | None -> None + | Some l -> Some (from_raw c l) + +let add c (l : Level_repr.t) n = from_raw c (Raw_level_repr.add l.level n) + +let sub c (l : Level_repr.t) n = + match Raw_level_repr.sub l.level n with + | None -> None + | Some raw_level -> + let cycle_eras = Raw_context.cycle_eras c in + let root_level = Level_repr.root_level cycle_eras in + if Raw_level_repr.(raw_level >= root_level.level) then + Some (from_raw c raw_level) + else None + +let current ctxt = Raw_context.current_level ctxt + +let previous ctxt = + let l = current ctxt in + match pred ctxt l with + | None -> assert false (* We never validate the Genesis... *) + | Some p -> p + +let first_level_in_cycle ctxt cycle = + let cycle_eras = Raw_context.cycle_eras ctxt in + Level_repr.first_level_in_cycle_from_eras ~cycle_eras cycle + +let last_level_in_cycle ctxt c = + match pred ctxt (first_level_in_cycle ctxt (Cycle_repr.succ c)) with + | None -> assert false + | Some x -> x + +let levels_in_cycle ctxt cycle = + let first = first_level_in_cycle ctxt cycle in + let rec loop (n : Level_repr.t) acc = + if Cycle_repr.(n.cycle = first.cycle) then loop (succ ctxt n) (n :: acc) + else acc + in + loop first [] + +let levels_in_current_cycle ctxt ?(offset = 0l) () = + let current_cycle = Cycle_repr.to_int32 (current ctxt).cycle in + let cycle = Int32.add current_cycle offset in + if Compare.Int32.(cycle < 0l) then [] + else + let cycle = Cycle_repr.of_int32_exn cycle in + levels_in_cycle ctxt cycle + +let levels_with_commitments_in_cycle ctxt c = + let first = first_level_in_cycle ctxt c in + let rec loop (n : Level_repr.t) acc = + if Cycle_repr.(n.cycle = first.cycle) then + if n.expected_commitment then loop (succ ctxt n) (n :: acc) + else loop (succ ctxt n) acc + else acc + in + loop first [] + +let last_preserved_block_level c = + let level = Raw_context.current_level c in + let block_conservation_cycles = + Constants_storage.blocks_preservation_cycles c + in + match Cycle_repr.sub level.cycle block_conservation_cycles with + | None -> Raw_level_repr.root + | Some cycle -> (first_level_in_cycle c cycle).level + +let last_finalized_block_level c = + let current = Raw_context.current_level c in + let current_raw = current.level in + let finalized_level = Raw_level_repr.sub current_raw 2 in + match finalized_level with None -> Raw_level_repr.root | Some l -> l + +let last_of_a_cycle ctxt level = + let cycle_eras = Raw_context.cycle_eras ctxt in + Level_repr.last_of_cycle ~cycle_eras level + +let dawn_of_a_new_cycle ctxt = + let level = current ctxt in + if last_of_a_cycle ctxt level then Some level.cycle else None + +let may_compute_randao ctxt = + let level = current ctxt in + let nonce_reveal_cutoff = Constants_storage.nonce_revelation_threshold ctxt in + Compare.Int32.equal level.cycle_position nonce_reveal_cutoff diff --git a/src/proto_020_PsParisC/lib_protocol/level_storage.mli b/src/proto_020_PsParisC/lib_protocol/level_storage.mli new file mode 100644 index 000000000000..64e8bc45e12f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/level_storage.mli @@ -0,0 +1,77 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val current : Raw_context.t -> Level_repr.t + +val previous : Raw_context.t -> Level_repr.t + +val root : Raw_context.t -> Level_repr.t + +val from_raw : Raw_context.t -> Raw_level_repr.t -> Level_repr.t + +(** Fails with [Negative_level_and_offset_sum] if the sum of the raw_level and the offset is negative. *) +val from_raw_with_offset : + Raw_context.t -> offset:int32 -> Raw_level_repr.t -> Level_repr.t tzresult + +(** When the given level is two or above, return its predecessor. When + the given level is one or less, return [None] (because we cannot + build the [Level_repr.t] for level zero). *) +val pred : Raw_context.t -> Level_repr.t -> Level_repr.t option + +val succ : Raw_context.t -> Level_repr.t -> Level_repr.t + +(** [i] must be positive *) +val add : Raw_context.t -> Level_repr.t -> int -> Level_repr.t + +(** [sub c level i] returns None if the level is before the first + level of the Alpha family of protocol, otherwise it returns the + expected level. [i] must be positive. *) +val sub : Raw_context.t -> Level_repr.t -> int -> Level_repr.t option + +val first_level_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t + +val last_level_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t + +val levels_in_cycle : Raw_context.t -> Cycle_repr.t -> Level_repr.t list + +val levels_in_current_cycle : + Raw_context.t -> ?offset:int32 -> unit -> Level_repr.t list + +val levels_with_commitments_in_cycle : + Raw_context.t -> Cycle_repr.t -> Level_repr.t list + +val last_preserved_block_level : Raw_context.t -> Raw_level_repr.t + +val last_finalized_block_level : Raw_context.t -> Raw_level_repr.t + +(** Returns [Some cycle] if the current level represents the last + level of [cycle] and [None] if the level is not the last level of a + cycle. *) +val dawn_of_a_new_cycle : Raw_context.t -> Cycle_repr.t option + +(** Returns [true] if RANDAO should be computed at the current level, that is + if the current level, relative to the cycle's start, equals the nonce + revelation period cut-off. *) +val may_compute_randao : Raw_context.t -> bool diff --git a/src/proto_020_PsParisC/lib_protocol/liquidity_baking_cpmm.ml b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_cpmm.ml new file mode 100644 index 000000000000..184e4d80d139 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_cpmm.ml @@ -0,0 +1,20 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +let script_hex : Hex.t = + `Hex + "02000011c405000764076407640865046e00000006256f776e6572076504620000000d256d696e4c71744d696e7465640765046200000013256d6178546f6b656e734465706f7369746564046b0000000925646561646c696e650000000d256164644c6971756964697479046c000000082564656661756c7407640865046e0000000325746f076504620000000a256c71744275726e65640765046a00000010256d696e58747a57697468647261776e0765046200000013256d696e546f6b656e7357697468647261776e046b0000000925646561646c696e65000000102572656d6f76654c69717569646974790865046e00000015256f7574707574446578746572436f6e74726163740765046200000010256d696e546f6b656e73426f756768740765046e0000000325746f076504620000000b25746f6b656e73536f6c64046b0000000925646561646c696e650000000d25746f6b656e546f546f6b656e07640865046e0000000325746f076504620000000b25746f6b656e73536f6c640765046a0000000d256d696e58747a426f75676874046b0000000925646561646c696e650000000b25746f6b656e546f58747a0865046e0000000325746f0765046200000010256d696e546f6b656e73426f75676874046b0000000925646561646c696e650000000b2578747a546f546f6b656e0501076504620000000a25746f6b656e506f6f6c0765046a000000082578747a506f6f6c0765046200000009256c7174546f74616c0765046e0000000d25746f6b656e41646472657373046e0000000b256c71744164647265737305020200000f7203210317034c0316072e02000009d1072e020000035a072e020000032603210317034c0316034c03210317034c0316034c03210317034c0316034c034003190328072c020000000c05200004074303620003032702000002ea0743036a000105700004032105710005031703160322072f0200000013074303680100000008444956206279203003270200000000031603130743036a0001034c0322072f02000000130743036801000000084449562062792030032702000000000316034c0321057100020570000603210571000703170317031605700002032105710003033a0322072f020000001307430368010000000844495620627920300327020000000003160570000205700006032105710007031605700003033a0322072f020000001307430368010000000844495620627920300327020000002a03210317034c03160743036200000570000203190325072c02000000000200000008074303620001031205700002034c0321057100020319032a072c020000000c05200005074303620004032702000001b60571000203210571000303190337072c020000000c0520000407430362000503270200000190057000030321057100040317031703170570000203210571000305700005032105710006031703170316031203420570000403210571000503170316034205700004032105710005031603420317034c032105710002057000050321057100060316031203420321031703170313057000060317031603120342034c03160342034c03490354034203480342034c032105710002034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d05700002033005700003034205700002032105710003034c03210317034c031605700002031703170317031706550765045b00000009257175616e74697479046e00000007257461726765740000000b256d696e744f724275726e072f020000000807430362000c032702000000000743036a000005700002057000030342034d05700002053d036d05700002031b05700002031b0342020000002803200321031703170313057000020321057100030317031603120342034c03160342053d036d0342020000066b072e020000038d03210317034c0316034c03210317034c0316034c03210317034c0316034c03210317034c0316034c034003190328072c020000000c05200005074303620003032702000003470743036a000003130319032a072c020000000c0520000507430362000a03270200000323057000040321057100050317031703160743036a000105700006032105710007031703160322072f0200000013074303680100000008444956206279203003270200000000031605700004032105710005033a0322072f020000001307430368010000000844495620627920300327020000000003160743036a0001034c033a0570000503210571000603170317031605700006032105710007031605700005032105710006033a0322072f02000000130743036801000000084449562062792030032702000000000316057000030570000203210571000303190337072c020000000c0520000607430362000b0327020000022e05700002034c03210571000203190337072c020000000c0520000507430362000d032702000002060570000203210571000305700005032105710006031703170316034b0356072f020000000807430362000e03270200000000034c032105710002057000060321057100070316034b0356072f020000000807430362000f03270200000000057000040743035b0000034b0348034205700006032105710007034c03210317034c031605700002031703170317031706550765045b00000009257175616e74697479046e00000007257461726765740000000b256d696e744f724275726e072f020000000807430362000c032702000000000743036a000005700002057000030342034d0570000305700005032105710006034203490354034205700006032105710007034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d05700004032105710005057000060555036c072f020000000807430362000903270200000000034c0743036c030b034d0570000603210571000703170317057000060570000703210571000803170316034b034205700006031603420321031703170317057000060342034c032105710002031703160342034c031603420317057000040342053d036d05700002031b05700002031b05700002031b034202000002d203210317034c0316034c03210317034c0316034c03210317034c0316034c03210317034c03160570000406550765046e0000000325746f0765046200000010256d696e546f6b656e73426f75676874046b0000000925646561646c696e650000000b2578747a546f546f6b656e072f020000000807430362001f032702000000000743036a000003130319032a072c020000000c0520000607430362000a0327020000022d05700002032105710003034003190328072c020000000c05200006074303620003032702000002050743036200a70f05700002032105710003033a0743036200a80f057000070321057100080316033a031205700006032105710007031703160743036200a70f05700004032105710005033a033a0322072f020000001307430368010000000844495620627920300327020000000003160743036200a80f0743036200a70f05700002032105710003033a0322072f02000000130743036801000000084449562062792030032702000000000316057000070321057100080317057000040321057100050570000903210571000a031603120342032103170317057000030321057100040570000a03170316034b0342034c031603420570000403490354034203480342034c032105710002034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d057000040570000303210571000405700006057000080342057000070342034d0570000305700004034b0743036e0100000024747a314b65326837734464616b484a5168385758345a3337326475314b4368736b7379550555036c072f020000000807430362000903270200000000034c0743036c030b034d05700003053d036d05700002031b05700002031b05700002031b0342020000058d072e02000002cc03210317034c0316034c03210317034c0316034c03210317034c0316034c034003190328072c020000000c05200004074303620003032702000002900743036a000003130319032a072c020000000c0520000407430362000a0327020000026c0743036200a70f05700002032105710003033a0743036200a80f057000050321057100060316033a03120743036a000105700005032105710006031703160322072f020000001307430368010000000844495620627920300327020000000003160743036200a70f05700004032105710005033a033a0322072f020000001307430368010000000844495620627920300327020000000003160743036a0001034c033a0743036200a80f0743036200a70f05700002032105710003033a0322072f0200000013074303680100000008444956206279203003270200000000031605700002034c03210571000203190337072c020000000a032007430362000803270200000000057000020321057100030349035403420348034205700005032105710006034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d034c032105710002057000050555036c072f020000000807430362000903270200000000034c0743036c030b034d0570000503210571000603170570000505700006032105710007031603120342032103170317057000050321057100060570000703170316034b0342034c031603420570000305700004034b0743036e0100000024747a314b65326837734464616b484a5168385758345a3337326475314b4368736b7379550555036c072f020000000807430362000903270200000000034c0743036c030b034d034c053d036d05700002031b05700002031b05700002031b034202000002b503210317034c0316034c03210317034c0316034c034003190328072c020000000c05200003074303620003032702000002830743036a000105700003032105710004031703160322072f0200000013074303680100000008444956206279203003270200000000031603130743036a0001034c0322072f020000001307430368010000000844495620627920300327020000000003160743036200a80f0743036200a70f05700002032105710003033a0322072f02000000130743036801000000084449562062792030032702000000000316032105700002034b03110743036200a70f05700002032105710003033a0743036200a80f05700004033a03120570000503210571000603160743036200a70f05700004032105710005033a033a0322072f0200000013074303680100000008444956206279203003270200000000031605700003034c03210571000203190337072c020000000a0320074303620012032702000000000321057000050321057100060316034b0356072f02000000080743036200130327020000000005700005032105710006031703170743036a000105700005033a05700006032105710007031703160312034205700005031603420317034c0342034c057000030342034903540342034c032105710002034c03210317034c0316034c03210317034c031605700003031703170317031606550765036e0765036e036200000009257472616e73666572072f0200000008074303620000032702000000000743036a000005700003057000030342057000030342034d0743036a000105700003033a0743036e0100000024747a314b65326837734464616b484a5168385758345a3337326475314b4368736b7379550555036c072f020000000807430362000903270200000000034c0743036c030b034d05700002053d036d05700002031b05700002031b0342" + +let script_bytes : Bytes.t option = Hex.to_bytes script_hex + +let script_opt : Script_repr.expr option = + Option.bind + script_bytes + (Data_encoding.Binary.of_bytes_opt Script_repr.expr_encoding) + +let script : Script_repr.expr = + Option.value_f ~default:(fun () -> assert false) script_opt diff --git a/src/proto_020_PsParisC/lib_protocol/liquidity_baking_lqt.ml b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_lqt.ml new file mode 100644 index 000000000000..7e85b96172ef --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_lqt.ml @@ -0,0 +1,20 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +let script_hex : Hex.t = + `Hex + "020000070005000764076407640865046e00000008257370656e6465720462000000062576616c75650000000825617070726f766508650865046e00000006256f776e6572046e00000008257370656e646572000000082572657175657374065a0362000000092563616c6c6261636b0000000d25676574416c6c6f77616e636507640865046e00000006256f776e6572065a0362000000092563616c6c6261636b0000000b2567657442616c616e63650865046c000000082572657175657374065a0362000000092563616c6c6261636b0000000f25676574546f74616c537570706c7907640865045b00000009257175616e74697479046e00000007257461726765740000000b256d696e744f724275726e0865046e000000052566726f6d0765046e0000000325746f0462000000062576616c756500000009257472616e73666572050107650861036e03620000000725746f6b656e73076508610765046e00000006256f776e6572046e00000008257370656e64657203620000000b25616c6c6f77616e6365730765046e000000062561646d696e04620000000d25746f74616c5f737570706c7905020200000552032103170743036a000003130319033c072c020000001607430368010000000b446f6e7453656e6454657a03270200000000034c0316072e02000001b2072e0200000132072e02000000e2034c03210571000203170316034c0321057100020316034803420743036200000570000303210571000403170319032a07430362000005700003032105710004057000030321057100040329072f020000000607430362000002000000000319032a0314072c0200000020074303680100000015556e73616665416c6c6f77616e63654368616e676503270200000000057000030321057100040317031705700002057000030317074303620000034c03210571000203190325072c02000000060320053e0362020000000203460570000303500342034c03160342053d036d03420200000044034c032105700002053d036d034c03210571000203170743036a000005700004031703160570000403160329072f02000000060743036200000200000000034d031b03420200000074072e0200000042034c032105700002053d036d034c03210571000203170743036a00000570000403160570000403160329072f02000000060743036200000200000000034d031b03420200000026034c032105700002053d036d034c03170743036a000005700003031703170317034d031b0342020000035e072e020000013c034c03210571000203170317031603480319033c072c02000000140743036801000000094f6e6c7941646d696e03270200000000032103160570000203210571000303160570000203210571000303170329072f0200000006074303620000020000000003120356072f020000003607430368010000002b43616e6e6f74206275726e206d6f7265207468616e207468652074617267657427732062616c616e63652e03270200000000034c032105710002031605700003032105710004031703170317031203110570000303210571000403170570000403160743036200000570000403210571000503190325072c020000000a057000030320053e03620200000006057000030346057000040317035003420321057100020317031703160342034c032105710002031703160342034c03160342053d036d03420200000216034c03210571000203170316057000020321057100030316057000020321057100030316034803190325072c0200000002034c02000000a903480570000303210571000403160342057000030321057100040317031705700003032105710004057000020321057100030329072f02000000060743036200000200000000034b0356072f020000001d0743036801000000124e6f74456e6f756768416c6c6f77616e636503270200000000057000030743036200000570000203210571000303190325072c0200000008034c0320053e03620200000004034c03460570000203500570000203210571000303170317057000020321057100030570000403210571000503160329072f02000000060743036200000200000000034b0356072f020000001b0743036801000000104e6f74456e6f75676842616c616e636503270200000000057000020743036200000570000203210571000303190325072c0200000008034c0320053e03620200000004034c034605700003032105710004031603500570000203210571000303170317034c03210571000205700004032105710005031703160329072f020000000607430362000002000000000312034c0743036200000570000203210571000303190325072c0200000008034c0320053e03620200000004034c034605700003031703160350057000020317034c0342032103170317057000020342034c03160342053d036d0342" + +let script_bytes : Bytes.t option = Hex.to_bytes script_hex + +let script_opt : Script_repr.expr option = + Option.bind + script_bytes + (Data_encoding.Binary.of_bytes_opt Script_repr.expr_encoding) + +let script : Script_repr.expr = + Option.value_f ~default:(fun () -> assert false) script_opt diff --git a/src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.ml b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.ml new file mode 100644 index 000000000000..ae49e7749ea9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.ml @@ -0,0 +1,267 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module is used to originate contracts for liquidity baking during + protocol stitching: a CPMM (constant product market making) contract and a + liquidity token FA1.2 contract, with the storage of each containing the + other's address. + + The CPMM's storage contains a token address, which corresponds to tzBTC when + originated on mainnet and a reference FA1.2 contract when originated for + testing. + + The test FA1.2 contract uses the same script as the liquidity token. Its + manager is initialized to the first bootstrap account. Before originating it, + we make sure we are not on mainnet by both checking for the existence of the + tzBTC contract and that the level is sufficiently low. + + The Michelson and Ligo code, as well as Coq proofs, for the CPMM and + liquidity token contracts are available here: + https://gitlab.com/dexter2tz/dexter2tz/-/tree/liquidity_baking + + All contracts were generated from Ligo at revision + 4d10d07ca05abe0f8a5fb97d15267bf5d339d9f4 and converted to OCaml using + `octez-client convert`. +*) + +open Michelson_v1_primitives +open Micheline + +let null_address = + Bytes.of_string + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + +let mainnet_tzBTC_address = + Contract_hash.of_b58check_exn "KT1PWx2mnDueood7fEmfbBDKx1D9BAnnXitn" + +(** If token_pool, xtz_pool, or lqt_total are ever zero the CPMM will be + permanently broken. Therefore, we initialize it with the null address + registered as a liquidity provider with 1 satoshi tzBTC and 100 mutez + (roughly the current exchange rate). *) +let cpmm_init_storage ~token_address ~lqt_address = + Script_repr.lazy_expr + (Micheline.strip_locations + (Prim + ( 0, + D_Pair, + [ + Int (1, Z.one); + Int (2, Z.of_int 100); + Int (3, Z.of_int 100); + String (4, token_address); + String (5, lqt_address); + ], + [] ))) + +let lqt_init_storage cpmm_address = + Script_repr.lazy_expr + (Micheline.strip_locations + (Prim + ( 0, + D_Pair, + [ + Seq + ( 1, + [ + Prim + ( 2, + D_Elt, + [Bytes (3, null_address); Int (4, Z.of_int 100)], + [] ); + ] ); + Seq (5, []); + String (6, cpmm_address); + Int (7, Z.of_int 100); + ], + [] ))) + +let test_fa12_init_storage manager = + Script_repr.lazy_expr + (Micheline.strip_locations + (Prim + ( 0, + D_Pair, + [ + Seq (1, []); + Seq (2, []); + String (3, manager); + Int (4, Z.of_int 10_000); + ], + [] ))) + +let originate ctxt address_hash ~balance script = + let open Lwt_result_syntax in + let* ctxt = + Contract_storage.raw_originate + ctxt + ~prepaid_bootstrap_storage:true + address_hash + ~script + in + let address = Contract_repr.Originated address_hash in + let* size = Contract_storage.used_storage_space ctxt address in + let* ctxt, _, origination_updates = + Fees_storage.burn_origination_fees + ~origin:Protocol_migration + ctxt + ~storage_limit:(Z.of_int64 Int64.max_int) + ~payer:`Liquidity_baking_subsidies + in + let* ctxt, _, storage_updates = + Fees_storage.burn_storage_fees + ~origin:Protocol_migration + ctxt + ~storage_limit:(Z.of_int64 Int64.max_int) + ~payer:`Liquidity_baking_subsidies + size + in + let* ctxt, transfer_updates = + Token.transfer + ~origin:Protocol_migration + ctxt + `Liquidity_baking_subsidies + (`Contract address) + balance + in + let balance_updates = + origination_updates @ storage_updates @ transfer_updates + in + let result : Migration_repr.origination_result = + { + balance_updates; + originated_contracts = [address_hash]; + storage_size = size; + paid_storage_size_diff = size; + } + in + return (ctxt, result) + +let originate_test_fa12 ~typecheck ctxt admin = + let open Lwt_result_syntax in + let*? ctxt, fa12_address = + Contract_storage.fresh_contract_from_current_nonce ctxt + in + let script = + Script_repr. + { + code = Script_repr.lazy_expr Liquidity_baking_lqt.script; + storage = + test_fa12_init_storage (Signature.Public_key_hash.to_b58check admin); + } + in + let* script, ctxt = typecheck ctxt script in + let+ ctxt, origination_result = + originate + ctxt + fa12_address + ~balance:(Tez_repr.of_mutez_exn 1_000_000L) + script + in + (ctxt, fa12_address, [origination_result]) + +(* hardcoded from lib_parameters *) +let first_bootstrap_account = + Signature.Public_key.hash + (Signature.Public_key.of_b58check_exn + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") + +let check_tzBTC ~typecheck current_level ctxt f = + let open Lwt_result_syntax in + let*! exists = + Contract_storage.exists + ctxt + (Contract_repr.Originated mainnet_tzBTC_address) + in + if exists then + (* If tzBTC exists, we're on mainnet and we use it as the token address in the CPMM. *) + f ctxt mainnet_tzBTC_address [] + else if + (* If the tzBTC contract does not exist, we originate a test FA1.2 contract using the same script as the LQT. This is so that we can test the contracts after performing the same protocol migration that will be done on mainnet. + + First, we check current level is below mainnet level roughly around 010 injection so we do not accidentally originate the test token contract on mainnet. *) + Compare.Int32.(current_level < 1_437_862l) + then + let* ctxt, token_address, token_result = + originate_test_fa12 ~typecheck ctxt first_bootstrap_account + (* Token contract admin *) + in + f ctxt token_address token_result + else + (* If we accidentally entered the tzBTC address incorrectly, but current level indicates this could be mainnet, we do not originate any contracts *) + return (ctxt, []) + +let init ctxt ~typecheck = + let open Lwt_result_syntax in + (* We use a custom origination nonce because it is unset when stitching from 009 *) + let nonce = Operation_hash.hash_string ["Drip, drip, drip."] in + let ctxt = Raw_context.init_origination_nonce ctxt nonce in + let* ctxt = Storage.Liquidity_baking.Toggle_ema.init ctxt 0l in + let current_level = + Raw_level_repr.to_int32 (Level_storage.current ctxt).level + in + let*? ctxt, cpmm_address = + Contract_storage.fresh_contract_from_current_nonce ctxt + in + let*? ctxt, lqt_address = + Contract_storage.fresh_contract_from_current_nonce ctxt + in + let* ctxt = Storage.Liquidity_baking.Cpmm_address.init ctxt cpmm_address in + check_tzBTC + ~typecheck + current_level + ctxt + (fun ctxt token_address token_result -> + let cpmm_script = + Script_repr. + { + code = Script_repr.lazy_expr Liquidity_baking_cpmm.script; + storage = + cpmm_init_storage + ~token_address:(Contract_hash.to_b58check token_address) + ~lqt_address:(Contract_hash.to_b58check lqt_address); + } + in + let* cpmm_script, ctxt = typecheck ctxt cpmm_script in + let lqt_script = + Script_repr. + { + code = Script_repr.lazy_expr Liquidity_baking_lqt.script; + storage = lqt_init_storage (Contract_hash.to_b58check cpmm_address); + } + in + let* lqt_script, ctxt = typecheck ctxt lqt_script in + let* ctxt, cpmm_result = + originate + ctxt + cpmm_address + ~balance:(Tez_repr.of_mutez_exn 100L) + cpmm_script + in + let+ ctxt, lqt_result = + originate ctxt lqt_address ~balance:Tez_repr.zero lqt_script + in + (* Unsets the origination nonce, which is okay because this is called after other originations in stitching. *) + let ctxt = Raw_context.unset_origination_nonce ctxt in + (ctxt, [cpmm_result; lqt_result] @ token_result)) diff --git a/src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.mli b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.mli new file mode 100644 index 000000000000..27059e493d50 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_migration.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val init : + Raw_context.t -> + typecheck: + (Raw_context.t -> + Script_repr.t -> + ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) tzresult + Lwt.t) -> + (Raw_context.t * Migration_repr.origination_result list) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.ml b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.ml new file mode 100644 index 000000000000..09618920f393 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Per_block_votes_repr + +let get_cpmm_address = Storage.Liquidity_baking.Cpmm_address.get + +let get_toggle_ema ctxt = + let open Lwt_result_syntax in + let* ema = Storage.Liquidity_baking.Toggle_ema.get ctxt in + Liquidity_baking_toggle_EMA.of_int32 ema + +let on_cpmm_exists ctxt f = + let open Lwt_result_syntax in + let* cpmm_contract = get_cpmm_address ctxt in + let*! exists = + Contract_storage.exists ctxt (Contract_repr.Originated cpmm_contract) + in + match exists with + | false -> + (* do nothing if the cpmm is not found *) + return (ctxt, []) + | true -> f ctxt cpmm_contract + +let update_toggle_ema ctxt ~per_block_vote = + let open Lwt_result_syntax in + let* old_ema = get_toggle_ema ctxt in + let new_ema = compute_new_liquidity_baking_ema ~per_block_vote old_ema in + let+ ctxt = + Storage.Liquidity_baking.Toggle_ema.update + ctxt + (Liquidity_baking_toggle_EMA.to_int32 new_ema) + in + (ctxt, new_ema) + +let check_ema_below_threshold ctxt ema = + Liquidity_baking_toggle_EMA.( + ema < Constants_storage.liquidity_baking_toggle_ema_threshold ctxt) + +let on_subsidy_allowed ctxt ~per_block_vote f = + let open Lwt_result_syntax in + let* ctxt, toggle_ema = update_toggle_ema ctxt ~per_block_vote in + if check_ema_below_threshold ctxt toggle_ema then + let+ ctxt, operation_results = on_cpmm_exists ctxt f in + (ctxt, operation_results, toggle_ema) + else return (ctxt, [], toggle_ema) diff --git a/src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.mli b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.mli new file mode 100644 index 000000000000..19641d588646 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/liquidity_baking_storage.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Get the address of the Constant-Product Market Maker receiving the + Liquidity Baking subsidy *) +val get_cpmm_address : Raw_context.t -> Contract_hash.t tzresult Lwt.t + +(** [on_subsidy_allowed ctxt ~per_block_vote f] updates the toggle EMA according to + [toggle_vote]. Then the callback function [f] is called if the following + conditions are met: + - the updated EMA is below the threshold, + - the CPMM contract exists. + + The role of the callback function [f] is to send the subsidy to the CPMM, + see [apply_liquidity_baking_subsidy] in [apply.ml]. *) +val on_subsidy_allowed : + Raw_context.t -> + per_block_vote:Per_block_votes_repr.per_block_vote -> + (Raw_context.t -> Contract_hash.t -> (Raw_context.t * 'a list) tzresult Lwt.t) -> + (Raw_context.t * 'a list * Per_block_votes_repr.Liquidity_baking_toggle_EMA.t) + tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/local_gas_counter.ml b/src/proto_020_PsParisC/lib_protocol/local_gas_counter.ml new file mode 100644 index 000000000000..5a7da2dcc375 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/local_gas_counter.ml @@ -0,0 +1,98 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(* + + Gas update and check for gas exhaustion + ======================================= + + Costs of various computations are subtracted from an amount of gas made + available for the script execution. + + Updating the gas counter is a critical aspect to operation validation + because it is done at many places. + + For this reason, the gas counter must be read and updated as quickly as + possible. Hence, the gas counter should be stored in a machine register. To + motivate the OCaml compiler to make that choice, we represent the gas counter + as a local parameter of the execution [step] function. + +*) + +type local_gas_counter = Local_gas_counter of int [@@ocaml.unboxed] + +(* + + The gas counter stored in the context is de-synchronized with the + [local_gas_counter] used locally. When we have to call a gas-consuming + function working on context with no local gas counter, we must update the + context so that it carries an up-to-date gas counter. Similarly, when we + return from such a function, the [local_gas_counter] must be updated as well. + + To statically track these points where the context's gas counter must be + updated, we introduce a type for outdated contexts. The [step] function + carries an [outdated_context]. When an external function needs a [context], + the typechecker points out the need for a conversion: this forces us to + either call [update_context], or better, when this is possible, the function + [use_gas_counter_in_context]. +*) +type outdated_context = Outdated_context of context [@@ocaml.unboxed] + +let outdated_context ctxt = Outdated_context ctxt [@@ocaml.inline always] + +let update_context (Local_gas_counter gas_counter) (Outdated_context ctxt) = + Gas.update_remaining_operation_gas ctxt (Gas.fp_of_milligas_int gas_counter) + [@@ocaml.inline always] + +let local_gas_counter ctxt = + Local_gas_counter (Gas.remaining_operation_gas ctxt :> int) + [@@ocaml.inline always] + +let local_gas_counter_and_outdated_context ctxt = + (local_gas_counter ctxt, outdated_context ctxt) + [@@ocaml.inline always] + +let use_gas_counter_in_context ctxt gas_counter f = + let open Lwt_result_syntax in + let ctxt = update_context gas_counter ctxt in + let+ y, ctxt = f ctxt in + (y, outdated_context ctxt, local_gas_counter ctxt) + [@@ocaml.inline always] + +let consume_opt (Local_gas_counter gas_counter) (cost : Gas.cost) = + let gas_counter = gas_counter - (cost :> int) in + if Compare.Int.(gas_counter < 0) then None + else Some (Local_gas_counter gas_counter) + [@@ocaml.inline always] + +let consume local_gas_counter cost = + let open Result_syntax in + match consume_opt local_gas_counter cost with + | None -> tzfail Gas.Operation_quota_exceeded + | Some local_gas_counter -> return local_gas_counter + [@@ocaml.inline always] diff --git a/src/proto_020_PsParisC/lib_protocol/local_gas_counter.mli b/src/proto_020_PsParisC/lib_protocol/local_gas_counter.mli new file mode 100644 index 000000000000..0f2555eab36a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/local_gas_counter.mli @@ -0,0 +1,68 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module exposes an API for local gas counting. It provides a set of + functions for updating a gas counter without applying it on an + an [Alpha_context.context]. *) + +(** A [local_gas_counter] is a wrapped [int]. *) +type local_gas_counter = Local_gas_counter of int [@@ocaml.unboxed] + +(** A type for describing a context that is not up to date with respect to gas + consumption. *) +type outdated_context + +(*** [update_context gas_counter outdated_ctxt] returns a regular context, + extracted from [outdated_ctxt] with [gas_counter] applied. *) +val update_context : + local_gas_counter -> outdated_context -> Alpha_context.context + +(** [local_gas_counter_and_outdated_context ctxt] returns the gas counter value + corresponding to the remaining gas in the given context [ctxt] along with + an [outdated_context] value. *) +val local_gas_counter_and_outdated_context : + Alpha_context.context -> local_gas_counter * outdated_context + +(** [use_gas_counter_in_context outdated_ctxt gas_counter f] first applies the + [gas_counter] on the outdated context [outdated_ctxt], then invokes [f] on + the resulting context, and returns a new [outdated_context] and a + [local_gas_counter] value. *) +val use_gas_counter_in_context : + outdated_context -> + local_gas_counter -> + (Alpha_context.context -> ('a * Alpha_context.context) tzresult Lwt.t) -> + ('a * outdated_context * local_gas_counter) tzresult Lwt.t + +(** [consume_opt amt cost] attempts to consume an [amt] of gas and returns the + new remaining value wrapped in [Some]. If the resulting gas is negative + [None] is returned. *) +val consume_opt : + local_gas_counter -> Alpha_context.Gas.cost -> local_gas_counter option + +(** [consume amt cost] attempts to consume an [amt] of gas and returns the + new remaining value as a result. If the resulting gas is negative, + an error [Gas.Operation_quota_exceeded] is instead returned. *) +val consume : + local_gas_counter -> Alpha_context.Gas.cost -> local_gas_counter tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/main.ml b/src/proto_020_PsParisC/lib_protocol/main.ml new file mode 100644 index 000000000000..727ff7616ea1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/main.ml @@ -0,0 +1,483 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Protocol Signature Instance *) + +type block_header_data = Alpha_context.Block_header.protocol_data + +type block_header = Alpha_context.Block_header.t = { + shell : Block_header.shell_header; + protocol_data : block_header_data; +} + +let block_header_data_encoding = + Alpha_context.Block_header.protocol_data_encoding + +type block_header_metadata = Apply_results.block_metadata + +let block_header_metadata_encoding_with_legacy_attestation_name = + Apply_results.block_metadata_encoding_with_legacy_attestation_name + +let block_header_metadata_encoding = Apply_results.block_metadata_encoding + +type operation_data = Alpha_context.packed_protocol_data = + | Operation_data : + 'kind Alpha_context.Operation.protocol_data + -> operation_data + +let operation_data_encoding = Alpha_context.Operation.protocol_data_encoding + +let operation_data_encoding_with_legacy_attestation_name = + Alpha_context.Operation.protocol_data_encoding_with_legacy_attestation_name + +type operation_receipt = Apply_results.packed_operation_metadata = + | Operation_metadata : + 'kind Apply_results.operation_metadata + -> operation_receipt + | No_operation_metadata : operation_receipt + +let operation_receipt_encoding = Apply_results.operation_metadata_encoding + +let operation_receipt_encoding_with_legacy_attestation_name = + Apply_results.operation_metadata_encoding_with_legacy_attestation_name + +let operation_data_and_receipt_encoding = + Apply_results.operation_data_and_metadata_encoding + +let operation_data_and_receipt_encoding_with_legacy_attestation_name = + Apply_results + .operation_data_and_metadata_encoding_with_legacy_attestation_name + +type operation = Alpha_context.packed_operation = { + shell : Operation.shell_header; + protocol_data : operation_data; +} + +let acceptable_pass = Alpha_context.Operation.acceptable_pass + +let max_block_length = Alpha_context.Block_header.max_header_length + +let max_operation_data_length = + Alpha_context.Constants.max_operation_data_length + +let validation_passes = + let open Alpha_context.Constants in + Updater. + [ + (* 2048 attestations *) + {max_size = 2048 * 2048; max_op = Some 2048}; + (* 32k of voting operations *) + {max_size = 32 * 1024; max_op = None}; + (* revelations, wallet activations and denunciations *) + { + max_size = max_anon_ops_per_block * 1024; + max_op = Some max_anon_ops_per_block; + }; + (* 512kB *) + {max_size = 512 * 1024; max_op = None}; + ] + +let rpc_services = + Alpha_services.register () ; + Services_registration.get_rpc_services () + +type validation_state = Validate.validation_state + +type application_state = Apply.application_state + +(** Circumstances and relevant information for [begin_validation] and + [begin_application] below. *) +type mode = + | Application of block_header + | Partial_validation of block_header + | Construction of { + predecessor_hash : Block_hash.t; + timestamp : Time.t; + block_header_data : block_header_data; + } + | Partial_construction of { + predecessor_hash : Block_hash.t; + timestamp : Time.t; + } + +let can_contain_preattestations mode = + let open Result_syntax in + match mode with + | Construction _ | Partial_construction _ -> return_true + | Application block_header | Partial_validation block_header -> + (* A preexisting block, which has a complete and correct block + header, can only contain preattestations when the locked + round in the fitness has an actual value. *) + let* locked_round = + Alpha_context.Fitness.locked_round_from_raw block_header.shell.fitness + in + return (Option.is_some locked_round) + +(** Initialize the consensus rights by first slot for modes that are + about the validation/application of a block: application, partial + validation, and full construction. + + In these modes, attestations must point to the predecessor's level + and preattestations, if any, to the block's level. *) +let init_consensus_rights_for_block ctxt mode ~predecessor_level = + let open Lwt_result_syntax in + let open Alpha_context in + let* ctxt, attestations_map = + Baking.attesting_rights_by_first_slot ctxt predecessor_level + in + let*? can_contain_preattestations = can_contain_preattestations mode in + let* ctxt, allowed_preattestations = + if can_contain_preattestations then + let* ctxt, preattestations_map = + Baking.attesting_rights_by_first_slot ctxt (Level.current ctxt) + in + return (ctxt, Some preattestations_map) + else return (ctxt, None) + in + let ctxt = + Consensus.initialize_consensus_operation + ctxt + ~allowed_attestations:(Some attestations_map) + ~allowed_preattestations + in + return ctxt + +(** Initialize the consensus rights for a mempool (partial + construction mode). + + In the mempool, there are three allowed levels for both + attestations and preattestations: [predecessor_level - 1] (aka the + grandparent's level), [predecessor_level] (that is, the level of + the mempool's head), and [predecessor_level + 1] (aka the current + level in ctxt). *) +let init_consensus_rights_for_mempool ctxt ~predecessor_level = + let open Lwt_result_syntax in + let open Alpha_context in + (* We don't want to compute the tables by first slot for all three + possible levels because it is time-consuming. So we don't compute + any [allowed_attestations] or [allowed_preattestations] tables. *) + let ctxt = + Consensus.initialize_consensus_operation + ctxt + ~allowed_attestations:None + ~allowed_preattestations:None + in + (* However, we want to ensure that the cycle rights are loaded in + the context, so that {!Stake_distribution.slot_owner} doesn't + have to initialize them each time it is called (we do this now + because the context is discarded at the end of the validation of + each operation, so we can't rely on the caching done by + [slot_owner] itself). *) + let cycle = (Level.current ctxt).cycle in + let* ctxt = Stake_distribution.load_sampler_for_cycle ctxt cycle in + (* If the cycle has changed between the grandparent level and the + current level, we also initialize the sampler for that + cycle. That way, all three allowed levels are covered. *) + match Level.pred ctxt predecessor_level with + | Some gp_level when Cycle.(gp_level.cycle <> cycle) -> + Stake_distribution.load_sampler_for_cycle ctxt gp_level.cycle + | Some _ | None -> return ctxt + +let prepare_ctxt ctxt mode ~(predecessor : Block_header.shell_header) = + let open Lwt_result_syntax in + let open Alpha_context in + let level, timestamp = + match mode with + | Application block_header | Partial_validation block_header -> + (block_header.shell.level, block_header.shell.timestamp) + | Construction {timestamp; _} | Partial_construction {timestamp; _} -> + (Int32.succ predecessor.level, timestamp) + in + let* ctxt, migration_balance_updates, migration_operation_results = + prepare ctxt ~level ~predecessor_timestamp:predecessor.timestamp ~timestamp + in + let*? predecessor_raw_level = Raw_level.of_int32 predecessor.level in + let predecessor_level = Level.from_raw ctxt predecessor_raw_level in + let* ctxt = Delegate.prepare_stake_distribution ctxt in + let* ctxt = + match mode with + | Application _ | Partial_validation _ | Construction _ -> + init_consensus_rights_for_block ctxt mode ~predecessor_level + | Partial_construction _ -> + init_consensus_rights_for_mempool ctxt ~predecessor_level + in + return + ( ctxt, + migration_balance_updates, + migration_operation_results, + predecessor_level ) + +let begin_validation ctxt chain_id mode ~predecessor = + let open Lwt_result_syntax in + let open Alpha_context in + let* ( ctxt, + _migration_balance_updates, + _migration_operation_results, + predecessor_level ) = + prepare_ctxt ctxt ~predecessor mode + in + let predecessor_timestamp = predecessor.timestamp in + let predecessor_fitness = predecessor.fitness in + match mode with + | Application block_header -> + let*? fitness = Fitness.from_raw block_header.shell.fitness in + Validate.begin_application + ctxt + chain_id + ~predecessor_level + ~predecessor_timestamp + block_header + fitness + | Partial_validation block_header -> + let*? fitness = Fitness.from_raw block_header.shell.fitness in + Validate.begin_partial_validation + ctxt + chain_id + ~predecessor_level + ~predecessor_timestamp + block_header + fitness + | Construction {predecessor_hash; timestamp; block_header_data} -> + let*? predecessor_round = Fitness.round_from_raw predecessor_fitness in + let*? round = + Round.round_of_timestamp + (Constants.round_durations ctxt) + ~predecessor_timestamp + ~predecessor_round + ~timestamp + in + Validate.begin_full_construction + ctxt + chain_id + ~predecessor_level + ~predecessor_round + ~predecessor_timestamp + ~predecessor_hash + round + block_header_data.contents + | Partial_construction _ -> + let*? predecessor_round = Fitness.round_from_raw predecessor_fitness in + return + (Validate.begin_partial_construction + ctxt + chain_id + ~predecessor_level + ~predecessor_round) + +let validate_operation = Validate.validate_operation + +let finalize_validation = Validate.finalize_block + +type error += Cannot_apply_in_partial_validation + +let () = + register_error_kind + `Permanent + ~id:"main.begin_application.cannot_apply_in_partial_validation" + ~title:"cannot_apply_in_partial_validation" + ~description: + "Cannot instantiate an application state using the 'Partial_validation' \ + mode." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Cannot instantiate an application state using the \ + 'Partial_validation' mode.") + Data_encoding.(empty) + (function Cannot_apply_in_partial_validation -> Some () | _ -> None) + (fun () -> Cannot_apply_in_partial_validation) + +let begin_application ctxt chain_id mode ~predecessor = + let open Lwt_result_syntax in + let open Alpha_context in + let* ( ctxt, + migration_balance_updates, + migration_operation_results, + predecessor_level ) = + prepare_ctxt ctxt ~predecessor mode + in + let predecessor_timestamp = predecessor.timestamp in + let predecessor_fitness = predecessor.fitness in + match mode with + | Application block_header -> + Apply.begin_application + ctxt + chain_id + ~migration_balance_updates + ~migration_operation_results + ~predecessor_fitness + block_header + | Partial_validation _ -> tzfail Cannot_apply_in_partial_validation + | Construction {predecessor_hash; timestamp; block_header_data; _} -> + let*? predecessor_round = Fitness.round_from_raw predecessor_fitness in + Apply.begin_full_construction + ctxt + chain_id + ~migration_balance_updates + ~migration_operation_results + ~predecessor_timestamp + ~predecessor_level + ~predecessor_round + ~predecessor_hash + ~timestamp + block_header_data.contents + | Partial_construction {predecessor_hash; _} -> + Apply.begin_partial_construction + ctxt + chain_id + ~migration_balance_updates + ~migration_operation_results + ~predecessor_hash + ~predecessor_fitness + +let apply_operation = Apply.apply_operation + +let finalize_application = Apply.finalize_block + +let compare_operations (oph1, op1) (oph2, op2) = + Alpha_context.Operation.compare (oph1, op1) (oph2, op2) + +let init chain_id ctxt block_header = + let open Lwt_result_syntax in + let level = block_header.Block_header.level in + let timestamp = block_header.timestamp in + let predecessor = block_header.predecessor in + let typecheck_smart_contract (ctxt : Alpha_context.context) + (script : Alpha_context.Script.t) = + let allow_forged_tickets_in_storage, allow_forged_lazy_storage_id_in_storage + = + (false, false) + (* There should be no forged value in bootstrap contracts. *) + in + let* Ex_script (Script parsed_script), ctxt = + Script_ir_translator.parse_script + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:true ()) + ~allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id_in_storage + script + in + let* storage, lazy_storage_diff, ctxt = + Script_ir_translator.extract_lazy_storage_diff + ctxt + Optimized + parsed_script.storage_type + parsed_script.storage + ~to_duplicate:Script_ir_translator.no_lazy_storage_id + ~to_update:Script_ir_translator.no_lazy_storage_id + ~temporary:false + in + let+ storage, ctxt = + Script_ir_translator.unparse_data + ctxt + Optimized + parsed_script.storage_type + storage + in + let storage = Alpha_context.Script.lazy_expr storage in + (({script with storage}, lazy_storage_diff), ctxt) + in + (* The cache must be synced at the end of block validation, so we do + so here for the first block in a protocol where `finalize_block` + is not called. *) + let*? raw_level = Alpha_context.Raw_level.of_int32 level in + let init_fitness = + Alpha_context.Fitness.create_without_locked_round + ~level:raw_level + ~round:Alpha_context.Round.zero + ~predecessor_round:Alpha_context.Round.zero + in + let* ctxt = + Alpha_context.prepare_first_block + chain_id + ~typecheck_smart_contract + ~typecheck_smart_rollup: + Sc_rollup_operations.validate_untyped_parameters_ty + ~level + ~timestamp + ~predecessor + ctxt + in + let cache_nonce = + Alpha_context.Cache.cache_nonce_from_block_header + block_header + ({ + payload_hash = Block_payload_hash.zero; + payload_round = Alpha_context.Round.zero; + per_block_votes = + { + liquidity_baking_vote = + Alpha_context.Per_block_votes.Per_block_vote_pass; + adaptive_issuance_vote = + Alpha_context.Per_block_votes.Per_block_vote_pass; + }; + seed_nonce_hash = None; + proof_of_work_nonce = + Bytes.make Constants_repr.proof_of_work_nonce_size '0'; + } + : Alpha_context.Block_header.contents) + in + let*! ctxt = Alpha_context.Cache.Admin.sync ctxt cache_nonce in + return + (Alpha_context.finalize ctxt (Alpha_context.Fitness.to_raw init_fitness)) + +let value_of_key ~chain_id:_ ~predecessor_context:ctxt ~predecessor_timestamp + ~predecessor_level:pred_level ~predecessor_fitness:_ ~predecessor:_ + ~timestamp = + let open Lwt_result_syntax in + let level = Int32.succ pred_level in + let* ctxt, _, _ = + Alpha_context.prepare ctxt ~level ~predecessor_timestamp ~timestamp + in + return (Apply.value_of_key ctxt) + +module Mempool = struct + include Mempool_validation + + let init ctxt chain_id ~head_hash ~(head : Block_header.shell_header) = + let open Lwt_result_syntax in + let open Alpha_context in + let* ( ctxt, + _migration_balance_updates, + _migration_operation_results, + head_level ) = + (* We use Partial_construction to factorize the [prepare_ctxt]. *) + prepare_ctxt + ctxt + (Partial_construction + {predecessor_hash = head_hash; timestamp = head.timestamp}) + ~predecessor:head + in + let*? predecessor_round = Fitness.round_from_raw head.fitness in + return + (init + ctxt + chain_id + ~predecessor_level:head_level + ~predecessor_round + ~predecessor_hash:head_hash) +end + +(* Vanity nonce: 2904751756914914 *) diff --git a/src/proto_020_PsParisC/lib_protocol/main.mli b/src/proto_020_PsParisC/lib_protocol/main.mli new file mode 100644 index 000000000000..d6d5913c57da --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/main.mli @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Protocol Signature Instance + + This module is the entrypoint to the protocol for shells and other + embedders. This signature is an instance of + {{!Tezos_protocol_environment_sigs.V7.T.Updater.PROTOCOL} the + [Updater.PROTOCOL] signature} from the + {{:https://tezos.gitlab.io/shell/the_big_picture.html#the-economic-protocol-environment-and-compiler} + Protocol Environment}. + + Each Protocol depends on a version of the Protocol Environment. For the + currently developed protocol, this is normally the latest version. You can + see {{!Tezos_protocol_environment_sigs} the full list of versions here}. + + For details on how Protocol and Environment interact, see + {{:https://tezos.gitlab.io/shell/the_big_picture.html} this overview}. + *) + +type operation_data = Alpha_context.packed_protocol_data + +type operation = Alpha_context.packed_operation = { + shell : Operation.shell_header; + protocol_data : operation_data; +} + +include + Updater.PROTOCOL + with type block_header_data = Alpha_context.Block_header.protocol_data + and type block_header_metadata = Apply_results.block_metadata + and type block_header = Alpha_context.Block_header.t + and type operation_data := operation_data + and type operation_receipt = Apply_results.packed_operation_metadata + and type operation := operation + and type validation_state = Validate.validation_state + and type application_state = Apply.application_state diff --git a/src/proto_020_PsParisC/lib_protocol/manager_counter_repr.ml b/src/proto_020_PsParisC/lib_protocol/manager_counter_repr.ml new file mode 100644 index 000000000000..9e93014af743 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/manager_counter_repr.ml @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Compare.Z + +let init = Z.zero + +let succ = Z.succ + +let pp = Z.pp_print + +let encoding_for_storage = Data_encoding.z + +let encoding_for_operation = Data_encoding.(check_size 10 n) + +let encoding_for_RPCs = Data_encoding.n + +let encoding_for_errors = Data_encoding.z + +module Internal_for_injection = struct + let of_string s = + match Z.of_string s with + | exception _ -> None + | z -> if z < Z.zero then None else Some z +end + +module Internal_for_tests = struct + let of_int i = + assert (Compare.Int.(i >= 0)) ; + Z.of_int i + + let to_int = Z.to_int + + let add c i = + let c = Z.(add c (of_int i)) in + assert (c >= Z.zero) ; + c +end diff --git a/src/proto_020_PsParisC/lib_protocol/manager_counter_repr.mli b/src/proto_020_PsParisC/lib_protocol/manager_counter_repr.mli new file mode 100644 index 000000000000..50fdf8e1ded5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/manager_counter_repr.mli @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Counters are used as anti-replay protection mechanism in + manager operations: each manager account stores a counter and + each manager operation declares a value for the counter. When + a manager operation is applied, the value of the counter of + its manager is checked and incremented. *) + +include Compare.S + +(** Initial value for a counter (zero). *) +val init : t + +(** Successor of a counter. *) +val succ : t -> t + +(** Pretty-printer for counters. *) +val pp : Format.formatter -> t -> unit + +(** Encoding for a counter to be used in {!Storage}. *) +val encoding_for_storage : t Data_encoding.t + +(** Encoding for a counter to be used in {!Operation_repr}. *) +val encoding_for_operation : t Data_encoding.t + +(** Encoding for a counter to be used in RPCs. *) +val encoding_for_RPCs : t Data_encoding.t + +(** Encoding for a counter to be used in errors. *) +val encoding_for_errors : t Data_encoding.t + +(** To be used in client injection only. *) +module Internal_for_injection : sig + (** Converts a string to a counter. + Returns [None] if the string does not represent a valid counter. *) + val of_string : string -> t option +end + +module Internal_for_tests : sig + val of_int : int -> t + + val to_int : t -> int + + val add : t -> int -> t +end diff --git a/src/proto_020_PsParisC/lib_protocol/manager_repr.ml b/src/proto_020_PsParisC/lib_protocol/manager_repr.ml new file mode 100644 index 000000000000..b96a51401289 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/manager_repr.ml @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Managers' keys *) + +type manager_key = + | Hash of Signature.Public_key_hash.t + | Public_key of Signature.Public_key.t + +type t = manager_key + +open Data_encoding + +let hash_case tag = + case + tag + ~title:"Public_key_hash" + Signature.Public_key_hash.encoding + (function Hash hash -> Some hash | _ -> None) + (fun hash -> Hash hash) + +let pubkey_case tag = + case + tag + ~title:"Public_key" + Signature.Public_key.encoding + (function Public_key hash -> Some hash | _ -> None) + (fun hash -> Public_key hash) + +let encoding = union [hash_case (Tag 0); pubkey_case (Tag 1)] diff --git a/src/proto_020_PsParisC/lib_protocol/manager_repr.mli b/src/proto_020_PsParisC/lib_protocol/manager_repr.mli new file mode 100644 index 000000000000..6ffcba3c3402 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/manager_repr.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Managers' keys *) + +(** The public key of the manager of a contract is reveled only after the + first operation. At Origination time, the manager provides only the hash + of its public key that is stored in the contract. When the public key + is actually revealed, the contract store is updated with the public key + instead of the hash of the key. *) +type manager_key = + | Hash of Signature.Public_key_hash.t + | Public_key of Signature.Public_key.t + +type t = manager_key + +val encoding : t Data_encoding.encoding diff --git a/src/proto_020_PsParisC/lib_protocol/mempool_validation.ml b/src/proto_020_PsParisC/lib_protocol/mempool_validation.ml new file mode 100644 index 000000000000..67dd1fbeaf76 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/mempool_validation.ml @@ -0,0 +1,220 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Validate + +type t = { + predecessor_hash : Block_hash.t; + operation_state : operation_conflict_state; + operations : packed_operation Operation_hash.Map.t; +} + +type validation_info = info + +type add_result = Added | Replaced of {removed : Operation_hash.t} | Unchanged + +type operation_conflict = Validate_errors.operation_conflict = + | Operation_conflict of { + existing : Operation_hash.t; + new_operation : Operation_hash.t; + } + +type add_error = + | Validation_error of error trace + | Add_conflict of operation_conflict + +type merge_error = Incompatible_mempool | Merge_conflict of operation_conflict + +let encoding : t Data_encoding.t = + let open Data_encoding in + def "mempool" + @@ conv + (fun {predecessor_hash; operation_state; operations} -> + (predecessor_hash, operation_state, operations)) + (fun (predecessor_hash, operation_state, operations) -> + {predecessor_hash; operation_state; operations}) + @@ obj3 + (req "predecessor_hash" Block_hash.encoding) + (req "operation_state" operation_conflict_state_encoding) + (req + "operations" + (Operation_hash.Map.encoding + (dynamic_size ~kind:`Uint30 Operation.encoding))) + +let init ctxt chain_id ~predecessor_level ~predecessor_round ~predecessor_hash : + validation_info * t = + let {info; operation_state; _} = + begin_partial_construction + ctxt + chain_id + ~predecessor_level + ~predecessor_round + in + ( info, + {predecessor_hash; operation_state; operations = Operation_hash.Map.empty} + ) + +type conflict_handler = + existing_operation:Operation_hash.t * packed_operation -> + new_operation:Operation_hash.t * packed_operation -> + [`Keep | `Replace] + +let remove_operation mempool oph = + match Operation_hash.Map.find_opt oph mempool.operations with + | None -> mempool + | Some {shell; protocol_data = Operation_data protocol_data} -> + let operations = Operation_hash.Map.remove oph mempool.operations in + let operation_state = + remove_operation mempool.operation_state {shell; protocol_data} + in + {mempool with operations; operation_state} + +let add_operation ?(check_signature = true) + ?(conflict_handler : conflict_handler option) info mempool + (oph, (packed_op : packed_operation)) : + (t * add_result, add_error) result Lwt.t = + let open Lwt_syntax in + let {shell; protocol_data = Operation_data protocol_data} = packed_op in + let operation : _ Alpha_context.operation = {shell; protocol_data} in + let* validate_result = check_operation ~check_signature info operation in + match validate_result with + | Error err -> Lwt.return_error (Validation_error err) + | Ok () -> ( + match check_operation_conflict mempool.operation_state oph operation with + | Ok () -> + let operation_state = + add_valid_operation mempool.operation_state oph operation + in + let operations = + Operation_hash.Map.add oph packed_op mempool.operations + in + let result = Added in + Lwt.return_ok ({mempool with operation_state; operations}, result) + | Error + (Validate_errors.Operation_conflict + {existing; new_operation = new_oph} as x) -> ( + match conflict_handler with + | Some handler -> ( + let new_operation = (new_oph, packed_op) in + let existing_operation = + match + Operation_hash.Map.find_opt existing mempool.operations + with + | None -> assert false + | Some op -> (existing, op) + in + match handler ~existing_operation ~new_operation with + | `Keep -> Lwt.return_ok (mempool, Unchanged) + | `Replace -> + let mempool = remove_operation mempool existing in + let operation_state = + add_valid_operation + mempool.operation_state + new_oph + operation + in + let operations = + Operation_hash.Map.add oph packed_op mempool.operations + in + Lwt.return_ok + ( {mempool with operations; operation_state}, + Replaced {removed = existing} )) + | None -> Lwt.return_error (Add_conflict x))) + +let merge ?conflict_handler existing_mempool new_mempool = + let open Result_syntax in + if + Block_hash.( + existing_mempool.predecessor_hash <> new_mempool.predecessor_hash) + then Error Incompatible_mempool + else + let unique_new_operations = + (* only retain unique operations that are in new_mempool *) + Operation_hash.Map.( + merge + (fun _ l r -> + match (l, r) with + | None, Some r -> Some r + | Some _, None -> None + | Some _, Some _ -> None + | None, None -> None) + existing_mempool.operations + new_mempool.operations) + in + let unopt_assert = function None -> assert false | Some o -> o in + let handle_conflict new_operation_content conflict = + match (conflict, conflict_handler) with + | Ok (), _ -> Ok `Add_new + | Error conflict, None -> Error (Merge_conflict conflict) + | ( Error (Operation_conflict {existing; new_operation}), + Some (f : conflict_handler) ) -> ( + (* New operations can only conflict with operations + already present in the existing mempool. *) + let existing_operation_content = + Operation_hash.Map.find_opt existing existing_mempool.operations + |> unopt_assert + in + match + f + ~existing_operation:(existing, existing_operation_content) + ~new_operation:(new_operation, new_operation_content) + with + | `Keep -> Ok `Do_nothing + | `Replace -> Ok (`Replace existing)) + in + Operation_hash.Map.fold_e + (fun roph packed_right_op mempool_acc -> + let {shell; protocol_data = Operation_data protocol_data} = + packed_right_op + in + let right_op = ({shell; protocol_data} : _ operation) in + let* conflict = + check_operation_conflict mempool_acc.operation_state roph right_op + |> handle_conflict packed_right_op + in + match conflict with + | `Do_nothing -> return mempool_acc + | `Add_new -> + let operation_state = + add_valid_operation mempool_acc.operation_state roph right_op + in + let operations = + Operation_hash.Map.add roph packed_right_op mempool_acc.operations + in + return {mempool_acc with operation_state; operations} + | `Replace loph -> + let mempool_acc = remove_operation mempool_acc loph in + let operation_state = + add_valid_operation mempool_acc.operation_state roph right_op + in + let operations = + Operation_hash.Map.add roph packed_right_op mempool_acc.operations + in + return {mempool_acc with operation_state; operations}) + unique_new_operations + existing_mempool + +let operations mempool = mempool.operations diff --git a/src/proto_020_PsParisC/lib_protocol/mempool_validation.mli b/src/proto_020_PsParisC/lib_protocol/mempool_validation.mli new file mode 100644 index 000000000000..6b9c8183d612 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/mempool_validation.mli @@ -0,0 +1,184 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module implements a mempool structure meant to be used by a + shell and bakers in order to incrementally accumulate commutative + operations which could then be safely used to bake a new + block. These mempool components guarantee a set of properties + useful for these purposes: + + - Every operation contained in a mempool is valid; + + - All the mempool's operations can safely be included (and + applicable) in a block in an arbitrary order which means + operations commutes. However, to build a valid block with these + operations: + + - Operations must be reorganized with regards to their validation + passes. + - Block's operations quota are ignored, it is the baker's + responsability to ensure that the set of selected operations + does not exceed gas/size operations quota. + - The baker must also include the required preattestations and + attestations. + + - The merging of two mempools also maintains the aforementioned + properties. + + Mempools do not depend on local data and therefore are + serializable. This is useful when a node needs to send a mempool + to another (remote-)process (e.g. the baker). +*) + +open Alpha_context + +(** Mempool type *) +type t + +(** Validation info type required to validate and add operations to a + mempool. *) +type validation_info + +(** Type of the function that may be provided in order to resolve a + potential conflict when adding an operation to an existing mempool + or when merging two mempools. This handler may be defined as a + simple order relation over operations (e.g. prioritize the most + profitable operations) or an arbitrary one (e.g. prioritize + operations where the source is a specific manager). + + Returning [`Keep] will leave the mempool unchanged and retain the + [existing_operation] while returning [`Replace] will remove + [existing_operation] and add [new_operation] instead. *) +type conflict_handler = + existing_operation:Operation_hash.t * packed_operation -> + new_operation:Operation_hash.t * packed_operation -> + [`Keep | `Replace] + +(** Return type when adding an operation to the mempool *) +type add_result = + | Added + (** [Added] means that an operation was successfully added to + the mempool without any conflict. *) + | Replaced of {removed : Operation_hash.t} + (** [Replaced {removed}] means that an operation was + successfully added but there was a conflict with the [removed] + operation which was removed from the mempool. *) + | Unchanged + (** [Unchanged] means that there was a conflict with an existing + operation which was considered better by the + [conflict_handler], therefore the new operation is discarded + and the mempool remains unchanged. *) + +type operation_conflict = Validate_errors.operation_conflict = + | Operation_conflict of { + existing : Operation_hash.t; + new_operation : Operation_hash.t; + } + +(** Error type returned when adding an operation to the mempool fails. *) +type add_error = + | Validation_error of error trace + (** [Validation_error _] means that the operation is invalid. *) + | Add_conflict of operation_conflict + (** [Add_conflict _] means that an operation conflicts with an + existing one. This error will only be obtained when no + [conflict_handler] was provided. Moreover, [Validation_error _] + takes precedence over [Add_conflict _] which implies that + we have the implicit invariant that the operation would be + valid if there was no conflict. Therefore, if + [add_operation] would have to be called again, it would be + redondant to check the operation's signature. *) + +(** Error type returned when the merge of two mempools fails. *) +type merge_error = + | Incompatible_mempool + (** [Incompatible_mempool _] means that the two mempools are not built + ontop of the same head and therefore cannot be considered. *) + | Merge_conflict of operation_conflict + (** [Merge_conflict _] arises when two mempools contain conflicting + operations and no [conflict_handler] was provided. *) + +(** Mempool encoding *) +val encoding : t Data_encoding.t + +(** Initialize a static [validation_info] and [mempool], required to validate and add + operations, and an incremental and serializable [mempool]. *) +val init : + context -> + Chain_id.t -> + predecessor_level:Level.t -> + predecessor_round:Round.t -> + predecessor_hash:Block_hash.t -> + validation_info * t + +(** Adds an operation to a [mempool] if and only if it is valid and + does not conflict with previously added operations. + + This function checks the validity of an operation (see + {!Validate.check_operation}) and tries to add it to the mempool. + + If an error occurs during the validation, the result will be a + [Validation_error ]. If a conflict with a previous operation + exists, the result will be an [Add_conflict] (see + {!Validate.check_operation_conflict}). Important: no + [Add_conflict] will be raised if a [conflict_handler] is + provided (see [add_result]). + + If no error is raised the operation is potentially added to the + [mempool] depending on the [add_result] value. *) +val add_operation : + ?check_signature:bool -> + ?conflict_handler:conflict_handler -> + validation_info -> + t -> + Operation_hash.t * packed_operation -> + (t * add_result, add_error) result Lwt.t + +(** [remove_operation mempool oph] removes the operation [oph] from + the [mempool]. The [mempool] remains unchanged when [oph] is not + present in the [mempool] *) +val remove_operation : t -> Operation_hash.t -> t + +(** [merge ?conflict_handler existing_mempool new_mempool] merges [new_mempool] + {b into} [existing_mempool]. + + Mempools may only be merged if they are compatible: i.e. both have + been initialised with the same predecessor block. Otherwise, the + [Incompatible_mempool] error is returned. + + Conflicts between operations from the two mempools can + occur. Similarly as [add_operation], a [Merge_conflict] error + may be raised when no [conflict_handler] is provided. + + [existing_operation] in [conflict_handler ~existing_operation ~new_operation] + references operations present in [existing_mempool] while + [new_operation] will reference operations present in + [new_mempool]. *) +val merge : + ?conflict_handler:conflict_handler -> t -> t -> (t, merge_error) result + +(** [operations mempool] returns the map of operations present in + [mempool]. *) +val operations : t -> packed_operation Operation_hash.Map.t diff --git a/src/proto_020_PsParisC/lib_protocol/merkle_list.ml b/src/proto_020_PsParisC/lib_protocol/merkle_list.ml new file mode 100644 index 000000000000..2f26c768269b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/merkle_list.ml @@ -0,0 +1,363 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Merkle_list_invalid_position + +let max_depth ~count_limit = + (* We assume that the Merkle_tree implementation computes a tree in a + logarithmic size of the number of leaves. *) + let log2 n = Z.numbits (Z.of_int n) in + log2 count_limit + +let () = + register_error_kind + `Temporary + ~id:"Merkle_list_invalid_position" + ~title:"Merkle_list_invalid_position" + ~description:"Merkle_list_invalid_position" + ~pp:(fun ppf () -> Format.fprintf ppf "%s" "Merkle_list_invalid_position") + Data_encoding.empty + (function Merkle_list_invalid_position -> Some () | _ -> None) + (fun () -> Merkle_list_invalid_position) + +module type T = sig + type t + + type h + + type elt + + type path + + val dummy_path : path + + val pp_path : Format.formatter -> path -> unit + + val nil : t + + val empty : h + + val root : t -> h + + val snoc : t -> elt -> t + + val snoc_tr : t -> elt -> t + + val of_list : elt list -> t + + val compute : elt list -> h + + val path_encoding : path Data_encoding.t + + val bounded_path_encoding : ?max_length:int -> unit -> path Data_encoding.t + + val compute_path : t -> int -> path tzresult + + val check_path : path -> int -> elt -> h -> bool tzresult + + val path_depth : path -> int + + val elt_bytes : elt -> Bytes.t + + module Internal_for_tests : sig + val path_to_list : path -> h list + + val equal : t -> t -> bool + + val to_list : t -> h list + end +end + +module Make (El : sig + type t + + val to_bytes : t -> bytes +end) +(H : S.HASH) : T with type elt = El.t and type h = H.t = struct + type h = H.t + + type elt = El.t + + let elt_bytes = El.to_bytes + + (* + The goal of this structure is to model an append-only list. + Its internal representation is that of a binary tree whose + leaves are all at the same level (the tree's height). + + To insert a new element in a full tree t, we create a new root with t + as its left subtree and a new tree t' as its right subtree. t' is just a + left-spine of the same height as t. Visually, + + t = / \ t' = / snoc 4 t = / \ + /\ /\ / / \ / + 0 1 2 3 4 /\ /\ / + 0 1 2 3 4 + + Then, this is a balanced tree by construction. + As the key in the tree for a given position is the position's + binary decomposition of size height(tree), the tree is dense. + For that reason, the use of extenders is not needed. + *) + + type tree = Empty | Leaf of h | Node of (h * tree * tree) + + (* The tree has the following invariants: + A node [Node left right] if valid iff + 1. [right] is Empty and [left] is not Empty, or + 2. [right] is not Empty and [left] is full + Additionally: + [t.depth] is the height of [t.tree] and + [t.next_pos] is the number of leaves in [t.tree] *) + type t = {tree : tree; depth : int; next_pos : int} + + type path = h list + + let dummy_path = [] + + let pp_path ppf = + Format.fprintf + ppf + "%a" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ") + H.pp) + + let empty = H.zero + + let root = function Empty -> empty | Leaf h -> h | Node (h, _, _) -> h + + let nil = {tree = Empty; depth = 0; next_pos = 0} + + let hash_elt el = H.hash_bytes [elt_bytes el] + + let leaf_of el = Leaf (hash_elt el) + + let hash2 h1 h2 = H.(hash_bytes [to_bytes h1; to_bytes h2]) + + let node_of t1 t2 = Node (hash2 (root t1) (root t2), t1, t2) + + (* to_bin computes the [depth]-long binary representation of [pos] + (left-padding with 0s if required). This corresponds to the tree traversal + of en element at position [pos] (false = left, true = right). + + Pre-condition: pos >= 0 /| pos < 2^depth + Post-condition: len(to_bin pos depth) = depth *) + let to_bin ~pos ~depth = + let rec aux acc pos depth = + let pos', dir = (pos / 2, pos mod 2) in + match depth with + | 0 -> acc + | d -> aux (Compare.Int.(dir = 1) :: acc) pos' (d - 1) + in + aux [] pos depth + + (* Constructs a tree of a given depth in which every right subtree is empty + * and the only leaf contains the hash of el. *) + let make_spine_with el = + let rec aux left = function + | 0 -> left + | d -> (aux [@tailcall]) (node_of left Empty) (d - 1) + in + aux (leaf_of el) + + let snoc t (el : elt) = + let rec traverse tree depth key = + match (tree, key) with + | Node (_, t_left, Empty), true :: _key -> + (* The base case where the left subtree is full and we start + * the right subtree by creating a new tree the size of the remaining + * depth and placing the new element in its leftmost position. *) + let t_right = make_spine_with el (depth - 1) in + node_of t_left t_right + | Node (_, t_left, Empty), false :: key -> + (* Traversing left, the left subtree is not full (and thus the right + * subtree is empty). Recurse on left subtree. *) + let t_left = traverse t_left (depth - 1) key in + node_of t_left Empty + | Node (_, t_left, t_right), true :: key -> + (* Traversing right, the left subtree is full. + * Recurse on right subtree *) + let t_right = traverse t_right (depth - 1) key in + node_of t_left t_right + | _, _ -> + (* Impossible by construction of the tree and of the key. + * See [tree] invariants and [to_bin]. *) + assert false + in + + let tree', depth' = + match (t.tree, t.depth, t.next_pos) with + | Empty, 0, 0 -> (node_of (leaf_of el) Empty, 1) + | tree, depth, pos when Int32.(equal (shift_left 1l depth) (of_int pos)) + -> + let t_right = make_spine_with el depth in + (node_of tree t_right, depth + 1) + | tree, depth, pos -> + let key = to_bin ~pos ~depth in + (traverse tree depth key, depth) + in + {tree = tree'; depth = depth'; next_pos = t.next_pos + 1} + + type zipper = Left of zipper * tree | Right of tree * zipper | Top + + let rec rebuild_tree z t = + match z with + | Top -> t + | Left (z, r) -> (rebuild_tree [@tailcall]) z (node_of t r) + | Right (l, z) -> (rebuild_tree [@tailcall]) z (node_of l t) + + let snoc_tr t (el : elt) = + let rec traverse (z : zipper) tree depth key = + match (tree, key) with + | Node (_, t_left, Empty), true :: _key -> + let t_right = make_spine_with el (depth - 1) in + rebuild_tree z (node_of t_left t_right) + | Node (_, t_left, Empty), false :: key -> + let z = Left (z, Empty) in + (traverse [@tailcall]) z t_left (depth - 1) key + | Node (_, t_left, t_right), true :: key -> + let z = Right (t_left, z) in + (traverse [@tailcall]) z t_right (depth - 1) key + | _, _ -> + (* Impossible by construction of the tree and of the key. + * See [tree] invariants and [to_bin]. *) + assert false + in + + let tree', depth' = + match (t.tree, t.depth, t.next_pos) with + | Empty, 0, 0 -> (node_of (leaf_of el) Empty, 1) + | tree, depth, pos when Int32.(equal (shift_left 1l depth) (of_int pos)) + -> + let t_right = make_spine_with el depth in + (node_of tree t_right, depth + 1) + | tree, depth, pos -> + let key = to_bin ~pos ~depth in + (traverse Top tree depth key, depth) + in + {tree = tree'; depth = depth'; next_pos = t.next_pos + 1} + + let rec tree_to_list = function + | Empty -> [] + | Leaf h -> [h] + | Node (_, t_left, t_right) -> tree_to_list t_left @ tree_to_list t_right + + let path_encoding = Data_encoding.(list H.encoding) + + let bounded_path_encoding ?max_length () = + match max_length with + | None -> path_encoding + | Some max_length -> Data_encoding.((list ~max_length) H.encoding) + + (* The order of the path is from bottom to top *) + let compute_path {tree; depth; next_pos} pos = + let open Result_syntax in + if Compare.Int.(pos < 0 || pos >= next_pos) then + tzfail Merkle_list_invalid_position + else + let key = to_bin ~pos ~depth in + let rec aux acc tree key = + match (tree, key) with + | Leaf _, [] -> return acc + | Node (_, l, r), b :: key -> + if b then aux (root l :: acc) r key else aux (root r :: acc) l key + | _ -> tzfail Merkle_list_invalid_position + in + aux [] tree key + + let check_path path pos el expected_root = + let open Result_syntax in + let depth = List.length path in + if + Compare.Int.(pos >= 0) + && Compare.Z.(Z.of_int pos < Z.shift_left Z.one depth) + then + let key = List.rev @@ to_bin ~pos ~depth in + let computed_root = + List.fold_left + (fun acc (sibling, b) -> + if b then hash2 sibling acc else hash2 acc sibling) + (hash_elt el) + (List.combine_drop path key) + in + return (H.equal computed_root expected_root) + else tzfail Merkle_list_invalid_position + + let path_depth path = List.length path + + let breadth_first_traversal ~leaf_func ~node_func ~empty ~res l = + let rec aux ~depth l = + let rec pairs acc = function + | [] -> List.rev acc + | [x] -> List.rev (node_func x empty :: acc) + | x :: y :: xs -> pairs (node_func x y :: acc) xs + in + match pairs [] l with + | [] -> res depth empty + | [t] -> res depth t + | pl -> aux ~depth:(depth + 1) pl + in + aux (List.map leaf_func l) ~depth:0 + + let compute = + breadth_first_traversal + ~leaf_func:hash_elt + ~node_func:hash2 + ~empty + ~res:(fun _ x -> x) + + let of_list l = + let depth, tree = + breadth_first_traversal + ~leaf_func:leaf_of + ~node_func:node_of + ~empty:Empty + ~res:(fun d l -> (d + 1, l)) + l + in + {tree; depth; next_pos = List.length l} + + let root t = root t.tree + + module Internal_for_tests = struct + let path_to_list x = x + + let to_list tree = tree_to_list tree.tree + + let equal t1 t2 = + let rec eq_tree t1 t2 = + match (t1, t2) with + | Empty, Empty -> true + | Leaf h1, Leaf h2 -> H.equal h1 h2 + | Node (h1, l1, r1), Node (h2, l2, r2) -> + H.equal h1 h2 && eq_tree l1 l2 && eq_tree r1 r2 + | _ -> false + in + Compare.Int.equal t1.depth t2.depth + && Compare.Int.equal t1.next_pos t2.next_pos + && eq_tree t1.tree t2.tree + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/merkle_list.mli b/src/proto_020_PsParisC/lib_protocol/merkle_list.mli new file mode 100644 index 000000000000..dceb20f2b347 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/merkle_list.mli @@ -0,0 +1,118 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Merkle_list_invalid_position + +(** Given a list of size [count_limit], returns the maximum depth of + its merklisation. *) +val max_depth : count_limit:int -> int + +module type T = sig + (** The type of a Merkle list *) + type t + + (** The type of a hash *) + type h + + (** The type of an element *) + type elt + + (** A path, together with an element's position, is the proof of inclusion + of an element in the Merkle list. *) + type path + + (** A dummy path that can be used as a placeholder when no path is + actually required. *) + val dummy_path : path + + val pp_path : Format.formatter -> path -> unit + + (** The empty Merkle list *) + val nil : t + + (** The empty hash *) + val empty : h + + (** [root t] returns the root hash of a Merkle list. *) + val root : t -> h + + (** [snoc t el] adds element [el] to a Merkle list [t] and returns + the new list. *) + val snoc : t -> elt -> t + + (** Tail recursive variant of [snoc]. *) + val snoc_tr : t -> elt -> t + + (** [of_list elems] returns the Merkle list constructed with [elems]. *) + val of_list : elt list -> t + + (** [compute elems] returns the root hash of the Merkle list constructed with + [elems]. *) + val compute : elt list -> h + + (** Encoding of a path. *) + val path_encoding : path Data_encoding.t + + (** Encoding of a path, with optional bound [max_length]. *) + val bounded_path_encoding : ?max_length:int -> unit -> path Data_encoding.t + + (** [compute_path t pos] computes the path of the element in position [pos]. + + Can fail with [Merkle_list_invalid_position] if [pos] is negative or + if it is greater than the number of elements in the list. *) + val compute_path : t -> int -> path tzresult + + (** [check_path path pos elt expected_root] checks that an [elt] with path + [path] at position [pos] has the [expected_root]. + + Can fail with [Merkle_list_invalid_position] if [pos] is negative or + if it is greater than the number of elements in the list. *) + val check_path : path -> int -> elt -> h -> bool tzresult + + (** [path_depth path] returns the depth of the tree [path] is + related to. *) + val path_depth : path -> int + + val elt_bytes : elt -> Bytes.t + + (**/**) + + module Internal_for_tests : sig + val path_to_list : path -> h list + + (** Checks equality between Merkle lists. Outside of testing, clients should + use [root] for comparison. *) + val equal : t -> t -> bool + + val to_list : t -> h list + end +end + +module Make (El : sig + type t + + val to_bytes : t -> bytes +end) +(H : S.HASH) : T with type elt = El.t and type h = H.t diff --git a/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.ml b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.ml new file mode 100644 index 000000000000..681337fa61c1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.ml @@ -0,0 +1,956 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Gas +module S = Saturation_repr +module Size = Gas_input_size + +module Cost_of = struct + let z_bytes (z : Z.t) = + let bits = Z.numbits z in + (7 + bits) / 8 + + let int_size_in_bytes (z : 'a Script_int.num) = z_bytes (Script_int.to_zint z) + + let manager_operation_int = 100 + + let manager_operation = step_cost @@ S.safe_int manager_operation_int + + module Interpreter = struct + open Michelson_v1_gas_costs + + let drop = atomic_step_cost cost_N_IDrop + + let dup = atomic_step_cost cost_N_IDup + + let swap = atomic_step_cost cost_N_ISwap + + let cons_some = atomic_step_cost cost_N_ICons_some + + let cons_none = atomic_step_cost cost_N_ICons_none + + let if_none = atomic_step_cost cost_N_IIf_none + + let opt_map = atomic_step_cost cost_N_IOpt_map + + let cons_pair = atomic_step_cost cost_N_ICons_pair + + let unpair = atomic_step_cost cost_N_IUnpair + + let car = atomic_step_cost cost_N_ICar + + let cdr = atomic_step_cost cost_N_ICdr + + let cons_left = atomic_step_cost cost_N_ILeft + + let cons_right = atomic_step_cost cost_N_IRight + + let if_left = atomic_step_cost cost_N_IIf_left + + let cons_list = atomic_step_cost cost_N_ICons_list + + let nil = atomic_step_cost cost_N_INil + + let if_cons = atomic_step_cost cost_N_IIf_cons + + let list_map : 'a Script_list.t -> Gas.cost = + fun _ -> atomic_step_cost cost_N_IList_map + + let list_size = atomic_step_cost cost_N_IList_size + + let list_iter : 'a Script_list.t -> Gas.cost = + fun _ -> atomic_step_cost cost_N_IList_iter + + let empty_set = atomic_step_cost cost_N_IEmpty_set + + let set_iter (type a) (set : a Script_typed_ir.set) = + let (module Box) = Script_set.get set in + atomic_step_cost (cost_N_ISet_iter Box.size) + + let set_size = atomic_step_cost cost_N_ISet_size + + let empty_map = atomic_step_cost cost_N_IEmpty_map + + let map_map (type k v) (map : (k, v) Script_typed_ir.map) = + let (module Box) = Script_map.get_module map in + atomic_step_cost (cost_N_IMap_map Box.size) + + let map_iter (type k v) (map : (k, v) Script_typed_ir.map) = + let (module Box) = Script_map.get_module map in + atomic_step_cost (cost_N_IMap_iter Box.size) + + let map_size = atomic_step_cost cost_N_IMap_size + + let big_map_elt_size = Script_expr_hash.size + + (* The uses of [cost_N_IMap_*] below are intentional. They are for + the cost of the big_map overlay. The other costs such as the storage + access and the deserialization are separately charged in the protocol. + We don't use [cost_N_IBig_map_*] here, since they include these partial + carbonations. *) + let big_map_mem ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_IMap_mem big_map_elt_size size) + + let big_map_get ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_IMap_get big_map_elt_size size) + + let big_map_update ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_IMap_update big_map_elt_size size) + + let big_map_get_and_update ({size; _} : _ Script_typed_ir.big_map_overlay) = + atomic_step_cost (cost_N_IMap_get_and_update big_map_elt_size size) + + let add_seconds_timestamp : + 'a Script_int.num -> Script_timestamp.t -> Gas.cost = + fun seconds timestamp -> + let seconds_bytes = int_size_in_bytes seconds in + let timestamp_bytes = z_bytes (Script_timestamp.to_zint timestamp) in + atomic_step_cost + (cost_N_IAdd_seconds_to_timestamp seconds_bytes timestamp_bytes) + + let add_timestamp_seconds : + Script_timestamp.t -> 'a Script_int.num -> Gas.cost = + fun timestamp seconds -> + let seconds_bytes = int_size_in_bytes seconds in + let timestamp_bytes = z_bytes (Script_timestamp.to_zint timestamp) in + atomic_step_cost + (cost_N_IAdd_timestamp_to_seconds timestamp_bytes seconds_bytes) + + let sub_timestamp_seconds : + Script_timestamp.t -> 'a Script_int.num -> Gas.cost = + fun timestamp seconds -> + let seconds_bytes = int_size_in_bytes seconds in + let timestamp_bytes = z_bytes (Script_timestamp.to_zint timestamp) in + atomic_step_cost + (cost_N_ISub_timestamp_seconds timestamp_bytes seconds_bytes) + + let diff_timestamps t1 t2 = + let t1_bytes = z_bytes (Script_timestamp.to_zint t1) in + let t2_bytes = z_bytes (Script_timestamp.to_zint t2) in + atomic_step_cost (cost_N_IDiff_timestamps t1_bytes t2_bytes) + + let concat_string_pair s1 s2 = + atomic_step_cost + (cost_N_IConcat_string_pair + (Script_string.length s1) + (Script_string.length s2)) + + let slice_string s = + atomic_step_cost (cost_N_ISlice_string (Script_string.length s)) + + let string_size = atomic_step_cost cost_N_IString_size + + let concat_bytes_pair b1 b2 = + atomic_step_cost + (cost_N_IConcat_bytes_pair (Bytes.length b1) (Bytes.length b2)) + + let slice_bytes b = atomic_step_cost (cost_N_ISlice_bytes (Bytes.length b)) + + let bytes_size = atomic_step_cost cost_N_IBytes_size + + let lsl_bytes input nbits = + match Script_int.to_int nbits with + | None -> Saturation_repr.saturated + | Some nbits -> + atomic_step_cost (cost_N_ILsl_bytes (Bytes.length input) nbits) + + let lsr_bytes input nbits = + let input_nbytes = Bytes.length input in + let nbits = + Option.value (Script_int.to_int nbits) ~default:(input_nbytes * 8) + in + atomic_step_cost (cost_N_ILsr_bytes input_nbytes nbits) + + let or_bytes b1 b2 = + atomic_step_cost (cost_N_IOr_bytes (Bytes.length b1) (Bytes.length b2)) + + let and_bytes b1 b2 = + atomic_step_cost (cost_N_IAnd_bytes (Bytes.length b1) (Bytes.length b2)) + + let xor_bytes b1 b2 = + atomic_step_cost (cost_N_IXor_bytes (Bytes.length b1) (Bytes.length b2)) + + let not_bytes b = atomic_step_cost (cost_N_INot_bytes (Bytes.length b)) + + let bytes_nat n = atomic_step_cost (cost_N_IBytes_nat (int_size_in_bytes n)) + + let nat_bytes b = atomic_step_cost (cost_N_INat_bytes (Bytes.length b)) + + let bytes_int n = atomic_step_cost (cost_N_IBytes_int (int_size_in_bytes n)) + + let int_bytes b = atomic_step_cost (cost_N_IInt_bytes (Bytes.length b)) + + let add_tez = atomic_step_cost cost_N_IAdd_tez + + let sub_tez = atomic_step_cost cost_N_ISub_tez + + let sub_tez_legacy = atomic_step_cost cost_N_ISub_tez_legacy + + let mul_teznat = atomic_step_cost cost_N_IMul_teznat + + let mul_nattez = atomic_step_cost cost_N_IMul_nattez + + let bool_or = atomic_step_cost cost_N_IOr + + let bool_and = atomic_step_cost cost_N_IAnd + + let bool_xor = atomic_step_cost cost_N_IXor + + let bool_not = atomic_step_cost cost_N_INot + + let is_nat = atomic_step_cost cost_N_IIs_nat + + let abs_int i = atomic_step_cost (cost_N_IAbs_int (int_size_in_bytes i)) + + let int_nat = atomic_step_cost cost_N_IInt_nat + + let neg i = atomic_step_cost (cost_N_INeg (int_size_in_bytes i)) + + let add_int i1 i2 = + atomic_step_cost + (cost_N_IAdd_int (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let add_nat i1 i2 = + atomic_step_cost + (cost_N_IAdd_nat (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let sub_int i1 i2 = + atomic_step_cost + (cost_N_ISub_int (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let mul_int i1 i2 = + atomic_step_cost + (cost_N_IMul_int (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let mul_nat i1 i2 = + atomic_step_cost + (cost_N_IMul_nat (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let ediv_teznat _tez _n = atomic_step_cost cost_N_IEdiv_teznat + + let ediv_tez = atomic_step_cost cost_N_IEdiv_tez + + let ediv_int i1 i2 = + atomic_step_cost + (cost_N_IEdiv_int (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let ediv_nat i1 i2 = + atomic_step_cost + (cost_N_IEdiv_nat (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let eq = atomic_step_cost cost_N_IEq + + let lsl_nat shifted = + atomic_step_cost (cost_N_ILsl_nat (int_size_in_bytes shifted)) + + let lsr_nat shifted = + atomic_step_cost (cost_N_ILsr_nat (int_size_in_bytes shifted)) + + let or_nat n1 n2 = + atomic_step_cost + (cost_N_IOr_nat (int_size_in_bytes n1) (int_size_in_bytes n2)) + + let and_nat n1 n2 = + atomic_step_cost + (cost_N_IAnd_nat (int_size_in_bytes n1) (int_size_in_bytes n2)) + + let and_int_nat n1 n2 = + atomic_step_cost + (cost_N_IAnd_int_nat (int_size_in_bytes n1) (int_size_in_bytes n2)) + + let xor_nat n1 n2 = + atomic_step_cost + (cost_N_IXor_nat (int_size_in_bytes n1) (int_size_in_bytes n2)) + + let not_int i = atomic_step_cost (cost_N_INot_int (int_size_in_bytes i)) + + let if_ = atomic_step_cost cost_N_IIf + + let loop = atomic_step_cost cost_N_ILoop + + let loop_left = atomic_step_cost cost_N_ILoop_left + + let dip = atomic_step_cost cost_N_IDip + + let view = atomic_step_cost cost_N_IView + + type algo = Ed25519 | Secp256k1 | P256 | Bls + + let algo_of_public_key (pkey : Signature.public_key) = + match pkey with + | Ed25519 _ -> Ed25519 + | Secp256k1 _ -> Secp256k1 + | P256 _ -> P256 + | Bls _ -> Bls + + let algo_of_public_key_hash (pkh : Signature.public_key_hash) = + match pkh with + | Ed25519 _ -> Ed25519 + | Secp256k1 _ -> Secp256k1 + | P256 _ -> P256 + | Bls _ -> Bls + + let check_signature_on_algo algo length = + match algo with + | Ed25519 -> cost_N_ICheck_signature_ed25519 length + | Secp256k1 -> cost_N_ICheck_signature_secp256k1 length + | P256 -> cost_N_ICheck_signature_p256 length + | Bls -> cost_N_ICheck_signature_bls length + + let check_signature pkey b = + check_signature_on_algo (algo_of_public_key pkey) (Bytes.length b) + + let blake2b b = atomic_step_cost (cost_N_IBlake2b (Bytes.length b)) + + let sha256 b = atomic_step_cost (cost_N_ISha256 (Bytes.length b)) + + let sha512 b = atomic_step_cost (cost_N_ISha512 (Bytes.length b)) + + let dign n = atomic_step_cost (cost_N_IDig n) + + let dugn n = atomic_step_cost (cost_N_IDug n) + + let dipn n = atomic_step_cost (cost_N_IDipN n) + + let dropn n = atomic_step_cost (cost_N_IDropN n) + + let voting_power = atomic_step_cost cost_N_IVoting_power + + let total_voting_power = atomic_step_cost cost_N_ITotal_voting_power + + let keccak b = atomic_step_cost (cost_N_IKeccak (Bytes.length b)) + + let sha3 b = atomic_step_cost (cost_N_ISha3 (Bytes.length b)) + + let add_bls12_381_g1 = atomic_step_cost cost_N_IAdd_bls12_381_g1 + + let add_bls12_381_g2 = atomic_step_cost cost_N_IAdd_bls12_381_g2 + + let add_bls12_381_fr = atomic_step_cost cost_N_IAdd_bls12_381_fr + + let mul_bls12_381_g1 = atomic_step_cost cost_N_IMul_bls12_381_g1 + + let mul_bls12_381_g2 = atomic_step_cost cost_N_IMul_bls12_381_g2 + + let mul_bls12_381_fr = atomic_step_cost cost_N_IMul_bls12_381_fr + + let mul_bls12_381_fr_z z = + atomic_step_cost (cost_N_IMul_bls12_381_fr_z (int_size_in_bytes z)) + + let mul_bls12_381_z_fr z = + atomic_step_cost (cost_N_IMul_bls12_381_z_fr (int_size_in_bytes z)) + + let int_bls12_381_fr = atomic_step_cost cost_N_IInt_bls12_381_z_fr + + let neg_bls12_381_g1 = atomic_step_cost cost_N_INeg_bls12_381_g1 + + let neg_bls12_381_g2 = atomic_step_cost cost_N_INeg_bls12_381_g2 + + let neg_bls12_381_fr = atomic_step_cost cost_N_INeg_bls12_381_fr + + let neq = atomic_step_cost cost_N_INeq + + let pairing_check_bls12_381 (l : 'a Script_list.t) = + atomic_step_cost (cost_N_IPairing_check_bls12_381 l.length) + + let comb n = atomic_step_cost (cost_N_IComb n) + + let uncomb n = atomic_step_cost (cost_N_IUncomb n) + + let comb_get n = atomic_step_cost (cost_N_IComb_get n) + + let comb_set n = atomic_step_cost (cost_N_IComb_set n) + + let dupn n = atomic_step_cost (cost_N_IDupN n) + + let sapling_verify_update ~inputs ~outputs ~bound_data = + atomic_step_cost + (cost_N_ISapling_verify_update_with_blake2b inputs outputs bound_data) + + let sapling_verify_update_deprecated ~inputs ~outputs = + atomic_step_cost + (cost_N_ISapling_verify_update_with_blake2b inputs outputs 0) + + let sapling_empty_state = atomic_step_cost cost_N_ISapling_empty_state + + let halt = atomic_step_cost cost_N_IHalt + + let push = atomic_step_cost cost_N_IPush + + let unit = atomic_step_cost cost_N_IUnit + + let empty_big_map = atomic_step_cost cost_N_IEmpty_big_map + + let lt = atomic_step_cost cost_N_ILt + + let le = atomic_step_cost cost_N_ILe + + let gt = atomic_step_cost cost_N_IGt + + let ge = atomic_step_cost cost_N_IGe + + let exec = atomic_step_cost cost_N_IExec + + let apply ~(rec_flag : bool) = atomic_step_cost (cost_N_IApply rec_flag) + + let lambda = atomic_step_cost cost_N_ILambda + + let address = atomic_step_cost cost_N_IAddress + + let contract = atomic_step_cost cost_N_IContract + + let transfer_tokens = atomic_step_cost cost_N_ITransfer_tokens + + let implicit_account = atomic_step_cost cost_N_IImplicit_account + + let create_contract = atomic_step_cost cost_N_ICreate_contract + + let set_delegate = atomic_step_cost cost_N_ISet_delegate + + let level = atomic_step_cost cost_N_ILevel + + let now = atomic_step_cost cost_N_INow + + let min_block_time = atomic_step_cost cost_N_IMin_block_time + + let source = atomic_step_cost cost_N_ISource + + let sender = atomic_step_cost cost_N_ISender + + let self = atomic_step_cost cost_N_ISelf + + let self_address = atomic_step_cost cost_N_ISelf_address + + let amount = atomic_step_cost cost_N_IAmount + + let balance = atomic_step_cost cost_N_IBalance + + let chain_id = atomic_step_cost cost_N_IChainId + + let ticket = atomic_step_cost cost_N_ITicket + + let read_ticket = atomic_step_cost cost_N_IRead_ticket + + let hash_key _ = atomic_step_cost cost_N_IHash_key + + let split_ticket amount_a amount_b = + atomic_step_cost + (cost_N_ISplit_ticket + (int_size_in_bytes amount_a) + (int_size_in_bytes amount_b)) + + let open_chest ~chest ~time = + let plaintext = + Script_typed_ir.Script_timelock.get_plaintext_size chest + in + let log_time = Z.log2 Z.(add one time) in + atomic_step_cost (cost_N_IOpen_chest log_time plaintext) + + (* --------------------------------------------------------------------- *) + (* Semi-hand-crafted models *) + + let compare_unit = atomic_step_cost (S.safe_int 10) + + let compare_pair_tag = atomic_step_cost (S.safe_int 10) + + let compare_or_tag = atomic_step_cost (S.safe_int 10) + + let compare_option_tag = atomic_step_cost (S.safe_int 10) + + let compare_bool = atomic_step_cost (cost_N_ICompare 1 1) + + let compare_signature = atomic_step_cost (S.safe_int 92) + + let compare_string s1 s2 = + atomic_step_cost + (cost_N_ICompare (Script_string.length s1) (Script_string.length s2)) + + let compare_bytes b1 b2 = + atomic_step_cost (cost_N_ICompare (Bytes.length b1) (Bytes.length b2)) + + let compare_mutez = atomic_step_cost (cost_N_ICompare 8 8) + + let compare_int i1 i2 = + atomic_step_cost + (cost_N_ICompare (int_size_in_bytes i1) (int_size_in_bytes i2)) + + let compare_nat n1 n2 = + atomic_step_cost + (cost_N_ICompare (int_size_in_bytes n1) (int_size_in_bytes n2)) + + let compare_key_hash = + let sz = Signature.Public_key_hash.size in + atomic_step_cost (cost_N_ICompare sz sz) + + let compare_key = atomic_step_cost (S.safe_int 92) + + let compare_timestamp t1 t2 = + atomic_step_cost + (cost_N_ICompare + (z_bytes (Script_timestamp.to_zint t1)) + (z_bytes (Script_timestamp.to_zint t2))) + + (* Maximum size of an entrypoint in bytes *) + let entrypoint_size = 31 + + let compare_address = + let sz = Signature.Public_key_hash.size + entrypoint_size in + atomic_step_cost (cost_N_ICompare sz sz) + + let compare_chain_id = atomic_step_cost (S.safe_int 30) + + (* Defunctionalized CPS *) + type cont = + | Compare : 'a Script_typed_ir.comparable_ty * 'a * 'a * cont -> cont + | Return : cont + + let compare : type a. a Script_typed_ir.comparable_ty -> a -> a -> cost = + fun ty x y -> + let rec compare : + type a. + a Script_typed_ir.comparable_ty -> a -> a -> cost -> cont -> cost = + fun ty x y acc k -> + match ty with + | Unit_t -> (apply [@tailcall]) Gas.(acc +@ compare_unit) k + | Never_t -> ( match x with _ -> .) + | Bool_t -> (apply [@tailcall]) Gas.(acc +@ compare_bool) k + | String_t -> (apply [@tailcall]) Gas.(acc +@ compare_string x y) k + | Signature_t -> (apply [@tailcall]) Gas.(acc +@ compare_signature) k + | Bytes_t -> (apply [@tailcall]) Gas.(acc +@ compare_bytes x y) k + | Mutez_t -> (apply [@tailcall]) Gas.(acc +@ compare_mutez) k + | Int_t -> (apply [@tailcall]) Gas.(acc +@ compare_int x y) k + | Nat_t -> (apply [@tailcall]) Gas.(acc +@ compare_nat x y) k + | Key_hash_t -> (apply [@tailcall]) Gas.(acc +@ compare_key_hash) k + | Key_t -> (apply [@tailcall]) Gas.(acc +@ compare_key) k + | Timestamp_t -> + (apply [@tailcall]) Gas.(acc +@ compare_timestamp x y) k + | Address_t -> (apply [@tailcall]) Gas.(acc +@ compare_address) k + | Chain_id_t -> (apply [@tailcall]) Gas.(acc +@ compare_chain_id) k + | Pair_t (tl, tr, _, YesYes) -> + (* Reasonable over-approximation of the cost of lexicographic comparison. *) + let xl, xr = x in + let yl, yr = y in + (compare [@tailcall]) + tl + xl + yl + Gas.(acc +@ compare_pair_tag) + (Compare (tr, xr, yr, k)) + | Or_t (tl, tr, _, YesYes) -> ( + match (x, y) with + | L x, L y -> + (compare [@tailcall]) tl x y Gas.(acc +@ compare_or_tag) k + | L _, R _ -> (apply [@tailcall]) Gas.(acc +@ compare_or_tag) k + | R _, L _ -> (apply [@tailcall]) Gas.(acc +@ compare_or_tag) k + | R x, R y -> + (compare [@tailcall]) tr x y Gas.(acc +@ compare_or_tag) k) + | Option_t (t, _, Yes) -> ( + match (x, y) with + | None, None -> + (apply [@tailcall]) Gas.(acc +@ compare_option_tag) k + | None, Some _ -> + (apply [@tailcall]) Gas.(acc +@ compare_option_tag) k + | Some _, None -> + (apply [@tailcall]) Gas.(acc +@ compare_option_tag) k + | Some x, Some y -> + (compare [@tailcall]) t x y Gas.(acc +@ compare_option_tag) k) + and apply cost k = + match k with + | Compare (ty, x, y, k) -> (compare [@tailcall]) ty x y cost k + | Return -> cost + in + compare ty x y Gas.free Return + + let set_mem (type a) (elt : a) (set : a Script_typed_ir.set) = + let (module Box) = Script_set.get set in + let per_elt_cost = Box.OPS.elt_size elt |> Size.to_int in + Michelson_v1_gas_costs.cost_N_ISet_mem per_elt_cost Box.size + + let set_update (type a) (elt : a) (set : a Script_typed_ir.set) = + let (module Box) = Script_set.get set in + let per_elt_cost = Box.OPS.elt_size elt |> Size.to_int in + Michelson_v1_gas_costs.cost_N_ISet_update per_elt_cost Box.size + + let map_mem (type k v) (elt : k) (map : (k, v) Script_typed_ir.map) = + let (module Box) = Script_map.get_module map in + let per_elt_cost = Box.OPS.key_size elt in + Michelson_v1_gas_costs.cost_N_IMap_mem per_elt_cost Box.size + + let map_get = map_mem + + let map_update (type k v) (elt : k) (map : (k, v) Script_typed_ir.map) = + let (module Box) = Script_map.get_module map in + let per_elt_cost = Box.OPS.key_size elt in + Michelson_v1_gas_costs.cost_N_IMap_update per_elt_cost Box.size + + let map_get_and_update (type k v) (elt : k) + (map : (k, v) Script_typed_ir.map) = + let (module Box) = Script_map.get_module map in + let per_elt_cost = Box.OPS.key_size elt in + Michelson_v1_gas_costs.cost_N_IMap_get_and_update per_elt_cost Box.size + + let view_get (elt : Script_string.t) (m : Script_typed_ir.view_map) = + map_get elt m + + let view_update (elt : Script_string.t) (m : Script_typed_ir.view_map) = + map_update elt m + + let join_tickets : + 'a Script_typed_ir.comparable_ty -> + 'a Script_typed_ir.ticket -> + 'a Script_typed_ir.ticket -> + Gas.cost = + fun ty ticket_a ticket_b -> + let contents_comparison = + compare ty ticket_a.contents ticket_b.contents + in + Gas.( + contents_comparison +@ compare_address + +@ add_nat + (ticket_a.amount :> Script_int.n Script_int.num) + (ticket_b.amount :> Script_int.n Script_int.num)) + + let emit = atomic_step_cost cost_N_IEmit + + (* Continuations *) + module Control = struct + let nil = atomic_step_cost cost_N_KNil + + let cons = atomic_step_cost cost_N_KCons + + let return = atomic_step_cost cost_N_KReturn + + let view_exit = atomic_step_cost cost_N_KView_exit + + let map_head = atomic_step_cost cost_N_KMap_head + + let undip = atomic_step_cost cost_N_KUndip + + let loop_in = atomic_step_cost cost_N_KLoop_in + + let loop_in_left = atomic_step_cost cost_N_KLoop_in_left + + let iter = atomic_step_cost cost_N_KIter + + let list_enter_body xs ys_len = + atomic_step_cost (cost_N_KList_enter_body xs ys_len) + + let list_exit_body = atomic_step_cost cost_N_KList_exit_body + + let map_enter_body (type k v) (map : (k, v) Script_typed_ir.map) = + let (module Box) = Script_map.get_module map in + atomic_step_cost (cost_N_KMap_enter_body Box.size) + + let map_exit_body (type k v) (key : k) (map : (k, v) Script_typed_ir.map) + = + map_update key map + end + + let concat_string_precheck (l : 'a Script_list.t) = + atomic_step_cost (cost_N_IConcat_string_precheck l.length) + + let concat_string total_bytes = + atomic_step_cost (cost_N_IConcat_string total_bytes) + + let concat_bytes total_bytes = + atomic_step_cost (cost_N_IConcat_bytes total_bytes) + + let unpack bytes = + let blen = Bytes.length bytes in + atomic_step_cost (cost_N_IUnpack blen) + + (* TODO benchmark *) + (* FIXME: imported from 006, needs proper benchmarks *) + let unpack_failed bytes = + (* We cannot instrument failed deserialization, + so we take worst case fees: a set of size 1 bytes values. *) + let blen = String.length bytes in + let len = S.safe_int blen in + let d = Z.numbits (Z.of_int blen) in + (len *@ alloc_mbytes_cost 1) + +@ len + *@ (S.safe_int d *@ (alloc_cost (S.safe_int 3) +@ step_cost S.one)) + end + + module Typechecking = struct + open Michelson_v1_gas_costs + + let public_key_optimized = + atomic_step_cost + @@ S.( + max + cost_DECODING_PUBLIC_KEY_ed25519 + (max + cost_DECODING_PUBLIC_KEY_secp256k1 + (max cost_DECODING_PUBLIC_KEY_p256 cost_DECODING_PUBLIC_KEY_bls))) + + let public_key_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_DECODING_PUBLIC_KEY_ed25519 + (max + cost_B58CHECK_DECODING_PUBLIC_KEY_secp256k1 + (max + cost_B58CHECK_DECODING_PUBLIC_KEY_p256 + cost_B58CHECK_DECODING_PUBLIC_KEY_bls))) + + let key_hash_optimized = + atomic_step_cost + @@ S.( + max + cost_DECODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_DECODING_PUBLIC_KEY_HASH_secp256k1 + (max + cost_DECODING_PUBLIC_KEY_HASH_p256 + cost_DECODING_PUBLIC_KEY_HASH_bls))) + + let key_hash_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1 + (max + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_p256 + cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_bls))) + + let signature_optimized = + atomic_step_cost + @@ S.( + max + cost_DECODING_SIGNATURE_ed25519 + (max + cost_DECODING_SIGNATURE_secp256k1 + (max cost_DECODING_SIGNATURE_p256 cost_DECODING_SIGNATURE_bls))) + + let signature_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_DECODING_SIGNATURE_ed25519 + (max + cost_B58CHECK_DECODING_SIGNATURE_secp256k1 + (max + cost_B58CHECK_DECODING_SIGNATURE_p256 + cost_B58CHECK_DECODING_SIGNATURE_bls))) + + let chain_id_optimized = atomic_step_cost cost_DECODING_CHAIN_ID + + let chain_id_readable = atomic_step_cost cost_B58CHECK_DECODING_CHAIN_ID + + (* Reasonable approximation *) + let address_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_readable = key_hash_readable + + let bls12_381_g1 = atomic_step_cost cost_DECODING_BLS_G1 + + let bls12_381_g2 = atomic_step_cost cost_DECODING_BLS_G2 + + let bls12_381_fr = atomic_step_cost cost_DECODING_BLS_FR + + let check_printable s = + atomic_step_cost (cost_CHECK_PRINTABLE (String.length s)) + + let ty_eq ty1 ty2 = + (* Assumes O(1) access to the size of a type *) + let size1 = Script_typed_ir.(ty_size ty1 |> Type_size.to_int) in + let size2 = Script_typed_ir.(ty_size ty2 |> Type_size.to_int) in + atomic_step_cost (cost_TY_EQ (Saturation_repr.min size1 size2)) + + (* The gas cost for comparing a type with a type of size 1 *) + let ty_eq_prim = atomic_step_cost (cost_TY_EQ (Saturation_repr.safe_int 1)) + + let parse_type_cycle = atomic_step_cost cost_PARSE_TYPE1 + + let parse_instr_cycle = atomic_step_cost cost_TYPECHECKING_CODE + + let parse_data_cycle = atomic_step_cost cost_TYPECHECKING_DATA + + (* Cost of a cycle of checking that a type is dupable *) + (* TODO: bench *) + let check_dupable_cycle = atomic_step_cost cost_TYPECHECKING_DATA + + let find_entrypoint_cycle = atomic_step_cost cost_FIND_ENTRYPOINT + + let bool = free + + let unit = free + + let timestamp_readable s = + atomic_step_cost (cost_TIMESTAMP_READABLE_DECODING (String.length s)) + + (* Balance stored at /contracts/index/hash/balance, on 64 bits *) + let contract_exists = + Gas.cost_of_repr @@ Storage_costs.read_access ~path_length:4 ~read_bytes:8 + + (* Constructing proof arguments consists in a decreasing loop in the result + monad, allocating at each step. We charge a reasonable overapproximation. *) + let proof_argument n = + atomic_step_cost (S.mul (S.safe_int n) (S.safe_int 50)) + + let chest_key = atomic_step_cost cost_DECODING_Chest_key + + let chest ~bytes = atomic_step_cost (cost_DECODING_Chest bytes) + end + + module Unparsing = struct + open Michelson_v1_gas_costs + + let public_key_optimized = + atomic_step_cost + @@ S.( + max + cost_ENCODING_PUBLIC_KEY_ed25519 + (max + cost_ENCODING_PUBLIC_KEY_secp256k1 + (max cost_ENCODING_PUBLIC_KEY_p256 cost_ENCODING_PUBLIC_KEY_bls))) + + let public_key_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_ENCODING_PUBLIC_KEY_ed25519 + (max + cost_B58CHECK_ENCODING_PUBLIC_KEY_secp256k1 + (max + cost_B58CHECK_ENCODING_PUBLIC_KEY_p256 + cost_B58CHECK_ENCODING_PUBLIC_KEY_bls))) + + let key_hash_optimized = + atomic_step_cost + @@ S.( + max + cost_ENCODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_ENCODING_PUBLIC_KEY_HASH_secp256k1 + (max + cost_ENCODING_PUBLIC_KEY_HASH_p256 + cost_ENCODING_PUBLIC_KEY_HASH_bls))) + + let key_hash_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519 + (max + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1 + (max + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256 + cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_bls))) + + let signature_optimized = + atomic_step_cost + @@ S.( + max + cost_ENCODING_SIGNATURE_ed25519 + (max + cost_ENCODING_SIGNATURE_secp256k1 + (max cost_ENCODING_SIGNATURE_p256 cost_ENCODING_SIGNATURE_bls))) + + let signature_readable = + atomic_step_cost + @@ S.( + max + cost_B58CHECK_ENCODING_SIGNATURE_ed25519 + (max + cost_B58CHECK_ENCODING_SIGNATURE_secp256k1 + (max + cost_B58CHECK_ENCODING_SIGNATURE_p256 + cost_B58CHECK_ENCODING_SIGNATURE_bls))) + + let chain_id_optimized = atomic_step_cost cost_ENCODING_CHAIN_ID + + let chain_id_readable = atomic_step_cost cost_B58CHECK_ENCODING_CHAIN_ID + + let timestamp_readable = atomic_step_cost cost_TIMESTAMP_READABLE_ENCODING + + (* Reasonable approximation *) + let address_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_optimized = key_hash_optimized + + (* Reasonable approximation *) + let contract_readable = key_hash_readable + + let bls12_381_g1 = atomic_step_cost cost_ENCODING_BLS_G1 + + let bls12_381_g2 = atomic_step_cost cost_ENCODING_BLS_G2 + + let bls12_381_fr = atomic_step_cost cost_ENCODING_BLS_FR + + let unparse_type ty = + atomic_step_cost @@ cost_UNPARSE_TYPE + @@ Script_typed_ir.(Type_size.to_int @@ ty_size ty) + + let unparse_instr_cycle = atomic_step_cost cost_UNPARSING_CODE + + let unparse_data_cycle = atomic_step_cost cost_UNPARSING_DATA + + let unit = Gas.free + + (* Reuse 006 costs. *) + let operation bytes = Script.bytes_node_cost bytes + + let sapling_transaction (t : Sapling.transaction) = + let inputs = Size.sapling_transaction_inputs t in + let outputs = Size.sapling_transaction_outputs t in + let bound_data = Size.sapling_transaction_bound_data t in + atomic_step_cost + (cost_SAPLING_TRANSACTION_ENCODING ~inputs ~outputs ~bound_data) + + let sapling_transaction_deprecated (t : Sapling.Legacy.transaction) = + let inputs = List.length t.inputs in + let outputs = List.length t.outputs in + atomic_step_cost + (cost_SAPLING_TRANSACTION_ENCODING ~inputs ~outputs ~bound_data:0) + + let sapling_diff (d : Sapling.diff) = + let nfs = List.length d.nullifiers in + let cms = List.length d.commitments_and_ciphertexts in + atomic_step_cost (cost_SAPLING_DIFF_ENCODING ~nfs ~cms) + + let chest_key = atomic_step_cost cost_ENCODING_Chest_key + + let chest ~plaintext_size = + atomic_step_cost (cost_ENCODING_Chest plaintext_size) + end +end + +module Internal_for_tests = struct + let int_cost_of_manager_operation = Cost_of.manager_operation_int +end diff --git a/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.mli b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.mli new file mode 100644 index 000000000000..8f64123e310c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas.mli @@ -0,0 +1,550 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides the gas costs for typechecking Michelson scripts, + parsing and unparsing Michelson values, and interpreting Michelson + instructions. +*) + +open Alpha_context + +module Cost_of : sig + (* The [manager_operation] cost is consumed each time a manager + operation (internal or external alike) is applied. This cost is + meant to cover the resources used in {!Apply} either directly + (dispatching on operation kinds) or indirectly (in particular in + the production of operation results). *) + val manager_operation : Gas.cost + + module Interpreter : sig + val drop : Gas.cost + + val dup : Gas.cost + + val swap : Gas.cost + + val cons_some : Gas.cost + + val cons_none : Gas.cost + + val if_none : Gas.cost + + val opt_map : Gas.cost + + val cons_pair : Gas.cost + + val unpair : Gas.cost + + val car : Gas.cost + + val cdr : Gas.cost + + val cons_left : Gas.cost + + val cons_right : Gas.cost + + val if_left : Gas.cost + + val cons_list : Gas.cost + + val nil : Gas.cost + + val if_cons : Gas.cost + + (* The argument of this function is ignored when calculating gas cost. *) + val list_map : 'a Script_list.t -> Gas.cost + + val list_size : Gas.cost + + (* The argument of this function is ignored when calculating gas cost. *) + val list_iter : 'a Script_list.t -> Gas.cost + + val empty_set : Gas.cost + + val set_iter : 'a Script_typed_ir.set -> Gas.cost + + val set_mem : 'a -> 'a Script_typed_ir.set -> Gas.cost + + val set_update : 'a -> 'a Script_typed_ir.set -> Gas.cost + + val set_size : Gas.cost + + val empty_map : Gas.cost + + val map_map : ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_iter : ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_mem : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_get : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_update : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_get_and_update : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + + val big_map_mem : (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val big_map_get : (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val big_map_update : (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val big_map_get_and_update : + (_, _) Script_typed_ir.big_map_overlay -> Gas.cost + + val map_size : Gas.cost + + val add_seconds_timestamp : + 'a Script_int.num -> Script_timestamp.t -> Gas.cost + + val add_timestamp_seconds : + Script_timestamp.t -> 'a Script_int.num -> Gas.cost + + val sub_timestamp_seconds : + Script_timestamp.t -> 'a Script_int.num -> Gas.cost + + val diff_timestamps : Script_timestamp.t -> Script_timestamp.t -> Gas.cost + + val concat_string_pair : Script_string.t -> Script_string.t -> Gas.cost + + val slice_string : Script_string.t -> Gas.cost + + val string_size : Gas.cost + + val concat_bytes_pair : bytes -> bytes -> Gas.cost + + val slice_bytes : bytes -> Gas.cost + + val bytes_size : Gas.cost + + val bytes_nat : Script_int.n Script_int.num -> Gas.cost + + val nat_bytes : bytes -> Gas.cost + + val bytes_int : Script_int.z Script_int.num -> Gas.cost + + val int_bytes : bytes -> Gas.cost + + val add_tez : Gas.cost + + val sub_tez : Gas.cost + + val sub_tez_legacy : Gas.cost + + val mul_teznat : Gas.cost + + val mul_nattez : Gas.cost + + val bool_or : Gas.cost + + val bool_and : Gas.cost + + val bool_xor : Gas.cost + + val bool_not : Gas.cost + + val is_nat : Gas.cost + + val abs_int : Script_int.z Script_int.num -> Gas.cost + + val int_nat : Gas.cost + + val neg : 'a Script_int.num -> Gas.cost + + val add_int : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val add_nat : + Script_int.n Script_int.num -> Script_int.n Script_int.num -> Gas.cost + + val sub_int : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val mul_int : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val mul_nat : Script_int.n Script_int.num -> 'a Script_int.num -> Gas.cost + + val ediv_teznat : 'a -> 'b Script_int.num -> Gas.cost + + val ediv_tez : Gas.cost + + val ediv_int : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val ediv_nat : Script_int.n Script_int.num -> 'a Script_int.num -> Gas.cost + + val eq : Gas.cost + + val lsl_nat : 'a Script_int.num -> Gas.cost + + val lsr_nat : 'a Script_int.num -> Gas.cost + + val lsl_bytes : bytes -> Script_int.n Script_int.num -> Gas.cost + + val lsr_bytes : bytes -> Script_int.n Script_int.num -> Gas.cost + + val or_nat : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val or_bytes : bytes -> bytes -> Gas.cost + + val and_nat : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val and_int_nat : + Script_int.z Script_int.num -> Script_int.n Script_int.num -> Gas.cost + + val and_bytes : bytes -> bytes -> Gas.cost + + val xor_nat : 'a Script_int.num -> 'b Script_int.num -> Gas.cost + + val xor_bytes : bytes -> bytes -> Gas.cost + + val not_int : 'a Script_int.num -> Gas.cost + + val not_bytes : bytes -> Gas.cost + + val if_ : Gas.cost + + val loop : Gas.cost + + val loop_left : Gas.cost + + val dip : Gas.cost + + type algo = Ed25519 | Secp256k1 | P256 | Bls + + val algo_of_public_key : Signature.public_key -> algo + + val algo_of_public_key_hash : Signature.public_key_hash -> algo + + val check_signature_on_algo : algo -> int -> Gas.cost + + val check_signature : Signature.public_key -> bytes -> Gas.cost + + val blake2b : bytes -> Gas.cost + + val sha256 : bytes -> Gas.cost + + val sha512 : bytes -> Gas.cost + + val dign : int -> Gas.cost + + val dugn : int -> Gas.cost + + val dipn : int -> Gas.cost + + val dropn : int -> Gas.cost + + val voting_power : Gas.cost + + val total_voting_power : Gas.cost + + val keccak : bytes -> Gas.cost + + val sha3 : bytes -> Gas.cost + + val add_bls12_381_g1 : Gas.cost + + val add_bls12_381_g2 : Gas.cost + + val add_bls12_381_fr : Gas.cost + + val mul_bls12_381_g1 : Gas.cost + + val mul_bls12_381_g2 : Gas.cost + + val mul_bls12_381_fr : Gas.cost + + val mul_bls12_381_fr_z : 'a Script_int.num -> Gas.cost + + val mul_bls12_381_z_fr : 'a Script_int.num -> Gas.cost + + val int_bls12_381_fr : Gas.cost + + val neg_bls12_381_g1 : Gas.cost + + val neg_bls12_381_g2 : Gas.cost + + val neg_bls12_381_fr : Gas.cost + + val neq : Gas.cost + + val pairing_check_bls12_381 : 'a Script_list.t -> Gas.cost + + val comb : int -> Gas.cost + + val uncomb : int -> Gas.cost + + val comb_get : int -> Gas.cost + + val comb_set : int -> Gas.cost + + val dupn : int -> Gas.cost + + val compare : 'a Script_typed_ir.comparable_ty -> 'a -> 'a -> Gas.cost + + val concat_string_precheck : 'a Script_list.t -> Gas.cost + + val concat_string : + Saturation_repr.may_saturate Saturation_repr.t -> Gas.cost + + val concat_bytes : + Saturation_repr.may_saturate Saturation_repr.t -> Gas.cost + + val halt : Gas.cost + + val push : Gas.cost + + val unit : Gas.cost + + val empty_big_map : Gas.cost + + val lt : Gas.cost + + val le : Gas.cost + + val gt : Gas.cost + + val ge : Gas.cost + + val exec : Gas.cost + + val apply : rec_flag:bool -> Gas.cost + + val lambda : Gas.cost + + val address : Gas.cost + + val contract : Gas.cost + + val view : Gas.cost + + val view_get : Script_string.t -> Script_typed_ir.view_map -> Gas.cost + + val view_update : Script_string.t -> Script_typed_ir.view_map -> Gas.cost + + val transfer_tokens : Gas.cost + + val implicit_account : Gas.cost + + val create_contract : Gas.cost + + val set_delegate : Gas.cost + + val balance : Gas.cost + + val level : Gas.cost + + val now : Gas.cost + + val min_block_time : Gas.cost + + val hash_key : Signature.Public_key.t -> Gas.cost + + val source : Gas.cost + + val sender : Gas.cost + + val self : Gas.cost + + val self_address : Gas.cost + + val amount : Gas.cost + + val chain_id : Gas.cost + + val unpack : bytes -> Gas.cost + + val unpack_failed : string -> Gas.cost + + val sapling_empty_state : Gas.cost + + val sapling_verify_update : + inputs:int -> outputs:int -> bound_data:int -> Gas.cost + + val sapling_verify_update_deprecated : inputs:int -> outputs:int -> Gas.cost + + val ticket : Gas.cost + + val read_ticket : Gas.cost + + val split_ticket : 'a Script_int.num -> 'a Script_int.num -> Gas.cost + + val join_tickets : + 'a Script_typed_ir.comparable_ty -> + 'a Script_typed_ir.ticket -> + 'a Script_typed_ir.ticket -> + Gas.cost + + val open_chest : + chest:Script_typed_ir.Script_timelock.chest -> time:Z.t -> Gas.cost + + (** cost to generate one event emission internal operation *) + val emit : Gas.cost + + module Control : sig + val nil : Gas.cost + + val cons : Gas.cost + + val return : Gas.cost + + val view_exit : Gas.cost + + val map_head : Gas.cost + + val undip : Gas.cost + + val loop_in : Gas.cost + + val loop_in_left : Gas.cost + + val iter : Gas.cost + + val list_enter_body : 'a list -> int -> Gas.cost + + val list_exit_body : Gas.cost + + val map_enter_body : ('k, 'v) Script_typed_ir.map -> Gas.cost + + val map_exit_body : 'k -> ('k, 'v) Script_typed_ir.map -> Gas.cost + end + end + + module Typechecking : sig + val public_key_optimized : Gas.cost + + val public_key_readable : Gas.cost + + val key_hash_optimized : Gas.cost + + val key_hash_readable : Gas.cost + + val signature_optimized : Gas.cost + + val signature_readable : Gas.cost + + val chain_id_optimized : Gas.cost + + val chain_id_readable : Gas.cost + + val address_optimized : Gas.cost + + val contract_optimized : Gas.cost + + val contract_readable : Gas.cost + + val bls12_381_g1 : Gas.cost + + val bls12_381_g2 : Gas.cost + + val bls12_381_fr : Gas.cost + + val check_printable : string -> Gas.cost + + val ty_eq : _ Script_typed_ir.ty -> _ Script_typed_ir.ty -> Gas.cost + + val ty_eq_prim : Gas.cost + + val parse_type_cycle : Gas.cost + + val parse_instr_cycle : Gas.cost + + val parse_data_cycle : Gas.cost + + val check_dupable_cycle : Gas.cost + + val find_entrypoint_cycle : Gas.cost + + val bool : Gas.cost + + val unit : Gas.cost + + val timestamp_readable : string -> Gas.cost + + val contract_exists : Gas.cost + + val proof_argument : int -> Gas.cost + + val chest_key : Gas.cost + + val chest : bytes:int -> Gas.cost + end + + module Unparsing : sig + val public_key_optimized : Gas.cost + + val public_key_readable : Gas.cost + + val key_hash_optimized : Gas.cost + + val key_hash_readable : Gas.cost + + val signature_optimized : Gas.cost + + val signature_readable : Gas.cost + + val chain_id_optimized : Gas.cost + + val chain_id_readable : Gas.cost + + val timestamp_readable : Gas.cost + + val address_optimized : Gas.cost + + val contract_optimized : Gas.cost + + val contract_readable : Gas.cost + + val bls12_381_g1 : Gas.cost + + val bls12_381_g2 : Gas.cost + + val bls12_381_fr : Gas.cost + + val unparse_type : ('a, _) Script_typed_ir.ty -> Gas.cost + + val unparse_instr_cycle : Gas.cost + + val unparse_data_cycle : Gas.cost + + val unit : Gas.cost + + val operation : bytes -> Gas.cost + + val sapling_transaction : Sapling.transaction -> Gas.cost + + val sapling_transaction_deprecated : Sapling.Legacy.transaction -> Gas.cost + + val sapling_diff : Sapling.diff -> Gas.cost + + val chest_key : Gas.cost + + val chest : plaintext_size:int -> Gas.cost + end +end + +module Internal_for_tests : sig + (** [int] value of {!Cost_of.manager_operation} *) + val int_cost_of_manager_operation : int +end diff --git a/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs.ml b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs.ml new file mode 100644 index 000000000000..fc383be25ba6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs.ml @@ -0,0 +1,216 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022-2023 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Michelson_v1_gas_costs_generated +module S = Saturation_repr + +(** Hand-edited/written cost functions *) + +(* Functions to be replaced by the generated code. + + The codegen cannot generate exactly the same code here. They have to + be replaced by the generated versions. +*) + +(* generated code is not usable: the const is not on a grid point *) +(* model N_ILsl_nat *) +(* Allocates at most [size + 256] bytes *) +let cost_N_ILsl_nat size = + let open S.Syntax in + let v0 = S.safe_int size in + S.safe_int 128 + (v0 lsr 1) + +(* generated code is not usable: the actual code and the model differ *) +(* model N_ILsl_bytes *) +(* Allocates [size + shift / 8] bytes *) +(* fun size1 -> fun size2 -> ((63.0681507316 + (0.667539714647 * size1)) + (0. * size2)) *) +let cost_N_ILsl_bytes size shift = + let open S.Syntax in + let v1 = S.safe_int size in + let v0 = S.safe_int shift in + S.safe_int 65 + (v1 lsr 1) + (v1 lsr 2) + (v0 lsr 4) + +(* ------------------------------------------------------------------------ *) + +(* N_ISapling_verify_update_with_blake2b + This function depends on another cost function cost_N_IBlake2b. + Such code can't be generated by the current Snoop. *) +let cost_N_ISapling_verify_update_with_blake2b size1 size2 bound_data = + let open S.Syntax in + cost_N_IBlake2b bound_data + cost_N_ISapling_verify_update size1 size2 + +(* N_IApply + The current generated model receives int as a flag, + but it should receive bool. *) +(* model N_IApply *) +(* fun size -> if (size = 0) then 140 else 220 *) +let cost_N_IApply rec_flag = if rec_flag then S.safe_int 220 else S.safe_int 140 + +(* N_KMap_enter_body + Removed conversion of [size] for optimization *) +(* model N_KMap_enter_body *) +let cost_N_KMap_enter_body size = + if Compare.Int.(size = 0) then S.safe_int 10 else S.safe_int 80 + +(* N_KList_enter_body + The generated model receives the length of `xs` as the first argument + and branches on whether it is 0 or not. + However, calculating the length makes the performance worse. + The model should be changed to receive `xs_is_nil` as the first argument. *) +(* model N_KList_enter_body *) +(* Approximating 1.797068 x term *) +let cost_N_KList_enter_body xs size_ys = + match xs with + | [] -> + let open S.Syntax in + let v0 = S.safe_int size_ys in + S.safe_int 30 + (v0 + (v0 lsr 1) + (v0 lsr 2) + (v0 lsr 4)) + | _ :: _ -> S.safe_int 30 + +(* model PARSE_TYPE + This is the cost of one iteration of parse_ty, extracted by hand from the + parameter fit for the PARSE_TYPE benchmark. *) +let cost_PARSE_TYPE1 = cost_PARSE_TYPE 1 + +(* model TYPECHECKING_CODE + This is the cost of one iteration of parse_instr, extracted by hand from the + parameter fit for the TYPECHECKING_CODE benchmark. *) +let cost_TYPECHECKING_CODE = S.safe_int 220 + +(* model UNPARSING_CODE + This is the cost of one iteration of unparse_instr, extracted by hand from the + parameter fit for the UNPARSING_CODE benchmark. *) +let cost_UNPARSING_CODE = S.safe_int 115 + +(* model TYPECHECKING_DATA + This is the cost of one iteration of parse_data, extracted by hand from the + parameter fit for the TYPECHECKING_DATA benchmark. *) +let cost_TYPECHECKING_DATA = S.safe_int 100 + +(* model UNPARSING_DATA + This is the cost of one iteration of unparse_data, extracted by hand from the + parameter fit for the UNPARSING_DATA benchmark. *) +let cost_UNPARSING_DATA = S.safe_int 65 + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2264 + Benchmark. + Currently approximated by 2 comparisons of the longest entrypoint. *) +let cost_FIND_ENTRYPOINT = cost_N_ICompare 31 31 + +(* ------------------------------------------------------------------------ *) + +(* These functions lack the corresponding models. *) + +(* model SAPLING_TRANSACTION_ENCODING *) +let cost_SAPLING_TRANSACTION_ENCODING ~inputs ~outputs ~bound_data = + S.safe_int (1500 + (inputs * 160) + (outputs * 320) + (bound_data lsr 3)) + +(* model SAPLING_DIFF_ENCODING *) +let cost_SAPLING_DIFF_ENCODING ~nfs ~cms = S.safe_int ((nfs * 22) + (cms * 215)) + +(* ------------------------------------------------------------------------ *) + +(* IDropN and IDupN use non affine models with multiple cases. The inferred + cost functions are more complex than the following affine functions. *) + +(* model N_IDropN *) +(* Approximating 2.713108 x term *) +let cost_N_IDropN size = + let open S.Syntax in + let v0 = S.safe_int size in + S.safe_int 30 + (S.safe_int 2 * v0) + (v0 lsr 1) + (v0 lsr 3) + +(* model N_IDupN *) +(* Approximating 1.222263 x term *) +let cost_N_IDupN size = + let open S.Syntax in + let v0 = S.safe_int size in + S.safe_int 20 + v0 + (v0 lsr 2) + +(* ------------------------------------------------------------------------ *) + +(* Following functions are partially carbonated: they charge some gas + by themselves. Their inferred gas parameters cannot be directly + used since they should contain the partial carbonation. +*) + +(* model N_IContract *) +(* Inferred value: 703.26072741 *) +(* Most computation happens in [parse_contract_for_script], which is + carbonated. *) +let cost_N_IContract = S.safe_int 30 + +(* model N_ICreate_contract *) +(* Inferred value: 814.154060743 *) +(* Most computation happens in [create_contract], which is carbonated. *) +let cost_N_ICreate_contract = S.safe_int 60 + +(* model N_ITransfer_tokens *) +(* Inferred value: 230.707394077 *) +(* Most computation happens in [transfer], which is carbonated. *) +let cost_N_ITransfer_tokens = S.safe_int 60 + +(* model IEmit *) +(* Inferred value: 244.687394077 *) +(* Most computation happens in [emit_event], which is carbonated. *) +let cost_N_IEmit = S.safe_int 30 + +(* --------------------------------------------------------------------- *) + +(* The cost functions below where not benchmarked, a cost model was derived + from looking at similar instructions. *) +(* Cost for Concat_string is paid in two steps: when entering the interpreter, + the user pays for the cost of computing the information necessary to compute + the actual gas (so it's meta-gas): indeed, one needs to run through the + list of strings to compute the total allocated cost. + [concat_string_precheck] corresponds to the meta-gas cost of this computation. +*) + +let cost_N_IConcat_string_precheck length = + (* we set the precheck to be slightly more expensive than cost_N_IList_iter *) + let open S.Syntax in + let length = S.safe_int length in + length * S.safe_int 10 + +(* This is the cost of allocating a string and blitting existing ones into it. *) +let cost_N_IConcat_string total_bytes = + let open S.Syntax in + S.safe_int 100 + (total_bytes lsr 1) + +(* Same story as Concat_string. *) +let cost_N_IConcat_bytes total_bytes = + let open S.Syntax in + S.safe_int 100 + (total_bytes lsr 1) + +(* A partially carbonated instruction, + so its model does not correspond to this function *) +(* Cost of Unpack pays two integer comparisons, and a Bytes slice *) +let cost_N_IUnpack total_bytes = + let open S.Syntax in + let total_bytes = S.safe_int total_bytes in + S.safe_int 260 + (total_bytes lsr 1) diff --git a/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs_generated.ml new file mode 100644 index 000000000000..a64681951e44 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/michelson_v1_gas_costs_generated.ml @@ -0,0 +1,3722 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model encoding/B58CHECK_DECODING_CHAIN_ID *) +(* max 10 1600. *) +let cost_B58CHECK_DECODING_CHAIN_ID = S.safe_int 1600 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_bls *) +(* max 10 3600. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_bls = S.safe_int 3600 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519 *) +(* max 10 3300. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 3300 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_p256 *) +(* max 10 3300. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_p256 = S.safe_int 3300 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1 *) +(* max 10 3300. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 3300 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_bls *) +(* max 10 79000. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_bls = S.safe_int 79000 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_ed25519 *) +(* max 10 4200. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_ed25519 = S.safe_int 4200 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_p256 *) +(* max 10 13450. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_p256 = S.safe_int 13450 + +(* model encoding/B58CHECK_DECODING_PUBLIC_KEY_secp256k1 *) +(* max 10 9000. *) +let cost_B58CHECK_DECODING_PUBLIC_KEY_secp256k1 = S.safe_int 9000 + +(* model encoding/B58CHECK_DECODING_SIGNATURE_bls *) +(* max 10 6400. *) +let cost_B58CHECK_DECODING_SIGNATURE_bls = S.safe_int 6400 + +(* model encoding/B58CHECK_DECODING_SIGNATURE_ed25519 *) +(* max 10 6400. *) +let cost_B58CHECK_DECODING_SIGNATURE_ed25519 = S.safe_int 6400 + +(* model encoding/B58CHECK_DECODING_SIGNATURE_p256 *) +(* max 10 6400. *) +let cost_B58CHECK_DECODING_SIGNATURE_p256 = S.safe_int 6400 + +(* model encoding/B58CHECK_DECODING_SIGNATURE_secp256k1 *) +(* max 10 6400. *) +let cost_B58CHECK_DECODING_SIGNATURE_secp256k1 = S.safe_int 6400 + +(* model encoding/B58CHECK_ENCODING_CHAIN_ID *) +(* max 10 1800. *) +let cost_B58CHECK_ENCODING_CHAIN_ID = S.safe_int 1800 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_bls *) +(* max 10 3200. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_bls = S.safe_int 3200 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519 *) +(* max 10 3200. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 3200 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256 *) +(* max 10 3200. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_p256 = S.safe_int 3200 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1 *) +(* max 10 3200. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 3200 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_bls *) +(* max 10 5900. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_bls = S.safe_int 5900 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_ed25519 *) +(* max 10 4500. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_ed25519 = S.safe_int 4500 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_p256 *) +(* max 10 4550. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_p256 = S.safe_int 4550 + +(* model encoding/B58CHECK_ENCODING_PUBLIC_KEY_secp256k1 *) +(* max 10 4950. *) +let cost_B58CHECK_ENCODING_PUBLIC_KEY_secp256k1 = S.safe_int 4950 + +(* model encoding/B58CHECK_ENCODING_SIGNATURE_bls *) +(* max 10 8300. *) +let cost_B58CHECK_ENCODING_SIGNATURE_bls = S.safe_int 8300 + +(* model encoding/B58CHECK_ENCODING_SIGNATURE_ed25519 *) +(* max 10 8300. *) +let cost_B58CHECK_ENCODING_SIGNATURE_ed25519 = S.safe_int 8300 + +(* model encoding/B58CHECK_ENCODING_SIGNATURE_p256 *) +(* max 10 8300. *) +let cost_B58CHECK_ENCODING_SIGNATURE_p256 = S.safe_int 8300 + +(* model encoding/B58CHECK_ENCODING_SIGNATURE_secp256k1 *) +(* max 10 8300. *) +let cost_B58CHECK_ENCODING_SIGNATURE_secp256k1 = S.safe_int 8300 + +(* model encoding/BLS_FR_FROM_Z *) +(* max 10 178.443333333 *) +let cost_BLS_FR_FROM_Z = S.safe_int 180 + +(* model encoding/BLS_FR_TO_Z *) +(* max 10 82.8933333333 *) +let cost_BLS_FR_TO_Z = S.safe_int 85 + +(* model encoding/CHECK_PRINTABLE *) +(* fun size -> max 10 (14. + (10. * size)) *) +let cost_CHECK_PRINTABLE size = + let size = S.safe_int size in + (size * S.safe_int 10) + S.safe_int 15 + +(* model encoding/DECODING_BLS_FR *) +(* max 10 120. *) +let cost_DECODING_BLS_FR = S.safe_int 120 + +(* model encoding/DECODING_BLS_G1 *) +(* max 10 54600. *) +let cost_DECODING_BLS_G1 = S.safe_int 54600 + +(* model encoding/DECODING_BLS_G2 *) +(* max 10 69000. *) +let cost_DECODING_BLS_G2 = S.safe_int 69000 + +(* model encoding/DECODING_CHAIN_ID *) +(* max 10 50. *) +let cost_DECODING_CHAIN_ID = S.safe_int 50 + +(* model encoding/DECODING_Chest *) +(* fun size -> max 10 (3750. + (0.03125 * size)) *) +let cost_DECODING_Chest size = + let size = S.safe_int size in + (size lsr 5) + S.safe_int 3750 + +(* model encoding/DECODING_Chest_key *) +(* max 10 9550. *) +let cost_DECODING_Chest_key = S.safe_int 9550 + +(* model encoding/DECODING_PUBLIC_KEY_HASH_bls *) +(* max 10 60. *) +let cost_DECODING_PUBLIC_KEY_HASH_bls = S.safe_int 60 + +(* model encoding/DECODING_PUBLIC_KEY_HASH_ed25519 *) +(* max 10 60. *) +let cost_DECODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 60 + +(* model encoding/DECODING_PUBLIC_KEY_HASH_p256 *) +(* max 10 60. *) +let cost_DECODING_PUBLIC_KEY_HASH_p256 = S.safe_int 60 + +(* model encoding/DECODING_PUBLIC_KEY_HASH_secp256k1 *) +(* max 10 60. *) +let cost_DECODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 60 + +(* model encoding/DECODING_PUBLIC_KEY_bls *) +(* max 10 74000. *) +let cost_DECODING_PUBLIC_KEY_bls = S.safe_int 74000 + +(* model encoding/DECODING_PUBLIC_KEY_ed25519 *) +(* max 10 60. *) +let cost_DECODING_PUBLIC_KEY_ed25519 = S.safe_int 60 + +(* model encoding/DECODING_PUBLIC_KEY_p256 *) +(* max 10 9550. *) +let cost_DECODING_PUBLIC_KEY_p256 = S.safe_int 9550 + +(* model encoding/DECODING_PUBLIC_KEY_secp256k1 *) +(* max 10 4900. *) +let cost_DECODING_PUBLIC_KEY_secp256k1 = S.safe_int 4900 + +(* model encoding/DECODING_SIGNATURE_bls *) +(* max 10 40. *) +let cost_DECODING_SIGNATURE_bls = S.safe_int 40 + +(* model encoding/DECODING_SIGNATURE_ed25519 *) +(* max 10 35. *) +let cost_DECODING_SIGNATURE_ed25519 = S.safe_int 35 + +(* model encoding/DECODING_SIGNATURE_p256 *) +(* max 10 35. *) +let cost_DECODING_SIGNATURE_p256 = S.safe_int 35 + +(* model encoding/DECODING_SIGNATURE_secp256k1 *) +(* max 10 35. *) +let cost_DECODING_SIGNATURE_secp256k1 = S.safe_int 35 + +(* model encoding/ENCODING_BLS_FR *) +(* max 10 80. *) +let cost_ENCODING_BLS_FR = S.safe_int 80 + +(* model encoding/ENCODING_BLS_G1 *) +(* max 10 3200. *) +let cost_ENCODING_BLS_G1 = S.safe_int 3200 + +(* model encoding/ENCODING_BLS_G2 *) +(* max 10 3900. *) +let cost_ENCODING_BLS_G2 = S.safe_int 3900 + +(* model encoding/ENCODING_CHAIN_ID *) +(* max 10 50. *) +let cost_ENCODING_CHAIN_ID = S.safe_int 50 + +(* model encoding/ENCODING_Chest *) +(* fun size -> max 10 (6250. + (0.09375 * size)) *) +let cost_ENCODING_Chest size = + let size = S.safe_int size in + (size lsr 4) + (size lsr 5) + S.safe_int 6250 + +(* model encoding/ENCODING_Chest_key *) +(* max 10 15900. *) +let cost_ENCODING_Chest_key = S.safe_int 15900 + +(* model encoding/ENCODING_PUBLIC_KEY_HASH_bls *) +(* max 10 80. *) +let cost_ENCODING_PUBLIC_KEY_HASH_bls = S.safe_int 80 + +(* model encoding/ENCODING_PUBLIC_KEY_HASH_ed25519 *) +(* max 10 70. *) +let cost_ENCODING_PUBLIC_KEY_HASH_ed25519 = S.safe_int 70 + +(* model encoding/ENCODING_PUBLIC_KEY_HASH_p256 *) +(* max 10 70. *) +let cost_ENCODING_PUBLIC_KEY_HASH_p256 = S.safe_int 70 + +(* model encoding/ENCODING_PUBLIC_KEY_HASH_secp256k1 *) +(* max 10 70. *) +let cost_ENCODING_PUBLIC_KEY_HASH_secp256k1 = S.safe_int 70 + +(* model encoding/ENCODING_PUBLIC_KEY_bls *) +(* max 10 90. *) +let cost_ENCODING_PUBLIC_KEY_bls = S.safe_int 90 + +(* model encoding/ENCODING_PUBLIC_KEY_ed25519 *) +(* max 10 80. *) +let cost_ENCODING_PUBLIC_KEY_ed25519 = S.safe_int 80 + +(* model encoding/ENCODING_PUBLIC_KEY_p256 *) +(* max 10 90. *) +let cost_ENCODING_PUBLIC_KEY_p256 = S.safe_int 90 + +(* model encoding/ENCODING_PUBLIC_KEY_secp256k1 *) +(* max 10 455. *) +let cost_ENCODING_PUBLIC_KEY_secp256k1 = S.safe_int 455 + +(* model encoding/ENCODING_SIGNATURE_bls *) +(* max 10 55. *) +let cost_ENCODING_SIGNATURE_bls = S.safe_int 55 + +(* model encoding/ENCODING_SIGNATURE_ed25519 *) +(* max 10 45. *) +let cost_ENCODING_SIGNATURE_ed25519 = S.safe_int 45 + +(* model encoding/ENCODING_SIGNATURE_p256 *) +(* max 10 45. *) +let cost_ENCODING_SIGNATURE_p256 = S.safe_int 45 + +(* model encoding/ENCODING_SIGNATURE_secp256k1 *) +(* max 10 45. *) +let cost_ENCODING_SIGNATURE_secp256k1 = S.safe_int 45 + +(* model encoding/TIMESTAMP_READABLE_DECODING *) +(* fun size -> max 10 (105. + (0.046875 * (size * (sqrt size)))) *) +let cost_TIMESTAMP_READABLE_DECODING size = + let size = S.safe_int size in + let w2 = sqrt size * size in + (w2 lsr 5) + (w2 lsr 6) + S.safe_int 105 + +(* model encoding/TIMESTAMP_READABLE_ENCODING *) +(* max 10 820. *) +let cost_TIMESTAMP_READABLE_ENCODING = S.safe_int 820 + +(* model interpreter/N_IAbs_int *) +(* fun size -> max 10 (20. + (0.5 * size)) *) +let cost_N_IAbs_int size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 20 + +(* model interpreter/N_IAbs_int_alloc *) +(* fun size -> max 10 (14.9523489645 + (0.50021084529 * size)) *) +let cost_N_IAbs_int_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 15 + +(* model interpreter/N_IAbs_int_synthesized *) +(* fun size -> + let time = 20. + (0.5 * size) in + let alloc = 14.9523489645 + (0.50021084529 * size) in + max 10 (max time alloc) *) +let cost_N_IAbs_int_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 20) (w1 + (size lsr 6) + S.safe_int 15) + +(* model interpreter/N_IAdd_bls12_381_fr *) +(* max 10 30. *) +let cost_N_IAdd_bls12_381_fr = S.safe_int 30 + +(* model interpreter/N_IAdd_bls12_381_fr_alloc *) +(* max 10 24. *) +let cost_N_IAdd_bls12_381_fr_alloc = S.safe_int 25 + +(* model interpreter/N_IAdd_bls12_381_fr_synthesized *) +(* let time = 30. in let alloc = 24. in max 10 (max time alloc) *) +let cost_N_IAdd_bls12_381_fr_synthesized = S.safe_int 30 + +(* model interpreter/N_IAdd_bls12_381_g1 *) +(* max 10 900. *) +let cost_N_IAdd_bls12_381_g1 = S.safe_int 900 + +(* model interpreter/N_IAdd_bls12_381_g1_alloc *) +(* max 10 80. *) +let cost_N_IAdd_bls12_381_g1_alloc = S.safe_int 80 + +(* model interpreter/N_IAdd_bls12_381_g1_synthesized *) +(* let time = 900. in let alloc = 80. in max 10 (max time alloc) *) +let cost_N_IAdd_bls12_381_g1_synthesized = S.safe_int 900 + +(* model interpreter/N_IAdd_bls12_381_g2 *) +(* max 10 2470. *) +let cost_N_IAdd_bls12_381_g2 = S.safe_int 2470 + +(* model interpreter/N_IAdd_bls12_381_g2_alloc *) +(* max 10 152. *) +let cost_N_IAdd_bls12_381_g2_alloc = S.safe_int 155 + +(* model interpreter/N_IAdd_bls12_381_g2_synthesized *) +(* let time = 2470. in let alloc = 152. in max 10 (max time alloc) *) +let cost_N_IAdd_bls12_381_g2_synthesized = S.safe_int 2470 + +(* model interpreter/N_IAdd_int *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IAdd_int size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAdd_int_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (16.6371367954 + (0.500211859928 * (max size1 size2))) *) +let cost_N_IAdd_int_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IAdd_int_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 16.6371367954 + (0.500211859928 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IAdd_int_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IAdd_nat *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IAdd_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAdd_nat_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (17.7896408261 + (0.500239743224 * (max size1 size2))) *) +let cost_N_IAdd_nat_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IAdd_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 17.7896408261 + (0.500239743224 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IAdd_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IAdd_seconds_to_timestamp *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IAdd_seconds_to_timestamp size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAdd_seconds_to_timestamp_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (16.6371367954 + (0.500211859928 * (max size1 size2))) *) +let cost_N_IAdd_seconds_to_timestamp_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IAdd_seconds_to_timestamp_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 16.6371367954 + (0.500211859928 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IAdd_seconds_to_timestamp_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IAdd_tez *) +(* max 10 20. *) +let cost_N_IAdd_tez = S.safe_int 20 + +(* model interpreter/N_IAdd_tez_alloc *) +(* max 10 12. *) +let cost_N_IAdd_tez_alloc = S.safe_int 15 + +(* model interpreter/N_IAdd_tez_synthesized *) +(* let time = 20. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IAdd_tez_synthesized = S.safe_int 20 + +(* model interpreter/N_IAdd_timestamp_to_seconds *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IAdd_timestamp_to_seconds size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAdd_timestamp_to_seconds_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (16.6371367954 + (0.500211859928 * (max size1 size2))) *) +let cost_N_IAdd_timestamp_to_seconds_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IAdd_timestamp_to_seconds_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 16.6371367954 + (0.500211859928 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IAdd_timestamp_to_seconds_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IAddress *) +(* max 10 10. *) +let cost_N_IAddress = S.safe_int 10 + +(* model interpreter/N_IAddress_alloc *) +(* max 10 28. *) +let cost_N_IAddress_alloc = S.safe_int 30 + +(* model interpreter/N_IAddress_synthesized *) +(* let time = 10. in let alloc = 28. in max 10 (max time alloc) *) +let cost_N_IAddress_synthesized = S.safe_int 30 + +(* model interpreter/N_IAmount *) +(* max 10 10. *) +let cost_N_IAmount = S.safe_int 10 + +(* model interpreter/N_IAmount_alloc *) +(* max 10 12. *) +let cost_N_IAmount_alloc = S.safe_int 15 + +(* model interpreter/N_IAmount_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IAmount_synthesized = S.safe_int 15 + +(* model interpreter/N_IAnd *) +(* max 10 10. *) +let cost_N_IAnd = S.safe_int 10 + +(* model interpreter/N_IAnd_alloc *) +(* max 10 0. *) +let cost_N_IAnd_alloc = S.safe_int 10 + +(* model interpreter/N_IAnd_bytes *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (min size1 size2))) *) +let cost_N_IAnd_bytes size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.min size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAnd_bytes_alloc *) +(* fun size1 -> + fun size2 -> max 10 (11.02845262 + (0.499972333803 * (min size1 size2))) *) +let cost_N_IAnd_bytes_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.min size1 size2 lsr 1) + S.safe_int 15 + +(* model interpreter/N_IAnd_bytes_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (min size1 size2)) in + let alloc = 11.02845262 + (0.499972333803 * (min size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IAnd_bytes_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.min size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAnd_int_nat *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (min size1 size2))) *) +let cost_N_IAnd_int_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.min size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAnd_int_nat_alloc *) +(* fun size1 -> + fun size2 -> max 10 (15.9658045767 + (0.500213721396 * size2)) *) +let cost_N_IAnd_int_nat_alloc _size1 size2 = + let size2 = S.safe_int size2 in + (size2 lsr 1) + (size2 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IAnd_int_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (min size1 size2)) in + let alloc = 15.9658045767 + (0.500213721396 * size2) in + max 10 (max time alloc) *) +let cost_N_IAnd_int_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + S.max + ((S.min size1 size2 lsr 1) + S.safe_int 35) + ((size2 lsr 1) + (size2 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IAnd_nat *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (min size1 size2))) *) +let cost_N_IAnd_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.min size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IAnd_nat_alloc *) +(* fun size1 -> + fun size2 -> max 10 (15.929319772 + (0.50029450095 * (min size1 size2))) *) +let cost_N_IAnd_nat_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.min size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IAnd_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (min size1 size2)) in + let alloc = 15.929319772 + (0.50029450095 * (min size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IAnd_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.min size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IAnd_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IAnd_synthesized = S.safe_int 10 + +(* model interpreter/N_IApply_alloc *) +(* fun size -> max 10 (if size = 0 then 225.986577181 else 510.013245033) *) +let cost_N_IApply_alloc size = + let size = S.safe_int size in + S.max + (S.safe_int 10) + (if size = S.safe_int 0 then S.safe_int 230 else S.safe_int 510) + +(* model interpreter/N_IApply_synthesized *) +(* fun size -> + let time = if size = 0 then 140. else 220. in + let alloc = if size = 0 then 225.986577181 else 510.013245033 in + max 10 (max time alloc) *) +let cost_N_IApply_synthesized size = + let size = S.safe_int size in + let w1 = size = S.safe_int 0 in + S.max + (S.max (S.safe_int 10) (if w1 then S.safe_int 140 else S.safe_int 220)) + (if w1 then S.safe_int 230 else S.safe_int 510) + +(* model interpreter/N_IBalance *) +(* max 10 10. *) +let cost_N_IBalance = S.safe_int 10 + +(* model interpreter/N_IBalance_alloc *) +(* max 10 12. *) +let cost_N_IBalance_alloc = S.safe_int 15 + +(* model interpreter/N_IBalance_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IBalance_synthesized = S.safe_int 15 + +(* model interpreter/N_IBig_map_get *) +(* fun size1 -> + fun size2 -> + max 10 + (822.930542675 + (2.84341564432 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IBig_map_get size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 * S.safe_int 2) + (w3 lsr 1) + (w3 lsr 2) + (w3 lsr 3) + S.safe_int 825 + +(* model interpreter/N_IBig_map_get_alloc *) +(* fun size1 -> fun size2 -> max 10 0. *) +let cost_N_IBig_map_get_alloc _size1 _size2 = S.safe_int 10 + +(* model interpreter/N_IBig_map_get_and_update *) +(* fun size1 -> + fun size2 -> + max 10 + (834.633876008 + (2.84264684858 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IBig_map_get_and_update size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 * S.safe_int 2) + (w3 lsr 1) + (w3 lsr 2) + (w3 lsr 3) + S.safe_int 835 + +(* model interpreter/N_IBig_map_get_and_update_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((25.084669453 * (log2 (1 + size2))) + 178.035218425) *) +let cost_N_IBig_map_get_and_update_alloc _size1 size2 = + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + (w1 * S.safe_int 25) + (w1 lsr 1) + S.safe_int 180 + +(* model interpreter/N_IBig_map_get_and_update_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + 834.633876008 + (2.84264684858 * (size1 * (log2 (1 + size2)))) in + let alloc = (25.084669453 * (log2 (1 + size2))) + 178.035218425 in + max 10 (max time alloc) *) +let cost_N_IBig_map_get_and_update_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + let w3 = w1 * size1 in + S.max + ((w3 * S.safe_int 2) + (w3 lsr 1) + (w3 lsr 2) + (w3 lsr 3) + S.safe_int 835) + ((w1 * S.safe_int 25) + (w1 lsr 1) + S.safe_int 180) + +(* model interpreter/N_IBig_map_get_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + 822.930542675 + (2.84341564432 * (size1 * (log2 (1 + size2)))) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IBig_map_get_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 * S.safe_int 2) + (w3 lsr 1) + (w3 lsr 2) + (w3 lsr 3) + S.safe_int 825 + +(* model interpreter/N_IBig_map_mem *) +(* fun size1 -> + fun size2 -> + max 10 (824.703876008 + (2.8436528598 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IBig_map_mem size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 * S.safe_int 2) + (w3 lsr 1) + (w3 lsr 2) + (w3 lsr 3) + S.safe_int 825 + +(* model interpreter/N_IBig_map_mem_alloc *) +(* fun size1 -> fun size2 -> max 10 0. *) +let cost_N_IBig_map_mem_alloc _size1 _size2 = S.safe_int 10 + +(* model interpreter/N_IBig_map_mem_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + 824.703876008 + (2.8436528598 * (size1 * (log2 (1 + size2)))) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IBig_map_mem_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 * S.safe_int 2) + (w3 lsr 1) + (w3 lsr 2) + (w3 lsr 3) + S.safe_int 825 + +(* model interpreter/N_IBig_map_update *) +(* fun size1 -> + fun size2 -> + max 10 + (816.020542675 + (3.16181279998 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IBig_map_update size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 * S.safe_int 3) + (w3 lsr 3) + (w3 lsr 4) + S.safe_int 820 + +(* model interpreter/N_IBig_map_update_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((25.084669453 * (log2 (1 + size2))) + 166.035218425) *) +let cost_N_IBig_map_update_alloc _size1 size2 = + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + (w1 * S.safe_int 25) + (w1 lsr 1) + S.safe_int 170 + +(* model interpreter/N_IBig_map_update_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + 816.020542675 + (3.16181279998 * (size1 * (log2 (1 + size2)))) in + let alloc = (25.084669453 * (log2 (1 + size2))) + 166.035218425 in + max 10 (max time alloc) *) +let cost_N_IBig_map_update_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + let w3 = w1 * size1 in + S.max + ((w3 * S.safe_int 3) + (w3 lsr 3) + (w3 lsr 4) + S.safe_int 820) + ((w1 * S.safe_int 25) + (w1 lsr 1) + S.safe_int 170) + +(* model interpreter/N_IBlake2b *) +(* fun size -> max 10 (430. + (1.125 * size)) *) +let cost_N_IBlake2b size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 430 + +(* model interpreter/N_IBlake2b_alloc *) +(* fun size -> max 10 24. *) +let cost_N_IBlake2b_alloc _size = S.safe_int 25 + +(* model interpreter/N_IBlake2b_synthesized *) +(* fun size -> + let time = 430. + (1.125 * size) in + let alloc = 24. in max 10 (max time alloc) *) +let cost_N_IBlake2b_synthesized size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 430 + +(* model interpreter/N_IBytes_int *) +(* fun size -> max 10 (90. + (3. * size)) *) +let cost_N_IBytes_int size = + let size = S.safe_int size in + (size * S.safe_int 3) + S.safe_int 90 + +(* model interpreter/N_IBytes_int_alloc *) +(* fun size -> max 10 (10.3902313247 + (0.499502439767 * size)) *) +let cost_N_IBytes_int_alloc size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 10 + +(* model interpreter/N_IBytes_int_synthesized *) +(* fun size -> + let time = 90. + (3. * size) in + let alloc = 10.3902313247 + (0.499502439767 * size) in + max 10 (max time alloc) *) +let cost_N_IBytes_int_synthesized size = + let size = S.safe_int size in + S.max ((size * S.safe_int 3) + S.safe_int 90) ((size lsr 1) + S.safe_int 10) + +(* model interpreter/N_IBytes_nat *) +(* fun size -> max 10 (75. + (3. * size)) *) +let cost_N_IBytes_nat size = + let size = S.safe_int size in + (size * S.safe_int 3) + S.safe_int 75 + +(* model interpreter/N_IBytes_nat_alloc *) +(* fun size -> max 10 (10.7311846492 + (0.499435286092 * size)) *) +let cost_N_IBytes_nat_alloc size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 15 + +(* model interpreter/N_IBytes_nat_synthesized *) +(* fun size -> + let time = 75. + (3. * size) in + let alloc = 10.7311846492 + (0.499435286092 * size) in + max 10 (max time alloc) *) +let cost_N_IBytes_nat_synthesized size = + let size = S.safe_int size in + S.max ((size * S.safe_int 3) + S.safe_int 75) ((size lsr 1) + S.safe_int 15) + +(* model interpreter/N_IBytes_size *) +(* max 10 10. *) +let cost_N_IBytes_size = S.safe_int 10 + +(* model interpreter/N_IBytes_size_alloc *) +(* max 10 0. *) +let cost_N_IBytes_size_alloc = S.safe_int 10 + +(* model interpreter/N_IBytes_size_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IBytes_size_synthesized = S.safe_int 10 + +(* model interpreter/N_ICar *) +(* max 10 10. *) +let cost_N_ICar = S.safe_int 10 + +(* model interpreter/N_ICar_alloc *) +(* max 10 0. *) +let cost_N_ICar_alloc = S.safe_int 10 + +(* model interpreter/N_ICar_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICar_synthesized = S.safe_int 10 + +(* model interpreter/N_ICdr *) +(* max 10 10. *) +let cost_N_ICdr = S.safe_int 10 + +(* model interpreter/N_ICdr_alloc *) +(* max 10 0. *) +let cost_N_ICdr_alloc = S.safe_int 10 + +(* model interpreter/N_ICdr_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICdr_synthesized = S.safe_int 10 + +(* model interpreter/N_IChainId *) +(* max 10 15. *) +let cost_N_IChainId = S.safe_int 15 + +(* model interpreter/N_IChainId_alloc *) +(* max 10 20. *) +let cost_N_IChainId_alloc = S.safe_int 20 + +(* model interpreter/N_IChainId_synthesized *) +(* let time = 15. in let alloc = 20. in max 10 (max time alloc) *) +let cost_N_IChainId_synthesized = S.safe_int 20 + +(* model interpreter/N_ICheck_signature_bls *) +(* fun size -> max 10 (1570000. + (3. * size)) *) +let cost_N_ICheck_signature_bls size = + let size = S.safe_int size in + (size * S.safe_int 3) + S.safe_int 1570000 + +(* model interpreter/N_ICheck_signature_bls_alloc *) +(* fun size -> max 10 0. *) +let cost_N_ICheck_signature_bls_alloc _size = S.safe_int 10 + +(* model interpreter/N_ICheck_signature_bls_synthesized *) +(* fun size -> + let time = 1570000. + (3. * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICheck_signature_bls_synthesized size = + let size = S.safe_int size in + (size * S.safe_int 3) + S.safe_int 1570000 + +(* model interpreter/N_ICheck_signature_ed25519 *) +(* fun size -> max 10 (65800. + (1.125 * size)) *) +let cost_N_ICheck_signature_ed25519 size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 65800 + +(* model interpreter/N_ICheck_signature_ed25519_alloc *) +(* fun size -> max 10 0. *) +let cost_N_ICheck_signature_ed25519_alloc _size = S.safe_int 10 + +(* model interpreter/N_ICheck_signature_ed25519_synthesized *) +(* fun size -> + let time = 65800. + (1.125 * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICheck_signature_ed25519_synthesized size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 65800 + +(* model interpreter/N_ICheck_signature_p256 *) +(* fun size -> max 10 (341000. + (1.125 * size)) *) +let cost_N_ICheck_signature_p256 size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 341000 + +(* model interpreter/N_ICheck_signature_p256_alloc *) +(* fun size -> max 10 0. *) +let cost_N_ICheck_signature_p256_alloc _size = S.safe_int 10 + +(* model interpreter/N_ICheck_signature_p256_synthesized *) +(* fun size -> + let time = 341000. + (1.125 * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICheck_signature_p256_synthesized size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 341000 + +(* model interpreter/N_ICheck_signature_secp256k1 *) +(* fun size -> max 10 (51600. + (1.125 * size)) *) +let cost_N_ICheck_signature_secp256k1 size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 51600 + +(* model interpreter/N_ICheck_signature_secp256k1_alloc *) +(* fun size -> max 10 0. *) +let cost_N_ICheck_signature_secp256k1_alloc _size = S.safe_int 10 + +(* model interpreter/N_ICheck_signature_secp256k1_synthesized *) +(* fun size -> + let time = 51600. + (1.125 * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICheck_signature_secp256k1_synthesized size = + let size = S.safe_int size in + (size lsr 3) + size + S.safe_int 51600 + +(* model interpreter/N_IComb *) +(* fun size -> max 10 (40. + (3.25 * (sub size 2))) *) +let cost_N_IComb size = + let size = S.safe_int size in + let w1 = S.sub size (S.safe_int 2) in + (w1 * S.safe_int 3) + (w1 lsr 2) + S.safe_int 40 + +(* model interpreter/N_IComb_alloc *) +(* fun size -> max 10 (5.60949553813 + (11.9823552149 * size)) *) +let cost_N_IComb_alloc size = + let size = S.safe_int size in + (size * S.safe_int 12) + S.safe_int 10 + +(* model interpreter/N_IComb_get *) +(* fun size -> max 10 (20. + (0.5625 * size)) *) +let cost_N_IComb_get size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 4) + S.safe_int 20 + +(* model interpreter/N_IComb_get_alloc *) +(* fun size -> max 10 (0. + (0. * size)) *) +let cost_N_IComb_get_alloc _size = S.safe_int 10 + +(* model interpreter/N_IComb_get_synthesized *) +(* fun size -> + let time = 20. + (0.5625 * size) in + let alloc = 0. + (0. * size) in max 10 (max time alloc) *) +let cost_N_IComb_get_synthesized size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 4) + S.safe_int 20 + +(* model interpreter/N_IComb_set *) +(* fun size -> max 10 (30. + (1.28125 * size)) *) +let cost_N_IComb_set size = + let size = S.safe_int size in + (size lsr 2) + (size lsr 5) + size + S.safe_int 30 + +(* model interpreter/N_IComb_set_alloc *) +(* fun size -> max 10 (5.97947366264 + (6.00684211245 * size)) *) +let cost_N_IComb_set_alloc size = + let size = S.safe_int size in + (size lsr 3) + (size * S.safe_int 6) + S.safe_int 10 + +(* model interpreter/N_IComb_set_synthesized *) +(* fun size -> + let time = 30. + (1.28125 * size) in + let alloc = 5.97947366264 + (6.00684211245 * size) in + max 10 (max time alloc) *) +let cost_N_IComb_set_synthesized size = + let size = S.safe_int size in + S.max + ((size lsr 2) + (size lsr 5) + size + S.safe_int 30) + ((size lsr 3) + (size * S.safe_int 6) + S.safe_int 10) + +(* model interpreter/N_IComb_synthesized *) +(* fun size -> + let time = 40. + (3.25 * (sub size 2)) in + let alloc = 5.60949553813 + (11.9823552149 * size) in + max 10 (max time alloc) *) +let cost_N_IComb_synthesized size = + let size = S.safe_int size in + let w1 = S.sub size (S.safe_int 2) in + S.max + ((w1 * S.safe_int 3) + (w1 lsr 2) + S.safe_int 40) + ((size * S.safe_int 12) + S.safe_int 10) + +(* model interpreter/N_ICompare *) +(* fun size1 -> + fun size2 -> max 10 (35. + (0.0234375 * (sub (min size1 size2) 1))) *) +let cost_N_ICompare size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub (S.min size1 size2) (S.safe_int 1) in + (w1 lsr 6) + (w1 lsr 7) + S.safe_int 35 + +(* model interpreter/N_ICompare_alloc *) +(* fun size1 -> fun size2 -> max 10 0. *) +let cost_N_ICompare_alloc _size1 _size2 = S.safe_int 10 + +(* model interpreter/N_ICompare_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.0234375 * (sub (min size1 size2) 1)) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ICompare_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub (S.min size1 size2) (S.safe_int 1) in + (w1 lsr 6) + (w1 lsr 7) + S.safe_int 35 + +(* model interpreter/N_IConcat_bytes_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((8.00002622858 + (0. * size1)) + (0.499999999744 * size2)) *) +let cost_N_IConcat_bytes_alloc _size1 size2 = + let size2 = S.safe_int size2 in + (size2 lsr 1) + S.safe_int 10 + +(* model interpreter/N_IConcat_bytes_pair *) +(* fun size1 -> fun size2 -> max 10 (45. + (0.5 * (size1 + size2))) *) +let cost_N_IConcat_bytes_pair size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + ((size1 + size2) lsr 1) + S.safe_int 45 + +(* model interpreter/N_IConcat_bytes_pair_alloc *) +(* fun size1 -> + fun size2 -> max 10 (8.00048828125 + (0.499999761581 * (size1 + size2))) *) +let cost_N_IConcat_bytes_pair_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + ((size1 + size2) lsr 1) + S.safe_int 10 + +(* model interpreter/N_IConcat_bytes_pair_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 45. + (0.5 * (size1 + size2)) in + let alloc = 8.00048828125 + (0.499999761581 * (size1 + size2)) in + max 10 (max time alloc) *) +let cost_N_IConcat_bytes_pair_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + ((size1 + size2) lsr 1) + S.safe_int 45 + +(* model interpreter/N_IConcat_bytes_synthesized *) +(* fun size1 -> + fun size2 -> + let time = (31.0272093413 + (0. * size1)) + (0.0853190494597 * size2) in + let alloc = (8.00002622858 + (0. * size1)) + (0.499999999744 * size2) in + max 10 (max time alloc) *) +let cost_N_IConcat_bytes_synthesized _size1 size2 = + let size2 = S.safe_int size2 in + S.max + ((size2 lsr 4) + (size2 lsr 6) + (size2 lsr 7) + S.safe_int 35) + ((size2 lsr 1) + S.safe_int 10) + +(* model interpreter/N_IConcat_string_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((6.82629751442 + (0. * size1)) + (0.500114619383 * size2)) *) +let cost_N_IConcat_string_alloc _size1 size2 = + let size2 = S.safe_int size2 in + (size2 lsr 1) + (size2 lsr 6) + S.safe_int 10 + +(* model interpreter/N_IConcat_string_pair *) +(* fun size1 -> fun size2 -> max 10 (45. + (0.5 * (size1 + size2))) *) +let cost_N_IConcat_string_pair size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + ((size1 + size2) lsr 1) + S.safe_int 45 + +(* model interpreter/N_IConcat_string_pair_alloc *) +(* fun size1 -> + fun size2 -> max 10 (8.00048828125 + (0.499999761581 * (size1 + size2))) *) +let cost_N_IConcat_string_pair_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + ((size1 + size2) lsr 1) + S.safe_int 10 + +(* model interpreter/N_IConcat_string_pair_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 45. + (0.5 * (size1 + size2)) in + let alloc = 8.00048828125 + (0.499999761581 * (size1 + size2)) in + max 10 (max time alloc) *) +let cost_N_IConcat_string_pair_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + ((size1 + size2) lsr 1) + S.safe_int 45 + +(* model interpreter/N_IConcat_string_synthesized *) +(* fun size1 -> + fun size2 -> + let time = (33.8372093413 + (0. * size1)) + (0.089723875507 * size2) in + let alloc = (6.82629751442 + (0. * size1)) + (0.500114619383 * size2) in + max 10 (max time alloc) *) +let cost_N_IConcat_string_synthesized _size1 size2 = + let size2 = S.safe_int size2 in + let w1 = size2 lsr 6 in + S.max + ((size2 lsr 4) + w1 + (size2 lsr 7) + (size2 lsr 8) + S.safe_int 35) + ((size2 lsr 1) + w1 + S.safe_int 10) + +(* model interpreter/N_ICons_list *) +(* max 10 10. *) +let cost_N_ICons_list = S.safe_int 10 + +(* model interpreter/N_ICons_list_alloc *) +(* max 10 24. *) +let cost_N_ICons_list_alloc = S.safe_int 25 + +(* model interpreter/N_ICons_list_synthesized *) +(* let time = 10. in let alloc = 24. in max 10 (max time alloc) *) +let cost_N_ICons_list_synthesized = S.safe_int 25 + +(* model interpreter/N_ICons_none *) +(* max 10 10. *) +let cost_N_ICons_none = S.safe_int 10 + +(* model interpreter/N_ICons_none_alloc *) +(* max 10 12. *) +let cost_N_ICons_none_alloc = S.safe_int 15 + +(* model interpreter/N_ICons_none_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_ICons_none_synthesized = S.safe_int 15 + +(* model interpreter/N_ICons_pair *) +(* max 10 10. *) +let cost_N_ICons_pair = S.safe_int 10 + +(* model interpreter/N_ICons_pair_alloc *) +(* max 10 12. *) +let cost_N_ICons_pair_alloc = S.safe_int 15 + +(* model interpreter/N_ICons_pair_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_ICons_pair_synthesized = S.safe_int 15 + +(* model interpreter/N_ICons_some *) +(* max 10 10. *) +let cost_N_ICons_some = S.safe_int 10 + +(* model interpreter/N_ICons_some_alloc *) +(* max 10 8. *) +let cost_N_ICons_some_alloc = S.safe_int 10 + +(* model interpreter/N_ICons_some_synthesized *) +(* let time = 10. in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_ICons_some_synthesized = S.safe_int 10 + +(* model interpreter/N_IContract_alloc *) +(* max 10 16. *) +let cost_N_IContract_alloc = S.safe_int 20 + +(* model interpreter/N_IContract_synthesized *) +(* let time = 30. in let alloc = 16. in max 10 (max time alloc) *) +let cost_N_IContract_synthesized = S.safe_int 30 + +(* model interpreter/N_ICreate_contract_alloc *) +(* max 10 196. *) +let cost_N_ICreate_contract_alloc = S.safe_int 200 + +(* model interpreter/N_ICreate_contract_synthesized *) +(* let time = 60. in let alloc = 196. in max 10 (max time alloc) *) +let cost_N_ICreate_contract_synthesized = S.safe_int 200 + +(* model interpreter/N_IDiff_timestamps *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IDiff_timestamps size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IDiff_timestamps_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (17.5501373306 + (0.500211925836 * (max size1 size2))) *) +let cost_N_IDiff_timestamps_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IDiff_timestamps_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 17.5501373306 + (0.500211925836 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IDiff_timestamps_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IDig *) +(* fun size -> max 10 (30. + (6.75 * size)) *) +let cost_N_IDig size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 2) + (size * S.safe_int 6) + S.safe_int 30 + +(* model interpreter/N_IDig_alloc *) +(* fun size -> max 10 (11.9761359318 + (12.005966017 * size)) *) +let cost_N_IDig_alloc size = + let size = S.safe_int size in + (size lsr 2) + (size * S.safe_int 12) + S.safe_int 15 + +(* model interpreter/N_IDig_synthesized *) +(* fun size -> + let time = 30. + (6.75 * size) in + let alloc = 11.9761359318 + (12.005966017 * size) in + max 10 (max time alloc) *) +let cost_N_IDig_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 2 in + S.max + ((size lsr 1) + w1 + (size * S.safe_int 6) + S.safe_int 30) + (w1 + (size * S.safe_int 12) + S.safe_int 15) + +(* model interpreter/N_IDip *) +(* max 10 10. *) +let cost_N_IDip = S.safe_int 10 + +(* model interpreter/N_IDipN *) +(* fun size -> max 10 (15. + (4. * size)) *) +let cost_N_IDipN size = + let size = S.safe_int size in + (size * S.safe_int 4) + S.safe_int 15 + +(* model interpreter/N_IDipN_alloc *) +(* fun size -> max 10 (0.00283557047624 + (11.9999972146 * size)) *) +let cost_N_IDipN_alloc size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 12) + +(* model interpreter/N_IDipN_synthesized *) +(* fun size -> + let time = 15. + (4. * size) in + let alloc = 0.00283557047624 + (11.9999972146 * size) in + max 10 (max time alloc) *) +let cost_N_IDipN_synthesized size = + let size = S.safe_int size in + S.max ((size * S.safe_int 4) + S.safe_int 15) (size * S.safe_int 12) + +(* model interpreter/N_IDip_alloc *) +(* max 10 0. *) +let cost_N_IDip_alloc = S.safe_int 10 + +(* model interpreter/N_IDip_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IDip_synthesized = S.safe_int 10 + +(* model interpreter/N_IDrop *) +(* max 10 10. *) +let cost_N_IDrop = S.safe_int 10 + +(* model interpreter/N_IDropN_alloc *) +(* fun size -> + max 10 + ((((0. * (min 300 size)) + (0. * (sub (min 400 size) 300))) + + (0. * (sub size 400))) + + 0.) *) +let cost_N_IDropN_alloc _size = S.safe_int 10 + +(* model interpreter/N_IDropN_synthesized *) +(* fun size -> + let time = + (((2.625 * (min 300 size)) + + (8.74162478422 * (sub (min 400 size) 300))) + + (3.26994250393 * (sub size 400))) + + 30. in + let alloc = + (((0. * (min 300 size)) + (0. * (sub (min 400 size) 300))) + + (0. * (sub size 400))) + + 0. in + max 10 (max time alloc) *) +let cost_N_IDropN_synthesized size = + let size = S.safe_int size in + let w2 = S.sub size (S.safe_int 400) in + let w3 = S.min (S.safe_int 300) size in + let w1 = S.sub (S.min (S.safe_int 400) size) (S.safe_int 300) in + (w1 * S.safe_int 8) + + (w2 * S.safe_int 3) + + (w3 * S.safe_int 2) + + (w1 lsr 1) + (w1 lsr 2) + (w2 lsr 2) + (w2 lsr 4) + (w3 lsr 1) + (w3 lsr 3) + + S.safe_int 30 + +(* model interpreter/N_IDrop_alloc *) +(* max 10 0. *) +let cost_N_IDrop_alloc = S.safe_int 10 + +(* model interpreter/N_IDrop_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IDrop_synthesized = S.safe_int 10 + +(* model interpreter/N_IDug *) +(* fun size -> max 10 (35. + (6.75 * size)) *) +let cost_N_IDug size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 2) + (size * S.safe_int 6) + S.safe_int 35 + +(* model interpreter/N_IDug_alloc *) +(* fun size -> max 10 (11.9761359318 + (12.005966017 * size)) *) +let cost_N_IDug_alloc size = + let size = S.safe_int size in + (size lsr 2) + (size * S.safe_int 12) + S.safe_int 15 + +(* model interpreter/N_IDug_synthesized *) +(* fun size -> + let time = 35. + (6.75 * size) in + let alloc = 11.9761359318 + (12.005966017 * size) in + max 10 (max time alloc) *) +let cost_N_IDug_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 2 in + S.max + ((size lsr 1) + w1 + (size * S.safe_int 6) + S.safe_int 35) + (w1 + (size * S.safe_int 12) + S.safe_int 15) + +(* model interpreter/N_IDup *) +(* max 10 10. *) +let cost_N_IDup = S.safe_int 10 + +(* model interpreter/N_IDupN_alloc *) +(* fun size -> + let size = sub size 1 in + max 10 + ((((0. * (min 300 size)) + (0. * (sub (min 400 size) 300))) + + (0. * (sub size 400))) + + 12.) *) +let cost_N_IDupN_alloc _size = S.safe_int 15 + +(* model interpreter/N_IDupN_synthesized *) +(* fun size -> + let time = + let size = sub size 1 in + (((1.25 * (min 300 size)) + (4.8094437716 * (sub (min 400 size) 300))) + + (2.13759591646 * (sub size 400))) + + 20. in + let alloc = + let size = sub size 1 in + (((0. * (min 300 size)) + (0. * (sub (min 400 size) 300))) + + (0. * (sub size 400))) + + 12. in + max 10 (max time alloc) *) +let cost_N_IDupN_synthesized size = + let size = S.safe_int size in + let w3 = S.sub size (S.safe_int 1) in + let w1 = S.sub w3 (S.safe_int 400) in + let w4 = S.min (S.safe_int 300) w3 in + let w2 = S.sub (S.min (S.safe_int 400) w3) (S.safe_int 300) in + (w1 * S.safe_int 2) + + (w2 * S.safe_int 4) + + w4 + (w1 lsr 3) + (w1 lsr 4) + (w2 lsr 1) + (w2 lsr 2) + (w2 lsr 3) + + (w4 lsr 2) + S.safe_int 20 + +(* model interpreter/N_IDup_alloc *) +(* max 10 12. *) +let cost_N_IDup_alloc = S.safe_int 15 + +(* model interpreter/N_IDup_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IDup_synthesized = S.safe_int 15 + +(* model interpreter/N_IEdiv_int *) +(* fun size1 -> + fun size2 -> + let q = sub size1 size2 in + max 10 + (((((0.0010986328125 * q) * size2) + (1.25 * size1)) + (12. * q)) + + 150.) *) +let cost_N_IEdiv_int size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 size2 in + (w1 * S.safe_int 12) + + (((w1 lsr 10) + (w1 lsr 13)) * size2) + + (size1 lsr 2) + size1 + S.safe_int 150 + +(* model interpreter/N_IEdiv_int_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (47.5167186214 + (0.500572259393 * (max size1 size2))) *) +let cost_N_IEdiv_int_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 50 + +(* model interpreter/N_IEdiv_int_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + let q = sub size1 size2 in + ((((0.0010986328125 * q) * size2) + (1.25 * size1)) + (12. * q)) + + 150. in + let alloc = 47.5167186214 + (0.500572259393 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IEdiv_int_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 size2 in + let w2 = S.max size1 size2 in + S.max + ((w1 * S.safe_int 12) + + (((w1 lsr 10) + (w1 lsr 13)) * size2) + + (size1 lsr 2) + size1 + S.safe_int 150) + ((w2 lsr 1) + (w2 lsr 6) + S.safe_int 50) + +(* model interpreter/N_IEdiv_nat *) +(* fun size1 -> + fun size2 -> + let q = sub size1 size2 in + max 10 + (((((0.0010986328125 * q) * size2) + (1.25 * size1)) + (12. * q)) + + 150.) *) +let cost_N_IEdiv_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 size2 in + (w1 * S.safe_int 12) + + (((w1 lsr 10) + (w1 lsr 13)) * size2) + + (size1 lsr 2) + size1 + S.safe_int 150 + +(* model interpreter/N_IEdiv_nat_alloc *) +(* fun size1 -> + fun size2 -> + max 10 + ((if size2 < size1 + then (0.500667315975 * size1) + (0. * size2) + else 0) + 40.6929981256) *) +let cost_N_IEdiv_nat_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (if size2 < size1 then (size1 lsr 1) + (size1 lsr 6) else S.safe_int 0) + + S.safe_int 45 + +(* model interpreter/N_IEdiv_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + let q = sub size1 size2 in + ((((0.0010986328125 * q) * size2) + (1.25 * size1)) + (12. * q)) + + 150. in + let alloc = + (if size2 < size1 + then (0.500667315975 * size1) + (0. * size2) + else 0) + 40.6929981256 in + max 10 (max time alloc) *) +let cost_N_IEdiv_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 size2 in + S.max + ((w1 * S.safe_int 12) + + (((w1 lsr 10) + (w1 lsr 13)) * size2) + + (size1 lsr 2) + size1 + S.safe_int 150) + ((if size2 < size1 then (size1 lsr 1) + (size1 lsr 6) else S.safe_int 0) + + S.safe_int 45) + +(* model interpreter/N_IEdiv_tez *) +(* max 10 80. *) +let cost_N_IEdiv_tez = S.safe_int 80 + +(* model interpreter/N_IEdiv_tez_alloc *) +(* max 10 32. *) +let cost_N_IEdiv_tez_alloc = S.safe_int 35 + +(* model interpreter/N_IEdiv_tez_synthesized *) +(* let time = 80. in let alloc = 32. in max 10 (max time alloc) *) +let cost_N_IEdiv_tez_synthesized = S.safe_int 80 + +(* model interpreter/N_IEdiv_teznat *) +(* max 10 70. *) +let cost_N_IEdiv_teznat = S.safe_int 70 + +(* model interpreter/N_IEdiv_teznat_alloc *) +(* max 10 44. *) +let cost_N_IEdiv_teznat_alloc = S.safe_int 45 + +(* model interpreter/N_IEdiv_teznat_synthesized *) +(* let time = 70. in let alloc = 44. in max 10 (max time alloc) *) +let cost_N_IEdiv_teznat_synthesized = S.safe_int 70 + +(* model interpreter/N_IEmit_alloc *) +(* max 10 124. *) +let cost_N_IEmit_alloc = S.safe_int 125 + +(* model interpreter/N_IEmit_synthesized *) +(* let time = 30. in let alloc = 124. in max 10 (max time alloc) *) +let cost_N_IEmit_synthesized = S.safe_int 125 + +(* model interpreter/N_IEmpty_big_map *) +(* max 10 300. *) +let cost_N_IEmpty_big_map = S.safe_int 300 + +(* model interpreter/N_IEmpty_big_map_alloc *) +(* max 10 44. *) +let cost_N_IEmpty_big_map_alloc = S.safe_int 45 + +(* model interpreter/N_IEmpty_big_map_synthesized *) +(* let time = 300. in let alloc = 44. in max 10 (max time alloc) *) +let cost_N_IEmpty_big_map_synthesized = S.safe_int 300 + +(* model interpreter/N_IEmpty_map *) +(* max 10 300. *) +let cost_N_IEmpty_map = S.safe_int 300 + +(* model interpreter/N_IEmpty_map_alloc *) +(* max 10 248. *) +let cost_N_IEmpty_map_alloc = S.safe_int 250 + +(* model interpreter/N_IEmpty_map_synthesized *) +(* let time = 300. in let alloc = 248. in max 10 (max time alloc) *) +let cost_N_IEmpty_map_synthesized = S.safe_int 300 + +(* model interpreter/N_IEmpty_set *) +(* max 10 300. *) +let cost_N_IEmpty_set = S.safe_int 300 + +(* model interpreter/N_IEmpty_set_alloc *) +(* max 10 184. *) +let cost_N_IEmpty_set_alloc = S.safe_int 185 + +(* model interpreter/N_IEmpty_set_synthesized *) +(* let time = 300. in let alloc = 184. in max 10 (max time alloc) *) +let cost_N_IEmpty_set_synthesized = S.safe_int 300 + +(* model interpreter/N_IEq *) +(* max 10 10. *) +let cost_N_IEq = S.safe_int 10 + +(* model interpreter/N_IEq_alloc *) +(* max 10 0. *) +let cost_N_IEq_alloc = S.safe_int 10 + +(* model interpreter/N_IEq_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IEq_synthesized = S.safe_int 10 + +(* model interpreter/N_IExec *) +(* max 10 10. *) +let cost_N_IExec = S.safe_int 10 + +(* model interpreter/N_IExec_alloc *) +(* max 10 0. *) +let cost_N_IExec_alloc = S.safe_int 10 + +(* model interpreter/N_IExec_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IExec_synthesized = S.safe_int 10 + +(* model interpreter/N_IFailwith *) +(* max 10 167.455190659 *) +let cost_N_IFailwith = S.safe_int 170 + +(* model interpreter/N_IFailwith_alloc *) +(* max 10 0. *) +let cost_N_IFailwith_alloc = S.safe_int 10 + +(* model interpreter/N_IFailwith_synthesized *) +(* let time = 167.455190659 in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IFailwith_synthesized = S.safe_int 170 + +(* model interpreter/N_IGe *) +(* max 10 10. *) +let cost_N_IGe = S.safe_int 10 + +(* model interpreter/N_IGe_alloc *) +(* max 10 0. *) +let cost_N_IGe_alloc = S.safe_int 10 + +(* model interpreter/N_IGe_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IGe_synthesized = S.safe_int 10 + +(* model interpreter/N_IGt *) +(* max 10 10. *) +let cost_N_IGt = S.safe_int 10 + +(* model interpreter/N_IGt_alloc *) +(* max 10 0. *) +let cost_N_IGt_alloc = S.safe_int 10 + +(* model interpreter/N_IGt_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IGt_synthesized = S.safe_int 10 + +(* model interpreter/N_IHalt *) +(* max 10 15. *) +let cost_N_IHalt = S.safe_int 15 + +(* model interpreter/N_IHalt_alloc *) +(* max 10 0. *) +let cost_N_IHalt_alloc = S.safe_int 10 + +(* model interpreter/N_IHalt_synthesized *) +(* let time = 15. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IHalt_synthesized = S.safe_int 15 + +(* model interpreter/N_IHash_key *) +(* max 10 605. *) +let cost_N_IHash_key = S.safe_int 605 + +(* model interpreter/N_IHash_key_alloc *) +(* max 10 32. *) +let cost_N_IHash_key_alloc = S.safe_int 35 + +(* model interpreter/N_IHash_key_synthesized *) +(* let time = 605. in let alloc = 32. in max 10 (max time alloc) *) +let cost_N_IHash_key_synthesized = S.safe_int 605 + +(* model interpreter/N_IIf *) +(* max 10 10. *) +let cost_N_IIf = S.safe_int 10 + +(* model interpreter/N_IIf_alloc *) +(* max 10 0. *) +let cost_N_IIf_alloc = S.safe_int 10 + +(* model interpreter/N_IIf_cons *) +(* max 10 10. *) +let cost_N_IIf_cons = S.safe_int 10 + +(* model interpreter/N_IIf_cons_alloc *) +(* max 10 0. *) +let cost_N_IIf_cons_alloc = S.safe_int 10 + +(* model interpreter/N_IIf_cons_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IIf_cons_synthesized = S.safe_int 10 + +(* model interpreter/N_IIf_left *) +(* max 10 10. *) +let cost_N_IIf_left = S.safe_int 10 + +(* model interpreter/N_IIf_left_alloc *) +(* max 10 0. *) +let cost_N_IIf_left_alloc = S.safe_int 10 + +(* model interpreter/N_IIf_left_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IIf_left_synthesized = S.safe_int 10 + +(* model interpreter/N_IIf_none *) +(* max 10 10. *) +let cost_N_IIf_none = S.safe_int 10 + +(* model interpreter/N_IIf_none_alloc *) +(* max 10 0. *) +let cost_N_IIf_none_alloc = S.safe_int 10 + +(* model interpreter/N_IIf_none_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IIf_none_synthesized = S.safe_int 10 + +(* model interpreter/N_IIf_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IIf_synthesized = S.safe_int 10 + +(* model interpreter/N_IImplicit_account *) +(* max 10 10. *) +let cost_N_IImplicit_account = S.safe_int 10 + +(* model interpreter/N_IImplicit_account_alloc *) +(* max 10 8. *) +let cost_N_IImplicit_account_alloc = S.safe_int 10 + +(* model interpreter/N_IImplicit_account_synthesized *) +(* let time = 10. in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_IImplicit_account_synthesized = S.safe_int 10 + +(* model interpreter/N_IInt_bls12_381_z_fr *) +(* max 10 115. *) +let cost_N_IInt_bls12_381_z_fr = S.safe_int 115 + +(* model interpreter/N_IInt_bls12_381_z_fr_alloc *) +(* max 10 28. *) +let cost_N_IInt_bls12_381_z_fr_alloc = S.safe_int 30 + +(* model interpreter/N_IInt_bls12_381_z_fr_synthesized *) +(* let time = 115. in let alloc = 28. in max 10 (max time alloc) *) +let cost_N_IInt_bls12_381_z_fr_synthesized = S.safe_int 115 + +(* model interpreter/N_IInt_bytes *) +(* fun size -> max 10 (20. + (2.5 * size)) *) +let cost_N_IInt_bytes size = + let size = S.safe_int size in + (size lsr 1) + (size * S.safe_int 2) + S.safe_int 20 + +(* model interpreter/N_IInt_bytes_alloc *) +(* fun size -> max 10 (15.3727158555 + (0.505091365778 * size)) *) +let cost_N_IInt_bytes_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 15 + +(* model interpreter/N_IInt_bytes_synthesized *) +(* fun size -> + let time = 20. + (2.5 * size) in + let alloc = 15.3727158555 + (0.505091365778 * size) in + max 10 (max time alloc) *) +let cost_N_IInt_bytes_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max + (w1 + (size * S.safe_int 2) + S.safe_int 20) + (w1 + (size lsr 6) + S.safe_int 15) + +(* model interpreter/N_IInt_nat *) +(* max 10 10. *) +let cost_N_IInt_nat = S.safe_int 10 + +(* model interpreter/N_IInt_nat_alloc *) +(* max 10 0. *) +let cost_N_IInt_nat_alloc = S.safe_int 10 + +(* model interpreter/N_IInt_nat_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IInt_nat_synthesized = S.safe_int 10 + +(* model interpreter/N_IIs_nat *) +(* max 10 10. *) +let cost_N_IIs_nat = S.safe_int 10 + +(* model interpreter/N_IIs_nat_alloc *) +(* max 10 8. *) +let cost_N_IIs_nat_alloc = S.safe_int 10 + +(* model interpreter/N_IIs_nat_synthesized *) +(* let time = 10. in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_IIs_nat_synthesized = S.safe_int 10 + +(* model interpreter/N_IJoin_tickets *) +(* fun content_size_x -> + fun content_size_y -> + fun amount_size_x -> + fun amount_size_y -> + max 10 + ((88.1705426747 + (0. * (min content_size_x content_size_y))) + + (0.0788934824125 * (max amount_size_x amount_size_y))) *) +let cost_N_IJoin_tickets _content_size_x _content_size_y amount_size_x + amount_size_y = + let amount_size_x = S.safe_int amount_size_x in + let amount_size_y = S.safe_int amount_size_y in + let w1 = S.max amount_size_x amount_size_y in + (w1 lsr 4) + (w1 lsr 6) + (w1 lsr 9) + S.safe_int 90 + +(* model interpreter/N_IJoin_tickets_alloc *) +(* fun content_size_x -> + fun content_size_y -> + fun amount_size_x -> + fun amount_size_y -> + max 10 + (42.1137922063 + + (0.500124881342 * (max amount_size_x amount_size_y))) *) +let cost_N_IJoin_tickets_alloc _content_size_x _content_size_y amount_size_x + amount_size_y = + let amount_size_x = S.safe_int amount_size_x in + let amount_size_y = S.safe_int amount_size_y in + let w1 = S.max amount_size_x amount_size_y in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 45 + +(* model interpreter/N_IJoin_tickets_synthesized *) +(* fun content_size_x -> + fun content_size_y -> + fun amount_size_x -> + fun amount_size_y -> + let time = + (88.1705426747 + (0. * (min content_size_x content_size_y))) + + (0.0788934824125 * (max amount_size_x amount_size_y)) in + let alloc = + 42.1137922063 + + (0.500124881342 * (max amount_size_x amount_size_y)) in + max 10 (max time alloc) *) +let cost_N_IJoin_tickets_synthesized _content_size_x _content_size_y + amount_size_x amount_size_y = + let amount_size_x = S.safe_int amount_size_x in + let amount_size_y = S.safe_int amount_size_y in + let w1 = S.max amount_size_x amount_size_y in + let w2 = w1 lsr 6 in + S.max + ((w1 lsr 4) + w2 + (w1 lsr 9) + S.safe_int 90) + ((w1 lsr 1) + w2 + S.safe_int 45) + +(* model interpreter/N_IKeccak *) +(* fun size -> max 10 (1350. + (8.25 * size)) *) +let cost_N_IKeccak size = + let size = S.safe_int size in + (size lsr 2) + (size * S.safe_int 8) + S.safe_int 1350 + +(* model interpreter/N_IKeccak_alloc *) +(* fun size -> max 10 24. *) +let cost_N_IKeccak_alloc _size = S.safe_int 25 + +(* model interpreter/N_IKeccak_synthesized *) +(* fun size -> + let time = 1350. + (8.25 * size) in + let alloc = 24. in max 10 (max time alloc) *) +let cost_N_IKeccak_synthesized size = + let size = S.safe_int size in + (size lsr 2) + (size * S.safe_int 8) + S.safe_int 1350 + +(* model interpreter/N_ILambda *) +(* max 10 (max 10. 10.) *) +let cost_N_ILambda = S.safe_int 10 + +(* model interpreter/N_ILambda_lam *) +(* max 10 10. *) +let cost_N_ILambda_lam = S.safe_int 10 + +(* model interpreter/N_ILambda_lam_alloc *) +(* max 10 68. *) +let cost_N_ILambda_lam_alloc = S.safe_int 70 + +(* model interpreter/N_ILambda_lam_synthesized *) +(* let time = 10. in let alloc = 68. in max 10 (max time alloc) *) +let cost_N_ILambda_lam_synthesized = S.safe_int 70 + +(* model interpreter/N_ILambda_lamrec *) +(* max 10 10. *) +let cost_N_ILambda_lamrec = S.safe_int 10 + +(* model interpreter/N_ILambda_lamrec_alloc *) +(* max 10 140. *) +let cost_N_ILambda_lamrec_alloc = S.safe_int 140 + +(* model interpreter/N_ILambda_lamrec_synthesized *) +(* let time = 10. in let alloc = 140. in max 10 (max time alloc) *) +let cost_N_ILambda_lamrec_synthesized = S.safe_int 140 + +(* model interpreter/N_ILe *) +(* max 10 10. *) +let cost_N_ILe = S.safe_int 10 + +(* model interpreter/N_ILe_alloc *) +(* max 10 0. *) +let cost_N_ILe_alloc = S.safe_int 10 + +(* model interpreter/N_ILe_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ILe_synthesized = S.safe_int 10 + +(* model interpreter/N_ILeft *) +(* max 10 10. *) +let cost_N_ILeft = S.safe_int 10 + +(* model interpreter/N_ILeft_alloc *) +(* max 10 8. *) +let cost_N_ILeft_alloc = S.safe_int 10 + +(* model interpreter/N_ILeft_synthesized *) +(* let time = 10. in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_ILeft_synthesized = S.safe_int 10 + +(* model interpreter/N_ILevel *) +(* max 10 10. *) +let cost_N_ILevel = S.safe_int 10 + +(* model interpreter/N_ILevel_alloc *) +(* max 10 12. *) +let cost_N_ILevel_alloc = S.safe_int 15 + +(* model interpreter/N_ILevel_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_ILevel_synthesized = S.safe_int 15 + +(* model interpreter/N_IList_iter *) +(* max 10 20. *) +let cost_N_IList_iter = S.safe_int 20 + +(* model interpreter/N_IList_iter_alloc *) +(* max 10 0. *) +let cost_N_IList_iter_alloc = S.safe_int 10 + +(* model interpreter/N_IList_iter_synthesized *) +(* let time = 20. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IList_iter_synthesized = S.safe_int 20 + +(* model interpreter/N_IList_map *) +(* max 10 20. *) +let cost_N_IList_map = S.safe_int 20 + +(* model interpreter/N_IList_map_alloc *) +(* max 10 1. *) +let cost_N_IList_map_alloc = S.safe_int 10 + +(* model interpreter/N_IList_map_synthesized *) +(* let time = 20. in let alloc = 1. in max 10 (max time alloc) *) +let cost_N_IList_map_synthesized = S.safe_int 20 + +(* model interpreter/N_IList_size *) +(* max 10 10. *) +let cost_N_IList_size = S.safe_int 10 + +(* model interpreter/N_IList_size_alloc *) +(* max 10 0. *) +let cost_N_IList_size_alloc = S.safe_int 10 + +(* model interpreter/N_IList_size_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IList_size_synthesized = S.safe_int 10 + +(* model interpreter/N_ILoop *) +(* max 10 (max 10. 1.01451868265) *) +let cost_N_ILoop = S.safe_int 10 + +(* model interpreter/N_ILoop_in *) +(* max 10 10. *) +let cost_N_ILoop_in = S.safe_int 10 + +(* model interpreter/N_ILoop_in_alloc *) +(* max 10 0. *) +let cost_N_ILoop_in_alloc = S.safe_int 10 + +(* model interpreter/N_ILoop_in_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ILoop_in_synthesized = S.safe_int 10 + +(* model interpreter/N_ILoop_left *) +(* max 10 (max 10. 10.) *) +let cost_N_ILoop_left = S.safe_int 10 + +(* model interpreter/N_ILoop_left_in *) +(* max 10 10. *) +let cost_N_ILoop_left_in = S.safe_int 10 + +(* model interpreter/N_ILoop_left_in_alloc *) +(* max 10 0. *) +let cost_N_ILoop_left_in_alloc = S.safe_int 10 + +(* model interpreter/N_ILoop_left_in_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ILoop_left_in_synthesized = S.safe_int 10 + +(* model interpreter/N_ILoop_left_out *) +(* max 10 10. *) +let cost_N_ILoop_left_out = S.safe_int 10 + +(* model interpreter/N_ILoop_left_out_alloc *) +(* max 10 0. *) +let cost_N_ILoop_left_out_alloc = S.safe_int 10 + +(* model interpreter/N_ILoop_left_out_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ILoop_left_out_synthesized = S.safe_int 10 + +(* model interpreter/N_ILoop_out *) +(* max 10 1.01451868265 *) +let cost_N_ILoop_out = S.safe_int 10 + +(* model interpreter/N_ILoop_out_alloc *) +(* max 10 0. *) +let cost_N_ILoop_out_alloc = S.safe_int 10 + +(* model interpreter/N_ILoop_out_synthesized *) +(* let time = 1.01451868265 in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ILoop_out_synthesized = S.safe_int 10 + +(* model interpreter/N_ILsl_bytes_alloc *) +(* fun size1 -> + fun size2 -> + max 10 + ((11.757438371 + (0.500014421862 * size1)) + + (0.0624426926223 * (sub size2 1))) *) +let cost_N_ILsl_bytes_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.sub size2 (S.safe_int 1) lsr 4) + + (size1 lsr 1) + (size1 lsr 6) + S.safe_int 15 + +(* model interpreter/N_ILsl_bytes_synthesized *) +(* fun size1 -> + fun size2 -> + let time = (65. + (0.75 * size1)) + (0.0625 * (sub size2 1)) in + let alloc = + (11.757438371 + (0.500014421862 * size1)) + + (0.0624426926223 * (sub size2 1)) in + max 10 (max time alloc) *) +let cost_N_ILsl_bytes_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = (S.sub size2 (S.safe_int 1) lsr 4) + (size1 lsr 1) in + S.max (w1 + (size1 lsr 2) + S.safe_int 65) (w1 + (size1 lsr 6) + S.safe_int 15) + +(* model interpreter/N_ILsl_nat_alloc *) +(* fun size -> max 10 (29.0640101265 + (0.500355618928 * size)) *) +let cost_N_ILsl_nat_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 30 + +(* model interpreter/N_ILsl_nat_synthesized *) +(* fun size -> + let time = 128. + (0.5 * size) in + let alloc = 29.0640101265 + (0.500355618928 * size) in + max 10 (max time alloc) *) +let cost_N_ILsl_nat_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 130) (w1 + (size lsr 6) + S.safe_int 30) + +(* model interpreter/N_ILsr_bytes *) +(* fun size1 -> + fun size2 -> + let q = sub size1 (size2 * 0.125) in max 10 (55. + (0.75 * q)) *) +let cost_N_ILsr_bytes size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 (size2 lsr 3) in + (w1 lsr 1) + (w1 lsr 2) + S.safe_int 55 + +(* model interpreter/N_ILsr_bytes_alloc *) +(* fun size1 -> + fun size2 -> + let q = sub size1 (size2 * 0.125) in + max 10 (11.1748222186 + (0.499974561517 * q)) *) +let cost_N_ILsr_bytes_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.sub size1 (size2 lsr 3) lsr 1) + S.safe_int 15 + +(* model interpreter/N_ILsr_bytes_synthesized *) +(* fun size1 -> + fun size2 -> + let time = let q = sub size1 (size2 * 0.125) in 55. + (0.75 * q) in + let alloc = + let q = sub size1 (size2 * 0.125) in + 11.1748222186 + (0.499974561517 * q) in + max 10 (max time alloc) *) +let cost_N_ILsr_bytes_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 (size2 lsr 3) in + (w1 lsr 1) + (w1 lsr 2) + S.safe_int 55 + +(* model interpreter/N_ILsr_nat *) +(* fun size -> max 10 (45. + (0.5 * size)) *) +let cost_N_ILsr_nat size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 45 + +(* model interpreter/N_ILsr_nat_alloc *) +(* fun size -> max 10 (19.6693071446 + (0.500176652166 * size)) *) +let cost_N_ILsr_nat_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 20 + +(* model interpreter/N_ILsr_nat_synthesized *) +(* fun size -> + let time = 45. + (0.5 * size) in + let alloc = 19.6693071446 + (0.500176652166 * size) in + max 10 (max time alloc) *) +let cost_N_ILsr_nat_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 45) (w1 + (size lsr 6) + S.safe_int 20) + +(* model interpreter/N_ILt *) +(* max 10 10. *) +let cost_N_ILt = S.safe_int 10 + +(* model interpreter/N_ILt_alloc *) +(* max 10 0. *) +let cost_N_ILt_alloc = S.safe_int 10 + +(* model interpreter/N_ILt_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ILt_synthesized = S.safe_int 10 + +(* model interpreter/N_IMap_get *) +(* fun size1 -> + fun size2 -> max 10 (45. + (0.046875 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IMap_get size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 5) + (w3 lsr 6) + S.safe_int 45 + +(* model interpreter/N_IMap_get_alloc *) +(* fun size1 -> fun size2 -> max 10 8. *) +let cost_N_IMap_get_alloc _size1 _size2 = S.safe_int 10 + +(* model interpreter/N_IMap_get_and_update *) +(* fun size1 -> + fun size2 -> max 10 (75. + (0.140625 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IMap_get_and_update size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 3) + (w3 lsr 6) + S.safe_int 75 + +(* model interpreter/N_IMap_get_and_update_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((27.8275684249 * (log2 (1 + size2))) + 90.906332394) *) +let cost_N_IMap_get_and_update_alloc _size1 size2 = + let size2 = S.safe_int size2 in + (log2 (size2 + S.safe_int 1) * S.safe_int 28) + S.safe_int 95 + +(* model interpreter/N_IMap_get_and_update_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 75. + (0.140625 * (size1 * (log2 (1 + size2)))) in + let alloc = (27.8275684249 * (log2 (1 + size2))) + 90.906332394 in + max 10 (max time alloc) *) +let cost_N_IMap_get_and_update_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + let w3 = w1 * size1 in + S.max + ((w3 lsr 3) + (w3 lsr 6) + S.safe_int 75) + ((w1 * S.safe_int 28) + S.safe_int 95) + +(* model interpreter/N_IMap_get_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 45. + (0.046875 * (size1 * (log2 (1 + size2)))) in + let alloc = 8. in max 10 (max time alloc) *) +let cost_N_IMap_get_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 5) + (w3 lsr 6) + S.safe_int 45 + +(* model interpreter/N_IMap_iter *) +(* fun size -> max 10 (50. + (7.625 * size)) *) +let cost_N_IMap_iter size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 3) + (size * S.safe_int 7) + S.safe_int 50 + +(* model interpreter/N_IMap_iter_alloc *) +(* fun size -> max 10 0. *) +let cost_N_IMap_iter_alloc _size = S.safe_int 10 + +(* model interpreter/N_IMap_iter_synthesized *) +(* fun size -> + let time = 50. + (7.625 * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IMap_iter_synthesized size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 3) + (size * S.safe_int 7) + S.safe_int 50 + +(* model interpreter/N_IMap_map *) +(* fun size -> max 10 (40. + (8.5 * size)) *) +let cost_N_IMap_map size = + let size = S.safe_int size in + (size lsr 1) + (size * S.safe_int 8) + S.safe_int 40 + +(* model interpreter/N_IMap_map_alloc *) +(* fun size -> max 10 0. *) +let cost_N_IMap_map_alloc _size = S.safe_int 10 + +(* model interpreter/N_IMap_map_synthesized *) +(* fun size -> + let time = 40. + (8.5 * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IMap_map_synthesized size = + let size = S.safe_int size in + (size lsr 1) + (size * S.safe_int 8) + S.safe_int 40 + +(* model interpreter/N_IMap_mem *) +(* fun size1 -> + fun size2 -> max 10 (45. + (0.046875 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IMap_mem size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 5) + (w3 lsr 6) + S.safe_int 45 + +(* model interpreter/N_IMap_mem_alloc *) +(* fun size1 -> fun size2 -> max 10 0. *) +let cost_N_IMap_mem_alloc _size1 _size2 = S.safe_int 10 + +(* model interpreter/N_IMap_mem_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 45. + (0.046875 * (size1 * (log2 (1 + size2)))) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IMap_mem_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 5) + (w3 lsr 6) + S.safe_int 45 + +(* model interpreter/N_IMap_size *) +(* max 10 10. *) +let cost_N_IMap_size = S.safe_int 10 + +(* model interpreter/N_IMap_size_alloc *) +(* max 10 0. *) +let cost_N_IMap_size_alloc = S.safe_int 10 + +(* model interpreter/N_IMap_size_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IMap_size_synthesized = S.safe_int 10 + +(* model interpreter/N_IMap_update *) +(* fun size1 -> + fun size2 -> max 10 (55. + (0.09375 * (size1 * (log2 (1 + size2))))) *) +let cost_N_IMap_update size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 4) + (w3 lsr 5) + S.safe_int 55 + +(* model interpreter/N_IMap_update_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((27.8275684249 * (log2 (1 + size2))) + 78.906332394) *) +let cost_N_IMap_update_alloc _size1 size2 = + let size2 = S.safe_int size2 in + (log2 (size2 + S.safe_int 1) * S.safe_int 28) + S.safe_int 80 + +(* model interpreter/N_IMap_update_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 55. + (0.09375 * (size1 * (log2 (1 + size2)))) in + let alloc = (27.8275684249 * (log2 (1 + size2))) + 78.906332394 in + max 10 (max time alloc) *) +let cost_N_IMap_update_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + let w3 = w1 * size1 in + S.max + ((w3 lsr 4) + (w3 lsr 5) + S.safe_int 55) + ((w1 * S.safe_int 28) + S.safe_int 80) + +(* model interpreter/N_IMin_block_time *) +(* max 10 20. *) +let cost_N_IMin_block_time = S.safe_int 20 + +(* model interpreter/N_IMin_block_time_alloc *) +(* max 10 12. *) +let cost_N_IMin_block_time_alloc = S.safe_int 15 + +(* model interpreter/N_IMin_block_time_synthesized *) +(* let time = 20. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IMin_block_time_synthesized = S.safe_int 20 + +(* model interpreter/N_IMul_bls12_381_fr *) +(* max 10 45. *) +let cost_N_IMul_bls12_381_fr = S.safe_int 45 + +(* model interpreter/N_IMul_bls12_381_fr_alloc *) +(* max 10 24. *) +let cost_N_IMul_bls12_381_fr_alloc = S.safe_int 25 + +(* model interpreter/N_IMul_bls12_381_fr_synthesized *) +(* let time = 45. in let alloc = 24. in max 10 (max time alloc) *) +let cost_N_IMul_bls12_381_fr_synthesized = S.safe_int 45 + +(* model interpreter/N_IMul_bls12_381_fr_z *) +(* fun size -> max 10 (265. + (1.0625 * size)) *) +let cost_N_IMul_bls12_381_fr_z size = + let size = S.safe_int size in + (size lsr 4) + size + S.safe_int 265 + +(* model interpreter/N_IMul_bls12_381_fr_z_alloc *) +(* fun size -> max 10 24. *) +let cost_N_IMul_bls12_381_fr_z_alloc _size = S.safe_int 25 + +(* model interpreter/N_IMul_bls12_381_fr_z_synthesized *) +(* fun size -> + let time = 265. + (1.0625 * size) in + let alloc = 24. in max 10 (max time alloc) *) +let cost_N_IMul_bls12_381_fr_z_synthesized size = + let size = S.safe_int size in + (size lsr 4) + size + S.safe_int 265 + +(* model interpreter/N_IMul_bls12_381_g1 *) +(* max 10 103000. *) +let cost_N_IMul_bls12_381_g1 = S.safe_int 103000 + +(* model interpreter/N_IMul_bls12_381_g1_alloc *) +(* max 10 80. *) +let cost_N_IMul_bls12_381_g1_alloc = S.safe_int 80 + +(* model interpreter/N_IMul_bls12_381_g1_synthesized *) +(* let time = 103000. in let alloc = 80. in max 10 (max time alloc) *) +let cost_N_IMul_bls12_381_g1_synthesized = S.safe_int 103000 + +(* model interpreter/N_IMul_bls12_381_g2 *) +(* max 10 220000. *) +let cost_N_IMul_bls12_381_g2 = S.safe_int 220000 + +(* model interpreter/N_IMul_bls12_381_g2_alloc *) +(* max 10 152. *) +let cost_N_IMul_bls12_381_g2_alloc = S.safe_int 155 + +(* model interpreter/N_IMul_bls12_381_g2_synthesized *) +(* let time = 220000. in let alloc = 152. in max 10 (max time alloc) *) +let cost_N_IMul_bls12_381_g2_synthesized = S.safe_int 220000 + +(* model interpreter/N_IMul_bls12_381_z_fr *) +(* fun size -> max 10 (265. + (1.0625 * size)) *) +let cost_N_IMul_bls12_381_z_fr size = + let size = S.safe_int size in + (size lsr 4) + size + S.safe_int 265 + +(* model interpreter/N_IMul_bls12_381_z_fr_alloc *) +(* fun size -> max 10 24. *) +let cost_N_IMul_bls12_381_z_fr_alloc _size = S.safe_int 25 + +(* model interpreter/N_IMul_bls12_381_z_fr_synthesized *) +(* fun size -> + let time = 265. + (1.0625 * size) in + let alloc = 24. in max 10 (max time alloc) *) +let cost_N_IMul_bls12_381_z_fr_synthesized size = + let size = S.safe_int size in + (size lsr 4) + size + S.safe_int 265 + +(* model interpreter/N_IMul_int *) +(* fun size1 -> + fun size2 -> + let a = size1 + size2 in + max 10 ((0.8125 * (a * (log2 (1 + a)))) + 55.) *) +let cost_N_IMul_int size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = size1 + size2 in + let w4 = log2 (w3 + S.safe_int 1) * w3 in + (w4 lsr 1) + (w4 lsr 2) + (w4 lsr 4) + S.safe_int 55 + +(* model interpreter/N_IMul_int_alloc *) +(* fun size1 -> + fun size2 -> max 10 (16.9221412881 + (0.500135612537 * (size1 + size2))) *) +let cost_N_IMul_int_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = size1 + size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_IMul_int_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + let a = size1 + size2 in (0.8125 * (a * (log2 (1 + a)))) + 55. in + let alloc = 16.9221412881 + (0.500135612537 * (size1 + size2)) in + max 10 (max time alloc) *) +let cost_N_IMul_int_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = size1 + size2 in + let w4 = log2 (w3 + S.safe_int 1) * w3 in + S.max + ((w4 lsr 1) + (w4 lsr 2) + (w4 lsr 4) + S.safe_int 55) + ((w3 lsr 1) + (w3 lsr 6) + S.safe_int 20) + +(* model interpreter/N_IMul_nat *) +(* fun size1 -> + fun size2 -> + let a = size1 + size2 in + max 10 ((0.8125 * (a * (log2 (1 + a)))) + 55.) *) +let cost_N_IMul_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = size1 + size2 in + let w4 = log2 (w3 + S.safe_int 1) * w3 in + (w4 lsr 1) + (w4 lsr 2) + (w4 lsr 4) + S.safe_int 55 + +(* model interpreter/N_IMul_nat_alloc *) +(* fun size1 -> + fun size2 -> max 10 (15.2155091333 + (0.500139029901 * (size1 + size2))) *) +let cost_N_IMul_nat_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = size1 + size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 15 + +(* model interpreter/N_IMul_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + let a = size1 + size2 in (0.8125 * (a * (log2 (1 + a)))) + 55. in + let alloc = 15.2155091333 + (0.500139029901 * (size1 + size2)) in + max 10 (max time alloc) *) +let cost_N_IMul_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = size1 + size2 in + let w4 = log2 (w3 + S.safe_int 1) * w3 in + S.max + ((w4 lsr 1) + (w4 lsr 2) + (w4 lsr 4) + S.safe_int 55) + ((w3 lsr 1) + (w3 lsr 6) + S.safe_int 15) + +(* model interpreter/N_IMul_nattez *) +(* max 10 50. *) +let cost_N_IMul_nattez = S.safe_int 50 + +(* model interpreter/N_IMul_nattez_alloc *) +(* max 10 12. *) +let cost_N_IMul_nattez_alloc = S.safe_int 15 + +(* model interpreter/N_IMul_nattez_synthesized *) +(* let time = 50. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IMul_nattez_synthesized = S.safe_int 50 + +(* model interpreter/N_IMul_teznat *) +(* max 10 50. *) +let cost_N_IMul_teznat = S.safe_int 50 + +(* model interpreter/N_IMul_teznat_alloc *) +(* max 10 12. *) +let cost_N_IMul_teznat_alloc = S.safe_int 15 + +(* model interpreter/N_IMul_teznat_synthesized *) +(* let time = 50. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IMul_teznat_synthesized = S.safe_int 50 + +(* model interpreter/N_INat_bytes *) +(* fun size -> max 10 (45. + (2.5 * size)) *) +let cost_N_INat_bytes size = + let size = S.safe_int size in + (size lsr 1) + (size * S.safe_int 2) + S.safe_int 45 + +(* model interpreter/N_INat_bytes_alloc *) +(* fun size -> max 10 (15.3744531872 + (0.505021872511 * size)) *) +let cost_N_INat_bytes_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 15 + +(* model interpreter/N_INat_bytes_synthesized *) +(* fun size -> + let time = 45. + (2.5 * size) in + let alloc = 15.3744531872 + (0.505021872511 * size) in + max 10 (max time alloc) *) +let cost_N_INat_bytes_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max + (w1 + (size * S.safe_int 2) + S.safe_int 45) + (w1 + (size lsr 6) + S.safe_int 15) + +(* model interpreter/N_INeg *) +(* fun size -> max 10 (25. + (0.5 * size)) *) +let cost_N_INeg size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 25 + +(* model interpreter/N_INeg_alloc *) +(* fun size -> max 10 (15.6123273039 + (0.500207090115 * size)) *) +let cost_N_INeg_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 20 + +(* model interpreter/N_INeg_bls12_381_fr *) +(* max 10 30. *) +let cost_N_INeg_bls12_381_fr = S.safe_int 30 + +(* model interpreter/N_INeg_bls12_381_fr_alloc *) +(* max 10 24. *) +let cost_N_INeg_bls12_381_fr_alloc = S.safe_int 25 + +(* model interpreter/N_INeg_bls12_381_fr_synthesized *) +(* let time = 30. in let alloc = 24. in max 10 (max time alloc) *) +let cost_N_INeg_bls12_381_fr_synthesized = S.safe_int 30 + +(* model interpreter/N_INeg_bls12_381_g1 *) +(* max 10 50. *) +let cost_N_INeg_bls12_381_g1 = S.safe_int 50 + +(* model interpreter/N_INeg_bls12_381_g1_alloc *) +(* max 10 80. *) +let cost_N_INeg_bls12_381_g1_alloc = S.safe_int 80 + +(* model interpreter/N_INeg_bls12_381_g1_synthesized *) +(* let time = 50. in let alloc = 80. in max 10 (max time alloc) *) +let cost_N_INeg_bls12_381_g1_synthesized = S.safe_int 80 + +(* model interpreter/N_INeg_bls12_381_g2 *) +(* max 10 70. *) +let cost_N_INeg_bls12_381_g2 = S.safe_int 70 + +(* model interpreter/N_INeg_bls12_381_g2_alloc *) +(* max 10 152. *) +let cost_N_INeg_bls12_381_g2_alloc = S.safe_int 155 + +(* model interpreter/N_INeg_bls12_381_g2_synthesized *) +(* let time = 70. in let alloc = 152. in max 10 (max time alloc) *) +let cost_N_INeg_bls12_381_g2_synthesized = S.safe_int 155 + +(* model interpreter/N_INeg_synthesized *) +(* fun size -> + let time = 25. + (0.5 * size) in + let alloc = 15.6123273039 + (0.500207090115 * size) in + max 10 (max time alloc) *) +let cost_N_INeg_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 25) (w1 + (size lsr 6) + S.safe_int 20) + +(* model interpreter/N_INeq *) +(* max 10 10. *) +let cost_N_INeq = S.safe_int 10 + +(* model interpreter/N_INeq_alloc *) +(* max 10 0. *) +let cost_N_INeq_alloc = S.safe_int 10 + +(* model interpreter/N_INeq_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_INeq_synthesized = S.safe_int 10 + +(* model interpreter/N_INil *) +(* max 10 10. *) +let cost_N_INil = S.safe_int 10 + +(* model interpreter/N_INil_alloc *) +(* max 10 12. *) +let cost_N_INil_alloc = S.safe_int 15 + +(* model interpreter/N_INil_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_INil_synthesized = S.safe_int 15 + +(* model interpreter/N_INot *) +(* max 10 10. *) +let cost_N_INot = S.safe_int 10 + +(* model interpreter/N_INot_alloc *) +(* max 10 0. *) +let cost_N_INot_alloc = S.safe_int 10 + +(* model interpreter/N_INot_bytes *) +(* fun size -> max 10 (30. + (0.5 * size)) *) +let cost_N_INot_bytes size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 30 + +(* model interpreter/N_INot_bytes_alloc *) +(* fun size -> max 10 (10.5493304199 + (0.499980342588 * size)) *) +let cost_N_INot_bytes_alloc size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 15 + +(* model interpreter/N_INot_bytes_synthesized *) +(* fun size -> + let time = 30. + (0.5 * size) in + let alloc = 10.5493304199 + (0.499980342588 * size) in + max 10 (max time alloc) *) +let cost_N_INot_bytes_synthesized size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 30 + +(* model interpreter/N_INot_int *) +(* fun size -> max 10 (25. + (0.5 * size)) *) +let cost_N_INot_int size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 25 + +(* model interpreter/N_INot_int_alloc *) +(* fun size -> max 10 (19.5017942553 + (0.500266135547 * size)) *) +let cost_N_INot_int_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 20 + +(* model interpreter/N_INot_int_synthesized *) +(* fun size -> + let time = 25. + (0.5 * size) in + let alloc = 19.5017942553 + (0.500266135547 * size) in + max 10 (max time alloc) *) +let cost_N_INot_int_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 25) (w1 + (size lsr 6) + S.safe_int 20) + +(* model interpreter/N_INot_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_INot_synthesized = S.safe_int 10 + +(* model interpreter/N_INow *) +(* max 10 10. *) +let cost_N_INow = S.safe_int 10 + +(* model interpreter/N_INow_alloc *) +(* max 10 12. *) +let cost_N_INow_alloc = S.safe_int 15 + +(* model interpreter/N_INow_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_INow_synthesized = S.safe_int 15 + +(* model interpreter/N_IOpen_chest *) +(* fun size1 -> + fun size2 -> + max 10 ((919000. + (22528. * (sub size1 1))) + (3.25 * size2)) *) +let cost_N_IOpen_chest size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.sub size1 (S.safe_int 1) * S.safe_int 22528) + + (size2 lsr 2) + + (size2 * S.safe_int 3) + + S.safe_int 919000 + +(* model interpreter/N_IOpen_chest_alloc *) +(* fun size1 -> + fun size2 -> + max 10 + ((15.4181598756 + (0.25261512656 * (sub size1 1))) + + (0.500643059623 * size2)) *) +let cost_N_IOpen_chest_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 (S.safe_int 1) in + (w1 lsr 2) + (w1 lsr 7) + (size2 lsr 1) + (size2 lsr 6) + S.safe_int 15 + +(* model interpreter/N_IOpen_chest_synthesized *) +(* fun size1 -> + fun size2 -> + let time = (919000. + (22528. * (sub size1 1))) + (3.25 * size2) in + let alloc = + (15.4181598756 + (0.25261512656 * (sub size1 1))) + + (0.500643059623 * size2) in + max 10 (max time alloc) *) +let cost_N_IOpen_chest_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.sub size1 (S.safe_int 1) in + S.max + ((w1 * S.safe_int 22528) + + (size2 lsr 2) + + (size2 * S.safe_int 3) + + S.safe_int 919000) + ((w1 lsr 2) + (w1 lsr 7) + (size2 lsr 1) + (size2 lsr 6) + S.safe_int 15) + +(* model interpreter/N_IOpt_map *) +(* max 10 (max 10. 0.) *) +let cost_N_IOpt_map = S.safe_int 10 + +(* model interpreter/N_IOpt_map_none *) +(* max 10 10. *) +let cost_N_IOpt_map_none = S.safe_int 10 + +(* model interpreter/N_IOpt_map_none_alloc *) +(* max 10 0. *) +let cost_N_IOpt_map_none_alloc = S.safe_int 10 + +(* model interpreter/N_IOpt_map_none_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IOpt_map_none_synthesized = S.safe_int 10 + +(* model interpreter/N_IOpt_map_some *) +(* max 10 0. *) +let cost_N_IOpt_map_some = S.safe_int 10 + +(* model interpreter/N_IOpt_map_some_alloc *) +(* max 10 0. *) +let cost_N_IOpt_map_some_alloc = S.safe_int 10 + +(* model interpreter/N_IOpt_map_some_synthesized *) +(* let time = 0. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IOpt_map_some_synthesized = S.safe_int 10 + +(* model interpreter/N_IOr *) +(* max 10 10. *) +let cost_N_IOr = S.safe_int 10 + +(* model interpreter/N_IOr_alloc *) +(* max 10 0. *) +let cost_N_IOr_alloc = S.safe_int 10 + +(* model interpreter/N_IOr_bytes *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IOr_bytes size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IOr_bytes_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (10.6873582322 + (0.499979321651 * (max size1 size2))) *) +let cost_N_IOr_bytes_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 15 + +(* model interpreter/N_IOr_bytes_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 10.6873582322 + (0.499979321651 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IOr_bytes_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IOr_nat *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IOr_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IOr_nat_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (13.9478780796 + (0.500186338819 * (max size1 size2))) *) +let cost_N_IOr_nat_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 15 + +(* model interpreter/N_IOr_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 13.9478780796 + (0.500186338819 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IOr_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 15) + +(* model interpreter/N_IOr_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IOr_synthesized = S.safe_int 10 + +(* model interpreter/N_IPairing_check_bls12_381 *) +(* fun size -> max 10 (450000. + (342500. * size)) *) +let cost_N_IPairing_check_bls12_381 size = + let size = S.safe_int size in + (size * S.safe_int 344064) + S.safe_int 450000 + +(* model interpreter/N_IPairing_check_bls12_381_alloc *) +(* fun size -> max 10 0. *) +let cost_N_IPairing_check_bls12_381_alloc _size = S.safe_int 10 + +(* model interpreter/N_IPairing_check_bls12_381_synthesized *) +(* fun size -> + let time = 450000. + (342500. * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IPairing_check_bls12_381_synthesized size = + let size = S.safe_int size in + (size * S.safe_int 344064) + S.safe_int 450000 + +(* model interpreter/N_IPush *) +(* max 10 10. *) +let cost_N_IPush = S.safe_int 10 + +(* model interpreter/N_IPush_alloc *) +(* max 10 12. *) +let cost_N_IPush_alloc = S.safe_int 15 + +(* model interpreter/N_IPush_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IPush_synthesized = S.safe_int 15 + +(* model interpreter/N_IRead_ticket *) +(* max 10 10. *) +let cost_N_IRead_ticket = S.safe_int 10 + +(* model interpreter/N_IRead_ticket_alloc *) +(* max 10 56. *) +let cost_N_IRead_ticket_alloc = S.safe_int 60 + +(* model interpreter/N_IRead_ticket_synthesized *) +(* let time = 10. in let alloc = 56. in max 10 (max time alloc) *) +let cost_N_IRead_ticket_synthesized = S.safe_int 60 + +(* model interpreter/N_IRight *) +(* max 10 10. *) +let cost_N_IRight = S.safe_int 10 + +(* model interpreter/N_IRight_alloc *) +(* max 10 8. *) +let cost_N_IRight_alloc = S.safe_int 10 + +(* model interpreter/N_IRight_synthesized *) +(* let time = 10. in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_IRight_synthesized = S.safe_int 10 + +(* model interpreter/N_ISapling_empty_state *) +(* max 10 300. *) +let cost_N_ISapling_empty_state = S.safe_int 300 + +(* model interpreter/N_ISapling_empty_state_alloc *) +(* max 10 28. *) +let cost_N_ISapling_empty_state_alloc = S.safe_int 30 + +(* model interpreter/N_ISapling_empty_state_synthesized *) +(* let time = 300. in let alloc = 28. in max 10 (max time alloc) *) +let cost_N_ISapling_empty_state_synthesized = S.safe_int 300 + +(* model interpreter/N_ISapling_verify_update *) +(* fun size1 -> + fun size2 -> + max 10 ((432500. + (5740000. * size1)) + (4636500. * size2)) *) +let cost_N_ISapling_verify_update size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (size1 * S.safe_int 5767168) + + (size2 * S.safe_int 4718592) + + S.safe_int 432500 + +(* model interpreter/N_ISapling_verify_update_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((50.74 + (12.0173040271 * size1)) + (24.0179324276 * size2)) *) +let cost_N_ISapling_verify_update_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (size1 lsr 2) + (size2 lsr 1) + + (size1 * S.safe_int 12) + + (size2 * S.safe_int 24) + + S.safe_int 55 + +(* model interpreter/N_ISapling_verify_update_synthesized *) +(* fun size1 -> + fun size2 -> + let time = (432500. + (5740000. * size1)) + (4636500. * size2) in + let alloc = + (50.74 + (12.0173040271 * size1)) + (24.0179324276 * size2) in + max 10 (max time alloc) *) +let cost_N_ISapling_verify_update_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + S.max + ((size1 * S.safe_int 5767168) + + (size2 * S.safe_int 4718592) + + S.safe_int 432500) + ((size1 lsr 2) + (size2 lsr 1) + + (size1 * S.safe_int 12) + + (size2 * S.safe_int 24) + + S.safe_int 55) + +(* model interpreter/N_ISelf *) +(* max 10 10. *) +let cost_N_ISelf = S.safe_int 10 + +(* model interpreter/N_ISelf_address *) +(* max 10 10. *) +let cost_N_ISelf_address = S.safe_int 10 + +(* model interpreter/N_ISelf_address_alloc *) +(* max 10 64. *) +let cost_N_ISelf_address_alloc = S.safe_int 65 + +(* model interpreter/N_ISelf_address_synthesized *) +(* let time = 10. in let alloc = 64. in max 10 (max time alloc) *) +let cost_N_ISelf_address_synthesized = S.safe_int 65 + +(* model interpreter/N_ISelf_alloc *) +(* max 10 52. *) +let cost_N_ISelf_alloc = S.safe_int 55 + +(* model interpreter/N_ISelf_synthesized *) +(* let time = 10. in let alloc = 52. in max 10 (max time alloc) *) +let cost_N_ISelf_synthesized = S.safe_int 55 + +(* model interpreter/N_ISender *) +(* max 10 10. *) +let cost_N_ISender = S.safe_int 10 + +(* model interpreter/N_ISender_alloc *) +(* max 10 72. *) +let cost_N_ISender_alloc = S.safe_int 75 + +(* model interpreter/N_ISender_synthesized *) +(* let time = 10. in let alloc = 72. in max 10 (max time alloc) *) +let cost_N_ISender_synthesized = S.safe_int 75 + +(* model interpreter/N_ISet_delegate *) +(* max 10 60. *) +let cost_N_ISet_delegate = S.safe_int 60 + +(* model interpreter/N_ISet_delegate_alloc *) +(* max 10 76. *) +let cost_N_ISet_delegate_alloc = S.safe_int 80 + +(* model interpreter/N_ISet_delegate_synthesized *) +(* let time = 60. in let alloc = 76. in max 10 (max time alloc) *) +let cost_N_ISet_delegate_synthesized = S.safe_int 80 + +(* model interpreter/N_ISet_iter *) +(* fun size -> max 10 (50. + (7.625 * size)) *) +let cost_N_ISet_iter size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 3) + (size * S.safe_int 7) + S.safe_int 50 + +(* model interpreter/N_ISet_iter_alloc *) +(* fun size -> max 10 0. *) +let cost_N_ISet_iter_alloc _size = S.safe_int 10 + +(* model interpreter/N_ISet_iter_synthesized *) +(* fun size -> + let time = 50. + (7.625 * size) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ISet_iter_synthesized size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 3) + (size * S.safe_int 7) + S.safe_int 50 + +(* model interpreter/N_ISet_mem *) +(* fun size1 -> + fun size2 -> + max 10 + (39.3805426747 + (0.0564536354586 * (size1 * (log2 (1 + size2))))) *) +let cost_N_ISet_mem size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 5) + (w3 lsr 6) + (w3 lsr 7) + (w3 lsr 9) + S.safe_int 40 + +(* model interpreter/N_ISet_mem_alloc *) +(* fun size1 -> fun size2 -> max 10 0. *) +let cost_N_ISet_mem_alloc _size1 _size2 = S.safe_int 10 + +(* model interpreter/N_ISet_mem_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + 39.3805426747 + (0.0564536354586 * (size1 * (log2 (1 + size2)))) in + let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ISet_mem_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 5) + (w3 lsr 6) + (w3 lsr 7) + (w3 lsr 9) + S.safe_int 40 + +(* model interpreter/N_ISet_size *) +(* max 10 10. *) +let cost_N_ISet_size = S.safe_int 10 + +(* model interpreter/N_ISet_size_alloc *) +(* max 10 0. *) +let cost_N_ISet_size_alloc = S.safe_int 10 + +(* model interpreter/N_ISet_size_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_ISet_size_synthesized = S.safe_int 10 + +(* model interpreter/N_ISet_update *) +(* fun size1 -> + fun size2 -> + max 10 + (49.8905426747 + (0.140036207663 * (size1 * (log2 (1 + size2))))) *) +let cost_N_ISet_update size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + (w3 lsr 3) + (w3 lsr 6) + S.safe_int 50 + +(* model interpreter/N_ISet_update_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((21.7417458006 * (log2 (1 + size2))) + 77.6256737848) *) +let cost_N_ISet_update_alloc _size1 size2 = + let size2 = S.safe_int size2 in + (log2 (size2 + S.safe_int 1) * S.safe_int 22) + S.safe_int 80 + +(* model interpreter/N_ISet_update_synthesized *) +(* fun size1 -> + fun size2 -> + let time = + 49.8905426747 + (0.140036207663 * (size1 * (log2 (1 + size2)))) in + let alloc = (21.7417458006 * (log2 (1 + size2))) + 77.6256737848 in + max 10 (max time alloc) *) +let cost_N_ISet_update_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + let w3 = w1 * size1 in + S.max + ((w3 lsr 3) + (w3 lsr 6) + S.safe_int 50) + ((w1 * S.safe_int 22) + S.safe_int 80) + +(* model interpreter/N_ISha256 *) +(* fun size -> max 10 (600. + (4.75 * size)) *) +let cost_N_ISha256 size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 2) + (size * S.safe_int 4) + S.safe_int 600 + +(* model interpreter/N_ISha256_alloc *) +(* fun size -> max 10 24. *) +let cost_N_ISha256_alloc _size = S.safe_int 25 + +(* model interpreter/N_ISha256_synthesized *) +(* fun size -> + let time = 600. + (4.75 * size) in + let alloc = 24. in max 10 (max time alloc) *) +let cost_N_ISha256_synthesized size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 2) + (size * S.safe_int 4) + S.safe_int 600 + +(* model interpreter/N_ISha3 *) +(* fun size -> max 10 (1350. + (8.25 * size)) *) +let cost_N_ISha3 size = + let size = S.safe_int size in + (size lsr 2) + (size * S.safe_int 8) + S.safe_int 1350 + +(* model interpreter/N_ISha3_alloc *) +(* fun size -> max 10 24. *) +let cost_N_ISha3_alloc _size = S.safe_int 25 + +(* model interpreter/N_ISha3_synthesized *) +(* fun size -> + let time = 1350. + (8.25 * size) in + let alloc = 24. in max 10 (max time alloc) *) +let cost_N_ISha3_synthesized size = + let size = S.safe_int size in + (size lsr 2) + (size * S.safe_int 8) + S.safe_int 1350 + +(* model interpreter/N_ISha512 *) +(* fun size -> max 10 (680. + (3. * size)) *) +let cost_N_ISha512 size = + let size = S.safe_int size in + (size * S.safe_int 3) + S.safe_int 680 + +(* model interpreter/N_ISha512_alloc *) +(* fun size -> max 10 40. *) +let cost_N_ISha512_alloc _size = S.safe_int 40 + +(* model interpreter/N_ISha512_synthesized *) +(* fun size -> + let time = 680. + (3. * size) in + let alloc = 40. in max 10 (max time alloc) *) +let cost_N_ISha512_synthesized size = + let size = S.safe_int size in + (size * S.safe_int 3) + S.safe_int 680 + +(* model interpreter/N_ISlice_bytes *) +(* fun size -> max 10 (25. + (0.5 * size)) *) +let cost_N_ISlice_bytes size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 25 + +(* model interpreter/N_ISlice_bytes_alloc *) +(* fun size -> max 10 (14.6142328624 + (0.500160203859 * size)) *) +let cost_N_ISlice_bytes_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 15 + +(* model interpreter/N_ISlice_bytes_synthesized *) +(* fun size -> + let time = 25. + (0.5 * size) in + let alloc = 14.6142328624 + (0.500160203859 * size) in + max 10 (max time alloc) *) +let cost_N_ISlice_bytes_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 25) (w1 + (size lsr 6) + S.safe_int 15) + +(* model interpreter/N_ISlice_string *) +(* fun size -> max 10 (25. + (0.5 * size)) *) +let cost_N_ISlice_string size = + let size = S.safe_int size in + (size lsr 1) + S.safe_int 25 + +(* model interpreter/N_ISlice_string_alloc *) +(* fun size -> max 10 (15.686099896 + (0.500163489638 * size)) *) +let cost_N_ISlice_string_alloc size = + let size = S.safe_int size in + (size lsr 1) + (size lsr 6) + S.safe_int 20 + +(* model interpreter/N_ISlice_string_synthesized *) +(* fun size -> + let time = 25. + (0.5 * size) in + let alloc = 15.686099896 + (0.500163489638 * size) in + max 10 (max time alloc) *) +let cost_N_ISlice_string_synthesized size = + let size = S.safe_int size in + let w1 = size lsr 1 in + S.max (w1 + S.safe_int 25) (w1 + (size lsr 6) + S.safe_int 20) + +(* model interpreter/N_ISource *) +(* max 10 10. *) +let cost_N_ISource = S.safe_int 10 + +(* model interpreter/N_ISource_alloc *) +(* max 10 72. *) +let cost_N_ISource_alloc = S.safe_int 75 + +(* model interpreter/N_ISource_synthesized *) +(* let time = 10. in let alloc = 72. in max 10 (max time alloc) *) +let cost_N_ISource_synthesized = S.safe_int 75 + +(* model interpreter/N_ISplit_ticket *) +(* fun size1 -> fun size2 -> max 10 (40. + (0.5 * (max size1 size2))) *) +let cost_N_ISplit_ticket size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 40 + +(* model interpreter/N_ISplit_ticket_alloc *) +(* fun size1 -> fun size2 -> max 10 52. *) +let cost_N_ISplit_ticket_alloc _size1 _size2 = S.safe_int 55 + +(* model interpreter/N_ISplit_ticket_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 40. + (0.5 * (max size1 size2)) in + let alloc = 52. in max 10 (max time alloc) *) +let cost_N_ISplit_ticket_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + S.max ((S.max size1 size2 lsr 1) + S.safe_int 40) (S.safe_int 55) + +(* model interpreter/N_IString_size *) +(* max 10 15. *) +let cost_N_IString_size = S.safe_int 15 + +(* model interpreter/N_IString_size_alloc *) +(* max 10 0. *) +let cost_N_IString_size_alloc = S.safe_int 10 + +(* model interpreter/N_IString_size_synthesized *) +(* let time = 15. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IString_size_synthesized = S.safe_int 15 + +(* model interpreter/N_ISub_int *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_ISub_int size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_ISub_int_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (17.5501373306 + (0.500211925836 * (max size1 size2))) *) +let cost_N_ISub_int_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_ISub_int_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 17.5501373306 + (0.500211925836 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_ISub_int_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_ISub_tez *) +(* max 10 15. *) +let cost_N_ISub_tez = S.safe_int 15 + +(* model interpreter/N_ISub_tez_alloc *) +(* max 10 20. *) +let cost_N_ISub_tez_alloc = S.safe_int 20 + +(* model interpreter/N_ISub_tez_legacy *) +(* max 10 20. *) +let cost_N_ISub_tez_legacy = S.safe_int 20 + +(* model interpreter/N_ISub_tez_legacy_alloc *) +(* max 10 12. *) +let cost_N_ISub_tez_legacy_alloc = S.safe_int 15 + +(* model interpreter/N_ISub_tez_legacy_synthesized *) +(* let time = 20. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_ISub_tez_legacy_synthesized = S.safe_int 20 + +(* model interpreter/N_ISub_tez_synthesized *) +(* let time = 15. in let alloc = 20. in max 10 (max time alloc) *) +let cost_N_ISub_tez_synthesized = S.safe_int 20 + +(* model interpreter/N_ISub_timestamp_seconds *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_ISub_timestamp_seconds size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_ISub_timestamp_seconds_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (17.5501373306 + (0.500211925836 * (max size1 size2))) *) +let cost_N_ISub_timestamp_seconds_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 20 + +(* model interpreter/N_ISub_timestamp_seconds_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 17.5501373306 + (0.500211925836 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_ISub_timestamp_seconds_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 20) + +(* model interpreter/N_ISwap *) +(* max 10 10. *) +let cost_N_ISwap = S.safe_int 10 + +(* model interpreter/N_ISwap_alloc *) +(* max 10 12. *) +let cost_N_ISwap_alloc = S.safe_int 15 + +(* model interpreter/N_ISwap_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_ISwap_synthesized = S.safe_int 15 + +(* model interpreter/N_ITicket *) +(* max 10 10. *) +let cost_N_ITicket = S.safe_int 10 + +(* model interpreter/N_ITicket_alloc *) +(* max 10 56. *) +let cost_N_ITicket_alloc = S.safe_int 60 + +(* model interpreter/N_ITicket_synthesized *) +(* let time = 10. in let alloc = 56. in max 10 (max time alloc) *) +let cost_N_ITicket_synthesized = S.safe_int 60 + +(* model interpreter/N_ITotal_voting_power *) +(* max 10 450. *) +let cost_N_ITotal_voting_power = S.safe_int 450 + +(* model interpreter/N_ITotal_voting_power_alloc *) +(* max 10 12. *) +let cost_N_ITotal_voting_power_alloc = S.safe_int 15 + +(* model interpreter/N_ITotal_voting_power_synthesized *) +(* let time = 450. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_ITotal_voting_power_synthesized = S.safe_int 450 + +(* model interpreter/N_ITransfer_tokens_alloc *) +(* max 10 120. *) +let cost_N_ITransfer_tokens_alloc = S.safe_int 120 + +(* model interpreter/N_ITransfer_tokens_synthesized *) +(* let time = 60. in let alloc = 120. in max 10 (max time alloc) *) +let cost_N_ITransfer_tokens_synthesized = S.safe_int 120 + +(* model interpreter/N_IUncomb *) +(* fun size -> max 10 (30. + (4. * (sub size 2))) *) +let cost_N_IUncomb size = + let size = S.safe_int size in + (S.sub size (S.safe_int 2) * S.safe_int 4) + S.safe_int 30 + +(* model interpreter/N_IUncomb_alloc *) +(* fun size -> max 10 (6.30950568452 + (11.9815614243 * size)) *) +let cost_N_IUncomb_alloc size = + let size = S.safe_int size in + (size * S.safe_int 12) + S.safe_int 10 + +(* model interpreter/N_IUncomb_synthesized *) +(* fun size -> + let time = 30. + (4. * (sub size 2)) in + let alloc = 6.30950568452 + (11.9815614243 * size) in + max 10 (max time alloc) *) +let cost_N_IUncomb_synthesized size = + let size = S.safe_int size in + S.max + ((S.sub size (S.safe_int 2) * S.safe_int 4) + S.safe_int 30) + ((size * S.safe_int 12) + S.safe_int 10) + +(* model interpreter/N_IUnit *) +(* max 10 10. *) +let cost_N_IUnit = S.safe_int 10 + +(* model interpreter/N_IUnit_alloc *) +(* max 10 12. *) +let cost_N_IUnit_alloc = S.safe_int 15 + +(* model interpreter/N_IUnit_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IUnit_synthesized = S.safe_int 15 + +(* model interpreter/N_IUnpack_alloc *) +(* max 10 8. *) +let cost_N_IUnpack_alloc = S.safe_int 10 + +(* model interpreter/N_IUnpack_synthesized *) +(* let time = 278.760542675 in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_IUnpack_synthesized = S.safe_int 280 + +(* model interpreter/N_IUnpair *) +(* max 10 10. *) +let cost_N_IUnpair = S.safe_int 10 + +(* model interpreter/N_IUnpair_alloc *) +(* max 10 12. *) +let cost_N_IUnpair_alloc = S.safe_int 15 + +(* model interpreter/N_IUnpair_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_IUnpair_synthesized = S.safe_int 15 + +(* model interpreter/N_IView *) +(* max 10 1460. *) +let cost_N_IView = S.safe_int 1460 + +(* model interpreter/N_IView_alloc *) +(* max 10 0. *) +let cost_N_IView_alloc = S.safe_int 10 + +(* model interpreter/N_IView_synthesized *) +(* let time = 1460. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IView_synthesized = S.safe_int 1460 + +(* model interpreter/N_IVoting_power *) +(* max 10 640. *) +let cost_N_IVoting_power = S.safe_int 640 + +(* model interpreter/N_IVoting_power_alloc *) +(* max 10 0. *) +let cost_N_IVoting_power_alloc = S.safe_int 10 + +(* model interpreter/N_IVoting_power_synthesized *) +(* let time = 640. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IVoting_power_synthesized = S.safe_int 640 + +(* model interpreter/N_IXor *) +(* max 10 15. *) +let cost_N_IXor = S.safe_int 15 + +(* model interpreter/N_IXor_alloc *) +(* max 10 0. *) +let cost_N_IXor_alloc = S.safe_int 10 + +(* model interpreter/N_IXor_bytes *) +(* fun size1 -> fun size2 -> max 10 (40. + (0.5 * (max size1 size2))) *) +let cost_N_IXor_bytes size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 40 + +(* model interpreter/N_IXor_bytes_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (10.6873582322 + (0.499979321651 * (max size1 size2))) *) +let cost_N_IXor_bytes_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 15 + +(* model interpreter/N_IXor_bytes_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 40. + (0.5 * (max size1 size2)) in + let alloc = 10.6873582322 + (0.499979321651 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IXor_bytes_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 40 + +(* model interpreter/N_IXor_nat *) +(* fun size1 -> fun size2 -> max 10 (35. + (0.5 * (max size1 size2))) *) +let cost_N_IXor_nat size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (S.max size1 size2 lsr 1) + S.safe_int 35 + +(* model interpreter/N_IXor_nat_alloc *) +(* fun size1 -> + fun size2 -> + max 10 (13.9478780796 + (0.500186338819 * (max size1 size2))) *) +let cost_N_IXor_nat_alloc size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + (w1 lsr 1) + (w1 lsr 6) + S.safe_int 15 + +(* model interpreter/N_IXor_nat_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 35. + (0.5 * (max size1 size2)) in + let alloc = 13.9478780796 + (0.500186338819 * (max size1 size2)) in + max 10 (max time alloc) *) +let cost_N_IXor_nat_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = S.max size1 size2 in + let w2 = w1 lsr 1 in + S.max (w2 + S.safe_int 35) (w2 + (w1 lsr 6) + S.safe_int 15) + +(* model interpreter/N_IXor_synthesized *) +(* let time = 15. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_IXor_synthesized = S.safe_int 15 + +(* model interpreter/N_KCons *) +(* max 10 10. *) +let cost_N_KCons = S.safe_int 10 + +(* model interpreter/N_KCons_alloc *) +(* max 10 0. *) +let cost_N_KCons_alloc = S.safe_int 10 + +(* model interpreter/N_KCons_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KCons_synthesized = S.safe_int 10 + +(* model interpreter/N_KIter *) +(* max 10 (max 10. 10.) *) +let cost_N_KIter = S.safe_int 10 + +(* model interpreter/N_KIter_empty *) +(* max 10 10. *) +let cost_N_KIter_empty = S.safe_int 10 + +(* model interpreter/N_KIter_empty_alloc *) +(* max 10 0. *) +let cost_N_KIter_empty_alloc = S.safe_int 10 + +(* model interpreter/N_KIter_empty_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KIter_empty_synthesized = S.safe_int 10 + +(* model interpreter/N_KIter_nonempty *) +(* max 10 10. *) +let cost_N_KIter_nonempty = S.safe_int 10 + +(* model interpreter/N_KIter_nonempty_alloc *) +(* max 10 0. *) +let cost_N_KIter_nonempty_alloc = S.safe_int 10 + +(* model interpreter/N_KIter_nonempty_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KIter_nonempty_synthesized = S.safe_int 10 + +(* model interpreter/N_KList_enter_body_alloc *) +(* fun size_xs -> + fun size_ys -> + max 10 (if size_xs = 0 then 23. + (12.0014700944 * size_ys) else 0.) *) +let cost_N_KList_enter_body_alloc size_xs size_ys = + let size_xs = S.safe_int size_xs in + let size_ys = S.safe_int size_ys in + S.max + (S.safe_int 10) + (if size_xs = S.safe_int 0 then + (size_ys lsr 2) + (size_ys * S.safe_int 12) + S.safe_int 25 + else S.safe_int 0) + +(* model interpreter/N_KList_enter_body_synthesized *) +(* fun size_xs -> + fun size_ys -> + let time = if size_xs = 0 then 30. + (1.8125 * size_ys) else 30. in + let alloc = + if size_xs = 0 then 23. + (12.0014700944 * size_ys) else 0. in + max 10 (max time alloc) *) +let cost_N_KList_enter_body_synthesized size_xs size_ys = + let size_xs = S.safe_int size_xs in + let size_ys = S.safe_int size_ys in + let w1 = size_ys lsr 2 in + let w2 = size_xs = S.safe_int 0 in + S.max + (S.max + (S.safe_int 10) + (if w2 then + (size_ys lsr 1) + w1 + (size_ys lsr 4) + size_ys + S.safe_int 30 + else S.safe_int 30)) + (if w2 then w1 + (size_ys * S.safe_int 12) + S.safe_int 25 + else S.safe_int 0) + +(* model interpreter/N_KList_exit_body *) +(* max 10 10. *) +let cost_N_KList_exit_body = S.safe_int 10 + +(* model interpreter/N_KList_exit_body_alloc *) +(* max 10 0. *) +let cost_N_KList_exit_body_alloc = S.safe_int 10 + +(* model interpreter/N_KList_exit_body_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KList_exit_body_synthesized = S.safe_int 10 + +(* model interpreter/N_KLoop_in *) +(* max 10 10. *) +let cost_N_KLoop_in = S.safe_int 10 + +(* model interpreter/N_KLoop_in_alloc *) +(* max 10 0. *) +let cost_N_KLoop_in_alloc = S.safe_int 10 + +(* model interpreter/N_KLoop_in_left *) +(* max 10 10. *) +let cost_N_KLoop_in_left = S.safe_int 10 + +(* model interpreter/N_KLoop_in_left_alloc *) +(* max 10 0. *) +let cost_N_KLoop_in_left_alloc = S.safe_int 10 + +(* model interpreter/N_KLoop_in_left_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KLoop_in_left_synthesized = S.safe_int 10 + +(* model interpreter/N_KLoop_in_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KLoop_in_synthesized = S.safe_int 10 + +(* model interpreter/N_KMap_enter_body_alloc *) +(* fun size -> max 10 (if size = 0 then 11. else 0.) *) +let cost_N_KMap_enter_body_alloc size = + let size = S.safe_int size in + S.max + (S.safe_int 10) + (if size = S.safe_int 0 then S.safe_int 15 else S.safe_int 0) + +(* model interpreter/N_KMap_enter_body_synthesized *) +(* fun size -> + let time = if size = 0 then 10. else 80. in + let alloc = if size = 0 then 11. else 0. in max 10 (max time alloc) *) +let cost_N_KMap_enter_body_synthesized size = + let size = S.safe_int size in + let w1 = size = S.safe_int 0 in + S.max + (S.max (S.safe_int 10) (if w1 then S.safe_int 10 else S.safe_int 80)) + (if w1 then S.safe_int 15 else S.safe_int 0) + +(* model interpreter/N_KMap_exit_body *) +(* fun size1 -> + fun size2 -> + max 10 (0. + (0.114964427843 * (size1 * (log2 (1 + size2))))) *) +let cost_N_KMap_exit_body size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w3 = log2 (size2 + S.safe_int 1) * size1 in + S.max + (S.safe_int 10) + ((w3 lsr 4) + (w3 lsr 5) + (w3 lsr 6) + (w3 lsr 8) + (w3 lsr 9)) + +(* model interpreter/N_KMap_exit_body_alloc *) +(* fun size1 -> + fun size2 -> + max 10 ((28.3877828935 * (log2 (1 + size2))) + 74.4085101791) *) +let cost_N_KMap_exit_body_alloc _size1 size2 = + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + (w1 * S.safe_int 28) + (w1 lsr 1) + S.safe_int 75 + +(* model interpreter/N_KMap_exit_body_synthesized *) +(* fun size1 -> + fun size2 -> + let time = 0. + (0.114964427843 * (size1 * (log2 (1 + size2)))) in + let alloc = (28.3877828935 * (log2 (1 + size2))) + 74.4085101791 in + max 10 (max time alloc) *) +let cost_N_KMap_exit_body_synthesized size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let w1 = log2 (size2 + S.safe_int 1) in + let w3 = w1 * size1 in + S.max + ((w3 lsr 4) + (w3 lsr 5) + (w3 lsr 6) + (w3 lsr 8) + (w3 lsr 9)) + ((w1 * S.safe_int 28) + (w1 lsr 1) + S.safe_int 75) + +(* model interpreter/N_KMap_head *) +(* max 10 20. *) +let cost_N_KMap_head = S.safe_int 20 + +(* model interpreter/N_KMap_head_alloc *) +(* max 10 8. *) +let cost_N_KMap_head_alloc = S.safe_int 10 + +(* model interpreter/N_KMap_head_synthesized *) +(* let time = 20. in let alloc = 8. in max 10 (max time alloc) *) +let cost_N_KMap_head_synthesized = S.safe_int 20 + +(* model interpreter/N_KNil *) +(* max 10 15. *) +let cost_N_KNil = S.safe_int 15 + +(* model interpreter/N_KNil_alloc *) +(* max 10 0. *) +let cost_N_KNil_alloc = S.safe_int 10 + +(* model interpreter/N_KNil_synthesized *) +(* let time = 15. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KNil_synthesized = S.safe_int 15 + +(* model interpreter/N_KReturn *) +(* max 10 10. *) +let cost_N_KReturn = S.safe_int 10 + +(* model interpreter/N_KReturn_alloc *) +(* max 10 0. *) +let cost_N_KReturn_alloc = S.safe_int 10 + +(* model interpreter/N_KReturn_synthesized *) +(* let time = 10. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KReturn_synthesized = S.safe_int 10 + +(* model interpreter/N_KUndip *) +(* max 10 10. *) +let cost_N_KUndip = S.safe_int 10 + +(* model interpreter/N_KUndip_alloc *) +(* max 10 12. *) +let cost_N_KUndip_alloc = S.safe_int 15 + +(* model interpreter/N_KUndip_synthesized *) +(* let time = 10. in let alloc = 12. in max 10 (max time alloc) *) +let cost_N_KUndip_synthesized = S.safe_int 15 + +(* model interpreter/N_KView_exit *) +(* max 10 20. *) +let cost_N_KView_exit = S.safe_int 20 + +(* model interpreter/N_KView_exit_alloc *) +(* max 10 0. *) +let cost_N_KView_exit_alloc = S.safe_int 10 + +(* model interpreter/N_KView_exit_synthesized *) +(* let time = 20. in let alloc = 0. in max 10 (max time alloc) *) +let cost_N_KView_exit_synthesized = S.safe_int 20 + +(* model interpreter/amplification_loop_model *) +(* fun size -> max 10 (0.329309341324 * size) *) +let cost_amplification_loop_model size = + let size = S.safe_int size in + S.max + (S.safe_int 10) + ((size lsr 2) + (size lsr 4) + (size lsr 6) + (size lsr 7)) + +(* model translator/PARSE_TYPE *) +(* fun size -> max 10 (0. + (60. * size)) *) +let cost_PARSE_TYPE size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 60) + +(* model translator/Parsing_Code_gas *) +(* fun size -> max 10 (0. + (0.890391244567 * size)) *) +let cost_Parsing_Code_gas size = + let size = S.safe_int size in + S.max + (S.safe_int 10) + ((size lsr 1) + (size lsr 2) + (size lsr 3) + (size lsr 6)) + +(* model translator/Parsing_Code_size *) +(* fun size1 -> + fun size2 -> + fun size3 -> + max 10 (((187.300458967 * size1) + (0. * size2)) + (0. * size3)) *) +let cost_Parsing_Code_size size1 _size2 _size3 = + let size1 = S.safe_int size1 in + S.max (S.safe_int 10) (size1 * S.safe_int 188) + +(* model translator/Parsing_Data_gas *) +(* fun size -> max 10 (67277.397394 + (0.142972986751 * size)) *) +let cost_Parsing_Data_gas size = + let size = S.safe_int size in + (size lsr 3) + (size lsr 6) + (size lsr 8) + S.safe_int 67280 + +(* model translator/Parsing_Data_size *) +(* fun size1 -> + fun size2 -> + fun size3 -> + max 10 + (((80.363444899 * size1) + (16.1426805777 * size2)) + + (68.9487320686 * size3)) *) +let cost_Parsing_Data_size size1 size2 size3 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + let size3 = S.safe_int size3 in + S.max + (S.safe_int 10) + ((size2 lsr 1) + + (size1 * S.safe_int 82) + + (size2 * S.safe_int 16) + + (size3 * S.safe_int 70)) + +(* model translator/TY_EQ *) +(* fun size -> max 10 (31.1882471167 + (21.8805791266 * size)) *) +let cost_TY_EQ size = (size * S.safe_int 22) + S.safe_int 35 + +(* model translator/UNPARSE_TYPE *) +(* fun size -> max 10 (0. + (20. * size)) *) +let cost_UNPARSE_TYPE size = S.max (S.safe_int 10) (size * S.safe_int 20) + +(* model translator/Unparsing_Code_gas *) +(* fun size -> max 10 (0. + (0.592309924661 * size)) *) +let cost_Unparsing_Code_gas size = + let size = S.safe_int size in + S.max (S.safe_int 10) ((size lsr 1) + (size lsr 4) + (size lsr 5)) + +(* model translator/Unparsing_Code_size *) +(* fun size1 -> + fun size2 -> + fun size3 -> + max 10 (((124.72642512 * size1) + (0. * size2)) + (0. * size3)) *) +let cost_Unparsing_Code_size size1 _size2 _size3 = + let size1 = S.safe_int size1 in + S.max (S.safe_int 10) (size1 * S.safe_int 126) + +(* model translator/Unparsing_Data_gas *) +(* fun size -> max 10 (31944.7865384 + (0.033862305692 * size)) *) +let cost_Unparsing_Data_gas size = + let size = S.safe_int size in + (size lsr 5) + (size lsr 9) + (size lsr 10) + S.safe_int 31945 + +(* model translator/Unparsing_Data_size *) +(* fun size1 -> + fun size2 -> + fun size3 -> + max 10 (((54.8706646933 * size1) + (0. * size2)) + (0. * size3)) *) +let cost_Unparsing_Data_size size1 _size2 _size3 = + let size1 = S.safe_int size1 in + S.max (S.safe_int 10) (size1 * S.safe_int 55) diff --git a/src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.ml b/src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.ml new file mode 100644 index 000000000000..1b370589413e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.ml @@ -0,0 +1,850 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Micheline + +type error += Unknown_primitive_name of string + +type error += Invalid_case of string + +type error += + | Invalid_primitive_name of + string Micheline.canonical * Micheline.canonical_location + +type prim = + | K_parameter + | K_storage + | K_code + | K_view + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | D_Ticket + | D_Lambda_rec + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_VIEW + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LAMBDA_REC + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_MIN_BLOCK_TIME + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SELF_ADDRESS + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SUB_MUTEZ + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE + | I_XOR + | I_ITER + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_DIG + | I_DUG + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_TICKET_DEPRECATED + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | I_OPEN_CHEST + | I_EMIT + | I_BYTES + | I_NAT + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_tx_rollup_l2_address + | T_sapling_transaction + | T_sapling_transaction_deprecated + | T_sapling_state + | T_chain_id + | T_never + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + | T_chest_key + | T_chest + | H_constant + +(* Auxiliary types for error documentation. + All the prim constructor prefixes must match their namespace. *) +type namespace = + | (* prefix "T" *) Type_namespace + | (* prefix "D" *) Constant_namespace + | (* prefix "I" *) Instr_namespace + | (* prefix "K" *) Keyword_namespace + | (* prefix "H" *) Constant_hash_namespace + +let namespace = function + | K_code | K_view | K_parameter | K_storage -> Keyword_namespace + | D_Elt | D_False | D_Left | D_None | D_Pair | D_Right | D_Some | D_True + | D_Unit | D_Lambda_rec | D_Ticket -> + Constant_namespace + | I_ABS | I_ADD | I_ADDRESS | I_AMOUNT | I_AND | I_APPLY | I_BALANCE + | I_BLAKE2B | I_CAR | I_CAST | I_CDR | I_CHAIN_ID | I_CHECK_SIGNATURE + | I_COMPARE | I_CONCAT | I_CONS | I_CONTRACT | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT | I_DIG | I_DIP | I_DROP | I_DUG | I_DUP | I_VIEW | I_EDIV + | I_EMPTY_BIG_MAP | I_EMPTY_MAP | I_EMPTY_SET | I_EQ | I_EXEC | I_FAILWITH + | I_GE | I_GET | I_GET_AND_UPDATE | I_GT | I_HASH_KEY | I_IF | I_IF_CONS + | I_IF_LEFT | I_IF_NONE | I_IMPLICIT_ACCOUNT | I_INT | I_ISNAT | I_ITER + | I_JOIN_TICKETS | I_KECCAK | I_LAMBDA | I_LAMBDA_REC | I_LE | I_LEFT + | I_LEVEL | I_LOOP | I_LOOP_LEFT | I_LSL | I_LSR | I_LT | I_MAP | I_MEM + | I_MUL | I_NEG | I_NEQ | I_NEVER | I_NIL | I_NONE | I_NOT | I_NOW + | I_MIN_BLOCK_TIME | I_OR | I_PACK | I_PAIR | I_PAIRING_CHECK | I_PUSH + | I_READ_TICKET | I_RENAME | I_RIGHT | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE | I_SELF | I_SELF_ADDRESS | I_SENDER + | I_SET_DELEGATE | I_SHA256 | I_SHA512 | I_SHA3 | I_SIZE | I_SLICE | I_SOME + | I_SOURCE | I_SPLIT_TICKET | I_STEPS_TO_QUOTA | I_SUB | I_SUB_MUTEZ | I_SWAP + | I_TICKET | I_TICKET_DEPRECATED | I_TOTAL_VOTING_POWER | I_TRANSFER_TOKENS + | I_UNIT | I_UNPACK | I_UNPAIR | I_UPDATE | I_VOTING_POWER | I_XOR + | I_OPEN_CHEST | I_EMIT | I_BYTES | I_NAT -> + Instr_namespace + | T_address | T_tx_rollup_l2_address | T_big_map | T_bool | T_bytes + | T_chain_id | T_contract | T_int | T_key | T_key_hash | T_lambda | T_list + | T_map | T_mutez | T_nat | T_never | T_operation | T_option | T_or | T_pair + | T_sapling_state | T_sapling_transaction | T_sapling_transaction_deprecated + | T_set | T_signature | T_string | T_timestamp | T_unit | T_bls12_381_fr + | T_bls12_381_g1 | T_bls12_381_g2 | T_ticket | T_chest_key | T_chest -> + Type_namespace + | H_constant -> Constant_hash_namespace + +let valid_case name = + let is_lower = function '_' | 'a' .. 'z' -> true | _ -> false in + let is_upper = function '_' | 'A' .. 'Z' -> true | _ -> false in + let rec for_all a b f = Compare.Int.(a > b) || (f a && for_all (a + 1) b f) in + let len = String.length name in + Compare.Int.(len <> 0) + && Compare.Char.(name.[0] <> '_') + && ((is_upper name.[0] && for_all 1 (len - 1) (fun i -> is_upper name.[i])) + || (is_upper name.[0] && for_all 1 (len - 1) (fun i -> is_lower name.[i])) + || (is_lower name.[0] && for_all 1 (len - 1) (fun i -> is_lower name.[i])) + ) + +let string_of_prim = function + | K_parameter -> "parameter" + | K_storage -> "storage" + | K_code -> "code" + | K_view -> "view" + | D_False -> "False" + | D_Elt -> "Elt" + | D_Left -> "Left" + | D_None -> "None" + | D_Pair -> "Pair" + | D_Right -> "Right" + | D_Some -> "Some" + | D_True -> "True" + | D_Unit -> "Unit" + | D_Ticket -> "Ticket" + | D_Lambda_rec -> "Lambda_rec" + | I_PACK -> "PACK" + | I_UNPACK -> "UNPACK" + | I_BLAKE2B -> "BLAKE2B" + | I_SHA256 -> "SHA256" + | I_SHA512 -> "SHA512" + | I_ABS -> "ABS" + | I_ADD -> "ADD" + | I_AMOUNT -> "AMOUNT" + | I_AND -> "AND" + | I_BALANCE -> "BALANCE" + | I_CAR -> "CAR" + | I_CDR -> "CDR" + | I_CHAIN_ID -> "CHAIN_ID" + | I_CHECK_SIGNATURE -> "CHECK_SIGNATURE" + | I_COMPARE -> "COMPARE" + | I_CONCAT -> "CONCAT" + | I_CONS -> "CONS" + | I_CREATE_ACCOUNT -> "CREATE_ACCOUNT" + | I_CREATE_CONTRACT -> "CREATE_CONTRACT" + | I_IMPLICIT_ACCOUNT -> "IMPLICIT_ACCOUNT" + | I_DIP -> "DIP" + | I_DROP -> "DROP" + | I_DUP -> "DUP" + | I_EDIV -> "EDIV" + | I_EMPTY_BIG_MAP -> "EMPTY_BIG_MAP" + | I_EMPTY_MAP -> "EMPTY_MAP" + | I_EMPTY_SET -> "EMPTY_SET" + | I_EQ -> "EQ" + | I_EXEC -> "EXEC" + | I_APPLY -> "APPLY" + | I_FAILWITH -> "FAILWITH" + | I_GE -> "GE" + | I_GET -> "GET" + | I_GET_AND_UPDATE -> "GET_AND_UPDATE" + | I_GT -> "GT" + | I_HASH_KEY -> "HASH_KEY" + | I_IF -> "IF" + | I_IF_CONS -> "IF_CONS" + | I_IF_LEFT -> "IF_LEFT" + | I_IF_NONE -> "IF_NONE" + | I_INT -> "INT" + | I_LAMBDA -> "LAMBDA" + | I_LAMBDA_REC -> "LAMBDA_REC" + | I_LE -> "LE" + | I_LEFT -> "LEFT" + | I_LEVEL -> "LEVEL" + | I_LOOP -> "LOOP" + | I_LSL -> "LSL" + | I_LSR -> "LSR" + | I_LT -> "LT" + | I_MAP -> "MAP" + | I_MEM -> "MEM" + | I_MUL -> "MUL" + | I_NEG -> "NEG" + | I_NEQ -> "NEQ" + | I_NIL -> "NIL" + | I_NONE -> "NONE" + | I_NOT -> "NOT" + | I_NOW -> "NOW" + | I_MIN_BLOCK_TIME -> "MIN_BLOCK_TIME" + | I_OR -> "OR" + | I_PAIR -> "PAIR" + | I_PUSH -> "PUSH" + | I_RIGHT -> "RIGHT" + | I_SIZE -> "SIZE" + | I_SOME -> "SOME" + | I_SOURCE -> "SOURCE" + | I_SENDER -> "SENDER" + | I_SELF -> "SELF" + | I_SELF_ADDRESS -> "SELF_ADDRESS" + | I_SLICE -> "SLICE" + | I_STEPS_TO_QUOTA -> "STEPS_TO_QUOTA" + | I_SUB -> "SUB" + | I_SUB_MUTEZ -> "SUB_MUTEZ" + | I_SWAP -> "SWAP" + | I_TRANSFER_TOKENS -> "TRANSFER_TOKENS" + | I_SET_DELEGATE -> "SET_DELEGATE" + | I_UNIT -> "UNIT" + | I_UNPAIR -> "UNPAIR" + | I_UPDATE -> "UPDATE" + | I_XOR -> "XOR" + | I_ITER -> "ITER" + | I_LOOP_LEFT -> "LOOP_LEFT" + | I_ADDRESS -> "ADDRESS" + | I_CONTRACT -> "CONTRACT" + | I_ISNAT -> "ISNAT" + | I_CAST -> "CAST" + | I_RENAME -> "RENAME" + | I_SAPLING_EMPTY_STATE -> "SAPLING_EMPTY_STATE" + | I_SAPLING_VERIFY_UPDATE -> "SAPLING_VERIFY_UPDATE" + | I_DIG -> "DIG" + | I_DUG -> "DUG" + | I_NEVER -> "NEVER" + | I_VOTING_POWER -> "VOTING_POWER" + | I_TOTAL_VOTING_POWER -> "TOTAL_VOTING_POWER" + | I_KECCAK -> "KECCAK" + | I_SHA3 -> "SHA3" + | I_PAIRING_CHECK -> "PAIRING_CHECK" + | I_TICKET -> "TICKET" + | I_TICKET_DEPRECATED -> "TICKET_DEPRECATED" + | I_READ_TICKET -> "READ_TICKET" + | I_SPLIT_TICKET -> "SPLIT_TICKET" + | I_JOIN_TICKETS -> "JOIN_TICKETS" + | I_OPEN_CHEST -> "OPEN_CHEST" + | I_EMIT -> "EMIT" + | I_VIEW -> "VIEW" + | I_BYTES -> "BYTES" + | I_NAT -> "NAT" + | T_bool -> "bool" + | T_contract -> "contract" + | T_int -> "int" + | T_key -> "key" + | T_key_hash -> "key_hash" + | T_lambda -> "lambda" + | T_list -> "list" + | T_map -> "map" + | T_big_map -> "big_map" + | T_nat -> "nat" + | T_option -> "option" + | T_or -> "or" + | T_pair -> "pair" + | T_set -> "set" + | T_signature -> "signature" + | T_string -> "string" + | T_bytes -> "bytes" + | T_mutez -> "mutez" + | T_timestamp -> "timestamp" + | T_unit -> "unit" + | T_operation -> "operation" + | T_address -> "address" + | T_tx_rollup_l2_address -> "tx_rollup_l2_address" + | T_sapling_state -> "sapling_state" + | T_sapling_transaction -> "sapling_transaction" + | T_sapling_transaction_deprecated -> "sapling_transaction_deprecated" + | T_chain_id -> "chain_id" + | T_never -> "never" + | T_bls12_381_g1 -> "bls12_381_g1" + | T_bls12_381_g2 -> "bls12_381_g2" + | T_bls12_381_fr -> "bls12_381_fr" + | T_ticket -> "ticket" + | T_chest_key -> "chest_key" + | T_chest -> "chest" + | H_constant -> "constant" + +let prim_of_string = + let open Result_syntax in + function + | "parameter" -> return K_parameter + | "storage" -> return K_storage + | "code" -> return K_code + | "view" -> return K_view + | "False" -> return D_False + | "Elt" -> return D_Elt + | "Left" -> return D_Left + | "None" -> return D_None + | "Pair" -> return D_Pair + | "Right" -> return D_Right + | "Some" -> return D_Some + | "True" -> return D_True + | "Unit" -> return D_Unit + | "Ticket" -> return D_Ticket + | "Lambda_rec" -> return D_Lambda_rec + | "PACK" -> return I_PACK + | "UNPACK" -> return I_UNPACK + | "BLAKE2B" -> return I_BLAKE2B + | "SHA256" -> return I_SHA256 + | "SHA512" -> return I_SHA512 + | "ABS" -> return I_ABS + | "ADD" -> return I_ADD + | "AMOUNT" -> return I_AMOUNT + | "AND" -> return I_AND + | "BALANCE" -> return I_BALANCE + | "CAR" -> return I_CAR + | "CDR" -> return I_CDR + | "CHAIN_ID" -> return I_CHAIN_ID + | "CHECK_SIGNATURE" -> return I_CHECK_SIGNATURE + | "COMPARE" -> return I_COMPARE + | "CONCAT" -> return I_CONCAT + | "CONS" -> return I_CONS + | "CREATE_ACCOUNT" -> return I_CREATE_ACCOUNT + | "CREATE_CONTRACT" -> return I_CREATE_CONTRACT + | "IMPLICIT_ACCOUNT" -> return I_IMPLICIT_ACCOUNT + | "DIP" -> return I_DIP + | "DROP" -> return I_DROP + | "DUP" -> return I_DUP + | "VIEW" -> return I_VIEW + | "EDIV" -> return I_EDIV + | "EMPTY_BIG_MAP" -> return I_EMPTY_BIG_MAP + | "EMPTY_MAP" -> return I_EMPTY_MAP + | "EMPTY_SET" -> return I_EMPTY_SET + | "EQ" -> return I_EQ + | "EXEC" -> return I_EXEC + | "APPLY" -> return I_APPLY + | "FAILWITH" -> return I_FAILWITH + | "GE" -> return I_GE + | "GET" -> return I_GET + | "GET_AND_UPDATE" -> return I_GET_AND_UPDATE + | "GT" -> return I_GT + | "HASH_KEY" -> return I_HASH_KEY + | "IF" -> return I_IF + | "IF_CONS" -> return I_IF_CONS + | "IF_LEFT" -> return I_IF_LEFT + | "IF_NONE" -> return I_IF_NONE + | "INT" -> return I_INT + | "KECCAK" -> return I_KECCAK + | "LAMBDA" -> return I_LAMBDA + | "LAMBDA_REC" -> return I_LAMBDA_REC + | "LE" -> return I_LE + | "LEFT" -> return I_LEFT + | "LEVEL" -> return I_LEVEL + | "LOOP" -> return I_LOOP + | "LSL" -> return I_LSL + | "LSR" -> return I_LSR + | "LT" -> return I_LT + | "MAP" -> return I_MAP + | "MEM" -> return I_MEM + | "MUL" -> return I_MUL + | "NEG" -> return I_NEG + | "NEQ" -> return I_NEQ + | "NIL" -> return I_NIL + | "NONE" -> return I_NONE + | "NOT" -> return I_NOT + | "NOW" -> return I_NOW + | "MIN_BLOCK_TIME" -> return I_MIN_BLOCK_TIME + | "OR" -> return I_OR + | "PAIR" -> return I_PAIR + | "UNPAIR" -> return I_UNPAIR + | "PAIRING_CHECK" -> return I_PAIRING_CHECK + | "PUSH" -> return I_PUSH + | "RIGHT" -> return I_RIGHT + | "SHA3" -> return I_SHA3 + | "SIZE" -> return I_SIZE + | "SOME" -> return I_SOME + | "SOURCE" -> return I_SOURCE + | "SENDER" -> return I_SENDER + | "SELF" -> return I_SELF + | "SELF_ADDRESS" -> return I_SELF_ADDRESS + | "SLICE" -> return I_SLICE + | "STEPS_TO_QUOTA" -> return I_STEPS_TO_QUOTA + | "SUB" -> return I_SUB + | "SUB_MUTEZ" -> return I_SUB_MUTEZ + | "SWAP" -> return I_SWAP + | "TRANSFER_TOKENS" -> return I_TRANSFER_TOKENS + | "SET_DELEGATE" -> return I_SET_DELEGATE + | "UNIT" -> return I_UNIT + | "UPDATE" -> return I_UPDATE + | "XOR" -> return I_XOR + | "ITER" -> return I_ITER + | "LOOP_LEFT" -> return I_LOOP_LEFT + | "ADDRESS" -> return I_ADDRESS + | "CONTRACT" -> return I_CONTRACT + | "ISNAT" -> return I_ISNAT + | "CAST" -> return I_CAST + | "RENAME" -> return I_RENAME + | "SAPLING_EMPTY_STATE" -> return I_SAPLING_EMPTY_STATE + | "SAPLING_VERIFY_UPDATE" -> return I_SAPLING_VERIFY_UPDATE + | "DIG" -> return I_DIG + | "DUG" -> return I_DUG + | "NEVER" -> return I_NEVER + | "VOTING_POWER" -> return I_VOTING_POWER + | "TOTAL_VOTING_POWER" -> return I_TOTAL_VOTING_POWER + | "TICKET" -> return I_TICKET + | "TICKET_DEPRECATED" -> return I_TICKET_DEPRECATED + | "READ_TICKET" -> return I_READ_TICKET + | "SPLIT_TICKET" -> return I_SPLIT_TICKET + | "JOIN_TICKETS" -> return I_JOIN_TICKETS + | "OPEN_CHEST" -> return I_OPEN_CHEST + | "EMIT" -> return I_EMIT + | "BYTES" -> return I_BYTES + | "NAT" -> return I_NAT + | "bool" -> return T_bool + | "contract" -> return T_contract + | "int" -> return T_int + | "key" -> return T_key + | "key_hash" -> return T_key_hash + | "lambda" -> return T_lambda + | "list" -> return T_list + | "map" -> return T_map + | "big_map" -> return T_big_map + | "nat" -> return T_nat + | "option" -> return T_option + | "or" -> return T_or + | "pair" -> return T_pair + | "set" -> return T_set + | "signature" -> return T_signature + | "string" -> return T_string + | "bytes" -> return T_bytes + | "mutez" -> return T_mutez + | "timestamp" -> return T_timestamp + | "unit" -> return T_unit + | "operation" -> return T_operation + | "address" -> return T_address + | "tx_rollup_l2_address" -> return T_tx_rollup_l2_address + | "sapling_state" -> return T_sapling_state + | "sapling_transaction" -> return T_sapling_transaction + | "sapling_transaction_deprecated" -> return T_sapling_transaction_deprecated + | "chain_id" -> return T_chain_id + | "never" -> return T_never + | "bls12_381_g1" -> return T_bls12_381_g1 + | "bls12_381_g2" -> return T_bls12_381_g2 + | "bls12_381_fr" -> return T_bls12_381_fr + | "ticket" -> return T_ticket + | "chest_key" -> return T_chest_key + | "chest" -> return T_chest + | "constant" -> return H_constant + | n -> + if valid_case n then tzfail (Unknown_primitive_name n) + else tzfail (Invalid_case n) + +let prims_of_strings expr = + let open Result_syntax in + let rec convert = function + | (Int _ | String _ | Bytes _) as expr -> return expr + | Prim (loc, prim, args, annot) -> + let* prim = + Error_monad.record_trace + (Invalid_primitive_name (expr, loc)) + (prim_of_string prim) + in + let+ args = List.map_e convert args in + Prim (loc, prim, args, annot) + | Seq (loc, args) -> + let+ args = List.map_e convert args in + Seq (loc, args) + in + let+ expr = convert (root expr) in + strip_locations expr + +let strings_of_prims expr = + let rec convert = function + | (Int _ | String _ | Bytes _) as expr -> expr + | Prim (loc, prim, args, annot) -> + let prim = string_of_prim prim in + let args = List.map convert args in + Prim (loc, prim, args, annot) + | Seq (loc, args) -> + let args = List.map convert args in + Seq (loc, args) + in + strip_locations (convert (root expr)) + +let prim_encoding = + let open Data_encoding in + def "michelson.v1.primitives" + @@ string_enum + (* Add the comment below every 10 lines *) + [ + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("parameter", K_parameter); + ("storage", K_storage); + ("code", K_code); + ("False", D_False); + ("Elt", D_Elt); + ("Left", D_Left); + ("None", D_None); + ("Pair", D_Pair); + ("Right", D_Right); + ("Some", D_Some); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("True", D_True); + ("Unit", D_Unit); + ("PACK", I_PACK); + ("UNPACK", I_UNPACK); + ("BLAKE2B", I_BLAKE2B); + ("SHA256", I_SHA256); + ("SHA512", I_SHA512); + ("ABS", I_ABS); + ("ADD", I_ADD); + ("AMOUNT", I_AMOUNT); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("AND", I_AND); + ("BALANCE", I_BALANCE); + ("CAR", I_CAR); + ("CDR", I_CDR); + ("CHECK_SIGNATURE", I_CHECK_SIGNATURE); + ("COMPARE", I_COMPARE); + ("CONCAT", I_CONCAT); + ("CONS", I_CONS); + ("CREATE_ACCOUNT", I_CREATE_ACCOUNT); + ("CREATE_CONTRACT", I_CREATE_CONTRACT); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("IMPLICIT_ACCOUNT", I_IMPLICIT_ACCOUNT); + ("DIP", I_DIP); + ("DROP", I_DROP); + ("DUP", I_DUP); + ("EDIV", I_EDIV); + ("EMPTY_MAP", I_EMPTY_MAP); + ("EMPTY_SET", I_EMPTY_SET); + ("EQ", I_EQ); + ("EXEC", I_EXEC); + ("FAILWITH", I_FAILWITH); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("GE", I_GE); + ("GET", I_GET); + ("GT", I_GT); + ("HASH_KEY", I_HASH_KEY); + ("IF", I_IF); + ("IF_CONS", I_IF_CONS); + ("IF_LEFT", I_IF_LEFT); + ("IF_NONE", I_IF_NONE); + ("INT", I_INT); + ("LAMBDA", I_LAMBDA); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("LE", I_LE); + ("LEFT", I_LEFT); + ("LOOP", I_LOOP); + ("LSL", I_LSL); + ("LSR", I_LSR); + ("LT", I_LT); + ("MAP", I_MAP); + ("MEM", I_MEM); + ("MUL", I_MUL); + ("NEG", I_NEG); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("NEQ", I_NEQ); + ("NIL", I_NIL); + ("NONE", I_NONE); + ("NOT", I_NOT); + ("NOW", I_NOW); + ("OR", I_OR); + ("PAIR", I_PAIR); + ("PUSH", I_PUSH); + ("RIGHT", I_RIGHT); + ("SIZE", I_SIZE); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("SOME", I_SOME); + ("SOURCE", I_SOURCE); + ("SENDER", I_SENDER); + ("SELF", I_SELF); + ("STEPS_TO_QUOTA", I_STEPS_TO_QUOTA); + ("SUB", I_SUB); + ("SWAP", I_SWAP); + ("TRANSFER_TOKENS", I_TRANSFER_TOKENS); + ("SET_DELEGATE", I_SET_DELEGATE); + ("UNIT", I_UNIT); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("UPDATE", I_UPDATE); + ("XOR", I_XOR); + ("ITER", I_ITER); + ("LOOP_LEFT", I_LOOP_LEFT); + ("ADDRESS", I_ADDRESS); + ("CONTRACT", I_CONTRACT); + ("ISNAT", I_ISNAT); + ("CAST", I_CAST); + ("RENAME", I_RENAME); + ("bool", T_bool); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("contract", T_contract); + ("int", T_int); + ("key", T_key); + ("key_hash", T_key_hash); + ("lambda", T_lambda); + ("list", T_list); + ("map", T_map); + ("big_map", T_big_map); + ("nat", T_nat); + ("option", T_option); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("or", T_or); + ("pair", T_pair); + ("set", T_set); + ("signature", T_signature); + ("string", T_string); + ("bytes", T_bytes); + ("mutez", T_mutez); + ("timestamp", T_timestamp); + ("unit", T_unit); + ("operation", T_operation); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("address", T_address); + (* Alpha_002 addition *) + ("SLICE", I_SLICE); + (* Alpha_005 addition *) + ("DIG", I_DIG); + ("DUG", I_DUG); + ("EMPTY_BIG_MAP", I_EMPTY_BIG_MAP); + ("APPLY", I_APPLY); + ("chain_id", T_chain_id); + ("CHAIN_ID", I_CHAIN_ID); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_008 addition *) + ("LEVEL", I_LEVEL); + ("SELF_ADDRESS", I_SELF_ADDRESS); + ("never", T_never); + ("NEVER", I_NEVER); + ("UNPAIR", I_UNPAIR); + ("VOTING_POWER", I_VOTING_POWER); + ("TOTAL_VOTING_POWER", I_TOTAL_VOTING_POWER); + ("KECCAK", I_KECCAK); + ("SHA3", I_SHA3); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_008 addition *) + ("PAIRING_CHECK", I_PAIRING_CHECK); + ("bls12_381_g1", T_bls12_381_g1); + ("bls12_381_g2", T_bls12_381_g2); + ("bls12_381_fr", T_bls12_381_fr); + ("sapling_state", T_sapling_state); + ("sapling_transaction_deprecated", T_sapling_transaction_deprecated); + ("SAPLING_EMPTY_STATE", I_SAPLING_EMPTY_STATE); + ("SAPLING_VERIFY_UPDATE", I_SAPLING_VERIFY_UPDATE); + ("ticket", T_ticket); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_008 addition *) + ("TICKET_DEPRECATED", I_TICKET_DEPRECATED); + ("READ_TICKET", I_READ_TICKET); + ("SPLIT_TICKET", I_SPLIT_TICKET); + ("JOIN_TICKETS", I_JOIN_TICKETS); + ("GET_AND_UPDATE", I_GET_AND_UPDATE); + (* Alpha_011 addition *) + ("chest", T_chest); + ("chest_key", T_chest_key); + ("OPEN_CHEST", I_OPEN_CHEST); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + ("VIEW", I_VIEW); + ("view", K_view); + ("constant", H_constant); + (* Alpha_012 addition *) + ("SUB_MUTEZ", I_SUB_MUTEZ); + (* Alpha_013 addition *) + ("tx_rollup_l2_address", T_tx_rollup_l2_address); + ("MIN_BLOCK_TIME", I_MIN_BLOCK_TIME); + ("sapling_transaction", T_sapling_transaction); + (* /!\ NEW INSTRUCTIONS MUST BE ADDED AT THE END OF THE STRING_ENUM, FOR BACKWARD COMPATIBILITY OF THE ENCODING. *) + (* Alpha_014 addition *) + ("EMIT", I_EMIT); + (* Alpha_015 addition *) + ("Lambda_rec", D_Lambda_rec); + ("LAMBDA_REC", I_LAMBDA_REC); + ("TICKET", I_TICKET); + ("BYTES", I_BYTES); + ("NAT", I_NAT); + (* Alpha_019 addition *) + ("Ticket", D_Ticket); + (* New instructions must be added here, for backward compatibility of the encoding. *) + (* Keep the comment above at the end of the list *) + ] + +let () = + register_error_kind + `Permanent + ~id:"michelson_v1.unknown_primitive_name" + ~title:"Unknown primitive name" + ~description:"In a script or data expression, a primitive was unknown." + ~pp:(fun ppf n -> Format.fprintf ppf "Unknown primitive %s." n) + Data_encoding.(obj1 (req "wrong_primitive_name" @@ string Plain)) + (function Unknown_primitive_name got -> Some got | _ -> None) + (fun got -> Unknown_primitive_name got) ; + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive_name_case" + ~title:"Invalid primitive name case" + ~description: + "In a script or data expression, a primitive name is neither uppercase, \ + lowercase or capitalized." + ~pp:(fun ppf n -> Format.fprintf ppf "Primitive %s has invalid case." n) + Data_encoding.(obj1 (req "wrong_primitive_name" @@ string Plain)) + (function Invalid_case name -> Some name | _ -> None) + (fun name -> Invalid_case name) ; + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive_name" + ~title:"Invalid primitive name" + ~description: + "In a script or data expression, a primitive name is unknown or has a \ + wrong case." + ~pp:(fun ppf _ -> Format.fprintf ppf "Invalid primitive.") + Data_encoding.( + obj2 + (req + "expression" + (Micheline.canonical_encoding ~variant:"generic" @@ string Plain)) + (req "location" Micheline.canonical_location_encoding)) + (function + | Invalid_primitive_name (expr, loc) -> Some (expr, loc) | _ -> None) + (fun (expr, loc) -> Invalid_primitive_name (expr, loc)) + +let string_of_namespace = function + | Type_namespace -> "T" + | Constant_namespace -> "D" + | Instr_namespace -> "I" + | Keyword_namespace -> "K" + | Constant_hash_namespace -> "H" diff --git a/src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.mli b/src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.mli new file mode 100644 index 000000000000..133edfc06799 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/michelson_v1_primitives.mli @@ -0,0 +1,241 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += (* `Permanent *) Unknown_primitive_name of string + +type error += (* `Permanent *) Invalid_case of string + +type error += + | (* `Permanent *) + Invalid_primitive_name of + string Micheline.canonical * Micheline.canonical_location + +(** Types of nodes in Michelson's AST. They fall into 4 categories: + - types (prefixed with [T_]); + - constants (prefixed with [D_]); + - instructions (prefixed with [I_]); + - keywords (prefixed with [K_]). + + Recall that Micheline is essentially just S-expressions with + a few extra atom types for strings and numbers. This variant + represents the values the [Prim] atoms in the Michelson subset + of Micheline. Other types (such as ['a Micheline.canonical]) are + frequently parameterized by this type. This gives us a strongly-typed + subset of Micheline while keeping the set of primitives independent + from the definition of Micheline for easier changes. +*) +type prim = + | K_parameter + | K_storage + | K_code + | K_view + | D_False + | D_Elt + | D_Left + | D_None + | D_Pair + | D_Right + | D_Some + | D_True + | D_Unit + | D_Ticket + | D_Lambda_rec + | I_PACK + | I_UNPACK + | I_BLAKE2B + | I_SHA256 + | I_SHA512 + | I_ABS + | I_ADD + | I_AMOUNT + | I_AND + | I_BALANCE + | I_CAR + | I_CDR + | I_CHAIN_ID + | I_CHECK_SIGNATURE + | I_COMPARE + | I_CONCAT + | I_CONS + | I_CREATE_ACCOUNT + | I_CREATE_CONTRACT + | I_IMPLICIT_ACCOUNT + | I_DIP + | I_DROP + | I_DUP + | I_VIEW + | I_EDIV + | I_EMPTY_BIG_MAP + | I_EMPTY_MAP + | I_EMPTY_SET + | I_EQ + | I_EXEC + | I_APPLY + | I_FAILWITH + | I_GE + | I_GET + | I_GET_AND_UPDATE + | I_GT + | I_HASH_KEY + | I_IF + | I_IF_CONS + | I_IF_LEFT + | I_IF_NONE + | I_INT + | I_LAMBDA + | I_LAMBDA_REC + | I_LE + | I_LEFT + | I_LEVEL + | I_LOOP + | I_LSL + | I_LSR + | I_LT + | I_MAP + | I_MEM + | I_MUL + | I_NEG + | I_NEQ + | I_NIL + | I_NONE + | I_NOT + | I_NOW + | I_MIN_BLOCK_TIME + | I_OR + | I_PAIR + | I_UNPAIR + | I_PUSH + | I_RIGHT + | I_SIZE + | I_SOME + | I_SOURCE + | I_SENDER + | I_SELF + | I_SELF_ADDRESS + | I_SLICE + | I_STEPS_TO_QUOTA + | I_SUB + | I_SUB_MUTEZ + | I_SWAP + | I_TRANSFER_TOKENS + | I_SET_DELEGATE + | I_UNIT + | I_UPDATE + | I_XOR + | I_ITER + | I_LOOP_LEFT + | I_ADDRESS + | I_CONTRACT + | I_ISNAT + | I_CAST + | I_RENAME + | I_SAPLING_EMPTY_STATE + | I_SAPLING_VERIFY_UPDATE + | I_DIG + | I_DUG + | I_NEVER + | I_VOTING_POWER + | I_TOTAL_VOTING_POWER + | I_KECCAK + | I_SHA3 + | I_PAIRING_CHECK + | I_TICKET + | I_TICKET_DEPRECATED + | I_READ_TICKET + | I_SPLIT_TICKET + | I_JOIN_TICKETS + | I_OPEN_CHEST + | I_EMIT + | I_BYTES + | I_NAT + | T_bool + | T_contract + | T_int + | T_key + | T_key_hash + | T_lambda + | T_list + | T_map + | T_big_map + | T_nat + | T_option + | T_or + | T_pair + | T_set + | T_signature + | T_string + | T_bytes + | T_mutez + | T_timestamp + | T_unit + | T_operation + | T_address + | T_tx_rollup_l2_address + | T_sapling_transaction + | T_sapling_transaction_deprecated + | T_sapling_state + | T_chain_id + | T_never + | T_bls12_381_g1 + | T_bls12_381_g2 + | T_bls12_381_fr + | T_ticket + | T_chest_key + | T_chest + (* See the interface of [Global_constants_storage]. *) + | H_constant + +(** Auxiliary types for error documentation. + All the prim constructor prefixes must match their namespace. *) + +type namespace = + | (* prefix "T" *) Type_namespace + | (* prefix "D" *) Constant_namespace + | (* prefix "I" *) Instr_namespace + | (* prefix "K" *) Keyword_namespace + (* The Constant Hash namespace is a singleton reserved + for the constant keyword. Unlike other primitives, + constants have no representation in the typed IR, + being fully expanded away before typechecking. *) + | (* prefix "H" *) Constant_hash_namespace + +val namespace : prim -> namespace + +val prim_encoding : prim Data_encoding.encoding + +val string_of_prim : prim -> string + +val prim_of_string : string -> prim tzresult + +val prims_of_strings : + string Micheline.canonical -> prim Micheline.canonical tzresult + +val strings_of_prims : prim Micheline.canonical -> string Micheline.canonical + +(** The string corresponds to the constructor prefix from the given namespace + (i.e. "T", "D", "I" or "K") *) +val string_of_namespace : namespace -> string diff --git a/src/proto_020_PsParisC/lib_protocol/migration_repr.ml b/src/proto_020_PsParisC/lib_protocol/migration_repr.ml new file mode 100644 index 000000000000..0008eed3f778 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/migration_repr.ml @@ -0,0 +1,65 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type origination_result = { + balance_updates : Receipt_repr.balance_updates; + originated_contracts : Contract_hash.t list; + storage_size : Z.t; + paid_storage_size_diff : Z.t; +} + +let origination_result_list_encoding = + let open Data_encoding in + def "operation.alpha.origination_result" + @@ list + (conv + (fun { + balance_updates; + originated_contracts; + storage_size; + paid_storage_size_diff; + } -> + ( balance_updates, + originated_contracts, + storage_size, + paid_storage_size_diff )) + (fun ( balance_updates, + originated_contracts, + storage_size, + paid_storage_size_diff ) -> + { + balance_updates; + originated_contracts; + storage_size; + paid_storage_size_diff; + }) + (obj4 + (dft "balance_updates" Receipt_repr.balance_updates_encoding []) + (dft + "originated_contracts" + (list Contract_repr.originated_encoding) + []) + (dft "storage_size" z Z.zero) + (dft "paid_storage_size_diff" z Z.zero))) diff --git a/src/proto_020_PsParisC/lib_protocol/migration_repr.mli b/src/proto_020_PsParisC/lib_protocol/migration_repr.mli new file mode 100644 index 000000000000..1fb90c08c0d7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/migration_repr.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Dupe of `Kind.origination successful_manager_operation_result` for use + inside Alpha_context. Converted in Apply_results. + + Doesn't consume gas and omits lazy_storage_diff field since it would + require copying Script_ir_translator functions to work on Raw_context. + *) +type origination_result = { + balance_updates : Receipt_repr.balance_updates; + originated_contracts : Contract_hash.t list; + storage_size : Z.t; + paid_storage_size_diff : Z.t; +} + +val origination_result_list_encoding : origination_result list Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.ml b/src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.ml new file mode 100644 index 000000000000..a2a57ace6416 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.ml @@ -0,0 +1,44 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type kind = Double_baking | Double_attesting | Double_preattesting + +let kind_encoding = + let open Data_encoding in + string_enum + [ + ("preattestation", Double_preattesting); + ("attestation", Double_attesting); + ("block", Double_baking); + ] + +type t = {level : Raw_level_repr.t; round : Round_repr.t; kind : kind} + +let compare_kind a b = + let to_int = function + | Double_baking -> 0 + | Double_attesting -> 1 + | Double_preattesting -> 2 + in + Compare.Int.compare (to_int a) (to_int b) + +let equal_kind a b = Compare.Int.equal 0 (compare_kind a b) + +let compare a b = + Compare.or_else (Raw_level_repr.compare a.level b.level) @@ fun () -> + Compare.or_else (Round_repr.compare a.round b.round) @@ fun () -> + compare_kind a.kind b.kind + +let encoding = + let open Data_encoding in + conv + (fun {level; round; kind} -> (level, round, kind)) + (fun (level, round, kind) -> {level; round; kind}) + (obj3 + (req "level" Raw_level_repr.encoding) + (req "round" Round_repr.encoding) + (req "kind" kind_encoding)) diff --git a/src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.mli b/src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.mli new file mode 100644 index 000000000000..d7dd11a5b7fe --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/misbehaviour_repr.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Which double signing event has occurred. *) +type kind = Double_baking | Double_attesting | Double_preattesting + +(** Internal representation of a double signing event used in + {!Denunciations_repr.item}. + + For a double baking event, the [level] and [round] are those of + both duplicate blocks. For a double (pre)attestating event, the + [level] and [round] are those that appear in the + {!Operation_repr.consensus_content} of both duplicate consensus + operations. + + Note: the culprit pkh doesn't appear as a field here because it is + typically used as a key when storing denunciation items in the + context. *) +type t = {level : Raw_level_repr.t; round : Round_repr.t; kind : kind} + +val kind_encoding : kind Data_encoding.t + +val encoding : t Data_encoding.t + +(** Comparison function for double signing kinds. + + [Double_baking < Double_attesting < Double_preattesting] *) +val compare_kind : kind -> kind -> int + +val equal_kind : kind -> kind -> bool + +(** Comparison function for misbehaviours. + + Misbehaviours are ordered by increasing level, then increasing + round, then kind using {!compare_kind}. *) +val compare : t -> t -> int diff --git a/src/proto_020_PsParisC/lib_protocol/misc.ml b/src/proto_020_PsParisC/lib_protocol/misc.ml new file mode 100644 index 000000000000..817c53730049 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/misc.ml @@ -0,0 +1,91 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Public_key_map = Map.Make (Signature.Public_key) + +type 'a lazyt = unit -> 'a + +type 'a lazy_list_t = LCons of 'a * 'a lazy_list_t tzresult Lwt.t lazyt + +type 'a lazy_list = 'a lazy_list_t tzresult Lwt.t + +let rec ( --> ) i j = + (* [i; i+1; ...; j] *) + if Compare.Int.(i > j) then [] else i :: (succ i --> j) + +let rec ( <-- ) i j = + (* [j; j-1; ...; i] *) + if Compare.Int.(i > j) then [] else j :: (i <-- pred j) + +let rec ( ---> ) i j = + (* [i; i+1; ...; j] *) + if Compare.Int32.(i > j) then [] else i :: (Int32.succ i ---> j) + +let split delim ?(limit = max_int) path = + let l = String.length path in + let rec do_slashes acc limit i = + if Compare.Int.(i >= l) then List.rev acc + else if Compare.Char.(path.[i] = delim) then do_slashes acc limit (i + 1) + else do_split acc limit i + and do_split acc limit i = + if Compare.Int.(limit <= 0) then + if Compare.Int.(i = l) then List.rev acc + else List.rev (String.sub path i (l - i) :: acc) + else do_component acc (pred limit) i i + and do_component acc limit i j = + if Compare.Int.(j >= l) then + if Compare.Int.(i = j) then List.rev acc + else List.rev (String.sub path i (j - i) :: acc) + else if Compare.Char.(path.[j] = delim) then + do_slashes (String.sub path i (j - i) :: acc) limit j + else do_component acc limit i (j + 1) + in + if Compare.Int.(limit > 0) then do_slashes [] limit 0 else [path] + +let pp_print_paragraph ppf description = + Format.fprintf + ppf + "@[%a@]" + Format.(pp_print_list ~pp_sep:pp_print_space pp_print_string) + (split ' ' description) + +let take n l = + let rec loop acc n xs = + if Compare.Int.(n <= 0) then Some (List.rev acc, xs) + else match xs with [] -> None | x :: xs -> loop (x :: acc) (n - 1) xs + in + loop [] n l + +let remove_prefix ~prefix s = + let x = String.length prefix in + let n = String.length s in + if Compare.Int.(n >= x) && Compare.String.(String.sub s 0 x = prefix) then + Some (String.sub s x (n - x)) + else None + +let rec remove_elem_from_list nb = function + | [] -> [] + | _ :: _ as l when Compare.Int.(nb <= 0) -> l + | _ :: tl -> remove_elem_from_list (nb - 1) tl diff --git a/src/proto_020_PsParisC/lib_protocol/misc.mli b/src/proto_020_PsParisC/lib_protocol/misc.mli new file mode 100644 index 000000000000..734ca29f9bcf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/misc.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {2 Helper functions} *) + +module Public_key_map : Map.S with type key = Signature.Public_key.t + +type 'a lazyt = unit -> 'a + +type 'a lazy_list_t = LCons of 'a * 'a lazy_list_t tzresult Lwt.t lazyt + +type 'a lazy_list = 'a lazy_list_t tzresult Lwt.t + +(** Include bounds *) +val ( --> ) : int -> int -> int list + +val ( <-- ) : int -> int -> int list + +val ( ---> ) : Int32.t -> Int32.t -> Int32.t list + +val pp_print_paragraph : Format.formatter -> string -> unit + +val take : int -> 'a list -> ('a list * 'a list) option + +(** Some (input with [prefix] removed), if string has [prefix], else [None] *) +val remove_prefix : prefix:string -> string -> string option + +(** [remove nb list] remove the first [nb] elements from the list [list]. *) +val remove_elem_from_list : int -> 'a list -> 'a list diff --git a/src/proto_020_PsParisC/lib_protocol/non_empty_string.ml b/src/proto_020_PsParisC/lib_protocol/non_empty_string.ml new file mode 100644 index 000000000000..410c86171248 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/non_empty_string.ml @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Compare.String + +let of_string = function "" -> None | s -> Some s + +let of_string_exn = function + | "" -> invalid_arg "Unexpected empty string" + | s -> s + +let cat2 a ?(sep = "") b = String.concat sep [a; b] diff --git a/src/proto_020_PsParisC/lib_protocol/non_empty_string.mli b/src/proto_020_PsParisC/lib_protocol/non_empty_string.mli new file mode 100644 index 000000000000..5807a2dcbb1a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/non_empty_string.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A string that is guaranteed to be non-empty *) +type t = private string + +include Compare.S with type t := t + +(** Returns [None] if the original string is empty. *) +val of_string : string -> t option + +(** Fails with [Invalid_argument] if the original string is empty. *) +val of_string_exn : string -> t + +(** [cat2 a b] concatenates [a] and [b]. + [cat2 a ~sep b] concatenates [a], [sep], and [b]. *) +val cat2 : t -> ?sep:string -> t -> t diff --git a/src/proto_020_PsParisC/lib_protocol/nonce_hash.ml b/src/proto_020_PsParisC/lib_protocol/nonce_hash.ml new file mode 100644 index 000000000000..10a3f7efe42b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/nonce_hash.ml @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* 32 *) +let nonce_hash = "\069\220\169" (* nce(53) *) + +module H = + Blake2B.Make + (Base58) + (struct + let name = "cycle_nonce" + + let title = "A nonce hash" + + let b58check_prefix = nonce_hash + + let size = None + end) + +include H +include Path_encoding.Make_hex (H) + +let () = Base58.check_encoded_prefix b58check_encoding "nce" 53 diff --git a/src/proto_020_PsParisC/lib_protocol/nonce_hash.mli b/src/proto_020_PsParisC/lib_protocol/nonce_hash.mli new file mode 100644 index 000000000000..aeeef12905bd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/nonce_hash.mli @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A specialized Blake2B implementation for hashing nonces. *) + +include S.HASH + +include Path_encoding.S with type t := t diff --git a/src/proto_020_PsParisC/lib_protocol/nonce_storage.ml b/src/proto_020_PsParisC/lib_protocol/nonce_storage.ml new file mode 100644 index 000000000000..5d372183dc81 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/nonce_storage.ml @@ -0,0 +1,144 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Seed_repr.nonce + +type nonce = t + +let encoding = Seed_repr.nonce_encoding + +type error += + | Too_late_revelation + | Too_early_revelation + | Already_revealed_nonce + | Inconsistent_nonce + +let () = + register_error_kind + `Branch + ~id:"nonce.too_late_revelation" + ~title:"Too late nonce revelation" + ~description:"Nonce revelation happens too late" + ~pp:(fun ppf () -> + Format.fprintf ppf "This nonce cannot be revealed anymore.") + Data_encoding.unit + (function Too_late_revelation -> Some () | _ -> None) + (fun () -> Too_late_revelation) ; + register_error_kind + `Temporary + ~id:"nonce.too_early_revelation" + ~title:"Too early nonce revelation" + ~description:"Nonce revelation happens before cycle end" + ~pp:(fun ppf () -> + Format.fprintf ppf "This nonce should not yet be revealed") + Data_encoding.unit + (function Too_early_revelation -> Some () | _ -> None) + (fun () -> Too_early_revelation) ; + register_error_kind + `Branch + ~id:"nonce.already_revealed" + ~title:"Already revealed nonce" + ~description:"Duplicated revelation for a nonce." + ~pp:(fun ppf () -> Format.fprintf ppf "This nonce was already revealed") + Data_encoding.unit + (function Already_revealed_nonce -> Some () | _ -> None) + (fun () -> Already_revealed_nonce) ; + register_error_kind + `Branch + ~id:"nonce.inconsistent" + ~title:"Inconsistent nonce" + ~description: + "The provided nonce is inconsistent with the committed nonce hash." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "This nonce revelation is invalid (inconsistent with the committed \ + hash)") + Data_encoding.unit + (function Inconsistent_nonce -> Some () | _ -> None) + (fun () -> Inconsistent_nonce) + +(* Checks that the level of a revelation is not too early or too late wrt to the + current context and that a nonce has not been already revealed for that level. + Also checks that we are not past the nonce revelation period. *) +let get_unrevealed ctxt (level : Level_repr.t) = + let open Lwt_result_syntax in + let current_level = Level_storage.current ctxt in + match Cycle_repr.pred current_level.cycle with + | None -> tzfail Too_early_revelation (* no revelations during cycle 0 *) + | Some revealed_cycle -> ( + if Cycle_repr.(revealed_cycle < level.Level_repr.cycle) then + tzfail Too_early_revelation + else if + Cycle_repr.(level.Level_repr.cycle < revealed_cycle) + || Compare.Int32.( + current_level.cycle_position + >= Constants_storage.nonce_revelation_threshold ctxt) + then tzfail Too_late_revelation + else + let* status = Storage.Seed.Nonce.get ctxt level in + match status with + | Revealed _ -> tzfail Already_revealed_nonce + | Unrevealed status -> return status) + +let record_hash ctxt unrevealed = + let level = Level_storage.current ctxt in + Storage.Seed.Nonce.init ctxt level (Unrevealed unrevealed) + +let check_unrevealed ctxt (level : Level_repr.t) nonce = + let open Lwt_result_syntax in + let* unrevealed = get_unrevealed ctxt level in + fail_unless + (Seed_repr.check_hash nonce unrevealed.nonce_hash) + Inconsistent_nonce + +let reveal ctxt level nonce = + Storage.Seed.Nonce.update ctxt level (Revealed nonce) + +type unrevealed = Storage.Seed.unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; +} + +type status = Storage.Seed.nonce_status = + | Unrevealed of unrevealed + | Revealed of Seed_repr.nonce + +let get = Storage.Seed.Nonce.get + +type nonce_presence = No_nonce_expected | Nonce_expected of status + +let check ctxt level = + let open Lwt_result_syntax in + let+ status_opt = Storage.Seed.Nonce.find ctxt level in + match status_opt with + | None -> No_nonce_expected + | Some status -> Nonce_expected status + +let of_bytes = Seed_repr.make_nonce + +let hash = Seed_repr.hash + +let check_hash = Seed_repr.check_hash diff --git a/src/proto_020_PsParisC/lib_protocol/nonce_storage.mli b/src/proto_020_PsParisC/lib_protocol/nonce_storage.mli new file mode 100644 index 000000000000..181682a41db9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/nonce_storage.mli @@ -0,0 +1,87 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides types and functions to manipulate nonces. + + A nonce is a byte sequence of fixed length, which is supposed to be random + and used only once, provided by a block producer and used to generate a + random seed (see {!module:Seed_repr}). *) + +type t = Seed_repr.nonce + +type nonce = t + +type error += + | Too_late_revelation + | Too_early_revelation + | Already_revealed_nonce + | Inconsistent_nonce + +val encoding : nonce Data_encoding.t + +type unrevealed = Storage.Seed.unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; +} + +type status = Unrevealed of unrevealed | Revealed of Seed_repr.nonce + +val get : Raw_context.t -> Level_repr.t -> status tzresult Lwt.t + +type nonce_presence = No_nonce_expected | Nonce_expected of status + +val check : Raw_context.t -> Level_repr.t -> nonce_presence tzresult Lwt.t + +val record_hash : Raw_context.t -> unrevealed -> Raw_context.t tzresult Lwt.t + +(** Checks that a nonce revelation operation can be safely applied. + + @return [Error Too_early_revelation] if the current cycle is the + cycle 0 or if the previous cycle is lesser than the cycle of the + input level. + + @return [Error Too_late_revelation] if the previous cycle is + greater than the cycle of the input level. This error is also + returned if the current level cycle position is greater or equal to + the nonce revelation threshold. + + @return [Error Already_revealed_nonce] if a nonce is already + revealed in the context for the input level. + + @return [Error Inconsistent_nonce] if the hash of the input nonce + does not correspond to the nonce recover from the context for the + given level. *) +val check_unrevealed : + Raw_context.t -> Level_repr.t -> nonce -> unit tzresult Lwt.t + +val reveal : + Raw_context.t -> Level_repr.t -> nonce -> Raw_context.t tzresult Lwt.t + +val of_bytes : bytes -> nonce tzresult + +val hash : nonce -> Nonce_hash.t + +val check_hash : nonce -> Nonce_hash.t -> bool diff --git a/src/proto_020_PsParisC/lib_protocol/operation_costs.ml b/src/proto_020_PsParisC/lib_protocol/operation_costs.ml new file mode 100644 index 000000000000..1c138b81f215 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/operation_costs.ml @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +module S = Saturation_repr +module I = Michelson_v1_gas.Cost_of.Interpreter + +(* TODO: + https://gitlab.com/tezos/tezos/-/issues/5141 + benchmark this. *) +let serialization_cost size = + let open S.Syntax in + let v0 = S.safe_int size in + v0 lsl 5 + +let check_signature_cost (algo : I.algo) (operation : _ operation) = + let open S.Syntax in + let size = Operation.unsigned_operation_length operation in + Gas.atomic_step_cost + (serialization_cost size + I.check_signature_on_algo algo size) diff --git a/src/proto_020_PsParisC/lib_protocol/operation_costs.mli b/src/proto_020_PsParisC/lib_protocol/operation_costs.mli new file mode 100644 index 000000000000..f6005929711d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/operation_costs.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +val check_signature_cost : + Michelson_v1_gas.Cost_of.Interpreter.algo -> _ operation -> Gas.cost diff --git a/src/proto_020_PsParisC/lib_protocol/operation_repr.ml b/src/proto_020_PsParisC/lib_protocol/operation_repr.ml new file mode 100644 index 000000000000..531efa05714a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/operation_repr.ml @@ -0,0 +1,2783 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Low level Repr. of Operations *) + +module Kind = struct + type preattestation_consensus_kind = Preattestation_consensus_kind + + type attestation_consensus_kind = Attestation_consensus_kind + + type 'a consensus = + | Preattestation_kind : preattestation_consensus_kind consensus + | Attestation_kind : attestation_consensus_kind consensus + + type preattestation = preattestation_consensus_kind consensus + + type attestation = attestation_consensus_kind consensus + + type seed_nonce_revelation = Seed_nonce_revelation_kind + + type vdf_revelation = Vdf_revelation_kind + + type 'a double_consensus_operation_evidence = + | Double_consensus_operation_evidence + + type double_attestation_evidence = + attestation_consensus_kind double_consensus_operation_evidence + + type double_preattestation_evidence = + preattestation_consensus_kind double_consensus_operation_evidence + + type double_baking_evidence = Double_baking_evidence_kind + + type activate_account = Activate_account_kind + + type proposals = Proposals_kind + + type ballot = Ballot_kind + + type reveal = Reveal_kind + + type transaction = Transaction_kind + + type origination = Origination_kind + + type delegation = Delegation_kind + + type event = Event_kind + + type set_deposits_limit = Set_deposits_limit_kind + + type increase_paid_storage = Increase_paid_storage_kind + + type update_consensus_key = Update_consensus_key_kind + + type drain_delegate = Drain_delegate_kind + + type failing_noop = Failing_noop_kind + + type register_global_constant = Register_global_constant_kind + + type transfer_ticket = Transfer_ticket_kind + + type dal_publish_commitment = Dal_publish_commitment_kind + + type sc_rollup_originate = Sc_rollup_originate_kind + + type sc_rollup_add_messages = Sc_rollup_add_messages_kind + + type sc_rollup_cement = Sc_rollup_cement_kind + + type sc_rollup_publish = Sc_rollup_publish_kind + + type sc_rollup_refute = Sc_rollup_refute_kind + + type sc_rollup_timeout = Sc_rollup_timeout_kind + + type sc_rollup_execute_outbox_message = + | Sc_rollup_execute_outbox_message_kind + + type sc_rollup_recover_bond = Sc_rollup_recover_bond_kind + + type zk_rollup_origination = Zk_rollup_origination_kind + + type zk_rollup_publish = Zk_rollup_publish_kind + + type zk_rollup_update = Zk_rollup_update_kind + + type 'a manager = + | Reveal_manager_kind : reveal manager + | Transaction_manager_kind : transaction manager + | Origination_manager_kind : origination manager + | Delegation_manager_kind : delegation manager + | Event_manager_kind : event manager + | Register_global_constant_manager_kind : register_global_constant manager + | Set_deposits_limit_manager_kind : set_deposits_limit manager + | Increase_paid_storage_manager_kind : increase_paid_storage manager + | Update_consensus_key_manager_kind : update_consensus_key manager + | Transfer_ticket_manager_kind : transfer_ticket manager + | Dal_publish_commitment_manager_kind : dal_publish_commitment manager + | Sc_rollup_originate_manager_kind : sc_rollup_originate manager + | Sc_rollup_add_messages_manager_kind : sc_rollup_add_messages manager + | Sc_rollup_cement_manager_kind : sc_rollup_cement manager + | Sc_rollup_publish_manager_kind : sc_rollup_publish manager + | Sc_rollup_refute_manager_kind : sc_rollup_refute manager + | Sc_rollup_timeout_manager_kind : sc_rollup_timeout manager + | Sc_rollup_execute_outbox_message_manager_kind + : sc_rollup_execute_outbox_message manager + | Sc_rollup_recover_bond_manager_kind : sc_rollup_recover_bond manager + | Zk_rollup_origination_manager_kind : zk_rollup_origination manager + | Zk_rollup_publish_manager_kind : zk_rollup_publish manager + | Zk_rollup_update_manager_kind : zk_rollup_update manager +end + +type 'a consensus_operation_type = + | Attestation : Kind.attestation consensus_operation_type + | Preattestation : Kind.preattestation consensus_operation_type + +type consensus_content = { + slot : Slot_repr.t; + level : Raw_level_repr.t; + (* The level is not required to validate an attestation when it corresponds + to the current payload, but if we want to filter attestations, we need + the level. *) + round : Round_repr.t; + block_payload_hash : Block_payload_hash.t; + (* NOTE: This could be just the hash of the set of operations (the + actual payload). The grandfather block hash should already be + fixed by the operation.shell.branch field. This is not really + important but could make things easier for debugging *) +} + +type dal_content = {attestation : Dal_attestation_repr.t} + +let consensus_content_encoding = + let open Data_encoding in + conv + (fun {slot; level; round; block_payload_hash} -> + (slot, level, round, block_payload_hash)) + (fun (slot, level, round, block_payload_hash) -> + {slot; level; round; block_payload_hash}) + (obj4 + (req "slot" Slot_repr.encoding) + (req "level" Raw_level_repr.encoding) + (req "round" Round_repr.encoding) + (req "block_payload_hash" Block_payload_hash.encoding)) + +let pp_consensus_content ppf content = + Format.fprintf + ppf + "(%ld, %a, %a, %a)" + (Raw_level_repr.to_int32 content.level) + Round_repr.pp + content.round + Slot_repr.pp + content.slot + Block_payload_hash.pp_short + content.block_payload_hash + +type consensus_watermark = + | Attestation of Chain_id.t + | Preattestation of Chain_id.t + +let to_watermark = function + | Preattestation chain_id -> + Signature.Custom + (Bytes.cat (Bytes.of_string "\x12") (Chain_id.to_bytes chain_id)) + | Attestation chain_id -> + Signature.Custom + (Bytes.cat (Bytes.of_string "\x13") (Chain_id.to_bytes chain_id)) + +let of_watermark = function + | Signature.Custom b -> + if Compare.Int.(Bytes.length b > 0) then + match Bytes.get b 0 with + | '\x12' -> + Option.map + (fun chain_id -> Preattestation chain_id) + (Chain_id.of_bytes_opt (Bytes.sub b 1 (Bytes.length b - 1))) + | '\x13' -> + Option.map + (fun chain_id -> Attestation chain_id) + (Chain_id.of_bytes_opt (Bytes.sub b 1 (Bytes.length b - 1))) + | _ -> None + else None + | _ -> None + +type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} + +let raw_encoding = Operation.encoding + +type 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; +} + +and 'kind protocol_data = { + contents : 'kind contents_list; + signature : Signature.t option; +} + +and _ contents_list = + | Single : 'kind contents -> 'kind contents_list + | Cons : + 'kind Kind.manager contents * 'rest Kind.manager contents_list + -> ('kind * 'rest) Kind.manager contents_list + +and _ contents = + | Preattestation : consensus_content -> Kind.preattestation contents + | Attestation : { + consensus_content : consensus_content; + dal_content : dal_content option; + } + -> Kind.attestation contents + | Seed_nonce_revelation : { + level : Raw_level_repr.t; + nonce : Seed_repr.nonce; + } + -> Kind.seed_nonce_revelation contents + | Vdf_revelation : { + solution : Seed_repr.vdf_solution; + } + -> Kind.vdf_revelation contents + | Double_preattestation_evidence : { + op1 : Kind.preattestation operation; + op2 : Kind.preattestation operation; + } + -> Kind.double_preattestation_evidence contents + | Double_attestation_evidence : { + op1 : Kind.attestation operation; + op2 : Kind.attestation operation; + } + -> Kind.double_attestation_evidence contents + | Double_baking_evidence : { + bh1 : Block_header_repr.t; + bh2 : Block_header_repr.t; + } + -> Kind.double_baking_evidence contents + | Activate_account : { + id : Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + } + -> Kind.activate_account contents + | Proposals : { + source : Signature.Public_key_hash.t; + period : int32; + proposals : Protocol_hash.t list; + } + -> Kind.proposals contents + | Ballot : { + source : Signature.Public_key_hash.t; + period : int32; + proposal : Protocol_hash.t; + ballot : Vote_repr.ballot; + } + -> Kind.ballot contents + | Drain_delegate : { + consensus_key : Signature.Public_key_hash.t; + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + -> Kind.drain_delegate contents + | Failing_noop : string -> Kind.failing_noop contents + | Manager_operation : { + source : Signature.public_key_hash; + fee : Tez_repr.t; + counter : Manager_counter_repr.t; + operation : 'kind manager_operation; + gas_limit : Gas_limit_repr.Arith.integral; + storage_limit : Z.t; + } + -> 'kind Kind.manager contents + +and _ manager_operation = + | Reveal : Signature.Public_key.t -> Kind.reveal manager_operation + | Transaction : { + amount : Tez_repr.t; + parameters : Script_repr.lazy_expr; + entrypoint : Entrypoint_repr.t; + destination : Contract_repr.t; + } + -> Kind.transaction manager_operation + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script_repr.t; + credit : Tez_repr.t; + } + -> Kind.origination manager_operation + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation manager_operation + | Register_global_constant : { + value : Script_repr.lazy_expr; + } + -> Kind.register_global_constant manager_operation + | Set_deposits_limit : + Tez_repr.t option + -> Kind.set_deposits_limit manager_operation + | Increase_paid_storage : { + amount_in_bytes : Z.t; + destination : Contract_hash.t; + } + -> Kind.increase_paid_storage manager_operation + | Update_consensus_key : + Signature.Public_key.t + -> Kind.update_consensus_key manager_operation + | Transfer_ticket : { + contents : Script_repr.lazy_expr; + ty : Script_repr.lazy_expr; + ticketer : Contract_repr.t; + amount : Ticket_amount.t; + destination : Contract_repr.t; + entrypoint : Entrypoint_repr.t; + } + -> Kind.transfer_ticket manager_operation + | Dal_publish_commitment : + Dal_operations_repr.Publish_commitment.t + -> Kind.dal_publish_commitment manager_operation + | Sc_rollup_originate : { + kind : Sc_rollups.Kind.t; + boot_sector : string; + parameters_ty : Script_repr.lazy_expr; + whitelist : Sc_rollup_whitelist_repr.t option; + } + -> Kind.sc_rollup_originate manager_operation + | Sc_rollup_add_messages : { + messages : string list; + } + -> Kind.sc_rollup_add_messages manager_operation + | Sc_rollup_cement : { + rollup : Sc_rollup_repr.t; + } + -> Kind.sc_rollup_cement manager_operation + | Sc_rollup_publish : { + rollup : Sc_rollup_repr.t; + commitment : Sc_rollup_commitment_repr.t; + } + -> Kind.sc_rollup_publish manager_operation + | Sc_rollup_refute : { + rollup : Sc_rollup_repr.t; + opponent : Sc_rollup_repr.Staker.t; + refutation : Sc_rollup_game_repr.refutation; + } + -> Kind.sc_rollup_refute manager_operation + | Sc_rollup_timeout : { + rollup : Sc_rollup_repr.t; + stakers : Sc_rollup_game_repr.Index.t; + } + -> Kind.sc_rollup_timeout manager_operation + | Sc_rollup_execute_outbox_message : { + rollup : Sc_rollup_repr.t; + cemented_commitment : Sc_rollup_commitment_repr.Hash.t; + output_proof : string; + } + -> Kind.sc_rollup_execute_outbox_message manager_operation + | Sc_rollup_recover_bond : { + sc_rollup : Sc_rollup_repr.t; + staker : Signature.public_key_hash; + } + -> Kind.sc_rollup_recover_bond manager_operation + | Zk_rollup_origination : { + public_parameters : Plonk.public_parameters; + circuits_info : [`Public | `Private | `Fee] Zk_rollup_account_repr.SMap.t; + init_state : Zk_rollup_state_repr.t; + nb_ops : int; + } + -> Kind.zk_rollup_origination manager_operation + | Zk_rollup_publish : { + zk_rollup : Zk_rollup_repr.t; + ops : (Zk_rollup_operation_repr.t * Zk_rollup_ticket_repr.t option) list; + } + -> Kind.zk_rollup_publish manager_operation + | Zk_rollup_update : { + zk_rollup : Zk_rollup_repr.t; + update : Zk_rollup_update_repr.t; + } + -> Kind.zk_rollup_update manager_operation + +let manager_kind : type kind. kind manager_operation -> kind Kind.manager = + function + | Reveal _ -> Kind.Reveal_manager_kind + | Transaction _ -> Kind.Transaction_manager_kind + | Origination _ -> Kind.Origination_manager_kind + | Delegation _ -> Kind.Delegation_manager_kind + | Register_global_constant _ -> Kind.Register_global_constant_manager_kind + | Set_deposits_limit _ -> Kind.Set_deposits_limit_manager_kind + | Increase_paid_storage _ -> Kind.Increase_paid_storage_manager_kind + | Update_consensus_key _ -> Kind.Update_consensus_key_manager_kind + | Transfer_ticket _ -> Kind.Transfer_ticket_manager_kind + | Dal_publish_commitment _ -> Kind.Dal_publish_commitment_manager_kind + | Sc_rollup_originate _ -> Kind.Sc_rollup_originate_manager_kind + | Sc_rollup_add_messages _ -> Kind.Sc_rollup_add_messages_manager_kind + | Sc_rollup_cement _ -> Kind.Sc_rollup_cement_manager_kind + | Sc_rollup_publish _ -> Kind.Sc_rollup_publish_manager_kind + | Sc_rollup_refute _ -> Kind.Sc_rollup_refute_manager_kind + | Sc_rollup_timeout _ -> Kind.Sc_rollup_timeout_manager_kind + | Sc_rollup_execute_outbox_message _ -> + Kind.Sc_rollup_execute_outbox_message_manager_kind + | Sc_rollup_recover_bond _ -> Kind.Sc_rollup_recover_bond_manager_kind + | Zk_rollup_origination _ -> Kind.Zk_rollup_origination_manager_kind + | Zk_rollup_publish _ -> Kind.Zk_rollup_publish_manager_kind + | Zk_rollup_update _ -> Kind.Zk_rollup_update_manager_kind + +type packed_manager_operation = + | Manager : 'kind manager_operation -> packed_manager_operation + +type packed_contents = Contents : 'kind contents -> packed_contents + +type packed_contents_list = + | Contents_list : 'kind contents_list -> packed_contents_list + +type packed_protocol_data = + | Operation_data : 'kind protocol_data -> packed_protocol_data + +type packed_operation = { + shell : Operation.shell_header; + protocol_data : packed_protocol_data; +} + +let pack ({shell; protocol_data} : _ operation) : packed_operation = + {shell; protocol_data = Operation_data protocol_data} + +let rec contents_list_to_list : type a. a contents_list -> _ = function + | Single o -> [Contents o] + | Cons (o, os) -> Contents o :: contents_list_to_list os + +let to_list = function Contents_list l -> contents_list_to_list l + +(* This first version of of_list has the type (_, string) result expected by + the conv_with_guard combinator of Data_encoding. For a more conventional + return type see [of_list] below. *) +let of_list_internal contents = + let rec of_list_internal acc = function + | [] -> Ok acc + | Contents o :: os -> ( + match (o, acc) with + | ( Manager_operation _, + Contents_list (Single (Manager_operation _) as rest) ) -> + (of_list_internal [@tailcall]) (Contents_list (Cons (o, rest))) os + | Manager_operation _, Contents_list (Cons _ as rest) -> + (of_list_internal [@tailcall]) (Contents_list (Cons (o, rest))) os + | _ -> + Error + "Operation list of length > 1 should only contain manager \ + operations.") + in + match List.rev contents with + | [] -> Error "Operation lists should not be empty." + | Contents o :: os -> of_list_internal (Contents_list (Single o)) os + +type error += Contents_list_error of string (* `Permanent *) + +let of_list l = + match of_list_internal l with + | Ok contents -> Ok contents + | Error s -> Result_syntax.tzfail @@ Contents_list_error s + +let tx_rollup_operation_tag_offset = 150 + +let tx_rollup_operation_origination_tag = tx_rollup_operation_tag_offset + 0 + +let tx_rollup_operation_submit_batch_tag = tx_rollup_operation_tag_offset + 1 + +let tx_rollup_operation_commit_tag = tx_rollup_operation_tag_offset + 2 + +let tx_rollup_operation_return_bond_tag = tx_rollup_operation_tag_offset + 3 + +let tx_rollup_operation_finalize_commitment_tag = + tx_rollup_operation_tag_offset + 4 + +let tx_rollup_operation_remove_commitment_tag = + tx_rollup_operation_tag_offset + 5 + +let tx_rollup_operation_rejection_tag = tx_rollup_operation_tag_offset + 6 + +let tx_rollup_operation_dispatch_tickets_tag = + tx_rollup_operation_tag_offset + 7 + +(** The following operation tags cannot be used again, it is checked + at compilation time. *) +let tx_rollup_forbidden_operation_tags = + [ + tx_rollup_operation_origination_tag; + tx_rollup_operation_submit_batch_tag; + tx_rollup_operation_commit_tag; + tx_rollup_operation_return_bond_tag; + tx_rollup_operation_finalize_commitment_tag; + tx_rollup_operation_remove_commitment_tag; + tx_rollup_operation_rejection_tag; + tx_rollup_operation_dispatch_tickets_tag; + ] + +let transfer_ticket_tag = tx_rollup_operation_tag_offset + 8 + +let sc_rollup_operation_tag_offset = 200 + +let sc_rollup_operation_origination_tag = sc_rollup_operation_tag_offset + 0 + +let sc_rollup_operation_add_message_tag = sc_rollup_operation_tag_offset + 1 + +let sc_rollup_operation_cement_tag = sc_rollup_operation_tag_offset + 2 + +let sc_rollup_operation_publish_tag = sc_rollup_operation_tag_offset + 3 + +let sc_rollup_operation_refute_tag = sc_rollup_operation_tag_offset + 4 + +let sc_rollup_operation_timeout_tag = sc_rollup_operation_tag_offset + 5 + +let sc_rollup_execute_outbox_message_tag = sc_rollup_operation_tag_offset + 6 + +let sc_rollup_operation_recover_bond_tag = sc_rollup_operation_tag_offset + 7 + +let dal_offset = 230 + +let dal_publish_commitment_tag = dal_offset + 0 + +let zk_rollup_operation_tag_offset = 250 + +let zk_rollup_operation_create_tag = zk_rollup_operation_tag_offset + 0 + +let zk_rollup_operation_publish_tag = zk_rollup_operation_tag_offset + 1 + +let zk_rollup_operation_update_tag = zk_rollup_operation_tag_offset + 2 + +module Encoding = struct + open Data_encoding + + (** These tags can not be used yet for operations. *) + let reserved_tag t = + (* These tags are reserved for future extensions: [fd] - [ff]. *) + Compare.Int.(t >= 0xfd) + || (* These tags were used by old operations. + The operations have been removed in protocol proposal N, it can + be unblocked in the future (e.g. proposal O, P etc.). *) + List.exists (Compare.Int.equal t) tx_rollup_forbidden_operation_tags + + let signature_prefix_tag = 0xff + + let () = assert (reserved_tag signature_prefix_tag) + + let case tag name args proj inj = + case + tag + ~title:(String.capitalize_ascii name) + (merge_objs (obj1 (req "kind" (constant name))) args) + (fun x -> match proj x with None -> None | Some x -> Some ((), x)) + (fun ((), x) -> inj x) + + module Manager_operations = struct + type 'kind case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_manager_operation -> 'kind manager_operation option; + proj : 'kind manager_operation -> 'a; + inj : 'a -> 'kind manager_operation; + } + -> 'kind case + + let reveal_case = + MCase + { + tag = 0; + name = "reveal"; + encoding = obj1 (req "public_key" Signature.Public_key.encoding); + select = (function Manager (Reveal _ as op) -> Some op | _ -> None); + proj = (function Reveal pkh -> pkh); + inj = (fun pkh -> Reveal pkh); + } + + let transaction_case = + MCase + { + tag = 1; + name = "transaction"; + encoding = + obj3 + (req "amount" Tez_repr.encoding) + (req "destination" Contract_repr.encoding) + (opt + "parameters" + (obj2 + (req "entrypoint" Entrypoint_repr.smart_encoding) + (req "value" Script_repr.lazy_expr_encoding))); + select = + (function Manager (Transaction _ as op) -> Some op | _ -> None); + proj = + (function + | Transaction {amount; destination; parameters; entrypoint} -> + let parameters = + if + Script_repr.is_unit_parameter parameters + && Entrypoint_repr.is_default entrypoint + then None + else Some (entrypoint, parameters) + in + (amount, destination, parameters)); + inj = + (fun (amount, destination, parameters) -> + let entrypoint, parameters = + match parameters with + | None -> (Entrypoint_repr.default, Script_repr.unit_parameter) + | Some (entrypoint, value) -> (entrypoint, value) + in + Transaction {amount; destination; parameters; entrypoint}); + } + + let origination_case = + MCase + { + tag = 2; + name = "origination"; + encoding = + obj3 + (req "balance" Tez_repr.encoding) + (opt "delegate" Signature.Public_key_hash.encoding) + (req "script" Script_repr.encoding); + select = + (function Manager (Origination _ as op) -> Some op | _ -> None); + proj = + (function + | Origination {credit; delegate; script} -> + (credit, delegate, script)); + inj = + (fun (credit, delegate, script) -> + Origination {credit; delegate; script}); + } + + let delegation_case = + MCase + { + tag = 3; + name = "delegation"; + encoding = obj1 (opt "delegate" Signature.Public_key_hash.encoding); + select = + (function Manager (Delegation _ as op) -> Some op | _ -> None); + proj = (function Delegation key -> key); + inj = (fun key -> Delegation key); + } + + let register_global_constant_case = + MCase + { + tag = 4; + name = "register_global_constant"; + encoding = obj1 (req "value" Script_repr.lazy_expr_encoding); + select = + (function + | Manager (Register_global_constant _ as op) -> Some op | _ -> None); + proj = (function Register_global_constant {value} -> value); + inj = (fun value -> Register_global_constant {value}); + } + + let set_deposits_limit_case = + MCase + { + tag = 5; + name = "set_deposits_limit"; + encoding = obj1 (opt "limit" Tez_repr.encoding); + select = + (function + | Manager (Set_deposits_limit _ as op) -> Some op | _ -> None); + proj = (function Set_deposits_limit key -> key); + inj = (fun key -> Set_deposits_limit key); + } + + let increase_paid_storage_case = + MCase + { + tag = 9; + name = "increase_paid_storage"; + encoding = + obj2 + (req "amount" Data_encoding.z) + (req "destination" Contract_repr.originated_encoding); + select = + (function + | Manager (Increase_paid_storage _ as op) -> Some op | _ -> None); + proj = + (function + | Increase_paid_storage {amount_in_bytes; destination} -> + (amount_in_bytes, destination)); + inj = + (fun (amount_in_bytes, destination) -> + Increase_paid_storage {amount_in_bytes; destination}); + } + + let update_consensus_key_tag = 6 + + let update_consensus_key_case = + MCase + { + tag = update_consensus_key_tag; + name = "update_consensus_key"; + encoding = obj1 (req "pk" Signature.Public_key.encoding); + select = + (function + | Manager (Update_consensus_key _ as op) -> Some op | _ -> None); + proj = (function Update_consensus_key consensus_pk -> consensus_pk); + inj = (fun consensus_pk -> Update_consensus_key consensus_pk); + } + + let transfer_ticket_case = + MCase + { + tag = transfer_ticket_tag; + name = "transfer_ticket"; + encoding = + obj6 + (req "ticket_contents" Script_repr.lazy_expr_encoding) + (req "ticket_ty" Script_repr.lazy_expr_encoding) + (req "ticket_ticketer" Contract_repr.encoding) + (req "ticket_amount" Ticket_amount.encoding) + (req "destination" Contract_repr.encoding) + (req "entrypoint" Entrypoint_repr.simple_encoding); + select = + (function + | Manager (Transfer_ticket _ as op) -> Some op | _ -> None); + proj = + (function + | Transfer_ticket + {contents; ty; ticketer; amount; destination; entrypoint} -> + (contents, ty, ticketer, amount, destination, entrypoint)); + inj = + (fun (contents, ty, ticketer, amount, destination, entrypoint) -> + Transfer_ticket + {contents; ty; ticketer; amount; destination; entrypoint}); + } + + let zk_rollup_origination_case = + MCase + { + tag = zk_rollup_operation_create_tag; + name = "zk_rollup_origination"; + encoding = + obj4 + (req "public_parameters" Plonk.public_parameters_encoding) + (req + "circuits_info" + Zk_rollup_account_repr.circuits_info_encoding) + (req "init_state" Zk_rollup_state_repr.encoding) + (* TODO https://gitlab.com/tezos/tezos/-/issues/3655 + Encoding of non-negative [nb_ops] for origination *) + (req "nb_ops" int31); + select = + (function + | Manager (Zk_rollup_origination _ as op) -> Some op | _ -> None); + proj = + (function + | Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops} -> + (public_parameters, circuits_info, init_state, nb_ops)); + inj = + (fun (public_parameters, circuits_info, init_state, nb_ops) -> + Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops}); + } + + let zk_rollup_publish_case = + MCase + { + tag = zk_rollup_operation_publish_tag; + name = "zk_rollup_publish"; + encoding = + obj2 + (req "zk_rollup" Zk_rollup_repr.Address.encoding) + (req "op" + @@ Data_encoding.list + (tup2 + Zk_rollup_operation_repr.encoding + (option Zk_rollup_ticket_repr.encoding))); + select = + (function + | Manager (Zk_rollup_publish _ as op) -> Some op | _ -> None); + proj = + (function Zk_rollup_publish {zk_rollup; ops} -> (zk_rollup, ops)); + inj = (fun (zk_rollup, ops) -> Zk_rollup_publish {zk_rollup; ops}); + } + + let zk_rollup_update_case = + MCase + { + tag = zk_rollup_operation_update_tag; + name = "zk_rollup_update"; + encoding = + obj2 + (req "zk_rollup" Zk_rollup_repr.Address.encoding) + (req "update" Zk_rollup_update_repr.encoding); + select = + (function + | Manager (Zk_rollup_update _ as op) -> Some op | _ -> None); + proj = + (function + | Zk_rollup_update {zk_rollup; update} -> (zk_rollup, update)); + inj = + (fun (zk_rollup, update) -> Zk_rollup_update {zk_rollup; update}); + } + + let sc_rollup_originate_case = + MCase + { + tag = sc_rollup_operation_origination_tag; + name = "smart_rollup_originate"; + encoding = + obj4 + (req "pvm_kind" Sc_rollups.Kind.encoding) + (req "kernel" (string Hex)) + (req "parameters_ty" Script_repr.lazy_expr_encoding) + (opt "whitelist" Sc_rollup_whitelist_repr.encoding); + select = + (function + | Manager (Sc_rollup_originate _ as op) -> Some op | _ -> None); + proj = + (function + | Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist} + -> + (kind, boot_sector, parameters_ty, whitelist)); + inj = + (fun (kind, boot_sector, parameters_ty, whitelist) -> + Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist}); + } + + let dal_publish_commitment_case = + MCase + { + tag = dal_publish_commitment_tag; + name = "dal_publish_commitment"; + encoding = + obj1 + (req + "slot_header" + Dal_operations_repr.Publish_commitment.encoding); + select = + (function + | Manager (Dal_publish_commitment _ as op) -> Some op | _ -> None); + proj = (function Dal_publish_commitment slot_header -> slot_header); + inj = (fun slot_header -> Dal_publish_commitment slot_header); + } + + let sc_rollup_add_messages_case = + MCase + { + tag = sc_rollup_operation_add_message_tag; + name = "smart_rollup_add_messages"; + encoding = obj1 (req "message" (list (string Hex))); + select = + (function + | Manager (Sc_rollup_add_messages _ as op) -> Some op | _ -> None); + proj = (function Sc_rollup_add_messages {messages} -> messages); + inj = (fun messages -> Sc_rollup_add_messages {messages}); + } + + let sc_rollup_cement_case = + MCase + { + tag = sc_rollup_operation_cement_tag; + name = "smart_rollup_cement"; + encoding = obj1 (req "rollup" Sc_rollup_repr.encoding); + select = + (function + | Manager (Sc_rollup_cement _ as op) -> Some op | _ -> None); + proj = (function Sc_rollup_cement {rollup} -> rollup); + inj = (fun rollup -> Sc_rollup_cement {rollup}); + } + + let sc_rollup_publish_case = + MCase + { + tag = sc_rollup_operation_publish_tag; + name = "smart_rollup_publish"; + encoding = + obj2 + (req "rollup" Sc_rollup_repr.encoding) + (req "commitment" Sc_rollup_commitment_repr.encoding); + select = + (function + | Manager (Sc_rollup_publish _ as op) -> Some op | _ -> None); + proj = + (function + | Sc_rollup_publish {rollup; commitment} -> (rollup, commitment)); + inj = + (fun (rollup, commitment) -> Sc_rollup_publish {rollup; commitment}); + } + + let sc_rollup_refute_case = + MCase + { + tag = sc_rollup_operation_refute_tag; + name = "smart_rollup_refute"; + encoding = + obj3 + (req "rollup" Sc_rollup_repr.encoding) + (req "opponent" Sc_rollup_repr.Staker.encoding) + (req "refutation" Sc_rollup_game_repr.refutation_encoding); + select = + (function + | Manager (Sc_rollup_refute _ as op) -> Some op | _ -> None); + proj = + (function + | Sc_rollup_refute {rollup; opponent; refutation} -> + (rollup, opponent, refutation)); + inj = + (fun (rollup, opponent, refutation) -> + Sc_rollup_refute {rollup; opponent; refutation}); + } + + let sc_rollup_timeout_case = + MCase + { + tag = sc_rollup_operation_timeout_tag; + name = "smart_rollup_timeout"; + encoding = + obj2 + (req "rollup" Sc_rollup_repr.encoding) + (req "stakers" Sc_rollup_game_repr.Index.encoding); + select = + (function + | Manager (Sc_rollup_timeout _ as op) -> Some op | _ -> None); + proj = + (function + | Sc_rollup_timeout {rollup; stakers} -> (rollup, stakers)); + inj = (fun (rollup, stakers) -> Sc_rollup_timeout {rollup; stakers}); + } + + let sc_rollup_execute_outbox_message_case = + MCase + { + tag = sc_rollup_execute_outbox_message_tag; + name = "smart_rollup_execute_outbox_message"; + encoding = + obj3 + (req "rollup" Sc_rollup_repr.encoding) + (req + "cemented_commitment" + Sc_rollup_commitment_repr.Hash.encoding) + (req "output_proof" (string Hex)); + select = + (function + | Manager (Sc_rollup_execute_outbox_message _ as op) -> Some op + | _ -> None); + proj = + (function + | Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof} -> + (rollup, cemented_commitment, output_proof)); + inj = + (fun (rollup, cemented_commitment, output_proof) -> + Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof}); + } + + let sc_rollup_recover_bond_case = + MCase + { + tag = sc_rollup_operation_recover_bond_tag; + name = "smart_rollup_recover_bond"; + encoding = + obj2 + (req "rollup" Sc_rollup_repr.Address.encoding) + (req "staker" Signature.Public_key_hash.encoding); + select = + (function + | Manager (Sc_rollup_recover_bond _ as op) -> Some op | _ -> None); + proj = + (function + | Sc_rollup_recover_bond {sc_rollup; staker} -> (sc_rollup, staker)); + inj = + (fun (sc_rollup, staker) -> + Sc_rollup_recover_bond {sc_rollup; staker}); + } + end + + type 'b case = + | Case : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_contents -> 'b contents option; + proj : 'b contents -> 'a; + inj : 'a -> 'b contents; + } + -> 'b case + + (* Encoding case that accepts legacy preattestation name : `preendorsement` in + JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let preendorsement_case = + Case + { + tag = 20; + name = "preendorsement"; + encoding = consensus_content_encoding; + select = + (function Contents (Preattestation _ as op) -> Some op | _ -> None); + proj = (fun (Preattestation preattestation) -> preattestation); + inj = (fun preattestation -> Preattestation preattestation); + } + + let preattestation_case = + Case + { + tag = 20; + name = "preattestation"; + encoding = consensus_content_encoding; + select = + (function Contents (Preattestation _ as op) -> Some op | _ -> None); + proj = (fun (Preattestation preattestation) -> preattestation); + inj = (fun preattestation -> Preattestation preattestation); + } + + (* Encoding that accepts legacy preattestation name : `preendorsement` in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let preendorsement_encoding = + let make (Case {tag; name; encoding; select = _; proj; inj}) = + case (Tag tag) name encoding (fun o -> Some (proj o)) (fun x -> inj x) + in + let to_list : Kind.preattestation contents_list -> _ = function + | Single o -> o + in + let of_list : Kind.preattestation contents -> _ = function + | o -> Single o + in + def "inlined.preendorsement" + @@ conv + (fun ({shell; protocol_data = {contents; signature}} : _ operation) -> + (shell, (contents, signature))) + (fun (shell, (contents, signature)) : _ operation -> + {shell; protocol_data = {contents; signature}}) + (merge_objs + Operation.shell_header_encoding + (obj2 + (req + "operations" + (conv to_list of_list + @@ def "inlined.preendorsement.contents" + @@ union [make preendorsement_case])) + (varopt "signature" Signature.encoding))) + + let preattestation_encoding = + let make (Case {tag; name; encoding; select = _; proj; inj}) = + case (Tag tag) name encoding (fun o -> Some (proj o)) (fun x -> inj x) + in + let to_list : Kind.preattestation contents_list -> _ = function + | Single o -> o + in + let of_list : Kind.preattestation contents -> _ = function + | o -> Single o + in + def "inlined.preattestation" + @@ conv + (fun ({shell; protocol_data = {contents; signature}} : _ operation) -> + (shell, (contents, signature))) + (fun (shell, (contents, signature)) : _ operation -> + {shell; protocol_data = {contents; signature}}) + (merge_objs + Operation.shell_header_encoding + (obj2 + (req + "operations" + (conv to_list of_list + @@ def "inlined.preattestation.contents" + @@ union [make preattestation_case])) + (varopt "signature" Signature.encoding))) + + let consensus_content_encoding = + obj4 + (req "slot" Slot_repr.encoding) + (req "level" Raw_level_repr.encoding) + (req "round" Round_repr.encoding) + (req "block_payload_hash" Block_payload_hash.encoding) + + let dal_content_encoding = + obj1 (req "dal_attestation" Dal_attestation_repr.encoding) + + let endorsement_encoding = consensus_content_encoding + + let endorsement_with_dal_encoding = + merge_objs consensus_content_encoding dal_content_encoding + + (* Precondition: [dal_content = None]. *) + let attestation_encoding_proj + (Attestation {consensus_content; dal_content = _}) = + ( consensus_content.slot, + consensus_content.level, + consensus_content.round, + consensus_content.block_payload_hash ) + + let attestation_encoding_inj (slot, level, round, block_payload_hash) = + Attestation + { + consensus_content = {slot; level; round; block_payload_hash}; + dal_content = None; + } + + (* Precondition: [dal_content <> None]. Check usage! *) + let attestation_with_dal_encoding_proj + (Attestation {consensus_content; dal_content}) = + match dal_content with + | None -> assert false + | Some dal_content -> + ( ( consensus_content.slot, + consensus_content.level, + consensus_content.round, + consensus_content.block_payload_hash ), + dal_content.attestation ) + + let attestation_with_dal_encoding_inj + ((slot, level, round, block_payload_hash), attestation) = + Attestation + { + consensus_content = {slot; level; round; block_payload_hash}; + dal_content = Some {attestation}; + } + + (* Encoding case that accepts legacy attestation name : `endorsement` in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let endorsement_case = + Case + { + tag = 21; + name = "endorsement"; + encoding = endorsement_encoding; + select = + (function + | Contents (Attestation {dal_content = None; _} as op) -> Some op + | _ -> None); + proj = attestation_encoding_proj; + inj = attestation_encoding_inj; + } + + let attestation_case = + Case + { + tag = 21; + name = "attestation"; + encoding = endorsement_encoding; + select = + (function + | Contents (Attestation {dal_content = None; _} as op) -> Some op + | _ -> None); + proj = attestation_encoding_proj; + inj = attestation_encoding_inj; + } + + let endorsement_with_dal_case = + Case + { + tag = 23; + name = "endorsement_with_dal"; + encoding = endorsement_with_dal_encoding; + select = + (function + | Contents (Attestation {dal_content = Some _; _} as op) -> Some op + | _ -> None); + proj = attestation_with_dal_encoding_proj; + inj = attestation_with_dal_encoding_inj; + } + + let attestation_with_dal_case = + Case + { + tag = 23; + name = "attestation_with_dal"; + encoding = endorsement_with_dal_encoding; + select = + (function + | Contents (Attestation {dal_content = Some _; _} as op) -> Some op + | _ -> None); + proj = attestation_with_dal_encoding_proj; + inj = attestation_with_dal_encoding_inj; + } + + (* Encoding that accepts legacy attestation name : `endorsement` in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let endorsement_encoding = + let make kind (Case {tag; name; encoding; select = _; proj; inj}) = + case + (Tag tag) + name + encoding + (function + | o -> ( + match (kind, o) with + | `Simple, (Attestation {dal_content = None; _} as op) -> + Some (proj op) + | `Full, (Attestation {dal_content = Some _; _} as op) -> + Some (proj op) + | _ -> None)) + (fun x -> inj x) + in + let to_list : Kind.attestation contents_list -> _ = fun (Single o) -> o in + let of_list : Kind.attestation contents -> _ = fun o -> Single o in + def "inlined.endorsement" + @@ conv + (fun ({shell; protocol_data = {contents; signature}} : _ operation) -> + (shell, (contents, signature))) + (fun (shell, (contents, signature)) : _ operation -> + {shell; protocol_data = {contents; signature}}) + (merge_objs + Operation.shell_header_encoding + (obj2 + (req + "operations" + (conv to_list of_list + @@ def "inlined.endorsement_mempool.contents" + @@ union + [ + make `Simple endorsement_case; + make `Full endorsement_with_dal_case; + ])) + (varopt "signature" Signature.encoding))) + + let attestation_encoding = + let make kind (Case {tag; name; encoding; select = _; proj; inj}) = + case + (Tag tag) + name + encoding + (function + | o -> ( + match (kind, o) with + | `Without_dal, (Attestation {dal_content = None; _} as op) -> + Some (proj op) + | `With_dal, (Attestation {dal_content = Some _; _} as op) -> + Some (proj op) + | _ -> None)) + (fun x -> inj x) + in + let to_list : Kind.attestation contents_list -> _ = fun (Single o) -> o in + let of_list : Kind.attestation contents -> _ = fun o -> Single o in + def "inlined.attestation" + @@ conv + (fun ({shell; protocol_data = {contents; signature}} : _ operation) -> + (shell, (contents, signature))) + (fun (shell, (contents, signature)) : _ operation -> + {shell; protocol_data = {contents; signature}}) + (merge_objs + Operation.shell_header_encoding + (obj2 + (req + "operations" + (conv to_list of_list + @@ def "inlined.attestation_mempool.contents" + @@ union + [ + make `Without_dal attestation_case; + make `With_dal attestation_with_dal_case; + ])) + (varopt "signature" Signature.encoding))) + + let seed_nonce_revelation_case = + Case + { + tag = 1; + name = "seed_nonce_revelation"; + encoding = + obj2 + (req "level" Raw_level_repr.encoding) + (req "nonce" Seed_repr.nonce_encoding); + select = + (function + | Contents (Seed_nonce_revelation _ as op) -> Some op | _ -> None); + proj = (fun (Seed_nonce_revelation {level; nonce}) -> (level, nonce)); + inj = (fun (level, nonce) -> Seed_nonce_revelation {level; nonce}); + } + + let vdf_revelation_case = + Case + { + tag = 8; + name = "vdf_revelation"; + encoding = obj1 (req "solution" Seed_repr.vdf_solution_encoding); + select = + (function Contents (Vdf_revelation _ as op) -> Some op | _ -> None); + proj = (function Vdf_revelation {solution} -> solution); + inj = (fun solution -> Vdf_revelation {solution}); + } + + (* Encoding case that accepts legacy double preattestation evidence name : + `double_preendorsement_evidence` in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let double_preendorsement_evidence_case : + Kind.double_preattestation_evidence case = + Case + { + tag = 7; + name = "double_preendorsement_evidence"; + encoding = + obj2 + (req "op1" (dynamic_size preendorsement_encoding)) + (req "op2" (dynamic_size preendorsement_encoding)); + select = + (function + | Contents (Double_preattestation_evidence _ as op) -> Some op + | _ -> None); + proj = (fun (Double_preattestation_evidence {op1; op2}) -> (op1, op2)); + inj = (fun (op1, op2) -> Double_preattestation_evidence {op1; op2}); + } + + let double_preattestation_evidence_case : + Kind.double_preattestation_evidence case = + Case + { + tag = 7; + name = "double_preattestation_evidence"; + encoding = + obj2 + (req "op1" (dynamic_size preattestation_encoding)) + (req "op2" (dynamic_size preattestation_encoding)); + select = + (function + | Contents (Double_preattestation_evidence _ as op) -> Some op + | _ -> None); + proj = (fun (Double_preattestation_evidence {op1; op2}) -> (op1, op2)); + inj = (fun (op1, op2) -> Double_preattestation_evidence {op1; op2}); + } + + (* Encoding case that accepts legacy double attestation evidence name : + `double_endorsement_evidence` in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let double_endorsement_evidence_case : Kind.double_attestation_evidence case = + Case + { + tag = 2; + name = "double_endorsement_evidence"; + encoding = + obj2 + (req "op1" (dynamic_size endorsement_encoding)) + (req "op2" (dynamic_size endorsement_encoding)); + select = + (function + | Contents (Double_attestation_evidence _ as op) -> Some op + | _ -> None); + proj = (fun (Double_attestation_evidence {op1; op2}) -> (op1, op2)); + inj = (fun (op1, op2) -> Double_attestation_evidence {op1; op2}); + } + + let double_attestation_evidence_case : Kind.double_attestation_evidence case = + Case + { + tag = 2; + name = "double_attestation_evidence"; + encoding = + obj2 + (req "op1" (dynamic_size attestation_encoding)) + (req "op2" (dynamic_size attestation_encoding)); + select = + (function + | Contents (Double_attestation_evidence _ as op) -> Some op + | _ -> None); + proj = (fun (Double_attestation_evidence {op1; op2}) -> (op1, op2)); + inj = (fun (op1, op2) -> Double_attestation_evidence {op1; op2}); + } + + let double_baking_evidence_case = + Case + { + tag = 3; + name = "double_baking_evidence"; + encoding = + obj2 + (req "bh1" (dynamic_size Block_header_repr.encoding)) + (req "bh2" (dynamic_size Block_header_repr.encoding)); + select = + (function + | Contents (Double_baking_evidence _ as op) -> Some op | _ -> None); + proj = (fun (Double_baking_evidence {bh1; bh2}) -> (bh1, bh2)); + inj = (fun (bh1, bh2) -> Double_baking_evidence {bh1; bh2}); + } + + let activate_account_case = + Case + { + tag = 4; + name = "activate_account"; + encoding = + obj2 + (req "pkh" Ed25519.Public_key_hash.encoding) + (req "secret" Blinded_public_key_hash.activation_code_encoding); + select = + (function + | Contents (Activate_account _ as op) -> Some op | _ -> None); + proj = + (fun (Activate_account {id; activation_code}) -> + (id, activation_code)); + inj = + (fun (id, activation_code) -> Activate_account {id; activation_code}); + } + + let proposals_case = + Case + { + tag = 5; + name = "proposals"; + encoding = + obj3 + (req "source" Signature.Public_key_hash.encoding) + (req "period" int32) + (req + "proposals" + (list + ~max_length:Constants_repr.max_proposals_per_delegate + Protocol_hash.encoding)); + select = + (function Contents (Proposals _ as op) -> Some op | _ -> None); + proj = + (fun (Proposals {source; period; proposals}) -> + (source, period, proposals)); + inj = + (fun (source, period, proposals) -> + Proposals {source; period; proposals}); + } + + let ballot_case = + Case + { + tag = 6; + name = "ballot"; + encoding = + obj4 + (req "source" Signature.Public_key_hash.encoding) + (req "period" int32) + (req "proposal" Protocol_hash.encoding) + (req "ballot" Vote_repr.ballot_encoding); + select = (function Contents (Ballot _ as op) -> Some op | _ -> None); + proj = + (function + | Ballot {source; period; proposal; ballot} -> + (source, period, proposal, ballot)); + inj = + (fun (source, period, proposal, ballot) -> + Ballot {source; period; proposal; ballot}); + } + + let drain_delegate_case = + Case + { + tag = 9; + name = "drain_delegate"; + encoding = + obj3 + (req "consensus_key" Signature.Public_key_hash.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "destination" Signature.Public_key_hash.encoding); + select = + (function Contents (Drain_delegate _ as op) -> Some op | _ -> None); + proj = + (function + | Drain_delegate {consensus_key; delegate; destination} -> + (consensus_key, delegate, destination)); + inj = + (fun (consensus_key, delegate, destination) -> + Drain_delegate {consensus_key; delegate; destination}); + } + + let failing_noop_case = + Case + { + tag = 17; + name = "failing_noop"; + encoding = obj1 (req "arbitrary" (string Hex)); + select = + (function Contents (Failing_noop _ as op) -> Some op | _ -> None); + proj = (function Failing_noop message -> message); + inj = (function message -> Failing_noop message); + } + + let manager_encoding = + obj5 + (req "source" Signature.Public_key_hash.encoding) + (req "fee" Tez_repr.encoding) + (req "counter" Manager_counter_repr.encoding_for_operation) + (req "gas_limit" (check_size 10 Gas_limit_repr.Arith.n_integral_encoding)) + (req "storage_limit" (check_size 10 n)) + + let extract : type kind. kind Kind.manager contents -> _ = function + | Manager_operation + {source; fee; counter; gas_limit; storage_limit; operation = _} -> + (source, fee, counter, gas_limit, storage_limit) + + let rebuild (source, fee, counter, gas_limit, storage_limit) operation = + Manager_operation + {source; fee; counter; gas_limit; storage_limit; operation} + + let make_manager_case tag (type kind) + (Manager_operations.MCase mcase : kind Manager_operations.case) = + Case + { + tag; + name = mcase.name; + encoding = merge_objs manager_encoding mcase.encoding; + select = + (function + | Contents (Manager_operation ({operation; _} as op)) -> ( + match mcase.select (Manager operation) with + | None -> None + | Some operation -> Some (Manager_operation {op with operation})) + | _ -> None); + proj = + (function + | Manager_operation {operation; _} as op -> + (extract op, mcase.proj operation)); + inj = (fun (op, contents) -> rebuild op (mcase.inj contents)); + } + + let reveal_case = make_manager_case 107 Manager_operations.reveal_case + + let transaction_case = + make_manager_case 108 Manager_operations.transaction_case + + let origination_case = + make_manager_case 109 Manager_operations.origination_case + + let delegation_case = make_manager_case 110 Manager_operations.delegation_case + + let register_global_constant_case = + make_manager_case 111 Manager_operations.register_global_constant_case + + let set_deposits_limit_case = + make_manager_case 112 Manager_operations.set_deposits_limit_case + + let increase_paid_storage_case = + make_manager_case 113 Manager_operations.increase_paid_storage_case + + let update_consensus_key_case = + make_manager_case 114 Manager_operations.update_consensus_key_case + + let transfer_ticket_case = + make_manager_case + transfer_ticket_tag + Manager_operations.transfer_ticket_case + + let dal_publish_commitment_case = + make_manager_case + dal_publish_commitment_tag + Manager_operations.dal_publish_commitment_case + + let sc_rollup_originate_case = + make_manager_case + sc_rollup_operation_origination_tag + Manager_operations.sc_rollup_originate_case + + let sc_rollup_add_messages_case = + make_manager_case + sc_rollup_operation_add_message_tag + Manager_operations.sc_rollup_add_messages_case + + let sc_rollup_cement_case = + make_manager_case + sc_rollup_operation_cement_tag + Manager_operations.sc_rollup_cement_case + + let sc_rollup_publish_case = + make_manager_case + sc_rollup_operation_publish_tag + Manager_operations.sc_rollup_publish_case + + let sc_rollup_refute_case = + make_manager_case + sc_rollup_operation_refute_tag + Manager_operations.sc_rollup_refute_case + + let sc_rollup_timeout_case = + make_manager_case + sc_rollup_operation_timeout_tag + Manager_operations.sc_rollup_timeout_case + + let sc_rollup_execute_outbox_message_case = + make_manager_case + sc_rollup_execute_outbox_message_tag + Manager_operations.sc_rollup_execute_outbox_message_case + + let sc_rollup_recover_bond_case = + make_manager_case + sc_rollup_operation_recover_bond_tag + Manager_operations.sc_rollup_recover_bond_case + + let zk_rollup_origination_case = + make_manager_case + zk_rollup_operation_create_tag + Manager_operations.zk_rollup_origination_case + + let zk_rollup_publish_case = + make_manager_case + zk_rollup_operation_publish_tag + Manager_operations.zk_rollup_publish_case + + let zk_rollup_update_case = + make_manager_case + zk_rollup_operation_update_tag + Manager_operations.zk_rollup_update_case + + type packed_case = PCase : 'b case -> packed_case + + let common_cases = + [ + PCase seed_nonce_revelation_case; + PCase vdf_revelation_case; + PCase double_baking_evidence_case; + PCase activate_account_case; + PCase proposals_case; + PCase ballot_case; + PCase reveal_case; + PCase transaction_case; + PCase origination_case; + PCase delegation_case; + PCase set_deposits_limit_case; + PCase increase_paid_storage_case; + PCase update_consensus_key_case; + PCase drain_delegate_case; + PCase failing_noop_case; + PCase register_global_constant_case; + PCase transfer_ticket_case; + PCase dal_publish_commitment_case; + PCase sc_rollup_originate_case; + PCase sc_rollup_add_messages_case; + PCase sc_rollup_cement_case; + PCase sc_rollup_publish_case; + PCase sc_rollup_refute_case; + PCase sc_rollup_timeout_case; + PCase sc_rollup_execute_outbox_message_case; + PCase sc_rollup_recover_bond_case; + PCase zk_rollup_origination_case; + PCase zk_rollup_publish_case; + PCase zk_rollup_update_case; + ] + + let contents_cases = + PCase preattestation_case :: PCase attestation_case + :: PCase attestation_with_dal_case + :: PCase double_preattestation_evidence_case + :: PCase double_attestation_evidence_case :: common_cases + + (** Encoding cases that accepts legacy attestation name : `endorsement` (and + preendorsement, double__evidence) in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements + kinds in JSON will not be accepted any more by the protocol (Planned for + protocol Q). *) + let contents_cases_with_legacy_attestation_name = + PCase preendorsement_case :: PCase endorsement_case + :: PCase endorsement_with_dal_case + :: PCase double_preendorsement_evidence_case + :: PCase double_endorsement_evidence_case :: common_cases + + let contents_encoding = + let make (PCase (Case {tag; name; encoding; select; proj; inj})) = + assert (not @@ reserved_tag tag) ; + case + (Tag tag) + name + encoding + (fun o -> match select o with None -> None | Some o -> Some (proj o)) + (fun x -> Contents (inj x)) + in + def "operation.alpha.contents" @@ union (List.map make contents_cases) + + let contents_encoding_with_legacy_attestation_name = + let make (PCase (Case {tag; name; encoding; select; proj; inj})) = + assert (not @@ reserved_tag tag) ; + case + (Tag tag) + name + encoding + (fun o -> match select o with None -> None | Some o -> Some (proj o)) + (fun x -> Contents (inj x)) + in + def "operation_with_legacy_attestation_name.alpha.contents" + @@ union (List.map make contents_cases_with_legacy_attestation_name) + + let contents_list_encoding = + conv_with_guard to_list of_list_internal (Variable.list contents_encoding) + + let contents_list_encoding_with_legacy_attestation_name = + conv_with_guard + to_list + of_list_internal + (Variable.list contents_encoding_with_legacy_attestation_name) + + let protocol_data_json_encoding = + conv + (fun (Operation_data {contents; signature}) -> + (Contents_list contents, signature)) + (fun (Contents_list contents, signature) -> + Operation_data {contents; signature}) + (obj2 + (req "contents" (dynamic_size contents_list_encoding)) + (opt "signature" Signature.encoding)) + + let protocol_data_json_encoding_with_legacy_attestation_name = + conv + (fun (Operation_data {contents; signature}) -> + (Contents_list contents, signature)) + (fun (Contents_list contents, signature) -> + Operation_data {contents; signature}) + (obj2 + (req + "contents" + (dynamic_size contents_list_encoding_with_legacy_attestation_name)) + (opt "signature" Signature.encoding)) + + type contents_or_signature_prefix = + | Actual_contents of packed_contents + | Signature_prefix of Signature.prefix + + let contents_or_signature_prefix_encoding = + let make_contents (PCase (Case {tag; name; encoding; select; proj; inj})) = + assert (not @@ reserved_tag tag) ; + case + (Tag tag) + name + encoding + (function + | Actual_contents o -> ( + match select o with None -> None | Some o -> Some (proj o)) + | _ -> None) + (fun x -> Actual_contents (Contents (inj x))) + in + def "operation.alpha.contents_or_signature_prefix" + @@ union + @@ case + (Tag signature_prefix_tag) + "signature_prefix" + (obj1 (req "signature_prefix" Signature.prefix_encoding)) + (function Signature_prefix prefix -> Some prefix | _ -> None) + (fun prefix -> Signature_prefix prefix) + (* The case signature_prefix is added to the operation's contents so that + we can store the prefix of BLS signatures without breaking the + encoding of operations. *) + :: List.map make_contents contents_cases + + let of_contents_and_signature_prefix contents_and_prefix = + let open Result_syntax in + let rec loop acc = function + | [] -> Ok acc + | Signature_prefix _ :: _ -> Error "Signature prefix must appear last" + | Actual_contents (Contents o) :: os -> ( + match (o, acc) with + | ( Manager_operation _, + Contents_list (Single (Manager_operation _) as rest) ) -> + (loop [@tailcall]) (Contents_list (Cons (o, rest))) os + | Manager_operation _, Contents_list (Cons _ as rest) -> + (loop [@tailcall]) (Contents_list (Cons (o, rest))) os + | _ -> + Error + "Operation list of length > 1 should only contain manager \ + operations.") + in + let rev_contents, prefix = + match List.rev contents_and_prefix with + | Signature_prefix prefix :: rev_contents -> (rev_contents, Some prefix) + | rev_contents -> (rev_contents, None) + in + let+ packed_contents = + match rev_contents with + | [] -> Error "Operation lists should not be empty." + | Signature_prefix _ :: _ -> Error "Signature prefix must appear last" + | Actual_contents (Contents o) :: os -> loop (Contents_list (Single o)) os + in + (packed_contents, prefix) + + let protocol_data_binary_encoding = + let open Result_syntax in + conv_with_guard + (fun (Operation_data {contents; signature}) -> + let contents_list = + List.map (fun c -> Actual_contents c) + @@ to_list (Contents_list contents) + in + let contents_and_signature_prefix, sig_suffix = + match signature with + | None -> (contents_list, Signature.(to_bytes zero)) + | Some signature -> ( + let {Signature.prefix; suffix} = + Signature.split_signature signature + in + match prefix with + | None -> (contents_list, suffix) + | Some prefix -> + (contents_list @ [Signature_prefix prefix], suffix)) + in + (contents_and_signature_prefix, sig_suffix)) + (fun (contents_and_signature_prefix, suffix) -> + let* Contents_list contents, prefix = + of_contents_and_signature_prefix contents_and_signature_prefix + in + let+ signature = + Result.of_option ~error:"Invalid signature" + @@ Signature.of_splitted {Signature.prefix; suffix} + in + let signature = + match prefix with + | None -> + if Signature.(signature = zero) then None else Some signature + | Some _ -> Some signature + in + Operation_data {contents; signature}) + (obj2 + (req + "contents_and_signature_prefix" + (Variable.list contents_or_signature_prefix_encoding)) + (req "signature_suffix" (Fixed.bytes Hex 64))) + + (* The binary and JSON encodings are different for protocol data, because we + have to fit BLS signatures (which are 96 bytes long) in a backward + compatible manner with fixed size signatures of 64 bytes. + + The JSON encoding is the same as in the previous protocols. + + To support BLS signatures, we extract the prefix of the signature and fit + it inside the field [contents] while keeping the 64 bytes suffix in the + same place as the other signature kinds (i.e. at the end). + + For instance the binary protocol data for a transfer operation signed by a + Ed25519 key would look like: + + +----------------+------------+ + | Transaction | signature | + +----+------+----+------------+ + | 6C | ... | 00 | (64 bytes) | + +----+------+----+------------+ + + The same transfer signed by a BLS key would be instead: + + +----------------+----------------------------+-------------------+ + | Transaction | signature prefix | signature suffix | + +----+------+----+----+----+------------------+-------------------+ + | 6C | ... | 00 | ff | 03 | (first 32 bytes) | (last 64 bytes) | + +----+------+----+----+----+------------------+-------------------+ + + Which can also be viewed with an equivalent schema: + + +----------------+----+---------------+--------------------------+ + | Transaction | ff | signature tag | signature | + +----+------+----+----+---------------+--------------------------+ + | 6C | ... | 00 | ff | 03 (BLS) | (96 bytes BLS signature) | + +----+------+----+----+---------------+--------------------------+ + + NOTE: BLS only supports the tagged format and Ed25519, Secp256k1 and P256 + signatures only support the untagged one. The latter restriction is only + here to guarantee unicity of the binary representation for signatures. + *) + let protocol_data_encoding = + def "operation.alpha.contents_and_signature" + @@ splitted + ~json:protocol_data_json_encoding + ~binary:protocol_data_binary_encoding + + let protocol_data_encoding_with_legacy_attestation_name = + def "operation_with_legacy_attestation_name.alpha.contents_and_signature" + @@ splitted + ~json:protocol_data_json_encoding_with_legacy_attestation_name + ~binary:protocol_data_binary_encoding + + let operation_encoding = + conv + (fun {shell; protocol_data} -> (shell, protocol_data)) + (fun (shell, protocol_data) -> {shell; protocol_data}) + (merge_objs Operation.shell_header_encoding protocol_data_encoding) + + let operation_encoding_with_legacy_attestation_name = + conv + (fun {shell; protocol_data} -> (shell, protocol_data)) + (fun (shell, protocol_data) -> {shell; protocol_data}) + (merge_objs + Operation.shell_header_encoding + protocol_data_encoding_with_legacy_attestation_name) + + let unsigned_operation_encoding = + def "operation.alpha.unsigned_operation" + @@ merge_objs + Operation.shell_header_encoding + (obj1 (req "contents" contents_list_encoding)) + + let unsigned_operation_encoding_with_legacy_attestation_name = + def "operation_with_legacy_attestation_name.alpha.unsigned_operation" + @@ merge_objs + Operation.shell_header_encoding + (obj1 + (req "contents" contents_list_encoding_with_legacy_attestation_name)) +end + +let encoding = Encoding.operation_encoding + +let encoding_with_legacy_attestation_name = + Encoding.operation_encoding_with_legacy_attestation_name + +let contents_encoding = Encoding.contents_encoding + +let contents_encoding_with_legacy_attestation_name = + Encoding.contents_encoding_with_legacy_attestation_name + +let contents_list_encoding = Encoding.contents_list_encoding + +let contents_list_encoding_with_legacy_attestation_name = + Encoding.contents_list_encoding_with_legacy_attestation_name + +let protocol_data_encoding = Encoding.protocol_data_encoding + +let protocol_data_encoding_with_legacy_attestation_name = + Encoding.protocol_data_encoding_with_legacy_attestation_name + +let unsigned_operation_encoding = Encoding.unsigned_operation_encoding + +let unsigned_operation_encoding_with_legacy_attestation_name = + Encoding.unsigned_operation_encoding_with_legacy_attestation_name + +let raw ({shell; protocol_data} : _ operation) = + let proto = + Data_encoding.Binary.to_bytes_exn + protocol_data_encoding + (Operation_data protocol_data) + in + {Operation.shell; proto} + +(** Each operation belongs to a validation pass that is an integer + abstracting its priority in a block. Except Failing_noop. *) + +let consensus_pass = 0 + +let voting_pass = 1 + +let anonymous_pass = 2 + +let manager_pass = 3 + +(** [acceptable_pass op] returns either the validation_pass of [op] + when defines and None when [op] is [Failing_noop]. *) +let acceptable_pass (op : packed_operation) = + let (Operation_data protocol_data) = op.protocol_data in + match protocol_data.contents with + | Single (Failing_noop _) -> None + | Single (Preattestation _) -> Some consensus_pass + | Single (Attestation _) -> Some consensus_pass + | Single (Proposals _) -> Some voting_pass + | Single (Ballot _) -> Some voting_pass + | Single (Seed_nonce_revelation _) -> Some anonymous_pass + | Single (Vdf_revelation _) -> Some anonymous_pass + | Single (Double_attestation_evidence _) -> Some anonymous_pass + | Single (Double_preattestation_evidence _) -> Some anonymous_pass + | Single (Double_baking_evidence _) -> Some anonymous_pass + | Single (Activate_account _) -> Some anonymous_pass + | Single (Drain_delegate _) -> Some anonymous_pass + | Single (Manager_operation _) -> Some manager_pass + | Cons (Manager_operation _, _ops) -> Some manager_pass + +(** [compare_by_passes] orders two operations in the reverse order of + their acceptable passes. *) +let compare_by_passes op1 op2 = + match (acceptable_pass op1, acceptable_pass op2) with + | Some op1_pass, Some op2_pass -> Compare.Int.compare op2_pass op1_pass + | None, Some _ -> -1 + | Some _, None -> 1 + | None, None -> 0 + +type error += Invalid_signature (* `Permanent *) + +type error += Missing_signature (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"operation.invalid_signature" + ~title:"Invalid operation signature" + ~description: + "The operation signature is ill-formed or has been made with the wrong \ + public key" + ~pp:(fun ppf () -> Format.fprintf ppf "The operation signature is invalid") + Data_encoding.unit + (function Invalid_signature -> Some () | _ -> None) + (fun () -> Invalid_signature) ; + register_error_kind + `Permanent + ~id:"operation.missing_signature" + ~title:"Missing operation signature" + ~description: + "The operation is of a kind that must be signed, but the signature is \ + missing" + ~pp:(fun ppf () -> Format.fprintf ppf "The operation requires a signature") + Data_encoding.unit + (function Missing_signature -> Some () | _ -> None) + (fun () -> Missing_signature) ; + register_error_kind + `Permanent + ~id:"operation.contents_list_error" + ~title:"Invalid list of operation contents." + ~description: + "An operation contents list has an unexpected shape; it should be either \ + a single operation or a non-empty list of manager operations" + ~pp:(fun ppf s -> + Format.fprintf + ppf + "An operation contents list has an unexpected shape: %s" + s) + Data_encoding.(obj1 (req "message" (string Hex))) + (function Contents_list_error s -> Some s | _ -> None) + (fun s -> Contents_list_error s) + +let serialize_unsigned_operation (type kind) + ({shell; protocol_data} : kind operation) : bytes = + Data_encoding.Binary.to_bytes_exn + unsigned_operation_encoding + (shell, Contents_list protocol_data.contents) + +let unsigned_operation_length (type kind) + ({shell; protocol_data} : kind operation) : int = + Data_encoding.Binary.length + unsigned_operation_encoding + (shell, Contents_list protocol_data.contents) + +let check_signature (type kind) key chain_id (op : kind operation) = + let open Result_syntax in + let serialized_operation = serialize_unsigned_operation op in + let check ~watermark signature = + if Signature.check ~watermark key signature serialized_operation then + return_unit + else tzfail Invalid_signature + in + match op.protocol_data.signature with + | None -> tzfail Missing_signature + | Some signature -> + let watermark = + match op.protocol_data.contents with + | Single (Preattestation _) -> to_watermark (Preattestation chain_id) + | Single (Attestation _) -> to_watermark (Attestation chain_id) + | Single + ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ + | Vdf_revelation _ | Double_attestation_evidence _ + | Double_preattestation_evidence _ | Double_baking_evidence _ + | Activate_account _ | Drain_delegate _ | Manager_operation _ ) -> + Generic_operation + | Cons (Manager_operation _, _ops) -> Generic_operation + in + check ~watermark signature + +let hash_raw = Operation.hash + +let hash (o : _ operation) = + let proto = + Data_encoding.Binary.to_bytes_exn + protocol_data_encoding + (Operation_data o.protocol_data) + in + Operation.hash {shell = o.shell; proto} + +let hash_packed (o : packed_operation) = + let proto = + Data_encoding.Binary.to_bytes_exn protocol_data_encoding o.protocol_data + in + Operation.hash {shell = o.shell; proto} + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +let equal_manager_operation_kind : + type a b. a manager_operation -> b manager_operation -> (a, b) eq option = + fun op1 op2 -> + match (op1, op2) with + | Reveal _, Reveal _ -> Some Eq + | Reveal _, _ -> None + | Transaction _, Transaction _ -> Some Eq + | Transaction _, _ -> None + | Origination _, Origination _ -> Some Eq + | Origination _, _ -> None + | Delegation _, Delegation _ -> Some Eq + | Delegation _, _ -> None + | Register_global_constant _, Register_global_constant _ -> Some Eq + | Register_global_constant _, _ -> None + | Set_deposits_limit _, Set_deposits_limit _ -> Some Eq + | Set_deposits_limit _, _ -> None + | Increase_paid_storage _, Increase_paid_storage _ -> Some Eq + | Increase_paid_storage _, _ -> None + | Update_consensus_key _, Update_consensus_key _ -> Some Eq + | Update_consensus_key _, _ -> None + | Transfer_ticket _, Transfer_ticket _ -> Some Eq + | Transfer_ticket _, _ -> None + | Dal_publish_commitment _, Dal_publish_commitment _ -> Some Eq + | Dal_publish_commitment _, _ -> None + | Sc_rollup_originate _, Sc_rollup_originate _ -> Some Eq + | Sc_rollup_originate _, _ -> None + | Sc_rollup_add_messages _, Sc_rollup_add_messages _ -> Some Eq + | Sc_rollup_add_messages _, _ -> None + | Sc_rollup_cement _, Sc_rollup_cement _ -> Some Eq + | Sc_rollup_cement _, _ -> None + | Sc_rollup_publish _, Sc_rollup_publish _ -> Some Eq + | Sc_rollup_publish _, _ -> None + | Sc_rollup_refute _, Sc_rollup_refute _ -> Some Eq + | Sc_rollup_refute _, _ -> None + | Sc_rollup_timeout _, Sc_rollup_timeout _ -> Some Eq + | Sc_rollup_timeout _, _ -> None + | Sc_rollup_execute_outbox_message _, Sc_rollup_execute_outbox_message _ -> + Some Eq + | Sc_rollup_execute_outbox_message _, _ -> None + | Sc_rollup_recover_bond _, Sc_rollup_recover_bond _ -> Some Eq + | Sc_rollup_recover_bond _, _ -> None + | Zk_rollup_origination _, Zk_rollup_origination _ -> Some Eq + | Zk_rollup_origination _, _ -> None + | Zk_rollup_publish _, Zk_rollup_publish _ -> Some Eq + | Zk_rollup_publish _, _ -> None + | Zk_rollup_update _, Zk_rollup_update _ -> Some Eq + | Zk_rollup_update _, _ -> None + +let equal_contents_kind : type a b. a contents -> b contents -> (a, b) eq option + = + fun op1 op2 -> + match (op1, op2) with + | Preattestation _, Preattestation _ -> Some Eq + | Preattestation _, _ -> None + | Attestation _, Attestation _ -> Some Eq + | Attestation _, _ -> None + | Seed_nonce_revelation _, Seed_nonce_revelation _ -> Some Eq + | Seed_nonce_revelation _, _ -> None + | Vdf_revelation _, Vdf_revelation _ -> Some Eq + | Vdf_revelation _, _ -> None + | Double_attestation_evidence _, Double_attestation_evidence _ -> Some Eq + | Double_attestation_evidence _, _ -> None + | Double_preattestation_evidence _, Double_preattestation_evidence _ -> + Some Eq + | Double_preattestation_evidence _, _ -> None + | Double_baking_evidence _, Double_baking_evidence _ -> Some Eq + | Double_baking_evidence _, _ -> None + | Activate_account _, Activate_account _ -> Some Eq + | Activate_account _, _ -> None + | Proposals _, Proposals _ -> Some Eq + | Proposals _, _ -> None + | Ballot _, Ballot _ -> Some Eq + | Ballot _, _ -> None + | Drain_delegate _, Drain_delegate _ -> Some Eq + | Drain_delegate _, _ -> None + | Failing_noop _, Failing_noop _ -> Some Eq + | Failing_noop _, _ -> None + | Manager_operation op1, Manager_operation op2 -> ( + match equal_manager_operation_kind op1.operation op2.operation with + | None -> None + | Some Eq -> Some Eq) + | Manager_operation _, _ -> None + +let rec equal_contents_kind_list : + type a b. a contents_list -> b contents_list -> (a, b) eq option = + fun op1 op2 -> + match (op1, op2) with + | Single op1, Single op2 -> equal_contents_kind op1 op2 + | Single _, Cons _ -> None + | Cons _, Single _ -> None + | Cons (op1, ops1), Cons (op2, ops2) -> ( + match equal_contents_kind op1 op2 with + | None -> None + | Some Eq -> ( + match equal_contents_kind_list ops1 ops2 with + | None -> None + | Some Eq -> Some Eq)) + +let equal : type a b. a operation -> b operation -> (a, b) eq option = + fun op1 op2 -> + if not (Operation_hash.equal (hash op1) (hash op2)) then None + else + equal_contents_kind_list + op1.protocol_data.contents + op2.protocol_data.contents + +(** {2 Comparing operations} *) + +(** Precondition: both operations are [valid]. Hence, it is possible + to compare them without any state representation. *) + +(** {3 Operation passes} *) + +type consensus_pass_type + +type voting_pass_type + +type anonymous_pass_type + +type manager_pass_type + +type noop_pass_type + +type _ pass = + | Consensus : consensus_pass_type pass + | Voting : voting_pass_type pass + | Anonymous : anonymous_pass_type pass + | Manager : manager_pass_type pass + | Noop : noop_pass_type pass + +(** Pass comparison. *) +let compare_inner_pass : type a b. a pass -> b pass -> int = + fun pass1 pass2 -> + match (pass1, pass2) with + | Consensus, (Voting | Anonymous | Manager | Noop) -> 1 + | (Voting | Anonymous | Manager | Noop), Consensus -> -1 + | Voting, (Anonymous | Manager | Noop) -> 1 + | (Anonymous | Manager | Noop), Voting -> -1 + | Anonymous, (Manager | Noop) -> 1 + | (Manager | Noop), Anonymous -> -1 + | Manager, Noop -> 1 + | Noop, Manager -> -1 + | Consensus, Consensus + | Voting, Voting + | Anonymous, Anonymous + | Manager, Manager + | Noop, Noop -> + 0 + +(** {3 Operation weights} *) + +(** [round_infos] is the pair of a [level] convert into {!int32} and + [round] convert into an {!int}. + + By convention, if the [round] is from an operation round that + failed to convert in a {!int}, the value of [round] is (-1). *) +type round_infos = {level : int32; round : int} + +(** [preattestation_infos] is the pair of a {!round_infos} and a [slot] + convert into an {!int}. *) +type preattestation_infos = {round : round_infos; slot : int} + +(** [attestation_infos] is the tuple consisting of a {!round_infos} value, a + [slot], and the number of DAL slots in the DAL attestation. *) +type attestation_infos = { + round_infos : round_infos; + slot : int; + number_of_dal_attested_slots : int; +} + +(** [double_baking_infos] is the pair of a {!round_infos} and a + {!block_header} hash. *) +type double_baking_infos = {round : round_infos; bh_hash : Block_hash.t} + +(** Compute a {!round_infos} from a {consensus_content} of a valid + operation. Hence, the [round] must convert in {!int}. + + Precondition: [c] comes from a valid operation. The [round] from a + valid operation should succeed to convert in {!int}. Hence, for the + unreachable path where the convertion failed, we put (-1) as + [round] value. *) +let round_infos_from_consensus_content (c : consensus_content) = + let level = Raw_level_repr.to_int32 c.level in + match Round_repr.to_int c.round with + | Ok round -> {level; round} + | Error _ -> {level; round = -1} + +(** Compute a {!attestation_infos} from a {!consensus_content}. It is + used to compute the weight of {!Attestation} and {!Preattestation}. + + Precondition: [c] comes from a valid operation. The {!Attestation} + or {!Preattestation} is valid, so its [round] must succeed to + convert into an {!int}. Hence, for the unreachable path where the + convertion fails, we put (-1) as [round] value (see + {!round_infos_from_consensus_content}). *) +let attestation_infos_from_consensus_content (c : consensus_content) = + let slot = Slot_repr.to_int c.slot in + let round = round_infos_from_consensus_content c in + {round; slot} + +(** Compute a {!attestation_infos} value from a {!consensus_content} value + and an optional {!dal_content} value. It is used to compute the weight of + an {!Attestation}. + + An {!Attestation} with no DAL content or with a DAL content that has 0 + attested DAL slots have the same weight (everything else being + equal). That's ok, because they are semantically equal, therefore it + does not matter which one is picked. + + Precondition: [c] and [d] come from a valid operation. *) +let attestation_infos_from_content (c : consensus_content) + (d : dal_content option) = + let slot = Slot_repr.to_int c.slot in + let round_infos = round_infos_from_consensus_content c in + { + round_infos; + slot; + number_of_dal_attested_slots = + Option.fold + ~none:0 + ~some:(fun d -> + Dal_attestation_repr.number_of_attested_slots d.attestation) + d; + } + +(** Compute a {!double_baking_infos} and a {!Block_header_repr.hash} + from a {!Block_header_repr.t}. It is used to compute the weight of + a {!Double_baking_evidence}. + + Precondition: [bh] comes from a valid operation. The + {!Double_baking_envidence} is valid, so its fitness from its first + denounced block header must succeed, and the round from this + fitness must convert in a {!int}. Hence, for the unreachable paths + where either the convertion fails or the fitness is not + retrievable, we put (-1) as [round] value. *) +let consensus_infos_and_hash_from_block_header (bh : Block_header_repr.t) = + let level = bh.shell.level in + let bh_hash = Block_header_repr.hash bh in + let round = + match Fitness_repr.from_raw bh.shell.fitness with + | Ok bh_fitness -> ( + match Round_repr.to_int (Fitness_repr.round bh_fitness) with + | Ok round -> {level; round} + | Error _ -> {level; round = -1}) + | Error _ -> {level; round = -1} + in + {round; bh_hash} + +(** The weight of an operation. + + Given an operation, its [weight] carries on static information that + is used to compare it to an operation of the same pass. + Operation weight are defined by validation pass. + + The [weight] of an {!Attestation} or {!Preattestation} depends on its + {!attestation_infos}. For {!Attestation}s it also depends on the number of + attested DAL slots. + + The [weight] of a voting operation depends on the pair of its + [period] and [source]. + + The [weight] of a {!Vdf_revelation} depends on its [solution]. + + The [weight] of a {!Seed_nonce_revelation} depends on its [level] + converted in {!int32}. + + The [weight] of a {!Double_preattestation} or + {!Double_attestation} depends on the [level] and [round] of their + first denounciated operations. The [level] and [round] are wrapped + in a {!round_infos}. + + The [weight] of a {!Double_baking} depends on the [level], [round] + and [hash] of its first denounciated block_header. the [level] and + [round] are wrapped in a {!double_baking_infos}. + + The [weight] of an {!Activate_account} depends on its public key + hash. + + The [weight] of an {!Drain_delegate} depends on the public key + hash of the delegate. + + The [weight] of {!Manager_operation} depends on its [fee] and + [gas_limit] ratio expressed in {!Q.t}. *) +type _ weight = + | Weight_attestation : attestation_infos -> consensus_pass_type weight + | Weight_preattestation : preattestation_infos -> consensus_pass_type weight + | Weight_proposals : + int32 * Signature.Public_key_hash.t + -> voting_pass_type weight + | Weight_ballot : + int32 * Signature.Public_key_hash.t + -> voting_pass_type weight + | Weight_seed_nonce_revelation : int32 -> anonymous_pass_type weight + | Weight_vdf_revelation : Seed_repr.vdf_solution -> anonymous_pass_type weight + | Weight_double_preattestation : round_infos -> anonymous_pass_type weight + | Weight_double_attestation : round_infos -> anonymous_pass_type weight + | Weight_double_baking : double_baking_infos -> anonymous_pass_type weight + | Weight_activate_account : + Ed25519.Public_key_hash.t + -> anonymous_pass_type weight + | Weight_drain_delegate : + Signature.Public_key_hash.t + -> anonymous_pass_type weight + | Weight_manager : Q.t * Signature.public_key_hash -> manager_pass_type weight + | Weight_noop : noop_pass_type weight + +(** The weight of an operation is the pair of its pass and weight. *) +type operation_weight = W : 'pass pass * 'pass weight -> operation_weight + +(** The {!weight} of a batch of {!Manager_operation} depends on the + sum of all [fee] and the sum of all [gas_limit]. + + Precondition: [op] is a valid manager operation: its sum + of accumulated [fee] must succeed. Hence, in the unreachable path where + the [fee] sum fails, we put [Tez_repr.zero] as its value. *) +let cumulate_fee_and_gas_of_manager : + type kind. + kind Kind.manager contents_list -> + Tez_repr.t * Gas_limit_repr.Arith.integral = + fun op -> + let add_without_error acc y = + match Tez_repr.(acc +? y) with + | Ok v -> v + | Error _ -> (* This cannot happen *) acc + in + let rec loop : + type kind. 'a -> 'b -> kind Kind.manager contents_list -> 'a * 'b = + fun fees_acc gas_limit_acc -> function + | Single (Manager_operation {fee; gas_limit; _}) -> + let total_fees = add_without_error fees_acc fee in + let total_gas_limit = + Gas_limit_repr.Arith.add gas_limit_acc gas_limit + in + (total_fees, total_gas_limit) + | Cons (Manager_operation {fee; gas_limit; _}, manops) -> + let fees_acc = add_without_error fees_acc fee in + let gas_limit_acc = Gas_limit_repr.Arith.add gas_limit gas_limit_acc in + loop fees_acc gas_limit_acc manops + in + loop Tez_repr.zero Gas_limit_repr.Arith.zero op + +(** The {!weight} of a {!Manager_operation} as well as a batch of + operations is the ratio in {!int64} between its [fee] and + [gas_limit] as computed by + {!cumulate_fee_and_gas_of_manager} converted in {!Q.t}. + We assume that the manager operation valid, thus its gas limit can + never be zero. We treat this case the same as gas_limit = 1 for the + sake of simplicity. +*) +let weight_manager : + type kind. + kind Kind.manager contents_list -> Q.t * Signature.public_key_hash = + fun op -> + let fee, glimit = cumulate_fee_and_gas_of_manager op in + let source = + match op with + | Cons (Manager_operation {source; _}, _) -> source + | Single (Manager_operation {source; _}) -> source + in + let fee_f = Q.of_int64 (Tez_repr.to_mutez fee) in + if Gas_limit_repr.Arith.(glimit = Gas_limit_repr.Arith.zero) then + (fee_f, source) + else + let gas_f = Q.of_bigint (Gas_limit_repr.Arith.integral_to_z glimit) in + (Q.(fee_f / gas_f), source) + +(** Computing the {!operation_weight} of an operation. [weight_of + (Failing_noop _)] is unreachable, for completness we define a + Weight_noop which carrries no information. *) +let weight_of : packed_operation -> operation_weight = + fun op -> + let (Operation_data protocol_data) = op.protocol_data in + match protocol_data.contents with + | Single (Failing_noop _) -> W (Noop, Weight_noop) + | Single (Preattestation consensus_content) -> + W + ( Consensus, + Weight_preattestation + (attestation_infos_from_consensus_content consensus_content) ) + | Single (Attestation {consensus_content; dal_content}) -> + W + ( Consensus, + Weight_attestation + (attestation_infos_from_content consensus_content dal_content) ) + | Single (Proposals {period; source; _}) -> + W (Voting, Weight_proposals (period, source)) + | Single (Ballot {period; source; _}) -> + W (Voting, Weight_ballot (period, source)) + | Single (Seed_nonce_revelation {level; _}) -> + W (Anonymous, Weight_seed_nonce_revelation (Raw_level_repr.to_int32 level)) + | Single (Vdf_revelation {solution}) -> + W (Anonymous, Weight_vdf_revelation solution) + | Single (Double_attestation_evidence {op1; _}) -> ( + match op1.protocol_data.contents with + | Single (Attestation {consensus_content; dal_content = _}) -> + W + ( Anonymous, + Weight_double_attestation + (round_infos_from_consensus_content consensus_content) )) + | Single (Double_preattestation_evidence {op1; _}) -> ( + match op1.protocol_data.contents with + | Single (Preattestation consensus_content) -> + W + ( Anonymous, + Weight_double_preattestation + (round_infos_from_consensus_content consensus_content) )) + | Single (Double_baking_evidence {bh1; _}) -> + let double_baking_infos = + consensus_infos_and_hash_from_block_header bh1 + in + W (Anonymous, Weight_double_baking double_baking_infos) + | Single (Activate_account {id; _}) -> + W (Anonymous, Weight_activate_account id) + | Single (Drain_delegate {delegate; _}) -> + W (Anonymous, Weight_drain_delegate delegate) + | Single (Manager_operation _) as ops -> + let manweight, src = weight_manager ops in + W (Manager, Weight_manager (manweight, src)) + | Cons (Manager_operation _, _) as ops -> + let manweight, src = weight_manager ops in + W (Manager, Weight_manager (manweight, src)) + +(** {3 Comparisons of operations' {!weight}} *) + +(** {4 Helpers} *) + +(** Compare a pair of elements in lexicographic order. *) +let compare_pair_in_lexico_order ~cmp_fst ~cmp_snd (a1, b1) (a2, b2) = + let resa = cmp_fst a1 a2 in + if Compare.Int.(resa <> 0) then resa else cmp_snd b1 b2 + +(** Compare in reverse order. *) +let compare_reverse (cmp : 'a -> 'a -> int) a b = cmp b a + +(** {4 Comparison of {!consensus_infos}} *) + +(** Two {!round_infos} pairs [(level, round)] compare in + lexicographic order: the one with the greater [level] being the + greater [round_infos]. When levels are the same, the one with the + greater [round] being the better. + + The better {!round_infos} is farther to the current state + when part of the weight of a valid consensus operation. + + The better {!round_infos} is nearer to the current state when + part of the weight of a valid denunciation. + + Precondition: the {!round_infos} are from valid operation. They + have been computed by either {!round_infos_from_consensus_content} + or {!consensus_infos_and_hash_from_block_header}. Both input + parameter from valid operations and put (-1) to the [round] in the + unreachable path where the original round fails to convert in + {!int}. *) +let compare_round_infos (infos1 : round_infos) (infos2 : round_infos) = + compare_pair_in_lexico_order + ~cmp_fst:Compare.Int32.compare + ~cmp_snd:Compare.Int.compare + (infos1.level, infos1.round) + (infos2.level, infos2.round) + +(** Two {!Preattestation}s are compared by their {!preattestation_infos}. + When their {!round_infos} are equal, they are compared according to + their [slot]: the smaller the better. *) +let compare_preattestation_infos (infos1 : preattestation_infos) + (infos2 : preattestation_infos) = + compare_pair_in_lexico_order + ~cmp_fst:compare_round_infos + ~cmp_snd:(compare_reverse Compare.Int.compare) + (infos1.round, infos1.slot) + (infos2.round, infos2.slot) + +(** Two {!double_baking_infos} are compared as their {!round_infos}. + When their {!round_infos} are equal, they are compared as the + hashes of their first denounced block header. *) +let compare_baking_infos infos1 infos2 = + compare_pair_in_lexico_order + ~cmp_fst:compare_round_infos + ~cmp_snd:Block_hash.compare + (infos1.round, infos1.bh_hash) + (infos2.round, infos2.bh_hash) + +(** Two {!Attestation}s are compared by their {!attestation_infos}. When their + {!round_infos} are equal, they are compared according to their [slot]: the + smaller the better. When the slots are also equal they are compared + according to the number of attested DAL slots: the more the better. *) +let compare_attestation_infos + {round_infos = infos1; slot = slot1; number_of_dal_attested_slots = n1} + {round_infos = infos2; slot = slot2; number_of_dal_attested_slots = n2} = + compare_pair_in_lexico_order + ~cmp_fst: + (compare_pair_in_lexico_order + ~cmp_fst:compare_round_infos + ~cmp_snd:(compare_reverse Compare.Int.compare)) + ~cmp_snd:Compare.Int.compare + ((infos1, slot1), n1) + ((infos2, slot2), n2) + +(** {4 Comparison of valid operations of the same validation pass} *) + +(** {5 Comparison of valid consensus operations} *) + +(** Comparing consensus operations by their [weight] uses the comparison on + {!attestation_infos} for {!Attestation}s and {!Preattestation}s. In case of + equality of their {!round_infos}, either they are of the same kind and their + [slot]s have to be compared in the reverse order, otherwise the + {!Attestation}s are better. In case of {!Attestation}s, the number of + attested DAL slots is taken into account when all else is equal. + + {!Dal_attestation} is smaller than the other kinds of + consensus operations. Two valid {!Dal_attestation} are + compared by {!compare_dal_attestation}. *) +let compare_consensus_weight w1 w2 = + match (w1, w2) with + | Weight_attestation infos1, Weight_attestation infos2 -> + compare_attestation_infos infos1 infos2 + | Weight_preattestation infos1, Weight_preattestation infos2 -> + compare_preattestation_infos infos1 infos2 + | ( Weight_attestation {round_infos = round_infos1; _}, + Weight_preattestation {round = round_infos2; _} ) -> + let cmp = compare_round_infos round_infos1 round_infos2 in + if Compare.Int.(cmp <> 0) then cmp else 1 + | ( Weight_preattestation {round = round_infos1; _}, + Weight_attestation {round_infos = round_infos2; _} ) -> + let cmp = compare_round_infos round_infos1 round_infos2 in + if Compare.Int.(cmp <> 0) then cmp else -1 + +(** {5 Comparison of valid voting operations} *) + +(** Two valid voting operations of the same kind are compared in the + lexicographic order of their pair of [period] and [source]. When + compared to each other, the {!Proposals} is better. *) +let compare_vote_weight w1 w2 = + let cmp i1 source1 i2 source2 = + compare_pair_in_lexico_order + (i1, source1) + (i2, source2) + ~cmp_fst:Compare.Int32.compare + ~cmp_snd:Signature.Public_key_hash.compare + in + match (w1, w2) with + | Weight_proposals (i1, source1), Weight_proposals (i2, source2) -> + cmp i1 source1 i2 source2 + | Weight_ballot (i1, source1), Weight_ballot (i2, source2) -> + cmp i1 source1 i2 source2 + | Weight_ballot _, Weight_proposals _ -> -1 + | Weight_proposals _, Weight_ballot _ -> 1 + +(** {5 Comparison of valid anonymous operations} *) + +(** Comparing two {!Double_attestation_evidence}, or two + {!Double_preattestation_evidence}, or comparing them to each other + is comparing their {!round_infos}, see {!compare_round_infos} for + more details. + + Comparing two {!Double_baking_evidence} is comparing as their + {!double_baking_infos}, see {!compare_double_baking_infos} for more + details. + + Two {!Seed_nonce_revelation} are compared by their [level]. + + Two {!Vdf_revelation} are compared by their [solution]. + + Two {!Activate_account} are compared as their [id]. + + When comparing different kind of anonymous operations, the order is + as follows: {!Double_preattestation_evidence} > + {!Double_attestation_evidence} > {!Double_baking_evidence} > + {!Vdf_revelation} > {!Seed_nonce_revelation} > {!Activate_account}. + *) +let compare_anonymous_weight w1 w2 = + match (w1, w2) with + | Weight_double_preattestation infos1, Weight_double_preattestation infos2 -> + compare_round_infos infos1 infos2 + | Weight_double_preattestation infos1, Weight_double_attestation infos2 -> + let cmp = compare_round_infos infos1 infos2 in + if Compare.Int.(cmp <> 0) then cmp else 1 + | Weight_double_attestation infos1, Weight_double_preattestation infos2 -> + let cmp = compare_round_infos infos1 infos2 in + if Compare.Int.(cmp <> 0) then cmp else -1 + | Weight_double_attestation infos1, Weight_double_attestation infos2 -> + compare_round_infos infos1 infos2 + | ( ( Weight_double_baking _ | Weight_seed_nonce_revelation _ + | Weight_vdf_revelation _ | Weight_activate_account _ + | Weight_drain_delegate _ ), + (Weight_double_preattestation _ | Weight_double_attestation _) ) -> + -1 + | ( (Weight_double_preattestation _ | Weight_double_attestation _), + ( Weight_double_baking _ | Weight_seed_nonce_revelation _ + | Weight_vdf_revelation _ | Weight_activate_account _ + | Weight_drain_delegate _ ) ) -> + 1 + | Weight_double_baking infos1, Weight_double_baking infos2 -> + compare_baking_infos infos1 infos2 + | ( ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ + | Weight_activate_account _ | Weight_drain_delegate _ ), + Weight_double_baking _ ) -> + -1 + | ( Weight_double_baking _, + ( Weight_seed_nonce_revelation _ | Weight_vdf_revelation _ + | Weight_activate_account _ | Weight_drain_delegate _ ) ) -> + 1 + | Weight_vdf_revelation solution1, Weight_vdf_revelation solution2 -> + Seed_repr.compare_vdf_solution solution1 solution2 + | ( ( Weight_seed_nonce_revelation _ | Weight_activate_account _ + | Weight_drain_delegate _ ), + Weight_vdf_revelation _ ) -> + -1 + | ( Weight_vdf_revelation _, + ( Weight_seed_nonce_revelation _ | Weight_activate_account _ + | Weight_drain_delegate _ ) ) -> + 1 + | Weight_seed_nonce_revelation l1, Weight_seed_nonce_revelation l2 -> + Compare.Int32.compare l1 l2 + | ( (Weight_activate_account _ | Weight_drain_delegate _), + Weight_seed_nonce_revelation _ ) -> + -1 + | ( Weight_seed_nonce_revelation _, + (Weight_activate_account _ | Weight_drain_delegate _) ) -> + 1 + | Weight_activate_account pkh1, Weight_activate_account pkh2 -> + Ed25519.Public_key_hash.compare pkh1 pkh2 + | Weight_drain_delegate _, Weight_activate_account _ -> -1 + | Weight_activate_account _, Weight_drain_delegate _ -> 1 + | Weight_drain_delegate pkh1, Weight_drain_delegate pkh2 -> + Signature.Public_key_hash.compare pkh1 pkh2 + +(** {5 Comparison of valid {!Manager_operation}} *) + +(** Two {!Manager_operation} are compared in the lexicographic order + of their pair of their [fee]/[gas] ratio -- as computed by + {!weight_manager} -- and their [source]. *) +let compare_manager_weight weight1 weight2 = + match (weight1, weight2) with + | Weight_manager (manweight1, source1), Weight_manager (manweight2, source2) + -> + compare_pair_in_lexico_order + (manweight1, source1) + (manweight2, source2) + ~cmp_fst:Compare.Q.compare + ~cmp_snd:Signature.Public_key_hash.compare + +(** Two {!operation_weight} are compared by their [pass], see + {!compare_inner_pass} for more details. When they have the same + [pass], they are compared by their [weight]. *) +let compare_operation_weight w1 w2 = + match (w1, w2) with + | W (Consensus, w1), W (Consensus, w2) -> compare_consensus_weight w1 w2 + | W (Voting, w1), W (Voting, w2) -> compare_vote_weight w1 w2 + | W (Anonymous, w1), W (Anonymous, w2) -> compare_anonymous_weight w1 w2 + | W (Manager, w1), W (Manager, w2) -> compare_manager_weight w1 w2 + | W (pass1, _), W (pass2, _) -> compare_inner_pass pass1 pass2 + +(** {3 Compare two valid operations} *) + +(** Two valid operations are compared as their {!operation_weight}, + see {!compare_operation_weight} for more details. + + When they are equal according to their {!operation_weight} comparison, they + compare as their hash. + Hence, [compare] returns [0] only when the hashes of both operations are + equal. + + Preconditions: [oph1] is the hash of [op1]; [oph2] the one of [op2]; and + [op1] and [op2] are both valid. *) +let compare (oph1, op1) (oph2, op2) = + let cmp_h = Operation_hash.(compare oph1 oph2) in + if Compare.Int.(cmp_h = 0) then 0 + else + let cmp = compare_operation_weight (weight_of op1) (weight_of op2) in + if Compare.Int.(cmp = 0) then cmp_h else cmp + +module Internal_for_benchmarking = struct + let serialize_unsigned_operation = serialize_unsigned_operation +end diff --git a/src/proto_020_PsParisC/lib_protocol/operation_repr.mli b/src/proto_020_PsParisC/lib_protocol/operation_repr.mli new file mode 100644 index 000000000000..b98884088c81 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/operation_repr.mli @@ -0,0 +1,828 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Low level Repr. of Operations + + Defines kinds of operations that can be performed on chain: + - preattestation + - attestation + - double baking evidence + - double preattestation evidence + - double attestation evidence + - seed nonce revelation + - account activation + - proposal (see: [Voting_repr]) + - ballot (see: [Voting_repr]) + - failing noop + - manager operation (which in turn has several types): + - revelation + - transaction + - origination + - delegation + - set deposits limitation + - smart rollup origination + - smart rollup add messages + - smart rollup publish + - smart rollup cement + - smart rollup refute + - smart rollup timeout + - smart rollup execute outbox message + - smart rollup recover bond + - zk rollup origination + - zk rollup publish + - zk rollup update + + Each of them can be encoded as raw bytes. Operations are distinguished at + type level using phantom type parameters. [packed_operation] type allows + for unifying them when required, for instance to put them on a single + list. *) + +module Kind : sig + type preattestation_consensus_kind = Preattestation_consensus_kind + + type attestation_consensus_kind = Attestation_consensus_kind + + type 'a consensus = + | Preattestation_kind : preattestation_consensus_kind consensus + | Attestation_kind : attestation_consensus_kind consensus + + type preattestation = preattestation_consensus_kind consensus + + type attestation = attestation_consensus_kind consensus + + type seed_nonce_revelation = Seed_nonce_revelation_kind + + type vdf_revelation = Vdf_revelation_kind + + type 'a double_consensus_operation_evidence = + | Double_consensus_operation_evidence + + type double_attestation_evidence = + attestation_consensus_kind double_consensus_operation_evidence + + type double_preattestation_evidence = + preattestation_consensus_kind double_consensus_operation_evidence + + type double_baking_evidence = Double_baking_evidence_kind + + type activate_account = Activate_account_kind + + type proposals = Proposals_kind + + type ballot = Ballot_kind + + type reveal = Reveal_kind + + type transaction = Transaction_kind + + type origination = Origination_kind + + type delegation = Delegation_kind + + type event = Event_kind + + type set_deposits_limit = Set_deposits_limit_kind + + type increase_paid_storage = Increase_paid_storage_kind + + type update_consensus_key = Update_consensus_key_kind + + type drain_delegate = Drain_delegate_kind + + type failing_noop = Failing_noop_kind + + type register_global_constant = Register_global_constant_kind + + type transfer_ticket = Transfer_ticket_kind + + type dal_publish_commitment = Dal_publish_commitment_kind + + type sc_rollup_originate = Sc_rollup_originate_kind + + type sc_rollup_add_messages = Sc_rollup_add_messages_kind + + type sc_rollup_cement = Sc_rollup_cement_kind + + type sc_rollup_publish = Sc_rollup_publish_kind + + type sc_rollup_refute = Sc_rollup_refute_kind + + type sc_rollup_timeout = Sc_rollup_timeout_kind + + type sc_rollup_execute_outbox_message = + | Sc_rollup_execute_outbox_message_kind + + type sc_rollup_recover_bond = Sc_rollup_recover_bond_kind + + type zk_rollup_origination = Zk_rollup_origination_kind + + type zk_rollup_publish = Zk_rollup_publish_kind + + type zk_rollup_update = Zk_rollup_update_kind + + type 'a manager = + | Reveal_manager_kind : reveal manager + | Transaction_manager_kind : transaction manager + | Origination_manager_kind : origination manager + | Delegation_manager_kind : delegation manager + | Event_manager_kind : event manager + | Register_global_constant_manager_kind : register_global_constant manager + | Set_deposits_limit_manager_kind : set_deposits_limit manager + | Increase_paid_storage_manager_kind : increase_paid_storage manager + | Update_consensus_key_manager_kind : update_consensus_key manager + | Transfer_ticket_manager_kind : transfer_ticket manager + | Dal_publish_commitment_manager_kind : dal_publish_commitment manager + | Sc_rollup_originate_manager_kind : sc_rollup_originate manager + | Sc_rollup_add_messages_manager_kind : sc_rollup_add_messages manager + | Sc_rollup_cement_manager_kind : sc_rollup_cement manager + | Sc_rollup_publish_manager_kind : sc_rollup_publish manager + | Sc_rollup_refute_manager_kind : sc_rollup_refute manager + | Sc_rollup_timeout_manager_kind : sc_rollup_timeout manager + | Sc_rollup_execute_outbox_message_manager_kind + : sc_rollup_execute_outbox_message manager + | Sc_rollup_recover_bond_manager_kind : sc_rollup_recover_bond manager + | Zk_rollup_origination_manager_kind : zk_rollup_origination manager + | Zk_rollup_publish_manager_kind : zk_rollup_publish manager + | Zk_rollup_update_manager_kind : zk_rollup_update manager +end + +type 'a consensus_operation_type = + | Attestation : Kind.attestation consensus_operation_type + | Preattestation : Kind.preattestation consensus_operation_type + +type consensus_content = { + slot : Slot_repr.t; + (* By convention, this is the validator's first slot. *) + level : Raw_level_repr.t; + (* The level of (pre)attested block. *) + round : Round_repr.t; + (* The round of (pre)attested block. *) + block_payload_hash : Block_payload_hash.t; + (* The payload hash of (pre)attested block. *) +} + +val consensus_content_encoding : consensus_content Data_encoding.t + +val pp_consensus_content : Format.formatter -> consensus_content -> unit + +(** The DAL content in an attestation operation having some level [l] refers to a + slot published at level [l - attestation_lag + 1]. Whenever there is a need + to disambiguate, one should use "attestation level" for the level inside the + operation and "attested level" for the level of the block including the + operation. We have: + - [attestation_level + 1 = attested_level] + - [published_level + attestation_lag = attested_level] *) +type dal_content = {attestation : Dal_attestation_repr.t} + +type consensus_watermark = + | Attestation of Chain_id.t + | Preattestation of Chain_id.t + +val to_watermark : consensus_watermark -> Signature.watermark + +val of_watermark : Signature.watermark -> consensus_watermark option + +type raw = Operation.t = {shell : Operation.shell_header; proto : bytes} + +val raw_encoding : raw Data_encoding.t + +(** An [operation] contains the operation header information in [shell] + and all data related to the operation itself in [protocol_data]. *) +type 'kind operation = { + shell : Operation.shell_header; + protocol_data : 'kind protocol_data; +} + +(** A [protocol_data] wraps together a signature for the operation and + the contents of the operation itself. *) +and 'kind protocol_data = { + contents : 'kind contents_list; + signature : Signature.t option; +} + +(** A [contents_list] is a list of contents, the GADT guarantees two + invariants: + - the list is not empty, and + - if the list has several elements then it only contains manager + operations. *) +and _ contents_list = + | Single : 'kind contents -> 'kind contents_list + | Cons : + 'kind Kind.manager contents * 'rest Kind.manager contents_list + -> ('kind * 'rest) Kind.manager contents_list + +(** A value of type [contents] an operation related to whether + consensus, governance or contract management. *) +and _ contents = + (* Preattestation: About consensus, preattestation of a block held by a + validator (specific to Tenderbake). *) + | Preattestation : consensus_content -> Kind.preattestation contents + (* Attestation: About consensus, attestation of a block held by a + validator. *) + | Attestation : { + consensus_content : consensus_content; + dal_content : dal_content option; + } + -> Kind.attestation contents + (* Seed_nonce_revelation: Nonces are created by bakers and are + combined to create pseudo-random seeds. Bakers are urged to reveal their + nonces after a given number of cycles to keep their block rewards + from being forfeited. *) + | Seed_nonce_revelation : { + level : Raw_level_repr.t; + nonce : Seed_repr.nonce; + } + -> Kind.seed_nonce_revelation contents + (* Vdf_revelation: VDF are computed from the seed generated by the revealed + nonces. *) + | Vdf_revelation : { + solution : Seed_repr.vdf_solution; + } + -> Kind.vdf_revelation contents + (* Double_preattestation_evidence: Double-preattestation is a + kind of malicious attack where a byzantine attempts to fork + the chain by preattesting blocks with different + contents (at the same level and same round) + twice. This behavior may be reported and the byzantine will have + its security deposit forfeited. *) + | Double_preattestation_evidence : { + op1 : Kind.preattestation operation; + op2 : Kind.preattestation operation; + } + -> Kind.double_preattestation_evidence contents + (* Double_attestation_evidence: Similar to double-preattestation but + for attestations. *) + | Double_attestation_evidence : { + op1 : Kind.attestation operation; + op2 : Kind.attestation operation; + } + -> Kind.double_attestation_evidence contents + (* Double_baking_evidence: Similarly to double-attestation but the + byzantine attempts to fork by signing two different blocks at the + same level. *) + | Double_baking_evidence : { + bh1 : Block_header_repr.t; + bh2 : Block_header_repr.t; + } + -> Kind.double_baking_evidence contents + (* Activate_account: Account activation allows to register a public + key hash on the blockchain. *) + | Activate_account : { + id : Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + } + -> Kind.activate_account contents + (* Proposals: A candidate protocol can be proposed for voting. *) + | Proposals : { + source : Signature.Public_key_hash.t; + period : int32; + proposals : Protocol_hash.t list; + } + -> Kind.proposals contents + (* Ballot: The validators of the chain will then vote on proposals. *) + | Ballot : { + source : Signature.Public_key_hash.t; + period : int32; + proposal : Protocol_hash.t; + ballot : Vote_repr.ballot; + } + -> Kind.ballot contents + (* [Drain_delegate { consensus_key ; delegate ; destination }] + transfers the spendable balance of the [delegate] to [destination] + when [consensus_key] is the active consensus key of [delegate].. *) + | Drain_delegate : { + consensus_key : Signature.Public_key_hash.t; + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + -> Kind.drain_delegate contents + (* Failing_noop: An operation never considered by the state machine + and which will always fail at [apply]. This allows end-users to + sign arbitrary messages which have no computational semantics. *) + | Failing_noop : string -> Kind.failing_noop contents + (* Manager_operation: Operations, emitted and signed by + a (revealed) implicit account, that describe management and + interactions between contracts (whether implicit or + smart). *) + | Manager_operation : { + source : Signature.Public_key_hash.t; + fee : Tez_repr.t; + counter : Manager_counter_repr.t; + operation : 'kind manager_operation; + gas_limit : Gas_limit_repr.Arith.integral; + storage_limit : Z.t; + } + -> 'kind Kind.manager contents + +(** A [manager_operation] describes management and interactions + between contracts (whether implicit or smart). *) +and _ manager_operation = + (* [Reveal] for the revelation of a public key, a one-time + prerequisite to any signed operation, in order to be able to + check the sender’s signature. *) + | Reveal : Signature.Public_key.t -> Kind.reveal manager_operation + (* [Transaction] of some amount to some destination contract. It can + also be used to execute/call smart-contracts. *) + | Transaction : { + amount : Tez_repr.t; + parameters : Script_repr.lazy_expr; + entrypoint : Entrypoint_repr.t; + destination : Contract_repr.t; + } + -> Kind.transaction manager_operation + (* [Origination] of a contract using a smart-contract [script] and + initially credited with the amount [credit]. *) + | Origination : { + delegate : Signature.Public_key_hash.t option; + script : Script_repr.t; + credit : Tez_repr.t; + } + -> Kind.origination manager_operation + (* [Delegation] to some staking contract (designated by its public + key hash). When this value is None, delegation is reverted as it + is set to nobody. *) + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation manager_operation + (* [Register_global_constant] allows registration and substitution + of a global constant available from any contract and registered in + the context. *) + | Register_global_constant : { + value : Script_repr.lazy_expr; + } + -> Kind.register_global_constant manager_operation + (* [Set_deposits_limit] sets an optional limit for frozen deposits + of a contract at a lower value than the maximum limit. When None, + the limit in unset back to the default maximum limit. *) + | Set_deposits_limit : + Tez_repr.t option + -> Kind.set_deposits_limit manager_operation + (* [Increase_paid_storage] allows a sender to pay to increase the paid storage of + some contract by some amount. *) + | Increase_paid_storage : { + amount_in_bytes : Z.t; + destination : Contract_hash.t; + } + -> Kind.increase_paid_storage manager_operation + (* [Update_consensus_key pk] updates the consensus key of + the signing delegate to [pk]. *) + | Update_consensus_key : + Signature.Public_key.t + -> Kind.update_consensus_key manager_operation + (** [Transfer_ticket] allows an implicit account (the "claimer") to + receive [amount] tickets, pulled out of [tx_rollup], to the + [entrypoint] of the smart contract [destination]. + + The ticket must have been addressed to the + claimer, who must be the source of this operation. It must have been + pulled out at [level] and from the message at [message_index]. The ticket + is composed of [ticketer; ty; contents]. *) + | Transfer_ticket : { + contents : Script_repr.lazy_expr; (** Contents of the withdrawn ticket *) + ty : Script_repr.lazy_expr; + (** Type of the withdrawn ticket's contents *) + ticketer : Contract_repr.t; (** Ticketer of the withdrawn ticket *) + amount : Ticket_amount.t; + (** Quantity of the withdrawn ticket. Must match the + amount that was enabled. *) + destination : Contract_repr.t; + (** The smart contract address that should receive the tickets. *) + entrypoint : Entrypoint_repr.t; + (** The entrypoint of the smart contract address that should receive the tickets. *) + } + -> Kind.transfer_ticket manager_operation + | Dal_publish_commitment : + Dal_operations_repr.Publish_commitment.t + -> Kind.dal_publish_commitment manager_operation + (** [Sc_rollup_originate] allows an implicit account to originate a new + smart contract rollup (initialized with a given boot sector). + The [parameters_ty] field allows to provide the expected interface + of the rollup being originated (i.e. its entrypoints with their + associated signatures) as a Michelson type. + *) + | Sc_rollup_originate : { + kind : Sc_rollups.Kind.t; + boot_sector : string; + parameters_ty : Script_repr.lazy_expr; + whitelist : Sc_rollup_whitelist_repr.t option; + } + -> Kind.sc_rollup_originate manager_operation + (* [Sc_rollup_add_messages] adds messages to the smart rollups' inbox. *) + | Sc_rollup_add_messages : { + messages : string list; + } + -> Kind.sc_rollup_add_messages manager_operation + | Sc_rollup_cement : { + rollup : Sc_rollup_repr.t; + } + -> Kind.sc_rollup_cement manager_operation + | Sc_rollup_publish : { + rollup : Sc_rollup_repr.t; + commitment : Sc_rollup_commitment_repr.t; + } + -> Kind.sc_rollup_publish manager_operation + | Sc_rollup_refute : { + rollup : Sc_rollup_repr.t; + opponent : Sc_rollup_repr.Staker.t; + refutation : Sc_rollup_game_repr.refutation; + } + -> Kind.sc_rollup_refute manager_operation + (** [Sc_rollup_refute { rollup; opponent; refutation }] makes a move + in a refutation game between the source of the operation and the + [opponent] under the given [rollup]. Both players must be stakers + on commitments in conflict. When [refutation = None], the game is + initialized. Next, when [refutation = Some move], [move] is the + next play for the current player. See {!Sc_rollup_game_repr} for + details. **) + | Sc_rollup_timeout : { + rollup : Sc_rollup_repr.t; + stakers : Sc_rollup_game_repr.Index.t; + } + -> Kind.sc_rollup_timeout manager_operation + (* [Sc_rollup_execute_outbox_message] executes a message from the rollup's + outbox. Messages may involve transactions to smart contract accounts on + Layer 1. *) + | Sc_rollup_execute_outbox_message : { + rollup : Sc_rollup_repr.t; (** The smart-contract rollup. *) + cemented_commitment : Sc_rollup_commitment_repr.Hash.t; + (** The hash of the last cemented commitment that the proof refers to. *) + output_proof : string; + (** A message along with a proof that it is included in the outbox + at a given outbox level and message index.*) + } + -> Kind.sc_rollup_execute_outbox_message manager_operation + | Sc_rollup_recover_bond : { + sc_rollup : Sc_rollup_repr.t; + staker : Signature.Public_key_hash.t; + } + -> Kind.sc_rollup_recover_bond manager_operation + | Zk_rollup_origination : { + public_parameters : Plonk.public_parameters; + circuits_info : [`Public | `Private | `Fee] Zk_rollup_account_repr.SMap.t; + (** Circuit names, alongside a tag indicating its kind. *) + init_state : Zk_rollup_state_repr.t; + nb_ops : int; + } + -> Kind.zk_rollup_origination manager_operation + | Zk_rollup_publish : { + zk_rollup : Zk_rollup_repr.t; + ops : (Zk_rollup_operation_repr.t * Zk_rollup_ticket_repr.t option) list; + (* See {!Zk_rollup_apply} *) + } + -> Kind.zk_rollup_publish manager_operation + | Zk_rollup_update : { + zk_rollup : Zk_rollup_repr.t; + update : Zk_rollup_update_repr.t; + } + -> Kind.zk_rollup_update manager_operation + +type packed_manager_operation = + | Manager : 'kind manager_operation -> packed_manager_operation + +type packed_contents = Contents : 'kind contents -> packed_contents + +type packed_contents_list = + | Contents_list : 'kind contents_list -> packed_contents_list + +val of_list : packed_contents list -> packed_contents_list tzresult + +val to_list : packed_contents_list -> packed_contents list + +type packed_protocol_data = + | Operation_data : 'kind protocol_data -> packed_protocol_data + +type packed_operation = { + shell : Operation.shell_header; + protocol_data : packed_protocol_data; +} + +val pack : 'kind operation -> packed_operation + +val manager_kind : 'kind manager_operation -> 'kind Kind.manager + +val encoding : packed_operation Data_encoding.t + +(** Operation encoding that accepts legacy attestation name : `endorsement` + (and preendorsement, double__evidence) in JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements kinds + in JSON will not be accepted any more by the protocol. +*) +val encoding_with_legacy_attestation_name : packed_operation Data_encoding.t + +val contents_encoding : packed_contents Data_encoding.t + +val contents_encoding_with_legacy_attestation_name : + packed_contents Data_encoding.t + +val contents_list_encoding : packed_contents_list Data_encoding.t + +val contents_list_encoding_with_legacy_attestation_name : + packed_contents_list Data_encoding.t + +val protocol_data_encoding : packed_protocol_data Data_encoding.t + +val protocol_data_encoding_with_legacy_attestation_name : + packed_protocol_data Data_encoding.t + +val unsigned_operation_encoding : + (Operation.shell_header * packed_contents_list) Data_encoding.t + +val unsigned_operation_encoding_with_legacy_attestation_name : + (Operation.shell_header * packed_contents_list) Data_encoding.t + +val raw : _ operation -> raw + +val hash_raw : raw -> Operation_hash.t + +val hash : _ operation -> Operation_hash.t + +val hash_packed : packed_operation -> Operation_hash.t + +(** Each operation belongs to a validation pass that is an integer + abstracting its priority in a block. Except Failing_noop. *) + +(** The validation pass of consensus operations. *) +val consensus_pass : int + +(** The validation pass of voting operations. *) +val voting_pass : int + +(** The validation pass of anonymous operations. *) +val anonymous_pass : int + +(** The validation pass of anonymous operations. *) +val manager_pass : int + +(** [acceptable_pass op] returns either the validation_pass of [op] + when defines and None when [op] is [Failing_noop]. *) +val acceptable_pass : packed_operation -> int option + +(** [compare_by_passes] orders two operations in the reverse order of + their acceptable passes. *) +val compare_by_passes : packed_operation -> packed_operation -> int + +(** [compare (oph1,op1) (oph2,op2)] defines a total ordering relation + on operations. + + The following requirements must be satisfied: [oph1] is the + [Operation.hash op1], [oph2] is [Operation.hash op2], and that + [op1] and [op2] are valid in the same context. + + [compare (oph1,op1) (oph2,op2) = 0] happens only if + [Operation_hash.compare oph1 oph2 = 0], meaning when [op1] and + [op2] are structurally identical. + + Two valid operations of different [validation_pass] are compared + according to {!acceptable_passes}: the one with the smaller pass + being the greater. + + Two valid operations of the same [validation_pass] are compared + according to a [weight], computed thanks to their static + information. + + The global order is as follows: + + {!Attestation} and {!Preattestation} > + {!Proposals} > {!Ballot} > {!Double_preattestation_evidence} > + {!Double_attestation_evidence} > {!Double_baking_evidence} > + {!Vdf_revelation} > {!Seed_nonce_revelation} > {!Activate_account} + > {!Drain_delegate} > {!Manager_operation}. + + {!Attestation} and {!Preattestation} are compared by the pair of their + [level] and [round] such as the farther to the current state [level] and + [round] is greater; e.g. the greater pair in lexicographic order being the + better. When equal and both operations being of the same kind, we compare + their [slot], the smaller being the better (assuming that the more slots an + attester has, the smaller is its smallest [slot]), and then the number of the + DAL attested slots, the more the better. When the pair is equal and comparing + an {!Attestation} to a {!Preattestation}, the {!Attestation} is better. + + Two voting operations are compared in the lexicographic order of + the pair of their [period] and [source]. A {!Proposals} is better + than a {!Ballot}. + + Two denunciations of the same kind are compared such as the farther + to the current state the better. For {!Double_baking_evidence} + in the case of equality, they are compared by the hashes of their first + denounced block_header. + + Two {!Vdf_revelation} ops are compared by their [solution]. + + Two {!Seed_nonce_relevation} ops are compared by their [level]. + + Two {!Activate_account} ops are compared by their [id]. + + Two {!Drain_delegate} ops are compared by their [delegate]. + + Two {!Manager_operation}s are compared in the lexicographic order of + the pair of their [fee]/[gas_limit] ratios and [source]. *) +val compare : + Operation_hash.t * packed_operation -> + Operation_hash.t * packed_operation -> + int + +type error += Missing_signature (* `Permanent *) + +type error += Invalid_signature (* `Permanent *) + +(** Measuring the length of an operation, ignoring its signature. + This is useful to define a gas model for the check of the + signature. *) +val unsigned_operation_length : _ operation -> int + +(** Check the signature of an operation. This function serializes the + operation before calling the [Signature.check] function with the + appropriate watermark. *) +val check_signature : + Signature.Public_key.t -> Chain_id.t -> _ operation -> unit tzresult + +type ('a, 'b) eq = Eq : ('a, 'a) eq + +val equal : 'a operation -> 'b operation -> ('a, 'b) eq option + +module Encoding : sig + type 'b case = + | Case : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_contents -> 'b contents option; + proj : 'b contents -> 'a; + inj : 'a -> 'b contents; + } + -> 'b case + + val preendorsement_case : Kind.preattestation case + + val preattestation_case : Kind.preattestation case + + val endorsement_case : Kind.attestation case + + val attestation_case : Kind.attestation case + + val endorsement_with_dal_case : Kind.attestation case + + val attestation_with_dal_case : Kind.attestation case + + val seed_nonce_revelation_case : Kind.seed_nonce_revelation case + + val vdf_revelation_case : Kind.vdf_revelation case + + val double_preendorsement_evidence_case : + Kind.double_preattestation_evidence case + + val double_preattestation_evidence_case : + Kind.double_preattestation_evidence case + + val double_endorsement_evidence_case : Kind.double_attestation_evidence case + + val double_attestation_evidence_case : Kind.double_attestation_evidence case + + val double_baking_evidence_case : Kind.double_baking_evidence case + + val activate_account_case : Kind.activate_account case + + val proposals_case : Kind.proposals case + + val ballot_case : Kind.ballot case + + val drain_delegate_case : Kind.drain_delegate case + + val failing_noop_case : Kind.failing_noop case + + val reveal_case : Kind.reveal Kind.manager case + + val transaction_case : Kind.transaction Kind.manager case + + val origination_case : Kind.origination Kind.manager case + + val delegation_case : Kind.delegation Kind.manager case + + val update_consensus_key_case : Kind.update_consensus_key Kind.manager case + + val register_global_constant_case : + Kind.register_global_constant Kind.manager case + + val set_deposits_limit_case : Kind.set_deposits_limit Kind.manager case + + val increase_paid_storage_case : Kind.increase_paid_storage Kind.manager case + + val transfer_ticket_case : Kind.transfer_ticket Kind.manager case + + val dal_publish_commitment_case : + Kind.dal_publish_commitment Kind.manager case + + val sc_rollup_originate_case : Kind.sc_rollup_originate Kind.manager case + + val sc_rollup_add_messages_case : + Kind.sc_rollup_add_messages Kind.manager case + + val sc_rollup_cement_case : Kind.sc_rollup_cement Kind.manager case + + val sc_rollup_publish_case : Kind.sc_rollup_publish Kind.manager case + + val sc_rollup_refute_case : Kind.sc_rollup_refute Kind.manager case + + val sc_rollup_timeout_case : Kind.sc_rollup_timeout Kind.manager case + + val sc_rollup_execute_outbox_message_case : + Kind.sc_rollup_execute_outbox_message Kind.manager case + + val sc_rollup_recover_bond_case : + Kind.sc_rollup_recover_bond Kind.manager case + + val zk_rollup_origination_case : Kind.zk_rollup_origination Kind.manager case + + val zk_rollup_publish_case : Kind.zk_rollup_publish Kind.manager case + + val zk_rollup_update_case : Kind.zk_rollup_update Kind.manager case + + module Manager_operations : sig + type 'b case = + | MCase : { + tag : int; + name : string; + encoding : 'a Data_encoding.t; + select : packed_manager_operation -> 'kind manager_operation option; + proj : 'kind manager_operation -> 'a; + inj : 'a -> 'kind manager_operation; + } + -> 'kind case + + val reveal_case : Kind.reveal case + + val transaction_case : Kind.transaction case + + val origination_case : Kind.origination case + + val delegation_case : Kind.delegation case + + val update_consensus_key_tag : int + + val update_consensus_key_case : Kind.update_consensus_key case + + val register_global_constant_case : Kind.register_global_constant case + + val set_deposits_limit_case : Kind.set_deposits_limit case + + val increase_paid_storage_case : Kind.increase_paid_storage case + + val transfer_ticket_case : Kind.transfer_ticket case + + val dal_publish_commitment_case : Kind.dal_publish_commitment case + + val sc_rollup_originate_case : Kind.sc_rollup_originate case + + val sc_rollup_add_messages_case : Kind.sc_rollup_add_messages case + + val sc_rollup_cement_case : Kind.sc_rollup_cement case + + val sc_rollup_publish_case : Kind.sc_rollup_publish case + + val sc_rollup_refute_case : Kind.sc_rollup_refute case + + val sc_rollup_timeout_case : Kind.sc_rollup_timeout case + + val sc_rollup_execute_outbox_message_case : + Kind.sc_rollup_execute_outbox_message case + + val sc_rollup_recover_bond_case : Kind.sc_rollup_recover_bond case + + val zk_rollup_origination_case : Kind.zk_rollup_origination case + + val zk_rollup_publish_case : Kind.zk_rollup_publish case + + val zk_rollup_update_case : Kind.zk_rollup_update case + end +end + +module Internal_for_benchmarking : sig + (* Serialize an operation, ignoring its signature. *) + val serialize_unsigned_operation : _ operation -> bytes +end diff --git a/src/proto_020_PsParisC/lib_protocol/origination_nonce.ml b/src/proto_020_PsParisC/lib_protocol/origination_nonce.ml new file mode 100644 index 000000000000..32bb5be371e1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/origination_nonce.ml @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Marigold *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = {operation_hash : Operation_hash.t; origination_index : int32} + +let encoding = + let open Data_encoding in + conv + (fun {operation_hash; origination_index} -> + (operation_hash, origination_index)) + (fun (operation_hash, origination_index) -> + {operation_hash; origination_index}) + @@ obj2 (req "operation" Operation_hash.encoding) (dft "index" int32 0l) + +let initial operation_hash = {operation_hash; origination_index = 0l} + +let incr nonce = + let origination_index = Int32.succ nonce.origination_index in + {nonce with origination_index} diff --git a/src/proto_020_PsParisC/lib_protocol/origination_nonce.mli b/src/proto_020_PsParisC/lib_protocol/origination_nonce.mli new file mode 100644 index 000000000000..cd44e5be14ff --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/origination_nonce.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Marigold *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Originated contracts and tx rollups handles are crafted from the hash of the + operation that triggered their origination (and nothing else). As a single + operation can trigger several originations, the corresponding handles are + forged from a deterministic sequence of nonces, initialized with the hash of + the operation. *) +type t = {operation_hash : Operation_hash.t; origination_index : int32} + +val encoding : t Data_encoding.t + +val initial : Operation_hash.t -> t + +val incr : t -> t diff --git a/src/proto_020_PsParisC/lib_protocol/parameters_repr.ml b/src/proto_020_PsParisC/lib_protocol/parameters_repr.ml new file mode 100644 index 000000000000..e009ade7db62 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/parameters_repr.ml @@ -0,0 +1,285 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type bootstrap_account = { + public_key_hash : Signature.Public_key_hash.t; + public_key : Signature.Public_key.t option; + amount : Tez_repr.t; + delegate_to : Signature.Public_key_hash.t option; + consensus_key : Signature.Public_key.t option; +} + +type bootstrap_contract = { + delegate : Signature.Public_key_hash.t option; + amount : Tez_repr.t; + script : Script_repr.t; + hash : Contract_hash.t option; +} + +type bootstrap_smart_rollup = { + address : Sc_rollup_repr.Address.t; + pvm_kind : Sc_rollups.Kind.t; + boot_sector : string; + parameters_ty : Script_repr.lazy_expr; + whitelist : Sc_rollup_whitelist_repr.t option; +} + +type t = { + bootstrap_accounts : bootstrap_account list; + bootstrap_contracts : bootstrap_contract list; + bootstrap_smart_rollups : bootstrap_smart_rollup list; + commitments : Commitment_repr.t list; + constants : Constants_parametric_repr.t; + security_deposit_ramp_up_cycles : int option; + no_reward_cycles : int option; +} + +let bootstrap_account_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Public_key_known" + (tup2 Signature.Public_key.encoding Tez_repr.encoding) + (function + | { + public_key_hash; + public_key = Some public_key; + amount; + delegate_to = None; + consensus_key = None; + } -> + assert ( + Signature.Public_key_hash.equal + (Signature.Public_key.hash public_key) + public_key_hash) ; + Some (public_key, amount) + | {public_key = None; _} + | {delegate_to = Some _; _} + | {consensus_key = Some _; _} -> + None) + (fun (public_key, amount) -> + { + public_key = Some public_key; + public_key_hash = Signature.Public_key.hash public_key; + amount; + delegate_to = None; + consensus_key = None; + }); + case + (Tag 1) + ~title:"Public_key_unknown" + (tup2 Signature.Public_key_hash.encoding Tez_repr.encoding) + (function + | { + public_key_hash; + public_key = None; + amount; + delegate_to = None; + consensus_key = None; + } -> + Some (public_key_hash, amount) + | {public_key = Some _; _} + | {delegate_to = Some _; _} + | {consensus_key = Some _; _} -> + None) + (fun (public_key_hash, amount) -> + { + public_key = None; + public_key_hash; + amount; + delegate_to = None; + consensus_key = None; + }); + case + (Tag 2) + ~title:"Public_key_known_with_delegate" + (tup3 + Signature.Public_key.encoding + Tez_repr.encoding + Signature.Public_key_hash.encoding) + (function + | { + public_key_hash; + public_key = Some public_key; + amount; + delegate_to = Some delegate; + consensus_key = None; + } -> + assert ( + Signature.Public_key_hash.equal + (Signature.Public_key.hash public_key) + public_key_hash) ; + Some (public_key, amount, delegate) + | {public_key = None; _} + | {delegate_to = None; _} + | {consensus_key = Some _; _} -> + None) + (fun (public_key, amount, delegate) -> + { + public_key = Some public_key; + public_key_hash = Signature.Public_key.hash public_key; + amount; + delegate_to = Some delegate; + consensus_key = None; + }); + case + (Tag 3) + ~title:"Public_key_unknown_with_delegate" + (tup3 + Signature.Public_key_hash.encoding + Tez_repr.encoding + Signature.Public_key_hash.encoding) + (function + | { + public_key_hash; + public_key = None; + amount; + delegate_to = Some delegate; + consensus_key = None; + } -> + Some (public_key_hash, amount, delegate) + | {public_key = Some _; _} + | {delegate_to = None; _} + | {consensus_key = Some _; _} -> + None) + (fun (public_key_hash, amount, delegate) -> + { + public_key = None; + public_key_hash; + amount; + delegate_to = Some delegate; + consensus_key = None; + }); + case + (Tag 4) + ~title:"Public_key_known_with_consensus_key" + (tup3 + Signature.Public_key.encoding + Tez_repr.encoding + Signature.Public_key.encoding) + (function + | { + public_key_hash; + public_key = Some public_key; + amount; + delegate_to = None; + consensus_key = Some consensus_key; + } -> + assert ( + Signature.Public_key_hash.equal + (Signature.Public_key.hash public_key) + public_key_hash) ; + Some (public_key, amount, consensus_key) + | {public_key = None; _} + | {delegate_to = Some _; _} + | {consensus_key = None; _} -> + None) + (fun (public_key, amount, consensus_key) -> + { + public_key = Some public_key; + public_key_hash = Signature.Public_key.hash public_key; + amount; + delegate_to = None; + consensus_key = Some consensus_key; + }); + ] + +let bootstrap_contract_encoding = + let open Data_encoding in + conv + (fun {delegate; amount; script; hash} -> (delegate, amount, script, hash)) + (fun (delegate, amount, script, hash) -> {delegate; amount; script; hash}) + (obj4 + (opt "delegate" Signature.Public_key_hash.encoding) + (req "amount" Tez_repr.encoding) + (req "script" Script_repr.encoding) + (opt "hash" Contract_hash.encoding)) + +let bootstrap_smart_rollup_encoding = + let open Data_encoding in + conv + (fun {address; pvm_kind; boot_sector; parameters_ty; whitelist} -> + (address, pvm_kind, boot_sector, parameters_ty, whitelist)) + (fun (address, pvm_kind, boot_sector, parameters_ty, whitelist) -> + {address; pvm_kind; boot_sector; parameters_ty; whitelist}) + (obj5 + (req "address" Sc_rollup_repr.Address.encoding) + (req "pvm_kind" Sc_rollups.Kind.encoding) + (req "kernel" (string Hex)) + (req "parameters_ty" Script_repr.lazy_expr_encoding) + (opt "whitelist" Sc_rollup_whitelist_repr.encoding)) + +let encoding = + let open Data_encoding in + conv + (fun { + bootstrap_accounts; + bootstrap_contracts; + bootstrap_smart_rollups; + commitments; + constants; + security_deposit_ramp_up_cycles; + no_reward_cycles; + } -> + ( ( bootstrap_accounts, + bootstrap_contracts, + bootstrap_smart_rollups, + commitments, + security_deposit_ramp_up_cycles, + no_reward_cycles ), + constants )) + (fun ( ( bootstrap_accounts, + bootstrap_contracts, + bootstrap_smart_rollups, + commitments, + security_deposit_ramp_up_cycles, + no_reward_cycles ), + constants ) -> + { + bootstrap_accounts; + bootstrap_contracts; + bootstrap_smart_rollups; + commitments; + constants; + security_deposit_ramp_up_cycles; + no_reward_cycles; + }) + (merge_objs + (obj6 + (req "bootstrap_accounts" (list bootstrap_account_encoding)) + (dft "bootstrap_contracts" (list bootstrap_contract_encoding) []) + (dft + "bootstrap_smart_rollups" + (list bootstrap_smart_rollup_encoding) + []) + (dft "commitments" (list Commitment_repr.encoding) []) + (opt "security_deposit_ramp_up_cycles" int31) + (opt "no_reward_cycles" int31)) + Constants_parametric_repr.encoding) + +let check_params params = Constants_repr.check_constants params.constants diff --git a/src/proto_020_PsParisC/lib_protocol/parameters_repr.mli b/src/proto_020_PsParisC/lib_protocol/parameters_repr.mli new file mode 100644 index 000000000000..373d57bfd198 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/parameters_repr.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines protocol parameters, i.e. constants regulating the + behaviour of the blockchain under the protocol. *) + +(** An implict contract (account) initially existing on a chain since genesis. *) +type bootstrap_account = { + public_key_hash : Signature.Public_key_hash.t; + public_key : Signature.Public_key.t option; + amount : Tez_repr.t; + delegate_to : Signature.Public_key_hash.t option; + consensus_key : Signature.Public_key.t option; +} + +(** An originated contract initially existing on a chain since genesis. *) +type bootstrap_contract = { + delegate : Signature.Public_key_hash.t option; + amount : Tez_repr.t; + script : Script_repr.t; + hash : Contract_hash.t option; + (** If the contract hash is not provided, generate a fresh hash. *) +} + +(** An originated smart rollup initially existing on a chain since genesis. *) +type bootstrap_smart_rollup = { + address : Sc_rollup_repr.Address.t; + pvm_kind : Sc_rollups.Kind.t; + boot_sector : string; + parameters_ty : Script_repr.lazy_expr; + whitelist : Sc_rollup_whitelist_repr.t option; +} + +(** Protocol parameters define some constants regulating behaviour of the + chain. *) +type t = { + bootstrap_accounts : bootstrap_account list; + bootstrap_contracts : bootstrap_contract list; + bootstrap_smart_rollups : bootstrap_smart_rollup list; + commitments : Commitment_repr.t list; + constants : Constants_parametric_repr.t; + security_deposit_ramp_up_cycles : int option; + no_reward_cycles : int option; +} + +val bootstrap_account_encoding : bootstrap_account Data_encoding.t + +val encoding : t Data_encoding.t + +val check_params : t -> unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/path_encoding.ml b/src/proto_020_PsParisC/lib_protocol/path_encoding.ml new file mode 100644 index 000000000000..935986395bfd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/path_encoding.ml @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type S = sig + type t + + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + val path_length : int +end + +module type ENCODING = sig + type t + + val to_bytes : t -> bytes + + val of_bytes_opt : bytes -> t option +end + +module Make_hex (H : ENCODING) = struct + let path_length = 1 + + let to_path t l = + let (`Hex key) = Hex.of_bytes (H.to_bytes t) in + key :: l + + let of_path = function + | [path] -> Option.bind (Hex.to_bytes (`Hex path)) H.of_bytes_opt + | _ -> None +end diff --git a/src/proto_020_PsParisC/lib_protocol/path_encoding.mli b/src/proto_020_PsParisC/lib_protocol/path_encoding.mli new file mode 100644 index 000000000000..e44d1db35038 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/path_encoding.mli @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type S = sig + type t + + (** [to_path t postfix] returns the context path name for [t] + postfixed with [postfix] *) + val to_path : t -> string list -> string list + + (** [of_path path] parses [path] as a context path name for [t] *) + val of_path : string list -> t option + + (** Directory levels of the path encoding of [t] *) + val path_length : int +end + +module type ENCODING = sig + type t + + val to_bytes : t -> bytes + + val of_bytes_opt : bytes -> t option +end + +(** Path encoding in hex: [/[0-9a-f]{2}+/] *) +module Make_hex (H : ENCODING) : S with type t := H.t diff --git a/src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.ml b/src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.ml new file mode 100644 index 000000000000..60bd70d862d9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.ml @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs. *) +(* *) +(*****************************************************************************) + +let find ctxt delegate = + let open Lwt_result_syntax in + let* denunciations_opt = Storage.Pending_denunciations.find ctxt delegate in + return @@ Option.value denunciations_opt ~default:[] + +let add_denunciation ctxt ~misbehaving_delegate operation_hash + ~rewarded_delegate misbehaviour = + let open Lwt_result_syntax in + let* denunciations = find ctxt misbehaving_delegate in + let denunciations = + Denunciations_repr.add + operation_hash + rewarded_delegate + misbehaviour + denunciations + in + let*! ctxt = + Storage.Pending_denunciations.add ctxt misbehaving_delegate denunciations + in + return ctxt + +let set_denunciations ctxt delegate denunciations = + match denunciations with + | [] -> Storage.Pending_denunciations.remove ctxt delegate + | _ -> Storage.Pending_denunciations.add ctxt delegate denunciations + +let has_pending_denunciations ctxt delegate = + (* we rely here on the fact that we never insert an empty list in the table *) + Storage.Pending_denunciations.mem ctxt delegate + +let fold = Storage.Pending_denunciations.fold + +let clear ctxt = Storage.Pending_denunciations.clear ctxt + +module For_RPC = struct + let pending_denunciations_list ctxt = + let open Lwt_syntax in + let+ r = Storage.Pending_denunciations.bindings ctxt in + List.map (fun (x, l) -> List.map (fun y -> (x, y)) l) r |> List.flatten +end diff --git a/src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.mli b/src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.mli new file mode 100644 index 000000000000..ffb5d4e16306 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/pending_denunciations_storage.mli @@ -0,0 +1,67 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs. *) +(* *) +(*****************************************************************************) +(** This module deals with pending denunciations before they are used to slash + delegates. + + This module is responsible for maintaining the table + {!Storage.Pending_denunciations} + + In particular, it maintains the invariant that no key is pointing to an + empty denunciation list. +*) + +(** Returns the pending denunciations list of the given delegate. + It returns an empty list if none are registered. + *) +val find : + Raw_context.t -> + Signature.public_key_hash -> + Denunciations_repr.item list tzresult Lwt.t + +(** Add a denunciation in the list of the given delegate *) +val add_denunciation : + Raw_context.t -> + misbehaving_delegate:Signature.public_key_hash -> + Operation_hash.t -> + rewarded_delegate:Signature.public_key_hash -> + Misbehaviour_repr.t -> + Raw_context.t tzresult Lwt.t + +(** Set the denunciation list of the given delegate. + Previously set denunciations would be erased. +*) +val set_denunciations : + Raw_context.t -> + Signature.public_key_hash -> + Denunciations_repr.t -> + Raw_context.t Lwt.t + +(** Tells if the given delegate has some pending denunciations *) +val has_pending_denunciations : + Raw_context.t -> Signature.public_key_hash -> bool Lwt.t + +(** See {!Storage.Pending_denunciations.fold} *) +val fold : + Raw_context.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f: + (Signature.public_key_hash -> + Denunciations_repr.item list -> + 'a -> + 'a Lwt.t) -> + 'a Lwt.t + +(** See {!Storage.Pending_denunciations.clear} *) +val clear : Raw_context.t -> Raw_context.t Lwt.t + +module For_RPC : sig + (** Returns a list of all denunciations paired with the offending delegate pkh. *) + val pending_denunciations_list : + Raw_context.t -> + (Signature.public_key_hash * Denunciations_repr.item) list Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.ml b/src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.ml new file mode 100644 index 000000000000..f61b6e633a70 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.ml @@ -0,0 +1,133 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* Copyright (c) 2022-2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Options available for per-block votes *) + +type per_block_vote = + | Per_block_vote_on + | Per_block_vote_off + | Per_block_vote_pass + +type per_block_votes = { + liquidity_baking_vote : per_block_vote; + adaptive_issuance_vote : per_block_vote; +} + +let ema_max = 2_000_000_000l + +let per_block_vote_compact_encoding = + let open Data_encoding in + let open Compact in + union + ~union_tag_bits:2 + ~cases_tag_bits:0 + [ + case + ~title:"per_block_vote_on" + (payload (constant "on")) + (function Per_block_vote_on -> Some () | _ -> None) + (fun () -> Per_block_vote_on); + case + ~title:"per_block_vote_off" + (payload (constant "off")) + (function Per_block_vote_off -> Some () | _ -> None) + (fun () -> Per_block_vote_off); + case + ~title:"per_block_vote_pass" + (payload (constant "pass")) + (function Per_block_vote_pass -> Some () | _ -> None) + (fun () -> Per_block_vote_pass); + ] + +let liquidity_baking_vote_encoding = + let open Data_encoding in + def + "liquidity_baking_vote" + (Compact.make ~tag_size:`Uint8 per_block_vote_compact_encoding) + +let adaptive_issuance_vote_encoding = + let open Data_encoding in + def + "adaptive_issuance_vote" + (Compact.make ~tag_size:`Uint8 per_block_vote_compact_encoding) + +let per_block_votes_compact_encoding = + let open Data_encoding in + let open Compact in + conv + (fun {liquidity_baking_vote; adaptive_issuance_vote} -> + (liquidity_baking_vote, adaptive_issuance_vote)) + (fun (liquidity_baking_vote, adaptive_issuance_vote) -> + {liquidity_baking_vote; adaptive_issuance_vote}) + (obj2 + (req "liquidity_baking_vote" per_block_vote_compact_encoding) + (req "adaptive_issuance_vote" per_block_vote_compact_encoding)) + +let per_block_votes_encoding = + let open Data_encoding in + def + "per_block_votes" + (Compact.make ~tag_size:`Uint8 per_block_votes_compact_encoding) + +module Liquidity_baking_toggle_EMA = Votes_EMA_repr.Make (struct + let baker_contribution = Z.of_int 500_000 + + let ema_max = ema_max +end) + +module Adaptive_issuance_launch_EMA = Votes_EMA_repr.Make (struct + (* The baker_contribution parameter of the adaptive issuance + activation vote was chosen so that 2 weeks are needed to move + the EMA from 0% to 50% when all bakers vote On. + + This was computed using the following formula: + + baker_contrib = (1/2) * ema_max * (1 - 2^(-1/k)) + + where k is the number of blocks in 2 weeks (which is 120960). + + Because of a small accumulation of rounding errors, two more + blocks are actually needed. *) + let baker_contribution = Z.of_int 5730 + + let ema_max = ema_max +end) + +let compute_new_liquidity_baking_ema ~per_block_vote ema = + match per_block_vote with + | Per_block_vote_pass -> ema + | Per_block_vote_off -> Liquidity_baking_toggle_EMA.update_ema_up ema + | Per_block_vote_on -> Liquidity_baking_toggle_EMA.update_ema_down ema + +let compute_new_adaptive_issuance_ema ~per_block_vote ema = + match per_block_vote with + | Per_block_vote_pass -> ema + | Per_block_vote_off -> Adaptive_issuance_launch_EMA.update_ema_down ema + | Per_block_vote_on -> Adaptive_issuance_launch_EMA.update_ema_up ema + +module Internal_for_tests = struct + let ema_max = ema_max +end diff --git a/src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.mli b/src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.mli new file mode 100644 index 000000000000..abaa67352d9b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/per_block_votes_repr.mli @@ -0,0 +1,88 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* Copyright (c) 2022-2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Options available for per-block votes *) + +type per_block_vote = + | Per_block_vote_on + | Per_block_vote_off + | Per_block_vote_pass + +type per_block_votes = { + liquidity_baking_vote : per_block_vote; + adaptive_issuance_vote : per_block_vote; +} + +val liquidity_baking_vote_encoding : per_block_vote Data_encoding.encoding + +val adaptive_issuance_vote_encoding : per_block_vote Data_encoding.encoding + +val per_block_votes_encoding : per_block_votes Data_encoding.encoding + +module Liquidity_baking_toggle_EMA : Votes_EMA_repr.T + +module Adaptive_issuance_launch_EMA : Votes_EMA_repr.T + +(** [compute_new_liquidity_baking_ema ~per_block_vote old_ema] returns the value + [new_ema] of the exponential moving average [old_ema] updated by the vote + [per_block_vote] interpreted as a vote to deactivate the liquidity baking + feature (Off increases the EMA). + + The EMA is updated as follows: + - if [per_block_vote] is [Per_block_vote_pass] then [new_ema] = [old_ema], + - if [per_block_vote] is [Per_block_vote_off], then [new_ema] = (1999 * ema[n] // 2000) + 1,000,000, + - if [per_block_vote] is [Per_block_vote_on], then [new_ema] = (1999 * ema[n] // 2000). + + The multiplication is performed in [Z.t] to avoid overflows, division is + rounded toward 1,000,000,000 (the middle of the interval). + *) +val compute_new_liquidity_baking_ema : + per_block_vote:per_block_vote -> + Liquidity_baking_toggle_EMA.t -> + Liquidity_baking_toggle_EMA.t + +(** [compute_new_adaptive_issuance_ema ~per_block_vote old_ema] returns the value + [new_ema] of the exponential moving average [old_ema] updated by the vote + [per_block_vote] interpreted as a vote to activate the adaptive issuance + feature (Off decreases the EMA). + + The EMA is updated as follows: + - if [per_block_vote] is [Per_block_vote_pass] then [new_ema] = [old_ema], + - if [per_block_vote] is [Per_block_vote_off], then [new_ema] = (1999 * ema[n] // 2000), + - if [per_block_vote] is [Per_block_vote_on], then [new_ema] = (1999 * ema[n] // 2000) + 1,000,000. + + The multiplication is performed in [Z.t] to avoid overflows, division is + rounded toward 1,000,000,000 (the middle of the interval). + *) +val compute_new_adaptive_issuance_ema : + per_block_vote:per_block_vote -> + Adaptive_issuance_launch_EMA.t -> + Adaptive_issuance_launch_EMA.t + +module Internal_for_tests : sig + (* Maximum value for EMA representation (both LB and AI) *) + val ema_max : Int32.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/percentage.ml b/src/proto_020_PsParisC/lib_protocol/percentage.ml new file mode 100644 index 000000000000..7696be983d96 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/percentage.ml @@ -0,0 +1,75 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type t = int + +(* The factor by which to multiply the smallest non-zero representation in + order to obtain 1%. A factor of 100 means that the precision is 0.01%. *) +let precision_factor = 100 + +let one_hundred_percent = 100 * precision_factor + +(* TODO #6918: Remove after P *) +let convert_from_o_to_p x = x * precision_factor + +(* TODO #6918: Remove after P *) +let of_int_guarded_legacy_in_o i = + if Compare.Int.(i >= 0 && i <= 100) then Ok i + else Error "Value must be between 0 and 100" + +let of_int_guarded i = + if Compare.Int.(i >= 0 && i <= one_hundred_percent) then Ok i + else + Error (Format.asprintf "Value must be between 0 and %d" one_hundred_percent) + +let of_int_bounded i = Compare.Int.(max 0 (min one_hundred_percent i)) + +(* TODO #6918: Remove after P *) +let encoding_legacy_in_o = + let open Data_encoding in + conv_with_guard (fun i -> i) of_int_guarded_legacy_in_o uint8 + +let encoding = + let open Data_encoding in + conv_with_guard (fun i -> i) of_int_guarded uint16 + +let of_ratio_bounded Ratio_repr.{numerator; denominator} = + of_int_bounded (one_hundred_percent * numerator / denominator) + +let of_q_bounded ~round (Q.{num; den} as q) = + if Compare.Q.(q >= Q.one) then one_hundred_percent + else + (* Ensures that [to_int] doesn't overflow *) + let div = match round with `Down -> Z.div | `Up -> Z.cdiv in + of_int_bounded + (Z.to_int (div (Z.mul (Z.of_int one_hundred_percent) num) den)) + +let to_q x = Q.of_ints x one_hundred_percent + +let neg p = one_hundred_percent - p + +let add_bounded p1 p2 = Compare.Int.min one_hundred_percent (p1 + p2) + +let sub_bounded p1 p2 = Compare.Int.max 0 (p1 - p2) + +let mul ~round a b = Q.mul (to_q a) (to_q b) |> of_q_bounded ~round + +let mul_q_bounded ~round a q = Q.mul (to_q a) q |> of_q_bounded ~round + +let p0 = 0 + +let p5 = 5 * precision_factor + +let p50 = 50 * precision_factor + +let p51 = 51 * precision_factor + +let p100 = one_hundred_percent + +module Compare = struct + include Compare.Int +end diff --git a/src/proto_020_PsParisC/lib_protocol/percentage.mli b/src/proto_020_PsParisC/lib_protocol/percentage.mli new file mode 100644 index 000000000000..c86d4cb14899 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/percentage.mli @@ -0,0 +1,56 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** A value representing percentages, between 0% and 100%, inclusive. + Precision of the representation is 0.01% *) +type t + +(* TODO #6918: Remove after P *) +val encoding_legacy_in_o : t Data_encoding.t + +val encoding : t Data_encoding.t + +(** Rounds down to the nearest 0.01% *) +val of_ratio_bounded : Ratio_repr.t -> t + +val of_q_bounded : round:[`Down | `Up] -> Q.t -> t + +val to_q : t -> Q.t + +(** [neg p] is [100% - p]. *) +val neg : t -> t + +val add_bounded : t -> t -> t + +val sub_bounded : t -> t -> t + +val mul : round:[`Down | `Up] -> t -> t -> t + +val mul_q_bounded : round:[`Down | `Up] -> t -> Q.t -> t + +(** Constants *) + +(** 0% *) +val p0 : t + +(** 5% *) +val p5 : t + +(** 50% *) +val p50 : t + +(** 51% *) +val p51 : t + +(** 100% *) +val p100 : t + +module Compare : sig + val ( >= ) : t -> t -> bool +end + +val convert_from_o_to_p : t -> t diff --git a/src/proto_020_PsParisC/lib_protocol/period_repr.ml b/src/proto_020_PsParisC/lib_protocol/period_repr.ml new file mode 100644 index 000000000000..d777907559ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/period_repr.ml @@ -0,0 +1,167 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* `Permanent *) +type error += Malformed_period of int64 | Invalid_arg | Period_overflow + +let () = + let open Data_encoding in + (* Malformed period *) + register_error_kind + `Permanent + ~id:"malformed_period" + ~title:"Malformed period" + ~description:"Period is negative." + ~pp:(fun ppf period -> + Format.fprintf ppf "The given period '%Ld' is negative " period) + (obj1 (req "malformed_period" int64)) + (function Malformed_period n -> Some n | _ -> None) + (fun n -> Malformed_period n) ; + (* Invalid arg *) + register_error_kind + `Permanent + ~id:"invalid_arg" + ~title:"Invalid arg" + ~description:"Negative multiple of periods are not allowed." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid arg") + empty + (function Invalid_arg -> Some () | _ -> None) + (fun () -> Invalid_arg) ; + let title = "Period overflow" in + register_error_kind + `Permanent + ~id:"period_overflow" + ~title + ~description:"Last operation generated an integer overflow." + ~pp:(fun ppf () -> Format.fprintf ppf "%s" title) + empty + (function Period_overflow -> Some () | _ -> None) + (fun () -> Period_overflow) + +module type INTERNAL = sig + type t = private int64 + + val create : int64 -> t option + + val zero : t + + val one : t + + val mult_ : t -> t -> t option + + val add_ : t -> t -> t option + + val encoding : t Data_encoding.t + + val rpc_arg : t RPC_arg.arg + + val pp : Format.formatter -> t -> unit + + include Compare.S with type t := t +end + +(* Internal module implementing natural numbers using int64. These are different + from usual (wrapping up) unsigned integers in that if one overflows the + representation bounds for int64 through [add] or [mul], a [None] value is + returned *) +module Internal : INTERNAL = struct + type t = Int64.t + + let encoding = + Data_encoding.( + with_decoding_guard + (fun t -> + if Compare.Int64.(t >= 0L) then Result_syntax.return_unit + else Error "Positive int64 required") + int64) + + let rpc_arg = RPC_arg.uint63 + + let pp ppf v = Format.fprintf ppf "%Ld" v + + include (Compare.Int64 : Compare.S with type t := t) + + let zero = 0L + + let one = 1L + + let create t = if t >= zero then Some t else None + + (* The create function is not used in the [mul_] and [add_] below to not add + extra Some | None pattern matching to handle since the overflow checks are + generic and apply as well to negative as positive integers . + + To handle overflows, both [add_] and [mult_] return option types. [None] is + returned on detected overflow, [Some value] when everything went well. *) + let mult_ a b = + if a <> zero then + let res = Int64.mul a b in + if Int64.div res a <> b then None else Some res + else Some zero + + let add_ a b = + let res = Int64.add a b in + if res < a || res < b then None else Some res +end + +include Internal + +type period = Internal.t + +let to_seconds (t : Internal.t) = (t :> int64) + +let of_seconds secs = + let open Result_syntax in + match Internal.create secs with + | Some v -> return v + | None -> tzfail (Malformed_period secs) + +let of_seconds_exn t = + match Internal.create t with + | Some t -> t + | None -> invalid_arg "Period.of_seconds_exn" + +let mult i p = + let open Result_syntax in + match Internal.create (Int64.of_int32 i) with + | None -> tzfail Invalid_arg + | Some iper -> ( + match Internal.mult_ iper p with + | None -> tzfail Period_overflow + | Some res -> return res) + +let add p1 p2 = + let open Result_syntax in + match Internal.add_ p1 p2 with + | None -> tzfail Period_overflow + | Some res -> return res + +let ( +? ) = add + +let one_second = Internal.one + +let one_minute = of_seconds_exn 60L + +let one_hour = of_seconds_exn 3600L diff --git a/src/proto_020_PsParisC/lib_protocol/period_repr.mli b/src/proto_020_PsParisC/lib_protocol/period_repr.mli new file mode 100644 index 000000000000..92f60493a57d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/period_repr.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t + +(** Represents a period of time as a non-negative integer. *) +type period = t + +include Compare.S with type t := t + +val encoding : period Data_encoding.t + +val rpc_arg : period RPC_arg.t + +val pp : Format.formatter -> period -> unit + +(** Returns the number of seconds contained in the period. *) +val to_seconds : period -> int64 + +(** Converts a number of seconds to a [period]. + + [of_second s] fails if [s] is not positive. *) +val of_seconds : int64 -> period tzresult + +(** Converts a number of seconds to [period]. + + [of_second s] fails if [s] is not positive. + It should only be used at toplevel for constants. *) +val of_seconds_exn : int64 -> period + +(** Safe addition of periods, guarded against overflow. *) +val add : period -> period -> period tzresult + +(** Alias for [add]. *) +val ( +? ) : period -> period -> period tzresult + +(** Safe multiplication by a positive integer. Guarded against overflow. *) +val mult : int32 -> period -> period tzresult + +val zero : period + +val one_second : period + +val one_minute : period + +val one_hour : period + +(** [compare x y] returns [0] if [x] is equal to [y], a negative + integer if [x] is shorter than [y], and a positive integer if [x] + is longer than [y]. *) +val compare : period -> period -> int diff --git a/src/proto_020_PsParisC/lib_protocol/ratio_repr.ml b/src/proto_020_PsParisC/lib_protocol/ratio_repr.ml new file mode 100644 index 000000000000..cabd42bacbde --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ratio_repr.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = {numerator : int; denominator : int} + +let encoding = + let open Data_encoding in + conv_with_guard + (fun r -> (r.numerator, r.denominator)) + (fun (numerator, denominator) -> + if Compare.Int.(denominator > 0) then Ok {numerator; denominator} + else Error "The denominator must be greater than 0.") + (obj2 (req "numerator" uint16) (req "denominator" uint16)) + +let pp fmt {numerator; denominator} = + Format.fprintf fmt "%d/%d" numerator denominator diff --git a/src/proto_020_PsParisC/lib_protocol/ratio_repr.mli b/src/proto_020_PsParisC/lib_protocol/ratio_repr.mli new file mode 100644 index 000000000000..237f04972695 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ratio_repr.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = {numerator : int; denominator : int} + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/raw_context.ml b/src/proto_020_PsParisC/lib_protocol/raw_context.ml new file mode 100644 index 000000000000..80b457124f2f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/raw_context.ml @@ -0,0 +1,2009 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Int_set = Set.Make (Compare.Int) + +(* + + Gas levels maintenance + ======================= + + The context maintains two levels of gas, one corresponds to the gas + available for the current operation while the other is the gas + available for the current block. Both levels are maintained + independently: [consume_gas] only decreases the operation level, + and block level should be updated with [consume_gas_limit_in_block]. + + A layered context + ================= + + Updating the context [remaining_operation_gas] is a critical routine + called very frequently by the operations performed by the protocol. + On the contrary, other fields are less frequently updated. + + In a previous version of the context datatype definition, all + the fields were represented at the toplevel. To update the remaining + gas, we had to copy ~25 fields (that is 200 bytes). + + With the following layered representation, we only have to + copy 2 fields (16 bytes) during [remaining_operation_gas] update. + This has a significant impact on the Michelson runtime efficiency. + + Here are the fields on the [back] of the context: + + *) + +type consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +let consensus_pk_encoding = + let open Data_encoding in + conv + (fun {delegate; consensus_pk; consensus_pkh} -> + if Signature.Public_key_hash.equal consensus_pkh delegate then + (consensus_pk, None) + else (consensus_pk, Some delegate)) + (fun (consensus_pk, delegate) -> + let consensus_pkh = Signature.Public_key.hash consensus_pk in + let delegate = + match delegate with None -> consensus_pkh | Some del -> del + in + {delegate; consensus_pk; consensus_pkh}) + (obj2 + (req "consensus_pk" Signature.Public_key.encoding) + (opt "delegate" Signature.Public_key_hash.encoding)) + +module Raw_consensus = struct + (** Consensus operations are indexed by their [initial slots]. Given + a delegate, the [initial slot] is the lowest slot assigned to + this delegate. *) + + type t = { + current_attestation_power : int; + (** Number of attestation slots recorded for the current block. *) + allowed_attestations : (consensus_pk * int * int) Slot_repr.Map.t option; + (** Attestations rights for the current block. Only an attestation for + the lowest slot in the block can be recorded. The map associates to + each initial slot the [pkh] associated to this slot with its + consensus attestation power and DAL attestation power. This is + [None] only in mempool mode. *) + allowed_preattestations : (consensus_pk * int * int) Slot_repr.Map.t option; + (** Preattestations rights for the current block. Only a preattestation + for the lowest slot in the block can be recorded. The map associates + to each initial slot the [pkh] associated to this slot with its + consensus attestation power and DAL attestation power. This is + [None] only in mempool mode, or in application mode when there is no + locked round (so the block cannot contain any preattestations). *) + forbidden_delegates : Signature.Public_key_hash.Set.t; + (** Delegates that are not allowed to bake or attest blocks; i.e., + delegates which have zero frozen deposit due to a previous + slashing. *) + attestations_seen : Slot_repr.Set.t; + (** Record the attestations already seen. Only initial slots are indexed. *) + preattestations_seen : Slot_repr.Set.t; + (** Record the preattestations already seen. Only initial slots + are indexed. *) + locked_round_evidence : (Round_repr.t * int) option; + (** Record the preattestation power for a locked round. *) + preattestations_quorum_round : Round_repr.t option; + (** in block construction mode, record the round of preattestations + included in a block. *) + attestation_branch : (Block_hash.t * Block_payload_hash.t) option; + } + + (** Invariant: + + - [slot \in attestations_seen => Int_map.mem slot allowed_attestations] + + - [slot \in preattestations_seen => Int_map.mem slot allowed_preattestations] + + - [ |attestations_seen| > 0 => |included attestations| > 0] + + *) + + let empty : t = + { + current_attestation_power = 0; + allowed_attestations = Some Slot_repr.Map.empty; + allowed_preattestations = Some Slot_repr.Map.empty; + forbidden_delegates = Signature.Public_key_hash.Set.empty; + attestations_seen = Slot_repr.Set.empty; + preattestations_seen = Slot_repr.Set.empty; + locked_round_evidence = None; + preattestations_quorum_round = None; + attestation_branch = None; + } + + type error += Double_inclusion_of_consensus_operation + + let () = + register_error_kind + `Branch + ~id:"operation.double_inclusion_of_consensus_operation" + ~title:"Double inclusion of consensus operation" + ~description:"double inclusion of consensus operation" + ~pp:(fun ppf () -> + Format.fprintf ppf "Double inclusion of consensus operation") + Data_encoding.empty + (function + | Double_inclusion_of_consensus_operation -> Some () | _ -> None) + (fun () -> Double_inclusion_of_consensus_operation) + + let record_attestation t ~initial_slot ~power = + let open Result_syntax in + let+ () = + error_when + (Slot_repr.Set.mem initial_slot t.attestations_seen) + Double_inclusion_of_consensus_operation + in + { + t with + current_attestation_power = t.current_attestation_power + power; + attestations_seen = Slot_repr.Set.add initial_slot t.attestations_seen; + } + + let record_preattestation ~initial_slot ~power round t = + let open Result_syntax in + let+ () = + error_when + (Slot_repr.Set.mem initial_slot t.preattestations_seen) + Double_inclusion_of_consensus_operation + in + let locked_round_evidence = + match t.locked_round_evidence with + | None -> Some (round, power) + | Some (_stored_round, evidences) -> + (* In mempool mode, round and stored_round can be different. + It doesn't matter in that case since quorum certificates + are not used in mempool. + For other cases [Apply.check_round] verifies it. *) + Some (round, evidences + power) + in + { + t with + locked_round_evidence; + preattestations_seen = + Slot_repr.Set.add initial_slot t.preattestations_seen; + } + + let set_forbidden_delegates delegates t = + {t with forbidden_delegates = delegates} + + let forbid_delegate delegate t = + { + t with + forbidden_delegates = + Signature.Public_key_hash.Set.add delegate t.forbidden_delegates; + } + + let set_preattestations_quorum_round round t = + match t.preattestations_quorum_round with + | Some round' -> + (* If the rounds are different, an error should have already + been raised. *) + assert (Round_repr.equal round round') ; + t + | None -> {t with preattestations_quorum_round = Some round} + + let initialize_with_attestations_and_preattestations ~allowed_attestations + ~allowed_preattestations t = + {t with allowed_attestations; allowed_preattestations} + + let locked_round_evidence t = t.locked_round_evidence + + let attestation_branch t = t.attestation_branch + + let set_attestation_branch t attestation_branch = + {t with attestation_branch = Some attestation_branch} +end + +type back = { + context : Context.t; + constants : Constants_parametric_repr.t; + round_durations : Round_repr.Durations.t; + cycle_eras : Level_repr.cycle_eras; + level : Level_repr.t; + predecessor_timestamp : Time.t; + timestamp : Time.t; + fees : Tez_repr.t; + origination_nonce : Origination_nonce.t option; + temporary_lazy_storage_ids : Lazy_storage_kind.Temp_ids.t; + internal_nonce : int; + internal_nonces_used : Int_set.t; + remaining_block_gas : Gas_limit_repr.Arith.fp; + unlimited_operation_gas : bool; + consensus : Raw_consensus.t; + non_consensus_operations_rev : Operation_hash.t list; + dictator_proposal_seen : bool; + sampler_state : (Seed_repr.seed * consensus_pk Sampler.t) Cycle_repr.Map.t; + stake_distribution_for_current_cycle : + Stake_repr.t Signature.Public_key_hash.Map.t option; + reward_coeff_for_current_cycle : Q.t; + sc_rollup_current_messages : Sc_rollup_inbox_merkelized_payload_hashes_repr.t; + dal_slot_fee_market : Dal_slot_repr.Slot_market.t; + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3105 + + We associate to a slot header some fees. This enable the use + of a fee market for slot publication. However, this is not + resilient from the game theory point of view. Probably we can find + better incentives here. In any case, because we want the following + invariant: + + - For each level and for each slot there is at most one slot + header. + + - We need to provide an incentive to avoid byzantines to post + dummy slot headers. *) + dal_attestation_slot_accountability : Dal_attestation_repr.Accountability.t; + dal_cryptobox : Dal.t option; + adaptive_issuance_enable : bool; +} + +(* + + The context is simply a record with two fields which + limits the cost of updating the [remaining_operation_gas]. + +*) +type t = {remaining_operation_gas : Gas_limit_repr.Arith.fp; back : back} + +type root = t + +(* + + Context fields accessors + ======================== + + To have the context related code more robust to evolutions, + we introduce accessors to get and to update the context + components. + +*) +let[@inline] context ctxt = ctxt.back.context + +let[@inline] current_level ctxt = ctxt.back.level + +let[@inline] predecessor_timestamp ctxt = ctxt.back.predecessor_timestamp + +let[@inline] current_timestamp ctxt = ctxt.back.timestamp + +let[@inline] round_durations ctxt = ctxt.back.round_durations + +let[@inline] cycle_eras ctxt = ctxt.back.cycle_eras + +let[@inline] constants ctxt = ctxt.back.constants + +let[@inline] sc_rollup ctxt = ctxt.back.constants.sc_rollup + +let[@inline] zk_rollup ctxt = ctxt.back.constants.zk_rollup + +let[@inline] recover ctxt = ctxt.back.context + +let[@inline] fees ctxt = ctxt.back.fees + +let[@inline] origination_nonce ctxt = ctxt.back.origination_nonce + +let[@inline] internal_nonce ctxt = ctxt.back.internal_nonce + +let[@inline] internal_nonces_used ctxt = ctxt.back.internal_nonces_used + +let[@inline] remaining_block_gas ctxt = ctxt.back.remaining_block_gas + +let[@inline] unlimited_operation_gas ctxt = ctxt.back.unlimited_operation_gas + +let[@inline] temporary_lazy_storage_ids ctxt = + ctxt.back.temporary_lazy_storage_ids + +let[@inline] remaining_operation_gas ctxt = ctxt.remaining_operation_gas + +let[@inline] non_consensus_operations_rev ctxt = + ctxt.back.non_consensus_operations_rev + +let[@inline] dictator_proposal_seen ctxt = ctxt.back.dictator_proposal_seen + +let[@inline] sampler_state ctxt = ctxt.back.sampler_state + +let[@inline] reward_coeff_for_current_cycle ctxt = + ctxt.back.reward_coeff_for_current_cycle + +let[@inline] adaptive_issuance_enable ctxt = ctxt.back.adaptive_issuance_enable + +let[@inline] update_back ctxt back = {ctxt with back} + +let[@inline] update_remaining_block_gas ctxt remaining_block_gas = + update_back ctxt {ctxt.back with remaining_block_gas} + +let[@inline] update_remaining_operation_gas ctxt remaining_operation_gas = + {ctxt with remaining_operation_gas} + +let[@inline] update_unlimited_operation_gas ctxt unlimited_operation_gas = + update_back ctxt {ctxt.back with unlimited_operation_gas} + +let[@inline] update_context ctxt context = + update_back ctxt {ctxt.back with context} + +let[@inline] update_constants ctxt constants = + update_back ctxt {ctxt.back with constants} + +let[@inline] update_origination_nonce ctxt origination_nonce = + update_back ctxt {ctxt.back with origination_nonce} + +let[@inline] update_internal_nonce ctxt internal_nonce = + update_back ctxt {ctxt.back with internal_nonce} + +let[@inline] update_internal_nonces_used ctxt internal_nonces_used = + update_back ctxt {ctxt.back with internal_nonces_used} + +let[@inline] update_fees ctxt fees = update_back ctxt {ctxt.back with fees} + +let[@inline] update_temporary_lazy_storage_ids ctxt temporary_lazy_storage_ids = + update_back ctxt {ctxt.back with temporary_lazy_storage_ids} + +let[@inline] update_non_consensus_operations_rev ctxt + non_consensus_operations_rev = + update_back ctxt {ctxt.back with non_consensus_operations_rev} + +let[@inline] update_dictator_proposal_seen ctxt dictator_proposal_seen = + update_back ctxt {ctxt.back with dictator_proposal_seen} + +let[@inline] update_sampler_state ctxt sampler_state = + update_back ctxt {ctxt.back with sampler_state} + +let[@inline] update_reward_coeff_for_current_cycle ctxt + reward_coeff_for_current_cycle = + update_back ctxt {ctxt.back with reward_coeff_for_current_cycle} + +let[@inline] set_adaptive_issuance_enable ctxt = + update_back ctxt {ctxt.back with adaptive_issuance_enable = true} + +type error += Too_many_internal_operations (* `Permanent *) + +type error += Block_quota_exceeded (* `Temporary *) + +type error += Operation_quota_exceeded (* `Temporary *) + +type error += Stake_distribution_not_set (* `Branch *) + +type error += Sampler_already_set of Cycle_repr.t (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"too_many_internal_operations" + ~title:"Too many internal operations" + ~description: + "A transaction exceeded the hard limit of internal operations it can emit" + empty + (function Too_many_internal_operations -> Some () | _ -> None) + (fun () -> Too_many_internal_operations) ; + register_error_kind + `Temporary + ~id:"gas_exhausted.operation" + ~title:"Gas quota exceeded for the operation" + ~description: + "A script or one of its callee took more time than the operation said it \ + would" + empty + (function Operation_quota_exceeded -> Some () | _ -> None) + (fun () -> Operation_quota_exceeded) ; + register_error_kind + `Temporary + ~id:"gas_exhausted.block" + ~title:"Gas quota exceeded for the block" + ~description: + "The sum of gas consumed by all the operations in the block exceeds the \ + hard gas limit per block" + empty + (function Block_quota_exceeded -> Some () | _ -> None) + (fun () -> Block_quota_exceeded) ; + register_error_kind + `Permanent + ~id:"delegate.stake_distribution_not_set" + ~title:"Stake distribution not set" + ~description:"The stake distribution for the current cycle is not set." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The stake distribution for the current cycle is not set.") + empty + (function Stake_distribution_not_set -> Some () | _ -> None) + (fun () -> Stake_distribution_not_set) ; + register_error_kind + `Permanent + ~id:"sampler_already_set" + ~title:"Sampler already set" + ~description: + "Internal error: Raw_context.set_sampler_for_cycle was called twice for \ + a given cycle" + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Internal error: sampler already set for cycle %a." + Cycle_repr.pp + c) + (obj1 (req "cycle" Cycle_repr.encoding)) + (function Sampler_already_set c -> Some c | _ -> None) + (fun c -> Sampler_already_set c) + +let fresh_internal_nonce ctxt = + let open Result_syntax in + if Compare.Int.(internal_nonce ctxt >= 65_535) then + tzfail Too_many_internal_operations + else + return + (update_internal_nonce ctxt (internal_nonce ctxt + 1), internal_nonce ctxt) + +let reset_internal_nonce ctxt = + let ctxt = update_internal_nonce ctxt 0 in + update_internal_nonces_used ctxt Int_set.empty + +let record_internal_nonce ctxt k = + update_internal_nonces_used ctxt (Int_set.add k (internal_nonces_used ctxt)) + +let internal_nonce_already_recorded ctxt k = + Int_set.mem k (internal_nonces_used ctxt) + +let get_collected_fees ctxt = fees ctxt + +let credit_collected_fees_only_call_from_token ctxt fees' = + let open Result_syntax in + let previous = get_collected_fees ctxt in + let+ fees = Tez_repr.(previous +? fees') in + update_fees ctxt fees + +let spend_collected_fees_only_call_from_token ctxt fees' = + let open Result_syntax in + let previous = get_collected_fees ctxt in + let+ fees = Tez_repr.(previous -? fees') in + update_fees ctxt fees + +type error += Undefined_operation_nonce (* `Permanent *) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"undefined_operation_nonce" + ~title:"Ill timed access to the origination nonce" + ~description: + "An origination was attempted out of the scope of a manager operation" + empty + (function Undefined_operation_nonce -> Some () | _ -> None) + (fun () -> Undefined_operation_nonce) + +let init_origination_nonce ctxt operation_hash = + let origination_nonce = Some (Origination_nonce.initial operation_hash) in + update_origination_nonce ctxt origination_nonce + +let increment_origination_nonce ctxt = + let open Result_syntax in + match origination_nonce ctxt with + | None -> tzfail Undefined_operation_nonce + | Some cur_origination_nonce -> + let origination_nonce = + Some (Origination_nonce.incr cur_origination_nonce) + in + let ctxt = update_origination_nonce ctxt origination_nonce in + return (ctxt, cur_origination_nonce) + +let get_origination_nonce ctxt = + let open Result_syntax in + match origination_nonce ctxt with + | None -> tzfail Undefined_operation_nonce + | Some origination_nonce -> return origination_nonce + +let unset_origination_nonce ctxt = update_origination_nonce ctxt None + +let gas_level ctxt = + let open Gas_limit_repr in + if unlimited_operation_gas ctxt then Unaccounted + else Limited {remaining = remaining_operation_gas ctxt} + +let block_gas_level = remaining_block_gas + +let consume_gas_limit_in_block ctxt gas_limit = + let open Gas_limit_repr in + let open Result_syntax in + let* () = + check_gas_limit + ~hard_gas_limit_per_operation: + (constants ctxt).hard_gas_limit_per_operation + ~gas_limit + in + let block_gas = block_gas_level ctxt in + let limit = Arith.fp gas_limit in + if Arith.(limit > block_gas) then tzfail Block_quota_exceeded + else + let level = Arith.sub (block_gas_level ctxt) limit in + let ctxt = update_remaining_block_gas ctxt level in + Ok ctxt + +let set_gas_limit ctxt (remaining : 'a Gas_limit_repr.Arith.t) = + let open Gas_limit_repr in + let remaining_operation_gas = Arith.fp remaining in + let ctxt = update_unlimited_operation_gas ctxt false in + {ctxt with remaining_operation_gas} + +let set_gas_unlimited ctxt = update_unlimited_operation_gas ctxt true + +let consume_gas ctxt cost = + let open Result_syntax in + match Gas_limit_repr.raw_consume (remaining_operation_gas ctxt) cost with + | Some gas_counter -> Ok (update_remaining_operation_gas ctxt gas_counter) + | None -> + if unlimited_operation_gas ctxt then return ctxt + else tzfail Operation_quota_exceeded + +let check_enough_gas ctxt cost = + let open Result_syntax in + let* (_ : t) = consume_gas ctxt cost in + return_unit + +let gas_consumed ~since ~until = + match (gas_level since, gas_level until) with + | Limited {remaining = before}, Limited {remaining = after} -> + Gas_limit_repr.Arith.sub before after + | _, _ -> Gas_limit_repr.Arith.zero + +type missing_key_kind = Get | Set | Del | Copy + +type storage_error = + | Incompatible_protocol_version of string + | Missing_key of string list * missing_key_kind + | Existing_key of string list + | Corrupted_data of string list + +let storage_error_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Incompatible_protocol_version" + (obj1 (req "incompatible_protocol_version" @@ string Plain)) + (function Incompatible_protocol_version arg -> Some arg | _ -> None) + (fun arg -> Incompatible_protocol_version arg); + case + (Tag 1) + ~title:"Missing_key" + (obj2 + (req "missing_key" (list @@ string Plain)) + (req + "function" + (string_enum + [("get", Get); ("set", Set); ("del", Del); ("copy", Copy)]))) + (function Missing_key (key, f) -> Some (key, f) | _ -> None) + (fun (key, f) -> Missing_key (key, f)); + case + (Tag 2) + ~title:"Existing_key" + (obj1 (req "existing_key" (list @@ string Plain))) + (function Existing_key key -> Some key | _ -> None) + (fun key -> Existing_key key); + case + (Tag 3) + ~title:"Corrupted_data" + (obj1 (req "corrupted_data" (list @@ string Plain))) + (function Corrupted_data key -> Some key | _ -> None) + (fun key -> Corrupted_data key); + ] + +let pp_storage_error ppf = function + | Incompatible_protocol_version version -> + Format.fprintf + ppf + "Found a context with an unexpected version '%s'." + version + | Missing_key (key, Get) -> + Format.fprintf ppf "Missing key '%s'." (String.concat "/" key) + | Missing_key (key, Set) -> + Format.fprintf + ppf + "Cannot set undefined key '%s'." + (String.concat "/" key) + | Missing_key (key, Del) -> + Format.fprintf + ppf + "Cannot delete undefined key '%s'." + (String.concat "/" key) + | Missing_key (key, Copy) -> + Format.fprintf + ppf + "Cannot copy undefined key '%s'." + (String.concat "/" key) + | Existing_key key -> + Format.fprintf + ppf + "Cannot initialize defined key '%s'." + (String.concat "/" key) + | Corrupted_data key -> + Format.fprintf + ppf + "Failed to parse the data at '%s'." + (String.concat "/" key) + +type error += Storage_error of storage_error + +let () = + register_error_kind + `Permanent + ~id:"context.storage_error" + ~title:"Storage error (fatal internal error)" + ~description: + "An error that should never happen unless something has been deleted or \ + corrupted in the database." + ~pp:(fun ppf err -> + Format.fprintf ppf "@[Storage error:@ %a@]" pp_storage_error err) + storage_error_encoding + (function Storage_error err -> Some err | _ -> None) + (fun err -> Storage_error err) + +let storage_error err = Result_syntax.tzfail (Storage_error err) + +(* Initialization *********************************************************) + +(* This key should always be populated for every version of the + protocol. It's absence meaning that the context is empty. *) +let version_key = ["version"] + +(* This value is set by the snapshot_alpha.sh script, don't change it. *) + +let protocol_migration_internal_message = + Sc_rollup_inbox_message_repr.Protocol_migration Constants_repr.version_value + +let protocol_migration_serialized_message = + match + Sc_rollup_inbox_message_repr.serialize + (Internal protocol_migration_internal_message) + with + | Ok msg -> msg + | Error trace -> + Format.kasprintf + failwith + "%s: Could not serialize protocol message : %a" + __LOC__ + pp_trace + trace + +let cycle_eras_key = [Constants_repr.version; "cycle_eras"] + +let constants_key = [Constants_repr.version; "constants"] + +let protocol_param_key = ["protocol_parameters"] + +let get_cycle_eras ctxt = + let open Lwt_syntax in + let+ bytes_opt = Context.find ctxt cycle_eras_key in + match bytes_opt with + | None -> storage_error (Missing_key (cycle_eras_key, Get)) + | Some bytes -> ( + match + Data_encoding.Binary.of_bytes_opt Level_repr.cycle_eras_encoding bytes + with + | None -> storage_error (Corrupted_data cycle_eras_key) + | Some cycle_eras -> Ok cycle_eras) + +let set_cycle_eras ctxt cycle_eras = + let open Lwt_result_syntax in + let bytes = + Data_encoding.Binary.to_bytes_exn Level_repr.cycle_eras_encoding cycle_eras + in + let*! ctxt = Context.add ctxt cycle_eras_key bytes in + return ctxt + +type error += Failed_to_parse_parameter of bytes + +type error += Failed_to_decode_parameter of Data_encoding.json * string + +let () = + register_error_kind + `Temporary + ~id:"context.failed_to_parse_parameter" + ~title:"Failed to parse parameter" + ~description:"The protocol parameters are not valid JSON." + ~pp:(fun ppf bytes -> + Format.fprintf + ppf + "@[Cannot parse the protocol parameter:@ %s@]" + (Bytes.to_string bytes)) + Data_encoding.(obj1 (req "contents" @@ bytes Hex)) + (function Failed_to_parse_parameter data -> Some data | _ -> None) + (fun data -> Failed_to_parse_parameter data) ; + register_error_kind + `Temporary + ~id:"context.failed_to_decode_parameter" + ~title:"Failed to decode parameter" + ~description:"Unexpected JSON object." + ~pp:(fun ppf (json, msg) -> + Format.fprintf + ppf + "@[Cannot decode the protocol parameter:@ %s@ %a@]" + msg + Data_encoding.Json.pp + json) + Data_encoding.(obj2 (req "contents" json) (req "error" @@ string Plain)) + (function + | Failed_to_decode_parameter (json, msg) -> Some (json, msg) | _ -> None) + (fun (json, msg) -> Failed_to_decode_parameter (json, msg)) + +let get_proto_param ctxt = + let open Lwt_result_syntax in + let*! bytes_opt = Context.find ctxt protocol_param_key in + match bytes_opt with + | None -> failwith "Missing protocol parameters." + | Some bytes -> ( + match Data_encoding.Binary.of_bytes_opt Data_encoding.json bytes with + | None -> tzfail (Failed_to_parse_parameter bytes) + | Some json -> ( + let*! ctxt = Context.remove ctxt protocol_param_key in + match Data_encoding.Json.destruct Parameters_repr.encoding json with + | exception (Data_encoding.Json.Cannot_destruct _ as exn) -> + Format.kasprintf + failwith + "Invalid protocol_parameters: %a %a" + (fun ppf -> Data_encoding.Json.print_error ppf) + exn + Data_encoding.Json.pp + json + | param -> + let*? () = Parameters_repr.check_params param in + return (param, ctxt))) + +let add_constants ctxt constants = + let bytes = + Data_encoding.Binary.to_bytes_exn + Constants_parametric_repr.encoding + constants + in + Context.add ctxt constants_key bytes + +let get_constants ctxt = + let open Lwt_result_syntax in + let*! bytes_opt = Context.find ctxt constants_key in + match bytes_opt with + | None -> failwith "Internal error: cannot read constants in context." + | Some bytes -> ( + match + Data_encoding.Binary.of_bytes_opt + Constants_parametric_repr.encoding + bytes + with + | None -> failwith "Internal error: cannot parse constants in context." + | Some constants -> return constants) + +let patch_constants ctxt f = + let open Lwt_syntax in + let constants = f (constants ctxt) in + let+ context = add_constants (context ctxt) constants in + let ctxt = update_context ctxt context in + update_constants ctxt constants + +let check_inited ctxt = + let open Lwt_syntax in + let+ bytes_opt = Context.find ctxt version_key in + match bytes_opt with + | None -> failwith "Internal error: un-initialized context." + | Some bytes -> + let s = Bytes.to_string bytes in + if Compare.String.(s = Constants_repr.version_value) then + Result.return_unit + else storage_error (Incompatible_protocol_version s) + +let check_cycle_eras (cycle_eras : Level_repr.cycle_eras) + (constants : Constants_parametric_repr.t) = + let current_era = Level_repr.current_era cycle_eras in + assert ( + Compare.Int32.(current_era.blocks_per_cycle = constants.blocks_per_cycle)) ; + assert ( + Compare.Int32.( + current_era.blocks_per_commitment = constants.blocks_per_commitment)) + +let prepare ~level ~predecessor_timestamp ~timestamp ~adaptive_issuance_enable + ctxt = + let open Lwt_result_syntax in + let*? level = Raw_level_repr.of_int32 level in + let* () = check_inited ctxt in + let* constants = get_constants ctxt in + let*? round_durations = + Round_repr.Durations.create + ~first_round_duration:constants.minimal_block_delay + ~delay_increment_per_round:constants.delay_increment_per_round + in + let+ cycle_eras = get_cycle_eras ctxt in + check_cycle_eras cycle_eras constants ; + let level = Level_repr.level_from_raw ~cycle_eras level in + let sc_rollup_current_messages = + Sc_rollup_inbox_repr.init_witness_no_history + in + { + remaining_operation_gas = Gas_limit_repr.Arith.zero; + back = + { + context = ctxt; + constants; + level; + predecessor_timestamp; + timestamp; + round_durations; + cycle_eras; + fees = Tez_repr.zero; + origination_nonce = None; + temporary_lazy_storage_ids = Lazy_storage_kind.Temp_ids.init; + internal_nonce = 0; + internal_nonces_used = Int_set.empty; + remaining_block_gas = + Gas_limit_repr.Arith.fp + constants.Constants_parametric_repr.hard_gas_limit_per_block; + unlimited_operation_gas = true; + consensus = Raw_consensus.empty; + non_consensus_operations_rev = []; + dictator_proposal_seen = false; + sampler_state = Cycle_repr.Map.empty; + stake_distribution_for_current_cycle = None; + reward_coeff_for_current_cycle = Q.one; + sc_rollup_current_messages; + dal_slot_fee_market = + Dal_slot_repr.Slot_market.init + ~length:constants.Constants_parametric_repr.dal.number_of_slots; + dal_attestation_slot_accountability = + Dal_attestation_repr.Accountability.init + ~number_of_slots: + constants.Constants_parametric_repr.dal.number_of_slots; + dal_cryptobox = None; + adaptive_issuance_enable; + }; + } + +type previous_protocol = Genesis of Parameters_repr.t | Oxford_018 + +let check_and_update_protocol_version ctxt = + let open Lwt_result_syntax in + let* previous_proto, ctxt = + let*! bytes_opt = Context.find ctxt version_key in + match bytes_opt with + | None -> + failwith "Internal error: un-initialized context in check_first_block." + | Some bytes -> + let s = Bytes.to_string bytes in + if Compare.String.(s = Constants_repr.version_value) then + failwith "Internal error: previously initialized context." + else if Compare.String.(s = "genesis") then + let+ param, ctxt = get_proto_param ctxt in + (Genesis param, ctxt) + else if Compare.String.(s = "oxford_018") then return (Oxford_018, ctxt) + else Lwt.return @@ storage_error (Incompatible_protocol_version s) + in + let*! ctxt = + Context.add ctxt version_key (Bytes.of_string Constants_repr.version_value) + in + return (previous_proto, ctxt) + +(* only for the migration *) +let[@warning "-32"] get_previous_protocol_constants ctxt = + let open Lwt_syntax in + let* bytes_opt = Context.find ctxt constants_key in + match bytes_opt with + | None -> + failwith + "Internal error: cannot read previous protocol constants in context." + | Some bytes -> ( + match + Data_encoding.Binary.of_bytes_opt + Constants_parametric_previous_repr.encoding + bytes + with + | None -> + failwith + "Internal error: cannot parse previous protocol constants in \ + context." + | Some constants -> return constants) + +let update_block_time_related_constants (c : Constants_parametric_repr.t) = + let divide_period p = + Period_repr.of_seconds_exn + Int64.(div (mul (Period_repr.to_seconds p) 2L) 3L) + in + let minimal_block_delay = divide_period c.minimal_block_delay in + let delay_increment_per_round = divide_period c.delay_increment_per_round in + let hard_gas_limit_per_block = + let two = Z.(succ one) in + let three = Z.(succ two) in + Gas_limit_repr.Arith.( + integral_exn + (Z.div (Z.mul (integral_to_z c.hard_gas_limit_per_block) two) three)) + in + let half_more x = Int32.(div (mul 3l x) 2l) in + let blocks_per_cycle = half_more c.blocks_per_cycle in + let blocks_per_commitment = half_more c.blocks_per_commitment in + let nonce_revelation_threshold = half_more c.nonce_revelation_threshold in + let max_operations_time_to_live = 3 * c.max_operations_time_to_live / 2 in + let block_time = Int64.to_int (Period_repr.to_seconds minimal_block_delay) in + let sc_rollup = + Constants_parametric_repr.update_sc_rollup_parameter c.sc_rollup ~block_time + in + { + c with + sc_rollup; + blocks_per_cycle; + blocks_per_commitment; + nonce_revelation_threshold; + max_operations_time_to_live; + minimal_block_delay; + delay_increment_per_round; + hard_gas_limit_per_block; + } + +let update_cycle_eras ctxt level ~prev_blocks_per_cycle ~blocks_per_cycle + ~blocks_per_commitment = + let open Lwt_result_syntax in + let* cycle_eras = get_cycle_eras ctxt in + let current_era = Level_repr.current_era cycle_eras in + let current_cycle = + let level_position = + Int32.sub level (Raw_level_repr.to_int32 current_era.first_level) + in + Cycle_repr.add + current_era.first_cycle + (Int32.to_int (Int32.div level_position prev_blocks_per_cycle)) + in + let new_cycle_era = + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn (Int32.succ level); + first_cycle = Cycle_repr.succ current_cycle; + blocks_per_cycle; + blocks_per_commitment; + } + in + let*? new_cycle_eras = Level_repr.add_cycle_era new_cycle_era cycle_eras in + set_cycle_eras ctxt new_cycle_eras + +(* You should ensure that if the type `Constants_parametric_repr.t` is + different from `Constants_parametric_previous_repr.t` or the value of these + constants is modified, is changed from the previous protocol, then + you `propagate` these constants to the new protocol by writing them + onto the context via the function `add_constants` or + `patch_constants`. + + This migration can be achieved also implicitly by modifying the + encoding directly in a way which is compatible with the previous + protocol. However, by doing so, you do not change the value of + these constants inside the context. *) +let prepare_first_block ~level ~timestamp _chain_id ctxt = + let open Lwt_result_syntax in + let* previous_proto, ctxt = check_and_update_protocol_version ctxt in + let* ctxt, previous_proto_constants = + match previous_proto with + | Genesis param -> + let*? first_level = Raw_level_repr.of_int32 level in + let cycle_era = + { + Level_repr.first_level; + first_cycle = Cycle_repr.root; + blocks_per_cycle = param.constants.blocks_per_cycle; + blocks_per_commitment = param.constants.blocks_per_commitment; + } + in + let*? cycle_eras = Level_repr.create_cycle_eras [cycle_era] in + let* ctxt = set_cycle_eras ctxt cycle_eras in + let*! result = add_constants ctxt param.constants in + return (result, None) + | Oxford_018 -> + let*! c = get_previous_protocol_constants ctxt in + + (* When modifying the line below, be careful that the values are + compatible with the encodings exported by the environment did not + change. *) + let cryptobox_parameters = + { + Dal.page_size = 3967; + slot_size = 126_944; + redundancy_factor = 8; + number_of_shards = 512; + } + in + let dal = + Constants_parametric_repr. + { + feature_enable = true; + incentives_enable = false; + number_of_slots = 32; + attestation_lag = 8; + attestation_threshold = 66; + cryptobox_parameters; + } + in + (* This test prevents the activation of the protocol if the + set of parameters given for the DAL is invalid. *) + let*? () = + match Dal.make cryptobox_parameters with + | Ok _cryptobox -> ok () + | Error (`Fail explanation) -> + error (Dal_errors_repr.Dal_cryptobox_error {explanation}) + in + let dal_activation_level = + if c.dal.feature_enable then + (* if dal was enable in previous protocol, do as if it were always + activated *) + Raw_level_repr.succ Raw_level_repr.root + else + (* dal activates at first level of the new protocol. *) + Raw_level_repr.of_int32_exn (Int32.succ level) + in + let dal_attested_slots_validity_lag = + (* A rollup node shouldn't import a page of an attested slot whose attested + level is too far in the past w.r.t. the current level. Importation window + is fixed to 241_920 levels below. It is the number of blocks produced + during 28 days (4 weeks) with a block time of 10 seconds. *) + 241_920 + in + let reveal_activation_level : + Constants_parametric_repr.sc_rollup_reveal_activation_level = + let ({ + raw_data = {blake2B}; + metadata; + dal_page = _; + dal_parameters = _; + } + : Constants_parametric_previous_repr + .sc_rollup_reveal_activation_level) = + c.sc_rollup.reveal_activation_level + in + { + raw_data = {blake2B}; + metadata; + dal_page = dal_activation_level; + dal_parameters = dal_activation_level; + (* Warning: the semantics of valid slots needs to be adapted if the + value of this parameter is changed in the future. + - If it is increased, some attested slots that were outdated with + the old value will become valid again. + - If it is decreased, some attested slots that were valid with + the old value will become outdated. + + In both cases, the status of slots before and after the value + change is different. So, the behaviour if a valid slot is + imported before the value upgrade but a refutation game + targetting a page of that slot is started after the upgrade is + not the correct/expected one. *) + dal_attested_slots_validity_lag; + } + in + let sc_rollup = + Constants_parametric_repr. + { + arith_pvm_enable = c.sc_rollup.arith_pvm_enable; + origination_size = c.sc_rollup.origination_size; + challenge_window_in_blocks = + c.sc_rollup.challenge_window_in_blocks; + stake_amount = c.sc_rollup.stake_amount; + commitment_period_in_blocks = + c.sc_rollup.commitment_period_in_blocks; + max_lookahead_in_blocks = c.sc_rollup.max_lookahead_in_blocks; + max_active_outbox_levels = c.sc_rollup.max_active_outbox_levels; + max_outbox_messages_per_level = + c.sc_rollup.max_outbox_messages_per_level; + number_of_sections_in_dissection = + c.sc_rollup.number_of_sections_in_dissection; + timeout_period_in_blocks = c.sc_rollup.timeout_period_in_blocks; + max_number_of_stored_cemented_commitments = + c.sc_rollup.max_number_of_stored_cemented_commitments; + max_number_of_parallel_games = + c.sc_rollup.max_number_of_parallel_games; + reveal_activation_level; + private_enable = c.sc_rollup.private_enable; + riscv_pvm_enable = c.sc_rollup.riscv_pvm_enable; + } + in + let zk_rollup = + Constants_parametric_repr. + { + enable = c.zk_rollup.enable; + origination_size = c.zk_rollup.origination_size; + min_pending_to_process = c.zk_rollup.min_pending_to_process; + max_ticket_payload_size = c.zk_rollup.max_ticket_payload_size; + } + in + + let adaptive_rewards_params = + Constants_parametric_repr. + { + issuance_ratio_final_min = Q.(0_25 // 100_00); + (* 0.25% *) + issuance_ratio_final_max = Q.(10 // 100) (* 10% *); + issuance_ratio_initial_min = Q.(45 // 1000); + (* 4.5% *) + issuance_ratio_initial_max = Q.(55 // 1000); + (* 5.5% *) + initial_period = 10; + (* 1 month *) + transition_period = 50; + (* 5 months *) + max_bonus = c.adaptive_issuance.adaptive_rewards_params.max_bonus; + growth_rate = + c.adaptive_issuance.adaptive_rewards_params.growth_rate; + center_dz = c.adaptive_issuance.adaptive_rewards_params.center_dz; + radius_dz = c.adaptive_issuance.adaptive_rewards_params.radius_dz; + } + in + let adaptive_issuance = + Constants_parametric_repr. + { + global_limit_of_staking_over_baking = + c.adaptive_issuance.global_limit_of_staking_over_baking; + edge_of_staking_over_delegation = + c.adaptive_issuance.edge_of_staking_over_delegation; + launch_ema_threshold = 0l; + adaptive_rewards_params; + activation_vote_enable = true; + autostaking_enable = c.adaptive_issuance.autostaking_enable; + force_activation = false; + ns_enable = true; + } + in + let liquidity_baking_subsidy = Tez_repr.(mul_exn one 5) in + let (issuance_weights : Constants_parametric_repr.issuance_weights) = + let ({ + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + liquidity_baking_subsidy_weight = _; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } + : Constants_parametric_previous_repr.issuance_weights) = + c.issuance_weights + in + let base_total_issued_per_minute = + let x = + Tez_repr.( + sub_opt base_total_issued_per_minute liquidity_baking_subsidy) + in + match x with None -> assert false | Some x -> x + in + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } + in + let direct_ticket_spending_enable = false in + let consensus_rights_delay = + (* We change the consensus_rights_delay value only for mainnet *) + if Compare.Int.(c.preserved_cycles = 5) then 2 else c.preserved_cycles + in + let Constants_repr.Generated.{max_slashing_threshold; _} = + Constants_repr.Generated.generate + ~consensus_committee_size:c.consensus_committee_size + in + let constants = + Constants_parametric_repr. + { + consensus_rights_delay; + blocks_preservation_cycles = 1; + delegate_parameters_activation_delay = c.preserved_cycles; + blocks_per_cycle = c.blocks_per_cycle; + blocks_per_commitment = c.blocks_per_commitment; + nonce_revelation_threshold = c.nonce_revelation_threshold; + cycles_per_voting_period = c.cycles_per_voting_period; + hard_gas_limit_per_operation = c.hard_gas_limit_per_operation; + hard_gas_limit_per_block = c.hard_gas_limit_per_block; + proof_of_work_threshold = c.proof_of_work_threshold; + minimal_stake = c.minimal_stake; + minimal_frozen_stake = c.minimal_frozen_stake; + vdf_difficulty = c.vdf_difficulty; + origination_size = c.origination_size; + max_operations_time_to_live = c.max_operations_time_to_live; + issuance_weights; + cost_per_byte = c.cost_per_byte; + hard_storage_limit_per_operation = + c.hard_storage_limit_per_operation; + quorum_min = c.quorum_min; + quorum_max = c.quorum_max; + min_proposal_quorum = c.min_proposal_quorum; + liquidity_baking_subsidy; + liquidity_baking_toggle_ema_threshold = + c.liquidity_baking_toggle_ema_threshold; + minimal_block_delay = c.minimal_block_delay; + delay_increment_per_round = c.delay_increment_per_round; + consensus_committee_size = c.consensus_committee_size; + consensus_threshold = c.consensus_threshold; + minimal_participation_ratio = c.minimal_participation_ratio; + limit_of_delegation_over_baking = + c.limit_of_delegation_over_baking; + percentage_of_frozen_deposits_slashed_per_double_baking = + Percentage.convert_from_o_to_p + c.percentage_of_frozen_deposits_slashed_per_double_baking; + percentage_of_frozen_deposits_slashed_per_double_attestation = + Percentage.convert_from_o_to_p + c.percentage_of_frozen_deposits_slashed_per_double_attestation; + max_slashing_per_block = Percentage.p100; + max_slashing_threshold; + (* The `testnet_dictator` should absolutely be None on mainnet *) + testnet_dictator = c.testnet_dictator; + initial_seed = c.initial_seed; + cache_script_size = c.cache_script_size; + cache_stake_distribution_cycles = + c.cache_stake_distribution_cycles; + cache_sampler_state_cycles = c.cache_sampler_state_cycles; + dal; + sc_rollup; + zk_rollup; + adaptive_issuance; + direct_ticket_spending_enable; + } + in + let block_time_is_at_least_8s = + (* This check is used to trigger the constants changes at migration on + this protocol for network that have block time strictly greater + than 7s such as mainnet and ghostnet *) + Compare.Int64.(Period_repr.to_seconds c.minimal_block_delay >= 8L) + in + let* ctxt, constants = + if block_time_is_at_least_8s then + let new_constants : Constants_parametric_repr.t = + update_block_time_related_constants constants + in + let* ctxt = + update_cycle_eras + ctxt + level + ~prev_blocks_per_cycle:constants.blocks_per_cycle + ~blocks_per_cycle:new_constants.blocks_per_cycle + ~blocks_per_commitment:new_constants.blocks_per_commitment + in + return (ctxt, new_constants) + else return (ctxt, constants) + in + let*! ctxt = add_constants ctxt constants in + return (ctxt, Some c) + in + let+ ctxt = + prepare + ctxt + ~level + ~predecessor_timestamp:timestamp + ~timestamp + ~adaptive_issuance_enable:false + in + (previous_proto, previous_proto_constants, ctxt) + +let activate ctxt h = + let open Lwt_syntax in + let+ new_ctxt = Updater.activate (context ctxt) h in + update_context ctxt new_ctxt + +(* Generic context ********************************************************) + +type key = string list + +type value = bytes + +type tree = Context.tree + +module type T = + Raw_context_intf.T + with type root := root + and type key := key + and type value := value + and type tree := tree + +let mem ctxt k = Context.mem (context ctxt) k + +let mem_tree ctxt k = Context.mem_tree (context ctxt) k + +let get ctxt k = + let open Lwt_result_syntax in + let*! v_opt = Context.find (context ctxt) k in + match v_opt with + | None -> Lwt.return @@ storage_error (Missing_key (k, Get)) + | Some v -> return v + +let get_tree ctxt k = + let open Lwt_result_syntax in + let*! v_opt = Context.find_tree (context ctxt) k in + match v_opt with + | None -> Lwt.return @@ storage_error (Missing_key (k, Get)) + | Some v -> return v + +let find ctxt k = Context.find (context ctxt) k + +let find_tree ctxt k = Context.find_tree (context ctxt) k + +let add ctxt k v = + let open Lwt_syntax in + let+ new_ctxt = Context.add (context ctxt) k v in + update_context ctxt new_ctxt + +let add_tree ctxt k v = + let open Lwt_syntax in + let+ new_ctxt = Context.add_tree (context ctxt) k v in + update_context ctxt new_ctxt + +let init ctxt k v = + let open Lwt_result_syntax in + let*! result = Context.mem (context ctxt) k in + match result with + | true -> Lwt.return @@ storage_error (Existing_key k) + | _ -> + let*! context = Context.add (context ctxt) k v in + return (update_context ctxt context) + +let init_tree ctxt k v : _ tzresult Lwt.t = + let open Lwt_result_syntax in + let*! result = Context.mem_tree (context ctxt) k in + match result with + | true -> Lwt.return @@ storage_error (Existing_key k) + | _ -> + let*! context = Context.add_tree (context ctxt) k v in + return (update_context ctxt context) + +let update ctxt k v = + let open Lwt_result_syntax in + let*! result = Context.mem (context ctxt) k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + let*! context = Context.add (context ctxt) k v in + return (update_context ctxt context) + +let update_tree ctxt k v = + let open Lwt_result_syntax in + let*! result = Context.mem_tree (context ctxt) k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + let*! context = Context.add_tree (context ctxt) k v in + return (update_context ctxt context) + +(* Verify that the key is present before deleting *) +let remove_existing ctxt k = + let open Lwt_result_syntax in + let*! result = Context.mem (context ctxt) k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + let*! context = Context.remove (context ctxt) k in + return (update_context ctxt context) + +(* Verify that the key is present before deleting *) +let remove_existing_tree ctxt k = + let open Lwt_result_syntax in + let*! result = Context.mem_tree (context ctxt) k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + let*! context = Context.remove (context ctxt) k in + return (update_context ctxt context) + +(* Do not verify before deleting *) +let remove ctxt k = + let open Lwt_syntax in + let+ new_ctxt = Context.remove (context ctxt) k in + update_context ctxt new_ctxt + +let add_or_remove ctxt k = function + | None -> remove ctxt k + | Some v -> add ctxt k v + +let add_or_remove_tree ctxt k = function + | None -> remove ctxt k + | Some v -> add_tree ctxt k v + +let list ctxt ?offset ?length k = Context.list (context ctxt) ?offset ?length k + +let fold ?depth ctxt k ~order ~init ~f = + Context.fold ?depth (context ctxt) k ~order ~init ~f + +let config ctxt = Context.config (context ctxt) + +module Proof = Context.Proof + +let length ctxt key = Context.length (context ctxt) key + +module Tree : + Raw_context_intf.TREE + with type t := t + and type key := key + and type value := value + and type tree := tree = struct + include Context.Tree + + let empty ctxt = Context.Tree.empty (context ctxt) + + let get t k = + let open Lwt_result_syntax in + let*! result = find t k in + match result with + | None -> Lwt.return @@ storage_error (Missing_key (k, Get)) + | Some v -> return v + + let get_tree t k = + let open Lwt_result_syntax in + let*! result = find_tree t k in + match result with + | None -> Lwt.return @@ storage_error (Missing_key (k, Get)) + | Some v -> return v + + let init t k v = + let open Lwt_result_syntax in + let*! result = mem t k in + match result with + | true -> Lwt.return @@ storage_error (Existing_key k) + | _ -> + let*! tree = add t k v in + return tree + + let init_tree t k v = + let open Lwt_result_syntax in + let*! result = mem_tree t k in + match result with + | true -> Lwt.return @@ storage_error (Existing_key k) + | _ -> + let*! tree = add_tree t k v in + return tree + + let update t k v = + let open Lwt_result_syntax in + let*! result = mem t k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + let*! tree = add t k v in + return tree + + let update_tree t k v = + let open Lwt_result_syntax in + let*! result = mem_tree t k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Set)) + | _ -> + let*! tree = add_tree t k v in + return tree + + (* Verify that the key is present before deleting *) + let remove_existing t k = + let open Lwt_result_syntax in + let*! result = mem t k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + let*! tree = remove t k in + return tree + + (* Verify that the key is present before deleting *) + let remove_existing_tree t k = + let open Lwt_result_syntax in + let*! result = mem_tree t k in + match result with + | false -> Lwt.return @@ storage_error (Missing_key (k, Del)) + | _ -> + let*! tree = remove t k in + return tree + + let add_or_remove t k = function None -> remove t k | Some v -> add t k v + + let add_or_remove_tree t k = function + | None -> remove t k + | Some v -> add_tree t k v +end + +let verify_tree_proof proof f = Context.verify_tree_proof proof f + +let verify_stream_proof proof f = Context.verify_stream_proof proof f + +let equal_config = Context.equal_config + +let project x = x + +let absolute_key _ k = k + +let description = Storage_description.create () + +let fold_map_temporary_lazy_storage_ids ctxt f = + f (temporary_lazy_storage_ids ctxt) |> fun (temporary_lazy_storage_ids, x) -> + (update_temporary_lazy_storage_ids ctxt temporary_lazy_storage_ids, x) + +let map_temporary_lazy_storage_ids_s ctxt f = + let open Lwt_syntax in + let+ ctxt, temporary_lazy_storage_ids = f (temporary_lazy_storage_ids ctxt) in + update_temporary_lazy_storage_ids ctxt temporary_lazy_storage_ids + +module Cache = struct + type key = Context.Cache.key + + type value = Context.Cache.value = .. + + let key_of_identifier = Context.Cache.key_of_identifier + + let identifier_of_key = Context.Cache.identifier_of_key + + let pp fmt ctxt = Context.Cache.pp fmt (context ctxt) + + let find c k = Context.Cache.find (context c) k + + let set_cache_layout c layout = + let open Lwt_syntax in + let+ ctxt = Context.Cache.set_cache_layout (context c) layout in + update_context c ctxt + + let update c k v = Context.Cache.update (context c) k v |> update_context c + + let sync c cache_nonce = + let open Lwt_syntax in + let+ ctxt = Context.Cache.sync (context c) ~cache_nonce in + update_context c ctxt + + let clear c = Context.Cache.clear (context c) |> update_context c + + let list_keys c ~cache_index = + Context.Cache.list_keys (context c) ~cache_index + + let key_rank c key = Context.Cache.key_rank (context c) key + + let cache_size_limit c ~cache_index = + Context.Cache.cache_size_limit (context c) ~cache_index + + let cache_size c ~cache_index = + Context.Cache.cache_size (context c) ~cache_index + + let future_cache_expectation c ~time_in_blocks = + Context.Cache.future_cache_expectation (context c) ~time_in_blocks + |> update_context c +end + +let record_non_consensus_operation_hash ctxt operation_hash = + update_non_consensus_operations_rev + ctxt + (operation_hash :: non_consensus_operations_rev ctxt) + +let non_consensus_operations ctxt = List.rev (non_consensus_operations_rev ctxt) + +let record_dictator_proposal_seen ctxt = update_dictator_proposal_seen ctxt true + +let dictator_proposal_seen ctxt = dictator_proposal_seen ctxt + +let init_sampler_for_cycle ctxt cycle seed state = + let open Result_syntax in + let map = sampler_state ctxt in + if Cycle_repr.Map.mem cycle map then tzfail (Sampler_already_set cycle) + else + let map = Cycle_repr.Map.add cycle (seed, state) map in + let ctxt = update_sampler_state ctxt map in + return ctxt + +let sampler_for_cycle ~read ctxt cycle = + let open Lwt_result_syntax in + let map = sampler_state ctxt in + match Cycle_repr.Map.find cycle map with + | Some (seed, state) -> return (ctxt, seed, state) + | None -> + let* seed, state = read ctxt in + let map = Cycle_repr.Map.add cycle (seed, state) map in + let ctxt = update_sampler_state ctxt map in + return (ctxt, seed, state) + +let find_stake_distribution_for_current_cycle ctxt = + ctxt.back.stake_distribution_for_current_cycle + +let stake_distribution_for_current_cycle ctxt = + let open Result_syntax in + match ctxt.back.stake_distribution_for_current_cycle with + | None -> tzfail Stake_distribution_not_set + | Some s -> return s + +let init_stake_distribution_for_current_cycle ctxt + stake_distribution_for_current_cycle = + update_back + ctxt + { + ctxt.back with + stake_distribution_for_current_cycle = + Some stake_distribution_for_current_cycle; + } + +module Internal_for_tests = struct + let add_level ctxt l = + let new_level = Level_repr.Internal_for_tests.add_level ctxt.back.level l in + let new_back = {ctxt.back with level = new_level} in + {ctxt with back = new_back} + + let add_cycles ctxt l = + let blocks_per_cycle = Int32.to_int (constants ctxt).blocks_per_cycle in + let new_level = + Level_repr.Internal_for_tests.add_cycles + ~blocks_per_cycle + ctxt.back.level + l + in + let new_back = {ctxt.back with level = new_level} in + {ctxt with back = new_back} +end + +module type CONSENSUS = sig + type t + + type 'value slot_map + + type slot_set + + type slot + + type round + + type consensus_pk + + val allowed_attestations : t -> (consensus_pk * int * int) slot_map option + + val allowed_preattestations : t -> (consensus_pk * int * int) slot_map option + + val forbidden_delegates : t -> Signature.Public_key_hash.Set.t + + type error += Slot_map_not_found of {loc : string} + + val current_attestation_power : t -> int + + val initialize_consensus_operation : + t -> + allowed_attestations:(consensus_pk * int * int) slot_map option -> + allowed_preattestations:(consensus_pk * int * int) slot_map option -> + t + + val record_attestation : t -> initial_slot:slot -> power:int -> t tzresult + + val record_preattestation : + t -> initial_slot:slot -> power:int -> round -> t tzresult + + val forbid_delegate : t -> Signature.Public_key_hash.t -> t + + val set_forbidden_delegates : t -> Signature.Public_key_hash.Set.t -> t + + val attestations_seen : t -> slot_set + + val get_preattestations_quorum_round : t -> round option + + val set_preattestations_quorum_round : t -> round -> t + + val locked_round_evidence : t -> (round * int) option + + val set_attestation_branch : t -> Block_hash.t * Block_payload_hash.t -> t + + val attestation_branch : t -> (Block_hash.t * Block_payload_hash.t) option +end + +module Consensus : + CONSENSUS + with type t := t + and type slot := Slot_repr.t + and type 'a slot_map := 'a Slot_repr.Map.t + and type slot_set := Slot_repr.Set.t + and type round := Round_repr.t + and type consensus_pk := consensus_pk = struct + let[@inline] update_consensus_with ctxt f = + {ctxt with back = {ctxt.back with consensus = f ctxt.back.consensus}} + + let[@inline] update_consensus_with_tzresult ctxt f = + let open Result_syntax in + let+ consensus = f ctxt.back.consensus in + {ctxt with back = {ctxt.back with consensus}} + + let[@inline] allowed_attestations ctxt = + ctxt.back.consensus.allowed_attestations + + let[@inline] allowed_preattestations ctxt = + ctxt.back.consensus.allowed_preattestations + + let[@inline] forbidden_delegates ctxt = + ctxt.back.consensus.forbidden_delegates + + let[@inline] set_forbidden_delegates ctxt delegates = + update_consensus_with ctxt (Raw_consensus.set_forbidden_delegates delegates) + + let[@inline] current_attestation_power ctxt = + ctxt.back.consensus.current_attestation_power + + let[@inline] get_preattestations_quorum_round ctxt = + ctxt.back.consensus.preattestations_quorum_round + + let[@inline] locked_round_evidence ctxt = + Raw_consensus.locked_round_evidence ctxt.back.consensus + + let[@inline] initialize_consensus_operation ctxt ~allowed_attestations + ~allowed_preattestations = + update_consensus_with + ctxt + (Raw_consensus.initialize_with_attestations_and_preattestations + ~allowed_attestations + ~allowed_preattestations) + + let[@inline] record_preattestation ctxt ~initial_slot ~power round = + update_consensus_with_tzresult + ctxt + (Raw_consensus.record_preattestation ~initial_slot ~power round) + + let[@inline] record_attestation ctxt ~initial_slot ~power = + update_consensus_with_tzresult + ctxt + (Raw_consensus.record_attestation ~initial_slot ~power) + + let[@inline] forbid_delegate ctxt delegate = + update_consensus_with ctxt (Raw_consensus.forbid_delegate delegate) + + let[@inline] attestations_seen ctxt = ctxt.back.consensus.attestations_seen + + let[@inline] set_preattestations_quorum_round ctxt round = + update_consensus_with + ctxt + (Raw_consensus.set_preattestations_quorum_round round) + + let[@inline] attestation_branch ctxt = + Raw_consensus.attestation_branch ctxt.back.consensus + + let[@inline] set_attestation_branch ctxt branch = + update_consensus_with ctxt (fun ctxt -> + Raw_consensus.set_attestation_branch ctxt branch) + + type error += Slot_map_not_found of {loc : string} + + let () = + register_error_kind + `Permanent + ~id:"raw_context.consensus.slot_map_not_found" + ~title:"Slot map not found" + ~description:"Pre-computed map by first slot not found." + Data_encoding.(obj1 (req "loc" (string Plain))) + (function Slot_map_not_found {loc} -> Some loc | _ -> None) + (fun loc -> Slot_map_not_found {loc}) +end + +(* + To optimize message insertion in smart contract rollup inboxes, we + maintain the sequence of current messages of each rollup used in + the block in a in-memory map. +*) +module Sc_rollup_in_memory_inbox = struct + let current_messages ctxt = ctxt.back.sc_rollup_current_messages + + let set_current_messages ctxt witness = + {ctxt with back = {ctxt.back with sc_rollup_current_messages = witness}} +end + +module Dal = struct + type cryptobox = Dal.t + + let make ctxt = + let open Result_syntax in + (* Dal.make takes some time (on the order of 10ms) so we memoize + its result to avoid calling it more than once per block. *) + match ctxt.back.dal_cryptobox with + | Some cryptobox -> return (ctxt, cryptobox) + | None -> ( + let Constants_parametric_repr.{dal = {cryptobox_parameters; _}; _} = + ctxt.back.constants + in + match Dal.make cryptobox_parameters with + | Ok cryptobox -> + let back = {ctxt.back with dal_cryptobox = Some cryptobox} in + return ({ctxt with back}, cryptobox) + | Error (`Fail explanation) -> + tzfail (Dal_errors_repr.Dal_cryptobox_error {explanation})) + + let number_of_slots ctxt = ctxt.back.constants.dal.number_of_slots + + let number_of_shards ctxt = + ctxt.back.constants.dal.cryptobox_parameters.number_of_shards + + let record_number_of_attested_shards ctxt attestation number = + let dal_attestation_slot_accountability = + Dal_attestation_repr.Accountability.record_number_of_attested_shards + ctxt.back.dal_attestation_slot_accountability + attestation + number + in + {ctxt with back = {ctxt.back with dal_attestation_slot_accountability}} + + let register_slot_header ctxt slot_header = + let open Result_syntax in + match + Dal_slot_repr.Slot_market.register + ctxt.back.dal_slot_fee_market + slot_header + with + | None -> + let length = + Dal_slot_repr.Slot_market.length ctxt.back.dal_slot_fee_market + in + tzfail + (Dal_errors_repr.Dal_register_invalid_slot_header + {length; slot_header}) + | Some (dal_slot_fee_market, updated) -> + if not updated then + tzfail + (Dal_errors_repr.Dal_publish_commitment_duplicate {slot_header}) + else return {ctxt with back = {ctxt.back with dal_slot_fee_market}} + + let candidates ctxt = + Dal_slot_repr.Slot_market.candidates ctxt.back.dal_slot_fee_market + + let is_slot_index_attested ctxt = + let threshold = + ctxt.back.constants.Constants_parametric_repr.dal.attestation_threshold + in + let number_of_shards = + ctxt.back.constants.Constants_parametric_repr.dal.cryptobox_parameters + .number_of_shards + in + Dal_attestation_repr.Accountability.is_slot_attested + ctxt.back.dal_attestation_slot_accountability + ~threshold + ~number_of_shards +end + +(* The type for relative context accesses instead from the root. In order for + the carbonated storage functions to consume the gas, this has gas infomation +*) +type local_context = { + tree : tree; + path : key; + remaining_operation_gas : Gas_limit_repr.Arith.fp; + unlimited_operation_gas : bool; +} + +let with_local_context ctxt key f = + let open Lwt_result_syntax in + let*! tree_opt = find_tree ctxt key in + let tree = + match tree_opt with None -> Tree.empty ctxt | Some tree -> tree + in + let local_ctxt = + { + tree; + path = key; + remaining_operation_gas = remaining_operation_gas ctxt; + unlimited_operation_gas = unlimited_operation_gas ctxt; + } + in + let* local_ctxt, res = f local_ctxt in + let*! ctxt = add_tree ctxt key local_ctxt.tree in + update_remaining_operation_gas ctxt local_ctxt.remaining_operation_gas + |> fun ctxt -> + update_unlimited_operation_gas ctxt local_ctxt.unlimited_operation_gas + |> fun ctxt -> return (ctxt, res) + +module Local_context : sig + include + Raw_context_intf.VIEW + with type t = local_context + and type key := key + and type value := value + and type tree := tree + + val consume_gas : + local_context -> Gas_limit_repr.cost -> local_context tzresult + + val absolute_key : local_context -> key -> key +end = struct + type t = local_context + + let consume_gas local cost = + let open Result_syntax in + match Gas_limit_repr.raw_consume local.remaining_operation_gas cost with + | Some gas_counter -> Ok {local with remaining_operation_gas = gas_counter} + | None -> + if local.unlimited_operation_gas then return local + else tzfail Operation_quota_exceeded + + let tree local = local.tree + + let update_root_tree local tree = {local with tree} + + let absolute_key local key = local.path @ key + + let find local = Tree.find (tree local) + + let find_tree local = Tree.find_tree (tree local) + + let mem local = Tree.mem (tree local) + + let mem_tree local = Tree.mem_tree (tree local) + + let get local = Tree.get (tree local) + + let get_tree local = Tree.get_tree (tree local) + + let update local key b = + let open Lwt_result_syntax in + let+ tree = Tree.update (tree local) key b in + update_root_tree local tree + + let update_tree local key b = + let open Lwt_result_syntax in + let+ tree = Tree.update_tree (tree local) key b in + update_root_tree local tree + + let init local key b = + let open Lwt_result_syntax in + let+ tree = Tree.init (tree local) key b in + update_root_tree local tree + + let init_tree local key t = + let open Lwt_result_syntax in + let+ tree = Tree.init_tree (tree local) key t in + update_root_tree local tree + + let add local i b = + let open Lwt_syntax in + let+ tree = Tree.add (tree local) i b in + update_root_tree local tree + + let add_tree local i t = + let open Lwt_syntax in + let+ tree = Tree.add_tree (tree local) i t in + update_root_tree local tree + + let remove local i = + let open Lwt_syntax in + let+ tree = Tree.remove (tree local) i in + update_root_tree local tree + + let remove_existing local key = + let open Lwt_result_syntax in + let+ tree = Tree.remove_existing (tree local) key in + update_root_tree local tree + + let remove_existing_tree local key = + let open Lwt_result_syntax in + let+ tree = Tree.remove_existing_tree (tree local) key in + update_root_tree local tree + + let add_or_remove local key vopt = + let open Lwt_syntax in + let+ tree = Tree.add_or_remove (tree local) key vopt in + update_root_tree local tree + + let add_or_remove_tree local key topt = + let open Lwt_syntax in + let+ tree = Tree.add_or_remove_tree (tree local) key topt in + update_root_tree local tree + + let fold ?depth local key ~order ~init ~f = + Tree.fold ?depth (tree local) key ~order ~init ~f + + let list local ?offset ?length key = + Tree.list (tree local) ?offset ?length key + + let config local = Tree.config (tree local) + + let length local i = Tree.length (tree local) i +end diff --git a/src/proto_020_PsParisC/lib_protocol/raw_context.mli b/src/proto_020_PsParisC/lib_protocol/raw_context.mli new file mode 100644 index 000000000000..8ce1fbe2de04 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/raw_context.mli @@ -0,0 +1,458 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili tech, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** State of the validation. + + Two parts: + + 1. Context.t: what is stored between blocks, this includes an + Irmin tree typically stored on disk and the cache (stored in + RAM). + + 2. Additional information needed during the validation of a + block but not persisted across blocks, always stored in + RAM. The gas counter is here. + + [Alpha_context.t] is actually implemented as [Raw_context.t]. + The difference is that Alpha_context.mli does not expose this + so functions manipulating an Alpha_context.t are guaranteed + to only access the context through the storage modules + exposed in Alpha_context.mli. These modules are in charge of + maintaining invariants over the structure of the context. *) + +(** {1 Errors} *) + +type error += Too_many_internal_operations (* `Permanent *) + +type missing_key_kind = Get | Set | Del | Copy + +(** An internal storage error that should not happen *) +type storage_error = + | Incompatible_protocol_version of string + | Missing_key of string list * missing_key_kind + | Existing_key of string list + | Corrupted_data of string list + +type error += Storage_error of storage_error + +type error += Failed_to_parse_parameter of bytes + +type error += Failed_to_decode_parameter of Data_encoding.json * string + +val storage_error : storage_error -> 'a tzresult + +(** {1 Abstract Context} *) + +(** Abstract view of the context. + Includes a handle to the functional key-value database + ({!Context.t}) along with some in-memory values (gas, etc.). *) +type t + +type root = t + +(** The internal message to be injected into the smart rollups’ shared + inbox when validating the very first block of this protocol. *) +val protocol_migration_internal_message : + Sc_rollup_inbox_message_repr.internal_inbox_message + +(** Serialized version of {!protocol_migration_internal_message}. *) +val protocol_migration_serialized_message : + Sc_rollup_inbox_message_repr.serialized + +(** Retrieves the state of the database and gives its abstract view. + It also returns wether this is the first block validated + with this version of the protocol. *) +val prepare : + level:Int32.t -> + predecessor_timestamp:Time.t -> + timestamp:Time.t -> + adaptive_issuance_enable:bool -> + Context.t -> + t tzresult Lwt.t + +type previous_protocol = Genesis of Parameters_repr.t | Oxford_018 + +val prepare_first_block : + level:int32 -> + timestamp:Time.t -> + Chain_id.t -> + Context.t -> + (previous_protocol * Constants_parametric_previous_repr.t option * t) tzresult + Lwt.t + +val activate : t -> Protocol_hash.t -> t Lwt.t + +(** Returns the state of the database resulting of operations on its + abstract view *) +val recover : t -> Context.t + +val current_level : t -> Level_repr.t + +val predecessor_timestamp : t -> Time.t + +val current_timestamp : t -> Time.t + +val constants : t -> Constants_parametric_repr.t + +val sc_rollup : t -> Constants_parametric_repr.sc_rollup + +val zk_rollup : t -> Constants_parametric_repr.zk_rollup + +val patch_constants : + t -> (Constants_parametric_repr.t -> Constants_parametric_repr.t) -> t Lwt.t + +val round_durations : t -> Round_repr.Durations.t + +(** Retrieve the cycle eras. *) +val cycle_eras : t -> Level_repr.cycle_eras + +(** Increment the current block fee stash that will be credited to the payload + producer's account at finalize_application *) +val credit_collected_fees_only_call_from_token : t -> Tez_repr.t -> t tzresult + +(** Decrement the current block fee stash that will be credited to the payload + producer's account at finalize_application *) +val spend_collected_fees_only_call_from_token : t -> Tez_repr.t -> t tzresult + +(** Returns the current block fee stash that will be credited to the payload + producer's account at finalize_application *) +val get_collected_fees : t -> Tez_repr.t + +(** [consume_gas_limit_in_block ctxt gas_limit] checks that + [gas_limit] is well-formed (i.e. it does not exceed the hard gas + limit per operation as defined in [ctxt], and it is positive), then + consumes [gas_limit] in the current block gas level of [ctxt]. + + @return [Error Gas_limit_repr.Gas_limit_too_high] if [gas_limit] + is greater than the allowed limit for operation gas level or + negative. + + @return [Error Block_quota_exceeded] if not enough gas remains in + the block. *) +val consume_gas_limit_in_block : t -> 'a Gas_limit_repr.Arith.t -> t tzresult + +val set_gas_limit : t -> 'a Gas_limit_repr.Arith.t -> t + +val set_gas_unlimited : t -> t + +val gas_level : t -> Gas_limit_repr.t + +val gas_consumed : since:t -> until:t -> Gas_limit_repr.Arith.fp + +val remaining_operation_gas : t -> Gas_limit_repr.Arith.fp + +val update_remaining_operation_gas : t -> Gas_limit_repr.Arith.fp -> t + +val block_gas_level : t -> Gas_limit_repr.Arith.fp + +val update_remaining_block_gas : t -> Gas_limit_repr.Arith.fp -> t + +type error += Undefined_operation_nonce (* `Permanent *) + +(** [init_origination_nonce ctxt hash] initialise the origination nonce in + memory from [hash]. See [Origination_nonce.t] for more information. *) +val init_origination_nonce : t -> Operation_hash.t -> t + +val get_origination_nonce : t -> Origination_nonce.t tzresult + +val increment_origination_nonce : t -> (t * Origination_nonce.t) tzresult + +(** [unset_origination_nonce ctxt] unset the origination nonce in memory. To be + used only when no more origination can be done in that operation. See + [Origination_nonce.t] for more information. *) +val unset_origination_nonce : t -> t + +(** {1 Generic accessors} *) + +type key = string list + +type value = bytes + +type tree + +type local_context + +module type T = + Raw_context_intf.T + with type root := root + and type key := key + and type value := value + and type tree := tree + +include T with type t := t and type local_context := local_context + +(** Initialize the local nonce used for preventing a script to + duplicate an internal operation to replay it. *) +val reset_internal_nonce : t -> t + +(** Increments the internal operation nonce. *) +val fresh_internal_nonce : t -> (t * int) tzresult + +(** Mark an internal operation nonce as taken. *) +val record_internal_nonce : t -> int -> t + +(** Check is the internal operation nonce has been taken. *) +val internal_nonce_already_recorded : t -> int -> bool + +val fold_map_temporary_lazy_storage_ids : + t -> + (Lazy_storage_kind.Temp_ids.t -> Lazy_storage_kind.Temp_ids.t * 'res) -> + t * 'res + +val map_temporary_lazy_storage_ids_s : + t -> + (Lazy_storage_kind.Temp_ids.t -> (t * Lazy_storage_kind.Temp_ids.t) Lwt.t) -> + t Lwt.t + +module Cache : sig + include + Context.CACHE + with type t := t + and type size := int + and type index := int + and type identifier := string + and type key = Context.Cache.key + and type value = Context.Cache.value + + val sync : t -> bytes -> t Lwt.t +end + +(* Hashes of non-consensus operations are stored so that, when + finalizing the block, we can compute the block's payload hash. *) +val record_non_consensus_operation_hash : t -> Operation_hash.t -> t + +val non_consensus_operations : t -> Operation_hash.t list + +type consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +val consensus_pk_encoding : consensus_pk Data_encoding.t + +(** Record that the dictator already voted in this block. *) +val record_dictator_proposal_seen : t -> t + +(** Checks whether the dictator voted in this block. *) +val dictator_proposal_seen : t -> bool + +(** [init_sampler_for_cycle ctxt cycle seed state] caches the seeded stake + sampler (a.k.a. [seed, state]) for [cycle] in memory for quick access. + + @return [Error Sampler_already_set] if the sampler was already + cached. *) +val init_sampler_for_cycle : + t -> Cycle_repr.t -> Seed_repr.seed -> consensus_pk Sampler.t -> t tzresult + +(** [sampler_for_cycle ~read ctxt cycle] returns the seeded stake + sampler for [cycle]. The sampler is read in memory if + [init_sampler_for_cycle] or [sampler_for_cycle] was previously + called for the same [cycle]. Otherwise, it is read "on-disk" with + the [read] function and then cached in [ctxt] like + [init_sampler_for_cycle]. *) +val sampler_for_cycle : + read:(t -> (Seed_repr.seed * consensus_pk Sampler.t) tzresult Lwt.t) -> + t -> + Cycle_repr.t -> + (t * Seed_repr.seed * consensus_pk Sampler.t) tzresult Lwt.t + +(* The stake distribution is stored both in [t] and in the cache. It + may be sufficient to only store it in the cache. *) +val stake_distribution_for_current_cycle : + t -> Stake_repr.t Signature.Public_key_hash.Map.t tzresult + +(** Like [stake_distribution_for_current_cycle] but returns [None] rather than + an error. *) +val find_stake_distribution_for_current_cycle : + t -> Stake_repr.t Signature.Public_key_hash.Map.t option + +val init_stake_distribution_for_current_cycle : + t -> Stake_repr.t Signature.Public_key_hash.Map.t -> t + +(** Returns the reward coefficient for the current cycle + This value is equal to the value in {!Storage.Issuance_coeff} if it exists, + or equal to [Q.one] otherwise. *) +val reward_coeff_for_current_cycle : t -> Q.t + +(** Updates the reward coefficient for the current cycle. + This update should only be called once per cycle. It is done in + [Adaptive_issuance_storage] *) +val update_reward_coeff_for_current_cycle : t -> Q.t -> t + +(** Returns true if adaptive issuance has launched. *) +val adaptive_issuance_enable : t -> bool + +(** Set the feature flag of adaptive issuance. *) +val set_adaptive_issuance_enable : t -> t + +module Internal_for_tests : sig + val add_level : t -> int -> t + + val add_cycles : t -> int -> t +end + +module type CONSENSUS = sig + type t + + type 'value slot_map + + type slot_set + + type slot + + type round + + type consensus_pk + + (** Returns a map where from the initial slot of each attester in the TB + committee for a given level, to the attester's public key and its + consensus power and DAL power. *) + val allowed_attestations : t -> (consensus_pk * int * int) slot_map option + + (** See {!allowed_attestations}. *) + val allowed_preattestations : t -> (consensus_pk * int * int) slot_map option + + (** Returns the set of delegates that are not allowed to bake or + attest blocks; i.e., delegates which have zero frozen deposit + due to a previous slashing. *) + val forbidden_delegates : t -> Signature.Public_key_hash.Set.t + + (** Missing pre-computed map by first slot. This error should not happen. *) + type error += Slot_map_not_found of {loc : string} + + (** [attestation power ctx] returns the attestation power of the + current block. *) + val current_attestation_power : t -> int + + (** Initializes the map of allowed attestations and preattestations, this + function must be called only once and before applying any consensus + operation. *) + val initialize_consensus_operation : + t -> + allowed_attestations:(consensus_pk * int * int) slot_map option -> + allowed_preattestations:(consensus_pk * int * int) slot_map option -> + t + + (** [record_attestation ctx ~initial_slot ~power] records an + attestation for the current block. + + The attestation should be valid in the sense that + [Int_map.find_opt initial_slot allowed_attestation ctx = Some + (pkh, power)]. *) + val record_attestation : t -> initial_slot:slot -> power:int -> t tzresult + + (** [record_preattestation ctx ~initial_slot ~power round + payload_hash power] records a preattestation for a proposal at + [round] with payload [payload_hash]. + + The preattestation should be valid in the sense that + [Int_map.find_opt initial_slot allowed_preattestation ctx = Some + (pkh, power)]. *) + val record_preattestation : + t -> initial_slot:slot -> power:int -> round -> t tzresult + + (** [forbid_delegate ctx delegate] adds [delegate] to the set of + forbidden delegates, which prevents this delegate from baking or + attesting. *) + val forbid_delegate : t -> Signature.Public_key_hash.t -> t + + (** [set_forbidden_delegate ctx delegates] sets [delegates] as the + current forbidden delegates. *) + val set_forbidden_delegates : t -> Signature.Public_key_hash.Set.t -> t + + val attestations_seen : t -> slot_set + + (** [get_preattestations_quorum_round ctx] returns [None] if no + preattestation are included in the current block. Otherwise, + return [Some r] where [r] is the round of the preattestations + included in the block. *) + val get_preattestations_quorum_round : t -> round option + + (** [set_preattestations_quorum_round ctx round] sets the round for + preattestations included in this block. This function should be + called only once. + + This function is only used in [Full_construction] mode. *) + val set_preattestations_quorum_round : t -> round -> t + + (** [locked_round_evidence ctx] returns the round of the recorded + preattestations as well as their power. *) + val locked_round_evidence : t -> (round * int) option + + val set_attestation_branch : t -> Block_hash.t * Block_payload_hash.t -> t + + val attestation_branch : t -> (Block_hash.t * Block_payload_hash.t) option +end + +module Consensus : + CONSENSUS + with type t := t + and type slot := Slot_repr.t + and type 'a slot_map := 'a Slot_repr.Map.t + and type slot_set := Slot_repr.Set.t + and type round := Round_repr.t + and type consensus_pk := consensus_pk + +module Sc_rollup_in_memory_inbox : sig + val current_messages : t -> Sc_rollup_inbox_merkelized_payload_hashes_repr.t + + val set_current_messages : + t -> Sc_rollup_inbox_merkelized_payload_hashes_repr.t -> t +end + +module Dal : sig + type cryptobox = Dal.t + + val make : t -> (t * cryptobox) tzresult + + val number_of_slots : t -> int + + val number_of_shards : t -> int + + (** [record_number_of_attested_shards ctxt attestation number_of_shards] + records that the [number_of_shards] shards were attested (declared + available by some attester). *) + val record_number_of_attested_shards : t -> Dal_attestation_repr.t -> int -> t + + (** [register_slot_header ctxt slot_header] returns a new context + where the new candidate [slot] have been taken into + account. Returns [Some (ctxt,updated)] where [updated=true] if + the candidate is registered. [Some (ctxt,false)] if another + candidate was already registered previously. Returns an error if + the slot is invalid. *) + val register_slot_header : t -> Dal_slot_repr.Header.t -> t tzresult + + (** [candidates ctxt] returns the current list of slot for which + there is at least one candidate. *) + val candidates : t -> Dal_slot_repr.Header.t list + + (** [is_slot_index_attested ctxt slot_index] returns [true] if the + [slot_index] is declared available by the protocol. [false] + otherwise. If the [index] is out of the interval + [0;number_of_slots - 1], returns [false]. *) + val is_slot_index_attested : t -> Dal_slot_index_repr.t -> bool +end diff --git a/src/proto_020_PsParisC/lib_protocol/raw_context_intf.ml b/src/proto_020_PsParisC/lib_protocol/raw_context_intf.ml new file mode 100644 index 000000000000..ff7bc662044a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/raw_context_intf.ml @@ -0,0 +1,599 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2018-2021 Tarides *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** All context manipulation functions. This signature is included + as-is for direct context accesses, and used in {!Storage_functors} + to provide restricted views to the context. *) + +(** The tree depth of a fold. See the [fold] function for more information. *) +type depth = [`Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int] + +(** The type for context configuration. If two trees or stores have the + same configuration, they will generate the same context hash. *) +type config = Context.config + +module type VIEW = sig + (* Same as [Environment_context.VIEW] but with extra getters and + setters functions. *) + + (** The type for context views. *) + type t + + (** The type for context keys. *) + type key = string list + + (** The type for context values. *) + type value = bytes + + (** The type for context trees. *) + type tree + + (** {2 Getters} *) + + (** [mem t k] is an Lwt promise that resolves to [true] iff [k] is bound + to a value in [t]. *) + val mem : t -> key -> bool Lwt.t + + (** [mem_tree t k] is like {!mem} but for trees. *) + val mem_tree : t -> key -> bool Lwt.t + + (** [get t k] is an Lwt promise that resolves to [Ok v] if [k] is + bound to the value [v] in [t] and {!Storage_Error Missing_key} + otherwise. *) + val get : t -> key -> value tzresult Lwt.t + + (** [get_tree] is like {!get} but for trees. *) + val get_tree : t -> key -> tree tzresult Lwt.t + + (** [find t k] is an Lwt promise that resolves to [Some v] if [k] is + bound to the value [v] in [t] and [None] otherwise. *) + val find : t -> key -> value option Lwt.t + + (** [find_tree t k] is like {!find} but for trees. *) + val find_tree : t -> key -> tree option Lwt.t + + (** [list t key] is the list of files and sub-nodes stored under [k] in [t]. + The result order is not specified but is stable. + + [offset] and [length] are used for pagination. *) + val list : + t -> ?offset:int -> ?length:int -> key -> (string * tree) list Lwt.t + + (** {2 Setters} *) + + (** [init t k v] is an Lwt promise that resolves to [Ok c] if: + + - [k] is unbound in [t]; + - [k] is bound to [v] in [c]; + - and [c] is similar to [t] otherwise. + + It is {!Storage_error Existing_key} if [k] is already bound in [t]. *) + val init : t -> key -> value -> t tzresult Lwt.t + + (** [init_tree] is like {!init} but for trees. *) + val init_tree : t -> key -> tree -> t tzresult Lwt.t + + (** [update t k v] is an Lwt promise that resolves to [Ok c] if: + + - [k] is bound in [t]; + - [k] is bound to [v] in [c]; + - and [c] is similar to [t] otherwise. + + It is {!Storage_error Missing_key} if [k] is not already bound in [t]. *) + val update : t -> key -> value -> t tzresult Lwt.t + + (** [update_tree] is like {!update} but for trees. *) + val update_tree : t -> key -> tree -> t tzresult Lwt.t + + (** [add t k v] is an Lwt promise that resolves to [c] such that: + + - [k] is bound to [v] in [c]; + - and [c] is similar to [t] otherwise. + + If [k] was already bound in [t] to a value that is physically equal + to [v], the result of the function is a promise that resolves to + [t]. Otherwise, the previous binding of [k] in [t] disappears. *) + val add : t -> key -> value -> t Lwt.t + + (** [add_tree] is like {!add} but for trees. *) + val add_tree : t -> key -> tree -> t Lwt.t + + (** [remove t k v] is an Lwt promise that resolves to [c] such that: + + - [k] is unbound in [c]; + - and [c] is similar to [t] otherwise. *) + val remove : t -> key -> t Lwt.t + + (** [remove_existing t k v] is an Lwt promise that resolves to [Ok c] if: + + - [k] is bound in [t] to a value; + - [k] is unbound in [c]; + - and [c] is similar to [t] otherwise.*) + val remove_existing : t -> key -> t tzresult Lwt.t + + (** [remove_existing_tree t k v] is an Lwt promise that reolves to [Ok c] if: + + - [k] is bound in [t] to a tree; + - [k] is unbound in [c]; + - and [c] is similar to [t] otherwise.*) + val remove_existing_tree : t -> key -> t tzresult Lwt.t + + (** [add_or_remove t k v] is: + + - [add t k x] if [v] is [Some x]; + - [remove t k] otherwise. *) + val add_or_remove : t -> key -> value option -> t Lwt.t + + (** [add_or_remove_tree t k v] is: + + - [add_tree t k x] if [v] is [Some x]; + - [remove t k] otherwise. *) + val add_or_remove_tree : t -> key -> tree option -> t Lwt.t + + (** {2 Folds} *) + + (** [fold ?depth t root ~order ~init ~f] recursively folds over the trees + and values of [t]. The [f] callbacks are called with a key relative + to [root]. [f] is never called with an empty key for values; i.e., + folding over a value is a no-op. + + The depth is 0-indexed. If [depth] is set (by default it is not), then [f] + is only called when the conditions described by the parameter is true: + + - [Eq d] folds over nodes and values of depth exactly [d]. + - [Lt d] folds over nodes and values of depth strictly less than [d]. + - [Le d] folds over nodes and values of depth less than or equal to [d]. + - [Gt d] folds over nodes and values of depth strictly more than [d]. + - [Ge d] folds over nodes and values of depth more than or equal to [d]. + + If [order] is [`Sorted] (the default), the elements are traversed in + lexicographic order of their keys. For large nodes, it is memory-consuming, + use [`Undefined] for a more memory efficient [fold]. *) + val fold : + ?depth:depth -> + t -> + key -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(key -> tree -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + (** {2 Hash configurations} *) + + (** [config t] is [t]'s hash configuration. *) + val config : t -> config + + (** [length t key] is an Lwt promise that resolves to the number of files and + sub-nodes stored under [k] in [t]. + + It is equivalent to [let+ l = list t k in List.length l] but has a constant-time + complexity. + + Most of the time, this function does not perform any I/O as the length is + cached in the tree. It may perform one read to load the root node of the + tree in case it has not been loaded already. The initial constant is the + same between [list] and [length]. They both perform the same kind of I/O + reads. While [list] usually performs a linear number of reads, [length] + does at most one. *) + val length : t -> key -> int Lwt.t +end + +module Kind = struct + type t = [`Value | `Tree] +end + +module type TREE = sig + (** [Tree] provides immutable, in-memory partial mirror of the + context, with lazy reads and delayed writes. The trees are Merkle + trees that carry the same hash as the part of the context they + mirror. + + Trees are immutable and non-persistent (they disappear if the + host crash), held in memory for efficiency, where reads are done + lazily and writes are done only when needed, e.g. on + [Context.commit]. If a key is modified twice, only the last + value will be written to disk on commit. *) + + (** The type for context views. *) + type t + + (** The type for context trees. *) + type tree + + include VIEW with type t := tree and type tree := tree + + (** [empty _] is the empty tree. *) + val empty : t -> tree + + (** [is_empty t] is true iff [t] is [empty _]. *) + val is_empty : tree -> bool + + (** [kind t] is [t]'s kind. It's either a tree node or a leaf + value. *) + val kind : tree -> Kind.t + + (** [to_value t] is an Lwt promise that resolves to [Some v] if [t] + is a leaf tree and [None] otherwise. It is equivalent to [find t + []]. *) + val to_value : tree -> value option Lwt.t + + (** [hash t] is [t]'s Merkle hash. *) + val hash : tree -> Context_hash.t + + (** [equal x y] is true iff [x] and [y] have the same Merkle hash. *) + val equal : tree -> tree -> bool + + (** {2 Caches} *) + + (** [clear ?depth t] clears all caches in the tree [t] for subtrees with a + depth higher than [depth]. If [depth] is not set, all of the subtrees are + cleared. *) + val clear : ?depth:int -> tree -> unit +end + +module type PROOF = sig + (** Proofs are compact representations of trees which can be shared + between peers. + + This is expected to be used as follows: + + - A first peer runs a function [f] over a tree [t]. While performing + this computation, it records: the hash of [t] (called [before] + below), the hash of [f t] (called [after] below) and a subset of [t] + which is needed to replay [f] without any access to the first peer's + storage. Once done, all these informations are packed into a proof of + type [t] that is sent to the second peer. + + - The second peer generates an initial tree [t'] from [p] and computes + [f t']. Once done, it compares [t']'s hash and [f t']'s hash to [before] + and [after]. If they match, they know that the result state [f t'] is a + valid context state, without having to have access to the full storage + of the first peer. *) + + (** The type for file and directory names. *) + type step = string + + (** The type for values. *) + type value = bytes + + (** The type of indices for inodes' children. *) + type index = int + + (** The type for hashes. *) + type hash = Context_hash.t + + (** The type for (internal) inode proofs. + + These proofs encode large directories into a tree-like structure. This + reflects irmin-pack's way of representing nodes and computing + hashes (tree-like representations for nodes scales better than flat + representations). + + [length] is the total number of entries in the children of the inode. + It's the size of the "flattened" version of that inode. [length] can be + used to prove the correctness of operations such [Tree.length] and + [Tree.list ~offset ~length] in an efficient way. + + In proofs with [version.is_binary = false], an inode at depth 0 has a + [length] of at least [257]. Below that threshold a [Node] tag is used in + [tree]. That threshold is [3] when [version.is_binary = true]. + + [proofs] contains the children proofs. It is a sparse list of ['a] values. + These values are associated to their index in the list, and the list is + kept sorted in increasing order of indices. ['a] can be a concrete proof + or a hash of that proof. + + In proofs with [version.is_binary = true], inodes have at most 2 proofs + (indexed 0 or 1). + + In proofs with [version.is_binary = false], inodes have at most 32 proofs + (indexed from 0 to 31). *) + type 'a inode = {length : int; proofs : (index * 'a) list} + + (** The type for inode extenders. + + An extender is a compact representation of a sequence of [inode] which + contain only one child. As for inodes, The ['a] parameter can be a + concrete proof or a hash of that proof. + + If an inode proof contains singleton children [i_0, ..., i_n] such as: + [{length=l; proofs = [ (i_0, {proofs = ... { proofs = [ (i_n, p) ] }})]}], + then it is compressed into the inode extender + [{length=l; segment = [i_0;..;i_n]; proof=p}] sharing the same lenght [l] + and final proof [p]. *) + type 'a inode_extender = {length : int; segment : index list; proof : 'a} + + (** The type for compressed and partial Merkle tree proofs. + + Tree proofs do not provide any guarantee with the ordering of + computations. For instance, if two effects commute, they won't be + distinguishable by this kind of proofs. + + [Value v] proves that a value [v] exists in the store. + + [Blinded_value h] proves a value with hash [h] exists in the store. + + [Node ls] proves that a a "flat" node containing the list of files [ls] + exists in the store. + + In proofs with [version.is_binary = true], the length of [ls] is at most + 2. + + In proofs with [version.is_binary = false], the length of [ls] is at most + 256. + + [Blinded_node h] proves that a node with hash [h] exists in the store. + + [Inode i] proves that an inode [i] exists in the store. + + [Extender e] proves that an inode extender [e] exist in the store. *) + type tree = + | Value of value + | Blinded_value of hash + | Node of (step * tree) list + | Blinded_node of hash + | Inode of inode_tree inode + | Extender of inode_tree inode_extender + + (** The type for inode trees. It is a subset of [tree], limited to nodes. + + [Blinded_inode h] proves that an inode with hash [h] exists in the store. + + [Inode_values ls] is similar to trees' [Node]. + + [Inode_tree i] is similar to tree's [Inode]. + + [Inode_extender e] is similar to trees' [Extender]. *) + and inode_tree = + | Blinded_inode of hash + | Inode_values of (step * tree) list + | Inode_tree of inode_tree inode + | Inode_extender of inode_tree inode_extender + + (** The type for kinded hashes. *) + type kinded_hash = [`Value of hash | `Node of hash] + + module Stream : sig + (** Stream proofs represent an explicit traversal of a Merle tree proof. + Every element (a node, a value, or a shallow pointer) met is first + "compressed" by shallowing its children and then recorded in the proof. + + As stream proofs directly encode the recursive construction of the + Merkle root hash is slightly simpler to implement: verifier simply + need to hash the compressed elements lazily, without any memory or + choice. + + Moreover, the minimality of stream proofs is trivial to check. + Once the computation has consumed the compressed elements required, + it is sufficient to check that no more compressed elements remain + in the proof. + + However, as the compressed elements contain all the hashes of their + shallow children, the size of stream proofs is larger + (at least double in size in practice) than tree proofs, which only + contains the hash for intermediate shallow pointers. *) + + (** The type for elements of stream proofs. + + [Value v] is a proof that the next element read in the store is the + value [v]. + + [Node n] is a proof that the next element read in the store is the + node [n]. + + [Inode i] is a proof that the next element read in the store is the + inode [i]. + + [Inode_extender e] is a proof that the next element read in the store + is the node extender [e]. *) + type elt = + | Value of value + | Node of (step * kinded_hash) list + | Inode of hash inode + | Inode_extender of hash inode_extender + + (** The type for stream proofs. + + The sequence [e_1 ... e_n] proves that the [e_1], ..., [e_n] are + read in the store in sequence. *) + type t = elt Seq.t + end + + type stream = Stream.t + + (** The type for proofs of kind ['a]. + + A proof [p] proves that the state advanced from [before p] to + [after p]. [state p]'s hash is [before p], and [state p] contains + the minimal information for the computation to reach [after p]. + + [version p] is the proof version, it packs several informations. + + [is_stream] discriminates between the stream proofs and the tree proofs. + + [is_binary] discriminates between proofs emitted from + [Tezos_context(_memory).Context_binary] and + [Tezos_context(_memory).Context]. + + It will also help discriminate between the data encoding techniques used. + + The version is meant to be decoded and encoded using the + {!Tezos_context_helpers.Context.decode_proof_version} and + {!Tezos_context_helpers.Context.encode_proof_version}. *) + type 'a t = { + version : int; + before : kinded_hash; + after : kinded_hash; + state : 'a; + } +end + +module type T = sig + (** The type for root contexts. *) + type root + + include VIEW + + module Tree : + TREE + with type t := t + and type key := key + and type value := value + and type tree := tree + + module Proof : PROOF + + (** [verify p f] runs [f] in checking mode. [f] is a function that takes a + tree as input and returns a new version of the tree and a result. [p] is a + proof, that is a minimal representation of the tree that contains what [f] + should be expecting. + + Therefore, contrary to trees found in a storage, the contents of the trees + passed to [f] may not be available. For this reason, looking up a value at + some [path] can now produce three distinct outcomes: + - A value [v] is present in the proof [p] and returned : [find tree path] + is a promise returning [Some v]; + - [path] is known to have no value in [tree] : [find tree path] is a + promise returning [None]; and + - [path] is known to have a value in [tree] but [p] does not provide it + because [f] should not need it: [verify] returns an error classifying + [path] as an invalid path (see below). + + The same semantics apply to all operations on the tree [t] passed to [f] + and on all operations on the trees built from [f]. + + The generated tree is the tree after [f] has completed. That tree is + disconnected from any storage (i.e. [index]). It is possible to run + operations on it as long as they don't require loading shallowed subtrees. + + The result is [Error (`Msg _)] if the proof is rejected: + - For tree proofs: when [p.before] is different from the hash of + [p.state]; + - For tree and stream proofs: when [p.after] is different from the hash + of [f p.state]; + - For tree proofs: when [f p.state] tries to access invalid paths in + [p.state]; + - For stream proofs: when the proof is not consumed in the exact same + order it was produced; + - For stream proofs: when the proof is too short or not empty once [f] is + done. + + @raise Failure if the proof version is invalid or incompatible with the + verifier. *) + type ('proof, 'result) verifier := + 'proof -> + (tree -> (tree * 'result) Lwt.t) -> + ( tree * 'result, + [ `Proof_mismatch of string + | `Stream_too_long of string + | `Stream_too_short of string ] ) + result + Lwt.t + + (** The type for tree proofs. + + Guarantee that the given computation performs exactly the same state + operations as the generating computation, *in some order*. *) + type tree_proof := Proof.tree Proof.t + + (** [verify_tree_proof] is the verifier of tree proofs. *) + val verify_tree_proof : (tree_proof, 'a) verifier + + (** The type for stream proofs. + + Guarantee that the given computation performs exactly the same state + operations as the generating computation, in the exact same order. *) + type stream_proof := Proof.stream Proof.t + + (** [verify_stream] is the verifier of stream proofs. *) + val verify_stream_proof : (stream_proof, 'a) verifier + + (** The equality function for context configurations. If two context have the + same configuration, they will generate the same context hashes. *) + val equal_config : config -> config -> bool + + (** Internally used in {!Storage_functors} to escape from a view. *) + val project : t -> root + + (** Internally used in {!Storage_functors} to retrieve a full key + from partial key relative a view. *) + val absolute_key : t -> key -> key + + (** Raised if block gas quota is exhausted during gas + consumption. *) + type error += Block_quota_exceeded + + (** Raised if operation gas quota is exhausted during gas + consumption. *) + type error += Operation_quota_exceeded + + (** Internally used in {!Storage_functors} to consume gas from + within a view. May raise {!Block_quota_exceeded} or + {!Operation_quota_exceeded}. *) + val consume_gas : t -> Gas_limit_repr.cost -> t tzresult + + (** Check if consume_gas will fail *) + val check_enough_gas : t -> Gas_limit_repr.cost -> unit tzresult + + val description : t Storage_description.t + + (** The type for local context accesses instead from the root. In order for + the carbonated storage functions to consume the gas, this has gas + infomation *) + type local_context + + (** + [with_local_context ctxt key f] runs function [f] over the local + context at path [key] of the global [ctxt]. Using the local context [f] + can perform faster context accesses under [key]. + *) + val with_local_context : + t -> + key -> + (local_context -> (local_context * 'a) tzresult Lwt.t) -> + (t * 'a) tzresult Lwt.t + + (** [Local_context] provides functions for local access from a specific + directory. *) + module Local_context : sig + include + VIEW + with type t = local_context + and type tree := tree + and type key := key + and type value := value + + (** Internally used in {!Storage_functors} to consume gas from + within a view. May raise {!Block_quota_exceeded} or + {!Operation_quota_exceeded}. *) + val consume_gas : + local_context -> Gas_limit_repr.cost -> local_context tzresult + + (** Internally used in {!Storage_functors} to retrieve the full key of a + partial key relative to the [local_context]. *) + val absolute_key : local_context -> key -> key + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/raw_level_repr.ml b/src/proto_020_PsParisC/lib_protocol/raw_level_repr.ml new file mode 100644 index 000000000000..63c9e1cd9587 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/raw_level_repr.ml @@ -0,0 +1,131 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = int32 + +type raw_level = t + +include (Compare.Int32 : Compare.S with type t := t) + +module Set = Set.Make (Compare.Int32) +module Map = Map.Make (Compare.Int32) + +let pp ppf level = Format.fprintf ppf "%ld" level + +let rpc_arg = + let construct raw_level = Int32.to_string raw_level in + let destruct str = + Int32.of_string_opt str |> Option.to_result ~none:"Cannot parse level" + in + RPC_arg.make + ~descr:"A level integer" + ~name:"block_level" + ~construct + ~destruct + () + +let root = 0l + +let succ = Int32.succ + +let add l i = + let x = Int32.add l (Int32.of_int i) in + assert (Compare.Int32.(x >= 0l)) ; + x + +let sub l i = + assert (Compare.Int.(i >= 0)) ; + let res = Int32.sub l (Int32.of_int i) in + if Compare.Int32.(res >= 0l) then Some res else None + +let pred l = if l = 0l then None else Some (Int32.pred l) + +let pred_dontreturnzero l = if l <= 1l then None else Some (Int32.pred l) + +let diff = Int32.sub + +let to_int32 l = l + +let to_int32_non_negative l = + match Bounded.Non_negative_int32.of_value l with + | Some x -> x + | _ -> assert false (* invariant: raw_levels are non-negative *) + +type error += Unexpected_level of Int32.t (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"unexpected_level" + ~title:"Unexpected level" + ~description:"Level must be non-negative." + ~pp:(fun ppf l -> + Format.fprintf + ppf + "The level is %s but should be non-negative." + (Int32.to_string l)) + Data_encoding.(obj1 (req "level" int32)) + (function Unexpected_level l -> Some l | _ -> None) + (fun l -> Unexpected_level l) + +let of_int32 l = + let open Result_syntax in + if Compare.Int32.(l >= 0l) then return l else tzfail (Unexpected_level l) + +let of_int32_exn l = + match of_int32 l with + | Ok l -> l + | Error _ -> invalid_arg "Level_repr.of_int32" + +let of_int32_non_negative l = + match of_int32 (Bounded.Non_negative_int32.to_value l) with + | Ok l -> l + | Error _ -> assert false (* invariant: raw_levels are non-negative *) + +let encoding = + Data_encoding.conv_with_guard + ~schema:Data_encoding.positive_int32_schema + to_int32 + (fun l -> + match of_int32 l with + | Ok l -> Ok l + | Error _ -> Error "Level_repr.of_int32") + Data_encoding.int32 + +module Index = struct + type t = raw_level + + let path_length = 1 + + let to_path level l = Int32.to_string level :: l + + let of_path = function [s] -> Int32.of_string_opt s | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_020_PsParisC/lib_protocol/raw_level_repr.mli b/src/proto_020_PsParisC/lib_protocol/raw_level_repr.mli new file mode 100644 index 000000000000..5be1510c03b2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/raw_level_repr.mli @@ -0,0 +1,75 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The shell's notion of a level: an integer indicating the number of blocks + since genesis: genesis is 0, all other blocks have increasing levels from + there. *) +type t + +type raw_level = t + +module Set : Set.S with type elt = t + +module Map : Map.S with type key = t + +(** @raise Invalid_argument when the level to encode is not positive *) +val encoding : raw_level Data_encoding.t + +val rpc_arg : raw_level RPC_arg.arg + +val pp : Format.formatter -> raw_level -> unit + +include Compare.S with type t := raw_level + +val to_int32 : raw_level -> int32 + +val to_int32_non_negative : raw_level -> Bounded.Non_negative_int32.t + +(** @raise Invalid_argument when the level to encode is negative *) +val of_int32_exn : int32 -> raw_level + +(** Can trigger Unexpected_level error when the level to encode is negative *) +val of_int32 : int32 -> raw_level tzresult + +val of_int32_non_negative : Bounded.Non_negative_int32.t -> raw_level + +val diff : raw_level -> raw_level -> int32 + +val root : raw_level + +val succ : raw_level -> raw_level + +val pred : raw_level -> raw_level option + +(** Return the predecessor of [l] when [l >= 2], otherwise return [None]. *) +val pred_dontreturnzero : raw_level -> raw_level option + +(** [add l i] i must be positive *) +val add : raw_level -> int -> raw_level + +(** [sub l i] i must be positive *) +val sub : raw_level -> int -> raw_level option + +module Index : Storage_description.INDEX with type t = raw_level diff --git a/src/proto_020_PsParisC/lib_protocol/receipt_repr.ml b/src/proto_020_PsParisC/lib_protocol/receipt_repr.ml new file mode 100644 index 000000000000..a85addec041b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/receipt_repr.ml @@ -0,0 +1,686 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Token = struct + type 'token t = + | Tez : Tez_repr.t t + | Staking_pseudotoken : Staking_pseudotoken_repr.t t + + let eq : + type token1 token2. + token1 t -> token2 t -> (token1, token2) Equality_witness.eq option = + fun t1 t2 -> + match (t1, t2) with + | Tez, Tez -> Some Refl + | Tez, _ | _, Tez -> None + | Staking_pseudotoken, Staking_pseudotoken -> Some Refl + + let equal : type token. token t -> token -> token -> bool = function + | Tez -> Tez_repr.( = ) + | Staking_pseudotoken -> Staking_pseudotoken_repr.( = ) + + let is_zero : type token. token t -> token -> bool = + fun token t -> + match token with + | Tez -> Tez_repr.(t = zero) + | Staking_pseudotoken -> Staking_pseudotoken_repr.(t = zero) + + let le : type token. token t -> token -> token -> bool = function + | Tez -> Tez_repr.( <= ) + | Staking_pseudotoken -> Staking_pseudotoken_repr.( <= ) + + let add : type token. token t -> token -> token -> token tzresult = function + | Tez -> Tez_repr.( +? ) + | Staking_pseudotoken -> Staking_pseudotoken_repr.( +? ) + + let sub : type token. token t -> token -> token -> token tzresult = function + | Tez -> Tez_repr.( -? ) + | Staking_pseudotoken -> Staking_pseudotoken_repr.( -? ) + + let pp_tez = + let tez_sym = "\xEA\x9C\xA9" in + fun ppf tez -> Format.fprintf ppf "%s%a" tez_sym Tez_repr.pp tez + + let pp : type token. token t -> Format.formatter -> token -> unit = function + | Tez -> pp_tez + | Staking_pseudotoken -> Staking_pseudotoken_repr.pp +end + +type 'token balance = + | Contract : Contract_repr.t -> Tez_repr.t balance + | Block_fees : Tez_repr.t balance + | Deposits : Frozen_staker_repr.t -> Tez_repr.t balance + | Unstaked_deposits : + Unstaked_frozen_staker_repr.t * Cycle_repr.t + -> Tez_repr.t balance + | Nonce_revelation_rewards : Tez_repr.t balance + | Attesting_rewards : Tez_repr.t balance + | Baking_rewards : Tez_repr.t balance + | Baking_bonuses : Tez_repr.t balance + | Storage_fees : Tez_repr.t balance + | Double_signing_punishments : Tez_repr.t balance + | Lost_attesting_rewards : + Signature.Public_key_hash.t * bool * bool + -> Tez_repr.t balance + | Liquidity_baking_subsidies : Tez_repr.t balance + | Burned : Tez_repr.t balance + | Commitments : Blinded_public_key_hash.t -> Tez_repr.t balance + | Bootstrap : Tez_repr.t balance + | Invoice : Tez_repr.t balance + | Initial_commitments : Tez_repr.t balance + | Minted : Tez_repr.t balance + | Frozen_bonds : Contract_repr.t * Bond_id_repr.t -> Tez_repr.t balance + | Sc_rollup_refutation_punishments : Tez_repr.t balance + | Sc_rollup_refutation_rewards : Tez_repr.t balance + | Staking_delegator_numerator : { + delegator : Contract_repr.t; + } + -> Staking_pseudotoken_repr.t balance + | Staking_delegate_denominator : { + delegate : Signature.public_key_hash; + } + -> Staking_pseudotoken_repr.t balance + +let token_of_balance : type token. token balance -> token Token.t = function + | Contract _ -> Token.Tez + | Block_fees -> Token.Tez + | Deposits _ -> Token.Tez + | Unstaked_deposits _ -> Token.Tez + | Nonce_revelation_rewards -> Token.Tez + | Attesting_rewards -> Token.Tez + | Baking_rewards -> Token.Tez + | Baking_bonuses -> Token.Tez + | Storage_fees -> Token.Tez + | Double_signing_punishments -> Token.Tez + | Lost_attesting_rewards _ -> Token.Tez + | Liquidity_baking_subsidies -> Token.Tez + | Burned -> Token.Tez + | Commitments _ -> Token.Tez + | Bootstrap -> Token.Tez + | Invoice -> Token.Tez + | Initial_commitments -> Token.Tez + | Minted -> Token.Tez + | Frozen_bonds _ -> Token.Tez + | Sc_rollup_refutation_punishments -> Token.Tez + | Sc_rollup_refutation_rewards -> Token.Tez + | Staking_delegator_numerator _ -> Token.Staking_pseudotoken + | Staking_delegate_denominator _ -> Token.Staking_pseudotoken + +let is_not_zero c = not (Compare.Int.equal c 0) + +let compare_balance : + type token1 token2. token1 balance -> token2 balance -> int = + fun ba bb -> + match (ba, bb) with + | Contract ca, Contract cb -> Contract_repr.compare ca cb + | Deposits sa, Deposits sb -> Frozen_staker_repr.compare sa sb + | Unstaked_deposits (sa, ca), Unstaked_deposits (sb, cb) -> + Compare.or_else (Unstaked_frozen_staker_repr.compare sa sb) (fun () -> + Cycle_repr.compare ca cb) + | Lost_attesting_rewards (pkha, pa, ra), Lost_attesting_rewards (pkhb, pb, rb) + -> + let c = Signature.Public_key_hash.compare pkha pkhb in + if is_not_zero c then c + else + let c = Compare.Bool.compare pa pb in + if is_not_zero c then c else Compare.Bool.compare ra rb + | Commitments bpkha, Commitments bpkhb -> + Blinded_public_key_hash.compare bpkha bpkhb + | Frozen_bonds (ca, ra), Frozen_bonds (cb, rb) -> + let c = Contract_repr.compare ca cb in + if is_not_zero c then c else Bond_id_repr.compare ra rb + | ( Staking_delegator_numerator {delegator = ca}, + Staking_delegator_numerator {delegator = cb} ) -> + Contract_repr.compare ca cb + | ( Staking_delegate_denominator {delegate = pkha}, + Staking_delegate_denominator {delegate = pkhb} ) -> + Signature.Public_key_hash.compare pkha pkhb + | _, _ -> + let index : type token. token balance -> int = function + | Contract _ -> 0 + | Block_fees -> 1 + | Deposits _ -> 2 + | Unstaked_deposits _ -> 3 + | Nonce_revelation_rewards -> 4 + | Attesting_rewards -> 5 + | Baking_rewards -> 6 + | Baking_bonuses -> 7 + | Storage_fees -> 8 + | Double_signing_punishments -> 9 + | Lost_attesting_rewards _ -> 10 + | Liquidity_baking_subsidies -> 11 + | Burned -> 12 + | Commitments _ -> 13 + | Bootstrap -> 14 + | Invoice -> 15 + | Initial_commitments -> 16 + | Minted -> 17 + | Frozen_bonds _ -> 18 + | Sc_rollup_refutation_punishments -> 19 + | Sc_rollup_refutation_rewards -> 20 + | Staking_delegator_numerator _ -> 21 + | Staking_delegate_denominator _ -> 22 + (* don't forget to add parameterized cases in the first part of the function *) + in + Compare.Int.compare (index ba) (index bb) + +type 'token balance_update = Debited of 'token | Credited of 'token + +type balance_and_update = + | Ex_token : 'token balance * 'token balance_update -> balance_and_update + +let is_zero_update : type token. token Token.t -> token balance_update -> bool = + fun token -> function Debited t | Credited t -> Token.is_zero token t + +let conv_balance_update encoding = + Data_encoding.conv + (function Credited v -> `Credited v | Debited v -> `Debited v) + (function `Credited v -> Credited v | `Debited v -> Debited v) + encoding + +let tez_balance_update_encoding = + let open Data_encoding in + def "operation_metadata.alpha.tez_balance_update" + @@ obj1 (req "change" (conv_balance_update Tez_repr.balance_update_encoding)) + +let staking_pseudotoken_balance_update_encoding = + let open Data_encoding in + def "operation_metadata.alpha.staking_abstract_quantity" + @@ obj1 + (req + "change" + (conv_balance_update Staking_pseudotoken_repr.balance_update_encoding)) + +let balance_and_update_encoding ~use_legacy_attestation_name = + let open Data_encoding in + let case = function + | Tag tag -> + (* The tag was used by old variant. It have been removed in + protocol proposal O, it can be unblocked in the future. *) + let tx_rollup_reserved_tag = [22; 23] in + assert ( + not @@ List.exists (Compare.Int.equal tag) tx_rollup_reserved_tag) ; + case (Tag tag) + | _ as c -> case c + in + let tez_case ~title tag enc (proj : Tez_repr.t balance -> _ option) inj = + case + ~title + tag + (merge_objs enc tez_balance_update_encoding) + (fun (Ex_token (balance, update)) -> + match token_of_balance balance with + | Tez -> proj balance |> Option.map (fun x -> (x, update)) + | _ -> None) + (fun (x, update) -> Ex_token (inj x, update)) + in + let staking_pseudotoken_case ~title tag enc + (proj : Staking_pseudotoken_repr.t balance -> _ option) inj = + case + ~title + tag + (merge_objs enc staking_pseudotoken_balance_update_encoding) + (fun (Ex_token (balance, update)) -> + match token_of_balance balance with + | Staking_pseudotoken -> + proj balance |> Option.map (fun x -> (x, update)) + | _ -> None) + (fun (x, update) -> Ex_token (inj x, update)) + in + def + (if use_legacy_attestation_name then + "operation_metadata_with_legacy_attestation_name.alpha.balance_and_update" + else "operation_metadata.alpha.balance_and_update") + @@ union + [ + tez_case + (Tag 0) + ~title:"Contract" + (obj2 + (req "kind" (constant "contract")) + (req "contract" Contract_repr.encoding)) + (function Contract c -> Some ((), c) | _ -> None) + (fun ((), c) -> Contract c); + tez_case + (Tag 2) + ~title:"Block_fees" + (obj2 + (req "kind" (constant "accumulator")) + (req "category" (constant "block fees"))) + (function Block_fees -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Block_fees); + tez_case + (Tag 4) + ~title:"Deposits" + (obj3 + (req "kind" (constant "freezer")) + (req "category" (constant "deposits")) + (req "staker" Frozen_staker_repr.encoding)) + (function Deposits staker -> Some ((), (), staker) | _ -> None) + (fun ((), (), staker) -> Deposits staker); + tez_case + (Tag 5) + ~title:"Nonce_revelation_rewards" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "nonce revelation rewards"))) + (function Nonce_revelation_rewards -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Nonce_revelation_rewards); + (* 6 was for Double_signing_evidence_rewards that has been removed. + https://gitlab.com/tezos/tezos/-/merge_requests/7758 *) + tez_case + (Tag 7) + ~title: + (if use_legacy_attestation_name then "Endorsing_rewards" + else "Attesting_rewards") + (obj2 + (req "kind" (constant "minted")) + (req + "category" + (constant + (if use_legacy_attestation_name then "endorsing rewards" + else "attesting rewards")))) + (function Attesting_rewards -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Attesting_rewards); + tez_case + (Tag 8) + ~title:"Baking_rewards" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "baking rewards"))) + (function Baking_rewards -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Baking_rewards); + tez_case + (Tag 9) + ~title:"Baking_bonuses" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "baking bonuses"))) + (function Baking_bonuses -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Baking_bonuses); + tez_case + (Tag 11) + ~title:"Storage_fees" + (obj2 + (req "kind" (constant "burned")) + (req "category" (constant "storage fees"))) + (function Storage_fees -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Storage_fees); + tez_case + (Tag 12) + ~title:"Double_signing_punishments" + (obj2 + (req "kind" (constant "burned")) + (req "category" (constant "punishments"))) + (function Double_signing_punishments -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Double_signing_punishments); + tez_case + (Tag 13) + ~title: + (if use_legacy_attestation_name then "Lost_endorsing_rewards" + else "Lost_attesting_rewards") + (obj5 + (req "kind" (constant "burned")) + (req + "category" + (constant + (if use_legacy_attestation_name then + "lost endorsing rewards" + else "lost attesting rewards"))) + (req "delegate" Signature.Public_key_hash.encoding) + (req "participation" Data_encoding.bool) + (req "revelation" Data_encoding.bool)) + (function + | Lost_attesting_rewards (d, p, r) -> Some ((), (), d, p, r) + | _ -> None) + (fun ((), (), d, p, r) -> Lost_attesting_rewards (d, p, r)); + tez_case + (Tag 14) + ~title:"Liquidity_baking_subsidies" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "subsidy"))) + (function Liquidity_baking_subsidies -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Liquidity_baking_subsidies); + tez_case + (Tag 15) + ~title:"Burned" + (obj2 + (req "kind" (constant "burned")) + (req "category" (constant "burned"))) + (function Burned -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Burned); + tez_case + (Tag 16) + ~title:"Commitments" + (obj3 + (req "kind" (constant "commitment")) + (req "category" (constant "commitment")) + (req "committer" Blinded_public_key_hash.encoding)) + (function Commitments bpkh -> Some ((), (), bpkh) | _ -> None) + (fun ((), (), bpkh) -> Commitments bpkh); + tez_case + (Tag 17) + ~title:"Bootstrap" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "bootstrap"))) + (function Bootstrap -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Bootstrap); + tez_case + (Tag 18) + ~title:"Invoice" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "invoice"))) + (function Invoice -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Invoice); + tez_case + (Tag 19) + ~title:"Initial_commitments" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "commitment"))) + (function Initial_commitments -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Initial_commitments); + tez_case + (Tag 20) + ~title:"Minted" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "minted"))) + (function Minted -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Minted); + tez_case + (Tag 21) + ~title:"Frozen_bonds" + (obj4 + (req "kind" (constant "freezer")) + (req "category" (constant "bonds")) + (req "contract" Contract_repr.encoding) + (req "bond_id" Bond_id_repr.encoding)) + (function Frozen_bonds (c, r) -> Some ((), (), c, r) | _ -> None) + (fun ((), (), c, r) -> Frozen_bonds (c, r)); + tez_case + (Tag 24) + ~title:"Smart_rollup_refutation_punishments" + (obj2 + (req "kind" (constant "burned")) + (req "category" (constant "smart_rollup_refutation_punishments"))) + (function + | Sc_rollup_refutation_punishments -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Sc_rollup_refutation_punishments); + tez_case + (Tag 25) + ~title:"Smart_rollup_refutation_rewards" + (obj2 + (req "kind" (constant "minted")) + (req "category" (constant "smart_rollup_refutation_rewards"))) + (function + | Sc_rollup_refutation_rewards -> Some ((), ()) | _ -> None) + (fun ((), ()) -> Sc_rollup_refutation_rewards); + tez_case + (Tag 26) + ~title:"Unstaked_deposits" + (obj4 + (req "kind" (constant "freezer")) + (req "category" (constant "unstaked_deposits")) + (req "staker" Unstaked_frozen_staker_repr.encoding) + (req "cycle" Cycle_repr.encoding)) + (function + | Unstaked_deposits (staker, cycle) -> Some ((), (), staker, cycle) + | _ -> None) + (fun ((), (), staker, cycle) -> Unstaked_deposits (staker, cycle)); + staking_pseudotoken_case + (Tag 27) + ~title:"Staking_delegator_numerator" + (obj3 + (req "kind" (constant "staking")) + (req "category" (constant "delegator_numerator")) + (req "delegator" Contract_repr.encoding)) + (function + | Staking_delegator_numerator {delegator} -> + Some ((), (), delegator) + | _ -> None) + (fun ((), (), delegator) -> Staking_delegator_numerator {delegator}); + staking_pseudotoken_case + (Tag 28) + ~title:"Staking_delegate_denominator" + (obj3 + (req "kind" (constant "staking")) + (req "category" (constant "delegate_denominator")) + (req "delegate" Signature.Public_key_hash.encoding)) + (function + | Staking_delegate_denominator {delegate} -> Some ((), (), delegate) + | _ -> None) + (fun ((), (), delegate) -> Staking_delegate_denominator {delegate}); + ] + +let balance_and_update_encoding_with_legacy_attestation_name = + balance_and_update_encoding ~use_legacy_attestation_name:true + +let balance_and_update_encoding = + balance_and_update_encoding ~use_legacy_attestation_name:false + +type update_origin = + | Block_application + | Protocol_migration + | Subsidy + | Simulation + | Delayed_operation of {operation_hash : Operation_hash.t} + +let compare_update_origin oa ob = + match (oa, ob) with + | ( Delayed_operation {operation_hash = oha}, + Delayed_operation {operation_hash = ohb} ) -> + Operation_hash.compare oha ohb + | _, _ -> + let index o = + match o with + | Block_application -> 0 + | Protocol_migration -> 1 + | Subsidy -> 2 + | Simulation -> 3 + | Delayed_operation _ -> 4 + (* don't forget to add parameterized cases in the first part of the function *) + in + Compare.Int.compare (index oa) (index ob) + +let update_origin_encoding = + let open Data_encoding in + def "operation_metadata.alpha.update_origin" + @@ union + [ + case + (Tag 0) + ~title:"Block_application" + (obj1 (req "origin" (constant "block"))) + (function Block_application -> Some () | _ -> None) + (fun () -> Block_application); + case + (Tag 1) + ~title:"Protocol_migration" + (obj1 (req "origin" (constant "migration"))) + (function Protocol_migration -> Some () | _ -> None) + (fun () -> Protocol_migration); + case + (Tag 2) + ~title:"Subsidy" + (obj1 (req "origin" (constant "subsidy"))) + (function Subsidy -> Some () | _ -> None) + (fun () -> Subsidy); + case + (Tag 3) + ~title:"Simulation" + (obj1 (req "origin" (constant "simulation"))) + (function Simulation -> Some () | _ -> None) + (fun () -> Simulation); + case + (Tag 4) + ~title:"Delayed_operation" + (obj2 + (req "origin" (constant "delayed_operation")) + (req "delayed_operation_hash" Operation_hash.encoding)) + (function + | Delayed_operation {operation_hash} -> Some ((), operation_hash) + | _ -> None) + (fun ((), operation_hash) -> Delayed_operation {operation_hash}); + ] + +type balance_update_item = + | Balance_update_item : + 'token balance * 'token balance_update * update_origin + -> balance_update_item + +let item balance balance_update update_origin = + Balance_update_item (balance, balance_update, update_origin) + +let item_encoding_with_legacy_attestation_name = + let open Data_encoding in + conv + (function + | Balance_update_item (balance, balance_update, update_origin) -> + (Ex_token (balance, balance_update), update_origin)) + (fun (Ex_token (balance, balance_update), update_origin) -> + Balance_update_item (balance, balance_update, update_origin)) + (merge_objs + balance_and_update_encoding_with_legacy_attestation_name + update_origin_encoding) + +let item_encoding = + let open Data_encoding in + conv + (function + | Balance_update_item (balance, balance_update, update_origin) -> + (Ex_token (balance, balance_update), update_origin)) + (fun (Ex_token (balance, balance_update), update_origin) -> + Balance_update_item (balance, balance_update, update_origin)) + (merge_objs balance_and_update_encoding update_origin_encoding) + +type balance_updates = balance_update_item list + +let balance_updates_encoding_with_legacy_attestation_name = + let open Data_encoding in + def "operation_metadata_with_legacy_attestation_name.alpha.balance_updates" + @@ list item_encoding_with_legacy_attestation_name + +let balance_updates_encoding = + let open Data_encoding in + def "operation_metadata.alpha.balance_updates" @@ list item_encoding + +module MakeBalanceMap (T : sig + type token +end) = +struct + include Map.Make (struct + type t = T.token balance * update_origin + + let compare (ba, ua) (bb, ub) = + let c = compare_balance ba bb in + if is_not_zero c then c else compare_update_origin ua ub + end) + + let update_r key (f : 'a option -> 'b option tzresult) map = + let open Result_syntax in + let* v_opt = f (find key map) in + match v_opt with + | Some v -> return (add key v map) + | None -> return (remove key map) +end + +module TezBalanceMap = MakeBalanceMap (struct + type token = Tez_repr.t +end) + +module StakingPseudotokenMap = MakeBalanceMap (struct + type token = Staking_pseudotoken_repr.t +end) + +type 'a balance_maps = { + tez : Tez_repr.t balance_update TezBalanceMap.t; + staking_pt : Staking_pseudotoken_repr.t balance_update StakingPseudotokenMap.t; +} + +let group_balance_updates balance_updates = + let open Result_syntax in + let update_map token update_r key update map = + update_r + key + (function + | None -> return_some update + | Some balance -> ( + match (balance, update) with + | Credited a, Debited b | Debited b, Credited a -> + (* Remove the binding since it just fell down to zero *) + if Token.equal token a b then return_none + else if Token.le token b a then + let* update = Token.sub token a b in + return_some (Credited update) + else + let* update = Token.sub token b a in + return_some (Debited update) + | Credited a, Credited b -> + let* update = Token.add token a b in + return_some (Credited update) + | Debited a, Debited b -> + let* update = Token.add token a b in + return_some (Debited update))) + map + in + let* {tez; staking_pt} = + List.fold_left_e + (fun acc (Balance_update_item (b, update, o)) -> + (* Do not do anything if the update is zero *) + let token = token_of_balance b in + if is_zero_update token update then return acc + else + match token with + | Tez -> + let+ tez = + update_map token TezBalanceMap.update_r (b, o) update acc.tez + in + {acc with tez} + | Staking_pseudotoken -> + let+ staking_pt = + update_map + token + StakingPseudotokenMap.update_r + (b, o) + update + acc.staking_pt + in + {acc with staking_pt}) + {tez = TezBalanceMap.empty; staking_pt = StakingPseudotokenMap.empty} + balance_updates + in + return + (StakingPseudotokenMap.fold + (fun (b, o) u acc -> Balance_update_item (b, u, o) :: acc) + staking_pt + (TezBalanceMap.fold + (fun (b, o) u acc -> Balance_update_item (b, u, o) :: acc) + tez + [])) diff --git a/src/proto_020_PsParisC/lib_protocol/receipt_repr.mli b/src/proto_020_PsParisC/lib_protocol/receipt_repr.mli new file mode 100644 index 000000000000..e78286e144aa --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/receipt_repr.mli @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Token : sig + type 'token t = + | Tez : Tez_repr.t t + | Staking_pseudotoken : Staking_pseudotoken_repr.t t + + val eq : + 'token1 t -> 'token2 t -> ('token1, 'token2) Equality_witness.eq option + + val equal : 'token t -> 'token -> 'token -> bool + + val is_zero : 'token t -> 'token -> bool + + val add : 'token t -> 'token -> 'token -> 'token tzresult + + val pp : 'token t -> Format.formatter -> 'token -> unit +end + +(** Places where tokens can be found in the ledger's state. *) +type 'token balance = + | Contract : Contract_repr.t -> Tez_repr.t balance + | Block_fees : Tez_repr.t balance + | Deposits : Frozen_staker_repr.t -> Tez_repr.t balance + | Unstaked_deposits : + Unstaked_frozen_staker_repr.t * Cycle_repr.t + -> Tez_repr.t balance + | Nonce_revelation_rewards : Tez_repr.t balance + | Attesting_rewards : Tez_repr.t balance + | Baking_rewards : Tez_repr.t balance + | Baking_bonuses : Tez_repr.t balance + | Storage_fees : Tez_repr.t balance + | Double_signing_punishments : Tez_repr.t balance + | Lost_attesting_rewards : + Signature.Public_key_hash.t * bool * bool + -> Tez_repr.t balance + | Liquidity_baking_subsidies : Tez_repr.t balance + | Burned : Tez_repr.t balance + | Commitments : Blinded_public_key_hash.t -> Tez_repr.t balance + | Bootstrap : Tez_repr.t balance + | Invoice : Tez_repr.t balance + | Initial_commitments : Tez_repr.t balance + | Minted : Tez_repr.t balance + | Frozen_bonds : Contract_repr.t * Bond_id_repr.t -> Tez_repr.t balance + | Sc_rollup_refutation_punishments : Tez_repr.t balance + | Sc_rollup_refutation_rewards : Tez_repr.t balance + | Staking_delegator_numerator : { + delegator : Contract_repr.t; + } + -> Staking_pseudotoken_repr.t balance + | Staking_delegate_denominator : { + delegate : Signature.public_key_hash; + } + -> Staking_pseudotoken_repr.t balance + +val token_of_balance : 'token balance -> 'token Token.t + +(** Compares two balances. *) +val compare_balance : 'token1 balance -> 'token2 balance -> int + +(** A credit or debit of token to a balance. *) +type 'token balance_update = Debited of 'token | Credited of 'token + +(** An origin of a balance update *) +type update_origin = + | Block_application (** Update from a block application *) + | Protocol_migration (** Update from a protocol migration *) + | Subsidy (** Update from an inflationary subsidy *) + | Simulation (** Simulation of an operation **) + | Delayed_operation of {operation_hash : Operation_hash.t} + (** Delayed application of an operation, whose hash is given. E.g. for + operations that take effect only at the end of the cycle. *) + +(** Compares two origins. *) +val compare_update_origin : update_origin -> update_origin -> int + +(** An item in a list of balance updates. + An item of the form [(Rewards (b,c), Credited am, ...)] indicates that the + balance of frozen rewards has been increased by [am] for baker [b] and cycle + [c]. *) +type balance_update_item = private + | Balance_update_item : + 'token balance * 'token balance_update * update_origin + -> balance_update_item + +(** Smart constructor for [balance_update_item]. *) +val item : + 'token balance -> + 'token balance_update -> + update_origin -> + balance_update_item + +(** A list of balance updates. Duplicates may happen. *) +type balance_updates = balance_update_item list + +(** The property [Json.destruct (Json.construct balance_updates) = balance_updates] + does not always hold for [balance_updates_encoding] when [balance_updates] + contains entries of the form [(_, _ Tez_repr.zero, _)]. This is because the + [balance_update] [(_ Tez_repr.zero)] always decodes into [(Credited Tez_repr.zero)]. *) +val balance_updates_encoding : balance_updates Data_encoding.t + +(** Balance updates encoding that uses legacy attestation name : `endorsing + right` and `lost endorsing right` when encoding to JSON + + https://gitlab.com/tezos/tezos/-/issues/5529 + + This encoding is temporary and should be removed when the endorsements kinds + in JSON will not be accepted any more by the protocol. +*) +val balance_updates_encoding_with_legacy_attestation_name : + balance_updates Data_encoding.t + +(** Group updates by (balance x origin), and remove zero-valued balances. *) +val group_balance_updates : balance_updates -> balance_updates tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/round_repr.ml b/src/proto_020_PsParisC/lib_protocol/round_repr.ml new file mode 100644 index 000000000000..bebf5c459088 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/round_repr.ml @@ -0,0 +1,531 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type round = int32 + +type t = round + +module Map = Map.Make (Int32) + +include (Compare.Int32 : Compare.S with type t := t) + +let zero = 0l + +let succ n = + if Compare.Int32.equal n Int32.max_int then + invalid_arg "round_repr.succ: cannot apply succ to maximum round value" + else Int32.succ n + +let pp fmt i = Format.fprintf fmt "%ld" i + +type error += Negative_round of int + +type error += Round_overflow of int + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"negative_round" + ~title:"Negative round" + ~description:"Round cannot be built out of negative integers." + ~pp:(fun ppf i -> + Format.fprintf + ppf + "Negative round cannot be built out of negative integers (%Ld)" + i) + (obj1 (req "Negative_round" int64)) + (function Negative_round i -> Some (Int64.of_int i) | _ -> None) + (fun i -> Negative_round (Int64.to_int i)) ; + register_error_kind + `Permanent + ~id:"round_overflow" + ~title:"Round overflow" + ~description: + "Round cannot be built out of integer greater than maximum int32 value." + ~pp:(fun ppf i -> + Format.fprintf + ppf + "Round cannot be built out of integer greater than maximum int32 value \ + (%Ld)" + i) + (obj1 (req "Round_overflow" int64)) + (function Round_overflow i -> Some (Int64.of_int i) | _ -> None) + (fun i -> Round_overflow (Int64.to_int i)) + +let of_int32 i = + let open Result_syntax in + if i >= 0l then return i else tzfail (Negative_round (Int32.to_int i)) + [@@inline] + +let pred r = + let p = Int32.pred r in + of_int32 p + +let of_int i = + let open Result_syntax in + if Compare.Int.(i < 0) then tzfail (Negative_round i) + else + (* i is positive *) + let i32 = Int32.of_int i in + if Compare.Int.(Int32.to_int i32 = i) then Ok i32 + else tzfail (Round_overflow i) + +let to_int i32 = + let open Result_syntax in + let i = Int32.to_int i32 in + if Int32.(equal (of_int i) i32) then return i else tzfail (Round_overflow i) + +let to_int32 t = t [@@inline] + +let to_slot round ~committee_size = + let open Result_syntax in + let* r = to_int round in + let slot = r mod committee_size in + Slot_repr.of_int slot + +let encoding = + Data_encoding.conv_with_guard + (fun i -> i) + (fun i -> + match of_int32 i with + | Ok _ as res -> res + | Error _ -> Error "Round_repr.encoding: negative round") + Data_encoding.int32 + +module Durations = struct + type t = { + first_round_duration : Period_repr.t; + delay_increment_per_round : Period_repr.t; + } + + type error += + | Non_increasing_rounds of {increment : Period_repr.t} + | Round_durations_must_be_at_least_one_second of {round : Period_repr.t} + + let () = + register_error_kind + `Permanent + ~id:"durations.non_increasing_rounds" + ~title:"Non increasing round" + ~description:"The provided rounds are not increasing." + ~pp:(fun ppf increment -> + Format.fprintf + ppf + "The provided rounds are not increasing (increment: %a)" + Period_repr.pp + increment) + Data_encoding.(obj1 (req "increment" Period_repr.encoding)) + (function + | Non_increasing_rounds {increment} -> Some increment | _ -> None) + (fun increment -> Non_increasing_rounds {increment}) + + let pp fmt t = + Format.fprintf + fmt + "%a,@ +%a" + Period_repr.pp + t.first_round_duration + Period_repr.pp + t.delay_increment_per_round + + let create ~first_round_duration ~delay_increment_per_round = + let open Result_syntax in + let* () = + error_when + Compare.Int64.(Period_repr.to_seconds first_round_duration < 1L) + (Round_durations_must_be_at_least_one_second + {round = first_round_duration}) + in + let* () = + error_when + Compare.Int64.(Period_repr.to_seconds delay_increment_per_round < 1L) + (Non_increasing_rounds {increment = delay_increment_per_round}) + in + return {first_round_duration; delay_increment_per_round} + + let create_opt ~first_round_duration ~delay_increment_per_round = + match create ~first_round_duration ~delay_increment_per_round with + | Ok v -> Some v + | Error _ -> None + + let encoding = + let open Data_encoding in + conv_with_guard + (fun {first_round_duration; delay_increment_per_round} -> + (first_round_duration, delay_increment_per_round)) + (fun (first_round_duration, delay_increment_per_round) -> + match create_opt ~first_round_duration ~delay_increment_per_round with + | None -> + Error + "Either round durations are non-increasing or minimal block \ + delay < 1" + | Some rounds -> Ok rounds) + (obj2 + (req "first_round_duration" Period_repr.encoding) + (req "delay_increment_per_round" Period_repr.encoding)) + + let round_duration {first_round_duration; delay_increment_per_round} round = + if Compare.Int32.(round < 0l) then + invalid_arg "round must be a non-negative integer" + else + let first_round_duration_s = Period_repr.to_seconds first_round_duration + and delay_increment_per_round_s = + Period_repr.to_seconds delay_increment_per_round + in + Period_repr.of_seconds_exn + Int64.( + add + first_round_duration_s + (mul (of_int32 round) delay_increment_per_round_s)) +end + +type error += Round_too_high of int32 + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"round_too_high" + ~title:"round too high" + ~description:"block round too high." + ~pp:(fun ppf round -> + Format.fprintf ppf "Block round is too high: %ld" round) + (obj1 (req "level_offset_too_high" int32)) + (function Round_too_high round -> Some round | _ -> None) + (fun round -> Round_too_high round) + +(* The duration of round n follows the arithmetic sequence: + + round_duration(0) = first_round_duration + round_duration(r+1) = round_duration(r) + delay_increment_per_round + + Hence, this sequence can be explicited into: + + round_duration(r) = first_round_duration + r * delay_increment_per_round + + The level offset of round r is the sum of the durations of the rounds up + until round r - 1. In other words, when r > 0 + + raw_level_offset_of_round(0) = 0 + raw_level_offset_of_round(r+1) = + raw_level_offset_of_round(r) + round_duration(r) + + Hence + + raw_level_offset_of_round(r) = Σ_{k=0}^{r-1} (round_duration(k)) + + After unfolding the series, the same function can be finally explicited into + + raw_level_offset_of_round(0) = 0 + raw_level_offset_of_round(r) = r * first_round_duration + + 1/2 * r * (r - 1) * delay_increment_per_round +*) +let raw_level_offset_of_round round_durations ~round = + let open Result_syntax in + if Compare.Int32.(round = zero) then return Int64.zero + else + let sum_durations = + let Durations.{first_round_duration; delay_increment_per_round} = + round_durations + in + let roundz = Int64.of_int32 round in + let m = Z.of_int64 Int64.(div (mul roundz (pred roundz)) 2L) in + Z.( + add + (mul + m + (Z.of_int64 @@ Period_repr.to_seconds delay_increment_per_round)) + (mul + (Z.of_int32 round) + (Z.of_int64 @@ Period_repr.to_seconds first_round_duration))) + in + if Z.fits_int64 sum_durations then return (Z.to_int64 sum_durations) + else tzfail (Round_too_high round) + +type error += Level_offset_too_high of Period_repr.t + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"level_offset_too_high" + ~title:"level offset too high" + ~description:"The block's level offset is too high." + ~pp:(fun ppf offset -> + Format.fprintf + ppf + "The block's level offset is too high: %a" + Period_repr.pp + offset) + (obj1 (req "level_offset_too_high" Period_repr.encoding)) + (function Level_offset_too_high offset -> Some offset | _ -> None) + (fun offset -> Level_offset_too_high offset) + +type round_and_offset = {round : int32; offset : Period_repr.t} + +(** Complexity: O(log level_offset). *) +let round_and_offset round_durations ~level_offset = + let open Result_syntax in + let level_offset_in_seconds = Period_repr.to_seconds level_offset in + (* We set the bound as 2^53 to prevent overflows when computing the + variable [discr] for reasonable values of [first_round_duration] and + [delay_increment_per_round]. This bound is derived by a rough approximation + from the inequation [discr] < Int64.max_int. *) + let overflow_bound = Int64.shift_right Int64.max_int 10 in + if Compare.Int64.(overflow_bound < level_offset_in_seconds) then + tzfail (Level_offset_too_high level_offset) + else + let Durations.{first_round_duration; delay_increment_per_round} = + round_durations + in + let first_round_duration = Period_repr.to_seconds first_round_duration in + let delay_increment_per_round = + Period_repr.to_seconds delay_increment_per_round + in + (* If [level_offset] is lower than the first round duration, then + the solution straightforward. *) + if Compare.Int64.(level_offset_in_seconds < first_round_duration) then + return {round = 0l; offset = level_offset} + else + let round = + if Compare.Int64.(delay_increment_per_round = Int64.zero) then + (* Case when delay_increment_per_round is zero and a simple + linear solution exists. *) + Int64.div level_offset_in_seconds first_round_duration + else + (* Case when the increment is non-negative and we look for the + quadratic solution. *) + let pow_2 n = Int64.mul n n in + let double n = Int64.shift_left n 1 in + let times_8 n = Int64.shift_left n 3 in + let half n = Int64.shift_right n 1 in + (* The integer square root is implemented using the Newton-Raphson + method. For any integer N, the convergence within the + neighborhood of √N is ensured within log2 (N) steps. *) + let sqrt (n : int64) = + let x0 = ref (half n) in + if Compare.Int64.(!x0 > 1L) then ( + let x1 = ref (half (Int64.add !x0 (Int64.div n !x0))) in + while Compare.Int64.(!x1 < !x0) do + x0 := !x1 ; + x1 := half (Int64.add !x0 (Int64.div n !x0)) + done ; + !x0) + else n + in + (* The idea is to solve the following equation in [round] and + use its integer value: + + Σ_{k=0}^{round-1} round_duration(k) = level_offset + + After unfolding the sum and expanding terms, we obtain a + quadratic equation: + + delay_increment_per_round × round² + + (2 first_round_duration - delay_increment_per_round) × round + - 2 level_offset + = 0 + + From there, we compute the discriminant and the solution of + the equation. + + Refer to https://gitlab.com/tezos/tezos/-/merge_requests/4009 + for more explanations. + *) + let discr = + Int64.add + (pow_2 + (Int64.sub + (double first_round_duration) + delay_increment_per_round)) + (times_8 + (Int64.mul delay_increment_per_round level_offset_in_seconds)) + in + Int64.div + (Int64.add + (Int64.sub + delay_increment_per_round + (double first_round_duration)) + (sqrt discr)) + (double delay_increment_per_round) + in + let* current_level_offset = + raw_level_offset_of_round round_durations ~round:(Int64.to_int32 round) + in + return + { + round = Int64.to_int32 round; + offset = + Period_repr.of_seconds_exn + (Int64.sub + (Period_repr.to_seconds level_offset) + current_level_offset); + } + +(** Complexity: O(|round_durations|). *) +let timestamp_of_round round_durations ~predecessor_timestamp ~predecessor_round + ~round = + let open Result_syntax in + let pred_round_duration = + Durations.round_duration round_durations predecessor_round + in + (* First, the function computes when the current level l is supposed + to start. This is given by adding to the timestamp of the round + of predecessor level l-1 [predecessor_timestamp], the duration of + its last round [predecessor_round]. *) + let* start_of_current_level = + Time_repr.(predecessor_timestamp +? pred_round_duration) + in + (* Finally, we sum the durations of the rounds at the current level l until + reaching current [round]. *) + let* level_offset = raw_level_offset_of_round round_durations ~round in + let level_offset = Period_repr.of_seconds_exn level_offset in + Time_repr.(start_of_current_level +? level_offset) + +(** Unlike [timestamp_of_round], this function gets the starting time + of a given round, given the timestamp and the round of a proposal + at the same level. + + We compute the starting time of [considered_round] from a given + [round_durations] description, some [current_round], and its + starting time [current_timestamp]. + + Complexity: O(|round_durations|). *) +let timestamp_of_another_round_same_level round_durations ~current_timestamp + ~current_round ~considered_round = + let open Result_syntax in + let* target_offset = + raw_level_offset_of_round round_durations ~round:considered_round + in + let* current_offset = + raw_level_offset_of_round round_durations ~round:current_round + in + return + @@ Time_repr.of_seconds + Int64.( + add + (sub (Time_repr.to_seconds current_timestamp) current_offset) + target_offset) + +type error += + | Round_of_past_timestamp of { + provided_timestamp : Time.t; + predecessor_timestamp : Time.t; + predecessor_round : t; + } + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"round_of_past_timestamp" + ~title:"Round_of_timestamp for past timestamp" + ~description:"Provided timestamp is before the expected level start." + ~pp:(fun ppf (provided_ts, predecessor_ts, round) -> + Format.fprintf + ppf + "Provided timestamp (%a) is before the expected level start (computed \ + based on predecessor_ts %a at round %a)." + Time.pp_hum + provided_ts + Time.pp_hum + predecessor_ts + pp + round) + (obj3 + (req "provided_timestamp" Time.encoding) + (req "predecessor_timestamp" Time.encoding) + (req "predecessor_round" encoding)) + (function + | Round_of_past_timestamp + {provided_timestamp; predecessor_timestamp; predecessor_round} -> + Some (provided_timestamp, predecessor_timestamp, predecessor_round) + | _ -> None) + (fun (provided_timestamp, predecessor_timestamp, predecessor_round) -> + Round_of_past_timestamp + {provided_timestamp; predecessor_timestamp; predecessor_round}) + +let round_of_timestamp round_durations ~predecessor_timestamp ~predecessor_round + ~timestamp = + let open Result_syntax in + let round_duration = + Durations.round_duration round_durations predecessor_round + in + let* start_of_current_level = + Time_repr.(predecessor_timestamp +? round_duration) + in + let* diff = + Period_repr.of_seconds (Time_repr.diff timestamp start_of_current_level) + |> Error_monad.record_trace + (Round_of_past_timestamp + { + predecessor_timestamp; + provided_timestamp = timestamp; + predecessor_round; + }) + in + let* round_and_offset = round_and_offset round_durations ~level_offset:diff in + return round_and_offset.round + +let level_offset_of_round round_durations ~round = + let open Result_syntax in + let* offset = raw_level_offset_of_round round_durations ~round in + return (Period_repr.of_seconds_exn offset) + +module Index = struct + type t = round + + let path_length = 1 + + let to_path round l = Int32.to_string round :: l + + let of_path = function [s] -> Int32.of_string_opt s | _ -> None + + let rpc_arg = + let construct round = Int32.to_string round in + let destruct str = + Int32.of_string_opt str |> Option.to_result ~none:"Cannot parse round" + in + RPC_arg.make + ~descr:"A round integer" + ~name:"block_round" + ~construct + ~destruct + () + + let encoding = encoding + + let compare = compare +end + +module Internal_for_tests = struct + type round_and_offset_raw = {round : round; offset : Period_repr.t} + + let round_and_offset round_durations ~level_offset = + let open Result_syntax in + let+ v = round_and_offset round_durations ~level_offset in + {round = v.round; offset = v.offset} +end diff --git a/src/proto_020_PsParisC/lib_protocol/round_repr.mli b/src/proto_020_PsParisC/lib_protocol/round_repr.mli new file mode 100644 index 000000000000..3adef4ec00c4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/round_repr.mli @@ -0,0 +1,249 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A round represents an iteration of the single-shot consensus algorithm. + + Rounds can be seen as an infinite, 0-indexed, list of durations. The + durations are generated by an arithmetic progression depending on + {!val:Constants_repr.minimal_block_delay} (its initial value, a.k.a the one for + round 0) and {!val:Constants_repr.delay_increment_per_round} (its common + difference) . + + Round identifiers are non-negative 32 bit integers. This interface ensures + that no negative round can be created. *) + +type round + +type t = round + +(** Round zero *) +val zero : t + +(** Successor of the given round. + + @raise Invalid_arg if applied to the upper bound of the round integer + representation. *) +val succ : t -> t + +(** Predecessor of the given round. + Returns an error if applied to [zero], as negative round are + prohibited. *) +val pred : t -> t tzresult + +(** Building a round from an int32. + Returns an error if applied to a negative number. *) +val of_int32 : int32 -> t tzresult + +val to_int32 : t -> int32 + +(** Building a round from an int. + Returns an error if applied to a negative number or a number + greater than Int32.max_int. *) +val of_int : int -> t tzresult + +(** Building an int from a round. + Returns an error if the value does not fit in max_int. (current + 32bit encodings always fit in int on 64bit architecture though). *) +val to_int : t -> int tzresult + +(** Returns the slot corresponding to the given round [r], that is [r + mod committee_size]. *) +val to_slot : t -> committee_size:int -> Slot_repr.t tzresult + +(** Round encoding. + Be aware that decoding a negative 32 bit integer would lead to an + exception. *) +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +include Compare.S with type t := t + +module Map : Map.S with type key = t + +(** {2 Round duration representation} *) + +module Durations : sig + (** [round_durations] represents the duration of rounds in seconds *) + type t + + val pp : Format.formatter -> t -> unit + + (** {3 Creation functions} *) + + (** [create ~first_round_duration ~delay_increment_per_round] creates a valid + duration value + + @param first_round_duration duration of round 0 + @param delay_increment_per_round amount of time added in from one round + duration to the duration of its next round + @raise Invalid_argument if + - first_round_duration <= 1; or + - delay_increment_per_round is <= 0 + *) + val create : + first_round_duration:Period_repr.t -> + delay_increment_per_round:Period_repr.t -> + t tzresult + + (** [create_opt ~first_round_duration ~delay_increment_per_round] returns a valid duration value + [Some d] when [create ~first_round_duration ~delay_increment_per_round] + does not fail. It returns [None] otherwise. *) + val create_opt : + first_round_duration:Period_repr.t -> + delay_increment_per_round:Period_repr.t -> + t option + + (** {b Warning} May trigger an exception when the expected invariant + does not hold. *) + val encoding : t Data_encoding.encoding + + (** {3 Accessors}*) + + (** [round_duration round_durations ~round] returns the duration of round + [~round]. This duration follows the arithmetic progression + + duration(round_n) = [first_round_duration] + round_n * [delay_increment_per_round] + + *) + val round_duration : t -> round -> Period_repr.t +end + +(** [level_offset_of_round round_durations ~round:r] represents the offset of the + starting time of round [r] with respect to the start of the level. + round = 0 1 2 3 r + + |-----|-----|-----|-----|-----|--- ... ... --|------|------- + | + <-------------------------------------------> + level_offset +*) +val level_offset_of_round : Durations.t -> round:t -> Period_repr.t tzresult + +(** [timestamp_of_round round_durations ~predecessor_timestamp:pred_ts + ~predecessor_round:pred_round ~round] returns the + starting time of round [round] given that the timestamp and the round of + the block at the previous level is [pred_ts] and [pred_round], + respectively. + + pred_round = 0 pred_round + + |-----|.. ... --|--------|-- ... --|------- + | | + | | + pred_ts | + | + start_of_cur_level + | + | + |-----|------|-- ... --|-------|- + cur_round = 0 1 | round + | + res_ts + + Precisely, the resulting timestamp is: + [pred_ts + round_duration(pred_round) + level_offset_of_round(round)]. +*) +val timestamp_of_round : + Durations.t -> + predecessor_timestamp:Time_repr.t -> + predecessor_round:t -> + round:t -> + Time_repr.t tzresult + +(** [timestamp_of_another_round_same_level + round_durations + ~current_timestamp + ~current_round + ~considered_round] + returns the starting time of round [considered_round]. + + start of current + level current ts result + | | | + | | | + |-----|----...--|-- ... ------|- + | | | | + cur_round = 0 1 current considered + round round + + It also works when [considered_round] is lower than [current_round]. + + Precisely, the resulting timestamp is: + [current_timestamp - level_offset_of_round(current_round) + + level_offset_of_round(considered_round)]. +*) +val timestamp_of_another_round_same_level : + Durations.t -> + current_timestamp:Time_repr.t -> + current_round:t -> + considered_round:t -> + Time_repr.t tzresult + +(** [round_of_timestamp round_durations ~predecessor_timestamp ~predecessor_round + ~timestamp:ts] returns the round to which the timestamp [ts] belongs to, + given that the timestamp and the round of the block at the previous level is + [pred_ts] and [pred_round], respectively. + + Precisely, the resulting round is: + [round_and_offset round_durations ~level_offset:diff] where + [diff = ts - (predecessor_timestamp + round_duration(predecessor_round)]. + + Returns an error when the timestamp is before the level start. Also + returns an error when the timestamp is so high that it would lead + to an integer overflow when computing the round. *) +val round_of_timestamp : + Durations.t -> + predecessor_timestamp:Time_repr.t -> + predecessor_round:t -> + timestamp:Time_repr.t -> + t tzresult + +module Index : Storage_description.INDEX with type t = round + +module Internal_for_tests : sig + type round_and_offset_raw = {round : round; offset : Period_repr.t} + + (** [round_and_offset round_durations ~level_offset], where [level_offset] + represents a time offset with respect to the start of the first round, + returns a tuple [(r, round_offset)] where the round [r] is such that + [level_offset_of_round(r) <= level_offset < level_offset_of_round(r+1)] and + [round_offset := level_offset - level_offset_of_round(r)]. + + round = 0 1 2 3 r + + |-----|-----|-----|-----|-----|--- ... ... --|--------|-- ... --|------- + | + round_delay(r) + | + | + <-----> + round_offset + <---------------------------------------------------> + level_offset +*) + val round_and_offset : + Durations.t -> level_offset:Period_repr.t -> round_and_offset_raw tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/sampler.ml b/src/proto_020_PsParisC/lib_protocol/sampler.ml new file mode 100644 index 000000000000..34eb5adda73b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sampler.ml @@ -0,0 +1,219 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + + This module implements the alias method for sampling from a given + distribution. The distribution need not be normalized. + +*) + +module type SMass = sig + type t + + val encoding : t Data_encoding.t + + val zero : t + + val of_int : int -> t + + val mul : t -> t -> t + + val add : t -> t -> t + + val sub : t -> t -> t + + val ( = ) : t -> t -> bool + + val ( <= ) : t -> t -> bool + + val ( < ) : t -> t -> bool +end + +module type S = sig + type mass + + type 'a t + + val create : ('a * mass) list -> 'a t + + val sample : 'a t -> (int_bound:int -> mass_bound:mass -> int * mass) -> 'a + + val encoding : 'a Data_encoding.t -> 'a t Data_encoding.t +end + +module Make (Mass : SMass) : S with type mass = Mass.t = struct + type mass = Mass.t + + type 'a t = { + total : Mass.t; + support : 'a FallbackArray.t; + p : Mass.t FallbackArray.t; + alias : int FallbackArray.t; + } + + let rec init_loop total p alias small large = + match (small, large) with + | [], _ -> List.iter (fun (_, i) -> FallbackArray.set p i total) large + | _, [] -> + (* This can only happen because of numerical inaccuracies e.g. when using + [Mass.t = float] *) + List.iter (fun (_, i) -> FallbackArray.set p i total) small + | (qi, i) :: small', (qj, j) :: large' -> + FallbackArray.set p i qi ; + FallbackArray.set alias i j ; + let qj' = Mass.sub (Mass.add qi qj) total in + if Mass.(qj' < total) then + init_loop total p alias ((qj', j) :: small') large' + else init_loop total p alias small' ((qj', j) :: large') + + let support : fallback:'a -> ('a * Mass.t) list -> 'a FallbackArray.t = + fun ~fallback measure -> FallbackArray.of_list ~fallback ~proj:fst measure + + let check_and_cleanup measure = + let total, measure = + List.fold_left + (fun ((total, m) as acc) ((_, p) as point) -> + if Mass.(zero < p) then (Mass.add total p, point :: m) + else if Mass.(p < zero) then invalid_arg "create" + else (* p = zero: drop point *) + acc) + (Mass.zero, []) + measure + in + match measure with + | [] -> invalid_arg "create" + | (fallback, _) :: _ -> (fallback, total, measure) + + (* NB: duplicate elements in the support are not merged; + the algorithm should still function correctly. *) + let create (measure : ('a * Mass.t) list) = + let fallback, total, measure = check_and_cleanup measure in + let length = List.length measure in + let n = Mass.of_int length in + let small, large = + List.fold_left_i + (fun i (small, large) (_, p) -> + let q = Mass.mul p n in + if Mass.(q < total) then ((q, i) :: small, large) + else (small, (q, i) :: large)) + ([], []) + measure + in + let support = support ~fallback measure in + let p = FallbackArray.make length Mass.zero in + let alias = FallbackArray.make length (-1) in + init_loop total p alias small large ; + {total; support; p; alias} + + let sample {total; support; p; alias} draw_i_elt = + let n = FallbackArray.length support in + let i, elt = draw_i_elt ~int_bound:n ~mass_bound:total in + let p = FallbackArray.get p i in + if Mass.(elt < p) then FallbackArray.get support i + else + let j = FallbackArray.get alias i in + assert (Compare.Int.(j >= 0)) ; + FallbackArray.get support j + + (* Note: this could go in the environment maybe? *) + let array_encoding : 'a Data_encoding.t -> 'a FallbackArray.t Data_encoding.t + = + fun venc -> + let open Data_encoding in + conv + (fun array -> + let length = FallbackArray.length array in + let fallback = FallbackArray.fallback array in + let elements = + List.rev (FallbackArray.fold (fun acc elt -> elt :: acc) array []) + in + (length, fallback, elements)) + (fun (length, fallback, elements) -> + let array = FallbackArray.make length fallback in + List.iteri (fun i elt -> FallbackArray.set array i elt) elements ; + array) + (obj3 + (req "length" int31) + (req "fallback" venc) + (req "elements" (list venc))) + + let mass_array_encoding = array_encoding Mass.encoding + + let int_array_encoding = array_encoding Data_encoding.int31 + + let encoding enc = + let open Data_encoding in + conv + (fun {total; support; p; alias} -> (total, support, p, alias)) + (fun (total, support, p, alias) -> {total; support; p; alias}) + (obj4 + (req "total" Mass.encoding) + (req "support" (array_encoding enc)) + (req "p" mass_array_encoding) + (req "alias" int_array_encoding)) +end + +module Internal_for_tests = struct + module Make = Make + + module type SMass = SMass +end + +module Mass : SMass with type t = int64 = struct + type t = int64 + + let encoding = Data_encoding.int64 + + let zero = 0L + + let of_int = Int64.of_int + + let mul = Int64.mul + + let add = Int64.add + + let sub = Int64.sub + + let ( = ) = Compare.Int64.( = ) + + let ( <= ) = Compare.Int64.( <= ) + + let ( < ) = Compare.Int64.( < ) +end + +(* This is currently safe to do that since since at this point the values for + [total] is 8 * 10^8 * 10^6 and the delegates [n] = 400. + + Therefore [let q = Mass.mul p n ...] in [create] does not overflow since p < + total. + + Assuming the total active stake does not increase too much, which is the case + at the current 5% inflation rate, this implementation can thus support around + 10000 delegates without overflows. + + If/when this happens, the implementation should be revisited. +*) +include Make (Mass) diff --git a/src/proto_020_PsParisC/lib_protocol/sampler.mli b/src/proto_020_PsParisC/lib_protocol/sampler.mli new file mode 100644 index 000000000000..00cf20a7768c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sampler.mli @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +(** Efficient sampling from given finitely supported (nonzero, positive) + measures using the alias method. Measures need not be normalized on input, + but sampling proceeds from the normalized probability measure associated + to the given measure. + *) + +(** [S] is the module type of a module allowing to construct samplers based + on the alias method. *) +module type S = sig + (** [mass] is the type in which finite measures take their values + (see [Mass] module type). *) + type mass + + (** ['a t] is the type of auxilliary data for sampling from + a given distribution. *) + type 'a t + + (** [create measure] constructs auxilliary data to sample from + [measure] after normalization. Complexity: O(n). + + It is assumed that the measure is positive. [measure] can contain + zero mass elements: those are removed in a pre-processing step. + The total mass of the measure should be strictly positive. + + @raise Invalid_argument if [measure] contains negative mass elements + or if it contains only zero mass elements. *) + val create : ('a * mass) list -> 'a t + + (** [sample auxdata rand] creates a sampler from [auxdata] that follows + the distribution associated to the measure specified when + creating the [auxdata]. The parameter [rand] is a random sampler + for the two random values used by the sampling method. The first + bound is at most the length of the list passed to [create] when + creating [auxdata]. The second bound is at most the sum of all + items in the list passed to [create]. *) + val sample : 'a t -> (int_bound:int -> mass_bound:mass -> int * mass) -> 'a + + (** [encoding e] constructs an encoding for ['a t] given an encoding for ['a]. *) + val encoding : 'a Data_encoding.t -> 'a t Data_encoding.t +end + +(**/**) + +module Internal_for_tests : sig + (** [Mass] is the module type describing the measure associated to points. + + The current signature reflects the need for efficiency for the arithmetic + operators. As such, they do not error or add dynamic checks for + over-/under-flow. + + One must make sure that the implementation of its arithmetic operators + cannot over-/under-flow under the current usage. *) + module type SMass = sig + (** [t] is the type describing the measure associated to points. *) + type t + + val encoding : t Data_encoding.t + + val zero : t + + val of_int : int -> t + + val mul : t -> t -> t + + val add : t -> t -> t + + val sub : t -> t -> t + + val ( = ) : t -> t -> bool + + val ( <= ) : t -> t -> bool + + val ( < ) : t -> t -> bool + end + + (** [Make(Mass)] instantiates a module allowing to creates + samplers for [Mass]-valued finite measures. *) + module Make : functor (Mass : SMass) -> S with type mass = Mass.t +end + +(** Sampler based on int64. In the current state of the protocol, this should + not ever over-/under-flow -- see the thought process in the .ml file. + + However, should the total stake increase a lot or the number of delegates get + close to 10k, this might not be true anymore and this module should be + revisited. *) +include S with type mass = Int64.t diff --git a/src/proto_020_PsParisC/lib_protocol/sapling_repr.ml b/src/proto_020_PsParisC/lib_protocol/sapling_repr.ml new file mode 100644 index 000000000000..0e54e90a5727 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sapling_repr.ml @@ -0,0 +1,205 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type transaction = Sapling.UTXO.transaction + +let transaction_encoding = Sapling.UTXO.transaction_encoding + +(* The two data structures in the state are all ordered by position, a diff + contains the elements starting from an offset position up to the most recent + position. A diff can be applied to a state stored in a context to obtain a + new state. + Diffs are used by the Michelson interpreter during the evaluation of smart + contracts to keep a temporary state that may be discarded. + Diffs are also returned by an RPC to allow a client to synchronize its own + state with the chain. +*) +type diff = { + commitments_and_ciphertexts : + (Sapling.Commitment.t * Sapling.Ciphertext.t) list; + nullifiers : Sapling.Nullifier.t list; +} + +let diff_encoding = + let open Data_encoding in + conv + (fun d -> (d.commitments_and_ciphertexts, d.nullifiers)) + (fun (commitments_and_ciphertexts, nullifiers) -> + (match commitments_and_ciphertexts with + | [] -> () + | (_cm_hd, ct_hd) :: rest -> + let memo_size = Sapling.Ciphertext.get_memo_size ct_hd in + List.iter + (fun (_cm, ct) -> + assert ( + Compare.Int.(Sapling.Ciphertext.get_memo_size ct = memo_size))) + rest) ; + {commitments_and_ciphertexts; nullifiers}) + (obj2 + (req + "commitments_and_ciphertexts" + (list (tup2 Sapling.Commitment.encoding Sapling.Ciphertext.encoding))) + (req "nullifiers" (list Sapling.Nullifier.encoding))) + +module Memo_size = struct + type t = int + + let encoding = Data_encoding.uint16 + + let equal = Compare.Int.( = ) + + let max_uint16 = 0xffff + + let max_uint16_z = Z.of_int max_uint16 + + let err = + Error + ("a positive 16-bit integer (between 0 and " ^ string_of_int max_uint16 + ^ ")") + + let parse_z z = + if Compare.Z.(Z.zero <= z) && Compare.Z.(z <= max_uint16_z) then + Ok (Z.to_int z) + else err + + let unparse_to_z = Z.of_int + + let in_memory_size (_ : t) = + let open Cache_memory_helpers in + !!0 +end + +let transaction_get_memo_size (transaction : Sapling.UTXO.transaction) = + match transaction.outputs with + | [] -> None + | {ciphertext; _} :: _ -> + (* Encoding ensures all ciphertexts have the same memo size. *) + Some (Sapling.Ciphertext.get_memo_size ciphertext) + +open Cache_memory_helpers + +(* This should be exported by [lib_sapling] rather than implemented here. *) +let input_in_memory_size = + (* type input = + * Sapling.UTXO.input = { + * cv : Sapling.CV.t; + * nf : Sapling.Nullifier.t; + * rk : Sapling.UTXO.rk; + * proof_i : Sapling.UTXO.spend_proof; + * signature : Sapling.UTXO.spend_sig; + * } *) + let cv_size = string_size_gen 32 in + let nf_size = string_size_gen 32 in + let rk_size = string_size_gen 32 in + let proof_i_size = string_size_gen @@ (48 + 96 + 48) in + let signature_size = string_size_gen 64 in + header_size +! (word_size *? 5) +! cv_size +! nf_size +! rk_size + +! proof_i_size +! signature_size + +let ciphertext_size = + (* type t = { + * cv : CV.t; + * epk : DH.epk; + * payload_enc : Bytes.t; + * nonce_enc : Crypto_box.nonce; + * payload_out : Bytes.t; + * nonce_out : Crypto_box.nonce; + * } *) + let cv_size = string_size_gen 32 in + let epk_size = string_size_gen 32 in + let nonce_enc_size = + string_size_gen 24 + (* from lib_hacl/hacl.ml:Nonce.size *) + in + let payload_out_size = + string_size_gen (32 + 32 + 16) + (* from lib_sapling/core.ml:Ciphertext.encoding *) + in + let nonce_out_size = string_size_gen 24 in + let fixed_payload_data_size = + 11 + 8 + 32 + 16 + 4 + (* from lib_sapling/core.ml:Ciphertext.get_memo_size *) + in + + fun memo_size -> + let payload_size = string_size_gen (memo_size + fixed_payload_data_size) in + header_size +! (word_size *? 6) +! cv_size +! epk_size +! payload_size + +! nonce_enc_size +! payload_out_size +! nonce_out_size + +let output_in_memory_size = + (* type output = { + * cm : Commitment.t; + * proof_o : output_proof; + * ciphertext : Ciphertext.t; + * } *) + let cm_size = string_size_gen 32 in + let proof_o_size = string_size_gen @@ (48 + 96 + 48) in + let ciphertext_size = ciphertext_size in + + fun memo_size -> + header_size +! (word_size *? 3) +! cm_size +! proof_o_size + +! ciphertext_size memo_size + +(** Returns an approximation of the in-memory size of a Sapling transaction. *) +let transaction_in_memory_size (transaction : Sapling.UTXO.transaction) = + (* type transaction = + * transaction = { + * inputs : Sapling.UTXO.input list; + * outputs : Sapling.UTXO.output list; + * binding_sig : Sapling.UTXO.binding_sig; + * balance : int64; + * root : Sapling.Hash.t; + * } *) + let binding_sig_size = string_size_gen 64 in + let balance_size = int64_size in + let root_size = string_size_gen 32 in + let inputs = List.length transaction.inputs in + let outputs = List.length transaction.outputs in + let memo_size = + Option.value ~default:0 (transaction_get_memo_size transaction) + in + let bound_data_size = string_size transaction.bound_data in + header_size +! (word_size *? 5) + +! (list_cell_size input_in_memory_size *? inputs) + +! (list_cell_size (output_in_memory_size memo_size) *? outputs) + +! binding_sig_size +! balance_size +! root_size +! bound_data_size + +(** Returns an approximation of the in-memory size of a Sapling diff. *) +let diff_in_memory_size ({commitments_and_ciphertexts; nullifiers} : diff) = + let cms_and_cts = List.length commitments_and_ciphertexts in + let nfs = List.length nullifiers in + let cm_size = string_size_gen 32 in + let nf_size = string_size_gen 32 in + let memo_size = + (* All memo_size in a diff should be equal (see invariant enforced by + [diff] encoding above) *) + match commitments_and_ciphertexts with + | [] -> 0 + | (_, ct) :: _ -> Sapling.Ciphertext.get_memo_size ct + in + header_size +! (word_size *? 2) + +! list_cell_size (boxed_tup2 cm_size (ciphertext_size memo_size)) + *? cms_and_cts + +! (list_cell_size nf_size *? nfs) diff --git a/src/proto_020_PsParisC/lib_protocol/sapling_services.ml b/src/proto_020_PsParisC/lib_protocol/sapling_services.ml new file mode 100644 index 000000000000..738cecaaff22 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sapling_services.ml @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let custom_root = + (RPC_path.(open_root / "context" / "sapling") + : RPC_context.t RPC_path.context) + +type diff_query = { + offset_commitment : Int64.t option; + offset_nullifier : Int64.t option; +} + +module S = struct + module Args = struct + type ('query_type, 'output_type) t = { + name : string; + description : string; + query : 'query_type RPC_query.t; + output : 'output_type Data_encoding.t; + f : context -> Sapling.Id.t -> 'query_type -> 'output_type tzresult Lwt.t; + } + + let get_diff_query : diff_query RPC_query.t = + let open RPC_query in + query (fun offset_commitment offset_nullifier -> + {offset_commitment; offset_nullifier}) + |+ opt_field + ~descr: + "Commitments and ciphertexts are returned from the specified \ + offset up to the most recent." + "offset_commitment" + RPC_arg.uint63 + (fun {offset_commitment; _} -> offset_commitment) + |+ opt_field + ~descr: + "Nullifiers are returned from the specified offset up to the most \ + recent." + "offset_nullifier" + RPC_arg.uint63 + (fun {offset_nullifier; _} -> offset_nullifier) + |> seal + + let encoding = + let open Data_encoding in + merge_objs (obj1 (req "root" Sapling.root_encoding)) Sapling.diff_encoding + + let get_diff = + { + name = "get_diff"; + description = + "Returns the root and a diff of a state starting from an optional \ + offset which is zero by default."; + query = get_diff_query; + output = encoding; + f = + (fun ctxt id {offset_commitment; offset_nullifier} -> + Sapling.get_diff ctxt id ?offset_commitment ?offset_nullifier ()); + } + end + + let make_service Args.{name; description; query; output; f} = + let path = RPC_path.(custom_root /: Sapling.rpc_arg / name) in + let service = RPC_service.get_service ~description ~query ~output path in + (service, fun ctxt id q () -> f ctxt id q) + + let get_diff = make_service Args.get_diff +end + +let register () = + let reg ~chunked (service, f) = + Services_registration.register1 ~chunked service f + in + reg ~chunked:false S.get_diff + +let mk_call1 (service, _f) ctxt block id q = + RPC_context.make_call1 service ctxt block id q () + +let get_diff ctxt block id ?offset_commitment ?offset_nullifier () = + mk_call1 S.get_diff ctxt block id {offset_commitment; offset_nullifier} diff --git a/src/proto_020_PsParisC/lib_protocol/sapling_storage.ml b/src/proto_020_PsParisC/lib_protocol/sapling_storage.ml new file mode 100644 index 000000000000..b2ef8eb25a91 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sapling_storage.ml @@ -0,0 +1,514 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type COMMITMENTS = sig + val init : Raw_context.t -> Storage.Sapling.id -> Raw_context.t Lwt.t + + val default_root : Sapling.Hash.t + + val get_root : + Raw_context.t -> + Storage.Sapling.id -> + (Raw_context.t * Sapling.Hash.t) tzresult Lwt.t + + val add : + Raw_context.t -> + Storage.Sapling.id -> + Sapling.Commitment.t list -> + int64 -> + (Raw_context.t * int) tzresult Lwt.t + + val get_from : + Raw_context.t -> + Storage.Sapling.id -> + int64 -> + Sapling.Commitment.t list tzresult Lwt.t +end + +module Commitments : COMMITMENTS = struct + module H = Sapling.Hash + + (** Incremental Merkle Tree + * + * A tree of height h contains 2^h leaves and h+1 levels of nodes with + * leaves at level 0 and root at level h. + * + * The leaves are commitments and the tree it is treated as always filled + * with a default value H.uncommitted. This allows to have proofs of + * membership, or witnesses, of fixed size. + * + * All the nodes at the same level of an empty tree have the same hash, + * which can be computed from the default value of the leaves. This is + * stored in the [uncommitted] list. + * + * Any subtree filled with default values is represented by the Empty + * constructor and given its height it's possible to compute its hash + * using the [uncommitted] list. + * + * The leaves are indexed by their position [pos], ranging from 0 to + * (2^h)-1. The encoding of [pos] limits the possible size of the tree. + * In any case the only valid height for the Sapling library is 32, so even + * if the library encodes positions as uint64, they never exceed uint32. + * + * The tree is incremental in the sense that leaves cannot be modified but + * only added and exclusively in successive positions. + * + * Given that elements are added and retrieved by position, it is possible + * to use this information to efficiently navigate the tree. + * Given a tree of height [h] and a position [pos], if pos < pow2 (h-1) only + * the left subtree needs to be inspected recursively. Otherwise only the + * right needs to be visited, decreasing [pos] by [pow2 (h-1)]. + * + * In order to avoid storing the height for each subtree (or worse + * recomputing it), each function with suffix `_height` expects the height + * of the tree as parameter. These functions are only for internal use and + * are later aliased by functions using the default height of a Sapling + * incremental Merkle tree. + * + * Each node of the tree is indexed starting from the root at index 1, + * followed by its left child at index 2, right child at index 3 and so on + * until the last leaf at index 2^(depth+1)-1, or in terms of height + * 2^(32 - height +1) -1. + * The functions left and right return the index of the left and right child + * of a node. + *) + + let pow2 h = Int64.(shift_left 1L h) + + let max_height = 32 + + let max_size = pow2 max_height + + let assert_node node height = + assert ( + let first_of_height = pow2 (max_height - height) in + let first_of_next_height = Int64.shift_left first_of_height 1 in + Compare.Int64.(node >= first_of_height && node < first_of_next_height)) + + let assert_height height = + assert (Compare.Int.(height >= 0 && height <= max_height)) + + let assert_pos pos height = + assert (Compare.Int64.(pos >= 0L && pos <= pow2 height)) + + let default_root = H.uncommitted ~height:max_height + + let init = Storage.Sapling.commitments_init + + let get_root_height ctx id node height = + let open Lwt_result_syntax in + assert_node node height ; + assert_height height ; + let+ ctx, cm_opt = Storage.Sapling.Commitments.find (ctx, id) node in + match cm_opt with + | None -> + let hash = H.uncommitted ~height in + (ctx, hash) + | Some hash -> (ctx, hash) + + let left node = Int64.mul node 2L + + let right node = Int64.(add (mul node 2L) 1L) + + (* Not tail-recursive *) + let rec split_at n l = + if Compare.Int64.(n = 0L) then ([], l) + else + match l with + | [] -> ([], l) + | x :: xs -> + let l1, l2 = split_at Int64.(pred n) xs in + (x :: l1, l2) + + (* [insert tree height pos cms] inserts the list of commitments + [cms] in the tree [tree] of height [height] at the next position [pos]. + Returns the context, the size of the added storage, and the hash of the + node. Not tail-recursive. + Pre: incremental tree /\ + size tree + List.length cms <= pow2 height /\ + pos = size tree /\ + Post: incremental tree /\ + to_list (insert tree height pos cms) = to_list t @ cms *) + let rec insert ctx id node height pos cms = + let open Lwt_result_syntax in + assert_node node height ; + assert_height height ; + assert_pos pos height ; + match (height, cms) with + | _, [] -> + let+ ctx, h = get_root_height ctx id node height in + (ctx, 0, h) + | 0, [cm] -> + let h = H.of_commitment cm in + let+ ctx, size = Storage.Sapling.Commitments.init (ctx, id) node h in + (ctx, size, h) + | _ -> + let height = height - 1 in + let* ctx, size_children, hl, hr = + if Compare.Int64.(pos < pow2 height) then + let at = Int64.(sub (pow2 height) pos) in + let cml, cmr = split_at at cms in + let* ctx, size_l, hl = insert ctx id (left node) height pos cml in + let+ ctx, size_r, hr = insert ctx id (right node) height 0L cmr in + (ctx, size_l + size_r, hl, hr) + else + let* ctx, hl = get_root_height ctx id (left node) height in + let pos = Int64.(sub pos (pow2 height)) in + let+ ctx, size_r, hr = insert ctx id (right node) height pos cms in + (ctx, size_r, hl, hr) + in + let h = H.merkle_hash ~height hl hr in + let+ ctx, size, _existing = + Storage.Sapling.Commitments.add (ctx, id) node h + in + (ctx, size + size_children, h) + + let rec fold_from_height ctx id node ~pos ~f ~acc height = + let open Lwt_result_syntax in + assert_node node height ; + assert_height height ; + assert_pos pos height ; + let* _ctx, cm_opt = + Storage.Sapling.Commitments.find (ctx, id) node + (* we don't count gas for this function, it is called only by RPC *) + in + match cm_opt with + | None -> return acc + | Some h -> + if Compare.Int.(height = 0) then return (f acc h) + else + let full = pow2 (height - 1) in + if Compare.Int64.(pos < full) then + let* acc = + fold_from_height ctx id (left node) ~pos ~f ~acc (height - 1) + in + (* Setting pos to 0 folds on the whole right subtree *) + fold_from_height ctx id (right node) ~pos:0L ~f ~acc (height - 1) + else + let pos = Int64.(sub pos full) in + fold_from_height ctx id (right node) ~pos ~f ~acc (height - 1) + + let root_node = 1L + + let get_root ctx id = get_root_height ctx id root_node max_height + + (* Expects pos to be the next position to insert. Pos is also the number of + inserted leaves. + A commitment should always be added together with a corresponding + ciphertext in the same position. + [insert] is not tail-recursive so we put a hard limit on the size of the + list of commitments. The use of [split_at] has O(n logn) complexity that is + less relevant on a smaller list. *) + let add ctx id cms pos = + let open Lwt_result_syntax in + let l = List.length cms in + assert (Compare.Int.(l <= 1000)) ; + let n' = Int64.(add pos (of_int l)) in + assert (Compare.Int64.(n' <= max_size)) ; + let+ ctx, size, _h = insert ctx id root_node max_height pos cms in + (ctx, size) + + let get_from ctx id pos = + let open Lwt_result_syntax in + let+ l = + fold_from_height + ctx + id + root_node + ~pos + ~f:(fun acc c -> H.to_commitment c :: acc) + ~acc:[] + max_height + in + List.rev l +end + +module Ciphertexts = struct + let init ctx id = Storage.Sapling.ciphertexts_init ctx id + + (* a ciphertext should always be added together with a corresponding + commitment in the same position *) + let add ctx id c pos = Storage.Sapling.Ciphertexts.init (ctx, id) pos c + + let get_from ctx id offset = + let open Lwt_result_syntax in + let rec aux (ctx, acc) pos = + let* ctx, c = Storage.Sapling.Ciphertexts.find (ctx, id) pos in + match c with + | None -> return (ctx, List.rev acc) + | Some c -> aux (ctx, c :: acc) (Int64.succ pos) + in + aux (ctx, []) offset +end + +(* Collection of nullifiers w/o duplicates, append-only. It has a dual + implementation with a hash map for constant `mem` and with a ordered set to + retrieve by position. *) +module Nullifiers = struct + let init = Storage.Sapling.nullifiers_init + + let size ctx id = Storage.Sapling.Nullifiers_size.get (ctx, id) + + let mem ctx id nf = Storage.Sapling.Nullifiers_hashed.mem (ctx, id) nf + + (* Allows for duplicates as they are already checked by verify_update before + updating the state. *) + let add ctx id nfs = + let open Lwt_result_syntax in + let* nf_start_pos = size ctx id in + let* ctx, nf_end_pos, size = + List.fold_left_es + (fun (ctx, pos, acc_size) nf -> + let* ctx, size = + Storage.Sapling.Nullifiers_hashed.init (ctx, id) nf + in + let+ ctx = Storage.Sapling.Nullifiers_ordered.init (ctx, id) pos nf in + (ctx, Int64.succ pos, Z.add acc_size (Z.of_int size))) + (ctx, nf_start_pos, Z.zero) + (List.rev nfs) + in + let+ ctx = Storage.Sapling.Nullifiers_size.update (ctx, id) nf_end_pos in + (ctx, size) + + let get_from ctx id offset = + let open Lwt_result_syntax in + let rec aux acc pos = + let* nf_opt = Storage.Sapling.Nullifiers_ordered.find (ctx, id) pos in + match nf_opt with + | None -> return @@ List.rev acc + | Some c -> aux (c :: acc) (Int64.succ pos) + in + aux [] offset +end + +(** Bounded queue of roots. The full size is initialized with the default + uncommitted root, that's why roots storage doesn't need to be carbonated. + A maximum of one new root is added per protocol level. + If multiple transactions for the same shielded pool are processed during the + same contract call or several calls in the same block, only the last root + will be stored. + This property prevents transactions in the same block from depending on each + other and guarantees that a transaction will be valid for a least two hours + (hence the 120 size) after being forged. *) +module Roots = struct + let size = 120l + + (* pos is the index of the last inserted element *) + + let get ctx id = + let open Lwt_result_syntax in + let* pos = Storage.Sapling.Roots_pos.get (ctx, id) in + Storage.Sapling.Roots.get (ctx, id) pos + + let init ctx id = + let open Lwt_result_syntax in + let rec aux ctx pos = + if Compare.Int32.(pos < 0l) then return ctx + else + let* ctx = + Storage.Sapling.Roots.init (ctx, id) pos Commitments.default_root + in + aux ctx (Int32.pred pos) + in + let* ctx = aux ctx (Int32.pred size) in + let* ctx = Storage.Sapling.Roots_pos.init (ctx, id) 0l in + let level = (Raw_context.current_level ctx).level in + Storage.Sapling.Roots_level.init (ctx, id) level + + let mem ctx id root = + let open Lwt_result_syntax in + let* start_pos = Storage.Sapling.Roots_pos.get (ctx, id) in + let rec aux pos = + let* hash = Storage.Sapling.Roots.get (ctx, id) pos in + if Compare.Int.(Sapling.Hash.compare hash root = 0) then return_true + else + let pos = Int32.(pred pos) in + let pos = if Compare.Int32.(pos < 0l) then Int32.pred size else pos in + if Compare.Int32.(pos = start_pos) then return_false else aux pos + in + aux start_pos + + (* allows duplicates *) + let add ctx id root = + let open Lwt_result_syntax in + let* pos = Storage.Sapling.Roots_pos.get (ctx, id) in + let level = (Raw_context.current_level ctx).level in + let* stored_level = Storage.Sapling.Roots_level.get (ctx, id) in + if Raw_level_repr.(stored_level = level) then + (* if there is another add during the same level, it will over-write on + the same position *) + let*! ctx = Storage.Sapling.Roots.add (ctx, id) pos root in + return ctx + else + (* it's the first add for this level *) + (* TODO(samoht): why is it using [update] and not [init] then? *) + let* ctx = Storage.Sapling.Roots_level.update (ctx, id) level in + let pos = Int32.rem (Int32.succ pos) size in + let* ctx = Storage.Sapling.Roots_pos.update (ctx, id) pos in + let*! ctx = Storage.Sapling.Roots.add (ctx, id) pos root in + return ctx +end + +(** This type links the permanent state stored in the context at the specified + id together with the ephemeral diff managed by the Michelson + interpreter. After a successful execution the diff can be applied to update + the state at id. The first time a state is created its id is None, one will + be assigned after the first application. *) +type state = { + id : Lazy_storage_kind.Sapling_state.Id.t option; + diff : Sapling_repr.diff; + memo_size : Sapling_repr.Memo_size.t; +} + +let empty_diff = + Sapling_repr.{commitments_and_ciphertexts = []; nullifiers = []} + +let empty_state ?id ~memo_size () = {id; diff = empty_diff; memo_size} + +(** Returns a state from an existing id. *) +let state_from_id ctxt id = + let open Lwt_result_syntax in + let+ memo_size = Storage.Sapling.Memo_size.get (ctxt, id) in + ({id = Some id; diff = empty_diff; memo_size}, ctxt) + +let rpc_arg = Storage.Sapling.rpc_arg + +let get_memo_size ctx id = Storage.Sapling.Memo_size.get (ctx, id) + +let init ctx id ~memo_size = + let open Lwt_result_syntax in + let*! ctx = Storage.Sapling.Memo_size.add (ctx, id) memo_size in + let*! ctx = Storage.Sapling.Commitments_size.add (ctx, id) Int64.zero in + let*! ctx = Commitments.init ctx id in + let*! ctx = Nullifiers.init ctx id in + let* ctx = Roots.init ctx id in + let*! ctx = Ciphertexts.init ctx id in + return ctx + +(** Applies a diff to a state id stored in the context. Updates Commitments, + Ciphertexts and Nullifiers using the diff and updates the Roots using the + new Commitments tree. *) +let apply_diff ctx id diff = + let open Lwt_result_syntax in + let open Sapling_repr in + let nb_commitments = List.length diff.commitments_and_ciphertexts in + let nb_nullifiers = List.length diff.nullifiers in + let sapling_cost = + Sapling_storage_costs.cost_SAPLING_APPLY_DIFF nb_nullifiers nb_commitments + in + let*? ctx = Raw_context.consume_gas ctx sapling_cost in + let* cm_start_pos = Storage.Sapling.Commitments_size.get (ctx, id) in + let cms = List.rev_map fst diff.commitments_and_ciphertexts in + let* ctx, size = Commitments.add ctx id cms cm_start_pos in + let* ctx = + Storage.Sapling.Commitments_size.update + (ctx, id) + (Int64.add cm_start_pos (Int64.of_int nb_commitments)) + in + let* ctx, _ct_end_pos, size = + List.fold_left_es + (fun (ctx, pos, acc_size) (_cm, cp) -> + let+ ctx, size = Ciphertexts.add ctx id cp pos in + (ctx, Int64.succ pos, Z.add acc_size (Z.of_int size))) + (ctx, cm_start_pos, Z.of_int size) + (List.rev diff.commitments_and_ciphertexts) + in + let* ctx, size_nf = Nullifiers.add ctx id diff.nullifiers in + let size = Z.add size size_nf in + match diff.commitments_and_ciphertexts with + | [] -> + (* avoids adding duplicates to Roots *) + return (ctx, size) + | _ :: _ -> + let* ctx, root = Commitments.get_root ctx id in + let+ ctx = Roots.add ctx id root in + (ctx, size) + +let add {id; diff; memo_size} cm_cipher_list = + assert ( + List.for_all + (fun (_cm, cipher) -> + Compare.Int.(Sapling.Ciphertext.get_memo_size cipher = memo_size)) + cm_cipher_list) ; + { + id; + diff = + { + diff with + commitments_and_ciphertexts = + List.rev cm_cipher_list @ diff.commitments_and_ciphertexts; + }; + memo_size; + } + +let root_mem ctx {id; _} tested_root = + match id with + | Some id -> Roots.mem ctx id tested_root + | None -> + return + Compare.Int.( + Sapling.Hash.compare tested_root Commitments.default_root = 0) + +(* to avoid a double spend we need to check the disk AND the diff *) +let nullifiers_mem ctx {id; diff; _} nf = + let exists_in_diff = + List.exists + (fun v -> Compare.Int.(Sapling.Nullifier.compare nf v = 0)) + diff.nullifiers + in + if exists_in_diff then return (ctx, true) + else + match id with + | None -> return (ctx, false) + | Some id -> Nullifiers.mem ctx id nf + +(* Allows for duplicates as they are already checked by verify_update before + updating the state. *) +let nullifiers_add {id; diff; memo_size} nf = + {id; diff = {diff with nullifiers = nf :: diff.nullifiers}; memo_size} + +type root = Sapling.Hash.t + +let root_encoding = Sapling.Hash.encoding + +let get_diff ctx id ?(offset_commitment = 0L) ?(offset_nullifier = 0L) () = + let open Lwt_result_syntax in + if + not + Sapling.Commitment.( + valid_position offset_commitment && valid_position offset_nullifier) + then failwith "Invalid argument." + else + let* commitments = Commitments.get_from ctx id offset_commitment in + let* root = Roots.get ctx id in + let* nullifiers = Nullifiers.get_from ctx id offset_nullifier in + let+ _ctx, ciphertexts = + Ciphertexts.get_from ctx id offset_commitment + (* we don't count gas for RPCs *) + in + match List.combine ~when_different_lengths:() commitments ciphertexts with + | Error () -> failwith "Invalid argument." + | Ok commitments_and_ciphertexts -> + (root, Sapling_repr.{commitments_and_ciphertexts; nullifiers}) diff --git a/src/proto_020_PsParisC/lib_protocol/sapling_storage_costs.ml b/src/proto_020_PsParisC/lib_protocol/sapling_storage_costs.ml new file mode 100644 index 000000000000..de9c8cbe7b59 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sapling_storage_costs.ml @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* Copyright (c) 2023 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Sapling_storage_costs_generated diff --git a/src/proto_020_PsParisC/lib_protocol/sapling_storage_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/sapling_storage_costs_generated.ml new file mode 100644 index 000000000000..0fd3cbbf2ebb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sapling_storage_costs_generated.ml @@ -0,0 +1,18 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model sapling/SAPLING_APPLY_DIFF *) +(* fun size1 -> + fun size2 -> max 10 ((1300000. + (5000. * size1)) + (55000. * size2)) *) +let cost_SAPLING_APPLY_DIFF size1 size2 = + let size1 = S.safe_int size1 in + let size2 = S.safe_int size2 in + (size1 * S.safe_int 5120) + (size2 * S.safe_int 55296) + S.safe_int 1300000 diff --git a/src/proto_020_PsParisC/lib_protocol/sapling_validator.ml b/src/proto_020_PsParisC/lib_protocol/sapling_validator.ml new file mode 100644 index 000000000000..97f1a3460fc0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sapling_validator.ml @@ -0,0 +1,115 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Check that each nullifier is not already present in the state and add it. + Important to avoid spending the same input twice in a transaction. *) +let rec check_and_update_nullifiers ctxt state inputs = + let open Lwt_result_syntax in + match inputs with + | [] -> return (ctxt, Some state) + | input :: inputs -> + let* ctxt, nullifier_in_state = + Sapling_storage.nullifiers_mem ctxt state Sapling.UTXO.(input.nf) + in + if nullifier_in_state then return (ctxt, None) + else + let state = + Sapling_storage.nullifiers_add state Sapling.UTXO.(input.nf) + in + check_and_update_nullifiers ctxt state inputs + +let verify_update : + Raw_context.t -> + Sapling_storage.state -> + Sapling_repr.transaction -> + string -> + (Raw_context.t * (Int64.t * Sapling_storage.state) option) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt state transaction key -> + (* Check the transaction *) + (* To avoid overflowing the balance, the number of inputs and outputs must be + bounded. + Ciphertexts' memo_size must match the state's memo_size. + These constraints are already enforced at the encoding level. *) + assert (Compare.Int.(List.compare_length_with transaction.inputs 5208 <= 0)) ; + assert (Compare.Int.(List.compare_length_with transaction.outputs 2019 <= 0)) ; + let pass = + List.for_all + (fun output -> + Compare.Int.( + Sapling.Ciphertext.get_memo_size Sapling.UTXO.(output.ciphertext) + = state.memo_size)) + transaction.outputs + in + if not pass then return (ctxt, None) + else + (* Check the root is a recent state *) + let* pass = Sapling_storage.root_mem ctxt state transaction.root in + if not pass then return (ctxt, None) + else + let+ ctxt, state_opt = + check_and_update_nullifiers ctxt state transaction.inputs + in + match state_opt with + | None -> (ctxt, None) + | Some state -> + Sapling.Verification.with_verification_ctx (fun vctx -> + let pass = + (* Check all the output ZK proofs *) + List.for_all + (fun output -> + Sapling.Verification.check_output vctx output) + transaction.outputs + in + if not pass then (ctxt, None) + else + let pass = + (* Check all the input Zk proofs and signatures *) + List.for_all + (fun input -> + Sapling.Verification.check_spend + vctx + input + transaction.root + key) + transaction.inputs + in + if not pass then (ctxt, None) + else + let pass = + (* Check the signature and balance of the whole transaction *) + Sapling.Verification.final_check vctx transaction key + in + if not pass then (ctxt, None) + else + (* update tree *) + let list_to_add = + List.map + (fun output -> + Sapling.UTXO.(output.cm, output.ciphertext)) + transaction.outputs + in + let state = Sapling_storage.add state list_to_add in + (ctxt, Some (transaction.balance, state))) diff --git a/src/proto_020_PsParisC/lib_protocol/saturation_repr.ml b/src/proto_020_PsParisC/lib_protocol/saturation_repr.ml new file mode 100644 index 000000000000..47739c809ba2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/saturation_repr.ml @@ -0,0 +1,200 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* let () = assert (Sys.int_size = 63) *) + +type _ t = int + +type mul_safe + +type may_saturate + +let may_saturate : _ t -> may_saturate t = fun x -> x + +let to_int x = x + +let ( < ) : _ t -> _ t -> bool = Compare.Int.( < ) + +let ( <= ) : _ t -> _ t -> bool = Compare.Int.( <= ) + +let ( > ) : _ t -> _ t -> bool = Compare.Int.( > ) + +let ( >= ) : _ t -> _ t -> bool = Compare.Int.( >= ) + +let ( = ) : _ t -> _ t -> bool = Compare.Int.( = ) + +let equal = ( = ) + +let ( <> ) : _ t -> _ t -> bool = Compare.Int.( <> ) + +let max : _ t -> _ t -> _ t = fun x y -> if x >= y then x else y + +let min : _ t -> _ t -> _ t = fun x y -> if x >= y then y else x + +let compare : _ t -> _ t -> _ t = Compare.Int.compare + +let saturated = max_int + +let ( >! ) : _ t -> int -> bool = Compare.Int.( > ) + +let of_int_opt t = if t >= 0 && t < saturated then Some t else None + +let of_z_opt z = + match Z.to_int z with int -> of_int_opt int | exception Z.Overflow -> None + +let to_z x = Z.of_int x + +let saturate_if_undef = function None -> saturated | Some x -> x + +let safe_z z = saturate_if_undef @@ of_z_opt z + +let safe_int x = of_int_opt x |> saturate_if_undef + +let numbits x = + let x = ref x and n = ref 0 in + (let y = !x lsr 32 in + if y <> 0 then ( + n := !n + 32 ; + x := y)) ; + (let y = !x lsr 16 in + if y <> 0 then ( + n := !n + 16 ; + x := y)) ; + (let y = !x lsr 8 in + if y <> 0 then ( + n := !n + 8 ; + x := y)) ; + (let y = !x lsr 4 in + if y <> 0 then ( + n := !n + 4 ; + x := y)) ; + (let y = !x lsr 2 in + if y <> 0 then ( + n := !n + 2 ; + x := y)) ; + if !x lsr 1 <> 0 then !n + 2 else !n + !x + +let zero = 0 + +let one = 1 + +let small_enough z = + (* The following literal triggers an error if compiled under 32-bit + architectures, please do not modify it. This is a static way to + ensure that this file is compiled under a 64-bit architecture. *) + z land 0x7fffffff80000000 = 0 + +let mul_safe x = if small_enough x then Some x else None + +let mul_safe_exn x = + if small_enough x then x + else failwith (Format.sprintf "mul_safe_exn: %d must be below 2147483648" x) + +let mul_safe_of_int_exn x = + Option.bind (of_int_opt x) mul_safe |> function + | None -> + failwith + (Format.sprintf "mul_safe_of_int_exn: %d must be below 2147483648" x) + | Some x -> x + +(* If [x] is positive, shifting to the right will produce a number + which is positive and is less than [x]. *) +let shift_right x y = (x :> int) lsr y + +let shift_left x y = + if shift_right saturated y < x then saturated else (x :> int) lsl y + +let mul x y = + (* assert (x >= 0 && y >= 0); *) + match x with + | 0 -> 0 + | x -> + if small_enough x && small_enough y then x * y + else if Compare.Int.(y > saturated / x) then saturated + else x * y + +let mul_fast x y = x * y + +let scale_fast x y = + if x = 0 then 0 + else if small_enough y then x * y + else if Compare.Int.(y > saturated / x) then saturated + else x * y + +let add x y = + let z = x + y in + if Compare.Int.(z >= 0) then z else saturated + +let succ x = add one x + +let sub x y = Compare.Int.max (x - y) 0 + +let sub_opt x y = + let s = x - y in + if Compare.Int.(s >= 0) then Some s else None + +(* Notice that Z.erem does not behave as mod on negative numbers. + Fortunately, the inhabitant of [t] are non-negative. *) +let erem x y = x mod y + +let ediv x y = x / y + +let sqrt x = + of_int_opt x + |> Option.map (fun x -> Z.of_int x |> Z.sqrt |> Z.to_int) + |> saturate_if_undef + +let t_to_z_exn z = + match of_z_opt z with + | None -> + (* since the encoding is applied to values of type [t]. *) assert false + | Some x -> x + +let z_encoding = Data_encoding.(check_size 9 (conv to_z t_to_z_exn z)) + +let n_encoding = Data_encoding.(check_size 9 (conv to_z t_to_z_exn n)) + +let pp fmt x = Format.pp_print_int fmt x + +module Syntax = struct + (* This is a good enough approximation. S.log2 0 = 1 *) + let log2 x = safe_int (1 + numbits x) + + let sqrt = sqrt + + let ( + ) = add + + let ( - ) = sub + + let ( * ) = mul + + let ( < ) = ( < ) + + let ( = ) = ( = ) + + let ( lsr ) = shift_right + + let ( lsl ) = shift_left +end diff --git a/src/proto_020_PsParisC/lib_protocol/saturation_repr.mli b/src/proto_020_PsParisC/lib_protocol/saturation_repr.mli new file mode 100644 index 000000000000..e1fcf58cb233 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/saturation_repr.mli @@ -0,0 +1,234 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides saturated arithmetic between 0 and 2^62 - 1. + + This means that the arithmetic operations provided by this module + do not overflow. If an operation would produce an integer [x] + greater than [2 ^ 62 - 1], it is [saturated] to this + value. Similarly, if an operation would produce a negative integer, + it outputs [zero] instead. + + This saturation arithmetic is used to monitor gas levels. While the + gas model can produce values beyond 2^62 - 1, there is no point in + distinguishing these values from 2^62 - 1 because the amount of gas + available is significantly lower than this limit. + + Notice that most saturation arithmetic operations do not behave + as their standard counterparts when one of their operands is + saturated. For instance, + + (saturated + saturated) - saturated = 0 + + For more information about saturation arithmetic, take a look at: + + https://en.wikipedia.org/wiki/Saturation_arithmetic + +*) + +(** An integer of type ['a t] is between [0] and [saturated]. + + The type parameter ['a] is [mul_safe] if the integer is known + not to overflow when multiplied with another [mul_safe t]. + + The type parameter ['a] is [may_saturate] if the integer is + not known to be sufficiently small to prevent overflow during + multiplication. + +*) +type 'a t = private int + +type mul_safe + +type may_saturate + +val may_saturate : _ t -> may_saturate t + +(** [to_int x] returns the underlying integer representing [x]. *) +val to_int : 'a t -> int + +(** 0 *) +val zero : _ t + +(** 1 *) +val one : _ t + +(** 2^62 - 1 *) +val saturated : may_saturate t + +(** We inherit the order over native integers. *) +val ( >= ) : _ t -> _ t -> bool + +val ( > ) : _ t -> _ t -> bool + +val ( <= ) : _ t -> _ t -> bool + +val ( < ) : _ t -> _ t -> bool + +val ( = ) : _ t -> _ t -> bool + +val ( <> ) : _ t -> _ t -> bool + +val equal : _ t -> _ t -> bool + +val min : 'a t -> 'a t -> 'a t + +val max : 'a t -> 'a t -> 'a t + +val compare : 'a t -> 'b t -> int + +(** [a >! b] is [a > b]. Avoids using [to_int]. *) +val ( >! ) : _ t -> int -> bool + +(** [numbits x] returns the number of bits used in the binary representation + of [x]. *) +val numbits : 'a t -> int + +(** [shift_right x y] behaves like a logical shift of [x] by [y] bits + to the right. [y] must be between 0 and 63. *) +val shift_right : 'a t -> int -> 'a t + +(** [shift_left x y] behaves like a logical shift of [x] by [y] bits + to the left. [y] must be between 0 and 63. In cases where [x lsl y] + is overflowing, [shift_left x y] is [saturated]. *) +val shift_left : 'a t -> int -> 'a t + +(** [mul x y] behaves like multiplication between native integers as + long as its result stay below [saturated]. Otherwise, [mul] returns + [saturated]. *) +val mul : _ t -> _ t -> may_saturate t + +(** [mul_safe x] returns a [mul_safe t] only if [x] does not trigger + overflows when multiplied with another [mul_safe t]. More precisely, + [x] is safe for fast multiplications if [x < 2147483648]. *) +val mul_safe : _ t -> mul_safe t option + +(** [mul_fast x y] exploits the fact that [x] and [y] are known not to + provoke overflows during multiplication to perform a mere + multiplication. *) +val mul_fast : mul_safe t -> mul_safe t -> may_saturate t + +(** [scale_fast x y] exploits the fact that [x] is known not to + provoke overflows during multiplication to perform a + multiplication faster than [mul]. *) +val scale_fast : mul_safe t -> _ t -> may_saturate t + +(** [add x y] behaves like addition between native integers as long as + its result stay below [saturated]. Otherwise, [add] returns + [saturated]. *) +val add : _ t -> _ t -> may_saturate t + +(** [succ x] is like [add one x] *) +val succ : _ t -> may_saturate t + +(** [sub x y] behaves like subtraction between native integers as long + as its result stay positive. Otherwise, [sub] returns [zero]. + This function assumes that [x] is not saturated. +*) +val sub : 'a t -> _ t -> 'a t + +(** [sub_opt x y] behaves like subtraction between native integers as + long as its result stay positive. Otherwise, [sub] returns + [None]. *) +val sub_opt : 'a t -> _ t -> 'a t option + +(** [ediv x y] returns [x / y]. This operation never saturates, hence + it is exactly the same as its native counterpart. [y] is supposed + to be strictly greater than 0, otherwise this function raises + [Division_by_zero]. *) +val ediv : 'a t -> _ t -> 'a t + +(** [erem x y] returns [x mod y]. [y] is supposed to be strictly + greater than 0, otherwise this function raises + [Division_by_zero]. *) +val erem : _ t -> 'b t -> 'b t + +(** [sqrt x] returns the square root of x, rounded down. *) +val sqrt : _ t -> 'a t + +(** [of_int_opt x] returns [Some x] if [x >= 0] and [x < saturated], + and [None] otherwise. *) +val of_int_opt : int -> may_saturate t option + +(** [of_z_opt x] returns [Some x] if [x >= 0] and [x < saturated], + and [None] otherwise. *) +val of_z_opt : Z.t -> may_saturate t option + +(** When a saturated integer is sufficiently small (i.e. strictly less + than 2147483648), we can assign it the type [mul_safe S.t] to use + it within fast multiplications, named [S.scale_fast] and + [S.mul_fast]. + + The following function allows such type assignment but may raise an + exception if the assumption is wrong. Therefore, [mul_safe_exn] + should only be used to define toplevel values, so that these + exceptions can only occur during startup. + *) +val mul_safe_exn : may_saturate t -> mul_safe t + +(** [mul_safe_of_int_exn x] is the composition of [of_int_opt] and + [mul_safe] in the option monad. This function raises [Invalid_argument] + if [x] is not safe. This function should be used on integer literals + that are obviously [mul_safe]. *) +val mul_safe_of_int_exn : int -> mul_safe t + +(** [safe_z z] is [of_z_opt x |> saturate_if_undef]. *) +val safe_z : Z.t -> may_saturate t + +(** [safe_int x] is [of_int_opt x |> saturate_if_undef]. *) +val safe_int : int -> may_saturate t + +(** [to_z z] is [Z.of_int]. *) +val to_z : _ t -> Z.t + +(** Encoding for [t] through the encoding for [z] integers. *) +val z_encoding : _ t Data_encoding.t + +(** Encoding for [t] through the encoding for non-negative integers. *) +val n_encoding : _ t Data_encoding.t + +(** A pretty-printer for native integers. *) +val pp : Format.formatter -> _ t -> unit + +(** Syntax for simple representations. *) +module Syntax : sig + val log2 : _ t -> may_saturate t + + val sqrt : _ t -> may_saturate t + + val ( + ) : _ t -> _ t -> may_saturate t + + val ( - ) : _ t -> _ t -> may_saturate t + + val ( * ) : _ t -> _ t -> may_saturate t + + val ( < ) : _ t -> _ t -> bool + + val ( = ) : _ t -> _ t -> bool + + val ( lsr ) : 'a t -> int -> 'a t + + val ( lsl ) : 'a t -> int -> 'a t +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_PVM_sig.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_PVM_sig.ml new file mode 100644 index 000000000000..2fe94f9cbf47 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_PVM_sig.ml @@ -0,0 +1,625 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module introduces the semantics of Proof-generating Virtual Machines. + + A PVM defines an operational semantics for some computational model. The + specificity of PVMs, in comparison with standard virtual machines, is their + ability to generate and to validate a *compact* proof that a given atomic + execution step turned a given state into another one. + + In the smart-contract rollups, PVMs are used for two purposes: + + - They allow for the externalization of rollup execution by completely + specifying the operational semantics of a given rollup. This + standardization of the semantics gives a unique and executable source of + truth about the interpretation of smart-contract rollup inboxes, seen as a + transformation of a rollup state. + + - They allow for the validation or refutation of a claim that the processing + of some messages led to a given new rollup state (given an actual source + of truth about the nature of these messages). +*) + +(** An input to a PVM is the [message_counter] element of an inbox at + a given [inbox_level] and contains a given [payload]. + + According the rollup management protocol, the payload must be obtained + through {!Sc_rollup_inbox_message_repr.serialize} which follows a documented + format. +*) + +type inbox_message = { + inbox_level : Raw_level_repr.t; + message_counter : Z.t; + payload : Sc_rollup_inbox_message_repr.serialized; +} + +type reveal_data = + | Raw_data of string + | Metadata of Sc_rollup_metadata_repr.t + | Dal_page of Dal_slot_repr.Page.content option + | Dal_parameters of Sc_rollup_dal_parameters_repr.t + +type input = Inbox_message of inbox_message | Reveal of reveal_data + +let pp_inbox_message fmt {inbox_level; message_counter; _} = + Format.fprintf + fmt + "@[level: %a@,message index: %a@]" + Raw_level_repr.pp + inbox_level + Z.pp_print + message_counter + +let pp_reveal_data fmt = function + | Raw_data _ -> Format.pp_print_string fmt "raw data" + | Metadata metadata -> Sc_rollup_metadata_repr.pp fmt metadata + | Dal_page content_opt -> + Format.pp_print_option + ~none:(fun fmt () -> Format.pp_print_string fmt "") + (fun fmt _a -> Format.fprintf fmt "") + fmt + content_opt + | Dal_parameters dal_parameters -> + Sc_rollup_dal_parameters_repr.pp fmt dal_parameters + +let pp_input fmt = function + | Inbox_message msg -> + Format.fprintf fmt "@[inbox message:@,%a@]" pp_inbox_message msg + | Reveal reveal -> + Format.fprintf fmt "@[reveal: %a@]" pp_reveal_data reveal + +(** [inbox_message_encoding] encoding value for {!inbox_message}. *) +let inbox_message_encoding = + let open Data_encoding in + conv + (fun {inbox_level; message_counter; payload} -> + (inbox_level, message_counter, (payload :> string))) + (fun (inbox_level, message_counter, payload) -> + let payload = Sc_rollup_inbox_message_repr.unsafe_of_string payload in + {inbox_level; message_counter; payload}) + (obj3 + (req "inbox_level" Raw_level_repr.encoding) + (req "message_counter" n) + (req "payload" (string Hex))) + +let reveal_data_encoding = + let open Data_encoding in + let kind name = req "reveal_data_kind" (constant name) in + let case_raw_data = + case + ~title:"raw data" + (Tag 0) + (obj2 + (kind "raw_data") + (req + "raw_data" + (check_size + Constants_repr.sc_rollup_message_size_limit + Variable.(string Hex)))) + (function Raw_data m -> Some ((), m) | _ -> None) + (fun ((), m) -> Raw_data m) + and case_metadata = + case + ~title:"metadata" + (Tag 1) + (obj2 (kind "metadata") (req "metadata" Sc_rollup_metadata_repr.encoding)) + (function Metadata md -> Some ((), md) | _ -> None) + (fun ((), md) -> Metadata md) + in + let case_dal_page = + case + ~title:"dal page" + (Tag 2) + (obj2 (kind "dal_page") (req "dal_page_content" (option (bytes Hex)))) + (function Dal_page p -> Some ((), p) | _ -> None) + (fun ((), p) -> Dal_page p) + in + let case_dal_parameters = + case + ~title:"dal parameters" + (Tag 3) + (obj2 + (kind "dal_parameters") + (req "dal_parameters" Sc_rollup_dal_parameters_repr.encoding)) + (function Dal_parameters p -> Some ((), p) | _ -> None) + (fun ((), p) -> Dal_parameters p) + in + union [case_raw_data; case_metadata; case_dal_page; case_dal_parameters] + +let input_encoding = + let open Data_encoding in + let kind name = req "input_kind" (constant name) in + let case_inbox_message = + case + ~title:"inbox msg" + (Tag 0) + (obj2 (kind "inbox_message") (req "inbox_message" inbox_message_encoding)) + (function Inbox_message m -> Some ((), m) | _ -> None) + (fun ((), m) -> Inbox_message m) + and case_reveal_revelation = + case + ~title:"reveal" + (Tag 1) + (obj2 (kind "reveal_revelation") (req "reveal_data" reveal_data_encoding)) + (function Reveal d -> Some ((), d) | _ -> None) + (fun ((), d) -> Reveal d) + in + union [case_inbox_message; case_reveal_revelation] + +(** [input_equal i1 i2] return whether [i1] and [i2] are equal. *) +let inbox_message_equal a b = + let {inbox_level; message_counter; payload} = a in + (* To be robust to the addition of fields in [input] *) + Raw_level_repr.equal inbox_level b.inbox_level + && Z.equal message_counter b.message_counter + && String.equal (payload :> string) (b.payload :> string) + +let reveal_data_equal a b = + match (a, b) with + | Raw_data a, Raw_data b -> String.equal a b + | Raw_data _, _ -> false + | Metadata a, Metadata b -> Sc_rollup_metadata_repr.equal a b + | Metadata _, _ -> false + | Dal_page a, Dal_page b -> Option.equal Bytes.equal a b + | Dal_page _, _ -> false + | Dal_parameters a, Dal_parameters b -> + Sc_rollup_dal_parameters_repr.equal a b + | Dal_parameters _, _ -> false + +let input_equal a b = + match (a, b) with + | Inbox_message a, Inbox_message b -> inbox_message_equal a b + | Inbox_message _, _ -> false + | Reveal a, Reveal b -> reveal_data_equal a b + | Reveal _, _ -> false + +module Input_hash = + Blake2B.Make + (Base58) + (struct + let name = "Smart_rollup_input_hash" + + let title = "A smart rollup input hash" + + let b58check_prefix = + "\001\118\125\135" (* "scd1(37)" decoded from base 58. *) + + let size = Some 20 + end) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/6562 + Consider supporting revealing historical DAL parameters. *) +type reveal = + | Reveal_raw_data of Sc_rollup_reveal_hash.t + | Reveal_metadata + | Request_dal_page of Dal_slot_repr.Page.t + | Reveal_dal_parameters + (** Request DAL parameters that were used for the slots published at + the current inbox level. *) + +let reveal_encoding = + let open Data_encoding in + let kind name = req "reveal_kind" (constant name) in + let case_raw_data = + case + ~title:"Reveal_raw_data" + (Tag 0) + (obj2 + (kind "reveal_raw_data") + (req "input_hash" Sc_rollup_reveal_hash.encoding)) + (function Reveal_raw_data s -> Some ((), s) | _ -> None) + (fun ((), s) -> Reveal_raw_data s) + and case_metadata = + case + ~title:"Reveal_metadata" + (Tag 1) + (obj1 (kind "reveal_metadata")) + (function Reveal_metadata -> Some () | _ -> None) + (fun () -> Reveal_metadata) + in + let case_dal_page = + case + ~title:"Request_dal_page" + (Tag 2) + (obj2 + (kind "request_dal_page") + (req "page_id" Dal_slot_repr.Page.encoding)) + (function Request_dal_page s -> Some ((), s) | _ -> None) + (fun ((), s) -> Request_dal_page s) + in + let case_dal_parameters = + case + ~title:"Reveal_dal_parameters" + (Tag 3) + (obj1 (kind "reveal_dal_parameters")) + (function Reveal_dal_parameters -> Some () | _ -> None) + (fun () -> Reveal_dal_parameters) + in + union [case_raw_data; case_metadata; case_dal_page; case_dal_parameters] + +(** [is_reveal_enabled] is the type of a predicate that tells if a kind of + reveal is activated at a certain block level. *) +type is_reveal_enabled = current_block_level:Raw_level_repr.t -> reveal -> bool + +let is_reveal_enabled_predicate + (t : Constants_parametric_repr.sc_rollup_reveal_activation_level) : + is_reveal_enabled = + fun ~current_block_level reveal -> + let activation_level = + match reveal with + | Reveal_raw_data h -> ( + match Sc_rollup_reveal_hash.scheme_of_hash h with + | Blake2B -> t.raw_data.blake2B) + | Reveal_metadata -> t.metadata + | Request_dal_page _ -> t.dal_page + | Reveal_dal_parameters -> t.dal_parameters + in + Raw_level_repr.(current_block_level >= activation_level) + +(** The PVM's current input expectations: + - [No_input_required] if the machine is busy and has no need for new input. + + - [Initial] if the machine has never received an input so expects the very + first item in the inbox. + + - [First_after (level, counter)] expects whatever comes next after that + position in the inbox. + + - [Needs_metadata] if the machine needs the metadata to continue + its execution. +*) +type input_request = + | No_input_required + | Initial + | First_after of Raw_level_repr.t * Z.t + | Needs_reveal of reveal + +(** [input_request_encoding] encoding value for {!input_request}. *) +let input_request_encoding = + let open Data_encoding in + let kind name = req "input_request_kind" (constant name) in + union + ~tag_size:`Uint8 + [ + case + ~title:"No_input_required" + (Tag 0) + (obj1 (kind "no_input_required")) + (function No_input_required -> Some () | _ -> None) + (fun () -> No_input_required); + case + ~title:"Initial" + (Tag 1) + (obj1 (kind "initial")) + (function Initial -> Some () | _ -> None) + (fun () -> Initial); + case + ~title:"First_after" + (Tag 2) + (obj3 + (kind "first_after") + (req "level" Raw_level_repr.encoding) + (req "counter" n)) + (function + | First_after (level, counter) -> Some ((), level, counter) + | _ -> None) + (fun ((), level, counter) -> First_after (level, counter)); + case + ~title:"Needs_reveal" + (Tag 3) + (obj2 (kind "needs_reveal") (req "reveal" reveal_encoding)) + (function Needs_reveal p -> Some ((), p) | _ -> None) + (fun ((), p) -> Needs_reveal p); + ] + +let pp_reveal fmt = function + | Reveal_raw_data hash -> Sc_rollup_reveal_hash.pp fmt hash + | Reveal_metadata -> Format.pp_print_string fmt "Reveal metadata" + | Request_dal_page id -> Dal_slot_repr.Page.pp fmt id + | Reveal_dal_parameters -> Format.pp_print_string fmt "Reveal DAL parameters" + +(** [pp_input_request fmt i] pretty prints the given input [i] to the formatter + [fmt]. *) +let pp_input_request fmt request = + match request with + | No_input_required -> Format.fprintf fmt "No_input_required" + | Initial -> Format.fprintf fmt "Initial" + | First_after (l, n) -> + Format.fprintf + fmt + "First_after (level = %a, counter = %a)" + Raw_level_repr.pp + l + Z.pp_print + n + | Needs_reveal reveal -> + Format.fprintf fmt "Needs reveal of %a" pp_reveal reveal + +let reveal_equal p1 p2 = + match (p1, p2) with + | Reveal_raw_data h1, Reveal_raw_data h2 -> Sc_rollup_reveal_hash.equal h1 h2 + | Reveal_raw_data _, _ -> false + | Reveal_metadata, Reveal_metadata -> true + | Reveal_metadata, _ -> false + | Request_dal_page a, Request_dal_page b -> Dal_slot_repr.Page.equal a b + | Request_dal_page _, _ -> false + | Reveal_dal_parameters, Reveal_dal_parameters -> true + | Reveal_dal_parameters, _ -> false + +(** [input_request_equal i1 i2] return whether [i1] and [i2] are equal. *) +let input_request_equal a b = + match (a, b) with + | No_input_required, No_input_required -> true + | No_input_required, _ -> false + | Initial, Initial -> true + | Initial, _ -> false + | First_after (l, n), First_after (m, o) -> + Raw_level_repr.equal l m && Z.equal n o + | First_after _, _ -> false + | Needs_reveal p1, Needs_reveal p2 -> reveal_equal p1 p2 + | Needs_reveal _, _ -> false + +(** Type that describes output values. *) +type output = { + outbox_level : Raw_level_repr.t; + (** The outbox level containing the message. The level corresponds to the + inbox level for which the message was produced. *) + message_index : Z.t; (** The message index. *) + message : Sc_rollup_outbox_message_repr.t; (** The message itself. *) +} + +(** [output_encoding] encoding value for {!output}. *) +let output_encoding = + let open Data_encoding in + conv + (fun {outbox_level; message_index; message} -> + (outbox_level, message_index, message)) + (fun (outbox_level, message_index, message) -> + {outbox_level; message_index; message}) + (obj3 + (req "outbox_level" Raw_level_repr.encoding) + (req "message_index" n) + (req "message" Sc_rollup_outbox_message_repr.encoding)) + +(** [pp_output fmt o] pretty prints the given output [o] to the formatter + [fmt]. *) +let pp_output fmt {outbox_level; message_index; message} = + Format.fprintf + fmt + "@[%a@;%a@;%a@;@]" + Raw_level_repr.pp + outbox_level + Z.pp_print + message_index + Sc_rollup_outbox_message_repr.pp + message + +module type S = sig + (** The state of the PVM denotes a state of the rollup. + + The life cycle of the PVM is as follows. It starts its execution + from an {!initial_state}. The initial state is specialized at + origination with a [boot_sector], using the + {!install_boot_sector} function. The resulting state is call the + “genesis” of the rollup. + + Afterwards, we classify states into two categories: "internal + states" do not require any external information to be executed + while "input states" are waiting for some information from the + inbox to be executable. *) + type state + + val pp : state -> (Format.formatter -> unit -> unit) Lwt.t + + (** A [context] represents the executable environment needed by the state to + exist. Typically, the rollup node storage can be part of this context to + allow the PVM state to be persistent. *) + type context + + (** A [hash] characterizes the contents of a state. *) + type hash = Sc_rollup_repr.State_hash.t + + (** During interactive refutation games, a player may need to provide a proof + that a given execution step is valid. The PVM implementation is + responsible for ensuring that this proof type has the correct semantics. + + A proof [p] has four parameters: + + - [start_hash := proof_start_state p] + - [stop_hash := proof_stop_state p] + - [input_requested := proof_input_requested p] + - [input_given := proof_input_given p] + + The following predicate must hold of a valid proof: + + [exists start_state, stop_state. + (state_hash start_state == start_hash) + AND (Option.map state_hash stop_state == stop_hash) + AND (is_input_state start_state == input_requested) + AND (match (input_given, input_requested) with + | (None, No_input_required) -> eval start_state == stop_state + | (None, Initial) -> stop_state == None + | (None, First_after (l, n)) -> stop_state == None + | (Some input, No_input_required) -> true + | (Some input, Initial) -> + set_input input_given start_state == stop_state + | (Some input, First_after (l, n)) -> + set_input input_given start_state == stop_state)] + + In natural language---the two hash parameters [start_hash] and [stop_hash] + must have actual [state] values (or possibly [None] in the case of + [stop_hash]) of which they are the hashes. The [input_requested] parameter + must be the correct request from the [start_hash], given according to + [is_input_state]. Finally there are four possibilities of [input_requested] + and [input_given]. + + - if no input is required, or given, the proof is a simple [eval] + step ; + - if input was required but not given, the [stop_hash] must be + [None] (the machine is blocked) ; + - if no input was required but some was given, this makes no sense + and it doesn't matter if the proof is valid or invalid (this + case will be ruled out by the inbox proof anyway) ; + - finally, if input was required and given, the proof is a + [set_input] step. *) + type proof + + (** [proof]s are embedded in L1 refutation game operations using + [proof_encoding]. Given that the size of L1 operations are limited, it is + of *critical* importance to make sure that no execution step of the PVM + can generate proofs that do not fit in L1 operations when encoded. If such + a proof existed, the rollup could get stuck. *) + val proof_encoding : proof Data_encoding.t + + (** [proof_start_state proof] returns the initial state hash of the [proof] + execution step. *) + val proof_start_state : proof -> hash + + (** [proof_stop_state proof] returns the final state hash of the [proof] + execution step. *) + val proof_stop_state : proof -> hash + + (** [state_hash state] returns a compressed representation of [state]. *) + val state_hash : state -> hash Lwt.t + + (** [initial_state ~empty] is the initial state of the PVM, before its + specialization with a given [boot_sector]. The initial state is built on + the [empty] state which must be provided. *) + val initial_state : empty:state -> state Lwt.t + + (** [install_boot_sector state boot_sector] specializes the initial + [state] of a PVM using a dedicated [boot_sector], submitted at + the origination of the rollup. *) + val install_boot_sector : state -> string -> state Lwt.t + + (** [is_input_state ~is_reveal_enabled state] returns the input expectations of the + [state]---does it need input, and if so, how far through the inbox + has it read so far? *) + val is_input_state : + is_reveal_enabled:is_reveal_enabled -> state -> input_request Lwt.t + + (** [set_input input state] sets [input] in [state] as the next + input to be processed. This must answer the [input_request] + from [is_input_state state]. *) + val set_input : input -> state -> state Lwt.t + + (** [eval s0] returns a state [s1] resulting from the + execution of an atomic step of the rollup at state [s0]. *) + val eval : state -> state Lwt.t + + (** [verify_proof ~is_reveal_enabled input p] checks the proof [p] with input [input] + and returns the [input_request] before the evaluation of the proof. See the + doc-string for the [proof] type. + + [verify_proof input p] fails when the proof is invalid in regards to the + given input. *) + val verify_proof : + is_reveal_enabled:is_reveal_enabled -> + input option -> + proof -> + input_request tzresult Lwt.t + + (** [produce_proof ctxt ~is_reveal_enabled input_given state] should return a [proof] + for the PVM step starting from [state], if possible. This may fail for + a few reasons: + - the [input_given] doesn't match the expectations of [state] ; + - the [context] for this instance of the PVM doesn't have access + to enough of the [state] to build the proof. *) + val produce_proof : + context -> + is_reveal_enabled:is_reveal_enabled -> + input option -> + state -> + proof tzresult Lwt.t + + (** The following type is inhabited by the proofs that a given [output] + is part of the outbox of a given [state]. *) + type output_proof + + (** [output_proof_encoding] encoding value for [output_proof]s. *) + val output_proof_encoding : output_proof Data_encoding.t + + (** [output_of_output_proof proof] returns the [output] that is referred to in + [proof]'s statement. *) + val output_of_output_proof : output_proof -> output + + (** [state_of_output_proof proof] returns the [state] hash that is referred to + in [proof]'s statement. *) + val state_of_output_proof : output_proof -> hash + + (** [verify_output_proof output_proof] returns the [output_proof]'s output + iff the proof is a valid witness that its [output] is part of its + [state]'s outbox. *) + val verify_output_proof : output_proof -> output tzresult Lwt.t + + (** [produce_output_proof ctxt state output] returns a proof that witnesses + the fact that [output] is part of [state]'s outbox. *) + val produce_output_proof : + context -> state -> output -> (output_proof, error) result Lwt.t + + (** [check_dissection ~default_number_of_sections ~start_chunk + ~stop_chunk chunks] fails if the dissection encoded by the list + [[start_chunk] @ chunks @ [stop_chunk]] does not satisfy the + properties expected by the PVM. *) + val check_dissection : + default_number_of_sections:int -> + start_chunk:Sc_rollup_dissection_chunk_repr.t -> + stop_chunk:Sc_rollup_dissection_chunk_repr.t -> + Sc_rollup_dissection_chunk_repr.t list -> + unit tzresult + + (** [get_current_level state] returns the current level of the [state], + returns [None] if it is not possible to compute the level. *) + val get_current_level : state -> Raw_level_repr.t option Lwt.t + + module Internal_for_tests : sig + (** [insert_failure state] corrupts the PVM state. This is used in + the loser mode of the rollup node. *) + val insert_failure : state -> state Lwt.t + end +end + +module type Generic_pvm_context_sig = sig + module Tree : Context.TREE with type key = string list and type value = bytes + + type tree = Tree.tree + + type proof + + val proof_encoding : proof Data_encoding.t + + val proof_before : proof -> Sc_rollup_repr.State_hash.t + + val proof_after : proof -> Sc_rollup_repr.State_hash.t + + val verify_proof : + proof -> (tree -> (tree * 'a) Lwt.t) -> (tree * 'a) option Lwt.t + + val produce_proof : + Tree.t -> tree -> (tree -> (tree * 'a) Lwt.t) -> (proof * 'a) option Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.ml new file mode 100644 index 000000000000..6962e7fec37d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.ml @@ -0,0 +1,1773 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr +module PS = Sc_rollup_PVM_sig + +type error += + | Arith_proof_production_failed + | Arith_output_proof_production_failed + | Arith_invalid_claim_about_outbox + +let () = + let open Data_encoding in + let msg = "Invalid claim about outbox" in + register_error_kind + `Permanent + ~id:"smart_rollup_arith_invalid_claim_about_outbox" + ~title:msg + ~pp:(fun fmt () -> Format.pp_print_string fmt msg) + ~description:msg + unit + (function Arith_invalid_claim_about_outbox -> Some () | _ -> None) + (fun () -> Arith_invalid_claim_about_outbox) ; + let msg = "Output proof production failed" in + register_error_kind + `Permanent + ~id:"smart_rollup_arith_output_proof_production_failed" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Arith_output_proof_production_failed -> Some () | _ -> None) + (fun () -> Arith_output_proof_production_failed) ; + let msg = "Proof production failed" in + register_error_kind + `Permanent + ~id:"smart_rollup_arith_proof_production_failed" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Arith_proof_production_failed -> Some () | _ -> None) + (fun () -> Arith_proof_production_failed) + +module type S = sig + include PS.S + + val parse_boot_sector : string -> string option + + val pp_boot_sector : Format.formatter -> string -> unit + + val pp : state -> (Format.formatter -> unit -> unit) Lwt.t + + val get_tick : state -> Sc_rollup_tick_repr.t Lwt.t + + type status = + | Halted + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + | Parsing + | Evaluating + + val get_status : + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + state -> + status Lwt.t + + val get_outbox : + Raw_level_repr.t -> state -> Sc_rollup_PVM_sig.output list Lwt.t + + type instruction = + | IPush : int -> instruction + | IAdd : instruction + | IStore : string -> instruction + + val equal_instruction : instruction -> instruction -> bool + + val pp_instruction : Format.formatter -> instruction -> unit + + val get_parsing_result : state -> bool option Lwt.t + + val get_code : state -> instruction list Lwt.t + + val get_stack : state -> int list Lwt.t + + val get_var : state -> string -> int option Lwt.t + + val get_evaluation_result : state -> bool option Lwt.t + + val get_is_stuck : state -> string option Lwt.t +end + +module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : + S + with type context = Context.Tree.t + and type state = Context.tree + and type proof = Context.proof = struct + module Tree = Context.Tree + + type context = Context.Tree.t + + type hash = State_hash.t + + type proof = Context.proof + + let proof_encoding = Context.proof_encoding + + let proof_start_state proof = Context.proof_before proof + + let proof_stop_state proof = Context.proof_after proof + + let parse_boot_sector s = Some s + + let pp_boot_sector fmt s = Format.fprintf fmt "%s" s + + type tree = Tree.tree + + type status = + | Halted + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + | Parsing + | Evaluating + + type instruction = + | IPush : int -> instruction + | IAdd : instruction + | IStore : string -> instruction + + let equal_instruction i1 i2 = + match (i1, i2) with + | IPush x, IPush y -> Compare.Int.(x = y) + | IAdd, IAdd -> true + | IStore x, IStore y -> Compare.String.(x = y) + | _, _ -> false + + let pp_instruction fmt = function + | IPush x -> Format.fprintf fmt "push(%d)" x + | IAdd -> Format.fprintf fmt "add" + | IStore x -> Format.fprintf fmt "store(%s)" x + + let check_dissection ~default_number_of_sections ~start_chunk ~stop_chunk = + let open Sc_rollup_dissection_chunk_repr in + let dist = Sc_rollup_tick_repr.distance start_chunk.tick stop_chunk.tick in + let section_maximum_size = Z.div dist (Z.of_int 2) in + Sc_rollup_dissection_chunk_repr.( + default_check + ~section_maximum_size + ~check_sections_number:default_check_sections_number + ~default_number_of_sections + ~start_chunk + ~stop_chunk) + + (* + + The machine state is represented using a Merkle tree. + + Here is the data model of this state represented in the tree: + + - tick : Sc_rollup_tick_repr.t + The current tick counter of the machine. + - status : status + The current status of the machine. + - stack : int deque + The stack of integers. + - next_message : string option + The current input message to be processed. + - code : instruction deque + The instructions parsed from the input message. + - lexer_state : int * int + The internal state of the lexer. + - parsing_state : parsing_state + The internal state of the parser. + - parsing_result : bool option + The outcome of parsing. + - evaluation_result : bool option + The outcome of evaluation. + + *) + module State = struct + type state = tree + + module Monad : sig + type 'a t + + val run : 'a t -> state -> (state * 'a option) Lwt.t + + val is_stuck : string option t + + val internal_error : string -> 'a t + + val return : 'a -> 'a t + + module Syntax : sig + val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t + end + + val remove : Tree.key -> unit t + + val find_value : Tree.key -> 'a Data_encoding.t -> 'a option t + + val children : Tree.key -> 'a Data_encoding.t -> (string * 'a) list t + + val get_value : default:'a -> Tree.key -> 'a Data_encoding.t -> 'a t + + val set_value : Tree.key -> 'a Data_encoding.t -> 'a -> unit t + end = struct + type 'a t = state -> (state * 'a option) Lwt.t + + let return x state = Lwt.return (state, Some x) + + let bind m f state = + let open Lwt_syntax in + let* state, res = m state in + match res with None -> return (state, None) | Some res -> f res state + + module Syntax = struct + let ( let* ) = bind + end + + let run m state = m state + + let internal_error_key = ["internal_error"] + + let internal_error msg tree = + let open Lwt_syntax in + let* tree = Tree.add tree internal_error_key (Bytes.of_string msg) in + return (tree, None) + + let is_stuck tree = + let open Lwt_syntax in + let* v = Tree.find tree internal_error_key in + return (tree, Some (Option.map Bytes.to_string v)) + + let remove key tree = + let open Lwt_syntax in + let* tree = Tree.remove tree key in + return (tree, Some ()) + + let decode encoding bytes state = + let open Lwt_syntax in + match Data_encoding.Binary.of_bytes_opt encoding bytes with + | None -> internal_error "Error during decoding" state + | Some v -> return (state, Some v) + + let find_value key encoding state = + let open Lwt_syntax in + let* obytes = Tree.find state key in + match obytes with + | None -> return (state, Some None) + | Some bytes -> + let* state, value = decode encoding bytes state in + return (state, Some value) + + let children key encoding state = + let open Lwt_syntax in + let* children = Tree.list state key in + let rec aux = function + | [] -> return (state, Some []) + | (key, tree) :: children -> ( + let* obytes = Tree.to_value tree in + match obytes with + | None -> internal_error "Invalid children" state + | Some bytes -> ( + let* state, v = decode encoding bytes state in + match v with + | None -> return (state, None) + | Some v -> ( + let* state, l = aux children in + match l with + | None -> return (state, None) + | Some l -> return (state, Some ((key, v) :: l))))) + in + aux children + + let get_value ~default key encoding = + let open Syntax in + let* ov = find_value key encoding in + match ov with None -> return default | Some x -> return x + + let set_value key encoding value tree = + let open Lwt_syntax in + Data_encoding.Binary.to_bytes_opt encoding value |> function + | None -> internal_error "Internal_Error during encoding" tree + | Some bytes -> + let* tree = Tree.add tree key bytes in + return (tree, Some ()) + end + + open Monad + + module Make_var (P : sig + type t + + val name : string + + val initial : t + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + end) = + struct + let key = [P.name] + + let create = set_value key P.encoding P.initial + + let get = + let open Monad.Syntax in + let* v = find_value key P.encoding in + match v with + | None -> + (* This case should not happen if [create] is properly called. *) + return P.initial + | Some v -> return v + + let set = set_value key P.encoding + + let pp = + let open Monad.Syntax in + let* v = get in + return @@ fun fmt () -> Format.fprintf fmt "@[%s : %a@]" P.name P.pp v + end + + module Make_dict (P : sig + type t + + val name : string + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + end) = + struct + let key k = [P.name; k] + + let get k = find_value (key k) P.encoding + + let set k v = set_value (key k) P.encoding v + + let entries = children [P.name] P.encoding + + let pp = + let open Monad.Syntax in + let* l = entries in + let pp_elem fmt (key, value) = + Format.fprintf fmt "@[%s : %a@]" key P.pp value + in + return @@ fun fmt () -> Format.pp_print_list pp_elem fmt l + end + + module Make_deque (P : sig + type t + + val name : string + + val encoding : t Data_encoding.t + end) = + struct + (* + + A stateful deque. + + [[head; end[] is the index range for the elements of the deque. + + The length of the deque is therefore [end - head]. + + *) + + let head_key = [P.name; "head"] + + let end_key = [P.name; "end"] + + let get_head = get_value ~default:Z.zero head_key Data_encoding.z + + let set_head = set_value head_key Data_encoding.z + + let get_end = get_value ~default:(Z.of_int 0) end_key Data_encoding.z + + let set_end = set_value end_key Data_encoding.z + + let idx_key idx = [P.name; Z.to_string idx] + + let top = + let open Monad.Syntax in + let* head_idx = get_head in + let* end_idx = get_end in + let* v = find_value (idx_key head_idx) P.encoding in + if Z.(leq end_idx head_idx) then return None + else + match v with + | None -> (* By invariants of the Deque. *) assert false + | Some x -> return (Some x) + + let push x = + let open Monad.Syntax in + let* head_idx = get_head in + let head_idx' = Z.pred head_idx in + let* () = set_head head_idx' in + set_value (idx_key head_idx') P.encoding x + + let pop = + let open Monad.Syntax in + let* head_idx = get_head in + let* end_idx = get_end in + if Z.(leq end_idx head_idx) then return None + else + let* v = find_value (idx_key head_idx) P.encoding in + match v with + | None -> (* By invariants of the Deque. *) assert false + | Some x -> + let* () = remove (idx_key head_idx) in + let head_idx = Z.succ head_idx in + let* () = set_head head_idx in + return (Some x) + + let inject x = + let open Monad.Syntax in + let* end_idx = get_end in + let end_idx' = Z.succ end_idx in + let* () = set_end end_idx' in + set_value (idx_key end_idx) P.encoding x + + let to_list = + let open Monad.Syntax in + let* head_idx = get_head in + let* end_idx = get_end in + let rec aux l idx = + if Z.(lt idx head_idx) then return l + else + let* v = find_value (idx_key idx) P.encoding in + match v with + | None -> (* By invariants of deque *) assert false + | Some v -> aux (v :: l) (Z.pred idx) + in + aux [] (Z.pred end_idx) + + let clear = remove [P.name] + end + + module Current_tick = Make_var (struct + include Sc_rollup_tick_repr + + let name = "tick" + end) + + module Vars = Make_dict (struct + type t = int + + let name = "vars" + + let encoding = Data_encoding.int31 + + let pp fmt x = Format.fprintf fmt "%d" x + end) + + module Stack = Make_deque (struct + type t = int + + let name = "stack" + + let encoding = Data_encoding.int31 + end) + + module Code = Make_deque (struct + type t = instruction + + let name = "code" + + let encoding = + Data_encoding.( + union + [ + case + ~title:"push" + (Tag 0) + Data_encoding.int31 + (function IPush x -> Some x | _ -> None) + (fun x -> IPush x); + case + ~title:"add" + (Tag 1) + Data_encoding.unit + (function IAdd -> Some () | _ -> None) + (fun () -> IAdd); + case + ~title:"store" + (Tag 2) + Data_encoding.(string Plain) + (function IStore x -> Some x | _ -> None) + (fun x -> IStore x); + ]) + end) + + module Boot_sector = Make_var (struct + type t = string + + let name = "boot_sector" + + let initial = "" + + let encoding = Data_encoding.(string Plain) + + let pp fmt s = Format.fprintf fmt "%s" s + end) + + module Status = Make_var (struct + type t = status + + let initial = Halted + + let encoding = + let open Data_encoding in + let kind name = req "status" (constant name) in + let case_halted = + case + ~title:"Halted" + (Tag 0) + (obj1 (kind "halted")) + (function Halted -> Some () | _ -> None) + (fun () -> Halted) + in + let case_waiting_for_input_message = + case + ~title:"Waiting_for_input_message" + (Tag 1) + (obj1 (kind "waiting_for_input_message")) + (function Waiting_for_input_message -> Some () | _ -> None) + (fun () -> Waiting_for_input_message) + in + let case_waiting_for_reveal = + case + ~title:"Waiting_for_reveal" + (Tag 2) + (obj2 + (kind "waiting_for_reveal") + (req "reveal" Sc_rollup_PVM_sig.reveal_encoding)) + (function Waiting_for_reveal r -> Some ((), r) | _ -> None) + (fun ((), r) -> Waiting_for_reveal r) + in + let case_parsing = + case + ~title:"Parsing" + (Tag 3) + (obj1 (kind "parsing")) + (function Parsing -> Some () | _ -> None) + (fun () -> Parsing) + in + let case_evaluating = + case + ~title:"Evaluating" + (Tag 4) + (obj1 (kind "evaluating")) + (function Evaluating -> Some () | _ -> None) + (fun () -> Evaluating) + in + union + [ + case_halted; + case_waiting_for_input_message; + case_waiting_for_reveal; + case_parsing; + case_evaluating; + ] + + let name = "status" + + let string_of_status = function + | Halted -> "Halted" + | Waiting_for_input_message -> "Waiting for input message" + | Waiting_for_reveal reveal -> + Format.asprintf + "Waiting for reveal %a" + Sc_rollup_PVM_sig.pp_reveal + reveal + | Parsing -> "Parsing" + | Evaluating -> "Evaluating" + + let pp fmt status = Format.fprintf fmt "%s" (string_of_status status) + end) + + module Required_reveal = Make_var (struct + type t = PS.reveal option + + let initial = None + + let encoding = Data_encoding.option PS.reveal_encoding + + let name = "required_reveal" + + let pp fmt v = + match v with + | None -> Format.fprintf fmt "" + | Some h -> PS.pp_reveal fmt h + end) + + module Metadata = Make_var (struct + type t = Sc_rollup_metadata_repr.t option + + let initial = None + + let encoding = Data_encoding.option Sc_rollup_metadata_repr.encoding + + let name = "metadata" + + let pp fmt v = + match v with + | None -> Format.fprintf fmt "" + | Some v -> Sc_rollup_metadata_repr.pp fmt v + end) + + module Current_level = Make_var (struct + type t = Raw_level_repr.t + + let initial = Raw_level_repr.root + + let encoding = Raw_level_repr.encoding + + let name = "current_level" + + let pp = Raw_level_repr.pp + end) + + type dal_slots_list = Dal_slot_index_repr.t list + + let dal_slots_list_encoding = + Data_encoding.list Dal_slot_index_repr.encoding + + let pp_dal_slots_list = + Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.pp_print_string fmt ":") + Dal_slot_index_repr.pp + + type dal_parameters = { + attestation_lag : int32; + number_of_pages : int32; + tracked_slots : dal_slots_list; + } + + module Dal_parameters = Make_var (struct + type t = dal_parameters + + let initial = + (* This initial value is, from a semantic point of vue, equivalent to + have [None], as no slot is tracked. + + For the initial values of the fields, only [tracked_slots]'s content + matters. Setting it the empty set means that the rollup is not + subscribed to the DAL. *) + {attestation_lag = 1l; number_of_pages = 0l; tracked_slots = []} + + let encoding = + let open Data_encoding in + conv + (fun {attestation_lag; number_of_pages; tracked_slots} -> + (attestation_lag, number_of_pages, tracked_slots)) + (fun (attestation_lag, number_of_pages, tracked_slots) -> + {attestation_lag; number_of_pages; tracked_slots}) + (obj3 + (req "attestation_lag" int32) + (req "number_of_pages" int32) + (req "tracked_slots" dal_slots_list_encoding)) + + let name = "dal_parameters" + + let pp fmt {attestation_lag; number_of_pages; tracked_slots} = + Format.fprintf + fmt + "dal:%ld:%ld:%a" + attestation_lag + number_of_pages + pp_dal_slots_list + tracked_slots + end) + + module Dal_remaining_slots = Make_var (struct + type t = dal_slots_list + + let initial = [] + + let encoding = dal_slots_list_encoding + + let name = "dal_remaining_slots" + + let pp = pp_dal_slots_list + end) + + module Message_counter = Make_var (struct + type t = Z.t option + + let initial = None + + let encoding = Data_encoding.option Data_encoding.n + + let name = "message_counter" + + let pp fmt = function + | None -> Format.fprintf fmt "None" + | Some c -> Format.fprintf fmt "Some %a" Z.pp_print c + end) + + (** Store an internal message counter. This is used to distinguish + an unparsable external message and a internal message, which we both + treat as no-ops. *) + module Internal_message_counter = Make_var (struct + type t = Z.t + + let initial = Z.zero + + let encoding = Data_encoding.n + + let name = "internal_message_counter" + + let pp fmt c = Z.pp_print fmt c + end) + + let incr_internal_message_counter = + let open Monad.Syntax in + let* current_counter = Internal_message_counter.get in + Internal_message_counter.set (Z.succ current_counter) + + module Next_message = Make_var (struct + type t = string option + + let initial = None + + let encoding = Data_encoding.(option (string Plain)) + + let name = "next_message" + + let pp fmt = function + | None -> Format.fprintf fmt "None" + | Some s -> Format.fprintf fmt "Some %s" s + end) + + type parser_state = ParseInt | ParseVar | SkipLayout + + module Lexer_state = Make_var (struct + type t = int * int + + let name = "lexer_buffer" + + let initial = (-1, -1) + + let encoding = Data_encoding.(tup2 int31 int31) + + let pp fmt (start, len) = + Format.fprintf fmt "lexer.(start = %d, len = %d)" start len + end) + + module Parser_state = Make_var (struct + type t = parser_state + + let name = "parser_state" + + let initial = SkipLayout + + let encoding = + Data_encoding.string_enum + [ + ("ParseInt", ParseInt); + ("ParseVar", ParseVar); + ("SkipLayout", SkipLayout); + ] + + let pp fmt = function + | ParseInt -> Format.fprintf fmt "Parsing int" + | ParseVar -> Format.fprintf fmt "Parsing var" + | SkipLayout -> Format.fprintf fmt "Skipping layout" + end) + + module Parsing_result = Make_var (struct + type t = bool option + + let name = "parsing_result" + + let initial = None + + let encoding = Data_encoding.(option bool) + + let pp fmt = function + | None -> Format.fprintf fmt "n/a" + | Some true -> Format.fprintf fmt "parsing succeeds" + | Some false -> Format.fprintf fmt "parsing fails" + end) + + module Evaluation_result = Make_var (struct + type t = bool option + + let name = "evaluation_result" + + let initial = None + + let encoding = Data_encoding.(option bool) + + let pp fmt = function + | None -> Format.fprintf fmt "n/a" + | Some true -> Format.fprintf fmt "evaluation succeeds" + | Some false -> Format.fprintf fmt "evaluation fails" + end) + + module Output_counter = Make_var (struct + type t = Z.t + + let initial = Z.zero + + let name = "output_counter" + + let encoding = Data_encoding.n + + let pp = Z.pp_print + end) + + module Output = Make_dict (struct + type t = Sc_rollup_PVM_sig.output + + let name = "output" + + let encoding = Sc_rollup_PVM_sig.output_encoding + + let pp = Sc_rollup_PVM_sig.pp_output + end) + + let pp = + let open Monad.Syntax in + let* status_pp = Status.pp in + let* message_counter_pp = Message_counter.pp in + let* next_message_pp = Next_message.pp in + let* parsing_result_pp = Parsing_result.pp in + let* parser_state_pp = Parser_state.pp in + let* lexer_state_pp = Lexer_state.pp in + let* evaluation_result_pp = Evaluation_result.pp in + let* vars_pp = Vars.pp in + let* output_pp = Output.pp in + let* stack = Stack.to_list in + let* current_tick_pp = Current_tick.pp in + return @@ fun fmt () -> + Format.fprintf + fmt + "@[@;\ + %a@;\ + %a@;\ + %a@;\ + %a@;\ + %a@;\ + %a@;\ + %a@;\ + tick : %a@;\ + vars : %a@;\ + output :%a@;\ + stack : %a@;\ + @]" + status_pp + () + message_counter_pp + () + next_message_pp + () + parsing_result_pp + () + parser_state_pp + () + lexer_state_pp + () + evaluation_result_pp + () + current_tick_pp + () + vars_pp + () + output_pp + () + Format.(pp_print_list pp_print_int) + stack + end + + open State + + type state = State.state + + open Monad + + let initial_state ~empty = + let m = + let open Monad.Syntax in + let* () = Status.set Halted in + return () + in + let open Lwt_syntax in + let* state, _ = run m empty in + return state + + let install_boot_sector state boot_sector = + let m = + let open Monad.Syntax in + let* () = Boot_sector.set boot_sector in + return () + in + let open Lwt_syntax in + let* state, _ = run m state in + return state + + let state_hash state = + let context_hash = Tree.hash state in + Lwt.return @@ State_hash.context_hash_to_state_hash context_hash + + let pp state = + let open Lwt_syntax in + let* _, pp = Monad.run pp state in + match pp with + | None -> return @@ fun fmt _ -> Format.fprintf fmt "" + | Some pp -> + let* state_hash = state_hash state in + return (fun fmt () -> + Format.fprintf fmt "@[%a: %a@]" State_hash.pp state_hash pp ()) + + let boot = + let open Monad.Syntax in + let* () = Status.create in + let* () = Next_message.create in + let* () = Status.set (Waiting_for_reveal Reveal_metadata) in + return () + + let result_of ~default m state = + let open Lwt_syntax in + let* _, v = run m state in + match v with None -> return default | Some v -> return v + + let state_of m state = + let open Lwt_syntax in + let* s, _ = run m state in + return s + + let get_tick = result_of ~default:Sc_rollup_tick_repr.initial Current_tick.get + + let get_status ~is_reveal_enabled : status Monad.t = + let open Monad.Syntax in + let* status = Status.get in + let* current_block_level = Current_level.get in + (* We do not put the machine in a stuck condition if a kind of reveal + happens to not be supported. This is a sensible thing to do, as if + there is an off-by-one error in the WASM kernel one can do an + incorrect reveal, which can put the PVM in a stuck state with no way + to upgrade the kernel to fix the off-by-one. *) + let try_return_reveal candidate : status = + match (current_block_level, candidate) with + | _, Waiting_for_reveal candidate -> + let is_enabled = is_reveal_enabled ~current_block_level candidate in + if is_enabled then Waiting_for_reveal candidate + else + Waiting_for_reveal + (Reveal_raw_data Sc_rollup_reveal_hash.well_known_reveal_hash) + | _, _ -> candidate + in + return + @@ + match status with + | Waiting_for_reveal _ -> try_return_reveal status + | s -> s + + let is_input_state_monadic ~is_reveal_enabled = + let open Monad.Syntax in + let* status = get_status ~is_reveal_enabled in + match status with + | Waiting_for_input_message -> ( + let* level = Current_level.get in + let* counter = Message_counter.get in + match counter with + | Some n -> return (PS.First_after (level, n)) + | None -> return PS.Initial) + | Waiting_for_reveal (Reveal_raw_data _) -> ( + let* r = Required_reveal.get in + match r with + | None -> internal_error "Internal error: Reveal invariant broken" + | Some reveal -> return (PS.Needs_reveal reveal)) + | Waiting_for_reveal Reveal_metadata -> + return PS.(Needs_reveal Reveal_metadata) + | Waiting_for_reveal (Request_dal_page page) -> + return PS.(Needs_reveal (Request_dal_page page)) + | Waiting_for_reveal Reveal_dal_parameters -> + return PS.(Needs_reveal Reveal_dal_parameters) + | Halted | Parsing | Evaluating -> return PS.No_input_required + + let is_input_state ~is_reveal_enabled = + result_of ~default:PS.No_input_required + @@ is_input_state_monadic ~is_reveal_enabled + + let get_current_level state = + let open Lwt_syntax in + let* _state_, current_level = Monad.run Current_level.get state in + return current_level + + let get_status ~is_reveal_enabled : state -> status Lwt.t = + result_of ~default:Waiting_for_input_message (get_status ~is_reveal_enabled) + + let get_outbox outbox_level state = + let open Lwt_syntax in + let+ entries = result_of ~default:[] Output.entries state in + List.filter_map + (fun (_, msg) -> + if Raw_level_repr.(msg.PS.outbox_level = outbox_level) then Some msg + else None) + entries + + let get_code = result_of ~default:[] @@ Code.to_list + + let get_parsing_result = result_of ~default:None @@ Parsing_result.get + + let get_stack = result_of ~default:[] @@ Stack.to_list + + let get_var state k = (result_of ~default:None @@ Vars.get k) state + + let get_evaluation_result = result_of ~default:None @@ Evaluation_result.get + + let get_is_stuck = result_of ~default:None @@ is_stuck + + let start_parsing : unit t = + let open Monad.Syntax in + let* () = Status.set Parsing in + let* () = Parsing_result.set None in + let* () = Parser_state.set SkipLayout in + let* () = Lexer_state.set (0, 0) in + let* () = Code.clear in + return () + + (** Compute and set the next Dal page to request if any. Otherwise, request + the next inbox message. + + The value of [target] allows to compute the next page to request: either + the first one the PVM is subscribed to, or the one after the given + (slot_index, page_index) page. *) + let next_dal_page dal_params ~target = + let open Monad.Syntax in + let open Dal_slot_repr in + let module Index = Dal_slot_index_repr in + let* case = + match (dal_params, target) with + | {tracked_slots = []; _}, `First_page _published_level -> + (* PVM subscribed to no slot. *) + return `Inbox_message + | {tracked_slots = index :: rest; _}, `First_page published_level -> + (* Initiate the DAL data fetching process with the first page of the + first slot. *) + let* () = Dal_remaining_slots.set rest in + return (`Dal (published_level, index, 0)) + | ( {number_of_pages; _}, + `Page_after {Page.slot_id = {published_level; index}; page_index} ) + -> ( + (* We already read some DAL pages for the published level. Try one of + the following in this order: + - Attempt to move to the next page of the current slot; + - In case all pages have been read; attempt to move to the next slot; + - In case all slots have been read; request the next inbox message. *) + let page_index = page_index + 1 in + if Compare.Int.(page_index < Int32.to_int number_of_pages) then + return (`Dal (published_level, index, page_index)) + else + let* remaining_slots = Dal_remaining_slots.get in + match remaining_slots with + | index :: rest -> + let* () = Dal_remaining_slots.set rest in + return (`Dal (published_level, index, 0)) + | [] -> return `Inbox_message) + in + match case with + | `Dal (published_level, index, page_index) -> + let page_id = {Page.slot_id = {published_level; index}; page_index} in + let* () = Required_reveal.set @@ Some (Request_dal_page page_id) in + Status.set (Waiting_for_reveal (Request_dal_page page_id)) + | `Inbox_message -> + let* () = Required_reveal.set None in + Status.set Waiting_for_input_message + + (** Request a Dal page or an input message depending on the value of the given + [published_level] argument and on the content of the {Required_reveal.get}. + *) + let update_waiting_for_data_status = + let open Dal_slot_repr in + let module Index = Dal_slot_index_repr in + fun ?published_level () -> + let open Monad.Syntax in + let* dal_params = Dal_parameters.get in + if List.is_empty dal_params.tracked_slots then + (* This rollup doesn't track any DAL slot. *) + Status.set Waiting_for_input_message + else + let* required_reveal = Required_reveal.get in + (* Depending on whether [?published_level] is set, and on the value stored + in [required_reveal], the next data to request may either be a DAL page + or an inbox message. *) + match (published_level, required_reveal) with + | None, None -> + (* The default case is to request an inbox message. *) + Status.set Waiting_for_input_message + | Some published_level, None -> + (* We are explictely asked to start fetching DAL pages. *) + next_dal_page dal_params ~target:(`First_page published_level) + | Some published_level, Some (Request_dal_page page_id) -> + (* We are moving to the next level, and there are no explicit inbox + messages in the previous level. *) + let* remaining_slots = Dal_remaining_slots.get in + assert ( + let slot_id = page_id.Page.slot_id in + let page_index = page_id.Page.page_index in + Compare.Int.( + Int32.to_int + @@ Raw_level_repr.diff published_level slot_id.published_level + = 1 + && List.is_empty remaining_slots + && page_index = Int32.to_int dal_params.number_of_pages - 1)) ; + next_dal_page dal_params ~target:(`First_page published_level) + | None, Some (Request_dal_page page_id) -> + (* We are in the same level, fetch the next page. *) + next_dal_page dal_params ~target:(`Page_after page_id) + | _, Some Reveal_metadata | _, Some Reveal_dal_parameters -> + (* Should not happen. *) + assert false + | _, Some (Reveal_raw_data _) -> + (* Note that, providing a DAC input via a DAL page will interrupt + the interpretation of the next DAL pages of the same level, as the + content of [Required_reveal] is lost. We should use two + distinct states if we don't want this to happen. *) + let* () = Required_reveal.set None in + Status.set Waiting_for_input_message + + let set_inbox_message_monadic {PS.inbox_level; message_counter; payload} = + let open Monad.Syntax in + let deserialized = Sc_rollup_inbox_message_repr.deserialize payload in + let* payload = + match deserialized with + | Error _ -> return None + | Ok (External payload) -> return (Some payload) + | Ok (Internal (Transfer {payload; destination; _})) -> ( + let* () = incr_internal_message_counter in + let* (metadata : Sc_rollup_metadata_repr.t option) = Metadata.get in + match metadata with + | Some {address; _} when Address.(destination = address) -> ( + match Micheline.root payload with + | Bytes (_, payload) -> + let payload = Bytes.to_string payload in + return (Some payload) + | _ -> return None) + | _ -> return None) + | Ok (Internal (Protocol_migration _)) -> + let* () = incr_internal_message_counter in + return None + | Ok (Internal Start_of_level) -> + let* () = incr_internal_message_counter in + return None + | Ok (Internal End_of_level) -> + let* () = incr_internal_message_counter in + return None + | Ok (Internal (Info_per_level _)) -> + let* () = incr_internal_message_counter in + return None + in + match payload with + | Some payload -> + let* boot_sector = Boot_sector.get in + let msg = boot_sector ^ payload in + let* () = Current_level.set inbox_level in + let* () = Message_counter.set (Some message_counter) in + let* () = Next_message.set (Some msg) in + let* () = start_parsing in + return () + | None -> ( + let* () = Current_level.set inbox_level in + let* () = Message_counter.set (Some message_counter) in + match deserialized with + | Ok (Internal Start_of_level) -> ( + let* dal_params = Dal_parameters.get in + let inbox_level = Raw_level_repr.to_int32 inbox_level in + (* the [published_level]'s pages to request is [inbox_level - + attestation_lag - 1]. *) + let lvl = + Int32.sub (Int32.sub inbox_level dal_params.attestation_lag) 1l + in + match Raw_level_repr.of_int32 lvl with + | Error _ -> + (* Too early. We cannot request DAL data yet. *) + return () + | Ok published_level -> ( + let* metadata = Metadata.get in + match metadata with + | None -> + assert false + (* Setting Metadata should be the first input provided to the + PVM. *) + | Some {origination_level; _} -> + if Raw_level_repr.(origination_level >= published_level) + then + (* We can only fetch DAL data that are published after + the rollup's origination level. *) + Status.set Waiting_for_input_message + else + (* Start fetching DAL data for this [published_level]. *) + update_waiting_for_data_status ~published_level ())) + | _ -> Status.set Waiting_for_input_message) + + let reveal_monadic reveal_data = + (* + + The inbox cursor is unchanged as the message comes from the + outer world. + + We don't have to check that the data is the one we + expected as we decided to trust the initial witness. + + It is the responsibility of the rollup node to check the validity + of the [reveal_data] if it does not want to publish a wrong commitment. + + *) + let open Monad.Syntax in + match reveal_data with + | PS.Raw_data data -> + (* Notice that a multi-page transmission is possible by embedding + a continuation encoded as an optional hash in [data]. *) + let* () = Next_message.set (Some data) in + let* () = start_parsing in + return () + | PS.Metadata metadata -> + let* () = Metadata.set (Some metadata) in + let* () = Status.set Waiting_for_input_message in + return () + | PS.Dal_page None -> + (* We may either move to the next DAL page or to the next inbox + message. *) + update_waiting_for_data_status () + | PS.Dal_page (Some data) -> + let* () = Next_message.set (Some (Bytes.to_string data)) in + let* () = start_parsing in + return () + | PS.Dal_parameters _ -> + (* Should not happen as requesting DAL parameters is disabled + in the arith PVM. *) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6563 + Support reveal DAL parameters in arith PVM in order to test + the refutation game for revealing DAL parameters. *) + assert false + + let ticked m = + let open Monad.Syntax in + let* tick = Current_tick.get in + let* () = Current_tick.set (Sc_rollup_tick_repr.next tick) in + m + + let set_input_monadic input = + match input with + | PS.Inbox_message m -> set_inbox_message_monadic m + | PS.Reveal s -> reveal_monadic s + + let set_input input = set_input_monadic input |> ticked |> state_of + + let next_char = + let open Monad.Syntax in + Lexer_state.( + let* start, len = get in + set (start, len + 1)) + + let no_message_to_lex () = + internal_error "lexer: There is no input message to lex" + + let current_char = + let open Monad.Syntax in + let* start, len = Lexer_state.get in + let* msg = Next_message.get in + match msg with + | None -> no_message_to_lex () + | Some s -> + if Compare.Int.(start + len < String.length s) then + return (Some s.[start + len]) + else return None + + let lexeme = + let open Monad.Syntax in + let* start, len = Lexer_state.get in + let* msg = Next_message.get in + match msg with + | None -> no_message_to_lex () + | Some s -> + let* () = Lexer_state.set (start + len, 0) in + return (String.sub s start len) + + let push_int_literal = + let open Monad.Syntax in + let* s = lexeme in + match int_of_string_opt s with + | Some x -> Code.inject (IPush x) + | None -> (* By validity of int parsing. *) assert false + + let push_var = + let open Monad.Syntax in + let* s = lexeme in + Code.inject (IStore s) + + let start_evaluating : unit t = + let open Monad.Syntax in + let* () = Status.set Evaluating in + let* () = Evaluation_result.set None in + return () + + let stop_parsing outcome = + let open Monad.Syntax in + let* () = Parsing_result.set (Some outcome) in + start_evaluating + + let stop_evaluating outcome = + let open Monad.Syntax in + let* () = Evaluation_result.set (Some outcome) in + (* Once the evaluation of the current input is done, we either request the + next DAL page or the next inbox message. *) + update_waiting_for_data_status () + + let parse : unit t = + let open Monad.Syntax in + let produce_add = + let* (_ : string) = lexeme in + let* () = next_char in + let* () = Code.inject IAdd in + return () + in + let produce_int = + let* () = push_int_literal in + let* () = Parser_state.set SkipLayout in + return () + in + let produce_var = + let* () = push_var in + let* () = Parser_state.set SkipLayout in + return () + in + let is_digit d = Compare.Char.(d >= '0' && d <= '9') in + let is_letter d = + Compare.Char.((d >= 'a' && d <= 'z') || (d >= 'A' && d <= 'Z')) + in + let is_identifier_char d = + is_letter d || is_digit d + || Compare.Char.(d = ':') + || Compare.Char.(d = '%') + in + let* parser_state = Parser_state.get in + match parser_state with + | ParseInt -> ( + let* char = current_char in + match char with + | Some d when is_digit d -> next_char + | Some '+' -> + let* () = produce_int in + let* () = produce_add in + return () + | Some (' ' | '\n') -> + let* () = produce_int in + let* () = next_char in + return () + | None -> + let* () = push_int_literal in + stop_parsing true + | _ -> stop_parsing false) + | ParseVar -> ( + let* char = current_char in + match char with + | Some d when is_identifier_char d -> next_char + | Some '+' -> + let* () = produce_var in + let* () = produce_add in + return () + | Some (' ' | '\n') -> + let* () = produce_var in + let* () = next_char in + return () + | None -> + let* () = push_var in + stop_parsing true + | _ -> stop_parsing false) + | SkipLayout -> ( + let* char = current_char in + match char with + | Some (' ' | '\n') -> next_char + | Some '+' -> produce_add + | Some d when is_digit d -> + let* (_ : string) = lexeme in + let* () = next_char in + let* () = Parser_state.set ParseInt in + return () + | Some d when is_letter d -> + let* (_ : string) = lexeme in + let* () = next_char in + let* () = Parser_state.set ParseVar in + return () + | None -> stop_parsing true + | _ -> stop_parsing false) + + let output (destination, entrypoint) v = + let open Monad.Syntax in + let open Sc_rollup_outbox_message_repr in + let* counter = Output_counter.get in + let* () = Output_counter.set (Z.succ counter) in + let unparsed_parameters = + Micheline.(Int ((), Z.of_int v) |> strip_locations) + in + let transaction = {unparsed_parameters; destination; entrypoint} in + let message = Atomic_transaction_batch {transactions = [transaction]} in + let* outbox_level = Current_level.get in + let output = + Sc_rollup_PVM_sig.{outbox_level; message_index = counter; message} + in + Output.set (Z.to_string counter) output + + let identifies_target_contract x = + let open Option_syntax in + match String.split_on_char '%' x with + | destination :: entrypoint -> ( + match Contract_hash.of_b58check_opt destination with + | None -> + if Compare.String.(x = "out") then + return (Contract_hash.zero, Entrypoint_repr.default) + else fail + | Some destination -> + let* entrypoint = + match entrypoint with + | [] -> return Entrypoint_repr.default + | _ -> + let* entrypoint = + Non_empty_string.of_string (String.concat "" entrypoint) + in + let* entrypoint = + Entrypoint_repr.of_annot_lax_opt entrypoint + in + return entrypoint + in + return (destination, entrypoint)) + | [] -> fail + + let evaluate_preimage_request hash = + let open Monad.Syntax in + match Sc_rollup_reveal_hash.of_hex hash with + | None -> stop_evaluating false + | Some hash -> + let reveal : Sc_rollup_PVM_sig.reveal = Reveal_raw_data hash in + let* () = Required_reveal.set (Some reveal) in + let* () = Status.set (Waiting_for_reveal reveal) in + return () + + let evaluate_dal_parameters dal_directive = + let dal_params = + (* Dal pages import directive is [dal::::::...:]. See + mli file.*) + let open Option_syntax in + match String.split_on_char ':' dal_directive with + | number_of_slots :: attestation_lag :: number_of_pages :: tracked_slots + -> + let* number_of_slots = Int32.of_string_opt number_of_slots in + let* attestation_lag = Int32.of_string_opt attestation_lag in + let* number_of_pages = Int32.of_string_opt number_of_pages in + let* tracked_slots = + let rec aux acc sl = + match sl with + | [] -> return (List.rev acc) + | s :: rest -> + let* dal_slot_int = int_of_string_opt s in + let* dal_slot = + Dal_slot_index_repr.of_int_opt + ~number_of_slots:(Int32.to_int number_of_slots) + dal_slot_int + in + (aux [@tailcall]) (dal_slot :: acc) rest + in + aux [] tracked_slots + in + Some {attestation_lag; number_of_pages; tracked_slots} + | _ -> None + in + let open Monad.Syntax in + match dal_params with + | None -> stop_evaluating false + | Some dal_params -> + let* () = Dal_parameters.set dal_params in + Status.set Waiting_for_input_message + + let remove_prefix prefix input input_len = + let prefix_len = String.length prefix in + if + Compare.Int.(input_len > prefix_len) + && String.(equal (sub input 0 prefix_len) prefix) + then Some (String.sub input prefix_len (input_len - prefix_len)) + else None + + let evaluate = + let open Monad.Syntax in + let* i = Code.pop in + match i with + | None -> stop_evaluating true + | Some (IPush x) -> Stack.push x + | Some (IStore x) -> ( + (* When evaluating an instruction [IStore x], we start by checking if [x] + is a reserved directive: + - "hash:", to import a reveal data; + - "dal:::", to request a Dal page; + - "out" or "%", to add a message in the outbox. + Otherwise, the instruction is interpreted as a directive to store the + top of the PVM's stack into the variable [x]. + *) + let len = String.length x in + match remove_prefix "hash:" x len with + | Some hash -> evaluate_preimage_request hash + | None -> ( + match remove_prefix "dal:" x len with + | Some dal_directive -> evaluate_dal_parameters dal_directive + | None -> ( + let* v = Stack.top in + match v with + | None -> stop_evaluating false + | Some v -> ( + match identifies_target_contract x with + | Some contract_entrypoint -> output contract_entrypoint v + | None -> Vars.set x v)))) + | Some IAdd -> ( + let* v = Stack.pop in + match v with + | None -> stop_evaluating false + | Some x -> ( + let* v = Stack.pop in + match v with + | None -> stop_evaluating false + | Some y -> Stack.push (x + y))) + + let reboot = + let open Monad.Syntax in + let* () = Status.set Waiting_for_input_message in + let* () = Stack.clear in + let* () = Code.clear in + return () + + let eval_step = + let open Monad.Syntax in + let* x = is_stuck in + match x with + | Some _ -> reboot + | None -> ( + let* status = Status.get in + match status with + | Halted -> boot + | Waiting_for_input_message | Waiting_for_reveal _ -> ( + let* msg = Next_message.get in + match msg with + | None -> internal_error "An input state was not provided an input." + | Some _ -> start_parsing) + | Parsing -> parse + | Evaluating -> evaluate) + + let eval state = state_of (ticked eval_step) state + + let step_transition ~is_reveal_enabled input_given state = + let open Lwt_syntax in + let* request = is_input_state ~is_reveal_enabled state in + let error msg = state_of (internal_error msg) state in + + let* state = + match (request, input_given) with + | PS.No_input_required, None -> eval state + | PS.No_input_required, Some _ -> + error "Invalid set_input: expecting no input message but got one." + | (PS.Initial | PS.First_after _), Some (PS.Inbox_message _ as input) + | ( PS.Needs_reveal (Reveal_raw_data _), + Some (PS.Reveal (Raw_data _) as input) ) + | PS.Needs_reveal Reveal_metadata, Some (PS.Reveal (Metadata _) as input) + | ( PS.Needs_reveal (PS.Request_dal_page _), + Some (PS.Reveal (Dal_page _) as input) ) -> + (* For all the cases above, the input request matches the given input, so + we proceed by setting the input. *) + set_input input state + | PS.Needs_reveal Reveal_dal_parameters, _ -> + error + "Invalid set_input: revealing DAL parameters is not supported in \ + the arith PVM." + | (PS.Initial | PS.First_after _), _ -> + error "Invalid set_input: expecting inbox message, got a reveal." + | PS.Needs_reveal (Reveal_raw_data _hash), _ -> + error + "Invalid set_input: expecting a raw data reveal, got an inbox \ + message or a reveal metadata." + | PS.Needs_reveal Reveal_metadata, _ -> + error + "Invalid set_input: expecting a metadata reveal, got an inbox \ + message or a raw data reveal." + | PS.Needs_reveal (PS.Request_dal_page _), _ -> + error + "Invalid set_input: expecting a dal page reveal, got an inbox \ + message or a raw data reveal." + in + return (state, request) + + type error += Arith_proof_verification_failed + + let verify_proof ~is_reveal_enabled input_given proof = + let open Lwt_result_syntax in + let*! result = + Context.verify_proof + proof + (step_transition ~is_reveal_enabled input_given) + in + match result with + | None -> tzfail Arith_proof_verification_failed + | Some (_state, request) -> return request + + let produce_proof context ~is_reveal_enabled input_given state = + let open Lwt_result_syntax in + let*! result = + Context.produce_proof + context + state + (step_transition ~is_reveal_enabled input_given) + in + match result with + | Some (tree_proof, _requested) -> return tree_proof + | None -> tzfail Arith_proof_production_failed + + type output_proof = { + output_proof : Context.proof; + output_proof_state : hash; + output_proof_output : PS.output; + } + + let output_proof_encoding = + let open Data_encoding in + conv + (fun {output_proof; output_proof_state; output_proof_output} -> + (output_proof, output_proof_state, output_proof_output)) + (fun (output_proof, output_proof_state, output_proof_output) -> + {output_proof; output_proof_state; output_proof_output}) + (obj3 + (req "output_proof" Context.proof_encoding) + (req "output_proof_state" State_hash.encoding) + (req "output_proof_output" PS.output_encoding)) + + let output_of_output_proof s = s.output_proof_output + + let state_of_output_proof s = s.output_proof_state + + let output_key message_index = Z.to_string message_index + + let get_output ~outbox_level ~message_index ~message state = + let open Lwt_syntax in + let* _state, output = run (Output.get (output_key message_index)) state in + let output = + let output = Option.join output in + Option.bind + output + (fun + { + outbox_level = found_outbox_level; + message = found_message; + message_index = _; + } + -> + (* We can safely ignore the [message_index] since it is the key + used to fetch the messag from the storage. *) + let found_message_encoded = + Data_encoding.Binary.to_string_exn + Sc_rollup_outbox_message_repr.encoding + found_message + in + let given_message_encoded = + Data_encoding.Binary.to_string_exn + Sc_rollup_outbox_message_repr.encoding + message + in + if + Raw_level_repr.equal outbox_level found_outbox_level + && Compare.String.equal found_message_encoded given_message_encoded + then Some message + else None) + in + return (state, output) + + let verify_output_proof p = + let open Lwt_result_syntax in + let outbox_level = p.output_proof_output.outbox_level in + let message_index = p.output_proof_output.message_index in + let message = p.output_proof_output.message in + let transition = get_output ~outbox_level ~message_index ~message in + let*! result = Context.verify_proof p.output_proof transition in + match result with + | Some (_state, Some message) -> + return Sc_rollup_PVM_sig.{outbox_level; message_index; message} + | _ -> tzfail Arith_output_proof_production_failed + + let produce_output_proof context state output_proof_output = + let open Lwt_result_syntax in + let outbox_level = output_proof_output.Sc_rollup_PVM_sig.outbox_level in + let message_index = output_proof_output.message_index in + let message = output_proof_output.message in + let*! result = + Context.produce_proof context state + @@ get_output ~outbox_level ~message_index ~message + in + match result with + | Some (output_proof, Some message) -> + let*! output_proof_state = state_hash state in + return + { + output_proof; + output_proof_state; + output_proof_output = {outbox_level; message_index; message}; + } + | _ -> fail Arith_output_proof_production_failed + + module Internal_for_tests = struct + let insert_failure state = + let open Lwt_syntax in + let add n = Tree.add state ["failures"; string_of_int n] Bytes.empty in + let* n = Tree.length state ["failures"] in + add n + end +end + +module Protocol_implementation = Make (struct + module Tree = struct + include Context.Tree + + type tree = Context.tree + + type t = Context.t + + type key = string list + + type value = bytes + end + + type tree = Context.tree + + type proof = Context.Proof.tree Context.Proof.t + + let verify_proof p f = + let open Lwt_option_syntax in + let*? () = Result.to_option (Context_binary_proof.check_is_binary p) in + Lwt.map Result.to_option (Context.verify_tree_proof p f) + + let produce_proof _context _state _f = + (* Can't produce proof without full context*) + Lwt.return_none + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> State_hash.context_hash_to_state_hash hash + + let proof_before proof = kinded_hash_to_state_hash proof.Context.Proof.before + + let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + + let proof_encoding = Context.Proof_encoding.V2.Tree2.tree_proof_encoding +end) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.mli new file mode 100644 index 000000000000..aba54e9723ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_arith.mli @@ -0,0 +1,166 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides a temporary toy rollup to be used as a demo. *) + +(** + + This rollup is a stack machine equipped with addition. + + It processes postfix arithmetic expressions written as sequence of + (space separated) [int] and [+] using the following rules: + + - a number [x] is interpreted as pushing [x] on the stack ; + + - a variable [a] is interpreted as storing the topmost element of the + stack in the storage under the name "a" ; + + - a variable [out] is interpreted as adding a message to the outbox + containing a single transaction batch with the topmost element of the + stack as payload, the zero contract as destination, and a default + entrypoint ; + + - a symbol [+] pops two integers [x] and [y] and pushes [x + y] on + the stack ; + + - an input [hash:] is interpreted as a directive to request the DAC + data whose hash is ; + + - an input [dal::::::...:] is interpreted as a directive + to provide the DAL parameters to the PVM, where: + - is the number of slots + - is the attestation lag; + - is the number of pages; + - each is a slot to which the PVM subscribes to for [current level - + attestation_lag - 1]. + + DAL parameters can be set at most once. At each Start_of_level of some level + [L] inbox message and if DAL is enabled for the rollup (via the directive + above), the PVM will request the pages of the slots it is subscribed to. The + (attested) slots that are actually fetched at level [L] are those published + at level [L - e - 1]. Note that providing some DAC data via a DAL page will + prevent from fetching the subsequent DAL pages. + + If a message is not syntactically correct or does not evaluate + correctly, the machine stops its evaluation and waits for the next + message. + + The machine has a boot sector which is a mere string used a prefix + for each message. + + The module implements the {!Sc_rollup_PVM_sig.S}Î interface to be + used in the smart contract rollup infrastructure. + + The machine exposes extra operations to be used in the rollup node. + +*) +module type S = sig + include Sc_rollup_PVM_sig.S + + (** [parse_boot_sector s] builds a boot sector from its human + writable description. *) + val parse_boot_sector : string -> string option + + (** [pp_boot_sector fmt s] prints a human readable representation of + a boot sector. *) + val pp_boot_sector : Format.formatter -> string -> unit + + (** [pp state] returns a pretty-printer valid for [state]. *) + val pp : state -> (Format.formatter -> unit -> unit) Lwt.t + + (** [get_tick state] returns the current tick of [state]. *) + val get_tick : state -> Sc_rollup_tick_repr.t Lwt.t + + (** The machine has five possible statuses: *) + type status = + | Halted + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + | Parsing + | Evaluating + + (** [get_status ~is_reveal_enabled state] returns the machine status in [state]. *) + val get_status : + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + state -> + status Lwt.t + + (** [get_outbox outbox_level state] returns the outbox in [state] + for a given [outbox_level]. *) + val get_outbox : + Raw_level_repr.t -> state -> Sc_rollup_PVM_sig.output list Lwt.t + + (** The machine has only three instructions. *) + type instruction = + | IPush : int -> instruction + | IAdd : instruction + | IStore : string -> instruction + + (** [equal_instruction i1 i2] is [true] iff [i1] equals [i2]. *) + val equal_instruction : instruction -> instruction -> bool + + (** [pp_instruction fmt i] shows a human readable representation of [i]. *) + val pp_instruction : Format.formatter -> instruction -> unit + + (** [get_parsing_result state] is [Some true] if the current + message is syntactically correct, [Some false] when it + contains a syntax error, and [None] when the machine is + not in parsing state. *) + val get_parsing_result : state -> bool option Lwt.t + + (** [get_code state] returns the current code obtained by parsing + the current input message. *) + val get_code : state -> instruction list Lwt.t + + (** [get_stack state] returns the current stack. *) + val get_stack : state -> int list Lwt.t + + (** [get_var state x] returns the current value of variable [x]. + Returns [None] if [x] does not exist. *) + val get_var : state -> string -> int option Lwt.t + + (** [get_evaluation_result state] returns [Some true] if the current + message evaluation succeeds, [Some false] if it failed, and + [None] if the evaluation has not been done yet. *) + val get_evaluation_result : state -> bool option Lwt.t + + (** [get_is_stuck state] returns [Some err] if some internal error + made the machine fail during the last evaluation step. [None] + if no internal error occurred. When a machine is stuck, it + reboots, waiting for the next message to process. *) + val get_is_stuck : state -> string option Lwt.t +end + +module Protocol_implementation : + S + with type context = Context.t + and type state = Context.tree + and type proof = Context.Proof.tree Context.Proof.t + +module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : + S + with type context = Context.Tree.t + and type state = Context.tree + and type proof = Context.proof diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.ml new file mode 100644 index 000000000000..7672212c8f0b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.ml @@ -0,0 +1,117 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr + +module Hash = struct + include Smart_rollup.Commitment_hash + include Path_encoding.Make_hex (Smart_rollup.Commitment_hash) +end + +module V1 = struct + type t = { + compressed_state : State_hash.t; + inbox_level : Raw_level_repr.t; + predecessor : Hash.t; + number_of_ticks : Number_of_ticks.t; + } + + let pp fmt {compressed_state; inbox_level; predecessor; number_of_ticks} = + Format.fprintf + fmt + "compressed_state: %a@,\ + inbox_level: %a@,\ + predecessor: %a@,\ + number_of_ticks: %Ld" + State_hash.pp + compressed_state + Raw_level_repr.pp + inbox_level + Hash.pp + predecessor + (Number_of_ticks.to_value number_of_ticks) + + let encoding = + let open Data_encoding in + conv + (fun {compressed_state; inbox_level; predecessor; number_of_ticks} -> + (compressed_state, inbox_level, predecessor, number_of_ticks)) + (fun (compressed_state, inbox_level, predecessor, number_of_ticks) -> + {compressed_state; inbox_level; predecessor; number_of_ticks}) + (obj4 + (req "compressed_state" State_hash.encoding) + (req "inbox_level" Raw_level_repr.encoding) + (req "predecessor" Hash.encoding) + (req "number_of_ticks" Number_of_ticks.encoding)) + + let hash_uncarbonated commitment = + let commitment_bytes = + Data_encoding.Binary.to_bytes_exn encoding commitment + in + Hash.hash_bytes [commitment_bytes] + + (* For [number_of_messages] and [number_of_ticks] min_value is equal to zero. *) + let genesis_commitment ~origination_level ~genesis_state_hash = + let open Sc_rollup_repr in + let number_of_ticks = Number_of_ticks.zero in + { + compressed_state = genesis_state_hash; + inbox_level = origination_level; + predecessor = Hash.zero; + number_of_ticks; + } + + type genesis_info = {level : Raw_level_repr.t; commitment_hash : Hash.t} + + let genesis_info_encoding = + let open Data_encoding in + conv + (fun {level; commitment_hash} -> (level, commitment_hash)) + (fun (level, commitment_hash) -> {level; commitment_hash}) + (obj2 + (req "level" Raw_level_repr.encoding) + (req "commitment_hash" Hash.encoding)) +end + +type versioned = V1 of V1.t + +let versioned_encoding = + let open Data_encoding in + union + [ + case + ~title:"V1" + (Tag 0) + V1.encoding + (function V1 commitment -> Some commitment) + (fun commitment -> V1 commitment); + ] + +include V1 + +let of_versioned = function V1 commitment -> commitment [@@inline] + +let to_versioned commitment = V1 commitment [@@inline] diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.mli new file mode 100644 index 000000000000..0c0cf8c5dbe6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_repr.mli @@ -0,0 +1,101 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr + +module Hash : sig + include S.HASH with type t = Smart_rollup.Commitment_hash.t + + include Storage_description.INDEX with type t := t +end + +(** A commitment represents a claim about the state of the Inbox and PVM at + some Inbox level. + + More formally, a commitment is a claim that: + + {ul + {li assuming the PVM and Inbox are in a state implied by [predecessor]} + {li the PVM consumes all the messages until (and including) [inbox_level] + from the inbox ; } + {li the PVM advances to the state [compressed_state] over + [number_of_ticks] ticks. } + } + + Commitments are disjoint. The next correct commitment is a function of the + previous machine state and Inbox. + + [compressed_state] and [number_of_ticks] can be proven/disproven by PVM + execution, or equivalently, by an interactive proof game between + conflicting parties, such that a correct executor always wins the game. +*) +module V1 : sig + type t = { + compressed_state : State_hash.t; + inbox_level : Raw_level_repr.t; + predecessor : Hash.t; + number_of_ticks : Number_of_ticks.t; + } + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + + val hash_uncarbonated : t -> Hash.t + + (** [genesis_commitment ~origination_level ~genesis_state_hash] is the + commitment that the protocol "publish" and "cement" when originating a new + rollup. Each rollup have a different [genesis_commitment] because the + [compressed_state] is computed after the boot sector is set. It has the + following values: + + {ul {li [compressed_state] = [genesis_state_hash]} + {li [inbox_level] = [origination_level]} + {li [predecessor] = {!Hash.zero}} + {li [number_of_ticks] = {!Sc_rollup_repr.Number_of_ticks.min_value}}} + + where {!Sc_rollup_repr.Number_of_messages.min_value} and + {!Sc_rollup_repr.Number_of_ticks.min_value} are equal to [zero]. + + See {!Sc_rollup_storage.originate} for the usage. *) + val genesis_commitment : + origination_level:Raw_level_repr.t -> + genesis_state_hash:Sc_rollup_repr.State_hash.t -> + t + + (** The genesis of a rollup is characterized by the Tezos level of + the rollup origination, and the hash of the commitment computed + by the protocol to specialize the PVM initial state with the + provided boot sector. *) + type genesis_info = {level : Raw_level_repr.t; commitment_hash : Hash.t} + + val genesis_info_encoding : genesis_info Data_encoding.t +end + +(** Versioning, see {!Sc_rollup_data_version_sig.S} for more information. *) +include Sc_rollup_data_version_sig.S with type t = V1.t + +include module type of V1 with type t = V1.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.ml new file mode 100644 index 000000000000..567b966b7846 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.ml @@ -0,0 +1,139 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_errors +module Store = Storage.Sc_rollup +module Commitment = Sc_rollup_commitment_repr +module Commitment_hash = Commitment.Hash + +let get_commitment_opt_unsafe ctxt rollup commitment = + let open Lwt_result_syntax in + let* ctxt, res = Store.Commitments.find (ctxt, rollup) commitment in + return (res, ctxt) + +let get_commitment_unsafe ctxt rollup commitment = + let open Lwt_result_syntax in + let* res, ctxt = get_commitment_opt_unsafe ctxt rollup commitment in + match res with + | None -> tzfail (Sc_rollup_unknown_commitment commitment) + | Some commitment -> return (commitment, ctxt) + +let last_cemented_commitment ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, res = Store.Last_cemented_commitment.find ctxt rollup in + match res with + | None -> tzfail (Sc_rollup_does_not_exist rollup) + | Some lcc -> return (lcc, ctxt) + +let get_commitment ctxt rollup commitment = + let open Lwt_result_syntax in + (* Assert that a last cemented commitment exists. *) + let* _lcc, ctxt = last_cemented_commitment ctxt rollup in + get_commitment_unsafe ctxt rollup commitment + +let last_cemented_commitment_hash_with_level ctxt rollup = + let open Lwt_result_syntax in + let* commitment_hash, ctxt = last_cemented_commitment ctxt rollup in + let+ {inbox_level; _}, ctxt = + get_commitment_unsafe ctxt rollup commitment_hash + in + (commitment_hash, inbox_level, ctxt) + +let set_commitment_added ctxt rollup node new_value = + let open Lwt_result_syntax in + let* ctxt, res = Store.Commitment_added.find (ctxt, rollup) node in + match res with + | Some old_value -> + (* No need to re-add the read value *) + return (0, old_value, ctxt) + | None -> + let* ctxt, size_diff, _was_bound = + Store.Commitment_added.add (ctxt, rollup) node new_value + in + return (size_diff, new_value, ctxt) + +let get_predecessor_opt_unsafe ctxt rollup node = + let open Lwt_result_syntax in + let* commitment, ctxt = get_commitment_opt_unsafe ctxt rollup node in + return (Option.map (fun (c : Commitment.t) -> c.predecessor) commitment, ctxt) + +let check_if_commitments_are_related ctxt rollup ~descendant ~ancestor = + let open Lwt_result_syntax in + let rec aux ctxt current_commitment_hash = + if Commitment_hash.(current_commitment_hash = ancestor) then + return (true, ctxt) + else + let* predecessor_commitment_opt, ctxt = + get_predecessor_opt_unsafe ctxt rollup current_commitment_hash + in + match predecessor_commitment_opt with + | None -> return (false, ctxt) + | Some cch -> (aux [@ocaml.tailcall]) ctxt cch + in + aux ctxt descendant + +let hash ctxt commitment = + let open Result_syntax in + let* ctxt = + Raw_context.consume_gas + ctxt + Sc_rollup_costs.Constants.cost_serialize_commitment + in + let commitment_bytes_opt = + Data_encoding.Binary.to_bytes_opt + Sc_rollup_commitment_repr.encoding + commitment + in + let* commitment_bytes = + Option.to_result + ~none:(trace_of_error Sc_rollup_bad_commitment_serialization) + commitment_bytes_opt + in + let bytes_len = Bytes.length commitment_bytes in + let* ctxt = + Raw_context.consume_gas ctxt (Sc_rollup_costs.cost_hash_bytes ~bytes_len) + in + return (ctxt, Sc_rollup_commitment_repr.Hash.hash_bytes [commitment_bytes]) + +module Internal_for_tests = struct + let get_cemented_commitments_with_levels ctxt rollup = + let open Lwt_result_syntax in + let rec aux ctxt commitments_with_levels commitment_hash = + let* commitment_opt, ctxt = + get_commitment_opt_unsafe ctxt rollup commitment_hash + in + match commitment_opt with + | None -> return (commitments_with_levels, ctxt) + | Some {predecessor; inbox_level; _} -> + (aux [@ocaml.tailcall]) + ctxt + ((commitment_hash, inbox_level) :: commitments_with_levels) + predecessor + in + let* lcc_hash, ctxt = last_cemented_commitment ctxt rollup in + let+ commitments_with_levels, ctxt = aux ctxt [] lcc_hash in + (commitments_with_levels, ctxt) +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.mli new file mode 100644 index 000000000000..c2b4fd8ad40a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_commitment_storage.mli @@ -0,0 +1,242 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Defines storage for Smart Contract Optimistic Rollups. + + {2 Commitments} + + [Commitment]s are stored directly in the L1 context. Commitments are + immutable and content-addressed, and can be indexed by a [Commitment_hash]. + + A commitment represents a claim about the state of a PVM. + + We also keep auxiliary state about each commitment, namely: + + {ul + {li When it was first added.} + {li Its current number of stakers.} + } + + This auxiliary data is not part of the commitment itself. They represent + information that the L1 knows about the claim, not the claim itself. + + {3 Predecessors and Boot state} + Each commitment contains the hash of its {i predecessor}. Multiple + commitments can have the same predecessor. Therefore, commitments form + a Merkle tree. + + Conceptually the root of this tree is the [Commitment_hash.zero]. This + commitment claims that the PVM (Proof-generating Virtual Machine) is in a + pre-boot state and waiting to start booting by interpreting the boot sector with + respect to the Machine semantics. + + {3 Cemented and Disputable commitments} + Commitments accepted as true by the protocol are referred to as Cemented. + A commitment that is not cemented is said to be disputable. + + {3 Stakers} + The Stakers table maps Stakers (implicit accounts) to commitments hashes. + + Let [Stakers(S)] mean "looking up the key S in [Stakers]". + + A staker [S] is directly staked on [C] if [Stakers(S) = C]. A staker [S] + is indirectly staked on [C] if [C] is an ancestor of [Stakers(S)] in the commitment tree. + + {3 Dispute} + Commitments that have at least one sibling are referred to as Disputed. + More formally, a commitment C is disputed if at least one staker is not + (directly or indirectly) staked on C. + + {3 Dispute resolution} + The rollup protocol ensures that all disputes are resolved before cementing + a commitment. Therefore, cemented commitments form a list rather than a tree. + + In the context we only store the Last Cemented Commitment (LCC), which is + by definition a descendant of [zero]. We also store all Disputable + commitments that have at least one Staker. + + For example, assuming the full set of commitments for a rollup + looks like this: + + {[ + LCC staker1 staker2 + | | | + | V | + V --c3 | + zero--c1 --c2--/ | + \ V + --c4------ c5 + ]} + then commitments [c2..c5] will be stored in the context. + + {3 Conflicts} + + Let Commitments(S) be the set of commitments directly staked on by staker S. + + Two stakers A and B are: + + {ul + {li In total agreement iff Commitments(A) = Commitments(B).} + {li In partial agreement iff either Commitments(A) ⊂ Commitments(B), or + Commitments(B) ⊂ Commitments(A).} + {li In conflict iff they are neither in total or partial agreement.}} + + We can further refine a conflict to note what they are in conflict about, + e.g. they may be in conflict about the inbox, about execution, or both. We + can resolve conflicts by first resolving the conflict about inbox, then + about execution (since execution is irrelevant if the inbox is not + correct). + *) + +module Commitment = Sc_rollup_commitment_repr +module Commitment_hash = Commitment.Hash + +(** [last_cemented_commitment context rollup] returns the last cemented + commitment of the rollup. + + If no commitments have been cemented, the rollup is said to be in a + pre-boot state, and [last_cemented_commitment = Commitment_hash.zero]. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist}} *) +val last_cemented_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + (Commitment_hash.t * Raw_context.t) tzresult Lwt.t + +(** [last_cemented_commitment_hash_with_level ctxt sc_rollup] returns the hash + and level of the last cemented commitment (lcc) for [sc_rollup]. If the + rollup exists but no lcc exists, the initial commitment + [Sc_rollup.Commitment.zero] together with the rollup origination level is + returned. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist}} +*) +val last_cemented_commitment_hash_with_level : + Raw_context.t -> + Sc_rollup_repr.t -> + (Commitment_hash.t * Raw_level_repr.t * Raw_context.t) tzresult Lwt.t + +(** [get_commitment context rollup commitment_hash] returns the commitment with + the given hash. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_unknown_commitment] if [commitment] does not exist} + } +*) +val get_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + Commitment_hash.t -> + (Commitment.t * Raw_context.t) tzresult Lwt.t + +(** [get_commitment_opt_unsafe context rollup commitment_hash] returns an + [Option.t] which is either a defined value containing the commitment with + the given hash, or `None` if such a commitment does not exist. This + function *must* be called only after they have checked for the existence + of the rollup, and therefore it is not necessary for it to check for the + existence of the rollup again. Otherwise, use the safe function + {!get_commitment}. +*) +val get_commitment_opt_unsafe : + Raw_context.t -> + Sc_rollup_repr.t -> + Commitment_hash.t -> + (Commitment.t Option.t * Raw_context.t) tzresult Lwt.t + +(** [get_commitment_unsafe context rollup commitment_hash] returns the commitment + with the given hash. + This function *must* be called only after they have checked for the existence + of the rollup, and therefore it is not necessary for it to check for the + existence of the rollup again. Otherwise, use the safe function + {!get_commitment}. + + May fail with: + {ul + {li [Sc_rollup_unknown_commitment] if [commitment] does not exist} + } +*) +val get_commitment_unsafe : + Raw_context.t -> + Sc_rollup_repr.t -> + Commitment_hash.t -> + (Commitment.t * Raw_context.t) tzresult Lwt.t + +(** [set_commitment_added ctxt rollup node current] sets the commitment + addition time of [node] to [current] iff the commitment time was + not previously set, and leaves it unchanged otherwise. + *) +val set_commitment_added : + Raw_context.t -> + Sc_rollup_repr.t -> + Commitment_hash.t -> + Raw_level_repr.t -> + (int * Raw_level_repr.t * Raw_context.t) tzresult Lwt.t + +(** [get_predecessor_opt_unsafe ctxt rollup commitment_hash] returns an + [Option.t] value containing the [rollup] commitment predecessor of + [commitment_hash] in the [ctxt], if any. It does not check for the + existence of the [rollup]. *) +val get_predecessor_opt_unsafe : + Raw_context.t -> + Sc_rollup_repr.t -> + Commitment_hash.t -> + (Commitment_hash.t Option.t * Raw_context.t) tzresult Lwt.t + +(** [check_if_commitments_are_related ~descendant ~ancestor] checks whether a + commitment with hash [~ancestor] exists as a predecessor of [~descendant], + among the list of commitments stored for [rollup] in [ctxt]. *) +val check_if_commitments_are_related : + Raw_context.t -> + Sc_rollup_repr.t -> + descendant:Commitment_hash.t -> + ancestor:Commitment_hash.t -> + (bool * Raw_context.t) tzresult Lwt.t + +(** Hash a commitment and account for gas spent. *) +val hash : + Raw_context.t -> Commitment.t -> (Raw_context.t * Commitment_hash.t) tzresult + +module Internal_for_tests : sig + (** [get_cemented_commitments_with_levels ctxt rollup] returns a list of all + cemented commitment hashes and corresponding inbox levels that are present + in the storage, ordered by inbox level. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + } +*) + val get_cemented_commitments_with_levels : + Raw_context.t -> + Sc_rollup_repr.t -> + ((Commitment_hash.t * Raw_level_repr.t) list * Raw_context.t) tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.ml new file mode 100644 index 000000000000..17354d9db833 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.ml @@ -0,0 +1,129 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Sc_rollup_costs_generated + +module Constants = struct + (* equal to Michelson_v1_gas.Cost_of.Unparsing.contract_optimized *) + let cost_decoding_contract_optimized = S.safe_int 70 + + (* equal to Michelson_v1_gas.Cost_of.Unparsing.key_hash_optimized *) + let cost_decoding_key_hash_optimized = S.safe_int 70 + + (* Set to the cost of encoding a pkh defined in {!Michelson_v1_gas} divided + by the number of characters of a pkh, with the result rounded up, i.e. + 70/20 + 1. + To be updated when benchmarking is completed. *) + let cost_encode_string_per_byte = S.safe_int 4 + + (* Cost of serializing a state hash. *) + let cost_serialize_state_hash = + let len = S.safe_int State_hash.size in + S.Syntax.(cost_encode_string_per_byte * len) + + (* Cost of serializing a commitment hash. *) + let cost_serialize_commitment_hash = + let len = S.safe_int Sc_rollup_commitment_repr.Hash.size in + S.Syntax.(cost_encode_string_per_byte * len) + + (* Cost of serializing a commitment. The cost of serializing the level and + number of ticks (both int32) is negligible. *) + let cost_serialize_commitment = + S.Syntax.(cost_serialize_state_hash + cost_serialize_commitment_hash) + + (* Cost of serializing an operation hash. *) + let cost_serialize_operation_hash = + let len = S.safe_int Operation_hash.size in + S.Syntax.(cost_encode_string_per_byte * len) + + (* Cost of serializing a nonce. The cost of serializing the index (an int32) + is negligible. *) + let cost_serialize_nonce = cost_serialize_operation_hash +end + +(* Reusing model from {!Ticket_costs.has_tickets_of_ty_cost}. *) +let is_valid_parameters_ty_cost ~ty_size = + let open S.Syntax in + let fixed_cost = S.safe_int 10 in + let coeff = S.safe_int 6 in + fixed_cost + (coeff * ty_size) + +let cost_serialize_internal_inbox_message + (internal_inbox_message : + Sc_rollup_inbox_message_repr.internal_inbox_message) = + match internal_inbox_message with + | Transfer {payload; sender = _; source = _; destination = _} -> + let lexpr = Script_repr.lazy_expr payload in + let expr_cost = Script_repr.force_bytes_cost lexpr in + S.Syntax.( + expr_cost + Constants.cost_decoding_contract_optimized + + Constants.cost_decoding_key_hash_optimized) + | Start_of_level -> Saturation_repr.zero + | End_of_level -> Saturation_repr.zero + | Protocol_migration _ -> Saturation_repr.zero + | Info_per_level _ -> Saturation_repr.zero + +let cost_deserialize_output_proof ~bytes_len = + cost_Sc_rollup_deserialize_output_proof_benchmark bytes_len + +let cost_serialize_external_inbox_message ~bytes_len = + let len = S.safe_int bytes_len in + S.Syntax.(Constants.cost_encode_string_per_byte * len) + +(* Equal to Michelson_v1_gas.Cost_of.Interpreter.blake2b. *) +let cost_hash_bytes ~bytes_len = + let open S.Syntax in + let v0 = S.safe_int bytes_len in + S.safe_int 430 + v0 + (v0 lsr 3) + +let cost_compare = Michelson_v1_gas_costs.cost_N_ICompare + +let cost_search_in_tick_list len tick_size = + let open S.Syntax in + S.safe_int len * cost_compare tick_size tick_size + +let cost_check_dissection ~number_of_states ~tick_size ~hash_size = + let open S.Syntax in + cost_search_in_tick_list number_of_states tick_size + + (S.safe_int 2 * cost_compare hash_size hash_size) + +let cost_add_message ~current_index ~msg_len = + let open S.Syntax in + let hash_cell_cost = + Skip_list_costs.model_hash_cell_computed_backpointers_count + ~index:current_index + in + let hash_content_cost = cost_hash_bytes ~bytes_len:msg_len in + let next_cell_cost = + Skip_list_costs.model_next ~length:(Z.succ current_index) + in + hash_cell_cost + hash_content_cost + next_cell_cost + +let cost_verify_output_proof ~bytes_len = + cost_Sc_rollup_verify_output_proof_benchmark bytes_len + +let cost_install_boot_sector_in_wasm_pvm ~boot_sector_size_in_bytes = + cost_Sc_rollup_install_boot_sector_benchmark boot_sector_size_in_bytes diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.mli new file mode 100644 index 000000000000..9544cc01b788 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs.mli @@ -0,0 +1,91 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module contains constants and utility functions for gas metering + functions used when handling SC rollups operations in context. *) + +module Constants : sig + val cost_serialize_state_hash : Gas_limit_repr.cost + + val cost_serialize_commitment_hash : Gas_limit_repr.cost + + val cost_serialize_commitment : Gas_limit_repr.cost + + val cost_serialize_nonce : Gas_limit_repr.cost +end + +(** [is_valid_parameters_ty_cost ty] returns the cost of checking whether a type + is a valid sc rollup parameter. *) +val is_valid_parameters_ty_cost : + ty_size:'a Saturation_repr.t -> Saturation_repr.may_saturate Saturation_repr.t + +(** [cost_serialize_internal_inbox_message internal_inbox_message] is the cost + of the serialization of an internal inbox message. It's equal to the cost of + serializing the script expression, with {!Script_repr.force_bytes_cost} plus + a fixed amount for the serialized addresses. + + It traverses the payload expression to find the precise cost. It is safe to + use {!Script_repr.force_bytes_cost} because the payload of an internal inbox + message is bounded. +*) +val cost_serialize_internal_inbox_message : + Sc_rollup_inbox_message_repr.internal_inbox_message -> Gas_limit_repr.cost + +(** [cost_deserialize_output_proof ~bytes_len] is the cost of the + deserialization of an output proof. *) +val cost_deserialize_output_proof : bytes_len:int -> Gas_limit_repr.cost + +(** [cost_serialize_external_inbox_message ~bytes_len] is the cost of the + serialization of an external inbox message of length [bytes_len]. It is + equal to the estimated cost of encoding a byte multiplied by [bytes_len]. *) +val cost_serialize_external_inbox_message : bytes_len:int -> Gas_limit_repr.cost + +(** [cost_hash_bytes ~bytes_len] is the cost of hashing [bytes_len] bytes. *) +val cost_hash_bytes : bytes_len:int -> Gas_limit_repr.cost + +(** [cost_check_dissection ~number_of_states ~tick_size ~hash_size] is the cost + of checking that a dissection with a given [number_of_states] used in a + refutation game is well-formed. This includes the comparison of a linear + number of ticks as well as the verification of two hashes of given + [hash_size]. *) +val cost_check_dissection : + number_of_states:int -> tick_size:int -> hash_size:int -> Gas_limit_repr.cost + +(** [cost_verify_output_proof ~bytes_len] is the cost of verifying an output + proof of length [bytes_len]. *) +val cost_verify_output_proof : bytes_len:int -> Gas_limit_repr.cost + +(** [cost_add_message ~new_cell_index ~msg_len] returns the cost of adding a + message of length [msg_len] to a sc-rollup inbox. This function is used + internally in the [Sc_rollup_storage] module and covers the function + {!Sc_rollup_inbox_merkelized_payload_hashes_repr.add_payload} *) +val cost_add_message : current_index:Z.t -> msg_len:int -> Gas_limit_repr.cost + +(** [cost_install_boot_sector_in_wasm_pvm ~boot_sector_size_in_bytes] + returns the cost of installing a boot sector in an empty WASM PVM + state. This function is used in the implementation of the + origination. *) +val cost_install_boot_sector_in_wasm_pvm : + boot_sector_size_in_bytes:int -> Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs_generated.ml new file mode 100644 index 000000000000..3ab66fdb763e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_costs_generated.ml @@ -0,0 +1,28 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model sc_rollup/Sc_rollup_deserialize_output_proof_benchmark *) +(* fun size -> max 10 (7100. + (6. * size)) *) +let cost_Sc_rollup_deserialize_output_proof_benchmark size = + let size = S.safe_int size in + (size * S.safe_int 6) + S.safe_int 7100 + +(* model sc_rollup/Sc_rollup_install_boot_sector_benchmark *) +(* fun size -> max 10 (13550. + (3.5 * size)) *) +let cost_Sc_rollup_install_boot_sector_benchmark size = + let size = S.safe_int size in + (size lsr 1) + (size * S.safe_int 3) + S.safe_int 13550 + +(* model sc_rollup/Sc_rollup_verify_output_proof_benchmark *) +(* fun size -> max 10 (103450. + (7. * size)) *) +let cost_Sc_rollup_verify_output_proof_benchmark size = + let size = S.safe_int size in + (size * S.safe_int 7) + S.safe_int 103450 diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.ml new file mode 100644 index 000000000000..932b4fa8c745 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.ml @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Marigold *) +(* *) +(*****************************************************************************) + +type t = { + number_of_slots : int64; + attestation_lag : int64; + slot_size : int64; + page_size : int64; +} + +let pp ppf {number_of_slots; attestation_lag; slot_size; page_size} = + Format.fprintf + ppf + "number_of_slots: %Ld ; attestation_lag: %Ld ; slot_size: %Ld ; page_size: \ + %Ld" + number_of_slots + attestation_lag + slot_size + page_size + +let equal t1 t2 = + Compare.Int64.( + t1.attestation_lag = t2.attestation_lag + && t1.slot_size = t2.slot_size + && t1.page_size = t2.page_size) + +let encoding = + let open Data_encoding in + conv + (fun {number_of_slots; attestation_lag; slot_size; page_size} -> + (number_of_slots, attestation_lag, slot_size, page_size)) + (fun (number_of_slots, attestation_lag, slot_size, page_size) -> + {number_of_slots; attestation_lag; slot_size; page_size}) + (obj4 + (req "number_of_slots" int64) + (req "attestation_lag" int64) + (req "slot_size" int64) + (req "page_size" int64)) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.mli new file mode 100644 index 000000000000..b0b82bb3d464 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dal_parameters_repr.mli @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Marigold *) +(* *) +(*****************************************************************************) + +(** DAL related parameters for the PVMs. *) + +(** DAL related parameters that would be useful to the kernel. These parameters are a + subset of the DAL parametric constants defined in {!Constants_parametric_repr}. + We use [int64] so they should be "large enough" to accommodate encoding changes + of types in {!Constants_parametric_repr} *) +type t = { + number_of_slots : int64; + attestation_lag : int64; + slot_size : int64; + page_size : int64; +} + +(** Pretty-printer for the parameters. *) +val pp : Format.formatter -> t -> unit + +(** Equality of the parameters. *) +val equal : t -> t -> bool + +(** Encoding of the parameters. *) +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_data_version_sig.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_data_version_sig.ml new file mode 100644 index 000000000000..efdf5466e936 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_data_version_sig.ml @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The values are versioned, to let the possibility to modify + the values in future iterations of the protocol. + + We allow the possibility to modify the values by introducing + a {!S.versioned} value that is the only values written in the storage. + + In future versions, the versioning is supposed to let us reinterpret old + stored values within the new protocol implementation. That is, each + access to the storage will transform old stored values to the + current version. +*) + +module type S = sig + type t + + type versioned + + val versioned_encoding : versioned Data_encoding.t + + val of_versioned : versioned -> t + + val to_versioned : t -> versioned +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.ml new file mode 100644 index 000000000000..534ce8fb6016 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.ml @@ -0,0 +1,322 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr + +type t = {state_hash : State_hash.t option; tick : Sc_rollup_tick_repr.t} + +let equal {state_hash; tick} chunk2 = + Option.equal State_hash.equal state_hash chunk2.state_hash + && Sc_rollup_tick_repr.equal tick chunk2.tick + +let encoding = + let open Data_encoding in + conv + (fun {state_hash; tick} -> (state_hash, tick)) + (fun (state_hash, tick) -> {state_hash; tick}) + (obj2 + (opt "state" State_hash.encoding) + (req "tick" Sc_rollup_tick_repr.encoding)) + +type error += + | (* `Temporary *) + Dissection_number_of_sections_mismatch of { + expected : Z.t; + given : Z.t; + } + | (* `Permanent *) Dissection_invalid_number_of_sections of Z.t + | (* `Temporary *) + Dissection_start_hash_mismatch of { + expected : Sc_rollup_repr.State_hash.t option; + given : Sc_rollup_repr.State_hash.t option; + } + | (* `Temporary *) + Dissection_stop_hash_mismatch of + Sc_rollup_repr.State_hash.t option + | (* `Temporary *) + Dissection_edge_ticks_mismatch of { + dissection_start_tick : Sc_rollup_tick_repr.t; + dissection_stop_tick : Sc_rollup_tick_repr.t; + chunk_start_tick : Sc_rollup_tick_repr.t; + chunk_stop_tick : Sc_rollup_tick_repr.t; + } + | (* `Permanent *) Dissection_ticks_not_increasing + | (* `Permanent *) Dissection_invalid_distribution of Z.t + | (* `Permanent *) Dissection_invalid_successive_states_shape + +let pp_state_hash = + let open Format in + pp_print_option ~none:(fun ppf () -> fprintf ppf "None") State_hash.pp + +let pp_hash_opt fmt = function + | None -> Format.fprintf fmt "None" + | Some x -> Sc_rollup_repr.State_hash.pp fmt x + +let pp ppf {state_hash; tick} = + let open Format in + fprintf + ppf + "State hash:%a@ Tick: %a" + pp_state_hash + state_hash + Sc_rollup_tick_repr.pp + tick + +let default_check_sections_number ~default_number_of_sections + ~number_of_sections ~dist = + let open Result_syntax in + let number_of_sections = Z.of_int number_of_sections in + let default_number_of_sections = Z.of_int default_number_of_sections in + let should_be_equal_to expected = + Dissection_number_of_sections_mismatch + {expected; given = number_of_sections} + in + if Compare.Z.(default_number_of_sections <= dist) then + error_unless + Compare.Z.(number_of_sections = default_number_of_sections) + (should_be_equal_to default_number_of_sections) + else if Compare.Z.(dist > Z.one) then + error_unless Compare.Z.(number_of_sections = dist) (should_be_equal_to dist) + else tzfail (Dissection_invalid_number_of_sections number_of_sections) + +let default_check ~section_maximum_size ~check_sections_number + ~default_number_of_sections ~start_chunk ~stop_chunk dissection = + let open Result_syntax in + let number_of_sections = Compare.Int.max 0 (List.length dissection - 1) in + let dist = Sc_rollup_tick_repr.distance start_chunk.tick stop_chunk.tick in + let* () = + check_sections_number ~default_number_of_sections ~number_of_sections ~dist + in + let* () = + match (List.hd dissection, List.last_opt dissection) with + | Some {state_hash = a; tick = a_tick}, Some {state_hash = b; tick = b_tick} + -> + let* () = + error_unless + (Option.equal State_hash.equal a start_chunk.state_hash + && not (Option.is_none a)) + (Dissection_start_hash_mismatch + {expected = start_chunk.state_hash; given = a}) + in + let* () = + error_unless + (not (Option.equal State_hash.equal b stop_chunk.state_hash)) + ((* If the [b] state is equal to [stop_chunk], that means we + agree on the after state of the section. But, we're trying + to dispute it, it doesn't make sense. *) + Dissection_stop_hash_mismatch + stop_chunk.state_hash) + in + Sc_rollup_tick_repr.( + error_unless + (a_tick = start_chunk.tick && b_tick = stop_chunk.tick) + (Dissection_edge_ticks_mismatch + { + dissection_start_tick = a_tick; + dissection_stop_tick = b_tick; + chunk_start_tick = start_chunk.tick; + chunk_stop_tick = stop_chunk.tick; + })) + | _ -> + (* This case is probably already handled by the + [Dissection_invalid_number_of_sections] returned above *) + tzfail + (Dissection_invalid_number_of_sections (Z.of_int number_of_sections)) + in + let rec traverse states = + match states with + | {state_hash = None; _} :: {state_hash = Some _; _} :: _ -> + tzfail Dissection_invalid_successive_states_shape + | {tick; _} :: ({tick = next_tick; state_hash = _} as next) :: others -> + if Sc_rollup_tick_repr.(tick < next_tick) then + let incr = Sc_rollup_tick_repr.distance tick next_tick in + if Z.(leq incr section_maximum_size) then traverse (next :: others) + else tzfail (Dissection_invalid_distribution section_maximum_size) + else tzfail Dissection_ticks_not_increasing + | _ -> return_unit + in + traverse dissection + +let () = + let description = "Mismatch in the number of sections in the dissection" in + register_error_kind + `Temporary + ~id:"smart_rollup_dissection_number_of_sections_mismatch" + ~title:description + ~description + ~pp:(fun ppf (expected, given) -> + Format.fprintf + ppf + "The number of sections must be equal to %a instead of %a" + Z.pp_print + expected + Z.pp_print + given) + Data_encoding.(obj2 (req "expected" n) (req "given" n)) + (function + | Dissection_number_of_sections_mismatch {expected; given} -> + Some (expected, given) + | _ -> None) + (fun (expected, given) -> + Dissection_number_of_sections_mismatch {expected; given}) ; + let description = "Invalid number of sections in the dissection" in + register_error_kind + `Permanent + ~id:"smart_rollup_dissection_invalid_number_of_sections" + ~title:description + ~description + ~pp:(fun ppf n -> + Format.fprintf + ppf + "A dissection with %a sections can never be valid" + Z.pp_print + n) + Data_encoding.(obj1 (req "value" n)) + (function Dissection_invalid_number_of_sections n -> Some n | _ -> None) + (fun n -> Dissection_invalid_number_of_sections n) ; + let description = "Mismatch in the start hash of the dissection" in + register_error_kind + `Temporary + ~id:"smart_rollup_dissection_start_hash_mismatch" + ~title:description + ~description + ~pp:(fun ppf (given, expected) -> + match given with + | None -> Format.fprintf ppf "The start hash must not be None" + | Some _ -> + Format.fprintf + ppf + "The start hash should be equal to %a, but the provided hash is %a" + pp_hash_opt + expected + pp_hash_opt + given) + Data_encoding.( + obj2 + (req "expected" (option Sc_rollup_repr.State_hash.encoding)) + (req "given" (option Sc_rollup_repr.State_hash.encoding))) + (function + | Dissection_start_hash_mismatch {expected; given} -> + Some (expected, given) + | _ -> None) + (fun (expected, given) -> Dissection_start_hash_mismatch {expected; given}) ; + let description = "Mismatch in the stop hash of the dissection" in + register_error_kind + `Temporary + ~id:"smart_rollup_dissection_stop_hash_mismatch" + ~title:description + ~description + ~pp:(fun ppf h -> + Format.fprintf ppf "The stop hash should not be equal to %a" pp_hash_opt h) + Data_encoding.( + obj1 (req "hash" (option Sc_rollup_repr.State_hash.encoding))) + (function Dissection_stop_hash_mismatch hopt -> Some hopt | _ -> None) + (fun hopt -> Dissection_stop_hash_mismatch hopt) ; + let description = "Mismatch in the edge ticks of the dissection" in + register_error_kind + `Temporary + ~id:"smart_rollup_dissection_edge_ticks_mismatch" + ~title:description + ~description + ~pp: + (fun ppf + ( dissection_start_tick, + dissection_stop_tick, + chunk_start_tick, + chunk_stop_tick ) -> + Sc_rollup_tick_repr.( + Format.fprintf + ppf + "We should have dissection_start_tick(%a) = %a and \ + dissection_stop_tick(%a) = %a" + pp + dissection_start_tick + pp + chunk_start_tick + pp + dissection_stop_tick + pp + chunk_stop_tick)) + Data_encoding.( + obj4 + (req "dissection_start_tick" Sc_rollup_tick_repr.encoding) + (req "dissection_stop_tick" Sc_rollup_tick_repr.encoding) + (req "chunk_start_tick" Sc_rollup_tick_repr.encoding) + (req "chunk_stop_tick" Sc_rollup_tick_repr.encoding)) + (function + | Dissection_edge_ticks_mismatch e -> + Some + ( e.dissection_start_tick, + e.dissection_stop_tick, + e.chunk_start_tick, + e.chunk_stop_tick ) + | _ -> None) + (fun ( dissection_start_tick, + dissection_stop_tick, + chunk_start_tick, + chunk_stop_tick ) -> + Dissection_edge_ticks_mismatch + { + dissection_start_tick; + dissection_stop_tick; + chunk_start_tick; + chunk_stop_tick; + }) ; + let description = "Ticks should only increase in dissection" in + register_error_kind + `Permanent + ~id:"smart_rollup_dissection_ticks_not_increasing" + ~title:description + ~description + ~pp:(fun ppf () -> Format.pp_print_string ppf description) + Data_encoding.empty + (function Dissection_ticks_not_increasing -> Some () | _ -> None) + (fun () -> Dissection_ticks_not_increasing) ; + register_error_kind + `Permanent + ~id:"smart_rollup_dissection_invalid_distribution" + ~title:description + ~description + ~pp:(fun ppf max -> + Format.fprintf + ppf + "Maximum tick increment in a section cannot be more than %a ticks" + Z.pp_print + max) + Data_encoding.(obj1 (req "section_max_size" n)) + (function Dissection_invalid_distribution max -> Some max | _ -> None) + (fun max -> Dissection_invalid_distribution max) ; + let description = "Cannot recover from a blocked state in a dissection" in + register_error_kind + `Permanent + ~id:"smart_rollup_dissection_invalid_successive_states_shape" + ~title:description + ~description + ~pp:(fun ppf () -> Format.pp_print_string ppf description) + Data_encoding.empty + (function + | Dissection_invalid_successive_states_shape -> Some () | _ -> None) + (fun () -> Dissection_invalid_successive_states_shape) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.mli new file mode 100644 index 000000000000..d81adbe90c9f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_dissection_chunk_repr.mli @@ -0,0 +1,108 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr + +(** A dissection chunk is made of an optional state hash, and a tick count. *) +type t = {state_hash : State_hash.t option; tick : Sc_rollup_tick_repr.t} + +val equal : t -> t -> bool + +val pp : Format.formatter -> t -> unit + +val encoding : t Data_encoding.t + +val default_check_sections_number : + default_number_of_sections:int -> + number_of_sections:int -> + dist:Z.t -> + unit tzresult + +(** We check firstly that [dissection] is the correct length. It must + be [default_number_of_sections] values long, unless the distance + between [start_tick] and [stop_tick] is too small to make this + possible, in which case it should be as long as possible. (If the + distance is one we fail immediately as there is no possible legal + dissection). + + Then we check that [dissection] starts at the correct tick and + state (specified by [start_chunk]), and that it ends at + [stop_chunk], at the correct tick and with a different state to + the current dissection. + + Finally, we check that [dissection] is well formed: it has + correctly ordered the ticks, and it begins with a real hash of the + form [Some s] not a [None] state. Note that we have to allow the + possibility of multiple [None] states because the restrictions on + dissection shape (which are necessary to prevent a 'linear-time + game' attack) will mean that sometimes the honest play is a + dissection with multiple [None] states. *) +val default_check : + section_maximum_size:Z.t -> + check_sections_number: + (default_number_of_sections:int -> + number_of_sections:int -> + dist:Z.t -> + unit tzresult) -> + default_number_of_sections:int -> + start_chunk:t -> + stop_chunk:t -> + t list -> + unit tzresult + +type error += + | Dissection_number_of_sections_mismatch of {expected : Z.t; given : Z.t} + (** There are more or less than the expected number of sections in the + given dissection. *) + | Dissection_invalid_number_of_sections of Z.t + (** There are less than two sections in the given dissection, which is + not valid. *) + | Dissection_start_hash_mismatch of { + expected : Sc_rollup_repr.State_hash.t option; + given : Sc_rollup_repr.State_hash.t option; + } + (** The given start hash in a dissection is [None] or doesn't match the + expected one.*) + | Dissection_stop_hash_mismatch of Sc_rollup_repr.State_hash.t option + (** The given stop state hash in a dissection should not match the last + hash of the section being refuted. *) + | Dissection_edge_ticks_mismatch of { + dissection_start_tick : Sc_rollup_tick_repr.t; + dissection_stop_tick : Sc_rollup_tick_repr.t; + chunk_start_tick : Sc_rollup_tick_repr.t; + chunk_stop_tick : Sc_rollup_tick_repr.t; + } + (** The given dissection's edge ticks don't match the edge ticks of the + section being refuted. *) + | Dissection_ticks_not_increasing + (** Invalid provided dissection because ticks are not increasing between + two successive sections. *) + | Dissection_invalid_distribution of Z.t + (** Invalid provided dissection because ticks split is not well balanced + across sections *) + | Dissection_invalid_successive_states_shape + (** A dissection cannot have a section with no state hash after another + section with some state hash. *) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_errors.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_errors.ml new file mode 100644 index 000000000000..93f7fbdc638f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_errors.ml @@ -0,0 +1,759 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Temporary *) Sc_rollup_disputed + | (* `Temporary *) Sc_rollup_no_valid_commitment_to_cement + | (* `Temporary *) Sc_rollup_does_not_exist of Sc_rollup_repr.t + | (* `Temporary *) Sc_rollup_no_conflict + | (* `Temporary *) Sc_rollup_no_stakers + | (* `Temporary *) Sc_rollup_not_staked + | (* `Temporary *) Sc_rollup_not_staked_on_lcc_or_ancestor + | (* `Temporary *) Sc_rollup_parent_not_lcc + | (* `Temporary *) Sc_rollup_remove_lcc_or_ancestor + | (* `Temporary *) Sc_rollup_staker_double_stake + | (* `Temporary *) Sc_rollup_too_far_ahead + | (* `Temporary *) + Sc_rollup_commitment_from_future of { + current_level : Raw_level_repr.t; + inbox_level : Raw_level_repr.t; + } + | (* `Temporary *) + Sc_rollup_commitment_too_recent of { + current_level : Raw_level_repr.t; + min_level : Raw_level_repr.t; + } + | (* `Temporary *) + Sc_rollup_unknown_commitment of + Sc_rollup_commitment_repr.Hash.t + | (* `Temporary *) Sc_rollup_bad_inbox_level + | (* `Temporary *) Sc_rollup_game_already_started + | (* `Temporary *) + Sc_rollup_max_number_of_parallel_games_reached of + Signature.Public_key_hash.t + | (* `Temporary *) Sc_rollup_wrong_turn + | (* `Temporary *) Sc_rollup_no_game + | (* `Temporary *) + Sc_rollup_staker_in_game of + [ `Refuter of Signature.public_key_hash + | `Defender of Signature.public_key_hash + | `Both of Signature.public_key_hash * Signature.public_key_hash ] + | (* `Temporary *) + Sc_rollup_timeout_level_not_reached of + int32 * Signature.public_key_hash + | (* `Temporary *) + Sc_rollup_max_number_of_messages_reached_for_commitment_period + | (* `Permanent *) Sc_rollup_add_zero_messages + | (* `Temporary *) Sc_rollup_invalid_outbox_message_index + | (* `Temporary *) Sc_rollup_outbox_level_expired + | (* `Temporary *) Sc_rollup_outbox_message_already_applied + | (* `Temporary *) + Sc_rollup_staker_funds_too_low of { + staker : Signature.public_key_hash; + sc_rollup : Sc_rollup_repr.t; + staker_balance : Tez_repr.t; + min_expected_balance : Tez_repr.t; + } + | (* `Temporary *) Sc_rollup_bad_commitment_serialization + | (* `Permanent *) Sc_rollup_address_generation + | (* `Permanent *) Sc_rollup_zero_tick_commitment + | (* `Permanent *) Sc_rollup_commitment_past_curfew + | (* `Permanent *) + Sc_rollup_not_valid_commitments_conflict of + Sc_rollup_commitment_repr.Hash.t + * Signature.public_key_hash + * Sc_rollup_commitment_repr.Hash.t + * Signature.public_key_hash + | (* `Permanent *) + Sc_rollup_wrong_staker_for_conflict_commitment of + Signature.public_key_hash * Sc_rollup_commitment_repr.Hash.t + | (* `Permanent *) + Sc_rollup_commitment_too_old of { + last_cemented_inbox_level : Raw_level_repr.t; + commitment_inbox_level : Raw_level_repr.t; + } + | (* `Temporary *) + Sc_rollup_no_commitment_to_cement of Raw_level_repr.t + | (* `Permanent *) + Sc_rollup_double_publish of Sc_rollup_commitment_repr.Hash.t + | Sc_rollup_empty_whitelist + | Sc_rollup_whitelist_disabled + | Sc_rollup_staker_not_in_whitelist + | Sc_rollup_duplicated_key_in_whitelist + | Sc_rollup_is_public + +let () = + register_error_kind + `Temporary + ~id:"smart_rollup_staker_in_game" + ~title:"Staker is already playing a game" + ~description:"Attempted to start a game where one staker is already busy" + ~pp:(fun ppf staker -> + let busy ppf = function + | `Refuter sc -> + Format.fprintf + ppf + "the refuter (%a) is" + Signature.Public_key_hash.pp + sc + | `Defender sc -> + Format.fprintf + ppf + "the defender (%a) is" + Signature.Public_key_hash.pp + sc + | `Both (refuter, defender) -> + Format.fprintf + ppf + "both the refuter (%a) and the defender (%a) are" + Signature.Public_key_hash.pp + refuter + Signature.Public_key_hash.pp + defender + in + Format.fprintf + ppf + "Attempted to start a game where %a already busy." + busy + staker) + Data_encoding.( + union + [ + case + (Tag 0) + ~title:"Refuter" + (obj1 (req "refuter" Signature.Public_key_hash.encoding)) + (function `Refuter sc -> Some sc | _ -> None) + (fun sc -> `Refuter sc); + case + (Tag 1) + ~title:"Defender" + (obj1 (req "defender" Signature.Public_key_hash.encoding)) + (function `Defender sc -> Some sc | _ -> None) + (fun sc -> `Defender sc); + case + (Tag 2) + ~title:"Both" + (obj2 + (req "refuter" Signature.Public_key_hash.encoding) + (req "defender" Signature.Public_key_hash.encoding)) + (function + | `Both (refuter, defender) -> Some (refuter, defender) + | _ -> None) + (fun (refuter, defender) -> `Both (refuter, defender)); + ]) + (function Sc_rollup_staker_in_game x -> Some x | _ -> None) + (fun x -> Sc_rollup_staker_in_game x) ; + let description = "Attempt to timeout game too early" in + register_error_kind + `Temporary + ~id:"smart_rollup_timeout_level_not_reached" + ~title:"Attempt to timeout game too early" + ~description + ~pp:(fun ppf (blocks_left, staker) -> + Format.fprintf + ppf + "%s. The player %a has %ld left blocks to play." + description + Signature.Public_key_hash.pp_short + staker + blocks_left) + Data_encoding.( + obj2 + (req "level_timeout" int32) + (req "staker" Signature.Public_key_hash.encoding)) + (function + | Sc_rollup_timeout_level_not_reached (blocks_left, staker) -> + Some (blocks_left, staker) + | _ -> None) + (fun (blocks_left, staker) -> + Sc_rollup_timeout_level_not_reached (blocks_left, staker)) ; + let description = + "Refutation game already started, must play with is_opening_move = false." + in + register_error_kind + `Temporary + ~id:"smart_rollup_game_already_started" + ~title:"Refutation game already started" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Sc_rollup_game_already_started -> Some () | _ -> None) + (fun () -> Sc_rollup_game_already_started) ; + let description = "Refutation game does not exist" in + register_error_kind + `Temporary + ~id:"smart_rollup_no_game" + ~title:"Refutation game does not exist" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Sc_rollup_no_game -> Some () | _ -> None) + (fun () -> Sc_rollup_no_game) ; + let description = "Attempt to play move but not staker's turn" in + register_error_kind + `Temporary + ~id:"smart_rollup_wrong_turn" + ~title:"Attempt to play move but not staker's turn" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Sc_rollup_wrong_turn -> Some () | _ -> None) + (fun () -> Sc_rollup_wrong_turn) ; + let description = + "Maximum number of messages reached for commitment period" + in + register_error_kind + `Temporary + ~id:"smart_rollup_max_number_of_messages_reached_for_commitment_period" + ~title:"Maximum number of messages reached for commitment period" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function + | Sc_rollup_max_number_of_messages_reached_for_commitment_period -> + Some () + | _ -> None) + (fun () -> Sc_rollup_max_number_of_messages_reached_for_commitment_period) ; + let description = "Tried to add zero messages to a smart rollup" in + register_error_kind + `Permanent + ~id:"smart_rollup_add_zero_messages" + ~title:description + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Sc_rollup_add_zero_messages -> Some () | _ -> None) + (fun () -> Sc_rollup_add_zero_messages) ; + let description = + "Attempted to cement a commitment but there is no valid commitment to \ + cement." + in + register_error_kind + `Temporary + ~id:"smart_rollup_no_valid_commitment_to_cement" + ~title:"No valid commitment to cement" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_no_valid_commitment_to_cement -> Some () | _ -> None) + (fun () -> Sc_rollup_no_valid_commitment_to_cement) ; + let description = "Attempted to cement a disputed commitment." in + register_error_kind + `Temporary + ~id:"smart_rollup_commitment_disputed" + ~title:"Commitment disputed" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_disputed -> Some () | _ -> None) + (fun () -> Sc_rollup_disputed) ; + let description = + "Attempted to use a smart rollup that has not been originated." + in + register_error_kind + `Temporary + ~id:"smart_rollup_does_not_exist" + ~title:"Smart rollup does not exist" + ~description + ~pp:(fun ppf x -> + Format.fprintf ppf "Smart rollup %a does not exist" Sc_rollup_repr.pp x) + Data_encoding.(obj1 (req "rollup" Sc_rollup_repr.encoding)) + (function Sc_rollup_does_not_exist x -> Some x | _ -> None) + (fun x -> Sc_rollup_does_not_exist x) ; + let description = "No conflict." in + register_error_kind + `Temporary + ~id:"smart_rollup_no_conflict" + ~title:"No conflict" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_no_conflict -> Some () | _ -> None) + (fun () -> Sc_rollup_no_conflict) ; + let description = "No stakers for the targeted smart rollup." in + register_error_kind + `Temporary + ~id:"smart_rollup_no_stakers" + ~title:"No stakers" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_no_stakers -> Some () | _ -> None) + (fun () -> Sc_rollup_no_stakers) ; + let description = + "This implicit account is not a staker of this smart rollup." + in + register_error_kind + `Temporary + ~id:"smart_rollup_not_staked" + ~title:"Unknown staker" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_not_staked -> Some () | _ -> None) + (fun () -> Sc_rollup_not_staked) ; + let description = + "Attempted to withdraw while not staked on the last cemented commitment or \ + its ancestor." + in + register_error_kind + `Temporary + ~id:"smart_rollup_not_staked_on_lcc_or_ancestor" + ~title:"Smart rollup not staked on LCC or its ancestor" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_not_staked_on_lcc_or_ancestor -> Some () | _ -> None) + (fun () -> Sc_rollup_not_staked_on_lcc_or_ancestor) ; + let description = "Parent is not the last cemented commitment." in + register_error_kind + `Temporary + ~id:"smart_rollup_parent_not_lcc" + ~title:"Parent is not the last cemented commitment" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_parent_not_lcc -> Some () | _ -> None) + (fun () -> Sc_rollup_parent_not_lcc) ; + let description = "Can not remove a staker committed on cemented." in + register_error_kind + `Temporary + ~id:"smart_rollup_remove_lcc_or_ancestor" + ~title:"Can not remove a staker" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_remove_lcc_or_ancestor -> Some () | _ -> None) + (fun () -> Sc_rollup_remove_lcc_or_ancestor) ; + let description = "Staker tried to double stake." in + register_error_kind + `Temporary + ~id:"smart_rollup_staker_double_stake" + ~title:description + ~description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "The staker tried to double stake, that is, it tried to publish a \ + commitment for an inbox level where it already published another \ + conflicting commitment. The staker is not allowed to changed its \ + mind.") + Data_encoding.empty + (function Sc_rollup_staker_double_stake -> Some () | _ -> None) + (fun () -> Sc_rollup_staker_double_stake) ; + let description = + "Commitment is too far ahead of the last cemented commitment." + in + register_error_kind + `Temporary + ~id:"smart_rollup_too_far_ahead" + ~title:"Commitment too far ahead" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_too_far_ahead -> Some () | _ -> None) + (fun () -> Sc_rollup_too_far_ahead) ; + let description = + "Attempted to cement a commitment before its refutation deadline." + in + register_error_kind + `Temporary + ~id:"smart_rollup_commitment_too_recent" + ~title:"Commitment too recent" + ~description + ~pp:(fun ppf (current_level, min_level) -> + Format.fprintf + ppf + "%s@ Current level: %a,@ minimal level: %a" + description + Raw_level_repr.pp + current_level + Raw_level_repr.pp + min_level) + Data_encoding.( + obj2 + (req "current_level" Raw_level_repr.encoding) + (req "min_level" Raw_level_repr.encoding)) + (function + | Sc_rollup_commitment_too_recent {current_level; min_level} -> + Some (current_level, min_level) + | _ -> None) + (fun (current_level, min_level) -> + Sc_rollup_commitment_too_recent {current_level; min_level}) ; + let description = "Unknown commitment." in + register_error_kind + `Temporary + ~id:"smart_rollup_unknown_commitment" + ~title:"Unknown commitment" + ~description + ~pp:(fun ppf x -> + Format.fprintf + ppf + "Commitment %a does not exist" + Sc_rollup_commitment_repr.Hash.pp + x) + Data_encoding.( + obj1 (req "commitment" Sc_rollup_commitment_repr.Hash.encoding)) + (function Sc_rollup_unknown_commitment x -> Some x | _ -> None) + (fun x -> Sc_rollup_unknown_commitment x) ; + let description = "Attempted to commit to a bad inbox level." in + register_error_kind + `Temporary + ~id:"smart_rollup_bad_inbox_level" + ~title:"Committing to a bad inbox level" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_bad_inbox_level -> Some () | _ -> None) + (fun () -> Sc_rollup_bad_inbox_level) ; + let description = "Invalid rollup outbox message index" in + register_error_kind + `Temporary + ~id:"smart_rollup_invalid_outbox_message_index" + ~title:"Invalid rollup outbox message index" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_invalid_outbox_message_index -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_outbox_message_index) ; + let description = "Outbox level expired" in + register_error_kind + `Temporary + ~id:"smart_rollup_outbox_level_expired" + ~title:description + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_outbox_level_expired -> Some () | _ -> None) + (fun () -> Sc_rollup_outbox_level_expired) ; + let description = "Outbox message already applied" in + register_error_kind + `Temporary + ~id:"smart_rollup_outbox_message_already_applied" + ~title:description + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_outbox_message_already_applied -> Some () | _ -> None) + (fun () -> Sc_rollup_outbox_message_already_applied) ; + register_error_kind + `Temporary + ~id:"smart_rollup_staker_funds_too_low" + ~title:"Staker does not have enough funds to make a deposit" + ~description: + "Staker doesn't have enough funds to make a smart rollup deposit." + ~pp:(fun ppf (staker, sc_rollup, staker_balance, min_expected_balance) -> + Format.fprintf + ppf + "Staker (%a) doesn't have enough funds to make the deposit for smart \ + rollup (%a). Staker's balance is %a while a balance of at least %a is \ + required." + Signature.Public_key_hash.pp + staker + Sc_rollup_repr.pp + sc_rollup + Tez_repr.pp + staker_balance + Tez_repr.pp + min_expected_balance) + Data_encoding.( + obj4 + (req "staker" Signature.Public_key_hash.encoding) + (req "smart_rollup" Sc_rollup_repr.encoding) + (req "staker_balance" Tez_repr.encoding) + (req "min_expected_balance" Tez_repr.encoding)) + (function + | Sc_rollup_staker_funds_too_low + {staker; sc_rollup; staker_balance; min_expected_balance} -> + Some (staker, sc_rollup, staker_balance, min_expected_balance) + | _ -> None) + (fun (staker, sc_rollup, staker_balance, min_expected_balance) -> + Sc_rollup_staker_funds_too_low + {staker; sc_rollup; staker_balance; min_expected_balance}) ; + let description = "Could not serialize commitment." in + register_error_kind + `Temporary + ~id:"smart_rollup_bad_commitment_serialization" + ~title:"Could not serialize commitment." + ~description:"Unable to hash the commitment serialization." + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_bad_commitment_serialization -> Some () | _ -> None) + (fun () -> Sc_rollup_bad_commitment_serialization) ; + let description = + "Commitment inbox level is greater or equal than current level" + in + register_error_kind + `Temporary + ~id:"smart_rollup_commitment_from_future" + ~title:"Commitment from future" + ~description + ~pp:(fun ppf (current_level, inbox_level) -> + Format.fprintf + ppf + "%s@ Current level: %a,@ commitment inbox level: %a" + description + Raw_level_repr.pp + current_level + Raw_level_repr.pp + inbox_level) + Data_encoding.( + obj2 + (req "current_level" Raw_level_repr.encoding) + (req "inbox_level" Raw_level_repr.encoding)) + (function + | Sc_rollup_commitment_from_future {current_level; inbox_level} -> + Some (current_level, inbox_level) + | _ -> None) + (fun (current_level, inbox_level) -> + Sc_rollup_commitment_from_future {current_level; inbox_level}) ; + let description = "Commitment is past the curfew for this level." in + register_error_kind + `Permanent + ~id:"smart_rollup_commitment_past_curfew" + ~title:"Commitment past curfew." + ~description: + "A commitment exists for this inbox level for longer than the curfew \ + period." + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_commitment_past_curfew -> Some () | _ -> None) + (fun () -> Sc_rollup_commitment_past_curfew) ; + let description = "Error while generating a smart rollup address" in + register_error_kind + `Permanent + ~id:"smart_rollup_address_generation" + ~title:description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + ~description + Data_encoding.empty + (function Sc_rollup_address_generation -> Some () | _ -> None) + (fun () -> Sc_rollup_address_generation) ; + let description = "Tried to publish a 0 tick commitment" in + register_error_kind + `Permanent + ~id:"smart_rollup_zero_tick_commitment" + ~title:description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + ~description + Data_encoding.empty + (function Sc_rollup_zero_tick_commitment -> Some () | _ -> None) + (fun () -> Sc_rollup_zero_tick_commitment) ; + let description = "Maximal number of parallel games reached" in + register_error_kind + `Temporary + ~id:"smart_rollup_maximal_number_of_parallel_games_reached" + ~title:description + ~pp:(fun ppf staker -> + Format.fprintf + ppf + "%a has reached the limit for number of parallel games" + Signature.Public_key_hash.pp + staker) + ~description + Data_encoding.(obj1 (req "staker" Signature.Public_key_hash.encoding)) + (function + | Sc_rollup_max_number_of_parallel_games_reached staker -> Some staker + | _ -> None) + (fun staker -> Sc_rollup_max_number_of_parallel_games_reached staker) ; + let description = "Conflicting commitments do not have a common ancestor" in + register_error_kind + `Permanent + ~id:"smart_rollup_not_valid_commitments_conflict" + ~title:description + ~pp:(fun ppf (c1, s1, c2, s2) -> + Format.fprintf + ppf + "The two commitments %a, staked by %a, and %a, staked by %a, does not \ + have a common predecessor. Two commitments are in conflict when there \ + direct predecessor is the same." + Sc_rollup_commitment_repr.Hash.pp + c1 + Signature.Public_key_hash.pp_short + s1 + Sc_rollup_commitment_repr.Hash.pp + c2 + Signature.Public_key_hash.pp_short + s2) + ~description + Data_encoding.( + obj4 + (req "commitment" Sc_rollup_commitment_repr.Hash.encoding) + (req "player" Signature.Public_key_hash.encoding) + (req "opponent_commitment" Sc_rollup_commitment_repr.Hash.encoding) + (req "opponent" Signature.Public_key_hash.encoding)) + (function + | Sc_rollup_not_valid_commitments_conflict (c1, s1, c2, s2) -> + Some (c1, s1, c2, s2) + | _ -> None) + (fun (c1, s1, c2, s2) -> + Sc_rollup_not_valid_commitments_conflict (c1, s1, c2, s2)) ; + let description = "Given commitment is not staked by given staker" in + register_error_kind + `Permanent + ~id:"smart_rollup_wrong_staker_for_conflict_commitment" + ~title:description + ~pp:(fun ppf (staker, commitment) -> + Format.fprintf + ppf + "The staker %a has not staked commitment %a" + Signature.Public_key_hash.pp + staker + Sc_rollup_commitment_repr.Hash.pp + commitment) + ~description + Data_encoding.( + obj2 + (req "player" Signature.Public_key_hash.encoding) + (req "commitment" Sc_rollup_commitment_repr.Hash.encoding)) + (function + | Sc_rollup_wrong_staker_for_conflict_commitment (staker, commitment) -> + Some (staker, commitment) + | _ -> None) + (fun (staker, commitment) -> + Sc_rollup_wrong_staker_for_conflict_commitment (staker, commitment)) ; + + let description = "Published commitment is too old" in + register_error_kind + `Permanent + ~id:"smart_rollup_commitment_too_old" + ~title:description + ~pp:(fun ppf (last_cemented_inbox_level, commitment_inbox_level) -> + Format.fprintf + ppf + "The published commitment is for the inbox level %a, the last cemented \ + commitment inbox level is %a. You cannot publish a commitment behind \ + the last cemented commitment." + Raw_level_repr.pp + last_cemented_inbox_level + Raw_level_repr.pp + commitment_inbox_level) + ~description + Data_encoding.( + obj2 + (req "last_cemented_inbox_level" Raw_level_repr.encoding) + (req "commitment_inbox_level" Raw_level_repr.encoding)) + (function + | Sc_rollup_commitment_too_old + {last_cemented_inbox_level; commitment_inbox_level} -> + Some (last_cemented_inbox_level, commitment_inbox_level) + | _ -> None) + (fun (last_cemented_inbox_level, commitment_inbox_level) -> + Sc_rollup_commitment_too_old + {last_cemented_inbox_level; commitment_inbox_level}) ; + let description = "No commitment to cement" in + register_error_kind + `Permanent + ~id:"smart_rollup_no_commitment_to_cement" + ~title:description + ~pp:(fun ppf inbox_level -> + Format.fprintf + ppf + "There is no commitment to cement at inbox level %a." + Raw_level_repr.pp + inbox_level) + ~description + Data_encoding.(obj1 (req "inbox_level" Raw_level_repr.encoding)) + (function + | Sc_rollup_no_commitment_to_cement inbox_level -> Some inbox_level + | _ -> None) + (fun inbox_level -> Sc_rollup_no_commitment_to_cement inbox_level) ; + register_error_kind + `Permanent + ~id:"smart_rollup_double_publish" + ~title:"The commitment was published twice by the operator" + ~pp:(fun ppf commitment_hash -> + Format.fprintf + ppf + "The operator publishing %a already published this commitment." + Sc_rollup_commitment_repr.Hash.pp + commitment_hash) + ~description + Data_encoding.( + obj1 (req "commitment_hash" Sc_rollup_commitment_repr.Hash.encoding)) + (function + | Sc_rollup_double_publish commitment_hash -> Some commitment_hash + | _ -> None) + (fun commitment_hash -> Sc_rollup_double_publish commitment_hash) ; + register_error_kind + `Permanent + ~id:"smart_rollup_empty_whitelist" + ~title:"Invalid whitelist: whitelist cannot be empty" + ~description:"Smart rollup whitelist cannot be empty" + ~pp:(fun ppf () -> + Format.fprintf ppf "Smart rollup whitelist cannot be empty.") + Data_encoding.empty + (function Sc_rollup_empty_whitelist -> Some () | _ -> None) + (fun () -> Sc_rollup_empty_whitelist) ; + register_error_kind + `Permanent + ~id:"smart_rollup_whitelist_disabled" + ~title:"Invalid whitelist: must be None when the feature is deactivated" + ~description:"The whitelist must be None when the feature is deactivated." + ~pp:(fun ppf () -> + Format.fprintf ppf "Private smart rollup with whitelist ACL is disabled.") + Data_encoding.empty + (function Sc_rollup_whitelist_disabled -> Some () | _ -> None) + (fun () -> Sc_rollup_whitelist_disabled) ; + register_error_kind + `Temporary + ~id:"smart_rollup_staker_not_in_whitelist" + ~title:description + ~description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "The rollup is private and the submitter of the commitment is not \ + present in the whitelist.") + Data_encoding.empty + (function Sc_rollup_staker_not_in_whitelist -> Some () | _ -> None) + (fun () -> Sc_rollup_staker_not_in_whitelist) ; + register_error_kind + `Temporary + ~id:"smart_rollup_duplicated_key_in_whitelist" + ~title:description + ~description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "The whitelist contains twice the same key. This is forbidden and all \ + keys in the whitelist should be disctinct.") + Data_encoding.empty + (function Sc_rollup_duplicated_key_in_whitelist -> Some () | _ -> None) + (fun () -> Sc_rollup_duplicated_key_in_whitelist) ; + register_error_kind + `Permanent + ~id:"smart_rollup_rollup_is_public" + ~title:description + ~description + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "The rollup is public, no update whitelist message can be executed.") + Data_encoding.empty + (function Sc_rollup_is_public -> Some () | _ -> None) + (fun () -> Sc_rollup_is_public) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.ml new file mode 100644 index 000000000000..3a1b1fe41298 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.ml @@ -0,0 +1,1026 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr + +(** {2 Refutation game errors} *) + +type error += + | (* `Temporary *) + Dissection_choice_not_found of Sc_rollup_tick_repr.t + | (* `Permanent *) Proof_unexpected_section_size of Z.t + | (* `Temporary *) + Proof_start_state_hash_mismatch of { + start_state_hash : Sc_rollup_repr.State_hash.t option; + start_proof : Sc_rollup_repr.State_hash.t; + } + | (* `Temporary *) + Proof_stop_state_hash_failed_to_refute of { + stop_state_hash : Sc_rollup_repr.State_hash.t option; + stop_proof : Sc_rollup_repr.State_hash.t option; + } + | (* `Temporary *) + Proof_stop_state_hash_failed_to_validate of { + stop_state_hash : Sc_rollup_repr.State_hash.t option; + stop_proof : Sc_rollup_repr.State_hash.t option; + } + | (* `Temporary *) Dissecting_during_final_move + +let pp_hash_opt fmt = function + | None -> Format.fprintf fmt "None" + | Some x -> Sc_rollup_repr.State_hash.pp fmt x + +let () = + let description = "Dissection choice not found" in + register_error_kind + `Temporary + ~id:"Dissection_choice_not_found" + ~title:description + ~description + ~pp:(fun ppf choice -> + Format.fprintf + ppf + "No section starting with tick %a found" + Sc_rollup_tick_repr.pp + choice) + Data_encoding.(obj1 (req "choice" Sc_rollup_tick_repr.encoding)) + (function Dissection_choice_not_found tick -> Some tick | _ -> None) + (fun tick -> Dissection_choice_not_found tick) ; + let description = "The distance for a proof should be equal to 1" in + register_error_kind + `Permanent + ~id:"Dissection_unexpected_section_size" + ~title:description + ~description + ~pp:(fun ppf n -> + Format.fprintf + ppf + "Distance should be equal to 1 in a proof, but got %a" + Z.pp_print + n) + Data_encoding.(obj1 (req "n" n)) + (function Proof_unexpected_section_size n -> Some n | _ -> None) + (fun n -> Proof_unexpected_section_size n) ; + let description = "The start state hash of the proof is invalid" in + register_error_kind + `Temporary + ~id:"Proof_start_state_hash_mismatch" + ~title:description + ~description + ~pp:(fun ppf (start_state_hash, start_proof) -> + Format.fprintf + ppf + "start(%a) should be equal to start_proof(%a)" + pp_hash_opt + start_state_hash + Sc_rollup_repr.State_hash.pp + start_proof) + Data_encoding.( + obj2 + (req "start_state_hash" (option Sc_rollup_repr.State_hash.encoding)) + (req "start_proof" Sc_rollup_repr.State_hash.encoding)) + (function + | Proof_start_state_hash_mismatch {start_state_hash; start_proof} -> + Some (start_state_hash, start_proof) + | _ -> None) + (fun (start_state_hash, start_proof) -> + Proof_start_state_hash_mismatch {start_state_hash; start_proof}) ; + let description = "Failed to refute the stop state hash with the proof" in + register_error_kind + `Temporary + ~id:"Proof_stop_state_hash_failed_to_refute" + ~title:description + ~description + ~pp:(fun ppf (stop_state_hash, stop_proof) -> + Format.fprintf + ppf + "Trying to refute %a, the stop_proof must not be equal to %a" + pp_hash_opt + stop_state_hash + pp_hash_opt + stop_proof) + Data_encoding.( + obj2 + (req "stop_state_hash" (option Sc_rollup_repr.State_hash.encoding)) + (req "stop_proof" (option Sc_rollup_repr.State_hash.encoding))) + (function + | Proof_stop_state_hash_failed_to_refute {stop_state_hash; stop_proof} -> + Some (stop_state_hash, stop_proof) + | _ -> None) + (fun (stop_state_hash, stop_proof) -> + Proof_stop_state_hash_failed_to_refute {stop_state_hash; stop_proof}) ; + let description = "Failed to validate the stop state hash with the proof" in + register_error_kind + `Temporary + ~id:"Proof_stop_state_hash_failed_to_validate" + ~title:description + ~description + ~pp:(fun ppf (stop_state_hash, stop_proof) -> + Format.fprintf + ppf + "Trying to validate %a, the stop_proof must not be equal to %a" + pp_hash_opt + stop_state_hash + pp_hash_opt + stop_proof) + Data_encoding.( + obj2 + (req "stop_state_hash" (option Sc_rollup_repr.State_hash.encoding)) + (req "stop_proof" (option Sc_rollup_repr.State_hash.encoding))) + (function + | Proof_stop_state_hash_failed_to_validate {stop_state_hash; stop_proof} + -> + Some (stop_state_hash, stop_proof) + | _ -> None) + (fun (stop_state_hash, stop_proof) -> + Proof_stop_state_hash_failed_to_validate {stop_state_hash; stop_proof}) ; + let description = "Tried to play a dissecting when the final move started" in + register_error_kind + `Temporary + ~id:"Dissecting_during_final_move" + ~title:description + ~description + ~pp:(fun ppf () -> Format.pp_print_string ppf description) + Data_encoding.empty + (function Dissecting_during_final_move -> Some () | _ -> None) + (fun () -> Dissecting_during_final_move) ; + () + +type player = Alice | Bob + +module V1 = struct + type dissection_chunk = Sc_rollup_dissection_chunk_repr.t = { + state_hash : State_hash.t option; + tick : Sc_rollup_tick_repr.t; + } + + type game_state = + | Dissecting of { + dissection : dissection_chunk list; + default_number_of_sections : int; + } + | Final_move of { + agreed_start_chunk : dissection_chunk; + refuted_stop_chunk : dissection_chunk; + } + + type t = { + turn : player; + inbox_snapshot : Sc_rollup_inbox_repr.history_proof; + dal_snapshot : Dal_slot_repr.History.t; + start_level : Raw_level_repr.t; + inbox_level : Raw_level_repr.t; + game_state : game_state; + } + + let player_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Alice" + (Tag 0) + (constant "alice") + (function Alice -> Some () | _ -> None) + (fun () -> Alice); + case + ~title:"Bob" + (Tag 1) + (constant "bob") + (function Bob -> Some () | _ -> None) + (fun () -> Bob); + ] + + let player_equal p1 p2 = + match (p1, p2) with + | Alice, Alice -> true + | Bob, Bob -> true + | _, _ -> false + + let game_state_equal gs1 gs2 = + match (gs1, gs2) with + | ( Dissecting + { + dissection = dissection1; + default_number_of_sections = default_number_of_sections1; + }, + Dissecting + { + dissection = dissection2; + default_number_of_sections = default_number_of_sections2; + } ) -> + Compare.Int.equal + default_number_of_sections1 + default_number_of_sections2 + && List.equal + Sc_rollup_dissection_chunk_repr.equal + dissection1 + dissection2 + | Dissecting _, _ -> false + | ( Final_move + { + agreed_start_chunk = agreed_start_chunk1; + refuted_stop_chunk = refuted_stop_chunk1; + }, + Final_move + { + agreed_start_chunk = agreed_start_chunk2; + refuted_stop_chunk = refuted_stop_chunk2; + } ) -> + Sc_rollup_dissection_chunk_repr.equal + agreed_start_chunk1 + agreed_start_chunk2 + && Sc_rollup_dissection_chunk_repr.equal + refuted_stop_chunk1 + refuted_stop_chunk2 + | Final_move _, _ -> false + + let equal + {turn; inbox_snapshot; dal_snapshot; start_level; inbox_level; game_state} + g2 = + player_equal turn g2.turn + && Sc_rollup_inbox_repr.equal_history_proof inbox_snapshot g2.inbox_snapshot + && Dal_slot_repr.History.equal dal_snapshot g2.dal_snapshot + && Raw_level_repr.equal start_level g2.start_level + && Raw_level_repr.equal inbox_level g2.inbox_level + && game_state_equal game_state g2.game_state + + let string_of_player = function Alice -> "alice" | Bob -> "bob" + + let pp_player ppf player = + Format.pp_print_string ppf (string_of_player player) + + let opponent = function Alice -> Bob | Bob -> Alice + + let dissection_encoding = + let open Data_encoding in + list Sc_rollup_dissection_chunk_repr.encoding + + let game_state_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Dissecting" + (Tag 0) + (obj3 + (req "kind" (constant "Dissecting")) + (req "dissection" dissection_encoding) + (req "default_number_of_sections" uint8)) + (function + | Dissecting {dissection; default_number_of_sections} -> + Some ((), dissection, default_number_of_sections) + | _ -> None) + (fun ((), dissection, default_number_of_sections) -> + Dissecting {dissection; default_number_of_sections}); + case + ~title:"Final_move" + (Tag 1) + (obj3 + (req "kind" (constant "Final_move")) + (req "agreed_start_chunk" Sc_rollup_dissection_chunk_repr.encoding) + (req "refuted_stop_chunk" Sc_rollup_dissection_chunk_repr.encoding)) + (function + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Some ((), agreed_start_chunk, refuted_stop_chunk) + | _ -> None) + (fun ((), agreed_start_chunk, refuted_stop_chunk) -> + Final_move {agreed_start_chunk; refuted_stop_chunk}); + ] + + let encoding = + let open Data_encoding in + conv + (fun { + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } -> + ( turn, + inbox_snapshot, + dal_snapshot, + start_level, + inbox_level, + game_state )) + (fun ( turn, + inbox_snapshot, + dal_snapshot, + start_level, + inbox_level, + game_state ) -> + { + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + }) + (obj6 + (req "turn" player_encoding) + (req "inbox_snapshot" Sc_rollup_inbox_repr.history_proof_encoding) + (req "dal_snapshot" Dal_slot_repr.History.encoding) + (req "start_level" Raw_level_repr.encoding) + (req "inbox_level" Raw_level_repr.encoding) + (req "game_state" game_state_encoding)) + + let pp_dissection ppf d = + Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.pp_print_string ppf ";\n") + Sc_rollup_dissection_chunk_repr.pp + ppf + d + + let pp_game_state ppf game_state = + let open Format in + match game_state with + | Dissecting {dissection; default_number_of_sections} -> + fprintf + ppf + "Dissecting %a using %d number of sections" + pp_dissection + dissection + default_number_of_sections + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + fprintf + ppf + "Final move to refute %a from %a, opponent failed to refute" + Sc_rollup_dissection_chunk_repr.pp + agreed_start_chunk + Sc_rollup_dissection_chunk_repr.pp + refuted_stop_chunk + + let pp ppf game = + Format.fprintf + ppf + "%a playing; inbox snapshot = %a; start level = %a; inbox level = %a; \ + game_state = %a" + pp_player + game.turn + Sc_rollup_inbox_repr.pp_history_proof + game.inbox_snapshot + Raw_level_repr.pp + game.start_level + Raw_level_repr.pp + game.inbox_level + pp_game_state + game.game_state +end + +type versioned = V1 of V1.t + +let versioned_encoding = + let open Data_encoding in + union + [ + case + ~title:"V1" + (Tag 0) + V1.encoding + (function V1 game -> Some game) + (fun game -> V1 game); + ] + +include V1 + +let of_versioned = function V1 game -> game [@@inline] + +let to_versioned game = V1 game [@@inline] + +module Index = struct + type t = {alice : Staker.t; bob : Staker.t} + + let make a b = + let alice, bob = + if Compare.Int.(Staker.compare a b > 0) then (b, a) else (a, b) + in + {alice; bob} + + let encoding = + let open Data_encoding in + conv + (fun {alice; bob} -> (alice, bob)) + (fun (alice, bob) -> make alice bob) + (obj2 (req "alice" Staker.encoding) (req "bob" Staker.encoding)) + + let compare {alice = a; bob = b} {alice = c; bob = d} = + match Staker.compare a c with 0 -> Staker.compare b d | x -> x + + let to_path {alice; bob} p = + Staker.to_b58check alice :: Staker.to_b58check bob :: p + + let both_of_b58check_opt (a, b) = + let ( let* ) = Option.bind in + let* a_staker = Staker.of_b58check_opt a in + let* b_staker = Staker.of_b58check_opt b in + Some (make a_staker b_staker) + + let of_path = function [a; b] -> both_of_b58check_opt (a, b) | _ -> None + + let path_length = 2 + + let rpc_arg = + let descr = + "A pair of stakers that index a smart rollup refutation game." + in + let construct {alice; bob} = + Format.sprintf "%s-%s" (Staker.to_b58check alice) (Staker.to_b58check bob) + in + let destruct s = + match String.split_on_char '-' s with + | [a; b] -> ( + match both_of_b58check_opt (a, b) with + | Some stakers -> Ok stakers + | None -> Error (Format.sprintf "Invalid game index notation %s" s)) + | _ -> Error (Format.sprintf "Invalid game index notation %s" s) + in + RPC_arg.make ~descr ~name:"game_index" ~construct ~destruct () + + let staker {alice; bob} = function Alice -> alice | Bob -> bob +end + +let make_chunk state_hash tick = {state_hash; tick} + +let initial inbox dal_snapshot ~start_level + ~(parent_commitment : Sc_rollup_commitment_repr.t) + ~(defender_commitment : Sc_rollup_commitment_repr.t) ~refuter ~defender + ~default_number_of_sections = + let ({alice; _} : Index.t) = Index.make refuter defender in + let alice_to_play = Staker.equal alice refuter in + let open Sc_rollup_tick_repr in + let tick = of_number_of_ticks defender_commitment.number_of_ticks in + let game_state = + Dissecting + { + dissection = + [ + make_chunk (Some parent_commitment.compressed_state) initial; + make_chunk (Some defender_commitment.compressed_state) tick; + make_chunk None (next tick); + ]; + default_number_of_sections; + } + in + + { + turn = (if alice_to_play then Alice else Bob); + inbox_snapshot = inbox; + dal_snapshot; + start_level; + inbox_level = defender_commitment.inbox_level; + game_state; + } + +type step = + | Dissection of dissection_chunk list + | Proof of Sc_rollup_proof_repr.serialized Sc_rollup_proof_repr.t + +let step_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Dissection" + (Tag 0) + dissection_encoding + (function Dissection d -> Some d | _ -> None) + (fun d -> Dissection d); + case + ~title:"Proof" + (Tag 1) + Sc_rollup_proof_repr.encoding + (function Proof p -> Some p | _ -> None) + (fun p -> Proof p); + ] + +let pp_step ppf step = + match step with + | Dissection states -> + Format.fprintf ppf "Dissection:@ " ; + Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.pp_print_string ppf ";\n\n") + (fun ppf {state_hash; tick} -> + Format.fprintf + ppf + "Tick: %a,@ State: %a\n" + Sc_rollup_tick_repr.pp + tick + (Format.pp_print_option State_hash.pp) + state_hash) + ppf + states + | Proof proof -> Format.fprintf ppf "proof: %a" Sc_rollup_proof_repr.pp proof + +type refutation = + | Start of { + player_commitment_hash : Sc_rollup_commitment_repr.Hash.t; + opponent_commitment_hash : Sc_rollup_commitment_repr.Hash.t; + } + | Move of {choice : Sc_rollup_tick_repr.t; step : step} + +let pp_refutation ppf = function + | Start {player_commitment_hash; opponent_commitment_hash} -> + Format.fprintf + ppf + "Start game between commitment hashes %a and %a" + Sc_rollup_commitment_repr.Hash.pp + player_commitment_hash + Sc_rollup_commitment_repr.Hash.pp + opponent_commitment_hash + | Move {choice; step} -> + Format.fprintf + ppf + "Tick: %a@ Step: %a" + Sc_rollup_tick_repr.pp + choice + pp_step + step + +let refutation_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Start" + (Tag 0) + (obj3 + (req "refutation_kind" (constant "start")) + (req + "player_commitment_hash" + Sc_rollup_commitment_repr.Hash.encoding) + (req + "opponent_commitment_hash" + Sc_rollup_commitment_repr.Hash.encoding)) + (function + | Start {player_commitment_hash; opponent_commitment_hash} -> + Some ((), player_commitment_hash, opponent_commitment_hash) + | _ -> None) + (fun ((), player_commitment_hash, opponent_commitment_hash) -> + Start {player_commitment_hash; opponent_commitment_hash}); + case + ~title:"Move" + (Tag 1) + (obj3 + (req "refutation_kind" (constant "move")) + (req "choice" Sc_rollup_tick_repr.encoding) + (req "step" step_encoding)) + (function Move {choice; step} -> Some ((), choice, step) | _ -> None) + (fun ((), choice, step) -> Move {choice; step}); + ] + +type reason = Conflict_resolved | Timeout + +let pp_reason ppf reason = + match reason with + | Conflict_resolved -> Format.fprintf ppf "conflict resolved" + | Timeout -> Format.fprintf ppf "timeout" + +let reason_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Conflict_resolved" + (Tag 0) + (constant "conflict_resolved") + (function Conflict_resolved -> Some () | _ -> None) + (fun () -> Conflict_resolved); + case + ~title:"Timeout" + (Tag 1) + (constant "timeout") + (function Timeout -> Some () | _ -> None) + (fun () -> Timeout); + ] + +type game_result = Loser of {reason : reason; loser : Staker.t} | Draw + +let pp_game_result ppf r = + let open Format in + match r with + | Loser {reason; loser} -> + fprintf ppf "%a lost because: %a" Staker.pp loser pp_reason reason + | Draw -> fprintf ppf "Draw" + +let game_result_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Loser" + (Tag 0) + (obj3 + (req "kind" (constant "loser")) + (req "reason" reason_encoding) + (req "player" Staker.encoding)) + (function + | Loser {reason; loser} -> Some ((), reason, loser) | _ -> None) + (fun ((), reason, loser) -> Loser {reason; loser}); + case + ~title:"Draw" + (Tag 1) + (obj1 (req "kind" (constant "draw"))) + (function Draw -> Some () | _ -> None) + (fun () -> Draw); + ] + +type status = Ongoing | Ended of game_result + +let pp_status ppf status = + match status with + | Ongoing -> Format.fprintf ppf "Game ongoing" + | Ended game_result -> + Format.fprintf ppf "Game ended: %a" pp_game_result game_result + +let status_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Ongoing" + (Tag 0) + (constant "ongoing") + (function Ongoing -> Some () | _ -> None) + (fun () -> Ongoing); + case + ~title:"Ended" + (Tag 1) + (obj1 (req "result" game_result_encoding)) + (function Ended r -> Some r | _ -> None) + (fun r -> Ended r); + ] + +let find_choice dissection tick = + let open Result_syntax in + let rec traverse states = + match states with + | ({state_hash = _; tick = state_tick} as curr) :: next :: others -> + if Sc_rollup_tick_repr.(tick = state_tick) then Ok (curr, next) + else traverse (next :: others) + | _ -> tzfail (Dissection_choice_not_found tick) + in + traverse dissection + +(** Check that the chosen interval is a single tick. *) +let check_proof_distance_is_one ~start_tick ~stop_tick = + let dist = Sc_rollup_tick_repr.distance start_tick stop_tick in + error_unless Z.(equal dist one) (Proof_unexpected_section_size dist) + +(** Check the proof begins with the correct state. *) +let check_proof_start_state ~pvm ~start_state proof = + let start_proof = Sc_rollup_proof_repr.start_of_pvm_step ~pvm proof in + error_unless + (Option.equal State_hash.equal start_state (Some start_proof)) + (Proof_start_state_hash_mismatch + {start_state_hash = start_state; start_proof}) + +(** Check the proof stops with a different state than refuted one. *) +let check_proof_stop_state ~pvm ~stop_state input_given + (input_request : Sc_rollup_PVM_sig.input_request) proof validate = + let stop_proof = + match (input_given, input_request) with + | None, No_input_required + | Some _, Initial + | Some _, First_after _ + | Some _, Needs_reveal _ -> + Some (Sc_rollup_proof_repr.stop_of_pvm_step ~pvm proof) + | Some _, No_input_required + | None, Initial + | None, First_after _ + | None, Needs_reveal _ -> + None + in + error_unless + (let b = Option.equal State_hash.equal stop_state stop_proof in + if validate then b else not b) + (if validate then + Proof_stop_state_hash_failed_to_validate + {stop_state_hash = stop_state; stop_proof} + else + Proof_stop_state_hash_failed_to_refute + {stop_state_hash = stop_state; stop_proof}) + +(** Check the proof validates the stop state. *) +let check_proof_validate_stop_state ~stop_state input input_request proof = + check_proof_stop_state ~stop_state input input_request proof true + +(** Check the proof refutes the stop state. *) +let check_proof_refute_stop_state ~stop_state input input_request proof = + check_proof_stop_state ~stop_state input input_request proof false + +(** Returns the validity of the first final move on top of a dissection. *) +let validity_final_move ~pvm ~dal_parameters ~dal_activation_level + ~dal_attestation_lag ~dal_number_of_slots ~first_move ~metadata ~proof ~game + ~start_chunk ~stop_chunk ~is_reveal_enabled ~dal_attested_slots_validity_lag + = + let open Lwt_result_syntax in + let*! res = + let {inbox_snapshot; inbox_level; dal_snapshot; _} = game in + let*! valid = + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This function is not resilient to dal parameters changes + (cryptobox parameters or dal_attestation_lag for instance). *) + Sc_rollup_proof_repr.valid + ~pvm + ~metadata + inbox_snapshot + inbox_level + dal_snapshot + dal_parameters + ~dal_activation_level + ~dal_attestation_lag + ~dal_number_of_slots + ~is_reveal_enabled + ~dal_attested_slots_validity_lag + proof + in + let*? () = + if first_move then + check_proof_distance_is_one + ~start_tick:start_chunk.tick + ~stop_tick:stop_chunk.tick + else Result_syntax.return_unit + in + let*? () = + check_proof_start_state + ~pvm + ~start_state:start_chunk.state_hash + proof.pvm_step + in + match valid with + | Ok (input, input_request) -> + let*? () = + if first_move then + check_proof_refute_stop_state + ~pvm + ~stop_state:stop_chunk.state_hash + input + input_request + proof.pvm_step + else + check_proof_validate_stop_state + ~pvm + ~stop_state:stop_chunk.state_hash + input + input_request + proof.pvm_step + in + return_true + | _ -> return_false + in + Lwt.return @@ Result.value ~default:false res + +(** Returns the validity of the first final move on top of a dissection. + + It is valid if and only: + - The distance of the refuted dissection is [1]. + - The proof start on the agreed start state. + - The proof stop on the state different than the refuted one. + - The proof is correctly verified. +*) +let validity_first_final_move ~pvm ~dal_parameters ~dal_activation_level + ~dal_attestation_lag ~dal_number_of_slots ~metadata ~proof ~game + ~start_chunk ~stop_chunk = + validity_final_move + ~pvm + ~dal_parameters + ~dal_activation_level + ~dal_attestation_lag + ~dal_number_of_slots + ~first_move:true + ~metadata + ~proof + ~game + ~start_chunk + ~stop_chunk + +(** Returns the validity of the second final move. + + It is valid if and only: + - The proof start on the agreed start state. + - The proof stop on the state validates the refuted one. + - The proof is correctly verified. +*) +let validity_second_final_move ~pvm ~dal_parameters ~dal_activation_level + ~dal_attestation_lag ~dal_number_of_slots ~metadata ~agreed_start_chunk + ~refuted_stop_chunk ~game ~proof = + validity_final_move + ~pvm + ~dal_parameters + ~dal_activation_level + ~dal_attestation_lag + ~dal_number_of_slots + ~first_move:false + ~metadata + ~proof + ~game + ~start_chunk:agreed_start_chunk + ~stop_chunk:refuted_stop_chunk + +let cost_play ~step ~choice = + match step with + | Dissection states -> + let number_of_states = List.length states in + let hash_size = State_hash.size in + let tick_size = Sc_rollup_tick_repr.size_in_bytes choice in + Sc_rollup_costs.cost_check_dissection + ~number_of_states + ~tick_size + ~hash_size + | Proof _proof -> + (* + + Proof verification is complex. We choose to follow a very + rough overaproximation based on the idea that proof + verification for both the inbox and the execution step is + dominated by hash computation. + + Assuming that the worst case is a proof of the maximal + operation data length, we consider the cost of hashing a + balanced binary tree of this size (with a maximal size of + leaves since the hashing of internal nodes can be neglected. + + We also consider the largest tick known. At the time of writing + this comment, the largest tick is the origination tick of the + PVM. + + If we assume the following worst-case for origination tick: + - the origination has been done with a kernel of maximum size, and + - most of the computation cost is consumed by importing this kernel + in the PVM, + + We can simply consider, again, that the cost of hashing the imported + kernel dominates everything else. + + We multiply this number by 10 for extra safety. + + At the time of writing this comment, this leads to 372940 + mgas for the proof wellformedness verification and 372940 + mgas for the cost of executing a tick. + + *) + let overapproximated_hashing_size = + 2 * Constants_repr.max_operation_data_length + in + let scale10 x = Saturation_repr.(mul (safe_int 10) x) in + scale10 @@ Gas_limit_repr.atomic_step_cost + @@ Michelson_v1_gas_costs.cost_N_IBlake2b overapproximated_hashing_size + +let play kind dal_parameters ~dal_activation_level ~dal_attestation_lag + ~dal_number_of_slots ~stakers metadata game ~step ~choice ~is_reveal_enabled + ~dal_attested_slots_validity_lag = + let open Lwt_result_syntax in + let (Packed ((module PVM) as pvm)) = Sc_rollups.Kind.pvm_of kind in + let mk_loser loser = + let loser = Index.staker stakers loser in + Either.Left (Loser {loser; reason = Conflict_resolved}) + in + match (step, game.game_state) with + | Dissection states, Dissecting {dissection; default_number_of_sections} -> + let*? start_chunk, stop_chunk = find_choice dissection choice in + let*? () = + PVM.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + states + in + let new_game_state = + Dissecting {dissection = states; default_number_of_sections} + in + return + (Either.Right + { + turn = opponent game.turn; + inbox_snapshot = game.inbox_snapshot; + dal_snapshot = game.dal_snapshot; + start_level = game.start_level; + inbox_level = game.inbox_level; + game_state = new_game_state; + }) + | Dissection _, Final_move _ -> tzfail Dissecting_during_final_move + | Proof proof, Dissecting {dissection; default_number_of_sections = _} -> + let*? start_chunk, stop_chunk = find_choice dissection choice in + let*? pvm_step = + Sc_rollup_proof_repr.unserialize_pvm_step ~pvm proof.pvm_step + in + let proof = {proof with pvm_step} in + let*! player_result = + validity_first_final_move + ~pvm + ~dal_parameters + ~dal_activation_level + ~dal_attestation_lag + ~dal_number_of_slots + ~proof + ~metadata + ~game + ~start_chunk + ~stop_chunk + ~is_reveal_enabled + ~dal_attested_slots_validity_lag + in + if player_result then return @@ mk_loser (opponent game.turn) + else + let new_game_state = + let agreed_start_chunk = start_chunk in + let refuted_stop_chunk = stop_chunk in + Final_move {agreed_start_chunk; refuted_stop_chunk} + in + return + (Either.Right + { + turn = opponent game.turn; + inbox_snapshot = game.inbox_snapshot; + dal_snapshot = game.dal_snapshot; + start_level = game.start_level; + inbox_level = game.inbox_level; + game_state = new_game_state; + }) + | Proof proof, Final_move {agreed_start_chunk; refuted_stop_chunk} -> + let*? pvm_step = + Sc_rollup_proof_repr.unserialize_pvm_step ~pvm proof.pvm_step + in + let proof = {proof with pvm_step} in + let*! player_result = + validity_second_final_move + ~pvm + ~dal_parameters + ~dal_activation_level + ~dal_attestation_lag + ~dal_number_of_slots + ~metadata + ~agreed_start_chunk + ~refuted_stop_chunk + ~game + ~proof + ~is_reveal_enabled + ~dal_attested_slots_validity_lag + in + if player_result then + (* If we play when the final move started, the opponent provided + a invalid proof. So if the defender manages to provide a valid + proof, he wins. *) + return @@ mk_loser (opponent game.turn) + else return (Either.Left Draw) + +module Internal_for_tests = struct + let find_choice = find_choice + + let check_dissection ~default_number_of_sections ~start_chunk ~stop_chunk = + let open Sc_rollup_dissection_chunk_repr in + let dist = Sc_rollup_tick_repr.distance start_chunk.tick stop_chunk.tick in + let section_maximum_size = Z.div dist (Z.of_int 2) in + Sc_rollup_dissection_chunk_repr.( + default_check + ~section_maximum_size + ~check_sections_number:default_check_sections_number + ~default_number_of_sections + ~start_chunk + ~stop_chunk) +end + +type timeout = {alice : int; bob : int; last_turn_level : Raw_level_repr.t} + +let timeout_encoding = + let open Data_encoding in + conv + (fun {alice; bob; last_turn_level} -> (alice, bob, last_turn_level)) + (fun (alice, bob, last_turn_level) -> {alice; bob; last_turn_level}) + (obj3 + (req "alice" int31) + (req "bob" int31) + (req "last_turn_level" Raw_level_repr.encoding)) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.mli new file mode 100644 index 000000000000..632a7c44b04b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_game_repr.mli @@ -0,0 +1,445 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The smart contract rollup refutation game types are defined here, as + well as the basic pure logic for: + + - how to create a new game from a pair of commits in the commit tree; + + - how to update a game or complete a game when a move is played. + + This game logic is used by the protocol when two commitments are in + conflict to determine which one of the commitments is wrong. + + Game state and moves + ==================== + + The first step consists of dissecting the commitment's number of ticks. + The game stores a list [dissection] of state hashes and tick counts. + These are the claims about the PVM history made by the player who has + just moved. + + The next player to move will specify a tick count which appears in + the [dissection]; this is the last of the state hashes which she + agrees with. She will then either: + + - provide a new [dissection] by giving a list of state hashes and + tick counts that starts at the chosen tick count and ends at the + next tick count in the previous [dissection]. It must agree at the + start but disagree with the final state. + + - if the tick difference between this state and the next is one, + there is no 'room' for a new [dissection]. In this case she must + provide a Merkle proof that shows the step in the current + [dissection] is invalid. + + If a player failed to prove that the current [dissection] is valid. + We reach the final move of the game. The other player will have + a chance to prove that the [dissection] is valid. + If both player fails to invalidate each other, the game ends in a draw. + + Initializing a game + =================== + + In order to trigger the start of a game, one player must publish a + first move. + + The [initial] function is called at this point. It converts a + parent-child pair of commitments (belonging to the other player) into + an initial [dissection]. The first move is immediately applied to + this to give the first state of the game. + + Note: it is quite possible for the game to end immediately after + this first move, either if the commitment has a tick count of one or + more probably if the refutation proves that the commitment was + 'premature' (the state is not blocked---there are further + computation steps to do or more inbox messages to read). + + Expected properties + =================== + + P1 - If [dissection] is honest, the next move must be dishonest: + + There is only one honest state hash for a given tick count. The + next player must provide a different hash to the honest hash in + the [dissection]. + + P2 - If [dissection] is dishonest, there is a strategy for a player + equipped with a perfect PVM to play an honest next move: + + The player with a perfect PVM can calculate honest hashes until + one disagrees with the [dissection], and challenges the dissection + at that point, publishing either an honest [dissection] or an + honest [Proof]. + + Each [dissection] has a maximum tick count step shorter than the + last, so by induction using P1 and P2 we have + + P1' - If [dissection] is honest, the last player has a winning + strategy. + + P2' - If [dissection] is dishonest, the next player has a winning + strategy. + + This allows us to see the following. (We use [refuter] to mean the + first player to move, and [defender] to mean the other player.) + + Honest refuter wins: + An honest refuter will be refuting a dishonest commitment, because + there is only one honest state possible per level. Therefore the + initial [dissection] will be dishonest. By P2' the refuter has a + winning strategy. + + Honest defender wins: + An honest defender will have made an honest commitment which will + be translated into an honest initial [dissection]. By P1' the + defender has a winning strategy. + +*) + +open Sc_rollup_repr + +type error += + | Dissection_choice_not_found of Sc_rollup_tick_repr.t + (** The given choice in a refutation is not a starting tick of any of + the sections in the current dissection. *) + | Proof_unexpected_section_size of Z.t + (** Invalid proof step because there is more than one tick. *) + | Proof_start_state_hash_mismatch of { + start_state_hash : Sc_rollup_repr.State_hash.t option; + start_proof : Sc_rollup_repr.State_hash.t; + } + (** The given proof's starting state doesn't match the expected one. *) + | Proof_stop_state_hash_failed_to_refute of { + stop_state_hash : Sc_rollup_repr.State_hash.t option; + stop_proof : Sc_rollup_repr.State_hash.t option; + } + (** The given proof's ending state should not match the state being + refuted. *) + | Proof_stop_state_hash_failed_to_validate of { + stop_state_hash : Sc_rollup_repr.State_hash.t option; + stop_proof : Sc_rollup_repr.State_hash.t option; + } + (** The given proof's ending state should match the state being + refuted. *) + | Dissecting_during_final_move + (** The step move is a dissecting where the final move has started + already. *) + +(** The two stakers index the game in the storage as a pair of public + key hashes which is in lexical order. We use [Alice] and [Bob] to + represent the first and second player in the pair respectively. *) +type player = Alice | Bob + +module V1 : sig + type dissection_chunk = Sc_rollup_dissection_chunk_repr.t + + (** Describes the current state of a game. *) + type game_state = + | Dissecting of { + dissection : dissection_chunk list; + (** [dissection], a list of states with tick counts. The current + player will specify, in the next move, a tick count that + indicates the last of these states that she agrees with. *) + default_number_of_sections : int; + (** [default_number_of_sections] is the number of sections a + disection should contain in the more general case where we still + have a high enough number of disputed ticks. *) + } + (** When the state is [Dissecting], both player are still dissecting + the commitment to find the tick to refute. *) + | Final_move of { + agreed_start_chunk : dissection_chunk; + refuted_stop_chunk : dissection_chunk; + } + (** When the state is [Final_move], either [Alice] or [Bob] already + played an invalid proof. + + The other player will have a chance to prove that the + [refuted_stop_state] is valid. + If both players fail to either validate or refute the stop state, + the current game state describes a draw situation. + In the same way, the draw can be described by the situation where + the two players manage to validate or refute the stop state. *) + + val game_state_encoding : game_state Data_encoding.t + + val game_state_equal : game_state -> game_state -> bool + + (** A game is characterized by: + + - [refuter_commitment_hash], the hash of the commitment of the player that + has initiated the game. + + - [defender_commitment_hash], the hash of the commitment of the player that + is tentatively refuted. + + - [turn], the player that must provide the next move. + + - [inbox_snapshot], a snapshot of the inbox state at the moment the + game is created. This is only used when checking [Input_step] and + [Blocked_step] proofs; it makes the proofs easier to create--- + otherwise they would have a 'moving target' because the actual + inbox may be updated continuously. + + - [dal_snapshot], a snapshot of the DAL's confirmed slots history at the + moment the game is created. In fact, since the confirmed slots history at + initialization would likely evolve during the game, we need a (fixed) + reference w.r.t. which Dal input proofs would be produced and verified if + needed. + + - [level], the inbox level of the commitment the game is refuting. + This is only used when checking [Blocked_step] proofs---the proof + will show that the next message available in [inbox_snapshot] is + at [level], so shouldn't be included in this commitment. + + - [game_state], the current state of the game, see {!type-game_state} + for more information. + + Invariants: + ----------- + - [dissection] must contain at least 2 values (normally it will be 32 + values, but smaller if there isn't enough space for a dissection + that size. The initial game dissection will be 3 values except in + the case of a zero-tick commit when it will have 2 values.) + - the first state hash value in [dissection] must not be [None] + - [inbox_snapshot] and [dal_snapshot] never change once the game is created + *) + type t = { + turn : player; + inbox_snapshot : Sc_rollup_inbox_repr.history_proof; + dal_snapshot : Dal_slot_repr.History.t; + start_level : Raw_level_repr.t; + inbox_level : Raw_level_repr.t; + game_state : game_state; + } + + (** [equal g1 g2] returns [true] iff [g1] is equal to [g2]. *) + val equal : t -> t -> bool + + (** Return the other player *) + val opponent : player -> player + + val encoding : t Data_encoding.t + + val pp_dissection : Format.formatter -> dissection_chunk list -> unit + + val player_equal : player -> player -> bool + + val player_encoding : player Data_encoding.t + + val pp : Format.formatter -> t -> unit +end + +(** Versioning, see {!Sc_rollup_data_version_sig.S} for more information. *) +include Sc_rollup_data_version_sig.S with type t = V1.t + +include + module type of V1 + with type dissection_chunk = V1.dissection_chunk + and type game_state = V1.game_state + and type t = V1.t + +module Index : sig + type t = private {alice : Staker.t; bob : Staker.t} + + (** [to_path i p] returns a new path with the path to the game indexed + by [i] added as a prefix to path [p]. See [Path_encoding] module. *) + val to_path : t -> string list -> string list + + val of_path : string list -> t option + + val path_length : int + + val rpc_arg : t RPC_arg.t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int + + val make : Staker.t -> Staker.t -> t + + (** Given an index in normal form, resolve a given [player] ([Alice] + or [Bob]) to the actual staker they represent. *) + val staker : t -> player -> Staker.t +end + +(** To begin a game, first the conflict point in the commit tree is + found, and then this function is applied. + + [initial inbox dal_slots_history ~start_level ~parent_commitment + ~defender_commitment ~refuter ~defender ~default_number_of_sections] will + construct an initial game where [refuter] is next to play. The game has + [dissection] with three states: + + - firstly, the state (with tick zero) of [parent_commitment], the + commitment that both stakers agree on. + + - secondly, the state and tick count of [defender_commitment], the + commitment that [defender] has staked on. + + - thirdly, a [None] state which is a single tick after the + [defender_commitment] commitment. This represents the claim, implicit in + the commitment, that the state given is blocked. + + This gives [refuter] a binary choice: she can refute the commit + itself by providing a new dissection between the two committed + states, or she can refute the claim that the [child] commit is a + blocked state by immediately providing a proof of a single tick + increment from that state to its successor. *) +val initial : + Sc_rollup_inbox_repr.history_proof -> + Dal_slot_repr.History.t -> + start_level:Raw_level_repr.t -> + parent_commitment:Sc_rollup_commitment_repr.t -> + defender_commitment:Sc_rollup_commitment_repr.t -> + refuter:Signature.public_key_hash -> + defender:Signature.public_key_hash -> + default_number_of_sections:int -> + t + +(** A [step] in the game is either a new dissection (if there are + intermediate ticks remaining to put in it) or a proof. *) +type step = + | Dissection of dissection_chunk list + | Proof of Sc_rollup_proof_repr.serialized Sc_rollup_proof_repr.t + +(** A [refutation] is a move in the game. *) +type refutation = + | Start of { + player_commitment_hash : Sc_rollup_commitment_repr.Hash.t; + opponent_commitment_hash : Sc_rollup_commitment_repr.Hash.t; + } + | Move of {choice : Sc_rollup_tick_repr.t; step : step} + (** [choice] is the final tick in the current dissection at which + the two players agree. *) + +val pp_refutation : Format.formatter -> refutation -> unit + +val refutation_encoding : refutation Data_encoding.t + +(** A game ends for one of two reasons: the conflict has been +resolved via a proof or a player has been timed out. *) +type reason = Conflict_resolved | Timeout + +val pp_reason : Format.formatter -> reason -> unit + +val reason_encoding : reason Data_encoding.t + +(** The game result. *) +type game_result = + | Loser of {reason : reason; loser : Staker.t} (** One player lost. *) + | Draw (** The game ended in a draw *) + +val pp_game_result : Format.formatter -> game_result -> unit + +val game_result_encoding : game_result Data_encoding.t + +(** A type that represents the current game status in a way that is + useful to the outside world (using actual [Staker.t] values + instead of the internal [player] type). + + The [Staker.t] in the [Ended] case is the loser of the game: the + staker who will have their stake slashed. + + Used in operation result types. *) +type status = Ongoing | Ended of game_result + +val pp_status : Format.formatter -> status -> unit + +val status_encoding : status Data_encoding.t + +(* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + Providing DAL parameters here is not resilient to their change during + protocol upgrade. *) + +(** Applies the move [refutation] to the game. Returns the game {!status} + after applying the move. + + In the case of the game continuing, this swaps the current + player and returns a [Ongoing] status. Otherwise, it returns a + [Ended ] status. + + The provided DAL related parameters are used in case the game needs to: + - Check that a page's content is part of a slot (using the slot's commitment) + when refuting a DAL page reveal. + - Check that the parameters are correct when refuting a DAL parameter reveal. +*) +val play : + Sc_rollups.Kind.t -> + Dal_slot_repr.parameters -> + dal_activation_level:Raw_level_repr.t option -> + dal_attestation_lag:int -> + dal_number_of_slots:int -> + stakers:Index.t -> + Sc_rollup_metadata_repr.t -> + t -> + step:step -> + choice:Sc_rollup_tick_repr.t -> + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + dal_attested_slots_validity_lag:int -> + (game_result, t) Either.t tzresult Lwt.t + +(** [cost_play ~step ~choice] returns the gas cost of [play] applied with[step], + and [choice]. *) +val cost_play : step:step -> choice:Sc_rollup_tick_repr.t -> Gas_limit_repr.cost + +(** A type that represents the number of blocks left for players to play. Each + player has her timeout value. `timeout` is expressed in the number of + blocks. + + Timeout logic is similar to a chess clock. Each player starts with the same + timeout. Each game move updates the timeout of the current player by + decreasing it by the amount of time she took to play, i.e. number of blocks + since the opponent last move. See {!Sc_rollup_refutation_storage.game_move} + to see the implementation. +*) +type timeout = { + alice : int; (** Timeout of [Alice]. *) + bob : int; (** Timeout of [Bob]. *) + last_turn_level : Raw_level_repr.t; (** Block level of the last turn move. *) +} + +val timeout_encoding : timeout Data_encoding.t + +module Internal_for_tests : sig + (** Checks that the tick count chosen by the current move is one of + the ones in the current dissection. Returns a tuple containing + the current dissection interval (including the two states) between + this tick and the next. *) + val find_choice : + dissection_chunk list -> + Sc_rollup_tick_repr.t -> + (dissection_chunk * dissection_chunk) tzresult + + (** See {!Sc_rollup_dissection_chunk_repr.default_check} *) + val check_dissection : + default_number_of_sections:int -> + start_chunk:dissection_chunk -> + stop_chunk:dissection_chunk -> + dissection_chunk list -> + unit tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.ml new file mode 100644 index 000000000000..909b39762ec5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.ml @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type error += (* `Permanent *) Merkelized_payload_hashes_proof_error of string + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"internal.smart_rollup_merklized_payload_hashes_proof" + ~title: + "Internal error: error occurred during proof production or validation" + ~description:"A merkelized payload hashes proof error." + ~pp:(fun ppf e -> Format.fprintf ppf "Proof error: %s" e) + (obj1 (req "error" (string Plain))) + (function Merkelized_payload_hashes_proof_error e -> Some e | _ -> None) + (fun e -> Merkelized_payload_hashes_proof_error e) + +module Skip_list_parameters = struct + let basis = 4 +end + +module Skip_list = Skip_list.Make (Skip_list_parameters) +module Hash = Smart_rollup.Merkelized_payload_hashes_hash + +type t = (Sc_rollup_inbox_message_repr.Hash.t, Hash.t) Skip_list.cell + +let equal = Skip_list.equal Hash.equal Sc_rollup_inbox_message_repr.Hash.equal + +let hash merkelized = + let payload_hash = Skip_list.content merkelized in + let back_pointers_hashes = Skip_list.back_pointers merkelized in + Sc_rollup_inbox_message_repr.Hash.to_bytes payload_hash + :: List.map Hash.to_bytes back_pointers_hashes + |> Hash.hash_bytes + +let pp fmt merkelized = + Format.fprintf + fmt + "@[cell ptr: %a@,@[cell content:@,%a@]@]" + Hash.pp_short + (hash merkelized) + (Skip_list.pp + ~pp_content:Sc_rollup_inbox_message_repr.Hash.pp_short + ~pp_ptr:Hash.pp_short) + merkelized + +let encoding = + Skip_list.encoding Hash.encoding Sc_rollup_inbox_message_repr.Hash.encoding + +type merkelized_and_payload = { + merkelized : t; + payload : Sc_rollup_inbox_message_repr.serialized; +} + +let equal_merkelized_and_payload {merkelized; payload} mp2 = + equal merkelized mp2.merkelized + && String.equal (payload :> string) (mp2.payload :> string) + +let pp_merkelized_and_payload fmt {merkelized; payload} = + Format.fprintf + fmt + "@[merkelized:@,%a@,payload: %a@]" + pp + merkelized + Format.pp_print_string + (payload :> string) + +let merkelized_and_payload_encoding = + let open Data_encoding in + conv + (fun {merkelized; payload} -> (merkelized, (payload :> string))) + (fun (merkelized, payload) -> + { + merkelized; + payload = Sc_rollup_inbox_message_repr.unsafe_of_string payload; + }) + (merge_objs encoding (obj1 (req "payload" (string Hex)))) + +module History = struct + include + Bounded_history_repr.Make + (struct + let name = "Smart_rollup_level_inbox_history" + end) + (Hash) + (struct + type nonrec t = merkelized_and_payload + + let pp = pp_merkelized_and_payload + + let equal = equal_merkelized_and_payload + + let encoding = merkelized_and_payload_encoding + end) + + let no_history = empty ~capacity:0L +end + +let remember history merkelized payload = + let prev_cell_ptr = hash merkelized in + History.remember prev_cell_ptr {merkelized; payload} history + +let genesis_no_history payload = + let payload_hash = + Sc_rollup_inbox_message_repr.hash_serialized_message payload + in + Skip_list.genesis payload_hash + +let genesis history payload = + let open Result_syntax in + let merkelized = genesis_no_history payload in + let+ history = remember history merkelized payload in + (history, merkelized) + +let add_payload_no_history prev_merkelized payload = + let prev_merkelized_ptr = hash prev_merkelized in + Skip_list.next + ~prev_cell:prev_merkelized + ~prev_cell_ptr:prev_merkelized_ptr + (Sc_rollup_inbox_message_repr.hash_serialized_message payload) + +let add_payload history prev_merkelized payload = + let open Result_syntax in + let merkelized = add_payload_no_history prev_merkelized payload in + let* history = remember history merkelized payload in + return (history, merkelized) + +let get_payload_hash = Skip_list.content + +let get_index = Skip_list.index + +type proof = t list + +let pp_proof = Format.pp_print_list pp + +let proof_encoding = Data_encoding.list encoding + +let produce_proof history ~index merkelized = + let open Option_syntax in + let deref ptr = + let* {merkelized; payload = _} = History.find ptr history in + return merkelized + in + let current_ptr = hash merkelized in + let lift_ptr = + let rec aux acc = function + | [] -> None + | [last_ptr] -> + let+ ({merkelized; _} as merkelized_and_payload) = + History.find last_ptr history + in + (merkelized_and_payload, List.rev (merkelized :: acc)) + | ptr :: rest -> + let* merkelized = deref ptr in + aux (merkelized :: acc) rest + in + aux [] + in + let* ptr_path = + Skip_list.back_path ~deref ~cell_ptr:current_ptr ~target_index:index + in + lift_ptr ptr_path + +let verify_proof inclusion_proof = + let open Result_syntax in + let* cell = + match inclusion_proof with + | cell :: _ -> return cell + | [] -> tzfail (Merkelized_payload_hashes_proof_error "proof is empty") + in + let rec aux (hash_map, ptr_list) = function + | [] -> tzfail (Merkelized_payload_hashes_proof_error "proof is empty") + | [target] -> + let target_ptr = hash target in + let hash_map = Hash.Map.add target_ptr target hash_map in + let ptr_list = List.rev (target_ptr :: ptr_list) in + return (hash_map, ptr_list, target, target_ptr) + | merkelized :: tail -> + let ptr = hash merkelized in + aux (Hash.Map.add ptr merkelized hash_map, ptr :: ptr_list) tail + in + let* hash_map, ptr_list, target, target_ptr = + aux (Hash.Map.empty, []) inclusion_proof + in + let deref ptr = Hash.Map.find ptr hash_map in + let cell_ptr = hash cell in + let* () = + error_unless + (Skip_list.valid_back_path + ~equal_ptr:Hash.equal + ~deref + ~cell_ptr + ~target_ptr + ptr_list) + (Merkelized_payload_hashes_proof_error "invalid proof") + in + return (target, cell) + +module Internal_for_tests = struct + let find_predecessor_payload payloads_history ~index payloads = + let open Option_syntax in + let deref ptr = + let* {merkelized; _} = History.find ptr payloads_history in + return merkelized + in + let cell_ptr = hash payloads in + Skip_list.find ~deref ~cell_ptr ~target_index:index + + let make_proof proof = proof +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.mli new file mode 100644 index 000000000000..9ef2a237d0f7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_merkelized_payload_hashes_repr.mli @@ -0,0 +1,118 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type error += Merkelized_payload_hashes_proof_error of string + +module Hash : S.HASH with type t = Smart_rollup.Merkelized_payload_hashes_hash.t + +(** A type representing the head of a merkelized list of + {!Sc_rollup_inbox_message_repr.serialized} message. It contains the hash of + the payload and the index on the list. *) +type t + +val encoding : t Data_encoding.t + +type merkelized_and_payload = { + merkelized : t; + payload : Sc_rollup_inbox_message_repr.serialized; +} + +(** A [History.t] is a lookup table of {!merkelized_and_payload}s. Payloads are + indexed by their hash {!Hash.t}. This history is needed in order to produce + {!proof}. + + A subtlety of this [history] type is that it is customizable depending on + how much of the inbox history you actually want to remember, using the + [capacity] parameter. In the L1 we use this with [capacity] set to zero, + which makes it immediately forget an old level as soon as we move to the + next. By contrast, the rollup node uses a history that is sufficiently large + to be able to take part in all potential refutation games occurring during + the challenge period. *) +module History : sig + include + Bounded_history_repr.S + with type key = Hash.t + and type value = merkelized_and_payload + + val no_history : t +end + +(** [hash merkelized] is the hash of [merkelized]. It is used as key to remember + a merkelized payload hash in an {!History.t}. *) +val hash : t -> Hash.t + +(** [remember history merkelized payload] remembers the [{merkelized; payload}] + in [history] with key [hash merkelized]. *) +val remember : + History.t -> + t -> + Sc_rollup_inbox_message_repr.serialized -> + History.t tzresult + +(** [genesis_no_history payload] is the initial merkelized payload hashes with + index 0. *) +val genesis_no_history : Sc_rollup_inbox_message_repr.serialized -> t + +(** [genesis history payload] is the initial merkelized payload hashes with + index 0. It is remembered in [history] using [remember]. *) +val genesis : + History.t -> + Sc_rollup_inbox_message_repr.serialized -> + (History.t * t) tzresult + +(** [add_payload_no_history merkelized payload] creates a new {!t} with [payload] + and [merkelized] as ancestor (i.e. [index = succ (get_index + merkelized)]). *) +val add_payload_no_history : t -> Sc_rollup_inbox_message_repr.serialized -> t + +(** [add_payload] is identical to {!add_payload_no_history} but the resulting + [merkelized] is remembered in [history] with [remember]. *) +val add_payload : + History.t -> + t -> + Sc_rollup_inbox_message_repr.serialized -> + (History.t * t) tzresult + +val equal : t -> t -> bool + +val pp : Format.formatter -> t -> unit + +(** [get_payload_hash merkelized] returns the + {!Sc_rollup_inbox_message_repr.serialized} payload's hash of + [merkelized]. *) +val get_payload_hash : t -> Sc_rollup_inbox_message_repr.Hash.t + +(** [get_index merkelized] returns the index of [merkelized]. *) +val get_index : t -> Z.t + +(** Given two t [(a, b)] and a {!Sc_rollup_inbox_message_repr.serialized} + [payload], a [proof] guarantees that [payload] hash is equal to [a] and that + [a] is an ancestor of [b]; i.e. [get_index a < get_index b]. *) +type proof = private t list + +val pp_proof : Format.formatter -> proof -> unit + +val proof_encoding : proof Data_encoding.t + +(** [produce_proof history ~index into_] returns a {!merkelized_and_payload} + with index [index] and a proof that it is an ancestor of [into_]. Returns + [None] if no merkelized payload with [index] is found (either in the + [history] or [index] is not inferior to [get_index into_]). *) +val produce_proof : + History.t -> index:Z.t -> t -> (merkelized_and_payload * proof) option + +(** [verify_proof proof] returns [(a, b)] where [proof] validates that [a] is an + ancestor of [b]. Fails when [proof] is not a valid inclusion proof. *) +val verify_proof : proof -> (t * t) tzresult + +module Internal_for_tests : sig + (** [find_predecessor_payload history ~index latest_merkelized] looks for the + {!t} with [index] that is an ancestor of [latest_merkelized]. *) + val find_predecessor_payload : History.t -> index:Z.t -> t -> t option + + val make_proof : t list -> proof +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.ml new file mode 100644 index 000000000000..e8a6f5e7be1d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.ml @@ -0,0 +1,223 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Permanent *) Error_encode_inbox_message + | (* `Permanent *) Error_decode_inbox_message + +let () = + let open Data_encoding in + let msg = + "Failed to encode a rollup management protocol inbox message value" + in + register_error_kind + `Permanent + ~id:"smart_rollup_inbox_message_encoding" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Error_encode_inbox_message -> Some () | _ -> None) + (fun () -> Error_encode_inbox_message) ; + let msg = + "Failed to decode a smart rollup management protocol inbox message value" + in + register_error_kind + `Permanent + ~id:"smart_rollup_inbox_message_decoding" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Error_decode_inbox_message -> Some () | _ -> None) + (fun () -> Error_decode_inbox_message) + +type internal_inbox_message = + | Transfer of { + payload : Script_repr.expr; + sender : Contract_hash.t; + source : Signature.public_key_hash; + destination : Sc_rollup_repr.Address.t; + } + | Start_of_level + | End_of_level + | Info_per_level of { + predecessor_timestamp : Time.t; + predecessor : Block_hash.t; + } + | Protocol_migration of string + +let internal_inbox_message_encoding = + let open Data_encoding in + let kind name = req "internal_inbox_message_kind" (constant name) in + union + [ + case + (Tag 0) + ~title:"Transfer" + (obj5 + (kind "transfer") + (req "payload" Script_repr.expr_encoding) + (req "sender" Contract_hash.encoding) + (req "source" Signature.Public_key_hash.encoding) + (req "destination" Sc_rollup_repr.Address.encoding)) + (function + | Transfer {payload; sender; source; destination} -> + Some ((), payload, sender, source, destination) + | _ -> None) + (fun ((), payload, sender, source, destination) -> + Transfer {payload; sender; source; destination}); + case + (Tag 1) + ~title:"Start_of_level" + (obj1 (kind "start_of_level")) + (function Start_of_level -> Some () | _ -> None) + (fun () -> Start_of_level); + case + (Tag 2) + ~title:"End_of_level" + (obj1 (kind "end_of_level")) + (function End_of_level -> Some () | _ -> None) + (fun () -> End_of_level); + case + (Tag 3) + ~title:"Info_per_level" + (obj3 + (kind "info_per_level") + (req "predecessor_timestamp" Time.encoding) + (req "predecessor" Block_hash.encoding)) + (function + | Info_per_level {predecessor_timestamp; predecessor} -> + Some ((), predecessor_timestamp, predecessor) + | _ -> None) + (fun ((), predecessor_timestamp, predecessor) -> + Info_per_level {predecessor_timestamp; predecessor}); + case + (Tag 4) + ~title:"Protocol_migration" + (obj2 (kind "protocol_migration") (req "protocol" (string Hex))) + (function Protocol_migration proto -> Some ((), proto) | _ -> None) + (fun ((), proto) -> Protocol_migration proto); + ] + +type t = Internal of internal_inbox_message | External of string + +let encoding = + let open Data_encoding in + check_size + Constants_repr.sc_rollup_message_size_limit + (union + [ + case + (Tag 0) + ~title:"Internal" + internal_inbox_message_encoding + (function + | Internal internal_message -> Some internal_message + | External _ -> None) + (fun internal_message -> Internal internal_message); + case + (Tag 1) + ~title:"External" + Variable.(string Hex) + (function External msg -> Some msg | Internal _ -> None) + (fun msg -> External msg); + ]) + +type serialized = string + +let serialize msg = + let open Result_syntax in + match Data_encoding.Binary.to_string_opt encoding msg with + | None -> tzfail Error_encode_inbox_message + | Some str -> return str + +let deserialize s = + let open Result_syntax in + match Data_encoding.Binary.of_string_opt encoding s with + | None -> tzfail Error_decode_inbox_message + | Some msg -> return msg + +let unsafe_of_string s = s + +let unsafe_to_string s = s + +(* 32 *) +let hash_prefix = "\003\255\138\145\170" (* srib3(55) *) + +module Hash = struct + let prefix = "srib3" + + let encoded_size = 55 + + module H = + Blake2B.Make + (Base58) + (struct + let name = "Smart_rollup_serialized_message_hash" + + let title = + "The hash of a serialized message of the smart rollup inbox." + + let b58check_prefix = hash_prefix + + (* defaults to 32 *) + let size = None + end) + + include H + + let () = Base58.check_encoded_prefix b58check_encoding prefix encoded_size +end + +let hash_serialized_message (payload : serialized) = + Hash.hash_string [(payload :> string)] + +let start_of_level_serialized = + (* If [Start_of_level] cannot be serialized, this will be detected at + startup time as we are defining a top-level value. *) + Data_encoding.Binary.to_string_exn encoding (Internal Start_of_level) + +let end_of_level_serialized = + (* If [End_of_level] cannot be serialized, this will be detected at + startup time as we are defining a top-level value. *) + Data_encoding.Binary.to_string_exn encoding (Internal End_of_level) + +let info_per_level_serialized ~predecessor_timestamp ~predecessor = + match + serialize (Internal (Info_per_level {predecessor_timestamp; predecessor})) + with + | Error _ -> + (* The info per level should always be serializable as the encoding + functions for this case do not fail. *) + assert false + | Ok info -> info + +let (_dummy_serialized_info_per_level_serialized : serialized) = + (* This allows to detect an error, at startup, we might have introduced in the + encoding of serialization of info per level messages . *) + info_per_level_serialized + ~predecessor_timestamp:(Time.of_seconds Int64.min_int) + ~predecessor:Block_hash.zero diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.mli new file mode 100644 index 000000000000..c4873becc4ea --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_message_repr.mli @@ -0,0 +1,107 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module exposes a type {!t} that represents inbox messages. Inbox + messages are produced by the Layer 1 protocol and are encoded using the + {!serialize} function, before being added to a smart-contract rollup's inbox. + + They are part of the [Rollup Management Protocol] that defines the + communication protocol for exchanging messages between Layer 1 and Layer 2 + for a smart-contract rollup. + + There are two types of inbox messages: external and internal. + + Internal messages originate from Layer 1 smart-contract and consist of: + - [payload] the parameters passed to the smart-contract rollup. + - [sender] the Layer 1 contract caller. + - [source] the public key hash used for originating the transaction. + + External messages originate from the [Sc_rollup_add_messages] + manager-operation and consists of strings. The Layer 2 node is responsible + for decoding and interpreting these messages. + *) + +(** [internal_inbox_message] represent an internal message in a inbox (L1 -> + L2). This is not inline so it can easily be used by + {!Sc_rollup_costs.cost_serialize_internal_inbox_message}. *) +type internal_inbox_message = + | Transfer of { + payload : Script_repr.expr; + (** A Micheline value containing the parameters passed to the rollup. *) + sender : Contract_hash.t; + (** The contract hash of an Layer 1 originated contract sending a message + to the rollup. *) + source : Signature.public_key_hash; + (** The implicit account that originated the transaction. *) + destination : Sc_rollup_repr.Address.t; + (** The destination, as a rollup address, for the message. *) + } + | Start_of_level + (** Internal message put at the beginning of each inbox's level. *) + | End_of_level (** Internal message put at the end of each inbox's level. *) + | Info_per_level of { + predecessor_timestamp : Time.t; + (** Timestamp of the predecessor block where this message is + pushed. *) + predecessor : Block_hash.t; + (** Predecessor of the block this message is pushed. *) + } + | Protocol_migration of string + +(** A type representing messages from Layer 1 to Layer 2. Internal ones are + originated from Layer 1 smart-contracts and external ones are messages from + an external manager operation. *) +type t = Internal of internal_inbox_message | External of string + +type serialized = private string + +(** Encoding for messages from Layer 1 to Layer 2 *) +val encoding : t Data_encoding.t + +(** [serialize msg] encodes the inbox message [msg] in binary format. *) +val serialize : t -> serialized tzresult + +(** [deserialize bs] decodes [bs] as an inbox_message [t]. *) +val deserialize : serialized -> t tzresult + +val unsafe_of_string : string -> serialized + +val unsafe_to_string : serialized -> string + +module Hash : S.HASH + +(** [hash_serialized_message payload] is the hash of [payload]. It is used by + {!Sc_rollup_inbox_merkelized_payload_hashes_repr.t}. *) +val hash_serialized_message : serialized -> Hash.t + +(** {!serialized} representation of [Internal [Start_of_level]]. *) +val start_of_level_serialized : serialized + +(** {!serialized} representation of [Internal [End_of_level]]. *) +val end_of_level_serialized : serialized + +(** {!info_per_level_serialized ~predecessor_timestamp ~predecessor} is the serialized representation of the internal message for {!Info_per_level}. *) +val info_per_level_serialized : + predecessor_timestamp:Time.t -> predecessor:Block_hash.t -> serialized diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.ml new file mode 100644 index 000000000000..aba4043dde4b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.ml @@ -0,0 +1,857 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + + A Merkelized inbox represents a list of messages. This list + is decomposed into sublists of messages, one for each Tezos level greater + than the level where SCORU is activated. + + This module is designed to: + + 1. provide a space-efficient representation for proofs of inbox + inclusions (only for inboxes obtained at the end of block + validation) ; + + 2. offer an efficient function to add a new batch of messages in the + inbox at the current level. + + To solve (1), we use a proof tree H which is implemented by a merkelized skip + list allowing for compact inclusion proofs (See {!skip_list_repr.ml}). + + To solve (2), we maintain a separate proof tree C witnessing the contents of + messages of the current level also implemented by a merkelized skip list for + the same reason. + + The protocol maintains the hashes of the head of H and C. + + The rollup node needs to maintain a full representation for C and a + partial representation for H back to the level of the LCC. + +*) +type error += Inbox_proof_error of string + +type error += Tried_to_add_zero_messages + +type error += Inbox_level_reached_messages_limit + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"internal.smart_rollup_inbox_proof_error" + ~title: + "Internal error: error occurred during proof production or validation" + ~description:"An inbox proof error." + ~pp:(fun ppf e -> Format.fprintf ppf "Inbox proof error: %s" e) + (obj1 (req "error" (string Plain))) + (function Inbox_proof_error e -> Some e | _ -> None) + (fun e -> Inbox_proof_error e) ; + + register_error_kind + `Permanent + ~id:"internal.smart_rollup_add_zero_messages" + ~title:"Internal error: trying to add zero messages" + ~description: + "Message adding functions must be called with a positive number of \ + messages" + ~pp:(fun ppf _ -> Format.fprintf ppf "Tried to add zero messages") + empty + (function Tried_to_add_zero_messages -> Some () | _ -> None) + (fun () -> Tried_to_add_zero_messages) ; + + let description = + Format.sprintf + "There can be only %s messages in an inbox level, the limit has been \ + reached." + (Z.to_string Constants_repr.sc_rollup_max_number_of_messages_per_level) + in + register_error_kind + `Permanent + ~id:"smart_rollup_inbox_level_reached_message_limit" + ~title:"Inbox level reached messages limit" + ~description + ~pp:(fun ppf _ -> Format.pp_print_string ppf description) + empty + (function Inbox_level_reached_messages_limit -> Some () | _ -> None) + (fun () -> Inbox_level_reached_messages_limit) + +module Int64_map = Map.Make (Int64) +module Hash = Smart_rollup.Inbox_hash + +module Skip_list_parameters = struct + let basis = 4 +end + +module Skip_list = Skip_list.Make (Skip_list_parameters) + +module V1 = struct + type level_proof = { + hash : Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t; + level : Raw_level_repr.t; + } + + let level_proof_encoding = + let open Data_encoding in + conv + (fun {hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 + (req + "hash" + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.encoding) + (req "level" Raw_level_repr.encoding)) + + let equal_level_proof {hash; level} level_proof_2 = + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.equal + hash + level_proof_2.hash + && Raw_level_repr.equal level level_proof_2.level + + type history_proof = (level_proof, Hash.t) Skip_list.cell + + let hash_history_proof cell = + let {hash; level} = Skip_list.content cell in + let back_pointers_hashes = Skip_list.back_pointers cell in + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.to_bytes hash + :: (Raw_level_repr.to_int32 level |> Int32.to_string |> Bytes.of_string) + :: List.map Hash.to_bytes back_pointers_hashes + |> Hash.hash_bytes + + let equal_history_proof = Skip_list.equal Hash.equal equal_level_proof + + let history_proof_encoding : history_proof Data_encoding.t = + Skip_list.encoding Hash.encoding level_proof_encoding + + let pp_level_proof fmt {hash; level} = + Format.fprintf + fmt + "hash: %a@,level: %a" + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.pp + hash + Raw_level_repr.pp + level + + let pp_history_proof fmt history_proof = + (Skip_list.pp ~pp_content:pp_level_proof ~pp_ptr:Hash.pp) fmt history_proof + + (** Construct an inbox [history] with a given [capacity]. If you + are running a rollup node, [capacity] needs to be large enough to + remember any levels for which you may need to produce proofs. *) + module History = + Bounded_history_repr.Make + (struct + let name = "Smart_rollup_inbox_history" + end) + (Hash) + (struct + type t = history_proof + + let pp = pp_history_proof + + let equal = equal_history_proof + + let encoding = history_proof_encoding + end) + + (* An inbox is composed of a metadata of type {!t}, and a [level witness] + representing the messages of the current level (held by the + [Raw_context.t] in the protocol). + + The metadata contains : + - [level] : the inbox level ; + - [old_levels_messages] : a witness of the inbox history. + *) + type t = {level : Raw_level_repr.t; old_levels_messages : history_proof} + + let equal inbox1 inbox2 = + (* To be robust to addition of fields in [t]. *) + let {level; old_levels_messages} = inbox1 in + Raw_level_repr.equal level inbox2.level + && equal_history_proof old_levels_messages inbox2.old_levels_messages + + let pp fmt {level; old_levels_messages} = + Format.fprintf + fmt + "@[{ level = %a@;old_levels_messages = %a@;}@]" + Raw_level_repr.pp + level + pp_history_proof + old_levels_messages + + let hash inbox = hash_history_proof inbox.old_levels_messages + + let inbox_level inbox = inbox.level + + let old_levels_messages inbox = inbox.old_levels_messages + + let current_witness inbox = + let {hash; _} = Skip_list.content inbox.old_levels_messages in + hash + + let encoding = + Data_encoding.( + conv + (fun {level; old_levels_messages} -> (level, old_levels_messages)) + (fun (level, old_levels_messages) -> {level; old_levels_messages}) + (obj2 + (req "level" Raw_level_repr.encoding) + (req "old_levels_messages" history_proof_encoding))) +end + +type versioned = V1 of V1.t + +let versioned_encoding = + let open Data_encoding in + union + [ + case + ~title:"V1" + (Tag 0) + V1.encoding + (function V1 inbox -> Some inbox) + (fun inbox -> V1 inbox); + ] + +include V1 + +let of_versioned = function V1 inbox -> inbox [@@inline] + +let to_versioned inbox = V1 inbox [@@inline] + +type serialized_proof = string + +let serialized_proof_encoding = Data_encoding.(string Hex) + +type payloads_proof = { + proof : Sc_rollup_inbox_merkelized_payload_hashes_repr.proof; + payload : Sc_rollup_inbox_message_repr.serialized option; +} + +let payloads_proof_encoding = + let open Data_encoding in + conv + (fun {proof; payload} -> (proof, (payload :> string option))) + (fun (proof, payload) -> + { + proof; + payload = + Option.map Sc_rollup_inbox_message_repr.unsafe_of_string payload; + }) + (obj2 + (req + "proof" + Sc_rollup_inbox_merkelized_payload_hashes_repr.proof_encoding) + (opt "payload" (string Hex))) + +let add_protocol_internal_message payload payloads_history witness = + Sc_rollup_inbox_merkelized_payload_hashes_repr.add_payload + payloads_history + witness + payload + +let add_protocol_internal_message_no_history payload witness = + Sc_rollup_inbox_merkelized_payload_hashes_repr.add_payload_no_history + witness + payload + +let add_message payload payloads_history witness = + let open Result_syntax in + let message_counter = + Sc_rollup_inbox_merkelized_payload_hashes_repr.get_index witness + in + let* () = + let max_number_of_messages_per_level = + Constants_repr.sc_rollup_max_number_of_messages_per_level + in + error_unless + Compare.Z.(message_counter <= max_number_of_messages_per_level) + Inbox_level_reached_messages_limit + in + Sc_rollup_inbox_merkelized_payload_hashes_repr.add_payload + payloads_history + witness + payload + +let take_snapshot inbox = inbox.old_levels_messages + +(** [archive history inbox witness] archives the current inbox level depending + on the [history] parameter's [capacity]. Updates the + [inbox.current_level] and [inbox.old_levels_messages]. *) +let archive history inbox witness = + let open Result_syntax in + (* [form_history_proof history inbox] adds the current inbox level to the + history and creates new [inbox.old_levels_messages] including + the current level. *) + let form_history_proof history inbox = + let prev_cell = inbox.old_levels_messages in + let prev_cell_ptr = hash_history_proof prev_cell in + let* history = History.remember prev_cell_ptr prev_cell history in + let current_level_proof = + let hash = Sc_rollup_inbox_merkelized_payload_hashes_repr.hash witness in + {hash; level = inbox.level} + in + let cell = Skip_list.next ~prev_cell ~prev_cell_ptr current_level_proof in + return (history, cell) + in + let* history, old_levels_messages = form_history_proof history inbox in + let inbox = {inbox with old_levels_messages} in + return (history, inbox) + +(** [archive_no_history inbox witness] archives the current inbox level. Updates + the [inbox.current_level] and [inbox.old_levels_messages]. *) +let archive_no_history inbox witness = + let old_levels_messages = + let prev_cell = inbox.old_levels_messages in + let prev_cell_ptr = hash_history_proof prev_cell in + let current_level_proof = + let hash = Sc_rollup_inbox_merkelized_payload_hashes_repr.hash witness in + {hash; level = inbox.level} + in + Skip_list.next ~prev_cell ~prev_cell_ptr current_level_proof + in + {inbox with old_levels_messages} + +let add_messages payloads_history payloads witness = + let open Result_syntax in + let* () = + error_when + (match payloads with [] -> true | _ -> false) + Tried_to_add_zero_messages + in + let* payloads_history, witness = + List.fold_left_e + (fun (payloads_history, witness) payload -> + add_message payload payloads_history witness) + (payloads_history, witness) + payloads + in + return (payloads_history, witness) + +let add_messages_no_history payloads witness = + let open Result_syntax in + let+ _, witness = + add_messages + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.no_history + payloads + witness + in + witness + +(* An [inclusion_proof] is a path in the Merkelized skip list + showing that a given inbox history is a prefix of another one. + This path has a size logarithmic in the difference between the + levels of the two inboxes. *) +type inclusion_proof = history_proof list + +let inclusion_proof_encoding = + let open Data_encoding in + list history_proof_encoding + +let pp_inclusion_proof = Format.pp_print_list pp_history_proof + +let pp_payloads_proof fmt {proof; payload} = + Format.fprintf + fmt + "payload: %a@,@[proof:@,%a@]" + Format.( + pp_print_option + ~none:(fun fmt () -> pp_print_string fmt "None") + (fun fmt payload -> + pp_print_string + fmt + (Sc_rollup_inbox_message_repr.unsafe_to_string payload))) + payload + Sc_rollup_inbox_merkelized_payload_hashes_repr.pp_proof + proof + +(* See the main docstring for this type (in the mli file) for + definitions of the three proof parameters [starting_point], + [message] and [snapshot]. In the below we deconstruct + [starting_point] into [(l, n)] where [l] is a level and [n] is a + message index. + + In a proof, [inclusion_proof] is an inclusion proof of [history_proof] into + [snapshot] where [history_proof] is the skip list cell for the level [l], + and [message_proof] is a tree proof showing that + + [exists witness . + (hash witness = history_proof.content.hash) + AND (get_messages_payload n witness = (_, message))] + + Note: in the case that [message] is [None] this shows that there's no + value at the index [n]; in this case we also must check that + [history_proof] equals [snapshot]. *) +type proof = {inclusion_proof : inclusion_proof; message_proof : payloads_proof} + +let pp_proof fmt {inclusion_proof; message_proof} = + Format.fprintf + fmt + "@[@[inclusion proof:@,%a@]@,@[payloads proof:@,%a@]@]" + pp_inclusion_proof + inclusion_proof + pp_payloads_proof + message_proof + +let proof_encoding = + let open Data_encoding in + conv + (fun {inclusion_proof; message_proof} -> (inclusion_proof, message_proof)) + (fun (inclusion_proof, message_proof) -> {inclusion_proof; message_proof}) + (obj2 + (req "inclusion_proof" inclusion_proof_encoding) + (req "message_proof" payloads_proof_encoding)) + +let of_serialized_proof = Data_encoding.Binary.of_string_opt proof_encoding + +let to_serialized_proof = Data_encoding.Binary.to_string_exn proof_encoding + +(** [verify_payloads_proof {proof; payload} head_cell_hash n label] handles + all the verification needed for a particular message proof at a particular + level. + + First it checks that [proof] is a valid inclusion of [payload_cell] in + [head_cell] and that [head_cell] hash is [head_cell_hash]. + + Then there is two cases, + + - either [n] is superior to the index of [head_cell] then the provided + [payload] must be empty (and [payload_cell = head_cell]); + + - or [0 < n < max_index head_cell] then the provided payload must exist and + the payload hash must equal the content of the [payload_cell]. +*) +let verify_payloads_proof {proof; payload} head_cell_hash n = + let open Result_syntax in + let* payload_cell, head_cell = + Sc_rollup_inbox_merkelized_payload_hashes_repr.verify_proof proof + in + (* Checks that [proof] is a valid inclusion of [payload_cell] in + [head_cell] and that [head_cell] hash is [head_cell_hash]. *) + let* () = + error_unless + (Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.equal + head_cell_hash + (Sc_rollup_inbox_merkelized_payload_hashes_repr.hash head_cell)) + (Inbox_proof_error (Format.sprintf "message_proof does not match history")) + in + let max_index = + Sc_rollup_inbox_merkelized_payload_hashes_repr.get_index head_cell + in + if Compare.Z.(n = Z.succ max_index) then + (* [n] is equal to the index of [head_cell] then the provided [payload] must + be init (,and [payload_cell = head_cell]) *) + let* () = + error_unless + (Option.is_none payload) + (Inbox_proof_error "Payload provided but none expected") + in + let* () = + error_unless + (Sc_rollup_inbox_merkelized_payload_hashes_repr.equal + payload_cell + head_cell) + (Inbox_proof_error "Provided proof is about a unexpected payload") + in + return_none + else if Compare.Z.(n <= max_index) then + (* [0 < n < max_index head_cell] then the provided [payload] must exists and + [payload_hash] must equal the content of the [payload_cell]. *) + let* payload = + match payload with + | Some payload -> return payload + | None -> + tzfail + (Inbox_proof_error + "Expected a payload but none provided in the proof") + in + let payload_hash = + Sc_rollup_inbox_message_repr.hash_serialized_message payload + in + let proven_payload_hash = + Sc_rollup_inbox_merkelized_payload_hashes_repr.get_payload_hash + payload_cell + in + let* () = + error_unless + (Sc_rollup_inbox_message_repr.Hash.equal + payload_hash + proven_payload_hash) + (Inbox_proof_error + "the payload provided does not match the payload's hash found in \ + the message proof") + in + let payload_index = + Sc_rollup_inbox_merkelized_payload_hashes_repr.get_index payload_cell + in + let* () = + error_unless + (Compare.Z.equal n payload_index) + (Inbox_proof_error + (Format.sprintf "found index in message_proof is incorrect")) + in + return_some payload + else + tzfail + (Inbox_proof_error + "Provided message counter is out of the valid range [0 -- (max_index \ + + 1)]") + +(** [produce_payloads_proof get_payloads_history head_cell_hash ~index] + + [get_payloads_history cell_hash] is a function that returns an + {!Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t}. The returned + history must contains the cell with hash [cell_hash], all its ancestor cell + and their associated payload. + + [head_cell] the latest cell of the [witness] we want to produce a proof on + with hash [head_cell_hash]. + + This function produce either: + + - if [index <= head_cell_max_index], a proof that [payload_cell] with + [index] is an ancestor to [head_cell] where [head_cell] is the cell with + hash [head_cell_hash]. It returns the proof and the payload associated to + [payload_cell]; + + - else a proof that [index] is out of bound for [head_cell]. It returns the + proof and no payload. +*) +let produce_payloads_proof get_payloads_history head_cell_hash ~index = + let open Lwt_result_syntax in + (* We first retrieve the history of cells for this level. *) + let*! payloads_history = get_payloads_history head_cell_hash in + (* We then fetch the actual head cell in the history. *) + let*? head_cell = + match + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.find + head_cell_hash + payloads_history + with + | Some {merkelized = head_cell; payload = _} -> Ok head_cell + | None -> + Result_syntax.tzfail + (Inbox_proof_error "could not find head_cell in the payloads_history") + in + let head_cell_max_index = + Sc_rollup_inbox_merkelized_payload_hashes_repr.get_index head_cell + in + (* if [index <= head_cell_max_index] then the index belongs to this level, we + prove its existence. Else the index is out of bounds, we prove its + non-existence. *) + let target_index = Compare.Z.(min index head_cell_max_index) in + (* We look for the cell at `target_index` starting from `head_cell`. If it + exists, we return the payload held in this cell. Otherwise, we prove that + [index] does not exist in this level. *) + let proof = + Sc_rollup_inbox_merkelized_payload_hashes_repr.produce_proof + payloads_history + head_cell + ~index:target_index + in + match proof with + | Some ({payload; merkelized = _}, proof) -> + if Compare.Z.(target_index = index) then + return {proof; payload = Some payload} + else return {proof; payload = None} + | None -> tzfail (Inbox_proof_error "could not produce a valid proof.") + +let verify_inclusion_proof inclusion_proof snapshot_history_proof = + let open Result_syntax in + let rec aux (hash_map, ptr_list) = function + | [] -> tzfail (Inbox_proof_error "inclusion proof is empty") + | [target] -> + let target_ptr = hash_history_proof target in + let hash_map = Hash.Map.add target_ptr target hash_map in + let ptr_list = target_ptr :: ptr_list in + return (hash_map, List.rev ptr_list, target, target_ptr) + | history_proof :: tail -> + let ptr = hash_history_proof history_proof in + aux (Hash.Map.add ptr history_proof hash_map, ptr :: ptr_list) tail + in + let* hash_map, ptr_list, target, target_ptr = + aux (Hash.Map.empty, []) inclusion_proof + in + let deref ptr = Hash.Map.find ptr hash_map in + let cell_ptr = hash_history_proof snapshot_history_proof in + let* () = + error_unless + (Skip_list.valid_back_path + ~equal_ptr:Hash.equal + ~deref + ~cell_ptr + ~target_ptr + ptr_list) + (Inbox_proof_error "invalid inclusion proof") + in + return target + +let produce_inclusion_proof deref inbox_snapshot l = + let open Lwt_result_syntax in + let compare {hash = _; level} = Raw_level_repr.compare level l in + let*! result = Skip_list.Lwt.search ~deref ~compare ~cell:inbox_snapshot in + match result with + | Skip_list.{rev_path; last_cell = Found history_proof} -> + return (List.rev rev_path, history_proof) + | {last_cell = Nearest _; _} + | {last_cell = No_exact_or_lower_ptr; _} + | {last_cell = Deref_returned_none; _} -> + (* We are only interested in the result where [search] returns a path to + the cell we were looking for. All the other cases should be + considered as an error. *) + tzfail + @@ Inbox_proof_error + (Format.asprintf + "Skip_list.search failed to find a valid path: %a" + (Skip_list.pp_search_result ~pp_cell:pp_history_proof) + result) + +let verify_proof (l, n) inbox_snapshot {inclusion_proof; message_proof} = + let open Result_syntax in + assert (Z.(geq n zero)) ; + let* history_proof = verify_inclusion_proof inclusion_proof inbox_snapshot in + let level_proof = Skip_list.content history_proof in + let* payload_opt = verify_payloads_proof message_proof level_proof.hash n in + match payload_opt with + | Some payload -> + return_some + Sc_rollup_PVM_sig.{inbox_level = l; message_counter = n; payload} + | None -> + if equal_history_proof inbox_snapshot history_proof then return_none + else + let* payload = + Sc_rollup_inbox_message_repr.(serialize (Internal Start_of_level)) + in + let inbox_level = Raw_level_repr.succ l in + let message_counter = Z.zero in + return_some Sc_rollup_PVM_sig.{inbox_level; message_counter; payload} + +let produce_proof ~get_payloads_history ~get_history inbox_snapshot (l, n) = + let open Lwt_result_syntax in + let* inclusion_proof, history_proof = + produce_inclusion_proof get_history inbox_snapshot l + in + let level_proof = Skip_list.content history_proof in + let* ({payload; proof = _} as message_proof) = + produce_payloads_proof get_payloads_history level_proof.hash ~index:n + in + let proof = {inclusion_proof; message_proof} in + let*? input = + let open Result_syntax in + match payload with + | Some payload -> + return_some + Sc_rollup_PVM_sig.{inbox_level = l; message_counter = n; payload} + | None -> + (* No payload means that there is no more message to read at the level of + [history_proof]. *) + if equal_history_proof inbox_snapshot history_proof then + (* if [history_proof] is equal to the snapshot then it means that there + is no more message to read. *) + return_none + else + (* Else we must read the [sol] of the next level. *) + let inbox_level = Raw_level_repr.succ l in + let message_counter = Z.zero in + let* payload = + Sc_rollup_inbox_message_repr.(serialize (Internal Start_of_level)) + in + return_some Sc_rollup_PVM_sig.{inbox_level; message_counter; payload} + in + return (proof, input) + +let init_witness payloads_history = + let open Result_syntax in + let sol = Sc_rollup_inbox_message_repr.start_of_level_serialized in + let* payloads_history, witness = + Sc_rollup_inbox_merkelized_payload_hashes_repr.genesis payloads_history sol + in + return (payloads_history, witness) + +let init_witness_no_history = + let sol = Sc_rollup_inbox_message_repr.start_of_level_serialized in + Sc_rollup_inbox_merkelized_payload_hashes_repr.genesis_no_history sol + +let add_info_per_level ~predecessor_timestamp ~predecessor payloads_history + witness = + let info_per_level = + Sc_rollup_inbox_message_repr.info_per_level_serialized + ~predecessor_timestamp + ~predecessor + in + add_protocol_internal_message info_per_level payloads_history witness + +let add_info_per_level_no_history ~predecessor_timestamp ~predecessor witness = + let info_per_level = + Sc_rollup_inbox_message_repr.info_per_level_serialized + ~predecessor_timestamp + ~predecessor + in + add_protocol_internal_message_no_history info_per_level witness + +let finalize_inbox_level payloads_history history inbox witness = + let open Result_syntax in + let inbox = {inbox with level = Raw_level_repr.succ inbox.level} in + let eol = Sc_rollup_inbox_message_repr.end_of_level_serialized in + let* payloads_history, witness = + add_protocol_internal_message eol payloads_history witness + in + let* history, inbox = archive history inbox witness in + return (payloads_history, history, witness, inbox) + +let finalize_inbox_level_no_history inbox witness = + let inbox = {inbox with level = Raw_level_repr.succ inbox.level} in + let eol = Sc_rollup_inbox_message_repr.end_of_level_serialized in + let witness = add_protocol_internal_message_no_history eol witness in + archive_no_history inbox witness + +let add_all_messages ~protocol_migration_message ~predecessor_timestamp + ~predecessor history inbox messages = + let open Result_syntax in + let* payloads = List.map_e Sc_rollup_inbox_message_repr.serialize messages in + let is_first_block = Option.is_some protocol_migration_message in + let payloads_history = + (* Must remember every [payloads] and internal messages pushed by the + protocol: SOL/Info_per_level/EOL. *) + let capacity = + (List.length payloads + 3 + if is_first_block then 1 else 0) + |> Int64.of_int + in + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.empty ~capacity + in + (* Add [SOL], [Info_per_level], and possibly [Protocol_migration]. *) + let* payloads_history, witness = init_witness payloads_history in + + let* payloads_history, witness = + add_info_per_level + ~predecessor_timestamp + ~predecessor + payloads_history + witness + in + + let* payloads_history, witness = + match protocol_migration_message with + | Some protocol_migration_message -> + let* message = + Sc_rollup_inbox_message_repr.serialize + (Internal protocol_migration_message) + in + add_message message payloads_history witness + | None -> return (payloads_history, witness) + in + + let* payloads_history, witness = + match payloads with + | [] -> return (payloads_history, witness) + | payloads -> add_messages payloads_history payloads witness + in + let* payloads_history, history, witness, inbox = + finalize_inbox_level payloads_history history inbox witness + in + + (* Wrap the messages so the caller can execute every actual messages + for this inbox. *) + let messages = + let open Sc_rollup_inbox_message_repr in + let sol = Internal Start_of_level in + let info_per_level = + Internal (Info_per_level {predecessor_timestamp; predecessor}) + in + let migration = + Option.fold + ~none:[] + ~some:(fun x -> [Internal x]) + protocol_migration_message + in + let eol = Internal End_of_level in + [sol] @ [info_per_level] @ migration @ messages @ [eol] + in + + return (payloads_history, history, inbox, witness, messages) + +let genesis ~protocol_migration_message ~predecessor_timestamp ~predecessor + level = + (* 1. Add [SOL], [Info_per_level] and [Protocol_migration]. *) + let witness = init_witness_no_history in + let witness = + add_info_per_level_no_history ~predecessor_timestamp ~predecessor witness + in + let witness = + add_protocol_internal_message_no_history protocol_migration_message witness + in + + (* 2. Add [EOL]. *) + let eol = Sc_rollup_inbox_message_repr.end_of_level_serialized in + let witness = add_protocol_internal_message_no_history eol witness in + + let level_proof = + let hash = Sc_rollup_inbox_merkelized_payload_hashes_repr.hash witness in + {hash; level} + in + + {level; old_levels_messages = Skip_list.genesis level_proof} + +module Internal_for_tests = struct + type nonrec inclusion_proof = inclusion_proof + + let pp_inclusion_proof = pp_inclusion_proof + + let produce_inclusion_proof = produce_inclusion_proof + + let verify_inclusion_proof = verify_inclusion_proof + + let serialized_proof_of_string x = x + + let get_level_of_history_proof (history_proof : history_proof) = + let ({level; _} : level_proof) = Skip_list.content history_proof in + level + + type nonrec payloads_proof = payloads_proof = { + proof : Sc_rollup_inbox_merkelized_payload_hashes_repr.proof; + payload : Sc_rollup_inbox_message_repr.serialized option; + } + + let pp_payloads_proof = pp_payloads_proof + + let produce_payloads_proof = produce_payloads_proof + + let verify_payloads_proof = verify_payloads_proof + + type nonrec level_proof = level_proof = { + hash : Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t; + level : Raw_level_repr.t; + } + + let level_proof_of_history_proof = Skip_list.content + + let expose_proof {inclusion_proof; message_proof} = + (inclusion_proof, message_proof) + + let make_proof inclusion_proof message_proof = + {inclusion_proof; message_proof} +end + +type inbox = t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.mli new file mode 100644 index 000000000000..e728ce8ff858 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_repr.mli @@ -0,0 +1,421 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Inbox_proof_error of string + +type error += Inbox_level_reached_messages_limit + +(** Merkelizing inbox for smart-contract rollups. + + {1 Overview} + + The inbox of a smart-contract rollup denotes the incoming messages + of the rollup. This inbox is the source of truth about what + operations are being published and have an effect on the rollup + state. As such, the inbox completely determines the state of the + rollup. Hence, if two claims disagree about the state of the + rollup, there are only two possibilities: either these two claims + correspond to two distinct interpretations of the same inbox ; or, + these two claims differ on their views about the contents of the + inbox itself. {!Sc_rollup_PVM_sig} is meant to arbitrate the first + kind of conflicts while {!Sc_rollup_inbox_repr} focuses on the second + kind of conflicts. + + {1 Inbox messages} + + A message is a chunk of bytes. Messages are indexed using natural + numbers and the level they are introduced. + + A message is said to be *consumed* when its processing has been + cemented, that is, when no refutation about its insertion can + happen anymore because the commitment that describes the effect of + this message on the state is cemented. A message is said to be + *available* (for dispute) if it is not consumed. + + A message processed by the rollup can be consumed or available. A + message unprocessed by the rollup is always available. + + The number of messages in an inbox level is bounded by + {!Constants_repr.sc_rollup_max_number_of_messages_per_level} + When a level inbox reaches the maximum number of messages in the inbox level, + the inbox is said to be full and cannot accept more messages at this level. + This limitation is meant to ensure that Merkle proofs about the inbox + contents have a bounded size. (See next section.) + + {1 Merkelization of the inbox} + + As for the state of the {!Sc_rollup_PVM_sig}, the layer 1 does not + have to store the entire inbox but only a compressed form + (typically a low number of hashes) that witnesses its contents, so + that the protocol can check the validity of a proof about its contents. + This saves space in the context of the layer 1 and is sufficient for the + layer 1 to provide a source of truth about the contents of the + inbox at the current level. + + {1 A level-indexed chain of inboxes} + + By design, inboxes are logically indexed by Tezos levels. This is + required to have a simple way to decide if two commitments are in + conflict. (See {!Sc_rollup_storage}.) + + A commitment included in the block at level L describes the effect + of the messages of the inboxes with a level between a starting + level L_0 and a stopping level L_1, both strictly inferior to + L. The level L_0 must be the inbox level of its parent + commitment. + + To be valid, a commitment needs to prove that it is reading + messages from an inbox which is consistent with the inbox at level + L stored in the layer 1 context. So, it should be possible at any + time to build a proof that a given inbox is a previous version at + level L_1 of the inbox found at level L: these are called inclusion + proofs. + + {1 Clients} + + This module is meant to be used both by the protocol and by the + rollup node in order to maintain consistent inboxes on both sides. + These two clients slightly differ on the amount of information they + store about the inbox. + + On the one hand, to reduce the space consumption of rollups on the + chain storage, the protocol only stores metadata about the + inbox. The messages' hash of the current level are kept in memory during + block validation only (See {!Raw_context.Sc_rollup_in_memory_inbox}). + By contrast, the messages of the previous levels are not kept in + the context at all. They can be retrieved from the chain + history though. However, being absent from the context, they are + not accessible to the protocol. + + On the other hand, the rollup node must keep a more precise inbox + to be able to produce Merkle proofs about the content of specific + messages, at least during the refutation period. + + To cope with the discrepancy of requirements in terms of inbox + storage while preserving a consistent Merkelization + between the protocol and the rollup node, this module exposes the + functions used to merkelize the inbox with an history (See + {!History_bounded_repr.t}) as parameters to remember. + +*) + +module Hash : S.HASH with type t = Smart_rollup.Inbox_hash.t + +module Skip_list : Skip_list.S + +module V1 : sig + type level_proof = { + hash : Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t; + level : Raw_level_repr.t; + } + + (** A [history_proof] is a [Skip_list.cell] that stores multiple + hashes. [Skip_list.content history_proof] gives the hash of this cell, + while [Skip_list.back_pointers history_proof] is an array of hashes of + earlier [history_proof]s in the inbox. + + On the one hand, we think of this type as representing the whole + Merkle structure of an inbox at a given level---it is the part of + {!t} above that can actually be used to prove things (it cannot be + forged by a malicious node because it much match the hash stored by + the L1). + + On the other hand, we think of this type as representing a single + proof-step back through the history of the inbox; given a hash that + appears at some point later in the inbox this type proves that that + hash points to this particular combination of a witness and further + back-pointers. + + In terms of size, this type is a small set of hashes; one for the + current witness and `O(log2(ix))` in the back-pointers, where [ix] + is the index of the cell in the skip list. That is, [ix] is the + number of non-empty levels between now and the origination level of + the rollup. + *) + type history_proof = (level_proof, Hash.t) Skip_list.cell + + (** The type of the inbox for a smart-contract rollup as stored + by the protocol in the context. Values that inhabit this type + only act as fingerprint for inboxes and contain: + - [level] : the inbox level ; + - [old_levels_messages] : a witness of the inbox history. + *) + type t = {level : Raw_level_repr.t; old_levels_messages : history_proof} + + val pp : Format.formatter -> t -> unit + + val equal : t -> t -> bool + + val hash : t -> Hash.t + + val encoding : t Data_encoding.t + + (** [inbox_level inbox] returns the maximum level of message insertion in + [inbox] or its initial level. *) + val inbox_level : t -> Raw_level_repr.t + + (** A [History.t] is basically a lookup table of {!history_proof}s. We + need this if we want to produce inbox proofs because it allows us + to dereference the 'pointer' hashes in any of the + [history_proof]s. This [deref] function is passed to + [Skip_list.back_path] or [Skip_list.search] to allow these + functions to construct valid paths back through the skip list. + + A subtlety of this [history] type is that it is customizable + depending on how much of the inbox history you actually want to + remember, using the [capacity] parameter. In the L1 we use this with + [capacity] set to zero, which makes it immediately forget an old + level as soon as we move to the next. By contrast, the rollup node + uses a history that is sufficiently large to be able to take part + in all potential refutation games occurring during the challenge + period. *) + module History : + Bounded_history_repr.S with type key = Hash.t and type value = history_proof + + val pp_history_proof : Format.formatter -> history_proof -> unit + + val history_proof_encoding : history_proof Data_encoding.t + + val equal_history_proof : history_proof -> history_proof -> bool + + (** [old_levels_messages inbox] returns the latest skip list cell of the inbox + history that is not up to change (i.e. not the current witness). *) + val old_levels_messages : t -> history_proof + + (** [current_witness inbox] returns the current witness of the inbox, i.e. the + merkelized payload hash. *) + val current_witness : + t -> Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t +end + +(** Versioning, see {!Sc_rollup_data_version_sig.S} for more information. *) +include Sc_rollup_data_version_sig.S with type t = V1.t + +include + module type of V1 + with type level_proof = V1.level_proof + and type history_proof = V1.history_proof + and type t = V1.t + +type serialized_proof + +val serialized_proof_encoding : serialized_proof Data_encoding.t + +(** [add_all_messages history inbox messages] starts a new inbox level, + adds all the [messages], then ends the inbox level. It can + be called even if [payloads] is empty. + + Remembers everything needed in a created [payloads_history] and [history]. + It is meant to be used by the rollup-node to reduce the risk of + de-synchronisation between the protocol and the node. + + Adds the messages pushed by the protocol and returns a list of messages + including them. The caller will need to execute this list of messages, + otherwise, it might miss some internal inputs. + + The expected value of [protocol_migration_message] is either [Some + Raw_context.protocol_migration_internal_message] (during the first + block of this protocol) or [None]. *) +val add_all_messages : + protocol_migration_message: + Sc_rollup_inbox_message_repr.internal_inbox_message option -> + predecessor_timestamp:Time.t -> + predecessor:Block_hash.t -> + History.t -> + t -> + Sc_rollup_inbox_message_repr.t list -> + (Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t + * History.t + * t + * Sc_rollup_inbox_merkelized_payload_hashes_repr.t + * Sc_rollup_inbox_message_repr.t list) + tzresult + +(** [add_messages_no_history payloads witness] updates the [witness] by + inserting the [payloads]. *) +val add_messages_no_history : + Sc_rollup_inbox_message_repr.serialized list -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.t tzresult + +(** Used at the beginning of a refutation game to create the + snapshot against which proofs in that game must be valid. + + One important note: + It takes the snapshot of the inbox for the current level. The snapshot + points to the inbox at the *beginning* of the current block level. This + prevents to create a mid-level snapshot for a refutation game if new + messages are added before and/or after in the same block. *) +val take_snapshot : t -> history_proof + +(** An inbox proof has three parameters: + + - the [starting_point], of type [Raw_level_repr.t * Z.t], specifying + a location in the inbox ; + + - the [message], of type [Sc_rollup_PVM_sig.input option] ; + + - and a reference [snapshot] inbox. + + A valid inbox proof implies the following semantics: beginning at + [starting_point] and reading forward through [snapshot], the first + message you reach will be [message]. + + Usually this is fairly simple because there will actually be a + message at the location specified by [starting_point]. But in some + cases [starting_point] is past the last message within a level, + and then the inbox proof's verification assumes that the next input + is the SOL of the next level, if not beyond the snapshot. +*) +type proof + +val pp_proof : Format.formatter -> proof -> unit + +val to_serialized_proof : proof -> serialized_proof + +val of_serialized_proof : serialized_proof -> proof option + +(** See the docstring for the [proof] type for details of proof semantics. + + [verify_proof starting_point inbox_snapshot proof] will return the third + parameter of the proof, [message], iff the proof is valid. *) +val verify_proof : + Raw_level_repr.t * Z.t -> + history_proof -> + proof -> + Sc_rollup_PVM_sig.inbox_message option tzresult + +(** [produce_proof ~get_payloads_history ~get_history inbox (level, counter)] + creates an inbox proof proving the first message after the index [counter] + at location [level]. This will fail if the [get_payloads_history] given + doesn't have sufficient data (it needs to be run on an with a full + history). *) +val produce_proof : + get_payloads_history: + (Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t Lwt.t) -> + get_history:(Hash.t -> history_proof option Lwt.t) -> + history_proof -> + Raw_level_repr.t * Z.t -> + (proof * Sc_rollup_PVM_sig.inbox_message option) tzresult Lwt.t + +(** [init_witness_no_history] initializes the witness for a new inbox level + by adding the first input, i.e. [Start_of_level]. *) +val init_witness_no_history : Sc_rollup_inbox_merkelized_payload_hashes_repr.t + +(** [add_info_per_level_no_history] adds the input [Info_per_level]. *) +val add_info_per_level_no_history : + predecessor_timestamp:Time.t -> + predecessor:Block_hash.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.t + +(** [finalize_inbox_level payloads_history history inbox level_witness] updates + the current inbox's level witness by adding [EOL], and archives the current + level. *) +val finalize_inbox_level_no_history : + t -> Sc_rollup_inbox_merkelized_payload_hashes_repr.t -> t + +(** [genesis ~protocol_migration_message ~timestamp ~predecessor + level] initializes the inbox at some given [level] with: [SOL], + [protocol_migration_message], [Info_per_level {timestamp; + predecessor}] and [EOL] inside. + + The expected value of [protocol_migration_message] is + [Raw_context.protocol_migration_internal_message]. *) +val genesis : + protocol_migration_message:Sc_rollup_inbox_message_repr.serialized -> + predecessor_timestamp:Time.t -> + predecessor:Block_hash.t -> + Raw_level_repr.t -> + t + +module Internal_for_tests : sig + (** Given a inbox [A] at some level [L] and another inbox [B] at some level + [L' >= L], an [inclusion_proof] guarantees that [A] is an older version of + [B]. + + To be more precise, an [inclusion_proof] guarantees that the previous + levels [witness]s of [A] are included in the previous levels [witness]s of + [B]. The current [witness] of [A] and [B] are not considered. + + The size of this proof is O(log2 (L' - L)). *) + type inclusion_proof = history_proof list + + val pp_inclusion_proof : Format.formatter -> inclusion_proof -> unit + + (** [produce_inclusion_proof get_history a b] exploits [get_history] + to produce a self-contained proof that [a] is an older version of [b]. *) + val produce_inclusion_proof : + (Hash.t -> history_proof option Lwt.t) -> + history_proof -> + Raw_level_repr.t -> + (inclusion_proof * history_proof) tzresult Lwt.t + + (** [verify_inclusion_proof proof snapshot] returns [A] iff [proof] is a minimal + and valid proof that [A] is included in [snapshot], fails otherwise. [A] is + part of the proof. *) + val verify_inclusion_proof : + inclusion_proof -> history_proof -> history_proof tzresult + + type payloads_proof = { + proof : Sc_rollup_inbox_merkelized_payload_hashes_repr.proof; + payload : Sc_rollup_inbox_message_repr.serialized option; + } + + val pp_payloads_proof : Format.formatter -> payloads_proof -> unit + + val produce_payloads_proof : + (Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t Lwt.t) -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t -> + index:Z.t -> + payloads_proof tzresult Lwt.t + + val verify_payloads_proof : + payloads_proof -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t -> + Z.t -> + Sc_rollup_inbox_message_repr.serialized option tzresult + + (** Allows to create a dumb {!serialized_proof} from a string, instead of + serializing a proof with {!to_serialized_proof}. *) + val serialized_proof_of_string : string -> serialized_proof + + val get_level_of_history_proof : history_proof -> Raw_level_repr.t + + type level_proof = { + hash : Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t; + level : Raw_level_repr.t; + } + + val level_proof_of_history_proof : history_proof -> level_proof + + val expose_proof : proof -> inclusion_proof * payloads_proof + + val make_proof : inclusion_proof -> payloads_proof -> proof +end + +type inbox = t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.ml new file mode 100644 index 000000000000..356f90bc52eb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.ml @@ -0,0 +1,162 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Store = Storage.Sc_rollup + +let get_inbox ctxt = + let open Lwt_result_syntax in + let* inbox = Store.Inbox.get ctxt in + return (inbox, ctxt) + +let add_messages ctxt messages = + let open Lwt_result_syntax in + let open Raw_context in + let current_messages = Sc_rollup_in_memory_inbox.current_messages ctxt in + let*? ctxt = + List.fold_left_e + (fun ctxt (message : Sc_rollup_inbox_message_repr.serialized) -> + let msg_len = String.length (message :> string) in + (* The average cost of adding a message with a + [current_index] from [0] to [1_000_000] is reached after [100_000] + messages. + If we use the real index, the simulations of [Sc_rollup_add_messages] + are always performed on an empty skip list. + *) + let cost = + Sc_rollup_costs.cost_add_message + ~current_index:Z.(of_int 100_000) + ~msg_len + in + Raw_context.consume_gas ctxt cost) + ctxt + messages + in + (* + Notice that the protocol is forgetful: it throws away the inbox + history. On the contrary, the history is stored by the rollup + node to produce inclusion proofs when needed. + *) + let*? current_messages = + Sc_rollup_inbox_repr.add_messages_no_history messages current_messages + in + let ctxt = + Sc_rollup_in_memory_inbox.set_current_messages ctxt current_messages + in + return ctxt + +let serialize_external_messages ctxt external_messages = + let open Result_syntax in + let open Sc_rollup_inbox_message_repr in + List.fold_left_map_e + (fun ctxt message -> + (* Pay gas for serializing an external message. *) + let* ctxt = + let bytes_len = String.length message in + Raw_context.consume_gas + ctxt + (Sc_rollup_costs.cost_serialize_external_inbox_message ~bytes_len) + in + let* serialized_message = serialize @@ External message in + return (ctxt, serialized_message)) + ctxt + external_messages + +let serialize_internal_message ctxt internal_message = + let open Result_syntax in + (* Pay gas for serializing an internal message. *) + let* ctxt = + Raw_context.consume_gas + ctxt + (Sc_rollup_costs.cost_serialize_internal_inbox_message internal_message) + in + let* message = + Sc_rollup_inbox_message_repr.(serialize @@ Internal internal_message) + in + return (message, ctxt) + +let add_external_messages ctxt external_messages = + let open Lwt_result_syntax in + let*? ctxt, messages = serialize_external_messages ctxt external_messages in + add_messages ctxt messages + +let add_internal_message ctxt internal_message = + let open Lwt_result_syntax in + let*? message, ctxt = serialize_internal_message ctxt internal_message in + add_messages ctxt [message] + +let add_deposit ctxt ~payload ~sender ~source ~destination = + let internal_message : Sc_rollup_inbox_message_repr.internal_inbox_message = + Transfer {destination; payload; sender; source} + in + add_internal_message ctxt internal_message + +let finalize_inbox_level ctxt = + let open Lwt_result_syntax in + let* inbox, ctxt = get_inbox ctxt in + let witness = Raw_context.Sc_rollup_in_memory_inbox.current_messages ctxt in + let inbox = + Sc_rollup_inbox_repr.finalize_inbox_level_no_history inbox witness + in + Store.Inbox.update ctxt inbox + +let add_level_info ~predecessor ctxt = + let open Lwt_result_syntax in + let predecessor_timestamp = Raw_context.predecessor_timestamp ctxt in + let witness = Raw_context.Sc_rollup_in_memory_inbox.current_messages ctxt in + let witness = + Sc_rollup_inbox_repr.add_info_per_level_no_history + ~predecessor_timestamp + ~predecessor + witness + in + let current_level = (Raw_context.current_level ctxt).level in + let+ first_level = Storage.Tenderbake.First_level_of_protocol.get ctxt in + let is_first_level_of_protocol = + (* first_level is set at the last block of a protocol, when mig is + run. *) + Int32.equal (Raw_level_repr.diff current_level first_level) 1l + in + let witness = + if is_first_level_of_protocol then + Sc_rollup_inbox_merkelized_payload_hashes_repr.add_payload_no_history + witness + Raw_context.protocol_migration_serialized_message + else witness + in + Raw_context.Sc_rollup_in_memory_inbox.set_current_messages ctxt witness + +let init_inbox ~predecessor ctxt = + let ({level; _} : Level_repr.t) = Raw_context.current_level ctxt in + let predecessor_timestamp = Raw_context.predecessor_timestamp ctxt in + let inbox = + Sc_rollup_inbox_repr.genesis + ~protocol_migration_message: + Raw_context.protocol_migration_serialized_message + ~predecessor_timestamp + ~predecessor + level + in + Store.Inbox.init ctxt inbox diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.mli new file mode 100644 index 000000000000..6f7fed515f16 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_inbox_storage.mli @@ -0,0 +1,63 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [get_inbox context] returns the current state of the inbox, + if it exists. *) +val get_inbox : + Raw_context.t -> (Sc_rollup_inbox_repr.t * Raw_context.t) tzresult Lwt.t + +(** [add_external_messages context messages] adds [messages] to the smart + rollups internal inbox level witness. *) +val add_external_messages : + Raw_context.t -> string list -> Raw_context.t tzresult Lwt.t + +(** [add_deposit ~payload ~sender ~source ~destination ctxt] adds the + internal deposit message of [payload], [sender], and [source] to + the smart-contract rollups' inbox. + + See [add_external_messages] for returned values and failures. +*) +val add_deposit : + Raw_context.t -> + payload:Script_repr.expr -> + sender:Contract_hash.t -> + source:Signature.public_key_hash -> + destination:Sc_rollup_repr.Address.t -> + Raw_context.t tzresult Lwt.t + +(** Initialize the inbox in the storage at protocol initialization. *) +val init_inbox : + predecessor:Block_hash.t -> Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Adds the [Info_per_level] in the in-memory inbox level witness. If + the current level is the first level of the current protocol then + also add [Migration] message. *) +val add_level_info : + predecessor:Block_hash.t -> Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** [finalize_inbox_level ctxt] ends the internal representation for the block. +*) +val finalize_inbox_level : Raw_context.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.ml new file mode 100644 index 000000000000..002b3443d5af --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.ml @@ -0,0 +1,140 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type void = | + +let void = + Data_encoding.( + conv_with_guard + (function (_ : void) -> .) + (fun _ -> Error "void has no inhabitant") + unit) + +type t = Context_binary.t + +type tree = Context_binary.tree + +let empty_tree () = Context_binary.(make_empty_context () |> Tree.empty) + +module Context_no_proofs = struct + module Tree = Context_binary.Tree + + type tree = Context_binary.tree + + type proof = void + + let verify_proof = function (_ : proof) -> . + + let produce_proof _context _state _step = assert false + + let proof_before = function (_ : proof) -> . + + let proof_after = function (_ : proof) -> . + + let proof_encoding = void +end + +module type S = sig + val parse_boot_sector : string -> string option + + val pp_boot_sector : Format.formatter -> string -> unit + + include + Sc_rollup_PVM_sig.S + with type context = Context_no_proofs.Tree.t + and type state = Context_no_proofs.tree + and type proof = void +end + +module Arith : S = Sc_rollup_arith.Make (Context_no_proofs) + +module Wasm : S = + Sc_rollup_wasm.V2_0_0.Make (Wasm_2_0_0.Make) (Context_no_proofs) + +module Riscv : S = struct + let parse_boot_sector _ = None + + let pp_boot_sector _fmtr _bs = () + + type state = tree + + let pp _state = Lwt.return (fun _ _ -> ()) + + type context = t + + type hash = Smart_rollup.State_hash.t + + type proof = void + + let proof_encoding = void + + let elim_void = function (_ : void) -> . + + let proof_start_state = elim_void + + let proof_stop_state = elim_void + + let state_hash _state = + Sc_rollup_riscv.(Protocol_implementation.state_hash (make_empty_state ())) + + let initial_state ~empty = Lwt.return empty + + let install_boot_sector state _bs = Lwt.return state + + let is_input_state ~is_reveal_enabled:_ _state = + failwith "is_input_state: unimplemented" + + let set_input _input _state = failwith "set_input: unimplemented" + + let eval _state = failwith "eval: unimplemented" + + let verify_proof ~is_reveal_enabled:_ _input_opt = elim_void + + let produce_proof _ctxt ~is_reveal_enabled:_ _input_opt _state = + failwith "produce_proof: unimplemented" + + type output_proof = void + + let output_proof_encoding = void + + let output_of_output_proof = elim_void + + let state_of_output_proof = elim_void + + let verify_output_proof = elim_void + + let produce_output_proof _ctxt _state _out = + failwith "produce_output_proof: unimplemented" + + let check_dissection ~default_number_of_sections:_ ~start_chunk:_ + ~stop_chunk:_ _chunks = + failwith "check_dissection: unimplemented" + + let get_current_level _state = failwith "get_current_level: unimplemented" + + module Internal_for_tests = struct + let insert_failure _state = failwith "insert_failure: unimplemented" + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.mli new file mode 100644 index 000000000000..4c82a8e4c397 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_machine_no_proofs.mli @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides instantiation of both the WASM and Arith PVM which can + be used to perform rollup computations, {b but} cannot be used to compute + proofs. *) + +type void = | + +type t = Context_binary.t + +type tree = Context_binary.tree + +val empty_tree : unit -> tree + +module type S = sig + val parse_boot_sector : string -> string option + + val pp_boot_sector : Format.formatter -> string -> unit + + include + Sc_rollup_PVM_sig.S + with type context = t + and type state = tree + and type proof = void +end + +module Arith : S + +module Wasm : S + +module Riscv : S diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.ml new file mode 100644 index 000000000000..8cec2b1c633d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.ml @@ -0,0 +1,221 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += (* Permanent *) Sc_rollup_invalid_destination + +let () = + let open Data_encoding in + let msg = "Invalid destination" in + register_error_kind + `Permanent + ~id:"smart_rollup_management_protocol_invalid_destination" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Sc_rollup_invalid_destination -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_destination) + +type transaction = + | Transaction : { + destination : Contract_hash.t; + entrypoint : Entrypoint.t; + parameters_ty : ('a, _) Script_typed_ir.ty; + parameters : 'a; + unparsed_parameters : Script.expr; + } + -> transaction + +type atomic_transaction_batch = {transactions : transaction list} + +type outbox_message = + | Atomic_transaction_batch of atomic_transaction_batch + | Whitelist_update of Sc_rollup.Whitelist.t option + +let make_internal_transfer ctxt ty ~payload ~sender ~source ~destination = + let open Lwt_result_syntax in + let+ payload, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized + ty + payload + in + ( Sc_rollup.Inbox_message.Internal + (Transfer {payload; sender; source; destination}), + ctxt ) + +let make_transaction ctxt ~parameters_ty ~unparsed_parameters ~destination + ~entrypoint = + let open Lwt_result_syntax in + (* Parse the parameters according to the given type. *) + let+ parameters, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:false + parameters_ty + (Micheline.root unparsed_parameters) + in + ( ctxt, + Transaction + {destination; entrypoint; parameters_ty; parameters; unparsed_parameters} + ) + +let internal_untyped_transaction ctxt + ({unparsed_parameters; destination; entrypoint} : + Sc_rollup.Outbox.Message.transaction) = + let open Lwt_result_syntax in + let* Script_ir_translator.Ex_script (Script {arg_type; entrypoints; _}), ctxt + = + let* ctxt, _cache_key, cached = Script_cache.find ctxt destination in + match cached with + | Some (_script, ex_script) -> return (ex_script, ctxt) + | None -> tzfail Sc_rollup_invalid_destination + in + (* Find the entrypoint type for the given entrypoint. *) + let*? res, ctxt = + Gas_monad.run + ctxt + (Script_ir_translator.find_entrypoint + ~error_details:(Informative ()) + arg_type + entrypoints + entrypoint) + in + let*? (Ex_ty_cstr {ty = parameters_ty; _}) = res in + make_transaction + ctxt + ~parameters_ty + ~unparsed_parameters + ~destination + ~entrypoint + +let internal_typed_transaction ctxt + ({unparsed_parameters; unparsed_ty; destination; entrypoint} : + Sc_rollup.Outbox.Message.typed_transaction) = + let open Lwt_result_syntax in + (* Parse the parameters type according to the type. *) + let*? Ex_ty parameters_ty, ctxt = + Script_ir_translator.parse_any_ty + ctxt + ~legacy:false + (Micheline.root unparsed_ty) + in + make_transaction + ctxt + ~parameters_ty + ~unparsed_parameters + ~destination + ~entrypoint + +let outbox_message_of_outbox_message_repr ctxt transactions = + let open Lwt_result_syntax in + match transactions with + | Sc_rollup.Outbox.Message.Atomic_transaction_batch {transactions} -> + let* ctxt, transactions = + List.fold_left_map_es internal_untyped_transaction ctxt transactions + in + return (Atomic_transaction_batch {transactions}, ctxt) + | Sc_rollup.Outbox.Message.Atomic_transaction_batch_typed {transactions} -> + let* ctxt, transactions = + List.fold_left_map_es internal_typed_transaction ctxt transactions + in + return (Atomic_transaction_batch {transactions}, ctxt) + | Sc_rollup.Outbox.Message.Whitelist_update whitelist_opt -> + return (Whitelist_update whitelist_opt, ctxt) + +module Internal_for_tests = struct + let make_transaction ctxt parameters_ty ~parameters ~destination ~entrypoint = + let open Lwt_result_syntax in + let* unparsed_parameters, ctxt = + Script_ir_translator.unparse_data ctxt Optimized parameters_ty parameters + in + return + ( Transaction + { + destination; + entrypoint; + parameters_ty; + parameters; + unparsed_parameters; + }, + ctxt ) + + let make_atomic_batch transactions = Atomic_transaction_batch {transactions} + + let serialize_outbox_transactions_untyped transactions = + let open Result_syntax in + let of_internal_transaction + (Transaction + { + destination; + entrypoint; + parameters_ty = _; + parameters = _; + unparsed_parameters; + }) = + return + {Sc_rollup.Outbox.Message.unparsed_parameters; destination; entrypoint} + in + let* transactions = List.map_e of_internal_transaction transactions in + let output_message_internal = + Sc_rollup.Outbox.Message.Atomic_transaction_batch {transactions} + in + Sc_rollup.Outbox.Message.serialize output_message_internal + + let serialize_outbox_transactions_typed transactions = + let open Result_syntax in + let of_internal_transaction + (Transaction + { + destination; + entrypoint; + parameters_ty; + parameters = _; + unparsed_parameters; + }) = + let unparsed_ty = + Script_ir_unparser.serialize_ty_for_error parameters_ty + in + return + { + Sc_rollup.Outbox.Message.unparsed_parameters; + unparsed_ty; + destination; + entrypoint; + } + in + let* transactions = List.map_e of_internal_transaction transactions in + let output_message_internal = + Sc_rollup.Outbox.Message.Atomic_transaction_batch_typed {transactions} + in + Sc_rollup.Outbox.Message.serialize output_message_internal + + let deserialize_inbox_message = Sc_rollup.Inbox_message.deserialize +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.mli new file mode 100644 index 000000000000..9b13c2d6db24 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_management_protocol.mli @@ -0,0 +1,121 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides a typed API for the Rollup Management Protocol that + defines the communication protocol for exchanging messages between Layer 1 + and Layer 2 for smart-contract rollups. + + The API exposes functions for constructing inbox messages. These are + messages produced by the Layer 1 protocol and added to a smart-contract + rollups inbox. + + The Layer 2 node is responsible for decoding and interpreting the messages. + + A type {!outbox_message} representing messages from Layer 2 to Layer 1 + is also provided. An {!outbox_message} consists of a set of transactions + to L1 accounts. + *) + +open Alpha_context + +type error += (* Permanent *) Sc_rollup_invalid_destination + +(** A type representing a Layer 2 to Layer 1 transaction. *) +type transaction = private + | Transaction : { + destination : Contract_hash.t; + entrypoint : Entrypoint.t; + parameters_ty : ('a, _) Script_typed_ir.ty; + parameters : 'a; + unparsed_parameters : Script.expr; + } + -> transaction + +(** A type representing a batch of Layer 2 to Layer 1 transactions. *) +type atomic_transaction_batch = private {transactions : transaction list} + +(** A typed representation of {!Sc_rollup.Outbox.Message.t}. *) +type outbox_message = private + | Atomic_transaction_batch of atomic_transaction_batch + | Whitelist_update of Sc_rollup.Whitelist.t option + +(** [make_internal_transfer ctxt ty ~payload ~sender ~source ~destination] + constructs a smart rollup's [inbox message] (an L1 to L2 message) + with the given [payload], [sender], and [source] targeting [destination]. *) +val make_internal_transfer : + context -> + ('a, _) Script_typed_ir.ty -> + payload:'a -> + sender:Contract_hash.t -> + source:public_key_hash -> + destination:Sc_rollup.Address.t -> + (Sc_rollup.Inbox_message.t * context) tzresult Lwt.t + +(** [outbox_message_of_outbox_message_repr ctxt msg] returns a typed version of + of the given outbox message [msg]. + + Fails with an [Sc_rollup_invalid_destination] error in case the parameters + don't match the type of the entrypoint and destination. *) +val outbox_message_of_outbox_message_repr : + context -> + Sc_rollup.Outbox.Message.t -> + (outbox_message * context) tzresult Lwt.t + +(** Function for constructing and encoding {!inbox_message} and + {!outbox_message} values. Since Layer 1 only ever consumes {!outbox_message} + values and produces {!inbox_message} values, these functions are used for + testing only. *) +module Internal_for_tests : sig + (** [make_transaction ctxt ty ~parameters ~destination ~entrypoint] creates a + Layer 1 to Layer 2 transaction. *) + val make_transaction : + context -> + ('a, _) Script_typed_ir.ty -> + parameters:'a -> + destination:Contract_hash.t -> + entrypoint:Entrypoint.t -> + (transaction * context) tzresult Lwt.t + + (** [make_atomic_batch ts] creates an atomic batch with the given + transactions [ts]. *) + val make_atomic_batch : transaction list -> outbox_message + + (** [serialize_output_transactions_untyped t] encodes the outbox transaction + batch [t] in binary format using the untyped outbox message + representation. *) + val serialize_outbox_transactions_untyped : + transaction list -> Sc_rollup.Outbox.Message.serialized tzresult + + (** [serialize_output_transactions_typed t] encodes the outbox + transaction batch [t] in binary format using the typed outbox message + representation. *) + val serialize_outbox_transactions_typed : + transaction list -> Sc_rollup.Outbox.Message.serialized tzresult + + (** [deserialize_inbox_message bs] decodes an inbox message from the given data + [bs]. *) + val deserialize_inbox_message : + Sc_rollup.Inbox_message.serialized -> Sc_rollup.Inbox_message.t tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.ml new file mode 100644 index 000000000000..5aea557a5959 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/3898 + We also need dynamic metadatas. *) + +type t = { + address : Sc_rollup_repr.Address.t; + origination_level : Raw_level_repr.t; +} + +let pp ppf {address; origination_level} = + Format.fprintf + ppf + "address: %a ; origination_level: %a" + Sc_rollup_repr.Address.pp + address + Raw_level_repr.pp + origination_level + +let equal {address; origination_level} metadata2 = + Sc_rollup_repr.Address.equal address metadata2.address + && Raw_level_repr.equal origination_level metadata2.origination_level + +let encoding = + let open Data_encoding in + conv + (fun {address; origination_level} -> (address, origination_level)) + (fun (address, origination_level) -> {address; origination_level}) + (obj2 + (req "address" Sc_rollup_repr.Address.encoding) + (req "origination_level" Raw_level_repr.encoding)) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.mli new file mode 100644 index 000000000000..c9b9ef648178 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_metadata_repr.mli @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Static rollup-related metadata for the PVMs. *) + +(** A metadata contains: *) +type t = { + address : Sc_rollup_repr.Address.t; (** The rollup address. *) + origination_level : Raw_level_repr.t; + (** The origination level of the rollup. *) +} + +(** Pretty-printer for metadatas *) +val pp : Format.formatter -> t -> unit + +(** Metadatas equality *) +val equal : t -> t -> bool + +(** Encoding for metadatas *) +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.ml new file mode 100644 index 000000000000..e442d705b0a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.ml @@ -0,0 +1,702 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type ('a, 'b) error_container = {given : 'a; last_update : 'b} + +type outdated_whitelist_update = + | Outdated_message_index of + (Z.t, Sc_rollup.Whitelist.last_whitelist_update) error_container + | Outdated_outbox_level of + (Raw_level.t, Sc_rollup.Whitelist.last_whitelist_update) error_container + +let outdated_whitelist_update_encoding = + Data_encoding.( + union + [ + case + ~title:"outdated_message_index" + (Tag 0) + (obj2 + (req "message_index" n) + (req + "last_whitelist_update" + Sc_rollup.Whitelist.last_whitelist_update_encoding)) + (function + | Outdated_message_index {given; last_update} -> + Some (given, last_update) + | _ -> None) + (fun (given, last_update) -> + Outdated_message_index {given; last_update}); + case + ~title:"outdated_outbox_level" + (Tag 1) + (obj2 + (req "outbox_level" Raw_level.encoding) + (req + "last_whitelist_update" + Sc_rollup.Whitelist.last_whitelist_update_encoding)) + (function + | Outdated_outbox_level {given; last_update} -> + Some (given, last_update) + | _ -> None) + (fun (given, last_update) -> + Outdated_outbox_level {given; last_update}); + ]) + +type error += + | (* Permanent *) Sc_rollup_invalid_parameters_type + | (* Permanent *) Sc_rollup_invalid_last_cemented_commitment + | (* Permanent *) Sc_rollup_invalid_output_proof + | (* Permanent *) Sc_rollup_invalid_outbox_level + | (* Permanent *) + Sc_rollup_outdated_whitelist_update of + outdated_whitelist_update + +type execute_outbox_message_result = { + paid_storage_size_diff : Z.t; + ticket_receipt : Ticket_receipt.t; + operations : Script_typed_ir.packed_internal_operation list; + whitelist_update : Sc_rollup.Whitelist.update option; +} + +let () = + let description = "Invalid parameters type for smart rollup" in + register_error_kind + `Permanent + ~id:"smart_rollup_invalid_parameters_type" + ~title:"Invalid parameters type" + ~description + ~pp:(fun fmt () -> Format.fprintf fmt "%s" description) + Data_encoding.unit + (function Sc_rollup_invalid_parameters_type -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_parameters_type) ; + let description = "Invalid last-cemented-commitment" in + register_error_kind + `Permanent + ~id:"smart_rollup_invalid_last_cemented_commitment" + ~title:description + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function + | Sc_rollup_invalid_last_cemented_commitment -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_last_cemented_commitment) ; + let description = "Invalid output proof" in + register_error_kind + `Permanent + ~id:"smart_rollup_invalid_output_proof" + ~title:description + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_invalid_output_proof -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_output_proof) ; + let description = "Invalid outbox level" in + register_error_kind + `Permanent + ~id:"smart_rollup_invalid_outbox_level" + ~title:description + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Sc_rollup_invalid_outbox_level -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_outbox_level) ; + let description = "Outdated whitelist update" in + register_error_kind + `Permanent + ~id:"smart_rollup_outdated_whitelist_update" + ~title:description + ~description + ~pp: + (fun ppf -> function + | Outdated_message_index {given; last_update} -> + Format.fprintf + ppf + "%s: got message index %a at outbox level %a, while the lastest \ + whitelist update occurred with message index %a." + description + Z.pp_print + given + Z.pp_print + last_update.message_index + Raw_level.pp + last_update.outbox_level + | Outdated_outbox_level {given; last_update} -> + Format.fprintf + ppf + "%s: got outbox level %a, while the current outbox level is %a \ + with message index %a." + description + Raw_level.pp + given + Raw_level.pp + last_update.outbox_level + Z.pp_print + last_update.message_index) + outdated_whitelist_update_encoding + (function Sc_rollup_outdated_whitelist_update e -> Some e | _ -> None) + (fun e -> Sc_rollup_outdated_whitelist_update e) + +type origination_result = { + address : Sc_rollup.Address.t; + size : Z.t; + genesis_commitment_hash : Sc_rollup.Commitment.Hash.t; +} + +type 'ret continuation = unit -> 'ret tzresult + +(* Only a subset of types are supported for rollups. + This function checks whether or not a type can be used for a rollup. *) +let rec validate_ty : + type a ac ret. + (a, ac) Script_typed_ir.ty -> + a Script_typed_ir.entrypoints_node -> + ret continuation -> + ret tzresult = + let open Result_syntax in + fun ty {nested = nested_entrypoints; at_node} k -> + let open Script_typed_ir in + match at_node with + | Some {name = _; original_type_expr = _} -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4023 + We currently don't support entrypoints as the entrypoint information + for L1 to L2 messages is not propagated to the rollup. *) + tzfail Sc_rollup_invalid_parameters_type + | None -> ( + match ty with + (* Valid primitive types. *) + | Unit_t -> (k [@ocaml.tailcall]) () + | Int_t -> (k [@ocaml.tailcall]) () + | Nat_t -> (k [@ocaml.tailcall]) () + | Signature_t -> (k [@ocaml.tailcall]) () + | String_t -> (k [@ocaml.tailcall]) () + | Bytes_t -> (k [@ocaml.tailcall]) () + | Key_hash_t -> (k [@ocaml.tailcall]) () + | Key_t -> (k [@ocaml.tailcall]) () + | Timestamp_t -> (k [@ocaml.tailcall]) () + | Address_t -> (k [@ocaml.tailcall]) () + | Bls12_381_g1_t -> (k [@ocaml.tailcall]) () + | Bls12_381_g2_t -> (k [@ocaml.tailcall]) () + | Bls12_381_fr_t -> (k [@ocaml.tailcall]) () + | Bool_t -> (k [@ocaml.tailcall]) () + | Never_t -> (k [@ocaml.tailcall]) () + | Chain_id_t -> (k [@ocaml.tailcall]) () + (* Valid collection types. *) + | Ticket_t (ty, _) -> + (validate_ty [@ocaml.tailcall]) ty no_entrypoints k + | Set_t (ty, _) -> (validate_ty [@ocaml.tailcall]) ty no_entrypoints k + | Option_t (ty, _, _) -> + (validate_ty [@ocaml.tailcall]) ty no_entrypoints k + | List_t (ty, _) -> (validate_ty [@ocaml.tailcall]) ty no_entrypoints k + | Pair_t (ty1, ty2, _, _) -> + (* Entrypoints may not be nested in pairs, hence the no_entrypoints + value. *) + (validate_two_tys [@ocaml.tailcall]) + ty1 + ty2 + no_entrypoints + no_entrypoints + k + | Or_t (ty1, ty2, _, _) -> + let entrypoints_l, entrypoints_r = + match nested_entrypoints with + | Entrypoints_None -> (no_entrypoints, no_entrypoints) + | Entrypoints_Or {left; right} -> (left, right) + in + (validate_two_tys [@ocaml.tailcall]) + ty1 + ty2 + entrypoints_l + entrypoints_r + k + | Map_t (key_ty, val_ty, _) -> + (* Entrypoints may not be nested in maps, hence the no_entrypoints + value. *) + (validate_two_tys [@ocaml.tailcall]) + key_ty + val_ty + no_entrypoints + no_entrypoints + k + (* Invalid types. *) + | Mutez_t -> tzfail Sc_rollup_invalid_parameters_type + | Big_map_t (_key_ty, _val_ty, _) -> + tzfail Sc_rollup_invalid_parameters_type + | Contract_t _ -> tzfail Sc_rollup_invalid_parameters_type + | Sapling_transaction_t _ -> tzfail Sc_rollup_invalid_parameters_type + | Sapling_transaction_deprecated_t _ -> + tzfail Sc_rollup_invalid_parameters_type + | Sapling_state_t _ -> tzfail Sc_rollup_invalid_parameters_type + | Operation_t -> tzfail Sc_rollup_invalid_parameters_type + | Chest_t -> tzfail Sc_rollup_invalid_parameters_type + | Chest_key_t -> tzfail Sc_rollup_invalid_parameters_type + | Lambda_t (_, _, _) -> tzfail Sc_rollup_invalid_parameters_type) + +and validate_two_tys : + type a ac b bc ret. + (a, ac) Script_typed_ir.ty -> + (b, bc) Script_typed_ir.ty -> + a Script_typed_ir.entrypoints_node -> + b Script_typed_ir.entrypoints_node -> + ret continuation -> + ret tzresult = + fun ty1 ty2 entrypoints1 entrypoints2 k -> + (validate_ty [@ocaml.tailcall]) ty1 entrypoints1 (fun () -> + (validate_ty [@ocaml.tailcall]) ty2 entrypoints2 k) + +let validate_parameters_ty : + type a ac. + context -> + (a, ac) Script_typed_ir.ty -> + a Script_typed_ir.entrypoints_node -> + context tzresult = + let open Result_syntax in + fun ctxt parameters_ty entrypoints -> + let* ctxt = + Gas.consume + ctxt + (Sc_rollup_costs.is_valid_parameters_ty_cost + ~ty_size:Script_typed_ir.(ty_size parameters_ty |> Type_size.to_int)) + in + let+ () = validate_ty parameters_ty entrypoints return in + ctxt + +let validate_untyped_parameters_ty ctxt parameters_ty = + let open Result_syntax in + (* Parse the type and check that the entrypoints are well-formed. Using + [parse_parameter_ty_and_entrypoints] restricts to [passable] types + (everything but operations), which is OK since [validate_ty] constraints + the type further. *) + let* ( Ex_parameter_ty_and_entrypoints + { + arg_type; + entrypoints = + {Script_typed_ir.root = entrypoint; original_type_expr = _}; + }, + ctxt ) = + Script_ir_translator.parse_parameter_ty_and_entrypoints + ctxt + ~legacy:false + (Micheline.root parameters_ty) + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4023 + We currently don't support entrypoints as the entrypoint information + for L1 to L2 messages is not propagated to the rollup. *) + validate_parameters_ty ctxt arg_type entrypoint + +let originate ?whitelist ctxt ~kind ~boot_sector ~parameters_ty = + let open Lwt_result_syntax in + let*? ctxt = + let open Result_syntax in + let* parameters_ty, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + parameters_ty + in + validate_untyped_parameters_ty ctxt parameters_ty + in + let boot_sector_size_in_bytes = String.length boot_sector in + let*? ctxt = + match kind with + | Sc_rollup.Kind.Wasm_2_0_0 | Example_arith | Riscv -> + (* + + We do not really care about the precision of the gas model + when it comes to the [Example_arith] PVM, so we use the + WASM PVM model for both cases. + + As you can convince yourself by code inspection, the cost + of [Sc_rollup.genesis_state_hash_of] is dominated by the + installation of the boot sector. + + *) + Gas.consume ctxt + @@ Sc_rollup_costs.cost_install_boot_sector_in_wasm_pvm + ~boot_sector_size_in_bytes + in + let*! genesis_hash = Sc_rollup.genesis_state_hash_of kind ~boot_sector in + let genesis_commitment = + Sc_rollup.Commitment.genesis_commitment + ~genesis_state_hash:genesis_hash + ~origination_level:(Level.current ctxt).level + in + let+ address, size, genesis_commitment_hash, ctxt = + Sc_rollup.originate ?whitelist ctxt ~kind ~parameters_ty ~genesis_commitment + in + ({address; size; genesis_commitment_hash}, ctxt) + +let to_transaction_operation ctxt rollup + (Sc_rollup_management_protocol.Transaction + {destination; entrypoint; parameters_ty; parameters; unparsed_parameters}) + = + let open Result_syntax in + let* ctxt, nonce = fresh_internal_nonce ctxt in + (* Validate the type of the parameters. Only types that can be transferred + from Layer 1 to Layer 2 are permitted. + + In principle, we could allow different types to be passed to the rollup and + from the rollup. In order to avoid confusion, and given that we don't + have any use case where they differ, we keep these sets identical. + + We don't check whether the type contains any entrypoints at this stage. + It has already been done during origination. + *) + let* ctxt = + validate_parameters_ty ctxt parameters_ty Script_typed_ir.no_entrypoints + in + let operation = + Script_typed_ir.Transaction_to_smart_contract + { + destination; + amount = Tez.zero; + entrypoint; + location = Micheline.dummy_location; + parameters_ty; + parameters; + unparsed_parameters; + } + in + return + ( Script_typed_ir.Internal_operation + {sender = Destination.Sc_rollup rollup; operation; nonce}, + ctxt ) + +let transfer_ticket_tokens ctxt ~source_destination ~acc_storage_diff + {Ticket_operations_diff.ticket_token; total_amount = _; destinations} = + let open Lwt_result_syntax in + List.fold_left_es + (fun (acc_storage_diff, ctxt) + (target_destination, (amount : Script_typed_ir.ticket_amount)) -> + let* ctxt, storage_diff = + Ticket_transfer.transfer_ticket + ctxt + ~sender:source_destination + ~dst:target_destination + ticket_token + Ticket_amount.((amount :> t)) + in + return (Z.(add acc_storage_diff storage_diff), ctxt)) + (acc_storage_diff, ctxt) + destinations + +let validate_and_decode_output_proof ctxt ~cemented_commitment rollup + ~output_proof = + let open Lwt_result_syntax in + (* Lookup the PVM of the rollup. *) + let* ctxt, Packed (module PVM) = + let+ ctxt, kind = Sc_rollup.kind ctxt rollup in + (ctxt, Sc_rollup.Kind.pvm_of kind) + in + let output_proof_length = String.length output_proof in + let*? ctxt = + Gas.consume + ctxt + (Sc_rollup_costs.cost_deserialize_output_proof + ~bytes_len:output_proof_length) + in + let*? output_proof = + match + Data_encoding.Binary.of_string_opt PVM.output_proof_encoding output_proof + with + | Some x -> Ok x + | None -> Result_syntax.tzfail Sc_rollup_invalid_output_proof + in + (* Verify that the states match. *) + let* {Sc_rollup.Commitment.compressed_state; _}, ctxt = + Sc_rollup.Commitment.get_commitment ctxt rollup cemented_commitment + in + let* () = + let output_proof_state = PVM.state_of_output_proof output_proof in + fail_unless + Sc_rollup.State_hash.(output_proof_state = compressed_state) + Sc_rollup_invalid_output_proof + in + (* Consume cost of output proof verification. *) + let*? ctxt = + Gas.consume + ctxt + (Sc_rollup_costs.cost_verify_output_proof ~bytes_len:output_proof_length) + in + (* Verify that the proof is valid. *) + let* output = PVM.verify_output_proof output_proof in + return (output, ctxt) + +let validate_outbox_level ctxt ~outbox_level ~lcc_level = + (* Check that outbox level is within the bounds of: + [min_level < outbox_level <= lcc_level] + Where + [min_level = lcc_level - max_active_levels] + + This prevents the rollup from putting messages at a level that is greater + than its corresponding inbox-level. It also prevents execution + of messages that are older than the maximum number of active levels. + *) + let max_active_levels = + Int32.to_int (Constants.sc_rollup_max_active_outbox_levels ctxt) + in + let outbox_level_is_active = + let min_allowed_level = + Int32.sub (Raw_level.to_int32 lcc_level) (Int32.of_int max_active_levels) + in + Compare.Int32.(min_allowed_level < Raw_level.to_int32 outbox_level) + in + fail_unless + (Raw_level.(outbox_level <= lcc_level) && outbox_level_is_active) + Sc_rollup_invalid_outbox_level + +let execute_outbox_message_transaction ctxt ~transactions ~rollup = + let open Lwt_result_syntax in + (* Turn the transaction batch into a list of operations. *) + let*? ctxt, operations = + List.fold_left_map_e + (fun ctxt transaction -> + let open Result_syntax in + let+ op, ctxt = to_transaction_operation ctxt rollup transaction in + (ctxt, op)) + ctxt + transactions + in + (* Extract the ticket-token diffs from the operations. We here make sure that + there are no tickets with amount zero. Zero-amount tickets are not allowed + as they cannot be tracked by the ticket-balance table. + *) + let* ticket_token_diffs, ctxt = + Ticket_operations_diff.ticket_diffs_of_operations ctxt operations + in + (* Update the ticket-balance table by transferring ticket-tokens to new + destinations for each transaction. This fails in case the rollup does not + hold a sufficient amount of any of the ticket-tokens transferred. + + The updates must happen before any of the operations are executed to avoid + a case where ticket-transfers are funded as a result of prior operations + depositing new tickets to the rollup. + *) + let* paid_storage_size_diff, ctxt = + let source_destination = Destination.Sc_rollup rollup in + List.fold_left_es + (fun (acc_storage_diff, ctxt) ticket_token_diff -> + transfer_ticket_tokens + ctxt + ~source_destination + ~acc_storage_diff + ticket_token_diff) + (Z.zero, ctxt) + ticket_token_diffs + in + let* ctxt, ticket_receipt = + List.fold_left_map_es + (fun ctxt + Ticket_operations_diff. + {ticket_token = ex_token; total_amount; destinations = _} -> + let+ ticket_token, ctxt = Ticket_token_unparser.unparse ctxt ex_token in + (* Here we only show the outgoing (negative) balance wrt to the rollup + address. The positive balances for the receiving contracts are + contained in the ticket updates for the internal operations. *) + let item = + Ticket_receipt. + { + ticket_token; + updates = + [ + { + account = Destination.Sc_rollup rollup; + amount = Z.neg (Script_int.to_zint total_amount); + }; + ]; + } + in + (ctxt, item)) + ctxt + ticket_token_diffs + in + return + ( { + paid_storage_size_diff; + ticket_receipt; + operations; + whitelist_update = None; + }, + ctxt ) + +let execute_outbox_message_whitelist_update (ctxt : t) ~rollup ~whitelist + ~outbox_level ~message_index = + let open Lwt_result_syntax in + let* ctxt, is_private = Sc_rollup.Whitelist.is_private ctxt rollup in + if is_private then + match whitelist with + | Some whitelist -> + (* The whitelist update fails with an empty list. *) + let*? () = + error_when + (List.is_empty whitelist) + Sc_rollup_errors.Sc_rollup_empty_whitelist + in + let* ( ctxt, + (Sc_rollup.Whitelist. + { + message_index = latest_message_index; + outbox_level = latest_outbox_level; + } as last_update) ) = + Sc_rollup.Whitelist.get_last_whitelist_update ctxt rollup + in + (* Do not apply whitelist update if a previous whitelist update + occurred with a greater message index for a given outbox level, + or with a greater outbox level. *) + let* () = + fail_when + (Raw_level.(latest_outbox_level = outbox_level) + && Compare.Z.(latest_message_index >= message_index)) + (Sc_rollup_outdated_whitelist_update + (Outdated_message_index {given = message_index; last_update})) + in + let* () = + fail_when + Raw_level.(outbox_level < latest_outbox_level) + (Sc_rollup_outdated_whitelist_update + (Outdated_outbox_level {given = outbox_level; last_update})) + in + let* ctxt, new_storage_size = + Sc_rollup.Whitelist.replace ctxt rollup ~whitelist + in + let* ctxt, size_diff = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6186 + Do not consider storage diffs for small updates to the storage. *) + Sc_rollup.Whitelist.set_last_whitelist_update + ctxt + rollup + {outbox_level; message_index} + in + let* ctxt, paid_storage_size_diff = + Sc_rollup.Whitelist.adjust_storage_space ctxt rollup ~new_storage_size + in + return + ( { + paid_storage_size_diff = Z.add paid_storage_size_diff size_diff; + ticket_receipt = []; + operations = []; + whitelist_update = Some (Private whitelist); + }, + ctxt ) + | None -> + let* ctxt, _freed_size = Sc_rollup.Whitelist.make_public ctxt rollup in + return + ( { + paid_storage_size_diff = Z.zero; + ticket_receipt = []; + operations = []; + whitelist_update = Some Public; + }, + ctxt ) + else tzfail Sc_rollup_errors.Sc_rollup_is_public + +let execute_outbox_message ctxt ~validate_and_decode_output_proof rollup + ~cemented_commitment ~output_proof = + let open Lwt_result_syntax in + (* Get inbox level of last cemented commitment, needed to validate that the + outbox message is active. This call also implicitly checks that the rollup + exists. *) + let* lcc_hash, lcc_level, ctxt = + Sc_rollup.Commitment.last_cemented_commitment_hash_with_level ctxt rollup + in + (* Check that the commitment is a cemented commitment still stored in the + context. We start from the [lcc_hash] of the rollup, which we know to be + stored in context. *) + let* is_cemented_commitment_in_context, ctxt = + Sc_rollup.Commitment.check_if_commitments_are_related + ctxt + rollup + ~descendant:lcc_hash + ~ancestor:cemented_commitment + in + let* () = + fail_unless + is_cemented_commitment_in_context + Sc_rollup_invalid_last_cemented_commitment + in + (* Validate and decode the output proofs. *) + let* Sc_rollup.{outbox_level; message_index; message}, ctxt = + validate_and_decode_output_proof + ctxt + ~cemented_commitment + rollup + ~output_proof + in + (* Validate that the outbox level is within valid bounds. *) + let* () = validate_outbox_level ctxt ~outbox_level ~lcc_level in + let* decoded_outbox_msg, ctxt = + Sc_rollup_management_protocol.outbox_message_of_outbox_message_repr + ctxt + message + in + let* receipt, ctxt = + match decoded_outbox_msg with + | Sc_rollup_management_protocol.Atomic_transaction_batch {transactions} -> + execute_outbox_message_transaction ctxt ~transactions ~rollup + | Sc_rollup_management_protocol.Whitelist_update whitelist -> + let is_enabled = Constants.sc_rollup_private_enable ctxt in + if is_enabled then + execute_outbox_message_whitelist_update + ctxt + ~rollup + ~whitelist + ~outbox_level + ~message_index + else tzfail Sc_rollup_errors.Sc_rollup_whitelist_disabled + in + (* Record that the message for the given level has been applied. This fails + in case a message for the rollup, outbox-level and message index has + already been executed. The storage diff returned may be negative. + *) + let* applied_msg_size_diff, ctxt = + Sc_rollup.Outbox.record_applied_message + ctxt + rollup + outbox_level + ~message_index:(Z.to_int message_index) + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3121 + Implement a more refined model. For instance a water-mark based one. + For now we only charge for positive contributions. It means that over time + we are overcharging for storage space. + *) + let applied_msg_size_diff = Z.max Z.zero applied_msg_size_diff in + return + ( { + receipt with + paid_storage_size_diff = + Z.add receipt.paid_storage_size_diff applied_msg_size_diff; + }, + ctxt ) + +module Internal_for_tests = struct + let execute_outbox_message = execute_outbox_message +end + +let execute_outbox_message ctxt = + execute_outbox_message ctxt ~validate_and_decode_output_proof diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.mli new file mode 100644 index 000000000000..8c9037b16a0f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_operations.mli @@ -0,0 +1,90 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** High-level operations over smart contract rollups. *) +open Alpha_context + +type error += + | (* Permanent *) Sc_rollup_invalid_parameters_type + | (* Permanent *) Sc_rollup_invalid_last_cemented_commitment + | (* Permanent *) Sc_rollup_invalid_output_proof + | (* Permanent *) Sc_rollup_invalid_outbox_level + +(** Result of calling the {!execute_outbox_message} function. *) +type execute_outbox_message_result = { + paid_storage_size_diff : Z.t; + ticket_receipt : Ticket_receipt.t; + operations : Script_typed_ir.packed_internal_operation list; + whitelist_update : Sc_rollup.Whitelist.update option; +} + +type origination_result = { + address : Sc_rollup.Address.t; + size : Z.t; + genesis_commitment_hash : Sc_rollup.Commitment.Hash.t; +} + +(** [originate ?whitelist context ~kind ~boot_sector ~parameters_ty] adds a new rollup + running in a given [kind] initialized with a [boot_sector] and to accept + smart contract calls of type [parameters_ty]. *) +val originate : + ?whitelist:Sc_rollup.Whitelist.t -> + context -> + kind:Sc_rollup.Kind.t -> + boot_sector:string -> + parameters_ty:Script_repr.lazy_expr -> + (origination_result * context) tzresult Lwt.t + +(** [execute_outbox_message ctxt rollup ~cemented_commitment + ~output_proof] validates the given outbox message and prepares a + set of resulting operations. *) +val execute_outbox_message : + context -> + Sc_rollup.t -> + cemented_commitment:Sc_rollup.Commitment.Hash.t -> + output_proof:string -> + (execute_outbox_message_result * context) tzresult Lwt.t + +(** [validate_untyped_parameters_ty ctxt script] parses the type and check + that the entrypoints are well-formed. *) +val validate_untyped_parameters_ty : context -> Script.expr -> context tzresult + +(** A module used for testing purposes only. *) +module Internal_for_tests : sig + (** Same as {!execute_outbox_message} but allows overriding the extraction + and validation of output proofs. *) + val execute_outbox_message : + context -> + validate_and_decode_output_proof: + (context -> + cemented_commitment:Sc_rollup.Commitment.Hash.t -> + Sc_rollup.t -> + output_proof:string -> + (Sc_rollup.output * context) tzresult Lwt.t) -> + Sc_rollup.t -> + cemented_commitment:Sc_rollup.Commitment.Hash.t -> + output_proof:string -> + (execute_outbox_message_result * context) tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.ml new file mode 100644 index 000000000000..b9fbb8c60958 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.ml @@ -0,0 +1,214 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | (* `Permanent *) Error_encode_outbox_message + | (* `Permanent *) Error_decode_outbox_message + +let () = + let open Data_encoding in + let msg = + "Failed to encode a rollup management protocol outbox message value" + in + register_error_kind + `Permanent + ~id:"smart_rollup_outbox_message_repr.error_encoding_outbox_message" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Error_encode_outbox_message -> Some () | _ -> None) + (fun () -> Error_encode_outbox_message) ; + let msg = + "Failed to decode a rollup management protocol outbox message value" + in + register_error_kind + `Permanent + ~id:"smart_rollup_outbox_message_repr.error_decoding_outbox_message" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function Error_decode_outbox_message -> Some () | _ -> None) + (fun () -> Error_decode_outbox_message) + +type transaction = { + unparsed_parameters : Script_repr.expr; (** The payload. *) + destination : Contract_hash.t; (** The recipient contract. *) + entrypoint : Entrypoint_repr.t; (** Entrypoint of the destination. *) +} + +let transaction_encoding = + let open Data_encoding in + conv + (fun {unparsed_parameters; destination; entrypoint} -> + (unparsed_parameters, destination, entrypoint)) + (fun (unparsed_parameters, destination, entrypoint) -> + {unparsed_parameters; destination; entrypoint}) + @@ obj3 + (req "parameters" Script_repr.expr_encoding) + (req "destination" Contract_repr.originated_encoding) + Entrypoint_repr.(dft "entrypoint" simple_encoding default) + +let pp_untyped_transaction fmt {destination; entrypoint; unparsed_parameters} = + let json = + Data_encoding.Json.construct Script_repr.expr_encoding unparsed_parameters + in + Format.fprintf + fmt + "@[<2>destination: %a@, entrypoint: %a@, unparsed_parameters: %a@]" + Contract_hash.pp + destination + Entrypoint_repr.pp + entrypoint + Data_encoding.Json.pp + json + +type typed_transaction = { + unparsed_parameters : Script_repr.expr; + unparsed_ty : Script_repr.expr; + destination : Contract_hash.t; + entrypoint : Entrypoint_repr.t; +} + +let typed_transaction_encoding = + let open Data_encoding in + conv + (fun {unparsed_parameters; unparsed_ty; destination; entrypoint} -> + (unparsed_parameters, unparsed_ty, destination, entrypoint)) + (fun (unparsed_parameters, unparsed_ty, destination, entrypoint) -> + {unparsed_parameters; unparsed_ty; destination; entrypoint}) + @@ obj4 + (req "parameters" Script_repr.expr_encoding) + (req "parameters_ty" Script_repr.expr_encoding) + (req "destination" Contract_repr.originated_encoding) + Entrypoint_repr.(dft "entrypoint" simple_encoding default) + +let pp_typed_transaction fmt + {destination; entrypoint; unparsed_parameters; unparsed_ty} = + let json_param = + Data_encoding.Json.construct Script_repr.expr_encoding unparsed_parameters + in + let json_ty = + Data_encoding.Json.construct Script_repr.expr_encoding unparsed_ty + in + Format.fprintf + fmt + "@[destination: %a@,\ + entrypoint: %a@,\ + unparsed_ty: %a@,\ + unparsed_parameters: %a@]" + Contract_hash.pp + destination + Entrypoint_repr.pp + entrypoint + Data_encoding.Json.pp + json_ty + Data_encoding.Json.pp + json_param + +type t = + | Atomic_transaction_batch of {transactions : transaction list} + | Atomic_transaction_batch_typed of {transactions : typed_transaction list} + | Whitelist_update of Sc_rollup_whitelist_repr.t option + +let encoding = + let open Data_encoding in + (* We use a union encoding in order to guarantee backwards compatibility + when outbox messages are extended with more constructors. + + Each new constructor must be added with an increased tag number. + *) + check_size + Constants_repr.sc_rollup_message_size_limit + (union + [ + case + (Tag 0) + ~title:"Atomic_transaction_batch" + (obj2 + (req "transactions" (list transaction_encoding)) + (req "kind" (constant "untyped"))) + (function + | Atomic_transaction_batch {transactions} -> Some (transactions, ()) + | _ -> None) + (fun (transactions, ()) -> Atomic_transaction_batch {transactions}); + case + (Tag 1) + ~title:"Atomic_transaction_batch_typed" + (obj2 + (req "transactions" (list typed_transaction_encoding)) + (req "kind" (constant "typed"))) + (function + | Atomic_transaction_batch_typed {transactions} -> + Some (transactions, ()) + | _ -> None) + (fun (transactions, ()) -> + Atomic_transaction_batch_typed {transactions}); + case + (Tag 2) + ~title:"Whitelist_update" + (obj2 + (opt "whitelist" Sc_rollup_whitelist_repr.encoding) + (req "kind" (constant "whitelist_update"))) + (function + | Whitelist_update whitelist_opt -> Some (whitelist_opt, ()) + | _ -> None) + (fun (whitelist_opt, ()) -> Whitelist_update whitelist_opt); + ]) + +let pp fmt = function + | Atomic_transaction_batch {transactions} -> + Format.pp_print_list + ~pp_sep:Format.pp_print_space + pp_untyped_transaction + fmt + transactions + | Atomic_transaction_batch_typed {transactions} -> + Format.pp_print_list + ~pp_sep:Format.pp_print_space + pp_typed_transaction + fmt + transactions + | Whitelist_update whitelist_opt -> + Format.pp_print_option Sc_rollup_whitelist_repr.pp fmt whitelist_opt + +type serialized = string + +let deserialize data = + let open Result_syntax in + match Data_encoding.Binary.of_string_opt encoding data with + | Some x -> return x + | None -> tzfail Error_decode_outbox_message + +let serialize outbox_message = + let open Result_syntax in + match Data_encoding.Binary.to_string_opt encoding outbox_message with + | Some str -> return str + | None -> tzfail Error_encode_outbox_message + +let unsafe_of_string s = s + +let unsafe_to_string s = s diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.mli new file mode 100644 index 000000000000..166cec0bfc9a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_message_repr.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines a data type {!t} that represents messages from Layer 2 + to Layer 1. + + They are part of the [Rollup Management Protocol] that defines the + communication protocol for exchanging messages between Layer 1 and Layer 2 + for smart-contract rollups. + + An outbox-message consists of a sequence of transactions to L1 + smart-contract accounts. All transactions contained in a message are + intended to be executed as a batch. + *) + +(** A transaction from L2 to L1. *) +type transaction = { + unparsed_parameters : Script_repr.expr; (** The payload. *) + destination : Contract_hash.t; (** The recipient contract. *) + entrypoint : Entrypoint_repr.t; (** Entrypoint of the destination. *) +} + +(** A transaction from L2 to L1, with typed payload. *) +type typed_transaction = { + unparsed_parameters : Script_repr.expr; (** The payload. *) + unparsed_ty : Script_repr.expr; (** The type of the payload. *) + destination : Contract_hash.t; (** The recipient contract. *) + entrypoint : Entrypoint_repr.t; (** Entrypoint of the destination. *) +} + +(** A type representing messages from Layer 2 to Layer 1. *) +type t = + | Atomic_transaction_batch of {transactions : transaction list} + | Atomic_transaction_batch_typed of {transactions : typed_transaction list} + | Whitelist_update of Sc_rollup_whitelist_repr.t option + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +type serialized = private string + +(** [deserialize ctxt bs] decodes an outbox message value from the + given data [bs]. The function involves parsing Micheline expressions to + typed values. *) +val deserialize : serialized -> t tzresult + +(** [serialize msg] serializes the given outbox message [msg]. *) +val serialize : t -> serialized tzresult + +(** [unsafe_of_string s] builds a serialized value out of a string. + You must understand the invariants of [serialized] to do so. *) +val unsafe_of_string : string -> serialized + +(** [unsafe_to_string s] builds a string out of a serialized value. + You must understand the invariants of [serialized] to manipulate + the resulting string. *) +val unsafe_to_string : serialized -> string diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.ml new file mode 100644 index 000000000000..6952ff828688 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.ml @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let level_index ctxt level = + let max_active_levels = + Constants_storage.sc_rollup_max_active_outbox_levels ctxt + in + Int32.rem (Raw_level_repr.to_int32 level) max_active_levels + +let record_applied_message ctxt rollup level ~message_index = + let open Lwt_result_syntax in + (* Check that the 0 <= message index < maximum number of outbox messages per + level. *) + let*? () = + let max_outbox_messages_per_level = + Constants_storage.sc_rollup_max_outbox_messages_per_level ctxt + in + error_unless + Compare.Int.( + 0 <= message_index && message_index < max_outbox_messages_per_level) + Sc_rollup_errors.Sc_rollup_invalid_outbox_message_index + in + let level_index = level_index ctxt level in + let* ctxt, level_and_bitset_opt = + Storage.Sc_rollup.Applied_outbox_messages.find (ctxt, rollup) level_index + in + let*? bitset, ctxt = + let open Result_syntax in + let* bitset, ctxt = + match level_and_bitset_opt with + | Some (existing_level, bitset) + when Raw_level_repr.(existing_level = level) -> + (* The level at the index is the same as requested. Fail if the + message has been applied already. *) + let* already_applied = Bitset.mem bitset message_index in + let* () = + error_when + already_applied + Sc_rollup_errors.Sc_rollup_outbox_message_already_applied + in + return (bitset, ctxt) + | Some (existing_level, _bitset) + when Raw_level_repr.(level < existing_level) -> + tzfail Sc_rollup_errors.Sc_rollup_outbox_level_expired + | Some _ | None -> + (* The old level is outdated or there is no previous bitset at + this index. *) + return (Bitset.empty, ctxt) + in + let* bitset = Bitset.add bitset message_index in + return (bitset, ctxt) + in + let+ ctxt, size_diff, _is_new = + Storage.Sc_rollup.Applied_outbox_messages.add + (ctxt, rollup) + level_index + (level, bitset) + in + (Z.of_int size_diff, ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.mli new file mode 100644 index 000000000000..1df195368aaa --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_outbox_storage.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A module for managing state concerning a rollup's outbox. *) + +(** [record_applied_message ctxt rollup level ~message_index] marks the message + in the outbox of rollup [rollup] at level [level] and position + [message_index] as processed. Returns the size diff resulting from adding an + entry. The size diff may be 0 if an entry already exists, or negative if an + index is replaced with a new level. + + An attempt to apply an old level that has already been replaced fails with + an [Sc_rollup_outbox_level_expired] error. + + In case a message has already been applied for the given level and message + index, the function fails with an [Sc_rollup_outbox_message_already_applied] + error. *) +val record_applied_message : + Raw_context.t -> + Sc_rollup_repr.t -> + Raw_level_repr.t -> + message_index:int -> + (Z.t * Raw_context.t) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.ml new file mode 100644 index 000000000000..562fa70d00ca --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.ml @@ -0,0 +1,597 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Sc_rollup_proof_check of string + +type error += Sc_rollup_invalid_serialized_inbox_proof + +let () = + register_error_kind + `Permanent + ~id:"smart_rollup_proof_check" + ~title:"Invalid proof" + ~description:"An invalid proof has been submitted" + ~pp:(fun fmt msg -> Format.fprintf fmt "Invalid proof: %s" msg) + Data_encoding.(obj1 @@ req "reason" (string Plain)) + (function Sc_rollup_proof_check msg -> Some msg | _ -> None) + (fun msg -> Sc_rollup_proof_check msg) ; + + register_error_kind + `Permanent + ~id:"smart_rollup_invalid_serialized_inbox_proof" + ~title:"Invalid serialized inbox proof" + ~description:"The serialized inbox proof can not be de-serialized" + ~pp:(fun fmt () -> Format.fprintf fmt "Invalid serialized inbox proof") + Data_encoding.unit + (function Sc_rollup_invalid_serialized_inbox_proof -> Some () | _ -> None) + (fun () -> Sc_rollup_invalid_serialized_inbox_proof) + +type reveal_proof = + | Raw_data_proof of string + | Metadata_proof + | Dal_page_proof of { + page_id : Dal_slot_repr.Page.t; + proof : Dal_slot_repr.History.proof; + } + | Dal_parameters_proof + +let reveal_proof_encoding = + let open Data_encoding in + let case_raw_data = + case + ~title:"raw data proof" + (Tag 0) + (obj2 + (req "reveal_proof_kind" (constant "raw_data_proof")) + (req + "raw_data" + Bounded.( + string + ~length_kind:`Uint16 + Hex + Constants_repr.sc_rollup_message_size_limit))) + (function Raw_data_proof s -> Some ((), s) | _ -> None) + (fun ((), s) -> Raw_data_proof s) + and case_metadata_proof = + case + ~title:"metadata proof" + (Tag 1) + (obj1 (req "reveal_proof_kind" (constant "metadata_proof"))) + (function Metadata_proof -> Some () | _ -> None) + (fun () -> Metadata_proof) + in + let case_dal_page = + case + ~title:"dal page proof" + (Tag 2) + (obj3 + (req "reveal_proof_kind" (constant "dal_page_proof")) + (req "dal_page_id" Dal_slot_repr.Page.encoding) + (req "dal_proof" Dal_slot_repr.History.proof_encoding)) + (function + | Dal_page_proof {page_id; proof} -> Some ((), page_id, proof) + | _ -> None) + (fun ((), page_id, proof) -> Dal_page_proof {page_id; proof}) + in + let case_dal_parameters = + case + ~title:"dal parameters proof" + (Tag 3) + (obj1 (req "reveal_proof_kind" (constant "dal_parameters_proof"))) + (function Dal_parameters_proof -> Some () | _ -> None) + (fun () -> Dal_parameters_proof) + in + union [case_raw_data; case_metadata_proof; case_dal_page; case_dal_parameters] + +type input_proof = + | Inbox_proof of { + level : Raw_level_repr.t; + message_counter : Z.t; + proof : Sc_rollup_inbox_repr.serialized_proof; + } + | Reveal_proof of reveal_proof + | First_inbox_message + +let input_proof_encoding = + let open Data_encoding in + let proof_kind kind = req "input_proof_kind" (constant kind) in + let case_inbox_proof = + case + ~title:"inbox proof" + (Tag 0) + (obj4 + (proof_kind "inbox_proof") + (req "level" Raw_level_repr.encoding) + (req "message_counter" Data_encoding.n) + (req "serialized_proof" Sc_rollup_inbox_repr.serialized_proof_encoding)) + (function + | Inbox_proof {level; message_counter; proof} -> + Some ((), level, message_counter, proof) + | _ -> None) + (fun ((), level, message_counter, proof) -> + Inbox_proof {level; message_counter; proof}) + in + let case_reveal_proof = + case + ~title:"reveal proof" + (Tag 1) + (obj2 + (proof_kind "reveal_proof") + (req "reveal_proof" reveal_proof_encoding)) + (function Reveal_proof s -> Some ((), s) | _ -> None) + (fun ((), s) -> Reveal_proof s) + in + let first_input = + case + ~title:"first input" + (Tag 2) + (obj1 (proof_kind "first_input")) + (function First_inbox_message -> Some () | _ -> None) + (fun () -> First_inbox_message) + in + union [case_inbox_proof; case_reveal_proof; first_input] + +type 'proof t = {pvm_step : 'proof; input_proof : input_proof option} + +type serialized = string + +let serialize_pvm_step (type state proof output) + ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) + (proof : proof) : serialized tzresult = + let open Result_syntax in + let (module PVM) = pvm in + match Data_encoding.Binary.to_string_opt PVM.proof_encoding proof with + | Some p -> return p + | None -> tzfail (Sc_rollup_proof_check "Cannot serialize proof") + +let unserialize_pvm_step (type state proof output) + ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) + (proof : string) : proof tzresult = + let open Result_syntax in + let (module PVM) = pvm in + match Data_encoding.Binary.of_string_opt PVM.proof_encoding proof with + | Some p -> return p + | None -> tzfail (Sc_rollup_proof_check "Cannot unserialize proof") + +let serialized_encoding = Data_encoding.string Hex + +let encoding = + let open Data_encoding in + conv + (fun {pvm_step; input_proof} -> (pvm_step, input_proof)) + (fun (pvm_step, input_proof) -> {pvm_step; input_proof}) + (obj2 + (req "pvm_step" serialized_encoding) + (opt "input_proof" input_proof_encoding)) + +let pp ppf _ = Format.fprintf ppf "Refutation game proof" + +let start_of_pvm_step (type state proof output) + ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) + (proof : proof) = + let (module P) = pvm in + P.proof_start_state proof + +let stop_of_pvm_step (type state proof output) + ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) + (proof : proof) = + let (module P) = pvm in + P.proof_stop_state proof + +(* This takes an [input] and checks if it is above the given level, + and if it is at or below the origination level for this rollup. + It returns [None] if this is the case. + + We use this to check that the PVM proof is obeying [commit_inbox_level] + correctly---if the message obtained from the inbox proof is above + [commit_inbox_level] the [input_given] in the PVM proof should be [None]. *) +let cut_at_level ~origination_level ~commit_inbox_level + (input : Sc_rollup_PVM_sig.input) = + match input with + | Inbox_message {inbox_level = input_level; _} -> + if + Raw_level_repr.( + input_level <= origination_level || commit_inbox_level < input_level) + then None + else Some input + | Reveal _data -> Some input + +let proof_error reason = + let open Lwt_result_syntax in + tzfail (Sc_rollup_proof_check reason) + +let check p reason = + let open Lwt_result_syntax in + if p then return_unit else proof_error reason + +let check_inbox_proof snapshot serialized_inbox_proof (level, counter) = + match Sc_rollup_inbox_repr.of_serialized_proof serialized_inbox_proof with + | None -> Result_syntax.tzfail Sc_rollup_invalid_serialized_inbox_proof + | Some inbox_proof -> + Sc_rollup_inbox_repr.verify_proof (level, counter) snapshot inbox_proof + +module Dal_helpers = struct + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + The current DAL refutation integration is not resilient to DAL parameters + changes when upgrading the protocol. The code needs to be adapted. *) + + let import_level_is_valid ~dal_activation_level ~dal_attestation_lag + ~origination_level ~commit_inbox_level ~published_level + ~dal_attested_slots_validity_lag = + (* [dal_attestation_lag] is supposed to be positive. *) + let open Raw_level_repr in + let dal_was_activated = + match dal_activation_level with + | None -> false + | Some dal_activation_level -> published_level >= dal_activation_level + in + let slot_published_after_origination = + published_level > origination_level + in + let not_too_recent = + add published_level dal_attestation_lag <= commit_inbox_level + in + (* An attested slot is not expired if its attested level (equal to + [published_level + dal_attestation_lag]) is not further than + [dal_attested_slots_validity_lag] from the given inbox level. *) + let ttl_not_expired = + Raw_level_repr.( + add + (add published_level dal_attestation_lag) + dal_attested_slots_validity_lag + >= commit_inbox_level) + in + dal_was_activated && slot_published_after_origination && not_too_recent + && ttl_not_expired + + let page_id_is_valid ~dal_number_of_slots ~dal_activation_level + ~dal_attestation_lag ~origination_level ~commit_inbox_level + cryptobox_parameters + Dal_slot_repr.Page.{slot_id = {published_level; index}; page_index} + ~dal_attested_slots_validity_lag = + let open Dal_slot_repr in + Result.is_ok + (Page.Index.check_is_in_range + ~number_of_pages:(Page.pages_per_slot cryptobox_parameters) + page_index) + && Result.is_ok + (Dal_slot_index_repr.check_is_in_range + ~number_of_slots:dal_number_of_slots + index) + && import_level_is_valid + ~dal_activation_level + ~dal_attestation_lag + ~origination_level + ~commit_inbox_level + ~published_level + ~dal_attested_slots_validity_lag + + let verify ~metadata ~dal_activation_level ~dal_attestation_lag + ~dal_number_of_slots ~commit_inbox_level dal_parameters page_id + dal_snapshot proof ~dal_attested_slots_validity_lag = + let open Result_syntax in + if + page_id_is_valid + dal_parameters + ~dal_activation_level + ~origination_level:metadata.Sc_rollup_metadata_repr.origination_level + ~dal_attestation_lag + ~commit_inbox_level + ~dal_number_of_slots + page_id + ~dal_attested_slots_validity_lag + then + let* input = + Dal_slot_repr.History.verify_proof + dal_parameters + page_id + dal_snapshot + proof + in + return_some (Sc_rollup_PVM_sig.Reveal (Dal_page input)) + else return_none + + let produce ~metadata ~dal_activation_level ~dal_attestation_lag + ~dal_number_of_slots ~commit_inbox_level dal_parameters page_id ~page_info + ~get_history confirmed_slots_history ~dal_attested_slots_validity_lag = + let open Lwt_result_syntax in + if + page_id_is_valid + dal_parameters + ~dal_number_of_slots + ~dal_activation_level + ~origination_level:metadata.Sc_rollup_metadata_repr.origination_level + ~dal_attestation_lag + ~commit_inbox_level + page_id + ~dal_attested_slots_validity_lag + then + let* proof, content_opt = + Dal_slot_repr.History.produce_proof + dal_parameters + page_id + ~page_info + ~get_history + confirmed_slots_history + in + return + ( Some (Reveal_proof (Dal_page_proof {proof; page_id})), + Some (Sc_rollup_PVM_sig.Reveal (Dal_page content_opt)) ) + else return (None, None) +end + +let valid (type state proof output) + ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) ~metadata + snapshot commit_inbox_level dal_snapshot dal_parameters + ~dal_activation_level ~dal_attestation_lag ~dal_number_of_slots + ~is_reveal_enabled ~dal_attested_slots_validity_lag (proof : proof t) = + let open Lwt_result_syntax in + let (module P) = pvm in + let origination_level = metadata.Sc_rollup_metadata_repr.origination_level in + let* input = + match proof.input_proof with + | None -> return_none + | Some (Inbox_proof {level; message_counter; proof}) -> + let*? inbox_message = + check_inbox_proof snapshot proof (level, Z.succ message_counter) + in + return + @@ Option.map (fun i -> Sc_rollup_PVM_sig.Inbox_message i) inbox_message + | Some First_inbox_message -> + let*? payload = + Sc_rollup_inbox_message_repr.(serialize (Internal Start_of_level)) + in + let inbox_level = Raw_level_repr.succ origination_level in + let message_counter = Z.zero in + return_some + Sc_rollup_PVM_sig.( + Inbox_message {inbox_level; message_counter; payload}) + | Some (Reveal_proof (Raw_data_proof data)) -> + return_some (Sc_rollup_PVM_sig.Reveal (Raw_data data)) + | Some (Reveal_proof Metadata_proof) -> + return_some (Sc_rollup_PVM_sig.Reveal (Metadata metadata)) + | Some (Reveal_proof (Dal_page_proof {proof; page_id})) -> + Dal_helpers.verify + ~dal_number_of_slots + ~metadata + ~dal_activation_level + ~dal_attested_slots_validity_lag + dal_parameters + ~dal_attestation_lag + ~commit_inbox_level + page_id + dal_snapshot + proof + |> Lwt.return + | Some (Reveal_proof Dal_parameters_proof) -> + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/6562 + Support revealing historical DAL parameters. + + Currently, we do not support revealing DAL parameters for the past. + We ignore the given [published_level] and use the DAL parameters. *) + return_some + (Sc_rollup_PVM_sig.Reveal + (Dal_parameters + Sc_rollup_dal_parameters_repr. + { + number_of_slots = Int64.of_int dal_number_of_slots; + attestation_lag = Int64.of_int dal_attestation_lag; + slot_size = Int64.of_int dal_parameters.slot_size; + page_size = Int64.of_int dal_parameters.page_size; + })) + in + let input = + Option.bind input (cut_at_level ~origination_level ~commit_inbox_level) + in + let* input_requested = + P.verify_proof ~is_reveal_enabled input proof.pvm_step + in + let* () = + match (proof.input_proof, input_requested) with + | None, No_input_required -> return_unit + | Some First_inbox_message, Initial -> + (* If the state is [Initial], we don't need a proof of the input, + we know it's the [Start_of_level] after the origination. *) + return_unit + | Some (Inbox_proof {level; message_counter; proof = _}), First_after (l, n) + -> + check + (Raw_level_repr.(level = l) && Z.(equal message_counter n)) + "Level and index of inbox proof are not equal to the one expected in \ + input request." + | ( Some (Reveal_proof (Raw_data_proof data)), + Needs_reveal (Reveal_raw_data expected_hash) ) -> + let scheme = Sc_rollup_reveal_hash.scheme_of_hash expected_hash in + + let data_hash = Sc_rollup_reveal_hash.hash_string ~scheme [data] in + check + (Sc_rollup_reveal_hash.equal data_hash expected_hash) + "Invalid reveal" + | Some (Reveal_proof Metadata_proof), Needs_reveal Reveal_metadata -> + return_unit + | ( Some (Reveal_proof (Dal_page_proof {page_id; proof = _})), + Needs_reveal (Request_dal_page pid) ) -> + check + (Dal_slot_repr.Page.equal page_id pid) + "Dal proof's page ID is not the one expected in input request." + | ( Some (Reveal_proof Dal_parameters_proof), + Needs_reveal Reveal_dal_parameters ) -> + return_unit + | None, (Initial | First_after _ | Needs_reveal _) + | Some _, No_input_required + | Some (Inbox_proof _), Needs_reveal _ + | _ -> + proof_error "Inbox proof and input request are dissociated." + in + return (input, input_requested) + +module type PVM_with_context_and_state = sig + include Sc_rollups.PVM.S + + val context : context + + val state : state + + val proof_encoding : proof Data_encoding.t + + val reveal : Sc_rollup_reveal_hash.t -> string option Lwt.t + + module Inbox_with_history : sig + val inbox : Sc_rollup_inbox_repr.history_proof + + val get_history : + Sc_rollup_inbox_repr.Hash.t -> + Sc_rollup_inbox_repr.history_proof option Lwt.t + + val get_payloads_history : + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t Lwt.t + end + + module Dal_with_history : sig + val confirmed_slots_history : Dal_slot_repr.History.t + + val get_history : + Dal_slot_repr.History.hash -> Dal_slot_repr.History.t option Lwt.t + + val page_info : + (Dal_slot_repr.Page.content * Dal_slot_repr.Page.proof) option + + val dal_parameters : Dal_slot_repr.parameters + + val dal_attestation_lag : int + + val dal_number_of_slots : int + + val dal_activation_level : Raw_level_repr.t option + + val dal_attested_slots_validity_lag : int + end +end + +let produce ~metadata pvm_and_state commit_inbox_level ~is_reveal_enabled = + let open Lwt_result_syntax in + let (module P : PVM_with_context_and_state) = pvm_and_state in + let open P in + let*! (request : Sc_rollup_PVM_sig.input_request) = + P.is_input_state ~is_reveal_enabled P.state + in + let origination_level = metadata.Sc_rollup_metadata_repr.origination_level in + let* input_proof, input_given = + match request with + | No_input_required -> return (None, None) + | Initial -> + (* The first input of a rollup is the [Start_of_level] after its + origination. *) + let* input = + let*? payload = + Sc_rollup_inbox_message_repr.(serialize (Internal Start_of_level)) + in + let inbox_level = Raw_level_repr.succ origination_level in + let message_counter = Z.zero in + return_some + Sc_rollup_PVM_sig.( + Inbox_message {inbox_level; message_counter; payload}) + in + let inbox_proof = First_inbox_message in + return (Some inbox_proof, input) + | First_after (level, message_counter) -> + let* inbox_proof, input = + Inbox_with_history.( + Sc_rollup_inbox_repr.produce_proof + ~get_payloads_history + ~get_history + inbox + (level, Z.succ message_counter)) + in + let input = + Option.map (fun msg -> Sc_rollup_PVM_sig.Inbox_message msg) input + in + let inbox_proof = + Inbox_proof + { + level; + message_counter; + proof = Sc_rollup_inbox_repr.to_serialized_proof inbox_proof; + } + in + return (Some inbox_proof, input) + | Needs_reveal (Reveal_raw_data h) -> ( + let*! res = reveal h in + match res with + | None -> proof_error "No reveal" + | Some data -> + return + ( Some (Reveal_proof (Raw_data_proof data)), + Some (Sc_rollup_PVM_sig.Reveal (Raw_data data)) )) + | Needs_reveal Reveal_metadata -> + return + ( Some (Reveal_proof Metadata_proof), + Some Sc_rollup_PVM_sig.(Reveal (Metadata metadata)) ) + | Needs_reveal (Request_dal_page page_id) -> + let open Dal_with_history in + Dal_helpers.produce + ~dal_number_of_slots + ~metadata + ~dal_activation_level + dal_parameters + ~dal_attestation_lag + ~commit_inbox_level + page_id + ~page_info + ~get_history + ~dal_attested_slots_validity_lag + confirmed_slots_history + | Needs_reveal Reveal_dal_parameters -> + let open Dal_with_history in + return + ( Some (Reveal_proof Dal_parameters_proof), + Some + Sc_rollup_PVM_sig.( + Reveal + (Dal_parameters + Sc_rollup_dal_parameters_repr. + { + number_of_slots = Int64.of_int dal_number_of_slots; + attestation_lag = Int64.of_int dal_attestation_lag; + slot_size = Int64.of_int dal_parameters.slot_size; + page_size = Int64.of_int dal_parameters.page_size; + })) ) + in + let input_given = + Option.bind + input_given + (cut_at_level ~origination_level ~commit_inbox_level) + in + let* pvm_step_proof = + P.produce_proof P.context ~is_reveal_enabled input_given P.state + in + let*? pvm_step = serialize_pvm_step ~pvm:(module P) pvm_step_proof in + return {pvm_step; input_proof} + +module Internal_for_tests = struct + let cut_at_level = cut_at_level +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.mli new file mode 100644 index 000000000000..968d4d2aebe1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_proof_repr.mli @@ -0,0 +1,315 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A refutation game proof is required as part of the final move in a + game. + + This proof is basically a combination of a PVM proof (provided by + each implementation of the PVM signature) and an input proof. To + check the proof we must check each part separately and then also + check that they match on the two points where they touch: + + - the [input_requested] of the PVM proof should match the starting + point of the input proof ; + + - the [input_given] of the PVM proof should match the output + message of the input proof. + + It is also often the case that the PVM proof has [No_input_required] + for its [input_requested] and [None] for its [input_given]. If this + is the case, we don't need the input proof at all and the [input_proof] + parameter in our proof should be [None]. *) + +(** The proof that a reveal is valid. *) +type reveal_proof = + | Raw_data_proof of string + (** The existence of reveal for a given hash when the + [input_requested] is the [Needs_reveal Reveal_raw_data]. *) + | Metadata_proof + | Dal_page_proof of { + page_id : Dal_slot_repr.Page.t; + proof : Dal_slot_repr.History.proof; + } + (** The existence or not of a confirmed slot for a given page ID when the + [input_requested] is the [Needs_reveal Request_dal_page]. *) + | Dal_parameters_proof + (** Proof for revealing DAL parameters that were used for the slots + published at [published_level]. The [published_level] parameter + enables the kernel to retrieve historical DAL parameters, + eliminating the need for each kernel to store past DAL parameters. *) + +(** A PVM proof [pvm_step] is combined with an [input_proof] to provide + the proof necessary to validate a single step in the refutation + game. + + If the step doesn't involve any input, [proof_input_requested + pvm_step] and [proof_input_given pvm_step] will be + [No_input_required] and [None] respectively, and in this case + [inbox] should also be [None]. + + In the case that input is involved, [input_proof] is either: + + - a proof of the next inbox message available from the inbox + after a given location; this must match up with [pvm_step] + to give a valid refutation proof ; or + + - a proof of a reveal satisfiability. + + - a claim that the input involved is the first input of the inbox, which + does not need to be proved as we know by construction what is + the input (i.e. the [Start_of_level] of the level after the rollup's + origination level). +*) + +type input_proof = + | Inbox_proof of { + level : Raw_level_repr.t; + message_counter : Z.t; + proof : Sc_rollup_inbox_repr.serialized_proof; + } + | Reveal_proof of reveal_proof + | First_inbox_message + +type 'proof t = {pvm_step : 'proof; input_proof : input_proof option} + +type serialized = private string + +(** [serialize_pvm_step ~pvm proof] turns a structured representation + of a step proof of [pvm] into its serialized representation. *) +val serialize_pvm_step : + pvm:('state, 'proof, 'output) Sc_rollups.PVM.implementation -> + 'proof -> + serialized tzresult + +(** [unserialize_pvm_step ~pvm proof] turns a serialized + representation of a step proof of [pvm] into its structured + representation. *) +val unserialize_pvm_step : + pvm:('state, 'proof, 'output) Sc_rollups.PVM.implementation -> + serialized -> + 'proof tzresult + +type error += Sc_rollup_proof_check of string + +type error += Sc_rollup_invalid_serialized_inbox_proof + +val serialized_encoding : serialized Data_encoding.t + +val encoding : serialized t Data_encoding.t + +val pp : Format.formatter -> 'a t -> unit + +(** The state hash of the machine before the step. This must be checked + against the value in the refutation game as well as checking the + proof is valid. *) +val start_of_pvm_step : + pvm:('state, 'proof, 'output) Sc_rollups.PVM.implementation -> + 'proof -> + Sc_rollup_repr.State_hash.t + +(** The state hash of the machine after the step. This must be checked + against the value in the refutation game as well as checking the + proof is valid. *) +val stop_of_pvm_step : + pvm:('state, 'proof, 'output) Sc_rollups.PVM.implementation -> + 'proof -> + Sc_rollup_repr.State_hash.t + +(** Check the validity of a proof. + + This function requires a few bits of data (available from the + refutation game record in the storage): + + - a snapshot of the inbox, that may be used by the [input] proof in case + it's an inbox message ; + + - a snapshot of the DAL confirmed slots structure, that may be used by + the [input] proof in case the input is a DAL page ; + + - the inbox level of the commitment, used to determine if an + output from the [input] proof is too recent to be allowed into + the PVM proof ; + + - DAL related parameters, to be able to check the page content membership + to a slot or check the revealed parameters if needed ; + + - the [pvm_name], used to check that the proof given has the right + PVM kind. + + - The level at which DAL is activated (None if the DAL is not enabled). + It also returns the optional input executed during the proof and the + input_request for the state at the beginning of the proof. +*) +val valid : + pvm:('state, 'proof, 'output) Sc_rollups.PVM.implementation -> + metadata:Sc_rollup_metadata_repr.t -> + Sc_rollup_inbox_repr.history_proof -> + Raw_level_repr.t -> + Dal_slot_repr.History.t -> + Dal_slot_repr.parameters -> + dal_activation_level:Raw_level_repr.t option -> + dal_attestation_lag:int -> + dal_number_of_slots:int -> + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + dal_attested_slots_validity_lag:int -> + 'proof t -> + (Sc_rollup_PVM_sig.input option * Sc_rollup_PVM_sig.input_request) tzresult + Lwt.t + +module type PVM_with_context_and_state = sig + include Sc_rollups.PVM.S + + val context : context + + val state : state + + val proof_encoding : proof Data_encoding.t + + val reveal : Sc_rollup_reveal_hash.t -> string option Lwt.t + + module Inbox_with_history : sig + val inbox : Sc_rollup_inbox_repr.history_proof + + val get_history : + Sc_rollup_inbox_repr.Hash.t -> + Sc_rollup_inbox_repr.history_proof option Lwt.t + + val get_payloads_history : + Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash.t -> + Sc_rollup_inbox_merkelized_payload_hashes_repr.History.t Lwt.t + end + + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This interface might not be resilient to dal parameters changes + (cryptobox parameters or dal_attestation_lag for instance). *) + module Dal_with_history : sig + (** The reference/snapshot cell of the DAL skip list that stores + confirmed slots. *) + val confirmed_slots_history : Dal_slot_repr.History.t + + (** A function to retrieve a history from an underlying cache. *) + val get_history : + Dal_slot_repr.History.hash -> Dal_slot_repr.History.t option Lwt.t + + (** In case we expect to generate an input proof that is a DAL page + confirmation, we should provide via [page_info] the information of the + page. That is: its content and the proof that the page is part of a + confirmed slot whose ID is part of the page's ID. + + In case we expect to generate an input proof to justify that a DAL page + is not confirmed, the value of [page_info] should be [None]. + + In case the proof doesn't involve DAL inputs, the value of [page_info] + is [None]. *) + val page_info : + (Dal_slot_repr.Page.content * Dal_slot_repr.Page.proof) option + + (** Some parameters of the DAL. Needed when checking a page's proof against + a slot's {!val: Dal_slot_repr.commitment}. *) + val dal_parameters : Dal_slot_repr.parameters + + (** The lag between the time an attestation is published on L1 + (its published_level) and the level it should be confirmed. *) + val dal_attestation_lag : int + + (** The number of DAL slots provided by the L1. *) + val dal_number_of_slots : int + + (** The level at which the DAL got activated, [None] if the DAL has not yet been activated. *) + val dal_activation_level : Raw_level_repr.t option + + val dal_attested_slots_validity_lag : int + end +end + +(** [produce ~metadata pvm_and_state inbox_context inbox_history + commit_inbox_level] will construct a full refutation game proof out of + the [state] given in [pvm_and_state]. It uses the [inbox] if necessary to + provide input in the proof. If the input is above or at [commit_level] it + will block it, and produce a proof that the PVM is blocked. If + the input requested is a reveal the proof production will also + fail. + + This will fail if any of the [context], [inbox_context], [inbox_history] or + [dal_slots_history_cache] given doesn't have enough data to make the proof. + For example, the 'protocol implementation' version of each PVM won't be + able to run this function. Similarly, the version of the inbox + stored in the L1 won't be enough because it forgets old levels. + + This uses the [name] in the [pvm_and_state] module to produce an + encodable [wrapped_proof] if possible. See the [wrap_proof] function + in [Sc_rollups]. + + It also need the [metadata] if it produces a proof for the [Needs_metadata] + state. +*) +val produce : + metadata:Sc_rollup_metadata_repr.t -> + (module PVM_with_context_and_state) -> + Raw_level_repr.t -> + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + serialized t tzresult Lwt.t + +module Dal_helpers : sig + (** We consider that a DAL page or slot published at a level [published_level] + is valid, and produce or verify a proof for it if, and only if, the level + is in the following boundaries: + + - DAL is activated and [published_level] >= [dal_activation_level] + - [published_level] > [origination_level]: this means that the slot of the + page was published after the rollup origination ; + + - [published_level] + [dal_attestation_lag] <= [commit_inbox_level]: this + means that the slot of the page has been attested before or at the + [commit_inbox_level]. + + According to the definition in {!Sc_rollup_commitment_repr}, + [commit_inbox_level] (aka inbox_level in that module) is the level + (included) up to which the PVM consumed all messages and DAL/DAC inputs + before producing the related commitment. + We also check that the given slot ID's index is within the range of + allowed slots thanks to [dal_number_of_slots]. *) + val import_level_is_valid : + dal_activation_level:Raw_level_repr.t option -> + dal_attestation_lag:int -> + origination_level:Raw_level_repr.t -> + commit_inbox_level:Raw_level_repr.t -> + published_level:Raw_level_repr.t -> + dal_attested_slots_validity_lag:int -> + bool +end + +(**/**) + +module Internal_for_tests : sig + (** Export internal [cut_at_level] function. See the docstring in the + implementation file for more information. *) + val cut_at_level : + origination_level:Raw_level_repr.t -> + commit_inbox_level:Raw_level_repr.t -> + Sc_rollup_PVM_sig.input -> + Sc_rollup_PVM_sig.input option +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.ml new file mode 100644 index 000000000000..ea12778a017a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.ml @@ -0,0 +1,665 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_errors +module Store = Storage.Sc_rollup +module Commitment = Sc_rollup_commitment_repr +module Commitment_storage = Sc_rollup_commitment_storage +module Commitment_hash = Commitment.Hash +module Stake_storage = Sc_rollup_stake_storage + +type point = { + commitment : Sc_rollup_commitment_repr.t; + hash : Commitment_hash.t; +} + +type conflict_point = point * point + +(** [initial_timeout ctxt] set the initial timeout of players. The initial + timeout of each player is equal to [sc_rollup_timeout_period_in_blocks]. *) +let initial_timeout ctxt = + let last_turn_level = (Raw_context.current_level ctxt).level in + let timeout_period_in_blocks = + Constants_storage.sc_rollup_timeout_period_in_blocks ctxt + in + Sc_rollup_game_repr. + { + alice = timeout_period_in_blocks; + bob = timeout_period_in_blocks; + last_turn_level; + } + +(** [update_timeout ctxt rollup game idx] update the timeout left for the + current player [game.turn]. Her new timeout is equal to [nb_of_block_left - + (current_level - last_turn_level)] where [nb_of_block_left] is her current + timeout. *) +let update_timeout ctxt rollup (game : Sc_rollup_game_repr.t) idx = + let open Lwt_result_syntax in + let* ctxt, timeout = Store.Game_timeout.get (ctxt, rollup) idx in + let current_level = (Raw_context.current_level ctxt).level in + let sub_block_left nb_of_block_left = + nb_of_block_left + - Int32.to_int (Raw_level_repr.diff current_level timeout.last_turn_level) + in + let new_timeout = + match game.turn with + | Alice -> + let nb_of_block_left = sub_block_left timeout.alice in + {timeout with last_turn_level = current_level; alice = nb_of_block_left} + | Bob -> + let nb_of_block_left = sub_block_left timeout.bob in + {timeout with last_turn_level = current_level; bob = nb_of_block_left} + in + let* ctxt, _ = Store.Game_timeout.update (ctxt, rollup) idx new_timeout in + return ctxt + +let get_ongoing_games_for_staker ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, entries = Store.Game.list_key_values ((ctxt, rollup), staker) in + let* ctxt, games = + List.fold_left_es + (fun (ctxt, games) (opponent, game_index) -> + let* ctxt, answer = Store.Game_info.find (ctxt, rollup) game_index in + match answer with + | None -> + (* A hash in [Store.Game] is always present in [Store.Game_info]. *) + assert false + | Some game -> + let games = + (game, Sc_rollup_game_repr.Index.make staker opponent) :: games + in + return (ctxt, games)) + (ctxt, []) + entries + in + return (games, ctxt) + +(** [commitments_are_conflicting ctxt rollup hash1_opt hash2_opt] + returns a conflict description iff [hash1_opt] and [hash2_opt] are + two different commitments with the same predecessor. *) +let commitments_are_conflicting ctxt rollup hash1_opt hash2_opt = + let open Lwt_result_syntax in + match (hash1_opt, hash2_opt) with + | Some hash1, Some hash2 when Commitment_hash.(hash1 <> hash2) -> + let* commitment1, ctxt = + Commitment_storage.get_commitment_unsafe ctxt rollup hash1 + in + let* commitment2, ctxt = + Commitment_storage.get_commitment_unsafe ctxt rollup hash2 + in + if Commitment_hash.(commitment1.predecessor = commitment2.predecessor) + then + let conflict_point = + ( {hash = hash1; commitment = commitment1}, + {hash = hash2; commitment = commitment2} ) + in + return (ctxt, Some conflict_point) + else return (ctxt, None) + | _ -> return (ctxt, None) + +(** [look_for_conflict ctxt rollup staker1_index staker2_index from_level + upto_level delta] looks for the first conflict of [staker1_index] + and [staker2_index]. + + It starts at [from_level] which the last cemented inbox level on the + [rollup], and climbs the staking's storage through a recursive + function. + + Two important notes: + {ol + {li The code can do at most (max_lookahead / commitment_period) recursive + calls, which can be a lot;} + {li Therefore, this code must be called only via a RPC, used by the + rollup-node. The {!check_conflict_point} used by the protocol is + on the other hand, very cheap.} + } + + FIXME: https://gitlab.com/tezos/tezos/-/issues/4477 + As it should be used only via an RPC (and by the rollup-node), we should + move this function (and other related functions) outside the protocol. +*) +let look_for_conflict ctxt rollup staker1_index staker2_index from_level + upto_level delta = + let open Lwt_result_syntax in + let rec go ctxt from_level = + if Raw_level_repr.(from_level >= upto_level) then + tzfail Sc_rollup_no_conflict + else + let* ctxt, commitments = + Sc_rollup_stake_storage.commitments_of_inbox_level + ctxt + rollup + from_level + in + let* ctxt, hash1_opt = + Sc_rollup_stake_storage.find_commitment_of_staker_in_commitments + ctxt + rollup + staker1_index + commitments + in + let* ctxt, hash2_opt = + Sc_rollup_stake_storage.find_commitment_of_staker_in_commitments + ctxt + rollup + staker2_index + commitments + in + let* ctxt, conflict_point_opt = + commitments_are_conflicting ctxt rollup hash1_opt hash2_opt + in + match conflict_point_opt with + | Some conflict_point -> return (conflict_point, ctxt) + | None -> + let from_level = Raw_level_repr.add from_level delta in + go ctxt from_level + in + go ctxt from_level + +(** [get_conflict_point ctxt rollup staker1 staker2] starts from the + LCC's successor and look for the first conflict between [staker1] and + [staker2], if any. *) +let get_conflict_point ctxt rollup staker1 staker2 = + let open Lwt_result_syntax in + let* ctxt, staker1_index = + Sc_rollup_staker_index_storage.get_staker_index_unsafe ctxt rollup staker1 + in + let* ctxt, staker2_index = + Sc_rollup_staker_index_storage.get_staker_index_unsafe ctxt rollup staker2 + in + let* _lcc, lcc_inbox_level, ctxt = + Commitment_storage.last_cemented_commitment_hash_with_level ctxt rollup + in + let current_level = (Raw_context.current_level ctxt).level in + let commitment_period = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + look_for_conflict + ctxt + rollup + staker1_index + staker2_index + (Raw_level_repr.add lcc_inbox_level commitment_period) + current_level + commitment_period + +let find_game ctxt rollup stakers = + let open Lwt_result_syntax in + let open Sc_rollup_game_repr.Index in + let* ctxt, game_index = + Store.Game.find ((ctxt, rollup), stakers.alice) stakers.bob + in + match game_index with + | None -> return (ctxt, None) + | Some game_hash -> Store.Game_info.find (ctxt, rollup) game_hash + +let get_game ctxt rollup stakers = + let open Lwt_result_syntax in + let* ctxt, game = find_game ctxt rollup stakers in + match game with + | None -> tzfail Sc_rollup_no_game + | Some game -> return (game, ctxt) + +let create_game ctxt rollup stakers game = + let open Lwt_result_syntax in + let open Sc_rollup_game_repr.Index in + let* ctxt, _ = Store.Game_info.init (ctxt, rollup) stakers game in + let* ctxt, _ = + Store.Game.init ((ctxt, rollup), stakers.alice) stakers.bob stakers + in + let* ctxt, _ = + Store.Game.init ((ctxt, rollup), stakers.bob) stakers.alice stakers + in + return ctxt + +let update_game ctxt rollup stakers new_game = + let open Lwt_result_syntax in + let* ctxt, _storage_diff = + Store.Game_info.update (ctxt, rollup) stakers new_game + in + return ctxt + +let remove_game ctxt rollup stakers = + let open Lwt_result_syntax in + let open Sc_rollup_game_repr.Index in + let* ctxt, _storage_diff, _was_here = + Store.Game.remove ((ctxt, rollup), stakers.alice) stakers.bob + in + let* ctxt, _storage_diff, _was_here = + Store.Game.remove ((ctxt, rollup), stakers.bob) stakers.alice + in + let* ctxt, _storage_diff, _was_here = + Store.Game_info.remove (ctxt, rollup) stakers + in + return ctxt + +(** [check_conflict_point ctxt rollup ~refuter ~refuter_commitment_hash + ~defender ~defender_commitment_hash] checks that the refuter is staked on + [commitment] with hash [refuter_commitment_hash], res. for [defender] and + [defender_commitment] with hash [defender_commitment_hash]. Fails with + {!Sc_rollup_errors.Sc_rollup_wrong_staker_for_conflict_commitment}. + + It also verifies that both are pointing to the same predecessor and thus are + in conflict, fails with + {!Sc_rollup_errors.Sc_rollup_not_first_conflict_between_stakers} otherwise. +*) +let check_conflict_point ctxt rollup ~refuter ~refuter_commitment_hash ~defender + ~defender_commitment_hash = + let open Lwt_result_syntax in + let fail_unless_staker_is_staked_on_commitment ctxt staker commitment_hash = + let* ctxt, is_staked = + Sc_rollup_stake_storage.is_staked_on ctxt rollup staker commitment_hash + in + let* () = + fail_unless + is_staked + (Sc_rollup_wrong_staker_for_conflict_commitment (staker, commitment_hash)) + in + return ctxt + in + let* ctxt = + fail_unless_staker_is_staked_on_commitment + ctxt + refuter + refuter_commitment_hash + in + let* ctxt = + fail_unless_staker_is_staked_on_commitment + ctxt + defender + defender_commitment_hash + in + let* refuter_commitment, ctxt = + Commitment_storage.get_commitment_unsafe ctxt rollup refuter_commitment_hash + in + let* defender_commitment, ctxt = + Commitment_storage.get_commitment_unsafe + ctxt + rollup + defender_commitment_hash + in + let* () = + fail_unless + Commitment_hash.(refuter_commitment_hash <> defender_commitment_hash) + Sc_rollup_errors.Sc_rollup_no_conflict + in + let* () = + fail_unless + Commitment_hash.( + refuter_commitment.predecessor = defender_commitment.predecessor) + (Sc_rollup_errors.Sc_rollup_not_valid_commitments_conflict + (refuter_commitment_hash, refuter, defender_commitment_hash, defender)) + in + return (defender_commitment, ctxt) + +let check_staker_availability ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, is_staker = + Sc_rollup_staker_index_storage.is_staker ctxt rollup staker + in + let* () = fail_unless is_staker Sc_rollup_not_staked in + let* ctxt, entries = Store.Game.list_key_values ((ctxt, rollup), staker) in + let* () = + fail_when + Compare.List_length_with.( + entries >= Constants_storage.sc_rollup_max_number_of_parallel_games ctxt) + (Sc_rollup_max_number_of_parallel_games_reached staker) + in + return ctxt + +(** [start_game ctxt rollup ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash)] initialises the game or if + it already exists fails with [Sc_rollup_game_already_started]. + + The game is created with [player] as the first player to + move. The initial state of the game will be obtained from the + commitment pair belonging to [opponent] at the conflict point. See + [Sc_rollup_game_repr.initial] for documentation on how a pair of + commitments is turned into an initial game state. + + This also deals with the other bits of data in the storage around + the game. Notice that a staker can participate in multiple games in + parallel. However, there is at most one game between two given stakers + since a staker can publish at most one commitment per inbox level. + + It also initialises the timeout level to the current level plus + [timeout_period_in_blocks] to mark the block level at which it becomes + possible for anyone to end the game by timeout. + + May fail with: + + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_no_conflict] if [player] is staked on an + ancestor of the commitment staked on by [opponent], or vice versa} + {li [Sc_rollup_not_staked] if one of the [player] or [opponent] is + not actually staked} + {li [Sc_rollup_staker_in_game] if one of the [player] or [opponent] + is already playing a game} + {li [Sc_rollup_not_first_conflict_between_stakers] if the provided + commitments are not the first commitments in conflict between + [player] and [opponent].} +*) +let start_game ctxt rollup ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash) = + let open Lwt_result_syntax in + (* When the game is started by a given [player], this player is + called the [refuter] and its opponent is the [defender]. *) + let refuter = player + and refuter_commitment_hash = player_commitment_hash + and defender = opponent + and defender_commitment_hash = opponent_commitment_hash in + let stakers = Sc_rollup_game_repr.Index.make refuter defender in + let* ctxt, game_exists = Store.Game_info.mem (ctxt, rollup) stakers in + let* () = fail_when game_exists Sc_rollup_game_already_started in + let* ctxt = check_staker_availability ctxt rollup stakers.alice in + let* ctxt = check_staker_availability ctxt rollup stakers.bob in + let* defender_commitment, ctxt = + check_conflict_point + ctxt + rollup + ~refuter + ~defender + ~refuter_commitment_hash + ~defender_commitment_hash + in + let* parent_commitment, ctxt = + Commitment_storage.get_commitment_unsafe + ctxt + rollup + defender_commitment.predecessor + in + let* inbox, ctxt = Sc_rollup_inbox_storage.get_inbox ctxt in + let default_number_of_sections = + Constants_storage.sc_rollup_number_of_sections_in_dissection ctxt + in + let* slots_history_snapshot = + Dal_slot_storage.get_slot_headers_history ctxt + in + let current_level = (Raw_context.current_level ctxt).level in + let game = + Sc_rollup_game_repr.initial + ~start_level:current_level + (Sc_rollup_inbox_repr.take_snapshot inbox) + slots_history_snapshot + ~refuter + ~defender + ~default_number_of_sections + ~parent_commitment + ~defender_commitment + in + let* ctxt = create_game ctxt rollup stakers game in + let* ctxt, _ = + Store.Game_timeout.init (ctxt, rollup) stakers (initial_timeout ctxt) + in + return ctxt + +let check_stakes ctxt rollup (stakers : Sc_rollup_game_repr.Index.t) = + let open Lwt_result_syntax in + let open Sc_rollup_game_repr in + let* ctxt, alice_stake = + Sc_rollup_staker_index_storage.is_staker ctxt rollup stakers.alice + in + let* ctxt, bob_stake = + Sc_rollup_staker_index_storage.is_staker ctxt rollup stakers.bob + in + let game_over loser = Loser {loser; reason = Conflict_resolved} in + match (alice_stake, bob_stake) with + | true, true -> return (None, ctxt) + | false, true -> return (Some (game_over stakers.alice), ctxt) + | true, false -> return (Some (game_over stakers.bob), ctxt) + | false, false -> return (Some Draw, ctxt) + +let game_move ctxt rollup ~player ~opponent ~step ~choice = + let open Lwt_result_syntax in + let stakers = Sc_rollup_game_repr.Index.make player opponent in + let* game, ctxt = get_game ctxt rollup stakers in + let* ctxt, kind = Store.PVM_kind.get ctxt rollup in + let* () = + fail_unless + (Sc_rollup_repr.Staker.equal + player + (Sc_rollup_game_repr.Index.staker stakers game.turn)) + Sc_rollup_wrong_turn + in + let* ctxt, metadata = Sc_rollup_storage.get_metadata ctxt rollup in + let constants = Constants_storage.parametric ctxt in + let dal = constants.dal in + let dal_activation_level = + if dal.feature_enable then + Some constants.sc_rollup.reveal_activation_level.dal_parameters + else None + in + let dal_attested_slots_validity_lag = + constants.sc_rollup.reveal_activation_level.dal_attested_slots_validity_lag + in + let* check_result, ctxt = check_stakes ctxt rollup stakers in + match check_result with + | Some game_result -> return (Some game_result, ctxt) + | None -> ( + let play_cost = Sc_rollup_game_repr.cost_play ~step ~choice in + let*? ctxt = Raw_context.consume_gas ctxt play_cost in + let* move_result = + Sc_rollup_game_repr.play + kind + dal.cryptobox_parameters + ~dal_activation_level + ~dal_attestation_lag:dal.attestation_lag + ~dal_number_of_slots:dal.number_of_slots + ~stakers + metadata + game + ~step + ~choice + ~is_reveal_enabled: + (Sc_rollup_PVM_sig.is_reveal_enabled_predicate + (Constants_storage.sc_rollup_reveal_activation_level ctxt)) + ~dal_attested_slots_validity_lag + in + match move_result with + | Either.Left game_result -> return (Some game_result, ctxt) + | Either.Right new_game -> + let* ctxt = update_game ctxt rollup stakers new_game in + let* ctxt = update_timeout ctxt rollup game stakers in + return (None, ctxt)) + +let get_timeout ctxt rollup stakers = + let open Lwt_result_syntax in + let* ctxt, timeout_opt = + Storage.Sc_rollup.Game_timeout.find (ctxt, rollup) stakers + in + match timeout_opt with + | Some timeout -> return (timeout, ctxt) + | None -> tzfail Sc_rollup_no_game + +let timeout ctxt rollup stakers = + let open Lwt_result_syntax in + let level = (Raw_context.current_level ctxt).level in + let* game, ctxt = get_game ctxt rollup stakers in + let* ctxt, timeout = Store.Game_timeout.get (ctxt, rollup) stakers in + let* () = + let block_left_before_timeout = + match game.turn with Alice -> timeout.alice | Bob -> timeout.bob + in + let level_of_timeout = + Raw_level_repr.add timeout.last_turn_level block_left_before_timeout + in + fail_unless + Raw_level_repr.(level > level_of_timeout) + (let blocks_left = Raw_level_repr.(diff level_of_timeout level) in + let staker = + match game.turn with Alice -> stakers.alice | Bob -> stakers.bob + in + Sc_rollup_timeout_level_not_reached (blocks_left, staker)) + in + let game_result = + match game.game_state with + | Dissecting _ -> + (* Timeout during the dissecting results in a loss. *) + let loser = Sc_rollup_game_repr.Index.staker stakers game.turn in + Sc_rollup_game_repr.(Loser {loser; reason = Timeout}) + | Final_move {agreed_start_chunk = _; refuted_stop_chunk = _} -> + (* Timeout-ed because the opponent played an invalid move and + the current player is not playing. Both are invalid moves. *) + Sc_rollup_game_repr.Draw + in + return (game_result, ctxt) + +let reward ctxt winner = + let open Lwt_result_syntax in + let winner_contract = Contract_repr.Implicit winner in + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + let*? reward = Tez_repr.(stake /? 2L) in + Token.transfer + ctxt + `Sc_rollup_refutation_rewards + (`Contract winner_contract) + reward + +let remove_if_staker_is_still_there ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, is_staker = + Sc_rollup_staker_index_storage.is_staker ctxt rollup staker + in + if is_staker then Stake_storage.remove_staker ctxt rollup staker + else return (ctxt, []) + +let apply_game_result ctxt rollup (stakers : Sc_rollup_game_repr.Index.t) + (game_result : Sc_rollup_game_repr.game_result) = + let open Lwt_result_syntax in + let status = Sc_rollup_game_repr.Ended game_result in + let* ctxt, balances_updates = + match game_result with + | Loser {loser; reason = _} -> + let losing_staker = loser in + let winning_staker = + let Sc_rollup_game_repr.Index.{alice; bob} = stakers in + if Signature.Public_key_hash.(alice = loser) then bob else alice + in + let* ctxt = remove_game ctxt rollup stakers in + let* ctxt, balance_updates_loser = + remove_if_staker_is_still_there ctxt rollup losing_staker + in + let* ctxt, balance_updates_winner = + (* The winner is rewarded only if he defeated himself the loser. + Another way to check this is to reward if the game result's reason + is not a forfeit. + *) + match balance_updates_loser with + | [] -> return (ctxt, []) + | _ -> reward ctxt winning_staker + in + let balances_updates = balance_updates_loser @ balance_updates_winner in + return (ctxt, balances_updates) + | Draw -> + let* ctxt = remove_game ctxt rollup stakers in + let* ctxt, balances_updates_alice = + remove_if_staker_is_still_there ctxt rollup stakers.alice + in + let* ctxt, balances_updates_bob = + remove_if_staker_is_still_there ctxt rollup stakers.bob + in + return (ctxt, balances_updates_alice @ balances_updates_bob) + in + let* ctxt, _storage_diff, _was_here = + Store.Game_timeout.remove (ctxt, rollup) stakers + in + return (status, ctxt, balances_updates) + +module Internal_for_tests = struct + let get_conflict_point = get_conflict_point +end + +type conflict = { + other : Sc_rollup_repr.Staker.t; + their_commitment : Sc_rollup_commitment_repr.t; + our_commitment : Sc_rollup_commitment_repr.t; + parent_commitment : Sc_rollup_commitment_repr.Hash.t; +} + +let conflict_encoding = + Data_encoding.( + conv + (fun {other; their_commitment; our_commitment; parent_commitment} -> + (other, their_commitment, our_commitment, parent_commitment)) + (fun (other, their_commitment, our_commitment, parent_commitment) -> + {other; their_commitment; our_commitment; parent_commitment}) + (obj4 + (req "other" Sc_rollup_repr.Staker.encoding) + (req "their_commitment" Sc_rollup_commitment_repr.encoding) + (req "our_commitment" Sc_rollup_commitment_repr.encoding) + (req "parent_commitment" Sc_rollup_commitment_repr.Hash.encoding))) + +let conflicting_stakers_uncarbonated ctxt rollup staker = + let open Lwt_result_syntax in + let make_conflict ctxt rollup other (our_point, their_point) = + let our_hash = our_point.hash and their_hash = their_point.hash in + let get = Sc_rollup_commitment_storage.get_commitment_unsafe ctxt rollup in + let* our_commitment, _ctxt = get our_hash in + let* their_commitment, _ctxt = get their_hash in + let parent_commitment = our_commitment.predecessor in + return {other; their_commitment; our_commitment; parent_commitment} + in + let*! stakers = + Sc_rollup_stake_storage.stakers_pkhs_uncarbonated ctxt ~rollup + in + List.fold_left_es + (fun conflicts other_staker -> + let*! res = get_conflict_point ctxt rollup staker other_staker in + match res with + | Ok (conflict_point, _) -> + let* conflict = + make_conflict ctxt rollup other_staker conflict_point + in + return (conflict :: conflicts) + | Error _ -> return conflicts) + [] + stakers + +let migrate_clean_refutation_games ctxt = + let open Lwt_result_syntax in + let remove_unstaked_games rollup = + List.fold_left_es + (fun ctxt (Sc_rollup_game_repr.Index.{alice; bob} as stakers) -> + let* ctxt, alice_active = + Sc_rollup_staker_index_storage.is_staker ctxt rollup alice + in + let* ctxt, bob_active = + Sc_rollup_staker_index_storage.is_staker ctxt rollup bob + in + if (not alice_active) && not bob_active then + remove_game ctxt rollup stakers + else return ctxt) + in + let* rollups = Sc_rollup_storage.list_unaccounted ctxt in + List.fold_left_es + (fun ctxt rollup -> + let*! players = + Storage.Sc_rollup.Game_info.keys_unaccounted (ctxt, rollup) + in + remove_unstaked_games rollup ctxt players) + ctxt + rollups diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.mli new file mode 100644 index 000000000000..99e320f2a62c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_refutation_storage.mli @@ -0,0 +1,220 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Commitment_hash = Sc_rollup_commitment_repr.Hash + +type point = { + commitment : Sc_rollup_commitment_repr.t; + hash : Commitment_hash.t; +} + +type conflict_point = point * point + +(** [get_ongoing_games_for_staker ctxt rollup staker] returns [games], + the list of refutation games currently played by [staker] in the + [rollup]. *) +val get_ongoing_games_for_staker : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + ((Sc_rollup_game_repr.t * Sc_rollup_game_repr.Index.t) list * Raw_context.t) + tzresult + Lwt.t + +(** [get_game ctxt rollup stakers] returns the [game] between + [stakers.alice] and [stakers.bob]. *) +val find_game : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_game_repr.Index.t -> + (Raw_context.t * Sc_rollup_game_repr.t option) tzresult Lwt.t + +(** A conflict between a staker and an [other] staker. The conflict is + about the commitment that follows the [parent_commitment]: + [their_commitment] and [our_commitment] are distinct, hence in + conflict. *) +type conflict = { + other : Sc_rollup_repr.Staker.t; + their_commitment : Sc_rollup_commitment_repr.t; + our_commitment : Sc_rollup_commitment_repr.t; + parent_commitment : Sc_rollup_commitment_repr.Hash.t; +} + +val conflict_encoding : conflict Data_encoding.t + +(** [conflicting_stakers_uncarbonated rollup staker] returns the list + of conflicts with [staker] in [rollup]. + + Notice that this operation can be expensive as it is proportional + to the number of stakers multiplied by the number of commitments in + the staked branches. Fortunately, this operation is only useful as + an RPC for the rollup node to look for a new conflict to solve. *) +val conflicting_stakers_uncarbonated : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + conflict list tzresult Lwt.t + +(** [start_game ctxt rollup ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash)] initiates a refutation game + between [player] and [opponent] in the given [rollup] as they are in + conflict with [commitment] and [opponent_commitment]. Where [commitment] is + the commitment in the storage with hash [player_commitment_hash] + (resp. [opponent_commitment] with [opponent_commitment_hash]). *) +val start_game : + Raw_context.t -> + Sc_rollup_repr.t -> + player:Signature.public_key_hash * Sc_rollup_commitment_repr.Hash.t -> + opponent:Signature.public_key_hash * Sc_rollup_commitment_repr.Hash.t -> + Raw_context.t tzresult Lwt.t + +(** [game_move ctxt rollup player opponent refutation] + handles the storage-side logic for when one of the players makes a + move in the game. It checks the game already exists. Then it checks + that [player] is the player whose turn it is; if so, it applies + [refutation] using the [play] function. + + If the result is a new game, this is stored and the timeout is updated. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_no_game] if [is_opening_move] is [false] but the + game does not exist} + {li [Sc_rollup_game_already_started] if [is_opening_move] is [true] + but the game already exists} + {li [Sc_rollup_no_conflict] if [player] is staked on an ancestor of + the commitment staked on by [opponent], or vice versa} + {li [Sc_rollup_not_staked] if one of the [player] or [opponent] is + not actually staked} + {li [Sc_rollup_staker_in_game] if one of the [player] or [opponent] + is already playing a game} + {li [Sc_rollup_wrong_turn] if a player is trying to move out of + turn} + } + + The [is_opening_move] argument is included here to make sure that an + operation intended to start a refutation game is never mistaken for + an operation to play the second move of the game---this may + otherwise happen due to non-deterministic ordering of L1 operations. + With the [is_opening_move] parameter, the worst case is that the + operation simply fails. Without it, the operation would be mistaken + for an invalid move in the game and the staker would lose their + stake! *) +val game_move : + Raw_context.t -> + Sc_rollup_repr.t -> + player:Sc_rollup_repr.Staker.t -> + opponent:Sc_rollup_repr.Staker.t -> + step:Sc_rollup_game_repr.step -> + choice:Sc_rollup_tick_repr.t -> + (Sc_rollup_game_repr.game_result option * Raw_context.t) tzresult Lwt.t + +(** [timeout ctxt rollup stakers] checks that the timeout has + elapsed and if this function returns a game result that punishes whichever + of [stakers] is supposed to have played a move. + + The timeout period is defined a protocol constant, see + {!Constants_storage.sc_rollup_timeout_period_in_blocks}. + + May fail with: + {ul + {li [Sc_rollup_no_game] if the game does not in fact exist} + {li [Sc_rollup_timeout_level_not_reached] if the player still has + time in which to play} + } + + Note: this function takes the two stakers as a pair rather than + separate arguments. This reflects the fact that for this function + the two players are symmetric. This function will normalize the + order of the players if necessary to get a valid game index, so the + argument [stakers] doesn't have to be in normal form. *) +val timeout : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_game_repr.Index.t -> + (Sc_rollup_game_repr.game_result * Raw_context.t) tzresult Lwt.t + +(** [get_timeout ctxt rollup stakers] returns the current timeout values of both + players. *) +val get_timeout : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_game_repr.Index.t -> + (Sc_rollup_game_repr.timeout * Raw_context.t) tzresult Lwt.t + +(** [apply_game_result ctxt rollup game_result] takes a [game_result] produced + by [timeout] or [game_move] and performs the necessary end-of-game + cleanup: remove the game itself from the store and punish the losing + player by removing their stake. In the case where the game ended in + a draw, both players are slashed. + + This is mostly just calling [remove_staker], so it can fail with the + same errors as that. However, if it is called on an [game_result] + generated by [game_move] or [timeout] it should not fail. + + Note: this function takes the two stakers as a pair rather than + separate arguments. This reflects the fact that for this function + the two players are symmetric. This function will normalize the + order of the players if necessary to get a valid game index, so the + argument [stakers] doesn't have to be in normal form. *) +val apply_game_result : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_game_repr.Index.t -> + Sc_rollup_game_repr.game_result -> + (Sc_rollup_game_repr.status * Raw_context.t * Receipt_repr.balance_updates) + tzresult + Lwt.t + +(** Removes pending refutation games in the context where the players + are no longer staked. *) +val migrate_clean_refutation_games : + Raw_context.t -> Raw_context.t tzresult Lwt.t + +(**/**) + +module Internal_for_tests : sig + (** [get_conflict_point context rollup staker1 staker2] returns the + first point of disagreement between the [staker1] and the + [staker2] + The returned commitments are distinct, and have the same [parent] + commitment; hence the same inbox level. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist} + {li [Sc_rollup_no_conflict] if [staker1] is staked on an ancestor of the + commitment staked on by [staker2], or vice versa} + {li [Sc_rollup_not_staked] if one of the stakers is not staked} + } *) + val get_conflict_point : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Sc_rollup_repr.Staker.t -> + (conflict_point * Raw_context.t) tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.ml new file mode 100644 index 000000000000..9dae54444251 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.ml @@ -0,0 +1,108 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2022 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Address = struct + include Smart_rollup.Address + + let prefix = "sr1" + + let () = Base58.check_encoded_prefix b58check_encoding prefix 36 + + let of_b58data = function Smart_rollup.Address.Data h -> Some h | _ -> None +end + +module Internal_for_tests = struct + let originated_sc_rollup nonce = + let data = + Data_encoding.Binary.to_bytes_exn Origination_nonce.encoding nonce + in + Address.hash_bytes [data] +end + +module State_hash = Smart_rollup.State_hash + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/5506 + Remove type and module aliases for Smart_rollup.Address. *) + +type t = Address.t + +let pp = Address.pp + +let encoding = Address.encoding + +let rpc_arg = Address.rpc_arg + +let in_memory_size (_ : t) = + let open Cache_memory_helpers in + h1w +! string_size_gen Address.size + +module Staker = struct + include Signature.Public_key_hash + + let rpc_arg_staker1 = + RPC_arg.like rpc_arg ?descr:(RPC_arg.descr rpc_arg).descr "staker1_pkh" + + let rpc_arg_staker2 = + RPC_arg.like rpc_arg ?descr:(RPC_arg.descr rpc_arg).descr "staker2_pkh" +end + +module Index = struct + type t = Address.t + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + Option.bind + (Hex.to_bytes (`Hex key)) + (Data_encoding.Binary.of_bytes_opt encoding) + | _ -> None + + let rpc_arg = rpc_arg + + let encoding = encoding + + let compare = Address.compare +end + +module Number_of_ticks = struct + include Bounded.Int64 (struct + let min_value = 0L + + let max_value = Int64.max_int + end) + + let zero = + match of_value 0L with + | Some zero -> zero + | None -> assert false (* unreachable case, since [min_int = 0l] *) +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.mli new file mode 100644 index 000000000000..d4d6aa0dcbfb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_repr.mli @@ -0,0 +1,102 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The basic components of an optimistic rollup for smart-contracts. *) + +(** + + An optimistic rollup for smart-contracts is made of two main + components: + + - a proof generating virtual machine (PVM), which provides the + essential semantics for the rollup operations to be validated by + the layer 1 in case of dispute about a commitment ; + + - a database which maintains the cemented operations of the rollup + as well as the potentially-disputed operations. + +*) + +(** A smart rollup has an address starting with "sr1". *) +module Address : sig + include module type of struct + include Smart_rollup.Address + end + + val of_b58data : Base58.data -> t option + + (** Prefix of smart rollup addresses in base58-check. *) + val prefix : string +end + +module Internal_for_tests : sig + val originated_sc_rollup : Origination_nonce.t -> Address.t +end + +module State_hash : module type of struct + include Smart_rollup.State_hash +end + +(** Number of ticks computed by a single commitment. This represents a claim + about the state of the PVM, which can be disputed as part of a commitment + dispute. + + See also {!Commitment_repr}. *) +module Number_of_ticks : sig + include Bounded.S with type ocaml_type := int64 + + val zero : t +end + +(** A smart contract rollup is identified by its address. *) +type t = Address.t + +val encoding : t Data_encoding.t + +val rpc_arg : t RPC_arg.t + +val pp : Format.formatter -> t -> unit + +(** [in_memory_size sc_rollup] returns the number of bytes [sc_rollup] + uses in RAM. *) +val in_memory_size : t -> Cache_memory_helpers.sint + +(** A [Staker] is an implicit account, identified by its public key hash. *) +module Staker : sig + include S.SIGNATURE_PUBLIC_KEY_HASH with type t = Signature.Public_key_hash.t + + (** Classic RPC argument with name ["pkh"]. *) + val rpc_arg : t RPC_arg.t + + (** RPC argument with name ["staker1_pkh"]. *) + val rpc_arg_staker1 : t RPC_arg.t + + (** RPC argument with name ["staker2_pkh"]. *) + val rpc_arg_staker2 : t RPC_arg.t +end + +(** The data model uses an index of these addresses. *) +module Index : Storage_description.INDEX with type t = Address.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.ml new file mode 100644 index 000000000000..1e4d6b51ca44 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.ml @@ -0,0 +1,133 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Reserve the first byte in the encoding to support multi-versioning + in the future. *) +module Blake2B = struct + include + Blake2B.Make + (Base58) + (struct + let name = "Smart_rollup_reveal_data_blake2b_hash" + + let title = "A smart rollup reveal hash" + + let b58check_prefix = + "\230\206\128\200\196" (* "scrrh1(56)" decoded from Base58. *) + + let size = Some 32 + end) + + let () = Base58.check_encoded_prefix b58check_encoding "scrrh1" 56 +end + +type supported_hashes = Blake2B + +type t = Blake2B of Blake2B.t + +let zero ~(scheme : supported_hashes) = + match scheme with Blake2B -> Blake2B Blake2B.zero + +let pp ppf hash = match hash with Blake2B hash -> Blake2B.pp ppf hash + +let equal h1 h2 = + match (h1, h2) with Blake2B h1, Blake2B h2 -> Blake2B.equal h1 h2 + +let compare h1 h2 = + match (h1, h2) with Blake2B h1, Blake2B h2 -> Blake2B.compare h1 h2 + +module Map = Map.Make (struct + type tmp = t + + type t = tmp + + let compare = compare +end) + +(* Size of the hash is the size of the inner hash plus one byte for the + tag used to identify the hashing scheme. *) +let size ~(scheme : supported_hashes) = + let tag_size = 1 in + let size_without_tag = match scheme with Blake2B -> Blake2B.size in + tag_size + size_without_tag + +let encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Reveal_data_hash_v0" + (Tag 0) + Blake2B.encoding + (fun (Blake2B s) -> Some s) + (fun s -> Blake2B s); + ] + +let hash_string ~(scheme : supported_hashes) ?key strings = + match scheme with Blake2B -> Blake2B (Blake2B.hash_string ?key strings) + +let hash_bytes ~(scheme : supported_hashes) ?key bytes = + match scheme with Blake2B -> Blake2B (Blake2B.hash_bytes ?key bytes) + +let scheme_of_hash hash = + match hash with Blake2B _hash -> (Blake2B : supported_hashes) + +let to_hex hash = + let (`Hex hash) = + (* The [encoding] of a hash here never, so [to_string_exn] is safe. *) + Hex.of_string @@ Data_encoding.Binary.to_string_exn encoding hash + in + hash + +let of_hex hex = + let open Option_syntax in + let* hash = Hex.to_bytes (`Hex hex) in + Data_encoding.Binary.of_bytes_opt encoding hash + +let rpc_arg = + let construct = to_hex in + let destruct hash = + match of_hex hash with + | None -> Error "Cannot parse reveal hash" + | Some reveal_hash -> Ok reveal_hash + in + RPC_arg.make + ~descr:"A reveal hash" + ~name:"reveal_hash" + ~destruct + ~construct + () + +(** The preimage of {!well_known_reveal_hash}. *) +let well_known_reveal_preimage = "" + +(** The hash requested by the WASM PVM if it cannot decode the input + provided by the WASM kernel, that is, if the bytes value cannot + be decoded with {!Sc_rollup_reveal_hash.encoding}. *) +let well_known_reveal_hash = + hash_string ~scheme:Blake2B [well_known_reveal_preimage] diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.mli new file mode 100644 index 000000000000..5b882f06c5fb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_reveal_hash.mli @@ -0,0 +1,91 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2023 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The type of a reveal hash. *) +type t + +(** The hashing schemes supported by the reveal hash. *) +type supported_hashes = Blake2B + +(** A Map module for storing reveal-hash-indexed values. *) +module Map : Map.S with type key = t + +(** [size ~scheme] returns the size of reveal hashes using the [scheme] + specified in input. *) +val size : scheme:supported_hashes -> int + +(** [zero ~scheme] returns the reveal hash corresponding to the zero hash + for the [scheme] specified in input. *) +val zero : scheme:supported_hashes -> t + +(** Formatting function for reveal-hashes. *) +val pp : Format.formatter -> t -> unit + +(** [equal hash1 hash2] checks if the two reveal-hashes [hash1] and [hash2] + are equal. This function must preserve the equality of individual + supported hashing schemes. If [hash1] and [hash2] are hashes obtained + from the same supported hashing scheme, then the [equal] function from + that hashing scheme is used to determine whether they are equivalent. + Otherwise, they are different. *) +val equal : t -> t -> bool + +(** [compare hash1 hash2] compares the values of the reveal hashes [hash1] + and [hash2]. This function must preserve the ordering of individual + supported hashing scheme. If [hash1] and [hash2] are reveal-hashes + obtained from the same hashing scheme, then [compare hash1 hash2] + should return the same result of the compare function exposed + by the hash module corresponding to their hashing scheme. *) +val compare : t -> t -> int + +(** The encoding of reveal hashes. *) +val encoding : t Data_encoding.t + +(** [hash_string ~scheme ?key strings] hashes [strings] using the + supported hashing [scheme] given in input. *) +val hash_string : scheme:supported_hashes -> ?key:string -> string list -> t + +(** [hash_bytes ~scheme ?key strings] hashes [bytes] using the + supported hashing [scheme] given in input. *) +val hash_bytes : scheme:supported_hashes -> ?key:bytes -> bytes list -> t + +(** [scheme_of_hash] hash returns the supported hashing scheme + that was used to obtain [hash]. *) +val scheme_of_hash : t -> supported_hashes + +val of_hex : string -> t option + +val to_hex : t -> string + +val rpc_arg : t RPC_arg.t + +(** The hash requested by the WASM PVM if it cannot decode the input + provided by the WASM kernel, that is, if the bytes value cannot + be decoded with {!val:encoding}. *) +val well_known_reveal_hash : t + +(** The preimage of {!well_known_reveal_hash}. *) +val well_known_reveal_preimage : string diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.ml new file mode 100644 index 000000000000..14490b1b993d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.ml @@ -0,0 +1,136 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(*****************************************************************************) + +open Sc_rollup_repr +module PS = Sc_rollup_PVM_sig + +(* [void] definition from [Sc_rollup_machine_no_proofs] *) +type void = | + +let void = + Data_encoding.( + conv_with_guard + (function (_ : void) -> .) + (fun _ -> Error "void has no inhabitant") + unit) + +type minimal_state = { + payload : string; + level : Raw_level_repr.t option; + message_counter : Z.t; + tick : Z.t; +} + +let minimal_state_encoding = + let open Data_encoding in + conv + (fun {payload; level; message_counter; tick} -> + (payload, level, message_counter, tick)) + (fun (payload, level, message_counter, tick) -> + {payload; level; message_counter; tick}) + @@ obj4 + (req "payload" (string Hex)) + (req "level" (option Raw_level_repr.encoding)) + (req "message_counter" n) + (req "tick" n) + +let make_empty_state () = + {payload = ""; level = None; message_counter = Z.zero; tick = Z.zero} + +let state_hash state = + [Data_encoding.Binary.to_bytes_exn minimal_state_encoding state] + |> Context_hash.hash_bytes |> State_hash.context_hash_to_state_hash + +module type S = sig + include PS.S + + val parse_boot_sector : string -> string option + + val pp_boot_sector : Format.formatter -> string -> unit +end + +module Protocol_implementation : + S + with type context = unit + and type state = minimal_state + and type proof = void = struct + let pp state = + Lwt.return @@ fun fmt () -> Format.pp_print_string fmt state.payload + + type state = minimal_state + + type context = unit + + type hash = State_hash.t + + type proof = void + + let proof_encoding = void + + let proof_start_state = function (_ : proof) -> . + + let proof_stop_state = function (_ : proof) -> . + + let state_hash state = Lwt.return (state_hash state) + + let initial_state ~empty = Lwt.return empty + + let install_boot_sector state boot_sector = + Lwt.return {state with payload = boot_sector} + + let is_input_state ~is_reveal_enabled:_ state = + Lwt.return + @@ + match state.level with + | None -> PS.Initial + | Some level -> PS.First_after (level, state.message_counter) + + let set_input input state = + Lwt.return + @@ + match input with + | PS.Inbox_message {inbox_level; message_counter; payload} -> + { + payload = Sc_rollup_inbox_message_repr.unsafe_to_string payload; + level = Some inbox_level; + message_counter; + tick = Z.succ state.tick; + } + | PS.Reveal _s -> assert false + + let eval state = Lwt.return {state with tick = Z.succ state.tick} + + let verify_proof ~is_reveal_enabled:_ _input = function (_ : proof) -> . + + let produce_proof _context ~is_reveal_enabled:_ _state _step = assert false + + type output_proof = void + + let output_proof_encoding = void + + let output_of_output_proof = function (_ : proof) -> . + + let state_of_output_proof = function (_ : proof) -> . + + let verify_output_proof = function (_ : proof) -> . + + let produce_output_proof _context _state _output = assert false + + let check_dissection ~default_number_of_sections:_ ~start_chunk:_ + ~stop_chunk:_ = + assert false + + let get_current_level {level; _} = Lwt.return level + + let parse_boot_sector s = Some s + + let pp_boot_sector fmt s = Format.fprintf fmt "%s" s + + module Internal_for_tests = struct + let insert_failure _state = assert false + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.mli new file mode 100644 index 000000000000..1116a7650e90 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_riscv.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(*****************************************************************************) + +type void = | + +type minimal_state = { + payload : string; + level : Raw_level_repr.t option; + message_counter : Z.t; + tick : Z.t; +} + +(* This encoding is used in the rollup node when embedding the state into an Irmin context. *) +val minimal_state_encoding : minimal_state Data_encoding.t + +val make_empty_state : unit -> minimal_state + +module type S = sig + include Sc_rollup_PVM_sig.S + + val parse_boot_sector : string -> string option + + val pp_boot_sector : Format.formatter -> string -> unit +end + +module Protocol_implementation : + S + with type context = unit + and type state = minimal_state + and type proof = void diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml new file mode 100644 index 000000000000..c25546aecb46 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml @@ -0,0 +1,829 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_errors +module Store = Storage.Sc_rollup +module Commitment_storage = Sc_rollup_commitment_storage +module Commitment = Sc_rollup_commitment_repr +module Commitment_hash = Commitment.Hash + +(** As the sets encoded with a list are proportional to the number of + stakers on the rollup, we admit that it will be a small set. We + also admit that a small list respecting the set properties is more + efficient than using a real {!Set.S}. *) +module Set_out_of_list (S : sig + type t := Raw_context.t * Sc_rollup_repr.t + + type key + + type value + + val equal_value : value -> value -> bool + + val find : t -> key -> (Raw_context.t * value list option) tzresult Lwt.t + + val add : + t -> key -> value list -> (Raw_context.t * int * bool) tzresult Lwt.t + + val remove : t -> key -> (Raw_context.t * int) tzresult Lwt.t +end) = +struct + let find ctxt rollup key = S.find (ctxt, rollup) key + + let get ctxt rollup key = + let open Lwt_result_syntax in + let* ctxt, values_opt = find ctxt rollup key in + return (ctxt, Option.value ~default:[] values_opt) + + let remove ctxt rollup key = S.remove (ctxt, rollup) key + + let mem ctxt rollup key value = + let open Lwt_result_syntax in + let* ctxt, values = get ctxt rollup key in + let exists = List.mem ~equal:S.equal_value value values in + return (ctxt, exists) + + let add ctxt rollup key value = + let open Lwt_result_syntax in + let* ctxt, existing_values = get ctxt rollup key in + let exists = List.mem ~equal:S.equal_value value existing_values in + if exists then return (ctxt, 0, existing_values) + else + let values = value :: existing_values in + let* ctxt, diff_size, _existed = S.add (ctxt, rollup) key values in + return (ctxt, diff_size, values) +end + +module Commitments_per_inbox_level = Set_out_of_list (struct + type key = Raw_level_repr.t + + type value = Commitment_hash.t + + let equal_value = Commitment_hash.equal + + let find = Store.Commitments_per_inbox_level.find + + let add = Store.Commitments_per_inbox_level.add + + let remove = Store.Commitments_per_inbox_level.remove_existing +end) + +module Commitment_stakers = Set_out_of_list (struct + type key = Commitment_hash.t + + type value = Sc_rollup_staker_index_repr.t + + let equal_value = Sc_rollup_staker_index_repr.equal + + let find = Store.Commitment_stakers.find + + let add = Store.Commitment_stakers.add + + let remove = Store.Commitment_stakers.remove_existing +end) + +(* Looks for the commitment [staker] is staking on, in the list of commitments + posted for this level. *) +let rec find_commitment_of_staker_in_commitments ctxt rollup staker_index = + let open Lwt_result_syntax in + function + | [] -> return (ctxt, None) + | commitment_hash :: rst -> + let* ctxt, exists = + Commitment_stakers.mem ctxt rollup commitment_hash staker_index + in + if exists then return (ctxt, Some commitment_hash) + else find_commitment_of_staker_in_commitments ctxt rollup staker_index rst + +let get_commitment_of_staker_in_commitments ctxt rollup staker_index commitments + = + let open Lwt_result_syntax in + let* ctxt, opt = + find_commitment_of_staker_in_commitments + ctxt + rollup + staker_index + commitments + in + match opt with + | Some res -> return (ctxt, res) + | None -> tzfail Sc_rollup_not_staked + +let find_staker ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, staker_index = + Sc_rollup_staker_index_storage.get_staker_index_unsafe ctxt rollup staker + in + let* ctxt, level = Store.Stakers.get (ctxt, rollup) staker_index in + let* ctxt, commitments_opt = + Commitments_per_inbox_level.find ctxt rollup level + in + match commitments_opt with + | None -> + (* The staked commitment is no longer active (i.e. cemented). *) + return (ctxt, None) + | Some commitments -> + let+ ctxt, commitment_hash = + get_commitment_of_staker_in_commitments + ctxt + rollup + staker_index + commitments + in + (ctxt, Some commitment_hash) + +let commitments_uncarbonated ctxt ~rollup ~inbox_level = + let open Lwt_result_syntax in + let* _, commitments = + Commitments_per_inbox_level.find ctxt rollup inbox_level + in + return commitments + +let stakers_ids_uncarbonated ctxt ~rollup ~commitment = + let open Lwt_result_syntax in + let* _, stakers_ids = + Store.Commitment_stakers.get (ctxt, rollup) commitment + in + return stakers_ids + +let staker_id_uncarbonated ctxt ~rollup ~pkh = + let open Lwt_result_syntax in + let* _, staker_index = Store.Staker_index.get (ctxt, rollup) pkh in + return staker_index + +let stakers_pkhs_uncarbonated ctxt ~rollup = + Sc_rollup_staker_index_storage.list_stakers_uncarbonated ctxt rollup + +let get_contract_and_stake ctxt staker = + let staker_contract = Contract_repr.Implicit staker in + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + (staker_contract, stake) + +(** [assert_staked_on_lcc_or_ancestor ctxt rollup ~staker_index lcc_inbox_level] + fails unless the most recent commitment [staker_index] has staked + is older than [lcc_inbox_level]. This is a necessary condition to + withdraw a staker's bond. *) +let assert_staked_on_lcc_or_ancestor ctxt rollup ~staker_index lcc_inbox_level = + let open Lwt_result_syntax in + let* ctxt, last_staked_level = + Store.Stakers.get (ctxt, rollup) staker_index + in + let* () = + fail_unless + Raw_level_repr.(last_staked_level <= lcc_inbox_level) + Sc_rollup_not_staked_on_lcc_or_ancestor + in + return ctxt + +let deposit_stake ctxt rollup staker = + let open Lwt_result_syntax in + (* Freeze the stake of [staker]. *) + let staker_contract, stake = get_contract_and_stake ctxt staker in + let* ctxt, staker_balance = + Contract_storage.get_balance_carbonated ctxt staker_contract + in + let bond_id = Bond_id_repr.Sc_rollup_bond_id rollup in + let* ctxt, balance_updates = + trace + (Sc_rollup_staker_funds_too_low + { + staker; + sc_rollup = rollup; + staker_balance; + min_expected_balance = stake; + }) + @@ Token.transfer + ctxt + (`Contract staker_contract) + (`Frozen_bonds (staker_contract, bond_id)) + stake + in + (* Initialize the index of [staker]. *) + let* ctxt, staker_index = + Sc_rollup_staker_index_storage.fresh_staker_index ctxt rollup staker + in + return (ctxt, balance_updates, staker_index) + +let withdraw_stake ctxt rollup staker = + let open Lwt_result_syntax in + let* _lcc, lcc_inbox_level, ctxt = + Commitment_storage.last_cemented_commitment_hash_with_level ctxt rollup + in + let* ctxt, staker_index = + Sc_rollup_staker_index_storage.get_staker_index_unsafe ctxt rollup staker + in + let* ctxt = + assert_staked_on_lcc_or_ancestor ctxt rollup ~staker_index lcc_inbox_level + in + let staker_contract, stake = get_contract_and_stake ctxt staker in + let bond_id = Bond_id_repr.Sc_rollup_bond_id rollup in + let* ctxt, balance_updates = + Token.transfer + ctxt + (`Frozen_bonds (staker_contract, bond_id)) + (`Contract staker_contract) + stake + in + let* ctxt = Sc_rollup_staker_index_storage.remove_staker ctxt rollup staker in + return (ctxt, balance_updates) + +let assert_commitment_not_too_far_ahead ctxt rollup lcc commitment = + let open Lwt_result_syntax in + let* lcc, ctxt = Commitment_storage.get_commitment_unsafe ctxt rollup lcc in + let min_level = Commitment.(lcc.inbox_level) in + let max_level = Commitment.(commitment.inbox_level) in + let sc_rollup_max_lookahead = + Constants_storage.sc_rollup_max_lookahead_in_blocks ctxt + in + let* () = + fail_when + Compare.Int32.( + sc_rollup_max_lookahead < Raw_level_repr.diff max_level min_level) + Sc_rollup_too_far_ahead + in + return ctxt + +(** Enfore that a commitment's inbox level increases by an exact fixed + amount over its predecessor. This property is used in several + places - not obeying it causes severe breakage. *) +let assert_commitment_period ctxt rollup commitment = + let open Lwt_result_syntax in + let pred_hash = Commitment.(commitment.predecessor) in + let* pred, ctxt = + Commitment_storage.get_commitment_unsafe ctxt rollup pred_hash + in + let pred_level = Commitment.(pred.inbox_level) in + (* Commitments needs to be posted for inbox levels every [commitment_period]. + Therefore, [commitment.inbox_level] must be + [predecessor_commitment.inbox_level + commitment_period]. *) + let sc_rollup_commitment_period = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + let* () = + fail_unless + Raw_level_repr.( + commitment.inbox_level = add pred_level sc_rollup_commitment_period) + Sc_rollup_bad_inbox_level + in + return ctxt + +(** [assert_commitment_is_not_past_curfew ctxt rollup inbox_level] + will look in the storage [Commitment_first_publication_level] for + the level of the oldest commit for [inbox_level] and if it is more + than [sc_rollup_challenge_window_in_blocks] ago it fails with + [Sc_rollup_commitment_past_curfew]. Otherwise it adds the + respective storage (if it is not set) and returns the context. *) +let assert_commitment_is_not_past_curfew ctxt rollup inbox_level = + let open Lwt_result_syntax in + let current_level = (Raw_context.current_level ctxt).level in + let* ctxt, oldest_commit = + Store.Commitment_first_publication_level.find (ctxt, rollup) inbox_level + in + match oldest_commit with + | Some oldest_commit -> + let refutation_deadline_blocks = + Int32.of_int + @@ Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let+ () = + fail_when + Compare.Int32.( + Raw_level_repr.diff current_level oldest_commit + > refutation_deadline_blocks) + Sc_rollup_commitment_past_curfew + in + (ctxt, 0) + | None -> + (* The storage cost is covered by the stake. *) + let* ctxt, size_diff, _existed = + Store.Commitment_first_publication_level.add + (ctxt, rollup) + inbox_level + current_level + in + return (ctxt, size_diff) + +(** Check invariants on [inbox_level], enforcing overallocation of storage, + regularity of block production and curfew. + + The constants used by [assert_refine_conditions_met] must be chosen such + that the maximum cost of storage allocated by each staker is at most the size + of their deposit. + *) +let assert_refine_conditions_met ~current_level ~lcc_inbox_level ctxt rollup lcc + commitment = + let open Lwt_result_syntax in + let commitment_inbox_level = commitment.Commitment.inbox_level in + let* () = + fail_unless + Raw_level_repr.(commitment_inbox_level > lcc_inbox_level) + (Sc_rollup_commitment_too_old + {last_cemented_inbox_level = lcc_inbox_level; commitment_inbox_level}) + in + let* ctxt = assert_commitment_not_too_far_ahead ctxt rollup lcc commitment in + let* ctxt = assert_commitment_period ctxt rollup commitment in + let* ctxt, size_diff = + assert_commitment_is_not_past_curfew + ctxt + rollup + Commitment.(commitment.inbox_level) + in + let* () = + fail_unless + Raw_level_repr.(commitment_inbox_level < current_level) + (Sc_rollup_commitment_from_future + {current_level; inbox_level = commitment.inbox_level}) + in + return (ctxt, size_diff) + +let is_staked_on ctxt rollup staker commitment_hash = + let open Lwt_result_syntax in + let* ctxt, staker_index_opt = + Sc_rollup_staker_index_storage.find_staker_index_unsafe ctxt rollup staker + in + match staker_index_opt with + | None -> return (ctxt, false) + | Some staker_index -> + Commitment_stakers.mem ctxt rollup commitment_hash staker_index + +let deallocate_commitment_contents ctxt rollup commitment_hash = + let open Lwt_result_syntax in + let* ctxt, _size_freed = + Store.Commitments.remove_existing (ctxt, rollup) commitment_hash + in + return ctxt + +let deallocate_commitment_metadata ctxt rollup commitment_hash = + let open Lwt_result_syntax in + let* ctxt, _size_freed = + Store.Commitment_added.remove_existing (ctxt, rollup) commitment_hash + in + return ctxt + +let deallocate_commitment ctxt rollup commitment_hash = + let open Lwt_result_syntax in + let* ctxt = deallocate_commitment_metadata ctxt rollup commitment_hash in + deallocate_commitment_contents ctxt rollup commitment_hash + +let find_commitment_to_deallocate ctxt rollup commitment_hash = + let open Lwt_result_syntax in + (* The recursion is safe as long as [num_commitments_to_keep] remains + a small value. *) + let rec aux ctxt commitment_hash n = + if Compare.Int.(n = 0) then return (Some commitment_hash, ctxt) + else + let* pred_hash, ctxt = + Commitment_storage.get_predecessor_opt_unsafe + ctxt + rollup + commitment_hash + in + match pred_hash with + | None -> return (None, ctxt) + | Some pred_hash -> (aux [@ocaml.tailcall]) ctxt pred_hash (n - 1) + in + (* We must not remove the commitment itself as we need it to allow + executing outbox messages for a limited period. The maximum number of + active cemented commitments available for execution is specified in + [ctxt.sc_rollup.max_number_of_stored_cemented_commitments]. + Instead, we remove the oldest cemented commitment that would exceed + [max_number_of_cemented_commitments], if such exist. + + Decrease max_number_of_stored_cemented_commitments by one because + we start counting commitments from old_lcc, rather than from new_lcc. + *) + let num_commitments_to_keep = + (Raw_context.constants ctxt).sc_rollup + .max_number_of_stored_cemented_commitments - 1 + in + aux ctxt commitment_hash num_commitments_to_keep + +(* Maximum storage size in bytes allocated during a {!refine_stake}. + The first commitment of a inbox_level allocates the most bytes, + subsequent commitments for the same level may cost less (e.g. same + commitment published). + + We are looking to assert that the most possible bytes allocated in the + storage is covered by the deposit. + + Maximum value computed and observed: + - Commitment_first_publication_level: 4 + - Commitments: 77 + - Commitments_added: 4 + - Stakers: 4 + - Commitments_per_inbox_level: 36 + - Commitment_stakers is variable but should not exceed 10 bytes + + That is, 125 bytes are fixed. + + The variable comes from the {!Sc_rollup_staker_index.encoding}. Although, + the index of the 10^9-th stakers is 6 bytes, 10 bytes as an over-approxiamtion + should be fine (10 bytes also accounts for the list's overhead encoding). +*) +let max_commitment_storage_size_in_bytes = 125 + 10 + +(** [set_staker_commitment ctxt rollup staker_index inbox_level commitment_hash] + updates the **latest** commitment [staker_index] stakes on. + Adds [staker_index] to the set of stakers staking on [commitment_hash]. *) +let set_staker_commitment ctxt rollup staker_index inbox_level commitment_hash = + let open Lwt_result_syntax in + (* Update the latest commitment [staker_index] stakes on. *) + let* ctxt, size_diff_stakers = + let* ctxt, last_level = Store.Stakers.get (ctxt, rollup) staker_index in + if Raw_level_repr.(last_level < inbox_level) then + Store.Stakers.update (ctxt, rollup) staker_index inbox_level + else return (ctxt, 0) + in + (* Adds [staker_index] to the set of stakers staking on [commitment_hash]. *) + let* ctxt, size_diff_commitment_stakers, _stakers = + Commitment_stakers.add ctxt rollup commitment_hash staker_index + in + let* () = + (* Publishing the same commitment is not an issue. However, this causes + a bad UX as operators can publish twice by mistake and pay twice + the fees. *) + fail_when + Compare.Int.(size_diff_commitment_stakers = 0) + (Sc_rollup_double_publish commitment_hash) + in + return (ctxt, size_diff_stakers + size_diff_commitment_stakers) + +(** [assert_staker_dont_double_stake ctxt rollup staker_index commitments] + asserts that [staker_index] do not stake on multiple commitments in + [commitments]. *) +let assert_staker_dont_double_stake ctxt rollup staker_index commitments = + let open Lwt_result_syntax in + (* Compute the list of commitments [staker_index] stakes on. *) + let* ctxt, staked_on_commitments = + List.fold_left_es + (fun (ctxt, staked_on_commitments) commitment -> + let* ctxt, is_staked_on = + Commitment_stakers.mem ctxt rollup commitment staker_index + in + if is_staked_on then return (ctxt, commitment :: staked_on_commitments) + else return (ctxt, staked_on_commitments)) + (ctxt, []) + commitments + in + let* () = + fail_when + Compare.List_length_with.(staked_on_commitments > 1) + Sc_rollup_errors.Sc_rollup_staker_double_stake + in + return ctxt + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2559 + Add a test checking that L2 nodes can catch up after going offline. *) +let refine_stake ctxt rollup commitment ~staker_index ~lcc ~lcc_inbox_level = + let open Lwt_result_syntax in + let publication_level = (Raw_context.current_level ctxt).level in + (* Checks the commitment validity, see {!assert_refine_conditions_met}. *) + let* ctxt, refine_conditions_size_diff = + assert_refine_conditions_met + ctxt + rollup + lcc + commitment + ~current_level:publication_level + ~lcc_inbox_level + in + let*? ctxt, commitment_hash = + Sc_rollup_commitment_storage.hash ctxt commitment + in + (* Adds the commitment to the storage. *) + let* ctxt, commitment_size_diff, _commit_existed = + Store.Commitments.add (ctxt, rollup) commitment_hash commitment + in + (* Initializes or fetches the level at which the commitment was first + published. *) + let* commitment_added_size_diff, commitment_added_level, ctxt = + Commitment_storage.set_commitment_added + ctxt + rollup + commitment_hash + publication_level + in + (* Updates the [staker_index]'s metadata. *) + let* ctxt, set_staker_commitment_size_diff = + set_staker_commitment + ctxt + rollup + staker_index + commitment.inbox_level + commitment_hash + in + (* Adds the [commitment] to the set of commitments for this inbox level. *) + let* ctxt, commitments_per_inbox_level_size_diff, commitments = + Commitments_per_inbox_level.add + ctxt + rollup + commitment.inbox_level + commitment_hash + in + (* Checks that the staker is not double staking, done at the end to avoid + the double get to the list of commitments. *) + let* ctxt = + assert_staker_dont_double_stake ctxt rollup staker_index commitments + in + let total_size_diff = + refine_conditions_size_diff + commitment_size_diff + + commitment_added_size_diff + set_staker_commitment_size_diff + + commitments_per_inbox_level_size_diff + in + return (commitment_hash, commitment_added_level, ctxt, total_size_diff) + +let publish_commitment ctxt rollup staker commitment = + let open Lwt_result_syntax in + let* ctxt = + if Constants_storage.sc_rollup_private_enable ctxt then + Sc_rollup_whitelist_storage.check_access_to_private_rollup + ctxt + rollup + staker + else return ctxt + in + let* lcc, lcc_inbox_level, ctxt = + Commitment_storage.last_cemented_commitment_hash_with_level ctxt rollup + in + let* () = + fail_when + Sc_rollup_repr.Number_of_ticks.( + commitment.Commitment.number_of_ticks = zero) + Sc_rollup_zero_tick_commitment + in + let* ctxt, staker_index_opt = + Sc_rollup_staker_index_storage.find_staker_index_unsafe ctxt rollup staker + in + (* If [staker] is an active staker, it has an index. *) + let* ctxt, balances_updates, staker_index = + match staker_index_opt with + | None -> deposit_stake ctxt rollup staker + | Some staker_index -> return (ctxt, [], staker_index) + in + let* commitment_hash, publication_level, ctxt, _size_diff = + refine_stake ctxt rollup ~staker_index commitment ~lcc ~lcc_inbox_level + in + return (commitment_hash, publication_level, ctxt, balances_updates) + +(** [active_stakers_index ctxt rollup stakers] filters [stakers] to return + only the active ones. *) +let active_stakers_index ctxt rollup stakers = + let open Lwt_result_syntax in + List.fold_left_es + (fun (ctxt, active_stakers_index) staker -> + let* ctxt, is_staker_active = + Sc_rollup_staker_index_storage.is_active ctxt rollup staker + in + if is_staker_active then return (ctxt, staker :: active_stakers_index) + else return (ctxt, active_stakers_index)) + (ctxt, []) + stakers + +let is_cementable_candidate_commitment ctxt rollup lcc commitment_hash = + let open Lwt_result_syntax in + let* commitment, ctxt = + Commitment_storage.get_commitment_unsafe ctxt rollup commitment_hash + in + if Commitment_hash.equal commitment.predecessor lcc then + let* ctxt, stakers_on_commitment = + Commitment_stakers.get ctxt rollup commitment_hash + in + let* ctxt, active_stakers_index = + active_stakers_index ctxt rollup stakers_on_commitment + in + (* The commitment is active if its predecessor is the LCC and + at least one active steaker has staked on it. *) + let commitment = + if Compare.List_length_with.(active_stakers_index > 0) then + Some commitment + else None + in + return (ctxt, commitment) + else (* Dangling commitment. *) + return (ctxt, None) + +let cementable_candidate_commitment_of_inbox_level ctxt rollup ~old_lcc + inbox_level = + let open Lwt_result_syntax in + let* ctxt, commitments = + Commitments_per_inbox_level.get ctxt rollup inbox_level + in + let rec collect_commitments ctxt candidate_commitment_res dangling_commitments + = function + | [] -> return (ctxt, candidate_commitment_res, dangling_commitments) + | candidate_commitment_hash :: rst -> ( + let* ctxt, candidate_commitment = + is_cementable_candidate_commitment + ctxt + rollup + old_lcc + candidate_commitment_hash + in + match (candidate_commitment, candidate_commitment_res) with + | Some _, Some _ -> + (* Second candidate commitment to cement, the inbox level is disputed. *) + tzfail Sc_rollup_disputed + | Some candidate_commitment, None -> + (* First candidate commitment to cement, it becomes the result. *) + collect_commitments + ctxt + (Some (candidate_commitment, candidate_commitment_hash)) + dangling_commitments + rst + | None, _ -> + collect_commitments + ctxt + candidate_commitment_res + (candidate_commitment_hash :: dangling_commitments) + rst) + in + collect_commitments ctxt None [] commitments + +(** [find_commitment_to_cement ctxt rollup ~old_lcc new_lcc_level] tries to find + the commitment to cement at inbox level [new_lcc_level]. + + A commitment can be cemented if: + {ol + {li The commitment's predecessor is the LCC.} + {li The challenge window period is over.} + {li The commitment is the only active commitment.} + } +*) +let find_commitment_to_cement ctxt rollup ~old_lcc new_lcc_level = + let open Lwt_result_syntax in + (* Checks that the commitment is the only active commitment. *) + let* ctxt, candidate_commitment, dangling_commitments = + cementable_candidate_commitment_of_inbox_level + ctxt + rollup + ~old_lcc + new_lcc_level + in + match candidate_commitment with + (* A commitment can be cemented if there is only one valid + commitment. *) + | Some (candidate_commitment, candidate_commitment_hash) -> + let* ctxt, candidate_commitment_added = + Store.Commitment_added.get (ctxt, rollup) candidate_commitment_hash + in + (* Checks that the commitment is past the challenge window. *) + let* () = + let challenge_windows_in_blocks = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let current_level = (Raw_context.current_level ctxt).level in + let min_level = + Raw_level_repr.add + candidate_commitment_added + challenge_windows_in_blocks + in + fail_when + Raw_level_repr.(current_level < min_level) + (Sc_rollup_commitment_too_recent {current_level; min_level}) + in + return + ( ctxt, + (candidate_commitment, candidate_commitment_hash), + dangling_commitments ) + | None -> tzfail Sc_rollup_no_valid_commitment_to_cement + +let deallocate_inbox_level ctxt rollup inbox_level new_lcc_hash + dangling_commitments = + let open Lwt_result_syntax in + let* ctxt, _size_diff = + Commitments_per_inbox_level.remove ctxt rollup inbox_level + in + let* ctxt = + List.fold_left_es + (fun ctxt commitment -> deallocate_commitment ctxt rollup commitment) + ctxt + dangling_commitments + in + let* ctxt = + List.fold_left_es + (fun ctxt commitment -> + let* ctxt, _freed_size = + Commitment_stakers.remove ctxt rollup commitment + in + return ctxt) + ctxt + (new_lcc_hash :: dangling_commitments) + in + let* ctxt = deallocate_commitment_metadata ctxt rollup new_lcc_hash in + let* ctxt, _size_freed = + Store.Commitment_first_publication_level.remove_existing + (ctxt, rollup) + inbox_level + in + return ctxt + +let update_saved_cemented_commitments ctxt rollup old_lcc = + let open Lwt_result_syntax in + let* too_old_cemented_commitment_hash_opt, ctxt = + find_commitment_to_deallocate ctxt rollup old_lcc + in + match too_old_cemented_commitment_hash_opt with + | None -> return ctxt + | Some too_old_cemented_commitment_hash -> + if Commitment_hash.(equal too_old_cemented_commitment_hash zero) then + return ctxt + else + deallocate_commitment_contents + ctxt + rollup + too_old_cemented_commitment_hash + +let cement_commitment ctxt rollup = + let open Lwt_result_syntax in + let* old_lcc, old_lcc_level, ctxt = + Commitment_storage.last_cemented_commitment_hash_with_level ctxt rollup + in + let sc_rollup_commitment_period = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + let new_lcc_level = + Raw_level_repr.add old_lcc_level sc_rollup_commitment_period + in + (* Assert conditions to cement are met. *) + let* ctxt, (new_lcc_commitment, new_lcc_commitment_hash), dangling_commitments + = + find_commitment_to_cement ctxt rollup ~old_lcc new_lcc_level + in + (* Update the LCC. *) + let* ctxt, _size_diff = + Store.Last_cemented_commitment.update ctxt rollup new_lcc_commitment_hash + in + (* Clean the storage. *) + let* ctxt = + deallocate_inbox_level + ctxt + rollup + new_lcc_commitment.inbox_level + new_lcc_commitment_hash + dangling_commitments + in + (* Update the saved cemented commitments. *) + let* ctxt = update_saved_cemented_commitments ctxt rollup old_lcc in + return (ctxt, new_lcc_commitment, new_lcc_commitment_hash) + +let remove_staker ctxt rollup staker = + let open Lwt_result_syntax in + let staker_contract, stake = get_contract_and_stake ctxt staker in + let bond_id = Bond_id_repr.Sc_rollup_bond_id rollup in + let* ctxt, balance_updates = + Token.transfer + ctxt + (`Frozen_bonds (staker_contract, bond_id)) + `Sc_rollup_refutation_punishments + stake + in + let* ctxt = Sc_rollup_staker_index_storage.remove_staker ctxt rollup staker in + return (ctxt, balance_updates) + +let commitments_of_inbox_level = Commitments_per_inbox_level.get + +let stakers_of_commitment = Commitment_stakers.get + +module Internal_for_tests = struct + let deposit_stake = deposit_stake + + let refine_stake ctxt rollup staker commitment = + let open Lwt_result_syntax in + let* lcc, lcc_inbox_level, _ctxt = + Commitment_storage.last_cemented_commitment_hash_with_level ctxt rollup + in + let* _ctxt, staker_index = + Sc_rollup_staker_index_storage.get_staker_index_unsafe ctxt rollup staker + in + let* commitment_hash, publication_level, ctxt, size_diff = + refine_stake ctxt rollup commitment ~staker_index ~lcc ~lcc_inbox_level + in + assert (Compare.Int.(size_diff < max_commitment_storage_size_in_bytes)) ; + return (commitment_hash, publication_level, ctxt) + + let max_commitment_storage_size_in_bytes = + max_commitment_storage_size_in_bytes +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.mli new file mode 100644 index 000000000000..43a13c71e3c1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.mli @@ -0,0 +1,244 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [remove_staker context rollup staker] forcibly removes the given [staker] + and confiscates their frozen deposits. + + Removes [staker] from the list of active stakers on the [rollup] and + clean its metadata. +*) +val remove_staker : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [publish_commitment context rollup staker commitment] published [commitment]. + + Starts by depositing a stake for [staker] if [staker] is not a known + staker of [rollup]. Then, [staker] will use its stake to stake on + [commitment]. + + For publishing to succeed, the following must hold: + {ol + {li A deposit exists (or can be deposited) for [staker].} + {li The commitment respects the commitment period and is not published + in advance.} + {li The commitment is not past the curfew, i.e., stakers has a limit on the + available time to publish, if a staker already published for this + inbox level.} + {li The [commitment.predecessor] exists.} + {li The [commitment] contains at least one tick.} + } + + Returns the hash of the given commitment, the level when the commitment + was first published by some staker, the modified context and the balance + updates if a stake was deposited. + + This function does not authenticate the staker. +*) +val publish_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Sc_rollup_commitment_repr.t -> + (Sc_rollup_commitment_repr.Hash.t + * Raw_level_repr.t + * Raw_context.t + * Receipt_repr.balance_updates) + tzresult + Lwt.t + +(** [cement context rollup] tries to cement the next inbox level commitment, + that is, the LCC's successor. Returns the cemented commitment hash and + its hash. + + For cementing to succeed, we need to have **one** commitment respecting + the following properties: + {ol + {li The deadline for [commitment] must have passed.} + {li The predecessor of [commitment] must be the Last Cemented Commitment.} + {li There must be at least one staker.} + {li All stakers must be indirectly staked on [commitment].} + } + + If successful, Last Cemented commitment is set to the found commitment, + and deallocate the old cemented commitment accordingly to the number + of stored cemented commitments. + + Clean the storage for the metadata added for this inbox level. +*) +val cement_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + (Raw_context.t + * Sc_rollup_commitment_repr.t + * Sc_rollup_commitment_repr.Hash.t) + tzresult + Lwt.t + +(** [find_staker context rollup staker] returns the most recent commitment + [staker] staked on, or [None] if its last staked commitment is older + or equal than the last cemented commitment. *) +val find_staker : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + (Raw_context.t * Sc_rollup_commitment_repr.Hash.t option) tzresult Lwt.t + +(** [is_staked_on context rollup staker commitment_hash] returns true + iff [staker] is an active staker and has staked on [commitment_hash]. *) +val is_staked_on : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Sc_rollup_commitment_repr.Hash.t -> + (Raw_context.t * bool) tzresult Lwt.t + +(** [commitments_uncarbonated ctxt ~rollup ~inbox_level] returns the + list of commitments associated to [rollup] at [inbox_level] *) +val commitments_uncarbonated : + Raw_context.t -> + rollup:Sc_rollup_repr.t -> + inbox_level:Raw_level_repr.t -> + Sc_rollup_commitment_repr.Hash.t list option tzresult Lwt.t + +(** [stakers_ids_uncarbonated ctxt ~rollup ~commitment] returns the + list of stakers' indexes associated to [rollup] for a specific + [commitment] *) +val stakers_ids_uncarbonated : + Raw_context.t -> + rollup:Sc_rollup_repr.t -> + commitment:Sc_rollup_commitment_repr.Hash.t -> + Sc_rollup_staker_index_repr.t list tzresult Lwt.t + +(** [staker_id_uncarbonated ctxt ~rollup ~pkh] returns the staker's + index associated to the public key hash [pkh] *) +val staker_id_uncarbonated : + Raw_context.t -> + rollup:Sc_rollup_repr.t -> + pkh:Signature.public_key_hash -> + Sc_rollup_staker_index_repr.t tzresult Lwt.t + +(** [stakers_pkhs_uncarbonated ctxt ~rollup] returns the public key hashes + of stakers that are currently actively staking on [rollup] *) +val stakers_pkhs_uncarbonated : + Raw_context.t -> + rollup:Sc_rollup_repr.t -> + Signature.public_key_hash list Lwt.t + +(** [withdraw_stake context rollup staker] removes [staker] and cleans + its metadata. [staker] is allowed to withdraw if it latest staked + commitment is older than the last cemented commitment. +*) +val withdraw_stake : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [commitments_of_inbox_level ctxt rollup inbox_level] returns the list + of commitments for [inbox_level]. *) +val commitments_of_inbox_level : + Raw_context.t -> + Sc_rollup_repr.t -> + Raw_level_repr.t -> + (Raw_context.t * Sc_rollup_commitment_repr.Hash.t list) tzresult Lwt.t + +(** [stakers_of_commitment ctxt rollup commitment_hash] returns the list + of stakers staking on [commitment_hash]. *) +val stakers_of_commitment : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_commitment_repr.Hash.t -> + (Raw_context.t * Sc_rollup_staker_index_repr.t list) tzresult Lwt.t + +(** [find_commitment_of_staker_in_commitments ctxt rollup staker_index commitments] + selects in [commitments] the hash of the commitment staked by + [staker_index], if any. *) +val find_commitment_of_staker_in_commitments : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_staker_index_repr.t -> + Sc_rollup_commitment_repr.Hash.t list -> + (Raw_context.t * Sc_rollup_commitment_repr.Hash.t option) tzresult Lwt.t + +(**/**) + +module Internal_for_tests : sig + (** [deposit_stake context rollup staker] stakes [staker] on the [rollup] by + freezing [sc_rollup_stake_amount] from [staker]'s account balance and + initializing [staker]'s metadata. + + This should usually be followed by [refine_stake] to stake on a + specific commitment. + + Returns the modified context, the balance updates of the frozen + deposit and the index created for [staker]. + *) + val deposit_stake : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + (Raw_context.t + * Receipt_repr.balance_updates + * Sc_rollup_staker_index_repr.t) + tzresult + Lwt.t + + (** [refine_stake context rollup commitment staker] makes [staker] + stakes on [commitment]. + + Because we do not assume any form of coordination between validators, we + do not distinguish between {i adding new} commitments and {i staking on + existing commitments}. The storage of commitments is content-addressable + to minimize storage duplication. + + The first time a commitment hash is staked on, it is assigned a deadline, + which is counted in Tezos blocks (levels). Further stakes on the block does + not affect the deadline. The commitment can not be cemented before the + deadline has expired. Note that if a commitment is removed due to disputes + and then re-entered, a later deadline may be assigned. Assuming one honest + staker is always available, this only affects invalid commitments. + + See {!publish_commitment} to see the list of properties this function + enforces. + + Returns the hashed commitment, at the first level this commitment was + published, and the modified context. + *) + val refine_stake : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + Sc_rollup_commitment_repr.t -> + (Sc_rollup_commitment_repr.Hash.t * Raw_level_repr.t * Raw_context.t) + tzresult + Lwt.t + + (** The maximum storage size requirement (in bytes) of a commitment *) + val max_commitment_storage_size_in_bytes : int +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.ml new file mode 100644 index 000000000000..818c5cb2098d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Z + +let encoding = Data_encoding.n + +module Index : Storage_description.INDEX with type t = t = struct + type nonrec t = t + + let encoding = encoding + + let compare = compare + + let path_length = 1 + + let to_path c l = Z.to_string c :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [c] -> Some (Z.of_string c) + + let rpc_arg = + let z_of_string s = + try Ok (Z.of_string s) with Failure _ -> Error "Cannot parse z value" + in + RPC_arg.make ~name:"z" ~destruct:z_of_string ~construct:Z.to_string () +end + +module Internal_for_tests = struct + let of_z z = z +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.mli new file mode 100644 index 000000000000..68a087e04d5c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_repr.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = private Z.t + +val zero : t + +val succ : t -> t + +val encoding : t Data_encoding.t + +val equal : t -> t -> bool + +module Index : Storage_description.INDEX with type t = t + +module Internal_for_tests : sig + val of_z : Z.t -> t +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.ml new file mode 100644 index 000000000000..b9f305ffde71 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_errors + +let init ctxt rollup = + Storage.Sc_rollup.Staker_index_counter.init + (ctxt, rollup) + Sc_rollup_staker_index_repr.zero + +let fresh_staker_index ctxt rollup staker = + let open Lwt_result_syntax in + (* This is safe because this storage is initialized at the rollup creation + in {!Sc_rollup_storage.originate} .*) + let* staker_index = + Storage.Sc_rollup.Staker_index_counter.get (ctxt, rollup) + in + let* ctxt = + Storage.Sc_rollup.Staker_index_counter.update + (ctxt, rollup) + (Sc_rollup_staker_index_repr.succ staker_index) + in + let* ctxt, _size = + Storage.Sc_rollup.Staker_index.init (ctxt, rollup) staker staker_index + in + let* ctxt, _size_diff = + Storage.Sc_rollup.Stakers.init + (ctxt, rollup) + staker_index + Raw_level_repr.root + in + return (ctxt, staker_index) + +let find_staker_index_unsafe ctxt rollup staker = + Storage.Sc_rollup.Staker_index.find (ctxt, rollup) staker + +let get_staker_index_unsafe ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, staker_index_opt = find_staker_index_unsafe ctxt rollup staker in + match staker_index_opt with + | None -> tzfail Sc_rollup_not_staked + | Some staker_index -> return (ctxt, staker_index) + +let remove_staker ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, staker_index = get_staker_index_unsafe ctxt rollup staker in + let* ctxt, _size_diff = + Storage.Sc_rollup.Staker_index.remove_existing (ctxt, rollup) staker + in + let* ctxt, _size_diff = + Storage.Sc_rollup.Stakers.remove_existing (ctxt, rollup) staker_index + in + return ctxt + +let list_stakers_uncarbonated ctxt rollup = + Storage.Sc_rollup.Staker_index.keys_unaccounted (ctxt, rollup) + +let is_active ctxt rollup staker_index = + Storage.Sc_rollup.Stakers.mem (ctxt, rollup) staker_index + +let is_staker ctxt rollup staker = + Storage.Sc_rollup.Staker_index.mem (ctxt, rollup) staker diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.mli new file mode 100644 index 000000000000..2d727889a9e6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_staker_index_storage.mli @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_staker_index_repr + +(** [init ctxt rollup] initialize a staker index counter for [rollup]. *) +val init : Raw_context.t -> Sc_rollup_repr.t -> Raw_context.t tzresult Lwt.t + +(** [fresh_staker_index ctxt rollup staker] creates a new index for [staker] and + store it in {!Storage.Sc_rollup.Staker_index}. *) +val fresh_staker_index : + Raw_context.t -> + Sc_rollup_repr.t -> + Signature.public_key_hash -> + (Raw_context.t * t) tzresult Lwt.t + +(** [find_staker_index_unsafe ctxt rollup staker] returns the index for the + [rollup]'s [staker]. This function *must* be called only after they have + checked for the existence of the rollup, and therefore it is not necessary + for it to check for the existence of the rollup again. Otherwise, use the + safe function {!find_staker_index}. *) +val find_staker_index_unsafe : + Raw_context.t -> + Sc_rollup_repr.t -> + Signature.public_key_hash -> + (Raw_context.t * t option) tzresult Lwt.t + +(** Same as {!find_staker_index_unsafe} but fails if the value is absent. *) +val get_staker_index_unsafe : + Raw_context.t -> + Sc_rollup_repr.t -> + Signature.public_key_hash -> + (Raw_context.t * t) tzresult Lwt.t + +(** [remove_staker ctxt rollup staker] cleans every storage associated + to [staker] and it's index. + The staker will be no longer considered active until a new index is given + to it, through a new call to {!fresh_staker_index}. *) +val remove_staker : + Raw_context.t -> + Sc_rollup_repr.t -> + Signature.public_key_hash -> + Raw_context.t tzresult Lwt.t + +(** [list_stakers_uncarbonated ctxt rollup] lists the active stakers on + [rollup]. *) +val list_stakers_uncarbonated : + Raw_context.t -> Sc_rollup_repr.t -> Signature.public_key_hash list Lwt.t + +(** [is_active ctxt rollup staker_index] returns true iff [staker_index] + is an active staker. *) +val is_active : + Raw_context.t -> + Sc_rollup_repr.t -> + t -> + (Raw_context.t * bool) tzresult Lwt.t + +(** [is_staker context rollup staker] returns [true] iff [staker] has a + deposit on the given [rollup]. *) +val is_staker : + Raw_context.t -> + Sc_rollup_repr.t -> + Sc_rollup_repr.Staker.t -> + (Raw_context.t * bool) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml new file mode 100644 index 000000000000..fe875fc93483 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml @@ -0,0 +1,226 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_errors +module Store = Storage.Sc_rollup +module Commitment = Sc_rollup_commitment_repr +module Commitment_hash = Commitment.Hash + +(** [new_address ctxt] produces an address completely + determined by an operation hash and an origination counter, and + accounts for gas spent. *) +let new_address ctxt = + let open Result_syntax in + let* ctxt, nonce = Raw_context.increment_origination_nonce ctxt in + let* ctxt = + Raw_context.consume_gas ctxt Sc_rollup_costs.Constants.cost_serialize_nonce + in + match Data_encoding.Binary.to_bytes_opt Origination_nonce.encoding nonce with + | None -> tzfail Sc_rollup_address_generation + | Some nonce_bytes -> + let bytes_len = Bytes.length nonce_bytes in + let+ ctxt = + Raw_context.consume_gas + ctxt + (Sc_rollup_costs.cost_hash_bytes ~bytes_len) + in + (ctxt, Sc_rollup_repr.Address.hash_bytes [nonce_bytes]) + +let init_genesis_info ctxt address genesis_commitment = + let open Lwt_result_syntax in + let*? ctxt, commitment_hash = + Sc_rollup_commitment_storage.hash ctxt genesis_commitment + in + (* The [genesis_commitment.inbox_level] is equal to the current level. *) + let genesis_info : Commitment.genesis_info = + {commitment_hash; level = genesis_commitment.inbox_level} + in + let* ctxt, size = Store.Genesis_info.init ctxt address genesis_info in + return (ctxt, genesis_info, size) + +let init_commitment_storage ctxt address + ({commitment_hash = genesis_commitment_hash; level = origination_level} : + Commitment.genesis_info) genesis_commitment = + let open Lwt_result_syntax in + let* ctxt, lcc_size = + Store.Last_cemented_commitment.init ctxt address genesis_commitment_hash + in + let* ctxt, commitment_size_diff = + Store.Commitments.init + (ctxt, address) + genesis_commitment_hash + genesis_commitment + in + (* Those stores [Store.Commitment_added] and [Store.Commitment_stake_count] + are going to be used to look this bootstrap commitment. + This commitment is added here so the + [sc_rollup_state_storage.deallocate] function does not have to handle a + edge case. + *) + let* ctxt, commitment_added_size_diff = + Store.Commitment_added.init + (ctxt, address) + genesis_commitment_hash + origination_level + in + (* Those stores [Store.Commitment_first_publication_level] and + [Store.Commitment_count_per_inbox_level] are populated with dummy values, + in order the [sc_rollup_state_storage.deallocate_commitment_metadata] + function does not have to handle an edge case of genesis commitment hash. + *) + let* ctxt, commitment_first_publication_level_diff = + Store.Commitment_first_publication_level.init + (ctxt, address) + origination_level + origination_level + in + let* ctxt, commitments_per_inbox_level_diff = + Store.Commitments_per_inbox_level.init + (ctxt, address) + origination_level + [genesis_commitment_hash] + in + return + ( ctxt, + lcc_size + commitment_size_diff + commitment_added_size_diff + + commitment_first_publication_level_diff + + commitments_per_inbox_level_diff ) + +let check_whitelist ctxt whitelist = + let open Result_syntax in + match whitelist with + | Some whitelist -> + let private_enabled = Constants_storage.sc_rollup_private_enable ctxt in + (* The whitelist must be None when the feature is deactivated. *) + let* () = + error_unless + private_enabled + Sc_rollup_errors.Sc_rollup_whitelist_disabled + in + (* The origination fails with an empty list. *) + error_when + (List.is_empty whitelist) + Sc_rollup_errors.Sc_rollup_empty_whitelist + | None -> Ok () + +let raw_originate ?whitelist ctxt ~kind ~parameters_ty ~genesis_commitment + ~address = + let open Lwt_result_syntax in + let*? () = check_whitelist ctxt whitelist in + let* ctxt, pvm_kind_size = Store.PVM_kind.init ctxt address kind in + let* ctxt, param_ty_size = + Store.Parameters_type.init ctxt address parameters_ty + in + let* ctxt = Sc_rollup_staker_index_storage.init ctxt address in + let* ctxt, genesis_info, genesis_info_size_diff = + init_genesis_info ctxt address genesis_commitment + in + let* ctxt, commitment_size_diff = + init_commitment_storage ctxt address genesis_info genesis_commitment + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4551 + There is no need to have both `origination_size` and the size of storage. + We should remove one of them. *) + let addresses_size = 2 * Sc_rollup_repr.Address.size in + let stored_kind_size = 2 (* because tag_size of kind encoding is 16bits. *) in + let origination_size = Constants_storage.sc_rollup_origination_size ctxt in + let* ctxt, whitelist_size = + let*? () = check_whitelist ctxt whitelist in + match whitelist with + | Some whitelist -> + let* ctxt, new_storage_size = + Sc_rollup_whitelist_storage.init + ~whitelist + ctxt + address + ~origination_level:genesis_info.level + in + Sc_rollup_whitelist_storage.adjust_storage_space + ctxt + address + ~new_storage_size + | None -> return (ctxt, Z.zero) + in + let size = + Z.( + add + (of_int + (origination_size + stored_kind_size + addresses_size + param_ty_size + + pvm_kind_size + genesis_info_size_diff + commitment_size_diff)) + whitelist_size) + in + return (size, genesis_info.commitment_hash, ctxt) + +let originate ?whitelist ctxt ~kind ~parameters_ty ~genesis_commitment = + let open Lwt_result_syntax in + let*? ctxt, address = new_address ctxt in + let* size, genesis_commitment, ctxt = + raw_originate + ?whitelist + ctxt + ~kind + ~parameters_ty + ~genesis_commitment + ~address + in + return (address, size, genesis_commitment, ctxt) + +let kind ctxt address = + let open Lwt_result_syntax in + let* ctxt, kind_opt = Store.PVM_kind.find ctxt address in + match kind_opt with + | Some k -> return (ctxt, k) + | None -> tzfail (Sc_rollup_errors.Sc_rollup_does_not_exist address) + +let list_unaccounted ctxt = + let open Lwt_result_syntax in + let*! res = Store.PVM_kind.keys_unaccounted ctxt in + return res + +let genesis_info ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, genesis_info = Store.Genesis_info.find ctxt rollup in + match genesis_info with + | None -> tzfail (Sc_rollup_does_not_exist rollup) + | Some genesis_info -> return (ctxt, genesis_info) + +let get_metadata ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, genesis_info = genesis_info ctxt rollup in + let metadata : Sc_rollup_metadata_repr.t = + {address = rollup; origination_level = genesis_info.level} + in + return (ctxt, metadata) + +let parameters_type ctxt rollup = + let open Lwt_result_syntax in + let+ ctxt, res = Store.Parameters_type.find ctxt rollup in + (res, ctxt) + +let must_exist ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, exists = Store.Genesis_info.mem ctxt rollup in + if exists then return ctxt else tzfail (Sc_rollup_does_not_exist rollup) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli new file mode 100644 index 000000000000..8da1651e5a5b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli @@ -0,0 +1,102 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [originate ?whitelist context ~kind ~parameters_ty ~genesis_commitment] produces an + address [a] for a smart contract rollup using the origination nonce found in + [context]. This function also initializes the storage with a new + entry indexed by [a] to remember the [kind] of the rollup at + address [a]. + + Also returns the number of allocated bytes. *) +val originate : + ?whitelist:Sc_rollup_whitelist_repr.t -> + Raw_context.t -> + kind:Sc_rollups.Kind.t -> + parameters_ty:Script_repr.lazy_expr -> + genesis_commitment:Sc_rollup_commitment_repr.t -> + (Sc_rollup_repr.Address.t + * Z.t + * Sc_rollup_commitment_repr.Hash.t + * Raw_context.t) + tzresult + Lwt.t + +(** [raw_originate ?whitelist context ~kind ~parameters_ty ~genesis_commitment ~address] is + exactly {!originate} but provides the rollup's address ([address]) instead + of randomly generating it. + + This should not be used by [apply.ml], this is needed for bootstrap + smart rollups only. +*) +val raw_originate : + ?whitelist:Sc_rollup_whitelist_repr.t -> + Raw_context.t -> + kind:Sc_rollups.Kind.t -> + parameters_ty:Script_repr.lazy_expr -> + genesis_commitment:Sc_rollup_commitment_repr.t -> + address:Sc_rollup_repr.Address.t -> + (Z.t * Sc_rollup_commitment_repr.Hash.t * Raw_context.t) tzresult Lwt.t + +(** [kind context address] returns the kind of the given rollup [address] iff + [address] is an existing rollup. Fails with an [Sc_rollup_does_not_exist] + error in case the rollup does not exist. *) +val kind : + Raw_context.t -> + Sc_rollup_repr.t -> + (Raw_context.t * Sc_rollups.Kind.t) tzresult Lwt.t + +val list_unaccounted : Raw_context.t -> Sc_rollup_repr.t list tzresult Lwt.t + +(** [genesis_info ctxt sc_rollup] returns the level at which a [sc_rollup] was + originated, and its genesis commitment hash. *) +val genesis_info : + Raw_context.t -> + Sc_rollup_repr.t -> + (Raw_context.t * Sc_rollup_commitment_repr.genesis_info) tzresult Lwt.t + +(** [get_metadata ctxt rollup] retrieves the origination level of the [rollup] + using {!Sc_rollup_commitment_repr.genesis_info} and creates a + {!Sc_rollup_metadata_repr.t}. + Fails with [Sc_rollup_does_not_exist {rollup}] if the genesis info is + missing. *) +val get_metadata : + Raw_context.t -> + Sc_rollup_repr.t -> + (Raw_context.t * Sc_rollup_metadata_repr.t) tzresult Lwt.t + +(** [parameters_type ctxt rollup] returns the registered type of a rollup. + Returns [None] in case there is no registered type for the rollup. *) +val parameters_type : + Raw_context.t -> + Sc_rollup_repr.t -> + (Script_repr.lazy_expr option * Raw_context.t) tzresult Lwt.t + +(** [must_exist ctxt rollup] checks whether the given [rollup] exists + in [ctxt]. If [rollup] exists, a new context is returned with gas + consumed for the lookup cost. If it does not exist, an error is + returned. *) +val must_exist : + Raw_context.t -> Sc_rollup_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.ml new file mode 100644 index 000000000000..690a612e7fd1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Z + +let initial = zero + +let next = succ + +let jump tick z = max initial (add tick z) + +let pp = pp_print + +let encoding = Data_encoding.n + +let distance tick1 tick2 = Z.abs (Z.sub tick1 tick2) + +let of_int x = if Compare.Int.(x < 0) then None else Some (Z.of_int x) + +let to_int x = if Z.fits_int x then Some (Z.to_int x) else None + +let of_z x = x + +let to_z x = x + +let of_number_of_ticks x = + Z.of_int64 (Sc_rollup_repr.Number_of_ticks.to_value x) + +let ( <= ) = leq + +let ( < ) = lt + +let ( >= ) = geq + +let ( > ) = gt + +let ( = ) = equal + +let ( <> ) x y = not (x = y) + +let size_in_bytes tick = + (* Same definition as in {!Michelson_v1_gas}. *) + let bits = numbits tick in + (7 + bits) / 8 + +module Map = Map.Make (Z) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.mli new file mode 100644 index 000000000000..1344b53f5502 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_tick_repr.mli @@ -0,0 +1,74 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module defines [Tick.t], an execution step counter for + smart-contract rollups. *) + +(** A tick is a counter for the execution step of a smart-contract rollup. *) +type t + +(** The initial tick. *) +val initial : t + +(** [next tick] returns the counter successor of [tick]. *) +val next : t -> t + +(** [jump tick k] moves [tick] by [k] (possibly negative) steps. + The move stops at [initial] when going back in time. *) +val jump : t -> Z.t -> t + +(** [distance t1 t2] is the absolute value of the difference between [t1] and [t2]. *) +val distance : t -> t -> Z.t + +(** [of_int x] returns [Some tick] for the rollup [x]-th execution + step if [x] is non-negative. Returns [None] otherwise. *) +val of_int : int -> t option + +(** [to_int tick] converts the [tick] into an integer. *) +val to_int : t -> int option + +(** [of_number_of_ticks] converts from the bounded int type defined in + the [Sc_rollup_repr] module. [Number_of_ticks] is used inside of + commitments to limit the maximum possible storage requirement. It is + bounded between one and [max_int] meaning that this can never return + a negative number so an [option] isn't required. *) +val of_number_of_ticks : Sc_rollup_repr.Number_of_ticks.t -> t + +val of_z : Z.t -> t + +val to_z : t -> Z.t + +(** [size_in_bytes tick] is the size in bytes of [tick]'s internal + representation. This function is used by the gas model. *) +val size_in_bytes : t -> int + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +include Compare.S with type t := t + +module Map : Map.S with type key = t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.ml new file mode 100644 index 000000000000..d984f8ff8c9f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.ml @@ -0,0 +1,733 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += WASM_proof_verification_failed + +type error += WASM_proof_production_failed + +type error += WASM_output_proof_production_failed + +type error += WASM_output_proof_verification_failed + +type error += WASM_invalid_claim_about_outbox + +type error += WASM_invalid_dissection_distribution + +let () = + let open Data_encoding in + let msg = "Invalid claim about outbox" in + register_error_kind + `Permanent + ~id:"smart_rollup_wasm_invalid_claim_about_outbox" + ~title:msg + ~pp:(fun fmt () -> Format.pp_print_string fmt msg) + ~description:msg + unit + (function WASM_invalid_claim_about_outbox -> Some () | _ -> None) + (fun () -> WASM_invalid_claim_about_outbox) ; + let msg = "Output proof production failed" in + register_error_kind + `Permanent + ~id:"smart_rollup_wasm_output_proof_production_failed" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function WASM_output_proof_production_failed -> Some () | _ -> None) + (fun () -> WASM_output_proof_production_failed) ; + let msg = "Output proof verification failed" in + register_error_kind + `Permanent + ~id:"smart_rollup_wasm_output_proof_verification_failed" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function WASM_output_proof_verification_failed -> Some () | _ -> None) + (fun () -> WASM_output_proof_verification_failed) ; + let msg = "Proof production failed" in + register_error_kind + `Permanent + ~id:"smart_rollup_wasm_proof_production_failed" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function WASM_proof_production_failed -> Some () | _ -> None) + (fun () -> WASM_proof_production_failed) ; + let msg = "Proof verification failed" in + register_error_kind + `Permanent + ~id:"smart_rollup_wasm_proof_verification_failed" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function WASM_proof_verification_failed -> Some () | _ -> None) + (fun () -> WASM_proof_verification_failed) ; + let msg = + "Invalid dissection distribution: not all ticks are a multiplier of the \ + maximum number of ticks of a snapshot" + in + register_error_kind + `Permanent + ~id:"smart_rollup_wasm_invalid_dissection_distribution" + ~title:msg + ~pp:(fun fmt () -> Format.fprintf fmt "%s" msg) + ~description:msg + unit + (function WASM_invalid_dissection_distribution -> Some () | _ -> None) + (fun () -> WASM_invalid_dissection_distribution) + +module V2_0_0 = struct + let current_version = Wasm_2_0_0.v4 + + let ticks_per_snapshot = Z.of_int64 50_000_000_000_000L + + let outbox_validity_period = 241_920l + + let outbox_message_limit = Z.of_int 100 + + let well_known_reveal_preimage = + Sc_rollup_reveal_hash.well_known_reveal_preimage + + let well_known_reveal_hash = Sc_rollup_reveal_hash.well_known_reveal_hash + + let decode_reveal (Wasm_2_0_0.Reveal_raw payload) = + match + Data_encoding.Binary.of_string_opt + Sc_rollup_PVM_sig.reveal_encoding + payload + with + | Some reveal -> reveal + | None -> + (* If the kernel has tried to submit an incorrect reveal request, + we don’t stuck the rollup. Instead, we fallback to the + requesting the [well_known_reveal_hash] preimage *) + Reveal_raw_data well_known_reveal_hash + + open Sc_rollup_repr + module PS = Sc_rollup_PVM_sig + + module type TreeS = + Context.TREE with type key = string list and type value = bytes + + module type Make_wasm = module type of Wasm_2_0_0.Make + + module type S = sig + include Sc_rollup_PVM_sig.S + + val parse_boot_sector : string -> string option + + val pp_boot_sector : Format.formatter -> string -> unit + + (** [get_tick state] gets the total tick counter for the given PVM state. *) + val get_tick : state -> Sc_rollup_tick_repr.t Lwt.t + + (** PVM status *) + type status = + | Computing + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + + (** [get_status ~is_reveal_enabled state] gives you the current execution status for the PVM. *) + val get_status : + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + state -> + status Lwt.t + + val get_outbox : + Raw_level_repr.t -> state -> Sc_rollup_PVM_sig.output list Lwt.t + end + + (* [Make (Make_backend) (Context)] creates a PVM. + + The Make_backend is a functor that creates the backend of the PVM. + The Conext provides the tree and the proof types. + *) + module Make + (Make_backend : Make_wasm) + (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : + S + with type context = Context.Tree.t + and type state = Context.tree + and type proof = Context.proof = struct + module Tree = Context.Tree + + type context = Context.Tree.t + + type hash = State_hash.t + + type proof = Context.proof + + let proof_encoding = Context.proof_encoding + + let proof_start_state proof = Context.proof_before proof + + let proof_stop_state proof = Context.proof_after proof + + let parse_boot_sector s = Hex.to_string @@ `Hex s + + let pp_boot_sector fmt s = Format.fprintf fmt "%s" s + + type tree = Tree.tree + + type status = + | Computing + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + + module State = struct + type state = tree + + module Monad : sig + type 'a t + + val run : 'a t -> state -> (state * 'a) Lwt.t + + val return : 'a -> 'a t + + module Syntax : sig + val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t + end + + val get : tree t + + val set : tree -> unit t + + val lift : 'a Lwt.t -> 'a t + end = struct + type 'a t = state -> (state * 'a) Lwt.t + + let return x state = Lwt.return (state, x) + + let bind m f state = + let open Lwt_syntax in + let* state, res = m state in + f res state + + module Syntax = struct + let ( let* ) = bind + end + + let run m state = m state + + let get s = Lwt.return (s, s) + + let set s _ = Lwt.return (s, ()) + + let lift m s = Lwt.map (fun r -> (s, r)) m + end + end + + type state = State.state + + module WASM_machine = Make_backend (Tree) + open State + + let pp _state = + Lwt.return @@ fun fmt () -> Format.pp_print_string fmt "" + + open Monad + + let initial_state ~empty = WASM_machine.initial_state current_version empty + + let install_boot_sector state boot_sector = + WASM_machine.install_boot_sector + ~ticks_per_snapshot + ~outbox_validity_period + ~outbox_message_limit + boot_sector + state + + let state_hash state = + let context_hash = Tree.hash state in + Lwt.return @@ State_hash.context_hash_to_state_hash context_hash + + let result_of m state = + let open Lwt_syntax in + let* _, v = run m state in + return v + + let state_of m state = + let open Lwt_syntax in + let* s, _ = run m state in + return s + + let get_tick : Sc_rollup_tick_repr.t Monad.t = + let open Monad.Syntax in + let* s = get in + let* info = lift (WASM_machine.get_info s) in + return @@ Sc_rollup_tick_repr.of_z info.current_tick + + let get_tick : state -> Sc_rollup_tick_repr.t Lwt.t = result_of get_tick + + let get_last_message_read : _ Monad.t = + let open Monad.Syntax in + let* s = get in + let* info = lift (WASM_machine.get_info s) in + return + @@ + match info.last_input_read with + | Some {inbox_level; message_counter} -> + let inbox_level = Raw_level_repr.of_int32_non_negative inbox_level in + Some (inbox_level, message_counter) + | _ -> None + + let get_status ~is_reveal_enabled = + let open Monad.Syntax in + let open Sc_rollup_PVM_sig in + let* s = get in + let* info = lift (WASM_machine.get_info s) in + let* last_read = get_last_message_read in + (* We do not put the machine in a stuck condition if a kind of reveal + happens to not be supported. This is a sensible thing to do, as if + there is an off-by-one error in the WASM kernel one can do an + incorrect reveal, which can put the PVM in a stuck state with no way + to upgrade the kernel to fix the off-by-one. *) + let try_return_reveal candidate = + match last_read with + | Some (current_block_level, _) -> + let is_enabled = is_reveal_enabled ~current_block_level candidate in + if is_enabled then Waiting_for_reveal candidate + else Waiting_for_reveal (Reveal_raw_data well_known_reveal_hash) + | None -> Waiting_for_reveal (Reveal_raw_data well_known_reveal_hash) + in + return + @@ + match info.input_request with + | No_input_required -> Computing + | Input_required -> Waiting_for_input_message + | Reveal_required req -> try_return_reveal (decode_reveal req) + + let is_input_state ~is_reveal_enabled = + let open Monad.Syntax in + let* status = get_status ~is_reveal_enabled in + match status with + | Waiting_for_input_message -> ( + let* last_read = get_last_message_read in + match last_read with + | Some (level, n) -> return (PS.First_after (level, n)) + | None -> return PS.Initial) + | Computing -> return PS.No_input_required + | Waiting_for_reveal reveal -> return (PS.Needs_reveal reveal) + + let is_input_state ~is_reveal_enabled = + result_of (is_input_state ~is_reveal_enabled) + + let get_status ~is_reveal_enabled : state -> status Lwt.t = + result_of (get_status ~is_reveal_enabled) + + let get_outbox outbox_level state = + let open Lwt_syntax in + let outbox_level_int32 = + Raw_level_repr.to_int32_non_negative outbox_level + in + let rec aux outbox message_index = + let output = + Wasm_2_0_0.{outbox_level = outbox_level_int32; message_index} + in + let* res = WASM_machine.get_output output state in + match res with + | None -> return (List.rev outbox) + | Some msg -> ( + let serialized = + Sc_rollup_outbox_message_repr.unsafe_of_string msg + in + match Sc_rollup_outbox_message_repr.deserialize serialized with + | Error _ -> + (* The [write_output] host function does not guarantee that the contents + of the returned output is a valid encoding of an outbox message. + We choose to ignore such messages. An alternative choice would be to + craft an output with a payload witnessing the illformedness of the + output produced by the kernel. *) + (aux [@ocaml.tailcall]) outbox (Z.succ message_index) + | Ok message -> + let output = PS.{outbox_level; message_index; message} in + (aux [@ocaml.tailcall]) + (output :: outbox) + (Z.succ message_index)) + in + aux [] Z.zero + + let set_input_state input = + let open Monad.Syntax in + match input with + | PS.Inbox_message input -> + let open PS in + let {inbox_level; message_counter; payload} = input in + let* s = get in + let* s = + lift + (WASM_machine.set_input_step + { + inbox_level = Raw_level_repr.to_int32_non_negative inbox_level; + message_counter; + } + (payload :> string) + s) + in + set s + | PS.Reveal (PS.Raw_data data) -> + let* s = get in + let* s = lift (WASM_machine.reveal_step (Bytes.of_string data) s) in + set s + | PS.Reveal (PS.Metadata metadata) -> + let metadata_bytes = + Data_encoding.Binary.to_bytes_exn + Sc_rollup_metadata_repr.encoding + metadata + in + let* s = get in + let* s = lift (WASM_machine.reveal_step metadata_bytes s) in + set s + | PS.Reveal (PS.Dal_page content_bytes) -> + let content_bytes = + Option.value ~default:Bytes.empty content_bytes + (* [content_opt] is [None] when the slot was not confirmed in the L1. + In this case, we return empty bytes. + + Note that the kernel can identify this unconfirmed slot scenario because + all confirmed pages have a size of 4KiB. Thus, a page can only be considered + empty (0KiB) if it is unconfirmed. *) + in + let* s = get in + let* s = lift (WASM_machine.reveal_step content_bytes s) in + set s + | PS.Reveal (PS.Dal_parameters dal_parameters) -> + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/6544 + reveal_dal_parameters result for slow execution PVM. *) + let dal_parameters_bytes = + Data_encoding.Binary.to_bytes_exn + Sc_rollup_dal_parameters_repr.encoding + dal_parameters + in + let* s = get in + let* s = lift (WASM_machine.reveal_step dal_parameters_bytes s) in + set s + + let set_input input = state_of @@ set_input_state input + + let eval_step = + let open Monad.Syntax in + let* s = get in + let* s = lift (WASM_machine.compute_step s) in + set s + + let eval state = state_of eval_step state + + let step_transition ~is_reveal_enabled input_given state = + let open Lwt_syntax in + let* request = is_input_state ~is_reveal_enabled state in + let* state = + match request with + | PS.No_input_required -> eval state + | _ -> ( + match input_given with + | Some input -> set_input input state + | None -> return state) + in + return (state, request) + + let verify_proof ~is_reveal_enabled input_given proof = + let open Lwt_result_syntax in + let*! result = + Context.verify_proof + proof + (step_transition ~is_reveal_enabled input_given) + in + match result with + | None -> tzfail WASM_proof_verification_failed + | Some (_state, request) -> return request + + let produce_proof context ~is_reveal_enabled input_given state = + let open Lwt_result_syntax in + let*! result = + Context.produce_proof + context + state + (step_transition ~is_reveal_enabled input_given) + in + match result with + | Some (tree_proof, _requested) -> return tree_proof + | None -> tzfail WASM_proof_production_failed + + type output_proof = { + output_proof : Context.proof; + output_proof_output : PS.output; + } + + let output_proof_encoding = + let open Data_encoding in + conv + (fun {output_proof; output_proof_output} -> + (output_proof, output_proof_output)) + (fun (output_proof, output_proof_output) -> + {output_proof; output_proof_output}) + (obj2 + (req "output_proof" Context.proof_encoding) + (req "output_proof_output" PS.output_encoding)) + + let output_of_output_proof s = s.output_proof_output + + let state_of_output_proof s = proof_start_state s.output_proof + + let get_output : PS.output -> Sc_rollup_outbox_message_repr.t option Monad.t + = + fun {outbox_level; message_index; message} -> + let open Monad.Syntax in + let* s = get in + let* result = + lift + (WASM_machine.get_output + { + outbox_level = Raw_level_repr.to_int32_non_negative outbox_level; + message_index; + } + s) + in + let message_encoded = + Data_encoding.Binary.to_string_exn + Sc_rollup_outbox_message_repr.encoding + message + in + return + @@ Option.bind result (fun result -> + if Compare.String.(result = message_encoded) then Some message + else None) + + let verify_output_proof p = + let open Lwt_result_syntax in + let transition = run @@ get_output p.output_proof_output in + let*! result = Context.verify_proof p.output_proof transition in + match result with + | Some (_state, Some message) -> + return + Sc_rollup_PVM_sig. + { + outbox_level = p.output_proof_output.outbox_level; + message_index = p.output_proof_output.message_index; + message; + } + | _ -> tzfail WASM_output_proof_verification_failed + + let produce_output_proof context state output_proof_output = + let open Lwt_result_syntax in + let*! result = + Context.produce_proof context state + @@ run + @@ get_output output_proof_output + in + match result with + | Some (output_proof, Some message) -> + return + { + output_proof; + output_proof_output = + { + outbox_level = output_proof_output.outbox_level; + message_index = output_proof_output.message_index; + message; + }; + } + | _ -> fail WASM_output_proof_production_failed + + let check_sections_number ~default_number_of_sections ~number_of_sections + ~dist = + let open Sc_rollup_dissection_chunk_repr in + let is_stop_chunk_aligned = + Compare.Z.(Z.rem dist ticks_per_snapshot = Z.zero) + in + let max_number_of_sections = Z.(div dist ticks_per_snapshot) in + let expected = + Compare.Z.min + (Z.of_int default_number_of_sections) + (if is_stop_chunk_aligned then max_number_of_sections + else Z.succ max_number_of_sections) + in + let given = Z.of_int number_of_sections in + error_unless + Compare.Z.(given = expected) + (Dissection_number_of_sections_mismatch {given; expected}) + + let check_dissection ~default_number_of_sections ~start_chunk ~stop_chunk + dissection = + let open Result_syntax in + let open Sc_rollup_dissection_chunk_repr in + let dist = + Sc_rollup_tick_repr.distance start_chunk.tick stop_chunk.tick + in + (* + We fall back to the default dissection check when the + [kernel_run] culprit has been found and is being dissected. + + This condition will also be met if the PVM is stuck (because + it is unlikely that [ticks_per_snapshot] messages can be + posted in a commitment period), which is OKay because the Fast + Execution cannot be leveraged in that case, which means the + ad-hoc dissection predicate would not provide any speed up. + *) + if Compare.Z.(dist <= ticks_per_snapshot) then + default_check + ~section_maximum_size:Z.(div dist (Z.of_int 2)) + ~check_sections_number:default_check_sections_number + ~default_number_of_sections + ~start_chunk + ~stop_chunk + dissection + else + (* + There are enough ticks to consider that at least one call + to [kernel_run] is involved. + + We now need to consider two cases: either [stop_chunk] is a + multiple of [ticks_per_snapshot] (the PVM is not stuck), or + it is not (the PVM has been stuck during the processing + of one of the ticks of the dissection). + + For the latter case, we want to validate a dissection if + + 1. Every complete [kernel_run] invocations are dissected + as normal in the n-1 first chunks, and + 2. The final section contains all the ticks of the + interrupted [kernel_run]. + *) + let is_stop_chunk_aligned = + Compare.Z.(Z.rem dist ticks_per_snapshot = Z.zero) + in + (* + We keep the same dissection predicate as the default + dissection that a given section cannot be more than half of + the “full distance”, but we only consider the complete + calls to [kernel_run] in the “full distance”. The remainder + ticks will be put in the very last section. + *) + let considered_dist = + if is_stop_chunk_aligned then dist + else + let last_valid_stop_tick = + Sc_rollup_tick_repr.of_z + Z.( + mul + (div + (Sc_rollup_tick_repr.to_z stop_chunk.tick) + ticks_per_snapshot) + ticks_per_snapshot) + in + Sc_rollup_tick_repr.(distance start_chunk.tick last_valid_stop_tick) + in + (* + There is one last corner case to consider: if the stuck + state happens in the second [kernel_run] of the period. + + In this case, the considered distance is equal to the + snapshot size, and divided this value by two means the + maximum size of a section becomes 0. + + So we keep that a section length is at least + [ticks_per_snapshot]. + *) + let section_maximum_size = + Z.max ticks_per_snapshot (Z.div considered_dist (Z.of_int 2)) + in + let* () = + default_check + ~section_maximum_size + ~check_sections_number + ~default_number_of_sections + ~start_chunk + ~stop_chunk + dissection + in + error_unless + (List.for_all + (fun chunk -> + let open Sc_rollup_tick_repr in + Z.( + equal (rem (to_z chunk.tick) ticks_per_snapshot) zero + || Sc_rollup_tick_repr.equal start_chunk.tick chunk.tick + || Sc_rollup_tick_repr.equal stop_chunk.tick chunk.tick)) + dissection) + WASM_invalid_dissection_distribution + + let get_current_level state = + let open Lwt_syntax in + let+ res = result_of get_last_message_read state in + Option.map fst res + + module Internal_for_tests = struct + let insert_failure state = + let open Lwt_syntax in + let add n = Tree.add state ["failures"; string_of_int n] Bytes.empty in + let* n = Tree.length state ["failures"] in + add n + end + end + + module Protocol_implementation = + Make + (Wasm_2_0_0.Make) + (struct + module Tree = struct + include Context.Tree + + type tree = Context.tree + + type t = Context.t + + type key = string list + + type value = bytes + end + + type tree = Context.tree + + type proof = Context.Proof.tree Context.Proof.t + + let verify_proof p f = + let open Lwt_option_syntax in + let*? () = + Result.to_option (Context_binary_proof.check_is_binary p) + in + Lwt.map Result.to_option (Context.verify_tree_proof p f) + + let produce_proof _context _state _f = + (* Can't produce proof without full context*) + Lwt.return_none + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> + State_hash.context_hash_to_state_hash hash + + let proof_before proof = + kinded_hash_to_state_hash proof.Context.Proof.before + + let proof_after proof = + kinded_hash_to_state_hash proof.Context.Proof.after + + let proof_encoding = Context.Proof_encoding.V2.Tree2.tree_proof_encoding + end) +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.mli new file mode 100644 index 000000000000..818da8195857 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_wasm.mli @@ -0,0 +1,129 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module V2_0_0 : sig + (** This module provides Proof-Generating Virtual Machine (PVM) running + WebAssembly (version 2.0.0). *) + + val current_version : Wasm_2_0_0.version + + module type S = sig + include Sc_rollup_PVM_sig.S + + (** [parse_boot_sector s] builds a boot sector from its human + writable description. *) + val parse_boot_sector : string -> string option + + (** [pp_boot_sector fmt s] prints a human readable representation of + a boot sector. *) + val pp_boot_sector : Format.formatter -> string -> unit + + (* Required by L2 node: *) + + (** [get_tick state] gets the total tick counter for the given PVM state. *) + val get_tick : state -> Sc_rollup_tick_repr.t Lwt.t + + (** PVM status *) + type status = + | Computing + | Waiting_for_input_message + | Waiting_for_reveal of Sc_rollup_PVM_sig.reveal + + (** [get_status ~is_reveal_enabled state] gives you the current execution status for the PVM. *) + val get_status : + is_reveal_enabled:Sc_rollup_PVM_sig.is_reveal_enabled -> + state -> + status Lwt.t + + (** [get_outbox outbox_level state] returns the outbox in [state] + for a given [outbox_level]. *) + val get_outbox : + Raw_level_repr.t -> state -> Sc_rollup_PVM_sig.output list Lwt.t + end + + module type Make_wasm = module type of Wasm_2_0_0.Make + + (** Build a WebAssembly PVM using the given proof-supporting context. *) + module Make + (Lib_scoru_Wasm : Make_wasm) + (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : + S + with type context = Context.Tree.t + and type state = Context.tree + and type proof = Context.proof + + (** This PVM is used for verification in the Protocol. [produce_proof] always returns [None]. *) + module Protocol_implementation : + S + with type context = Context.t + and type state = Context.tree + and type proof = Context.Proof.tree Context.Proof.t + + (** Number of ticks between snapshotable states, chosen low enough + to maintain refutability. + + {b Warning:} This value is used to specialize the dissection + predicate of the WASM PVM. Do not change it without a migration + plan for already originated smart rollups. + + Depends on + - speed (tick/s) of node in slow mode (from benchmark, 6000000 tick/s) + - the number of ticks in a commitment ({!Int64.max_int}, + as per Number_of_ticks.max_value) + + see #3590 for more pointers *) + val ticks_per_snapshot : Z.t + + (* The number of outboxes to keep, which is for a period of two + weeks. For a block time of 5 seconds, this equals to (60 * 60 * + 24 * 14) / 5 = 241_920 blocks. We choose to consider 5 seconds + instead of 10 proposed in protocol P to remove the need to + introduce a new PVM version every time the block time is + modified. We believe 5 seconds is small enough to be "safe" for + multiple months. It does not create a critical issue, we will just keep + more outboxes than expected. *) + val outbox_validity_period : int32 + + (* Maximum number of outbox messages per level. + + Equals to {Constants_parametric_repr.max_outbox_messages_per_level}. *) + val outbox_message_limit : Z.t + + (** The hash requested by the WASM PVM if it cannot decode the input + provided by the WASM kernel, that is, if the bytes value cannot + be decoded with {!Sc_rollup_reveal_hash.encoding}. *) + val well_known_reveal_hash : Sc_rollup_reveal_hash.t + + (** The preimage of {!well_known_reveal_hash}. *) + val well_known_reveal_preimage : string + + (** Convert a raw reveal request of the WASM PVM into a typed reveal as + defined by the protocol. + + If the decoding fails, fallback to requesting the preimage of the + {!well_known_reveal_hash}. *) + val decode_reveal : Wasm_2_0_0.reveal -> Sc_rollup_PVM_sig.reveal +end diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.ml new file mode 100644 index 000000000000..efcbde19acdf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.ml @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Signature.Public_key_hash.t list + +let encoding = + let open Data_encoding in + (* The whitelist size is checked to forbid the origination of a + whitelist that is bigger than any subsequent whitelist + update. This check is valid because the binary outbox message + encoding size is only two bytes longer than the maximum whitelist + update size (encoded in binary), where the encoding of a key is + 20 bytes long. *) + check_size (Constants_repr.sc_rollup_message_size_limit - 2) + @@ list Signature.Public_key_hash.encoding + +let pp ppf = + let open Format in + fprintf + ppf + "@[@[[@,%a@]@,]@]" + (pp_print_list + ~pp_sep:(fun ppf () -> fprintf ppf ";@ ") + Signature.Public_key_hash.pp_short) + +type last_whitelist_update = { + message_index : Z.t; + outbox_level : Raw_level_repr.t; +} + +let last_whitelist_update_encoding = + Data_encoding.( + conv + (fun {message_index; outbox_level} -> (message_index, outbox_level)) + (fun (message_index, outbox_level) -> {message_index; outbox_level}) + (obj2 + (req "message_index" n) + (req "outbox_level" Raw_level_repr.encoding))) + +type update = Public | Private of t + +let update_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Public" + (obj1 (req "kind" (constant "public"))) + (function Public -> Some () | _ -> None) + (fun () -> Public); + case + (Tag 1) + ~title:"Private" + (obj2 (req "kind" (constant "update")) (req "whitelist" encoding)) + (function Private whitelist -> Some ((), whitelist) | _ -> None) + (fun ((), whitelist) -> Private whitelist); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.mli new file mode 100644 index 000000000000..ef41acb50f5a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_repr.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Signature.Public_key_hash.t list + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +(** This type is used in the `Storage.Last_whitelist_update. It is the + latest whitelist update message executed in the L1. It is used to + prevent user to execute whitelist update in unchronological + order. *) +type last_whitelist_update = { + message_index : Z.t; + outbox_level : Raw_level_repr.t; +} + +val last_whitelist_update_encoding : last_whitelist_update Data_encoding.t + +type update = Public | Private of t + +val update_encoding : update Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.ml new file mode 100644 index 000000000000..9852731d3c24 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.ml @@ -0,0 +1,147 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let is_private ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, rollup_is_public = + Storage.Sc_rollup.Whitelist.is_empty (ctxt, rollup) + in + return (ctxt, not rollup_is_public) + +let init_whitelist ctxt rollup_address ~whitelist = + let open Lwt_result_syntax in + let* ctxt, used_storage = + List.fold_left_es + (fun (ctxt, size) e -> + let* ctxt, size_e = + (* the storage fails when there key already exists. This is + only to improve the UX so that it returns a cleaner + error. *) + trace Sc_rollup_errors.Sc_rollup_duplicated_key_in_whitelist + @@ Storage.Sc_rollup.Whitelist.init (ctxt, rollup_address) e + in + return (ctxt, Z.add size (Z.of_int size_e))) + (ctxt, Z.zero) + whitelist + in + return (ctxt, used_storage) + +let init ctxt rollup_address ~whitelist ~origination_level = + let open Lwt_result_syntax in + let* ctxt, used_storage = init_whitelist ctxt rollup_address ~whitelist in + let* ctxt, _whitelist_update_storage = + Storage.Sc_rollup.Last_whitelist_update.init + ctxt + rollup_address + {outbox_level = origination_level; message_index = Z.zero} + in + return (ctxt, used_storage) + +let check_access_to_private_rollup ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, rollup_is_private = is_private ctxt rollup in + if rollup_is_private then + let* ctxt, staker_in_whitelist = + Storage.Sc_rollup.Whitelist.mem (ctxt, rollup) staker + in + let* () = + fail_when + (not staker_in_whitelist) + Sc_rollup_errors.Sc_rollup_staker_not_in_whitelist + in + return ctxt + else return ctxt + +let find_whitelist_uncarbonated ctxt rollup_address = + let open Lwt_result_syntax in + let* _, is_private = is_private ctxt rollup_address in + if is_private then + let*! elts = + Storage.Sc_rollup.Whitelist.fold_keys_unaccounted + (ctxt, rollup_address) + ~order:`Sorted + ~init:[] + ~f:(fun pkh acc -> Lwt.return (pkh :: acc)) + in + return (Some elts) + else return None + +let replace ctxt rollup ~whitelist = + let open Lwt_result_syntax in + let* ctxt = Storage.Sc_rollup.Whitelist.clear (ctxt, rollup) in + init_whitelist ~whitelist ctxt rollup + +let make_public ctxt rollup = + let open Lwt_result_syntax in + let* ctxt = Storage.Sc_rollup.Whitelist.clear (ctxt, rollup) in + let* used_storage = + Storage.Sc_rollup.Whitelist_used_storage_space.find ctxt rollup + in + let used_storage = Option.value ~default:Z.zero used_storage in + let*! ctxt = + Storage.Sc_rollup.Whitelist_used_storage_space.remove ctxt rollup + in + return (ctxt, used_storage) + +let adjust_storage_space ctxt rollup ~new_storage_size = + let open Lwt_result_syntax in + let* used_storage = + Storage.Sc_rollup.Whitelist_used_storage_space.find ctxt rollup + in + let used_storage = Option.value ~default:Z.zero used_storage in + let storage_diff = Z.sub new_storage_size used_storage in + if Compare.Z.(storage_diff = Z.zero) then return (ctxt, Z.zero) + else + let*! ctxt = + Storage.Sc_rollup.Whitelist_used_storage_space.add + ctxt + rollup + new_storage_size + in + let* paid_storage = + Storage.Sc_rollup.Whitelist_paid_storage_space.find ctxt rollup + in + let paid_storage = Option.value ~default:Z.zero paid_storage in + let diff = Z.sub new_storage_size paid_storage in + if Compare.Z.(Z.zero < diff) then + let*! ctxt = + Storage.Sc_rollup.Whitelist_paid_storage_space.add + ctxt + rollup + new_storage_size + in + return (ctxt, diff) + else return (ctxt, Z.zero) + +let get_last_whitelist_update = Storage.Sc_rollup.Last_whitelist_update.get + +(** TODO: https://gitlab.com/tezos/tezos/-/issues/6186 + Do not consider storage diffs for small updates to the storage. *) +let set_last_whitelist_update ctxt rollup update = + let open Lwt_result_syntax in + let* ctxt, diff_size, _ = + Storage.Sc_rollup.Last_whitelist_update.add ctxt rollup update + in + return (ctxt, Z.of_int diff_size) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.mli new file mode 100644 index 000000000000..9aab7d157283 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_whitelist_storage.mli @@ -0,0 +1,107 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Sc_rollup_whitelist_repr + +(** [is_private context rollup] returns true if and only if the [rollup] + is private, along with the new context accounting for the gas consumption + of the function call. *) +val is_private : + Raw_context.t -> Sc_rollup_repr.t -> (Raw_context.t * bool) tzresult Lwt.t + +(** [init context rollup ~whitelist] returns the new context resulting from + the addition of the elements of [whitelist] to the whitelist in the given + [rollup]'s storage, along with the used storage space. *) +val init : + Raw_context.t -> + Sc_rollup_repr.t -> + whitelist:t -> + origination_level:Raw_level_repr.t -> + (Raw_context.t * Z.t) tzresult Lwt.t + +(** [check_access_to_private_rollup context rollup staker_pkh] returns an error + if [staker_pkh] is not in the whitelist of [rollup] if the [rollup] is marked + as private. Returns the gas consumed by performing the call otherwise. + Assumes the private rollup feature is activated. *) +val check_access_to_private_rollup : + Raw_context.t -> + Sc_rollup_repr.t -> + Signature.public_key_hash -> + Raw_context.t tzresult Lwt.t + +(** [find_whitelist_uncarbonated context rollup] returns the whitelist from the storage. *) +val find_whitelist_uncarbonated : + Raw_context.t -> + Sc_rollup_repr.t -> + Signature.public_key_hash list option tzresult Lwt.t + +(** [replace context rollup ~whitelist] replaces the whitelist of + [rollup] in the storage by [whitelist]. Returns the resulting + context along with the used storage space. *) +val replace : + Raw_context.t -> + Sc_rollup_repr.t -> + whitelist:t -> + (Raw_context.t * Z.t) tzresult Lwt.t + +(** [make_public context rollup] removes the whitelist of [rollup] from + the storage thus making the rollup public. Returns the resulting + context along with the freed storage space. *) +val make_public : + Raw_context.t -> Sc_rollup_repr.t -> (Raw_context.t * Z.t) tzresult Lwt.t + +(** [adjust_storage_space ctxt ~new_storage_size] updates the used + storage space for the whitelist according to + [new_storage_size]. The additional positive amount of unpaid + storage is returned. If no unpaid storage is consumed, this amount + is 0. + + Note that when storage space for the whitelist is released we may later + use that space for free. For this reason, the amount returned may be less + than the given (positive) [storage_diff]. *) +val adjust_storage_space : + Raw_context.t -> + Sc_rollup_repr.t -> + new_storage_size:Z.t -> + (Raw_context.t * Z.t) tzresult Lwt.t + +(** [get_last_whitelist_update ctxt rollup] returns the pair (outbox level, + message index) of the latest message of update to the whitelist. Returns + None if no whitelist update has been applied. The returned context accounts + for the gas consumption of the storage's update. *) +val get_last_whitelist_update : + Raw_context.t -> + Sc_rollup_repr.t -> + (Raw_context.t * last_whitelist_update) tzresult Lwt.t + +(** [set_last_whitelist_update ctxt rollup (outbox_level, message_index)] set + the outbox level and message index of the latest message of update to the + whitelist. Returns the new context, and the difference from the old (maybe 0) + to the new size of the underlying storage. *) +val set_last_whitelist_update : + Raw_context.t -> + Sc_rollup_repr.t -> + last_whitelist_update -> + (Raw_context.t * Z.t) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollups.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollups.ml new file mode 100644 index 000000000000..037a1c54e7ad --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollups.ml @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module PVM = struct + type boot_sector = string + + module type S = sig + val parse_boot_sector : string -> boot_sector option + + val pp_boot_sector : Format.formatter -> boot_sector -> unit + + include Sc_rollup_PVM_sig.S + end + + type ('state, 'proof, 'output) implementation = + (module S + with type state = 'state + and type proof = 'proof + and type output_proof = 'output) + + type t = Packed : ('state, 'proof, 'output) implementation -> t [@@unboxed] +end + +module Kind = struct + (* + Each time we add a data constructor to [t], we also need: + - to extend [Sc_rollups.all] with this new constructor ; + - to update [Sc_rollups.of_string] and [encoding] ; + - to update [Sc_rollups.wrapped_proof] and [wrapped_proof_encoding]. + + *) + type t = Example_arith | Wasm_2_0_0 | Riscv + + let all = [Example_arith; Wasm_2_0_0; Riscv] + + let to_string = function + | Example_arith -> "arith" + | Wasm_2_0_0 -> "wasm_2_0_0" + | Riscv -> "riscv" + + let of_string = function + | "arith" -> Some Example_arith + | "wasm_2_0_0" -> Some Wasm_2_0_0 + | "riscv" -> Some Riscv + | _ -> None + + let encoding = + Data_encoding.string_enum @@ List.map (fun k -> (to_string k, k)) all + + let pp fmt = function + | Example_arith -> Format.pp_print_string fmt "arith" + | Wasm_2_0_0 -> Format.pp_print_string fmt "wasm_2_0_0" + | Riscv -> Format.pp_print_string fmt "riscv" + + let equal x y = + match (x, y) with + | Example_arith, Example_arith -> true + | Wasm_2_0_0, Wasm_2_0_0 -> true + | Riscv, Riscv -> true + | _ -> false + + let example_arith_pvm = + PVM.Packed (module Sc_rollup_arith.Protocol_implementation) + + let wasm_2_0_0_pvm = + PVM.Packed (module Sc_rollup_wasm.V2_0_0.Protocol_implementation) + + let riscv_pvm = PVM.Packed (module Sc_rollup_riscv.Protocol_implementation) + + let pvm_of = function + | Example_arith -> example_arith_pvm + | Wasm_2_0_0 -> wasm_2_0_0_pvm + | Riscv -> riscv_pvm + + let no_proof_machine_of : t -> (module Sc_rollup_machine_no_proofs.S) = + function + | Example_arith -> (module Sc_rollup_machine_no_proofs.Arith) + | Wasm_2_0_0 -> (module Sc_rollup_machine_no_proofs.Wasm) + | Riscv -> (module Sc_rollup_machine_no_proofs.Riscv) +end + +let genesis_state_hash_of ~boot_sector kind = + let open Lwt_syntax in + let (module Machine) = Kind.no_proof_machine_of kind in + let empty = Sc_rollup_machine_no_proofs.empty_tree () in + let* tree = Machine.initial_state ~empty in + let* tree = Machine.install_boot_sector tree boot_sector in + Machine.state_hash tree diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollups.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollups.mli new file mode 100644 index 000000000000..f6df1426ef86 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollups.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Here is the list of PVMs available in this protocol. *) + +module PVM : sig + type boot_sector = string + + module type S = sig + val parse_boot_sector : string -> boot_sector option + + val pp_boot_sector : Format.formatter -> boot_sector -> unit + + include Sc_rollup_PVM_sig.S + end + + type ('state, 'proof, 'output) implementation = + (module S + with type state = 'state + and type proof = 'proof + and type output_proof = 'output) + + type t = Packed : ('state, 'proof, 'output) implementation -> t [@@unboxed] +end + +(** A smart contract rollup has a kind, which assigns meaning to + rollup operations. *) +module Kind : sig + (** + + The list of available rollup kinds. + + This list must only be appended for backward compatibility. + *) + type t = Example_arith | Wasm_2_0_0 | Riscv + + val encoding : t Data_encoding.t + + val equal : t -> t -> bool + + (** [pvm_of kind] returns the [PVM] of the given [kind]. *) + val pvm_of : t -> PVM.t + + (** [all] returns all implemented PVMs. *) + val all : t list + + val of_string : string -> t option + + val to_string : t -> string + + val pp : Format.formatter -> t -> unit +end + +(** [genesis_hash_of machine ~boot_sector] computes the initial state hash of a + rollup given an initial [boot_sector]. *) +val genesis_state_hash_of : + boot_sector:string -> Kind.t -> Sc_rollup_repr.State_hash.t Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/script_big_map.ml b/src/proto_020_PsParisC/lib_protocol/script_big_map.ml new file mode 100644 index 000000000000..d1bd1482a9a7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_big_map.ml @@ -0,0 +1,101 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_typed_ir +open Script_ir_translator + +let empty key_type value_type = + Big_map + { + id = None; + diff = {map = Big_map_overlay.empty; size = 0}; + key_type; + value_type; + } + +let mem ctxt key (Big_map {id; diff; key_type; _}) = + let open Lwt_result_syntax in + let* key_hash, ctxt = hash_comparable_data ctxt key_type key in + match (Big_map_overlay.find key_hash diff.map, id) with + | None, None -> return (false, ctxt) + | None, Some id -> + let+ ctxt, res = Alpha_context.Big_map.mem ctxt id key_hash in + (res, ctxt) + | Some (_, None), _ -> return (false, ctxt) + | Some (_, Some _), _ -> return (true, ctxt) + +let get_by_hash ctxt key (Big_map {id; diff; value_type; _}) = + let open Lwt_result_syntax in + match (Big_map_overlay.find key diff.map, id) with + | Some (_, x), _ -> return (x, ctxt) + | None, None -> return (None, ctxt) + | None, Some id -> ( + let* ctxt, value_opt = Alpha_context.Big_map.get_opt ctxt id key in + match value_opt with + | None -> return (None, ctxt) + | Some value -> + let+ x, ctxt = + parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:true ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + value_type + (Micheline.root value) + in + (Some x, ctxt)) + +let get ctxt key (Big_map {key_type; _} as map) = + let open Lwt_result_syntax in + let* key_hash, ctxt = hash_comparable_data ctxt key_type key in + get_by_hash ctxt key_hash map + +let update_by_hash key_hash key value (Big_map map) = + let contains = Big_map_overlay.mem key_hash map.diff.map in + Big_map + { + map with + diff = + { + map = Big_map_overlay.add key_hash (key, value) map.diff.map; + size = (if contains then map.diff.size else map.diff.size + 1); + }; + } + +let update ctxt key value (Big_map {key_type; _} as map) = + let open Lwt_result_syntax in + let* key_hash, ctxt = hash_comparable_data ctxt key_type key in + let map = update_by_hash key_hash key value map in + return (map, ctxt) + +let get_and_update ctxt key value (Big_map {key_type; _} as map) = + let open Lwt_result_syntax in + let* key_hash, ctxt = hash_comparable_data ctxt key_type key in + let new_map = update_by_hash key_hash key value map in + let* old_value, ctxt = get_by_hash ctxt key_hash map in + return ((old_value, new_map), ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/script_big_map.mli b/src/proto_020_PsParisC/lib_protocol/script_big_map.mli new file mode 100644 index 000000000000..62fac92a1846 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_big_map.mli @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** [empty] is the big map with no bindings. *) +val empty : + 'a Script_typed_ir.comparable_ty -> + ('b, _) Script_typed_ir.ty -> + ('a, 'b) Script_typed_ir.big_map + +(** [mem ctxt key big_map] returns [true] iff [key] is bound in the + given [big_map]. + Consumes the cost of hashing the given key. + Consumes as [Storage.Big_map.Contents.mem] if the key is not bound + yet in the current overlay. *) +val mem : + context -> + 'key -> + ('key, 'value) Script_typed_ir.big_map -> + (bool * context) tzresult Lwt.t + +(** [get ctxt key big_map] returns the value bound by [key] in the + given [big_map]. If the [key] is not bound, [None] is returned instead. + Consumes cost of hashing the given key. + Consumes cost as [Storage.Big_map.Contents.find] in case of the given key + is absent in the current overlay. + Consumes cost of parsing data if the value is readed from storage. *) +val get : + context -> + 'key -> + ('key, 'value) Script_typed_ir.big_map -> + ('value option * context) tzresult Lwt.t + +(** [update ctxt key new_value big_map] updates the value bound by [key] + with [v] if the [new_value] is [Some v]. When the [new_value] is [None], + delete the entire entry bound by [key] in the [big_map]. + Consumes cost for hashing the given key. + See {!get_and_update} for details. *) +val update : + context -> + 'key -> + 'value option -> + ('key, 'value) Script_typed_ir.big_map -> + (('key, 'value) Script_typed_ir.big_map * context) tzresult Lwt.t + +(** [get_and_update ctxt key new_value big_map] works just like + [update ctxt key new_value big_map] except it also returns + the old value bound by [key]. + Consumes cost for hashing the given key. + This does {i not} modify the underlying storage, only the diff table. *) +val get_and_update : + context -> + 'key -> + 'value option -> + ('key, 'value) Script_typed_ir.big_map -> + (('value option * ('key, 'value) Script_typed_ir.big_map) * context) tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/script_bytes.ml b/src/proto_020_PsParisC/lib_protocol/script_bytes.ml new file mode 100644 index 000000000000..aa0685a22a6e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_bytes.ml @@ -0,0 +1,204 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Bytes + +let bytes_and = logand + +let bytes_or = logor + +let bytes_xor = logxor + +let bytes_not = lognot + +let bytes_lsl a n = + (* We have to limit the number of shifts for LSL *) + match Script_int.to_int n with + | Some n when Compare.Int.(n <= 64000) -> Some (shift_left a n) + | _ -> None + +let bytes_lsr a n = + (* No limit on the number of shifts for LSR *) + match Script_int.to_int n with + | None -> + (* [LSR bytes max_int] can shift out completely the longest + possible [bytes]. *) + Bytes.empty + | Some n -> shift_right a n + +module Conversion_BE : sig + (** Convert a natural number to bytes using big-endian encoding. + + Returns [None] when the argument is negative. + + Examples: + + - [bytes_of_nat_be (Z.of_int 0x00) = Some Bytes.empty] + - [bytes_of_nat_be (Z.of_int 0x01) = Some (Bytes.of_string "\x01")] + - [bytes_of_nat_be (Z.of_int 0xff) = Some (Bytes.of_string "\xff")] + - [bytes_of_nat_be (Z.of_int 0x100) = Some (Bytes.of_strnig "\x01\x00")] + - [bytes_of_nat_be (Z.of_int (-1)) = None] + *) + val bytes_of_nat_be : Z.t -> bytes option + + (** Convert bytes to a natural number using big-endian encoding. + + Examples: + + - [nat_of_bytes_be Bytes.empty = Z.of_int 0x00] + - [nat_of_bytes_be (Bytes.of_string "\x00") = Z.of_int 0x00] + - [nat_of_bytes_be (Bytes.of_string "\x01") = Z.of_int 0x01] + - [nat_of_bytes_be (Bytes.of_string "\x00\x01") = Z.of_int 0x01] + - [nat_of_bytes_be (Bytes.of_string "\xff") = Z.of_int 0xff] + - [nat_of_bytes_be (Bytes.of_string "\x00\x00\xff") = Z.of_int 0xff] + - [nat_of_bytes_be (Bytes.of_string "\x01\x00") = Z.of_int 0x0100] + *) + val nat_of_bytes_be : bytes -> Z.t + + (** Convert an integer to bytes using big-endian encoding. + Negative numbers are handled by two's-complement. + + Examples: + + - [bytes_of_int_be (Z.of_int 0x00) = Bytes.empty] + - [bytes_of_int_be (Z.of_int 0x01) = Bytes.of_string "\x01"] + - [bytes_of_int_be (Z.of_int 0x7f) = Bytes.of_string "\x7f"] + - [bytes_of_int_be (Z.of_int (-0x80)) = Bytes.of_string "\x80"] + - [bytes_of_int_be (Z.of_int 0x80) = Bytes.of_string "\x00\x80"] (not ["\x80"]) + - [bytes_of_int_be (Z.of_int (-0x81)) = Bytes.of_string "\xff\x7f"] (not ["\x7f"]) + - [bytes_of_int_be (Z.of_int 0x8000) = Bytes.of_string "\x00\x80\x00"], (not ["\x80\x00"]) + *) + val bytes_of_int_be : Z.t -> bytes + + (** Convert bytes to an integer using big-endian encoding. + Negative numbers are handled by two's-complement. + + Examples: + + - [int_of_bytes_be Bytes.empty = Z.of_int 0x00] + - [int_of_bytes_be (Bytes.of_string "\x01") = Z.of_int 0x01] + - [int_of_bytes_be (Bytes.of_string "\x00\x01") = Z.of_int 0x01] + - [int_of_bytes_be (Bytes.of_string "\x7f") = Z.of_int 0x7f] + - [int_of_bytes_be (Bytes.of_string "\x00\x7f") = Z.of_int 0x7f] + - [int_of_bytes_be (Bytes.of_string "\x80") = Z.of_int (-0x80)] (not [0x80]) + - [int_of_bytes_be (Bytes.of_string "\xff\x80") = Z.of_int (-0x80)] + - [int_of_bytes_be (Bytes.of_string "\xff\x8f") = Z.of_int (-0x81)] + *) + val int_of_bytes_be : bytes -> Z.t +end = struct + let encode_nat_be nbytes default z = + (* [nbytes] is the exact number of the bytes to encode [z]. + + When encoding an integer to bytes, it is first converted to + a natural number using 2's complement, and then sent to this function. + [default] is the prefix byte which may be required for the integer + encoding. [Some '\000'] when the integer is zero or positive. + [Some '\255'] when negative. + *) + assert (Compare.Z.(z >= Z.zero)) ; + (* [Z.to_bits] encodes zero and positive numbers in the little endian. + The result string can be zero trailed to make its length multiple + of 4 or 8. + *) + let string_le = Z.to_bits z in + let slen = String.length string_le in + (* If [slen = nbytes]: + string_le aabbcc + the final output ccbbaa + + else if [slen > nbytes]: + string_le aabbcc0000 + the final output ccbbaa + + else if [slen < nbytes] and [default= Some DD]: + This is to encode an integer which requires an extra byte. + string_le aabbcc + encoded DDccbbaa + + otherwise: error, which should not happen. + *) + Bytes.init nbytes (fun i -> + let j = nbytes - i - 1 in + if Compare.Int.(j >= slen) then + Option.value_f default ~default:(fun () -> + assert false (* it never happens *)) + else string_le.[j]) + + let bytes_of_nat_be z = + match Z.compare z Z.zero with + | -1 -> None + | 0 -> Some Bytes.empty + | _ -> + let nbits = Z.log2up (Z.succ z) in + let nbytes = (nbits + 7) / 8 in + Some (encode_nat_be nbytes None z) + + let bytes_of_int_be z = + match Z.compare z Z.zero with + | 0 -> Bytes.empty + | 1 -> + let nbits = Z.log2up (Z.succ z) + 1 (* The top bit must be 0 *) in + let nbytes = (nbits + 7) / 8 in + encode_nat_be nbytes (Some '\000') z + | _ -> + let nbits = Z.log2up Z.(neg z) + 1 (* The top bit must be 1 *) in + let nbytes = (nbits + 7) / 8 in + let nbits' = nbytes * 8 in + let z'' = Z.(add (shift_left one nbits') z) in + encode_nat_be nbytes (Some '\255') z'' + + let nat_of_bytes_be bytes = + (* [Z.of_bits] ignores trailing zeros *) + let len = Bytes.length bytes in + (* Z.of_bits uses little-endian encoding but we want a big-endian + encoding so we reverse [bytes] while converting it to `string`. *) + Z.of_bits @@ String.init len (fun i -> Bytes.get bytes (len - i - 1)) + + let int_of_bytes_be bytes = + let nbytes = Bytes.length bytes in + if Compare.Int.(nbytes = 0) then Z.zero + else + let top_bit = Compare.Int.(Char.code (Bytes.get bytes 0) land 128 <> 0) in + if top_bit then + (* negative *) + let z = nat_of_bytes_be bytes in + let nbits = nbytes * 8 in + Z.(sub z (shift_left one nbits)) + else nat_of_bytes_be bytes +end + +open Script_int + +let bytes_of_nat_be (n : n num) = + (* The function always succeeds since the argument is 0 or positive *) + match Conversion_BE.bytes_of_nat_be @@ to_zint n with + | Some bytes -> bytes + | None -> assert false + +let nat_of_bytes_be b = abs @@ of_zint @@ Conversion_BE.nat_of_bytes_be b + +let bytes_of_int_be (z : z num) = Conversion_BE.bytes_of_int_be @@ to_zint z + +let int_of_bytes_be b = of_zint @@ Conversion_BE.int_of_bytes_be b diff --git a/src/proto_020_PsParisC/lib_protocol/script_bytes.mli b/src/proto_020_PsParisC/lib_protocol/script_bytes.mli new file mode 100644 index 000000000000..c37bccfe4a63 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_bytes.mli @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Semantics of logical and bit-shift operators for bytes *) + +(** [bytes_or a b] returns the logical or'ed bytes of [a] and [b]. + If the arguments have different lengths, the shorter one is 0-padded + on the left before the logical operation. For example: + + 0x1200 OR 0x34 = 0x1200 OR 0x0034 = 0x1234 + 0x0012 OR 0xff = 0x0012 OR 0x00ff = 0x00ff (instead of 0xff) +*) +val bytes_or : bytes -> bytes -> bytes + +(** [bytes_and a b] returns the logical and'ed bytes of [a] and [b]. + If the arguments have different lengths, the prefix of the longer one + is removed to have the same length as the shorter one before the logical + operation. For example: + + 0x1234 AND 0x30 = 0x34 AND 0x30 = 0x30 + 0x12f00f AND 0x0fff = 0xf00f AND 0x0fff = 0x000f (instead of 0x0f) +*) +val bytes_and : bytes -> bytes -> bytes + +(** [bytes_xor a b] returns the logical xor'ed bytes of [a] and [b]. + If the arguments have different lengths, the shorter one is 0-padded + on the left before the logical operation. For example: + + 0x1200 XOR 0x34 = 0x1200 XOR 0x0034 = 0x1234 + 0x0012 XOR 0xff = 0x0012 XOR 0x00ff = 0x00ed (instead of 0xed) +*) +val bytes_xor : bytes -> bytes -> bytes + +(** [bytes_not a] returns the logical not'ed bytes of [a] with the same + length of [a]. For example: + + NOT 0xff00 = 0x00ff (instead of 0xff) +*) +val bytes_not : bytes -> bytes + +(** [bytes_lsl bytes bits] returns the [bits] left shifted bytes of [bytes]. + If [bits] is more than 64000, it returns [None]. + + The function always returns a longer bytes of the input if [bits] + is not 0. For example: + + 0x12 LSL 1 = 0x0024 (instead of 0x24) + 0x0012 LSL 9 = 0x00002400 (instead of 0x002400 or 0x2400) +*) +val bytes_lsl : bytes -> Script_int.n Script_int.num -> bytes option + +(** [bytes_lsr bytes bits] returns the [bits] right shifted bytes of [bytes]. + + 0x1234 LSR 1 = 0x091a + 0x1234 LSR 8 = 0x12 (instead of 0x0012) +*) +val bytes_lsr : bytes -> Script_int.n Script_int.num -> bytes + +(** Convert a natural number to bytes using big-endian encoding. *) +val bytes_of_nat_be : Script_int.n Script_int.num -> bytes + +(** Convert bytes to a natural number using big-endian encoding. *) +val nat_of_bytes_be : bytes -> Script_int.n Script_int.num + +(** Convert an integer to bytes using big-endian encoding. + Negative numbers are handled by two's-complement. *) +val bytes_of_int_be : Script_int.z Script_int.num -> bytes + +(** Convert bytes to an integer using big-endian encoding. + Negative numbers are handled by two's-complement. *) +val int_of_bytes_be : bytes -> Script_int.z Script_int.num + +module Conversion_BE : sig + val bytes_of_nat_be : Z.t -> bytes option + + val nat_of_bytes_be : bytes -> Z.t + + val bytes_of_int_be : Z.t -> bytes + + val int_of_bytes_be : bytes -> Z.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_cache.ml b/src/proto_020_PsParisC/lib_protocol/script_cache.ml new file mode 100644 index 000000000000..70a79eb8f447 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_cache.ml @@ -0,0 +1,126 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type identifier = string + +let identifier_of_contract addr = Contract_hash.to_b58check addr + +let contract_of_identifier identifier = + let open Result_syntax in + match Contract_hash.of_b58check_opt identifier with + | Some addr -> return addr + | None -> tzfail (Contract_repr.Invalid_contract_notation identifier) + +type cached_contract = Script.t * Script_ir_translator.ex_script + +let load_and_elaborate ctxt addr = + let open Lwt_result_syntax in + let* ctxt, script = Contract.get_script ctxt addr in + match script with + | None -> return (ctxt, None) + | Some script -> + Script_ir_translator.( + let* ex_script, ctxt = + parse_script + ctxt + script + ~elab_conf:Script_ir_translator_config.(make ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + in + (* We consume gas after the fact in order to not have to instrument + [script_size] (for efficiency). + This is safe, as we already pay gas proportional to storage size + in [parse_script] beforehand. *) + let size, cost = script_size ex_script in + let*? ctxt = Gas.consume ctxt cost in + return (ctxt, Some (script, ex_script, size))) + +module Client = struct + type cached_value = cached_contract + + let namespace = Cache.create_namespace "contract" + + let cache_index = 0 + + let value_of_identifier ctxt identifier = + let open Lwt_result_syntax in + (* + + I/O, deserialization, and elaboration of contracts scripts + are cached. + + *) + let*? addr = contract_of_identifier identifier in + let* (_ : context), result = load_and_elaborate ctxt addr in + match result with + | None -> + (* [value_of_identifier ctxt k] is applied to identifiers stored + in the cache. Only script-based contracts that have been + executed are in the cache. Hence, [get_script] always + succeeds for these identifiers if [ctxt] and the [cache] are + properly synchronized by the shell. *) + failwith "Script_cache: Inconsistent script cache." + | Some (unparsed_script, ir_script, _) -> return (unparsed_script, ir_script) +end + +module Cache = (val Cache.register_exn (module Client)) + +let find ctxt addr = + let open Lwt_result_syntax in + let identifier = identifier_of_contract addr in + let* contract_opt = Cache.find ctxt identifier in + match contract_opt with + | Some (unparsed_script, ex_script) -> + return (ctxt, identifier, Some (unparsed_script, ex_script)) + | None -> ( + let* ctxt, result = load_and_elaborate ctxt addr in + match result with + | None -> return (ctxt, identifier, None) + | Some (unparsed_script, script_ir, size) -> + let cached_value = (unparsed_script, script_ir) in + let*? ctxt = + Cache.update ctxt identifier (Some (cached_value, size)) + in + return (ctxt, identifier, Some (unparsed_script, script_ir))) + +let update ctxt identifier updated_script approx_size = + Cache.update ctxt identifier (Some (updated_script, approx_size)) + +let entries ctxt = + let open Result_syntax in + Cache.list_identifiers ctxt + |> List.map_e @@ fun (identifier, age) -> + let+ contract = contract_of_identifier identifier in + (contract, age) + +let contract_rank ctxt addr = + Cache.identifier_rank ctxt (identifier_of_contract addr) + +let size = Cache.size + +let size_limit = Cache.size_limit diff --git a/src/proto_020_PsParisC/lib_protocol/script_cache.mli b/src/proto_020_PsParisC/lib_protocol/script_cache.mli new file mode 100644 index 000000000000..0e9ddbd1e637 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_cache.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module manages the cache for smart contracts. + + This cache must be consistent with the on-disk representation + of the smart contracts. In particular, [update] must be called + each time a contract storage is updated. + +*) + +open Alpha_context + +(** Each cached script has a unique identifier in the cache. *) +type identifier + +(** The cache holds the unparsed and the internal representation of + the contract. *) +type cached_contract = Script.t * Script_ir_translator.ex_script + +(** [find ctxt contract] returns [(ctxt', identifier, script)] where: + - [ctxt'] is [ctxt] with less gas; + - [identifier] is the identifier identifying the [contract] in the cache; + - [script = None] if there is no such contract in [ctxt]; + - [script = Some (unparsed_script, ir_script)] where + - [unparsed_script] is the contract code and storage; + - [script_ir] is a typed internal representation of the contract, i.e., + the abstract syntax tree of its code as well as its storage. + + This function consumes gas depending on the cache. If the contract is not + in the cache, then the function also consumes the gas of [Contract.get_script] + and [Script_ir_translator.parse_script]. *) +val find : + context -> + Contract_hash.t -> + (context * identifier * cached_contract option) tzresult Lwt.t + +(** [update ctxt identifier unparsed_script ir_script size] refreshes the + cached contract identified by [identifier] with a new [unparsed_script], + a new [ir_script], and a new size. *) +val update : context -> identifier -> cached_contract -> int -> context tzresult + +(** [entries ctxt] returns the contracts in the cache as well as their + respective size. The list is sorted by date of last modification: + the least recently updated entry comes first. *) +val entries : context -> (Contract_hash.t * int) list tzresult + +(** [contract_rank ctxt contract] returns the number of contracts + older than [contract] in the cache of [ctxt]. This function + returns [None] if [contract] does not exist in the cache of + [ctxt]. *) +val contract_rank : context -> Contract_hash.t -> int option + +(** [size ctxt] is an overapproximation of the cache size in + memory (in bytes). *) +val size : context -> int + +(** [size_limit ctxt] is the maximal size of the cache (in bytes). *) +val size_limit : context -> int diff --git a/src/proto_020_PsParisC/lib_protocol/script_comparable.ml b/src/proto_020_PsParisC/lib_protocol/script_comparable.ml new file mode 100644 index 000000000000..5ef9466d0ba5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_comparable.ml @@ -0,0 +1,89 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_typed_ir + +let compare_address {destination = destination1; entrypoint = entrypoint1} + {destination = destination2; entrypoint = entrypoint2} = + let lres = Destination.compare destination1 destination2 in + if Compare.Int.(lres = 0) then Entrypoint.compare entrypoint1 entrypoint2 + else lres + +type compare_comparable_cont = + | Compare_comparable : + 'a comparable_ty * 'a * 'a * compare_comparable_cont + -> compare_comparable_cont + | Compare_comparable_return : compare_comparable_cont + +let compare_comparable : type a. a comparable_ty -> a -> a -> int = + let rec compare_comparable : + type a. a comparable_ty -> compare_comparable_cont -> a -> a -> int = + fun kind k x y -> + match (kind, x, y) with + | Unit_t, (), () -> (apply [@tailcall]) 0 k + | Never_t, _, _ -> . + | Signature_t, x, y -> (apply [@tailcall]) (Script_signature.compare x y) k + | String_t, x, y -> (apply [@tailcall]) (Script_string.compare x y) k + | Bool_t, x, y -> (apply [@tailcall]) (Compare.Bool.compare x y) k + | Mutez_t, x, y -> (apply [@tailcall]) (Tez.compare x y) k + | Key_hash_t, x, y -> + (apply [@tailcall]) (Signature.Public_key_hash.compare x y) k + | Key_t, x, y -> (apply [@tailcall]) (Signature.Public_key.compare x y) k + | Int_t, x, y -> (apply [@tailcall]) (Script_int.compare x y) k + | Nat_t, x, y -> (apply [@tailcall]) (Script_int.compare x y) k + | Timestamp_t, x, y -> (apply [@tailcall]) (Script_timestamp.compare x y) k + | Address_t, x, y -> (apply [@tailcall]) (compare_address x y) k + | Bytes_t, x, y -> (apply [@tailcall]) (Compare.Bytes.compare x y) k + | Chain_id_t, x, y -> (apply [@tailcall]) (Script_chain_id.compare x y) k + | Pair_t (tl, tr, _, YesYes), (lx, rx), (ly, ry) -> + (compare_comparable [@tailcall]) + tl + (Compare_comparable (tr, rx, ry, k)) + lx + ly + | Or_t (tl, _, _, YesYes), L x, L y -> + (compare_comparable [@tailcall]) tl k x y + | Or_t _, L _, R _ -> -1 + | Or_t _, R _, L _ -> 1 + | Or_t (_, tr, _, YesYes), R x, R y -> + (compare_comparable [@tailcall]) tr k x y + | Option_t _, None, None -> (apply [@tailcall]) 0 k + | Option_t _, None, Some _ -> -1 + | Option_t _, Some _, None -> 1 + | Option_t (t, _, Yes), Some x, Some y -> + (compare_comparable [@tailcall]) t k x y + and apply ret k = + match (ret, k) with + | 0, Compare_comparable (ty, x, y, k) -> + (compare_comparable [@tailcall]) ty k x y + | 0, Compare_comparable_return -> 0 + | ret, _ -> + (* ret <> 0, we perform an early exit *) + if Compare.Int.(ret > 0) then 1 else -1 + in + fun t -> compare_comparable t Compare_comparable_return diff --git a/src/proto_020_PsParisC/lib_protocol/script_comparable.mli b/src/proto_020_PsParisC/lib_protocol/script_comparable.mli new file mode 100644 index 000000000000..8f489511625a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_comparable.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val compare_comparable : 'a Script_typed_ir.comparable_ty -> 'a -> 'a -> int + +val compare_address : Script_typed_ir.address -> Script_typed_ir.address -> int diff --git a/src/proto_020_PsParisC/lib_protocol/script_expr_hash.ml b/src/proto_020_PsParisC/lib_protocol/script_expr_hash.ml new file mode 100644 index 000000000000..4b26c6d4234d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_expr_hash.ml @@ -0,0 +1,44 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let script_expr_hash = "\013\044\064\027" (* expr(54) *) + +module H = + Blake2B.Make + (Base58) + (struct + let name = "script_expr" + + let title = "A script expression ID" + + let b58check_prefix = script_expr_hash + + let size = None + end) + +include H +include Path_encoding.Make_hex (H) + +let () = Base58.check_encoded_prefix b58check_encoding "expr" 54 diff --git a/src/proto_020_PsParisC/lib_protocol/script_expr_hash.mli b/src/proto_020_PsParisC/lib_protocol/script_expr_hash.mli new file mode 100644 index 000000000000..8ba38e2eaaf5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_expr_hash.mli @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A specialized Blake2B implementation for hashing Michelson expressions. *) + +include S.HASH + +include Path_encoding.S with type t := t diff --git a/src/proto_020_PsParisC/lib_protocol/script_int.ml b/src/proto_020_PsParisC/lib_protocol/script_int.ml new file mode 100644 index 000000000000..0fe44ad35b49 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_int.ml @@ -0,0 +1,126 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type n = Natural_tag + +type z = Integer_tag + +(* We could define `num` as a GADT with constructors for `n` and `z`. + This would enable factorizing the code a bit in the Michelson interpreter and + also make formal the claim that `num` is only instantiated with `n` and `z`, + but it would result in space and time overheads when manipulating `num`s, by + having to deconstruct to and reconstruct from `Z.t`. *) +type 't repr = Z.t + +type 't num = Num_tag of 't repr [@@ocaml.unboxed] + +let compare (Num_tag x) (Num_tag y) = Z.compare x y + +let zero = Num_tag Z.zero + +let one = Num_tag Z.one + +let zero_n = Num_tag Z.zero + +let one_n = Num_tag Z.one + +let to_string (Num_tag x) = Z.to_string x + +let of_string s = Option.catch (fun () -> Num_tag (Z.of_string s)) + +let of_int32 n = Num_tag (Z.of_int64 @@ Int64.of_int32 n) + +let to_int64 (Num_tag x) = Option.catch (fun () -> Z.to_int64 x) + +let of_int64 n = Num_tag (Z.of_int64 n) + +let to_int (Num_tag x) = Option.catch (fun () -> Z.to_int x) + +let of_int n = Num_tag (Z.of_int n) + +let of_zint x = Num_tag x + +let to_zint (Num_tag x) = x + +let add (Num_tag x) (Num_tag y) = Num_tag (Z.add x y) + +let sub (Num_tag x) (Num_tag y) = Num_tag (Z.sub x y) + +let mul (Num_tag x) (Num_tag y) = Num_tag (Z.mul x y) + +let ediv (Num_tag x) (Num_tag y) = + let ediv_tagged x y = + let quo, rem = Z.ediv_rem x y in + (Num_tag quo, Num_tag rem) + in + Option.catch (fun () -> ediv_tagged x y) + +let add_n = add + +let succ_n (Num_tag x) = Num_tag (Z.succ x) + +let mul_n = mul + +let ediv_n = ediv + +let abs (Num_tag x) = Num_tag (Z.abs x) + +let is_nat (Num_tag x) = + if Compare.Z.(x < Z.zero) then None else Some (Num_tag x) + +let neg (Num_tag x) = Num_tag (Z.neg x) + +let int (Num_tag x) = Num_tag x + +let shift_left (Num_tag x) (Num_tag y) = + if Compare.Int.(Z.compare y (Z.of_int 256) > 0) then None + else + let y = Z.to_int y in + Some (Num_tag (Z.shift_left x y)) + +let shift_right (Num_tag x) (Num_tag y) = + if Compare.Int.(Z.compare y (Z.of_int 256) > 0) then None + else + let y = Z.to_int y in + Some (Num_tag (Z.shift_right x y)) + +let shift_left_n = shift_left + +let shift_right_n = shift_right + +let logor (Num_tag x) (Num_tag y) = Num_tag (Z.logor x y) + +let logxor (Num_tag x) (Num_tag y) = Num_tag (Z.logxor x y) + +let logand (Num_tag x) (Num_tag y) = Num_tag (Z.logand x y) + +let lognot (Num_tag x) = Num_tag (Z.lognot x) + +let z_encoding : z num Data_encoding.encoding = + Data_encoding.(conv (fun (Num_tag z) -> z) (fun z -> Num_tag z) z) + +let n_encoding : n num Data_encoding.encoding = + Data_encoding.(conv (fun (Num_tag n) -> n) (fun n -> Num_tag n) n) diff --git a/src/proto_020_PsParisC/lib_protocol/script_int.mli b/src/proto_020_PsParisC/lib_protocol/script_int.mli new file mode 100644 index 000000000000..e31ad5646d91 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_int.mli @@ -0,0 +1,168 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The types for arbitrary precision integers in Michelson. + The type variable ['t] is always [n] or [z], + [n num] and [z num] are incompatible. + + This is internally a [Z.t]. + This module mostly adds signedness preservation guarantees. *) +type 't repr + +(** [num] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) +type 't num = Num_tag of 't repr [@@ocaml.unboxed] + +(** Flag for natural numbers. *) +type n = Natural_tag + +(** Flag for relative numbers. *) +type z = Integer_tag + +(** Natural zero. *) +val zero_n : n num + +(** Natural one. *) +val one_n : n num + +(** Natural successor. + + [succ_n x] is the same as [add_n one_n]. + *) +val succ_n : n num -> n num + +(** Relative zero. *) +val zero : z num + +(** Relative one. *) +val one : z num + +(** Compare two numbers as if they were *) +val compare : 'a num -> 'a num -> int + +(** Conversion to an OCaml [string] in decimal notation. *) +val to_string : _ num -> string + +(** Conversion from an OCaml [string]. + Returns [None] in case of an invalid notation. + Supports [+] and [-] sign modifiers, and [0x], [0o] and [0b] base modifiers. *) +val of_string : string -> z num option + +(** Conversion from an OCaml [int32]. *) +val of_int32 : int32 -> z num + +(** Conversion to an OCaml [int64], returns [None] on overflow. *) +val to_int64 : _ num -> int64 option + +(** Conversion from an OCaml [int64]. *) +val of_int64 : int64 -> z num + +(** Conversion to an OCaml [int], returns [None] on overflow. *) +val to_int : _ num -> int option + +(** Conversion from an OCaml [int]. *) +val of_int : int -> z num + +(** Conversion from a Zarith integer ([Z.t]). *) +val of_zint : Z.t -> z num + +(** Conversion to a Zarith integer ([Z.t]). *) +val to_zint : 'a num -> Z.t + +(** Addition between naturals. *) +val add_n : n num -> n num -> n num + +(** Multiplication with a natural. *) +val mul_n : n num -> 'a num -> 'a num + +(** Euclidean division of a natural. + [ediv_n n d] returns [None] if divisor is zero, + or [Some (q, r)] where [n = d * q + r] and [[0 <= r < d]] otherwise. *) +val ediv_n : n num -> 'a num -> ('a num * n num) option + +(** Sign agnostic addition. + Use {!add_n} when working with naturals to preserve the sign. *) +val add : _ num -> _ num -> z num + +(** Sign agnostic subtraction. *) +val sub : _ num -> _ num -> z num + +(** Sign agnostic multiplication. + Use {!mul_n} when working with a natural to preserve the sign. *) +val mul : _ num -> _ num -> z num + +(** Sign agnostic euclidean division. + [ediv n d] returns [None] if divisor is zero, + or [Some (q, r)] where [n = d * q + r] and [[0 <= r < |d|]] otherwise. + Use {!ediv_n} when working with a natural to preserve the sign. *) +val ediv : _ num -> _ num -> (z num * n num) option + +(** Compute the absolute value of a relative, turning it into a natural. *) +val abs : z num -> n num + +(** Partial identity over [N]. *) +val is_nat : z num -> n num option + +(** Negates a number. *) +val neg : _ num -> z num + +(** Turns a natural into a relative, not changing its value. *) +val int : n num -> z num + +(** Reverses each bit in the representation of the number. + Also applies to the sign. *) +val lognot : _ num -> z num + +(** Shifts the natural to the left of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_left_n : n num -> n num -> n num option + +(** Shifts the natural to the right of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_right_n : n num -> n num -> n num option + +(** Shifts the number to the left of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_left : 'a num -> n num -> 'a num option + +(** Shifts the number to the right of a number of bits between 0 and 256. + Returns [None] if the amount is too high. *) +val shift_right : 'a num -> n num -> 'a num option + +(** Applies a boolean or operation to each bit. *) +val logor : 'a num -> 'a num -> 'a num + +(** Applies a boolean and operation to each bit. *) +val logand : _ num -> n num -> n num + +(** Applies a boolean xor operation to each bit. *) +val logxor : n num -> n num -> n num + +(** Naturals are encoded using Data_encoding.n *) +val n_encoding : n num Data_encoding.encoding + +(** Integers are encoded using Data_encoding.z *) +val z_encoding : z num Data_encoding.encoding diff --git a/src/proto_020_PsParisC/lib_protocol/script_interpreter.ml b/src/proto_020_PsParisC/lib_protocol/script_interpreter.ml new file mode 100644 index 000000000000..7ffcfcabc21e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_interpreter.ml @@ -0,0 +1,1997 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + + This module implements an interpreter for Michelson. It takes the + form of a [step] function that interprets script instructions in a + dedicated abstract machine. + + The interpreter is written in a small-step style: an execution + [step] only interprets a single instruction by updating the + configuration of a dedicated abstract machine. + + This abstract machine has two components: + + - a stack to control which instructions must be executed ; and + + - a stack of values where instructions get their inputs and put + their outputs. + + In addition, the machine has access to effectful primitives to + interact with the execution environment (e.g. the Tezos + node). These primitives live in the [Lwt+State+Error] monad. Hence, + this interpreter produces a computation in the [Lwt+State+Error] + monad. + + This interpreter enjoys the following properties: + + - The interpreter is tail-recursive, hence it is robust to stack + overflow. This property is checked by the compiler thanks to the + [@ocaml.tailcall] annotation of each recursive call. + + - The interpreter is type-preserving. Thanks to GADTs, the typing + rules of Michelson are statically checked by the OCaml typechecker: + a Michelson program cannot go wrong. + + - The interpreter is tagless. Thanks to GADTs, the exact shape of + the stack is known statically so the interpreter does not have to + check that the input stack has the shape expected by the + instruction to be executed. + + Outline + ======= + + This file is organized as follows: + + 1. Definition of runtime errors. + + 2. Interpretation loop: This is the main functionality of this + module, aka the [step] function. + + 3. Interface functions: This part of the module builds high-level + functions on top of the more basic [step] function. + + Auxiliary definitions can be found in {!Script_interpreter_defs}. + + Implementation details are explained along the file. + +*) + +open Alpha_context +open Script_typed_ir +open Script_ir_translator +open Local_gas_counter +open Script_interpreter_defs +module S = Saturation_repr + +type step_constants = Script_typed_ir.step_constants = { + sender : Destination.t; + payer : Signature.public_key_hash; + self : Contract_hash.t; + amount : Tez.t; + balance : Tez.t; + chain_id : Chain_id.t; + now : Script_timestamp.t; + level : Script_int.n Script_int.num; +} + +(* ---- Run-time errors -----------------------------------------------------*) + +type error += Reject of Script.location * Script.expr * execution_trace option + +type error += Overflow of Script.location * execution_trace option + +type error += Runtime_contract_error of Contract_hash.t + +type error += Bad_contract_parameter of Contract.t (* `Permanent *) + +type error += Cannot_serialize_failure + +type error += Cannot_serialize_storage + +type error += Michelson_too_many_recursive_calls + +let () = + let open Data_encoding in + let trace_encoding : Script_typed_ir.execution_trace encoding = + list + @@ obj3 + (req "location" Script.location_encoding) + (req "gas" Gas.Arith.z_fp_encoding) + (req "stack" (list Script.expr_encoding)) + in + (* Reject *) + register_error_kind + `Temporary + ~id:"michelson_v1.script_rejected" + ~title:"Script failed" + ~description:"A FAILWITH instruction was reached" + (obj3 + (req "location" Script.location_encoding) + (req "with" Script.expr_encoding) + (opt "trace" trace_encoding)) + (function Reject (loc, v, trace) -> Some (loc, v, trace) | _ -> None) + (fun (loc, v, trace) -> Reject (loc, v, trace)) ; + (* Overflow *) + register_error_kind + `Temporary + ~id:"michelson_v1.script_overflow" + ~title:"Script failed (overflow error)" + ~description: + "While interpreting a Michelson script, an overflow was detected" + (obj2 + (req "location" Script.location_encoding) + (opt "trace" trace_encoding)) + (function Overflow (loc, trace) -> Some (loc, trace) | _ -> None) + (fun (loc, trace) -> Overflow (loc, trace)) ; + (* Runtime contract error *) + register_error_kind + `Temporary + ~id:"michelson_v1.runtime_error" + ~title:"Script runtime error" + ~description:"Toplevel error for all runtime script errors" + (obj2 + (req "contract_handle" Contract.originated_encoding) + (req "contract_code" (constant "Deprecated"))) + (function + | Runtime_contract_error contract -> Some (contract, ()) | _ -> None) + (fun (contract, ()) -> Runtime_contract_error contract) ; + (* Bad contract parameter *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_contract_parameter" + ~title:"Contract supplied an invalid parameter" + ~description: + "Either no parameter was supplied to a contract with a non-unit \ + parameter type, a non-unit parameter was passed to an account, or a \ + parameter was supplied of the wrong type" + Data_encoding.(obj1 (req "contract" Contract.encoding)) + (function Bad_contract_parameter c -> Some c | _ -> None) + (fun c -> Bad_contract_parameter c) ; + (* Cannot serialize failure *) + register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_failure" + ~title:"Not enough gas to serialize argument of FAILWITH" + ~description: + "Argument of FAILWITH was too big to be serialized with the provided gas" + Data_encoding.empty + (function Cannot_serialize_failure -> Some () | _ -> None) + (fun () -> Cannot_serialize_failure) ; + (* Cannot serialize storage *) + register_error_kind + `Temporary + ~id:"michelson_v1.cannot_serialize_storage" + ~title:"Not enough gas to serialize execution storage" + ~description: + "The returned storage was too big to be serialized with the provided gas" + Data_encoding.empty + (function Cannot_serialize_storage -> Some () | _ -> None) + (fun () -> Cannot_serialize_storage) + +(* + + Interpretation loop + =================== + +*) + +(* + + As announced earlier, the [step] function produces a computation in + the [Lwt+State+Error] monad. The [State] monad is implemented by + having the [context] passed as input and returned updated as + output. The [Error] monad is represented by the [tzresult] type + constructor. + + The [step] function is actually defined as an internal + tail-recursive routine of the toplevel [step]. It monitors the gas + level before executing the instruction under focus, once this is + done, it recursively calls itself on the continuation held by the + current instruction. + + For each pure instruction (i.e. that is not monadic), the + interpretation simply updates the input arguments of the [step] + function. Since these arguments are (most likely) stored in + hardware registers and since the tail-recursive calls are compiled + into direct jumps, this interpretation technique offers good + performances while saving safety thanks to a rich typing. + + For each impure instruction, the interpreter makes use of monadic + bindings to compose monadic primitives with the [step] function. + Again, we make sure that the recursive calls to [step] are tail + calls by annotating them with [@ocaml.tailcall]. + + The [step] function is actually based on several mutually + recursive functions that can be separated in two groups: the first + group focuses on the evaluation of continuations while the second + group is about evaluating the instructions. + +*) + +module Raw = struct + (* + + Evaluation of continuations + =========================== + + As explained in [Script_typed_ir], there are several kinds of + continuations, each having a specific evaluation rules. The + following group of functions starts with a list of evaluation + rules for continuations that generate fresh continuations. This + group ends with the definition of [next], which dispatches + evaluation rules depending on the continuation at stake. + + Some of these functions generate fresh continuations. As such, they + expect a constructor [instrument] which inserts a [KLog] if the + evaluation is logged. + + *) + let rec kmap_exit : + type a b c e f m n o. (a, b, c, e, f, m, n, o) kmap_exit_type = + fun instrument g gas body xs ty ys yk ks accu stack -> + let ys = Script_map.update yk (Some accu) ys in + let ks = instrument @@ KMap_enter_body (body, xs, ys, ty, ks) in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and kmap_enter : + type a b c d f i j k. (a, b, c, d, f, i, j, k) kmap_enter_type = + fun instrument g gas body xs ty ys ks accu stack -> + match xs with + | [] -> (next [@ocaml.tailcall]) g gas ks ys (accu, stack) + | (xk, xv) :: xs -> + let ks = instrument @@ KMap_exit_body (body, xs, ys, xk, ty, ks) in + let res = (xk, xv) in + let stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas body ks res stack + [@@inline] + + and klist_exit : type a b c d e i j. (a, b, c, d, e, i, j) klist_exit_type = + fun instrument g gas body xs ys ty len ks accu stack -> + let ys = Script_list.cons accu ys in + let ks = instrument @@ KList_enter_body (body, xs, ys, ty, len, ks) in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and klist_enter : type a b c d e f j. (a, b, c, d, e, f, j) klist_enter_type = + fun instrument g gas body xs ys ty len ks' accu stack -> + match xs with + | [] -> + let ys = Script_list.rev ys in + (next [@ocaml.tailcall]) g gas ks' ys (accu, stack) + | x :: xs -> + let ks = instrument @@ KList_exit_body (body, xs, ys, ty, len, ks') in + (step [@ocaml.tailcall]) g gas body ks x (accu, stack) + [@@inline] + + and kloop_in_left : + type a b c d e f g. (a, b, c, d, e, f, g) kloop_in_left_type = + fun g gas ks0 ki ks' accu stack -> + match accu with + | L v -> (step [@ocaml.tailcall]) g gas ki ks0 v stack + | R v -> (next [@ocaml.tailcall]) g gas ks' v stack + [@@inline] + + and kloop_in : type a b c r f s. (a, b, c, r, f, s) kloop_in_type = + fun g gas ks0 ki ks' accu stack -> + let accu', stack' = stack in + if accu then (step [@ocaml.tailcall]) g gas ki ks0 accu' stack' + else (next [@ocaml.tailcall]) g gas ks' accu' stack' + [@@inline] + + and kiter : type a b s r f c. (a, b, s, r, f, c) kiter_type = + fun instrument g gas body ty xs ks accu stack -> + match xs with + | [] -> (next [@ocaml.tailcall]) g gas ks accu stack + | x :: xs -> + let ks = instrument @@ KIter (body, ty, xs, ks) in + (step [@ocaml.tailcall]) g gas body ks x (accu, stack) + [@@inline] + + and next : + type a s r f. + outdated_context * step_constants -> + local_gas_counter -> + (a, s, r, f) continuation -> + a -> + s -> + (r * f * outdated_context * local_gas_counter) tzresult Lwt.t = + fun ((ctxt, _) as g) gas ks0 accu stack -> + match consume_control gas ks0 with + | None -> tzfail Gas.Operation_quota_exceeded + | Some gas -> ( + match ks0 with + | KLog (ks, sty, logger) -> + (logger.klog [@ocaml.tailcall]) logger g gas sty ks0 ks accu stack + | KNil -> Lwt.return (Ok (accu, stack, ctxt, gas)) + | KCons (k, ks) -> (step [@ocaml.tailcall]) g gas k ks accu stack + | KLoop_in (ki, ks') -> + (kloop_in [@ocaml.tailcall]) g gas ks0 ki ks' accu stack + | KReturn (stack', _, ks) -> + (next [@ocaml.tailcall]) g gas ks accu stack' + | KMap_head (f, ks) -> (next [@ocaml.tailcall]) g gas ks (f accu) stack + | KLoop_in_left (ki, ks') -> + (kloop_in_left [@ocaml.tailcall]) g gas ks0 ki ks' accu stack + | KUndip (x, _, ks) -> (next [@ocaml.tailcall]) g gas ks x (accu, stack) + | KIter (body, ty, xs, ks) -> + (kiter [@ocaml.tailcall]) id g gas body ty xs ks accu stack + | KList_enter_body (body, xs, ys, ty, len, ks) -> + (klist_enter [@ocaml.tailcall]) + id + g + gas + body + xs + ys + ty + len + ks + accu + stack + | KList_exit_body (body, xs, ys, ty, len, ks) -> + (klist_exit [@ocaml.tailcall]) + id + g + gas + body + xs + ys + ty + len + ks + accu + stack + | KMap_enter_body (body, xs, ys, ty, ks) -> + (kmap_enter [@ocaml.tailcall]) id g gas body xs ty ys ks accu stack + | KMap_exit_body (body, xs, ys, yk, ty, ks) -> + (kmap_exit [@ocaml.tailcall]) + id + g + gas + body + xs + ty + ys + yk + ks + accu + stack + | KView_exit (orig_step_constants, ks) -> + let g = (fst g, orig_step_constants) in + (next [@ocaml.tailcall]) g gas ks accu stack) + + (* + + Evaluation of instructions + ========================== + + The following functions define evaluation rules for instructions that + generate fresh continuations. As such, they expect a constructor + [instrument] which inserts a [KLog] if the evaluation is logged. + + The [step] function is taking care of the evaluation of the other + instructions. + +*) + and ilist_map : + type a b c d e f g h i. (a, b, c, d, e, f, g, h, i) ilist_map_type = + fun instrument g gas body k ks ty accu stack -> + let xs = accu.elements in + let ys = Script_list.empty in + let len = accu.length in + let ks = + instrument @@ KList_enter_body (body, xs, ys, ty, len, KCons (k, ks)) + in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and ilist_iter : + type a b c d e f g cmp. (a, b, c, d, e, f, g, cmp) ilist_iter_type = + fun instrument g gas body ty k ks accu stack -> + let xs = accu.elements in + let ks = instrument @@ KIter (body, ty, xs, KCons (k, ks)) in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and iset_iter : type a b c d e f g. (a, b, c, d, e, f, g) iset_iter_type = + fun instrument g gas body ty k ks accu stack -> + let set = accu in + let l = List.rev (Script_set.fold (fun e acc -> e :: acc) set []) in + let ks = instrument @@ KIter (body, ty, l, KCons (k, ks)) in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and imap_map : + type a b c d e f g h i j. (a, b, c, d, e, f, g, h, i, j) imap_map_type = + fun instrument g gas body k ks ty accu stack -> + let map = accu in + let xs = List.rev (Script_map.fold (fun k v a -> (k, v) :: a) map []) in + let ys = Script_map.empty_from map in + let ks = instrument @@ KMap_enter_body (body, xs, ys, ty, KCons (k, ks)) in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and imap_iter : + type a b c d e f g h cmp. (a, b, c, d, e, f, g, h, cmp) imap_iter_type = + fun instrument g gas body ty k ks accu stack -> + let map = accu in + let l = List.rev (Script_map.fold (fun k v a -> (k, v) :: a) map []) in + let ks = instrument @@ KIter (body, ty, l, KCons (k, ks)) in + let accu, stack = stack in + (next [@ocaml.tailcall]) g gas ks accu stack + [@@inline] + + and imul_teznat : type a b c d e f. (a, b, c, d, e, f) imul_teznat_type = + let open Lwt_result_syntax in + fun logger g gas loc k ks accu stack -> + let x = accu in + let y, stack = stack in + match Script_int.to_int64 y with + | None -> + let* log = get_log logger in + tzfail (Overflow (loc, log)) + | Some y -> + let*? res = Tez.(x *? y) in + (step [@ocaml.tailcall]) g gas k ks res stack + + and imul_nattez : type a b c d e f. (a, b, c, d, e, f) imul_nattez_type = + let open Lwt_result_syntax in + fun logger g gas loc k ks accu stack -> + let y = accu in + let x, stack = stack in + match Script_int.to_int64 y with + | None -> + let* log = get_log logger in + tzfail (Overflow (loc, log)) + | Some y -> + let*? res = Tez.(x *? y) in + (step [@ocaml.tailcall]) g gas k ks res stack + + and ilsl_nat : type a b c d e f. (a, b, c, d, e, f) ilsl_nat_type = + let open Lwt_result_syntax in + fun logger g gas loc k ks accu stack -> + let x = accu and y, stack = stack in + match Script_int.shift_left_n x y with + | None -> + let* log = get_log logger in + tzfail (Overflow (loc, log)) + | Some x -> (step [@ocaml.tailcall]) g gas k ks x stack + + and ilsr_nat : type a b c d e f. (a, b, c, d, e, f) ilsr_nat_type = + let open Lwt_result_syntax in + fun logger g gas loc k ks accu stack -> + let x = accu and y, stack = stack in + match Script_int.shift_right_n x y with + | None -> + let* log = get_log logger in + tzfail (Overflow (loc, log)) + | Some r -> (step [@ocaml.tailcall]) g gas k ks r stack + + and ilsl_bytes : type a b c d e f. (a, b, c, d, e, f) ilsl_bytes_type = + let open Lwt_result_syntax in + fun logger g gas loc k ks accu stack -> + let x = accu and y, stack = stack in + match Script_bytes.bytes_lsl x y with + | None -> + let* log = get_log logger in + tzfail (Overflow (loc, log)) + | Some res -> (step [@ocaml.tailcall]) g gas k ks res stack + + and ifailwith : ifailwith_type = + let open Lwt_result_syntax in + { + ifailwith = + (fun logger (ctxt, _) gas kloc tv accu -> + let v = accu in + let ctxt = update_context gas ctxt in + let* v, _ctxt = + trace Cannot_serialize_failure (unparse_data ctxt Optimized tv v) + in + let* log = get_log logger in + tzfail (Reject (kloc, v, log))); + } + + and iexec : type a b c d e f g. (a, b, c, d, e, f, g) iexec_type = + fun instrument logger g gas cont_sty k ks accu stack -> + let arg = accu and code, stack = stack in + let log_code b = + let body = + match logger with + | None -> b.kinstr + | Some logger -> logger.log_kinstr logger b.kbef b.kinstr + in + let ks = instrument @@ KReturn (stack, cont_sty, KCons (k, ks)) in + (body, ks) + in + match code with + | Lam (body, _) -> + let body, ks = log_code body in + (step [@ocaml.tailcall]) g gas body ks arg (EmptyCell, EmptyCell) + | LamRec (body, _) -> + let body, ks = log_code body in + (step [@ocaml.tailcall]) g gas body ks arg (code, (EmptyCell, EmptyCell)) + + and iview : type a b c d e f i o. (a, b, c, d, e, f, i, o) iview_type = + let open Lwt_result_syntax in + fun instrument + (ctxt, sc) + gas + (View_signature {name; input_ty; output_ty}) + stack_ty + k + ks + accu + stack -> + let input = accu in + let addr, stack = stack in + let ctxt = update_context gas ctxt in + let return_none ctxt = + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks None stack + in + let legacy = Script_ir_translator_config.make ~legacy:true () in + match addr.destination with + | Contract (Implicit _) | Sc_rollup _ | Zk_rollup _ -> + (return_none [@ocaml.tailcall]) ctxt + | Contract (Originated contract_hash as c) -> ( + let* ctxt, script_opt = Contract.get_script ctxt contract_hash in + match script_opt with + | None -> (return_none [@ocaml.tailcall]) ctxt + | Some script -> ( + let* Ex_script (Script {storage; storage_type; views; _}), ctxt = + parse_script + ~elab_conf:legacy + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + ctxt + script + in + let*? ctxt = + Gas.consume ctxt (Interp_costs.view_get name views) + in + match Script_map.get name views with + | None -> (return_none [@ocaml.tailcall]) ctxt + | Some view -> ( + let view_result = + Script_ir_translator.parse_view + ctxt + ~elab_conf:legacy + storage_type + view + in + let* ( Typed_view + { + input_ty = input_ty'; + output_ty = output_ty'; + kinstr; + original_code_expr = _; + }, + ctxt ) = + trace_eval + (fun () -> + Script_tc_errors.Ill_typed_contract + (Micheline.strip_locations view.view_code, [])) + view_result + in + let io_ty = + let open Gas_monad.Syntax in + let* out_eq = + ty_eq ~error_details:Fast output_ty' output_ty + in + let+ in_eq = ty_eq ~error_details:Fast input_ty input_ty' in + (out_eq, in_eq) + in + let*? eq, ctxt = Gas_monad.run ctxt io_ty in + match eq with + | Error Inconsistent_types_fast -> + (return_none [@ocaml.tailcall]) ctxt + | Ok (Eq, Eq) -> + let kcons = + KCons (ICons_some (kinstr_location k, k), ks) + in + let* ctxt, balance = + Contract.get_balance_carbonated ctxt c + in + let gas, ctxt = + local_gas_counter_and_outdated_context ctxt + in + let sty = + Option.map (fun t -> Item_t (output_ty, t)) stack_ty + in + (step [@ocaml.tailcall]) + ( ctxt, + { + sender = + Destination.Contract (Contract.Originated sc.self); + self = contract_hash; + amount = Tez.zero; + balance; + (* The following remain unchanged, but let's + list them anyway, so that we don't forget + to update something added later. *) + payer = sc.payer; + chain_id = sc.chain_id; + now = sc.now; + level = sc.level; + } ) + gas + kinstr + (instrument + @@ KView_exit (sc, KReturn (stack, sty, kcons))) + (input, storage) + (EmptyCell, EmptyCell)))) + + and step : type a s b t r f. (a, s, b, t, r, f) step_type = + let open Lwt_result_syntax in + fun ((ctxt, sc) as g) gas i ks accu stack -> + match consume_instr gas i accu stack with + | None -> tzfail Gas.Operation_quota_exceeded + | Some gas -> ( + match i with + | ILog (_, sty, event, logger, k) -> + (logger.ilog [@ocaml.tailcall]) + logger + event + sty + g + gas + k + ks + accu + stack + | IHalt _ -> (next [@ocaml.tailcall]) g gas ks accu stack + (* stack ops *) + | IDrop (_, k) -> + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IDup (_, k) -> (step [@ocaml.tailcall]) g gas k ks accu (accu, stack) + | ISwap (_, k) -> + let top, stack = stack in + (step [@ocaml.tailcall]) g gas k ks top (accu, stack) + | IPush (_, _ty, v, k) -> + (step [@ocaml.tailcall]) g gas k ks v (accu, stack) + | IUnit (_, k) -> (step [@ocaml.tailcall]) g gas k ks () (accu, stack) + (* options *) + | ICons_some (_, k) -> + (step [@ocaml.tailcall]) g gas k ks (Some accu) stack + | ICons_none (_, _ty, k) -> + (step [@ocaml.tailcall]) g gas k ks None (accu, stack) + | IIf_none {branch_if_none; branch_if_some; k; _} -> ( + match accu with + | None -> + let accu, stack = stack in + (step [@ocaml.tailcall]) + g + gas + branch_if_none + (KCons (k, ks)) + accu + stack + | Some v -> + (step [@ocaml.tailcall]) + g + gas + branch_if_some + (KCons (k, ks)) + v + stack) + | IOpt_map {body; k; loc = _} -> ( + match accu with + | None -> (step [@ocaml.tailcall]) g gas k ks None stack + | Some v -> + let ks' = KMap_head (Option.some, KCons (k, ks)) in + (step [@ocaml.tailcall]) g gas body ks' v stack) + (* pairs *) + | ICons_pair (_, k) -> + let b, stack = stack in + (step [@ocaml.tailcall]) g gas k ks (accu, b) stack + | IUnpair (_, k) -> + let a, b = accu in + (step [@ocaml.tailcall]) g gas k ks a (b, stack) + | ICar (_, k) -> + let a, _ = accu in + (step [@ocaml.tailcall]) g gas k ks a stack + | ICdr (_, k) -> + let _, b = accu in + (step [@ocaml.tailcall]) g gas k ks b stack + (* ors *) + | ICons_left (_, _tyb, k) -> + (step [@ocaml.tailcall]) g gas k ks (L accu) stack + | ICons_right (_, _tya, k) -> + (step [@ocaml.tailcall]) g gas k ks (R accu) stack + | IIf_left {branch_if_left; branch_if_right; k; _} -> ( + match accu with + | L v -> + (step [@ocaml.tailcall]) + g + gas + branch_if_left + (KCons (k, ks)) + v + stack + | R v -> + (step [@ocaml.tailcall]) + g + gas + branch_if_right + (KCons (k, ks)) + v + stack) + (* lists *) + | ICons_list (_, k) -> + let tl, stack = stack in + let accu = Script_list.cons accu tl in + (step [@ocaml.tailcall]) g gas k ks accu stack + | INil (_, _ty, k) -> + let stack = (accu, stack) in + let accu = Script_list.empty in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IIf_cons {branch_if_cons; branch_if_nil; k; _} -> ( + match Script_list.uncons accu with + | None -> + let accu, stack = stack in + (step [@ocaml.tailcall]) + g + gas + branch_if_nil + (KCons (k, ks)) + accu + stack + | Some (hd, tl) -> + (step [@ocaml.tailcall]) + g + gas + branch_if_cons + (KCons (k, ks)) + hd + (tl, stack)) + | IList_map (_, body, ty, k) -> + (ilist_map [@ocaml.tailcall]) id g gas body k ks ty accu stack + | IList_size (_, k) -> + let list = accu in + let len = Script_int.(abs (of_int list.length)) in + (step [@ocaml.tailcall]) g gas k ks len stack + | IList_iter (_, ty, body, k) -> + (ilist_iter [@ocaml.tailcall]) id g gas body ty k ks accu stack + (* sets *) + | IEmpty_set (_, ty, k) -> + let res = Script_set.empty ty in + let stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas k ks res stack + | ISet_iter (_, ty, body, k) -> + (iset_iter [@ocaml.tailcall]) id g gas body ty k ks accu stack + | ISet_mem (_, k) -> + let set, stack = stack in + let res = Script_set.mem accu set in + (step [@ocaml.tailcall]) g gas k ks res stack + | ISet_update (_, k) -> + let presence, (set, stack) = stack in + let res = Script_set.update accu presence set in + (step [@ocaml.tailcall]) g gas k ks res stack + | ISet_size (_, k) -> + let res = Script_set.size accu in + (step [@ocaml.tailcall]) g gas k ks res stack + (* maps *) + | IEmpty_map (_, kty, _vty, k) -> + let res = Script_map.empty kty and stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMap_map (_, ty, body, k) -> + (imap_map [@ocaml.tailcall]) id g gas body k ks ty accu stack + | IMap_iter (_, kvty, body, k) -> + (imap_iter [@ocaml.tailcall]) id g gas body kvty k ks accu stack + | IMap_mem (_, k) -> + let map, stack = stack in + let res = Script_map.mem accu map in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMap_get (_, k) -> + let map, stack = stack in + let res = Script_map.get accu map in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMap_update (_, k) -> + let v, (map, stack) = stack in + let key = accu in + let res = Script_map.update key v map in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMap_get_and_update (_, k) -> + let key = accu in + let v, (map, rest) = stack in + let map' = Script_map.update key v map in + let v' = Script_map.get key map in + (step [@ocaml.tailcall]) g gas k ks v' (map', rest) + | IMap_size (_, k) -> + let res = Script_map.size accu in + (step [@ocaml.tailcall]) g gas k ks res stack + (* Big map operations *) + | IEmpty_big_map (_, tk, tv, k) -> + let ebm = Script_big_map.empty tk tv in + (step [@ocaml.tailcall]) g gas k ks ebm (accu, stack) + | IBig_map_mem (_, k) -> + let map, stack = stack in + let key = accu in + let* res, ctxt, gas = + use_gas_counter_in_context ctxt gas @@ fun ctxt -> + Script_big_map.mem ctxt key map + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks res stack + | IBig_map_get (_, k) -> + let map, stack = stack in + let key = accu in + let* res, ctxt, gas = + use_gas_counter_in_context ctxt gas @@ fun ctxt -> + Script_big_map.get ctxt key map + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks res stack + | IBig_map_update (_, k) -> + let key = accu in + let maybe_value, (map, stack) = stack in + let* big_map, ctxt, gas = + use_gas_counter_in_context ctxt gas @@ fun ctxt -> + Script_big_map.update ctxt key maybe_value map + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks big_map stack + | IBig_map_get_and_update (_, k) -> + let key = accu in + let v, (map, stack) = stack in + let* (v', map'), ctxt, gas = + use_gas_counter_in_context ctxt gas @@ fun ctxt -> + Script_big_map.get_and_update ctxt key v map + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks v' (map', stack) + (* timestamp operations *) + | IAdd_seconds_to_timestamp (_, k) -> + let n = accu in + let t, stack = stack in + let result = Script_timestamp.add_delta t n in + (step [@ocaml.tailcall]) g gas k ks result stack + | IAdd_timestamp_to_seconds (_, k) -> + let t = accu in + let n, stack = stack in + let result = Script_timestamp.add_delta t n in + (step [@ocaml.tailcall]) g gas k ks result stack + | ISub_timestamp_seconds (_, k) -> + let t = accu in + let s, stack = stack in + let result = Script_timestamp.sub_delta t s in + (step [@ocaml.tailcall]) g gas k ks result stack + | IDiff_timestamps (_, k) -> + let t1 = accu in + let t2, stack = stack in + let result = Script_timestamp.diff t1 t2 in + (step [@ocaml.tailcall]) g gas k ks result stack + (* string operations *) + | IConcat_string_pair (_, k) -> + let x = accu in + let y, stack = stack in + let s = Script_string.concat_pair x y in + (step [@ocaml.tailcall]) g gas k ks s stack + | IConcat_string (_, k) -> + let ss = accu in + (* The cost for this fold_left has been paid upfront *) + let total_length = + List.fold_left + (fun acc s -> S.add acc (S.safe_int (Script_string.length s))) + S.zero + ss.elements + in + let*? gas = + consume gas (Interp_costs.concat_string total_length) + in + let s = Script_string.concat ss.elements in + (step [@ocaml.tailcall]) g gas k ks s stack + | ISlice_string (_, k) -> + let offset = accu and length, (s, stack) = stack in + let s_length = Z.of_int (Script_string.length s) in + let offset = Script_int.to_zint offset in + let length = Script_int.to_zint length in + if + Compare.Z.(offset < s_length && Z.add offset length <= s_length) + then + let s = + Script_string.sub s (Z.to_int offset) (Z.to_int length) + in + (step [@ocaml.tailcall]) g gas k ks (Some s) stack + else (step [@ocaml.tailcall]) g gas k ks None stack + | IString_size (_, k) -> + let s = accu in + let result = Script_int.(abs (of_int (Script_string.length s))) in + (step [@ocaml.tailcall]) g gas k ks result stack + (* bytes operations *) + | IConcat_bytes_pair (_, k) -> + let x = accu in + let y, stack = stack in + let s = Bytes.cat x y in + (step [@ocaml.tailcall]) g gas k ks s stack + | IConcat_bytes (_, k) -> + let ss = accu in + (* The cost for this fold_left has been paid upfront *) + let total_length = + List.fold_left + (fun acc s -> S.add acc (S.safe_int (Bytes.length s))) + S.zero + ss.elements + in + let*? gas = + consume gas (Interp_costs.concat_string total_length) + in + let s = Bytes.concat Bytes.empty ss.elements in + (step [@ocaml.tailcall]) g gas k ks s stack + | ISlice_bytes (_, k) -> + let offset = accu and length, (s, stack) = stack in + let s_length = Z.of_int (Bytes.length s) in + let offset = Script_int.to_zint offset in + let length = Script_int.to_zint length in + if + Compare.Z.(offset < s_length && Z.add offset length <= s_length) + then + let s = Bytes.sub s (Z.to_int offset) (Z.to_int length) in + (step [@ocaml.tailcall]) g gas k ks (Some s) stack + else (step [@ocaml.tailcall]) g gas k ks None stack + | IBytes_size (_, k) -> + let s = accu in + let result = Script_int.(abs (of_int (Bytes.length s))) in + (step [@ocaml.tailcall]) g gas k ks result stack + | ILsl_bytes (loc, k) -> ilsl_bytes None g gas loc k ks accu stack + | ILsr_bytes (_, k) -> + let x = accu and y, stack = stack in + let res = Script_bytes.bytes_lsr x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IOr_bytes (_, k) -> + let x = accu and y, stack = stack in + let res = Script_bytes.bytes_or x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IAnd_bytes (_, k) -> + let x = accu and y, stack = stack in + let res = Script_bytes.bytes_and x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IXor_bytes (_, k) -> + let x = accu and y, stack = stack in + let res = Script_bytes.bytes_xor x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | INot_bytes (_, k) -> + let x = accu in + let res = Script_bytes.bytes_not x in + (step [@ocaml.tailcall]) g gas k ks res stack + | IBytes_nat (_, k) -> + let n = accu in + let result = Script_bytes.bytes_of_nat_be n in + (step [@ocaml.tailcall]) g gas k ks result stack + | INat_bytes (_, k) -> + let s = accu in + let result = Script_bytes.nat_of_bytes_be s in + (step [@ocaml.tailcall]) g gas k ks result stack + | IBytes_int (_, k) -> + let n = accu in + let result = Script_bytes.bytes_of_int_be n in + (step [@ocaml.tailcall]) g gas k ks result stack + | IInt_bytes (_, k) -> + let s = accu in + let result = Script_bytes.int_of_bytes_be s in + (step [@ocaml.tailcall]) g gas k ks result stack + (* currency operations *) + | IAdd_tez (_, k) -> + let x = accu in + let y, stack = stack in + let*? res = Tez.(x +? y) in + (step [@ocaml.tailcall]) g gas k ks res stack + | ISub_tez (_, k) -> + let x = accu in + let y, stack = stack in + let res = Tez.sub_opt x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | ISub_tez_legacy (_, k) -> + let x = accu in + let y, stack = stack in + let*? res = Tez.(x -? y) in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMul_teznat (loc, k) -> imul_teznat None g gas loc k ks accu stack + | IMul_nattez (loc, k) -> imul_nattez None g gas loc k ks accu stack + (* boolean operations *) + | IOr (_, k) -> + let x = accu in + let y, stack = stack in + (step [@ocaml.tailcall]) g gas k ks (x || y) stack + | IAnd (_, k) -> + let x = accu in + let y, stack = stack in + (step [@ocaml.tailcall]) g gas k ks (x && y) stack + | IXor (_, k) -> + let x = accu in + let y, stack = stack in + let res = Compare.Bool.(x <> y) in + (step [@ocaml.tailcall]) g gas k ks res stack + | INot (_, k) -> + let x = accu in + (step [@ocaml.tailcall]) g gas k ks (not x) stack + (* integer operations *) + | IIs_nat (_, k) -> + let x = accu in + let res = Script_int.is_nat x in + (step [@ocaml.tailcall]) g gas k ks res stack + | IAbs_int (_, k) -> + let x = accu in + let res = Script_int.abs x in + (step [@ocaml.tailcall]) g gas k ks res stack + | IInt_nat (_, k) -> + let x = accu in + let res = Script_int.int x in + (step [@ocaml.tailcall]) g gas k ks res stack + | INeg (_, k) -> + let x = accu in + let res = Script_int.neg x in + (step [@ocaml.tailcall]) g gas k ks res stack + | IAdd_int (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.add x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IAdd_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.add_n x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | ISub_int (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.sub x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMul_int (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.mul x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMul_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.mul_n x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IEdiv_teznat (_, k) -> + let x = accu and y, stack = stack in + let x = Script_int.of_int64 (Tez.to_mutez x) in + let result = + match Script_int.ediv x y with + | None -> None + | Some (q, r) -> ( + match (Script_int.to_int64 q, Script_int.to_int64 r) with + | Some q, Some r -> ( + match (Tez.of_mutez q, Tez.of_mutez r) with + | Some q, Some r -> Some (q, r) + (* Cannot overflow *) + | _ -> assert false) + (* Cannot overflow *) + | _ -> assert false) + in + (step [@ocaml.tailcall]) g gas k ks result stack + | IEdiv_tez (_, k) -> + let x = accu and y, stack = stack in + let x = Script_int.abs (Script_int.of_int64 (Tez.to_mutez x)) in + let y = Script_int.abs (Script_int.of_int64 (Tez.to_mutez y)) in + let result = + match Script_int.ediv_n x y with + | None -> None + | Some (q, r) -> ( + match Script_int.to_int64 r with + | None -> assert false (* Cannot overflow *) + | Some r -> ( + match Tez.of_mutez r with + | None -> assert false (* Cannot overflow *) + | Some r -> Some (q, r))) + in + (step [@ocaml.tailcall]) g gas k ks result stack + | IEdiv_int (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.ediv x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IEdiv_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.ediv_n x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | ILsl_nat (loc, k) -> ilsl_nat None g gas loc k ks accu stack + | ILsr_nat (loc, k) -> ilsr_nat None g gas loc k ks accu stack + | IOr_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.logor x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IAnd_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.logand x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IAnd_int_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.logand x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IXor_nat (_, k) -> + let x = accu and y, stack = stack in + let res = Script_int.logxor x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | INot_int (_, k) -> + let x = accu in + let res = Script_int.lognot x in + (step [@ocaml.tailcall]) g gas k ks res stack + (* control *) + | IIf {branch_if_true; branch_if_false; k; _} -> + let res, stack = stack in + if accu then + (step [@ocaml.tailcall]) + g + gas + branch_if_true + (KCons (k, ks)) + res + stack + else + (step [@ocaml.tailcall]) + g + gas + branch_if_false + (KCons (k, ks)) + res + stack + | ILoop (_, body, k) -> + let ks = KLoop_in (body, KCons (k, ks)) in + (next [@ocaml.tailcall]) g gas ks accu stack + | ILoop_left (_, bl, br) -> + let ks = KLoop_in_left (bl, KCons (br, ks)) in + (next [@ocaml.tailcall]) g gas ks accu stack + | IDip (_, b, ty, k) -> + let ign = accu in + let ks = KUndip (ign, ty, KCons (k, ks)) in + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas b ks accu stack + | IExec (_, sty, k) -> iexec id None g gas sty k ks accu stack + | IApply (_, capture_ty, k) -> + let capture = accu in + let lam, stack = stack in + let* lam', ctxt, gas = apply ctxt gas capture_ty capture lam in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks lam' stack + | ILambda (_, lam, k) -> + (step [@ocaml.tailcall]) g gas k ks lam (accu, stack) + | IFailwith (kloc, tv) -> + let {ifailwith} = ifailwith in + ifailwith None g gas kloc tv accu + (* comparison *) + | ICompare (_, ty, k) -> + let a = accu in + let b, stack = stack in + let r = + Script_int.of_int @@ Script_comparable.compare_comparable ty a b + in + (step [@ocaml.tailcall]) g gas k ks r stack + (* comparators *) + | IEq (_, k) -> + let a = accu in + let a = Script_int.compare a Script_int.zero in + let a = Compare.Int.(a = 0) in + (step [@ocaml.tailcall]) g gas k ks a stack + | INeq (_, k) -> + let a = accu in + let a = Script_int.compare a Script_int.zero in + let a = Compare.Int.(a <> 0) in + (step [@ocaml.tailcall]) g gas k ks a stack + | ILt (_, k) -> + let a = accu in + let a = Script_int.compare a Script_int.zero in + let a = Compare.Int.(a < 0) in + (step [@ocaml.tailcall]) g gas k ks a stack + | ILe (_, k) -> + let a = accu in + let a = Script_int.compare a Script_int.zero in + let a = Compare.Int.(a <= 0) in + (step [@ocaml.tailcall]) g gas k ks a stack + | IGt (_, k) -> + let a = accu in + let a = Script_int.compare a Script_int.zero in + let a = Compare.Int.(a > 0) in + (step [@ocaml.tailcall]) g gas k ks a stack + | IGe (_, k) -> + let a = accu in + let a = Script_int.compare a Script_int.zero in + let a = Compare.Int.(a >= 0) in + (step [@ocaml.tailcall]) g gas k ks a stack + (* packing *) + | IPack (_, ty, k) -> + let value = accu in + let* bytes, ctxt, gas = + use_gas_counter_in_context ctxt gas @@ fun ctxt -> + Script_ir_translator.pack_data ctxt ty value + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks bytes stack + | IUnpack (_, ty, k) -> + let bytes = accu in + let* opt, ctxt, gas = + use_gas_counter_in_context ctxt gas @@ fun ctxt -> + unpack ctxt ~ty ~bytes + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks opt stack + | IAddress (_, k) -> + let typed_contract = accu in + let destination = Typed_contract.destination typed_contract in + let entrypoint = Typed_contract.entrypoint typed_contract in + let address = {destination; entrypoint} in + (step [@ocaml.tailcall]) g gas k ks address stack + | IContract (loc, t, entrypoint, k) -> ( + let addr = accu in + let entrypoint_opt = + if Entrypoint.is_default addr.entrypoint then Some entrypoint + else if Entrypoint.is_default entrypoint then + Some addr.entrypoint + else (* both entrypoints are non-default *) None + in + match entrypoint_opt with + | Some entrypoint -> + let ctxt = update_context gas ctxt in + let* ctxt, maybe_contract = + Script_ir_translator.parse_contract_for_script + ctxt + loc + t + addr.destination + ~entrypoint + in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + let accu = maybe_contract in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks accu stack + | None -> (step [@ocaml.tailcall]) (ctxt, sc) gas k ks None stack) + | ITransfer_tokens (loc, k) -> + let p = accu in + let amount, (typed_contract, stack) = stack in + let* accu, ctxt, gas = + transfer (ctxt, sc) gas amount loc typed_contract p + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks accu stack + | IImplicit_account (_, k) -> + let key = accu in + let res = Typed_implicit key in + (step [@ocaml.tailcall]) g gas k ks res stack + | IView (_, view_signature, stack_ty, k) -> + (iview [@ocaml.tailcall]) + id + g + gas + view_signature + stack_ty + k + ks + accu + stack + | ICreate_contract {storage_type; code; k; loc = _} -> + (* Removed the instruction's arguments manager, spendable and delegatable *) + let delegate = accu in + let credit, (init, stack) = stack in + let* res, contract, ctxt, gas = + create_contract g gas storage_type code delegate credit init + in + let destination = Destination.Contract (Originated contract) in + let stack = + ({destination; entrypoint = Entrypoint.default}, stack) + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks res stack + | ISet_delegate (_, k) -> + let delegate = accu in + let operation = Delegation delegate in + let ctxt = update_context gas ctxt in + let*? ctxt, nonce = fresh_internal_nonce ctxt in + let piop = + Internal_operation + { + sender = Destination.Contract (Contract.Originated sc.self); + operation; + nonce; + } + in + let res = {piop; lazy_storage_diff = None} in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks res stack + | IBalance (_, k) -> + let ctxt = update_context gas ctxt in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + let g = (ctxt, sc) in + (step [@ocaml.tailcall]) g gas k ks sc.balance (accu, stack) + | ILevel (_, k) -> + (step [@ocaml.tailcall]) g gas k ks sc.level (accu, stack) + | INow (_, k) -> + (step [@ocaml.tailcall]) g gas k ks sc.now (accu, stack) + | IMin_block_time (_, k) -> + let ctxt = update_context gas ctxt in + let min_block_time = + Alpha_context.Constants.minimal_block_delay ctxt + |> Period.to_seconds |> Script_int.of_int64 + (* Realistically the block delay is never negative. *) + |> Script_int.abs + in + let new_stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas k ks min_block_time new_stack + | ICheck_signature (_, k) -> + let key = accu and signature, (message, stack) = stack in + let res = Script_signature.check key signature message in + (step [@ocaml.tailcall]) g gas k ks res stack + | IHash_key (_, k) -> + let key = accu in + let res = Signature.Public_key.hash key in + (step [@ocaml.tailcall]) g gas k ks res stack + | IBlake2b (_, k) -> + let bytes = accu in + let hash = Raw_hashes.blake2b bytes in + (step [@ocaml.tailcall]) g gas k ks hash stack + | ISha256 (_, k) -> + let bytes = accu in + let hash = Raw_hashes.sha256 bytes in + (step [@ocaml.tailcall]) g gas k ks hash stack + | ISha512 (_, k) -> + let bytes = accu in + let hash = Raw_hashes.sha512 bytes in + (step [@ocaml.tailcall]) g gas k ks hash stack + | ISource (_, k) -> + let destination : Destination.t = Contract (Implicit sc.payer) in + let res = {destination; entrypoint = Entrypoint.default} in + (step [@ocaml.tailcall]) g gas k ks res (accu, stack) + | ISender (_, k) -> + let destination : Destination.t = sc.sender in + let res = {destination; entrypoint = Entrypoint.default} in + (step [@ocaml.tailcall]) g gas k ks res (accu, stack) + | ISelf (_, ty, entrypoint, k) -> + let res = + Typed_originated + {arg_ty = ty; contract_hash = sc.self; entrypoint} + in + (step [@ocaml.tailcall]) g gas k ks res (accu, stack) + | ISelf_address (_, k) -> + let destination : Destination.t = Contract (Originated sc.self) in + let res = {destination; entrypoint = Entrypoint.default} in + (step [@ocaml.tailcall]) g gas k ks res (accu, stack) + | IAmount (_, k) -> + let accu = sc.amount and stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IDig (_, _n, n', k) -> + let (accu, stack), x = + interp_stack_prefix_preserving_operation + (fun v stack -> (stack, v)) + n' + accu + stack + in + let accu = x and stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IDug (_, _n, n', k) -> + let v = accu in + let accu, stack = stack in + let (accu, stack), () = + interp_stack_prefix_preserving_operation + (fun accu stack -> ((v, (accu, stack)), ())) + n' + accu + stack + in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IDipn (_, _n, n', b, k) -> + let accu, stack, ks = kundip n' accu stack (KCons (k, ks)) in + (step [@ocaml.tailcall]) g gas b ks accu stack + | IDropn (_, _n, n', k) -> + let stack = + let rec aux : + type a s b t. + (b, t, b, t, a, s, a, s) stack_prefix_preservation_witness -> + a -> + s -> + b * t = + fun w accu stack -> + match w with + | KRest -> (accu, stack) + | KPrefix (_, _ty, w) -> + let accu, stack = stack in + aux w accu stack + in + aux n' accu stack + in + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas k ks accu stack + | ISapling_empty_state (_, memo_size, k) -> + let state = Sapling.empty_state ~memo_size () in + (step [@ocaml.tailcall]) g gas k ks state (accu, stack) + | ISapling_verify_update (_, k) -> ( + let transaction = accu in + let state, stack = stack in + let address = Contract_hash.to_b58check sc.self in + let sc_chain_id = Script_chain_id.make sc.chain_id in + let chain_id = Script_chain_id.to_b58check sc_chain_id in + let anti_replay = address ^ chain_id in + let ctxt = update_context gas ctxt in + let* ctxt, balance_state_opt = + Sapling.verify_update ctxt state transaction anti_replay + in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + match balance_state_opt with + | Some (balance, state) -> + let state = + Some + ( Bytes.of_string transaction.bound_data, + (Script_int.of_int64 balance, state) ) + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks state stack + | None -> (step [@ocaml.tailcall]) (ctxt, sc) gas k ks None stack) + | ISapling_verify_update_deprecated (_, k) -> ( + let transaction = accu in + let state, stack = stack in + let address = Contract_hash.to_b58check sc.self in + let sc_chain_id = Script_chain_id.make sc.chain_id in + let chain_id = Script_chain_id.to_b58check sc_chain_id in + let anti_replay = address ^ chain_id in + let ctxt = update_context gas ctxt in + let* ctxt, balance_state_opt = + Sapling.Legacy.verify_update ctxt state transaction anti_replay + in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + match balance_state_opt with + | Some (balance, state) -> + let state = Some (Script_int.of_int64 balance, state) in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks state stack + | None -> (step [@ocaml.tailcall]) (ctxt, sc) gas k ks None stack) + | IChainId (_, k) -> + let accu = Script_chain_id.make sc.chain_id + and stack = (accu, stack) in + (step [@ocaml.tailcall]) g gas k ks accu stack + | INever _ -> ( match accu with _ -> .) + | IVoting_power (_, k) -> + let key_hash = accu in + let ctxt = update_context gas ctxt in + let* ctxt, power = Vote.get_voting_power ctxt key_hash in + let power = Script_int.(abs (of_int64 power)) in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks power stack + | ITotal_voting_power (_, k) -> + let ctxt = update_context gas ctxt in + let* ctxt, power = Vote.get_total_voting_power ctxt in + let power = Script_int.(abs (of_int64 power)) in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + let g = (ctxt, sc) in + (step [@ocaml.tailcall]) g gas k ks power (accu, stack) + | IKeccak (_, k) -> + let bytes = accu in + let hash = Raw_hashes.keccak256 bytes in + (step [@ocaml.tailcall]) g gas k ks hash stack + | ISha3 (_, k) -> + let bytes = accu in + let hash = Raw_hashes.sha3_256 bytes in + (step [@ocaml.tailcall]) g gas k ks hash stack + | IAdd_bls12_381_g1 (_, k) -> + let x = accu and y, stack = stack in + let accu = Script_bls.G1.add x y in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IAdd_bls12_381_g2 (_, k) -> + let x = accu and y, stack = stack in + let accu = Script_bls.G2.add x y in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IAdd_bls12_381_fr (_, k) -> + let x = accu and y, stack = stack in + let accu = Script_bls.Fr.add x y in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IMul_bls12_381_g1 (_, k) -> + let x = accu and y, stack = stack in + let accu = Script_bls.G1.mul x y in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IMul_bls12_381_g2 (_, k) -> + let x = accu and y, stack = stack in + let accu = Script_bls.G2.mul x y in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IMul_bls12_381_fr (_, k) -> + let x = accu and y, stack = stack in + let accu = Script_bls.Fr.mul x y in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IMul_bls12_381_fr_z (_, k) -> + let x = accu and y, stack = stack in + let x = Script_bls.Fr.of_z (Script_int.to_zint x) in + let res = Script_bls.Fr.mul x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IMul_bls12_381_z_fr (_, k) -> + let y = accu and x, stack = stack in + let x = Script_bls.Fr.of_z (Script_int.to_zint x) in + let res = Script_bls.Fr.mul x y in + (step [@ocaml.tailcall]) g gas k ks res stack + | IInt_bls12_381_fr (_, k) -> + let x = accu in + let res = Script_int.of_zint (Script_bls.Fr.to_z x) in + (step [@ocaml.tailcall]) g gas k ks res stack + | INeg_bls12_381_g1 (_, k) -> + let x = accu in + let accu = Script_bls.G1.negate x in + (step [@ocaml.tailcall]) g gas k ks accu stack + | INeg_bls12_381_g2 (_, k) -> + let x = accu in + let accu = Script_bls.G2.negate x in + (step [@ocaml.tailcall]) g gas k ks accu stack + | INeg_bls12_381_fr (_, k) -> + let x = accu in + let accu = Script_bls.Fr.negate x in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IPairing_check_bls12_381 (_, k) -> + let pairs = accu in + let check = Script_bls.pairing_check pairs.elements in + (step [@ocaml.tailcall]) g gas k ks check stack + | IComb (_, _, witness, k) -> + let rec aux : + type a b s c d t. + (a, b, s, c, d, t) comb_gadt_witness -> + a * (b * s) -> + c * (d * t) = + fun witness stack -> + match (witness, stack) with + | Comb_one, stack -> stack + | Comb_succ witness', (a, tl) -> + let b, tl' = aux witness' tl in + ((a, b), tl') + in + let stack = aux witness (accu, stack) in + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IUncomb (_, _, witness, k) -> + let rec aux : + type a b s c d t. + (a, b, s, c, d, t) uncomb_gadt_witness -> + a * (b * s) -> + c * (d * t) = + fun witness stack -> + match (witness, stack) with + | Uncomb_one, stack -> stack + | Uncomb_succ witness', ((a, b), tl) -> (a, aux witness' (b, tl)) + in + let stack = aux witness (accu, stack) in + let accu, stack = stack in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IComb_get (_, _, witness, k) -> + let comb = accu in + let rec aux : + type before after. + (before, after) comb_get_gadt_witness -> before -> after = + fun witness comb -> + match (witness, comb) with + | Comb_get_zero, v -> v + | Comb_get_one, (a, _) -> a + | Comb_get_plus_two witness', (_, b) -> aux witness' b + in + let accu = aux witness comb in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IComb_set (_, _, witness, k) -> + let value = accu and comb, stack = stack in + let rec aux : + type value before after. + (value, before, after) comb_set_gadt_witness -> + value -> + before -> + after = + fun witness value item -> + match (witness, item) with + | Comb_set_zero, _ -> value + | Comb_set_one, (_hd, tl) -> (value, tl) + | Comb_set_plus_two witness', (hd, tl) -> + (hd, aux witness' value tl) + in + let accu = aux witness value comb in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IDup_n (_, _, witness, k) -> + let rec aux : + type a b before after. + (a, b, before, after) dup_n_gadt_witness -> + a * (b * before) -> + after = + fun witness stack -> + match (witness, stack) with + | Dup_n_zero, (a, _) -> a + | Dup_n_succ witness', (_, tl) -> aux witness' tl + in + let stack = (accu, stack) in + let accu = aux witness stack in + (step [@ocaml.tailcall]) g gas k ks accu stack + (* Tickets *) + | ITicket_deprecated (_, _, k) -> ( + let contents = accu and amount, stack = stack in + match Ticket_amount.of_n amount with + | Some amount -> + let ticketer = Contract.Originated sc.self in + let accu = {ticketer; contents; amount} in + (step [@ocaml.tailcall]) g gas k ks accu stack + | None -> tzfail Script_tc_errors.Forbidden_zero_ticket_quantity) + | ITicket (_, _, k) -> ( + let contents = accu and amount, stack = stack in + match Ticket_amount.of_n amount with + | Some amount -> + let ticketer = Contract.Originated sc.self in + let accu = Some {ticketer; contents; amount} in + (step [@ocaml.tailcall]) g gas k ks accu stack + | None -> (step [@ocaml.tailcall]) g gas k ks None stack) + | IRead_ticket (_, _, k) -> + let {ticketer; contents; amount} = accu in + let stack = (accu, stack) in + let destination : Destination.t = Contract ticketer in + let addr = {destination; entrypoint = Entrypoint.default} in + let accu = + (addr, (contents, (amount :> Script_int.n Script_int.num))) + in + (step [@ocaml.tailcall]) g gas k ks accu stack + | ISplit_ticket (_, k) -> + let ticket = accu and (amount_a, amount_b), stack = stack in + let result = + Option.bind (Ticket_amount.of_n amount_a) @@ fun amount_a -> + Option.bind (Ticket_amount.of_n amount_b) @@ fun amount_b -> + let amount = Ticket_amount.add amount_a amount_b in + if + Compare.Int.( + Script_int.( + compare (amount :> n num) (ticket.amount :> n num)) + = 0) + then + Some + ( {ticket with amount = amount_a}, + {ticket with amount = amount_b} ) + else None + in + (step [@ocaml.tailcall]) g gas k ks result stack + | IJoin_tickets (_, contents_ty, k) -> + let ticket_a, ticket_b = accu in + let result = + if + Compare.Int.( + Contract.compare ticket_a.ticketer ticket_b.ticketer = 0 + && Script_comparable.compare_comparable + contents_ty + ticket_a.contents + ticket_b.contents + = 0) + then + Some + { + ticketer = ticket_a.ticketer; + contents = ticket_a.contents; + amount = Ticket_amount.add ticket_a.amount ticket_b.amount; + } + else None + in + (step [@ocaml.tailcall]) g gas k ks result stack + | IOpen_chest (_, k) -> + let open Timelock in + let chest_key = accu in + let chest, (time_z, stack) = stack in + (* If the time is not an integer we then consider the proof as + incorrect. Indeed the verification asks for an integer for practical reasons. + Therefore no proof can be correct.*) + let accu = + match Script_int.to_int time_z with + | None -> None + | Some time -> ( + match Script_timelock.open_chest chest chest_key ~time with + | Correct bytes -> Some bytes + | Bogus_opening -> None) + in + (step [@ocaml.tailcall]) g gas k ks accu stack + | IEmit {tag; ty = event_type; unparsed_ty; k; loc = _} -> + let event_data = accu in + let* accu, ctxt, gas = + emit_event + (ctxt, sc) + gas + ~event_type + ~unparsed_ty + ~tag + ~event_data + in + (step [@ocaml.tailcall]) (ctxt, sc) gas k ks accu stack) +end + +open Raw + +(* + + Entrypoints + =========== + +*) + +let step_descr ~log_now logger (ctxt, sc) descr accu stack = + let open Lwt_result_syntax in + let gas, outdated_ctxt = local_gas_counter_and_outdated_context ctxt in + let* accu, stack, ctxt, gas = + match logger with + | None -> step (outdated_ctxt, sc) gas descr.kinstr KNil accu stack + | Some logger -> + (if log_now then + let loc = kinstr_location descr.kinstr in + logger.log_interp descr.kinstr ctxt loc descr.kbef (accu, stack)) ; + let log = + ILog + ( kinstr_location descr.kinstr, + descr.kbef, + LogEntry, + logger, + descr.kinstr ) + in + let knil = KLog (KNil, descr.kaft, logger) in + step (outdated_ctxt, sc) gas log knil accu stack + in + return (accu, stack, update_context gas ctxt) + +let interp logger g lam arg = + let open Lwt_result_syntax in + match lam with + | LamRec (code, _) -> + let+ ret, (EmptyCell, EmptyCell), ctxt = + step_descr ~log_now:true logger g code arg (lam, (EmptyCell, EmptyCell)) + in + (ret, ctxt) + | Lam (code, _) -> + let+ ret, (EmptyCell, EmptyCell), ctxt = + step_descr ~log_now:true logger g code arg (EmptyCell, EmptyCell) + in + (ret, ctxt) + +(* + + High-level functions + ==================== + +*) +type execution_arg = + | Typed_arg : + Script.location * ('a, _) Script_typed_ir.ty * 'a + -> execution_arg + | Untyped_arg : Script.expr -> execution_arg + +let lift_execution_arg (type a ac) ctxt ~internal (entrypoint_ty : (a, ac) ty) + (construct : a -> 'b) arg : ('b * context) tzresult Lwt.t = + let open Lwt_result_syntax in + let* entrypoint_arg, ctxt = + match arg with + | Untyped_arg arg -> + let arg = Micheline.root arg in + parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + ~allow_forged_tickets:internal + ~allow_forged_lazy_storage_id:internal + entrypoint_ty + arg + | Typed_arg (loc, parsed_arg_ty, parsed_arg) -> + let*? res, ctxt = + Gas_monad.run + ctxt + (Script_ir_translator.ty_eq + ~error_details:(Informative loc) + entrypoint_ty + parsed_arg_ty) + in + let*? Eq = res in + let parsed_arg : a = parsed_arg in + return (parsed_arg, ctxt) + in + return (construct entrypoint_arg, ctxt) + +type execution_result = { + script : Script_ir_translator.ex_script; + code_size : int; + storage : Script.expr; + lazy_storage_diff : Lazy_storage.diffs option; + operations : packed_internal_operation list; + ticket_diffs : Z.t Ticket_token_map.t; + ticket_receipt : Ticket_receipt.t; +} + +let execute_any_arg logger ctxt mode step_constants ~entrypoint ~internal + unparsed_script cached_script arg = + let open Lwt_result_syntax in + let elab_conf = + Script_ir_translator_config.make + ~legacy:true + ~keep_extra_types_for_interpreter_logging:(Option.is_some logger) + () + in + let* ( Ex_script + (Script + { + code_size; + code; + arg_type; + storage = old_storage; + storage_type; + entrypoints; + views; + }), + ctxt ) = + match cached_script with + | None -> + parse_script + ctxt + unparsed_script + ~elab_conf + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + | Some ex_script -> return (ex_script, ctxt) + in + let*? r, ctxt = + Gas_monad.run + ctxt + (find_entrypoint + ~error_details:(Informative ()) + arg_type + entrypoints + entrypoint) + in + let self_contract = Contract.Originated step_constants.self in + let*? (Ex_ty_cstr {ty = entrypoint_ty; construct; original_type_expr = _}) = + record_trace (Bad_contract_parameter self_contract) r + in + let* arg, ctxt = + trace + (Bad_contract_parameter self_contract) + (lift_execution_arg ctxt ~internal entrypoint_ty construct arg) + in + let*? to_duplicate, ctxt = + Script_ir_translator.collect_lazy_storage ctxt arg_type arg + in + let*? to_update, ctxt = + Script_ir_translator.collect_lazy_storage ctxt storage_type old_storage + in + let* (ops, new_storage), ctxt = + trace + (Runtime_contract_error step_constants.self) + (interp logger (ctxt, step_constants) code (arg, old_storage)) + in + let* storage, lazy_storage_diff, ctxt = + Script_ir_translator.extract_lazy_storage_diff + ctxt + mode + ~temporary:false + ~to_duplicate + ~to_update + storage_type + new_storage + in + let* unparsed_storage, ctxt = + trace Cannot_serialize_storage (unparse_data ctxt mode storage_type storage) + in + let op_to_couple op = (op.piop, op.lazy_storage_diff) in + let operations, op_diffs = + ops.elements |> List.map op_to_couple |> List.split + in + let lazy_storage_diff_all = + match + List.flatten + (List.map (Option.value ~default:[]) (op_diffs @ [lazy_storage_diff])) + with + | [] -> None + | diff -> Some diff + in + let script = + Ex_script + (Script + {code_size; code; arg_type; storage; storage_type; entrypoints; views}) + in + let*? arg_type_has_tickets, ctxt = + Ticket_scanner.type_has_tickets ctxt arg_type + in + let*? storage_type_has_tickets, ctxt = + Ticket_scanner.type_has_tickets ctxt storage_type + in + (* Collect the ticket diffs *) + let* ticket_diffs, ticket_receipt, ctxt = + Ticket_accounting.ticket_diffs + ctxt + ~self_contract + ~arg_type_has_tickets + ~storage_type_has_tickets + ~arg + ~old_storage + ~new_storage + ~lazy_storage_diff:(Option.value ~default:[] lazy_storage_diff) + in + (* We consume gas after the fact in order to not have to instrument + [script_size] (for efficiency). + This is safe, as we already pay gas proportional to storage size + in [unparse_data]. *) + let size, cost = Script_ir_translator.script_size script in + let*? ctxt = Gas.consume ctxt cost in + return + ( { + script; + code_size = size; + storage = unparsed_storage; + lazy_storage_diff = lazy_storage_diff_all; + operations; + ticket_diffs; + ticket_receipt; + }, + ctxt ) + +let execute_with_typed_parameter ?logger ctxt ~cached_script mode step_constants + ~script ~entrypoint ~parameter_ty ~location ~parameter ~internal = + execute_any_arg + logger + ctxt + mode + step_constants + ~entrypoint + ~internal + script + cached_script + (Typed_arg (location, parameter_ty, parameter)) + +let execute ?logger ctxt ~cached_script mode step_constants ~script ~entrypoint + ~parameter ~internal = + execute_any_arg + logger + ctxt + mode + step_constants + ~entrypoint + ~internal + script + cached_script + (Untyped_arg parameter) + +(* + + Internals + ========= + +*) + +(* + + We export the internals definitions for tool that requires + a white-box view on the interpreter, typically snoop, the + gas model inference engine. + +*) +module Internals = struct + let next logger g gas sty ks accu stack = + let ks = + match logger with None -> ks | Some logger -> KLog (ks, sty, logger) + in + next g gas ks accu stack + + let kstep logger ctxt step_constants sty kinstr accu stack = + let open Lwt_result_syntax in + let kinstr = + match logger with + | None -> kinstr + | Some logger -> + ILog (kinstr_location kinstr, sty, LogEntry, logger, kinstr) + in + let gas, outdated_ctxt = local_gas_counter_and_outdated_context ctxt in + let* accu, stack, ctxt, gas = + step (outdated_ctxt, step_constants) gas kinstr KNil accu stack + in + return (accu, stack, update_context gas ctxt) + + let step (ctxt, step_constants) gas ks accu stack = + step (ctxt, step_constants) gas ks KNil accu stack + + let step_descr logger ctxt step_constants descr stack = + step_descr ~log_now:false logger (ctxt, step_constants) descr stack + + module Raw = Raw +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_interpreter.mli b/src/proto_020_PsParisC/lib_protocol/script_interpreter.mli new file mode 100644 index 000000000000..193a5c4d5b2a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_interpreter.mli @@ -0,0 +1,253 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This is the Michelson interpreter. + + This module offers a way to execute either a Michelson script or a + Michelson instruction. + + Implementation details are documented in the .ml file. + +*) + +open Alpha_context +open Script_typed_ir + +type error += Reject of Script.location * Script.expr * execution_trace option + +type error += Overflow of Script.location * execution_trace option + +type error += Runtime_contract_error of Contract_hash.t + +type error += Bad_contract_parameter of Contract.t (* `Permanent *) + +type error += Cannot_serialize_failure + +type error += Cannot_serialize_storage + +type error += Michelson_too_many_recursive_calls + +(** The result from script interpretation. *) +type execution_result = { + script : Script_ir_translator.ex_script; + code_size : int; + storage : Script.expr; + lazy_storage_diff : Lazy_storage.diffs option; + operations : packed_internal_operation list; + ticket_diffs : Z.t Ticket_token_map.t; + ticket_receipt : Ticket_receipt.t; +} + +type step_constants = Script_typed_ir.step_constants = { + sender : Destination.t; + payer : Signature.public_key_hash; + self : Contract_hash.t; + amount : Tez.t; + balance : Tez.t; + chain_id : Chain_id.t; + now : Script_timestamp.t; + level : Script_int.n Script_int.num; +} + +(** [execute ?logger ctxt ~cached_script mode step_constant ~script + ~entrypoint ~parameter ~internal] interprets the [script]'s + [entrypoint] for a given [parameter]. + + This will update the local storage of the contract + [step_constants.self]. Other pieces of contextual information + ([sender], [payer], [amount], and [chain_id]) are also passed in + [step_constant]. + + [internal] is [true] if and only if the execution happens within an + internal operation. + + [mode] is the unparsing mode, as declared by + {!Script_ir_translator}. + + [cached_script] is the cached elaboration of [script], that is the + well typed abstract syntax tree produced by the type elaboration of + [script] during a previous execution and stored in the in-memory + cache. + +*) +val execute : + ?logger:logger -> + Alpha_context.t -> + cached_script:Script_ir_translator.ex_script option -> + Script_ir_unparser.unparsing_mode -> + step_constants -> + script:Script.t -> + entrypoint:Entrypoint.t -> + parameter:Script.expr -> + internal:bool -> + (execution_result * context) tzresult Lwt.t + +(** [execute_with_typed_parameter ?logger ctxt ~cached_script mode + step_constant ~script ~entrypoint loc ~parameter_ty ~parameter ~internal] + interprets the [script]'s [entrypoint] for a given (typed) [parameter]. + + See {!execute} for more details about the function's arguments. +*) +val execute_with_typed_parameter : + ?logger:logger -> + Alpha_context.context -> + cached_script:Script_ir_translator.ex_script option -> + Script_ir_unparser.unparsing_mode -> + step_constants -> + script:Script.t -> + entrypoint:Entrypoint.t -> + parameter_ty:('a, _) Script_typed_ir.ty -> + location:Script.location -> + parameter:'a -> + internal:bool -> + (execution_result * context) tzresult Lwt.t + +(** Internal interpretation loop + ============================ + + The following types and the following functions are exposed + in the interface to allow the inference of a gas model in + snoop. + + Strictly speaking, they should not be considered as part of + the interface since they expose implementation details that + may change in the future. + +*) + +module Internals : sig + (** Internally, the interpretation loop uses a local gas counter. *) + + (** [next logger (ctxt, step_constants) local_gas_counter ks accu + stack] is an internal function which interprets the continuation + [ks] to execute the interpreter on the current A-stack. *) + val next : + logger option -> + Local_gas_counter.outdated_context * step_constants -> + Local_gas_counter.local_gas_counter -> + ('a, 's) stack_ty -> + ('a, 's, 'r, 'f) continuation -> + 'a -> + 's -> + ('r + * 'f + * Local_gas_counter.outdated_context + * Local_gas_counter.local_gas_counter) + tzresult + Lwt.t + + val step : + Local_gas_counter.outdated_context * step_constants -> + Local_gas_counter.local_gas_counter -> + ('a, 's, 'r, 'f) Script_typed_ir.kinstr -> + 'a -> + 's -> + ('r + * 'f + * Local_gas_counter.outdated_context + * Local_gas_counter.local_gas_counter) + tzresult + Lwt.t + + val step_descr : + logger option -> + context -> + Script_typed_ir.step_constants -> + ('a, 's, 'r, 'f) Script_typed_ir.kdescr -> + 'a -> + 's -> + ('r * 'f * context) tzresult Lwt.t + + (** [kstep logger ctxt step_constants kinstr accu stack] interprets the + script represented by [kinstr] under the context [ctxt]. This will + turn a stack whose topmost element is [accu] and remaining elements + [stack] into a new accumulator and a new stack. This function also + returns an updated context. If [logger] is given, [kstep] calls back + its functions at specific points of the execution. The execution is + parameterized by some [step_constants]. *) + val kstep : + logger option -> + context -> + step_constants -> + ('a, 's) stack_ty -> + ('a, 's, 'r, 'f) Script_typed_ir.kinstr -> + 'a -> + 's -> + ('r * 'f * context) tzresult Lwt.t + + module Raw : sig + open Local_gas_counter + open Script_interpreter_defs + + val kmap_exit : ('a, 'b, 'c, 'e, 'f, 'm, 'n, 'o) kmap_exit_type + + val kmap_enter : ('a, 'b, 'c, 'd, 'f, 'i, 'j, 'k) kmap_enter_type + + val klist_exit : ('a, 'b, 'c, 'd, 'e, 'i, 'j) klist_exit_type + + val klist_enter : ('a, 'b, 'c, 'd, 'e, 'f, 'j) klist_enter_type + + val kloop_in_left : ('a, 'b, 'c, 'd, 'e, 'f, 'g) kloop_in_left_type + + val kloop_in : ('a, 'b, 'c, 'r, 'f, 's) kloop_in_type + + val kiter : ('a, 'b, 's, 'r, 'f, 'c) kiter_type + + val next : + outdated_context * step_constants -> + local_gas_counter -> + ('a, 's, 'r, 'f) continuation -> + 'a -> + 's -> + ('r * 'f * outdated_context * local_gas_counter) tzresult Lwt.t + + val ilist_map : ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i) ilist_map_type + + val ilist_iter : ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'cmp) ilist_iter_type + + val iset_iter : ('a, 'b, 'c, 'd, 'e, 'f, 'g) iset_iter_type + + val imap_map : ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j) imap_map_type + + val imap_iter : ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'cmp) imap_iter_type + + val imul_teznat : ('a, 'b, 'c, 'd, 'e, 'f) imul_teznat_type + + val imul_nattez : ('a, 'b, 'c, 'd, 'e, 'f) imul_nattez_type + + val ilsl_nat : ('a, 'b, 'c, 'd, 'e, 'f) ilsl_nat_type + + val ilsr_nat : ('a, 'b, 'c, 'd, 'e, 'f) ilsr_nat_type + + val ifailwith : ifailwith_type + + val iexec : ('a, 'b, 'c, 'd, 'e, 'f, 'g) iexec_type + + val iview : ('a, 'b, 'c, 'd, 'e, 'f, 'i, 'o) iview_type + + val step : ('a, 's, 'b, 't, 'r, 'f) step_type + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_interpreter_defs.ml b/src/proto_020_PsParisC/lib_protocol/script_interpreter_defs.ml new file mode 100644 index 000000000000..f63fcd930472 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_interpreter_defs.ml @@ -0,0 +1,1070 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + + This module provides auxiliary definitions used in the interpreter. + + These are internal private definitions. Do not rely on them outside + the interpreter. + +*) + +open Alpha_context +open Script +open Script_typed_ir +open Script_ir_translator +open Local_gas_counter + +type error += Rollup_invalid_transaction_amount | Rollup_invalid_entrypoint + +let () = + register_error_kind + `Permanent + ~id:"operation.rollup_invalid_transaction_amount" + ~title:"Transaction amount to a rollup must be zero" + ~description: + "Because rollups are outside of the delegation mechanism of Tezos, they \ + cannot own Tez, and therefore transactions targeting a rollup must have \ + its amount field set to zero." + ~pp:(fun ppf () -> + Format.pp_print_string ppf "Transaction amount to a rollup must be zero.") + Data_encoding.unit + (function Rollup_invalid_transaction_amount -> Some () | _ -> None) + (fun () -> Rollup_invalid_transaction_amount) ; + register_error_kind + `Permanent + ~id:"operation.rollup_invalid_entrypoint" + ~title:"Only the default entrypoint is allowed for rollups" + ~description:"Rollups only support transactions to the default entrypoint." + ~pp:(fun ppf () -> + Format.pp_print_string + ppf + "Rollups only support transactions to the default entrypoint.") + Data_encoding.unit + (function Rollup_invalid_entrypoint -> Some () | _ -> None) + (fun () -> Rollup_invalid_entrypoint) + +(* + + Computing the cost of Michelson instructions + ============================================ + + The function [cost_of_instr] provides a cost model for Michelson + instructions. It is used by the interpreter to track the + consumption of gas. This consumption may depend on the values + on the stack. + + *) + +module Interp_costs = Michelson_v1_gas.Cost_of.Interpreter + +let cost_of_instr : type a s r f. (a, s, r, f) kinstr -> a -> s -> Gas.cost = + fun i accu stack -> + match i with + | IList_map _ -> + let list = accu in + Interp_costs.list_map list + | IList_iter _ -> + let list = accu in + Interp_costs.list_iter list + | ISet_iter _ -> + let set = accu in + Interp_costs.set_iter set + | ISet_mem _ -> + let v = accu and set, _ = stack in + Interp_costs.set_mem v set + | ISet_update _ -> + let v = accu and _, (set, _) = stack in + Interp_costs.set_update v set + | IMap_map _ -> + let map = accu in + Interp_costs.map_map map + | IMap_iter _ -> + let map = accu in + Interp_costs.map_iter map + | IMap_mem _ -> + let v = accu and map, _ = stack in + Interp_costs.map_mem v map + | IMap_get _ -> + let v = accu and map, _ = stack in + Interp_costs.map_get v map + | IMap_update _ -> + let k = accu and _, (map, _) = stack in + Interp_costs.map_update k map + | IMap_get_and_update _ -> + let k = accu and _, (map, _) = stack in + Interp_costs.map_get_and_update k map + | IBig_map_mem _ -> + let Big_map map, _ = stack in + Interp_costs.big_map_mem map.diff + | IBig_map_get _ -> + let Big_map map, _ = stack in + Interp_costs.big_map_get map.diff + | IBig_map_update _ -> + let _, (Big_map map, _) = stack in + Interp_costs.big_map_update map.diff + | IBig_map_get_and_update _ -> + let _, (Big_map map, _) = stack in + Interp_costs.big_map_get_and_update map.diff + | IAdd_seconds_to_timestamp _ -> + let n = accu and t, _ = stack in + Interp_costs.add_seconds_timestamp n t + | IAdd_timestamp_to_seconds _ -> + let t = accu and n, _ = stack in + Interp_costs.add_timestamp_seconds t n + | ISub_timestamp_seconds _ -> + let t = accu and n, _ = stack in + Interp_costs.sub_timestamp_seconds t n + | IDiff_timestamps _ -> + let t1 = accu and t2, _ = stack in + Interp_costs.diff_timestamps t1 t2 + | IConcat_string_pair _ -> + let x = accu and y, _ = stack in + Interp_costs.concat_string_pair x y + | IConcat_string _ -> + let ss = accu in + Interp_costs.concat_string_precheck ss + | ISlice_string _ -> + let (_offset : Script_int.n Script_int.num) = accu in + let _length, (s, _) = stack in + Interp_costs.slice_string s + | IConcat_bytes_pair _ -> + let x = accu and y, _ = stack in + Interp_costs.concat_bytes_pair x y + | IConcat_bytes _ -> + let ss = accu in + Interp_costs.concat_string_precheck ss + | ISlice_bytes _ -> + let _, (s, _) = stack in + Interp_costs.slice_bytes s + | IBytes_nat _ -> + let n = accu in + Interp_costs.bytes_nat n + | INat_bytes _ -> + let b = accu in + Interp_costs.nat_bytes b + | IBytes_int _ -> + let n = accu in + Interp_costs.bytes_int n + | IInt_bytes _ -> + let b = accu in + Interp_costs.int_bytes b + | IMul_teznat _ -> Interp_costs.mul_teznat + | IMul_nattez _ -> Interp_costs.mul_nattez + | IAbs_int _ -> + let x = accu in + Interp_costs.abs_int x + | INeg _ -> + let x = accu in + Interp_costs.neg x + | IAdd_int _ -> + let x = accu and y, _ = stack in + Interp_costs.add_int x y + | IAdd_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.add_nat x y + | ISub_int _ -> + let x = accu and y, _ = stack in + Interp_costs.sub_int x y + | IMul_int _ -> + let x = accu and y, _ = stack in + Interp_costs.mul_int x y + | IMul_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.mul_nat x y + | IEdiv_teznat _ -> + let x = accu and y, _ = stack in + Interp_costs.ediv_teznat x y + | IEdiv_int _ -> + let x = accu and y, _ = stack in + Interp_costs.ediv_int x y + | IEdiv_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.ediv_nat x y + | ILsl_nat _ -> + let x = accu in + Interp_costs.lsl_nat x + | ILsl_bytes _ -> + let x = accu in + let y, _ = stack in + Interp_costs.lsl_bytes x y + | ILsr_nat _ -> + let x = accu in + Interp_costs.lsr_nat x + | ILsr_bytes _ -> + let x = accu in + let y, _ = stack in + Interp_costs.lsr_bytes x y + | IOr_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.or_nat x y + | IOr_bytes _ -> + let x = accu and y, _ = stack in + Interp_costs.or_bytes x y + | IAnd_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.and_nat x y + | IAnd_int_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.and_int_nat x y + | IAnd_bytes _ -> + let x = accu and y, _ = stack in + Interp_costs.and_bytes x y + | IXor_nat _ -> + let x = accu and y, _ = stack in + Interp_costs.xor_nat x y + | IXor_bytes _ -> + let x = accu and y, _ = stack in + Interp_costs.xor_bytes x y + | INot_int _ -> + let x = accu in + Interp_costs.not_int x + | INot_bytes _ -> + let x = accu in + Interp_costs.not_bytes x + | ICompare (_, ty, _) -> + let a = accu and b, _ = stack in + Interp_costs.compare ty a b + | ICheck_signature _ -> + let key = accu and _, (message, _) = stack in + Interp_costs.check_signature key message + | IHash_key _ -> + let pk = accu in + Interp_costs.hash_key pk + | IBlake2b _ -> + let bytes = accu in + Interp_costs.blake2b bytes + | ISha256 _ -> + let bytes = accu in + Interp_costs.sha256 bytes + | ISha512 _ -> + let bytes = accu in + Interp_costs.sha512 bytes + | IKeccak _ -> + let bytes = accu in + Interp_costs.keccak bytes + | ISha3 _ -> + let bytes = accu in + Interp_costs.sha3 bytes + | IPairing_check_bls12_381 _ -> + let pairs = accu in + Interp_costs.pairing_check_bls12_381 pairs + | ISapling_verify_update _ -> + let tx = accu in + let inputs = Gas_input_size.sapling_transaction_inputs tx in + let outputs = Gas_input_size.sapling_transaction_outputs tx in + let bound_data = Gas_input_size.sapling_transaction_bound_data tx in + Interp_costs.sapling_verify_update ~inputs ~outputs ~bound_data + | ISapling_verify_update_deprecated _ -> + let tx = accu in + let inputs = List.length tx.inputs in + let outputs = List.length tx.outputs in + Interp_costs.sapling_verify_update_deprecated ~inputs ~outputs + | ISplit_ticket _ -> + let (amount_a, amount_b), _ = stack in + Interp_costs.split_ticket amount_a amount_b + | IJoin_tickets (_, ty, _) -> + let ticket_a, ticket_b = accu in + Interp_costs.join_tickets ty ticket_a ticket_b + | IHalt _ -> Interp_costs.halt + | IDrop _ -> Interp_costs.drop + | IDup _ -> Interp_costs.dup + | ISwap _ -> Interp_costs.swap + | IPush _ -> Interp_costs.push + | IUnit _ -> Interp_costs.unit + | ICons_some _ -> Interp_costs.cons_some + | ICons_none _ -> Interp_costs.cons_none + | IIf_none _ -> Interp_costs.if_none + | IOpt_map _ -> Interp_costs.opt_map + | ICons_pair _ -> Interp_costs.cons_pair + | IUnpair _ -> Interp_costs.unpair + | ICar _ -> Interp_costs.car + | ICdr _ -> Interp_costs.cdr + | ICons_left _ -> Interp_costs.cons_left + | ICons_right _ -> Interp_costs.cons_right + | IIf_left _ -> Interp_costs.if_left + | ICons_list _ -> Interp_costs.cons_list + | INil _ -> Interp_costs.nil + | IIf_cons _ -> Interp_costs.if_cons + | IList_size _ -> Interp_costs.list_size + | IEmpty_set _ -> Interp_costs.empty_set + | ISet_size _ -> Interp_costs.set_size + | IEmpty_map _ -> Interp_costs.empty_map + | IMap_size _ -> Interp_costs.map_size + | IEmpty_big_map _ -> Interp_costs.empty_big_map + | IString_size _ -> Interp_costs.string_size + | IBytes_size _ -> Interp_costs.bytes_size + | IAdd_tez _ -> Interp_costs.add_tez + | ISub_tez _ -> Interp_costs.sub_tez + | ISub_tez_legacy _ -> Interp_costs.sub_tez_legacy + | IOr _ -> Interp_costs.bool_or + | IAnd _ -> Interp_costs.bool_and + | IXor _ -> Interp_costs.bool_xor + | INot _ -> Interp_costs.bool_not + | IIs_nat _ -> Interp_costs.is_nat + | IInt_nat _ -> Interp_costs.int_nat + | IInt_bls12_381_fr _ -> Interp_costs.int_bls12_381_fr + | IEdiv_tez _ -> Interp_costs.ediv_tez + | IIf _ -> Interp_costs.if_ + | ILoop _ -> Interp_costs.loop + | ILoop_left _ -> Interp_costs.loop_left + | IDip _ -> Interp_costs.dip + | IExec _ -> Interp_costs.exec + | IApply _ -> ( + let l, _ = stack in + match l with + | Lam _ -> Interp_costs.apply ~rec_flag:false + | LamRec _ -> Interp_costs.apply ~rec_flag:true) + | ILambda _ -> Interp_costs.lambda + | IFailwith _ -> Gas.free + | IEq _ -> Interp_costs.eq + | INeq _ -> Interp_costs.neq + | ILt _ -> Interp_costs.lt + | ILe _ -> Interp_costs.le + | IGt _ -> Interp_costs.gt + | IGe _ -> Interp_costs.ge + | IPack _ -> Gas.free + | IUnpack _ -> + let b = accu in + Interp_costs.unpack b + | IAddress _ -> Interp_costs.address + | IContract _ -> Interp_costs.contract + | ITransfer_tokens _ -> Interp_costs.transfer_tokens + | IView _ -> Interp_costs.view + | IImplicit_account _ -> Interp_costs.implicit_account + | ISet_delegate _ -> Interp_costs.set_delegate + | IBalance _ -> Interp_costs.balance + | ILevel _ -> Interp_costs.level + | INow _ -> Interp_costs.now + | IMin_block_time _ -> Interp_costs.min_block_time + | ISapling_empty_state _ -> Interp_costs.sapling_empty_state + | ISource _ -> Interp_costs.source + | ISender _ -> Interp_costs.sender + | ISelf _ -> Interp_costs.self + | ISelf_address _ -> Interp_costs.self_address + | IAmount _ -> Interp_costs.amount + | IDig (_, n, _, _) -> Interp_costs.dign n + | IDug (_, n, _, _) -> Interp_costs.dugn n + | IDipn (_, n, _, _, _) -> Interp_costs.dipn n + | IDropn (_, n, _, _) -> Interp_costs.dropn n + | IChainId _ -> Interp_costs.chain_id + | ICreate_contract _ -> Interp_costs.create_contract + | INever _ -> ( match accu with _ -> .) + | IVoting_power _ -> Interp_costs.voting_power + | ITotal_voting_power _ -> Interp_costs.total_voting_power + | IAdd_bls12_381_g1 _ -> Interp_costs.add_bls12_381_g1 + | IAdd_bls12_381_g2 _ -> Interp_costs.add_bls12_381_g2 + | IAdd_bls12_381_fr _ -> Interp_costs.add_bls12_381_fr + | IMul_bls12_381_g1 _ -> Interp_costs.mul_bls12_381_g1 + | IMul_bls12_381_g2 _ -> Interp_costs.mul_bls12_381_g2 + | IMul_bls12_381_fr _ -> Interp_costs.mul_bls12_381_fr + | INeg_bls12_381_g1 _ -> Interp_costs.neg_bls12_381_g1 + | INeg_bls12_381_g2 _ -> Interp_costs.neg_bls12_381_g2 + | INeg_bls12_381_fr _ -> Interp_costs.neg_bls12_381_fr + | IMul_bls12_381_fr_z _ -> + let z = accu in + Interp_costs.mul_bls12_381_fr_z z + | IMul_bls12_381_z_fr _ -> + let z, _ = stack in + Interp_costs.mul_bls12_381_z_fr z + | IDup_n (_, n, _, _) -> Interp_costs.dupn n + | IComb (_, n, _, _) -> Interp_costs.comb n + | IUncomb (_, n, _, _) -> Interp_costs.uncomb n + | IComb_get (_, n, _, _) -> Interp_costs.comb_get n + | IComb_set (_, n, _, _) -> Interp_costs.comb_set n + | ITicket _ | ITicket_deprecated _ -> Interp_costs.ticket + | IRead_ticket _ -> Interp_costs.read_ticket + | IOpen_chest _ -> + let (_chest_key : Script_timelock.chest_key) = accu + and chest, (time, _) = stack in + Interp_costs.open_chest ~chest ~time:(Script_int.to_zint time) + | IEmit _ -> Interp_costs.emit + | ILog _ -> Gas.free + [@@ocaml.inline always] + +let cost_of_control : type a s r f. (a, s, r, f) continuation -> Gas.cost = + fun ks -> + match ks with + | KLog _ -> Gas.free + | KNil -> Interp_costs.Control.nil + | KCons (_, _) -> Interp_costs.Control.cons + | KReturn _ -> Interp_costs.Control.return + | KMap_head (_, _) -> Interp_costs.Control.map_head + | KUndip (_, _, _) -> Interp_costs.Control.undip + | KLoop_in (_, _) -> Interp_costs.Control.loop_in + | KLoop_in_left (_, _) -> Interp_costs.Control.loop_in_left + | KIter (_, _, _, _) -> Interp_costs.Control.iter + | KList_enter_body (_, xs, _, _, len, _) -> + Interp_costs.Control.list_enter_body xs len + | KList_exit_body (_, _, _, _, _, _) -> Interp_costs.Control.list_exit_body + | KMap_enter_body (_, _, map, _, _) -> Interp_costs.Control.map_enter_body map + | KMap_exit_body (_, _, map, key, _, _) -> + Interp_costs.Control.map_exit_body key map + | KView_exit (_, _) -> Interp_costs.Control.view_exit + +(* + + [step] calls [consume_instr] at the beginning of each execution step. + + [Local_gas_counter.consume] is used in the implementation of + [IConcat_string] and [IConcat_bytes] because in that special cases, the + cost is expressed with respect to a non-constant-time computation on the + inputs. + +*) + +let consume_instr local_gas_counter k accu stack = + let cost = cost_of_instr k accu stack in + consume_opt local_gas_counter cost + [@@ocaml.inline always] + +let consume_control local_gas_counter ks = + let cost = cost_of_control ks in + consume_opt local_gas_counter cost + [@@ocaml.inline always] + +let get_log = function None -> return_none | Some logger -> logger.get_log () + [@@ocaml.inline always] + +(* + + Auxiliary functions used by the interpretation loop + =================================================== + +*) + +(* The following function pops n elements from the stack + and push their reintroduction in the continuations stack. *) +let rec kundip : + type a s e z c u d w b t. + (a, s, e, z, c, u, d, w) stack_prefix_preservation_witness -> + c -> + u -> + (d, w, b, t) continuation -> + a * s * (e, z, b, t) continuation = + fun w accu stack ks -> + match w with + | KPrefix (_loc, ty, w) -> + let ks = KUndip (accu, Some ty, ks) in + let accu, stack = stack in + kundip w accu stack ks + | KRest -> (accu, stack, ks) + +(* [apply ctxt gas ty v lam] specializes [lam] by fixing its first + formal argument to [v]. The type of [v] is represented by [ty]. *) +let apply ctxt gas capture_ty capture lam = + let open Lwt_result_syntax in + let loc = Micheline.dummy_location in + let ctxt = update_context gas ctxt in + let*? ty_expr, ctxt = Script_ir_unparser.unparse_ty ~loc ctxt capture_ty in + let* const_expr, ctxt = unparse_data ctxt Optimized capture_ty capture in + let make_expr expr = + Micheline.( + Seq + ( loc, + Prim (loc, I_PUSH, [ty_expr; Micheline.root const_expr], []) + :: Prim (loc, I_PAIR, [], []) + :: expr )) + in + let lam' = + match lam with + | LamRec (descr, expr) -> ( + let (Item_t (full_arg_ty, Item_t (Lambda_t (_, _, _), Bot_t))) = + descr.kbef + in + let (Item_t (ret_ty, Bot_t)) = descr.kaft in + let*? arg_ty_expr, ctxt = + Script_ir_unparser.unparse_ty ~loc ctxt full_arg_ty + in + let*? ret_ty_expr, ctxt = + Script_ir_unparser.unparse_ty ~loc ctxt ret_ty + in + match full_arg_ty with + | Pair_t (capture_ty, arg_ty, _, _) -> + let arg_stack_ty = Item_t (arg_ty, Bot_t) in + (* To avoid duplicating the recursive lambda [lam], we + return a regular lambda that builds the tuple of + parameters and applies it to `lam`. Since `lam` is + recursive it will push itself on top of the stack at + execution time. *) + let full_descr = + { + kloc = descr.kloc; + kbef = arg_stack_ty; + kaft = descr.kaft; + kinstr = + IPush + ( descr.kloc, + capture_ty, + capture, + ICons_pair + ( descr.kloc, + ILambda + ( descr.kloc, + lam, + ISwap + ( descr.kloc, + IExec + ( descr.kloc, + Some descr.kaft, + IHalt descr.kloc ) ) ) ) ); + } + in + let full_expr = + make_expr + Micheline. + [ + Prim + (loc, I_LAMBDA_REC, [arg_ty_expr; ret_ty_expr; expr], []); + Prim (loc, I_SWAP, [], []); + Prim (loc, I_EXEC, [], []); + ] + in + return (Lam (full_descr, full_expr), ctxt)) + | Lam (descr, expr) -> ( + let (Item_t (full_arg_ty, Bot_t)) = descr.kbef in + match full_arg_ty with + | Pair_t (capture_ty, arg_ty, _, _) -> + let arg_stack_ty = Item_t (arg_ty, Bot_t) in + let full_descr = + { + kloc = descr.kloc; + kbef = arg_stack_ty; + kaft = descr.kaft; + kinstr = + IPush + ( descr.kloc, + capture_ty, + capture, + ICons_pair (descr.kloc, descr.kinstr) ); + } + in + let full_expr = make_expr [expr] in + return (Lam (full_descr, full_expr), ctxt)) + in + let* lam', ctxt = lam' in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + return (lam', ctxt, gas) + +let make_transaction_to_sc_rollup ctxt ~destination ~amount ~entrypoint + ~parameters_ty ~parameters = + let open Lwt_result_syntax in + let*? () = + error_unless Tez.(amount = zero) Rollup_invalid_transaction_amount + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4023 + We currently don't support entrypoints as the entrypoint information + for L1 to L2 messages is not propagated to the rollup. *) + let*? () = + error_unless (Entrypoint.is_default entrypoint) Rollup_invalid_entrypoint + in + let+ unparsed_parameters, ctxt = + unparse_data ctxt Optimized parameters_ty parameters + in + ( Transaction_to_sc_rollup + {destination; entrypoint; parameters_ty; parameters; unparsed_parameters}, + ctxt ) + +(** [emit_event] generates an internal operation that will effect an event emission + if the contract code returns this successfully. *) +let emit_event (type t tc) (ctxt, sc) gas ~(event_type : (t, tc) ty) + ~unparsed_ty ~tag ~(event_data : t) = + let open Lwt_result_syntax in + let ctxt = update_context gas ctxt in + (* No need to take care of lazy storage as only packable types are allowed *) + let lazy_storage_diff = None in + let* unparsed_data, ctxt = + unparse_data ctxt Optimized event_type event_data + in + let*? ctxt, nonce = fresh_internal_nonce ctxt in + let operation = Event {ty = unparsed_ty; tag; unparsed_data} in + let iop = + { + sender = Destination.Contract (Contract.Originated sc.self); + operation; + nonce; + } + in + let res = {piop = Internal_operation iop; lazy_storage_diff} in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + return (res, ctxt, gas) + +let make_transaction_to_zk_rollup (type t) ctxt ~destination ~amount + ~(parameters_ty : ((t ticket, bytes) pair, _) ty) ~parameters = + let open Lwt_result_syntax in + let*? () = + error_unless Tez.(amount = zero) Rollup_invalid_transaction_amount + in + let+ unparsed_parameters, ctxt = + unparse_data ctxt Optimized parameters_ty parameters + in + ( Transaction_to_zk_rollup + {destination; parameters_ty; parameters; unparsed_parameters}, + ctxt ) + +(* [transfer (ctxt, sc) gas tez parameters_ty parameters destination entrypoint] + creates an operation that transfers an amount of [tez] to a destination and + an entrypoint instantiated with argument [parameters] of type + [parameters_ty]. *) +let transfer (type t) (ctxt, sc) gas amount location + (typed_contract : t typed_contract) (parameters : t) = + let open Lwt_result_syntax in + let ctxt = update_context gas ctxt in + let* operation, lazy_storage_diff, ctxt = + match typed_contract with + | Typed_implicit destination -> + let () = parameters in + return (Transaction_to_implicit {destination; amount}, None, ctxt) + | Typed_implicit_with_ticket {destination; ticket_ty} -> + let* unparsed_ticket, ctxt = + unparse_data ctxt Optimized ticket_ty parameters + in + return + ( Transaction_to_implicit_with_ticket + { + destination; + amount; + ticket_ty; + ticket = parameters; + unparsed_ticket = Script.lazy_expr unparsed_ticket; + }, + None, + ctxt ) + | Typed_originated + {arg_ty = parameters_ty; contract_hash = destination; entrypoint} -> + let*? to_duplicate, ctxt = + collect_lazy_storage ctxt parameters_ty parameters + in + let to_update = no_lazy_storage_id in + let* parameters, lazy_storage_diff, ctxt = + extract_lazy_storage_diff + ctxt + Optimized + parameters_ty + parameters + ~to_duplicate + ~to_update + ~temporary:true + in + let+ unparsed_parameters, ctxt = + unparse_data ctxt Optimized parameters_ty parameters + in + ( Transaction_to_smart_contract + { + destination; + amount; + entrypoint; + location; + parameters_ty; + parameters; + unparsed_parameters; + }, + lazy_storage_diff, + ctxt ) + | Typed_sc_rollup + {arg_ty = parameters_ty; sc_rollup = destination; entrypoint} -> + let+ operation, ctxt = + make_transaction_to_sc_rollup + ctxt + ~destination + ~amount + ~entrypoint + ~parameters_ty + ~parameters + in + (operation, None, ctxt) + | Typed_zk_rollup {arg_ty = parameters_ty; zk_rollup = destination} -> + let+ operation, ctxt = + make_transaction_to_zk_rollup + ctxt + ~destination + ~amount + ~parameters_ty + ~parameters + in + (operation, None, ctxt) + in + let*? ctxt, nonce = fresh_internal_nonce ctxt in + let iop = + { + sender = Destination.Contract (Contract.Originated sc.self); + operation; + nonce; + } + in + let res = {piop = Internal_operation iop; lazy_storage_diff} in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + return (res, ctxt, gas) + +(** [create_contract (ctxt, sc) gas storage_ty code delegate credit init] + creates an origination operation for a contract represented by [code], some + initial [credit] (withdrawn from the contract being executed), and an + initial storage [init] of type [storage_ty]. *) +let create_contract (ctxt, sc) gas storage_type code delegate credit init = + let open Lwt_result_syntax in + let ctxt = update_context gas ctxt in + let*? to_duplicate, ctxt = collect_lazy_storage ctxt storage_type init in + let to_update = no_lazy_storage_id in + let* init, lazy_storage_diff, ctxt = + extract_lazy_storage_diff + ctxt + Optimized + storage_type + init + ~to_duplicate + ~to_update + ~temporary:true + in + let* unparsed_storage, ctxt = unparse_data ctxt Optimized storage_type init in + let*? ctxt, preorigination = + Contract.fresh_contract_from_current_nonce ctxt + in + let operation = + Origination + { + credit; + delegate; + code; + unparsed_storage; + preorigination; + storage_type; + storage = init; + } + in + let*? ctxt, nonce = fresh_internal_nonce ctxt in + let sender = Destination.Contract (Contract.Originated sc.self) in + let piop = Internal_operation {sender; operation; nonce} in + let res = {piop; lazy_storage_diff} in + let gas, ctxt = local_gas_counter_and_outdated_context ctxt in + return (res, preorigination, ctxt, gas) + +(* [unpack ctxt ty bytes] deserialize [bytes] into a value of type [ty]. *) +let unpack ctxt ~ty ~bytes = + let open Lwt_result_syntax in + let*? ctxt = + Gas.consume + ctxt + (Script.deserialization_cost_estimated_from_bytes (Bytes.length bytes)) + in + if + Compare.Int.(Bytes.length bytes >= 1) + && Compare.Int.(TzEndian.get_uint8 bytes 0 = 0x05) + then + let str = Bytes.sub_string bytes 1 (Bytes.length bytes - 1) in + match Data_encoding.Binary.of_string_opt Script.expr_encoding str with + | None -> + let*? ctxt = Gas.consume ctxt (Interp_costs.unpack_failed str) in + return (None, ctxt) + | Some expr -> ( + let*! value_opt = + parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ty + (Micheline.root expr) + in + match value_opt with + | Ok (value, ctxt) -> return (Some value, ctxt) + | Error _ignored -> + let*? ctxt = Gas.consume ctxt (Interp_costs.unpack_failed str) in + return (None, ctxt)) + else return (None, ctxt) + +(* [interp_stack_prefix_preserving_operation f w accu stack] applies + a well-typed operation [f] under some prefix of the A-stack + exploiting [w] to justify that the shape of the stack is + preserved. *) +let rec interp_stack_prefix_preserving_operation : + type a s b t c u d w result. + (a -> s -> (b * t) * result) -> + (a, s, b, t, c, u, d, w) stack_prefix_preservation_witness -> + c -> + u -> + (d * w) * result = + fun f n accu stk -> + match (n, stk) with + | KPrefix (_, _, n), rest -> + interp_stack_prefix_preserving_operation f n (fst rest) (snd rest) + |> fun ((v, rest'), result) -> ((accu, (v, rest')), result) + | KRest, v -> f accu v + +(* + + Some auxiliary functions have complex types and must be annotated + because of GADTs and polymorphic recursion. + + To improve readibility, we introduce their types as abbreviations: + + *) + +(* A function of this type either introduces type-preserving + instrumentation of a continuation for the purposes of logging + or returns given continuation unchanged. *) +type ('a, 'b, 'c, 'd) cont_instrumentation = + ('a, 'b, 'c, 'd) continuation -> ('a, 'b, 'c, 'd) continuation + +let id x = x + +type ('a, 'b, 'c, 'e, 'f, 'm, 'n, 'o) kmap_exit_type = + ('a, 'b, 'e, 'f) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('m * 'n, 'a * 'b, 'o, 'a * 'b) kinstr -> + ('m * 'n) list -> + (('m, 'o) map, 'c) ty option -> + ('m, 'o) map -> + 'm -> + (('m, 'o) map, 'a * 'b, 'e, 'f) continuation -> + 'o -> + 'a * 'b -> + ('e * 'f * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'j, 'k) kmap_enter_type = + ('a, 'b * 'c, 'd, 'e) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('j * 'k, 'b * 'c, 'a, 'b * 'c) kinstr -> + ('j * 'k) list -> + (('j, 'a) map, 'f) ty option -> + ('j, 'a) map -> + (('j, 'a) map, 'b * 'c, 'd, 'e) continuation -> + 'b -> + 'c -> + ('d * 'e * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'i, 'j) klist_exit_type = + ('a, 'b, 'c, 'd) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('i, 'a * 'b, 'j, 'a * 'b) kinstr -> + 'i list -> + 'j Script_list.t -> + ('j Script_list.t, 'e) ty option -> + int -> + ('j Script_list.t, 'a * 'b, 'c, 'd) continuation -> + 'j -> + 'a * 'b -> + ('c * 'd * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'j) klist_enter_type = + ('b, 'a * 'c, 'd, 'e) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('j, 'a * 'c, 'b, 'a * 'c) kinstr -> + 'j list -> + 'b Script_list.t -> + ('b Script_list.t, 'f) ty option -> + int -> + ('b Script_list.t, 'a * 'c, 'd, 'e) continuation -> + 'a -> + 'c -> + ('d * 'e * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g) kloop_in_left_type = + outdated_context * step_constants -> + local_gas_counter -> + ('c, 'd, 'e, 'f) continuation -> + ('a, 'g, 'c, 'd) kinstr -> + ('b, 'g, 'e, 'f) continuation -> + ('a, 'b) or_ -> + 'g -> + ('e * 'f * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'r, 'f, 's) kloop_in_type = + outdated_context * step_constants -> + local_gas_counter -> + ('b, 'c, 'r, 'f) continuation -> + ('a, 's, 'b, 'c) kinstr -> + ('a, 's, 'r, 'f) continuation -> + bool -> + 'a * 's -> + ('r * 'f * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 's, 'r, 'f, 'c) kiter_type = + ('a, 's, 'r, 'f) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('b, 'a * 's, 'a, 's) kinstr -> + ('b, 'c) ty option -> + 'b list -> + ('a, 's, 'r, 'f) continuation -> + 'a -> + 's -> + ('r * 'f * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i) ilist_map_type = + ('a, 'b, 'c, 'd) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('e, 'a * 'b, 'f, 'a * 'b) kinstr -> + ('f Script_list.t, 'a * 'b, 'g, 'h) kinstr -> + ('g, 'h, 'c, 'd) continuation -> + ('f Script_list.t, 'i) ty option -> + 'e Script_list.t -> + 'a * 'b -> + ('c * 'd * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'cmp) ilist_iter_type = + ('a, 'b, 'c, 'd) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('e, 'a * 'b, 'a, 'b) kinstr -> + ('e, 'cmp) ty option -> + ('a, 'b, 'f, 'g) kinstr -> + ('f, 'g, 'c, 'd) continuation -> + 'e Script_list.t -> + 'a * 'b -> + ('c * 'd * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g) iset_iter_type = + ('a, 'b, 'c, 'd) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('e, 'a * 'b, 'a, 'b) kinstr -> + 'e comparable_ty option -> + ('a, 'b, 'f, 'g) kinstr -> + ('f, 'g, 'c, 'd) continuation -> + 'e set -> + 'a * 'b -> + ('c * 'd * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j) imap_map_type = + ('a, 'b, 'c, 'd) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('e * 'f, 'a * 'b, 'g, 'a * 'b) kinstr -> + (('e, 'g) map, 'a * 'b, 'h, 'i) kinstr -> + ('h, 'i, 'c, 'd) continuation -> + (('e, 'g) map, 'j) ty option -> + ('e, 'f) map -> + 'a * 'b -> + ('c * 'd * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'cmp) imap_iter_type = + ('a, 'b, 'c, 'd) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('e * 'f, 'a * 'b, 'a, 'b) kinstr -> + ('e * 'f, 'cmp) ty option -> + ('a, 'b, 'g, 'h) kinstr -> + ('g, 'h, 'c, 'd) continuation -> + ('e, 'f) map -> + 'a * 'b -> + ('c * 'd * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f) imul_teznat_type = + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + Script.location -> + (Tez.t, 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + Tez.t -> + Script_int.n Script_int.num * 'b -> + ('e * 'f * outdated_context * local_gas_counter, error trace) result Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f) imul_nattez_type = + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + Script.location -> + (Tez.t, 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + Script_int.n Script_int.num -> + Tez.t * 'b -> + ('e * 'f * outdated_context * local_gas_counter, error trace) result Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f) ilsl_nat_type = + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + Script.location -> + (Script_int.n Script_int.num, 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + Script_int.n Script_int.num -> + Script_int.n Script_int.num * 'b -> + ('e * 'f * outdated_context * local_gas_counter, error trace) result Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f) ilsr_nat_type = + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + Script.location -> + (Script_int.n Script_int.num, 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + Script_int.n Script_int.num -> + Script_int.n Script_int.num * 'b -> + ('e * 'f * outdated_context * local_gas_counter, error trace) result Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f) ilsl_bytes_type = + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + Script.location -> + (bytes, 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + bytes -> + Script_int.n Script_int.num * 'b -> + ('e * 'f * outdated_context * local_gas_counter, error trace) result Lwt.t + +type ifailwith_type = { + ifailwith : + 'a 'ac 'b. + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + Script.location -> + ('a, 'ac) ty -> + 'a -> + ('b, error trace) result Lwt.t; +} +[@@unboxed] + +type ('a, 'b, 'c, 'd, 'e, 'f, 'g) iexec_type = + ('a, end_of_stack, 'e, 'f) cont_instrumentation -> + logger option -> + outdated_context * step_constants -> + local_gas_counter -> + ('a, 'b) stack_ty option -> + ('a, 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + 'g -> + ('g, 'a) lambda * 'b -> + ('e * 'f * outdated_context * local_gas_counter) tzresult Lwt.t + +type ('a, 'b, 'c, 'd, 'e, 'f, 'i, 'o) iview_type = + ('o, end_of_stack, 'e, 'f) cont_instrumentation -> + outdated_context * step_constants -> + local_gas_counter -> + ('i, 'o) view_signature -> + ('a, 'b) stack_ty option -> + ('o option, 'a * 'b, 'c, 'd) kinstr -> + ('c, 'd, 'e, 'f) continuation -> + 'i -> + address * ('a * 'b) -> + ('e * 'f * outdated_context * local_gas_counter) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_annot.ml b/src/proto_020_PsParisC/lib_protocol/script_ir_annot.ml new file mode 100644 index 000000000000..dcf75b0518ec --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_annot.ml @@ -0,0 +1,315 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Micheline +open Script_tc_errors + +type var_annot = Var_annot + +type type_annot = Type_annot + +type field_annot = Field_annot of Non_empty_string.t [@@ocaml.unboxed] + +let error_unexpected_annot loc annot = + let open Result_syntax in + match annot with + | [] -> return_unit + | _ :: _ -> tzfail (Unexpected_annotation loc) + +(* Check that the predicate p holds on all s.[k] for k >= i *) +let string_iter p s i = + let open Result_syntax in + let len = String.length s in + let rec aux i = + if Compare.Int.(i >= len) then return_unit + else + let* () = p s.[i] in + aux (i + 1) + in + aux i + +let is_allowed_char = function + | 'a' .. 'z' | 'A' .. 'Z' | '_' | '.' | '%' | '@' | '0' .. '9' -> true + | _ -> false + +(* Valid annotation characters as defined by the allowed_annot_char function from lib_micheline/micheline_parser *) +let check_char loc c = + let open Result_syntax in + if is_allowed_char c then return_unit else tzfail (Unexpected_annotation loc) + +(* This constant is defined in lib_micheline/micheline_parser which is not available in the environment. *) +let max_annot_length = 255 + +type annot_opt = + | Field_annot_opt of Non_empty_string.t option + | Type_annot_opt of type_annot option + | Var_annot_opt of var_annot option + +let at = Non_empty_string.of_string_exn "@" + +let parse_annot loc s = + let open Result_syntax in + (* allow empty annotations as wildcards but otherwise only accept + annotations that start with [a-zA-Z_] *) + let sub_or_wildcard wrap s = + match Non_empty_string.of_string s with + | None -> return @@ wrap None + | Some s -> ( + match (s :> string).[0] with + | 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' -> + (* check that all characters are valid*) + let* () = string_iter (check_char loc) (s :> string) 1 in + return @@ wrap (Some s) + | _ -> tzfail (Unexpected_annotation loc)) + in + let len = String.length s in + if Compare.Int.(len = 0 || len > max_annot_length) then + tzfail (Unexpected_annotation loc) + else + let rest = String.sub s 1 (len - 1) in + match s.[0] with + | ':' -> + sub_or_wildcard + (fun a -> + Type_annot_opt + (Option.map (fun (_ : Non_empty_string.t) -> Type_annot) a)) + rest + | '@' -> + sub_or_wildcard + (fun a -> + Var_annot_opt + (Option.map (fun (_ : Non_empty_string.t) -> Var_annot) a)) + rest + | '%' -> sub_or_wildcard (fun a -> Field_annot_opt a) rest + | _ -> tzfail (Unexpected_annotation loc) + +let parse_annots loc ?(allow_special_var = false) ?(allow_special_field = false) + l = + let open Result_syntax in + List.map_e + (function + | "@%" when allow_special_var -> return @@ Var_annot_opt (Some Var_annot) + | "@%%" when allow_special_var -> return @@ Var_annot_opt (Some Var_annot) + | "%@" when allow_special_field -> return @@ Field_annot_opt (Some at) + | s -> parse_annot loc s) + l + +let opt_field_of_field_opt = function + | None -> None + | Some a -> Some (Field_annot a) + +let classify_annot loc l : + (var_annot option list * type_annot option list * field_annot option list) + tzresult = + let open Result_syntax in + try + let _, rv, _, rt, _, rf = + List.fold_left + (fun (in_v, rv, in_t, rt, in_f, rf) a -> + match (a, in_v, rv, in_t, rt, in_f, rf) with + | Var_annot_opt a, true, _, _, _, _, _ + | Var_annot_opt a, false, [], _, _, _, _ -> + (true, a :: rv, false, rt, false, rf) + | Type_annot_opt a, _, _, true, _, _, _ + | Type_annot_opt a, _, _, false, [], _, _ -> + (false, rv, true, a :: rt, false, rf) + | Field_annot_opt a, _, _, _, _, true, _ + | Field_annot_opt a, _, _, _, _, false, [] -> + (false, rv, false, rt, true, opt_field_of_field_opt a :: rf) + | _ -> raise Exit) + (false, [], false, [], false, []) + l + in + return (List.rev rv, List.rev rt, List.rev rf) + with Exit -> tzfail (Ungrouped_annotations loc) + +let get_one_annot loc = + let open Result_syntax in + function + | [] -> return_none + | [a] -> return a + | _ -> tzfail (Unexpected_annotation loc) + +let get_two_annot loc = + let open Result_syntax in + function + | [] -> return (None, None) + | [a] -> return (a, None) + | [a; b] -> return (a, b) + | _ -> tzfail (Unexpected_annotation loc) + +let check_type_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc vars in + let* () = error_unexpected_annot loc fields in + let+ (_a : type_annot option) = get_one_annot loc types in + () + +let parse_field_annot : + Script.location -> string -> Non_empty_string.t option tzresult = + let open Result_syntax in + fun loc annot -> + if Compare.Int.(String.length annot <= 0) || Compare.Char.(annot.[0] <> '%') + then return_none + else + let+ annot_opt = parse_annot loc annot in + match annot_opt with Field_annot_opt annot_opt -> annot_opt | _ -> None + +let is_field_annot loc a = + let open Result_syntax in + let+ result = parse_field_annot loc a in + Option.is_some result + +let extract_field_annot : + Script.node -> (Script.node * Non_empty_string.t option) tzresult = + let open Result_syntax in + function + | Prim (loc, prim, args, annot) as expr -> + let rec extract_first acc = function + | [] -> return (expr, None) + | s :: rest -> ( + let* str_opt = parse_field_annot loc s in + match str_opt with + | None -> extract_first (s :: acc) rest + | Some _ as some_field_annot -> + let annot = List.rev_append acc rest in + return (Prim (loc, prim, args, annot), some_field_annot)) + in + extract_first [] annot + | expr -> return (expr, None) + +let has_field_annot node = + let open Result_syntax in + let+ _node, result = extract_field_annot node in + Option.is_some result + +let remove_field_annot node = + let open Result_syntax in + let+ node, _a = extract_field_annot node in + node + +let extract_entrypoint_annot node = + let open Result_syntax in + let+ node, field_annot_opt = extract_field_annot node in + ( node, + Option.bind field_annot_opt (fun field_annot -> + Entrypoint.of_annot_lax_opt field_annot) ) + +let check_var_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc types in + let* () = error_unexpected_annot loc fields in + let+ (_a : var_annot option) = get_one_annot loc vars in + () + +let check_constr_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots ~allow_special_field:true loc annot in + classify_annot loc annots + in + let* (_v : var_annot option) = get_one_annot loc vars in + let* (_t : type_annot option) = get_one_annot loc types in + let+ _f1, _f2 = get_two_annot loc fields in + () + +let check_two_var_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc types in + let* () = error_unexpected_annot loc fields in + let+ _a1, _a2 = get_two_annot loc vars in + () + +let check_destr_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc ~allow_special_var:true annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc types in + let* (_v : var_annot option) = get_one_annot loc vars in + let+ (_f : field_annot option) = get_one_annot loc fields in + () + +let check_unpair_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc ~allow_special_var:true annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc types in + let* _vcar, _vcdr = get_two_annot loc vars in + let+ _f1, _f2 = get_two_annot loc fields in + () + +let parse_entrypoint_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc types in + let* f = get_one_annot loc fields in + let+ (_v : var_annot option) = get_one_annot loc vars in + f + +let parse_entrypoint_annot_strict loc annot = + let open Result_syntax in + let* entrypoint_annot = parse_entrypoint_annot loc annot in + match entrypoint_annot with + | None -> Ok Entrypoint.default + | Some (Field_annot a) -> Entrypoint.of_annot_strict ~loc a + +let parse_entrypoint_annot_lax loc annot = + let open Result_syntax in + let* entrypoint_annot = parse_entrypoint_annot loc annot in + match entrypoint_annot with + | None -> Ok Entrypoint.default + | Some (Field_annot annot) -> Entrypoint.of_annot_lax annot + +let check_var_type_annot loc annot = + let open Result_syntax in + let* vars, types, fields = + let* annots = parse_annots loc annot in + classify_annot loc annots + in + let* () = error_unexpected_annot loc fields in + let* (_v : var_annot option) = get_one_annot loc vars in + let+ (_t : type_annot option) = get_one_annot loc types in + () diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_annot.mli b/src/proto_020_PsParisC/lib_protocol/script_ir_annot.mli new file mode 100644 index 000000000000..a91723da4458 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_annot.mli @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** @return an error {!Unexpected_annotation} in the monad the list is not empty. *) +val error_unexpected_annot : Script.location -> 'a list -> unit tzresult + +(** check_xxx_annot functions below are remains from the past (they were called + parse_xxx_annot before). + They check that annotations are well-formed and, depending on different + contexts, that only the annotations that are expected to be found are + present. + Hopefully we will relax this property soon. +*) + +(** Check a type annotation only. *) +val check_type_annot : Script.location -> string list -> unit tzresult + +(** Check a field annotation only. *) +val is_field_annot : Script.location -> string -> bool tzresult + +(** Checks whether a node has a field annotation. *) +val has_field_annot : Script.node -> bool tzresult + +(** Removes a field annotation from a node. *) +val remove_field_annot : Script.node -> Script.node tzresult + +(** Extract and remove a field annotation as an entrypoint from a node *) +val extract_entrypoint_annot : + Script.node -> (Script.node * Entrypoint.t option) tzresult + +(** Instruction annotations parsing *) + +(** Check a variable annotation. *) +val check_var_annot : Script.location -> string list -> unit tzresult + +val is_allowed_char : char -> bool + +val check_constr_annot : Script.location -> string list -> unit tzresult + +val check_two_var_annot : Script.location -> string list -> unit tzresult + +val check_destr_annot : Script.location -> string list -> unit tzresult + +val check_unpair_annot : Script.location -> string list -> unit tzresult + +(** Parses a field annotation and converts it to an entrypoint. + An error is returned if the annotation is too long or is "default". + An empty annotation is converted to "default". *) +val parse_entrypoint_annot_strict : + Script.location -> string list -> Entrypoint.t tzresult + +(** Parse a field annotation and convert it to an entrypoint. + An error is returned if the field annot is too long. + An empty annotation is converted to "default". *) +val parse_entrypoint_annot_lax : + Script.location -> string list -> Entrypoint.t tzresult + +val check_var_type_annot : Script.location -> string list -> unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_translator.ml b/src/proto_020_PsParisC/lib_protocol/script_ir_translator.ml new file mode 100644 index 000000000000..d6befe9ab5fd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_translator.ml @@ -0,0 +1,6107 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Micheline +open Script +open Script_tc_errors +open Script_ir_annot +open Script_typed_ir +open Script_ir_unparser +module Typecheck_costs = Michelson_v1_gas.Cost_of.Typechecking +module Unparse_costs = Michelson_v1_gas.Cost_of.Unparsing +module Tc_context = Script_tc_context + +type elab_conf = Script_ir_translator_config.elab_config + +type ex_stack_ty = Ex_stack_ty : ('a, 's) stack_ty -> ex_stack_ty + +(* Equality witnesses *) +type ('ta, 'tb) eq = Eq : ('same, 'same) eq + +(* + + The following type represents an instruction parameterized by its + continuation. During the elaboration of the typed term, a sequence + of instructions in Micheline is read from left to right: hence, the + elaboration needs to wait for the next instruction to be elaborated + to be able to construct the current instruction. + +*) +type ('a, 's, 'b, 'u) cinstr = { + apply : 'r 'f. ('b, 'u, 'r, 'f) kinstr -> ('a, 's, 'r, 'f) kinstr; +} +[@@ocaml.unboxed] + +(* + + While a [Script_typed_ir.descr] contains a fully defined + instruction, [descr] contains a [cinstr], that is an instruction + parameterized by the next instruction, as explained in the previous + comment. + +*) +type ('a, 's, 'b, 'u) descr = { + loc : Script.location; + bef : ('a, 's) stack_ty; + aft : ('b, 'u) stack_ty; + instr : ('a, 's, 'b, 'u) cinstr; +} + +let close_descr {loc; bef; aft; instr} = + let kinstr = instr.apply (IHalt loc) in + {kloc = loc; kbef = bef; kaft = aft; kinstr} + +let compose_descr : + type a s b u c v. + Script.location -> + (a, s, b, u) descr -> + (b, u, c, v) descr -> + (a, s, c, v) descr = + fun loc d1 d2 -> + { + loc; + bef = d1.bef; + aft = d2.aft; + instr = {apply = (fun k -> d1.instr.apply (d2.instr.apply k))}; + } + +type tc_context = Tc_context.t + +(* ---- Error helpers -------------------------------------------------------*) + +let location = function + | Prim (loc, _, _, _) + | Int (loc, _) + | String (loc, _) + | Bytes (loc, _) + | Seq (loc, _) -> + loc + +let kind_equal a b = + match (a, b) with + | Int_kind, Int_kind + | String_kind, String_kind + | Bytes_kind, Bytes_kind + | Prim_kind, Prim_kind + | Seq_kind, Seq_kind -> + true + | _ -> false + +let kind = function + | Int _ -> Int_kind + | String _ -> String_kind + | Bytes _ -> Bytes_kind + | Prim _ -> Prim_kind + | Seq _ -> Seq_kind + +let unexpected expr exp_kinds exp_ns exp_prims = + match expr with + | Int (loc, _) -> Invalid_kind (loc, Prim_kind :: exp_kinds, Int_kind) + | String (loc, _) -> Invalid_kind (loc, Prim_kind :: exp_kinds, String_kind) + | Bytes (loc, _) -> Invalid_kind (loc, Prim_kind :: exp_kinds, Bytes_kind) + | Seq (loc, _) -> Invalid_kind (loc, Prim_kind :: exp_kinds, Seq_kind) + | Prim (loc, name, _, _) -> ( + let open Michelson_v1_primitives in + match (namespace name, exp_ns) with + | Type_namespace, Type_namespace + | Instr_namespace, Instr_namespace + | Constant_namespace, Constant_namespace -> + Invalid_primitive (loc, exp_prims, name) + | ns, _ -> Invalid_namespace (loc, name, exp_ns, ns)) + +let check_kind kinds expr = + let open Result_syntax in + let kind = kind expr in + if List.exists (kind_equal kind) kinds then return_unit + else + let loc = location expr in + tzfail (Invalid_kind (loc, kinds, kind)) + +let check_comparable : + type a ac. + Script.location -> (a, ac) ty -> (ac, Dependent_bool.yes) eq tzresult = + let open Result_syntax in + fun loc ty -> + match is_comparable ty with + | Yes -> return Eq + | No -> + let t = Script_ir_unparser.serialize_ty_for_error ty in + tzfail (Comparable_type_expected (loc, t)) + +let pack_node unparsed ctxt = + let bytes = + Data_encoding.( + Binary.to_bytes_exn (tup2 (Fixed.string Plain 1) expr_encoding)) + ("\x05", unparsed) + in + (bytes, ctxt) + +let pack_comparable_data ctxt ty data = + let open Lwt_result_syntax in + let+ unparsed, ctxt = unparse_comparable_data ctxt Optimized_legacy ty data in + pack_node unparsed ctxt + +let hash_bytes ctxt bytes = + let open Result_syntax in + let+ ctxt = + Gas.consume ctxt (Michelson_v1_gas.Cost_of.Interpreter.blake2b bytes) + in + (Script_expr_hash.(hash_bytes [bytes]), ctxt) + +let hash_comparable_data ctxt ty data = + let open Lwt_result_syntax in + let* bytes, ctxt = pack_comparable_data ctxt ty data in + Lwt.return @@ hash_bytes ctxt bytes + +(* ---- Tickets ------------------------------------------------------------ *) + +(* + All comparable types are dupable, this function exists only to not forget + checking this property when adding new types. +*) +let check_dupable_comparable_ty : type a. a comparable_ty -> unit = function + | Unit_t | Never_t | Int_t | Nat_t | Signature_t | String_t | Bytes_t + | Mutez_t | Bool_t | Key_hash_t | Key_t | Timestamp_t | Chain_id_t | Address_t + | Pair_t _ | Or_t _ | Option_t _ -> + () + +let check_dupable_ty ctxt loc ty = + let open Result_syntax in + let rec aux : type a ac. location -> (a, ac) ty -> (unit, error) Gas_monad.t = + fun loc ty -> + let open Gas_monad.Syntax in + let* () = Gas_monad.consume_gas Typecheck_costs.check_dupable_cycle in + match ty with + | Unit_t -> return_unit + | Int_t -> return_unit + | Nat_t -> return_unit + | Signature_t -> return_unit + | String_t -> return_unit + | Bytes_t -> return_unit + | Mutez_t -> return_unit + | Key_hash_t -> return_unit + | Key_t -> return_unit + | Timestamp_t -> return_unit + | Address_t -> return_unit + | Bool_t -> return_unit + | Contract_t _ -> return_unit + | Operation_t -> return_unit + | Chain_id_t -> return_unit + | Never_t -> return_unit + | Bls12_381_g1_t -> return_unit + | Bls12_381_g2_t -> return_unit + | Bls12_381_fr_t -> return_unit + | Sapling_state_t _ -> return_unit + | Sapling_transaction_t _ -> return_unit + | Sapling_transaction_deprecated_t _ -> return_unit + | Chest_t -> return_unit + | Chest_key_t -> return_unit + | Ticket_t _ -> fail @@ Unexpected_ticket loc + | Pair_t (ty_a, ty_b, _, _) -> + let* () = aux loc ty_a in + aux loc ty_b + | Or_t (ty_a, ty_b, _, _) -> + let* () = aux loc ty_a in + aux loc ty_b + | Lambda_t (_, _, _) -> + (* + Lambda are dupable as long as: + - they don't contain non-dupable values, e.g. in `PUSH` + (mostly non-dupable values should probably be considered forged) + - they are not the result of a partial application on a non-dupable + value. `APPLY` rejects non-packable types (because of `PUSH`). + Hence non-dupable should imply non-packable. + *) + return_unit + | Option_t (ty, _, _) -> aux loc ty + | List_t (ty, _) -> aux loc ty + | Set_t (key_ty, _) -> + let () = check_dupable_comparable_ty key_ty in + return_unit + | Map_t (key_ty, val_ty, _) -> + let () = check_dupable_comparable_ty key_ty in + aux loc val_ty + | Big_map_t (key_ty, val_ty, _) -> + let () = check_dupable_comparable_ty key_ty in + aux loc val_ty + in + let gas = aux loc ty in + let* res, ctxt = Gas_monad.run ctxt gas in + match res with Ok () -> return ctxt | Error e -> tzfail e + +let type_metadata_eq : + type error_trace. + error_details:(_, error_trace) error_details -> + 'a ty_metadata -> + 'b ty_metadata -> + (unit, error_trace) result = + fun ~error_details {size = size_a} {size = size_b} -> + Type_size.check_eq ~error_details size_a size_b + +let default_ty_eq_error loc ty1 ty2 = + let ty1 = serialize_ty_for_error ty1 in + let ty2 = serialize_ty_for_error ty2 in + Inconsistent_types (loc, ty1, ty2) + +let memo_size_eq : + type error_trace. + error_details:(_, error_trace) error_details -> + Sapling.Memo_size.t -> + Sapling.Memo_size.t -> + (unit, error_trace) result = + fun ~error_details ms1 ms2 -> + if Sapling.Memo_size.equal ms1 ms2 then Result_syntax.return_unit + else + Error + (match error_details with + | Fast -> Inconsistent_types_fast + | Informative _ -> trace_of_error @@ Inconsistent_memo_sizes (ms1, ms2)) + +(* Check that two types are equal. + + The result is an equality witness between the types of the two inputs within + the gas monad (for gas consumption). +*) +let ty_eq : + type a ac b bc error_trace. + error_details:(Script.location, error_trace) error_details -> + (a, ac) ty -> + (b, bc) ty -> + (((a, ac) ty, (b, bc) ty) eq, error_trace) Gas_monad.t = + let open Result_syntax in + fun ~(error_details : (_, error_trace) error_details) ty1 ty2 -> + let record_trace_eval : + type a. + (Script.location -> error) -> + (a, error_trace) result -> + (a, error_trace) result = + match error_details with + | Fast -> fun _f m -> m + | Informative loc -> fun f m -> record_trace_eval (fun () -> f loc) m + in + let type_metadata_eq meta1 meta2 = + type_metadata_eq ~error_details meta1 meta2 + |> record_trace_eval (fun loc -> default_ty_eq_error loc ty1 ty2) + in + let memo_size_eq ms1 ms2 = memo_size_eq ~error_details ms1 ms2 in + let rec help : + type ta tac tb tbc. + (ta, tac) ty -> + (tb, tbc) ty -> + (((ta, tac) ty, (tb, tbc) ty) eq, error_trace) result = + fun ty1 ty2 -> + help0 ty1 ty2 + |> record_trace_eval (fun loc -> default_ty_eq_error loc ty1 ty2) + and help0 : + type ta tac tb tbc. + (ta, tac) ty -> + (tb, tbc) ty -> + (((ta, tac) ty, (tb, tbc) ty) eq, error_trace) result = + fun ty1 ty2 -> + let not_equal () = + Error + (match error_details with + | Fast -> (Inconsistent_types_fast : error_trace) + | Informative loc -> trace_of_error @@ default_ty_eq_error loc ty1 ty2) + in + match (ty1, ty2) with + | Unit_t, Unit_t -> return (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Unit_t, _ -> not_equal () + | Int_t, Int_t -> return Eq + | Int_t, _ -> not_equal () + | Nat_t, Nat_t -> return Eq + | Nat_t, _ -> not_equal () + | Key_t, Key_t -> return Eq + | Key_t, _ -> not_equal () + | Key_hash_t, Key_hash_t -> return Eq + | Key_hash_t, _ -> not_equal () + | String_t, String_t -> return Eq + | String_t, _ -> not_equal () + | Bytes_t, Bytes_t -> return Eq + | Bytes_t, _ -> not_equal () + | Signature_t, Signature_t -> return Eq + | Signature_t, _ -> not_equal () + | Mutez_t, Mutez_t -> return Eq + | Mutez_t, _ -> not_equal () + | Timestamp_t, Timestamp_t -> return Eq + | Timestamp_t, _ -> not_equal () + | Address_t, Address_t -> return Eq + | Address_t, _ -> not_equal () + | Bool_t, Bool_t -> return Eq + | Bool_t, _ -> not_equal () + | Chain_id_t, Chain_id_t -> return Eq + | Chain_id_t, _ -> not_equal () + | Never_t, Never_t -> return Eq + | Never_t, _ -> not_equal () + | Operation_t, Operation_t -> return Eq + | Operation_t, _ -> not_equal () + | Bls12_381_g1_t, Bls12_381_g1_t -> return Eq + | Bls12_381_g1_t, _ -> not_equal () + | Bls12_381_g2_t, Bls12_381_g2_t -> return Eq + | Bls12_381_g2_t, _ -> not_equal () + | Bls12_381_fr_t, Bls12_381_fr_t -> return Eq + | Bls12_381_fr_t, _ -> not_equal () + | Map_t (tal, tar, meta1), Map_t (tbl, tbr, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let* Eq = help tar tbr in + let+ Eq = help tal tbl in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Map_t _, _ -> not_equal () + | Big_map_t (tal, tar, meta1), Big_map_t (tbl, tbr, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let* Eq = help tar tbr in + let+ Eq = help tal tbl in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Big_map_t _, _ -> not_equal () + | Set_t (ea, meta1), Set_t (eb, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let+ Eq = help ea eb in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Set_t _, _ -> not_equal () + | Ticket_t (ea, meta1), Ticket_t (eb, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let+ Eq = help ea eb in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Ticket_t _, _ -> not_equal () + | Pair_t (tal, tar, meta1, cmp1), Pair_t (tbl, tbr, meta2, cmp2) -> + let* () = type_metadata_eq meta1 meta2 in + let* Eq = help tal tbl in + let+ Eq = help tar tbr in + let Eq = Dependent_bool.merge_dand cmp1 cmp2 in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Pair_t _, _ -> not_equal () + | Or_t (tal, tar, meta1, cmp1), Or_t (tbl, tbr, meta2, cmp2) -> + let* () = type_metadata_eq meta1 meta2 in + let* Eq = help tal tbl in + let+ Eq = help tar tbr in + let Eq = Dependent_bool.merge_dand cmp1 cmp2 in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Or_t _, _ -> not_equal () + | Lambda_t (tal, tar, meta1), Lambda_t (tbl, tbr, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let* Eq = help tal tbl in + let+ Eq = help tar tbr in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Lambda_t _, _ -> not_equal () + | Contract_t (tal, meta1), Contract_t (tbl, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let+ Eq = help tal tbl in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Contract_t _, _ -> not_equal () + | Option_t (tva, meta1, _), Option_t (tvb, meta2, _) -> + let* () = type_metadata_eq meta1 meta2 in + let+ Eq = help tva tvb in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | Option_t _, _ -> not_equal () + | List_t (tva, meta1), List_t (tvb, meta2) -> + let* () = type_metadata_eq meta1 meta2 in + let+ Eq = help tva tvb in + (Eq : ((ta, tac) ty, (tb, tbc) ty) eq) + | List_t _, _ -> not_equal () + | Sapling_state_t ms1, Sapling_state_t ms2 -> + let+ () = memo_size_eq ms1 ms2 in + Eq + | Sapling_state_t _, _ -> not_equal () + | Sapling_transaction_t ms1, Sapling_transaction_t ms2 -> + let+ () = memo_size_eq ms1 ms2 in + Eq + | Sapling_transaction_t _, _ -> not_equal () + | ( Sapling_transaction_deprecated_t ms1, + Sapling_transaction_deprecated_t ms2 ) -> + let+ () = memo_size_eq ms1 ms2 in + Eq + | Sapling_transaction_deprecated_t _, _ -> not_equal () + | Chest_t, Chest_t -> return Eq + | Chest_t, _ -> not_equal () + | Chest_key_t, Chest_key_t -> return Eq + | Chest_key_t, _ -> not_equal () + in + let open Gas_monad.Syntax in + let* () = Gas_monad.consume_gas (Typecheck_costs.ty_eq ty1 ty2) in + Gas_monad.of_result @@ help ty1 ty2 + +(* Same as ty_eq but for stacks. + A single error monad is used here because there is no need to + recover from stack merging errors. *) +let rec stack_eq : + type ta tb ts tu. + Script.location -> + context -> + int -> + (ta, ts) stack_ty -> + (tb, tu) stack_ty -> + (((ta, ts) stack_ty, (tb, tu) stack_ty) eq * context) tzresult = + let open Result_syntax in + fun loc ctxt lvl stack1 stack2 -> + match (stack1, stack2) with + | Bot_t, Bot_t -> return (Eq, ctxt) + | Item_t (ty1, rest1), Item_t (ty2, rest2) -> + let* eq, ctxt = + Gas_monad.run ctxt @@ ty_eq ~error_details:(Informative loc) ty1 ty2 + |> record_trace (Bad_stack_item lvl) + in + let* Eq = eq in + let+ Eq, ctxt = stack_eq loc ctxt (lvl + 1) rest1 rest2 in + ((Eq : ((ta, ts) stack_ty, (tb, tu) stack_ty) eq), ctxt) + | _, _ -> tzfail Bad_stack_length + +(* ---- Type checker results -------------------------------------------------*) + +type ('a, 's) judgement = + | Typed : ('a, 's, 'b, 'u) descr -> ('a, 's) judgement + | Failed : { + descr : 'b 'u. ('b, 'u) stack_ty -> ('a, 's, 'b, 'u) descr; + } + -> ('a, 's) judgement + +(* ---- Type checker (Untyped expressions -> Typed IR) ----------------------*) + +type ('a, 's, 'b, 'u, 'c, 'v) branch = { + branch : + 'r 'f. + ('a, 's, 'r, 'f) descr -> ('b, 'u, 'r, 'f) descr -> ('c, 'v, 'r, 'f) descr; +} +[@@unboxed] + +let merge_branches : + type a s b u c v. + context -> + Script.location -> + (a, s) judgement -> + (b, u) judgement -> + (a, s, b, u, c, v) branch -> + ((c, v) judgement * context) tzresult = + let open Result_syntax in + fun ctxt loc btr bfr {branch} -> + match (btr, bfr) with + | Typed ({aft = aftbt; _} as dbt), Typed ({aft = aftbf; _} as dbf) -> + let unmatched_branches () = + let aftbt = serialize_stack_for_error ctxt aftbt in + let aftbf = serialize_stack_for_error ctxt aftbf in + Unmatched_branches (loc, aftbt, aftbf) + in + record_trace_eval + unmatched_branches + (let+ Eq, ctxt = stack_eq loc ctxt 1 aftbt aftbf in + (Typed (branch dbt dbf), ctxt)) + | Failed {descr = descrt}, Failed {descr = descrf} -> + let descr ret = branch (descrt ret) (descrf ret) in + return (Failed {descr}, ctxt) + | Typed dbt, Failed {descr = descrf} -> + return (Typed (branch dbt (descrf dbt.aft)), ctxt) + | Failed {descr = descrt}, Typed dbf -> + return (Typed (branch (descrt dbf.aft) dbf), ctxt) + +let parse_memo_size (n : (location, _) Micheline.node) : + Sapling.Memo_size.t tzresult = + match n with + | Int (_, z) -> ( + match Sapling.Memo_size.parse_z z with + | Ok _ as ok_memo_size -> ok_memo_size + | Error msg -> + Result_syntax.tzfail + @@ Invalid_syntactic_constant (location n, strip_locations n, msg)) + | _ -> Result_syntax.tzfail @@ Invalid_kind (location n, [Int_kind], kind n) + +type ex_comparable_ty = + | Ex_comparable_ty : 'a comparable_ty -> ex_comparable_ty + +type ex_parameter_ty_and_entrypoints_node = + | Ex_parameter_ty_and_entrypoints_node : { + arg_type : ('a, _) ty; + entrypoints : 'a entrypoints_node; + } + -> ex_parameter_ty_and_entrypoints_node + +(** [parse_ty] can be used to parse regular types as well as parameter types + together with their entrypoints. + + In the first case, use [~ret:Don't_parse_entrypoints], [parse_ty] will + return an [ex_ty]. + + In the second case, use [~ret:Parse_entrypoints], [parse_ty] will return + an [ex_parameter_ty_and_entrypoints_node]. +*) +type ('ret, 'name) parse_ty_ret = + | Don't_parse_entrypoints : (ex_ty, unit) parse_ty_ret + | Parse_entrypoints + : (ex_parameter_ty_and_entrypoints_node, Entrypoint.t option) parse_ty_ret + +let rec parse_ty : + type ret name. + context -> + stack_depth:int -> + legacy:bool -> + allow_lazy_storage:bool -> + allow_operation:bool -> + allow_contract:bool -> + allow_ticket:bool -> + ret:(ret, name) parse_ty_ret -> + Script.node -> + (ret * context) tzresult = + let open Result_syntax in + fun ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret + node -> + let* ctxt = Gas.consume ctxt Typecheck_costs.parse_type_cycle in + if Compare.Int.(stack_depth > 10000) then + tzfail Typechecking_too_many_recursive_calls + else + let* node, name = + match ret with + | Don't_parse_entrypoints -> return (node, (() : name)) + | Parse_entrypoints -> extract_entrypoint_annot node + in + let return ctxt ty : ret * context = + match ret with + | Don't_parse_entrypoints -> (Ex_ty ty, ctxt) + | Parse_entrypoints -> + let at_node = + Option.map (fun name -> {name; original_type_expr = node}) name + in + ( Ex_parameter_ty_and_entrypoints_node + { + arg_type = ty; + entrypoints = {at_node; nested = Entrypoints_None}; + }, + ctxt ) + in + match node with + | Prim (loc, T_unit, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt unit_t + | Prim (loc, T_int, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt int_t + | Prim (loc, T_nat, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt nat_t + | Prim (loc, T_string, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt string_t + | Prim (loc, T_bytes, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt bytes_t + | Prim (loc, T_mutez, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt mutez_t + | Prim (loc, T_bool, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt bool_t + | Prim (loc, T_key, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt key_t + | Prim (loc, T_key_hash, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt key_hash_t + | Prim (loc, T_chest_key, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt chest_key_t + | Prim (loc, T_chest, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt chest_t + | Prim (loc, T_timestamp, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt timestamp_t + | Prim (loc, T_address, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt address_t + | Prim (loc, T_signature, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt signature_t + | Prim (loc, T_operation, [], annot) -> + if allow_operation then + let+ () = check_type_annot loc annot in + return ctxt operation_t + else tzfail (Unexpected_operation loc) + | Prim (loc, T_chain_id, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt chain_id_t + | Prim (loc, T_never, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt never_t + | Prim (loc, T_bls12_381_g1, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt bls12_381_g1_t + | Prim (loc, T_bls12_381_g2, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt bls12_381_g2_t + | Prim (loc, T_bls12_381_fr, [], annot) -> + let+ () = check_type_annot loc annot in + return ctxt bls12_381_fr_t + | Prim (loc, T_contract, [utl], annot) -> + if allow_contract then + let* () = check_type_annot loc annot in + let* Ex_ty tl, ctxt = + parse_passable_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + utl + ~ret:Don't_parse_entrypoints + in + let+ ty = contract_t loc tl in + return ctxt ty + else tzfail (Unexpected_contract loc) + | Prim (loc, T_pair, utl :: utr, annot) -> + let* () = check_type_annot loc annot in + let* utl = remove_field_annot utl in + let* Ex_ty tl, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret:Don't_parse_entrypoints + utl + in + let* utr = + match utr with + | [utr] -> remove_field_annot utr + | utr -> + (* Unfold [pair t1 ... tn] as [pair t1 (... (pair tn-1 tn))] *) + Ok (Prim (loc, T_pair, utr, [])) + in + let* Ex_ty tr, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret:Don't_parse_entrypoints + utr + in + let+ (Ty_ex_c ty) = pair_t loc tl tr in + return ctxt ty + | Prim (loc, T_or, [utl; utr], annot) -> ( + let* () = check_type_annot loc annot in + let* utl, utr = + match ret with + | Don't_parse_entrypoints -> + let* utl = remove_field_annot utl in + let+ utr = remove_field_annot utr in + (utl, utr) + | Parse_entrypoints -> Ok (utl, utr) + in + let* parsed_l, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret + utl + in + let* parsed_r, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret + utr + in + match ret with + | Don't_parse_entrypoints -> + let (Ex_ty tl) = parsed_l in + let (Ex_ty tr) = parsed_r in + let+ (Ty_ex_c ty) = or_t loc tl tr in + ((Ex_ty ty : ret), ctxt) + | Parse_entrypoints -> + let (Ex_parameter_ty_and_entrypoints_node + {arg_type = tl; entrypoints = left}) = + parsed_l + in + let (Ex_parameter_ty_and_entrypoints_node + {arg_type = tr; entrypoints = right}) = + parsed_r + in + let+ (Ty_ex_c arg_type) = or_t loc tl tr in + let entrypoints = + let at_node = + Option.map + (fun name -> {name; original_type_expr = node}) + name + in + {at_node; nested = Entrypoints_Or {left; right}} + in + ( Ex_parameter_ty_and_entrypoints_node {arg_type; entrypoints}, + ctxt )) + | Prim (loc, T_lambda, [uta; utr], annot) -> + let* () = check_type_annot loc annot in + let* Ex_ty ta, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy uta + in + let* Ex_ty tr, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy utr + in + let+ ty = lambda_t loc ta tr in + return ctxt ty + | Prim (loc, T_option, [ut], annot) -> + let* () = check_type_annot loc annot in + let* Ex_ty t, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret:Don't_parse_entrypoints + ut + in + let+ ty = option_t loc t in + return ctxt ty + | Prim (loc, T_list, [ut], annot) -> + let* () = check_type_annot loc annot in + let* Ex_ty t, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret:Don't_parse_entrypoints + ut + in + let+ ty = list_t loc t in + return ctxt ty + | Prim (loc, T_ticket, [ut], annot) -> + if allow_ticket then + let* () = check_type_annot loc annot in + let* Ex_comparable_ty t, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt ut + in + let+ ty = ticket_t loc t in + return ctxt ty + else tzfail (Unexpected_ticket loc) + | Prim (loc, T_set, [ut], annot) -> + let* () = check_type_annot loc annot in + let* Ex_comparable_ty t, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt ut + in + let+ ty = set_t loc t in + return ctxt ty + | Prim (loc, T_map, [uta; utr], annot) -> + let* () = check_type_annot loc annot in + let* Ex_comparable_ty ta, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt uta + in + let* Ex_ty tr, ctxt = + parse_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + ~ret:Don't_parse_entrypoints + utr + in + let+ ty = map_t loc ta tr in + return ctxt ty + | Prim (loc, T_sapling_transaction, [memo_size], annot) -> + let* () = check_type_annot loc annot in + let+ memo_size = parse_memo_size memo_size in + return ctxt (sapling_transaction_t ~memo_size) + | Prim (loc, T_sapling_transaction_deprecated, [memo_size], annot) -> + if legacy (* Legacy check introduced in Jakarta. *) then + let* () = check_type_annot loc annot in + let+ memo_size = parse_memo_size memo_size in + return ctxt (sapling_transaction_deprecated_t ~memo_size) + else tzfail (Deprecated_instruction T_sapling_transaction_deprecated) + (* + /!\ When adding new lazy storage kinds, be careful to use + [when allow_lazy_storage] /!\ + Lazy storage should not be packable to avoid stealing a lazy storage + from another contract with `PUSH t id` or `UNPACK`. + *) + | Prim (loc, T_big_map, args, annot) when allow_lazy_storage -> + let+ Ex_ty ty, ctxt = + parse_big_map_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + loc + args + annot + in + return ctxt ty + | Prim (loc, T_sapling_state, [memo_size], annot) when allow_lazy_storage + -> + let* () = check_type_annot loc annot in + let+ memo_size = parse_memo_size memo_size in + return ctxt (sapling_state_t ~memo_size) + | Prim (loc, (T_big_map | T_sapling_state), _, _) -> + tzfail (Unexpected_lazy_storage loc) + | Prim + ( loc, + (( T_unit | T_signature | T_int | T_nat | T_string | T_bytes + | T_mutez | T_bool | T_key | T_key_hash | T_timestamp | T_address + | T_chain_id | T_operation | T_never ) as prim), + l, + _ ) -> + tzfail (Invalid_arity (loc, prim, 0, List.length l)) + | Prim + ( loc, + ((T_set | T_list | T_option | T_contract | T_ticket) as prim), + l, + _ ) -> + tzfail (Invalid_arity (loc, prim, 1, List.length l)) + | Prim (loc, ((T_pair | T_or | T_map | T_lambda) as prim), l, _) -> + tzfail (Invalid_arity (loc, prim, 2, List.length l)) + | Prim (_, T_tx_rollup_l2_address, _, _) -> + tzfail @@ Deprecated_instruction T_tx_rollup_l2_address + | expr -> + tzfail + @@ unexpected + expr + [] + Type_namespace + [ + T_bls12_381_fr; + T_bls12_381_g1; + T_bls12_381_g2; + T_bool; + T_bytes; + T_chain_id; + T_contract; + T_int; + T_key; + T_key_hash; + T_lambda; + T_list; + T_map; + T_mutez; + T_nat; + T_never; + T_operation; + T_option; + T_or; + T_pair; + T_set; + T_signature; + T_string; + T_ticket; + T_timestamp; + T_unit; + ] + +and parse_comparable_ty : + context -> + stack_depth:int -> + Script.node -> + (ex_comparable_ty * context) tzresult = + let open Result_syntax in + fun ctxt ~stack_depth node -> + let* Ex_ty t, ctxt = + parse_ty + ~ret:Don't_parse_entrypoints + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy:false + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:false + ~allow_ticket:false + node + in + match is_comparable t with + | Yes -> return (Ex_comparable_ty t, ctxt) + | No -> + tzfail + (Comparable_type_expected + (location node, Micheline.strip_locations node)) + +and parse_passable_ty : + type ret name. + context -> + stack_depth:int -> + legacy:bool -> + ret:(ret, name) parse_ty_ret -> + Script.node -> + (ret * context) tzresult = + fun ctxt ~stack_depth ~legacy -> + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:true + ~allow_operation:false + ~allow_contract:true + ~allow_ticket:true + +and parse_any_ty : + context -> + stack_depth:int -> + legacy:bool -> + Script.node -> + (ex_ty * context) tzresult = + fun ctxt ~stack_depth ~legacy -> + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:true + ~allow_operation:true + ~allow_contract:true + ~allow_ticket:true + ~ret:Don't_parse_entrypoints + +and parse_big_map_ty ctxt ~stack_depth ~legacy big_map_loc args map_annot = + let open Result_syntax in + let* ctxt = Gas.consume ctxt Typecheck_costs.parse_type_cycle in + match args with + | [key_ty; value_ty] -> + let* () = check_type_annot big_map_loc map_annot in + let* Ex_comparable_ty key_ty, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt key_ty + in + let* Ex_ty value_ty, ctxt = + parse_big_map_value_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + value_ty + in + let+ big_map_ty = big_map_t big_map_loc key_ty value_ty in + (Ex_ty big_map_ty, ctxt) + | args -> tzfail @@ Invalid_arity (big_map_loc, T_big_map, 2, List.length args) + +and parse_big_map_value_ty ctxt ~stack_depth ~legacy value_ty = + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:false + ~allow_ticket:true + ~ret:Don't_parse_entrypoints + value_ty + +let parse_packable_ty ctxt ~stack_depth ~legacy node = + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:false + (* type contract is forbidden in UNPACK because of + https://gitlab.com/tezos/tezos/-/issues/301 *) + ~allow_ticket:false + ~ret:Don't_parse_entrypoints + node + +let parse_view_input_ty ctxt ~stack_depth ~legacy node = + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:true + ~allow_ticket:false + ~ret:Don't_parse_entrypoints + node + +let parse_view_output_ty ctxt ~stack_depth ~legacy node = + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:false + ~allow_operation:false + ~allow_contract:true + ~allow_ticket:false + ~ret:Don't_parse_entrypoints + node + +let parse_storage_ty ctxt ~stack_depth ~legacy node = + (parse_ty [@tailcall]) + ctxt + ~stack_depth + ~legacy + ~allow_lazy_storage:true + ~allow_operation:false + ~allow_contract:false + ~allow_ticket:true + ~ret:Don't_parse_entrypoints + node + +(* check_packable: determine if a `ty` is packable into Michelson *) +let check_packable ~allow_contract loc root = + let open Result_syntax in + let rec check : type t tc. (t, tc) ty -> unit tzresult = function + (* /!\ When adding new lazy storage kinds, be sure to return an error. /!\ + Lazy storage should not be packable. *) + | Big_map_t _ -> tzfail (Unexpected_lazy_storage loc) + | Sapling_state_t _ -> tzfail (Unexpected_lazy_storage loc) + | Operation_t -> tzfail (Unexpected_operation loc) + | Unit_t -> return_unit + | Int_t -> return_unit + | Nat_t -> return_unit + | Signature_t -> return_unit + | String_t -> return_unit + | Bytes_t -> return_unit + | Mutez_t -> return_unit + | Key_hash_t -> return_unit + | Key_t -> return_unit + | Timestamp_t -> return_unit + | Address_t -> return_unit + | Bool_t -> return_unit + | Chain_id_t -> return_unit + | Never_t -> return_unit + | Set_t (_, _) -> return_unit + | Ticket_t _ -> tzfail (Unexpected_ticket loc) + | Lambda_t (_, _, _) -> return_unit + | Bls12_381_g1_t -> return_unit + | Bls12_381_g2_t -> return_unit + | Bls12_381_fr_t -> return_unit + | Pair_t (l_ty, r_ty, _, _) -> + let* () = check l_ty in + check r_ty + | Or_t (l_ty, r_ty, _, _) -> + let* () = check l_ty in + check r_ty + | Option_t (v_ty, _, _) -> check v_ty + | List_t (elt_ty, _) -> check elt_ty + | Map_t (_, elt_ty, _) -> check elt_ty + | Contract_t (_, _) when allow_contract -> return_unit + | Contract_t (_, _) -> tzfail (Unexpected_contract loc) + | Sapling_transaction_t _ -> return_unit + | Sapling_transaction_deprecated_t _ -> return_unit + | Chest_key_t -> return_unit + | Chest_t -> return_unit + in + check root + +type toplevel = { + code_field : Script.node; + arg_type : Script.node; + storage_type : Script.node; + views : view_map; +} + +type ('arg, 'storage) code = + | Code : { + code : + (('arg, 'storage) pair, (operation Script_list.t, 'storage) pair) lambda; + arg_type : ('arg, _) ty; + storage_type : ('storage, _) ty; + views : view_map; + entrypoints : 'arg entrypoints; + code_size : Cache_memory_helpers.sint; + } + -> ('arg, 'storage) code + +type ex_script = Ex_script : ('a, 'c) Script_typed_ir.script -> ex_script + +type ex_code = Ex_code : ('a, 'c) code -> ex_code + +type 'storage typed_view = + | Typed_view : { + input_ty : ('input, _) ty; + output_ty : ('output, _) ty; + kinstr : ('input * 'storage, end_of_stack, 'output, end_of_stack) kinstr; + original_code_expr : Script.node; + } + -> 'storage typed_view + +type 'storage typed_view_map = (Script_string.t, 'storage typed_view) map + +type (_, _) dig_proof_argument = + | Dig_proof_argument : + ('x, 'a * 's, 'a, 's, 'b, 't, 'c, 'u) stack_prefix_preservation_witness + * ('x, _) ty + * ('c, 'u) stack_ty + -> ('b, 't) dig_proof_argument + +type (_, _, _) dug_proof_argument = + | Dug_proof_argument : + (('a, 's, 'x, 'a * 's, 'b, 't, 'c, 'u) stack_prefix_preservation_witness + * ('c, 'u) stack_ty) + -> ('b, 't, 'x) dug_proof_argument + +type (_, _) dipn_proof_argument = + | Dipn_proof_argument : + ('fa, 'fs, 'fb, 'fu, 'a, 's, 'b, 'u) stack_prefix_preservation_witness + * context + * ('fa, 'fs, 'fb, 'fu) descr + * ('b, 'u) stack_ty + -> ('a, 's) dipn_proof_argument + +type (_, _) dropn_proof_argument = + | Dropn_proof_argument : + ('fa, 'fs, 'fa, 'fs, 'a, 's, 'a, 's) stack_prefix_preservation_witness + * ('fa, 'fs) stack_ty + -> ('a, 's) dropn_proof_argument + +type (_, _, _) comb_proof_argument = + | Comb_proof_argument : + ('a, 'b, 's, 'c, 'd, 't) comb_gadt_witness * ('c, 'd * 't) stack_ty + -> ('a, 'b, 's) comb_proof_argument + +type (_, _, _) uncomb_proof_argument = + | Uncomb_proof_argument : + ('a, 'b, 's, 'c, 'd, 't) uncomb_gadt_witness * ('c, 'd * 't) stack_ty + -> ('a, 'b, 's) uncomb_proof_argument + +type 'before comb_get_proof_argument = + | Comb_get_proof_argument : + ('before, 'after) comb_get_gadt_witness * ('after, _) ty + -> 'before comb_get_proof_argument + +type ('rest, 'before) comb_set_proof_argument = + | Comb_set_proof_argument : + ('rest, 'before, 'after) comb_set_gadt_witness * ('after, _) ty + -> ('rest, 'before) comb_set_proof_argument + +type (_, _, _) dup_n_proof_argument = + | Dup_n_proof_argument : + ('a, 'b, 's, 't) dup_n_gadt_witness * ('t, _) ty + -> ('a, 'b, 's) dup_n_proof_argument + +let rec make_dug_proof_argument : + type a s x xc. + location -> + int -> + (x, xc) ty -> + (a, s) stack_ty -> + (a, s, x) dug_proof_argument option = + fun loc n x stk -> + match (n, stk) with + | 0, rest -> Some (Dug_proof_argument (KRest, Item_t (x, rest))) + | n, Item_t (v, rest) -> + make_dug_proof_argument loc (n - 1) x rest + |> Option.map @@ fun (Dug_proof_argument (n', aft')) -> + Dug_proof_argument (KPrefix (loc, v, n'), Item_t (v, aft')) + | _, _ -> None + +let rec make_comb_get_proof_argument : + type b bc. int -> (b, bc) ty -> b comb_get_proof_argument option = + fun n ty -> + match (n, ty) with + | 0, value_ty -> Some (Comb_get_proof_argument (Comb_get_zero, value_ty)) + | 1, Pair_t (hd_ty, _, _annot, _) -> + Some (Comb_get_proof_argument (Comb_get_one, hd_ty)) + | n, Pair_t (_, tl_ty, _annot, _) -> + make_comb_get_proof_argument (n - 2) tl_ty + |> Option.map + @@ fun (Comb_get_proof_argument (comb_get_left_witness, ty')) -> + Comb_get_proof_argument (Comb_get_plus_two comb_get_left_witness, ty') + | _ -> None + +let rec make_comb_set_proof_argument : + type value valuec before beforec a s. + context -> + (a, s) stack_ty -> + location -> + int -> + (value, valuec) ty -> + (before, beforec) ty -> + (value, before) comb_set_proof_argument tzresult = + let open Result_syntax in + fun ctxt stack_ty loc n value_ty ty -> + match (n, ty) with + | 0, _ -> return (Comb_set_proof_argument (Comb_set_zero, value_ty)) + | 1, Pair_t (_hd_ty, tl_ty, _, _) -> + let+ (Ty_ex_c after_ty) = pair_t loc value_ty tl_ty in + Comb_set_proof_argument (Comb_set_one, after_ty) + | n, Pair_t (hd_ty, tl_ty, _, _) -> + let* (Comb_set_proof_argument (comb_set_left_witness, tl_ty')) = + make_comb_set_proof_argument ctxt stack_ty loc (n - 2) value_ty tl_ty + in + let+ (Ty_ex_c after_ty) = pair_t loc hd_ty tl_ty' in + Comb_set_proof_argument + (Comb_set_plus_two comb_set_left_witness, after_ty) + | _ -> + let whole_stack = serialize_stack_for_error ctxt stack_ty in + tzfail (Bad_stack (loc, I_UPDATE, 2, whole_stack)) + +type 'a ex_ty_cstr = + | Ex_ty_cstr : { + ty : ('b, _) Script_typed_ir.ty; + construct : 'b -> 'a; + original_type_expr : Script.node; + } + -> 'a ex_ty_cstr + +let find_entrypoint (type full fullc error_context error_trace) + ~(error_details : (error_context, error_trace) error_details) + (full : (full, fullc) ty) (entrypoints : full entrypoints) entrypoint : + (full ex_ty_cstr, error_trace) Gas_monad.t = + let open Gas_monad.Syntax in + let rec find_entrypoint : + type t tc. + (t, tc) ty -> + t entrypoints_node -> + Entrypoint.t -> + (t ex_ty_cstr, unit) Gas_monad.t = + fun ty entrypoints entrypoint -> + let* () = Gas_monad.consume_gas Typecheck_costs.find_entrypoint_cycle in + match (ty, entrypoints) with + | _, {at_node = Some {name; original_type_expr}; _} + when Entrypoint.(name = entrypoint) -> + return (Ex_ty_cstr {ty; construct = (fun e -> e); original_type_expr}) + | Or_t (tl, tr, _, _), {nested = Entrypoints_Or {left; right}; _} -> ( + Gas_monad.bind_recover (find_entrypoint tl left entrypoint) @@ function + | Ok (Ex_ty_cstr {ty; construct; original_type_expr}) -> + return + (Ex_ty_cstr + { + ty; + construct = (fun e -> L (construct e)); + original_type_expr; + }) + | Error () -> + let+ (Ex_ty_cstr {ty; construct; original_type_expr}) = + find_entrypoint tr right entrypoint + in + Ex_ty_cstr + {ty; construct = (fun e -> R (construct e)); original_type_expr}) + | _, {nested = Entrypoints_None; _} -> Gas_monad.of_result (Error ()) + in + let {root; original_type_expr} = entrypoints in + Gas_monad.bind_recover (find_entrypoint full root entrypoint) @@ function + | Ok f_t -> return f_t + | Error () -> + if Entrypoint.is_default entrypoint then + return + (Ex_ty_cstr {ty = full; construct = (fun e -> e); original_type_expr}) + else + Gas_monad.of_result + @@ Error + (match error_details with + | Fast -> (Inconsistent_types_fast : error_trace) + | Informative _ -> trace_of_error @@ No_such_entrypoint entrypoint) + +let find_entrypoint_for_type (type full fullc exp expc error_trace) + ~error_details ~(full : (full, fullc) ty) ~(expected : (exp, expc) ty) + entrypoints entrypoint : + (Entrypoint.t * (exp, expc) ty, error_trace) Gas_monad.t = + let open Gas_monad.Syntax in + let* res = find_entrypoint ~error_details full entrypoints entrypoint in + match res with + | Ex_ty_cstr {ty; _} -> ( + match entrypoints.root.at_node with + | Some {name; original_type_expr = _} + when Entrypoint.is_root name && Entrypoint.is_default entrypoint -> + Gas_monad.bind_recover + (ty_eq ~error_details:Fast ty expected) + (function + | Ok Eq -> return (Entrypoint.default, (ty : (exp, expc) ty)) + | Error Inconsistent_types_fast -> + let+ Eq = ty_eq ~error_details full expected in + (Entrypoint.root, (full : (exp, expc) ty))) + | _ -> + let+ Eq = ty_eq ~error_details ty expected in + (entrypoint, (ty : (exp, expc) ty))) + +let well_formed_entrypoints (type full fullc) (full : (full, fullc) ty) + entrypoints = + let open Result_syntax in + let merge path (type t tc) (ty : (t, tc) ty) + (entrypoints : t entrypoints_node) reachable + ((first_unreachable, all) as acc) = + match entrypoints.at_node with + | None -> + return + ( (if reachable then acc + else + match ty with + | Or_t _ -> acc + | _ -> ( + match first_unreachable with + | None -> (Some (List.rev path), all) + | Some _ -> acc)), + reachable ) + | Some {name; original_type_expr = _} -> + if Entrypoint.Set.mem name all then tzfail (Duplicate_entrypoint name) + else return ((first_unreachable, Entrypoint.Set.add name all), true) + in + let rec check : + type t tc. + (t, tc) ty -> + t entrypoints_node -> + prim list -> + bool -> + prim list option * Entrypoint.Set.t -> + (prim list option * Entrypoint.Set.t) tzresult = + fun t entrypoints path reachable acc -> + match (t, entrypoints) with + | Or_t (tl, tr, _, _), {nested = Entrypoints_Or {left; right}; _} -> + let* acc, l_reachable = merge (D_Left :: path) tl left reachable acc in + let* acc, r_reachable = + merge (D_Right :: path) tr right reachable acc + in + let* acc = check tl left (D_Left :: path) l_reachable acc in + check tr right (D_Right :: path) r_reachable acc + | _ -> return acc + in + let init, reachable = + match entrypoints.at_node with + | None -> (Entrypoint.Set.empty, false) + | Some {name; original_type_expr = _} -> + (Entrypoint.Set.singleton name, true) + in + let* first_unreachable, all = + check full entrypoints [] reachable (None, init) + in + if not (Entrypoint.Set.mem Entrypoint.default all) then return_unit + else + match first_unreachable with + | None -> return_unit + | Some path -> tzfail (Unreachable_entrypoint path) + +type ex_parameter_ty_and_entrypoints = + | Ex_parameter_ty_and_entrypoints : { + arg_type : ('a, _) ty; + entrypoints : 'a entrypoints; + } + -> ex_parameter_ty_and_entrypoints + +let parse_parameter_ty_and_entrypoints : + context -> + stack_depth:int -> + legacy:bool -> + Script.node -> + (ex_parameter_ty_and_entrypoints * context) tzresult = + let open Result_syntax in + fun ctxt ~stack_depth ~legacy node -> + let* Ex_parameter_ty_and_entrypoints_node {arg_type; entrypoints}, ctxt = + parse_passable_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + node + ~ret:Parse_entrypoints + in + let+ () = + if legacy (* Legacy check introduced before Ithaca. *) then return_unit + else well_formed_entrypoints arg_type entrypoints + in + let entrypoints = {root = entrypoints; original_type_expr = node} in + (Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, ctxt) + +let parse_passable_ty = parse_passable_ty ~ret:Don't_parse_entrypoints + +let parse_uint ~nb_bits = + let open Result_syntax in + assert (Compare.Int.(nb_bits >= 0 && nb_bits <= 30)) ; + let max_int = (1 lsl nb_bits) - 1 in + let max_z = Z.of_int max_int in + function + | Micheline.Int (_, n) when Compare.Z.(Z.zero <= n) && Compare.Z.(n <= max_z) + -> + return (Z.to_int n) + | node -> + tzfail + @@ Invalid_syntactic_constant + ( location node, + strip_locations node, + "a positive " ^ string_of_int nb_bits + ^ "-bit integer (between 0 and " ^ string_of_int max_int ^ ")" ) + +let parse_uint10 = parse_uint ~nb_bits:10 + +let parse_uint11 = parse_uint ~nb_bits:11 + +(* The type returned by this function is used to: + - serialize and deserialize tickets when they are stored or transferred, + - type the READ_TICKET instruction. *) +let opened_ticket_type loc ty = comparable_pair_3_t loc address_t ty nat_t + +(* -- parse data of primitive types -- *) + +let parse_unit ctxt ~legacy = + let open Result_syntax in + function + | Prim (loc, D_Unit, [], annot) -> + let* () = + if legacy (* Legacy check introduced before Ithaca. *) then return_unit + else error_unexpected_annot loc annot + in + let+ ctxt = Gas.consume ctxt Typecheck_costs.unit in + ((), ctxt) + | Prim (loc, D_Unit, l, _) -> + tzfail @@ Invalid_arity (loc, D_Unit, 0, List.length l) + | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_Unit] + +let parse_bool ctxt ~legacy = + let open Result_syntax in + function + | Prim (loc, D_True, [], annot) -> + let* () = + if legacy (* Legacy check introduced before Ithaca. *) then return_unit + else error_unexpected_annot loc annot + in + let+ ctxt = Gas.consume ctxt Typecheck_costs.bool in + (true, ctxt) + | Prim (loc, D_False, [], annot) -> + let* () = + if legacy (* Legacy check introduced before Ithaca. *) then return_unit + else error_unexpected_annot loc annot + in + let+ ctxt = Gas.consume ctxt Typecheck_costs.bool in + (false, ctxt) + | Prim (loc, ((D_True | D_False) as c), l, _) -> + tzfail @@ Invalid_arity (loc, c, 0, List.length l) + | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_True; D_False] + +let parse_string ctxt : Script.node -> (Script_string.t * context) tzresult = + let open Result_syntax in + function + | String (loc, v) as expr -> + let* ctxt = Gas.consume ctxt (Typecheck_costs.check_printable v) in + record_trace + (Invalid_syntactic_constant + (loc, strip_locations expr, "a printable ascii string")) + (let+ s = Script_string.of_string v in + (s, ctxt)) + | expr -> tzfail @@ Invalid_kind (location expr, [String_kind], kind expr) + +let parse_bytes ctxt = + let open Result_syntax in + function + | Bytes (_, v) -> return (v, ctxt) + | expr -> tzfail @@ Invalid_kind (location expr, [Bytes_kind], kind expr) + +let parse_int ctxt = + let open Result_syntax in + function + | Int (_, v) -> return (Script_int.of_zint v, ctxt) + | expr -> tzfail @@ Invalid_kind (location expr, [Int_kind], kind expr) + +let parse_nat ctxt : + Script.node -> (Script_int.n Script_int.num * context) tzresult = + let open Result_syntax in + function + | Int (loc, v) as expr -> ( + let v = Script_int.of_zint v in + match Script_int.is_nat v with + | Some nat -> return (nat, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a non-negative integer")) + | expr -> tzfail @@ Invalid_kind (location expr, [Int_kind], kind expr) + +let parse_mutez ctxt : Script.node -> (Tez.t * context) tzresult = + let open Result_syntax in + function + | Int (loc, v) as expr -> ( + match + let open Option in + bind (catch (fun () -> Z.to_int64 v)) Tez.of_mutez + with + | Some tez -> Ok (tez, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid mutez amount")) + | expr -> tzfail @@ Invalid_kind (location expr, [Int_kind], kind expr) + +let parse_timestamp ctxt : + Script.node -> (Script_timestamp.t * context) tzresult = + let open Result_syntax in + function + | Int (_, v) (* As unparsed with [Optimized] or out of bounds [Readable]. *) + -> + return (Script_timestamp.of_zint v, ctxt) + | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( + let* ctxt = Gas.consume ctxt (Typecheck_costs.timestamp_readable s) in + match Script_timestamp.of_string s with + | Some v -> return (v, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid timestamp")) + | expr -> + tzfail @@ Invalid_kind (location expr, [String_kind; Int_kind], kind expr) + +let parse_key ctxt : Script.node -> (public_key * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + (* As unparsed with [Optimized]. *) + let* ctxt = Gas.consume ctxt Typecheck_costs.public_key_optimized in + match + Data_encoding.Binary.of_bytes_opt Signature.Public_key.encoding bytes + with + | Some k -> return (k, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid public key")) + | String (loc, s) as expr -> ( + (* As unparsed with [Readable]. *) + let* ctxt = Gas.consume ctxt Typecheck_costs.public_key_readable in + match Signature.Public_key.of_b58check_opt s with + | Some k -> return (k, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid public key")) + | expr -> + tzfail + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_key_hash ctxt : Script.node -> (public_key_hash * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + (* As unparsed with [Optimized]. *) + let* ctxt = Gas.consume ctxt Typecheck_costs.key_hash_optimized in + match + Data_encoding.Binary.of_bytes_opt + Signature.Public_key_hash.encoding + bytes + with + | Some k -> return (k, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid key hash")) + | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.key_hash_readable in + match Signature.Public_key_hash.of_b58check_opt s with + | Some k -> return (k, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid key hash")) + | expr -> + tzfail + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_signature ctxt : Script.node -> (signature * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr (* As unparsed with [Optimized]. *) -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.signature_optimized in + match + Data_encoding.Binary.of_bytes_opt Script_signature.encoding bytes + with + | Some k -> return (k, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid signature")) + | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.signature_readable in + match Script_signature.of_b58check_opt s with + | Some s -> return (s, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid signature")) + | expr -> + tzfail + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_chain_id ctxt : Script.node -> (Script_chain_id.t * context) tzresult + = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.chain_id_optimized in + match + Data_encoding.Binary.of_bytes_opt Script_chain_id.encoding bytes + with + | Some k -> return (k, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid chain id")) + | String (loc, s) as expr -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.chain_id_readable in + match Script_chain_id.of_b58check_opt s with + | Some s -> return (s, ctxt) + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid chain id")) + | expr -> + tzfail + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_address ctxt : Script.node -> (address * context) tzresult = + let open Result_syntax in + let destination_allowed loc {destination; entrypoint} ctxt = + match destination with + | Destination.Zk_rollup _ when not (Constants.zk_rollup_enable ctxt) -> + tzfail @@ Zk_rollup_disabled loc + | _ -> Ok ({destination; entrypoint}, ctxt) + in + function + | Bytes (loc, bytes) as expr (* As unparsed with [Optimized]. *) -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.contract_optimized in + match + Data_encoding.Binary.of_bytes_opt + Data_encoding.(tup2 Destination.encoding Entrypoint.value_encoding) + bytes + with + | Some (destination, entrypoint) -> + destination_allowed loc {destination; entrypoint} ctxt + | None -> + tzfail + @@ Invalid_syntactic_constant + (loc, strip_locations expr, "a valid address")) + | String (loc, s) (* As unparsed with [Readable]. *) -> + let* ctxt = Gas.consume ctxt Typecheck_costs.contract_readable in + let* addr, entrypoint = + match String.index_opt s '%' with + | None -> return (s, Entrypoint.default) + | Some pos -> + let len = String.length s - pos - 1 in + let name = String.sub s (pos + 1) len in + let+ entrypoint = Entrypoint.of_string_strict ~loc name in + (String.sub s 0 pos, entrypoint) + in + let* destination = Destination.of_b58check addr in + destination_allowed loc {destination; entrypoint} ctxt + | expr -> + tzfail + @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) + +let parse_never expr : (never * context) tzresult = + Result_syntax.tzfail @@ Invalid_never_expr (location expr) + +let parse_bls12_381_g1 ctxt : + Script.node -> (Script_bls.G1.t * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bs) as expr -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_g1 in + match Script_bls.G1.of_bytes_opt bs with + | Some pt -> return (pt, ctxt) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid BLS12-381 G1 element"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_bls12_381_g2 ctxt : + Script.node -> (Script_bls.G2.t * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bs) as expr -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_g2 in + match Script_bls.G2.of_bytes_opt bs with + | Some pt -> return (pt, ctxt) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid BLS12-381 G2 element"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_bls12_381_fr ctxt : + Script.node -> (Script_bls.Fr.t * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bs) as expr -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_fr in + match Script_bls.Fr.of_bytes_opt bs with + | Some pt -> return (pt, ctxt) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid BLS12-381 field element"))) + | Int (_, v) -> + let* ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_fr in + return (Script_bls.Fr.of_z v, ctxt) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_sapling_transaction ctxt ~memo_size : + Script.node -> (Sapling.transaction * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + match + Data_encoding.Binary.of_bytes_opt Sapling.transaction_encoding bytes + with + | Some transaction -> ( + match Sapling.transaction_get_memo_size transaction with + | None -> return (transaction, ctxt) + | Some transac_memo_size -> + let* () = + memo_size_eq + ~error_details:(Informative ()) + memo_size + transac_memo_size + in + return (transaction, ctxt)) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid Sapling transaction"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_sapling_transaction_deprecated ctxt ~memo_size : + Script.node -> (Sapling.Legacy.transaction * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + match + Data_encoding.Binary.of_bytes_opt + Sapling.Legacy.transaction_encoding + bytes + with + | Some transaction -> ( + match Sapling.Legacy.transaction_get_memo_size transaction with + | None -> return (transaction, ctxt) + | Some transac_memo_size -> + let* () = + memo_size_eq + ~error_details:(Informative ()) + memo_size + transac_memo_size + in + return (transaction, ctxt)) + | None -> + tzfail + (Invalid_syntactic_constant + ( loc, + strip_locations expr, + "a valid Sapling transaction (deprecated format)" ))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_chest_key ctxt : + Script.node -> (Script_timelock.chest_key * context) tzresult = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + let* ctxt = Gas.consume ctxt Typecheck_costs.chest_key in + match + Data_encoding.Binary.of_bytes_opt + Script_timelock.chest_key_encoding + bytes + with + | Some chest_key -> return (chest_key, ctxt) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid time-lock chest key"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_chest ctxt : Script.node -> (Script_timelock.chest * context) tzresult + = + let open Result_syntax in + function + | Bytes (loc, bytes) as expr -> ( + let* ctxt = + Gas.consume ctxt (Typecheck_costs.chest ~bytes:(Bytes.length bytes)) + in + match + Data_encoding.Binary.of_bytes_opt Script_timelock.chest_encoding bytes + with + | Some chest -> return (chest, ctxt) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid time-lock chest"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +(* -- parse data of complex types -- *) + +let parse_pair (type r) parse_l parse_r ctxt ~legacy + (r_comb_witness : (r, unit -> _) comb_witness) expr = + let open Lwt_result_syntax in + let parse_comb loc l rs = + let* l, ctxt = parse_l ctxt l in + let*? r = + match (rs, r_comb_witness) with + | [r], _ -> Ok r + | [], _ -> Result_syntax.tzfail @@ Invalid_arity (loc, D_Pair, 2, 1) + | _ :: _, Comb_Pair _ -> + (* Unfold [Pair x1 ... xn] as [Pair x1 (Pair x2 ... xn-1 xn))] + for type [pair ta (pair tb1 tb2)] and n >= 3 only *) + Ok (Prim (loc, D_Pair, rs, [])) + | _ -> + Result_syntax.tzfail + @@ Invalid_arity (loc, D_Pair, 2, 1 + List.length rs) + in + let+ r, ctxt = parse_r ctxt r in + ((l, r), ctxt) + in + match expr with + | Prim (loc, D_Pair, l :: rs, annot) -> + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result_syntax.return_unit + else error_unexpected_annot loc annot + in + parse_comb loc l rs + | Prim (loc, D_Pair, l, _) -> + tzfail @@ Invalid_arity (loc, D_Pair, 2, List.length l) + (* Unfold [{x1; ...; xn}] as [Pair x1 x2 ... xn-1 xn] for n >= 2 *) + | Seq (loc, l :: (_ :: _ as rs)) -> parse_comb loc l rs + | Seq (loc, l) -> tzfail @@ Invalid_seq_arity (loc, 2, List.length l) + | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_Pair] + +let parse_or parse_l parse_r ctxt ~legacy = + let open Lwt_result_syntax in + function + | Prim (loc, D_Left, [v], annot) -> + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result_syntax.return_unit + else error_unexpected_annot loc annot + in + let+ v, ctxt = parse_l ctxt v in + (L v, ctxt) + | Prim (loc, D_Left, l, _) -> + tzfail @@ Invalid_arity (loc, D_Left, 1, List.length l) + | Prim (loc, D_Right, [v], annot) -> + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result_syntax.return_unit + else error_unexpected_annot loc annot + in + let+ v, ctxt = parse_r ctxt v in + (R v, ctxt) + | Prim (loc, D_Right, l, _) -> + tzfail @@ Invalid_arity (loc, D_Right, 1, List.length l) + | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_Left; D_Right] + +let parse_option parse_v ctxt ~legacy = + let open Lwt_result_syntax in + function + | Prim (loc, D_Some, [v], annot) -> + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result_syntax.return_unit + else error_unexpected_annot loc annot + in + let+ v, ctxt = parse_v ctxt v in + (Some v, ctxt) + | Prim (loc, D_Some, l, _) -> + tzfail @@ Invalid_arity (loc, D_Some, 1, List.length l) + | Prim (loc, D_None, [], annot) -> + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result_syntax.return_unit + else error_unexpected_annot loc annot + in + return (None, ctxt) + | Prim (loc, D_None, l, _) -> + tzfail @@ Invalid_arity (loc, D_None, 0, List.length l) + | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_Some; D_None] + +let comb_witness1 : type t tc. (t, tc) ty -> (t, unit -> unit) comb_witness = + function + | Pair_t _ -> Comb_Pair Comb_Any + | _ -> Comb_Any + +let parse_view_name ctxt : Script.node -> (Script_string.t * context) tzresult = + let open Result_syntax in + function + | String (loc, v) as expr -> + (* The limitation of length of string is same as entrypoint *) + if Compare.Int.(String.length v > 31) then tzfail (View_name_too_long v) + else + let rec check_char i = + if Compare.Int.(i < 0) then return v + else if Script_ir_annot.is_allowed_char v.[i] then check_char (i - 1) + else tzfail (Bad_view_name loc) + in + let* ctxt = Gas.consume ctxt (Typecheck_costs.check_printable v) in + record_trace + (Invalid_syntactic_constant + ( loc, + strip_locations expr, + "string [a-zA-Z0-9_.%@] and the maximum string length of 31 \ + characters" )) + (let* v = check_char (String.length v - 1) in + let+ s = Script_string.of_string v in + (s, ctxt)) + | expr -> tzfail @@ Invalid_kind (location expr, [String_kind], kind expr) + +let parse_toplevel : context -> Script.expr -> (toplevel * context) tzresult = + let open Result_syntax in + fun ctxt toplevel -> + record_trace (Ill_typed_contract (toplevel, [])) + @@ + match root toplevel with + | Int (loc, _) -> tzfail (Invalid_kind (loc, [Seq_kind], Int_kind)) + | String (loc, _) -> tzfail (Invalid_kind (loc, [Seq_kind], String_kind)) + | Bytes (loc, _) -> tzfail (Invalid_kind (loc, [Seq_kind], Bytes_kind)) + | Prim (loc, _, _, _) -> tzfail (Invalid_kind (loc, [Seq_kind], Prim_kind)) + | Seq (_, fields) -> ( + let rec find_fields ctxt p s c views fields = + match fields with + | [] -> return (ctxt, (p, s, c, views)) + | Int (loc, _) :: _ -> + tzfail (Invalid_kind (loc, [Prim_kind], Int_kind)) + | String (loc, _) :: _ -> + tzfail (Invalid_kind (loc, [Prim_kind], String_kind)) + | Bytes (loc, _) :: _ -> + tzfail (Invalid_kind (loc, [Prim_kind], Bytes_kind)) + | Seq (loc, _) :: _ -> + tzfail (Invalid_kind (loc, [Prim_kind], Seq_kind)) + | Prim (loc, K_parameter, [arg], annot) :: rest -> ( + match p with + | None -> find_fields ctxt (Some (arg, loc, annot)) s c views rest + | Some _ -> tzfail (Duplicate_field (loc, K_parameter))) + | Prim (loc, K_storage, [arg], annot) :: rest -> ( + match s with + | None -> find_fields ctxt p (Some (arg, loc, annot)) c views rest + | Some _ -> tzfail (Duplicate_field (loc, K_storage))) + | Prim (loc, K_code, [arg], annot) :: rest -> ( + match c with + | None -> find_fields ctxt p s (Some (arg, loc, annot)) views rest + | Some _ -> tzfail (Duplicate_field (loc, K_code))) + | Prim (loc, ((K_parameter | K_storage | K_code) as name), args, _) + :: _ -> + tzfail (Invalid_arity (loc, name, 1, List.length args)) + | Prim (loc, K_view, [name; input_ty; output_ty; view_code], _) + :: rest -> + let* str, ctxt = parse_view_name ctxt name in + let* ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.view_update str views) + in + if Script_map.mem str views then tzfail (Duplicated_view_name loc) + else + let views' = + Script_map.update + str + (Some {input_ty; output_ty; view_code}) + views + in + find_fields ctxt p s c views' rest + | Prim (loc, K_view, args, _) :: _ -> + tzfail (Invalid_arity (loc, K_view, 4, List.length args)) + | Prim (loc, name, _, _) :: _ -> + let allowed = [K_parameter; K_storage; K_code; K_view] in + tzfail (Invalid_primitive (loc, allowed, name)) + in + let* ctxt, toplevel = + find_fields ctxt None None None (Script_map.empty string_t) fields + in + match toplevel with + | None, _, _, _ -> tzfail (Missing_field K_parameter) + | Some _, None, _, _ -> tzfail (Missing_field K_storage) + | Some _, Some _, None, _ -> tzfail (Missing_field K_code) + | ( Some (p, ploc, pannot), + Some (s, sloc, sannot), + Some (c, cloc, cannot), + views ) -> + let* () = Script_ir_annot.error_unexpected_annot ploc pannot in + let* () = Script_ir_annot.error_unexpected_annot cloc cannot in + let+ () = Script_ir_annot.error_unexpected_annot sloc sannot in + ({code_field = c; arg_type = p; views; storage_type = s}, ctxt)) + +(* Normalize lambdas during parsing *) + +let normalized_lam ~unparse_code_rec ~stack_depth ctxt kdescr code_field = + let open Lwt_result_syntax in + let+ code_field, ctxt = + unparse_code_rec ctxt ~stack_depth:(stack_depth + 1) Optimized code_field + in + (Lam (kdescr, code_field), ctxt) + +let normalized_lam_rec ~unparse_code_rec ~stack_depth ctxt kdescr code_field = + let open Lwt_result_syntax in + let+ code_field, ctxt = + unparse_code_rec ctxt ~stack_depth:(stack_depth + 1) Optimized code_field + in + (LamRec (kdescr, code_field), ctxt) + +(* -- parse data of any type -- *) + +(* + Some values, such as operations, tickets, or big map ids, are used only + internally and are not allowed to be forged by users. + In [parse_data], both [allow_forged_tickets] and [allow_forged_lazy_storage_id] should be [false] for: + - PUSH + - UNPACK + - storage on origination + And [true] for: + - internal calls parameters + - storage after origination. + For + - user-provided script parameters + [allow_forged_lazy_storage_id] should be [false] but [allow_forged_tickets] should be [true] as users are allowed to transfer tickets. Checking ticket ownership is handled by the ticket table. + *) + +let rec parse_data : + type a ac. + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + stack_depth:int -> + context -> + allow_forged_tickets:bool -> + allow_forged_lazy_storage_id:bool -> + (a, ac) ty -> + Script.node -> + (a * context) tzresult Lwt.t = + fun ~unparse_code_rec + ~elab_conf + ~stack_depth + ctxt + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + ty + script_data -> + let open Lwt_result_syntax in + let*? ctxt = Gas.consume ctxt Typecheck_costs.parse_data_cycle in + let non_terminal_recursion ctxt ty script_data = + if Compare.Int.(stack_depth > 10_000) then + tzfail Typechecking_too_many_recursive_calls + else + parse_data + ~unparse_code_rec + ~elab_conf + ~stack_depth:(stack_depth + 1) + ctxt + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + ty + script_data + in + let parse_data_error () = + let ty = serialize_ty_for_error ty in + Invalid_constant (location script_data, strip_locations script_data, ty) + in + let fail_parse_data () = tzfail (parse_data_error ()) in + let traced_no_lwt body = record_trace_eval parse_data_error body in + let traced body = trace_eval parse_data_error body in + let traced_fail err = + Lwt.return @@ traced_no_lwt (Result_syntax.tzfail err) + in + let parse_items ctxt expr key_type value_type items item_wrapper = + let+ _, items, ctxt = + List.fold_left_es + (fun (last_value, map, ctxt) item -> + match item with + | Prim (loc, D_Elt, [k; v], annot) -> + let*? () = + if elab_conf.legacy (* Legacy check introduced before Ithaca. *) + then Result_syntax.return_unit + else error_unexpected_annot loc annot + in + let* k, ctxt = non_terminal_recursion ctxt key_type k in + let* v, ctxt = non_terminal_recursion ctxt value_type v in + let*? ctxt = + let open Result_syntax in + match last_value with + | Some value -> + let* ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.compare + key_type + value + k) + in + let c = + Script_comparable.compare_comparable key_type value k + in + if Compare.Int.(0 <= c) then + if Compare.Int.(0 = c) then + tzfail (Duplicate_map_keys (loc, strip_locations expr)) + else + tzfail (Unordered_map_keys (loc, strip_locations expr)) + else return ctxt + | None -> return ctxt + in + let*? ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.map_update k map) + in + return + (Some k, Script_map.update k (Some (item_wrapper v)) map, ctxt) + | Prim (loc, D_Elt, l, _) -> + tzfail @@ Invalid_arity (loc, D_Elt, 2, List.length l) + | Prim (loc, name, _, _) -> + tzfail @@ Invalid_primitive (loc, [D_Elt], name) + | Int _ | String _ | Bytes _ | Seq _ -> fail_parse_data ()) + (None, Script_map.empty key_type, ctxt) + items + |> traced + in + (items, ctxt) + in + let parse_big_map_items (type t) ctxt expr (key_type : t comparable_ty) + value_type items item_wrapper = + let+ _, map, ctxt = + List.fold_left_es + (fun (last_key, {map; size}, ctxt) item -> + match item with + | Prim (loc, D_Elt, [k; v], annot) -> + let*? () = + if elab_conf.legacy (* Legacy check introduced before Ithaca. *) + then Result_syntax.return_unit + else error_unexpected_annot loc annot + in + let* k, ctxt = non_terminal_recursion ctxt key_type k in + let* key_hash, ctxt = hash_comparable_data ctxt key_type k in + let* v, ctxt = non_terminal_recursion ctxt value_type v in + let*? ctxt = + let open Result_syntax in + match last_key with + | Some last_key -> + let* ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.compare + key_type + last_key + k) + in + let c = + Script_comparable.compare_comparable key_type last_key k + in + if Compare.Int.(0 <= c) then + if Compare.Int.(0 = c) then + tzfail (Duplicate_map_keys (loc, strip_locations expr)) + else + tzfail (Unordered_map_keys (loc, strip_locations expr)) + else return ctxt + | None -> return ctxt + in + let*? ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.big_map_update + {map; size}) + in + if Big_map_overlay.mem key_hash map then + tzfail (Duplicate_map_keys (loc, strip_locations expr)) + else + return + ( Some k, + { + map = Big_map_overlay.add key_hash (k, item_wrapper v) map; + size = size + 1; + }, + ctxt ) + | Prim (loc, D_Elt, l, _) -> + tzfail @@ Invalid_arity (loc, D_Elt, 2, List.length l) + | Prim (loc, name, _, _) -> + tzfail @@ Invalid_primitive (loc, [D_Elt], name) + | Int _ | String _ | Bytes _ | Seq _ -> fail_parse_data ()) + (None, {map = Big_map_overlay.empty; size = 0}, ctxt) + items + |> traced + in + (map, ctxt) + in + let legacy = elab_conf.legacy in + match (ty, script_data) with + | Unit_t, expr -> + Lwt.return @@ traced_no_lwt + @@ (parse_unit ctxt ~legacy expr : (a * context) tzresult) + | Bool_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_bool ctxt ~legacy expr + | String_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_string ctxt expr + | Bytes_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_bytes ctxt expr + | Int_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_int ctxt expr + | Nat_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_nat ctxt expr + | Mutez_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_mutez ctxt expr + | Timestamp_t, expr -> + Lwt.return @@ traced_no_lwt @@ parse_timestamp ctxt expr + | Key_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_key ctxt expr + | Key_hash_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_key_hash ctxt expr + | Signature_t, expr -> + Lwt.return @@ traced_no_lwt @@ parse_signature ctxt expr + | Operation_t, _ -> + (* operations cannot appear in parameters or storage, + the protocol should never parse the bytes of an operation *) + assert false + | Chain_id_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_chain_id ctxt expr + | Address_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_address ctxt expr + | Contract_t (arg_ty, _), expr -> + traced + (let*? address, ctxt = parse_address ctxt expr in + let loc = location expr in + let+ ctxt, typed_contract = + parse_contract_data + ~stack_depth:(stack_depth + 1) + ctxt + loc + arg_ty + address.destination + ~entrypoint:address.entrypoint + in + (typed_contract, ctxt)) + (* Pairs *) + | Pair_t (tl, tr, _, _), expr -> + let r_witness = comb_witness1 tr in + let parse_l ctxt v = non_terminal_recursion ctxt tl v in + let parse_r ctxt v = non_terminal_recursion ctxt tr v in + traced @@ parse_pair parse_l parse_r ctxt ~legacy r_witness expr + (* Ors *) + | Or_t (tl, tr, _, _), expr -> + let parse_l ctxt v = non_terminal_recursion ctxt tl v in + let parse_r ctxt v = non_terminal_recursion ctxt tr v in + traced @@ parse_or parse_l parse_r ctxt ~legacy expr + (* Lambdas *) + | Lambda_t (ta, tr, _ty_name), (Seq (_loc, _) as script_instr) -> + let* kdescr, ctxt = + traced + @@ parse_kdescr + ~unparse_code_rec + Tc_context.data + ~elab_conf + ~stack_depth:(stack_depth + 1) + ctxt + ta + tr + script_instr + in + (normalized_lam [@ocaml.tailcall]) + ~unparse_code_rec + ctxt + ~stack_depth + kdescr + script_instr + | ( Lambda_t (ta, tr, _ty_name), + Prim (loc, D_Lambda_rec, [(Seq (_loc, _) as script_instr)], []) ) -> + traced + @@ let*? lambda_rec_ty = lambda_t loc ta tr in + parse_lam_rec + ~unparse_code_rec + Tc_context.(add_lambda data) + ~elab_conf + ~stack_depth:(stack_depth + 1) + ctxt + ta + tr + lambda_rec_ty + script_instr + | Lambda_t _, expr -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + (* Options *) + | Option_t (t, _, _), expr -> + let parse_v ctxt v = non_terminal_recursion ctxt t v in + traced @@ parse_option parse_v ctxt ~legacy expr + (* Lists *) + | List_t (t, _ty_name), Seq (_loc, items) -> + traced + @@ List.fold_left_es + (fun (rest, ctxt) v -> + let+ v, ctxt = non_terminal_recursion ctxt t v in + (Script_list.cons v rest, ctxt)) + (Script_list.empty, ctxt) + (List.rev items) + | List_t _, expr -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + (* Tickets *) + | Ticket_t (t, _ty_name), expr -> + (* This local function handles the case of parsing the `Ticket` data constructor. *) + let parse_ticket loc ticketer contents_type contents amount = + (* Ensure that the content type provided in the ticket constructor + matches the ticket type expected by the entrypoint. *) + let*? Ex_ty expected, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy contents_type + in + let*? eq, ctxt = + Gas_monad.run ctxt + @@ + let error_details = Informative loc in + ty_eq ~error_details t expected + in + let*? Eq = eq in + let* {destination; entrypoint = _}, ctxt = + non_terminal_recursion ctxt address_t ticketer + in + let* contents, ctxt = non_terminal_recursion ctxt t contents in + let+ amount, ctxt = non_terminal_recursion ctxt nat_t amount in + ((destination, contents, amount), ctxt) + in + if allow_forged_tickets then + let* (destination, contents, amount), ctxt = + match expr with + | Prim + ( loc, + D_Ticket, + [ticketer; contents_type; contents; amount], + _annot ) -> + parse_ticket loc ticketer contents_type contents amount + | Prim (_, D_Pair, _, _) -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6833 + + In the future, this [D_Pair] constructor must + be allowed only when the legacy flag is set to true. *) + let*? ty = opened_ticket_type (location expr) t in + let+ ({destination; entrypoint = _}, (contents, amount)), ctxt = + non_terminal_recursion ctxt ty expr + in + ((destination, contents, amount), ctxt) + | _ -> + tzfail @@ unexpected expr [] Constant_namespace [D_Ticket; D_Pair] + in + match Ticket_amount.of_n amount with + | Some amount -> ( + match destination with + | Contract ticketer -> return ({ticketer; contents; amount}, ctxt) + | Sc_rollup _ | Zk_rollup _ -> + tzfail (Unexpected_ticket_owner destination)) + | None -> traced_fail Forbidden_zero_ticket_quantity + else traced_fail (Unexpected_forged_value (location expr)) + (* Sets *) + | Set_t (t, _ty_name), (Seq (loc, vs) as expr) -> + let+ _, set, ctxt = + traced + @@ List.fold_left_es + (fun (last_value, set, ctxt) v -> + let* v, ctxt = non_terminal_recursion ctxt t v in + let*? ctxt = + let open Result_syntax in + match last_value with + | Some value -> + let* ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.compare + t + value + v) + in + let c = Script_comparable.compare_comparable t value v in + if Compare.Int.(0 <= c) then + if Compare.Int.(0 = c) then + tzfail + (Duplicate_set_values (loc, strip_locations expr)) + else + tzfail + (Unordered_set_values (loc, strip_locations expr)) + else return ctxt + | None -> return ctxt + in + let*? ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.set_update v set) + in + return (Some v, Script_set.update v true set, ctxt)) + (None, Script_set.empty t, ctxt) + vs + in + (set, ctxt) + | Set_t _, expr -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + (* Maps *) + | Map_t (tk, tv, _ty_name), (Seq (_, vs) as expr) -> + parse_items ctxt expr tk tv vs (fun x -> x) + | Map_t _, expr -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + | Big_map_t (tk, tv, _ty_name), expr -> + let* id_opt, diff, ctxt = + match expr with + | Int (loc, id) -> + return + (Some (id, loc), {map = Big_map_overlay.empty; size = 0}, ctxt) + | Seq (_, vs) -> + let+ diff, ctxt = + parse_big_map_items ctxt expr tk tv vs (fun x -> Some x) + in + (None, diff, ctxt) + | Prim (loc, D_Pair, [Int (loc_id, id); Seq (_, vs)], annot) -> + let*? () = error_unexpected_annot loc annot in + let*? tv_opt = option_t loc tv in + let+ diff, ctxt = + parse_big_map_items ctxt expr tk tv_opt vs (fun x -> x) + in + (Some (id, loc_id), diff, ctxt) + | Prim (_, D_Pair, [Int _; expr], _) -> + traced_fail (Invalid_kind (location expr, [Seq_kind], kind expr)) + | Prim (_, D_Pair, [expr; _], _) -> + traced_fail (Invalid_kind (location expr, [Int_kind], kind expr)) + | Prim (loc, D_Pair, l, _) -> + traced_fail @@ Invalid_arity (loc, D_Pair, 2, List.length l) + | _ -> + traced_fail + (unexpected expr [Seq_kind; Int_kind] Constant_namespace [D_Pair]) + in + let+ id, ctxt = + match id_opt with + | None -> return (None, ctxt) + | Some (id, loc) -> + if allow_forged_lazy_storage_id then + let id = Big_map.Id.parse_z id in + let* ctxt, tys_opt = Big_map.exists ctxt id in + match tys_opt with + | None -> traced_fail (Invalid_big_map (loc, id)) + | Some (btk, btv) -> + let*? Ex_comparable_ty btk, ctxt = + parse_comparable_ty + ~stack_depth:(stack_depth + 1) + ctxt + (Micheline.root btk) + in + let*? Ex_ty btv, ctxt = + parse_big_map_value_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + (Micheline.root btv) + in + let*? eq, ctxt = + Gas_monad.run ctxt + @@ + let open Gas_monad.Syntax in + let error_details = Informative loc in + let* Eq = ty_eq ~error_details tk btk in + ty_eq ~error_details tv btv + in + let*? Eq = eq in + return (Some id, ctxt) + else traced_fail (Unexpected_forged_value loc) + in + (Big_map {id; diff; key_type = tk; value_type = tv}, ctxt) + | Never_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_never expr + (* Bls12_381 types *) + | Bls12_381_g1_t, expr -> + Lwt.return @@ traced_no_lwt @@ parse_bls12_381_g1 ctxt expr + | Bls12_381_g2_t, expr -> + Lwt.return @@ traced_no_lwt @@ parse_bls12_381_g2 ctxt expr + | Bls12_381_fr_t, expr -> + Lwt.return @@ traced_no_lwt @@ parse_bls12_381_fr ctxt expr + (* + /!\ When adding new lazy storage kinds, you may want to guard the parsing + of identifiers with [allow_forged_lazy_storage_id]. + *) + (* Sapling *) + | Sapling_transaction_t memo_size, expr -> + Lwt.return @@ traced_no_lwt + @@ parse_sapling_transaction ctxt ~memo_size expr + | Sapling_transaction_deprecated_t memo_size, expr -> + Lwt.return @@ traced_no_lwt + @@ parse_sapling_transaction_deprecated ctxt ~memo_size expr + | Sapling_state_t memo_size, Int (loc, id) -> + if allow_forged_lazy_storage_id then + let id = Sapling.Id.parse_z id in + let* state, ctxt = Sapling.state_from_id ctxt id in + let*? () = + traced_no_lwt + @@ memo_size_eq + ~error_details:(Informative ()) + memo_size + state.Sapling.memo_size + in + return (state, ctxt) + else traced_fail (Unexpected_forged_value loc) + | Sapling_state_t memo_size, Seq (_, []) -> + return (Sapling.empty_state ~memo_size (), ctxt) + | Sapling_state_t _, expr -> + (* Do not allow to input diffs as they are untrusted and may not be the + result of a verify_update. *) + traced_fail + (Invalid_kind (location expr, [Int_kind; Seq_kind], kind expr)) + (* Time lock*) + | Chest_key_t, expr -> + Lwt.return @@ traced_no_lwt @@ parse_chest_key ctxt expr + | Chest_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_chest ctxt expr + +and parse_view : + type storage storagec. + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + context -> + (storage, storagec) ty -> + view -> + (storage typed_view * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec + ~elab_conf + ctxt + storage_type + {input_ty; output_ty; view_code} -> + let legacy = elab_conf.legacy in + let input_ty_loc = location input_ty in + let*? Ex_ty input_ty, ctxt = + record_trace_eval + (fun () -> + Ill_formed_type + (Some "arg of view", strip_locations input_ty, input_ty_loc)) + (parse_view_input_ty ctxt ~stack_depth:0 ~legacy input_ty) + in + let output_ty_loc = location output_ty in + let*? Ex_ty output_ty, ctxt = + record_trace_eval + (fun () -> + Ill_formed_type + (Some "return of view", strip_locations output_ty, output_ty_loc)) + (parse_view_output_ty ctxt ~stack_depth:0 ~legacy output_ty) + in + let*? (Ty_ex_c pair_ty) = pair_t input_ty_loc input_ty storage_type in + let* judgement, ctxt = + parse_instr + ~unparse_code_rec + ~elab_conf + ~stack_depth:0 + Tc_context.view + ctxt + view_code + (Item_t (pair_ty, Bot_t)) + in + Lwt.return + @@ + match judgement with + | Failed {descr} -> + let {kinstr; _} = close_descr (descr (Item_t (output_ty, Bot_t))) in + Ok + ( Typed_view + {input_ty; output_ty; kinstr; original_code_expr = view_code}, + ctxt ) + | Typed ({loc; aft; _} as descr) -> ( + let ill_type_view stack_ty loc = + let actual = serialize_stack_for_error ctxt stack_ty in + let expected_stack = Item_t (output_ty, Bot_t) in + let expected = serialize_stack_for_error ctxt expected_stack in + Ill_typed_view {loc; actual; expected} + in + let open Result_syntax in + match aft with + | Item_t (ty, Bot_t) -> + let error_details = Informative loc in + let* eq, ctxt = + Gas_monad.run ctxt + @@ Gas_monad.record_trace_eval ~error_details (fun loc -> + ill_type_view aft loc) + @@ ty_eq ~error_details ty output_ty + in + let* Eq = eq in + let {kinstr; _} = close_descr descr in + Ok + ( Typed_view + {input_ty; output_ty; kinstr; original_code_expr = view_code}, + ctxt ) + | _ -> tzfail (ill_type_view aft loc)) + +and parse_views : + type storage storagec. + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + context -> + (storage, storagec) ty -> + view_map -> + (storage typed_view_map * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec ~elab_conf ctxt storage_type views -> + let aux ctxt name cur_view = + let*? ctxt = + Gas.consume + ctxt + (Michelson_v1_gas.Cost_of.Interpreter.view_update name views) + in + parse_view ~unparse_code_rec ~elab_conf ctxt storage_type cur_view + in + Script_map.map_es_in_context aux ctxt views + +and parse_kdescr : + type arg argc ret retc. + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + stack_depth:int -> + tc_context -> + context -> + (arg, argc) ty -> + (ret, retc) ty -> + Script.node -> + ((arg, end_of_stack, ret, end_of_stack) kdescr * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec + ~elab_conf + ~stack_depth + tc_context + ctxt + arg + ret + script_instr -> + let* result = + parse_instr + ~unparse_code_rec + ~elab_conf + tc_context + ctxt + ~stack_depth:(stack_depth + 1) + script_instr + (Item_t (arg, Bot_t)) + in + match result with + | Typed ({loc; aft = Item_t (ty, Bot_t) as stack_ty; _} as descr), ctxt -> + let error_details = Informative loc in + let*? eq, ctxt = + Gas_monad.run ctxt + @@ Gas_monad.record_trace_eval ~error_details (fun loc -> + let ret = serialize_ty_for_error ret in + let stack_ty = serialize_stack_for_error ctxt stack_ty in + Bad_return (loc, stack_ty, ret)) + @@ ty_eq ~error_details ty ret + in + let*? Eq = eq in + return + ( (close_descr descr : (arg, end_of_stack, ret, end_of_stack) kdescr), + ctxt ) + | Typed {loc; aft = stack_ty; _}, ctxt -> + let ret = serialize_ty_for_error ret in + let stack_ty = serialize_stack_for_error ctxt stack_ty in + tzfail @@ Bad_return (loc, stack_ty, ret) + | Failed {descr}, ctxt -> + return + ( (close_descr (descr (Item_t (ret, Bot_t))) + : (arg, end_of_stack, ret, end_of_stack) kdescr), + ctxt ) + +and parse_lam_rec : + type arg argc ret retc. + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + stack_depth:int -> + tc_context -> + context -> + (arg, argc) ty -> + (ret, retc) ty -> + ((arg, ret) lambda, _) ty -> + Script.node -> + ((arg, ret) lambda * context) tzresult Lwt.t = + fun ~unparse_code_rec + ~elab_conf + ~stack_depth + tc_context + ctxt + arg + ret + lambda_rec_ty + script_instr -> + let open Lwt_result_syntax in + let* result = + parse_instr + ~unparse_code_rec + ~elab_conf + tc_context + ctxt + ~stack_depth:(stack_depth + 1) + script_instr + (Item_t (arg, Item_t (lambda_rec_ty, Bot_t))) + in + match result with + | Typed ({loc; aft = Item_t (ty, Bot_t) as stack_ty; _} as descr), ctxt -> + let*? closed_descr, ctxt = + let open Result_syntax in + let error_details = Informative loc in + let* eq, ctxt = + Gas_monad.run ctxt + @@ Gas_monad.record_trace_eval ~error_details (fun loc -> + let ret = serialize_ty_for_error ret in + let stack_ty = serialize_stack_for_error ctxt stack_ty in + Bad_return (loc, stack_ty, ret)) + @@ ty_eq ~error_details ty ret + in + let* Eq = eq in + Ok + ( (close_descr descr + : ( arg, + (arg, ret) lambda * end_of_stack, + ret, + end_of_stack ) + kdescr), + ctxt ) + in + (normalized_lam_rec [@ocaml.tailcall]) + ~unparse_code_rec + ~stack_depth + ctxt + closed_descr + script_instr + | Typed {loc; aft = stack_ty; _}, ctxt -> + let ret = serialize_ty_for_error ret in + let stack_ty = serialize_stack_for_error ctxt stack_ty in + tzfail @@ Bad_return (loc, stack_ty, ret) + | Failed {descr}, ctxt -> + (normalized_lam_rec [@ocaml.tailcall]) + ~unparse_code_rec + ~stack_depth + ctxt + (close_descr (descr (Item_t (ret, Bot_t)))) + script_instr + +and parse_instr : + type a s. + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + stack_depth:int -> + tc_context -> + context -> + Script.node -> + (a, s) stack_ty -> + ((a, s) judgement * context) tzresult Lwt.t = + fun ~unparse_code_rec + ~elab_conf + ~stack_depth + tc_context + ctxt + script_instr + stack_ty -> + let open Lwt_result_syntax in + let for_logging_only x = + if elab_conf.keep_extra_types_for_interpreter_logging then Some x else None + in + let check_item_ty (type a ac b bc) ctxt (exp : (a, ac) ty) (got : (b, bc) ty) + loc name n m : ((a, b) eq * context) tzresult = + let open Result_syntax in + record_trace_eval (fun () -> + let stack_ty = serialize_stack_for_error ctxt stack_ty in + Bad_stack (loc, name, m, stack_ty)) + @@ record_trace + (Bad_stack_item n) + (let* eq, ctxt = + Gas_monad.run ctxt @@ ty_eq ~error_details:(Informative loc) exp got + in + let* Eq = eq in + Ok ((Eq : (a, b) eq), ctxt)) + in + let log_stack loc stack_ty aft = + match (elab_conf.type_logger, script_instr) with + | None, _ | Some _, (Int _ | String _ | Bytes _) -> () + | Some log, (Prim _ | Seq _) -> + (* Unparsing for logging is not carbonated as this + is used only by the client and not the protocol *) + let stack_ty_before = unparse_stack_uncarbonated stack_ty in + let stack_ty_after = unparse_stack_uncarbonated aft in + log loc ~stack_ty_before ~stack_ty_after + in + let typed_no_lwt ctxt loc instr aft = + log_stack loc stack_ty aft ; + let j = Typed {loc; instr; bef = stack_ty; aft} in + Ok (j, ctxt) + in + let typed ctxt loc instr aft = + Lwt.return @@ typed_no_lwt ctxt loc instr aft + in + let*? ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + let non_terminal_recursion tc_context ctxt script_instr stack_ty = + if Compare.Int.(stack_depth > 10000) then + tzfail Typechecking_too_many_recursive_calls + else + parse_instr + ~unparse_code_rec + ~elab_conf + tc_context + ctxt + ~stack_depth:(stack_depth + 1) + script_instr + stack_ty + in + let bad_stack_error ctxt loc prim relevant_stack_portion = + let whole_stack = serialize_stack_for_error ctxt stack_ty in + Result_syntax.tzfail + (Bad_stack (loc, prim, relevant_stack_portion, whole_stack)) + in + let legacy = elab_conf.legacy in + match (script_instr, stack_ty) with + (* stack ops *) + | Prim (loc, I_DROP, [], annot), Item_t (_, rest) -> + (let*? () = error_unexpected_annot loc annot in + typed ctxt loc {apply = (fun k -> IDrop (loc, k))} rest + : ((a, s) judgement * context) tzresult Lwt.t) + | Prim (loc, I_DROP, [n], result_annot), whole_stack -> + let*? whole_n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument whole_n) in + let rec make_proof_argument : + type a s. + int -> (a, s) stack_ty -> (a, s) dropn_proof_argument tzresult = + let open Result_syntax in + fun n stk -> + match (Compare.Int.(n = 0), stk) with + | true, rest -> return (Dropn_proof_argument (KRest, rest)) + | false, Item_t (a, rest) -> + let+ (Dropn_proof_argument (n', stack_after_drops)) = + make_proof_argument (n - 1) rest + in + Dropn_proof_argument (KPrefix (loc, a, n'), stack_after_drops) + | _, _ -> + let whole_stack = serialize_stack_for_error ctxt whole_stack in + tzfail (Bad_stack (loc, I_DROP, whole_n, whole_stack)) + in + let*? () = error_unexpected_annot loc result_annot in + let*? (Dropn_proof_argument (n', stack_after_drops)) = + make_proof_argument whole_n whole_stack + in + let kdropn k = IDropn (loc, whole_n, n', k) in + typed ctxt loc {apply = kdropn} stack_after_drops + | Prim (loc, I_DROP, (_ :: _ :: _ as l), _), _ -> + (* Technically, the arities 0 and 1 are allowed but the error only mentions 1. + However, DROP is equivalent to DROP 1 so hinting at an arity of 1 makes sense. *) + tzfail (Invalid_arity (loc, I_DROP, 1, List.length l)) + | Prim (loc, I_DUP, [], annot), (Item_t (v, _) as stack) -> + let*? () = check_var_annot loc annot in + let*? ctxt = + record_trace_eval + (fun () -> + let t = serialize_ty_for_error v in + Non_dupable_type (loc, t)) + (check_dupable_ty ctxt loc v) + in + let dup = {apply = (fun k -> IDup (loc, k))} in + typed ctxt loc dup (Item_t (v, stack)) + | Prim (loc, I_DUP, [n], v_annot), (Item_t _ as stack_ty) -> + let*? () = check_var_annot loc v_annot in + let rec make_proof_argument : + type a b s. + int -> (a, b * s) stack_ty -> (a, b, s) dup_n_proof_argument tzresult + = + let open Result_syntax in + fun n (stack_ty : (a, b * s) stack_ty) -> + match (n, stack_ty) with + | 1, Item_t (hd_ty, _) -> + return (Dup_n_proof_argument (Dup_n_zero, hd_ty)) + | n, Item_t (_, (Item_t (_, _) as tl_ty)) -> + let+ (Dup_n_proof_argument (dup_n_witness, b_ty)) = + make_proof_argument (n - 1) tl_ty + in + Dup_n_proof_argument (Dup_n_succ dup_n_witness, b_ty) + | _ -> bad_stack_error ctxt loc I_DUP 1 + in + let*? n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + let*? () = + error_unless (Compare.Int.( > ) n 0) (Dup_n_bad_argument loc) + in + let*? (Dup_n_proof_argument (witness, after_ty)) = + record_trace (Dup_n_bad_stack loc) (make_proof_argument n stack_ty) + in + let*? ctxt = + record_trace_eval + (fun () -> + let t = serialize_ty_for_error after_ty in + Non_dupable_type (loc, t)) + (check_dupable_ty ctxt loc after_ty) + in + let dupn = {apply = (fun k -> IDup_n (loc, n, witness, k))} in + typed ctxt loc dupn (Item_t (after_ty, stack_ty)) + | Prim (loc, I_DIG, [n], result_annot), stack -> + let rec make_proof_argument : + type a s. int -> (a, s) stack_ty -> (a, s) dig_proof_argument tzresult + = + let open Result_syntax in + fun n stk -> + match (Compare.Int.(n = 0), stk) with + | true, Item_t (v, rest) -> + return @@ Dig_proof_argument (KRest, v, rest) + | false, Item_t (v, rest) -> + let+ (Dig_proof_argument (n', x, aft')) = + make_proof_argument (n - 1) rest + in + Dig_proof_argument (KPrefix (loc, v, n'), x, Item_t (v, aft')) + | _, _ -> + let whole_stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, I_DIG, 3, whole_stack)) + in + let*? n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + let*? () = error_unexpected_annot loc result_annot in + let*? (Dig_proof_argument (n', x, aft)) = make_proof_argument n stack in + let dig = {apply = (fun k -> IDig (loc, n, n', k))} in + typed ctxt loc dig (Item_t (x, aft)) + | Prim (loc, I_DIG, (([] | _ :: _ :: _) as l), _), _ -> + tzfail (Invalid_arity (loc, I_DIG, 1, List.length l)) + | Prim (loc, I_DUG, [n], result_annot), Item_t (x, whole_stack) -> ( + let*? whole_n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument whole_n) in + let*? () = error_unexpected_annot loc result_annot in + match make_dug_proof_argument loc whole_n x whole_stack with + | None -> + let whole_stack = serialize_stack_for_error ctxt whole_stack in + tzfail (Bad_stack (loc, I_DUG, whole_n, whole_stack)) + | Some (Dug_proof_argument (n', aft)) -> + let dug = {apply = (fun k -> IDug (loc, whole_n, n', k))} in + typed ctxt loc dug aft) + | Prim (loc, I_DUG, [_], result_annot), stack -> + let*? () = error_unexpected_annot loc result_annot in + let stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, I_DUG, 1, stack)) + | Prim (loc, I_DUG, (([] | _ :: _ :: _) as l), _), _ -> + tzfail (Invalid_arity (loc, I_DUG, 1, List.length l)) + | Prim (loc, I_SWAP, [], annot), Item_t (v, Item_t (w, rest)) -> + let*? () = error_unexpected_annot loc annot in + let swap = {apply = (fun k -> ISwap (loc, k))} in + let stack_ty = Item_t (w, Item_t (v, rest)) in + typed ctxt loc swap stack_ty + | Prim (loc, I_PUSH, [t; d], annot), stack -> + let*? () = check_var_annot loc annot in + let*? Ex_ty t, ctxt = + parse_packable_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy t + in + let* v, ctxt = + parse_data + ~unparse_code_rec + ~elab_conf + ~stack_depth:(stack_depth + 1) + ctxt + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + t + d + in + let push = {apply = (fun k -> IPush (loc, t, v, k))} in + typed ctxt loc push (Item_t (t, stack)) + | Prim (loc, I_UNIT, [], annot), stack -> + let*? () = check_var_type_annot loc annot in + let unit = {apply = (fun k -> IUnit (loc, k))} in + typed ctxt loc unit (Item_t (unit_t, stack)) + (* options *) + | Prim (loc, I_SOME, [], annot), Item_t (t, rest) -> + let*? () = check_var_type_annot loc annot in + let cons_some = {apply = (fun k -> ICons_some (loc, k))} in + let*? ty = option_t loc t in + typed ctxt loc cons_some (Item_t (ty, rest)) + | Prim (loc, I_NONE, [t], annot), stack -> + let*? Ex_ty t, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy t + in + let*? () = check_var_type_annot loc annot in + let cons_none = {apply = (fun k -> ICons_none (loc, t, k))} in + let*? ty = option_t loc t in + let stack_ty = Item_t (ty, stack) in + typed ctxt loc cons_none stack_ty + | Prim (loc, I_MAP, [body], annot), Item_t (Option_t (t, _, _), rest) -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = check_var_type_annot loc annot in + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt body (Item_t (t, rest)) + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ({loc; aft = Item_t (ret, aft_rest); _} as kibody) -> + let invalid_map_body () = + let aft = serialize_stack_for_error ctxt kibody.aft in + Invalid_map_body (loc, aft) + in + record_trace_eval + invalid_map_body + (let* Eq, ctxt = stack_eq loc ctxt 1 aft_rest rest in + let* opt_ty = option_t loc ret in + let final_stack = Item_t (opt_ty, rest) in + let body = kibody.instr.apply (IHalt loc) in + let apply k = IOpt_map {loc; body; k} in + typed_no_lwt ctxt loc {apply} final_stack) + | Typed {aft = Bot_t; _} -> + let aft = serialize_stack_for_error ctxt Bot_t in + tzfail (Invalid_map_body (loc, aft)) + | Failed _ -> tzfail (Invalid_map_block_fail loc)) + | ( Prim (loc, I_IF_NONE, [bt; bf], annot), + (Item_t (Option_t (t, _, _), rest) as bef) ) -> + let*? () = check_kind [Seq_kind] bt in + let*? () = check_kind [Seq_kind] bf in + let*? () = error_unexpected_annot loc annot in + let* btr, ctxt = non_terminal_recursion tc_context ctxt bt rest in + let stack_ty = Item_t (t, rest) in + let* bfr, ctxt = non_terminal_recursion tc_context ctxt bf stack_ty in + let branch ibt ibf = + let ifnone = + { + apply = + (fun k -> + let hloc = kinstr_location k in + let branch_if_none = ibt.instr.apply (IHalt hloc) + and branch_if_some = ibf.instr.apply (IHalt hloc) in + IIf_none {loc; branch_if_none; branch_if_some; k}); + } + in + {loc; instr = ifnone; bef; aft = ibt.aft} + in + Lwt.return @@ merge_branches ctxt loc btr bfr {branch} + (* pairs *) + | Prim (loc, I_PAIR, [], annot), Item_t (a, Item_t (b, rest)) -> + let*? () = check_constr_annot loc annot in + let*? (Ty_ex_c ty) = pair_t loc a b in + let stack_ty = Item_t (ty, rest) in + let cons_pair = {apply = (fun k -> ICons_pair (loc, k))} in + typed ctxt loc cons_pair stack_ty + | Prim (loc, I_PAIR, [n], annot), (Item_t _ as stack_ty) -> + let*? () = check_var_annot loc annot in + let rec make_proof_argument : + type a b s. + int -> (a, b * s) stack_ty -> (a, b, s) comb_proof_argument tzresult = + let open Result_syntax in + fun n stack_ty -> + match (n, stack_ty) with + | 1, Item_t _ -> return (Comb_proof_argument (Comb_one, stack_ty)) + | n, Item_t (a_ty, (Item_t _ as tl_ty)) -> + let* (Comb_proof_argument (comb_witness, Item_t (b_ty, tl_ty'))) = + make_proof_argument (n - 1) tl_ty + in + let+ (Ty_ex_c pair_t) = pair_t loc a_ty b_ty in + Comb_proof_argument + (Comb_succ comb_witness, Item_t (pair_t, tl_ty')) + | _ -> bad_stack_error ctxt loc I_PAIR 1 + in + let*? n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + let*? () = error_unless (Compare.Int.( > ) n 1) (Pair_bad_argument loc) in + let*? (Comb_proof_argument (witness, after_ty)) = + make_proof_argument n stack_ty + in + let comb = {apply = (fun k -> IComb (loc, n, witness, k))} in + typed ctxt loc comb after_ty + | Prim (loc, I_UNPAIR, [n], annot), (Item_t _ as stack_ty) -> + let*? () = error_unexpected_annot loc annot in + let rec make_proof_argument : + type a b s. + int -> (a, b * s) stack_ty -> (a, b, s) uncomb_proof_argument tzresult + = + let open Result_syntax in + fun n stack_ty -> + match (n, stack_ty) with + | 1, (Item_t _ as stack) -> + return (Uncomb_proof_argument (Uncomb_one, stack)) + | n, Item_t (Pair_t (a_ty, b_ty, _, _), tl_ty) -> + let+ (Uncomb_proof_argument (uncomb_witness, after_ty)) = + make_proof_argument (n - 1) (Item_t (b_ty, tl_ty)) + in + Uncomb_proof_argument + (Uncomb_succ uncomb_witness, Item_t (a_ty, after_ty)) + | _ -> bad_stack_error ctxt loc I_UNPAIR 1 + in + let*? n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + let*? () = + error_unless (Compare.Int.( > ) n 1) (Unpair_bad_argument loc) + in + let*? (Uncomb_proof_argument (witness, after_ty)) = + make_proof_argument n stack_ty + in + let uncomb = {apply = (fun k -> IUncomb (loc, n, witness, k))} in + typed ctxt loc uncomb after_ty + | Prim (loc, I_GET, [n], annot), Item_t (comb_ty, rest_ty) -> ( + let*? () = check_var_annot loc annot in + let*? n = parse_uint11 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + match make_comb_get_proof_argument n comb_ty with + | None -> + let whole_stack = serialize_stack_for_error ctxt stack_ty in + tzfail (Bad_stack (loc, I_GET, 1, whole_stack)) + | Some (Comb_get_proof_argument (witness, ty')) -> + let after_stack_ty = Item_t (ty', rest_ty) in + let comb_get = {apply = (fun k -> IComb_get (loc, n, witness, k))} in + typed ctxt loc comb_get after_stack_ty) + | ( Prim (loc, I_UPDATE, [n], annot), + Item_t (value_ty, Item_t (comb_ty, rest_ty)) ) -> + let*? () = check_var_annot loc annot in + let*? n = parse_uint11 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + let*? (Comb_set_proof_argument (witness, after_ty)) = + make_comb_set_proof_argument ctxt stack_ty loc n value_ty comb_ty + in + let after_stack_ty = Item_t (after_ty, rest_ty) in + let comb_set = {apply = (fun k -> IComb_set (loc, n, witness, k))} in + typed ctxt loc comb_set after_stack_ty + | Prim (loc, I_UNPAIR, [], annot), Item_t (Pair_t (a, b, _, _), rest) -> + let*? () = check_unpair_annot loc annot in + let unpair = {apply = (fun k -> IUnpair (loc, k))} in + typed ctxt loc unpair (Item_t (a, Item_t (b, rest))) + | Prim (loc, I_CAR, [], annot), Item_t (Pair_t (a, _, _, _), rest) -> + let*? () = check_destr_annot loc annot in + let car = {apply = (fun k -> ICar (loc, k))} in + typed ctxt loc car (Item_t (a, rest)) + | Prim (loc, I_CDR, [], annot), Item_t (Pair_t (_, b, _, _), rest) -> + let*? () = check_destr_annot loc annot in + let cdr = {apply = (fun k -> ICdr (loc, k))} in + typed ctxt loc cdr (Item_t (b, rest)) + (* ors *) + | Prim (loc, I_LEFT, [tr], annot), Item_t (tl, rest) -> + let*? Ex_ty tr, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy tr + in + let*? () = check_constr_annot loc annot in + let cons_left = {apply = (fun k -> ICons_left (loc, tr, k))} in + let*? (Ty_ex_c ty) = or_t loc tl tr in + let stack_ty = Item_t (ty, rest) in + typed ctxt loc cons_left stack_ty + | Prim (loc, I_RIGHT, [tl], annot), Item_t (tr, rest) -> + let*? Ex_ty tl, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy tl + in + let*? () = check_constr_annot loc annot in + let cons_right = {apply = (fun k -> ICons_right (loc, tl, k))} in + let*? (Ty_ex_c ty) = or_t loc tl tr in + let stack_ty = Item_t (ty, rest) in + typed ctxt loc cons_right stack_ty + | ( Prim (loc, I_IF_LEFT, [bt; bf], annot), + (Item_t (Or_t (tl, tr, _, _), rest) as bef) ) -> + let*? () = check_kind [Seq_kind] bt in + let*? () = check_kind [Seq_kind] bf in + let*? () = error_unexpected_annot loc annot in + let* btr, ctxt = + non_terminal_recursion tc_context ctxt bt (Item_t (tl, rest)) + in + let* bfr, ctxt = + non_terminal_recursion tc_context ctxt bf (Item_t (tr, rest)) + in + let branch ibt ibf = + let instr = + { + apply = + (fun k -> + let hloc = kinstr_location k in + let branch_if_left = ibt.instr.apply (IHalt hloc) + and branch_if_right = ibf.instr.apply (IHalt hloc) in + IIf_left {loc; branch_if_left; branch_if_right; k}); + } + in + {loc; instr; bef; aft = ibt.aft} + in + Lwt.return @@ merge_branches ctxt loc btr bfr {branch} + (* lists *) + | Prim (loc, I_NIL, [t], annot), stack -> + let*? Ex_ty t, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy t + in + let*? () = check_var_type_annot loc annot in + let nil = {apply = (fun k -> INil (loc, t, k))} in + let*? ty = list_t loc t in + typed ctxt loc nil (Item_t (ty, stack)) + | ( Prim (loc, I_CONS, [], annot), + Item_t (tv, (Item_t (List_t (t, _), _) as stack)) ) -> + let*? Eq, ctxt = check_item_ty ctxt tv t loc I_CONS 1 2 in + let*? () = check_var_annot loc annot in + let cons_list = {apply = (fun k -> ICons_list (loc, k))} in + (typed ctxt loc cons_list stack + : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_IF_CONS, [bt; bf], annot), + (Item_t (List_t (t, _), rest) as bef) ) -> + let*? () = check_kind [Seq_kind] bt in + let*? () = check_kind [Seq_kind] bf in + let*? () = error_unexpected_annot loc annot in + let* btr, ctxt = + non_terminal_recursion tc_context ctxt bt (Item_t (t, bef)) + in + let* bfr, ctxt = non_terminal_recursion tc_context ctxt bf rest in + let branch ibt ibf = + let instr = + { + apply = + (fun k -> + let hloc = kinstr_location k in + let branch_if_cons = ibt.instr.apply (IHalt hloc) + and branch_if_nil = ibf.instr.apply (IHalt hloc) in + IIf_cons {loc; branch_if_nil; branch_if_cons; k}); + } + in + {loc; instr; bef; aft = ibt.aft} + in + Lwt.return @@ merge_branches ctxt loc btr bfr {branch} + | Prim (loc, I_SIZE, [], annot), Item_t (List_t _, rest) -> + let*? () = check_var_type_annot loc annot in + let list_size = {apply = (fun k -> IList_size (loc, k))} in + typed ctxt loc list_size (Item_t (nat_t, rest)) + | Prim (loc, I_MAP, [body], annot), Item_t (List_t (elt, _), starting_rest) + -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = check_var_type_annot loc annot in + let* judgement, ctxt = + non_terminal_recursion + tc_context + ctxt + body + (Item_t (elt, starting_rest)) + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ({aft = Item_t (ret, rest) as aft; _} as kibody) -> + let invalid_map_body () = + let aft = serialize_stack_for_error ctxt aft in + Invalid_map_body (loc, aft) + in + record_trace_eval + invalid_map_body + (let* Eq, ctxt = stack_eq loc ctxt 1 rest starting_rest in + let hloc = loc in + let ibody = kibody.instr.apply (IHalt hloc) in + let* ty = list_t loc ret in + let list_map = + { + apply = + (fun k -> IList_map (loc, ibody, for_logging_only ty, k)); + } + in + let stack = Item_t (ty, rest) in + typed_no_lwt ctxt loc list_map stack) + | Typed {aft; _} -> + let aft = serialize_stack_for_error ctxt aft in + tzfail (Invalid_map_body (loc, aft)) + | Failed _ -> tzfail (Invalid_map_block_fail loc)) + | Prim (loc, I_ITER, [body], annot), Item_t (List_t (elt, _), rest) -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = error_unexpected_annot loc annot in + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt body (Item_t (elt, rest)) + in + let mk_list_iter ibody = + { + apply = + (fun k -> + let hinfo = loc in + let ibody = ibody.instr.apply (IHalt hinfo) in + IList_iter (loc, for_logging_only elt, ibody, k)); + } + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ({aft; _} as ibody) -> + let invalid_iter_body () = + let aft = serialize_stack_for_error ctxt ibody.aft in + let rest = serialize_stack_for_error ctxt rest in + Invalid_iter_body (loc, rest, aft) + in + record_trace_eval + invalid_iter_body + (let* Eq, ctxt = stack_eq loc ctxt 1 aft rest in + typed_no_lwt ctxt loc (mk_list_iter ibody) rest) + | Failed {descr} -> typed_no_lwt ctxt loc (mk_list_iter (descr rest)) rest + ) + (* sets *) + | Prim (loc, I_EMPTY_SET, [t], annot), rest -> + let*? Ex_comparable_ty t, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt t + in + let*? () = check_var_type_annot loc annot in + let instr = {apply = (fun k -> IEmpty_set (loc, t, k))} in + let*? ty = set_t loc t in + typed ctxt loc instr (Item_t (ty, rest)) + | Prim (loc, I_ITER, [body], annot), Item_t (Set_t (elt, _), rest) -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = error_unexpected_annot loc annot in + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt body (Item_t (elt, rest)) + in + let mk_iset_iter ibody = + { + apply = + (fun k -> + let hinfo = loc in + let ibody = ibody.instr.apply (IHalt hinfo) in + ISet_iter (loc, for_logging_only elt, ibody, k)); + } + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ({aft; _} as ibody) -> + let invalid_iter_body () = + let aft = serialize_stack_for_error ctxt ibody.aft in + let rest = serialize_stack_for_error ctxt rest in + Invalid_iter_body (loc, rest, aft) + in + record_trace_eval + invalid_iter_body + (let* Eq, ctxt = stack_eq loc ctxt 1 aft rest in + typed_no_lwt ctxt loc (mk_iset_iter ibody) rest) + | Failed {descr} -> typed_no_lwt ctxt loc (mk_iset_iter (descr rest)) rest + ) + | Prim (loc, I_MEM, [], annot), Item_t (v, Item_t (Set_t (elt, _), rest)) -> + let*? () = check_var_type_annot loc annot in + let*? Eq, ctxt = check_item_ty ctxt elt v loc I_MEM 1 2 in + let instr = {apply = (fun k -> ISet_mem (loc, k))} in + (typed ctxt loc instr (Item_t (bool_t, rest)) + : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_UPDATE, [], annot), + Item_t (v, Item_t (Bool_t, (Item_t (Set_t (elt, _), _) as stack))) ) -> + let*? Eq, ctxt = check_item_ty ctxt elt v loc I_UPDATE 1 3 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISet_update (loc, k))} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | Prim (loc, I_SIZE, [], annot), Item_t (Set_t _, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISet_size (loc, k))} in + typed ctxt loc instr (Item_t (nat_t, rest)) + (* maps *) + | Prim (loc, I_EMPTY_MAP, [tk; tv], annot), stack -> + let*? Ex_comparable_ty tk, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt tk + in + let*? Ex_ty tv, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy tv + in + let*? () = check_var_type_annot loc annot in + let instr = + {apply = (fun k -> IEmpty_map (loc, tk, for_logging_only tv, k))} + in + let*? ty = map_t loc tk tv in + typed ctxt loc instr (Item_t (ty, stack)) + | Prim (loc, I_MAP, [body], annot), Item_t (Map_t (kt, elt, _), starting_rest) + -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = check_var_type_annot loc annot in + let*? (Ty_ex_c ty) = pair_t loc kt elt in + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt body (Item_t (ty, starting_rest)) + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ({aft = Item_t (ret, rest) as aft; _} as ibody) -> + let invalid_map_body () = + let aft = serialize_stack_for_error ctxt aft in + Invalid_map_body (loc, aft) + in + record_trace_eval + invalid_map_body + (let* Eq, ctxt = stack_eq loc ctxt 1 rest starting_rest in + let* ty = map_t loc kt ret in + let instr = + { + apply = + (fun k -> + let hinfo = loc in + let ibody = ibody.instr.apply (IHalt hinfo) in + IMap_map (loc, for_logging_only ty, ibody, k)); + } + in + let stack = Item_t (ty, rest) in + typed_no_lwt ctxt loc instr stack) + | Typed {aft; _} -> + let aft = serialize_stack_for_error ctxt aft in + tzfail (Invalid_map_body (loc, aft)) + | Failed _ -> tzfail (Invalid_map_block_fail loc)) + | Prim (loc, I_ITER, [body], annot), Item_t (Map_t (key, element_ty, _), rest) + -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = error_unexpected_annot loc annot in + let*? (Ty_ex_c ty) = pair_t loc key element_ty in + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt body (Item_t (ty, rest)) + in + let make_instr ibody = + { + apply = + (fun k -> + let hinfo = loc in + let ibody = ibody.instr.apply (IHalt hinfo) in + IMap_iter (loc, for_logging_only ty, ibody, k)); + } + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ({aft; _} as ibody) -> + let invalid_iter_body () = + let aft = serialize_stack_for_error ctxt ibody.aft in + let rest = serialize_stack_for_error ctxt rest in + Invalid_iter_body (loc, rest, aft) + in + record_trace_eval + invalid_iter_body + (let* Eq, ctxt = stack_eq loc ctxt 1 aft rest in + typed_no_lwt ctxt loc (make_instr ibody) rest) + | Failed {descr} -> typed_no_lwt ctxt loc (make_instr (descr rest)) rest) + | Prim (loc, I_MEM, [], annot), Item_t (vk, Item_t (Map_t (k, _, _), rest)) -> + let*? Eq, ctxt = check_item_ty ctxt vk k loc I_MEM 1 2 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMap_mem (loc, k))} in + (typed ctxt loc instr (Item_t (bool_t, rest)) + : ((a, s) judgement * context) tzresult Lwt.t) + | Prim (loc, I_GET, [], annot), Item_t (vk, Item_t (Map_t (k, elt, _), rest)) + -> + let*? Eq, ctxt = check_item_ty ctxt vk k loc I_GET 1 2 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMap_get (loc, k))} in + let*? ty = option_t loc elt in + let stack = Item_t (ty, rest) in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_UPDATE, [], annot), + Item_t + ( vk, + Item_t (Option_t (vv, _, _), (Item_t (Map_t (k, v, _), _) as stack)) + ) ) -> + let*? Eq, ctxt = check_item_ty ctxt vk k loc I_UPDATE 1 3 in + let*? Eq, ctxt = check_item_ty ctxt vv v loc I_UPDATE 2 3 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMap_update (loc, k))} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_GET_AND_UPDATE, [], annot), + Item_t + ( vk, + (Item_t (Option_t (vv, _, _), Item_t (Map_t (k, v, _), _)) as stack) + ) ) -> + let*? Eq, ctxt = check_item_ty ctxt vk k loc I_GET_AND_UPDATE 1 3 in + let*? Eq, ctxt = check_item_ty ctxt vv v loc I_GET_AND_UPDATE 2 3 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMap_get_and_update (loc, k))} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | Prim (loc, I_SIZE, [], annot), Item_t (Map_t (_, _, _), rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMap_size (loc, k))} in + typed ctxt loc instr (Item_t (nat_t, rest)) + (* big_map *) + | Prim (loc, I_EMPTY_BIG_MAP, [tk; tv], annot), stack -> + let*? Ex_comparable_ty tk, ctxt = + parse_comparable_ty ~stack_depth:(stack_depth + 1) ctxt tk + in + let*? Ex_ty tv, ctxt = + parse_big_map_value_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy tv + in + let*? () = check_var_type_annot loc annot in + let instr = {apply = (fun k -> IEmpty_big_map (loc, tk, tv, k))} in + let*? ty = big_map_t loc tk tv in + let stack = Item_t (ty, stack) in + typed ctxt loc instr stack + | ( Prim (loc, I_MEM, [], annot), + Item_t (set_key, Item_t (Big_map_t (k, _, _), rest)) ) -> + let*? Eq, ctxt = check_item_ty ctxt set_key k loc I_MEM 1 2 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBig_map_mem (loc, k))} in + let stack = Item_t (bool_t, rest) in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_GET, [], annot), + Item_t (vk, Item_t (Big_map_t (k, elt, _), rest)) ) -> + let*? Eq, ctxt = check_item_ty ctxt vk k loc I_GET 1 2 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBig_map_get (loc, k))} in + let*? ty = option_t loc elt in + let stack = Item_t (ty, rest) in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_UPDATE, [], annot), + Item_t + ( set_key, + Item_t + ( Option_t (set_value, _, _), + (Item_t (Big_map_t (map_key, map_value, _), _) as stack) ) ) ) -> + let*? Eq, ctxt = check_item_ty ctxt set_key map_key loc I_UPDATE 1 3 in + let*? Eq, ctxt = + check_item_ty ctxt set_value map_value loc I_UPDATE 2 3 + in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBig_map_update (loc, k))} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_GET_AND_UPDATE, [], annot), + Item_t + ( vk, + (Item_t (Option_t (vv, _, _), Item_t (Big_map_t (k, v, _), _)) as + stack) ) ) -> + let*? Eq, ctxt = check_item_ty ctxt vk k loc I_GET_AND_UPDATE 1 3 in + let*? Eq, ctxt = check_item_ty ctxt vv v loc I_GET_AND_UPDATE 2 3 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBig_map_get_and_update (loc, k))} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + (* Sapling *) + | Prim (loc, I_SAPLING_EMPTY_STATE, [memo_size], annot), rest -> + let*? memo_size = parse_memo_size memo_size in + let*? () = check_var_annot loc annot in + let instr = + {apply = (fun k -> ISapling_empty_state (loc, memo_size, k))} + in + let stack = Item_t (sapling_state_t ~memo_size, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_SAPLING_VERIFY_UPDATE, [], _), + Item_t + ( Sapling_transaction_deprecated_t transaction_memo_size, + Item_t ((Sapling_state_t state_memo_size as state_ty), rest) ) ) -> + if legacy (* Legacy check introduced in Jakarta. *) then + let*? () = + memo_size_eq + ~error_details:(Informative ()) + state_memo_size + transaction_memo_size + in + let instr = + {apply = (fun k -> ISapling_verify_update_deprecated (loc, k))} + in + let*? (Ty_ex_c pair_ty) = pair_t loc int_t state_ty in + let*? ty = option_t loc pair_ty in + let stack = Item_t (ty, rest) in + typed ctxt loc instr stack + else tzfail (Deprecated_instruction T_sapling_transaction_deprecated) + | ( Prim (loc, I_SAPLING_VERIFY_UPDATE, [], _), + Item_t + ( Sapling_transaction_t transaction_memo_size, + Item_t ((Sapling_state_t state_memo_size as state_ty), rest) ) ) -> + let*? () = + memo_size_eq + ~error_details:(Informative ()) + state_memo_size + transaction_memo_size + in + let instr = {apply = (fun k -> ISapling_verify_update (loc, k))} in + let*? (Ty_ex_c pair_ty) = pair_t loc int_t state_ty in + let*? (Ty_ex_c pair_ty) = pair_t loc bytes_t pair_ty in + let*? ty = option_t loc pair_ty in + let stack = Item_t (ty, rest) in + typed ctxt loc instr stack + (* control *) + | Seq (loc, []), stack -> + let instr = {apply = (fun k -> k)} in + typed ctxt loc instr stack + | Seq (_, [single]), stack -> + non_terminal_recursion tc_context ctxt single stack + | Seq (loc, hd :: tl), stack -> ( + let* judgement, ctxt = non_terminal_recursion tc_context ctxt hd stack in + match judgement with + | Failed _ -> tzfail (Fail_not_in_tail_position (Micheline.location hd)) + | Typed ({aft = middle; _} as ihd) -> + let+ judgement, ctxt = + non_terminal_recursion + tc_context + ctxt + (Seq (Micheline.dummy_location, tl)) + middle + in + let judgement = + match judgement with + | Failed {descr} -> + let descr ret = compose_descr loc ihd (descr ret) in + Failed {descr} + | Typed itl -> Typed (compose_descr loc ihd itl) + in + (judgement, ctxt)) + | Prim (loc, I_IF, [bt; bf], annot), (Item_t (Bool_t, rest) as bef) -> + let*? () = check_kind [Seq_kind] bt in + let*? () = check_kind [Seq_kind] bf in + let*? () = error_unexpected_annot loc annot in + let* btr, ctxt = non_terminal_recursion tc_context ctxt bt rest in + let* bfr, ctxt = non_terminal_recursion tc_context ctxt bf rest in + let branch ibt ibf = + let instr = + { + apply = + (fun k -> + let hloc = kinstr_location k in + let branch_if_true = ibt.instr.apply (IHalt hloc) + and branch_if_false = ibf.instr.apply (IHalt hloc) in + IIf {loc; branch_if_true; branch_if_false; k}); + } + in + {loc; instr; bef; aft = ibt.aft} + in + Lwt.return @@ merge_branches ctxt loc btr bfr {branch} + | Prim (loc, I_LOOP, [body], annot), (Item_t (Bool_t, rest) as stack) -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = error_unexpected_annot loc annot in + let* judgement, ctxt = non_terminal_recursion tc_context ctxt body rest in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ibody -> + let unmatched_branches () = + let aft = serialize_stack_for_error ctxt ibody.aft in + let stack = serialize_stack_for_error ctxt stack in + Unmatched_branches (loc, aft, stack) + in + record_trace_eval + unmatched_branches + (let* Eq, ctxt = stack_eq loc ctxt 1 ibody.aft stack in + let instr = + { + apply = + (fun k -> + let loc = kinstr_location k in + let ibody = ibody.instr.apply (IHalt loc) in + ILoop (loc, ibody, k)); + } + in + typed_no_lwt ctxt loc instr rest) + | Failed {descr} -> + let instr = + { + apply = + (fun k -> + let loc = kinstr_location k in + let ibody = descr stack in + let ibody = ibody.instr.apply (IHalt loc) in + ILoop (loc, ibody, k)); + } + in + typed_no_lwt ctxt loc instr rest) + | ( Prim (loc, I_LOOP_LEFT, [body], annot), + (Item_t (Or_t (tl, tr, _, _), rest) as stack) ) -> ( + let*? () = check_kind [Seq_kind] body in + let*? () = check_var_annot loc annot in + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt body (Item_t (tl, rest)) + in + let open Result_syntax in + Lwt.return + @@ + match judgement with + | Typed ibody -> + let unmatched_branches () = + let aft = serialize_stack_for_error ctxt ibody.aft in + let stack = serialize_stack_for_error ctxt stack in + Unmatched_branches (loc, aft, stack) + in + record_trace_eval + unmatched_branches + (let* Eq, ctxt = stack_eq loc ctxt 1 ibody.aft stack in + let instr = + { + apply = + (fun k -> + let loc = kinstr_location k in + let ibody = ibody.instr.apply (IHalt loc) in + ILoop_left (loc, ibody, k)); + } + in + let stack = Item_t (tr, rest) in + typed_no_lwt ctxt loc instr stack) + | Failed {descr} -> + let instr = + { + apply = + (fun k -> + let loc = kinstr_location k in + let ibody = descr stack in + let ibody = ibody.instr.apply (IHalt loc) in + ILoop_left (loc, ibody, k)); + } + in + let stack = Item_t (tr, rest) in + typed_no_lwt ctxt loc instr stack) + | Prim (loc, I_LAMBDA, [arg; ret; code], annot), stack -> + let*? Ex_ty arg, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy arg + in + let*? Ex_ty ret, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy ret + in + let*? () = check_kind [Seq_kind] code in + let*? () = check_var_annot loc annot in + let* kdescr, ctxt = + parse_kdescr + ~unparse_code_rec + (Tc_context.add_lambda tc_context) + ~elab_conf + ~stack_depth:(stack_depth + 1) + ctxt + arg + ret + code + in + (* No need to normalize the unparsed component to Optimized mode here + because the script is already normalized in Optimized mode. *) + let instr = {apply = (fun k -> ILambda (loc, Lam (kdescr, code), k))} in + let*? ty = lambda_t loc arg ret in + let stack = Item_t (ty, stack) in + typed ctxt loc instr stack + | ( Prim (loc, I_LAMBDA_REC, [arg_ty_expr; ret_ty_expr; lambda_expr], annot), + stack ) -> + let*? Ex_ty arg, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy arg_ty_expr + in + let*? Ex_ty ret, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy ret_ty_expr + in + let*? () = check_kind [Seq_kind] lambda_expr in + let*? () = check_var_annot loc annot in + let*? lambda_rec_ty = lambda_t loc arg ret in + let* code, ctxt = + parse_lam_rec + ~unparse_code_rec:(fun ctxt ~stack_depth:_ _unparsing_mode node -> + return (node, ctxt)) + (* No need to normalize the unparsed component to Optimized mode here + because the script is already normalized in Optimized mode. *) + Tc_context.(add_lambda tc_context) + ~elab_conf + ~stack_depth:(stack_depth + 1) + ctxt + arg + ret + lambda_rec_ty + lambda_expr + in + let instr = {apply = (fun k -> ILambda (loc, code, k))} in + let stack = Item_t (lambda_rec_ty, stack) in + typed ctxt loc instr stack + | ( Prim (loc, I_EXEC, [], annot), + Item_t (arg, Item_t (Lambda_t (param, ret, _), rest)) ) -> + let*? Eq, ctxt = check_item_ty ctxt arg param loc I_EXEC 1 2 in + let*? () = check_var_annot loc annot in + let stack = Item_t (ret, rest) in + let instr = {apply = (fun k -> IExec (loc, for_logging_only stack, k))} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, I_APPLY, [], annot), + Item_t + ( capture, + Item_t (Lambda_t (Pair_t (capture_ty, arg_ty, _, _), ret, _), rest) ) + ) -> + let*? () = check_packable ~allow_contract:false loc capture_ty in + let*? Eq, ctxt = check_item_ty ctxt capture capture_ty loc I_APPLY 1 2 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IApply (loc, capture_ty, k))} in + let*? res_ty = + lambda_t loc arg_ty ret + (* This cannot tzfail because the type [lambda 'arg 'ret] is always smaller than + the input type [lambda (pair 'arg 'capture) 'ret]. In an ideal world, there + would be a smart deconstructor to ensure this statically. *) + in + let stack = Item_t (res_ty, rest) in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | Prim (loc, I_DIP, [code], annot), Item_t (v, rest) -> ( + let*? () = error_unexpected_annot loc annot in + let*? () = check_kind [Seq_kind] code in + let* judgement, ctxt = non_terminal_recursion tc_context ctxt code rest in + match judgement with + | Typed descr -> + let instr = + { + apply = + (fun k -> + let b = descr.instr.apply (IHalt descr.loc) in + IDip (loc, b, for_logging_only v, k)); + } + in + let stack = Item_t (v, descr.aft) in + typed ctxt loc instr stack + | Failed _ -> tzfail (Fail_not_in_tail_position loc)) + | Prim (loc, I_DIP, [n; code], result_annot), stack -> + let*? n = parse_uint10 n in + let*? ctxt = Gas.consume ctxt (Typecheck_costs.proof_argument n) in + let rec make_proof_argument : + type a s. + int -> (a, s) stack_ty -> (a, s) dipn_proof_argument tzresult Lwt.t = + fun n stk -> + match (Compare.Int.(n = 0), stk) with + | true, rest -> ( + let* judgement, ctxt = + non_terminal_recursion tc_context ctxt code rest + in + match judgement with + | Typed descr -> + return + (Dipn_proof_argument (KRest, ctxt, descr, descr.aft) + : (a, s) dipn_proof_argument) + | Failed _ -> tzfail (Fail_not_in_tail_position loc)) + | false, Item_t (v, rest) -> + let+ (Dipn_proof_argument (n', ctxt, descr, aft')) = + make_proof_argument (n - 1) rest + in + let w = KPrefix (loc, v, n') in + Dipn_proof_argument (w, ctxt, descr, Item_t (v, aft')) + | _, _ -> + let whole_stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, I_DIP, 1, whole_stack)) + in + let*? () = error_unexpected_annot loc result_annot in + let* (Dipn_proof_argument (n', ctxt, descr, aft)) = + make_proof_argument n stack + in + let b = descr.instr.apply (IHalt descr.loc) in + let res = {apply = (fun k -> IDipn (loc, n, n', b, k))} in + typed ctxt loc res aft + | Prim (loc, I_DIP, (([] | _ :: _ :: _ :: _) as l), _), _ -> + (* Technically, the arities 1 and 2 are allowed but the error only mentions 2. + However, DIP {code} is equivalent to DIP 1 {code} so hinting at an arity of 2 makes sense. *) + tzfail (Invalid_arity (loc, I_DIP, 2, List.length l)) + | Prim (loc, I_FAILWITH, [], annot), Item_t (v, _rest) -> + let*? () = error_unexpected_annot loc annot in + let*? () = check_packable ~allow_contract:false loc v in + let instr = {apply = (fun _k -> IFailwith (loc, v))} in + let descr aft = {loc; instr; bef = stack_ty; aft} in + log_stack loc stack_ty Bot_t ; + return (Failed {descr}, ctxt) + | Prim (loc, I_NEVER, [], annot), Item_t (Never_t, _rest) -> + let*? () = error_unexpected_annot loc annot in + let instr = {apply = (fun _k -> INever loc)} in + let descr aft = {loc; instr; bef = stack_ty; aft} in + log_stack loc stack_ty Bot_t ; + return (Failed {descr}, ctxt) + (* timestamp operations *) + | Prim (loc, I_ADD, [], annot), Item_t (Timestamp_t, Item_t (Int_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_timestamp_to_seconds (loc, k))} in + typed ctxt loc instr (Item_t (Timestamp_t, rest)) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Int_t, (Item_t (Timestamp_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_seconds_to_timestamp (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SUB, [], annot), Item_t (Timestamp_t, Item_t (Int_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_timestamp_seconds (loc, k))} in + let stack = Item_t (Timestamp_t, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_SUB, [], annot), + Item_t (Timestamp_t, Item_t (Timestamp_t, rest)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IDiff_timestamps (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + (* string operations *) + | ( Prim (loc, I_CONCAT, [], annot), + Item_t (String_t, (Item_t (String_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IConcat_string_pair (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_CONCAT, [], annot), Item_t (List_t (String_t, _), rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IConcat_string (loc, k))} in + typed ctxt loc instr (Item_t (String_t, rest)) + | ( Prim (loc, I_SLICE, [], annot), + Item_t (Nat_t, Item_t (Nat_t, Item_t (String_t, rest))) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISlice_string (loc, k))} in + let stack = Item_t (option_string_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_SIZE, [], annot), Item_t (String_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IString_size (loc, k))} in + let stack = Item_t (nat_t, rest) in + typed ctxt loc instr stack + (* bytes operations *) + | ( Prim (loc, I_CONCAT, [], annot), + Item_t (Bytes_t, (Item_t (Bytes_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IConcat_bytes_pair (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_CONCAT, [], annot), Item_t (List_t (Bytes_t, _), rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IConcat_bytes (loc, k))} in + let stack = Item_t (Bytes_t, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_SLICE, [], annot), + Item_t (Nat_t, Item_t (Nat_t, Item_t (Bytes_t, rest))) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISlice_bytes (loc, k))} in + let stack = Item_t (option_bytes_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_SIZE, [], annot), Item_t (Bytes_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBytes_size (loc, k))} in + let stack = Item_t (nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_BYTES, [], annot), Item_t (Nat_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBytes_nat (loc, k))} in + let stack = Item_t (bytes_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_NAT, [], annot), Item_t (Bytes_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INat_bytes (loc, k))} in + let stack = Item_t (nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_BYTES, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBytes_int (loc, k))} in + let stack = Item_t (bytes_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_INT, [], annot), Item_t (Bytes_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IInt_bytes (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + (* currency operations *) + | ( Prim (loc, I_ADD, [], annot), + Item_t (Mutez_t, (Item_t (Mutez_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_tez (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_SUB, [], annot), + Item_t (Mutez_t, (Item_t (Mutez_t, _) as stack)) ) -> + if legacy (* Legacy check introduced in Ithaca. *) then + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_tez_legacy (loc, k))} in + typed ctxt loc instr stack + else tzfail (Deprecated_instruction I_SUB) + | Prim (loc, I_SUB_MUTEZ, [], annot), Item_t (Mutez_t, Item_t (Mutez_t, rest)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_tez (loc, k))} in + let stack = Item_t (option_mutez_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Mutez_t, Item_t (Nat_t, rest)) -> + (* no type name check *) + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_teznat (loc, k))} in + let stack = Item_t (Mutez_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Nat_t, (Item_t (Mutez_t, _) as stack)) + -> + (* no type name check *) + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_nattez (loc, k))} in + typed ctxt loc instr stack + (* boolean operations *) + | Prim (loc, I_OR, [], annot), Item_t (Bool_t, (Item_t (Bool_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IOr (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_AND, [], annot), Item_t (Bool_t, (Item_t (Bool_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAnd (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_XOR, [], annot), Item_t (Bool_t, (Item_t (Bool_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IXor (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_NOT, [], annot), (Item_t (Bool_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INot (loc, k))} in + typed ctxt loc instr stack + (* integer operations *) + | Prim (loc, I_ABS, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAbs_int (loc, k))} in + let stack = Item_t (nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_ISNAT, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IIs_nat (loc, k))} in + let stack = Item_t (option_nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_INT, [], annot), Item_t (Nat_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IInt_nat (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_NEG, [], annot), (Item_t (Int_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INeg (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_NEG, [], annot), Item_t (Nat_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INeg (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_ADD, [], annot), Item_t (Int_t, (Item_t (Int_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_int (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_ADD, [], annot), Item_t (Int_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_int (loc, k))} in + let stack = Item_t (Int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_ADD, [], annot), Item_t (Nat_t, (Item_t (Int_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_int (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_ADD, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SUB, [], annot), Item_t (Int_t, (Item_t (Int_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_int (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SUB, [], annot), Item_t (Int_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_int (loc, k))} in + let stack = Item_t (Int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_SUB, [], annot), Item_t (Nat_t, (Item_t (Int_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_int (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SUB, [], annot), Item_t (Nat_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISub_int (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Int_t, (Item_t (Int_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_int (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Int_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_int (loc, k))} in + let stack = Item_t (Int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Nat_t, (Item_t (Int_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_EDIV, [], annot), Item_t (Mutez_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEdiv_teznat (loc, k))} in + let stack = Item_t (option_pair_mutez_mutez_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_EDIV, [], annot), Item_t (Mutez_t, Item_t (Mutez_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEdiv_tez (loc, k))} in + let stack = Item_t (option_pair_nat_mutez_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_EDIV, [], annot), Item_t (Int_t, Item_t (Int_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEdiv_int (loc, k))} in + let stack = Item_t (option_pair_int_nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_EDIV, [], annot), Item_t (Int_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEdiv_int (loc, k))} in + let stack = Item_t (option_pair_int_nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_EDIV, [], annot), Item_t (Nat_t, Item_t (Int_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEdiv_nat (loc, k))} in + let stack = Item_t (option_pair_int_nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_EDIV, [], annot), Item_t (Nat_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEdiv_nat (loc, k))} in + let stack = Item_t (option_pair_nat_nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_LSL, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILsl_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_LSL, [], annot), Item_t (Bytes_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILsl_bytes (loc, k))} in + let stack = Item_t (Bytes_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_LSR, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILsr_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_LSR, [], annot), Item_t (Bytes_t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILsr_bytes (loc, k))} in + let stack = Item_t (Bytes_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_OR, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IOr_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_OR, [], annot), Item_t (Bytes_t, (Item_t (Bytes_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IOr_bytes (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_AND, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAnd_nat (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_AND, [], annot), Item_t (Int_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAnd_int_nat (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_AND, [], annot), + Item_t (Bytes_t, (Item_t (Bytes_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAnd_bytes (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_XOR, [], annot), Item_t (Nat_t, (Item_t (Nat_t, _) as stack)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IXor_nat (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_XOR, [], annot), + Item_t (Bytes_t, (Item_t (Bytes_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IXor_bytes (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_NOT, [], annot), (Item_t (Int_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INot_int (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_NOT, [], annot), Item_t (Nat_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INot_int (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_NOT, [], annot), (Item_t (Bytes_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INot_bytes (loc, k))} in + typed ctxt loc instr stack + (* comparison *) + | Prim (loc, I_COMPARE, [], annot), Item_t (t1, Item_t (t2, rest)) -> + let*? () = check_var_annot loc annot in + let*? Eq, ctxt = check_item_ty ctxt t1 t2 loc I_COMPARE 1 2 in + let*? Eq = check_comparable loc t1 in + let instr = {apply = (fun k -> ICompare (loc, t1, k))} in + let stack = Item_t (int_t, rest) in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + (* comparators *) + | Prim (loc, I_EQ, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IEq (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_NEQ, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INeq (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_LT, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILt (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_GT, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IGt (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_LE, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILe (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_GE, [], annot), Item_t (Int_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IGe (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + (* annotations *) + | Prim (loc, I_CAST, [cast_t], annot), (Item_t (t, _) as stack) -> + let*? () = check_var_annot loc annot in + let*? Ex_ty cast_t, ctxt = + parse_any_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy cast_t + in + let*? eq, ctxt = + Gas_monad.run ctxt @@ ty_eq ~error_details:(Informative loc) cast_t t + in + let*? Eq = eq in + (* We can reuse [stack] because [a ty = b ty] means [a = b]. *) + let instr = {apply = (fun k -> k)} in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | Prim (loc, I_RENAME, [], annot), (Item_t _ as stack) -> + let*? () = check_var_annot loc annot in + (* can erase annot *) + let instr = {apply = (fun k -> k)} in + typed ctxt loc instr stack + (* packing *) + | Prim (loc, I_PACK, [], annot), Item_t (t, rest) -> + let*? () = + check_packable + ~allow_contract:true + (* allow to pack contracts for hash/signature checks *) loc + t + in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IPack (loc, t, k))} in + let stack = Item_t (bytes_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_UNPACK, [ty], annot), Item_t (Bytes_t, rest) -> + let*? Ex_ty t, ctxt = + parse_packable_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy ty + in + let*? () = check_var_type_annot loc annot in + let*? res_ty = option_t loc t in + let instr = {apply = (fun k -> IUnpack (loc, t, k))} in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + (* protocol *) + | Prim (loc, I_ADDRESS, [], annot), Item_t (Contract_t _, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAddress (loc, k))} in + let stack = Item_t (address_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_CONTRACT, [ty], annot), Item_t (Address_t, rest) -> + let*? Ex_ty t, ctxt = + parse_passable_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy ty + in + let*? contract_ty = contract_t loc t in + let*? res_ty = option_t loc contract_ty in + let*? entrypoint = parse_entrypoint_annot_strict loc annot in + let instr = {apply = (fun k -> IContract (loc, t, entrypoint, k))} in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_VIEW, [name; output_ty], annot), + Item_t (input_ty, Item_t (Address_t, rest)) ) -> + let output_ty_loc = location output_ty in + let*? name, ctxt = parse_view_name ctxt name in + let*? Ex_ty output_ty, ctxt = + parse_view_output_ty ctxt ~stack_depth:0 ~legacy output_ty + in + let*? res_ty = option_t output_ty_loc output_ty in + let*? () = check_var_annot loc annot in + let instr = + { + apply = + (fun k -> + IView + ( loc, + View_signature {name; input_ty; output_ty}, + for_logging_only rest, + k )); + } + in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + | ( Prim (loc, (I_TRANSFER_TOKENS as prim), [], annot), + Item_t (p, Item_t (Mutez_t, Item_t (Contract_t (cp, _), rest))) ) -> + let*? () = Tc_context.check_not_in_view loc ~legacy tc_context prim in + let*? Eq, ctxt = check_item_ty ctxt p cp loc prim 1 4 in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ITransfer_tokens (loc, k))} in + let stack = Item_t (operation_t, rest) in + (typed ctxt loc instr stack : ((a, s) judgement * context) tzresult Lwt.t) + | ( Prim (loc, (I_SET_DELEGATE as prim), [], annot), + Item_t (Option_t (Key_hash_t, _, _), rest) ) -> + let*? () = Tc_context.check_not_in_view loc ~legacy tc_context prim in + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISet_delegate (loc, k))} in + let stack = Item_t (operation_t, rest) in + typed ctxt loc instr stack + | Prim (_, I_CREATE_ACCOUNT, _, _), _ -> + tzfail (Deprecated_instruction I_CREATE_ACCOUNT) + | Prim (loc, I_IMPLICIT_ACCOUNT, [], annot), Item_t (Key_hash_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IImplicit_account (loc, k))} in + let stack = Item_t (contract_unit_t, rest) in + typed ctxt loc instr stack + | ( Prim (loc, (I_CREATE_CONTRACT as prim), [(Seq _ as code)], annot), + Item_t + (Option_t (Key_hash_t, _, _), Item_t (Mutez_t, Item_t (ginit, rest))) ) + -> ( + let*? () = Tc_context.check_not_in_view ~legacy loc tc_context prim in + let*? () = check_two_var_annot loc annot in + (* We typecheck the script to make sure we will originate only well-typed + contracts but then we throw away the typed version, except for the + storage type which is kept for efficiency in the ticket scanner. *) + let canonical_code = Micheline.strip_locations code in + let*? {arg_type; storage_type; code_field; views}, ctxt = + parse_toplevel ctxt canonical_code + in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, ctxt = + record_trace + (Ill_formed_type (Some "parameter", canonical_code, location arg_type)) + (parse_parameter_ty_and_entrypoints + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + arg_type) + in + let*? Ex_ty storage_type, ctxt = + record_trace + (Ill_formed_type + (Some "storage", canonical_code, location storage_type)) + (parse_storage_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy + storage_type) + in + let*? (Ty_ex_c arg_type_full) = pair_t loc arg_type storage_type in + let*? (Ty_ex_c ret_type_full) = + pair_t loc list_operation_t storage_type + in + let* result = + trace + (Ill_typed_contract (canonical_code, [])) + (parse_kdescr + ~unparse_code_rec + (Tc_context.toplevel + ~storage_type + ~param_type:arg_type + ~entrypoints) + ctxt + ~elab_conf + ~stack_depth:(stack_depth + 1) + arg_type_full + ret_type_full + code_field) + in + match result with + | {kbef = Item_t (arg, Bot_t); kaft = Item_t (ret, Bot_t); _}, ctxt -> + let views_result = + parse_views ~unparse_code_rec ctxt ~elab_conf storage_type views + in + let* _typed_views, ctxt = + trace (Ill_typed_contract (canonical_code, [])) views_result + in + let*? storage_eq, ctxt = + let error_details = Informative loc in + Gas_monad.run ctxt + @@ + let open Gas_monad.Syntax in + let* Eq = ty_eq ~error_details arg arg_type_full in + let* Eq = ty_eq ~error_details ret ret_type_full in + ty_eq ~error_details storage_type ginit + in + let*? Eq = storage_eq in + let instr = + { + apply = + (fun k -> + ICreate_contract {loc; storage_type; code = canonical_code; k}); + } + in + let stack = Item_t (operation_t, Item_t (address_t, rest)) in + typed ctxt loc instr stack) + | Prim (loc, I_NOW, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INow (loc, k))} in + let stack = Item_t (timestamp_t, stack) in + typed ctxt loc instr stack + | Prim (loc, I_MIN_BLOCK_TIME, [], _), stack -> + typed + ctxt + loc + {apply = (fun k -> IMin_block_time (loc, k))} + (Item_t (nat_t, stack)) + | Prim (loc, I_AMOUNT, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAmount (loc, k))} in + let stack = Item_t (mutez_t, stack) in + typed ctxt loc instr stack + | Prim (loc, I_CHAIN_ID, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IChainId (loc, k))} in + let stack = Item_t (chain_id_t, stack) in + typed ctxt loc instr stack + | Prim (loc, I_BALANCE, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBalance (loc, k))} in + let stack = Item_t (mutez_t, stack) in + typed ctxt loc instr stack + | Prim (loc, I_LEVEL, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ILevel (loc, k))} in + let stack = Item_t (nat_t, stack) in + typed ctxt loc instr stack + | Prim (loc, I_VOTING_POWER, [], annot), Item_t (Key_hash_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IVoting_power (loc, k))} in + let stack = Item_t (nat_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_TOTAL_VOTING_POWER, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ITotal_voting_power (loc, k))} in + let stack = Item_t (nat_t, stack) in + typed ctxt loc instr stack + | Prim (_, I_STEPS_TO_QUOTA, _, _), _ -> + tzfail (Deprecated_instruction I_STEPS_TO_QUOTA) + | Prim (loc, I_SOURCE, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISource (loc, k))} in + let stack = Item_t (address_t, stack) in + typed ctxt loc instr stack + | Prim (loc, I_SENDER, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISender (loc, k))} in + let stack = Item_t (address_t, stack) in + typed ctxt loc instr stack + | Prim (loc, (I_SELF as prim), [], annot), stack -> ( + let*? entrypoint = parse_entrypoint_annot_lax loc annot in + let open Tc_context in + match tc_context.callsite with + | _ when is_in_lambda tc_context -> + tzfail + (Forbidden_instr_in_context (loc, Script_tc_errors.Lambda, prim)) + (* [Data] is for pushed instructions of lambda type. *) + | Data -> + tzfail + (Forbidden_instr_in_context (loc, Script_tc_errors.Lambda, prim)) + | View -> + tzfail (Forbidden_instr_in_context (loc, Script_tc_errors.View, prim)) + | Toplevel {param_type; entrypoints; storage_type = _} -> + let*? r, ctxt = + Gas_monad.run ctxt + @@ find_entrypoint + ~error_details:(Informative ()) + param_type + entrypoints + entrypoint + in + let*? (Ex_ty_cstr {ty = param_type; _}) = r in + let*? res_ty = contract_t loc param_type in + let instr = + {apply = (fun k -> ISelf (loc, param_type, entrypoint, k))} + in + let stack = Item_t (res_ty, stack) in + typed ctxt loc instr stack) + | Prim (loc, I_SELF_ADDRESS, [], annot), stack -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISelf_address (loc, k))} in + let stack = Item_t (address_t, stack) in + typed ctxt loc instr stack + (* cryptography *) + | Prim (loc, I_HASH_KEY, [], annot), Item_t (Key_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IHash_key (loc, k))} in + let stack = Item_t (key_hash_t, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_CHECK_SIGNATURE, [], annot), + Item_t (Key_t, Item_t (Signature_t, Item_t (Bytes_t, rest))) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ICheck_signature (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_BLAKE2B, [], annot), (Item_t (Bytes_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IBlake2b (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SHA256, [], annot), (Item_t (Bytes_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISha256 (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SHA512, [], annot), (Item_t (Bytes_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISha512 (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_KECCAK, [], annot), (Item_t (Bytes_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IKeccak (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_SHA3, [], annot), (Item_t (Bytes_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> ISha3 (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_ADD, [], annot), + Item_t (Bls12_381_g1_t, (Item_t (Bls12_381_g1_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_bls12_381_g1 (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_ADD, [], annot), + Item_t (Bls12_381_g2_t, (Item_t (Bls12_381_g2_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_bls12_381_g2 (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_ADD, [], annot), + Item_t (Bls12_381_fr_t, (Item_t (Bls12_381_fr_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IAdd_bls12_381_fr (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_g1_t, Item_t (Bls12_381_fr_t, rest)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_g1 (loc, k))} in + let stack = Item_t (Bls12_381_g1_t, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_g2_t, Item_t (Bls12_381_fr_t, rest)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_g2 (loc, k))} in + let stack = Item_t (Bls12_381_g2_t, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_MUL, [], annot), + Item_t (Bls12_381_fr_t, (Item_t (Bls12_381_fr_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_fr (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_MUL, [], annot), + Item_t (Nat_t, (Item_t (Bls12_381_fr_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_fr_z (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_MUL, [], annot), + Item_t (Int_t, (Item_t (Bls12_381_fr_t, _) as stack)) ) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_fr_z (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Bls12_381_fr_t, Item_t (Int_t, rest)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_z_fr (loc, k))} in + let stack = Item_t (Bls12_381_fr_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_MUL, [], annot), Item_t (Bls12_381_fr_t, Item_t (Nat_t, rest)) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IMul_bls12_381_z_fr (loc, k))} in + let stack = Item_t (Bls12_381_fr_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_INT, [], annot), Item_t (Bls12_381_fr_t, rest) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IInt_bls12_381_fr (loc, k))} in + let stack = Item_t (int_t, rest) in + typed ctxt loc instr stack + | Prim (loc, I_NEG, [], annot), (Item_t (Bls12_381_g1_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INeg_bls12_381_g1 (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_NEG, [], annot), (Item_t (Bls12_381_g2_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INeg_bls12_381_g2 (loc, k))} in + typed ctxt loc instr stack + | Prim (loc, I_NEG, [], annot), (Item_t (Bls12_381_fr_t, _) as stack) -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> INeg_bls12_381_fr (loc, k))} in + typed ctxt loc instr stack + | ( Prim (loc, I_PAIRING_CHECK, [], annot), + Item_t (List_t (Pair_t (Bls12_381_g1_t, Bls12_381_g2_t, _, _), _), rest) ) + -> + let*? () = check_var_annot loc annot in + let instr = {apply = (fun k -> IPairing_check_bls12_381 (loc, k))} in + let stack = Item_t (bool_t, rest) in + typed ctxt loc instr stack + (* Tickets *) + | Prim (loc, I_TICKET, [], annot), Item_t (t, Item_t (Nat_t, rest)) -> + let*? () = check_var_annot loc annot in + let*? Eq = check_comparable loc t in + let*? res_ty = ticket_t loc t in + let instr = {apply = (fun k -> ITicket (loc, for_logging_only t, k))} in + let*? res_ty = option_t loc res_ty in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + | Prim (loc, I_TICKET_DEPRECATED, [], annot), Item_t (t, Item_t (Nat_t, rest)) + -> + if legacy then + let*? () = check_var_annot loc annot in + let*? Eq = check_comparable loc t in + let*? res_ty = ticket_t loc t in + let instr = + {apply = (fun k -> ITicket_deprecated (loc, for_logging_only t, k))} + in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + else tzfail (Deprecated_instruction I_TICKET_DEPRECATED) + | ( Prim (loc, I_READ_TICKET, [], annot), + (Item_t (Ticket_t (t, _), _) as full_stack) ) -> + let*? () = check_var_annot loc annot in + let () = check_dupable_comparable_ty t in + let*? result = opened_ticket_type loc t in + let instr = + {apply = (fun k -> IRead_ticket (loc, for_logging_only t, k))} + in + let stack = Item_t (result, full_stack) in + typed ctxt loc instr stack + | ( Prim (loc, I_SPLIT_TICKET, [], annot), + Item_t + ( (Ticket_t (t, _) as ticket_t), + Item_t (Pair_t (Nat_t, Nat_t, _, _), rest) ) ) -> + let*? () = check_var_annot loc annot in + let () = check_dupable_comparable_ty t in + let*? (Ty_ex_c pair_tickets_ty) = pair_t loc ticket_t ticket_t in + let*? res_ty = option_t loc pair_tickets_ty in + let instr = {apply = (fun k -> ISplit_ticket (loc, k))} in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + | ( Prim (loc, I_JOIN_TICKETS, [], annot), + Item_t + ( Pair_t + ( (Ticket_t (contents_ty_a, _) as ty_a), + Ticket_t (contents_ty_b, _), + _, + _ ), + rest ) ) -> + let*? () = check_var_annot loc annot in + let*? eq, ctxt = + Gas_monad.run ctxt + @@ ty_eq ~error_details:(Informative loc) contents_ty_a contents_ty_b + in + let*? Eq = eq in + let*? res_ty = option_t loc ty_a in + let instr = {apply = (fun k -> IJoin_tickets (loc, contents_ty_a, k))} in + let stack = Item_t (res_ty, rest) in + typed ctxt loc instr stack + (* Timelocks *) + | ( Prim (loc, I_OPEN_CHEST, [], _), + Item_t (Chest_key_t, Item_t (Chest_t, Item_t (Nat_t, rest))) ) -> + let instr = {apply = (fun k -> IOpen_chest (loc, k))} in + typed ctxt loc instr (Item_t (option_bytes_t, rest)) + (* Events *) + | Prim (loc, I_EMIT, [], annot), Item_t (data, rest) -> + let*? () = check_packable ~allow_contract:false loc data in + let*? tag = parse_entrypoint_annot_strict loc annot in + let*? unparsed_ty, ctxt = unparse_ty ~loc:() ctxt data in + let*? ctxt = Gas.consume ctxt (Script.strip_locations_cost unparsed_ty) in + let unparsed_ty = Micheline.strip_locations unparsed_ty in + let instr = + {apply = (fun k -> IEmit {loc; tag; ty = data; unparsed_ty; k})} + in + typed ctxt loc instr (Item_t (Operation_t, rest)) + | Prim (loc, I_EMIT, [ty_node], annot), Item_t (data, rest) -> + let*? Ex_ty ty, ctxt = + parse_packable_ty ctxt ~stack_depth:(stack_depth + 1) ~legacy ty_node + in + let*? Eq, ctxt = check_item_ty ctxt ty data loc I_EMIT 1 2 in + let*? tag = parse_entrypoint_annot_strict loc annot in + let*? ctxt = Gas.consume ctxt (Script.strip_locations_cost ty_node) in + let unparsed_ty = Micheline.strip_locations ty_node in + let instr = + {apply = (fun k -> IEmit {loc; tag; ty = data; unparsed_ty; k})} + in + typed ctxt loc instr (Item_t (Operation_t, rest)) + (* Primitive parsing errors *) + | ( Prim + ( loc, + (( I_DUP | I_SWAP | I_SOME | I_UNIT | I_PAIR | I_UNPAIR | I_CAR + | I_CDR | I_CONS | I_CONCAT | I_SLICE | I_MEM | I_UPDATE | I_GET + | I_EXEC | I_FAILWITH | I_SIZE | I_ADD | I_SUB | I_SUB_MUTEZ | I_MUL + | I_EDIV | I_OR | I_AND | I_XOR | I_NOT | I_ABS | I_NEG | I_LSL + | I_LSR | I_COMPARE | I_EQ | I_NEQ | I_LT | I_GT | I_LE | I_GE + | I_TRANSFER_TOKENS | I_SET_DELEGATE | I_NOW | I_MIN_BLOCK_TIME + | I_IMPLICIT_ACCOUNT | I_AMOUNT | I_BALANCE | I_LEVEL + | I_CHECK_SIGNATURE | I_HASH_KEY | I_SOURCE | I_SENDER | I_BLAKE2B + | I_SHA256 | I_SHA512 | I_ADDRESS | I_RENAME | I_PACK | I_ISNAT + | I_INT | I_SELF | I_CHAIN_ID | I_NEVER | I_VOTING_POWER + | I_TOTAL_VOTING_POWER | I_KECCAK | I_SHA3 | I_PAIRING_CHECK + | I_TICKET | I_READ_TICKET | I_SPLIT_TICKET | I_JOIN_TICKETS + | I_OPEN_CHEST ) as name), + (_ :: _ as l), + _ ), + _ ) -> + tzfail (Invalid_arity (loc, name, 0, List.length l)) + | ( Prim + ( loc, + (( I_NONE | I_LEFT | I_RIGHT | I_NIL | I_MAP | I_ITER | I_EMPTY_SET + | I_LOOP | I_LOOP_LEFT | I_CONTRACT | I_CAST | I_UNPACK + | I_CREATE_CONTRACT | I_EMIT ) as name), + (([] | _ :: _ :: _) as l), + _ ), + _ ) -> + tzfail (Invalid_arity (loc, name, 1, List.length l)) + | ( Prim + ( loc, + (( I_PUSH | I_VIEW | I_IF_NONE | I_IF_LEFT | I_IF_CONS | I_EMPTY_MAP + | I_EMPTY_BIG_MAP | I_IF ) as name), + (([] | [_] | _ :: _ :: _ :: _) as l), + _ ), + _ ) -> + tzfail (Invalid_arity (loc, name, 2, List.length l)) + | ( Prim (loc, I_LAMBDA, (([] | [_] | [_; _] | _ :: _ :: _ :: _ :: _) as l), _), + _ ) -> + tzfail (Invalid_arity (loc, I_LAMBDA, 3, List.length l)) + (* Stack errors *) + | ( Prim + ( loc, + (( I_ADD | I_SUB | I_SUB_MUTEZ | I_MUL | I_EDIV | I_AND | I_OR | I_XOR + | I_LSL | I_LSR | I_CONCAT | I_PAIRING_CHECK ) as name), + [], + _ ), + Item_t (ta, Item_t (tb, _)) ) -> + let ta = serialize_ty_for_error ta in + let tb = serialize_ty_for_error tb in + tzfail (Undefined_binop (loc, name, ta, tb)) + | ( Prim + ( loc, + (( I_NEG | I_ABS | I_NOT | I_SIZE | I_EQ | I_NEQ | I_LT | I_GT | I_LE + | I_GE + (* CONCAT is both unary and binary; this case can only be triggered + on a singleton stack *) + | I_CONCAT ) as name), + [], + _ ), + Item_t (t, _) ) -> + let t = serialize_ty_for_error t in + tzfail (Undefined_unop (loc, name, t)) + | Prim (loc, ((I_UPDATE | I_SLICE | I_OPEN_CHEST) as name), [], _), stack -> + let stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, name, 3, stack)) + | Prim (loc, I_CREATE_CONTRACT, _, _), stack -> + let stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, I_CREATE_CONTRACT, 7, stack)) + | Prim (loc, I_TRANSFER_TOKENS, [], _), stack -> + let stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, I_TRANSFER_TOKENS, 4, stack)) + | ( Prim + ( loc, + (( I_DROP | I_DUP | I_CAR | I_CDR | I_UNPAIR | I_SOME | I_BLAKE2B + | I_SHA256 | I_SHA512 | I_DIP | I_IF_NONE | I_LEFT | I_RIGHT + | I_IF_LEFT | I_IF | I_LOOP | I_IF_CONS | I_IMPLICIT_ACCOUNT | I_NEG + | I_ABS | I_INT | I_NOT | I_HASH_KEY | I_EQ | I_NEQ | I_LT | I_GT + | I_LE | I_GE | I_SIZE | I_FAILWITH | I_RENAME | I_PACK | I_ISNAT + | I_ADDRESS | I_SET_DELEGATE | I_CAST | I_MAP | I_ITER | I_LOOP_LEFT + | I_UNPACK | I_CONTRACT | I_NEVER | I_KECCAK | I_SHA3 | I_READ_TICKET + | I_JOIN_TICKETS ) as name), + _, + _ ), + stack ) -> + let stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, name, 1, stack)) + | ( Prim + ( loc, + (( I_SWAP | I_PAIR | I_CONS | I_GET | I_MEM | I_EXEC + | I_CHECK_SIGNATURE | I_ADD | I_SUB | I_SUB_MUTEZ | I_MUL | I_EDIV + | I_AND | I_OR | I_XOR | I_LSL | I_LSR | I_COMPARE | I_PAIRING_CHECK + | I_TICKET | I_SPLIT_TICKET ) as name), + _, + _ ), + stack ) -> + let stack = serialize_stack_for_error ctxt stack in + tzfail (Bad_stack (loc, name, 2, stack)) + (* Generic parsing errors *) + | expr, _ -> + tzfail + @@ unexpected + expr + [Seq_kind] + Instr_namespace + [ + I_ABS; + I_ADD; + I_AMOUNT; + I_AND; + I_BALANCE; + I_BLAKE2B; + I_CAR; + I_CDR; + I_CHECK_SIGNATURE; + I_COMPARE; + I_CONCAT; + I_CONS; + I_CREATE_CONTRACT; + I_DIG; + I_DIP; + I_DROP; + I_DUG; + I_DUP; + I_EDIV; + I_EMPTY_BIG_MAP; + I_EMPTY_MAP; + I_EMPTY_SET; + I_EQ; + I_EXEC; + I_FAILWITH; + I_GE; + I_GET; + I_GET_AND_UPDATE; + I_GT; + I_HASH_KEY; + I_IF; + I_IF_CONS; + I_IF_LEFT; + I_IF_NONE; + I_IMPLICIT_ACCOUNT; + I_INT; + I_ITER; + I_JOIN_TICKETS; + I_KECCAK; + I_LAMBDA; + I_LE; + I_LEFT; + I_LEVEL; + I_LOOP; + I_LSL; + I_LSR; + I_LT; + I_MAP; + I_MEM; + I_MIN_BLOCK_TIME; + I_MUL; + I_NEG; + I_NEQ; + I_NEVER; + I_NIL; + I_NONE; + I_NOT; + I_NOW; + I_OPEN_CHEST; + I_OR; + I_PAIR; + I_PAIRING_CHECK; + I_PUSH; + I_READ_TICKET; + I_RIGHT; + I_SAPLING_EMPTY_STATE; + I_SAPLING_VERIFY_UPDATE; + I_SELF; + I_SELF_ADDRESS; + I_SENDER; + I_SHA256; + I_SHA3; + I_SHA512; + I_SIZE; + I_SOME; + I_SOURCE; + I_SPLIT_TICKET; + I_SUB; + I_SUB_MUTEZ; + I_SWAP; + I_TICKET; + I_TOTAL_VOTING_POWER; + I_TRANSFER_TOKENS; + I_UNIT; + I_UNPAIR; + I_UPDATE; + I_VIEW; + I_VOTING_POWER; + I_XOR; + ] + +and parse_contract_data : + type arg argc. + stack_depth:int -> + context -> + Script.location -> + (arg, argc) ty -> + Destination.t -> + entrypoint:Entrypoint.t -> + (context * arg typed_contract) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~stack_depth ctxt loc arg destination ~entrypoint -> + let error_details = Informative loc in + let* ctxt, res = + parse_contract + ~stack_depth:(stack_depth + 1) + ctxt + ~error_details + loc + arg + destination + ~entrypoint + in + let*? res in + return (ctxt, res) + +(* [parse_contract] is used both to: + - parse contract data by [parse_data] ([parse_contract_data]) + - to execute the [CONTRACT] instruction ([parse_contract_for_script]). + + The return type resembles the [Gas_monad]: + - the outer [tzresult] is for gas exhaustion and internal errors + - the inner [result] is for other legitimate cases of failure. + + The inner [result] is turned into an [option] by [parse_contract_for_script]. + Both [tzresult] are merged by [parse_contract_data]. +*) +and parse_contract : + type arg argc err. + stack_depth:int -> + context -> + error_details:(location, err) error_details -> + Script.location -> + (arg, argc) ty -> + Destination.t -> + entrypoint:Entrypoint.t -> + (context * (arg typed_contract, err) result) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~stack_depth ctxt ~error_details loc arg destination ~entrypoint -> + let error ctxt f_err : context * (_, err) result = + ( ctxt, + Error + (match error_details with + | Fast -> (Inconsistent_types_fast : err) + | Informative loc -> trace_of_error @@ f_err loc) ) + in + let*? ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + match destination with + | Contract contract -> ( + match contract with + | Implicit destination -> + if Entrypoint.is_default entrypoint then + (* An implicit account on the "default" entrypoint always exists and has type unit + or (ticket cty). *) + let typecheck = + let open Gas_monad.Syntax in + let* () = Gas_monad.consume_gas Typecheck_costs.ty_eq_prim in + match arg with + | Unit_t -> + return (Typed_implicit destination : arg typed_contract) + | Ticket_t _ as ticket_ty -> + return (Typed_implicit_with_ticket {ticket_ty; destination}) + | _ -> + Gas_monad.of_result + @@ Error + (match error_details with + | Fast -> (Inconsistent_types_fast : err) + | Informative loc -> + trace_of_error + @@ Unexpected_implicit_account_parameters_type + (loc, serialize_ty_for_error arg)) + in + let*? v, ctxt = Gas_monad.run ctxt typecheck in + return (ctxt, v) + else + (* An implicit account on any other entrypoint is not a valid contract. *) + return @@ error ctxt (fun _loc -> No_such_entrypoint entrypoint) + | Originated contract_hash -> + trace + (Invalid_contract (loc, contract)) + (let* ctxt, code = Contract.get_script_code ctxt contract_hash in + match code with + | None -> + return + (error ctxt (fun loc -> Invalid_contract (loc, contract))) + | Some code -> + let*? code, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + code + in + (* can only fail because of gas *) + let*? {arg_type; _}, ctxt = parse_toplevel ctxt code in + let*? ( Ex_parameter_ty_and_entrypoints + {arg_type = targ; entrypoints}, + ctxt ) = + parse_parameter_ty_and_entrypoints + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy:true + arg_type + in + let*? entrypoint_arg, ctxt = + Gas_monad.run ctxt + @@ find_entrypoint_for_type + ~error_details + ~full:targ + ~expected:arg + entrypoints + entrypoint + in + return + ( ctxt, + let open Result_syntax in + let* entrypoint, arg_ty = entrypoint_arg in + Ok (Typed_originated {arg_ty; contract_hash; entrypoint}) + ))) + | Zk_rollup zk_rollup -> + let+ ctxt = Zk_rollup.assert_exist ctxt zk_rollup in + if Entrypoint.(is_deposit entrypoint) then + match arg with + | Pair_t (Ticket_t (_, _), Bytes_t, _, _) -> + ( ctxt, + Ok + (Typed_zk_rollup {arg_ty = arg; zk_rollup} + : arg typed_contract) ) + | _ -> + error ctxt (fun loc -> + Zk_rollup_bad_deposit_parameter + (loc, serialize_ty_for_error arg)) + else error ctxt (fun _loc -> No_such_entrypoint entrypoint) + | Sc_rollup sc_rollup -> ( + let* parameters_type, ctxt = Sc_rollup.parameters_type ctxt sc_rollup in + match parameters_type with + | None -> + return + (error ctxt (fun _loc -> + Sc_rollup.Errors.Sc_rollup_does_not_exist sc_rollup)) + | Some parameters_type -> + let*? parameters_type, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + parameters_type + in + let*? ( Ex_parameter_ty_and_entrypoints + {arg_type = full; entrypoints}, + ctxt ) = + parse_parameter_ty_and_entrypoints + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy:true + (root parameters_type) + in + let*? entrypoint_arg, ctxt = + Gas_monad.run ctxt + @@ find_entrypoint_for_type + ~error_details + ~full + ~expected:arg + entrypoints + entrypoint + in + return + ( ctxt, + let open Result_syntax in + let* entrypoint, arg_ty = entrypoint_arg in + Ok (Typed_sc_rollup {arg_ty; sc_rollup; entrypoint}) )) + +(* Same as [parse_contract], but does not fail when the contact is missing or + if the expected type doesn't match the actual one. In that case None is + returned and some overapproximation of the typechecking gas is consumed. + This can still fail on gas exhaustion. *) +let parse_contract_for_script : + type arg argc. + context -> + Script.location -> + (arg, argc) ty -> + Destination.t -> + entrypoint:Entrypoint.t -> + (context * arg typed_contract option) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt loc arg destination ~entrypoint -> + let+ ctxt, res = + parse_contract + ~stack_depth:0 + ctxt + ~error_details:Fast + loc + arg + destination + ~entrypoint + in + ( ctxt, + match res with + | Ok res -> Some res + | Error Inconsistent_types_fast -> None ) + +let view_size view = + let open Script_typed_ir_size in + node_size view.view_code ++ node_size view.input_ty + ++ node_size view.output_ty + +let code_size ctxt code views = + let open Result_syntax in + let open Script_typed_ir_size in + let views_size = Script_map.fold (fun _ v s -> view_size v ++ s) views zero in + (* The size of the storage_type and the arg_type is counted by + [lambda_size]. *) + let ir_size = lambda_size code in + let nodes, code_size = views_size ++ ir_size in + (* We consume gas after the fact in order to not have to instrument + [node_size] (for efficiency). + This is safe, as we already pay gas proportional to [views_size] and + [ir_size] during their typechecking. *) + let+ ctxt = Gas.consume ctxt (Script_typed_ir_size_costs.nodes_cost ~nodes) in + (code_size, ctxt) + +let parse_code : + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + context -> + code:lazy_expr -> + (ex_code * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec ~elab_conf ctxt ~code -> + let*? code, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + code + in + let legacy = elab_conf.legacy in + let* ctxt, code = Global_constants_storage.expand ctxt code in + let*? {arg_type; storage_type; code_field; views}, ctxt = + parse_toplevel ctxt code + in + let arg_type_loc = location arg_type in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, ctxt = + record_trace + (Ill_formed_type (Some "parameter", code, arg_type_loc)) + (parse_parameter_ty_and_entrypoints + ctxt + ~stack_depth:0 + ~legacy + arg_type) + in + let storage_type_loc = location storage_type in + let*? Ex_ty storage_type, ctxt = + record_trace + (Ill_formed_type (Some "storage", code, storage_type_loc)) + (parse_storage_ty ctxt ~stack_depth:0 ~legacy storage_type) + in + let*? (Ty_ex_c arg_type_full) = + pair_t storage_type_loc arg_type storage_type + in + let*? (Ty_ex_c ret_type_full) = + pair_t storage_type_loc list_operation_t storage_type + in + let* kdescr, ctxt = + trace + (Ill_typed_contract (code, [])) + (parse_kdescr + ~unparse_code_rec + Tc_context.(toplevel ~storage_type ~param_type:arg_type ~entrypoints) + ~elab_conf + ctxt + ~stack_depth:0 + arg_type_full + ret_type_full + code_field) + in + let code = Lam (kdescr, code_field) in + let*? code_size, ctxt = code_size ctxt code views in + return + ( Ex_code + (Code {code; arg_type; storage_type; views; entrypoints; code_size}), + ctxt ) + +let parse_storage : + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + context -> + allow_forged_tickets:bool -> + allow_forged_lazy_storage_id:bool -> + ('storage, _) ty -> + storage:lazy_expr -> + ('storage * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec + ~elab_conf + ctxt + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + storage_type + ~storage -> + let*? storage, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + storage + in + trace_eval + (fun () -> + let storage_type = serialize_ty_for_error storage_type in + Ill_typed_data (None, storage, storage_type)) + (parse_data + ~unparse_code_rec + ~elab_conf + ~stack_depth:0 + ctxt + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + storage_type + (root storage)) + +let parse_script : + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + elab_conf:elab_conf -> + context -> + allow_forged_tickets_in_storage:bool -> + allow_forged_lazy_storage_id_in_storage:bool -> + Script.t -> + (ex_script * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec + ~elab_conf + ctxt + ~allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id_in_storage + {code; storage} -> + let* ( Ex_code + (Code + {code; arg_type; storage_type; views; entrypoints; code_size}), + ctxt ) = + parse_code ~unparse_code_rec ~elab_conf ctxt ~code + in + let+ storage, ctxt = + parse_storage + ~unparse_code_rec + ~elab_conf + ctxt + ~allow_forged_tickets:allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id:allow_forged_lazy_storage_id_in_storage + storage_type + ~storage + in + ( Ex_script + (Script + { + code_size; + code; + arg_type; + storage; + storage_type; + views; + entrypoints; + }), + ctxt ) + +type typechecked_code_internal = + | Typechecked_code_internal : { + toplevel : toplevel; + arg_type : ('arg, _) ty; + storage_type : ('storage, _) ty; + entrypoints : 'arg entrypoints; + typed_views : 'storage typed_view_map; + type_map : type_map; + } + -> typechecked_code_internal + +let typecheck_code : + unparse_code_rec:Script_ir_unparser.unparse_code_rec -> + legacy:bool -> + show_types:bool -> + context -> + Script.expr -> + (typechecked_code_internal * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~unparse_code_rec ~legacy ~show_types ctxt code -> + (* Constants need to be expanded or [parse_toplevel] may fail. *) + let* ctxt, code = Global_constants_storage.expand ctxt code in + let*? toplevel, ctxt = parse_toplevel ctxt code in + let {arg_type; storage_type; code_field; views} = toplevel in + let type_map = ref [] in + let arg_type_loc = location arg_type in + let*? Ex_parameter_ty_and_entrypoints {arg_type; entrypoints}, ctxt = + record_trace + (Ill_formed_type (Some "parameter", code, arg_type_loc)) + (parse_parameter_ty_and_entrypoints + ctxt + ~stack_depth:0 + ~legacy + arg_type) + in + let storage_type_loc = location storage_type in + let*? ex_storage_type, ctxt = + record_trace + (Ill_formed_type (Some "storage", code, storage_type_loc)) + (parse_storage_ty ctxt ~stack_depth:0 ~legacy storage_type) + in + let (Ex_ty storage_type) = ex_storage_type in + let*? (Ty_ex_c arg_type_full) = + pair_t storage_type_loc arg_type storage_type + in + let*? (Ty_ex_c ret_type_full) = + pair_t storage_type_loc list_operation_t storage_type + in + let type_logger loc ~stack_ty_before ~stack_ty_after = + type_map := (loc, (stack_ty_before, stack_ty_after)) :: !type_map + in + let type_logger = if show_types then Some type_logger else None in + let elab_conf = Script_ir_translator_config.make ~legacy ?type_logger () in + let result = + parse_kdescr + ~unparse_code_rec + (Tc_context.toplevel ~storage_type ~param_type:arg_type ~entrypoints) + ctxt + ~elab_conf + ~stack_depth:0 + arg_type_full + ret_type_full + code_field + in + let* (_ : (_, _, _, _) kdescr), ctxt = + trace (Ill_typed_contract (code, !type_map)) result + in + let views_result = + parse_views ~unparse_code_rec ctxt ~elab_conf storage_type views + in + let+ typed_views, ctxt = + trace (Ill_typed_contract (code, !type_map)) views_result + in + ( Typechecked_code_internal + { + toplevel; + arg_type; + storage_type; + entrypoints; + typed_views; + type_map = !type_map; + }, + ctxt ) + +(* Uncarbonated because used only in RPCs *) +let list_entrypoints_uncarbonated (type full fullc) (full : (full, fullc) ty) + (entrypoints : full entrypoints) = + let merge path (type t tc) (ty : (t, tc) ty) + (entrypoints : t entrypoints_node) reachable ((unreachables, all) as acc) + = + match entrypoints.at_node with + | None -> + ( (if reachable then acc + else + match ty with + | Or_t _ -> acc + | _ -> (List.rev path :: unreachables, all)), + reachable ) + | Some {name; original_type_expr} -> + ( (if Entrypoint.Map.mem name all then + (List.rev path :: unreachables, all) + else + ( unreachables, + Entrypoint.Map.add name (Ex_ty ty, original_type_expr) all )), + true ) + in + let rec fold_tree : + type t tc. + (t, tc) ty -> + t entrypoints_node -> + prim list -> + bool -> + prim list list * (ex_ty * Script.node) Entrypoint.Map.t -> + prim list list * (ex_ty * Script.node) Entrypoint.Map.t = + fun t entrypoints path reachable acc -> + match (t, entrypoints) with + | Or_t (tl, tr, _, _), {nested = Entrypoints_Or {left; right}; _} -> + let acc, l_reachable = merge (D_Left :: path) tl left reachable acc in + let acc, r_reachable = merge (D_Right :: path) tr right reachable acc in + let acc = fold_tree tl left (D_Left :: path) l_reachable acc in + fold_tree tr right (D_Right :: path) r_reachable acc + | _ -> acc + in + let init, reachable = + match entrypoints.root.at_node with + | None -> (Entrypoint.Map.empty, false) + | Some {name; original_type_expr} -> + (Entrypoint.Map.singleton name (Ex_ty full, original_type_expr), true) + in + fold_tree full entrypoints.root [] reachable ([], init) + +include Data_unparser (struct + let opened_ticket_type = opened_ticket_type + + let parse_packable_ty = parse_packable_ty + + let parse_data = parse_data +end) + +let unparse_code_rec : unparse_code_rec = + let open Lwt_result_syntax in + fun ctxt ~stack_depth mode node -> + let* code, ctxt = unparse_code ctxt ~stack_depth mode node in + return (Micheline.root code, ctxt) + +let parse_and_unparse_script_unaccounted ctxt ~legacy + ~allow_forged_tickets_in_storage ~allow_forged_lazy_storage_id_in_storage + mode ~normalize_types {code; storage} = + let open Lwt_result_syntax in + let*? code, ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + code + in + let* ( Typechecked_code_internal + { + toplevel = + { + code_field; + arg_type = original_arg_type_expr; + storage_type = original_storage_type_expr; + views; + }; + arg_type; + storage_type; + entrypoints; + typed_views; + type_map = _; + }, + ctxt ) = + typecheck_code ~unparse_code_rec ~legacy ~show_types:false ctxt code + in + let* storage, ctxt = + parse_storage + ~unparse_code_rec + ~elab_conf:(Script_ir_translator_config.make ~legacy ()) + ctxt + ~allow_forged_tickets:allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id:allow_forged_lazy_storage_id_in_storage + storage_type + ~storage + in + let* code, ctxt = unparse_code ctxt ~stack_depth:0 mode code_field in + let* storage, ctxt = + unparse_data ctxt ~stack_depth:0 mode storage_type storage + in + let loc = Micheline.dummy_location in + let* arg_type, storage_type, views, ctxt = + if normalize_types then + let*? arg_type, ctxt = + unparse_parameter_ty ~loc ctxt arg_type ~entrypoints + in + let*? storage_type, ctxt = unparse_ty ~loc ctxt storage_type in + let+ views, ctxt = + Script_map.map_es_in_context + (fun ctxt + _name + (Typed_view + {input_ty; output_ty; kinstr = _; original_code_expr}) -> + let*? input_ty, ctxt = unparse_ty ~loc ctxt input_ty in + let*? output_ty, ctxt = unparse_ty ~loc ctxt output_ty in + return ({input_ty; output_ty; view_code = original_code_expr}, ctxt)) + ctxt + typed_views + in + (arg_type, storage_type, views, ctxt) + else return (original_arg_type_expr, original_storage_type_expr, views, ctxt) + in + let* views, ctxt = + Script_map.map_es_in_context + (fun ctxt _name {input_ty; output_ty; view_code} -> + let+ view_code, ctxt = + unparse_code ctxt ~stack_depth:0 mode view_code + in + let view_code = Micheline.root view_code in + ({input_ty; output_ty; view_code}, ctxt)) + ctxt + views + in + let open Micheline in + let unparse_view_unaccounted name {input_ty; output_ty; view_code} views = + Prim + ( loc, + K_view, + [ + String (loc, Script_string.to_string name); + input_ty; + output_ty; + view_code; + ], + [] ) + :: views + in + let views = Script_map.fold unparse_view_unaccounted views [] |> List.rev in + let code = + Seq + ( loc, + [ + Prim (loc, K_parameter, [arg_type], []); + Prim (loc, K_storage, [storage_type], []); + Prim (loc, K_code, [Micheline.root code], []); + ] + @ views ) + in + return + ( {code = lazy_expr (strip_locations code); storage = lazy_expr storage}, + ctxt ) + +let pack_data_with_mode ctxt ty data ~mode = + let open Lwt_result_syntax in + let+ unparsed, ctxt = unparse_data ~stack_depth:0 ctxt mode ty data in + pack_node unparsed ctxt + +let hash_data ctxt ty data = + let open Lwt_result_syntax in + let* bytes, ctxt = pack_data_with_mode ctxt ty data ~mode:Optimized_legacy in + Lwt.return @@ hash_bytes ctxt bytes + +let pack_data ctxt ty data = + pack_data_with_mode ctxt ty data ~mode:Optimized_legacy + +(* ---------------- Lazy storage---------------------------------------------*) + +type lazy_storage_ids = Lazy_storage.IdSet.t + +let no_lazy_storage_id = Lazy_storage.IdSet.empty + +let diff_of_big_map ctxt mode ~temporary ~ids_to_copy + (Big_map {id; key_type; value_type; diff}) = + let open Lwt_result_syntax in + let* ctxt, init, id = + match id with + | Some id -> + if Lazy_storage.IdSet.mem Big_map id ids_to_copy then + let+ ctxt, duplicate = Big_map.fresh ~temporary ctxt in + (ctxt, Lazy_storage.Copy {src = id}, duplicate) + else + (* The first occurrence encountered of a big_map reuses the + ID. This way, the payer is only charged for the diff. + For this to work, this diff has to be put at the end of + the global diff, otherwise the duplicates will use the + updated version as a base. This is true because we add + this diff first in the accumulator of + `extract_lazy_storage_updates`, and this accumulator is not + reversed. *) + return (ctxt, Lazy_storage.Existing, id) + | None -> + let* ctxt, id = Big_map.fresh ~temporary ctxt in + let kt = unparse_comparable_ty_uncarbonated ~loc:() key_type in + let*? ctxt = Gas.consume ctxt (Script.strip_locations_cost kt) in + let*? kv, ctxt = unparse_ty ~loc:() ctxt value_type in + let*? ctxt = Gas.consume ctxt (Script.strip_locations_cost kv) in + let key_type = Micheline.strip_locations kt in + let value_type = Micheline.strip_locations kv in + return (ctxt, Lazy_storage.(Alloc Big_map.{key_type; value_type}), id) + in + let pairs = + Big_map_overlay.fold + (fun key_hash (key, value) acc -> (key_hash, key, value) :: acc) + diff.map + [] + in + let+ updates, ctxt = + List.fold_left_es + (fun (acc, ctxt) (key_hash, key, value) -> + let*? ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + let* key, ctxt = unparse_comparable_data ctxt mode key_type key in + let+ value, ctxt = + match value with + | None -> return (None, ctxt) + | Some x -> + let+ node, ctxt = + unparse_data ~stack_depth:0 ctxt mode value_type x + in + (Some node, ctxt) + in + let diff_item = Big_map.{key; key_hash; value} in + (diff_item :: acc, ctxt)) + ([], ctxt) + (List.rev pairs) + in + (Lazy_storage.Update {init; updates}, id, ctxt) + +let diff_of_sapling_state ctxt ~temporary ~ids_to_copy + ({id; diff; memo_size} : Sapling.state) = + let open Lwt_result_syntax in + let+ ctxt, init, id = + match id with + | Some id -> + if Lazy_storage.IdSet.mem Sapling_state id ids_to_copy then + let+ ctxt, duplicate = Sapling.fresh ~temporary ctxt in + (ctxt, Lazy_storage.Copy {src = id}, duplicate) + else return (ctxt, Lazy_storage.Existing, id) + | None -> + let+ ctxt, id = Sapling.fresh ~temporary ctxt in + (ctxt, Lazy_storage.Alloc Sapling.{memo_size}, id) + in + (Lazy_storage.Update {init; updates = diff}, id, ctxt) + +(** + Witness flag for whether a type can be populated by a value containing a + lazy storage. + [False_f] must be used only when a value of the type cannot contain a lazy + storage. + + This flag is built in [has_lazy_storage] and used only in + [extract_lazy_storage_updates] and [collect_lazy_storage]. + + This flag is necessary to avoid these two functions to have a quadratic + complexity in the size of the type. + + Add new lazy storage kinds here. + + Please keep the usage of this GADT local. + *) + +type 'ty has_lazy_storage = + | Big_map_f : ('a, 'b) big_map has_lazy_storage + | Sapling_state_f : Sapling.state has_lazy_storage + | False_f : _ has_lazy_storage + | Pair_f : + 'a has_lazy_storage * 'b has_lazy_storage + -> ('a, 'b) pair has_lazy_storage + | Or_f : + 'a has_lazy_storage * 'b has_lazy_storage + -> ('a, 'b) or_ has_lazy_storage + | Option_f : 'a has_lazy_storage -> 'a option has_lazy_storage + | List_f : 'a has_lazy_storage -> 'a Script_list.t has_lazy_storage + | Map_f : 'v has_lazy_storage -> (_, 'v) map has_lazy_storage + +(** + This function is called only on storage and parameter types of contracts, + once per typechecked contract. It has a complexity linear in the size of + the types, which happen to be literally written types, so the gas for them + has already been paid. + *) +let rec has_lazy_storage : type t tc. (t, tc) ty -> t has_lazy_storage = + fun ty -> + let aux1 cons t = + match has_lazy_storage t with False_f -> False_f | h -> cons h + in + let aux2 cons t1 t2 = + match (has_lazy_storage t1, has_lazy_storage t2) with + | False_f, False_f -> False_f + | h1, h2 -> cons h1 h2 + in + match ty with + | Big_map_t (_, _, _) -> Big_map_f + | Sapling_state_t _ -> Sapling_state_f + | Unit_t -> False_f + | Int_t -> False_f + | Nat_t -> False_f + | Signature_t -> False_f + | String_t -> False_f + | Bytes_t -> False_f + | Mutez_t -> False_f + | Key_hash_t -> False_f + | Key_t -> False_f + | Timestamp_t -> False_f + | Address_t -> False_f + | Bool_t -> False_f + | Lambda_t (_, _, _) -> False_f + | Set_t (_, _) -> False_f + | Contract_t (_, _) -> False_f + | Operation_t -> False_f + | Chain_id_t -> False_f + | Never_t -> False_f + | Bls12_381_g1_t -> False_f + | Bls12_381_g2_t -> False_f + | Bls12_381_fr_t -> False_f + | Sapling_transaction_t _ -> False_f + | Sapling_transaction_deprecated_t _ -> False_f + | Ticket_t _ -> False_f + | Chest_key_t -> False_f + | Chest_t -> False_f + | Pair_t (l, r, _, _) -> aux2 (fun l r -> Pair_f (l, r)) l r + | Or_t (l, r, _, _) -> aux2 (fun l r -> Or_f (l, r)) l r + | Option_t (t, _, _) -> aux1 (fun h -> Option_f h) t + | List_t (t, _) -> aux1 (fun h -> List_f h) t + | Map_t (_, t, _) -> aux1 (fun h -> Map_f h) t + +(** + Transforms a value potentially containing lazy storage in an intermediary + state to a value containing lazy storage only represented by identifiers. + + Returns the updated value, the updated set of ids to copy, and the lazy + storage diff to show on the receipt and apply on the storage. + + *) +let extract_lazy_storage_updates ctxt mode ~temporary ids_to_copy acc ty x = + let rec aux : + type a ac. + context -> + unparsing_mode -> + temporary:bool -> + Lazy_storage.IdSet.t -> + Lazy_storage.diffs -> + (a, ac) ty -> + a -> + has_lazy_storage:a has_lazy_storage -> + (context * a * Lazy_storage.IdSet.t * Lazy_storage.diffs) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage -> + let*? ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + match (has_lazy_storage, ty, x) with + | False_f, _, _ -> return (ctxt, x, ids_to_copy, acc) + | Big_map_f, Big_map_t (_, _, _), map -> + let+ diff, id, ctxt = + diff_of_big_map ctxt mode ~temporary ~ids_to_copy map + in + let map = + let (Big_map map) = map in + Big_map + { + map with + diff = {map = Big_map_overlay.empty; size = 0}; + id = Some id; + } + in + let diff = Lazy_storage.make Big_map id diff in + let ids_to_copy = Lazy_storage.IdSet.add Big_map id ids_to_copy in + (ctxt, map, ids_to_copy, diff :: acc) + | Sapling_state_f, Sapling_state_t _, sapling_state -> + let+ diff, id, ctxt = + diff_of_sapling_state ctxt ~temporary ~ids_to_copy sapling_state + in + let sapling_state = + Sapling.empty_state ~id ~memo_size:sapling_state.memo_size () + in + let diff = Lazy_storage.make Sapling_state id diff in + let ids_to_copy = + Lazy_storage.IdSet.add Sapling_state id ids_to_copy + in + (ctxt, sapling_state, ids_to_copy, diff :: acc) + | Pair_f (hl, hr), Pair_t (tyl, tyr, _, _), (xl, xr) -> + let* ctxt, xl, ids_to_copy, acc = + aux ctxt mode ~temporary ids_to_copy acc tyl xl ~has_lazy_storage:hl + in + let+ ctxt, xr, ids_to_copy, acc = + aux ctxt mode ~temporary ids_to_copy acc tyr xr ~has_lazy_storage:hr + in + (ctxt, (xl, xr), ids_to_copy, acc) + | Or_f (has_lazy_storage, _), Or_t (ty, _, _, _), L x -> + let+ ctxt, x, ids_to_copy, acc = + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + in + (ctxt, L x, ids_to_copy, acc) + | Or_f (_, has_lazy_storage), Or_t (_, ty, _, _), R x -> + let+ ctxt, x, ids_to_copy, acc = + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + in + (ctxt, R x, ids_to_copy, acc) + | Option_f has_lazy_storage, Option_t (ty, _, _), Some x -> + let+ ctxt, x, ids_to_copy, acc = + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + in + (ctxt, Some x, ids_to_copy, acc) + | List_f has_lazy_storage, List_t (ty, _), l -> + let+ ctxt, l, ids_to_copy, acc = + List.fold_left_es + (fun (ctxt, l, ids_to_copy, acc) x -> + let+ ctxt, x, ids_to_copy, acc = + aux + ctxt + mode + ~temporary + ids_to_copy + acc + ty + x + ~has_lazy_storage + in + (ctxt, Script_list.cons x l, ids_to_copy, acc)) + (ctxt, Script_list.empty, ids_to_copy, acc) + l.elements + in + let reversed = Script_list.rev l in + (ctxt, reversed, ids_to_copy, acc) + | Map_f has_lazy_storage, Map_t (_, ty, _), map -> + let (module M) = Script_map.get_module map in + let bindings m = M.OPS.fold (fun k v bs -> (k, v) :: bs) m [] in + let+ ctxt, m, ids_to_copy, acc = + List.fold_left_es + (fun (ctxt, m, ids_to_copy, acc) (k, x) -> + let+ ctxt, x, ids_to_copy, acc = + aux + ctxt + mode + ~temporary + ids_to_copy + acc + ty + x + ~has_lazy_storage + in + (ctxt, M.OPS.add k x m, ids_to_copy, acc)) + (ctxt, M.OPS.empty, ids_to_copy, acc) + (bindings M.boxed) + in + let module M = struct + module OPS = M.OPS + + type key = M.key + + type value = M.value + + let boxed = m + + let size = M.size + end in + ( ctxt, + Script_map.make + (module M : Boxed_map + with type key = M.key + and type value = M.value), + ids_to_copy, + acc ) + | _, Option_t (_, _, _), None -> return (ctxt, None, ids_to_copy, acc) + in + let has_lazy_storage = has_lazy_storage ty in + aux ctxt mode ~temporary ids_to_copy acc ty x ~has_lazy_storage + +(** We namespace an error type for [fold_lazy_storage]. The error case is only + available when the ['error] parameter is equal to unit. *) +module Fold_lazy_storage = struct + type ('acc, 'error) result = + | Ok : 'acc -> ('acc, 'error) result + | Error : ('acc, unit) result +end + +(** Prematurely abort if [f] generates an error. Use this function without the + [unit] type for [error] if you are in a case where errors are impossible. + *) +let rec fold_lazy_storage : + type a ac error. + f:('acc, error) Fold_lazy_storage.result Lazy_storage.IdSet.fold_f -> + init:'acc -> + context -> + (a, ac) ty -> + a -> + has_lazy_storage:a has_lazy_storage -> + (('acc, error) Fold_lazy_storage.result * context) tzresult = + let open Result_syntax in + fun ~f ~init ctxt ty x ~has_lazy_storage -> + let* ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + match (has_lazy_storage, ty, x) with + | Big_map_f, Big_map_t (_, _, _), Big_map {id = Some id; _} -> + let* ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + return (f.f Big_map id (Fold_lazy_storage.Ok init), ctxt) + | Sapling_state_f, Sapling_state_t _, {id = Some id; _} -> + let* ctxt = Gas.consume ctxt Typecheck_costs.parse_instr_cycle in + return (f.f Sapling_state id (Fold_lazy_storage.Ok init), ctxt) + | False_f, _, _ -> return (Fold_lazy_storage.Ok init, ctxt) + | Big_map_f, Big_map_t (_, _, _), Big_map {id = None; _} -> + return (Fold_lazy_storage.Ok init, ctxt) + | Sapling_state_f, Sapling_state_t _, {id = None; _} -> + return (Fold_lazy_storage.Ok init, ctxt) + | Pair_f (hl, hr), Pair_t (tyl, tyr, _, _), (xl, xr) -> ( + let* init, ctxt = + fold_lazy_storage ~f ~init ctxt tyl xl ~has_lazy_storage:hl + in + match init with + | Fold_lazy_storage.Ok init -> + fold_lazy_storage ~f ~init ctxt tyr xr ~has_lazy_storage:hr + | Fold_lazy_storage.Error -> return (init, ctxt)) + | Or_f (has_lazy_storage, _), Or_t (ty, _, _, _), L x -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | Or_f (_, has_lazy_storage), Or_t (_, ty, _, _), R x -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | _, Option_t (_, _, _), None -> return (Fold_lazy_storage.Ok init, ctxt) + | Option_f has_lazy_storage, Option_t (ty, _, _), Some x -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | List_f has_lazy_storage, List_t (ty, _), l -> + List.fold_left_e + (fun ((init, ctxt) : ('acc, error) Fold_lazy_storage.result * context) + x -> + match init with + | Fold_lazy_storage.Ok init -> + fold_lazy_storage ~f ~init ctxt ty x ~has_lazy_storage + | Fold_lazy_storage.Error -> return (init, ctxt)) + (Fold_lazy_storage.Ok init, ctxt) + l.elements + | Map_f has_lazy_storage, Map_t (_, ty, _), m -> + Script_map.fold + (fun _ + v + (acc : + (('acc, error) Fold_lazy_storage.result * context) tzresult) -> + let* init, ctxt = acc in + match init with + | Fold_lazy_storage.Ok init -> + fold_lazy_storage ~f ~init ctxt ty v ~has_lazy_storage + | Fold_lazy_storage.Error -> return (init, ctxt)) + m + (return (Fold_lazy_storage.Ok init, ctxt)) + +let collect_lazy_storage ctxt ty x = + let open Result_syntax in + let has_lazy_storage = has_lazy_storage ty in + let f kind id (acc : (_, never) Fold_lazy_storage.result) = + let acc = match acc with Fold_lazy_storage.Ok acc -> acc in + Fold_lazy_storage.Ok (Lazy_storage.IdSet.add kind id acc) + in + let* ids, ctxt = + fold_lazy_storage + ~f:{f} + ~init:no_lazy_storage_id + ctxt + ty + x + ~has_lazy_storage + in + match ids with Fold_lazy_storage.Ok ids -> return (ids, ctxt) + +let extract_lazy_storage_diff ctxt mode ~temporary ~to_duplicate ~to_update ty v + = + (* + Basically [to_duplicate] are ids from the argument and [to_update] are ids + from the storage before execution (i.e. it is safe to reuse them since they + will be owned by the same contract). + *) + let open Lwt_result_syntax in + let to_duplicate = Lazy_storage.IdSet.diff to_duplicate to_update in + let+ ctxt, v, alive, diffs = + extract_lazy_storage_updates ctxt mode ~temporary to_duplicate [] ty v + in + let diffs = + if temporary then diffs + else + let dead = Lazy_storage.IdSet.diff to_update alive in + Lazy_storage.IdSet.fold_all + {f = (fun kind id acc -> Lazy_storage.make kind id Remove :: acc)} + dead + diffs + in + match diffs with + | [] -> (v, None, ctxt) + | diffs -> (v, Some diffs (* do not reverse *), ctxt) + +let list_of_big_map_ids ids = + Lazy_storage.IdSet.fold Big_map (fun id acc -> id :: acc) ids [] + +let parse_data ~elab_conf ctxt ~allow_forged_tickets + ~allow_forged_lazy_storage_id ty t = + parse_data + ~unparse_code_rec + ~elab_conf + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + ~stack_depth:0 + ctxt + ty + t + +let parse_view ~elab_conf ctxt ty view = + parse_view ~unparse_code_rec ~elab_conf ctxt ty view + +let parse_views ~elab_conf ctxt ty views = + parse_views ~unparse_code_rec ~elab_conf ctxt ty views + +let parse_code ~elab_conf ctxt ~code = + parse_code ~unparse_code_rec ~elab_conf ctxt ~code + +let parse_storage ~elab_conf ctxt ~allow_forged_tickets + ~allow_forged_lazy_storage_id ty ~storage = + parse_storage + ~unparse_code_rec + ~elab_conf + ctxt + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + ty + ~storage + +let parse_script ~elab_conf ctxt ~allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id_in_storage script = + parse_script + ~unparse_code_rec + ~elab_conf + ctxt + ~allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id_in_storage + script + +let parse_comparable_data ?type_logger ctxt ty t = + parse_data + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ?type_logger ()) + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ctxt + ty + t + +let parse_instr : + type a s. + elab_conf:elab_conf -> + tc_context -> + context -> + Script.node -> + (a, s) stack_ty -> + ((a, s) judgement * context) tzresult Lwt.t = + fun ~elab_conf tc_context ctxt script_instr stack_ty -> + parse_instr + ~unparse_code_rec + ~elab_conf + ~stack_depth:0 + tc_context + ctxt + script_instr + stack_ty + +let unparse_data = unparse_data ~stack_depth:0 + +let unparse_code ctxt mode code = + let open Lwt_result_syntax in + (* Constants need to be expanded or [unparse_code] may fail. *) + let* ctxt, code = + Global_constants_storage.expand ctxt (strip_locations code) + in + unparse_code ~stack_depth:0 ctxt mode (root code) + +let parse_contract_data context loc arg_ty contract ~entrypoint = + parse_contract_data ~stack_depth:0 context loc arg_ty contract ~entrypoint + +let parse_toplevel ctxt toplevel = + let open Lwt_result_syntax in + let* ctxt, toplevel = Global_constants_storage.expand ctxt toplevel in + Lwt.return @@ parse_toplevel ctxt toplevel + +let parse_comparable_ty = parse_comparable_ty ~stack_depth:0 + +let parse_big_map_value_ty = parse_big_map_value_ty ~stack_depth:0 + +let parse_packable_ty = parse_packable_ty ~stack_depth:0 + +let parse_passable_ty = parse_passable_ty ~stack_depth:0 + +let parse_any_ty = parse_any_ty ~stack_depth:0 + +let parse_ty = parse_ty ~stack_depth:0 ~ret:Don't_parse_entrypoints + +let parse_parameter_ty_and_entrypoints = + parse_parameter_ty_and_entrypoints ~stack_depth:0 + +let get_single_sapling_state ctxt ty x = + let open Result_syntax in + let has_lazy_storage = has_lazy_storage ty in + let f (type i a u) (kind : (i, a, u) Lazy_storage.Kind.t) (id : i) + single_id_opt : (Sapling.Id.t option, unit) Fold_lazy_storage.result = + match kind with + | Lazy_storage.Kind.Sapling_state -> ( + match single_id_opt with + | Fold_lazy_storage.Ok None -> Fold_lazy_storage.Ok (Some id) + | Fold_lazy_storage.Ok (Some _) -> + Fold_lazy_storage.Error (* more than one *) + | Fold_lazy_storage.Error -> single_id_opt) + | _ -> single_id_opt + in + let* id, ctxt = + fold_lazy_storage ~f:{f} ~init:None ctxt ty x ~has_lazy_storage + in + match id with + | Fold_lazy_storage.Ok (Some id) -> return (Some id, ctxt) + | Fold_lazy_storage.Ok None | Fold_lazy_storage.Error -> return (None, ctxt) + +(* + + {!Script_cache} needs a measure of the script size in memory. + Determining this size is not easy in OCaml because of sharing. + + Indeed, many values present in the script share the same memory + area. This is especially true for types and stack types: they are + heavily shared in every typed IR internal representation. As a + consequence, computing the size of the typed IR without taking + sharing into account leads to a size which is sometimes two order + of magnitude bigger than the actual size. + + We could track down this sharing. Unfortunately, sharing is not + part of OCaml semantics: for this reason, a compiler can optimize + memory representation by adding more sharing. If two nodes use + different optimization flags or compilers, such a precise + computation of the memory footprint of scripts would lead to two + distinct sizes. As these sizes occur in the blockchain context, + this situation would lead to a fork. + + For this reason, we introduce a *size model* for the script size. + This model provides an overapproximation of the actual size in + memory. The risk is to be too far from the actual size: the cache + would then be wrongly marked as full. This situation would make the + cache less useful but should present no security risk . + + *) +let script_size + (Ex_script + (Script + { + code_size; + code = _; + arg_type = _; + storage; + storage_type; + entrypoints = _; + views = _; + })) = + let nodes, storage_size = + Script_typed_ir_size.value_size storage_type storage + in + let cost = Script_typed_ir_size_costs.nodes_cost ~nodes in + (Saturation_repr.(add code_size storage_size |> to_int), cost) + +let typecheck_code ~legacy ~show_types ctxt code = + let open Lwt_result_syntax in + let+ Typechecked_code_internal {type_map; _}, ctxt = + typecheck_code ~unparse_code_rec ~legacy ~show_types ctxt code + in + (type_map, ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_translator.mli b/src/proto_020_PsParisC/lib_protocol/script_ir_translator.mli new file mode 100644 index 000000000000..ebe241b20354 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_translator.mli @@ -0,0 +1,468 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Overview: + + This mli is organized into roughly three parts: + + 1. A set of new types prefixed with "ex_" + Michelson is encoded in a GADT that preserves certain properties about its + type system. If you haven't read about GADT's, check out the relevant section + in the Tezos docs: + https://tezos.gitlab.io/developer/gadt.html#generalized-algebraic-data-types-gadts + + The idea is that type representing a Michelson type, ['a ty], is parameterized + by a type 'a. But that 'a can't be just _any_ type; it must be valid according + to the definition of ['a ty]. Thus, if I give you a value of type ['a ty], + all you know is that "there exists some 'a such that 'a ty exists". You must be + careful not to accidentally quantify 'a universally, that is "for all 'a, + 'a ty exists", otherwise you'll get an annoying error about 'a trying to escape + it's scope. We do this by hiding 'a in an existential type. This is what + ex_comparable_ty, ex_ty, ex_stack_ty, etc. do. + + 2. A set of functions dealing with high-level Michelson types: + This module also provides functions for interacting with the list, map, + set, and big_map Michelson types. + + 3. A set of functions for parsing and typechecking Michelson. + Finally, and what you likely came for, the module provides many functions prefixed + with "parse_" that convert untyped Micheline (which is essentially S-expressions + with a few primitive atom types) into the GADT encoding well-typed Michelson. Likewise + there is a number of functions prefixed "unparse_" that do the reverse. These functions + consume gas, and thus are parameterized by an [Alpha_context.t]. + + The variety of functions reflects the variety of things one might want to parse, + from [parse_data] for arbitrary Micheline expressions to [parse_contract_data] for + well-formed Michelson contracts. +*) + +(** {1 Michelson Existential Witness types} *) +open Alpha_context + +open Script_typed_ir +open Script_tc_errors + +type ('ta, 'tb) eq = Eq : ('same, 'same) eq + +type ex_comparable_ty = + | Ex_comparable_ty : 'a Script_typed_ir.comparable_ty -> ex_comparable_ty + +type ex_parameter_ty_and_entrypoints = + | Ex_parameter_ty_and_entrypoints : { + arg_type : ('a, _) Script_typed_ir.ty; + entrypoints : 'a Script_typed_ir.entrypoints; + } + -> ex_parameter_ty_and_entrypoints + +type ex_stack_ty = + | Ex_stack_ty : ('a, 's) Script_typed_ir.stack_ty -> ex_stack_ty + +type ex_script = Ex_script : ('a, 'b) Script_typed_ir.script -> ex_script + +type toplevel = { + code_field : Script.node; + arg_type : Script.node; + storage_type : Script.node; + views : Script_typed_ir.view_map; +} + +type ('arg, 'storage) code = + | Code : { + code : + ( ('arg, 'storage) Script_typed_ir.pair, + ( Script_typed_ir.operation Script_list.t, + 'storage ) + Script_typed_ir.pair ) + Script_typed_ir.lambda; + arg_type : ('arg, _) Script_typed_ir.ty; + storage_type : ('storage, _) Script_typed_ir.ty; + views : Script_typed_ir.view_map; + entrypoints : 'arg Script_typed_ir.entrypoints; + code_size : Cache_memory_helpers.sint; + (** This is an over-approximation of the value size in memory, in + bytes, of the contract's static part, that is its + code. This includes the code of the contract as well as the code + of the views. The storage size is not taken into account by this + field as it has a dynamic size. *) + } + -> ('arg, 'storage) code + +type ex_code = Ex_code : ('a, 'c) code -> ex_code + +type 'storage typed_view = + | Typed_view : { + input_ty : ('input, _) Script_typed_ir.ty; + output_ty : ('output, _) Script_typed_ir.ty; + kinstr : + ( 'input * 'storage, + Script_typed_ir.end_of_stack, + 'output, + Script_typed_ir.end_of_stack ) + Script_typed_ir.kinstr; + original_code_expr : Script.node; + } + -> 'storage typed_view + +type 'storage typed_view_map = + (Script_string.t, 'storage typed_view) Script_typed_ir.map + +type ('a, 's, 'b, 'u) cinstr = { + apply : + 'r 'f. + ('b, 'u, 'r, 'f) Script_typed_ir.kinstr -> + ('a, 's, 'r, 'f) Script_typed_ir.kinstr; +} +[@@ocaml.unboxed] + +type ('a, 's, 'b, 'u) descr = { + loc : Script.location; + bef : ('a, 's) Script_typed_ir.stack_ty; + aft : ('b, 'u) Script_typed_ir.stack_ty; + instr : ('a, 's, 'b, 'u) cinstr; +} + +type tc_context = Script_tc_context.t + +type ('a, 's) judgement = + | Typed : ('a, 's, 'b, 'u) descr -> ('a, 's) judgement + | Failed : { + descr : 'b 'u. ('b, 'u) Script_typed_ir.stack_ty -> ('a, 's, 'b, 'u) descr; + } + -> ('a, 's) judgement + +val close_descr : + ('a, 'b, 'c, 'd) descr -> ('a, 'b, 'c, 'd) Script_typed_ir.kdescr + +(* ---- Lists, Sets and Maps ----------------------------------------------- *) + +(** {2 High-level Michelson Data Types} *) +val ty_eq : + error_details:(Script.location, 'error_trace) error_details -> + ('a, 'ac) Script_typed_ir.ty -> + ('b, 'bc) Script_typed_ir.ty -> + ( (('a, 'ac) Script_typed_ir.ty, ('b, 'bc) Script_typed_ir.ty) eq, + 'error_trace ) + Gas_monad.t + +(** {3 Parsing and Typechecking Michelson} *) +val parse_comparable_data : + ?type_logger:Script_ir_translator_config.type_logger -> + context -> + 'a Script_typed_ir.comparable_ty -> + Script.node -> + ('a * context) tzresult Lwt.t + +(* Parsing a Micheline node data into an IR-typed data. *) +val parse_data : + elab_conf:Script_ir_translator_config.elab_config -> + context -> + allow_forged_tickets:bool -> + allow_forged_lazy_storage_id:bool -> + ('a, _) Script_typed_ir.ty -> + Script.node -> + ('a * context) tzresult Lwt.t + +(* Unparsing an IR-typed data back into a Micheline node data *) +val unparse_data : + context -> + Script_ir_unparser.unparsing_mode -> + ('a, _) Script_typed_ir.ty -> + 'a -> + (Script.expr * context) tzresult Lwt.t + +val unparse_code : + context -> + Script_ir_unparser.unparsing_mode -> + Script.node -> + (Script.expr * context) tzresult Lwt.t + +(** For benchmarking purpose, we also export versions of the unparsing + functions which don't call location stripping. These functions are + not carbonated and should not be called directly from the protocol. *) +module Internal_for_benchmarking : sig + val unparse_data : + context -> + stack_depth:int -> + Script_ir_unparser.unparsing_mode -> + ('a, 'ac) ty -> + 'a -> + (Script.node * context) tzresult Lwt.t + + val unparse_code : + context -> + stack_depth:int -> + Script_ir_unparser.unparsing_mode -> + Script.node -> + (Script.node * context) tzresult Lwt.t +end + +val parse_instr : + elab_conf:Script_ir_translator_config.elab_config -> + tc_context -> + context -> + Script.node -> + ('a, 's) Script_typed_ir.stack_ty -> + (('a, 's) judgement * context) tzresult Lwt.t + +(** + [parse_ty] specialized for the right-hand side part of a big map type, i.e. + the `value` in `big_map key value`. +*) +val parse_big_map_value_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +val parse_packable_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +val parse_passable_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +val parse_comparable_ty : + context -> Script.node -> (ex_comparable_ty * context) tzresult + +val parse_parameter_ty_and_entrypoints : + context -> + legacy:bool -> + Script.node -> + (ex_parameter_ty_and_entrypoints * context) tzresult + +val parse_view_input_ty : + context -> + stack_depth:int -> + legacy:bool -> + Script.node -> + (ex_ty * context) tzresult + +val parse_view_output_ty : + context -> + stack_depth:int -> + legacy:bool -> + Script.node -> + (ex_ty * context) tzresult + +val parse_view : + elab_conf:Script_ir_translator_config.elab_config -> + context -> + ('storage, _) Script_typed_ir.ty -> + Script_typed_ir.view -> + ('storage typed_view * context) tzresult Lwt.t + +val parse_views : + elab_conf:Script_ir_translator_config.elab_config -> + context -> + ('storage, _) Script_typed_ir.ty -> + Script_typed_ir.view_map -> + ('storage typed_view_map * context) tzresult Lwt.t + +(** + [parse_ty] allowing big_map values, operations, contract and tickets. +*) +val parse_any_ty : + context -> legacy:bool -> Script.node -> (ex_ty * context) tzresult + +(** We expose [parse_ty] for convenience to external tools. Please use + specialized versions such as [parse_packable_ty], [parse_passable_ty], + [parse_comparable_ty], or [parse_big_map_value_ty] if possible. *) +val parse_ty : + context -> + legacy:bool -> + allow_lazy_storage:bool -> + allow_operation:bool -> + allow_contract:bool -> + allow_ticket:bool -> + Script.node -> + (ex_ty * context) tzresult + +val parse_toplevel : + context -> Script.expr -> (toplevel * context) tzresult Lwt.t + +(** High-level function to typecheck a Michelson script. This function is not + used for validating operations but only for the [typecheck_code] RPC. + + If [show_types] is set to [true], details of the typechecking are returned + in the [type_map], otherwise the returned [type_map] is empty. *) +val typecheck_code : + legacy:bool -> + show_types:bool -> + context -> + Script.expr -> + (type_map * context) tzresult Lwt.t + +val parse_code : + elab_conf:Script_ir_translator_config.elab_config -> + context -> + code:Script.lazy_expr -> + (ex_code * context) tzresult Lwt.t + +val parse_storage : + elab_conf:Script_ir_translator_config.elab_config -> + context -> + allow_forged_tickets:bool -> + allow_forged_lazy_storage_id:bool -> + ('storage, _) Script_typed_ir.ty -> + storage:Script.lazy_expr -> + ('storage * context) tzresult Lwt.t + +(** Combines [parse_code] and [parse_storage] *) +val parse_script : + elab_conf:Script_ir_translator_config.elab_config -> + context -> + allow_forged_tickets_in_storage:bool -> + allow_forged_lazy_storage_id_in_storage:bool -> + Script.t -> + (ex_script * context) tzresult Lwt.t + +(* Gas accounting may not be perfect in this function, as it is only called by RPCs. *) +val parse_and_unparse_script_unaccounted : + context -> + legacy:bool -> + allow_forged_tickets_in_storage:bool -> + allow_forged_lazy_storage_id_in_storage:bool -> + Script_ir_unparser.unparsing_mode -> + normalize_types:bool -> + Script.t -> + (Script.t * context) tzresult Lwt.t + +val parse_contract_data : + context -> + Script.location -> + ('a, _) Script_typed_ir.ty -> + Destination.t -> + entrypoint:Entrypoint.t -> + (context * 'a Script_typed_ir.typed_contract) tzresult Lwt.t + +val parse_contract_for_script : + context -> + Script.location -> + ('a, _) Script_typed_ir.ty -> + Destination.t -> + entrypoint:Entrypoint.t -> + (context * 'a Script_typed_ir.typed_contract option) tzresult Lwt.t + +(** ['a ex_ty_cstr] is like [ex_ty], but also adds to the existential a function + used to reconstruct a value of type ['a] from the internal type of the + existential. Typically, it will be used to go from the type of an + entry-point to the full type of a contract. *) +type 'a ex_ty_cstr = + | Ex_ty_cstr : { + ty : ('b, _) Script_typed_ir.ty; + construct : 'b -> 'a; + original_type_expr : Script.node; + } + -> 'a ex_ty_cstr + +val find_entrypoint : + error_details:(_, 'error_trace) error_details -> + ('t, _) Script_typed_ir.ty -> + 't Script_typed_ir.entrypoints -> + Entrypoint.t -> + ('t ex_ty_cstr, 'error_trace) Gas_monad.t + +val list_entrypoints_uncarbonated : + ('t, _) Script_typed_ir.ty -> + 't Script_typed_ir.entrypoints -> + Michelson_v1_primitives.prim list list + * (ex_ty * Script.node) Entrypoint.Map.t + +val pack_data : + context -> + ('a, _) Script_typed_ir.ty -> + 'a -> + (bytes * context) tzresult Lwt.t + +val hash_comparable_data : + context -> + 'a Script_typed_ir.comparable_ty -> + 'a -> + (Script_expr_hash.t * context) tzresult Lwt.t + +val hash_data : + context -> + ('a, _) Script_typed_ir.ty -> + 'a -> + (Script_expr_hash.t * context) tzresult Lwt.t + +type lazy_storage_ids + +val no_lazy_storage_id : lazy_storage_ids + +(** Traverse the given type, producing a {!lazy_storage_ids} for + use with {!extract_lazy_storage_diff}. + *) +val collect_lazy_storage : + context -> + ('a, _) Script_typed_ir.ty -> + 'a -> + (lazy_storage_ids * context) tzresult + +val list_of_big_map_ids : lazy_storage_ids -> Big_map.Id.t list + +(** Produce a lazy storage diff, containing in-memory writes to + lazy data structures such as big_maps yet to be committed. + + The resulting diff can be committed to the underlying storage + (context) using [Lazy_storage_diff.apply]. + + @param to_duplicate + Lazy data structure reference produced via {!collect_lazy_storage} + that can not be reused. Typically collected via traversing + the parameters to a smart contract. + @param to_update + Lazy data structure reference produced via {!collect_lazy_storage} + that can be reused. Typically collected via traversing the previous + storage of a smart contract. + *) +val extract_lazy_storage_diff : + context -> + Script_ir_unparser.unparsing_mode -> + temporary:bool -> + to_duplicate:lazy_storage_ids -> + to_update:lazy_storage_ids -> + ('a, _) Script_typed_ir.ty -> + 'a -> + ('a * Lazy_storage.diffs option * context) tzresult Lwt.t + +(* return [None] if none or more than one found *) +val get_single_sapling_state : + context -> + ('a, _) Script_typed_ir.ty -> + 'a -> + (Sapling.Id.t option * context) tzresult + +(** [code_size ctxt code views] returns an overapproximation of the size of + the in-memory representation of [code] and [views] in bytes in the + context [ctxt]. *) +val code_size : + context -> + ('a, 'b) Script_typed_ir.lambda -> + Script_typed_ir.view_map -> + (Cache_memory_helpers.sint * context) tzresult + +(** [script_size script] returns an overapproximation of the size of + the in-memory representation of [script] in bytes as well as the cost + associated to computing that overapproximation. *) +val script_size : ex_script -> int * Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_translator_config.ml b/src/proto_020_PsParisC/lib_protocol/script_ir_translator_config.ml new file mode 100644 index 000000000000..a8c535735b08 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_translator_config.ml @@ -0,0 +1,91 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** [type_logger] is a function, whose task is to log how a stack's type + is altered by some operation being logged. *) +type type_logger = + Script.location -> + stack_ty_before:Script.expr list -> + stack_ty_after:Script.expr list -> + unit + +(** LEGACY MODE is the feature of the Translator and Interpreter which + allows us to distinguish between scripts already originated on chain + and new ones. + + The reason to treat those types of scripts differently is the evolving + nature of Michelson, which sometimes requires disabling features + available in previous versions. These features must be supported at all + times for already originated contracts, but we still want to disable + them at least for new contracts. + + This distinction gives us a handy deprecation mechanism, which + allows us to make sure that from a certain point on no more + contract will be originated using these deprecated features. When + that point time is reached, it becomes possible to patch existing + contracts so that they no longer use the feature and remove it + entirely. + + As a side effect, legacy mode can also be used to skip checks that + have already been performed and hence are guaranteed to pass.*) + +(** [elab_config] is a record grouping together some flags and options + shared by many of the functions in [Script_ir_translator]. It's + convenient to group them together, because they're of similar + types ([bool] or ['a option]), so they're easier not to mix together. + It also makes for shorter and more readable function calls. *) +type elab_config = { + type_logger : type_logger option; + (** A function responsible for logging stack types during typechecking. + Used especially in plugins for editors and IDEs. *) + keep_extra_types_for_interpreter_logging : bool; + (** If set to [true], it instructs the elaborator to retain some + additional type information necessary for logging. This should + never be enabled during validation to save memory occupied by + cached contracts. + + NOTE: if this option wasn't passed to the elaborator and the + interpreter was still called with logging enabled, it might + result in a crash. This cannot be helped at the moment, but since + logging is never enabled during validation, we should be safe. *) + legacy : bool; (** If set to true, it enables the legacy mode (see above). *) +} + +(** [make ?type_logger ?logging_enabled ~legacy ()] creates an [elab_config] + record to be passed to parsing functions in [Script_ir_translator]. + + Note: [?logging_enabled] defaults to [false], because it only ever should + be set to [true] if the Translator is called from outside the protocol + (i.e. from the Plugin). *) +let make : + ?type_logger:type_logger -> + ?keep_extra_types_for_interpreter_logging:bool -> + legacy:bool -> + unit -> + elab_config = + fun ?type_logger ?(keep_extra_types_for_interpreter_logging = false) ~legacy () -> + {type_logger; keep_extra_types_for_interpreter_logging; legacy} diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_unparser.ml b/src/proto_020_PsParisC/lib_protocol/script_ir_unparser.ml new file mode 100644 index 000000000000..2a911dd3b1f0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_unparser.ml @@ -0,0 +1,855 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Micheline +open Script_typed_ir +open Michelson_v1_primitives +module Unparse_costs = Michelson_v1_gas.Cost_of.Unparsing + +type unparsing_mode = Optimized | Readable | Optimized_legacy + +(* This part contains the unparsing that does not depend on parsing + (everything that cannot contain a lambda). The rest is located at + the end of the file. *) + +let unparse_memo_size ~loc memo_size = + let z = Sapling.Memo_size.unparse_to_z memo_size in + Int (loc, z) + +let rec unparse_ty_and_entrypoints_uncarbonated : + type a ac loc. + loc:loc -> (a, ac) ty -> a entrypoints_node -> loc Script.michelson_node = + fun ~loc ty {nested = nested_entrypoints; at_node} -> + let name, args = + match ty with + | Unit_t -> (T_unit, []) + | Int_t -> (T_int, []) + | Nat_t -> (T_nat, []) + | Signature_t -> (T_signature, []) + | String_t -> (T_string, []) + | Bytes_t -> (T_bytes, []) + | Mutez_t -> (T_mutez, []) + | Bool_t -> (T_bool, []) + | Key_hash_t -> (T_key_hash, []) + | Key_t -> (T_key, []) + | Timestamp_t -> (T_timestamp, []) + | Address_t -> (T_address, []) + | Operation_t -> (T_operation, []) + | Chain_id_t -> (T_chain_id, []) + | Never_t -> (T_never, []) + | Bls12_381_g1_t -> (T_bls12_381_g1, []) + | Bls12_381_g2_t -> (T_bls12_381_g2, []) + | Bls12_381_fr_t -> (T_bls12_381_fr, []) + | Contract_t (ut, _meta) -> + let t = + unparse_ty_and_entrypoints_uncarbonated ~loc ut no_entrypoints + in + (T_contract, [t]) + | Pair_t (utl, utr, _meta, _) -> ( + let tl = + unparse_ty_and_entrypoints_uncarbonated ~loc utl no_entrypoints + in + let tr = + unparse_ty_and_entrypoints_uncarbonated ~loc utr no_entrypoints + in + (* Fold [pair a1 (pair ... (pair an-1 an))] into [pair a1 ... an] *) + (* Note that the folding does not happen if the pair on the right has an + annotation because this annotation would be lost *) + match tr with + | Prim (_, T_pair, ts, []) -> (T_pair, tl :: ts) + | _ -> (T_pair, [tl; tr])) + | Or_t (utl, utr, _meta, _) -> + let entrypoints_l, entrypoints_r = + match nested_entrypoints with + | Entrypoints_None -> (no_entrypoints, no_entrypoints) + | Entrypoints_Or {left; right} -> (left, right) + in + let tl = + unparse_ty_and_entrypoints_uncarbonated ~loc utl entrypoints_l + in + let tr = + unparse_ty_and_entrypoints_uncarbonated ~loc utr entrypoints_r + in + (T_or, [tl; tr]) + | Lambda_t (uta, utr, _meta) -> + let ta = + unparse_ty_and_entrypoints_uncarbonated ~loc uta no_entrypoints + in + let tr = + unparse_ty_and_entrypoints_uncarbonated ~loc utr no_entrypoints + in + (T_lambda, [ta; tr]) + | Option_t (ut, _meta, _) -> + let ut = + unparse_ty_and_entrypoints_uncarbonated ~loc ut no_entrypoints + in + (T_option, [ut]) + | List_t (ut, _meta) -> + let t = + unparse_ty_and_entrypoints_uncarbonated ~loc ut no_entrypoints + in + (T_list, [t]) + | Ticket_t (ut, _meta) -> + let t = unparse_comparable_ty_uncarbonated ~loc ut in + (T_ticket, [t]) + | Set_t (ut, _meta) -> + let t = unparse_comparable_ty_uncarbonated ~loc ut in + (T_set, [t]) + | Map_t (uta, utr, _meta) -> + let ta = unparse_comparable_ty_uncarbonated ~loc uta in + let tr = + unparse_ty_and_entrypoints_uncarbonated ~loc utr no_entrypoints + in + (T_map, [ta; tr]) + | Big_map_t (uta, utr, _meta) -> + let ta = unparse_comparable_ty_uncarbonated ~loc uta in + let tr = + unparse_ty_and_entrypoints_uncarbonated ~loc utr no_entrypoints + in + (T_big_map, [ta; tr]) + | Sapling_transaction_t memo_size -> + (T_sapling_transaction, [unparse_memo_size ~loc memo_size]) + | Sapling_transaction_deprecated_t memo_size -> + (T_sapling_transaction_deprecated, [unparse_memo_size ~loc memo_size]) + | Sapling_state_t memo_size -> + (T_sapling_state, [unparse_memo_size ~loc memo_size]) + | Chest_key_t -> (T_chest_key, []) + | Chest_t -> (T_chest, []) + in + let annot = + match at_node with + | None -> [] + | Some {name; original_type_expr = _} -> + [Entrypoint.unparse_as_field_annot name] + in + Prim (loc, name, args, annot) + +and unparse_comparable_ty_uncarbonated : + type a loc. loc:loc -> a comparable_ty -> loc Script.michelson_node = + fun ~loc ty -> unparse_ty_and_entrypoints_uncarbonated ~loc ty no_entrypoints + +let unparse_ty_uncarbonated ~loc ty = + unparse_ty_and_entrypoints_uncarbonated ~loc ty no_entrypoints + +let unparse_ty ~loc ctxt ty = + let open Result_syntax in + let+ ctxt = Gas.consume ctxt (Unparse_costs.unparse_type ty) in + (unparse_ty_uncarbonated ~loc ty, ctxt) + +let unparse_parameter_ty ~loc ctxt ty ~entrypoints = + let open Result_syntax in + let+ ctxt = Gas.consume ctxt (Unparse_costs.unparse_type ty) in + (unparse_ty_and_entrypoints_uncarbonated ~loc ty entrypoints.root, ctxt) + +let serialize_ty_for_error ty = + (* + Types are bounded by [Constants.michelson_maximum_type_size], so + [unparse_ty_uncarbonated] and [strip_locations] are bounded in time. + + It is hence OK to use them in errors that are not caught in the validation + (only once in apply). + *) + unparse_ty_uncarbonated ~loc:() ty |> Micheline.strip_locations + +let rec unparse_stack_uncarbonated : + type a s. (a, s) stack_ty -> Script.expr list = function + | Bot_t -> [] + | Item_t (ty, rest) -> + let uty = unparse_ty_uncarbonated ~loc:() ty in + let urest = unparse_stack_uncarbonated rest in + strip_locations uty :: urest + +let serialize_stack_for_error ctxt stack_ty = + match Gas.level ctxt with + | Unaccounted -> unparse_stack_uncarbonated stack_ty + | Limited _ -> [] + +let unparse_unit ~loc ctxt () = Ok (Prim (loc, D_Unit, [], []), ctxt) + +let unparse_int ~loc ctxt v = Ok (Int (loc, Script_int.to_zint v), ctxt) + +let unparse_nat ~loc ctxt v = Ok (Int (loc, Script_int.to_zint v), ctxt) + +let unparse_string ~loc ctxt s = + Ok (String (loc, Script_string.to_string s), ctxt) + +let unparse_bytes ~loc ctxt s = Ok (Bytes (loc, s), ctxt) + +let unparse_bool ~loc ctxt b = + Ok (Prim (loc, (if b then D_True else D_False), [], []), ctxt) + +let unparse_timestamp ~loc ctxt mode t = + let open Result_syntax in + match mode with + | Optimized | Optimized_legacy -> + return (Int (loc, Script_timestamp.to_zint t), ctxt) + | Readable -> ( + let* ctxt = Gas.consume ctxt Unparse_costs.timestamp_readable in + match Script_timestamp.to_notation t with + | None -> return (Int (loc, Script_timestamp.to_zint t), ctxt) + | Some s -> return (String (loc, s), ctxt)) + +let unparse_address ~loc ctxt mode {destination; entrypoint} = + let open Result_syntax in + match mode with + | Optimized | Optimized_legacy -> + let+ ctxt = Gas.consume ctxt Unparse_costs.contract_optimized in + let bytes = + Data_encoding.Binary.to_bytes_exn + Data_encoding.(tup2 Destination.encoding Entrypoint.value_encoding) + (destination, entrypoint) + in + (Bytes (loc, bytes), ctxt) + | Readable -> + let+ ctxt = Gas.consume ctxt Unparse_costs.contract_readable in + let notation = + Destination.to_b58check destination + ^ Entrypoint.to_address_suffix entrypoint + in + (String (loc, notation), ctxt) + +let unparse_contract ~loc ctxt mode typed_contract = + let destination = Typed_contract.destination typed_contract in + let entrypoint = Typed_contract.entrypoint typed_contract in + let address = {destination; entrypoint} in + unparse_address ~loc ctxt mode address + +let unparse_signature ~loc ctxt mode s = + let open Result_syntax in + let s = Script_signature.get s in + match mode with + | Optimized | Optimized_legacy -> + let+ ctxt = Gas.consume ctxt Unparse_costs.signature_optimized in + let bytes = Data_encoding.Binary.to_bytes_exn Signature.encoding s in + (Bytes (loc, bytes), ctxt) + | Readable -> + let+ ctxt = Gas.consume ctxt Unparse_costs.signature_readable in + (String (loc, Signature.to_b58check s), ctxt) + +let unparse_mutez ~loc ctxt v = Ok (Int (loc, Z.of_int64 (Tez.to_mutez v)), ctxt) + +let unparse_key ~loc ctxt mode k = + let open Result_syntax in + match mode with + | Optimized | Optimized_legacy -> + let+ ctxt = Gas.consume ctxt Unparse_costs.public_key_optimized in + let bytes = + Data_encoding.Binary.to_bytes_exn Signature.Public_key.encoding k + in + (Bytes (loc, bytes), ctxt) + | Readable -> + let+ ctxt = Gas.consume ctxt Unparse_costs.public_key_readable in + (String (loc, Signature.Public_key.to_b58check k), ctxt) + +let unparse_key_hash ~loc ctxt mode k = + let open Result_syntax in + match mode with + | Optimized | Optimized_legacy -> + let+ ctxt = Gas.consume ctxt Unparse_costs.key_hash_optimized in + let bytes = + Data_encoding.Binary.to_bytes_exn Signature.Public_key_hash.encoding k + in + (Bytes (loc, bytes), ctxt) + | Readable -> + let+ ctxt = Gas.consume ctxt Unparse_costs.key_hash_readable in + (String (loc, Signature.Public_key_hash.to_b58check k), ctxt) + +(* Operations are only unparsed during the production of execution traces of + the interpreter. *) +let unparse_operation ~loc ctxt {piop; lazy_storage_diff = _} = + let open Result_syntax in + let iop = Apply_internal_results.packed_internal_operation piop in + let bytes = + Data_encoding.Binary.to_bytes_exn + Apply_internal_results.internal_operation_encoding + iop + in + let+ ctxt = Gas.consume ctxt (Unparse_costs.operation bytes) in + (Bytes (loc, bytes), ctxt) + +let unparse_chain_id ~loc ctxt mode chain_id = + let open Result_syntax in + match mode with + | Optimized | Optimized_legacy -> + let+ ctxt = Gas.consume ctxt Unparse_costs.chain_id_optimized in + let bytes = + Data_encoding.Binary.to_bytes_exn Script_chain_id.encoding chain_id + in + (Bytes (loc, bytes), ctxt) + | Readable -> + let+ ctxt = Gas.consume ctxt Unparse_costs.chain_id_readable in + (String (loc, Script_chain_id.to_b58check chain_id), ctxt) + +let unparse_bls12_381_g1 ~loc ctxt x = + let open Result_syntax in + let+ ctxt = Gas.consume ctxt Unparse_costs.bls12_381_g1 in + let bytes = Script_bls.G1.to_bytes x in + (Bytes (loc, bytes), ctxt) + +let unparse_bls12_381_g2 ~loc ctxt x = + let open Result_syntax in + let+ ctxt = Gas.consume ctxt Unparse_costs.bls12_381_g2 in + let bytes = Script_bls.G2.to_bytes x in + (Bytes (loc, bytes), ctxt) + +let unparse_bls12_381_fr ~loc ctxt x = + let open Result_syntax in + let+ ctxt = Gas.consume ctxt Unparse_costs.bls12_381_fr in + let bytes = Script_bls.Fr.to_bytes x in + (Bytes (loc, bytes), ctxt) + +let unparse_with_data_encoding ~loc ctxt s unparse_cost encoding = + let open Lwt_result_syntax in + let*? ctxt = Gas.consume ctxt unparse_cost in + let bytes = Data_encoding.Binary.to_bytes_exn encoding s in + return (Bytes (loc, bytes), ctxt) + +(* -- Unparsing data of complex types -- *) + +type ('ty, 'depth) comb_witness = + | Comb_Pair : ('t, 'd) comb_witness -> (_ * 't, unit -> 'd) comb_witness + | Comb_Any : (_, _) comb_witness + +let unparse_pair (type r) ~loc unparse_l unparse_r ctxt mode + (r_comb_witness : (r, unit -> unit -> _) comb_witness) (l, (r : r)) = + let open Lwt_result_syntax in + let* l, ctxt = unparse_l ctxt l in + let+ r, ctxt = unparse_r ctxt r in + (* Fold combs. + For combs, three notations are supported: + - a) [Pair x1 (Pair x2 ... (Pair xn-1 xn) ...)], + - b) [Pair x1 x2 ... xn-1 xn], and + - c) [{x1; x2; ...; xn-1; xn}]. + In readable mode, we always use b), + in optimized mode we use the shortest to serialize: + - for n=2, [Pair x1 x2], + - for n=3, [Pair x1 (Pair x2 x3)], + - for n>=4, [{x1; x2; ...; xn}]. + *) + let res = + match (mode, r_comb_witness, r) with + | Optimized, Comb_Pair _, Micheline.Seq (_, r) -> + (* Optimized case n > 4 *) + Micheline.Seq (loc, l :: r) + | ( Optimized, + Comb_Pair (Comb_Pair _), + Prim (_, D_Pair, [x2; Prim (_, D_Pair, [x3; x4], [])], []) ) -> + (* Optimized case n = 4 *) + Micheline.Seq (loc, [l; x2; x3; x4]) + | Readable, Comb_Pair _, Prim (_, D_Pair, xs, []) -> + (* Readable case n > 2 *) + Prim (loc, D_Pair, l :: xs, []) + | _ -> + (* The remaining cases are: + - Optimized n = 2, + - Optimized n = 3, and + - Readable n = 2, + - Optimized_legacy, any n *) + Prim (loc, D_Pair, [l; r], []) + in + (res, ctxt) + +let unparse_or ~loc unparse_l unparse_r ctxt = + let open Lwt_result_syntax in + function + | L l -> + let+ l, ctxt = unparse_l ctxt l in + (Prim (loc, D_Left, [l], []), ctxt) + | R r -> + let+ r, ctxt = unparse_r ctxt r in + (Prim (loc, D_Right, [r], []), ctxt) + +let unparse_option ~loc unparse_v ctxt = + let open Lwt_result_syntax in + function + | Some v -> + let+ v, ctxt = unparse_v ctxt v in + (Prim (loc, D_Some, [v], []), ctxt) + | None -> return (Prim (loc, D_None, [], []), ctxt) + +(* -- Unparsing data of comparable types -- *) + +let comb_witness2 : + type t tc. (t, tc) ty -> (t, unit -> unit -> unit) comb_witness = function + | Pair_t (_, Pair_t _, _, _) -> Comb_Pair (Comb_Pair Comb_Any) + | Pair_t _ -> Comb_Pair Comb_Any + | _ -> Comb_Any + +let rec unparse_comparable_data_rec : + type a loc. + loc:loc -> + context -> + unparsing_mode -> + a comparable_ty -> + a -> + (loc Script.michelson_node * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~loc ctxt mode ty a -> + (* No need for stack_depth here. Unlike [unparse_data], + [unparse_comparable_data] doesn't call [unparse_code]. + The stack depth is bounded by the type depth, currently bounded + by 1000 (michelson_maximum_type_size). *) + let*? ctxt = + Gas.consume ctxt Unparse_costs.unparse_data_cycle + (* We could have a smaller cost but let's keep it consistent with + [unparse_data] for now. *) + in + match (ty, a) with + | Unit_t, v -> Lwt.return @@ unparse_unit ~loc ctxt v + | Int_t, v -> Lwt.return @@ unparse_int ~loc ctxt v + | Nat_t, v -> Lwt.return @@ unparse_nat ~loc ctxt v + | String_t, s -> Lwt.return @@ unparse_string ~loc ctxt s + | Bytes_t, s -> Lwt.return @@ unparse_bytes ~loc ctxt s + | Bool_t, b -> Lwt.return @@ unparse_bool ~loc ctxt b + | Timestamp_t, t -> Lwt.return @@ unparse_timestamp ~loc ctxt mode t + | Address_t, address -> Lwt.return @@ unparse_address ~loc ctxt mode address + | Signature_t, s -> Lwt.return @@ unparse_signature ~loc ctxt mode s + | Mutez_t, v -> Lwt.return @@ unparse_mutez ~loc ctxt v + | Key_t, k -> Lwt.return @@ unparse_key ~loc ctxt mode k + | Key_hash_t, k -> Lwt.return @@ unparse_key_hash ~loc ctxt mode k + | Chain_id_t, chain_id -> + Lwt.return @@ unparse_chain_id ~loc ctxt mode chain_id + | Pair_t (tl, tr, _, YesYes), pair -> + let r_witness = comb_witness2 tr in + let unparse_l ctxt v = + unparse_comparable_data_rec ~loc ctxt mode tl v + in + let unparse_r ctxt v = + unparse_comparable_data_rec ~loc ctxt mode tr v + in + unparse_pair ~loc unparse_l unparse_r ctxt mode r_witness pair + | Or_t (tl, tr, _, YesYes), v -> + let unparse_l ctxt v = + unparse_comparable_data_rec ~loc ctxt mode tl v + in + let unparse_r ctxt v = + unparse_comparable_data_rec ~loc ctxt mode tr v + in + unparse_or ~loc unparse_l unparse_r ctxt v + | Option_t (t, _, Yes), v -> + let unparse_v ctxt v = unparse_comparable_data_rec ~loc ctxt mode t v in + unparse_option ~loc unparse_v ctxt v + | Never_t, _ -> . + +let account_for_future_serialization_cost unparsed_data ctxt = + let open Result_syntax in + let* ctxt = Gas.consume ctxt (Script.strip_locations_cost unparsed_data) in + let unparsed_data = Micheline.strip_locations unparsed_data in + let+ ctxt = + Gas.consume ctxt (Script.micheline_serialization_cost unparsed_data) + in + (unparsed_data, ctxt) + +type unparse_code_rec = + t -> + stack_depth:int -> + unparsing_mode -> + Script.node -> + ((canonical_location, prim) node * t, error trace) result Lwt.t + +module type MICHELSON_PARSER = sig + val opened_ticket_type : + Script.location -> + 'a comparable_ty -> + (address, ('a, Script_int.n Script_int.num) pair) pair comparable_ty + tzresult + + val parse_packable_ty : + context -> + stack_depth:int -> + legacy:bool -> + Script.node -> + (ex_ty * context) tzresult + + val parse_data : + unparse_code_rec:unparse_code_rec -> + elab_conf:Script_ir_translator_config.elab_config -> + stack_depth:int -> + context -> + allow_forged_tickets:bool -> + allow_forged_lazy_storage_id:bool -> + ('a, 'ac) ty -> + Script.node -> + ('a * t) tzresult Lwt.t +end + +module Data_unparser (P : MICHELSON_PARSER) = struct + open Script_tc_errors + + (* -- Unparsing data of any type -- *) + let rec unparse_data_rec : + type a ac. + context -> + stack_depth:int -> + unparsing_mode -> + (a, ac) ty -> + a -> + (Script.node * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt ~stack_depth mode ty a -> + let*? ctxt = Gas.consume ctxt Unparse_costs.unparse_data_cycle in + let non_terminal_recursion ctxt mode ty a = + if Compare.Int.(stack_depth > 10_000) then + tzfail Script_tc_errors.Unparsing_too_many_recursive_calls + else unparse_data_rec ctxt ~stack_depth:(stack_depth + 1) mode ty a + in + let loc = Micheline.dummy_location in + match (ty, a) with + | Unit_t, v -> Lwt.return @@ unparse_unit ~loc ctxt v + | Int_t, v -> Lwt.return @@ unparse_int ~loc ctxt v + | Nat_t, v -> Lwt.return @@ unparse_nat ~loc ctxt v + | String_t, s -> Lwt.return @@ unparse_string ~loc ctxt s + | Bytes_t, s -> Lwt.return @@ unparse_bytes ~loc ctxt s + | Bool_t, b -> Lwt.return @@ unparse_bool ~loc ctxt b + | Timestamp_t, t -> Lwt.return @@ unparse_timestamp ~loc ctxt mode t + | Address_t, address -> + Lwt.return @@ unparse_address ~loc ctxt mode address + | Contract_t _, contract -> + Lwt.return @@ unparse_contract ~loc ctxt mode contract + | Signature_t, s -> Lwt.return @@ unparse_signature ~loc ctxt mode s + | Mutez_t, v -> Lwt.return @@ unparse_mutez ~loc ctxt v + | Key_t, k -> Lwt.return @@ unparse_key ~loc ctxt mode k + | Key_hash_t, k -> Lwt.return @@ unparse_key_hash ~loc ctxt mode k + | Operation_t, operation -> + Lwt.return @@ unparse_operation ~loc ctxt operation + | Chain_id_t, chain_id -> + Lwt.return @@ unparse_chain_id ~loc ctxt mode chain_id + | Bls12_381_g1_t, x -> Lwt.return @@ unparse_bls12_381_g1 ~loc ctxt x + | Bls12_381_g2_t, x -> Lwt.return @@ unparse_bls12_381_g2 ~loc ctxt x + | Bls12_381_fr_t, x -> Lwt.return @@ unparse_bls12_381_fr ~loc ctxt x + | Pair_t (tl, tr, _, _), pair -> + let r_witness = comb_witness2 tr in + let unparse_l ctxt v = non_terminal_recursion ctxt mode tl v in + let unparse_r ctxt v = non_terminal_recursion ctxt mode tr v in + unparse_pair ~loc unparse_l unparse_r ctxt mode r_witness pair + | Or_t (tl, tr, _, _), v -> + let unparse_l ctxt v = non_terminal_recursion ctxt mode tl v in + let unparse_r ctxt v = non_terminal_recursion ctxt mode tr v in + unparse_or ~loc unparse_l unparse_r ctxt v + | Option_t (t, _, _), v -> + let unparse_v ctxt v = non_terminal_recursion ctxt mode t v in + unparse_option ~loc unparse_v ctxt v + | List_t (t, _), items -> + let+ items, ctxt = + List.fold_left_es + (fun (l, ctxt) element -> + let+ unparsed, ctxt = + non_terminal_recursion ctxt mode t element + in + (unparsed :: l, ctxt)) + ([], ctxt) + items.elements + in + (Micheline.Seq (loc, List.rev items), ctxt) + | Ticket_t (t, _), {ticketer; contents; amount} -> + (* ideally we would like to allow a little overhead here because it is only used for unparsing *) + let*? t = P.opened_ticket_type loc t in + let destination : Destination.t = Contract ticketer in + let addr = {destination; entrypoint = Entrypoint.default} in + (unparse_data_rec [@tailcall]) + ctxt + ~stack_depth + mode + t + (addr, (contents, (amount :> Script_int.n Script_int.num))) + | Set_t (t, _), set -> + let+ items, ctxt = + List.fold_left_es + (fun (l, ctxt) item -> + let+ item, ctxt = + unparse_comparable_data_rec ~loc ctxt mode t item + in + (item :: l, ctxt)) + ([], ctxt) + (Script_set.fold (fun e acc -> e :: acc) set []) + in + (Micheline.Seq (loc, items), ctxt) + | Map_t (kt, vt, _), map -> + let items = Script_map.fold (fun k v acc -> (k, v) :: acc) map [] in + let+ items, ctxt = + unparse_items_rec + ctxt + ~stack_depth:(stack_depth + 1) + mode + kt + vt + items + in + (Micheline.Seq (loc, items), ctxt) + | Big_map_t (_kt, _vt, _), Big_map {id = Some id; diff = {size; _}; _} + when Compare.Int.( = ) size 0 -> + return (Micheline.Int (loc, Big_map.Id.unparse_to_z id), ctxt) + | Big_map_t (kt, vt, _), Big_map {id = Some id; diff = {map; _}; _} -> + let items = + Big_map_overlay.fold (fun _ (k, v) acc -> (k, v) :: acc) map [] + in + let items = + (* Sort the items in Michelson comparison order and not in key + hash order. This code path is only exercised for tracing, + so we don't bother carbonating this sort operation + precisely. Also, the sort uses a reverse compare because + [unparse_items] will reverse the result. *) + List.sort + (fun (a, _) (b, _) -> Script_comparable.compare_comparable kt b a) + items + in + (* this can't fail if the original type is well-formed + because [option vt] is always strictly smaller than [big_map kt vt] *) + let*? vt = option_t loc vt in + let+ items, ctxt = + unparse_items_rec + ctxt + ~stack_depth:(stack_depth + 1) + mode + kt + vt + items + in + ( Micheline.Prim + ( loc, + D_Pair, + [Int (loc, Big_map.Id.unparse_to_z id); Seq (loc, items)], + [] ), + ctxt ) + | Big_map_t (kt, vt, _), Big_map {id = None; diff = {map; _}; _} -> + let items = + Big_map_overlay.fold + (fun _ (k, v) acc -> + match v with None -> acc | Some v -> (k, v) :: acc) + map + [] + in + let items = + (* See note above. *) + List.sort + (fun (a, _) (b, _) -> Script_comparable.compare_comparable kt b a) + items + in + let+ items, ctxt = + unparse_items_rec + ctxt + ~stack_depth:(stack_depth + 1) + mode + kt + vt + items + in + (Micheline.Seq (loc, items), ctxt) + | Lambda_t _, Lam (_, original_code) -> + unparse_code_rec + ctxt + ~stack_depth:(stack_depth + 1) + mode + original_code + | Lambda_t _, LamRec (_, original_code) -> + let+ body, ctxt = + unparse_code_rec + ctxt + ~stack_depth:(stack_depth + 1) + mode + original_code + in + (Micheline.Prim (loc, D_Lambda_rec, [body], []), ctxt) + | Never_t, _ -> . + | Sapling_transaction_t _, s -> + let*? ctxt = Gas.consume ctxt (Unparse_costs.sapling_transaction s) in + let bytes = + Data_encoding.Binary.to_bytes_exn Sapling.transaction_encoding s + in + return (Bytes (loc, bytes), ctxt) + | Sapling_transaction_deprecated_t _, s -> + let*? ctxt = + Gas.consume ctxt (Unparse_costs.sapling_transaction_deprecated s) + in + let bytes = + Data_encoding.Binary.to_bytes_exn + Sapling.Legacy.transaction_encoding + s + in + return (Bytes (loc, bytes), ctxt) + | Sapling_state_t _, {id; diff; _} -> + let*? ctxt = Gas.consume ctxt (Unparse_costs.sapling_diff diff) in + return + ( (match diff with + | {commitments_and_ciphertexts = []; nullifiers = []} -> ( + match id with + | None -> Micheline.Seq (loc, []) + | Some id -> + let id = Sapling.Id.unparse_to_z id in + Micheline.Int (loc, id)) + | diff -> ( + let diff_bytes = + Data_encoding.Binary.to_bytes_exn Sapling.diff_encoding diff + in + let unparsed_diff = Bytes (loc, diff_bytes) in + match id with + | None -> unparsed_diff + | Some id -> + let id = Sapling.Id.unparse_to_z id in + Micheline.Prim + (loc, D_Pair, [Int (loc, id); unparsed_diff], []))), + ctxt ) + | Chest_key_t, s -> + unparse_with_data_encoding + ~loc + ctxt + s + Unparse_costs.chest_key + Script_timelock.chest_key_encoding + | Chest_t, s -> + unparse_with_data_encoding + ~loc + ctxt + s + (Unparse_costs.chest + ~plaintext_size:(Script_timelock.get_plaintext_size s)) + Script_timelock.chest_encoding + + and unparse_items_rec : + type k v vc. + context -> + stack_depth:int -> + unparsing_mode -> + k comparable_ty -> + (v, vc) ty -> + (k * v) list -> + (Script.node list * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt ~stack_depth mode kt vt items -> + List.fold_left_es + (fun (l, ctxt) (k, v) -> + let loc = Micheline.dummy_location in + let* key, ctxt = unparse_comparable_data_rec ~loc ctxt mode kt k in + let+ value, ctxt = + unparse_data_rec ctxt ~stack_depth:(stack_depth + 1) mode vt v + in + (Prim (loc, D_Elt, [key; value], []) :: l, ctxt)) + ([], ctxt) + items + + and unparse_code_rec ctxt ~stack_depth mode code = + let open Lwt_result_syntax in + let elab_conf = Script_ir_translator_config.make ~legacy:true () in + let*? ctxt = Gas.consume ctxt Unparse_costs.unparse_instr_cycle in + let non_terminal_recursion ctxt mode code = + if Compare.Int.(stack_depth > 10_000) then + tzfail Unparsing_too_many_recursive_calls + else unparse_code_rec ctxt ~stack_depth:(stack_depth + 1) mode code + in + match code with + | Prim (loc, I_PUSH, [ty; data], annot) -> + let*? Ex_ty t, ctxt = + P.parse_packable_ty + ctxt + ~stack_depth:(stack_depth + 1) + ~legacy:elab_conf.legacy + ty + in + let allow_forged_tickets, allow_forged_lazy_storage_id = + (false, false) + (* Forgeable in PUSH data are already forbidden at parsing, + the only case for which this matters is storing a lambda resulting + from APPLYing a non-forgeable but this cannot happen either as long + as all packable values are also forgeable. *) + in + let* data, ctxt = + P.parse_data + ~unparse_code_rec + ~elab_conf + ctxt + ~stack_depth:(stack_depth + 1) + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + t + data + in + let* data, ctxt = + unparse_data_rec ctxt ~stack_depth:(stack_depth + 1) mode t data + in + return (Prim (loc, I_PUSH, [ty; data], annot), ctxt) + | Seq (loc, items) -> + let* items, ctxt = + List.fold_left_es + (fun (l, ctxt) item -> + let+ item, ctxt = non_terminal_recursion ctxt mode item in + (item :: l, ctxt)) + ([], ctxt) + items + in + return (Micheline.Seq (loc, List.rev items), ctxt) + | Prim (loc, prim, items, annot) -> + let* items, ctxt = + List.fold_left_es + (fun (l, ctxt) item -> + let+ item, ctxt = non_terminal_recursion ctxt mode item in + (item :: l, ctxt)) + ([], ctxt) + items + in + return (Prim (loc, prim, List.rev items, annot), ctxt) + | (Int _ | String _ | Bytes _) as atom -> return (atom, ctxt) + + let unparse_data ctxt ~stack_depth mode ty v = + let open Lwt_result_syntax in + let* unparsed_data, ctxt = unparse_data_rec ctxt ~stack_depth mode ty v in + Lwt.return (account_for_future_serialization_cost unparsed_data ctxt) + + let unparse_code ctxt ~stack_depth mode v = + let open Lwt_result_syntax in + let* unparsed_data, ctxt = unparse_code_rec ctxt ~stack_depth mode v in + Lwt.return (account_for_future_serialization_cost unparsed_data ctxt) + + let unparse_items ctxt ~stack_depth mode ty vty vs = + let open Lwt_result_syntax in + let* unparsed_datas, ctxt = + unparse_items_rec ctxt ~stack_depth mode ty vty vs + in + let*? unparsed_datas, ctxt = + List.fold_left_e + (fun (acc, ctxt) unparsed_data -> + let open Result_syntax in + let+ unparsed_data, ctxt = + account_for_future_serialization_cost unparsed_data ctxt + in + (unparsed_data :: acc, ctxt)) + ([], ctxt) + unparsed_datas + in + return (List.rev unparsed_datas, ctxt) + + module Internal_for_benchmarking = struct + let unparse_data = unparse_data_rec + + let unparse_code = unparse_code_rec + end +end + +let unparse_comparable_data ctxt mode ty v = + let open Lwt_result_syntax in + let* unparsed_data, ctxt = + unparse_comparable_data_rec ctxt ~loc:() mode ty v + in + Lwt.return (account_for_future_serialization_cost unparsed_data ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/script_ir_unparser.mli b/src/proto_020_PsParisC/lib_protocol/script_ir_unparser.mli new file mode 100644 index 000000000000..193607ba1f73 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_ir_unparser.mli @@ -0,0 +1,257 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_typed_ir + +(** Flag that drives unparsing of typed values to nodes. + - [Optimized_legacy] must be kept backward-compatible in order to compute + valid hashes (of big map keys). + - [Optimized] may be used as long as the result can be read by + {!Script_ir_translator.parse_data}. + - [Readable] produces with [string] values instead of [bytes] when feasible. +*) +type unparsing_mode = Optimized | Readable | Optimized_legacy + +(** [('t, 'd) comb_witness] describes types of values belonging to a [comb] + of type ['t] and size ['d]. *) +type ('ty, 'depth) comb_witness = + | Comb_Pair : ('t, 'd) comb_witness -> (_ * 't, unit -> 'd) comb_witness + | Comb_Any : (_, _) comb_witness + +(** [serialize_ty_for_error ty] returns the Micheline representation of [ty] + suitable for rendering in an error message. Does not consume gas, since + when this function is called, the operation must have already failed. *) +val serialize_ty_for_error : ('a, 'b) ty -> Script.expr + +(** [serialize_stack_for_error ctxt stack_ty] returns a Micheline representation of + [stack_ty] as a list of Micheline expressions ONLY IF gas is unlimited + in [ctxt]. Otherwise returns an empty list. *) +val serialize_stack_for_error : context -> ('a, 'b) stack_ty -> Script.expr list + +(** [unparse_ty ~loc ctxt ty] returns the Micheline representation of a given + type and an update context, where gas has been properly consumed. *) +val unparse_ty : + loc:'loc -> + context -> + ('b, 'c) ty -> + ('loc Script.michelson_node * context, error trace) result + +(** [unparse_comparable_ty_uncarbonated ~loc ty] returns the Michelson + representation of comparable type [ty] without consuming gas. *) +val unparse_comparable_ty_uncarbonated : + loc:'loc -> 'a comparable_ty -> 'loc Script.michelson_node + +(** [unparse_stack_uncarbonated stack_ty] returns the Micheline representation + of [stack_ty]. Does not consume gas. *) +val unparse_stack_uncarbonated : ('a, 's) stack_ty -> Script.expr list + +(** [unparse_parameter_ty ~loc ctxt ty ~entrypoints] is a specialised version of + [unparse_ty], which also analyses [entrypoints] in order to annotate + the returned type with adequate annotations. *) +val unparse_parameter_ty : + loc:'loc -> + context -> + ('a, 'c) ty -> + entrypoints:'a entrypoints -> + ('loc Script.michelson_node * context, error trace) result + +(** [unparse_bls12_381_g1 ~loc ctxt bls] returns the Micheline representation + of [bls] and consumes gas from [ctxt]. *) +val unparse_bls12_381_g1 : + loc:'loc -> + context -> + Script_bls.G1.t -> + ('loc Script.michelson_node * context, error trace) result + +(** [unparse_bls12_381_g1 ~loc ctxt bls] returns the Micheline representation + of [bls] and consumes gas from [ctxt]. *) +val unparse_bls12_381_g2 : + loc:'loc -> + context -> + Script_bls.G2.t -> + ('loc Script.michelson_node * context, error trace) result + +(** [unparse_bls12_381_g1 ~loc ctxt bls] returns the Micheline representation + of [bls] and consumes gas from [ctxt]. *) +val unparse_bls12_381_fr : + loc:'loc -> + context -> + Script_bls.Fr.t -> + ('loc Script.michelson_node * context, error trace) result + +(** [unparse_operation ~loc ctxt op] returns the Micheline representation of + [op] and consumes gas from [ctxt]. Useful only for producing execution + traces in the interpreter. *) +val unparse_operation : + loc:'loc -> + context -> + Script_typed_ir.operation -> + ('loc Script.michelson_node * context, error trace) result + +(** [unparse_with_data_encoding ~loc ctxt v gas_cost enc] returns the bytes + representation of [v] wrapped in [Micheline.Bytes], consuming [gas_cost] + from [ctxt]. *) +val unparse_with_data_encoding : + loc:'loc -> + context -> + 'a -> + Gas.cost -> + 'a Data_encoding.t -> + ('loc Script.michelson_node * context, error trace) result Lwt.t + +(** [unparse_comparable_data ctxt unparsing_mode ty v] returns the + Micheline representation of [v] of type [ty], consuming gas from + [ctxt]. *) +val unparse_comparable_data : + context -> + unparsing_mode -> + 'a comparable_ty -> + 'a -> + (Script.expr * context) tzresult Lwt.t + +(** [unparse_contract ~loc ctxt unparsin_mode contract] returns a Micheline + representation of a given contract in a given [unparsing_mode]. Consumes + gas [ctxt]. *) +val unparse_contract : + loc:'loc -> + context -> + unparsing_mode -> + 'b typed_contract -> + ('loc Script.michelson_node * context, error trace) result + +(** Lambdas are normalized at parsing and also at unparsing. These + normalizations require to parse and unparse data appearing inside + PUSH and introduces a mutual dependency between this module and + [Script_ir_translator] which is resolved as follows: + - [Script_ir_translator.parse_data] takes the normalization function + [unparse_code_rec] as argument, + - the unparsing function [unparse_data_rec] and the normalization + function [unparse_code_rec] are mutually defined in a functor + parameterized by the missing bits from [Script_ir_translator]; see the + module signature [MICHELSON_PARSER] below. + *) + +(** The [unparse_code_rec] function is not exported (except through + the [Internal_for_benchmarking] module), but needs to be called by + [parse_data] to normalize lambdas so it is passed as argument to + the [parse_data] of the [MICHELSON_PARSER] signature below and to + several functions of [Script_ir_translator]. To avoid repeating the + signature of this function we define a type alias for it. *) +type unparse_code_rec = + context -> + stack_depth:int -> + unparsing_mode -> + Script.node -> + (Script.node * context) tzresult Lwt.t + +(** [MICHELSON_PARSER] signature describes a set of dependencies required to + unparse arbitrary values in the IR. Because some of those values contain + just a Michelson code that does not need to be parsed immediately, + unparsing them requires extracting information from that code – that's + why we depend on the parser here. *) + +module type MICHELSON_PARSER = sig + val opened_ticket_type : + Script.location -> + 'a comparable_ty -> + (address, ('a, Script_int.n Script_int.num) pair) pair comparable_ty + tzresult + + val parse_packable_ty : + context -> + stack_depth:int -> + legacy:bool -> + Script.node -> + (ex_ty * context) tzresult + + val parse_data : + unparse_code_rec:unparse_code_rec -> + elab_conf:Script_ir_translator_config.elab_config -> + stack_depth:int -> + context -> + allow_forged_tickets:bool -> + allow_forged_lazy_storage_id:bool -> + ('a, 'ac) ty -> + Script.node -> + ('a * t) tzresult Lwt.t +end + +module Data_unparser : functor (P : MICHELSON_PARSER) -> sig + (** [unparse_data ctxt ~stack_depth unparsing_mode ty data] returns the + Micheline representation of [data] of type [ty], consuming an appropriate + amount of gas from [ctxt]. *) + val unparse_data : + context -> + stack_depth:int -> + unparsing_mode -> + ('a, 'ac) ty -> + 'a -> + (Script.expr * context) tzresult Lwt.t + + (** [unparse_items ctxt ~stack_depth unparsing_mode kty vty assoc] returns the + Micheline representation of [assoc] (being an association list) with keys + of type [kty] and values of type [vty]. Gas is being consumed from + [ctxt]. *) + val unparse_items : + context -> + stack_depth:int -> + unparsing_mode -> + 'k comparable_ty -> + ('v, 'vc) ty -> + ('k * 'v) list -> + (Script.expr list * context) tzresult Lwt.t + + (** [unparse_code ctxt ~stack_depth unparsing_mode code] returns [code] + with [I_PUSH] instructions parsed and unparsed back to make sure that + only forgeable values are being pushed. The gas is being consumed from + [ctxt]. *) + val unparse_code : + context -> + stack_depth:int -> + unparsing_mode -> + Script.node -> + (Script.expr * context, error trace) result Lwt.t + + (** For benchmarking purpose, we also export versions of the unparsing + functions which don't call location stripping. These functions are + not carbonated and should not be called directly from the protocol. *) + module Internal_for_benchmarking : sig + val unparse_data : + context -> + stack_depth:int -> + unparsing_mode -> + ('a, 'ac) ty -> + 'a -> + (Script.node * context) tzresult Lwt.t + + val unparse_code : + context -> + stack_depth:int -> + unparsing_mode -> + Script.node -> + (Script.node * context) tzresult Lwt.t + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_list.ml b/src/proto_020_PsParisC/lib_protocol/script_list.ml new file mode 100644 index 000000000000..66d97bdbffbc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_list.ml @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type 'elt t = {elements : 'elt list; length : int} + +let of_list l = {elements = l; length = List.length l} [@@inline always] + +let to_list {elements; length = _} = elements [@@inline always] + +let empty : 'a t = {elements = []; length = 0} + +let cons : 'a -> 'a t -> 'a t = + fun elt l -> {length = 1 + l.length; elements = elt :: l.elements} + +let length {elements = _; length} = length [@@inline always] + +let uncons = function + | {elements = []; length = _} -> None + | {elements = hd :: tl; length} -> + Some (hd, {elements = tl; length = length - 1}) + +let rev {elements; length} = {elements = List.rev elements; length} + [@@inline always] diff --git a/src/proto_020_PsParisC/lib_protocol/script_list.mli b/src/proto_020_PsParisC/lib_protocol/script_list.mli new file mode 100644 index 000000000000..dbd19d6467c0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_list.mli @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type 'elt t = private {elements : 'elt list; length : int} + +(** Convert an OCaml list into Michelson list. *) +val of_list : 'a list -> 'a t + +(** Convert a Michelson list to an OCaml list. *) +val to_list : 'a t -> 'a list + +(** [length l] returns the number of elements in [l] as [int]. *) +val length : 'a t -> int + +(** Empty list. *) +val empty : 'a t + +(** Prepend an element. *) +val cons : 'a -> 'a t -> 'a t + +(** [uncons l] returns [Some (hd, tl)] where [hd :: tl = l] if [l] is + not empty or [None] otherwise. *) +val uncons : 'a t -> ('a * 'a t) option + +(** [rev l] returns a list containing all elements of [l] in reversed order. *) +val rev : 'a t -> 'a t diff --git a/src/proto_020_PsParisC/lib_protocol/script_map.ml b/src/proto_020_PsParisC/lib_protocol/script_map.ml new file mode 100644 index 000000000000..d5e5e4e819cd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_map.ml @@ -0,0 +1,147 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_typed_ir + +let make x = Map_tag x + +let get_module (Map_tag x) = x + +let empty_from : type a b c. (a, b) map -> (a, c) map = + fun (Map_tag (module Box)) -> + Map_tag + (module struct + type key = a + + type value = c + + module OPS = Box.OPS + + let boxed = OPS.empty + + let size = 0 + end) + +let empty : type a b. a comparable_ty -> (a, b) map = + fun ty -> + let module OPS = struct + let key_size = Gas_comparable_input_size.size_of_comparable_value ty + + include Map.Make (struct + type t = a + + let compare = Script_comparable.compare_comparable ty + end) + end in + Map_tag + (module struct + type key = a + + type value = b + + module OPS = OPS + + let boxed = OPS.empty + + let size = 0 + end) + +let get : type key value. key -> (key, value) map -> value option = + fun k (Map_tag (module Box)) -> Box.OPS.find k Box.boxed + +let update : type a b. a -> b option -> (a, b) map -> (a, b) map = + fun k v (Map_tag (module Box)) -> + let boxed, size = + let contains = + match Box.OPS.find k Box.boxed with None -> false | _ -> true + in + match v with + | Some v -> (Box.OPS.add k v Box.boxed, Box.size + if contains then 0 else 1) + | None -> (Box.OPS.remove k Box.boxed, Box.size - if contains then 1 else 0) + in + Map_tag + (module struct + type key = a + + type value = b + + module OPS = Box.OPS + + let boxed = boxed + + let size = size + end) + +let mem : type key value. key -> (key, value) map -> bool = + fun k (Map_tag (module Box)) -> + match Box.OPS.find k Box.boxed with None -> false | _ -> true + +let fold : + type key value acc. + (key -> value -> acc -> acc) -> (key, value) map -> acc -> acc = + fun f (Map_tag (module Box)) -> Box.OPS.fold f Box.boxed + +let fold_es : + type key value acc. + (key -> value -> acc -> acc tzresult Lwt.t) -> + (key, value) map -> + acc -> + acc tzresult Lwt.t = + fun f (Map_tag (module Box)) -> Box.OPS.fold_es f Box.boxed + +let size : type key value. (key, value) map -> Script_int.n Script_int.num = + fun (Map_tag (module Box)) -> Script_int.(abs (of_int Box.size)) + +let map_es_in_context : + type context key value value'. + (context -> key -> value -> (value' * context) tzresult Lwt.t) -> + context -> + (key, value) map -> + ((key, value') map * context) tzresult Lwt.t = + let open Lwt_result_syntax in + fun f ctxt (Map_tag (module Box)) -> + let+ map, ctxt = + Box.OPS.fold_es + (fun key value (map, ctxt) -> + let+ value, ctxt = f ctxt key value in + (Box.OPS.add key value map, ctxt)) + Box.boxed + (Box.OPS.empty, ctxt) + in + ( Map_tag + (module struct + type key = Box.key + + type value = value' + + module OPS = Box.OPS + + let boxed = map + + let size = Box.size + end), + ctxt ) diff --git a/src/proto_020_PsParisC/lib_protocol/script_map.mli b/src/proto_020_PsParisC/lib_protocol/script_map.mli new file mode 100644 index 000000000000..23fab2b979b6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_map.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Functions to ease the manipulation of Michelson maps. + + A map in Michelson is a type-homegeneous, partial function of keys to + values, along with the functions that operate on the structure (through a + first-class module). +*) + +open Script_typed_ir + +val make : + (module Boxed_map with type key = 'key and type value = 'value) -> + ('key, 'value) map + +val get_module : + ('key, 'value) map -> + (module Boxed_map with type key = 'key and type value = 'value) + +(** [empty cmp_ty] creates a map module where keys have size + [Gas_comparable_input_size.size_of_comparable_value cmp_ty] and are compared + with [Script_comparable.compare_comparable cmp_ty] (used for sorting keys, + which ensures a reasonable complexity of the map functions). + The function returns an empty map packaged as a first-class map module. *) +val empty : 'a comparable_ty -> ('a, 'b) map + +(** [empty_from map] creates an empty map module where the size of keys and the + comparison function are those of [map]. *) +val empty_from : ('a, 'b) map -> ('a, 'c) map + +val fold : + ('key -> 'value -> 'acc -> 'acc) -> ('key, 'value) map -> 'acc -> 'acc + +val fold_es : + ('key -> 'value -> 'acc -> 'acc tzresult Lwt.t) -> + ('key, 'value) map -> + 'acc -> + 'acc tzresult Lwt.t + +(** [update k (Some v) map] associates [v] to [k] in [map] (overwriting the + previous value, if any), and [update k None map] removes the potential + association to [k] in [map]. *) +val update : 'a -> 'b option -> ('a, 'b) map -> ('a, 'b) map + +val mem : 'key -> ('key, 'value) map -> bool + +val get : 'key -> ('key, 'value) map -> 'value option + +val size : ('a, 'b) map -> Script_int.n Script_int.num + +val map_es_in_context : + ('context -> 'key -> 'value1 -> ('value2 * 'context) tzresult Lwt.t) -> + 'context -> + ('key, 'value1) map -> + (('key, 'value2) map * 'context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/script_repr.ml b/src/proto_020_PsParisC/lib_protocol/script_repr.ml new file mode 100644 index 000000000000..8a9fd53c6865 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_repr.ml @@ -0,0 +1,320 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type location = Micheline.canonical_location + +let location_encoding = Micheline.canonical_location_encoding + +type annot = Micheline.annot + +type expr = Michelson_v1_primitives.prim Micheline.canonical + +type lazy_expr = expr Data_encoding.lazy_t + +type 'location michelson_node = + ('location, Michelson_v1_primitives.prim) Micheline.node + +type node = location michelson_node + +let expr_encoding = + Micheline.canonical_encoding + ~variant:"michelson_v1" + Michelson_v1_primitives.prim_encoding + +type error += Lazy_script_decode (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"invalid_binary_format" + ~title:"Invalid binary format" + ~description: + "Could not deserialize some piece of data from its binary representation" + ~pp:(fun fmt () -> + Format.fprintf + fmt + "Could not deserialize some piece of data from its binary \ + representation") + Data_encoding.empty + (function Lazy_script_decode -> Some () | _ -> None) + (fun () -> Lazy_script_decode) + +let lazy_expr_encoding = Data_encoding.lazy_encoding expr_encoding + +let lazy_expr expr = Data_encoding.make_lazy expr_encoding expr + +type t = {code : lazy_expr; storage : lazy_expr} + +let encoding = + let open Data_encoding in + def "scripted.contracts" + @@ conv + (fun {code; storage} -> (code, storage)) + (fun (code, storage) -> {code; storage}) + (obj2 (req "code" lazy_expr_encoding) (req "storage" lazy_expr_encoding)) + +module S = Saturation_repr + +module Micheline_size = struct + type t = { + nodes : S.may_saturate S.t; + string_bytes : S.may_saturate S.t; + z_bytes : S.may_saturate S.t; + } + + let zero = {nodes = S.zero; string_bytes = S.zero; z_bytes = S.zero} + + let add_int acc n = + let numbits = Z.numbits n in + let z_bytes = + S.safe_int ((numbits + 7) / 8) + (* Compute the number of bytes in a Z.t *) + in + { + nodes = S.succ acc.nodes; + string_bytes = acc.string_bytes; + z_bytes = S.add acc.z_bytes z_bytes; + } + + let add_string acc n = + let string_bytes = S.safe_int (String.length n) in + { + nodes = S.succ acc.nodes; + string_bytes = S.add acc.string_bytes string_bytes; + z_bytes = acc.z_bytes; + } + + let add_bytes acc n = + let string_bytes = S.safe_int (Bytes.length n) in + { + nodes = S.succ acc.nodes; + string_bytes = S.add acc.string_bytes string_bytes; + z_bytes = acc.z_bytes; + } + + let add_node s = {s with nodes = S.succ s.nodes} + + (* We model annotations as Seqs of Strings *) + let of_annots acc annots = + List.fold_left (fun acc s -> add_string acc s) acc annots + + let rec of_nodes acc nodes more_nodes = + let open Micheline in + match nodes with + | [] -> ( + match more_nodes with + | [] -> acc + | nodes :: more_nodes -> + (of_nodes [@ocaml.tailcall]) acc nodes more_nodes) + | Int (_, n) :: nodes -> + let acc = add_int acc n in + (of_nodes [@ocaml.tailcall]) acc nodes more_nodes + | String (_, s) :: nodes -> + let acc = add_string acc s in + (of_nodes [@ocaml.tailcall]) acc nodes more_nodes + | Bytes (_, s) :: nodes -> + let acc = add_bytes acc s in + (of_nodes [@ocaml.tailcall]) acc nodes more_nodes + | Prim (_, _, args, annots) :: nodes -> + let acc = add_node acc in + let acc = of_annots acc annots in + (of_nodes [@ocaml.tailcall]) acc args (nodes :: more_nodes) + | Seq (_, args) :: nodes -> + let acc = add_node acc in + (of_nodes [@ocaml.tailcall]) acc args (nodes :: more_nodes) + + let of_node node = of_nodes zero [node] [] +end + +(* Costs pertaining to deserialization of Micheline values (bytes to Micheline). + The costs are given in atomic steps (see [Gas_limit_repr]). *) +module Micheline_decoding = struct + (* Cost vector allowing to compute decoding costs as a function of the + size of the Micheline term *) + let micheline_size_dependent_cost + ({nodes; string_bytes; z_bytes} : Micheline_size.t) = + Script_repr_costs.cost_DECODING_MICHELINE nodes z_bytes string_bytes + + let bytes_dependent_cost = Script_repr_costs.cost_DECODING_MICHELINE_bytes +end + +(* Costs pertaining to serialization of Micheline values (Micheline to bytes) + The costs are given in atomic steps (see [Gas_limit_repr]). *) +module Micheline_encoding = struct + (* Cost vector allowing to compute encoding cost as a function of the + size of the Micheline term *) + let micheline_size_dependent_cost + ({nodes; string_bytes; z_bytes} : Micheline_size.t) = + Script_repr_costs.cost_ENCODING_MICHELINE nodes z_bytes string_bytes + + let bytes_dependent_cost = Script_repr_costs.cost_ENCODING_MICHELINE_bytes +end + +let expr_size expr = Micheline_size.of_node (Micheline.root expr) + +(* Compute the cost of serializing a term of given [size]. *) +let serialization_cost size = + Gas_limit_repr.atomic_step_cost + @@ Micheline_encoding.micheline_size_dependent_cost size + +(* Compute the cost of serializing a given term. *) +let micheline_serialization_cost v = serialization_cost (expr_size v) + +(* Compute the cost of deserializing a term of given [size]. *) +let deserialization_cost size = + Gas_limit_repr.atomic_step_cost + @@ Micheline_decoding.micheline_size_dependent_cost size + +(* Estimate the cost of deserializing a term encoded in [bytes_len] bytes. *) +let deserialization_cost_estimated_from_bytes bytes_len = + Gas_limit_repr.atomic_step_cost + @@ Micheline_decoding.bytes_dependent_cost (S.safe_int bytes_len) + +(* Estimate the cost of serializing a term from its encoded form, + having [bytes_len] bytes. *) +let serialization_cost_estimated_from_bytes bytes_len = + Gas_limit_repr.atomic_step_cost + @@ Micheline_encoding.bytes_dependent_cost (S.safe_int bytes_len) + +let cost_micheline_strip_locations size = + Gas_limit_repr.atomic_step_cost + @@ Script_repr_costs.cost_strip_locations_micheline size + +let cost_micheline_strip_annotations size = + Gas_limit_repr.atomic_step_cost + @@ Script_repr_costs.cost_strip_annotations size + +(* This is currently used to estimate the cost of serializing an operation. *) +let bytes_node_cost s = serialization_cost_estimated_from_bytes (Bytes.length s) + +let deserialized_cost expr = + Gas_limit_repr.atomic_step_cost @@ deserialization_cost (expr_size expr) + +let force_decode_cost lexpr = + Data_encoding.apply_lazy + ~fun_value:(fun _ -> Gas_limit_repr.free) + ~fun_bytes:(fun b -> + deserialization_cost_estimated_from_bytes (Bytes.length b)) + ~fun_combine:(fun _ _ -> Gas_limit_repr.free) + lexpr + +let stable_force_decode_cost lexpr = + let has_bytes = + Data_encoding.apply_lazy + ~fun_value:(fun v -> `Only_value v) + ~fun_bytes:(fun b -> `Has_bytes b) + ~fun_combine:(fun _v b -> + (* When the lazy_expr contains both a deserialized version + and a serialized one, we compute the cost from the + serialized version because its is cheaper to do. *) + b) + lexpr + in + match has_bytes with + | `Has_bytes b -> deserialization_cost_estimated_from_bytes (Bytes.length b) + | `Only_value v -> + (* This code path should not be reached in theory because values that are + decoded should have been encoded before. + Here we use Data_encoding.Binary.length, which yields the same results + as serializing the value and taking the size, without the need to + encode (in particular, less allocations). + *) + deserialization_cost_estimated_from_bytes + (Data_encoding.Binary.length expr_encoding v) + +let force_decode lexpr = + let open Result_syntax in + match Data_encoding.force_decode lexpr with + | Some v -> return v + | None -> tzfail Lazy_script_decode + +let force_bytes_cost expr = + (* Estimating the cost directly from the bytes would be cheaper, but + using [serialization_cost] is more accurate. *) + Data_encoding.apply_lazy + ~fun_value:(fun v -> Some v) + ~fun_bytes:(fun _ -> None) + ~fun_combine:(fun _ _ -> None) + expr + |> Option.fold ~none:Gas_limit_repr.free ~some:micheline_serialization_cost + +let force_bytes expr = + Error_monad.catch_f + (fun () -> Data_encoding.force_bytes expr) + (fun _ -> Lazy_script_decode) + +let unit = + Micheline.strip_locations (Prim (0, Michelson_v1_primitives.D_Unit, [], [])) + +let unit_parameter = lazy_expr unit + +let is_unit v = + match Micheline.root v with + | Prim (_, Michelson_v1_primitives.D_Unit, [], []) -> true + | _ -> false + +let is_unit_parameter = + let unit_bytes = Data_encoding.force_bytes unit_parameter in + Data_encoding.apply_lazy + ~fun_value:is_unit + ~fun_bytes:(fun b -> Compare.Bytes.equal b unit_bytes) + ~fun_combine:(fun res _ -> res) + +let rec strip_annotations node = + let open Micheline in + match node with + | (Int (_, _) | String (_, _) | Bytes (_, _)) as leaf -> leaf + | Prim (loc, name, args, _) -> + Prim (loc, name, List.map strip_annotations args, []) + | Seq (loc, args) -> Seq (loc, List.map strip_annotations args) + +let rec micheline_fold_aux node f acc k = + match node with + | Micheline.Int (_, _) -> k (f acc node) + | Micheline.String (_, _) -> k (f acc node) + | Micheline.Bytes (_, _) -> k (f acc node) + | Micheline.Prim (_, _, subterms, _) -> + micheline_fold_nodes subterms f (f acc node) k + | Micheline.Seq (_, subterms) -> + micheline_fold_nodes subterms f (f acc node) k + +and micheline_fold_nodes subterms f acc k = + match subterms with + | [] -> k acc + | node :: nodes -> + micheline_fold_nodes nodes f acc @@ fun acc -> + micheline_fold_aux node f acc k + +let fold node init f = micheline_fold_aux node f init (fun x -> x) + +let micheline_nodes node = fold node 0 @@ fun n _ -> n + 1 + +let strip_locations_cost node = + let nodes = micheline_nodes node in + cost_micheline_strip_locations nodes + +let strip_annotations_cost node = + let nodes = micheline_nodes node in + cost_micheline_strip_annotations nodes diff --git a/src/proto_020_PsParisC/lib_protocol/script_repr.mli b/src/proto_020_PsParisC/lib_protocol/script_repr.mli new file mode 100644 index 000000000000..97f5b0a4db0f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_repr.mli @@ -0,0 +1,137 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Defines a Michelson expression representation as a Micheline node with + canonical ([int]) location and [Michelson_v1_primitives.prim] as content. + + Types [expr] and [node] both define representation of Michelson + expressions and are indeed the same type internally, although this is not + visible outside Micheline due to interface abstraction. *) + +(** Locations are used by Micheline mostly for error-reporting and pretty- + printing expressions. [canonical_location] is simply an [int]. *) +type location = Micheline.canonical_location + +(** Annotations attached to Michelson expressions. *) +type annot = Micheline.annot + +(** Represents a Michelson expression as canonical Micheline. *) +type expr = Michelson_v1_primitives.prim Micheline.canonical + +type error += Lazy_script_decode (* `Permanent *) + +(** A record containing either an underlying serialized representation of an + expression or a deserialized one, or both. If either is absent, it will be + computed on-demand. *) +type lazy_expr = expr Data_encoding.lazy_t + +type 'location michelson_node = + ('location, Michelson_v1_primitives.prim) Micheline.node + +(** Same as [expr], but used in different contexts, as required by Micheline's + abstract interface. *) +type node = location michelson_node + +val location_encoding : location Data_encoding.t + +val expr_encoding : expr Data_encoding.t + +val lazy_expr_encoding : lazy_expr Data_encoding.t + +val lazy_expr : expr -> lazy_expr + +(** Type [t] joins the contract's code and storage in a single record. *) +type t = {code : lazy_expr; storage : lazy_expr} + +val encoding : t Data_encoding.encoding + +(* Basic gas costs of operations related to processing Michelson: *) + +val deserialization_cost_estimated_from_bytes : int -> Gas_limit_repr.cost + +val deserialized_cost : expr -> Gas_limit_repr.cost + +val bytes_node_cost : bytes -> Gas_limit_repr.cost + +(** Returns (a lower bound on) the cost to deserialize a + {!type-lazy_expr}. If the expression has already been deserialized + (i.e. the lazy expression contains the deserialized value or both + the bytes representation and the deserialized value) then the cost + is {b free}. *) +val force_decode_cost : lazy_expr -> Gas_limit_repr.cost + +(** Like {!force_decode_cost}, excepted that the returned cost does + not depend on the internal state of the lazy_expr. This means that + the cost is never free (excepted for zero bytes expressions). *) +val stable_force_decode_cost : lazy_expr -> Gas_limit_repr.cost + +val force_decode : lazy_expr -> expr tzresult + +(** Returns the cost to serialize a {!type-lazy_expr}. If the expression + has already been deserialized (i.e. le lazy expression contains the + bytes representation or both the bytes representation and the + deserialized value) then the cost is {b free}. *) +val force_bytes_cost : lazy_expr -> Gas_limit_repr.cost + +val force_bytes : lazy_expr -> bytes tzresult + +val unit : expr + +val unit_parameter : lazy_expr + +val is_unit : expr -> bool + +val is_unit_parameter : lazy_expr -> bool + +val strip_annotations : node -> node + +val strip_locations_cost : _ michelson_node -> Gas_limit_repr.cost + +val strip_annotations_cost : node -> Gas_limit_repr.cost + +(** Computes the cost of serializing a given term. *) +val micheline_serialization_cost : expr -> Gas_limit_repr.cost + +module Micheline_size : sig + type t = { + nodes : Saturation_repr.may_saturate Saturation_repr.t; + string_bytes : Saturation_repr.may_saturate Saturation_repr.t; + z_bytes : Saturation_repr.may_saturate Saturation_repr.t; + } + + val of_node : node -> t +end + +(** [micheline_nodes root] returns the number of internal nodes in the + micheline expression held from [root]. *) +val micheline_nodes : node -> int + +(** [fold node i f] traverses [node] applying [f] on an + accumulator initialized by [i]. *) +val fold : + ('loc, 'prim) Micheline.node -> + 'acc -> + ('acc -> ('loc, 'prim) Micheline.node -> 'acc) -> + 'acc diff --git a/src/proto_020_PsParisC/lib_protocol/script_repr_costs.ml b/src/proto_020_PsParisC/lib_protocol/script_repr_costs.ml new file mode 100644 index 000000000000..9316828b839d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_repr_costs.ml @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Script_repr_costs_generated + +(* Cost of running [strip_locations] on a term with [size] nodes. + Note that [strip_locations] will reallocate a fresh Micheline tree. + This only depends on the total number of nodes (not the size of + the leaves). + + let cost_strip_locations_micheline = cost_strip_locations_micheline +*) + +(* Cost of running [strip_annotations] on a term with [size] nodes. + Note that [strip_annotations] will reallocate a fresh Micheline tree. + This only depends on the total number of nodes (not the size of + the leaves). + + let cost_strip_annotations = cost_strip_annotations +*) diff --git a/src/proto_020_PsParisC/lib_protocol/script_repr_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/script_repr_costs_generated.ml new file mode 100644 index 000000000000..5b97f2ebcd6e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_repr_costs_generated.ml @@ -0,0 +1,58 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model encoding/DECODING_MICHELINE *) +(* fun size1 -> + fun size2 -> + fun size3 -> max 10 (((60. * size1) + (10. * size2)) + (10. * size3)) *) +let cost_DECODING_MICHELINE size1 size2 size3 = + S.max + (S.safe_int 10) + ((size1 * S.safe_int 60) + (size2 * S.safe_int 10) + (size3 * S.safe_int 10)) + +(* model encoding/DECODING_MICHELINE_bytes *) +(* fun size -> max 10 (20. * size) *) +let cost_DECODING_MICHELINE_bytes size = + S.max (S.safe_int 10) (size * S.safe_int 20) + +(* model encoding/ENCODING_MICHELINE *) +(* fun size1 -> + fun size2 -> + fun size3 -> max 10 (((100. * size1) + (25. * size2)) + (10. * size3)) *) +let cost_ENCODING_MICHELINE size1 size2 size3 = + S.max + (S.safe_int 10) + ((size1 * S.safe_int 100) + + (size2 * S.safe_int 25) + + (size3 * S.safe_int 10)) + +(* model encoding/ENCODING_MICHELINE_bytes *) +(* fun size -> max 10 (33. * size) *) +let cost_ENCODING_MICHELINE_bytes size = + S.max (S.safe_int 10) (size * S.safe_int 33) + +(* model micheline/strip_locations_micheline *) +(* fun size -> max 10 (51. * size) *) +let cost_strip_locations_micheline size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 51) + +(* model script_repr/MICHELINE_NODES *) +(* fun size -> max 10 (0. + (6.4928521501 * size)) *) +let cost_MICHELINE_NODES size = + let size = S.safe_int size in + S.max (S.safe_int 10) ((size lsr 1) + (size * S.safe_int 6)) + +(* model script_repr/strip_annotations *) +(* fun size -> max 10 (51. * size) *) +let cost_strip_annotations size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 51) diff --git a/src/proto_020_PsParisC/lib_protocol/script_set.ml b/src/proto_020_PsParisC/lib_protocol/script_set.ml new file mode 100644 index 000000000000..c18824cdb973 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_set.ml @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_typed_ir + +let make x = Set_tag x + +let get (Set_tag x) = x + +let empty : type a. a comparable_ty -> a set = + fun ty -> + let module OPS : Boxed_set_OPS with type elt = a = struct + let elt_size = Gas_comparable_input_size.size_of_comparable_value ty + + include Set.Make (struct + type t = a + + let compare = Script_comparable.compare_comparable ty + end) + end in + Set_tag + (module struct + type elt = a + + module OPS = OPS + + let boxed = OPS.empty + + let size = 0 + end) + +let update : type a. a -> bool -> a set -> a set = + fun v b (Set_tag (module Box)) -> + Set_tag + (module struct + type elt = a + + module OPS = Box.OPS + + let boxed = + if b then Box.OPS.add v Box.boxed else Box.OPS.remove v Box.boxed + + let size = + let mem = Box.OPS.mem v Box.boxed in + if mem then if b then Box.size else Box.size - 1 + else if b then Box.size + 1 + else Box.size + end) + +let mem : type elt. elt -> elt set -> bool = + fun v (Set_tag (module Box)) -> Box.OPS.mem v Box.boxed + +let fold : type elt acc. (elt -> acc -> acc) -> elt set -> acc -> acc = + fun f (Set_tag (module Box)) -> Box.OPS.fold f Box.boxed + +let size : type elt. elt set -> Script_int.n Script_int.num = + fun (Set_tag (module Box)) -> Script_int.(abs (of_int Box.size)) diff --git a/src/proto_020_PsParisC/lib_protocol/script_set.mli b/src/proto_020_PsParisC/lib_protocol/script_set.mli new file mode 100644 index 000000000000..bffb228a0752 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_set.mli @@ -0,0 +1,57 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Functions to ease the manipulation of sets of values in Michelson. + + A set in Michelson is a collection of type-homegeneous values along with the + functions that operate on the structure (through a first-class module). In + particular, the {!size} function runs in constant time. +*) + +open Script_typed_ir + +val make : (module Boxed_set with type elt = 'elt) -> 'elt set + +val get : 'elt set -> (module Boxed_set with type elt = 'elt) + +(** [empty cmp_ty] creates a set module where elements have size + [Gas_comparable_input_size.size_of_comparable_value cmp_ty] and are compared + with [Script_comparable.compare_comparable cmp_ty] (used for sorting values, + which ensures a reasonable complexity of the set functions). + The function returns an empty set packaged as a first-class set module. *) +val empty : 'a comparable_ty -> 'a set + +val fold : ('elt -> 'acc -> 'acc) -> 'elt set -> 'acc -> 'acc + +(** [update v true set] adds [v] to [set], and [update v false set] removes [v] + from [set]. *) +val update : 'a -> bool -> 'a set -> 'a set + +val mem : 'elt -> 'elt set -> bool + +(** [size set] runs in constant time. *) +val size : 'elt set -> Script_int.n Script_int.num diff --git a/src/proto_020_PsParisC/lib_protocol/script_string.ml b/src/proto_020_PsParisC/lib_protocol/script_string.ml new file mode 100644 index 000000000000..cd1272372b24 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_string.ml @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Strings of printable characters *) + +type repr = string (* Invariant: contains only printable characters *) + +type t = String_tag of repr [@@ocaml.unboxed] + +type error += Non_printable_character of (int * string) + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"michelson_v1.non_printable_character" + ~title:"Non printable character in a Michelson string" + ~description: + "Michelson strings are only allowed to contain printable characters \ + (either the newline character or characters in the [32, 126] ASCII \ + range)." + ~pp:(fun ppf (pos, s) -> + Format.fprintf + ppf + "In Michelson string \"%s\", character at position %d has ASCII code \ + %d. Expected: either a newline character (ASCII code 10) or a \ + printable character (ASCII code between 32 and 126)." + s + pos + (Char.code s.[pos])) + (obj2 (req "position" int31) (req "string" (string Plain))) + (function Non_printable_character (pos, s) -> Some (pos, s) | _ -> None) + (fun (pos, s) -> Non_printable_character (pos, s)) + +let empty = String_tag "" + +let of_string v = + let open Result_syntax in + let rec check_printable_ascii i = + if Compare.Int.(i < 0) then return (String_tag v) + else + match v.[i] with + | '\n' | '\x20' .. '\x7E' -> check_printable_ascii (i - 1) + | _ -> tzfail @@ Non_printable_character (i, v) + in + check_printable_ascii (String.length v - 1) + +let to_string (String_tag s) = s + +let compare (String_tag x) (String_tag y) = Compare.String.compare x y + +let length (String_tag s) = String.length s + +let concat_pair (String_tag x) (String_tag y) = String_tag (x ^ y) + +let concat l = + let l = List.map (fun (String_tag s) -> s) l in + String_tag (String.concat "" l) + +let sub (String_tag s) offset length = String_tag (String.sub s offset length) diff --git a/src/proto_020_PsParisC/lib_protocol/script_string.mli b/src/proto_020_PsParisC/lib_protocol/script_string.mli new file mode 100644 index 000000000000..e76a3b15e67c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_string.mli @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Strings of printable characters *) + +type repr + +(** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) +type t = String_tag of repr [@@ocaml.unboxed] + +type error += Non_printable_character of (int * string) + +val empty : t + +val of_string : string -> t tzresult + +val to_string : t -> string + +val compare : t -> t -> int + +val length : t -> int + +val concat_pair : t -> t -> t + +val concat : t list -> t + +val sub : t -> int -> int -> t diff --git a/src/proto_020_PsParisC/lib_protocol/script_tc_context.ml b/src/proto_020_PsParisC/lib_protocol/script_tc_context.ml new file mode 100644 index 000000000000..419eb38d7648 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_tc_context.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_typed_ir + +type in_lambda = bool + +type callsite = + | Toplevel : { + storage_type : ('sto, _) ty; + param_type : ('param, _) ty; + entrypoints : 'param Script_typed_ir.entrypoints; + } + -> callsite + | View : callsite + | Data : callsite + +type t = {callsite : callsite; in_lambda : in_lambda} + +let init callsite = {callsite; in_lambda = false} + +let toplevel ~storage_type ~param_type ~entrypoints = + init (Toplevel {storage_type; param_type; entrypoints}) + +let view = init View + +(* [data] is prefered over [toplevel] outside [Script_ir_translator], because + [toplevel] needs to setup a lot of information. *) +let data = init Data + +let add_lambda tc_context = {tc_context with in_lambda = true} + +let is_in_lambda {callsite = _; in_lambda} = in_lambda + +let check_not_in_view loc ~legacy tc_context prim = + let open Result_syntax in + match tc_context.callsite with + (* The forbidden (stateful) instructions in views are in facts allowed in + lambdas in views, because they could be returned to the caller, and then + executed on his responsibility. *) + | Toplevel _ | Data -> return_unit + | View + when is_in_lambda tc_context + || legacy (* Legacy check introduced in Jakarta *) -> + return_unit + | View -> + tzfail Script_tc_errors.(Forbidden_instr_in_context (loc, View, prim)) diff --git a/src/proto_020_PsParisC/lib_protocol/script_tc_context.mli b/src/proto_020_PsParisC/lib_protocol/script_tc_context.mli new file mode 100644 index 000000000000..14f907133edd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_tc_context.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_typed_ir + +(** This module defines the typechecking context used during the translation + from Michelson untyped nodes to typed nodes ([Script_ir_translator]). + The context keeps track of the origin of the code (top-level from a contract, + in a view, etc.), plus some information to allow or forbid instructions + given the context (no `SELF` in a lambda for example). *) + +(** Lambdas are a bit special when considering stateful instructions such as + [TRANSFER_TOKENS]. + For instance, a view containing a [TRANSFER_TOKENS] is not OK, because + calling the view would transfer tokens from the view's owner. + However, a view returning a lambda containing a [TRANSFER_TOKENS] could be + considered OK, as the decision whether to execute it or not falls on + the view's caller, whose tokens would be transfered. + This type is used to keep track of whether we are inside a lambda: it is + [true] when inside a lambda, and [false] otherwise. *) +type in_lambda = bool + +(** The calling context when parsing Michelson code: either a top-level contract + code, the code of a view, or code in data (when pushing a block of + instructions for example). *) +type callsite = + | Toplevel : { + storage_type : ('sto, _) ty; + param_type : ('param, _) ty; + entrypoints : 'param Script_typed_ir.entrypoints; + } + -> callsite + | View : callsite + | Data : callsite + +type t = {callsite : callsite; in_lambda : in_lambda} + +val init : callsite -> t + +val toplevel : + storage_type:('sto, _) ty -> + param_type:('param, _) ty -> + entrypoints:'param Script_typed_ir.entrypoints -> + t + +val view : t + +(** This value can be used outside the translation module as a simple context + when testing code, for example. *) +val data : t + +val add_lambda : t -> t + +val is_in_lambda : t -> bool + +val check_not_in_view : + Script.location -> legacy:bool -> t -> Script.prim -> unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/script_tc_errors.ml b/src/proto_020_PsParisC/lib_protocol/script_tc_errors.ml new file mode 100644 index 000000000000..d3e8855e3807 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_tc_errors.ml @@ -0,0 +1,226 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script + +(* ---- Error definitions ---------------------------------------------------*) + +type kind = Int_kind | String_kind | Bytes_kind | Prim_kind | Seq_kind + +type unparsed_stack_ty = Script.expr list + +type type_map = (Script.location * (unparsed_stack_ty * unparsed_stack_ty)) list + +(* Structure errors *) +type error += Invalid_arity of Script.location * prim * int * int + +type error += Invalid_seq_arity of Script.location * int * int + +type error += + | Invalid_namespace of + Script.location + * prim + * Michelson_v1_primitives.namespace + * Michelson_v1_primitives.namespace + +type error += Invalid_primitive of Script.location * prim list * prim + +type error += Invalid_kind of Script.location * kind list * kind + +type error += Invalid_never_expr of Script.location + +type error += Missing_field of prim + +type error += Duplicate_field of Script.location * prim + +type error += Unexpected_lazy_storage of Script.location + +type error += Unexpected_operation of Script.location + +type error += Unexpected_contract of Script.location + +type error += No_such_entrypoint of Entrypoint.t + +type error += Duplicate_entrypoint of Entrypoint.t + +type error += Unreachable_entrypoint of prim list + +(* Transaction rollup errors *) + +type error += Tx_rollup_bad_deposit_parameter of Script.location * Script.expr + +type error += Tx_rollup_invalid_ticket_amount of Z.t + +type error += Forbidden_zero_ticket_quantity + +(* Smart-contract rollup errors *) + +type error += Sc_rollup_disabled of Script.location + +(* Zero Knowledge rollup errors *) + +type error += Zk_rollup_disabled of Script.location + +type error += Zk_rollup_bad_deposit_parameter of Script.location * Script.expr + +(* Instruction typing errors *) +type error += Fail_not_in_tail_position of Script.location + +type error += + | Undefined_binop : + Script.location * prim * Script.expr * Script.expr + -> error + +type error += Undefined_unop : Script.location * prim * Script.expr -> error + +type error += + | Bad_return : Script.location * unparsed_stack_ty * Script.expr -> error + +type error += + | Bad_stack : Script.location * prim * int * unparsed_stack_ty -> error + +type error += + | Unmatched_branches : + Script.location * unparsed_stack_ty * unparsed_stack_ty + -> error + +(* View errors *) +type error += View_name_too_long of string + +type error += Bad_view_name of Script.location + +type error += + | Ill_typed_view of { + loc : Script.location; + actual : unparsed_stack_ty; + expected : unparsed_stack_ty; + } + +type error += Duplicated_view_name of Script.location + +type context_desc = Lambda | View + +type error += + | Forbidden_instr_in_context of Script.location * context_desc * prim + +type error += Bad_stack_length + +type error += Bad_stack_item of int + +type error += Unexpected_annotation of Script.location + +type error += Ungrouped_annotations of Script.location + +type error += Invalid_map_body : Script.location * unparsed_stack_ty -> error + +type error += Invalid_map_block_fail of Script.location + +type error += + | Invalid_iter_body : + Script.location * unparsed_stack_ty * unparsed_stack_ty + -> error + +type error += Type_too_large : Script.location * int -> error + +type error += Pair_bad_argument of Script.location + +type error += Unpair_bad_argument of Script.location + +type error += Dup_n_bad_argument of Script.location + +type error += Dup_n_bad_stack of Script.location + +(* Value typing errors *) +type error += + | Invalid_constant : Script.location * Script.expr * Script.expr -> error + +type error += + | Invalid_syntactic_constant : Script.location * Script.expr * string -> error + +type error += Invalid_contract of Script.location * Contract.t + +type error += Invalid_big_map of Script.location * Big_map.Id.t + +type error += Comparable_type_expected : Script.location * Script.expr -> error + +type error += Inconsistent_type_sizes : int * int -> error + +type error += + | Inconsistent_types : Script.location * Script.expr * Script.expr -> error + +type error += + | Unexpected_implicit_account_parameters_type : + Script.location * Script.expr + -> error + +type error += + | Inconsistent_memo_sizes : Sapling.Memo_size.t * Sapling.Memo_size.t -> error + +type error += Unordered_map_keys of Script.location * Script.expr + +type error += Unordered_set_values of Script.location * Script.expr + +type error += Duplicate_map_keys of Script.location * Script.expr + +type error += Duplicate_set_values of Script.location * Script.expr + +(* Toplevel errors *) +type error += + | Ill_typed_data : string option * Script.expr * Script.expr -> error + +type error += Ill_formed_type of string option * Script.expr * Script.location + +type error += Ill_typed_contract : Script.expr * type_map -> error + +(* Deprecation errors *) +type error += Deprecated_instruction of prim + +(* Stackoverflow errors *) +type error += Typechecking_too_many_recursive_calls + +type error += Unparsing_too_many_recursive_calls + +(* Ticket errors *) +type error += Unexpected_ticket of Script.location + +type error += Unexpected_forged_value of Script.location + +type error += Non_dupable_type of Script.location * Script.expr + +type error += Unexpected_ticket_owner of Destination.t + +(* Merge type errors *) + +type inconsistent_types_fast_error = + | Inconsistent_types_fast + (** This value is only used when the details of the error don't matter because +the error will be ignored later. For example, when types are compared during +the interpretation of the [CONTRACT] instruction any error will lead to +returning [None] but the content of the error will be ignored. *) + +type (_, _) error_details = + | Informative : 'error_context -> ('error_context, error trace) error_details + | Fast : (_, inconsistent_types_fast_error) error_details diff --git a/src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.ml b/src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.ml new file mode 100644 index 000000000000..a24e2c6545bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.ml @@ -0,0 +1,832 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script +open Script_tc_errors + +(* Helpers for encoding *) +let stack_ty_enc = Data_encoding.list Script.expr_encoding + +let type_map_enc = + let open Data_encoding in + list + (conv + (fun (loc, (bef, aft)) -> (loc, bef, aft)) + (fun (loc, bef, aft) -> (loc, (bef, aft))) + (obj3 + (req "location" Script.location_encoding) + (req "stack_before" stack_ty_enc) + (req "stack_after" stack_ty_enc))) + +(* main registration *) +let () = + let open Data_encoding in + let located enc = + merge_objs (obj1 (req "location" Script.location_encoding)) enc + in + let arity_enc = int8 in + let namespace_enc = + def + "primitiveNamespace" + ~title:"Primitive namespace" + ~description: + "One of the five possible namespaces of primitive (data constructor, \ + type name, instruction, keyword, or constant hash)." + @@ string_enum + [ + ("type", Michelson_v1_primitives.Type_namespace); + ("constant", Constant_namespace); + ("instruction", Instr_namespace); + ("keyword", Keyword_namespace); + ("constant_hash", Constant_hash_namespace); + ] + in + let kind_enc = + def + "expressionKind" + ~title:"Expression kind" + ~description: + "One of the four possible kinds of expression (integer, string, \ + primitive application or sequence)." + @@ string_enum + [ + ("integer", Int_kind); + ("string", String_kind); + ("bytes", Bytes_kind); + ("primitiveApplication", Prim_kind); + ("sequence", Seq_kind); + ] + in + let context_desc_enc = + let open Data_encoding in + def "michelson_v1.context_desc" + @@ string_enum [("Lambda", Lambda); ("View", View)] + in + (* -- Structure errors ---------------------- *) + (* Invalid arity *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_arity" + ~title:"Invalid arity" + ~description: + "In a script or data expression, a primitive was applied to an \ + unsupported number of arguments." + (located + (obj3 + (req "primitive_name" Script.prim_encoding) + (req "expected_arity" arity_enc) + (req "wrong_arity" arity_enc))) + (function + | Invalid_arity (loc, name, exp, got) -> Some (loc, (name, exp, got)) + | _ -> None) + (fun (loc, (name, exp, got)) -> Invalid_arity (loc, name, exp, got)) ; + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_seq_arity" + ~title:"Invalid sequence arity" + ~description: + "In a script or data expression, a sequence was used with a number of \ + elements too small." + (located + (obj2 + (req "minimal_expected_arity" arity_enc) + (req "wrong_arity" arity_enc))) + (function + | Invalid_seq_arity (loc, exp, got) -> Some (loc, (exp, got)) | _ -> None) + (fun (loc, (exp, got)) -> Invalid_seq_arity (loc, exp, got)) ; + (* Missing field *) + register_error_kind + `Permanent + ~id:"michelson_v1.missing_script_field" + ~title:"Script is missing a field (parse error)" + ~description:"When parsing script, a field was expected, but not provided" + (obj1 (req "prim" prim_encoding)) + (function Missing_field prim -> Some prim | _ -> None) + (fun prim -> Missing_field prim) ; + (* Invalid primitive *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive" + ~title:"Invalid primitive" + ~description:"In a script or data expression, a primitive was unknown." + (located + (obj2 + (dft "expected_primitive_names" (list prim_encoding) []) + (req "wrong_primitive_name" prim_encoding))) + (function + | Invalid_primitive (loc, exp, got) -> Some (loc, (exp, got)) | _ -> None) + (fun (loc, (exp, got)) -> Invalid_primitive (loc, exp, got)) ; + (* Invalid kind *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_expression_kind" + ~title:"Invalid expression kind" + ~description: + "In a script or data expression, an expression was of the wrong kind \ + (for instance a string where only a primitive applications can appear)." + (located + (obj2 (req "expected_kinds" (list kind_enc)) (req "wrong_kind" kind_enc))) + (function + | Invalid_kind (loc, exp, got) -> Some (loc, (exp, got)) | _ -> None) + (fun (loc, (exp, got)) -> Invalid_kind (loc, exp, got)) ; + (* Invalid namespace *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_primitive_namespace" + ~title:"Invalid primitive namespace" + ~description: + "In a script or data expression, a primitive was of the wrong namespace." + (located + (obj3 + (req "primitive_name" prim_encoding) + (req "expected_namespace" namespace_enc) + (req "wrong_namespace" namespace_enc))) + (function + | Invalid_namespace (loc, name, exp, got) -> Some (loc, (name, exp, got)) + | _ -> None) + (fun (loc, (name, exp, got)) -> Invalid_namespace (loc, name, exp, got)) ; + (* Invalid literal for type never *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_never_expr" + ~title:"Invalid expression for type never" + ~description: + "In a script or data expression, an expression was provided but a value \ + of type never was expected. No expression can have type never." + (located unit) + (function Invalid_never_expr loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Invalid_never_expr loc) ; + (* Duplicate field *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_script_field" + ~title:"Script has a duplicated field (parse error)" + ~description:"When parsing script, a field was found more than once" + (obj2 (req "loc" location_encoding) (req "prim" prim_encoding)) + (function Duplicate_field (loc, prim) -> Some (loc, prim) | _ -> None) + (fun (loc, prim) -> Duplicate_field (loc, prim)) ; + (* Unexpected big_map *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_lazy_storage" + ~title:"Lazy storage in unauthorized position (type error)" + ~description: + "When parsing script, a big_map or sapling_state type was found in a \ + position where it could end up stored inside a big_map, which is \ + forbidden for now." + (obj1 (req "loc" location_encoding)) + (function Unexpected_lazy_storage loc -> Some loc | _ -> None) + (fun loc -> Unexpected_lazy_storage loc) ; + (* Unexpected operation *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_operation" + ~title:"Operation in unauthorized position (type error)" + ~description: + "When parsing script, an operation type was found in the storage or \ + parameter field." + (obj1 (req "loc" location_encoding)) + (function Unexpected_operation loc -> Some loc | _ -> None) + (fun loc -> Unexpected_operation loc) ; + (* No such entrypoint *) + register_error_kind + `Permanent + ~id:"michelson_v1.no_such_entrypoint" + ~title:"No such entrypoint (type error)" + ~description:"An entrypoint was not found when calling a contract." + (obj1 (req "entrypoint" Entrypoint.simple_encoding)) + (function No_such_entrypoint entrypoint -> Some entrypoint | _ -> None) + (fun entrypoint -> No_such_entrypoint entrypoint) ; + (* Unreachable entrypoint *) + register_error_kind + `Permanent + ~id:"michelson_v1.unreachable_entrypoint" + ~title:"Unreachable entrypoint (type error)" + ~description:"An entrypoint in the contract is not reachable." + (obj1 (req "path" (list prim_encoding))) + (function Unreachable_entrypoint path -> Some path | _ -> None) + (fun path -> Unreachable_entrypoint path) ; + (* Tx rollup bad deposit parameter *) + register_error_kind + `Permanent + ~id:"michelson_v1.tx_rollup_bad_deposit_parameter" + ~title:"Bad deposit parameter" + ~description: + "The parameter to the deposit entrypoint of a transaction rollup should \ + be a pair of a ticket and the address of a recipient transaction \ + rollup." + (located (obj1 (req "parameter" Script.expr_encoding))) + (function + | Tx_rollup_bad_deposit_parameter (loc, expr) -> Some (loc, expr) + | _ -> None) + (fun (loc, expr) -> Tx_rollup_bad_deposit_parameter (loc, expr)) ; + (* Tx rollup invalid ticket amount *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_tx_rollup_ticket_amount" + ~title:"Invalid ticket amount" + ~description: + "Ticket amount to be deposited in a transaction rollup should be \ + strictly positive and fit in a signed 64-bit integer" + (obj1 (req "requested_value" Data_encoding.z)) + (function Tx_rollup_invalid_ticket_amount z -> Some z | _ -> None) + (fun z -> Tx_rollup_invalid_ticket_amount z) ; + register_error_kind + `Permanent + ~id:"michelson_v1.forbidden_zero_amount_ticket" + ~title:"Zero ticket amount is not allowed" + ~description: + "It is not allowed to use a zero amount ticket in this operation." + Data_encoding.empty + (function Forbidden_zero_ticket_quantity -> Some () | _ -> None) + (fun () -> Forbidden_zero_ticket_quantity) ; + (* Sc rollup disabled *) + register_error_kind + `Permanent + ~id:"michelson_v1.sc_rollup_disabled" + ~title:"Sc rollup are disabled" + ~description:"Cannot use smart rollup features as they are disabled." + (obj1 (req "location" Script.location_encoding)) + (function Sc_rollup_disabled loc -> Some loc | _ -> None) + (fun loc -> Sc_rollup_disabled loc) ; + (* Duplicate entrypoint *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_entrypoint" + ~title:"Duplicate entrypoint (type error)" + ~description:"Two entrypoints have the same name." + (obj1 (req "path" Entrypoint.simple_encoding)) + (function Duplicate_entrypoint entrypoint -> Some entrypoint | _ -> None) + (fun entrypoint -> Duplicate_entrypoint entrypoint) ; + (* Unexpected contract *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_contract" + ~title:"Contract in unauthorized position (type error)" + ~description: + "When parsing script, a contract type was found in the storage or \ + parameter field." + (obj1 (req "loc" location_encoding)) + (function Unexpected_contract loc -> Some loc | _ -> None) + (fun loc -> Unexpected_contract loc) ; + (* -- Value typing errors ---------------------- *) + (* Unordered map keys *) + register_error_kind + `Permanent + ~id:"michelson_v1.unordered_map_literal" + ~title:"Invalid map key order" + ~description:"Map keys must be in strictly increasing order" + (obj2 + (req "location" Script.location_encoding) + (req "item" Script.expr_encoding)) + (function Unordered_map_keys (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Unordered_map_keys (loc, expr)) ; + (* Duplicate map keys *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_map_keys" + ~title:"Duplicate map keys" + ~description:"Map literals cannot contain duplicated keys" + (obj2 + (req "location" Script.location_encoding) + (req "item" Script.expr_encoding)) + (function Duplicate_map_keys (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Duplicate_map_keys (loc, expr)) ; + (* Unordered set values *) + register_error_kind + `Permanent + ~id:"michelson_v1.unordered_set_literal" + ~title:"Invalid set value order" + ~description:"Set values must be in strictly increasing order" + (obj2 + (req "location" Script.location_encoding) + (req "value" Script.expr_encoding)) + (function + | Unordered_set_values (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Unordered_set_values (loc, expr)) ; + (* Duplicate set values *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicate_set_values_in_literal" + ~title:"Sets literals cannot contain duplicate elements" + ~description: + "Set literals cannot contain duplicate elements, but a duplicate was \ + found while parsing." + (obj2 + (req "location" Script.location_encoding) + (req "value" Script.expr_encoding)) + (function + | Duplicate_set_values (loc, expr) -> Some (loc, expr) | _ -> None) + (fun (loc, expr) -> Duplicate_set_values (loc, expr)) ; + (* -- Instruction typing errors ------------- *) + (* Fail not in tail position *) + register_error_kind + `Permanent + ~id:"michelson_v1.fail_not_in_tail_position" + ~title:"FAIL not in tail position" + ~description:"There is non trivial garbage code after a FAIL instruction." + (located empty) + (function Fail_not_in_tail_position loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Fail_not_in_tail_position loc) ; + (* Undefined binary operation *) + register_error_kind + `Permanent + ~id:"michelson_v1.undefined_binop" + ~title:"Undefined binop" + ~description: + "A binary operation is called on operands of types over which it is not \ + defined." + (located + (obj3 + (req "operator_name" prim_encoding) + (req "wrong_left_operand_type" Script.expr_encoding) + (req "wrong_right_operand_type" Script.expr_encoding))) + (function + | Undefined_binop (loc, n, tyl, tyr) -> Some (loc, (n, tyl, tyr)) + | _ -> None) + (fun (loc, (n, tyl, tyr)) -> Undefined_binop (loc, n, tyl, tyr)) ; + (* Undefined unary operation *) + register_error_kind + `Permanent + ~id:"michelson_v1.undefined_unop" + ~title:"Undefined unop" + ~description: + "A unary operation is called on an operand of type over which it is not \ + defined." + (located + (obj2 + (req "operator_name" prim_encoding) + (req "wrong_operand_type" Script.expr_encoding))) + (function Undefined_unop (loc, n, ty) -> Some (loc, (n, ty)) | _ -> None) + (fun (loc, (n, ty)) -> Undefined_unop (loc, n, ty)) ; + (* Bad return *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_return" + ~title:"Bad return" + ~description:"Unexpected stack at the end of a lambda or script." + (located + (obj2 + (req "expected_return_type" Script.expr_encoding) + (req "wrong_stack_type" stack_ty_enc))) + (function Bad_return (loc, sty, ty) -> Some (loc, (ty, sty)) | _ -> None) + (fun (loc, (ty, sty)) -> Bad_return (loc, sty, ty)) ; + (* Bad stack *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_stack" + ~title:"Bad stack" + ~description:"The stack has an unexpected length or contents." + (located + (obj3 + (req "primitive_name" prim_encoding) + (req "relevant_stack_portion" int16) + (req "wrong_stack_type" stack_ty_enc))) + (function + | Bad_stack (loc, name, s, sty) -> Some (loc, (name, s, sty)) | _ -> None) + (fun (loc, (name, s, sty)) -> Bad_stack (loc, name, s, sty)) ; + (* Unexpected annotation *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_annotation" + ~title:"An annotation was encountered where no annotation is expected" + ~description:"A node in the syntax tree was improperly annotated" + (located empty) + (function Unexpected_annotation loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Unexpected_annotation loc) ; + (* Ungrouped annotations *) + register_error_kind + `Permanent + ~id:"michelson_v1.ungrouped_annotations" + ~title:"Annotations of the same kind were found spread apart" + ~description:"Annotations of the same kind must be grouped" + (located empty) + (function Ungrouped_annotations loc -> Some (loc, ()) | _ -> None) + (fun (loc, ()) -> Ungrouped_annotations loc) ; + (* Unmatched branches *) + register_error_kind + `Permanent + ~id:"michelson_v1.unmatched_branches" + ~title:"Unmatched branches" + ~description: + "At the join point at the end of two code branches the stacks have \ + inconsistent lengths or contents." + (located + (obj2 + (req "first_stack_type" stack_ty_enc) + (req "other_stack_type" stack_ty_enc))) + (function + | Unmatched_branches (loc, stya, styb) -> Some (loc, (stya, styb)) + | _ -> None) + (fun (loc, (stya, styb)) -> Unmatched_branches (loc, stya, styb)) ; + (* Bad stack item *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_stack_item" + ~title:"Bad stack item" + ~description: + "The type of a stack item is unexpected (this error is always \ + accompanied by a more precise one)." + (obj1 (req "item_level" int16)) + (function Bad_stack_item n -> Some n | _ -> None) + (fun n -> Bad_stack_item n) ; + (* Forbidden instruction in a context. *) + register_error_kind + `Permanent + ~id:"michelson_v1.forbidden_instr_in_context" + ~title:"Forbidden instruction in context" + ~description: + "An instruction was encountered in a context where it is forbidden." + (located + (obj2 + (req "context" context_desc_enc) + (req "forbidden_instruction" prim_encoding))) + (function + | Forbidden_instr_in_context (loc, ctxt, prim) -> Some (loc, (ctxt, prim)) + | _ -> None) + (fun (loc, (ctxt, prim)) -> Forbidden_instr_in_context (loc, ctxt, prim)) ; + (* Bad stack length *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_stack_lengths" + ~title:"Inconsistent stack lengths" + ~description: + "A stack was of an unexpected length (this error is always in the \ + context of a located error)." + empty + (function Bad_stack_length -> Some () | _ -> None) + (fun () -> Bad_stack_length) ; + (* -- Value typing errors ------------------- *) + (* Invalid constant *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_constant" + ~title:"Invalid constant" + ~description:"A data expression was invalid for its expected type." + (located + (obj2 + (req "expected_type" Script.expr_encoding) + (req "wrong_expression" Script.expr_encoding))) + (function + | Invalid_constant (loc, expr, ty) -> Some (loc, (ty, expr)) | _ -> None) + (fun (loc, (ty, expr)) -> Invalid_constant (loc, expr, ty)) ; + (* View name too long *) + register_error_kind + `Permanent + ~id:"michelson_v1.view_name_too_long" + ~title:"View name too long (type error)" + ~description:"A view name exceeds the maximum length of 31 characters." + (obj1 (req "name" (string Plain))) + (function View_name_too_long name -> Some name | _ -> None) + (fun name -> View_name_too_long name) ; + (* Duplicated view name *) + register_error_kind + `Permanent + ~id:"michelson_v1.duplicated_view_name" + ~title:"Duplicated view name" + ~description:"The name of view in toplevel should be unique." + (obj1 (req "location" Script.location_encoding)) + (function Duplicated_view_name loc -> Some loc | _ -> None) + (fun loc -> Duplicated_view_name loc) ; + (* Invalid syntactic constant *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_syntactic_constant" + ~title:"Invalid constant (parse error)" + ~description:"A compile-time constant was invalid for its expected form." + (located + (obj2 + (req "expected_form" (string Plain)) + (req "wrong_expression" Script.expr_encoding))) + (function + | Invalid_syntactic_constant (loc, expr, expected) -> + Some (loc, (expected, expr)) + | _ -> None) + (fun (loc, (expected, expr)) -> + Invalid_syntactic_constant (loc, expr, expected)) ; + (* Invalid contract *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_contract" + ~title:"Invalid contract" + ~description: + "A script or data expression references a contract that does not exist \ + or assumes a wrong type for an existing contract." + (located (obj1 (req "contract" Contract.encoding))) + (function Invalid_contract (loc, c) -> Some (loc, c) | _ -> None) + (fun (loc, c) -> Invalid_contract (loc, c)) ; + (* Invalid big_map *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_big_map" + ~title:"Invalid big_map" + ~description: + "A script or data expression references a big_map that does not exist or \ + assumes a wrong type for an existing big_map." + (located (obj1 (req "big_map" Big_map.Id.encoding))) + (function Invalid_big_map (loc, c) -> Some (loc, c) | _ -> None) + (fun (loc, c) -> Invalid_big_map (loc, c)) ; + (* Comparable type expected *) + register_error_kind + `Permanent + ~id:"michelson_v1.comparable_type_expected" + ~title:"Comparable type expected" + ~description: + "A non comparable type was used in a place where only comparable types \ + are accepted." + (located (obj1 (req "wrong_type" Script.expr_encoding))) + (function + | Comparable_type_expected (loc, ty) -> Some (loc, ty) | _ -> None) + (fun (loc, ty) -> Comparable_type_expected (loc, ty)) ; + (* Inconsistent type sizes *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_type_sizes" + ~title:"Inconsistent type sizes" + ~description: + "Two types were expected to be equal but they have different sizes." + (obj2 (req "first_type_size" int31) (req "other_type_size" int31)) + (function + | Inconsistent_type_sizes (tya, tyb) -> Some (tya, tyb) | _ -> None) + (fun (tya, tyb) -> Inconsistent_type_sizes (tya, tyb)) ; + (* Inconsistent types *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_types" + ~title:"Inconsistent types" + ~description: + "This is the basic type clash error, that appears in several places \ + where the equality of two types have to be proven, it is always \ + accompanied with another error that provides more context." + (obj3 + (req "loc" Script.location_encoding) + (req "first_type" Script.expr_encoding) + (req "other_type" Script.expr_encoding)) + (function + | Inconsistent_types (loc, tya, tyb) -> Some (loc, tya, tyb) | _ -> None) + (fun (loc, tya, tyb) -> Inconsistent_types (loc, tya, tyb)) ; + (* Inconsistent types *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_implicit_account_parameters_type" + ~title:"Unexpected implicit account parameters type" + ~description: + "An implicit account can only accept either a unit or a ticket value as \ + a call parameter." + (obj2 + (req "loc" Script.location_encoding) + (req "type" Script.expr_encoding)) + (function + | Unexpected_implicit_account_parameters_type (loc, ty) -> Some (loc, ty) + | _ -> None) + (fun (loc, ty) -> Unexpected_implicit_account_parameters_type (loc, ty)) ; + (* Inconsistent memo_sizes *) + register_error_kind + `Permanent + ~id:"michelson_v1.inconsistent_memo_sizes" + ~title:"Inconsistent memo sizes" + ~description:"Memo sizes of two sapling states or transactions do not match" + (obj2 + (req "first_memo_size" Sapling.Memo_size.encoding) + (req "other_memo_size" Sapling.Memo_size.encoding)) + (function + | Inconsistent_memo_sizes (msa, msb) -> Some (msa, msb) | _ -> None) + (fun (msa, msb) -> Inconsistent_memo_sizes (msa, msb)) ; + (* -- Instruction typing errors ------------------- *) + (* Bad view name *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_view_name" + ~title:"Bad view name" + ~description:"In a view declaration, the view name must be a string" + (obj1 (req "loc" Script.location_encoding)) + (function Bad_view_name loc -> Some loc | _ -> None) + (fun loc -> Bad_view_name loc) ; + (* Invalid view body *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_typed_view" + ~title:"Ill typed view" + ~description:"The return of a view block did not match the expected type" + (obj3 + (req "loc" Script.location_encoding) + (req "resulted_view_stack" stack_ty_enc) + (req "expected_view_stack" stack_ty_enc)) + (function + | Ill_typed_view {loc; actual; expected} -> Some (loc, actual, expected) + | _ -> None) + (fun (loc, actual, expected) -> Ill_typed_view {loc; actual; expected}) ; + (* Invalid map body *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_map_body" + ~title:"Invalid map body" + ~description:"The body of a map block did not match the expected type" + (obj2 (req "loc" Script.location_encoding) (req "body_type" stack_ty_enc)) + (function Invalid_map_body (loc, stack) -> Some (loc, stack) | _ -> None) + (fun (loc, stack) -> Invalid_map_body (loc, stack)) ; + (* Invalid map block FAIL *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_map_block_fail" + ~title:"FAIL instruction occurred as body of map block" + ~description: + "FAIL cannot be the only instruction in the body. The proper type of the \ + return list cannot be inferred." + (obj1 (req "loc" Script.location_encoding)) + (function Invalid_map_block_fail loc -> Some loc | _ -> None) + (fun loc -> Invalid_map_block_fail loc) ; + (* Invalid ITER body *) + register_error_kind + `Permanent + ~id:"michelson_v1.invalid_iter_body" + ~title:"ITER body returned wrong stack type" + ~description: + "The body of an ITER instruction must result in the same stack type as \ + before the ITER." + (obj3 + (req "loc" Script.location_encoding) + (req "bef_stack" stack_ty_enc) + (req "aft_stack" stack_ty_enc)) + (function + | Invalid_iter_body (loc, bef, aft) -> Some (loc, bef, aft) | _ -> None) + (fun (loc, bef, aft) -> Invalid_iter_body (loc, bef, aft)) ; + (* Type too large *) + register_error_kind + `Permanent + ~id:"michelson_v1.type_too_large" + ~title:"Stack item type too large" + ~description:"An instruction generated a type larger than the limit." + (obj2 (req "loc" Script.location_encoding) (req "maximum_type_size" uint16)) + (function Type_too_large (loc, maxts) -> Some (loc, maxts) | _ -> None) + (fun (loc, maxts) -> Type_too_large (loc, maxts)) ; + (* Bad PAIR argument *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_pair_argument" + ~title:"0 or 1 passed to PAIR" + ~description:"PAIR expects an argument of at least 2" + (obj1 (req "loc" Script.location_encoding)) + (function Pair_bad_argument loc -> Some loc | _ -> None) + (fun loc -> Pair_bad_argument loc) ; + (* Bad UNPAIR argument *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_unpair_argument" + ~title:"0 or 1 passed to UNPAIR" + ~description:"UNPAIR expects an argument of at least 2" + (obj1 (req "loc" Script.location_encoding)) + (function Unpair_bad_argument loc -> Some loc | _ -> None) + (fun loc -> Unpair_bad_argument loc) ; + (* Bad dup_n argument *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_dupn_argument" + ~title:"0 passed to DUP n" + ~description:"DUP expects an argument of at least 1 (passed 0)" + (obj1 (req "loc" Script.location_encoding)) + (function Dup_n_bad_argument loc -> Some loc | _ -> None) + (fun loc -> Dup_n_bad_argument loc) ; + (* Bad dup_n stack *) + register_error_kind + `Permanent + ~id:"michelson_v1.bad_dupn_stack" + ~title:"Stack too short when typing DUP n" + ~description:"Stack present when typing DUP n was too short" + (obj1 (req "loc" Script.location_encoding)) + (function Dup_n_bad_stack x -> Some x | _ -> None) + (fun x -> Dup_n_bad_stack x) ; + (* -- Toplevel errors ------------------- *) + (* Ill typed data *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_typed_data" + ~title:"Ill typed data" + ~description: + "The toplevel error thrown when trying to typecheck a data expression \ + against a given type (always followed by more precise errors)." + (obj3 + (opt "identifier" (string Plain)) + (req "expected_type" Script.expr_encoding) + (req "ill_typed_expression" Script.expr_encoding)) + (function + | Ill_typed_data (name, expr, ty) -> Some (name, ty, expr) | _ -> None) + (fun (name, ty, expr) -> Ill_typed_data (name, expr, ty)) ; + (* Ill formed type *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_formed_type" + ~title:"Ill formed type" + ~description: + "The toplevel error thrown when trying to parse a type expression \ + (always followed by more precise errors)." + (obj3 + (opt "identifier" (string Plain)) + (req "ill_formed_expression" Script.expr_encoding) + (req "location" Script.location_encoding)) + (function + | Ill_formed_type (name, expr, loc) -> Some (name, expr, loc) | _ -> None) + (fun (name, expr, loc) -> Ill_formed_type (name, expr, loc)) ; + (* Ill typed contract *) + register_error_kind + `Permanent + ~id:"michelson_v1.ill_typed_contract" + ~title:"Ill typed contract" + ~description: + "The toplevel error thrown when trying to typecheck a contract code \ + against given input, output and storage types (always followed by more \ + precise errors)." + (obj2 + (req "ill_typed_code" Script.expr_encoding) + (req "type_map" type_map_enc)) + (function + | Ill_typed_contract (expr, type_map) -> Some (expr, type_map) | _ -> None) + (fun (expr, type_map) -> Ill_typed_contract (expr, type_map)) ; + (* Deprecated instruction *) + register_error_kind + `Permanent + ~id:"michelson_v1.deprecated_instruction" + ~title:"Script is using a deprecated instruction" + ~description: + "A deprecated instruction usage is disallowed in newly created contracts" + (obj1 (req "prim" prim_encoding)) + (function Deprecated_instruction prim -> Some prim | _ -> None) + (fun prim -> Deprecated_instruction prim) ; + (* Typechecking stack overflow *) + register_error_kind + `Temporary + ~id:"michelson_v1.typechecking_too_many_recursive_calls" + ~title:"Too many recursive calls during typechecking" + ~description:"Too many recursive calls were needed for typechecking" + Data_encoding.empty + (function Typechecking_too_many_recursive_calls -> Some () | _ -> None) + (fun () -> Typechecking_too_many_recursive_calls) ; + (* Unparsing stack overflow *) + register_error_kind + `Temporary + ~id:"michelson_v1.unparsing_stack_overflow" + ~title:"Too many recursive calls during unparsing" + ~description:"Too many recursive calls were needed for unparsing" + Data_encoding.empty + (function Unparsing_too_many_recursive_calls -> Some () | _ -> None) + (fun () -> Unparsing_too_many_recursive_calls) ; + (* Unexpected forged value *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_forged_value" + ~title:"Unexpected forged value" + ~description: + "A forged value was encountered but disallowed for that position." + (obj1 (req "location" Script.location_encoding)) + (function Unexpected_forged_value loc -> Some loc | _ -> None) + (fun loc -> Unexpected_forged_value loc) ; + (* Unexpected ticket *) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_ticket" + ~title:"Ticket in unauthorized position (type error)" + ~description:"A ticket type has been found" + (obj1 (req "loc" location_encoding)) + (function Unexpected_ticket loc -> Some loc | _ -> None) + (fun loc -> Unexpected_ticket loc) ; + (* Attempt to duplicate a non-dupable type *) + register_error_kind + `Permanent + ~id:"michelson_v1.non_dupable_type" + ~title:"Non-dupable type duplication attempt" + ~description:"DUP was used on a non-dupable type (e.g. tickets)." + (obj2 (req "loc" location_encoding) (req "type" Script.expr_encoding)) + (function Non_dupable_type (loc, ty) -> Some (loc, ty) | _ -> None) + (fun (loc, ty) -> Non_dupable_type (loc, ty)) ; + (* Unexpected ticket owner*) + register_error_kind + `Permanent + ~id:"michelson_v1.unexpected_ticket_owner" + ~title:"Unexpected ticket owner" + ~description:"Ticket can only be created by a smart contract" + (obj1 (req "ticketer" Destination.encoding)) + (function Unexpected_ticket_owner t -> Some t | _ -> None) + (fun t -> Unexpected_ticket_owner t) diff --git a/src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.mli b/src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.mli new file mode 100644 index 000000000000..dd2e61e500ce --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_tc_errors_registration.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module registers all the errors from [Script_tc_errors] as a top-level + effect. *) + +open Alpha_context +open Script + +val type_map_enc : + (location * (expr list * expr list)) list Data_encoding.encoding diff --git a/src/proto_020_PsParisC/lib_protocol/script_timestamp.ml b/src/proto_020_PsParisC/lib_protocol/script_timestamp.ml new file mode 100644 index 000000000000..105d751473e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_timestamp.ml @@ -0,0 +1,66 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type repr = Z.t + +type t = Timestamp_tag of repr [@@ocaml.unboxed] + +let compare (Timestamp_tag x) (Timestamp_tag y) = Z.compare x y + +let of_int64 i = Timestamp_tag (Z.of_int64 i) + +let of_string x = + match Time_repr.of_notation x with + | None -> Option.catch (fun () -> Timestamp_tag (Z.of_string x)) + | Some time -> Some (of_int64 (Time_repr.to_seconds time)) + +let to_notation (Timestamp_tag x) = + Option.catch (fun () -> + Time_repr.to_notation (Time.of_seconds (Z.to_int64 x))) + +let to_num_str (Timestamp_tag x) = Z.to_string x + +let to_string x = match to_notation x with None -> to_num_str x | Some s -> s + +let diff (Timestamp_tag x) (Timestamp_tag y) = Script_int.of_zint @@ Z.sub x y + +let sub_delta (Timestamp_tag t) delta = + Timestamp_tag (Z.sub t (Script_int.to_zint delta)) + +let add_delta (Timestamp_tag t) delta = + Timestamp_tag (Z.add t (Script_int.to_zint delta)) + +let to_zint (Timestamp_tag x) = x + +let of_zint x = Timestamp_tag x + +let encoding = Data_encoding.(conv to_zint of_zint z) + +let now ctxt = + let open Alpha_context in + let first_delay = Period.to_seconds (Constants.minimal_block_delay ctxt) in + let current_timestamp = Timestamp.predecessor ctxt in + Time.add current_timestamp first_delay |> Timestamp.to_seconds |> of_int64 diff --git a/src/proto_020_PsParisC/lib_protocol/script_timestamp.mli b/src/proto_020_PsParisC/lib_protocol/script_timestamp.mli new file mode 100644 index 000000000000..2d246ae4f9a3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_timestamp.mli @@ -0,0 +1,75 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Defines the internal Michelson representation for timestamps and basic + operations that can be performed on it. *) + +open Script_int + +type repr + +(** Representation of timestamps specific to the Michelson interpreter. + A number of seconds since the epoch. + [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) +type t = Timestamp_tag of repr [@@ocaml.unboxed] + +(** Convert a number of seconds since the epoch to a timestamp.*) +val of_int64 : int64 -> t + +(** Compare timestamps. Returns [1] if the first timestamp is later than the + second one; [0] if they're equal and [-1] othwerwise. *) +val compare : t -> t -> int + +(** Convert a timestamp to RFC3339 notation if possible **) +val to_notation : t -> string option + +(** Convert a timestamp to a string representation of the seconds *) +val to_num_str : t -> string + +(** Convert to RFC3339 notation if possible, or num if not *) +val to_string : t -> string + +val of_string : string -> t option + +(** Returns difference between timestamps as integral number of seconds + in Michelson representation of numbers. *) +val diff : t -> t -> z num + +(** Add a number of seconds to the timestamp. *) +val add_delta : t -> z num -> t + +(** Subtract a number of seconds from the timestamp. *) +val sub_delta : t -> z num -> t + +val to_zint : t -> Z.t + +val of_zint : Z.t -> t + +(* Timestamps are encoded exactly as Z. *) +val encoding : t Data_encoding.encoding + +val now : Alpha_context.t -> t diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir.ml b/src/proto_020_PsParisC/lib_protocol/script_typed_ir.ml new file mode 100644 index 000000000000..45d9c4993216 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir.ml @@ -0,0 +1,2468 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_int +open Dependent_bool + +(* + + The step function of the interpreter is parametrized by a bunch of values called the step constants. + These values are indeed constants during the call of a smart contract with the notable exception of + the IView instruction which modifies `sender`, `self`, and `amount` and the KView_exit continuation + which restores them. + ====================== + +*) +type step_constants = { + sender : Destination.t; + (** The address calling this contract, as returned by SENDER. *) + payer : Signature.public_key_hash; + (** The address of the implicit account that initiated the chain of contract calls, as returned by SOURCE. *) + self : Contract_hash.t; + (** The address of the contract being executed, as returned by SELF and SELF_ADDRESS. + Also used: + - as ticketer in TICKET + - as caller in VIEW, TRANSFER_TOKENS, and CREATE_CONTRACT *) + amount : Tez.t; + (** The amount of the current transaction, as returned by AMOUNT. *) + balance : Tez.t; (** The balance of the contract as returned by BALANCE. *) + chain_id : Chain_id.t; + (** The chain id of the chain, as returned by CHAIN_ID. *) + now : Script_timestamp.t; + (** The earliest time at which the current block could have been timestamped, as returned by NOW. *) + level : Script_int.n Script_int.num; + (** The level of the current block, as returned by LEVEL. *) +} + +(* Preliminary definitions. *) + +type never = | + +type address = {destination : Destination.t; entrypoint : Entrypoint.t} + +module Script_signature = struct + type t = Signature_tag of signature [@@ocaml.unboxed] + + let make s = Signature_tag s + + let get (Signature_tag s) = s + + let encoding = + Data_encoding.conv + (fun (Signature_tag x) -> x) + (fun x -> Signature_tag x) + Signature.encoding + + let of_b58check_opt x = Option.map make (Signature.of_b58check_opt x) + + let check ?watermark pub_key (Signature_tag s) bytes = + Signature.check ?watermark pub_key s bytes + + let compare (Signature_tag x) (Signature_tag y) = Signature.compare x y + + let size (Signature_tag s) = Signature.size s +end + +type signature = Script_signature.t + +type ('a, 'b) pair = 'a * 'b + +(* We cannot call this type "or" as in Michelson because "or" is an + OCaml keyword. *) +type ('a, 'b) or_ = L of 'a | R of 'b + +module Script_chain_id = struct + type t = Chain_id_tag of Chain_id.t [@@ocaml.unboxed] + + let make x = Chain_id_tag x + + let compare (Chain_id_tag x) (Chain_id_tag y) = Chain_id.compare x y + + let size = Chain_id.size + + let encoding = + Data_encoding.conv (fun (Chain_id_tag x) -> x) make Chain_id.encoding + + let to_b58check (Chain_id_tag x) = Chain_id.to_b58check x + + let of_b58check_opt x = Option.map make (Chain_id.of_b58check_opt x) +end + +module Script_bls = struct + module type S = sig + type t + + type fr + + val add : t -> t -> t + + val mul : t -> fr -> t + + val negate : t -> t + + val of_bytes_opt : Bytes.t -> t option + + val to_bytes : t -> Bytes.t + end + + module Fr = struct + type t = Fr_tag of Bls.Primitive.Fr.t [@@ocaml.unboxed] + + open Bls.Primitive.Fr + + let add (Fr_tag x) (Fr_tag y) = Fr_tag (add x y) + + let mul (Fr_tag x) (Fr_tag y) = Fr_tag (mul x y) + + let negate (Fr_tag x) = Fr_tag (negate x) + + let of_bytes_opt bytes = Option.map (fun x -> Fr_tag x) (of_bytes_opt bytes) + + let to_bytes (Fr_tag x) = to_bytes x + + let of_z z = Fr_tag (of_z z) + + let to_z (Fr_tag x) = to_z x + end + + module G1 = struct + type t = G1_tag of Bls.Primitive.G1.t [@@ocaml.unboxed] + + open Bls.Primitive.G1 + + let add (G1_tag x) (G1_tag y) = G1_tag (add x y) + + let mul (G1_tag x) (Fr.Fr_tag y) = G1_tag (mul x y) + + let negate (G1_tag x) = G1_tag (negate x) + + let of_bytes_opt bytes = Option.map (fun x -> G1_tag x) (of_bytes_opt bytes) + + let to_bytes (G1_tag x) = to_bytes x + end + + module G2 = struct + type t = G2_tag of Bls.Primitive.G2.t [@@ocaml.unboxed] + + open Bls.Primitive.G2 + + let add (G2_tag x) (G2_tag y) = G2_tag (add x y) + + let mul (G2_tag x) (Fr.Fr_tag y) = G2_tag (mul x y) + + let negate (G2_tag x) = G2_tag (negate x) + + let of_bytes_opt bytes = Option.map (fun x -> G2_tag x) (of_bytes_opt bytes) + + let to_bytes (G2_tag x) = to_bytes x + end + + let pairing_check l = + let l = List.map (fun (G1.G1_tag x, G2.G2_tag y) -> (x, y)) l in + Bls.Primitive.pairing_check l +end + +module Script_timelock = struct + type chest_key = Chest_key_tag of Timelock.chest_key [@@ocaml.unboxed] + + let make_chest_key chest_key = Chest_key_tag chest_key + + let chest_key_encoding = + Data_encoding.conv + (fun (Chest_key_tag x) -> x) + (fun x -> Chest_key_tag x) + Timelock.chest_key_encoding + + type chest = Chest_tag of Timelock.chest [@@ocaml.unboxed] + + let make_chest chest = Chest_tag chest + + let chest_encoding = + Data_encoding.conv + (fun (Chest_tag x) -> x) + (fun x -> Chest_tag x) + Timelock.chest_encoding + + let open_chest (Chest_tag chest) (Chest_key_tag chest_key) ~time = + Timelock.open_chest chest chest_key ~time + + let get_plaintext_size (Chest_tag x) = Timelock.get_plaintext_size x +end + +type ticket_amount = Ticket_amount.t + +type 'a ticket = {ticketer : Contract.t; contents : 'a; amount : ticket_amount} + +module type TYPE_SIZE = sig + (* A type size represents the size of its type parameter. + This constraint is enforced inside this module (Script_typed_ir), hence there + should be no way to construct a type size outside of it. + + It allows keeping type metadata and types non-private. + + The size of a type is the number of nodes in its AST + representation. In other words, the size of a type is 1 plus the size of + its arguments. For instance, the size of [Unit] is 1 and the size of + [Pair ty1 ty2] is [1] plus the size of [ty1] and [ty2]. + + This module is here because we want three levels of visibility over this + code: + - inside this submodule, we have [type 'a t = int] + - outside of [Script_typed_ir], the ['a t] type is abstract and we have + the invariant that whenever [x : 'a t] we have that [x] is exactly + the size of ['a]. + - in-between (inside [Script_typed_ir] but outside the [Type_size] + submodule), the type is abstract but we have access to unsafe + constructors that can break the invariant. + *) + type 'a t + + val check_eq : + error_details:('error_context, 'error_trace) Script_tc_errors.error_details -> + 'a t -> + 'b t -> + (unit, 'error_trace) result + + val to_int : 'a t -> Saturation_repr.mul_safe Saturation_repr.t + + (* Unsafe constructors, to be used only safely and inside this module *) + + val one : _ t + + val compound1 : Script.location -> _ t -> _ t tzresult + + val compound2 : Script.location -> _ t -> _ t -> _ t tzresult +end + +module Type_size : TYPE_SIZE = struct + type 'a t = int + + let () = + (* static-like check that all [t] values fit in a [mul_safe] *) + let (_ : Saturation_repr.mul_safe Saturation_repr.t) = + Saturation_repr.mul_safe_of_int_exn Constants.michelson_maximum_type_size + in + () + + let to_int = Saturation_repr.mul_safe_of_int_exn + + let one = 1 + + let check_eq : + type a b error_trace. + error_details:(_, error_trace) Script_tc_errors.error_details -> + a t -> + b t -> + (unit, error_trace) result = + fun ~error_details x y -> + if Compare.Int.(x = y) then Result.return_unit + else + Error + (match error_details with + | Fast -> Inconsistent_types_fast + | Informative _ -> + trace_of_error @@ Script_tc_errors.Inconsistent_type_sizes (x, y)) + + let of_int loc size = + let open Result_syntax in + let max_size = Constants.michelson_maximum_type_size in + if Compare.Int.(size <= max_size) then return size + else tzfail (Script_tc_errors.Type_too_large (loc, max_size)) + + let compound1 loc size = of_int loc (1 + size) + + let compound2 loc size1 size2 = of_int loc (1 + size1 + size2) +end + +type empty_cell = EmptyCell + +type end_of_stack = empty_cell * empty_cell + +type 'a ty_metadata = {size : 'a Type_size.t} [@@unboxed] + +(* + + This signature contains the exact set of functions used in the + protocol. We do not include all [Set.S] because this would + increase the size of the first class modules used to represent + [boxed_set]. + + Warning: for any change in this signature, there must be a + change in [Script_typed_ir_size.value_size] which updates + [boxing_space] in the case for sets. + +*) +module type Boxed_set_OPS = sig + type t + + type elt + + val elt_size : elt -> int (* Gas_input_size.t *) + + val empty : t + + val add : elt -> t -> t + + val mem : elt -> t -> bool + + val remove : elt -> t -> t + + val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a +end + +module type Boxed_set = sig + type elt + + module OPS : Boxed_set_OPS with type elt = elt + + val boxed : OPS.t + + val size : int +end + +type 'elt set = Set_tag of (module Boxed_set with type elt = 'elt) +[@@ocaml.unboxed] + +(* + + Same remark as for [Boxed_set_OPS]. (See below.) + +*) +module type Boxed_map_OPS = sig + type 'a t + + type key + + val key_size : key -> int (* Gas_input_size.t *) + + val empty : 'value t + + val add : key -> 'value -> 'value t -> 'value t + + val remove : key -> 'value t -> 'value t + + val find : key -> 'value t -> 'value option + + val fold : (key -> 'value -> 'a -> 'a) -> 'value t -> 'a -> 'a + + val fold_es : + (key -> 'value -> 'a -> 'a tzresult Lwt.t) -> + 'value t -> + 'a -> + 'a tzresult Lwt.t +end + +module type Boxed_map = sig + type key + + type value + + module OPS : Boxed_map_OPS with type key = key + + val boxed : value OPS.t + + val size : int +end + +type ('key, 'value) map = + | Map_tag of (module Boxed_map with type key = 'key and type value = 'value) +[@@ocaml.unboxed] + +module Big_map_overlay = Map.Make (struct + type t = Script_expr_hash.t + + let compare = Script_expr_hash.compare +end) + +type ('key, 'value) big_map_overlay = { + map : ('key * 'value option) Big_map_overlay.t; + size : int; +} + +type view = { + input_ty : Script.node; + output_ty : Script.node; + view_code : Script.node; +} + +type view_map = (Script_string.t, view) map + +type entrypoint_info = {name : Entrypoint.t; original_type_expr : Script.node} + +type 'arg entrypoints_node = { + at_node : entrypoint_info option; + nested : 'arg nested_entrypoints; +} + +and 'arg nested_entrypoints = + | Entrypoints_Or : { + left : 'l entrypoints_node; + right : 'r entrypoints_node; + } + -> ('l, 'r) or_ nested_entrypoints + | Entrypoints_None : _ nested_entrypoints + +let no_entrypoints = {at_node = None; nested = Entrypoints_None} + +type logging_event = LogEntry | LogExit of Script.location + +type 'arg entrypoints = { + root : 'arg entrypoints_node; + original_type_expr : Script.node; +} + +(* ---- Instructions --------------------------------------------------------*) +and ('before_top, 'before, 'result_top, 'result) kinstr = + (* + Stack + ----- + *) + | IDrop : + Script.location * ('b, 'S, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IDup : + Script.location * ('a, 'a * ('b * 'S), 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | ISwap : + Script.location * ('b, 'a * ('c * 'S), 'r, 'F) kinstr + -> ('a, 'b * ('c * 'S), 'r, 'F) kinstr + | IPush : + Script.location * ('ty, _) ty * 'ty * ('ty, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IUnit : + Script.location * (unit, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + (* + Pairs + ----- + *) + | ICons_pair : + Script.location * (('a, 'b) pair, 'c * 'S, 'r, 'F) kinstr + -> ('a, 'b * ('c * 'S), 'r, 'F) kinstr + | ICar : + Script.location * ('a, 'S, 'r, 'F) kinstr + -> (('a, 'b) pair, 'S, 'r, 'F) kinstr + | ICdr : + Script.location * ('b, 'S, 'r, 'F) kinstr + -> (('a, 'b) pair, 'S, 'r, 'F) kinstr + | IUnpair : + Script.location * ('a, 'b * 'S, 'r, 'F) kinstr + -> (('a, 'b) pair, 'S, 'r, 'F) kinstr + (* + Options + ------- + *) + | ICons_some : + Script.location * ('v option, 'a * 'S, 'r, 'F) kinstr + -> ('v, 'a * 'S, 'r, 'F) kinstr + | ICons_none : + Script.location * ('b, _) ty * ('b option, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IIf_none : { + loc : Script.location; + branch_if_none : ('b, 'S, 'c, 'T) kinstr; + branch_if_some : ('a, 'b * 'S, 'c, 'T) kinstr; + k : ('c, 'T, 'r, 'F) kinstr; + } + -> ('a option, 'b * 'S, 'r, 'F) kinstr + | IOpt_map : { + loc : Script.location; + body : ('a, 'S, 'b, 'S) kinstr; + k : ('b option, 'S, 'c, 'F) kinstr; + } + -> ('a option, 'S, 'c, 'F) kinstr + (* + Ors + ------ + *) + | ICons_left : + Script.location * ('b, _) ty * (('a, 'b) or_, 'c * 'S, 'r, 'F) kinstr + -> ('a, 'c * 'S, 'r, 'F) kinstr + | ICons_right : + Script.location * ('a, _) ty * (('a, 'b) or_, 'c * 'S, 'r, 'F) kinstr + -> ('b, 'c * 'S, 'r, 'F) kinstr + | IIf_left : { + loc : Script.location; + branch_if_left : ('a, 'S, 'c, 'T) kinstr; + branch_if_right : ('b, 'S, 'c, 'T) kinstr; + k : ('c, 'T, 'r, 'F) kinstr; + } + -> (('a, 'b) or_, 'S, 'r, 'F) kinstr + (* + Lists + ----- + *) + | ICons_list : + Script.location * ('a Script_list.t, 'S, 'r, 'F) kinstr + -> ('a, 'a Script_list.t * 'S, 'r, 'F) kinstr + | INil : + Script.location * ('b, _) ty * ('b Script_list.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IIf_cons : { + loc : Script.location; + branch_if_cons : ('a, 'a Script_list.t * ('b * 'S), 'c, 'T) kinstr; + branch_if_nil : ('b, 'S, 'c, 'T) kinstr; + k : ('c, 'T, 'r, 'F) kinstr; + } + -> ('a Script_list.t, 'b * 'S, 'r, 'F) kinstr + | IList_map : + Script.location + * ('a, 'c * 'S, 'b, 'c * 'S) kinstr + * ('b Script_list.t, _) ty option + * ('b Script_list.t, 'c * 'S, 'r, 'F) kinstr + -> ('a Script_list.t, 'c * 'S, 'r, 'F) kinstr + | IList_iter : + Script.location + * ('a, _) ty option + * ('a, 'b * 'S, 'b, 'S) kinstr + * ('b, 'S, 'r, 'F) kinstr + -> ('a Script_list.t, 'b * 'S, 'r, 'F) kinstr + | IList_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> ('a Script_list.t, 'S, 'r, 'F) kinstr + (* + Sets + ---- + *) + | IEmpty_set : + Script.location * 'b comparable_ty * ('b set, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISet_iter : + Script.location + * 'a comparable_ty option + * ('a, 'b * 'S, 'b, 'S) kinstr + * ('b, 'S, 'r, 'F) kinstr + -> ('a set, 'b * 'S, 'r, 'F) kinstr + | ISet_mem : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ('a, 'a set * 'S, 'r, 'F) kinstr + | ISet_update : + Script.location * ('a set, 'S, 'r, 'F) kinstr + -> ('a, bool * ('a set * 'S), 'r, 'F) kinstr + | ISet_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> ('a set, 'S, 'r, 'F) kinstr + (* + Maps + ---- + *) + | IEmpty_map : + Script.location + * 'b comparable_ty + * ('c, _) ty option + * (('b, 'c) map, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IMap_map : + Script.location + * (('a, 'c) map, _) ty option + * (('a, 'b) pair, 'd * 'S, 'c, 'd * 'S) kinstr + * (('a, 'c) map, 'd * 'S, 'r, 'F) kinstr + -> (('a, 'b) map, 'd * 'S, 'r, 'F) kinstr + | IMap_iter : + Script.location + * (('a, 'b) pair, _) ty option + * (('a, 'b) pair, 'c * 'S, 'c, 'S) kinstr + * ('c, 'S, 'r, 'F) kinstr + -> (('a, 'b) map, 'c * 'S, 'r, 'F) kinstr + | IMap_mem : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) map * 'S, 'r, 'F) kinstr + | IMap_get : + Script.location * ('b option, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) map * 'S, 'r, 'F) kinstr + | IMap_update : + Script.location * (('a, 'b) map, 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) map * 'S), 'r, 'F) kinstr + | IMap_get_and_update : + Script.location * ('b option, ('a, 'b) map * 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) map * 'S), 'r, 'F) kinstr + | IMap_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (('a, 'b) map, 'S, 'r, 'F) kinstr + (* + Big maps + -------- + *) + | IEmpty_big_map : + Script.location + * 'b comparable_ty + * ('c, _) ty + * (('b, 'c) big_map, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IBig_map_mem : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) big_map * 'S, 'r, 'F) kinstr + | IBig_map_get : + Script.location * ('b option, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) big_map * 'S, 'r, 'F) kinstr + | IBig_map_update : + Script.location * (('a, 'b) big_map, 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) big_map * 'S), 'r, 'F) kinstr + | IBig_map_get_and_update : + Script.location * ('b option, ('a, 'b) big_map * 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) big_map * 'S), 'r, 'F) kinstr + (* + Strings + ------- + *) + | IConcat_string : + Script.location * (Script_string.t, 'S, 'r, 'F) kinstr + -> (Script_string.t Script_list.t, 'S, 'r, 'F) kinstr + | IConcat_string_pair : + Script.location * (Script_string.t, 'S, 'r, 'F) kinstr + -> (Script_string.t, Script_string.t * 'S, 'r, 'F) kinstr + | ISlice_string : + Script.location * (Script_string.t option, 'S, 'r, 'F) kinstr + -> (n num, n num * (Script_string.t * 'S), 'r, 'F) kinstr + | IString_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (Script_string.t, 'S, 'r, 'F) kinstr + (* + Bytes + ----- + *) + | IConcat_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes Script_list.t, 'S, 'r, 'F) kinstr + | IConcat_bytes_pair : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | ISlice_bytes : + Script.location * (bytes option, 'S, 'r, 'F) kinstr + -> (n num, n num * (bytes * 'S), 'r, 'F) kinstr + | IBytes_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ILsl_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, n num * 'S, 'r, 'F) kinstr + | ILsr_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, n num * 'S, 'r, 'F) kinstr + | IOr_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | IAnd_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | IXor_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | INot_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | INat_bytes : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IBytes_nat : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (n num, 'S, 'r, 'F) kinstr + | IInt_bytes : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IBytes_int : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + (* + Timestamps + ---------- + *) + | IAdd_seconds_to_timestamp : + Script.location * (Script_timestamp.t, 'S, 'r, 'F) kinstr + -> (z num, Script_timestamp.t * 'S, 'r, 'F) kinstr + | IAdd_timestamp_to_seconds : + Script.location * (Script_timestamp.t, 'S, 'r, 'F) kinstr + -> (Script_timestamp.t, z num * 'S, 'r, 'F) kinstr + | ISub_timestamp_seconds : + Script.location * (Script_timestamp.t, 'S, 'r, 'F) kinstr + -> (Script_timestamp.t, z num * 'S, 'r, 'F) kinstr + | IDiff_timestamps : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (Script_timestamp.t, Script_timestamp.t * 'S, 'r, 'F) kinstr + (* + Tez + --- + *) + | IAdd_tez : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + | ISub_tez : + Script.location * (Tez.t option, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + | ISub_tez_legacy : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + | IMul_teznat : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (Tez.t, n num * 'S, 'r, 'F) kinstr + | IMul_nattez : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (n num, Tez.t * 'S, 'r, 'F) kinstr + | IEdiv_teznat : + Script.location * ((Tez.t, Tez.t) pair option, 'S, 'r, 'F) kinstr + -> (Tez.t, n num * 'S, 'r, 'F) kinstr + | IEdiv_tez : + Script.location * ((n num, Tez.t) pair option, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + (* + Booleans + -------- + *) + | IOr : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, bool * 'S, 'r, 'F) kinstr + | IAnd : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, bool * 'S, 'r, 'F) kinstr + | IXor : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, bool * 'S, 'r, 'F) kinstr + | INot : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, 'S, 'r, 'F) kinstr + (* + Integers + -------- + *) + | IIs_nat : + Script.location * (n num option, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | INeg : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'S, 'r, 'F) kinstr + | IAbs_int : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | IInt_nat : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (n num, 'S, 'r, 'F) kinstr + | IAdd_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IAdd_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | ISub_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IMul_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IMul_nat : + Script.location * ('a num, 'S, 'r, 'F) kinstr + -> (n num, 'a num * 'S, 'r, 'F) kinstr + | IEdiv_int : + Script.location * ((z num, n num) pair option, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IEdiv_nat : + Script.location * (('a num, n num) pair option, 'S, 'r, 'F) kinstr + -> (n num, 'a num * 'S, 'r, 'F) kinstr + | ILsl_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | ILsr_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | IOr_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + (* Even though `IAnd_nat` and `IAnd_int_nat` could be merged into a single + instruction from both the type and behavior point of views, their gas costs + differ too much (see `cost_N_IAnd_nat` and `cost_N_IAnd_int_nat` in + `Michelson_v1_gas.Cost_of.Generated_costs`), so we keep them separated. *) + | IAnd_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | IAnd_int_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (z num, n num * 'S, 'r, 'F) kinstr + | IXor_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | INot_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'S, 'r, 'F) kinstr + (* + Control + ------- + *) + | IIf : { + loc : Script.location; + branch_if_true : ('a, 'S, 'b, 'T) kinstr; + branch_if_false : ('a, 'S, 'b, 'T) kinstr; + k : ('b, 'T, 'r, 'F) kinstr; + } + -> (bool, 'a * 'S, 'r, 'F) kinstr + | ILoop : + Script.location * ('a, 'S, bool, 'a * 'S) kinstr * ('a, 'S, 'r, 'F) kinstr + -> (bool, 'a * 'S, 'r, 'F) kinstr + | ILoop_left : + Script.location + * ('a, 'S, ('a, 'b) or_, 'S) kinstr + * ('b, 'S, 'r, 'F) kinstr + -> (('a, 'b) or_, 'S, 'r, 'F) kinstr + | IDip : + Script.location + * ('b, 'S, 'c, 'T) kinstr + * ('a, _) ty option + * ('a, 'c * 'T, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IExec : + Script.location * ('b, 'S) stack_ty option * ('b, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) lambda * 'S, 'r, 'F) kinstr + | IApply : + Script.location * ('a, _) ty * (('b, 'c) lambda, 'S, 'r, 'F) kinstr + -> ('a, (('a, 'b) pair, 'c) lambda * 'S, 'r, 'F) kinstr + | ILambda : + Script.location + * ('b, 'c) lambda + * (('b, 'c) lambda, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IFailwith : Script.location * ('a, _) ty -> ('a, 'S, 'r, 'F) kinstr + (* + Comparison + ---------- + *) + | ICompare : + Script.location * 'a comparable_ty * (z num, 'b * 'S, 'r, 'F) kinstr + -> ('a, 'a * ('b * 'S), 'r, 'F) kinstr + (* + Comparators + ----------- + *) + | IEq : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | INeq : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | ILt : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | IGt : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | ILe : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | IGe : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + (* + Protocol + -------- + *) + | IAddress : + Script.location * (address, 'S, 'r, 'F) kinstr + -> ('a typed_contract, 'S, 'r, 'F) kinstr + | IContract : + Script.location + * ('a, _) ty + * Entrypoint.t + * ('a typed_contract option, 'S, 'r, 'F) kinstr + -> (address, 'S, 'r, 'F) kinstr + | IView : + Script.location + * ('a, 'b) view_signature + * ('c, 'S) stack_ty option + * ('b option, 'c * 'S, 'r, 'F) kinstr + -> ('a, address * ('c * 'S), 'r, 'F) kinstr + | ITransfer_tokens : + Script.location * (operation, 'S, 'r, 'F) kinstr + -> ('a, Tez.t * ('a typed_contract * 'S), 'r, 'F) kinstr + | IImplicit_account : + Script.location * (unit typed_contract, 'S, 'r, 'F) kinstr + -> (public_key_hash, 'S, 'r, 'F) kinstr + | ICreate_contract : { + loc : Script.location; + storage_type : ('a, _) ty; + code : Script.expr; + k : (operation, address * ('c * 'S), 'r, 'F) kinstr; + } + -> (public_key_hash option, Tez.t * ('a * ('c * 'S)), 'r, 'F) kinstr + | ISet_delegate : + Script.location * (operation, 'S, 'r, 'F) kinstr + -> (public_key_hash option, 'S, 'r, 'F) kinstr + | INow : + Script.location * (Script_timestamp.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IMin_block_time : + Script.location * (n num, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IBalance : + Script.location * (Tez.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ILevel : + Script.location * (n num, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ICheck_signature : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (public_key, signature * (bytes * 'S), 'r, 'F) kinstr + | IHash_key : + Script.location * (public_key_hash, 'S, 'r, 'F) kinstr + -> (public_key, 'S, 'r, 'F) kinstr + | IPack : + Script.location * ('a, _) ty * (bytes, 'b * 'S, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IUnpack : + Script.location * ('a, _) ty * ('a option, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IBlake2b : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISha256 : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISha512 : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISource : + Script.location * (address, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISender : + Script.location * (address, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISelf : + Script.location + * ('b, _) ty + * Entrypoint.t + * ('b typed_contract, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISelf_address : + Script.location * (address, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IAmount : + Script.location * (Tez.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISapling_empty_state : + Script.location + * Sapling.Memo_size.t + * (Sapling.state, 'a * 'S, 'b, 'F) kinstr + -> ('a, 'S, 'b, 'F) kinstr + | ISapling_verify_update : + Script.location + * ((bytes, (z num, Sapling.state) pair) pair option, 'S, 'r, 'F) kinstr + -> (Sapling.transaction, Sapling.state * 'S, 'r, 'F) kinstr + | ISapling_verify_update_deprecated : + Script.location * ((z num, Sapling.state) pair option, 'S, 'r, 'F) kinstr + -> (Sapling.Legacy.transaction, Sapling.state * 'S, 'r, 'F) kinstr + | IDig : + Script.location + * int + * ('b, 'c * 'T, 'c, 'T, 'a, 'S, 'd, 'U) stack_prefix_preservation_witness + * ('b, 'd * 'U, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IDug : + Script.location + * int + * ('c, 'T, 'a, 'c * 'T, 'b, 'S, 'd, 'U) stack_prefix_preservation_witness + * ('d, 'U, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IDipn : + Script.location + * int + * ('c, 'T, 'd, 'V, 'a, 'S, 'b, 'U) stack_prefix_preservation_witness + * ('c, 'T, 'd, 'V) kinstr + * ('b, 'U, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IDropn : + Script.location + * int + * ('b, 'U, 'b, 'U, 'a, 'S, 'a, 'S) stack_prefix_preservation_witness + * ('b, 'U, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IChainId : + Script.location * (Script_chain_id.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | INever : Script.location -> (never, 'S, 'r, 'F) kinstr + | IVoting_power : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (public_key_hash, 'S, 'r, 'F) kinstr + | ITotal_voting_power : + Script.location * (n num, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IKeccak : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISha3 : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IAdd_bls12_381_g1 : + Script.location * (Script_bls.G1.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G1.t, Script_bls.G1.t * 'S, 'r, 'F) kinstr + | IAdd_bls12_381_g2 : + Script.location * (Script_bls.G2.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G2.t, Script_bls.G2.t * 'S, 'r, 'F) kinstr + | IAdd_bls12_381_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_g1 : + Script.location * (Script_bls.G1.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G1.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_g2 : + Script.location * (Script_bls.G2.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G2.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_z_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, 'a num * 'S, 'r, 'F) kinstr + | IMul_bls12_381_fr_z : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> ('a num, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IInt_bls12_381_fr : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + | INeg_bls12_381_g1 : + Script.location * (Script_bls.G1.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G1.t, 'S, 'r, 'F) kinstr + | INeg_bls12_381_g2 : + Script.location * (Script_bls.G2.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G2.t, 'S, 'r, 'F) kinstr + | INeg_bls12_381_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + | IPairing_check_bls12_381 : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ( (Script_bls.G1.t, Script_bls.G2.t) pair Script_list.t, + 'S, + 'r, + 'F ) + kinstr + | IComb : + Script.location + * int + * ('a, 'b, 'S, 'c, 'd, 'T) comb_gadt_witness + * ('c, 'd * 'T, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IUncomb : + Script.location + * int + * ('a, 'b, 'S, 'c, 'd, 'T) uncomb_gadt_witness + * ('c, 'd * 'T, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IComb_get : + Script.location + * int + * ('t, 'v) comb_get_gadt_witness + * ('v, 'a * 'S, 'r, 'F) kinstr + -> ('t, 'a * 'S, 'r, 'F) kinstr + | IComb_set : + Script.location + * int + * ('a, 'b, 'c) comb_set_gadt_witness + * ('c, 'd * 'S, 'r, 'F) kinstr + -> ('a, 'b * ('d * 'S), 'r, 'F) kinstr + | IDup_n : + Script.location + * int + * ('a, 'b, 'S, 't) dup_n_gadt_witness + * ('t, 'a * ('b * 'S), 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | ITicket : + Script.location + * 'a comparable_ty option + * ('a ticket option, 'S, 'r, 'F) kinstr + -> ('a, n num * 'S, 'r, 'F) kinstr + | ITicket_deprecated : + Script.location * 'a comparable_ty option * ('a ticket, 'S, 'r, 'F) kinstr + -> ('a, n num * 'S, 'r, 'F) kinstr + | IRead_ticket : + Script.location + * 'a comparable_ty option + * ((address, ('a, n num) pair) pair, 'a ticket * 'S, 'r, 'F) kinstr + -> ('a ticket, 'S, 'r, 'F) kinstr + | ISplit_ticket : + Script.location * (('a ticket, 'a ticket) pair option, 'S, 'r, 'F) kinstr + -> ('a ticket, (n num, n num) pair * 'S, 'r, 'F) kinstr + | IJoin_tickets : + Script.location * 'a comparable_ty * ('a ticket option, 'S, 'r, 'F) kinstr + -> (('a ticket, 'a ticket) pair, 'S, 'r, 'F) kinstr + | IOpen_chest : + Script.location * (bytes option, 'S, 'r, 'F) kinstr + -> ( Script_timelock.chest_key, + Script_timelock.chest * (n num * 'S), + 'r, + 'F ) + kinstr + | IEmit : { + loc : Script.location; + tag : Entrypoint.t; + ty : ('a, _) ty; + unparsed_ty : Script.expr; + k : (operation, 'S, 'r, 'F) kinstr; + } + -> ('a, 'S, 'r, 'F) kinstr + (* + Internal control instructions + ----------------------------- + *) + | IHalt : Script.location -> ('a, 'S, 'a, 'S) kinstr + | ILog : + Script.location + * ('a, 'S) stack_ty + * logging_event + * logger + * ('a, 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + +and ('arg, 'ret) lambda = + | Lam : + ('arg, end_of_stack, 'ret, end_of_stack) kdescr * Script.node + -> ('arg, 'ret) lambda + | LamRec : + ('arg, ('arg, 'ret) lambda * end_of_stack, 'ret, end_of_stack) kdescr + * Script.node + -> ('arg, 'ret) lambda + +and 'arg typed_contract = + | Typed_implicit : public_key_hash -> unit typed_contract + | Typed_implicit_with_ticket : { + ticket_ty : ('arg ticket, _) ty; + destination : public_key_hash; + } + -> 'arg ticket typed_contract + | Typed_originated : { + arg_ty : ('arg, _) ty; + contract_hash : Contract_hash.t; + entrypoint : Entrypoint.t; + } + -> 'arg typed_contract + | Typed_sc_rollup : { + arg_ty : ('arg, _) ty; + sc_rollup : Sc_rollup.t; + entrypoint : Entrypoint.t; + } + -> 'arg typed_contract + | Typed_zk_rollup : { + arg_ty : (('a ticket, bytes) pair, _) ty; + zk_rollup : Zk_rollup.t; + } + -> ('a ticket, bytes) pair typed_contract + +and (_, _, _, _) continuation = + | KNil : ('r, 'F, 'r, 'F) continuation + | KCons : + ('a, 'S, 'b, 'T) kinstr * ('b, 'T, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + | KReturn : + 'S * ('a, 'S) stack_ty option * ('a, 'S, 'r, 'F) continuation + -> ('a, end_of_stack, 'r, 'F) continuation + | KMap_head : + ('a -> 'b) * ('b, 'S, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + | KUndip : + 'b * ('b, _) ty option * ('b, 'a * 'S, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + | KLoop_in : + ('a, 'S, bool, 'a * 'S) kinstr * ('a, 'S, 'r, 'F) continuation + -> (bool, 'a * 'S, 'r, 'F) continuation + | KLoop_in_left : + ('a, 'S, ('a, 'b) or_, 'S) kinstr * ('b, 'S, 'r, 'F) continuation + -> (('a, 'b) or_, 'S, 'r, 'F) continuation + | KIter : + ('a, 'b * 'S, 'b, 'S) kinstr + * ('a, _) ty option + * 'a list + * ('b, 'S, 'r, 'F) continuation + -> ('b, 'S, 'r, 'F) continuation + | KList_enter_body : + ('a, 'c * 'S, 'b, 'c * 'S) kinstr + * 'a list + * 'b Script_list.t + * ('b Script_list.t, _) ty option + * int + * ('b Script_list.t, 'c * 'S, 'r, 'F) continuation + -> ('c, 'S, 'r, 'F) continuation + | KList_exit_body : + ('a, 'c * 'S, 'b, 'c * 'S) kinstr + * 'a list + * 'b Script_list.t + * ('b Script_list.t, _) ty option + * int + * ('b Script_list.t, 'c * 'S, 'r, 'F) continuation + -> ('b, 'c * 'S, 'r, 'F) continuation + | KMap_enter_body : + (('a, 'b) pair, 'd * 'S, 'c, 'd * 'S) kinstr + * ('a, 'b) pair list + * ('a, 'c) map + * (('a, 'c) map, _) ty option + * (('a, 'c) map, 'd * 'S, 'r, 'F) continuation + -> ('d, 'S, 'r, 'F) continuation + | KMap_exit_body : + (('a, 'b) pair, 'd * 'S, 'c, 'd * 'S) kinstr + * ('a, 'b) pair list + * ('a, 'c) map + * 'a + * (('a, 'c) map, _) ty option + * (('a, 'c) map, 'd * 'S, 'r, 'F) continuation + -> ('c, 'd * 'S, 'r, 'F) continuation + | KView_exit : + step_constants * ('a, 'S, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + | KLog : + ('a, 'S, 'r, 'F) continuation * ('a, 'S) stack_ty * logger + -> ('a, 'S, 'r, 'F) continuation + +and ('a, 'S, 'b, 'F, 'c, 'U) logging_function = + ('a, 'S, 'b, 'F) kinstr -> + context -> + Script.location -> + ('c, 'U) stack_ty -> + 'c * 'U -> + unit + +and execution_trace = (Script.location * Gas.Arith.fp * Script.expr list) list + +and logger = { + log_interp : 'a 'S 'b 'F 'c 'U. ('a, 'S, 'b, 'F, 'c, 'U) logging_function; + get_log : unit -> execution_trace option tzresult Lwt.t; + klog : 'a 'S 'r 'F. ('a, 'S, 'r, 'F) klog; + ilog : 'a 'S 'b 'T 'r 'F. ('a, 'S, 'b, 'T, 'r, 'F) ilog; + log_kinstr : 'a 'b 'c 'd. ('a, 'b, 'c, 'd) log_kinstr; +} + +and ('a, 'S, 'r, 'F) klog = + logger -> + Local_gas_counter.outdated_context * step_constants -> + Local_gas_counter.local_gas_counter -> + ('a, 'S) stack_ty -> + ('a, 'S, 'r, 'F) continuation -> + ('a, 'S, 'r, 'F) continuation -> + 'a -> + 'S -> + ('r + * 'F + * Local_gas_counter.outdated_context + * Local_gas_counter.local_gas_counter) + tzresult + Lwt.t + +and ('a, 'S, 'b, 'T, 'r, 'F) ilog = + logger -> + logging_event -> + ('a, 'S) stack_ty -> + ('a, 'S, 'b, 'T, 'r, 'F) step_type + +and ('a, 'S, 'b, 'T, 'r, 'F) step_type = + Local_gas_counter.outdated_context * step_constants -> + Local_gas_counter.local_gas_counter -> + ('a, 'S, 'b, 'T) kinstr -> + ('b, 'T, 'r, 'F) continuation -> + 'a -> + 'S -> + ('r + * 'F + * Local_gas_counter.outdated_context + * Local_gas_counter.local_gas_counter) + tzresult + Lwt.t + +and ('a, 'b, 'c, 'd) log_kinstr = + logger -> + ('a, 'b) stack_ty -> + ('a, 'b, 'c, 'd) kinstr -> + ('a, 'b, 'c, 'd) kinstr + +(* ---- Auxiliary types -----------------------------------------------------*) +and ('ty, 'comparable) ty = + | Unit_t : (unit, yes) ty + | Int_t : (z num, yes) ty + | Nat_t : (n num, yes) ty + | Signature_t : (signature, yes) ty + | String_t : (Script_string.t, yes) ty + | Bytes_t : (bytes, yes) ty + | Mutez_t : (Tez.t, yes) ty + | Key_hash_t : (public_key_hash, yes) ty + | Key_t : (public_key, yes) ty + | Timestamp_t : (Script_timestamp.t, yes) ty + | Address_t : (address, yes) ty + | Bool_t : (bool, yes) ty + | Pair_t : + ('a, 'ac) ty + * ('b, 'bc) ty + * ('a, 'b) pair ty_metadata + * ('ac, 'bc, 'rc) dand + -> (('a, 'b) pair, 'rc) ty + | Or_t : + ('a, 'ac) ty + * ('b, 'bc) ty + * ('a, 'b) or_ ty_metadata + * ('ac, 'bc, 'rc) dand + -> (('a, 'b) or_, 'rc) ty + | Lambda_t : + ('arg, _) ty * ('ret, _) ty * ('arg, 'ret) lambda ty_metadata + -> (('arg, 'ret) lambda, no) ty + | Option_t : + ('v, 'c) ty * 'v option ty_metadata * 'c dbool + -> ('v option, 'c) ty + | List_t : + ('v, _) ty * 'v Script_list.t ty_metadata + -> ('v Script_list.t, no) ty + | Set_t : 'v comparable_ty * 'v set ty_metadata -> ('v set, no) ty + | Map_t : + 'k comparable_ty * ('v, _) ty * ('k, 'v) map ty_metadata + -> (('k, 'v) map, no) ty + | Big_map_t : + 'k comparable_ty * ('v, _) ty * ('k, 'v) big_map ty_metadata + -> (('k, 'v) big_map, no) ty + | Contract_t : + ('arg, _) ty * 'arg typed_contract ty_metadata + -> ('arg typed_contract, no) ty + | Sapling_transaction_t : Sapling.Memo_size.t -> (Sapling.transaction, no) ty + | Sapling_transaction_deprecated_t : + Sapling.Memo_size.t + -> (Sapling.Legacy.transaction, no) ty + | Sapling_state_t : Sapling.Memo_size.t -> (Sapling.state, no) ty + | Operation_t : (operation, no) ty + | Chain_id_t : (Script_chain_id.t, yes) ty + | Never_t : (never, yes) ty + | Bls12_381_g1_t : (Script_bls.G1.t, no) ty + | Bls12_381_g2_t : (Script_bls.G2.t, no) ty + | Bls12_381_fr_t : (Script_bls.Fr.t, no) ty + | Ticket_t : 'a comparable_ty * 'a ticket ty_metadata -> ('a ticket, no) ty + | Chest_key_t : (Script_timelock.chest_key, no) ty + | Chest_t : (Script_timelock.chest, no) ty + +and 'ty comparable_ty = ('ty, yes) ty + +and ('top_ty, 'resty) stack_ty = + | Item_t : + ('ty, _) ty * ('ty2, 'rest) stack_ty + -> ('ty, 'ty2 * 'rest) stack_ty + | Bot_t : (empty_cell, empty_cell) stack_ty + +and ('key, 'value) big_map = + | Big_map : { + id : Big_map.Id.t option; + diff : ('key, 'value) big_map_overlay; + key_type : 'key comparable_ty; + value_type : ('value, _) ty; + } + -> ('key, 'value) big_map + +and ('a, 'S, 'r, 'F) kdescr = { + kloc : Script.location; + kbef : ('a, 'S) stack_ty; + kaft : ('r, 'F) stack_ty; + kinstr : ('a, 'S, 'r, 'F) kinstr; +} + +and (_, _, _, _, _, _, _, _) stack_prefix_preservation_witness = + | KPrefix : + Script.location + * ('a, _) ty + * ('c, 'V, 'd, 'W, 'x, 'S, 'y, 'U) stack_prefix_preservation_witness + -> ( 'c, + 'V, + 'd, + 'W, + 'a, + 'x * 'S, + 'a, + 'y * 'U ) + stack_prefix_preservation_witness + | KRest : ('a, 'S, 'b, 'U, 'a, 'S, 'b, 'U) stack_prefix_preservation_witness + +and (_, _, _, _, _, _) comb_gadt_witness = + | Comb_one : ('a, 'x, 'before, 'a, 'x, 'before) comb_gadt_witness + | Comb_succ : + ('b, 'c, 'S, 'd, 'e, 'T) comb_gadt_witness + -> ('a, 'b, 'c * 'S, 'a * 'd, 'e, 'T) comb_gadt_witness + +and (_, _, _, _, _, _) uncomb_gadt_witness = + | Uncomb_one : ('a, 'x, 'before, 'a, 'x, 'before) uncomb_gadt_witness + | Uncomb_succ : + ('b, 'c, 'S, 'd, 'e, 'T) uncomb_gadt_witness + -> (('a, 'b) pair, 'c, 'S, 'a, 'd, 'e * 'T) uncomb_gadt_witness + +and ('before, 'after) comb_get_gadt_witness = + | Comb_get_zero : ('b, 'b) comb_get_gadt_witness + | Comb_get_one : (('a, 'b) pair, 'a) comb_get_gadt_witness + | Comb_get_plus_two : + ('before, 'after) comb_get_gadt_witness + -> (('a, 'before) pair, 'after) comb_get_gadt_witness + +and ('value, 'before, 'after) comb_set_gadt_witness = + | Comb_set_zero : ('value, _, 'value) comb_set_gadt_witness + | Comb_set_one + : ('value, ('hd, 'tl) pair, ('value, 'tl) pair) comb_set_gadt_witness + | Comb_set_plus_two : + ('value, 'before, 'after) comb_set_gadt_witness + -> ('value, ('a, 'before) pair, ('a, 'after) pair) comb_set_gadt_witness + +and (_, _, _, _) dup_n_gadt_witness = + | Dup_n_zero : ('a, _, _, 'a) dup_n_gadt_witness + | Dup_n_succ : + ('b, 'c, 'stack, 'd) dup_n_gadt_witness + -> ('a, 'b, 'c * 'stack, 'd) dup_n_gadt_witness + +and ('input, 'output) view_signature = + | View_signature : { + name : Script_string.t; + input_ty : ('input, _) ty; + output_ty : ('output, _) ty; + } + -> ('input, 'output) view_signature + +and 'kind internal_operation_contents = + | Transaction_to_implicit : { + destination : Signature.Public_key_hash.t; + amount : Tez.t; + } + -> Kind.transaction internal_operation_contents + | Transaction_to_implicit_with_ticket : { + destination : Signature.Public_key_hash.t; + ticket_ty : ('content ticket, _) ty; + ticket : 'content ticket; + unparsed_ticket : Script.lazy_expr; + amount : Tez.t; + } + -> Kind.transaction internal_operation_contents + | Transaction_to_smart_contract : { + destination : Contract_hash.t; + amount : Tez.t; + entrypoint : Entrypoint.t; + location : Script.location; + parameters_ty : ('a, _) ty; + parameters : 'a; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents + | Transaction_to_sc_rollup : { + destination : Sc_rollup.t; + entrypoint : Entrypoint.t; + parameters_ty : ('a, _) ty; + parameters : 'a; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents + | Event : { + ty : Script.expr; + tag : Entrypoint.t; + unparsed_data : Script.expr; + } + -> Kind.event internal_operation_contents + | Transaction_to_zk_rollup : { + destination : Zk_rollup.t; + parameters_ty : (('a ticket, bytes) pair, _) ty; + parameters : ('a ticket, bytes) pair; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents + | Origination : { + delegate : Signature.Public_key_hash.t option; + code : Script.expr; + unparsed_storage : Script.expr; + credit : Tez.t; + preorigination : Contract_hash.t; + storage_type : ('storage, _) ty; + storage : 'storage; + } + -> Kind.origination internal_operation_contents + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation internal_operation_contents + +and 'kind internal_operation = { + sender : Destination.t; + operation : 'kind internal_operation_contents; + nonce : int; +} + +and packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation +[@@ocaml.unboxed] + +and operation = { + piop : packed_internal_operation; + lazy_storage_diff : Lazy_storage.diffs option; +} + +type ex_ty = Ex_ty : ('a, _) ty -> ex_ty + +type ('arg, 'storage) script = + | Script : { + code : + (('arg, 'storage) pair, (operation Script_list.t, 'storage) pair) lambda; + arg_type : ('arg, _) ty; + storage : 'storage; + storage_type : ('storage, _) ty; + views : view_map; + entrypoints : 'arg entrypoints; + code_size : Cache_memory_helpers.sint; + (* This is an over-approximation of the value size in memory, in + bytes, of the contract's static part, that is its source + code. This includes the code of the contract as well as the code + of the views. The storage size is not taken into account by this + field as it has a dynamic size. *) + } + -> ('arg, 'storage) script + +let manager_kind : + type kind. kind internal_operation_contents -> kind Kind.manager = function + | Transaction_to_implicit _ -> Kind.Transaction_manager_kind + | Transaction_to_implicit_with_ticket _ -> Kind.Transaction_manager_kind + | Transaction_to_smart_contract _ -> Kind.Transaction_manager_kind + | Transaction_to_sc_rollup _ -> Kind.Transaction_manager_kind + | Transaction_to_zk_rollup _ -> Kind.Transaction_manager_kind + | Event _ -> Kind.Event_manager_kind + | Origination _ -> Kind.Origination_manager_kind + | Delegation _ -> Kind.Delegation_manager_kind + +let kinstr_location : type a s b f. (a, s, b, f) kinstr -> Script.location = + fun i -> + match i with + | IDrop (loc, _) -> loc + | IDup (loc, _) -> loc + | ISwap (loc, _) -> loc + | IPush (loc, _, _, _) -> loc + | IUnit (loc, _) -> loc + | ICons_pair (loc, _) -> loc + | ICar (loc, _) -> loc + | ICdr (loc, _) -> loc + | IUnpair (loc, _) -> loc + | ICons_some (loc, _) -> loc + | ICons_none (loc, _, _) -> loc + | IIf_none {loc; _} -> loc + | IOpt_map {loc; _} -> loc + | ICons_left (loc, _, _) -> loc + | ICons_right (loc, _, _) -> loc + | IIf_left {loc; _} -> loc + | ICons_list (loc, _) -> loc + | INil (loc, _, _) -> loc + | IIf_cons {loc; _} -> loc + | IList_map (loc, _, _, _) -> loc + | IList_iter (loc, _, _, _) -> loc + | IList_size (loc, _) -> loc + | IEmpty_set (loc, _, _) -> loc + | ISet_iter (loc, _, _, _) -> loc + | ISet_mem (loc, _) -> loc + | ISet_update (loc, _) -> loc + | ISet_size (loc, _) -> loc + | IEmpty_map (loc, _, _, _) -> loc + | IMap_map (loc, _, _, _) -> loc + | IMap_iter (loc, _, _, _) -> loc + | IMap_mem (loc, _) -> loc + | IMap_get (loc, _) -> loc + | IMap_update (loc, _) -> loc + | IMap_get_and_update (loc, _) -> loc + | IMap_size (loc, _) -> loc + | IEmpty_big_map (loc, _, _, _) -> loc + | IBig_map_mem (loc, _) -> loc + | IBig_map_get (loc, _) -> loc + | IBig_map_update (loc, _) -> loc + | IBig_map_get_and_update (loc, _) -> loc + | IConcat_string (loc, _) -> loc + | IConcat_string_pair (loc, _) -> loc + | ISlice_string (loc, _) -> loc + | IString_size (loc, _) -> loc + | IConcat_bytes (loc, _) -> loc + | IConcat_bytes_pair (loc, _) -> loc + | ISlice_bytes (loc, _) -> loc + | IBytes_size (loc, _) -> loc + | ILsl_bytes (loc, _) -> loc + | ILsr_bytes (loc, _) -> loc + | IOr_bytes (loc, _) -> loc + | IAnd_bytes (loc, _) -> loc + | IXor_bytes (loc, _) -> loc + | INot_bytes (loc, _) -> loc + | INat_bytes (loc, _) -> loc + | IBytes_nat (loc, _) -> loc + | IInt_bytes (loc, _) -> loc + | IBytes_int (loc, _) -> loc + | IAdd_seconds_to_timestamp (loc, _) -> loc + | IAdd_timestamp_to_seconds (loc, _) -> loc + | ISub_timestamp_seconds (loc, _) -> loc + | IDiff_timestamps (loc, _) -> loc + | IAdd_tez (loc, _) -> loc + | ISub_tez (loc, _) -> loc + | ISub_tez_legacy (loc, _) -> loc + | IMul_teznat (loc, _) -> loc + | IMul_nattez (loc, _) -> loc + | IEdiv_teznat (loc, _) -> loc + | IEdiv_tez (loc, _) -> loc + | IOr (loc, _) -> loc + | IAnd (loc, _) -> loc + | IXor (loc, _) -> loc + | INot (loc, _) -> loc + | IIs_nat (loc, _) -> loc + | INeg (loc, _) -> loc + | IAbs_int (loc, _) -> loc + | IInt_nat (loc, _) -> loc + | IAdd_int (loc, _) -> loc + | IAdd_nat (loc, _) -> loc + | ISub_int (loc, _) -> loc + | IMul_int (loc, _) -> loc + | IMul_nat (loc, _) -> loc + | IEdiv_int (loc, _) -> loc + | IEdiv_nat (loc, _) -> loc + | ILsl_nat (loc, _) -> loc + | ILsr_nat (loc, _) -> loc + | IOr_nat (loc, _) -> loc + | IAnd_nat (loc, _) -> loc + | IAnd_int_nat (loc, _) -> loc + | IXor_nat (loc, _) -> loc + | INot_int (loc, _) -> loc + | IIf {loc; _} -> loc + | ILoop (loc, _, _) -> loc + | ILoop_left (loc, _, _) -> loc + | IDip (loc, _, _, _) -> loc + | IExec (loc, _, _) -> loc + | IApply (loc, _, _) -> loc + | ILambda (loc, _, _) -> loc + | IFailwith (loc, _) -> loc + | ICompare (loc, _, _) -> loc + | IEq (loc, _) -> loc + | INeq (loc, _) -> loc + | ILt (loc, _) -> loc + | IGt (loc, _) -> loc + | ILe (loc, _) -> loc + | IGe (loc, _) -> loc + | IAddress (loc, _) -> loc + | IContract (loc, _, _, _) -> loc + | ITransfer_tokens (loc, _) -> loc + | IView (loc, _, _, _) -> loc + | IImplicit_account (loc, _) -> loc + | ICreate_contract {loc; _} -> loc + | ISet_delegate (loc, _) -> loc + | INow (loc, _) -> loc + | IMin_block_time (loc, _) -> loc + | IBalance (loc, _) -> loc + | ILevel (loc, _) -> loc + | ICheck_signature (loc, _) -> loc + | IHash_key (loc, _) -> loc + | IPack (loc, _, _) -> loc + | IUnpack (loc, _, _) -> loc + | IBlake2b (loc, _) -> loc + | ISha256 (loc, _) -> loc + | ISha512 (loc, _) -> loc + | ISource (loc, _) -> loc + | ISender (loc, _) -> loc + | ISelf (loc, _, _, _) -> loc + | ISelf_address (loc, _) -> loc + | IAmount (loc, _) -> loc + | ISapling_empty_state (loc, _, _) -> loc + | ISapling_verify_update (loc, _) -> loc + | ISapling_verify_update_deprecated (loc, _) -> loc + | IDig (loc, _, _, _) -> loc + | IDug (loc, _, _, _) -> loc + | IDipn (loc, _, _, _, _) -> loc + | IDropn (loc, _, _, _) -> loc + | IChainId (loc, _) -> loc + | INever loc -> loc + | IVoting_power (loc, _) -> loc + | ITotal_voting_power (loc, _) -> loc + | IKeccak (loc, _) -> loc + | ISha3 (loc, _) -> loc + | IAdd_bls12_381_g1 (loc, _) -> loc + | IAdd_bls12_381_g2 (loc, _) -> loc + | IAdd_bls12_381_fr (loc, _) -> loc + | IMul_bls12_381_g1 (loc, _) -> loc + | IMul_bls12_381_g2 (loc, _) -> loc + | IMul_bls12_381_fr (loc, _) -> loc + | IMul_bls12_381_z_fr (loc, _) -> loc + | IMul_bls12_381_fr_z (loc, _) -> loc + | IInt_bls12_381_fr (loc, _) -> loc + | INeg_bls12_381_g1 (loc, _) -> loc + | INeg_bls12_381_g2 (loc, _) -> loc + | INeg_bls12_381_fr (loc, _) -> loc + | IPairing_check_bls12_381 (loc, _) -> loc + | IComb (loc, _, _, _) -> loc + | IUncomb (loc, _, _, _) -> loc + | IComb_get (loc, _, _, _) -> loc + | IComb_set (loc, _, _, _) -> loc + | IDup_n (loc, _, _, _) -> loc + | ITicket (loc, _, _) -> loc + | ITicket_deprecated (loc, _, _) -> loc + | IRead_ticket (loc, _, _) -> loc + | ISplit_ticket (loc, _) -> loc + | IJoin_tickets (loc, _, _) -> loc + | IOpen_chest (loc, _) -> loc + | IEmit {loc; _} -> loc + | IHalt loc -> loc + | ILog (loc, _, _, _, _) -> loc + +let meta_basic = {size = Type_size.one} + +let meta_compound1 loc ({size} : _ ty_metadata) : _ ty_metadata tzresult = + let open Result_syntax in + let+ size = Type_size.compound1 loc size in + {size} + +let meta_compound2 loc ({size = size1} : _ ty_metadata) + ({size = size2} : _ ty_metadata) : _ ty_metadata tzresult = + let open Result_syntax in + let+ size = Type_size.compound2 loc size1 size2 in + {size} + +let unit_metadata : unit ty_metadata = meta_basic + +let never_metadata : never ty_metadata = meta_basic + +let int_metadata : z num ty_metadata = meta_basic + +let nat_metadata : n num ty_metadata = meta_basic + +let signature_metadata : signature ty_metadata = meta_basic + +let string_metadata : Script_string.t ty_metadata = meta_basic + +let bytes_metadata : bytes ty_metadata = meta_basic + +let mutez_metadata : Tez.t ty_metadata = meta_basic + +let bool_metadata : bool ty_metadata = meta_basic + +let key_hash_metadata : public_key_hash ty_metadata = meta_basic + +let key_metadata : public_key ty_metadata = meta_basic + +let timestamp_metadata : Script_timestamp.t ty_metadata = meta_basic + +let chain_id_metadata : Script_chain_id.t ty_metadata = meta_basic + +let address_metadata : address ty_metadata = meta_basic + +let sapling_transaction_metadata : Sapling.transaction ty_metadata = meta_basic + +let sapling_transaction_deprecated_metadata : + Sapling.Legacy.transaction ty_metadata = + meta_basic + +let sapling_state_metadata : Sapling.state ty_metadata = meta_basic + +let operation_metadata : operation ty_metadata = meta_basic + +let bls12_381_g1_metadata : Script_bls.G1.t ty_metadata = meta_basic + +let bls12_381_g2_metadata : Script_bls.G2.t ty_metadata = meta_basic + +let bls12_381_fr_metadata : Script_bls.Fr.t ty_metadata = meta_basic + +let chest_metadata : Script_timelock.chest ty_metadata = meta_basic + +let chest_key_metadata : Script_timelock.chest_key ty_metadata = meta_basic + +let pair_metadata : + Script.location -> + 'a ty_metadata -> + 'b ty_metadata -> + ('a, 'b) pair ty_metadata tzresult = + meta_compound2 + +let or_metadata : + Script.location -> + 'a ty_metadata -> + 'b ty_metadata -> + ('a, 'b) or_ ty_metadata tzresult = + meta_compound2 + +let lambda_metadata : + Script.location -> + 'a ty_metadata -> + 'b ty_metadata -> + ('a, 'b) lambda ty_metadata tzresult = + meta_compound2 + +let option_metadata : + Script.location -> 'a ty_metadata -> 'a option ty_metadata tzresult = + meta_compound1 + +let list_metadata : + Script.location -> 'a ty_metadata -> 'a Script_list.t ty_metadata tzresult = + meta_compound1 + +let set_metadata : + Script.location -> 'a ty_metadata -> 'a set ty_metadata tzresult = + meta_compound1 + +let map_metadata : + Script.location -> + 'a ty_metadata -> + 'b ty_metadata -> + ('a, 'b) map ty_metadata tzresult = + meta_compound2 + +let big_map_metadata : + Script.location -> + 'a ty_metadata -> + 'b ty_metadata -> + ('a, 'b) big_map ty_metadata tzresult = + meta_compound2 + +let contract_metadata : + Script.location -> 'a ty_metadata -> 'a typed_contract ty_metadata tzresult + = + meta_compound1 + +let ticket_metadata : + Script.location -> 'a ty_metadata -> 'a ticket ty_metadata tzresult = + meta_compound1 + +let ty_metadata : type a ac. (a, ac) ty -> a ty_metadata = function + | Unit_t -> unit_metadata + | Never_t -> never_metadata + | Int_t -> int_metadata + | Nat_t -> nat_metadata + | Signature_t -> signature_metadata + | String_t -> string_metadata + | Bytes_t -> bytes_metadata + | Mutez_t -> mutez_metadata + | Bool_t -> bool_metadata + | Key_hash_t -> key_hash_metadata + | Key_t -> key_metadata + | Timestamp_t -> timestamp_metadata + | Chain_id_t -> chain_id_metadata + | Address_t -> address_metadata + | Pair_t (_, _, meta, _) -> meta + | Or_t (_, _, meta, _) -> meta + | Option_t (_, meta, _) -> meta + | Lambda_t (_, _, meta) -> meta + | List_t (_, meta) -> meta + | Set_t (_, meta) -> meta + | Map_t (_, _, meta) -> meta + | Big_map_t (_, _, meta) -> meta + | Ticket_t (_, meta) -> meta + | Contract_t (_, meta) -> meta + | Sapling_transaction_t _ -> sapling_transaction_metadata + | Sapling_transaction_deprecated_t _ -> + sapling_transaction_deprecated_metadata + | Sapling_state_t _ -> sapling_state_metadata + | Operation_t -> operation_metadata + | Bls12_381_g1_t -> bls12_381_g1_metadata + | Bls12_381_g2_t -> bls12_381_g2_metadata + | Bls12_381_fr_t -> bls12_381_fr_metadata + | Chest_t -> chest_metadata + | Chest_key_t -> chest_key_metadata + +let ty_size t = (ty_metadata t).size + +let is_comparable : type v c. (v, c) ty -> c dbool = function + | Never_t -> Yes + | Unit_t -> Yes + | Int_t -> Yes + | Nat_t -> Yes + | Signature_t -> Yes + | String_t -> Yes + | Bytes_t -> Yes + | Mutez_t -> Yes + | Bool_t -> Yes + | Key_hash_t -> Yes + | Key_t -> Yes + | Timestamp_t -> Yes + | Chain_id_t -> Yes + | Address_t -> Yes + | Pair_t (_, _, _, dand) -> dbool_of_dand dand + | Or_t (_, _, _, dand) -> dbool_of_dand dand + | Option_t (_, _, cmp) -> cmp + | Lambda_t _ -> No + | List_t _ -> No + | Set_t _ -> No + | Map_t _ -> No + | Big_map_t _ -> No + | Ticket_t _ -> No + | Contract_t _ -> No + | Sapling_transaction_t _ -> No + | Sapling_transaction_deprecated_t _ -> No + | Sapling_state_t _ -> No + | Operation_t -> No + | Bls12_381_g1_t -> No + | Bls12_381_g2_t -> No + | Bls12_381_fr_t -> No + | Chest_t -> No + | Chest_key_t -> No + +type 'v ty_ex_c = Ty_ex_c : ('v, _) ty -> 'v ty_ex_c [@@ocaml.unboxed] + +let assert_ok1 f x = + match f Micheline.dummy_location x with + | Ok res -> res + | Error _ -> assert false + +let assert_ok2 f x y = + match f Micheline.dummy_location x y with + | Ok res -> res + | Error _ -> assert false + +let unit_t = Unit_t + +let int_t = Int_t + +let nat_t = Nat_t + +let signature_t = Signature_t + +let string_t = String_t + +let bytes_t = Bytes_t + +let mutez_t = Mutez_t + +let key_hash_t = Key_hash_t + +let key_t = Key_t + +let timestamp_t = Timestamp_t + +let address_t = Address_t + +let bool_t = Bool_t + +let pair_t : + type a ac b bc. + Script.location -> (a, ac) ty -> (b, bc) ty -> (a, b) pair ty_ex_c tzresult + = + fun loc l r -> + let open Result_syntax in + let+ metadata = pair_metadata loc (ty_metadata l) (ty_metadata r) in + let (Ex_dand cmp) = dand (is_comparable l) (is_comparable r) in + Ty_ex_c (Pair_t (l, r, metadata, cmp)) + +let pair_3_t loc l m r = + let open Result_syntax in + let* (Ty_ex_c r) = pair_t loc m r in + pair_t loc l r + +let comparable_pair_t loc l r = + let open Result_syntax in + let+ metadata = pair_metadata loc (ty_metadata l) (ty_metadata r) in + Pair_t (l, r, metadata, YesYes) + +let comparable_pair_3_t loc l m r = + let open Result_syntax in + let* r = comparable_pair_t loc m r in + comparable_pair_t loc l r + +let pair_int_int_unit_t = + let iu_metadata = assert_ok2 pair_metadata int_metadata unit_metadata in + let iiu_metadata = assert_ok2 pair_metadata int_metadata iu_metadata in + Pair_t + (int_t, Pair_t (int_t, unit_t, iu_metadata, YesYes), iiu_metadata, YesYes) + +let or_t : + type a ac b bc. + Script.location -> (a, ac) ty -> (b, bc) ty -> (a, b) or_ ty_ex_c tzresult = + let open Result_syntax in + fun loc l r -> + let+ metadata = or_metadata loc (ty_metadata l) (ty_metadata r) in + let (Ex_dand cmp) = dand (is_comparable l) (is_comparable r) in + Ty_ex_c (Or_t (l, r, metadata, cmp)) + +let or_bytes_bool_t = + Or_t + ( bytes_t, + bool_t, + assert_ok2 or_metadata bytes_metadata bool_metadata, + YesYes ) + +let comparable_or_t loc l r = + let open Result_syntax in + let+ metadata = or_metadata loc (ty_metadata l) (ty_metadata r) in + Or_t (l, r, metadata, YesYes) + +let lambda_t loc l r = + let open Result_syntax in + let+ metadata = lambda_metadata loc (ty_metadata l) (ty_metadata r) in + Lambda_t (l, r, metadata) + +let option_t loc t = + let open Result_syntax in + let+ metadata = option_metadata loc (ty_metadata t) in + let cmp = is_comparable t in + Option_t (t, metadata, cmp) + +let option_mutez_t = + Option_t (mutez_t, assert_ok1 option_metadata mutez_metadata, Yes) + +let option_string_t = + Option_t (string_t, assert_ok1 option_metadata string_metadata, Yes) + +let option_bytes_t = + Option_t (bytes_t, assert_ok1 option_metadata bytes_metadata, Yes) + +let option_nat_t = Option_t (nat_t, assert_ok1 option_metadata nat_metadata, Yes) + +let option_pair_nat_nat_t = + let pmetadata = assert_ok2 pair_metadata nat_metadata nat_metadata in + let ometadata = assert_ok1 option_metadata pmetadata in + Option_t (Pair_t (nat_t, nat_t, pmetadata, YesYes), ometadata, Yes) + +let option_pair_nat_mutez_t = + let pmetadata = assert_ok2 pair_metadata nat_metadata mutez_metadata in + let ometadata = assert_ok1 option_metadata pmetadata in + Option_t (Pair_t (nat_t, mutez_t, pmetadata, YesYes), ometadata, Yes) + +let option_pair_mutez_mutez_t = + let pmetadata = assert_ok2 pair_metadata mutez_metadata mutez_metadata in + let ometadata = assert_ok1 option_metadata pmetadata in + Option_t (Pair_t (mutez_t, mutez_t, pmetadata, YesYes), ometadata, Yes) + +let option_pair_int_nat_t = + let pmetadata = assert_ok2 pair_metadata int_metadata nat_metadata in + let ometadata = assert_ok1 option_metadata pmetadata in + Option_t (Pair_t (int_t, nat_t, pmetadata, YesYes), ometadata, Yes) + +let list_t loc t = + let open Result_syntax in + let+ metadata = list_metadata loc (ty_metadata t) in + List_t (t, metadata) + +let operation_t = Operation_t + +let list_operation_t = + List_t (operation_t, assert_ok1 list_metadata operation_metadata) + +let set_t loc t = + let open Result_syntax in + let+ metadata = set_metadata loc (ty_metadata t) in + Set_t (t, metadata) + +let map_t loc l r = + let open Result_syntax in + let+ metadata = map_metadata loc (ty_metadata l) (ty_metadata r) in + Map_t (l, r, metadata) + +let big_map_t loc l r = + let open Result_syntax in + let+ metadata = big_map_metadata loc (ty_metadata l) (ty_metadata r) in + Big_map_t (l, r, metadata) + +let contract_t loc t = + let open Result_syntax in + let+ metadata = contract_metadata loc (ty_metadata t) in + Contract_t (t, metadata) + +let contract_unit_t = + Contract_t (unit_t, assert_ok1 contract_metadata unit_metadata) + +let sapling_transaction_t ~memo_size = Sapling_transaction_t memo_size + +let sapling_transaction_deprecated_t ~memo_size = + Sapling_transaction_deprecated_t memo_size + +let sapling_state_t ~memo_size = Sapling_state_t memo_size + +let chain_id_t = Chain_id_t + +let never_t = Never_t + +let bls12_381_g1_t = Bls12_381_g1_t + +let bls12_381_g2_t = Bls12_381_g2_t + +let bls12_381_fr_t = Bls12_381_fr_t + +let ticket_t loc t = + let open Result_syntax in + let+ metadata = ticket_metadata loc (ty_metadata t) in + Ticket_t (t, metadata) + +let chest_key_t = Chest_key_t + +let chest_t = Chest_t + +type 'a kinstr_traverse = { + apply : 'b 'S 'r 'F. 'a -> ('b, 'S, 'r, 'F) kinstr -> 'a; +} + +let kinstr_traverse i init f = + let rec aux : + type ret a s r f. 'accu -> (a, s, r, f) kinstr -> ('accu -> ret) -> ret = + fun accu t continue -> + let accu = f.apply accu t in + let next k = + (aux [@ocaml.tailcall]) accu k (fun accu -> + (continue [@ocaml.tailcall]) accu) + in + let next2 k1 k2 = + (aux [@ocaml.tailcall]) accu k1 (fun accu -> + (aux [@ocaml.tailcall]) accu k2 (fun accu -> + (continue [@ocaml.tailcall]) accu)) + in + let next3 k1 k2 k3 = + (aux [@ocaml.tailcall]) accu k1 (fun accu -> + (aux [@ocaml.tailcall]) accu k2 (fun accu -> + (aux [@ocaml.tailcall]) accu k3 (fun accu -> + (continue [@ocaml.tailcall]) accu))) + in + let return () = (continue [@ocaml.tailcall]) accu in + match t with + | IDrop (_, k) -> (next [@ocaml.tailcall]) k + | IDup (_, k) -> (next [@ocaml.tailcall]) k + | ISwap (_, k) -> (next [@ocaml.tailcall]) k + | IPush (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IUnit (_, k) -> (next [@ocaml.tailcall]) k + | ICons_pair (_, k) -> (next [@ocaml.tailcall]) k + | ICar (_, k) -> (next [@ocaml.tailcall]) k + | ICdr (_, k) -> (next [@ocaml.tailcall]) k + | IUnpair (_, k) -> (next [@ocaml.tailcall]) k + | ICons_some (_, k) -> (next [@ocaml.tailcall]) k + | ICons_none (_, _, k) -> (next [@ocaml.tailcall]) k + | IIf_none {loc = _; branch_if_none = k1; branch_if_some = k2; k} -> + (next3 [@ocaml.tailcall]) k1 k2 k + | IOpt_map {loc = _; body; k} -> (next2 [@ocaml.tailcall]) body k + | ICons_left (_, _, k) -> (next [@ocaml.tailcall]) k + | ICons_right (_, _, k) -> (next [@ocaml.tailcall]) k + | IIf_left {loc = _; branch_if_left = k1; branch_if_right = k2; k} -> + (next3 [@ocaml.tailcall]) k1 k2 k + | ICons_list (_, k) -> (next [@ocaml.tailcall]) k + | INil (_, _, k) -> (next [@ocaml.tailcall]) k + | IIf_cons {loc = _; branch_if_nil = k1; branch_if_cons = k2; k} -> + (next3 [@ocaml.tailcall]) k1 k2 k + | IList_map (_, k1, _, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IList_iter (_, _, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IList_size (_, k) -> (next [@ocaml.tailcall]) k + | IEmpty_set (_, _, k) -> (next [@ocaml.tailcall]) k + | ISet_iter (_, _, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | ISet_mem (_, k) -> (next [@ocaml.tailcall]) k + | ISet_update (_, k) -> (next [@ocaml.tailcall]) k + | ISet_size (_, k) -> (next [@ocaml.tailcall]) k + | IEmpty_map (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IMap_map (_, _, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IMap_iter (_, _, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IMap_mem (_, k) -> (next [@ocaml.tailcall]) k + | IMap_get (_, k) -> (next [@ocaml.tailcall]) k + | IMap_update (_, k) -> (next [@ocaml.tailcall]) k + | IMap_get_and_update (_, k) -> (next [@ocaml.tailcall]) k + | IMap_size (_, k) -> (next [@ocaml.tailcall]) k + | IEmpty_big_map (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IBig_map_mem (_, k) -> (next [@ocaml.tailcall]) k + | IBig_map_get (_, k) -> (next [@ocaml.tailcall]) k + | IBig_map_update (_, k) -> (next [@ocaml.tailcall]) k + | IBig_map_get_and_update (_, k) -> (next [@ocaml.tailcall]) k + | IConcat_string (_, k) -> (next [@ocaml.tailcall]) k + | IConcat_string_pair (_, k) -> (next [@ocaml.tailcall]) k + | ISlice_string (_, k) -> (next [@ocaml.tailcall]) k + | IString_size (_, k) -> (next [@ocaml.tailcall]) k + | IConcat_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IConcat_bytes_pair (_, k) -> (next [@ocaml.tailcall]) k + | ISlice_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IBytes_size (_, k) -> (next [@ocaml.tailcall]) k + | ILsl_bytes (_, k) -> (next [@ocaml.tailcall]) k + | ILsr_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IOr_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IAnd_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IXor_bytes (_, k) -> (next [@ocaml.tailcall]) k + | INot_bytes (_, k) -> (next [@ocaml.tailcall]) k + | INat_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IBytes_nat (_, k) -> (next [@ocaml.tailcall]) k + | IInt_bytes (_, k) -> (next [@ocaml.tailcall]) k + | IBytes_int (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_seconds_to_timestamp (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_timestamp_to_seconds (_, k) -> (next [@ocaml.tailcall]) k + | ISub_timestamp_seconds (_, k) -> (next [@ocaml.tailcall]) k + | IDiff_timestamps (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_tez (_, k) -> (next [@ocaml.tailcall]) k + | ISub_tez (_, k) -> (next [@ocaml.tailcall]) k + | ISub_tez_legacy (_, k) -> (next [@ocaml.tailcall]) k + | IMul_teznat (_, k) -> (next [@ocaml.tailcall]) k + | IMul_nattez (_, k) -> (next [@ocaml.tailcall]) k + | IEdiv_teznat (_, k) -> (next [@ocaml.tailcall]) k + | IEdiv_tez (_, k) -> (next [@ocaml.tailcall]) k + | IOr (_, k) -> (next [@ocaml.tailcall]) k + | IAnd (_, k) -> (next [@ocaml.tailcall]) k + | IXor (_, k) -> (next [@ocaml.tailcall]) k + | INot (_, k) -> (next [@ocaml.tailcall]) k + | IIs_nat (_, k) -> (next [@ocaml.tailcall]) k + | INeg (_, k) -> (next [@ocaml.tailcall]) k + | IAbs_int (_, k) -> (next [@ocaml.tailcall]) k + | IInt_nat (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_int (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_nat (_, k) -> (next [@ocaml.tailcall]) k + | ISub_int (_, k) -> (next [@ocaml.tailcall]) k + | IMul_int (_, k) -> (next [@ocaml.tailcall]) k + | IMul_nat (_, k) -> (next [@ocaml.tailcall]) k + | IEdiv_int (_, k) -> (next [@ocaml.tailcall]) k + | IEdiv_nat (_, k) -> (next [@ocaml.tailcall]) k + | ILsl_nat (_, k) -> (next [@ocaml.tailcall]) k + | ILsr_nat (_, k) -> (next [@ocaml.tailcall]) k + | IOr_nat (_, k) -> (next [@ocaml.tailcall]) k + | IAnd_nat (_, k) -> (next [@ocaml.tailcall]) k + | IAnd_int_nat (_, k) -> (next [@ocaml.tailcall]) k + | IXor_nat (_, k) -> (next [@ocaml.tailcall]) k + | INot_int (_, k) -> (next [@ocaml.tailcall]) k + | IIf {loc = _; branch_if_true = k1; branch_if_false = k2; k} -> + (next3 [@ocaml.tailcall]) k1 k2 k + | ILoop (_, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | ILoop_left (_, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IDip (_, k1, _, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IExec (_, _, k) -> (next [@ocaml.tailcall]) k + | IApply (_, _, k) -> (next [@ocaml.tailcall]) k + | ILambda (_, _, k) -> (next [@ocaml.tailcall]) k + | IFailwith (_, _) -> (return [@ocaml.tailcall]) () + | ICompare (_, _, k) -> (next [@ocaml.tailcall]) k + | IEq (_, k) -> (next [@ocaml.tailcall]) k + | INeq (_, k) -> (next [@ocaml.tailcall]) k + | ILt (_, k) -> (next [@ocaml.tailcall]) k + | IGt (_, k) -> (next [@ocaml.tailcall]) k + | ILe (_, k) -> (next [@ocaml.tailcall]) k + | IGe (_, k) -> (next [@ocaml.tailcall]) k + | IAddress (_, k) -> (next [@ocaml.tailcall]) k + | IContract (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IView (_, _, _, k) -> (next [@ocaml.tailcall]) k + | ITransfer_tokens (_, k) -> (next [@ocaml.tailcall]) k + | IImplicit_account (_, k) -> (next [@ocaml.tailcall]) k + | ICreate_contract {k; _} -> (next [@ocaml.tailcall]) k + | ISet_delegate (_, k) -> (next [@ocaml.tailcall]) k + | INow (_, k) -> (next [@ocaml.tailcall]) k + | IMin_block_time (_, k) -> (next [@ocaml.tailcall]) k + | IBalance (_, k) -> (next [@ocaml.tailcall]) k + | ILevel (_, k) -> (next [@ocaml.tailcall]) k + | ICheck_signature (_, k) -> (next [@ocaml.tailcall]) k + | IHash_key (_, k) -> (next [@ocaml.tailcall]) k + | IPack (_, _, k) -> (next [@ocaml.tailcall]) k + | IUnpack (_, _, k) -> (next [@ocaml.tailcall]) k + | IBlake2b (_, k) -> (next [@ocaml.tailcall]) k + | ISha256 (_, k) -> (next [@ocaml.tailcall]) k + | ISha512 (_, k) -> (next [@ocaml.tailcall]) k + | ISource (_, k) -> (next [@ocaml.tailcall]) k + | ISender (_, k) -> (next [@ocaml.tailcall]) k + | ISelf (_, _, _, k) -> (next [@ocaml.tailcall]) k + | ISelf_address (_, k) -> (next [@ocaml.tailcall]) k + | IAmount (_, k) -> (next [@ocaml.tailcall]) k + | ISapling_empty_state (_, _, k) -> (next [@ocaml.tailcall]) k + | ISapling_verify_update (_, k) -> (next [@ocaml.tailcall]) k + | ISapling_verify_update_deprecated (_, k) -> (next [@ocaml.tailcall]) k + | IDig (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IDug (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IDipn (_, _, _, k1, k2) -> (next2 [@ocaml.tailcall]) k1 k2 + | IDropn (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IChainId (_, k) -> (next [@ocaml.tailcall]) k + | INever _ -> (return [@ocaml.tailcall]) () + | IVoting_power (_, k) -> (next [@ocaml.tailcall]) k + | ITotal_voting_power (_, k) -> (next [@ocaml.tailcall]) k + | IKeccak (_, k) -> (next [@ocaml.tailcall]) k + | ISha3 (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_bls12_381_g1 (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_bls12_381_g2 (_, k) -> (next [@ocaml.tailcall]) k + | IAdd_bls12_381_fr (_, k) -> (next [@ocaml.tailcall]) k + | IMul_bls12_381_g1 (_, k) -> (next [@ocaml.tailcall]) k + | IMul_bls12_381_g2 (_, k) -> (next [@ocaml.tailcall]) k + | IMul_bls12_381_fr (_, k) -> (next [@ocaml.tailcall]) k + | IMul_bls12_381_z_fr (_, k) -> (next [@ocaml.tailcall]) k + | IMul_bls12_381_fr_z (_, k) -> (next [@ocaml.tailcall]) k + | IInt_bls12_381_fr (_, k) -> (next [@ocaml.tailcall]) k + | INeg_bls12_381_g1 (_, k) -> (next [@ocaml.tailcall]) k + | INeg_bls12_381_g2 (_, k) -> (next [@ocaml.tailcall]) k + | INeg_bls12_381_fr (_, k) -> (next [@ocaml.tailcall]) k + | IPairing_check_bls12_381 (_, k) -> (next [@ocaml.tailcall]) k + | IComb (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IUncomb (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IComb_get (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IComb_set (_, _, _, k) -> (next [@ocaml.tailcall]) k + | IDup_n (_, _, _, k) -> (next [@ocaml.tailcall]) k + | ITicket (_, _, k) -> (next [@ocaml.tailcall]) k + | ITicket_deprecated (_, _, k) -> (next [@ocaml.tailcall]) k + | IRead_ticket (_, _, k) -> (next [@ocaml.tailcall]) k + | ISplit_ticket (_, k) -> (next [@ocaml.tailcall]) k + | IJoin_tickets (_, _, k) -> (next [@ocaml.tailcall]) k + | IOpen_chest (_, k) -> (next [@ocaml.tailcall]) k + | IEmit {k; _} -> (next [@ocaml.tailcall]) k + | IHalt _ -> (return [@ocaml.tailcall]) () + | ILog (_, _, _, _, k) -> (next [@ocaml.tailcall]) k + in + aux init i (fun accu -> accu) + +type 'a ty_traverse = {apply : 't 'tc. 'a -> ('t, 'tc) ty -> 'a} + +let ty_traverse = + let rec aux : + type ret t tc accu. + accu ty_traverse -> accu -> (t, tc) ty -> (accu -> ret) -> ret = + fun f accu ty continue -> + let accu = f.apply accu ty in + match ty with + | Unit_t | Int_t | Nat_t | Signature_t | String_t | Bytes_t | Mutez_t + | Key_hash_t | Key_t | Timestamp_t | Address_t | Bool_t + | Sapling_transaction_t _ | Sapling_transaction_deprecated_t _ + | Sapling_state_t _ | Operation_t | Chain_id_t | Never_t | Bls12_381_g1_t + | Bls12_381_g2_t | Bls12_381_fr_t -> + (continue [@ocaml.tailcall]) accu + | Ticket_t (cty, _) -> (aux [@ocaml.tailcall]) f accu cty continue + | Chest_key_t | Chest_t -> (continue [@ocaml.tailcall]) accu + | Pair_t (ty1, ty2, _, _) -> + (next2 [@ocaml.tailcall]) f accu ty1 ty2 continue + | Or_t (ty1, ty2, _, _) -> (next2 [@ocaml.tailcall]) f accu ty1 ty2 continue + | Lambda_t (ty1, ty2, _) -> + (next2 [@ocaml.tailcall]) f accu ty1 ty2 continue + | Option_t (ty1, _, _) -> (aux [@ocaml.tailcall]) f accu ty1 continue + | List_t (ty1, _) -> (aux [@ocaml.tailcall]) f accu ty1 continue + | Set_t (cty, _) -> (aux [@ocaml.tailcall]) f accu cty continue + | Map_t (cty, ty1, _) -> (next2 [@ocaml.tailcall]) f accu cty ty1 continue + | Big_map_t (cty, ty1, _) -> + (next2 [@ocaml.tailcall]) f accu cty ty1 continue + | Contract_t (ty1, _) -> (aux [@ocaml.tailcall]) f accu ty1 continue + and next2 : + type a ac b bc ret accu. + accu ty_traverse -> + accu -> + (a, ac) ty -> + (b, bc) ty -> + (accu -> ret) -> + ret = + fun f accu ty1 ty2 continue -> + (aux [@ocaml.tailcall]) f accu ty1 (fun accu -> + (aux [@ocaml.tailcall]) f accu ty2 continue) + in + fun ty init f -> aux f init ty (fun accu -> accu) + +type 'accu stack_ty_traverse = { + apply : 'ty 'S. 'accu -> ('ty, 'S) stack_ty -> 'accu; +} + +let stack_ty_traverse (type a t) (sty : (a, t) stack_ty) init f = + let rec aux : type b u. 'accu -> (b, u) stack_ty -> 'accu = + fun accu sty -> + match sty with + | Bot_t -> f.apply accu sty + | Item_t (_, sty') -> aux (f.apply accu sty) sty' + in + aux init sty + +type 'a value_traverse = {apply : 't 'tc. 'a -> ('t, 'tc) ty -> 't -> 'a} + +let value_traverse (type t tc) (ty : (t, tc) ty) (x : t) init f = + let rec aux : type ret t tc. 'accu -> (t, tc) ty -> t -> ('accu -> ret) -> ret + = + fun accu ty x continue -> + let accu = f.apply accu ty x in + let next2 ty1 ty2 x1 x2 = + (aux [@ocaml.tailcall]) accu ty1 x1 (fun accu -> + (aux [@ocaml.tailcall]) accu ty2 x2 (fun accu -> + (continue [@ocaml.tailcall]) accu)) + in + let next ty1 x1 = + (aux [@ocaml.tailcall]) accu ty1 x1 (fun accu -> + (continue [@ocaml.tailcall]) accu) + in + let return () = (continue [@ocaml.tailcall]) accu in + let rec on_list ty' accu = function + | [] -> (continue [@ocaml.tailcall]) accu + | x :: xs -> + (aux [@ocaml.tailcall]) accu ty' x (fun accu -> + (on_list [@ocaml.tailcall]) ty' accu xs) + in + match ty with + | Unit_t | Int_t | Nat_t | Signature_t | String_t | Bytes_t | Mutez_t + | Key_hash_t | Key_t | Timestamp_t | Address_t | Bool_t + | Sapling_transaction_t _ | Sapling_transaction_deprecated_t _ + | Sapling_state_t _ | Operation_t | Chain_id_t | Never_t | Bls12_381_g1_t + | Bls12_381_g2_t | Bls12_381_fr_t | Chest_key_t | Chest_t + | Lambda_t (_, _, _) -> + (return [@ocaml.tailcall]) () + | Pair_t (ty1, ty2, _, _) -> + (next2 [@ocaml.tailcall]) ty1 ty2 (fst x) (snd x) + | Or_t (ty1, ty2, _, _) -> ( + match x with + | L l -> (next [@ocaml.tailcall]) ty1 l + | R r -> (next [@ocaml.tailcall]) ty2 r) + | Option_t (ty, _, _) -> ( + match x with + | None -> return () + | Some v -> (next [@ocaml.tailcall]) ty v) + | Ticket_t (cty, _) -> (aux [@ocaml.tailcall]) accu cty x.contents continue + | List_t (ty', _) -> on_list ty' accu x.elements + | Map_t (kty, ty', _) -> + let (Map_tag (module M)) = x in + let bindings = M.OPS.fold (fun k v bs -> (k, v) :: bs) M.boxed [] in + on_bindings accu kty ty' continue bindings + | Set_t (ty', _) -> + let (Set_tag (module M)) = x in + let elements = M.OPS.fold (fun x s -> x :: s) M.boxed [] in + on_list ty' accu elements + | Big_map_t (_, _, _) -> + (* For big maps, there is no obvious recursion scheme so we + delegate this case to the client. *) + (return [@ocaml.tailcall]) () + | Contract_t (_, _) -> (return [@ocaml.tailcall]) () + and on_bindings : + type ret k v vc. + 'accu -> + k comparable_ty -> + (v, vc) ty -> + ('accu -> ret) -> + (k * v) list -> + ret = + fun accu kty ty' continue xs -> + match xs with + | [] -> (continue [@ocaml.tailcall]) accu + | (k, v) :: xs -> + (aux [@ocaml.tailcall]) accu kty k (fun accu -> + (aux [@ocaml.tailcall]) accu ty' v (fun accu -> + (on_bindings [@ocaml.tailcall]) accu kty ty' continue xs)) + in + aux init ty x (fun accu -> accu) + +let stack_top_ty : type a b s. (a, b * s) stack_ty -> a ty_ex_c = function + | Item_t (ty, _) -> Ty_ex_c ty + +module Typed_contract = struct + let destination : type a. a typed_contract -> Destination.t = function + | Typed_implicit pkh -> Destination.Contract (Implicit pkh) + | Typed_implicit_with_ticket {destination; _} -> + Destination.Contract (Implicit destination) + | Typed_originated {contract_hash; _} -> + Destination.Contract (Originated contract_hash) + | Typed_sc_rollup {sc_rollup; _} -> Destination.Sc_rollup sc_rollup + | Typed_zk_rollup {zk_rollup; _} -> Destination.Zk_rollup zk_rollup + + let arg_ty : type a. a typed_contract -> a ty_ex_c = function + | Typed_implicit _ -> (Ty_ex_c Unit_t : a ty_ex_c) + | Typed_implicit_with_ticket {ticket_ty; _} -> Ty_ex_c ticket_ty + | Typed_originated {arg_ty; _} -> Ty_ex_c arg_ty + | Typed_sc_rollup {arg_ty; _} -> Ty_ex_c arg_ty + | Typed_zk_rollup {arg_ty; _} -> Ty_ex_c arg_ty + + let entrypoint : type a. a typed_contract -> Entrypoint.t = function + | Typed_implicit _ | Typed_implicit_with_ticket _ -> Entrypoint.default + | Typed_originated {entrypoint; _} | Typed_sc_rollup {entrypoint; _} -> + entrypoint + | Typed_zk_rollup _ -> Entrypoint.deposit + + module Internal_for_tests = struct + let typed_exn : + type a ac. + (a, ac) ty -> Destination.t -> Entrypoint.t -> a typed_contract = + fun arg_ty destination entrypoint -> + match (destination, arg_ty) with + | Contract (Implicit pkh), Unit_t -> Typed_implicit pkh + | Contract (Implicit _), _ -> + invalid_arg "Implicit contracts expect type unit" + | Contract (Originated contract_hash), _ -> + Typed_originated {arg_ty; contract_hash; entrypoint} + | Sc_rollup sc_rollup, _ -> + Typed_sc_rollup {arg_ty; sc_rollup; entrypoint} + | Zk_rollup zk_rollup, Pair_t (Ticket_t _, Bytes_t, _, _) -> + (Typed_zk_rollup {arg_ty; zk_rollup} : a typed_contract) + | Zk_rollup _, _ -> + invalid_arg "ZK rollups expect type (pair (ticket _) bytes)" + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir.mli b/src/proto_020_PsParisC/lib_protocol/script_typed_ir.mli new file mode 100644 index 000000000000..679f1f4a0051 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir.mli @@ -0,0 +1,1889 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_int +open Dependent_bool + +(* + + The step function of the interpreter is parametrized by a bunch of values called the step constants. + These values are indeed constants during the call of a smart contract with the notable exception of + the IView instruction which modifies `sender`, `self`, and `amount` and the KView_exit continuation + which restores them. + ====================== + +*) +type step_constants = { + sender : Destination.t; + (** The address calling this contract, as returned by SENDER. *) + payer : Signature.public_key_hash; + (** The address of the implicit account that initiated the chain of contract calls, as returned by SOURCE. *) + self : Contract_hash.t; + (** The address of the contract being executed, as returned by SELF and SELF_ADDRESS. + Also used: + - as ticketer in TICKET + - as caller in VIEW, TRANSFER_TOKENS, and CREATE_CONTRACT *) + amount : Tez.t; + (** The amount of the current transaction, as returned by AMOUNT. *) + balance : Tez.t; (** The balance of the contract as returned by BALANCE. *) + chain_id : Chain_id.t; + (** The chain id of the chain, as returned by CHAIN_ID. *) + now : Script_timestamp.t; + (** The earliest time at which the current block could have been timestamped, as returned by NOW. *) + level : Script_int.n Script_int.num; + (** The level of the current block, as returned by LEVEL. *) +} + +(* Preliminary definitions. *) + +type never = | + +type address = {destination : Destination.t; entrypoint : Entrypoint.t} + +module Script_signature : sig + (** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) + type t = Signature_tag of signature [@@ocaml.unboxed] + + val make : signature -> t + + val get : t -> signature + + val encoding : t Data_encoding.t + + val of_b58check_opt : string -> t option + + val check : + ?watermark:Signature.watermark -> + Signature.Public_key.t -> + t -> + Bytes.t -> + bool + + val compare : t -> t -> int + + val size : t -> int +end + +type signature = Script_signature.t + +type ('a, 'b) pair = 'a * 'b + +type ('a, 'b) or_ = L of 'a | R of 'b + +module Script_chain_id : sig + (** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) + type t = Chain_id_tag of Chain_id.t [@@ocaml.unboxed] + + val make : Chain_id.t -> t + + val compare : t -> t -> int + + val size : int + + val encoding : t Data_encoding.t + + val to_b58check : t -> string + + val of_b58check_opt : string -> t option +end + +module Script_bls : sig + module type S = sig + type t + + type fr + + val add : t -> t -> t + + val mul : t -> fr -> t + + val negate : t -> t + + val of_bytes_opt : Bytes.t -> t option + + val to_bytes : t -> Bytes.t + end + + module Fr : sig + (** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) + type t = Fr_tag of Bls.Primitive.Fr.t [@@ocaml.unboxed] + + include S with type t := t and type fr := t + + val of_z : Z.t -> t + + val to_z : t -> Z.t + end + + module G1 : sig + (** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) + type t = G1_tag of Bls.Primitive.G1.t [@@ocaml.unboxed] + + include S with type t := t and type fr := Fr.t + end + + module G2 : sig + (** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) + type t = G2_tag of Bls.Primitive.G2.t [@@ocaml.unboxed] + + include S with type t := t and type fr := Fr.t + end + + val pairing_check : (G1.t * G2.t) list -> bool +end + +module Script_timelock : sig + (** [chest_key] is made algebraic in order to distinguish it from the other + type parameters of [Script_typed_ir.ty]. *) + type chest_key = Chest_key_tag of Timelock.chest_key [@@ocaml.unboxed] + + val make_chest_key : Timelock.chest_key -> chest_key + + val chest_key_encoding : chest_key Data_encoding.t + + (** [chest] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) + type chest = Chest_tag of Timelock.chest [@@ocaml.unboxed] + + val make_chest : Timelock.chest -> chest + + val chest_encoding : chest Data_encoding.t + + val open_chest : chest -> chest_key -> time:int -> Timelock.opening_result + + val get_plaintext_size : chest -> int +end + +type ticket_amount = Ticket_amount.t + +type 'a ticket = {ticketer : Contract.t; contents : 'a; amount : ticket_amount} + +type empty_cell = EmptyCell + +type end_of_stack = empty_cell * empty_cell + +module Type_size : sig + type 'a t + + val check_eq : + error_details:('error_context, 'error_trace) Script_tc_errors.error_details -> + 'a t -> + 'b t -> + (unit, 'error_trace) result + + val to_int : 'a t -> Saturation_repr.mul_safe Saturation_repr.t +end + +type 'a ty_metadata = {size : 'a Type_size.t} [@@unboxed] + +module type Boxed_set_OPS = sig + type t + + type elt + + val elt_size : elt -> int (* Gas_input_size.t *) + + val empty : t + + val add : elt -> t -> t + + val mem : elt -> t -> bool + + val remove : elt -> t -> t + + val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a +end + +module type Boxed_set = sig + type elt + + module OPS : Boxed_set_OPS with type elt = elt + + val boxed : OPS.t + + val size : int +end + +(** [set] is made algebraic in order to distinguish it from the other type + parameters of [ty]. *) +type 'elt set = Set_tag of (module Boxed_set with type elt = 'elt) +[@@ocaml.unboxed] + +module type Boxed_map_OPS = sig + type 'a t + + type key + + val key_size : key -> int (* Gas_input_size.t *) + + val empty : 'value t + + val add : key -> 'value -> 'value t -> 'value t + + val remove : key -> 'value t -> 'value t + + val find : key -> 'value t -> 'value option + + val fold : (key -> 'value -> 'a -> 'a) -> 'value t -> 'a -> 'a + + val fold_es : + (key -> 'value -> 'a -> 'a tzresult Lwt.t) -> + 'value t -> + 'a -> + 'a tzresult Lwt.t +end + +module type Boxed_map = sig + type key + + type value + + module OPS : Boxed_map_OPS with type key = key + + val boxed : value OPS.t + + val size : int +end + +(** [map] is made algebraic in order to distinguish it from the other type + parameters of [ty]. *) +type ('key, 'value) map = + | Map_tag of (module Boxed_map with type key = 'key and type value = 'value) +[@@ocaml.unboxed] + +module Big_map_overlay : Map.S with type key = Script_expr_hash.t + +type ('key, 'value) big_map_overlay = { + map : ('key * 'value option) Big_map_overlay.t; + size : int; +} + +type view = { + input_ty : Script.node; + output_ty : Script.node; + view_code : Script.node; +} + +type view_map = (Script_string.t, view) map + +type entrypoint_info = {name : Entrypoint.t; original_type_expr : Script.node} + +(** ['arg entrypoints] represents the tree of entrypoints of a parameter type + ['arg]. + [at_node] are entrypoint details at that node if it is not [None]. + [nested] are the entrypoints below the node in the tree. + It is always [Entrypoints_None] for non-or nodes. + But it is also ok to have [Entrypoints_None] for an or node, it just + means that there are no entrypoints below that node in the tree. +*) +type 'arg entrypoints_node = { + at_node : entrypoint_info option; + nested : 'arg nested_entrypoints; +} + +and 'arg nested_entrypoints = + | Entrypoints_Or : { + left : 'l entrypoints_node; + right : 'r entrypoints_node; + } + -> ('l, 'r) or_ nested_entrypoints + | Entrypoints_None : _ nested_entrypoints + +(** [no_entrypoints] is [{at_node = None; nested = Entrypoints_None}] *) +val no_entrypoints : _ entrypoints_node + +type logging_event = LogEntry | LogExit of Script.location + +type 'arg entrypoints = { + root : 'arg entrypoints_node; + original_type_expr : Script.node; +} + +(* ---- Instructions --------------------------------------------------------*) + +(* + + The instructions of Michelson are represented in the following + Generalized Algebraic Datatypes. + + There are three important aspects in that type declaration. + + First, we follow a tagless approach for values: they are directly + represented as OCaml values. This reduces the computational cost of + interpretation because there is no need to check the shape of a + value before applying an operation to it. To achieve that, the GADT + encodes the typing rules of the Michelson programming + language. This static information is sufficient for the typechecker + to justify the absence of runtime checks. As a bonus, it also + ensures that well-typed Michelson programs cannot go wrong: if the + interpreter typechecks then we have the static guarantee that no + stack underflow or type error can occur at runtime. + + Second, we maintain the invariant that the stack type always has a + distinguished topmost element. This invariant is important to + implement the stack as an accumulator followed by a linked list of + cells, a so-called A-Stack. This representation is considered in + the literature[1] as an efficient representation of the stack for a + stack-based abstract machine, mainly because this opens the + opportunity for the accumulator to be stored in a hardware + register. In the GADT, this invariant is encoded by representing + the stack type using two parameters instead of one: the first one + is the type of the accumulator while the second is the type of the + rest of the stack. + + Third, in this representation, each instruction embeds its + potential successor instructions in the control flow. This design + choice permits an efficient implementation of the continuation + stack in the interpreter. Assigning a precise type to this kind of + instruction which is a cell in a linked list of instructions is + similar to the typing of delimited continuations: we need to give a + type to the stack ['before] the execution of the instruction, a + type to the stack ['after] the execution of the instruction and + before the execution of the next, and a type for the [`result]ing + stack type after the execution of the whole chain of instructions. + + Combining these three aspects, the type [kinstr] needs four + parameters: + + ('before_top, 'before, 'result_top, 'result) kinstr + + Notice that we could have chosen to only give two parameters to + [kinstr] by manually enforcing each argument to be a pair but this + is error-prone: with four parameters, this constraint is enforced + by the arity of the type constructor itself. + + Hence, an instruction which has a successor instruction enjoys a + type of the form: + + ... * ('after_top, 'after, 'result_top, 'result) kinstr * ... -> + ('before_top, 'before, 'result_top, 'result) kinstr + + where ['before_top] and ['before] are the types of the stack top + and rest before the instruction chain, ['after_top] and ['after] + are the types of the stack top and rest after the instruction + chain, and ['result_top] and ['result] are the types of the stack + top and rest after the instruction chain. The [IHalt] instruction + ends a sequence of instructions and has no successor, as shown by + its type: + + IHalt : Script.location -> ('a, 'S, 'a, 'S) kinstr + + Each instruction is decorated by its location: its value is only + used for logging and error reporting and has no impact on the + operational semantics. + + Notations: + ---------- + + In the following declaration, we use 'a, 'b, 'c, 'd, ... to assign + types to stack cell contents while we use 'S, 'T, 'U, ... to + assign types to stacks. + + The types for the final result and stack rest of a whole sequence + of instructions are written 'r and 'F (standing for "result" and + "final stack rest", respectively). + + Instructions for internal execution steps + ========================================= + + Some instructions encoded in the following type are not present in the + source language. They only appear during evaluation to account for + intermediate execution steps. Indeed, since the interpreter follows + a small-step style, it is sometimes necessary to decompose a + source-level instruction (e.g. List_map) into several instructions + with smaller steps. This technique seems required to get an + efficient tail-recursive interpreter. + + References + ========== + [1]: http://www.complang.tuwien.ac.at/projects/interpreters.html + + *) +and ('before_top, 'before, 'result_top, 'result) kinstr = + (* + Stack + ----- + *) + | IDrop : + Script.location * ('b, 'S, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IDup : + Script.location * ('a, 'a * ('b * 'S), 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | ISwap : + Script.location * ('b, 'a * ('c * 'S), 'r, 'F) kinstr + -> ('a, 'b * ('c * 'S), 'r, 'F) kinstr + | IPush : + Script.location * ('ty, _) ty * 'ty * ('ty, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IUnit : + Script.location * (unit, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + (* + Pairs + ----- + *) + | ICons_pair : + Script.location * (('a, 'b) pair, 'c * 'S, 'r, 'F) kinstr + -> ('a, 'b * ('c * 'S), 'r, 'F) kinstr + | ICar : + Script.location * ('a, 'S, 'r, 'F) kinstr + -> (('a, 'b) pair, 'S, 'r, 'F) kinstr + | ICdr : + Script.location * ('b, 'S, 'r, 'F) kinstr + -> (('a, 'b) pair, 'S, 'r, 'F) kinstr + | IUnpair : + Script.location * ('a, 'b * 'S, 'r, 'F) kinstr + -> (('a, 'b) pair, 'S, 'r, 'F) kinstr + (* + Options + ------- + *) + | ICons_some : + Script.location * ('v option, 'a * 'S, 'r, 'F) kinstr + -> ('v, 'a * 'S, 'r, 'F) kinstr + | ICons_none : + Script.location * ('b, _) ty * ('b option, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IIf_none : { + loc : Script.location; + branch_if_none : ('b, 'S, 'c, 'T) kinstr; + branch_if_some : ('a, 'b * 'S, 'c, 'T) kinstr; + k : ('c, 'T, 'r, 'F) kinstr; + } + -> ('a option, 'b * 'S, 'r, 'F) kinstr + | IOpt_map : { + loc : Script.location; + body : ('a, 'S, 'b, 'S) kinstr; + k : ('b option, 'S, 'c, 'F) kinstr; + } + -> ('a option, 'S, 'c, 'F) kinstr + (* + Ors + ------ + *) + | ICons_left : + Script.location * ('b, _) ty * (('a, 'b) or_, 'c * 'S, 'r, 'F) kinstr + -> ('a, 'c * 'S, 'r, 'F) kinstr + | ICons_right : + Script.location * ('a, _) ty * (('a, 'b) or_, 'c * 'S, 'r, 'F) kinstr + -> ('b, 'c * 'S, 'r, 'F) kinstr + | IIf_left : { + loc : Script.location; + branch_if_left : ('a, 'S, 'c, 'T) kinstr; + branch_if_right : ('b, 'S, 'c, 'T) kinstr; + k : ('c, 'T, 'r, 'F) kinstr; + } + -> (('a, 'b) or_, 'S, 'r, 'F) kinstr + (* + Lists + ----- + *) + | ICons_list : + Script.location * ('a Script_list.t, 'S, 'r, 'F) kinstr + -> ('a, 'a Script_list.t * 'S, 'r, 'F) kinstr + | INil : + Script.location * ('b, _) ty * ('b Script_list.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IIf_cons : { + loc : Script.location; + branch_if_cons : ('a, 'a Script_list.t * ('b * 'S), 'c, 'T) kinstr; + branch_if_nil : ('b, 'S, 'c, 'T) kinstr; + k : ('c, 'T, 'r, 'F) kinstr; + } + -> ('a Script_list.t, 'b * 'S, 'r, 'F) kinstr + | IList_map : + Script.location + * ('a, 'c * 'S, 'b, 'c * 'S) kinstr + * ('b Script_list.t, _) ty option + * ('b Script_list.t, 'c * 'S, 'r, 'F) kinstr + -> ('a Script_list.t, 'c * 'S, 'r, 'F) kinstr + | IList_iter : + Script.location + * ('a, _) ty option + * ('a, 'b * 'S, 'b, 'S) kinstr + * ('b, 'S, 'r, 'F) kinstr + -> ('a Script_list.t, 'b * 'S, 'r, 'F) kinstr + | IList_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> ('a Script_list.t, 'S, 'r, 'F) kinstr + (* + Sets + ---- + *) + | IEmpty_set : + Script.location * 'b comparable_ty * ('b set, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISet_iter : + Script.location + * 'a comparable_ty option + * ('a, 'b * 'S, 'b, 'S) kinstr + * ('b, 'S, 'r, 'F) kinstr + -> ('a set, 'b * 'S, 'r, 'F) kinstr + | ISet_mem : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ('a, 'a set * 'S, 'r, 'F) kinstr + | ISet_update : + Script.location * ('a set, 'S, 'r, 'F) kinstr + -> ('a, bool * ('a set * 'S), 'r, 'F) kinstr + | ISet_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> ('a set, 'S, 'r, 'F) kinstr + (* + Maps + ---- + *) + | IEmpty_map : + Script.location + * 'b comparable_ty + * ('c, _) ty option + * (('b, 'c) map, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IMap_map : + Script.location + * (('a, 'c) map, _) ty option + * (('a, 'b) pair, 'd * 'S, 'c, 'd * 'S) kinstr + * (('a, 'c) map, 'd * 'S, 'r, 'F) kinstr + -> (('a, 'b) map, 'd * 'S, 'r, 'F) kinstr + | IMap_iter : + Script.location + * (('a, 'b) pair, _) ty option + * (('a, 'b) pair, 'c * 'S, 'c, 'S) kinstr + * ('c, 'S, 'r, 'F) kinstr + -> (('a, 'b) map, 'c * 'S, 'r, 'F) kinstr + | IMap_mem : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) map * 'S, 'r, 'F) kinstr + | IMap_get : + Script.location * ('b option, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) map * 'S, 'r, 'F) kinstr + | IMap_update : + Script.location * (('a, 'b) map, 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) map * 'S), 'r, 'F) kinstr + | IMap_get_and_update : + Script.location * ('b option, ('a, 'b) map * 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) map * 'S), 'r, 'F) kinstr + | IMap_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (('a, 'b) map, 'S, 'r, 'F) kinstr + (* + Big maps + -------- + *) + | IEmpty_big_map : + Script.location + * 'b comparable_ty + * ('c, _) ty + * (('b, 'c) big_map, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IBig_map_mem : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) big_map * 'S, 'r, 'F) kinstr + | IBig_map_get : + Script.location * ('b option, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) big_map * 'S, 'r, 'F) kinstr + | IBig_map_update : + Script.location * (('a, 'b) big_map, 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) big_map * 'S), 'r, 'F) kinstr + | IBig_map_get_and_update : + Script.location * ('b option, ('a, 'b) big_map * 'S, 'r, 'F) kinstr + -> ('a, 'b option * (('a, 'b) big_map * 'S), 'r, 'F) kinstr + (* + Strings + ------- + *) + | IConcat_string : + Script.location * (Script_string.t, 'S, 'r, 'F) kinstr + -> (Script_string.t Script_list.t, 'S, 'r, 'F) kinstr + | IConcat_string_pair : + Script.location * (Script_string.t, 'S, 'r, 'F) kinstr + -> (Script_string.t, Script_string.t * 'S, 'r, 'F) kinstr + | ISlice_string : + Script.location * (Script_string.t option, 'S, 'r, 'F) kinstr + -> (n num, n num * (Script_string.t * 'S), 'r, 'F) kinstr + | IString_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (Script_string.t, 'S, 'r, 'F) kinstr + (* + Bytes + ----- + *) + | IConcat_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes Script_list.t, 'S, 'r, 'F) kinstr + | IConcat_bytes_pair : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | ISlice_bytes : + Script.location * (bytes option, 'S, 'r, 'F) kinstr + -> (n num, n num * (bytes * 'S), 'r, 'F) kinstr + | IBytes_size : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ILsl_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, n num * 'S, 'r, 'F) kinstr + | ILsr_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, n num * 'S, 'r, 'F) kinstr + | IOr_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | IAnd_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | IXor_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, bytes * 'S, 'r, 'F) kinstr + | INot_bytes : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | INat_bytes : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IBytes_nat : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (n num, 'S, 'r, 'F) kinstr + | IInt_bytes : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IBytes_int : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + (* + Timestamps + ---------- + *) + | IAdd_seconds_to_timestamp : + Script.location * (Script_timestamp.t, 'S, 'r, 'F) kinstr + -> (z num, Script_timestamp.t * 'S, 'r, 'F) kinstr + | IAdd_timestamp_to_seconds : + Script.location * (Script_timestamp.t, 'S, 'r, 'F) kinstr + -> (Script_timestamp.t, z num * 'S, 'r, 'F) kinstr + | ISub_timestamp_seconds : + Script.location * (Script_timestamp.t, 'S, 'r, 'F) kinstr + -> (Script_timestamp.t, z num * 'S, 'r, 'F) kinstr + | IDiff_timestamps : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (Script_timestamp.t, Script_timestamp.t * 'S, 'r, 'F) kinstr + (* + Tez + --- + *) + | IAdd_tez : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + | ISub_tez : + Script.location * (Tez.t option, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + | ISub_tez_legacy : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + | IMul_teznat : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (Tez.t, n num * 'S, 'r, 'F) kinstr + | IMul_nattez : + Script.location * (Tez.t, 'S, 'r, 'F) kinstr + -> (n num, Tez.t * 'S, 'r, 'F) kinstr + | IEdiv_teznat : + Script.location * ((Tez.t, Tez.t) pair option, 'S, 'r, 'F) kinstr + -> (Tez.t, n num * 'S, 'r, 'F) kinstr + | IEdiv_tez : + Script.location * ((n num, Tez.t) pair option, 'S, 'r, 'F) kinstr + -> (Tez.t, Tez.t * 'S, 'r, 'F) kinstr + (* + Booleans + -------- + *) + | IOr : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, bool * 'S, 'r, 'F) kinstr + | IAnd : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, bool * 'S, 'r, 'F) kinstr + | IXor : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, bool * 'S, 'r, 'F) kinstr + | INot : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (bool, 'S, 'r, 'F) kinstr + (* + Integers + -------- + *) + | IIs_nat : + Script.location * (n num option, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | INeg : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'S, 'r, 'F) kinstr + | IAbs_int : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | IInt_nat : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (n num, 'S, 'r, 'F) kinstr + | IAdd_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IAdd_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | ISub_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IMul_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IMul_nat : + Script.location * ('a num, 'S, 'r, 'F) kinstr + -> (n num, 'a num * 'S, 'r, 'F) kinstr + | IEdiv_int : + Script.location * ((z num, n num) pair option, 'S, 'r, 'F) kinstr + -> ('a num, 'b num * 'S, 'r, 'F) kinstr + | IEdiv_nat : + Script.location * (('a num, n num) pair option, 'S, 'r, 'F) kinstr + -> (n num, 'a num * 'S, 'r, 'F) kinstr + | ILsl_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | ILsr_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | IOr_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | IAnd_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | IAnd_int_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (z num, n num * 'S, 'r, 'F) kinstr + | IXor_nat : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (n num, n num * 'S, 'r, 'F) kinstr + | INot_int : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> ('a num, 'S, 'r, 'F) kinstr + (* + Control + ------- + *) + | IIf : { + loc : Script.location; + branch_if_true : ('a, 'S, 'b, 'T) kinstr; + branch_if_false : ('a, 'S, 'b, 'T) kinstr; + k : ('b, 'T, 'r, 'F) kinstr; + } + -> (bool, 'a * 'S, 'r, 'F) kinstr + | ILoop : + Script.location * ('a, 'S, bool, 'a * 'S) kinstr * ('a, 'S, 'r, 'F) kinstr + -> (bool, 'a * 'S, 'r, 'F) kinstr + | ILoop_left : + Script.location + * ('a, 'S, ('a, 'b) or_, 'S) kinstr + * ('b, 'S, 'r, 'F) kinstr + -> (('a, 'b) or_, 'S, 'r, 'F) kinstr + | IDip : + Script.location + * ('b, 'S, 'c, 'T) kinstr + * ('a, _) ty option + * ('a, 'c * 'T, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IExec : + Script.location * ('b, 'S) stack_ty option * ('b, 'S, 'r, 'F) kinstr + -> ('a, ('a, 'b) lambda * 'S, 'r, 'F) kinstr + | IApply : + Script.location * ('a, _) ty * (('b, 'c) lambda, 'S, 'r, 'F) kinstr + -> ('a, (('a, 'b) pair, 'c) lambda * 'S, 'r, 'F) kinstr + | ILambda : + Script.location + * ('b, 'c) lambda + * (('b, 'c) lambda, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IFailwith : Script.location * ('a, _) ty -> ('a, 'S, 'r, 'F) kinstr + (* + Comparison + ---------- + *) + | ICompare : + Script.location * 'a comparable_ty * (z num, 'b * 'S, 'r, 'F) kinstr + -> ('a, 'a * ('b * 'S), 'r, 'F) kinstr + (* + Comparators + ----------- + *) + | IEq : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | INeq : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | ILt : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | IGt : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | ILe : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + | IGe : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (z num, 'S, 'r, 'F) kinstr + (* + Protocol + -------- + *) + | IAddress : + Script.location * (address, 'S, 'r, 'F) kinstr + -> ('a typed_contract, 'S, 'r, 'F) kinstr + | IContract : + Script.location + * ('a, _) ty + * Entrypoint.t + * ('a typed_contract option, 'S, 'r, 'F) kinstr + -> (address, 'S, 'r, 'F) kinstr + | IView : + Script.location + * ('a, 'b) view_signature + * ('c, 'S) stack_ty option + * ('b option, 'c * 'S, 'r, 'F) kinstr + -> ('a, address * ('c * 'S), 'r, 'F) kinstr + | ITransfer_tokens : + Script.location * (operation, 'S, 'r, 'F) kinstr + -> ('a, Tez.t * ('a typed_contract * 'S), 'r, 'F) kinstr + | IImplicit_account : + Script.location * (unit typed_contract, 'S, 'r, 'F) kinstr + -> (public_key_hash, 'S, 'r, 'F) kinstr + | ICreate_contract : { + loc : Script.location; + storage_type : ('a, _) ty; + code : Script.expr; + k : (operation, address * ('c * 'S), 'r, 'F) kinstr; + } + -> (public_key_hash option, Tez.t * ('a * ('c * 'S)), 'r, 'F) kinstr + | ISet_delegate : + Script.location * (operation, 'S, 'r, 'F) kinstr + -> (public_key_hash option, 'S, 'r, 'F) kinstr + | INow : + Script.location * (Script_timestamp.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IMin_block_time : + Script.location * (n num, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IBalance : + Script.location * (Tez.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ILevel : + Script.location * (n num, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ICheck_signature : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> (public_key, signature * (bytes * 'S), 'r, 'F) kinstr + | IHash_key : + Script.location * (public_key_hash, 'S, 'r, 'F) kinstr + -> (public_key, 'S, 'r, 'F) kinstr + | IPack : + Script.location * ('a, _) ty * (bytes, 'b * 'S, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IUnpack : + Script.location * ('a, _) ty * ('a option, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IBlake2b : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISha256 : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISha512 : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISource : + Script.location * (address, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISender : + Script.location * (address, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISelf : + Script.location + * ('b, _) ty + * Entrypoint.t + * ('b typed_contract, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISelf_address : + Script.location * (address, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IAmount : + Script.location * (Tez.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | ISapling_empty_state : + Script.location + * Sapling.Memo_size.t + * (Sapling.state, 'a * 'S, 'b, 'F) kinstr + -> ('a, 'S, 'b, 'F) kinstr + | ISapling_verify_update : + Script.location + * ((bytes, (z num, Sapling.state) pair) pair option, 'S, 'r, 'F) kinstr + -> (Sapling.transaction, Sapling.state * 'S, 'r, 'F) kinstr + | ISapling_verify_update_deprecated : + (* legacy introduced in J *) + Script.location + * ((z num, Sapling.state) pair option, 'S, 'r, 'F) kinstr + -> (Sapling.Legacy.transaction, Sapling.state * 'S, 'r, 'F) kinstr + | IDig : + Script.location + (* + There is a prefix of length [n] common to the input stack + of type ['a * 's] and an intermediary stack of type ['d * 'u]. + *) + * int + (* + Under this common prefix, the input stack has type ['b * 'c * 't] and + the intermediary stack type ['c * 't] because we removed the ['b] from + the input stack. This value of type ['b] is pushed on top of the + stack passed to the continuation. + *) + * ('b, 'c * 'T, 'c, 'T, 'a, 'S, 'd, 'U) stack_prefix_preservation_witness + * ('b, 'd * 'U, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IDug : + Script.location + (* + The input stack has type ['a * 'b * 's]. + + There is a prefix of length [n] common to its substack + of type ['b * 's] and the output stack of type ['d * 'u]. + *) + * int + (* + Under this common prefix, the first stack has type ['c * 't] + and the second has type ['a * 'c * 't] because we have pushed + the topmost element of this input stack under the common prefix. + *) + * ('c, 'T, 'a, 'c * 'T, 'b, 'S, 'd, 'U) stack_prefix_preservation_witness + * ('d, 'U, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IDipn : + Script.location + (* The body of Dipn is applied under a prefix of size [n]... *) + * int + (* + ... the relation between the types of the input and output stacks + is characterized by the following witness. + (See forthcoming comments about [stack_prefix_preservation_witness].) + *) + * ('c, 'T, 'd, 'V, 'a, 'S, 'b, 'U) stack_prefix_preservation_witness + * ('c, 'T, 'd, 'V) kinstr + * ('b, 'U, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IDropn : + Script.location + (* + The input stack enjoys a prefix of length [n]... + *) + * int + (* + ... and the following value witnesses that under this prefix + the stack has type ['b * 'u]. + *) + * ('b, 'U, 'b, 'U, 'a, 'S, 'a, 'S) stack_prefix_preservation_witness + (* + This stack is passed to the continuation since we drop the + entire prefix. + *) + * ('b, 'U, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IChainId : + Script.location * (Script_chain_id.t, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | INever : Script.location -> (never, 'S, 'r, 'F) kinstr + | IVoting_power : + Script.location * (n num, 'S, 'r, 'F) kinstr + -> (public_key_hash, 'S, 'r, 'F) kinstr + | ITotal_voting_power : + Script.location * (n num, 'a * 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + | IKeccak : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | ISha3 : + Script.location * (bytes, 'S, 'r, 'F) kinstr + -> (bytes, 'S, 'r, 'F) kinstr + | IAdd_bls12_381_g1 : + Script.location * (Script_bls.G1.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G1.t, Script_bls.G1.t * 'S, 'r, 'F) kinstr + | IAdd_bls12_381_g2 : + Script.location * (Script_bls.G2.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G2.t, Script_bls.G2.t * 'S, 'r, 'F) kinstr + | IAdd_bls12_381_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_g1 : + Script.location * (Script_bls.G1.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G1.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_g2 : + Script.location * (Script_bls.G2.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G2.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IMul_bls12_381_z_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, 'a num * 'S, 'r, 'F) kinstr + | IMul_bls12_381_fr_z : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> ('a num, Script_bls.Fr.t * 'S, 'r, 'F) kinstr + | IInt_bls12_381_fr : + Script.location * (z num, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + | INeg_bls12_381_g1 : + Script.location * (Script_bls.G1.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G1.t, 'S, 'r, 'F) kinstr + | INeg_bls12_381_g2 : + Script.location * (Script_bls.G2.t, 'S, 'r, 'F) kinstr + -> (Script_bls.G2.t, 'S, 'r, 'F) kinstr + | INeg_bls12_381_fr : + Script.location * (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + -> (Script_bls.Fr.t, 'S, 'r, 'F) kinstr + | IPairing_check_bls12_381 : + Script.location * (bool, 'S, 'r, 'F) kinstr + -> ( (Script_bls.G1.t, Script_bls.G2.t) pair Script_list.t, + 'S, + 'r, + 'F ) + kinstr + | IComb : + Script.location + * int + * ('a, 'b, 'S, 'c, 'd, 'T) comb_gadt_witness + * ('c, 'd * 'T, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IUncomb : + Script.location + * int + * ('a, 'b, 'S, 'c, 'd, 'T) uncomb_gadt_witness + * ('c, 'd * 'T, 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | IComb_get : + Script.location + * int + * ('t, 'v) comb_get_gadt_witness + * ('v, 'a * 'S, 'r, 'F) kinstr + -> ('t, 'a * 'S, 'r, 'F) kinstr + | IComb_set : + Script.location + * int + * ('a, 'b, 'c) comb_set_gadt_witness + * ('c, 'd * 'S, 'r, 'F) kinstr + -> ('a, 'b * ('d * 'S), 'r, 'F) kinstr + | IDup_n : + Script.location + * int + * ('a, 'b, 'S, 't) dup_n_gadt_witness + * ('t, 'a * ('b * 'S), 'r, 'F) kinstr + -> ('a, 'b * 'S, 'r, 'F) kinstr + | ITicket : + Script.location + * 'a comparable_ty option + * ('a ticket option, 'S, 'r, 'F) kinstr + -> ('a, n num * 'S, 'r, 'F) kinstr + | ITicket_deprecated : + Script.location * 'a comparable_ty option * ('a ticket, 'S, 'r, 'F) kinstr + -> ('a, n num * 'S, 'r, 'F) kinstr + | IRead_ticket : + Script.location + * 'a comparable_ty option + * ((address, ('a, n num) pair) pair, 'a ticket * 'S, 'r, 'F) kinstr + -> ('a ticket, 'S, 'r, 'F) kinstr + | ISplit_ticket : + Script.location * (('a ticket, 'a ticket) pair option, 'S, 'r, 'F) kinstr + -> ('a ticket, (n num, n num) pair * 'S, 'r, 'F) kinstr + | IJoin_tickets : + Script.location * 'a comparable_ty * ('a ticket option, 'S, 'r, 'F) kinstr + -> (('a ticket, 'a ticket) pair, 'S, 'r, 'F) kinstr + | IOpen_chest : + Script.location * (bytes option, 'S, 'r, 'F) kinstr + -> ( Script_timelock.chest_key, + Script_timelock.chest * (n num * 'S), + 'r, + 'F ) + kinstr + | IEmit : { + loc : Script.location; + tag : Entrypoint.t; + ty : ('a, _) ty; + unparsed_ty : Script.expr; + k : (operation, 'S, 'r, 'F) kinstr; + } + -> ('a, 'S, 'r, 'F) kinstr + (* + + Internal control instructions + ============================= + + The following instructions are not available in the source language. + They are used by the internals of the interpreter. + *) + | IHalt : Script.location -> ('a, 'S, 'a, 'S) kinstr + | ILog : + Script.location + * ('a, 'S) stack_ty + * logging_event + * logger + * ('a, 'S, 'r, 'F) kinstr + -> ('a, 'S, 'r, 'F) kinstr + +and ('arg, 'ret) lambda = + | Lam : + ('arg, end_of_stack, 'ret, end_of_stack) kdescr * Script.node + -> ('arg, 'ret) lambda + | LamRec : + ('arg, ('arg, 'ret) lambda * end_of_stack, 'ret, end_of_stack) kdescr + * Script.node + -> ('arg, 'ret) lambda + +and 'arg typed_contract = + | Typed_implicit : public_key_hash -> unit typed_contract + | Typed_implicit_with_ticket : { + ticket_ty : ('arg ticket, _) ty; + destination : public_key_hash; + } + -> 'arg ticket typed_contract + | Typed_originated : { + arg_ty : ('arg, _) ty; + contract_hash : Contract_hash.t; + entrypoint : Entrypoint.t; + } + -> 'arg typed_contract + | Typed_sc_rollup : { + arg_ty : ('arg, _) ty; + sc_rollup : Sc_rollup.t; + entrypoint : Entrypoint.t; + } + -> 'arg typed_contract + | Typed_zk_rollup : { + arg_ty : (('a ticket, bytes) pair, _) ty; + zk_rollup : Zk_rollup.t; + } + -> ('a ticket, bytes) pair typed_contract + +(* + + Control stack + ============= + + The control stack is a list of [kinstr]. + + Since [kinstr] denotes a list of instructions, the control stack + can be seen as a list of instruction sequences, each representing a + form of delimited continuation (i.e. a control stack fragment). The + [continuation] GADT ensures that the input and output stack types of the + continuations are consistent. + + Loops have a special treatment because their control stack is reused + as is for the next iteration. This avoids the reallocation of a + control stack cell at each iteration. + + To implement [step] as a tail-recursive function, we implement + higher-order iterators (i.e. MAPs and ITERs) using internal instructions +. Roughly speaking, these instructions help in decomposing the execution + of [I f c] (where [I] is an higher-order iterator over a container [c]) + into three phases: to start the iteration, to execute [f] if there are + elements to be processed in [c], and to loop. + + Dip also has a dedicated constructor in the control stack. This + allows the stack prefix to be restored after the execution of the + [Dip]'s body. + + Following the same style as in [kinstr], [continuation] has four + arguments, two for each stack types. More precisely, with + + [('bef_top, 'bef, 'aft_top, 'aft) continuation] + + we encode the fact that the stack before executing the continuation + has type [('bef_top * 'bef)] and that the stack after this execution + has type [('aft_top * 'aft)]. + +*) +and (_, _, _, _) continuation = + (* This continuation returns immediately. *) + | KNil : ('r, 'F, 'r, 'F) continuation + (* This continuation starts with the next instruction to execute. *) + | KCons : + ('a, 'S, 'b, 'T) kinstr * ('b, 'T, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + (* This continuation represents a call frame: it stores the caller's + stack of type ['s] and the continuation which expects the callee's + result on top of the stack. *) + | KReturn : + 'S * ('a, 'S) stack_ty option * ('a, 'S, 'r, 'F) continuation + -> ('a, end_of_stack, 'r, 'F) continuation + (* This continuation is useful when stack head requires some wrapping or + unwrapping before it can be passed forward. For instance this continuation + is used after a [MAP] instruction applied to an option in order to wrap the + result back in a [Some] constructor. + + /!\ When using it, make sure the function runs in constant time or that gas + has been properly charged beforehand. + Also make sure it runs with a small, bounded stack. + *) + | KMap_head : + ('a -> 'b) * ('b, 'S, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + (* This continuation comes right after a [Dip i] to restore the topmost + element ['b] of the stack after having executed [i] in the substack + of type ['a * 's]. *) + | KUndip : + 'b * ('b, _) ty option * ('b, 'a * 'S, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + (* This continuation is executed at each iteration of a loop with + a Boolean condition. *) + | KLoop_in : + ('a, 'S, bool, 'a * 'S) kinstr * ('a, 'S, 'r, 'F) continuation + -> (bool, 'a * 'S, 'r, 'F) continuation + (* This continuation is executed at each iteration of a loop with + a condition encoded by a sum type. *) + | KLoop_in_left : + ('a, 'S, ('a, 'b) or_, 'S) kinstr * ('b, 'S, 'r, 'F) continuation + -> (('a, 'b) or_, 'S, 'r, 'F) continuation + (* This continuation is executed at each iteration of a traversal. + (Used in List, Map and Set.) *) + | KIter : + ('a, 'b * 'S, 'b, 'S) kinstr + * ('a, _) ty option + * 'a list + * ('b, 'S, 'r, 'F) continuation + -> ('b, 'S, 'r, 'F) continuation + (* This continuation represents each step of a List.map. *) + | KList_enter_body : + ('a, 'c * 'S, 'b, 'c * 'S) kinstr + * 'a list + * 'b Script_list.t + * ('b Script_list.t, _) ty option + * int + * ('b Script_list.t, 'c * 'S, 'r, 'F) continuation + -> ('c, 'S, 'r, 'F) continuation + (* This continuation represents what is done after each step of a List.map. *) + | KList_exit_body : + ('a, 'c * 'S, 'b, 'c * 'S) kinstr + * 'a list + * 'b Script_list.t + * ('b Script_list.t, _) ty option + * int + * ('b Script_list.t, 'c * 'S, 'r, 'F) continuation + -> ('b, 'c * 'S, 'r, 'F) continuation + (* This continuation represents each step of a Map.map. *) + | KMap_enter_body : + (('a, 'b) pair, 'd * 'S, 'c, 'd * 'S) kinstr + * ('a * 'b) list + * ('a, 'c) map + * (('a, 'c) map, _) ty option + * (('a, 'c) map, 'd * 'S, 'r, 'F) continuation + -> ('d, 'S, 'r, 'F) continuation + (* This continuation represents what is done after each step of a Map.map. *) + | KMap_exit_body : + (('a, 'b) pair, 'd * 'S, 'c, 'd * 'S) kinstr + * ('a * 'b) list + * ('a, 'c) map + * 'a + * (('a, 'c) map, _) ty option + * (('a, 'c) map, 'd * 'S, 'r, 'F) continuation + -> ('c, 'd * 'S, 'r, 'F) continuation + (* This continuation represents what is done after returning from a view. + It holds the original step constants value prior to entering the view. *) + | KView_exit : + step_constants * ('a, 'S, 'r, 'F) continuation + -> ('a, 'S, 'r, 'F) continuation + (* This continuation instruments the execution with a [logger]. *) + | KLog : + ('a, 'S, 'r, 'F) continuation * ('a, 'S) stack_ty * logger + -> ('a, 'S, 'r, 'F) continuation + +(* + + Execution instrumentation + ========================= + + One can observe the context and the stack at some specific points + of an execution step. This feature is implemented by calling back + some [logging_function]s defined in a record of type [logger] + passed as argument to the step function. + + A [logger] is typically embedded in an [KLog] continuation by the + client to trigger an evaluation instrumented with some logging. The + logger is then automatically propagated to the logging instruction + [ILog] as well as to any instructions that need to generate a + backtrace when it fails (e.g., [IFailwith], [IMul_teznat], ...). + +*) +and ('a, 'S, 'b, 'F, 'c, 'U) logging_function = + ('a, 'S, 'b, 'F) kinstr -> + context -> + Script.location -> + ('c, 'U) stack_ty -> + 'c * 'U -> + unit + +and execution_trace = (Script.location * Gas.Arith.fp * Script.expr list) list + +and logger = { + log_interp : 'a 'S 'b 'F 'c 'U. ('a, 'S, 'b, 'F, 'c, 'U) logging_function; + (** [log_interp] is called at each call of the internal function + [interp]. [interp] is called when starting the interpretation of + a script and subsequently at each [Exec] instruction. *) + get_log : unit -> execution_trace option tzresult Lwt.t; + (** [get_log] allows to obtain an execution trace, if any was + produced. *) + klog : 'a 'S 'r 'F. ('a, 'S, 'r, 'F) klog; + (** [klog] is called on [KLog] inserted when instrumenting + continuations. *) + ilog : 'a 'S 'b 'T 'r 'F. ('a, 'S, 'b, 'T, 'r, 'F) ilog; + (** [ilog] is called on [ILog] inserted when instrumenting + instructions. *) + log_kinstr : 'a 'b 'c 'd. ('a, 'b, 'c, 'd) log_kinstr; + (** [log_kinstr] instruments an instruction with [ILog]. *) +} + +and ('a, 'S, 'r, 'F) klog = + logger -> + Local_gas_counter.outdated_context * step_constants -> + Local_gas_counter.local_gas_counter -> + ('a, 'S) stack_ty -> + ('a, 'S, 'r, 'F) continuation -> + ('a, 'S, 'r, 'F) continuation -> + 'a -> + 'S -> + ('r + * 'F + * Local_gas_counter.outdated_context + * Local_gas_counter.local_gas_counter) + tzresult + Lwt.t + +and ('a, 'S, 'b, 'T, 'r, 'F) ilog = + logger -> + logging_event -> + ('a, 'S) stack_ty -> + ('a, 'S, 'b, 'T, 'r, 'F) step_type + +and ('a, 'S, 'b, 'T, 'r, 'F) step_type = + Local_gas_counter.outdated_context * step_constants -> + Local_gas_counter.local_gas_counter -> + ('a, 'S, 'b, 'T) kinstr -> + ('b, 'T, 'r, 'F) continuation -> + 'a -> + 'S -> + ('r + * 'F + * Local_gas_counter.outdated_context + * Local_gas_counter.local_gas_counter) + tzresult + Lwt.t + +and ('a, 'b, 'c, 'd) log_kinstr = + logger -> + ('a, 'b) stack_ty -> + ('a, 'b, 'c, 'd) kinstr -> + ('a, 'b, 'c, 'd) kinstr + +(* ---- Auxiliary types -----------------------------------------------------*) +and ('ty, 'comparable) ty = + | Unit_t : (unit, yes) ty + | Int_t : (z num, yes) ty + | Nat_t : (n num, yes) ty + | Signature_t : (signature, yes) ty + | String_t : (Script_string.t, yes) ty + | Bytes_t : (bytes, yes) ty + | Mutez_t : (Tez.t, yes) ty + | Key_hash_t : (public_key_hash, yes) ty + | Key_t : (public_key, yes) ty + | Timestamp_t : (Script_timestamp.t, yes) ty + | Address_t : (address, yes) ty + | Bool_t : (bool, yes) ty + | Pair_t : + ('a, 'ac) ty + * ('b, 'bc) ty + * ('a, 'b) pair ty_metadata + * ('ac, 'bc, 'rc) dand + -> (('a, 'b) pair, 'rc) ty + | Or_t : + ('a, 'ac) ty + * ('b, 'bc) ty + * ('a, 'b) or_ ty_metadata + * ('ac, 'bc, 'rc) dand + -> (('a, 'b) or_, 'rc) ty + | Lambda_t : + ('arg, _) ty * ('ret, _) ty * ('arg, 'ret) lambda ty_metadata + -> (('arg, 'ret) lambda, no) ty + | Option_t : + ('v, 'c) ty * 'v option ty_metadata * 'c dbool + -> ('v option, 'c) ty + | List_t : + ('v, _) ty * 'v Script_list.t ty_metadata + -> ('v Script_list.t, no) ty + | Set_t : 'v comparable_ty * 'v set ty_metadata -> ('v set, no) ty + | Map_t : + 'k comparable_ty * ('v, _) ty * ('k, 'v) map ty_metadata + -> (('k, 'v) map, no) ty + | Big_map_t : + 'k comparable_ty * ('v, _) ty * ('k, 'v) big_map ty_metadata + -> (('k, 'v) big_map, no) ty + | Contract_t : + ('arg, _) ty * 'arg typed_contract ty_metadata + -> ('arg typed_contract, no) ty + | Sapling_transaction_t : Sapling.Memo_size.t -> (Sapling.transaction, no) ty + | Sapling_transaction_deprecated_t : + Sapling.Memo_size.t + -> (Sapling.Legacy.transaction, no) ty + | Sapling_state_t : Sapling.Memo_size.t -> (Sapling.state, no) ty + | Operation_t : (operation, no) ty + | Chain_id_t : (Script_chain_id.t, yes) ty + | Never_t : (never, yes) ty + | Bls12_381_g1_t : (Script_bls.G1.t, no) ty + | Bls12_381_g2_t : (Script_bls.G2.t, no) ty + | Bls12_381_fr_t : (Script_bls.Fr.t, no) ty + | Ticket_t : 'a comparable_ty * 'a ticket ty_metadata -> ('a ticket, no) ty + | Chest_key_t : (Script_timelock.chest_key, no) ty + | Chest_t : (Script_timelock.chest, no) ty + +and 'ty comparable_ty = ('ty, yes) ty + +and ('top_ty, 'resty) stack_ty = + | Item_t : + ('ty, _) ty * ('ty2, 'rest) stack_ty + -> ('ty, 'ty2 * 'rest) stack_ty + | Bot_t : (empty_cell, empty_cell) stack_ty + +and ('key, 'value) big_map = + | Big_map : { + id : Big_map.Id.t option; + diff : ('key, 'value) big_map_overlay; + key_type : 'key comparable_ty; + value_type : ('value, _) ty; + } + -> ('key, 'value) big_map + +and ('a, 'S, 'r, 'F) kdescr = { + kloc : Script.location; + kbef : ('a, 'S) stack_ty; + kaft : ('r, 'F) stack_ty; + kinstr : ('a, 'S, 'r, 'F) kinstr; +} + +(* + + Several instructions work under an arbitrary deep stack prefix + (e.g, IDipn, IDropn, etc). To convince the typechecker that + these instructions are well-typed, we must provide a witness + to statically characterize the relationship between the input + and the output stacks. The inhabitants of the following GADT + act as such witnesses. + + More precisely, a value [w] of type + + [(c, t, d, v, a, s, b, u) stack_prefix_preservation_witness] + + proves that there is a common prefix between an input stack + of type [a * s] and an output stack of type [b * u]. This prefix + is as deep as the number of [KPrefix] application in [w]. When + used with an operation parameterized by a natural number [n] + characterizing the depth at which the operation must be applied, + [w] is the Peano encoding of [n]. + + When this prefix is removed from the two stacks, the input stack + has type [c * t] while the output stack has type [d * v]. + +*) +and (_, _, _, _, _, _, _, _) stack_prefix_preservation_witness = + | KPrefix : + Script.location + * ('a, _) ty + * ('c, 'V, 'd, 'W, 'x, 'S, 'y, 'U) stack_prefix_preservation_witness + -> ( 'c, + 'V, + 'd, + 'W, + 'a, + 'x * 'S, + 'a, + 'y * 'U ) + stack_prefix_preservation_witness + | KRest : ('a, 'S, 'b, 'U, 'a, 'S, 'b, 'U) stack_prefix_preservation_witness + +and (_, _, _, _, _, _) comb_gadt_witness = + | Comb_one : ('a, 'x, 'before, 'a, 'x, 'before) comb_gadt_witness + | Comb_succ : + ('b, 'c, 'S, 'd, 'e, 'T) comb_gadt_witness + -> ('a, 'b, 'c * 'S, 'a * 'd, 'e, 'T) comb_gadt_witness + +and (_, _, _, _, _, _) uncomb_gadt_witness = + | Uncomb_one : ('a, 'x, 'before, 'a, 'x, 'before) uncomb_gadt_witness + | Uncomb_succ : + ('b, 'c, 'S, 'd, 'e, 'T) uncomb_gadt_witness + -> (('a, 'b) pair, 'c, 'S, 'a, 'd, 'e * 'T) uncomb_gadt_witness + +and ('before, 'after) comb_get_gadt_witness = + | Comb_get_zero : ('b, 'b) comb_get_gadt_witness + | Comb_get_one : (('a, 'b) pair, 'a) comb_get_gadt_witness + | Comb_get_plus_two : + ('before, 'after) comb_get_gadt_witness + -> (('a, 'before) pair, 'after) comb_get_gadt_witness + +and ('value, 'before, 'after) comb_set_gadt_witness = + | Comb_set_zero : ('value, _, 'value) comb_set_gadt_witness + | Comb_set_one + : ('value, ('hd, 'tl) pair, ('value, 'tl) pair) comb_set_gadt_witness + | Comb_set_plus_two : + ('value, 'before, 'after) comb_set_gadt_witness + -> ('value, ('a, 'before) pair, ('a, 'after) pair) comb_set_gadt_witness + +(* + + [dup_n_gadt_witness ('a, 'b, 'S, 'T)] ensures that there exists at least + [n] elements in ['a, 'b, 's] and that the [n]-th element is of type + ['t]. Here [n] follows Peano's encoding (0 and successor). + Besides, [0] corresponds to the topmost element of ['s]. + + This relational predicate is defined by induction on [n]. + +*) +and (_, _, _, _) dup_n_gadt_witness = + | Dup_n_zero : ('a, _, _, 'a) dup_n_gadt_witness + | Dup_n_succ : + ('b, 'c, 'stack, 'd) dup_n_gadt_witness + -> ('a, 'b, 'c * 'stack, 'd) dup_n_gadt_witness + +and ('input, 'output) view_signature = + | View_signature : { + name : Script_string.t; + input_ty : ('input, _) ty; + output_ty : ('output, _) ty; + } + -> ('input, 'output) view_signature + +and 'kind internal_operation_contents = + | Transaction_to_implicit : { + destination : Signature.Public_key_hash.t; + amount : Tez.t; + } + -> Kind.transaction internal_operation_contents + | Transaction_to_implicit_with_ticket : { + destination : Signature.Public_key_hash.t; + ticket_ty : ('content ticket, _) ty; + ticket : 'content ticket; + unparsed_ticket : Script.lazy_expr; + amount : Tez.t; + } + -> Kind.transaction internal_operation_contents + | Transaction_to_smart_contract : { + (* The [unparsed_parameters] field may seem useless since we have + access to a typed version of the field (with [parameters_ty] and + [parameters]), but we keep it so that we do not have to unparse the + typed version in order to produce the receipt + ([Apply_internal_results.internal_operation_contents]). *) + destination : Contract_hash.t; + amount : Tez.t; + entrypoint : Entrypoint.t; + location : Script.location; + parameters_ty : ('a, _) ty; + parameters : 'a; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents + | Transaction_to_sc_rollup : { + destination : Sc_rollup.t; + entrypoint : Entrypoint.t; + parameters_ty : ('a, _) ty; + parameters : 'a; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents + | Event : { + ty : Script.expr; + tag : Entrypoint.t; + unparsed_data : Script.expr; + } + -> Kind.event internal_operation_contents + | Transaction_to_zk_rollup : { + destination : Zk_rollup.t; + parameters_ty : (('a ticket, bytes) pair, _) ty; + parameters : ('a ticket, bytes) pair; + unparsed_parameters : Script.expr; + } + -> Kind.transaction internal_operation_contents + | Origination : { + delegate : Signature.Public_key_hash.t option; + code : Script.expr; + unparsed_storage : Script.expr; + credit : Tez.t; + preorigination : Contract_hash.t; + storage_type : ('storage, _) ty; + storage : 'storage; + } + -> Kind.origination internal_operation_contents + | Delegation : + Signature.Public_key_hash.t option + -> Kind.delegation internal_operation_contents + +and 'kind internal_operation = { + sender : Destination.t; + operation : 'kind internal_operation_contents; + nonce : int; +} + +and packed_internal_operation = + | Internal_operation : 'kind internal_operation -> packed_internal_operation +[@@ocaml.unboxed] + +and operation = { + piop : packed_internal_operation; + lazy_storage_diff : Lazy_storage.diffs option; +} + +type ('arg, 'storage) script = + | Script : { + code : + (('arg, 'storage) pair, (operation Script_list.t, 'storage) pair) lambda; + arg_type : ('arg, _) ty; + storage : 'storage; + storage_type : ('storage, _) ty; + views : view_map; + entrypoints : 'arg entrypoints; + code_size : Cache_memory_helpers.sint; + } + -> ('arg, 'storage) script + +type ex_ty = Ex_ty : ('a, _) ty -> ex_ty + +val manager_kind : 'kind internal_operation_contents -> 'kind Kind.manager + +val kinstr_location : (_, _, _, _) kinstr -> Script.location + +val ty_size : ('a, _) ty -> 'a Type_size.t + +val is_comparable : ('v, 'c) ty -> 'c dbool + +type 'v ty_ex_c = Ty_ex_c : ('v, _) ty -> 'v ty_ex_c [@@ocaml.unboxed] + +val unit_t : unit comparable_ty + +val int_t : z num comparable_ty + +val nat_t : n num comparable_ty + +val signature_t : signature comparable_ty + +val string_t : Script_string.t comparable_ty + +val bytes_t : Bytes.t comparable_ty + +val mutez_t : Tez.t comparable_ty + +val key_hash_t : public_key_hash comparable_ty + +val key_t : public_key comparable_ty + +val timestamp_t : Script_timestamp.t comparable_ty + +val address_t : address comparable_ty + +val bool_t : bool comparable_ty + +val pair_t : + Script.location -> ('a, _) ty -> ('b, _) ty -> ('a, 'b) pair ty_ex_c tzresult + +val pair_3_t : + Script.location -> + ('a, _) ty -> + ('b, _) ty -> + ('c, _) ty -> + ('a, ('b, 'c) pair) pair ty_ex_c tzresult + +val comparable_pair_t : + Script.location -> + 'a comparable_ty -> + 'b comparable_ty -> + ('a, 'b) pair comparable_ty tzresult + +val comparable_pair_3_t : + Script.location -> + 'a comparable_ty -> + 'b comparable_ty -> + 'c comparable_ty -> + ('a, ('b, 'c) pair) pair comparable_ty tzresult + +val pair_int_int_unit_t : (z num, (z num, unit) pair) pair comparable_ty + +val or_t : + Script.location -> ('a, _) ty -> ('b, _) ty -> ('a, 'b) or_ ty_ex_c tzresult + +val comparable_or_t : + Script.location -> + 'a comparable_ty -> + 'b comparable_ty -> + ('a, 'b) or_ comparable_ty tzresult + +val or_bytes_bool_t : (Bytes.t, bool) or_ comparable_ty + +val lambda_t : + Script.location -> + ('arg, _) ty -> + ('ret, _) ty -> + (('arg, 'ret) lambda, no) ty tzresult + +val option_t : Script.location -> ('v, 'c) ty -> ('v option, 'c) ty tzresult + +val option_mutez_t : Tez.t option comparable_ty + +val option_string_t : Script_string.t option comparable_ty + +val option_bytes_t : Bytes.t option comparable_ty + +val option_nat_t : n num option comparable_ty + +val option_pair_nat_nat_t : (n num, n num) pair option comparable_ty + +val option_pair_nat_mutez_t : (n num, Tez.t) pair option comparable_ty + +val option_pair_mutez_mutez_t : (Tez.t, Tez.t) pair option comparable_ty + +val option_pair_int_nat_t : (z num, n num) pair option comparable_ty + +val list_t : Script.location -> ('v, _) ty -> ('v Script_list.t, no) ty tzresult + +val list_operation_t : (operation Script_list.t, no) ty + +val set_t : Script.location -> 'v comparable_ty -> ('v set, no) ty tzresult + +val map_t : + Script.location -> + 'k comparable_ty -> + ('v, _) ty -> + (('k, 'v) map, no) ty tzresult + +val big_map_t : + Script.location -> + 'k comparable_ty -> + ('v, _) ty -> + (('k, 'v) big_map, no) ty tzresult + +val contract_t : + Script.location -> ('arg, _) ty -> ('arg typed_contract, no) ty tzresult + +val contract_unit_t : (unit typed_contract, no) ty + +val sapling_transaction_t : + memo_size:Sapling.Memo_size.t -> (Sapling.transaction, no) ty + +val sapling_transaction_deprecated_t : + memo_size:Sapling.Memo_size.t -> (Sapling.Legacy.transaction, no) ty + +val sapling_state_t : memo_size:Sapling.Memo_size.t -> (Sapling.state, no) ty + +val operation_t : (operation, no) ty + +val chain_id_t : Script_chain_id.t comparable_ty + +val never_t : never comparable_ty + +val bls12_381_g1_t : (Script_bls.G1.t, no) ty + +val bls12_381_g2_t : (Script_bls.G2.t, no) ty + +val bls12_381_fr_t : (Script_bls.Fr.t, no) ty + +val ticket_t : + Script.location -> 'a comparable_ty -> ('a ticket, no) ty tzresult + +val chest_key_t : (Script_timelock.chest_key, no) ty + +val chest_t : (Script_timelock.chest, no) ty + +(** + + The following functions named `X_traverse` for X in + [{ kinstr, ty, stack_ty, value }] provide tail recursive top down + traversals over the values of these types. + + The traversal goes through a value and rewrites an accumulator + along the way starting from some [init]ial value for the + accumulator. + + All these traversals follow the same recursion scheme: the + user-provided function is first called on the toplevel value, then + the traversal recurses on the direct subvalues of the same type. + + Hence, the user-provided function must only compute the + contribution of the value on the accumulator minus the contribution + of its subvalues of the same type. + +*) +type 'a kinstr_traverse = { + apply : 'b 'S 'r 'F. 'a -> ('b, 'S, 'r, 'F) kinstr -> 'a; +} + +val kinstr_traverse : + ('a, 'S, 'c, 'F) kinstr -> 'ret -> 'ret kinstr_traverse -> 'ret + +type 'a ty_traverse = {apply : 't 'tc. 'a -> ('t, 'tc) ty -> 'a} + +val ty_traverse : ('a, _) ty -> 'r -> 'r ty_traverse -> 'r + +type 'accu stack_ty_traverse = { + apply : 'ty 'S. 'accu -> ('ty, 'S) stack_ty -> 'accu; +} + +val stack_ty_traverse : ('a, 'S) stack_ty -> 'r -> 'r stack_ty_traverse -> 'r + +type 'a value_traverse = {apply : 't 'tc. 'a -> ('t, 'tc) ty -> 't -> 'a} + +val value_traverse : ('t, _) ty -> 't -> 'r -> 'r value_traverse -> 'r + +val stack_top_ty : ('a, 'b * 'S) stack_ty -> 'a ty_ex_c + +module Typed_contract : sig + val destination : _ typed_contract -> Destination.t + + val arg_ty : 'a typed_contract -> 'a ty_ex_c + + val entrypoint : _ typed_contract -> Entrypoint.t + + module Internal_for_tests : sig + (* This function doesn't guarantee that the contract is well-typed wrt its + registered type at origination, it only guarantees that the type is + plausible wrt to the destination kind. *) + val typed_exn : + ('a, _) ty -> Destination.t -> Entrypoint.t -> 'a typed_contract + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.ml b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.ml new file mode 100644 index 000000000000..e3ade406d01d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.ml @@ -0,0 +1,708 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +open Script_typed_ir +include Cache_memory_helpers + +let script_string_size s = Script_string.to_string s |> string_size + +let ty_traverse_f = + let base_basic = + !!0 + (* Basic types count for 0 because they are all static values, hence shared + and not counted by `reachable_words`. + On the other hand compound types are functions, hence not shared. *) + in + let base_compound_no_meta = header_size in + let base_compound _meta = h1w in + let apply : type a ac. nodes_and_size -> (a, ac) ty -> nodes_and_size = + fun accu ty -> + match ty with + | Unit_t -> ret_succ_adding accu base_basic + | Int_t -> ret_succ_adding accu base_basic + | Nat_t -> ret_succ_adding accu base_basic + | Signature_t -> ret_succ_adding accu base_basic + | String_t -> ret_succ_adding accu base_basic + | Bytes_t -> ret_succ_adding accu base_basic + | Mutez_t -> ret_succ_adding accu base_basic + | Key_hash_t -> ret_succ_adding accu base_basic + | Key_t -> ret_succ_adding accu base_basic + | Timestamp_t -> ret_succ_adding accu base_basic + | Address_t -> ret_succ_adding accu base_basic + | Bool_t -> ret_succ_adding accu base_basic + | Operation_t -> ret_succ_adding accu base_basic + | Chain_id_t -> ret_succ_adding accu base_basic + | Never_t -> ret_succ_adding accu base_basic + | Bls12_381_g1_t -> ret_succ_adding accu base_basic + | Bls12_381_g2_t -> ret_succ_adding accu base_basic + | Bls12_381_fr_t -> ret_succ_adding accu base_basic + | Chest_key_t -> ret_succ_adding accu base_basic + | Chest_t -> ret_succ_adding accu base_basic + | Pair_t (_ty1, _ty2, a, _) -> + ret_succ_adding accu @@ (base_compound a +! (word_size *? 3)) + | Or_t (_ty1, _ty2, a, _) -> + ret_succ_adding accu @@ (base_compound a +! (word_size *? 3)) + | Lambda_t (_ty1, _ty2, a) -> + ret_succ_adding accu @@ (base_compound a +! (word_size *? 2)) + | Option_t (_ty, a, _) -> + ret_succ_adding accu @@ (base_compound a +! (word_size *? 2)) + | List_t (_ty, a) -> ret_succ_adding accu @@ (base_compound a +! word_size) + | Set_t (_cty, a) -> ret_succ_adding accu @@ (base_compound a +! word_size) + | Map_t (_cty, _ty, a) -> + ret_succ_adding accu @@ (base_compound a +! (word_size *? 2)) + | Big_map_t (_cty, _ty, a) -> + ret_succ_adding accu @@ (base_compound a +! (word_size *? 2)) + | Contract_t (_ty, a) -> + ret_succ_adding accu @@ (base_compound a +! word_size) + | Sapling_transaction_t m -> + ret_succ_adding accu + @@ base_compound_no_meta + +! Sapling.Memo_size.in_memory_size m + +! word_size + | Sapling_transaction_deprecated_t m -> + ret_succ_adding accu + @@ base_compound_no_meta + +! Sapling.Memo_size.in_memory_size m + +! word_size + | Sapling_state_t m -> + ret_succ_adding accu + @@ base_compound_no_meta + +! Sapling.Memo_size.in_memory_size m + +! word_size + | Ticket_t (_cty, a) -> + ret_succ_adding accu @@ (base_compound a +! word_size) + in + ({apply} : nodes_and_size ty_traverse) + +let ty_size : type a ac. (a, ac) ty -> nodes_and_size = + fun ty -> ty_traverse ty zero ty_traverse_f + +(* Types stored for logging are optional and never present in the cache. Therefore + it's safe not to count them. *) +let ty_for_logging_size : type a ac. (a, ac) ty option -> sint = fun _ty -> !!0 + +let stack_ty_size s = + let apply : type a s. nodes_and_size -> (a, s) stack_ty -> nodes_and_size = + fun accu s -> + match s with + | Bot_t -> ret_succ accu + | Item_t (ty, _) -> ret_succ_adding (accu ++ ty_size ty) h2w + in + stack_ty_traverse s zero {apply} + +(* Stack types for logging are optional and never present in the cache. Therefore + it's safe not to count them. One word taken by the [None] tag is already + accounted for by the call-sites of this function. *) +let stack_ty_for_logging_size : type a s. (a, s) stack_ty option -> sint = + fun _ -> !!0 + +let script_nat_size n = Script_int.to_zint n |> z_size + +let script_int_size n = Script_int.to_zint n |> z_size + +let signature_size (Script_signature.Signature_tag x) = + match x with + (* By Obj.reachable_words. *) + | Ed25519 _ | Secp256k1 _ | P256 _ | Unknown _ -> !!96 + | Bls _ -> !!128 + +let key_hash_size (_x : Signature.public_key_hash) = !!64 +(* By Obj.reachable_words. *) + +let public_key_size (x : public_key) = + h1w + +? + match x with + | Ed25519 _ -> 64 + | Secp256k1 _ -> 72 + | P256 _ -> 96 + | Bls _ -> 64 + +let mutez_size = h2w + +let timestamp_size x = Script_timestamp.to_zint x |> z_size + +let destination_size = Destination.in_memory_size + +let address_size addr = + h2w + +! destination_size addr.destination + +! Entrypoint.in_memory_size addr.entrypoint + +let view_signature_size (View_signature {name; input_ty; output_ty}) = + ret_adding + (ty_size input_ty ++ ty_size output_ty) + (h3w +! script_string_size name) + +let script_expr_hash_size = !!64 + +(* Note: this function is NOT tail-recursive, but that's okay, since + the recursion is bound by the size of the witness, which is an + 11-bit unsigned integer, i.e. at most 2048. This is enough to + guarantee there will be no stack overflow. *) +let rec stack_prefix_preservation_witness_size_internal : + type a b c d e f g h. + (a, b, c, d, e, f, g, h) stack_prefix_preservation_witness -> nodes_and_size + = function + | KPrefix (_loc, ty, w) -> + ret_succ_adding + (ty_size ty ++ stack_prefix_preservation_witness_size_internal w) + h3w + | KRest -> zero + +let stack_prefix_preservation_witness_size (_n : int) w = + stack_prefix_preservation_witness_size_internal w + +let peano_shape_proof = + let scale = header_size +! h1w in + fun k -> scale *? k + +let comb_gadt_witness_size n (_w : (_, _, _, _, _, _) comb_gadt_witness) = + peano_shape_proof n + +let uncomb_gadt_witness_size n (_w : (_, _, _, _, _, _) uncomb_gadt_witness) = + peano_shape_proof n + +let comb_get_gadt_witness_size n (_w : (_, _) comb_get_gadt_witness) = + peano_shape_proof n + +let comb_set_gadt_witness_size n (_w : (_, _, _) comb_set_gadt_witness) = + peano_shape_proof n + +let dup_n_gadt_witness_size n (_w : (_, _, _, _) dup_n_gadt_witness) = + peano_shape_proof n + +let contract_size : type t. t typed_contract -> nodes_and_size = function + | Typed_implicit _ -> ret_adding zero (h1w +! public_key_hash_in_memory_size) + | Typed_implicit_with_ticket {ticket_ty; destination = _} -> + ret_adding (ty_size ticket_ty) (h2w +! public_key_hash_in_memory_size) + | Typed_originated {arg_ty; contract_hash = _; entrypoint} -> + ret_adding + (ty_size arg_ty) + (h3w +! blake2b_hash_size +! Entrypoint.in_memory_size entrypoint) + | Typed_sc_rollup {arg_ty; sc_rollup; entrypoint} -> + ret_adding + (ty_size arg_ty) + (h3w + +! Sc_rollup.in_memory_size sc_rollup + +! Entrypoint.in_memory_size entrypoint) + | Typed_zk_rollup {arg_ty; zk_rollup} -> + ret_adding (ty_size arg_ty) (h2w +! Zk_rollup.in_memory_size zk_rollup) + +let sapling_state_size {Sapling.id; diff; memo_size} = + h3w + +! option_size (fun x -> z_size (Sapling.Id.unparse_to_z x)) id + +! Sapling.diff_in_memory_size diff + +! Sapling.Memo_size.in_memory_size memo_size + +let chain_id_size = !!16 (* by Obj.reachable_words. *) + +(* [contents] is handled by the recursion scheme in [value_size]. *) +let ticket_size {ticketer; contents = _; amount} = + h3w + +! Contract.in_memory_size ticketer + +! script_nat_size (amount :> Script_int.n Script_int.num) + +let chest_size chest = + (* + type chest = { + locked_value : locked_value; + ciphertext : ciphertext; + } + *) + let locked_value_size = 256 in + let ciphertext_size = Script_timelock.get_plaintext_size chest in + h3w +? (locked_value_size + ciphertext_size) + +let chest_key_size _ = + (* + type chest_key = { + vdf_tuple : vdf_tuple; a record of 3 group elements, each of size 256 bytes + nonce : Z.t; RSA modulus size (256 bytes) + 128 bits + } + *) + let vdf_tuple_size = 3 * 256 in + let nonce_size = 256 + 16 in + h2w +? (vdf_tuple_size + nonce_size) + +(* The following mutually recursive functions are mostly + tail-recursive and the only recursive call that is not a tailcall + cannot be nested. (See [big_map_size].) For this reason, these + functions should not trigger stack overflows. *) +let rec value_size : + type a ac. + count_lambda_nodes:bool -> + nodes_and_size -> + (a, ac) ty -> + a -> + nodes_and_size = + fun ~count_lambda_nodes accu ty x -> + let apply : type a ac. nodes_and_size -> (a, ac) ty -> a -> nodes_and_size = + fun accu ty x -> + match ty with + | Unit_t -> ret_succ accu + | Int_t -> ret_succ_adding accu (script_int_size x) + | Nat_t -> ret_succ_adding accu (script_nat_size x) + | Signature_t -> ret_succ_adding accu (signature_size x) + | String_t -> ret_succ_adding accu (script_string_size x) + | Bytes_t -> ret_succ_adding accu (bytes_size x) + | Mutez_t -> ret_succ_adding accu mutez_size + | Key_hash_t -> ret_succ_adding accu (key_hash_size x) + | Key_t -> ret_succ_adding accu (public_key_size x) + | Timestamp_t -> ret_succ_adding accu (timestamp_size x) + | Address_t -> ret_succ_adding accu (address_size x) + | Bool_t -> ret_succ accu + | Pair_t (_, _, _, _) -> ret_succ_adding accu h2w + | Or_t (_, _, _, _) -> ret_succ_adding accu h1w + | Lambda_t (_, _, _) -> + (lambda_size [@ocaml.tailcall]) ~count_lambda_nodes (ret_succ accu) x + | Option_t (_, _, _) -> ret_succ_adding accu (option_size (fun _ -> !!0) x) + | List_t (_, _) -> ret_succ_adding accu (h2w +! (h2w *? x.length)) + | Set_t (_, _) -> + let module M = (val Script_set.get x) in + let boxing_space = !!536 (* By Obj.reachable_words. *) in + ret_succ_adding accu (boxing_space +! (h4w *? M.size)) + | Map_t (_, _, _) -> + let module M = (val Script_map.get_module x) in + let boxing_space = !!696 (* By Obj.reachable_words. *) in + ret_succ_adding accu (boxing_space +! (h5w *? M.size)) + | Big_map_t (cty, ty', _) -> + (big_map_size [@ocaml.tailcall]) + ~count_lambda_nodes + (ret_succ accu) + cty + ty' + x + | Contract_t (_, _) -> ret_succ (accu ++ contract_size x) + | Sapling_transaction_t _ -> + ret_succ_adding accu (Sapling.transaction_in_memory_size x) + | Sapling_transaction_deprecated_t _ -> + ret_succ_adding accu (Sapling.Legacy.transaction_in_memory_size x) + | Sapling_state_t _ -> ret_succ_adding accu (sapling_state_size x) + (* Operations are neither storable nor pushable, so they can appear neither + in the storage nor in the script. Hence they cannot appear in the cache + and we never need to measure their size. *) + | Operation_t -> assert false + | Chain_id_t -> ret_succ_adding accu chain_id_size + | Never_t -> ( match x with _ -> .) + | Bls12_381_g1_t -> ret_succ_adding accu !!Bls.Primitive.G1.size_in_memory + | Bls12_381_g2_t -> ret_succ_adding accu !!Bls.Primitive.G2.size_in_memory + | Bls12_381_fr_t -> ret_succ_adding accu !!Bls.Primitive.Fr.size_in_memory + | Ticket_t (_, _) -> ret_succ_adding accu (ticket_size x) + | Chest_key_t -> ret_succ_adding accu (chest_key_size x) + | Chest_t -> ret_succ_adding accu (chest_size x) + in + value_traverse ty x accu {apply} + +and big_map_size : + type a b bc. + count_lambda_nodes:bool -> + nodes_and_size -> + a comparable_ty -> + (b, bc) ty -> + (a, b) big_map -> + nodes_and_size = + fun ~count_lambda_nodes accu cty ty' (Big_map {id; diff; key_type; value_type}) -> + (* [Map.bindings] cannot overflow and only consumes a + logarithmic amount of stack. *) + let diff_size = + let map_size = + Big_map_overlay.fold + (fun _key_hash (key, value) accu -> + let base = h5w +! (word_size *? 3) +! script_expr_hash_size in + let accu = ret_succ_adding accu base in + (* The following recursive call cannot introduce a stack + overflow because this would require a key of type + big_map while big_map is not comparable. *) + let accu = value_size ~count_lambda_nodes accu cty key in + match value with + | None -> accu + | Some value -> + let accu = ret_succ_adding accu h1w in + (value_size [@ocaml.tailcall]) ~count_lambda_nodes accu ty' value) + diff.map + accu + in + ret_adding map_size h2w + in + let big_map_id_size s = z_size (Big_map.Id.unparse_to_z s) in + let id_size = option_size big_map_id_size id in + ret_adding + (ty_size key_type ++ ty_size value_type ++ diff_size) + (h4w +! id_size) + +and lambda_size : + type i o. + count_lambda_nodes:bool -> nodes_and_size -> (i, o) lambda -> nodes_and_size + = + fun ~count_lambda_nodes accu lam -> + let count_lambda_body kdescr node = + (* We assume that the nodes' size have already been counted if the + lambda is not a toplevel lambda. *) + let accu = + ret_adding + (accu ++ if count_lambda_nodes then node_size node else zero) + h2w + in + (kdescr_size [@ocaml.tailcall]) ~count_lambda_nodes:false accu kdescr + in + match lam with + | Lam (kdescr, node) -> count_lambda_body kdescr node + | LamRec (kdescr, node) -> count_lambda_body kdescr node + +and kdescr_size : + type a s r f. + count_lambda_nodes:bool -> + nodes_and_size -> + (a, s, r, f) kdescr -> + nodes_and_size = + fun ~count_lambda_nodes accu {kloc = _; kbef; kaft; kinstr} -> + let accu = + ret_adding (accu ++ stack_ty_size kbef ++ stack_ty_size kaft) h4w + in + (kinstr_size [@ocaml.tailcall]) ~count_lambda_nodes accu kinstr + +and kinstr_size : + type a s r f. + count_lambda_nodes:bool -> + nodes_and_size -> + (a, s, r, f) kinstr -> + nodes_and_size = + fun ~count_lambda_nodes accu t -> + (* To avoid forgetting counting things, the [apply] function below must ignore + no values (can be checked by grepping \b_\w*\b), except for the [ILog] case. + Use the [base] function depending on the number of continuations in the + instruction and only count other fields. + Location counts as zero because it's an immediate integer. + Continuations are counted by the [kinstr_traverse] function. + *) + let base0 (_loc : Script.location) = h1w in + let base1 (_loc : Script.location) (_k : (_, _, _, _) kinstr) = h2w in + let base2 (_loc : Script.location) (_k1 : (_, _, _, _) kinstr) + (_k2 : (_, _, _, _) kinstr) = + h3w + in + let base3 (_loc : Script.location) (_k1 : (_, _, _, _) kinstr) + (_k2 : (_, _, _, _) kinstr) (_k3 : (_, _, _, _) kinstr) = + h4w + in + let apply : + type a s r f. nodes_and_size -> (a, s, r, f) kinstr -> nodes_and_size = + fun accu t -> + match t with + | IDrop (loc, k) -> ret_succ_adding accu (base1 loc k) + | IDup (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISwap (loc, k) -> ret_succ_adding accu (base1 loc k) + | IPush (loc, ty, x, k) -> + let accu = ret_succ_adding accu (base1 loc k +! (word_size *? 2)) in + (value_size [@ocaml.tailcall]) + ~count_lambda_nodes + (accu ++ ty_size ty) + ty + x + | IUnit (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICons_pair (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICar (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICdr (loc, k) -> ret_succ_adding accu (base1 loc k) + | IUnpair (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICons_some (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICons_none (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | IIf_none {loc; branch_if_none = k1; branch_if_some = k2; k = k3} -> + ret_succ_adding accu (base3 loc k1 k2 k3) + | IOpt_map {loc; body = k1; k = k2} -> + ret_succ_adding accu (base2 loc k1 k2) + | ICons_left (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | ICons_right (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | IIf_left {loc; branch_if_left = k1; branch_if_right = k2; k = k3} -> + ret_succ_adding accu (base3 loc k1 k2 k3) + | ICons_list (loc, k) -> ret_succ_adding accu (base1 loc k) + | INil (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | IIf_cons {loc; branch_if_nil = k1; branch_if_cons = k2; k = k3} -> + ret_succ_adding accu (base3 loc k1 k2 k3) + | IList_map (loc, k1, ty, k2) -> + ret_succ_adding + accu + (base2 loc k1 k2 +! ty_for_logging_size ty +! word_size) + | IList_iter (loc, ty, k1, k2) -> + ret_succ_adding + accu + (base2 loc k1 k2 +! ty_for_logging_size ty +! word_size) + | IList_size (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEmpty_set (loc, cty, k) -> + ret_succ_adding (accu ++ ty_size cty) (base1 loc k +! word_size) + | ISet_iter (loc, ty, k1, k2) -> + ret_succ_adding + accu + (base2 loc k1 k2 +! ty_for_logging_size ty +! word_size) + | ISet_mem (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISet_update (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISet_size (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEmpty_map (loc, cty, vty, k) -> + ret_succ_adding + (accu ++ ty_size cty) + (base1 loc k +! ty_for_logging_size vty +! (word_size *? 2)) + | IMap_map (loc, ty, k1, k2) -> + ret_succ_adding + accu + (base2 loc k1 k2 +! ty_for_logging_size ty +! word_size) + | IMap_iter (loc, kvty, k1, k2) -> + ret_succ_adding + accu + (base2 loc k1 k2 +! ty_for_logging_size kvty +! word_size) + | IMap_mem (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMap_get (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMap_update (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMap_get_and_update (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMap_size (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEmpty_big_map (loc, cty, ty, k) -> + ret_succ_adding + (accu ++ ty_size cty ++ ty_size ty) + (base1 loc k +! (word_size *? 2)) + | IBig_map_mem (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBig_map_get (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBig_map_update (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBig_map_get_and_update (loc, k) -> ret_succ_adding accu (base1 loc k) + | IConcat_string (loc, k) -> ret_succ_adding accu (base1 loc k) + | IConcat_string_pair (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISlice_string (loc, k) -> ret_succ_adding accu (base1 loc k) + | IString_size (loc, k) -> ret_succ_adding accu (base1 loc k) + | IConcat_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IConcat_bytes_pair (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISlice_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBytes_size (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILsl_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILsr_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IOr_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAnd_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IXor_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | INot_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBytes_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | INat_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBytes_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IInt_bytes (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_seconds_to_timestamp (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_timestamp_to_seconds (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISub_timestamp_seconds (loc, k) -> ret_succ_adding accu (base1 loc k) + | IDiff_timestamps (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_tez (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISub_tez (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISub_tez_legacy (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_teznat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_nattez (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEdiv_teznat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEdiv_tez (loc, k) -> ret_succ_adding accu (base1 loc k) + | IOr (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAnd (loc, k) -> ret_succ_adding accu (base1 loc k) + | IXor (loc, k) -> ret_succ_adding accu (base1 loc k) + | INot (loc, k) -> ret_succ_adding accu (base1 loc k) + | IIs_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | INeg (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAbs_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IInt_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISub_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEdiv_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEdiv_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILsl_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILsr_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IOr_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAnd_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAnd_int_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | IXor_nat (loc, k) -> ret_succ_adding accu (base1 loc k) + | INot_int (loc, k) -> ret_succ_adding accu (base1 loc k) + | IIf {loc; branch_if_true = k1; branch_if_false = k2; k = k3} -> + ret_succ_adding accu (base3 loc k1 k2 k3) + | ILoop (loc, k1, k2) -> ret_succ_adding accu (base2 loc k1 k2) + | ILoop_left (loc, k1, k2) -> ret_succ_adding accu (base2 loc k1 k2) + | IDip (loc, k1, ty, k2) -> + ret_succ_adding + accu + (base2 loc k1 k2 +! ty_for_logging_size ty +! word_size) + | IExec (loc, sty, k) -> + ret_succ_adding + accu + (base1 loc k +! stack_ty_for_logging_size sty +! word_size) + | IApply (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | ILambda (loc, lambda, k) -> + let accu = ret_succ_adding accu (base1 loc k +! word_size) in + (lambda_size [@ocaml.tailcall]) ~count_lambda_nodes accu lambda + | IFailwith (loc, ty) -> + ret_succ_adding (accu ++ ty_size ty) (base0 loc +! word_size) + | ICompare (loc, cty, k) -> + ret_succ_adding (accu ++ ty_size cty) (base1 loc k +! word_size) + | IEq (loc, k) -> ret_succ_adding accu (base1 loc k) + | INeq (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILt (loc, k) -> ret_succ_adding accu (base1 loc k) + | IGt (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILe (loc, k) -> ret_succ_adding accu (base1 loc k) + | IGe (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAddress (loc, k) -> ret_succ_adding accu (base1 loc k) + | IContract (loc, ty, s, k) -> + ret_succ_adding + (accu ++ ty_size ty) + (base1 loc k +! Entrypoint.in_memory_size s +! (word_size *? 2)) + | IView (loc, s, sty, k) -> + ret_succ_adding + (accu ++ view_signature_size s) + (base1 loc k +! stack_ty_for_logging_size sty +! (word_size *? 2)) + | ITransfer_tokens (loc, k) -> ret_succ_adding accu (base1 loc k) + | IImplicit_account (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICreate_contract {loc; storage_type; code; k} -> + ret_succ_adding + (accu ++ ty_size storage_type ++ expr_size code) + (base1 loc k +! (word_size *? 2)) + | ISet_delegate (loc, k) -> ret_succ_adding accu (base1 loc k) + | INow (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMin_block_time (loc, k) -> ret_succ_adding accu (base1 loc k) + | IBalance (loc, k) -> ret_succ_adding accu (base1 loc k) + | ILevel (loc, k) -> ret_succ_adding accu (base1 loc k) + | ICheck_signature (loc, k) -> ret_succ_adding accu (base1 loc k) + | IHash_key (loc, k) -> ret_succ_adding accu (base1 loc k) + | IPack (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | IUnpack (loc, ty, k) -> + ret_succ_adding (accu ++ ty_size ty) (base1 loc k +! word_size) + | IBlake2b (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISha256 (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISha512 (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISource (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISender (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISelf (loc, ty, s, k) -> + ret_succ_adding + (accu ++ ty_size ty) + (base1 loc k +! (word_size *? 2) +! Entrypoint.in_memory_size s) + | ISelf_address (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAmount (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISapling_empty_state (loc, m, k) -> + ret_succ_adding + accu + (base1 loc k +! word_size +! Sapling.Memo_size.in_memory_size m) + | ISapling_verify_update (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISapling_verify_update_deprecated (loc, k) -> + ret_succ_adding accu (base1 loc k) + | IDig (loc, n, w, k) -> + ret_succ_adding + (accu ++ stack_prefix_preservation_witness_size n w) + (base1 loc k +! (word_size *? 2)) + | IDug (loc, n, w, k) -> + ret_succ_adding + (accu ++ stack_prefix_preservation_witness_size n w) + (base1 loc k +! (word_size *? 2)) + | IDipn (loc, n, w, k1, k2) -> + ret_succ_adding + (accu ++ stack_prefix_preservation_witness_size n w) + (base2 loc k1 k2 +! (word_size *? 2)) + | IDropn (loc, n, w, k) -> + ret_succ_adding + (accu ++ stack_prefix_preservation_witness_size n w) + (base1 loc k +! (word_size *? 2)) + | IChainId (loc, k) -> ret_succ_adding accu (base1 loc k) + | INever loc -> ret_succ_adding accu (base0 loc) + | IVoting_power (loc, k) -> ret_succ_adding accu (base1 loc k) + | ITotal_voting_power (loc, k) -> ret_succ_adding accu (base1 loc k) + | IKeccak (loc, k) -> ret_succ_adding accu (base1 loc k) + | ISha3 (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_bls12_381_g1 (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_bls12_381_g2 (loc, k) -> ret_succ_adding accu (base1 loc k) + | IAdd_bls12_381_fr (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_bls12_381_g1 (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_bls12_381_g2 (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_bls12_381_fr (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_bls12_381_z_fr (loc, k) -> ret_succ_adding accu (base1 loc k) + | IMul_bls12_381_fr_z (loc, k) -> ret_succ_adding accu (base1 loc k) + | IInt_bls12_381_fr (loc, k) -> ret_succ_adding accu (base1 loc k) + | INeg_bls12_381_g1 (loc, k) -> ret_succ_adding accu (base1 loc k) + | INeg_bls12_381_g2 (loc, k) -> ret_succ_adding accu (base1 loc k) + | INeg_bls12_381_fr (loc, k) -> ret_succ_adding accu (base1 loc k) + | IPairing_check_bls12_381 (loc, k) -> ret_succ_adding accu (base1 loc k) + | IComb (loc, n, w, k) -> + ret_succ_adding + accu + (base1 loc k +! (word_size *? 2) +! comb_gadt_witness_size n w) + | IUncomb (loc, n, w, k) -> + ret_succ_adding + accu + (base1 loc k +! (word_size *? 2) +! uncomb_gadt_witness_size n w) + | IComb_get (loc, n, w, k) -> + ret_succ_adding + accu + (base1 loc k +! (word_size *? 2) +! comb_get_gadt_witness_size n w) + | IComb_set (loc, n, w, k) -> + ret_succ_adding + accu + (base1 loc k +! (word_size *? 2) +! comb_set_gadt_witness_size n w) + | IDup_n (loc, n, w, k) -> + ret_succ_adding + accu + (base1 loc k +! (word_size *? 2) +! dup_n_gadt_witness_size n w) + | ITicket (loc, cty, k) -> + ret_succ_adding + accu + (base1 loc k +! ty_for_logging_size cty +! word_size) + | ITicket_deprecated (loc, cty, k) -> + ret_succ_adding + accu + (base1 loc k +! ty_for_logging_size cty +! word_size) + | IRead_ticket (loc, ty, k) -> + ret_succ_adding accu (base1 loc k +! ty_for_logging_size ty +! word_size) + | ISplit_ticket (loc, k) -> ret_succ_adding accu (base1 loc k) + | IJoin_tickets (loc, cty, k) -> + ret_succ_adding (accu ++ ty_size cty) (base1 loc k +! word_size) + | IOpen_chest (loc, k) -> ret_succ_adding accu (base1 loc k) + | IEmit {loc; tag; ty; unparsed_ty; k} -> + ret_succ_adding + (accu ++ ty_size ty ++ expr_size unparsed_ty) + (base1 loc k +! Entrypoint.in_memory_size tag +! (word_size *? 3)) + | IHalt loc -> ret_succ_adding accu (base0 loc) + | ILog _ -> + (* This instruction is ignored because it is only used for testing. + Keep this case at the end. *) + accu + in + kinstr_traverse t accu {apply} + +let lambda_size lam = lambda_size ~count_lambda_nodes:true zero lam + +let kinstr_size kinstr = kinstr_size ~count_lambda_nodes:true zero kinstr + +let value_size ty x = value_size ~count_lambda_nodes:true zero ty x + +module Internal_for_tests = struct + let ty_size = ty_size + + let kinstr_size = kinstr_size + + let stack_prefix_preservation_witness_size = + stack_prefix_preservation_witness_size_internal +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.mli b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.mli new file mode 100644 index 000000000000..41fc1434d1ad --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size.mli @@ -0,0 +1,85 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides overapproximation of memory footprint for + Michelson-related values. + + These overapproximations are used by the cache to evaluate its own + memory footprint and enforce declared limit over its size. + +*) + +(** [value_size ty v] returns an overapproximation of the size of the + in-memory representation of [v] of type [ty]. *) +val value_size : + ('a, _) Script_typed_ir.ty -> 'a -> Cache_memory_helpers.nodes_and_size + +(** [lambda_size l] returns an overapproximation of the size of the + internal IR for the Michelson lambda abstraction [l]. *) +val lambda_size : + ('a, 'b) Script_typed_ir.lambda -> Cache_memory_helpers.nodes_and_size + +(** [node_size root] returns the size of the in-memory representation + of [root] in bytes. This is an over-approximation of the memory + actually consumed by [root] since no sharing is taken into + account. *) +val node_size : + ('loc, 'prim) Micheline.node -> Cache_memory_helpers.nodes_and_size + +(** Pointwise addition (reexport from {!Cache_memory_helpers}) *) +val ( ++ ) : + Cache_memory_helpers.nodes_and_size -> + Cache_memory_helpers.nodes_and_size -> + Cache_memory_helpers.nodes_and_size + +(** Zero vector (reexport from {!Cache_memory_helpers}) *) +val zero : Cache_memory_helpers.nodes_and_size + +(**/**) + +module Internal_for_tests : sig + (** [ty_size ty] returns an overapproximation of the size of the + in-memory representation of type [ty]. *) + val ty_size : + ('a, _) Script_typed_ir.ty -> Cache_memory_helpers.nodes_and_size + + (** [kinstr_size i] returns an overapproximation of the size of the + internal IR [i]. *) + val kinstr_size : + ('a, 's, 'r, 'f) Script_typed_ir.kinstr -> + Cache_memory_helpers.nodes_and_size + + val stack_prefix_preservation_witness_size : + ( 'a, + 'b, + 'c, + 'd, + 'e, + 'f, + 'g, + 'h ) + Script_typed_ir.stack_prefix_preservation_witness -> + Cache_memory_helpers.nodes_and_size +end diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.ml b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.ml new file mode 100644 index 000000000000..9f1c157c8e20 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.ml @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Script_typed_ir_size_costs_generated + +(* [coeff] should be the maximum of + [script_typed_ir_size/KINSTR_SIZE_size_coeff] + [script_typed_ir_size/NODE_SIZE_ns_per_node_coeff] + [script_typed_ir_size/TYPE_SIZE_size_coeff] + [script_typed_ir_size/VALUE_SIZE_size_coeff] +*) +(* FIXME insert proper gas constants (the gas constant below was fitted on + a non-standard machine) *) +let nodes_cost ~nodes = + let open S.Syntax in + let nodes = Cache_memory_helpers.Nodes.to_int nodes in + let coeff = S.safe_int 45 in + coeff * S.safe_int nodes |> Gas_limit_repr.atomic_step_cost diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.mli b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.mli new file mode 100644 index 000000000000..0daf34b91c02 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [nodes_cost ~nodes] returns the cost of having called + a function in {!Script_typed_ir_size} that returns [nodes], i.e. + [value_size], [lambda_size] and [node_size] +*) +val nodes_cost : nodes:Cache_memory_helpers.Nodes.t -> Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs_generated.ml new file mode 100644 index 000000000000..54ccda9c770f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/script_typed_ir_size_costs_generated.ml @@ -0,0 +1,34 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model script_typed_ir_size/KINSTR_SIZE *) +(* fun size -> max 10 (0. + (16.9107287794 * size)) *) +let cost_KINSTR_SIZE size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 17) + +(* model script_typed_ir_size/NODE_SIZE *) +(* fun size -> max 10 (0. + (25.3968974269 * size)) *) +let cost_NODE_SIZE size = + let size = S.safe_int size in + S.max (S.safe_int 10) ((size lsr 1) + (size * S.safe_int 25)) + +(* model script_typed_ir_size/TYPE_SIZE *) +(* fun size -> max 10 (0. + (16.223250671 * size)) *) +let cost_TYPE_SIZE size = + let size = S.safe_int size in + S.max (S.safe_int 10) ((size lsr 1) + (size * S.safe_int 16)) + +(* model script_typed_ir_size/VALUE_SIZE *) +(* fun size -> max 10 (0. + (19.5698881074 * size)) *) +let cost_VALUE_SIZE size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 20) diff --git a/src/proto_020_PsParisC/lib_protocol/seed_repr.ml b/src/proto_020_PsParisC/lib_protocol/seed_repr.ml new file mode 100644 index 000000000000..ab00efece29d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/seed_repr.ml @@ -0,0 +1,201 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Tezos Protocol Implementation - Random number generation *) + +type seed = B of State_hash.t + +type nonce = bytes + +type vdf_setup = Vdf.discriminant * Vdf.challenge + +type vdf_solution = Vdf.result * Vdf.proof + +let seed_to_bytes x = + let seed_to_state_hash (B b) = b in + State_hash.to_bytes (seed_to_state_hash x) + +let vdf_setup_encoding = + let open Data_encoding in + let vdf_discriminant_encoding = + conv_with_guard + Vdf.discriminant_to_bytes + (fun b -> + Option.to_result + ~none:"VDF discriminant could not be deserialised" + (Vdf.discriminant_of_bytes_opt b)) + (Fixed.(bytes Hex) Vdf.discriminant_size_bytes) + in + let vdf_challenge_encoding = + conv_with_guard + Vdf.challenge_to_bytes + (fun b -> + Option.to_result + ~none:"VDF challenge could not be deserialised" + (Vdf.challenge_of_bytes_opt b)) + (Fixed.(bytes Hex) Vdf.form_size_bytes) + in + tup2 vdf_discriminant_encoding vdf_challenge_encoding + +let vdf_solution_encoding = + let open Data_encoding in + let vdf_result_encoding = + conv_with_guard + Vdf.result_to_bytes + (fun b -> + Option.to_result + ~none:"VDF result could not be deserialised" + (Vdf.result_of_bytes_opt b)) + (Fixed.(bytes Hex) Vdf.form_size_bytes) + in + let vdf_proof_encoding = + conv_with_guard + Vdf.proof_to_bytes + (fun b -> + Option.to_result + ~none:"VDF proof could not be deserialised" + (Vdf.proof_of_bytes_opt b)) + (Fixed.(bytes Hex) Vdf.form_size_bytes) + in + tup2 vdf_result_encoding vdf_proof_encoding + +let pp_solution ppf solution = + let result, proof = solution in + Format.fprintf + ppf + "@[VDF result: %a" + Hex.pp + (Hex.of_bytes (Vdf.result_to_bytes result)) ; + Format.fprintf + ppf + "@,VDF proof: %a" + Hex.pp + (Hex.of_bytes (Vdf.proof_to_bytes proof)) ; + Format.fprintf ppf "@]" + +let nonce_encoding = Data_encoding.Fixed.(bytes Hex) Constants_repr.nonce_length + +let zero_bytes = Bytes.make Nonce_hash.size '\000' + +let state_hash_encoding = + let open Data_encoding in + conv + State_hash.to_bytes + State_hash.of_bytes_exn + (Fixed.(bytes Hex) Nonce_hash.size) + +let seed_encoding = + let open Data_encoding in + conv (fun (B b) -> b) (fun b -> B b) state_hash_encoding + +let update_seed (B state) nonce = + B (State_hash.hash_bytes [State_hash.to_bytes state; nonce]) + +type error += Unexpected_nonce_length (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"unexpected_nonce_length" + ~title:"Unexpected nonce length" + ~description:"Nonce length is incorrect." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Nonce length is not %i bytes long as it should." + Constants_repr.nonce_length) + Data_encoding.empty + (function Unexpected_nonce_length -> Some () | _ -> None) + (fun () -> Unexpected_nonce_length) + +let make_nonce nonce = + let open Result_syntax in + if Compare.Int.(Bytes.length nonce <> Constants_repr.nonce_length) then + tzfail Unexpected_nonce_length + else return nonce + +let hash nonce = Nonce_hash.hash_bytes [nonce] + +let check_hash nonce hash = + Compare.Int.(Bytes.length nonce = Constants_repr.nonce_length) + && Nonce_hash.equal (Nonce_hash.hash_bytes [nonce]) hash + +let nonce_hash_key_part = Nonce_hash.to_path + +let initial_nonce_0 = zero_bytes + +let deterministic_seed seed = update_seed seed zero_bytes + +let initial_seeds ?initial_seed n = + let rec loop acc elt i = + if Compare.Int.(i = 1) then List.rev (elt :: acc) + else loop (elt :: acc) (deterministic_seed elt) (i - 1) + in + let first_seed = + match initial_seed with + | Some initial_seed -> update_seed (B initial_seed) initial_nonce_0 + | None -> B (State_hash.hash_bytes []) + in + loop [] first_seed n + +let nonce_discriminant = Bytes.of_string "Tezos_generating_vdf_discriminant" + +let nonce_challenge = Bytes.of_string "Tezos_generating_vdf_challenge" + +let generate_vdf_setup ~seed_discriminant ~seed_challenge = + let size = Vdf.discriminant_size_bytes in + let seed = + update_seed seed_discriminant nonce_discriminant |> seed_to_bytes + in + let discriminant = Vdf.generate_discriminant ~seed size in + let input = update_seed seed_challenge nonce_challenge |> seed_to_bytes in + let challenge = Vdf.generate_challenge discriminant input in + (discriminant, challenge) + +let verify (discriminant, challenge) vdf_difficulty solution = + (* We return false when getting non group elements as input *) + let result, proof = solution in + (* Note: external library call must be wrapped to ensure that + exceptions are caught. *) + Option.catch (fun () -> + Vdf.verify discriminant challenge vdf_difficulty result proof) + +let vdf_to_seed seed_challenge solution = + let result, _ = solution in + update_seed seed_challenge (Vdf.result_to_bytes result) + +type seed_status = RANDAO_seed | VDF_seed + +let seed_status_encoding = + let to_bool = function RANDAO_seed -> false | VDF_seed -> true in + let of_bool t = if t then VDF_seed else RANDAO_seed in + Data_encoding.conv to_bool of_bool Data_encoding.bool + +let compare_vdf_solution solution solution' = + let result, _ = solution in + let result', _ = solution' in + Compare.Bytes.compare + (Vdf.result_to_bytes result) + (Vdf.result_to_bytes result') diff --git a/src/proto_020_PsParisC/lib_protocol/seed_repr.mli b/src/proto_020_PsParisC/lib_protocol/seed_repr.mli new file mode 100644 index 000000000000..e15c31b99a83 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/seed_repr.mli @@ -0,0 +1,100 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Random number generation + + This is not expected to be a good cryptographic random number + generator. In particular this is supposed to be used in situations + where the seed is a globally known information. + + The only expected property is: It should be difficult to find a + seed such that the generated sequence is a given one. *) + +(** {2 Random Generation} *) + +(** A random seed, to derive random sequences from *) +type seed + +(** A VDF discriminant and challenge *) +type vdf_setup = Vdf.discriminant * Vdf.challenge + +(** A VDF result, to derive a seed from *) +type vdf_solution = Vdf.result * Vdf.proof + +val pp_solution : Format.formatter -> vdf_solution -> unit + +(** Compare only the first element of two vdf_solution, that are + of [Vdf.result]. *) +val compare_vdf_solution : vdf_solution -> vdf_solution -> int + +val generate_vdf_setup : + seed_discriminant:seed -> seed_challenge:seed -> vdf_setup + +val verify : vdf_setup -> Int64.t -> vdf_solution -> bool option + +val vdf_to_seed : seed -> vdf_solution -> seed + +(** {2 Entropy} *) + +(** A nonce for adding entropy to the generator *) +type nonce + +(** Add entropy to the seed generator *) +val update_seed : seed -> nonce -> seed + +(** Use a byte sequence as a nonce *) +val make_nonce : bytes -> nonce tzresult + +(** Compute the hash of a nonce *) +val hash : nonce -> Nonce_hash.t + +(** [check_hash nonce hash] is true if the nonce correspond to the hash *) +val check_hash : nonce -> Nonce_hash.t -> bool + +(** For using nonce hashes as keys in the hierarchical database *) +val nonce_hash_key_part : Nonce_hash.t -> string list -> string list + +(** Returns a new seed by hashing the one passed with a constant. *) +val deterministic_seed : seed -> seed + +(** [initial_seeds n] generates the first [n] seeds for which there are no nonces. + The first seed is a constant value. The kth seed is the hash of seed (k-1) + concatenated with a constant. If an [initial_seed] is provided, the + {i first} seed is created using it as the first one. *) +val initial_seeds : ?initial_seed:State_hash.t -> int -> seed list + +(** {2 Serializers} *) + +val nonce_encoding : nonce Data_encoding.t + +val seed_encoding : seed Data_encoding.t + +val vdf_setup_encoding : vdf_setup Data_encoding.t + +val vdf_solution_encoding : vdf_solution Data_encoding.t + +type seed_status = RANDAO_seed | VDF_seed + +val seed_status_encoding : seed_status Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/seed_storage.ml b/src/proto_020_PsParisC/lib_protocol/seed_storage.ml new file mode 100644 index 000000000000..9409d20883cd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/seed_storage.ml @@ -0,0 +1,265 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type seed_computation_status = + | Nonce_revelation_stage + | Vdf_revelation_stage of { + seed_discriminant : Seed_repr.seed; + seed_challenge : Seed_repr.seed; + } + | Computation_finished + +type error += + | (* `Permanent *) + Unknown of { + oldest : Cycle_repr.t; + cycle : Cycle_repr.t; + latest : Cycle_repr.t; + } + | Already_accepted + | Unverified_vdf + | Too_early_revelation + +let () = + register_error_kind + `Permanent + ~id:"seed.unknown_seed" + ~title:"Unknown seed" + ~description:"The requested seed is not available" + ~pp:(fun ppf (oldest, cycle, latest) -> + if Cycle_repr.(cycle < oldest) then + Format.fprintf + ppf + "The seed for cycle %a has been cleared from the context (oldest \ + known seed is for cycle %a)" + Cycle_repr.pp + cycle + Cycle_repr.pp + oldest + else + Format.fprintf + ppf + "The seed for cycle %a has not been computed yet (latest known seed \ + is for cycle %a)" + Cycle_repr.pp + cycle + Cycle_repr.pp + latest) + Data_encoding.( + obj3 + (req "oldest" Cycle_repr.encoding) + (req "requested" Cycle_repr.encoding) + (req "latest" Cycle_repr.encoding)) + (function + | Unknown {oldest; cycle; latest} -> Some (oldest, cycle, latest) + | _ -> None) + (fun (oldest, cycle, latest) -> Unknown {oldest; cycle; latest}) ; + register_error_kind + `Temporary + ~id:"vdf.too_early_revelation" + ~title:"Too early VDF revelation" + ~description:"VDF revelation before the end of the nonce revelation period" + Data_encoding.unit + (function Too_early_revelation -> Some () | _ -> None) + (fun () -> Too_early_revelation) ; + register_error_kind + `Branch + ~id:"vdf.unverified_result" + ~title:"Unverified VDF" + ~description:"VDF verification failed" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "A correct VDF result and Wesolowski's proof are expected") + Data_encoding.unit + (function Unverified_vdf -> Some () | _ -> None) + (fun () -> Unverified_vdf) ; + register_error_kind + `Branch + ~id:"vdf.previously_revealed" + ~title:"Previously revealed VDF" + ~description:"Duplicate VDF revelation in cycle" + Data_encoding.unit + (function Already_accepted -> Some () | _ -> None) + (fun () -> Already_accepted) + +let purge_nonces_and_get_unrevealed ctxt ~cycle = + let open Lwt_result_syntax in + let levels = Level_storage.levels_with_commitments_in_cycle ctxt cycle in + let combine (c, unrevealed) level = + let* seed = Storage.Seed.Nonce.get c level in + match seed with + | Revealed _ -> + let+ c = Storage.Seed.Nonce.remove_existing c level in + (c, unrevealed) + | Unrevealed u -> + let+ c = Storage.Seed.Nonce.remove_existing c level in + (c, u :: unrevealed) + in + List.fold_left_es combine (ctxt, []) levels + +let compute_randao ctxt = + let open Lwt_result_syntax in + let current_cycle = (Level_storage.current ctxt).cycle in + let delay = Constants_storage.consensus_rights_delay ctxt in + let cycle_computed = Cycle_repr.add current_cycle (delay + 1) in + let*! seed_computed = Storage.Seed.For_cycle.mem ctxt cycle_computed in + (* Check if seed has already been computed, and not in cycle 0. *) + match Cycle_repr.(pred current_cycle, pred cycle_computed) with + | Some prev_cycle, Some prev_cycle_computed when not seed_computed -> + (* Retrieve the levels with nonce commitments in the previous cycle. *) + let levels = + Level_storage.levels_with_commitments_in_cycle ctxt prev_cycle + in + (* Retrieve previous preserved seed. *) + let* prev_seed = Storage.Seed.For_cycle.get ctxt prev_cycle_computed in + (* Generate preserved seed by updating previous preserved seed with current revealed nonces. *) + let combine (c, random_seed) level = + let* seed = Storage.Seed.Nonce.get c level in + match seed with + | Revealed nonce -> return (c, Seed_repr.update_seed random_seed nonce) + | Unrevealed _ -> return (c, random_seed) + in + let seed = Seed_repr.deterministic_seed prev_seed in + let* c, seed = List.fold_left_es combine (ctxt, seed) levels in + Storage.Seed.For_cycle.init c cycle_computed seed + | _, _ -> return ctxt + +let get_seed_computation_status ctxt = + let open Lwt_result_syntax in + let current_level = Level_storage.current ctxt in + let current_cycle = current_level.cycle in + let nonce_revelation_threshold = + Constants_storage.nonce_revelation_threshold ctxt + in + if Compare.Int32.(current_level.cycle_position < nonce_revelation_threshold) + then return Nonce_revelation_stage + else + let* status = Storage.Seed.get_status ctxt in + match status with + | RANDAO_seed -> + let delay = Constants_storage.consensus_rights_delay ctxt in + let cycle_computed = Cycle_repr.add current_cycle (delay + 1) in + let previous_cycle = Cycle_repr.add current_cycle delay in + let* seed_discriminant = + Storage.Seed.For_cycle.get ctxt previous_cycle + in + let* seed_challenge = Storage.Seed.For_cycle.get ctxt cycle_computed in + return (Vdf_revelation_stage {seed_discriminant; seed_challenge}) + | VDF_seed -> return Computation_finished + +let check_vdf ctxt vdf_solution = + let open Lwt_result_syntax in + let* r = get_seed_computation_status ctxt in + match r with + | Computation_finished -> tzfail Already_accepted + | Nonce_revelation_stage -> tzfail Too_early_revelation + | Vdf_revelation_stage {seed_discriminant; seed_challenge} -> + (* To avoid recomputing the discriminant and challenge for every (potentially + * invalid) submission in a cycle, we compute them once and store them *) + let* stored = Storage.Seed.VDF_setup.find ctxt in + let* ctxt, setup = + match stored with + | None -> + let setup = + Seed_repr.generate_vdf_setup ~seed_discriminant ~seed_challenge + in + let*! ctxt = Storage.Seed.VDF_setup.add ctxt setup in + return (ctxt, setup) + | Some setup -> return (ctxt, setup) + in + let*? () = + error_unless + (Option.value + ~default:false + (Seed_repr.verify + setup + (Constants_storage.vdf_difficulty ctxt) + vdf_solution)) + Unverified_vdf + in + return_unit + +let update_seed ctxt vdf_solution = + let open Lwt_result_syntax in + (* compute and update seed and change seed status from RANDAO to + VDF *) + let current_cycle = (Level_storage.current ctxt).cycle in + let delay = Constants_storage.consensus_rights_delay ctxt in + let cycle_computed = Cycle_repr.add current_cycle (delay + 1) in + let* seed_challenge = Storage.Seed.For_cycle.get ctxt cycle_computed in + let new_seed = Seed_repr.vdf_to_seed seed_challenge vdf_solution in + Storage.Seed.For_cycle.update ctxt cycle_computed new_seed Seed_repr.VDF_seed + +let raw_for_cycle = Storage.Seed.For_cycle.get + +let for_cycle ctxt cycle = + let open Lwt_result_syntax in + let delay = Constants_storage.consensus_rights_delay ctxt in + let max_slashing_period = Constants_repr.max_slashing_period in + let current_cycle = (Level_storage.current ctxt).cycle in + let latest = + if Cycle_repr.(current_cycle = root) then + Cycle_repr.add current_cycle (delay + 1) + else Cycle_repr.add current_cycle delay + in + let oldest = + match Cycle_repr.sub current_cycle (max_slashing_period - 1) with + | None -> Cycle_repr.root + | Some oldest -> oldest + in + let*? () = + error_unless + Cycle_repr.(oldest <= cycle && cycle <= latest) + (Unknown {oldest; cycle; latest}) + in + Storage.Seed.For_cycle.get ctxt cycle + +let init ?initial_seed ctxt = + let open Lwt_result_syntax in + let delay = Constants_storage.consensus_rights_delay ctxt in + let* ctxt = Storage.Seed_status.init ctxt Seed_repr.RANDAO_seed in + let+ (_ : int), ctxt = + List.fold_left_es + (fun (c, ctxt) seed -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in + let+ ctxt = Storage.Seed.For_cycle.init ctxt cycle seed in + (c + 1, ctxt)) + (0, ctxt) + (Seed_repr.initial_seeds ?initial_seed (delay + 2)) + in + ctxt + +let cycle_end ctxt last_cycle = + let open Lwt_result_syntax in + let*! ctxt = Storage.Seed.VDF_setup.remove ctxt in + (* NB: the clearing of past seeds is done elsewhere by the caller *) + match Cycle_repr.pred last_cycle with + | None -> return (ctxt, []) + | Some previous_cycle -> + (* cycle with revelations *) + purge_nonces_and_get_unrevealed ctxt ~cycle:previous_cycle + +let remove_for_cycle = Storage.Seed.For_cycle.remove_existing diff --git a/src/proto_020_PsParisC/lib_protocol/seed_storage.mli b/src/proto_020_PsParisC/lib_protocol/seed_storage.mli new file mode 100644 index 000000000000..f99b047eb9e9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/seed_storage.mli @@ -0,0 +1,100 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This modules handles the storage of random nonce seeds. + + This module is responsible for maintaining the table + {!Storage.Seed.For_cycle}. *) + +type seed_computation_status = + | Nonce_revelation_stage + | Vdf_revelation_stage of { + seed_discriminant : Seed_repr.seed; + seed_challenge : Seed_repr.seed; + } + | Computation_finished + +type error += + | (* `Permanent *) + Unknown of { + oldest : Cycle_repr.t; + cycle : Cycle_repr.t; + latest : Cycle_repr.t; + } + | Already_accepted + | Unverified_vdf + | Too_early_revelation + +(** Generates the first [consensus_rights_delay+2] seeds for which + there are no nonces. *) +val init : + ?initial_seed:State_hash.t -> Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Verifies if a VDF (result, proof) is valid. + + @return [Error Too_early_revelation] if the nonce revelation + threshold is greater than the current level cycle position. + + @return [Error Already_accepted] if a VDF seed has already been + recorded. + + @return [Error Unverified_vdf] if the {!Seed_repr.vdf_solution} is + not verified. *) +val check_vdf : Raw_context.t -> Seed_repr.vdf_solution -> unit tzresult Lwt.t + +(** Updates the seed with a function of the VDF result. *) +val update_seed : + Raw_context.t -> Seed_repr.vdf_solution -> Raw_context.t tzresult Lwt.t + +(** Returns the seed associated with the given cycle. Returns a generic storage + error when the seed is not available. *) +val raw_for_cycle : + Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + +(** Returns the seed associated with the given cycle. Returns the {!Unknown} + error when the seed is not available. *) +val for_cycle : Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + +(** Computes RANDAO output for cycle #(current_cycle + preserved + 1) *) +val compute_randao : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Must be run at the end of the cycle, resets the VDF state and returns + unrevealed nonces to know which party has to forfeit its attesting + rewards for that cycle. *) +val cycle_end : + Raw_context.t -> + Cycle_repr.t -> + (Raw_context.t * Nonce_storage.unrevealed list) tzresult Lwt.t + +(** Return the random seed computation status, that is whether the VDF + computation period has started, and if so the information needed, or if it has + finished for the current cycle. *) +val get_seed_computation_status : + Raw_context.t -> seed_computation_status tzresult Lwt.t + +(** Removes the seed associated with the given cycle from the storage. It + assumes the seed exists. If it does not it returns a generic storage error. *) +val remove_for_cycle : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/services_registration.ml b/src/proto_020_PsParisC/lib_protocol/services_registration.ml new file mode 100644 index 000000000000..d17f65d6df52 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/services_registration.ml @@ -0,0 +1,143 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type rpc_context = { + block_hash : Block_hash.t; + block_header : Block_header.shell_header; + context : Alpha_context.t; +} + +let rpc_init ({block_hash; block_header; context} : Updater.rpc_context) mode = + let open Lwt_result_syntax in + let timestamp = block_header.timestamp in + let level = + match mode with + | `Head_level -> block_header.level + | `Successor_level -> Int32.succ block_header.level + in + let+ context, _, _ = + Alpha_context.prepare + ~level + ~predecessor_timestamp:timestamp + ~timestamp + context + in + {block_hash; block_header; context} + +let rpc_services = + ref (RPC_directory.empty : Updater.rpc_context RPC_directory.t) + +let register0_fullctxt ~chunked s f = + let open Lwt_result_syntax in + rpc_services := + RPC_directory.register ~chunked !rpc_services s (fun ctxt q i -> + let* ctxt = rpc_init ctxt `Head_level in + f ctxt q i) + +let register0 ~chunked s f = + register0_fullctxt ~chunked s (fun {context; _} -> f context) + +let register0_noctxt ~chunked s f = + rpc_services := + RPC_directory.register ~chunked !rpc_services s (fun _ q i -> f q i) + +let register1_fullctxt ~chunked s f = + let open Lwt_result_syntax in + rpc_services := + RPC_directory.register ~chunked !rpc_services s (fun (ctxt, arg) q i -> + let* ctxt = rpc_init ctxt `Head_level in + f ctxt arg q i) + +let register1 ~chunked s f = + register1_fullctxt ~chunked s (fun {context; _} x -> f context x) + +let register2_fullctxt ~chunked s f = + let open Lwt_result_syntax in + rpc_services := + RPC_directory.register + ~chunked + !rpc_services + s + (fun ((ctxt, arg1), arg2) q i -> + let* ctxt = rpc_init ctxt `Head_level in + f ctxt arg1 arg2 q i) + +let register2 ~chunked s f = + register2_fullctxt ~chunked s (fun {context; _} a1 a2 q i -> + f context a1 a2 q i) + +let opt_register0_fullctxt ~chunked s f = + let open Lwt_result_syntax in + rpc_services := + RPC_directory.opt_register ~chunked !rpc_services s (fun ctxt q i -> + let* ctxt = rpc_init ctxt `Head_level in + f ctxt q i) + +let opt_register0 ~chunked s f = + opt_register0_fullctxt ~chunked s (fun {context; _} -> f context) + +let opt_register1_fullctxt ~chunked s f = + let open Lwt_result_syntax in + rpc_services := + RPC_directory.opt_register ~chunked !rpc_services s (fun (ctxt, arg) q i -> + let* ctxt = rpc_init ctxt `Head_level in + f ctxt arg q i) + +let opt_register1 ~chunked s f = + opt_register1_fullctxt ~chunked s (fun {context; _} x -> f context x) + +let opt_register2_fullctxt ~chunked s f = + let open Lwt_result_syntax in + rpc_services := + RPC_directory.opt_register + ~chunked + !rpc_services + s + (fun ((ctxt, arg1), arg2) q i -> + let* ctxt = rpc_init ctxt `Head_level in + f ctxt arg1 arg2 q i) + +let opt_register2 ~chunked s f = + opt_register2_fullctxt ~chunked s (fun {context; _} a1 a2 q i -> + f context a1 a2 q i) + +let get_rpc_services () = + let open Lwt_syntax in + let p = + RPC_directory.map + (fun c -> + let+ ctxt = rpc_init c `Head_level in + match ctxt with + | Error t -> + raise (Failure (Format.asprintf "%a" Error_monad.pp_trace t)) + | Ok c -> c.context) + (Storage_description.build_directory Alpha_context.description) + in + RPC_directory.register_dynamic_directory + !rpc_services + RPC_path.(open_root / "context" / "raw" / "json") + (fun _ -> Lwt.return p) diff --git a/src/proto_020_PsParisC/lib_protocol/services_registration.mli b/src/proto_020_PsParisC/lib_protocol/services_registration.mli new file mode 100644 index 000000000000..c6bc2ed72c92 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/services_registration.mli @@ -0,0 +1,145 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Functions for RPC service registration, using [Updater.rpc_context] and + [RPC_service.t] from the Protocol Environment. + + This module is a frontend to a mutable service directory. The various + [register] functions update the directory as a side-effect. + + The [get_rpc_services] function returns the resulting [RPC_context]. It is + parameterized by [Updater.rpc_context] which acts as the service prefix (in + practice meaning this type will be passed to each handler). Hence, + Protocol RPC services provide a {i read-only} view of the Ledger state. + *) + +open Alpha_context + +type rpc_context = { + block_hash : Block_hash.t; + block_header : Block_header.shell_header; + context : t; +} + +(** [rpc_init rpc_context mode] allows to instantiate an [rpc_context] + using the [Alpha_context] representation from a raw context + representation (the one the shell knows). + + If [mode = `Head_level], the [Alpha_context] uses the same level + as the head of the chain (given by [rpc_context.block_header]). + + If [mode= `Successor_level], the [Alpha_context] uses the + successor level of the head. + + This function aims to be used by RPCs, in particular by RPCs which + simulate an operation to determine the fees/gas of an + operation. Using the [`Head_level] can be dangerous if some storage + paths depend on the level. Using the successor level allows to + ensure that the simulation is done on a fresh level. *) +val rpc_init : + Updater.rpc_context -> + [`Head_level | `Successor_level] -> + rpc_context Error_monad.tzresult Lwt.t + +val register0 : + chunked:bool -> + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context, + 'a, + 'b, + 'c ) + RPC_service.t -> + (t -> 'a -> 'b -> 'c Error_monad.tzresult Lwt.t) -> + unit + +val register0_noctxt : + chunked:bool -> + ([< RPC_service.meth], Updater.rpc_context, 'a, 'b, 'c, 'd) RPC_service.t -> + ('b -> 'c -> 'd Error_monad.tzresult Lwt.t) -> + unit + +val register1 : + chunked:bool -> + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context * 'a, + 'b, + 'c, + 'd ) + RPC_service.t -> + (t -> 'a -> 'b -> 'c -> 'd Error_monad.tzresult Lwt.t) -> + unit + +val register2 : + chunked:bool -> + ( [< RPC_service.meth], + Updater.rpc_context, + (Updater.rpc_context * 'a) * 'b, + 'c, + 'd, + 'e ) + RPC_service.t -> + (t -> 'a -> 'b -> 'c -> 'd -> 'e Error_monad.tzresult Lwt.t) -> + unit + +val opt_register0 : + chunked:bool -> + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context, + 'a, + 'b, + 'c ) + RPC_service.t -> + (t -> 'a -> 'b -> 'c option Error_monad.tzresult Lwt.t) -> + unit + +val opt_register1 : + chunked:bool -> + ( [< RPC_service.meth], + Updater.rpc_context, + Updater.rpc_context * 'a, + 'b, + 'c, + 'd ) + RPC_service.t -> + (t -> 'a -> 'b -> 'c -> 'd option Error_monad.tzresult Lwt.t) -> + unit + +val opt_register2 : + chunked:bool -> + ( [< RPC_service.meth], + Updater.rpc_context, + (Updater.rpc_context * 'a) * 'b, + 'c, + 'd, + 'e ) + RPC_service.t -> + (t -> 'a -> 'b -> 'c -> 'd -> 'e option Error_monad.tzresult Lwt.t) -> + unit + +val get_rpc_services : unit -> Updater.rpc_context RPC_directory.directory diff --git a/src/proto_020_PsParisC/lib_protocol/shared_stake.ml b/src/proto_020_PsParisC/lib_protocol/shared_stake.ml new file mode 100644 index 000000000000..ed755b479086 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/shared_stake.ml @@ -0,0 +1,198 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type shared = {baker_part : Tez_repr.t; stakers_part : Tez_repr.t} + +let share ~adaptive_issuance_global_limit_of_staking_over_baking + (delegate_parameters : Staking_parameters_repr.t) ~rounding + ~full_staking_balance amount = + let open Result_syntax in + let num, den = + Full_staking_balance_repr.own_ratio + ~adaptive_issuance_global_limit_of_staking_over_baking + ~delegate_limit_of_staking_over_baking_millionth: + delegate_parameters.limit_of_staking_over_baking_millionth + full_staking_balance + in + let* baker_part = + let rounding = + match rounding with `Towards_stakers -> `Down | `Towards_baker -> `Up + in + Tez_repr.mul_ratio ~rounding amount ~num ~den + in + let* stakers_part = Tez_repr.(amount -? baker_part) in + return {baker_part; stakers_part} + +type reward_distrib = { + to_baker_from_staking : Tez_repr.t; + to_baker_from_edge_over_stakers : Tez_repr.t; + to_stakers : Tez_repr.t; + to_spendable : Tez_repr.t; +} + +(** Compute the reward distribution between frozen and spendable according to: + - the [full_staking_balance] of the delegate composed of the [own_frozen] + and [staked_frozen] parts (the delegated part is ignored). + - the [stake] of the delegate composed of the [frozen] deposits and the + [weighted_delegated] tokens. + - the [edge_of_baking_over_staking_billionth] parameter set by the baker in 1_000_000_000th + - the [rewards] to be distributed + +Preconditions: + - 0 <= [edge_of_baking_over_staking_billionth] <= 1_000_000_000 + +Rounding favors: + - staking over delegation + - baking over staking + +In case the delegate's stake is zero, everything goes to the spendable balance. +*) +let compute_reward_distrib + ~adaptive_issuance_global_limit_of_staking_over_baking delegate_parameters + ~full_staking_balance ~stake ~(rewards : Tez_repr.t) = + let open Result_syntax in + let ({frozen; weighted_delegated} : Stake_repr.t) = stake in + let* total_stake = Tez_repr.(frozen +? weighted_delegated) in + if Tez_repr.(total_stake <= zero) then + return + { + to_spendable = rewards; + to_baker_from_staking = Tez_repr.zero; + to_baker_from_edge_over_stakers = Tez_repr.zero; + to_stakers = Tez_repr.zero; + } + else + let* to_spendable = + Tez_repr.mul_ratio + ~rounding:`Down + rewards + ~num:(Tez_repr.to_mutez weighted_delegated) + ~den:(Tez_repr.to_mutez total_stake) + in + let* to_frozen = Tez_repr.(rewards -? to_spendable) in + let* {baker_part; stakers_part} = + share + ~adaptive_issuance_global_limit_of_staking_over_baking + delegate_parameters + ~rounding:`Towards_baker + ~full_staking_balance + to_frozen + in + let to_baker_from_staking = baker_part in + let* to_baker_from_edge_over_stakers = + Tez_repr.mul_ratio + ~rounding:`Up + stakers_part + ~num: + (Int64.of_int32 + delegate_parameters.edge_of_baking_over_staking_billionth) + ~den:1_000_000_000L + in + let* to_stakers = + Tez_repr.(stakers_part -? to_baker_from_edge_over_stakers) + in + return + { + to_baker_from_staking; + to_baker_from_edge_over_stakers; + to_stakers; + to_spendable; + } + +let share ~rounding ctxt delegate amount = + let open Lwt_result_syntax in + let* delegate_parameters = + Delegate_staking_parameters.of_delegate ctxt delegate + in + let* full_staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + Lwt.return + (share + ~adaptive_issuance_global_limit_of_staking_over_baking: + (Constants_storage + .adaptive_issuance_global_limit_of_staking_over_baking + ctxt) + delegate_parameters + ~rounding + ~full_staking_balance + amount) + +let compute_reward_distrib ctxt delegate stake rewards = + let open Lwt_result_syntax in + let* (delegate_parameters : Staking_parameters_repr.t) = + Delegate_staking_parameters.of_delegate ctxt delegate + in + let* full_staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + Lwt.return + @@ compute_reward_distrib + ~adaptive_issuance_global_limit_of_staking_over_baking: + (Constants_storage + .adaptive_issuance_global_limit_of_staking_over_baking + ctxt) + delegate_parameters + ~full_staking_balance + ~stake + ~rewards + +let pay_rewards ctxt ?active_stake ~source ~delegate rewards = + let open Lwt_result_syntax in + let* active_stake = + match active_stake with + | Some active_stake -> return active_stake + | None -> + let*? stake_distrib = + Raw_context.stake_distribution_for_current_cycle ctxt + in + return + (Option.value + (Signature.Public_key_hash.Map.find delegate stake_distrib) + ~default:Stake_repr.zero) + in + let* { + to_baker_from_staking; + to_baker_from_edge_over_stakers; + to_stakers; + to_spendable; + } = + compute_reward_distrib ctxt delegate active_stake rewards + in + let* ctxt, balance_updates_frozen_rewards_baker = + Token.transfer + ctxt + source + (`Frozen_deposits (Frozen_staker_repr.baker delegate)) + to_baker_from_staking + in + let* ctxt, balance_updates_frozen_rewards_baker_edge = + Token.transfer + ctxt + source + (`Frozen_deposits (Frozen_staker_repr.baker_edge delegate)) + to_baker_from_edge_over_stakers + in + let* ctxt, balance_updates_frozen_rewards_stakers = + Token.transfer + ctxt + source + (`Frozen_deposits (Frozen_staker_repr.shared_between_stakers ~delegate)) + to_stakers + in + let+ ctxt, balance_updates_spendable_rewards = + Token.transfer + ctxt + source + (`Contract (Contract_repr.Implicit delegate)) + to_spendable + in + ( ctxt, + balance_updates_frozen_rewards_baker + @ balance_updates_frozen_rewards_baker_edge + @ balance_updates_frozen_rewards_stakers @ balance_updates_spendable_rewards + ) diff --git a/src/proto_020_PsParisC/lib_protocol/shared_stake.mli b/src/proto_020_PsParisC/lib_protocol/shared_stake.mli new file mode 100644 index 000000000000..2902c80bd1f0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/shared_stake.mli @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type shared = {baker_part : Tez_repr.t; stakers_part : Tez_repr.t} + +(** [share ~rounding ctxt delegate amount] shares [amount] between a [baker_part] and a + [stakers_part] proportionally to their shares in [delegate]'s frozen + deposits. + [rounding] controls where the extra mutez goes in case the split doesn't + fall on integer values. *) +val share : + rounding:[`Towards_stakers | `Towards_baker] -> + Raw_context.t -> + Signature.public_key_hash -> + Tez_repr.t -> + shared tzresult Lwt.t + +(** [pay_rewards ctxt ?active_stake source delegate] transfers the rewards to the + [delegate] spendable balance and frozen balance. + + The distribution is based on the baker's staking parameters. + + If adaptive issuance is enabled, it also accounts for the repartition of the + delegate's [active_stake] between delegated token and frozen deposits. + If [active_stake] is not provided, it will be retrieved from the context. +*) +val pay_rewards : + Raw_context.t -> + ?active_stake:Stake_repr.t -> + source:[< Token.giver] -> + delegate:Signature.public_key_hash -> + Tez_repr.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/skip_list_costs.ml b/src/proto_020_PsParisC/lib_protocol/skip_list_costs.ml new file mode 100644 index 000000000000..9c3295539041 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/skip_list_costs.ml @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Skip_list_costs_generated + +let model_next ~length = cost_next (S.safe_z length) + +let model_hash_cell ~backpointers_count = + cost_hash_cell (S.safe_int backpointers_count) + +let model_hash_cell_computed_backpointers_count ~index = + cost_hash_cell (S.Syntax.log2 (S.safe_z index)) diff --git a/src/proto_020_PsParisC/lib_protocol/skip_list_costs.mli b/src/proto_020_PsParisC/lib_protocol/skip_list_costs.mli new file mode 100644 index 000000000000..65e868bb0e73 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/skip_list_costs.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [model_next ~length] returns the gas cost of inserting a cell in a + skip list of a given [length], assuming basis equals 2. *) +val model_next : length:Z.t -> Saturation_repr.may_saturate Saturation_repr.t + +(** [model_hash_cell ~backpointers_count] returns the gas cost of + hashing the last cell with a given [backpointers_count], assuming + basis equals 2. *) +val model_hash_cell : + backpointers_count:int -> Saturation_repr.may_saturate Saturation_repr.t + +(** [model_hash_cell_computed_backpointers_count ~index] same as + {!model_hash_cell} but compute the number of backpointers a specific cell + will have. Assuming basis equals 2. *) +val model_hash_cell_computed_backpointers_count : + index:Z.t -> Saturation_repr.may_saturate Saturation_repr.t diff --git a/src/proto_020_PsParisC/lib_protocol/skip_list_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/skip_list_costs_generated.ml new file mode 100644 index 000000000000..25f996e18a2f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/skip_list_costs_generated.ml @@ -0,0 +1,20 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model skip_list/hash_cell *) +(* fun size -> max 10 (250. + (57. * size)) *) +let cost_hash_cell size = (size * S.safe_int 57) + S.safe_int 250 + +(* model skip_list/next *) +(* fun size -> max 10 (19.2125537461 * (log2 (1 + size))) *) +let cost_next size = + let w1 = log2 (size + S.safe_int 1) in + S.max (S.safe_int 10) ((w1 * S.safe_int 19) + (w1 lsr 1)) diff --git a/src/proto_020_PsParisC/lib_protocol/slash_percentage.ml b/src/proto_020_PsParisC/lib_protocol/slash_percentage.ml new file mode 100644 index 000000000000..83e31903dab7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/slash_percentage.ml @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +let for_double_baking ctxt = + Constants_storage.percentage_of_frozen_deposits_slashed_per_double_baking ctxt + +let for_double_attestation ctxt rights denounced = + if + not + (Constants_storage.adaptive_issuance_ns_enable ctxt + && Constants_storage.adaptive_issuance_enable ctxt) + then + Constants_storage + .percentage_of_frozen_deposits_slashed_per_double_attestation + ctxt + else + let total_rights_denounced = + List.fold_left + (fun total delegate -> + Option.value + (Signature.Public_key_hash.Map.find delegate rights) + ~default:0 + |> ( + ) total) + 0 + denounced + in + let threshold_max = (Raw_context.constants ctxt).max_slashing_threshold in + let max_slashing = (Raw_context.constants ctxt).max_slashing_per_block in + if Compare.Int.(total_rights_denounced >= threshold_max) then max_slashing + else + let num_z = Z.(pow (of_int total_rights_denounced) 2) in + let den_z = Z.(pow (of_int threshold_max) 2) in + Percentage.mul_q_bounded ~round:`Up max_slashing Q.(num_z /// den_z) + +let get ctxt ~(kind : Misbehaviour_repr.kind) ~(level : Level_repr.t) + (denounced : Signature.public_key_hash list) = + let open Lwt_result_syntax in + match kind with + | Double_baking -> return (ctxt, for_double_baking ctxt) + | Double_attesting | Double_preattesting -> + let* ctxt, rights = Delegate_sampler.attesting_rights_count ctxt level in + return (ctxt, for_double_attestation ctxt rights denounced) + +module Internal_for_tests = struct + let for_double_attestation = for_double_attestation +end diff --git a/src/proto_020_PsParisC/lib_protocol/slash_percentage.mli b/src/proto_020_PsParisC/lib_protocol/slash_percentage.mli new file mode 100644 index 000000000000..3a557576f44c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/slash_percentage.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** [get ctxt ~kind ~level denounced] returns the percentage that needs to be + applied for the given misbehaviour. + + [denounced] is the list of delegates that have been denounced together for + the given [kind], for the given [level] and for the same round. The amount + slashed increases quadratically as the number of attesting slots of + denounced delegates increases. The maximum slashing value + [max_slashing_per_block] is reached when that number of slots reaches + [max_slashing_threshold] . *) +val get : + Raw_context.t -> + kind:Misbehaviour_repr.kind -> + level:Level_repr.t -> + Signature.public_key_hash list -> + (Raw_context.t * Percentage.t) tzresult Lwt.t + +module Internal_for_tests : sig + val for_double_attestation : + Raw_context.t -> + int Signature.Public_key_hash.Map.t -> + Signature.Public_key_hash.t list -> + Percentage.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/slot_repr.ml b/src/proto_020_PsParisC/lib_protocol/slot_repr.ml new file mode 100644 index 000000000000..a8e9193120a6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/slot_repr.ml @@ -0,0 +1,121 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Invalid_slot of int + +let () = + register_error_kind + `Permanent + ~id:"slot.invalid_slot" + ~title:"invalid slot" + ~description:"Invalid slot" + ~pp:(fun ppf x -> Format.fprintf ppf "invalid slot: %d" x) + Data_encoding.(obj1 (req "bad_slot" int31)) + (function Invalid_slot x -> Some x | _ -> None) + (fun x -> Invalid_slot x) + +include Compare.Int + +type slot = t + +(* TODO? should there be some assertions to verify that slots are + never too big ? Or do that in a storage module that depends on + constants ? *) + +let encoding = Data_encoding.uint16 + +let pp = Format.pp_print_int + +let zero = 0 + +let to_int x = x + +(* We assume 2^16 slots is big enough. + + We could increase that, but we would need to make sure there is no big + performance penalty first. *) +let max_value = (1 lsl 16) - 1 + +let of_int_do_not_use_except_for_parameters i = i + +let of_int i = + let open Result_syntax in + if Compare.Int.(i < 0 || i > max_value) then tzfail (Invalid_slot i) + else return i + +let succ slot = of_int (slot + 1) + +module Map = Map.Make (Compare.Int) +module Set = Set.Make (Compare.Int) + +module Range = struct + (* For now, we only need full intervals. If we ever need sparse ones, we + could switch this representation to interval trees. [hi] and [lo] bounds + are included. *) + type t = Interval of {lo : int; hi : int} + + let create ~min ~count = + let open Result_syntax in + let* () = error_when (min < 0) (Invalid_slot min) in + let* () = error_when (min > max_value) (Invalid_slot min) in + let* () = error_when (count < 1) (Invalid_slot count) in + let* () = error_when (count > max_value) (Invalid_slot count) in + let max = min + count - 1 in + let* () = error_when (max > max_value) (Invalid_slot max) in + return (Interval {lo = min; hi = max}) + + let fold f init (Interval {lo; hi}) = + let rec loop ~acc ~next = + if Compare.Int.(next > hi) then acc + else loop ~acc:(f acc next) ~next:(next + 1) + in + loop ~acc:(f init lo) ~next:(lo + 1) + + let fold_es f init (Interval {lo; hi}) = + let open Lwt_result_syntax in + let rec loop ~acc ~next = + if Compare.Int.(next > hi) then return acc + else + let* acc = f acc next in + loop ~acc ~next:(next + 1) + in + let* acc = f init lo in + loop ~acc ~next:(lo + 1) + + let rev_fold_es f init (Interval {lo; hi}) = + let open Lwt_result_syntax in + let rec loop ~acc ~next = + if Compare.Int.(next < lo) then return acc + else + let* acc = f acc next in + loop ~acc ~next:(next - 1) + in + let* acc = f init hi in + loop ~acc ~next:(hi - 1) +end + +module Internal_for_tests = struct + let of_int = of_int +end diff --git a/src/proto_020_PsParisC/lib_protocol/slot_repr.mli b/src/proto_020_PsParisC/lib_protocol/slot_repr.mli new file mode 100644 index 000000000000..27b574b4f2ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/slot_repr.mli @@ -0,0 +1,121 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Slot index representation *) + +(** {1 Abstract type} *) + +(** A slot index is in essence a bounded whole number. That is, it is not + allowed to overflow [max_value], nor does it wrap when calling [succ + max_value]. In this case it returns an [Invalid_slot] error.*) +type t + +type slot = t + +val encoding : t Data_encoding.t + +(** {1 Constructors }*) + +val zero : t + +(** Upper bound on the value a slot index can take *) +val max_value : t + +(** [of_int i] creates a slot index from integer [i]. + + @return [Error (Invalid_slot i)] if [i < 0 || i > max_value], and + [Ok slot] otherwise + *) +val of_int : int -> t tzresult + +(** [of_int_do_not_use_except_for_parameters i] is an unchecked construction + function. + + It may be used in cases where one knows [0 <= i <= max_value], e.g., when + creating protocol parameters. + + When in doubt, use [of_int] or [of_int_exn]. + *) +val of_int_do_not_use_except_for_parameters : int -> t + +(** {1 Operator and pretty-printer} *) + +(** [succ n] either returns an [Invalid_slot] error if [n] is [max_value] or [ok + value] otherwise. *) +val succ : t -> t tzresult + +(** {1 Conversion/Printing} *) + +(** [to_int slot] returns the integral representation of a slot index. This + value is always a whole number. *) +val to_int : t -> int + +val pp : Format.formatter -> t -> unit + +(** {1 Submodules} *) + +module Map : Map.S with type key = t + +module Set : Set.S with type elt = t + +include Compare.S with type t := t + +(** {2 Slot ranges} *) +module Range : sig + (** An ordered range of slots, in increasing order. *) + type t + + (** {3 Constructor} *) + + (** [create ~min ~count] creates a full slot range starting at [min], of size + [count], i.e, [min, min + count - 1]. + + [create] errors if + - [min < 0] + - [count < 1] + - [min + count - 1 > max_value] + *) + val create : min:int -> count:int -> t tzresult + + (** {3 Iterators} *) + + (** [fold f acc range] folds [f] over the values of [range], in increasing + order. *) + val fold : ('a -> slot -> 'a) -> 'a -> t -> 'a + + (** [fold_es f acc range] folds [f] over the values of [range], in increasing + order. *) + val fold_es : + ('a -> slot -> 'a tzresult Lwt.t) -> 'a -> t -> 'a tzresult Lwt.t + + (** [rev_fold_es f acc range] folds [f] over the values of [range], in decreasing + order. *) + val rev_fold_es : + ('a -> slot -> 'a tzresult Lwt.t) -> 'a -> t -> 'a tzresult Lwt.t +end + +module Internal_for_tests : sig + val of_int : int -> t tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/stake_context.ml b/src/proto_020_PsParisC/lib_protocol/stake_context.ml new file mode 100644 index 000000000000..cdc8c4eef3ae --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/stake_context.ml @@ -0,0 +1,104 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let apply_limits ctxt staking_parameters staking_balance = + let open Result_syntax in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let own_frozen = Full_staking_balance_repr.own_frozen staking_balance in + let staked_frozen = Full_staking_balance_repr.staked_frozen staking_balance in + let allowed_staked_frozen = + Full_staking_balance_repr.allowed_staked_frozen + ~adaptive_issuance_global_limit_of_staking_over_baking: + (Constants_storage.adaptive_issuance_global_limit_of_staking_over_baking + ctxt) + ~delegate_limit_of_staking_over_baking_millionth: + staking_parameters + .Staking_parameters_repr.limit_of_staking_over_baking_millionth + staking_balance + in + let delegated = + Full_staking_balance_repr.min_delegated_in_cycle + ~current_cycle + staking_balance + in + let limit_of_delegation_over_baking = + Int64.of_int (Constants_storage.limit_of_delegation_over_baking ctxt) + in + (* Overstaked tez count as delegated. + Note that, unlike delegated tez, overstaked tez may not have been staked + the whole cycle to contribute to rights, but they are going to be frozen + for several cycles. *) + let* overstaked = Tez_repr.(staked_frozen -? allowed_staked_frozen) in + let* delegated = Tez_repr.(delegated +? overstaked) in + (* Overdelegated tez don't count. *) + let delegated = + match Tez_repr.(own_frozen *? limit_of_delegation_over_baking) with + | Ok max_allowed_delegated -> Tez_repr.min max_allowed_delegated delegated + | Error _max_allowed_delegated_overflows -> delegated + in + let* weighted_delegated = + if Constants_storage.adaptive_issuance_enable ctxt then + let edge_of_staking_over_delegation = + Int64.of_int + (Constants_storage.adaptive_issuance_edge_of_staking_over_delegation + ctxt) + in + Tez_repr.(delegated /? edge_of_staking_over_delegation) + else return delegated + in + let+ frozen = Tez_repr.(own_frozen +? allowed_staked_frozen) in + Stake_repr.make ~frozen ~weighted_delegated + +let optimal_frozen_wrt_delegated_without_ai ctxt full_staking_balance = + let open Result_syntax in + let limit_of_delegation_over_baking = + Int64.of_int (Constants_storage.limit_of_delegation_over_baking ctxt) + in + (* Without AI, frozen deposit is optimal when `delegated = + limit_of_delegation_over_baking * frozen`. Freezing more would + unnecessarily freeze tokens, freezing less would under exploit delegated + rights due to over-delegation limit. + + With AI the optimum is to freeze as much as possible, this computation + would make no sense. *) + let delegated = + Full_staking_balance_repr.current_delegated full_staking_balance + in + let own_frozen = Full_staking_balance_repr.own_frozen full_staking_balance in + let* power = Tez_repr.(delegated +? own_frozen) in + let* opti_frozen = + Tez_repr.mul_ratio + ~rounding:`Up + power + ~num:1L + ~den:(Int64.add limit_of_delegation_over_baking 1L) + in + let min_frozen = Constants_storage.minimal_frozen_stake ctxt in + return (Tez_repr.max opti_frozen min_frozen) + +let baking_weight ctxt staking_parameters f = + let open Result_syntax in + let+ s = apply_limits ctxt staking_parameters f in + Stake_repr.staking_weight s diff --git a/src/proto_020_PsParisC/lib_protocol/stake_context.mli b/src/proto_020_PsParisC/lib_protocol/stake_context.mli new file mode 100644 index 000000000000..7648e535085c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/stake_context.mli @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Functions on stake and depending on the context. *) + +(** Apply the delegation_over_baking and staking_over_baking limits of + a delegate. Overstaked tez count as delegated, overdelegated tez + do not count at all. *) +val apply_limits : + Raw_context.t -> + Staking_parameters_repr.t -> + Full_staking_balance_repr.t -> + Stake_repr.t tzresult + +(** The weight of a baker used for baking and attesting rights. *) +val baking_weight : + Raw_context.t -> + Staking_parameters_repr.t -> + Full_staking_balance_repr.t -> + int64 tzresult + +val optimal_frozen_wrt_delegated_without_ai : + Raw_context.t -> Full_staking_balance_repr.t -> Tez_repr.t tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/stake_repr.ml b/src/proto_020_PsParisC/lib_protocol/stake_repr.ml new file mode 100644 index 000000000000..8dd7364b79fb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/stake_repr.ml @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = {frozen : Tez_repr.t; weighted_delegated : Tez_repr.t} + +let make ~frozen ~weighted_delegated = {frozen; weighted_delegated} + +let get_frozen {frozen; _} = frozen + +let encoding = + let open Data_encoding in + conv + (fun {frozen; weighted_delegated} -> (frozen, weighted_delegated)) + (fun (frozen, weighted_delegated) -> {frozen; weighted_delegated}) + (obj2 (req "frozen" Tez_repr.encoding) (req "delegated" Tez_repr.encoding)) + +let zero = make ~frozen:Tez_repr.zero ~weighted_delegated:Tez_repr.zero + +let ( +? ) {frozen = f1; weighted_delegated = d1} + {frozen = f2; weighted_delegated = d2} = + let open Result_syntax in + let* frozen = Tez_repr.(f1 +? f2) in + let+ weighted_delegated = Tez_repr.(d1 +? d2) in + {frozen; weighted_delegated} + +let staking_weight {frozen; weighted_delegated} = + let frozen = Tez_repr.to_mutez frozen in + let weighted_delegated = Tez_repr.to_mutez weighted_delegated in + Int64.add frozen weighted_delegated + +let compare s1 s2 = Int64.compare (staking_weight s1) (staking_weight s2) + +let has_minimal_stake_to_participate ~minimal_stake {frozen; weighted_delegated} + = + match Tez_repr.(frozen +? weighted_delegated) with + | Error _total_overflows -> true + | Ok total -> Tez_repr.(total >= minimal_stake) diff --git a/src/proto_020_PsParisC/lib_protocol/stake_repr.mli b/src/proto_020_PsParisC/lib_protocol/stake_repr.mli new file mode 100644 index 000000000000..a00ac7a1e03e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/stake_repr.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Stake of a delegate. + + It has the invariants enforced by {!Stake_context.apply_limits}: + [frozen] excludes any overstaked tez, and [weighted_delegated] + includes overstaked tez but excludes overdelegated tez. *) +type t = private {frozen : Tez_repr.t; weighted_delegated : Tez_repr.t} + +val zero : t + +(** Builds a {!t}. Should only be called in + {!Stake_context.apply_limits} to enforce the invariants. *) +val make : frozen:Tez_repr.t -> weighted_delegated:Tez_repr.t -> t + +val encoding : t Data_encoding.t + +(** Returns only the frozen part of a stake. This includes the frozen + balances from the delegate and any stakers, but excludes any + overstaked tez. *) +val get_frozen : t -> Tez_repr.t + +val ( +? ) : t -> t -> t tzresult + +(** The weight of a staker or a set of stakers. Since this + function is applied on a [Stake_repr.t], the limits should already + have been applied using [apply_limits] if necessary. *) +val staking_weight : t -> int64 + +val compare : t -> t -> int + +val has_minimal_stake_to_participate : minimal_stake:Tez_repr.t -> t -> bool diff --git a/src/proto_020_PsParisC/lib_protocol/stake_storage.ml b/src/proto_020_PsParisC/lib_protocol/stake_storage.ml new file mode 100644 index 000000000000..53ad57c4fe74 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/stake_storage.ml @@ -0,0 +1,318 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Selected_distribution_for_cycle = struct + module Cache_client = struct + type cached_value = (Signature.Public_key_hash.t * Stake_repr.t) list + + let namespace = Cache_repr.create_namespace "stake_distribution" + + let cache_index = 1 + + let value_of_identifier ctxt identifier = + let cycle = Cycle_repr.of_string_exn identifier in + Storage.Stake.Selected_distribution_for_cycle.get ctxt cycle + end + + module Cache = (val Cache_repr.register_exn (module Cache_client)) + + let identifier_of_cycle cycle = Format.asprintf "%a" Cycle_repr.pp cycle + + let init ctxt cycle stakes = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let* ctxt = + Storage.Stake.Selected_distribution_for_cycle.init ctxt cycle stakes + in + let size = 1 (* that's symbolic: 1 cycle = 1 entry *) in + let*? ctxt = Cache.update ctxt id (Some (stakes, size)) in + return ctxt + + let get ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let* value_opt = Cache.find ctxt id in + match value_opt with + | None -> Storage.Stake.Selected_distribution_for_cycle.get ctxt cycle + | Some v -> return v + + let find ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let* value_opt = Cache.find ctxt id in + match value_opt with + | None -> Storage.Stake.Selected_distribution_for_cycle.find ctxt cycle + | Some _ as some_v -> return some_v + + let remove_existing ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let*? ctxt = Cache.update ctxt id None in + Storage.Stake.Selected_distribution_for_cycle.remove_existing ctxt cycle + + let remove ctxt cycle = + let open Lwt_result_syntax in + let id = identifier_of_cycle cycle in + let*? ctxt = Cache.update ctxt id None in + let*! ctxt = + Storage.Stake.Selected_distribution_for_cycle.remove ctxt cycle + in + return ctxt +end + +let get_full_staking_balance = Storage.Stake.Staking_balance.get + +let has_minimal_stake ctxt staking_balance = + let minimal_stake = Constants_storage.minimal_stake ctxt in + Full_staking_balance_repr.has_minimal_stake_to_be_considered + ~minimal_stake + staking_balance + +let initialize_delegate ctxt delegate ~delegated = + let open Lwt_result_syntax in + let current_level = Raw_context.current_level ctxt in + let balance = + Full_staking_balance_repr.init + ~own_frozen:Tez_repr.zero + ~staked_frozen:Tez_repr.zero + ~delegated + ~current_level + in + let* ctxt = Storage.Stake.Staking_balance.init ctxt delegate balance in + if has_minimal_stake ctxt balance then + let*! ctxt = + Storage.Stake.Active_delegates_with_minimal_stake.add ctxt delegate + in + return ctxt + else return ctxt + +let update_stake ~f ctxt delegate = + let open Lwt_result_syntax in + let* staking_balance_before = get_full_staking_balance ctxt delegate in + let*? staking_balance = f staking_balance_before in + let* ctxt = + Storage.Stake.Staking_balance.update ctxt delegate staking_balance + in + (* Since the staking balance has changed, the delegate might have + moved across the minimal stake barrier. If so we may need to + update the set of active delegates with minimal stake. *) + let had_minimal_stake_before = + has_minimal_stake ctxt staking_balance_before + in + let has_minimal_stake_after = has_minimal_stake ctxt staking_balance in + match (had_minimal_stake_before, has_minimal_stake_after) with + | true, false -> + (* Decrease below the minimal stake. *) + let* inactive = Delegate_activation_storage.is_inactive ctxt delegate in + if inactive then + (* The delegate is inactive so it wasn't in the set and we + don't need to update it. *) + return ctxt + else + let*! ctxt = + Storage.Stake.Active_delegates_with_minimal_stake.remove ctxt delegate + in + return ctxt + | false, true -> + (* Increase above the minimal stake. *) + let* inactive = Delegate_activation_storage.is_inactive ctxt delegate in + if inactive then + (* The delegate is inactive so we don't need to add it to the + set. *) + return ctxt + else + let*! ctxt = + Storage.Stake.Active_delegates_with_minimal_stake.add ctxt delegate + in + return ctxt + | false, false | true, true -> return ctxt + +let remove_delegated_stake ctxt delegate amount = + let current_level = Raw_context.current_level ctxt in + let f = Full_staking_balance_repr.remove_delegated ~current_level ~amount in + update_stake ctxt delegate ~f + +let remove_own_frozen_stake ctxt delegate amount = + let f = Full_staking_balance_repr.remove_own_frozen ~amount in + update_stake ctxt delegate ~f + +let remove_staked_frozen_stake ctxt delegate amount = + let f = Full_staking_balance_repr.remove_staked_frozen ~amount in + update_stake ctxt delegate ~f + +let remove_frozen_stake_only_call_from_token ctxt staker amount = + match staker with + | Frozen_staker_repr.Baker delegate -> + remove_own_frozen_stake ctxt delegate amount + | Frozen_staker_repr.Baker_edge delegate -> + (* This case should not happen because [Baker_edge] is only + intended to be used for rewards. *) + remove_own_frozen_stake ctxt delegate amount + | Single_staker {staker = _; delegate} | Shared_between_stakers {delegate} -> + remove_staked_frozen_stake ctxt delegate amount + +let add_delegated_stake ctxt delegate amount = + let current_level = Raw_context.current_level ctxt in + let f = Full_staking_balance_repr.add_delegated ~current_level ~amount in + update_stake ctxt delegate ~f + +let add_own_frozen_stake ctxt delegate amount = + let f = Full_staking_balance_repr.add_own_frozen ~amount in + update_stake ctxt delegate ~f + +let add_staked_frozen_stake ctxt delegate amount = + let f = Full_staking_balance_repr.add_staked_frozen ~amount in + update_stake ctxt delegate ~f + +let add_frozen_stake_only_call_from_token ctxt staker amount = + match staker with + | Frozen_staker_repr.Baker delegate -> + add_own_frozen_stake ctxt delegate amount + | Frozen_staker_repr.Baker_edge delegate -> + add_own_frozen_stake ctxt delegate amount + | Single_staker {staker = _; delegate} | Shared_between_stakers {delegate} -> + add_staked_frozen_stake ctxt delegate amount + +let set_inactive ctxt delegate = + let open Lwt_syntax in + let* ctxt = Delegate_activation_storage.set_inactive ctxt delegate in + Storage.Stake.Active_delegates_with_minimal_stake.remove ctxt delegate + +let set_active ctxt delegate = + let open Lwt_result_syntax in + let* ctxt, inactive = Delegate_activation_storage.set_active ctxt delegate in + if not inactive then return ctxt + else + let* staking_balance = get_full_staking_balance ctxt delegate in + if has_minimal_stake ctxt staking_balance then + let*! ctxt = + Storage.Stake.Active_delegates_with_minimal_stake.add ctxt delegate + in + return ctxt + else return ctxt + +let set_selected_distribution_for_cycle ctxt cycle stakes total_stake = + let open Lwt_result_syntax in + let stakes = List.sort (fun (_, x) (_, y) -> Stake_repr.compare y x) stakes in + let* ctxt = Selected_distribution_for_cycle.init ctxt cycle stakes in + let*! ctxt = Storage.Stake.Total_active_stake.add ctxt cycle total_stake in + return ctxt + +let fold_on_active_delegates_with_minimal_stake_es ctxt ~f ~order ~init = + let open Lwt_result_syntax in + Storage.Stake.Active_delegates_with_minimal_stake.fold + ctxt + ~order + ~init:(Ok init) + ~f:(fun delegate acc -> + let*? acc in + f delegate acc) + +let clear_at_cycle_end ctxt ~new_cycle = + let open Lwt_result_syntax in + let max_slashing_period = Constants_repr.max_slashing_period in + match Cycle_repr.sub new_cycle max_slashing_period with + | None -> return ctxt + | Some cycle_to_clear -> + let* ctxt = + Storage.Stake.Total_active_stake.remove_existing ctxt cycle_to_clear + in + Selected_distribution_for_cycle.remove_existing ctxt cycle_to_clear + +let fold_on_active_delegates_with_minimal_stake_s = + Storage.Stake.Active_delegates_with_minimal_stake.fold + +let get_selected_distribution = Selected_distribution_for_cycle.get + +let find_selected_distribution = Selected_distribution_for_cycle.find + +let get_selected_distribution_as_map ctxt cycle = + let open Lwt_result_syntax in + let+ stakes = Selected_distribution_for_cycle.get ctxt cycle in + List.fold_left + (fun map (pkh, stake) -> Signature.Public_key_hash.Map.add pkh stake map) + Signature.Public_key_hash.Map.empty + stakes + +let prepare_stake_distribution ctxt = + let open Lwt_result_syntax in + let level = Level_storage.current ctxt in + let+ stake_distribution = get_selected_distribution_as_map ctxt level.cycle in + Raw_context.init_stake_distribution_for_current_cycle ctxt stake_distribution + +let get_total_active_stake = Storage.Stake.Total_active_stake.get + +let remove_contract_delegated_stake ctxt contract amount = + let open Lwt_result_syntax in + let* delegate_opt = Contract_delegate_storage.find ctxt contract in + match delegate_opt with + | None -> return ctxt + | Some delegate -> remove_delegated_stake ctxt delegate amount + +let add_contract_delegated_stake ctxt contract amount = + let open Lwt_result_syntax in + let* delegate_opt = Contract_delegate_storage.find ctxt contract in + match delegate_opt with + | None -> return ctxt + | Some delegate -> add_delegated_stake ctxt delegate amount + +(* let's assume that consensus_rights_delay <= preserved_cycles; + we need to keep [ new_cycles; new_cycles + consensus_rights_delay ] + and remove the rest, i.e., + [ new_cycles + consensus_rights_delay + 1; new_cycles + preserved_cycles ] *) +let cleanup_values_for_protocol_p ctxt ~preserved_cycles ~consensus_rights_delay + ~new_cycle = + let open Lwt_result_syntax in + assert (Compare.Int.(consensus_rights_delay <= preserved_cycles)) ; + if Compare.Int.(consensus_rights_delay = preserved_cycles) then return ctxt + else + let start_cycle = Cycle_repr.add new_cycle (consensus_rights_delay + 1) in + let end_cycle = Cycle_repr.add new_cycle preserved_cycles in + List.fold_left_es + (fun ctxt cycle_to_clear -> + let*! ctxt = + Storage.Stake.Total_active_stake.remove ctxt cycle_to_clear + in + Selected_distribution_for_cycle.remove ctxt cycle_to_clear) + ctxt + Cycle_repr.(start_cycle ---> end_cycle) + +module For_RPC = struct + let get_staking_balance ctxt delegate = + let open Lwt_result_syntax in + let* staking_balance = Storage.Stake.Staking_balance.get ctxt delegate in + Lwt.return (Full_staking_balance_repr.current_total staking_balance) +end + +module Internal_for_tests = struct + let get ctxt delegate = + let open Lwt_result_syntax in + let*! result = + Storage.Stake.Active_delegates_with_minimal_stake.mem ctxt delegate + in + match result with + | true -> For_RPC.get_staking_balance ctxt delegate + | false -> return Tez_repr.zero +end diff --git a/src/proto_020_PsParisC/lib_protocol/stake_storage.mli b/src/proto_020_PsParisC/lib_protocol/stake_storage.mli new file mode 100644 index 000000000000..721e24698c6e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/stake_storage.mli @@ -0,0 +1,163 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides basic operations (accessors and setters) on + staking tokens. + + It is responsible for maintaining the following tables: + - {!Storage.Stake.Selected_distribution_for_cycle} + - {!Storage.Stake.Staking_balance} + - {!Storage.Stake.Active_delegates_with_minimal_stake} + - {!Storage.Stake.Total_active_stake} +*) + +val initialize_delegate : + Raw_context.t -> + Signature.public_key_hash -> + delegated:Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val get_full_staking_balance : + Raw_context.t -> + Signature.public_key_hash -> + Full_staking_balance_repr.t tzresult Lwt.t + +val remove_delegated_stake : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val remove_frozen_stake_only_call_from_token : + Raw_context.t -> + Frozen_staker_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val add_delegated_stake : + Raw_context.t -> + Signature.Public_key_hash.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val add_frozen_stake_only_call_from_token : + Raw_context.t -> + Frozen_staker_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +val set_inactive : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t Lwt.t + +val set_active : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t + +(** [fold ctxt ~f ~order init] folds [f] on the list of active delegates having the + minimal required stake. The folding process starts with [init]. Each element of the + list is the public key hash of a delegate. *) +val fold_on_active_delegates_with_minimal_stake_es : + Raw_context.t -> + f:(Signature.Public_key_hash.t -> 'a -> 'a tzresult Lwt.t) -> + order:[`Sorted | `Undefined] -> + init:'a -> + 'a tzresult Lwt.t + +(** [set_selected_distribution_for_cycle ctxt cycle distrib total_stake] saves + the selected distribution [distrib] of the [total_stake] for the given + [cycle]. *) +val set_selected_distribution_for_cycle : + Raw_context.t -> + Cycle_repr.t -> + (Signature.public_key_hash * Stake_repr.t) list -> + Stake_repr.t -> + Raw_context.t tzresult Lwt.t + +val clear_at_cycle_end : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val fold_on_active_delegates_with_minimal_stake_s : + Raw_context.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Signature.Public_key_hash.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + +val get_selected_distribution : + Raw_context.t -> + Cycle_repr.t -> + (Signature.Public_key_hash.t * Stake_repr.t) list tzresult Lwt.t + +val find_selected_distribution : + Raw_context.t -> + Cycle_repr.t -> + (Signature.Public_key_hash.t * Stake_repr.t) list option tzresult Lwt.t + +val get_selected_distribution_as_map : + Raw_context.t -> + Cycle_repr.t -> + Stake_repr.t Signature.Public_key_hash.Map.t tzresult Lwt.t + +(** Copy the stake distribution for the current cycle (from + [Storage.Stake.Selected_distribution_for_cycle]) in the raw + context. *) +val prepare_stake_distribution : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** [get_total_active_stake ctxt cycle] retrieves the amount in Tez of the + active stake at [cycle] from [ctxt]. *) +val get_total_active_stake : + Raw_context.t -> Cycle_repr.t -> Stake_repr.t tzresult Lwt.t + +(** [add_contract_delegated_stake ctxt contract amount] calls + [Stake_storage.add_delegated_stake ctxt delegate amount] if + [contract] has a [delegate]. Otherwise this function does + nothing. *) +val add_contract_delegated_stake : + Raw_context.t -> Contract_repr.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t + +(** [remove_contract_delegated_stake ctxt contract amount] calls + [Stake_storage.remove_delegated_stake ctxt delegate amount] if + [contract] has a [delegate]. Otherwise this function does + nothing. *) +val remove_contract_delegated_stake : + Raw_context.t -> Contract_repr.t -> Tez_repr.t -> Raw_context.t tzresult Lwt.t + +val cleanup_values_for_protocol_p : + Raw_context.t -> + preserved_cycles:int -> + consensus_rights_delay:int -> + new_cycle:Cycle_repr.t -> + Raw_context.t tzresult Lwt.t + +module For_RPC : sig + val get_staking_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t +end + +module Internal_for_tests : sig + (** Same as [get_staking_balance] but returns zero if the argument + is not an active delegate above minimal stake. *) + val get : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/staking.ml b/src/proto_020_PsParisC/lib_protocol/staking.ml new file mode 100644 index 000000000000..53b30cb6b8fb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking.ml @@ -0,0 +1,429 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Cannot_stake_with_unfinalizable_unstake_requests_to_another_delegate + | Manual_staking_forbidden + +let () = + let description = + "A contract tries to stake to its delegate while having unstake requests \ + to a previous delegate that cannot be finalized yet. Try again in a later \ + cycle (no more than consensus_rights_delay + max_slashing_period)." + in + register_error_kind + `Permanent + ~id: + "operation.cannot_stake_with_unfinalizable_unstake_requests_to_another_delegate" + ~title: + "Cannot stake with unfinalizable unstake requests to another delegate" + ~description + Data_encoding.unit + (function + | Cannot_stake_with_unfinalizable_unstake_requests_to_another_delegate -> + Some () + | _ -> None) + (fun () -> + Cannot_stake_with_unfinalizable_unstake_requests_to_another_delegate) ; + register_error_kind + `Temporary + ~id:"operation.manual_staking_forbidden" + ~title:"Manual staking operations are forbidden" + ~description: + "Manual staking operations are forbidden because staking is currently \ + automated." + Data_encoding.unit + (function Manual_staking_forbidden -> Some () | _ -> None) + (fun () -> Manual_staking_forbidden) + +let perform_finalizable_unstake_transfers ctxt contract finalizable = + let open Lwt_result_syntax in + List.fold_left_es + (fun (ctxt, balance_updates) (delegate, cycle, amount) -> + let+ ctxt, new_balance_updates = + Token.transfer + ctxt + (`Unstaked_frozen_deposits + (Unstaked_frozen_staker_repr.Single (contract, delegate), cycle)) + (`Contract contract) + amount + in + (ctxt, new_balance_updates @ balance_updates)) + (ctxt, []) + finalizable + +(* The [check_unfinalizable] function in argument must consume its gas, if + relevant. *) +let finalize_unstake_and_check ~for_next_cycle_use_only_after_slashing + ~check_unfinalizable ctxt contract = + let open Lwt_result_syntax in + let*? ctxt = + Raw_context.consume_gas + ctxt + Adaptive_issuance_costs.prepare_finalize_unstake_cost + in + let* prepared_opt = + Unstake_requests_storage.prepare_finalize_unstake + ~for_next_cycle_use_only_after_slashing + ctxt + contract + in + match prepared_opt with + | None -> return (ctxt, [], None) + | Some {finalizable; unfinalizable} -> ( + let* ctxt = check_unfinalizable ctxt unfinalizable in + match finalizable with + | [] -> return (ctxt, [], Some unfinalizable) + | _ -> + (* We only update the unstake requests if the [finalizable] list is not empty. + Indeed, if it is not empty, it means that at least one of the unstake operations + will be finalized, and the storage needs to be updated accordingly. + Conversely, if finalizable is empty, then [unfinalizable] contains + all the previous unstake requests, that should remain as requests after this + operation. *) + let*? ctxt = + Raw_context.consume_gas + ctxt + Adaptive_issuance_costs.finalize_unstake_and_check_cost + in + let* ctxt = + Unstake_requests_storage.update ctxt contract unfinalizable + in + let* ctxt, balance_updates = + perform_finalizable_unstake_transfers ctxt contract finalizable + in + return (ctxt, balance_updates, Some unfinalizable)) + +let finalize_unstake ctxt ~for_next_cycle_use_only_after_slashing contract = + let open Lwt_result_syntax in + let check_unfinalizable ctxt _unfinalizable = return ctxt in + let* ctxt, balance_updates, _ = + finalize_unstake_and_check + ~for_next_cycle_use_only_after_slashing + ~check_unfinalizable + ctxt + contract + in + return (ctxt, balance_updates) + +let can_stake_from_unstake ctxt ~for_next_cycle_use_only_after_slashing + ~delegate = + let open Lwt_result_syntax in + let* slashing_history_opt = Storage.Slashed_deposits.find ctxt delegate in + let slashing_history = Option.value slashing_history_opt ~default:[] in + + let* slashing_history_opt_o = + Storage.Contract.Slashed_deposits__Oxford.find + ctxt + (Contract_repr.Implicit delegate) + in + let slashing_history_o = + Option.value slashing_history_opt_o ~default:[] + |> List.map (fun (a, b) -> (a, Percentage.convert_from_o_to_p b)) + in + + let slashing_history = slashing_history @ slashing_history_o in + + let current_cycle = (Raw_context.current_level ctxt).cycle in + let current_cycle = + if for_next_cycle_use_only_after_slashing then Cycle_repr.succ current_cycle + else current_cycle + in + let slashable_deposits_period = + Constants_storage.slashable_deposits_period ctxt + in + let oldest_slashable_cycle = + Cycle_repr.sub current_cycle (slashable_deposits_period + 1) + |> Option.value ~default:Cycle_repr.root + in + let*! is_denounced = + Pending_denunciations_storage.has_pending_denunciations ctxt delegate + in + let is_slashed = + List.exists + (fun (x, _) -> Cycle_repr.(x >= oldest_slashable_cycle)) + slashing_history + in + return @@ not (is_denounced || is_slashed) + +let stake_from_unstake_for_delegate ctxt ~for_next_cycle_use_only_after_slashing + ~delegate ~unfinalizable_requests_opt amount = + let open Lwt_result_syntax in + let remove_from_unstaked_frozen_deposit ctxt cycle delegate sender_contract + amount = + let* ctxt, balance_updates = + Token.transfer + ctxt + (`Unstaked_frozen_deposits + (Unstaked_frozen_staker_repr.Single (sender_contract, delegate), cycle)) + (`Frozen_deposits + (Frozen_staker_repr.single_staker ~staker:sender_contract ~delegate)) + amount + in + let* ctxt = + Unstaked_frozen_deposits_storage + .decrease_initial_amount_only_for_stake_from_unstake + ctxt + delegate + cycle + amount + in + return (ctxt, balance_updates) + in + match unfinalizable_requests_opt with + | None -> return (ctxt, [], amount) + | Some Unstake_requests_storage.{delegate = delegate_requests; requests} -> + if + Signature.Public_key_hash.(delegate <> delegate_requests) + && not (List.is_empty requests) + then (* Should not be possible *) + return (ctxt, [], Tez_repr.zero) + else + let* allowed = + can_stake_from_unstake + ctxt + ~for_next_cycle_use_only_after_slashing + ~delegate + in + if not allowed then + (* a slash could have modified the unstaked frozen deposits: cannot stake from unstake *) + return (ctxt, [], amount) + else + let sender_contract = Contract_repr.Implicit delegate in + let requests_sorted = + List.sort + (fun (cycle1, _) (cycle2, _) -> + Cycle_repr.compare cycle2 cycle1 + (* decreasing cycle order, to release first the tokens + that would be frozen for the longest time *)) + requests + in + let rec transfer_from_unstake ctxt balance_updates + remaining_amount_to_transfer updated_requests_rev requests = + if Tez_repr.(remaining_amount_to_transfer = zero) then + return + ( ctxt, + balance_updates, + Tez_repr.zero, + List.rev_append requests updated_requests_rev ) + else + match requests with + | [] -> + return + ( ctxt, + balance_updates, + remaining_amount_to_transfer, + updated_requests_rev ) + | (cycle, requested_amount) :: t -> + if Tez_repr.(remaining_amount_to_transfer >= requested_amount) + then + let* ctxt, cycle_balance_updates = + remove_from_unstaked_frozen_deposit + ctxt + cycle + delegate + sender_contract + requested_amount + in + let*? remaining_amount = + Tez_repr.( + remaining_amount_to_transfer -? requested_amount) + in + transfer_from_unstake + ctxt + (balance_updates @ cycle_balance_updates) + remaining_amount + updated_requests_rev + t + else + let* ctxt, cycle_balance_updates = + remove_from_unstaked_frozen_deposit + ctxt + cycle + delegate + sender_contract + remaining_amount_to_transfer + in + let*? new_requested_amount = + Tez_repr.( + requested_amount -? remaining_amount_to_transfer) + in + return + ( ctxt, + balance_updates @ cycle_balance_updates, + Tez_repr.zero, + List.rev_append + t + ((cycle, new_requested_amount) :: updated_requests_rev) + ) + in + let* ( ctxt, + balance_updates, + remaining_amount_to_transfer, + updated_requests_rev ) = + transfer_from_unstake ctxt [] amount [] requests_sorted + in + let updated_requests = List.rev updated_requests_rev in + let* ctxt = + Unstake_requests_storage.update + ctxt + sender_contract + {delegate; requests = updated_requests} + in + return (ctxt, balance_updates, remaining_amount_to_transfer) + +let stake ctxt ~for_next_cycle_use_only_after_slashing + ~(amount : [`At_most of Tez_repr.t | `Exactly of Tez_repr.t]) ~sender + ~delegate = + let open Lwt_result_syntax in + let check_unfinalizable ctxt + Unstake_requests_storage.{delegate = unstake_delegate; requests} = + match (requests, amount) with + | [], _ | _ :: _, `At_most _ -> return ctxt + | _ :: _, `Exactly _ -> + if Signature.Public_key_hash.(delegate <> unstake_delegate) then + tzfail + Cannot_stake_with_unfinalizable_unstake_requests_to_another_delegate + else return ctxt + in + let sender_contract = Contract_repr.Implicit sender in + let* ctxt, finalize_balance_updates, unfinalizable_requests_opt = + finalize_unstake_and_check + ~check_unfinalizable + ctxt + ~for_next_cycle_use_only_after_slashing + sender_contract + in + let tez_amount = + match amount with `Exactly amount | `At_most amount -> amount + in + (* stake from unstake for eligible delegates *) + let* ctxt, stake_balance_updates1, amount_from_liquid = + if Signature.Public_key_hash.(sender <> delegate) then + return (ctxt, [], tez_amount) + else + stake_from_unstake_for_delegate + ctxt + ~for_next_cycle_use_only_after_slashing + ~delegate + ~unfinalizable_requests_opt + tez_amount + in + (* Get amount to transfer from liquid wrt mode *) + let* amount_from_liquid = + match amount with + | `Exactly _ -> return amount_from_liquid + | `At_most _ -> + let* spendable = + Contract_storage.get_balance ctxt (Implicit delegate) + in + return Tez_repr.(min amount_from_liquid spendable) + in + (* Issue pseudotokens for delegators *) + let* ctxt, stake_balance_updates2 = + if Signature.Public_key_hash.(sender <> delegate) then + Staking_pseudotokens_storage.stake + ctxt + ~contract:sender_contract + ~delegate + amount_from_liquid + else return (ctxt, []) + in + let+ ctxt, stake_balance_updates3 = + Token.transfer + ctxt + (`Contract sender_contract) + (`Frozen_deposits + (Frozen_staker_repr.single_staker ~staker:sender_contract ~delegate)) + amount_from_liquid + in + ( ctxt, + stake_balance_updates1 @ stake_balance_updates2 @ stake_balance_updates3 + @ finalize_balance_updates ) + +let request_unstake ctxt ~for_next_cycle_use_only_after_slashing + ~sender_contract ~delegate requested_amount = + let open Lwt_result_syntax in + let* ctxt, tez_to_unstake, request_unstake_balance_updates = + Staking_pseudotokens_storage.request_unstake + ctxt + ~contract:sender_contract + ~delegate + requested_amount + in + if Tez_repr.(tez_to_unstake = zero) then + return (ctxt, request_unstake_balance_updates) + else + let*? ctxt = + Raw_context.consume_gas ctxt Adaptive_issuance_costs.request_unstake_cost + in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let concerned_cycle = + if for_next_cycle_use_only_after_slashing then + Cycle_repr.succ current_cycle + else current_cycle + in + let* ctxt, balance_updates = + Token.transfer + ctxt + (`Frozen_deposits + (Frozen_staker_repr.single_staker ~staker:sender_contract ~delegate)) + (`Unstaked_frozen_deposits + ( Unstaked_frozen_staker_repr.Single (sender_contract, delegate), + concerned_cycle )) + tez_to_unstake + in + let* ctxt, finalize_balance_updates = + finalize_unstake + ctxt + ~for_next_cycle_use_only_after_slashing + sender_contract + in + let+ ctxt = + Unstake_requests_storage.add + ctxt + ~contract:sender_contract + ~delegate + concerned_cycle + tez_to_unstake + in + ( ctxt, + request_unstake_balance_updates @ balance_updates + @ finalize_balance_updates ) + +type staking_automation = Auto_staking | Manual_staking + +let staking_automation ctxt = + if + Raw_context.adaptive_issuance_enable ctxt + || not (Constants_storage.adaptive_issuance_autostaking_enable ctxt) + then Manual_staking + else Auto_staking + +let check_manual_staking_allowed ctxt = + let open Result_syntax in + match staking_automation ctxt with + | Manual_staking -> return_unit + | Auto_staking -> error Manual_staking_forbidden diff --git a/src/proto_020_PsParisC/lib_protocol/staking.mli b/src/proto_020_PsParisC/lib_protocol/staking.mli new file mode 100644 index 000000000000..e3b6925fae18 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking.mli @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [stake ctxt ~sender ~for_next_cycle_use_only_after_slashing ~delegate amount] + add [amount] as [sender]'s stake to [delegate]. + + If [for_next_cycle_use_only_after_slashing] is true, the implicit + finalisation is done for the next cycle. It is meant to be used only at + cycle end after the application of the slashing. + + *) +val stake : + Raw_context.t -> + for_next_cycle_use_only_after_slashing:bool -> + amount:[`At_most of Tez_repr.t | `Exactly of Tez_repr.t] -> + sender:Signature.Public_key_hash.t -> + delegate:Signature.public_key_hash -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [request_unstake ctxt ~for_next_cycle_use_only_after_slashing ~sender_contract ~delegate amount] + records a request from [sender_contract] to unstake [amount] from [delegate]. + + If [for_next_cycle_use_only_after_slashing] is true, the unstake request and + the implicit finalisation is done for the next cycle. It is meant to be used + only at cycle end after the application of the slashing. *) +val request_unstake : + Raw_context.t -> + for_next_cycle_use_only_after_slashing:bool -> + sender_contract:Contract_repr.t -> + delegate:Signature.public_key_hash -> + Tez_repr.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [finalize_unstake ctxt ~for_next_cycle_use_only_after_slashing contract] + performs the finalization of all unstake requests from [contract] that can + be finalized. + An unstake request can be finalized if it is old enough, specifically the + requested amount must not be at stake anymore and must not be slashable + anymore, i.e. after [consensus_rights_delay + max_slashing_period] after the + request. + Amounts are transferred from the [contract]'s delegate (at request time) + unstaked frozen deposits to [contract]'s spendable balance, minus slashing + the requested stake undergone in between. + + If [for_next_cycle_use_only_after_slashing] is true, the finalization is + done for the next cycle. It is meant to be used only at cycle end after the + application of the slashing.*) +val finalize_unstake : + Raw_context.t -> + for_next_cycle_use_only_after_slashing:bool -> + Contract_repr.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** Staking can be either automated or manual. If Adaptive Issuance is + enabled, staking must be manual. *) +type staking_automation = Auto_staking | Manual_staking + +val staking_automation : Raw_context.t -> staking_automation + +val check_manual_staking_allowed : Raw_context.t -> unit tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.ml b/src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.ml new file mode 100644 index 000000000000..d5fcd6f40127 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.ml @@ -0,0 +1,112 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + limit_of_staking_over_baking_millionth : int32; + edge_of_baking_over_staking_billionth : int32; +} + +let maximum_edge_of_baking_over_staking_billionth = + (* max is 1 (1_000_000_000 billionth) *) + 1_000_000_000l + +let default = + { + limit_of_staking_over_baking_millionth = 0l; + edge_of_baking_over_staking_billionth = 1_000_000_000l; + } + +type error += Invalid_staking_parameters + +let () = + register_error_kind + `Permanent + ~id:"operations.invalid_staking_parameters" + ~title:"Invalid parameters for staking parameters" + ~description:"The staking parameters are invalid." + ~pp:(fun ppf () -> Format.fprintf ppf "Invalid staking parameters") + Data_encoding.empty + (function Invalid_staking_parameters -> Some () | _ -> None) + (fun () -> Invalid_staking_parameters) + +let make ~limit_of_staking_over_baking_millionth + ~edge_of_baking_over_staking_billionth = + if + Compare.Int32.(limit_of_staking_over_baking_millionth < 0l) + || Compare.Int32.(edge_of_baking_over_staking_billionth < 0l) + || Compare.Int32.( + edge_of_baking_over_staking_billionth + > maximum_edge_of_baking_over_staking_billionth) + then Error () + else + Ok + { + limit_of_staking_over_baking_millionth; + edge_of_baking_over_staking_billionth; + } + +let encoding = + let open Data_encoding in + conv_with_guard + (fun { + limit_of_staking_over_baking_millionth; + edge_of_baking_over_staking_billionth; + } -> + ( limit_of_staking_over_baking_millionth, + edge_of_baking_over_staking_billionth )) + (fun ( limit_of_staking_over_baking_millionth, + edge_of_baking_over_staking_billionth ) -> + Result.map_error + (fun () -> "Invalid staking parameters") + (make + ~limit_of_staking_over_baking_millionth + ~edge_of_baking_over_staking_billionth)) + (obj2 + (req "limit_of_staking_over_baking_millionth" int32) + (req "edge_of_baking_over_staking_billionth" int32)) + +let make ~limit_of_staking_over_baking_millionth + ~edge_of_baking_over_staking_billionth = + match + if + Compare.Z.(limit_of_staking_over_baking_millionth < Z.zero) + || Compare.Z.(edge_of_baking_over_staking_billionth < Z.zero) + || not (Z.fits_int32 edge_of_baking_over_staking_billionth) + then Error () + else + let limit_of_staking_over_baking_millionth = + if Z.fits_int32 limit_of_staking_over_baking_millionth then + Z.to_int32 limit_of_staking_over_baking_millionth + else Int32.max_int + in + let edge_of_baking_over_staking_billionth = + Z.to_int32 edge_of_baking_over_staking_billionth + in + make + ~limit_of_staking_over_baking_millionth + ~edge_of_baking_over_staking_billionth + with + | Error () -> Result_syntax.tzfail Invalid_staking_parameters + | Ok _ as ok -> ok diff --git a/src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.mli b/src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.mli new file mode 100644 index 000000000000..c416000219cc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking_parameters_repr.mli @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = private { + limit_of_staking_over_baking_millionth : int32; + edge_of_baking_over_staking_billionth : int32; +} + +(** Value used when unset *) +val default : t + +type error += Invalid_staking_parameters + +val make : + limit_of_staking_over_baking_millionth:Z.t -> + edge_of_baking_over_staking_billionth:Z.t -> + t tzresult + +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.ml b/src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.ml new file mode 100644 index 000000000000..a5e824144142 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.ml @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* A pseudotoken is not a Tez but it behaves similarly so let's reuse its operations. *) + +include Tez_repr + +let of_int64_exn = of_mutez_exn + +let to_int64 = to_mutez + +let of_z_exn z = of_int64_exn (Z.to_int64 z) + +let to_z t = Z.of_int64 (to_int64 t) + +let init_of_tez tz = tz + +let pred pt = sub_opt pt one_mutez diff --git a/src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.mli b/src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.mli new file mode 100644 index 000000000000..9cdb0da998c2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking_pseudotoken_repr.mli @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Pseudotoken used in staking. + It represents a share of the total frozen deposits of a baker. *) +include Compare.S + +val encoding : t Data_encoding.t + +val balance_update_encoding : [`Credited of t | `Debited of t] Data_encoding.t + +val zero : t + +val of_z_exn : Z.t -> t + +val to_int64 : t -> Int64.t + +val to_z : t -> Z.t + +val init_of_tez : Tez_repr.t -> t + +val ( +? ) : t -> t -> t tzresult + +val ( -? ) : t -> t -> t tzresult + +val pred : t -> t option + +(** See {!Tez_repr.mul_ratio}. *) +val mul_ratio : + rounding:[`Down | `Up] -> t -> num:int64 -> den:int64 -> t tzresult + +val pp : Format.formatter -> t -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.ml b/src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.ml new file mode 100644 index 000000000000..9d65bb3d7901 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.ml @@ -0,0 +1,530 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {0} Introduction + + This module is responsible for maintaining the + {!Storage.Contract.Frozen_deposits_pseudotokens} and + {!Storage.Contract.Staking_pseudotokens} tables. + + {1} Terminology + + Even so a registered delegate is always technically in a delegation + relation with itself, in this module, when we use the word + "delegator", we always mean a delegator different from the + delegate itself. The word "staker" means for a delegator who + participates in staking. The word "staker" means any participant + in staking, either a delegate or a staker. In this module, we + use the word "contract" to mean either a delegate or a delegator. + + {1} Full staking balance of a delegate + + For each delegate, the {!Stake_storage} module is responsible to + track three tez quantities which can be requested with the + {!Stake_storage.get_full_staking_balance} function: [own_frozen] + is the frozen deposits of the delegate, [staked_frozen] is the + sum of all frozen deposits of its stakers, and [delegate] is the + sum of all tez delegated to the delegate (some of which may belong + to the delegate itself). This module is in charge of tracking the + frozen deposits of each staker. Since we already have access to + their sum ([staked_frozen]) we only need to track the proportion + of this sum owned by each staker. + + {1} Pseudo-tokens + + The {!Storage.Contract.Frozen_deposits_pseudotokens} and + {!Storage.Contract.Staking_pseudotokens} tables are used to keep + track of this proportion. The amounts stored in these tables don't + have a fixed value in tez, they can be seen as shares of the total + frozen deposits of a delegate's stakers, we call them + pseudotokens. Pseudotokens are minted when a staker increases + its share using the stake pseudo-operation; they are burnt when a + staker decreases its share using the request-unstake + pseudo-operation. Events which modify uniformly the frozen + deposits of all the stakers of a delegate (reward distribution + and slashing) don't lead to minting nor burning any pseudotokens; + that's the main motivation for using these pseudotokens: thanks to + them we never need to iterate over the stakers of a delegate + (whose number is unbounded). + + + {1} Conversion rate: + + The conversion rate between pseudotokens and mutez (the value in + mutez of a pseudotoken) should be given by the ratio between the + delegate's current staked frozen deposits and the total number + of pseudotokens of the delegate; it's actually the case when this + total number of pseudotokens is positive. When the total number of + pseudotokens of a delegate is null, the conversion rate could + theoretically have any value but extreme values are dangerous + because of overflows and loss of precision; for these reasons, we + use one as the conversion rate when the total number of + pseudotokens is null, which can happen in two situations: + + - the first time a delegator stakes since the + migration which created the pseudotoken tables, and + + - when stakers empty their delegate's staked frozen deposits and later + receive rewards. + + + {2} Implementation: + + The {!Storage.Contract.Staking_pseudotokens} table stores for + each staker its {i staking balance pseudotokens} which is the + number of pseudotokens owned by the staker. + + The {!Storage.Contract.Frozen_deposits_pseudotokens} table stores + for each delegate the {i frozen deposits pseudotokens} of the + delegate which is defined as the sum of all the staking balance + pseudotokens of its stakers. + + For both tables, pseudotokens are represented using the + [Pseudotoken_repr.t] type which is, like [Tez_repr.t], stored on + non-negative signed int64. + + + {2} Invariants: + + {3} Invariant 1: frozen deposits pseudotokens initialization + + For {!Storage.Contract.Frozen_deposits_pseudotokens}, a missing + key is equivalent to a value of [0]. This case means that there are + no pseudotokens, the delegate has no staker, the conversion rate is [1]. + + {3} Invariant 2: staking balance pseudotokens initialization + + For {!Storage.Contract.Staking_pseudotokens}, a missing key is + equivalent to a value of [0]. + + {3} Invariant 3: relationship between frozen deposits and staking + balance pseudotokens + + For a given delegate, their frozen deposits pseudotokens equal + the sum of all staking pseudotokens of their delegators. + + {3} Invariant 4: delegates have no staking pseudotokens. +*) + +(** When a delegate gets totally slashed, the value of its + pseudotokens becomes 0 and before minting any new token we would + need to iterate over all stakers to empty their pseudotoken + balances. We want to avoid iterating over stakers so we forbid + {b stake} in this case. *) +type error += Cannot_stake_on_fully_slashed_delegate + +(** These two types are not exported, they are views to the portions + of the storage which are relevant in this module when a delegate + or a staker are considered. *) +type delegate_balances = { + delegate : Signature.public_key_hash; + frozen_deposits_staked_tez : Tez_repr.t; + frozen_deposits_pseudotokens : Staking_pseudotoken_repr.t; +} + +type delegator_balances = { + delegator : Contract_repr.t; + pseudotoken_balance : Staking_pseudotoken_repr.t; + delegate_balances : delegate_balances; +} + +(** {0} Functions reading from the storage *) + +(** [get_frozen_deposits_staked_tez ctxt ~delegate] returns the sum of frozen + deposits, in tez, of the delegate's stakers. *) +let get_frozen_deposits_staked_tez ctxt ~delegate = + let open Lwt_result_syntax in + let+ staking_balance = Stake_storage.get_full_staking_balance ctxt delegate in + Full_staking_balance_repr.staked_frozen staking_balance + +let get_own_frozen_deposits ctxt ~delegate = + let open Lwt_result_syntax in + let+ staking_balance = Stake_storage.get_full_staking_balance ctxt delegate in + Full_staking_balance_repr.own_frozen staking_balance + +(** [get_frozen_deposits_pseudotokens ctxt ~delegate] returns the total + number of pseudotokens in circulation for the given + [delegate]. This should, by invariant 3 be the sum of the + staking balance (in pseudotokens) of all its delegators. + + To preserve invariant 1, this should be the only function of this + module reading from the + {!Storage.Contract.Frozen_deposits_pseudotokens} table. *) +let get_frozen_deposits_pseudotokens ctxt ~delegate = + let open Lwt_result_syntax in + let+ frozen_deposits_pseudotokens_opt = + Storage.Contract.Frozen_deposits_pseudotokens.find ctxt (Implicit delegate) + in + Option.value + frozen_deposits_pseudotokens_opt + ~default:Staking_pseudotoken_repr.zero + +(** [staking_pseudotokens_balance ctxt ~delegator] returns + [delegator]'s current staking balance in pseudotokens. + + To preserve invariant 2, this should be the only function of this + module reading from the {!Storage.Contract.Staking_pseudotokens} + table. +*) +let staking_pseudotokens_balance ctxt ~delegator = + let open Lwt_result_syntax in + let+ staking_pseudotokens_opt = + Storage.Contract.Staking_pseudotokens.find ctxt delegator + in + Option.value ~default:Staking_pseudotoken_repr.zero staking_pseudotokens_opt + +(** [get_delegate_balances ctxt ~delegate] records the staked frozen deposits + in tez and pseudotokens of a given delegate. + + Postcondition: + delegate = result.delegate /\ + get_frozen_deposits_staked_tez ctxt ~delegate = return result.frozen_deposits_staked_tez /\ + get_frozen_deposits_pseudotokens ctxt ~delegate = return result.frozen_deposits_pseudotokens +*) +let get_delegate_balances ctxt ~delegate = + let open Lwt_result_syntax in + let* frozen_deposits_staked_tez = + get_frozen_deposits_staked_tez ctxt ~delegate + in + let+ frozen_deposits_pseudotokens = + get_frozen_deposits_pseudotokens ctxt ~delegate + in + {delegate; frozen_deposits_staked_tez; frozen_deposits_pseudotokens} + +(** [get_delegator_balances ctxt ~delegator ~delegate_balances] enriches + the [delegate_balances] with [delegator]'s pseudotoken balance. + + Precondition: + unchecked: [delegator != delegate_balance.delegate] /\ + unchecked: [delegator] delegates to [delegate_balance.delegate] + unchecked: get_delegate_balances ctxt ~delegate = return delegate_balances + Postcondition: + result.delegator = delegator /\ + result.delegate_balances = delegate_balances /\ + staking_pseudotokens_balance ctxt ~delegator = return result.pseudotoken_balance +*) +let get_delegator_balances ctxt ~delegator ~delegate_balances = + let open Lwt_result_syntax in + let+ pseudotoken_balance = staking_pseudotokens_balance ctxt ~delegator in + {delegator; pseudotoken_balance; delegate_balances} + +(** [mint_pseudotokens ctxt delegator_balances_before + pseudotokens_to_mint] mints [pseudotokens_to_mint] pseudotokens + and assign them to [delegator_balances_before.delegator]. Both + tables are updated to maintain invariant 3. + + Precondition: + unchecked: get_delegator_balances ctxt delegator_balances_before.delegator = return delegator_balances_before /\ + unchecked: invariant3(ctxt) + Postcondition: + get_delegator_balances ctxt delegator_balances_before.delegator = + return {delegator_balances_before with + pseudotoken_balance += pseudotokens_to_mint; + delegate_balances.frozen_deposits_pseudotokens += pseudotokens_to_mint} /\ + invariant3(ctxt) +*) +let mint_pseudotokens ctxt (delegator_balances_before : delegator_balances) + pseudotokens_to_mint = + let open Lwt_result_syntax in + let delegator = delegator_balances_before.delegator in + let delegate = delegator_balances_before.delegate_balances.delegate in + let*? new_pseudotoken_balance = + Staking_pseudotoken_repr.( + delegator_balances_before.pseudotoken_balance +? pseudotokens_to_mint) + in + let*? new_delegate_total_frozen_deposits_pseudotokens = + Staking_pseudotoken_repr.( + delegator_balances_before.delegate_balances.frozen_deposits_pseudotokens + +? pseudotokens_to_mint) + in + let*! ctxt = + Storage.Contract.Staking_pseudotokens.add + ctxt + delegator + new_pseudotoken_balance + in + let*! ctxt = + Storage.Contract.Frozen_deposits_pseudotokens.add + ctxt + (Implicit delegate) + new_delegate_total_frozen_deposits_pseudotokens + in + let balance_updates = + Receipt_repr. + [ + item + (Staking_delegator_numerator {delegator}) + (Credited pseudotokens_to_mint) + Block_application; + item + (Staking_delegate_denominator {delegate}) + (Credited pseudotokens_to_mint) + Block_application; + ] + in + return (ctxt, balance_updates) + +(** [burn_pseudotokens ctxt delegator_balances_before + pseudotokens_to_burn] burns [pseudotokens_to_burn] pseudotokens + from the balance of [delegator_balances_before.delegator]. Both + tables are updated to maintain invariant 3. + + Precondition: + unchecked: get_delegator_balances ctxt delegator_balances_before.delegator = return delegator_balances_before /\ + unchecked: invariant3(ctxt) + Postcondition: + get_delegator_balances ctxt delegator_balances_before.delegator = + return {delegator_balances_before with + pseudotoken_balance -= pseudotokens_to_mint; + delegate_balances.frozen_deposits_pseudotokens -= pseudotokens_to_mint} /\ + invariant3(ctxt) +*) +let burn_pseudotokens ctxt (delegator_balances_before : delegator_balances) + pseudotokens_to_burn = + let open Lwt_result_syntax in + let delegator = delegator_balances_before.delegator in + let delegate = delegator_balances_before.delegate_balances.delegate in + let*? new_pseudotoken_balance = + Staking_pseudotoken_repr.( + delegator_balances_before.pseudotoken_balance -? pseudotokens_to_burn) + in + let*? new_delegate_total_frozen_deposits_pseudotokens = + Staking_pseudotoken_repr.( + delegator_balances_before.delegate_balances.frozen_deposits_pseudotokens + -? pseudotokens_to_burn) + in + let*! ctxt = + Storage.Contract.Staking_pseudotokens.add + ctxt + delegator + new_pseudotoken_balance + in + let*! ctxt = + Storage.Contract.Frozen_deposits_pseudotokens.add + ctxt + (Implicit delegate) + new_delegate_total_frozen_deposits_pseudotokens + in + let balance_updates = + Receipt_repr. + [ + item + (Staking_delegate_denominator {delegate}) + (Debited pseudotokens_to_burn) + Block_application; + item + (Staking_delegator_numerator {delegator}) + (Debited pseudotokens_to_burn) + Block_application; + ] + in + return (ctxt, balance_updates) + +(** {0} Conversion between tez and pseudotokens *) + +(** Tez -> pseudotokens conversion. + Precondition: + tez_amount <> 0 /\ + delegate_balances.frozen_deposits_pseudotokens <> 0 /\ + delegate_balances.frozen_deposits_staked_tez <> 0. + Postcondition: + result <> 0. +*) +let pseudotokens_of ~rounding (delegate_balances : delegate_balances) tez_amount + = + assert ( + Staking_pseudotoken_repr.( + delegate_balances.frozen_deposits_pseudotokens <> zero)) ; + assert (Tez_repr.(delegate_balances.frozen_deposits_staked_tez <> zero)) ; + assert (Tez_repr.(tez_amount <> zero)) ; + Staking_pseudotoken_repr.mul_ratio + ~rounding + delegate_balances.frozen_deposits_pseudotokens + ~num:(Tez_repr.to_mutez tez_amount) + ~den:(Tez_repr.to_mutez delegate_balances.frozen_deposits_staked_tez) + +(** Pseudotokens -> tez conversion. + Precondition: + delegate_balances.frozen_deposits_pseudotokens <> 0. +*) +let tez_of ~rounding (delegate_balances : delegate_balances) pseudotoken_amount + = + assert ( + Staking_pseudotoken_repr.( + delegate_balances.frozen_deposits_pseudotokens <> zero)) ; + Tez_repr.mul_ratio + ~rounding + delegate_balances.frozen_deposits_staked_tez + ~num:(Staking_pseudotoken_repr.to_int64 pseudotoken_amount) + ~den: + (Staking_pseudotoken_repr.to_int64 + delegate_balances.frozen_deposits_pseudotokens) + +(** [compute_pseudotoken_credit_for_tez_amount delegate_balances + tez_amount] is a safe wrapper around [pseudotokens_of + delegate_balances tez_amount]. + + Rounding disadvantages newcomer (gets less pseudotokens for the same tez + value). +*) +let compute_pseudotoken_credit_for_tez_amount delegate_balances tez_amount = + let open Result_syntax in + if Tez_repr.(tez_amount = zero) then + (* This is dead code because Apply.apply_stake already forbids the + amount=0 case. We keep this dead code here to avoid putting too + many preconditions on the usage of this module. *) + return Staking_pseudotoken_repr.zero + else if + Staking_pseudotoken_repr.( + delegate_balances.frozen_deposits_pseudotokens = zero) + then + (* Pseudotokens are not yet initialized, the conversion rate is + 1. *) + return @@ Staking_pseudotoken_repr.init_of_tez tez_amount + else if Tez_repr.(delegate_balances.frozen_deposits_staked_tez = zero) then + (* Can only happen in an attempt to stake after a full + slashing. We forbid this case to avoid having to iterate over + all stakers to reset their pseudotoken balances. *) + tzfail Cannot_stake_on_fully_slashed_delegate + else pseudotokens_of ~rounding:`Down delegate_balances tez_amount + +let stake ctxt ~delegator ~delegate tez_amount = + let open Lwt_result_syntax in + let* delegate_balances = get_delegate_balances ctxt ~delegate in + let*? pseudotokens_to_credit = + compute_pseudotoken_credit_for_tez_amount delegate_balances tez_amount + in + let* delegator_balances = + get_delegator_balances ctxt ~delegator ~delegate_balances + in + mint_pseudotokens ctxt delegator_balances pseudotokens_to_credit + +(** {0} Exported functions, see the mli file. *) +let stake ctxt ~contract ~delegate tez_amount = + if Contract_repr.(contract = Implicit delegate) then + (* No pseudotokens for delegates. *) + Lwt_result_syntax.return (ctxt, []) + else stake ctxt ~delegator:contract ~delegate tez_amount + +(* + Rounding disadvantages unstaker. *) +let request_unstake ctxt ~delegator ~delegate requested_amount = + let open Lwt_result_syntax in + let* delegate_balances = get_delegate_balances ctxt ~delegate in + if Tez_repr.(delegate_balances.frozen_deposits_staked_tez = zero) then + return (ctxt, Tez_repr.zero, []) + else + let* delegator_balances = + get_delegator_balances ctxt ~delegator ~delegate_balances + in + if Staking_pseudotoken_repr.(delegator_balances.pseudotoken_balance = zero) + then return (ctxt, Tez_repr.zero, []) + else ( + assert ( + Staking_pseudotoken_repr.( + delegate_balances.frozen_deposits_pseudotokens <> zero)) ; + + let*? max_to_request = + tez_of + ~rounding:`Down + delegate_balances + delegator_balances.pseudotoken_balance + in + let requested_amount = Tez_repr.min max_to_request requested_amount in + let*? requested_pseudotokens = + pseudotokens_of ~rounding:`Up delegate_balances requested_amount + in + let pseudotokens_to_unstake = + Staking_pseudotoken_repr.min + requested_pseudotokens + delegator_balances.pseudotoken_balance + in + let*? tez_to_unstake = + tez_of ~rounding:`Down delegate_balances pseudotokens_to_unstake + in + let*? pseudotokens_to_unstake, tez_to_unstake = + let open Result_syntax in + if Tez_repr.(tez_to_unstake > requested_amount) then ( + (* this may happen because of the rounding up of pseudotokens, in + this case we resort to unstaking a bit less *) + let pseudotokens_to_unstake = + match Staking_pseudotoken_repr.pred pseudotokens_to_unstake with + | None -> assert false (* by postcondition of pseudotokens_of *) + | Some pt -> pt + in + let* tez_to_unstake = + tez_of ~rounding:`Down delegate_balances pseudotokens_to_unstake + in + assert (Tez_repr.(tez_to_unstake <= requested_amount)) ; + return (pseudotokens_to_unstake, tez_to_unstake)) + else return (pseudotokens_to_unstake, tez_to_unstake) + in + let+ ctxt, balance_updates = + burn_pseudotokens ctxt delegator_balances pseudotokens_to_unstake + in + (ctxt, tez_to_unstake, balance_updates)) + +let request_unstake ctxt ~contract ~delegate requested_amount = + let open Lwt_result_syntax in + if Tez_repr.(requested_amount = zero) then return (ctxt, Tez_repr.zero, []) + else if Contract_repr.(contract = Implicit delegate) then + let+ delegate_own_frozen_deposits = + get_own_frozen_deposits ctxt ~delegate + in + (ctxt, Tez_repr.min delegate_own_frozen_deposits requested_amount, []) + else request_unstake ctxt ~delegator:contract ~delegate requested_amount + +module For_RPC = struct + let staked_balance ctxt ~delegator ~delegate = + let open Lwt_result_syntax in + let* delegate_balances = get_delegate_balances ctxt ~delegate in + let* delegator_balances = + get_delegator_balances ctxt ~delegator ~delegate_balances + in + if + Staking_pseudotoken_repr.( + delegate_balances.frozen_deposits_pseudotokens <> zero) + then + Lwt.return + @@ tez_of + ~rounding:`Down + delegate_balances + delegator_balances.pseudotoken_balance + else ( + assert ( + Staking_pseudotoken_repr.(delegator_balances.pseudotoken_balance = zero)) ; + return Tez_repr.zero) + + let staked_balance ctxt ~contract ~delegate = + if Contract_repr.(contract = Implicit delegate) then + get_own_frozen_deposits ctxt ~delegate + else staked_balance ctxt ~delegator:contract ~delegate + + let staking_pseudotokens_balance = staking_pseudotokens_balance + + let get_frozen_deposits_pseudotokens = get_frozen_deposits_pseudotokens + + let get_frozen_deposits_staked_tez = get_frozen_deposits_staked_tez +end diff --git a/src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.mli b/src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.mli new file mode 100644 index 000000000000..727e3e201dee --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/staking_pseudotokens_storage.mli @@ -0,0 +1,92 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module is responsible for maintaining the + {!Storage.Contract.Frozen_deposits_pseudotokens} and + {!Storage.Contract.Staking_pseudotokens} tables. *) + +(** [stake ctxt ~contract ~delegate amount] credits the [contract]'s + staking pseudotokens and the [delegate]'s frozen deposits pseudotokens by + an amount of pseudotokens corresponding to [amount] using [delegate]'s + staked frozen deposits pseudotokens/tez rate. + + This function must be called on "stake" **before** transferring tez to + [delegate]'s frozen deposits. + + [delegate] must be [contract]'s delegate. *) +val stake : + Raw_context.t -> + contract:Contract_repr.t -> + delegate:Signature.Public_key_hash.t -> + Tez_repr.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [request_unstake ctxt ~contract ~delegate amount] debits the [contract]'s + staking pseudotokens and the [delegate]'s frozen deposits pseudotokens by + an amount of pseudotokens corresponding to [amount] using [delegate]'s + staked frozen deposits pseudotokens/tez rate capped by [contract]'s staking + pseudotokens balance. + + It returns the tez amount corresponding to the debited pseudotokens. + + Resulting context do not make sense if [delegate] is not [contract]'s + delegate. *) +val request_unstake : + Raw_context.t -> + contract:Contract_repr.t -> + delegate:Signature.Public_key_hash.t -> + Tez_repr.t -> + (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t + +module For_RPC : sig + (** [staked_balance ctxt ~contract ~delegate] returns [contract]'s + current staked tez. + For delegate, it is their own frozen deposits. + For delegators, their staking balance in pseudotokens is converted into tez + using [delegate]'s staked frozen deposits tez/pseudotokens rate. + + The given [delegate] should be [contract]'s delegate. Otherwise the given + [Tez.t] amount will not make sense. *) + val staked_balance : + Raw_context.t -> + contract:Contract_repr.t -> + delegate:Signature.Public_key_hash.t -> + Tez_repr.t tzresult Lwt.t + + val staking_pseudotokens_balance : + Raw_context.t -> + delegator:Contract_repr.t -> + Staking_pseudotoken_repr.t tzresult Lwt.t + + val get_frozen_deposits_pseudotokens : + Raw_context.t -> + delegate:Signature.public_key_hash -> + Staking_pseudotoken_repr.t tzresult Lwt.t + + val get_frozen_deposits_staked_tez : + Raw_context.t -> + delegate:Signature.public_key_hash -> + Tez_repr.t tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/state_hash.ml b/src/proto_020_PsParisC/lib_protocol/state_hash.ml new file mode 100644 index 000000000000..a39ce4a21127 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/state_hash.ml @@ -0,0 +1,44 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let random_state_hash = "\076\064\204" (* rng(53): never used... *) + +module H = + Blake2B.Make + (Base58) + (struct + let name = "random" + + let title = "A random generation state" + + let b58check_prefix = random_state_hash + + let size = None + end) + +include H +include Path_encoding.Make_hex (H) + +let () = Base58.check_encoded_prefix b58check_encoding "rng" 53 diff --git a/src/proto_020_PsParisC/lib_protocol/state_hash.mli b/src/proto_020_PsParisC/lib_protocol/state_hash.mli new file mode 100644 index 000000000000..7ae77f3a0c42 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/state_hash.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A specialized Blake2B implementation for hashing internal states of random + number generators. *) + +include S.HASH diff --git a/src/proto_020_PsParisC/lib_protocol/storage.ml b/src/proto_020_PsParisC/lib_protocol/storage.ml new file mode 100644 index 000000000000..ad2b76ee94cb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage.ml @@ -0,0 +1,2308 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Storage_functors +open Storage_sigs + +module Encoding = struct + module UInt16 : VALUE with type t = int = struct + type t = int + + let encoding = Data_encoding.uint16 + end + + module Int32 : VALUE with type t = Int32.t = struct + type t = Int32.t + + let encoding = Data_encoding.int32 + end + + module Int64 : VALUE with type t = Int64.t = struct + type t = Int64.t + + let encoding = Data_encoding.int64 + end + + module Z : VALUE with type t = Z.t = struct + type t = Z.t + + let encoding = Data_encoding.z + end + + module Manager_counter : VALUE with type t = Manager_counter_repr.t = struct + type t = Manager_counter_repr.t + + let encoding = Manager_counter_repr.encoding_for_storage + end +end + +module Int31_index : INDEX with type t = int = struct + type t = int + + let path_length = 1 + + let to_path c l = string_of_int c :: l + + let of_path = function [] | _ :: _ :: _ -> None | [c] -> int_of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } +end + +module Make_index (H : Storage_description.INDEX) : + INDEX with type t = H.t and type 'a ipath = 'a * H.t = struct + include H + + type 'a ipath = 'a * t + + let args = Storage_description.One {rpc_arg; encoding; compare} +end + +module type Simple_single_data_storage = sig + type value + + val get : Raw_context.t -> value tzresult Lwt.t + + val update : Raw_context.t -> value -> Raw_context.t tzresult Lwt.t + + val init : Raw_context.t -> value -> Raw_context.t tzresult Lwt.t +end + +module Block_round : Simple_single_data_storage with type value = Round_repr.t = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["block_round"] + end) + (Round_repr) + +module Tenderbake = struct + module First_level_of_protocol = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["first_level_of_protocol"] + end) + (Raw_level_repr) + + module Branch = struct + type t = Block_hash.t * Block_payload_hash.t + + let encoding = + Data_encoding.( + obj2 + (req "grand_parent_hash" Block_hash.encoding) + (req "predecessor_payload" Block_payload_hash.encoding)) + end + + module Attestation_branch = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["attestation_branch"] + end) + (Branch) + + module Forbidden_delegates = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["forbidden_delegates"] + end) + (Signature.Public_key_hash.Set) +end + +(** Contracts handling *) + +type missed_attestations_info = {remaining_slots : int; missed_levels : int} + +module Missed_attestations_info = struct + type t = missed_attestations_info + + let encoding = + let open Data_encoding in + conv + (fun {remaining_slots; missed_levels} -> (remaining_slots, missed_levels)) + (fun (remaining_slots, missed_levels) -> {remaining_slots; missed_levels}) + (obj2 (req "remaining_slots" int31) (req "missed_levels" int31)) +end + +(* TODO #6918: move closer to its only use left after P *) +module Slashed_deposits_history = struct + type slashed_percentage = Percentage.t + + (* invariant: sorted list *) + type t = (Cycle_repr.t * slashed_percentage) list + + let encoding = + let open Data_encoding in + list + (obj2 + (req "cycle" Cycle_repr.encoding) + (req "slashed_percentage" Percentage.encoding)) + + let add cycle percentage history = + let rec loop rev_prefix = function + | (c, p) :: tl when Cycle_repr.(cycle = c) -> + let p = Percentage.add_bounded p percentage in + (* cycle found, do not change the order *) + List.rev_append rev_prefix ((c, p) :: tl) + | ((c, _) as hd) :: tl when Cycle_repr.(cycle > c) -> + (* [cycle] must be inserted later *) + loop (hd :: rev_prefix) tl + | suffix -> + (* [cycle] between [rev_prefix] and [suffix] *) + List.rev_append rev_prefix ((cycle, percentage) :: suffix) + in + loop [] history + + let rec get cycle = function + | (c, p) :: _ when Cycle_repr.(cycle = c) -> p + | (c, _) :: tl when Cycle_repr.(cycle > c) -> get cycle tl + | _ -> Percentage.p0 +end + +(* TODO #6918: Remove after P *) +module Slashed_deposits_history__Oxford = struct + include Slashed_deposits_history + + let encoding = + let open Data_encoding in + list + (obj2 + (req "cycle" Cycle_repr.encoding) + (req "slashed_percentage" Percentage.encoding_legacy_in_o)) +end + +module Unstake_request = struct + type request = Cycle_repr.t * Tez_repr.t + + type requests = request list + + type t = {delegate : Signature.Public_key_hash.t; requests : requests} + + let request_encoding = + let open Data_encoding in + obj2 + (req "cycle" Cycle_repr.encoding) + (req "requested_amount" Tez_repr.encoding) + + let requests_encoding = Data_encoding.list request_encoding + + let encoding = + let open Data_encoding in + conv + (fun {delegate; requests} -> (delegate, requests)) + (fun (delegate, requests) -> {delegate; requests}) + (obj2 + (req "delegate" Contract_repr.implicit_encoding) + (req "requests" requests_encoding)) + + let add cycle amount requests = + let open Result_syntax in + let rec loop rev_prefix = function + | [] -> + (* cycle does not exist -> add at the head *) + Ok ((cycle, amount) :: requests) + | (c, a) :: tl when Cycle_repr.(c = cycle) -> + let+ a = Tez_repr.(a +? amount) in + (* cycle found, do not change the order *) + List.rev_append rev_prefix ((c, a) :: tl) + | hd :: tl -> loop (hd :: rev_prefix) tl + in + loop [] requests +end + +module Contract = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["contracts"] + end) + + module Global_counter : + Simple_single_data_storage with type value = Manager_counter_repr.t = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["global_counter"] + end) + (Encoding.Manager_counter) + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Contract_repr.Index)) + + let fold = Indexed_context.fold_keys + + let list = Indexed_context.keys + + type local_context = Indexed_context.local_context + + let with_local_context = Indexed_context.with_local_context + + module Spendable_balance = + Indexed_context.Make_map + (Registered) + (struct + let name = ["balance"] + end) + (Tez_repr) + + module Missed_attestations = + Indexed_context.Make_map + (Registered) + (struct + let name = ["missed_attestations"] + end) + (Missed_attestations_info) + + module Manager = + Indexed_context.Make_map + (Registered) + (struct + let name = ["manager"] + end) + (Manager_repr) + + module Consensus_key = + Indexed_context.Make_map + (Registered) + (struct + let name = ["consensus_key"; "active"] + end) + (Signature.Public_key) + + module Staking_parameters = + Indexed_context.Make_map + (Registered) + (struct + let name = ["staking_parameters"; "active"] + end) + (Staking_parameters_repr) + + module Delegate = + Indexed_context.Make_map + (Registered) + (struct + let name = ["delegate"] + end) + (Signature.Public_key_hash) + + module Inactive_delegate = + Indexed_context.Make_set + (Registered) + (struct + let name = ["inactive_delegate"] + end) + + module Delegate_last_cycle_before_deactivation = + Indexed_context.Make_map + (Registered) + (struct + (* FIXME? Change the key name to reflect the functor's name *) + let name = ["delegate_desactivation"] + end) + (Cycle_repr) + + module Delegated = + Make_data_set_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["delegated"] + end)) + (Make_index (Contract_repr.Index)) + + module Counter = + Indexed_context.Make_map + (Registered) + (struct + let name = ["counter"] + end) + (Encoding.Manager_counter) + + (* Consume gas for serialization and deserialization of expr in this + module *) + module Make_carbonated_map_expr (N : Storage_sigs.NAME) : + Storage_sigs.Non_iterable_indexed_carbonated_data_storage + with type key = Contract_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t = struct + module I = + Indexed_context.Make_carbonated_map (Registered) (N) + (struct + type t = Script_repr.lazy_expr + + let encoding = Script_repr.lazy_expr_encoding + end) + + type context = I.context + + type key = I.key + + type value = I.value + + let mem = I.mem + + let remove_existing = I.remove_existing + + let remove = I.remove + + let consume_deserialize_gas ctxt value = + Raw_context.consume_gas ctxt (Script_repr.force_decode_cost value) + + let consume_serialize_gas ctxt value = + Raw_context.consume_gas ctxt (Script_repr.force_bytes_cost value) + + let get ctxt contract = + let open Lwt_result_syntax in + let* ctxt, value = I.get ctxt contract in + let*? ctxt = consume_deserialize_gas ctxt value in + return (ctxt, value) + + let find ctxt contract = + let open Lwt_result_syntax in + let* ctxt, value_opt = I.find ctxt contract in + match value_opt with + | None -> return (ctxt, None) + | Some value -> + let*? ctxt = consume_deserialize_gas ctxt value in + return (ctxt, value_opt) + + let update ctxt contract value = + let open Lwt_result_syntax in + let*? ctxt = consume_serialize_gas ctxt value in + I.update ctxt contract value + + let add_or_remove ctxt contract value_opt = + let open Lwt_result_syntax in + match value_opt with + | None -> I.add_or_remove ctxt contract None + | Some value -> + let*? ctxt = consume_serialize_gas ctxt value in + I.add_or_remove ctxt contract value_opt + + let init ctxt contract value = + let open Lwt_result_syntax in + let*? ctxt = consume_serialize_gas ctxt value in + I.init ctxt contract value + + let add ctxt contract value = + let open Lwt_result_syntax in + let*? ctxt = consume_serialize_gas ctxt value in + I.add ctxt contract value + + let keys_unaccounted = I.keys_unaccounted + end + + module Code = Make_carbonated_map_expr (struct + let name = ["code"] + end) + + module Storage = Make_carbonated_map_expr (struct + let name = ["storage"] + end) + + module Paid_storage_space = + Indexed_context.Make_map + (Registered) + (struct + let name = ["paid_bytes"] + end) + (Encoding.Z) + + module Used_storage_space = + Indexed_context.Make_map + (Registered) + (struct + let name = ["used_bytes"] + end) + (Encoding.Z) + + module Unstaked_frozen_deposits = + Indexed_context.Make_map + (Registered) + (struct + let name = ["unstaked_frozen_deposits"] + end) + (Unstaked_frozen_deposits_repr) + + module Unstake_requests = + Indexed_context.Make_map + (Registered) + (struct + let name = ["unstake_requests"] + end) + (Unstake_request) + + module Frozen_deposits_pseudotokens = + Indexed_context.Make_map + (Registered) + (struct + let name = ["frozen_deposits_pseudotokens"] + end) + (Staking_pseudotoken_repr) + + module Staking_pseudotokens = + Indexed_context.Make_map + (Registered) + (struct + let name = ["staking_pseudotokens"] + end) + (Staking_pseudotoken_repr) + + module Frozen_deposits_limit = + Indexed_context.Make_map + (Registered) + (struct + let name = ["frozen_deposits_limit"] + end) + (Tez_repr) + + (* TODO #6918: Remove after P *) + module Slashed_deposits__Oxford = + Indexed_context.Make_map + (Ghost) + (struct + let name = ["slashed_deposits"] + end) + (Slashed_deposits_history__Oxford) + + module Bond_id_index = + Make_indexed_subcontext + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["bond_id_index"] + end)) + (Make_index (Bond_id_repr.Index)) + + module Frozen_bonds = + Bond_id_index.Make_carbonated_map + (Registered) + (struct + let name = ["frozen_bonds"] + end) + (Tez_repr) + + let fold_bond_ids = Bond_id_index.fold_keys + + module Total_frozen_bonds = + Indexed_context.Make_map + (Registered) + (struct + let name = ["total_frozen_bonds"] + end) + (Tez_repr) + + module Total_supply = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["total_supply"] + end) + (Tez_repr) +end + +module type NEXT = sig + type id + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t +end + +module Global_constants = struct + module Map : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Script_expr_hash.t + and type value = Script_repr.expr = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["global_constant"] + end)) + (Make_index (Script_expr_hash)) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) +end + +(** Big maps handling *) + +module Big_map = struct + type id = Lazy_storage_kind.Big_map.Id.t + + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["big_maps"] + end) + + module Next : NEXT with type id := id = struct + module Storage = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["next"] + end) + (Lazy_storage_kind.Big_map.Id) + + let incr ctxt = + let open Lwt_result_syntax in + let* i = Storage.get ctxt in + let* ctxt = Storage.update ctxt (Lazy_storage_kind.Big_map.Id.next i) in + return (ctxt, i) + + let init ctxt = Storage.init ctxt Lazy_storage_kind.Big_map.Id.init + end + + module Index = Lazy_storage_kind.Big_map.Id + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Index)) + + let rpc_arg = Index.rpc_arg + + let fold = Indexed_context.fold_keys + + let list = Indexed_context.keys + + let remove ctxt n = Indexed_context.remove ctxt n + + let copy ctxt ~from ~to_ = Indexed_context.copy ctxt ~from ~to_ + + type key = Raw_context.t * Index.t + + module Total_bytes = + Indexed_context.Make_map + (Registered) + (struct + let name = ["total_bytes"] + end) + (Encoding.Z) + + module Key_type = + Indexed_context.Make_map + (Registered) + (struct + let name = ["key_type"] + end) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) + + module Value_type = + Indexed_context.Make_map + (Registered) + (struct + let name = ["value_type"] + end) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) + + module Contents = struct + module I = + Storage_functors.Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["contents"] + end)) + (Make_index (Script_expr_hash)) + (struct + type t = Script_repr.expr + + let encoding = Script_repr.expr_encoding + end) + + type context = I.context + + type key = I.key + + type value = I.value + + let mem = I.mem + + let remove_existing = I.remove_existing + + let remove = I.remove + + let update = I.update + + let add_or_remove = I.add_or_remove + + let init = I.init + + let add = I.add + + let list_key_values = I.list_key_values + + let consume_deserialize_gas ctxt value = + Raw_context.consume_gas ctxt (Script_repr.deserialized_cost value) + + let get ctxt contract = + let open Lwt_result_syntax in + let* ctxt, value = I.get ctxt contract in + let*? ctxt = consume_deserialize_gas ctxt value in + return (ctxt, value) + + let find ctxt contract = + let open Lwt_result_syntax in + let* ctxt, value_opt = I.find ctxt contract in + match value_opt with + | None -> return (ctxt, None) + | Some value -> + let*? ctxt = consume_deserialize_gas ctxt value in + return (ctxt, value_opt) + + let keys_unaccounted = I.keys_unaccounted + end +end + +module Sapling = struct + type id = Lazy_storage_kind.Sapling_state.Id.t + + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["sapling"] + end) + + module Next = struct + module Storage = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["next"] + end) + (Lazy_storage_kind.Sapling_state.Id) + + let incr ctxt = + let open Lwt_result_syntax in + let* i = Storage.get ctxt in + let* ctxt = + Storage.update ctxt (Lazy_storage_kind.Sapling_state.Id.next i) + in + return (ctxt, i) + + let init ctxt = Storage.init ctxt Lazy_storage_kind.Sapling_state.Id.init + end + + module Index = Lazy_storage_kind.Sapling_state.Id + + let rpc_arg = Index.rpc_arg + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Index)) + + let remove ctxt n = Indexed_context.remove ctxt n + + let copy ctxt ~from ~to_ = Indexed_context.copy ctxt ~from ~to_ + + module Total_bytes = + Indexed_context.Make_map + (Registered) + (struct + let name = ["total_bytes"] + end) + (Encoding.Z) + + module Commitments_size = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments_size"] + end) + (Encoding.Int64) + + module Memo_size = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["memo_size"] + end) + (Sapling_repr.Memo_size) + + module Commitments : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Hash.t = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + Int64.of_string_opt hash + |> Result.of_option ~error:"Cannot parse node position" + in + RPC_arg.make + ~descr:"The position of a node in a sapling commitment tree" + ~name:"sapling_node_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_node_position" + ~title:"Sapling node position" + ~description: + "The position of a node in a sapling commitment tree" + Data_encoding.int64 + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (Sapling.Hash) + + let commitments_init ctx id = + let open Lwt_syntax in + let+ ctx, (_id : id) = + Indexed_context.Raw_context.remove (ctx, id) ["commitments"] + in + ctx + + module Ciphertexts : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Ciphertext.t = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["ciphertexts"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + Int64.of_string_opt hash + |> Result.of_option ~error:"Cannot parse ciphertext position" + in + RPC_arg.make + ~descr:"The position of a sapling ciphertext" + ~name:"sapling_ciphertext_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_ciphertext_position" + ~title:"Sapling ciphertext position" + ~description:"The position of a sapling ciphertext" + Data_encoding.int64 + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (Sapling.Ciphertext) + + let ciphertexts_init ctx id = + let open Lwt_syntax in + let+ ctx, (_id : id) = + Indexed_context.Raw_context.remove (ctx, id) ["ciphertexts"] + in + ctx + + module Nullifiers_size = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nullifiers_size"] + end) + (Encoding.Int64) + + (* For sequential access when building a diff *) + module Nullifiers_ordered : + Non_iterable_indexed_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Nullifier.t = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nullifiers_ordered"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + Int64.of_string_opt hash + |> Result.of_option ~error:"Cannot parse nullifier position" + in + RPC_arg.make + ~descr:"A sapling nullifier position" + ~name:"sapling_nullifier_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_nullifier_position" + ~title:"Sapling nullifier position" + ~description:"Sapling nullifier position" + Data_encoding.int64 + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (Sapling.Nullifier) + + (* Check membership in O(1) for verify_update *) + module Nullifiers_hashed = + Make_carbonated_data_set_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nullifiers_hashed"] + end)) + (Make_index (struct + type t = Sapling.Nullifier.t + + let encoding = Sapling.Nullifier.encoding + + let of_string hexstring = + Option.bind + (Hex.to_bytes (`Hex hexstring)) + (Data_encoding.Binary.of_bytes_opt encoding) + |> Result.of_option ~error:"Cannot parse sapling nullifier" + + let to_string nf = + let b = Data_encoding.Binary.to_bytes_exn encoding nf in + let (`Hex hexstring) = Hex.of_bytes b in + hexstring + + let rpc_arg = + RPC_arg.make + ~descr:"A sapling nullifier" + ~name:"sapling_nullifier" + ~construct:to_string + ~destruct:of_string + () + + let compare = Sapling.Nullifier.compare + + let path_length = 1 + + let to_path c l = to_string c :: l + + let of_path = function + | [c] -> Result.to_option (of_string c) + | _ -> None + end)) + + let nullifiers_init ctx id = + let open Lwt_syntax in + let* ctx = Nullifiers_size.add (ctx, id) Int64.zero in + let* ctx, id = + Indexed_context.Raw_context.remove (ctx, id) ["nullifiers_ordered"] + in + let+ ctx, (_id : id) = + Indexed_context.Raw_context.remove (ctx, id) ["nullifiers_hashed"] + in + ctx + + module Roots : + Non_iterable_indexed_data_storage + with type t := Raw_context.t * id + and type key = int32 + and type value = Sapling.Hash.t = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["roots"] + end)) + (Make_index (struct + type t = int32 + + let rpc_arg = + let construct = Int32.to_string in + let destruct hash = + Int32.of_string_opt hash + |> Result.of_option ~error:"Cannot parse nullifier position" + in + RPC_arg.make + ~descr:"A sapling root" + ~name:"sapling_root" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "sapling_root" + ~title:"Sapling root" + ~description:"Sapling root" + Data_encoding.int32 + + let compare = Compare.Int32.compare + + let path_length = 1 + + let to_path c l = Int32.to_string c :: l + + let of_path = function [c] -> Int32.of_string_opt c | _ -> None + end)) + (Sapling.Hash) + + module Roots_pos = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["roots_pos"] + end) + (Encoding.Int32) + + module Roots_level = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["roots_level"] + end) + (Raw_level_repr) +end + +module Public_key_hash = struct + open Signature + include Signature.Public_key_hash + module Path_Ed25519 = Path_encoding.Make_hex (Ed25519.Public_key_hash) + module Path_Secp256k1 = Path_encoding.Make_hex (Secp256k1.Public_key_hash) + module Path_P256 = Path_encoding.Make_hex (P256.Public_key_hash) + module Path_Bls = Path_encoding.Make_hex (Bls.Public_key_hash) + + let to_path (key : public_key_hash) l = + match key with + | Ed25519 h -> "ed25519" :: Path_Ed25519.to_path h l + | Secp256k1 h -> "secp256k1" :: Path_Secp256k1.to_path h l + | P256 h -> "p256" :: Path_P256.to_path h l + | Bls h -> "bls" :: Path_Bls.to_path h l + + let of_path : _ -> public_key_hash option = function + | "ed25519" :: rest -> ( + match Path_Ed25519.of_path rest with + | Some pkh -> Some (Ed25519 pkh) + | None -> None) + | "secp256k1" :: rest -> ( + match Path_Secp256k1.of_path rest with + | Some pkh -> Some (Secp256k1 pkh) + | None -> None) + | "p256" :: rest -> ( + match Path_P256.of_path rest with + | Some pkh -> Some (P256 pkh) + | None -> None) + | "bls" :: rest -> ( + match Path_Bls.of_path rest with + | Some pkh -> Some (Bls pkh) + | None -> None) + | _ -> None + + let path_length = + let l1 = Path_Ed25519.path_length + and l2 = Path_Secp256k1.path_length + and l3 = Path_P256.path_length + and l4 = Path_Bls.path_length in + assert (Compare.Int.(l1 = l2 && l2 = l3 && l3 = l4)) ; + l1 + 1 +end + +module Public_key_hash_index = Make_index (Public_key_hash) + +module Protocol_hash_with_path_encoding = struct + include Protocol_hash + include Path_encoding.Make_hex (Protocol_hash) +end + +module Delegates = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["delegates"] + end)) + (Public_key_hash_index) + +module Consensus_keys = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["consensus_keys"] + end)) + (Public_key_hash_index) + +module Pending_denunciations = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["denunciations"] + end)) + (Public_key_hash_index) + (Denunciations_repr) + +module Slashed_deposits = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["slashed_deposits"] + end)) + (Public_key_hash_index) + (Slashed_deposits_history) + +(** Per cycle storage *) + +(* TODO #6957: Remove this from protocol Q. *) +type denounced__Oxford = {for_double_attesting : bool; for_double_baking : bool} + +type denounced = { + for_double_preattesting : bool; + for_double_attesting : bool; + for_double_baking : bool; +} + +let default_denounced = + { + for_double_preattesting = false; + for_double_attesting = false; + for_double_baking = false; + } + +module Cycle = struct + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["cycle"] + end)) + (Make_index (Cycle_repr.Index)) + + module Already_denounced = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["already_denounced"] + end)) + (Pair + (Pair + (Make_index + (Raw_level_repr.Index)) + (Make_index (Round_repr.Index))) + (Public_key_hash_index)) + (struct + type t = denounced + + let encoding = + let open Data_encoding in + conv + (fun { + for_double_preattesting; + for_double_attesting; + for_double_baking; + } -> + (for_double_preattesting, for_double_attesting, for_double_baking)) + (fun ( for_double_preattesting, + for_double_attesting, + for_double_baking ) -> + {for_double_preattesting; for_double_attesting; for_double_baking}) + (obj3 + (req "for_double_preattesting" bool) + (req "for_double_attesting" bool) + (req "for_double_baking" bool)) + end) + + (* TODO #6957: Remove this from protocol Q. *) + module Already_denounced__Oxford = + Make_indexed_data_storage + (Make_subcontext (Ghost) (Indexed_context.Raw_context) + (struct + let name = ["slashed_deposits"] + end)) + (Pair (Make_index (Raw_level_repr.Index)) (Public_key_hash_index)) + (struct + type t = denounced__Oxford + + let encoding = + let open Data_encoding in + conv + (fun ({for_double_attesting; for_double_baking} : denounced__Oxford) -> + (for_double_attesting, for_double_baking)) + (fun (for_double_attesting, for_double_baking) -> + {for_double_attesting; for_double_baking}) + (obj2 + (req "for_double_attesting" bool) + (req "for_double_baking" bool)) + end) + + module Selected_stake_distribution = + Indexed_context.Make_map + (Registered) + (struct + let name = ["selected_stake_distribution"] + end) + (struct + type t = (Signature.Public_key_hash.t * Stake_repr.t) list + + let encoding = + Data_encoding.( + Variable.list + (obj2 + (req "baker" Signature.Public_key_hash.encoding) + (req "active_stake" Stake_repr.encoding))) + end) + + module Total_active_stake = + Indexed_context.Make_map + (Registered) + (struct + let name = ["total_active_stake"] + end) + (Stake_repr) + + module Delegate_sampler_state = + Indexed_context.Make_map + (Registered) + (struct + let name = ["delegate_sampler_state"] + end) + (struct + type t = Raw_context.consensus_pk Sampler.t + + let encoding = Sampler.encoding Raw_context.consensus_pk_encoding + end) + + module Issuance_bonus = + Indexed_context.Make_map + (Registered) + (struct + let name = ["issuance_bonus"] + end) + (Issuance_bonus_repr) + + module Issuance_coeff = + Indexed_context.Make_map + (Registered) + (struct + let name = ["issuance_coeff"] + end) + (struct + type t = Q.t + + let encoding = + Data_encoding.( + conv_with_guard + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> + if Compare.Z.(num > Z.zero && den > Z.zero) then + Ok (Q.make num den) + else + Error + "Invalid Reward Coefficient: only positive values allowed") + (obj2 (req "numerator" n) (req "denominator" n))) + end) + + type unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + } + + type nonce_status = + | Unrevealed of unrevealed_nonce + | Revealed of Seed_repr.nonce + + let nonce_status_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Unrevealed" + (tup2 Nonce_hash.encoding Signature.Public_key_hash.encoding) + (function + | Unrevealed {nonce_hash; delegate} -> Some (nonce_hash, delegate) + | _ -> None) + (fun (nonce_hash, delegate) -> Unrevealed {nonce_hash; delegate}); + case + (Tag 1) + ~title:"Revealed" + Seed_repr.nonce_encoding + (function Revealed nonce -> Some nonce | _ -> None) + (fun nonce -> Revealed nonce); + ] + + module Nonce = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["nonces"] + end)) + (Make_index (Raw_level_repr.Index)) + (struct + type t = nonce_status + + let encoding = nonce_status_encoding + end) + + module Seed = + Indexed_context.Make_map + (Registered) + (struct + let name = ["random_seed"] + end) + (struct + type t = Seed_repr.seed + + let encoding = Seed_repr.seed_encoding + end) + + module Pending_consensus_keys = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["pending_consensus_keys"] + end)) + (Make_index (Contract_repr.Index)) + (Signature.Public_key) + + module Pending_staking_parameters = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["pending_staking_parameters"] + end)) + (Make_index (Contract_repr.Index)) + (Staking_parameters_repr) +end + +module Already_denounced = Cycle.Already_denounced +module Already_denounced__Oxford = Cycle.Already_denounced__Oxford +module Pending_consensus_keys = Cycle.Pending_consensus_keys +module Pending_staking_parameters = Cycle.Pending_staking_parameters + +module Stake = struct + module Staking_balance = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["staking_balance"] + end)) + (Public_key_hash_index) + (Full_staking_balance_repr) + + module Active_delegates_with_minimal_stake = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["active_delegates_with_minimal_stake"] + end)) + (Public_key_hash_index) + + module Selected_distribution_for_cycle = Cycle.Selected_stake_distribution + module Total_active_stake = Cycle.Total_active_stake +end + +module Delegate_sampler_state = Cycle.Delegate_sampler_state +module Issuance_bonus = Cycle.Issuance_bonus +module Issuance_coeff = Cycle.Issuance_coeff + +(** Votes *) + +module Vote = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["votes"] + end) + + module Pred_period_kind = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["pred_period_kind"] + end) + (struct + type t = Voting_period_repr.kind + + let encoding = Voting_period_repr.kind_encoding + end) + + module Current_period = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["current_period"] + end) + (struct + type t = Voting_period_repr.t + + let encoding = Voting_period_repr.encoding + end) + + module Participation_ema = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["participation_ema"] + end) + (Encoding.Int32) + + module Current_proposal = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["current_proposal"] + end) + (Protocol_hash) + + module Voting_power_in_listings = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["voting_power_in_listings"] + end) + (Encoding.Int64) + + module Listings = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["listings"] + end)) + (Public_key_hash_index) + (Encoding.Int64) + + module Proposals = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["proposals"] + end)) + (Pair + (Make_index + (Protocol_hash_with_path_encoding)) + (Public_key_hash_index)) + + module Proposals_count = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["proposals_count"] + end)) + (Public_key_hash_index) + (Encoding.UInt16) + + module Ballots = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["ballots"] + end)) + (Public_key_hash_index) + (struct + type t = Vote_repr.ballot + + let encoding = Vote_repr.ballot_encoding + end) +end + +module type FOR_CYCLE = sig + val init : + Raw_context.t -> + Cycle_repr.t -> + Seed_repr.seed -> + Raw_context.t tzresult Lwt.t + + val mem : Raw_context.t -> Cycle_repr.t -> bool Lwt.t + + val get : Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + + val update : + Raw_context.t -> + Cycle_repr.t -> + Seed_repr.seed -> + Seed_repr.seed_status -> + Raw_context.t tzresult Lwt.t + + val remove_existing : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t +end + +(** Seed *) + +module Seed_status = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["seed_status"] + end) + (struct + type t = Seed_repr.seed_status + + let encoding = Seed_repr.seed_status_encoding + end) + +module Seed = struct + type unrevealed_nonce = Cycle.unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + } + + type nonce_status = Cycle.nonce_status = + | Unrevealed of unrevealed_nonce + | Revealed of Seed_repr.nonce + + module Nonce : + Non_iterable_indexed_data_storage + with type key := Level_repr.t + and type value := nonce_status + and type t := Raw_context.t = struct + open Level_repr + + type context = Raw_context.t + + let mem ctxt (l : Level_repr.t) = Cycle.Nonce.mem (ctxt, l.cycle) l.level + + let get ctxt (l : Level_repr.t) = Cycle.Nonce.get (ctxt, l.cycle) l.level + + let find ctxt (l : Level_repr.t) = Cycle.Nonce.find (ctxt, l.cycle) l.level + + let update ctxt (l : Level_repr.t) v = + Cycle.Nonce.update (ctxt, l.cycle) l.level v + + let init ctxt (l : Level_repr.t) v = + Cycle.Nonce.init (ctxt, l.cycle) l.level v + + let add ctxt (l : Level_repr.t) v = + Cycle.Nonce.add (ctxt, l.cycle) l.level v + + let add_or_remove ctxt (l : Level_repr.t) v = + Cycle.Nonce.add_or_remove (ctxt, l.cycle) l.level v + + let remove_existing ctxt (l : Level_repr.t) = + Cycle.Nonce.remove_existing (ctxt, l.cycle) l.level + + let remove ctxt (l : Level_repr.t) = + Cycle.Nonce.remove (ctxt, l.cycle) l.level + end + + module VDF_setup = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["vdf_challenge"] + end) + (struct + type t = Seed_repr.vdf_setup + + let encoding = Seed_repr.vdf_setup_encoding + end) + + module For_cycle : FOR_CYCLE = struct + let init ctxt cycle seed = + let open Lwt_result_syntax in + let* ctxt = Cycle.Seed.init ctxt cycle seed in + let*! ctxt = Seed_status.add ctxt Seed_repr.RANDAO_seed in + return ctxt + + let mem = Cycle.Seed.mem + + let get = Cycle.Seed.get + + let update ctxt cycle seed status = + let open Lwt_result_syntax in + let* ctxt = Cycle.Seed.update ctxt cycle seed in + Seed_status.update ctxt status + + let remove_existing = Cycle.Seed.remove_existing + end + + let get_status = Seed_status.get +end + +(** Commitments *) + +module Commitments = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["commitments"] + end)) + (Make_index (Blinded_public_key_hash.Index)) + (Tez_repr) + +(** Ramp up rewards... *) + +module Ramp_up = struct + type reward = { + baking_reward_fixed_portion : Tez_repr.t; + baking_reward_bonus_per_slot : Tez_repr.t; + attesting_reward_per_slot : Tez_repr.t; + } + + module Rewards = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["ramp_up"; "rewards"] + end)) + (Make_index (Cycle_repr.Index)) + (struct + type t = reward + + let encoding = + Data_encoding.( + conv + (fun { + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + } -> + ( baking_reward_fixed_portion, + baking_reward_bonus_per_slot, + attesting_reward_per_slot )) + (fun ( baking_reward_fixed_portion, + baking_reward_bonus_per_slot, + attesting_reward_per_slot ) -> + { + baking_reward_fixed_portion; + baking_reward_bonus_per_slot; + attesting_reward_per_slot; + }) + (obj3 + (req "baking_reward_fixed_portion" Tez_repr.encoding) + (req "baking_reward_bonus_per_slot" Tez_repr.encoding) + (req "attesting_reward_per_slot" Tez_repr.encoding))) + end) +end + +module Pending_migration = struct + module Balance_updates = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["pending_migration_balance_updates"] + end) + (struct + type t = Receipt_repr.balance_updates + + let encoding = Receipt_repr.balance_updates_encoding + end) + + module Operation_results = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["pending_migration_operation_results"] + end) + (struct + type t = Migration_repr.origination_result list + + let encoding = Migration_repr.origination_result_list_encoding + end) + + let remove ctxt = + let open Lwt_result_syntax in + let balance_updates ctxt = + let* balance_updates_opt = Balance_updates.find ctxt in + match balance_updates_opt with + | Some balance_updates -> + let*! ctxt = Balance_updates.remove ctxt in + (* When applying balance updates in a migration, we must attach receipts. + The balance updates returned from here will be applied in the first + block of the new protocol. *) + return (ctxt, balance_updates) + | None -> return (ctxt, []) + in + let operation_results ctxt = + let* operation_results_opt = Operation_results.find ctxt in + match operation_results_opt with + | Some operation_results -> + let*! ctxt = Operation_results.remove ctxt in + return (ctxt, operation_results) + | None -> return (ctxt, []) + in + let* ctxt, balance_updates = balance_updates ctxt in + let* ctxt, operation_results = operation_results ctxt in + return (ctxt, balance_updates, operation_results) +end + +module Liquidity_baking = struct + module Toggle_ema = + Make_single_data_storage (Registered) (Raw_context) + (struct + (* The old "escape" name is kept here to avoid migrating this. *) + let name = ["liquidity_baking_escape_ema"] + end) + (Encoding.Int32) + + module Cpmm_address = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["liquidity_baking_cpmm_address"] + end) + (struct + type t = Contract_hash.t + + (* Keeping contract-compatible encoding to avoid migrating this. *) + let encoding = Contract_repr.originated_encoding + end) +end + +module Adaptive_issuance = struct + module Launch_ema = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["adaptive_issuance_ema"] + end) + (Encoding.Int32) + + module Activation = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["adaptive_issuance_launch_cycle"] + end) + (struct + type t = Cycle_repr.t option + + let encoding = Data_encoding.option Cycle_repr.encoding + end) +end + +module Ticket_balance = struct + module Name = struct + let name = ["ticket_balance"] + end + + module Raw_context = Make_subcontext (Registered) (Raw_context) (Name) + + module Paid_storage_space = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["paid_bytes"] + end) + (Encoding.Z) + + module Used_storage_space = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["used_bytes"] + end) + (Encoding.Z) + + module Table_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["table"] + end) + + module Index = Make_index (Ticket_hash_repr.Index) + module Table = + Make_indexed_carbonated_data_storage (Table_context) (Index) (Encoding.Z) +end + +module Sc_rollup = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["smart_rollup"] + end) + + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["index"] + end)) + (Make_index (Sc_rollup_repr.Index)) + + module Make_versioned + (Versioned_value : Sc_rollup_data_version_sig.S) (Data_storage : sig + type context + + type key + + type value = Versioned_value.versioned + + val get : context -> key -> (Raw_context.t * value) tzresult Lwt.t + + val find : + context -> key -> (Raw_context.t * value option) tzresult Lwt.t + + val update : + context -> key -> value -> (Raw_context.t * int) tzresult Lwt.t + + val init : + context -> key -> value -> (Raw_context.t * int) tzresult Lwt.t + + val add : + context -> key -> value -> (Raw_context.t * int * bool) tzresult Lwt.t + + val add_or_remove : + context -> + key -> + value option -> + (Raw_context.t * int * bool) tzresult Lwt.t + end) = + struct + include Data_storage + + type value = Versioned_value.t + + let get ctxt key = + let open Lwt_result_syntax in + let* ctxt, versioned = get ctxt key in + return (ctxt, Versioned_value.of_versioned versioned) + + let find ctxt key = + let open Lwt_result_syntax in + let* ctxt, versioned = find ctxt key in + return (ctxt, Option.map Versioned_value.of_versioned versioned) + + let update ctxt key value = + update ctxt key (Versioned_value.to_versioned value) + + let init ctxt key value = init ctxt key (Versioned_value.to_versioned value) + + let add ctxt key value = add ctxt key (Versioned_value.to_versioned value) + + let add_or_remove ctxt key value = + add_or_remove ctxt key (Option.map Versioned_value.to_versioned value) + end + + module PVM_kind = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["kind"] + end) + (struct + type t = Sc_rollups.Kind.t + + let encoding = Sc_rollups.Kind.encoding + end) + + module Parameters_type = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["parameters_type"] + end) + (struct + type t = Script_repr.lazy_expr + + let encoding = Script_repr.lazy_expr_encoding + end) + + module Genesis_info = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["genesis_info"] + end) + (struct + type t = Sc_rollup_commitment_repr.genesis_info + + let encoding = Sc_rollup_commitment_repr.genesis_info_encoding + end) + + module Inbox = struct + include + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["inbox"] + end) + (struct + type t = Sc_rollup_inbox_repr.versioned + + let encoding = Sc_rollup_inbox_repr.versioned_encoding + end) + + type value = Sc_rollup_inbox_repr.t + + let of_versioned = Sc_rollup_inbox_repr.of_versioned + + let to_versioned = Sc_rollup_inbox_repr.to_versioned + + let get ctxt = + let open Lwt_result_syntax in + let* versioned = get ctxt in + return (of_versioned versioned) + + let find ctxt = + let open Lwt_result_syntax in + let* versioned = find ctxt in + return (Option.map of_versioned versioned) + + let init ctxt value = init ctxt (to_versioned value) + + let update ctxt value = update ctxt (to_versioned value) + + let add ctxt value = + let versioned = to_versioned value in + add ctxt versioned + + let add_or_remove ctxt value = + add_or_remove ctxt (Option.map to_versioned value) + end + + module Last_cemented_commitment = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["last_cemented_commitment"] + end) + (struct + type t = Sc_rollup_commitment_repr.Hash.t + + let encoding = Sc_rollup_commitment_repr.Hash.encoding + end) + + module Staker_index_counter = + Make_single_data_storage (Registered) (Indexed_context.Raw_context) + (struct + let name = ["staker_index_counter"] + end) + (Sc_rollup_staker_index_repr) + + module Staker_index = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["staker_index"] + end)) + (Public_key_hash_index) + (Sc_rollup_staker_index_repr) + + module Stakers = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["stakers"] + end)) + (Make_index (Sc_rollup_staker_index_repr.Index)) + (Raw_level_repr) + + module Commitments_versioned = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments"] + end)) + (Make_index (Sc_rollup_commitment_repr.Hash)) + (struct + type t = Sc_rollup_commitment_repr.versioned + + let encoding = Sc_rollup_commitment_repr.versioned_encoding + end) + + module Commitments = struct + include Commitments_versioned + include Make_versioned (Sc_rollup_commitment_repr) (Commitments_versioned) + end + + module Commitment_indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitment_index"] + end)) + (Make_index (Sc_rollup_commitment_repr.Hash)) + + module Commitment_stakers = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments_stakers"] + end)) + (Make_index (Sc_rollup_commitment_repr.Hash)) + (struct + type t = Sc_rollup_staker_index_repr.t list + + let encoding = Data_encoding.list Sc_rollup_staker_index_repr.encoding + end) + + module Commitments_per_inbox_level = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitments_per_inbox_level"] + end)) + (Make_index (Raw_level_repr.Index)) + (struct + type t = Sc_rollup_commitment_repr.Hash.t list + + let encoding = + Data_encoding.list Sc_rollup_commitment_repr.Hash.encoding + end) + + module Commitment_first_publication_level = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitment_first_publication_level"] + end)) + (Make_index (Raw_level_repr.Index)) + (Raw_level_repr) + + module Commitment_added = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["commitment_added"] + end)) + (Make_index (Sc_rollup_commitment_repr.Hash)) + (Raw_level_repr) + + module Game_info_versioned = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["refutation_game_info"] + end)) + (Make_index (Sc_rollup_game_repr.Index)) + (struct + type t = Sc_rollup_game_repr.versioned + + let encoding = Sc_rollup_game_repr.versioned_encoding + end) + + module Game_info = struct + include Game_info_versioned + include Make_versioned (Sc_rollup_game_repr) (Game_info_versioned) + end + + module Games_per_staker = + Make_indexed_subcontext + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["game"] + end)) + (Public_key_hash_index) + + module Game = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Games_per_staker.Raw_context) + (struct + let name = ["opponents"] + end)) + (Public_key_hash_index) + (struct + type t = Sc_rollup_game_repr.Index.t + + let encoding = Sc_rollup_game_repr.Index.encoding + end) + + module Game_timeout = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["game_timeout"] + end)) + (Make_index (Sc_rollup_game_repr.Index)) + (struct + type t = Sc_rollup_game_repr.timeout + + let encoding = Sc_rollup_game_repr.timeout_encoding + end) + + (** An index used for a SCORU's outbox levels. An outbox level is mapped to + the index through: [outbox_level % sc_rollup_max_active_outbox_levels]. + That way we keep a limited number of entries. The current value of an + entry contains the most recently added level that maps to the index. *) + module Level_index = struct + type t = int32 + + let rpc_arg = + let construct = Int32.to_string in + let destruct hash = + Int32.of_string_opt hash + |> Result.of_option ~error:"Cannot parse level index" + in + RPC_arg.make + ~descr:"The level index for applied outbox message records" + ~name:"level_index" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "level_index" + ~title:"Level index" + ~description:"The level index for applied outbox message records" + Data_encoding.int32 + + let compare = Compare.Int32.compare + + let path_length = 1 + + let to_path c l = Int32.to_string c :: l + + let of_path = function [c] -> Int32.of_string_opt c | _ -> None + end + + module Level_index_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["level_index"] + end)) + (Make_index (Level_index)) + + module Bitset_and_level = struct + type t = Raw_level_repr.t * Bitset.t + + let encoding = + Data_encoding.( + obj2 + (req "level" Raw_level_repr.encoding) + (req "bitset" Bitset.encoding)) + end + + module Applied_outbox_messages = + Level_index_context.Make_carbonated_map + (Registered) + (struct + let name = ["applied_outbox_messages"] + end) + (Bitset_and_level) + + module Whitelist = + Make_carbonated_data_set_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["whitelist"] + end)) + (Public_key_hash_index) + + module Whitelist_paid_storage_space = + Indexed_context.Make_map + (Registered) + (struct + let name = ["whitelist_paid_bytes"] + end) + (Encoding.Z) + + module Whitelist_used_storage_space = + Indexed_context.Make_map + (Registered) + (struct + let name = ["whitelist_use_bytes"] + end) + (Encoding.Z) + + module Last_whitelist_update = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["last_whitelist_update"] + end) + (struct + type t = Sc_rollup_whitelist_repr.last_whitelist_update + + let encoding = Sc_rollup_whitelist_repr.last_whitelist_update_encoding + end) +end + +module Dal = struct + module Raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["dal"] + end) + + (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3113 + + This is only for prototyping. Probably something smarter would be + to index each header directly. *) + (* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3684 + + This storage should be carbonated. *) + module Slot = struct + module Slot_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["slot"] + end) + + module Level_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["level"] + end)) + (Make_index (Raw_level_repr.Index)) + + module Headers = + Level_context.Make_map + (Registered) + (struct + let name = ["slot_headers"] + end) + (struct + type t = Dal_slot_repr.Header.t list + + let encoding = Data_encoding.(list Dal_slot_repr.Header.encoding) + end) + + module History = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["slot_headers_history"] + end) + (struct + type t = Dal_slot_repr.History.t + + let encoding = Dal_slot_repr.History.encoding + end) + end +end + +module Zk_rollup = struct + module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["zk_rollup"] + end)) + (Make_index (Zk_rollup_repr.Index)) + + module Account : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Zk_rollup_repr.t + and type value = Zk_rollup_account_repr.t = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["account"] + end) + (Zk_rollup_account_repr) + + module Pending_list = + Indexed_context.Make_carbonated_map + (Registered) + (struct + let name = ["pending_list"] + end) + (struct + type t = Zk_rollup_repr.pending_list + + let encoding = Zk_rollup_repr.pending_list_encoding + end) + + module Pending_operation : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * Zk_rollup_repr.t + and type key = int64 + and type value = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option = + Make_indexed_carbonated_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["pending_operations"] + end)) + (Make_index (struct + type t = int64 + + let rpc_arg = + let construct = Int64.to_string in + let destruct hash = + Int64.of_string_opt hash + |> Result.of_option + ~error:"Cannot parse pending operation position" + in + RPC_arg.make + ~descr: + "The position of an operation in a pending operations list" + ~name:"zkru_pending_op_position" + ~construct + ~destruct + () + + let encoding = + Data_encoding.def + "zkru_pending_op_position" + ~title:"Zkru pending operation position" + ~description: + "The position of an operation in a pending operations list" + Data_encoding.Compact.(make ~tag_size:`Uint8 int64) + + let compare = Compare.Int64.compare + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function [c] -> Int64.of_string_opt c | _ -> None + end)) + (struct + type t = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option + + let encoding = + Data_encoding.( + tup2 + Zk_rollup_operation_repr.encoding + (option Ticket_hash_repr.encoding)) + end) +end + +module Legacy = struct + module Grand_parent_branch = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["grand_parent_branch"] + end) + (Tenderbake.Branch) +end diff --git a/src/proto_020_PsParisC/lib_protocol/storage.mli b/src/proto_020_PsParisC/lib_protocol/storage.mli new file mode 100644 index 000000000000..2b905fcce5e4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage.mli @@ -0,0 +1,1072 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Typed storage + + This module hides the hierarchical (key x value) database under + pre-allocated typed accessors for all persistent entities of the + tezos context. + + This interface enforces no invariant on the contents of the + database. Its goal is to centralize all accessors in order to have + a complete view over the database contents and avoid key + collisions. *) + +open Storage_sigs + +module type Simple_single_data_storage = sig + type value + + val get : Raw_context.t -> value tzresult Lwt.t + + val update : Raw_context.t -> value -> Raw_context.t tzresult Lwt.t + + val init : Raw_context.t -> value -> Raw_context.t tzresult Lwt.t +end + +module Block_round : Simple_single_data_storage with type value = Round_repr.t + +type missed_attestations_info = {remaining_slots : int; missed_levels : int} + +module Slashed_deposits_history : sig + type slashed_percentage = Percentage.t + + type t = (Cycle_repr.t * slashed_percentage) list + + (** [add cycle percentage history] adds the [percentage] for the [cycle] in + the [history]. + If the cycle exists, the associated percentage is updated and capped at + 100 and the cycle order in the list is unchanged. + If the cycle does not exist, the new pair [(cycle, percentage)] is added + at the beginning of the list. + *) + val add : Cycle_repr.t -> slashed_percentage -> t -> t + + (** [get cycle history] returns the percentage for [cycle] in [history] or + 0 if there is no such cycle. *) + val get : Cycle_repr.t -> t -> slashed_percentage +end + +(* TODO #6918: Remove after P *) +module Slashed_deposits_history__Oxford : + module type of Slashed_deposits_history + +module Unstake_request : sig + type request = Cycle_repr.t * Tez_repr.t + + type requests = request list + + type t = {delegate : Signature.Public_key_hash.t; requests : requests} + + val add : Cycle_repr.t -> Tez_repr.t -> requests -> requests tzresult +end + +module Contract : sig + (** Storage from this submodule must only be accessed through the + module `Contract`. *) + + module Global_counter : + Simple_single_data_storage with type value = Manager_counter_repr.t + + (** The domain of alive contracts *) + val fold : + Raw_context.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Contract_repr.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + val list : Raw_context.t -> Contract_repr.t list Lwt.t + + (** see {!Raw_context_intf.T.local_context} *) + type local_context + + (** see {!Raw_context_intf.T.with_local_context} *) + val with_local_context : + Raw_context.t -> + Contract_repr.t -> + (local_context -> (local_context * 'a) tzresult Lwt.t) -> + (Raw_context.t * 'a) tzresult Lwt.t + + (** The tez possessed by a contract and that can be used. A contract + may also possess tez in frozen deposits. Empty balances (of zero + tez) are only allowed for originated contracts, not for implicit + ones. *) + module Spendable_balance : + Indexed_data_storage_with_local_context + with type key = Contract_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t + and type local_context := local_context + + (** If the value is not set, the delegate didn't miss any attesting + opportunity. If it is set, this value is a record of type + [missed_attestations_info], where: + - [remaining_slots] is the difference between the maximum number of + slots that can be missed and the number of missed slots; + therefore, when the number is positive, it represents the number + of slots that a delegate can still miss before forfeiting its + attesting rewards for the current cycle; when the number is zero + it means rewards are not lost, but no further slots can be + missed anymore; + - [missed_levels] represents the number of missed levels (for + attesting). *) + module Missed_attestations : + Indexed_data_storage + with type key = Contract_repr.t + and type value = missed_attestations_info + and type t := Raw_context.t + + (** The manager of a contract *) + module Manager : + Indexed_data_storage_with_local_context + with type key = Contract_repr.t + and type value = Manager_repr.t + and type t := Raw_context.t + and type local_context := local_context + + (** The active consensus key of a delegate *) + module Consensus_key : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Signature.Public_key.t + and type t := Raw_context.t + + (** The delegate of a contract, if any. *) + module Delegate : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Signature.Public_key_hash.t + and type t := Raw_context.t + + module Staking_parameters : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Staking_parameters_repr.t + and type t := Raw_context.t + + (** All contracts (implicit and originated) that are delegated, if any *) + module Delegated : + Data_set_storage + with type elt = Contract_repr.t + and type t = Raw_context.t * Contract_repr.t + + (** Tez that were part of frozen deposits (either [own_frozen] or + [staked_frozen] in {!Staking_balance}) but have been requested to be + unstaked by a staker. + They won't be part of the stake for future distributions. + For cycles [current_cycle - consensus_rights_delay - max_slashing_period + 1] to + [current_cycle] they are still slashable. + For cycle [current_cycle - consensus_rights_delay - max_slashing_period] they are + not slashable anymore and hence any other older cycles must be squashed + into this one at cycle end. *) + module Unstaked_frozen_deposits : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Unstaked_frozen_deposits_repr.t + and type t := Raw_context.t + + (** The contract's unstake requests that haven't been finalized yet. *) + module Unstake_requests : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Unstake_request.t + and type t := Raw_context.t + + (** The sum of all pseudotokens owned by stakers + corresponding to shares of the [staked_frozen] in {!Staking_balance}. *) + module Frozen_deposits_pseudotokens : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Staking_pseudotoken_repr.t + and type t := Raw_context.t + + (** Share of the contract's delegate frozen deposits the contract owns. *) + module Staking_pseudotokens : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Staking_pseudotoken_repr.t + and type t := Raw_context.t + + (** If there is a value, the frozen balance for the contract won't + exceed it (starting in consensus_rights_delay + 1). *) + module Frozen_deposits_limit : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t + + module Inactive_delegate : + Data_set_storage with type elt = Contract_repr.t and type t = Raw_context.t + + (** The last cycle where the delegate is considered active; that is, + at the next cycle it will be considered inactive. *) + module Delegate_last_cycle_before_deactivation : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Cycle_repr.t + and type t := Raw_context.t + + module Counter : + Indexed_data_storage_with_local_context + with type key = Contract_repr.t + and type value = Manager_counter_repr.t + and type t := Raw_context.t + and type local_context := local_context + + module Code : + Non_iterable_indexed_carbonated_data_storage + with type key = Contract_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t + + module Storage : + Non_iterable_indexed_carbonated_data_storage + with type key = Contract_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t + + (** Current storage space in bytes. + Includes code, global storage and big map elements. *) + module Used_storage_space : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Z.t + and type t := Raw_context.t + + (** Maximal space available without needing to burn new fees. *) + module Paid_storage_space : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Z.t + and type t := Raw_context.t + + (* TODO #6918: Remove after P *) + module Slashed_deposits__Oxford : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Slashed_deposits_history.t + and type t := Raw_context.t + + (** Associates a contract and a bond_id with a bond, i.e. an amount of tez + that is frozen. *) + module Frozen_bonds : + Non_iterable_indexed_carbonated_data_storage + with type key = Bond_id_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t * Contract_repr.t + + val fold_bond_ids : + Raw_context.t * Contract_repr.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(Bond_id_repr.t -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + (** Associates a contract with the total of all its frozen bonds. *) + module Total_frozen_bonds : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t + + (** Stores the amount of tokens currently present on chain *) + module Total_supply : + Single_data_storage with type value = Tez_repr.t and type t := Raw_context.t +end + +module Big_map : sig + type id = Lazy_storage_kind.Big_map.Id.t + + module Next : sig + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + end + + (** The domain of alive big maps *) + val fold : + Raw_context.t -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(id -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + val list : Raw_context.t -> id list Lwt.t + + val remove : Raw_context.t -> id -> Raw_context.t Lwt.t + + val copy : Raw_context.t -> from:id -> to_:id -> Raw_context.t tzresult Lwt.t + + type key = Raw_context.t * id + + val rpc_arg : id RPC_arg.t + + module Contents : sig + include + Non_iterable_indexed_carbonated_data_storage + with type key = Script_expr_hash.t + and type value = Script_repr.expr + and type t := key + + val list_key_values : + ?offset:int -> + ?length:int -> + Raw_context.t * id -> + (Raw_context.t * (Script_expr_hash.t * Script_repr.expr) list) tzresult + Lwt.t + end + + module Total_bytes : + Indexed_data_storage_with_local_context + with type key = id + and type value = Z.t + and type t := Raw_context.t + + module Key_type : + Indexed_data_storage + with type key = id + and type value = Script_repr.expr + and type t := Raw_context.t + + module Value_type : + Indexed_data_storage + with type key = id + and type value = Script_repr.expr + and type t := Raw_context.t +end + +module Sapling : sig + type id = Lazy_storage_kind.Sapling_state.Id.t + + val rpc_arg : id RPC_arg.t + + module Next : sig + val incr : Raw_context.t -> (Raw_context.t * id) tzresult Lwt.t + + val init : Raw_context.t -> Raw_context.t tzresult Lwt.t + end + + val copy : Raw_context.t -> from:id -> to_:id -> Raw_context.t tzresult Lwt.t + + val remove : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Total_bytes : + Indexed_data_storage + with type key = id + and type value = Z.t + and type t := Raw_context.t + + (* Used by both Commitments and Ciphertexts *) + module Commitments_size : + Single_data_storage with type t := Raw_context.t * id and type value = int64 + + module Memo_size : + Single_data_storage with type t := Raw_context.t * id and type value = int + + module Commitments : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Hash.t + + val commitments_init : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Ciphertexts : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Ciphertext.t + + val ciphertexts_init : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Nullifiers_size : + Single_data_storage with type t := Raw_context.t * id and type value = int64 + + module Nullifiers_ordered : + Non_iterable_indexed_data_storage + with type t := Raw_context.t * id + and type key = int64 + and type value = Sapling.Nullifier.t + + module Nullifiers_hashed : + Carbonated_data_set_storage + with type t := Raw_context.t * id + and type elt = Sapling.Nullifier.t + + val nullifiers_init : Raw_context.t -> id -> Raw_context.t Lwt.t + + module Roots : + Non_iterable_indexed_data_storage + with type t := Raw_context.t * id + and type key = int32 + and type value = Sapling.Hash.t + + module Roots_pos : + Single_data_storage with type t := Raw_context.t * id and type value = int32 + + module Roots_level : + Single_data_storage + with type t := Raw_context.t * id + and type value = Raw_level_repr.t +end + +(** Set of all registered delegates. *) +module Delegates : + Data_set_storage + with type t := Raw_context.t + and type elt = Signature.Public_key_hash.t + +(** Set of all active consensus keys in cycle `current + consensus_rights_delay + 1` *) +module Consensus_keys : + Data_set_storage + with type t := Raw_context.t + and type elt = Signature.Public_key_hash.t + +(** The pending consensus key of a delegate at the given cycle *) +module Pending_consensus_keys : + Indexed_data_storage + with type t := Raw_context.t * Cycle_repr.t + and type key = Contract_repr.t + and type value = Signature.public_key + +(** All denunciations of the current and previous cycles that will have an effect + (slashing, reward), i.e. all below 100%, deferred to the end of their + slashing period. *) +module Pending_denunciations : + Indexed_data_storage + with type t := Raw_context.t + and type key = Signature.public_key_hash + and type value = Denunciations_repr.t + +(** History of slashed deposits: an associative list of cycles to slashed + percentages. + + This storage is inefficient but is not expected to grow large (as of + 2023-11-28, the last slashing on mainnet dates back to: + - 2021-12-17 for double baking (154 events in total), + - 2019-08-08 for double endorsing (24 events in total). + Since slashings are here grouped by baker and cycle, there would only be + a few elements in each list. + + The slashing percentages are used to compute the real value of stake + withdrawals. + Currently there is no limit to the age of the events we need to store + because there is no such limit for stake withdrawals. + At worst we can revisit this decision in a later protocol amendment (in + 25 cycles) or clean up this storage manually or automatically. *) +module Slashed_deposits : + Indexed_data_storage + with type t := Raw_context.t + and type key = Signature.public_key_hash + and type value = Slashed_deposits_history.t + +(** Needed for the stitching from Oxford to P. + TODO #6957: Remove this from protocol Q. *) +type denounced__Oxford = {for_double_attesting : bool; for_double_baking : bool} + +(** This type is used to track which denunciations have already been + recorded, to avoid slashing multiple times the same event. *) +type denounced = { + for_double_preattesting : bool; + for_double_attesting : bool; + for_double_baking : bool; +} + +(** {!denounced} with all fields set to [false]. *) +val default_denounced : denounced + +(** Set used to avoid slashing multiple times the same event *) +module Already_denounced : + Indexed_data_storage + with type t := Raw_context.t * Cycle_repr.t + and type key = + (Raw_level_repr.t * Round_repr.t) * Signature.Public_key_hash.t + and type value = denounced + +(** Needed for the stitching from Oxford to P. + TODO #6957: Remove this from protocol Q. *) +module Already_denounced__Oxford : + Indexed_data_storage + with type t := Raw_context.t * Cycle_repr.t + and type key = Raw_level_repr.t * Signature.Public_key_hash.t + and type value = denounced__Oxford + +module Pending_staking_parameters : + Indexed_data_storage + with type t := Raw_context.t * Cycle_repr.t + and type key = Contract_repr.t + and type value = Staking_parameters_repr.t + +module Stake : sig + (** The map of all the stake of all delegates, including those with + less than {!Constants_parametric_repr.minimal_stake}. It might + be large. *) + module Staking_balance : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = Full_staking_balance_repr.t + and type t := Raw_context.t + + (** This should be fairly small compared to staking balance *) + module Active_delegates_with_minimal_stake : + Data_set_storage + with type elt = Signature.Public_key_hash.t + and type t := Raw_context.t + + (** List of active stake *) + module Selected_distribution_for_cycle : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = (Signature.Public_key_hash.t * Stake_repr.t) list + and type t := Raw_context.t + + (** Sum of the active stakes of all the delegates with + {!Constants_parametric_repr.minimal_stake} *) + module Total_active_stake : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Stake_repr.t + and type t := Raw_context.t +end + +(** State of the sampler used to select delegates. Managed synchronously + with [Stake.Selected_distribution_for_cycle]. *) +module Delegate_sampler_state : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Raw_context.consensus_pk Sampler.t + and type t := Raw_context.t + +(** Compounding reward bonus for Adaptive Issuance *) +module Issuance_bonus : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Issuance_bonus_repr.t + and type t := Raw_context.t + +(** Multiplicative coefficient for rewards under Adaptive Issuance + (Includes the bonus) *) +module Issuance_coeff : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Q.t + and type t := Raw_context.t + +(** Votes *) + +module Vote : sig + module Pred_period_kind : + Single_data_storage + with type value = Voting_period_repr.kind + and type t := Raw_context.t + + module Current_period : + Single_data_storage + with type value = Voting_period_repr.t + and type t := Raw_context.t + + (** Participation exponential moving average, in centile of percentage *) + module Participation_ema : + Single_data_storage with type value = int32 and type t := Raw_context.t + + module Current_proposal : + Single_data_storage + with type value = Protocol_hash.t + and type t := Raw_context.t + + (** Sum of voting weights of all delegates. *) + module Voting_power_in_listings : + Single_data_storage with type value = int64 and type t := Raw_context.t + + (** Contains all delegates with their assigned voting weight. *) + module Listings : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = int64 + and type t := Raw_context.t + + (** Set of protocol proposal with corresponding proposer delegate *) + module Proposals : + Data_set_storage + with type elt = Protocol_hash.t * Signature.Public_key_hash.t + and type t := Raw_context.t + + (** Keeps for each delegate the number of proposed protocols *) + module Proposals_count : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = int + and type t := Raw_context.t + + (** Contains for each delegate its ballot *) + module Ballots : + Indexed_data_storage + with type key = Signature.Public_key_hash.t + and type value = Vote_repr.ballot + and type t := Raw_context.t +end + +module type FOR_CYCLE = sig + val init : + Raw_context.t -> + Cycle_repr.t -> + Seed_repr.seed -> + Raw_context.t tzresult Lwt.t + + val mem : Raw_context.t -> Cycle_repr.t -> bool Lwt.t + + val get : Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + + val update : + Raw_context.t -> + Cycle_repr.t -> + Seed_repr.seed -> + Seed_repr.seed_status -> + Raw_context.t tzresult Lwt.t + + val remove_existing : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t +end + +(** Seed *) + +module Seed_status : + Simple_single_data_storage with type value = Seed_repr.seed_status + +module Seed : sig + (** Storage from this submodule must only be accessed through the + module `Seed`. *) + + type unrevealed_nonce = { + nonce_hash : Nonce_hash.t; + delegate : Signature.Public_key_hash.t; + } + + type nonce_status = + | Unrevealed of unrevealed_nonce + | Revealed of Seed_repr.nonce + + module Nonce : + Non_iterable_indexed_data_storage + with type key := Level_repr.t + and type value := nonce_status + and type t := Raw_context.t + + module VDF_setup : + Single_data_storage + with type value = Seed_repr.vdf_setup + and type t := Raw_context.t + + module For_cycle : FOR_CYCLE + + val get_status : Raw_context.t -> Seed_repr.seed_status tzresult Lwt.t +end + +(** Commitments *) + +module Commitments : + Indexed_data_storage + with type key = Blinded_public_key_hash.t + and type value = Tez_repr.t + and type t := Raw_context.t + +(** Ramp up rewards *) +module Ramp_up : sig + type reward = { + baking_reward_fixed_portion : Tez_repr.t; + baking_reward_bonus_per_slot : Tez_repr.t; + attesting_reward_per_slot : Tez_repr.t; + } + + module Rewards : + Indexed_data_storage + with type key = Cycle_repr.t + and type value := reward + and type t := Raw_context.t +end + +module Pending_migration : sig + module Balance_updates : + Single_data_storage + with type value = Receipt_repr.balance_updates + and type t := Raw_context.t + + module Operation_results : + Single_data_storage + with type value = Migration_repr.origination_result list + and type t := Raw_context.t + + val remove : + Raw_context.t -> + (Raw_context.t + * Receipt_repr.balance_updates + * Migration_repr.origination_result list) + tzresult + Lwt.t +end + +module Liquidity_baking : sig + (** Exponential moving average (ema) of flags set in protocol_data.contents. + The liquidity baking subsidy is not sent to the CPMM if this EMA is above + the threshold set in constants. **) + module Toggle_ema : + Single_data_storage with type t := Raw_context.t and type value = Int32.t + + (** Constant product market maker contract that receives liquidity baking subsidy. **) + module Cpmm_address : + Single_data_storage + with type t := Raw_context.t + and type value = Contract_hash.t +end + +module Adaptive_issuance : sig + (** Exponential moving average (ema) of votes set in the block header + protocol_data.contents. Once the feature is activated, it can no + longer be deactivated without a protocol amendment. **) + module Launch_ema : + Single_data_storage with type t := Raw_context.t and type value = Int32.t + + (** Cycle [Some c] from which adaptive issuance is (or will be) + active, or [None] if the feature is not yet planned to activate. **) + module Activation : + Single_data_storage + with type t := Raw_context.t + and type value = Cycle_repr.t option +end + +(** A map of [Script_repr.expr] values, indexed by their hash ([Script_expr_hash.t]). + Values from this map can be incorporated by any contract via the primitive + [Michelson_v1_primitives.H_constant]. *) +module Global_constants : sig + module Map : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Script_expr_hash.t + and type value = Script_repr.expr +end + +(** This module exposes a balance table for tracking ticket ownership. + The table is a mapping from keys to values where the keys consist of a + hashed representation of: + - A ticketer, i.e. the creator of the ticket + - The content of a the ticket + - The contract that owns some amount of the ticket + The values of the table are the amounts owned by each key. + *) +module Ticket_balance : sig + module Table : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Ticket_hash_repr.t + and type value = Z.t + + module Paid_storage_space : + Single_data_storage with type t := Raw_context.t and type value = Z.t + + module Used_storage_space : + Single_data_storage with type t := Raw_context.t and type value = Z.t +end + +(** Tenderbake *) + +module Tenderbake : sig + (** [First_level_of_protocol] stores the level of the first block of + this protocol. *) + module First_level_of_protocol : + Single_data_storage + with type t := Raw_context.t + and type value = Raw_level_repr.t + + (** [Attestation_branch] stores a single value composed of the + grandparent hash and the predecessor's payload (computed with + the grandparent hash) used to verify the validity of + attestations. *) + module Attestation_branch : + Single_data_storage + with type value = Block_hash.t * Block_payload_hash.t + and type t := Raw_context.t + + (** [Forbidden_delegates] stores the set of delegates that are not + allowed to bake or attest blocks. *) + module Forbidden_delegates : + Single_data_storage + with type value = Signature.Public_key_hash.Set.t + and type t := Raw_context.t +end + +module Sc_rollup : sig + (** Smart contract rollup. + + Storage from this submodule must only be accessed through the + module `Sc_rollup_storage`. + + Each smart contract rollup is associated to: + + - a PVM kind (provided at creation time, read-only) + - a metadata (generated at creation time, read-only) + - a boot sector (provided at creation time, read-only) + - a parameters type specifying the types of parameters the rollup accepts + - the L1 block level at which the rollup was created + - a merkelized inbox, of which only the root hash is stored + - a map from stakers to their newest staked commitments + - a map from stakers to commitments + - a map from commitments to the time (level) of their first insertion + + For performance reasons we also store (per rollup): + + - the total number of active stakers; + - the number of stakers per commitment. + - the commitments per inbox level. + + See module {!Sc_rollup_repr.Commitment} for details. + *) + module PVM_kind : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_repr.t + and type value = Sc_rollups.Kind.t + and type t := Raw_context.t + + module Parameters_type : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_repr.t + and type value = Script_repr.lazy_expr + and type t := Raw_context.t + + module Genesis_info : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_repr.t + and type value = Sc_rollup_commitment_repr.genesis_info + and type t := Raw_context.t + + module Inbox : + Single_data_storage + with type value = Sc_rollup_inbox_repr.t + and type t := Raw_context.t + + module Last_cemented_commitment : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_repr.t + and type value = Sc_rollup_commitment_repr.Hash.t + and type t := Raw_context.t + + (** Contains the current latest attributed index for stakers. *) + module Staker_index_counter : + Single_data_storage + with type value = Sc_rollup_staker_index_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + (** Contains the index of any staker that currently have stake. *) + module Staker_index : + Non_iterable_indexed_carbonated_data_storage + with type key = Signature.Public_key_hash.t + and type value = Sc_rollup_staker_index_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + (** Contains the most recent inbox level staked by an active staker. *) + module Stakers : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_staker_index_repr.t + and type value = Raw_level_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + module Commitments : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_commitment_repr.Hash.t + and type value = Sc_rollup_commitment_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + (** Contains for all commitment not yet cemented the list of stakers that have + staked on it. *) + module Commitment_stakers : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_commitment_repr.Hash.t + and type value = Sc_rollup_staker_index_repr.t list + and type t = Raw_context.t * Sc_rollup_repr.t + + (** This storage contains for each rollup and inbox level not yet cemented the + level of publication of the first commitment. This is used to compute the + curfew for a given rollup and inbox level. + + The storage size is bounded for each rollup by + + [max_lookahead / commitment_period] + + Since the storage is cleaned when commitments are cemented, this storage + space is only temporarily bought by stakers with their deposits. + *) + module Commitment_first_publication_level : + Non_iterable_indexed_carbonated_data_storage + with type key = Raw_level_repr.t + and type value = Raw_level_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + (** Stores the commitments published for an inbox level. *) + module Commitments_per_inbox_level : + Non_iterable_indexed_carbonated_data_storage + with type key = Raw_level_repr.t + and type value = Sc_rollup_commitment_repr.Hash.t list + and type t = Raw_context.t * Sc_rollup_repr.t + + module Commitment_added : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_commitment_repr.Hash.t + and type value = Raw_level_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + module Game_info : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_game_repr.Index.t + and type value = Sc_rollup_game_repr.t + and type t = Raw_context.t * Sc_rollup_repr.t + + (** Refutation games are indexed by the rollup, by one staker, and + by its opponent staker. Hence, each game appears twice. This is + convenient to quickly compute the opponents of a given staker. *) + module Game : + Indexed_carbonated_data_storage + with type key = Signature.Public_key_hash.t + and type value = Sc_rollup_game_repr.Index.t + and type t = + (Raw_context.t * Sc_rollup_repr.t) * Signature.Public_key_hash.t + + (** [Game_timeout] stores the block level at which the staker whose + turn it is to move will (become vulnerable to) timeout. The staker + pair should always be in lexical order to ensure that this value is + not duplicated. + *) + module Game_timeout : + Non_iterable_indexed_carbonated_data_storage + with type key = Sc_rollup_game_repr.Index.t + and type value = Sc_rollup_game_repr.timeout + and type t = Raw_context.t * Sc_rollup_repr.t + + (** A carbonated storage for keeping track of applied outbox messages for a + a SCORU. + + The [key] is an [int32] value that represents the index of a SCORU's + outbox level. An outbox level is mapped to the index through: + + [index = outbox_level % sc_rollup_max_active_outbox_levels] + + The rationale is to keep a limited number of entries. The current value of + an entry contains the most recently added level that maps to the index. + + The [value] is a pair of the actual outbox level and a bitset containing + the set of applied messages. + *) + module Applied_outbox_messages : + Non_iterable_indexed_carbonated_data_storage + with type t = Raw_context.t * Sc_rollup_repr.t + and type key = int32 + and type value = Raw_level_repr.t * Bitset.t + + (** A carbonated storage for stakers (identified by their public key hashes) + that are able to stake on commitments. If the storage is + empty then the rollup is public (anyone can publish commitments for the rollup), + otherwise it is private (only the members of the whitelist can publish commitments). *) + module Whitelist : + Carbonated_data_set_storage + with type t := Raw_context.t * Sc_rollup_repr.t + and type elt = Signature.Public_key_hash.t + + (** Maximal space available for the whitelist without needing to burn new fees. *) + module Whitelist_paid_storage_space : + Indexed_data_storage + with type key = Sc_rollup_repr.t + and type value = Z.t + and type t = Raw_context.t + + (** Current storage space in bytes used by the whitelist. *) + module Whitelist_used_storage_space : + Indexed_data_storage + with type t = Raw_context.t + and type key = Sc_rollup_repr.t + and type value = Z.t + + (** Outbox level and message of the latest whitelist update of a given rollup. *) + module Last_whitelist_update : + Non_iterable_indexed_carbonated_data_storage + with type t = Raw_context.t + and type key = Sc_rollup_repr.t + and type value = Sc_rollup_whitelist_repr.last_whitelist_update +end + +module Dal : sig + module Slot : sig + (** This is a temporary storage for slot headers proposed onto the L1. *) + module Headers : + Non_iterable_indexed_data_storage + with type t = Raw_context.t + and type key = Raw_level_repr.t + and type value = Dal_slot_repr.Header.t list + + (** This is a permanent storage for slot headers confirmed by the L1. *) + module History : + Single_data_storage + with type t := Raw_context.t + and type value = Dal_slot_repr.History.t + end +end + +module Zk_rollup : sig + (** ZK rollup. + + Each ZK rollup is associated to: + + - an Account, as described in [Zk_rollup_repr] + - a pending list description, consisting of its head's index and + a counter + - a map from integer indeces to L2 operations, to store the actual + pending list + *) + module Account : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Zk_rollup_repr.t + and type value = Zk_rollup_account_repr.t + + module Pending_list : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t + and type key = Zk_rollup_repr.t + and type value = Zk_rollup_repr.pending_list + + module Pending_operation : + Non_iterable_indexed_carbonated_data_storage + with type t := Raw_context.t * Zk_rollup_repr.t + and type key = int64 + and type value = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option +end + +module Legacy : sig + (** [Grand_parent_branch] stores a single value composed of the + great-grand parent hash and the grand parent's payload *) + module Grand_parent_branch : + Single_data_storage + with type value = Block_hash.t * Block_payload_hash.t + and type t := Raw_context.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/storage_costs.ml b/src/proto_020_PsParisC/lib_protocol/storage_costs.ml new file mode 100644 index 000000000000..76436c8285de --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_costs.ml @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Storage_costs_generated + +(* The model for read accesses is the following: + + cost(path_length, read_bytes) = 200_000 + 5000 * path_length + 2 * read_bytes +*) +let read_access ~path_length ~read_bytes = + let open Saturation_repr in + let open S.Syntax in + Gas_limit_repr.atomic_step_cost + @@ safe_int 200_000 + + (safe_int 5000 * safe_int path_length) + + (safe_int 2 * safe_int read_bytes) + +(* The model for write accesses is the following: + + cost(written_bytes) = 200_000 + 4 * written_bytes +*) +let write_access ~written_bytes = + let open Saturation_repr in + let open S.Syntax in + Gas_limit_repr.atomic_step_cost + @@ (safe_int 200_000 + (safe_int 4 * safe_int written_bytes)) + +let list_key_values_traverse ~size = cost_List_key_values size diff --git a/src/proto_020_PsParisC/lib_protocol/storage_costs.mli b/src/proto_020_PsParisC/lib_protocol/storage_costs.mli new file mode 100644 index 000000000000..8c4e4c703ea8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_costs.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Cost of reading [read_bytes] at a key of length [path_length]. *) +val read_access : path_length:int -> read_bytes:int -> Gas_limit_repr.cost + +(** Cost of performing a single write access, writing [written_bytes] bytes. *) +val write_access : written_bytes:int -> Gas_limit_repr.cost + +(** [list_key_values_traverse ~size] returns the cost of traversing a context + with [size] number of elements. *) +val list_key_values_traverse : size:int -> Gas_limit_repr.cost diff --git a/src/proto_020_PsParisC/lib_protocol/storage_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/storage_costs_generated.ml new file mode 100644 index 000000000000..b60c01874129 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_costs_generated.ml @@ -0,0 +1,22 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model storage/List_key_values *) +(* fun size -> max 10 (470. + (117. * size)) *) +let cost_List_key_values size = + let size = S.safe_int size in + (size * S.safe_int 118) + S.safe_int 470 + +(* model storage/List_key_values/intercept *) +(* fun size -> max 10 (470. + (117. * size)) *) +let cost_intercept size = + let size = S.safe_int size in + (size * S.safe_int 118) + S.safe_int 470 diff --git a/src/proto_020_PsParisC/lib_protocol/storage_description.ml b/src/proto_020_PsParisC/lib_protocol/storage_description.ml new file mode 100644 index 000000000000..9acc76778a72 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_description.ml @@ -0,0 +1,395 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module StringMap = Map.Make (String) + +type 'key t = 'key desc_with_path + +(** [desc_with_path] describes a position in the storage. It's composed + [rev_path] which is the reverse path up to the position, and [dir] the + position's [description]. [rev_path] is only useful in case of an error to + print a descriptive message. [List.rev rev_path] is a storage's path that + contains no conflict and allows the registration of a [dir]'s storage. + NB: [rev_path] indicates the position in the tree, so once the node is + added, it won't change; whereas [dir] is mutable because when more subtrees + are added this may require updating it. *) +and 'key desc_with_path = { + rev_path : string list; + mutable dir : 'key description; +} + +and 'key description = + | Empty : 'key description + | Value : { + get : 'key -> 'a option tzresult Lwt.t; + encoding : 'a Data_encoding.t; + } + -> 'key description + | NamedDir : 'key t StringMap.t -> 'key description + | IndexedDir : { + arg : 'a RPC_arg.t; + arg_encoding : 'a Data_encoding.t; + list : 'key -> 'a list tzresult Lwt.t; + subdir : ('key * 'a) t; + } + -> 'key description + +let rec pp : type a. Format.formatter -> a t -> unit = + fun ppf {dir; _} -> + match dir with + | Empty -> Format.fprintf ppf "Empty" + | Value _e -> Format.fprintf ppf "Value" + | NamedDir map -> + Format.fprintf + ppf + "@[%a@]" + (Format.pp_print_list pp_item) + (StringMap.bindings map) + | IndexedDir {arg; subdir; _} -> + let name = Format.asprintf "<%s>" (RPC_arg.descr arg).name in + pp_item ppf (name, subdir) + +and pp_item : type a. Format.formatter -> string * a t -> unit = + fun ppf (name, desc) -> Format.fprintf ppf "@[%s@ %a@]" name pp desc + +let pp_rev_path ppf path = + Format.fprintf + ppf + "[%a]" + Format.( + pp_print_list + ~pp_sep:(fun ppf () -> pp_print_string ppf " / ") + pp_print_string) + (List.rev path) + +let rec register_named_subcontext : type r. r t -> string list -> r t = + fun desc names -> + match (desc.dir, names) with + | _, [] -> desc + | Value _, _ | IndexedDir _, _ -> + Format.kasprintf + invalid_arg + "Could not register a named subcontext at %a because of an existing %a." + pp_rev_path + desc.rev_path + pp + desc + | Empty, name :: names -> + let subdir = {rev_path = name :: desc.rev_path; dir = Empty} in + desc.dir <- NamedDir (StringMap.singleton name subdir) ; + register_named_subcontext subdir names + | NamedDir map, name :: names -> + let subdir = + match StringMap.find name map with + | Some subdir -> subdir + | None -> + let subdir = {rev_path = name :: desc.rev_path; dir = Empty} in + desc.dir <- NamedDir (StringMap.add name subdir map) ; + subdir + in + register_named_subcontext subdir names + +type (_, _, _) args = + | One : { + rpc_arg : 'a RPC_arg.t; + encoding : 'a Data_encoding.t; + compare : 'a -> 'a -> int; + } + -> ('key, 'a, 'key * 'a) args + | Pair : + ('key, 'a, 'inter_key) args * ('inter_key, 'b, 'sub_key) args + -> ('key, 'a * 'b, 'sub_key) args + +let rec unpack : type a b c. (a, b, c) args -> c -> a * b = function + | One _ -> fun x -> x + | Pair (l, r) -> + let unpack_l = unpack l in + let unpack_r = unpack r in + fun x -> + let c, d = unpack_r x in + let b, a = unpack_l c in + (b, (a, d)) + +let rec pack : type a b c. (a, b, c) args -> a -> b -> c = function + | One _ -> fun b a -> (b, a) + | Pair (l, r) -> + let pack_l = pack l in + let pack_r = pack r in + fun b (a, d) -> + let c = pack_l b a in + pack_r c d + +let rec compare : type a b c. (a, b, c) args -> b -> b -> int = function + | One {compare; _} -> compare + | Pair (l, r) -> ( + let compare_l = compare l in + let compare_r = compare r in + fun (a1, b1) (a2, b2) -> + match compare_l a1 a2 with 0 -> compare_r b1 b2 | x -> x) + +let destutter equal l = + match l with + | [] -> [] + | (i, _) :: l -> + let rec loop acc i = function + | [] -> acc + | (j, _) :: l -> if equal i j then loop acc i l else loop (j :: acc) j l + in + loop [i] i l + +let rec register_indexed_subcontext : + type r a b. + r t -> list:(r -> a list tzresult Lwt.t) -> (r, a, b) args -> b t = + fun desc ~list path -> + let open Lwt_result_syntax in + match path with + | Pair (left, right) -> + let compare_left = compare left in + let equal_left x y = Compare.Int.(compare_left x y = 0) in + let list_left r = + let+ l = list r in + destutter equal_left l + in + let list_right r = + let a, k = unpack left r in + let+ l = list a in + List.map snd (List.filter (fun (x, _) -> equal_left x k) l) + in + register_indexed_subcontext + (register_indexed_subcontext desc ~list:list_left left) + ~list:list_right + right + | One {rpc_arg = arg; encoding = arg_encoding; _} -> ( + match desc.dir with + | Value _ | NamedDir _ -> + Format.kasprintf + invalid_arg + "Could not register an indexed subcontext at %a because of an \ + existing %a." + pp_rev_path + desc.rev_path + pp + desc + | Empty -> + let subdir = + { + rev_path = + Format.sprintf "(Maybe of %s)" RPC_arg.(descr arg).name + :: desc.rev_path; + dir = Empty; + } + in + desc.dir <- IndexedDir {arg; arg_encoding; list; subdir} ; + subdir + | IndexedDir {arg = inner_arg; subdir; _} -> ( + match RPC_arg.eq arg inner_arg with + | None -> + Format.kasprintf + invalid_arg + "An indexed subcontext at %a already exists but has a \ + different argument: `%s` <> `%s`." + pp_rev_path + desc.rev_path + (RPC_arg.descr arg).name + (RPC_arg.descr inner_arg).name + | Some RPC_arg.Eq -> subdir)) + +let register_value : + type a b. + a t -> get:(a -> b option tzresult Lwt.t) -> b Data_encoding.t -> unit = + fun desc ~get encoding -> + match desc.dir with + | Empty -> desc.dir <- Value {get; encoding} + | _ -> + Format.kasprintf + invalid_arg + "Could not register a value at %a because of an existing %a." + pp_rev_path + desc.rev_path + pp + desc + +let create () = {rev_path = []; dir = Empty} + +module type INDEX = sig + type t + + include Path_encoding.S with type t := t + + val rpc_arg : t RPC_arg.t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int +end + +type _ handler = + | Handler : { + encoding : 'a Data_encoding.t; + get : 'key -> int -> 'a tzresult Lwt.t; + } + -> 'key handler + +type _ opt_handler = + | Opt_handler : { + encoding : 'a Data_encoding.t; + get : 'key -> int -> 'a option tzresult Lwt.t; + } + -> 'key opt_handler + +let rec combine_object = + let open Lwt_result_syntax in + function + | [] -> + Handler {encoding = Data_encoding.unit; get = (fun _ _ -> return_unit)} + | (name, Opt_handler handler) :: fields -> + let (Handler handlers) = combine_object fields in + Handler + { + encoding = + Data_encoding.merge_objs + Data_encoding.(obj1 (opt name (dynamic_size handler.encoding))) + handlers.encoding; + get = + (fun k i -> + let* v1 = handler.get k i in + let* v2 = handlers.get k i in + return (v1, v2)); + } + +type query = {depth : int} + +let depth_query = + let open RPC_query in + query (fun depth -> {depth}) + |+ field "depth" RPC_arg.uint 0 (fun t -> t.depth) + |> seal + +let build_directory : type key. key t -> key RPC_directory.t = + fun dir -> + let rpc_dir = ref (RPC_directory.empty : key RPC_directory.t) in + let register : + type ikey. + chunked:bool -> (key, ikey) RPC_path.t -> ikey opt_handler -> unit = + fun ~chunked path (Opt_handler {encoding; get}) -> + let service = + RPC_service.get_service ~query:depth_query ~output:encoding path + in + rpc_dir := + RPC_directory.opt_register ~chunked !rpc_dir service (fun k q () -> + get k (q.depth + 1)) + in + let rec build_handler : + type ikey. ikey t -> (key, ikey) RPC_path.t -> ikey opt_handler = + let open Lwt_result_syntax in + fun desc path -> + match desc.dir with + | Empty -> + Opt_handler + {encoding = Data_encoding.unit; get = (fun _ _ -> return_none)} + | Value {get; encoding} -> + let handler = + Opt_handler + { + encoding; + get = + (fun k i -> + if Compare.Int.(i < 0) then return_none else get k); + } + in + register ~chunked:true path handler ; + handler + | NamedDir map -> + let fields = StringMap.bindings map in + let fields = + List.map + (fun (name, dir) -> + (name, build_handler dir RPC_path.(path / name))) + fields + in + let (Handler handler) = combine_object fields in + let handler = + Opt_handler + { + encoding = handler.encoding; + get = + (fun k i -> + if Compare.Int.(i < 0) then return_none + else + let* v = handler.get k (i - 1) in + return_some v); + } + in + register ~chunked:true path handler ; + handler + | IndexedDir {arg; arg_encoding; list; subdir} -> + let (Opt_handler handler) = + build_handler subdir RPC_path.(path /: arg) + in + let encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"Leaf" + (dynamic_size arg_encoding) + (function key, None -> Some key | _ -> None) + (fun key -> (key, None)); + case + (Tag 1) + ~title:"Dir" + (tup2 + (dynamic_size arg_encoding) + (dynamic_size handler.encoding)) + (function key, Some value -> Some (key, value) | _ -> None) + (fun (key, value) -> (key, Some value)); + ] + in + let get k i = + if Compare.Int.(i < 0) then return_none + else if Compare.Int.(i = 0) then return_some [] + else + let* keys = list k in + let* values = + List.map_es + (fun key -> + if Compare.Int.(i = 1) then return (key, None) + else + let+ value = handler.get (k, key) (i - 1) in + (key, value)) + keys + in + return_some values + in + let handler = + Opt_handler + {encoding = Data_encoding.(list (dynamic_size encoding)); get} + in + register ~chunked:true path handler ; + handler + in + ignore (build_handler dir RPC_path.open_root : key opt_handler) ; + !rpc_dir diff --git a/src/proto_020_PsParisC/lib_protocol/storage_description.mli b/src/proto_020_PsParisC/lib_protocol/storage_description.mli new file mode 100644 index 000000000000..33e44cc39f13 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_description.mli @@ -0,0 +1,93 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module is responsible for building the description of the current state + of the storage, which is then used to build specification of the RPC + endpoints for accessing the storage. It produces [resto] [RPC_directory.t] + values, which can be used directly to construct the RPC endpoint tree. *) + +(** Typed description of the key-value context. *) +type 'key t + +(** Trivial display of the key-value context layout. *) +val pp : Format.formatter -> 'key t -> unit + +(** Export an RPC hierarchy for querying the context. There is one service + by possible path in the context. Services for "directory" are able to + aggregate in one JSON object the whole subtree. *) +val build_directory : 'key t -> 'key RPC_directory.t + +(** Create a empty context description, + keys will be registered by side effects. *) +val create : unit -> 'key t + +(** Register a single key accessor at a given path. *) +val register_value : + 'key t -> get:('key -> 'a option tzresult Lwt.t) -> 'a Data_encoding.t -> unit + +(** Return a description for a prefixed fragment of the given context. + All keys registered in the subcontext will be shared by the external + context *) +val register_named_subcontext : 'key t -> string list -> 'key t + +(** Description of an index as a sequence of `RPC_arg.t`. *) +type (_, _, _) args = + | One : { + rpc_arg : 'a RPC_arg.t; + encoding : 'a Data_encoding.t; + compare : 'a -> 'a -> int; + } + -> ('key, 'a, 'key * 'a) args + | Pair : + ('key, 'a, 'inter_key) args * ('inter_key, 'b, 'sub_key) args + -> ('key, 'a * 'b, 'sub_key) args + +(** Return a description for a indexed sub-context. + All keys registered in the subcontext will be shared by the external + context. One should provide a function to list all the registered + index in the context. *) +val register_indexed_subcontext : + 'key t -> + list:('key -> 'arg list tzresult Lwt.t) -> + ('key, 'arg, 'sub_key) args -> + 'sub_key t + +(** Helpers for manipulating and defining indexes. *) + +val pack : ('key, 'a, 'sub_key) args -> 'key -> 'a -> 'sub_key + +val unpack : ('key, 'a, 'sub_key) args -> 'sub_key -> 'key * 'a + +module type INDEX = sig + type t + + include Path_encoding.S with type t := t + + val rpc_arg : t RPC_arg.t + + val encoding : t Data_encoding.t + + val compare : t -> t -> int +end diff --git a/src/proto_020_PsParisC/lib_protocol/storage_functors.ml b/src/proto_020_PsParisC/lib_protocol/storage_functors.ml new file mode 100644 index 000000000000..beaf1a1a633e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_functors.ml @@ -0,0 +1,1500 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Storage_sigs + +module Registered = struct + let ghost = false +end + +module Ghost = struct + let ghost = true +end + +module type ENCODER = sig + type t + + val of_bytes : key:(unit -> string list) -> bytes -> t tzresult + + val to_bytes : t -> bytes +end + +module Make_encoder (V : VALUE) : ENCODER with type t := V.t = struct + let of_bytes ~key b = + let open Result_syntax in + match Data_encoding.Binary.of_bytes_opt V.encoding b with + | None -> tzfail (Raw_context.Storage_error (Corrupted_data (key ()))) + | Some v -> return v + + let to_bytes v = + match Data_encoding.Binary.to_bytes_opt V.encoding v with + | Some b -> b + | None -> Bytes.empty +end + +let len_name = "len" + +let data_name = "data" + +let encode_len_value bytes = + let length = Bytes.length bytes in + Data_encoding.(Binary.to_bytes_exn int31) length + +let decode_len_value key len = + let open Result_syntax in + match Data_encoding.(Binary.of_bytes_opt int31) len with + | None -> tzfail (Raw_context.Storage_error (Corrupted_data key)) + | Some len -> return len + +module Make_subcontext (R : REGISTER) (C : Raw_context.T) (N : NAME) : + Raw_context.T with type t = C.t and type local_context = C.local_context = +struct + type t = C.t + + type local_context = C.local_context + + let to_key k = N.name @ k + + let mem t k = C.mem t (to_key k) + + let mem_tree t k = C.mem_tree t (to_key k) + + let get t k = C.get t (to_key k) + + let get_tree t k = C.get_tree t (to_key k) + + let find t k = C.find t (to_key k) + + let find_tree t k = C.find_tree t (to_key k) + + let add t k v = C.add t (to_key k) v + + let add_tree t k v = C.add_tree t (to_key k) v + + let init t k v = C.init t (to_key k) v + + let init_tree t k v = C.init_tree t (to_key k) v + + let update t k v = C.update t (to_key k) v + + let update_tree t k v = C.update_tree t (to_key k) v + + let add_or_remove t k v = C.add_or_remove t (to_key k) v + + let add_or_remove_tree t k v = C.add_or_remove_tree t (to_key k) v + + let remove_existing t k = C.remove_existing t (to_key k) + + let remove_existing_tree t k = C.remove_existing_tree t (to_key k) + + let remove t k = C.remove t (to_key k) + + let list t ?offset ?length k = C.list t ?offset ?length (to_key k) + + let fold ?depth t k ~order ~init ~f = + C.fold ?depth t (to_key k) ~order ~init ~f + + let config t = C.config t + + module Tree = C.Tree + module Proof = C.Proof + + let verify_tree_proof = C.verify_tree_proof + + let verify_stream_proof = C.verify_stream_proof + + let equal_config = C.equal_config + + let project = C.project + + let absolute_key c k = C.absolute_key c (to_key k) + + type error += Block_quota_exceeded = C.Block_quota_exceeded + + type error += Operation_quota_exceeded = C.Operation_quota_exceeded + + let consume_gas = C.consume_gas + + let check_enough_gas = C.check_enough_gas + + let description = + let description = + if R.ghost then Storage_description.create () else C.description + in + Storage_description.register_named_subcontext description N.name + + let length = C.length + + let with_local_context ctxt k f = C.with_local_context ctxt (to_key k) f + + module Local_context = C.Local_context +end + +module Make_single_data_storage + (R : REGISTER) + (C : Raw_context.T) + (N : NAME) + (V : VALUE) : Single_data_storage with type t = C.t and type value = V.t = +struct + type t = C.t + + type context = t + + type value = V.t + + let mem t = C.mem t N.name + + include Make_encoder (V) + + let get t = + let open Lwt_result_syntax in + let* b = C.get t N.name in + let key () = C.absolute_key t N.name in + let*? v = of_bytes ~key b in + return v + + let find t = + let open Lwt_result_syntax in + let*! bytes_opt = C.find t N.name in + match bytes_opt with + | None -> return_none + | Some b -> + let key () = C.absolute_key t N.name in + let*? v = of_bytes ~key b in + return_some v + + let init t v = + let open Lwt_result_syntax in + let+ t = C.init t N.name (to_bytes v) in + C.project t + + let update t v = + let open Lwt_result_syntax in + let+ t = C.update t N.name (to_bytes v) in + C.project t + + let add t v = + let open Lwt_syntax in + let+ t = C.add t N.name (to_bytes v) in + C.project t + + let add_or_remove t v = + let open Lwt_syntax in + let+ t = C.add_or_remove t N.name (Option.map to_bytes v) in + C.project t + + let remove t = + let open Lwt_syntax in + let+ t = C.remove t N.name in + C.project t + + let remove_existing t = + let open Lwt_result_syntax in + let+ t = C.remove_existing t N.name in + C.project t + + let () = + let open Storage_description in + let description = + if R.ghost then Storage_description.create () else C.description + in + register_value + ~get:find + (register_named_subcontext description N.name) + V.encoding +end + +module type INDEX = sig + type t + + include Path_encoding.S with type t := t + + type 'a ipath + + val args : ('a, t, 'a ipath) Storage_description.args +end + +module Pair (I1 : INDEX) (I2 : INDEX) : INDEX with type t = I1.t * I2.t = struct + type t = I1.t * I2.t + + let path_length = I1.path_length + I2.path_length + + let to_path (x, y) l = I1.to_path x (I2.to_path y l) + + let of_path l = + match Misc.take I1.path_length l with + | None -> None + | Some (l1, l2) -> ( + match (I1.of_path l1, I2.of_path l2) with + | Some x, Some y -> Some (x, y) + | _ -> None) + + type 'a ipath = 'a I1.ipath I2.ipath + + let args = Storage_description.Pair (I1.args, I2.args) +end + +module Make_data_set_storage (C : Raw_context.T) (I : INDEX) : + Data_set_storage with type t = C.t and type elt = I.t = struct + type t = C.t + + type context = t + + type elt = I.t + + let inited = Bytes.of_string "inited" + + let mem s i = C.mem s (I.to_path i []) + + let add s i = + let open Lwt_syntax in + let+ t = C.add s (I.to_path i []) inited in + C.project t + + let remove s i = + let open Lwt_syntax in + let+ t = C.remove s (I.to_path i []) in + C.project t + + let clear s = + let open Lwt_syntax in + let+ t = C.remove s [] in + C.project t + + let fold s ~order ~init ~f = + C.fold ~depth:(`Eq I.path_length) s [] ~order ~init ~f:(fun file tree acc -> + match C.Tree.kind tree with + | `Value -> ( + match I.of_path file with None -> assert false | Some p -> f p acc) + | `Tree -> Lwt.return acc) + + let elements s = + fold s ~order:`Sorted ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Lwt_result_syntax in + let open Storage_description in + let unpack = unpack I.args in + register_value (* TODO fixme 'elements...' *) + ~get:(fun c -> + let c, k = unpack c in + let*! result = mem c k in + match result with true -> return_some true | false -> return_none) + (register_indexed_subcontext + ~list:(fun c -> + let*! result = elements c in + return result) + C.description + I.args) + Data_encoding.bool +end + +module Make_indexed_data_storage (C : Raw_context.T) (I : INDEX) (V : VALUE) : + Indexed_data_storage with type t = C.t and type key = I.t and type value = V.t = +struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let mem s i = C.mem s (I.to_path i []) + + let is_empty i = + let open Lwt_syntax in + let* root = C.find_tree i [] in + match root with + | None -> return_true + | Some root -> return @@ C.Tree.is_empty root + + let get s i = + let open Lwt_result_syntax in + let* b = C.get s (I.to_path i []) in + let key () = C.absolute_key s (I.to_path i []) in + let*? v = of_bytes ~key b in + return v + + let find s i = + let open Lwt_result_syntax in + let*! bytes_opt = C.find s (I.to_path i []) in + match bytes_opt with + | None -> return_none + | Some b -> + let key () = C.absolute_key s (I.to_path i []) in + let*? v = of_bytes ~key b in + return_some v + + let update s i v = + let open Lwt_result_syntax in + let+ t = C.update s (I.to_path i []) (to_bytes v) in + C.project t + + let init s i v = + let open Lwt_result_syntax in + let+ t = C.init s (I.to_path i []) (to_bytes v) in + C.project t + + let add s i v = + let open Lwt_syntax in + let+ t = C.add s (I.to_path i []) (to_bytes v) in + C.project t + + let add_or_remove s i v = + let open Lwt_syntax in + let+ t = C.add_or_remove s (I.to_path i []) (Option.map to_bytes v) in + C.project t + + let remove s i = + let open Lwt_syntax in + let+ t = C.remove s (I.to_path i []) in + C.project t + + let remove_existing s i = + let open Lwt_result_syntax in + let+ t = C.remove_existing s (I.to_path i []) in + C.project t + + let clear s = + let open Lwt_syntax in + let+ t = C.remove s [] in + C.project t + + let fold s ~order ~init ~f = + let open Lwt_syntax in + C.fold ~depth:(`Eq I.path_length) s [] ~order ~init ~f:(fun file tree acc -> + let* bytes_opt = C.Tree.to_value tree in + match bytes_opt with + | Some v -> ( + match I.of_path file with + | None -> assert false + | Some path -> ( + let key () = C.absolute_key s file in + match of_bytes ~key v with + | Ok v -> f path v acc + | Error _ -> return acc)) + | None -> return acc) + + let fold_keys s ~order ~init ~f = + fold s ~order ~init ~f:(fun k _ acc -> f k acc) + + let bindings s = + fold s ~order:`Sorted ~init:[] ~f:(fun p v acc -> + Lwt.return ((p, v) :: acc)) + + let keys s = + fold_keys s ~order:`Sorted ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Lwt_result_syntax in + let open Storage_description in + let unpack = unpack I.args in + register_value + ~get:(fun c -> + let c, k = unpack c in + find c k) + (register_indexed_subcontext + ~list:(fun c -> + let*! result = keys c in + return result) + C.description + I.args) + V.encoding +end + +(* Internal-use-only version of {!Make_indexed_carbonated_data_storage} to + expose fold_keys_unaccounted *) +module Make_indexed_carbonated_data_storage_INTERNAL + (C : Raw_context.T) + (I : INDEX) + (V : VALUE) : + Indexed_carbonated_data_storage_INTERNAL + with type t = C.t + and type key = I.t + and type value = V.t = struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let data_key i = I.to_path i [data_name] + + let len_key i = I.to_path i [len_name] + + let consume_mem_gas c key = + let path_length = List.length @@ C.absolute_key c key in + C.consume_gas c (Storage_costs.read_access ~path_length ~read_bytes:0) + + let existing_size c i = + let open Lwt_result_syntax in + let*! bytes_opt = C.find c (len_key i) in + match bytes_opt with + | None -> return (0, false) + | Some len -> + let*? len = decode_len_value (len_key i) len in + return (len, true) + + let consume_read_gas get c i = + let open Lwt_result_syntax in + let len_key = len_key i in + let* len = get c len_key in + let path_length = List.length @@ C.absolute_key c len_key in + let*? read_bytes = decode_len_value len_key len in + let cost = Storage_costs.read_access ~path_length ~read_bytes in + let*? t = C.consume_gas c cost in + return t + + (* For the future: here, we bill a generic cost for encoding the value + to bytes. It would be cleaner for users of this functor to provide + gas costs for the encoding. *) + let consume_serialize_write_gas set c i v = + let open Lwt_result_syntax in + let bytes = to_bytes v in + let len = Bytes.length bytes in + let*? c = C.consume_gas c (Gas_limit_repr.alloc_mbytes_cost len) in + let cost = Storage_costs.write_access ~written_bytes:len in + let*? c = C.consume_gas c cost in + let+ c = set c (len_key i) (encode_len_value bytes) in + (c, bytes) + + let consume_remove_gas del c i = + let open Lwt_result_syntax in + let*? c = C.consume_gas c (Storage_costs.write_access ~written_bytes:0) in + del c (len_key i) + + let mem s i = + let open Lwt_result_syntax in + let key = data_key i in + let*? s = consume_mem_gas s key in + let*! exists = C.mem s key in + return (C.project s, exists) + + let is_empty s = + let open Lwt_result_syntax in + let root_key = [] in + let*? s = consume_mem_gas s root_key in + let*! root_opt = C.find_tree s root_key in + match root_opt with + | None -> return @@ (C.project s, true) + | Some root -> + let is_empty = C.Tree.is_empty root in + return @@ (C.project s, is_empty) + + let get_unprojected s i = + let open Lwt_result_syntax in + let* s = consume_read_gas C.get s i in + let* b = C.get s (data_key i) in + let key () = C.absolute_key s (data_key i) in + let*? v = of_bytes ~key b in + return (s, v) + + let get s i = + let open Lwt_result_syntax in + let+ s, v = get_unprojected s i in + (C.project s, v) + + let find s i = + let open Lwt_result_syntax in + let key = data_key i in + let*? s = consume_mem_gas s key in + let*! exists = C.mem s key in + if exists then + let+ s, v = get s i in + (s, Some v) + else return (C.project s, None) + + let update s i v = + let open Lwt_result_syntax in + let* prev_size, _ = existing_size s i in + let* s, bytes = consume_serialize_write_gas C.update s i v in + let+ t = C.update s (data_key i) bytes in + let size_diff = Bytes.length bytes - prev_size in + (C.project t, size_diff) + + let init s i v = + let open Lwt_result_syntax in + let* s, bytes = consume_serialize_write_gas C.init s i v in + let+ t = C.init s (data_key i) bytes in + let size = Bytes.length bytes in + (C.project t, size) + + let add s i v = + let open Lwt_result_syntax in + let add s i v = + let*! ctxt = C.add s i v in + return ctxt + in + let* prev_size, existed = existing_size s i in + let* s, bytes = consume_serialize_write_gas add s i v in + let+ t = add s (data_key i) bytes in + let size_diff = Bytes.length bytes - prev_size in + (C.project t, size_diff, existed) + + let remove s i = + let open Lwt_result_syntax in + let remove s i = + let*! ctxt = C.remove s i in + return ctxt + in + let* prev_size, existed = existing_size s i in + let* s = consume_remove_gas remove s i in + let+ t = remove s (data_key i) in + (C.project t, prev_size, existed) + + let clear s = + let open Lwt_result_syntax in + let*? s = C.consume_gas s (Storage_costs.write_access ~written_bytes:0) in + let*! t = C.remove s [] in + return (C.project t) + + let remove_existing s i = + let open Lwt_result_syntax in + let* prev_size, _ = existing_size s i in + let* s = consume_remove_gas C.remove_existing s i in + let+ t = C.remove_existing s (data_key i) in + (C.project t, prev_size) + + let add_or_remove s i v = + match v with None -> remove s i | Some v -> add s i v + + (* TODO https://gitlab.com/tezos/tezos/-/issues/3318 + Switch implementation to use [C.list]. + Given that MR !2771 which flattens paths is done, we should use + [C.list] to avoid having to iterate over all keys when [length] and/or + [offset] is passed. + *) + let list_key_values ?(offset = 0) ?(length = max_int) s = + let open Lwt_result_syntax in + let root = [] in + let depth = `Eq I.path_length in + let*! size = C.length s root in + (* Regardless of the [length] argument, all elements stored in the context + are traversed. We therefore pay a gas cost proportional to the number of + elements, given by [size], upfront. We also pay gas for decoding elements + whenever they are loaded in the body of the fold. *) + let*? s = C.consume_gas s (Storage_costs.list_key_values_traverse ~size) in + let+ s, rev_values, _offset, _length = + C.fold + s + root + ~depth + ~order:`Sorted + ~init:(Ok (s, [], offset, length)) + ~f:(fun file tree acc -> + match (C.Tree.kind tree, acc) with + | `Tree, Ok (s, rev_values, offset, length) -> ( + if Compare.Int.(length <= 0) then + (* Keep going until the end, we have no means of short-circuiting *) + Lwt.return acc + else if Compare.Int.(offset > 0) then + (* Offset (first element) not reached yet *) + let offset = pred offset in + Lwt.return (Ok (s, rev_values, offset, length)) + else + (* Nominal case *) + match I.of_path file with + | None -> assert false + | Some key -> + (* This also accounts for gas for loading the element. *) + let+ s, value = get_unprojected s key in + (s, (key, value) :: rev_values, 0, pred length)) + | _ -> + (* Even if we run out of gas or fail in some other way, we still + traverse the whole tree. In this case there is no context to + update. *) + Lwt.return acc) + in + (C.project s, List.rev rev_values) + + let fold_keys_unaccounted s ~order ~init ~f = + C.fold + ~depth:(`Eq (1 + I.path_length)) + s + [] + ~order + ~init + ~f:(fun file tree acc -> + match C.Tree.kind tree with + | `Value -> ( + match List.rev file with + | last :: _ when Compare.String.(last = len_name) -> Lwt.return acc + | last :: rest when Compare.String.(last = data_name) -> ( + let file = List.rev rest in + match I.of_path file with + | None -> assert false + | Some path -> f path acc) + | _ -> assert false) + | `Tree -> Lwt.return acc) + + let keys_unaccounted s = + fold_keys_unaccounted s ~order:`Sorted ~init:[] ~f:(fun p acc -> + Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let open Lwt_result_syntax in + let unpack = unpack I.args in + register_value (* TODO export consumed gas ?? *) + ~get:(fun c -> + let c, k = unpack c in + let+ _, v = find c k in + v) + (register_indexed_subcontext + ~list:(fun c -> + let*! result = keys_unaccounted c in + return result) + C.description + I.args) + V.encoding +end + +module Make_indexed_carbonated_data_storage : functor + (C : Raw_context.T) + (I : INDEX) + (V : VALUE) + -> + Indexed_carbonated_data_storage + with type t = C.t + and type key = I.t + and type value = V.t = + Make_indexed_carbonated_data_storage_INTERNAL + +module Make_carbonated_data_set_storage (C : Raw_context.T) (I : INDEX) : + Carbonated_data_set_storage with type t = C.t and type elt = I.t = struct + module V = struct + type t = unit + + let encoding = Data_encoding.unit + end + + module M = Make_indexed_carbonated_data_storage_INTERNAL (C) (I) (V) + + type t = M.t + + type context = t + + type elt = I.t + + let mem = M.mem + + let is_empty = M.is_empty + + let clear = M.clear + + let init s i = M.init s i () + + let add s i = M.add s i () + + let remove s i = M.remove s i + + let fold_keys_unaccounted = M.fold_keys_unaccounted +end + +module Make_indexed_data_snapshotable_storage + (C : Raw_context.T) + (Snapshot_index : INDEX) + (I : INDEX) + (V : VALUE) : + Indexed_data_snapshotable_storage + with type t = C.t + and type snapshot = Snapshot_index.t + and type key = I.t + and type value = V.t = struct + type snapshot = Snapshot_index.t + + let data_name = ["current"] + + let snapshot_name = ["snapshot"] + + module C_data = + Make_subcontext (Registered) (C) + (struct + let name = data_name + end) + + module C_snapshot = + Make_subcontext (Registered) (C) + (struct + let name = snapshot_name + end) + + module V_encoder = Make_encoder (V) + include Make_indexed_data_storage (C_data) (I) (V) + module Snapshot = + Make_indexed_data_storage (C_snapshot) (Pair (Snapshot_index) (I)) (V) + + let snapshot_path id = snapshot_name @ Snapshot_index.to_path id [] + + let snapshot_exists s id = C.mem_tree s (snapshot_path id) + + let err_missing_key key = Raw_context.storage_error (Missing_key (key, Copy)) + + let snapshot s id = + let open Lwt_result_syntax in + let*! tree_opt = C.find_tree s data_name in + match tree_opt with + | None -> Lwt.return (err_missing_key data_name) + | Some tree -> + let*! t = C.add_tree s (snapshot_path id) tree in + return (C.project t) + + let fold_snapshot s id ~order ~init ~f = + let open Lwt_result_syntax in + let*! tree_opt = C.find_tree s (snapshot_path id) in + match tree_opt with + | None -> Lwt.return (err_missing_key data_name) + | Some tree -> + C_data.Tree.fold + tree + ~depth:(`Eq I.path_length) + [] + ~order + ~init:(Ok init) + ~f:(fun file tree acc -> + let*? acc in + let*! bytes_opt = C.Tree.to_value tree in + match bytes_opt with + | Some v -> ( + match I.of_path file with + | None -> assert false + | Some path -> ( + let key () = C.absolute_key s file in + match V_encoder.of_bytes ~key v with + | Ok v -> f path v acc + | Error _ -> return acc)) + | None -> return acc) + + let delete_snapshot s id = + let open Lwt_syntax in + let+ t = C.remove s (snapshot_path id) in + C.project t +end + +module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : + Indexed_raw_context + with type t = C.t + and type key = I.t + and type 'a ipath = 'a I.ipath + and type local_context = C.local_context = struct + type t = C.t + + type context = t + + type key = I.t + + type 'a ipath = 'a I.ipath + + type local_context = C.local_context + + let clear t = + let open Lwt_syntax in + let+ t = C.remove t [] in + C.project t + + let is_empty i = + let open Lwt_syntax in + let* root = C.find_tree i [] in + match root with + | None -> return_true + | Some root -> return @@ C.Tree.is_empty root + + let fold_keys t ~order ~init ~f = + C.fold ~depth:(`Eq I.path_length) t [] ~order ~init ~f:(fun path tree acc -> + match C.Tree.kind tree with + | `Tree -> ( + match I.of_path path with + | None -> assert false + | Some path -> f path acc) + | `Value -> Lwt.return acc) + + let keys t = + fold_keys t ~order:`Sorted ~init:[] ~f:(fun i acc -> Lwt.return (i :: acc)) + + let err_missing_key key = Raw_context.storage_error (Missing_key (key, Copy)) + + let copy t ~from ~to_ = + let open Lwt_result_syntax in + let from = I.to_path from [] in + let to_ = I.to_path to_ [] in + let*! tree_opt = C.find_tree t from in + match tree_opt with + | None -> Lwt.return (err_missing_key from) + | Some tree -> + let*! ctxt = C.add_tree t to_ tree in + return ctxt + + let remove t k = C.remove t (I.to_path k []) + + let description = + let open Lwt_result_syntax in + Storage_description.register_indexed_subcontext + ~list:(fun c -> + let*! result = keys c in + return result) + C.description + I.args + + let unpack = Storage_description.unpack I.args + + let pack = Storage_description.pack I.args + + module Raw_context : + Raw_context.T + with type t = C.t I.ipath + and type local_context = C.local_context = struct + type t = C.t I.ipath + + type local_context = C.local_context + + let to_key i k = I.to_path i k + + let mem c k = + let t, i = unpack c in + C.mem t (to_key i k) + + let mem_tree c k = + let t, i = unpack c in + C.mem_tree t (to_key i k) + + let get c k = + let t, i = unpack c in + C.get t (to_key i k) + + let get_tree c k = + let t, i = unpack c in + C.get_tree t (to_key i k) + + let find c k = + let t, i = unpack c in + C.find t (to_key i k) + + let find_tree c k = + let t, i = unpack c in + C.find_tree t (to_key i k) + + let list c ?offset ?length k = + let t, i = unpack c in + C.list t ?offset ?length (to_key i k) + + let init c k v = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t = C.init t (to_key i k) v in + pack t i + + let init_tree c k v = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t = C.init_tree t (to_key i k) v in + pack t i + + let update c k v = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t = C.update t (to_key i k) v in + pack t i + + let update_tree c k v = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t = C.update_tree t (to_key i k) v in + pack t i + + let add c k v = + let open Lwt_syntax in + let t, i = unpack c in + let+ t = C.add t (to_key i k) v in + pack t i + + let add_tree c k v = + let open Lwt_syntax in + let t, i = unpack c in + let+ t = C.add_tree t (to_key i k) v in + pack t i + + let add_or_remove c k v = + let open Lwt_syntax in + let t, i = unpack c in + let+ t = C.add_or_remove t (to_key i k) v in + pack t i + + let add_or_remove_tree c k v = + let open Lwt_syntax in + let t, i = unpack c in + let+ t = C.add_or_remove_tree t (to_key i k) v in + pack t i + + let remove_existing c k = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t = C.remove_existing t (to_key i k) in + pack t i + + let remove_existing_tree c k = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t = C.remove_existing_tree t (to_key i k) in + pack t i + + let remove c k = + let open Lwt_syntax in + let t, i = unpack c in + let+ t = C.remove t (to_key i k) in + pack t i + + let fold ?depth c k ~order ~init ~f = + let t, i = unpack c in + C.fold ?depth t (to_key i k) ~order ~init ~f + + let config c = + let t, _ = unpack c in + C.config t + + module Tree = struct + include C.Tree + + let empty c = + let t, _ = unpack c in + C.Tree.empty t + end + + module Proof = C.Proof + + let verify_tree_proof = C.verify_tree_proof + + let verify_stream_proof = C.verify_stream_proof + + let equal_config = C.equal_config + + let project c = + let t, _ = unpack c in + C.project t + + let absolute_key c k = + let t, i = unpack c in + C.absolute_key t (to_key i k) + + type error += Block_quota_exceeded = C.Block_quota_exceeded + + type error += Operation_quota_exceeded = C.Operation_quota_exceeded + + let consume_gas c g = + let open Result_syntax in + let t, i = unpack c in + let* t = C.consume_gas t g in + return (pack t i) + + let check_enough_gas c g = + let t, _i = unpack c in + C.check_enough_gas t g + + let description = description + + let length c = + let t, _i = unpack c in + C.length t + + let with_local_context c k f = + let open Lwt_result_syntax in + let t, i = unpack c in + let+ t, res = C.with_local_context t (to_key i k) f in + (pack t i, res) + + module Local_context = C.Local_context + end + + let with_local_context s i f = + let open Lwt_result_syntax in + let+ c, x = Raw_context.with_local_context (pack s i) [] f in + let s, _ = unpack c in + (s, x) + + module Make_set (R : REGISTER) (N : NAME) : + Data_set_storage with type t = t and type elt = key = struct + type t = C.t + + type context = t + + type elt = I.t + + let inited = Bytes.of_string "inited" + + let mem s i = Raw_context.mem (pack s i) N.name + + let add s i = + let open Lwt_syntax in + let+ c = Raw_context.add (pack s i) N.name inited in + let s, _ = unpack c in + C.project s + + let remove s i = + let open Lwt_syntax in + let+ c = Raw_context.remove (pack s i) N.name in + let s, _ = unpack c in + C.project s + + let clear s = + let open Lwt_syntax in + let+ t = + fold_keys s ~init:s ~order:`Sorted ~f:(fun i s -> + let+ c = Raw_context.remove (pack s i) N.name in + let s, _ = unpack c in + s) + in + C.project t + + let fold s ~order ~init ~f = + let open Lwt_syntax in + fold_keys s ~order ~init ~f:(fun i acc -> + let* result = mem s i in + match result with true -> f i acc | false -> Lwt.return acc) + + let elements s = + fold s ~order:`Sorted ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) + + let () = + let open Lwt_result_syntax in + let open Storage_description in + let unpack = unpack I.args in + let description = + if R.ghost then Storage_description.create () + else Raw_context.description + in + register_value + ~get:(fun c -> + let c, k = unpack c in + let*! result = mem c k in + match result with true -> return_some true | false -> return_none) + (register_named_subcontext description N.name) + Data_encoding.bool + end + + module Make_map (R : REGISTER) (N : NAME) (V : VALUE) : + Indexed_data_storage_with_local_context + with type t = t + and type key = key + and type value = V.t + and type local_context = local_context = struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + type nonrec local_context = local_context + + include Make_encoder (V) + + let is_empty i = + let open Lwt_syntax in + let* root = C.find_tree i [] in + match root with + | None -> return_true + | Some root -> return @@ C.Tree.is_empty root + + let mem s i = Raw_context.mem (pack s i) N.name + + let get s i = + let open Lwt_result_syntax in + let* b = Raw_context.get (pack s i) N.name in + let key () = Raw_context.absolute_key (pack s i) N.name in + let*? v = of_bytes ~key b in + return v + + let find s i = + let open Lwt_result_syntax in + let*! bytes_opt = Raw_context.find (pack s i) N.name in + match bytes_opt with + | None -> return_none + | Some b -> + let key () = Raw_context.absolute_key (pack s i) N.name in + let*? v = of_bytes ~key b in + return_some v + + let update s i v = + let open Lwt_result_syntax in + let+ c = Raw_context.update (pack s i) N.name (to_bytes v) in + let s, _ = unpack c in + C.project s + + let init s i v = + let open Lwt_result_syntax in + let+ c = Raw_context.init (pack s i) N.name (to_bytes v) in + let s, _ = unpack c in + C.project s + + let add s i v = + let open Lwt_syntax in + let+ c = Raw_context.add (pack s i) N.name (to_bytes v) in + let s, _ = unpack c in + C.project s + + let add_or_remove s i v = + let open Lwt_syntax in + let+ c = + Raw_context.add_or_remove (pack s i) N.name (Option.map to_bytes v) + in + let s, _ = unpack c in + C.project s + + let remove s i = + let open Lwt_syntax in + let+ c = Raw_context.remove (pack s i) N.name in + let s, _ = unpack c in + C.project s + + let remove_existing s i = + let open Lwt_result_syntax in + let+ c = Raw_context.remove_existing (pack s i) N.name in + let s, _ = unpack c in + C.project s + + let clear s = + let open Lwt_syntax in + let+ t = + fold_keys s ~order:`Sorted ~init:s ~f:(fun i s -> + let+ c = Raw_context.remove (pack s i) N.name in + let s, _ = unpack c in + s) + in + C.project t + + let fold s ~order ~init ~f = + let open Lwt_syntax in + fold_keys s ~order ~init ~f:(fun i acc -> + let* value_opt = get s i in + match value_opt with Error _ -> return acc | Ok v -> f i v acc) + + let bindings s = + fold s ~order:`Sorted ~init:[] ~f:(fun p v acc -> + Lwt.return ((p, v) :: acc)) + + let fold_keys s ~order ~init ~f = + let open Lwt_syntax in + fold_keys s ~order ~init ~f:(fun i acc -> + let* result = mem s i in + match result with false -> return acc | true -> f i acc) + + let keys s = + fold_keys s ~order:`Sorted ~init:[] ~f:(fun p acc -> + Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let unpack = unpack I.args in + let description = + if R.ghost then Storage_description.create () + else Raw_context.description + in + register_value + ~get:(fun c -> + let c, k = unpack c in + find c k) + (register_named_subcontext description N.name) + V.encoding + + module Local = struct + type context = Raw_context.Local_context.t + + let mem local = Raw_context.Local_context.mem local N.name + + let get local = + let open Lwt_result_syntax in + let* r = Raw_context.Local_context.get local N.name in + let key () = Raw_context.Local_context.absolute_key local N.name in + let*? v = of_bytes ~key r in + return v + + let find local = + let open Lwt_result_syntax in + let*! bytes_opt = Raw_context.Local_context.find local N.name in + match bytes_opt with + | None -> return_none + | Some b -> + let key () = Raw_context.Local_context.absolute_key local N.name in + let*? v = of_bytes ~key b in + return_some v + + let init local v = + Raw_context.Local_context.init local N.name (to_bytes v) + + let update local v = + Raw_context.Local_context.update local N.name (to_bytes v) + + let add local v = Raw_context.Local_context.add local N.name (to_bytes v) + + let add_or_remove local vo = + Raw_context.Local_context.add_or_remove + local + N.name + (Option.map to_bytes vo) + + let remove_existing local = + Raw_context.Local_context.remove_existing local N.name + + let remove local = Raw_context.Local_context.remove local N.name + end + end + + module Make_carbonated_map (R : REGISTER) (N : NAME) (V : VALUE) : + Non_iterable_indexed_carbonated_data_storage + with type t = t + and type key = key + and type value = V.t = struct + type t = C.t + + type context = t + + type key = I.t + + type value = V.t + + include Make_encoder (V) + + let len_name = len_name :: N.name + + let data_name = data_name :: N.name + + let consume_mem_gas c = + let path_length = List.length (Raw_context.absolute_key c N.name) + 1 in + Raw_context.consume_gas + c + (Storage_costs.read_access ~path_length ~read_bytes:0) + + let existing_size c = + let open Lwt_result_syntax in + let*! bytes_opt = Raw_context.find c len_name in + match bytes_opt with + | None -> return (0, false) + | Some len -> + let*? len = decode_len_value len_name len in + return (len, true) + + let consume_read_gas get c = + let open Lwt_result_syntax in + let path_length = List.length (Raw_context.absolute_key c N.name) + 1 in + let* len = get c len_name in + let*? read_bytes = decode_len_value len_name len in + let*? c = + Raw_context.consume_gas + c + (Storage_costs.read_access ~path_length ~read_bytes) + in + return c + + let consume_write_gas set c v = + let open Lwt_result_syntax in + let bytes = to_bytes v in + let len = Bytes.length bytes in + let*? c = + Raw_context.consume_gas + c + (Storage_costs.write_access ~written_bytes:len) + in + let+ c = set c len_name (encode_len_value bytes) in + (c, bytes) + + let consume_remove_gas del c = + let open Lwt_result_syntax in + let*? c = + Raw_context.consume_gas c (Storage_costs.write_access ~written_bytes:0) + in + del c len_name + + let mem s i = + let open Lwt_result_syntax in + let*? c = consume_mem_gas (pack s i) in + let*! res = Raw_context.mem c data_name in + return (Raw_context.project c, res) + + let get s i = + let open Lwt_result_syntax in + let* c = consume_read_gas Raw_context.get (pack s i) in + let* b = Raw_context.get c data_name in + let key () = Raw_context.absolute_key c data_name in + let*? v = of_bytes ~key b in + return (Raw_context.project c, v) + + let find s i = + let open Lwt_result_syntax in + let*? c = consume_mem_gas (pack s i) in + let s, _ = unpack c in + let*! exists = Raw_context.mem (pack s i) data_name in + if exists then + let+ s, v = get s i in + (s, Some v) + else return (C.project s, None) + + let update s i v = + let open Lwt_result_syntax in + let* prev_size, _ = existing_size (pack s i) in + let* c, bytes = consume_write_gas Raw_context.update (pack s i) v in + let+ c = Raw_context.update c data_name bytes in + let size_diff = Bytes.length bytes - prev_size in + (Raw_context.project c, size_diff) + + let init s i v = + let open Lwt_result_syntax in + let* c, bytes = consume_write_gas Raw_context.init (pack s i) v in + let+ c = Raw_context.init c data_name bytes in + let size = Bytes.length bytes in + (Raw_context.project c, size) + + let add s i v = + let open Lwt_result_syntax in + let add c k v = + let*! ctxt = Raw_context.add c k v in + return ctxt + in + let* prev_size, existed = existing_size (pack s i) in + let* c, bytes = consume_write_gas add (pack s i) v in + let+ c = add c data_name bytes in + let size_diff = Bytes.length bytes - prev_size in + (Raw_context.project c, size_diff, existed) + + let remove s i = + let open Lwt_result_syntax in + let remove c k = + let*! ctxt = Raw_context.remove c k in + return ctxt + in + let* prev_size, existed = existing_size (pack s i) in + let* c = consume_remove_gas remove (pack s i) in + let+ c = remove c data_name in + (Raw_context.project c, prev_size, existed) + + let remove_existing s i = + let open Lwt_result_syntax in + let* prev_size, _ = existing_size (pack s i) in + let* c = consume_remove_gas Raw_context.remove_existing (pack s i) in + let+ c = Raw_context.remove_existing c data_name in + (Raw_context.project c, prev_size) + + let add_or_remove s i v = + match v with None -> remove s i | Some v -> add s i v + + let mem_unaccounted s i = Raw_context.mem (pack s i) data_name + + let fold_keys_unaccounted s ~order ~init ~f = + let open Lwt_syntax in + fold_keys s ~order ~init ~f:(fun i acc -> + let* result = mem_unaccounted s i in + match result with false -> return acc | true -> f i acc) + + let keys_unaccounted s = + fold_keys_unaccounted s ~order:`Sorted ~init:[] ~f:(fun p acc -> + Lwt.return (p :: acc)) + + let () = + let open Storage_description in + let open Lwt_result_syntax in + let unpack = unpack I.args in + let description = + if R.ghost then Storage_description.create () + else Raw_context.description + in + register_value + ~get:(fun c -> + let c, k = unpack c in + let+ _, v = find c k in + v) + (register_named_subcontext description N.name) + V.encoding + end +end + +module type WRAPPER = sig + type t + + type key + + val wrap : t -> key + + val unwrap : key -> t option +end + +module Wrap_indexed_data_storage + (C : Indexed_data_storage) + (K : WRAPPER with type key := C.key) : + Indexed_data_storage + with type t = C.t + and type key = K.t + and type value = C.value = struct + type t = C.t + + type context = C.t + + type key = K.t + + type value = C.value + + let is_empty ctxt = C.is_empty ctxt + + let mem ctxt k = C.mem ctxt (K.wrap k) + + let get ctxt k = C.get ctxt (K.wrap k) + + let find ctxt k = C.find ctxt (K.wrap k) + + let update ctxt k v = C.update ctxt (K.wrap k) v + + let init ctxt k v = C.init ctxt (K.wrap k) v + + let add ctxt k v = C.add ctxt (K.wrap k) v + + let add_or_remove ctxt k v = C.add_or_remove ctxt (K.wrap k) v + + let remove_existing ctxt k = C.remove_existing ctxt (K.wrap k) + + let remove ctxt k = C.remove ctxt (K.wrap k) + + let clear ctxt = C.clear ctxt + + let fold ctxt ~order ~init ~f = + C.fold ctxt ~order ~init ~f:(fun k v acc -> + match K.unwrap k with None -> Lwt.return acc | Some k -> f k v acc) + + let bindings s = + fold s ~order:`Sorted ~init:[] ~f:(fun p v acc -> + Lwt.return ((p, v) :: acc)) + + let fold_keys s ~order ~init ~f = + C.fold_keys s ~order ~init ~f:(fun k acc -> + match K.unwrap k with None -> Lwt.return acc | Some k -> f k acc) + + let keys s = + fold_keys s ~order:`Sorted ~init:[] ~f:(fun p acc -> Lwt.return (p :: acc)) +end diff --git a/src/proto_020_PsParisC/lib_protocol/storage_functors.mli b/src/proto_020_PsParisC/lib_protocol/storage_functors.mli new file mode 100644 index 000000000000..8ab39501caf3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_functors.mli @@ -0,0 +1,125 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Tezos Protocol Implementation - Typed storage builders. + + Contains functors used by [Storage] to create the structure on + disk. + + See {!Make_subcontext} + *) + +open Storage_sigs + +module Registered : REGISTER + +module Ghost : REGISTER + +(** Given a [Raw_context], return a new [Raw_context] that projects into + a given subtree. Similar to a {i functional lens}. + *) +module Make_subcontext (_ : REGISTER) (C : Raw_context.T) (_ : NAME) : + Raw_context.T with type t = C.t + +module Make_single_data_storage + (_ : REGISTER) + (C : Raw_context.T) + (_ : NAME) + (V : VALUE) : Single_data_storage with type t = C.t and type value = V.t + +(** A type that can be serialized as a [string list], and used + as a prefix in the typed datastore. + + Useful to implement storage of maps and sets. + *) +module type INDEX = sig + type t + + include Path_encoding.S with type t := t + + type 'a ipath + + val args : ('a, t, 'a ipath) Storage_description.args +end + +module Pair (I1 : INDEX) (I2 : INDEX) : INDEX with type t = I1.t * I2.t + +(** Create storage for a compound type. *) +module Make_data_set_storage (C : Raw_context.T) (I : INDEX) : + Data_set_storage with type t = C.t and type elt = I.t + +(** Like [Make_data_set_storage], adding tracking of storage cost. *) +module Make_carbonated_data_set_storage (C : Raw_context.T) (I : INDEX) : + Carbonated_data_set_storage with type t = C.t and type elt = I.t + +(** This functor creates storage for types with a notion of an index. *) +module Make_indexed_data_storage (C : Raw_context.T) (I : INDEX) (V : VALUE) : + Indexed_data_storage with type t = C.t and type key = I.t and type value = V.t + +(** Like [Make_indexed_data_storage], adding tracking of storage cost. *) +module Make_indexed_carbonated_data_storage + (C : Raw_context.T) + (I : INDEX) + (V : VALUE) : + Indexed_carbonated_data_storage + with type t = C.t + and type key = I.t + and type value = V.t + +module Make_indexed_data_snapshotable_storage + (C : Raw_context.T) + (Snapshot : INDEX) + (I : INDEX) + (V : VALUE) : + Indexed_data_snapshotable_storage + with type t = C.t + and type snapshot = Snapshot.t + and type key = I.t + and type value = V.t + +module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : + Indexed_raw_context + with type t = C.t + and type key = I.t + and type 'a ipath = 'a I.ipath + +module type WRAPPER = sig + type t + + type key + + val wrap : t -> key + + val unwrap : key -> t option +end + +module Wrap_indexed_data_storage + (C : Indexed_data_storage) + (K : WRAPPER with type key := C.key) : + Indexed_data_storage + with type t = C.t + and type key = K.t + and type value = C.value diff --git a/src/proto_020_PsParisC/lib_protocol/storage_sigs.ml b/src/proto_020_PsParisC/lib_protocol/storage_sigs.ml new file mode 100644 index 000000000000..48cbc76adbc4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/storage_sigs.ml @@ -0,0 +1,517 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2019-2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** {1 Entity Accessor Signatures} *) + +(** The generic signature of a single data accessor (a single value + bound to a specific key in the hierarchical (key x value) + database). *) +module type Single_data_storage = sig + type t + + type context = t + + (** The type of the value *) + type value + + (** Tells if the data is already defined *) + val mem : context -> bool Lwt.t + + (** Retrieve the value from the storage bucket ; returns a + {!Storage_error} if the key is not set or if the deserialisation + fails *) + val get : context -> value tzresult Lwt.t + + (** Retrieves the value from the storage bucket ; returns [None] if + the data is not initialized, or {!Storage_helpers.Storage_error} + if the deserialisation fails *) + val find : context -> value option tzresult Lwt.t + + (** Allocates the storage bucket and initializes it ; returns a + {!Storage_error Existing_key} if the bucket exists *) + val init : context -> value -> Raw_context.t tzresult Lwt.t + + (** Updates the content of the bucket ; returns a {!Storage_Error + Missing_key} if the value does not exist *) + val update : context -> value -> Raw_context.t tzresult Lwt.t + + (** Allocates the data and initializes it with a value ; just + updates it if the bucket exists *) + val add : context -> value -> Raw_context.t Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], deletes the storage bucket ; does + nothing if the bucket does not exist. *) + val add_or_remove : context -> value option -> Raw_context.t Lwt.t + + (** Delete the storage bucket ; returns a {!Storage_error + Missing_key} if the bucket does not exist *) + val remove_existing : context -> Raw_context.t tzresult Lwt.t + + (** Removes the storage bucket and its contents ; does nothing if + the bucket does not exist *) + val remove : context -> Raw_context.t Lwt.t +end + +(** Restricted version of {!Indexed_data_storage} w/o iterators. *) +module type Non_iterable_indexed_data_storage = sig + type t + + type context = t + + (** An abstract type for keys *) + type key + + (** The type of values *) + type value + + (** Tells if a given key is already bound to a storage bucket *) + val mem : context -> key -> bool Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns {!Storage_error Missing_key} if the key is not set ; + returns {!Storage_error Corrupted_data} if the deserialisation + fails. *) + val get : context -> key -> value tzresult Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns [None] if the value is not set ; returns {!Storage_error + Corrupted_data} if the deserialisation fails. *) + val find : context -> key -> value option tzresult Lwt.t + + (** Updates the content of a bucket ; returns A {!Storage_Error + Missing_key} if the value does not exist. *) + val update : context -> key -> value -> Raw_context.t tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it ; + returns a {!Storage_error Existing_key} if the bucket exists. *) + val init : context -> key -> value -> Raw_context.t tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it + with a value ; just updates it if the bucket exists. *) + val add : context -> key -> value -> Raw_context.t Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], deletes the storage bucket ; does + nothing if the bucket does not exist. *) + val add_or_remove : context -> key -> value option -> Raw_context.t Lwt.t + + (** Delete a storage bucket and its contents ; returns a + {!Storage_error Missing_key} if the bucket does not exist. *) + val remove_existing : context -> key -> Raw_context.t tzresult Lwt.t + + (** Removes a storage bucket and its contents ; does nothing if the + bucket does not exist. *) + val remove : context -> key -> Raw_context.t Lwt.t +end + +(** Variant of {!Non_iterable_indexed_data_storage} with gas accounting. *) +module type Non_iterable_indexed_carbonated_data_storage = sig + type t + + type context = t + + (** An abstract type for keys *) + type key + + (** The type of values *) + type value + + (** Tells if a given key is already bound to a storage bucket. + Consumes [Gas_repr.read_bytes_cost Z.zero]. *) + val mem : context -> key -> (Raw_context.t * bool) tzresult Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns {!Storage_error Missing_key} if the key is not set ; + returns {!Storage_error Corrupted_data} if the deserialisation + fails. + Consumes [Gas_repr.read_bytes_cost ]. *) + val get : context -> key -> (Raw_context.t * value) tzresult Lwt.t + + (** Retrieve a value from the storage bucket at a given key ; + returns [None] if the value is not set ; returns {!Storage_error + Corrupted_data} if the deserialisation fails. + Consumes [Gas_repr.read_bytes_cost ] if present + or [Gas_repr.read_bytes_cost Z.zero]. *) + val find : context -> key -> (Raw_context.t * value option) tzresult Lwt.t + + (** Updates the content of a bucket ; returns A {!Storage_Error + Missing_key} if the value does not exist. + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the difference from the old to the new size. *) + val update : context -> key -> value -> (Raw_context.t * int) tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it ; + returns a {!Storage_error Existing_key} if the bucket exists. + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the size. *) + val init : context -> key -> value -> (Raw_context.t * int) tzresult Lwt.t + + (** Allocates a storage bucket at the given key and initializes it + with a value ; just updates it if the bucket exists. + Consumes serialization cost. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the difference from the old (maybe 0) to the new size, and a boolean + indicating if a value was already associated to this key. *) + val add : + context -> key -> value -> (Raw_context.t * int * bool) tzresult Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], deletes the storage bucket ; does + nothing if the bucket does not exist + Consumes serialization cost. + Consumes the same gas cost as either {!remove} or {!init_set}. + Returns the difference from the old (maybe 0) to the new size, and a boolean + indicating if a value was already associated to this key. *) + val add_or_remove : + context -> + key -> + value option -> + (Raw_context.t * int * bool) tzresult Lwt.t + + (** Delete a storage bucket and its contents ; returns a + {!Storage_error Missing_key} if the bucket does not exist. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + Returns the freed size. *) + val remove_existing : context -> key -> (Raw_context.t * int) tzresult Lwt.t + + (** Removes a storage bucket and its contents ; does nothing if the + bucket does not exist. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + Returns the freed size, and a boolean + indicating if a value was already associated to this key. *) + val remove : context -> key -> (Raw_context.t * int * bool) tzresult Lwt.t + + (** Returns the list of all storage bucket keys. + Not carbonated (i.e. gas is not consumed); use with care. *) + val keys_unaccounted : context -> key list Lwt.t +end + +module type Indexed_carbonated_data_storage = sig + include Non_iterable_indexed_carbonated_data_storage + + (** [list_key_values ?offset ?length storage] lists the key and value pairs of + each entry in the given [storage]. The first [offset] values are ignored + (if passed). Negative offsets are treated as [0]. There will be no more + than [length] values in the result list (if passed). Negative values are + treated as [0]. + + The returned {!context} takes into account gas consumption of traversing + the keys and loading values. *) + val list_key_values : + ?offset:int -> + ?length:int -> + t -> + (Raw_context.t * (key * value) list) tzresult Lwt.t + + (** Returns [true] iff [context] is empty. + Consumes [Gas_repr.read_bytes_cost Z.zero].*) + val is_empty : context -> (Raw_context.t * bool) tzresult Lwt.t + + (** [clear storage] removes all values from the storage. + Consumes [Gas_repr.write_bytes_cost Z.zero] .*) + val clear : context -> Raw_context.t tzresult Lwt.t +end + +module type Indexed_carbonated_data_storage_INTERNAL = sig + include Indexed_carbonated_data_storage + + val fold_keys_unaccounted : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(key -> 'a -> 'a Lwt.t) -> + 'a Lwt.t +end + +(** The generic signature of indexed data accessors (a set of values + of the same type indexed by keys of the same form in the + hierarchical (key x value) database). *) +module type Indexed_data_storage = sig + include Non_iterable_indexed_data_storage + + (** Empties all the keys and associated data. *) + val clear : context -> Raw_context.t Lwt.t + + (** Lists all the keys. *) + val keys : context -> key list Lwt.t + + (** Lists all the keys and associated data. *) + val bindings : context -> (key * value) list Lwt.t + + (** Iterates over all the keys and associated data. *) + val fold : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(key -> value -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + (** Iterate over all the keys. *) + val fold_keys : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(key -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + (** Returns [true] iff [context] is empty. *) + val is_empty : context -> bool Lwt.t +end + +module type Indexed_data_storage_with_local_context = sig + include Indexed_data_storage + + type local_context + + module Local : sig + type context = local_context + + (** Tells if the data is already defined *) + val mem : context -> bool Lwt.t + + (** Retrieves the value from the storage bucket; returns a + {!Storage_error} if the key is not set or if the deserialisation + fails *) + val get : context -> value tzresult Lwt.t + + (** Retrieves the value from the storage bucket ; returns [None] if + the data is not initialized, or {!Storage_helpers.Storage_error} + if the deserialisation fails *) + val find : context -> value option tzresult Lwt.t + + (** Allocates the storage bucket and initializes it ; returns a + {!Storage_error Existing_key} if the bucket exists *) + val init : context -> value -> context tzresult Lwt.t + + (** Updates the content of the bucket; returns a {!Storage_Error + Missing_key} if the value does not exist *) + val update : context -> value -> context tzresult Lwt.t + + (** Allocates the data and initializes it with a value ; just + updates it if the bucket exists *) + val add : context -> value -> context Lwt.t + + (** When the value is [Some v], allocates the data and initializes + it with [v] ; just updates it if the bucket exists. When the + value is [None], deletes the storage bucket ; it does + nothing if the bucket does not exist. *) + val add_or_remove : context -> value option -> context Lwt.t + + (** Delete the storage bucket ; returns a {!Storage_error + Missing_key} if the bucket does not exist *) + val remove_existing : context -> context tzresult Lwt.t + + (** Removes the storage bucket and its contents; does nothing if + the bucket does not exist *) + val remove : context -> context Lwt.t + end +end + +module type Indexed_data_snapshotable_storage = sig + type snapshot + + type key + + include Indexed_data_storage with type key := key + + module Snapshot : + Indexed_data_storage + with type key = snapshot * key + and type value = value + and type t = t + + val snapshot_exists : context -> snapshot -> bool Lwt.t + + val snapshot : context -> snapshot -> Raw_context.t tzresult Lwt.t + + val fold_snapshot : + context -> + snapshot -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(key -> value -> 'a -> 'a tzresult Lwt.t) -> + 'a tzresult Lwt.t + + val delete_snapshot : context -> snapshot -> Raw_context.t Lwt.t +end + +(** The generic signature of a data set accessor (a set of values + bound to a specific key prefix in the hierarchical (key x value) + database). *) +module type Data_set_storage = sig + type t + + type context = t + + (** The type of elements. *) + type elt + + (** Tells if an elt is a member of the set *) + val mem : context -> elt -> bool Lwt.t + + (** Adds an elt as a member of the set *) + val add : context -> elt -> Raw_context.t Lwt.t + + (** Removes an elt from the set ; does nothing if not a member *) + val remove : context -> elt -> Raw_context.t Lwt.t + + (** Returns the elements of the set, deserialized in a list in no + particular order. *) + val elements : context -> elt list Lwt.t + + (** Iterates over the elements of the set. *) + val fold : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(elt -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + (** Removes all elements in the set *) + val clear : context -> Raw_context.t Lwt.t +end + +(** Variant of {!Data_set_storage} with gas accounting. *) +module type Carbonated_data_set_storage = sig + type t + + type context = t + + (** The type of elements. *) + type elt + + (** Returns true if and only if the set contains no elements. + Consumes [Gas_repr.read_bytes_cost Z.zero].*) + val is_empty : context -> (Raw_context.t * bool) tzresult Lwt.t + + (** Tells whether an elt is a member of the set. + Consumes [Gas_repr.read_bytes_cost Z.zero] *) + val mem : context -> elt -> (Raw_context.t * bool) tzresult Lwt.t + + (** Adds an elt as a member of the set. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the new size. *) + val init : context -> elt -> (Raw_context.t * int) tzresult Lwt.t + + (** Adds an elt as a member of the set. + Consumes [Gas_repr.write_bytes_cost ]. + Returns the new size, and true if the value previously existed. *) + val add : context -> elt -> (Raw_context.t * int * bool) tzresult Lwt.t + + (** Removes an elt from the set ; does nothing if not a member. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + Returns the freed size, and a boolean + indicating if a value was already associated to this key. *) + val remove : context -> elt -> (Raw_context.t * int * bool) tzresult Lwt.t + + (** Removes all elt from the set. + Consumes [Gas_repr.write_bytes_cost Z.zero]. + + This function does not returns the freed size. This is because + it would need to fold over all keys or add a size accumulator + and no usage exists so far. *) + val clear : context -> Raw_context.t tzresult Lwt.t + + val fold_keys_unaccounted : + context -> + order:[`Sorted | `Undefined] -> + init:'acc -> + f:(elt -> 'acc -> 'acc Lwt.t) -> + 'acc Lwt.t +end + +module type NAME = sig + val name : Raw_context.key +end + +module type VALUE = sig + type t + + val encoding : t Data_encoding.t +end + +module type REGISTER = sig + val ghost : bool +end + +module type Indexed_raw_context = sig + type t + + type context = t + + type key + + type 'a ipath + + type local_context + + val clear : context -> Raw_context.t Lwt.t + + val is_empty : context -> bool Lwt.t + + val fold_keys : + context -> + order:[`Sorted | `Undefined] -> + init:'a -> + f:(key -> 'a -> 'a Lwt.t) -> + 'a Lwt.t + + val keys : context -> key list Lwt.t + + val remove : context -> key -> context Lwt.t + + val copy : context -> from:key -> to_:key -> context tzresult Lwt.t + + val with_local_context : + context -> + key -> + (local_context -> (local_context * 'a) tzresult Lwt.t) -> + (context * 'a) tzresult Lwt.t + + module Make_set (_ : REGISTER) (_ : NAME) : + Data_set_storage with type t = t and type elt = key + + module Make_map (_ : REGISTER) (_ : NAME) (V : VALUE) : + Indexed_data_storage_with_local_context + with type t = t + and type key = key + and type value = V.t + and type local_context = local_context + + module Make_carbonated_map (_ : REGISTER) (_ : NAME) (V : VALUE) : + Non_iterable_indexed_carbonated_data_storage + with type t = t + and type key = key + and type value = V.t + + module Raw_context : Raw_context.T with type t = t ipath +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/README.md b/src/proto_020_PsParisC/lib_protocol/test/README.md new file mode 100644 index 000000000000..d938f4e7cb3d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/README.md @@ -0,0 +1,30 @@ +# lib_protocol tests + +This folder contains unit, integration and property-based tests for +the economic protocol definition. The tests are organized in +sub-folders: first by type of test, and for integration, a further +subdivision by theme: + +- `unit`: tests that sit below `Alpha_context`. +- `integration`: tests that require passing around a context. + - `michelson`: tests that involve Micheline expressions. + - `consensus`: tests for consensus: baking, attestation, etc. + - `gas`: tests for gas. + - `operations`: test for operations. +- `pbt`: for property-based tests using `qcheck`. + +Finally, `helpers/` contains common definitions for writing tests. + +There might not be a clear-cut location for new tests. For new +integration tests, either add them directly to `integration/` or +create a new sub-folder corresponding to the theme of the test. + +# Running + +To run all the tests, run: + +``` +dune runtest src/proto_alpha/lib_protocol/ +``` + +To run an individual test file, consult its `Invocation` header. diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/README.md b/src/proto_020_PsParisC/lib_protocol/test/helpers/README.md new file mode 100644 index 000000000000..b071cfb4ec03 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/README.md @@ -0,0 +1,3 @@ +## Helpers to build unit/integration tests for the protocol + +The OPAM package `tezos-alpha-test-helpers` contains helpers to build unit/integration tests, like forging a block, a context, nonces, operations, etc. diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/account.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/account.ml new file mode 100644 index 000000000000..444ccc5e4d52 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/account.ml @@ -0,0 +1,147 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + pkh : Signature.Public_key_hash.t; + pk : Signature.Public_key.t; + sk : Signature.Secret_key.t; +} + +type account = t + +let known_accounts = Signature.Public_key_hash.Table.create 17 + +let random_seed ~rng_state = + Bytes.init Tezos_crypto.Hacl.Ed25519.sk_size (fun _i -> + Char.chr (Random.State.int rng_state 256)) + +let random_algo ~rng_state : Signature.algo = + match Random.State.int rng_state 3 with + | 0 -> Ed25519 + | 1 -> Secp256k1 + | 2 -> P256 + | 3 -> Bls + | _ -> assert false + +let new_account ?(rng_state = Random.State.make_self_init ()) + ?(seed = random_seed ~rng_state) ?(algo = random_algo ~rng_state) () = + let pkh, pk, sk = Signature.generate_key ~algo ~seed () in + let account = {pkh; pk; sk} in + Signature.Public_key_hash.Table.add known_accounts pkh account ; + account + +let add_account ({pkh; _} as account) = + Signature.Public_key_hash.Table.add known_accounts pkh account + +let activator_account = + let seed = random_seed ~rng_state:(Random.State.make [|0x1337533D|]) in + new_account ~seed () + +let find pkh = + let open Lwt_result_syntax in + match Signature.Public_key_hash.Table.find known_accounts pkh with + | Some k -> return k + | None -> failwith "Missing account: %a" Signature.Public_key_hash.pp pkh + +let find_alternate pkh = + let exception Found of t in + try + Signature.Public_key_hash.Table.iter + (fun pkh' account -> + if not (Signature.Public_key_hash.equal pkh pkh') then + raise (Found account)) + known_accounts ; + raise Not_found + with Found account -> account + +let dummy_account = + let seed = + random_seed ~rng_state:(Random.State.make [|0x1337533D; 0x1337533D|]) + in + new_account ~seed () + +let default_initial_balance = Tez.of_mutez_exn 4_000_000_000_000L + +let generate_accounts ?rng_state n : t list tzresult = + Signature.Public_key_hash.Table.clear known_accounts ; + List.init ~when_negative_length:[] n (fun _i -> new_account ?rng_state ()) + +let commitment_secret = + Blinded_public_key_hash.activation_code_of_hex + "aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb" + |> WithExceptions.Option.get ~loc:__LOC__ + +let new_commitment ?seed () = + let open Lwt_result_wrap_syntax in + let pkh, pk, sk = Signature.generate_key ?seed ~algo:Ed25519 () in + let unactivated_account = {pkh; pk; sk} in + let open Commitment in + let pkh = match pkh with Ed25519 pkh -> pkh | _ -> assert false in + let bpkh = Blinded_public_key_hash.of_ed25519_pkh commitment_secret pkh in + let*?@ amount = Tez.(one *? 4_000L) in + return (unactivated_account, {blinded_public_key_hash = bpkh; amount}) + +let pkh_of_contract_exn = function + | Contract.Implicit pkh -> pkh + | Originated _ -> assert false + +let make_bootstrap_account ?(balance = default_initial_balance) + ?(delegate_to = None) ?(consensus_key = None) account = + Parameters. + { + public_key_hash = account.pkh; + public_key = Some account.pk; + amount = balance; + delegate_to; + consensus_key; + } + +let rec make_bootstrap_accounts ?(bootstrap_balances = []) + ?(bootstrap_delegations = []) ?(bootstrap_consensus_keys = []) accounts = + let decons_of_opt = function x :: xs -> (x, xs) | [] -> (None, []) in + let decons = function x :: xs -> (Some x, xs) | [] -> (None, []) in + match accounts with + | account :: accounts -> + let balance, bootstrap_balances = decons bootstrap_balances in + let delegate_to, bootstrap_delegations = + decons_of_opt bootstrap_delegations + in + let consensus_key, bootstrap_consensus_keys = + decons_of_opt bootstrap_consensus_keys + in + make_bootstrap_account + ?balance:(Option.map Tez.of_mutez_exn balance) + ~delegate_to + ~consensus_key + account + :: make_bootstrap_accounts + ~bootstrap_balances + ~bootstrap_delegations + ~bootstrap_consensus_keys + accounts + | [] -> [] diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/account.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/account.mli new file mode 100644 index 000000000000..62ae056b2e6a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/account.mli @@ -0,0 +1,100 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + pkh : Signature.Public_key_hash.t; + pk : Signature.Public_key.t; + sk : Signature.Secret_key.t; +} + +type account = t + +val known_accounts : t Signature.Public_key_hash.Table.t + +val activator_account : account + +val dummy_account : account + +(** [new_account ?rng_state ?seed ?algo ()] creates a new account with curve + [algo] with the given [seed] (or [rng_state] to generate the seed) and add + it to the global account state. +*) +val new_account : + ?rng_state:Random.State.t -> + ?seed:Bytes.t -> + ?algo:Signature.algo -> + unit -> + account + +val add_account : t -> unit + +val find : Signature.Public_key_hash.t -> t tzresult Lwt.t + +val find_alternate : Signature.Public_key_hash.t -> t + +(** 4.000.000.000 tez *) +val default_initial_balance : Tez.t + +(** [generate_accounts ?rng_state n] first frees the global account state then + generates [n] random accounts with [rng_state] to generate the seed and adds + them to the global account state. +*) +val generate_accounts : ?rng_state:Random.State.t -> int -> t list tzresult + +val commitment_secret : Blinded_public_key_hash.activation_code + +val new_commitment : + ?seed:Bytes.t -> unit -> (account * Commitment.t) tzresult Lwt.t + +(** Fails if the contract is not an implicit one *) +val pkh_of_contract_exn : Contract.t -> Signature.Public_key_hash.t + +(** [make_bootstrap_account ~initial_balance ~delegate_to account] creates a + {!Parameters.bootstrap_account} from an account with the default or set + values. default [initial_balance] is [default_initial_balance], + [delegate_to] is [None] and [consensus_key] is [None]. +*) +val make_bootstrap_account : + ?balance:Tez.t -> + ?delegate_to:Signature.public_key_hash option -> + ?consensus_key:Signature.public_key option -> + t -> + Parameters.bootstrap_account + +(** [make_bootstrap_accounts ~bootstrap_balances ~bootstrap_delegations + ~bootstrap_consensus_keys accounts] combines the lists [accounts], + [bootstrap_balances], [bootstrap_delegations] and [bootstrap_consensus_keys] + to create a list of {!Parameters.bootstrap_account} using + [make_bootstrap_account]. +*) +val make_bootstrap_accounts : + ?bootstrap_balances:int64 list -> + ?bootstrap_delegations:Signature.public_key_hash option list -> + ?bootstrap_consensus_keys:Signature.public_key option list -> + t list -> + Parameters.bootstrap_account list diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/adaptive_issuance_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/adaptive_issuance_helpers.ml new file mode 100644 index 000000000000..504bb7859556 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/adaptive_issuance_helpers.ml @@ -0,0 +1,1276 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let join_errors e1 e2 = + let open Lwt_result_syntax in + match (e1, e2) with + | Ok (), Ok () -> return_unit + | Error e, Ok () | Ok (), Error e -> fail e + | Error e1, Error e2 -> fail (e1 @ e2) + +(** Tez manipulation module *) +module Tez = struct + include Protocol.Alpha_context.Tez + + let ( + ) a b = + let open Lwt_result_wrap_syntax in + let*?@ s = a +? b in + return s + + let ( - ) a b = + let open Lwt_result_wrap_syntax in + let*?@ s = a -? b in + return s + + let ( +! ) a b = + let a = to_mutez a in + let b = to_mutez b in + Int64.add a b |> of_mutez_exn + + let ( -! ) a b = + let a = to_mutez a in + let b = to_mutez b in + Int64.sub a b |> of_mutez_exn + + let of_mutez = of_mutez_exn + + let of_z a = Z.to_int64 a |> of_mutez + + let of_q ~round_up Q.{num; den} = + (if round_up then Z.cdiv num den else Z.div num den) |> of_z + + let ratio num den = + Q.make (Z.of_int64 (to_mutez num)) (Z.of_int64 (to_mutez den)) + + let mul_q tez portion = + let tez_z = to_mutez tez |> Z.of_int64 in + Q.(mul portion ~$$tez_z) +end + +(** Representation of Tez with non integer values *) +module Partial_tez = struct + include Q + + let of_tez a = Tez.to_mutez a |> of_int64 + + let to_tez_rem {num; den} = + let tez, rem = Z.div_rem num den in + (Tez.of_z tez, rem /// den) + + let to_tez ~round_up = Tez.of_q ~round_up + + let get_rem a = snd (to_tez_rem a) + + let pp fmt a = + let tez, rem = to_tez_rem a in + (* If rem = 0, we keep the (+ 0), to indicate that it's a partial tez *) + Format.fprintf fmt "%a ( +%aµꜩ )" Tez.pp tez Q.pp_print rem +end + +module Cycle = Protocol.Alpha_context.Cycle + +(** [Frozen_tez] represents frozen stake and frozen unstaked funds. + Properties: + - sum of all current partial tez is an integer + - Can only add integer amounts + - Can always subtract integer amount (if lower than frozen amount) + - If subtracting partial amount, must be the whole frozen amount (for given contract). + The remainder is then distributed equally amongst remaining accounts, to keep property 1. + - All entries of current are positive, non zero. +*) +module Frozen_tez = struct + (* The map in current maps the stakers' name with their staked value. + It contains only delegators of the delegate which owns the frozen tez *) + type t = { + delegate : string; + initial : Tez.t; + self_current : Tez.t; + co_current : Partial_tez.t String.Map.t; + } + + let zero = + { + delegate = ""; + initial = Tez.zero; + self_current = Tez.zero; + co_current = String.Map.empty; + } + + let init amount account delegate = + if account = delegate then + { + delegate; + initial = amount; + self_current = amount; + co_current = String.Map.empty; + } + else + { + delegate; + initial = amount; + self_current = Tez.zero; + co_current = String.Map.singleton account (Partial_tez.of_tez amount); + } + + let union a b = + assert (a.delegate = b.delegate) ; + { + delegate = a.delegate; + initial = Tez.(a.initial +! b.initial); + self_current = Tez.(a.self_current +! b.self_current); + co_current = + String.Map.union + (fun _ x y -> Some Partial_tez.(x + y)) + a.co_current + b.co_current; + } + + let get account frozen_tez = + if account = frozen_tez.delegate then + Partial_tez.of_tez frozen_tez.self_current + else + match String.Map.find account frozen_tez.co_current with + | None -> Partial_tez.zero + | Some p -> p + + let total_co_current_q co_current = + String.Map.fold + (fun _ x acc -> Partial_tez.(x + acc)) + co_current + Partial_tez.zero + + let total_current a = + let r = total_co_current_q a.co_current in + let tez, rem = Partial_tez.to_tez_rem r in + assert (Q.(equal rem zero)) ; + Tez.(tez +! a.self_current) + + let add_q_to_all_co_current quantity co_current = + let s = total_co_current_q co_current in + let f p_amount = + let q = Q.div p_amount s in + Partial_tez.add p_amount (Q.mul quantity q) + in + String.Map.map f co_current + + (* For rewards, distribute equally *) + let add_tez_to_all_current tez a = + let self_portion = Tez.ratio a.self_current (total_current a) in + let self_quantity = Tez.mul_q tez self_portion |> Tez.of_q ~round_up:true in + let co_quantity = Partial_tez.of_tez Tez.(tez -! self_quantity) in + let co_current = add_q_to_all_co_current co_quantity a.co_current in + {a with co_current; self_current = Tez.(a.self_current +! self_quantity)} + + (* For slashing, slash equally *) + let sub_tez_from_all_current tez a = + let self_portion = Tez.ratio a.self_current (total_current a) in + let self_quantity = + Tez.mul_q tez self_portion |> Tez.of_q ~round_up:false + in + let self_current = + if Tez.(self_quantity >= a.self_current) then Tez.zero + else Tez.(a.self_current -! self_quantity) + in + let co_quantity = Tez.(tez -! self_quantity) in + let s = total_co_current_q a.co_current in + if Partial_tez.(geq (of_tez co_quantity) s) then + {a with self_current; co_current = String.Map.empty} + else + let f p_amount = + let q = Q.div p_amount s in + Partial_tez.sub p_amount (Tez.mul_q co_quantity q) + (* > 0 *) + in + {a with self_current; co_current = String.Map.map f a.co_current} + + (* Adds frozen to account. Happens each stake in frozen deposits *) + let add_current amount account a = + if account = a.delegate then + {a with self_current = Tez.(a.self_current +! amount)} + else + { + a with + co_current = + String.Map.update + account + (function + | None -> Some (Partial_tez.of_tez amount) + | Some q -> Some Partial_tez.(add q (of_tez amount))) + a.co_current; + } + + (* Adds frozen to account. Happens each unstake to unstaked frozen deposits *) + let add_init amount account a = union a (init amount account a.delegate) + + (* Allows amount greater than current frozen amount. + Happens each unstake in frozen deposits *) + let sub_current amount account a = + if account = a.delegate then + let amount = Tez.min amount a.self_current in + ({a with self_current = Tez.(a.self_current -! amount)}, amount) + else + match String.Map.find account a.co_current with + | None -> (a, Tez.zero) + | Some frozen -> + let amount_q = Partial_tez.of_tez amount in + if Q.(geq amount_q frozen) then + let removed, remainder = Partial_tez.to_tez_rem frozen in + let co_current = String.Map.remove account a.co_current in + let co_current = add_q_to_all_co_current remainder co_current in + ({a with co_current}, removed) + else + let co_current = + String.Map.add account Q.(frozen - amount_q) a.co_current + in + ({a with co_current}, amount) + + let sub_current_and_init amount account a = + let a, amount = sub_current amount account a in + ({a with initial = Tez.(a.initial -! amount)}, amount) + + let slash base_amount (pct : Protocol.Percentage.t) a = + let pct_q = Protocol.Percentage.to_q pct in + let slashed_amount = + Tez.mul_q base_amount pct_q |> Tez.of_q ~round_up:false + in + let total_current = total_current a in + let slashed_amount_final = Tez.min slashed_amount total_current in + (sub_tez_from_all_current slashed_amount a, slashed_amount_final) +end + +(** Representation of Unstaked frozen deposits *) +module Unstaked_frozen = struct + type r = { + cycle : Cycle.t; + (* initial total requested amount (slash ∝ initial) *) + initial : Tez.t; + (* current amount, slashes applied here *) + current : Tez.t; + (* initial requests, don't apply slash unless finalize or balance query *) + requests : Tez.t String.Map.t; + (* slash pct memory for requests *) + slash_pct : int; + } + + type t = r list + + type get_info = {cycle : Cycle.t; request : Tez.t; current : Tez.t} + + type get_info_list = get_info list + + type finalizable_info = { + amount : Tez.t; + slashed_requests : Tez.t String.Map.t; + } + + let zero = [] + + let init_r cycle request account = + { + cycle; + initial = request; + current = request; + requests = String.Map.singleton account request; + slash_pct = 0; + } + + let apply_slash_to_request slash_pct amount = + let slashed_amount = + Tez.mul_q amount Q.(slash_pct // 100) |> Tez.of_q ~round_up:true + in + Tez.(amount -! slashed_amount) + + let apply_slash_to_current slash_pct initial current = + let slashed_amount = + Tez.mul_q initial Q.(slash_pct // 100) |> Tez.of_q ~round_up:false + in + Tez.sub_opt current slashed_amount |> Option.value ~default:Tez.zero + + let remove_zeros (a : t) : t = + List.filter (fun ({current; _} : r) -> Tez.(current > zero)) a + + let get account unstaked : get_info_list = + List.filter_map + (fun {cycle; requests; slash_pct; _} -> + String.Map.find account requests + |> Option.map (fun request -> + { + cycle; + request; + current = apply_slash_to_request slash_pct request; + })) + unstaked + + let get_total account unstaked = + get account unstaked + |> List.fold_left + (fun acc ({current; _} : get_info) -> Tez.(acc +! current)) + Tez.zero + + let sum_current unstaked = + List.fold_left + (fun acc ({current; _} : r) -> Tez.(acc +! current)) + Tez.zero + unstaked + + (* Happens each unstake operation *) + let rec add_unstake cycle amount account : t -> t = function + | [] -> [init_r cycle amount account] + | ({cycle = c; requests; initial; current; slash_pct} as h) :: t -> + let open Tez in + if Cycle.equal c cycle then ( + assert (Int.equal slash_pct 0) ; + { + cycle; + initial = initial +! amount; + current = current +! amount; + slash_pct; + requests = + String.Map.update + account + (function + | None -> Some amount | Some x -> Some Tez.(x +! amount)) + requests; + } + :: t) + else h :: add_unstake cycle amount account t + + (* Happens in stake from unstake *) + let sub_unstake amount account : r -> r = + fun {cycle; requests; initial; current; slash_pct} -> + assert (slash_pct = 0) ; + let open Tez in + { + cycle; + initial = initial -! amount; + current = current -! amount; + slash_pct; + requests = + String.Map.update + account + (function + | None -> + assert (Tez.(amount = zero)) ; + None + | Some x -> + if Tez.(x = amount) then None else Some Tez.(x -! amount)) + requests; + } + + (* Makes given cycle finalizable (and unslashable) *) + let rec pop_cycle cycle : t -> finalizable_info * t = function + | [] -> ({amount = Tez.zero; slashed_requests = String.Map.empty}, []) + | ({cycle = c; requests; initial = _; current; slash_pct} as h) :: t -> + if Cycle.(c = cycle) then + let amount = current in + let slashed_requests = + String.Map.map (apply_slash_to_request slash_pct) requests + in + ({amount; slashed_requests}, t) + else if Cycle.(c < cycle) then + Stdlib.failwith + "Unstaked_frozen: found unfinalized cycle before given [cycle]. \ + Make sure to call [apply_unslashable] every cycle" + else + let info, rest = pop_cycle cycle t in + (info, h :: rest) + + let slash ~slashable_deposits_period slashed_cycle pct_times_100 a = + remove_zeros a + |> List.map + (fun + ({cycle; requests = _; initial; current; slash_pct = old_slash_pct} + as r) + -> + if + Cycle.( + cycle > slashed_cycle + || add cycle slashable_deposits_period < slashed_cycle) + then (r, Tez.zero) + else + let new_current = + apply_slash_to_current pct_times_100 initial current + in + let slashed = Tez.(current -! new_current) in + let slash_pct = min 100 (pct_times_100 + old_slash_pct) in + ({r with slash_pct; current = new_current}, slashed)) + |> List.split +end + +(** Representation of unstaked finalizable tez *) +module Unstaked_finalizable = struct + (* Slashing might put inaccessible tez in this container: they are represented in the remainder. + They still count towards the total supply, but are currently owned by noone. + At most one mutez per unstaking account per slashed cycle *) + type t = {map : Tez.t String.Map.t; remainder : Tez.t} + + let zero = {map = String.Map.empty; remainder = Tez.zero} + + (* Called when unstaked frozen for some cycle becomes finalizable *) + let add_from_poped_ufd + ({amount; slashed_requests} : Unstaked_frozen.finalizable_info) + {map; remainder} = + let total_requested = + String.Map.fold (fun _ x acc -> Tez.(x +! acc)) slashed_requests Tez.zero + in + let remainder = Tez.(remainder +! amount -! total_requested) in + let map = + String.Map.union (fun _ a b -> Some Tez.(a +! b)) map slashed_requests + in + {map; remainder} + + let total {map; remainder} = + String.Map.fold (fun _ x acc -> Tez.(x +! acc)) map remainder + + let get account {map; _} = + match String.Map.find account map with None -> Tez.zero | Some x -> x +end + +(** Abstraction of the staking parameters for tests *) +type staking_parameters = { + limit_of_staking_over_baking : Q.t; + edge_of_baking_over_staking : Q.t; +} + +module CycleMap = Map.Make (Cycle) + +(** Abstract information of accounts *) +type account_state = { + pkh : Signature.Public_key_hash.t; + contract : Protocol.Alpha_context.Contract.t; + delegate : string option; + parameters : staking_parameters; + liquid : Tez.t; + bonds : Tez.t; + (* The three following fields contain maps from the account's stakers to, + respectively, their frozen stake, their unstaked frozen balance, and + their unstaked finalizable funds. Additionally, [unstaked_frozen] indexes + the maps with the cycle at which the unstake operation occurred. *) + frozen_deposits : Frozen_tez.t; + unstaked_frozen : Unstaked_frozen.t; + unstaked_finalizable : Unstaked_finalizable.t; + staking_delegator_numerator : Z.t; + staking_delegate_denominator : Z.t; + frozen_rights : Tez.t CycleMap.t; + slashed_cycles : Cycle.t list; +} + +let init_account ?delegate ~pkh ~contract ~parameters ?(liquid = Tez.zero) + ?(bonds = Tez.zero) ?(frozen_deposits = Frozen_tez.zero) + ?(unstaked_frozen = Unstaked_frozen.zero) + ?(unstaked_finalizable = Unstaked_finalizable.zero) + ?(staking_delegator_numerator = Z.zero) + ?(staking_delegate_denominator = Z.zero) ?(frozen_rights = CycleMap.empty) + ?(slashed_cycles = []) () = + { + pkh; + contract; + delegate; + parameters; + liquid; + bonds; + frozen_deposits; + unstaked_frozen; + unstaked_finalizable; + staking_delegator_numerator; + staking_delegate_denominator; + frozen_rights; + slashed_cycles; + } + +type account_map = account_state String.Map.t + +(** Balance returned by RPCs. Partial tez are rounded down *) +type balance = { + liquid_b : Tez.t; + bonds_b : Tez.t; + staked_b : Partial_tez.t; + unstaked_frozen_b : Tez.t; + unstaked_finalizable_b : Tez.t; + staking_delegator_numerator_b : Z.t; + staking_delegate_denominator_b : Z.t; +} + +let balance_zero = + { + liquid_b = Tez.zero; + bonds_b = Tez.zero; + staked_b = Partial_tez.zero; + unstaked_frozen_b = Tez.zero; + unstaked_finalizable_b = Tez.zero; + staking_delegator_numerator_b = Z.zero; + staking_delegate_denominator_b = Z.zero; + } + +let balance_of_account account_name (account_map : account_map) = + match String.Map.find account_name account_map with + | None -> raise Not_found + | Some + { + pkh = _; + contract = _; + delegate; + parameters = _; + liquid; + bonds; + frozen_deposits = _; + unstaked_frozen = _; + unstaked_finalizable = _; + staking_delegator_numerator; + staking_delegate_denominator; + frozen_rights = _; + slashed_cycles = _; + } -> + let balance = + { + balance_zero with + liquid_b = liquid; + bonds_b = bonds; + staking_delegator_numerator_b = staking_delegator_numerator; + staking_delegate_denominator_b = staking_delegate_denominator; + } + in + let balance = + match delegate with + | None -> balance + | Some d -> ( + match String.Map.find d account_map with + | None -> raise Not_found + | Some delegate_account -> + { + balance with + staked_b = + Frozen_tez.get account_name delegate_account.frozen_deposits; + }) + in + (* Because an account can still have frozen or finalizable funds from a delegate + that is not its own, we iterate over all of them *) + let unstaked_frozen_b, unstaked_finalizable_b = + String.Map.fold + (fun _delegate_name delegate (frozen, finalzbl) -> + let frozen = + Tez.( + frozen + +! Unstaked_frozen.get_total + account_name + delegate.unstaked_frozen) + in + let finalzbl = + Tez.( + finalzbl + +! Unstaked_finalizable.get + account_name + delegate.unstaked_finalizable) + in + (frozen, finalzbl)) + account_map + (Tez.zero, Tez.zero) + in + {balance with unstaked_frozen_b; unstaked_finalizable_b} + +let balance_pp fmt + { + liquid_b; + bonds_b; + staked_b; + unstaked_frozen_b; + unstaked_finalizable_b; + staking_delegator_numerator_b; + staking_delegate_denominator_b; + } = + Format.fprintf + fmt + "{@;\ + @[ liquid : %a@;\ + bonds : %a@;\ + staked : %a@;\ + unstaked_frozen : %a@;\ + unstaked_finalizable : %a@;\ + staking_delegator_numerator : %a@;\ + staking_delegate_denominator : %a@;\ + }@." + Tez.pp + liquid_b + Tez.pp + bonds_b + Partial_tez.pp + staked_b + Tez.pp + unstaked_frozen_b + Tez.pp + unstaked_finalizable_b + Z.pp_print + staking_delegator_numerator_b + Z.pp_print + staking_delegate_denominator_b + +let balance_update_pp fmt + ( { + liquid_b = a_liquid_b; + bonds_b = a_bonds_b; + staked_b = a_staked_b; + unstaked_frozen_b = a_unstaked_frozen_b; + unstaked_finalizable_b = a_unstaked_finalizable_b; + staking_delegator_numerator_b = a_staking_delegator_numerator_b; + staking_delegate_denominator_b = a_staking_delegate_denominator_b; + }, + { + liquid_b = b_liquid_b; + bonds_b = b_bonds_b; + staked_b = b_staked_b; + unstaked_frozen_b = b_unstaked_frozen_b; + unstaked_finalizable_b = b_unstaked_finalizable_b; + staking_delegator_numerator_b = b_staking_delegator_numerator_b; + staking_delegate_denominator_b = b_staking_delegate_denominator_b; + } ) = + Format.fprintf + fmt + "{@;\ + @[ liquid : %a -> %a@;\ + bonds : %a -> %a@;\ + staked : %a -> %a@;\ + unstaked_frozen : %a -> %a@;\ + unstaked_finalizable : %a -> %a@;\ + staking_delegator_numerator : %a -> %a@;\ + staking_delegate_denominator : %a -> %a@;\ + }@." + Tez.pp + a_liquid_b + Tez.pp + b_liquid_b + Tez.pp + a_bonds_b + Tez.pp + b_bonds_b + Partial_tez.pp + a_staked_b + Partial_tez.pp + b_staked_b + Tez.pp + a_unstaked_frozen_b + Tez.pp + b_unstaked_frozen_b + Tez.pp + a_unstaked_finalizable_b + Tez.pp + b_unstaked_finalizable_b + Z.pp_print + a_staking_delegator_numerator_b + Z.pp_print + b_staking_delegator_numerator_b + Z.pp_print + a_staking_delegate_denominator_b + Z.pp_print + b_staking_delegate_denominator_b + +let assert_balance_equal ~loc account_name + { + liquid_b = a_liquid_b; + bonds_b = a_bonds_b; + staked_b = a_staked_b; + unstaked_frozen_b = a_unstaked_frozen_b; + unstaked_finalizable_b = a_unstaked_finalizable_b; + staking_delegator_numerator_b = a_staking_delegator_numerator_b; + staking_delegate_denominator_b = a_staking_delegate_denominator_b; + } + { + liquid_b = b_liquid_b; + bonds_b = b_bonds_b; + staked_b = b_staked_b; + unstaked_frozen_b = b_unstaked_frozen_b; + unstaked_finalizable_b = b_unstaked_finalizable_b; + staking_delegator_numerator_b = b_staking_delegator_numerator_b; + staking_delegate_denominator_b = b_staking_delegate_denominator_b; + } = + let open Lwt_result_syntax in + let f s = Format.asprintf "%s: %s" account_name s in + let* () = + List.fold_left + (fun a b -> + let*! a in + let*! b in + join_errors a b) + return_unit + [ + Assert.equal + ~loc + Tez.equal + (f "Liquid balances do not match") + Tez.pp + a_liquid_b + b_liquid_b; + Assert.equal + ~loc + Tez.equal + (f "Bonds balances do not match") + Tez.pp + a_bonds_b + b_bonds_b; + Assert.equal + ~loc + Tez.equal + (f "Staked balances do not match") + Tez.pp + (Partial_tez.to_tez ~round_up:false a_staked_b) + (Partial_tez.to_tez ~round_up:false b_staked_b); + Assert.equal + ~loc + Tez.equal + (f "Unstaked frozen balances do not match") + Tez.pp + a_unstaked_frozen_b + b_unstaked_frozen_b; + Assert.equal + ~loc + Tez.equal + (f "Unstaked finalizable balances do not match") + Tez.pp + a_unstaked_finalizable_b + b_unstaked_finalizable_b; + Assert.equal + ~loc + Z.equal + (f "Staking delegator numerators do not match") + Z.pp_print + a_staking_delegator_numerator_b + b_staking_delegator_numerator_b; + Assert.equal + ~loc + Z.equal + (f "Staking delegate denominators do not match") + Z.pp_print + a_staking_delegate_denominator_b + b_staking_delegate_denominator_b; + ] + in + return_unit + +let update_account ~f account_name account_map = + String.Map.update + account_name + (function None -> raise Not_found | Some x -> Some (f x)) + account_map + +let add_liquid_rewards amount account_name account_map = + let f account = + let liquid = Tez.(account.liquid +! amount) in + {account with liquid} + in + update_account ~f account_name account_map + +let add_frozen_rewards amount account_name account_map = + let f account = + let frozen_deposits = + Frozen_tez.add_tez_to_all_current amount account.frozen_deposits + in + {account with frozen_deposits} + in + update_account ~f account_name account_map + +let apply_burn amount src_name account_map = + let f src = {src with liquid = Tez.(src.liquid -! amount)} in + update_account ~f src_name account_map + +let apply_transfer amount src_name dst_name account_map = + match + (String.Map.find src_name account_map, String.Map.find dst_name account_map) + with + | Some src, Some _ -> + if Tez.(src.liquid < amount) then + (* Invalid amount: operation will fail *) + account_map + else + let f_src src = + let liquid = Tez.(src.liquid -! amount) in + {src with liquid} + in + let f_dst dst = + let liquid = Tez.(dst.liquid +! amount) in + {dst with liquid} + in + let account_map = update_account ~f:f_src src_name account_map in + update_account ~f:f_dst dst_name account_map + | _ -> raise Not_found + +let stake_from_unstake amount current_cycle consensus_rights_delay delegate_name + account_map = + match String.Map.find delegate_name account_map with + | None -> raise Not_found + | Some ({unstaked_frozen; frozen_deposits; slashed_cycles; _} as account) -> + let oldest_slashable_cycle = + Cycle.(sub current_cycle (consensus_rights_delay + 1)) + |> Option.value ~default:Cycle.root + in + if + List.exists + (fun x -> Cycle.(x >= oldest_slashable_cycle)) + slashed_cycles + then (account_map, amount) + else + let unstaked_frozen = + List.sort + (fun (Unstaked_frozen.{cycle = cycle1; _} : Unstaked_frozen.r) + {cycle = cycle2; _} -> Cycle.compare cycle2 cycle1) + unstaked_frozen + in + let rec aux acc_unstakes rem_amount rem_unstakes = + match rem_unstakes with + | [] -> (acc_unstakes, rem_amount) + | (Unstaked_frozen.{initial; _} as h) :: t -> + if Tez.(rem_amount = zero) then + (acc_unstakes @ rem_unstakes, Tez.zero) + else if Tez.(rem_amount >= initial) then + let h = Unstaked_frozen.sub_unstake initial delegate_name h in + let rem_amount = Tez.(rem_amount -! initial) in + aux (acc_unstakes @ [h]) rem_amount t + else + let h = + Unstaked_frozen.sub_unstake rem_amount delegate_name h + in + (acc_unstakes @ [h] @ t, Tez.zero) + in + let unstaked_frozen, rem_amount = aux [] amount unstaked_frozen in + let frozen_deposits = + Frozen_tez.add_current + Tez.(amount -! rem_amount) + delegate_name + frozen_deposits + in + let account = {account with unstaked_frozen; frozen_deposits} in + let account_map = + update_account ~f:(fun _ -> account) delegate_name account_map + in + (account_map, rem_amount) + +let apply_stake amount current_cycle consensus_rights_delay staker_name + account_map = + match String.Map.find staker_name account_map with + | None -> raise Not_found + | Some staker -> ( + match staker.delegate with + | None -> + (* Invalid operation: no delegate *) + account_map + | Some delegate_name -> + let old_account_map = account_map in + let account_map, amount = + if delegate_name = staker_name then + stake_from_unstake + amount + current_cycle + consensus_rights_delay + staker_name + account_map + else (account_map, amount) + in + if Tez.(staker.liquid < amount) then + (* Invalid amount: operation will fail *) + old_account_map + else + let f_staker staker = + let liquid = Tez.(staker.liquid -! amount) in + {staker with liquid} + in + let f_delegate delegate = + let frozen_deposits = + Frozen_tez.add_current + amount + staker_name + delegate.frozen_deposits + in + {delegate with frozen_deposits} + in + let account_map = + update_account ~f:f_staker staker_name account_map + in + update_account ~f:f_delegate delegate_name account_map) + +let apply_unstake cycle amount staker_name account_map = + match String.Map.find staker_name account_map with + | None -> raise Not_found + | Some staker -> ( + match staker.delegate with + | None -> (* Invalid operation: no delegate *) account_map + | Some delegate_name -> ( + match String.Map.find delegate_name account_map with + | None -> raise Not_found + | Some delegate -> + let frozen_deposits, amount_unstaked = + Frozen_tez.sub_current + amount + staker_name + delegate.frozen_deposits + in + let delegate = {delegate with frozen_deposits} in + let account_map = + String.Map.add delegate_name delegate account_map + in + let f delegate = + let unstaked_frozen = + Unstaked_frozen.add_unstake + cycle + amount_unstaked + staker_name + delegate.unstaked_frozen + in + {delegate with unstaked_frozen} + in + update_account ~f delegate_name account_map)) + +let apply_unslashable_f cycle delegate = + let amount_unslashable, unstaked_frozen = + Unstaked_frozen.pop_cycle cycle delegate.unstaked_frozen + in + let unstaked_finalizable = + Unstaked_finalizable.add_from_poped_ufd + amount_unslashable + delegate.unstaked_finalizable + in + {delegate with unstaked_frozen; unstaked_finalizable} + +(* Updates unstaked unslashable values for given account *) +let apply_unslashable cycle account_name account_map = + update_account ~f:(apply_unslashable_f cycle) account_name account_map + +(* Updates unstaked unslashable values in all accounts *) +let apply_unslashable_for_all cycle account_map = + String.Map.map (apply_unslashable_f cycle) account_map + +let apply_finalize staker_name account_map = + match String.Map.find staker_name account_map with + | None -> raise Not_found + | Some _staker -> + (* Because an account can still have finalizable funds from a delegate + that is not its own, we iterate over all of them *) + String.Map.fold + (fun delegate_name delegate account_map_acc -> + match + String.Map.find staker_name delegate.unstaked_finalizable.map + with + | None -> account_map_acc + | Some amount -> + let f_staker staker = + let liquid = Tez.(staker.liquid +! amount) in + {staker with liquid} + in + let f_delegate delegate = + let map = + String.Map.remove + staker_name + delegate.unstaked_finalizable.map + in + { + delegate with + unstaked_finalizable = + {delegate.unstaked_finalizable with map}; + } + in + let account_map_acc = + update_account ~f:f_staker staker_name account_map_acc + in + update_account ~f:f_delegate delegate_name account_map_acc) + account_map + account_map + +let balance_and_total_balance_of_account account_name account_map = + let ({ + liquid_b; + bonds_b; + staked_b; + unstaked_frozen_b; + unstaked_finalizable_b; + staking_delegator_numerator_b = _; + staking_delegate_denominator_b = _; + } as balance) = + balance_of_account account_name account_map + in + ( balance, + Tez.( + liquid_b +! bonds_b + +! Partial_tez.to_tez ~round_up:false staked_b + +! unstaked_frozen_b +! unstaked_finalizable_b) ) + +let apply_slashing + ( culprit, + Protocol.Denunciations_repr.{rewarded; misbehaviour; operation_hash = _} + ) constants account_map = + let find_account_name_from_pkh_exn pkh account_map = + match + Option.map + fst + String.Map.( + choose + @@ filter + (fun _ account -> + Signature.Public_key_hash.equal pkh account.pkh) + account_map) + with + | None -> assert false + | Some x -> x + in + let slashed_cycle = + Block.current_cycle_of_level + ~blocks_per_cycle: + constants.Protocol.Alpha_context.Constants.Parametric.blocks_per_cycle + ~current_level:(Protocol.Raw_level_repr.to_int32 misbehaviour.level) + in + let culprit_name = find_account_name_from_pkh_exn culprit account_map in + let rewarded_name = find_account_name_from_pkh_exn rewarded account_map in + let slashed_pct = + match misbehaviour.kind with + | Double_baking -> + constants + .Protocol.Alpha_context.Constants.Parametric + .percentage_of_frozen_deposits_slashed_per_double_baking + | Double_attesting | Double_preattesting -> + constants.percentage_of_frozen_deposits_slashed_per_double_attestation + in + let get_total_supply acc_map = + String.Map.fold + (fun _name + { + pkh = _; + contract = _; + delegate = _; + parameters = _; + liquid; + bonds; + frozen_deposits; + unstaked_frozen; + unstaked_finalizable; + staking_delegator_numerator = _; + staking_delegate_denominator = _; + frozen_rights = _; + slashed_cycles = _; + } + tot -> + Tez.( + liquid +! bonds + +! Frozen_tez.total_current frozen_deposits + +! Unstaked_frozen.sum_current unstaked_frozen + +! Unstaked_finalizable.total unstaked_finalizable + +! tot)) + acc_map + Tez.zero + in + let total_before_slash = get_total_supply account_map in + let slash_culprit + ({frozen_deposits; unstaked_frozen; frozen_rights; _} as acc) = + let base_rights = + CycleMap.find slashed_cycle frozen_rights + |> Option.value ~default:Tez.zero + in + let frozen_deposits, slashed_frozen = + Frozen_tez.slash base_rights slashed_pct frozen_deposits + in + let slashed_pct_q = Protocol.Percentage.to_q slashed_pct in + let slashed_pct = Q.(100 // 1 * slashed_pct_q |> to_int) in + let unstaked_frozen, slashed_unstaked = + Unstaked_frozen.slash + ~slashable_deposits_period:constants.consensus_rights_delay + slashed_cycle + slashed_pct + unstaked_frozen + in + ( {acc with frozen_deposits; unstaked_frozen}, + slashed_frozen :: slashed_unstaked ) + in + let culprit_account = + String.Map.find culprit_name account_map + |> Option.value_f ~default:(fun () -> raise Not_found) + in + let slashed_culprit_account, total_slashed = slash_culprit culprit_account in + let account_map = + update_account + ~f:(fun _ -> slashed_culprit_account) + culprit_name + account_map + in + let total_after_slash = get_total_supply account_map in + let portion_reward = + constants.adaptive_issuance.global_limit_of_staking_over_baking + 2 + in + (* For each container slashed, the snitch gets a reward transferred. It gets rounded + down each time *) + let reward_to_snitch = + List.map + (fun x -> Tez.mul_q x Q.(1 // portion_reward) |> Tez.of_q ~round_up:false) + total_slashed + |> List.fold_left Tez.( +! ) Tez.zero + in + let account_map = + add_liquid_rewards reward_to_snitch rewarded_name account_map + in + let actual_total_burnt_amount = + Tez.(total_before_slash -! total_after_slash -! reward_to_snitch) + in + (account_map, actual_total_burnt_amount) + +(* Given cycle is the cycle for which the rights are computed, usually current + + consensus rights delay *) +let update_frozen_rights_cycle cycle account_map = + String.Map.map + (fun ({frozen_deposits; frozen_rights; _} as acc) -> + let total_frozen = Frozen_tez.total_current frozen_deposits in + let frozen_rights = CycleMap.add cycle total_frozen frozen_rights in + {acc with frozen_rights}) + account_map + +let get_balance_from_context ctxt contract = + let open Lwt_result_syntax in + let* liquid_b = Context.Contract.balance ctxt contract in + let* bonds_b = Context.Contract.frozen_bonds ctxt contract in + let* staked_b = Context.Contract.staked_balance ctxt contract in + let staked_b = + Option.value ~default:Tez.zero staked_b |> Partial_tez.of_tez + in + let* unstaked_frozen_b = + Context.Contract.unstaked_frozen_balance ctxt contract + in + let unstaked_frozen_b = Option.value ~default:Tez.zero unstaked_frozen_b in + let* unstaked_finalizable_b = + Context.Contract.unstaked_finalizable_balance ctxt contract + in + let unstaked_finalizable_b = + Option.value ~default:Tez.zero unstaked_finalizable_b + in + let* total_balance = Context.Contract.full_balance ctxt contract in + let* staking_delegator_numerator_b = + Context.Contract.staking_numerator ctxt contract + in + let*! staking_delegate_denominator_b = + match (contract : Protocol.Alpha_context.Contract.t) with + | Implicit pkh -> + let*! result = Context.Delegate.staking_denominator ctxt pkh in + Lwt.return + (match result with + | Ok v -> v + | Error _ -> (* Not a delegate *) Z.zero) + | Originated _ -> Lwt.return Z.zero + in + let bd = + { + liquid_b; + bonds_b; + staked_b; + unstaked_frozen_b; + unstaked_finalizable_b; + staking_delegator_numerator_b; + staking_delegate_denominator_b; + } + in + return (bd, total_balance) + +let assert_balance_check ~loc ctxt account_name account_map = + let open Lwt_result_syntax in + match String.Map.find account_name account_map with + | None -> raise Not_found + | Some account -> + let* balance_ctxt, total_balance_ctxt = + get_balance_from_context ctxt account.contract + in + let balance, total_balance = + balance_and_total_balance_of_account account_name account_map + in + let*! r1 = assert_balance_equal ~loc account_name balance_ctxt balance in + let*! r2 = + Assert.equal + ~loc + Tez.equal + (Format.asprintf "%s : Total balances do not match" account_name) + Tez.pp + total_balance_ctxt + total_balance + in + join_errors r1 r2 + +let get_launch_cycle ~loc blk = + let open Lwt_result_syntax in + let* launch_cycle_opt = Context.get_adaptive_issuance_launch_cycle (B blk) in + Assert.get_some ~loc launch_cycle_opt + +(** AI operations *) + +let stake ctxt contract amount = + Op.transaction + ctxt + ~entrypoint:Protocol.Alpha_context.Entrypoint.stake + ~fee:Tez.zero + contract + contract + amount + +let set_delegate_parameters ctxt delegate + ~parameters:{limit_of_staking_over_baking; edge_of_baking_over_staking} = + let entrypoint = Protocol.Alpha_context.Entrypoint.set_delegate_parameters in + let limit_of_staking_over_baking_millionth = + Q.mul limit_of_staking_over_baking (Q.of_int 1_000_000) |> Q.to_int + in + let edge_of_baking_over_staking_billionth = + Q.mul edge_of_baking_over_staking (Q.of_int 1_000_000_000) |> Q.to_int + in + let parameters = + Protocol.Alpha_context.Script.lazy_expr + (Expr.from_string + (Printf.sprintf + "Pair %d (Pair %d Unit)" + limit_of_staking_over_baking_millionth + edge_of_baking_over_staking_billionth)) + in + Op.transaction + ctxt + ~entrypoint + ~parameters + ~fee:Tez.zero + delegate + delegate + Tez.zero + +let unstake ctxt contract amount = + Op.transaction + ctxt + ~entrypoint:Protocol.Alpha_context.Entrypoint.unstake + ~fee:Tez.zero + contract + contract + amount + +let finalize_unstake ctxt ?(amount = Tez.zero) contract = + Op.transaction + ctxt + ~entrypoint:Protocol.Alpha_context.Entrypoint.finalize_unstake + ~fee:Tez.zero + contract + contract + amount + +let portion_of_rewards_to_liquid_for_cycle ?policy ctxt cycle pkh rewards = + let open Lwt_result_syntax in + let* {frozen; weighted_delegated} = + Context.Delegate.stake_for_cycle ?policy ctxt cycle pkh + in + let portion = Tez.(ratio weighted_delegated (frozen +! weighted_delegated)) in + let to_liquid = Tez.mul_q rewards portion in + return (Partial_tez.to_tez ~round_up:false to_liquid) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/assert.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/assert.ml new file mode 100644 index 000000000000..9f42a9e2ec7c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/assert.ml @@ -0,0 +1,324 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +let error ~loc v f = + let open Lwt_result_syntax in + match v with + | Error err when List.exists f err -> return_unit + | Ok _ -> failwith "Unexpected successful result (%s)" loc + | Error err -> failwith "@[Unexpected error (%s): %a@]" loc pp_print_trace err + +let test_error_encodings e = + let module E = Environment.Error_monad in + ignore (E.pp Format.str_formatter e) ; + let e' = E.json_of_error e |> E.error_of_json in + assert (e = e') + +let proto_error ~loc v f = + error ~loc v (function + | Environment.Ecoproto_error err -> + test_error_encodings err ; + f err + | _ -> false) + +let proto_error_with_info ?(error_info_field = `Title) ~loc v + expected_error_info = + let info err = + let i = Error_monad.find_info_of_error (Environment.wrap_tzerror err) in + match error_info_field with + | `Title -> i.title + | `Id -> i.id + | `Description -> i.description + | `Message -> Format.asprintf "%a" Environment.Error_monad.pp err + in + proto_error ~loc v (function err -> + Format.printf + "@[THE ERROR IS: %s@,EXPECTED: %s@]@." + (info err) + expected_error_info ; + let info = info err in + String.equal info expected_error_info) + +let equal ~loc (cmp : 'a -> 'a -> bool) msg pp a b = + let open Lwt_result_syntax in + if not (cmp a b) then + failwith "@[@[[%s]@] - @[%s : %a is not equal to %a@]@]" loc msg pp a pp b + else return_unit + +let leq ~loc (cmp : 'a -> 'a -> int) msg pp a b = + let open Lwt_result_syntax in + if cmp a b > 0 then + failwith + "@[@[[%s]@] - @[%s : %a is not less or equal to %a@]@]" + loc + msg + pp + a + pp + b + else return_unit + +let lt ~loc (cmp : 'a -> 'a -> int) msg pp a b = + let open Lwt_result_syntax in + if cmp a b >= 0 then + failwith "@[@[[%s]@] - @[%s : %a is not less than %a@]@]" loc msg pp a pp b + else return_unit + +let not_equal ~loc (cmp : 'a -> 'a -> bool) msg pp a b = + let open Lwt_result_syntax in + if cmp a b then + failwith "@[@[[%s]@] - @[%s : %a is equal to %a@]@]" loc msg pp a pp b + else return_unit + +module Int32 = struct + include Int32 + + let pp pp v = Format.pp_print_int pp (Int32.to_int v) +end + +module Int64 = struct + include Int64 + + let pp pp v = Format.pp_print_int pp (Int64.to_int v) +end + +(* char *) +let equal_char ~loc a b = + equal ~loc Char.equal "Characters aren't equal" Format.pp_print_char a b + +(* int *) +let equal_int ~loc (a : int) (b : int) = + equal ~loc Int.equal "Integers aren't equal" Format.pp_print_int a b + +let not_equal_int ~loc (a : int) (b : int) = + not_equal ~loc Int.equal "Integers are equal" Format.pp_print_int a b + +let leq_int ~loc (a : int) (b : int) = + leq ~loc Compare.Int.compare "Integer comparison" Format.pp_print_int a b + +(* int32 *) +let equal_int32 ~loc (a : int32) (b : int32) = + equal ~loc Int32.equal "Int32 aren't equal" Int32.pp a b + +let leq_int32 ~loc (a : int32) (b : int32) = + leq ~loc Compare.Int32.compare "Int32 comparison" Int32.pp a b + +let lt_int32 ~loc (a : int32) (b : int32) = + lt ~loc Compare.Int32.compare "Int32 comparison" Int32.pp a b + +(* int64 *) +let equal_int64 ~loc (a : int64) (b : int64) = + equal ~loc Compare.Int64.( = ) "Int64 aren't equal" Int64.pp a b + +let not_equal_int64 ~loc (a : int64) (b : int64) = + not_equal ~loc Int64.equal "Int64 are equal" Int64.pp a b + +let leq_int64 ~loc (a : int64) (b : int64) = + leq ~loc Compare.Int64.compare "Int64 comparison" Int64.pp a b + +let equal_z ~loc (a : Z.t) (b : Z.t) = + equal ~loc Compare.Z.( = ) "Z are not equal" Z.pp_print a b + +let equal_q ~loc (a : Q.t) (b : Q.t) = + equal ~loc Compare.Q.( = ) "Q are not equal" Q.pp_print a b + +(* bool *) +let equal_bool ~loc (a : bool) (b : bool) = + equal ~loc Bool.equal "Booleans aren't equal" Format.pp_print_bool a b + +let not_equal_bool ~loc (a : bool) (b : bool) = + not_equal ~loc Bool.equal "Booleans are equal" Format.pp_print_bool a b + +let is_true ~loc (a : bool) = + equal ~loc Bool.equal "Boolean is not true" Format.pp_print_bool a true + +(* string *) +let equal_string ~loc (a : string) (b : string) = + equal ~loc String.equal "Strings aren't equal" Format.pp_print_string a b + +let not_equal_string ~loc (a : string) (b : string) = + not_equal ~loc String.equal "Strings are equal" Format.pp_print_string a b + +(* tez *) +let equal_tez ~loc (a : Alpha_context.Tez.t) (b : Alpha_context.Tez.t) = + let open Alpha_context in + equal ~loc Tez.( = ) "Tez aren't equal" Tez.pp a b + +let not_equal_tez ~loc (a : Alpha_context.Tez.t) (b : Alpha_context.Tez.t) = + let open Alpha_context in + not_equal ~loc Tez.( = ) "Tez are equal" Tez.pp a b + +(* pkh *) +let equal_pkh ~loc (a : Signature.Public_key_hash.t) + (b : Signature.Public_key_hash.t) = + let module PKH = Signature.Public_key_hash in + equal ~loc PKH.equal "Public key hashes aren't equal" PKH.pp a b + +let not_equal_pkh ~loc (a : Signature.Public_key_hash.t) + (b : Signature.Public_key_hash.t) = + let module PKH = Signature.Public_key_hash in + not_equal ~loc PKH.equal "Public key hashes are equal" PKH.pp a b + +(* protocol hash *) +let equal_protocol_hash ~loc (a : Protocol_hash.t) (b : Protocol_hash.t) = + equal + ~loc + Protocol_hash.equal + "Protocol hashes aren't equal" + Protocol_hash.pp + a + b + +let not_equal_protocol_hash ~loc (a : Protocol_hash.t) (b : Protocol_hash.t) = + not_equal + ~loc + Protocol_hash.equal + "Protocol hashes are equal" + Protocol_hash.pp + a + b + +let get_some ~loc = + let open Lwt_result_syntax in + function Some x -> return x | None -> failwith "Unexpected None (%s)" loc + +let is_none ~loc ~pp = + let open Lwt_result_syntax in + function + | Some x -> failwith "Unexpected (Some %a) (%s)" pp x loc + | None -> return_unit + +let equal_result ~loc ~pp_ok ~pp_error eq_ok eq_error a b = + equal + ~loc + (Result.equal ~ok:eq_ok ~error:eq_error) + "Results are not equal" + (Format.pp_print_result ~ok:pp_ok ~error:pp_error) + a + b + +let is_error ~loc ~pp = + let open Lwt_result_syntax in + function + | Ok x -> failwith "Unexpected (Ok %a) (%s)" pp x loc | Error _ -> return_unit + +let get_ok ~__LOC__ = + let open Lwt_result_syntax in + function + | Ok r -> return r + | Error err -> + failwith "@[Unexpected error (%s): %a@]" __LOC__ pp_print_trace err + +open Context + +(* Some asserts for account operations *) + +let contract_property_is property ~loc b contract expected = + let open Lwt_result_syntax in + let* balance = property b contract in + equal_tez ~loc balance expected + +(** [balance_is b c amount] checks that the current balance [b] of contract [c] + is [amount]. +*) +let balance_is = contract_property_is Contract.balance + +(** [frozen_bonds_is b c amount] checks that the current frozen bonds of + contract [c] is [amount]. +*) +let frozen_bonds_is = contract_property_is Contract.frozen_bonds + +let balance_or_frozen_bonds_was_operated ~is_balance ~operand ~loc b contract + old_balance amount = + let open Lwt_result_wrap_syntax in + let*?@ expected = operand old_balance amount in + let f = if is_balance then balance_is else frozen_bonds_is in + f ~loc b contract expected + +(** [balance_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s balance was credited [amount] tez in comparison to + [old_balance]. +*) +let balance_was_credited = + balance_or_frozen_bonds_was_operated + ~is_balance:true + ~operand:Alpha_context.Tez.( +? ) + +(** [balance_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s balance was debited [amount] tez in comparison to + [old_balance]. +*) +let balance_was_debited = + balance_or_frozen_bonds_was_operated + ~is_balance:true + ~operand:Alpha_context.Tez.( -? ) + +(** [frozen_bonds_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s frozen bonds was credited [amount] tez in comparison to + [old_balance]. +*) +let frozen_bonds_was_credited = + balance_or_frozen_bonds_was_operated + ~is_balance:false + ~operand:Alpha_context.Tez.( +? ) + +(** [frozen_bonds_was_credited ~loc ctxt contract old_balance amount] checks + that [contract]'s frozen bonds was credited [amount] tez in comparison to + [old_balance]. +*) +let frozen_bonds_was_debited = + balance_or_frozen_bonds_was_operated + ~is_balance:false + ~operand:Alpha_context.Tez.( -? ) + +let pp_print_list pp out xs = + let list_pp fmt = + Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ";@.") fmt + in + Format.fprintf out "[%a]" (list_pp pp) xs + +let assert_equal_list ~loc eq msg pp = + equal ~loc (List.equal eq) msg (pp_print_list pp) + +let assert_equal_list_opt ~loc eq msg pp = + equal + ~loc + (Option.equal (List.equal eq)) + msg + (Format.pp_print_option (pp_print_list pp)) + +let to_json_string encoding x = + x + |> Data_encoding.Json.construct encoding + |> Format.asprintf "\n%a\n" Data_encoding.Json.pp + +let equal_with_encoding ~loc encoding a b = + equal_string ~loc (to_json_string encoding a) (to_json_string encoding b) + +let not_equal_with_encoding ~loc encoding a b = + not_equal_string ~loc (to_json_string encoding a) (to_json_string encoding b) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.ml new file mode 100644 index 000000000000..46827683863c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.ml @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let make_big_map block ~source ~key_type ~value_type key_values = + let open Lwt_result_wrap_syntax in + let key_type = Expr.from_string key_type in + let value_type = Expr.from_string value_type in + let* operation, originated = + Op.contract_origination_hash (B block) source ~script:Op.dummy_script + in + let* block = Block.bake ~operation block in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let*@ ctxt, big_map_id = Big_map.fresh ~temporary:false ctxt in + let* updates, ctxt = + List.fold_left_es + (fun (kvs, ctxt) (key, value) -> + let key_hash = + match + Data_encoding.Binary.to_bytes_opt Script_repr.expr_encoding key + with + | Some bytes -> Script_expr_hash.hash_bytes [bytes] + | None -> assert false + in + return ({Big_map.key; key_hash; value = Some value} :: kvs, ctxt)) + ([], ctxt) + key_values + in + let*@ ctxt = + Contract.update_script_storage + ctxt + originated + key_type + (Some + [ + Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update + { + init = Lazy_storage.Alloc Big_map.{key_type; value_type}; + updates; + }); + ]) + in + return (big_map_id, ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.mli new file mode 100644 index 000000000000..eca8c1dbd083 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/big_map_helpers.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** [make_big_map block ~source ~key_type ~value_type key_values] constructs a + new big-map with the given key-type [key_type] and value type [value_type]. + + The big-map is owned by a new contract that is originated from [source], + with script {!Op.dummy_script}, and consists of a list of key-value pairs + according to the given [key_values] list of Micheline expressions. *) +val make_big_map : + Block.t -> + source:Alpha_context.Contract.t -> + key_type:string -> + value_type:string -> + (Script_repr.expr * Script_repr.expr) list -> + (Lazy_storage_kind.Big_map.Id.t * Alpha_context.context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/block.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/block.ml new file mode 100644 index 000000000000..36d673fd77c6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/block.ml @@ -0,0 +1,1330 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module Proto_Nonce = Nonce (* Renamed otherwise is masked by Alpha_context *) +open Alpha_context + +(* This type collects a block and the context that results from its application *) +type t = { + hash : Block_hash.t; + header : Block_header.t; + operations : Operation.packed list; + context : Tezos_protocol_environment.Context.t; + constants : Constants.Parametric.t; +} + +type block = t + +let rpc_context block = + { + Environment.Updater.block_hash = block.hash; + block_header = block.header.shell; + context = block.context; + } + +let rpc_ctxt = + new Environment.proto_rpc_context_of_directory + rpc_context + Plugin.RPC.rpc_services + +(******** Policies ***********) + +(* Policies are functions that take a block and return a tuple + [(account, level, timestamp)] for the [forge_header] function. *) + +(* This type is used only to provide a simpler interface to the exterior. *) +type baker_policy = + | By_round of int + | By_account of public_key_hash + | Excluding of public_key_hash list + +type baking_mode = Application | Baking + +let get_next_baker_by_round round block = + let open Lwt_result_syntax in + let+ bakers = + Plugin.RPC.Baking_rights.get rpc_ctxt ~all:true ~max_round:(round + 1) block + in + let {Plugin.RPC.Baking_rights.delegate = pkh; consensus_key; timestamp; _} = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun {Plugin.RPC.Baking_rights.round = r; _} -> + Round.to_int32 r = Int32.of_int round) + bakers + in + ( pkh, + consensus_key, + round, + WithExceptions.Option.to_exn ~none:(Failure "") timestamp ) + +type error += No_slots_found_for of Signature.Public_key_hash.t + +let () = + register_error_kind + `Permanent + ~id:(Protocol.name ^ "_Block.No_slots_found_for") + ~title:"No slots found for given pkh" + ~description:"No slots found for given public key hash" + ~pp:(fun ppf pkh -> + Format.fprintf + ppf + "No slots found for %a" + Signature.Public_key_hash.pp + pkh) + Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) + (function No_slots_found_for pkh -> Some pkh | _ -> None) + (fun pkh -> No_slots_found_for pkh) + +let get_next_baker_by_account pkh block = + let open Lwt_result_wrap_syntax in + let* bakers = Plugin.RPC.Baking_rights.get rpc_ctxt ~delegates:[pkh] block in + let* { + Plugin.RPC.Baking_rights.delegate = pkh; + consensus_key; + timestamp; + round; + _; + } = + match List.hd bakers with + | Some b -> return b + | None -> tzfail (No_slots_found_for pkh) + in + let*?@ round = Round.to_int round in + return + ( pkh, + consensus_key, + round, + WithExceptions.Option.to_exn ~none:(Failure __LOC__) timestamp ) + +let get_next_baker_excluding excludes block = + let open Lwt_result_wrap_syntax in + let* bakers = Plugin.RPC.Baking_rights.get rpc_ctxt block in + let { + Plugin.RPC.Baking_rights.delegate = pkh; + consensus_key; + timestamp; + round; + _; + } = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun {Plugin.RPC.Baking_rights.consensus_key; _} -> + not + (List.mem + ~equal:Signature.Public_key_hash.equal + consensus_key + excludes)) + bakers + in + let*?@ round = Round.to_int round in + return + ( pkh, + consensus_key, + round, + WithExceptions.Option.to_exn ~none:(Failure "") timestamp ) + +let dispatch_policy = function + | By_round r -> get_next_baker_by_round r + | By_account a -> get_next_baker_by_account a + | Excluding al -> get_next_baker_excluding al + +let get_next_baker ?(policy = By_round 0) = dispatch_policy policy + +let get_round (b : t) = + let open Result_syntax in + let fitness = b.header.shell.fitness in + Fitness.( + let+ fitness = from_raw fitness in + round fitness) + +module Forge = struct + type header = { + baker : public_key_hash; + consensus_key : public_key_hash; + (* the signer of the block *) + shell : Block_header.shell_header; + contents : Block_header.contents; + } + + let default_proof_of_work_nonce = + Bytes.create Constants.proof_of_work_nonce_size + + let rec naive_pow_miner ~proof_of_work_threshold shell header = + let open Lwt_result_syntax in + match + Hacl_star.Hacl.RandomBuffer.randombytes + ~size:Constants.proof_of_work_nonce_size + with + | Some proof_of_work_nonce -> + let cand = Block_header.{header with proof_of_work_nonce} in + if + Block_header.Proof_of_work.check_header_proof_of_work_stamp + shell + cand + proof_of_work_threshold + then return cand + else naive_pow_miner ~proof_of_work_threshold shell header + | None -> failwith "Impossible to gather randomness" + + let make_contents + ?(proof_of_work_threshold = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_test + .proof_of_work_threshold) ~payload_hash ~payload_round + ?(liquidity_baking_toggle_vote = Per_block_votes.Per_block_vote_pass) + ?(adaptive_issuance_vote = Per_block_votes.Per_block_vote_pass) + ~seed_nonce_hash shell = + naive_pow_miner + ~proof_of_work_threshold + shell + Block_header. + { + payload_hash; + payload_round; + proof_of_work_nonce = default_proof_of_work_nonce; + seed_nonce_hash; + per_block_votes = + { + liquidity_baking_vote = liquidity_baking_toggle_vote; + adaptive_issuance_vote; + }; + } + + let make_shell ~level ~predecessor ~timestamp ~fitness ~operations_hash = + Tezos_base.Block_header. + { + level; + predecessor; + timestamp; + fitness; + operations_hash; + (* We don't care of the following values, only the shell validates them. *) + proto_level = 0; + validation_passes = 0; + context = Context_hash.zero; + } + + let set_seed_nonce_hash + ?(proof_of_work_threshold = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_test + .proof_of_work_threshold) seed_nonce_hash + {baker; consensus_key; shell; contents} = + let open Lwt_result_syntax in + let+ contents = + naive_pow_miner + ~proof_of_work_threshold + shell + {contents with seed_nonce_hash} + in + {baker; consensus_key; shell; contents} + + let set_baker baker ?(consensus_key = baker) header = + {header with baker; consensus_key} + + let sign_header {consensus_key; shell; contents; _} = + let open Lwt_result_syntax in + let+ signer_account = Account.find consensus_key in + let unsigned_bytes = + Data_encoding.Binary.to_bytes_exn + Block_header.unsigned_encoding + (shell, contents) + in + let signature = + Signature.sign + ~watermark:Block_header.(to_watermark (Block_header Chain_id.zero)) + signer_account.sk + unsigned_bytes + in + Block_header.{shell; protocol_data = {contents; signature}} + + let classify_operations operations = + let validation_passes_len = List.length Main.validation_passes in + let t = Array.make validation_passes_len [] in + List.iter + (fun (op : packed_operation) -> + match Main.acceptable_pass op with + | None -> () + | Some pass -> t.(pass) <- op :: t.(pass)) + operations ; + let t = Array.map List.rev t in + Array.to_list t + + let forge_header ?(locked_round = None) ?(payload_round = None) + ?(policy = By_round 0) ?timestamp ?(operations = []) + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote pred = + let open Lwt_result_wrap_syntax in + let pred_fitness = + match Fitness.from_raw pred.header.shell.fitness with + | Ok pred_fitness -> pred_fitness + | _ -> assert false + in + let predecessor_round = Fitness.round pred_fitness in + let* delegate, consensus_key, round, expected_timestamp = + dispatch_policy policy pred + in + let timestamp = Option.value ~default:expected_timestamp timestamp in + let level = Int32.succ pred.header.shell.level in + let*?@ raw_level = Raw_level.of_int32 level in + let*?@ round = Round.of_int round in + let*?@ fitness = + Fitness.create ~level:raw_level ~predecessor_round ~round ~locked_round + in + let fitness = Fitness.to_raw fitness in + let* seed_nonce_hash = + let+ level = Plugin.RPC.current_level ~offset:1l rpc_ctxt pred in + match level with + | {expected_commitment = true; _} -> Some (fst (Proto_Nonce.generate ())) + | {expected_commitment = false; _} -> None + in + let hashes = List.map Operation.hash_packed operations in + let operations_hash = + Operation_list_list_hash.compute [Operation_list_hash.compute hashes] + in + let shell = + make_shell + ~level + ~predecessor:pred.hash + ~timestamp + ~fitness + ~operations_hash + in + let operations = classify_operations operations in + let non_consensus_operations = + List.concat (match List.tl operations with None -> [] | Some l -> l) + in + let hashes = List.map Operation.hash_packed non_consensus_operations in + let payload_round = + match payload_round with None -> round | Some r -> r + in + let payload_hash = + Block_payload.hash + ~predecessor_hash:shell.predecessor + ~payload_round + hashes + in + let+ contents = + make_contents + ~seed_nonce_hash + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + ~payload_hash + ~payload_round + shell + in + {baker = delegate; consensus_key; shell; contents} + + (* compatibility only, needed by incremental *) + let contents + ?(proof_of_work_threshold = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_test + .proof_of_work_threshold) ?seed_nonce_hash + ?(liquidity_baking_toggle_vote = Per_block_votes.Per_block_vote_pass) + ?(adaptive_issuance_vote = Per_block_votes.Per_block_vote_pass) + ~payload_hash ~payload_round shell_header = + naive_pow_miner + ~proof_of_work_threshold + shell_header + { + Block_header.proof_of_work_nonce = default_proof_of_work_nonce; + seed_nonce_hash; + per_block_votes = + { + liquidity_baking_vote = liquidity_baking_toggle_vote; + adaptive_issuance_vote; + }; + payload_hash; + payload_round; + } +end + +(********* Genesis creation *************) + +(* Hard-coded context key *) +let protocol_param_key = ["protocol_parameters"] + +let check_constants_consistency constants = + let open Lwt_result_syntax in + let open Constants.Parametric in + let {blocks_per_cycle; blocks_per_commitment; nonce_revelation_threshold; _} = + constants + in + let* () = + Error_monad.unless (blocks_per_commitment <= blocks_per_cycle) (fun () -> + failwith + "Inconsistent constants : blocks_per_commitment must be less than \ + blocks_per_cycle") + in + Error_monad.unless (nonce_revelation_threshold <= blocks_per_cycle) (fun () -> + failwith + "Inconsistent constants : nonce_revelation_threshold must be less than \ + blocks_per_cycle") + +let prepare_main_init_params ?bootstrap_contracts commitments constants + bootstrap_accounts = + let open Lwt_syntax in + let open Tezos_protocol_020_PsParisC_parameters in + let parameters = + Default_parameters.parameters_of_constants + ~bootstrap_accounts + ?bootstrap_contracts + ~commitments + constants + in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + Tezos_protocol_environment.Context.( + let empty = Tezos_protocol_environment.Memory_context.empty in + let* ctxt = add empty ["version"] (Bytes.of_string "genesis") in + add ctxt protocol_param_key proto_params) + +let initial_context ?(commitments = []) ?bootstrap_contracts chain_id constants + header bootstrap_accounts = + let open Lwt_result_wrap_syntax in + let*! ctxt = + prepare_main_init_params + ?bootstrap_contracts + commitments + constants + bootstrap_accounts + in + let+@ {context; _} = Main.init chain_id ctxt header in + context + +let initial_alpha_context ?(commitments = []) constants + (block_header : Block_header.shell_header) bootstrap_accounts = + let open Lwt_result_wrap_syntax in + let*! ctxt = + prepare_main_init_params commitments constants bootstrap_accounts + in + let level = block_header.level in + let timestamp = block_header.timestamp in + let predecessor = block_header.predecessor in + let typecheck_smart_contract (ctxt : Alpha_context.context) + (script : Alpha_context.Script.t) = + let allow_forged_tickets_in_storage, allow_forged_lazy_storage_id_in_storage + = + (false, false) + (* There should be no forged value in bootstrap contracts. *) + in + let* Ex_script (Script parsed_script), ctxt = + Script_ir_translator.parse_script + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id_in_storage + script + in + let* storage, lazy_storage_diff, ctxt = + Script_ir_translator.extract_lazy_storage_diff + ctxt + Optimized + parsed_script.storage_type + parsed_script.storage + ~to_duplicate:Script_ir_translator.no_lazy_storage_id + ~to_update:Script_ir_translator.no_lazy_storage_id + ~temporary:false + in + let+ storage, ctxt = + Script_ir_translator.unparse_data + ctxt + Optimized + parsed_script.storage_type + storage + in + let storage = Alpha_context.Script.lazy_expr storage in + (({script with storage}, lazy_storage_diff), ctxt) + in + let*@ result = + Alpha_context.prepare_first_block + ~typecheck_smart_contract + ~typecheck_smart_rollup: + Sc_rollup_operations.validate_untyped_parameters_ty + ~level + ~timestamp + ~predecessor + Chain_id.zero + ctxt + in + return result + +let genesis_with_parameters parameters = + let open Lwt_result_wrap_syntax in + let hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + in + let fitness = + Fitness_repr.create_without_locked_round + ~level:(Protocol.Raw_level_repr.of_int32_exn 0l) + ~predecessor_round:Round_repr.zero + ~round:Round_repr.zero + |> Fitness_repr.to_raw + in + let shell = + Forge.make_shell + ~level:0l + ~predecessor:hash + ~timestamp:Time.Protocol.epoch + ~fitness + ~operations_hash:Operation_list_list_hash.zero + in + let* contents = + Forge.make_contents + ~payload_hash:Block_payload_hash.zero + ~payload_round:Round.zero + ~seed_nonce_hash:None + shell + in + let open Tezos_protocol_020_PsParisC_parameters in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + let*! ctxt = + Tezos_protocol_environment.Context.( + let empty = Tezos_protocol_environment.Memory_context.empty in + let*! ctxt = add empty ["version"] (Bytes.of_string "genesis") in + add ctxt protocol_param_key proto_params) + in + let chain_id = Chain_id.of_block_hash hash in + let*@ {context; _} = Main.init chain_id ctxt shell in + return + { + hash; + header = {shell; protocol_data = {contents; signature = Signature.zero}}; + operations = []; + context; + constants = parameters.constants; + } + +let validate_bootstrap_accounts + (bootstrap_accounts : Parameters.bootstrap_account list) minimal_stake = + let open Lwt_result_wrap_syntax in + if bootstrap_accounts = [] then + Stdlib.failwith "Must have one account with minimal_stake to bake" ; + (* Check there are at least minimal_stake tokens *) + Lwt.catch + (fun () -> + let* (_ : Tez.t) = + List.fold_left_es + (fun acc (Parameters.{amount; _} : Parameters.bootstrap_account) -> + let*?@ acc = Tez.( +? ) acc amount in + if acc >= minimal_stake then raise Exit else return acc) + Tez.zero + bootstrap_accounts + in + failwith + "Insufficient tokens in initial accounts: the amount should be at \ + least minimal_stake") + (function Exit -> return_unit | exc -> Lwt.reraise exc) + +let prepare_initial_context_params ?consensus_committee_size + ?consensus_threshold ?min_proposal_quorum ?level ?cost_per_byte + ?issuance_weights ?origination_size ?blocks_per_cycle + ?cycles_per_voting_period ?sc_rollup_arith_pvm_enable + ?sc_rollup_private_enable ?sc_rollup_riscv_pvm_enable ?dal_enable + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold ?dal + ?adaptive_issuance ?consensus_rights_delay () = + let open Lwt_result_syntax in + let open Tezos_protocol_020_PsParisC_parameters in + let constants = Default_parameters.constants_test in + let min_proposal_quorum = + Option.value ~default:constants.min_proposal_quorum min_proposal_quorum + in + let cost_per_byte = + Option.value ~default:constants.cost_per_byte cost_per_byte + in + let issuance_weights = + Option.value ~default:constants.issuance_weights issuance_weights + in + let origination_size = + Option.value ~default:constants.origination_size origination_size + in + let blocks_per_cycle = + Option.value ~default:constants.blocks_per_cycle blocks_per_cycle + in + let cycles_per_voting_period = + Option.value + ~default:constants.cycles_per_voting_period + cycles_per_voting_period + in + let consensus_threshold = + Option.value ~default:constants.consensus_threshold consensus_threshold + in + let consensus_committee_size = + Option.value + ~default:constants.consensus_committee_size + consensus_committee_size + in + let sc_rollup_arith_pvm_enable = + Option.value + ~default:constants.sc_rollup.arith_pvm_enable + sc_rollup_arith_pvm_enable + in + let sc_rollup_riscv_pvm_enable = + Option.value + ~default:constants.sc_rollup.riscv_pvm_enable + sc_rollup_riscv_pvm_enable + in + let sc_rollup_private_enable = + Option.value + ~default:constants.sc_rollup.private_enable + sc_rollup_private_enable + in + let dal_enable = + Option.value ~default:constants.dal.feature_enable dal_enable + in + let zk_rollup_enable = + Option.value ~default:constants.zk_rollup.enable zk_rollup_enable + in + let hard_gas_limit_per_block = + Option.value + ~default:constants.hard_gas_limit_per_block + hard_gas_limit_per_block + in + let nonce_revelation_threshold = + Option.value + ~default:constants.nonce_revelation_threshold + nonce_revelation_threshold + in + let dal = Option.value ~default:constants.dal dal in + let adaptive_issuance = + Option.value ~default:constants.adaptive_issuance adaptive_issuance + in + let consensus_rights_delay = + Option.value + ~default:constants.consensus_rights_delay + consensus_rights_delay + in + + let constants = + { + constants with + issuance_weights; + origination_size; + blocks_per_cycle; + cycles_per_voting_period; + min_proposal_quorum; + cost_per_byte; + consensus_committee_size; + consensus_threshold; + sc_rollup = + { + constants.sc_rollup with + arith_pvm_enable = sc_rollup_arith_pvm_enable; + private_enable = sc_rollup_private_enable; + riscv_pvm_enable = sc_rollup_riscv_pvm_enable; + }; + dal = {dal with feature_enable = dal_enable}; + zk_rollup = {constants.zk_rollup with enable = zk_rollup_enable}; + adaptive_issuance; + hard_gas_limit_per_block; + nonce_revelation_threshold; + consensus_rights_delay; + } + in + let* () = check_constants_consistency constants in + let hash = + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" + in + let level = Option.value ~default:0l level in + let fitness = + Fitness_repr.create_without_locked_round + ~level:(Protocol.Raw_level_repr.of_int32_exn level) + ~predecessor_round:Round_repr.zero + ~round:Round_repr.zero + |> Fitness_repr.to_raw + in + let shell = + Forge.make_shell + ~level + ~predecessor:hash + ~timestamp:Time.Protocol.epoch + ~fitness + ~operations_hash:Operation_list_list_hash.zero + in + return (constants, shell, hash) + +(* if no parameter file is passed we check in the current directory + where the test is run *) +let genesis ?commitments ?consensus_committee_size ?consensus_threshold + ?min_proposal_quorum ?bootstrap_contracts ?level ?cost_per_byte + ?issuance_weights ?origination_size ?blocks_per_cycle + ?cycles_per_voting_period ?sc_rollup_arith_pvm_enable + ?sc_rollup_private_enable ?sc_rollup_riscv_pvm_enable ?dal_enable + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold ?dal + ?adaptive_issuance (bootstrap_accounts : Parameters.bootstrap_account list) + = + let open Lwt_result_syntax in + let* constants, shell, hash = + prepare_initial_context_params + ?consensus_committee_size + ?consensus_threshold + ?min_proposal_quorum + ?level + ?cost_per_byte + ?issuance_weights + ?origination_size + ?blocks_per_cycle + ?cycles_per_voting_period + ?sc_rollup_arith_pvm_enable + ?sc_rollup_private_enable + ?sc_rollup_riscv_pvm_enable + ?dal_enable + ?zk_rollup_enable + ?hard_gas_limit_per_block + ?nonce_revelation_threshold + ?dal + ?adaptive_issuance + () + in + let* () = + validate_bootstrap_accounts bootstrap_accounts constants.minimal_stake + in + let* context = + initial_context + ?commitments + ?bootstrap_contracts + (Chain_id.of_block_hash hash) + constants + shell + bootstrap_accounts + in + let+ contents = + Forge.make_contents + ~payload_hash:Block_payload_hash.zero + ~payload_round:Round.zero + ~seed_nonce_hash:None + shell + in + { + hash; + header = {shell; protocol_data = {contents; signature = Signature.zero}}; + operations = []; + context; + constants; + } + +let alpha_context ?commitments ?min_proposal_quorum ?consensus_rights_delay + (bootstrap_accounts : Parameters.bootstrap_account list) = + let open Lwt_result_syntax in + let* constants, shell, _hash = + prepare_initial_context_params + ?min_proposal_quorum + ?consensus_rights_delay + () + in + let* () = + validate_bootstrap_accounts bootstrap_accounts constants.minimal_stake + in + initial_alpha_context ?commitments constants shell bootstrap_accounts + +(********* Baking *************) + +let begin_validation_and_application ctxt chain_id mode ~predecessor = + let open Lwt_result_syntax in + let* validation_state = begin_validation ctxt chain_id mode ~predecessor in + let* application_state = begin_application ctxt chain_id mode ~predecessor in + return (validation_state, application_state) + +let get_application_vstate (pred : t) (operations : Protocol.operation trace) = + let open Lwt_result_wrap_syntax in + let* header = Forge.forge_header pred ~operations in + let* header = Forge.sign_header header in + let*@ result = + begin_validation_and_application + pred.context + Chain_id.zero + (Application header) + ~predecessor:pred.header.shell + in + return result + +(* Note that by calling this function without [protocol_data], we + force the mode to be partial construction. *) +let get_construction_vstate ?(policy = By_round 0) ?timestamp + ?(protocol_data = None) (pred : t) = + let open Lwt_result_wrap_syntax in + let open Protocol in + let* _pkh, _ck, _round, expected_timestamp = dispatch_policy policy pred in + let timestamp = Option.value ~default:expected_timestamp timestamp in + let mode = + match protocol_data with + | None -> Partial_construction {predecessor_hash = pred.hash; timestamp} + | Some block_header_data -> + Construction + {predecessor_hash = pred.hash; timestamp; block_header_data} + in + let*@ result = + begin_validation_and_application + pred.context + Chain_id.zero + mode + ~predecessor:pred.header.shell + in + return result + +let validate_and_apply_operation (validation_state, application_state) op = + let open Lwt_result_syntax in + let oph = Operation.hash_packed op in + let* validation_state = validate_operation validation_state oph op in + let* application_state, receipt = apply_operation application_state oph op in + return ((validation_state, application_state), receipt) + +let finalize_validation_and_application (validation_state, application_state) + shell_header = + let open Lwt_result_syntax in + let* () = finalize_validation validation_state in + finalize_application application_state shell_header + +let detect_manager_failure : + type kind. kind Apply_results.operation_metadata -> _ = + let open Result_syntax in + let rec detect_manager_failure : + type kind. kind Apply_results.contents_result_list -> _ = + let open Apply_results in + let open Apply_operation_result in + let open Apply_internal_results in + let detect_manager_failure_single (type kind) + (Manager_operation_result + {operation_result; internal_operation_results; _} : + kind Kind.manager Apply_results.contents_result) = + let detect_manager_failure (type kind) + (result : (kind, _, _) operation_result) = + match result with + | Applied _ -> return_unit + | Skipped _ -> assert false + | Backtracked (_, None) -> + (* there must be another error for this to happen *) + return_unit + | Backtracked (_, Some errs) -> fail errs + | Failed (_, errs) -> fail errs + in + let* () = detect_manager_failure operation_result in + List.iter_e + (fun (Internal_operation_result (_, r)) -> detect_manager_failure r) + internal_operation_results + in + function + | Single_result (Manager_operation_result _ as res) -> + detect_manager_failure_single res + | Single_result _ -> return_unit + | Cons_result (res, rest) -> + let* () = detect_manager_failure_single res in + detect_manager_failure rest + in + fun {contents} -> detect_manager_failure contents + +let apply_with_metadata ?(policy = By_round 0) ?(check_size = true) + ?(baking_mode = Application) ~allow_manager_failures header + ?(operations = []) pred = + let open Lwt_result_wrap_syntax in + let* context, result, contents_result = + let* vstate = + match baking_mode with + | Application -> + let*@ result = + begin_validation_and_application + pred.context + Chain_id.zero + (Application header) + ~predecessor:pred.header.shell + in + return result + | Baking -> + get_construction_vstate + ~policy + ~protocol_data:(Some header.protocol_data) + (pred : t) + in + let*@ vstate, contents_result = + List.fold_left_es + (fun (vstate, contents_result) op -> + (if check_size then + let operation_size = + Data_encoding.Binary.length Operation.encoding op + in + if operation_size > Constants_repr.max_operation_data_length then + raise + (invalid_arg + (Format.sprintf + "The operation size is %d, it exceeds the constant \ + maximum size %d" + operation_size + Constants_repr.max_operation_data_length))) ; + let* state, result = validate_and_apply_operation vstate op in + if allow_manager_failures then + return (state, result :: contents_result) + else + match result with + | No_operation_metadata -> return (state, contents_result) + | Operation_metadata metadata -> + let*? () = detect_manager_failure metadata in + return (state, result :: contents_result)) + (vstate, []) + operations + in + let+@ validation, result = + finalize_validation_and_application vstate (Some header.shell) + in + (validation.context, result, List.rev contents_result) + in + let hash = Block_header.hash header in + let+ constants = Alpha_services.Constants.parametric rpc_ctxt pred in + ({hash; header; operations; context; constants}, (result, contents_result)) + +let apply header ?(operations = []) ?(allow_manager_failures = false) pred = + let open Lwt_result_syntax in + let* t, _metadata = + apply_with_metadata + header + ~operations + pred + ~baking_mode:Application + ~allow_manager_failures + in + return t + +let bake_with_metadata ?locked_round ?policy ?timestamp ?operation ?operations + ?payload_round ?check_size ?baking_mode ?(allow_manager_failures = false) + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote pred = + let open Lwt_result_syntax in + let operations = + match (operation, operations) with + | Some op, Some ops -> Some (op :: ops) + | Some op, None -> Some [op] + | None, Some ops -> Some ops + | None, None -> None + in + let* header = + Forge.forge_header + ?payload_round + ?locked_round + ?timestamp + ?policy + ?operations + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + pred + in + let* header = Forge.sign_header header in + apply_with_metadata + ?policy + ?check_size + ?baking_mode + ~allow_manager_failures + header + ?operations + pred + +let bake_n_with_metadata ?locked_round ?policy ?timestamp ?payload_round + ?check_size ?baking_mode ?(allow_manager_failures = false) + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote n pred = + let open Lwt_result_syntax in + let get_next b = + bake_with_metadata + ?locked_round + ?policy + ?timestamp + ?payload_round + ?check_size + ?baking_mode + ~allow_manager_failures + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + b + in + let* b = get_next pred in + List.fold_left_es (fun (b, _metadata) _ -> get_next b) b (2 -- n) + +let bake ?baking_mode ?(allow_manager_failures = false) ?payload_round + ?locked_round ?policy ?timestamp ?operation ?operations + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote ?check_size pred = + let open Lwt_result_syntax in + let* t, (_metadata : block_header_metadata * operation_receipt list) = + bake_with_metadata + ?payload_round + ?baking_mode + ~allow_manager_failures + ?locked_round + ?policy + ?timestamp + ?operation + ?operations + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + ?check_size + pred + in + return t + +(********** Cycles ****************) + +let bake_n ?baking_mode ?policy ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote n b = + List.fold_left_es + (fun b _ -> + bake + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + b) + b + (1 -- n) + +let rec bake_while_with_metadata ?baking_mode ?policy + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote + ?(invariant = fun _ -> Lwt_result_syntax.return_unit) ?previous_metadata + predicate b = + let open Lwt_result_syntax in + let* () = invariant b in + let* new_block, (metadata, _) = + bake_with_metadata + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + b + in + if predicate new_block metadata then + (bake_while_with_metadata [@ocaml.tailcall]) + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + ~previous_metadata:metadata + ~invariant + predicate + new_block + else return (b, (previous_metadata, metadata)) + +let bake_while_with_metadata = bake_while_with_metadata ?previous_metadata:None + +let bake_while ?baking_mode ?policy ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote ?invariant predicate b = + let open Lwt_result_syntax in + let* b, _ = + bake_while_with_metadata + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + ?invariant + (fun block _metadata -> predicate block) + b + in + return b + +let bake_until_level ?baking_mode ?policy ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote level b = + bake_while + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + (fun b -> b.header.shell.level <= Raw_level.to_int32 level) + b + +let balance_update_of_internal_operation_result = function + | Protocol.Apply_internal_results.Internal_operation_result (_, iopr) -> ( + match iopr with + | Protocol.Apply_operation_result.Backtracked _ | Failed _ | Skipped _ -> + assert false + | Applied siopr -> ( + match siopr with + | ITransaction_result + (Transaction_to_contract_result {balance_updates; _}) + | ITransaction_result + (Transaction_to_zk_rollup_result {balance_updates; _}) + | IOrigination_result {balance_updates; _} + | IDelegation_result {balance_updates; _} -> + balance_updates + | ITransaction_result (Transaction_to_sc_rollup_result _) + | IEvent_result _ -> + [])) + +let balance_update_of_operation_result : + type a. + a Protocol.Apply_results.manager_operation_result -> + Protocol.Alpha_context.Receipt.balance_updates = function + | Protocol.Apply_operation_result.Backtracked _ | Failed _ | Skipped _ -> + assert false + | Applied siopr -> ( + match siopr with + | Protocol.Apply_results.Transaction_result + (Transaction_to_sc_rollup_result _) + | Reveal_result _ | Update_consensus_key_result _ + | Set_deposits_limit_result _ | Transfer_ticket_result _ + | Dal_publish_commitment_result _ | Sc_rollup_originate_result _ + | Sc_rollup_add_messages_result _ | Sc_rollup_cement_result _ + | Sc_rollup_publish_result _ | Sc_rollup_refute_result _ + | Sc_rollup_timeout_result _ | Sc_rollup_execute_outbox_message_result _ + | Sc_rollup_recover_bond_result _ | Zk_rollup_origination_result _ + | Zk_rollup_publish_result _ | Zk_rollup_update_result _ -> + [] + | Delegation_result {balance_updates; _} + | Transaction_result + ( Transaction_to_contract_result {balance_updates; _} + | Transaction_to_zk_rollup_result {balance_updates; _} ) + | Origination_result {balance_updates; _} + | Register_global_constant_result {balance_updates; _} + | Increase_paid_storage_result {balance_updates; _} -> + balance_updates) + +let balance_updates_of_single_content : + type a. + a Protocol.Apply_results.contents_result -> + Protocol.Alpha_context.Receipt.balance_updates = function + | Proposals_result | Ballot_result -> [] + | Preattestation_result {balance_updates; _} + | Attestation_result {balance_updates; _} + | Seed_nonce_revelation_result balance_updates + | Vdf_revelation_result balance_updates + | Double_attestation_evidence_result {balance_updates; _} + | Double_preattestation_evidence_result {balance_updates; _} + | Double_baking_evidence_result {balance_updates; _} + | Activate_account_result balance_updates + | Drain_delegate_result {balance_updates; _} -> + balance_updates + | Manager_operation_result + {balance_updates; internal_operation_results; operation_result} -> + balance_updates + @ (List.map + balance_update_of_internal_operation_result + internal_operation_results + |> List.flatten) + @ balance_update_of_operation_result operation_result + +let rec balance_updates_of_contents : + type a. + a Protocol.Apply_results.contents_result_list -> + Protocol.Alpha_context.Receipt.balance_updates = function + | Single_result c -> balance_updates_of_single_content c + | Cons_result (h, t) -> + balance_updates_of_single_content h @ balance_updates_of_contents t + +let balance_updates_of_packed_operation_metadata : + Protocol.Apply_results.packed_operation_metadata -> + Protocol.Alpha_context.Receipt.balance_updates = function + | No_operation_metadata -> [] + | Operation_metadata {contents} -> balance_updates_of_contents contents + +let get_balance_updates_from_metadata + ( Apply_results.{balance_updates; implicit_operations_results; _}, + operation_receipts ) = + let implicit_balance_updates = + List.( + map + (fun (Protocol.Apply_results.Successful_manager_result r) -> + balance_update_of_operation_result (Applied r)) + implicit_operations_results) + |> List.flatten + in + balance_updates + @ (List.map balance_updates_of_packed_operation_metadata operation_receipts + |> List.flatten) + @ implicit_balance_updates + +let bake_n_with_all_balance_updates ?baking_mode ?policy + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote n b = + let open Lwt_result_syntax in + let+ b, balance_updates_rev = + List.fold_left_es + (fun (b, balance_updates_rev) _ -> + let* b, metadata = + bake_with_metadata + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + b + in + let balance_updates_rev = + List.rev_append + balance_updates_rev + (get_balance_updates_from_metadata metadata) + in + return (b, balance_updates_rev)) + (b, []) + (1 -- n) + in + (b, List.rev balance_updates_rev) + +let bake_n_with_origination_results ?baking_mode ?policy n b = + let open Lwt_result_syntax in + let+ b, origination_results_rev = + List.fold_left_es + (fun (b, origination_results_rev) _ -> + let* b, (metadata, _) = bake_with_metadata ?baking_mode ?policy b in + let origination_results_rev = + List.fold_left + (fun origination_results_rev -> + let open Apply_results in + function + | Successful_manager_result (Reveal_result _) + | Successful_manager_result (Delegation_result _) + | Successful_manager_result (Update_consensus_key_result _) + | Successful_manager_result (Transaction_result _) + | Successful_manager_result (Register_global_constant_result _) + | Successful_manager_result (Set_deposits_limit_result _) + | Successful_manager_result (Increase_paid_storage_result _) + | Successful_manager_result (Transfer_ticket_result _) + | Successful_manager_result (Dal_publish_commitment_result _) + | Successful_manager_result (Sc_rollup_originate_result _) + | Successful_manager_result (Sc_rollup_add_messages_result _) + | Successful_manager_result (Sc_rollup_cement_result _) + | Successful_manager_result (Sc_rollup_publish_result _) + | Successful_manager_result (Sc_rollup_refute_result _) + | Successful_manager_result (Sc_rollup_timeout_result _) + | Successful_manager_result + (Sc_rollup_execute_outbox_message_result _) + | Successful_manager_result (Sc_rollup_recover_bond_result _) + | Successful_manager_result (Zk_rollup_origination_result _) + | Successful_manager_result (Zk_rollup_publish_result _) + | Successful_manager_result (Zk_rollup_update_result _) -> + origination_results_rev + | Successful_manager_result (Origination_result x) -> + Origination_result x :: origination_results_rev) + origination_results_rev + metadata.implicit_operations_results + in + return (b, origination_results_rev)) + (b, []) + (1 -- n) + in + (b, List.rev origination_results_rev) + +let bake_n_with_liquidity_baking_toggle_ema ?baking_mode ?policy + ?liquidity_baking_toggle_vote ?adaptive_issuance_vote n b = + let open Lwt_result_syntax in + let+ b, (metadata, _) = + bake_n_with_metadata + ?baking_mode + ?policy + ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote + n + b + in + (b, metadata.liquidity_baking_toggle_ema) + +let current_cycle_of_level ~blocks_per_cycle ~current_level = + let current_cycle = Int32.div current_level blocks_per_cycle in + let current_cycle = Cycle.add Cycle.root (Int32.to_int current_cycle) in + current_cycle + +let current_cycle b = + let blocks_per_cycle = b.constants.blocks_per_cycle in + let current_level = b.header.shell.level in + current_cycle_of_level ~blocks_per_cycle ~current_level + +let last_block_of_cycle b = + let blocks_per_cycle = b.constants.blocks_per_cycle in + let current_level = b.header.shell.level in + let mod_plus_one = Int32.(rem (succ current_level) blocks_per_cycle) in + Int32.(equal mod_plus_one zero) + +let bake_until_cycle ?baking_mode ?policy cycle (b : t) = + let open Lwt_result_syntax in + let* final_block_of_previous_cycle = + bake_while + ?baking_mode + ?policy + (fun block -> Cycle.(current_cycle block < cycle)) + b + in + bake ?baking_mode ?policy final_block_of_previous_cycle + +let bake_until_cycle_with_metadata ?baking_mode ?policy cycle (b : t) = + bake_while_with_metadata + ?baking_mode + ?policy + (fun block _ -> Cycle.(current_cycle block < cycle)) + b + +let bake_until_cycle_end ?baking_mode ?policy b = + let cycle = current_cycle b in + bake_until_cycle ?baking_mode ?policy (Cycle.succ cycle) b + +let bake_until_cycle_end_with_metadata ?baking_mode ?policy b = + let open Lwt_result_syntax in + let cycle = current_cycle b in + let* blk, (eoc_metadata, nxt_metadata) = + bake_until_cycle_with_metadata ?baking_mode ?policy (Cycle.succ cycle) b + in + return (blk, eoc_metadata, nxt_metadata) + +let bake_until_n_cycle_end ?baking_mode ?policy n b = + let cycle = current_cycle b in + bake_until_cycle ?baking_mode ?policy (Cycle.add cycle n) b + +let bake_until_n_cycle_end_with_metadata ?baking_mode ?policy n b = + let open Lwt_result_syntax in + let cycle = current_cycle b in + let* blk, (eoc_metadata, nxt_metadata) = + bake_until_cycle_with_metadata ?baking_mode ?policy (Cycle.add cycle n) b + in + return (blk, eoc_metadata, nxt_metadata) + +let debited_of_balance_update_item (it : Receipt.balance_update_item) : + Tez.t option = + let open Receipt in + match it with + | Balance_update_item (Contract _, Debited tez, _) -> Some tez + | _ -> None + +let autostaked_opt baker (metadata : block_header_metadata) = + let autostaked_bal_up_opt = + List.find + (function + | Receipt.Balance_update_item + (Contract tzbaker, Receipt.Debited debited_tez, _origin) + when tzbaker = Implicit baker -> + List.exists + (function + | Receipt.Balance_update_item + (Deposits _staker, Receipt.Credited tez, _origin) -> + Tez.(tez = debited_tez) + | _ -> false) + metadata.balance_updates + | _ -> false) + metadata.balance_updates + in + Option.map + (fun receipt -> + match debited_of_balance_update_item receipt with + | None -> assert false + | Some tez -> tez) + autostaked_bal_up_opt + +let autostaked ?(loc = __LOC__) baker metadata = + ignore loc ; + match autostaked_opt baker metadata with None -> Tez.zero | Some tez -> tez diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/block.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/block.mli new file mode 100644 index 000000000000..02fe3efa0ec7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/block.mli @@ -0,0 +1,429 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = { + hash : Block_hash.t; + header : Block_header.t; + operations : Operation.packed list; + context : Tezos_protocol_environment.Context.t; (** Resulting context *) + constants : Constants.Parametric.t; +} + +type block = t + +val rpc_ctxt : t Environment.RPC_context.simple + +(** Policies to select the next baker: + - [By_round r] selects the baker at round [r] + - [By_account pkh] selects the first slot for baker [pkh] + - [Excluding pkhs] selects the first baker that doesn't belong to [pkhs] + + Note that bakers can have active consensus keys different from + their regular delegate keys. For the [By_account pkh] policy, [pkh] + refers to the baker's delegate key. However, for the [Excluding pkhs] + policy, [pkhs] refer to the baker's active consensus key. *) +type baker_policy = + | By_round of int + | By_account of public_key_hash + | Excluding of public_key_hash list + +(** + The default baking functions below is to use (blocks) [Application] mode. + Setting [baking_mode] allows to switch to [Full_construction] mode. +*) +type baking_mode = Application | Baking + +type error += No_slots_found_for of Signature.Public_key_hash.t + +(** Returns (account, consensus_key, round, timestamp) of the next baker given + a policy, defaults to By_round 0. *) +val get_next_baker : + ?policy:baker_policy -> + t -> + (public_key_hash * public_key_hash * int * Time.Protocol.t) tzresult Lwt.t + +val get_round : block -> Round.t Environment.Error_monad.tzresult + +module Forge : sig + val contents : + ?proof_of_work_threshold:Int64.t -> + ?seed_nonce_hash:Nonce_hash.t -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + payload_hash:Block_payload_hash.t -> + payload_round:Round.t -> + Block_header.shell_header -> + Block_header.contents tzresult Lwt.t + + type header + + val classify_operations : packed_operation list -> packed_operation list list + + (** Forges a correct header following the policy. + The header can then be modified and applied with [apply]. *) + val forge_header : + ?locked_round:Alpha_context.Round.t option -> + ?payload_round:Round.t option -> + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?operations:Operation.packed list -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + t -> + header tzresult Lwt.t + + (** Sets uniquely seed_nonce_hash of a header *) + val set_seed_nonce_hash : + ?proof_of_work_threshold:int64 -> + Nonce_hash.t option -> + header -> + (header, tztrace) result Lwt.t + + (** Sets the baker that will sign the header to an arbitrary pkh *) + val set_baker : + public_key_hash -> + ?consensus_key:Signature.public_key_hash -> + header -> + header + + (** Signs the header with the key of the baker configured in the header. + The header can no longer be modified, only applied. *) + val sign_header : header -> Block_header.block_header tzresult Lwt.t +end + +val check_constants_consistency : Constants.Parametric.t -> unit tzresult Lwt.t + +(** [genesis accounts] : generates an initial block with the + given constants [] and initializes [accounts] with their + associated amounts. +*) +val genesis : + ?commitments:Commitment.t list -> + ?consensus_committee_size:int -> + ?consensus_threshold:int -> + ?min_proposal_quorum:int32 -> + ?bootstrap_contracts:Parameters.bootstrap_contract list -> + ?level:int32 -> + ?cost_per_byte:Tez.t -> + ?issuance_weights:Constants.Parametric.issuance_weights -> + ?origination_size:int -> + ?blocks_per_cycle:int32 -> + ?cycles_per_voting_period:int32 -> + ?sc_rollup_arith_pvm_enable:bool -> + ?sc_rollup_private_enable:bool -> + ?sc_rollup_riscv_pvm_enable:bool -> + ?dal_enable:bool -> + ?zk_rollup_enable:bool -> + ?hard_gas_limit_per_block:Gas.Arith.integral -> + ?nonce_revelation_threshold:int32 -> + ?dal:Constants.Parametric.dal -> + ?adaptive_issuance:Constants.Parametric.adaptive_issuance -> + Parameters.bootstrap_account list -> + block tzresult Lwt.t + +val genesis_with_parameters : Parameters.t -> block tzresult Lwt.t + +(** [alpha_context accounts] : instantiates an alpha_context with the + given constants [] and initializes [accounts] with their + associated amounts. +*) +val alpha_context : + ?commitments:Commitment.t list -> + ?min_proposal_quorum:int32 -> + ?consensus_rights_delay:int -> + Parameters.bootstrap_account list -> + Alpha_context.t tzresult Lwt.t + +(** + [get_application_vstate pred operations] constructs a protocol validation + environment for operations in application mode on top of the given block + with the given operations. It's a shortcut for [begin_application] +*) +val get_application_vstate : + t -> + Protocol.operation list -> + (validation_state * application_state) tzresult Lwt.t + +(** + [get_construction_vstate ?policy ?timestamp ?protocol_data pred] + constructs a protocol validation environment for operations in + construction mode on top of the given block. The mode is + full(baking)/partial(mempool) if [protocol_data] given/absent. It's a + shortcut for [begin_construction] + *) +val get_construction_vstate : + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?protocol_data:block_header_data option -> + block -> + (validation_state * application_state) tzresult Lwt.t + +(** applies a signed header and its operations to a block and + obtains a new block *) +val apply : + Block_header.block_header -> + ?operations:Operation.packed list -> + ?allow_manager_failures:bool -> + t -> + t tzresult Lwt.t + +(** [bake b] returns a block [b'] which has as predecessor block [b]. + Optional parameter [policy] allows to pick the next baker in + several ways. If [check_size] is [true] (the default case), then + the function checks that the operations passed as arguments satisfy + the size limit of Tezos operations, as defined in the protocol. + This function bundles together [forge_header], [sign_header] and + [apply]. These functions should be used instead of bake to craft + unusual blocks for testing together with setters for properties of + the headers. Setting [allow_manager_failures] (default=false), + allows baking blocks with manager operation(s) that are valid but + that could fail during their application. If this is not set, the + block is correctly baked but the operations' application will fail + silently. For examples see seed.ml or double_baking.ml +*) +val bake : + ?baking_mode:baking_mode -> + ?allow_manager_failures:bool -> + ?payload_round:Round.t option -> + ?locked_round:Alpha_context.Round.t option -> + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?operation:Operation.packed -> + ?operations:Operation.packed list -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + ?check_size:bool -> + t -> + t tzresult Lwt.t + +(** Variant of [bake] that returns the block metadata of the baked block. **) +val bake_with_metadata : + ?locked_round:Alpha_context.Round.t option -> + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?operation:Operation.packed -> + ?operations:Operation.packed list -> + ?payload_round:Round.t option -> + ?check_size:bool -> + ?baking_mode:baking_mode -> + ?allow_manager_failures:bool -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + t -> + (t * (block_header_metadata * operation_receipt list)) tzresult Lwt.t + +(** Bakes [n] blocks. *) +val bake_n : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + int -> + t -> + block tzresult Lwt.t + +(** Bakes until the given level is reached. *) +val bake_until_level : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + Raw_level.t -> + t -> + block tzresult Lwt.t + +(** Version of bake_n that returns a list of all balance updates included + in the metadata of baked blocks. **) +val bake_n_with_all_balance_updates : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + int -> + t -> + (block * Alpha_context.Receipt.balance_updates) tzresult Lwt.t + +(** Version of bake_n that returns a list of all origination results + in the metadata of baked blocks. **) +val bake_n_with_origination_results : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + int -> + t -> + (block + * Alpha_context.Kind.origination + Apply_results.successful_manager_operation_result + list) + tzresult + Lwt.t + +(** Version of bake_n that returns the liquidity baking toggle EMA after [n] blocks. **) +val bake_n_with_liquidity_baking_toggle_ema : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes.per_block_vote -> + int -> + t -> + (block * Alpha_context.Per_block_votes.Liquidity_baking_toggle_EMA.t) tzresult + Lwt.t + +(** Variant of [bake_n] that returns the block metadata of the last + baked block. [n] must be positive, otherwise a single block is baked. **) +val bake_n_with_metadata : + ?locked_round:Round.t option -> + ?policy:baker_policy -> + ?timestamp:Timestamp.time -> + ?payload_round:Round.t option -> + ?check_size:bool -> + ?baking_mode:baking_mode -> + ?allow_manager_failures:bool -> + ?liquidity_baking_toggle_vote:Per_block_votes_repr.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes_repr.per_block_vote -> + int -> + block -> + (block * (block_header_metadata * operation_receipt list)) tzresult Lwt.t + +val get_balance_updates_from_metadata : + block_header_metadata * operation_receipt list -> + Alpha_context.Receipt.balance_updates + +(** Bake blocks while a predicate over the block holds. The returned + block is the last one for which the predicate holds; in case the + predicate never holds, the input block is returned. When the + optional [invariant] argument is provided, it is checked on the + input block and on each baked block, including the returned one + (the last one satisfy the predicate); it is however not checked + on the next block (the first one to invalidate the predicate). *) +val bake_while : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes_repr.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes_repr.per_block_vote -> + ?invariant:(block -> unit tzresult Lwt.t) -> + (block -> bool) -> + block -> + block tzresult Lwt.t + +(* Same as [bake_while] but the predicate also has access to the + metadata resulting from the application of the block. + + optionnal metadata of the last block stisfying the condition and metadata of + the last block (which don't) are returned together with the block. +*) +val bake_while_with_metadata : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes_repr.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes_repr.per_block_vote -> + ?invariant:(block -> unit tzresult Lwt.t) -> + (block -> block_header_metadata -> bool) -> + block -> + (block * (block_header_metadata option * block_header_metadata)) tzresult + Lwt.t + +val current_cycle_of_level : + blocks_per_cycle:int32 -> current_level:int32 -> Cycle.t + +val current_cycle : block -> Cycle.t + +val last_block_of_cycle : block -> bool + +(** Given a block [b] at level [l] bakes enough blocks to complete a cycle, + that is [blocks_per_cycle - (l % blocks_per_cycle)]. *) +val bake_until_cycle_end : + ?baking_mode:baking_mode -> ?policy:baker_policy -> t -> t tzresult Lwt.t + +(** Given a block [b] at level [l] bakes enough blocks to complete a cycle, + that is [blocks_per_cycle - (l % blocks_per_cycle)]. *) +val bake_until_cycle_end_with_metadata : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + block -> + (block * block_header_metadata option * block_header_metadata) tzresult Lwt.t + +(** Bakes enough blocks to end [n] cycles. *) +val bake_until_n_cycle_end : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + int -> + t -> + t tzresult Lwt.t + +val bake_until_n_cycle_end_with_metadata : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + int -> + block -> + (block * block_header_metadata option * block_header_metadata) tzresult Lwt.t + +(** Bakes enough blocks to reach the cycle. *) +val bake_until_cycle : + ?baking_mode:baking_mode -> + ?policy:baker_policy -> + Cycle.t -> + t -> + t tzresult Lwt.t + +(** Common util function to create parameters for [initial_context] function *) +val prepare_initial_context_params : + ?consensus_committee_size:int -> + ?consensus_threshold:int -> + ?min_proposal_quorum:int32 -> + ?level:int32 -> + ?cost_per_byte:Tez.t -> + ?issuance_weights:Constants.Parametric.issuance_weights -> + ?origination_size:int -> + ?blocks_per_cycle:int32 -> + ?cycles_per_voting_period:int32 -> + ?sc_rollup_arith_pvm_enable:bool -> + ?sc_rollup_private_enable:bool -> + ?sc_rollup_riscv_pvm_enable:bool -> + ?dal_enable:bool -> + ?zk_rollup_enable:bool -> + ?hard_gas_limit_per_block:Gas.Arith.integral -> + ?nonce_revelation_threshold:int32 -> + ?dal:Constants.Parametric.dal -> + ?adaptive_issuance:Constants.Parametric.adaptive_issuance -> + ?consensus_rights_delay:int -> + unit -> + ( Constants.Parametric.t * Block_header.shell_header * Block_hash.t, + tztrace ) + result + Lwt.t + +(** [autostaked_opt delegate metadata] returns [Some amount] if [amount] tez + have been staked for the given [delegate]. [None] otherwise. *) +val autostaked_opt : public_key_hash -> block_header_metadata -> Tez.t option + +(** same as [autostaked_opt] but fails in case autostaking didn't provoke a + stake operation. *) +val autostaked : + ?loc:string -> public_key_hash -> block_header_metadata -> Tez.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/consensus_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/consensus_helpers.ml new file mode 100644 index 000000000000..c5fe62a3b10d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/consensus_helpers.ml @@ -0,0 +1,191 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type mode = Application | Construction | Mempool + +let show_mode = function + | Application -> "Application" + | Construction -> "Construction" + | Mempool -> "Mempool" + +type kind = Preattestation | Attestation + +(** Craft an attestation or preattestation, and bake a block + containing it (in application or construction modes) or inject it + into a mempool. When [error] is [None], check that it succeeds, + otherwise check that it fails as specified by [error]. + + By default, the (pre)attestation is for the first slot and is + signed by the delegate that owns this slot. Moreover, the operation + points to the given [attested_block]: in other words, it has that + block's level, round, payload hash, and its branch is the + predecessor of that block. Optional arguments allow to override + these default parameters. + + The [predecessor] is used as the predecessor of the baked block or + the head of the mempool. When it is not provided, we use the + [attested_block] for this. *) +let test_consensus_operation ?delegate ?slot ?level ?round ?block_payload_hash + ?branch ~attested_block ?(predecessor = attested_block) ?error ~loc kind + mode = + let open Lwt_result_syntax in + let* operation = + match kind with + | Preattestation -> + Op.preattestation + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + attested_block + | Attestation -> + Op.attestation + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + attested_block + in + let check_error res = + match error with + | Some error -> Assert.proto_error ~loc res error + | None -> + let*? _ = res in + return_unit + in + match mode with + | Application -> + let*! result = + Block.bake ~baking_mode:Application ~operation predecessor + in + check_error result + | Construction -> + let*! result = Block.bake ~baking_mode:Baking ~operation predecessor in + check_error result + | Mempool -> + let*! res = + let* inc = + Incremental.begin_construction ~mempool_mode:true predecessor + in + let* inc = Incremental.add_operation inc operation in + (* Finalization doesn't do much in mempool mode, but some RPCs + still call it, so we check that it doesn't fail unexpectedly. *) + Incremental.finalize_block inc + in + check_error res + +let test_consensus_operation_all_modes_different_outcomes ?delegate ?slot ?level + ?round ?block_payload_hash ?branch ~attested_block ?predecessor ~loc + ?application_error ?construction_error ?mempool_error kind = + List.iter_es + (fun (mode, error) -> + test_consensus_operation + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + ~attested_block + ?predecessor + ?error + ~loc:(Format.sprintf "%s (%s mode)" loc (show_mode mode)) + kind + mode) + [ + (Application, application_error); + (Construction, construction_error); + (Mempool, mempool_error); + ] + +let test_consensus_operation_all_modes ?delegate ?slot ?level ?round + ?block_payload_hash ?branch ~attested_block ?predecessor ?error ~loc kind = + test_consensus_operation_all_modes_different_outcomes + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + ~attested_block + ?predecessor + ~loc + ?application_error:error + ?construction_error:error + ?mempool_error:error + kind + +let delegate_of_first_slot b = + let open Lwt_result_syntax in + let module V = Plugin.RPC.Validators in + let+ attesters = Context.get_attesters b in + match attesters with + | {V.consensus_key; slots = s :: _; _} :: _ -> (consensus_key, s) + | _ -> assert false + +let delegate_of_slot ?(different_slot = false) slot b = + let open Lwt_result_syntax in + let module V = Plugin.RPC.Validators in + let+ attesters = Context.get_attesters b in + List.find_map + (function + | {V.consensus_key; slots = s :: _; _} + when if different_slot then not (Slot.equal s slot) + else Slot.equal s slot -> + Some consensus_key + | _ -> None) + attesters + |> function + | None -> assert false + | Some d -> d + +let test_consensus_op_for_next ~genesis ~kind ~next = + let open Lwt_result_syntax in + let dorsement ~attested_block ~delegate = + match kind with + | `Preattestation -> Op.preattestation ~delegate attested_block + | `Attestation -> Op.attestation ~delegate attested_block + in + let* b1 = Block.bake genesis in + let* b2 = + match next with + | `Level -> Block.bake b1 + | `Round -> Block.bake ~policy:(By_round 1) genesis + in + let* inc = Incremental.begin_construction ~mempool_mode:true b1 in + let* delegate, slot = delegate_of_first_slot (B b1) in + let* operation = dorsement ~attested_block:b1 ~delegate in + let* inc = Incremental.add_operation inc operation in + let* delegate = delegate_of_slot ~different_slot:true slot (B b2) in + let* operation = dorsement ~attested_block:b2 ~delegate in + let* (_ : Incremental.t) = Incremental.add_operation inc operation in + return_unit diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/context.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/context.ml new file mode 100644 index 000000000000..a6aefda902a4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/context.ml @@ -0,0 +1,789 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t = B of Block.t | I of Incremental.t + +let get_alpha_ctxt ?(policy = Block.By_round 0) c = + let open Lwt_result_syntax in + match c with + | I i -> return (Incremental.alpha_ctxt i) + | B b -> + let* i = Incremental.begin_construction ~policy b in + return (Incremental.alpha_ctxt i) + +let branch = function B b -> b.hash | I i -> (Incremental.predecessor i).hash + +let pred_branch = function + | B b -> b.header.shell.predecessor + | I i -> (Incremental.predecessor i).hash + +let level = function B b -> b.header.shell.level | I i -> Incremental.level i + +let get_level ctxt = + let open Result_wrap_syntax in + let+@ res = level ctxt |> Raw_level.of_int32 in + res + +let rpc_ctxt = + object + method call_proto_service0 + : 'm 'q 'i 'o. + ( ([< Tezos_rpc.Service.meth] as 'm), + Environment.RPC_context.t, + Environment.RPC_context.t, + 'q, + 'i, + 'o ) + Tezos_rpc.Service.t -> + t -> + 'q -> + 'i -> + 'o tzresult Lwt.t = + fun s pr q i -> + match pr with + | B b -> Block.rpc_ctxt#call_proto_service0 s b q i + | I b -> Incremental.rpc_ctxt#call_proto_service0 s b q i + + method call_proto_service1 + : 'm 'a 'q 'i 'o. + ( ([< Tezos_rpc.Service.meth] as 'm), + Environment.RPC_context.t, + Environment.RPC_context.t * 'a, + 'q, + 'i, + 'o ) + Tezos_rpc.Service.t -> + t -> + 'a -> + 'q -> + 'i -> + 'o tzresult Lwt.t = + fun s pr a q i -> + match pr with + | B bl -> Block.rpc_ctxt#call_proto_service1 s bl a q i + | I bl -> Incremental.rpc_ctxt#call_proto_service1 s bl a q i + + method call_proto_service2 + : 'm 'a 'b 'q 'i 'o. + ( ([< Tezos_rpc.Service.meth] as 'm), + Environment.RPC_context.t, + (Environment.RPC_context.t * 'a) * 'b, + 'q, + 'i, + 'o ) + Tezos_rpc.Service.t -> + t -> + 'a -> + 'b -> + 'q -> + 'i -> + 'o tzresult Lwt.t = + fun s pr a b q i -> + match pr with + | B bl -> Block.rpc_ctxt#call_proto_service2 s bl a b q i + | I bl -> Incremental.rpc_ctxt#call_proto_service2 s bl a b q i + + method call_proto_service3 + : 'm 'a 'b 'c 'q 'i 'o. + ( ([< Tezos_rpc.Service.meth] as 'm), + Environment.RPC_context.t, + ((Environment.RPC_context.t * 'a) * 'b) * 'c, + 'q, + 'i, + 'o ) + Tezos_rpc.Service.t -> + t -> + 'a -> + 'b -> + 'c -> + 'q -> + 'i -> + 'o tzresult Lwt.t = + fun s pr a b c q i -> + match pr with + | B bl -> Block.rpc_ctxt#call_proto_service3 s bl a b c q i + | I bl -> Incremental.rpc_ctxt#call_proto_service3 s bl a b c q i + end + +let get_attesters ctxt = Plugin.RPC.Validators.get rpc_ctxt ctxt + +let get_first_different_attesters ctxt = + let open Lwt_result_syntax in + let+ attesters = get_attesters ctxt in + match attesters with x :: y :: _ -> (x, y) | _ -> assert false + +let get_attester ctxt = + let open Lwt_result_syntax in + let+ attesters = get_attesters ctxt in + let attester = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd attesters in + (attester.consensus_key, attester.slots) + +let get_attester_slot ctxt pkh = + let open Lwt_result_syntax in + let+ attesters = get_attesters ctxt in + List.find_map + (function + | {Plugin.RPC.Validators.consensus_key; slots; _} -> + if Signature.Public_key_hash.(consensus_key = pkh) then Some slots + else None) + attesters + +let get_attester_n ctxt n = + let open Lwt_result_syntax in + let+ attesters = Plugin.RPC.Validators.get rpc_ctxt ctxt in + let attester = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth attesters n + in + (attester.consensus_key, attester.slots) + +let get_attesting_power_for_delegate ctxt ?level pkh = + let open Lwt_result_syntax in + let levels = Option.map (fun level -> [level]) level in + let* attesters = Plugin.RPC.Validators.get rpc_ctxt ?levels ctxt in + let rec find_slots_for_delegate = function + | [] -> return 0 + | {Plugin.RPC.Validators.delegate; slots; _} :: t -> + if Signature.Public_key_hash.equal delegate pkh then + return (List.length slots) + else find_slots_for_delegate t + in + find_slots_for_delegate attesters + +let get_cumulated_attesting_power_for_delegate ctxt ~levels pkh = + let open Lwt_result_syntax in + List.fold_left_es + (fun accu level -> + let+ power = get_attesting_power_for_delegate ctxt ~level pkh in + accu + power) + 0 + levels + +let get_current_voting_power = Delegate_services.current_voting_power rpc_ctxt + +let get_voting_power = Delegate_services.voting_power rpc_ctxt + +let get_total_voting_power = Alpha_services.Voting.total_voting_power rpc_ctxt + +let get_current_baking_power = Delegate_services.current_baking_power rpc_ctxt + +let get_bakers ?filter ?cycle ctxt = + let open Lwt_result_syntax in + let+ bakers = Plugin.RPC.Baking_rights.get rpc_ctxt ?cycle ctxt in + (match filter with None -> bakers | Some f -> List.filter f bakers) + |> List.map (fun p -> p.Plugin.RPC.Baking_rights.delegate) + +let get_baker ctxt ~round = + let open Lwt_result_syntax in + let* bakers = get_bakers ~filter:(fun x -> x.round = round) ctxt in + (* there is only one baker for a given round *) + match bakers with [baker] -> return baker | _ -> assert false + +let get_first_different_baker baker bakers = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.find + (fun baker' -> Signature.Public_key_hash.( <> ) baker baker') + bakers + +let get_first_different_bakers ?(excluding = []) ctxt = + let open Lwt_result_syntax in + let+ bakers = get_bakers ctxt in + let bakers = + List.filter + (fun baker -> not (List.mem ~equal:( = ) baker excluding)) + bakers + in + match bakers with + | [] -> assert false + | baker_1 :: other_bakers -> + (baker_1, get_first_different_baker baker_1 other_bakers) + +let get_seed_nonce_hash ctxt = + let open Lwt_result_syntax in + let header = + match ctxt with B {header; _} -> header | I i -> Incremental.header i + in + match header.protocol_data.contents.seed_nonce_hash with + | None -> failwith "No committed nonce" + | Some hash -> return hash + +let get_seed ctxt = Alpha_services.Seed.get rpc_ctxt ctxt + +let get_seed_computation ctxt = + Alpha_services.Seed_computation.get rpc_ctxt ctxt + +let get_constants ctxt = Alpha_services.Constants.all rpc_ctxt ctxt + +let default_test_constants = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_test + +let get_issuance_per_minute ctxt = + Adaptive_issuance_services.current_issuance_per_minute rpc_ctxt ctxt + +let get_baking_reward_fixed_portion ctxt = + let open Lwt_result_wrap_syntax in + let* {Constants.parametric = csts; _} = get_constants ctxt in + let*?@ reward = + Delegate.Rewards.For_RPC.reward_from_constants + csts + ~reward_kind:Baking_reward_fixed_portion + in + return reward + +let get_bonus_reward ctxt ~attesting_power = + let open Lwt_result_wrap_syntax in + let* {Constants.parametric = {consensus_threshold; _} as csts; _} = + get_constants ctxt + in + let*?@ baking_reward_bonus_per_slot = + Delegate.Rewards.For_RPC.reward_from_constants + csts + ~reward_kind:Baking_reward_bonus_per_slot + in + let multiplier = max 0 (attesting_power - consensus_threshold) in + return Test_tez.(baking_reward_bonus_per_slot *! Int64.of_int multiplier) + +let get_attesting_reward ctxt ~expected_attesting_power = + let open Lwt_result_wrap_syntax in + let* {Constants.parametric = csts; _} = get_constants ctxt in + let*?@ attesting_reward_per_slot = + Delegate.Rewards.For_RPC.reward_from_constants + csts + ~reward_kind:Attesting_reward_per_slot + in + let*?@ t = + Tez.(attesting_reward_per_slot *? Int64.of_int expected_attesting_power) + in + return t + +let get_liquidity_baking_subsidy ctxt = + let open Lwt_result_wrap_syntax in + let* {Constants.parametric = csts; _} = get_constants ctxt in + let*?@ reward = + Delegate.Rewards.For_RPC.liquidity_baking_subsidy_from_constants csts + in + return reward + +let get_liquidity_baking_cpmm_address ctxt = + Alpha_services.Liquidity_baking.get_cpmm_address rpc_ctxt ctxt + +let get_adaptive_issuance_launch_cycle ctxt = + Adaptive_issuance_services.launch_cycle rpc_ctxt ctxt + +let get_total_frozen_stake ctxt = + Adaptive_issuance_services.total_frozen_stake rpc_ctxt ctxt + +let get_total_supply ctxt = + Adaptive_issuance_services.total_supply rpc_ctxt ctxt + +let get_seed_nonce_revelation_tip ctxt = + let open Lwt_result_wrap_syntax in + let* {Constants.parametric = csts; _} = get_constants ctxt in + let*?@ reward = + Delegate.Rewards.For_RPC.reward_from_constants + csts + ~reward_kind:Seed_nonce_revelation_tip + in + return reward + +let get_vdf_revelation_tip ctxt = + let open Lwt_result_wrap_syntax in + let* {Constants.parametric = csts; _} = get_constants ctxt in + let*?@ reward = + Delegate.Rewards.For_RPC.reward_from_constants + csts + ~reward_kind:Vdf_revelation_tip + in + return reward + +let get_ai_current_yearly_rate ctxt = + Adaptive_issuance_services.current_yearly_rate rpc_ctxt ctxt + +let get_ai_current_yearly_rate_exact ctxt = + Adaptive_issuance_services.current_yearly_rate_exact rpc_ctxt ctxt + +let get_ai_expected_issuance ctxt = + Adaptive_issuance_services.expected_issuance rpc_ctxt ctxt + +let get_denunciations ctxt = + Alpha_services.Denunciations.denunciations rpc_ctxt ctxt + +let get_denunciations_for_delegate ctxt = + Alpha_services.Delegate.pending_denunciations rpc_ctxt ctxt + +let estimated_shared_pending_slashed_amount ctxt = + Alpha_services.Delegate.estimated_shared_pending_slashed_amount rpc_ctxt ctxt + +let estimated_own_pending_slashed_amount ctxt = + Alpha_services.Contract.estimated_own_pending_slashed_amount rpc_ctxt ctxt + +module Dal = struct + let shards ctxt = Plugin.RPC.Dal.dal_shards rpc_ctxt ctxt +end + +(* Voting *) + +module Vote = struct + let get_ballots ctxt = Alpha_services.Voting.ballots rpc_ctxt ctxt + + let get_ballot_list ctxt = Alpha_services.Voting.ballot_list rpc_ctxt ctxt + + let get_current_period ctxt = + Alpha_services.Voting.current_period rpc_ctxt ctxt + + let get_current_quorum ctxt = + Alpha_services.Voting.current_quorum rpc_ctxt ctxt + + let get_listings ctxt = Alpha_services.Voting.listings rpc_ctxt ctxt + + let get_proposals ctxt = Alpha_services.Voting.proposals rpc_ctxt ctxt + + let get_current_proposal ctxt = + Alpha_services.Voting.current_proposal rpc_ctxt ctxt + + let get_protocol (b : Block.t) = + Tezos_protocol_environment.Context.get_protocol b.context + + let get_delegate_proposal_count ctxt pkh = + Alpha_services.Voting.delegate_proposal_count rpc_ctxt ctxt pkh + + let get_participation_ema (b : Block.t) = + let open Lwt_syntax in + let+ bytes_opt = + Environment.Context.find b.context ["votes"; "participation_ema"] + in + match bytes_opt with + | None -> assert false + | Some bytes -> Ok (TzEndian.get_int32 bytes 0) + + let set_participation_ema (b : Block.t) ema = + let open Lwt_syntax in + let bytes = Bytes.make 4 '\000' in + TzEndian.set_int32 bytes 0 ema ; + let+ context = + Environment.Context.add b.context ["votes"; "participation_ema"] bytes + in + {b with context} + + type delegate_info = Alpha_context.Vote.delegate_info = { + voting_power : Int64.t option; + current_ballot : Alpha_context.Vote.ballot option; + current_proposals : Protocol_hash.t list; + remaining_proposals : int; + } +end + +module Contract = struct + let pp = Alpha_context.Contract.pp + + let equal a b = Alpha_context.Contract.compare a b = 0 + + let pkh = function + | Contract.Implicit p -> p + | Originated _ -> Stdlib.failwith "pkh: only for implicit contracts" + + let balance ctxt contract = + Alpha_services.Contract.balance rpc_ctxt ctxt contract + + let frozen_bonds ctxt contract = + Alpha_services.Contract.frozen_bonds rpc_ctxt ctxt contract + + let balance_and_frozen_bonds ctxt contract = + Alpha_services.Contract.balance_and_frozen_bonds rpc_ctxt ctxt contract + + let staked_balance ctxt contract = + Alpha_services.Contract.staked_balance rpc_ctxt ctxt contract + + let unstaked_frozen_balance ctxt contract = + Alpha_services.Contract.unstaked_frozen_balance rpc_ctxt ctxt contract + + let unstaked_finalizable_balance ctxt contract = + Alpha_services.Contract.unstaked_finalizable_balance rpc_ctxt ctxt contract + + let full_balance ctxt contract = + Alpha_services.Contract.full_balance rpc_ctxt ctxt contract + + let staking_numerator ctxt contract = + let open Lwt_result_syntax in + let+ pseudotokens = + Alpha_services.Contract.staking_numerator rpc_ctxt ctxt contract + in + Staking_pseudotoken.Internal_for_tests.to_z pseudotokens + + let counter ctxt (contract : Contract.t) = + match contract with + | Originated _ -> invalid_arg "Helpers.Context.counter" + | Implicit mgr -> Alpha_services.Contract.counter rpc_ctxt ctxt mgr + + let manager _ (contract : Contract.t) = + match contract with + | Originated _ -> invalid_arg "Helpers.Context.manager" + | Implicit pkh -> Account.find pkh + + let is_manager_key_revealed ctxt (contract : Contract.t) = + let open Lwt_result_syntax in + match contract with + | Originated _ -> invalid_arg "Helpers.Context.is_manager_key_revealed" + | Implicit mgr -> + let+ res = Alpha_services.Contract.manager_key rpc_ctxt ctxt mgr in + res <> None + + let delegate ctxt contract = + Alpha_services.Contract.delegate rpc_ctxt ctxt contract + + let delegate_opt ctxt contract = + Alpha_services.Contract.delegate_opt rpc_ctxt ctxt contract + + let storage ctxt contract = + Alpha_services.Contract.storage rpc_ctxt ctxt contract + + let script ctxt contract = + let open Lwt_result_syntax in + let* {code; storage = _} = + Alpha_services.Contract.script rpc_ctxt ctxt contract + in + match Data_encoding.force_decode code with + | Some v -> return v + | None -> invalid_arg "Cannot force lazy script" + + let script_hash ctxt contract = + let open Lwt_result_syntax in + let* script = script ctxt contract in + let bytes = Data_encoding.Binary.to_bytes_exn Script.expr_encoding script in + return @@ Script_expr_hash.hash_bytes [bytes] +end + +module Delegate = struct + type info = Delegate_services.info = { + full_balance : Tez.t; + current_frozen_deposits : Tez.t; + frozen_deposits : Tez.t; + staking_balance : Tez.t; + frozen_deposits_limit : Tez.t option; + delegated_contracts : Alpha_context.Contract.t list; + delegated_balance : Tez.t; + min_delegated_in_current_cycle : Tez.t * Level_repr.t option; + total_delegated_stake : Tez.t; + staking_denominator : Staking_pseudotoken.t; + deactivated : bool; + grace_period : Cycle.t; + pending_denunciations : bool; + voting_info : Alpha_context.Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; + } + + type stake = {frozen : Tez.t; weighted_delegated : Tez.t} + + let info ctxt pkh = Plugin.RPC.Delegates.info rpc_ctxt ctxt pkh + + let full_balance ctxt pkh = Delegate_services.full_balance rpc_ctxt ctxt pkh + + let current_frozen_deposits ctxt pkh = + Delegate_services.current_frozen_deposits rpc_ctxt ctxt pkh + + let initial_frozen_deposits ctxt pkh = + Delegate_services.frozen_deposits rpc_ctxt ctxt pkh + + let staking_balance ctxt pkh = + Delegate_services.staking_balance rpc_ctxt ctxt pkh + + let staking_denominator ctxt pkh = + let open Lwt_result_syntax in + let+ pseudotokens = + Delegate_services.staking_denominator rpc_ctxt ctxt pkh + in + Staking_pseudotoken.Internal_for_tests.to_z pseudotokens + + let frozen_deposits_limit ctxt pkh = + Delegate_services.frozen_deposits_limit rpc_ctxt ctxt pkh + + let deactivated ctxt pkh = Delegate_services.deactivated rpc_ctxt ctxt pkh + + let voting_info ctxt d = Alpha_services.Delegate.voting_info rpc_ctxt ctxt d + + let consensus_key ctxt pkh = Delegate_services.consensus_key rpc_ctxt ctxt pkh + + let participation ctxt pkh = Delegate_services.participation rpc_ctxt ctxt pkh + + let is_forbidden ?policy ctxt pkh = + let open Lwt_result_syntax in + let* ctxt = get_alpha_ctxt ?policy ctxt in + return (Delegate.is_forbidden_delegate ctxt pkh) + + let stake_for_cycle ?policy ctxt cycle pkh = + let open Lwt_result_wrap_syntax in + let* alpha_ctxt = get_alpha_ctxt ?policy ctxt in + let*@ stakes = + Protocol.Alpha_context.Stake_distribution.Internal_for_tests + .get_selected_distribution + alpha_ctxt + cycle + in + let stake_opt = + List.assoc ~equal:Signature.Public_key_hash.equal pkh stakes + in + let Protocol.Stake_repr.{frozen; weighted_delegated} = + Option.value ~default:Protocol.Stake_repr.zero stake_opt + in + let frozen = Protocol.Tez_repr.to_mutez frozen |> Tez.of_mutez_exn in + let weighted_delegated = + Protocol.Tez_repr.to_mutez weighted_delegated |> Tez.of_mutez_exn + in + return {frozen; weighted_delegated} +end + +module Sc_rollup = struct + let inbox ctxt = + Environment.RPC_context.make_call0 + Plugin.RPC.Sc_rollup.S.inbox + rpc_ctxt + ctxt + () + () + + let whitelist ctxt rollup = + Environment.RPC_context.make_call1 + Plugin.RPC.Sc_rollup.S.whitelist + rpc_ctxt + ctxt + rollup + () + () + + let commitment ctxt sc_rollup hash = + Environment.RPC_context.make_call2 + Plugin.RPC.Sc_rollup.S.commitment + rpc_ctxt + ctxt + sc_rollup + hash + () + () + + let genesis_info ctxt sc_rollup = + Environment.RPC_context.make_call1 + Plugin.RPC.Sc_rollup.S.genesis_info + rpc_ctxt + ctxt + sc_rollup + () + () + + let timeout ctxt sc_rollup staker1 staker2 = + Environment.RPC_context.make_call3 + Plugin.RPC.Sc_rollup.S.timeout + rpc_ctxt + ctxt + sc_rollup + staker1 + staker2 + () + () + + let ongoing_games_for_staker ctxt sc_rollup staker = + Environment.RPC_context.make_call2 + Plugin.RPC.Sc_rollup.S.ongoing_refutation_games + rpc_ctxt + ctxt + sc_rollup + staker + () + () +end + +type (_, _) tup = + | T1 : ('a, 'a) tup + | T2 : ('a, 'a * 'a) tup + | T3 : ('a, 'a * 'a * 'a) tup + | TList : int -> ('a, 'a list) tup + +let tup_hd : type a r. (a, r) tup -> r -> a = + fun tup elts -> + match (tup, elts) with + | T1, v -> v + | T2, (v, _) -> v + | T3, (v, _, _) -> v + | TList _, v :: _ -> v + | TList _, [] -> assert false + +let tup_n : type a r. (a, r) tup -> int = function + | T1 -> 1 + | T2 -> 2 + | T3 -> 3 + | TList n -> n + +let tup_get : type a r. (a, r) tup -> a list -> r = + fun tup list -> + match (tup, list) with + | T1, [v] -> v + | T2, [v1; v2] -> (v1, v2) + | T3, [v1; v2; v3] -> (v1, v2, v3) + | TList _, l -> l + | _ -> assert false + +let init_gen tup ?rng_state ?commitments ?bootstrap_balances + ?bootstrap_delegations ?bootstrap_consensus_keys ?consensus_committee_size + ?consensus_threshold ?min_proposal_quorum ?bootstrap_contracts ?level + ?cost_per_byte ?issuance_weights ?origination_size ?blocks_per_cycle + ?cycles_per_voting_period ?sc_rollup_arith_pvm_enable + ?sc_rollup_private_enable ?sc_rollup_riscv_pvm_enable ?dal_enable + ?zk_rollup_enable ?hard_gas_limit_per_block ?nonce_revelation_threshold ?dal + ?adaptive_issuance () = + let open Lwt_result_syntax in + let n = tup_n tup in + let*? accounts = Account.generate_accounts ?rng_state n in + let contracts = + List.map (fun a -> Alpha_context.Contract.Implicit Account.(a.pkh)) accounts + in + let bootstrap_accounts = + Account.make_bootstrap_accounts + ?bootstrap_balances + ?bootstrap_delegations + ?bootstrap_consensus_keys + accounts + in + let+ blk = + Block.genesis + ?commitments + ?consensus_committee_size + ?consensus_threshold + ?min_proposal_quorum + ?bootstrap_contracts + ?level + ?cost_per_byte + ?issuance_weights + ?origination_size + ?blocks_per_cycle + ?cycles_per_voting_period + ?sc_rollup_arith_pvm_enable + ?sc_rollup_private_enable + ?sc_rollup_riscv_pvm_enable + ?dal_enable + ?zk_rollup_enable + ?hard_gas_limit_per_block + ?nonce_revelation_threshold + ?dal + ?adaptive_issuance + bootstrap_accounts + in + (blk, tup_get tup contracts) + +let init_n n = init_gen (TList n) + +let init1 = init_gen T1 + +let init2 = init_gen T2 + +let init3 = init_gen T3 + +let create_bootstrap_accounts n = + let open Result_syntax in + let* accounts = Account.generate_accounts n in + let contracts = + List.map (fun a -> Alpha_context.Contract.Implicit Account.(a.pkh)) accounts + in + let bootstrap_accounts = Account.make_bootstrap_accounts accounts in + return (bootstrap_accounts, contracts) + +let init_with_constants_gen tup constants = + let open Lwt_result_syntax in + let n = tup_n tup in + let*? bootstrap_accounts, contracts = create_bootstrap_accounts n in + let parameters = + Tezos_protocol_020_PsParisC_parameters.Default_parameters + .parameters_of_constants + ~bootstrap_accounts + constants + in + let* blk = Block.genesis_with_parameters parameters in + return (blk, tup_get tup contracts) + +let init_with_constants_n constants n = + init_with_constants_gen (TList n) constants + +let init_with_constants1 = init_with_constants_gen T1 + +let init_with_constants2 = init_with_constants_gen T2 + +let init_with_parameters_gen tup parameters = + let open Lwt_result_syntax in + let n = tup_n tup in + let*? bootstrap_accounts, contracts = create_bootstrap_accounts n in + let parameters = Parameters.{parameters with bootstrap_accounts} in + let* blk = Block.genesis_with_parameters parameters in + return (blk, tup_get tup contracts) + +let init_with_parameters_n params n = init_with_parameters_gen (TList n) params + +let init_with_parameters1 = init_with_parameters_gen T1 + +let init_with_parameters2 = init_with_parameters_gen T2 + +let default_raw_context () = + let open Lwt_result_wrap_syntax in + let open Tezos_protocol_020_PsParisC_parameters in + let initial_account = Account.new_account () in + let bootstrap_accounts = + Account.make_bootstrap_account + ~balance:(Tez.of_mutez_exn 100_000_000_000L) + initial_account + in + let* constants, _, _ = Block.prepare_initial_context_params () in + let parameters = + Default_parameters.parameters_of_constants + ~bootstrap_accounts:[bootstrap_accounts] + ~commitments:[] + constants + in + let json = Default_parameters.json_of_parameters parameters in + let proto_params = + Data_encoding.Binary.to_bytes_exn Data_encoding.json json + in + let protocol_param_key = ["protocol_parameters"] in + let*! context = + Tezos_protocol_environment.Context.( + let empty = Tezos_protocol_environment.Memory_context.empty in + let*! ctxt = add empty ["version"] (Bytes.of_string "genesis") in + add ctxt protocol_param_key proto_params) + in + let typecheck_smart_contract ctxt script_repr = + return ((script_repr, None), ctxt) + in + let typecheck_smart_rollup ctxt _script_repr = Ok ctxt in + let*@ e = + Init_storage.prepare_first_block + Chain_id.zero + context + ~level:0l + ~timestamp:(Time.Protocol.of_seconds 1643125688L) + ~predecessor:Block_hash.zero + ~typecheck_smart_contract + ~typecheck_smart_rollup + in + return e diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/context.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/context.mli new file mode 100644 index 000000000000..c6593218e140 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/context.mli @@ -0,0 +1,458 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Environment + +type t = B of Block.t | I of Incremental.t + +val branch : t -> Block_hash.t + +val pred_branch : t -> Block_hash.t + +val get_level : t -> Raw_level.t tzresult + +(** Given a context, returns the list of attesters charactized by + the [level], the public key hash of the [delegate], its [consensus_key] + and its assigned [slots]. + see {! Plugin.RPC.Validator.t}. *) +val get_attesters : t -> Plugin.RPC.Validators.t list tzresult Lwt.t + +(** Return the two first elements of the list returns by [get_attesters]. *) +val get_first_different_attesters : + t -> (Plugin.RPC.Validators.t * Plugin.RPC.Validators.t) tzresult Lwt.t + +(** Return the first element [delegate,slot] of the list returns by + [get_attesters], where [delegate] is the [consensus key] when + is set. *) +val get_attester : t -> (public_key_hash * Slot.t list) tzresult Lwt.t + +(** Given a [delegate], and a context [ctxt], if [delegate] is in + [get_attesters ctxt] returns the [slots] of [delegate] otherwise + return [None]. *) +val get_attester_slot : + t -> public_key_hash -> Slot.t list option tzresult Lwt.t + +(** Return the [n]th element of the list returns by [get_attesters]. *) +val get_attester_n : t -> int -> (public_key_hash * Slot.t list) tzresult Lwt.t + +(** Counts the number of attesting slots that the given delegate has + in the requested level. If ommited, [level] defaults to the next + level. *) +val get_attesting_power_for_delegate : + t -> ?level:Raw_level.t -> public_key_hash -> int tzresult Lwt.t + +(** Sums the result of [get_attesting_power_for_delegate] over a list + of levels. *) +val get_cumulated_attesting_power_for_delegate : + t -> levels:Raw_level.t list -> public_key_hash -> int tzresult Lwt.t + +val get_current_voting_power : + t -> public_key_hash -> int64 Environment.Error_monad.shell_tzresult Lwt.t + +val get_voting_power : + t -> public_key_hash -> int64 Environment.Error_monad.shell_tzresult Lwt.t + +val get_total_voting_power : + t -> int64 Environment.Error_monad.shell_tzresult Lwt.t + +val get_current_baking_power : + t -> public_key_hash -> int64 Environment.Error_monad.shell_tzresult Lwt.t + +val get_bakers : + ?filter:(Plugin.RPC.Baking_rights.t -> bool) -> + ?cycle:Cycle.t -> + t -> + public_key_hash list tzresult Lwt.t + +val get_baker : t -> round:Round.t -> public_key_hash tzresult Lwt.t + +val get_first_different_baker : + public_key_hash -> public_key_hash trace -> public_key_hash + +val get_first_different_bakers : + ?excluding:public_key_hash list -> + t -> + (public_key_hash * public_key_hash) tzresult Lwt.t + +val get_seed_nonce_hash : t -> Nonce_hash.t tzresult Lwt.t + +(** Returns the seed of the cycle to which the block belongs to. *) +val get_seed : t -> Seed.seed tzresult Lwt.t + +val get_seed_computation : t -> Seed.seed_computation_status tzresult Lwt.t + +(** Returns all the constants of the protocol *) +val get_constants : t -> Constants.t tzresult Lwt.t + +(** The default constants used in the test framework. To be used with + [init_with_constants]. *) +val default_test_constants : Constants.Parametric.t + +val get_issuance_per_minute : t -> Tez.t tzresult Lwt.t + +val get_baking_reward_fixed_portion : t -> Tez.t tzresult Lwt.t + +val get_bonus_reward : t -> attesting_power:int -> Tez.t tzresult Lwt.t + +val get_attesting_reward : + t -> expected_attesting_power:int -> Tez.t tzresult Lwt.t + +val get_liquidity_baking_subsidy : t -> Tez.t tzresult Lwt.t + +val get_liquidity_baking_cpmm_address : t -> Contract_hash.t tzresult Lwt.t + +val get_adaptive_issuance_launch_cycle : t -> Cycle.t option tzresult Lwt.t + +val get_total_frozen_stake : t -> Tez.t tzresult Lwt.t + +val get_total_supply : t -> Tez.t tzresult Lwt.t + +val get_seed_nonce_revelation_tip : t -> Tez.t tzresult Lwt.t + +val get_vdf_revelation_tip : t -> Tez.t tzresult Lwt.t + +val get_ai_current_yearly_rate : t -> string tzresult Lwt.t + +val get_ai_current_yearly_rate_exact : t -> Q.t tzresult Lwt.t + +val get_ai_expected_issuance : + t -> Adaptive_issuance_services.expected_rewards list tzresult Lwt.t + +val get_denunciations : + t -> + (Signature.Public_key_hash.t * Denunciations_repr.item) list tzresult Lwt.t + +val get_denunciations_for_delegate : + t -> + Signature.Public_key_hash.t -> + Denunciations_repr.item list tzresult Lwt.t + +val estimated_shared_pending_slashed_amount : + t -> public_key_hash -> Tez.t tzresult Lwt.t + +val estimated_own_pending_slashed_amount : + t -> public_key_hash -> Tez.t tzresult Lwt.t + +module Vote : sig + val get_ballots : t -> Vote.ballots tzresult Lwt.t + + val get_ballot_list : + t -> (Signature.Public_key_hash.t * Vote.ballot) list tzresult Lwt.t + + val get_current_period : t -> Voting_period.info tzresult Lwt.t + + val get_current_quorum : t -> int32 tzresult Lwt.t + + val get_participation_ema : Block.t -> int32 tzresult Lwt.t + + val get_listings : + t -> (Signature.Public_key_hash.t * int64) list tzresult Lwt.t + + val get_proposals : t -> int64 Protocol_hash.Map.t tzresult Lwt.t + + val get_current_proposal : t -> Protocol_hash.t option tzresult Lwt.t + + val get_protocol : Block.t -> Protocol_hash.t Lwt.t + + val set_participation_ema : Block.t -> int32 -> Block.t Lwt.t + + type delegate_info = Alpha_context.Vote.delegate_info = { + voting_power : Int64.t option; + current_ballot : Alpha_context.Vote.ballot option; + current_proposals : Protocol_hash.t list; + remaining_proposals : int; + } + + (** See {!Vote_storage.get_delegate_proposal_count}. + + Note that unlike most functions in the current module, this one + does not call an RPC. *) + val get_delegate_proposal_count : t -> public_key_hash -> int tzresult Lwt.t +end + +module Dal : sig + val shards : + t -> + ?level:Raw_level.t -> + ?delegates:Signature.public_key_hash list -> + unit -> + Plugin.RPC.Dal.S.shards_output tzresult Lwt.t +end + +module Contract : sig + val pp : Format.formatter -> Contract.t -> unit + + val equal : Contract.t -> Contract.t -> bool + + val pkh : Contract.t -> public_key_hash + + (** Returns the balance of a contract, by default the main balance. + If the contract is implicit the frozen balances are available too: + deposit, fees or rewards. *) + val balance : t -> Contract.t -> Tez.t tzresult Lwt.t + + val frozen_bonds : t -> Contract.t -> Tez.t tzresult Lwt.t + + val balance_and_frozen_bonds : t -> Contract.t -> Tez.t tzresult Lwt.t + + val staked_balance : t -> Contract.t -> Tez.t option tzresult Lwt.t + + val unstaked_frozen_balance : t -> Contract.t -> Tez.t option tzresult Lwt.t + + val unstaked_finalizable_balance : + t -> Contract.t -> Tez.t option tzresult Lwt.t + + val full_balance : t -> Contract.t -> Tez.t tzresult Lwt.t + + val staking_numerator : t -> Contract.t -> Z.t tzresult Lwt.t + + val counter : t -> Contract.t -> Manager_counter.t tzresult Lwt.t + + val manager : t -> Contract.t -> Account.t tzresult Lwt.t + + val is_manager_key_revealed : t -> Contract.t -> bool tzresult Lwt.t + + val delegate : t -> Contract.t -> public_key_hash tzresult Lwt.t + + val delegate_opt : t -> Contract.t -> public_key_hash option tzresult Lwt.t + + val storage : t -> Contract_hash.t -> Script.expr tzresult Lwt.t + + val script : t -> Contract_hash.t -> Script.expr tzresult Lwt.t + + val script_hash : t -> Contract_hash.t -> Script_expr_hash.t tzresult Lwt.t +end + +module Delegate : sig + type info = Delegate_services.info = { + full_balance : Tez.t; + current_frozen_deposits : Tez.t; + frozen_deposits : Tez.t; + staking_balance : Tez.t; + frozen_deposits_limit : Tez.t option; + delegated_contracts : Alpha_context.Contract.t list; + delegated_balance : Tez.t; + min_delegated_in_current_cycle : Tez.t * Level_repr.t option; + total_delegated_stake : Tez.t; + staking_denominator : Staking_pseudotoken.t; + deactivated : bool; + grace_period : Cycle.t; + pending_denunciations : bool; + voting_info : Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; + } + + type stake = {frozen : Tez.t; weighted_delegated : Tez.t} + + val info : t -> public_key_hash -> Delegate_services.info tzresult Lwt.t + + val full_balance : t -> public_key_hash -> Tez.t tzresult Lwt.t + + val current_frozen_deposits : t -> public_key_hash -> Tez.t tzresult Lwt.t + + (** calls the RPC [frozen_deposits]: we're using a different name to + be more easily distinguishable from [current_frozen_deposits] *) + val initial_frozen_deposits : t -> public_key_hash -> Tez.t tzresult Lwt.t + + val staking_balance : t -> public_key_hash -> Tez.t tzresult Lwt.t + + val staking_denominator : t -> public_key_hash -> Z.t tzresult Lwt.t + + val frozen_deposits_limit : + t -> public_key_hash -> Tez.t option tzresult Lwt.t + + val deactivated : t -> public_key_hash -> bool tzresult Lwt.t + + val voting_info : t -> public_key_hash -> Vote.delegate_info tzresult Lwt.t + + val consensus_key : + t -> public_key_hash -> Delegate_services.consensus_keys_info tzresult Lwt.t + + val participation : + t -> public_key_hash -> Delegate.For_RPC.participation_info tzresult Lwt.t + + (** This function might begin constructing a block. Use [policy] to + specify a valid baker for the new block (default [By_round 0]) *) + val is_forbidden : + ?policy:Block.baker_policy -> t -> public_key_hash -> bool tzresult Lwt.t + + val stake_for_cycle : + ?policy:Block.baker_policy -> + t -> + Cycle.t -> + public_key_hash -> + stake tzresult Lwt.t +end + +module Sc_rollup : sig + val inbox : t -> Sc_rollup.Inbox.t tzresult Lwt.t + + val whitelist : + t -> Sc_rollup.t -> Sc_rollup.Whitelist.t option tzresult Lwt.t + + val commitment : + t -> + Sc_rollup.t -> + Sc_rollup.Commitment.Hash.t -> + Sc_rollup.Commitment.t tzresult Lwt.t + + val genesis_info : + t -> Sc_rollup.t -> Sc_rollup.Commitment.genesis_info tzresult Lwt.t + + val timeout : + t -> + Sc_rollup.t -> + Signature.Public_key_hash.t -> + Signature.Public_key_hash.t -> + Sc_rollup.Game.timeout option tzresult Lwt.t + + val ongoing_games_for_staker : + t -> + Sc_rollup.t -> + Signature.public_key_hash -> + (Sc_rollup.Game.t * Signature.public_key_hash * Signature.public_key_hash) + list + tzresult + Lwt.t +end + +type (_, _) tup = + | T1 : ('a, 'a) tup + | T2 : ('a, 'a * 'a) tup + | T3 : ('a, 'a * 'a * 'a) tup + | TList : int -> ('a, 'a list) tup + +val tup_hd : ('a, 'elts) tup -> 'elts -> 'a + +type 'accounts init := + ?rng_state:Random.State.t -> + ?commitments:Commitment.t list -> + ?bootstrap_balances:int64 list -> + ?bootstrap_delegations:Signature.Public_key_hash.t option list -> + ?bootstrap_consensus_keys:Signature.Public_key.t option list -> + ?consensus_committee_size:int -> + ?consensus_threshold:int -> + ?min_proposal_quorum:int32 -> + ?bootstrap_contracts:Parameters.bootstrap_contract list -> + ?level:int32 -> + ?cost_per_byte:Tez.t -> + ?issuance_weights:Constants.Parametric.issuance_weights -> + ?origination_size:int -> + ?blocks_per_cycle:int32 -> + ?cycles_per_voting_period:int32 -> + ?sc_rollup_arith_pvm_enable:bool -> + ?sc_rollup_private_enable:bool -> + ?sc_rollup_riscv_pvm_enable:bool -> + ?dal_enable:bool -> + ?zk_rollup_enable:bool -> + ?hard_gas_limit_per_block:Gas.Arith.integral -> + ?nonce_revelation_threshold:int32 -> + ?dal:Constants.Parametric.dal -> + ?adaptive_issuance:Constants.Parametric.adaptive_issuance -> + unit -> + (Block.t * 'accounts) tzresult Lwt.t + +(** Returns an initial block and the implicit contracts corresponding + to its bootstrap accounts. The number of bootstrap accounts, and + the structure of the returned contracts, are specified by the [tup] + argument. *) +val init_gen : (Alpha_context.Contract.t, 'accounts) tup -> 'accounts init + +(** [init_n n] : returns an initial block with [n] initialized accounts + and the associated implicit contracts *) +val init_n : int -> Alpha_context.Contract.t list init + +(** [init1] : returns an initial block with 1 initialized bootstrap account + and the associated implicit contract *) +val init1 : Alpha_context.Contract.t init + +(** [init2] : returns an initial block with 2 initialized bootstrap accounts + and the associated implicit contracts *) +val init2 : (Alpha_context.Contract.t * Alpha_context.Contract.t) init + +(** [init3] : returns an initial block with 3 initialized bootstrap accounts + and the associated implicit contracts *) +val init3 : + (Alpha_context.Contract.t + * Alpha_context.Contract.t + * Alpha_context.Contract.t) + init + +val init_with_constants_gen : + (Alpha_context.Contract.t, 'contracts) tup -> + Constants.Parametric.t -> + (Block.t * 'contracts) tzresult Lwt.t + +val init_with_constants_n : + Constants.Parametric.t -> + int -> + (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t + +val init_with_constants1 : + Constants.Parametric.t -> (Block.t * Alpha_context.Contract.t) tzresult Lwt.t + +val init_with_constants2 : + Constants.Parametric.t -> + (Block.t * (Alpha_context.Contract.t * Alpha_context.Contract.t)) tzresult + Lwt.t + +(** [init_with_parameters_gen tup params] returns an initial block parametrised + with [params] and the implicit contracts corresponding to its bootstrap + accounts. The number of bootstrap accounts, and the structure of the + returned contracts, are specified by the [tup] argument. *) +val init_with_parameters_gen : + (Alpha_context.Contract.t, 'contracts) tup -> + Parameters.t -> + (Block.t * 'contracts) tzresult Lwt.t + +(** [init_with_parameters_n params n] returns an initial block parametrized + with [params] with [n] initialized accounts and the associated implicit + contracts *) +val init_with_parameters_n : + Parameters.t -> + int -> + (Block.t * Alpha_context.Contract.t list) tzresult Lwt.t + +(** [init_with_parameters1 params] returns an initial block parametrized with + [params] with one initialized account and the associated implicit + contract. *) +val init_with_parameters1 : + Parameters.t -> (Block.t * Alpha_context.Contract.t) tzresult Lwt.t + +(** [init_with_parameters2 params] returns an initial block parametrized with + [params] with two initialized accounts and the associated implicit + contracts *) +val init_with_parameters2 : + Parameters.t -> + (Block.t * (Alpha_context.Contract.t * Alpha_context.Contract.t)) tzresult + Lwt.t + +(** [default_raw_context] returns a [Raw_context.t] for use in tests + below [Alpha_context] *) +val default_raw_context : unit -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/contract_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/contract_helpers.ml new file mode 100644 index 000000000000..32043ee302b7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/contract_helpers.ml @@ -0,0 +1,160 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Initializes 2 addresses to do only operations plus one that will be + used to bake. *) +let init () = + let open Lwt_result_syntax in + let+ b, (src0, src1, src2) = Context.init3 ~consensus_threshold:0 () in + let baker = + match src0 with Implicit v -> v | Originated _ -> assert false + in + (b, baker, src1, src2) + +(** Return contents of a given file as string. *) +let read_file f = + In_channel.with_open_text f (fun ic -> + really_input_string ic (in_channel_length ic)) + +(** Loads a script from file. *) +let load_script ~storage file = + let contract_string = read_file file in + let code = Expr.toplevel_from_string contract_string in + let storage = Expr.from_string storage in + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + +(** Returns a block in which the contract is originated. *) +let originate_contract_hash file storage src b baker = + let open Lwt_result_syntax in + let script = load_script ~storage file in + let* operation, dst = + Op.contract_origination_hash (B b) src ~fee:(Test_tez.of_int 10) ~script + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) b + in + let* incr = Incremental.add_operation incr operation in + let+ b = Incremental.finalize_block incr in + (dst, b) + +let originate_contract file storage src b baker = + let open Lwt_result_syntax in + let+ dst, b = originate_contract_hash file storage src b baker in + (Contract.Originated dst, b) + +let fake_KT1 = + Contract_hash.of_b58check_exn "KT1FAKEFAKEFAKEFAKEFAKEFAKEFAKGGSE2x" + +let default_self = fake_KT1 + +let default_payer = Signature.Public_key_hash.zero + +let default_sender = Contract.Implicit default_payer + +let default_step_constants = + Script_interpreter. + { + sender = Contract default_sender; + payer = default_payer; + self = default_self; + amount = Tez.zero; + balance = Tez.zero; + chain_id = Chain_id.zero; + now = Script_timestamp.of_zint Z.zero; + level = Script_int.zero_n; + } + +(** Helper function that parses and typechecks a script, its initial storage and + parameters from strings. It then executes the typed script with the storage + and parameters and returns the result. + + The [step_constants] argument passes in some data which remains constant + throughout script's execution, hence the name. This includes addresses of + the sender and payer, the address of the smart contract, the amount of Tez + transferred to it and so on. + + An [internal] operation is an operation generated by smart contract's execution + rather than by an implicit account. *) +let run_script ctx ?logger ?(step_constants = default_step_constants) + ?(internal = false) contract ?(entrypoint = Entrypoint.default) ~storage + ~parameter () = + let open Lwt_result_wrap_syntax in + let contract_expr = Expr.from_string contract in + let storage_expr = Expr.from_string storage in + let parameter_expr = Expr.from_string parameter in + let script = + Script.{code = lazy_expr contract_expr; storage = lazy_expr storage_expr} + in + let*@ res = + Script_interpreter.execute + ctx + Readable + step_constants + ?logger + ~script + ~cached_script:None + ~entrypoint + ~parameter:parameter_expr + ~internal + in + return res + +let originate_contract_from_string_hash ~script ~storage ~source_contract ~baker + block = + let open Lwt_result_syntax in + let code = Expr.toplevel_from_string script in + let storage = Expr.from_string storage in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + let* operation, dst = + Op.contract_origination_hash + (B block) + source_contract + ~fee:(Test_tez.of_int 10) + ~script + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let* incr = Incremental.add_operation incr operation in + let+ b = Incremental.finalize_block incr in + (dst, script, b) + +let originate_contract_from_string ~script ~storage ~source_contract ~baker + block = + let open Lwt_result_syntax in + let+ dst, script, b = + originate_contract_from_string_hash + ~script + ~storage + ~source_contract + ~baker + block + in + (Contract.Originated dst, script, b) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_logic.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_logic.ml new file mode 100644 index 000000000000..a1d4d8027c58 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_logic.ml @@ -0,0 +1,102 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This is a simulation of the CPMM contract, as implemented in mligo + in [src/proto_alpha/lib_protocol/contracts/cpmm.mligo]. The + interested reader should look for comments in this file to gain a + better understanding of the contract logic. *) +module Simulate_raw = struct + let mutez_to_natural t = Z.of_int64 (Tez.to_mutez t) + + let natural_to_mutez n = Tez.of_mutez_exn (Z.to_int64 n) + + let addLiquidity ~tokenPool ~xtzPool ~lqtTotal ~amount = + let xtzPool = mutez_to_natural xtzPool in + let nat_amount = mutez_to_natural amount in + let lqt_minted = Z.(nat_amount * lqtTotal / xtzPool) in + let tokens_deposited = Z.(cdiv (nat_amount * tokenPool) xtzPool) in + (lqt_minted, tokens_deposited) + + let removeLiquidity ~tokenPool ~xtzPool ~lqtTotal ~lqtBurned = + let xtz_withdrawn = + natural_to_mutez Z.(lqtBurned * mutez_to_natural xtzPool / lqtTotal) + in + let tokens_withdrawn = Z.(lqtBurned * tokenPool / lqtTotal) in + (xtz_withdrawn, tokens_withdrawn) + + let tokenToXtz ~tokenPool ~xtzPool ~tokensSold = + let fee = Z.of_int 999 in + let xtz_bought_nat = + Z.( + tokensSold * fee * mutez_to_natural xtzPool + / ((tokenPool * of_int 1000) + (tokensSold * fee))) + in + let bought = Z.(xtz_bought_nat * of_int 999 / of_int 1000) in + (natural_to_mutez bought, xtz_bought_nat) + + let xtzToToken ~tokenPool ~xtzPool ~amount = + let fee = Z.of_int 999 in + let xtzPool = mutez_to_natural xtzPool in + let nat_amount = mutez_to_natural amount in + let amount_net_burn = Z.(nat_amount * Z.of_int 999 / Z.of_int 1000) in + let tokens_bought = + Z.( + amount_net_burn * fee * tokenPool + / ((xtzPool * Z.of_int 1000) + (amount_net_burn * fee))) + in + (tokens_bought, amount_net_burn) + + let tokenToToken ~tokenPool ~xtzPool ~tokensSold = + let fee = Z.of_int 999 in + let xtz_bought_nat = + Z.( + tokensSold * fee * mutez_to_natural xtzPool + / ((tokenPool * of_int 1000) + (tokensSold * fee))) + in + let xtz_bought_net_burn = Z.(xtz_bought_nat * of_int 999 / of_int 1000) in + (natural_to_mutez xtz_bought_net_burn, xtz_bought_nat) +end + +module Simulate = struct + open Cpmm_repr.Storage + + let addLiquidity {tokenPool; xtzPool; lqtTotal; _} amount = + Simulate_raw.addLiquidity ~xtzPool ~tokenPool ~lqtTotal ~amount + + let removeLiquidity {tokenPool; xtzPool; lqtTotal; _} lqtBurned = + Simulate_raw.removeLiquidity ~tokenPool ~xtzPool ~lqtTotal ~lqtBurned + + let tokenToXtz {tokenPool; xtzPool; _} tokensSold = + Simulate_raw.tokenToXtz ~tokenPool ~xtzPool ~tokensSold + + let xtzToToken {tokenPool; xtzPool; _} amount = + Simulate_raw.xtzToToken ~tokenPool ~xtzPool ~amount + + let tokenToToken {tokenPool; xtzPool; _} tokensSold = + Simulate_raw.tokenToToken ~tokenPool ~xtzPool ~tokensSold +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_repr.ml new file mode 100644 index 000000000000..365f5b30ac70 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/cpmm_repr.ml @@ -0,0 +1,386 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Expr_common + +(* // ============================================================================= + * // Storage + * // ============================================================================= *) + +module Storage = struct + type t = { + tokenPool : Z.t; + xtzPool : Tez.t; + lqtTotal : Z.t; + tokenAddress : Contract_hash.t; + lqtAddress : Contract_hash.t; + } + + let zero : t = + { + tokenPool = Z.zero; + xtzPool = Tez.zero; + lqtTotal = Z.zero; + tokenAddress = Contract_hash.zero; + lqtAddress = Contract_hash.zero; + } + + let to_string {tokenPool; xtzPool; lqtTotal; tokenAddress; lqtAddress} = + Format.asprintf + "{tokenPool : %a; xtzPool : %s; lqtTotal : %a; tokenAddress : %s; \ + lqtAddress : %s;}" + Z.pp_print + tokenPool + (Int64.to_string @@ Tez.to_mutez xtzPool) + Z.pp_print + lqtTotal + (Contract_hash.to_b58check tokenAddress) + (Contract_hash.to_b58check lqtAddress) + + let pp fmt s = Format.fprintf fmt "%s" (to_string s) + + let eq s s' = s = s' + + let to_expr : + loc:'a -> + t -> + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node = + fun ~loc {tokenPool; xtzPool; lqtTotal; tokenAddress; lqtAddress} -> + comb + ~loc + [ + int ~loc tokenPool; + mutez ~loc xtzPool; + int ~loc lqtTotal; + address_string ~loc (Contract.Originated tokenAddress); + address_string ~loc (Contract.Originated lqtAddress); + ] + + let to_michelson_string e = + let e = to_expr ~loc:0 e in + Format.asprintf + "%a" + Michelson_v1_printer.print_expr + (Micheline.strip_locations e) + + type exn += Invalid_storage_expr of string + + (** Note: parses a storage unparsed in readable mode (as + e.g. returned by [Alpha_services.Contract.storage]), so that + contracts are represented by strings. *) + let of_expr_exn : + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node -> t = + function + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Int (_, tokenPool); + Tezos_micheline.Micheline.Int (_, xtzPool); + Tezos_micheline.Micheline.Int (_, lqtTotal); + Tezos_micheline.Micheline.String (_, tokenAddress); + Tezos_micheline.Micheline.String (_, lqtAddress); + ], + [] ) -> + let xtzPool = Tez.of_mutez_exn (Z.to_int64 xtzPool) in + let tokenAddress = originated_of_string_exn tokenAddress in + let lqtAddress = originated_of_string_exn lqtAddress in + {tokenPool; xtzPool; lqtTotal; tokenAddress; lqtAddress} + | e -> + let canonical = Micheline.strip_locations e in + let msg = + Format.asprintf + "Not a valid CPMM storage: %s /// %a" + (try + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc:true + canonical + with Z.Overflow -> + "Cannot represent as micheline due to overflowing Z -> int") + Michelson_v1_printer.print_expr + canonical + in + raise (Invalid_storage_expr msg) + + let get (ctxt : Context.t) ~(contract : Contract.t) : t tzresult Lwt.t = + let open Lwt_result_syntax in + match contract with + | Implicit _ -> + invalid_arg "Cpmm_repr.Storage.get called on implicit account" + | Originated c -> + let+ expr = Context.Contract.storage ctxt c in + Micheline.root expr |> of_expr_exn + + let of_tuple (tokenPool, xtzPool, lqtTotal, tokenAddress, lqtAddress) = + {tokenPool; xtzPool; lqtTotal; tokenAddress; lqtAddress} + + let to_tuple {tokenPool; xtzPool; lqtTotal; tokenAddress; lqtAddress} = + (tokenPool, xtzPool, lqtTotal, tokenAddress, lqtAddress) + + let valid {tokenPool; xtzPool; lqtTotal; _} = + tokenPool > Z.zero && lqtTotal > Z.zero && Tez.(xtzPool > Tez.zero) +end + +module Parameter = struct + (* // ============================================================================= + * // Entrypoints + * // ============================================================================= *) + + type add_liquidity = { + owner : Contract.t; + minLqtMinted : Z.t; + maxTokensDeposited : Z.t; + deadline : Script_timestamp.t; + } + + type remove_liquidity = { + to_ : Contract.t; + (* recipient of the liquidity redemption *) + lqtBurned : Z.t; + (* amount of lqt owned by sender to burn *) + minXtzWithdrawn : Tez.t; + (* minimum amount of Tez.t to withdraw *) + minTokensWithdrawn : Z.t; + (* minimum amount of tokens to withdraw *) + deadline : Script_timestamp.t; + (* the time before which the request must be completed *) + } + + type token_to_token = { + outputDexterContract : Contract.t; + minTokensBought : Z.t; + to_ : Contract.t; + tokensSold : Z.t; + deadline : Script_timestamp.t; + } + + type token_to_xtz = { + to_ : Contract.t; + tokensSold : Z.t; + minXtzBought : Tez.t; + deadline : Script_timestamp.t; + } + + type xtz_to_token = { + to_ : Contract.t; + minTokensBought : Z.t; + deadline : Script_timestamp.t; + } + + type t = + | AddLiquidity of add_liquidity + | Default of unit + | RemoveLiquidity of remove_liquidity + | TokenToToken of token_to_token + | TokenToXtz of token_to_xtz + | XtzToToken of xtz_to_token + + let addLiquidity p = AddLiquidity p + + let default p = Default p + + let removeLiquidity p = RemoveLiquidity p + + let tokenToToken p = TokenToToken p + + let tokenToXtz p = TokenToXtz p + + let xtzToToken p = XtzToToken p + + let add_liquidity_to_string : add_liquidity -> string = + fun {owner; minLqtMinted; maxTokensDeposited; deadline} -> + Format.asprintf + "{owner : %s; minLqtMinted : %a; maxTokensDeposited : %a; deadline : %s }" + (Contract.to_b58check owner) + Z.pp_print + minLqtMinted + Z.pp_print + maxTokensDeposited + (Script_timestamp.to_string deadline) + + let remove_liquidity_to_string : remove_liquidity -> string = + fun {to_; lqtBurned; minXtzWithdrawn; minTokensWithdrawn; deadline} -> + Format.asprintf + "{owner : %s; lqtBurned : %a; minXtzWithdrawn : %s; minTokensWithdrawn : \ + %a; deadline : %s }" + (Contract.to_b58check to_) + Z.pp_print + lqtBurned + (Int64.to_string @@ Tez.to_mutez minXtzWithdrawn) + Z.pp_print + minTokensWithdrawn + (Script_timestamp.to_string deadline) + + let token_to_token_to_string : token_to_token -> string = + fun {outputDexterContract; minTokensBought; to_; tokensSold; deadline} -> + Format.asprintf + "{outputDexterContract : %s; minTokensBought : %a; to_ : %s; tokensSold \ + : %a; deadline : %s }" + (Contract.to_b58check outputDexterContract) + Z.pp_print + minTokensBought + (Contract.to_b58check to_) + Z.pp_print + tokensSold + (Script_timestamp.to_string deadline) + + let token_to_xtz_to_string : token_to_xtz -> string = + fun {to_; tokensSold; minXtzBought; deadline} -> + Format.asprintf + "{to_ : %s; tokensSold : %a; minXtzBought : %s; deadline : %s }" + (Contract.to_b58check to_) + Z.pp_print + tokensSold + (Int64.to_string @@ Tez.to_mutez minXtzBought) + (Script_timestamp.to_string deadline) + + let xtz_to_token_to_string : xtz_to_token -> string = + fun {to_; minTokensBought; deadline} -> + Format.asprintf + "{to_ : %s; minTokensBought : %a; deadline : %s }" + (Contract.to_b58check to_) + Z.pp_print + minTokensBought + (Script_timestamp.to_string deadline) + + let to_string : t -> string = function + | AddLiquidity p -> + Format.asprintf "AddLiquidity %s" (add_liquidity_to_string p) + | Default () -> "Default ()" + | RemoveLiquidity p -> + Format.asprintf "RemoveLiquidity %s" (remove_liquidity_to_string p) + | TokenToToken p -> + Format.asprintf "TokenToToken (%s)" (token_to_token_to_string p) + | TokenToXtz p -> + Format.asprintf "TokenToXtz (%s)" (token_to_xtz_to_string p) + | XtzToToken p -> + Format.asprintf "XtzToToken (%s)" (xtz_to_token_to_string p) + + let entrypoint_of_parameter : t -> Entrypoint.t = function + | AddLiquidity _ -> Entrypoint.of_string_strict_exn "addLiquidity" + | Default _ -> Entrypoint.default + | RemoveLiquidity _ -> Entrypoint.of_string_strict_exn "removeLiquidity" + | TokenToToken _ -> Entrypoint.of_string_strict_exn "tokenToToken" + | TokenToXtz _ -> Entrypoint.of_string_strict_exn "tokenToXtz" + | XtzToToken _ -> Entrypoint.of_string_strict_exn "xtzToToken" + + let pp fmt s = Format.fprintf fmt "%s" (to_string s) + + let eq s s' = s = s' + + let to_expr_rooted : + loc:'a -> + t -> + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node = + fun ~loc -> function + | AddLiquidity {owner; minLqtMinted; maxTokensDeposited; deadline} -> + comb + ~loc + [ + address_string ~loc owner; + int ~loc minLqtMinted; + int ~loc maxTokensDeposited; + timestamp ~loc deadline; + ] + | Default () -> unit ~loc () + | RemoveLiquidity + {to_; lqtBurned; minXtzWithdrawn; minTokensWithdrawn; deadline} -> + comb + ~loc + [ + address_string ~loc to_; + int ~loc lqtBurned; + mutez ~loc minXtzWithdrawn; + int ~loc minTokensWithdrawn; + timestamp ~loc deadline; + ] + | TokenToToken + {outputDexterContract; minTokensBought; to_; tokensSold; deadline} -> + comb + ~loc + [ + address_string ~loc outputDexterContract; + int ~loc minTokensBought; + address_string ~loc to_; + int ~loc tokensSold; + timestamp ~loc deadline; + ] + | TokenToXtz {to_; tokensSold; minXtzBought; deadline} -> + comb + ~loc + [ + address_string ~loc to_; + int ~loc tokensSold; + mutez ~loc minXtzBought; + timestamp ~loc deadline; + ] + | XtzToToken {to_; minTokensBought; deadline} -> + comb + ~loc + [ + address_string ~loc to_; + int ~loc minTokensBought; + timestamp ~loc deadline; + ] + + let to_expr : + loc:'a -> + t -> + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node = + fun ~loc p -> + let rooted = to_expr_rooted ~loc p in + match p with + | AddLiquidity _ -> left ~loc @@ left ~loc @@ left ~loc rooted + | Default () -> left ~loc @@ left ~loc @@ right ~loc rooted + | RemoveLiquidity _ -> left ~loc @@ right ~loc @@ left ~loc rooted + | TokenToToken _ -> left ~loc @@ right ~loc @@ right ~loc rooted + | TokenToXtz _ -> right ~loc @@ left ~loc rooted + | XtzToToken _ -> right ~loc @@ right ~loc rooted + + let to_michelson_string e = + let e = to_expr ~loc:0 e in + Format.asprintf + "%a" + Michelson_v1_printer.print_expr + (Micheline.strip_locations e) +end + +let transaction (ctxt : Context.t) ~(contract : Contract.t) ~(src : Contract.t) + ?(amount = Tez.zero) (parameters : Parameter.t) = + let entrypoint = Parameter.entrypoint_of_parameter parameters in + let rooted_param_lazy = + parameters + |> Parameter.to_expr_rooted ~loc:0 + |> Micheline.strip_locations |> Alpha_context.Script.lazy_expr + in + Op.transaction + ctxt + src + contract + amount + ~entrypoint + ~parameters:rooted_param_lazy diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.ml new file mode 100644 index 000000000000..3d9e72457d2e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.ml @@ -0,0 +1,282 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module S = Dal_slot_repr +module Slot_index = Dal_slot_index_repr +module P = S.Page +module Hist = S.History +module Ihist = Hist.Internal_for_tests + +(** Error used below for functions that don't return their failures in the monad + error. *) +type error += Test_failure of string + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:(Protocol.name ^ "_test_failure") + ~title:"Test failure" + ~description:"Test failure." + ~pp:(fun ppf e -> Format.fprintf ppf "Test failure: %s" e) + (obj1 (req "error" string)) + (function Test_failure e -> Some e | _ -> None) + (fun e -> Test_failure e) + +let mk_cryptobox dal_params = + let open Result_syntax in + let () = Cryptobox.Internal_for_tests.init_prover_dal () in + match Cryptobox.make dal_params with + | Ok dal -> return dal + | Error (`Fail s) -> fail [Test_failure s] + +let derive_dal_parameters (reference : Cryptobox.parameters) ~redundancy_factor + ~constants_divider = + { + S.redundancy_factor; + page_size = reference.page_size / constants_divider; + slot_size = reference.slot_size / constants_divider; + number_of_shards = reference.number_of_shards / constants_divider; + } + +let content_slot_id = function + | Hist.Internal_for_tests.Unattested id | Attested {id; _} -> id + +module Make (Parameters : sig + val dal_parameters : Alpha_context.Constants.Parametric.dal + + val cryptobox : Cryptobox.t Lazy.t +end) = +struct + (* Some global constants. *) + + let params = Parameters.dal_parameters.cryptobox_parameters + + let cryptobox = Parameters.cryptobox + + let genesis_history = Hist.genesis + + let genesis_history_cache = Hist.History_cache.empty ~capacity:3000L + + let level_one = Raw_level_repr.(succ root) + + let level_ten = Raw_level_repr.(of_int32_exn 10l) + + (* Helper functions. *) + + let get_history cache h = + Hist.History_cache.(Map.find h (view cache)) |> Lwt.return + + let dal_mk_polynomial_from_slot slot_data = + let open Result_syntax in + let cryptobox = Lazy.force cryptobox in + match Cryptobox.polynomial_from_slot cryptobox slot_data with + | Ok p -> return p + | Error (`Slot_wrong_size s) -> + fail + [ + Test_failure + (Format.sprintf "polynomial_from_slot: Slot_wrong_size (%s)" s); + ] + + let dal_commit cryptobox polynomial = + let open Result_syntax in + match Cryptobox.commit cryptobox polynomial with + | Ok cm -> return cm + | Error + ((`Invalid_degree_strictly_less_than_expected _ | `Prover_SRS_not_loaded) + as commit_error) -> + fail [Test_failure (Cryptobox.string_of_commit_error commit_error)] + + let dal_mk_prove_page polynomial page_id = + let open Result_syntax in + let cryptobox = Lazy.force cryptobox in + match Cryptobox.prove_page cryptobox polynomial page_id.P.page_index with + | Ok p -> return p + | Error `Page_index_out_of_range -> + fail [Test_failure "compute_proof_segment: Page_index_out_of_range"] + | Error + ((`Invalid_degree_strictly_less_than_expected _ | `Prover_SRS_not_loaded) + as commit_error) -> + fail [Test_failure (Cryptobox.string_of_commit_error commit_error)] + + let mk_slot ?(level = level_one) ?(index = Slot_index.zero) + ?(fill_function = fun _i -> 'x') () = + let open Result_syntax in + let slot_data = Bytes.init params.slot_size fill_function in + let* polynomial = dal_mk_polynomial_from_slot slot_data in + let cryptobox = Lazy.force cryptobox in + let* commitment = dal_commit cryptobox polynomial in + return + ( slot_data, + polynomial, + S.Header.{id = {published_level = level; index}; commitment} ) + + let mk_page_id published_level slot_index page_index = + P.{slot_id = {published_level; index = slot_index}; page_index} + + let no_data = Some (fun ~default_char:_ _ -> None) + + let mk_page_info ?(default_char = 'x') ?level ?slot_index + ?(page_index = P.Index.zero) ?(custom_data = None) (slot : S.Header.t) + polynomial = + let open Result_syntax in + let level = + match level with None -> slot.id.published_level | Some level -> level + in + let slot_index = + match slot_index with None -> slot.id.index | Some index -> index + in + let page_id = mk_page_id level slot_index page_index in + let* page_proof = dal_mk_prove_page polynomial page_id in + match custom_data with + | None -> + let page_data = Bytes.make params.page_size default_char in + return (Some (page_data, page_proof), page_id) + | Some mk_data -> ( + match mk_data ~default_char params.page_size with + | None -> return (None, page_id) + | Some page_data -> return (Some (page_data, page_proof), page_id)) + + let succ_slot_index index = + Option.value_f + Slot_index.( + of_int_opt + ~number_of_slots:Parameters.dal_parameters.number_of_slots + (to_int index + 1)) + ~default:(fun () -> Slot_index.zero) + + let next_char c = Char.(chr ((code c + 1) mod 255)) + + (** Auxiliary test function used by both unit and PBT tests: This function + produces a proof from the given information and verifies the produced result, + if any. The result of each step is checked with [check_produce_result] and + [check_verify_result], respectively. *) + let produce_and_verify_proof ~check_produce ?check_verify ~get_history + skip_list ~page_info ~page_id = + let open Lwt_result_wrap_syntax in + let*!@ res = + Hist.produce_proof params ~page_info page_id ~get_history skip_list + in + let* () = check_produce res page_info in + match check_verify with + | None -> return_unit + | Some check_verify -> + let*? proof, _input_opt = res in + let@ res = Hist.verify_proof params page_id skip_list proof in + check_verify res page_info + + (* Some check functions. *) + + (** Check that/if the returned content is the expected one. *) + let assert_content_is ~__LOC__ ~expected returned = + Assert.equal + ~loc:__LOC__ + (Option.equal Bytes.equal) + "Returned %s doesn't match the expected one" + (fun fmt opt -> + match opt with + | None -> Format.fprintf fmt "" + | Some bs -> Format.fprintf fmt "" (Bytes.to_string bs)) + returned + expected + + let expected_data page_info proof_status = + match (page_info, proof_status) with + | Some (d, _p), `Confirmed -> Some d + | None, `Confirmed -> assert false + | _ -> None + + let proof_status_to_string = function + | `Confirmed -> "CONFIRMED" + | `Unconfirmed -> "UNCONFIRMED" + + let successful_check_produce_result ~__LOC__ proof_status res page_info = + let open Lwt_result_syntax in + let* proof, input_opt = Assert.get_ok ~__LOC__ res in + let* () = + if Hist.Internal_for_tests.proof_statement_is proof proof_status then + return_unit + else + failwith + "Expected to have a %s page proof. Got %a@." + (proof_status_to_string proof_status) + (Hist.pp_proof ~serialized:false) + proof + in + assert_content_is + ~__LOC__ + input_opt + ~expected:(expected_data page_info proof_status) + + let failing_check_produce_result ~__LOC__ ~expected_error res _page_info = + Assert.proto_error ~loc:__LOC__ res (fun e -> + match (e, expected_error) with + | Hist.Dal_proof_error s, Hist.Dal_proof_error expected -> + String.equal s expected + | ( Hist.Unexpected_page_size {expected_size = e1; page_size = p1}, + Hist.Unexpected_page_size {expected_size = e2; page_size = p2} ) -> + e1 = e2 && p1 = p2 + | _ -> false) + + let successful_check_verify_result ~__LOC__ proof_status res page_info = + let open Lwt_result_syntax in + let* content = Assert.get_ok ~__LOC__ res in + let expected = expected_data page_info proof_status in + assert_content_is ~__LOC__ ~expected content + + (** Checks if the two provided Page.proof are equal. *) + let eq_page_proof = + let bytes_opt_of_proof page_proof = + Data_encoding.Binary.to_bytes_opt P.proof_encoding page_proof + in + fun pp1 pp2 -> + Option.equal Bytes.equal (bytes_opt_of_proof pp1) (bytes_opt_of_proof pp2) + + let slot_confirmed_but_page_data_not_provided ~__LOC__ = + failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Dal_proof_error + "The page ID's slot is confirmed, but no page content and proof are \ + provided.") + + let slot_not_confirmed_but_page_data_provided ~__LOC__ = + failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Dal_proof_error + "The page ID's slot is not confirmed, but page content and proof \ + are provided.") + + let bad_history_cache ~__LOC__ = + failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Dal_proof_error + "Skip_list.search returned Nearest', while all given levels to \ + produce proofs are supposed to be in the skip list.") +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.mli new file mode 100644 index 000000000000..649920b8aeae --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/dal_helpers.mli @@ -0,0 +1,188 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Returns an object of type {!Cryptobox.t} from the given DAL paramters. *) +val mk_cryptobox : Cryptobox.parameters -> Cryptobox.t tzresult + +(** Derive new DAL parameters from the given ones by: + - setting the given redundancy factor ; + - dividing the other fields by the given factor. +*) +val derive_dal_parameters : + Cryptobox.parameters -> + redundancy_factor:int -> + constants_divider:int -> + Cryptobox.parameters + +(** Returns the slot id of the given cell's content . *) +val content_slot_id : + Dal_slot_repr.History.Internal_for_tests.cell_content -> + Dal_slot_repr.Header.id + +module Make (P : sig + val dal_parameters : Alpha_context.Constants.Parametric.dal + + val cryptobox : Cryptobox.t Lazy.t +end) : sig + (** Some global constants. *) + + val genesis_history : Dal_slot_repr.History.t + + val genesis_history_cache : Dal_slot_repr.History.History_cache.t + + val level_one : Raw_level_repr.t + + val level_ten : Raw_level_repr.t + + (** Helper functions. *) + + (** Retrieves the history from a given cache. *) + val get_history : + Dal_slot_repr.History.History_cache.t -> + Dal_slot_repr.History.hash -> + Dal_slot_repr.History.t option Lwt.t + + (** Returns the slot's polynomial from the given slot's data. *) + val dal_mk_polynomial_from_slot : bytes -> Cryptobox.polynomial tzresult + + (* Commits to the given polynomial. *) + val dal_commit : + Cryptobox.t -> + Cryptobox.polynomial -> + (Cryptobox.commitment, error trace) result + + (** Using the given slot's polynomial, this function computes the page proof of + the page whose ID is provided. *) + val dal_mk_prove_page : + Cryptobox.polynomial -> + Dal_slot_repr.Page.t -> + Cryptobox.page_proof tzresult + + (** Constructs a slot whose ID is defined from the given level and given + index, and whose data are built using the given fill function. The function + returns the slot's data, polynomial, and header (in the sense: ID + kate + commitment). *) + val mk_slot : + ?level:Raw_level_repr.t -> + ?index:Dal_slot_index_repr.t -> + ?fill_function:(int -> char) -> + unit -> + (bytes * Cryptobox.polynomial * Dal_slot_repr.Header.t) tzresult + + (** Constructs a record value of type Page.id. *) + val mk_page_id : + Raw_level_repr.t -> Dal_slot_index_repr.t -> int -> Dal_slot_repr.Page.t + + val no_data : (default_char:char -> int -> bytes option) option + + (** Constructs a page whose level and slot indexes are those of the given slot + (except if level is redefined via [?level]), and whose page index and data + are given by arguments [page_index] and [mk_data]. If [mk_data] is set to + [No], the function returns the pair (None, page_id). Otherwise, the page's + [data] and [proof] is computed, and the function returns [Some (data, + proof), page_id]. *) + val mk_page_info : + ?default_char:char -> + ?level:Raw_level_repr.t -> + ?slot_index:Dal_slot_index_repr.t -> + ?page_index:int -> + ?custom_data:(default_char:char -> int -> bytes option) option -> + Dal_slot_repr.Header.t -> + Cryptobox.polynomial -> + ( (bytes * Cryptobox.page_proof) option * Dal_slot_repr.Page.t, + error trace ) + result + + (** Returns the char after [c]. Restarts from the char whose code is 0 if [c]'s + code is 255. *) + val next_char : char -> char + + (** Increment the given slot index. Returns zero in case of overflow. *) + val succ_slot_index : Dal_slot_index_repr.t -> Dal_slot_index_repr.t + + (** Auxiliary test function used by both unit and PBT tests: This function + produces a proof from the given information and verifies the produced + result, if any. The result of each step is checked with + [check_produce_result] and [check_verify_result], respectively. *) + val produce_and_verify_proof : + check_produce: + ((Dal_slot_repr.History.proof * bytes option) tzresult -> + (bytes * Cryptobox.page_proof) option -> + (unit, tztrace) result Lwt.t) -> + ?check_verify: + (bytes option tzresult -> + (bytes * Cryptobox.page_proof) option -> + (unit, tztrace) result Lwt.t) -> + get_history: + (Dal_slot_repr.History.hash -> Dal_slot_repr.History.t option Lwt.t) -> + Dal_slot_repr.History.t -> + page_info:(bytes * Cryptobox.page_proof) option -> + page_id:Dal_slot_repr.Page.t -> + (unit, tztrace) result Lwt.t + + (** Check if two page proofs are equal. *) + val eq_page_proof : Cryptobox.page_proof -> Cryptobox.page_proof -> bool + + (** Helper for the case where produce_proof is expected to succeed. *) + val successful_check_produce_result : + __LOC__:string -> + [`Confirmed | `Unconfirmed] -> + (Dal_slot_repr.History.proof * bytes option) tzresult -> + (bytes * 'a) option -> + (unit, tztrace) result Lwt.t + + (** Helper for the case where verify_proof is expected to succeed. *) + val successful_check_verify_result : + __LOC__:string -> + [> `Confirmed] -> + bytes option tzresult -> + (bytes * 'a) option -> + (unit, tztrace) result Lwt.t + + (** Helper for the case where produce_proof is expected to fail because the slot + is confirmed but no page information are provided. *) + val slot_confirmed_but_page_data_not_provided : + __LOC__:string -> 'a tzresult -> 'b -> unit tzresult Lwt.t + + (** Helper for the case where produce_proof is expected to fail because the slot + is not confirmed but page_info are provided. *) + val slot_not_confirmed_but_page_data_provided : + __LOC__:string -> 'a tzresult -> 'b -> unit tzresult Lwt.t + + (** Helper for the case where produce_proof is expected to fail. *) + val failing_check_produce_result : + __LOC__:string -> + expected_error:Environment.Error_monad.error -> + 'a tzresult -> + 'b -> + unit tzresult Lwt.t + + (** Helper for the case where produce_proof is expected to fail because some + cells are missing in the history cache. *) + val bad_history_cache : + __LOC__:string -> 'a tzresult -> 'b -> unit tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/dummy_zk_rollup.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/dummy_zk_rollup.ml new file mode 100644 index 000000000000..b473deaf56b3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/dummy_zk_rollup.ml @@ -0,0 +1,632 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Dummy ZK Rollup for testing the ZKRU integration in the protocol. + The library Plompiler is used to build the circuits (in a module V as + verifier) and the corresponding functions to produce the inputs for the + circuits (in a module P as prover). + + The state of this rollup is a boolean value, which will be + represented with a scalar value of [zero] for [false] and + [one] for [true]. + + This RU has only one operation, with [op_code] 0. In addition to the + common header (see {!Zk_rollup_operation_repr}), this operation has + as payload one scalar representing a boolean value. + + The transition function [f] for this rollup is: + + {[ + f : operation -> state -> state + f (Op b) s = if b = s then not s else s + ]} + + That is, the state bool is flipped only if the operation's payload is + equal to the current state. + + The operation can be used publicly or in a private batch. The circuits + that describe the RU are: + - ["op"]: for a single public operation. + - ["batch-"[N]]: for a batch of [N] private operations. [N] is determined + by the [batch_size] parameter to the [Operator] functor. + - ["fee"]: the trivial fees circuit, since this RU has no concept of fees. + + NB: the "op" circuit does not add any constraints over the operation's + [exit_validity] other than it being in [{0, 1}]. This means that the dummy + rollup can be used to test deposits/withdrawals, but the rollup will not + perform any monetary bookkeeping. +*) + +open Plompiler + +(** Helper types and modules *) + +(** Empty types to represent bounds *) + +type balance + +type amount + +type fee + +type op_code + +(** Bounds required for the dummy rollup. *) +module Bound : sig + type 'a t = private Z.t + + val bound_balance : balance t + + val bound_amount : amount t + + val bound_fee : fee t + + val bound_op_code : op_code t + + val v : 'a t -> Z.t +end = struct + type 'a t = Z.t + + (** These bounds are exclusive. *) + + (** Upper bound for ticket balance, as found in the price field of an + operation's header *) + let bound_balance = Z.(shift_left one 20) + + (** Upper bound for ticket amount, used for fee circuit *) + let bound_amount = Z.(shift_left one 20) + + (** Upper bound for fee amount of one public operation *) + let bound_fee = Z.(shift_left one 10) + + (** Upper bound for op code *) + let bound_op_code = Z.one + + let v x = x +end + +(** Modules to manipulate bounded integers, both as OCaml values and in circuit + representation. +*) +module Bounded = Bounded.Make (Bound) + +(** Types used for the Dummy Rollup circuits. + This module is split into: + - P: concrete OCaml version of the types, + - V: Plompiler's circuit representation for P's types, and + - Encodings: conversion between P and V. +*) +module Types = struct + module P = struct + type state = bool + + module Bounded = Bounded.P + + type 'a ticket = {id : S.t; amount : 'a Bounded.t} + + type tezos_pkh = Environment.Signature.Public_key_hash.t + + type header = { + op_code : op_code Bounded.t; + price : balance ticket; + l1_dst : tezos_pkh; + rollup_id : tezos_pkh; + } + + type op = {header : header; payload : bool} + + (** Dummy values for these types. Useful to get the circuit without having + the actual inputs. *) + module Dummy = struct + let op_code = Bounded.make ~bound:Bound.bound_op_code Z.zero + + let balance = Bounded.make ~bound:Bound.bound_balance Z.zero + + let tezos_pkh = Environment.Signature.Public_key_hash.zero + + let ticket_balance = {id = S.zero; amount = balance} + + let header = + { + op_code; + price = ticket_balance; + l1_dst = tezos_pkh; + rollup_id = tezos_pkh; + } + end + end + + module V (L : LIB) = struct + open L + module Bounded_u = Bounded.V (L) + + type 'a ticket_u = {id : scalar repr; amount : 'a Bounded_u.t} + + type tezos_pkh_u = scalar repr + + type header_u = { + op_code : op_code Bounded_u.t; + price : balance ticket_u; + l1_dst : tezos_pkh_u; + rollup_id : tezos_pkh_u; + } + + type op_u = {header : header_u; payload : bool repr} + end + + module Encodings (L : LIB) = struct + module Bounded_e = Bounded.Encoding (L) + open P + + open V (L) + + open L.Encodings + + let op_code_encoding ~safety = + Bounded_e.encoding ~safety Bound.bound_op_code + + let encoding_to_scalar e x = + let bs = Data_encoding.Binary.to_bytes_exn e x in + let z = Z.of_bits @@ Bytes.to_string bs in + Bls12_381.Fr.of_z z + + let encoding_of_scalar e x = + let z = Bls12_381.Fr.to_z x in + let bs = Bytes.of_string @@ Z.to_bits z in + Data_encoding.Binary.of_bytes_exn e bs + + let tezos_pkh_encoding : (tezos_pkh, tezos_pkh_u, _) encoding = + conv + (fun pkhu -> pkhu) + (fun w -> w) + (encoding_to_scalar Signature.Public_key_hash.encoding) + (encoding_of_scalar Signature.Public_key_hash.encoding) + scalar_encoding + + let amount_encoding ~safety = Bounded_e.encoding ~safety Bound.bound_amount + + let fee_encoding ~safety = Bounded_e.encoding ~safety Bound.bound_fee + + let ticket_encoding ~safety (bound : 'a Bound.t) : + ('a ticket, 'a ticket_u, _) encoding = + conv + (fun {id; amount} -> (id, amount)) + (fun (id, amount) -> {id; amount}) + (fun ({id; amount} : 'a ticket) -> (id, amount)) + (fun (id, amount) -> {id; amount}) + (obj2_encoding scalar_encoding (Bounded_e.encoding ~safety bound)) + + let ticket_balance_encoding ~safety = + ticket_encoding ~safety Bound.bound_balance + + let header_encoding ~safety : (header, header_u, _) encoding = + conv + (fun {op_code; price; l1_dst; rollup_id} -> + (op_code, (price, (l1_dst, rollup_id)))) + (fun (op_code, (price, (l1_dst, rollup_id))) -> + {op_code; price; l1_dst; rollup_id}) + (fun ({op_code; price; l1_dst; rollup_id} : header) -> + (op_code, (price, (l1_dst, rollup_id)))) + (fun (op_code, (price, (l1_dst, rollup_id))) -> + {op_code; price; l1_dst; rollup_id}) + (obj4_encoding + (op_code_encoding ~safety) + (* We use an Unsafe Bounded scalar encoding here to be able to + detect that an out-of-range value has been passed. + This encoding is unsafe in the sense that such value will cause + a failure in proving, instead of a circuit that can prove that + the argument is out-of-range. + This is enough for Protocol testing purposes, while keeping + the dummy circuit small. + *) + (ticket_balance_encoding ~safety:Unsafe) + tezos_pkh_encoding + tezos_pkh_encoding) + + let op_encoding : (op, op_u, _) encoding = + conv + (fun {header; payload} -> (header, payload)) + (fun (header, payload) -> {header; payload}) + (fun ({header; payload} : op) -> (header, payload)) + (fun (header, payload) -> {header; payload}) + (obj2_encoding (header_encoding ~safety:NoCheck) bool_encoding) + end +end + +(** Plompiler circuits for the dummy rollup *) +module V (L : LIB) = struct + open L + module E = Types.Encodings (L) + module Encodings = L.Encodings + open Encodings + + open Types.V (L) + + let coerce (type a) (x : a Bounded_u.t) = + fst (x : a Bounded_u.t :> scalar repr * Z.t) + + (** Common logic for the state transition function *) + let logic_op ~old_state ~rollup_id op = + ignore rollup_id ; + let* valid = equal old_state op.payload in + let* new_state = Bool.bnot old_state in + let* expected_new_state = Bool.ifthenelse valid new_state old_state in + Num.assert_eq_const (coerce op.header.op_code) S.zero + (* >* assert_equal rollup_id op.header.rollup_id *) + >* ret expected_new_state + + (** Circuit definition for one public operation *) + let predicate_op ?(kind = `Public) ~old_state ~new_state ~fee ~exit_validity + ~rollup_id op = + let* old_state = input ~kind:`Public @@ Input.bool old_state in + let* new_state = input ~kind:`Public @@ Input.bool new_state in + let* (_fee : scalar repr) = + input ~kind:`Public + @@ E.((fee_encoding ~safety:Bounded_e.Unsafe).input) fee + in + let* (_exit_validity : bool repr) = + input ~kind:`Public @@ Input.bool exit_validity + in + let* rollup_id = + input ~kind:`Public @@ E.(tezos_pkh_encoding.input) rollup_id + in + let* op = input ~kind @@ E.op_encoding.input op in + let op = E.op_encoding.decode op in + let* expected_new_state = logic_op ~old_state ~rollup_id op in + assert_equal expected_new_state new_state + + (** Circuit definition for a batch of private operations *) + let predicate_batch ~old_state ~new_state ~fees ~rollup_id ops = + let* old_state = input ~kind:`Public @@ Input.bool old_state in + let* new_state = input ~kind:`Public @@ Input.bool new_state in + let* (_fees : scalar repr) = + input ~kind:`Public + @@ E.((amount_encoding ~safety:Bounded_e.Unsafe).input) fees + in + let* rollup_id = + input ~kind:`Public @@ E.(tezos_pkh_encoding.input) rollup_id + in + let* ops = input @@ (Encodings.list_encoding E.op_encoding).input ops in + let ops = (Encodings.list_encoding E.op_encoding).decode ops in + let* computed_final_state = + foldM + (fun old_state op -> logic_op ~old_state ~rollup_id op) + old_state + ops + in + assert_equal computed_final_state new_state + + (** Fee circuit *) + let predicate_fees ~old_state ~new_state ~fees = + let* old_state = input ~kind:`Public @@ Input.bool old_state in + let* new_state = input ~kind:`Public @@ Input.bool new_state in + let* (_fees : scalar repr) = + input ~kind:`Public + @@ E.((amount_encoding ~safety:Bounded_e.Unsafe).input) fees + in + assert_equal old_state new_state +end + +(** Basic rollup operator for generating Updates. *) +module Operator (Params : sig + val batch_size : int +end) : sig + open Protocol.Alpha_context + + (** Initial state of the rollup *) + val init_state : Zk_rollup.State.t + + (** Map associating every circuit identifier to its kind *) + val circuits : [`Public | `Private | `Fee] Kzg.SMap.t + + (** Commitment to the circuits *) + val lazy_pp : + (Plonk.Main_protocol.prover_public_parameters + * Plonk.Main_protocol.verifier_public_parameters) + lazy_t + + (** [craft_update state ~zk_rollup ?private_ops ?exit_validities public_ops] + will apply first the [public_ops], then the [private_ops]. While doing so, + the public inputs for every circuit will be collected. A Plonk proof of + correctness of the application these operations is created. *) + val craft_update : + Zk_rollup.State.t -> + zk_rollup:Zk_rollup.t -> + ?private_ops:Zk_rollup.Operation.t list list -> + ?exit_validities:bool list -> + Zk_rollup.Operation.t list -> + Zk_rollup.State.t * Zk_rollup.Update.t + + module Internal_for_tests : sig + val true_op : Zk_rollup.Operation.t + + val false_op : Zk_rollup.Operation.t + + val pending : Zk_rollup.Operation.t list + + val private_ops : Zk_rollup.Operation.t list list + + val lazy_update_data : Zk_rollup.Update.t lazy_t + end +end = struct + open Protocol.Alpha_context + module SMap = Kzg.SMap + module Dummy = Types.P.Dummy + module T = Types.P + module VC = V (LibCircuit) + + let lazy_srs = + lazy + (let open Octez_bls12_381_polynomial in + (Srs.generate_insecure 9 1, Srs.generate_insecure 1 1)) + + let dummy_l1_dst = + Hex.to_bytes_exn (`Hex "0002298c03ed7d454a101eb7022bc95f7e5f41ac78") + + let dummy_rollup_id = + let address = + Zk_rollup.Address.of_b58check_exn "epx18RJJqrYuJQqhB636BWvukU3XBNQGbtm8C" + in + Data_encoding.Binary.to_bytes_exn Zk_rollup.Address.encoding address + + let dummy_ticket_hash = Bytes.make 32 '0' + + let of_proto_state : Zk_rollup.State.t -> Types.P.state = + fun s -> Bls12_381.Fr.is_one s.(0) + + let to_proto_state : Types.P.state -> Zk_rollup.State.t = + fun s -> if s then [|Bls12_381.Fr.one|] else [|Bls12_381.Fr.zero|] + + let dummy_op = T.{header = Dummy.header; payload = false} + + let batch_name = "batch-" ^ string_of_int Params.batch_size + + (* Circuits that define the rollup, alongside their public input size and + solver *) + let circuit_map = + let get_circuit _name c = + let r = LibCircuit.get_cs ~optimize:true c in + (Plonk.Circuit.to_plonk r, r.public_input_size, r.solver) + in + SMap.of_list + @@ List.map + (fun (n, c) -> (n, get_circuit n c)) + [ + ( "op", + VC.predicate_op + ~old_state:false + ~new_state:true + ~fee:(T.Bounded.make ~bound:Bound.bound_fee Z.zero) + ~exit_validity:false + ~rollup_id:Dummy.tezos_pkh + dummy_op ); + ( batch_name, + VC.predicate_batch + ~old_state:false + ~new_state:true + ~fees:(T.Bounded.make ~bound:Bound.bound_amount Z.zero) + ~rollup_id:Dummy.tezos_pkh + (Stdlib.List.init Params.batch_size (Fun.const dummy_op)) ); + ( "fee", + VC.predicate_fees + ~old_state:false + ~new_state:false + ~fees:(T.Bounded.make ~bound:Bound.bound_amount Z.zero) ); + ] + + let circuits = + SMap.(add "op" `Public @@ add batch_name `Private @@ add "fee" `Fee empty) + + let lazy_pp = + lazy + (let srs = Lazy.force lazy_srs in + Plonk.Main_protocol.setup + ~zero_knowledge:false + (SMap.map (fun (a, b, _) -> (a, b)) circuit_map) + ~srs) + + let insert s x m = + match SMap.find_opt s m with + | None -> SMap.add s [x] m + | Some l -> SMap.add s (x :: l) m + + let craft_update : + Zk_rollup.State.t -> + zk_rollup:Zk_rollup.t -> + ?private_ops:Zk_rollup.Operation.t list list -> + ?exit_validities:bool list -> + Zk_rollup.Operation.t list -> + Zk_rollup.State.t * Zk_rollup.Update.t = + fun s ~zk_rollup ?(private_ops = []) ?exit_validities pending -> + let prover_pp, public_parameters = Lazy.force lazy_pp in + let s = of_proto_state s in + let rev_inputs = SMap.empty in + let exit_validities = + match exit_validities with + | None -> List.map (Fun.const true) pending + | Some l -> + assert (List.length l = List.length pending) ; + l + in + let _circ, _pi_size, op_solver = SMap.find "op" circuit_map in + (* Process the public operations *) + let s, rev_inputs, rev_pending_pis = + Stdlib.List.fold_left2 + (fun (s, rev_inputs, rev_pending_pis) op exit_validity -> + let new_state = + if s = of_proto_state Zk_rollup.Operation.(op.payload) then not s + else s + in + let fee = Bls12_381.Fr.zero in + let pi_to_send = + Zk_rollup.Update. + {new_state = to_proto_state new_state; fee; exit_validity} + in + let exit_validity_s = + if exit_validity then Bls12_381.Fr.one else Bls12_381.Fr.zero + in + let public_inputs = + Array.concat + [ + to_proto_state s; + to_proto_state new_state; + [|fee; exit_validity_s; Zk_rollup.to_scalar zk_rollup|]; + Zk_rollup.Operation.to_scalar_array op; + ] + in + let private_inputs = Solver.solve op_solver public_inputs in + ( new_state, + insert + "op" + Plonk.Main_protocol. + {witness = private_inputs; input_commitments = []} + rev_inputs, + ("op", pi_to_send) :: rev_pending_pis )) + (s, rev_inputs, []) + pending + exit_validities + in + let pending_pis = List.rev rev_pending_pis in + + let _circ, _pi_size, batch_solver = SMap.find batch_name circuit_map in + (* Process the private operation batches *) + let s, rev_inputs, rev_private_pis = + if private_ops = [] then (s, rev_inputs, []) + else + List.fold_left + (fun (s, rev_inputs, rev_private_pis) batch -> + let new_state = + List.fold_left + (fun s op -> + if s = of_proto_state Zk_rollup.Operation.(op.payload) then + not s + else s) + s + batch + in + let fees = Bls12_381.Fr.zero in + let pi_to_send : Zk_rollup.Update.private_inner_pi = + Zk_rollup.Update.{new_state = to_proto_state new_state; fees} + in + let public_inputs = + Array.concat + [ + to_proto_state s; + to_proto_state new_state; + [|fees; Zk_rollup.to_scalar zk_rollup|]; + ] + in + let initial = + Array.concat + ([public_inputs] + @ List.map Zk_rollup.Operation.to_scalar_array batch) + in + let private_inputs = Solver.solve batch_solver initial in + ( new_state, + insert + batch_name + Plonk.Main_protocol. + {witness = private_inputs; input_commitments = []} + rev_inputs, + (batch_name, pi_to_send) :: rev_private_pis )) + (s, rev_inputs, []) + private_ops + in + let private_pis = List.rev rev_private_pis in + (* Dummy fee circuit *) + let _circ, _pi_size, fee_solver = SMap.find "fee" circuit_map in + let rev_inputs, fee_pi = + let fee_pi = Zk_rollup.Update.{new_state = to_proto_state s} in + let fees = Bls12_381.Fr.zero in + + let public_inputs = + Array.concat [to_proto_state s; to_proto_state s; [|fees|]] + in + let private_inputs = Solver.solve fee_solver public_inputs in + ( insert + "fee" + Plonk.Main_protocol.{witness = private_inputs; input_commitments = []} + rev_inputs, + fee_pi ) + in + let inputs = SMap.map List.rev rev_inputs in + let proof = Plonk.Main_protocol.prove prover_pp ~inputs in + let verifier_inputs = + Plonk.Main_protocol.to_verifier_inputs prover_pp inputs + in + assert ( + Plonk.Main_protocol.verify public_parameters ~inputs:verifier_inputs proof) ; + ( to_proto_state s, + Zk_rollup.Update.{pending_pis; private_pis; fee_pi; proof} ) + + let init_state = to_proto_state false + + module Internal_for_tests = struct + let true_op = + Zk_rollup.Operation. + { + op_code = 0; + price = + (let id = + Data_encoding.Binary.of_bytes_exn + Ticket_hash.encoding + dummy_ticket_hash + in + {id; amount = Z.zero}); + l1_dst = + Data_encoding.Binary.of_bytes_exn + Signature.Public_key_hash.encoding + dummy_l1_dst; + rollup_id = + Data_encoding.Binary.of_bytes_exn + Zk_rollup.Address.encoding + dummy_rollup_id; + payload = [|Bls12_381.Fr.one|]; + } + + let false_op = {true_op with payload = [|Bls12_381.Fr.zero|]} + + let pending = [false_op; true_op; true_op] + + let n_batches = 2 + + let private_ops = + Stdlib.List.init n_batches @@ Fun.const + @@ Stdlib.List.init Params.batch_size (fun i -> + if i mod 2 = 0 then false_op else true_op) + + let lazy_update_data = + lazy + (snd + @@ craft_update + init_state + ~zk_rollup: + (Data_encoding.Binary.of_bytes_exn + Zk_rollup.Address.encoding + dummy_rollup_id) + ~private_ops + pending) + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/dune b/src/proto_020_PsParisC/lib_protocol/test/helpers/dune new file mode 100644 index 000000000000..6167b19c955f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/dune @@ -0,0 +1,42 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_019_PtParisB_test_helpers) + (public_name octez-protocol-019-PtParisB-libs.test-helpers) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-alcotezt + tezt + octez-libs.base-test-helpers + qcheck-alcotest + octez-libs.test-helpers + octez-libs.base + octez-libs.micheline + octez-libs.stdlib-unix + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.parameters + octez-proto-libs.protocol-environment + octez-protocol-019-PtParisB-libs.plugin + octez-shell-libs.shell-services + octez-libs.plompiler + octez-libs.crypto-dal + octez-protocol-019-PtParisB-libs.smart-rollup) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base_test_helpers + -open Tezos_base.TzPervasives + -open Tezos_micheline + -open Tezos_stdlib_unix + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_shell_services + -open Tezos_crypto_dal + -open Tezos_smart_rollup_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/expr.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/expr.ml new file mode 100644 index 000000000000..468d09535ae8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/expr.ml @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +exception Expression_from_string + +(** Parse a Michelson expression from string, raising an exception on error. *) +let from_string ?(check_micheline_indentation = false) str : Script.expr = + let ast, errs = + Michelson_v1_parser.parse_expression ~check:check_micheline_indentation str + in + (match errs with + | [] -> () + | lst -> + Format.printf "expr_from_string: %a\n" Error_monad.pp_print_trace lst ; + raise Expression_from_string) ; + ast.expanded + +(** Parses a Michelson contract from string, raising an exception on error. *) +let toplevel_from_string ?(check_micheline_indentation = false) str = + let ast, errs = + Michelson_v1_parser.parse_toplevel ~check:check_micheline_indentation str + in + match errs with [] -> ast.expanded | _ -> Stdlib.failwith "parse toplevel" + +let to_string c = Format.asprintf "%a" Michelson_v1_printer.print_expr c diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/expr_common.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/expr_common.ml new file mode 100644 index 000000000000..554bba47ce07 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/expr_common.ml @@ -0,0 +1,98 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(* From OCaml values to Micheline expressions *) + +let seq ?(loc = 0) l = Tezos_micheline.Micheline.Seq (loc, l) + +let pair ?(loc = 0) a b = + Tezos_micheline.Micheline.Prim (loc, Script.D_Pair, [a; b], []) + +let pair_n ?(loc = 0) els = + Tezos_micheline.Micheline.Prim (loc, Script.D_Pair, els, []) + +let comb ?(loc = 0) es = + Tezos_micheline.Micheline.Prim (loc, Script.D_Pair, es, []) + +let none ?(loc = 0) () = + Tezos_micheline.Micheline.Prim (loc, Script.D_None, [], []) + +let some ?(loc = 0) a = + Tezos_micheline.Micheline.Prim (loc, Script.D_Some, [a], []) + +let left ?(loc = 0) a = + Tezos_micheline.Micheline.Prim (loc, Script.D_Left, [a], []) + +let right ?(loc = 0) b = + Tezos_micheline.Micheline.Prim (loc, Script.D_Right, [b], []) + +let unit ?(loc = 0) () = + Tezos_micheline.Micheline.Prim (loc, Script.D_Unit, [], []) + +let int ?(loc = 0) i = Tezos_micheline.Micheline.Int (loc, i) + +let bytes ?(loc = 0) s = Tezos_micheline.Micheline.Bytes (loc, s) + +let string ?(loc = 0) s = Tezos_micheline.Micheline.String (loc, s) + +let mutez ?(loc = 0) m = int ~loc (Z.of_int64 (Tez.to_mutez m)) + +(* Translate a timestamp to a Micheline expression in optimized + form *) +let timestamp ?(loc = 0) ts = int ~loc (Script_timestamp.to_zint ts) + +let address ?(loc = 0) adr = + bytes ~loc @@ Data_encoding.Binary.to_bytes_exn Contract.encoding adr + +let address_string ?(loc = 0) adr = string ~loc @@ Contract.to_b58check adr + +let big_map_id ?(loc = 0) id = int ~loc @@ Big_map.Id.unparse_to_z id + +(* From Micheline expressions to OCaml values *) + +let timestamp_of_zint zint = Script_timestamp.of_zint zint + +let public_key_of_bytes_exn b = + Data_encoding.Binary.of_bytes_exn Signature.Public_key.encoding b + +let address_of_bytes_exn b = + Data_encoding.Binary.of_bytes_exn Contract.encoding b + +type exn += Invalid_address_expr of string + +let address_of_string_exn s = + match Contract.of_b58check s with + | Ok c -> c + | Error _ -> raise @@ Invalid_address_expr s + +let originated_of_string_exn s = + match address_of_string_exn s with + | Contract.Originated addr -> addr + | Contract.Implicit _ -> + invalid_arg + "Expected originated contract address, got implicit contract address" diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.ml new file mode 100644 index 000000000000..decfedcbf6da --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.ml @@ -0,0 +1,311 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +module Proto_Nonce = Nonce (* Renamed otherwise is masked by Alpha_context *) +open Alpha_context + +type t = { + predecessor : Block.t; + state : validation_state * application_state; + rev_operations : Operation.packed list; + rev_tickets : operation_receipt list; + header : Block_header.t; + delegate : Account.t; + constants : Constants.Parametric.t; +} + +type incremental = t + +let predecessor {predecessor; _} = predecessor + +let header {header; _} = header + +let rev_tickets {rev_tickets; _} = rev_tickets + +let validation_state {state = vs, _; _} = vs + +let level st = st.header.shell.level + +let alpha_ctxt {state = _, application_state; _} = application_state.ctxt + +let rpc_context st = + let fitness = (header st).shell.fitness in + let result = Alpha_context.finalize (alpha_ctxt st) fitness in + { + Environment.Updater.block_hash = Block_hash.zero; + block_header = {st.header.shell with fitness = result.fitness}; + context = result.context; + } + +let rpc_ctxt = + new Environment.proto_rpc_context_of_directory + rpc_context + Plugin.RPC.rpc_services + +let set_alpha_ctxt st ctxt = + {st with state = (fst st.state, {(snd st.state) with ctxt})} + +let begin_validation_and_application ctxt chain_id mode ~predecessor = + let open Lwt_result_syntax in + let* validation_state = begin_validation ctxt chain_id mode ~predecessor in + let* application_state = begin_application ctxt chain_id mode ~predecessor in + return (validation_state, application_state) + +let begin_construction ?timestamp ?seed_nonce_hash ?(mempool_mode = false) + ?(policy = Block.By_round 0) ?liquidity_baking_toggle_vote + ?adaptive_issuance_vote (predecessor : Block.t) = + let open Lwt_result_wrap_syntax in + let* delegate, _consensus_key, round, real_timestamp = + Block.get_next_baker ~policy predecessor + in + let* delegate = Account.find delegate in + let*?@ payload_round = Round.of_int round in + let timestamp = Option.value ~default:real_timestamp timestamp in + let* seed_nonce_hash = + match seed_nonce_hash with + | Some _hash -> return seed_nonce_hash + | None -> ( + let+ level = + Plugin.RPC.current_level ~offset:1l Block.rpc_ctxt predecessor + in + match level with + | {expected_commitment = true; _} -> + Some (fst (Proto_Nonce.generate ())) + | {expected_commitment = false; _} -> None) + in + let shell : Block_header.shell_header = + { + predecessor = predecessor.hash; + proto_level = predecessor.header.shell.proto_level; + validation_passes = predecessor.header.shell.validation_passes; + fitness = predecessor.header.shell.fitness; + timestamp; + level = predecessor.header.shell.level; + context = Context_hash.zero; + operations_hash = Operation_list_list_hash.zero; + } + in + let* contents = + Block.Forge.contents + ?seed_nonce_hash + ?adaptive_issuance_vote + ?liquidity_baking_toggle_vote + ~payload_hash:Block_payload_hash.zero + ~payload_round + shell + in + let mode = + if mempool_mode then + Partial_construction {predecessor_hash = predecessor.hash; timestamp} + else + let block_header_data = + {Block_header.contents; signature = Signature.zero} + in + Construction + {predecessor_hash = predecessor.hash; timestamp; block_header_data} + in + let header = + {Block_header.shell; protocol_data = {contents; signature = Signature.zero}} + in + let*@ state = + begin_validation_and_application + predecessor.context + Chain_id.zero + mode + ~predecessor:predecessor.header.shell + in + return + { + predecessor; + state; + rev_operations = []; + rev_tickets = []; + header; + delegate; + constants = predecessor.constants; + } + +let detect_script_failure : + type kind. kind Apply_results.operation_metadata -> _ = + let open Result_syntax in + let rec detect_script_failure : + type kind. kind Apply_results.contents_result_list -> _ = + let open Apply_results in + let open Apply_operation_result in + let open Apply_internal_results in + let detect_script_failure_single (type kind) + (Manager_operation_result + {operation_result; internal_operation_results; _} : + kind Kind.manager Apply_results.contents_result) = + let detect_script_failure (type kind) + (result : (kind, _, _) operation_result) = + match result with + | Applied _ -> return_unit + | Skipped _ -> assert false + | Backtracked (_, None) -> + (* there must be another error for this to happen *) + return_unit + | Backtracked (_, Some errs) -> fail (Environment.wrap_tztrace errs) + | Failed (_, errs) -> fail (Environment.wrap_tztrace errs) + in + let* () = detect_script_failure operation_result in + List.iter_e + (fun (Internal_operation_result (_, r)) -> detect_script_failure r) + internal_operation_results + in + function + | Single_result (Manager_operation_result _ as res) -> + detect_script_failure_single res + | Single_result _ -> return_unit + | Cons_result (res, rest) -> + let* () = detect_script_failure_single res in + detect_script_failure rest + in + fun {contents} -> detect_script_failure contents + +let check_operation_size ?(check_size = true) op = + if check_size then + let operation_size = Data_encoding.Binary.length Operation.encoding op in + if operation_size > Constants_repr.max_operation_data_length then + raise + (invalid_arg + (Format.sprintf + "The operation size is %d: it exceeds the constant maximum size \ + %d." + operation_size + Constants_repr.max_operation_data_length)) + +let validate_operation ?expect_failure ?check_size st op = + let open Lwt_result_wrap_syntax in + check_operation_size ?check_size op ; + let validation_state, application_state = st.state in + let oph = Operation.hash_packed op in + let*!@ res = validate_operation validation_state oph op in + match (expect_failure, res) with + | Some _, Ok _ -> failwith "Error expected while validating operation" + | Some f, Error err -> + let* () = f err in + return st + | None, Error err -> fail err + | None, Ok validation_state -> + return {st with state = (validation_state, application_state)} + +let add_operation ?expect_failure ?expect_apply_failure ?allow_manager_failure + ?check_size st op = + let open Lwt_result_wrap_syntax in + let open Apply_results in + let* st = validate_operation ?expect_failure ?check_size st op in + match expect_failure with + | Some _ -> + (* The expected failure has already been observed in + [validate_operation]. *) + return st + | None -> ( + let validation_state, application_state = st.state in + let oph = Operation.hash_packed op in + let*@ application_state, metadata = + apply_operation application_state oph op + in + let st = + { + st with + state = (validation_state, application_state); + rev_operations = op :: st.rev_operations; + rev_tickets = metadata :: st.rev_tickets; + } + in + 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 = + let open Lwt_result_syntax in + let* () = finalize_validation validation_state in + finalize_application application_state shell_header + +let finalize_block st = + let open Lwt_result_wrap_syntax in + let operations = List.rev st.rev_operations in + let operations_hash = + Operation_list_list_hash.compute + [Operation_list_hash.compute (List.map Operation.hash_packed operations)] + in + let shell_header = + { + st.header.shell with + level = Int32.succ st.header.shell.level; + operations_hash; + } + in + let*@ validation_result, _ = + finalize_validation_and_application st.state (Some shell_header) + in + let operations = List.rev st.rev_operations in + let operations_hash = + Operation_list_list_hash.compute + [Operation_list_hash.compute (List.map Operation.hash_packed operations)] + in + let header = + { + st.header with + shell = + { + st.header.shell with + level = Int32.succ st.header.shell.level; + operations_hash; + fitness = validation_result.fitness; + }; + } + in + let hash = Block_header.hash header in + return + { + Block.hash; + header; + operations; + context = validation_result.context; + constants = st.constants; + } + +let assert_validate_operation_fails expect_failure op block = + let open Lwt_result_syntax in + let* i = begin_construction block in + let* (_i : incremental) = validate_operation ~expect_failure i op in + return_unit diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.mli new file mode 100644 index 000000000000..a50718801060 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/incremental.mli @@ -0,0 +1,139 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +type t + +type incremental = t + +val predecessor : incremental -> Block.t + +val header : incremental -> Block_header.t + +val rev_tickets : incremental -> operation_receipt list + +val validation_state : incremental -> validation_state + +val level : incremental -> int32 + +(** [begin_construction ?mempool_mode predecessor] uses + {!Main.begin_validation_and_application} to create a validation and + application state on top of [predecessor] for the construction of a + new block. + + Optional arguments allow to override defaults: + + {ul {li [?mempool_mode:bool]: when [true], use [Partial_construction] + mode. By default, it is [false] and the mode is [Construction].}} *) +val begin_construction : + ?timestamp:Time.Protocol.t -> + ?seed_nonce_hash:Nonce_hash.t -> + ?mempool_mode:bool -> + ?policy:Block.baker_policy -> + ?liquidity_baking_toggle_vote:Per_block_votes_repr.per_block_vote -> + ?adaptive_issuance_vote:Per_block_votes_repr.per_block_vote -> + Block.t -> + incremental tzresult Lwt.t + +(** [validate_operation ?expect_failure ?check_size i op] tries to + validate [op] in the validation state of [i]. If the validation + succeeds, the function returns the incremental value with a + validation state updated after the validate. 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 an + [expect_failure] is provided, [validate_operation] fails.} + + {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 validate_operation : + ?expect_failure:(error list -> unit tzresult Lwt.t) -> + ?check_size:bool -> + incremental -> + Operation.packed -> + incremental tzresult Lwt.t + +(** [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: + + @param expect_failure + 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. + + @param expect_apply_failure + application of [op] is expected to fail and + [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. + + @param allow_manager_failure + marks that manager operation failures after fee taken are ignored. + + @param check_size + 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 -> + incremental tzresult Lwt.t + +(** [finalize_block i] creates a [Block.t] based on the protocol + states and the operations contained in [i]. The function calls + [Main.finalize_application] to compute a new context. *) +val finalize_block : incremental -> Block.t tzresult Lwt.t + +(** [assert_validate_operation_fails expect_failure operation block] + calls {!begin_construction} on top of [block], then + {!validate_operation} with [~expect_failure]. *) +val assert_validate_operation_fails : + (tztrace -> unit tzresult Lwt.t) -> + Operation.packed -> + Block.t -> + unit tzresult Lwt.t + +val rpc_ctxt : incremental Environment.RPC_context.simple + +val alpha_ctxt : incremental -> Alpha_context.context + +val set_alpha_ctxt : incremental -> Alpha_context.context -> incremental diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.ml new file mode 100644 index 000000000000..2a81f101afae --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.ml @@ -0,0 +1,328 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Liquidity_baking_machine +open QCheck2.Gen + +let total_xtz = 32_000_000_000_000L + +let ten_subsidies = 25_000_000L + +let rec remove_last_element = function + | [_] -> [] + | x :: rst -> x :: remove_last_element rst + | [] -> raise (Invalid_argument "remove_last_element") + +(** Try to shrink a list by removing elements from the tail of said + list. + + The elements themselves are not shrinked. *) +let rec shrink_list l = + if l == [] then Seq.empty + else + let l = remove_last_element l in + Seq.cons l (shrink_list l) + +let gen_balances : int64 -> int -> int -> balances QCheck2.Gen.t = + fun max_xtz max_tzbtc max_liquidity -> + let open Tezos_test_helpers.Qcheck2_helpers in + let+ xtz = int64_strictly_positive_gen max_xtz + and+ tzbtc = int_strictly_positive_gen max_tzbtc + and+ liquidity = int_strictly_positive_gen max_liquidity in + {xtz; tzbtc; liquidity} + +let gen_specs : int -> int -> specs QCheck2.Gen.t = + fun total_tzbtc total_liquidity -> + (* 1. We pick a random number to decide how many implicit account we + will set-up in the specs. Note that there will be one more + implicit accounts, the [Holder], that we will use to reach the + expected balances for the CPMM and the implicit accounts. *) + let* accounts_numbers = int_range 10 20 in + (* 2. To keep the generator simpler, we do not try to strictly reach + the [total_tzbtc] and [total_liquidity] value, but rather we + compute maxima for the implicit accounts balances from + them. *) + (* 2.1. We divide a fraction of the [total_xtz] that we need to + share to the implicit accounts. The rationale is to provide + a large amount to xtz to [Holder], so that we do not have to + worry about it being “rich enough.” *) + let max_xtz = Int64.(div total_xtz (of_int (50 * accounts_numbers))) in + (* 2.2. We divide [total_tzbtc] between the implicit accounts *and* + the CPMM contract. *) + let max_tzbtc = total_tzbtc / (accounts_numbers + 1) in + (* 2.2. We divide [total_liquidity] between the implicit accounts only. *) + let max_liquidity = total_liquidity / accounts_numbers in + let+ cpmm_balance = gen_balances max_xtz max_tzbtc 1 + and+ accounts_balances = + list_repeat accounts_numbers (gen_balances max_xtz max_tzbtc max_liquidity) + in + { + cpmm_min_xtz_balance = cpmm_balance.xtz; + cpmm_min_tzbtc_balance = cpmm_balance.tzbtc; + accounts_balances; + } + +type 'a optgen = 'a option QCheck2.Gen.t + +let ( let*? ) (m : 'a optgen) (f : 'a -> 'b optgen) = + let* x = m in + match x with None -> return None | Some x -> f x + +(** [genopt_oneof l] tries to generate a value using the generators of + [l], one at a time. + + First, the list [l] is randomized, then each generator is + tried. The first one to return a result (not [None]) is picked. If + all generators returns [None], the generators tries again with the + whole list (at most 100 times). If no generator of [l] is able to + return a result, then [genopt_oneof l] returns [None]. *) +let genopt_oneof (l : 'a optgen list) : 'a optgen = + let* l = QCheck2.Gen.shuffle_l l in + let rec aux n = function + | [] -> if n = 0 then pure None else aux (n - 1) l + | g :: l -> ( + let* x = g in + match x with None -> aux n l | Some x -> pure @@ Some x) + in + aux 100 l + +let genopt_account ?choice ?(filter = Fun.const true) env : contract_id optgen = + let l = + List.filter + filter + (Option.fold ~none:env.implicit_accounts ~some:(fun x -> [x]) choice) + in + if l = [] then return None else map Option.some (oneofl l) + +let genopt_account_with_tzbtc ?choice ?(min = 1) env state = + genopt_account + ?choice + ~filter:(fun a -> SymbolicMachine.get_tzbtc_balance a env state >= min) + env + +let genopt_account_with_xtz ?choice ?(min = 1L) env state = + genopt_account + ?choice + ~filter:(fun a -> SymbolicMachine.get_xtz_balance a state >= min) + env + +let genopt_account_with_liquidity ?choice ?(min = 1) env state = + genopt_account + ?choice + ~filter:(fun a -> SymbolicMachine.get_liquidity_balance a env state >= min) + env + +let genopt_step_tzbtc_to_xtz : + ?source:contract_id -> + ?destination:contract_id -> + contract_id env -> + SymbolicMachine.t -> + contract_id step optgen = + fun ?source ?destination env state -> + let*? source = genopt_account_with_tzbtc ?choice:source env state in + let*? destination = genopt_account ?choice:destination env in + let+ tzbtc_deposit = + Tezos_test_helpers.Qcheck2_helpers.int_strictly_positive_gen + (SymbolicMachine.get_tzbtc_balance source env state) + in + (* See note (2) *) + if + SymbolicMachine.get_tzbtc_balance env.cpmm_contract env state + < Int.max_int - tzbtc_deposit + then Some (SellTzBTC {source; destination; tzbtc_deposit}) + else None + +let genopt_step_xtz_to_tzbtc : + ?source:contract_id -> + ?destination:contract_id -> + contract_id env -> + SymbolicMachine.t -> + contract_id step optgen = + fun ?source ?destination env state -> + let*? source = genopt_account_with_xtz ?choice:source env state in + let*? destination = genopt_account ?choice:destination env in + let+ xtz_deposit = + map + Int64.of_int + (int_range + 1 + (Int64.to_int @@ SymbolicMachine.get_xtz_balance source state)) + in + (* See note (2) *) + if + SymbolicMachine.get_xtz_balance env.cpmm_contract state + < Int64.(sub max_int (add ten_subsidies xtz_deposit)) + then Some (BuyTzBTC {source; destination; xtz_deposit}) + else None + +let genopt_step_add_liquidity : + ?source:contract_id -> + ?destination:contract_id -> + contract_id env -> + SymbolicMachine.t -> + contract_id step optgen = + fun ?source ?destination env state -> + let rec find_xtz_deposit candidate max_tzbtc_deposit = + let tzbtc_deposit = + SymbolicMachine.predict_required_tzbtc_deposit candidate env state + in + if tzbtc_deposit <= max_tzbtc_deposit then candidate + else find_xtz_deposit (Int64.div candidate 2L) max_tzbtc_deposit + in + let*? source = genopt_account_with_xtz ?choice:source env state in + let*? destination = genopt_account ?choice:destination env in + let source_xtz_pool = SymbolicMachine.get_xtz_balance source state in + (* the source needs at least one xtz *) + if 1L < source_xtz_pool then + let+ candidate = + Tezos_test_helpers.Qcheck2_helpers.int64_strictly_positive_gen + source_xtz_pool + in + let xtz_deposit = + find_xtz_deposit + candidate + (SymbolicMachine.get_tzbtc_balance source env state) + in + (* See note (2) *) + if + SymbolicMachine.get_xtz_balance env.cpmm_contract state + < Int64.(sub max_int (add ten_subsidies xtz_deposit)) + then Some (AddLiquidity {source; destination; xtz_deposit}) + else None + else pure None + +let genopt_step_remove_liquidity : + ?source:contract_id -> + ?destination:contract_id -> + contract_id env -> + SymbolicMachine.t -> + contract_id step optgen = + fun ?source ?destination env state -> + let*? source = genopt_account_with_liquidity ?choice:source env state in + let*? destination = genopt_account ?choice:destination env in + let lqt_available = SymbolicMachine.get_liquidity_balance source env state in + if 1 < lqt_available then + let+ lqt_burned = + int_range 1 (SymbolicMachine.get_liquidity_balance source env state) + in + Some (RemoveLiquidity {source; destination; lqt_burned}) + else return None + +let genopt_step : + ?source:contract_id -> + ?destination:contract_id -> + contract_id env -> + SymbolicMachine.t -> + contract_id step optgen = + fun ?source ?destination env state -> + genopt_oneof + [ + genopt_step_tzbtc_to_xtz env state ?source ?destination; + genopt_step_xtz_to_tzbtc env state ?source ?destination; + genopt_step_add_liquidity env state ?source ?destination; + genopt_step_remove_liquidity env state ?source ?destination; + ] + +let gen_steps : + ?source:contract_id -> + ?destination:contract_id -> + contract_id env -> + SymbolicMachine.t -> + int -> + contract_id step list QCheck2.Gen.t = + fun ?source ?destination env state size -> + let rec inner env state size random_state = + if size <= 0 then [] + else + let h = + QCheck2.Gen.generate1 + ~rand:random_state + (genopt_step ?source ?destination env state) + in + match h with + | None -> [] + | Some h -> + let state = SymbolicMachine.step h env state in + let rst = inner env state (size - 1) random_state in + h :: rst + in + QCheck2.Gen.make_primitive ~gen:(inner env state size) ~shrink:(fun l -> + shrink_list l) + +let gen_scenario : + tzbtc -> liquidity -> int -> (specs * contract_id step list) QCheck2.Gen.t = + fun total_tzbtc total_liquidity size -> + let* specs = gen_specs total_tzbtc total_liquidity in + let state, env = SymbolicMachine.build specs in + let+ scenario = gen_steps env state size in + (specs, scenario) + +let pp_scenario fmt (specs, steps) = + Format.( + fprintf + fmt + "@[{@ @[ @[specs@ = %a;@]@ @[steps@ = @[[ \ + %a]@]@]@]}@]" + pp_specs + specs + (pp_print_list + ~pp_sep:(fun fmt _ -> fprintf fmt "@ ; ") + (pp_step pp_contract_id)) + steps) + +let print_scenario = Format.asprintf "%a" pp_scenario + +let gen_adversary_scenario : + tzbtc -> + liquidity -> + int -> + (specs * contract_id * contract_id step list) QCheck2.Gen.t = + fun total_tzbtc total_liquidity size -> + let* specs = gen_specs total_tzbtc total_liquidity in + let state, env = SymbolicMachine.build ~subsidy:0L specs in + let* c = oneofl env.implicit_accounts in + let+ scenario = gen_steps ~source:c ~destination:c env state size in + (specs, c, scenario) + +let print_adversary_scenario (specs, _, steps) = + Format.asprintf "%a" pp_scenario (specs, steps) + +(* -------------------------------------------------------------------------- *) + +(* Note (1) + + We shrink a valid scenario by removing steps from its tails, + because a prefix of a valid scenario remains a valid + scenario. Removing a random element of a scenario could lead to an + invalid scenario. We have to use QCheck2.Gen.make_primitive to specify + the shrinking method of the generator, and avoid defaulting on the + shrinking implied by QCheck2.Gen.bind *) + +(* Note (2) + + If we are not being careful, it is possible to provoke an overflow + in the xtzPool and tzbtcPool. We try to avoid that as much as + possible by being very careful with the steps that are likely to + add xtz to the contract. *) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.mli new file mode 100644 index 000000000000..02a0a12ebc93 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_generator.mli @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides a set of abstractions to reason about the + so-called “liquidity baking” feature[1]. + + [1]: https://gitlab.com/tezos/tzip/-/blob/367628e1a576c3926bedc1d6107b2945607c2605/drafts/current/draft-liquidity_baking.md + + We remind that this feature is built upon three smart contracts: + (1) a CPMM contract initially based on Dexter 2, and (2) two + tokens contracts. + + Our purpose for Liquidity Baking is to easily express and test + invariants regarding the execution of these contracts. To that + end, we have introduced a set of dedicated types to describe + arbitrary contexts in terms of account balances (see + [Liquidity_baking_machine.specs]), along with [build] functions + that turn a description of a context into concrete states. + + In this module, we provide QCheck2 generators which allow to + construct arbitrary specifications for states, and so-called + scenarios ({i i.e.}, sequences of entrypoint calls). *) + +open Liquidity_baking_machine + +(** [gen_specs max_tzbtc max_liquidity] constructs arbitrary Liquidity + Baking [specs] for an initial state, where at most [max_tzbtc] and + [max_liquidity] are shared among an arbitrary number of implicit + accounts. *) +val gen_specs : tzbtc -> liquidity -> specs QCheck2.Gen.t + +(** [gen_scenario max_tzbtc max_liquidity size] constructs arbitrary + Liquidity Baking [specs] with a semantics similar to [gen_specs], along with sequences of {b valid} + scenarios ({i i.e.}, sequences of entrypoint calls) of length + [size]. By valid, we mean that running the scenario using a + Liquidity baking machine initialized with the [specs] should + succeed. *) +val gen_scenario : + tzbtc -> liquidity -> int -> (specs * contract_id step list) QCheck2.Gen.t + +(** [print_scenario scenario] produces a string representation of [scenario], + as produced by [gen_scenario]. *) +val print_scenario : specs * contract_id step list -> string + +(** [gen_adversary_scenario max_tzbtc max_liquidity size] constructs + arbitrary scenarios that can be used to challenge the “no global + gain” property of Liquidity Baking. + + The key idea of this property is the following: a given contract + cannot profit from Liquidity Baking if they are the only one to + interact with the CPMM (in the absence of subsidies). The scenario + generated by [gen_adversary_scenario] only consists in [step] + performed by one contract. This contract is identified by the + [contract_id] returned by this function. *) +val gen_adversary_scenario : + tzbtc -> + liquidity -> + int -> + (specs * contract_id * contract_id step list) QCheck2.Gen.t + +(** [print_adversary_scenario scenario] produces a string representation of [scenario], + as produced by [gen_adversary_scenario]. *) +val print_adversary_scenario : + specs * contract_id * contract_id step list -> string diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.ml new file mode 100644 index 000000000000..e18fec45dd60 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.ml @@ -0,0 +1,1399 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** To implement the interface of this module, as described and + documented in the related MLI file, we rely on the OCaml module + system. More precisely, most of the implementation of the two + public machines ([ValidationMachine] and [SymbolicMachine]) is + derived by means of functors. + + The machines provide two key functions which can be used in a + test suite: + + - [M.build specs] which allows to construct an initial state of + a machine [M] that satisfies the properties described by + [specs] (along with the so-called “environment” of the + machine) + - [M.step s env state] (resp. [M.run]) which allows to execute a + so-called scenario [step] (resp. a sequence of [step]s, {i + i.e.}, a complete scenario) by the machine [M] from the state + [state]. + + The module is organized as follows: + + 1. We introduce the necessary abstractions we later use to + specify the properties the initial state of a given machine + needs to satisfy (most notably the [specs] type). + 2. Then, we introduce the [step] type, which describes the + various actions we can make a machine perform as part of a + more complete scenario. + 3. We introduce the [MACHINE] module type which lists the + necessary types and functions we need to derive a machine + capable of executing scenarios, and the [Machine.Make] + functor that we can use to derive such a machine + automatically. + 4. We introduce the [MACHINE_WITH_INIT] module type which is a + superset of [MACHINE], extended with an [init] function + (analogous to {! Context.init_n}) to create an initial, mostly + blank state, and the [MachineBuilder.Make] functor that we + can use to derive a machine with a [build] function. + 5. We construct the [ConcreteMachine], that allows to + asynchronously execute scenarios against the Tezos + blockchain. + 6. We implement the [AbstractMachine.Make] functor, which we + can use to construct machines that can simulate the + execution scenarios completely off-chains, by reimplementing + the LB features logic in pure OCaml. + 7. We use [AbstractMachine.Make] to create the [SymbolicMachine]. + 8. We use the [AbstractMachine.Make] functor in conjuction with + the [ConcreteMachine] to introduce the [ValidationMachine]. + + _ + / \ A warning for developers willing to modify this module: + / | \ dealing with the subsidy of the Liquidity Baking (LB) + / · \ feature is probably the main source of complexity and + /_______\ fragility of this module. + + At several places (marked with a /!\ note), we need to predict the + xtz pool of the CPMM contract, in order to compute the amount of + tzBTC token it will provide or request. To make this prediction, + we need to determine how many blocks have been/will be baked. This + means that each time we modify the code of the machine functors, + we will probably have to modify the code marked with /!\ too. + + To reduce the potential to get things wrong, we have introduced + constants to prevent the use of “magic numbers” (numbers whose + meaning cannot be guessed only by looking at the formula). The + value of these constants is not statically checked, so pay extra + attention before modifying them. + + Ideally, we could probably compute these magic numbers using a + dedicated machine, whose purpose would be to count the number of + call to the [bake] function. For the sake of simplicity, we do not + do it currently. *) + +(** The number of blocks baked in order to execute the {! + AddLiquidity} step. *) +let blocks_per_add_liquidity_step = 2L + +(** The number of blocks baked by the [init] function. Since + Tenderbake, we need to compensate for deposits, so the number is + no longer constant. It is linear wrt. the number of accounts. *) +let blocks_during_init len = Int64.add 3L len + +(** The number of blocks baked by the [mint_tzbtc] functions *) +let blocks_per_mint_tzbtc = 1L + +(** A timestamp “far in the future” which should not be exceeded when + running tests. *) +let far_future = Script_timestamp.of_zint (Z.of_int 42_000) +(* Hypothesis: the tests start at timestamp 0, and 42000 is + “big enough.” *) + +(* --------------------------------------------------------------------------- *) + +(** {1 Miscellaneous Helpers} *) +module List_helpers = struct + let rec zip l r = + match (l, r) with + | xl :: rstl, xr :: rstr -> (xl, xr) :: zip rstl rstr + | _ -> [] + + let nth_exn l n = + match List.nth l n with + | Some x -> x + | _ -> raise (Invalid_argument "nth_exn") + + let assoc_exn c l = + match List.assoc ~equal:( = ) c l with + | Some x -> x + | _ -> raise (Invalid_argument "assoc_exn") +end + +(* --------------------------------------------------------------------------- *) + +(** {1 Characterizing Initial Machines States} *) + +(** In order to run so-called scenarios against our machines, we first + need to characterize their initial state. *) + +type xtz = int64 + +type tzbtc = int + +type liquidity = int + +type balances = {xtz : xtz; tzbtc : tzbtc; liquidity : liquidity} + +let pp_balances fmt b = + Format.fprintf + fmt + "@[{xtz = %a; tzbtc = %d; liquidity = %d}@]" + Tez.pp + (Tez.of_mutez_exn b.xtz) + b.tzbtc + b.liquidity + +let xtz {xtz; _} = xtz + +type specs = { + cpmm_min_xtz_balance : xtz; + cpmm_min_tzbtc_balance : tzbtc; + accounts_balances : balances list; +} + +let pp_specs fmt specs = + Format.( + fprintf + fmt + "@[{@ @[cpmm = {min_xtz = %a; min_tzbtc = %d}@ @[accounts = \ + [@ %a@ ]@]@]@ }@]" + Tez.pp + (Tez.of_mutez_exn specs.cpmm_min_xtz_balance) + specs.cpmm_min_tzbtc_balance + (pp_print_list ~pp_sep:pp_print_space pp_balances) + specs.accounts_balances) + +(* --------------------------------------------------------------------------- *) + +(** {1 Scenario [step] }*) + +type 'a step = + | SellTzBTC of {source : 'a; destination : 'a; tzbtc_deposit : tzbtc} + | BuyTzBTC of {source : 'a; destination : 'a; xtz_deposit : xtz} + | AddLiquidity of {source : 'a; destination : 'a; xtz_deposit : xtz} + | RemoveLiquidity of {source : 'a; destination : 'a; lqt_burned : liquidity} + +let pp_step pp_contract fmt = function + | SellTzBTC p -> + Format.( + fprintf + fmt + "@[SellTzBTC(%a, %dtz₿, %a)@]" + pp_contract + p.source + p.tzbtc_deposit + pp_contract + p.destination) + | BuyTzBTC p -> + Format.( + fprintf + fmt + "@[BuyTzBTC(%a, %aꜩ, %a)@]" + pp_contract + p.source + Tez.pp + (Tez.of_mutez_exn p.xtz_deposit) + pp_contract + p.destination) + | AddLiquidity p -> + Format.( + fprintf + fmt + "@[AddLiquidity(%a, %aꜩ, %a)@]" + pp_contract + p.source + Tez.pp + (Tez.of_mutez_exn p.xtz_deposit) + pp_contract + p.destination) + | RemoveLiquidity p -> + Format.( + fprintf + fmt + "@[RemoveLiquidity(%a, %d lqt, %a)@]" + pp_contract + p.source + p.lqt_burned + pp_contract + p.destination) + +type contract_id = + | Cpmm + | Holder + | TzBTC + | TzBTCAdmin + | Liquidity + | LiquidityAdmin + | ImplicitAccount of int + +let contract_id_to_string = function + | Holder -> "holder" + | Cpmm -> "cpmm" + | TzBTC -> "tzbtc" + | TzBTCAdmin -> "tzbtc_admin" + | Liquidity -> "lqt" + | LiquidityAdmin -> "lqt_admin" + | ImplicitAccount i -> Format.sprintf "#%d" i + +let pp_contract_id fmt c = Format.(fprintf fmt "[%s]" (contract_id_to_string c)) + +(* --------------------------------------------------------------------------- *) + +(** {1 Machines} *) + +(** {2 Machine Environment} *) + +type 'a env = { + cpmm_contract : 'a; + tzbtc_contract : 'a; + tzbtc_admin : 'a; + liquidity_contract : 'a; + liquidity_admin : 'a; + implicit_accounts : 'a list; + holder : 'a; + subsidy : xtz; +} + +let refine_contract env = function + | Cpmm -> env.cpmm_contract + | TzBTC -> env.tzbtc_contract + | TzBTCAdmin -> env.tzbtc_admin + | Liquidity -> env.liquidity_contract + | LiquidityAdmin -> env.liquidity_admin + | Holder -> env.holder + | ImplicitAccount i -> List_helpers.nth_exn env.implicit_accounts i + +let refine_step env step = + match step with + | SellTzBTC p -> + SellTzBTC + { + p with + source = refine_contract env p.source; + destination = refine_contract env p.destination; + } + | BuyTzBTC p -> + BuyTzBTC + { + p with + source = refine_contract env p.source; + destination = refine_contract env p.destination; + } + | AddLiquidity p -> + AddLiquidity + { + p with + source = refine_contract env p.source; + destination = refine_contract env p.destination; + } + | RemoveLiquidity p -> + RemoveLiquidity + { + p with + source = refine_contract env p.source; + destination = refine_contract env p.destination; + } + +(** {2 Machine Module Type} *) + +module type MACHINE = sig + type 'a m + + type contract + + type t + + type operation + + val pp_contract : Format.formatter -> contract -> unit + + val ( let* ) : 'a m -> ('a -> 'b m) -> 'b m + + val fold_m : ('a -> 'b -> 'a m) -> 'a -> 'b list -> 'a m + + val pure : 'a -> 'a m + + val get_balances : contract -> contract env -> t -> balances m + + val get_xtz_balance : contract -> t -> xtz m + + val get_tzbtc_balance : contract -> contract env -> t -> tzbtc m + + val get_liquidity_balance : contract -> contract env -> t -> liquidity m + + val get_cpmm_total_liquidity : contract env -> t -> liquidity m + + val bake : + invariant:(contract env -> t -> bool m) -> + baker:contract -> + operation list -> + contract env -> + t -> + t m + + val transaction : src:contract -> contract -> xtz -> t -> operation m + + val token_to_xtz : + src:contract -> contract -> tzbtc -> contract env -> t -> operation m + + val xtz_to_token : + src:contract -> contract -> xtz -> contract env -> t -> operation m + + (* [mint_or_burn_tzbtc contract amount env state] will construct an + operation to credit or remove [amount] tzbtc tokens to [contract] *) + val mint_or_burn_tzbtc : + contract -> liquidity -> contract env -> t -> operation m + + (** [approve_tzbtc contract amount env state] will construct an + operation to authorize the CPMM contract to spend [amount] tzbtc + on behalf of [contract] *) + val approve_tzbtc : contract -> tzbtc -> contract env -> t -> operation m + + val add_liquidity : + src:contract -> contract -> xtz -> tzbtc -> contract env -> t -> operation m + + val remove_liquidity : + src:contract -> contract -> liquidity -> contract env -> t -> operation m + + val reveal : Account.t -> t -> operation m +end + +(** {2 Tezos Constants} *) + +let default_subsidy = + let c = Default_parameters.constants_test in + match Delegate.Rewards.For_RPC.liquidity_baking_subsidy_from_constants c with + | Ok x -> Tez.to_mutez x + | Error _ -> assert false + +let security_deposit = 640_000_000L + +(* When calling [Context.init_n] with a list of initial balances, the + sum of these balances should be equal to this constant. *) +let total_xtz = 32_000_000_000_000L + +let tzbtc_admin_account : Account.t = + { + pkh = + Signature.Public_key_hash.of_b58check_exn + "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; + pk = + Signature.Public_key.of_b58check_exn + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"; + sk = + Signature.Secret_key.of_b58check_exn + "edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh"; + } + +let cpmm_initial_balance = {xtz = 100L; tzbtc = 1; liquidity = 0} + +let cpmm_initial_liquidity_supply = 100 + +(** {2 Machine Functor} *) + +module Machine = struct + module Make (S : MACHINE) = struct + open S + + let mint_tzbtc destination ~invariant amount env state = + let* op = mint_or_burn_tzbtc destination amount env state in + bake ~invariant ~baker:env.holder [op] env state + + let add_liquidity ~invariant src dst xtz_deposit tzbtc_deposit env state = + let* lqt_op = approve_tzbtc src tzbtc_deposit env state in + let* state = bake ~invariant ~baker:env.holder [lqt_op] env state in + let* cpmm_op = + add_liquidity ~src dst xtz_deposit tzbtc_deposit env state + in + bake ~invariant ~baker:env.holder [cpmm_op] env state + + let remove_liquidity ~invariant src dst lqt_burned env state = + let* cpmm_op = remove_liquidity ~src dst lqt_burned env state in + bake ~invariant ~baker:env.holder [cpmm_op] env state + + let sell_tzbtc ~invariant src dst tzbtc_deposit env state = + let* tzbtc_op = approve_tzbtc src tzbtc_deposit env state in + let* state = bake ~invariant ~baker:env.holder [tzbtc_op] env state in + let* cpmm_op = token_to_xtz ~src dst tzbtc_deposit env state in + bake ~invariant ~baker:env.holder [cpmm_op] env state + + let buy_tzbtc ~invariant src dst xtz_deposit env state = + let* cpmm_op = xtz_to_token ~src dst xtz_deposit env state in + bake ~invariant ~baker:env.holder [cpmm_op] env state + + let check_state_satisfies_specs (env : S.contract env) (state : S.t) + (specs : specs) = + let implicit_accounts_targets = + List_helpers.zip env.implicit_accounts specs.accounts_balances + in + let* () = + fold_m + (fun _ acc -> + let expected = + List_helpers.assoc_exn acc implicit_accounts_targets + in + let* amount = get_balances acc env state in + assert (expected = amount) ; + pure ()) + () + env.implicit_accounts + in + let* cpmm_tzbtc_balance = get_tzbtc_balance env.cpmm_contract env state in + assert (specs.cpmm_min_tzbtc_balance <= cpmm_tzbtc_balance) ; + let* current_cpmm_xtz = get_xtz_balance env.cpmm_contract state in + assert ( + Int64.(to_int specs.cpmm_min_xtz_balance <= to_int @@ current_cpmm_xtz)) ; + pure () + + (** [predict_required_tzbtc_deposit xtz_deposit env state] + predicts the tzbtc deposit which will be required by the CPMM + contract for a deposit of [xtz_deposit]. + + This function is used by the machines to make the according + call to the [approve] entrypoint of the TzBTC contract. *) + let predict_required_tzbtc_deposit xtz_deposit env state = + let* xtzPool = get_xtz_balance env.cpmm_contract state in + (* /!\ We need to take into accounts the number of blocks baked + to actually call the [add_liquidity] entry point of the + CPMM. *) + let xtzPool = + Tez.of_mutez_exn + Int64.(add xtzPool (mul blocks_per_add_liquidity_step env.subsidy)) + in + let* tokenPool = get_tzbtc_balance env.cpmm_contract env state in + let tokenPool = Z.of_int tokenPool in + let* lqtTotal = get_cpmm_total_liquidity env state in + let lqtTotal = Z.of_int lqtTotal in + let amount = Tez.of_mutez_exn xtz_deposit in + let _, tokens_deposited = + Cpmm_logic.Simulate_raw.addLiquidity + ~tokenPool + ~xtzPool + ~lqtTotal + ~amount + in + pure (Z.to_int tokens_deposited) + + let step ?(invariant = fun _ _ -> pure true) s env state = + match s with + | SellTzBTC {source; destination; tzbtc_deposit} -> + sell_tzbtc ~invariant source destination tzbtc_deposit env state + | BuyTzBTC {source; destination; xtz_deposit} -> + buy_tzbtc ~invariant source destination xtz_deposit env state + | AddLiquidity {source; destination; xtz_deposit} -> + let* tzbtc_deposit = + predict_required_tzbtc_deposit xtz_deposit env state + in + add_liquidity + ~invariant + source + destination + xtz_deposit + tzbtc_deposit + env + state + | RemoveLiquidity {source; destination; lqt_burned} -> + remove_liquidity ~invariant source destination lqt_burned env state + + let run ?(invariant = fun _ _ -> pure true) scenario env state = + fold_m + (fun state s -> step ~invariant (refine_step env s) env state) + state + scenario + end +end + +let initial_xtz_repartition accounts_balances = + let distributed_xtz = List.fold_left Int64.add 0L accounts_balances in + let bootstrap1_xtz = Int64.sub total_xtz distributed_xtz in + let bootstrap_balances = bootstrap1_xtz :: accounts_balances in + let n = List.length bootstrap_balances in + (n, bootstrap_balances) + +(* --------------------------------------------------------------------------- *) + +(** {1 Machines with a [build] Function} *) + +module type MACHINE_WITH_INIT = sig + include MACHINE + + (** [init balances] will create an “initial” state wherein the + [balances] have been distributed to [n] implicit contracts ([n] + being the size of the [balances] list). This function also + creates a [holder] implicit account which has the rest of the + xtz liquidity (the test framework forces the sum of xtz balances + to be equal to [total_xtz]). [init] also accepts an optional + argument [subsidy] to modify the default value of the subsidy + minted by the protocol in favor of the CPMM. *) + val init : + invariant:(contract env -> t -> bool m) -> + ?subsidy:xtz -> + xtz list -> + (t * contract env) m +end + +(** [initial_xtz_pool] balances predicts the value of the CPMM’s xtz + pool just before we start using the [add_liquidity] entrypoint to + provide to each implicit accounts the necessary liquidity + tokens. *) +let initial_xtz_pool balances subsidy = + (* /!\ In addition to the initial CPMM balances, we need to take + into account the subsidies of each block baked before this + point, which currently consist in: + + - One call to the [init] function + - One call to the [mint_tzbtc] function per implicit + accounts + + If the [build] function changes, this functions needs to be + updated accordingly. *) + let len = Int64.of_int (List.length balances) in + Int64.( + add + cpmm_initial_balance.xtz + (mul + (add (blocks_during_init len) (mul blocks_per_mint_tzbtc len)) + subsidy)) + +(** [predict_initial_balances xtz_pool tzbtc_pool lqt_total balances] + evaluates the extra xtz and tzbtc tokens to add to each balance of + the list [balances] so that the related implicit accounts can call + the [add_liquidity] entrypoint in order to have the required + liquidity token. + + For instance, for a balance [b] such that [b.liquidity = 10], we + compute [xtz_etra] and [tzbtc_extra] so that the implicit account + will be able to buy [10] liquidity tokens, and replace [b] with + [{b with xtz = b.xtz + xtz_extra; tzbtc = b.tzbtc + tzbtc_extra}] + in the returned list. + + The implementation of this function is made more complex than it + should due to the mechanism of subsidy of LB. In particular, it is + depends on the number of block baked to buy liquidities. *) +let predict_initial_balances balances subsidy = + let open Z in + let subsidy_z = of_int64 subsidy in + (* Due to the roundness of [Z.( / )], it is not straightforward to + find the inverse of the equation used to compute the number of + liquidity tokens bought with the [add_liquidity] entrypoint. To + find the suitable number of xtz to propose in order to buy + [liquidity_target], we naively search for the correct + solution. We compute a [xtz_candidate] by ignoring the roundness + of [Z.( / )], then increment it until it works. *) + let find_xtz_extra xtz_pool lqt_total liquidity_target = + let rec aux xtz_candidate = + let liquidity_z = xtz_candidate * lqt_total / xtz_pool in + if liquidity_z = liquidity_target then xtz_candidate + else aux (xtz_candidate + Z.one) + in + let xtz_extra_candidate = liquidity_target * xtz_pool / lqt_total in + aux xtz_extra_candidate + in + let rec predict_initial_balances xtz_pool tzbtc_pool lqt_total = function + | {xtz; tzbtc; liquidity} :: rst -> + (* balance inputs *) + (* /!\ We compute two blocks per [add_liquidity] entrypoint, + hence the two subsidies *) + let xtz_pool = + xtz_pool + (Z.of_int64 blocks_per_add_liquidity_step * subsidy_z) + in + let xtz_z = of_int64 xtz in + let tzbtc_z = of_int tzbtc in + let liquidity_z = of_int liquidity in + (* compute extra for being able to buy liquidity tokens *) + let xtz_extra = find_xtz_extra xtz_pool lqt_total liquidity_z in + let tzbtc_extra = cdiv (xtz_extra * tzbtc_pool) xtz_pool in + (* compute new balances *) + let xtz = to_int64 (xtz_z + xtz_extra) in + let tzbtc = to_int (tzbtc_z + tzbtc_extra) in + let liquidity = to_int liquidity_z in + (* new pools *) + let xtz_pool' = xtz_pool + xtz_extra in + let tzbtc_pool' = tzbtc_pool + tzbtc_extra in + let lqt_total' = lqt_total + liquidity_z in + (* recursion time *) + {xtz; tzbtc; liquidity} + :: predict_initial_balances xtz_pool' tzbtc_pool' lqt_total' rst + | [] -> [] + in + predict_initial_balances + (of_int64 @@ initial_xtz_pool balances subsidy) + (of_int cpmm_initial_balance.tzbtc) + (of_int cpmm_initial_liquidity_supply) + balances + +module MachineBuilder = struct + module Make (S : MACHINE_WITH_INIT) = struct + open S + include Machine.Make (S) + + let build : + ?invariant:(S.contract env -> S.t -> bool m) -> + ?subsidy:xtz -> + specs -> + (S.t * S.contract env) m = + fun ?(invariant = fun _ _ -> pure true) + ?(subsidy = default_subsidy) + ({cpmm_min_xtz_balance; accounts_balances; cpmm_min_tzbtc_balance} as + specs) -> + let accounts_balances_with_extra = + predict_initial_balances accounts_balances subsidy + in + let xtz_balances_with_extra = List.map xtz accounts_balances_with_extra in + (* 1. Create an initial context *) + let* state, env = init ~invariant ~subsidy xtz_balances_with_extra in + let* cond = invariant env state in + assert cond ; + (* 2. Provide the initial tzBTC liquidities to implicit accounts *) + let accounts = + List_helpers.zip + env.implicit_accounts + (List_helpers.zip accounts_balances accounts_balances_with_extra) + in + let* state = + fold_m + (fun state (address, (_, balances)) -> + mint_tzbtc ~invariant address balances.tzbtc env state) + state + accounts + in + (* 3. Make implicit accounts buy liquidities *) + let* state = + fold_m + (fun state (address, (target_balances, balances_with_extra)) -> + let xtz = Int64.sub balances_with_extra.xtz target_balances.xtz in + let tzbtc = balances_with_extra.tzbtc - target_balances.tzbtc in + add_liquidity ~invariant address address xtz tzbtc env state) + state + accounts + in + (* 4. Provide any missing tzbtc tokens to [cpmm_contract], if necessary *) + let* current_cpmm_tzbtc_balance = + get_tzbtc_balance env.cpmm_contract env state + in + let tzbtc_missing = cpmm_min_tzbtc_balance - current_cpmm_tzbtc_balance in + let* state = + if 0 < tzbtc_missing then + (* 4.1. Provide the tokens to the [bootstrap1] account, as a + temporary holder for CPMM missing tzBTC balance *) + let* state = + mint_tzbtc ~invariant env.holder tzbtc_missing env state + in + (* 4.1. Make [bootstrap1] buy some xtz against the appropriate + amount of tzbtc *) + sell_tzbtc ~invariant env.holder env.holder tzbtc_missing env state + else pure state + in + (* 5. Provide any missing xtz tokens to [cpmm_contract], if necessary *) + let* current_cpmm_xtz_balance = get_xtz_balance env.cpmm_contract state in + let xtz_missing = + Int64.sub cpmm_min_xtz_balance current_cpmm_xtz_balance + in + let* state = + if 0L < xtz_missing then + let* op = + transaction ~src:env.holder env.cpmm_contract xtz_missing state + in + bake ~invariant ~baker:env.holder [op] env state + else pure state + in + let* () = check_state_satisfies_specs env state specs in + pure (state, env) + end +end + +(* --------------------------------------------------------------------------- *) + +module ConcreteBaseMachine : + MACHINE_WITH_INIT + with type 'a m = 'a tzresult Lwt.t + and type contract = Contract.t + and type t = Block.t = struct + type 'a m = 'a tzresult Lwt.t + + type contract = Contract.t + + type operation = packed_operation + + type t = Block.t + + let pp_contract = Contract.pp + + let ( let* ) = Lwt_result_syntax.( let* ) + + let fold_m = Environment.List.fold_left_es + + let pure = Lwt_result_syntax.return + + let get_xtz_balance contract blk = + let* x = Context.Contract.balance (B blk) contract in + pure @@ Tez.to_mutez x + + let get_tzbtc_balance contract env blk = + let destination = Destination.Contract contract in + let* mamount = + Lqt_fa12_repr.Storage.getBalance_opt + (B blk) + ~contract:env.tzbtc_contract + {destination; entrypoint = Entrypoint.default} + in + pure (Option.value (Option.map Z.to_int mamount) ~default:0) + + let get_liquidity_balance contract env blk = + let destination = Destination.Contract contract in + let* mamount = + Lqt_fa12_repr.Storage.getBalance_opt + (B blk) + ~contract:env.liquidity_contract + {destination; entrypoint = Entrypoint.default} + in + pure (Option.value (Option.map Z.to_int mamount) ~default:0) + + let get_cpmm_total_liquidity env blk = + let* cpmm_storage = + Cpmm_repr.Storage.get (B blk) ~contract:env.cpmm_contract + in + pure @@ Z.to_int cpmm_storage.lqtTotal + + let get_balances contract env blk = + let* xtz = get_xtz_balance contract blk in + let* tzbtc = get_tzbtc_balance contract env blk in + let* liquidity = get_liquidity_balance contract env blk in + pure {xtz; tzbtc; liquidity} + + let bake ~invariant ~baker ops env blk = + let open Lwt_result_syntax in + let* incr = + Incremental.begin_construction + ~policy:(Block.By_account (Context.Contract.pkh baker)) + blk + in + let* incr = fold_m Incremental.add_operation incr ops in + let* blk = Incremental.finalize_block incr in + let* cond = invariant env blk in + assert cond ; + return blk + + let reveal (account : Account.t) blk = Op.revelation (B blk) account.pk + + let transaction ~src dst amount blk = + Op.transaction (B blk) src dst (Tez.of_mutez_exn amount) + + let token_to_xtz ~src dst tzbtc_deposit env blk = + Cpmm_repr.transaction + (B blk) + ~src + ~contract:env.cpmm_contract + (Cpmm_repr.Parameter.TokenToXtz + { + to_ = dst; + minXtzBought = Tez.zero; + tokensSold = Z.of_int tzbtc_deposit; + deadline = far_future; + }) + + let xtz_to_token ~src dst amount env blk = + Cpmm_repr.transaction + (B blk) + ~src + ~contract:env.cpmm_contract + (Cpmm_repr.Parameter.XtzToToken + {to_ = dst; minTokensBought = Z.zero; deadline = far_future}) + ~amount:(Tez.of_mutez_exn amount) + + let approve_tzbtc src tzbtc env blk = + let maxTokensDeposited = Z.of_int tzbtc in + Lqt_fa12_repr.transaction + (B blk) + ~src + ~contract:env.tzbtc_contract + (Lqt_fa12_repr.Parameter.Approve + {spender = env.cpmm_contract; value = maxTokensDeposited}) + + let mint_or_burn_tzbtc target amount env blk = + let quantity = Z.of_int amount in + let ctxt = Context.B blk in + Lqt_fa12_repr.transaction + ctxt + ~src:env.tzbtc_admin + ~contract:env.tzbtc_contract + (Lqt_fa12_repr.Parameter.mintOrBurn {target; quantity}) + + let add_liquidity ~src dst xtz_deposit tzbtc_deposit env blk = + let amount = Tez.of_mutez_exn xtz_deposit in + let maxTokensDeposited = Z.of_int tzbtc_deposit in + Cpmm_repr.transaction + (B blk) + ~src + ~contract:env.cpmm_contract + ~amount + (Cpmm_repr.Parameter.AddLiquidity + { + owner = dst; + maxTokensDeposited; + minLqtMinted = Z.zero; + deadline = far_future; + }) + + let remove_liquidity ~src dst lqt_burned env blk = + let lqtBurned = Z.of_int lqt_burned in + Cpmm_repr.transaction + (B blk) + ~src + ~contract:env.cpmm_contract + (Cpmm_repr.Parameter.RemoveLiquidity + { + to_ = dst; + lqtBurned; + minXtzWithdrawn = Tez.zero; + minTokensWithdrawn = Z.zero; + deadline = far_future; + }) + + let reveal_tzbtc_admin ~invariant env state = + Account.add_account tzbtc_admin_account ; + let* op1 = transaction ~src:env.holder env.tzbtc_admin 1L state in + let* state = bake ~invariant ~baker:env.holder [op1] env state in + let* op2 = reveal tzbtc_admin_account state in + bake ~invariant ~baker:env.holder [op2] env state + + let init ~invariant ?subsidy:_ accounts_balances = + let n, bootstrap_balances = initial_xtz_repartition accounts_balances in + let* result = + Context.init_n + n + ~consensus_threshold:0 + ~bootstrap_balances + ~cost_per_byte:Tez.zero + ~origination_size:0 + ~blocks_per_cycle:10_000l + ~cycles_per_voting_period:1l + () + in + match result with + | blk, holder :: accounts -> + let ctxt = Context.B blk in + let* cpmm_contract = Context.get_liquidity_baking_cpmm_address ctxt in + let* storage = Context.Contract.storage ctxt cpmm_contract in + let storage = Cpmm_repr.Storage.of_expr_exn (Micheline.root storage) in + let tzbtc_contract = storage.tokenAddress in + let liquidity_contract = storage.lqtAddress in + let* storage = Context.Contract.storage ctxt tzbtc_contract in + let storage = + Lqt_fa12_repr.Storage.of_expr_exn (Micheline.root storage) + in + let tzbtc_admin = storage.admin in + let* storage = Context.Contract.storage ctxt liquidity_contract in + let storage = + Lqt_fa12_repr.Storage.of_expr_exn (Micheline.root storage) + in + let liquidity_admin = storage.admin in + let* subsidy = Context.get_liquidity_baking_subsidy (B blk) in + let env = + { + cpmm_contract = Contract.Originated cpmm_contract; + tzbtc_contract = Contract.Originated tzbtc_contract; + tzbtc_admin; + liquidity_contract = Contract.Originated liquidity_contract; + liquidity_admin; + implicit_accounts = accounts; + holder; + subsidy = Tez.to_mutez subsidy; + } + in + let* blk = + reveal_tzbtc_admin ~invariant:(fun _ _ -> pure true) env blk + in + let* op = + mint_or_burn_tzbtc + env.cpmm_contract + cpmm_initial_balance.tzbtc + env + blk + in + let* blk = + bake ~invariant:(fun _ _ -> pure true) ~baker:env.holder [op] env blk + in + (* Since Tenderbake, we need to compensate for potential deposits + related to the consensus. *) + let* blk = + List.fold_left_i_es + (fun idx blk contract -> + match List.nth accounts_balances idx with + | Some target -> + let* balance = get_xtz_balance contract blk in + let delta = Int64.(sub target balance) in + if Compare.Int64.(0L = delta) then + (* We need to be able to determine the number of + blocks baked in the init function (to predict the + CPMM balance). So even when there is no delta to + compensate with, we bake an empty block. *) + bake + ~invariant:(fun _ _ -> pure true) + ~baker:env.holder + [] + env + blk + else if Compare.Int64.(0L < delta) then + let* op = transaction ~src:env.holder contract delta blk in + bake + ~invariant:(fun _ _ -> pure true) + ~baker:env.holder + [op] + env + blk + else assert false + | None -> assert false) + blk + accounts + in + (* We did not check the invariant before, because the CPMM + contract was in an inconsistent state. More precisely, it + was supposed to hold tzbtc tokens, while in practice it was + not. This was solved by the last call to [bake]. *) + let* cond = invariant env blk in + assert cond ; + pure (blk, env) + | _ -> assert false +end + +module ConcreteMachine = struct + include ConcreteBaseMachine + include Machine.Make (ConcreteBaseMachine) + include MachineBuilder.Make (ConcreteBaseMachine) +end + +(* --------------------------------------------------------------------------- *) + +(** {1 Abstract Machines} *) + +type 'a state = { + cpmm_total_liquidity : liquidity; + accounts_balances : ('a * balances) list; +} + +let refine_state env state = + { + cpmm_total_liquidity = state.cpmm_total_liquidity; + accounts_balances = + List.map + (fun (c, b) -> (refine_contract env c, b)) + state.accounts_balances; + } + +let update_balances account f state = + match List.assoc ~equal:( = ) account state.accounts_balances with + | Some b -> + { + state with + accounts_balances = + (account, f b) + :: List.remove_assoc ~equal:( = ) account state.accounts_balances; + } + | _ -> assert false + +let update_xtz_balance account f = + update_balances account (fun b -> {b with xtz = f b.xtz}) + +let update_tzbtc_balance account f = + update_balances account (fun b -> {b with tzbtc = f b.tzbtc}) + +let update_liquidity_balance account f = + update_balances account (fun b -> {b with liquidity = f b.liquidity}) + +let transfer_xtz_balance src dest d st = + update_xtz_balance src (fun b -> Int64.sub b d) st + |> update_xtz_balance dest (fun b -> Int64.add b d) + +let transfer_tzbtc_balance src dest d st = + update_tzbtc_balance src (fun b -> b - d) st + |> update_tzbtc_balance dest (fun b -> d + b) + +module AbstractMachine = struct + module type C = sig + type t + + val pp : Format.formatter -> t -> unit + end + + module Make (C : C) : + MACHINE with type 'a m = 'a and type contract = C.t and type t = C.t state = + struct + type 'a m = 'a + + type contract = C.t + + type t = C.t state + + type operation = t -> t + + let pp_contract = C.pp + + let ( let* ) x f = f x + + let pure = Fun.id + + let fold_m = List.fold_left + + let get_balances account state = + match List.assoc ~equal:( = ) account state.accounts_balances with + | Some x -> x + | _ -> assert false + + let get_xtz_balance account state = (get_balances account state).xtz + + let get_tzbtc_balance account _env state = + (get_balances account state).tzbtc + + let get_liquidity_balance account _env state = + (get_balances account state).liquidity + + let get_balances account _env state = get_balances account state + + let get_cpmm_total_liquidity _env state = state.cpmm_total_liquidity + + let reveal _pk _state state = state + + let transaction ~src dst amount _ state = + transfer_xtz_balance src dst amount state + + let xtz_bought tzbtc env state = + let xtzPool = + Tez.of_mutez_exn @@ get_xtz_balance env.cpmm_contract state + in + let tokenPool = + Z.of_int @@ get_tzbtc_balance env.cpmm_contract env state + in + let tokensSold = Z.of_int tzbtc in + let xtz_bought, xtz_net_bought = + Cpmm_logic.Simulate_raw.tokenToXtz ~xtzPool ~tokenPool ~tokensSold + in + (Z.to_int64 xtz_net_bought, Tez.to_mutez xtz_bought) + + let token_to_xtz ~src dst amount env _ state = + let xtz_bought, xtz_net_bought = xtz_bought amount env state in + state + |> transfer_tzbtc_balance src env.cpmm_contract amount + |> update_xtz_balance env.cpmm_contract (fun b -> Int64.sub b xtz_bought) + |> update_xtz_balance dst (Int64.add xtz_net_bought) + + let tzbtc_bought env state amount = + let xtzPool = + Tez.of_mutez_exn @@ get_xtz_balance env.cpmm_contract state + in + let tokenPool = + Z.of_int @@ get_tzbtc_balance env.cpmm_contract env state + in + let amount = Tez.of_mutez_exn amount in + let tzbtc_bought, xtz_earnt = + Cpmm_logic.Simulate_raw.xtzToToken ~xtzPool ~tokenPool ~amount + in + (Z.to_int tzbtc_bought, Z.to_int64 xtz_earnt) + + let xtz_to_token ~src dst amount env _ state = + let tzbtc_bought, xtz_earnt = tzbtc_bought env state amount in + update_xtz_balance src (fun b -> Int64.sub b amount) state + |> update_xtz_balance env.cpmm_contract (Int64.add xtz_earnt) + |> transfer_tzbtc_balance env.cpmm_contract dst tzbtc_bought + + let mint_or_burn_tzbtc target amount _ _ = + update_tzbtc_balance target (( + ) amount) + + let approve_tzbtc _contract _amount _env _state = Fun.id + + let add_liquidity ~src dst xtz_deposit _tzbtc_deposit env _ state = + let xtzPool = + Tez.of_mutez_exn (get_xtz_balance env.cpmm_contract state) + in + let tokenPool = + Z.of_int (get_tzbtc_balance env.cpmm_contract env state) + in + let lqtTotal = Z.of_int state.cpmm_total_liquidity in + let amount = Tez.of_mutez_exn xtz_deposit in + let lqt_minted, tokens_deposited = + Cpmm_logic.Simulate_raw.addLiquidity + ~tokenPool + ~xtzPool + ~lqtTotal + ~amount + in + let lqt_minted = Z.to_int lqt_minted in + let tokens_deposited = Z.to_int tokens_deposited in + let state = + transfer_xtz_balance src env.cpmm_contract xtz_deposit state + |> transfer_tzbtc_balance src env.cpmm_contract tokens_deposited + |> update_liquidity_balance dst (( + ) lqt_minted) + in + { + state with + cpmm_total_liquidity = state.cpmm_total_liquidity + lqt_minted; + } + + let remove_liquidity ~src dst lqt_burned env _ state = + let xtzPool = + Tez.of_mutez_exn (get_xtz_balance env.cpmm_contract state) + in + let tokenPool = + Z.of_int (get_tzbtc_balance env.cpmm_contract env state) + in + let lqtTotal = Z.of_int state.cpmm_total_liquidity in + let lqtBurned = Z.of_int lqt_burned in + let xtz_withdrawn, tokens_withdrawn = + Cpmm_logic.Simulate_raw.removeLiquidity + ~tokenPool + ~xtzPool + ~lqtTotal + ~lqtBurned + in + let xtz_withdrawn = Tez.to_mutez xtz_withdrawn in + let tokens_withdrawn = Z.to_int tokens_withdrawn in + let state = + update_xtz_balance dst (fun b -> Int64.add b xtz_withdrawn) state + |> update_tzbtc_balance dst (( + ) tokens_withdrawn) + |> update_liquidity_balance src (fun b -> b - lqt_burned) + |> update_xtz_balance env.cpmm_contract (fun b -> + Int64.sub b xtz_withdrawn) + |> update_tzbtc_balance env.cpmm_contract (fun b -> + b - tokens_withdrawn) + in + { + state with + cpmm_total_liquidity = state.cpmm_total_liquidity - lqt_burned; + } + + (* Ideally, we should also deal with the release of security + deposit, but since our tests are not long enough for this to + happen, we omit this aspect of the simulation. *) + let bake ~invariant ~baker operations env state = + let state = + update_xtz_balance env.cpmm_contract (Int64.add env.subsidy) state + |> (fun state -> List.fold_left ( |> ) state operations) + |> update_xtz_balance baker (fun b -> Int64.sub b security_deposit) + in + assert (invariant env state) ; + state + end +end + +(* --------------------------------------------------------------------------- *) + +(** {1 Symbolic Machine} *) + +module SymbolicBaseMachine : + MACHINE_WITH_INIT + with type 'a m = 'a + and type contract = contract_id + and type t = contract_id state = struct + include AbstractMachine.Make (struct + type t = contract_id + + let pp = pp_contract_id + end) + + let init ~invariant:_ ?(subsidy = default_subsidy) accounts_balances = + let _, bootstrap_balances = initial_xtz_repartition accounts_balances in + let len = Int64.of_int (List.length accounts_balances) in + match bootstrap_balances with + | holder_xtz :: accounts -> + let xtz_cpmm = + Int64.( + add cpmm_initial_balance.xtz (mul (blocks_during_init len) subsidy)) + in + ( { + cpmm_total_liquidity = cpmm_initial_liquidity_supply; + accounts_balances = + (Cpmm, {cpmm_initial_balance with xtz = xtz_cpmm}) + :: (Holder, {xtz = holder_xtz; tzbtc = 0; liquidity = 0}) + :: (TzBTCAdmin, {xtz = 0L; tzbtc = 0; liquidity = 0}) + :: List.mapi + (fun i xtz -> + (ImplicitAccount i, {xtz; tzbtc = 0; liquidity = 0})) + accounts; + }, + { + cpmm_contract = Cpmm; + tzbtc_contract = TzBTC; + tzbtc_admin = TzBTCAdmin; + liquidity_contract = Liquidity; + liquidity_admin = LiquidityAdmin; + implicit_accounts = + List.mapi (fun i _ -> ImplicitAccount i) accounts; + holder = Holder; + subsidy; + } ) + | [] -> assert false +end + +module SymbolicMachine = struct + include SymbolicBaseMachine + include Machine.Make (SymbolicBaseMachine) + include MachineBuilder.Make (SymbolicBaseMachine) +end + +(* --------------------------------------------------------------------------- *) + +(** {1 Validation Machine} *) + +module ValidationBaseMachine : + MACHINE_WITH_INIT + with type 'a m = 'a ConcreteBaseMachine.m + and type t = ConcreteBaseMachine.t * Contract.t state + and type contract = Contract.t = struct + module GhostMachine = AbstractMachine.Make (struct + type t = Contract.t + + let pp = Contract.pp + end) + + type 'a m = 'a ConcreteBaseMachine.m + + type t = ConcreteBaseMachine.t * GhostMachine.t + + type contract = Contract.t + + type operation = ConcreteBaseMachine.operation * GhostMachine.operation + + let pp_contract = Contract.pp + + let ( let* ) = ConcreteBaseMachine.( let* ) + + let fold_m = ConcreteBaseMachine.fold_m + + let pure = ConcreteBaseMachine.pure + + let get_balances contract env (_, state) = + pure (GhostMachine.get_balances contract env state) + + let get_xtz_balance contract (_, state) = + pure (GhostMachine.get_xtz_balance contract state) + + let get_tzbtc_balance contract env (_, state) = + pure (GhostMachine.get_tzbtc_balance contract env state) + + let get_liquidity_balance contract env (_, state) = + pure (GhostMachine.get_liquidity_balance contract env state) + + let get_cpmm_total_liquidity env (_, state) = + pure (GhostMachine.get_cpmm_total_liquidity env state) + + let bake ~invariant ~baker ops env (blk, state) = + let cops = List.map fst ops in + let rops = List.map snd ops in + let* blk = + ConcreteBaseMachine.( + bake ~invariant:(fun _ _ -> pure true) ~baker cops env blk) + in + let state = + GhostMachine.bake ~invariant:(fun _ _ -> true) ~baker rops env state + in + let* cond = invariant env (blk, state) in + assert cond ; + pure (blk, state) + + let transaction ~src dst xtz (blk, state) = + let* cop = ConcreteBaseMachine.transaction ~src dst xtz blk in + pure (cop, GhostMachine.transaction ~src dst xtz state) + + let token_to_xtz ~src dst tzbtc env (blk, state) = + let* cop = ConcreteBaseMachine.token_to_xtz ~src dst tzbtc env blk in + pure (cop, GhostMachine.token_to_xtz ~src dst tzbtc env state) + + let xtz_to_token ~src dst xtz env (blk, state) = + let* cop = ConcreteBaseMachine.xtz_to_token ~src dst xtz env blk in + pure (cop, GhostMachine.xtz_to_token ~src dst xtz env state) + + let mint_or_burn_tzbtc dst tzbtc env (blk, state) = + let* cop = ConcreteBaseMachine.mint_or_burn_tzbtc dst tzbtc env blk in + pure (cop, GhostMachine.mint_or_burn_tzbtc dst tzbtc env state) + + let approve_tzbtc dst tzbtc env (blk, state) = + let* cop = ConcreteBaseMachine.approve_tzbtc dst tzbtc env blk in + pure (cop, GhostMachine.approve_tzbtc dst tzbtc env state) + + let add_liquidity ~src dst xtz_deposit tzbtc_deposit env (blk, state) = + let* cop = + ConcreteBaseMachine.add_liquidity + ~src + dst + xtz_deposit + tzbtc_deposit + env + blk + in + pure + ( cop, + GhostMachine.add_liquidity ~src dst xtz_deposit tzbtc_deposit env state + ) + + let remove_liquidity ~src dst lqt_burned env (blk, state) = + let* cop = + ConcreteBaseMachine.remove_liquidity ~src dst lqt_burned env blk + in + pure (cop, GhostMachine.remove_liquidity ~src dst lqt_burned env state) + + let reveal account (blk, state) = + let* cop = ConcreteBaseMachine.reveal account blk in + pure (cop, GhostMachine.reveal account state) + + let init ~invariant ?subsidy balances = + let* blk, env = + ConcreteBaseMachine.init + ~invariant:(fun _ _ -> Lwt_result_syntax.return_true) + ?subsidy + balances + in + let state, _ = + SymbolicBaseMachine.init ~invariant:(fun _ _ -> true) ?subsidy balances + in + let state = refine_state env state in + let* cond = invariant env (blk, state) in + assert cond ; + pure ((blk, state), env) +end + +module ValidationMachine = struct + include ValidationBaseMachine + include Machine.Make (ValidationBaseMachine) + include MachineBuilder.Make (ValidationBaseMachine) + + module Symbolic = struct + let get_xtz_balance = get_xtz_balance + + let get_tzbtc_balance = get_tzbtc_balance + + let get_liquidity_balance = get_liquidity_balance + + let get_cpmm_total_liquidity = get_cpmm_total_liquidity + end + + module Concrete = struct + let get_xtz_balance contract (blk, _) = + ConcreteMachine.get_xtz_balance contract blk + + let get_tzbtc_balance contract env (blk, _) = + ConcreteMachine.get_tzbtc_balance contract env blk + + let get_liquidity_balance contract env (blk, _) = + ConcreteMachine.get_liquidity_balance contract env blk + + let get_cpmm_total_liquidity env (blk, _) = + ConcreteMachine.get_cpmm_total_liquidity env blk + end +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.mli new file mode 100644 index 000000000000..76107f8b4d61 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/liquidity_baking_machine.mli @@ -0,0 +1,387 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This module provides the means to test extensively the Liquidity + Baking (LB) feature. We recall that this feature is built upon + three smart contracts: (1) a CPMM contract initially based on + Dexter 2, and (2) two tokens contracts. Our objective is to run + “scenarios” consisting in interleaved, realistic calls to these + contracts, and to assert these scenarios do not yield any + undesirable behaviors. + + To that end, three “machines” are provided. + + - The {! SymbolicMachine} allows to simulate scenarios involving + the LB feature completely off-chain. It can be seen as an + abstraction of the concrete implementation provided by the Tezos + node. + - The {! ConcreteMachine } allows to execute scenarios on-chain. + - The {! ValidationMachine } combines the two previously mentioned + machines. In other words, the {! ValidationMachine} makes the {! + SymbolicMachine} and the [ConcreteMachine] execute the same + scenarios, and asserts they remain synchronized after each baked + block. + + The {! ValidationMachine} allows to (1) validate the {! + SymbolicMachine} ({i i.e.,} the reimplementation of the LB + contracts logic) against the real implementation provided by + Tezos, {b and} the contracts originated by the protocol correctly + implement the LB logic, as implemented by the {! SymbolicMachine}. + That is, the {! ValidationMachine} reports desynchronization of + the two machines, but cannot explain this desynchronization. *) + +(** {1 Machine State Characterization} *) + +type xtz = int64 + +type tzbtc = int + +type liquidity = int + +(** As far as liquidity baking is concerned, an account can hold three + kinds of tokens: [xtz], [tzbtc], and [liquidity]. *) +type balances = {xtz : xtz; tzbtc : tzbtc; liquidity : liquidity} + +val pp_balances : Format.formatter -> balances -> unit + +(** A value of type [specs] allows to specify an initial state of a + “machine”. + + In a nutshell, it consists in specifying the minimal balances of + the CPMM contracts and a set of implicit contracts. The two + machines provided by this module has a [build] function which + turns a [specs] into a consistent initial state for this + machine. *) +type specs = { + cpmm_min_xtz_balance : xtz; + cpmm_min_tzbtc_balance : tzbtc; + accounts_balances : balances list; +} + +val pp_specs : Format.formatter -> specs -> unit + +(** A value of type ['a env] (where ['a] is the type of contract + identifiers) summarizes the different contracts involved in the LB + feature. + + Values of type [env] are constructed by the [build] function of + the machines. *) +type 'a env = private { + cpmm_contract : 'a; + tzbtc_contract : 'a; + tzbtc_admin : 'a; + liquidity_contract : 'a; + liquidity_admin : 'a; + implicit_accounts : 'a list; + holder : 'a; + subsidy : xtz; +} + +(** A value of type ['a step] (where ['a] is the type used to identify + contracts) describes a consistent sequence of LB smart contract + calls. + + For instance, [SellTzBTC] consists in approving an allowance in + the [TzBTC] contract, then calling the [token_to_xtz] entry point + of the [CPMM]. *) +type 'a step = + | SellTzBTC of {source : 'a; destination : 'a; tzbtc_deposit : tzbtc} + | BuyTzBTC of {source : 'a; destination : 'a; xtz_deposit : xtz} + | AddLiquidity of {source : 'a; destination : 'a; xtz_deposit : xtz} + | RemoveLiquidity of {source : 'a; destination : 'a; lqt_burned : liquidity} + +val pp_step : + (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a step -> unit + +(** A summary of the state of a machine, parameterized by the type of + contract identifier. *) +type 'a state = { + cpmm_total_liquidity : liquidity; + accounts_balances : ('a * balances) list; +} + +(** {1 The Symbolic Machine} *) + +(** In the {! SymbolicMachine}, a contract is identified by a symbolic + value. *) +type contract_id = + | Cpmm + | Holder + | TzBTC + | TzBTCAdmin + | Liquidity + | LiquidityAdmin + (* We use integers to distinguish between implicit account because + this integer has the extra benefit of being the index of the + related account in [env.implicit_accounts]. *) + | ImplicitAccount of int + +val pp_contract_id : Format.formatter -> contract_id -> unit + +module SymbolicMachine : sig + (** The state of the {! SymbolicMachine}. *) + type t = contract_id state + + (** [get_xtz_balance c state] returns the amount of mutez owned by + [c] in [state]. *) + val get_xtz_balance : contract_id -> t -> xtz + + (** [get_tzbtc_balance c env state] returns the amount of TzBTC + owned by [c] in [state], according to the [TzBTC] contract. *) + val get_tzbtc_balance : contract_id -> contract_id env -> t -> tzbtc + + (** [get_liquidity_balance c env state] returns the amount of + liquidity token owned by [c] in [state], according to the + [Liquidity] contract. *) + val get_liquidity_balance : contract_id -> contract_id env -> t -> liquidity + + (** [get_cpmm_total_liquidity env state] fetches the current amount + of liquidity tokens distributed by the CPMM contract from the + state [state]. *) + val get_cpmm_total_liquidity : contract_id env -> t -> liquidity + + (** [predict_required_tzbtc_deposit xtz_deposit env state] predicts + the deposit in TzBTC which will be required by the CPMM contract + when executing a step [AddLiquidity] with [xtz_deposit] from + [state]. *) + val predict_required_tzbtc_deposit : xtz -> contract_id env -> t -> tzbtc + + (** [build specs] computes (1) an initial state for the {! + SymbolicMachine}, and (2) the environment associated to this + state. + + The machine enforces the resulting state is consistent with the + [specs] given as inputs, and raises an [Assert_failure] + exception if it does not. + + One can use the optional argument [subsidy] to set the subsidy + amount to a given value (by default, we use the same as the main + chain). Additionally, the [invariant] optional argument can be + used to verify that a given invariant holds at the end of the + initialization. *) + val build : + ?invariant:(contract_id env -> t -> bool) -> + ?subsidy:xtz -> + specs -> + t * contract_id env + + (** [step s env state] executes a single step [s] from [state]. + + The [invariant] optional argument can be used to verify that a + given invariant holds after each baked block. *) + val step : + ?invariant:(contract_id env -> t -> bool) -> + contract_id step -> + contract_id env -> + t -> + t + + (** [run steps env state] executes a list of steps from [state]. + + The [invariant] optional argument can be used to verify that a + given invariant holds after each baked block. *) + val run : + ?invariant:(contract_id env -> t -> bool) -> + contract_id step list -> + contract_id env -> + t -> + t +end + +(** A machine that can execute scenarios onchain. *) +module ConcreteMachine : sig + (** The state of the {! ConcreteMachine}. *) + type t = Block.t + + (** [get_xtz_balance c state] returns the amount of mutez owned by + [c] in [state]. *) + val get_xtz_balance : Contract.t -> t -> xtz tzresult Lwt.t + + (** [get_tzbtc_balance c env state] returns the amount of TzBTC + owned by [c] in [state], according to the [TzBTC] contract. *) + val get_tzbtc_balance : + Contract.t -> Contract.t env -> t -> tzbtc tzresult Lwt.t + + (** [get_liquidity_balance c env state] returns the amount of + liquidity token owned by [c] in [state], according to the + [Liquidity] contract. *) + val get_liquidity_balance : + Contract.t -> Contract.t env -> t -> liquidity tzresult Lwt.t + + (** [get_cpmm_total_liquidity env state] fetches the current amount + of liquidity tokens distributed by the CPMM contract from the + state [state]. *) + val get_cpmm_total_liquidity : Contract.t env -> t -> liquidity tzresult Lwt.t + + (** [build specs] asynchronously computes (1) an initial block for + the {! ConcreteMachine}, and (2) the environment associated to + this block. + + The machine enforces the resulting state is consistent with the + [specs] given as inputs, and raises an [Assert_failure] + exception if it does not. It also enforces that the machines + used underneath remain in sync. + + One can use the optional argument [subsidy] to set the subsidy + amount to a given value (by default, we use the same as the main + chain). Additionally, the [invariant] optional argument can be + used to verify that a given invariant holds at the end of the + initialization. *) + val build : + ?invariant:(Contract.t env -> t -> bool tzresult Lwt.t) -> + ?subsidy:xtz -> + specs -> + (t * Contract.t env) tzresult Lwt.t + + (** [step s env state] asynchronously executes a single step [s] + from [state]. + + The [invariant] optional argument can be used to verify that a + given invariant holds after each baked block. *) + val step : + ?invariant:(Contract.t env -> t -> bool tzresult Lwt.t) -> + Contract.t step -> + Contract.t env -> + t -> + t tzresult Lwt.t + + (** [run lss env state] asynchronously executes a list of steps from + [state]. + + The [invariant] optional argument can be used to verify that a + given invariant holds after each baked block. *) + val run : + ?invariant:(Contract.t env -> t -> bool tzresult Lwt.t) -> + contract_id step list -> + Contract.t env -> + t -> + t tzresult Lwt.t +end + +module ValidationMachine : sig + (** The state of the {! ValidationMachine}. *) + type t = ConcreteMachine.t * Contract.t state + + module Symbolic : sig + (** A collections of functions to introspect the symbolic part of + the [ValidationMachine] state. *) + + (** [get_xtz_balance c state] returns the amount of mutez owned by + [c] in the symbolic part of [state]. *) + val get_xtz_balance : Contract.t -> t -> xtz tzresult Lwt.t + + (** [get_tzbtc_balance c env state] returns the amount of TzBTC + owned by [c] in the symbolic part of [state], according to the + [TzBTC] contract. *) + val get_tzbtc_balance : + Contract.t -> Contract.t env -> t -> tzbtc tzresult Lwt.t + + (** [get_liquidity_balance c env state] returns the amount of + liquidity token owned by [c] in the symbolic part of [state], + according to the [Liquidity] contract. *) + val get_liquidity_balance : + Contract.t -> Contract.t env -> t -> liquidity tzresult Lwt.t + + (** [get_cpmm_total_liquidity env state] fetches the   current + amount of liquidity tokens distributed by the CPMM   contract + using the symbolic part of the state [state]. *) + val get_cpmm_total_liquidity : + Contract.t env -> t -> liquidity tzresult Lwt.t + end + + module Concrete : sig + (** A collections of functions to introspect the concrete part of + the [ValidationMachine] state. *) + + (** [get_xtz_balance c state] returns the amount of mutez owned by + [c] in the concrete part of [state]. *) + val get_xtz_balance : Contract.t -> t -> xtz tzresult Lwt.t + + (** [get_tzbtc_balance c env state] returns the amount of TzBTC + owned by [c] in the concrete part of [state], according to the + [TzBTC] contract. *) + val get_tzbtc_balance : + Contract.t -> Contract.t env -> t -> tzbtc tzresult Lwt.t + + (** [get_liquidity_balance c env state] returns the amount of + liquidity token owned by [c] in the concrete part of [state], + according to the [Liquidity] contract. *) + val get_liquidity_balance : + Contract.t -> Contract.t env -> t -> liquidity tzresult Lwt.t + + (** [get_cpmm_total_liquidity env state] fetches the current + amount of liquidity tokens distributed by the CPMM contract + using the concrete part of the state [state]. *) + val get_cpmm_total_liquidity : + Contract.t env -> t -> liquidity tzresult Lwt.t + end + + (** [build specs] asynchronously computes (1) an initial state for + the {! ValidationMachine}, and (2) the environment associated to + this state. + + The machine enforces the resulting state is consistent with the + [specs] given as inputs, and raises an [Assert_failure] + exception if it does not. It also enforces that the machines + used underneath remain in sync. + + One can use the optional argument [subsidy] to set the subsidy + amount to a given value (by default, we use the same as the main + chain). Additionally, the [invariant] optional argument can be + used to verify that a given invariant holds at the end of the + initialization. *) + val build : + ?invariant:(Contract.t env -> t -> bool tzresult Lwt.t) -> + ?subsidy:xtz -> + specs -> + (t * Contract.t env) tzresult Lwt.t + + (** [step s env state] asynchronously executes a single step [s] + from [state]. + + The [invariant] optional argument can be used to verify that a + given invariant holds after each baked block. *) + val step : + ?invariant:(Contract.t env -> t -> bool tzresult Lwt.t) -> + Contract.t step -> + Contract.t env -> + t -> + t tzresult Lwt.t + + (** [run lss env state] asynchronously executes a list of steps from + [state]. + + The [invariant] optional argument can be used to verify that a + given invariant holds after each baked block. *) + val run : + ?invariant:(Contract.t env -> t -> bool tzresult Lwt.t) -> + contract_id step list -> + Contract.t env -> + t -> + t tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/lqt_fa12_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/lqt_fa12_repr.ml new file mode 100644 index 000000000000..47f8bde4e4b8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/lqt_fa12_repr.ml @@ -0,0 +1,261 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Expr_common + +module Parameter = struct + (* // ============================================================================= + * // Entrypoints + * // ============================================================================= *) + + (* Note: in the lqt_fa12 contract, [value] is a nat. Hence, it + should always be positive *) + type approve = {spender : Contract.t; value : Z.t} + + type mintOrBurn = {quantity : Z.t; target : Contract.t} + + (* Note: this wrapper does not implement a reprensentation for the + entrypoints transfer, getAllowance, getBalance, getTotalSupply, + as they are not used as of yet. *) + type t = Approve of approve | MintOrBurn of mintOrBurn + + let approve p = + assert (Z.lt Z.zero p.value || Z.equal Z.zero p.value) ; + Approve p + + let mintOrBurn p = MintOrBurn p + + let approve_to_string {spender; value} = + Format.asprintf + "{ spender: %a; value: %a }" + Contract.pp + spender + Z.pp_print + value + + let mint_or_burn_to_string {quantity; target} = + Format.asprintf + "{ quantity: %a; target: %a }" + Z.pp_print + quantity + Contract.pp + target + + let to_string : t -> string = function + | Approve p -> Format.asprintf "Approve %s" (approve_to_string p) + | MintOrBurn p -> Format.asprintf "MintOrBurn %s" (mint_or_burn_to_string p) + + let entrypoint_of_parameter : t -> Entrypoint.t = function + | Approve _ -> Entrypoint.of_string_strict_exn "approve" + | MintOrBurn _ -> Entrypoint.of_string_strict_exn "mintOrBurn" + + let pp fmt s = Format.fprintf fmt "%s" (to_string s) + + let eq s s' = s = s' + + let to_expr_rooted : + loc:'a -> + t -> + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node = + fun ~loc -> function + | MintOrBurn {quantity; target} -> + comb ~loc [int ~loc quantity; address_string ~loc target] + | Approve {spender; value} -> + comb ~loc [address_string ~loc spender; int ~loc value] + + let to_expr : + loc:'a -> + t -> + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node = + fun ~loc p -> + let rooted = to_expr_rooted ~loc p in + match p with + | MintOrBurn _ -> right ~loc @@ left ~loc rooted + | Approve _ -> left ~loc @@ left ~loc @@ left ~loc rooted + + let to_michelson_string e = + let e = to_expr ~loc:0 e in + Format.asprintf + "%a" + Michelson_v1_printer.print_expr + (Micheline.strip_locations e) +end + +(* // ============================================================================= + * // Storage + * // ============================================================================= *) + +module Storage = struct + let pp_big_map_id fmt v = Z.pp_print fmt (Big_map.Id.unparse_to_z v) + + type t = { + tokens : Big_map.Id.t; + allowances : Big_map.Id.t; + admin : Contract.t; + totalSupply : Z.t; + } + + let pp {tokens; allowances; admin; totalSupply} = + Format.asprintf + "{ tokens: %a; allowances: %a; admin: %a; totalSupply: %a}" + Z.pp_print + (Big_map.Id.unparse_to_z tokens) + Z.pp_print + (Big_map.Id.unparse_to_z allowances) + Contract.pp + admin + Z.pp_print + totalSupply + + let null : t = + { + tokens = Big_map.Id.parse_z Z.zero; + allowances = Big_map.Id.parse_z Z.one; + admin = Contract.Implicit Signature.Public_key_hash.zero; + totalSupply = Z.zero; + } + + let eq s s' = s = s' + + let to_expr : + loc:'a -> + t -> + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node = + fun ~loc {tokens; allowances; admin; totalSupply} -> + comb + ~loc + [ + big_map_id ~loc tokens; + big_map_id ~loc allowances; + address_string ~loc admin; + int ~loc totalSupply; + ] + + let to_michelson_string e = + let e = to_expr ~loc:0 e in + Format.asprintf + "%a" + Michelson_v1_printer.print_expr + (Micheline.strip_locations e) + + type exn += Invalid_storage_expr of string + + (** Note: parses a storage unparsed in readable mode (as + e.g. returned by [Alpha_services.Contract.storage]), so that + contracts are represented by strings. *) + let of_expr_exn : + ('a, Michelson_v1_primitives.prim) Tezos_micheline.Micheline.node -> t = + function + | Tezos_micheline.Micheline.Prim + ( _, + Script.D_Pair, + [ + Tezos_micheline.Micheline.Int (_, tokens); + Tezos_micheline.Micheline.Int (_, allowances); + Tezos_micheline.Micheline.String (_, admin); + Tezos_micheline.Micheline.Int (_, totalSupply); + ], + [] ) -> + let tokens = Big_map.Id.parse_z tokens in + let allowances = Big_map.Id.parse_z allowances in + let admin = address_of_string_exn admin in + {tokens; allowances; admin; totalSupply} + | e -> + let canonical = Micheline.strip_locations e in + let msg = + Format.asprintf + "Not a valid LQT_FA1.2 storage: %s /// %a" + (try + Michelson_v1_printer.micheline_string_of_expression + ~zero_loc:true + canonical + with Z.Overflow -> + "Cannot represent as micheline due to overflowing Z -> int") + Michelson_v1_printer.print_expr + canonical + in + raise (Invalid_storage_expr msg) + + let get (ctxt : Context.t) ~(contract : Contract.t) : t tzresult Lwt.t = + let open Lwt_result_syntax in + match contract with + | Implicit _ -> + invalid_arg "Lqt_fa12_repr.Storage.get called on implicit account" + | Originated c -> + let+ expr = Context.Contract.storage ctxt c in + Micheline.root expr |> of_expr_exn + + let get_alpha_context (ctxt : Context.t) : Alpha_context.t tzresult Lwt.t = + let open Lwt_result_syntax in + let+ result = + match ctxt with + | B b -> + (* can perhaps be retrieved through Raw_context.prepare ? *) + Incremental.begin_construction b + | I i -> return i + in + Incremental.alpha_ctxt result + + let getBalance_opt (ctxt : Context.t) ~(contract : Contract.t) + (owner : Script_typed_ir.address) = + let open Lwt_result_wrap_syntax in + let* storage = get ctxt ~contract in + let tokens = storage.tokens in + let* ctxt = get_alpha_context ctxt in + let*@ address_hash, ctxt = + Script_ir_translator.hash_data ctxt Script_typed_ir.address_t owner + in + let*@ _, result = Big_map.get_opt ctxt tokens address_hash in + match result with + | Some canonical -> ( + match Tezos_micheline.Micheline.root canonical with + | Tezos_micheline.Micheline.Int (_, amount) -> return_some amount + | _ -> assert false) + | None -> return_none + + let getBalance (ctxt : Context.t) ~(contract : Contract.t) + (owner : Script_typed_ir.address) = + let open Lwt_result_syntax in + let+ t = getBalance_opt ctxt ~contract owner in + Option.value ~default:Z.zero t +end + +let transaction (ctxt : Context.t) ~(contract : Contract.t) ~(src : Contract.t) + ?(amount = Tez.zero) (parameters : Parameter.t) = + let entrypoint = Parameter.entrypoint_of_parameter parameters in + let rooted_param_lazy = + parameters + |> Parameter.to_expr_rooted ~loc:0 + |> Micheline.strip_locations |> Alpha_context.Script.lazy_expr + in + Op.transaction + ctxt + src + contract + amount + ~entrypoint + ~parameters:rooted_param_lazy diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.ml new file mode 100644 index 000000000000..820b0f6815e5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.ml @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Tezos_base.TzPervasives.Lwt_result_syntax + +let wrap m = + let open Lwt_syntax in + let+ result = m in + Environment.wrap_tzresult result + +let ( let@ ) m f = + let x = Environment.wrap_tzresult m in + f x + +let ( let*@ ) m f = + let* x = wrap m in + f x + +let ( let*?@ ) m f = + let*? x = Environment.wrap_tzresult m in + f x + +let ( let*!@ ) m f = + let*! x = wrap m in + f x + +let ( let+@ ) m f = + let+ x = wrap m in + f x diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.mli new file mode 100644 index 000000000000..f00f62ed6ca9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/lwt_result_wrap_syntax.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Extends the {!Lwt_result_syntax} with additional utilities for wrapping + results produced by the protocol, i.e. [Environment.Error_monad.tzresult], + to [tzresult Lwt.t] values used in the tests. + + The added utilities are binding operators. They use the same symbols as + the ones from {!Lwt_result_syntax} with an added [@] character. This + character symbolizes the {!e wrapping} of the internal error monad type in a + shell error. *) + +include module type of Tezos_base.TzPervasives.Lwt_result_syntax + +(** [wrap res] maps the result type contained in [res] to a tzresult + value. *) +val wrap : 'a Environment.Error_monad.tzresult Lwt.t -> 'a tzresult Lwt.t + +(** [let@ x = m in f x] is equivalent to [let x = Environment.wrap_tzresult m in f x] *) +val ( let@ ) : 'a Environment.Error_monad.tzresult -> ('a tzresult -> 'b) -> 'b + +(** [let*@ x = m in f x] is equivalent to [let* x = wrap m in f x]. + + Mnemonic: [@] "wraps" a protocol error in a shell error. *) +val ( let*@ ) : + 'a Environment.Error_monad.tzresult Lwt.t -> + ('a -> 'b tzresult Lwt.t) -> + 'b tzresult Lwt.t + +(** [let*?@ x = m in f x] is equivalent to [let*? x = Environment.wrap_tzresult + m in f x]. + + Mnemonic: [@] "wraps" a protocol error in a shell error. *) +val ( let*?@ ) : + 'a Environment.Error_monad.tzresult -> + ('a -> 'b tzresult Lwt.t) -> + 'b tzresult Lwt.t + +(** [let*!@ x = m in f x] is equivalent to [let*! x = wrap m in f x]. + + Mnemonic: [@] "wraps" a protocol error in a shell error. *) +val ( let*!@ ) : + 'a Environment.Error_monad.tzresult Lwt.t -> + ('a tzresult -> 'b Lwt.t) -> + 'b Lwt.t + +(** [let+@ x = m in f x] is equivalent to [let+ x = wrap m in f x]. + + Mnemonic: [@] "wraps" a protocol error in a shell error. *) +val ( let+@ ) : + 'a Environment.Error_monad.tzresult Lwt.t -> ('a -> 'b) -> 'b tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/merkle_list_helper.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/merkle_list_helper.ml new file mode 100644 index 000000000000..bf823ad6f954 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/merkle_list_helper.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let prefix = "\001\002\003" (* 8uE(36) *) + +module Hash = + Environment.Blake2B.Make + (Environment.Base58) + (struct + let name = "Merkle_list" + + let title = "Merkle_list" + + let b58check_prefix = prefix + + let size = Some 20 + end) + +module ML = + Protocol.Merkle_list.Make + (struct + type t = bytes + + let to_bytes x = x + end) + (Hash) + +include ML + +(* Hash two hashes *) +let hash2 (h1 : Hash.t) (h2 : Hash.t) = + Hash.(hash_bytes [to_bytes h1; to_bytes h2]) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.ml new file mode 100644 index 000000000000..8edff6991395 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.ml @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2014-2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(*****************************************************************************) + +open Protocol + +module Table = Hashtbl.Make (struct + type t = Nonce_hash.t + + let hash h = Int32.to_int (TzEndian.get_int32 (Nonce_hash.to_bytes h) 0) + + let equal = Nonce_hash.equal +end) + +let known_nonces = Table.create 17 + +let generate () = + match + Alpha_context.Nonce.of_bytes + @@ Tezos_crypto.Rand.generate Alpha_context.Constants.nonce_length + with + | Ok nonce -> + let hash = Alpha_context.Nonce.hash nonce in + Table.add known_nonces hash nonce ; + (hash, nonce) + | Error _ -> assert false + +let forget_all () = Table.clear known_nonces + +let get hash = Table.find known_nonces hash diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.mli new file mode 100644 index 000000000000..8a8b258b0658 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/nonce.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +(** Returns a fresh nonce and its corresponding hash (and stores them). *) +val generate : unit -> Nonce_hash.t * Alpha_context.Nonce.t + +val get : Nonce_hash.t -> Alpha_context.Nonce.t option + +val forget_all : unit -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/op.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/op.ml new file mode 100644 index 000000000000..b1ee1cdb0441 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/op.ml @@ -0,0 +1,1065 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let pack_operation ctxt signature contents = + let branch = Context.branch ctxt in + Operation.pack + ({shell = {branch}; protocol_data = {contents; signature}} : _ Operation.t) + +let sign ?(watermark = Signature.Generic_operation) sk branch contents = + let unsigned = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + ({branch}, Contents_list contents) + in + let signature = Some (Signature.sign ~watermark sk unsigned) in + ({shell = {branch}; protocol_data = {contents; signature}} : _ Operation.t) + +(** Generates the block payload hash based on the hash [pred_hash] of + the predecessor block and the hash of non-consensus operations of + the current block [b]. *) +let mk_block_payload_hash payload_round (b : Block.t) = + let ops = Block.Forge.classify_operations b.operations in + let non_consensus_operations = + List.concat (match List.tl ops with None -> [] | Some l -> l) + in + let hashes = List.map Operation.hash_packed non_consensus_operations in + Block_payload.hash + ~predecessor_hash:b.header.shell.predecessor + ~payload_round + hashes + +let mk_consensus_content_signer_and_branch ?delegate ?slot ?level ?round + ?block_payload_hash ?branch attested_block = + let open Lwt_result_wrap_syntax in + let branch = + match branch with + | None -> attested_block.Block.header.shell.predecessor + | Some branch -> branch + in + let* delegate_pkh, slots = + match delegate with + | None -> Context.get_attester (B attested_block) + | Some del -> ( + let* slots = Context.get_attester_slot (B attested_block) del in + match slots with + | None -> return (del, []) + | Some slots -> return (del, slots)) + in + let slot = + match slot with None -> Stdlib.List.hd slots | Some slot -> slot + in + let* level = + match level with + | None -> + let*? level = Context.get_level (B attested_block) in + return level + | Some level -> return level + in + let* round = + match round with + | None -> + let*?@ round = Block.get_round attested_block in + return round + | Some round -> return round + in + let block_payload_hash = + match block_payload_hash with + | None -> mk_block_payload_hash round attested_block + | Some block_payload_hash -> block_payload_hash + in + let consensus_content = {slot; level; round; block_payload_hash} in + let* signer = Account.find delegate_pkh in + return (consensus_content, signer.sk, branch) + +let raw_attestation ?delegate ?slot ?level ?round ?block_payload_hash + ?dal_content ?branch attested_block = + let open Lwt_result_syntax in + let* consensus_content, signer, branch = + mk_consensus_content_signer_and_branch + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + attested_block + in + let op = Single (Attestation {consensus_content; dal_content}) in + return + (sign + ~watermark:Operation.(to_watermark (Attestation Chain_id.zero)) + signer + branch + op) + +let attestation ?delegate ?slot ?level ?round ?block_payload_hash ?dal_content + ?branch attested_block = + let open Lwt_result_syntax in + let* op = + raw_attestation + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?dal_content + ?branch + attested_block + in + return (Operation.pack op) + +let raw_preattestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch + attested_block = + let open Lwt_result_syntax in + let* consensus_content, signer, branch = + mk_consensus_content_signer_and_branch + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + attested_block + in + let op = Single (Preattestation consensus_content) in + return + (sign + ~watermark:Operation.(to_watermark (Preattestation Chain_id.zero)) + signer + branch + op) + +let preattestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch + attested_block = + let open Lwt_result_syntax in + let* op = + raw_preattestation + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + attested_block + in + return (Operation.pack op) + +let sign ?watermark sk ctxt (Contents_list contents) = + Operation.pack (sign ?watermark sk ctxt contents) + +let batch_operations ?(recompute_counters = false) ~source ctxt + (operations : packed_operation list) = + let open Lwt_result_wrap_syntax in + let operations = + List.map + (function + | {Alpha_context.protocol_data = Operation_data {contents; _}; _} -> + Operation.to_list (Contents_list contents)) + operations + |> List.flatten + in + let* operations = + if recompute_counters then + let* counter = Context.Contract.counter ctxt source in + (* Update counters and transform into a contents_list *) + let _, rev_operations = + List.fold_left + (fun (counter, acc) -> function + | Contents (Manager_operation m) -> + ( Manager_counter.succ counter, + Contents (Manager_operation {m with counter}) :: acc ) + | x -> (counter, x :: acc)) + (Manager_counter.succ counter, []) + operations + in + return (List.rev rev_operations) + else return operations + in + let* account = Context.Contract.manager ctxt source in + let*?@ operations = Operation.of_list operations in + return @@ sign account.sk (Context.branch ctxt) operations + +type gas_limit = Max | High | Low | Zero | Custom_gas of Gas.Arith.integral + +let default_low_gas_limit op pkh = + let {shell; protocol_data = Operation_data protocol_data} = op in + let op : _ operation = {shell; protocol_data} in + let check_sig_gas = + Operation_costs.check_signature_cost + (Michelson_v1_gas.Cost_of.Interpreter.algo_of_public_key_hash pkh) + op + in + let total_cost = + Gas.(Michelson_v1_gas.Cost_of.manager_operation +@ check_sig_gas) + in + (* Some tests need milligas precision to distinguish failures in + validation from failures in application but limits in the + protocol are statically guaranteed to be integral values so we + use Obj.magic to bypass them. *) + (Obj.magic total_cost : Gas.Arith.integral) + +let default_high_gas_limit = + Gas.Arith.integral_of_int_exn + (49_000 + Michelson_v1_gas.Internal_for_tests.int_cost_of_manager_operation) + +let resolve_gas_limit ?(force_reveal = false) ctxt op source gas_limit = + let open Lwt_result_syntax in + let pkh = Context.Contract.pkh source in + let* revealed = Context.Contract.is_manager_key_revealed ctxt source in + match gas_limit with + | Max -> + let* c = Context.get_constants ctxt in + return (c.parametric.hard_gas_limit_per_operation, None) + | High -> return (default_high_gas_limit, None) + | Low when force_reveal && not revealed -> + (* If force reveal is set, the operation is a batch where the reveal is + the first operation. This operation should have a gas_limit + corresponding to the manager_operation constant (Low) + the cost of the + signature checking. The second op should only have Low as gas_limit *) + let op_gas : Gas.Arith.integral = + Obj.magic Michelson_v1_gas.Cost_of.manager_operation + in + return (op_gas, Some (default_low_gas_limit op pkh)) + | Low -> return (default_low_gas_limit op pkh, None) + | Zero -> return (Gas.Arith.zero, None) + | Custom_gas x -> return (x, None) + +let pp_gas_limit fmt = function + | Max -> Format.fprintf fmt "Max" + | High -> + Format.fprintf fmt "High: %a" Gas.Arith.pp_integral default_high_gas_limit + | Low -> Format.fprintf fmt "Low" + | Zero -> Format.fprintf fmt "Zero: %a" Gas.Arith.pp_integral Gas.Arith.zero + | Custom_gas x -> Format.fprintf fmt "Custom: %a" Gas.Arith.pp_integral x + +let combine_operations ?public_key ?counter ?spurious_operation ~source ctxt + (packed_operations : packed_operation list) = + let open Lwt_result_wrap_syntax in + assert (match packed_operations with [] -> false | _ :: _ -> true) ; + (* Hypothesis : each operation must have the same branch (is this really true?) *) + let {Tezos_base.Operation.branch} = + (WithExceptions.Option.get ~loc:__LOC__ @@ List.hd packed_operations).shell + in + assert ( + List.for_all + (fun {shell = {Tezos_base.Operation.branch = b; _}; _} -> + Block_hash.(branch = b)) + packed_operations) ; + (* TODO? : check signatures consistency *) + let unpacked_operations = + List.map + (function + | {Alpha_context.protocol_data = Operation_data {contents; _}; _} -> ( + match Contents_list contents with + | Contents_list (Single o) -> Contents o + | Contents_list + (Cons (Manager_operation {operation = Reveal _; _}, Single o)) + -> + Contents o + | _ -> (* TODO : decent error *) assert false)) + packed_operations + in + let* counter = + match counter with + | Some counter -> return counter + | None -> Context.Contract.counter ctxt source + in + (* We increment the counter *) + let counter = Manager_counter.succ counter in + let* account = Context.Contract.manager ctxt source in + let public_key = Option.value ~default:account.pk public_key in + let* manager_op, counter = + let+ is_revealed = Context.Contract.is_manager_key_revealed ctxt source in + match is_revealed with + | false -> + let reveal_op = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee = Tez.zero; + counter; + operation = Reveal public_key; + gas_limit = default_high_gas_limit; + storage_limit = Z.zero; + } + in + (Some (Contents reveal_op), Manager_counter.succ counter) + | true -> (None, counter) + in + (* Update counters and transform into a contents_list *) + let counter, rev_operations = + List.fold_left + (fun (counter, acc) -> function + | Contents (Manager_operation m) -> + ( Manager_counter.succ counter, + Contents (Manager_operation {m with counter}) :: acc ) + | x -> (counter, x :: acc)) + (counter, match manager_op with None -> [] | Some op -> [op]) + unpacked_operations + in + let operations = List.rev rev_operations in + (* patch a random operation with a corrupted pkh *) + let operations = + match spurious_operation with + | None -> operations + | Some op -> + let op = + match op with + | {protocol_data; shell = _} -> ( + match protocol_data with + | Operation_data {contents; _} -> ( + match contents with + | Cons _ -> assert false + | Single (Manager_operation m) -> + Alpha_context.Contents + (Manager_operation {m with counter}) + | Single op -> Contents op)) + in + (* Insert at the end *) + operations @ [op] + in + let*?@ operations = Operation.of_list operations in + return @@ sign account.sk (Context.branch ctxt) operations + +let manager_operation_with_fixed_gas_limit ?(force_reveal = false) ?counter + ~gas_limit ?(reveal_gas_limit = default_high_gas_limit) ?(fee = Tez.zero) + ?storage_limit ?public_key ~source ctxt operation = + let open Lwt_result_syntax in + let* counter = + match counter with + | Some counter -> return counter + | None -> Context.Contract.counter ctxt source + in + let* c = Context.get_constants ctxt in + let storage_limit = + Option.value + ~default:c.parametric.hard_storage_limit_per_operation + storage_limit + in + let* account = Context.Contract.manager ctxt source in + let public_key = Option.value ~default:account.pk public_key in + let counter = Manager_counter.succ counter in + let+ revealed = Context.Contract.is_manager_key_revealed ctxt source in + (* If the manager is revealed or we are not forcing reveals, we + generate a singleton manager operation. *) + if revealed || not force_reveal then + let op = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee; + counter; + operation; + gas_limit; + storage_limit; + } + in + Contents_list (Single op) + (* Otherwise if the manager is unrevealed and we are + force_revaling managers by default, we pre-attach a revelation + for it. *) + else + let op_reveal = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee = Tez.zero; + counter; + operation = Reveal public_key; + gas_limit = reveal_gas_limit; + storage_limit = Z.zero; + } + in + let op = + Manager_operation + { + source = Signature.Public_key.hash public_key; + fee; + counter = Manager_counter.succ counter; + operation; + gas_limit; + storage_limit; + } + in + Contents_list (Cons (op_reveal, Single op)) + +let manager_operation ?force_reveal ?counter ?fee ?(gas_limit = High) + ?storage_limit ?public_key ~source ctxt operation = + let open Lwt_result_syntax in + let default_gas_limit = default_high_gas_limit in + let* (Contents_list dummy_operation) = + manager_operation_with_fixed_gas_limit + ?force_reveal + ?counter + ~gas_limit:default_gas_limit + ?fee + ?storage_limit + ?public_key + ~source + ctxt + operation + in + let* gas_limit, reveal_gas_limit = + resolve_gas_limit + ?force_reveal + ctxt + { + shell = {branch = Context.branch ctxt}; + protocol_data = + Operation_data {contents = dummy_operation; signature = None}; + } + source + gas_limit + in + manager_operation_with_fixed_gas_limit + ?force_reveal + ?counter + ~gas_limit + ?reveal_gas_limit + ?fee + ?storage_limit + ?public_key + ~source + ctxt + operation + +let revelation_with_fixed_gas_limit ?(fee = Tez.zero) ~gas_limit + ?(storage_limit = Z.zero) ?counter ?(forge_pkh = None) ctxt public_key = + let open Lwt_result_syntax in + (* If Some pkh is provided to ?forge_pkh we take that hash at face + value, otherwise we honestly compute the hash from + [public_key]. This is useful to test forging Reveal operations + (cf. tezos!5182). *) + let pkh = + match forge_pkh with + | Some pkh -> pkh + | None -> Signature.Public_key.hash public_key + in + let source = Contract.Implicit pkh in + let+ counter = + match counter with + | None -> Context.Contract.counter ctxt source + | Some ctr -> return ctr + in + let counter = Manager_counter.succ counter in + Manager_operation + { + source = pkh; + fee; + counter; + operation = Reveal public_key; + gas_limit; + storage_limit; + } + +let revelation ?fee ?(gas_limit = High) ?storage_limit ?counter ?forge_pkh ctxt + public_key = + let open Lwt_result_syntax in + let* (Manager_operation {source; _} as dummy_operation) = + revelation_with_fixed_gas_limit + ?fee + ~gas_limit:default_high_gas_limit + ?storage_limit + ?counter + ?forge_pkh + ctxt + public_key + in + let* gas_limit, _ = + resolve_gas_limit + ctxt + { + shell = {branch = Context.branch ctxt}; + protocol_data = + Operation_data {contents = Single dummy_operation; signature = None}; + } + (Contract.Implicit source) + gas_limit + in + let* op = + revelation_with_fixed_gas_limit + ?fee + ~gas_limit + ?storage_limit + ?counter + ?forge_pkh + ctxt + public_key + in + let sop = Contents_list (Single op) in + let+ account = Context.Contract.manager ctxt (Implicit source) in + sign account.sk (Context.branch ctxt) sop + +let failing_noop ctxt source arbitrary = + let open Lwt_result_syntax in + let op = Contents_list (Single (Failing_noop arbitrary)) in + let* account = Account.find source in + return @@ sign account.sk (Context.branch ctxt) op + +let originated_contract_hash op = + let nonce = Protocol.Origination_nonce.initial (Operation.hash_packed op) in + Contract_hash.of_nonce nonce + +let originated_contract op = Contract.Originated (originated_contract_hash op) + +exception Impossible + +let contract_origination_gen k ?force_reveal ?counter ?delegate ~script + ?public_key ?credit ?fee ?gas_limit ?storage_limit ctxt source = + let open Lwt_result_syntax in + let* account = Context.Contract.manager ctxt source in + let default_credit = Tez.of_mutez @@ Int64.of_int 1000001 in + let default_credit = + WithExceptions.Option.to_exn ~none:Impossible default_credit + in + let credit = Option.value ~default:default_credit credit in + let operation = Origination {delegate; script; credit} in + let+ sop = + manager_operation + ?force_reveal + ?counter + ?public_key + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + operation + in + k (sign account.sk (Context.branch ctxt) sop) + +let contract_origination = + contract_origination_gen (fun op -> (op, originated_contract op)) + +let contract_origination_hash = + contract_origination_gen (fun op -> (op, originated_contract_hash op)) + +let register_global_constant ?force_reveal ?counter ?public_key ?fee ?gas_limit + ?storage_limit ctxt ~source ~value = + let open Lwt_result_syntax in + let* account = Context.Contract.manager ctxt source in + let operation = Register_global_constant {value} in + let+ sop = + manager_operation + ?force_reveal + ?counter + ?public_key + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + operation + in + sign account.sk (Context.branch ctxt) sop + +let unsafe_transaction ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ?(parameters = Script.unit_parameter) ?(entrypoint = Entrypoint.default) + ctxt (src : Contract.t) (destination : Contract.t) (amount : Tez.t) = + let open Lwt_result_syntax in + let top = Transaction {amount; parameters; destination; entrypoint} in + let* sop = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + top + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) sop + +let transaction ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ?parameters ?entrypoint ctxt (src : Contract.t) (dst : Contract.t) + (amount : Tez.t) = + unsafe_transaction + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ?parameters + ?entrypoint + ctxt + src + dst + amount + +let delegation ?force_reveal ?fee ?gas_limit ?counter ?storage_limit ctxt source + dst = + let open Lwt_result_syntax in + let top = Delegation dst in + let* sop = + manager_operation + ?force_reveal + ?fee + ?counter + ?gas_limit + ?storage_limit + ~source + ctxt + top + in + let+ account = Context.Contract.manager ctxt source in + sign account.sk (Context.branch ctxt) sop + +let set_deposits_limit ?force_reveal ?fee ?gas_limit ?storage_limit ?counter + ctxt source limit = + let open Lwt_result_syntax in + let top = Set_deposits_limit limit in + let* sop = + manager_operation + ?force_reveal + ?fee + ?counter + ?storage_limit + ?gas_limit + ~source + ctxt + top + in + let+ account = Context.Contract.manager ctxt source in + sign account.sk (Context.branch ctxt) sop + +let increase_paid_storage ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ctxt ~source ~destination (amount : Z.t) = + let open Lwt_result_syntax in + let top = Increase_paid_storage {amount_in_bytes = amount; destination} in + let* sop = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + top + in + let+ account = Context.Contract.manager ctxt source in + sign account.sk (Context.branch ctxt) sop + +let activation ctxt (pkh : Signature.Public_key_hash.t) activation_code = + let open Lwt_result_syntax in + let+ id = + match pkh with + | Ed25519 edpkh -> return edpkh + | _ -> + failwith + "Wrong public key hash : %a - Commitments must be activated with an \ + Signature.Ed25519 encrypted public key hash" + Signature.Public_key_hash.pp + pkh + in + let contents = Single (Activate_account {id; activation_code}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let double_attestation ctxt op1 op2 = + let contents = Single (Double_attestation_evidence {op1; op2}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let double_preattestation ctxt op1 op2 = + let contents = Single (Double_preattestation_evidence {op1; op2}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let double_baking ctxt bh1 bh2 = + let contents = Single (Double_baking_evidence {bh1; bh2}) in + let branch = Context.branch ctxt in + { + shell = {branch}; + protocol_data = Operation_data {contents; signature = None}; + } + +let seed_nonce_revelation ctxt level nonce = + { + shell = {branch = Context.branch ctxt}; + protocol_data = + Operation_data + { + contents = Single (Seed_nonce_revelation {level; nonce}); + signature = None; + }; + } + +let vdf_revelation ctxt solution = + { + shell = {branch = Context.branch ctxt}; + protocol_data = + Operation_data + {contents = Single (Vdf_revelation {solution}); signature = None}; + } + +let get_period ?period ctxt = + let open Lwt_result_syntax in + match period with + | Some period -> return period + | None -> + let* current_period = Context.Vote.get_current_period ctxt in + return current_period.voting_period.index + +let proposals_contents ctxt proposer ?period proposals = + let open Lwt_result_syntax in + let source = Context.Contract.pkh proposer in + let* period = get_period ?period ctxt in + return (Single (Proposals {source; period; proposals})) + +let proposals ctxt proposer ?period proposals = + let open Lwt_result_syntax in + let* contents = proposals_contents ctxt proposer ?period proposals in + let* account = Account.find (Context.Contract.pkh proposer) in + return (sign account.sk (Context.branch ctxt) (Contents_list contents)) + +let ballot_contents ctxt voter ?period proposal ballot = + let open Lwt_result_syntax in + let source = Context.Contract.pkh voter in + let* period = get_period ?period ctxt in + return (Single (Ballot {source; period; proposal; ballot})) + +let ballot ctxt voter ?period proposal ballot = + let open Lwt_result_syntax in + let* contents = ballot_contents ctxt voter ?period proposal ballot in + let* account = Account.find (Context.Contract.pkh voter) in + return (sign account.sk (Context.branch ctxt) (Contents_list contents)) + +let dummy_script = + let open Micheline in + Script. + { + code = + lazy_expr + (strip_locations + (Seq + ( (), + [ + Prim ((), K_parameter, [Prim ((), T_unit, [], [])], []); + Prim ((), K_storage, [Prim ((), T_unit, [], [])], []); + Prim + ( (), + K_code, + [ + Seq + ( (), + [ + Prim ((), I_CDR, [], []); + Prim + ( (), + I_NIL, + [Prim ((), T_operation, [], [])], + [] ); + Prim ((), I_PAIR, [], []); + ] ); + ], + [] ); + ] ))); + storage = lazy_expr (strip_locations (Prim ((), D_Unit, [], []))); + } + +let dummy_script_cost = Test_tez.of_mutez_exn 9_500L + +let transfer_ticket ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + ~(source : Contract.t) ~contents ~ty ~ticketer ~amount ~destination + ~entrypoint = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + (Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint}) + in + let+ account = Context.Contract.manager ctxt source in + sign account.sk (Context.branch ctxt) to_sign_op + +let originated_sc_rollup op = + let packed = Operation.hash_packed op in + let nonce = Origination_nonce.Internal_for_tests.initial packed in + Sc_rollup.Internal_for_tests.originated_sc_rollup nonce + +let sc_rollup_origination ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ?whitelist ctxt (src : Contract.t) kind ~boot_sector ~parameters_ty = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist}) + in + let* account = Context.Contract.manager ctxt src in + let op = sign account.sk (Context.branch ctxt) to_sign_op in + let t = originated_sc_rollup op |> fun addr -> (op, addr) in + return t + +let sc_rollup_publish ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) rollup commitment = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_publish {rollup; commitment}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let sc_rollup_cement ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) rollup = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_cement {rollup}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let sc_rollup_execute_outbox_message ?counter ?fee ?gas_limit ?storage_limit + ?force_reveal ctxt (src : Contract.t) rollup cemented_commitment + ~output_proof = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let sc_rollup_recover_bond ?counter ?fee ?gas_limit ?storage_limit ?force_reveal + ctxt (source : Contract.t) (sc_rollup : Sc_rollup.t) + (staker : public_key_hash) = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source + ctxt + (Sc_rollup_recover_bond {sc_rollup; staker}) + in + let+ account = Context.Contract.manager ctxt source in + sign account.sk (Context.branch ctxt) to_sign_op + +let sc_rollup_add_messages ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ctxt (src : Contract.t) messages = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_add_messages {messages}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let sc_rollup_refute ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) rollup opponent refutation = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_refute {rollup; opponent; refutation}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let sc_rollup_timeout ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) rollup stakers = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Sc_rollup_timeout {rollup; stakers}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let dal_publish_commitment ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ctxt (src : Contract.t) slot_header = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Dal_publish_commitment slot_header) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let originated_zk_rollup op = + let packed = Operation.hash_packed op in + let nonce = Origination_nonce.Internal_for_tests.initial packed in + Zk_rollup.Internal_for_tests.originated_zk_rollup nonce + +let zk_rollup_origination ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ctxt (src : Contract.t) ~public_parameters ~circuits_info ~init_state + ~nb_ops = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Zk_rollup_origination + {public_parameters; circuits_info; init_state; nb_ops}) + in + let+ account = Context.Contract.manager ctxt src in + let op = sign account.sk (Context.branch ctxt) to_sign_op in + originated_zk_rollup op |> fun addr -> (op, addr) + +let update_consensus_key ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ctxt (src : Contract.t) pkh = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Update_consensus_key pkh) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let drain_delegate ctxt ~consensus_key ~delegate ~destination = + let open Lwt_result_syntax in + let contents = + Single (Drain_delegate {consensus_key; delegate; destination}) + in + let+ account = + Context.Contract.manager ctxt (Contract.Implicit consensus_key) + in + sign account.sk (Context.branch ctxt) (Contents_list contents) + +let zk_rollup_publish ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) ~zk_rollup ~ops = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Zk_rollup_publish {zk_rollup; ops}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op + +let zk_rollup_update ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt + (src : Contract.t) ~zk_rollup ~update = + let open Lwt_result_syntax in + let* to_sign_op = + manager_operation + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ~source:src + ctxt + (Zk_rollup_update {zk_rollup; update}) + in + let+ account = Context.Contract.manager ctxt src in + sign account.sk (Context.branch ctxt) to_sign_op diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/op.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/op.mli new file mode 100644 index 000000000000..5f39291b0461 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/op.mli @@ -0,0 +1,633 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/3181 + Improve documentation of the operation helpers *) + +(** Assemble the given signature and [contents_list] into a + [packed_operation]. + + The context argument is used to retrieve the branch. + + If the [signature option] argument is [None], then the resulting + operation is unsigned. + + This function is mainly useful to craft an operation with a + missing or invalid signatue. Otherwise, it is often better to use + one of the helpers below: they handle the signature internally to + directly return well-signed operations. *) +val pack_operation : + Context.t -> signature option -> 'a contents_list -> packed_operation + +val sign : + ?watermark:Signature.watermark -> + Signature.secret_key -> + Block_hash.t -> + packed_contents_list -> + packed_operation + +(** Create an unpacked attestation that is expected for given [Block.t]. + + Optional parameters allow to specify the attested values: [level], + [round], [block_payload_hash], and/or [dal_content]. + + They also allow to specify the attester ([delegate]), and/or the + [slot]. These default to the first slot and its delegate. + + Finally, the operation [branch] can be specified. It defaults to the + predecessor of the attested block. *) +val raw_attestation : + ?delegate:public_key_hash -> + ?slot:Slot.t -> + ?level:Raw_level.t -> + ?round:Round.t -> + ?block_payload_hash:Block_payload_hash.t -> + ?dal_content:dal_content -> + ?branch:Block_hash.t -> + Block.t -> + Kind.attestation Operation.t tzresult Lwt.t + +(** Create an unpacked preattestation that is expected for a given + [Block.t]. + + Optional parameters are the same than {!raw_attestation}. *) +val raw_preattestation : + ?delegate:public_key_hash -> + ?slot:Slot.t -> + ?level:Raw_level.t -> + ?round:Round.t -> + ?block_payload_hash:Block_payload_hash.t -> + ?branch:Block_hash.t -> + Block.t -> + Kind.preattestation Operation.t tzresult Lwt.t + +(** Create a packed attestation that is expected for a given + [Block.t] by packing the result of {!raw_attestation}. *) +val attestation : + ?delegate:public_key_hash -> + ?slot:Slot.t -> + ?level:Raw_level.t -> + ?round:Round.t -> + ?block_payload_hash:Block_payload_hash.t -> + ?dal_content:dal_content -> + ?branch:Block_hash.t -> + Block.t -> + Operation.packed tzresult Lwt.t + +(** Create a packed preattestation that is expected for a given + [Block.t] by packing the result of {!raw_preattestation}. *) +val preattestation : + ?delegate:public_key_hash -> + ?slot:Slot.t -> + ?level:Raw_level.t -> + ?round:Round.t -> + ?block_payload_hash:Block_payload_hash.t -> + ?branch:Block_hash.t -> + Block.t -> + Operation.packed tzresult Lwt.t + +type gas_limit = + | Max (** Max corresponds to the [max_gas_limit_per_operation] constant. *) + | High + (** High corresponds to [50_000] gas unit which should cover a + majority of use-cases. This is the default used when forging + manager operations. *) + | Low (** Low corresponds to the gas entry cost of a manager operation *) + | Zero + | Custom_gas of Gas.Arith.integral + +(** Pretty printer for gas_limit type. *) +val pp_gas_limit : Format.formatter -> gas_limit -> unit + +val transaction : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?parameters:Script.lazy_expr -> + ?entrypoint:Entrypoint.t -> + Context.t -> + Contract.t -> + Contract.t -> + Tez.t -> + Operation.packed tzresult Lwt.t + +(** Same as [transaction], but with a more generic destination + parameter. It is said unsafe because it can construct transactions + that will always fail, such as + + {ul {li Transaction to the deposit entrypoint of a transaction + rollup, as these transactions are necessarily internals.}} + + Optional arguments allow to override defaults: + + {ul {li [?force_reveal:bool]: prepend the operation to reveal + [source]'s public key if the latter has not been revealed + yet. Disabled (set to [false]) by default.}} *) +val unsafe_transaction : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?parameters: + Michelson_v1_primitives.prim Micheline.canonical Data_encoding.lazy_t -> + ?entrypoint:Entrypoint_repr.t -> + Context.t -> + Contract.t -> + Contract.t -> + Tez.t -> + packed_operation tzresult Lwt.t + +val delegation : + ?force_reveal:bool -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?counter:Manager_counter.t -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + public_key_hash option -> + Operation.packed tzresult Lwt.t + +val set_deposits_limit : + ?force_reveal:bool -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + Context.t -> + Contract.t -> + Tez.t option -> + Operation.packed tzresult Lwt.t + +val increase_paid_storage : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + source:Contract.t -> + destination:Contract_hash.t -> + Z.t -> + Operation.packed tzresult Lwt.t + +(** [revelation ?fee ?gas_limit ?forge_pkh ctxt pkh] Creates a new + [Reveal] {!manager_operation} to reveal a public key [pkh] + applying to current context [ctxt]. + + Optional arguments allow to override defaults: + + {ul {li [?fee:Tez.t]: specify a fee, otherwise set to + [Tez.zero].} + + {li [?gas_limit:Gas.Arith.integral]: force a gas limit, otherwise + set to 10000 gas units.} + + {li [?forge_pkh]: use a provided [pkh] as source, instead of + hashing [pkh]. Useful for forging non-honest reveal operations} + + {li [?storage_limit:Z.t]: forces a storage limit, otherwise + set to [Z.zero]}} +*) +val revelation : + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?counter:Manager_counter.t -> + ?forge_pkh:public_key_hash option -> + Context.t -> + public_key -> + (packed_operation, tztrace) result Lwt.t + +val failing_noop : + Context.t -> public_key_hash -> string -> Operation.packed tzresult Lwt.t + +(** [contract_origination ctxt source] Create a new contract origination + operation, sign it with [source] and returns it alongside the contract + address. The contract address is using the initial origination nonce with the + hash of the operation. If this operation is combined with [combine_operations] + then the contract address is false as the nonce is not based on the correct + operation hash. + + Optional arguments allow to override defaults: + + {ul {li [?force_reveal:bool]: prepend the operation to reveal + [source]'s public key if the latter has not been revealed + yet. Disabled (set to [false]) by default.}} *) +val contract_origination : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?delegate:public_key_hash -> + script:Script.t -> + ?public_key:public_key -> + ?credit:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + (Operation.packed * Contract.t) tzresult Lwt.t + +val contract_origination_hash : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?delegate:public_key_hash -> + script:Script.t -> + ?public_key:public_key -> + ?credit:Tez.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + (Operation.packed * Contract_hash.t) tzresult Lwt.t + +val originated_contract : Operation.packed -> Contract.t + +val register_global_constant : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?public_key:Signature.public_key -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + (* Account doing the registration *) + source:Contract.t -> + (* Micheline value to be registered *) + value:Protocol.Alpha_context.Script.lazy_expr -> + (Protocol.operation, tztrace) result Lwt.t + +val double_attestation : + Context.t -> + Kind.attestation Operation.t -> + Kind.attestation Operation.t -> + Operation.packed + +val double_preattestation : + Context.t -> + Kind.preattestation Operation.t -> + Kind.preattestation Operation.t -> + Operation.packed + +val double_baking : + Context.t -> + Block_header.block_header -> + Block_header.block_header -> + Operation.packed + +val activation : + Context.t -> + Signature.Public_key_hash.t -> + Blinded_public_key_hash.activation_code -> + Operation.packed tzresult Lwt.t + +val combine_operations : + ?public_key:public_key -> + ?counter:Manager_counter.t -> + ?spurious_operation:packed_operation -> + source:Contract.t -> + Context.t -> + packed_operation list -> + packed_operation tzresult Lwt.t + +(** Batch a list of (already signed) operations and (re-)sign with the + [source]. No revelation is inserted and the counters are kept as + they are unless [recompute_counters] is set to [true] (defaults false). *) +val batch_operations : + ?recompute_counters:bool -> + source:Contract.t -> + Context.t -> + packed_operation list -> + packed_operation tzresult Lwt.t + +(** Reveals a seed_nonce that was previously committed at a certain level *) +val seed_nonce_revelation : + Context.t -> Raw_level.t -> Nonce.t -> Operation.packed + +(** Reveals a VDF with a proof of correctness *) +val vdf_revelation : Context.t -> Seed.vdf_solution -> Operation.packed + +(** Craft the [contents_list] for a Proposals operation. + + Invocation: [proposals_contents ctxt source ?period proposals]. + + @param period defaults to the index of the current voting period + in [ctxt]. *) +val proposals_contents : + Context.t -> + Contract.t -> + ?period:int32 -> + Protocol_hash.t list -> + Kind.proposals contents_list tzresult Lwt.t + +(** Craft a Proposals operation. + + Invocation: [proposals ctxt source ?period proposals]. + + @param period defaults to the index of the current voting period + in [ctxt]. *) +val proposals : + Context.t -> + Contract.t -> + ?period:int32 -> + Protocol_hash.t list -> + Operation.packed tzresult Lwt.t + +(** Craft the [contents_list] for a Ballot operation. + + Invocation: [ballot_contents ctxt source ?period proposal ballot]. + + @param period defaults to the index of the current voting period + in [ctxt]. *) +val ballot_contents : + Context.t -> + Contract.t -> + ?period:int32 -> + Protocol_hash.t -> + Vote.ballot -> + Kind.ballot contents_list tzresult Lwt.t + +(** Craft a Ballot operation. + + Invocation: [ballot ctxt source ?period proposal ballot]. + + @param period defaults to the index of the current voting period + in [ctxt]. *) +val ballot : + Context.t -> + Contract.t -> + ?period:int32 -> + Protocol_hash.t -> + Vote.ballot -> + Operation.packed tzresult Lwt.t + +val dummy_script : Script.t + +val dummy_script_cost : Tez.t + +(** [transfer_ticket] allows an implicit account to transfer tickets they owned. + + The arguments are: + + {ul + {li [Context.t]: the context on which to apply the operation} + {li [source:Contract.t]: the source contract of the operation} + {li [Tx_rollup.t]: the rollup to which the withdrawal pertains} + {li [Tx_rollup_level.t]: the level on which the withdrawal was commited} + {li [contents:Script.lazy_expr]: the contents of the ticket of + the withdrawal} + {li [ty:Script.lazy_expr]: the type of the ticket of the withdrawal} + {li [ticketer:Contract.t]: the ticketer of the ticket of the withdrawal} + {li [Z.t]: the quantity of the ticket of the withdrawal} + {li [destination:Contract.t]: the destination contract that + should receive the ticket of the withdrawal} + {li [Entrypoint_repr.t]: the entrypoint of the destination + contract to which the ticket should be sent}} + + Optional arguments allow to override defaults: + + {ul {li [?force_reveal:bool]: prepend the operation to reveal + [source]'s public key if the latter has not been revealed + yet. Disabled (set to [false]) by default.}} *) +val transfer_ticket : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + source:Contract.t -> + contents:Script.lazy_expr -> + ty:Script.lazy_expr -> + ticketer:Contract.t -> + amount:Ticket_amount.t -> + destination:Contract.t -> + entrypoint:Entrypoint_repr.t -> + (packed_operation, tztrace) result Lwt.t + +(** [sc_rollup_origination ctxt source kind boot_sector] originates a + new smart contract rollup of some given [kind] booting using + [boot_sector]. + + Optional arguments allow to override defaults: + + {ul {li [?force_reveal:bool]: prepend the operation to reveal + [source]'s public key if the latter has not been revealed + yet. Disabled (set to [false]) by default.}} *) +val sc_rollup_origination : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?whitelist:Sc_rollup.Whitelist.t -> + Context.t -> + Contract.t -> + Sc_rollup.Kind.t -> + boot_sector:string -> + parameters_ty:Script.lazy_expr -> + (packed_operation * Sc_rollup.t) tzresult Lwt.t + +(** [sc_rollup_publish ctxt source rollup commitment] tries to publish + a commitment to the SCORU. Optional arguments allow to override + defaults: + + Optional arguments allow to override defaults: + + {ul {li [?force_reveal:bool]: prepend the operation to reveal + [source]'s public key if the latter has not been revealed + yet. Disabled (set to [false]) by default.}} *) +val sc_rollup_publish : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + Sc_rollup.t -> + Sc_rollup.Commitment.t -> + Operation.packed tzresult Lwt.t + +(** [sc_rollup_cement ctxt source rollup] tries to cement a commitment. + + Optional arguments allow to override defaults: + + {ul {li [?force_reveal:bool]: prepend the operation to reveal + [source]'s public key if the latter has not been revealed + yet. Disabled (set to [false]) by default.}} *) +val sc_rollup_cement : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + Sc_rollup.t -> + Operation.packed tzresult Lwt.t + +val sc_rollup_execute_outbox_message : + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?force_reveal:bool -> + Context.t -> + Contract.t -> + Sc_rollup.t -> + Sc_rollup.Commitment.Hash.t -> + output_proof:string -> + (packed_operation, tztrace) result Lwt.t + +(** [sc_rollup_recover_bond ctxt source sc_rollup staker] recovers the + commitment bond of [staker]. *) +val sc_rollup_recover_bond : + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?force_reveal:bool -> + Context.t -> + Contract.t -> + Sc_rollup.t -> + public_key_hash -> + Operation.packed tzresult Lwt.t + +val sc_rollup_add_messages : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + string list -> + Operation.packed tzresult Lwt.t + +val sc_rollup_refute : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + Sc_rollup.t -> + public_key_hash -> + Sc_rollup.Game.refutation -> + Operation.packed tzresult Lwt.t + +val sc_rollup_timeout : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + Sc_rollup.t -> + Sc_rollup.Game.Index.t -> + Operation.packed tzresult Lwt.t + +val dal_publish_commitment : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + Dal.Operations.Publish_commitment.t -> + (packed_operation, tztrace) result Lwt.t + +(** [zk_rollup_origination ctxt source ~public_parameters ~circuits_info + ~init_state ~nb_ops] tries to originate a ZK Rollup. *) +val zk_rollup_origination : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + public_parameters:Plonk.Main_protocol.verifier_public_parameters -> + circuits_info:[`Public | `Private | `Fee] Zk_rollup.Account.SMap.t -> + init_state:Zk_rollup.State.t -> + nb_ops:int -> + (Operation.packed * Zk_rollup.t) tzresult Lwt.t + +val update_consensus_key : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + public_key -> + (packed_operation, tztrace) result Lwt.t + +val drain_delegate : + Context.t -> + consensus_key:Signature.Public_key_hash.t -> + delegate:Signature.Public_key_hash.t -> + destination:Signature.Public_key_hash.t -> + packed_operation tzresult Lwt.t + +(** [zk_rollup_publish ctxt source ~zk_rollup ~op] tries to add an operation + to the pending list of a ZK Rollup. *) +val zk_rollup_publish : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + zk_rollup:Zk_rollup.t -> + ops:(Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list -> + Operation.packed tzresult Lwt.t + +(** [zk_rollup_update ctxt source ~zk_rollup ~update] tries to apply an update + to a ZK Rollup. *) +val zk_rollup_update : + ?force_reveal:bool -> + ?counter:Manager_counter.t -> + ?fee:Tez.t -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + Context.t -> + Contract.t -> + zk_rollup:Zk_rollup.t -> + update:Zk_rollup.Update.t -> + Operation.packed tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/operation_generator.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/operation_generator.ml new file mode 100644 index 000000000000..587f3f109276 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/operation_generator.ml @@ -0,0 +1,726 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** These generators aims at generating operations which are not + necessary correct. The goal is to tests functions such as {! + Operation.compare} with as much as possible parameters that play a + role in operation [weight] computation. + + When adding a new operation, one should also add its weight + computation, hence knows which kind of generator should be provided + for this new operation.*) + +open Protocol +open Alpha_context + +(** {2 Operations kind labelling.} *) + +let consensus_pass = `PConsensus + +let anonymous_pass = `PAnonymous + +let vote_pass = `PVote + +let manager_pass = `PManager + +let all_passes = [`PConsensus; `PAnonymous; `PVote; `PManager] + +let all_non_manager_passes = [`PConsensus; `PAnonymous; `PVote] + +let consensus_kinds = [`KPreattestation; `KAttestation] + +let anonymous_kinds = + [ + `KSeed_nonce_revelation; + `KVdf_revelation; + `KDouble_attestation; + `KDouble_preattestation; + `KDouble_baking; + `KActivate_account; + ] + +let vote_kinds = [`KProposals; `KBallot] + +(* N.b. we do not consider Failing_noop as those will never be valid. *) +let manager_kinds = + [ + `KReveal; + `KTransaction; + `KOrigination; + `KDelegation; + `KSet_deposits_limit; + `KIncrease_paid_storage; + `KRegister_global_constant; + `KTransfer_ticket; + `KDal_publish_commitment; + `KSc_rollup_originate; + `KSc_rollup_add_messages; + `KSc_rollup_cement; + `KSc_rollup_publish; + `KSc_rollup_refute; + `KSc_rollup_timeout; + `KSc_rollup_execute_outbox_message; + `KSc_rollup_recover_bond; + ] + +let pass_to_operation_kinds = function + | `PConsensus -> consensus_kinds + | `PVote -> vote_kinds + | `PAnonymous -> anonymous_kinds + | `PManager -> [`KManager] + +let pp_kind fmt k = + Format.fprintf + fmt + "%s" + (match k with + | `KPreattestation -> "KPreattestation" + | `KAttestation -> "KAttestation" + | `KDal_attestation -> "KDal_attestation" + | `KSeed_nonce_revelation -> "KSeed_nonce_revelation" + | `KVdf_revelation -> "KVdf_revelation" + | `KDouble_attestation -> "KDouble_attestation" + | `KDouble_preattestation -> "KDouble_preattestation" + | `KDouble_baking -> "KDouble_baking" + | `KActivate_account -> "KActivate_account" + | `KProposals -> "KProposals" + | `KBallot -> "KBallot" + | `KManager -> "KManager") + +(** {2 Generators} *) + +module Gen_hash (H : sig + type t + + val size : int + + val of_bytes_exn : bytes -> t +end) = +struct + let gen = + let open QCheck2.Gen in + let+ str = string_size (pure H.size) in + H.of_bytes_exn (Bytes.unsafe_of_string str) +end + +(** {3 Selection in hashes list} *) + +let gen_block_hash = + let module G = Gen_hash (Block_hash) in + G.gen + +let random_payload_hash = + let module G = Gen_hash (Block_payload_hash) in + G.gen + +let gen_algo = QCheck2.Gen.oneofl Signature.algos + +let random_seed = + let open QCheck2.Gen in + let+ str = string_size (pure Tezos_crypto.Hacl.Ed25519.sk_size) in + Bytes.unsafe_of_string str + +let random_keys = + let open QCheck2.Gen in + let* algo = gen_algo in + let+ seed = random_seed in + Signature.generate_key ~algo ~seed () + +let random_tz1 = + let open QCheck2.Gen in + let+ str = string_size (pure Signature.Ed25519.Public_key_hash.size) in + (Ed25519 (Signature.Ed25519.Public_key_hash.of_string_exn str) + : public_key_hash) + +let random_tz2 = + let open QCheck2.Gen in + let+ str = string_size (pure Signature.Secp256k1.Public_key_hash.size) in + (Secp256k1 (Signature.Secp256k1.Public_key_hash.of_string_exn str) + : public_key_hash) + +let random_tz3 = + let open QCheck2.Gen in + let+ str = string_size (pure Signature.P256.Public_key_hash.size) in + (P256 (Signature.P256.Public_key_hash.of_string_exn str) : public_key_hash) + +let random_tz4 = + let open QCheck2.Gen in + let+ str = string_size (pure Signature.Bls.Public_key_hash.size) in + (Bls (Signature.Bls.Public_key_hash.of_string_exn str) : public_key_hash) + +let random_pkh = + let open QCheck2.Gen in + let* algo = gen_algo in + match algo with + | Ed25519 -> random_tz1 + | Secp256k1 -> random_tz2 + | P256 -> random_tz3 + | Bls -> random_tz4 + +let random_pk = + let open QCheck2.Gen in + let+ _, pk, _ = random_keys in + pk + +let random_signature = + let open QCheck2.Gen in + let* algo = option ~ratio:0.8 gen_algo in + match algo with + | None -> + let+ str = string_size (pure Signature.Ed25519.size) in + (Unknown (Bytes.unsafe_of_string str) : Signature.t) + | Some Ed25519 -> + let+ str = string_size (pure Signature.Ed25519.size) in + (Ed25519 (Signature.Ed25519.of_string_exn str) : Signature.t) + | Some Secp256k1 -> + let+ str = string_size (pure Signature.Secp256k1.size) in + (Secp256k1 (Signature.Secp256k1.of_string_exn str) : Signature.t) + | Some P256 -> + let+ str = string_size (pure Signature.P256.size) in + (P256 (Signature.P256.of_string_exn str) : Signature.t) + | Some Bls -> + let+ seed = random_seed in + let _, _, sk = Signature.generate_key ~algo:Bls ~seed () in + Signature.sign sk Bytes.empty + +let random_signature = + let open QCheck2.Gen in + graft_corners + random_signature + Signature. + [ + of_ed25519 Signature.Ed25519.zero; + of_secp256k1 Signature.Secp256k1.zero; + of_p256 Signature.P256.zero; + of_bls Signature.Bls.zero; + Unknown (Bytes.make 64 '\000'); + ] + () + +let random_contract_hash = + let module G = Gen_hash (Contract_hash) in + G.gen + +let block_headers = + let bh1 = + {json|{ "level": 2, "proto": 1, "predecessor": "BLbcVY1kYiKQy2MJJfoHJMN2xRk5QPG1PEKWMDSyW2JMxBsMmiL", "timestamp": "2022-08-08T11:16:30Z", "validation_pass": 4, "operations_hash": "LLoa7bxRTKaQN2bLYoitYB6bU2DvLnBAqrVjZcvJ364cTcX2PZYKU", "fitness": [ "02", "00000002", "", "ffffffff", "00000001" ], "context": "CoUvpF8XBUfz3w9CJumt4ZKGZkrcdcfs1Qdrrd1ZeFij64E1QCud", "payload_hash": "vh2TyrWeZ2dydEy9ZjmvrjQvyCs5sdHZPypcZrXDUSM1tNuPermf", "payload_round": 1, "proof_of_work_nonce": "62de1e0d00000000", "liquidity_baking_toggle_vote": "pass", "adaptive_issuance_vote": "pass", "signature": "sigaXGo4DWsZwo1SvbKCp2hLgE5jcwd61Ufkc3iMt3sXy3NBj9jticuJKJnRhyH2ZPJQMwEuDqQTgZgoK5xRH6HeF7YxLb4u" }|json} + in + let bh2 = + {json|{ "level": 3, "proto": 1, "predecessor": "BLAUNUbzKHgA4DYQEXCbxY73wdE2roGAzvJJbFp8dQe62Ekpada", "timestamp": "2022-08-08T11:16:32Z", "validation_pass": 4, "operations_hash": "LLoaWjBX8Cm8DVpoLNtm7FPNnxUdL6Dakq122pVfNHYaf2rE9GQXi", "fitness": [ "02", "00000003", "", "fffffffe", "00000000" ], "context": "CoUtWowJUqXwMm4pbR1jjyFfVRHqRHGs6bYVDaaByvbmULoAND2x", "payload_hash": "vh1p1VzeYjZLEW6WDqdTwVy354KEmGCDgPmagEKcLN4NT4X58mNk", "payload_round": 0, "proof_of_work_nonce": "62de1e0d00000000", "liquidity_baking_toggle_vote": "pass", "adaptive_issuance_vote": "pass", "signature": "sigVqWWE7BPuxHqPWiVRmzQ1eMZZAPAxGJ94ytY2sjV8Y1Z4QH1F2bPGZS1ZeWDbqmcppPPFobRpi7wNasQ17Mm9CFGKag2t" }|json} + in + let bh3 = + {json|{ "level": 4, "proto": 1, "predecessor": "BLuurCvGmNPTzXSnGCpcFPy5h8A49PwH2LnfAWBnp5R1qv5czwe", "timestamp": "2022-08-08T11:16:33Z", "validation_pass": 4, "operations_hash": "LLoaf8AANzyNxhk715zykDrwG5Bpqw6FsZLWWNp2Dcm3ewFrcc3Wc", "fitness": [ "02", "00000004", "", "ffffffff", "00000000" ], "context": "CoVzxEBMDhxpGVxrguik6r5qVogJBFyhuvwm2KZBcsmvqhekPiwL", "payload_hash": "vh2gWcSUUhJBwvjx4vS7JN5ioMVWpHCSK6W2MKNPr5dn6NUdfFDQ", "payload_round": 0, "proof_of_work_nonce": "62de1e0d00000000", "seed_nonce_hash": "nceV3VjdHp1yk6uqcQicQBxLJY1AfWvLSabQpqnpiqkC1q2tS35EN", "liquidity_baking_toggle_vote": "pass", "adaptive_issuance_vote": "pass", "signature": "sigijumaDLSQwjh2AKK7af1VcEDsZsRwbweL8hF176puhHy3ySVocNCbrwPqJLiQP8EbqY5YL6z6b1vDaw12h8MQU2Rh4SW1" }|json} + in + List.map + (fun s -> + let open Data_encoding.Json in + from_string s |> function + | Ok json -> destruct Alpha_context.Block_header.encoding json + | Error _ -> assert false) + [bh1; bh2; bh3] + +let random_block_header = QCheck2.Gen.oneofl block_headers + +let random_sc_rollup = + let module G = Gen_hash (Sc_rollup.Address) in + G.gen + +let random_proto = + let module G = Gen_hash (Protocol_hash) in + G.gen + +let random_code = + let open QCheck2.Gen in + let+ str = string_size (pure Signature.Ed25519.Public_key_hash.size) in + let (`Hex hex) = Hex.of_string str in + Blinded_public_key_hash.activation_code_of_hex hex + |> WithExceptions.Option.get ~loc:__LOC__ + +(** {2 Operations parameters generators} *) + +let random_shell : Tezos_base.Operation.shell_header QCheck2.Gen.t = + let open QCheck2.Gen in + let+ branch = gen_block_hash in + Tezos_base.Operation.{branch} + +let gen_slot = + let open QCheck2.Gen in + let+ i = small_nat in + match Slot.Internal_for_tests.of_int i with + | Ok slot -> slot + | Error _ -> assert false + +let gen_level = + let open QCheck2.Gen in + let+ i = ui32 in + match Raw_level.of_int32 i with Ok v -> v | Error _ -> assert false + +let gen_round = + let open QCheck2.Gen in + let+ i = ui32 in + match Round.of_int32 i with Ok v -> v | Error _ -> assert false + +let generate_consensus_content : consensus_content QCheck2.Gen.t = + let open QCheck2.Gen in + let* slot = gen_slot in + let* level = gen_level in + let* round = gen_round in + let+ block_payload_hash = random_payload_hash in + {slot; level; round; block_payload_hash} + +let gen_tez = + let open QCheck2.Gen in + let+ i = ui64 in + match Tez.of_mutez i with None -> Tez.zero | Some v -> v + +let gen_fee = gen_tez + +let gen_amount = gen_tez + +let gen_amount_in_bytes = + let open QCheck2.Gen in + let+ i = nat in + Z.of_int i + +let random_contract = + let open QCheck2.Gen in + let* b = bool in + if b then + let+ pkh = random_pkh in + Contract.Implicit pkh + else + let+ contract_hash = random_contract_hash in + Contract.Originated contract_hash + +let gen_counters = + let open QCheck2.Gen in + let+ i = nat in + Manager_counter.Internal_for_tests.of_int i + +let gen_ticket_amounts = + let open QCheck2.Gen in + let+ i = nat in + Option.value (Ticket_amount.of_zint (Z.of_int i)) ~default:Ticket_amount.one + +let gen_gas_limit = + let open QCheck2.Gen in + let+ i = nat in + Gas.Arith.integral_of_int_exn i + +let gen_storage_limit = + let open QCheck2.Gen in + let+ i = nat in + Z.of_int i + +let nonces = + List.map + (fun i -> + let b = Bytes.create 32 in + Bytes.set_int8 b 0 i ; + Alpha_context.Nonce.of_bytes b |> function + | Ok v -> v + | Error _ -> assert false) + [1; 2; 3] + +let random_nonce = QCheck2.Gen.oneofl nonces + +let vdf_solutions = + let open Environment.Vdf in + let opt_assert = function Some v -> v | None -> assert false in + List.map + (fun i -> + let b = Bytes.create form_size_bytes in + Bytes.set_int8 b 0 i ; + let result = result_of_bytes_opt b |> opt_assert in + let proof = proof_of_bytes_opt b |> opt_assert in + (result, proof)) + [1; 2; 3] + +(** {2 Generators for each Operation Kind} *) + +let wrap_operation sh (pdata : 'kind protocol_data) : 'kind operation = + {shell = sh; protocol_data = pdata} + +let generate_op (gen_op : 'kind contents QCheck2.Gen.t) : + 'kind operation QCheck2.Gen.t = + let open QCheck2.Gen in + let* op = gen_op in + let* signature = option ~ratio:0.9 random_signature in + let+ shell = random_shell in + let contents = Single op in + let protocol_data = {contents; signature} in + wrap_operation shell protocol_data + +let generate_operation gen_op = + let open QCheck2.Gen in + let+ op = generate_op gen_op in + Operation.pack op + +let generate_preattestation = + let open QCheck2.Gen in + let+ cc = generate_consensus_content in + Preattestation cc + +let generate_attestation = + let open QCheck2.Gen in + let+ cc = generate_consensus_content in + Attestation {consensus_content = cc; dal_content = None} + +let generate_vdf_revelation = + let open QCheck2.Gen in + let+ solution = oneofl vdf_solutions in + Vdf_revelation {solution} + +let generate_seed_nonce_revelation = + let open QCheck2.Gen in + let* level = gen_level in + let+ nonce = random_nonce in + Seed_nonce_revelation {level; nonce} + +let generate_double_preattestation = + let open QCheck2.Gen in + let* op1 = generate_op generate_preattestation in + let+ op2 = generate_op generate_preattestation in + Double_preattestation_evidence {op1; op2} + +let generate_double_attestation = + let open QCheck2.Gen in + let* op1 = generate_op generate_attestation in + let+ op2 = generate_op generate_attestation in + Double_attestation_evidence {op1; op2} + +let generate_double_baking = + let open QCheck2.Gen in + let* bh1 = random_block_header in + let+ bh2 = random_block_header in + Double_baking_evidence {bh1; bh2} + +let generate_activate_account = + let open QCheck2.Gen in + let* activation_code = random_code in + let+ id = random_tz1 in + let id = match id with Signature.Ed25519 pkh -> pkh | _ -> assert false in + Activate_account {id; activation_code} + +let random_period = + let open QCheck2.Gen in + let+ i = ui32 in + i + +let generate_proposals = + let open QCheck2.Gen in + let* source = random_pkh in + let+ period = random_period in + let proposals = [] in + Proposals {source; period; proposals} + +let generate_ballot = + let open QCheck2.Gen in + let* source = random_pkh in + let* period = random_period in + let+ proposal = random_proto in + let ballot = Vote.Pass in + Ballot {source; period; proposal; ballot} + +let generate_manager_aux ?source gen_manop = + let open QCheck2.Gen in + let* source = + match source with None -> random_pkh | Some source -> return source + in + let* fee = gen_fee in + let* counter = gen_counters in + let* gas_limit = gen_gas_limit in + let* storage_limit = gen_storage_limit in + let+ operation = gen_manop in + Manager_operation {source; fee; counter; operation; gas_limit; storage_limit} + +let generate_manager ?source gen_manop = + generate_op (generate_manager_aux ?source gen_manop) + +let generate_manager_operation ?source gen_manop = + let open QCheck2.Gen in + let+ manop = generate_manager ?source gen_manop in + Operation.pack manop + +let generate_reveal = + let open QCheck2.Gen in + let+ pk = random_pk in + Reveal pk + +let generate_transaction = + let open QCheck2.Gen in + let* amount = gen_amount in + let+ destination = random_contract in + let parameters = Script.unit_parameter in + let entrypoint = Entrypoint.default in + Transaction {amount; parameters; entrypoint; destination} + +let generate_origination = + let open QCheck2.Gen in + let+ credit = gen_amount in + let delegate = None in + let script = Script.{code = unit_parameter; storage = unit_parameter} in + Origination {delegate; script; credit} + +let generate_delegation = + let open QCheck2.Gen in + let+ delegate = option random_pkh in + Delegation delegate + +let generate_increase_paid_storage = + let open QCheck2.Gen in + let* amount_in_bytes = gen_amount_in_bytes in + let+ destination = random_contract_hash in + Increase_paid_storage {amount_in_bytes; destination} + +let generate_set_deposits_limit = + let open QCheck2.Gen in + let+ amount_opt = option gen_amount in + Set_deposits_limit amount_opt + +let generate_register_global_constant = + let value = Script_repr.lazy_expr (Expr.from_string "Pair 1 2") in + QCheck2.Gen.pure (Register_global_constant {value}) + +let generate_transfer_ticket = + let open QCheck2.Gen in + let* ticketer = random_contract in + let* destination = random_contract in + let+ amount = gen_ticket_amounts in + let contents = Script.lazy_expr (Expr.from_string "1") in + let ty = Script.lazy_expr (Expr.from_string "nat") in + let entrypoint = Entrypoint.default in + Transfer_ticket {contents; ty; ticketer; amount; destination; entrypoint} + +let generate_dal_publish_commitment = + let slot_index = Alpha_context.Dal.Slot_index.zero in + let commitment = Alpha_context.Dal.Slot.Commitment.zero in + let commitment_proof = Alpha_context.Dal.Slot.Commitment_proof.zero in + let slot_header = + Alpha_context.Dal.Operations.Publish_commitment. + {slot_index; commitment; commitment_proof} + in + QCheck2.Gen.pure (Dal_publish_commitment slot_header) + +let generate_sc_rollup_originate = + let kind = Sc_rollup.Kind.Example_arith in + let boot_sector = "" in + let parameters_ty = Script.lazy_expr (Expr.from_string "1") in + let whitelist = None in + QCheck2.Gen.pure + (Sc_rollup_originate {kind; boot_sector; parameters_ty; whitelist}) + +let generate_sc_rollup_add_messages = + let open QCheck2.Gen in + return (Sc_rollup_add_messages {messages = []}) + +let sc_dummy_commitment = + let number_of_ticks = + match Sc_rollup.Number_of_ticks.of_value 3000L with + | None -> assert false + | Some x -> x + in + Sc_rollup.Commitment. + { + predecessor = Sc_rollup.Commitment.Hash.zero; + inbox_level = Raw_level.of_int32_exn Int32.zero; + number_of_ticks; + compressed_state = Sc_rollup.State_hash.zero; + } + +let generate_sc_rollup_cement = + let open QCheck2.Gen in + let+ rollup = random_sc_rollup in + Sc_rollup_cement {rollup} + +let generate_sc_rollup_publish = + let open QCheck2.Gen in + let+ rollup = random_sc_rollup in + let commitment = sc_dummy_commitment in + Sc_rollup_publish {rollup; commitment} + +let generate_sc_rollup_refute = + let open QCheck2.Gen in + let* opponent = random_pkh in + let+ rollup = random_sc_rollup in + let refutation : Sc_rollup.Game.refutation = + Sc_rollup.Game.Move {choice = Sc_rollup.Tick.initial; step = Dissection []} + in + Sc_rollup_refute {rollup; opponent; refutation} + +let generate_sc_rollup_timeout = + let open QCheck2.Gen in + let* source = random_pkh in + let* rollup = random_sc_rollup in + let+ staker = random_pkh in + let stakers = Sc_rollup.Game.Index.make source staker in + Sc_rollup_timeout {rollup; stakers} + +let generate_sc_rollup_execute_outbox_message = + let open QCheck2.Gen in + let+ rollup = random_sc_rollup in + let cemented_commitment = + Sc_rollup.Commitment.hash_uncarbonated sc_dummy_commitment + in + let output_proof = "" in + Sc_rollup_execute_outbox_message {rollup; cemented_commitment; output_proof} + +let generate_sc_rollup_recover_bond = + let open QCheck2.Gen in + let* staker = random_pkh in + let+ sc_rollup = random_sc_rollup in + Sc_rollup_recover_bond {sc_rollup; staker} + +(** {2 By Kind Operation Generator} *) + +let generator_of ?source = function + | `KReveal -> generate_manager_operation ?source generate_reveal + | `KTransaction -> generate_manager_operation ?source generate_transaction + | `KOrigination -> generate_manager_operation ?source generate_origination + | `KSet_deposits_limit -> + generate_manager_operation ?source generate_set_deposits_limit + | `KIncrease_paid_storage -> + generate_manager_operation ?source generate_increase_paid_storage + | `KDelegation -> generate_manager_operation ?source generate_delegation + | `KRegister_global_constant -> + generate_manager_operation ?source generate_register_global_constant + | `KTransfer_ticket -> + generate_manager_operation ?source generate_transfer_ticket + | `KDal_publish_commitment -> + generate_manager_operation ?source generate_dal_publish_commitment + | `KSc_rollup_originate -> + generate_manager_operation ?source generate_sc_rollup_originate + | `KSc_rollup_add_messages -> + generate_manager_operation ?source generate_sc_rollup_add_messages + | `KSc_rollup_cement -> + generate_manager_operation ?source generate_sc_rollup_cement + | `KSc_rollup_publish -> + generate_manager_operation ?source generate_sc_rollup_publish + | `KSc_rollup_refute -> + generate_manager_operation ?source generate_sc_rollup_refute + | `KSc_rollup_timeout -> + generate_manager_operation ?source generate_sc_rollup_timeout + | `KSc_rollup_execute_outbox_message -> + generate_manager_operation + ?source + generate_sc_rollup_execute_outbox_message + | `KSc_rollup_recover_bond -> + generate_manager_operation ?source generate_sc_rollup_recover_bond + +let generate_non_manager_operation = + let open QCheck2.Gen in + let* pass = oneofl all_non_manager_passes in + let* kind = oneofl (pass_to_operation_kinds pass) in + match kind with + | `KPreattestation -> generate_operation generate_preattestation + | `KAttestation -> generate_operation generate_attestation + | `KSeed_nonce_revelation -> generate_operation generate_seed_nonce_revelation + | `KVdf_revelation -> generate_operation generate_vdf_revelation + | `KDouble_attestation -> generate_operation generate_double_attestation + | `KDouble_preattestation -> generate_operation generate_double_preattestation + | `KDouble_baking -> generate_operation generate_double_baking + | `KActivate_account -> generate_operation generate_activate_account + | `KProposals -> generate_operation generate_proposals + | `KBallot -> generate_operation generate_ballot + | `KManager -> assert false + +let generate_manager_operation batch_size = + let open QCheck2.Gen in + let* source = random_pkh in + let source = Some source in + let* l = + flatten_l (Stdlib.List.init batch_size (fun _ -> oneofl manager_kinds)) + in + let* packed_manager_ops = flatten_l (List.map (generator_of ?source) l) in + let first_op = Stdlib.List.hd packed_manager_ops in + let unpacked_operations = + List.map + (function + | {Alpha_context.protocol_data = Operation_data {contents; _}; _} -> ( + match Contents_list contents with + | Contents_list (Single o) -> Contents o + | Contents_list + (Cons (Manager_operation {operation = Reveal _; _}, Single o)) + -> + Contents o + | _ -> assert false)) + packed_manager_ops + in + let contents_list = + List.fold_left + (fun acc -> function + | Contents (Manager_operation m) -> + Contents (Manager_operation m) :: acc + | x -> x :: acc) + [] + unpacked_operations + |> List.rev + in + let (Contents_list contents_list) = + match Operation.of_list contents_list with Ok v -> v | _ -> assert false + in + let signature = + match first_op.protocol_data with + | Operation_data {signature; _} -> signature + in + let protocol_data = {contents = contents_list; signature} in + return (Operation.pack {shell = first_op.shell; protocol_data}) + +(** The default upper bound on the number of manager operations in a batch. + + As of December 2022, there is no batch maximal size enforced + anywhere in the protocol. However, the Octez Shell only accepts + batches of at most [operations_batch_size] operations, which has a + default value of [50] in [src/lib_shell_services/shell_limits.ml]. + The protocol tests do not necessarily have to align with this + value, but there is no reason either to choose a different + one. Therefore, they use the same bound, but decremented once to + account for some tests adding a reveal at the front of the batch as + needed. *) +let max_batch_size = 49 + +let generate_operation = + let open QCheck2.Gen in + let* pass = oneofl all_passes in + let* kind = oneofl (pass_to_operation_kinds pass) in + let+ packed_operation = + match kind with + | `KPreattestation -> generate_operation generate_preattestation + | `KAttestation -> generate_operation generate_attestation + | `KSeed_nonce_revelation -> + generate_operation generate_seed_nonce_revelation + | `KVdf_revelation -> generate_operation generate_vdf_revelation + | `KDouble_attestation -> generate_operation generate_double_attestation + | `KDouble_preattestation -> + generate_operation generate_double_preattestation + | `KDouble_baking -> generate_operation generate_double_baking + | `KActivate_account -> generate_operation generate_activate_account + | `KProposals -> generate_operation generate_proposals + | `KBallot -> generate_operation generate_ballot + | `KManager -> + let* batch_size = int_range 1 max_batch_size in + generate_manager_operation batch_size + in + (kind, (Operation.hash_packed packed_operation, packed_operation)) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.ml new file mode 100644 index 000000000000..bcdac4e586f8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.ml @@ -0,0 +1,22 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Trilitech *) +(* *) +(*****************************************************************************) + +include Tezos_base.TzPervasives.Result_syntax + +let wrap = Environment.wrap_tzresult + +let ( let@ ) m f = + let x = wrap m in + f x + +let ( let*@ ) m f = + let* x = wrap m in + f x + +let ( let+@ ) m f = + let+ x = wrap m in + f x diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.mli new file mode 100644 index 000000000000..0c296a30bd6c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/result_wrap_syntax.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Trilitech *) +(* *) +(*****************************************************************************) + +(** Extends the {!Result_syntax} with additional utilities for wrapping + results produced by the protocol, i.e. [Environment.Error_monad.tzresult], + to [tzresult] values used in the tests. + + The added utilities are binding operators. They use the same symbols as + the ones from {!Result_syntax} with an added [@] character. This + character symbolizes the {!e wrapping} of the internal error monad type in a + shell error. *) + +include module type of Tezos_base.TzPervasives.Result_syntax + +(** [wrap res] is equivalent to [Environment.wrap_tzresult res] *) +val wrap : 'a Environment.Error_monad.tzresult -> 'a tzresult + +(** [let@ x = m in f x] is equivalent to [let x = Environment.wrap_tzresult m in f x] *) +val ( let@ ) : 'a Environment.Error_monad.tzresult -> ('a tzresult -> 'b) -> 'b + +(** [let*@ x = m in f x] is equivalent to [let* x = Environment.wrap_tzresult m in f x]. + Mnemonic: [@] "wraps" a protocol error in a shell error. *) +val ( let*@ ) : + 'a Environment.Error_monad.tzresult -> ('a -> 'b tzresult) -> 'b tzresult + +(** [let+@ x = m in f x] is equivalent to [let+ x = Environment.wrap_tzresult m in f x]. + Mnemonic: [@] "wraps" a protocol error in a shell error. *) +val ( let+@ ) : 'a Environment.Error_monad.tzresult -> ('a -> 'b) -> 'b tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/rewards.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/rewards.ml new file mode 100644 index 000000000000..9499ddbba961 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/rewards.ml @@ -0,0 +1,1641 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2019--2021 Nomadic Labs, *) +(* Copyright (c) 2019 Cryptium Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The tables are precomputed using this the following formulas: + +let max_attestations = 256 +let max_reward = 40 + +let r = 0.5 +let a = 3. +let b = 1.5 + +let ( -- ) i j = List.init (j - i + 1) (fun x -> x + i) + +let baking_rewards = + let reward p e = + let r_aux = + if p = 0 then + r *. (float_of_int max_reward) + else + a + in + let r = r_aux /. (float_of_int max_attestations) in + let r = 1_000_000. *. r in + Float.to_int ((float_of_int e) *. (ceil r)) in + + let ps = 0 -- 2 in + let es = 0 -- max_attestations in + + List.map (fun p -> + List.map (fun e -> + reward p e + ) es |> Array.of_list + ) ps |> Array.of_list + + +let attesting_rewards = + let reward p e = + let r_aux = + (1. -. r) *. + (float_of_int max_reward) /. + (float_of_int max_attestations) in + let r = if p = 0 then r_aux else r_aux /. b in + let r = 1_000_000. *. r in + Float.to_int ((float_of_int e) *. (floor r)) in + + let ps = 0 -- 2 in + let es = 0 -- max_attestations in + + List.map (fun p -> + List.map (fun e -> + reward p e + ) es |> Array.of_list + ) ps |> Array.of_list + + *) + +let baking_rewards : int array array = + [| + [| + 0; + 78125; + 156250; + 234375; + 312500; + 390625; + 468750; + 546875; + 625000; + 703125; + 781250; + 859375; + 937500; + 1015625; + 1093750; + 1171875; + 1250000; + 1328125; + 1406250; + 1484375; + 1562500; + 1640625; + 1718750; + 1796875; + 1875000; + 1953125; + 2031250; + 2109375; + 2187500; + 2265625; + 2343750; + 2421875; + 2500000; + 2578125; + 2656250; + 2734375; + 2812500; + 2890625; + 2968750; + 3046875; + 3125000; + 3203125; + 3281250; + 3359375; + 3437500; + 3515625; + 3593750; + 3671875; + 3750000; + 3828125; + 3906250; + 3984375; + 4062500; + 4140625; + 4218750; + 4296875; + 4375000; + 4453125; + 4531250; + 4609375; + 4687500; + 4765625; + 4843750; + 4921875; + 5000000; + 5078125; + 5156250; + 5234375; + 5312500; + 5390625; + 5468750; + 5546875; + 5625000; + 5703125; + 5781250; + 5859375; + 5937500; + 6015625; + 6093750; + 6171875; + 6250000; + 6328125; + 6406250; + 6484375; + 6562500; + 6640625; + 6718750; + 6796875; + 6875000; + 6953125; + 7031250; + 7109375; + 7187500; + 7265625; + 7343750; + 7421875; + 7500000; + 7578125; + 7656250; + 7734375; + 7812500; + 7890625; + 7968750; + 8046875; + 8125000; + 8203125; + 8281250; + 8359375; + 8437500; + 8515625; + 8593750; + 8671875; + 8750000; + 8828125; + 8906250; + 8984375; + 9062500; + 9140625; + 9218750; + 9296875; + 9375000; + 9453125; + 9531250; + 9609375; + 9687500; + 9765625; + 9843750; + 9921875; + 10000000; + 10078125; + 10156250; + 10234375; + 10312500; + 10390625; + 10468750; + 10546875; + 10625000; + 10703125; + 10781250; + 10859375; + 10937500; + 11015625; + 11093750; + 11171875; + 11250000; + 11328125; + 11406250; + 11484375; + 11562500; + 11640625; + 11718750; + 11796875; + 11875000; + 11953125; + 12031250; + 12109375; + 12187500; + 12265625; + 12343750; + 12421875; + 12500000; + 12578125; + 12656250; + 12734375; + 12812500; + 12890625; + 12968750; + 13046875; + 13125000; + 13203125; + 13281250; + 13359375; + 13437500; + 13515625; + 13593750; + 13671875; + 13750000; + 13828125; + 13906250; + 13984375; + 14062500; + 14140625; + 14218750; + 14296875; + 14375000; + 14453125; + 14531250; + 14609375; + 14687500; + 14765625; + 14843750; + 14921875; + 15000000; + 15078125; + 15156250; + 15234375; + 15312500; + 15390625; + 15468750; + 15546875; + 15625000; + 15703125; + 15781250; + 15859375; + 15937500; + 16015625; + 16093750; + 16171875; + 16250000; + 16328125; + 16406250; + 16484375; + 16562500; + 16640625; + 16718750; + 16796875; + 16875000; + 16953125; + 17031250; + 17109375; + 17187500; + 17265625; + 17343750; + 17421875; + 17500000; + 17578125; + 17656250; + 17734375; + 17812500; + 17890625; + 17968750; + 18046875; + 18125000; + 18203125; + 18281250; + 18359375; + 18437500; + 18515625; + 18593750; + 18671875; + 18750000; + 18828125; + 18906250; + 18984375; + 19062500; + 19140625; + 19218750; + 19296875; + 19375000; + 19453125; + 19531250; + 19609375; + 19687500; + 19765625; + 19843750; + 19921875; + 20000000; + |]; + [| + 0; + 11719; + 23438; + 35157; + 46876; + 58595; + 70314; + 82033; + 93752; + 105471; + 117190; + 128909; + 140628; + 152347; + 164066; + 175785; + 187504; + 199223; + 210942; + 222661; + 234380; + 246099; + 257818; + 269537; + 281256; + 292975; + 304694; + 316413; + 328132; + 339851; + 351570; + 363289; + 375008; + 386727; + 398446; + 410165; + 421884; + 433603; + 445322; + 457041; + 468760; + 480479; + 492198; + 503917; + 515636; + 527355; + 539074; + 550793; + 562512; + 574231; + 585950; + 597669; + 609388; + 621107; + 632826; + 644545; + 656264; + 667983; + 679702; + 691421; + 703140; + 714859; + 726578; + 738297; + 750016; + 761735; + 773454; + 785173; + 796892; + 808611; + 820330; + 832049; + 843768; + 855487; + 867206; + 878925; + 890644; + 902363; + 914082; + 925801; + 937520; + 949239; + 960958; + 972677; + 984396; + 996115; + 1007834; + 1019553; + 1031272; + 1042991; + 1054710; + 1066429; + 1078148; + 1089867; + 1101586; + 1113305; + 1125024; + 1136743; + 1148462; + 1160181; + 1171900; + 1183619; + 1195338; + 1207057; + 1218776; + 1230495; + 1242214; + 1253933; + 1265652; + 1277371; + 1289090; + 1300809; + 1312528; + 1324247; + 1335966; + 1347685; + 1359404; + 1371123; + 1382842; + 1394561; + 1406280; + 1417999; + 1429718; + 1441437; + 1453156; + 1464875; + 1476594; + 1488313; + 1500032; + 1511751; + 1523470; + 1535189; + 1546908; + 1558627; + 1570346; + 1582065; + 1593784; + 1605503; + 1617222; + 1628941; + 1640660; + 1652379; + 1664098; + 1675817; + 1687536; + 1699255; + 1710974; + 1722693; + 1734412; + 1746131; + 1757850; + 1769569; + 1781288; + 1793007; + 1804726; + 1816445; + 1828164; + 1839883; + 1851602; + 1863321; + 1875040; + 1886759; + 1898478; + 1910197; + 1921916; + 1933635; + 1945354; + 1957073; + 1968792; + 1980511; + 1992230; + 2003949; + 2015668; + 2027387; + 2039106; + 2050825; + 2062544; + 2074263; + 2085982; + 2097701; + 2109420; + 2121139; + 2132858; + 2144577; + 2156296; + 2168015; + 2179734; + 2191453; + 2203172; + 2214891; + 2226610; + 2238329; + 2250048; + 2261767; + 2273486; + 2285205; + 2296924; + 2308643; + 2320362; + 2332081; + 2343800; + 2355519; + 2367238; + 2378957; + 2390676; + 2402395; + 2414114; + 2425833; + 2437552; + 2449271; + 2460990; + 2472709; + 2484428; + 2496147; + 2507866; + 2519585; + 2531304; + 2543023; + 2554742; + 2566461; + 2578180; + 2589899; + 2601618; + 2613337; + 2625056; + 2636775; + 2648494; + 2660213; + 2671932; + 2683651; + 2695370; + 2707089; + 2718808; + 2730527; + 2742246; + 2753965; + 2765684; + 2777403; + 2789122; + 2800841; + 2812560; + 2824279; + 2835998; + 2847717; + 2859436; + 2871155; + 2882874; + 2894593; + 2906312; + 2918031; + 2929750; + 2941469; + 2953188; + 2964907; + 2976626; + 2988345; + 3000064; + |]; + [| + 0; + 11719; + 23438; + 35157; + 46876; + 58595; + 70314; + 82033; + 93752; + 105471; + 117190; + 128909; + 140628; + 152347; + 164066; + 175785; + 187504; + 199223; + 210942; + 222661; + 234380; + 246099; + 257818; + 269537; + 281256; + 292975; + 304694; + 316413; + 328132; + 339851; + 351570; + 363289; + 375008; + 386727; + 398446; + 410165; + 421884; + 433603; + 445322; + 457041; + 468760; + 480479; + 492198; + 503917; + 515636; + 527355; + 539074; + 550793; + 562512; + 574231; + 585950; + 597669; + 609388; + 621107; + 632826; + 644545; + 656264; + 667983; + 679702; + 691421; + 703140; + 714859; + 726578; + 738297; + 750016; + 761735; + 773454; + 785173; + 796892; + 808611; + 820330; + 832049; + 843768; + 855487; + 867206; + 878925; + 890644; + 902363; + 914082; + 925801; + 937520; + 949239; + 960958; + 972677; + 984396; + 996115; + 1007834; + 1019553; + 1031272; + 1042991; + 1054710; + 1066429; + 1078148; + 1089867; + 1101586; + 1113305; + 1125024; + 1136743; + 1148462; + 1160181; + 1171900; + 1183619; + 1195338; + 1207057; + 1218776; + 1230495; + 1242214; + 1253933; + 1265652; + 1277371; + 1289090; + 1300809; + 1312528; + 1324247; + 1335966; + 1347685; + 1359404; + 1371123; + 1382842; + 1394561; + 1406280; + 1417999; + 1429718; + 1441437; + 1453156; + 1464875; + 1476594; + 1488313; + 1500032; + 1511751; + 1523470; + 1535189; + 1546908; + 1558627; + 1570346; + 1582065; + 1593784; + 1605503; + 1617222; + 1628941; + 1640660; + 1652379; + 1664098; + 1675817; + 1687536; + 1699255; + 1710974; + 1722693; + 1734412; + 1746131; + 1757850; + 1769569; + 1781288; + 1793007; + 1804726; + 1816445; + 1828164; + 1839883; + 1851602; + 1863321; + 1875040; + 1886759; + 1898478; + 1910197; + 1921916; + 1933635; + 1945354; + 1957073; + 1968792; + 1980511; + 1992230; + 2003949; + 2015668; + 2027387; + 2039106; + 2050825; + 2062544; + 2074263; + 2085982; + 2097701; + 2109420; + 2121139; + 2132858; + 2144577; + 2156296; + 2168015; + 2179734; + 2191453; + 2203172; + 2214891; + 2226610; + 2238329; + 2250048; + 2261767; + 2273486; + 2285205; + 2296924; + 2308643; + 2320362; + 2332081; + 2343800; + 2355519; + 2367238; + 2378957; + 2390676; + 2402395; + 2414114; + 2425833; + 2437552; + 2449271; + 2460990; + 2472709; + 2484428; + 2496147; + 2507866; + 2519585; + 2531304; + 2543023; + 2554742; + 2566461; + 2578180; + 2589899; + 2601618; + 2613337; + 2625056; + 2636775; + 2648494; + 2660213; + 2671932; + 2683651; + 2695370; + 2707089; + 2718808; + 2730527; + 2742246; + 2753965; + 2765684; + 2777403; + 2789122; + 2800841; + 2812560; + 2824279; + 2835998; + 2847717; + 2859436; + 2871155; + 2882874; + 2894593; + 2906312; + 2918031; + 2929750; + 2941469; + 2953188; + 2964907; + 2976626; + 2988345; + 3000064; + |]; + |] + +let attesting_rewards : int array array = + [| + [| + 0; + 78125; + 156250; + 234375; + 312500; + 390625; + 468750; + 546875; + 625000; + 703125; + 781250; + 859375; + 937500; + 1015625; + 1093750; + 1171875; + 1250000; + 1328125; + 1406250; + 1484375; + 1562500; + 1640625; + 1718750; + 1796875; + 1875000; + 1953125; + 2031250; + 2109375; + 2187500; + 2265625; + 2343750; + 2421875; + 2500000; + 2578125; + 2656250; + 2734375; + 2812500; + 2890625; + 2968750; + 3046875; + 3125000; + 3203125; + 3281250; + 3359375; + 3437500; + 3515625; + 3593750; + 3671875; + 3750000; + 3828125; + 3906250; + 3984375; + 4062500; + 4140625; + 4218750; + 4296875; + 4375000; + 4453125; + 4531250; + 4609375; + 4687500; + 4765625; + 4843750; + 4921875; + 5000000; + 5078125; + 5156250; + 5234375; + 5312500; + 5390625; + 5468750; + 5546875; + 5625000; + 5703125; + 5781250; + 5859375; + 5937500; + 6015625; + 6093750; + 6171875; + 6250000; + 6328125; + 6406250; + 6484375; + 6562500; + 6640625; + 6718750; + 6796875; + 6875000; + 6953125; + 7031250; + 7109375; + 7187500; + 7265625; + 7343750; + 7421875; + 7500000; + 7578125; + 7656250; + 7734375; + 7812500; + 7890625; + 7968750; + 8046875; + 8125000; + 8203125; + 8281250; + 8359375; + 8437500; + 8515625; + 8593750; + 8671875; + 8750000; + 8828125; + 8906250; + 8984375; + 9062500; + 9140625; + 9218750; + 9296875; + 9375000; + 9453125; + 9531250; + 9609375; + 9687500; + 9765625; + 9843750; + 9921875; + 10000000; + 10078125; + 10156250; + 10234375; + 10312500; + 10390625; + 10468750; + 10546875; + 10625000; + 10703125; + 10781250; + 10859375; + 10937500; + 11015625; + 11093750; + 11171875; + 11250000; + 11328125; + 11406250; + 11484375; + 11562500; + 11640625; + 11718750; + 11796875; + 11875000; + 11953125; + 12031250; + 12109375; + 12187500; + 12265625; + 12343750; + 12421875; + 12500000; + 12578125; + 12656250; + 12734375; + 12812500; + 12890625; + 12968750; + 13046875; + 13125000; + 13203125; + 13281250; + 13359375; + 13437500; + 13515625; + 13593750; + 13671875; + 13750000; + 13828125; + 13906250; + 13984375; + 14062500; + 14140625; + 14218750; + 14296875; + 14375000; + 14453125; + 14531250; + 14609375; + 14687500; + 14765625; + 14843750; + 14921875; + 15000000; + 15078125; + 15156250; + 15234375; + 15312500; + 15390625; + 15468750; + 15546875; + 15625000; + 15703125; + 15781250; + 15859375; + 15937500; + 16015625; + 16093750; + 16171875; + 16250000; + 16328125; + 16406250; + 16484375; + 16562500; + 16640625; + 16718750; + 16796875; + 16875000; + 16953125; + 17031250; + 17109375; + 17187500; + 17265625; + 17343750; + 17421875; + 17500000; + 17578125; + 17656250; + 17734375; + 17812500; + 17890625; + 17968750; + 18046875; + 18125000; + 18203125; + 18281250; + 18359375; + 18437500; + 18515625; + 18593750; + 18671875; + 18750000; + 18828125; + 18906250; + 18984375; + 19062500; + 19140625; + 19218750; + 19296875; + 19375000; + 19453125; + 19531250; + 19609375; + 19687500; + 19765625; + 19843750; + 19921875; + 20000000; + |]; + [| + 0; + 52083; + 104166; + 156249; + 208332; + 260415; + 312498; + 364581; + 416664; + 468747; + 520830; + 572913; + 624996; + 677079; + 729162; + 781245; + 833328; + 885411; + 937494; + 989577; + 1041660; + 1093743; + 1145826; + 1197909; + 1249992; + 1302075; + 1354158; + 1406241; + 1458324; + 1510407; + 1562490; + 1614573; + 1666656; + 1718739; + 1770822; + 1822905; + 1874988; + 1927071; + 1979154; + 2031237; + 2083320; + 2135403; + 2187486; + 2239569; + 2291652; + 2343735; + 2395818; + 2447901; + 2499984; + 2552067; + 2604150; + 2656233; + 2708316; + 2760399; + 2812482; + 2864565; + 2916648; + 2968731; + 3020814; + 3072897; + 3124980; + 3177063; + 3229146; + 3281229; + 3333312; + 3385395; + 3437478; + 3489561; + 3541644; + 3593727; + 3645810; + 3697893; + 3749976; + 3802059; + 3854142; + 3906225; + 3958308; + 4010391; + 4062474; + 4114557; + 4166640; + 4218723; + 4270806; + 4322889; + 4374972; + 4427055; + 4479138; + 4531221; + 4583304; + 4635387; + 4687470; + 4739553; + 4791636; + 4843719; + 4895802; + 4947885; + 4999968; + 5052051; + 5104134; + 5156217; + 5208300; + 5260383; + 5312466; + 5364549; + 5416632; + 5468715; + 5520798; + 5572881; + 5624964; + 5677047; + 5729130; + 5781213; + 5833296; + 5885379; + 5937462; + 5989545; + 6041628; + 6093711; + 6145794; + 6197877; + 6249960; + 6302043; + 6354126; + 6406209; + 6458292; + 6510375; + 6562458; + 6614541; + 6666624; + 6718707; + 6770790; + 6822873; + 6874956; + 6927039; + 6979122; + 7031205; + 7083288; + 7135371; + 7187454; + 7239537; + 7291620; + 7343703; + 7395786; + 7447869; + 7499952; + 7552035; + 7604118; + 7656201; + 7708284; + 7760367; + 7812450; + 7864533; + 7916616; + 7968699; + 8020782; + 8072865; + 8124948; + 8177031; + 8229114; + 8281197; + 8333280; + 8385363; + 8437446; + 8489529; + 8541612; + 8593695; + 8645778; + 8697861; + 8749944; + 8802027; + 8854110; + 8906193; + 8958276; + 9010359; + 9062442; + 9114525; + 9166608; + 9218691; + 9270774; + 9322857; + 9374940; + 9427023; + 9479106; + 9531189; + 9583272; + 9635355; + 9687438; + 9739521; + 9791604; + 9843687; + 9895770; + 9947853; + 9999936; + 10052019; + 10104102; + 10156185; + 10208268; + 10260351; + 10312434; + 10364517; + 10416600; + 10468683; + 10520766; + 10572849; + 10624932; + 10677015; + 10729098; + 10781181; + 10833264; + 10885347; + 10937430; + 10989513; + 11041596; + 11093679; + 11145762; + 11197845; + 11249928; + 11302011; + 11354094; + 11406177; + 11458260; + 11510343; + 11562426; + 11614509; + 11666592; + 11718675; + 11770758; + 11822841; + 11874924; + 11927007; + 11979090; + 12031173; + 12083256; + 12135339; + 12187422; + 12239505; + 12291588; + 12343671; + 12395754; + 12447837; + 12499920; + 12552003; + 12604086; + 12656169; + 12708252; + 12760335; + 12812418; + 12864501; + 12916584; + 12968667; + 13020750; + 13072833; + 13124916; + 13176999; + 13229082; + 13281165; + 13333248; + |]; + [| + 0; + 52083; + 104166; + 156249; + 208332; + 260415; + 312498; + 364581; + 416664; + 468747; + 520830; + 572913; + 624996; + 677079; + 729162; + 781245; + 833328; + 885411; + 937494; + 989577; + 1041660; + 1093743; + 1145826; + 1197909; + 1249992; + 1302075; + 1354158; + 1406241; + 1458324; + 1510407; + 1562490; + 1614573; + 1666656; + 1718739; + 1770822; + 1822905; + 1874988; + 1927071; + 1979154; + 2031237; + 2083320; + 2135403; + 2187486; + 2239569; + 2291652; + 2343735; + 2395818; + 2447901; + 2499984; + 2552067; + 2604150; + 2656233; + 2708316; + 2760399; + 2812482; + 2864565; + 2916648; + 2968731; + 3020814; + 3072897; + 3124980; + 3177063; + 3229146; + 3281229; + 3333312; + 3385395; + 3437478; + 3489561; + 3541644; + 3593727; + 3645810; + 3697893; + 3749976; + 3802059; + 3854142; + 3906225; + 3958308; + 4010391; + 4062474; + 4114557; + 4166640; + 4218723; + 4270806; + 4322889; + 4374972; + 4427055; + 4479138; + 4531221; + 4583304; + 4635387; + 4687470; + 4739553; + 4791636; + 4843719; + 4895802; + 4947885; + 4999968; + 5052051; + 5104134; + 5156217; + 5208300; + 5260383; + 5312466; + 5364549; + 5416632; + 5468715; + 5520798; + 5572881; + 5624964; + 5677047; + 5729130; + 5781213; + 5833296; + 5885379; + 5937462; + 5989545; + 6041628; + 6093711; + 6145794; + 6197877; + 6249960; + 6302043; + 6354126; + 6406209; + 6458292; + 6510375; + 6562458; + 6614541; + 6666624; + 6718707; + 6770790; + 6822873; + 6874956; + 6927039; + 6979122; + 7031205; + 7083288; + 7135371; + 7187454; + 7239537; + 7291620; + 7343703; + 7395786; + 7447869; + 7499952; + 7552035; + 7604118; + 7656201; + 7708284; + 7760367; + 7812450; + 7864533; + 7916616; + 7968699; + 8020782; + 8072865; + 8124948; + 8177031; + 8229114; + 8281197; + 8333280; + 8385363; + 8437446; + 8489529; + 8541612; + 8593695; + 8645778; + 8697861; + 8749944; + 8802027; + 8854110; + 8906193; + 8958276; + 9010359; + 9062442; + 9114525; + 9166608; + 9218691; + 9270774; + 9322857; + 9374940; + 9427023; + 9479106; + 9531189; + 9583272; + 9635355; + 9687438; + 9739521; + 9791604; + 9843687; + 9895770; + 9947853; + 9999936; + 10052019; + 10104102; + 10156185; + 10208268; + 10260351; + 10312434; + 10364517; + 10416600; + 10468683; + 10520766; + 10572849; + 10624932; + 10677015; + 10729098; + 10781181; + 10833264; + 10885347; + 10937430; + 10989513; + 11041596; + 11093679; + 11145762; + 11197845; + 11249928; + 11302011; + 11354094; + 11406177; + 11458260; + 11510343; + 11562426; + 11614509; + 11666592; + 11718675; + 11770758; + 11822841; + 11874924; + 11927007; + 11979090; + 12031173; + 12083256; + 12135339; + 12187422; + 12239505; + 12291588; + 12343671; + 12395754; + 12447837; + 12499920; + 12552003; + 12604086; + 12656169; + 12708252; + 12760335; + 12812418; + 12864501; + 12916584; + 12968667; + 13020750; + 13072833; + 13124916; + 13176999; + 13229082; + 13281165; + 13333248; + |]; + |] diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/sapling_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/sapling_helpers.ml new file mode 100644 index 000000000000..5e058258d5e1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/sapling_helpers.ml @@ -0,0 +1,501 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol + +module Common = struct + let memo_size_of_int i = + match Alpha_context.Sapling.Memo_size.parse_z @@ Z.of_int i with + | Ok memo_size -> memo_size + | Error _ -> assert false + + let int_of_memo_size ms = + Alpha_context.Sapling.Memo_size.unparse_to_z ms |> Z.to_int + + let assert_true res = + let open Lwt_result_syntax in + let+ res in + assert res + + let assert_false res = + let open Lwt_result_syntax in + let+ res in + assert (not res) + + let assert_some res = + let open Lwt_result_syntax in + let+ result = res in + match result with Some s -> s | None -> assert false + + let assert_none res = + let open Lwt_result_syntax in + let* result = res in + match result with Some _ -> assert false | None -> return_unit + + let assert_error res = + let open Lwt_syntax in + let* result = res in + match result with Ok _ -> assert false | Error _ -> return_ok_unit + + let print ?(prefix = "") e v = + Format.printf + "%s: %s\n" + prefix + Data_encoding.(Json.to_string (Json.construct e v)) + + let to_hex x encoding = + Hex.show (Hex.of_bytes Data_encoding.Binary.(to_bytes_exn encoding x)) + + let randomized_byte ?pos v encoding = + let bytes = Data_encoding.Binary.(to_bytes_exn encoding v) in + let rec aux () = + let random_char = Random.int 256 |> char_of_int in + let pos = Option.value ~default:(Random.int (Bytes.length bytes)) pos in + if random_char = Bytes.get bytes pos then aux () + else Bytes.set bytes pos random_char + in + aux () ; + Data_encoding.Binary.(of_bytes_exn encoding bytes) + + type wallet = { + sk : Tezos_sapling.Core.Wallet.Spending_key.t; + vk : Tezos_sapling.Core.Wallet.Viewing_key.t; + } + + let wallet_gen () = + let sk = + Tezos_sapling.Core.Wallet.Spending_key.of_seed + (Tezos_crypto.Hacl.Rand.gen 32) + in + let vk = Tezos_sapling.Core.Wallet.Viewing_key.of_sk sk in + {sk; vk} + + let gen_addr n vk = + let rec aux n index res = + if Compare.Int.( <= ) n 0 then res + else + let new_index, new_addr = + Tezos_sapling.Core.Client.Viewing_key.new_address vk index + in + aux (n - 1) new_index (new_addr :: res) + in + aux n Tezos_sapling.Core.Client.Viewing_key.default_index [] + + let gen_nf () = + let {vk; _} = wallet_gen () in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk default_index) + in + let amount = 10L in + let rcm = Tezos_sapling.Core.Client.Rcm.random () in + let position = 10L in + Tezos_sapling.Core.Client.Nullifier.compute addr vk ~amount rcm ~position + + let gen_cm_cipher ~memo_size () = + let open Tezos_sapling.Core.Client in + let {vk; _} = wallet_gen () in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk default_index) + in + let amount = 10L in + let rcm = Tezos_sapling.Core.Client.Rcm.random () in + let cm = Commitment.compute addr ~amount rcm in + let cipher = + let payload_enc = + Data_encoding.Binary.to_bytes_exn + Data_encoding.bytes + (Tezos_crypto.Hacl.Rand.gen (memo_size + 4 + 16 + 11 + 32 + 8)) + in + Data_encoding.Binary.of_bytes_exn + Ciphertext.encoding + (Bytes.concat + Bytes.empty + [ + Bytes.create (32 + 32); + payload_enc; + Bytes.create (24 + 64 + 16 + 24); + ]) + in + (cm, cipher) + + (* rebuilds from empty at each call *) + let client_state_of_diff ~memo_size (root, diff) = + let open Alpha_context.Sapling in + let cs = + Tezos_sapling.Storage.add + (Tezos_sapling.Storage.empty ~memo_size) + diff.commitments_and_ciphertexts + in + assert (Tezos_sapling.Storage.get_root cs = root) ; + List.fold_left + (fun s nf -> Tezos_sapling.Storage.add_nullifier s nf) + cs + diff.nullifiers +end + +module Alpha_context_helpers = struct + include Common + + let init () = + let open Lwt_result_wrap_syntax in + let* b, _contract = Context.init1 () in + let+@ ctxt, _, _ = + Alpha_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + (* ~fitness:b.header.shell.fitness *) + in + ctxt + + (* takes a state obtained from Sapling.empty_state or Sapling.state_from_id and + passed through Sapling.verify_update *) + let finalize ctx = + let open Lwt_result_wrap_syntax in + let open Alpha_context in + let open Sapling in + function + | {id = None; diff; memo_size} -> + let*@ ctx, id = Sapling.fresh ~temporary:false ctx in + let init = Lazy_storage.Alloc {memo_size} in + let lazy_storage_diff = Lazy_storage.Update {init; updates = diff} in + let diffs = [Lazy_storage.make Sapling_state id lazy_storage_diff] in + let+@ ctx, _added_size = Lazy_storage.apply ctx diffs in + (ctx, id) + | {id = Some id; diff; _} -> + let init = Lazy_storage.Existing in + let lazy_storage_diff = Lazy_storage.Update {init; updates = diff} in + let diffs = [Lazy_storage.make Sapling_state id lazy_storage_diff] in + let+@ ctx, _added_size = Lazy_storage.apply ctx diffs in + (ctx, id) + + (* disk only version *) + let verify_update ctx ?memo_size ?id vt = + let open Lwt_result_wrap_syntax in + let anti_replay = "anti-replay" in + let* vs, ctx = + match id with + | None -> + let* memo_size = + match memo_size with + | None -> ( + match vt.Environment.Sapling.UTXO.outputs with + | [] -> failwith "Can't infer memo_size from empty outputs" + | output :: _ -> + return + @@ Environment.Sapling.Ciphertext.get_memo_size + output.ciphertext) + | Some memo_size -> return memo_size + in + let memo_size = memo_size_of_int memo_size in + let vs = Alpha_context.Sapling.empty_state ~memo_size () in + return (vs, ctx) + | Some id -> + (* let*! result = Storage.Sapling.Roots.get (Obj.magic ctx, id) 0l in *) + (* let*?@ _, root = result in *) + (* print ~prefix:"verify: " Environment.Sapling.Hash.encoding root ; *) + let*@ result = Alpha_context.Sapling.state_from_id ctx id in + return result + in + let*@ ctx, res = + Alpha_context.Sapling.verify_update ctx vs vt anti_replay + in + match res with + | None -> return_none + | Some (_balance, vs) -> + let* ctx, id = finalize ctx vs in + let fake_fitness = + Alpha_context.( + let level = + match Raw_level.of_int32 0l with + | Error _ -> assert false + | Ok l -> l + in + Fitness.create_without_locked_round + ~level + ~predecessor_round:Round.zero + ~round:Round.zero + |> Fitness.to_raw) + in + let ectx = (Alpha_context.finalize ctx fake_fitness).context in + (* bump the level *) + let+@ ctx, _, _ = + Alpha_context.prepare + ectx + ~level: + Alpha_context.( + Raw_level.to_int32 Level.((succ ctx (current ctx)).level)) + ~predecessor_timestamp:(Time.Protocol.of_seconds Int64.zero) + ~timestamp:(Time.Protocol.of_seconds Int64.zero) + in + Some (ctx, id) + + (* Same as before but for legacy *) + let verify_update_legacy ctx ?memo_size ?id vt = + let open Lwt_result_wrap_syntax in + let anti_replay = "anti-replay" in + let* vs, ctx = + match id with + | None -> + let* memo_size = + match memo_size with + | None -> ( + match vt.Environment.Sapling.UTXO.Legacy.outputs with + | [] -> failwith "Can't infer memo_size from empty outputs" + | output :: _ -> + return + @@ Environment.Sapling.Ciphertext.get_memo_size + output.ciphertext) + | Some memo_size -> return memo_size + in + let memo_size = memo_size_of_int memo_size in + let vs = Alpha_context.Sapling.empty_state ~memo_size () in + return (vs, ctx) + | Some id -> + (* let*! result = Storage.Sapling.Roots.get (Obj.magic ctx, id) 0l in *) + (* let*?@ _, root = result in *) + (* print ~prefix:"verify: " Environment.Sapling.Hash.encoding root ; *) + let*@ result = Alpha_context.Sapling.state_from_id ctx id in + return result + in + let*@ ctx, res = + Alpha_context.Sapling.Legacy.verify_update ctx vs vt anti_replay + in + match res with + | None -> return_none + | Some (_balance, vs) -> + let* ctx, id = finalize ctx vs in + let fake_fitness = + Alpha_context.( + let level = + match Raw_level.of_int32 0l with + | Error _ -> assert false + | Ok l -> l + in + Fitness.create_without_locked_round + ~level + ~predecessor_round:Round.zero + ~round:Round.zero + |> Fitness.to_raw) + in + let ectx = (Alpha_context.finalize ctx fake_fitness).context in + (* bump the level *) + let+@ ctx, _, _ = + Alpha_context.prepare + ectx + ~level: + Alpha_context.( + Raw_level.to_int32 Level.((succ ctx (current ctx)).level)) + ~predecessor_timestamp:(Time.Protocol.of_seconds Int64.zero) + ~timestamp:(Time.Protocol.of_seconds Int64.zero) + in + Some (ctx, id) + + let transfer_inputs_outputs w cs is = + (* Tezos_sapling.Storage.size cs *) + (* |> fun (a, b) -> *) + (* Printf.printf "%Ld %Ld" a b ; *) + let inputs = + List.map + (fun i -> + Tezos_sapling.Forge.Input.get cs (Int64.of_int i) w.vk + |> WithExceptions.Option.get ~loc:__LOC__ + |> snd) + is + in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address w.vk default_index) + in + let memo_size = Tezos_sapling.Storage.get_memo_size cs in + let o = + Tezos_sapling.Forge.make_output addr 1000000L (Bytes.create memo_size) + in + (inputs, [o]) + + let transfer w cs is = + let anti_replay = "anti-replay" in + let ins, outs = transfer_inputs_outputs w cs is in + (* change the wallet of this last line *) + Tezos_sapling.Forge.forge_transaction + ins + outs + w.sk + anti_replay + ~bound_data:"" + cs + + let transfer_legacy w cs is = + let anti_replay = "anti-replay" in + let ins, outs = transfer_inputs_outputs w cs is in + (* change the wallet of this last line *) + Tezos_sapling.Forge.forge_transaction_legacy ins outs w.sk anti_replay cs + + let client_state_alpha ctx id = + let open Lwt_result_wrap_syntax in + let*@ diff = Alpha_context.Sapling.get_diff ctx id () in + let+@ {memo_size; _}, _ctx = Alpha_context.Sapling.state_from_id ctx id in + let memo_size = int_of_memo_size memo_size in + client_state_of_diff ~memo_size diff +end + +(* + Interpreter level +*) + +module Interpreter_helpers = struct + include Common + include Contract_helpers + + (** Returns a block in which the contract is originated. + Also returns the associated anti-replay string and KT1 address. *) + let originate_contract_hash file storage src b baker = + let open Lwt_result_syntax in + let+ dst, b = originate_contract_hash file storage src b baker in + let anti_replay = + Format.asprintf "%a%a" Contract_hash.pp dst Chain_id.pp Chain_id.zero + in + (dst, b, anti_replay) + + let hex_shield ~memo_size wallet anti_replay = + let ps = Tezos_sapling.Storage.empty ~memo_size in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.( + new_address wallet.vk default_index) + in + let output = + Tezos_sapling.Forge.make_output addr 15L (Bytes.create memo_size) + in + let pt = + Tezos_sapling.Forge.forge_transaction + [] + [output] + wallet.sk + anti_replay + ~bound_data:"" + ps + in + let hex_string = + "0x" + ^ Hex.show + (Hex.of_bytes + Data_encoding.Binary.( + to_bytes_exn + Tezos_sapling.Core.Client.UTXO.transaction_encoding + pt)) + in + hex_string + + (* Make a transaction and sync a local client state. [to_exclude] is the list + of addresses that cannot bake the block*) + let transac_and_sync ~memo_size block parameters amount src dst baker = + let open Lwt_result_syntax in + let amount_tez = + Test_tez.(Alpha_context.Tez.one_mutez *! Int64.of_int amount) + in + let fee = Test_tez.of_int 10 in + let* operation = + Op.transaction + ~gas_limit:Max + ~fee + (B block) + src + (Alpha_context.Contract.Originated dst) + amount_tez + ~parameters + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let* incr = Incremental.add_operation incr operation in + let* block = Incremental.finalize_block incr in + let+ diff = + Alpha_services.Contract.single_sapling_get_diff + Block.rpc_ctxt + block + dst + ~offset_commitment:0L + ~offset_nullifier:0L + () + in + let state = client_state_of_diff ~memo_size diff in + (block, state) + + (* Returns a list of printed shield transactions and their total amount. *) + let shield ~memo_size sk number_transac vk printer anti_replay = + let state = Tezos_sapling.Storage.empty ~memo_size in + let rec aux number_transac number_outputs index amount_output total res = + if Compare.Int.(number_transac <= 0) then (res, total) + else + let new_index, new_addr = + Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk index) + in + let outputs = + WithExceptions.List.init ~loc:__LOC__ number_outputs (fun _ -> + Tezos_sapling.Forge.make_output + new_addr + amount_output + (Bytes.create memo_size)) + in + let tr_hex = + to_hex + (Tezos_sapling.Forge.forge_transaction + ~number_dummy_inputs:0 + ~number_dummy_outputs:0 + [] + outputs + sk + anti_replay + ~bound_data:"" + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + aux + (number_transac - 1) + (number_outputs + 1) + new_index + (Int64.add 20L amount_output) + (total + (number_outputs * Int64.to_int amount_output)) + (printer tr_hex :: res) + in + aux + number_transac + 2 + Tezos_sapling.Core.Wallet.Viewing_key.default_index + 20L + 0 + [] + + (* This fails if the operation is not correct wrt the block *) + let next_block block operation = + let open Lwt_result_syntax in + let* incr = Incremental.begin_construction block in + let* incr = Incremental.add_operation incr operation in + Incremental.finalize_block incr +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/sc_rollup_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/sc_rollup_helpers.ml new file mode 100644 index 000000000000..133a589ecd60 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/sc_rollup_helpers.ml @@ -0,0 +1,1021 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let originated_rollup op = + let nonce = + Origination_nonce.Internal_for_tests.initial (Operation.hash_packed op) + in + Contract.Internal_for_tests.originated_contract nonce + +module Arith_pvm = Pvm_in_memory.Arith +module Wasm_pvm = Pvm_in_memory.Wasm + +module Make_in_memory_context (Context : sig + type tree + + include + Tezos_context_sigs.Context.TEZOS_CONTEXT + with type memory_context_tree := tree + and type tree := tree + and type value_key = Context_hash.t + and type node_key = Context_hash.t +end) = +struct + module Tree = struct + include Context.Tree + + type tree = Context.tree + + type t = Context.t + + type key = string list + + type value = bytes + end + + type tree = Tree.tree + + type proof = Context.Proof.tree Context.Proof.t + + let hash_tree _ = assert false + + let verify_proof p f = + Lwt.map Result.to_option (Context.verify_tree_proof p f) + + let produce_proof context state step = + let open Lwt_syntax in + let* context = Context.add_tree context [] state in + let* h = Context.commit ~time:Time.Protocol.epoch context in + let index = Context.index context in + let* context = Context.checkout_exn index h in + match Tree.kinded_key state with + | Some k -> + let index = Context.index context in + let* p = Context.produce_tree_proof index k step in + return_some p + | None -> return_none + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> + Sc_rollup.State_hash.context_hash_to_state_hash hash + + let proof_before proof = kinded_hash_to_state_hash proof.Context.Proof.before + + let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + + let proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 + .tree_proof_encoding +end + +module Wrong_in_memory_context = + Make_in_memory_context (Tezos_context_memory.Context) + +module Wrong_arith_pvm : + Sc_rollup.PVM.S + with type context = Wrong_in_memory_context.Tree.t + and type state = Wrong_in_memory_context.tree + and type proof = + Tezos_context_memory.Context.Proof.tree + Tezos_context_memory.Context.Proof.t = + Sc_rollup.ArithPVM.Make (Wrong_in_memory_context) + +let genesis_commitment ~boot_sector ~origination_level kind = + let open Lwt_syntax in + let+ genesis_state_hash = Sc_rollup.genesis_state_hash_of kind ~boot_sector in + Sc_rollup.Commitment.genesis_commitment ~origination_level ~genesis_state_hash + +let genesis_commitment_raw ~boot_sector ~origination_level kind = + let open Lwt_syntax in + let origination_level = + Raw_level_repr.to_int32 origination_level + |> Alpha_context.Raw_level.of_int32_exn + in + let kind = + match kind with + | Sc_rollups.Kind.Example_arith -> Sc_rollup.Kind.Example_arith + | Sc_rollups.Kind.Wasm_2_0_0 -> Sc_rollup.Kind.Wasm_2_0_0 + | Sc_rollups.Kind.Riscv -> Sc_rollup.Kind.Riscv + in + let* res = genesis_commitment ~boot_sector ~origination_level kind in + let res = + Data_encoding.Binary.to_bytes_exn Sc_rollup.Commitment.encoding res + |> Data_encoding.Binary.of_bytes_exn Sc_rollup_commitment_repr.encoding + in + return res + +(** {2 Inbox message helpers.} *) + +(** {1 Above [Alpha_context].} *) + +let message_serialize msg = + WithExceptions.Result.get_ok + ~loc:__LOC__ + Sc_rollup.Inbox_message.(serialize msg) + +let make_external_inbox_message str = message_serialize (External str) + +let make_internal_inbox_message internal_msg = + message_serialize (Internal internal_msg) + +let make_input ?(inbox_level = Raw_level.root) ?(message_counter = Z.zero) + payload = + Sc_rollup.Inbox_message {inbox_level; message_counter; payload} + +let make_external_input ?inbox_level ?message_counter str = + let payload = make_external_inbox_message str in + make_input ?inbox_level ?message_counter payload + +let make_sol ~inbox_level = + let payload = make_internal_inbox_message Start_of_level in + make_input ~inbox_level ~message_counter:Z.zero payload + +let make_eol ~inbox_level ~message_counter = + let payload = make_internal_inbox_message End_of_level in + make_input ~inbox_level ~message_counter payload + +let make_info_per_level ~inbox_level ~predecessor_timestamp ~predecessor = + let payload = + make_internal_inbox_message + (Info_per_level {predecessor_timestamp; predecessor}) + in + make_input ~inbox_level ~message_counter:Z.one payload + +let make_protocol_migration ~inbox_level = + let payload = + make_internal_inbox_message + Sc_rollup.Inbox_message.protocol_migration_internal_message + in + make_input ~inbox_level ~message_counter:Z.(succ one) payload + +(** Message is the combination of a [message] and its associated [input]. + + [message] is used to: + - Construct the protocol inbox, when [message] is [`Message]. The protocol + adds [`SOL] and [`EOL] itself. + - Construct the players' inboxes. + + [input] is used to evaluate the players' inboxes. + +*) +type message = { + input : Sc_rollup.input; + message : + [ `SOL + | `Info_per_level of Timestamp.t * Block_hash.t + | `Message of string + | `EOL ]; +} + +(** Put as much information as possible in this record so it can be used + in different setups: + 1. Creating an inbox on the protocol-side, requires [messages] only. + 2. Re-construct an inbox, requires [payloads], [timestamp], [predecessor]. + 3. Evaluate inputs in a PVM, requires [inputs] + + [level] is useful for (1) (2) (3). + *) +type payloads_per_level = { + messages : string list; (** List of external messages. *) + payloads : Sc_rollup.Inbox_message.serialized list; + (** List of external serialized messages. *) + predecessor_timestamp : Time.Protocol.t; + (** predecessor timestamp of the [Info_per_level]. *) + predecessor : Block_hash.t; (** Predecessor of the [Info_per_level]. *) + level : Raw_level.t; + inputs : Sc_rollup.input list; + (** List of all inputs for the level, to be read by a PVM. *) +} + +let pp_input fmt (input : Sc_rollup.input) = + match input with + | Reveal _ -> assert false + | Inbox_message {inbox_level; message_counter; _} -> + Format.fprintf + fmt + "(%a, %s)" + Raw_level.pp + inbox_level + (Z.to_string message_counter) + +let pp_message fmt {input; message} = + Format.fprintf + fmt + "{ input = %a; message = %S }" + pp_input + input + (match message with + | `SOL -> "SOL" + | `Info_per_level (predecessor_timestamp, block_hash) -> + Format.asprintf + "Info_per_level (%s, %a)" + (Timestamp.to_notation predecessor_timestamp) + Block_hash.pp + block_hash + | `Message msg -> msg + | `EOL -> "EOL") + +(** Creates inputs based on string messages. *) +let strs_to_inputs inbox_level messages = + List.fold_left + (fun (acc, message_counter) message -> + let input = make_external_input ~inbox_level ~message_counter message in + ({input; message = `Message message} :: acc, Z.succ message_counter)) + ([], Z.of_int 2) + messages + +(** Transform the list of all inputs the PVM should read. *) +let make_inputs ~first_block predecessor_timestamp predecessor messages + inbox_level = + (* SOL is at index 0. *) + let sol = make_sol ~inbox_level in + (* Info_per_level is at index 1. *) + let info_per_level = + make_info_per_level ~inbox_level ~predecessor_timestamp ~predecessor + in + let mig = + if first_block then [make_protocol_migration ~inbox_level] else [] + in + (* External inputs start at index 2. *) + let external_inputs = + List.mapi + (fun i message -> + make_external_input + ~inbox_level + ~message_counter:(Z.of_int (2 + List.length mig + i)) + message) + messages + in + (* EOL is after SOL/Info_per_level and all external inputs, therefore, + at index [2 + List.length messages]. *) + let eol = + let message_counter = + Z.of_int (2 + List.length mig + List.length messages) + in + make_eol ~inbox_level ~message_counter + in + [sol; info_per_level] @ mig @ external_inputs @ [eol] + +let predecessor_timestamp_and_hash_from_level level = + let level_int64 = Int64.of_int32 @@ Raw_level.to_int32 level in + let predecessor_timestamp = Time.Protocol.of_seconds level_int64 in + let hash = Block_hash.hash_string [Int64.to_string level_int64] in + (predecessor_timestamp, hash) + +(** Wrap messages, predecessor_timestamp and predecessor of a level into a + [payloads_per_level] .*) +let wrap_messages level + ?(pred_info = predecessor_timestamp_and_hash_from_level level) messages : + payloads_per_level = + let predecessor_timestamp, predecessor = pred_info in + let payloads = List.map make_external_inbox_message messages in + let inputs = + make_inputs + ~first_block:(level = Raw_level.root || level = Raw_level.(succ root)) + predecessor_timestamp + predecessor + messages + level + in + {payloads; predecessor_timestamp; predecessor; messages; level; inputs} + +(** An empty inbox level is a SOL,IPL and EOL. *) +let make_empty_level ?pred_info inbox_level = + wrap_messages ?pred_info inbox_level [] + +let gen_messages ?pred_info inbox_level gen_message = + let open QCheck2.Gen in + let* input = gen_message in + let* inputs = small_list gen_message in + return (wrap_messages ?pred_info inbox_level (input :: inputs)) + +let gen_payloads_for_levels ~start_level ~max_level gen_message = + let open QCheck2.Gen in + let rec aux acc n = + match n with + | n when n < 0 -> + (* Prevent [Stack_overflow]. *) + assert false + | 0 -> return acc + | n -> + let inbox_level = + Raw_level.of_int32_exn (Int32.of_int (start_level + n - 1)) + in + let* empty_level = bool in + let* level_messages = + if empty_level then return (make_empty_level inbox_level) + else gen_messages inbox_level gen_message + in + aux (level_messages :: acc) (n - 1) + in + aux [] (max_level - start_level) + +(** {1 Below [Alpha_context].} *) + +let message_serialize_repr msg = + WithExceptions.Result.get_ok + ~loc:__LOC__ + Sc_rollup_inbox_message_repr.(serialize msg) + +let make_external_inbox_message_repr str = message_serialize_repr (External str) + +let make_internal_inbox_message_repr internal_msg = + message_serialize_repr (Internal internal_msg) + +let make_input_repr ?(inbox_level = Raw_level_repr.root) + ?(message_counter = Z.zero) payload = + Sc_rollup_PVM_sig.Inbox_message {inbox_level; message_counter; payload} + +let make_external_input_repr ?inbox_level ?message_counter str = + let payload = make_external_inbox_message_repr str in + make_input_repr ?inbox_level ?message_counter payload + +let make_sol_repr ~inbox_level = + let payload = make_internal_inbox_message_repr Start_of_level in + make_input_repr ~inbox_level ~message_counter:Z.zero payload + +let make_eol_repr ~inbox_level ~message_counter = + let payload = make_internal_inbox_message_repr End_of_level in + make_input_repr ~inbox_level ~message_counter payload + +(** Message is the combination of a [message] and its associated [input]. + + [message] is used to: + - Construct the protocol inbox, when [message] is [`Message]. The protocol + adds [`SOL] and [`EOL] itself. + - Construct the players' inboxes. + + [input] is used to evaluate the players' inboxes. + +*) +type message_repr = { + input_repr : Sc_rollup_PVM_sig.input; + message_repr : [`SOL | `Message of string | `EOL]; +} + +let pp_input_repr fmt (input_repr : Sc_rollup_PVM_sig.input) = + match input_repr with + | Reveal _ -> assert false + | Inbox_message {inbox_level; message_counter; _} -> + Format.fprintf + fmt + "(%a, %s)" + Raw_level_repr.pp + inbox_level + (Z.to_string message_counter) + +let pp_message_repr fmt {input_repr; message_repr} = + Format.fprintf + fmt + "{ input_repr = %a; message_repr = %S }" + pp_input_repr + input_repr + (match message_repr with + | `SOL -> "SOL" + | `Message msg -> msg + | `EOL -> "EOL") + +(** An empty inbox level is a SOL,IPL and EOL. *) +let make_empty_level_repr inbox_level = + let sol = {input_repr = make_sol_repr ~inbox_level; message_repr = `SOL} in + let eol = + { + input_repr = make_eol_repr ~inbox_level ~message_counter:Z.one; + message_repr = `EOL; + } + in + (inbox_level, [sol; eol]) + +(** Creates input_reprs based on string message_reprs. *) +let strs_to_input_reprs_repr inbox_level message_reprs = + List.fold_left + (fun (acc, message_counter) message_repr -> + let input_repr = + make_external_input_repr ~inbox_level ~message_counter message_repr + in + ( {input_repr; message_repr = `Message message_repr} :: acc, + Z.succ message_counter )) + ([], Z.one) + message_reprs + +(** Transform message_reprs into input_reprs and wrap them between SOL and EOL. *) +let wrap_message_reprs_repr inbox_level strs = + let sol = {input_repr = make_sol_repr ~inbox_level; message_repr = `SOL} in + let rev_input_reprs, message_counter = + strs_to_input_reprs_repr inbox_level strs + in + let input_reprs = List.rev rev_input_reprs in + let eol = + { + input_repr = make_eol_repr ~inbox_level ~message_counter; + message_repr = `EOL; + } + in + (sol :: input_reprs) @ [eol] + +let gen_message_reprs_for_levels_repr ~start_level ~max_level gen_message_repr = + let open QCheck2.Gen in + let rec aux acc n = + match n with + | 0 -> return acc + | n when n > 0 -> + let inbox_level = + Raw_level_repr.of_int32_exn (Int32.of_int (start_level + n - 1)) + in + let* empty_level = bool in + let* level_message_reprs = + if empty_level then return (make_empty_level_repr inbox_level) + else + let* message_reprs = + let* input_repr = gen_message_repr in + let* input_reprs = small_list gen_message_repr in + return (input_repr :: input_reprs) + in + return + (inbox_level, wrap_message_reprs_repr inbox_level message_reprs) + in + aux (level_message_reprs :: acc) (n - 1) + | _ -> + (* Prevent [Stack_overflow]. *) + assert false + in + aux [] (max_level - start_level) + +module Payloads_histories = + Map.Make (Sc_rollup.Inbox_merkelized_payload_hashes.Hash) + +type payloads_histories = + Sc_rollup.Inbox_merkelized_payload_hashes.History.t Payloads_histories.t + +let get_payloads_history payloads_histories witness = + Payloads_histories.find witness payloads_histories + |> WithExceptions.Option.get ~loc:__LOC__ + |> Lwt.return + +let get_history history i = Sc_rollup.Inbox.History.find i history |> Lwt.return + +let inbox_message_of_input input = + match input with Sc_rollup.Inbox_message x -> Some x | _ -> None + +let payloads_from_messages = + List.map (fun {input; _} -> + match input with + | Inbox_message {payload; _} -> payload + | Reveal _ -> assert false) + +let first_after payloads_per_levels level message_counter = + let payloads_at_level level = + List.find + (fun {level = payloads_level; _} -> level = payloads_level) + payloads_per_levels + in + let payloads_per_level = + WithExceptions.Option.get ~loc:__LOC__ @@ payloads_at_level level + in + match List.nth payloads_per_level.inputs (Z.to_int message_counter) with + | Some input -> inbox_message_of_input input + | None -> ( + (* If no input at (l, n), the next input is (l+1, 0). *) + let next_level = Raw_level.succ level in + match payloads_at_level next_level with + | None -> None + | Some payloads_per_level -> + let input = Stdlib.List.hd payloads_per_level.inputs in + inbox_message_of_input input) + +let list_of_inputs_from_list_of_messages + (payloads_per_levels : message list list) = + List.map + (fun inputs -> + let payloads = List.map (fun {input; _} -> input) inputs in + payloads) + payloads_per_levels + +let dumb_init level = + Sc_rollup.Inbox.genesis + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + level + +let dumb_init_repr level = + Sc_rollup_inbox_repr.genesis + ~protocol_migration_message: + Raw_context.protocol_migration_serialized_message + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + level + +let origination_op ?force_reveal ?counter ?fee ?gas_limit ?storage_limit + ?(boot_sector = "") ?(parameters_ty = "unit") ?whitelist ctxt src kind = + Op.sc_rollup_origination + ?force_reveal + ?counter + ?fee + ?gas_limit + ?storage_limit + ?whitelist + ctxt + src + kind + ~boot_sector + ~parameters_ty:(Script.lazy_expr @@ Expr.from_string parameters_ty) + +let latest_level_proof inbox = + Sc_rollup.Inbox.Internal_for_tests.level_proof_of_history_proof + @@ Sc_rollup.Inbox.old_levels_messages inbox + +let latest_level_proof_hash inbox = (latest_level_proof inbox).hash + +module Node_inbox = struct + type t = { + inbox : Sc_rollup.Inbox.t; + history : Sc_rollup.Inbox.History.t; + payloads_histories : payloads_histories; + } + + let new_inbox ?(genesis_predecessor_timestamp = Time.Protocol.epoch) + ?(genesis_predecessor = Block_hash.zero) + ?(inbox_creation_level = Raw_level.root) () = + let open Result_syntax in + let inbox = + Sc_rollup.Inbox.genesis + ~predecessor_timestamp:genesis_predecessor_timestamp + ~predecessor:genesis_predecessor + inbox_creation_level + in + let history = Sc_rollup.Inbox.History.empty ~capacity:10000L in + let payloads_histories = Payloads_histories.empty in + return {inbox; history; payloads_histories} + + let fill_inbox ~inbox_creation_level node_inbox payloads_per_levels = + let open Result_wrap_syntax in + let rec aux {inbox; history; payloads_histories} = function + | [] -> return {inbox; history; payloads_histories} + | ({ + payloads = _; + predecessor_timestamp; + predecessor; + messages; + level; + inputs = _; + } : + payloads_per_level) + :: rst -> + let messages = + List.map + (fun message -> Sc_rollup.Inbox_message.External message) + messages + in + let*@ payloads_history, history, inbox, witness, _messages = + Sc_rollup.Inbox.add_all_messages + ~first_block:Raw_level.(equal (succ inbox_creation_level) level) + ~predecessor_timestamp + ~predecessor + history + inbox + messages + in + (* Store in the history this archived level. *) + let witness_hash = + Sc_rollup.Inbox_merkelized_payload_hashes.hash witness + in + let payloads_histories = + Payloads_histories.add + witness_hash + payloads_history + payloads_histories + in + aux {inbox; history; payloads_histories} rst + in + aux node_inbox payloads_per_levels + + let construct_inbox ?(inbox_creation_level = Raw_level.root) + ?genesis_predecessor_timestamp ?genesis_predecessor payloads_per_levels = + let open Result_syntax in + let* node_inbox = + new_inbox + ?genesis_predecessor_timestamp + ?genesis_predecessor + ~inbox_creation_level + () + in + fill_inbox ~inbox_creation_level node_inbox payloads_per_levels + + let get_history history hash = + Lwt.return @@ Sc_rollup.Inbox.History.find hash history + + let produce_proof {payloads_histories; history; _} inbox_snapshot + (level, message_counter) = + let open Lwt_result_wrap_syntax in + wrap + @@ Sc_rollup.Inbox.produce_proof + ~get_payloads_history:(get_payloads_history payloads_histories) + ~get_history:(get_history history) + inbox_snapshot + (level, message_counter) + + let produce_and_expose_proof node_inbox node_inbox_snapshot + (level, message_counter) = + let open Lwt_result_syntax in + let* proof, input = + produce_proof node_inbox node_inbox_snapshot (level, message_counter) + in + let exposed_proof = Sc_rollup.Inbox.Internal_for_tests.expose_proof proof in + return (exposed_proof, input) + + let produce_payloads_proof {payloads_histories; _} + (head_cell_hash : Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t) + message_counter = + let open Lwt_result_wrap_syntax in + wrap + @@ Sc_rollup.Inbox.Internal_for_tests.produce_payloads_proof + (get_payloads_history payloads_histories) + head_cell_hash + ~index:message_counter + + let produce_inclusion_proof {history; _} inbox_snapshot level = + let open Lwt_result_wrap_syntax in + wrap + @@ Sc_rollup.Inbox.Internal_for_tests.produce_inclusion_proof + (get_history history) + inbox_snapshot + level +end + +module Protocol_inbox = struct + let new_inbox ?(genesis_predecessor_timestamp = Time.Protocol.epoch) + ?(genesis_predecessor = Block_hash.zero) + ?(inbox_creation_level = Raw_level.root) () = + Sc_rollup.Inbox.genesis + ~predecessor_timestamp:genesis_predecessor_timestamp + ~predecessor:genesis_predecessor + inbox_creation_level + + let fill_inbox ~inbox_creation_level inbox payloads_per_levels = + let open Result_wrap_syntax in + let rec aux inbox = function + | [] -> return inbox + | ({ + payloads = _; + predecessor_timestamp; + predecessor; + messages; + level; + inputs = _; + } : + payloads_per_level) + :: rst -> + let payloads = + List.map + (fun message -> Sc_rollup.Inbox_message.(External message)) + messages + in + let*@ _, _, inbox, _, _ = + Sc_rollup.Inbox.add_all_messages + ~first_block:Raw_level.(equal (succ inbox_creation_level) level) + ~predecessor_timestamp + ~predecessor + (Sc_rollup.Inbox.History.empty ~capacity:1000L) + inbox + payloads + in + aux inbox rst + in + aux inbox payloads_per_levels + + let add_new_level ?pred_info inbox messages = + let next_level = Raw_level.succ @@ Sc_rollup.Inbox.inbox_level inbox in + let messages_per_level = wrap_messages ?pred_info next_level messages in + fill_inbox inbox [messages_per_level] + + let add_new_empty_level ?pred_info inbox = + let next_level = Raw_level.succ @@ Sc_rollup.Inbox.inbox_level inbox in + let empty_level = [make_empty_level ?pred_info next_level] in + fill_inbox inbox empty_level + + let construct_inbox ?(inbox_creation_level = Raw_level.root) + ?genesis_predecessor_timestamp ?genesis_predecessor payloads_per_levels = + let inbox = + new_inbox + ?genesis_predecessor_timestamp + ?genesis_predecessor + ~inbox_creation_level + () + in + fill_inbox ~inbox_creation_level inbox payloads_per_levels +end + +let construct_node_and_protocol_inbox ?inbox_creation_level + ?genesis_predecessor_timestamp ?genesis_predecessor payloads_per_levels = + let open Result_syntax in + let* node_inbox = + Node_inbox.construct_inbox + ?inbox_creation_level + ?genesis_predecessor_timestamp + ?genesis_predecessor + payloads_per_levels + in + let* protocol_inbox = + Protocol_inbox.construct_inbox + ?inbox_creation_level + ?genesis_predecessor_timestamp + ?genesis_predecessor + payloads_per_levels + in + return (node_inbox, protocol_inbox) + +module Protocol_inbox_with_ctxt = struct + let fill_inbox block list_of_messages contract = + let open Lwt_result_syntax in + let* block, list_of_messages = + List.fold_left_map_es + (fun (block : Block.t) ({messages; _} as messages_per_level) -> + let predecessor = block.hash in + let predecessor_timestamp = block.header.shell.timestamp in + + let* block = + match messages with + | [] -> + let* block = Block.bake block in + return block + | messages -> + let* operation_add_message = + Op.sc_rollup_add_messages (B block) contract messages + in + let* block = + Block.bake ~operation:operation_add_message block + in + return block + in + + return + (block, {messages_per_level with predecessor; predecessor_timestamp})) + block + list_of_messages + in + return (block, list_of_messages) +end + +let is_reveal_enabled_default = + Sc_rollup.is_reveal_enabled_predicate + Default_parameters.constants_mainnet.sc_rollup.reveal_activation_level + +let tick_of_int_exn ?(__LOC__ = __LOC__) n = + WithExceptions.Option.get ~loc:__LOC__ (Sc_rollup.Tick.of_int n) + +module type PVM_eval = sig + include Sc_rollup.PVM.S + + val make_empty_context : unit -> context + + val initial_hash : hash Lwt.t + + val eval_until_input : + fuel:int option -> + our_states:(int * hash) trace -> + int -> + state -> + (state * int option * int * (int * hash) trace) Lwt.t + + val eval_inputs_from_initial_state : + metadata:Sc_rollup.Metadata.t -> + ?fuel:int -> + ?bootsector:string -> + Sc_rollup.input trace trace -> + (state * Sc_rollup.Tick.t * (Sc_rollup.Tick.t * hash) trace, 'a) result + Lwt.t +end + +module Make_PVM_eval (PVM : sig + include Sc_rollup.PVM.S + + val make_empty_state : unit -> state + + val make_empty_context : unit -> context +end) : PVM_eval with type context = PVM.context and type state = PVM.state = +struct + include PVM + + let bootsector_state ~bootsector = + let open Lwt_syntax in + let empty = make_empty_state () in + let* state = initial_state ~empty in + let* state = install_boot_sector state bootsector in + return state + + let initial_hash = + let open Lwt_syntax in + let empty = make_empty_state () in + let* state = initial_state ~empty in + state_hash state + + let consume_fuel = Option.map pred + + let continue_with_fuel ~our_states ~(tick : int) fuel state f = + let open Lwt_syntax in + match fuel with + | Some 0 -> return (state, fuel, tick, our_states) + | _ -> f tick our_states (consume_fuel fuel) state + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3498 + + the following is almost the same code as in the rollup node, except that it + creates the association list (tick, state_hash). *) + let eval_until_input ~fuel ~our_states start_tick state = + let open Lwt_syntax in + let rec go ~our_states fuel (tick : int) state = + let* input_request = + is_input_state ~is_reveal_enabled:is_reveal_enabled_default state + in + match fuel with + | Some 0 -> return (state, fuel, tick, our_states) + | None | Some _ -> ( + match input_request with + | No_input_required -> + let* state = eval state in + let* state_hash = state_hash state in + let our_states = (tick, state_hash) :: our_states in + go ~our_states (consume_fuel fuel) (tick + 1) state + | Needs_reveal (Request_dal_page _pid) -> + (* TODO/DAL: https://gitlab.com/tezos/tezos/-/issues/4160 + We assume that there are no confirmed Dal slots. + We'll reuse the infra to provide Dal pages in the future. *) + let input = Sc_rollup.(Reveal (Dal_page None)) in + let* state = set_input input state in + let* state_hash = state_hash state in + let our_states = (tick, state_hash) :: our_states in + go ~our_states (consume_fuel fuel) (tick + 1) state + | Needs_reveal (Reveal_raw_data _) + | Needs_reveal Reveal_metadata + | Needs_reveal Reveal_dal_parameters + | Initial | First_after _ -> + return (state, fuel, tick, our_states)) + in + go ~our_states fuel start_tick state + + let eval_metadata ~fuel ~our_states tick state ~metadata = + let open Lwt_syntax in + continue_with_fuel ~our_states ~tick fuel state + @@ fun tick our_states fuel state -> + let input = Sc_rollup.(Reveal (Metadata metadata)) in + let* state = set_input input state in + let* state_hash = state_hash state in + let our_states = (tick, state_hash) :: our_states in + let tick = succ tick in + return (state, fuel, tick, our_states) + + let feed_input ~fuel ~our_states ~tick state input = + let open Lwt_syntax in + let* state, fuel, tick, our_states = + eval_until_input ~fuel ~our_states tick state + in + continue_with_fuel ~our_states ~tick fuel state + @@ fun tick our_states fuel state -> + let* state = set_input input state in + let* state_hash = state_hash state in + let our_states = (tick, state_hash) :: our_states in + let tick = tick + 1 in + let* state, fuel, tick, our_states = + eval_until_input ~fuel ~our_states tick state + in + return (state, fuel, tick, our_states) + + let eval_inbox ?fuel ~inputs ~tick state = + let open Lwt_result_syntax in + List.fold_left_es + (fun (state, fuel, tick, our_states) input -> + let*! state, fuel, tick, our_states = + feed_input ~fuel ~our_states ~tick state input + in + return (state, fuel, tick, our_states)) + (state, fuel, tick, []) + inputs + + let eval_inputs ~fuel ~tick ?(our_states = []) ~inputs_per_levels state = + let open Lwt_result_syntax in + List.fold_left_es + (fun (state, fuel, tick, our_states) inputs -> + let* state, fuel, tick, our_states' = + eval_inbox ?fuel ~inputs ~tick state + in + return (state, fuel, tick, our_states @ our_states')) + (state, fuel, tick, our_states) + inputs_per_levels + + let eval_inputs_from_initial_state ~metadata ?fuel ?(bootsector = "") + inputs_per_levels = + let open Lwt_result_syntax in + let*! state = bootsector_state ~bootsector in + let*! state_hash = state_hash state in + let tick = 0 in + let our_states = [(tick, state_hash)] in + let tick = succ tick in + (* 1. We evaluate the boot sector. *) + let*! state, fuel, tick, our_states = + eval_until_input ~fuel ~our_states tick state + in + (* 2. We evaluate the metadata. *) + let*! state, fuel, tick, our_states = + eval_metadata ~fuel ~our_states tick state ~metadata + in + (* 3. We evaluate the inbox. *) + let* state, _fuel, tick, our_states = + eval_inputs state ~fuel ~tick ~our_states ~inputs_per_levels + in + let our_states = + List.sort (fun (x, _) (y, _) -> Compare.Int.compare x y) our_states + in + let our_states = + List.map + (fun (tick_int, state) -> (tick_of_int_exn tick_int, state)) + our_states + in + let tick = tick_of_int_exn tick in + return (state, tick, our_states) +end + +module Arith_pvm_eval = Make_PVM_eval (Arith_pvm) +module Wasm_pvm_eval = Make_PVM_eval (Wasm_pvm) + +let make_pvm_with_context_and_state (type context state) + (module PVM : Sc_rollup.PVM.S + with type context = context + and type state = state) ~state ~context ~reveal ~inbox () : + (module Sc_rollup.Proof.PVM_with_context_and_state) = + let Node_inbox.{payloads_histories; history; inbox} = inbox in + (module struct + include PVM + + let context : context = context + + let state = state + + let reveal = reveal + + module Inbox_with_history = struct + let inbox = Sc_rollup.Inbox.old_levels_messages inbox + + let get_history inbox = + Sc_rollup.Inbox.History.find inbox history |> Lwt.return + + let get_payloads_history witness_hash = + Payloads_histories.find witness_hash payloads_histories + |> WithExceptions.Option.get ~loc:__LOC__ + |> Lwt.return + end + + (* FIXME/DAL-REFUTATION: https://gitlab.com/tezos/tezos/-/issues/3992 + Extend refutation game to handle Dal refutation case. *) + module Dal_with_history = struct + let confirmed_slots_history = Dal.Slots_history.genesis + + let get_history _hash = Lwt.return_none + + let page_info = None + + let dal_parameters = + Default_parameters.constants_test.dal.cryptobox_parameters + + let dal_attestation_lag = + Default_parameters.constants_test.dal.attestation_lag + + let dal_number_of_slots = + Default_parameters.constants_test.dal.number_of_slots + + let dal_activation_level = + let constants = Default_parameters.constants_test in + if constants.dal.feature_enable then + Some constants.sc_rollup.reveal_activation_level.dal_parameters + else None + + let dal_attested_slots_validity_lag = + let constants = Default_parameters.constants_test in + constants.sc_rollup.reveal_activation_level + .dal_attested_slots_validity_lag + end + end) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.ml new file mode 100644 index 000000000000..b5a21d8219aa --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.ml @@ -0,0 +1,14 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(*****************************************************************************) + +let update k v m ctxt = Protocol.Script_big_map.update ctxt k v m + +let of_list key_ty ty xs ctxt = + List.fold_left_es + (fun (bm, ctxt) (k, v) -> update k (Some v) bm ctxt) + (Protocol.Script_big_map.empty key_ty ty, ctxt) + xs diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.mli new file mode 100644 index 000000000000..f87ffc773395 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_big_map.mli @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(*****************************************************************************) + +(** Update a big map. See [Script_typed_ir.big_map_get_and_update] for details. *) +val update : + 'key -> + 'value option -> + ('key, 'value) Protocol.Script_typed_ir.big_map -> + Protocol.Alpha_context.t -> + (('key, 'value) Protocol.Script_typed_ir.big_map * Protocol.Alpha_context.t) + Environment.Error_monad.tzresult + Lwt.t + +(** Convert a list to a [Script_big_map]. If the list contains duplicate keys, + the first occurence is used. + *) +val of_list : + 'key Protocol.Script_typed_ir.comparable_ty -> + ('value, _) Protocol.Script_typed_ir.ty -> + ('key * 'value) list -> + Protocol.Alpha_context.t -> + (('key, 'value) Protocol.Script_typed_ir.big_map * Protocol.Alpha_context.t) + Environment.Error_monad.tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.ml new file mode 100644 index 000000000000..5b780f7ac8e2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.ml @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let of_list : + type k v. + k Protocol.Script_typed_ir.comparable_ty -> + (k * v) list -> + (k, v) Protocol.Script_typed_ir.map = + fun ty1 xs -> + List.fold_left + (fun rs (k, v) -> Protocol.Script_map.update k (Some v) rs) + (Protocol.Script_map.empty ty1) + xs diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.mli new file mode 100644 index 000000000000..e81cf5956c93 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_map.mli @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Convert a list to a [Script_map]. If the list contains duplicate keys, + the last occurence is used. *) +val of_list : + 'k Protocol.Script_typed_ir.comparable_ty -> + ('k * 'v) list -> + ('k, 'v) Protocol.Script_typed_ir.map diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.ml new file mode 100644 index 000000000000..b02d082465a4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.ml @@ -0,0 +1,31 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let of_list ty1 xs = + List.fold_left + (fun rs k -> Protocol.Script_set.update k true rs) + (Protocol.Script_set.empty ty1) + xs diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.mli new file mode 100644 index 000000000000..7df70020e3b3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/script_set.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Convert a list to a Script IR set. If the list contains duplicates, + the last occurence is used. *) +val of_list : + 'a Protocol.Script_typed_ir.comparable_ty -> + 'a list -> + 'a Protocol.Script_typed_ir.set diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/test_global_constants.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/test_global_constants.ml new file mode 100644 index 000000000000..c05ae1b804b2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/test_global_constants.ml @@ -0,0 +1,325 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Micheline +open Michelson_v1_primitives + +let create_context () = + let open Lwt_result_syntax in + let*? accounts = Account.generate_accounts 2 in + Block.alpha_context (Account.make_bootstrap_accounts accounts) + +let expr_to_hash expr = + let open Result_syntax in + let lexpr = Script_repr.lazy_expr expr in + let+ b = Script_repr.force_bytes lexpr in + Script_expr_hash.hash_bytes [b] + +let assert_expr_equal loc = + Assert.equal + ~loc + ( = ) + "Michelson Expressions Not Equal" + Michelson_v1_printer.print_expr + +let assert_proto_error_id loc id result = + let test err = + (Error_monad.find_info_of_error err).id + = "proto." ^ Protocol.name ^ "." ^ id + in + Assert.error ~loc result test + +let assert_ok_lwt x = + match Lwt_main.run x with + | Ok x -> x + | Error _ -> raise @@ Failure "Called assert_ok_lwt on Error" + +let assert_ok = function + | Ok x -> x + | Error _ -> raise @@ Failure "Called assert_ok on Error" + +(** Filters out values that would cause [register] *) +let assume_expr_not_too_large expr = + let node = root expr in + QCheck2.assume @@ not + @@ Global_constants_storage.Internal_for_tests.node_too_large node + +module Generators = struct + let context_gen () = QCheck2.Gen.return (create_context () |> assert_ok_lwt) + + let prims = + [ + K_parameter; + K_storage; + K_code; + D_False; + D_Elt; + D_Left; + D_None; + D_Pair; + D_Right; + D_Some; + D_True; + D_Unit; + D_Ticket; + I_PACK; + I_UNPACK; + I_BLAKE2B; + I_SHA256; + I_SHA512; + I_ABS; + I_ADD; + I_AMOUNT; + I_AND; + I_BALANCE; + I_CAR; + I_CDR; + I_CHAIN_ID; + I_CHECK_SIGNATURE; + I_COMPARE; + I_CONCAT; + I_CONS; + I_CREATE_ACCOUNT; + I_CREATE_CONTRACT; + I_IMPLICIT_ACCOUNT; + I_DIP; + I_DROP; + I_DUP; + I_EDIV; + I_EMPTY_BIG_MAP; + I_EMPTY_MAP; + I_EMPTY_SET; + I_EQ; + I_EXEC; + I_APPLY; + I_FAILWITH; + I_GE; + I_GET; + I_GET_AND_UPDATE; + I_GT; + I_HASH_KEY; + I_IF; + I_IF_CONS; + I_IF_LEFT; + I_IF_NONE; + I_INT; + I_LAMBDA; + I_LE; + I_LEFT; + I_LEVEL; + I_LOOP; + I_LSL; + I_LSR; + I_LT; + I_MAP; + I_MEM; + I_MUL; + I_NEG; + I_NEQ; + I_NIL; + I_NONE; + I_NOT; + I_NOW; + I_OR; + I_PAIR; + I_UNPAIR; + I_PUSH; + I_RIGHT; + I_SIZE; + I_SOME; + I_SOURCE; + I_SENDER; + I_SELF; + I_SELF_ADDRESS; + I_SLICE; + I_STEPS_TO_QUOTA; + I_SUB; + I_SWAP; + I_TRANSFER_TOKENS; + I_SET_DELEGATE; + I_UNIT; + I_UPDATE; + I_XOR; + I_ITER; + I_LOOP_LEFT; + I_ADDRESS; + I_CONTRACT; + I_ISNAT; + I_CAST; + I_RENAME; + I_SAPLING_EMPTY_STATE; + I_SAPLING_VERIFY_UPDATE; + I_DIG; + I_DUG; + I_NEVER; + I_VOTING_POWER; + I_TOTAL_VOTING_POWER; + I_KECCAK; + I_SHA3; + I_PAIRING_CHECK; + I_TICKET; + I_READ_TICKET; + I_SPLIT_TICKET; + I_JOIN_TICKETS; + T_bool; + T_contract; + T_int; + T_key; + T_key_hash; + T_lambda; + T_list; + T_map; + T_big_map; + T_nat; + T_option; + T_or; + T_pair; + T_set; + T_signature; + T_string; + T_bytes; + T_mutez; + T_timestamp; + T_unit; + T_operation; + T_address; + T_sapling_transaction_deprecated; + T_sapling_state; + T_chain_id; + T_never; + T_bls12_381_g1; + T_bls12_381_g2; + T_bls12_381_fr; + T_ticket; + H_constant; + ] + + let prim_gen = QCheck2.Gen.oneofl prims + + let prims_without_constants_gen = + QCheck2.Gen.oneofl (List.filter (fun x -> x != H_constant) prims) + + let z_gen = QCheck2.Gen.map Z.of_int QCheck2.Gen.int + + let micheline_node_gen l_gen p_gen annot_gen : + ('l, 'p) Micheline.node QCheck2.Gen.t = + let open Micheline in + let open QCheck2.Gen in + fix + (fun self () -> + frequency + [ + (3, map (fun (l, x) -> Int (l, x)) (pair l_gen z_gen)); + (3, map (fun (l, x) -> String (l, x)) (pair l_gen string)); + ( 3, + map + (fun (l, x) -> Bytes (l, Bytes.of_string x)) + (pair l_gen string) ); + ( 1, + map + (fun (l, p, args, annot) -> Prim (l, p, args, annot)) + (quad + l_gen + p_gen + (list_size (int_bound 10) (self ())) + annot_gen) ); + ( 1, + map + (fun (l, args) -> Seq (l, args)) + (pair l_gen (list_size (int_bound 10) (self ()))) ); + ]) + () + + let rec replace_with_constant : + Script.node -> Script.location -> Script.node * Script.node option = + fun node loc -> + let open Michelson_v1_primitives in + let open Micheline in + let rec loop : Script.node list -> Script.node list * Script.node option = + function + | [] -> ([], None) + | hd :: tl -> ( + match replace_with_constant hd loc with + | node, Some x -> (node :: tl, Some x) + | _, None -> + let l, x = loop tl in + (hd :: l, x)) + in + match node with + | (Int (l, _) | String (l, _) | Bytes (l, _)) as node -> + if l = loc then + let hash = + node |> strip_locations |> expr_to_hash |> assert_ok + |> Script_expr_hash.to_b58check + in + (Prim (-1, H_constant, [String (-1, hash)], []), Some node) + else (node, None) + | Prim (l, prim, args, annot) as node -> + if l = loc then + let hash = + node |> strip_locations |> expr_to_hash |> assert_ok + |> Script_expr_hash.to_b58check + in + (Prim (-1, H_constant, [String (-1, hash)], []), Some node) + else + let result, x = loop args in + (Prim (l, prim, result, annot), x) + | Seq (l, args) as node -> + if l = loc then + let hash = + node |> strip_locations |> expr_to_hash |> assert_ok + |> Script_expr_hash.to_b58check + in + (Prim (-1, H_constant, [String (-1, hash)], []), Some node) + else + let result, x = loop args in + (Seq (l, result), x) + + let micheline_gen p_gen annot_gen = + QCheck2.Gen.map + Micheline.strip_locations + (micheline_node_gen (QCheck2.Gen.return (-1)) p_gen annot_gen) + + let canonical_without_constant_gen () = + QCheck2.Gen.map + strip_locations + (micheline_node_gen + (QCheck2.Gen.return (-1)) + prims_without_constants_gen + (QCheck2.Gen.return [])) + + let canonical_with_constant_gen () = + let open QCheck2.Gen in + canonical_without_constant_gen () >>= fun expr -> + let size = Script_repr.micheline_nodes (root expr) in + 0 -- (size - 1) >|= fun loc -> + match replace_with_constant (root expr) loc with + | _, None -> assert false + | node, Some replaced_node -> + (expr, strip_locations node, strip_locations replaced_node) +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/test_tez.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/test_tez.ml new file mode 100644 index 000000000000..7d523a82c98e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/test_tez.ml @@ -0,0 +1,68 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Environment + +(* This module wraps the errors from the protocol *) +open Tez + +let ( +? ) t1 t2 = t1 +? t2 |> wrap_tzresult + +let ( -? ) t1 t2 = t1 -? t2 |> wrap_tzresult + +let ( *? ) t1 t2 = t1 *? t2 |> wrap_tzresult + +let ( +! ) t1 t2 = + match t1 +? t2 with Ok r -> r | Error _ -> Pervasives.failwith "adding tez" + +let ( -! ) t1 t2 = + match t1 -? t2 with + | Ok r -> r + | Error _ -> Pervasives.failwith "subtracting tez" + +let ( *! ) t1 t2 = + match t1 *? t2 with + | Ok r -> r + | Error _ -> Pervasives.failwith "multiplying tez" + +let ( /! ) t1 t2 = + match t1 /? t2 with + | Ok r -> r + | Error _ -> Pervasives.failwith "dividing tez" + +let of_int x = + match Tez.of_mutez (Int64.mul (Int64.of_int x) 1_000_000L) with + | None -> invalid_arg "tez_of_int" + | Some x -> x + +let of_mutez_exn x = + match Tez.of_mutez x with None -> invalid_arg "tez_of_mutez" | Some x -> x + +let to_mutez = Tez.to_mutez + +let max_tez = + match Tez.of_mutez Int64.max_int with None -> assert false | Some p -> p diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/testable.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/testable.ml new file mode 100644 index 000000000000..80702598e1a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/testable.ml @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let contract : Protocol.Alpha_context.Contract.t Alcotest.testable = + let open Protocol in + let open Alpha_context in + Alcotest.testable Contract.pp Contract.( = ) + +let script_expr : Protocol.Alpha_context.Script.expr Alcotest.testable = + Alcotest.testable Michelson_v1_printer.print_expr ( = ) + +let trace : tztrace Alcotest.testable = Alcotest.testable pp_print_trace ( = ) + +let protocol_error : Environment.Error_monad.error Alcotest.testable = + Alcotest.testable Environment.Error_monad.pp ( = ) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/ticket_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/ticket_helpers.ml new file mode 100644 index 000000000000..f3fe9ad5805e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/ticket_helpers.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let assert_balance ctxt ~loc key expected = + let open Lwt_result_wrap_syntax in + let*@ balance, _ = Ticket_balance.get_balance ctxt key in + match (balance, expected) with + | Some b, Some eb -> Assert.equal_int ~loc (Z.to_int b) eb + | None, Some eb -> failwith "Expected balance %d" eb + | Some eb, None -> failwith "Expected None but got %d" (Z.to_int eb) + | None, None -> return_unit + +let string_ticket_token ticketer content = + let open Lwt_result_wrap_syntax in + let contents = + Result.value_f ~default:(fun _ -> assert false) + @@ Script_string.of_string content + in + let*?@ ticketer = Contract.of_b58check ticketer in + return + (Ticket_token.Ex_token + {ticketer; contents_type = Script_typed_ir.string_t; contents}) + +let adjust_ticket_token_balance alpha_ctxt owner ticket_token ~delta = + let open Lwt_result_wrap_syntax in + let*@ ticket_token_hash, ctxt = + Ticket_balance_key.of_ex_token alpha_ctxt ~owner ticket_token + in + let*@ (_ : Z.t), alpha_ctxt = + Ticket_balance.adjust_balance ctxt ticket_token_hash ~delta + in + return (ticket_token_hash, alpha_ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.ml new file mode 100644 index 000000000000..f04fab9a7c8e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.ml @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Test_tez + +let transfer_and_check_balances ?(with_burn = false) ~loc b ?(fee = Tez.zero) + ?expect_apply_failure src dst amount = + let open Lwt_result_syntax in + let*? amount_fee = fee +? amount in + let* bal_src = Context.Contract.balance (I b) src in + let* bal_dst = Context.Contract.balance (I b) dst in + let* op = + Op.transaction + ~force_reveal:true + ~gas_limit:(Custom_gas (Alpha_context.Gas.Arith.integral_of_int_exn 3000)) + (I b) + ~fee + src + dst + amount + in + let* b = Incremental.add_operation ?expect_apply_failure b op in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (I b) + in + let*? origination_burn = cost_per_byte *? Int64.of_int origination_size in + let*? amount_fee_burn = amount_fee +? origination_burn in + let amount_fee_maybe_burn = + if with_burn then amount_fee_burn else amount_fee + in + let* () = + Assert.balance_was_debited ~loc (I b) src bal_src amount_fee_maybe_burn + in + let+ () = Assert.balance_was_credited ~loc (I b) dst bal_dst amount in + (b, op) + +let n_transactions n b ?fee source dest amount = + let open Lwt_result_syntax in + List.fold_left_es + (fun b _ -> + let* i, _ = + transfer_and_check_balances ~loc:__LOC__ b ?fee source dest amount + in + let* b = Incremental.finalize_block i in + Incremental.begin_construction b) + b + (1 -- n) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.mli b/src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.mli new file mode 100644 index 000000000000..86e17da6e2e4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/transfers.mli @@ -0,0 +1,68 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** [transfer_and_check_balances b fee src dst amount] + this function takes a block, an optional parameter fee if fee does not + given it will be set to zero tez, a source contract, a destination contract + and the amount that one wants to transfer. + + 1- Transfer the amount of tez (w/wo fee) from a source contract to a + destination contract. + + 2- Check the equivalent of the balance of the source/destination + contract before and after transfer is validated. + + This function returns a pair: + - A block that added a valid operation + - a valid operation *) +val transfer_and_check_balances : + ?with_burn:bool -> + loc:string -> + Incremental.t -> + ?fee:Tez.t -> + ?expect_apply_failure:(error trace -> unit tzresult Lwt.t) -> + Contract.t -> + Contract.t -> + Tez.t -> + (Incremental.t * packed_operation) tzresult Lwt.t + +(** [n_transactions n b fee source dest amount] + this function takes a number of "n" that one wish to transfer, + a block, an optional parameter fee, a source contract, + a destination contract and an amount one wants to transfer. + + This function will do a transaction from a source contract to + a destination contract with the amount "n" times. *) +val n_transactions : + int -> + Incremental.t -> + ?fee:Tez.t -> + Contract.t -> + Contract.t -> + Tez.t -> + Incremental.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml new file mode 100644 index 000000000000..eb710552b7cc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/zk_rollup_l2_helpers.ml @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Dummy_zk_rollup = Dummy_zk_rollup diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune new file mode 100644 index 000000000000..422f3420d041 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune @@ -0,0 +1,64 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name + src_proto_019_PtParisB_lib_protocol_test_integration_consensus_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-alcotezt + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.base-test-helpers + tezos-protocol-019-PtParisB.parameters + octez-protocol-019-PtParisB-libs.plugin) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_019_PtParisB_test_helpers + -open Tezos_base_test_helpers + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_plugin_019_PtParisB) + (modules + test_baking + test_consensus_key + test_deactivation + test_delegation + test_double_baking + test_double_attestation + test_double_preattestation + test_attestation + test_frozen_deposits + test_helpers_rpcs + test_participation + test_preattestation_functor + test_preattestation + test_seed)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_integration_consensus_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_attestation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_attestation.ml new file mode 100644 index 000000000000..d7a118715297 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_attestation.ml @@ -0,0 +1,894 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (attestation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_attestation.ml + Subject: Attesting a block adds an extra layer of confidence + to the Tezos' PoS algorithm. The block attesting + operation must be included in the following block. +*) + +open Protocol +open Alpha_context + +let init_genesis ?policy ?dal_enable () = + let open Lwt_result_syntax in + let* genesis, _contracts = + Context.init_n ?dal_enable ~consensus_threshold:0 5 () + in + let* b = Block.bake ?policy genesis in + return (genesis, b) + +(** {1 Positive tests} *) + +(** Correct attestation from the slot 0 attester. *) +let test_simple_attestation () = + let open Lwt_result_syntax in + let* _genesis, attested_block = init_genesis () in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~attested_block + Attestation + +(** Test that the attestation's branch does not affect its + validity. *) +let test_arbitrary_branch () = + let open Lwt_result_syntax in + let* _genesis, attested_block = init_genesis () in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~attested_block + ~branch:Block_hash.zero + Attestation + +(** Correct attestation with a level and a round that are both + different from {!test_simple_attestation}. *) +let test_non_zero_round () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* attested_block = Block.bake ~policy:(By_round 10) b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~attested_block + Attestation + +(** Fitness gap: this is a straightforward update from Emmy to Tenderbake, + that is, check that the level is incremented in a child block. *) +let test_fitness_gap () = + let open Lwt_result_syntax in + let* _genesis, pred_b = init_genesis () in + let* operation = Op.attestation pred_b in + let* b = Block.bake ~operation pred_b in + let fitness = + match Fitness.from_raw b.header.shell.fitness with + | Ok fitness -> fitness + | _ -> assert false + in + let pred_fitness = + match Fitness.from_raw pred_b.header.shell.fitness with + | Ok fitness -> fitness + | _ -> assert false + in + let level = Fitness.level fitness in + let pred_level = Fitness.level pred_fitness in + let level_diff = + Int32.sub (Raw_level.to_int32 level) (Raw_level.to_int32 pred_level) + in + Assert.equal_int32 ~loc:__LOC__ level_diff 1l + +(** Return a delegate and its second smallest slot for the level of [block]. *) +let delegate_and_second_slot block = + let open Lwt_result_syntax in + let* attesters = Context.get_attesters (B block) in + let delegate, slots = + (* Find an attester with more than 1 slot. *) + WithExceptions.Option.get + ~loc:__LOC__ + (List.find_map + (fun {RPC.Validators.delegate; slots; _} -> + if Compare.List_length_with.(slots > 1) then Some (delegate, slots) + else None) + attesters) + in + (* Check that the slots are sorted and have no duplicates. *) + let rec check_sorted = function + | [] | [_] -> true + | x :: (y :: _ as t) -> Slot.compare x y < 0 && check_sorted t + in + assert (check_sorted slots) ; + let slot = + match slots with [] | [_] -> assert false | _ :: slot :: _ -> slot + in + return (delegate, slot) + +(** Test that the mempool accepts attestations with a non-normalized + slot (that is, a slot that belongs to the delegate but is not the + delegate's smallest slot) at all three allowed levels for + attestations (and various rounds). *) +let test_mempool_second_slot () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent ~policy:(By_round 3) in + let* future_block = Block.bake predecessor ~policy:(By_round 5) in + let check_non_smallest_slot_ok loc attested_block = + let* delegate, slot = delegate_and_second_slot attested_block in + Consensus_helpers.test_consensus_operation + ~loc + ~attested_block + ~predecessor + ~delegate + ~slot + Attestation + Mempool + in + let* () = check_non_smallest_slot_ok __LOC__ grandparent in + let* () = check_non_smallest_slot_ok __LOC__ predecessor in + check_non_smallest_slot_ok __LOC__ future_block + +(** {1 Negative tests} + + The following test scenarios are supposed to raise errors. *) + +(** {2 Wrong slot} *) + +(** Apply an attestation with a negative slot. *) +let test_negative_slot () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init_n 5 () in + let* b = Block.bake genesis in + let* delegate, _slots = Context.get_attester (B b) in + Lwt.catch + (fun () -> + let* (_ : packed_operation) = + Op.attestation + ~delegate + ~slot:(Slot.of_int_do_not_use_except_for_parameters (-1)) + b + in + failwith "negative slot should not be accepted by the binary format") + (function + | Data_encoding.Binary.Write_error _ -> return_unit | e -> Lwt.reraise e) + +(** Attestation with a non-normalized slot (that is, a slot that + belongs to the delegate but is not the delegate's smallest slot). + It should fail in application and construction modes, but be + accepted in mempool mode. *) +let test_not_smallest_slot () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* delegate, slot = delegate_and_second_slot b in + let error_wrong_slot = function + | Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation + {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false + in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:b + ~delegate + ~slot + ~application_error:error_wrong_slot + ~construction_error:error_wrong_slot + ?mempool_error:None + Attestation + +let delegate_and_someone_elses_slot block = + let open Lwt_result_syntax in + let* attesters = Context.get_attesters (B block) in + let delegate, other_delegate_slot = + match attesters with + | [] | [_] -> assert false (* at least two delegates with rights *) + | {delegate; _} :: {slots; _} :: _ -> + (delegate, WithExceptions.Option.get ~loc:__LOC__ (List.hd slots)) + in + return (delegate, other_delegate_slot) + +(** Attestation with a slot that does not belong to the delegate. *) +let test_not_own_slot () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* delegate, other_delegate_slot = delegate_and_someone_elses_slot b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~attested_block:b + ~delegate + ~slot:other_delegate_slot + ~error:(function + | Alpha_context.Operation.Invalid_signature -> true | _ -> false) + Attestation + +(** In mempool mode, also test attestations with a slot that does not + belong to the delegate for various allowed levels and rounds. *) +let test_mempool_not_own_slot () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis ~policy:(By_round 2) () in + let* predecessor = Block.bake grandparent ~policy:(By_round 1) in + let* future_block = Block.bake predecessor in + let check_not_own_slot_fails loc b = + let* delegate, other_delegate_slot = delegate_and_someone_elses_slot b in + Consensus_helpers.test_consensus_operation + ~loc + ~attested_block:b + ~delegate + ~slot:other_delegate_slot + ~error:(function + | Alpha_context.Operation.Invalid_signature -> true | _ -> false) + Attestation + Mempool + in + let* () = check_not_own_slot_fails __LOC__ grandparent in + let* () = check_not_own_slot_fails __LOC__ predecessor in + check_not_own_slot_fails __LOC__ future_block + +(** {2 Wrong level} *) + +let error_old_level = function + | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false + +(** Attestation that is one level too old, aka grandparent attestation + (the attestation is expected to point to the level of the + predecessor of the block/mempool containing the attestation, but + instead it points to the grandparent's level). + + This attestation should fail in a block (application or + construction), but be accepted in mempool mode. *) +let test_one_level_too_old () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:grandparent + ~predecessor + ~application_error:error_old_level + ~construction_error:error_old_level + ?mempool_error:None + Attestation + +(** Attestation that is two levels too old (pointing to the + great-grandparent instead of the predecessor). It should fail in + all modes. *) +let test_two_levels_too_old () = + let open Lwt_result_syntax in + let* _genesis, greatgrandparent = init_genesis () in + let* grandparent = Block.bake greatgrandparent in + let* predecessor = Block.bake grandparent in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~attested_block:greatgrandparent + ~predecessor + ~error:error_old_level + Attestation + +let error_future_level = function + | Validate_errors.Consensus.Consensus_operation_for_future_level {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false + +(** Attestation that is one level in the future (pointing to the same + level as the block/mempool containing the attestation instead of + its predecessor/head). It should fail in a block (application or + construction) but succeed in a mempool. *) +let test_one_level_in_the_future () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* next_level_block = Block.bake predecessor in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:next_level_block + ~predecessor + ~application_error:error_future_level + ~construction_error:error_future_level + ?mempool_error:None + Attestation + +(** Attestation that is two levels in the future. It should fail in + all modes. *) +let test_two_levels_future () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* next_level_block = Block.bake predecessor in + let* after_next_level_block = Block.bake next_level_block in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~attested_block:after_next_level_block + ~predecessor + ~error:error_future_level + Attestation + +(** {2 Wrong round} *) + +let error_old_round = function + | Validate_errors.Consensus.Consensus_operation_for_old_round {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false + +(** Attestation that is one round too old. It should fail in a block + (application or construction) but succeed in a mempool. *) +let test_one_round_too_old () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* round0_block = Block.bake b in + let* predecessor = Block.bake ~policy:(By_round 1) b in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:round0_block + ~predecessor + ~application_error:error_old_round + ~construction_error:error_old_round + ?mempool_error:None + Attestation + +(** Attestation that is many rounds too old. It should fail in a block + (application or construction) but succeed in a mempool. *) +let test_many_rounds_too_old () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* round5_block = Block.bake ~policy:(By_round 5) b in + let* predecessor = Block.bake ~policy:(By_round 15) b in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:round5_block + ~predecessor + ~application_error:error_old_round + ~construction_error:error_old_round + ?mempool_error:None + Attestation + +let error_future_round = function + | Validate_errors.Consensus.Consensus_operation_for_future_round {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false + +(** Attestation that is one round in the future. It should fail in a + block (application or construction) but succeed in a mempool. *) +let test_one_round_in_the_future () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* predecessor = Block.bake b in + let* round1_block = Block.bake ~policy:(By_round 1) b in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:round1_block + ~predecessor + ~application_error:error_future_round + ~construction_error:error_future_round + ?mempool_error:None + Attestation + +(** Attestation that is many rounds in the future. It should fail in a + block (application or construction) but succeed in a mempool. *) +let test_many_rounds_future () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* predecessor = Block.bake ~policy:(By_round 5) b in + let* round15_block = Block.bake ~policy:(By_round 15) b in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block:round15_block + ~predecessor + ~application_error:error_future_round + ~construction_error:error_future_round + ?mempool_error:None + Attestation + +(** {2 Wrong payload hash} *) + +(** Attestation with an incorrect payload hash. It should fail in a + block (application or construction) but succeed in a mempool. *) +let test_wrong_payload_hash () = + let open Lwt_result_syntax in + let* _genesis, attested_block = init_genesis () in + let error_wrong_payload_hash = function + | Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation + {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false + in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~attested_block + ~block_payload_hash:Block_payload_hash.zero + ~application_error:error_wrong_payload_hash + ~construction_error:error_wrong_payload_hash + ?mempool_error:None + Attestation + +(** {1 Conflict tests} + + Some positive and some negative tests. *) + +let assert_conflict_error ~loc res = + Assert.proto_error ~loc res (function + | Validate_errors.Consensus.Conflicting_consensus_operation {kind; _} + when kind = Validate_errors.Consensus.Attestation -> + true + | _ -> false) + +(** Test that attestations conflict with: + - an identical attestation, and + - an attestation on the same block with a different branch. + + In mempool mode, also test that they conflict with an attestation + on the same level and round but with a different payload hash + (such an attestation is invalid in application and construction modes). *) +let test_conflict () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* op = Op.attestation b in + let* op_different_branch = Op.attestation ~branch:Block_hash.zero b in + (* Test in application and construction (aka baking) modes *) + let assert_conflict loc baking_mode tested_op = + let*! block = Block.bake ~baking_mode ~operations:[op; tested_op] b in + assert_conflict_error ~loc block + in + let* () = assert_conflict __LOC__ Application op in + let* () = assert_conflict __LOC__ Application op_different_branch in + let* () = assert_conflict __LOC__ Baking op in + let* () = assert_conflict __LOC__ Baking op_different_branch in + (* Test in mempool mode. *) + let* inc = Incremental.begin_construction ~mempool_mode:true b in + let* inc = Incremental.validate_operation inc op in + let assert_mempool_conflict loc tested_op = + let*! result = Incremental.validate_operation inc tested_op in + assert_conflict_error ~loc result + in + let* () = assert_mempool_conflict __LOC__ op in + let* () = assert_mempool_conflict __LOC__ op_different_branch in + let* op_different_payload_hash = + Op.attestation ~block_payload_hash:Block_payload_hash.zero b + in + let* () = assert_mempool_conflict __LOC__ op_different_payload_hash in + return_unit + +(** In mempool mode, test that grandparent attestations conflict with: + - an identical attestation, + - an attestation on the same block with a different branch, and + - an attestation on the same block with a different payload hash. + + This test would make no sense in application or construction modes, + since grandparent attestations fail anyway (as can be observed in + {!test_one_level_too_old}). *) +let test_grandparent_conflict () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent in + let* op = Op.attestation grandparent in + let* op_different_branch = + Op.attestation ~branch:Block_hash.zero grandparent + in + let* op_different_payload_hash = + Op.attestation ~block_payload_hash:Block_payload_hash.zero grandparent + in + let* inc = Incremental.begin_construction ~mempool_mode:true predecessor in + let* inc = Incremental.validate_operation inc op in + let assert_conflict loc tested_op = + let*! result = Incremental.validate_operation inc tested_op in + assert_conflict_error ~loc result + in + let* () = assert_conflict __LOC__ op in + let* () = assert_conflict __LOC__ op_different_branch in + let* () = assert_conflict __LOC__ op_different_payload_hash in + return_unit + +(** In mempool mode, test that attestations with the same future level + and same non-zero round conflict. This is not tested in application + and construction modes since such attestations would be invalid. *) +let test_future_level_conflict () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* future_block = Block.bake ~policy:(By_round 10) predecessor in + let* op = Op.attestation future_block in + let* op_different_branch = + Op.attestation ~branch:Block_hash.zero future_block + in + let* op_different_payload_hash = + Op.attestation ~block_payload_hash:Block_payload_hash.zero future_block + in + let* inc = Incremental.begin_construction ~mempool_mode:true predecessor in + let* inc = Incremental.validate_operation inc op in + let assert_conflict loc tested_op = + let*! result = Incremental.validate_operation inc tested_op in + assert_conflict_error ~loc result + in + let* () = assert_conflict __LOC__ op in + let* () = assert_conflict __LOC__ op_different_branch in + let* () = assert_conflict __LOC__ op_different_payload_hash in + return_unit + +(** In mempool mode, test that there is no conflict between an + attestation and a preattestation for the same slot (here the first + slot), same level, and same round. *) +let test_no_conflict_with_preattestation_mempool () = + let open Lwt_result_syntax in + let* _genesis, attested_block = init_genesis () in + let* op_attestation = Op.attestation attested_block in + let* op_preattestation = Op.preattestation attested_block in + let* inc = Incremental.begin_construction ~mempool_mode:true attested_block in + let* inc = Incremental.add_operation inc op_attestation in + let* inc = Incremental.add_operation inc op_preattestation in + let* _inc = Incremental.finalize_block inc in + return_unit + +(** In application and construction (aka baking) modes, test that + there is no conflict between an attestation and a preattestation + for the same slot (here the first slot). Note that the operations + don't have the same level because the required levels for them to + be valid are different. *) +let test_no_conflict_with_preattestation_block () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* round0_block = Block.bake predecessor in + let* op_attestation = Op.attestation predecessor in + let* op_preattestation = Op.preattestation round0_block in + let bake_both_ops baking_mode = + Block.bake + ~baking_mode + ~payload_round:(Some Round.zero) + ~locked_round:(Some Round.zero) + ~policy:(By_round 1) + ~operations:[op_attestation; op_preattestation] + predecessor + in + let* (_ : Block.t) = bake_both_ops Application in + let* (_ : Block.t) = bake_both_ops Baking in + return_unit + +(** In mempool mode, test that there is no conflict between + attestations for the same slot (here the first slot) with various + allowed levels and rounds. + + There are no similar tests in application and construction modes + because valid attestations always have the same level and round. *) +let test_no_conflict_various_levels_and_rounds () = + let open Lwt_result_syntax in + let* genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent in + let* future_block = Block.bake predecessor in + let* alt_grandparent = Block.bake ~policy:(By_round 1) genesis in + let* alt_predecessor = Block.bake ~policy:(By_round 1) grandparent in + let* alt_future = Block.bake ~policy:(By_round 10) alt_predecessor in + let* inc = Incremental.begin_construction ~mempool_mode:true predecessor in + let add_attestation inc attested_block = + let* (op : packed_operation) = Op.attestation attested_block in + let (Operation_data protocol_data) = op.protocol_data in + let content = + match protocol_data.contents with + | Single (Attestation {consensus_content = content; _}) -> content + | _ -> assert false + in + Format.eprintf + "level: %ld, round: %ld@." + (Raw_level.to_int32 content.level) + (Round.to_int32 content.round) ; + Incremental.add_operation inc op + in + let* inc = add_attestation inc grandparent in + let* inc = add_attestation inc predecessor in + let* inc = add_attestation inc future_block in + let* inc = add_attestation inc alt_grandparent in + let* inc = add_attestation inc alt_predecessor in + let* inc = add_attestation inc alt_future in + let* _inc = Incremental.finalize_block inc in + return_unit + +(** {1 Consensus threshold tests} + + Both positive and negative tests. *) + +(** Check that: + - a block with not enough attestation cannot be baked; + - a block with enough attestation is baked. *) +let test_attestation_threshold ~sufficient_threshold () = + let open Lwt_result_wrap_syntax in + (* We choose a relative large number of accounts so that the probability that + any delegate has [consensus_threshold] slots is low and most delegates have + about 1 slot so we can get closer to the limit of [consensus_threshold]: we + check that a block with attesting power [consensus_threshold - 1] won't be + baked. *) + let* genesis, _contracts = Context.init_n 10 () in + let* b = Block.bake genesis in + let* {parametric = {consensus_threshold; _}; _} = + Context.get_constants (B b) + in + let* attesters_list = Context.get_attesters (B b) in + let*?@ round = Block.get_round b in + let* _, attestations = + List.fold_left_es + (fun (counter, attestations) {Plugin.RPC.Validators.delegate; slots; _} -> + let new_counter = counter + List.length slots in + if + (sufficient_threshold && counter < consensus_threshold) + || ((not sufficient_threshold) && new_counter < consensus_threshold) + then + let* attestation = Op.attestation ~round ~delegate b in + return (new_counter, attestation :: attestations) + else return (counter, attestations)) + (0, []) + attesters_list + in + let*! b = Block.bake ~operations:attestations b in + if sufficient_threshold then return_unit + else + Assert.proto_error ~loc:__LOC__ b (function + | Validate_errors.Block.Not_enough_attestations _ -> true + | _ -> false) + +let test_two_attestations_with_same_attester () = + let open Lwt_result_syntax in + let* _genesis, attested_block = init_genesis ~dal_enable:true () in + let* op1 = Op.raw_attestation attested_block in + let dal_content = + let attestation = + Dal.Attestation.commit Dal.Attestation.empty Dal.Slot_index.zero + in + {attestation} + in + let* op2 = Op.raw_attestation ~dal_content attested_block in + let*! res = + Block.bake + ~baking_mode:Application + ~operations:[Operation.pack op1; Operation.pack op2] + attested_block + in + let error = function + | Validate_errors.( + Consensus.Conflicting_consensus_operation + { + kind = Attestation; + conflict = Operation_conflict {existing; new_operation}; + }) -> + Operation_hash.equal existing (Operation.hash op1) + && Operation_hash.equal new_operation (Operation.hash op2) + | _ -> false + in + Assert.proto_error ~loc:__LOC__ res error + +(* Check that if an attester includes some DAL content but is not in the DAL + committee, then an error is returned at block validation. + + Note that we change the value of [consensus_committee_size] because with the + default test parameters, [consensus_committee_size = 25 < 64 = + number_of_shards], so that test would not work! *) +let test_attester_not_in_dal_committee () = + let open Lwt_result_syntax in + let bal_high = 80_000_000_000L in + let bal_low = 08_000_000_000L in + (* Create many accounts with balance [bal_high] and one with [bal_low]. *) + let n = 10 in + let bootstrap_balances = bal_low :: Stdlib.List.init n (fun _ -> bal_high) in + let dal = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_sandbox + .dal + in + let dal = + (* We need to take a small number of shards to be sure there is a + really high probability an attester is not part of the DAL + committee in the first hundred blocks. *) + { + dal with + cryptobox_parameters = + {dal.cryptobox_parameters with number_of_shards = 64}; + } + in + let* genesis, contracts = + Context.init_gen + ~dal_enable:true + ~dal + ~consensus_committee_size:100 + ~consensus_threshold:0 + ~bootstrap_balances + (Context.TList (n + 1)) + () + in + let pkh = Stdlib.List.hd contracts |> Context.Contract.pkh in + let rec iter b i = + let* committee = Context.get_attesters (B b) in + let* dal_committee = Context.Dal.shards (B b) () in + let in_committee = + List.exists + (fun del -> + Signature.Public_key_hash.equal pkh del.RPC.Validators.delegate) + committee + in + let in_dal_committee = + List.exists + (fun ({delegate; _} : Plugin.RPC.Dal.S.shards_assignment) -> + Signature.Public_key_hash.equal pkh delegate) + dal_committee + in + if in_committee && not in_dal_committee then + let dal_content = {attestation = Dal.Attestation.empty} in + let* op = Op.attestation ~delegate:pkh ~dal_content b in + let* ctxt = Incremental.begin_construction b in + let expect_apply_failure = function + | [ + Environment.Ecoproto_error + (Alpha_context.Dal_errors + .Dal_data_availibility_attester_not_in_committee + {attester; level; slot = _}); + ] + when Signature.Public_key_hash.equal attester pkh + && Raw_level.to_int32 level = b.header.shell.level -> + return_unit + | errs -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + errs + in + Incremental.add_operation ctxt op ~expect_failure:expect_apply_failure + else + let* b = Block.bake b in + if i = 100 then + failwith + "The account is in all DAL committees for 100 levels! The test needs \ + to be adapted." + else iter b (i + 1) + in + let* b = Block.bake genesis in + let* _ = iter b 0 in + return_unit + +let test_dal_attestation_threshold () = + let open Lwt_result_wrap_syntax in + let n = 100 in + let* genesis, contracts = Context.init_n n ~consensus_threshold:0 () in + let contract = Stdlib.List.hd contracts in + let* { + parametric = + { + dal = + { + attestation_lag; + attestation_threshold; + cryptobox_parameters = {number_of_shards; _}; + _; + }; + _; + }; + _; + } = + Context.get_constants (B genesis) + in + let slot_index = Dal.Slot_index.zero in + let commitment = Alpha_context.Dal.Slot.Commitment.zero in + let commitment_proof = Alpha_context.Dal.Slot.Commitment_proof.zero in + let slot_header = + Dal.Operations.Publish_commitment.{slot_index; commitment; commitment_proof} + in + let* op = Op.dal_publish_commitment (B genesis) contract slot_header in + let* b = Block.bake genesis ~operation:op in + let* b = Block.bake_n (attestation_lag - 1) b in + let* dal_committee = Context.Dal.shards (B b) () in + let attestation = Dal.Attestation.commit Dal.Attestation.empty slot_index in + let dal_content = {attestation} in + let min_power = attestation_threshold * number_of_shards / 100 in + Log.info "Number of minimum required attested shards: %d" min_power ; + let* _ = + List.fold_left_es + (fun (acc_ops, acc_power) + ({delegate; indexes} : RPC.Dal.S.shards_assignment) -> + let* op = Op.attestation ~delegate ~dal_content b in + let ops = op :: acc_ops in + let power = acc_power + List.length indexes in + let* _b, (metadata, _ops) = + Block.bake_with_metadata ~operations:ops b + in + let attested_expected = power >= min_power in + let attested = + Dal.Attestation.is_attested metadata.dal_attestation slot_index + in + Log.info "With %d power, the slot is attested: %b " power attested ; + Check.(attested = attested_expected) + Check.bool + ~error_msg: + "Unexpected attestation status for slot 0: got %L, expected %R " ; + return (ops, power)) + ([], 0) + dal_committee + in + return_unit + +let tests = + [ + (* Positive tests *) + Tztest.tztest "Simple attestation" `Quick test_simple_attestation; + Tztest.tztest "Arbitrary branch" `Quick test_arbitrary_branch; + Tztest.tztest "Non-zero round" `Quick test_non_zero_round; + Tztest.tztest "Fitness gap" `Quick test_fitness_gap; + Tztest.tztest "Mempool: non-smallest slot" `Quick test_mempool_second_slot; + (* Negative tests *) + (* Wrong slot *) + Tztest.tztest "Attestation with slot -1" `Quick test_negative_slot; + Tztest.tztest "Non-normalized slot" `Quick test_not_smallest_slot; + Tztest.tztest "Not own slot" `Quick test_not_own_slot; + Tztest.tztest "Mempool: not own slot" `Quick test_mempool_not_own_slot; + (* Wrong level *) + Tztest.tztest "One level too old" `Quick test_one_level_too_old; + Tztest.tztest "Two levels too old" `Quick test_two_levels_too_old; + Tztest.tztest "One level in the future" `Quick test_one_level_in_the_future; + Tztest.tztest "Two levels in the future" `Quick test_two_levels_future; + (* Wrong round *) + Tztest.tztest "One round too old" `Quick test_one_round_too_old; + Tztest.tztest "Many rounds too old" `Quick test_many_rounds_too_old; + Tztest.tztest "One round in the future" `Quick test_one_round_in_the_future; + Tztest.tztest "Many rounds in the future" `Quick test_many_rounds_future; + (* Wrong payload hash *) + Tztest.tztest "Wrong payload hash" `Quick test_wrong_payload_hash; + (* Conflict tests (some negative, some positive) *) + Tztest.tztest "Conflict" `Quick test_conflict; + Tztest.tztest "Grandparent conflict" `Quick test_grandparent_conflict; + Tztest.tztest "Future level conflict" `Quick test_future_level_conflict; + Tztest.tztest + "No conflict with preattestation (mempool)" + `Quick + test_no_conflict_with_preattestation_mempool; + Tztest.tztest + "No conflict with preattestation (block)" + `Quick + test_no_conflict_with_preattestation_block; + Tztest.tztest + "No conflict with various levels and rounds" + `Quick + test_no_conflict_various_levels_and_rounds; + (* Consensus threshold tests (one positive and one negative) *) + Tztest.tztest + "sufficient attestation threshold" + `Quick + (test_attestation_threshold ~sufficient_threshold:true); + Tztest.tztest + "insufficient attestation threshold" + `Quick + (test_attestation_threshold ~sufficient_threshold:false); + Tztest.tztest + "two attestations with same attester in a block" + `Quick + test_two_attestations_with_same_attester; + Tztest.tztest + "attester not in DAL committee" + `Quick + test_attester_not_in_dal_committee; + Tztest.tztest + "DAL attestation_threshold" + `Quick + test_dal_attestation_threshold; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("attestation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_baking.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_baking.ml new file mode 100644 index 000000000000..919883d52fff --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_baking.ml @@ -0,0 +1,488 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (baking) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_baking.ml + Subject: Rewards and bakers. Tests based on RPCs. +*) + +open Protocol +open Alpha_context + +(** Verify the level is correctly computed when the first cycle is + passed and after baking a certain fixed number of blocks (10 for + the moment). The result should be [blocks_per_cycle + 10] where + [blocks_per_cycle] comes from the constants of the selected + protocol. + + IMPROVEMENTS: + - Randomize the number of cycle. + - Randomize the number of accounts created at the beginning + - Randomize the blocks per cycle. + - Randomize the number of blocks baked after the n cycles baked + previously. *) +let test_cycle () = + let open Lwt_result_syntax in + let* b, _contracts = Context.init_n ~consensus_threshold:0 5 () in + let* csts = Context.get_constants (B b) in + let blocks_per_cycle = csts.parametric.blocks_per_cycle in + let pp fmt x = Format.fprintf fmt "%ld" x in + let* b = Block.bake b in + let* b = Block.bake_until_cycle_end b in + let*? curr_level = Context.get_level (B b) in + let* () = + Assert.equal + ~loc:__LOC__ + Int32.equal + "not the right level" + pp + (Alpha_context.Raw_level.to_int32 curr_level) + blocks_per_cycle + in + let*? l = Context.get_level (B b) in + let* b = Block.bake_n 10 b in + let*? curr_level = Context.get_level (B b) in + Assert.equal + ~loc:__LOC__ + Int32.equal + "not the right level" + pp + (Alpha_context.Raw_level.to_int32 curr_level) + (Int32.add (Alpha_context.Raw_level.to_int32 l) 10l) + +(** Test baking [n] cycles in a raw works smoothly. *) +let test_bake_n_cycles n () = + let open Lwt_result_syntax in + let open Block in + let policy = By_round 0 in + let* block, _contract = Context.init1 ~consensus_threshold:0 () in + let* (_block : block) = Block.bake_until_n_cycle_end ~policy n block in + return_unit + +(** Check that, after one or two voting periods, the voting power of a baker is + updated according to the rewards it receives for baking the blocks in the + voting periods. Note we consider only one baker. *) +let test_voting_power_cache () = + let open Lwt_result_syntax in + let open Block in + let policy = By_round 0 in + let* genesis, _contract = Context.init1 ~consensus_threshold:0 () in + let* csts = Context.get_constants (B genesis) in + let blocks_per_voting_period = + Int32.( + mul + csts.parametric.blocks_per_cycle + csts.parametric.cycles_per_voting_period) + in + let blocks_per_voting_periods n = + Int64.of_int (n * Int32.to_int blocks_per_voting_period) + in + let* baking_reward = Context.get_baking_reward_fixed_portion (B genesis) in + let* bakers = Context.get_bakers (B genesis) in + let baker = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd bakers in + let* full_balance = Context.Delegate.full_balance (B genesis) baker in + let assert_voting_power ~loc n block = + let* voting_power = Context.get_voting_power (B block) baker in + Assert.equal_int64 ~loc n voting_power + in + (* the voting power is the full staking balance *) + let initial_voting_power_at_genesis = Tez.to_mutez full_balance in + let* () = + assert_voting_power ~loc:__LOC__ initial_voting_power_at_genesis genesis + in + let rewards_after_one_voting_period = + Test_tez.(baking_reward *! Int64.pred (blocks_per_voting_periods 1)) + in + let expected_delta_voting_power_after_one_voting_period = + Tez.to_mutez rewards_after_one_voting_period + in + let* block = + Block.bake_n ~policy (Int32.to_int blocks_per_voting_period - 1) genesis + in + let expected_voting_power_after_one_voting_period = + Int64.add + initial_voting_power_at_genesis + expected_delta_voting_power_after_one_voting_period + in + let* () = + assert_voting_power + ~loc:__LOC__ + expected_voting_power_after_one_voting_period + block + in + let rewards_after_two_voting_periods = + Test_tez.(baking_reward *! Int64.pred (blocks_per_voting_periods 2)) + in + let expected_delta_voting_power_after_two_voting_periods = + Tez.to_mutez rewards_after_two_voting_periods + in + let* block = + Block.bake_n ~policy (Int32.to_int blocks_per_voting_period) block + in + let expected_voting_power_after_two_voting_periods = + Int64.add + initial_voting_power_at_genesis + expected_delta_voting_power_after_two_voting_periods + in + assert_voting_power + ~loc:__LOC__ + expected_voting_power_after_two_voting_periods + block + +(** test that after baking, one gets the baking reward fixed portion. *) +let test_basic_baking_reward () = + let open Lwt_result_syntax in + let* genesis, baker = Context.init1 ~consensus_threshold:0 () in + let* b = Block.bake genesis in + let baker_pkh = Context.Contract.pkh baker in + let* bal = Context.Contract.balance (B b) baker in + let* frozen_deposit = + Context.Delegate.current_frozen_deposits (B b) baker_pkh + in + let* br = Context.get_baking_reward_fixed_portion (B b) in + let open Test_tez in + let expected_initial_balance = bal +! frozen_deposit -! br in + Assert.equal_tez + ~loc:__LOC__ + expected_initial_balance + Account.default_initial_balance + +let get_contract_for_pkh contracts pkh = + let open Lwt_result_syntax in + let rec find_contract = function + | [] -> assert false + | c :: t -> + let c_pkh = Context.Contract.pkh c in + if Signature.Public_key_hash.equal c_pkh pkh then return c + else find_contract t + in + find_contract contracts + +(** Test that + - the block producer gets the bonus for including the attestations; + - the payload producer gets the baking reward. + + The test checks this in two scenarios, in the first one the payload producer + and the block producer are the same delegate, in the second one they are + different. The first scenario is checked by first baking block [b1] and then + block [b2] at round 0 containing a number of attestations for [b1] and the + checking the balance of [b2]'s baker. For the second scenario another block + [b2'] is build on top of [b1] by a different baker, using the same payload as + [b2]. *) +let test_rewards_block_and_payload_producer () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_n ~consensus_threshold:1 10 () in + let* baker_b1 = Context.get_baker (B genesis) ~round:Round.zero in + let* baker_b1_contract = get_contract_for_pkh contracts baker_b1 in + let* b1 = Block.bake ~policy:(By_round 0) genesis in + let* attesters = Context.get_attesters (B b1) in + let* attesters = + List.map_es + (function + | {Plugin.RPC.Validators.delegate; slots; _} -> return (delegate, slots)) + attesters + in + (* We let just a part of the attesters vote; we assume here that 5 of 10 + attesters will have together at least one slot (to pass the threshold), but + not all slots (to make the test more interesting, otherwise we know the + total attesting power). *) + let attesters = List.take_n 5 attesters in + let* attestations = + List.map_ep + (fun (attester, _slots) -> Op.attestation ~delegate:attester b1) + attesters + in + let attesting_power = + List.fold_left + (fun acc (_pkh, slots) -> acc + List.length slots) + 0 + attesters + in + let fee = Tez.one in + let* tx = + Op.transaction (B b1) ~fee baker_b1_contract baker_b1_contract Tez.one + in + let* b2 = + Block.bake ~policy:(By_round 0) ~operations:(attestations @ [tx]) b1 + in + let* baker_b2 = Context.get_baker (B b1) ~round:Round.zero in + let* baker_b2_contract = get_contract_for_pkh contracts baker_b2 in + let* bal = Context.Contract.balance (B b2) baker_b2_contract in + let* frozen_deposit = + Context.Delegate.current_frozen_deposits (B b2) baker_b2 + in + let* baking_reward = Context.get_baking_reward_fixed_portion (B b2) in + let* bonus_reward = Context.get_bonus_reward (B b2) ~attesting_power in + let* reward_for_b1 = + if Signature.Public_key_hash.equal baker_b2 baker_b1 then + Context.get_baking_reward_fixed_portion (B b1) + else return Tez.zero + in + (* we are in the first scenario where the payload producer is the same as the + block producer, in our case, [baker_b2]. [baker_b2] gets the baking reward + plus the fee for the transaction [tx]. *) + let expected_balance = + let open Test_tez in + Account.default_initial_balance -! frozen_deposit +! baking_reward + +! bonus_reward +! reward_for_b1 +! fee + in + let* () = Assert.equal_tez ~loc:__LOC__ bal expected_balance in + (* Some new baker [baker_b2'] bakes b2' at the first round which does not + correspond to a slot of [baker_b2] and it includes the PQC for [b2]. We + check that the fixed baking reward goes to the payload producer [baker_b2], + while the bonus goes to the the block producer (aka baker) [baker_b2']. *) + let* attesters = Context.get_attesters (B b2) in + let* preattesters = + List.map_es + (function + | {Plugin.RPC.Validators.delegate; slots; _} -> return (delegate, slots)) + attesters + in + let* preattestations = + List.map_ep + (fun (attester, _slots) -> Op.preattestation ~delegate:attester b2) + preattesters + in + let* baker_b2 = Context.get_baker (B b1) ~round:Round.zero in + let* bakers = Context.get_bakers (B b1) in + let baker_b2' = Context.get_first_different_baker baker_b2 bakers in + let* b2' = + Block.bake + ~payload_round:(Some Round.zero) + ~locked_round:(Some Round.zero) + ~policy:(By_account baker_b2') + ~operations:(preattestations @ attestations @ [tx]) + b1 + in + (* [baker_b2], as payload producer, gets the block reward and the fees *) + let* bal = Context.Contract.balance (B b2') baker_b2_contract in + let* frozen_deposit = + Context.Delegate.current_frozen_deposits (B b2') baker_b2 + in + let reward_for_b1 = + if Signature.Public_key_hash.equal baker_b2 baker_b1 then baking_reward + else Tez.zero + in + let expected_balance = + let open Test_tez in + Account.default_initial_balance +! baking_reward -! frozen_deposit + +! reward_for_b1 +! fee + in + let* () = Assert.equal_tez ~loc:__LOC__ bal expected_balance in + (* [baker_b2'] gets the bonus because he is the one who included the + attestations *) + let* baker_b2'_contract = get_contract_for_pkh contracts baker_b2' in + let* bal' = Context.Contract.balance (B b2') baker_b2'_contract in + let* frozen_deposits' = + Context.Delegate.current_frozen_deposits (B b2') baker_b2' + in + let* baker_b1 = Context.get_baker (B genesis) ~round:Round.zero in + let reward_for_b1' = + if Signature.Public_key_hash.equal baker_b2' baker_b1 then baking_reward + else Tez.zero + in + let expected_balance' = + let open Test_tez in + Account.default_initial_balance +! bonus_reward +! reward_for_b1' + -! frozen_deposits' + in + Assert.equal_tez ~loc:__LOC__ bal' expected_balance' + +(** We test that: + - a delegate that has active stake can bake; + - a delegate that has no active stake cannot bake. +*) +let test_enough_active_stake_to_bake ~has_active_stake () = + let open Lwt_result_syntax in + let* b_for_constants, _contract = Context.init1 () in + let* Constants.{parametric = {minimal_stake; _}; _} = + Context.get_constants (B b_for_constants) + in + let tpr = Tez.to_mutez minimal_stake in + (* N.B. setting the balance has an impact on the active stake; without + delegation, the full balance is the same as the staking balance and the + active balance is less or equal the staking balance (see + [Delegate_sampler.select_distribution_for_cycle]). *) + let initial_bal1 = if has_active_stake then tpr else Int64.sub tpr 1L in + let* b0, (account1, _account2) = + Context.init2 + ~bootstrap_balances:[initial_bal1; tpr] + ~consensus_threshold:0 + () + in + let pkh1 = Context.Contract.pkh account1 in + let* baking_reward_fixed_portion = + Context.get_baking_reward_fixed_portion (B b0) + in + let*! b1 = Block.bake ~policy:(By_account pkh1) b0 in + if has_active_stake then + let*? b1 in + let* bal = Context.Contract.balance (B b1) account1 in + let* frozen_deposit = + Context.Delegate.current_frozen_deposits (B b1) pkh1 + in + let expected_bal = + Test_tez.( + Tez.of_mutez_exn initial_bal1 + +! baking_reward_fixed_portion -! frozen_deposit) + in + Assert.equal_tez ~loc:__LOC__ bal expected_bal + else + (* pkh1 has less than minimal_stake so it will have no slots, thus it + cannot be a proposer, thus it cannot bake. Precisely, bake fails because + get_next_baker_by_account fails with "No slots found for pkh1" *) + Assert.error ~loc:__LOC__ b1 (fun _ -> true) + +let test_committee_sampling () = + let open Lwt_result_syntax in + let test_distribution max_round distribution = + let bootstrap_balances, bounds = List.split distribution in + let*? accounts = + Account.generate_accounts (List.length bootstrap_balances) + in + let bootstrap_accounts = + Account.make_bootstrap_accounts ~bootstrap_balances accounts + in + let consensus_committee_size = max_round in + assert ( + (* Enforce that we are not mistakenly testing a value for committee_size + that violates invariants of module Slot_repr. *) + Result.is_ok + (Slot_repr.of_int consensus_committee_size)) ; + let constants = + { + Default_parameters.constants_test with + consensus_committee_size; + consensus_threshold = 0; + } + in + let parameters = + Default_parameters.parameters_of_constants ~bootstrap_accounts constants + in + let* genesis = Block.genesis_with_parameters parameters in + let+ bakers = + Plugin.RPC.Baking_rights.get Block.rpc_ctxt ~all:true ~max_round genesis + in + let stats = Stdlib.Hashtbl.create 10 in + Stdlib.List.iter2 + (fun acc bounds -> Stdlib.Hashtbl.add stats acc.Account.pkh (bounds, 0)) + accounts + bounds ; + List.iter + (fun {Plugin.RPC.Baking_rights.delegate = pkh; _} -> + let bounds, n = Stdlib.Hashtbl.find stats pkh in + Stdlib.Hashtbl.replace stats pkh (bounds, n + 1)) + bakers ; + let one_failed = ref false in + + Format.eprintf + "@[Testing with baker distribution [%a],@ committee size %d.@]@." + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") + (fun ppf (tez, _) -> Format.fprintf ppf "%Ld" tez)) + distribution + max_round ; + + Format.eprintf + "@[@,%a@]@." + (fun ppf stats -> + Stdlib.Hashtbl.iter + (fun pkh ((min_p, max_p), n) -> + let failed = not (n >= min_p && n <= max_p) in + Format.fprintf + ppf + "@[- %a %d%a@]@," + Signature.Public_key_hash.pp + pkh + n + (fun ppf failed -> + if failed then + Format.fprintf ppf " [FAIL] should be in [%d, %d]" min_p max_p + else Format.fprintf ppf "") + failed ; + one_failed := failed || !one_failed) + stats) + stats ; + + if !one_failed then + Stdlib.failwith + "The proportion of bakers marked as [FAILED] in the log output appear \ + in the wrong proportion in the committee." + else Format.eprintf "Test succesful.@." + in + (* The tests below are not deterministic, but the probability that + they fail is infinitesimal. *) + let accounts = + let expected_lower_bound = 6_100 and expected_upper_bound = 6_900 in + let balance = 8_000_000_000L in + let account = (balance, (expected_lower_bound, expected_upper_bound)) in + Array.(make 10 account |> to_list) + in + let* () = test_distribution 65535 accounts in + let* () = + test_distribution + 10_000 + [ + (16_000_000_000L, (4_600, 5_400)); + (8_000_000_000L, (2_200, 2_800)); + (8_000_000_000L, (2_200, 2_800)); + ] + in + test_distribution + 10_000 + [(792_000_000_000L, (9_830, 9_970)); (8_000_000_000L, (40, 160))] + +let tests = + [ + Tztest.tztest "cycle" `Quick test_cycle; + Tztest.tztest "bake_n_cycles for 12 cycles" `Quick (test_bake_n_cycles 12); + Tztest.tztest "voting_power" `Quick test_voting_power_cache; + Tztest.tztest + "the fixed baking reward is given after a bake" + `Quick + test_basic_baking_reward; + Tztest.tztest + "the block producer gets the bonus while the payload producer gets the \ + baking reward " + `Quick + test_rewards_block_and_payload_producer; + Tztest.tztest + "a delegate with 8000 tez can bake" + `Quick + (test_enough_active_stake_to_bake ~has_active_stake:true); + Tztest.tztest + "a delegate with 7999 tez cannot bake" + `Quick + (test_enough_active_stake_to_bake ~has_active_stake:false); + Tztest.tztest "committee sampling" `Quick test_committee_sampling; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("baking", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_consensus_key.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_consensus_key.ml new file mode 100644 index 000000000000..67a8554c0e5c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_consensus_key.ml @@ -0,0 +1,345 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (delegate_storage) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_consensus_key.ml + Subject: consistency of the [Drain_delegate] operation + *) + +open Protocol +open Alpha_context + +let constants = + { + Default_parameters.constants_test with + issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + }; + consensus_threshold = 0; + origination_size = 0; + } + +(** Checks that staking balance is sum of delegators' stake. *) +let check_delegate_staking_invariant blk delegate_pkh = + let open Lwt_result_wrap_syntax in + let* delegate_staking_balance = + Context.Delegate.staking_balance (B blk) delegate_pkh + in + let* self_staking_balance = + Context.Delegate.full_balance (B blk) delegate_pkh + in + let* delegate_info = Context.Delegate.info (B blk) delegate_pkh in + let delegate_contract = Contract.Implicit delegate_pkh in + let delegated_contracts = + List.filter + (fun c -> Contract.(c <> delegate_contract)) + delegate_info.delegated_contracts + in + let* delegators_stake = + List.fold_left_es + (fun total pkh -> + let* staking_balance = + Context.Contract.balance_and_frozen_bonds (B blk) pkh + in + let*?@ t = Tez.(total +? staking_balance) in + return t) + self_staking_balance + delegated_contracts + in + Assert.equal_tez ~loc:__LOC__ delegate_staking_balance delegators_stake + +let update_consensus_key blk delegate public_key = + let open Lwt_result_syntax in + let nb_delay_cycles = constants.consensus_rights_delay + 1 in + let* update_ck = + Op.update_consensus_key (B blk) (Contract.Implicit delegate) public_key + in + let* blk' = Block.bake ~operation:update_ck blk in + Block.bake_until_n_cycle_end nb_delay_cycles blk' + +let delegate_stake blk source delegate = + let open Lwt_result_syntax in + let* delegation = + Op.delegation (B blk) (Contract.Implicit source) (Some delegate) + in + Block.bake ~operation:delegation blk + +let transfer_tokens blk source destination amount = + let open Lwt_result_syntax in + let* transfer_op = + Op.transaction + (B blk) + (Contract.Implicit source) + (Contract.Implicit destination) + amount + in + Block.bake ~operation:transfer_op blk + +let may_reveal_manager_key blk (pkh, pk) = + let open Lwt_result_syntax in + let* is_revealed = + Context.Contract.is_manager_key_revealed (B blk) (Contract.Implicit pkh) + in + if is_revealed then return blk + else + let* reveal_op = Op.revelation (B blk) pk in + Block.bake ~operation:reveal_op blk + +let drain_delegate ~policy blk consensus_key delegate destination + expected_final_balance = + let open Lwt_result_syntax in + let* drain_del = + Op.drain_delegate (B blk) ~consensus_key ~delegate ~destination + in + let* blk' = Block.bake ~policy ~operation:drain_del blk in + let* () = check_delegate_staking_invariant blk' delegate in + let* final_balance = + Context.Contract.balance (B blk') (Contract.Implicit delegate) + in + Assert.equal_tez ~loc:__LOC__ final_balance expected_final_balance + +let get_first_2_accounts_contracts (a1, a2) = + ((a1, Context.Contract.pkh a1), (a2, Context.Contract.pkh a2)) + +let test_drain_delegate_scenario f = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (_contract1, account1_pkh), (_contract2, account2_pkh) = + get_first_2_accounts_contracts contracts + in + let consensus_account = Account.new_account () in + let delegate = account1_pkh in + let consensus_pk = consensus_account.pk in + let consensus_pkh = consensus_account.pkh in + let* blk' = + transfer_tokens genesis account2_pkh consensus_pkh Tez.one_mutez + in + let* blk' = update_consensus_key blk' delegate consensus_pk in + f blk' consensus_pkh consensus_pk delegate + +let test_drain_delegate ~low_balance ~exclude_ck ~ck_delegates () = + let open Lwt_result_syntax in + test_drain_delegate_scenario (fun blk consensus_pkh consensus_pk delegate -> + let policy = + if exclude_ck then Block.Excluding [consensus_pkh] + else Block.By_account delegate + in + let* blk = + if ck_delegates then + let* blk = may_reveal_manager_key blk (consensus_pkh, consensus_pk) in + delegate_stake blk consensus_pkh delegate + else return blk + in + let* delegate_balance = + Context.Contract.balance (B blk) (Contract.Implicit delegate) + in + let* blk = + if low_balance then + let* blk = + transfer_tokens blk delegate consensus_pkh delegate_balance + in + let* blk = may_reveal_manager_key blk (consensus_pkh, consensus_pk) in + transfer_tokens + blk + consensus_pkh + delegate + Tez.(of_mutez_exn 1_000_000L) + else return blk + in + let* delegate_balance = + Context.Contract.balance (B blk) (Contract.Implicit delegate) + in + let expected_final_balance = + if exclude_ck then Tez.zero + else Tez.(max one) Test_tez.(delegate_balance /! 100L) + in + drain_delegate + ~policy + blk + consensus_pkh + delegate + consensus_pkh + expected_final_balance) + +let test_drain_empty_delegate ~exclude_ck () = + let open Lwt_result_syntax in + test_drain_delegate_scenario (fun blk consensus_pkh _consensus_pk delegate -> + let policy = + if exclude_ck then Block.Excluding [consensus_pkh] + else Block.By_account delegate + in + let* delegate_balance = + Context.Contract.balance (B blk) (Contract.Implicit delegate) + in + let* blk = transfer_tokens blk delegate consensus_pkh delegate_balance in + let*! res = + drain_delegate ~policy blk consensus_pkh delegate consensus_pkh Tez.zero + in + Assert.proto_error_with_info + ~loc:__LOC__ + res + "Drain delegate without enough balance for allocation burn or drain \ + fees") + +let test_tz4_consensus_key () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants1 constants in + let account1_pkh = Context.Contract.pkh contracts in + let consensus_account = Account.new_account ~algo:Bls () in + let delegate = account1_pkh in + let consensus_pk = consensus_account.pk in + let consensus_pkh = consensus_account.pkh in + let* blk' = + transfer_tokens genesis account1_pkh consensus_pkh Tez.one_mutez + in + let* operation = + Op.update_consensus_key (B blk') (Contract.Implicit delegate) consensus_pk + in + let tz4_pk = match consensus_pk with Bls pk -> pk | _ -> assert false in + let expect_failure = function + | [ + Environment.Ecoproto_error + (Delegate_consensus_key.Invalid_consensus_key_update_tz4 pk); + ] + when Signature.Bls.Public_key.(pk = tz4_pk) -> + return_unit + | err -> + failwith + "Error trace:@,\ + \ %a does not match the \ + [Delegate_consensus_key.Invalid_consensus_key_update_tz4] error" + Error_monad.pp_print_trace + err + in + let* inc = Incremental.begin_construction blk' in + let* (_i : Incremental.t) = + Incremental.validate_operation ~expect_failure inc operation + in + return_unit + +let test_attestation_with_consensus_key () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants1 constants in + let account1_pkh = Context.Contract.pkh contracts in + let consensus_account = Account.new_account () in + let delegate = account1_pkh in + let consensus_pk = consensus_account.pk in + let consensus_pkh = consensus_account.pkh in + let* blk' = + transfer_tokens genesis account1_pkh consensus_pkh Tez.one_mutez + in + let* b_pre = update_consensus_key blk' delegate consensus_pk in + let* b = Block.bake b_pre in + let slot = Slot.of_int_do_not_use_except_for_parameters 0 in + let* attestation = Op.attestation ~delegate:account1_pkh ~slot b in + let*! res = Block.bake ~operation:attestation b in + let* () = + Assert.proto_error ~loc:__LOC__ res (function + | Operation.Invalid_signature -> true + | _ -> false) + in + let* attestation = Op.attestation ~delegate:consensus_pkh ~slot b in + let* (_good_block : Block.t) = Block.bake ~operation:attestation b in + return_unit + +let tests = + Tztest. + [ + tztest + "drain delegate high balance, excluding ck, ck delegates" + `Quick + (test_drain_delegate + ~low_balance:false + ~exclude_ck:true + ~ck_delegates:true); + tztest + "drain delegate high balance, excluding ck, ck does not delegate" + `Quick + (test_drain_delegate + ~low_balance:false + ~exclude_ck:true + ~ck_delegates:false); + tztest + "drain delegate high balance, with ck, ck delegates" + `Quick + (test_drain_delegate + ~low_balance:false + ~exclude_ck:false + ~ck_delegates:true); + tztest + "drain delegate high balance, with ck, ck does not delegate" + `Quick + (test_drain_delegate + ~low_balance:false + ~exclude_ck:false + ~ck_delegates:false); + tztest + "drain delegate low balance, excluding ck, ck delegates" + `Quick + (test_drain_delegate + ~low_balance:true + ~exclude_ck:true + ~ck_delegates:true); + tztest + "drain delegate low balance, excluding ck, ck does not delegate" + `Quick + (test_drain_delegate + ~low_balance:true + ~exclude_ck:true + ~ck_delegates:false); + tztest + "drain delegate low balance, with ck, ck delegates" + `Quick + (test_drain_delegate + ~low_balance:true + ~exclude_ck:false + ~ck_delegates:true); + tztest + "drain delegate low balance, with ck, ck does not delegate" + `Quick + (test_drain_delegate + ~low_balance:true + ~exclude_ck:false + ~ck_delegates:false); + tztest + "empty drain delegate excluding ck" + `Quick + (test_drain_empty_delegate ~exclude_ck:true); + tztest + "empty drain delegate with ck" + `Quick + (test_drain_empty_delegate ~exclude_ck:false); + tztest "tz4 consensus key" `Quick test_tz4_consensus_key; + tztest "attestation with ck" `Quick test_attestation_with_consensus_key; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("consensus key", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_deactivation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_deactivation.ml new file mode 100644 index 000000000000..f53067c69cf8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_deactivation.ml @@ -0,0 +1,402 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_deactivation.ml + Subject: After a given number of cycles during which a delegate has not + made use of its baking and attesting rights, its account will + be deactivated for validator selection. To bake/attest + again, it will have to re-activate its account. +*) + +open Protocol +open Alpha_context +open Test_tez + +(** Check that [Delegate.staking_balance] is the same as [Delegate.full_balance] + (this is not true in general, but in these tests it is because they only deal + with self-delegation. Also, check that [Delegate.staking_balance] coincides + with [Stake_storage.Internal_for_tests.get] when the account is active and it + has the minimal required stake. *) +let check_stake ~loc (b : Block.t) (account : Account.t) = + let open Lwt_result_wrap_syntax in + let* staking_balance = Context.Delegate.staking_balance (B b) account.pkh in + let* full_balance = Context.Delegate.full_balance (B b) account.pkh in + let* () = Assert.equal_tez ~loc full_balance staking_balance in + let*@ ctxt = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ stake = Stake_storage.Internal_for_tests.get ctxt account.pkh in + Assert.equal_int64 + ~loc + (Tez_repr.to_mutez stake) + (Tez.to_mutez staking_balance) + +(** Check that [Stake_storage.Internal_for_tests.get] returns 0 (following a + deactivation). Note that in case of deactivation [Delegate.staking_balance] + does not necessarily coincide with [Stake_storage.Internal_for_tests.get] in + that [Delegate.staking_balance] may be positive + (while [Stake_storage.Internal_for_tests.get] returns 0 because the account + is no longer in [Active_delegate_with_minimal_stake] because of deactivation, + see [Stake_storage].) *) +let check_no_stake ~loc (b : Block.t) (account : Account.t) = + let open Lwt_result_wrap_syntax in + let*@ ctxt = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ stake = Stake_storage.Internal_for_tests.get ctxt account.pkh in + Assert.equal_int64 ~loc (Tez_repr.to_mutez stake) 0L + +(** Create a block with two initialized contracts/accounts. Assert + that the first account has a staking balance that is equal to its + own balance, and that its staking rights are consistent + (check_stake). *) +let test_simple_staking_rights () = + let open Lwt_result_syntax in + let* b, (a1, _a2) = Context.init2 () in + let* balance = Context.Contract.balance (B b) a1 in + let delegate1 = Context.Contract.pkh a1 in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) delegate1 + in + let expected_initial_balance = + Account.default_initial_balance -! frozen_deposits + in + let* () = Assert.equal_tez ~loc:__LOC__ balance expected_initial_balance in + let* m1 = Context.Contract.manager (B b) a1 in + let* info = Context.Delegate.info (B b) m1.pkh in + let* () = + Assert.equal_tez + ~loc:__LOC__ + Account.default_initial_balance + info.staking_balance + in + check_stake ~loc:__LOC__ b m1 + +(** Create a block with two initialized contracts/accounts. Bake + five blocks. Assert that the staking balance of the first account + equals to its balance. Then both accounts have consistent staking + rights. *) +let test_simple_staking_rights_after_baking () = + let open Lwt_result_syntax in + let* b, (a1, a2) = Context.init2 ~consensus_threshold:0 () in + let* m1 = Context.Contract.manager (B b) a1 in + let* m2 = Context.Contract.manager (B b) a2 in + let* b = Block.bake_n ~policy:(By_account m2.pkh) 5 b in + let* balance = Context.Contract.balance (B b) a1 in + let delegate1 = Context.Contract.pkh a1 in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) delegate1 + in + let*? full_balance = balance +? frozen_deposits in + let* info = Context.Delegate.info (B b) m1.pkh in + let* () = Assert.equal_tez ~loc:__LOC__ full_balance info.staking_balance in + let* () = check_stake ~loc:__LOC__ b m1 in + check_stake ~loc:__LOC__ b m2 + +let check_active_staking_balance ~loc ~deactivated b (m : Account.t) = + let open Lwt_result_syntax in + let* info = Context.Delegate.info (B b) m.pkh in + let* () = Assert.equal_bool ~loc info.deactivated deactivated in + if deactivated then check_no_stake ~loc b m else check_stake ~loc b m + +let run_until_deactivation () = + let open Lwt_result_syntax in + let* b, (a1, a2) = Context.init2 ~consensus_threshold:0 () in + let* balance_start = Context.Contract.balance (B b) a1 in + let* m1 = Context.Contract.manager (B b) a1 in + let* m2 = Context.Contract.manager (B b) a2 in + let* () = check_active_staking_balance ~loc:__LOC__ ~deactivated:false b m1 in + let* info = Context.Delegate.info (B b) m1.pkh in + let* b = + Block.bake_until_cycle ~policy:(By_account m2.pkh) info.grace_period b + in + let* () = check_active_staking_balance ~loc:__LOC__ ~deactivated:false b m1 in + let* b = Block.bake_until_cycle_end ~policy:(By_account m2.pkh) b in + let+ () = check_active_staking_balance ~loc:__LOC__ ~deactivated:true b m1 in + (b, ((a1, m1), balance_start), (a2, m2)) + +(** From an initialized block with two contracts/accounts, the first + one is active then deactivated. After baking, check that the + account is active again. Baking rights are ensured. *) +let test_deactivation_then_bake () = + let open Lwt_result_syntax in + let* ( b, + ((_deactivated_contract, deactivated_account), _start_balance), + (_a2, _m2) ) = + run_until_deactivation () + in + let* b = Block.bake ~policy:(By_account deactivated_account.pkh) b in + check_active_staking_balance + ~loc:__LOC__ + ~deactivated:false + b + deactivated_account + +(** check that an account which is deactivated for [consensus_rights_delay] cannot be + part of a committee *) +let test_a_really_deactivated_account_is_not_in_the_committee () = + let open Lwt_result_syntax in + let* ( b, + ((_deactivated_contract, deactivated_account), _start_balance), + (_a2, m2) ) = + run_until_deactivation () + in + (* at this point, the deactivated account can either bake (because it still + has rights) and become active again, or, in case it is inactive for another + [consensus_rights_delay], it has no more rights, thus cannot be part of the + committee. *) + let constants = Default_parameters.constants_test in + let* b = + Block.bake_until_n_cycle_end + (constants.consensus_rights_delay + 1) + ~policy:(By_account m2.pkh) + b + in + let* bakers = + Plugin.RPC.Baking_rights.get + Block.rpc_ctxt + ~delegates:[deactivated_account.pkh] + b + in + match List.hd bakers with Some _ -> assert false | None -> return_unit + +(** A deactivated account, after baking with self-delegation, is + active again. Preservation of its balance is tested. Baking rights + are ensured. *) +let test_deactivation_then_self_delegation () = + let open Lwt_result_syntax in + let* ( b, + ((deactivated_contract, deactivated_account), _start_balance), + (_a2, m2) ) = + run_until_deactivation () + in + let* self_delegation = + Op.delegation (B b) deactivated_contract (Some deactivated_account.pkh) + in + let* b = + Block.bake ~policy:(By_account m2.pkh) b ~operation:self_delegation + in + let* () = + check_active_staking_balance + ~loc:__LOC__ + ~deactivated:false + b + deactivated_account + in + check_stake ~loc:__LOC__ b deactivated_account + +(** A deactivated account, which is emptied (into a newly created sink + account), then self-delegated, becomes activated. Its balance is + zero. Baking rights are ensured. *) +let test_deactivation_then_empty_then_self_delegation () = + let open Lwt_result_syntax in + let* ( b, + ((deactivated_contract, deactivated_account), _start_balance), + (_a2, m2) ) = + run_until_deactivation () + in + (* empty the contract *) + let* balance = Context.Contract.balance (B b) deactivated_contract in + let sink_account = Account.new_account () in + let sink_contract = Contract.Implicit sink_account.pkh in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (B b) + in + let*? origination_burn = cost_per_byte *? Int64.of_int origination_size in + let amount = + match balance -? origination_burn with Ok r -> r | Error _ -> assert false + in + let* empty_contract = + Op.transaction (B b) deactivated_contract sink_contract amount + in + let* b1 = + Block.bake ~policy:(By_account m2.pkh) ~operation:empty_contract b + in + (* the account is deactivated, the stake is 0. *) + let* () = check_no_stake ~loc:__LOC__ b deactivated_account in + (* self delegation *) + let* self_delegation = + Op.delegation (B b1) deactivated_contract (Some deactivated_account.pkh) + in + let* b2 = + Block.bake ~policy:(By_account m2.pkh) ~operation:self_delegation b1 + in + let* () = + check_active_staking_balance + ~loc:__LOC__ + ~deactivated:false + b2 + deactivated_account + in + (* the account is activated, the stake is still 0. *) + let* balance = Context.Contract.balance (B b2) deactivated_contract in + Assert.equal_tez ~loc:__LOC__ Tez.zero balance + +(** A deactivated account, which is emptied, then self-delegated, then + re-credited of the sunk amount, becomes active again. Staking + rights remain consistent. *) +let test_deactivation_then_empty_then_self_delegation_then_recredit () = + let open Lwt_result_syntax in + let* ( b, + ((deactivated_contract, deactivated_account), _start_balance), + (_a2, m2) ) = + run_until_deactivation () + in + (* empty the contract *) + let* balance = Context.Contract.balance (B b) deactivated_contract in + let sink_account = Account.new_account () in + let sink_contract = Contract.Implicit sink_account.pkh in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (B b) + in + let*? origination_burn = cost_per_byte *? Int64.of_int origination_size in + let amount = + match balance -? origination_burn with Ok r -> r | Error _ -> assert false + in + let* empty_contract = + Op.transaction + ~force_reveal:true + (B b) + deactivated_contract + sink_contract + amount + in + let* b0 = + Block.bake ~policy:(By_account m2.pkh) ~operation:empty_contract b + in + (* the account is deactivated, the stake is 0. *) + let* () = check_no_stake ~loc:__LOC__ b deactivated_account in + (**** self delegation *) + let* self_delegation = + Op.delegation (B b0) deactivated_contract (Some deactivated_account.pkh) + in + let* b1 = + Block.bake ~policy:(By_account m2.pkh) ~operation:self_delegation b0 + in + (* the account is still deactivated *) + let* () = check_no_stake ~loc:__LOC__ b deactivated_account in + (**** recredit *) + let* recredit_contract = + Op.transaction + ~force_reveal:true + (B b1) + sink_contract + deactivated_contract + amount + in + let* b2 = + Block.bake ~policy:(By_account m2.pkh) ~operation:recredit_contract b1 + in + let* () = + check_active_staking_balance + ~loc:__LOC__ + ~deactivated:false + b2 + deactivated_account + in + let* balance2 = Context.Contract.balance (B b2) deactivated_contract in + let* () = Assert.equal_tez ~loc:__LOC__ amount balance2 in + check_stake ~loc:__LOC__ b2 deactivated_account + +(** Initialize a block with two contracts/accounts. A third new account is also + created. The first account is self-delegated. First account sends to third + one minimal_stake tez (so that, once it is active, it can appear in + [Active_delegate_with_minimal_stake]. The third account has no delegate and is + consistent for baking rights. Then, it is self-delegated and is supposed to + be activated. Again, consistency for baking rights are preserved for the + first and third accounts. *) +let test_delegation () = + let open Lwt_result_syntax in + let* b, (a1, a2) = Context.init2 ~consensus_threshold:0 () in + let m3 = Account.new_account () in + Account.add_account m3 ; + let* m1 = Context.Contract.manager (B b) a1 in + let* m2 = Context.Contract.manager (B b) a2 in + let a3 = Contract.Implicit m3.pkh in + let* delegate = Context.Contract.delegate_opt (B b) a1 in + (match delegate with + | None -> assert false + | Some pkh -> assert (Signature.Public_key_hash.equal pkh m1.pkh)) ; + let constants = Default_parameters.constants_test in + let minimal_stake = constants.minimal_stake in + let* transact = Op.transaction ~force_reveal:true (B b) a1 a3 minimal_stake in + let* b = Block.bake ~policy:(By_account m2.pkh) b ~operation:transact in + let* delegate = Context.Contract.delegate_opt (B b) a3 in + (match delegate with None -> () | Some _ -> assert false) ; + let* () = check_no_stake ~loc:__LOC__ b m3 in + let* delegation = Op.delegation ~force_reveal:true (B b) a3 (Some m3.pkh) in + let* b = Block.bake ~policy:(By_account m2.pkh) b ~operation:delegation in + let* delegate = Context.Contract.delegate_opt (B b) a3 in + (match delegate with + | None -> assert false + | Some pkh -> assert (Signature.Public_key_hash.equal pkh m3.pkh)) ; + let* () = check_active_staking_balance ~loc:__LOC__ ~deactivated:false b m3 in + let* () = check_stake ~loc:__LOC__ b m3 in + check_stake ~loc:__LOC__ b m1 + +let tests = + [ + Tztest.tztest "simple staking rights" `Quick test_simple_staking_rights; + Tztest.tztest + "simple staking rights after baking" + `Quick + test_simple_staking_rights_after_baking; + Tztest.tztest "deactivation then bake" `Quick test_deactivation_then_bake; + Tztest.tztest + "deactivation then self delegation" + `Quick + test_deactivation_then_self_delegation; + Tztest.tztest + "deactivation then empty then self delegation" + `Quick + test_deactivation_then_empty_then_self_delegation; + Tztest.tztest + "deactivation then empty then self delegation then recredit" + `Quick + test_deactivation_then_empty_then_self_delegation_then_recredit; + Tztest.tztest "delegate" `Quick test_delegation; + Tztest.tztest + "a really deactivated account is not part of the committee" + `Quick + test_a_really_deactivated_account_is_not_in_the_committee; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("deactivation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_delegation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_delegation.ml new file mode 100644 index 000000000000..02a4db82e28b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_delegation.ml @@ -0,0 +1,1804 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (delegation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_delegation.ml + Subject: - Properties on bootstrap contracts (self-delegation, + cannot delete/change their delegate (as opposed to contracts + not-being-delegate which can do these), bootstrap manager + as delegate during origination). + - Properties on delegation depending on whether delegate + keys registration, through origination and delegation. +*) + +open Protocol +open Alpha_context +open Test_tez + +(*****************************************************************************) +(* Bootstrap contracts + ------------------- + Bootstrap contracts are heavily used in other tests. It is helpful to test + some properties of these contracts, so we can correctly interpret the other + tests that use them. *) +(*****************************************************************************) + +let expect_error err = + let open Lwt_result_syntax in + function + | err0 :: _ when err = err0 -> return_unit + | _ -> failwith "Unexpected successful result" + +let expect_alpha_error err = expect_error (Environment.Ecoproto_error err) + +let expect_no_change_registered_delegate_pkh pkh = + let open Lwt_result_syntax in + function + | Environment.Ecoproto_error (Delegate_storage.Contract.No_deletion pkh0) :: _ + when pkh0 = pkh -> + return_unit + | _ -> failwith "Delegate can not be deleted and operation should fail." + +let expect_too_low_balance_error i op = + let open Lwt_result_syntax in + let*! err = Incremental.add_operation i op in + Assert.proto_error_with_info ~loc:__LOC__ err "Balance too low" + +let expect_delegate_already_active_error i op = + let open Lwt_result_syntax in + let*! err = Incremental.add_operation i op in + Assert.proto_error_with_info ~loc:__LOC__ err "Delegate already active" + +(** Bootstrap contracts delegate to themselves. *) +let bootstrap_manager_is_bootstrap_delegate () = + let open Lwt_result_syntax in + let* b, bootstrap0 = Context.init1 () in + let* delegate0 = Context.Contract.delegate (B b) bootstrap0 in + let* manager0 = Context.Contract.manager (B b) bootstrap0 in + Assert.equal_pkh ~loc:__LOC__ delegate0 manager0.pkh + +(** Bootstrap contracts cannot change their delegate. *) +let bootstrap_delegate_cannot_change ~fee () = + let open Lwt_result_syntax in + let* b, (bootstrap0, bootstrap1) = Context.init2 () in + let pkh1 = Context.Contract.pkh bootstrap0 in + let* i = Incremental.begin_construction b ~policy:(Block.Excluding [pkh1]) in + let* manager1 = Context.Contract.manager (I i) bootstrap1 in + let* balance0 = Context.Contract.balance (I i) bootstrap0 in + let* delegate0 = Context.Contract.delegate (I i) bootstrap0 in + (* change delegation to bootstrap1 *) + let* set_delegate = Op.delegation ~fee (I i) bootstrap0 (Some manager1.pkh) in + if fee > balance0 then expect_too_low_balance_error i set_delegate + else + let* i = + Incremental.add_operation + ~expect_apply_failure: + (expect_no_change_registered_delegate_pkh delegate0) + i + set_delegate + in + let* b = Incremental.finalize_block i in + (* bootstrap0 still has same delegate *) + let* delegate0_after = Context.Contract.delegate (B b) bootstrap0 in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate0_after delegate0 in + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (B b) bootstrap0 balance0 fee + +(** Bootstrap contracts cannot delete their delegation. *) +let bootstrap_delegate_cannot_be_removed ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 () in + let* i = Incremental.begin_construction b in + let* balance = Context.Contract.balance (I i) bootstrap in + let* delegate = Context.Contract.delegate (I i) bootstrap in + let* manager = Context.Contract.manager (I i) bootstrap in + (* remove delegation *) + let* set_delegate = Op.delegation ~fee (I i) bootstrap None in + if fee > balance then expect_too_low_balance_error i set_delegate + else + let* i = + Incremental.add_operation + ~expect_apply_failure: + (expect_no_change_registered_delegate_pkh manager.pkh) + i + set_delegate + in + (* delegate has not changed *) + let* delegate_after = Context.Contract.delegate (I i) bootstrap in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate delegate_after in + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + +(** Contracts not registered as delegate can change their + delegation. *) +let delegate_can_be_changed_from_unregistered_contract ~fee () = + let open Lwt_result_syntax in + let* b, (bootstrap0, bootstrap1) = Context.init2 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let unregistered = Contract.Implicit unregistered_pkh in + let* manager0 = Context.Contract.manager (B b) bootstrap0 in + let* manager1 = Context.Contract.manager (B b) bootstrap1 in + let credit = of_int 10 in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap0 unregistered credit + in + let* balance = Context.Contract.balance (B b) bootstrap0 in + let* b = Block.bake b ~operation:credit_contract in + (* delegate to bootstrap0 *) + let* set_delegate = + Op.delegation + ~force_reveal:true + ~fee:Tez.zero + (B b) + unregistered + (Some manager0.pkh) + in + let* b = Block.bake b ~operation:set_delegate in + let* delegate = Context.Contract.delegate (B b) unregistered in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate manager0.pkh in + (* change delegation to bootstrap1 *) + let* change_delegate = + Op.delegation ~force_reveal:true ~fee (B b) unregistered (Some manager1.pkh) + in + let* i = Incremental.begin_construction b in + if fee > balance then expect_too_low_balance_error i change_delegate + else + let* i = Incremental.add_operation i change_delegate in + (* delegate has changed *) + let* delegate_after = Context.Contract.delegate (I i) unregistered in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate_after manager1.pkh in + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) unregistered credit fee + +(** Contracts not registered as delegate can delete their + delegation. *) +let delegate_can_be_removed_from_unregistered_contract ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let unregistered = Contract.Implicit unregistered_pkh in + let* manager = Context.Contract.manager (B b) bootstrap in + let credit = of_int 10 in + let* credit_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + unregistered + credit + in + let* balance = Context.Contract.balance (B b) bootstrap in + let* b = Block.bake b ~operation:credit_contract in + (* delegate to bootstrap *) + let* set_delegate = + Op.delegation + ~force_reveal:true + ~fee:Tez.zero + (B b) + unregistered + (Some manager.pkh) + in + let* b = Block.bake b ~operation:set_delegate in + let* delegate = Context.Contract.delegate (B b) unregistered in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh in + (* remove delegation *) + let* delete_delegate = Op.delegation ~fee (B b) unregistered None in + let* i = Incremental.begin_construction b in + if fee > balance then expect_too_low_balance_error i delete_delegate + else + let* i = Incremental.add_operation i delete_delegate in + (* the delegate has been removed *) + let* () = + let* pkh = Context.Contract.delegate_opt (I i) unregistered in + match pkh with + | None -> return_unit + | Some _ -> failwith "Expected delegate to be removed" + in + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) unregistered credit fee + +(** Bootstrap keys are already registered as delegate keys. *) +let bootstrap_manager_already_registered_delegate ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 () in + let* i = Incremental.begin_construction b in + let* manager = Context.Contract.manager (I i) bootstrap in + let pkh = manager.pkh in + let impl_contract = Contract.Implicit pkh in + let* balance = Context.Contract.balance (I i) impl_contract in + let* sec_reg = Op.delegation ~fee (I i) impl_contract (Some pkh) in + if fee > balance then expect_too_low_balance_error i sec_reg + else + let* i = + Incremental.add_operation + ~expect_apply_failure:(function + | Environment.Ecoproto_error Delegate_storage.Contract.Active_delegate + :: _ -> + return_unit + | _ -> + failwith "Delegate is already active and operation should fail.") + i + sec_reg + in + (* fee has been debited *) + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + +(** Bootstrap manager can be set as delegate of an originated contract + (through origination operation). *) +let delegate_to_bootstrap_by_origination ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 () in + let* i = Incremental.begin_construction b in + let* manager = Context.Contract.manager (I i) bootstrap in + let* balance = Context.Contract.balance (I i) bootstrap in + (* originate a contract with bootstrap's manager as delegate *) + let* op, orig_contract = + Op.contract_origination + ~fee + ~credit:Tez.zero + ~delegate:manager.pkh + (I i) + bootstrap + ~script:Op.dummy_script + in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (I i) + in + (* 0.257tz *) + let*? origination_burn = cost_per_byte *? Int64.of_int origination_size in + let*? t = fee +? origination_burn in + let*? total_fee = Op.dummy_script_cost +? t in + if fee > balance then expect_too_low_balance_error i op + else if total_fee > balance && balance >= fee then + (* origination did not proceed; fee has been debited *) + let expect_apply_failure = function + | Environment.Ecoproto_error err :: _ -> + Assert.test_error_encodings err ; + let error_info = + Error_monad.find_info_of_error (Environment.wrap_tzerror err) + in + if String.equal error_info.title "Balance too low" then return_unit + else failwith "unexpected failure" + | _ -> + failwith + "Test_delegation.delegate_to_bootstrap_by_origination was expected \ + to fail but has not" + in + let* i = Incremental.add_operation i ~expect_apply_failure op in + (* fee was taken *) + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + in + (* originated contract has not been created *) + let*! err = Context.Contract.balance (I i) orig_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + else + (* bootstrap is delegate, fee + origination burn have been debited *) + let* i = Incremental.add_operation i op in + let* delegate = Context.Contract.delegate (I i) orig_contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate manager.pkh in + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance total_fee + +let undelegated_originated_bootstrap_contract () = + let open Lwt_result_wrap_syntax in + let* b, _contract = + Context.init1 + ~bootstrap_contracts: + [ + Parameters. + { + delegate = None; + amount = Tez.zero; + script = Op.dummy_script; + hash = None; + }; + ] + () + in + let* b = Block.bake b in + (* We know the address of the first originated bootstrap contract because we know the bootstrap origination nonce. This address corresponds to the first TF vesting contract on mainnnet. *) + let*?@ originated_bootstrap0 = + Alpha_context.Contract.of_b58check "KT1WPEis2WhAc2FciM2tZVn8qe6pCBe9HkDp" + in + let* delegate0 = Context.Contract.delegate_opt (B b) originated_bootstrap0 in + match delegate0 with + | None -> return_unit + | Some _ -> failwith "Bootstrap contract should be undelegated (%s)" __LOC__ + +let delegated_implicit_bootstrap_contract () = + let open Lwt_result_wrap_syntax in + let*? accounts = Account.generate_accounts 2 in + let to_pkh, from_pkh = + match accounts with + | [account1; account2] -> (account1.pkh, account2.pkh) + | _ -> assert false + in + let bootstrap_delegations = [None; Some to_pkh] in + let bootstrap_accounts = + Account.make_bootstrap_accounts ~bootstrap_delegations accounts + in + let* b = Block.genesis bootstrap_accounts in + let* () = + let* pkh = Context.Contract.delegate_opt (B b) (Implicit from_pkh) in + match pkh with + | Some pkh when pkh = to_pkh -> return_unit + | Some _ | None -> + failwith "Bootstrap contract should be delegated (%s)." __LOC__ + in + (* Test delegation amount *) + let* i = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt i in + let*@ amount = Delegate.For_RPC.delegated_balance ctxt to_pkh in + Assert.equal_tez ~loc:__LOC__ amount (Tez.of_mutez_exn 4_000_000_000_000L) + +let tests_bootstrap_contracts = + [ + Tztest.tztest + "bootstrap contracts delegate to themselves" + `Quick + bootstrap_manager_is_bootstrap_delegate; + Tztest.tztest + "bootstrap contracts can change their delegate (small fee)" + `Quick + (bootstrap_delegate_cannot_change ~fee:Tez.one_mutez); + Tztest.tztest + "bootstrap contracts can change their delegate (max fee)" + `Quick + (bootstrap_delegate_cannot_change ~fee:max_tez); + Tztest.tztest + "bootstrap contracts cannot remove their delegation (small fee)" + `Quick + (bootstrap_delegate_cannot_be_removed ~fee:Tez.one_mutez); + Tztest.tztest + "bootstrap contracts cannot remove their delegation (max fee)" + `Quick + (bootstrap_delegate_cannot_be_removed ~fee:max_tez); + Tztest.tztest + "contracts not registered as delegate can change their delegation (small \ + fee)" + `Quick + (delegate_can_be_changed_from_unregistered_contract ~fee:Tez.one_mutez); + Tztest.tztest + "contracts not registered as delegate can change their delegation (max \ + fee)" + `Quick + (delegate_can_be_changed_from_unregistered_contract ~fee:max_tez); + Tztest.tztest + "contracts not registered as delegate can remove their delegation (small \ + fee)" + `Quick + (delegate_can_be_removed_from_unregistered_contract ~fee:Tez.one_mutez); + Tztest.tztest + "contracts not registered as delegate can remove their delegation (max \ + fee)" + `Quick + (delegate_can_be_removed_from_unregistered_contract ~fee:max_tez); + Tztest.tztest + "bootstrap keys are already registered as delegate keys (small fee)" + `Quick + (bootstrap_manager_already_registered_delegate ~fee:Tez.one_mutez); + Tztest.tztest + "bootstrap keys are already registered as delegate keys (max fee)" + `Quick + (bootstrap_manager_already_registered_delegate ~fee:max_tez); + Tztest.tztest + "bootstrap manager can be delegate (init origination, small fee)" + `Quick + (delegate_to_bootstrap_by_origination ~fee:Tez.one_mutez); + (* balance enough for fee but not for fee + origination burn + dummy script storage cost *) + Tztest.tztest + "bootstrap manager can be delegate (init origination, edge case)" + `Quick + (delegate_to_bootstrap_by_origination + ~fee:(Tez.of_mutez_exn 3_999_999_705_000L)); + (* fee bigger than bootstrap's initial balance*) + Tztest.tztest + "bootstrap manager can be delegate (init origination, large fee)" + `Quick + (delegate_to_bootstrap_by_origination ~fee:(Test_tez.of_int 10_000_000)); + Tztest.tztest + "originated bootstrap contract can be undelegated" + `Quick + undelegated_originated_bootstrap_contract; + Tztest.tztest + "originated bootstrap contract can be delegated" + `Quick + delegated_implicit_bootstrap_contract; + ] + +(*****************************************************************************) +(* Delegate registration + --------------------- + A delegate is a pkh. Delegates must be registered. Registration is + done via the self-delegation of the implicit contract corresponding + to the pkh. The implicit contract must be credited when the + self-delegation is done. Furthermore, trying to register an already + registered key raises an error. + + In this series of tests, we verify that + 1- unregistered delegate keys cannot be delegated to, + 2- registered keys can be delegated to, + 3- registering an already registered key raises an error. + + We consider three scenarios for setting a delegate: + - through origination, + - through delegation when the implicit contract has no delegate yet, + - through delegation when the implicit contract already has a delegate. + + We also test that emptying the implicit contract linked to a + registered delegate key does not unregister the delegate key. + + Valid registration + ------------------ + Unregistered key: + - contract not credited and no self-delegation, + - contract credited but no self-delegation, + - contract not credited and self-delegation. + + Not credited: + - no credit operation + - credit operation of 1μꜩ and then debit operation of 1μꜩ *) +(*****************************************************************************) + +(* Part A. + Unregistered delegate keys cannot be used for delegation + + Two main series of tests: without self-delegation and with a failed attempt at self-delegation: + + 1/ no self-delegation + a/ no credit + - no token transfer + - credit of 1μꜩ and then debit of 1μꜩ + b/ with credit of 1μꜩ. + For every scenario, we try three different ways of delegating: + - through origination (init origination) + - through delegation when no delegate was assigned (init delegation) + - through delegation when a delegate was assigned (switch delegation). + + 2/ Self-delegation fails if the contract has no credit. We try the + two possibilities of 1a for non-credited contracts. *) + +let expect_unregistered_key pkh = + let open Lwt_result_syntax in + function + | Environment.Ecoproto_error (Delegate_storage.Unregistered_delegate pkh0) + :: _ + when pkh = pkh0 -> + return_unit + | _ -> failwith "Delegate key is not registered: operation should fail." + +(* Part A. Section 1. + No self-delegation. *) + +(** No token transfer, no self-delegation. Originated account. If + fees are higher than balance, [Balance_too_low] is + raised. Otherwise, it checks the correct exception is raised + (unregistered key), and the fees are still debited. Using RPCs, we + verify the contract has not been originated. *) +let test_unregistered_delegate_key_init_origination ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 () in + let* i = Incremental.begin_construction b in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + (* origination with delegate argument *) + let* op, orig_contract = + Op.contract_origination + ~fee + ~delegate:unregistered_pkh + (I i) + bootstrap + ~script:Op.dummy_script + in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (I i) + in + let*? origination_burn = cost_per_byte *? Int64.of_int origination_size in + let*? (_total_fee : Tez.t) = fee +? origination_burn in + (* FIXME unused variable *) + let* balance = Context.Contract.balance (I i) bootstrap in + if fee > balance then expect_too_low_balance_error i op + else + (* origination did not proceed; fee has been debited *) + let* i = + Incremental.add_operation + ~expect_apply_failure:(expect_unregistered_key unregistered_pkh) + i + op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + in + (* originated contract has not been created *) + let*! err = Context.Contract.balance (I i) orig_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + +(** Delegation when delegate key is not assigned. Delegate account is + initialized. If fees are higher than initial credit (10 tez), + [Balance_too_low] is raised. Otherwise, fees are still debited. The + implicit contract has no delegate. *) +let test_unregistered_delegate_key_init_delegation ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = Account.(unregistered_delegate_account.pkh) in + (* initial credit for the delegated contract *) + let credit = of_int 10 in + let* credit_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + impl_contract + credit + in + let* b = Block.bake b ~operation:credit_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract credit in + (* try to delegate *) + let* delegate_op = + Op.delegation + ~force_reveal:true + ~fee + (B b) + impl_contract + (Some unregistered_delegate_pkh) + in + let* i = Incremental.begin_construction b in + if fee > credit then expect_too_low_balance_error i delegate_op + else + (* fee has been debited; no delegate *) + let* i = + Incremental.add_operation + i + ~expect_apply_failure: + (expect_unregistered_key unregistered_delegate_pkh) + delegate_op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + in + (* implicit contract has no delegate *) + let*! err = Context.Contract.delegate (I i) impl_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + +(** Re-delegation when a delegate key was already assigned. If fees + are higher than initial credit (10 tez), [Balance_too_low] is + raised. Otherwise, fees are not debited and the implicit contract + delegate remains unchanged. *) +let test_unregistered_delegate_key_switch_delegation ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let bootstrap_pkh = Context.Contract.pkh bootstrap in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = Account.(unregistered_delegate_account.pkh) in + (* initial credit for the delegated contract *) + let credit = of_int 10 in + let* init_credit = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + impl_contract + credit + in + let* b = Block.bake b ~operation:init_credit in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract credit in + (* set and check the initial delegate *) + let* delegate_op = + Op.delegation + ~force_reveal:true + ~fee:Tez.zero + (B b) + impl_contract + (Some bootstrap_pkh) + in + let* b = Block.bake b ~operation:delegate_op in + let* delegate_pkh = Context.Contract.delegate (B b) bootstrap in + let* () = Assert.equal_pkh ~loc:__LOC__ bootstrap_pkh delegate_pkh in + (* try to delegate *) + let* delegate_op = + Op.delegation ~fee (B b) impl_contract (Some unregistered_delegate_pkh) + in + let* i = Incremental.begin_construction b in + if fee > credit then expect_too_low_balance_error i delegate_op + else + (* fee has been debited; no delegate *) + let* i = + Incremental.add_operation + i + ~expect_apply_failure: + (expect_unregistered_key unregistered_delegate_pkh) + delegate_op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + in + (* implicit contract delegate has not changed *) + let* delegate_pkh_after = Context.Contract.delegate (I i) bootstrap in + Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate_pkh_after + +(** Same as [unregistered_delegate_key_init_origination] and credits + [amount], no self-delegation. *) +let test_unregistered_delegate_key_init_origination_credit ~fee ~amount () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + (* credit + check balance *) + let* create_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap impl_contract amount + in + let* b = Block.bake b ~operation:create_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* origination with delegate argument *) + let* balance = Context.Contract.balance (B b) bootstrap in + let* op, orig_contract = + Op.contract_origination + ~fee + ~delegate:unregistered_pkh + (B b) + bootstrap + ~script:Op.dummy_script + in + let* i = Incremental.begin_construction b in + if fee > balance then expect_too_low_balance_error i op + else + (* origination not done, fee taken *) + let* i = + Incremental.add_operation + ~expect_apply_failure:(expect_unregistered_key unregistered_pkh) + i + op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + in + let*! err = Context.Contract.balance (I i) orig_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + +(** Same as [unregistered_delegate_key_init_delegation] and credits + the amount [amount] of the implicit contract. *) +let test_unregistered_delegate_key_init_delegation_credit ~fee ~amount () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = Account.(unregistered_delegate_account.pkh) in + (* credit + check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + impl_contract + amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* initial credit for the delegated contract *) + let credit = of_int 10 in + let*? balance = credit +? amount in + let* init_credit = + Op.transaction ~fee:Tez.zero (B b) bootstrap impl_contract credit + in + let* b = Block.bake ~operation:init_credit b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract balance in + (* try to delegate *) + let* delegate_op = + Op.delegation + ~force_reveal:true + ~fee + (B b) + impl_contract + (Some unregistered_delegate_pkh) + in + let* i = Incremental.begin_construction b in + if fee > credit then expect_too_low_balance_error i delegate_op + else + (* fee has been taken, no delegate for contract *) + let* i = + Incremental.add_operation + ~expect_apply_failure: + (expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + in + let*! err = Context.Contract.delegate (I i) impl_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + +(** Same as in [unregistered_delegate_key_switch_delegation] and + credits the amount [amount] to the implicit contract. *) +let test_unregistered_delegate_key_switch_delegation_credit ~fee ~amount () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let bootstrap_pkh = Context.Contract.pkh bootstrap in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = Account.(unregistered_delegate_account.pkh) in + (* credit + check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + impl_contract + amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* initial credit for the delegated contract *) + let credit = of_int 10 in + let*? balance = credit +? amount in + let* init_credit = + Op.transaction ~fee:Tez.zero (B b) bootstrap impl_contract credit + in + let* b = Block.bake ~operation:init_credit b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract balance in + (* set and check the initial delegate *) + let* delegate_op = + Op.delegation + ~force_reveal:true + ~fee:Tez.zero + (B b) + impl_contract + (Some bootstrap_pkh) + in + let* b = Block.bake ~operation:delegate_op b in + let* delegate_pkh = Context.Contract.delegate (B b) bootstrap in + let* () = Assert.equal_pkh ~loc:__LOC__ bootstrap_pkh delegate_pkh in + (* switch delegate through delegation *) + let* delegate_op = + Op.delegation ~fee (B b) impl_contract (Some unregistered_delegate_pkh) + in + let* i = Incremental.begin_construction b in + if fee > credit then expect_too_low_balance_error i delegate_op + else + (* fee has been taken, delegate for contract has not changed *) + let* i = + Incremental.add_operation + ~expect_apply_failure: + (expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract balance fee + in + let* delegate = Context.Contract.delegate (I i) impl_contract in + let* () = + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_delegate_pkh + in + Assert.equal_pkh ~loc:__LOC__ delegate bootstrap_pkh + +(** A credit of some amount followed by a debit of the same amount, + no self-delegation. *) +let test_unregistered_delegate_key_init_origination_credit_debit ~fee ~amount () + = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + (* credit + check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake b ~operation:create_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* debit + check balance *) + let* debit_contract = + Op.transaction ~force_reveal:true (B b) impl_contract bootstrap amount + in + let* b = Block.bake b ~operation:debit_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* origination with delegate argument *) + let* balance = Context.Contract.balance (B b) bootstrap in + let* op, orig_contract = + Op.contract_origination + ~fee + ~delegate:unregistered_pkh + (B b) + bootstrap + ~script:Op.dummy_script + in + let* i = Incremental.begin_construction b in + if fee > balance then expect_too_low_balance_error i op + else + (* fee taken, origination not processed *) + let* i = + Incremental.add_operation + ~expect_apply_failure:(expect_unregistered_key unregistered_pkh) + i + op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) bootstrap balance fee + in + let*! err = Context.Contract.balance (I i) orig_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + +(** Same as in [unregistered_delegate_key_init_delegation] but credits + then debits the amount [amount] to the implicit contract. *) +let test_unregistered_delegate_key_init_delegation_credit_debit ~amount ~fee () + = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = Account.(unregistered_delegate_account.pkh) in + (* credit + check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + impl_contract + amount + in + let* b = Block.bake b ~operation:create_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* debit + check balance *) + let* debit_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + impl_contract + bootstrap + amount + in + let* b = Block.bake b ~operation:debit_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* initial credit for the delegated contract *) + let credit = of_int 10 in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap impl_contract credit + in + let* b = Block.bake b ~operation:credit_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract credit in + (* try to delegate *) + let* delegate_op = + Op.delegation + ~force_reveal:true + ~fee + (B b) + impl_contract + (Some unregistered_delegate_pkh) + in + let* i = Incremental.begin_construction b in + if fee > credit then expect_too_low_balance_error i delegate_op + else + (* fee has been taken, no delegate for contract *) + let* i = + Incremental.add_operation + ~expect_apply_failure: + (expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + in + let*! err = Context.Contract.delegate (I i) impl_contract in + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + +(** Same as in [unregistered_delegate_key_switch_delegation] but + credits then debits the amount [amount] to the implicit contract. *) +let test_unregistered_delegate_key_switch_delegation_credit_debit ~fee ~amount + () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let bootstrap_pkh = Context.Contract.pkh bootstrap in + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + let unregistered_delegate_account = Account.new_account () in + let unregistered_delegate_pkh = Account.(unregistered_delegate_account.pkh) in + (* credit + check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + ~fee:Tez.zero + (B b) + bootstrap + impl_contract + amount + in + let* b = Block.bake b ~operation:create_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* debit + check balance *) + let* debit_contract = + Op.transaction ~force_reveal:true (B b) impl_contract bootstrap amount + in + let* b = Block.bake b ~operation:debit_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* delegation - initial credit for the delegated contract *) + let credit = of_int 10 in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap impl_contract credit + in + let* b = Block.bake b ~operation:credit_contract in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract credit in + (* set and check the initial delegate *) + let* delegate_op = + Op.delegation + ~force_reveal:true + ~fee:Tez.zero + (B b) + impl_contract + (Some bootstrap_pkh) + in + let* b = Block.bake b ~operation:delegate_op in + let* delegate_pkh = Context.Contract.delegate (B b) bootstrap in + let* () = Assert.equal_pkh ~loc:__LOC__ bootstrap_pkh delegate_pkh in + (* switch delegate through delegation *) + let* delegate_op = + Op.delegation (B b) ~fee impl_contract (Some unregistered_delegate_pkh) + in + let* i = Incremental.begin_construction b in + if fee > credit then expect_too_low_balance_error i delegate_op + else + (* fee has been taken, delegate for contract has not changed *) + let* i = + Incremental.add_operation + ~expect_apply_failure: + (expect_unregistered_key unregistered_delegate_pkh) + i + delegate_op + in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) impl_contract credit fee + in + let* delegate = Context.Contract.delegate (I i) impl_contract in + Assert.not_equal_pkh ~loc:__LOC__ delegate unregistered_delegate_pkh + +(* Part A. Section 2. + Self-delegation to an empty contract fails. *) + +(** Self-delegation with zero-balance contract should fail. *) +let test_failed_self_delegation_no_transaction () = + let open Lwt_result_syntax in + let* b, _contract = Context.init1 () in + let* i = Incremental.begin_construction b in + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + (* check balance *) + let* balance = Context.Contract.balance (I i) impl_contract in + let* () = Assert.equal_tez ~loc:__LOC__ Tez.zero balance in + (* self delegation fails *) + let* self_delegation = + Op.delegation (I i) impl_contract (Some unregistered_pkh) + in + let*! err = Incremental.add_operation i self_delegation in + Assert.proto_error_with_info ~loc:__LOC__ err "Empty implicit contract" + +(** Implicit contract is credited then debited of same amount (i.e., + is emptied). Self-delegation fails. *) +let test_failed_self_delegation_emptied_implicit_contract amount () = + let open Lwt_result_syntax in + (* create an implicit contract *) + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + (* credit implicit contract and check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* empty implicit contract and check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) impl_contract bootstrap amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* self delegation fails *) + let* self_delegation = + Op.delegation (B b) impl_contract (Some unregistered_pkh) + in + let* i = Incremental.begin_construction b in + let*! err = Incremental.add_operation i self_delegation in + Assert.proto_error_with_info ~loc:__LOC__ err "Empty implicit contract" + +(** Implicit contract is credited with a non-zero quantity [amount] + tz, then it is delegated. The operation of debit of [amount] tz + should fail as the contract is already delegated. *) +let test_emptying_delegated_implicit_contract_fails amount () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let* bootstrap_manager = Context.Contract.manager (B b) bootstrap in + let account = Account.new_account () in + let unregistered_pkh = Account.(account.pkh) in + let impl_contract = Contract.Implicit unregistered_pkh in + (* credit unregistered implicit contract and check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* delegate the contract to the bootstrap *) + let* delegation = + Op.delegation + ~force_reveal:true + (B b) + impl_contract + (Some bootstrap_manager.pkh) + in + let* b = Block.bake ~operation:delegation b in + (* empty implicit contract and expect error since the contract is delegated *) + let* create_contract = Op.transaction (B b) impl_contract bootstrap amount in + let* i = Incremental.begin_construction b in + let*! err = Incremental.add_operation i create_contract in + Assert.proto_error_with_info + ~loc:__LOC__ + err + "Empty implicit delegated contract" + +(* Part B. + - Valid registration: + - Credit implicit contract with some ꜩ + verification of balance + - Self delegation + verification + - Empty contract + verification of balance + verification of not being erased / self-delegation + - Create delegator implicit contract w first implicit contract as delegate + verification of delegation. *) + +(** Initialized account is credited of [amount] tz, then + self-delegated. *) +let test_valid_delegate_registration_init_delegation_credit amount () = + let open Lwt_result_syntax in + (* create an implicit contract *) + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.Implicit delegate_pkh in + (* credit > 0ꜩ + check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* self delegation + verification *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some delegate_pkh) + in + let* b = Block.bake ~operation:self_delegation b in + let* delegate = Context.Contract.delegate (B b) impl_contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh in + (* create an implicit contract with no delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.Implicit unregistered_pkh in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap delegator Tez.one + in + let* b = Block.bake ~operation:credit_contract b in + (* check no delegate for delegator contract *) + let*! err = Context.Contract.delegate (B b) delegator in + let* () = + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + in + (* delegation to the newly registered key *) + let* delegation = + Op.delegation ~force_reveal:true (B b) delegator (Some delegate_account.pkh) + in + let* b = Block.bake ~operation:delegation b in + (* check delegation *) + let* delegator_delegate = Context.Contract.delegate (B b) delegator in + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(** Create an implicit contract, credits with [amount] + tz. Self-delegates. Create another implicit contract with + bootstrap as delegate. Re-delegate it to the first implicit + contract. *) +let test_valid_delegate_registration_switch_delegation_credit amount () = + let open Lwt_result_syntax in + (* create an implicit contract *) + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.Implicit delegate_pkh in + (* credit > 0ꜩ + check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* self delegation + verification *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some delegate_pkh) + in + let* b = Block.bake ~operation:self_delegation b in + let* delegate = Context.Contract.delegate (B b) impl_contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh in + (* create an implicit contract with bootstrap's account as delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.Implicit unregistered_pkh in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap delegator Tez.one + in + let* b = Block.bake ~operation:credit_contract b in + let* bootstrap_manager = Context.Contract.manager (B b) bootstrap in + let* delegation = + Op.delegation + ~force_reveal:true + (B b) + delegator + (Some bootstrap_manager.pkh) + in + let* b = Block.bake ~operation:delegation b in + (* test delegate of new contract is bootstrap *) + let* delegator_delegate = Context.Contract.delegate (B b) delegator in + let* () = + Assert.equal_pkh ~loc:__LOC__ delegator_delegate bootstrap_manager.pkh + in + (* delegation with newly registered key *) + let* delegation = Op.delegation (B b) delegator (Some delegate_account.pkh) in + let* b = Block.bake ~operation:delegation b in + let* delegator_delegate = Context.Contract.delegate (B b) delegator in + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(** Create an implicit contract. *) +let test_valid_delegate_registration_init_delegation_credit_debit amount () = + let open Lwt_result_syntax in + (* create an implicit contract *) + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.Implicit delegate_pkh in + (* credit > 0ꜩ+ check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* self delegation + verification *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some delegate_pkh) + in + let* b = Block.bake ~operation:self_delegation b in + let* delegate = Context.Contract.delegate (B b) impl_contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate in + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + let* empty_contract = Op.transaction (B b) impl_contract bootstrap amount in + let* b = Block.bake ~operation:empty_contract b in + (* impl_contract is empty *) + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* verify self-delegation after contract is emptied *) + let* delegate = Context.Contract.delegate (B b) impl_contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate in + (* create an implicit contract with no delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.Implicit unregistered_pkh in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap delegator Tez.one + in + let* b = Block.bake ~operation:credit_contract b in + (* check no delegate for delegator contract *) + let*! err = Context.Contract.delegate (B b) delegator in + let* () = + Assert.error ~loc:__LOC__ err (function + | Tezos_rpc.Context.Not_found _ -> true + | _ -> false) + in + (* delegation to the newly registered key *) + let* delegation = + Op.delegation ~force_reveal:true (B b) delegator (Some delegate_account.pkh) + in + let* b = Block.bake ~operation:delegation b in + (* check delegation *) + let* delegator_delegate = Context.Contract.delegate (B b) delegator in + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(** A created implicit contract is credited with [amount] tz, then is + self-delegated. It is emptied (fund back into bootstrap), and + should remain existing (as registered as delegate). Another created + implicit contract is delegated to bootstrap, then should be able to + be re-delegated to the latter contract. *) +let test_valid_delegate_registration_switch_delegation_credit_debit amount () = + let open Lwt_result_syntax in + (* create an implicit contract *) + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let delegate_account = Account.new_account () in + let delegate_pkh = Account.(delegate_account.pkh) in + let impl_contract = Contract.Implicit delegate_pkh in + (* credit > 0ꜩ + check balance *) + let* create_contract = + Op.transaction ~force_reveal:true (B b) bootstrap impl_contract amount + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract amount in + (* self delegation + verification *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some delegate_pkh) + in + let* b = Block.bake ~operation:self_delegation b in + let* delegate = Context.Contract.delegate (B b) impl_contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate_pkh delegate in + (* empty implicit contracts are usually deleted but they are kept if + they were registered as delegates. we empty the contract in + order to verify this. *) + let* empty_contract = Op.transaction (B b) impl_contract bootstrap amount in + let* b = Block.bake ~operation:empty_contract b in + (* impl_contract is empty *) + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* create an implicit contract with bootstrap's account as delegate *) + let unregistered_account = Account.new_account () in + let unregistered_pkh = Account.(unregistered_account.pkh) in + let delegator = Contract.Implicit unregistered_pkh in + let* credit_contract = + Op.transaction ~fee:Tez.zero (B b) bootstrap delegator Tez.one + in + let* b = Block.bake ~operation:credit_contract b in + let* bootstrap_manager = Context.Contract.manager (B b) bootstrap in + let* delegation = + Op.delegation + ~force_reveal:true + (B b) + delegator + (Some bootstrap_manager.pkh) + in + let* b = Block.bake ~operation:delegation b in + (* test delegate of new contract is bootstrap *) + let* delegator_delegate = Context.Contract.delegate (B b) delegator in + let* () = + Assert.equal_pkh ~loc:__LOC__ delegator_delegate bootstrap_manager.pkh + in + (* delegation with newly registered key *) + let* delegation = + Op.delegation ~force_reveal:true (B b) delegator (Some delegate_account.pkh) + in + let* b = Block.bake ~operation:delegation b in + let* delegator_delegate = Context.Contract.delegate (B b) delegator in + Assert.equal_pkh ~loc:__LOC__ delegator_delegate delegate_pkh + +(* Part C. + A second self-delegation should raise an [Active_delegate] error. *) + +(** Second self-delegation should fail with implicit contract with + some credit. *) +let test_double_registration () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.Implicit pkh in + (* credit 1μꜩ+ check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + (B b) + bootstrap + impl_contract + Tez.one_mutez + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.one_mutez in + (* self-delegation *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some pkh) + in + let* b = Block.bake ~operation:self_delegation b in + (* second self-delegation *) + let* second_registration = Op.delegation (B b) impl_contract (Some pkh) in + let* i = Incremental.begin_construction b in + expect_delegate_already_active_error i second_registration + +(** Second self-delegation should fail with implicit contract emptied + after first self-delegation. *) +let test_double_registration_when_empty () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.Implicit pkh in + (* credit 1μꜩ+ check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + (B b) + bootstrap + impl_contract + Tez.one_mutez + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.one_mutez in + (* self delegation *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some pkh) + in + let* b = Block.bake ~operation:self_delegation b in + (* empty the delegate account *) + let* empty_contract = + Op.transaction (B b) impl_contract bootstrap Tez.one_mutez + in + let* b = Block.bake ~operation:empty_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* second self-delegation *) + let* second_registration = Op.delegation (B b) impl_contract (Some pkh) in + let* i = Incremental.begin_construction b in + expect_delegate_already_active_error i second_registration + +(** Second self-delegation should fail with implicit contract emptied + then credited back after first self-delegation. *) +let test_double_registration_when_recredited () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let pkh = Account.(account.pkh) in + let impl_contract = Contract.Implicit pkh in + (* credit 1μꜩ+ check balance *) + let* create_contract = + Op.transaction + ~force_reveal:true + (B b) + bootstrap + impl_contract + Tez.one_mutez + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.one_mutez in + (* self delegation *) + let* self_delegation = + Op.delegation ~force_reveal:true (B b) impl_contract (Some pkh) + in + let* b = Block.bake ~operation:self_delegation b in + (* empty the delegate account *) + let* empty_contract = + Op.transaction + ~force_reveal:true + (B b) + impl_contract + bootstrap + Tez.one_mutez + in + let* b = Block.bake ~operation:empty_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.zero in + (* credit 1μꜩ+ check balance *) + let* create_contract = + Op.transaction (B b) bootstrap impl_contract Tez.one_mutez + in + let* b = Block.bake ~operation:create_contract b in + let* () = Assert.balance_is ~loc:__LOC__ (B b) impl_contract Tez.one_mutez in + (* second self-delegation *) + let* second_registration = Op.delegation (B b) impl_contract (Some pkh) in + let* i = Incremental.begin_construction b in + expect_delegate_already_active_error i second_registration + +(** Self-delegation on unrevealed contract. *) +let test_unregistered_and_unrevealed_self_delegate_key_init_delegation ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let {Account.pkh; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; _} = Account.new_account () in + let contract = Alpha_context.Contract.Implicit pkh in + let* operation = + Op.transaction ~force_reveal:true (B b) bootstrap contract (of_int 10) + in + let* b = Block.bake ~operation b in + let* op = + Op.delegation ~fee ~force_reveal:true (B b) contract (Some delegate_pkh) + in + let* balance = Context.Contract.balance (B b) contract in + let* i = Incremental.begin_construction b in + if fee > balance then expect_too_low_balance_error i op + else + (* origination did not proceed; fee has been debited *) + let* i = + Incremental.add_operation + ~expect_apply_failure:(expect_unregistered_key delegate_pkh) + i + op + in + Assert.balance_was_debited ~loc:__LOC__ (I i) contract balance fee + +(** Self-delegation on revealed but not registered contract. *) +let test_unregistered_and_revealed_self_delegate_key_init_delegation ~fee () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let {Account.pkh; pk; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; _} = Account.new_account () in + let contract = Alpha_context.Contract.Implicit pkh in + let* operation = Op.transaction (B b) bootstrap contract (of_int 10) in + let* b = Block.bake ~operation b in + let* operation = Op.revelation (B b) pk in + let* b = Block.bake ~operation b in + let* op = Op.delegation ~fee (B b) contract (Some delegate_pkh) in + let* balance = Context.Contract.balance (B b) contract in + let* i = Incremental.begin_construction b in + if fee > balance then expect_too_low_balance_error i op + else + (* origination did not proceed; fee has been debited *) + let* i = + Incremental.add_operation + ~expect_apply_failure:(expect_unregistered_key delegate_pkh) + i + op + in + Assert.balance_was_debited ~loc:__LOC__ (I i) contract balance fee + +(** Self-delegation emptying a fresh contract. *) +let test_self_delegation_emptying_contract () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let {Account.pkh; pk; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; _} = Account.new_account () in + let contract = Alpha_context.Contract.Implicit pkh in + let amount = of_int 10 in + let* operation = Op.transaction (B b) bootstrap contract amount in + let* b = Block.bake ~operation b in + let* operation = Op.revelation ~fee:Tez.zero (B b) pk in + let* b = Block.bake ~operation b in + let* op = Op.delegation ~fee:amount (B b) contract (Some delegate_pkh) in + let* () = + let* is_revealed = + Context.Contract.is_manager_key_revealed (B b) contract + in + match is_revealed with + | false -> failwith "contract should exist" + | true -> return_unit + in + let* i = Incremental.begin_construction b in + (* The delegation operation should be applied and the fees + debited but it is expected to fail in the apply-part. *) + let* i = + Incremental.add_operation ~expect_apply_failure:(fun _ -> return_unit) i op + in + let* is_revealed = Context.Contract.is_manager_key_revealed (I i) contract in + match is_revealed with + | false -> return_unit + | true -> failwith "contract should have been removed" + +(** Self-delegation on revealed and registered contract. *) +let test_registered_self_delegate_key_init_delegation () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let {Account.pkh; _} = Account.new_account () in + let {Account.pkh = delegate_pkh; pk = delegate_pk; _} = + Account.new_account () + in + let contract = Alpha_context.Contract.Implicit pkh in + let delegate_contract = Alpha_context.Contract.Implicit delegate_pkh in + let* operation = + Op.transaction ~force_reveal:true (B b) bootstrap contract (of_int 10) + in + let* b = Block.bake ~operation b in + let* operation = + Op.transaction (B b) bootstrap delegate_contract (of_int 1) + in + let* b = Block.bake ~operation b in + let* operation = Op.revelation (B b) delegate_pk in + let* b = Block.bake ~operation b in + let* operation = Op.delegation (B b) delegate_contract (Some delegate_pkh) in + let* b = Block.bake ~operation b in + let* operation = + Op.delegation ~force_reveal:true (B b) contract (Some delegate_pkh) + in + let* b = Block.bake ~operation b in + let* delegate = Context.Contract.delegate (B b) contract in + let* () = Assert.equal_pkh ~loc:__LOC__ delegate delegate_pkh in + return_unit + +let test_bls_account_cannot_self_delegate () = + let open Lwt_result_syntax in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let {Account.pkh = tz4_pkh; pk = tz4_pk; _} = + Account.new_account ~algo:Bls () + in + let tz4_contract = Alpha_context.Contract.Implicit tz4_pkh in + let* operation = + Op.transaction + ~force_reveal:true + (B b) + bootstrap + tz4_contract + (of_int 200_000) + in + let* b = Block.bake ~operation b in + let* operation = Op.revelation (B b) tz4_pk in + let* b = Block.bake ~operation b in + let* operation = Op.delegation (B b) tz4_contract (Some tz4_pkh) in + let* inc = Incremental.begin_construction b in + let tz4_pkh = match tz4_pkh with Bls pkh -> pkh | _ -> assert false in + let expect_failure = function + | [ + Environment.Ecoproto_error + (Contract_delegate_storage.Forbidden_tz4_delegate pkh); + ] + when Signature.Bls.Public_key_hash.(pkh = tz4_pkh) -> + return_unit + | err -> + failwith + "Error trace:@,\ + %a does not match the \ + [Contract_delegate_storage.Forbidden_tz4_delegate] error" + Error_monad.pp_print_trace + err + in + let* (_i : Incremental.t) = + Incremental.validate_operation ~expect_failure inc operation + in + return_unit + +let tests_delegate_registration = + [ + Tztest.tztest "TEST" `Quick test_bls_account_cannot_self_delegate; + (*** unregistered delegate key: no self-delegation ***) + (* no token transfer, no self-delegation *) + Tztest.tztest + "unregistered delegate key (origination, small fee)" + `Quick + (test_unregistered_delegate_key_init_origination ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key (origination, edge case fee)" + `Quick + (test_unregistered_delegate_key_init_origination ~fee:(of_int 3_999_488)); + Tztest.tztest + "unregistered delegate key (origination, large fee)" + `Quick + (test_unregistered_delegate_key_init_origination ~fee:(of_int 10_000_000)); + Tztest.tztest + "unregistered delegate key (init with delegation, small fee)" + `Quick + (test_unregistered_delegate_key_init_delegation ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key (init with delegation, max fee)" + `Quick + (test_unregistered_delegate_key_init_delegation ~fee:max_tez); + Tztest.tztest + "unregistered delegate key (switch with delegation, small fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key (switch with delegation, max fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation ~fee:max_tez); + (* credit/debit 1μꜩ, no self-delegation *) + Tztest.tztest + "unregistered delegate key - credit/debit 1μꜩ (origination, small fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit_debit + ~fee:Tez.one_mutez + ~amount:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit/debit 1μꜩ (origination, large fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit_debit + ~fee:max_tez + ~amount:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit/debit 1μꜩ (init with delegation, \ + small fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit/debit 1μꜩ (init with delegation, \ + large fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:max_tez); + Tztest.tztest + "unregistered delegate key - credit/debit 1μꜩ (switch with delegation, \ + small fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit/debit 1μꜩ (switch with delegation, \ + large fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit_debit + ~amount:Tez.one_mutez + ~fee:max_tez); + (* credit 1μꜩ, no self-delegation *) + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (origination, small fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit + ~fee:Tez.one_mutez + ~amount:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (origination, edge case fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit + ~fee:(of_int 3_999_488) + ~amount:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (origination, large fee)" + `Quick + (test_unregistered_delegate_key_init_origination_credit + ~fee:(of_int 10_000_000) + ~amount:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (init with delegation, small fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (init with delegation, large fee)" + `Quick + (test_unregistered_delegate_key_init_delegation_credit + ~amount:Tez.one_mutez + ~fee:max_tez); + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (switch with delegation, small \ + fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit + ~amount:Tez.one_mutez + ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered delegate key - credit 1μꜩ (switch with delegation, large \ + fee)" + `Quick + (test_unregistered_delegate_key_switch_delegation_credit + ~amount:Tez.one_mutez + ~fee:max_tez); + (* self delegation on unrevealed and unregistered contract *) + Tztest.tztest + "unregistered and unrevealed self-delegation (small fee)" + `Quick + (test_unregistered_and_unrevealed_self_delegate_key_init_delegation + ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered and unrevealed self-delegation (large fee)" + `Quick + (test_unregistered_and_unrevealed_self_delegate_key_init_delegation + ~fee:max_tez); + (* self delegation on unregistered contract *) + Tztest.tztest + "unregistered and revealed self-delegation (small fee)" + `Quick + (test_unregistered_and_revealed_self_delegate_key_init_delegation + ~fee:Tez.one_mutez); + Tztest.tztest + "unregistered and revealed self-delegation large fee)" + `Quick + (test_unregistered_and_revealed_self_delegate_key_init_delegation + ~fee:max_tez); + Tztest.tztest + "unregistered and revealed self-delegation (fee = balance)" + `Quick + test_self_delegation_emptying_contract; + (* self delegation on registered contract *) + Tztest.tztest + "registered and revealed self-delegation" + `Quick + test_registered_self_delegate_key_init_delegation; + (*** unregistered delegate key: failed self-delegation ***) + (* no token transfer, self-delegation *) + Tztest.tztest + "failed self-delegation: no transaction" + `Quick + test_failed_self_delegation_no_transaction; + (* credit 1μtz, debit 1μtz, self-delegation *) + Tztest.tztest + "failed self-delegation: credit & debit 1μꜩ" + `Quick + (test_failed_self_delegation_emptied_implicit_contract Tez.one_mutez); + (* credit 1μtz, delegate, debit 1μtz *) + Tztest.tztest + "empty delegated contract is not deleted: credit 1μꜩ, delegate & debit \ + 1μꜩ" + `Quick + (test_emptying_delegated_implicit_contract_fails Tez.one_mutez); + (*** valid registration ***) + (* valid registration: credit 1 μꜩ, self delegation *) + Tztest.tztest + "valid delegate registration: credit 1μꜩ, self delegation (init with \ + delegation)" + `Quick + (test_valid_delegate_registration_init_delegation_credit Tez.one_mutez); + Tztest.tztest + "valid delegate registration: credit 1μꜩ, self delegation (switch with \ + delegation)" + `Quick + (test_valid_delegate_registration_switch_delegation_credit Tez.one_mutez); + (* valid registration: credit 1 μꜩ, self delegation, debit 1μꜩ *) + Tztest.tztest + "valid delegate registration: credit 1μꜩ, self delegation, debit 1μꜩ \ + (init with delegation)" + `Quick + (test_valid_delegate_registration_init_delegation_credit_debit + Tez.one_mutez); + Tztest.tztest + "valid delegate registration: credit 1μꜩ, self delegation, debit 1μꜩ \ + (switch with delegation)" + `Quick + (test_valid_delegate_registration_switch_delegation_credit_debit + Tez.one_mutez); + (*** double registration ***) + Tztest.tztest "double registration" `Quick test_double_registration; + Tztest.tztest + "double registration when delegate account is emptied" + `Quick + test_double_registration_when_empty; + Tztest.tztest + "double registration when delegate account is emptied and then recredited" + `Quick + test_double_registration_when_recredited; + ] + +(******************************************************************************) +(* Main *) +(******************************************************************************) + +let tests = tests_bootstrap_contracts @ tests_delegate_registration + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("delegation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_attestation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_attestation.ml new file mode 100644 index 000000000000..44955162dca2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_attestation.ml @@ -0,0 +1,963 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (double attestation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_double_attestation.ml + Subject: Double attestation evidence operation may happen when an + attester attested two different blocks on the same level. +*) + +open Protocol +open Alpha_context + +(****************************************************************) +(* Utility functions *) +(****************************************************************) +let autostaking_disabled = + { + Default_parameters.constants_test.adaptive_issuance with + autostaking_enable = false; + } + +let block_fork ?excluding b = + let open Lwt_result_syntax in + let* baker_1, baker_2 = Context.get_first_different_bakers ?excluding (B b) in + let* blk_a = Block.bake ~policy:(By_account baker_1) b in + let+ blk_b = Block.bake ~policy:(By_account baker_2) b in + (blk_a, blk_b) + +(* Checks that there is exactly one denunciation for the given delegate *) +let check_denunciations ~(level : Raw_level.t) b delegate = + let open Lwt_result_syntax in + let* denunciations = Context.get_denunciations (B b) in + match denunciations with + | [(d, item)] when Signature.Public_key_hash.equal d delegate -> + assert (item.Denunciations_repr.misbehaviour.kind = Double_attesting) ; + assert ( + Raw_level_repr.to_int32 item.Denunciations_repr.misbehaviour.level + = Raw_level.to_int32 level) ; + return_unit + | _ -> assert false + +let check_empty_denunciations b = + let open Lwt_result_syntax in + let* denunciations = Context.get_denunciations (B b) in + match denunciations with [] -> return_unit | _ -> assert false + +(****************************************************************) +(* Tests *) +(****************************************************************) + +let order_attestations ~correct_order op1 op2 = + let oph1 = Operation.hash op1 in + let oph2 = Operation.hash op2 in + let c = Operation_hash.compare oph1 oph2 in + if correct_order then if c < 0 then (op1, op2) else (op2, op1) + else if c < 0 then (op2, op1) + else (op1, op2) + +let double_attestation ctxt ?(correct_order = true) op1 op2 = + let e1, e2 = order_attestations ~correct_order op1 op2 in + Op.double_attestation ctxt e1 e2 + +let double_preattestation ctxt ?(correct_order = true) op1 op2 = + let e1, e2 = order_attestations ~correct_order op1 op2 in + Op.double_preattestation ctxt e1 e2 + +(** This test verifies that when a "cheater" double attests and + doesn't have enough tokens to re-freeze of full deposit, we only + freeze what we can (i.e. the remaining balance) but we check that + another denunciation will slash 50% of the initial (expected) amount + of the deposit. *) + +(** Simple scenario where two attestations are made from the same + delegate and exposed by a double_attestation operation. Also verify + that punishment is operated. *) +let test_valid_double_attestation_evidence () = + let open Lwt_result_wrap_syntax in + let constants = + { + Default_parameters.constants_test with + issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + }; + consensus_threshold = 0; + } + in + let* genesis, _contracts = Context.init_with_constants2 constants in + let* blk_1, blk_2 = block_fork genesis in + (* from blk_1 we bake blk_a and from blk_2 we bake blk_b so that + the same delegate attests blk_a and blk_b and these 2 form + a valid double attestation evidence; + - note that we cannot have double attestation evidence + at the level of blk_1, blk_2 because both have as parent genesis + and so the attestations are identical because the blocks blk_1, blk_2 + are identical. *) + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* delegate, _ = Context.get_attester (B blk_a) in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let* bakers = Context.get_bakers (B blk_a) in + let baker = Context.get_first_different_baker delegate bakers in + let* full_balance = Context.Delegate.full_balance (B blk_a) baker in + let* () = check_empty_denunciations blk_a in + let* blk_final = Block.bake ~policy:(By_account baker) ~operation blk_a in + (* Check that parts of the frozen deposits are slashed *) + let*? double_level = Context.get_level (B blk_a) in + let* () = check_denunciations ~level:double_level blk_final delegate in + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_a) delegate + in + let* initial_frozen_deposits = + Context.Delegate.initial_frozen_deposits (B blk_final) delegate + in + let* frozen_deposits_right_after = + Context.Delegate.current_frozen_deposits (B blk_final) delegate + in + (* Check that the initial frozen deposits have not changed *) + let* () = + Assert.equal_tez ~loc:__LOC__ initial_frozen_deposits frozen_deposits_before + in + (* Similarly for current frozen deposits because slashing is deferred to the + end of the cycle. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_right_after + frozen_deposits_before + in + let* blk_eoc, metadata, _ = + Block.bake_until_n_cycle_end_with_metadata + ~policy:(By_account baker) + 2 + blk_final + in + let metadata = Option.value_f ~default:(fun () -> assert false) metadata in + let autostaked = Block.autostaked delegate metadata in + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B blk_eoc) delegate + in + let frozen_deposits_after = Test_tez.(frozen_deposits_after -! autostaked) in + let one_minus_p = + Percentage.neg + constants.percentage_of_frozen_deposits_slashed_per_double_attestation + in + let {Q.num; den} = Percentage.to_q one_minus_p in + let expected_frozen_deposits_after = + Test_tez.(frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + expected_frozen_deposits_after + frozen_deposits_after + in + (* Check that [baker] is rewarded with: + - baking_reward_fixed_portion for baking and, + - half of the frozen_deposits for including the evidence *) + let*?@ baking_reward = + Delegate.Rewards.For_RPC.reward_from_constants + constants + ~reward_kind:Baking_reward_fixed_portion + in + let divider = + Int64.add + 2L + (Int64.of_int + constants.adaptive_issuance.global_limit_of_staking_over_baking) + in + let evidence_reward = Test_tez.(frozen_deposits_after /! divider) in + let expected_reward = Test_tez.(baking_reward +! evidence_reward) in + let* full_balance_with_rewards = + Context.Delegate.full_balance (B blk_eoc) baker + in + let real_reward = Test_tez.(full_balance_with_rewards -! full_balance) in + Assert.equal_tez ~loc:__LOC__ expected_reward real_reward + +(** Check that a double (pre)attestation evidence with equivalent + attestations but on different branches succeeds. *) +let test_different_branch () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* blk = Block.bake genesis in + let* attester, _slots = Context.get_attester (B blk) in + let* attestation_a = Op.raw_attestation ~delegate:attester blk in + let* attestation_b = + Op.raw_attestation ~branch:Block_hash.zero ~delegate:attester blk + in + let operation = double_attestation (B blk) attestation_a attestation_b in + let* _blk = Block.bake ~operation blk in + let* preattestation_a = Op.raw_preattestation ~delegate:attester blk in + let* preattestation_b = + Op.raw_preattestation ~branch:Block_hash.zero ~delegate:attester blk + in + let operation = + double_preattestation (B blk) preattestation_a preattestation_b + in + let* _blk = Block.bake ~operation blk in + return_unit + +(** Check that a double (pre)attestation evidence succeeds when the + operations have distinct slots (that both belong to the delegate) + and are otherwise identical. *) +let test_different_slots () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* blk = Block.bake genesis in + let* attesters = Context.get_attesters (B blk) in + let delegate, slot1, slot2 = + (* Find an attester with more than 1 slot. *) + WithExceptions.Option.get + ~loc:__LOC__ + (List.find_map + (fun (attester : RPC.Validators.t) -> + match attester.slots with + | slot1 :: slot2 :: _ -> Some (attester.delegate, slot1, slot2) + | _ -> None) + attesters) + in + let* attestation1 = Op.raw_attestation ~delegate ~slot:slot1 blk in + let* attestation2 = Op.raw_attestation ~delegate ~slot:slot2 blk in + let doubleA = double_attestation (B blk) attestation1 attestation2 in + let* (_ : Block.t) = Block.bake ~operation:doubleA blk in + let* preattestation1 = Op.raw_preattestation ~delegate ~slot:slot1 blk in + let* preattestation2 = Op.raw_preattestation ~delegate ~slot:slot2 blk in + let doubleB = double_preattestation (B blk) preattestation1 preattestation2 in + let* (_ : Block.t) = Block.bake ~operation:doubleB blk in + return_unit + +(** Say a delegate double-attests twice and say the 2 evidences are timely + included. Then the delegate can no longer bake. *) +let test_two_double_attestation_evidences_leadsto_no_bake () = + let open Lwt_result_syntax in + let issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + } + in + let* genesis, _contracts = + Context.init3 ~consensus_threshold:0 ~issuance_weights () + in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* delegate, _ = Context.get_attester (B blk_a) in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let* bakers = Context.get_bakers (B blk_a) in + let baker = Context.get_first_different_baker delegate bakers in + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_a) delegate + in + let* blk_with_evidence1 = + Block.bake ~policy:(By_account baker) ~operation blk_a + in + let* blk_30, blk_40 = block_fork ~excluding:[delegate] blk_with_evidence1 in + let* blk_3 = Block.bake ~policy:(Excluding [delegate]) blk_30 in + let* blk_4 = Block.bake ~policy:(Excluding [delegate]) blk_40 in + let* attestation_3 = Op.raw_attestation blk_3 in + let* attestation_4 = Op.raw_attestation blk_4 in + let operation = + double_attestation (B blk_with_evidence1) attestation_3 attestation_4 + in + let* blk_with_evidence2, (_blk_metadata, operations_recpts) = + Block.bake_with_metadata ~policy:(By_account baker) ~operation blk_3 + in + Log.info "Baked block with double attestation evidence" ; + let rcpt = + List.find + (fun (rcpt : operation_receipt) -> + match rcpt with + | Operation_metadata + { + contents = + Apply_results.Single_result + (Apply_results.Double_attestation_evidence_result rslt); + } -> + rslt.forbidden_delegate = Some delegate + | _ -> false) + operations_recpts + in + let* _ = Assert.get_some ~loc:__LOC__ rcpt in + (* Check that the frozen deposits haven't changed yet. *) + let* frozen_deposits_right_after = + Context.Delegate.current_frozen_deposits (B blk_with_evidence2) delegate + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_before + frozen_deposits_right_after + in + let* is_forbidden = + Context.Delegate.is_forbidden + ~policy:(Block.By_account baker) + (B blk_with_evidence2) + delegate + in + let* () = Assert.is_true ~loc:__LOC__ is_forbidden in + let*! b = Block.bake ~policy:(By_account delegate) blk_with_evidence2 in + (* a delegate with 0 frozen deposits cannot bake *) + let* () = + Assert.proto_error ~loc:__LOC__ b (function + | Validate_errors.Consensus.Forbidden_delegate _ -> true + | _ -> false) + in + (* Check that all frozen deposits have been slashed at the end of the cycle. *) + let* b, metadata, _ = + Block.bake_until_n_cycle_end_with_metadata + ~policy:(By_account baker) + 2 + blk_with_evidence2 + in + let metadata = Option.value_f ~default:(fun () -> assert false) metadata in + let autostaked = Block.autostaked delegate metadata in + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B b) delegate + in + let frozen_deposits_after = Test_tez.(frozen_deposits_after -! autostaked) in + let* base_reward = Context.get_baking_reward_fixed_portion (B genesis) in + let* to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy:(By_account baker) + (B b) + (Block.current_cycle b) + delegate + base_reward + in + (* [delegate] baked one block. The block rewards for that block should be all + that's left *) + Assert.equal_tez + ~loc:__LOC__ + Test_tez.(base_reward -! to_liquid) + frozen_deposits_after + +(** Say a delegate double-attests twice in a cycle, + and say the 2 evidences are included in different (valid) cycles. + Then the delegate is forbidden and can no longer bake. *) +let test_two_double_attestation_evidences_staggered () = + let open Lwt_result_syntax in + let* genesis, _contracts = + Context.init3 + ~consensus_threshold:0 + ~adaptive_issuance:autostaking_disabled + () + in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* delegate, _ = Context.get_attester (B blk_a) in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let* bakers = Context.get_bakers (B blk_a) in + let baker = Context.get_first_different_baker delegate bakers in + let* (_full_balance : Tez.t) = + Context.Delegate.full_balance (B blk_a) baker + in + let* blk_with_evidence1 = + Block.bake ~policy:(By_account baker) ~operation blk_a + in + + let* blk_30, blk_40 = block_fork ~excluding:[delegate] blk_with_evidence1 in + let* blk_3 = Block.bake ~policy:(Excluding [delegate]) blk_30 in + let* blk_4 = Block.bake ~policy:(Excluding [delegate]) blk_40 in + let* attestation_3 = Op.raw_attestation ~delegate blk_3 in + let* attestation_4 = Op.raw_attestation ~delegate blk_4 in + let operation_evidence2 = + double_attestation (B blk_with_evidence1) attestation_3 attestation_4 + in + + let* operation = + Adaptive_issuance_helpers.stake + (B blk_with_evidence1) + (Protocol.Alpha_context.Contract.Implicit delegate) + (Tez.of_mutez_exn 1_000_000_000L) + in + let* blk_with_stake = + Block.bake ~policy:(By_account baker) ~operation blk_with_evidence1 + in + let* blk_new_cycle, _metadata, _ = + Block.bake_until_cycle_end_with_metadata + ~policy:(By_account baker) + blk_with_stake + in + let* blk_with_evidence2 = + Block.bake + ~policy:(By_account baker) + ~operation:operation_evidence2 + blk_new_cycle + in + (* Check that NOT all the frozen deposits are slashed *) + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B blk_with_evidence2) delegate + in + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_new_cycle) delegate + in + Log.info + "Tez before slashing: %a @.After slashing %a @." + Tez.pp + frozen_deposits_before + Tez.pp + frozen_deposits_after ; + let* () = Assert.not_equal_tez ~loc:__LOC__ Tez.zero frozen_deposits_after in + let* is_forbidden = + Context.Delegate.is_forbidden + ~policy:(Block.By_account baker) + (B blk_with_evidence2) + delegate + in + let* () = Assert.is_true ~loc:__LOC__ is_forbidden in + let*! b = Block.bake ~policy:(By_account delegate) blk_with_evidence2 in + (* A forbidden delegate cannot bake *) + Assert.proto_error ~loc:__LOC__ b (function + | Validate_errors.Consensus.Forbidden_delegate _ -> true + | _ -> false) + +(** Say a delegate double-attests twice in two consecutive cycles, + and say the 2 evidences are timely included. Then the delegate + is forbidden and can no longer bake. *) +let test_two_double_attestation_evidences_consecutive_cycles () = + let open Lwt_result_syntax in + let* genesis, _contracts = + Context.init3 + ~consensus_threshold:0 + ~adaptive_issuance:autostaking_disabled + () + in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* delegate, _ = Context.get_attester (B blk_a) in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let* bakers = Context.get_bakers (B blk_a) in + let baker = Context.get_first_different_baker delegate bakers in + let* (_full_balance : Tez.t) = + Context.Delegate.full_balance (B blk_a) baker + in + let* blk_with_evidence1 = + Block.bake ~policy:(By_account baker) ~operation blk_a + in + let* operation = + Adaptive_issuance_helpers.stake + (B blk_with_evidence1) + (Protocol.Alpha_context.Contract.Implicit delegate) + (Tez.of_mutez_exn 1_000_000_000L) + in + let* blk_with_stake = + Block.bake ~policy:(By_account baker) ~operation blk_with_evidence1 + in + let* blk_new_cycle = + Block.bake_until_cycle_end ~policy:(Excluding [delegate]) blk_with_stake + in + let* blk_30, blk_40 = block_fork ~excluding:[delegate] blk_new_cycle in + let* blk_3 = Block.bake ~policy:(Excluding [delegate]) blk_30 in + let* blk_4 = Block.bake ~policy:(Excluding [delegate]) blk_40 in + let* attestation_3 = Op.raw_attestation ~delegate blk_3 in + let* attestation_4 = Op.raw_attestation ~delegate blk_4 in + let operation = + double_attestation (B blk_new_cycle) attestation_3 attestation_4 + in + let* blk_with_evidence2 = + Block.bake ~policy:(By_account baker) ~operation blk_3 + in + (* Check that NOT all the frozen deposits are slashed *) + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B blk_with_evidence2) delegate + in + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_3) delegate + in + Log.info + "Tez before slashing: %a @.After slashing %a @." + Tez.pp + frozen_deposits_before + Tez.pp + frozen_deposits_after ; + let* () = Assert.not_equal_tez ~loc:__LOC__ Tez.zero frozen_deposits_after in + let* is_forbidden = + Context.Delegate.is_forbidden + ~policy:(Block.By_account baker) + (B blk_with_evidence2) + delegate + in + let* () = Assert.is_true ~loc:__LOC__ is_forbidden in + let*! b = Block.bake ~policy:(By_account delegate) blk_with_evidence2 in + (* A forbidden delegate cannot bake *) + Assert.proto_error ~loc:__LOC__ b (function + | Validate_errors.Consensus.Forbidden_delegate _ -> true + | _ -> false) + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Check that an invalid double attestation operation that exposes a + valid attestation fails. *) +let test_invalid_double_attestation () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init_n ~consensus_threshold:0 10 () in + let* b = Block.bake genesis in + let* attestation = Op.raw_attestation b in + let* b = Block.bake ~operation:(Operation.pack attestation) b in + Op.double_attestation (B b) attestation attestation |> fun operation -> + let*! res = Block.bake ~operation b in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_denunciation + Misbehaviour.Double_attesting -> + true + | _ -> false) + +(** Check that an double attestation operation that is invalid due to + incorrect ordering of the attestations fails. *) +let test_invalid_double_attestation_variant () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* b = Block.bake_until_cycle_end genesis in + let* blk_1, blk_2 = block_fork b in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + double_attestation + (B genesis) + ~correct_order:false + attestation_a + attestation_b + |> fun operation -> + let*! res = Block.bake ~operation genesis in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_denunciation + Misbehaviour.Double_attesting -> + true + | _ -> false) + +(** Check that a future-cycle double attestation fails. *) +let test_too_early_double_attestation_evidence () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* b = Block.bake_until_cycle_end genesis in + let* blk_1, blk_2 = block_fork b in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + double_attestation (B genesis) attestation_a attestation_b |> fun operation -> + let*! res = Block.bake ~operation genesis in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Too_early_denunciation + {kind = Misbehaviour.Double_attesting; _} -> + true + | _ -> false) + +(** Check that after [max_slashing_period * blocks_per_cycle + 1], it is not possible + to create a double_attestation anymore. *) +let test_too_late_double_attestation_evidence () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let max_slashing_period = Constants.max_slashing_period in + let* Constants.{parametric = {blocks_per_cycle; _}; _} = + Context.get_constants (B genesis) + in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + let* blk = + Block.bake_n + ((max_slashing_period * Int32.to_int blocks_per_cycle) + 1) + blk_a + in + double_attestation (B blk) attestation_a attestation_b |> fun operation -> + let*! res = Block.bake ~operation blk in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Outdated_denunciation + {kind = Misbehaviour.Double_attesting; _} -> + true + | _ -> false) + +(** Check that an invalid double attestation evidence that exposes two + attestations made by two different attesters fails. *) +let test_different_delegates () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* genesis = Block.bake genesis in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* attester_a, attester_b = + Context.get_first_different_attesters (B blk_b) + in + let* e_a = Op.raw_attestation ~delegate:attester_a.delegate blk_a in + let* e_b = Op.raw_attestation ~delegate:attester_b.delegate blk_b in + let* (_ : Block.t) = Block.bake ~operation:(Operation.pack e_b) blk_b in + double_attestation (B blk_b) e_a e_b |> fun operation -> + let*! res = Block.bake ~operation blk_b in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Inconsistent_denunciation + {kind = Misbehaviour.Double_attesting; _} -> + true + | _ -> false) + +(** Check that a double attestation evidence that exposes a ill-formed + attestation fails. *) +let test_wrong_delegate () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* attester_a, _a_slots = Context.get_attester (B blk_a) in + let* attestation_a = Op.raw_attestation ~delegate:attester_a blk_a in + let* attester0, _slots0 = Context.get_attester_n (B blk_b) 0 in + let* attester1, _slots1 = Context.get_attester_n (B blk_b) 1 in + let attester_b = + if Signature.Public_key_hash.equal attester_a attester0 then attester1 + else attester0 + in + let* attestation_b = Op.raw_attestation ~delegate:attester_b blk_b in + double_attestation (B blk_b) attestation_a attestation_b |> fun operation -> + let*! res = Block.bake ~operation blk_b in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Inconsistent_denunciation + {kind = Misbehaviour.Double_attesting; _} -> + true + | _ -> false) + +let test_freeze_more_with_low_balance = + let open Lwt_result_syntax in + let get_attesting_slots_for_account ctxt account = + (* Get the slots of the given account in the given context. *) + let* attesters_list = Context.get_attesters ctxt in + match attesters_list with + | [d1; d2] -> + return + (if Signature.Public_key_hash.equal account d1.delegate then d1 + else if Signature.Public_key_hash.equal account d2.delegate then d2 + else assert false) + .slots + | _ -> assert false + (* there are exactly two attesters for this test. *) + in + let double_attest_and_punish b2 account1 = + let open Lwt_result_syntax in + (* Bake a block on top of [b2] that includes a double-attestation + denunciation of [account1]. *) + let* blk_d1, blk_d2 = block_fork b2 in + let* blk_a = Block.bake ~policy:(Block.By_account account1) blk_d1 in + let* blk_b = Block.bake ~policy:(Block.By_account account1) blk_d2 in + let* slots_a = get_attesting_slots_for_account (B blk_a) account1 in + let slot = + match List.hd slots_a with None -> assert false | Some s -> s + in + let* attestation_a = Op.raw_attestation ~delegate:account1 ~slot blk_a in + let* slots_b = get_attesting_slots_for_account (B blk_b) account1 in + let slot = + match List.hd slots_b with None -> assert false | Some s -> s + in + let* attestation_b = Op.raw_attestation ~delegate:account1 ~slot blk_b in + let denunciation = double_attestation (B b2) attestation_a attestation_b in + Block.bake ~policy:(Excluding [account1]) b2 ~operations:[denunciation] + in + let check_unique_attester b account2 = + let* attesters_list = Context.get_attesters (B b) in + match attesters_list with + | [{delegate; _}] when Signature.Public_key_hash.equal account2 delegate -> + return_unit + | _ -> failwith "We are supposed to only have account2 as attester." + in + fun () -> + let constants = + { + Default_parameters.constants_test with + issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + }; + consensus_threshold = 0; + origination_size = 0; + consensus_rights_delay = 5; + percentage_of_frozen_deposits_slashed_per_double_attestation = + (* enforce that percentage is 50% in the test's params. *) + Percentage.p50; + adaptive_issuance = + { + Default_parameters.constants_test.adaptive_issuance with + autostaking_enable = false; + }; + } + in + let* genesis, (c1, c2) = Context.init_with_constants2 constants in + let account1 = Context.Contract.pkh c1 in + let account2 = Context.Contract.pkh c2 in + (* we empty the available balance of [account1]. *) + let* info1 = Context.Delegate.info (B genesis) account1 in + let* op = + Op.transaction + (B genesis) + (Contract.Implicit account1) + (Contract.Implicit account2) + Test_tez.(info1.full_balance -! info1.frozen_deposits) + in + let* b2 = + Block.bake ~policy:(Block.By_account account2) genesis ~operations:[op] + in + let* info2 = Context.Delegate.info (B b2) account1 in + (* after block [b2], the spendable balance of [account1] is 0tz. So, given + that we have the invariant full_balance = spendable balance + + frozen_deposits, in this particular case, full_balance = frozen_deposits + for [account1], and the frozen_deposits didn't change since genesis. *) + let* () = + Assert.equal_tez ~loc:__LOC__ info2.full_balance info2.frozen_deposits + in + let* () = + Assert.equal_tez ~loc:__LOC__ info1.frozen_deposits info2.frozen_deposits + in + let* b3 = double_attest_and_punish b2 account1 in + (* Denunciation has happened but slashing hasn't yet. + We check that frozen deposits haven't changed and still correspond to the + full balance and itself hasn't changed. *) + let* info3 = Context.Delegate.info (B b3) account1 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + info3.frozen_deposits + info3.current_frozen_deposits + in + let* () = + Assert.equal_tez ~loc:__LOC__ info3.full_balance info3.frozen_deposits + in + let* () = + Assert.equal_tez ~loc:__LOC__ info3.full_balance info2.full_balance + in + (* We now bake until end of cycle only with [account2]: + block of the new cycle are called cX below. *) + let* c1 = Block.bake_until_cycle_end ~policy:(By_account account2) b3 in + (* Denunciation has happened: we check that the full balance of [account1] + is (still) equal to its deposit. *) + let* info4 = Context.Delegate.info (B c1) account1 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + info4.full_balance + info4.current_frozen_deposits + in + (* We also check that compared to deposits at block [b2], [account1] lost + 50% of its deposits. *) + let one_minus_slash_percentage = + Percentage.neg + constants.percentage_of_frozen_deposits_slashed_per_double_attestation + in + let {Q.num; den} = Percentage.to_q one_minus_slash_percentage in + let expected_frozen_deposits_after = + Test_tez.(info2.frozen_deposits *! Z.to_int64 num /! Z.to_int64 den) + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + expected_frozen_deposits_after + info4.current_frozen_deposits + in + let* c2 = double_attest_and_punish c1 account1 in + (* Second denunciation has happened but slashing not yet, again. + Current frozen deposits reflect the slashing of 50% of the original + deposits. *) + let* info5 = Context.Delegate.info (B c2) account1 in + let* () = + Assert.not_equal_tez + ~loc:__LOC__ + info5.current_frozen_deposits + info5.frozen_deposits + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + info5.current_frozen_deposits + info4.current_frozen_deposits + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + info5.full_balance + info5.current_frozen_deposits + in + let*! c3 = Block.bake c2 ~policy:(By_account account1) in + (* Once the denunciations has summed up to 100%, the baker cannot bake anymore *) + let* () = + Assert.proto_error ~loc:__LOC__ c3 (function + | Validate_errors.Consensus.Forbidden_delegate _ -> true + | _ -> false) + in + let* c3 = Block.bake_until_cycle_end c2 ~policy:(By_account account2) in + (* Second slashing has happened: we check that the full balance of + [account1] reflects the slashing of 50% of the original deposit. Its + current deposits are thus 0tz. *) + let* info6 = Context.Delegate.info (B c3) account1 in + let* () = Assert.equal_tez ~loc:__LOC__ info6.full_balance Tez.zero in + let* () = + Assert.equal_tez ~loc:__LOC__ info6.current_frozen_deposits Tez.zero + in + (* We bake [2 * consensus_rights_delay - 1] additional cycles only with [account2]. + Because [account1] does not bake during this period, it loses its rights. + *) + let* d1 = + Block.bake_until_n_cycle_end + ~policy:(By_account account2) + ((2 * constants.consensus_rights_delay) - 1) + c3 + in + let* info7 = Context.Delegate.info (B d1) account1 in + (* [account1] is only deactivated after 1 + [2 * consensus_rights_delay] (see + [Delegate_activation_storage.set_active] since the last time it was + active, that is, since the first cycle. Thus the cycle at which + [account1] is deactivated is 2 + [2 * consensus_rights_delay] from genesis. *) + let* () = Assert.equal_bool ~loc:__LOC__ info7.deactivated false in + (* account1 is still active, but has no rights. *) + let* () = check_unique_attester d1 account2 in + let* e1 = Block.bake_until_cycle_end ~policy:(By_account account2) d1 in + (* account1 has no rights and furthermore is no longer active. *) + let* () = check_unique_attester e1 account2 in + let* info8 = Context.Delegate.info (B e1) account1 in + Assert.equal_bool ~loc:__LOC__ info8.deactivated true + +(** Injecting a valid double attestation multiple times raises an error. *) +let test_two_double_attestation_evidences_leads_to_duplicate_denunciation () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init2 ~consensus_threshold:0 () in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* delegate, _ = Context.get_attester (B blk_a) in + let* attestation_a = Op.raw_attestation blk_a in + let* attestation_b = Op.raw_attestation blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let operation2 = double_attestation (B genesis) attestation_b attestation_a in + let* bakers = Context.get_bakers (B blk_a) in + let baker = Context.get_first_different_baker delegate bakers in + let* (_full_balance : Tez.t) = + Context.Delegate.full_balance (B blk_a) baker + in + let*! e = + Block.bake + ~policy:(By_account baker) + ~operations:[operation; operation2] + blk_a + in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Conflicting_denunciation + {kind = Misbehaviour.Double_attesting; _} -> + true + | _ -> false) + in + let* blk_with_evidence1 = + Block.bake ~policy:(By_account baker) ~operation blk_a + in + let*! e = + Block.bake ~policy:(By_account baker) ~operation blk_with_evidence1 + in + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Already_denounced + {kind = Misbehaviour.Double_attesting; _} -> + true + | _ -> false) + +let tests = + [ + Tztest.tztest + "valid double attestation evidence" + `Quick + test_valid_double_attestation_evidence; + Tztest.tztest + "valid evidence with same (pre)attestations on different branches" + `Quick + test_different_branch; + Tztest.tztest + "valid evidence with same (pre)attestations on different slots" + `Quick + test_different_slots; + Tztest.tztest + "2 valid double attestation evidences lead to not being able to bake" + `Quick + test_two_double_attestation_evidences_leadsto_no_bake; + Tztest.tztest + "2 valid double attestation evidences for double signings in consecutive \ + cycles lead to forbidding" + `Quick + test_two_double_attestation_evidences_consecutive_cycles; + Tztest.tztest + "2 valid double attestation evidences in consecutive cycles for double \ + signing in same cycle lead to forbidding" + `Quick + test_two_double_attestation_evidences_staggered; + Tztest.tztest + "valid double attestation injected multiple time" + `Quick + test_two_double_attestation_evidences_leads_to_duplicate_denunciation; + Tztest.tztest + "invalid double attestation evidence" + `Quick + test_invalid_double_attestation; + Tztest.tztest + "another invalid double attestation evidence" + `Quick + test_invalid_double_attestation_variant; + Tztest.tztest + "too early double attestation evidence" + `Quick + test_too_early_double_attestation_evidence; + Tztest.tztest + "too late double attestation evidence" + `Quick + test_too_late_double_attestation_evidence; + Tztest.tztest "different delegates" `Quick test_different_delegates; + Tztest.tztest "wrong delegate" `Quick test_wrong_delegate; + (* This test has been deactivated following the changes of the + forbidding mechanism that now forbids delegates right after the + first denunciation, it should be fixed and reactivated + https://gitlab.com/tezos/tezos/-/issues/6904 *) + (* Tztest.tztest *) + (* "freeze available balance after slashing" *) + (* `Quick *) + (* test_freeze_more_with_low_balance; *) + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("double attestation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_baking.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_baking.ml new file mode 100644 index 000000000000..a16e3591008e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_baking.ml @@ -0,0 +1,647 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (double baking) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_double_baking.ml + Subject: A double baking evidence operation may be injected when it has + been observed that a baker baked two different blocks at the + same level and same round. +*) + +open Protocol +open Alpha_context + +(****************************************************************) +(* Utility functions *) +(****************************************************************) + +(** Bake two blocks at the same level using the same policy (i.e. same + baker). *) +let block_fork ?policy (contract_a, contract_b) b = + let open Lwt_result_syntax in + let* operation = + Op.transaction (B b) contract_a contract_b Alpha_context.Tez.one_cent + in + let* blk_a = Block.bake ?policy ~operation b in + let+ blk_b = Block.bake ?policy b in + (blk_a, blk_b) + +let order_block_hashes ~correct_order bh1 bh2 = + let hash1 = Block_header.hash bh1 in + let hash2 = Block_header.hash bh2 in + let c = Block_hash.compare hash1 hash2 in + if correct_order then if c < 0 then (bh1, bh2) else (bh2, bh1) + else if c < 0 then (bh2, bh1) + else (bh1, bh2) + +let double_baking ctxt ?(correct_order = true) bh1 bh2 = + let bh1, bh2 = order_block_hashes ~correct_order bh1 bh2 in + Op.double_baking ctxt bh1 bh2 + +(****************************************************************) +(* Tests *) +(****************************************************************) + +(** Simple scenario where two blocks are baked by a same baker and + exposed by a double baking evidence operation. *) +let test_valid_double_baking_evidence () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init2 ~consensus_threshold:0 () in + let* c = Context.get_constants (B genesis) in + let p = + c.parametric.percentage_of_frozen_deposits_slashed_per_double_baking + in + let* baker1, baker2 = Context.get_first_different_bakers (B genesis) in + let* blk_fst_cycle, _, _ = + Block.bake_until_cycle_end_with_metadata ~policy:(By_account baker2) genesis + in + let* blk_a, blk_b = + block_fork ~policy:(By_account baker1) contracts blk_fst_cycle + in + let operation = double_baking (B blk_a) blk_a.header blk_b.header in + let* blk_final = Block.bake ~policy:(By_account baker2) ~operation blk_a in + (* Check that the frozen deposits haven't been slashed, yet. *) + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_a) baker1 + in + let* frozen_deposits_right_after = + Context.Delegate.current_frozen_deposits (B blk_final) baker1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_before + frozen_deposits_right_after + in + (* Check that the initial frozen deposits has not changed *) + let* initial_frozen_deposits_before = + Context.Delegate.initial_frozen_deposits (B blk_a) baker1 + in + let* initial_frozen_deposits_after = + Context.Delegate.initial_frozen_deposits (B blk_final) baker1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + initial_frozen_deposits_before + initial_frozen_deposits_after + in + (* Check that the frozen deposits have been slashed at the end of the cycle. *) + let* blk_eoc, end_cycle_metadata, _next_cycle = + Block.bake_until_n_cycle_end_with_metadata + ~policy:(By_account baker2) + 2 + blk_final + in + let end_cycle_metadata = + Option.value_f ~default:(fun () -> assert false) end_cycle_metadata + in + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B blk_eoc) baker1 + in + let autostaked = Block.autostaked baker1 end_cycle_metadata in + let Q.{num; den} = Percentage.to_q p in + let expected_frozen_deposits_after = + Test_tez.( + frozen_deposits_before + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) + +! autostaked) + in + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_after + expected_frozen_deposits_after + +(* auxiliary function used in [double_attestation] *) +let order_attestations ~correct_order op1 op2 = + let oph1 = Operation.hash op1 in + let oph2 = Operation.hash op2 in + let c = Operation_hash.compare oph1 oph2 in + if correct_order then if c < 0 then (op1, op2) else (op2, op1) + else if c < 0 then (op2, op1) + else (op1, op2) + +(* auxiliary function used in + [test_valid_double_baking_followed_by_double_attesting] and + [test_valid_double_attesting_followed_by_double_baking] *) +let double_attestation ctxt ?(correct_order = true) op1 op2 = + let e1, e2 = order_attestations ~correct_order op1 op2 in + Op.double_attestation ctxt e1 e2 + +let test_valid_double_baking_followed_by_double_attesting () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init2 ~consensus_threshold:0 () in + let* baker1, baker2 = Context.get_first_different_bakers (B genesis) in + let* b = Block.bake genesis in + let* blk_a, blk_b = block_fork ~policy:(By_account baker1) contracts b in + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_a) baker1 + in + let* initial_frozen_deposits_before = + Context.Delegate.initial_frozen_deposits (B blk_a) baker1 + in + double_baking (B blk_a) blk_a.header blk_b.header |> fun operation -> + let* blk_with_db_evidence = + Block.bake ~policy:(By_account baker2) ~operation blk_a + in + let* e1, e2 = Context.get_first_different_attesters (B blk_a) in + let delegate = + if Signature.Public_key_hash.( = ) e1.delegate baker1 then e1.delegate + else e2.delegate + in + let* attestation_a = Op.raw_attestation ~delegate blk_a in + let* attestation_b = Op.raw_attestation ~delegate blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let* blk_final = + Block.bake ~policy:(By_account baker2) ~operation blk_with_db_evidence + in + let* frozen_deposits_right_after = + Context.Delegate.current_frozen_deposits (B blk_final) baker1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_before + frozen_deposits_right_after + in + let* blk_eoc, metadata, _ = + Block.bake_until_n_cycle_end_with_metadata + ~policy:(By_account baker2) + 2 + blk_final + in + let metadata = Option.value_f ~default:(fun () -> assert false) metadata in + let autostaked = Block.autostaked baker1 metadata in + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B blk_eoc) baker1 + in + let* csts = Context.get_constants (B genesis) in + let p_de = + csts.parametric.percentage_of_frozen_deposits_slashed_per_double_attestation + in + let p_db = + csts.parametric.percentage_of_frozen_deposits_slashed_per_double_baking + in + let p = Percentage.add_bounded p_de p_db in + let Q.{num; den} = Percentage.to_q p in + let expected_frozen_deposits_after = + Test_tez.( + frozen_deposits_before + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) + +! autostaked) + in + (* Both slashings are computed on the initial amount of frozen deposits so + the percentages are additive, not multiplicative. *) + Assert.equal_tez + ~loc:__LOC__ + expected_frozen_deposits_after + frozen_deposits_after + +(* auxiliary function used in [test_valid_double_attesting_followed_by_double_baking] *) +let block_fork_diff b = + let open Lwt_result_syntax in + let* baker_1, baker_2 = Context.get_first_different_bakers (B b) in + let* blk_a = Block.bake ~policy:(By_account baker_1) b in + let* blk_b = Block.bake ~policy:(By_account baker_2) b in + return (blk_a, blk_b) + +let test_valid_double_attesting_followed_by_double_baking () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init2 ~consensus_threshold:0 () in + let* baker1, baker2 = Context.get_first_different_bakers (B genesis) in + let* blk_1, blk_2 = block_fork_diff genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B blk_a) baker1 + in + let* initial_frozen_deposits_before = + Context.Delegate.initial_frozen_deposits (B blk_a) baker1 + in + let* e1, e2 = Context.get_first_different_attesters (B blk_a) in + let delegate = + if Signature.Public_key_hash.( = ) e1.delegate baker1 then e1.delegate + else e2.delegate + in + let* attestation_a = Op.raw_attestation ~delegate blk_a in + let* attestation_b = Op.raw_attestation ~delegate blk_b in + let operation = double_attestation (B genesis) attestation_a attestation_b in + let* blk_with_de_evidence = + Block.bake ~policy:(By_account baker2) ~operation blk_a + in + let* blk_a, blk_b = block_fork ~policy:(By_account baker1) contracts blk_1 in + double_baking (B blk_a) blk_a.header blk_b.header |> fun operation -> + let* blk_with_db_evidence = + Block.bake ~policy:(By_account baker2) ~operation blk_with_de_evidence + in + let* frozen_deposits_right_after = + Context.Delegate.current_frozen_deposits (B blk_with_db_evidence) baker1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_before + frozen_deposits_right_after + in + let* blk_eoc, end_cycle_metadata, _ = + Block.bake_until_n_cycle_end_with_metadata + ~policy:(By_account baker2) + 2 + blk_with_db_evidence + in + let end_cycle_metadata = + Option.value_f ~default:(fun () -> assert false) end_cycle_metadata + in + let autostaked = Block.autostaked baker1 end_cycle_metadata in + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B blk_eoc) baker1 + in + let* csts = Context.get_constants (B genesis) in + let p_de = + csts.parametric.percentage_of_frozen_deposits_slashed_per_double_attestation + in + let p_db = + csts.parametric.percentage_of_frozen_deposits_slashed_per_double_baking + in + let p = Percentage.add_bounded p_de p_db in + let Q.{num; den} = Percentage.to_q p in + let expected_frozen_deposits_after = + Test_tez.( + frozen_deposits_before + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) + +! autostaked) + in + (* Both slashings are computed on the initial amount of frozen deposits so + the percentages are additive, not multiplicative. *) + Assert.equal_tez + ~loc:__LOC__ + expected_frozen_deposits_after + frozen_deposits_after + +(** Test that the payload producer of the block containing a double + baking evidence (and not the block producer, if different) receives + the reward. *) +let test_payload_producer_gets_evidence_rewards () = + let open Lwt_result_syntax in + let* genesis, contracts = + Context.init_n ~consensus_threshold:0 ~consensus_committee_size:64 10 () + in + let* c = Context.get_constants (B genesis) in + let p = + c.parametric.percentage_of_frozen_deposits_slashed_per_double_baking + in + let* baking_reward_fixed_portion = + Context.get_baking_reward_fixed_portion (B genesis) + in + let* baker1, baker2 = Context.get_first_different_bakers (B genesis) in + let c1_c2 = + match contracts with c1 :: c2 :: _ -> (c1, c2) | _ -> assert false + in + let* b1, b2 = block_fork ~policy:(By_account baker1) c1_c2 genesis in + double_baking (B b1) b1.header b2.header |> fun db_evidence -> + let* b_with_evidence = + Block.bake ~policy:(By_account baker2) ~operation:db_evidence b1 + in + let* attesters = Context.get_attesters (B b_with_evidence) in + let* preattesters = + List.map_es + (function + | {Plugin.RPC.Validators.delegate; slots; _} -> return (delegate, slots)) + attesters + in + let* preattestations = + List.map_ep + (fun (attester, _slots) -> + Op.preattestation ~delegate:attester b_with_evidence) + preattesters + in + let* b' = + Block.bake + ~payload_round:(Some Round.zero) + ~locked_round:(Some Round.zero) + ~policy:(By_account baker1) + ~operations:(preattestations @ [db_evidence]) + b1 + in + (* The denunciation happened but no slashing nor reward happened yet. *) + let* frozen_deposits_before = + Context.Delegate.current_frozen_deposits (B b1) baker1 + in + let* initial_frozen_deposits_before = + Context.Delegate.initial_frozen_deposits (B b1) baker1 + in + let* frozen_deposits_right_after = + Context.Delegate.current_frozen_deposits (B b') baker1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_right_after + frozen_deposits_before + in + let* full_balance = Context.Delegate.full_balance (B b1) baker2 in + let expected_reward_right_after = baking_reward_fixed_portion in + let* full_balance_with_rewards_right_after = + Context.Delegate.full_balance (B b') baker2 + in + let real_reward_right_after = + Test_tez.(full_balance_with_rewards_right_after -! full_balance) + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + expected_reward_right_after + real_reward_right_after + in + (* Slashing and rewarding happen at the end of the cycle. *) + let* b', end_cycle_metadata, _ = + Block.bake_until_n_cycle_end_with_metadata ~policy:(By_account baker2) 2 b' + in + let end_cycle_metadata = + Option.value_f ~default:(fun () -> assert false) end_cycle_metadata + in + let autostaked = Block.autostaked baker1 end_cycle_metadata in + let* frozen_deposits_after = + Context.Delegate.current_frozen_deposits (B b') baker1 + in + let Q.{num; den} = Percentage.to_q p in + let expected_frozen_deposits_after = + Test_tez.( + frozen_deposits_before + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) + +! autostaked) + in + (* the frozen deposits of the double-signer [baker1] are slashed *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_after + expected_frozen_deposits_after + in + let slashed_amount = + Test_tez.(frozen_deposits_before -! (frozen_deposits_after -! autostaked)) + in + (* [baker2] included the double baking evidence in [b_with_evidence] + and so it receives the reward for the evidence included in [b'] + (besides the reward for proposing the payload). *) + let divider = + Int64.add + 2L + (Int64.of_int + c.parametric.adaptive_issuance.global_limit_of_staking_over_baking) + in + let evidence_reward = Test_tez.(slashed_amount /! divider) in + let baked_blocks = + Int64.of_int + (Int32.to_int b'.header.shell.level - Int32.to_int b1.header.shell.level) + in + let expected_reward = + Test_tez.((baking_reward_fixed_portion *! baked_blocks) +! evidence_reward) + in + let* full_balance_with_rewards = + Context.Delegate.full_balance (B b') baker2 + in + let real_reward = Test_tez.(full_balance_with_rewards -! full_balance) in + let* () = Assert.equal_tez ~loc:__LOC__ expected_reward real_reward in + (* [baker1] did not produce the payload, it does not receive the reward for the + evidence *) + let* full_balance_at_b1 = Context.Delegate.full_balance (B b1) baker1 in + let* full_balance_at_b' = Context.Delegate.full_balance (B b') baker1 in + Assert.equal_tez + ~loc:__LOC__ + full_balance_at_b' + Test_tez.(full_balance_at_b1 -! slashed_amount) + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Check that a double baking operation fails if it exposes the same two + blocks. *) +let test_same_blocks () = + let open Lwt_result_syntax in + let* b, _contracts = Context.init2 () in + let* ba = Block.bake b in + double_baking (B ba) ba.header ba.header |> fun operation -> + let*! res = Block.bake ~operation ba in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_double_baking_evidence _ -> true + | _ -> false) + +(** Check that an double baking operation that is invalid due to + incorrect ordering of the block headers fails. *) +let test_incorrect_order () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init2 ~consensus_threshold:0 () in + let* blk_a, blk_b = block_fork ~policy:(By_round 0) contracts genesis in + double_baking (B genesis) ~correct_order:false blk_a.header blk_b.header + |> fun operation -> + let*! res = Block.bake ~operation genesis in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_double_baking_evidence _ -> true + | _ -> false) + +(** Check that a double baking operation exposing two blocks with + different levels fails. *) +let test_different_levels () = + let open Lwt_result_syntax in + let* b, contracts = Context.init2 ~consensus_threshold:0 () in + let* blk_a, blk_b = block_fork ~policy:(By_round 0) contracts b in + let* blk_b_2 = Block.bake blk_b in + double_baking (B blk_a) blk_a.header blk_b_2.header |> fun operation -> + let*! res = Block.bake ~operation blk_a in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_double_baking_evidence _ -> true + | _ -> false) + +(** Check that a double baking operation exposing two yet-to-be-baked + blocks fails. *) +let test_too_early_double_baking_evidence () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init2 ~consensus_threshold:0 () in + let* b = Block.bake_until_cycle_end genesis in + let* blk_a, blk_b = block_fork ~policy:(By_round 0) contracts b in + double_baking (B b) blk_a.header blk_b.header |> fun operation -> + let*! res = Block.bake ~operation genesis in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Too_early_denunciation + {kind = Misbehaviour.Double_baking; _} -> + true + | _ -> false) + +(** Check that after [max_slashing_period * blocks_per_cycle + 1] blocks -- corresponding to 2 cycles + --, it is not possible to create a double baking operation anymore. *) +let test_too_late_double_baking_evidence () = + let open Lwt_result_syntax in + let max_slashing_period = Constants.max_slashing_period in + let* b, contracts = Context.init2 ~consensus_threshold:0 () in + let* blk_a, blk_b = block_fork ~policy:(By_round 0) contracts b in + let* blk = Block.bake_until_n_cycle_end max_slashing_period blk_a in + double_baking (B blk) blk_a.header blk_b.header |> fun operation -> + let*! res = Block.bake ~operation blk in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Outdated_denunciation + {kind = Misbehaviour.Double_baking; _} -> + true + | _ -> false) + +(** Check that before [blocks_per_cycle] blocks + -- corresponding to 2 cycles --, it is still possible to create a + double baking operation. *) +let test_just_in_time_double_baking_evidence () = + let open Lwt_result_syntax in + let* b, contracts = Context.init2 ~consensus_threshold:0 () in + let* Constants.{parametric = {blocks_per_cycle; _}; _} = + Context.get_constants (B b) + in + let* blk_a, blk_b = block_fork ~policy:(By_round 0) contracts b in + let* blk = Block.bake_until_cycle_end blk_a in + let* blk = Block.bake_n Int32.(sub blocks_per_cycle 2l |> to_int) blk in + let operation = double_baking (B blk) blk_a.header blk_b.header in + (* We include the denunciation in the previous to last block of the + cycle. *) + let* (_ : Block.t) = Block.bake ~operation blk in + return_unit + +(** Check that an invalid double baking evidence that exposes two + block baking with same level made by different bakers fails. *) +let test_different_delegates () = + let open Lwt_result_syntax in + let* b, _contracts = Context.init2 () in + let* baker_1, baker_2 = Context.get_first_different_bakers (B b) in + let* blk_a = Block.bake ~policy:(By_account baker_1) b in + let* blk_b = Block.bake ~policy:(By_account baker_2) b in + double_baking (B blk_a) blk_a.header blk_b.header |> fun operation -> + let*! e = Block.bake ~operation blk_a in + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Invalid_double_baking_evidence _ -> true + | _ -> false) + +(** This test is supposed to mimic that a block cannot be baked by one baker and + signed by another. The way it tries to show this is by using a + Double_baking_evidence operation: + - say [baker_1] bakes block blk_a so blk_a has a header with baker_1's + signature + - say we create an artificial [header_b] for a block b' with timestamp [ts] + at the same level as [blk_a], and the header is created such that it says that + b' is baked by the same [baker_1] and signed by [baker_2] + - because [header_b] says that b' is baked by [baker_0], b' has the same + round as [blk_a], which together with the fact that b' and [blk_a] have the + same level, means that double_baking is valid: we have [blk_a] and b' at the + same level and round, but with different timestamps and signed by different + bakers. + This test fails with an error stating that block is signed by the wrong + baker. *) +let test_wrong_signer () = + let open Lwt_result_syntax in + let header_custom_signer baker baker_2 timestamp b = + let* header = + Block.Forge.forge_header ~policy:(By_account baker) ~timestamp b + in + Block.Forge.set_baker baker_2 header |> Block.Forge.sign_header + in + let* b, _contracts = Context.init2 () in + let* baker_1, baker_2 = Context.get_first_different_bakers (B b) in + let* blk_a = Block.bake ~policy:(By_account baker_1) b in + let ts = Timestamp.of_seconds_string (Int64.to_string 10L) in + match ts with + | None -> assert false + | Some ts -> + let* header_b = header_custom_signer baker_1 baker_2 ts b in + double_baking (B blk_a) blk_a.header header_b |> fun operation -> + let*! e = Block.bake ~operation blk_a in + Assert.proto_error_with_info ~loc:__LOC__ e "Invalid block signature" + +(** an evidence can only be accepted once (this also means that the + same evidence doesn't lead to slashing the offender twice) *) +let test_double_evidence () = + let open Lwt_result_syntax in + let* blk, (c1, c2, _c3) = Context.init3 ~consensus_threshold:0 () in + let* blk_a, blk_b = block_fork (c1, c2) blk in + let* blk = Block.bake_until_cycle_end blk_a in + double_baking (B blk) blk_a.header blk_b.header |> fun evidence -> + let*! e = Block.bake ~operations:[evidence; evidence] blk in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Conflicting_denunciation + {kind = Misbehaviour.Double_baking; _} -> + true + | _ -> false) + in + let* blk = Block.bake ~operation:evidence blk in + double_baking (B blk) blk_b.header blk_a.header |> fun evidence -> + let*! e = Block.bake ~operation:evidence blk in + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Already_denounced _ -> true + | _ -> false) + +let tests = + [ + Tztest.tztest + "valid double baking evidence" + `Quick + test_valid_double_baking_evidence; + Tztest.tztest + "payload producer receives the rewards for double baking evidence" + `Quick + test_payload_producer_gets_evidence_rewards; + (* Should fail*) + Tztest.tztest "same blocks" `Quick test_same_blocks; + Tztest.tztest "incorrect order" `Quick test_incorrect_order; + Tztest.tztest "different levels" `Quick test_different_levels; + Tztest.tztest + "too early double baking evidence" + `Quick + test_too_early_double_baking_evidence; + Tztest.tztest + "too late double baking evidence" + `Quick + test_too_late_double_baking_evidence; + Tztest.tztest + "just in time double baking evidence" + `Quick + test_just_in_time_double_baking_evidence; + Tztest.tztest "different delegates" `Quick test_different_delegates; + Tztest.tztest "wrong delegate" `Quick test_wrong_signer; + Tztest.tztest + "reject double injection of an evidence" + `Quick + test_double_evidence; + Tztest.tztest + "double baking followed by double attesting" + `Quick + test_valid_double_baking_followed_by_double_attesting; + Tztest.tztest + "double attesting followed by double baking" + `Quick + test_valid_double_attesting_followed_by_double_baking; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("double baking", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_preattestation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_preattestation.ml new file mode 100644 index 000000000000..c8509a16622b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_double_preattestation.ml @@ -0,0 +1,472 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (double preattestation) in Full_construction & Application modes + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_double_preattestation.ml + Subject: These tests target different cases for double preattestation *) + +open Protocol +open Alpha_context + +module type MODE = sig + val name : string + + val baking_mode : Block.baking_mode +end + +module BakeWithMode (Mode : MODE) : sig + val tests : unit Alcotest_lwt.test_case trace +end = struct + let name = Mode.name + + let bake = Block.bake ~baking_mode:Mode.baking_mode + + let bake_n = Block.bake_n ~baking_mode:Mode.baking_mode + + let bake_until_n_cycle_end = + Block.bake_until_n_cycle_end ~baking_mode:Mode.baking_mode + + (****************************************************************) + (* Utility functions *) + (****************************************************************) + + (** Helper function for illformed denunciations construction *) + + let pick_attesters ctxt = + let open Lwt_result_syntax in + let module V = Plugin.RPC.Validators in + let* validators_list = Context.get_attesters ctxt in + match validators_list with + | a :: b :: _ -> + return ((a.V.delegate, a.V.slots), (b.V.delegate, b.V.slots)) + | _ -> assert false + + let invalid_denunciation loc res = + Assert.proto_error ~loc res (function + | Validate_errors.Anonymous.Invalid_denunciation + Misbehaviour.Double_preattesting -> + true + | _ -> false) + + let malformed_double_preattestation_denunciation + ?(include_attestation = false) ?(block_round = 0) + ?(mk_evidence = fun ctxt p1 p2 -> Op.double_preattestation ctxt p1 p2) + ~loc () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init_n ~consensus_threshold:0 10 () in + let* b1 = bake genesis in + let* b2_A = bake ~policy:(By_round 0) b1 in + let* e = Op.attestation b1 in + let operations = if include_attestation then [e] else [] in + let* b2_B = bake ~policy:(By_round block_round) ~operations b1 in + let* op1 = Op.raw_preattestation b2_A in + let* op2 = Op.raw_preattestation b2_B in + let op = mk_evidence (B genesis) op1 op2 in + let*! res = bake b1 ~operations:[op] in + invalid_denunciation loc res + + let max_slashing_period () = + let open Lwt_result_syntax in + let* genesis, _contract = Context.init1 ~consensus_threshold:0 () in + let max_slashing_period = Constants.max_slashing_period in + let* {parametric = {blocks_per_cycle; _}; _} = + Context.get_constants (B genesis) + in + return (max_slashing_period * Int32.to_int blocks_per_cycle) + + let already_denounced loc res = + Assert.proto_error ~loc res (function + | Validate_errors.Anonymous.Already_denounced + {kind = Misbehaviour.Double_preattesting; _} -> + true + | _ -> false) + + let inconsistent_denunciation loc res = + Assert.proto_error ~loc res (function + | Validate_errors.Anonymous.Inconsistent_denunciation + {kind = Misbehaviour.Double_preattesting; _} -> + true + | _ -> false) + + let outdated_denunciation loc res = + Assert.proto_error ~loc res (function + | Validate_errors.Anonymous.Outdated_denunciation + {kind = Misbehaviour.Double_preattesting; _} -> + true + | _ -> false) + + let unexpected_failure loc res = + (* no error is expected *) + Assert.proto_error ~loc res (function _ -> false) + + let unexpected_success loc _ _ _ _ _ = + Alcotest.fail (loc ^ ": Test should not succeed") + + let expected_success _loc baker pred bbad d1 d2 = + let open Lwt_result_syntax in + (* same preattesters in case denunciation succeeds*) + let* () = Assert.equal_pkh ~loc:__LOC__ d1 d2 in + let* constants = Context.get_constants (B pred) in + let p = + constants.parametric + .percentage_of_frozen_deposits_slashed_per_double_attestation + in + (* let's bake the block on top of pred without denunciating d1 *) + let* bgood = bake ~policy:(By_account baker) pred in + (* Slashing hasn't happened yet. *) + let* bal_good = Context.Delegate.full_balance (B bgood) d1 in + let* bal_bad = Context.Delegate.full_balance (B bbad) d1 in + let* () = Assert.equal_tez ~loc:__LOC__ bal_good bal_bad in + (* Slashing happens at the end of the cycle. *) + let* bgood = bake_until_n_cycle_end ~policy:(By_account baker) 2 bgood in + let* bbad = bake_until_n_cycle_end ~policy:(By_account baker) 2 bbad in + (* Checking what the attester lost *) + let* frozen_deposit = + Context.Delegate.current_frozen_deposits (B pred) d1 + in + let* bal_good = Context.Delegate.full_balance (B bgood) d1 in + let* bal_bad = Context.Delegate.full_balance (B bbad) d1 in + (* the diff of the two balances in normal and in denunciation cases *) + let diff_end_bal = Test_tez.(bal_good -! bal_bad) in + (* amount lost due to denunciation *) + let Q.{num; den} = Percentage.to_q p in + let lost_deposit = + Test_tez.(frozen_deposit *! Z.to_int64 num /! Z.to_int64 den) + in + (* some of the lost deposits (depending on staking constants) will be earned by the baker *) + let divider = + Int64.add + 2L + (Int64.of_int + constants.parametric.adaptive_issuance + .global_limit_of_staking_over_baking) + in + let denun_reward = Test_tez.(lost_deposit /! divider) in + (* if the baker is the attester, he'll only loose half of the deposits *) + let expected_attester_loss = + if Signature.Public_key_hash.equal baker d1 then + Test_tez.(lost_deposit -! denun_reward) + else lost_deposit + in + let* () = + Assert.equal_tez ~loc:__LOC__ expected_attester_loss diff_end_bal + in + (* Checking what the baker earned (or lost) *) + let* bal_good = Context.Delegate.full_balance (B bgood) baker in + let* bal_bad = Context.Delegate.full_balance (B bbad) baker in + (* if baker = attester, the baker's balance in the good case is better, + because half of his deposits are burnt in the bad (double-preattestation) + situation. In case baker <> attester, bal_bad of the baker gets half of + burnt deposit of d1, so it's higher + *) + let high, low = + if Signature.Public_key_hash.equal baker d1 then (bal_good, bal_bad) + else (bal_bad, bal_good) + in + let diff_baker = Test_tez.(high -! low) in + (* the baker has either earnt or lost (in case baker = d1) half of burnt + attestation deposits *) + let* () = Assert.equal_tez ~loc:__LOC__ denun_reward diff_baker in + return_unit + + let order_preattestations ~correct_order op1 op2 = + let oph1 = Operation.hash op1 in + let oph2 = Operation.hash op2 in + let c = Operation_hash.compare oph1 oph2 in + if correct_order then if c < 0 then (op1, op2) else (op2, op1) + else if c < 0 then (op2, op1) + else (op1, op2) + + let adaptive_issuance = + { + Default_parameters.constants_test.adaptive_issuance with + autostaking_enable = false; + } + + let issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + } + + (** Helper function for denunciations inclusion *) + let generic_double_preattestation_denunciation ~nb_blocks_before_double + ~nb_blocks_before_denunciation + ?(test_expected_ok = + fun _loc _baker _pred _bbad _d1 _d2 -> Lwt_result_syntax.return_unit) + ?(test_expected_ko = fun _loc _res -> Lwt_result_syntax.return_unit) + ?(pick_attesters = + let open Lwt_result_syntax in + fun ctxt -> + let* a, _b = pick_attesters ctxt in + return (a, a)) ~loc () = + let open Lwt_result_syntax in + let* genesis, contracts = + Context.init_n + ~issuance_weights + ~adaptive_issuance + ~consensus_threshold:0 + ~consensus_committee_size:64 + 10 + () + in + let addr = + match List.hd contracts with None -> assert false | Some e -> e + in + (* bake `nb_blocks_before_double blocks` before double preattesting *) + let* blk = bake_n nb_blocks_before_double genesis in + (* producing two differents blocks and two preattestations op1 and op2 *) + let* trans = Op.transaction (B genesis) addr addr Tez.one_mutez in + let* head_A = bake ~policy:(By_round 0) blk in + let* head_B = bake ~policy:(By_round 0) blk ~operations:[trans] in + let* (d1, _slots1), (d2, _slots2) = pick_attesters (B head_A) in + (* default: d1 = d2 *) + let* op1 = Op.raw_preattestation ~delegate:d1 head_A in + let* op2 = Op.raw_preattestation ~delegate:d2 head_B in + let op1, op2 = order_preattestations ~correct_order:true op1 op2 in + (* bake `nb_blocks_before_denunciation` before double preattestation denunciation *) + let* blk = bake_n nb_blocks_before_denunciation blk in + let op : Operation.packed = Op.double_preattestation (B blk) op1 op2 in + let* baker = Context.get_baker (B blk) ~round:Round.zero in + let*! head_opt = bake ~policy:(By_account baker) blk ~operations:[op] in + match head_opt with + | Ok new_head -> + let* () = test_expected_ok loc baker blk new_head d1 d2 in + let op : Operation.packed = + Op.double_preattestation (B new_head) op2 op1 + in + let* () = + let*! block = + bake ~policy:(Excluding [d1; d2]) new_head ~operations:[op] + in + invalid_denunciation loc block + in + let op : Operation.packed = + Op.double_preattestation (B new_head) op1 op2 + in + let*! block = + bake ~policy:(Excluding [d1; d2]) new_head ~operations:[op] + in + already_denounced loc block + | Error _ as res -> test_expected_ko loc res + + (****************************************************************) + (* Tests *) + (****************************************************************) + + (** Preattesting two blocks that are structurally equal is not punished *) + let malformed_double_preattestation_denunciation_same_payload_hash_1 () = + malformed_double_preattestation_denunciation ~loc:__LOC__ () + + (** Preattesting two blocks that are structurally equal up to the attestations + they include is not punished *) + let malformed_double_preattestation_denunciation_same_payload_hash_2 () = + malformed_double_preattestation_denunciation + (* including an attestation in one of the blocks doesn't change its + payload hash *) + ~include_attestation:true + ~loc:__LOC__ + () + + (** Denunciation evidence cannot have the same operations *) + let malformed_double_preattestation_denunciation_same_preattestation () = + malformed_double_preattestation_denunciation + (* exactly the same preattestation operation => illformed *) + ~mk_evidence:(fun ctxt p1 _p2 -> Op.double_preattestation ctxt p1 p1) + ~loc:__LOC__ + () + + (** Preattesting two blocks with different rounds is not punished *) + let malformed_double_preattestation_denunciation_different_rounds () = + malformed_double_preattestation_denunciation ~loc:__LOC__ ~block_round:1 () + + (** Preattesting two blocks by two different validators is not punished *) + let malformed_double_preattestation_denunciation_different_validators () = + generic_double_preattestation_denunciation + ~nb_blocks_before_double:0 + ~nb_blocks_before_denunciation:2 + ~test_expected_ok:unexpected_success + ~test_expected_ko:inconsistent_denunciation + ~pick_attesters (* pick different attesters *) + ~loc:__LOC__ + () + + (** Attempt a denunciation of a double-pre in the first block after genesis *) + let double_preattestation_just_after_upgrade () = + generic_double_preattestation_denunciation + ~nb_blocks_before_double:0 + ~nb_blocks_before_denunciation:1 + ~test_expected_ok:expected_success + ~test_expected_ko:unexpected_failure + ~loc:__LOC__ + () + + (** Denunciation of double-pre at level L is injected at level L' = max_slashing_period. + The denunciation is outdated. *) + let double_preattestation_denunciation_during_slashing_period () = + let open Lwt_result_syntax in + let* max_slashing_period = max_slashing_period () in + generic_double_preattestation_denunciation + ~nb_blocks_before_double:0 + ~nb_blocks_before_denunciation:(max_slashing_period / 2) + ~test_expected_ok:expected_success + ~test_expected_ko:unexpected_failure + ~loc:__LOC__ + () + + (** Denunciation of double-pre at level L is injected 1 block after unfreeze + delay. Too late: denunciation is outdated. *) + let double_preattestation_denunciation_after_slashing_period () = + let open Lwt_result_syntax in + let* max_slashing_period = max_slashing_period () in + generic_double_preattestation_denunciation + ~nb_blocks_before_double:0 + ~nb_blocks_before_denunciation:(max_slashing_period + 1) + ~test_expected_ok:unexpected_success + ~test_expected_ko:outdated_denunciation + ~loc:__LOC__ + () + + let double_preattestation ctxt ?(correct_order = true) op1 op2 = + let e1, e2 = order_preattestations ~correct_order op1 op2 in + Op.double_preattestation ctxt e1 e2 + + let block_fork b = + let open Lwt_result_syntax in + let* baker_1, baker_2 = Context.get_first_different_bakers (B b) in + let* blk_a = Block.bake ~policy:(By_account baker_1) b in + let+ blk_b = Block.bake ~policy:(By_account baker_2) b in + (blk_a, blk_b) + + (** Injecting a valid double preattestation multiple time raises an error. *) + let test_two_double_preattestation_evidences_leads_to_duplicate_denunciation + () = + let open Lwt_result_syntax in + let* genesis, _contracts = + Context.init2 ~adaptive_issuance ~consensus_threshold:0 () + in + let* blk_1, blk_2 = block_fork genesis in + let* blk_a = Block.bake blk_1 in + let* blk_b = Block.bake blk_2 in + let* delegate, _ = Context.get_attester (B blk_a) in + let* preattestation_a = Op.raw_preattestation blk_a in + let* preattestation_b = Op.raw_preattestation blk_b in + let operation = + double_preattestation (B genesis) preattestation_a preattestation_b + in + let operation2 = + double_preattestation (B genesis) preattestation_b preattestation_a + in + let* bakers = Context.get_bakers (B blk_a) in + let baker = Context.get_first_different_baker delegate bakers in + let* (_full_balance : Tez.t) = + Context.Delegate.full_balance (B blk_a) baker + in + let*! e = + Block.bake + ~policy:(By_account baker) + ~operations:[operation; operation2] + blk_a + in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Conflicting_denunciation + {kind = Misbehaviour.Double_preattesting; _} -> + true + | _ -> false) + in + let* blk_with_evidence1 = + Block.bake ~policy:(By_account baker) ~operation blk_a + in + let*! e = + Block.bake ~policy:(By_account baker) ~operation blk_with_evidence1 + in + already_denounced __LOC__ e + + let my_tztest title test = + Tztest.tztest (Format.sprintf "%s: %s" name title) test + + let tests = + [ + (* illformed denunciations *) + my_tztest + "ko: malformed_double_preattestation_denunciation_same_payload_hash_1" + `Quick + malformed_double_preattestation_denunciation_same_payload_hash_1; + my_tztest + "ko: malformed_double_preattestation_denunciation_same_payload_hash_2" + `Quick + malformed_double_preattestation_denunciation_same_payload_hash_2; + my_tztest + "ko: malformed_double_preattestation_denunciation_different_rounds" + `Quick + malformed_double_preattestation_denunciation_different_rounds; + my_tztest + "ko: malformed_double_preattestation_denunciation_same_preattestation" + `Quick + malformed_double_preattestation_denunciation_same_preattestation; + my_tztest + "ko: malformed_double_preattestation_denunciation_different_validators" + `Quick + malformed_double_preattestation_denunciation_different_validators; + my_tztest + "double_preattestation_just_after_upgrade" + `Quick + double_preattestation_just_after_upgrade; + (* tests for unfreeze *) + my_tztest + "double_preattestation_denunciation_during_slashing_period" + `Quick + double_preattestation_denunciation_during_slashing_period; + my_tztest + "double_preattestation_denunciation_after_slashing_period" + `Quick + double_preattestation_denunciation_after_slashing_period; + my_tztest + "valid double preattestation injected multiple times" + `Quick + test_two_double_preattestation_evidences_leads_to_duplicate_denunciation; + ] +end + +let tests = + let module AppMode = BakeWithMode (struct + let name = "AppMode" + + let baking_mode = Block.Application + end) in + let module ConstrMode = BakeWithMode (struct + let name = "ConstrMode" + + let baking_mode = Block.Baking + end) in + AppMode.tests @ ConstrMode.tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("double preattestation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_frozen_deposits.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_frozen_deposits.ml new file mode 100644 index 000000000000..1098ef508d0f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_frozen_deposits.ml @@ -0,0 +1,1075 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (frozen_deposits) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_frozen_deposits.ml + Subject: consistency of frozen deposits and the [set_deposits_limit] operation + *) + +open Protocol +open Alpha_context +open Test_tez + +let constants = + { + Default_parameters.constants_test with + issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + }; + consensus_threshold = 0; + origination_size = 0; + } + +let get_first_2_accounts_contracts (a1, a2) = + ((a1, Context.Contract.pkh a1), (a2, Context.Contract.pkh a2)) + +(* Terminology: + + - staking balance = full balance + delegated stake; obtained with + Delegate.staking_balance + + - active stake = the amount of tez with which a delegate participates in + consensus; it must be greater than [minimal_stake] and less or equal the staking + balance; it is computed in [Delegate_sampler.select_distribution_for_cycle] + + - frozen deposits = represents frozen_deposits_percentage of the maximum stake during + consensus_rights_delay + max_slashing_period cycles; obtained with + Delegate.current_frozen_deposits + + - spendable balance = full balance - frozen deposits; obtained with Contract.balance + + - full balance = spendable balance + frozen deposits; obtained with Delegate.full_balance +*) +let test_invariants () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (contract2, _account2) = + get_first_2_accounts_contracts contracts + in + let* staking_balance = + Context.Delegate.staking_balance (B genesis) account1 + in + let* full_balance = Context.Delegate.full_balance (B genesis) account1 in + let* spendable_balance = Context.Contract.balance (B genesis) contract1 in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + (* before delegation *) + let* () = Assert.equal_tez ~loc:__LOC__ full_balance staking_balance in + let* () = + Assert.equal_tez + ~loc:__LOC__ + full_balance + Test_tez.(spendable_balance +! frozen_deposits) + in + (* to see how delegation plays a role, let's delegate to account1; + N.B. account2 represents a delegate so it cannot delegate to account1; this is + why we go through new_account as an intermediate *) + let* spendable_balance2 = Context.Contract.balance (B genesis) contract2 in + let new_account = (Account.new_account ()).pkh in + let new_contract = Contract.Implicit new_account in + (* we first put some money in new_account *) + let* transfer = + Op.transaction + ~force_reveal:true + (B genesis) + contract2 + new_contract + spendable_balance2 + in + let* b = Block.bake ~operation:transfer genesis in + let* new_account_balance = Context.Contract.balance (B b) new_contract in + let* () = + Assert.equal_tez ~loc:__LOC__ new_account_balance spendable_balance2 + in + let* delegation = + Op.delegation ~force_reveal:true (B b) new_contract (Some account1) + in + let* b1 = Block.bake ~operation:delegation b in + let* b2 = Block.bake_until_cycle_end b1 in + let* new_staking_balance = Context.Delegate.staking_balance (B b2) account1 in + let* new_full_balance = Context.Delegate.full_balance (B b2) account1 in + let* new_spendable_balance = Context.Contract.balance (B b2) contract1 in + let* new_frozen_deposits = + Context.Delegate.current_frozen_deposits (B b2) account1 + in + (* after delegation, we see the delegated stake reflected in the new staking + balance of account1 *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + Test_tez.(new_full_balance +! new_account_balance) + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_full_balance + Test_tez.(new_spendable_balance +! new_frozen_deposits) + in + let expected_new_frozen_deposits = + Test_tez.( + (* in this particular example, if we follow the calculation of the active + stake, it is precisely the new_staking_balance *) + new_staking_balance + /! Int64.of_int (constants.limit_of_delegation_over_baking + 1)) + in + Assert.equal_tez ~loc:__LOC__ new_frozen_deposits expected_new_frozen_deposits + +let adjust_staking_towards_limit ~limit ~block ~account ~contract = + let open Lwt_result_syntax in + (* Since we do not have the set_deposit_limit operation anymore (nor + do we have automatic staking) this function adjusts the amount of + staking towards the given [limit] for the given [account], + [contract]. It takes a block and returns a new block if a stake + or unstake operation is necessary, or the same block if the limit + was already reached. *) + let* fd = Context.Delegate.current_frozen_deposits (B block) account in + if limit = fd then return block + else + match Tez.sub_opt limit fd with + | Some diff -> + let* adjustment_operation = + Adaptive_issuance_helpers.stake (B block) contract diff + in + Block.bake ~operation:adjustment_operation block + | None -> ( + match Tez.sub_opt fd limit with + | None -> return block + | Some diff -> + let* adjustment_operation = + Adaptive_issuance_helpers.unstake (B block) contract diff + in + Block.bake ~operation:adjustment_operation block) + +let test_limit_with_overdelegation () = + let open Lwt_result_syntax in + let constants = + { + constants with + adaptive_issuance = + { + Default_parameters.constants_test.adaptive_issuance with + autostaking_enable = false; + }; + limit_of_delegation_over_baking = 9; + } + in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (contract2, account2) = + get_first_2_accounts_contracts contracts + in + (* - [account1] and [account2] will give 80% of their balance to + [new_account] + - [new_account] will overdelegate to [account1] but [account1] will apply + a frozen deposits target and limit to 15% of its stake *) + let* initial_staking_balance = + Context.Delegate.staking_balance (B genesis) account1 + in + let* initial_staking_balance' = + Context.Delegate.staking_balance (B genesis) account2 + in + let amount = Test_tez.(initial_staking_balance *! 8L /! 10L) in + let amount' = Test_tez.(initial_staking_balance' *! 8L /! 10L) in + let limit = Test_tez.(initial_staking_balance *! 15L /! 100L) in + let new_account = (Account.new_account ()).pkh in + let new_contract = Contract.Implicit new_account in + let* transfer1 = + Op.transaction ~force_reveal:true (B genesis) contract1 new_contract amount + in + let* transfer2 = + Op.transaction ~force_reveal:true (B genesis) contract2 new_contract amount' + in + let* b = Block.bake ~operations:[transfer1; transfer2] genesis in + let expected_new_staking_balance = + Test_tez.(initial_staking_balance -! amount) + in + let* new_staking_balance = Context.Delegate.staking_balance (B b) account1 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + expected_new_staking_balance + in + let expected_new_staking_balance' = + Test_tez.(initial_staking_balance' -! amount') + in + let* new_staking_balance' = Context.Delegate.staking_balance (B b) account2 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance' + expected_new_staking_balance' + in + let* delegation = + Op.delegation ~force_reveal:true (B b) new_contract (Some account1) + in + let* b = Block.bake ~operation:delegation b in + (* Overdelegation means that now there isn't enough staking, and the + baker who wants to have its stake close to its defined limit + should adjust it. *) + let* b = + adjust_staking_towards_limit + ~block:b + ~account:account1 + ~contract:contract1 + ~limit + in + let expected_new_frozen_deposits = limit in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez ~loc:__LOC__ frozen_deposits expected_new_frozen_deposits + in + let cycles_to_bake = + 2 * (constants.consensus_rights_delay + Constants.max_slashing_period) + in + let rec loop b n = + if n = 0 then return b + else + let* b = Block.bake_until_cycle_end ~policy:(By_account account1) b in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits + expected_new_frozen_deposits + in + loop b (pred n) + in + (* Check that frozen deposits do not change for a sufficient period of + time *) + let* (_ : Block.t) = loop b cycles_to_bake in + return_unit + +let test_may_not_bake_again_after_full_deposit_slash () = + let open Lwt_result_syntax in + let order_ops op1 op2 = + let oph1 = Operation.hash op1 in + let oph2 = Operation.hash op2 in + let c = Operation_hash.compare oph1 oph2 in + if c < 0 then (op1, op2) else (op2, op1) + in + let* genesis, contracts = Context.init_with_constants2 constants in + let (good_contract, good_account), (slashed_contract, slashed_account) = + get_first_2_accounts_contracts contracts + in + let* operation = + Op.transaction + (B genesis) + good_contract + slashed_contract + Alpha_context.Tez.one_cent + in + let* blk_a = + Block.bake ~policy:(By_account slashed_account) ~operation genesis + in + let* blk_b = Block.bake ~policy:(By_account slashed_account) genesis in + let* preattestation1 = + Op.raw_preattestation ~delegate:slashed_account blk_a + in + let* preattestation2 = + Op.raw_preattestation ~delegate:slashed_account blk_b + in + let preattestation1, preattestation2 = + order_ops preattestation1 preattestation2 + in + let double_preattestation_op = + Op.double_preattestation (B blk_a) preattestation1 preattestation2 + in + let* b = + Block.bake + ~policy:(By_account good_account) + ~operation:double_preattestation_op + blk_a + in + let* fd_before = + Context.Delegate.current_frozen_deposits (B b) slashed_account + in + let* operation = + Op.transaction + (B b) + good_contract + slashed_contract + Alpha_context.Tez.one_cent + in + let* blk_a = Block.bake ~policy:(By_account slashed_account) ~operation b in + let* blk_b = Block.bake ~policy:(By_account slashed_account) b in + let* attestation1 = Op.raw_attestation ~delegate:slashed_account blk_a in + let* attestation2 = Op.raw_attestation ~delegate:slashed_account blk_b in + let attestation1, attestation2 = order_ops attestation1 attestation2 in + let double_attestation_op = + Op.double_attestation (B blk_a) attestation1 attestation2 + in + let* b = + Block.bake + ~policy:(By_account good_account) + ~operation:double_attestation_op + b + in + (* The [slashed_account]'s deposits haven't changed yet... *) + let* fd = Context.Delegate.current_frozen_deposits (B b) slashed_account in + let* () = Assert.equal_tez ~loc:__LOC__ fd fd_before in + (* ...though we are immediately not allowed to bake with [slashed_account] *) + let*! res = Block.bake ~policy:(By_account slashed_account) b in + let* () = + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Consensus.Forbidden_delegate _ -> true + | _ -> false) + in + let* b, metadata, _ = + Block.bake_until_cycle_end_with_metadata ~policy:(By_account good_account) b + in + (* Assert that the [slashed_account]'s deposits are increased by autostaking. *) + let metadata = Option.value_f ~default:(fun () -> assert false) metadata in + let autostaked = Block.autostaked slashed_account metadata in + let* fd = Context.Delegate.current_frozen_deposits (B b) slashed_account in + let* () = Assert.equal_tez ~loc:__LOC__ fd autostaked in + (* Though [slashed_account] is still forbidden for two more cycles. *) + let*! res = Block.bake ~policy:(By_account slashed_account) b in + let* () = + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Consensus.Forbidden_delegate _ -> true + | _ -> false) + in + let* b = Block.bake_until_n_cycle_end 2 ~policy:(By_account good_account) b in + (* Check that [slashed_account] can bake since it's a new cycle and + autostake increased the frozen deposits enough to bake. *) + let* (_ : Block.t) = Block.bake ~policy:(By_account slashed_account) b in + return_unit + +let test_set_limit balance_percentage () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (_contract2, account2) = + get_first_2_accounts_contracts contracts + in + let* () = + let* res = Context.Delegate.frozen_deposits_limit (B genesis) account1 in + match res with + | Some _ -> Alcotest.fail "unexpected deposits limit" + | None -> return_unit + in + (* Test deposit consistency before and after first cycle *) + let* full_balance = Context.Delegate.full_balance (B genesis) account1 in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + let expected_deposits = + full_balance /! Int64.of_int (constants.limit_of_delegation_over_baking + 1) + in + let* () = Assert.equal_tez ~loc:__LOC__ frozen_deposits expected_deposits in + (* Bake until end of first cycle *) + let* b = Block.bake_until_cycle_end genesis in + let* full_balance = Context.Delegate.full_balance (B genesis) account1 in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + let expected_deposits = + full_balance /! Int64.of_int (constants.limit_of_delegation_over_baking + 1) + in + let* () = Assert.equal_tez ~loc:__LOC__ frozen_deposits expected_deposits in + (* set deposits limit to balance_percentage out of the balance *) + let limit = + Test_tez.(full_balance *! Int64.of_int balance_percentage /! 100L) + in + let* operation = Op.set_deposits_limit (B genesis) contract1 (Some limit) in + let* b = Block.bake ~policy:(By_account account2) ~operation b in + let* () = + let* frozen_deposits_limit = + Context.Delegate.frozen_deposits_limit (B b) account1 + in + match frozen_deposits_limit with + | Some set_limit -> Assert.equal_tez ~loc:__LOC__ set_limit limit + | None -> Alcotest.fail "unexpected absence of deposits limit" + in + (* the frozen deposits limit affects the active stake at cycle end. *) + let* b = Block.bake_until_cycle_end ~policy:(By_account account2) b in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + Assert.equal_tez ~loc:__LOC__ frozen_deposits limit + +let test_unset_limit () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (_contract2, account2) = + get_first_2_accounts_contracts contracts + in + (* set the limit to 0 *) + let* operation = + Op.set_deposits_limit (B genesis) contract1 (Some Tez.zero) + in + let* b = Block.bake ~policy:(By_account account2) ~operation genesis in + let* () = + let* frozen_deposits_limit = + Context.Delegate.frozen_deposits_limit (B b) account1 + in + match frozen_deposits_limit with + | Some set_limit -> Assert.equal_tez ~loc:__LOC__ set_limit Tez.zero + | None -> Alcotest.fail "unexpected absence of deposits limit" + in + let* b = Block.bake_until_cycle_end ~policy:(By_account account2) b in + let* frozen_deposits_at_b = + Context.Delegate.current_frozen_deposits (B b) account1 + in + (* after cycle end, the 0 limit is reflected in the deposit which becomes 0 + itself *) + let* () = Assert.equal_tez ~loc:__LOC__ frozen_deposits_at_b Tez.zero in + (* unset the 0 limit *) + let* operation = Op.set_deposits_limit (B b) contract1 None in + let* b = Block.bake ~policy:(By_account account2) ~operation b in + let* () = + let* frozen_deposits_limit = + Context.Delegate.frozen_deposits_limit (B b) account1 + in + match frozen_deposits_limit with + | Some _ -> Alcotest.fail "unexpected deposits limit" + | None -> return_unit + in + (* removing the 0 limit is visible once the cycle ends *) + let* bfin = Block.bake_until_cycle_end ~policy:(By_account account2) b in + let* frozen_deposits_at_bfin = + Context.Delegate.current_frozen_deposits (B bfin) account1 + in + (* without a limit and with autostaking staking, the new deposit is no more + zero; note that account1 hasn't baked any block. *) + let* () = + Assert.not_equal_tez ~loc:__LOC__ frozen_deposits_at_bfin Tez.zero + in + return_unit + +let test_cannot_bake_with_zero_deposits_limit () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (_contract2, account2) = + get_first_2_accounts_contracts contracts + in + (* N.B. there is no non-zero frozen deposits value for which one cannot bake: + even with a small deposit one can still bake, though with a smaller probability + (because the frozen deposits value impacts the active stake and the active + stake is the one used to determine baking/endorsing rights. *) + let* operation = + Op.set_deposits_limit (B genesis) contract1 (Some Tez.zero) + in + let* b = Block.bake ~policy:(By_account account2) ~operation genesis in + (* autostaking happens before staking right computations, + so the limit will apply in constants.consensus_rights_delay+1 *) + let expected_number_of_cycles_with_rights_from_previous_deposit = + constants.consensus_rights_delay + in + let* b = + Block.bake_until_n_cycle_end + ~policy:(By_account account2) + expected_number_of_cycles_with_rights_from_previous_deposit + b + in + (* by now, the frozen deposits of account1 are 0 but it still has slashable + unstaked frozen deposits so it can still bake. *) + let* fd = Context.Delegate.current_frozen_deposits (B b) account1 in + let* () = Assert.equal_tez ~loc:__LOC__ fd Tez.zero in + let* ufd = + Context.Contract.unstaked_frozen_balance (B b) (Implicit account1) + in + let ufd = Option.value_f ufd ~default:(fun () -> assert false) in + let* () = Assert.not_equal_tez ~loc:__LOC__ ufd Tez.zero in + let* (_ : Block.t) = Block.bake ~policy:(By_account account1) b in + let* b = Block.bake_until_cycle_end ~policy:(By_account account2) b in + (* after one cycle is passed, the frozen deposit window has passed + and the baker should now effectively have no baking rights. *) + let* fd = Context.Delegate.current_frozen_deposits (B b) account1 in + let* () = Assert.equal_tez ~loc:__LOC__ fd Tez.zero in + let*! b1 = Block.bake ~policy:(By_account account1) b in + let* () = + Assert.error ~loc:__LOC__ b1 (function + | Block.No_slots_found_for _ -> true + | _ -> false) + in + (* Unstaked frozen deposits are released two cycles later. *) + let* b = Block.bake_until_n_cycle_end 2 b in + let* ufd = + Context.Contract.unstaked_frozen_balance (B b) (Implicit account1) + in + let ufd = Option.value_f ufd ~default:(fun () -> assert false) in + Assert.equal_tez ~loc:__LOC__ ufd Tez.zero + +let test_deposits_after_stake_removal () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (contract2, account2) = + get_first_2_accounts_contracts contracts + in + let* initial_frozen_deposits_1 = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + let* initial_frozen_deposits_2 = + Context.Delegate.current_frozen_deposits (B genesis) account2 + in + (* Move half the account1's balance to account2 *) + let* full_balance = Context.Delegate.full_balance (B genesis) account1 in + let half_balance = Test_tez.(full_balance /! 2L) in + let* operation = + Op.transaction (B genesis) contract1 contract2 half_balance + in + let* b = Block.bake ~operation genesis in + let* frozen_deposits_1 = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez ~loc:__LOC__ frozen_deposits_1 initial_frozen_deposits_1 + in + let* frozen_deposits_2 = + Context.Delegate.current_frozen_deposits (B b) account2 + in + let* () = + Assert.equal_tez ~loc:__LOC__ frozen_deposits_2 initial_frozen_deposits_2 + in + (* Bake a cycle. *) + let expected_new_frozen_deposits_2 = + Test_tez.(initial_frozen_deposits_2 *! 3L /! 2L) + in + let* b = Block.bake_until_cycle_end b in + let* frozen_deposits_2 = + Context.Delegate.current_frozen_deposits (B b) account2 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_2 + expected_new_frozen_deposits_2 + in + (* Updating initial_frozen_deposits_x of accountx after autostaking *) + let* initial_frozen_deposits_1 = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* initial_frozen_deposits_2 = + Context.Delegate.current_frozen_deposits (B b) account2 + in + (* Frozen deposits aren't affected by balance change... *) + let rec loop b n = + if n = 0 then return b + else + let* frozen_deposits_1 = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_1 + initial_frozen_deposits_1 + in + let* frozen_deposits_2 = + Context.Delegate.current_frozen_deposits (B b) account2 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits_2 + initial_frozen_deposits_2 + in + let* b, _, _ = Block.bake_until_cycle_end_with_metadata b in + loop b (pred n) + in + (* the frozen deposits for account1 do not change until [preserved cycles + + max_slashing_period] are baked (-1 because we already baked a cycle) *) + let* b = + loop b (constants.consensus_rights_delay + Constants.max_slashing_period - 1) + in + (* and still after preserved cycles + max_slashing_period, the frozen_deposits + for account1 won't reflect the decrease in account1's active stake + without manual staking. *) + let* frozen_deposits_1 = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez ~loc:__LOC__ frozen_deposits_1 initial_frozen_deposits_1 + in + (* similarly account2's frozen deposits aren't increased automatically *) + let* frozen_deposits_2 = + Context.Delegate.current_frozen_deposits (B b) account2 + in + Assert.equal_tez ~loc:__LOC__ frozen_deposits_2 initial_frozen_deposits_2 + +let test_deposits_unfrozen_after_deactivation () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (_contract1, account1), (_contract2, account2) = + get_first_2_accounts_contracts contracts + in + let* initial_frozen_deposits = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + (* [account1] will not participate (ie bake/attest); we set the + expected last cycles at which it is considered active and at + which it has non-zero deposits *) + let last_active_cycle = + 1 + (2 * constants.consensus_rights_delay) + (* according to [Delegate_storage.set_active] *) + in + let last_cycle_with_deposits = + last_active_cycle + constants.consensus_rights_delay + + Constants.max_slashing_period + (* according to [Delegate_storage.freeze_deposits] *) + in + let cycles_to_bake = + last_cycle_with_deposits + constants.consensus_rights_delay + in + let rec loop b n = + if n = 0 then return b + else + let* ai_activation_cycle = + Context.get_adaptive_issuance_launch_cycle (B b) + in + let frozen_deposits_when_deactivated = + match ai_activation_cycle with + | None -> Tez.zero + | Some cycle -> + if Cycle.(cycle > add root last_active_cycle) then Tez.zero + else initial_frozen_deposits + in + let* b = Block.bake_until_cycle_end ~policy:(By_account account2) b in + let* is_deactivated = Context.Delegate.deactivated (B b) account1 in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let new_cycle = cycles_to_bake - n + 1 in + let* () = + Assert.equal_bool + ~loc:__LOC__ + is_deactivated + (new_cycle > last_active_cycle) + in + (* deposits are automatically unfrozen for deactivated delegates only *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits + (if is_deactivated then frozen_deposits_when_deactivated + else initial_frozen_deposits) + in + loop b (pred n) + in + let* (_ : Block.t) = loop genesis cycles_to_bake in + return_unit + +let test_frozen_deposits_with_delegation () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (_contract1, account1), (contract2, account2) = + get_first_2_accounts_contracts contracts + in + let* initial_staking_balance = + Context.Delegate.staking_balance (B genesis) account1 + in + let* initial_frozen_deposits = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + let* delegated_amount = Context.Contract.balance (B genesis) contract2 in + let new_account = Account.new_account () in + let new_contract = Contract.Implicit new_account.pkh in + let* transfer = + Op.transaction + ~force_reveal:true + (B genesis) + contract2 + new_contract + delegated_amount + in + let* b = Block.bake ~operation:transfer genesis in + let* new_staking_balance = Context.Delegate.staking_balance (B b) account2 in + let expected_new_staking_balance = + Test_tez.(initial_staking_balance -! delegated_amount) + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + expected_new_staking_balance + in + let* delegation = + Op.delegation ~force_reveal:true (B b) new_contract (Some account1) + in + let* b = Block.bake ~operation:delegation b in + let expected_new_staking_balance = + Test_tez.(initial_staking_balance +! delegated_amount) + in + let* new_staking_balance = Context.Delegate.staking_balance (B b) account1 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + expected_new_staking_balance + in + (* Bake one cycle. *) + let* b = Block.bake_until_cycle_end b in + let expected_new_frozen_deposits = + Test_tez.( + initial_frozen_deposits + +! delegated_amount + /! Int64.of_int (constants.limit_of_delegation_over_baking + 1)) + in + let* new_frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_frozen_deposits + expected_new_frozen_deposits + in + let cycles_to_bake = + 2 * (constants.consensus_rights_delay + Constants.max_slashing_period) + in + let rec loop b n = + if n = 0 then return b + else + let* b = Block.bake_until_cycle_end ~policy:(By_account account1) b in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits + expected_new_frozen_deposits + in + loop b (pred n) + in + (* Check that frozen deposits do not change for a sufficient period of + time *) + let* (_ : Block.t) = loop b cycles_to_bake in + return_unit + +let test_frozen_deposits_with_overdelegation () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (contract2, account2) = + get_first_2_accounts_contracts contracts + in + (* - [account1] and [account2] give their spendable balance to [new_account] + - [new_account] overdelegates to [account1] *) + let* initial_staking_balance = + Context.Delegate.staking_balance (B genesis) account1 + in + let* initial_staking_balance' = + Context.Delegate.staking_balance (B genesis) account2 + in + let* initial_frozen_deposits = + Context.Delegate.current_frozen_deposits (B genesis) account1 + in + let* amount = Context.Contract.balance (B genesis) contract1 in + let* amount' = Context.Contract.balance (B genesis) contract2 in + let new_account = (Account.new_account ()).pkh in + let new_contract = Contract.Implicit new_account in + let* transfer1 = + Op.transaction ~force_reveal:true (B genesis) contract1 new_contract amount + in + let* transfer2 = + Op.transaction ~force_reveal:true (B genesis) contract2 new_contract amount' + in + let* b = Block.bake ~operations:[transfer1; transfer2] genesis in + let expected_new_staking_balance = + Test_tez.(initial_staking_balance -! amount) + in + let* new_staking_balance = Context.Delegate.staking_balance (B b) account1 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + expected_new_staking_balance + in + let expected_new_staking_balance' = + Test_tez.(initial_staking_balance' -! amount') + in + let* new_staking_balance' = Context.Delegate.staking_balance (B b) account2 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance' + expected_new_staking_balance' + in + let* delegation = + Op.delegation ~force_reveal:true (B b) new_contract (Some account1) + in + let* b = Block.bake ~operation:delegation b in + let* new_staking_balance = Context.Delegate.staking_balance (B b) account1 in + let expected_new_staking_balance = + Test_tez.(initial_frozen_deposits +! amount +! amount') + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + expected_new_staking_balance + in + (* Finish the cycle to update the frozen deposits *) + let* b = Block.bake_until_cycle_end b in + let* expected_new_frozen_deposits = + Context.Delegate.full_balance (B b) account1 + in + (* the equality follows from the definition of active stake in + [Delegate_sampler.select_distribution_for_cycle]. *) + assert (initial_frozen_deposits = expected_new_frozen_deposits) ; + let* new_frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_frozen_deposits + expected_new_frozen_deposits + in + let cycles_to_bake = + 2 * (constants.consensus_rights_delay + Constants.max_slashing_period) + in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez ~loc:__LOC__ frozen_deposits expected_new_frozen_deposits + in + let rec loop b n = + if n = 0 then return b + else + let* b = Block.bake_until_cycle_end ~policy:(By_account account1) b in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits + expected_new_frozen_deposits + in + loop b (pred n) + in + (* Check that frozen deposits do not change for a sufficient period of + time *) + let* (_ : Block.t) = loop b cycles_to_bake in + return_unit + +let test_set_limit_with_overdelegation () = + let open Lwt_result_syntax in + let constants = {constants with limit_of_delegation_over_baking = 9} in + let* genesis, contracts = Context.init_with_constants2 constants in + let (contract1, account1), (contract2, account2) = + get_first_2_accounts_contracts contracts + in + (* - [account1] and [account2] will give 80% of their balance to + [new_account] + - [new_account] will overdelegate to [account1] and [account1] will set + its frozen deposits limit to 15% of its stake *) + let* initial_staking_balance = + Context.Delegate.staking_balance (B genesis) account1 + in + let* initial_staking_balance' = + Context.Delegate.staking_balance (B genesis) account2 + in + let amount = Test_tez.(initial_staking_balance *! 8L /! 10L) in + let amount' = Test_tez.(initial_staking_balance' *! 8L /! 10L) in + let limit = Test_tez.(initial_staking_balance *! 15L /! 100L) in + let new_account = (Account.new_account ()).pkh in + let new_contract = Contract.Implicit new_account in + let* transfer1 = + Op.transaction ~force_reveal:true (B genesis) contract1 new_contract amount + in + let* transfer2 = + Op.transaction ~force_reveal:true (B genesis) contract2 new_contract amount' + in + let* b = Block.bake ~operations:[transfer1; transfer2] genesis in + let* set_deposits = Op.set_deposits_limit (B b) contract1 (Some limit) in + let* b = Block.bake ~operation:set_deposits b in + let expected_new_staking_balance = + Test_tez.(initial_staking_balance -! amount) + in + let* new_staking_balance = Context.Delegate.staking_balance (B b) account1 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance + expected_new_staking_balance + in + let expected_new_staking_balance' = + Test_tez.(initial_staking_balance' -! amount') + in + let* new_staking_balance' = Context.Delegate.staking_balance (B b) account2 in + let* () = + Assert.equal_tez + ~loc:__LOC__ + new_staking_balance' + expected_new_staking_balance' + in + let* delegation = + Op.delegation ~force_reveal:true (B b) new_contract (Some account1) + in + let* b = Block.bake ~operation:delegation b in + (* Finish the cycle. account1's frozen deposits are increased + automatically. *) + let* b = Block.bake_until_cycle_end b in + let expected_new_frozen_deposits = limit in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez ~loc:__LOC__ frozen_deposits expected_new_frozen_deposits + in + let cycles_to_bake = + 2 * (constants.consensus_rights_delay + Constants.max_slashing_period) + in + let rec loop b n = + if n = 0 then return b + else + let* b = Block.bake_until_cycle_end ~policy:(By_account account1) b in + let* frozen_deposits = + Context.Delegate.current_frozen_deposits (B b) account1 + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + frozen_deposits + expected_new_frozen_deposits + in + loop b (pred n) + in + (* Check that frozen deposits do not change for a sufficient period of + time *) + let* (_b : Block.t) = loop b cycles_to_bake in + return_unit + +(** This test fails when [to_cycle] in [Delegate.freeze_deposits] is smaller than + [new_cycle + consensus_rights_delay]. *) +let test_error_is_thrown_when_smaller_upper_bound_for_frozen_window () = + let open Lwt_result_syntax in + let* genesis, contracts = Context.init_with_constants2 constants in + let contract1, contract2 = contracts in + let account1 = Context.Contract.pkh contract1 in + (* [account2] delegates (through [new_account]) to [account1] its spendable + balance. The point is to make [account1] have a lot of staking balance so + that, after [consensus_rights_delay] when the active stake reflects this increase + in staking balance, its [maximum_stake_to_be_deposited] is bigger than the frozen + deposit which is computed on a smaller window because [to_cycle] is smaller + than [new_cycle + consensus_rights_delay]. *) + let* delegated_amount = Context.Contract.balance (B genesis) contract2 in + let new_account = Account.new_account () in + let new_contract = Contract.Implicit new_account.pkh in + let* transfer = + Op.transaction + ~force_reveal:true + (B genesis) + contract2 + new_contract + delegated_amount + in + let* b = Block.bake ~operation:transfer genesis in + let* delegation = + Op.delegation ~force_reveal:true (B b) new_contract (Some account1) + in + let* b = Block.bake ~operation:delegation b in + let* b = Block.bake_until_cycle_end b in + (* After 1 cycle, namely, at cycle 2, [account1] transfers all its spendable + balance. *) + let* balance1 = Context.Contract.balance (B b) contract1 in + let* operation = + Op.transaction ~force_reveal:true (B b) contract1 contract2 balance1 + in + let* b = Block.bake ~operation b in + let* (_ : Block.t) = + Block.bake_until_n_cycle_end constants.consensus_rights_delay b + in + (* By this time, after [consensus_rights_delay] passed after [account1] has emptied + its spendable balance, because [account1] had a big staking balance at + cycle 0, at this cycle it has a big active stake, and so its + [maximum_stake_to_be_deposited] too is bigger than [frozen_deposits.current_amount], + so the variable [to_freeze] in [freeze_deposits] is positive. + Because the spendable balance of [account1] is 0, an error "Underflowing + subtraction" is raised at the end of the cycle when updating the balance by + subtracting [to_freeze] in [freeze_deposits]. + Note that by taking [to_cycle] is [new_cycle + consensus_rights_delay], + [frozen_deposits.current_amount] can no longer be smaller + than [maximum_stake_to_be_deposited], that is, the invariant + maximum_stake_to_be_deposited <= frozen_deposits + balance is preserved. + *) + return_unit + +let tests = + Tztest. + [ + tztest "invariants" `Quick test_invariants; + tztest "set deposits limit to 0%" `Quick (test_set_limit 0); + tztest "set deposits limit to 5%" `Quick (test_set_limit 5); + tztest "unset deposits limit" `Quick test_unset_limit; + tztest + "cannot bake with zero deposits limit" + `Quick + test_cannot_bake_with_zero_deposits_limit; + tztest + "deposits after stake removal" + `Quick + test_deposits_after_stake_removal; + tztest + "deposits are unfrozen after deactivation" + `Quick + test_deposits_unfrozen_after_deactivation; + tztest + "frozen deposits with delegation" + `Quick + test_frozen_deposits_with_delegation; + tztest + "test simulation of limited staking with overdelegation" + `Quick + test_limit_with_overdelegation; + (* This test has been deactivated following the changes of the + forbidding mechanism that now forbids delegates right after + the first denunciation, it should be fixed and reactivated + https://gitlab.com/tezos/tezos/-/issues/6904 *) + (* tztest *) + (* "test cannot bake again after full deposit slash" *) + (* `Quick *) + (* test_may_not_bake_again_after_full_deposit_slash; *) + tztest + "frozen deposits with overdelegation" + `Quick + test_frozen_deposits_with_overdelegation; + tztest + "set limit with overdelegation" + `Quick + test_set_limit_with_overdelegation; + tztest + "error is thrown when the frozen window is smaller" + `Quick + test_error_is_thrown_when_smaller_upper_bound_for_frozen_window; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("frozen deposits", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_helpers_rpcs.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_helpers_rpcs.ml new file mode 100644 index 000000000000..ba1b2e0e530b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_helpers_rpcs.ml @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Helpers RPCs) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_helpers_rpcs.ml + Subject: On RPCs. +*) + +(* Test the baking_rights RPC. + Future levels or cycles are not tested because it's hard in this framework, + using only RPCs, to fabricate them. *) +let test_baking_rights () = + let open Lwt_result_syntax in + let* b, (c1, _c2) = Context.init2 () in + let open Plugin.RPC.Baking_rights in + (* default max_round returns 65 results *) + let* rights = get Block.rpc_ctxt b ~all:true in + assert (Compare.List_length_with.(rights = 65)) ; + (* arbitrary max_round *) + let max_round = 15 in + let* rights = get Block.rpc_ctxt b ~all:true ~max_round in + assert (Compare.List_length_with.(rights = max_round + 1)) ; + (* filtering by delegate *) + let d = Context.Contract.pkh c1 in + let* rights = get Block.rpc_ctxt b ~all:true ~delegates:[d] in + assert (List.for_all (fun {delegate; _} -> delegate = d) rights) ; + (* filtering by cycle *) + let* {cycle; _} = Plugin.RPC.current_level Block.rpc_ctxt b in + let* rights = get Block.rpc_ctxt b ~all:true ~cycle in + let* first, last = Plugin.RPC.levels_in_current_cycle Block.rpc_ctxt b in + assert ( + List.for_all (fun {level; _} -> level >= first && level <= last) rights) ; + (* filtering by level *) + let* {level; _} = Plugin.RPC.current_level Block.rpc_ctxt b in + let* rights = get Block.rpc_ctxt b ~all:true ~levels:[level] in + let expected_level = level in + assert (List.for_all (fun {level; _} -> level = expected_level) rights) ; + return_unit + +let tests = [Tztest.tztest "baking_rights" `Quick test_baking_rights] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("helpers rpcs", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_participation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_participation.ml new file mode 100644 index 000000000000..1c3ec534abcf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_participation.ml @@ -0,0 +1,250 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (participation monitoring) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_participation.ml + Subject: Participation monitoring in Tenderbake +*) + +open Protocol +open Alpha_context + +(** [baker] bakes and [attester] attests *) +let bake_and_attest_once (_b_pred, b_cur) baker attester = + let open Lwt_result_wrap_syntax in + let open Context in + let* attesters_list = Context.get_attesters (B b_cur) in + List.find_map + (function + | {Plugin.RPC.Validators.delegate; slots; _} -> + if Signature.Public_key_hash.equal delegate attester then + Some (delegate, slots) + else None) + attesters_list + |> function + | None -> assert false + | Some (delegate, _slots) -> + let*?@ round = Block.get_round b_cur in + let* attestation = Op.attestation ~round ~delegate b_cur in + Block.bake_with_metadata + ~policy:(By_account baker) + ~operation:attestation + b_cur + +(** We test that: + - a delegate that participates enough, gets its attesting rewards at the end of the cycle, + - a delegate that does not participating enough during a cycle, doesn't get rewarded. + + The case distinction is made by the boolean argument [sufficient_participation]. + If [sufficient_participation] is true, + then a validator attests for as long as the minimal required activity is not reached, + otherwise it does not attest. + Finally, we check the validator's balance at the end of the cycle. +*) +let test_participation ~sufficient_participation () = + let open Lwt_result_wrap_syntax in + let n_accounts = 2 in + let* b0, accounts = Context.init_n ~consensus_threshold:1 n_accounts () in + let* csts = Context.get_constants (B b0) in + let blocks_per_cycle = Int32.to_int csts.parametric.blocks_per_cycle in + let mpr = csts.parametric.minimal_participation_ratio in + assert (blocks_per_cycle mod mpr.denominator = 0) ; + (* if this assertion does not hold, then the test might be incorrect *) + let committee_size = csts.parametric.consensus_committee_size in + let expected_nb_slots = blocks_per_cycle * committee_size / n_accounts in + let minimal_nb_active_slots = + mpr.numerator * expected_nb_slots / mpr.denominator + in + let account1, account2 = + match accounts with a1 :: a2 :: _ -> (a1, a2) | _ -> assert false + in + let del1 = Context.Contract.pkh account1 in + let del2 = Context.Contract.pkh account2 in + let* b1 = Block.bake ~policy:(By_account del1) b0 in + (* To separate concerns, only [del1] bakes: this way, we don't need to + consider baking rewards for [del2]. Delegate [del2] attests only + if the target [minimal_nb_active_slots] is not reached; for the + rest, it is [del1] that attests. *) + let* pred_b, b, _, last_del2_autostaked = + List.fold_left_es + (fun (b_pred, b_crt, attesting_power, _last_del2_autostaked) level -> + let int_level = Int32.of_int level in + let*?@ level = Raw_level.of_int32 int_level in + let* attesting_power_for_level = + Context.get_attesting_power_for_delegate (B b_crt) ~level del1 + in + let attester, new_attesting_power = + if + sufficient_participation + && attesting_power < minimal_nb_active_slots + then (del2, attesting_power + attesting_power_for_level) + else (del1, attesting_power) + in + let* b, (metadata, _) = + bake_and_attest_once (b_pred, b_crt) del1 attester + in + let autostaked = Block.autostaked_opt del2 metadata in + return (b_crt, b, new_attesting_power, autostaked)) + (b0, b1, 0, None) + (2 -- (blocks_per_cycle - 1)) + in + let* bal2_at_pred_b = + let+ t = Context.Contract.balance (B pred_b) account2 in + Tez.to_mutez t + in + let* bal2_at_b = + let+ t = Context.Contract.balance (B b) account2 in + Tez.to_mutez t + in + (* - If not sufficient_participation, we check that the balance of del2 at b is the + balance of del2 at pred_b; consequently, no rewards could have been given + to del2. + - If sufficient participation, we check that the balance of del2 at b is the + balance of del2 at pred_b plus the attesting rewards. *) + let* er = + Context.get_attesting_reward + (B b) + ~expected_attesting_power:expected_nb_slots + in + let autostaked = + Tez.to_mutez @@ Option.value ~default:Tez.zero last_del2_autostaked + in + let attesting_rewards = if sufficient_participation then er else Tez.zero in + let* attesting_rewards = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + (B b) + (Block.current_cycle b) + del2 + attesting_rewards + in + let attesting_rewards = Test_tez.to_mutez attesting_rewards in + let expected_bal2_at_b = + Int64.(sub (add bal2_at_pred_b attesting_rewards) autostaked) + in + Assert.equal_int64 ~loc:__LOC__ bal2_at_b expected_bal2_at_b + +(* We bake and attest with 1 out of 2 accounts; we monitor the result + returned by the '../delegates//participation' RPC for the + non-participating account. *) +let test_participation_rpc () = + let open Lwt_result_wrap_syntax in + let n_accounts = 2 in + let* b0, (account1, account2) = Context.init2 ~consensus_threshold:1 () in + let del1 = Context.Contract.pkh account1 in + let del2 = Context.Contract.pkh account2 in + let* csts = Context.get_constants (B b0) in + let blocks_per_cycle = Int32.to_int csts.parametric.blocks_per_cycle in + let Ratio.{numerator; denominator} = + csts.parametric.minimal_participation_ratio + in + let expected_cycle_activity = + blocks_per_cycle * csts.parametric.consensus_committee_size / n_accounts + in + let minimal_cycle_activity = + expected_cycle_activity * numerator / denominator + in + let allowed_missed_slots = expected_cycle_activity - minimal_cycle_activity in + let*?@ attesting_reward_per_slot = + Alpha_context.Delegate.Rewards.For_RPC.reward_from_constants + csts.parametric + ~reward_kind:Attesting_reward_per_slot + in + let expected_attesting_rewards = + Test_tez.(attesting_reward_per_slot *! Int64.of_int expected_cycle_activity) + in + let* b1 = Block.bake ~policy:(By_account del1) b0 in + let* _, _, _ = + List.fold_left_es + (fun (b_pred, b_crt, total_attesting_power) level_int -> + let* info = Context.Delegate.participation (B b_crt) del2 in + let* () = + Assert.equal_int + ~loc:__LOC__ + info.expected_cycle_activity + expected_cycle_activity + in + let* () = + Assert.equal_int + ~loc:__LOC__ + info.minimal_cycle_activity + minimal_cycle_activity + in + let* () = + Assert.equal_int ~loc:__LOC__ info.missed_levels (level_int - 1) + in + let missed_slots = total_attesting_power in + let* () = + Assert.equal_int ~loc:__LOC__ info.missed_slots missed_slots + in + let remaining_allowed_missed_slots = + allowed_missed_slots - missed_slots + in + let* () = + Assert.equal_int + ~loc:__LOC__ + info.remaining_allowed_missed_slots + (max 0 remaining_allowed_missed_slots) + in + let attesting_rewards = + if remaining_allowed_missed_slots >= 0 then expected_attesting_rewards + else Tez.zero + in + let* () = + Assert.equal_tez + ~loc:__LOC__ + info.expected_attesting_rewards + attesting_rewards + in + let* b, _ = bake_and_attest_once (b_pred, b_crt) del1 del1 in + (* [level_int] is the level of [b_crt] *) + let*?@ level = level_int |> Int32.of_int |> Raw_level.of_int32 in + let* attesting_power = + Context.get_attesting_power_for_delegate (B b_crt) ~level del2 + in + return (b_crt, b, total_attesting_power + attesting_power)) + (b0, b1, 0) + (1 -- (blocks_per_cycle - 2)) + in + return_unit + +let tests = + [ + Tztest.tztest + "insufficient participation" + `Quick + (test_participation ~sufficient_participation:false); + Tztest.tztest + "minimal participation" + `Quick + (test_participation ~sufficient_participation:true); + Tztest.tztest "participation RPC" `Quick test_participation_rpc; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("participation monitoring", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation.ml new file mode 100644 index 000000000000..10252b3f80d7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation.ml @@ -0,0 +1,255 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (preattestation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_preattestation.ml +*) + +open Protocol +open Alpha_context + +(****************************************************************) +(* Utility functions *) +(****************************************************************) + +let init_genesis ?policy () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init_n ~consensus_threshold:0 5 () in + let* b = Block.bake ?policy genesis in + return (genesis, b) + +(****************************************************************) +(* Tests *) +(****************************************************************) + +(** Test that the preattestation's branch does not affect its + validity. *) +let test_preattestation_with_arbitrary_branch () = + let open Lwt_result_syntax in + let* genesis, _contract = Context.init1 () in + let* blk = Block.bake genesis in + let* operation = Op.preattestation ~branch:Block_hash.zero blk in + let* inc = Incremental.begin_construction ~mempool_mode:true blk in + let* _inc = Incremental.validate_operation inc operation in + return_unit + +(** Consensus operation for future level : apply a preattestation with a level in the future *) +let test_consensus_operation_preattestation_for_future_level () = + let open Lwt_result_syntax in + let* _genesis, pred = init_genesis () in + let raw_level = Raw_level.of_int32 (Int32.of_int 10) in + let level = match raw_level with Ok l -> l | Error _ -> assert false in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~level + ~error:(function + | Validate_errors.Consensus.Consensus_operation_for_future_level {kind; _} + when kind = Validate_errors.Consensus.Preattestation -> + true + | _ -> false) + Preattestation + Mempool + +(** Consensus operation for old level : apply a preattestation with a level in the past *) +let test_consensus_operation_preattestation_for_old_level () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* pred = Block.bake grandparent in + let raw_level = Raw_level.of_int32 (Int32.of_int 0) in + let level = match raw_level with Ok l -> l | Error _ -> assert false in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~level + ~error:(function + | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} + when kind = Validate_errors.Consensus.Preattestation -> + true + | _ -> false) + Preattestation + Mempool + +(** Consensus operation for future round : apply a preattestation with a round in the future *) +let test_consensus_operation_preattestation_for_future_round () = + let open Lwt_result_wrap_syntax in + let* _genesis, pred = init_genesis () in + let*?@ round = Round.of_int 21 in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~round + Preattestation + Mempool + +(** Consensus operation for old round : apply a preattestation with a round in the past *) +let test_consensus_operation_preattestation_for_old_round () = + let open Lwt_result_wrap_syntax in + let* _genesis, pred = init_genesis ~policy:(By_round 10) () in + let*?@ round = Round.of_int 0 in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~round + Preattestation + Mempool + +(** Consensus operation on competing proposal : apply a preattestation on a competing proposal *) +let test_consensus_operation_preattestation_on_competing_proposal () = + let open Lwt_result_syntax in + let* _genesis, pred = init_genesis () in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~block_payload_hash:Block_payload_hash.zero + Preattestation + Mempool + +(** Unexpected preattestations in block : apply a preattestation with an incorrect round *) +let test_unexpected_preattestations_in_blocks () = + let open Lwt_result_syntax in + let* _genesis, pred = init_genesis () in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~error:(function + | Validate_errors.Consensus.Unexpected_preattestation_in_block -> true + | _ -> false) + Preattestation + Application + +(** Round too high : apply a preattestation with a too high round *) +let test_too_high_round () = + let open Lwt_result_wrap_syntax in + let* _genesis, pred = init_genesis () in + let raw_level = Raw_level.of_int32 (Int32.of_int 2) in + let level = match raw_level with Ok l -> l | Error _ -> assert false in + let*?@ round = Round.of_int 1 in + Consensus_helpers.test_consensus_operation + ~loc:__LOC__ + ~attested_block:pred + ~round + ~level + ~error:(function + | Validate_errors.Consensus.Preattestation_round_too_high _ -> true + | _ -> false) + Preattestation + Construction + +(** Duplicate preattestation : apply a preattestation that has already been applied. *) +let test_duplicate_preattestation () = + let open Lwt_result_syntax in + let* genesis, _ = init_genesis () in + let* b = Block.bake genesis in + let* inc = Incremental.begin_construction ~mempool_mode:true b in + let* operation = Op.preattestation b in + let* inc = Incremental.add_operation inc operation in + let* operation = Op.preattestation b in + let*! res = Incremental.add_operation inc operation in + Assert.proto_error_with_info + ~loc:__LOC__ + res + "Double inclusion of consensus operation" + +(** Preattestation for next level *) +let test_preattestation_for_next_level () = + let open Lwt_result_syntax in + let* genesis, _ = init_genesis () in + Consensus_helpers.test_consensus_op_for_next + ~genesis + ~kind:`Preattestation + ~next:`Level + +(** Preattestation for next round *) +let test_preattestation_for_next_round () = + let open Lwt_result_syntax in + let* genesis, _ = init_genesis () in + Consensus_helpers.test_consensus_op_for_next + ~genesis + ~kind:`Preattestation + ~next:`Round + +let tests = + let module AppMode = Test_preattestation_functor.BakeWithMode (struct + let name = "AppMode" + + let baking_mode = Block.Application + end) in + let module ConstrMode = Test_preattestation_functor.BakeWithMode (struct + let name = "ConstrMode" + + let baking_mode = Block.Baking + end) in + AppMode.tests @ ConstrMode.tests + @ [ + Tztest.tztest + "Preattestation with arbitrary branch" + `Quick + test_preattestation_with_arbitrary_branch; + Tztest.tztest + "Preattestation for future level" + `Quick + test_consensus_operation_preattestation_for_future_level; + Tztest.tztest + "Preattestation for old level" + `Quick + test_consensus_operation_preattestation_for_old_level; + Tztest.tztest + "Preattestation for future round" + `Quick + test_consensus_operation_preattestation_for_future_round; + Tztest.tztest + "Preattestation for old round" + `Quick + test_consensus_operation_preattestation_for_old_round; + Tztest.tztest + "Preattestation on competing proposal" + `Quick + test_consensus_operation_preattestation_on_competing_proposal; + Tztest.tztest + "Unexpected preattestations in blocks" + `Quick + test_unexpected_preattestations_in_blocks; + Tztest.tztest "Preattestations round too high" `Quick test_too_high_round; + Tztest.tztest + "Duplicate preattestation" + `Quick + test_duplicate_preattestation; + Tztest.tztest + "Preattestation for next level" + `Quick + test_preattestation_for_next_level; + Tztest.tztest + "Preattestation for next round" + `Quick + test_preattestation_for_next_round; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("preattestation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation_functor.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation_functor.ml new file mode 100644 index 000000000000..3ff3c5351f74 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_preattestation_functor.ml @@ -0,0 +1,285 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (preattestation) in Full_construction & Application modes + Subject: preattestation inclusion in a block +*) + +open Protocol +open Alpha_context + +(****************************************************************) +(* Utility functions *) +(****************************************************************) +module type MODE = sig + val name : string + + val baking_mode : Block.baking_mode +end + +module BakeWithMode (Mode : MODE) : sig + val tests : unit Alcotest_lwt.test_case trace +end = struct + let name = Mode.name + + let bake = Block.bake ~baking_mode:Mode.baking_mode + + let aux_simple_preattestation_inclusion ?(payload_round = Some Round.zero) + ?(locked_round = Some Round.zero) ?(block_round = 1) + ?(preattestation_round = Round.zero) + ?(preattested_block = fun _predpred _pred curr -> curr) + ?(mk_ops = fun op -> [op]) + ?(get_delegate_and_slot = + fun _predpred _pred _curr -> Lwt_result_syntax.return (None, None)) + ?(post_process = Ok (fun _ -> Lwt_result_syntax.return_unit)) ~loc () = + let open Lwt_result_syntax in + let* genesis, _contracts = Context.init_n ~consensus_threshold:1 5 () in + let* b1 = bake genesis in + let* attestation = Op.attestation b1 in + let* b2 = bake b1 ~operations:[attestation] in + let attested_block = preattested_block genesis b1 b2 in + let* delegate, slot = get_delegate_and_slot genesis b1 b2 in + let* p = + Op.preattestation + ?delegate + ?slot + ~round:preattestation_round + attested_block + in + let operations = attestation :: (mk_ops @@ p) in + let*! res = + bake + ~payload_round + ~locked_round + ~policy:(By_round block_round) + ~operations + b1 + in + match (res, post_process) with + | Ok ok, Ok success_fun -> success_fun ok + | Error _, Error error -> Assert.proto_error ~loc res error + | Ok _, Error _ -> Assert.error ~loc res (fun _ -> false) + | Error _, Ok _ -> Assert.error ~loc res (fun _ -> false) + + (****************************************************************) + (* Tests *) + (****************************************************************) + + (** OK: bake a block "_b2_1" at round 1, containing a PQC and a locked + round of round 0 *) + let include_preattestation_in_block_with_locked_round () = + aux_simple_preattestation_inclusion ~loc:__LOC__ () + + (** KO: The same preattestation injected twice in the PQC *) + let duplicate_preattestation_in_pqc () = + aux_simple_preattestation_inclusion (* inject the op twice *) + ~mk_ops:(fun op -> [op; op]) + ~loc:__LOC__ + ~post_process: + (Error + (function + | Validate_errors.Consensus.Conflicting_consensus_operation {kind; _} + when kind = Validate_errors.Consensus.Preattestation -> + true + | _ -> false)) + () + + (** KO: locked round declared in the block is not smaller than + that block's round *) + let locked_round_not_before_block_round () = + aux_simple_preattestation_inclusion + (* default locked_round = 0 < block_round = 1 for this aux function *) + ~block_round:0 + ~loc:__LOC__ + ~post_process: + (Error + (function + | Fitness_repr.Locked_round_not_less_than_round _ -> true + | _ -> false)) + () + + (** KO: because we announce a locked_round, but we don't provide the + preattestation quorum certificate in the operations *) + let with_locked_round_in_block_but_without_any_pqc () = + (* This test only fails in Application mode. If full_construction mode, the + given locked_round is not used / checked. Moreover, the test succeed in + this case. + *) + let open Lwt_result_syntax in + let post_process = + if Mode.baking_mode == Block.Application then + Error (function Fitness_repr.Wrong_fitness -> true | _ -> false) + else Ok (fun _ -> return_unit) + in + aux_simple_preattestation_inclusion + (* with declared locked_round but without a PQC in the ops *) + ~mk_ops:(fun _p -> []) + ~loc:__LOC__ + ~post_process + () + + (** KO: The preattested block is the pred one, not the current one *) + let preattestation_has_wrong_level () = + aux_simple_preattestation_inclusion + (* preattestation should be for _curr block to be valid *) + ~preattested_block:(fun _predpred pred _curr -> pred) + ~loc:__LOC__ + ~post_process: + (Error + (function + | Validate_errors.Consensus.Consensus_operation_for_old_level + {kind; _} + when kind = Validate_errors.Consensus.Preattestation -> + true + | _ -> false)) + () + + (** OK: explicit the correct attester and preattesting slot in the test *) + let preattestation_in_block_with_good_slot () = + let open Lwt_result_syntax in + aux_simple_preattestation_inclusion + ~get_delegate_and_slot:(fun _predpred _pred curr -> + let module V = Plugin.RPC.Validators in + let* validators = Context.get_attesters (B curr) in + match validators with + | {V.delegate; slots = s :: _; _} :: _ -> return (Some delegate, Some s) + | _ -> assert false + (* there is at least one attester with a slot *)) + ~loc:__LOC__ + () + + (** KO: the used slot for injecting the attestation is not the canonical one *) + let preattestation_in_block_with_wrong_slot () = + let open Lwt_result_syntax in + aux_simple_preattestation_inclusion + ~get_delegate_and_slot:(fun _predpred _pred curr -> + let module V = Plugin.RPC.Validators in + let* validators = Context.get_attesters (B curr) in + match validators with + | {V.delegate; V.slots = _ :: non_canonical_slot :: _; _} :: _ -> + return (Some delegate, Some non_canonical_slot) + | _ -> assert false + (* there is at least one attester with a slot *)) + ~loc:__LOC__ + ~post_process: + (Error + (function + | Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation + {kind; _} + when kind = Validate_errors.Consensus.Preattestation -> + true + | _ -> false)) + () + + (** KO: the delegate tries to injects with a canonical slot of another delegate *) + let preattestation_in_block_with_wrong_signature () = + let open Lwt_result_syntax in + aux_simple_preattestation_inclusion + ~get_delegate_and_slot:(fun _predpred _pred curr -> + let module V = Plugin.RPC.Validators in + let* validators = Context.get_attesters (B curr) in + match validators with + | {V.delegate; _} :: {V.slots = s :: _; _} :: _ -> + (* the canonical slot s is not owned by the delegate "delegate" !*) + return (Some delegate, Some s) + | _ -> assert false + (* there is at least one attester with a slot *)) + ~loc:__LOC__ + ~post_process: + (Error + (function Operation_repr.Invalid_signature -> true | _ -> false)) + () + + (** KO: cannot have a locked_round higher than attached PQC's round *) + let locked_round_is_higher_than_pqc_round () = + (* This test only fails in Application mode. If full_construction mode, the + given locked_round is not used / checked. Moreover, the test succeed in + this case. + *) + let open Lwt_result_syntax in + let post_process = + if Mode.baking_mode == Application then + Error + (function + | Validate_errors.Consensus.Consensus_operation_for_old_round + {kind; _} + when kind = Validate_errors.Consensus.Preattestation -> + true + | _ -> false) + else Ok (fun _ -> return_unit) + in + aux_simple_preattestation_inclusion + ~preattestation_round:Round.zero + ~locked_round:(Some (Round.succ Round.zero)) + ~block_round:2 + ~loc:__LOC__ + ~post_process + () + + let my_tztest title test = + Tztest.tztest (Format.sprintf "%s: %s" name title) test + + let tests = + [ + my_tztest + "ok: include_preattestation_in_block_with_locked_round" + `Quick + include_preattestation_in_block_with_locked_round; + my_tztest + "ko: duplicate_preattestation_in_pqc" + `Quick + duplicate_preattestation_in_pqc; + my_tztest + "ko:locked_round_not_before_block_round" + `Quick + locked_round_not_before_block_round; + my_tztest + "ko: with_locked_round_in_block_but_without_any_pqc" + `Quick + with_locked_round_in_block_but_without_any_pqc; + my_tztest + "ko: preattestation_has_wrong_level" + `Quick + preattestation_has_wrong_level; + my_tztest + "ok: preattestation_in_block_with_good_slot" + `Quick + preattestation_in_block_with_good_slot; + my_tztest + "ko: preattestation_in_block_with_wrong_slot" + `Quick + preattestation_in_block_with_wrong_slot; + my_tztest + "ko: preattestation_in_block_with_wrong_signature" + `Quick + preattestation_in_block_with_wrong_signature; + my_tztest + "ko: locked_round_is_higher_than_pqc_round" + `Quick + locked_round_is_higher_than_pqc_round; + ] +end diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_seed.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_seed.ml new file mode 100644 index 000000000000..1b4ce9e1bf4e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/test_seed.ml @@ -0,0 +1,716 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (seed) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/consensus/main.exe \ + -- --file test_seed.ml + Subject: - seed_nonce_hash included in some blocks + - revelation operation of seed_nonce that should correspond + to each seed_nonce_hash +*) + +open Protocol + +(** Checking that, in the absence of nonce revelations and VDF computation, + the seed of each cycle is correctly computed based on the seed of + the previous cycle. *) +let test_seed_no_commitment () = + let open Lwt_result_syntax in + let n_cycles = 15 in + let (Hash initial_seed) = + let empty_bytes = Bytes.(copy empty) in + Tezos_crypto.Hacl.Blake2b.direct empty_bytes Nonce_hash.size + in + let seeds = + (* compute the first `n_cycles` expected seeds *) + let zero_bytes = Bytes.make Nonce_hash.size '\000' in + let rec make_seeds s = function + | 0 -> [] + | n -> + let (Hash h) = + Tezos_crypto.Hacl.Blake2b.direct + (Bytes.cat s zero_bytes) + Nonce_hash.size + in + h :: make_seeds h (n - 1) + in + make_seeds initial_seed n_cycles + in + let check_seed b expected_seed = + let open Alpha_context in + let* s = Context.get_seed (B b) in + let seed_bytes = Data_encoding.Binary.to_bytes_exn Seed.seed_encoding s in + (if expected_seed <> seed_bytes then + let seed_pp = + Hex.show + (Hex.of_string + (Data_encoding.Binary.to_string_exn Seed.seed_encoding s)) + in + let expected_seed_pp = Hex.show (Hex.of_bytes expected_seed) in + Stdlib.failwith + (Format.sprintf "Seed: %s\nExpected: %s\n\n" seed_pp expected_seed_pp)) ; + return b + in + let rec bake_and_check_seed b = function + | [] -> return b + | s :: seeds -> + let* b = Block.bake_until_cycle_end b in + let* b = check_seed b s in + let* b = Block.bake_n 2 b in + bake_and_check_seed b seeds + in + let* b, _delegates = + Context.init3 + ~blocks_per_cycle:8l + ~consensus_threshold:0 + ~nonce_revelation_threshold:2l + () + in + let* b = check_seed b initial_seed in + let* (_ : Block.t) = bake_and_check_seed b seeds in + return_unit + +(** Baking [blocks_per_commitment] blocks without a [seed_nonce_hash] + commitment fails with an "Invalid commitment in block header" error. *) +let test_no_commitment () = + let open Lwt_result_syntax in + let* b, _contracts = Context.init_n ~consensus_threshold:0 5 () in + let* {parametric = {blocks_per_commitment; _}; _} = + Context.get_constants (B b) + in + let blocks_per_commitment = Int32.to_int blocks_per_commitment in + (* Bake normally until before the commitment *) + let* b = Block.bake_n (blocks_per_commitment - 2) b in + (* Forge a block with empty commitment and apply it *) + let* header = Block.Forge.forge_header b in + let* header = Block.Forge.set_seed_nonce_hash None header in + let* header = Block.Forge.sign_header header in + let*! e = Block.apply header b in + Assert.proto_error_with_info + ~loc:__LOC__ + e + "Invalid commitment in block header" + +(** Choose a baker, denote it by id. In the first cycle, make id bake only once. + Check that: + - when id reveals the nonce too early, there's an error + - when id reveals at the right time but the wrong value, there's an error + - when another baker reveals correctly, it receives the tip + - revealing twice produces an error *) +let test_revelation_early_wrong_right_twice () = + let open Lwt_result_syntax in + let open Assert in + let* b, _contracts = Context.init_n ~consensus_threshold:0 5 () in + let* csts = Context.get_constants (B b) in + let* tip = Context.get_seed_nonce_revelation_tip (B b) in + let blocks_per_commitment = + Int32.to_int csts.parametric.blocks_per_commitment + in + let* baking_reward_fixed_portion = + Context.get_baking_reward_fixed_portion (B b) + in + (* get the pkh of a baker *) + let* pkh, _, _, _ = Block.get_next_baker b in + let id = Alpha_context.Contract.Implicit pkh in + let policy = Block.Excluding [pkh] in + (* bake until commitment - 2, excluding id *) + let* b = Block.bake_n ~policy (blocks_per_commitment - 2) b in + let* bal_main = Context.Contract.balance (B b) id in + let cycle_for_rewards = Block.current_cycle b in + (* the baker [id] will include a seed_nonce commitment *) + let* b = Block.bake ~policy:(Block.By_account pkh) b in + let*? level_commitment = Context.get_level (B b) in + let* committed_hash = Context.get_seed_nonce_hash (B b) in + (* test that the baking reward is received *) + let* reward_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + baking_reward_fixed_portion + in + let* () = + balance_was_credited ~loc:__LOC__ (B b) id bal_main reward_to_liquid + in + (* test that revealing too early produces an error *) + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + in + let*! e = Block.bake ~policy ~operation b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Too_early_revelation -> true + | _ -> false) + in + (* finish the cycle excluding the committing baker, id *) + let* b = Block.bake_until_cycle_end ~policy b in + (* test that revealing at the right time but the wrong value + produces an error *) + let wrong_hash, _ = Nonce.generate () in + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get wrong_hash) + in + let*! e = Block.bake ~operation b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Inconsistent_nonce -> true + | _ -> false) + in + (* reveals correctly *) + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + in + let* baker_pkh, _, _, _ = Block.get_next_baker ~policy b in + let baker = Alpha_context.Contract.Implicit baker_pkh in + let* baker_bal = Context.Contract.balance (B b) baker in + (* test that revealing twice in a block produces an error *) + let*! e = + Block.bake + ~policy:(Block.By_account baker_pkh) + ~operations:[operation; operation] + b + in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Conflicting_nonce_revelation _ -> true + | _ -> false) + in + let cycle_for_rewards = Block.current_cycle b in + let* b = Block.bake ~policy:(Block.By_account baker_pkh) ~operation b in + (* test that the baker gets the tip reward plus the baking reward*) + let* tip_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + tip + in + let* baking_reward_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + baking_reward_fixed_portion + in + let reward_to_liquid = Test_tez.(baking_reward_to_liquid +! tip_to_liquid) in + + let* () = + balance_was_credited ~loc:__LOC__ (B b) baker baker_bal reward_to_liquid + in + (* test that revealing twice produces an error *) + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get wrong_hash) + in + let*! e = Block.bake ~operation ~policy b in + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Already_revealed_nonce -> true + | _ -> false) + +(** Test that revealing too late produces an error. Note that a + committer who doesn't reveal at cycle 1 is not punished.*) +let test_revelation_missing_and_late () = + let open Lwt_result_syntax in + let open Context in + let open Assert in + let* b, _contracts = Context.init_n ~consensus_threshold:0 5 () in + let* csts = get_constants (B b) in + let blocks_per_commitment = + Int32.to_int csts.parametric.blocks_per_commitment + in + let nonce_revelation_threshold = + Int32.to_int csts.parametric.nonce_revelation_threshold + in + (* bake until commitment *) + let* b = Block.bake_n (blocks_per_commitment - 2) b in + (* the next baker [id] will include a seed_nonce commitment *) + let* pkh, _, _, _ = Block.get_next_baker b in + let* b = Block.bake b in + let*? level_commitment = Context.get_level (B b) in + let* committed_hash = Context.get_seed_nonce_hash (B b) in + (* finish cycle 0 excluding the committing baker [id] *) + let policy = Block.Excluding [pkh] in + let* b = Block.bake_until_cycle_end ~policy b in + (* test that revealing after revelation period produces an error *) + let* b = Block.bake_n (nonce_revelation_threshold - 1) b in + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + in + let*! e = Block.bake ~operation ~policy b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Too_late_revelation -> true + | _ -> false) + in + (* finish cycle 1 excluding the committing baker [id] *) + let* b = Block.bake_until_cycle_end ~policy b in + (* test that revealing too late after cycle 1 produces an error *) + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + in + let*! e = Block.bake ~operation b in + Assert.proto_error ~loc:__LOC__ e (function + | Nonce_storage.Too_late_revelation -> true + | _ -> false) + +(** Test that we do not distribute attesting rewards if the nonce was + not revealed. *) +let test_unrevealed () = + let open Lwt_result_syntax in + let open Alpha_context in + let constants = + { + Default_parameters.constants_test with + issuance_weights = + { + base_total_issued_per_minute = Tez.one; + attesting_reward_weight = 1; + baking_reward_bonus_weight = 0; + baking_reward_fixed_portion_weight = 0; + seed_nonce_revelation_tip_weight = 0; + vdf_revelation_tip_weight = 0; + }; + consensus_threshold = 0; + minimal_participation_ratio = Ratio.{numerator = 0; denominator = 1}; + } + in + let* b, (_account1, account2) = Context.init_with_constants2 constants in + let delegate2 = Context.Contract.pkh account2 in + (* Delegate 2 will add a nonce but never reveals it *) + let* csts = Context.get_constants (B b) in + let blocks_per_commitment = + Int32.to_int csts.parametric.blocks_per_commitment + in + let bake_and_attest_block ?policy (_pred_b, b) = + let* slots = Context.get_attesters (B b) in + let* attestations = + List.map_es + (fun {Plugin.RPC.Validators.consensus_key; _} -> + Op.attestation ~delegate:consensus_key b) + slots + in + Block.bake ?policy ~operations:attestations b + in + (* Bake until commitment *) + let* b = Block.bake_n (blocks_per_commitment - 2) b in + (* Baker delegate 2 will include a seed_nonce commitment *) + let policy = Block.By_account delegate2 in + let* b = Block.bake_until_cycle_end ~policy b in + let* info_before = Context.Delegate.info (B b) delegate2 in + let* b' = Block.bake ~policy b in + let* b = bake_and_attest_block ~policy (b, b') in + (* Finish cycle 1 excluding the first baker *) + let* b = Block.bake_until_cycle_end ~policy b in + let* info_after = Context.Delegate.info (B b) delegate2 in + (* Assert that we did not received a reward because we didn't + reveal the nonce. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + info_before.full_balance + info_after.full_balance + in + return_unit + +let test_vdf_status () = + let open Lwt_result_syntax in + let* b, _ = Context.init3 ~consensus_threshold:0 () in + let* b = Block.bake b in + let* status = Context.get_seed_computation (B b) in + assert (status = Alpha_context.Seed.Nonce_revelation_stage) ; + let* constants = Context.get_constants (B b) in + let* b = + Block.bake_n + (Int32.to_int constants.parametric.nonce_revelation_threshold) + b + in + let* status = Context.get_seed_computation (B b) in + assert ( + match status with + | Alpha_context.Seed.Vdf_revelation_stage _ -> true + | _ -> false) ; + return_unit + +(** Choose a baker, denote it by id. In the first cycle, make id bake only once. + Check that: + - when the vdf is revealed too early, there's an error + - when the vdf is revealed at the right time but the wrong value, there's an error + - when the vdf is revealed at the right time and the correct value, + - the baker receives a reward + - the VDF status is updated to "Computation_finished" + - the seed is updated with the vdf solution + - another vdf revelation produces an error *) +let test_early_incorrect_unverified_correct_already_vdf () = + let open Lwt_result_syntax in + let open Assert in + let* b, _ = Context.init3 ~consensus_threshold:0 () in + let* csts = Context.get_constants (B b) in + let blocks_per_commitment = + Int32.to_int csts.parametric.blocks_per_commitment + in + let nonce_revelation_threshold = + Int32.to_int csts.parametric.nonce_revelation_threshold + in + let* baking_reward_fixed_portion = + Context.get_baking_reward_fixed_portion (B b) + in + let* seed_nonce_revelation_tip = + Context.get_seed_nonce_revelation_tip (B b) + in + let* vdf_nonce_revelation_tip = Context.get_vdf_revelation_tip (B b) in + (* get the pkh of a baker *) + let* pkh, _, _, _ = Block.get_next_baker b in + let id = Alpha_context.Contract.Implicit pkh in + let policy = Block.Excluding [pkh] in + (* bake until commitment - 2, excluding id *) + let* b = Block.bake_n ~policy (blocks_per_commitment - 2) b in + let* bal_main = Context.Contract.balance (B b) id in + (* the baker [id] will include a seed_nonce commitment *) + let cycle_for_rewards = Block.current_cycle b in + let* b = Block.bake ~policy:(Block.By_account pkh) b in + let*? level_commitment = Context.get_level (B b) in + let* committed_hash = Context.get_seed_nonce_hash (B b) in + (* test that the baking reward is received *) + let* reward_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + baking_reward_fixed_portion + in + let* () = + balance_was_credited ~loc:__LOC__ (B b) id bal_main reward_to_liquid + in + (* finish the cycle excluding the committing baker, id *) + let* b = Block.bake_until_cycle_end ~policy b in + (* reveals correctly *) + let operation = + Op.seed_nonce_revelation + (B b) + level_commitment + (WithExceptions.Option.to_exn ~none:Not_found @@ Nonce.get committed_hash) + in + let* baker_pkh, _, _, _ = Block.get_next_baker ~policy b in + let baker = Alpha_context.Contract.Implicit baker_pkh in + let* baker_bal = Context.Contract.balance (B b) baker in + let cycle_for_rewards = Block.current_cycle b in + let* b = Block.bake ~policy:(Block.By_account baker_pkh) ~operation b in + (* test that the baker gets the tip reward plus the baking reward*) + let* tip_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + seed_nonce_revelation_tip + in + let* baking_reward_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + baking_reward_fixed_portion + in + let reward_to_liquid = Test_tez.(tip_to_liquid +! baking_reward_to_liquid) in + let* () = + balance_was_credited ~loc:__LOC__ (B b) baker baker_bal reward_to_liquid + in + (* test that revealing the VDF early produces an error *) + let dummy_solution = + let open Environment.Vdf in + let dummy = Bytes.create Environment.Vdf.form_size_bytes in + let result = Stdlib.Option.get @@ result_of_bytes_opt dummy in + let proof = Stdlib.Option.get @@ proof_of_bytes_opt dummy in + (result, proof) + in + let operation = Op.vdf_revelation (B b) dummy_solution in + let*! e = Block.bake ~operation b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Seed_storage.Too_early_revelation -> true + | _ -> false) + in + (* bake until nonce reveal period finishes *) + let* b = Block.bake_n ~policy nonce_revelation_threshold b in + (* test that revealing non group elements produces an error *) + let operation = Op.vdf_revelation (B b) dummy_solution in + let*! e = Block.bake ~operation b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Seed_storage.Unverified_vdf -> true + | _ -> false) + in + let* seed_status = Context.get_seed_computation (B b) in + match seed_status with + | Nonce_revelation_stage -> assert false + | Computation_finished -> assert false + | Vdf_revelation_stage info -> ( + (* generate the VDF discriminant and challenge *) + let discriminant, challenge = + Alpha_context.Seed.generate_vdf_setup + ~seed_discriminant:info.seed_discriminant + ~seed_challenge:info.seed_challenge + in + (* test that revealing wrong VDF produces an error *) + let wrong_solution = + let open Environment.Vdf in + let f = challenge_to_bytes challenge in + let result = Stdlib.Option.get @@ result_of_bytes_opt f in + let proof = Stdlib.Option.get @@ proof_of_bytes_opt f in + (result, proof) + in + let operation = Op.vdf_revelation (B b) wrong_solution in + let*! e = Block.bake ~operation b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Seed_storage.Unverified_vdf -> true + | _ -> false) + in + (* test with correct input *) + (* compute the VDF solution (the result and the proof ) *) + let solution = + (* generate the result and proof *) + Environment.Vdf.prove + discriminant + challenge + csts.parametric.vdf_difficulty + in + let* baker_bal = Context.Contract.balance (B b) baker in + let operation = Op.vdf_revelation (B b) solution in + let*! e = + Block.bake + ~policy:(Block.By_account baker_pkh) + ~operations:[operation; operation] + b + in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Validate_errors.Anonymous.Conflicting_vdf_revelation _ -> true + | _ -> false) + in + (* verify the balance was credited following operation inclusion *) + let cycle_for_rewards = Block.current_cycle b in + let* b = Block.bake ~policy:(Block.By_account baker_pkh) ~operation b in + let* tip_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + vdf_nonce_revelation_tip + in + let* baking_reward_to_liquid = + Adaptive_issuance_helpers.portion_of_rewards_to_liquid_for_cycle + ~policy + (B b) + cycle_for_rewards + pkh + baking_reward_fixed_portion + in + let reward_to_liquid = + Test_tez.(tip_to_liquid +! baking_reward_to_liquid) + in + let* () = + balance_was_credited ~loc:__LOC__ (B b) baker baker_bal reward_to_liquid + in + (* verify the seed status has changed *) + let* seed_status = Context.get_seed_computation (B b) in + match seed_status with + | Nonce_revelation_stage -> assert false + | Vdf_revelation_stage _ -> assert false + | Computation_finished -> + (* test than sending another VDF reveal produces an error *) + let operation = Op.vdf_revelation (B b) solution in + let*! e = Block.bake ~operation b in + let* () = + Assert.proto_error ~loc:__LOC__ e (function + | Seed_storage.Already_accepted -> true + | _ -> false) + in + (* verify the stored seed has the expected value *) + let open Data_encoding.Binary in + let open Alpha_context in + (* retrieving & converting seed stored in cycle n + preserved_cycle + 1 *) + let* b = + Block.bake_until_n_cycle_end + ~policy + (csts.parametric.consensus_rights_delay + 1) + b + in + let* stored_seed = Context.get_seed (B b) in + let vdf_stored_seed = to_bytes_exn Seed.seed_encoding stored_seed in + (* recomputing seed with randao output and vdf solution *) + let vdf_expected_seed = + let randao_seed = + to_bytes_exn Seed.seed_encoding info.seed_challenge + |> of_bytes_exn Seed_repr.seed_encoding + in + Seed_repr.vdf_to_seed randao_seed solution + |> to_bytes_exn Seed_repr.seed_encoding + in + assert (Bytes.(equal vdf_expected_seed vdf_stored_seed)) ; + return_unit) + +(* We check that bounds used in [Seed_storage.for_cycle] are as expected. *) +let test_cycle_bounds () = + let open Lwt_result_syntax in + let* b, _accounts = Context.init1 ~consensus_threshold:0 () in + let* csts = Context.get_constants (B b) in + let past_offset = Constants_repr.max_slashing_period - 1 in + let future_offset = csts.parametric.consensus_rights_delay in + let open Alpha_context.Cycle in + let expected_error_message direction current_cycle = + match direction with + | `Past -> + let oldest_cycle = Stdlib.Option.get (sub current_cycle past_offset) in + let older_cycle = Stdlib.Option.get (sub oldest_cycle 1) in + Format.asprintf + "The seed for cycle %a has been cleared from the context (oldest \ + known seed is for cycle %a)" + pp + older_cycle + pp + oldest_cycle + | `Future -> + let latest_cycle = add current_cycle future_offset in + let later_cycle = add latest_cycle 1 in + Format.asprintf + "The seed for cycle %a has not been computed yet (latest known seed \ + is for cycle %a)" + pp + later_cycle + pp + latest_cycle + | `Missing_sampler_state cycle -> + Format.asprintf + "Storage error:\n Missing key 'cycle/%a/delegate_sampler_state'." + pp + cycle + in + let cycle = root in + let* (_ : _ list) = + Context.get_bakers ~cycle:(add cycle future_offset) (B b) + in + let future_cycle = add cycle (future_offset + 1) in + let*! res = Context.get_bakers ~cycle:future_cycle (B b) in + (* the first cycle is special *) + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + ~error_info_field:`Message + res + (expected_error_message (`Missing_sampler_state future_cycle) cycle) + in + let* b = Block.bake_until_cycle_end b in + let cycle = add cycle 1 in + let* (_ : _ list) = Context.get_bakers ~cycle:root (B b) in + let* (_ : _ list) = + Context.get_bakers ~cycle:(add cycle future_offset) (B b) + in + let*! res = Context.get_bakers ~cycle:(add cycle (future_offset + 1)) (B b) in + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + res + ~error_info_field:`Message + (expected_error_message `Future cycle) + in + let* b = Block.bake_until_n_cycle_end past_offset b in + let cycle = add cycle past_offset in + let* (_ : _ list) = + Context.get_bakers ~cycle:(Stdlib.Option.get (sub cycle past_offset)) (B b) + in + let*! res = + Context.get_bakers + ~cycle:(Stdlib.Option.get (sub cycle (past_offset + 1))) + (B b) + in + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + res + ~error_info_field:`Message + (expected_error_message `Past cycle) + in + let* (_ : _ list) = + Context.get_bakers ~cycle:(add cycle future_offset) (B b) + in + let*! res = Context.get_bakers ~cycle:(add cycle (future_offset + 1)) (B b) in + Assert.proto_error_with_info + ~loc:__LOC__ + res + ~error_info_field:`Message + (expected_error_message `Future cycle) + +let tests = + [ + Tztest.tztest + "seed computation (no commitment)" + `Quick + test_seed_no_commitment; + Tztest.tztest "no commitment" `Quick test_no_commitment; + Tztest.tztest + "revelation_early_wrong_right_twice" + `Quick + test_revelation_early_wrong_right_twice; + Tztest.tztest + "revelation_missing_and_late" + `Quick + test_revelation_missing_and_late; + Tztest.tztest "unrevealed" `Quick test_unrevealed; + Tztest.tztest + "early_incorrect_unverified_correct_already_vdf" + `Quick + test_early_incorrect_unverified_correct_already_vdf; + Tztest.tztest "VDF status" `Quick test_vdf_status; + Tztest.tztest "for_cycle cycle bounds" `Quick test_cycle_bounds; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("seed", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/dune new file mode 100644 index 000000000000..d4ede79ff063 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/dune @@ -0,0 +1,60 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_protocol_test_integration_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + tezt + octez-libs.tezos-context + octez-alcotezt + octez-libs.base + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.protocol + tezos-protocol-019-PtParisB.parameters + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.base-test-helpers) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base.TzPervasives + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_019_PtParisB_test_helpers + -open Tezos_base_test_helpers) + (modules + test_constants + test_frozen_bonds + test_adaptive_issuance_launch + test_adaptive_issuance_roundtrip + test_liquidity_baking + test_storage_functions + test_storage + test_token)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_integration_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (deps (glob_files wasm_kernel/*.wasm)) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune new file mode 100644 index 000000000000..35b93cb45f6b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune @@ -0,0 +1,45 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_protocol_test_integration_gas_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-alcotezt + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.base-test-helpers) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_019_PtParisB_test_helpers + -open Tezos_base_test_helpers) + (modules test_gas_costs test_gas_levels)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_integration_gas_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_costs.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_costs.ml new file mode 100644 index 000000000000..a5c58e2873b2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_costs.ml @@ -0,0 +1,291 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (gas costs) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/gas/main.exe \ + -- --file test_gas_costs.ml + Subject: Gas costs + Current limitations: for maps, sets & compare, we only test + integer comparable keys. +*) + +open Protocol +module S = Saturation_repr + +let dummy_list = Script_list.(cons 42 empty) + +let forty_two = Script_int.of_int 42 + +let forty_two_n = Script_int.abs forty_two + +let dummy_set = + let open Script_set in + update forty_two true (empty Script_typed_ir.int_t) + +let dummy_map = + let open Script_map in + update forty_two (Some forty_two) (empty Script_typed_ir.int_t) + +let dummy_timestamp = Script_timestamp.of_zint (Z.of_int 42) + +let dummy_pk = + Signature.Public_key.of_b58check_exn + "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU" + +let dummy_bytes = Bytes.of_string "dummy" + +let dummy_string = + match Script_string.of_string "dummy" with + | Ok s -> s + | Error _ -> assert false + +let dummy_ty = Script_typed_ir.never_t + +let free = ["balance"; "bool"; "parsing_unit"; "unparsing_unit"] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_interpreter_costs = + let open Michelson_v1_gas.Cost_of.Interpreter in + [ + ("drop", drop); + ("dup", dup); + ("swap", swap); + ("cons_some", cons_some); + ("cons_none", cons_none); + ("if_none", if_none); + ("cons_pair", cons_pair); + ("car", car); + ("cdr", cdr); + ("cons_left", cons_left); + ("cons_right", cons_right); + ("if_left", if_left); + ("cons_list", cons_list); + ("nil", nil); + ("if_cons", if_cons); + ("list_map", list_map dummy_list); + ("list_size", list_size); + ("list_iter", list_iter dummy_list); + ("empty_set", empty_set); + ("set_iter", set_iter dummy_set); + ("set_mem", set_mem forty_two dummy_set); + ("set_update", set_update forty_two dummy_set); + ("set_size", set_size); + ("empty_map", empty_map); + ("map_map", map_map dummy_map); + ("map_iter", map_iter dummy_map); + ("map_mem", map_mem forty_two dummy_map); + ("map_get", map_get forty_two dummy_map); + ("map_update", map_update forty_two dummy_map); + ("map_size", map_size); + ("add_seconds_timestamp", add_seconds_timestamp forty_two dummy_timestamp); + ("sub_timestamp_seconds", sub_timestamp_seconds dummy_timestamp forty_two); + ("diff_timestamps", diff_timestamps dummy_timestamp dummy_timestamp); + ("concat_string_pair", concat_string_pair dummy_string dummy_string); + ("slice_string", slice_string dummy_string); + ("string_size", string_size); + ("concat_bytes_pair", concat_bytes_pair dummy_bytes dummy_bytes); + ("slice_bytes", slice_bytes dummy_bytes); + ("bytes_size", bytes_size); + ("add_tez", add_tez); + ("sub_tez", sub_tez); + ("mul_teznat", mul_teznat); + ("bool_or", bool_or); + ("bool_and", bool_and); + ("bool_xor", bool_xor); + ("bool_not", bool_not); + ("is_nat", is_nat); + ("abs_int", abs_int forty_two); + ("int_nat", int_nat); + ("neg", neg forty_two); + ("add_int", add_int forty_two forty_two); + ("sub_int", sub_int forty_two forty_two); + ("mul_int", mul_int forty_two forty_two); + ("ediv_teznat", ediv_teznat Alpha_context.Tez.fifty_cents forty_two); + ("ediv_tez", ediv_tez); + ("ediv_int", ediv_int forty_two (Script_int.of_int 1)); + ("eq", eq); + ("lsl_nat", lsl_nat forty_two); + ("lsr_nat", lsr_nat forty_two); + ("or_nat", or_nat forty_two forty_two); + ("and_nat", and_nat forty_two forty_two); + ("xor_nat", xor_nat forty_two forty_two); + ("not_int", not_int forty_two); + ("if_", if_); + ("loop", loop); + ("loop_left", loop_left); + ("dip", dip); + ("check_signature", check_signature dummy_pk dummy_bytes); + ("blake2b", blake2b dummy_bytes); + ("sha256", sha256 dummy_bytes); + ("sha512", sha512 dummy_bytes); + ("dign", dign 42); + ("dugn", dugn 42); + ("dipn", dipn 42); + ("dropn", dropn 42); + ("neq", neq); + ("compare", compare Script_typed_ir.int_t forty_two forty_two); + ( "concat_string_precheck", + concat_string_precheck Script_list.(cons "42" empty) ); + ("concat_string", concat_string (S.safe_int 42)); + ("concat_bytes", concat_bytes (S.safe_int 42)); + ("exec", exec); + ("apply_rec", apply ~rec_flag:true); + ("apply", apply ~rec_flag:false); + ("lambda", lambda); + ("address", address); + ("contract", contract); + ("transfer_tokens", transfer_tokens); + ("implicit_account", implicit_account); + ("create_contract", create_contract); + ("set_delegate", set_delegate); + (* balance is free *) + ("balance", balance); + ("level", level); + ("now", now); + ("hash_key", hash_key dummy_pk); + ("source", source); + ("sender", sender); + ("self", self); + ("self_address", self_address); + ("amount", amount); + ("chain_id", chain_id); + ("unpack_failed", unpack_failed "dummy"); + ] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_parsing_costs = + let open Michelson_v1_gas.Cost_of.Typechecking in + [ + ("public_key_optimized", public_key_optimized); + ("public_key_readable", public_key_readable); + ("key_hash_optimized", key_hash_optimized); + ("key_hash_readable", key_hash_readable); + ("signature_optimized", signature_optimized); + ("signature_readable", signature_readable); + ("chain_id_optimized", chain_id_optimized); + ("chain_id_readable", chain_id_readable); + ("address_optimized", address_optimized); + ("contract_optimized", contract_optimized); + ("contract_readable", contract_readable); + ("check_printable", check_printable "dummy"); + ("ty_eq", ty_eq dummy_ty dummy_ty); + ("ty_eq_prim", ty_eq_prim); + ("parse_type_cycle", parse_type_cycle); + ("parse_instr_cycle", parse_instr_cycle); + ("parse_data_cycle", parse_data_cycle); + ("bool", bool); + ("parsing_unit", unit); + ("timestamp_readable", timestamp_readable "dummy"); + ("contract_exists", contract_exists); + ("proof_argument", proof_argument 42); + ] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_unparsing_costs = + let open Michelson_v1_gas.Cost_of.Unparsing in + [ + ("public_key_optimized", public_key_optimized); + ("public_key_readable", public_key_readable); + ("key_hash_optimized", key_hash_optimized); + ("key_hash_readable", key_hash_readable); + ("signature_optimized", signature_optimized); + ("signature_readable", signature_readable); + ("chain_id_optimized", chain_id_optimized); + ("chain_id_readable", chain_id_readable); + ("timestamp_readable", timestamp_readable); + ("address_optimized", address_optimized); + ("contract_optimized", contract_optimized); + ("contract_readable", contract_readable); + ("unparse_type", unparse_type dummy_ty); + ("unparse_instr_cycle", unparse_instr_cycle); + ("unparse_data_cycle", unparse_data_cycle); + ("unparsing_unit", unit); + ("operation", operation dummy_bytes); + ] + +(* /!\ The compiler will only complain if costs are _removed_ /!\*) +let all_io_costs = + let open Storage_costs in + [ + ("read_access 0 0", read_access ~path_length:0 ~read_bytes:0); + ("read_access 1 0", read_access ~path_length:1 ~read_bytes:0); + ("read_access 0 1", read_access ~path_length:0 ~read_bytes:1); + ("read_access 1 1", read_access ~path_length:1 ~read_bytes:1); + ("write_access 0", write_access ~written_bytes:0); + ("write_access 1", write_access ~written_bytes:1); + ] + +(* Here we're using knowledge of the internal representation of costs to + cast them to S ... *) +let cast_cost_to_s (c : Alpha_context.Gas.cost) : _ S.t = + Data_encoding.Binary.to_bytes_exn Alpha_context.Gas.cost_encoding c + |> Data_encoding.Binary.of_bytes_exn S.n_encoding + +(** Checks that all costs are positive values. *) +let test_cost_reprs_are_all_positive list () = + let open Lwt_result_syntax in + List.iter_es + (fun (cost_name, cost) -> + if S.(cost > S.zero) then return_unit + else if S.equal cost S.zero && List.mem ~equal:String.equal cost_name free + then return_unit + else + tzfail + (Exn + (Failure (Format.asprintf "Gas cost test \"%s\" failed" cost_name)))) + list + +(** Checks that all costs are positive values. *) +let test_costs_are_all_positive list () = + let list = + List.map (fun (cost_name, cost) -> (cost_name, cast_cost_to_s cost)) list + in + test_cost_reprs_are_all_positive list () + +let tests = + [ + Tztest.tztest + "Positivity of interpreter costs" + `Quick + (test_costs_are_all_positive all_interpreter_costs); + Tztest.tztest + "Positivity of typechecking costs" + `Quick + (test_costs_are_all_positive all_parsing_costs); + Tztest.tztest + "Positivity of unparsing costs" + `Quick + (test_costs_are_all_positive all_unparsing_costs); + Tztest.tztest + "Positivity of io costs" + `Quick + (test_cost_reprs_are_all_positive all_io_costs); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("gas cost functions", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_levels.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_levels.ml new file mode 100644 index 000000000000..ef8cbc932bca --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/test_gas_levels.ml @@ -0,0 +1,632 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Gas levels) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/gas/main.exe \ + -- --file test_gas_levels.ml + Subject: On gas consumption and exhaustion. +*) + +open Protocol +open Raw_context +module S = Saturation_repr + +(* This value is supposed to be larger than the block gas level limit + but not saturated. *) +let opg = max_int / 10000 + +exception Gas_levels_test_error of string + +let err x = Exn (Gas_levels_test_error x) + +let succeed x = match x with Ok _ -> true | _ -> false + +let failed x = not (succeed x) + +let dummy_context () = + let open Lwt_result_wrap_syntax in + let* block, _contract = Context.init1 ~consensus_threshold:0 () in + let*@ ctxt = + Raw_context.prepare + ~level:Int32.zero + ~predecessor_timestamp:Time.Protocol.epoch + ~timestamp:Time.Protocol.epoch + (* ~fitness:[] *) + (block.context : Tezos_protocol_environment.Context.t) + ~adaptive_issuance_enable:false + in + return ctxt + +let consume_gas_lwt context gas = + let open Lwt_result_wrap_syntax in + let*?@ ctxt = consume_gas context (S.safe_int gas) in + return ctxt + +let consume_gas_limit_in_block_lwt context gas = + let open Lwt_result_wrap_syntax in + let*?@ ctxt = consume_gas_limit_in_block context gas in + return ctxt + +let test_detect_gas_exhaustion_in_fresh_context () = + let open Lwt_result_syntax in + let* context = dummy_context () in + fail_unless + (consume_gas context (S.safe_int opg) |> succeed) + (err "In a fresh context, gas consumption is unlimited.") + +(** Create a context with a given block gas level, capped at the + hard gas limit per block *) +let make_context remaining_block_gas = + let open Lwt_result_syntax in + let open Gas_limit_repr in + let* context = dummy_context () in + let hard_limit = Arith.fp (constants context).hard_gas_limit_per_operation in + let hard_limit_block = + Arith.fp (constants context).hard_gas_limit_per_block + in + let block_gas = Arith.(unsafe_fp (Z.of_int remaining_block_gas)) in + let rec aux context to_consume = + (* Because of saturated arithmetic, [to_consume] should never be negative. *) + assert (Arith.(to_consume >= zero)) ; + if Arith.(to_consume = zero) then return context + else if Arith.(to_consume <= hard_limit) then + consume_gas_limit_in_block_lwt context to_consume + else + let* context = consume_gas_limit_in_block_lwt context hard_limit in + aux context (Arith.sub to_consume hard_limit) + in + aux context Arith.(sub hard_limit_block block_gas) + +(** Test operation gas exhaustion. Should pass when remaining gas is 0, + and fail when it goes over *) +let test_detect_gas_exhaustion_when_operation_gas_hits_zero () = + let open Lwt_result_syntax in + let gas_op = 100000 in + let* context = dummy_context () in + set_gas_limit context (Gas_limit_repr.Arith.unsafe_fp (Z.of_int gas_op)) + |> fun context -> + let* () = + fail_unless + (consume_gas context (S.safe_int gas_op) |> succeed) + (err "Succeed when consuming exactly the remaining operation gas.") + in + fail_unless + (consume_gas context (S.safe_int (gas_op + 1)) |> failed) + (err "Fail when consuming more than the remaining operation gas.") + +(** Test block gas exhaustion *) +let test_detect_gas_exhaustion_when_block_gas_hits_zero () = + let open Lwt_result_syntax in + let gas k = Gas_limit_repr.Arith.unsafe_fp (Z.of_int k) in + let remaining_gas = gas 100000 and too_much = gas (100000 + 1) in + let* context = make_context 100000 in + let* () = + fail_unless + (consume_gas_limit_in_block context remaining_gas |> succeed) + (err "Succeed when consuming exactly the remaining block gas.") + in + fail_unless + (consume_gas_limit_in_block context too_much |> failed) + (err "Fail when consuming more than the remaining block gas.") + +(** Test invalid gas limit. Should fail when limit is above the hard gas limit per + operation *) +let test_detect_gas_limit_consumption_above_hard_gas_operation_limit () = + let open Lwt_result_syntax in + let* context = dummy_context () in + fail_unless + (consume_gas_limit_in_block + context + (Gas_limit_repr.Arith.unsafe_fp (Z.of_int opg)) + |> failed) + (err + "Fail when consuming gas above the hard limit per operation in the \ + block.") + +(** For a given [context], check if its levels match those given in [block_level] and + [operation_level] *) +let check_context_levels context block_level operation_level = + let open Lwt_result_syntax in + let op_check = + match gas_level context with + | Unaccounted -> true + | Limited {remaining} -> + Gas_limit_repr.Arith.(unsafe_fp (Z.of_int operation_level) = remaining) + in + let block_check = + Gas_limit_repr.Arith.( + unsafe_fp (Z.of_int block_level) = block_gas_level context) + in + let* () = + fail_unless + (op_check || block_check) + (err "Unexpected block and operation gas levels") + in + let* () = fail_unless op_check (err "Unexpected operation gas level") in + fail_unless block_check (err "Unexpected block gas level") + +let monitor remaining_block_gas initial_operation_level consumed_gas () = + let open Lwt_result_syntax in + let op_limit = + Gas_limit_repr.Arith.unsafe_fp (Z.of_int initial_operation_level) + in + let* context = make_context remaining_block_gas in + let* context = consume_gas_limit_in_block_lwt context op_limit in + set_gas_limit context op_limit |> fun context -> + let* context = consume_gas_lwt context consumed_gas in + check_context_levels + context + (remaining_block_gas - initial_operation_level) + (initial_operation_level - consumed_gas) + +let test_monitor_gas_level = monitor 1000 100 10 + +(** Test cas consumption mode switching (limited -> unlimited) *) +let test_set_gas_unlimited () = + let open Lwt_result_syntax in + let init_block_gas = 100000 in + let op_limit_int = 10000 in + let op_limit = Gas_limit_repr.Arith.unsafe_fp (Z.of_int op_limit_int) in + let* context = make_context init_block_gas in + set_gas_limit context op_limit |> set_gas_unlimited |> fun context -> + let* context = consume_gas_lwt context opg in + check_context_levels context init_block_gas (-1) + +(** Test cas consumption mode switching (unlimited -> limited) *) +let test_set_gas_limited () = + let open Lwt_result_syntax in + let init_block_gas = 100000 in + let op_limit_int = 10000 in + let op_limit = Gas_limit_repr.Arith.unsafe_fp (Z.of_int op_limit_int) in + let op_gas = 100 in + let* context = make_context init_block_gas in + set_gas_unlimited context |> fun context -> + set_gas_limit context op_limit |> fun context -> + let* context = consume_gas_lwt context op_gas in + check_context_levels context init_block_gas (op_limit_int - op_gas) + +(*** Tests with blocks ***) + +let begin_validation_and_application ctxt chain_id mode ~predecessor = + let open Lwt_result_syntax in + let* validation_state = begin_validation ctxt chain_id mode ~predecessor in + let* application_state = begin_application ctxt chain_id mode ~predecessor in + return (validation_state, application_state) + +let validate_and_apply_operation (validation_state, application_state) op = + let open Lwt_result_syntax in + let oph = Alpha_context.Operation.hash_packed op in + let* validation_state = validate_operation validation_state oph op in + let* application_state, receipt = apply_operation application_state oph op in + return ((validation_state, application_state), receipt) + +let finalize_validation_and_application (validation_state, application_state) + shell_header = + let open Lwt_result_syntax in + let* () = finalize_validation validation_state in + finalize_application application_state shell_header + +let apply_with_gas header ?(operations = []) (pred : Block.t) = + let open Lwt_result_wrap_syntax in + let open Alpha_context in + let+@ context, consumed_gas = + let* vstate = + begin_validation_and_application + pred.context + Chain_id.zero + (Application header) + ~predecessor:pred.header.shell + in + let* vstate = + List.fold_left_es + (fun vstate op -> + let+ state, _result = validate_and_apply_operation vstate op in + state) + vstate + operations + in + let+ validation, result = + finalize_validation_and_application vstate (Some header.shell) + in + (validation.context, result.consumed_gas) + in + let hash = Block_header.hash header in + ( {Block.hash; header; operations; context; constants = pred.constants}, + consumed_gas ) + +let bake_with_gas ?policy ?timestamp ?operation ?operations pred = + let open Lwt_result_syntax in + let operations = + match (operation, operations) with + | Some op, Some ops -> Some (op :: ops) + | Some op, None -> Some [op] + | None, Some ops -> Some ops + | None, None -> None + in + let* header = Block.Forge.forge_header ?timestamp ?policy ?operations pred in + let* header = Block.Forge.sign_header header in + apply_with_gas header ?operations pred + +let check_consumed_gas consumed expected = + fail_unless + Alpha_context.Gas.Arith.(consumed = expected) + (err + (Format.asprintf + "Gas discrepancy: consumed gas : %a | expected : %a\n" + Alpha_context.Gas.Arith.pp + consumed + Alpha_context.Gas.Arith.pp + expected)) + +let lazy_unit = Alpha_context.Script.lazy_expr (Expr.from_string "Unit") + +let prepare_origination block source script = + let code = Expr.toplevel_from_string script in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_unit} + in + Op.contract_origination (B block) source ~script + +let originate_contract block source script = + let open Lwt_result_syntax in + let* operation, dst = prepare_origination block source script in + let* block = Block.bake ~operation block in + return (block, dst) + +let init_block n to_originate = + let open Lwt_result_syntax in + let* block, src_list = Context.init_n n ~consensus_threshold:0 () in + match src_list with + | [] -> assert false + | src :: _ -> + (*** originate contracts ***) + let rec full_originate block originated = function + | [] -> return (block, List.rev originated) + | h :: t -> + let* block, ct = originate_contract block src h in + full_originate block (ct :: originated) t + in + let* block, originated = full_originate block [] to_originate in + return (block, src_list, originated) + +let nil_contract = + "parameter unit;\n\ + storage unit;\n\ + code {\n\ + \ DROP;\n\ + \ UNIT; NIL operation; PAIR\n\ + \ }\n" + +let fail_contract = "parameter unit; storage unit; code { FAIL }" + +let loop_contract = + "parameter unit;\n\ + storage unit;\n\ + code {\n\ + \ DROP;\n\ + \ PUSH bool True;\n\ + \ LOOP {\n\ + \ PUSH string \"GASGASGAS\";\n\ + \ PACK;\n\ + \ SHA3;\n\ + \ DROP;\n\ + \ PUSH bool True\n\ + \ };\n\ + \ UNIT; NIL operation; PAIR\n\ + \ }\n" + +let block_with_one_origination n contract = + let open Lwt_result_syntax in + let* block, srcs, originated = init_block n [contract] in + match originated with [dst] -> return (block, srcs, dst) | _ -> assert false + +let full_block n () = + let open Lwt_result_syntax in + let* block, src_list, originated = + init_block n [nil_contract; fail_contract; loop_contract] + in + let dst_nil, dst_fail, dst_loop = + match originated with [c1; c2; c3] -> (c1, c2, c3) | _ -> assert false + in + return (block, src_list, dst_nil, dst_fail, dst_loop) + +(** Combine a list of operations into an operation list. Also returns + the sum of their gas limits.*) +let combine_operations_with_gas block list_dst = + let open Lwt_result_syntax in + let rec make_op_list src full_gas op_list = function + | [] -> return (src, full_gas, List.rev op_list) + | (src, dst, gas_limit) :: t -> + let* op = + Op.transaction + ~gas_limit:(Custom_gas gas_limit) + (B block) + src + dst + Alpha_context.Tez.zero + in + make_op_list + (Some src) + (Alpha_context.Gas.Arith.add full_gas gas_limit) + (op :: op_list) + t + in + let* src, full_gas, op_list = + make_op_list None Alpha_context.Gas.Arith.zero [] list_dst + in + match src with + | None -> assert false + | Some source -> + let* operation = + Op.batch_operations ~recompute_counters:true ~source (B block) op_list + in + return (operation, full_gas) + +(** Applies [combine_operations_with_gas] to lists in a list, then bake a block + with this list of operations. Also returns the sum of all gas limits *) +let bake_operations_with_gas block list_list_dst = + let open Lwt_result_syntax in + let rec make_list full_gas op_list = function + | [] -> return (full_gas, List.rev op_list) + | list_dst :: t -> + let* op, gas = combine_operations_with_gas block list_dst in + make_list (Alpha_context.Gas.Arith.add full_gas gas) (op :: op_list) t + in + let* gas_limit_total, operations = + make_list Alpha_context.Gas.Arith.zero [] list_list_dst + in + let* block, consumed_gas = bake_with_gas ~operations block in + return (block, consumed_gas, gas_limit_total) + +(* A sampler for gas limits, the returned value should always be high + enough to apply a simple manager operation but lower than the + operation gas limit. *) +let basic_gas_sampler () = + Alpha_context.Gas.Arith.integral_of_int_exn + (Michelson_v1_gas.Internal_for_tests.int_cost_of_manager_operation + 1000 + + Random.int 900) + +let generic_test_block_one_origination contract gas_sampler structure = + let open Lwt_result_syntax in + let sources_number = List.length structure in + let* block, src_list, dst = + block_with_one_origination sources_number contract + in + let lld = + List.mapi + (fun i t -> + match List.nth src_list i with + | None -> assert false + | Some src -> (List.map (fun _ -> (src, dst, gas_sampler ()))) t) + structure + in + let* _block, consumed_gas, gas_limit_total = + bake_operations_with_gas block lld + in + check_consumed_gas consumed_gas gas_limit_total + +let make_batch_test_block_one_origination name contract gas_sampler = + let test = generic_test_block_one_origination contract gas_sampler in + let test_one_operation () = test [[()]] in + let test_one_operation_list () = test [[(); (); ()]] in + let test_many_single_operations () = test [[()]; [()]; [()]] in + let test_mixed_operations () = test [[(); ()]; [()]; [(); (); ()]] in + let app_n = List.map (fun (x, y) -> (x ^ " with contract " ^ name, y)) in + app_n + [ + ("bake one operation", test_one_operation); + ("bake one operation list", test_one_operation_list); + ("multiple single operations", test_many_single_operations); + ("both lists and single operations", test_mixed_operations); + ] + +let hard_gas_limit_per_operation = 1_040_000 + +let hard_gas_limit_per_block = 1_733_333 + +(** Tests the consumption of all gas in a block, should pass *) +let test_consume_exactly_all_block_gas () = + let open Lwt_result_syntax in + let number_of_ops = 2 in + let* block, src_list, dst = + block_with_one_origination number_of_ops nil_contract + in + let lld = + List.mapi + (fun i src -> + [ + ( src, + dst, + Alpha_context.Gas.Arith.integral_of_int_exn + (if i = number_of_ops - 1 then + hard_gas_limit_per_block - hard_gas_limit_per_operation + else hard_gas_limit_per_operation) ); + ]) + src_list + in + let* _, _, _ = bake_operations_with_gas block lld in + return_unit + +(** Tests the consumption of more than the block gas level with many single + operations, should fail *) +let test_malformed_block_max_limit_reached () = + let open Lwt_result_syntax in + let number_of_ops = 2 in + let* block, src_list, dst = + block_with_one_origination number_of_ops nil_contract + in + let lld = + List.mapi + (fun i src -> + [ + ( src, + dst, + Alpha_context.Gas.Arith.integral_of_int_exn + (if i = number_of_ops - 1 then + hard_gas_limit_per_block - hard_gas_limit_per_operation + 1 + else hard_gas_limit_per_operation) ); + ]) + src_list + in + let*! result = bake_operations_with_gas block lld in + match result with + | Error _ -> return_unit + | Ok _ -> + tzfail + (err + "Invalid block: sum of operation gas limits exceeds hard gas limit \ + per block") + +(** Tests the consumption of more than the block gas level with one big + operation list, should fail *) +let test_malformed_block_max_limit_reached' () = + let open Lwt_result_syntax in + let number_of_ops = 2 in + let* block, src_list, dst = + block_with_one_origination number_of_ops nil_contract + in + let lld = + List.mapi + (fun i src -> + [ + ( src, + dst, + Alpha_context.Gas.Arith.integral_of_int_exn + (if i = number_of_ops - 1 then + hard_gas_limit_per_block - hard_gas_limit_per_operation + 1 + else hard_gas_limit_per_operation) ); + ]) + src_list + in + let*! result = bake_operations_with_gas block lld in + match result with + | Error _ -> return_unit + | Ok _ -> + tzfail + (err + "Invalid block: sum of gas limits in operation list exceeds hard \ + gas limit per block") + +let test_block_mixed_operations () = + let open Lwt_result_syntax in + let number_of_ops = 4 in + let* block, src_list, dst_nil, dst_fail, dst_loop = + full_block number_of_ops () + in + let l = [[dst_nil]; [dst_nil; dst_fail; dst_nil]; [dst_loop]; [dst_nil]] in + let*? lld = + List.map2 + ~when_different_lengths:[] + (fun src l -> (List.map (fun x -> (src, x, basic_gas_sampler ()))) l) + src_list + l + in + let* _block, consumed_gas, gas_limit_total = + bake_operations_with_gas block lld + in + check_consumed_gas consumed_gas gas_limit_total + +(** Test that emptying an account does not cost extra-gas *) +let test_emptying_account_gas () = + let open Lwt_result_syntax in + let open Alpha_context in + let* b, bootstrap = Context.init1 ~consensus_threshold:0 () in + let bootstrap_pkh = Context.Contract.pkh bootstrap in + let {Account.pkh; pk; _} = Account.new_account () in + let contract = Contract.Implicit pkh in + let amount = Test_tez.of_int 10 in + let* op1 = Op.transaction (B b) bootstrap contract amount in + let* b = Block.bake ~operation:op1 b in + let* op2 = Op.revelation ~fee:Tez.zero (B b) pk in + let* b = Block.bake ~operation:op2 b in + let gas_limit = Op.Low in + let* op = + Op.delegation ~fee:amount ~gas_limit (B b) contract (Some bootstrap_pkh) + in + let* i = Incremental.begin_construction b in + (* The delegation operation should be valid as the operation effect + would be to remove [contract] and should not generate any extra + gas cost. *) + let expect_apply_failure = function + | [Environment.Ecoproto_error (Storage_error (Raw_context.Missing_key _))] + -> + (* The delegation is expected to fail in the apply part as the + contract was emptied when fees were retrieved. *) + return_unit + | err -> failwith "got unexpected error: %a" pp_print_trace err + in + let* (_i : Incremental.t) = + Incremental.add_operation ~expect_apply_failure i op + in + return_unit + +let quick (what, how) = Tztest.tztest what `Quick how + +let tests = + List.map + quick + ([ + ( "Detect gas exhaustion in fresh context", + test_detect_gas_exhaustion_in_fresh_context ); + ( "Detect gas exhaustion when operation gas as hits zero", + test_detect_gas_exhaustion_when_operation_gas_hits_zero ); + ( "Detect gas exhaustion when block gas as hits zero", + test_detect_gas_exhaustion_when_block_gas_hits_zero ); + ( "Detect gas limit consumption when it is above the hard gas operation \ + limit", + test_detect_gas_limit_consumption_above_hard_gas_operation_limit ); + ( "Each new operation impacts block gas level, each gas consumption \ + impacts operation gas level", + test_monitor_gas_level ); + ( "Switches operation gas consumption from limited to unlimited", + test_set_gas_unlimited ); + ( "Switches operation gas consumption from unlimited to limited", + test_set_gas_limited ); + ( "Accepts a block that consumes all of its gas", + test_consume_exactly_all_block_gas ); + ( "Detect when the sum of all operation gas limits exceeds the hard gas \ + limit per block", + test_malformed_block_max_limit_reached ); + ( "Detect when gas limit of operation list exceeds the hard gas limit \ + per block", + test_malformed_block_max_limit_reached' ); + ("the gas consumption of various operations", test_block_mixed_operations); + ("emptying an account costs gas", test_emptying_account_gas); + ] + @ make_batch_test_block_one_origination "nil" nil_contract basic_gas_sampler + @ make_batch_test_block_one_origination + "fail" + fail_contract + basic_gas_sampler + @ make_batch_test_block_one_origination + "infinite loop" + loop_contract + basic_gas_sampler) + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("gas levels", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/big_interpreter_stack.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/big_interpreter_stack.tz new file mode 100644 index 000000000000..24832df0827f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/big_interpreter_stack.tz @@ -0,0 +1,5 @@ +{ parameter unit ; + storage unit ; + code { CAR ; + { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { {} ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; } ; + NIL operation; PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/emit.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/emit.tz new file mode 100644 index 000000000000..c8c2da0886d0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/emit.tz @@ -0,0 +1,16 @@ +parameter unit; +storage unit; +code { DROP ; + UNIT ; + PUSH string "right" ; + RIGHT nat ; + EMIT %tag1 ; + PUSH nat 2 ; + LEFT string ; + EMIT %tag2 (or (nat %int) (string %str)) ; + NIL operation ; + SWAP ; + CONS ; + SWAP ; + CONS ; + PAIR } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/fail_rec.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/fail_rec.tz new file mode 100644 index 000000000000..cac888664928 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/fail_rec.tz @@ -0,0 +1,8 @@ +{ parameter unit; + storage unit; + code { CAR; + LAMBDA_REC unit unit { }; + SWAP; + EXEC; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_CREATE_CONTRACT.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_CREATE_CONTRACT.tz new file mode 100644 index 000000000000..e3ee1fd0665a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_CREATE_CONTRACT.tz @@ -0,0 +1,24 @@ +# This contract uses CREATE_CONTRACT in a view, which is forbidden. +{ + storage unit ; + parameter unit ; + code { + CAR ; + NIL operation ; + PAIR + } ; + view "v" unit unit { + DROP ; + UNIT ; + PUSH mutez 5 ; + NONE key_hash ; + CREATE_CONTRACT { + storage unit ; + parameter unit ; + code { CAR ; NIL operation ; PAIR } + } ; + DROP ; + DROP ; + UNIT + } +} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SELF.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SELF.tz new file mode 100644 index 000000000000..79636452d4bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SELF.tz @@ -0,0 +1,11 @@ +# This contract uses SELF in a view, which is forbidden. +{ + storage unit ; + parameter unit ; + code { + CAR ; + NIL operation ; + PAIR + } ; + view "v" unit unit { DROP ; SELF ; DROP ; UNIT } +} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SET_DELEGATE.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SET_DELEGATE.tz new file mode 100644 index 000000000000..7e396e55dab1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_SET_DELEGATE.tz @@ -0,0 +1,11 @@ +# This contract uses SET_DELEGATE in a view, which is forbidden. +{ + storage unit ; + parameter unit ; + code { + CAR ; + NIL operation ; + PAIR + } ; + view "v" key_hash unit { CAR ; SOME ; SET_DELEGATE ; DROP ; UNIT } +} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_TRANSFER_TOKENS.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_TRANSFER_TOKENS.tz new file mode 100644 index 000000000000..e6adb07fd31b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/forbidden_op_in_view_TRANSFER_TOKENS.tz @@ -0,0 +1,12 @@ +# This contract uses TRANSFER_TOKENS in a view, which is forbidden. +{ + storage unit ; + parameter unit ; + code { + CAR ; + NIL operation ; + PAIR + } ; + view "v" (pair unit mutez (contract unit)) unit + { CAR ; UNPAPAIR ; TRANSFER_TOKENS ; DROP ; UNIT } +} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/int-store.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/int-store.tz new file mode 100644 index 000000000000..acd5104c042b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/int-store.tz @@ -0,0 +1,3 @@ +{ parameter unit ; + storage int ; + code { CDR ; NIL operation; PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/omega.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/omega.tz new file mode 100644 index 000000000000..52adfdf1facc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/omega.tz @@ -0,0 +1,9 @@ +{ parameter unit; + storage unit; + code { CAR; + LAMBDA_REC unit unit + { EXEC }; + SWAP; + EXEC; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact.tz new file mode 100644 index 000000000000..b3dd6402f440 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact.tz @@ -0,0 +1,19 @@ +{ parameter int; + storage int; + code { CAR ; + LAMBDA_REC int int + { DUP; + EQ; + IF { PUSH int 1 } + { DUP; + DUP 3; + PUSH int 1; + DUP 4; + SUB; + EXEC; + MUL}; + DIP { DROP 2 }}; + SWAP; + EXEC; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply.tz new file mode 100644 index 000000000000..85515df4cde8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply.tz @@ -0,0 +1,24 @@ + {parameter int; + storage int; + code { CAR ; + LAMBDA_REC (pair unit int) int + { UNPAIR; + DUP 2; + EQ; + IF { PUSH int 1 } + { DUP 2; + DUP 4; + DUP 3; + APPLY; + PUSH int 1; + DUP 3; + SUB; + EXEC; + MUL}; + DIP { DROP 3 }}; + UNIT; + APPLY; + SWAP; + EXEC; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply_store.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply_store.tz new file mode 100644 index 000000000000..8d38ed03bddb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_apply_store.tz @@ -0,0 +1,27 @@ +{ storage (or int (lambda int int)); + parameter (or (unit %gen) (int %exec)); + code { UNPAIR; + IF_LEFT{ DROP 2; + LAMBDA_REC (pair unit int) int + { UNPAIR; + DUP 2; + EQ; + IF { PUSH int 1 } + { DUP 2; + DUP 4; + DUP 3; + APPLY; + PUSH int 1; + DUP 3; + SUB; + EXEC; + MUL}; + DIP { DROP 3 }}; + UNIT; + APPLY; + RIGHT int} + { DIP { ASSERT_RIGHT }; + EXEC; + LEFT (lambda int int)}; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_store.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_store.tz new file mode 100644 index 000000000000..c4825db7f634 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/rec_fact_store.tz @@ -0,0 +1,22 @@ +{ storage (or int (lambda int int)); + parameter (or (unit %gen) (int %exec)); + code { UNPAIR; + IF_LEFT{ DROP 2; + LAMBDA_REC int int + { DUP; + EQ; + IF { PUSH int 1 } + { DUP; + DUP 3; + PUSH int 1; + DUP 4; + SUB; + EXEC; + MUL}; + DIP { DROP 2 }}; + RIGHT int} + { DIP { ASSERT_RIGHT }; + EXEC; + LEFT (lambda int int)}; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract.tz new file mode 100644 index 000000000000..0b9e2ff99264 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract.tz @@ -0,0 +1,73 @@ +# This contract manages a shielded pool with a 1 to 1 conversion with respect to +# the mutez, updated by a list of Sapling transactions. +# As a convention, all unshield transactions must contain in their `bound_data` +# field a Micheline encoded public_key_hash which is used as the recipient of +# the unshielded tez. + +storage (sapling_state 8); +parameter (list (sapling_transaction 8)); +code { # Stack manipulation + UNPAIR; + NIL operation; + SWAP; + DIP { SWAP}; + AMOUNT ; + SWAP ; + DIP {SWAP} ; + ITER { + # If the transaction is valid, the resulting stack contains the + # bound_data and balance of the transaction and the updated + # state. If the rest of the script goes well, this state + # will be the new state of the smart contract. + SAPLING_VERIFY_UPDATE; + # In the case of an invalid transaction, we stop. + ASSERT_SOME; + UNPAIR; + SWAP; + UNPAIR; + # Convert the balance in mutez, keeping the signed balance on top + # of the stack and the balance in mutez as the second element. + DUP; + DIP { ABS; # in case of negative balance i.e. shielding + PUSH mutez 1; + MUL; }; + # We have three cases now: unshielding, shielding and transfers. + # If the balance is strictly positive (i.e. unshielding), we send + # funds to the given address. + # If we can't unpack an address from the bound_data, we stop. + IFGT { + DIIP {UNPACK key_hash; + ASSERT_SOME; + IMPLICIT_ACCOUNT }; + SWAP; + # The tokens are transferred to the recipient. + DIP { UNIT; + TRANSFER_TOKENS; + SWAP; + DIP {CONS} ;}; + } + # If the balance is negative or 0 (i.e. shielding or transfer), + # we verify the amount transferred in the transaction is + # exactly the balance returned by verify_update. This enforces + # the conversion 1-1 between mutez and shielded token + # as the balance in mutez of the contract will always be + # the same as the number of tokens in the sapling_state. + # No operation is executed. + { + DIIP {SWAP}; + DIP {SWAP}; + SWAP; + SUB_MUTEZ; ASSERT_SOME; + # For a transfer or shield operation, we don't expect an + # implicit account in the `bound_data` field. + # If one is given, we fail as it might be an invalid + # operation or an erroneous call. + DIIP { SIZE; PUSH nat 0; ASSERT_CMPEQ; }; + SWAP; + }; + }; + DIP { + PUSH mutez 0; + ASSERT_CMPEQ;}; + SWAP; + PAIR} diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_double.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_double.tz new file mode 100644 index 000000000000..b826428db278 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_double.tz @@ -0,0 +1,27 @@ +storage (pair (sapling_state :left 8) (sapling_state :right 8) ); +parameter (pair bool (pair (sapling_transaction :left 8) (sapling_transaction :right 8)) ); +code { UNPAIR ; + UNPAIR ; + DIP {UNPAIR} ; + DIIIP {UNPAIR} ; + DIIP {SWAP} ; + IF { SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + CDR ; CDR ; + DIP {DIP {DUP}; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME ; + DROP;}; + } + { DIP { DUP}; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME; + DROP ; + DIP { SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + CDR ; CDR; + }}; + PAIR; + NIL operation; + PAIR; + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_drop.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_drop.tz new file mode 100644 index 000000000000..b4d4a3a56bc8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_drop.tz @@ -0,0 +1,13 @@ +storage (unit); +parameter (list (sapling_transaction 8)); +code { UNPAIR ; + SAPLING_EMPTY_STATE 8; + SWAP ; + ITER { SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + CDR ; CDR ; + } ; + DROP ; + NIL operation; + PAIR; + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_send.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_send.tz new file mode 100644 index 000000000000..43a6edba46ec --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_send.tz @@ -0,0 +1,20 @@ +storage (unit); +parameter (pair (contract (or (sapling_transaction 8) (sapling_state 8))) (sapling_transaction 8)); +code { UNPAIR ; + UNPAIR; + SWAP ; + SAPLING_EMPTY_STATE 8; + SWAP ; + SAPLING_VERIFY_UPDATE ; + ASSERT_SOME ; + CDR ; + CDR ; + PUSH mutez 0; + SWAP ; + RIGHT (sapling_transaction 8); + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + PAIR; + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_state_as_arg.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_state_as_arg.tz new file mode 100644 index 000000000000..e8a96df046ee --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_contract_state_as_arg.tz @@ -0,0 +1,18 @@ +storage (option (sapling_transaction 8)); +parameter (or (sapling_transaction 8) (sapling_state 8)); +code { UNPAIR ; + IF_LEFT + { + DIP {DROP;}; + SOME; + } + { DIP {ASSERT_SOME;}; + SWAP ; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME; + DROP ; + NONE (sapling_transaction 8) ; + }; + NIL operation; + PAIR; + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_push_sapling_state.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_push_sapling_state.tz new file mode 100644 index 000000000000..8d1db432bf2e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_push_sapling_state.tz @@ -0,0 +1,11 @@ +# Attempt to use `PUSH sapling_state 0` where 0 is the ID of a sapling state. +# sapling_state is not allowed in the instruction PUSH. +parameter unit; +storage unit; +code { DROP; + PUSH (sapling_state 8) 0; + DROP; + PUSH unit Unit; + NIL operation; + PAIR; + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_use_existing_state.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_use_existing_state.tz new file mode 100644 index 000000000000..bc8c46a28d87 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/sapling_use_existing_state.tz @@ -0,0 +1,12 @@ +parameter (pair (sapling_transaction 8) (sapling_state 8)); +storage (sapling_state 8); +code { UNPAIR; + UNPAIR; + DIIP { DROP }; + SAPLING_VERIFY_UPDATE; + ASSERT_SOME; + CDR; + CDR; + NIL operation; + PAIR; + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/temp_big_maps.tz b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/temp_big_maps.tz new file mode 100644 index 000000000000..0a9162f8f982 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/contracts/temp_big_maps.tz @@ -0,0 +1,81 @@ +# Testing passing/originating with big maps from different sources +# This contract is used by test_temp_big_maps.ml + +# The left member of the parameter is either: +# - (Left True) to use a fresh big map +# - (Left False) to use the stored big map +# - (Right bigmap) to use the passed big map + +# The right member of the parameter is used to decide between: +# - passing the argument (positive value) +# - doing nothing (zero) +# - originating (negative value) + +parameter (pair (or bool (big_map int int)) int); +storage (big_map int int); +code + { # parameter * storage :: [] + UNPAIR; # parameter :: storage :: [] + UNPAIR; # parameter.fst :: parameter.snd :: storage :: [] + DIP { SWAP }; # parameter.fst :: storage :: parameter.snd :: [] + IF_LEFT + { # parameter.fst.Left :: storage :: parameter.snd :: [] + IF + { # storage :: parameter.snd :: [] + DROP; # parameter.snd :: [] + EMPTY_BIG_MAP int int; # empty_big_map :: parameter.snd :: [] + PUSH (option int) (Some 2); # Some 2 :: empty_big_map :: parameter.snd :: [] + PUSH int 1; # 1 :: Some 2 :: empty_big_map :: parameter.snd :: [] + UPDATE; # big_map { 1 -> 2 } :: parameter.snd :: [] + } + { # stored_big_map :: parameter.snd :: [] + } + } + { # parameter.fst.Right :: storage :: parameter.snd :: [] + DIP { DROP } # passed_big_map :: parameter.snd :: [] + }; + DUP; # big_map :: big_map :: parameter.snd :: [] + DIG 2; # parameter.snd :: big_map :: big_map :: [] + DUP; # parameter.snd :: parameter.snd :: big_map :: big_map :: [] + IFGT + { # parameter.snd :: big_map :: big_map :: [] + PUSH int -1; + ADD; # parameter.snd - 1 :: big_map :: big_map :: [] + SWAP; # big_map :: parameter.snd - 1 :: big_map :: [] + RIGHT bool ; # Right big_map :: parameter.snd - 1 :: big_map :: [] + PAIR; # Right big_map * (parameter.snd - 1) :: big_map :: [] + DIP { SELF; PUSH mutez 0; }; # Right big_map * (parameter.snd - 1) :: 0 mutez :: self :: big_map :: [] + TRANSFER_TOKENS; # transfer_tokens :: big_map :: [] + NIL operation; # nil_operation :: transfer_tokens :: big_map :: [] + SWAP; # transfer_tokens :: nil_operation :: big_map :: [] + CONS # list operation :: big_map :: [] + } + { # parameter.snd :: big_map :: big_map :: [] + IFEQ + { # big_map :: big_map :: [] + DROP; # big_map :: [] + NIL operation; # list operation :: big_map :: [] + } + { # big_map :: big_map :: [] + PUSH mutez 0; # 0 mutez :: big_map :: big_map :: [] + NONE key_hash; # None key_hash :: 0 mutez :: big_map :: big_map :: [] + CREATE_CONTRACT + { + parameter unit; + storage (big_map int int); + code + { + UNPAIR; + DROP; + NIL operation; + PAIR + } + }; # create_contract :: address :: big_map :: [] + DIP { DROP }; # create_contract :: big_map :: [] + NIL operation; # nil_operation :: create_contract :: big_map :: [] + SWAP; # create_contract :: nil_operation :: big_map :: [] + CONS # list operation :: big_map :: [] + }; + }; + PAIR # (list operation * big_map) :: [] + } diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune new file mode 100644 index 000000000000..352e6faced36 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune @@ -0,0 +1,84 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name + src_proto_019_PtParisB_lib_protocol_test_integration_michelson_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-alcotezt + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.base-test-helpers + octez-protocol-019-PtParisB-libs.client + tezos-benchmark + octez-libs.micheline + tezos-benchmark-019-PtParisB + tezos-benchmark-type-inference-019-PtParisB + octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-019-PtParisB.parameters) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_019_PtParisB_test_helpers + -open Tezos_base_test_helpers + -open Tezos_client_019_PtParisB + -open Tezos_micheline + -open Tezos_benchmark_019_PtParisB + -open Tezos_benchmark_type_inference_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB) + (modules + test_annotations + test_block_time_instructions + test_contract_event + test_global_constants_storage + test_interpretation + test_lazy_storage_diff + test_patched_contracts + test_sapling + test_script_cache + test_script_typed_ir_size + test_temp_big_maps + test_ticket_accounting + test_ticket_balance_key + test_ticket_balance + test_ticket_lazy_storage_diff + test_ticket_manager + test_ticket_operations_diff + test_ticket_scanner + test_ticket_storage + test_ticket_direct_spending + test_typechecking + test_lambda_normalization)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_integration_michelson_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (deps + (glob_files contracts/*) + (glob_files patched_contracts/*) + (glob_files_rec ../../../../../../michelson_test_scripts/*)) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_annotations.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_annotations.ml new file mode 100644 index 000000000000..13d80f5b40e6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_annotations.ml @@ -0,0 +1,150 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Michelson annotations) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_annotations.ml + Subject: This module tests that Michelson annotations are properly handled. +*) + +open Protocol +open Alpha_context + +let type_with_annotations = + "(option :a (or :b (pair %c :d (int %e :f) (nat :g %h)) (bool %i :j)))" + +let contract_with_annotations = + Printf.sprintf + "{ parameter %s ;\n storage %s ;\n code { FAILWITH } }" + type_with_annotations + type_with_annotations + +let contract_factory_with_annotations = + Printf.sprintf + "{ parameter %s ;\n\ + \ storage (option address) ;\n\ + \ code { CAR ;\n\ + \ AMOUNT ;\n\ + \ NONE key_hash ;\n\ + \ CREATE_CONTRACT %s ;\n\ + \ DIP { SOME ;\n\ + \ NIL operation } ;\n\ + \ CONS ;\n\ + \ PAIR } }" + type_with_annotations + contract_with_annotations + +let lazy_none = Script.lazy_expr (Expr.from_string "None") + +let init_and_originate contract_code_string = + let open Lwt_result_syntax in + let* b, source = Context.init1 ~consensus_threshold:0 () in + let* inc = Incremental.begin_construction b in + let code = Expr.toplevel_from_string contract_code_string in + let script = Script.{code = lazy_expr code; storage = lazy_none} in + let* operation, addr = Op.contract_origination_hash (I inc) source ~script in + let+ inc = Incremental.add_operation inc operation in + (inc, source, addr) + +let assert_stored_script_equal inc addr expected_code_string = + let open Lwt_result_syntax in + let* stored_script = Context.Contract.script (I inc) addr in + Assert.equal_string + ~loc:__LOC__ + expected_code_string + (Expr.to_string stored_script) + +let get_address_from_storage inc factory_addr = + let open Lwt_result_wrap_syntax in + let* factory_storage = Context.Contract.storage (I inc) factory_addr in + let ctxt = Incremental.alpha_ctxt inc in + let*?@ option_address_t = Script_typed_ir.(option_t 0 address_t) in + let*! res = + Script_ir_translator.parse_data + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:false ()) + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + option_address_t + (Micheline.root factory_storage) + in + let*?@ factory_storage, _ctxt = res in + match factory_storage with + | Some {entrypoint; _} when not (Entrypoint.is_default entrypoint) -> + failwith "Did not expect non-default entrypoint" + | Some {destination = Contract (Implicit _); _} -> + failwith "Did not expect implict account" + | Some {destination = Contract (Originated addr); entrypoint = _it_is_default} + -> + return addr + | _ -> + failwith + "The factory contract should have stored the address of the originated \ + contract" + +(* Checks that [contract_with_annotations] once originated is stored as is. *) +let test_external_origination () = + let open Lwt_result_syntax in + let* inc, _source, addr = init_and_originate contract_with_annotations in + assert_stored_script_equal inc addr contract_with_annotations + +(* Checks that [contract_with_annotations] originated from + [contract_factory_with_annotations] is stored as is. *) +let test_internal_origination () = + let open Lwt_result_syntax in + let* inc, source, factory = + init_and_originate contract_factory_with_annotations + in + let* operation = + Op.transaction + (I inc) + source + (Contract.Originated factory) + ~parameters:lazy_none + Tez.zero + in + let* b = Incremental.finalize_block inc in + let* inc = Incremental.begin_construction b in + let* inc = Incremental.add_operation inc operation in + let* addr = get_address_from_storage inc factory in + assert_stored_script_equal inc addr contract_with_annotations + +let tests = + [ + Tztest.tztest + "External origination preserves annotations" + `Quick + test_external_origination; + Tztest.tztest + "Internal origination preserves annotations" + `Quick + test_internal_origination; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("annotations", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_block_time_instructions.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_block_time_instructions.ml new file mode 100644 index 000000000000..23448e118963 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_block_time_instructions.ml @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Michelson block-time instructions) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_block_time_instructions.ml + Subject: This module tests that Michelson instructions related to block time are correct. +*) + +open Tezos_protocol_020_PsParisC_parameters +open Protocol +open Alpha_context + +let context_with_constants constants = + let open Lwt_result_syntax in + let* block, _contracts = Context.init_with_constants1 constants in + let+ incremental = Incremental.begin_construction block in + Incremental.alpha_ctxt incremental + +let test_min_block_time () = + let open Lwt_result_syntax in + let* context = context_with_constants Default_parameters.constants_mainnet in + let* result, _ = + Contract_helpers.run_script + context + ~storage:"0" + ~parameter:"Unit" + {| { parameter unit; storage nat; code { DROP; MIN_BLOCK_TIME; NIL operation; PAIR } } |} + () + in + + let expected_value = + Default_parameters.constants_mainnet.minimal_block_delay + |> Period.to_seconds |> Z.of_int64 + in + + match Micheline.root result.storage with + | Int (_, result_storage) when Z.equal result_storage expected_value -> + return_unit + | _ -> + failwith + "Expected storage to be %a, but got %a" + Z.pp_print + expected_value + Micheline_printer.print_expr + (Micheline_printer.printable + Michelson_v1_primitives.string_of_prim + result.storage) + +let tests = + [ + Tztest.tztest + "MIN_BLOCK_TIME gives current minimal block delay" + `Quick + test_min_block_time; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("block time instructions", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_contract_event.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_contract_event.ml new file mode 100644 index 000000000000..2fb6fc85850f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_contract_event.ml @@ -0,0 +1,140 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Testing + ------- + Component: Protocol (event logging) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_contract_event.ml + Subject: This module tests that the event logs can be written to the receipt + in correct order and expected format. +*) + +(** Parse a Michelson contract from string. *) +let originate_contract file storage src b = + let open Lwt_result_syntax in + let load_file f = + let ic = open_in f in + let res = really_input_string ic (in_channel_length ic) in + close_in ic ; + res + in + let contract_string = load_file file in + let code = Expr.toplevel_from_string contract_string in + let storage = Expr.from_string storage in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + let* operation, dst = + Op.contract_origination (B b) src ~fee:(Test_tez.of_int 10) ~script + in + let* incr = Incremental.begin_construction b in + let* incr = Incremental.add_operation incr operation in + let+ b = Incremental.finalize_block incr in + (dst, b) + +let path = project_root // Filename.dirname __FILE__ + +(** Run emit.tz and assert that both the order of events and data content are correct *) +let contract_test () = + let open Lwt_result_syntax in + let* b, src = Context.init1 ~consensus_threshold:0 () in + let* dst, b = originate_contract (path // "contracts/emit.tz") "Unit" src b in + let fee = Test_tez.of_int 10 in + let parameters = Script.unit_parameter in + let* operation = + Op.transaction ~fee ~parameters (B b) src dst (Test_tez.of_int 0) + in + let* incr = Incremental.begin_construction b in + let* incr = Incremental.add_operation incr operation in + match Incremental.rev_tickets incr with + | [ + Operation_metadata + { + contents = + Single_result + (Manager_operation_result + { + internal_operation_results = + [ + Internal_operation_result + ( { + operation = + Event {tag = tag1; payload = data1; ty = ty1}; + _; + }, + Applied (IEvent_result _) ); + Internal_operation_result + ( { + operation = + Event {tag = tag2; payload = data2; ty = ty2}; + _; + }, + Applied (IEvent_result _) ); + ]; + _; + }); + }; + ] -> + let open Micheline in + ((match root data1 with + | Prim (_, D_Right, [String (_, "right")], _) -> () + | _ -> assert false) ; + + match root data2 with + | Prim (_, D_Left, [Int (_, n)], _) -> assert (Z.to_int n = 2) + | _ -> assert false) ; + assert (Entrypoint.to_string tag1 = "tag1") ; + assert (Entrypoint.to_string tag2 = "tag2") ; + (match root ty1 with + | Prim (_, T_or, [Prim (_, T_nat, [], []); Prim (_, T_string, [], [])], []) + -> + () + | _ -> assert false) ; + (match root ty2 with + | Prim + ( _, + T_or, + [Prim (_, T_nat, [], ["%int"]); Prim (_, T_string, [], ["%str"])], + [] ) -> + () + | _ -> assert false) ; + return_unit + | _ -> assert false + +let tests = + [ + Tztest.tztest + "contract emits event with correct data in proper order" + `Quick + contract_test; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("event logging", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_global_constants_storage.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_global_constants_storage.ml new file mode 100644 index 000000000000..b0ea0f4f00fc --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_global_constants_storage.ml @@ -0,0 +1,156 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context +open Transfers + +(** Testing + ------- + Component: Protocol (global table of constants) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_global_constants_storage.ml + Subject: This module tests that the global table of constants + can be written to and read from across blocks. +*) + +let get_next_context b = + let open Lwt_result_syntax in + let* b = Incremental.begin_construction b in + return (Incremental.alpha_ctxt b) + +let assert_proto_error_id loc id result = + let test err = + (Error_monad.find_info_of_error err).id + = "proto." ^ Protocol.name ^ "." ^ id + in + Assert.error ~loc result test + +let expr_to_hash expr = + let open Result_syntax in + let lexpr = Script_repr.lazy_expr @@ Expr.from_string expr in + let+ b = Script_repr.force_bytes lexpr in + Script_expr_hash.hash_bytes [b] + +(* This test has a long wind-up, but is very simple: it just asserts + that values written to the global table of constants persist across + blocks. *) +let get_happy_path () = + let open Lwt_result_wrap_syntax in + let* b, (alice, bob) = Context.init2 ~consensus_threshold:0 () in + let* b = Incremental.begin_construction b in + let expr_str = "Pair 3 7" in + let expr = Expr.from_string expr_str in + let*?@ hash = expr_to_hash expr_str in + let* op = + Op.register_global_constant + (I b) + ~source:alice + ~value:(Script_repr.lazy_expr expr) + in + let* b = Incremental.add_operation b op in + let* b = Incremental.finalize_block b in + let assert_unchanged b = + let* context = get_next_context b in + let*! result = Global_constants_storage.get context hash in + let*?@ _, result_expr = result in + let+ () = + Test_global_constants.assert_expr_equal __LOC__ expr result_expr + in + b + in + let* b = assert_unchanged b in + let do_many_transfers b = + let* b = Incremental.begin_construction b in + let* b = n_transactions 10 b alice bob (Tez.of_mutez_exn 1000L) in + let* b = Incremental.finalize_block b in + assert_unchanged b + in + let* (_ : Block.t) = + let* b = do_many_transfers b in + let* b = do_many_transfers b in + do_many_transfers b + in + return_unit + +(* Blocks that include a registration of a bad expression should + fail. *) +let test_registration_of_bad_expr_fails () = + let open Lwt_result_syntax in + let* b, alice = Context.init1 () in + let* b = Incremental.begin_construction b in + (* To produce the failure, we attempt to register an expression with + a malformed hash. *) + let expr = Expr.from_string "Pair 1 (constant \"foo\")" in + let* op = + Op.register_global_constant + (I b) + ~source:alice + ~value:(Script_repr.lazy_expr expr) + in + let*! result = Incremental.add_operation b op in + assert_proto_error_id __LOC__ "Badly_formed_constant_expression" result + +(* You cannot register the same expression twice. *) +let test_no_double_register () = + let open Lwt_result_syntax in + let* b, alice = Context.init1 ~consensus_threshold:0 () in + let expr = Expr.from_string "Pair 1 2" in + let* operation = + Op.register_global_constant + (B b) + ~source:alice + ~value:(Script_repr.lazy_expr expr) + in + let* b = Block.bake ~operation b in + (* Register the same expression again *) + let* op = + Op.register_global_constant + (B b) + ~source:alice + ~value:(Script_repr.lazy_expr expr) + in + let* i = Incremental.begin_construction b in + let*! result = Incremental.add_operation i op in + assert_proto_error_id __LOC__ "Expression_already_registered" result + +let tests = + [ + Tztest.tztest "Multiple blocks happy path" `Quick get_happy_path; + Tztest.tztest + "Bad register global operations fail when added to the block" + `Quick + test_registration_of_bad_expr_fails; + Tztest.tztest + "You cannot register the same expression twice." + `Quick + test_no_double_register; + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("global table of constants", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_interpretation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_interpretation.ml new file mode 100644 index 000000000000..117b013a40df --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_interpretation.ml @@ -0,0 +1,487 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (interpretation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_interpretation.ml + Subject: Interpretation of Michelson scripts +*) + +open Protocol +open Alpha_context +open Script_interpreter + +let test_context () = + let open Lwt_result_syntax in + let* b, _cs = Context.init3 () in + let* v = Incremental.begin_construction b in + return (Incremental.alpha_ctxt v) + +let logger = + Script_interpreter_logging.make + (module struct + let log_interp _ _ _ _ _ = () + + let log_entry _ _ _ _ _ = () + + let log_exit _ _ _ _ _ = () + + let log_control _ = () + + let get_log () = Lwt_result_syntax.return_none + end) + +let run_step ctxt code accu stack = + let open Lwt_result_syntax in + let open Script_interpreter in + let open Contract_helpers in + let* ((_, _, ctxt') as r) = + Internals.step_descr None ctxt default_step_constants code accu stack + in + let* _, _, ctxt'' = + Internals.step_descr + (Some logger) + ctxt + default_step_constants + code + accu + stack + in + if Gas.(remaining_operation_gas ctxt' <> remaining_operation_gas ctxt'') then + Alcotest.failf "Logging should not have an impact on gas consumption." ; + return r + +(** Runs a script with an ill-typed parameter and verifies that a + Bad_contract_parameter error is returned. *) +let test_bad_contract_parameter () = + let open Lwt_result_syntax in + let* ctx = test_context () in + (* Run script with a parameter of wrong type *) + let*! result = + Contract_helpers.run_script + ctx + "{parameter unit; storage unit; code { CAR; NIL operation; PAIR }}" + ~storage:"Unit" + ~parameter:"0" + () + in + match result with + | Ok _ -> Alcotest.fail "expected an error" + | Error (Environment.Ecoproto_error (Bad_contract_parameter source') :: _) -> + Alcotest.(check Testable.contract) + "incorrect field in Bad_contract_parameter" + (Contract.Originated Contract_helpers.default_self) + source' ; + return_unit + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace errs + +let test_multiplication_close_to_overflow_passes () = + let open Lwt_result_syntax in + let* ctx = test_context () in + (* Get sure that multiplication deals with numbers between 2^62 and + 2^63 without overflowing *) + let*! result = + Contract_helpers.run_script + ctx + "{parameter unit;storage unit;code {DROP; PUSH mutez \ + 2944023901536524477; PUSH nat 2; MUL; DROP; UNIT; NIL operation; PAIR}}" + ~storage:"Unit" + ~parameter:"Unit" + () + in + match result with + | Ok _ -> return_unit + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace errs + +let dummy_loc = -1 + +(** The purpose of these two tests is to check that the Michelson interpreter is + stack-safe (because it is tail-recursive). + + This requires to confront it to deep recursions, typically deeper than what + the gas limit allows. Unfortunately we cannot run the interpreter in + unaccounted gas mode because for efficiency it uses a custom gas management + that represents the gas counter as a mere integer. Instead we set the gas + counter to the highest possible value ([Saturation_repr.saturated]); with + the current gas costs and limits this enables more than a million recursive + calls which is larger than the stack size. *) + +let test_stack_overflow () = + let open Lwt_result_syntax in + let open Script_typed_ir in + let* ctxt = test_context () in + (* Set the gas counter to the maximum value *) + let ctxt = + Gas.update_remaining_operation_gas ctxt + @@ Gas.fp_of_milligas_int (Saturation_repr.saturated :> int) + in + let stack = Bot_t in + let descr kinstr = {kloc = 0; kbef = stack; kaft = stack; kinstr} in + let enorme_et_seq n = + let rec aux n acc = + if n = 0 then acc + else aux (n - 1) (IPush (dummy_loc, Bool_t, true, IDrop (dummy_loc, acc))) + in + aux n (IHalt dummy_loc) + in + let*! result = + run_step ctxt (descr (enorme_et_seq 1_000_000)) EmptyCell EmptyCell + in + match result with + | Ok _ -> return_unit + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + Alcotest.failf "Unexpected error (%s) at %s" trace_string __LOC__ + +(** The stack-safety of the interpreter relies a lot on the stack-safety of + Lwt.bind. This second test is similar to the previous one but uses an + instruction (IBig_map_mem) for which the interpreter calls Lwt.bind. *) + +let test_stack_overflow_in_lwt () = + let open Lwt_result_syntax in + let open Script_typed_ir in + let* ctxt = test_context () in + let ctxt = + Gas.update_remaining_operation_gas ctxt + @@ Gas.fp_of_milligas_int (Saturation_repr.saturated :> int) + in + let stack = Bot_t in + let descr kinstr = {kloc = 0; kbef = stack; kaft = stack; kinstr} in + let push_empty_big_map k = IEmpty_big_map (dummy_loc, unit_t, unit_t, k) in + let large_mem_seq n = + let rec aux n acc = + if n = 0 then acc + else + aux + (n - 1) + (IDup + ( dummy_loc, + IPush + ( dummy_loc, + Unit_t, + (), + IBig_map_mem (dummy_loc, IDrop (dummy_loc, acc)) ) )) + in + aux n (IDrop (dummy_loc, IHalt dummy_loc)) + in + let script = push_empty_big_map (large_mem_seq 1_000_000) in + let*! result = run_step ctxt (descr script) EmptyCell EmptyCell in + match result with + | Ok _ -> return_unit + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + Alcotest.failf "Unexpected error (%s) at %s" trace_string __LOC__ + +(** Test the encoding/decoding of script_interpreter.ml specific errors *) +let test_json_roundtrip name testable enc v = + let open Lwt_result_syntax in + let v' = + Data_encoding.Json.destruct enc (Data_encoding.Json.construct enc v) + in + Alcotest.check + testable + (Format.asprintf "round trip should not change value of %s" name) + v + v' ; + return_unit + +(** Encoding/decoding of script_interpreter.ml specific errors. *) +let test_json_roundtrip_err name e () = + test_json_roundtrip + name + Testable.protocol_error + Environment.Error_monad.error_encoding + e + +let error_encoding_tests = + let contract_zero = Contract.Implicit Signature.Public_key_hash.zero in + let script_expr_int = Micheline.strip_locations (Micheline.Int (0, Z.zero)) in + List.map + (fun (name, e) -> + Tztest.tztest + (Format.asprintf "test error encoding: %s" name) + `Quick + (test_json_roundtrip_err name e)) + [ + ("Reject", Reject (0, script_expr_int, None)); + ("Overflow", Overflow (0, None)); + ("Runtime_contract_error", Runtime_contract_error Contract_hash.zero); + ("Bad_contract_parameter", Bad_contract_parameter contract_zero); + ("Cannot_serialize_failure", Cannot_serialize_failure); + ("Cannot_serialize_storage", Cannot_serialize_storage); + ] + +module Test_map_instr_on_options = struct + type storage = {prev : int option; total : int} + + (* storage: (last input * total); param replaces the last input and + if some – gets added to the total. *) + let test_map_option_script = + {| { parameter (option int); + storage (pair (option int) int); + code { + UNPAIR ; + DIP { CDR } ; + MAP { + DUP ; + DIP { ADD } ; + } ; + PAIR ; + NIL operation ; + PAIR ; + } + } |} + + let run_test_map_opt_script param {prev; total} = + let open Lwt_result_syntax in + let storage = + Option.fold + ~none:(Format.sprintf "Pair None %d" total) + ~some:(fun p -> Format.sprintf "Pair (Some %d) %d" p total) + prev + in + let parameter = + Option.fold ~none:"None" ~some:(Format.sprintf "Some %d") param + in + let* ctxt = test_context () in + Contract_helpers.run_script + ctxt + test_map_option_script + ~storage + ~parameter + () + + let assume_storage_shape = + let open Micheline in + let open Michelson_v1_primitives in + function + | Prim (_, D_Pair, [Prim (_, D_None, [], _); Int (_, total)], _) -> + {prev = None; total = Z.to_int total} + | Prim (_, D_Pair, [Prim (_, D_Some, [Int (_, prev)], _); Int (_, total)], _) + -> + {prev = Some (Z.to_int prev); total = Z.to_int total} + | _ -> QCheck2.assume_fail () + + let assertions storage_before storage_after = + let open Lwt_result_syntax in + function + | None -> + let* () = + Assert.is_none ~loc:__LOC__ ~pp:Format.pp_print_int storage_after.prev + in + Assert.equal_int ~loc:__LOC__ storage_before.total storage_after.total + | Some input -> + let* prev_aft = Assert.get_some ~loc:__LOC__ storage_after.prev in + let* () = Assert.equal_int ~loc:__LOC__ input prev_aft in + Assert.equal_int + ~loc:__LOC__ + (storage_before.total + input) + storage_after.total + + let test_mapping (input, prev, total) = + let open Lwt_result_syntax in + let storage_before = {prev; total} in + let* {storage; _}, _ = run_test_map_opt_script input storage_before in + let new_storage = assume_storage_shape (Micheline.root storage) in + assertions storage_before new_storage input +end + +let test_contract path storage param ~entrypoint_str ~ok ~ko = + let open Lwt_result_syntax in + let entrypoint = + match entrypoint_str with + | None -> Entrypoint.default + | Some str -> Entrypoint.of_string_strict_exn str + in + let* ctx = test_context () in + let read_file filename = + let ch = open_in filename in + let s = really_input_string ch (in_channel_length ch) in + close_in ch ; + s + in + let script = read_file path in + let*! result = + Contract_helpers.run_script + ctx + script + ~storage + ~parameter:param + ~entrypoint + () + in + match result with Ok (res, _) -> ok res | Error t -> ko t + +let fail_with_trace trace = + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace trace + +let test_contract_success path storage param expected_storage_str + ?entrypoint_str () = + let open Lwt_result_syntax in + let expected_storage = Expr.from_string expected_storage_str in + test_contract + path + storage + param + ~ok:(fun real -> + if real.storage = expected_storage then return_unit + else Alcotest.fail "Unexpected result") + ~ko:fail_with_trace + ~entrypoint_str + +let test_contract_fail path storage param ?entrypoint_str () = + let open Lwt_result_syntax in + test_contract + path + storage + param + ~ok:(fun _ -> + Alcotest.failf + "Unexpected success: interpreting %s should have failed." + path) + ~ko:(fun _ -> return_unit) + ~entrypoint_str + +let test_store_and_reload path ~init_storage ~entrypoint_str_1 ~param_1 + ~expected_storage_str_1 ~entrypoint_str_2 ~param_2 ~expected_storage_str_2 + () = + let expected_storage_1 = Expr.from_string expected_storage_str_1 in + test_contract + path + init_storage + param_1 + ~entrypoint_str:(Some entrypoint_str_1) + ~ok:(fun real -> + if real.storage = expected_storage_1 then + test_contract_success + path + expected_storage_str_1 + param_2 + expected_storage_str_2 + ~entrypoint_str:entrypoint_str_2 + () + else + Alcotest.failf + "Unexpected result. \n Expected :\n %s \n Real : \n %s \n" + (Expr.to_string expected_storage_1) + (Expr.to_string real.storage)) + ~ko:fail_with_trace + +let path = project_root // Filename.dirname __FILE__ + +let tests = + [ + Tztest.tztest "bad contract error" `Quick test_bad_contract_parameter; + Tztest.tztest "check robustness overflow error" `Slow test_stack_overflow; + Tztest.tztest + "check robustness overflow error in lwt" + `Slow + test_stack_overflow_in_lwt; + Tztest.tztest + "multiplication no illegitimate overflow" + `Quick + test_multiplication_close_to_overflow_passes; + Tztest.tztest "stack overflow error" `Slow test_stack_overflow; + Tztest.tztest_qcheck2 + ~name:"map instr against options" + QCheck2.Gen.( + triple (opt small_signed_int) (opt small_signed_int) small_signed_int) + Test_map_instr_on_options.test_mapping; + Tztest.tztest + "lambda_rec instruction" + `Quick + (test_contract_success (path // "contracts/rec_fact.tz") "0" "5" "120"); + Tztest.tztest + "lambda_rec instruction with apply" + `Quick + (test_contract_success + (path // "contracts/rec_fact_apply.tz") + "0" + "5" + "120"); + Tztest.tztest + "lambda_rec instruction with an infinite recursion" + `Quick + (test_contract_fail (path // "contracts/omega.tz") "Unit" "Unit"); + Tztest.tztest + "lambda_rec instruction storage" + `Quick + (test_store_and_reload + (path // "contracts/rec_fact_store.tz") + ~init_storage:"Left 0" + ~entrypoint_str_1:"gen" + ~param_1:"Unit" + ~expected_storage_str_1: + {|Right + (Lambda_rec + { DUP ; + EQ ; + IF { PUSH int 1 } { DUP ; DUP 3 ; PUSH int 1 ; DUP 4 ; SUB + ; EXEC ; MUL } ; + DIP { DROP 2 } })|} + ~entrypoint_str_2:"exec" + ~param_2:"5" + ~expected_storage_str_2:"Left 120"); + Tztest.tztest + "lambda_rec instruction storage apply store" + `Quick + (test_store_and_reload + (path // "contracts/rec_fact_apply_store.tz") + ~init_storage:"Left 0" + ~entrypoint_str_1:"gen" + ~param_1:"Unit" + ~expected_storage_str_1: + {|Right + { PUSH unit Unit ; + PAIR ; + LAMBDA_REC + (pair unit int) + int + { UNPAIR ; + DUP 2 ; + EQ ; + IF { PUSH int 1 } + { DUP 2 ; DUP 4 ; DUP 3 ; APPLY ; PUSH int 1 ; DUP 3 ; + SUB ; EXEC ; MUL } ; + DIP { DROP 3 } } ; + SWAP ; + EXEC }|} + ~entrypoint_str_2:"exec" + ~param_2:"5" + ~expected_storage_str_2:"Left 120"); + ] + @ error_encoding_tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("interpretation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lambda_normalization.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lambda_normalization.ml new file mode 100644 index 000000000000..1c126a775db0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lambda_normalization.ml @@ -0,0 +1,244 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Michelson) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_lambda_normalization.ml + Subject: Test that lambdas are normalized to optimized format at elaboration +*) + +open Protocol +open Alpha_context +open Script_typed_ir + +let new_ctxt () = + let open Lwt_result_wrap_syntax in + let* block, _contract = Context.init1 () in + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + +let parse_and_project (ty : ((_, _) lambda, _) ty) (node : Script.node) = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + let elab_conf = Script_ir_translator_config.make ~legacy:false () in + let*@ lam, _ctxt = + Script_ir_translator.parse_data + ~elab_conf + ctxt + ~allow_forged_tickets:false + ~allow_forged_lazy_storage_id:false + ty + node + in + match lam with + | Lam (_kdescr, node) -> return node + | LamRec (_kdescr, node) -> + return + Micheline.( + Prim (dummy_location, Michelson_v1_primitives.D_Lambda_rec, [node], [])) + +let node_of_string str = + let open Lwt_result_wrap_syntax in + let*? parsed = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_expression ~check:false str + in + return @@ Micheline.root parsed.expanded + +let node_to_string node = + Format.asprintf + "%a" + Micheline_printer.print_expr + ((Micheline_printer.printable Michelson_v1_primitives.string_of_prim) + (Micheline.strip_locations node)) + +let assert_lambda_normalizes_to ~loc ty str expected = + let open Lwt_result_wrap_syntax in + let* node = node_of_string str in + let* node_normalized = parse_and_project ty node in + let str_normalized = node_to_string node_normalized in + let* expected_node = node_of_string expected in + let expected = node_to_string expected_node in + Assert.equal_string ~loc expected str_normalized + +let assert_normalizes_to ~loc ty str expected = + let open Lwt_result_wrap_syntax in + let* () = assert_lambda_normalizes_to ~loc ty str expected in + let* () = + assert_lambda_normalizes_to + ~loc + ty + ("Lambda_rec " ^ str) + ("Lambda_rec " ^ expected) + in + return_unit + +let test_lambda_normalization () = + let open Lwt_result_wrap_syntax in + let*?@ ty = + Script_typed_ir.(lambda_t Micheline.dummy_location unit_t never_t) + in + let*?@ lam_unit_unit = + Script_typed_ir.(lambda_t Micheline.dummy_location unit_t unit_t) + in + let* () = + (* Empty sequence normalizes to itself. *) + assert_lambda_normalizes_to ~loc:__LOC__ lam_unit_unit "{}" "{}" + in + let* () = + (* Another example normalizing to itself. *) + assert_normalizes_to ~loc:__LOC__ ty "{FAILWITH}" "{FAILWITH}" + in + let* () = + (* Readable address normalizes to optimized. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; FAILWITH}|} + {|{PUSH address 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78; FAILWITH}|} + in + let* () = + (* Binary pair normalizes to itself. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH (pair nat nat) (Pair 0 0); FAILWITH}|} + {|{PUSH (pair nat nat) (Pair 0 0); FAILWITH}|} + in + let* () = + (* Ternary pair normalizes to nested binary pairs. Type is unchanged. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH (pair nat nat nat) (Pair 0 0 0); FAILWITH}|} + {|{PUSH (pair nat nat nat) (Pair 0 (Pair 0 0)); FAILWITH}|} + in + let* () = + (* Same with nested pairs in type. Type is still unchanged. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH (pair nat (pair nat nat)) (Pair 0 0 0); FAILWITH}|} + {|{PUSH (pair nat (pair nat nat)) (Pair 0 (Pair 0 0)); FAILWITH}|} + in + let* () = + (* Quadrary pair normalizes to sequence. Type is unchanged. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH (pair nat nat nat nat) (Pair 0 0 0 0); FAILWITH}|} + {|{PUSH (pair nat nat nat nat) {0; 0; 0; 0}; FAILWITH}|} + in + let* () = + (* Code inside LAMBDA is normalized too. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{LAMBDA unit never + {PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; FAILWITH}; + FAILWITH}|} + {|{LAMBDA unit never + {PUSH address 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78; FAILWITH}; + FAILWITH}|} + in + let* () = + (* Same with LAMBDA replaced by PUSH. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH (lambda unit never) + {PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; FAILWITH}; + FAILWITH}|} + {|{PUSH (lambda unit never) + {PUSH address 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78; FAILWITH}; + FAILWITH}|} + in + let* () = + (* Code inside LAMBDA_REC is normalized too. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{LAMBDA_REC unit never + {PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; + FAILWITH}; + FAILWITH}|} + {|{LAMBDA_REC unit never + {PUSH address 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78; + FAILWITH}; + FAILWITH}|} + in + let* () = + (* Same with LAMBDA_REC replaced by PUSH. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH (lambda unit never) + (Lambda_rec + {PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; + FAILWITH}); + FAILWITH}|} + {|{PUSH (lambda unit never) + (Lambda_rec + {PUSH address 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78; + FAILWITH}); + FAILWITH}|} + in + let* () = + (* Code inside CREATE_CONTRACT is normalized too. *) + assert_normalizes_to + ~loc:__LOC__ + ty + {|{PUSH mutez 0; + NONE key_hash; + CREATE_CONTRACT + {parameter unit; + storage unit; + code { PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"; FAILWITH}}; + DROP; + FAILWITH}|} + {|{PUSH mutez 0; + NONE key_hash; + CREATE_CONTRACT + {parameter unit; + storage unit; + code { PUSH address 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78; FAILWITH}}; + DROP; + FAILWITH}|} + in + return_unit + +let tests = + [ + Tztest.tztest + "lambdas are normalized to optimized format during elaboration" + `Quick + test_lambda_normalization; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("lambda normalization", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lazy_storage_diff.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lazy_storage_diff.ml new file mode 100644 index 000000000000..639736259150 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_lazy_storage_diff.ml @@ -0,0 +1,153 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Michelson) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_lazy_storage_diff.ml + Subject: Test lazy storage +*) + +open Protocol + +(** Generation of input data *) + +let ids = + [|1; 42; 1337; 1984|] |> Array.map Z.of_int + |> Array.map Lazy_storage_kind.Big_map.Id.parse_z + +let strs = [|"0"; "True"; "nat"; "bool"|] + +let exprs = strs |> Array.map Expr.from_string + +let hashes = + strs |> Array.map (fun x -> [x]) |> Array.map Script_expr_hash.hash_string + +let updates_len_existing = [1; 2; 3] + +let updates_len_other = 0 :: updates_len_existing + +let gen_inits idx : + (( Lazy_storage_kind.Big_map.Id.t, + Lazy_storage_kind.Big_map.alloc ) + Lazy_storage_diff.init + * int list) + list = + [ + (Existing, updates_len_existing); + (Copy {src = ids.(idx - 1)}, updates_len_other); + ( Alloc {key_type = exprs.(idx); value_type = exprs.(idx - 1)}, + updates_len_other ); + ] + +let gen_update_list idx : Lazy_storage_kind.Big_map.update list = + [None; Some exprs.(idx)] + |> List.map (fun value -> + Lazy_storage_kind.Big_map. + {key = exprs.(idx); key_hash = hashes.(idx); value}) + +let rec gen_updates updates_len : Lazy_storage_kind.Big_map.updates list = + if updates_len = 0 then [] + else + gen_updates (updates_len - 1) + |> List.map (fun suffix -> + gen_update_list updates_len + |> List.map (fun prefix -> prefix :: suffix)) + |> List.flatten + +let gen_updates_list updates_lens : Lazy_storage_kind.Big_map.updates list = + updates_lens |> List.map gen_updates |> List.flatten + +let gen_diffs idx : + ( Lazy_storage_kind.Big_map.Id.t, + Lazy_storage_kind.Big_map.alloc, + Lazy_storage_kind.Big_map.updates ) + Lazy_storage_diff.diff + list = + let open Lazy_storage_diff in + Remove + :: (gen_inits idx + |> List.map (fun (init, updates_lens) -> + gen_updates_list updates_lens + |> List.map (fun updates -> Update {init; updates})) + |> List.flatten) + +let gen_diffs_items idx : Lazy_storage_diff.diffs_item list = + let id = ids.(idx) in + gen_diffs idx |> List.map (fun diff -> Lazy_storage_diff.make Big_map id diff) + +let rec gen_diffs_list len : Lazy_storage_diff.diffs list = + if len = 0 then [] + else + gen_diffs_list (len - 1) + |> List.map (fun suffix -> + gen_diffs_items len |> List.map (fun prefix -> prefix :: suffix)) + |> List.flatten + +let diffs_list_lens = [0; 1; 2; 3] + +let diffs_list : Lazy_storage_diff.diffs list = + diffs_list_lens |> List.map gen_diffs_list |> List.flatten + +(** Properties to check *) + +let conversion_roundtrip lazy_storage_diff = + let legacy_big_map_diff = + Contract_storage.Legacy_big_map_diff.of_lazy_storage_diff lazy_storage_diff + in + let reconverted = + Contract_storage.Legacy_big_map_diff.to_lazy_storage_diff + legacy_big_map_diff + in + assert (Stdlib.( = ) reconverted lazy_storage_diff) + +let encoding_roundtrip lazy_storage_diff = + let encoded = + Data_encoding.Binary.to_bytes_exn + Lazy_storage_diff.encoding + lazy_storage_diff + in + match Data_encoding.Binary.of_bytes Lazy_storage_diff.encoding encoded with + | Ok decoded -> assert (Stdlib.( = ) decoded lazy_storage_diff) + | Error _ -> Stdlib.failwith "Decoding failed" + +(** Iterator and test definitions *) + +let on_diffs f () = + let open Lwt_result_syntax in + List.iter f diffs_list ; + return_unit + +(* Marked Slow because they take 5 to 10 seconds and are unlikely to change *) +let tests = + [ + Tztest.tztest "conversion roundtrip" `Slow (on_diffs conversion_roundtrip); + Tztest.tztest "encoding roundtrip" `Slow (on_diffs encoding_roundtrip); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("lazy storage diff", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_patched_contracts.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_patched_contracts.ml new file mode 100644 index 000000000000..e4d4acfaedb4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_patched_contracts.ml @@ -0,0 +1,221 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Migration (patched scripts) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_patched_contracts.ml + Subject: Migration +*) + +open Tezos_micheline +open Protocol + +module type LEGACY_SCRIPT_PATCHES = sig + type t + + val script_hash : t -> Script_expr_hash.t + + val code : t -> Michelson_v1_primitives.prim Micheline.canonical + + val patches : t list +end + +module type LEGACY_PATCH_TESTS = sig + type t + + val tests : t -> unit Alcotest_lwt.test_case list +end + +let script_hash_testable = + Alcotest.testable Script_expr_hash.pp Script_expr_hash.equal + +(** This functor provides testing for legacy script patches. Patches to + be tested should be placed in a module conformal to the signature + [LEGACY_SCRIPT_PATCHES]. It should contain a list of patches and for + each patch it has to provide a hash of the patched contract and the + new code (as binary-encoded Micheline). + + Additionally for each patch 3 files need to be placed in + [patched_contracts] subdirectory: + * script_hash.original.tz – containing the original version of the + script; + * script_hash.patched.tz - containing the patched version; + * script_hash.diff - containing the diff between the two. + + These files are there so that reviewers of the migration can easily + see what changes are made to each contract and these tests make sure + that the patched code supplied in file is identical to the one + included in the migration; and that the diff is correct. *) +module Legacy_patch_test (Patches : LEGACY_SCRIPT_PATCHES) : + LEGACY_PATCH_TESTS with type t = Patches.t = struct + type t = Patches.t + + let readable_micheline m = + let open Micheline in + map_node (fun _ -> ()) Michelson_v1_primitives.string_of_prim (root m) + + let path = project_root // Filename.dirname __FILE__ + + let contract_path ?(ext = "patched.tz") hash = + Filename.concat "patched_contracts" + @@ Format.asprintf "%a.%s" Script_expr_hash.pp hash ext + + let read_file ?ext hash = + let filename = path // contract_path ?ext hash in + Lwt_io.(with_file ~mode:Input filename read) + + (* Test that the hashes of the scripts in ./patched_contract/.original.tz + match hashes of the contracts being updated by the migration. *) + let test_original_contract legacy_script_hash () = + let open Lwt_result_syntax in + let*! code = read_file ~ext:"original.tz" legacy_script_hash in + let michelson = Michelson_v1_parser.parse_toplevel ~check:true code in + let*? prog = Micheline_parser.no_parsing_error michelson in + let bytes = + Data_encoding.Binary.to_bytes_exn + Alpha_context.Script.expr_encoding + prog.expanded + in + Alcotest.check + script_hash_testable + "Expr hash doesn't match" + legacy_script_hash + (Script_expr_hash.hash_bytes [bytes]) ; + return_unit + + (* Test that the binary-encoded versions of the patched contracts used during the + migration correspond to the content of the `./patched_contracts/.tz` + files *) + let test_patched_contract patch () = + let open Lwt_result_syntax in + let*! expected_michelson = read_file @@ Patches.script_hash patch in + let*? program = + Micheline_parser.no_parsing_error + @@ Michelson_v1_parser.parse_toplevel ~check:true expected_michelson + in + match + Micheline_diff.diff + ~prev:(readable_micheline @@ Patches.code patch) + ~current:(readable_micheline program.expanded) + () + with + | Some diff -> + let msg = + Format.asprintf + "Patched code for %a different than expected!\n%a" + Script_expr_hash.pp + (Patches.script_hash patch) + Micheline_printer.print_expr + diff + in + Alcotest.fail msg + | None -> return_unit + + (* Test that the diff files `./patched_contracts/.diff` + are the results of the `diff` command on the corresponding + original and patched files *) + let verify_diff legacy_script_hash () = + let open Lwt_result_syntax in + let*! expected_diff = read_file ~ext:"diff" legacy_script_hash in + let original_code = contract_path ~ext:"original.tz" legacy_script_hash in + (* The other test asserts that this is indeed the patched code. *) + let current_code = contract_path ~ext:"patched.tz" legacy_script_hash in + let diff_cmd = + ( "", + [| + "diff"; + "-u"; + "--label"; + original_code; + "--label"; + current_code; + original_code; + current_code; + |] ) + in + let*! actual_diff = Lwt_process.pread ~cwd:path diff_cmd in + Alcotest.(check string) "same diff" expected_diff actual_diff ; + return_unit + + let typecheck_patched_script code () = + let open Lwt_result_wrap_syntax in + (* Number 3 below controls how many accounts should be + created. This number shouldn't be too small or the context + won't have enough at least [minimal_stake] tokens. *) + let* block, _contracts = Context.init3 () in + let* inc = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt inc in + let*@ _code, _ctxt = + Script_ir_translator.parse_code + ~elab_conf:Script_ir_translator_config.(make ~legacy:false ()) + ~code:(Script_repr.lazy_expr code) + ctxt + in + return_unit + + let tests (patch : Patches.t) = + let script_hash = Patches.script_hash patch in + [ + Tztest.tztest + (Format.asprintf + "check original contract hash %a" + Script_expr_hash.pp + script_hash) + `Quick + (test_original_contract script_hash); + Tztest.tztest + (Format.asprintf + "check patched contract %a" + Script_expr_hash.pp + script_hash) + `Quick + (test_patched_contract patch); + Tztest.tztest + (Format.asprintf "verify patch for %a" Script_expr_hash.pp script_hash) + `Quick + (verify_diff script_hash); + Tztest.tztest + (Format.asprintf "type check %a" Script_expr_hash.pp script_hash) + `Quick + (typecheck_patched_script @@ Patches.code patch); + ] +end + +(* List modules containing patched scripts here: *) +let test_modules : (module LEGACY_SCRIPT_PATCHES) list = + [(module Legacy_script_patches)] + +let tests = + List.concat_map + (fun (module Patches : LEGACY_SCRIPT_PATCHES) -> + let module Test = Legacy_patch_test (Patches) in + List.concat_map Test.tests Patches.patches) + test_modules + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("patched contracts", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_sapling.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_sapling.ml new file mode 100644 index 000000000000..95a9df666085 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_sapling.ml @@ -0,0 +1,1331 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Sapling) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_sapling.ml + Subject: On the privacy-preserving library Sapling +*) + +open Protocol +open Alpha_context +open Test_tez + +module Raw_context_tests = struct + open Sapling_helpers.Common + + (* This test adds to the first 100 positions in the commitments tree the + constant value `uncommitted` for which we know the corresponding root and + tests that the returned root is as expected. *) + let commitments_add_uncommitted () = + let open Lwt_result_wrap_syntax in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let module H = Tezos_sapling.Core.Client.Hash in + let cm = H.uncommitted ~height:0 in + let expected_root = H.uncommitted ~height:32 in + let*@ ctx, id = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id ~memo_size:0 in + let* (_ctx : Raw_context.t) = + List.fold_left_es + (fun ctx pos -> + let*@ ctx, root = Sapling_storage.Commitments.get_root ctx id in + assert (root = expected_root) ; + let*@ ctx, _size = + Sapling_storage.Commitments.add + ctx + id + [H.to_commitment cm] + (Int64.of_int pos) + in + let+@ ctx, root = Sapling_storage.Commitments.get_root ctx id in + assert (root = expected_root) ; + ctx) + ctx + (0 -- 99) + in + return_unit + + (* Nullifiers don't check for duplicates are it's done by verify_update, + however committing to disk twice the same nf causes a storage error by + trying to initialize the same key twice. *) + let nullifier_double () = + let open Lwt_result_wrap_syntax in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ ctx, id = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id ~memo_size:0 in + let nf = gen_nf () in + let open Sapling_storage in + let state = + {id = Some id; diff = Sapling_storage.empty_diff; memo_size = 0} + in + let state = nullifiers_add state nf in + let state = nullifiers_add state nf in + assert (Compare.List_length_with.(state.diff.nullifiers = 2)) ; + let*@ disk_size = Sapling_storage.Nullifiers.size ctx id in + assert (disk_size = 0L) ; + Sapling_storage.apply_diff ctx id state.diff |> assert_error + + (* In this test we add two lists of nullifiers to the state, one is applied to + the context (committed to disk) and one is kept in kept in a diff (only in + memory). We then check that nullifier_mem answers true for those two lists + and false for a third one. *) + let nullifier_test () = + let open Lwt_result_wrap_syntax in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ ctx, id = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id ~memo_size:0 in + let nf_list_ctx = + WithExceptions.List.init ~loc:__LOC__ 10 (fun _ -> gen_nf ()) + in + let state = + List.fold_left + (fun state nf -> Sapling_storage.nullifiers_add state nf) + {id = Some id; diff = Sapling_storage.empty_diff; memo_size = 0} + nf_list_ctx + in + let*@ ctx, _ = Sapling_storage.apply_diff ctx id state.diff in + let nf_list_diff = + WithExceptions.List.init ~loc:__LOC__ 10 (fun _ -> gen_nf ()) + in + let state = + List.fold_left + (fun state nf -> Sapling_storage.nullifiers_add state nf) + state + nf_list_diff + in + let* () = + List.iter_ep + (fun nf -> + let*@ _ctx, bool = Sapling_storage.nullifiers_mem ctx state nf in + assert bool ; + return_unit) + (nf_list_ctx @ nf_list_diff) + in + let nf_list_absent = + WithExceptions.List.init ~loc:__LOC__ 10 (fun _ -> gen_nf ()) + in + List.iter_ep + (fun nf -> + let*@ _ctx, bool = Sapling_storage.nullifiers_mem ctx state nf in + assert (not bool) ; + return_unit) + nf_list_absent + + (* This test applies a diff with tuples of ciphertext, commitment. Then it + checks the result of get_from with different indexes. *) + let cm_cipher_test () = + let open Lwt_result_wrap_syntax in + Random.self_init () ; + let memo_size = Random.int 200 in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ ctx, id = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id ~memo_size in + let*@ diff, ctx = Sapling_storage.state_from_id ctx id in + let list_added = + WithExceptions.List.init ~loc:__LOC__ 10 (fun _ -> + gen_cm_cipher ~memo_size ()) + in + let state = Sapling_storage.add diff list_added in + let*@ ctx, (_ : Z.t) = Sapling_storage.apply_diff ctx id state.diff in + let rec test_from from until expected = + if from > until then return_unit + else + let*@ ctx, result = Sapling_storage.Ciphertexts.get_from ctx id from in + let expected_cipher = List.map snd expected in + assert (result = expected_cipher) ; + let*@ result = Sapling_storage.Commitments.get_from ctx id from in + let expected_cm = List.map fst expected in + assert (result = expected_cm) ; + test_from + (Int64.succ from) + until + (WithExceptions.Option.get ~loc:__LOC__ @@ List.tl expected) + in + test_from 0L 9L list_added + + (* This test tests the insertion of a list vs inserting one by one. + It does so by checking the equality of the roots. *) + let list_insertion_test () = + let open Lwt_result_wrap_syntax in + Random.self_init () ; + let memo_size = Random.int 200 in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ ctx, id_one_by_one = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id_one_by_one ~memo_size in + let list_to_add = + fst @@ List.split + @@ WithExceptions.List.init ~loc:__LOC__ 33 (fun _ -> + gen_cm_cipher ~memo_size ()) + in + let rec test counter ctx = + if counter >= 32 then return_unit + else + (* add a single cm to the existing tree *) + let*@ ctx, _size = + Sapling_storage.Commitments.add + ctx + id_one_by_one + [ + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth list_to_add counter; + ] + (Int64.of_int counter) + (* create a new tree and add a list of cms *) + in + let*@ ctx, id_all_at_once = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id_all_at_once ~memo_size in + let*@ ctx, _size = + Sapling_storage.Commitments.add + ctx + id_all_at_once + (WithExceptions.List.init ~loc:__LOC__ (counter + 1) (fun i -> + WithExceptions.Option.get ~loc:__LOC__ + @@ List.nth list_to_add i)) + 0L + in + let*@ ctx, root_one_by_one = + Sapling_storage.Commitments.get_root ctx id_one_by_one + in + let*@ ctx, root_all_at_once = + Sapling_storage.Commitments.get_root ctx id_all_at_once + in + assert (root_all_at_once = root_one_by_one) ; + test (counter + 1) ctx + in + test 0 ctx + + (* This test adds 10 more roots the maximum capacity, all at different + levels, and checks that all but the first 10 are stored. + Then it adds one in the diff and checks it is stored. + Then it adds 10 at the same level and check that only the last one is + stored. *) + let root_test () = + let open Lwt_result_wrap_syntax in + let open Tezos_sapling.Core in + let gen_root () = + Data_encoding.Binary.of_bytes_exn + Validator.Hash.encoding + (Tezos_crypto.Hacl.Rand.gen 32) + in + let roots_ctx = + WithExceptions.List.init + ~loc:__LOC__ + (Int32.to_int Sapling_storage.Roots.size + 10) + (fun _ -> gen_root ()) + in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ ctx, id = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id ~memo_size:0 in + (* Add one root per level to the context *) + let* ctx, _ = + List.fold_left_es + (fun (ctx, cnt) root -> + let*@ ctx = Sapling_storage.Roots.add ctx id root in + (* Very low level way to "bake" a block. It would be better to use the + helpers functions but they complicate the access to the raw_context. *) + let+@ ctx = + Raw_context.prepare + ~level:(Int32.add b.header.shell.level cnt) + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + (Raw_context.recover ctx) + ~adaptive_issuance_enable:false + in + (ctx, Int32.succ cnt)) + (ctx, 0l) + roots_ctx + in + (* Check mem on all the roots in the context. *) + let state = + Sapling_storage. + {id = Some id; diff = Sapling_storage.empty_diff; memo_size = 0} + in + let* (_ : int) = + List.fold_left_es + (fun i root -> + let+@ bool = Sapling_storage.root_mem ctx state root in + assert (if i < 10 then not bool else bool) ; + i + 1) + 0 + roots_ctx + in + (* Add roots w/o increasing the level *) + let roots_same_level = + WithExceptions.List.init ~loc:__LOC__ 10 (fun _ -> gen_root ()) + in + let* ctx = + List.fold_left_es + (fun ctx root -> + let*@ ctxt = Sapling_storage.Roots.add ctx id root in + return ctxt) + ctx + roots_same_level + in + let* _, _ = + List.fold_left_es + (fun (i, ctx) root -> + let+@ bool = Sapling_storage.root_mem ctx state root in + assert (if i < 9 then not bool else bool) ; + (i + 1, ctx)) + (0, ctx) + roots_same_level + in + return_unit + + let test_get_memo_size () = + let open Lwt_result_wrap_syntax in + let* b, _contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ ctx, id = + Lazy_storage_diff.fresh + Lazy_storage_kind.Sapling_state + ~temporary:false + ctx + in + let*@ ctx = Sapling_storage.init ctx id ~memo_size:0 in + let+@ memo_size = Sapling_storage.get_memo_size ctx id in + assert (memo_size = 0) +end + +module Alpha_context_tests = struct + open Sapling_helpers.Alpha_context_helpers + + (* Create a transaction with memo_size 1, test that is validates with a newly + created empty_state with memo_size 1 and does not with memo_size 0. *) + let test_verify_memo () = + let open Lwt_result_syntax in + let* ctx = init () in + let sk = + Tezos_sapling.Core.Wallet.Spending_key.of_seed + (Tezos_crypto.Hacl.Rand.gen 32) + in + let vt = + let ps = Tezos_sapling.Storage.empty ~memo_size:0 in + (* the dummy output will have memo_size 0 *) + Tezos_sapling.Forge.forge_transaction + ~number_dummy_outputs:1 + [] + [] + sk + "anti-replay" + ~bound_data:"" + ps + in + let* _, _ = verify_update ctx vt ~memo_size:0 |> assert_some in + verify_update ctx vt ~memo_size:1 |> assert_none + + (* Bench the proving and validation time of shielding and transferring several + tokens. *) + let test_bench_phases () = + let open Lwt_result_syntax in + let* ctx = init () in + let rounds = 5 in + Log.info "\nrounds: %d\n" rounds ; + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer w cs [] in + let* ctx, id = verify_update ctx vt |> assert_some in + let* cs = client_state_alpha ctx id in + let start = Unix.gettimeofday () in + let vts = List.map (fun _ -> transfer w cs []) (1 -- rounds) in + let ctime_shields = Unix.gettimeofday () -. start in + Log.info "client_shields %f\n" ctime_shields ; + let start = Unix.gettimeofday () in + let* ctx = + List.fold_left_es + (fun ctx vt -> + let+ ctx, _id = verify_update ctx ~id vt |> assert_some in + ctx) + ctx + vts + in + let vtime_shields = Unix.gettimeofday () -. start in + Log.info "valdtr_shields %f\n" vtime_shields ; + let* cs = client_state_alpha ctx id in + let start = Unix.gettimeofday () in + let vts = List.map (fun i -> transfer w cs [i]) (1 -- rounds) in + let ctime_transfers = Unix.gettimeofday () -. start in + Log.info "client_txs %f\n" ctime_transfers ; + let start = Unix.gettimeofday () in + let+ (_ctx : context) = + List.fold_left_es + (fun ctx vt -> + let+ ctx, _id = verify_update ctx ~id vt |> assert_some in + ctx) + ctx + vts + in + let vtime_transfers = Unix.gettimeofday () -. start in + Log.info "valdtr_txs %f\n" vtime_transfers + + (* Same as before but for the legacy instruction. *) + let test_bench_phases_legacy () = + let open Lwt_result_syntax in + let* ctx = init () in + let rounds = 5 in + Log.info "\nrounds: %d\n" rounds ; + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer_legacy w cs [] in + let* ctx, id = verify_update_legacy ctx vt |> assert_some in + let* cs = client_state_alpha ctx id in + let start = Unix.gettimeofday () in + let vts = List.map (fun _ -> transfer_legacy w cs []) (1 -- rounds) in + let ctime_shields = Unix.gettimeofday () -. start in + Log.info "client_shields %f\n" ctime_shields ; + let start = Unix.gettimeofday () in + let* ctx = + List.fold_left_es + (fun ctx vt -> + let+ ctx, _id = verify_update_legacy ctx ~id vt |> assert_some in + ctx) + ctx + vts + in + let vtime_shields = Unix.gettimeofday () -. start in + Log.info "valdtr_shields %f\n" vtime_shields ; + let* cs = client_state_alpha ctx id in + let start = Unix.gettimeofday () in + let vts = List.map (fun i -> transfer_legacy w cs [i]) (1 -- rounds) in + let ctime_transfers = Unix.gettimeofday () -. start in + Log.info "client_txs %f\n" ctime_transfers ; + let start = Unix.gettimeofday () in + let+ (_ctx : context) = + List.fold_left_es + (fun ctx vt -> + let+ ctx, _id = verify_update_legacy ctx ~id vt |> assert_some in + ctx) + ctx + vts + in + let vtime_transfers = Unix.gettimeofday () -. start in + Log.info "valdtr_txs %f\n" vtime_transfers + + (* Transfer several times the same token. *) + let test_bench_fold_over_same_token () = + let open Lwt_result_syntax in + let* ctx = init () in + let rounds = 5 in + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer w cs [] in + let* ctx, id = verify_update ctx vt |> assert_some in + let rec loop cnt ctx = + if cnt >= rounds then return_unit + else + (* inefficient: re-synch from scratch at each round *) + let* cs = client_state_alpha ctx id in + let vt = transfer w cs [cnt] in + let* ctx, _id = verify_update ctx ~id vt |> assert_some in + loop (cnt + 1) ctx + in + loop 0 ctx + + (* + The following tests trigger all the branches of + Sapling_validator.verify_update. + The function performs several checks and returns None in case of failure. + During development the function was modified to throw a different exception + for each of its checks so to be sure that they were reached. + *) + + (* Test that double spending the same input fails the nf check. *) + let test_double_spend_same_input () = + let open Lwt_result_syntax in + let* ctx = init () in + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* one verify_update to get the id *) + let vt = transfer w cs [] in + let* ctx, id = verify_update ctx vt |> assert_some in + let* cs = client_state_alpha ctx id in + let vt = transfer w cs [0] in + let* _ctx, id = verify_update ctx ~id vt |> assert_some in + let vt = transfer w cs [0; 0] in + verify_update ctx ~id vt |> assert_none + + let test_verifyupdate_one_transaction () = + let open Lwt_result_syntax in + let* ctx = init () in + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + let vt = transfer w cs [] in + let* ctx, id = verify_update ctx vt |> assert_some in + let* cs = client_state_alpha ctx id in + let vt = transfer w cs [0] in + (* fails sig check because of wrong balance *) + let vt_broken = + Tezos_sapling.Core.Validator.UTXO. + {vt with balance = Int64.(succ vt.balance)} + in + let* () = verify_update ctx ~id vt_broken |> assert_none in + (* randomize one output to fail check outputs *) + (* don't randomize the ciphertext as it is not part of the proof *) + let open Tezos_sapling.Core.Client.UTXO in + let o = WithExceptions.Option.get ~loc:__LOC__ @@ List.hd vt.outputs in + let o_wrong_cm = + { + o with + cm = randomized_byte o.cm Tezos_sapling.Core.Client.Commitment.encoding; + } + in + let vt_broken = + Tezos_sapling.Core.Validator.UTXO.{vt with outputs = [o_wrong_cm]} + in + let* () = verify_update ctx ~id vt_broken |> assert_none in + (* position inside the cv *) + let pos = Random.int 32 in + let o_wrong_cv = + { + o with + ciphertext = + randomized_byte + ~pos + o.ciphertext + Tezos_sapling.Core.Client.Ciphertext.encoding; + } + in + let vt_broken = + Tezos_sapling.Core.Validator.UTXO.{vt with outputs = [o_wrong_cv]} + in + verify_update ctx ~id vt_broken |> assert_none + + let test_verifyupdate_two_transactions () = + let open Lwt_result_syntax in + let* ctx = init () in + let w = wallet_gen () in + let cs = Tezos_sapling.Storage.empty ~memo_size:8 in + (* generate the first storage *) + let vt = transfer w cs [] in + let* ctx, id1 = verify_update ctx vt |> assert_some in + let* cs1 = client_state_alpha ctx id1 in + let vt1 = transfer w cs1 [0] in + (* generate the second storage *) + let vt = transfer w cs [] in + let* ctx, id2 = verify_update ctx vt |> assert_some in + let* cs2 = client_state_alpha ctx id2 in + let vt2 = transfer w cs2 [0] in + (* fail root check *) + let* () = verify_update ctx ~id:id1 vt2 |> assert_none in + (* Swap the root so that it passes the root_mem check but fails + the input check *) + let vt1_broken = + Tezos_sapling.Core.Validator.UTXO.{vt2 with root = vt1.root} + in + let* () = verify_update ctx ~id:id1 vt1_broken |> assert_none in + (* fail the sig check *) + let vt1_broken = + Tezos_sapling.Core.Validator.UTXO.{vt1 with outputs = vt2.outputs} + in + verify_update ctx ~id:id1 vt1_broken |> assert_none +end + +module Interpreter_tests = struct + open Sapling_helpers.Interpreter_helpers + + let parameters_of_list transactions = + let string = "{ " ^ String.concat " ; " transactions ^ " }" in + Alpha_context.Script.(lazy_expr (Expr.from_string string)) + + let path = project_root // Filename.dirname __FILE__ + + (* In this test, we use a contract which takes a list of transactions, applies + all of them, and assert all of them are correct. It also enforces a 1-to-1 + conversion with mutez by asking an amount to shield and asking for a pkh to + unshield. + We create 2 keys a and b. We originate the contract, then do two lists of + shield for a, then transfers several outputs to b while unshielding, then + transfer all of b inputs to a while adding dummy inputs and outputs. + At last, we fail by making a faulty transaction. *) + let test_shielded_tez () = + let open Lwt_result_wrap_syntax in + let* genesis, baker, src0, src1 = init () in + let memo_size = 8 in + let* dst, b1, anti_replay = + originate_contract_hash + (path // "contracts/sapling_contract.tz") + "{ }" + src0 + genesis + baker + in + let wa = wallet_gen () in + let list_transac, total = + shield ~memo_size wa.sk 2 wa.vk (Format.sprintf "0x%s") anti_replay + in + let parameters = parameters_of_list list_transac in + (* a does a list of shield transaction *) + let* b2, _state = + transac_and_sync ~memo_size b1 parameters total src0 dst baker + in + (* we shield again on another block, forging with the empty state *) + let list_transac, total' = + shield ~memo_size wa.sk 2 wa.vk (Format.sprintf "0x%s") anti_replay + in + let parameters = parameters_of_list list_transac in + (* a does a list of shield transaction *) + let* b3, state = + transac_and_sync ~memo_size b2 parameters total' src0 dst baker + in + (* address that will receive an unshield *) + let* balance_before_shield = Context.Contract.balance (B b3) src1 in + (* address that will receive an unshield *) + let wb = wallet_gen () in + let list_addr = gen_addr 2 wb.vk in + (* Take the first two inputs *) + let list_forge_input = + List.map + (fun pos_int -> + let pos = Int64.of_int pos_int in + let forge_input = + snd + (Tezos_sapling.Forge.Input.get state pos wa.vk + |> WithExceptions.Option.get ~loc:__LOC__) + in + forge_input) + (0 -- 4) + in + let list_forge_output = + List.map + (fun addr -> Tezos_sapling.Forge.make_output addr 1L (Bytes.create 8)) + list_addr + in + let src1_pkh = Context.Contract.pkh src1 in + let* incr = Incremental.begin_construction b3 in + let alpha_ctxt = Incremental.alpha_ctxt incr in + let*@ bound_data, _alpha_ctxt = + Script_ir_translator.pack_data + alpha_ctxt + Script_typed_ir.key_hash_t + src1_pkh + in + let hex_transac = + to_hex + (Tezos_sapling.Forge.forge_transaction + ~number_dummy_inputs:0 + ~number_dummy_outputs:0 + list_forge_input + list_forge_output + wa.sk + anti_replay + ~bound_data:(Bytes.to_string bound_data) + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + let string = Format.sprintf "{0x%s}" hex_transac in + let parameters = + Alpha_context.Script.(lazy_expr (Expr.from_string string)) + in + (* a transfers to b and unshield some money to src_1 (the pkh) *) + let* b4, state = + transac_and_sync ~memo_size b3 parameters 0 src0 dst baker + in + let* balance_after_shield = Context.Contract.balance (B b4) src1 in + let diff_due_to_shield = + Int64.sub + (Test_tez.to_mutez balance_after_shield) + (Test_tez.to_mutez balance_before_shield) + in + (* The balance after shield is obtained from the balance before shield by + the shield specific update. *) + (* The inputs total [total] mutez and 2 of those are transfered in shielded tez *) + let* () = + Assert.equal_int ~loc:__LOC__ (Int64.to_int diff_due_to_shield) (total - 2) + in + let list_forge_input = + List.map + (fun i -> + let pos = Int64.of_int (i + 5 + 5) in + let forge_input = + snd + (Tezos_sapling.Forge.Input.get state pos wb.vk + |> WithExceptions.Option.get ~loc:__LOC__) + in + forge_input) + (0 -- 1) + in + let addr_a = + snd + @@ Tezos_sapling.Core.Client.Viewing_key.new_address + wa.vk + Tezos_sapling.Core.Client.Viewing_key.default_index + in + let output = Tezos_sapling.Forge.make_output addr_a 2L (Bytes.create 8) in + let hex_transac = + to_hex + (Tezos_sapling.Forge.forge_transaction + ~number_dummy_inputs:1 + ~number_dummy_outputs:1 + list_forge_input + [output] + wb.sk + anti_replay + ~bound_data:"" + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + let string = Format.sprintf "{0x%s}" hex_transac in + let parameters = + Alpha_context.Script.(lazy_expr (Expr.from_string string)) + in + (* b transfers to a with dummy inputs and outputs *) + let* b, state = + transac_and_sync ~memo_size b4 parameters 0 src0 dst baker + in + (* Here we fail by doing the same transaction again*) + let* incr = Incremental.begin_construction b in + let fee = Test_tez.of_int 10 in + let dst = Alpha_context.Contract.Originated dst in + let* operation = + Op.transaction ~gas_limit:Max ~fee (B b) src0 dst Tez.zero ~parameters + in + let* (_incr : Incremental.t) = + Incremental.add_operation (* TODO make more precise *) + ~expect_apply_failure:(fun _ -> return_unit) + incr + operation + in + (* Here we fail by changing the field bound_data*) + let orginal_transac = + Tezos_sapling.Forge.forge_transaction + list_forge_input + [output] + wb.sk + anti_replay + ~bound_data:"right" + state + in + let modified_transac = + Tezos_sapling.Core.Validator.UTXO. + {orginal_transac with bound_data = "wrong"} + in + let string = + Format.sprintf + "{0x%s}" + (to_hex + modified_transac + Tezos_sapling.Core.Client.UTXO.transaction_encoding) + in + let parameters = + Alpha_context.Script.(lazy_expr (Expr.from_string string)) + in + let* incr = Incremental.begin_construction b in + let fee = Test_tez.of_int 10 in + let* operation = + Op.transaction ~gas_limit:Max ~fee (B b) src0 dst Tez.zero ~parameters + in + let* (_incr : Incremental.t) = + Incremental.add_operation (* TODO make more precise *) + ~expect_apply_failure:(fun _ -> return_unit) + incr + operation + in + return_unit + + let test_push_sapling_state_should_be_forbidden () = + let open Lwt_result_syntax in + let* block, baker, src, _ = + init () + (* Originating a contract to get a sapling_state with ID 0, used in the next contract *) + in + let* _, _, _ = + originate_contract_hash + (path // "contracts/sapling_contract.tz") + "{ }" + src + block + baker + in + (* Originating the next contract should fail *) + let*! result = + originate_contract_hash + (path // "contracts/sapling_push_sapling_state.tz") + "{ }" + src + block + baker + in + match result with + | Error + [ + Environment.Ecoproto_error (Script_tc_errors.Ill_typed_contract _); + Environment.Ecoproto_error + (Script_tc_errors.Unexpected_lazy_storage _); + ] -> + return_unit + | _ -> assert false + + let test_use_state_from_other_contract_and_transact () = + let open Lwt_result_syntax in + (* + Attempt to use a sapling state of a contract A in a contract B + *) + let* block, baker, src, _ = init () (* Originating the contracts *) in + let memo_size = 8 in + (* let* _shielded_pool_contract_address, block, _anti_replay_shielded_pool = + originate_contract "contracts/sapling_contract.tz" "{ }" src block baker in + *) + let* existing_state_contract_address, block, anti_replay_2 = + originate_contract_hash + (path // "contracts/sapling_use_existing_state.tz") + "{ }" + src + block + baker + in + (* we create one shielding transaction and transform it in Micheline to use + it as a parameter + *) + let wa = wallet_gen () in + let transactions, _total = + shield + ~memo_size + wa.sk + 1 + wa.vk + (Format.sprintf "(Pair 0x%s 0)") + anti_replay_2 + in + let transaction = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd transactions + in + let parameters = + Alpha_context.Script.(lazy_expr (Expr.from_string transaction)) + in + let*! result = + transac_and_sync + ~memo_size + block + parameters + 0 + src + existing_state_contract_address + baker + in + match result with + | Ok _ -> Alcotest.failf "Unexpected operations success" + | Error errs -> + assert ( + List.exists + (function + | Environment.Ecoproto_error + (Tezos_protocol_020_PsParisC.Protocol.Script_tc_errors + .Unexpected_forged_value _) -> + true + | _ -> false) + errs) ; + return_unit + + (* In this test we do two transactions in one block and same two in two block. + We check that the sate is the same expect for roots. + The second transaction is possible only if the first one is done. *) + let test_transac_and_block () = + let open Lwt_result_wrap_syntax in + let* b, baker, src, _ = init () in + let memo_size = 8 in + let* dst, block_start, anti_replay = + originate_contract_hash + (path // "contracts/sapling_contract.tz") + "{ }" + src + b + baker + in + let {sk; vk} = wallet_gen () in + let hex_transac_1 = hex_shield ~memo_size {sk; vk} anti_replay in + let string_1 = Format.sprintf "{%s}" hex_transac_1 in + let parameters_1 = + Alpha_context.Script.(lazy_expr (Expr.from_string string_1)) + in + let* block_1, state = + transac_and_sync ~memo_size block_start parameters_1 15 src dst baker + in + let intermediary_root = Tezos_sapling.Storage.get_root state in + let addr = + snd + @@ Tezos_sapling.Core.Wallet.Viewing_key.(new_address vk default_index) + in + let output = Tezos_sapling.Forge.make_output addr 15L (Bytes.create 8) in + let hex_transac_2 = + "0x" + ^ to_hex + (Tezos_sapling.Forge.forge_transaction + [ + snd + (Tezos_sapling.Forge.Input.get state 0L vk + |> WithExceptions.Option.get ~loc:__LOC__); + ] + [output] + sk + anti_replay + ~bound_data:"" + state) + Tezos_sapling.Core.Client.UTXO.transaction_encoding + in + let string_2 = Format.sprintf "{%s}" hex_transac_2 in + let parameters_2 = + Alpha_context.Script.(lazy_expr (Expr.from_string string_2)) + in + let* block_1, state_1 = + transac_and_sync ~memo_size block_1 parameters_2 0 src dst baker + in + let final_root = Tezos_sapling.Storage.get_root state_1 in + let* _root, diff_1 = + Alpha_services.Contract.single_sapling_get_diff + Block.rpc_ctxt + block_1 + dst + ~offset_commitment:0L + ~offset_nullifier:0L + () + in + let fee = Test_tez.of_int 10 in + let*? amount_tez = Tez.one_mutez *? Int64.of_int 15 in + let* operation1 = + Op.transaction + ~gas_limit:High + ~fee + (B block_start) + src + (Contract.Originated dst) + amount_tez + ~parameters:parameters_1 + in + let* incr = Incremental.begin_construction block_start in + (* We need to manually get the counter here *) + let ctx = Incremental.alpha_ctxt incr in + let pkh = Context.Contract.pkh src in + let*@ counter = Alpha_context.Contract.get_counter ctx pkh in + let* operation2 = + Op.transaction + ~gas_limit:High + ~counter + ~fee + (B block_start) + src + (Contract.Originated dst) + Tez.zero + ~parameters:parameters_2 + in + let* operation = + Op.batch_operations + ~recompute_counters:true + ~source:src + (I incr) + [operation1; operation2] + in + let* incr = Incremental.add_operation incr operation in + let* block_2 = Incremental.finalize_block incr in + let* _root, diff_2 = + Alpha_services.Contract.single_sapling_get_diff + Block.rpc_ctxt + block_2 + dst + ~offset_commitment:0L + ~offset_nullifier:0L + () + in + (* We check that the same transactions have passed *) + assert (diff_1 = diff_2) ; + let is_root_in block dst root = + let* incr = Incremental.begin_construction block in + let ctx_2 = Incremental.alpha_ctxt incr in + let* script = Alpha_services.Contract.script Block.rpc_ctxt block dst in + let ctx_without_gas_2 = Alpha_context.Gas.set_unlimited ctx_2 in + let*@ Ex_script (Script script), ctxt = + Script_ir_translator.parse_script + ctx_without_gas_2 + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let*?@ id, _ctx_2 = + Script_ir_translator.get_single_sapling_state + ctxt + script.storage_type + script.storage + in + let single_id = WithExceptions.Option.get ~loc:__LOC__ id in + let id = + Lazy_storage_kind.Sapling_state.Id.parse_z + @@ Alpha_context.Sapling.Id.unparse_to_z single_id + in + let*@ raw_ctx = + Raw_context.prepare + block.context + ~level:block.header.shell.level + ~predecessor_timestamp:block.header.shell.timestamp + ~timestamp:block.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let*@ result = Sapling_storage.Roots.mem raw_ctx id root in + return result + in + (* We check that the second state did not store the root in between + transactions. *) + let* () = is_root_in block_2 dst intermediary_root |> assert_false in + (* We check that the second state did store the final root. *) + let* () = is_root_in block_2 dst final_root |> assert_true in + (* We check that the first state did store the final root. *) + let* () = is_root_in block_1 dst final_root |> assert_true in + (* We check that the first state did store the root in between transactions. *) + is_root_in block_1 dst intermediary_root |> assert_true + + (* In this test we try a contract which creates an empty sapling state on the + fly. It then applies a list of transactions, checks they are correct and + drops the result. We make several shields in the same list (since the state + is drop). *) + let test_drop () = + let open Lwt_result_syntax in + let* b, baker, src, _ = init () in + let* dst, b, anti_replay = + originate_contract_hash + (path // "contracts/sapling_contract_drop.tz") + "Unit" + src + b + baker + in + let {sk; vk} = wallet_gen () in + let list_transac, _total = + shield ~memo_size:8 sk 4 vk (Format.sprintf "0x%s") anti_replay + in + let parameters = parameters_of_list list_transac in + let dst = Contract.Originated dst in + let* operation = + Op.transaction + ~gas_limit:Max + ~fee:(Test_tez.of_int 10) + (B b) + src + dst + Tez.zero + ~parameters + in + let* (_b : Block.t) = next_block b operation in + return_unit + + (* We use a contrac with two states. Its parameter is two transactions and a + bool. The two transactions are tested valid against the two states, but + only one state according to the bool is updated. + We do two transactions shielding to different keys in the two states. + At each transactions both are applied but only state is updated. + We then check that the first state is updated in the correct way. *) + let test_double () = + let open Lwt_result_wrap_syntax in + let* b, baker, src, _ = init () in + let memo_size = 8 in + let* dst, b, anti_replay = + originate_contract_hash + (path // "contracts/sapling_contract_double.tz") + "(Pair { } { })" + src + b + baker + in + let wa = wallet_gen () in + let hex_transac_1 = hex_shield ~memo_size wa anti_replay in + let wb = wallet_gen () in + let hex_transac_2 = hex_shield ~memo_size wb anti_replay in + let str_1 = + "(Pair True (Pair " ^ hex_transac_1 ^ " " ^ hex_transac_2 ^ "))" + in + let str_2 = + "(Pair False (Pair " ^ hex_transac_2 ^ " " ^ hex_transac_1 ^ "))" + in + (* transac 1 is applied to state_1*) + let parameters_1 = + Alpha_context.Script.(lazy_expr (Expr.from_string str_1)) + in + (* tranasc_2 is applied to state_2*) + let parameters_2 = + Alpha_context.Script.(lazy_expr (Expr.from_string str_2)) + in + let fee = Test_tez.of_int 10 in + let cdst = Contract.Originated dst in + let* operation = + Op.transaction + ~gas_limit:Max + ~fee + (B b) + src + cdst + Tez.zero + ~parameters:parameters_1 + in + let* b = next_block b operation in + let* operation = + Op.transaction + ~gas_limit:Max + ~fee + (B b) + src + cdst + Tez.zero + ~parameters:parameters_2 + in + let* b = next_block b operation in + let* incr = Incremental.begin_construction b in + let ctx = Incremental.alpha_ctxt incr in + let ctx_without_gas = Alpha_context.Gas.set_unlimited ctx in + let* storage = Alpha_services.Contract.storage Block.rpc_ctxt b dst in + let storage_lazy_expr = Alpha_context.Script.lazy_expr storage in + let*?@ (Ty_ex_c tytype) = + let memo_size = memo_size_of_int memo_size in + let open Script_typed_ir in + let state_ty = sapling_state_t ~memo_size in + pair_t (-1) state_ty state_ty + in + let*@ (state_1, state_2), _ctx = + Script_ir_translator.parse_storage + ctx_without_gas + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + tytype + ~storage:storage_lazy_expr + in + (*Only works when diff is empty*) + let local_state_from_disk disk_state ctx = + let id = + Alpha_context.Sapling.(disk_state.id) + |> WithExceptions.Option.get ~loc:__LOC__ + in + let+@ diff = + Alpha_context.Sapling.get_diff + ctx + id + ~offset_commitment:0L + ~offset_nullifier:0L + () + in + client_state_of_diff ~memo_size diff + in + let* state_1 = local_state_from_disk state_1 ctx in + let+ state_2 = local_state_from_disk state_2 ctx in + (* we check that first state contains 15 to addr_1 but not 15 to addr_2*) + assert (Option.is_some @@ Tezos_sapling.Forge.Input.get state_1 0L wa.vk) ; + assert (Option.is_some @@ Tezos_sapling.Forge.Input.get state_2 0L wa.vk) ; + assert (Option.is_none @@ Tezos_sapling.Forge.Input.get state_1 0L wb.vk) ; + assert (Option.is_none @@ Tezos_sapling.Forge.Input.get state_2 0L wb.vk) + + let test_state_as_arg () = + let open Lwt_result_syntax in + let* b, baker, src, _ = init () in + let* dst, b, anti_replay = + originate_contract_hash + (path // "contracts/sapling_contract_state_as_arg.tz") + "None" + src + b + baker + in + let* dst_2, b, anti_replay_2 = + originate_contract_hash + (path // "contracts/sapling_contract_send.tz") + "Unit" + src + b + baker + in + let w = wallet_gen () in + let hex_transac_1 = hex_shield ~memo_size:8 w anti_replay in + let string = "Left " ^ hex_transac_1 in + let parameters = + Alpha_context.Script.(lazy_expr (Expr.from_string string)) + in + let fee = Test_tez.of_int 10 in + let dst = Contract.Originated dst in + let* operation = + Op.transaction ~gas_limit:Max ~fee (B b) src dst Tez.zero ~parameters + in + let* b = next_block b operation in + let contract = "0x" ^ to_hex dst Alpha_context.Contract.encoding in + let hex_transac_2 = hex_shield ~memo_size:8 w anti_replay_2 in + let string = "(Pair " ^ contract ^ " " ^ hex_transac_2 ^ ")" in + let parameters = + Alpha_context.Script.(lazy_expr (Expr.from_string string)) + in + let dst_2 = Contract.Originated dst_2 in + let* operation = + Op.transaction ~gas_limit:Max ~fee (B b) src dst_2 Tez.zero ~parameters + in + let* (_b : Block.t) = next_block b operation in + return_unit +end + +let tests = + [ + Tztest.tztest + "commitments_add_uncommitted" + `Quick + Raw_context_tests.commitments_add_uncommitted; + Tztest.tztest "nullifier_double" `Quick Raw_context_tests.nullifier_double; + Tztest.tztest "nullifier_test" `Quick Raw_context_tests.nullifier_test; + Tztest.tztest "cm_cipher_test" `Quick Raw_context_tests.cm_cipher_test; + Tztest.tztest + "list_insertion_test" + `Quick + Raw_context_tests.list_insertion_test; + Tztest.tztest "root" `Quick Raw_context_tests.root_test; + Tztest.tztest "get_memo_size" `Quick Raw_context_tests.test_get_memo_size; + Tztest.tztest "verify_memo" `Quick Alpha_context_tests.test_verify_memo; + Tztest.tztest "bench_phases" `Slow Alpha_context_tests.test_bench_phases; + Tztest.tztest + "bench_phases_legacy" + `Slow + Alpha_context_tests.test_bench_phases_legacy; + Tztest.tztest + "bench_fold_over_same_token" + `Slow + Alpha_context_tests.test_bench_fold_over_same_token; + Tztest.tztest + "double_spend_same_input" + `Quick + Alpha_context_tests.test_double_spend_same_input; + Tztest.tztest + "verifyupdate_one_transaction" + `Quick + Alpha_context_tests.test_verifyupdate_one_transaction; + Tztest.tztest + "verifyupdate_two_transactions" + `Quick + Alpha_context_tests.test_verifyupdate_two_transactions; + Tztest.tztest "shielded_tez" `Quick Interpreter_tests.test_shielded_tez; + Tztest.tztest + "use state from other contract and transact" + `Quick + Interpreter_tests.test_use_state_from_other_contract_and_transact; + Tztest.tztest + "Instruction PUSH sapling_state 0 should be forbidden" + `Quick + Interpreter_tests.test_push_sapling_state_should_be_forbidden; + Tztest.tztest + "transac_and_block" + `Quick + Interpreter_tests.test_transac_and_block; + Tztest.tztest "drop" `Quick Interpreter_tests.test_drop; + Tztest.tztest "double" `Quick Interpreter_tests.test_double; + Tztest.tztest "state_as_arg" `Quick Interpreter_tests.test_state_as_arg; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sapling", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_cache.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_cache.ml new file mode 100644 index 000000000000..55bb295f9446 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_cache.ml @@ -0,0 +1,484 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (cache) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_script_cache.ml + Subject: These unit tests check basic behavior of script cache +*) + +open Protocol +open Alpha_context +open Contract_helpers +open Script_ir_translator + +exception Script_cache_test_error of string + +let err x = Exn (Script_cache_test_error x) + +(* + + The following value is hard-coded to detect change in the size + model. It has been computed by a manual run of the test. + +*) +let liquidity_baking_contract_size = 182272 + +let liquidity_baking_contract = + Contract_hash.of_b58check_exn "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" + +let make_block block f = + let open Lwt_result_syntax in + let* incr = Incremental.begin_construction block in + let* ret, ctxt = f (Incremental.alpha_ctxt incr) in + let incr = Incremental.set_alpha_ctxt incr ctxt in + let* block = Incremental.finalize_block incr in + let* next_block = Block.bake block in + return (ret, next_block) + +let ( @! ) f g = + let open Lwt_result_syntax in + f @@ fun ctxt -> + let* ret = g ctxt in + return (ret, ctxt) + +let equal_scripts (s1 : Script.t) (s2 : Script.t) = + let open Result_syntax in + Script_repr.( + let* code1 = force_bytes s1.code in + let* code2 = force_bytes s2.code in + let* storage1 = force_bytes s1.storage in + let* storage2 = force_bytes s2.storage in + return (Bytes.equal code1 code2 && Bytes.equal storage1 storage2)) + +let find ctxt addr = + let open Lwt_result_wrap_syntax in + let*@ ctxt, identifier, result = Script_cache.find ctxt addr in + match result with + | None -> + (* by [find_correctly_looks_up]. *) + assert false + | Some (script, Ex_script ir) -> + return (ctxt, identifier, script, Ex_script ir) + +let value_as_int : + type a ac. (a, ac) Script_typed_ir.ty -> a -> Script_int.z Script_int.num = + fun ty v -> match ty with Int_t -> v | _ -> Stdlib.failwith "value_as_int" + +let path = project_root // Filename.dirname __FILE__ + +let add_some_contracts k src block baker = + let open Lwt_result_syntax in + let* liquidity_baking_contract_id, block = + make_block block @@ fun ctxt -> + let* ctxt, id, _, _ = find ctxt liquidity_baking_contract in + return (id, ctxt) + in + let* rev_contracts, block = + List.fold_left_es + (fun (rev_contracts, block) _ -> + let* addr, block = + originate_contract_hash + (path // "contracts/int-store.tz") + "31" + src + block + baker + in + let* block = Block.bake block in + make_block block @@ fun ctxt -> + let* ctxt, id, _, _ = find ctxt addr in + let contract = (id, addr) in + return (contract :: rev_contracts, ctxt)) + ([], block) + (1 -- k) + in + let contracts = + (* After each baking [liquidity_baking_contract] is the most + recently used contract. *) + let lb = (liquidity_baking_contract_id, liquidity_baking_contract) in + List.rev (lb :: rev_contracts) + in + return (contracts, block) + +(* + + The following value is hard-coded to detect change in the size + model. It has been computed by a manual run of the test. + +*) +let int_store_contract_size = 592 + +(* + + Check our assumptions regarding the size of reference scripts. + +*) +let assert_cache_size expected_size ctxt = + fail_unless + (Script_cache.size ctxt = expected_size) + (err + (Printf.sprintf + "Invalid script cache size, expecting %d, got %d" + expected_size + (Script_cache.size ctxt))) + +let test_size_of_liquidity_baking_contract () = + let open Lwt_result_syntax in + let* block, _, _, _ = init () in + let* (), _block = + make_block block @! assert_cache_size liquidity_baking_contract_size + in + return_unit + +let test_size_of_int_store_contract () = + let open Lwt_result_wrap_syntax in + let* block, baker, src, _ = init () in + let* addr, block = + originate_contract_hash + (path // "contracts/int-store.tz") + "31" + src + block + baker + in + let* (), _block = + make_block block @! fun ctxt -> + let*@ ctxt, _, _ = Script_cache.find ctxt addr in + assert_cache_size + (int_store_contract_size + liquidity_baking_contract_size) + ctxt + in + return_unit + +(* + + When a contract is in the context, [find] correctly returns it. + +*) +let test_find_correctly_looks_up () = + let open Lwt_result_wrap_syntax in + let* block, baker, src, _ = init () in + let* addr, block = + originate_contract_hash + (path // "contracts/sapling_contract.tz") + "{ }" + src + block + baker + in + let* (), _block = + make_block block @! fun ctxt -> + (* + Contract is present. + *) + let*@ _, _, result = Script_cache.find ctxt addr in + let*@ ctxt, script = Contract.get_script ctxt addr in + let*?@ cond = + match (result, script) with + | None, _ -> Result_syntax.return_false + | Some _, None -> + (* because we assume that get_script correctly behaves. *) + assert false + | Some (cached_script, _), Some script -> + equal_scripts script cached_script + in + let* () = + fail_unless + cond + (err "find should be able to retrieve an originated contract") + (* + Contract is absent. + *) + in + let addr = Contract_helpers.fake_KT1 in + let*@ _, _, cached_contract = Script_cache.find ctxt addr in + fail_unless + (cached_contract = None) + (err "find should return None for unbound contracts") + in + return_unit + +(* + + [test_update] correctly modifies a cached contract in the context. + +*) +let test_update_modifies_cached_contract () = + let open Lwt_result_wrap_syntax in + let* block, baker, src, _ = init () in + let* addr, block = + originate_contract_hash + (path // "contracts/int-store.tz") + "36" + src + block + baker + in + let* (), _block = + make_block block @! fun ctxt -> + let* ctxt, identifier, script, Ex_script (Script ir) = find ctxt addr in + match ir.storage_type with + | Int_t -> + let storage' = Script_int.(add ir.storage (Script_int.of_int 1)) in + let cached_contract' = + (script, Ex_script (Script {ir with storage = storage'})) + in + let*?@ ctxt = Script_cache.update ctxt identifier cached_contract' 1 in + let* _, _, _, Ex_script (Script ir') = find ctxt addr in + let storage = value_as_int ir'.storage_type ir'.storage in + fail_unless + (Script_int.compare storage storage' = 0) + (err + (Format.sprintf + "Update failed, expecting %s, got %s" + (Script_int.to_string storage') + (Script_int.to_string storage))) + | _ -> + (* by definition of int-store.tz. *) + assert false + in + return_unit + +(* + + [test_entries] returns the list of cached scripts in order of least + modification date. + +*) +let test_entries_returns_the_list_in_correct_order () = + let open Lwt_result_wrap_syntax in + let ncontracts = 10 in + let* block, baker, src, _ = init () in + let* contracts, block = add_some_contracts ncontracts src block baker in + let addrs = snd @@ List.split contracts in + let* (), _block = + make_block block @! fun ctxt -> + let*?@ entries = Script_cache.entries ctxt in + let cached_contracts = fst (List.split entries) in + fail_unless + (addrs = cached_contracts) + (err "entries must return cached contracts in order") + in + return_unit + +(* + + [test_contract_rank] correctly computes LRU rank. + +*) +let test_contract_rank_is_lru_rank () = + let open Lwt_result_syntax in + let ncontracts = 10 in + let* block, baker, src, _ = init () in + let* contracts, block = add_some_contracts ncontracts src block baker in + let addrs = snd @@ List.split contracts in + let* (), _block = + make_block block @! fun ctxt -> + let rec check_rank k = function + | [] -> return_unit + | addr :: addrs -> ( + match Script_cache.contract_rank ctxt addr with + | None -> tzfail (err "Contract rank should find a cached contract") + | Some rank -> + let* () = + fail_unless + (k = rank) + (err + (Printf.sprintf + "Invalid contract rank, expecting %d, got %d" + k + rank)) + in + check_rank (k + 1) addrs) + in + check_rank 0 addrs + in + return_unit + +(* + + [size] correctly returns the sums of the (declared) sizes. + +*) +let test_size_adds_entries_sizes () = + let open Lwt_result_syntax in + let ncontracts = 10 in + let* block, baker, src, _ = init () in + let* _, block = add_some_contracts ncontracts src block baker in + let* (), _block = + make_block block @! fun ctxt -> + let expected_size = + liquidity_baking_contract_size + (ncontracts * int_store_contract_size) + in + fail_unless + (Script_cache.size ctxt = expected_size) + (err + (Printf.sprintf + "Invalid script cache size, expecting %d, got %d" + expected_size + (Script_cache.size ctxt))) + in + return_unit + +(* + + [test_size_limit] is the value found in [Constants_repr.cache_layout]. + +*) +let defined_size_limit = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_mainnet + .cache_script_size + +let test_size_limit_is_in_constants_repr () = + let open Lwt_result_syntax in + let* block, _baker, _src, _ = init () in + let* (), _block = + make_block block @! fun ctxt -> + fail_unless + (Script_cache.size_limit ctxt = defined_size_limit) + (err + (Printf.sprintf + "Invalid size limit, expecting %d, got %d" + defined_size_limit + (Script_cache.size_limit ctxt))) + in + return_unit + +(* + + [test_entries] are conform to an LRU strategy: when the cache is + full the least recently used entries are removed. + +*) +let test_entries_shows_lru () = + let open Lwt_result_wrap_syntax in + let ncontracts = 10 in + let* block, baker, src, _ = init () in + let* contracts, block = add_some_contracts ncontracts src block baker in + (* We pretend that the contracts' sizes grow so much that they cannot all + fit into the cache. *) + let new_size = 2 * defined_size_limit / ncontracts in + let* (), block = + make_block block @@ fun ctxt -> + let* ctxt = + List.fold_left_es + (fun ctxt (_, addr) -> + let* ctxt, id, script, cached_contract = find ctxt addr in + let*?@ result = + Script_cache.update ctxt id (script, cached_contract) new_size + in + return result) + ctxt + contracts + in + return ((), ctxt) + in + (* At this point, the cache should only contain the most recently modified + contracts. *) + let* (), _block = + make_block block @@ fun ctxt -> + let*?@ entries = Script_cache.entries ctxt in + let rev_entries = List.rev entries in + let rev_contracts = List.rev contracts in + let rec aux rev_entries rev_contracts = + Printf.eprintf + "%d %d\n" + (List.length rev_entries) + (List.length rev_contracts) ; + match (rev_entries, rev_contracts) with + | [], _ -> + (* We do not count liquidity baking contract. *) + let removed_contracts = List.length rev_contracts - 1 in + fail_unless + (removed_contracts = ncontracts / 2) + (err + (Printf.sprintf + "Too few contracts have been removed from the cache while it \ + is full, %d remaining while expecting %d" + removed_contracts + (ncontracts / 2))) + | (contract, size) :: rev_entries, (_, contract') :: rev_contracts -> + let* () = + fail_unless + (size = new_size || contract = liquidity_baking_contract) + (err + (Printf.sprintf + "A contract in the cache has not the right size, expecting \ + %d, got %d" + new_size + size)) + in + let* () = + fail_unless + (contract = contract') + (err + (Printf.sprintf + "entries do not return cached contracts in right order")) + in + aux rev_entries rev_contracts + | _, [] -> + (* There cannot be more entries than contracts. *) + assert false + in + let* () = aux rev_entries rev_contracts in + return ((), ctxt) + in + return_unit + +let tests = + let open Tztest in + [ + tztest + "assumption about size of liquidity baking holds" + `Quick + test_size_of_liquidity_baking_contract; + tztest + "assumption about size of 'int_store' contract holds" + `Quick + test_size_of_int_store_contract; + tztest "find correctly looks up" `Quick test_find_correctly_looks_up; + tztest + "update correctly modifies" + `Quick + test_update_modifies_cached_contract; + tztest + "entries correctly list contracts in order" + `Quick + test_entries_returns_the_list_in_correct_order; + tztest "contract_rank is LRU rank" `Quick test_contract_rank_is_lru_rank; + tztest "size returns entries size" `Quick test_size_adds_entries_sizes; + tztest + "size limit is a protocol constant" + `Quick + test_size_limit_is_in_constants_repr; + tztest "entries show LRU behavior" `Quick test_entries_shows_lru; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("script cache", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_typed_ir_size.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_typed_ir_size.ml new file mode 100644 index 000000000000..25dc40a99c4f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_script_typed_ir_size.ml @@ -0,0 +1,1053 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (script typed IR size) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_script_typed_ir_size.ml + Subject: Script_typed_ir computes good approximation of values' sizes +*) + +open Protocol +open Alpha_context +open Script_typed_ir + +(* + Helpers + ------- +*) + +exception Script_typed_ir_test_error of string + +let err x = Exn (Script_typed_ir_test_error x) + +let dummy_loc = Micheline.dummy_location + +let get = Stdlib.Option.get + +let is_ok m = match m with Ok x -> x | _ -> assert false + +let footprint v = + (* This is to turn every statically allocated data into + heap-allocated data, to consider the worst-case in-memory + representation of values. Note that it does NOT remove sharing.*) + let v' = + try Marshal.(from_bytes (to_bytes v [Closures]) 0) + with _ -> (* Custom blocks are problematic. *) v + in + let size v = Obj.(reachable_words (repr v) * 8) in + max (size v) (size v') + +(** [gen_string s] returns a heap-allocated string. Notice that a + string literal ["foo"] written in the code is statically allocated + and is therefore not counted by [Obj.reachable_words]. *) +let gen_string s = + let s = Bytes.of_string s |> Bytes.to_string in + is_ok @@ Script_string.of_string s + +let boxed_set_elements s = Script_set.fold (fun x s -> x :: s) s [] + +let boxed_map_bindings s = Script_map.fold (fun k v s -> (k, v) :: s) s [] + +let big_map_bindings (Big_map s) = Big_map_overlay.bindings s.diff.map + +let show_script_int fmt x = Z.pp_print fmt (Script_int.to_zint x) + +let show_bool fmt b = Format.fprintf fmt "%B" b + +let show_script_string fmt x = + Format.fprintf fmt "%s" (Script_string.to_string x) + +let show_address fmt Script_typed_ir.{destination; entrypoint} = + Format.fprintf + fmt + "%a(%d):%a(%d)" + Destination.pp + destination + (footprint destination) + Entrypoint.pp + entrypoint + (footprint entrypoint) + +let dont_show _fmt _ = () + +let size = {Tezos_benchmark.Base_samplers.min = 4; max = 32} + +module Crypto_samplers = +Tezos_benchmark.Crypto_samplers.Make_finite_key_pool (struct + let size = 10 + + let algo = `Default +end) + +include + Michelson_samplers.Make + (struct + let parameters : Michelson_samplers.parameters = + { + base_parameters = + { + Michelson_samplers_base.int_size = size; + string_size = size; + bytes_size = size; + }; + list_size = size; + set_size = size; + map_size = size; + } + end) + (Crypto_samplers) + +let random_state = Random.State.make [|37; 73; 17; 71; 42|] + +let sample_ty size = Random_type.m_type ~size () random_state + +let sample_value ty = Random_value.value ty random_state + +type ex = Ex : string * ('a, _) Script_typed_ir.ty * 'a * int -> ex [@@boxed] + +let ex ?(error = 0) label ty v = Ex (label, ty, v, error) + +let ex_random ?(error = 0) show ty ?(sample = fun () -> sample_value ty) label = + let v = sample () in + let label = Format.asprintf "@[%a%s@]@." show v label in + ex ~error label ty v + +let exs ?(error = 0) n show ty ?(sample = fun () -> sample_value ty) label = + List.map (fun _ -> ex_random ~error show ty label ~sample) (1 -- n) + +let nsample = 100 + +type ex_kinstr = Kinstr : string * ('a, 'b, 'c, 'd) kinstr -> ex_kinstr +[@@boxed] + +(** [check_value_size ()] covers a finite number of cases of Michelson + values, checking that the cost model is sound with respect to their + memory footprint. + + One could wonder why we do not simply use a single value generator + based on a randomly chosen type. We actually implemented such a + strategy in a previous version of this test but this results in a + flaky test. Indeed, for some types, the values are overapproximated + and it was difficult to correctly handle the accumulation of errors + when types were randomly composed. + + The current strategy requires more code but, in exchange, it + provides a finer control over the overapproximation. As a + consequence, we can check for example that there is no + overapproximation for values for which the model is exact. We can + also check that the overapproximation is at least well understood + on the values for which size model is not exact. *) +let check_value_size () = + let check (Ex (what, ty, v, error)) = + let expected_size = footprint v in + let _, size = Script_typed_ir_size.value_size ty v in + let size = Saturation_repr.to_int size in + fail_when + (expected_size + error < size || size < expected_size) + (err + (Printf.sprintf + "%s was expected to have size %d while the size model answered %d \ + (with +%d accepted over approximation error)" + what + expected_size + size + error)) + in + List.iter_es + check + ((* + Unit_t + ====== + *) + [ex "() : unit" Unit_t ()] + (* + Int_t + ===== + *) + @ (let error = 8 in + [ + ex ~error "0 : int" Int_t Script_int.zero; + ex ~error "2^63 : int" Int_t (Script_int.of_int max_int); + ex + ~error + "37^73 : int" + Int_t + (Script_int.of_zint Z.(pow (of_int 37) 73)); + ex + ~error + "-37^73 : int" + Int_t + (Script_int.of_zint Z.(neg (pow (of_int 37) 73))); + ex + ~error + "13270006022583112970 : int" + Int_t + (get @@ Script_int.of_string "13270006022583112970"); + ] + @ exs ~error nsample show_script_int Int_t ": int") + (* + Nat_t + ===== + *) + @ (let error = 8 in + [ + ex ~error "0 : nat" Nat_t Script_int.zero_n; + ex + ~error + "2^63 : nat" + Nat_t + (get Script_int.(is_nat @@ of_int max_int)); + ex + ~error + "37^73 : int" + Nat_t + (get Script_int.(is_nat @@ of_zint Z.(pow (of_int 37) 73))); + ] + @ exs ~error nsample show_script_int Nat_t ": nat") + (* + Signature_t + =========== + *) + @ (let show fmt (Script_typed_ir.Script_signature.Signature_tag s) = + Signature.pp fmt s + in + exs ~error:8 nsample show Signature_t ": signature") + (* + String_t + ======== + *) + @ (let show fmt s = Format.fprintf fmt "%s" (Script_string.to_string s) in + exs nsample show String_t ": string") + (* + Bytes_t + ======= + *) + @ (let show fmt s = Format.fprintf fmt "%s" (Bytes.to_string s) in + exs nsample show Bytes_t ": bytes") + (* + Mutez_t + ======= + *) + @ (let show fmt t = Format.fprintf fmt "%s" (Tez.to_string t) in + exs nsample show Mutez_t ": mutez") + (* + Key_hash_t + ========== + *) + @ (let show = Signature.Public_key_hash.pp in + exs nsample show Key_hash_t ": key_hash") + (* + Key_t + ===== + *) + @ (let show = Signature.Public_key.pp in + exs nsample show Key_t ": key_t") + (* + Timestamp_t + =========== + *) + @ (let show fmt s = + Format.fprintf fmt "%s" (Script_timestamp.to_string s) + in + exs ~error:8 nsample show Timestamp_t ": timestamp_t") + (* + Address_t + ========= + *) + @ exs nsample show_address Address_t ": address_t" + (* + Bool_t + ====== + *) + @ [ex "true : bool" Bool_t true; ex "false : bool" Bool_t false] + (* + Pair_t + ====== + *) + @ (let module P = struct + type ('a, 'b) f = {apply : 'c. ('a * 'b, 'c) ty -> ex} + end in + let on_pair : type a b. (a, _) ty -> (b, _) ty -> (a, b) P.f -> ex = + fun ty1 ty2 f -> + let (Ty_ex_c ty) = is_ok @@ pair_t dummy_loc ty1 ty2 in + f.apply ty + in + let open Script_int in + [ + (* "int * int" *) + on_pair + int_t + int_t + {apply = (fun ty -> ex "(0, 0) : int * int" ty (of_int 0, of_int 0))}; + (* "string * string" *) + on_pair + string_t + string_t + { + apply = + (fun ty -> + let foo = gen_string "foo" in + let bar = gen_string "bar" in + ex "(foo, bar) : string * string" ty (foo, bar)); + }; + (* "string * int" *) + on_pair + string_t + int_t + { + apply = + (fun ty -> + let foo = gen_string "foo" in + ex "(foo, 0) : string * int" ty (foo, of_int 0)); + }; + (* "int * int * int" *) + on_pair + int_t + int_t + { + apply = + (fun ty -> + on_pair int_t ty + @@ { + apply = + (fun ty -> + ex + "(0, (1, 2)) : int * int * int" + ty + (of_int 0, (of_int 1, of_int 2))); + }); + }; + ]) + (* + Or_t + ======= + *) + @ (let module P = struct + type ('a, 'b) f = {apply : 'c. (('a, 'b) or_, 'c) ty -> ex} + end in + let on_or : type a b. (a, _) ty -> (b, _) ty -> (a, b) P.f -> ex = + fun ty1 ty2 f -> + let (Ty_ex_c ty) = is_ok @@ or_t dummy_loc ty1 ty2 in + f.apply ty + in + let open Script_int in + [ + (* "int + int" *) + on_or + int_t + int_t + {apply = (fun ty -> ex "L 0 : int + int" ty (L (of_int 0)))}; + on_or + int_t + int_t + {apply = (fun ty -> ex "R 0 : int + int" ty (R (of_int 0)))}; + (* "string + string" *) + on_or + string_t + string_t + { + apply = + (fun ty -> + let foo = gen_string "foo" in + ex "L foo : string * string" ty (L foo)); + }; + on_or + string_t + string_t + { + apply = + (fun ty -> + let foo = gen_string "foo" in + ex "R foo : string * string" ty (R foo)); + }; + (* "string + int" *) + on_or + string_t + int_t + { + apply = + (fun ty -> + let foo = gen_string "foo" in + ex "L foo : string * int" ty (L foo)); + }; + (* "int + int + int" *) + on_or + int_t + int_t + { + apply = + (fun ty -> + on_or + int_t + ty + { + apply = + (fun ty -> ex "L 0 : int + int + int" ty (L (of_int 0))); + }); + }; + on_or + int_t + int_t + { + apply = + (fun ty -> + on_or + int_t + ty + { + apply = + (fun ty -> + ex "R (L 0) : int + int + int" ty (R (L (of_int 0)))); + }); + }; + on_or + int_t + int_t + { + apply = + (fun ty -> + on_or + int_t + ty + { + apply = + (fun ty -> + ex "R (R 0) : int + int + int" ty (R (R (of_int 0)))); + }); + }; + ]) + (* + Option_t + ======== + *) + @ (let module P = struct + type 'a f = {apply : 'c. ('a option, 'c) ty -> ex} + end in + let on_option : type a. (a, _) ty -> a P.f -> ex = + fun ty f -> f.apply @@ is_ok @@ option_t dummy_loc ty + in + let open Script_int in + [ + (* "option int" *) + on_option int_t {apply = (fun ty -> ex "None : option int" ty None)}; + on_option + int_t + {apply = (fun ty -> ex "Some 0 : option int" ty (Some (of_int 0)))}; + (* "option string" *) + on_option + string_t + {apply = (fun ty -> ex "None : option string" ty None)}; + on_option + string_t + { + apply = + (fun ty -> + ex "Some \"foo\" : option string" ty (Some (gen_string "foo"))); + }; + ]) + (* + List_t + ====== + *) + @ (let module P = struct + type 'a f = {apply : 'c. ('a Script_list.t, 'c) ty -> ex list} + end in + let on_list : type a. (a, _) ty -> a P.f -> ex list = + fun ty f -> f.apply @@ is_ok @@ list_t dummy_loc ty + in + let check ty show_elt = + on_list + ty + { + apply = + (fun ty -> + let show fmt l = + Format.pp_print_list show_elt fmt @@ Script_list.to_list l + in + exs nsample show ty ": list _"); + } + in + check string_t show_script_string) + (* + Set_t + ====== + *) + @ (let module P = struct + type 'a f = {apply : 'c. ('a set, 'c) ty -> ex list} + end in + let on_set : type a. (a, _) ty -> a P.f -> ex list = + fun ty f -> f.apply @@ is_ok @@ set_t dummy_loc ty + in + let check ty show_elt = + on_set + ty + { + apply = + (fun ty -> + let show fmt s = + Format.fprintf + fmt + "%a / %a" + show_script_int + (Script_set.size s) + (Format.pp_print_list show_elt) + (boxed_set_elements s) + in + exs nsample show ty ": set _"); + } + in + check string_t show_script_string) + (* + Map_t + ====== + *) + @ (let module P = struct + type ('k, 'v) f = {apply : 'c. (('k, 'v) map, 'c) ty -> ex list} + end in + let on_map : type k v. (k, _) ty -> (v, _) ty -> (k, v) P.f -> ex list = + fun kty vty f -> f.apply @@ is_ok @@ map_t dummy_loc kty vty + in + let check kty vty show_key show_value = + on_map + kty + vty + { + apply = + (fun ty -> + let show_binding fmt (k, v) = + Format.fprintf fmt "(%a -> %a)" show_key k show_value v + in + let show fmt s = + Format.pp_print_list show_binding fmt (boxed_map_bindings s) + in + exs nsample show ty ": map _"); + } + in + check string_t string_t show_script_string show_script_string) + (* + Big_map_t + ====== + *) + @ (let module P = struct + type ('k, 'v) f = {apply : 'c. (('k, 'v) big_map, 'c) ty -> ex list} + end in + let on_big_map : type k v. (k, _) ty -> (v, _) ty -> (k, v) P.f -> ex list + = + fun kty vty f -> f.apply @@ is_ok @@ big_map_t dummy_loc kty vty + in + let check kty vty show_key show_value = + on_big_map + kty + vty + { + apply = + (fun ty -> + let show_binding fmt (_, (k, v)) = + match v with + | Some v -> + Format.fprintf fmt "(%a -> %a)" show_key k show_value v + | None -> Format.fprintf fmt "(%a?)" show_key k + in + let show fmt s = + Format.pp_print_list show_binding fmt (big_map_bindings s) + in + exs nsample show ty ": big_map _"); + } + in + check bool_t bool_t show_bool show_bool) + (* + Contract_t + ========= + *) + @ (let show fmt typed_contract = + let destination = Typed_contract.destination typed_contract in + let entrypoint = Typed_contract.entrypoint typed_contract in + show_address fmt {destination; entrypoint} + in + exs + nsample + show + (is_ok @@ contract_t dummy_loc string_t) + ": contract string") + (* + Chain_t + ========= + *) + @ exs nsample dont_show chain_id_t ": chain_id" + (* + Bls12_381_g1_t + ============== + *) + @ exs nsample dont_show bls12_381_g1_t ": bls12_381_g1_t" + (* + Bls12_381_g2_t + ============== + *) + @ exs nsample dont_show bls12_381_g2_t ": bls12_381_g2_t" + (* + Bls12_381_fr_t + ============== + *) + @ exs nsample dont_show bls12_381_fr_t ": bls12_381_fr_t" + (* + Ticket_t + ======== + *) + @ exs + ~error:8 + nsample + dont_show + (is_ok @@ ticket_t dummy_loc bool_t) + ": ticket bool" + (* + Missing by lack of fully functional samplers: + - Sapling_transaction_t ; + - Sapling_transaction_deprecated_t ; + - Sapling_state ; + - Operation_t ; + - Chest_key_t ; + - Chest_t ; + - Lambda_t. + Missing because of language deprecation: + - Tx_rollup_l2_address_t. + *) + ) + +let check_ty_size () = + let check () = + match (sample_ty (Random.int 10 + 1) : ex_ty) with + | Ex_ty ty -> + let expected_size = footprint ty in + let _, size = Script_typed_ir_size.Internal_for_tests.ty_size ty in + let size = Saturation_repr.to_int size in + let what = "some type" in + fail_when + (size <> expected_size) + (err + (Printf.sprintf + "%s was expected to have size %d while the size model answered \ + %d." + what + expected_size + size)) + in + List.iter_es (fun _ -> check ()) (1 -- nsample) + +let check_size ~name ~expected item = + let open Lwt_result_syntax in + let _, e = expected item in + let exp = Saturation_repr.to_int e in + let actual = 8 * Obj.(reachable_words @@ repr item) in + let overapprox = 1_000_000 * (exp - actual) / actual in + let msg verb = + Printf.sprintf + "For %s model predicts the size of %d bytes; while actual measured size \ + is %d bytes. The model %s %d.%04d%%" + name + exp + actual + verb + (abs @@ (overapprox / 10_000)) + (abs @@ (overapprox mod 10_000)) + in + let* () = fail_when (overapprox < 0) (err @@ msg "under-approximates by") in + fail_when (overapprox > 0) (err @@ msg "over-approximates by") +(* We expected the model to always be exact. *) + +(* Test that the model accurately predicts instruction sizes. It tests each + type of instruction separately as much as possible. Tested values are + specifically tailored so that they can't be shared (in particular all + reused values are wrapped in functions to discourage sharing). Thanks + to this the model gives precise predictions for each instruction. In real + life the model will over-approximate due to sharing. It should never under- + approximate though. *) +let check_kinstr_size () = + let open Lwt_result_syntax in + let check (Kinstr (name, instr)) = + check_size + ~name + ~expected:Script_typed_ir_size.Internal_for_tests.kinstr_size + instr + in + (* Location is an immediate value, so we don't care if it's shared. *) + let loc = Micheline.dummy_location in + let str s = + (* It's important to transform the string somehow, or else it will be shared + and thus not reached by Obj.reachable_words. *) + match Script_string.of_string @@ String.uppercase_ascii s with + | Ok ss -> ss + | Error _ -> assert false + in + let entrypoint name = + Entrypoint.of_string_strict_exn @@ String.uppercase_ascii name + in + (* Constants below are wrapped in functions to force recomputation and + discourage sharing. *) + let halt () = IHalt loc in + let drop () = IDrop (loc, halt ()) in + let cdr = ICdr (loc, halt ()) in + let push ty v = IPush (loc, ty, v, halt ()) in + let unit_option_t () = + WithExceptions.Result.get_ok ~loc:__LOC__ @@ option_t loc Unit_t + in + let stack_type () = Item_t (unit_option_t (), Bot_t) in + let id_lambda () = + Lam + ( { + kloc = loc; + kbef = stack_type (); + kaft = stack_type (); + kinstr = halt (); + }, + Micheline.Seq (loc, []) ) + in + (* Following constants are used but once. *) + let zero_memo_size = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Alpha_context.Sapling.Memo_size.parse_z Z.zero + in + (* Check size of the lambda alone. *) + let* () = + check_size + ~name:"id lambda" + ~expected:Script_typed_ir_size.lambda_size + (id_lambda ()) + in + (* Testing individual instructions. *) + List.iter_es + check + [ + Kinstr ("IDrop", drop ()); + Kinstr ("IDup", IDup (loc, halt ())); + Kinstr ("ISwap", ISwap (loc, halt ())); + Kinstr ("IPush", push String_t @@ str "tezos"); + Kinstr ("ICons_pair", ICons_pair (loc, halt ())); + Kinstr ("ICar", ICar (loc, halt ())); + Kinstr ("ICdr", cdr); + Kinstr ("IUnpair", IUnpair (loc, halt ())); + Kinstr ("ICons_some", ICons_some (loc, halt ())); + Kinstr ("ICons_none", ICons_none (loc, Int_t, halt ())); + Kinstr + ( "IIf_none", + IIf_none + { + loc; + branch_if_some = drop (); + branch_if_none = halt (); + k = halt (); + } ); + Kinstr ("IOpt_map", IOpt_map {loc; body = halt (); k = halt ()}); + Kinstr ("ICons_left", ICons_left (loc, Nat_t, halt ())); + Kinstr ("ICons_right", ICons_right (loc, Int_t, halt ())); + Kinstr + ( "IIf_left", + IIf_left + { + loc; + branch_if_left = drop (); + branch_if_right = drop (); + k = halt (); + } ); + Kinstr ("ICons_list", ICons_list (loc, halt ())); + Kinstr ("INil", INil (loc, Bytes_t, halt ())); + Kinstr + ( "IIf_cons", + IIf_cons + { + loc; + branch_if_cons = IDrop (loc, drop ()); + branch_if_nil = halt (); + k = halt (); + } ); + Kinstr ("IList_map", IList_map (loc, halt (), None, halt ())); + Kinstr ("IList_iter", IList_iter (loc, None, drop (), halt ())); + Kinstr ("IList_size", IList_size (loc, halt ())); + Kinstr ("IEmpty_set", IEmpty_set (loc, String_t, halt ())); + Kinstr ("ISet_iter", ISet_iter (loc, None, drop (), halt ())); + Kinstr ("ISet_mem", ISet_mem (loc, halt ())); + Kinstr ("ISet_update", ISet_update (loc, halt ())); + Kinstr ("ISet_size", ISet_size (loc, halt ())); + Kinstr ("IEmpty_map", IEmpty_map (loc, Nat_t, None, halt ())); + Kinstr ("IMap_map", IMap_map (loc, None, cdr, halt ())); + Kinstr ("IMap_iter", IMap_iter (loc, None, drop (), halt ())); + Kinstr ("IMap_mem", IMap_mem (loc, halt ())); + Kinstr ("IMap_get", IMap_get (loc, halt ())); + Kinstr ("IMap_update", IMap_update (loc, halt ())); + Kinstr ("IMap_get_and_update", IMap_get_and_update (loc, halt ())); + Kinstr ("IMap_size", IMap_size (loc, halt ())); + Kinstr ("IEmpty_big_map", IEmpty_big_map (loc, Nat_t, String_t, halt ())); + Kinstr ("IBig_map_mem", IBig_map_mem (loc, halt ())); + Kinstr ("IBig_map_get", IBig_map_get (loc, halt ())); + Kinstr ("IBig_map_update", IBig_map_update (loc, halt ())); + Kinstr ("IBig_map_get_and_update", IBig_map_get_and_update (loc, halt ())); + Kinstr ("IConcat_string", IConcat_string (loc, halt ())); + Kinstr ("IConcat_string_pair", IConcat_string_pair (loc, halt ())); + Kinstr ("ISlice_string", ISlice_string (loc, halt ())); + Kinstr ("IString_size", IString_size (loc, halt ())); + Kinstr ("IConcat_bytes", IConcat_bytes (loc, halt ())); + Kinstr ("IConcat_bytes_pair", IConcat_bytes_pair (loc, halt ())); + Kinstr ("ISlice_bytes", ISlice_bytes (loc, halt ())); + Kinstr ("IBytes_size", IBytes_size (loc, halt ())); + Kinstr + ("IAdd_seconds_to_timestamp ", IAdd_seconds_to_timestamp (loc, halt ())); + Kinstr + ("IAdd_timestamp_to_seconds", IAdd_timestamp_to_seconds (loc, halt ())); + Kinstr ("ISub_timestamp_seconds", ISub_timestamp_seconds (loc, halt ())); + Kinstr ("IDiff_timestamps", IDiff_timestamps (loc, halt ())); + Kinstr ("IAdd_tez", IAdd_tez (loc, halt ())); + Kinstr ("ISub_tez", ISub_tez (loc, halt ())); + Kinstr ("ISub_tez_legacy", ISub_tez_legacy (loc, halt ())); + Kinstr ("IMul_tez_nat", IMul_teznat (loc, halt ())); + Kinstr ("IMul_nattez", IMul_nattez (loc, halt ())); + Kinstr ("IEdiv_teznat", IEdiv_teznat (loc, halt ())); + Kinstr ("IEdiv_nattez", IEdiv_tez (loc, halt ())); + Kinstr ("IOr", IOr (loc, halt ())); + Kinstr ("IAnd", IAnd (loc, halt ())); + Kinstr ("IXor", IXor (loc, halt ())); + Kinstr ("INot", INot (loc, halt ())); + Kinstr ("IIs_nat", IIs_nat (loc, halt ())); + Kinstr ("INeg", INeg (loc, halt ())); + Kinstr ("IAbs_int", IAbs_int (loc, halt ())); + Kinstr ("IInt_nat", IInt_nat (loc, halt ())); + Kinstr ("IAdd_int", IAdd_int (loc, halt ())); + Kinstr ("IAdd_nat", IAdd_nat (loc, halt ())); + Kinstr ("ISub_int", ISub_int (loc, halt ())); + Kinstr ("IMul_int", IMul_int (loc, halt ())); + Kinstr ("IMul_nat", IMul_nat (loc, halt ())); + Kinstr ("IEdiv_int", IEdiv_int (loc, halt ())); + Kinstr ("IEdiv_nat", IEdiv_nat (loc, halt ())); + Kinstr ("ILsl_nat", ILsl_nat (loc, halt ())); + Kinstr ("ILsr_nat", ILsr_nat (loc, halt ())); + Kinstr ("IOr_nat", IOr_nat (loc, halt ())); + Kinstr ("IAnd_nat", IAnd_nat (loc, halt ())); + Kinstr ("IAnd_int_nat", IAnd_int_nat (loc, halt ())); + Kinstr ("IXor_nat", IXor_nat (loc, halt ())); + Kinstr ("INot_int", INot_int (loc, halt ())); + Kinstr ("IAnd_bytes", IAnd_bytes (loc, halt ())); + Kinstr ("IOr_bytes", IOr_bytes (loc, halt ())); + Kinstr ("IXor_bytes", IXor_bytes (loc, halt ())); + Kinstr ("INot_bytes", INot_bytes (loc, halt ())); + Kinstr ("ILsl_bytes", ILsl_bytes (loc, halt ())); + Kinstr ("ILsr_bytes", ILsr_bytes (loc, halt ())); + Kinstr + ( "IIf", + IIf + { + loc; + branch_if_true = halt (); + branch_if_false = halt (); + k = halt (); + } ); + Kinstr ("ILoop", ILoop (loc, push Bool_t true, halt ())); + Kinstr ("ILoop_left", ILoop_left (loc, INever loc, halt ())); + Kinstr ("IDip", IDip (loc, halt (), None, halt ())); + Kinstr ("IExec", IExec (loc, None, halt ())); + Kinstr ("IApply", IApply (loc, String_t, halt ())); + Kinstr ("ILambda", ILambda (loc, id_lambda (), halt ())); + Kinstr ("IFailwith", IFailwith (loc, String_t)); + Kinstr ("ICompare", ICompare (loc, String_t, halt ())); + Kinstr ("IEq", IEq (loc, halt ())); + Kinstr ("INeq", INeq (loc, halt ())); + Kinstr ("ILt", ILt (loc, halt ())); + Kinstr ("IGt", IGt (loc, halt ())); + Kinstr ("ILe", ILe (loc, halt ())); + Kinstr ("IGe", IGe (loc, halt ())); + Kinstr ("IAddress", IAddress (loc, halt ())); + Kinstr ("IContract", IContract (loc, Unit_t, entrypoint "entry", halt ())); + Kinstr + ( "IView", + IView + ( loc, + View_signature + { + name = str "myview"; + input_ty = unit_option_t (); + output_ty = unit_option_t (); + }, + None, + halt () ) ); + Kinstr ("ITransfer_tokens", ITransfer_tokens (loc, halt ())); + Kinstr ("IImplicit_account", IImplicit_account (loc, halt ())); + Kinstr + ( "ICreate_contract", + ICreate_contract + { + loc; + storage_type = Unit_t; + code = Micheline.(strip_locations @@ Seq (loc, [])); + k = halt (); + } ); + Kinstr ("ISet_delegate", ISet_delegate (loc, halt ())); + Kinstr ("INow", INow (loc, halt ())); + Kinstr ("IMin_block_time", IMin_block_time (loc, halt ())); + Kinstr ("IBalance", IBalance (loc, halt ())); + Kinstr ("ILevel", ILevel (loc, halt ())); + Kinstr ("ICheck_signature", ICheck_signature (loc, halt ())); + Kinstr ("IHash_key", IHash_key (loc, halt ())); + Kinstr ("IPack", IPack (loc, Int_t, halt ())); + Kinstr ("IUnpack", IUnpack (loc, Int_t, halt ())); + Kinstr ("IBlake2b", IBlake2b (loc, halt ())); + Kinstr ("ISha_256", ISha256 (loc, halt ())); + Kinstr ("ISha512", ISha512 (loc, halt ())); + Kinstr ("ISource", ISource (loc, halt ())); + Kinstr ("ISender", ISender (loc, halt ())); + Kinstr ("ISelf", ISelf (loc, Unit_t, entrypoint "entry", halt ())); + Kinstr ("ISelf_address", ISelf_address (loc, halt ())); + Kinstr ("IAmount", IAmount (loc, halt ())); + Kinstr + ( "ISapling_empty_state", + ISapling_empty_state (loc, zero_memo_size, halt ()) ); + Kinstr ("ISapling_verify_update", ISapling_verify_update (loc, halt ())); + Kinstr + ( "ISapling_verify_update_deprecated", + ISapling_verify_update_deprecated (loc, halt ()) ); + Kinstr ("IDig", IDig (loc, 0, KRest, halt ())); + Kinstr ("IDug", IDug (loc, 0, KRest, halt ())); + Kinstr ("IDipn", IDipn (loc, 0, KRest, halt (), halt ())); + Kinstr ("IDropn", IDropn (loc, 0, KRest, halt ())); + Kinstr ("IChainId", IChainId (loc, halt ())); + Kinstr ("INever", INever loc); + Kinstr ("IVoting_power", IVoting_power (loc, halt ())); + Kinstr ("ITotal_voting_power", ITotal_voting_power (loc, halt ())); + Kinstr ("IKeccak", IKeccak (loc, halt ())); + Kinstr ("ISha3", ISha3 (loc, halt ())); + Kinstr ("IAdd_bls12_381_g1", IAdd_bls12_381_g1 (loc, halt ())); + Kinstr ("IAdd_bls12_381_2g", IAdd_bls12_381_g2 (loc, halt ())); + Kinstr ("IAdd_bls12_381_fr", IAdd_bls12_381_fr (loc, halt ())); + Kinstr ("IMul_bls12_381_g1", IMul_bls12_381_g1 (loc, halt ())); + Kinstr ("IMul_bls12_381_g2", IMul_bls12_381_g2 (loc, halt ())); + Kinstr ("IMul_bls12_381_fr", IMul_bls12_381_fr (loc, halt ())); + Kinstr ("IMul_bls12_381_z_fr", IMul_bls12_381_z_fr (loc, halt ())); + Kinstr ("IMul_bls12_381_fr_z", IMul_bls12_381_fr_z (loc, halt ())); + Kinstr ("IMul_bls12_381_fr_z", IMul_bls12_381_fr_z (loc, halt ())); + Kinstr ("IInt_bls12_381_fr", IInt_bls12_381_fr (loc, halt ())); + Kinstr ("INeg_bls12_381_g1", INeg_bls12_381_g1 (loc, halt ())); + Kinstr ("INeg_bls12_381_g2", INeg_bls12_381_g2 (loc, halt ())); + Kinstr ("INeg_bls12_381_fr", INeg_bls12_381_fr (loc, halt ())); + Kinstr + ("IPairing_check_bls12_381", IPairing_check_bls12_381 (loc, halt ())); + Kinstr ("IComb", IComb (loc, 0, Comb_one, halt ())); + Kinstr ("IUncomb", IUncomb (loc, 0, Uncomb_one, halt ())); + Kinstr ("IComb_get", IComb_get (loc, 0, Comb_get_zero, halt ())); + Kinstr ("IComb_set", IComb_set (loc, 0, Comb_set_zero, halt ())); + Kinstr ("IDup_n", IDup_n (loc, 0, Dup_n_zero, halt ())); + Kinstr ("ITicket", ITicket (loc, None, halt ())); + Kinstr ("IRead_ticket", IRead_ticket (loc, None, halt ())); + Kinstr ("ISplit_ticket", ISplit_ticket (loc, halt ())); + Kinstr ("IJoin_tickets", IJoin_tickets (loc, Unit_t, halt ())); + Kinstr ("IOpen_chest", IOpen_chest (loc, halt ())); + Kinstr + ( "IEmit", + IEmit + { + loc; + tag = entrypoint "entry"; + ty = Unit_t; + unparsed_ty = Micheline.(strip_locations @@ Seq (loc, [])); + k = halt (); + } ); + Kinstr ("IHalt ()", halt ()); + ] + +let check_witness_sizes () = + let loc = Micheline.dummy_location in + let stack_prefix_preservation = + KPrefix + ( loc, + Unit_t, + KPrefix + ( loc, + Unit_t, + KPrefix + ( loc, + Unit_t, + KPrefix + ( loc, + Unit_t, + KPrefix + ( loc, + Unit_t, + KPrefix + ( loc, + Unit_t, + KPrefix (loc, Unit_t, KPrefix (loc, Unit_t, KRest)) + ) ) ) ) ) ) + in + check_size + ~name:"stack_prefix_preservation_witness" + ~expected: + Script_typed_ir_size.Internal_for_tests + .stack_prefix_preservation_witness_size + stack_prefix_preservation + +let check_micheline_sizes () = + let open Michelson_v1_primitives in + let check (name, micheline) = + check_size ~name ~expected:Cache_memory_helpers.node_size micheline + in + let int i = Micheline.(Int (dummy_loc, Z.of_int i)) in + let big_int z = Micheline.(Int (dummy_loc, z)) in + let str s = Micheline.(String (dummy_location, String.lowercase_ascii s)) in + let bytes b = Micheline.(Bytes (dummy_location, Bytes.of_string b)) in + let prim ?(annot = []) p args = + Micheline.(Prim (dummy_location, p, args, annot)) + in + let seq xs = Micheline.(Seq (dummy_location, xs)) in + List.iter_es + check + [ + ("empty micheline", seq []); + ("a single number", int 1024); + ("a large number", big_int Z.(of_int 3 * of_int max_int)); + ("a short string", str "tezostezostezos"); + ("a short bytestring", bytes "tezostezostezos"); + ("a prim with no args", prim I_UNIT []); + ("a seq of prims", seq [prim I_DUP []; prim I_DROP []]); + ("a prim with arg", prim I_DIG [int 2]); + ( "combine everything together", + seq + [ + prim I_UNIT []; + prim I_DUG [int 3] ~annot:[String.lowercase_ascii "@number"]; + prim I_DIP [seq [prim I_DROP [int 2]]]; + prim I_PUSH [prim T_string []; str "tezos"]; + ] ); + ] + +let tests = + let open Tztest in + [ + tztest "value size" `Quick check_value_size; + tztest "ty size" `Quick check_ty_size; + tztest "kinstr size" `Quick check_kinstr_size; + tztest "witness sizes" `Quick check_witness_sizes; + tztest "micheline sizes" `Quick check_micheline_sizes; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("script typed ir size", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_temp_big_maps.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_temp_big_maps.ml new file mode 100644 index 000000000000..2b5cdb834057 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_temp_big_maps.ml @@ -0,0 +1,118 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (temporary big maps) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_temp_big_maps.ml + Subject: On temporary big maps. +*) + +open Protocol + +let to_raw_context (b : Block.t) = + let open Lwt_result_wrap_syntax in + let+@ ctxt = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + ctxt + +let check_no_dangling_temp_big_map b = + let open Lwt_result_syntax in + let* ctxt = to_raw_context b in + let*! () = + Storage.Big_map.fold ctxt ~init:() ~order:`Sorted ~f:(fun id () -> + assert (not (Lazy_storage_kind.Big_map.Id.is_temp id)) ; + Lwt.return_unit) + in + let*! () = + Storage.Big_map.fold ctxt ~init:() ~order:`Undefined ~f:(fun id () -> + assert (not (Lazy_storage_kind.Big_map.Id.is_temp id)) ; + Lwt.return_unit) + in + return_unit + +let call_the_contract b ~baker ~src contract param_left param_right = + let open Lwt_result_syntax in + let fee = Alpha_context.Tez.one in + let amount = Alpha_context.Tez.zero in + let param = Printf.sprintf "Pair (%s) %s" param_left param_right in + let parameters = Alpha_context.Script.lazy_expr (Expr.from_string param) in + let* operation = Op.transaction ~fee (B b) src contract amount ~parameters in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) b + in + let* incr = Incremental.add_operation incr operation in + Incremental.finalize_block incr + +let path = project_root // Filename.dirname __FILE__ + +(** Originates the contract at contracts/temp_big_maps.tz and calls it with + the pair [(param_left, param_right)]. + An action (originating, storing, passing, passing twice) is done on a big + map (either fresh, passed, or stored). + All combinations are exercised. +*) +let test_temp_big_maps_contract param_left param_right () = + let open Lwt_result_syntax in + let* b, baker, src, _src2 = Contract_helpers.init () in + let* contract, b = + Contract_helpers.originate_contract + (path // "contracts/temp_big_maps.tz") + "{}" + src + b + baker + in + let* () = check_no_dangling_temp_big_map b in + let* b = call_the_contract b ~baker ~src contract param_left param_right in + check_no_dangling_temp_big_map b + +let param_left_values = ["Left True"; "Left False"; "Right {}"] + +let param_right_values = ["-1"; "0"; "1"; "2"] + +let tests = + List.flatten + (List.map + (fun param_left -> + List.map + (fun param_right -> + Tztest.tztest + (Printf.sprintf "temp_big_maps(%s, %s)" param_left param_right) + `Quick + (test_temp_big_maps_contract param_left param_right)) + param_right_values) + param_left_values) + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("temp big maps", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_accounting.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_accounting.ml new file mode 100644 index 000000000000..7c573262dfc7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_accounting.ml @@ -0,0 +1,1447 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_scanner) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_accounting.ml + Subject: Ticket scanner tests +*) + +open Protocol +open Alpha_context +open Script_typed_ir + +let assert_equal_string_list ~loc msg = + Assert.assert_equal_list ~loc String.equal msg Format.pp_print_string + +let assert_fail_with ~loc ~msg f = + let open Lwt_result_wrap_syntax in + let*!@ res = f () in + match res with + | Error [x] -> + let x = Format.asprintf "%a" Error_monad.pp x in + Assert.equal ~loc String.equal "" Format.pp_print_string msg x + | Ok _ -> failwith "Expected an error at %s, but got `Ok'." loc + | Error _ -> failwith "Expected a single error at %s." loc + +let string_list_of_ex_token_diffs ctxt token_diffs = + let open Lwt_result_wrap_syntax in + let accum (xs, ctxt) + (Ticket_token.Ex_token {ticketer; contents_type; contents}, amount) = + let*@ x, ctxt = + Script_ir_unparser.unparse_comparable_data + ctxt + Script_ir_unparser.Readable + contents_type + contents + in + let str = + Format.asprintf + {|{ticketer: "%a"; contents: %a; amount: %a}|} + Contract.pp + ticketer + Michelson_v1_printer.print_expr + x + Z.pp_print + amount + in + return (str :: xs, ctxt) + in + let* xs, ctxt = List.fold_left_es accum ([], ctxt) token_diffs in + return (List.rev xs, ctxt) + +let make_ex_token ctxt ~ticketer ~type_exp ~content_exp = + let open Lwt_result_wrap_syntax in + let*?@ Script_ir_translator.Ex_comparable_ty contents_type, ctxt = + let node = Micheline.root @@ Expr.from_string type_exp in + Script_ir_translator.parse_comparable_ty ctxt node + in + let*?@ ticketer = Contract.of_b58check ticketer in + let*@ contents, ctxt = + let node = Micheline.root @@ Expr.from_string content_exp in + Script_ir_translator.parse_comparable_data ctxt contents_type node + in + return (Ticket_token.Ex_token {ticketer; contents_type; contents}, ctxt) + +let assert_equal_ticket_diffs ~loc ctxt given expected = + let open Lwt_result_syntax in + let* ctxt, tbs1 = + List.fold_left_map_es + (fun ctxt ((ticketer, content), delta) -> + let+ token, ctxt = + make_ex_token + ctxt + ~ticketer + ~type_exp:"string" + ~content_exp:(Printf.sprintf "%S" content) + in + (ctxt, (token, Z.of_int delta))) + ctxt + expected + in + let* tbs1, ctxt = string_list_of_ex_token_diffs ctxt tbs1 in + let* tbs2, _ctxt = string_list_of_ex_token_diffs ctxt given in + assert_equal_string_list + ~loc + "Compare token balances" + (List.sort String.compare tbs1) + (List.sort String.compare tbs2) + +let assert_equal_ticket_receipt ~loc given expected = + let open Lwt_result_wrap_syntax in + let make_receipt_item (ticketer, content, updates) = + let*?@ ticketer = Contract.of_b58check ticketer in + let contents = Expr.from_string (Printf.sprintf "%S" content) in + let contents_type = Expr.from_string "string" in + let ticket_token = Ticket_token.{ticketer; contents_type; contents} in + let updates = + List.map + (fun (account, amount) -> + let account = Destination.Contract account in + let amount = Z.of_int amount in + Ticket_receipt.{account; amount}) + updates + in + return Ticket_receipt.{ticket_token; updates} + in + let* expected = List.map_es make_receipt_item expected in + Assert.equal_with_encoding + ~loc + (Data_encoding.list Ticket_receipt.item_encoding) + expected + given + +let updates_of_key_values ctxt ~key_type ~value_type key_values = + let open Lwt_result_wrap_syntax in + List.fold_right_es + (fun (key, value) (kvs, ctxt) -> + let*@ key_hash, ctxt = + Script_ir_translator.hash_comparable_data ctxt key_type key + in + let*@ key, ctxt = + Script_ir_unparser.unparse_comparable_data + ctxt + Script_ir_unparser.Readable + key_type + key + in + let* value, ctxt = + match value with + | None -> return (None, ctxt) + | Some value -> + let*@ value_node, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Readable + value_type + value + in + return (Some value_node, ctxt) + in + return ({Big_map.key; key_hash; value} :: kvs, ctxt)) + key_values + ([], ctxt) + +let make_alloc big_map_id alloc updates = + Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update {init = Lazy_storage.Alloc alloc; updates}) + +let init () = + let open Lwt_result_syntax in + let* block, source = Context.init1 () in + let* operation, originated = + Op.contract_origination_hash (B block) source ~script:Op.dummy_script + in + let* block = Block.bake ~operation block in + let* inc = Incremental.begin_construction block in + return (originated, Incremental.alpha_ctxt inc) + +(** Initializes one address for operations and one baker. *) +let init_for_operation () = + let open Lwt_result_syntax in + let+ block, (src0, src1) = Context.init2 ~consensus_threshold:0 () in + let baker = Context.Contract.pkh src0 in + (baker, src1, block) + +let two_ticketers block = + let open Lwt_result_syntax in + let* result = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt result in + let*! cs = Contract.list ctxt in + match cs with c1 :: c2 :: _ -> return (c1, c2) | _ -> assert false + +let ticket_list_script = + {| + { parameter (list (ticket string)); + storage (list (ticket string)); + code { CAR; NIL operation ; PAIR } } + |} + +let setup ctxt ~key_type ~value_type entries = + let open Lwt_result_wrap_syntax in + let*@ ctxt, big_map_id = Big_map.fresh ~temporary:false ctxt in + let* updates, ctxt = + updates_of_key_values + ctxt + ~key_type + ~value_type + (List.map (fun (k, v) -> (k, Some v)) entries) + in + let*?@ key_type_node, ctxt = + Script_ir_unparser.unparse_ty ~loc:Micheline.dummy_location ctxt key_type + in + let*?@ value_type_node, ctxt = + Script_ir_unparser.unparse_ty ~loc:Micheline.dummy_location ctxt value_type + in + let key_type = Micheline.strip_locations key_type_node in + let value_type = Micheline.strip_locations value_type_node in + let alloc = make_alloc big_map_id Big_map.{key_type; value_type} updates in + return (alloc, big_map_id, ctxt) + +let new_big_map ctxt contract ~key_type ~value_type entries = + let open Lwt_result_wrap_syntax in + let* alloc, big_map_id, ctxt = setup ctxt ~key_type ~value_type entries in + let storage = Expr.from_string "{}" in + let*@ ctxt = + Contract.update_script_storage ctxt contract storage (Some [alloc]) + in + return (big_map_id, ctxt) + +let alloc_diff ctxt ~key_type ~value_type entries = + let open Lwt_result_syntax in + let* allocations, _, ctxt = setup ctxt ~key_type ~value_type entries in + return (allocations, ctxt) + +let remove_diff ctxt contract ~key_type ~value_type ~existing_entries = + let open Lwt_result_syntax in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type existing_entries + in + return (Lazy_storage.make Lazy_storage.Kind.Big_map big_map_id Remove, ctxt) + +let copy_diff ctxt contract ~key_type ~value_type ~existing_entries ~updates = + let open Lwt_result_wrap_syntax in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type existing_entries + in + let* updates, ctxt = + updates_of_key_values ctxt ~key_type ~value_type updates + in + let*@ ctxt, new_big_map_id = Big_map.fresh ctxt ~temporary:false in + return + ( Lazy_storage.make + Lazy_storage.Kind.Big_map + new_big_map_id + (Update {init = Lazy_storage.Copy {src = big_map_id}; updates}), + ctxt ) + +let existing_diff ctxt contract ~key_type ~value_type ~existing_entries ~updates + = + let open Lwt_result_syntax in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type existing_entries + in + let* updates, ctxt = + updates_of_key_values ctxt ~key_type ~value_type updates + in + return + ( Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update {init = Lazy_storage.Existing; updates}), + ctxt ) + +let empty_big_map ctxt ~key_type ~value_type = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let*@ ctxt, big_map_id = Big_map.fresh ~temporary:false ctxt in + return + ( Big_map + { + id = Some big_map_id; + diff = {map = Big_map_overlay.empty; size = 0}; + key_type; + value_type; + }, + ctxt ) + +let make_big_map ctxt contract ~key_type ~value_type entries = + let open Lwt_result_syntax in + let open Script_typed_ir in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type entries + in + return + ( Big_map + { + id = Some big_map_id; + diff = {map = Big_map_overlay.empty; size = 0}; + key_type; + value_type; + }, + ctxt ) + +let originate_script block ~script ~storage ~sender ~baker ~forges_tickets = + let open Lwt_result_syntax in + let code = Expr.toplevel_from_string script in + let storage = Expr.from_string storage in + let* operation, destination = + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + Op.contract_origination_hash + (B block) + sender + ~fee:(Test_tez.of_int 10) + ~script + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let* incr = + Incremental.add_operation + ?expect_apply_failure: + (if forges_tickets then Some (fun _ -> return_unit) else None) + incr + operation + in + let script = (code, storage) in + let+ block = Incremental.finalize_block incr in + (destination, script, block) + +let origination_operation ctxt ~sender ~script:(code, storage) ~orig_contract = + let open Lwt_result_wrap_syntax in + let script = Script.{code = lazy_expr code; storage = lazy_expr storage} in + let unparsed_storage = storage in + let*@ ( Script_ir_translator.Ex_script + (Script + { + storage_type; + storage; + code = _; + arg_type = _; + views = _; + entrypoints = _; + code_size = _; + }), + ctxt ) = + Script_ir_translator.parse_script + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let operation = + Internal_operation + { + sender; + operation = + Origination + { + delegate = None; + code; + unparsed_storage; + credit = Tez.one; + preorigination = orig_contract; + storage_type; + storage; + }; + nonce = 1; + } + in + return (operation, ctxt) + +let originate block ~sender ~baker ~script ~storage ~forges_tickets = + let open Lwt_result_syntax in + let* orig_contract, script, block = + originate_script block ~script ~storage ~sender ~baker ~forges_tickets + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + return (orig_contract, script, incr) + +let transfer_operation ctxt ~sender ~destination ~arg_type ~arg = + let open Lwt_result_wrap_syntax in + let*@ params_node, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Readable + arg_type + arg + in + return + ( Internal_operation + { + sender; + operation = + Transaction_to_smart_contract + { + amount = Tez.zero; + unparsed_parameters = params_node; + entrypoint = Entrypoint.default; + destination; + location = Micheline.dummy_location; + parameters_ty = arg_type; + parameters = arg; + }; + nonce = 1; + }, + ctxt ) + +let ticket_string_type = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Script_typed_ir.(ticket_t (-1) string_t) + +let ticket_string_list_type = + Result.value_f ~default:(fun _ -> assert false) + @@ Script_typed_ir.list_t (-1) ticket_string_type + +let boxed_list = Script_list.of_list + +let big_map_type ~key_type ~value_type = + Script_typed_ir.big_map_t (-1) key_type value_type + +let type_has_tickets ctxt ty = Ticket_scanner.type_has_tickets ctxt ty + +(** Test that adding a ticket to a lazy storage diff is picked up. *) +let assert_ticket_diffs ctxt ~loc ~self_contract ~arg_type ~storage_type ~arg + ~old_storage ~new_storage ~lazy_storage_diff ~expected_diff + ~expected_receipt = + let open Lwt_result_wrap_syntax in + let*?@ arg_type_has_tickets, ctxt = type_has_tickets ctxt arg_type in + let*?@ storage_type_has_tickets, ctxt = type_has_tickets ctxt storage_type in + let*@ ticket_diff, ticket_receipt, ctxt = + Ticket_accounting.ticket_diffs + ctxt + ~self_contract:(Originated self_contract) + ~arg_type_has_tickets + ~storage_type_has_tickets + ~arg + ~old_storage + ~new_storage + ~lazy_storage_diff + in + let*?@ ticket_diffs, ctxt = Ticket_token_map.to_list ctxt ticket_diff in + let* () = assert_equal_ticket_diffs ~loc ctxt ticket_diffs expected_diff in + let expected_receipt = + List.map + (fun (contract, contents, amounts) -> + let amounts = + List.map + (fun (contract, amount) -> (Contract.Originated contract, amount)) + amounts + in + (contract, contents, amounts)) + expected_receipt + in + assert_equal_ticket_receipt ~loc ticket_receipt expected_receipt + +let assert_balance = Ticket_helpers.assert_balance + +let string_ticket ticketer contents amount = + let amount = + WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_n @@ Script_int.abs @@ Script_int.of_int amount + in + let ticketer = + Result.value_f ~default:(fun _ -> assert false) + @@ Contract.of_b58check ticketer + in + let contents = + Result.value_f ~default:(fun _ -> assert false) + @@ Script_string.of_string contents + in + Script_typed_ir.{ticketer; contents; amount} + +let string_ticket_token = Ticket_helpers.string_ticket_token + +let test_diffs_empty () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let*?@ int_ticket_big_map_ty = + big_map_type ~key_type:int_t ~value_type:ticket_string_type + in + (* Start with an empty big-map *) + let* empty_big_map, ctxt = + empty_big_map ctxt ~key_type:int_t ~value_type:ticket_string_type + in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:unit_t + ~storage_type:int_ticket_big_map_ty + ~arg:() + ~old_storage:empty_big_map + ~new_storage:empty_big_map + ~lazy_storage_diff:[] + ~expected_diff:[] + ~expected_receipt:[] + +(** Test that sending one ticket as an argument, when the new storage is empty + results in: + - Negative diff + - Empty receipt (since no ticket was added/removed from storage) *) +let test_diffs_tickets_in_args () = + let open Lwt_result_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let arg = string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:ticket_string_type + ~storage_type:unit_t + ~arg + ~old_storage:() + ~new_storage:() + ~lazy_storage_diff:[] + ~expected_diff:[(("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1)] + ~expected_receipt:[] + +(** Test adding a ticket to the args, which is also accounted for in the new + storage, results in: + - Empty diff + - Receipt with positive update (since one ticket was added to storage) *) +let test_diffs_tickets_in_args_and_storage () = + let open Lwt_result_syntax in + let* contract, ctxt = init () in + let arg = string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:ticket_string_type + ~storage_type:ticket_string_list_type + ~arg + ~old_storage:(boxed_list []) + ~new_storage:(boxed_list [arg]) + ~lazy_storage_diff:[] + ~expected_diff:[(("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 0)] + ~expected_receipt: + [("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, 1)])] + +(** Test that adding two tickets in the args, and only one new ticket in the + storage results in: + - Negative diff + - Receipt with single positive update (since one ticket was added to storage) *) +let test_diffs_drop_one_ticket () = + let open Lwt_result_syntax in + let* contract, ctxt = init () in + let arg = + boxed_list + [ + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1; + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 1; + ] + in + let new_storage = + boxed_list [string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1] + in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:ticket_string_list_type + ~storage_type:ticket_string_list_type + ~arg + ~old_storage:(boxed_list []) + ~new_storage + ~lazy_storage_diff:[] + ~expected_diff: + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 0); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), -1); + ] + ~expected_receipt: + [("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, 1)])] + +(** Test that adding a new ticket to the storage results in: + - Positive diff + - Receipt with single positive update *) +let test_diffs_adding_new_ticket_to_storage () = + let open Lwt_result_syntax in + let* contract, ctxt = init () in + let new_storage = + boxed_list [string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1] + in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:Script_typed_ir.unit_t + ~storage_type:ticket_string_list_type + ~arg:() + ~old_storage:(boxed_list []) + ~new_storage + ~lazy_storage_diff:[] + ~expected_diff:[(("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1)] + ~expected_receipt: + [("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, 1)])] + +(** Test that removing one ticket from the storage results in: + - Negative diff + - Receipt with negative update *) +let test_diffs_remove_from_storage () = + let open Lwt_result_syntax in + let* contract, ctxt = init () in + let old_storage = + boxed_list + [ + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1; + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 2; + ] + in + let new_storage = + boxed_list [string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1] + in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:Script_typed_ir.unit_t + ~storage_type:ticket_string_list_type + ~arg:() + ~old_storage + ~new_storage + ~lazy_storage_diff:[] + ~expected_diff: + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 0); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), -2); + ] + ~expected_receipt: + [("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", [(contract, -2)])] + +(* Test adding ticket through lazy-storage diff results in: + - Positive diff + - Receipt with positive update *) +let test_diffs_lazy_storage_alloc () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let*?@ int_ticket_big_map_ty = + big_map_type ~key_type:int_t ~value_type:ticket_string_type + in + (* Start with an empty big-map *) + let* empty_big_map, ctxt = + empty_big_map ctxt ~key_type:int_t ~value_type:ticket_string_type + in + (* We add one ticket to the storage. *) + let* lazy_storage_diff, ctxt = + alloc_diff + ctxt + ~key_type:int_t + ~value_type:ticket_string_type + [ + ( Script_int.of_int 1, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ); + ] + in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:int_ticket_big_map_ty + ~storage_type:int_ticket_big_map_ty + ~arg:empty_big_map + ~old_storage:empty_big_map + ~new_storage:empty_big_map + ~lazy_storage_diff:[lazy_storage_diff] + ~expected_diff:[(("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1)] + ~expected_receipt: + [("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, 1)])] + +(* Test removing a big map containing a ticket results in: + - Negative diff + - Receipt with negative update *) +let test_diffs_remove_from_big_map () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let*?@ int_ticket_big_map_ty = + big_map_type ~key_type:int_t ~value_type:ticket_string_type + in + (* Start with an empty big-map *) + let* empty_big_map, ctxt = + empty_big_map ctxt ~key_type:int_t ~value_type:ticket_string_type + in + (* Remove one ticket from the lazy storage. *) + let* lazy_storage_diff, ctxt = + remove_diff + ctxt + contract + ~key_type:int_t + ~value_type:ticket_string_type + ~existing_entries: + [ + ( Script_int.of_int 1, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ); + ] + in + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:unit_t + ~storage_type:int_ticket_big_map_ty + ~arg:() + ~old_storage:empty_big_map + ~new_storage:empty_big_map + ~lazy_storage_diff:[lazy_storage_diff] + ~expected_diff:[(("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1)] + ~expected_receipt: + [("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, -1)])] + +(** Test copying a big-map. *) +let test_diffs_copy_big_map () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let*?@ int_ticket_big_map_ty = + big_map_type ~key_type:int_t ~value_type:ticket_string_type + in + (* Start with an empty big-map *) + let* empty_big_map, ctxt = + empty_big_map ctxt ~key_type:int_t ~value_type:ticket_string_type + in + (* We add one ticket to the storage. *) + let* lazy_storage_diff, ctxt = + copy_diff + ctxt + contract + ~key_type:int_t + ~value_type:ticket_string_type + ~existing_entries: + [ + ( Script_int.of_int 1, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ); + ] + ~updates: + [ + ( Script_int.of_int 2, + Some (string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 1) + ); + ] + in + (* We copy a big-map with one ticket inside (this is illegal in Michelson). + Then we add a new ticket to the map. The result is two new tickets. + *) + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:unit_t + ~storage_type:int_ticket_big_map_ty + ~arg:() + ~old_storage:empty_big_map + ~new_storage:empty_big_map + ~lazy_storage_diff:[lazy_storage_diff] + ~expected_diff: + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), 1); + ] + ~expected_receipt: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, 1)]); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", [(contract, 1)]); + ] + +(** Test that adding and removing items from an existing big-map results + yield corresponding ticket-token diffs. *) +let test_diffs_add_to_existing_big_map () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let*?@ int_ticket_big_map_ty = + big_map_type ~key_type:int_t ~value_type:ticket_string_type + in + let* old_storage, ctxt = + make_big_map + ctxt + contract + ~key_type:int_t + ~value_type:ticket_string_type + [ + (* It doesn't matter what the old entries are. They are never traversed *) + ( Script_int.of_int 1, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ); + ( Script_int.of_int 2, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 1 ); + ( Script_int.of_int 3, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 1 ); + ] + in + (* We add one ticket to the storage. *) + let* lazy_storage_diff, ctxt = + existing_diff + ctxt + contract + ~key_type:int_t + ~value_type:ticket_string_type + ~existing_entries: + [ + ( Script_int.of_int 1, + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ); + ] + ~updates: + [ + (* Add one new ticket to the big-map. *) + ( Script_int.of_int 2, + Some (string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 2) + ); + (* Remove a ticket *) + (Script_int.of_int 1, None); + ] + in + (* Even if the old and the new storage are the same (and contains tickets) + we should still detect the diff from the lazy-storage diff. + Since the old and new storage are lazy, they should never be traversed. + *) + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:unit_t + ~storage_type:int_ticket_big_map_ty + ~arg:() + ~old_storage + ~new_storage:old_storage + ~lazy_storage_diff:[lazy_storage_diff] + ~expected_diff: + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), 2); + ] + ~expected_receipt: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", [(contract, -1)]); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", [(contract, 2)]); + ] + +(** Test a combination of updates. *) +let test_diffs_args_storage_and_lazy_diffs () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* contract, ctxt = init () in + let*?@ int_ticket_big_map_ty = + big_map_type ~key_type:int_t ~value_type:ticket_string_type + in + let*?@ (Ty_ex_c list_big_map_pair_type) = + pair_t (-1) ticket_string_list_type int_ticket_big_map_ty + in + let* empty_big_map, ctxt = + empty_big_map ctxt ~key_type:int_t ~value_type:ticket_string_type + in + (* We send two tickets in the args. *) + let arg = + boxed_list + [ + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1; + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 1; + ] + in + (* We add three tickets to the storage. *) + let* lazy_storage_diff, ctxt = + existing_diff + ctxt + contract + ~key_type:int_t + ~value_type:ticket_string_type + ~existing_entries:[] + ~updates: + [ + ( Script_int.of_int 1, + Some (string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1) + ); + ( Script_int.of_int 2, + Some (string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 1) + ); + ( Script_int.of_int 3, + Some + (string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 1) + ); + ] + in + (* We have three tickets in the old storage. *) + let old_storage = + ( boxed_list + [ + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1; + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 1; + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 1; + ], + empty_big_map ) + in + let new_storage = + ( boxed_list + [ + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 1; + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "yellow" 1; + ], + empty_big_map ) + in + (* + Diff: + Before script execution: + - Args: 1 red, 1 blue + - Old storage : 1 red, 1 blue, 1 green + - Total: 2 red, 2 blue, 1 green + After execution: + - New_storage: 1 green, 1 yellow + - Lazy-diff: 1 red, 1 blue, 1 green + - Total: 1 red, 1 blue, 2 green, 1 yellow + Net diff: + - -1 red, -1 blue, +1 green, +1 yellow + Receipt (diff in storage): + Before script execution: + - Old storage : 1 red, 1 blue, 1 green + - Total: 1 red, 1 blue, 1 green + After execution: + - New_storage: 1 green, 1 yellow + - Lazy-diff: 1 red, 1 blue, 1 green + - Total: 1 red, 1 blue, 2 green, 1 yellow + Net diff: + - +1 green, +1 yellow + + *) + assert_ticket_diffs + ctxt + ~loc:__LOC__ + ~self_contract:contract + ~arg_type:ticket_string_list_type + ~storage_type:list_big_map_pair_type + ~arg + ~old_storage + ~new_storage + ~lazy_storage_diff:[lazy_storage_diff] + ~expected_diff: + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), 1); + ] + ~expected_receipt: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow", [(contract, 1)]); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", [(contract, 1)]); + ] + +(** Test that attempting to transfer a ticket that exceeds the budget fails. *) +let test_update_invalid_transfer () = + let open Lwt_result_syntax in + let* baker, sender, block = init_for_operation () in + let* destination, _script, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let ctxt = Incremental.alpha_ctxt incr in + let arg_type = ticket_string_list_type in + let arg = + boxed_list [string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1] + in + let* operation, ctxt = + transfer_operation + ctxt + ~sender:(Contract sender) + ~destination + ~arg_type + ~arg + in + assert_fail_with + ~loc:__LOC__ + ~msg: + "Attempted to send 1 unit(s) of a ticket created by \ + KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq." + (fun () -> + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:sender + ~ticket_diffs:Ticket_token_map.empty + [operation]) + +(** Test that adding more tickets created by the [self] contract is valid and + results in a balance update. *) +let test_update_ticket_self_diff () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init_for_operation () in + let* self, _script, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let ticketer = Contract_hash.to_b58check self in + let self = Contract.Originated self in + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let*@ ticket_diffs, ctxt = + Ticket_token_map.of_list + ctxt + ~merge_overlap:(fun _ -> assert false) + [(red_token, Z.of_int 10)] + in + let*@ _, ctxt = + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs + [] + in + (* After update, we should have 10 added red tokens. *) + let*@ red_self_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract self) + red_token + in + assert_balance ~loc:__LOC__ ctxt red_self_token_hash (Some 10) + +(* Test that sending tickets to self succeed (there are no budget constraints). *) +let test_update_self_ticket_transfer () = + let open Lwt_result_wrap_syntax in + let* baker, self, block = init_for_operation () in + let* ticket_receiver, _script, incr = + originate + block + ~sender:self + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + (* Ticket is self. That means we can transfer an unlimited amounts of such + ticket-tokens. *) + let ticketer = Contract.to_b58check self in + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let* operation, ctxt = + let arg_type = ticket_string_list_type in + let arg = + boxed_list + [ + (* Send a total of 10 units of ticket-tokens. *) + string_ticket ticketer "red" 1; + string_ticket ticketer "red" 2; + string_ticket ticketer "red" 3; + string_ticket ticketer "red" 4; + ] + in + transfer_operation + ctxt + ~sender:(Contract self) + ~destination:ticket_receiver + ~arg_type + ~arg + in + let*@ _, ctxt = + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs:Ticket_token_map.empty + [operation] + in + (* Once we're done with the update, we expect ticket-receiver to have been + credited with 10 units of ticket-tokens. *) + let* () = + let*@ red_receiver_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract (Originated ticket_receiver)) + red_token + in + assert_balance ~loc:__LOC__ ctxt red_receiver_token_hash (Some 10) + in + return_unit + +(** Test that transferring a ticket that does not exceed the budget succeeds. *) +let test_update_valid_transfer () = + let open Lwt_result_wrap_syntax in + let* baker, self, block = init_for_operation () in + let* destination, _script, incr = + originate + block + ~sender:self + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let ticketer = "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" in + assert (ticketer <> Contract.to_b58check self) ; + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let*@ red_self_token_hash, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:(Contract self) red_token + in + let*@ red_receiver_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract (Originated destination)) + red_token + in + (* Set up the balance so that the self contract owns one ticket. *) + let*@ _, ctxt = + Ticket_balance.adjust_balance ctxt red_self_token_hash ~delta:Z.one + in + let* operation, ctxt = + let arg_type = ticket_string_list_type in + let arg = boxed_list [string_ticket ticketer "red" 1] in + transfer_operation ctxt ~sender:(Contract self) ~destination ~arg_type ~arg + in + let*@ ticket_diffs, ctxt = + Ticket_token_map.of_list + ctxt + ~merge_overlap:(fun _ -> assert false) + [(red_token, Z.of_int (-1))] + in + let*@ _, ctxt = + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs + [operation] + in + (* Once we're done with the update, we expect the balance to have been moved + from [self] to [destination]. *) + let* () = assert_balance ~loc:__LOC__ ctxt red_self_token_hash None in + let* () = assert_balance ~loc:__LOC__ ctxt red_receiver_token_hash (Some 1) in + return_unit + +(** Test that transferring a ticket to itself is allowed and does not impact + the balance. *) +let test_update_transfer_tickets_to_self () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init_for_operation () in + let* self_hash, _script, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let ticketer = "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" in + assert (ticketer <> Contract_hash.to_b58check self_hash) ; + let self = Contract.Originated self_hash in + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let*@ red_self_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract self) + red_token + in + (* Set up the balance so that the self contract owns ten tickets. *) + let*@ _, ctxt = + Ticket_balance.adjust_balance ctxt red_self_token_hash ~delta:(Z.of_int 10) + in + let* operation, ctxt = + let arg_type = ticket_string_list_type in + let arg = boxed_list [string_ticket ticketer "red" 1] in + transfer_operation + ctxt + ~sender:(Contract self) + ~destination:self_hash + ~arg_type + ~arg + in + let*@ _, ctxt = + (* Ticket diff removes 5 tickets. *) + let* ticket_diffs, ctxt = + Ticket_token_map.of_list + ctxt + ~merge_overlap:(fun _ -> assert false) + [(red_token, Z.of_int (-5))] + in + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs + [operation] + in + (* We started with 10 units. Removed 5 from storage and sent one to [self]. + Therefore we expect 10 - 5 + 1 = 6 units remaining. *) + let* () = assert_balance ~loc:__LOC__ ctxt red_self_token_hash (Some 6) in + return_unit + +(** Test that attempting to originate a contract with tickets that exceed the + budget fails. *) +let test_update_invalid_origination () = + let open Lwt_result_syntax in + let* baker, sender, block = init_for_operation () in + let* orig_contract, script, incr = + let storage = + let ticketer = "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" in + Printf.sprintf + {|{ Pair %S "red" 1; Pair %S "green" 1; Pair %S "blue" 1; } |} + ticketer + ticketer + ticketer + in + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let ctxt = Incremental.alpha_ctxt incr in + let* operation, ctxt = + origination_operation ctxt ~sender:(Contract sender) ~orig_contract ~script + in + assert_fail_with + ~loc:__LOC__ + ~msg: + "Attempted to send 1 unit(s) of a ticket created by \ + KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq." + (fun () -> + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:sender + ~ticket_diffs:Ticket_token_map.empty + [operation]) + +(** Test update valid origination. *) +let test_update_valid_origination () = + let open Lwt_result_wrap_syntax in + let* baker, self, block = init_for_operation () in + let ticketer = "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" in + assert (ticketer <> Contract.to_b58check self) ; + let* orig_contract, script, incr = + let storage = Printf.sprintf {|{ Pair %S "red" 1; }|} ticketer in + originate + block + ~sender:self + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let*@ red_self_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract self) + red_token + in + (* Set up the balance so that the self contract owns one ticket. *) + let*@ _, ctxt = + Ticket_balance.adjust_balance ctxt red_self_token_hash ~delta:Z.one + in + let* operation, ctxt = + origination_operation ctxt ~sender:(Contract self) ~orig_contract ~script + in + let*@ _, ctxt = + let* ticket_diffs, ctxt = + Ticket_token_map.of_list + ctxt + ~merge_overlap:(fun _ -> assert false) + [(red_token, Z.of_int (-1))] + in + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs + [operation] + in + (* Once we're done with the update, we expect the balance to have been moved + from [self] to [destination]. *) + let*@ red_originated_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract (Originated orig_contract)) + red_token + in + assert_balance ~loc:__LOC__ ctxt red_originated_token_hash (Some 1) + +let test_update_self_origination () = + let open Lwt_result_wrap_syntax in + let* baker, self, block = init_for_operation () in + let ticketer = Contract.to_b58check self in + let* orig_contract, script, incr = + let storage = Printf.sprintf {|{ Pair %S "red" 1; }|} ticketer in + originate + block + ~sender:self + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let*@ red_originated_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract (Originated orig_contract)) + red_token + in + let* operation, ctxt = + origination_operation ctxt ~sender:(Contract self) ~orig_contract ~script + in + let*@ _, ctxt = + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs:Ticket_token_map.empty + [operation] + in + (* Once we're done with the update, we expect the balance to have been + credited to the originated contract. *) + assert_balance ~loc:__LOC__ ctxt red_originated_token_hash (Some 1) + +(** Test ticket-token map of list with duplicates. *) +let test_ticket_token_map_of_list_with_duplicates () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init_for_operation () in + let* self, _script, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let ticketer = Contract_hash.to_b58check self in + let self = Contract.Originated self in + let ctxt = Incremental.alpha_ctxt incr in + let* red_token = string_ticket_token ticketer "red" in + let*@ ticket_diffs, ctxt = + Ticket_token_map.of_list + ctxt + ~merge_overlap:(fun ctxt v1 v2 -> Ok (Z.add v1 v2, ctxt)) + [(red_token, Z.of_int 10); (red_token, Z.of_int 5)] + in + let*@ _, ctxt = + Ticket_accounting.update_ticket_balances + ctxt + ~self_contract:self + ~ticket_diffs + [] + in + (* After update, we should have 10 + 5 added red tokens. *) + let*@ red_self_token_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract self) + red_token + in + assert_balance ~loc:__LOC__ ctxt red_self_token_hash (Some 15) + +let tests = + [ + Tztest.tztest "Diffs empty" `Quick test_diffs_empty; + Tztest.tztest "Diffs for tickets in args" `Quick test_diffs_tickets_in_args; + Tztest.tztest + "Diffs for tickets in args and storage" + `Quick + test_diffs_tickets_in_args_and_storage; + Tztest.tztest "Diffs for dropped ticket" `Quick test_diffs_drop_one_ticket; + Tztest.tztest + "Diffs for adding new ticket to storage" + `Quick + test_diffs_adding_new_ticket_to_storage; + Tztest.tztest + "Diffs for removing from storage" + `Quick + test_diffs_remove_from_storage; + Tztest.tztest + "Diffs for lazy storage allocation" + `Quick + test_diffs_lazy_storage_alloc; + Tztest.tztest + "Diffs for removing from big-map" + `Quick + test_diffs_remove_from_big_map; + Tztest.tztest "Diffs for copying a big-map" `Quick test_diffs_copy_big_map; + Tztest.tztest + "Diffs for adding to an existing big-map" + `Quick + test_diffs_add_to_existing_big_map; + Tztest.tztest + "Diffs for args, storage and lazy-diff" + `Quick + test_diffs_args_storage_and_lazy_diffs; + Tztest.tztest + "Update tickets balances with invalid transfer" + `Quick + test_update_invalid_transfer; + Tztest.tztest "Update ticket self diff" `Quick test_update_ticket_self_diff; + Tztest.tztest + "Update ticket balances for valid transfer" + `Quick + test_update_valid_transfer; + Tztest.tztest + "Update ticket balances for transfer with 'self' tickets" + `Quick + test_update_self_ticket_transfer; + Tztest.tztest + "Update transfer tickets to self" + `Quick + test_update_transfer_tickets_to_self; + Tztest.tztest + "Update invalid origination" + `Quick + test_update_invalid_origination; + Tztest.tztest + "Update valid origination" + `Quick + test_update_valid_origination; + Tztest.tztest + "Update valid self origination" + `Quick + test_update_self_origination; + Tztest.tztest + "ticket-token map with duplicate keys" + `Quick + test_ticket_token_map_of_list_with_duplicates; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket accounting", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance.ml new file mode 100644 index 000000000000..d94ef30163e3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance.ml @@ -0,0 +1,1791 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_balance_key) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_balance.ml + Subject: Ticket balance key hashing +*) + +open Protocol +open Alpha_context + +type init_env = { + block : Block.t; + baker : Signature.public_key_hash; + contract : Contract.t; +} + +let init_env () = + let open Lwt_result_wrap_syntax in + let* block, baker, contract, _src2 = Contract_helpers.init () in + return {block; baker; contract} + +let transaction block ~baker ~sender ~entrypoint ~recipient ~parameters = + let open Lwt_result_wrap_syntax in + let parameters = Script.lazy_expr @@ Expr.from_string parameters in + let* operation = + Op.transaction + (B block) + ~gas_limit:Max + ~entrypoint + ~parameters + ~fee:Tez.one + sender + recipient + (Tez.of_mutez_exn 0L) + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let* incr = Incremental.add_operation incr operation in + Incremental.finalize_block incr + +let originate = Contract_helpers.originate_contract_from_string + +let get_balance ctxt ~token ~owner = + let open Lwt_result_wrap_syntax in + let* key_hash, ctxt = Ticket_balance_key.of_ex_token ctxt ~owner token in + Ticket_balance.get_balance ctxt key_hash + +let get_used_ticket_storage block = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + wrap + @@ Ticket_balance.Internal_for_tests.used_storage_space + (Incremental.alpha_ctxt incr) + +let get_paid_ticket_storage block = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + wrap + @@ Ticket_balance.Internal_for_tests.paid_storage_space + (Incremental.alpha_ctxt incr) + +let get_used_contract_storage block contract = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + let alpha_ctxt = Incremental.alpha_ctxt incr in + wrap @@ Alpha_context.Contract.used_storage_space alpha_ctxt contract + +let get_paid_contract_storage block contract = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + let alpha_ctxt = Incremental.alpha_ctxt incr in + wrap + @@ Alpha_context.Contract.Internal_for_tests.paid_storage_space + alpha_ctxt + contract + +let assert_paid_contract_storage ~loc block contract expected = + let open Lwt_result_wrap_syntax in + let* storage = get_paid_contract_storage block contract in + Assert.equal + ~loc + Z.equal + "Paid contract storage " + Z.pp_print + (Z.of_int expected) + storage + +let assert_used_contract_storage ~loc block contract expected = + let open Lwt_result_wrap_syntax in + let* storage = get_used_contract_storage block contract in + Assert.equal + ~loc + Z.equal + "Used contract storage " + Z.pp_print + (Z.of_int expected) + storage + +let assert_paid_ticket_storage ~loc block expected = + let open Lwt_result_wrap_syntax in + let* storage = get_paid_ticket_storage block in + Assert.equal + ~loc + Z.equal + "Paid ticket storage " + Z.pp_print + (Z.of_int expected) + storage + +let assert_used_ticket_storage ~loc block expected = + let open Lwt_result_wrap_syntax in + let* storage = get_used_ticket_storage block in + Assert.equal + ~loc + Z.equal + "Used ticket storage " + Z.pp_print + (Z.of_int expected) + storage + +let assert_token_balance ~loc block token owner expected = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let*@ balance, _ = + get_balance ctxt ~token ~owner:(Destination.Contract owner) + in + match (balance, expected) with + | Some b, Some e -> Assert.equal_int ~loc (Z.to_int b) e + | Some b, None -> + failwith "%s: Expected no balance but got some %d" loc (Z.to_int b) + | None, Some b -> failwith "%s: Expected balance %d but got none" loc b + | None, None -> return_unit + +let string_token ~ticketer content = + let contents = + WithExceptions.Result.get_ok ~loc:__LOC__ @@ Script_string.of_string content + in + Ticket_token.Ex_token + {ticketer; contents_type = Script_typed_ir.string_t; contents} + +let unit_ticket ~ticketer = + Ticket_token.Ex_token + {ticketer; contents_type = Script_typed_ir.unit_t; contents = ()} + +let new_contracts ~before ~after = + let open Lwt_result_wrap_syntax in + let all_contracts current_block = + let* result = Incremental.begin_construction current_block in + let ctxt = Incremental.alpha_ctxt result in + let*! cs = Contract.list ctxt in + return cs + in + let* cs1 = all_contracts before in + let* cs2 = all_contracts after in + let not_in_cs1 = + let module S = Set.Make (String) in + let set = S.of_list @@ List.map Contract.to_b58check cs1 in + fun c -> not @@ S.mem (Contract.to_b58check c) set + in + return (List.filter not_in_cs1 cs2) + +let get_new_contract before f = + let open Lwt_result_wrap_syntax in + let* after = f before in + let* contracts = new_contracts ~before ~after in + match contracts with + | c :: _ -> return (c, after) + | _ -> failwith "Expected one new contracts" + +(** Test adding a ticket to a strict storage. *) +let test_add_strict () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* Originate *) + let* contract, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter unit; + storage (list (ticket string)); + code + { CDR; + PUSH nat 1; + PUSH string "Red"; + TICKET; + ASSERT_SOME; + CONS; + NIL operation ; + PAIR } } + |} + ~storage:"{}" + block + in + let token_red = string_token ~ticketer:contract "Red" in + (* Before calling the contract the balance should be empty. *) + let* () = assert_token_balance ~loc:__LOC__ block token_red contract None in + (* Run the script *) + let* block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"Unit" + in + (* After calling the contract, one ticket is added and balance is one. *) + let* () = + assert_token_balance ~loc:__LOC__ block token_red contract (Some 1) + in + (* Calling the contract again should increase the balance once more. *) + let* block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"Unit" + in + assert_token_balance ~loc:__LOC__ block token_red contract (Some 2) + +(** Test adding and removing tickets from a list in the storage. *) +let test_add_remove () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* Originate *) + let* contract, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (or (unit %add) (unit %remove)); + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { DROP ; + PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + CONS ; + NIL operation ; + PAIR } + { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } + |} + ~storage:"{}" + block + in + let add_one block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"Left Unit" + in + let clear block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"Right Unit" + in + let token_red = string_token ~ticketer:contract "Red" in + (* Before calling the contract the balance should be empty *) + let* () = assert_token_balance ~loc:__LOC__ block token_red contract None in + (* Call the contract twice *) + let* block = add_one block in + let* block = add_one block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red contract (Some 2) + in + (* Remove tickets from the contract *) + let* block = clear block in + assert_token_balance ~loc:__LOC__ block token_red contract None + +(** Test adding multiple tickets to a big-map. *) +let test_add_to_big_map () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + let* contract, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter int ; + storage (big_map int (ticket string)) ; + code { LEFT (big_map int (ticket string)) ; + LOOP_LEFT + { UNPAIR ; + PUSH int 0 ; + SWAP ; + DUP ; + DUG 2 ; + COMPARE ; + LE ; + IF { DROP ; RIGHT (pair int (big_map int (ticket string))) } + { SWAP ; + PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + SOME ; + DUP 3 ; + GET_AND_UPDATE ; + DROP ; + PUSH int 1 ; + DIG 2 ; + SUB ; + PAIR ; + LEFT (big_map int (ticket string)) } } ; + NIL operation ; + PAIR } } + |} + ~storage:"{}" + block + in + let* block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"100" + in + let token_red = string_token ~ticketer:contract "Red" in + assert_token_balance ~loc:__LOC__ block token_red contract (Some 100) + +(** Test adding, swapping and clearing big-maps from storage. + The script contains in its storage two big-maps: + + pair + (big_map %map1 int (ticket string)) + (big_map %map2 int (ticket string))) + + And takes three actions: + 1) Add one ticket to map1 + 2) Swap map1 and map2 + 3) Clear map1 + *) +let test_swap_big_map () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + let* contract, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (or (or (int %add) (unit %clear)) (unit %swap)) ; + storage (pair (big_map %map1 int (ticket string)) (big_map %map2 int (ticket string))) ; + code { UNPAIR ; + NIL operation ; + SWAP ; + IF_LEFT + { IF_LEFT + { DIG 2 ; + UNPAIR ; + PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + SOME ; + DIG 3 ; + GET_AND_UPDATE ; + DROP ; + PAIR ; + SWAP ; + PAIR } + { DROP ; SWAP ; CDR ; EMPTY_BIG_MAP int (ticket string) ; + PAIR ; SWAP ; PAIR } } + { DROP ; SWAP ; UNPAIR ; SWAP ; PAIR ; SWAP ; PAIR } } } + |} + ~storage:"Pair {} {}" + block + in + let add_to_index block ix = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:(Printf.sprintf "Left (Left %d)" ix) + in + let swap_big_maps block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"Right Unit" + in + let clear_left_big_map block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:contract + ~parameters:"Left (Right Unit)" + in + (* Add three tickets to [map1] *) + let* block = add_to_index block 1 in + let* block = add_to_index block 2 in + let* block = add_to_index block 3 in + let token_red = string_token ~ticketer:contract "Red" in + let* () = + assert_token_balance ~loc:__LOC__ block token_red contract (Some 3) + in + (* Swap [map1] and [map2]. This should not impact the ticket balance. *) + let* block = swap_big_maps block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red contract (Some 3) + in + (* Remove all tickets from [map1] (which is empty). *) + let* block = clear_left_big_map block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red contract (Some 3) + in + (* Swap [map1] and [map2]. Now, [map1] contains three tickets. *) + let* block = swap_big_maps block in + (* Clear all tickets from [map1]. *) + let* block = clear_left_big_map block in + assert_token_balance ~loc:__LOC__ block token_red contract None + +(* Test sending a ticket to an address *) +let test_send_tickets () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract that can receive a ticket and store it in a list. *) + let* ticket_receiver, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (ticket string) ; + storage (list (ticket string)) ; + code { UNPAIR ; CONS ; NIL operation ; PAIR } } + |} + ~storage:"{}" + block + in + (* A contract that, given an address to a contract that receives tickets, + mints a ticket and sends it over. *) + let* ticket_sender, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter address ; + storage unit ; + code { CAR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract of type `ticket(string)' not found" ; + FAILWITH } + { PUSH mutez 0 ; + PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + |} + ~storage:"Unit" + block + in + let mint_and_send block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_sender + ~parameters: + (Printf.sprintf {|"%s"|} @@ Contract.to_b58check ticket_receiver) + in + (* Call ticket-sender twice in order to transfer tickets to ticket-receiver *) + let* block = mint_and_send block in + let* block = mint_and_send block in + let token_red = string_token ~ticketer:ticket_sender "Red" in + assert_token_balance ~loc:__LOC__ block token_red ticket_receiver (Some 2) + +(** Test sending and storing tickets with amount zero. *) +let test_send_and_store_zero_amount_tickets () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract that, given an address to a contract that receives tickets, + mints a ticket and sends it over. *) + let* ticket_minter, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + |} + ~storage:"Unit" + block + in + (* A contract with two entrypoints: + - Store (ticket): stores the received ticket. + - Send (address) sends the last received tickets to the given address. + *) + let ticket_storer_script = + {| + { parameter (or (address %send) (ticket %store string)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { CONTRACT (ticket string) ; + IF_NONE + { DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { SWAP ; + IF_CONS + { DIG 2 ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + SWAP ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } + { DROP ; PUSH string "Empty storage" ; FAILWITH } } } + { CONS ; NIL operation ; PAIR } } } + |} + in + let* ticket_store_1, _script, block = + originate + ~baker + ~source_contract + ~script:ticket_storer_script + ~storage:"{}" + block + in + let* ticket_store_2, _script, block = + originate + ~baker + ~source_contract + ~script:ticket_storer_script + ~storage:"{}" + block + in + let mint_and_send_to_storer_1 block amount = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_minter + ~parameters: + (Printf.sprintf + {|Pair "%s%s" %d|} + (Contract.to_b58check ticket_store_1) + "%store" + amount) + in + let send_from_store_1_to_store_2 block = + transaction + ~entrypoint:(Entrypoint.of_string_strict_exn "send") + ~baker + ~sender:source_contract + block + ~recipient:ticket_store_1 + ~parameters: + (Printf.sprintf + {|"%s%s"|} + (Contract.to_b58check ticket_store_2) + "%store") + in + let token_red = string_token ~ticketer:ticket_minter "Red" in + (* Mint and send a ticket with amount 0 to [ticket_store_1], which fails. + After the transaction: + + [ticket_store_1]: + [ ] + *) + let*! result = mint_and_send_to_storer_1 block 0 in + assert (Result.is_error result) ; + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 None + in + (* Mint and send a ticket with amount 10 to [ticket_store_1]. After + the transaction: + + [ticket_store_1]: + [ + (TM, "Red", 10) + ] + *) + let* block = mint_and_send_to_storer_1 block 10 in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 (Some 10) + in + (* Send the top of [ticket_storer_1]'s list to [ticket_store_2]. That is the + ticket (TM, "Red", 10). After the transaction: + + ticket_store_1: + [ ] + ticket_store_2: + [ + (TM, "Red", 10) + ] + *) + let* block = send_from_store_1_to_store_2 block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_2 (Some 10) + in + (* Send the top of [ticket_store_1]'s stack to [ticket_store_2]. + However, this fails because [ticket_store_1]'s stack is empty. + Now, [ticket_store_2] holds both tickets. + + ticket_store_1: + [ ] + [ticket_store_2]: + [ + (TM, "Red", 10) + ] + *) + let*! result = send_from_store_1_to_store_2 block in + assert (Result.is_error result) ; + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_2 (Some 10) + in + (* Mint and send a ticket with amount 5 to [ticket_store_1]. After the + transaction: + + [ticket_store_1]: + [ + (TM, "Red", 5) + ] + [ticket_store_2]: + [ + (TM, "Red", 10) + ] + *) + let* block = mint_and_send_to_storer_1 block 5 in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 (Some 5) + in + (* Send the top of [ticket_store_1]'s stack to [ticket_store_2]. That is the + ticket (TM, "Red", 5). After the transaction, [ticket_store_2] holds three + tickets: + + ticket_store_1: + [ ] + [ticket_store_2]: + [ + (TM, "Red", 5) + (TM, "Red", 10) + ] + *) + let* block = send_from_store_1_to_store_2 block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_1 None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_store_2 (Some 15) + in + return_unit + +(** Test sending tickets to an implicit account. *) +let test_send_tickets_to_implicit_account () = + let open Lwt_result_wrap_syntax in + let* block, baker, contract, contract2 = Contract_helpers.init () in + let () = + match (contract, contract2) with + | Contract.Implicit _, Contract.Implicit _ -> () + | _ -> assert false + in + (* A contract that receives an address and mints and sends a ticket to it. *) + let* ticketer, _script, block = + originate + ~baker + ~source_contract:contract + ~script: + {| + { parameter address; + storage unit; + code { CAR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0; + PUSH nat 1 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR }}} + |} + ~storage:"Unit" + block + in + let* block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:contract + block + ~recipient:ticketer + ~parameters:(Printf.sprintf {|"%s"|} (Contract.to_b58check contract2)) + in + let token = string_token ~ticketer "Ticket" in + assert_token_balance ~loc:__LOC__ block token contract2 (Some 1) + +(** Test sending tickets in a big-map. *) +let test_send_tickets_in_big_map () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract that can receive a big-map with tickets. *) + let* ticket_receiver, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (big_map int (ticket string)) ; + storage (big_map int (ticket string)) ; + code { CAR ; NIL operation ; PAIR } } + |} + ~storage:"{}" + block + in + (* A contract with two actions: + - [mint_and_save(key, content)] for creating and saving a new ticket in + a big-map. + - [send (address)] for transferring the big-map to the given address. + *) + let* ticket_manager, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (or (pair %mint_and_save int string) (address %send)) ; + storage (big_map int (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { UNPAIR ; + DIG 2 ; + PUSH nat 1 ; + DIG 3 ; + TICKET ; + ASSERT_SOME ; + SOME ; + DIG 2 ; + GET_AND_UPDATE ; + DROP ; + NIL operation ; + PAIR } + { CONTRACT (big_map int (ticket string)) ; + IF_NONE + { PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + EMPTY_BIG_MAP int (ticket string) ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } } + |} + ~storage:"{}" + block + in + let mint_and_save key content block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_manager + ~parameters:(Printf.sprintf {|Left (Pair %d "%s")|} key content) + in + let send block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_manager + ~parameters: + (Printf.sprintf {|Right "%s"|} @@ Contract.to_b58check ticket_receiver) + in + let token_red = string_token ~ticketer:ticket_manager "Red" in + let token_blue = string_token ~ticketer:ticket_manager "Blue" in + let token_yellow = string_token ~ticketer:ticket_manager "Yellow" in + (* Call ticket manager to mint and save three tickets in a big-map. *) + let* block = mint_and_save 1 "Red" block in + let* block = mint_and_save 2 "Blue" block in + let* block = mint_and_save 3 "Yellow" block in + (* Verify that all three tickets are accounted for and belong to + ticket-manager. *) + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_manager (Some 1) + in + let* () = + assert_token_balance ~loc:__LOC__ block token_blue ticket_manager (Some 1) + in + let* () = + assert_token_balance ~loc:__LOC__ block token_yellow ticket_manager (Some 1) + in + (* Send over the big-map with tickets to ticket-receiver. *) + let* block = send block in + (* Verify that all three tickets now belong to the ticket-receiver contract. *) + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_receiver (Some 1) + in + let* () = + assert_token_balance ~loc:__LOC__ block token_blue ticket_receiver (Some 1) + in + let* () = + assert_token_balance + ~loc:__LOC__ + block + token_yellow + ticket_receiver + (Some 1) + in + (* Finally test that the ticket-manager no longer holds any of the tickets *) + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_manager None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_blue ticket_manager None + in + assert_token_balance ~loc:__LOC__ block token_yellow ticket_manager None + +(* Test sending tickets in a big-map. *) +let test_modify_big_map () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract with two actions: + - [Add ((int, string))] for adding a ticket to the big-map. + - [Remove(int)] for removing an index from the big-map. + *) + let* ticket_manager, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (or (pair %add int string) (int %remove)) ; + storage (big_map int (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { UNPAIR ; + DIG 2 ; + PUSH nat 1 ; + DIG 3 ; + TICKET ; + ASSERT_SOME ; + SOME ; + DIG 2 ; + GET_AND_UPDATE ; + DROP ; + NIL operation ; + PAIR } + { SWAP ; + NONE (ticket string) ; + DIG 2 ; + GET_AND_UPDATE ; + DROP ; + NIL operation ; + PAIR } } } + |} + ~storage:"{}" + block + in + let add key content block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_manager + ~parameters:(Printf.sprintf {|Left (Pair %d "%s")|} key content) + in + let remove key block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_manager + ~parameters:(Printf.sprintf {|Right %d|} key) + in + let token_red = string_token ~ticketer:ticket_manager "Red" in + let token_blue = string_token ~ticketer:ticket_manager "Blue" in + let token_yellow = string_token ~ticketer:ticket_manager "Yellow" in + let token_green = string_token ~ticketer:ticket_manager "Green" in + (* Add a red, blue and a yellow ticket *) + let* block = add 1 "Red" block in + let* block = add 2 "Blue" block in + let* block = add 3 "Yellow" block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_manager (Some 1) + in + let* () = + assert_token_balance ~loc:__LOC__ block token_blue ticket_manager (Some 1) + in + let* () = + assert_token_balance ~loc:__LOC__ block token_yellow ticket_manager (Some 1) + in + (* Replace the red ticket at index 1 with a green one. *) + let* block = add 1 "Green" block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_manager None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_green ticket_manager (Some 1) + in + (* Remove the blue ticket at index 2. *) + let* block = remove 2 block in + let* () = + assert_token_balance ~loc:__LOC__ block token_blue ticket_manager None + in + (* Add one more green ticket at index 4 and verify that the total count is 2. *) + let* block = add 4 "Green" block in + assert_token_balance ~loc:__LOC__ block token_green ticket_manager (Some 2) + +(* Test sending tickets in a big-map to a receiver that drops it. *) +let test_send_tickets_in_big_map_and_drop () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract that can receive a big-map with tickets but drops it. *) + let* ticket_receiver, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (big_map int (ticket string)) ; + storage unit; + code { DROP; PUSH unit Unit; NIL operation ; PAIR } } + |} + ~storage:"Unit" + block + in + (* A contract that, given an address, creates a ticket and sends it to the + corresponding contract in a big-map. *) + let* ticket_sender, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter address ; + storage unit ; + code { CAR ; + EMPTY_BIG_MAP int (ticket string) ; + PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + SOME ; + PUSH int 1 ; + GET_AND_UPDATE ; + DROP ; + SWAP ; + CONTRACT (big_map int (ticket string)) ; + IF_NONE + { DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + + |} + ~storage:"Unit" + block + in + let token_red = string_token ~ticketer:ticket_sender "Red" in + (* Call ticket-sender to send a ticket to ticket-receiver. *) + let* block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_sender + ~parameters: + (Printf.sprintf {|"%s"|} @@ Contract.to_b58check ticket_receiver) + in + (* Verify that neither ticket-sender nor ticket-receiver holds any balance + for the ticket. *) + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_sender None + in + assert_token_balance ~loc:__LOC__ block token_red ticket_receiver None + +(* Test create contract with tickets *) +let test_create_contract_with_ticket () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + let* ticket_creator, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (pair (pair string nat) key_hash) ; + storage unit ; + code { UNPAIR ; + UNPAIR ; + UNPAIR ; + TICKET ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + SOME ; + CREATE_CONTRACT + { parameter (ticket string) ; + storage (ticket string) ; + code { CAR ; NIL operation ; PAIR } } ; + SWAP ; + DROP ; + SWAP ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } + |} + ~storage:"Unit" + block + in + let token_red = string_token ~ticketer:ticket_creator "Red" in + (* Call ticket-creator to originate a new contract with one ticket *) + let* new_contract, block = + get_new_contract block (fun block -> + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_creator + ~parameters: + (Printf.sprintf + {|Pair (Pair "Red" 1) "%s"|} + (Contract.to_b58check source_contract))) + in + let* () = + assert_token_balance ~loc:__LOC__ block token_red new_contract (Some 1) + in + assert_token_balance ~loc:__LOC__ block token_red ticket_creator None + +let test_join_tickets () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + let* ticket_joiner, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter unit ; + storage (option (ticket string)) ; + code { CDR ; + IF_NONE + { PUSH nat 1 ; PUSH string "Red" ; + TICKET ; ASSERT_SOME ; SOME ; NIL operation ; PAIR } + { PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + PAIR ; + JOIN_TICKETS ; + NIL operation ; + PAIR } } } + |} + ~storage:"None" + block + in + let token_red = string_token ~ticketer:ticket_joiner "Red" in + (* Call ticket joiner to create and join an additional ticket. *) + let add block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_joiner + ~parameters:"Unit" + in + (* Add three tickets *) + let* block = add block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_joiner (Some 1) + in + let* block = add block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_joiner (Some 2) + in + let* block = add block in + assert_token_balance ~loc:__LOC__ block token_red ticket_joiner (Some 3) + +(* A simple fungible token contract implemented using tickets of type + [ticket unit]. + parameter: + - burn: ticket unit + - mint: (contract %destination (ticket unit)) x (nat %amount) +*) +let ticket_builder = + {| + + parameter + (or (ticket %burn unit) + (pair %mint (contract %destination (ticket unit)) (nat %amount))); + storage address; + code + { + AMOUNT; PUSH mutez 0; ASSERT_CMPEQ; + + UNPAIR; + IF_LEFT + { + # Burn entrypoint + # Check that the ticket is ticketed by ourselves + READ_TICKET; CAR; SELF_ADDRESS; ASSERT_CMPEQ; + + # Drop the ticket + DROP; + + # Finish + NIL operation + } + { + # Mint entrypoint + # Authenticate SENDER + DUP @manager 2; SENDER; ASSERT_CMPEQ; + + UNPAIR; + SWAP; UNIT; TICKET; ASSERT_SOME; + PUSH mutez 0; SWAP; TRANSFER_TOKENS; + NIL operation; SWAP; CONS + }; + PAIR + } + + |} + +(* A simple wallet for fungible tokens implemented using tickets of + type [ticket unit]. + parameter: + - receive: ticket unit + - send: + * destination: (contract (ticket unit)) + * amount: nat + * ticketer: address +*) +let ticket_wallet = + {| + parameter + (or + (ticket %receive unit) + (pair %send (contract %destination (ticket unit)) (nat %amount) (address %ticketer))); + storage (pair (address %manager) (big_map %tickets address (ticket unit))); + code + { + AMOUNT; PUSH mutez 0; ASSERT_CMPEQ; + + UNPAIR 3; + IF_LEFT + { + # Receive entrypoint + + # Get the ticketer + READ_TICKET; CAR @ticketer; DUP; + + # Extract the associated ticket, if any, from the stored big map + DIG 4; + NONE (ticket unit); + DIG 2; + GET_AND_UPDATE; + + # Join it with the parameter + IF_SOME + { + DIG 3; + PAIR; + JOIN_TICKETS; + ASSERT_SOME + } + { DIG 2 }; + SOME; + DIG 2; + GET_AND_UPDATE; + ASSERT_NONE; + SWAP; + PAIR; + NIL operation + } + { + # Send entrypoints + + # Authenticate SENDER + DUP @manager 2; SENDER; ASSERT_CMPEQ; + + UNPAIR 3; + + # Get the ticket associated to the requested ticketer + DIG 4; + NONE (ticket unit); + DUP @ticketer 5; + GET_AND_UPDATE; + ASSERT_SOME; + + # Substract the requested amount + READ_TICKET; + GET @total_amount 4; + DUP @amount 5; + SWAP; SUB; + DUP; EQ; + IF + { + # Drop @remaining_amount because it is zero + DROP; + # Drop @amount because this is now irrelevant + DIG 3; DROP; + # Drop @ticketer because we are not storing any ticket in this wallet + DIG 3; DROP; + # Bring the big map to the stack top since the ticket entry is already striked out + DUG 3 + } + { + ISNAT; ASSERT_SOME @remaining_amount; + + # Split the ticket + DIG 4; PAIR; SWAP; SPLIT_TICKET; + ASSERT_SOME; UNPAIR @to_send @to_keep; + + # Store the ticket to keep + DUG 5; + SOME; + DIG 3; + GET_AND_UPDATE; + ASSERT_NONE; + }; + DIG 2; PAIR; + + # Send the ticket + SWAP; + PUSH mutez 0; + DIG 3; + TRANSFER_TOKENS; + NIL operation; + SWAP; + CONS; + }; + PAIR + } + |} + +(** Test ticket wallet implementation including sending tickets to self. *) +let test_ticket_wallet () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + let* ticket_builder, _script, block = + originate + ~baker + ~source_contract + ~script:ticket_builder + ~storage:(Printf.sprintf "%S" @@ Contract.to_b58check source_contract) + block + in + let* ticket_wallet, _script, block = + originate + ~baker + ~source_contract + ~script:ticket_wallet + ~storage: + (Printf.sprintf "Pair %S {}" @@ Contract.to_b58check source_contract) + block + in + (* Call ticket-builder to mint one ticket and send to ticket-wallet. *) + let ticket_builder_token = unit_ticket ~ticketer:ticket_builder in + let send_one block = + transaction + ~entrypoint:(Entrypoint.of_string_strict_exn "mint") + ~baker + ~sender:source_contract + block + ~recipient:ticket_builder + ~parameters: + (Printf.sprintf + {|Pair "%s%sreceive" 1|} + (Contract.to_b58check ticket_wallet) + "%") + in + (* Call ticket wallet to send a ticket to ticket-builder's burn address + entrypoint. *) + let send_to_burn block = + transaction + ~entrypoint:(Entrypoint.of_string_strict_exn "send") + ~baker + ~sender:source_contract + block + ~recipient:ticket_wallet + ~parameters: + (Printf.sprintf + {|Pair "%s%sburn" 1 %S|} + (Contract.to_b58check ticket_builder) + "%" + (Contract.to_b58check ticket_builder)) + in + let send_to_self block = + transaction + ~entrypoint:(Entrypoint.of_string_strict_exn "send") + ~baker + ~sender:source_contract + block + ~recipient:ticket_wallet + ~parameters: + (Printf.sprintf + {|Pair "%s%sreceive" 1 %S|} + (Contract.to_b58check ticket_wallet) + "%" + (Contract.to_b58check ticket_builder)) + in + let assert_balance block balance = + assert_token_balance + ~loc:__LOC__ + block + ticket_builder_token + ticket_wallet + balance + in + (* Mint and send tickets to wallet. *) + let* block = send_one block in + let* () = assert_balance block (Some 1) in + let* block = send_one block in + let* () = assert_balance block (Some 2) in + (* Send to self should not affect the balance. *) + let* block = send_to_self block in + let* () = assert_balance block (Some 2) in + (* Burn tickets by sending to burn address. *) + let* block = send_to_burn block in + let* () = assert_balance block (Some 1) in + let* block = send_to_burn block in + assert_balance block None + +(* Test used ticket storage and paid storage. *) +let test_ticket_storage () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract that can receive a ticket and store it. Each new ticket it + receives is added to a list. *) + let* ticket_keeper, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (ticket string) ; + storage (list (ticket string)) ; + code { UNPAIR ; CONS ; NIL operation ; PAIR } } + |} + ~storage:"{}" + block + in + (* A contract that receives a pair of ticket and address and forwards the + ticket to the given address. The contract does not store any tickets. *) + let* ticket_forwarder, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (pair (ticket string) address) ; + storage unit ; + code { CAR ; + UNPAIR ; + SWAP ; + CONTRACT (ticket string) ; + IF_NONE + { DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + |} + ~storage:"Unit" + block + in + (* A contract that takes two addresses: one to a ticket-forward contract and + one to a ticket-receiver contract, mints and sends the ticket to a + ticket-forward address along with the address of the ticket-receiver. + + Altogether we have: + + [ticket_minter] ----> [ticket_forwarder] ----> [ticket_receiver] + *) + let* ticket_minter, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (pair address address) ; storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (pair (ticket string) address) ; + IF_NONE + { DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH nat 1 ; + PUSH string "Red" ; + TICKET ; + ASSERT_SOME ; + PAIR ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } |} + ~storage:"Unit" + block + in + let mint_and_send block = + transaction + ~entrypoint:Entrypoint.default + ~baker + ~sender:source_contract + block + ~recipient:ticket_minter + ~parameters: + (Printf.sprintf + {|Pair %S %S|} + (Contract.to_b58check ticket_forwarder) + (Contract.to_b58check ticket_keeper)) + in + let* block = mint_and_send block in + let token_red = string_token ~ticketer:ticket_minter "Red" in + (* Verify that the ticket is accredited to the ticket keeper and no one else. + The ticket table now looks like: + *) + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_minter None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_forwarder None + in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_keeper (Some 1) + in + (* Both ticket paid and used storage should now be 65 bytes for the key and + one for the value. Ticket table looks like: + + | Owner x Ticket-token | Amount | + |--------------------------|--------| + | ticket_keeper x Red | 1 | + + Used storage: 65 + 1 = 66 + + Paid storage: 66 + *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 66 in + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 66 in + (* Send another ticket that uses the same slot. That does not increase used + storage. The first call from [ticket_minter] to ticket-forwarder results in + a table: + + | Owner x Ticket-token | Amount | + |--------------------------|--------| + | ticket_forwarder x Red | 1 | + | ticket_keeper x Red | 1 | + + Used storage: 132 + + The call from ticket-forwarder to [ticket_keeper] results in: + + | Owner x Ticket-token | Amount | + |--------------------------|--------| + | ticket_keeper x Red | 2 | + + Used storage: 66 + + Noted that the paid-storage "water-marker" was pushed up to 132. + *) + let* block = mint_and_send block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_keeper (Some 2) + in + let* () = assert_used_ticket_storage ~loc:__LOC__ block 66 in + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 132 in + (* Send yet another ticket that uses the same slot. That does not increase used + storage and it's using already paid storage. The first call from + [ticket_minter] to ticket-forwarder results in a table: + + | Owner x Ticket-token | Amount | + |--------------------------|--------| + | ticket_forwarder x Red | 1 | + | ticket_keeper x Red | 2 | + + Used storage: 132 + + The call from ticket-forwarder to [ticket_keeper] results in: + + | Owner x Ticket-token | Amount | + |--------------------------|--------| + | ticket_keeper x Red | 3 | + + Used storage: 66 + + Here, the paid_storage "water-mark" is not pushed up. + *) + let* block = mint_and_send block in + let* () = + assert_token_balance ~loc:__LOC__ block token_red ticket_keeper (Some 3) + in + let* () = assert_used_ticket_storage ~loc:__LOC__ block 66 in + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 132 in + return_unit + +(* Test used ticket storage and paid storage. *) +let test_storage_for_create_and_remove_tickets () = + let open Lwt_result_wrap_syntax in + let* {block; baker; contract = source_contract} = init_env () in + (* A contract with two endpoints: + - Create n tickets and add to its storage + - Remove all tickets + *) + let* ticket_manager, _script, block = + originate + ~baker + ~source_contract + ~script: + {| + { parameter (or (pair %add nat string) (unit %clear)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; ASSERT_SOME ; CONS ; NIL operation ; PAIR } + { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } + |} + ~storage:"{}" + block + in + let add block n content = + transaction + ~entrypoint:(Entrypoint.of_string_strict_exn "add") + ~baker + ~sender:source_contract + block + ~recipient:ticket_manager + ~parameters:(Printf.sprintf "Pair %d %S" n content) + in + let clear block = + transaction + ~entrypoint:(Entrypoint.of_string_strict_exn "clear") + ~baker + ~sender:source_contract + block + ~recipient:ticket_manager + ~parameters:"Unit" + in + (* Initially the used and paid contract storage size is 141. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 141 + in + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 141 + in + (* Add 1000 units of "A" tickets. *) + let* block = add block 1000 "A" in + (* After adding one block the new used and paid storage grows to accommodate + for the new ticket. The size is 141 + 40 (size of ticket) = 181. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 181 + in + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 181 + in + (* The size of used and paid-for ticket storage is 67 bytes. (65 for hash + and 2 for amount). *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 67 in + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 67 in + (* Add 1000 units of "B" tickets. *) + let* block = add block 1000 "B" in + (* The new used and paid for contract storage grow to 155 + 40 = 195. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 221 + in + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 + in + (* The new used and paid for ticket storage doubles (2 * 67 = 134). *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 134 in + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in + (* Clear all tickets. *) + let* block = clear block in + (* We're back to 115 base-line for the used contract storage and keep 195 for + paid. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 141 + in + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 + in + (* Since the ticket-table is empty it does not take up any space. However, + we've already paid for 134 bytes. *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 0 in + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in + (* Add one unit of "C" tickets. *) + let* block = add block 1 "C" in + (* The new used storage is 141 + 39 (size of ticket) = 180. The size is 39 + rather than 40 because it carries a smaller amount payload. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 180 + in + (* We still have paid for 221 contract storage. *) + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 + in + (* There is one row in the ticket table with size 65 (for the hash) + 1 + (for the amount) = 65 bytes. *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 66 in + (* We've still paid for 134 bytes however. *) + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in + (* Add yet another "C" ticket. *) + let* block = add block 1 "C" in + (* The new used storage is 180 + 39 (size of ticket) = 219. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 219 + in + (* We still have paid for 221 contract storage. *) + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 221 + in + (* There is still only one row in the ticket table with size 66. *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 66 in + (* And we've still paid for 134 bytes. *) + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in + (* Add a "D" ticket. *) + let* block = add block 1 "D" in + (* The new used storage is 219 + 39 (size of ticket) = 258. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 258 + in + (* The paid storage also increases to 258. *) + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 258 + in + (* There are now two rows in the ticket table: 2 x 66 = 132 *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 132 in + (* And we've still paid for 134 bytes. *) + let* () = assert_paid_ticket_storage ~loc:__LOC__ block 134 in + let* block = add block 1 "E" in + (* The new used storage is 258 + 39 (size of ticket) = 297. *) + let* () = + assert_used_contract_storage ~loc:__LOC__ block ticket_manager 297 + in + (* The paid storage also increases to 297. *) + let* () = + assert_paid_contract_storage ~loc:__LOC__ block ticket_manager 297 + in + (* There are now three rows in the ticket table: 3 x 66 = 198. *) + let* () = assert_used_ticket_storage ~loc:__LOC__ block 198 in + (* And the paid storage has increased. *) + assert_paid_ticket_storage ~loc:__LOC__ block 198 + +let tests = + [ + Tztest.tztest "add strict" `Quick test_add_strict; + Tztest.tztest "add and remove" `Quick test_add_remove; + Tztest.tztest "add to big-map" `Quick test_add_to_big_map; + Tztest.tztest "swap big-map" `Quick test_swap_big_map; + Tztest.tztest "send ticket" `Quick test_send_tickets; + Tztest.tztest + "send ticket to implicit" + `Quick + test_send_tickets_to_implicit_account; + Tztest.tztest + "send and store tickets with amount 0" + `Quick + test_send_and_store_zero_amount_tickets; + Tztest.tztest "send tickets in big-map" `Quick test_send_tickets_in_big_map; + Tztest.tztest "modify big-map" `Quick test_modify_big_map; + Tztest.tztest "send drop" `Quick test_send_tickets_in_big_map_and_drop; + Tztest.tztest + "create contract with ticket" + `Quick + test_create_contract_with_ticket; + Tztest.tztest "join" `Quick test_join_tickets; + Tztest.tztest "wallet" `Quick test_ticket_wallet; + Tztest.tztest "ticket storage" `Quick test_ticket_storage; + Tztest.tztest + "storage for create and remove tickets" + `Quick + test_storage_for_create_and_remove_tickets; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket balance", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance_key.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance_key.ml new file mode 100644 index 000000000000..43d361299c61 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_balance_key.ml @@ -0,0 +1,453 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_balance_key) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_balance_key.ml + Subject: Ticket balance key hashing +*) + +open Protocol +open Alpha_context + +let new_ctxt () = + let open Lwt_result_wrap_syntax in + let* block, _contract = Context.init1 () in + let* incr = Incremental.begin_construction block in + return @@ Incremental.alpha_ctxt incr + +let make_contract ticketer = + let open Lwt_result_wrap_syntax in + let*?@ x = Contract.of_b58check ticketer in + return x + +let make_ex_token ctxt ~ticketer ~ty ~content = + let open Lwt_result_wrap_syntax in + let*?@ Script_ir_translator.Ex_comparable_ty cty, ctxt = + let node = Micheline.root @@ Expr.from_string ty in + Script_ir_translator.parse_comparable_ty ctxt node + in + let* ticketer = make_contract ticketer in + let*@ contents, ctxt = + let node = Micheline.root @@ Expr.from_string content in + Script_ir_translator.parse_comparable_data ctxt cty node + in + return (Ticket_token.Ex_token {contents_type = cty; ticketer; contents}, ctxt) + +let make_key ctxt ~ticketer ~ty ~content ~owner = + let open Lwt_result_wrap_syntax in + let* ex_token, ctxt = make_ex_token ctxt ~ticketer ~ty ~content in + let* owner = make_contract owner in + let*@ key, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract owner) + ex_token + in + return (key, ctxt) + +let equal_script_hash ~loc msg key1 key2 = + Assert.equal ~loc Ticket_hash.equal msg Ticket_hash.pp key1 key2 + +let not_equal_script_hash ~loc msg key1 key2 = + Assert.not_equal ~loc Ticket_hash.equal msg Ticket_hash.pp key1 key2 + +let assert_keys ~ticketer1 ~ticketer2 ~ty1 ~ty2 ~amount1 ~amount2 ~content1 + ~content2 ~owner1 ~owner2 assert_condition = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + let* key1, ctxt = + make_key ctxt ~ticketer:ticketer1 ~ty:ty1 ~content:content1 ~owner:owner1 + in + let* key2, _ = + make_key ctxt ~ticketer:ticketer2 ~ty:ty2 ~content:content2 ~owner:owner2 + in + assert_condition (key1, amount1) (key2, amount2) + +let assert_keys_not_equal ~loc = + assert_keys (fun (key1, _) (key2, _) -> + not_equal_script_hash ~loc "Assert that keys are not equal" key1 key2) + +let assert_keys_equal ~loc = + assert_keys (fun (key1, _) (key2, _) -> + equal_script_hash ~loc "Assert that keys are equal" key1 key2) + +(** Test that tickets with two different amounts map to the same hash. + The amount is not part of the ticket balance key. *) +let test_different_amounts () = + assert_keys_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"unit" + ~ty2:"unit" + ~content1:"Unit" + ~content2:"Unit" + ~amount1:1 + ~amount2:2 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that two tickets with different ticketers map to different hashes. *) +let test_different_ticketers () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~ty1:"nat" + ~ty2:"nat" + ~content1:"1" + ~content2:"1" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that two tickets with different owners map to different hashes. *) +let test_different_owners () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"nat" + ~ty2:"nat" + ~content1:"1" + ~content2:"1" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + +(** Test that two tickets with different contents map to different hashes. *) +let test_different_content () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"nat" + ~ty2:"nat" + ~content1:"1" + ~content2:"2" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type nat and a ticket of type int, with the same + content, map to different hashes. *) +let test_nat_int () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"nat" + ~ty2:"int" + ~content1:"1" + ~content2:"1" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type nat and a ticket of type mutez, with the same + content, map to different hashes. *) +let test_nat_mutez () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"nat" + ~ty2:"mutez" + ~content1:"1" + ~content2:"1" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type nat and a ticket of type bool, with the + contents (False/0), map to different hashes. *) +let test_bool_nat () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"bool" + ~ty2:"nat" + ~content1:"False" + ~content2:"0" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type nat and a ticket of type bytes, with the + contents (0/0x), map to different hashes. *) +let test_nat_bytes () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"nat" + ~ty2:"bytes" + ~content1:"0" + ~content2:"0x" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type string and a chain_id with same content + map to different hashes. *) +let test_string_chain_id () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"string" + ~ty2:"chain_id" + ~content1:{|"NetXynUjJNZm7wi"|} + ~content2:{|"NetXynUjJNZm7wi"|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type string and a key_hash with same content + map to different hashes. *) +let test_string_key_hash () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"string" + ~ty2:"key_hash" + ~content1:{|"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"|} + ~content2:{|"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type string and a key with same content + map to different hashes. *) +let test_string_key () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"string" + ~ty2:"key" + ~content1:{|"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"|} + ~content2:{|"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type string and a timestamp with same content + map to different hashes. *) +let test_string_timestamp () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"string" + ~ty2:"timestamp" + ~content1:{|"2019-09-26T10:59:51Z"|} + ~content2:{|"2019-09-26T10:59:51Z"|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type string and a address with same content + map to different hashes. *) +let test_string_address () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"string" + ~ty2:"address" + ~content1:{|"KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%entrypoint"|} + ~content2:{|"KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%entrypoint"|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type string and a signature with same content + map to different hashes. *) +let test_string_signature () = + let signature = + {|"edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7"|} + in + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"string" + ~ty2:"signature" + ~content1:signature + ~content2:signature + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Tests that annotations are not taken into account when hashing keys. + Two comparable types that only differ in their annotations should + map to to the same hash. Here, the type [pair int string] is identical to + [pair (int %id) (string %name)]. + *) +let test_annotation_pair () = + assert_keys_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"(pair int string)" + ~ty2:{|(pair (int %id) (string %name))|} + ~content1:{|Pair 1 "hello"|} + ~content2:{|Pair 1 "hello"|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Tests that annotations are not taken into account when hashing keys. + Here the types [or int string] and [or (int %id) (string %name)] + should hash to the same key. + *) +let test_annotation_or () = + assert_keys_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"(or int string)" + ~ty2:{|(or (int %id) (string %name))|} + ~content1:{|Left 1|} + ~content2:{|Left 1|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Tests that annotations are not taken into account when hashing keys. + Here the types [int] and [(int :int_alias)] should hash to the same key. + *) +let test_annotation_type_alias () = + assert_keys_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"int" + ~ty2:"(int :int_alias)" + ~content1:"0" + ~content2:"0" + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Tests that annotations are not taken into account when hashing keys. + Here the types [pair (or int string) int] and + [pair (or (int %id) (string %name)) int] should hash to the same key. + *) +let test_annotation_pair_or () = + assert_keys_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"pair (or int string) int" + ~ty2:{|pair (or (int %id) (string %name)) int|} + ~content1:{|Pair (Left 1) 2|} + ~content2:{|Pair (Left 1) 2|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type [option int] and [option nat] with the same + content, [None], don't map to the same hash. *) +let test_option_none () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"option int" + ~ty2:"option nat" + ~content1:{|None|} + ~content2:{|None|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +(** Test that a ticket of type [option int] and [option nat] with the same + content, [Some 0], don't map to the same hash. *) +let test_option_some () = + assert_keys_not_equal + ~loc:__LOC__ + ~ticketer1:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ticketer2:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~ty1:"option int" + ~ty2:"option nat" + ~content1:{|Some 0|} + ~content2:{|Some 0|} + ~amount1:1 + ~amount2:1 + ~owner1:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + ~owner2:"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +let tests = + [ + Tztest.tztest "different ticketers" `Quick test_different_ticketers; + Tztest.tztest "different owners" `Quick test_different_owners; + Tztest.tztest "different content" `Quick test_different_content; + Tztest.tztest "different amounts" `Quick test_different_amounts; + Tztest.tztest "nat int" `Quick test_nat_int; + Tztest.tztest "nat mutez" `Quick test_nat_mutez; + Tztest.tztest "not bool" `Quick test_bool_nat; + Tztest.tztest "nat bytes" `Quick test_nat_bytes; + Tztest.tztest "string chain_id" `Quick test_string_chain_id; + Tztest.tztest "string key_hash" `Quick test_string_key_hash; + Tztest.tztest "string timestamp" `Quick test_string_timestamp; + Tztest.tztest "string address" `Quick test_string_address; + Tztest.tztest "string key" `Quick test_string_key; + Tztest.tztest "string signature" `Quick test_string_signature; + Tztest.tztest "annotations for pair" `Quick test_annotation_pair; + Tztest.tztest "annotations for or" `Quick test_annotation_or; + Tztest.tztest "annotations for type alias" `Quick test_annotation_type_alias; + Tztest.tztest "annotations for paired ors" `Quick test_annotation_pair_or; + Tztest.tztest "option none" `Quick test_option_none; + Tztest.tztest "option some" `Quick test_option_some; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket balance key", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_direct_spending.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_direct_spending.ml new file mode 100644 index 000000000000..a73d20ebf5a9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_direct_spending.ml @@ -0,0 +1,195 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* Copyright (c) 2023-2024 Marigold *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Tickets, direct spending from implicit accounts + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_direct_spending.ml + Subject: Test direct spending of tickets from implicit accounts +*) + +open Protocol +open Alpha_context + +type constructor = Pair | Ticket + +let originate_contract ~code ~storage originator block = + let open Lwt_result_syntax in + let storage = Script.lazy_expr (Expr.from_string storage) in + let code = Script.lazy_expr (Expr.toplevel_from_string code) in + let script = Script.{code; storage} in + let* operation, contract_address = + Op.contract_origination ~script (B block) originator + in + let* block = Block.bake ~operation block in + return (contract_address, block) + +let call_contract ~source ~contract ?entrypoint ~arg block = + let open Lwt_result_syntax in + let arg = Script.lazy_expr (Expr.from_string arg) in + let* operation = + Op.transaction + ~parameters:arg + ?entrypoint + (B block) + source + contract + Tez.zero + in + Block.bake ~operation block + +let assert_ticket_balance ~loc ~ticketer ~expected_balance owner block = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let token = + Ticket_token.Ex_token + {ticketer; contents_type = Script_typed_ir.unit_t; contents = ()} + in + let*@ key_hash, ctxt = Ticket_balance_key.of_ex_token ctxt ~owner token in + let*@ balance_opt, _ctxt = Ticket_balance.get_balance ctxt key_hash in + let balance = Option.value ~default:Z.zero balance_opt in + Assert.equal_z ~loc balance (Z.of_int expected_balance) + +let ticket_boomerang_script = + {| +# This contract sends back a unit ticket of amount 1 to its sender +parameter unit; +storage unit; +code + { + DROP; + NIL operation; + SENDER; CONTRACT (ticket unit); ASSERT_SOME; + PUSH mutez 0; + PUSH nat 1; UNIT; TICKET; ASSERT_SOME; + TRANSFER_TOKENS; + CONS; + UNIT; SWAP; PAIR + } + |} + +let ticket_consumer_script = + {| +# This contract consumes a unit ticket +parameter (ticket unit); +storage unit; +code + { + CDR; + NIL operation; + PAIR + } +|} + +(** This test validates the transfer of tickets from implicit accounts to originated accounts + using the [Transaction] manager operation. It performs the following steps: + + 1. Deposit a ticket into an implicit account using [ticket_boomerang_script]. + 2. The implicit account then transfers the ticket to [ticket_consumer_script] + using [Transaction]. + 3. The outcome depends [direct_ticket_spending_enable] feature flag: + - If enabled: The ticket transfer should be successful, + resulting in an updated balance in the ticket table. + - If disabled: The transfer attempt should fail, + triggering a [Bad_contract_parameter] error. *) +let test_spending ~direct_ticket_spending_enable ~constructor () = + let open Lwt_result_syntax in + let constants = + let default_constants = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_test + in + { + default_constants with + consensus_threshold = 0; + direct_ticket_spending_enable; + } + in + let* block, (delegate, implicit) = Context.init_with_constants2 constants in + (* Originate a contract sending tickets to whoever ask for them. *) + let* boomerang, block = + originate_contract + ~code:ticket_boomerang_script + ~storage:"Unit" + delegate + block + in + let boomerang_str = Format.asprintf "%a" Contract.pp boomerang in + let* consumer, block = + originate_contract + ~code:ticket_consumer_script + ~storage:"Unit" + delegate + block + in + let* () = + assert_ticket_balance + ~loc:__LOC__ + ~ticketer:boomerang + ~expected_balance:0 + (Destination.Contract implicit) + block + in + let* block = + call_contract ~source:implicit ~contract:boomerang ~arg:"Unit" block + in + let* () = + assert_ticket_balance + ~loc:__LOC__ + ~ticketer:boomerang + ~expected_balance:1 + (Destination.Contract implicit) + block + in + let arg = + match constructor with + | Pair -> sf "Pair %S Unit 1" boomerang_str + | Ticket -> sf "Ticket %S unit Unit 1" boomerang_str + in + if direct_ticket_spending_enable then + let* block = call_contract ~source:implicit ~contract:consumer ~arg block in + assert_ticket_balance + ~loc:__LOC__ + ~ticketer:boomerang + ~expected_balance:0 + (Destination.Contract implicit) + block + else + let*! res = call_contract ~source:implicit ~contract:consumer ~arg block in + Assert.proto_error ~loc:__LOC__ res (function + | Script_interpreter.Bad_contract_parameter _ -> true + | _ -> false) + +let tests = + [ + Tztest.tztest + "Test ticket spending from implicit accounts (feature enabled) with Pair \ + ticket constructor" + `Quick + (test_spending ~direct_ticket_spending_enable:true ~constructor:Pair); + Tztest.tztest + "Test ticket spending from implicit accounts (feature disabled) with \ + Pair ticket constructor" + `Quick + (test_spending ~direct_ticket_spending_enable:false ~constructor:Pair); + Tztest.tztest + "Test ticket spending from implicit accounts (feature enabled) with \ + Ticket constructor" + `Quick + (test_spending ~direct_ticket_spending_enable:true ~constructor:Ticket); + Tztest.tztest + "Test ticket spending from implicit accounts (feature disabled) with \ + Ticket constructor" + `Quick + (test_spending ~direct_ticket_spending_enable:false ~constructor:Ticket); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket direct spending", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_lazy_storage_diff.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_lazy_storage_diff.ml new file mode 100644 index 000000000000..8eba4534e7a3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_lazy_storage_diff.ml @@ -0,0 +1,698 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_scanner) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_lazy_storage_diff.ml + Subject: Ticket scanner tests +*) + +open Protocol +open Alpha_context + +let assert_equal_string_list ~loc msg = + Assert.assert_equal_list ~loc String.equal msg Format.pp_print_string + +let string_list_of_ex_token_diffs ctxt token_diffs = + let open Lwt_result_wrap_syntax in + let accum (xs, ctxt) + (Ticket_token.Ex_token {ticketer; contents_type; contents}, amount) = + let*@ x, ctxt = + Script_ir_unparser.unparse_comparable_data + ctxt + Script_ir_unparser.Readable + contents_type + contents + in + let str = + Format.asprintf + "((%a, %a), %a)" + Contract.pp + ticketer + Michelson_v1_printer.print_expr + x + Z.pp_print + amount + in + return (str :: xs, ctxt) + in + let* xs, ctxt = List.fold_left_es accum ([], ctxt) token_diffs in + return (List.rev xs, ctxt) + +let make_ex_token ctxt ~ticketer ~type_exp ~content_exp = + let open Lwt_result_wrap_syntax in + let*?@ Script_ir_translator.Ex_comparable_ty contents_type, ctxt = + let node = Micheline.root @@ Expr.from_string type_exp in + Script_ir_translator.parse_comparable_ty ctxt node + in + let*@ ticketer = Lwt.return @@ Contract.of_b58check ticketer in + let*@ contents, ctxt = + let node = Micheline.root @@ Expr.from_string content_exp in + Script_ir_translator.parse_comparable_data ctxt contents_type node + in + return (Ticket_token.Ex_token {ticketer; contents_type; contents}, ctxt) + +let assert_equal_balances ~loc ctxt given expected = + let open Lwt_result_wrap_syntax in + let* ctxt, tbs1 = + List.fold_left_map_es + (fun ctxt ((ticketer, content), delta) -> + let+ token, ctxt = + make_ex_token + ctxt + ~ticketer + ~type_exp:"string" + ~content_exp:(Printf.sprintf "%S" content) + in + (ctxt, (token, Z.of_int delta))) + ctxt + expected + in + let* tbs1, ctxt = string_list_of_ex_token_diffs ctxt tbs1 in + let* tbs2, _ctxt = string_list_of_ex_token_diffs ctxt given in + assert_equal_string_list + ~loc + "Compare token balances" + (List.sort String.compare tbs1) + (List.sort String.compare tbs2) + +let updates_of_key_values ctxt key_values = + let open Lwt_result_wrap_syntax in + List.fold_right_es + (fun (key, value) (kvs, ctxt) -> + let*@ key_hash, ctxt = + Script_ir_translator.hash_comparable_data + ctxt + Script_typed_ir.int_t + (Script_int.of_int key) + in + return + ( { + Big_map.key = Expr.from_string @@ string_of_int key; + key_hash; + value = Option.map Expr.from_string value; + } + :: kvs, + ctxt )) + key_values + ([], ctxt) + +let make_alloc big_map_id alloc updates = + Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update {init = Lazy_storage.Alloc alloc; updates}) + +let init () = + let open Lwt_result_wrap_syntax in + let* block, source = Context.init1 () in + let* operation, originated = + Op.contract_origination_hash (B block) source ~script:Op.dummy_script + in + let* block = Block.bake ~operation block in + let* inc = Incremental.begin_construction block in + return (originated, Incremental.alpha_ctxt inc) + +let setup ctxt contract ~key_type ~value_type entries = + let open Lwt_result_wrap_syntax in + let*@ ctxt, big_map_id = Big_map.fresh ~temporary:false ctxt in + let key_type = Expr.from_string key_type in + let value_type = Expr.from_string value_type in + let* updates, ctxt = updates_of_key_values ctxt entries in + let alloc = make_alloc big_map_id Big_map.{key_type; value_type} updates in + return (alloc, big_map_id, contract, ctxt) + +let new_big_map ctxt contract ~key_type ~value_type entries = + let open Lwt_result_wrap_syntax in + let* alloc, big_map_id, contract, ctxt = + setup ctxt contract ~key_type ~value_type + @@ List.map (fun (k, v) -> (k, Some v)) entries + in + let storage = Expr.from_string "{}" in + let*@ ctxt = + Contract.update_script_storage ctxt contract storage (Some [alloc]) + in + return (big_map_id, ctxt) + +let alloc_diff ctxt contract ~key_type ~value_type entries = + let open Lwt_result_wrap_syntax in + let* allocations, _, _, ctxt = + setup + ctxt + contract + ~key_type + ~value_type + (List.map (fun (k, v) -> (k, Some v)) entries) + in + return (allocations, ctxt) + +let remove_diff ctxt contract ~key_type ~value_type ~existing_entries = + let open Lwt_result_wrap_syntax in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type existing_entries + in + return (Lazy_storage.make Lazy_storage.Kind.Big_map big_map_id Remove, ctxt) + +let copy_diff ctxt contract ~key_type ~value_type ~existing_entries ~updates = + let open Lwt_result_wrap_syntax in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type existing_entries + in + let* updates, ctxt = updates_of_key_values ctxt updates in + let*@ ctxt, new_big_map_id = Big_map.fresh ctxt ~temporary:false in + return + ( Lazy_storage.make + Lazy_storage.Kind.Big_map + new_big_map_id + (Update {init = Lazy_storage.Copy {src = big_map_id}; updates}), + ctxt ) + +let existing_diff ctxt contract ~key_type ~value_type ~existing_entries ~updates + = + let open Lwt_result_wrap_syntax in + let* big_map_id, ctxt = + new_big_map ctxt contract ~key_type ~value_type existing_entries + in + let* updates, ctxt = updates_of_key_values ctxt updates in + return + ( Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update {init = Lazy_storage.Existing; updates}), + ctxt ) + +(** Test that no ticket-tokens are extracted from a diff for allocating an empty + big-map. *) +let test_allocate_new_empty () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + alloc_diff ctxt contract ~key_type:"int" ~value_type:"ticket string" [] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances ~loc:__LOC__ ctxt diff [] + +(** Test that no ticket-tokens are extracted from a lazy-diff of a big-map + that does not contain tickets. *) +let test_allocate_new_no_tickets () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + alloc_diff + ctxt + contract + ~key_type:"int" + ~value_type:"string" + [(1, {|"A"|}); (2, {|"B"|}); (3, {|"C"|})] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances ~loc:__LOC__ ctxt diff [] + +(** Test that ticket-tokens can be extracted from a lazy-diff for allocating a + new big-map. *) +let test_allocate_new () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + alloc_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + (3, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 2); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), 3); + ] + +(** Test that ticket-tokens with negative balances are extracted from a + lazy-diff that removes a big-map. *) +let test_remove_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + remove_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + (3, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), -2); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), -3); + ] + +(** Test that there are no ticket-token balance deltas extracted from a + lazy-diff that applies no updates. *) +let test_no_updates_to_existing_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + existing_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + (3, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + ~updates:[] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances ~loc:__LOC__ ctxt diff [] + +(** Test that ticket-tokens extracted reflect the balance diffs that are + extracted from a lazy-diff that modifies an existing big-map. + *) +let test_update_existing_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + existing_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + (3, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + ~updates: + [ + (* Replace entry at index 1 *) + (1, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "yellow" 4|}); + (* Remove entry at index 2 *) + (2, None); + (* Add new entry at index 4 *) + (4, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "pink" 5|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), -2); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), 4); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "pink"), 5); + ] + +(** Test that ticket-tokens extracted reflect the balance diffs that are + extracted from a lazy-diff that modifies an existing big-map and with + multiple updates to the same key. + *) +let test_update_same_key_multiple_times_existing_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + existing_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [(1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|})] + ~updates: + [ + (* Replace entry at index 1 *) + (1, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "yellow" 1|}); + (* Replace entry at index 1 *) + (1, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 1|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), -1); + ] + +(** Test that ticket-tokens extracted reflect the balance diffs that are + extracted from a lazy-diff that modifies an existing big-map and with + multiple removals of the same item. + *) +let test_remove_same_key_multiple_times_existing_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + existing_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [(1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|})] + ~updates: + [ + (* Remove entry at index 1 *) + (1, None); + (* Remove entry at index 1 again *) + (1, None); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [(("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1)] + +(** Test that ticket-tokens extracted reflect the balance diffs that are + extracted from a lazy-diff that modifies an existing big-map and with + multiple additions and removals of the same item. + *) +let test_update_and_remove_same_key_multiple_times_existing_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + existing_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [(1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|})] + ~updates: + [ + (* Remove entry at index 1 *) + (1, None); + (* Add a yellow ticket at index 1. *) + (1, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "yellow" 1|}); + (* Remove entry at index 1 again *) + (1, None); + (* Add a green ticket at index 1. *) + (1, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 1|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 1); + ] + +(** Test that the extracted ticket-tokens from a lazy diff for copying a big-map + reflects the tokens of the source as well as the updates. *) +let test_copy_big_map () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + copy_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + (3, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + ~updates:[] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 2); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), 3); + ] + +(** Test that the extracted ticket-tokens from a lazy diff for copying a big-map + reflects the tokens of the source as well as the updates. *) +let test_copy_big_map_with_updates () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + copy_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + (3, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + ~updates: + [ + (* Remove element at index 1*) + (1, None); + (* Replace element at index 3 *) + (3, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "yellow" 4|}); + (* Add a new element at index 4 *) + (4, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "pink" 5|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 2); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), 3); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), -3); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), 4); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "pink"), 5); + ] + +(** Test that the extracted ticket-tokens from a lazy diff for copying a big-map + with multiple updates to the same key reflects the tokens of the source as + well as the updates. *) +let test_copy_big_map_with_updates_to_same_key () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff, ctxt = + copy_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [(1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|})] + ~updates: + [ + (* Remove element at index 1 *) + (1, None); + (* Add element at index 1 *) + (1, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "yellow" 2|}); + (* Remove again *) + (1, None); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff ctxt [diff] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (* From the copy of the big-map *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1); + (* From removing the element from the copied big-map *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (* From adding to the copied big-map. *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), 2); + (* From removing from the copied big-map *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "yellow"), -2); + ] + +(** Test combinations of lazy-diffs. *) +let test_mix_lazy_diffs () = + let open Lwt_result_wrap_syntax in + let* contract, ctxt = init () in + let* diff_copy, ctxt = + copy_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [(1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|})] + ~updates: + [ + (* Remove element at index 1 *) + (1, None); + (* Replace element at index 2 *) + (2, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "green" 2|}); + ] + in + let* diff_existing, ctxt = + existing_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [(1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1|})] + ~updates: + [ + (* Remove entry at index 2 *) + (2, None); + (* Add new entry at index 3 *) + (3, Some {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "blue" 3|}); + ] + in + let* diff_remove, ctxt = + remove_diff + ctxt + contract + ~key_type:"int" + ~value_type:"ticket string" + ~existing_entries: + [ + (1, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "white" 1|}); + (2, {|Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "black" 1|}); + ] + in + let*@ diff, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff + ctxt + [diff_copy; diff_existing; diff_remove] + in + assert_equal_balances + ~loc:__LOC__ + ctxt + diff + [ + (* From the copy *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green"), 2); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red"), 1); + (* From updating an existing *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue"), 3); + (* From the remove *) + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "white"), -1); + (("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "black"), -1); + ] + +let tests = + [ + Tztest.tztest "allocate new empty" `Quick test_allocate_new_empty; + Tztest.tztest "allocate new" `Quick test_allocate_new; + Tztest.tztest "allocate new no tickets" `Quick test_allocate_new_no_tickets; + Tztest.tztest "Remove" `Quick test_remove_big_map; + Tztest.tztest + "no updates to existing" + `Quick + test_no_updates_to_existing_big_map; + Tztest.tztest "update existing big-map" `Quick test_update_existing_big_map; + Tztest.tztest + "update same key multiple times on existing big-map" + `Quick + test_update_same_key_multiple_times_existing_big_map; + Tztest.tztest + "remove same key multiple times on existing big-map" + `Quick + test_remove_same_key_multiple_times_existing_big_map; + Tztest.tztest + "update and remove same key multiple times on existing big-map" + `Quick + test_update_and_remove_same_key_multiple_times_existing_big_map; + Tztest.tztest "copy" `Quick test_copy_big_map; + Tztest.tztest "copy with updates" `Quick test_copy_big_map_with_updates; + Tztest.tztest + "copy with multiple updates to same key" + `Quick + test_copy_big_map_with_updates_to_same_key; + Tztest.tztest "mix lazy diffs" `Quick test_mix_lazy_diffs; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket lazy storage diff", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_manager.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_manager.ml new file mode 100644 index 000000000000..c83fda8e0e6e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_manager.ml @@ -0,0 +1,819 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_balance_key) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_manager.ml + Subject: Tests that compare the ticket-balance table against tickets in the + contract storages. The tests include a lot of operations that + sends and store tickets. After each operation we check that the + ticket balance table reflects the actual tickets stored. + This relies on the invariant that any ticket-token referenced by + the table corresponds to a ticket in a storage. Currently, storage + is the only place to actually keep existing tickets. +*) + +open Protocol +open Alpha_context + +type init_env = { + block : Block.t; + baker : Signature.public_key_hash; + contract : Contract.t; +} + +let init_env () = + let open Lwt_result_wrap_syntax in + let* block, baker, contract, _src2 = Contract_helpers.init () in + return {block; baker; contract} + +let collect_token_amounts ctxt tickets = + let open Lwt_result_syntax in + let accum (tokens, ctxt) ticket = + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in + let tokens = (token, Script_int.(to_zint (amount :> n num))) :: tokens in + return (tokens, ctxt) + in + List.fold_left_es accum ([], ctxt) tickets + +let tokens_of_value ~include_lazy ctxt ty x = + let open Lwt_result_wrap_syntax in + let*? has_tickets, ctxt = Ticket_scanner.type_has_tickets ctxt ty in + let* tickets, ctxt = + Ticket_scanner.tickets_of_value ~include_lazy ctxt has_tickets x + in + let* tas, ctxt = collect_token_amounts ctxt tickets in + let* bm, ctxt = + Ticket_token_map.of_list + ctxt + ~merge_overlap:(fun ctxt v1 v2 -> Ok (Z.add v1 v2, ctxt)) + tas + in + Lwt.return @@ Ticket_token_map.to_list ctxt bm + +(* Extract ticket-token balance of storage *) +let ticket_balance_of_storage ctxt (contract : Alpha_context.Contract.t) = + let open Lwt_result_wrap_syntax in + match contract with + | Implicit _ -> return ([], ctxt) + | Originated contract_hash -> ( + let*@ ctxt, script = + Alpha_context.Contract.get_script ctxt contract_hash + in + match script with + | None -> return ([], ctxt) + | Some script -> + let*@ ( Script_ir_translator.Ex_script + (Script {storage; storage_type; _}), + ctxt ) = + Script_ir_translator.parse_script + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let*@ tokens, ctxt = + tokens_of_value ~include_lazy:true ctxt storage_type storage + in + let*@ tokens, ctxt = + List.fold_left_es + (fun (acc, ctxt) (ex_token, amount) -> + let* key, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Contract contract) + ex_token + in + let acc = (key, amount) :: acc in + return (acc, ctxt)) + ([], ctxt) + tokens + in + return (tokens, ctxt)) + +let transaction block ~sender ~recipient ~amount ~parameters = + let open Lwt_result_wrap_syntax in + let parameters = Script.lazy_expr @@ Expr.from_string parameters in + let* block = Incremental.begin_construction block in + let* operation = + Op.transaction + (I block) + ~gas_limit:Max + ~entrypoint:Entrypoint.default + ~parameters + ~fee:Tez.zero + sender + recipient + (Tez.of_mutez_exn amount) + in + let* block = Incremental.add_operation block operation in + Incremental.finalize_block block + +let all_contracts current_block = + let open Lwt_result_wrap_syntax in + let* result = Incremental.begin_construction current_block in + let ctxt = Incremental.alpha_ctxt result in + let*! cs = Contract.list ctxt in + return cs + +(* Fetch all added contracts between [before] and [after]. *) +let new_contracts ~before ~after = + let open Lwt_result_wrap_syntax in + let* cs1 = all_contracts before in + let* cs2 = all_contracts after in + let not_in_cs1 = + let module S = Set.Make (String) in + let set = S.of_list @@ List.map Contract.to_b58check cs1 in + fun c -> not @@ S.mem (Contract.to_b58check c) set + in + return @@ List.filter not_in_cs1 cs2 + +let get_first_two_new_contracts before f = + let open Lwt_result_wrap_syntax in + let* after = f before in + let* c = new_contracts ~before ~after in + match c with + | c1 :: c2 :: _ -> return (c1, c2, after) + | _ -> failwith "Expected two new contracts" + +let show_key_balance key balance = + let key = String.escaped @@ Format.asprintf "%a" Ticket_hash.pp key in + let balance = Z.to_string balance in + (key, balance) + +let compare_key_balance (k1, b1) (k2, b2) = + match String.compare k1 k2 with + | n when n <> 0 -> n + | _ -> String.compare b1 b2 + +let normalize_balances key_balances = + List.filter_map + (fun (key, balance) -> + if Z.equal balance Z.zero then None + else Some (show_key_balance key balance)) + key_balances + |> List.sort compare_key_balance + +let equal_key_balances kb1 kb2 = + let compare x y = compare_key_balance x y = 0 in + List.for_all2 + ~when_different_lengths:"Length of key-balances don't match" + compare + kb1 + kb2 + +let show_balance_table kvs = + let show_rows kvs = + let key_col_length = + List.fold_left (fun mx (s, _) -> max mx (String.length s)) 0 kvs + in + let column align col_length s = + let space = + Stdlib.List.init (col_length - String.length s) (fun _ -> " ") + |> String.concat "" + in + match align with + | `Left -> Printf.sprintf "%s%s" s space + | `Right -> Printf.sprintf "%s%s" space s + in + List.map + (fun (k, v) -> + Printf.sprintf + "| %s | %s |" + (column `Left key_col_length k) + (column `Right 8 v)) + kvs + |> String.concat "\n" + in + show_rows (("Token x Content x Owner", "Balance") :: kvs) + +let validate_ticket_balances block = + let open Lwt_result_wrap_syntax in + let* contracts = all_contracts block in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let* kvs_storage, ctxt = + List.fold_left_es + (fun (acc, ctxt) contract -> + let* lists, ctxt = ticket_balance_of_storage ctxt contract in + return (lists @ acc, ctxt)) + ([], ctxt) + contracts + in + let*@ kvs_balance, _ctxt = + List.fold_left_es + (fun (acc, ctxt) (key, _) -> + let* balance, ctxt = Ticket_balance.get_balance ctxt key in + let acc = + match balance with None -> acc | Some b -> (key, b) :: acc + in + return (acc, ctxt)) + ([], ctxt) + kvs_storage + in + let kvs_storage = normalize_balances kvs_storage in + let kvs_balance = normalize_balances kvs_balance in + let print_both () = + print_endline "Storage table:" ; + print_endline @@ show_balance_table kvs_storage ; + print_endline "Balance table:" ; + print_endline @@ show_balance_table kvs_balance + in + match equal_key_balances kvs_balance kvs_storage with + | Ok true -> return_unit + | Ok false -> + print_both () ; + failwith "Storage and balance don't match" + | Error e -> + print_both () ; + failwith "%s" e + +module Ticket_manager = struct + (* A rather complicated script for various ticket operations. + See documentation for [action] below for a list of the params. + *) + let script = + {| + { parameter + (or (or (or (or %add (pair %add_lazy (pair int string) nat) (pair %add_strict string nat)) + (pair %create (pair string nat) key_hash)) + (or (or %remove (or (unit %remove_all_lazy) (int %remove_lazy)) (unit %remove_strict)) + (big_map %replace_big_map int (ticket string)))) + (or %send + (or (pair %send_lazy int address) (pair %send_new (pair string nat) address)) + (or (unit %send_self_replace_big_map) (address %send_strict)))) ; + storage (pair (list %list (ticket string)) (big_map %map int (ticket string))) ; + code { NIL (ticket string) ; + SWAP ; + UNPAIR ; + IF_LEFT + { DIG 2 ; + DROP ; + IF_LEFT + { IF_LEFT + { IF_LEFT + { # `add_lazy` entrypoint + UNPAIR ; + UNPAIR ; + DIG 3 ; + DIG 3 ; + SWAP ; + UNPAIR ; + SWAP ; + DUP 3 ; + DUP 6 ; + TICKET ; + ASSERT_SOME ; + SOME ; + DUP 5 ; + GET_AND_UPDATE ; + DROP ; + DUP 3 ; + DUP 6 ; + TICKET ; + ASSERT_SOME ; + SOME ; + DUP 5 ; + GET_AND_UPDATE ; + DROP ; + DIG 2 ; + DIG 4 ; + TICKET ; + ASSERT_SOME ; + SOME ; + DIG 3 ; + GET_AND_UPDATE ; + DROP ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } + { + # `add_strict` entrypoint + UNPAIR ; + DIG 2 ; + UNPAIR ; + DIG 3 ; + DIG 3 ; + TICKET ; + ASSERT_SOME ; + CONS ; + PAIR ; + NIL operation ; + PAIR } } + { # `create` entrypoint + UNPAIR ; + UNPAIR ; + DUP 3 ; + DUG 2 ; + TICKET ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + SOME ; + CREATE_CONTRACT + { parameter (ticket string) ; + storage (ticket string) ; + code { JOIN_TICKETS ; + IF_NONE + { PUSH string "Failed to join tickets" ; FAILWITH } + { NIL operation ; PAIR } } } ; + SWAP ; + DROP ; + EMPTY_BIG_MAP int (ticket string) ; + PUSH nat 99 ; + PUSH string "NEW_TICKET_IN_ORIGINATED_CONTRACT" ; + TICKET ; + ASSERT_SOME ; + SOME ; + PUSH int 1 ; + GET_AND_UPDATE ; + DROP ; + PUSH mutez 0 ; + DIG 3 ; + SOME ; + CREATE_CONTRACT + { parameter (ticket string) ; + storage (big_map int (ticket string)) ; + code { UNPAIR ; + SOME ; + PUSH int 1 ; + GET_AND_UPDATE ; + DROP ; + NIL operation ; + PAIR } } ; + SWAP ; + DROP ; + DIG 2 ; + NIL operation ; + DIG 2 ; + CONS ; + DIG 2 ; + CONS ; + PAIR } } + { IF_LEFT + { IF_LEFT + { IF_LEFT + { # `remove_all_lazy` entrypoint + DROP ; + CAR ; + EMPTY_BIG_MAP int (ticket string) ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } + { # `remove` entrypoint + SWAP ; + UNPAIR ; + SWAP ; + NONE (ticket string) ; + DIG 3 ; + GET_AND_UPDATE ; + DROP ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } } + { # `remove_strict` entrypoint + DROP ; CDR ; NIL (ticket string) ; PAIR ; NIL operation ; PAIR } } + { # `replace_big_map` entrypoint + SWAP ; + CAR ; + SWAP ; + NONE (ticket string) ; + PUSH int 1 ; + GET_AND_UPDATE ; + DROP ; + PUSH nat 1 ; + PUSH string "ADDED_BY_REPLACE_BIG_MAP" ; + TICKET ; + ASSERT_SOME ; + SOME ; + PUSH int 11 ; + GET_AND_UPDATE ; + DROP ; + NONE (ticket string) ; + PUSH int 11 ; + GET_AND_UPDATE ; + DROP ; + PUSH nat 1 ; + PUSH string "ADDED_BY_REPLACE_BIG_MAP" ; + TICKET ; + ASSERT_SOME ; + SOME ; + PUSH int 11 ; + GET_AND_UPDATE ; + DROP ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } } } + { IF_LEFT + { DIG 2 ; + DROP ; + IF_LEFT + { # `send_lazy` entrypoint + UNPAIR ; + DIG 2 ; + UNPAIR ; + DIG 3 ; + CONTRACT (ticket string) ; + IF_NONE + { DIG 2 ; + DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { DIG 2 ; + NONE (ticket string) ; + DIG 4 ; + GET_AND_UPDATE ; + IF_NONE + { SWAP ; DROP ; PUSH string "Could not find ticket" ; FAILWITH } + { DIG 2 ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + SWAP ; + DIG 2 ; + PAIR ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + { # `send_new` entrypoint + UNPAIR ; + UNPAIR ; + DIG 3 ; + DIG 3 ; + SWAP ; + UNPAIR ; + DIG 2 ; + CONTRACT (ticket string) ; + IF_NONE + { DIG 2 ; + DROP ; + DIG 2 ; + DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { PUSH mutez 0 ; + DIG 5 ; + DIG 5 ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + DUG 2 ; + PAIR ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + { IF_LEFT + { # `send_self_replace_big_map` entrypoint + DROP ; + SWAP ; + DROP ; + UNPAIR ; + SELF_ADDRESS ; + CONTRACT + (or (or (or (or %add (pair %add_lazy (pair int string) nat) (pair %add_strict string nat)) + (pair %create (pair string nat) key_hash)) + (or (or %remove (or (unit %remove_all_lazy) (int %remove_lazy)) (unit %remove_strict)) + (big_map %replace_big_map int (ticket string)))) + (or %send + (or (pair %send_lazy int address) (pair %send_new (pair string nat) address)) + (or (unit %send_self_replace_big_map) (address %send_strict)))) ; + IF_NONE + { PUSH string "Failed to get self-contract" ; FAILWITH } + { EMPTY_BIG_MAP int (ticket string) ; + DIG 3 ; + PUSH nat 1 ; + PUSH string "ADDED_BY_SEND_SELF_REPLACE" ; + TICKET ; + ASSERT_SOME ; + SOME ; + PUSH int 10 ; + GET_AND_UPDATE ; + DROP ; + NONE (ticket string) ; + PUSH int 2 ; + GET_AND_UPDATE ; + DROP ; + DIG 2 ; + PUSH mutez 0 ; + DIG 2 ; + RIGHT (or (or unit int) unit) ; + RIGHT + (or (or (pair (pair int string) nat) (pair string nat)) (pair (pair string nat) key_hash)) ; + LEFT (or (or (pair int address) (pair (pair string nat) address)) (or unit address)) ; + TRANSFER_TOKENS ; + SWAP ; + PUSH nat 1 ; + PUSH string "ADDED_BY_SEND_SELF_REPLACE_TO_STORAGE" ; + TICKET ; + ASSERT_SOME ; + SOME ; + PUSH int 11 ; + GET_AND_UPDATE ; + DROP ; + DIG 2 ; + PAIR ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } + { # `send_strict` entrypoint + SWAP ; + UNPAIR ; + DIG 2 ; + CONTRACT (ticket string) ; + IF_NONE + { DROP ; + PUSH string "Contract of type `ticket(string)` not found" ; + FAILWITH } + { NONE (ticket string) ; + DIG 2 ; + ITER { SWAP ; IF_NONE { SOME } { PAIR ; JOIN_TICKETS } } ; + IF_NONE + { DROP ; PUSH string "Couldn't produce a ticket" ; FAILWITH } + { SWAP ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + SWAP ; + DIG 2 ; + PAIR ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } } } } } + |} + + type remove_args = Remove_lazy of int | Remove_strict | Remove_all_lazy + + type send_args = + | Send_lazy of {index : int; recipient : Contract.t} + | Send_strict of Contract.t + | Send_new of {content : string; amount : int; recipient : Contract.t} + | Send_self_replace_big_map + + type add_args = + | Add_lazy of {index : int; content : string; amount : int} + | Add_strict of {content : string; amount : int} + + type action = + | Remove of remove_args + | Add of add_args + | Create of {content : string; amount : int; originator : Contract.t} + | Send of send_args + + let remove_lazy ~index = Remove (Remove_lazy index) + + let remove_strict = Remove Remove_strict + + let add_lazy ~index ~content ~amount = Add (Add_lazy {index; content; amount}) + + let add_strict ~content ~amount = Add (Add_strict {content; amount}) + + let create ~content ~amount ~originator = Create {content; amount; originator} + + let send_lazy ~index ~recipient = Send (Send_lazy {index; recipient}) + + let send_strict ~recipient = Send (Send_strict recipient) + + let send_new ~content ~amount ~recipient = + Send (Send_new {content; amount; recipient}) + + let remove_all_lazy = Remove Remove_all_lazy + + let send_self_replace_big_map = Send Send_self_replace_big_map + + let string_args = function + | Remove (Remove_lazy ix) -> + Printf.sprintf "Left (Right (Left (Left (Right %d))))" ix + | Remove Remove_strict -> "Left (Right (Left (Right Unit)))" + | Remove Remove_all_lazy -> "Left (Right (Left (Left (Left Unit))))" + | Add (Add_lazy {index; content; amount}) -> + Printf.sprintf + {|Left (Left (Left (Left (Pair (Pair %d "%s") %d))))|} + index + content + amount + | Add (Add_strict {content; amount}) -> + Printf.sprintf + {|Left (Left (Left (Right (Pair "%s" %d))))|} + content + amount + | Create {content; amount; originator} -> + Printf.sprintf + {|Left (Left (Right (Pair (Pair "%s" %d) "%s")))|} + content + amount + (Contract.to_b58check originator) + | Send (Send_lazy {index; recipient}) -> + Printf.sprintf + {|Right (Left (Left (Pair %d "%s")))|} + index + (Contract.to_b58check recipient) + | Send (Send_strict contract) -> + Printf.sprintf + {|Right (Right (Right "%s"))|} + (Contract.to_b58check contract) + | Send (Send_new {content; amount; recipient}) -> + Printf.sprintf + {|(Right (Left (Right (Pair (Pair "%s" %d) "%s"))))|} + content + amount + (Contract.to_b58check recipient) + | Send Send_self_replace_big_map -> "Right (Right (Left Unit))" + + let originate block ~originator baker = + Contract_helpers.originate_contract_from_string + ~script + ~storage:"Pair {} {}" + ~source_contract:originator + ~baker + block + + let transaction block ~sender ~ticket_manager ~parameters = + let parameters = string_args parameters in + transaction block ~sender ~recipient:ticket_manager ~amount:0L ~parameters +end + +(* Sets up the environment and returns a function for running a transaction + and validating the balance table against tickets in the storage once + completed. *) +let setup_test () = + let open Lwt_result_wrap_syntax in + let module TM = Ticket_manager in + let* {block; baker; contract = originator} = init_env () in + let* ticket_manager, _script, block = TM.originate block ~originator baker in + let test block parameters = + let* b = + TM.transaction block ~sender:originator ~ticket_manager ~parameters + in + let* () = validate_ticket_balances b in + return b + in + return (test, originator, block) + +(** Test create new contracts and send tickets to them. *) +let test_create_contract_and_send_tickets () = + let open Lwt_result_wrap_syntax in + let module TM = Ticket_manager in + let* test, originator, b = setup_test () in + + (* Call the `create` endpoint that creates two new ticket receiver contracts: + - Both contracts accepts a single ticket as an argument. + - The first holds a big-map with tickets in its storage. + - The second holds a ticket in its storage and only accepts "green" tickets. + - The second contract joins all received tickets. + *) + let* ticket_receiver_green_1, ticket_receiver_green_2, b = + get_first_two_new_contracts b @@ fun b -> + test b @@ TM.create ~content:"Green" ~amount:1 ~originator + in + (* + * Invoke the second ticket receiver contract: + - Remove all strict tickets + - Replace them with a list of 2 green ones + - Send all (joined) strict tickets to the ticket receiver + *) + let* b = test b @@ TM.remove_strict in + let* b = test b @@ TM.add_strict ~content:"Green" ~amount:1 in + let* b = test b @@ TM.add_strict ~content:"Green" ~amount:1 in + let* b = test b @@ TM.send_strict ~recipient:ticket_receiver_green_1 in + (* Send a new ticket *) + let* b = + test + b + (TM.send_new + ~content:"Green" + ~amount:10 + ~recipient:ticket_receiver_green_1) + in + (* Add a green ticket to the lazy storage at index 1 and send it to the green + ticket-receiver *) + let* b = test b @@ TM.add_lazy ~index:1 ~content:"Green" ~amount:10 in + let* (_b : Block.t) = + test b @@ TM.send_lazy ~index:1 ~recipient:ticket_receiver_green_2 + in + return_unit + +(** Tets add and remove tickets from lazy storage. *) +let test_add_remove_from_lazy_storage () = + let open Lwt_result_wrap_syntax in + let module TM = Ticket_manager in + let* tm, _, b = setup_test () in + let* b = tm b @@ TM.add_lazy ~index:1 ~content:"Red" ~amount:10 in + let* b = tm b @@ TM.add_lazy ~index:2 ~content:"Green" ~amount:10 in + let* b = tm b @@ TM.add_lazy ~index:3 ~content:"Blue" ~amount:10 in + (* Remove ticket at index 1. *) + let* b = tm b @@ TM.remove_lazy ~index:1 in + let* b = tm b @@ TM.add_lazy ~index:1 ~content:"Red" ~amount:1 in + let* b = tm b @@ TM.add_lazy ~index:2 ~content:"Green" ~amount:2 in + let* b = tm b @@ TM.add_lazy ~index:3 ~content:"Blue" ~amount:3 in + (* Remove the big-map. *) + let* b = tm b TM.remove_all_lazy in + (* Add back a ticket at index 1. *) + let* (_b : Block.t) = + tm b @@ TM.add_lazy ~index:1 ~content:"Red" ~amount:10 + in + return_unit + +(** Test send to self and replace big-map. *) +let test_send_self_replace_big_map () = + let open Lwt_result_wrap_syntax in + let module TM = Ticket_manager in + let* tm, _, b = setup_test () in + (* Send self replace bigmap *) + let* b = tm b @@ TM.add_lazy ~index:1 ~content:"Red" ~amount:1 in + let* b = tm b @@ TM.add_lazy ~index:2 ~content:"Green" ~amount:1 in + let* b = tm b @@ TM.add_lazy ~index:3 ~content:"Blue" ~amount:1 in + let* b = tm b @@ TM.send_self_replace_big_map in + let* b = tm b @@ TM.send_self_replace_big_map in + let* (_b : Block.t) = tm b @@ TM.send_self_replace_big_map in + return_unit + +(** Test add to and remove from strict storage. *) +let test_add_remove_strict () = + let open Lwt_result_wrap_syntax in + let module TM = Ticket_manager in + let* tm, _, b = setup_test () in + (* Add some more strict tickets *) + let* b = tm b @@ TM.add_strict ~content:"Red" ~amount:1 in + let* b = tm b @@ TM.add_strict ~content:"Red" ~amount:2 in + let* b = tm b @@ TM.add_strict ~content:"Red" ~amount:20 in + let* b = tm b @@ TM.add_strict ~content:"Green" ~amount:1 in + let* b = tm b @@ TM.add_strict ~content:"Red" ~amount:1 in + + (* Remove strict tickets *) + let* b = tm b @@ TM.remove_strict in + let* (_b : Block.t) = tm b @@ TM.add_strict ~content:"Red" ~amount:1 in + return_unit + +(** Test mixed operations. *) +let test_mixed_operations () = + let open Lwt_result_wrap_syntax in + let module TM = Ticket_manager in + let* tm, _, b = setup_test () in + (* Add some more strict tickets *) + let* b = tm b @@ TM.add_strict ~content:"Red" ~amount:1 in + let* b = tm b @@ TM.add_strict ~content:"Green" ~amount:1 in + (* Add some lazy tickets *) + let* b = tm b @@ TM.add_lazy ~index:1 ~content:"Red" ~amount:1 in + let* b = tm b @@ TM.add_lazy ~index:2 ~content:"Green" ~amount:1 in + let* b = tm b @@ TM.add_lazy ~index:3 ~content:"Blue" ~amount:1 in + (* Remove strict and lazy *) + let* b = tm b @@ TM.remove_strict in + let* (_b : Block.t) = tm b @@ TM.remove_all_lazy in + return_unit + +let tests = + [ + Tztest.tztest "Create contract" `Quick test_create_contract_and_send_tickets; + Tztest.tztest + "Send self replace big-map" + `Quick + test_send_self_replace_big_map; + Tztest.tztest + "Add and remove from strict storage" + `Quick + test_add_remove_strict; + Tztest.tztest + "Add and remove from lazy storage" + `Quick + test_add_remove_from_lazy_storage; + Tztest.tztest "Mix of operations" `Quick test_mixed_operations; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket manager", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml new file mode 100644 index 000000000000..4014664f3284 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_operations_diff.ml @@ -0,0 +1,1327 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_scanner) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_operations_diff.ml + Subject: Ticket scanner tests +*) + +open Protocol +open Alpha_context +open Script_typed_ir + +(** A local non-private type that mirrors + [Ticket_operations_diff.ticket_token_diff]. *) +type ticket_token_diff = { + ticket_token : Ticket_token.ex_token; + total_amount : Script_int.n Script_int.num; + destinations : (Destination.t * ticket_amount) list; +} + +let to_local_ticket_token_diff + {Ticket_operations_diff.ticket_token; total_amount; destinations} = + {ticket_token; total_amount; destinations} + +let assert_fails ~loc ?error m = + let open Lwt_result_syntax in + let*! res = m in + let rec aux err_res = + match (err_res, error) with + | Environment.Ecoproto_error err' :: rest, Some err -> + (* Matched exact error. *) + if err' = err then return_unit else aux rest + | _ :: rest, Some _ -> aux rest + | [], Some _ -> + (* Expected a different error. *) + let msg = + Printf.sprintf "Expected a different error at location %s" loc + in + Stdlib.failwith msg + | _, None -> + (* Any error is ok. *) + return_unit + in + match res with + | Ok _ -> Stdlib.failwith "Expected failure" + | Error err_res -> aux err_res + +let big_map_updates_of_key_values ctxt key_values = + let open Lwt_result_wrap_syntax in + List.fold_right_es + (fun (key, value) (kvs, ctxt) -> + let*@ key_hash, ctxt = + Script_ir_translator.hash_comparable_data + ctxt + Script_typed_ir.int_t + (Script_int.of_int key) + in + return + ( { + Big_map.key = Expr.from_string @@ string_of_int key; + key_hash; + value = Option.map Expr.from_string value; + } + :: kvs, + ctxt )) + key_values + ([], ctxt) + +let new_int_key_big_map ctxt contract ~value_type entries = + let open Lwt_result_wrap_syntax in + let*@ ctxt, big_map_id = Big_map.fresh ~temporary:false ctxt in + let key_type = Expr.from_string "int" in + let value_type = Expr.from_string value_type in + let* updates, ctxt = + big_map_updates_of_key_values ctxt + @@ List.map (fun (k, v) -> (k, Some v)) entries + in + let alloc = + Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update + {init = Lazy_storage.Alloc Big_map.{key_type; value_type}; updates}) + in + let storage = Expr.from_string "{}" in + let*@ ctxt = + Contract.update_script_storage ctxt contract storage (Some [alloc]) + in + return (big_map_id, ctxt) + +let assert_equal_string_list ~loc msg = + Assert.assert_equal_list ~loc String.equal msg Format.pp_print_string + +let string_of_ticket_token ctxt + (Ticket_token.Ex_token {ticketer; contents_type; contents}) = + let open Lwt_result_wrap_syntax in + let*@ x, _ = + Script_ir_unparser.unparse_comparable_data + ctxt + Script_ir_unparser.Readable + contents_type + contents + in + return + @@ Format.asprintf + {|("%a", %a)|} + Contract.pp + ticketer + Michelson_v1_printer.print_expr + x + +let string_of_destination_and_amounts cas = + Format.asprintf + "[%a]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt "; ") + (fun fmt (contract, (amount : ticket_amount)) -> + Format.fprintf + fmt + {|("%a", %s)|} + Destination.pp + contract + Script_int.(to_string (amount :> n num)))) + cas + +let string_of_ticket_operations_diff ctxt + {ticket_token; total_amount; destinations} = + let open Lwt_result_wrap_syntax in + let* ticket_token = string_of_ticket_token ctxt ticket_token in + let destinations = string_of_destination_and_amounts destinations in + return + (Printf.sprintf + "(%s, %s, %s)" + ticket_token + (Script_int.to_string total_amount) + destinations) + +let assert_equal_ticket_token_diffs ctxt ~loc ticket_diffs + ~(expected : ticket_token_diff list) = + let open Lwt_result_wrap_syntax in + (* Sort destinations by contract and the strings alphabetically so that order + does not matter for comparison. *) + let sorted_strings ticket_diffs = + let ticket_diffs = + List.map + (fun {ticket_token; total_amount; destinations} -> + { + ticket_token; + total_amount; + destinations = + List.sort + (fun (c1, _) (c2, _) -> Destination.compare c1 c2) + destinations; + }) + ticket_diffs + in + let+ strings = + List.map_es (string_of_ticket_operations_diff ctxt) ticket_diffs + in + List.sort String.compare strings + in + let* exp_str_diffs = sorted_strings expected in + let* str_diffs = + sorted_strings @@ List.map to_local_ticket_token_diff ticket_diffs + in + assert_equal_string_list + ~loc + "Equal ticket-token-diffs" + exp_str_diffs + str_diffs + +let string_token ~ticketer content = + let contents = + Result.value_f ~default:(fun _ -> assert false) + @@ Script_string.of_string content + in + Ticket_token.Ex_token + {ticketer; contents_type = Script_typed_ir.string_t; contents} + +(** Initializes one address for operations and one baker. *) +let init () = + let open Lwt_result_wrap_syntax in + let+ block, (src0, src1) = Context.init2 ~consensus_threshold:0 () in + let baker = Context.Contract.pkh src0 in + (baker, src1, block) + +let originate block ~script ~storage ~sender ~baker ~forges_tickets = + let open Lwt_result_wrap_syntax in + let code = Expr.toplevel_from_string script in + let storage = Expr.from_string storage in + let* operation, destination = + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + Op.contract_origination_hash + (B block) + sender + ~fee:(Test_tez.of_int 10) + ~script + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let* incr = + Incremental.add_operation + ?expect_apply_failure: + (if forges_tickets then Some (fun _ -> return_unit) else None) + incr + operation + in + let script = (code, storage) in + let+ block = Incremental.finalize_block incr in + (destination, script, block) + +let two_ticketers block = + let open Lwt_result_wrap_syntax in + let* result = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt result in + let*! cs = Contract.list ctxt in + match cs with c1 :: c2 :: _ -> return (c1, c2) | _ -> assert false + +let one_ticketer block = + let open Lwt_result_wrap_syntax in + let+ c1, _c2 = two_ticketers block in + c1 + +let nat n = Script_int.(abs @@ of_int n) + +let origination_operation block ~sender ~baker ~script ~storage ~forges_tickets + = + let open Lwt_result_wrap_syntax in + let* orig_contract, (code, storage), block = + originate block ~script ~storage ~sender ~baker ~forges_tickets + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let ctxt = Incremental.alpha_ctxt incr in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + let unparsed_storage = storage in + let*@ ( Script_ir_translator.Ex_script + (Script + { + storage_type; + storage; + code = _; + arg_type = _; + views = _; + entrypoints = _; + code_size = _; + }), + ctxt ) = + Script_ir_translator.parse_script + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~allow_forged_tickets_in_storage:true + ~allow_forged_lazy_storage_id_in_storage:true + script + in + let operation = + Script_typed_ir.Internal_operation + { + sender = Contract sender; + operation = + Origination + { + delegate = None; + code; + unparsed_storage; + credit = Tez.one; + preorigination = orig_contract; + storage_type; + storage; + }; + nonce = 1; + } + in + let incr = Incremental.set_alpha_ctxt incr ctxt in + return (Contract.Originated orig_contract, operation, incr) + +let delegation_operation ~sender = + Script_typed_ir.Internal_operation + {sender; operation = Delegation None; nonce = 1} + +let originate block ~sender ~baker ~script ~storage ~forges_tickets = + let open Lwt_result_wrap_syntax in + let* orig_contract, _script, block = + originate block ~script ~storage ~sender ~baker ~forges_tickets + in + let* incr = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + return (orig_contract, incr) + +let transfer_operation ~incr ~sender ~destination ~parameters_ty ~parameters = + let open Lwt_result_wrap_syntax in + let ctxt = Incremental.alpha_ctxt incr in + let*@ params_node, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Readable + parameters_ty + parameters + in + let incr = Incremental.set_alpha_ctxt incr ctxt in + return + ( Script_typed_ir.Internal_operation + { + sender; + operation = + Transaction_to_smart_contract + { + amount = Tez.zero; + unparsed_parameters = params_node; + entrypoint = Entrypoint.default; + destination; + location = Micheline.dummy_location; + parameters_ty; + parameters; + }; + nonce = 1; + }, + incr ) + +let ticket_diffs_of_operations incr operations = + Ticket_operations_diff.ticket_diffs_of_operations + (Incremental.alpha_ctxt incr) + operations + +let unit_script = + {| + { parameter unit; + storage unit; + code { CAR; NIL operation ; PAIR } } + |} + +let ticket_list_script = + {| + { parameter (list (ticket string)); + storage (list (ticket string)); + code { CAR; NIL operation ; PAIR } } + |} + +let ticket_big_map_script = + {| + { parameter (big_map int (ticket string)); + storage (big_map int (ticket string)); + code { CAR; NIL operation ; PAIR } } + |} + +let list_ticket_string_ty = + let open Result_syntax in + let* ticket_ty = ticket_t Micheline.dummy_location string_t in + list_t Micheline.dummy_location ticket_ty + +let make_ticket (ticketer, contents, amount) = + let open Lwt_result_syntax in + let*? contents = Script_string.of_string contents in + let amount = nat amount in + let*? amount = + Option.value_e + ~error: + (Environment.Error_monad.trace_of_error + Script_tc_errors.Forbidden_zero_ticket_quantity) + @@ Ticket_amount.of_n amount + in + return {ticketer; contents; amount} + +let make_tickets ts = + let open Lwt_result_wrap_syntax in + let* elements = List.map_es make_ticket ts in + return @@ Script_list.of_list elements + +let transfer_tickets_operation ~incr ~sender ~destination tickets = + let open Lwt_result_wrap_syntax in + let*?@ parameters_ty = list_ticket_string_ty in + let*@ parameters = make_tickets tickets in + transfer_operation ~incr ~sender ~destination ~parameters_ty ~parameters + +(** Test that no tickets are returned for operations that do not contain + tickets. *) +let test_non_ticket_operations () = + let open Lwt_result_wrap_syntax in + let* _baker, sender, block = init () in + let* incr = Incremental.begin_construction block in + let operations = [delegation_operation ~sender:(Contract sender)] in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr operations in + assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] + +(** Test transfer to a contract that does not take tickets. *) +let test_transfer_to_non_ticket_contract () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* orig_contract, incr = + originate + block + ~sender + ~baker + ~script:unit_script + ~storage:"Unit" + ~forges_tickets:false + in + let* operation, incr = + transfer_operation + ~incr + ~sender:(Contract sender) + ~destination:orig_contract + ~parameters_ty:unit_t + ~parameters:() + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] + +(** Test transfer an empty list of tickets. *) +let test_transfer_empty_ticket_list () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* orig_contract, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:orig_contract + [] + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] + +let one = Ticket_amount.one + +let two = Ticket_amount.add one one + +let three = Ticket_amount.add two one + +let five = Ticket_amount.add three two + +(** Test transfer a list of one ticket. *) +let test_transfer_one_ticket () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let* orig_contract, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:orig_contract + [(ticketer, "white", 1)] + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "white"; + total_amount = nat 1; + destinations = + [(Destination.Contract (Originated orig_contract), one)]; + }; + ] + +(** Test transferring a list of multiple tickets. This should work when + zero-tickets are disabled as well as when the parameters do not contain any + zero-amount tickets. *) +let test_transfer_multiple_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let* orig_contract, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:orig_contract + [ + (ticketer, "red", 1); + (ticketer, "blue", 2); + (ticketer, "green", 3); + (ticketer, "red", 4); + ] + in + let orig_contract = Contract.Originated orig_contract in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 5; + destinations = [(Destination.Contract orig_contract, five)]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 2; + destinations = [(Destination.Contract orig_contract, two)]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 3; + destinations = [(Destination.Contract orig_contract, three)]; + }; + ] + +(** Test transfer a list of tickets of different types. *) +let test_transfer_different_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer1, ticketer2 = two_ticketers block in + let* destination, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination + [ + (ticketer1, "red", 1); + (ticketer1, "green", 1); + (ticketer1, "blue", 1); + (ticketer2, "red", 1); + (ticketer2, "green", 1); + (ticketer2, "blue", 1); + (ticketer1, "red", 1); + (ticketer1, "green", 1); + (ticketer1, "blue", 1); + ] + in + let destination = Destination.Contract (Originated destination) in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer:ticketer1 "red"; + total_amount = nat 2; + destinations = [(destination, two)]; + }; + { + ticket_token = string_token ~ticketer:ticketer1 "green"; + total_amount = nat 2; + destinations = [(destination, two)]; + }; + { + ticket_token = string_token ~ticketer:ticketer1 "blue"; + total_amount = nat 2; + destinations = [(destination, two)]; + }; + { + ticket_token = string_token ~ticketer:ticketer2 "red"; + total_amount = nat 1; + destinations = [(destination, one)]; + }; + { + ticket_token = string_token ~ticketer:ticketer2 "green"; + total_amount = nat 1; + destinations = [(destination, one)]; + }; + { + ticket_token = string_token ~ticketer:ticketer2 "blue"; + total_amount = nat 1; + destinations = [(destination, one)]; + }; + ] + +(** Test transfer to two contracts with different types of tickets. *) +let test_transfer_to_two_contracts_with_different_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let parameters = + [(ticketer, "red", 1); (ticketer, "green", 1); (ticketer, "blue", 1)] + in + let* destination1, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation1, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:destination1 + parameters + in + let* block = Incremental.finalize_block incr in + let* destination2, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation2, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:destination2 + parameters + in + let*@ ticket_diffs, ctxt = + ticket_diffs_of_operations incr [operation1; operation2] + in + let one = Ticket_amount.one in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract (Originated destination2), one); + (Destination.Contract (Originated destination1), one); + ]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract (Originated destination2), one); + (Destination.Contract (Originated destination1), one); + ]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract (Originated destination2), one); + (Destination.Contract (Originated destination1), one); + ]; + }; + ] + +(** Test originate a contract that does not contain tickets. *) +let test_originate_non_ticket_contract () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* _orig_contract, operation, incr = + origination_operation + block + ~sender + ~baker + ~script:unit_script + ~storage:"Unit" + ~forges_tickets:false + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] + +(** Test originate a contract with an empty list of tickets. *) +let test_originate_with_empty_tickets_list () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let storage = "{}" in + let* _orig_contract, operation, incr = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:false + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs ctxt ~loc:__LOC__ ticket_diffs ~expected:[] + +(** Test originate a contract with a single ticket. *) +let test_originate_with_one_ticket () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let storage = + Printf.sprintf {|{Pair %S "white" 1}|} (Contract.to_b58check ticketer) + in + let* orig_contract, operation, ctxt = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations ctxt [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "white"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + ] + +(** Test originate a contract with multiple tickets. *) +let test_originate_with_multiple_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let storage = + let ticketer_addr = Contract.to_b58check ticketer in + Printf.sprintf + {|{ + Pair %S "red" 1; + Pair %S "blue" 2 ; + Pair %S "green" 3; + Pair %S "red" 4;} + |} + ticketer_addr + ticketer_addr + ticketer_addr + ticketer_addr + in + let* orig_contract, operation, ctxt = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations ctxt [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 5; + destinations = [(Destination.Contract orig_contract, five)]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 2; + destinations = [(Destination.Contract orig_contract, two)]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 3; + destinations = [(Destination.Contract orig_contract, three)]; + }; + ] + +(** Test originate a contract with multiple tickets of different types. *) +let test_originate_with_different_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer1, ticketer2 = two_ticketers block in + let storage = + let ticketer1_addr = Contract.to_b58check ticketer1 in + let ticketer2_addr = Contract.to_b58check ticketer2 in + Printf.sprintf + {|{ + Pair %S "red" 1; + Pair %S "green" 1; + Pair %S "blue" 1; + Pair %S "red" 1; + Pair %S "green" 1; + Pair %S "blue" 1 ; + Pair %S "red" 1; + Pair %S "green" 1; + Pair %S "blue" 1; } + |} + ticketer1_addr + ticketer1_addr + ticketer1_addr + ticketer2_addr + ticketer2_addr + ticketer2_addr + ticketer1_addr + ticketer1_addr + ticketer1_addr + in + let* orig_contract, operation, ctxt = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations ctxt [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer:ticketer1 "red"; + total_amount = nat 2; + destinations = [(Destination.Contract orig_contract, two)]; + }; + { + ticket_token = string_token ~ticketer:ticketer1 "green"; + total_amount = nat 2; + destinations = [(Destination.Contract orig_contract, two)]; + }; + { + ticket_token = string_token ~ticketer:ticketer1 "blue"; + total_amount = nat 2; + destinations = [(Destination.Contract orig_contract, two)]; + }; + { + ticket_token = string_token ~ticketer:ticketer2 "red"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + { + ticket_token = string_token ~ticketer:ticketer2 "green"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + { + ticket_token = string_token ~ticketer:ticketer2 "blue"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + ] + +(** Test originate two contracts with multiple tickets of different types. *) +let test_originate_two_contracts_with_different_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let storage = + let ticketer_addr = Contract.to_b58check ticketer in + Printf.sprintf + {|{Pair %S "red" 1; Pair %S "green" 1; Pair %S "blue" 1; }|} + ticketer_addr + ticketer_addr + ticketer_addr + in + let* orig_contract1, operation1, incr = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let* block = Incremental.finalize_block incr in + let* orig_contract2, operations2, incr = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let*@ ticket_diffs, ctxt = + ticket_diffs_of_operations incr [operation1; operations2] + in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract orig_contract2, one); + (Destination.Contract orig_contract1, one); + ]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract orig_contract2, one); + (Destination.Contract orig_contract1, one); + ]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract orig_contract2, one); + (Destination.Contract orig_contract1, one); + ]; + }; + ] + +(** Test originate and transfer tickets. *) +let test_originate_and_transfer () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let ticketer_addr = Contract.to_b58check ticketer in + let storage = + Printf.sprintf + {|{Pair %S "red" 1; Pair %S "green" 1; Pair %S "blue" 1; }|} + ticketer_addr + ticketer_addr + ticketer_addr + in + let* orig_contract1, operation1, incr = + origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + in + let* block = Incremental.finalize_block incr in + let* destination2, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + let* operation2, incr = + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:destination2 + [(ticketer, "red", 1); (ticketer, "green", 1); (ticketer, "blue", 1)] + in + let*@ ticket_diffs, ctxt = + ticket_diffs_of_operations incr [operation1; operation2] + in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract (Originated destination2), one); + (Destination.Contract orig_contract1, one); + ]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract (Originated destination2), one); + (Destination.Contract orig_contract1, one); + ]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 2; + destinations = + [ + (Destination.Contract (Originated destination2), one); + (Destination.Contract orig_contract1, one); + ]; + }; + ] + +(** Test originate a contract with a big-map with tickets inside. *) +let test_originate_big_map_with_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, ticketer, block = init () in + let* operation, originated = + Op.contract_origination_hash (B block) ticketer ~script:Op.dummy_script + in + let* block = Block.bake ~operation block in + let* incr = Incremental.begin_construction block in + let ticketer_addr = Contract.to_b58check ticketer in + let* big_map_id, ctxt = + new_int_key_big_map + (Incremental.alpha_ctxt incr) + originated + ~value_type:"ticket string" + [ + (1, Printf.sprintf {|Pair %S "red" 1|} ticketer_addr); + (2, Printf.sprintf {|Pair %S "green" 1|} ticketer_addr); + (3, Printf.sprintf {|Pair %S "blue" 1|} ticketer_addr); + ] + in + let incr = Incremental.set_alpha_ctxt incr ctxt in + let* block = Incremental.finalize_block incr in + let* orig_contract, operation, incr = + let storage = + Printf.sprintf "%d" @@ Z.to_int (Big_map.Id.unparse_to_z big_map_id) + in + origination_operation + block + ~sender:ticketer + ~baker + ~script:ticket_big_map_script + ~storage + ~forges_tickets:true + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer "red"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + { + ticket_token = string_token ~ticketer "green"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + { + ticket_token = string_token ~ticketer "blue"; + total_amount = nat 1; + destinations = [(Destination.Contract orig_contract, one)]; + }; + ] + +(** Test transfer a big-map with tickets. *) +let test_transfer_big_map_with_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, ticketer_contract, block = init () in + let* operation, originated = + Op.contract_origination_hash + (B block) + ticketer_contract + ~script:Op.dummy_script + in + let* block = Block.bake ~operation block in + let* incr = Incremental.begin_construction block in + let ticketer_addr = Contract.to_b58check ticketer_contract in + let* big_map_id, ctxt = + new_int_key_big_map + (Incremental.alpha_ctxt incr) + originated + ~value_type:"ticket string" + [ + (1, Printf.sprintf {|Pair %S "red" 1|} ticketer_addr); + (2, Printf.sprintf {|Pair %S "green" 1|} ticketer_addr); + (3, Printf.sprintf {|Pair %S "blue" 1|} ticketer_addr); + ] + in + let incr = Incremental.set_alpha_ctxt incr ctxt in + let* block = Incremental.finalize_block incr in + let* orig_contract, incr = + originate + block + ~sender:ticketer_contract + ~baker + ~script:ticket_big_map_script + ~storage:"{}" + ~forges_tickets:false + in + let open Lwt_result_syntax in + let*?@ value_type = ticket_t Micheline.dummy_location string_t in + let*?@ parameters_ty = big_map_t Micheline.dummy_location int_t value_type in + let parameters = + Big_map + { + id = Some big_map_id; + diff = {map = Big_map_overlay.empty; size = 0}; + key_type = int_t; + value_type; + } + in + let* operation, incr = + transfer_operation + ~incr + ~sender:(Contract ticketer_contract) + ~destination:orig_contract + ~parameters_ty + ~parameters + in + let*@ ticket_diffs, ctxt = ticket_diffs_of_operations incr [operation] in + let destination = Destination.Contract (Originated orig_contract) in + assert_equal_ticket_token_diffs + ctxt + ~loc:__LOC__ + ticket_diffs + ~expected: + [ + { + ticket_token = string_token ~ticketer:ticketer_contract "red"; + total_amount = nat 1; + destinations = [(destination, one)]; + }; + { + ticket_token = string_token ~ticketer:ticketer_contract "green"; + total_amount = nat 1; + destinations = [(destination, one)]; + }; + { + ticket_token = string_token ~ticketer:ticketer_contract "blue"; + total_amount = nat 1; + destinations = [(destination, one)]; + }; + ] + +(** Test transferring a list of multiple tickets where two of them have zero + amounts fails. *) +let test_transfer_fails_on_multiple_zero_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let* orig_contract, incr = + originate + block + ~sender + ~baker + ~script:ticket_list_script + ~storage:"{}" + ~forges_tickets:false + in + assert_fails + ~loc:__LOC__ + ~error:Script_tc_errors.Forbidden_zero_ticket_quantity + @@ (* let* operation, incr = *) + transfer_tickets_operation + ~incr + ~sender:(Contract sender) + ~destination:orig_contract + [ + (ticketer, "red", 1); + (ticketer, "blue", 0); + (ticketer, "green", 2); + (ticketer, "red", 0); + (ticketer, "green", 3); + ] + +(** Test that zero-amount tickets are detected and that an error is yielded. *) +let test_fail_on_zero_amount_tickets () = + let open Lwt_result_wrap_syntax in + let* baker, sender, block = init () in + let* ticketer = one_ticketer block in + let storage = + let ticketer_addr = Contract.to_b58check ticketer in + Printf.sprintf + {| + { Pair %S "red" 1; + Pair %S "blue" 2 ; + Pair %S "green" 3; + Pair %S "red" 0; + Pair %S "red" 4; } + |} + ticketer_addr + ticketer_addr + ticketer_addr + ticketer_addr + ticketer_addr + in + assert_fails + ~loc:__LOC__ + ~error:Script_tc_errors.Forbidden_zero_ticket_quantity + @@ origination_operation + block + ~sender + ~baker + ~script:ticket_list_script + ~storage + ~forges_tickets:true + +let tests = + [ + Tztest.tztest + "operations that do not involve tickets" + `Quick + test_non_ticket_operations; + Tztest.tztest + "transfer to non-ticket contract" + `Quick + test_transfer_to_non_ticket_contract; + Tztest.tztest + "transfer empty ticket list" + `Quick + test_transfer_empty_ticket_list; + Tztest.tztest "transfer one ticket" `Quick test_transfer_one_ticket; + Tztest.tztest + "transfer multiple tickets" + `Quick + test_transfer_multiple_tickets; + Tztest.tztest + "transfer different tickets" + `Quick + test_transfer_different_tickets; + Tztest.tztest + "transfer to two contracts with different tickets" + `Quick + test_transfer_to_two_contracts_with_different_tickets; + Tztest.tztest + "originate contract that does not contain tickets" + `Quick + test_originate_non_ticket_contract; + Tztest.tztest + "originate with empty ticket list" + `Quick + test_originate_with_empty_tickets_list; + Tztest.tztest + "originate with one ticket" + `Quick + test_originate_with_one_ticket; + Tztest.tztest + "originate with multiple tickets" + `Quick + test_originate_with_multiple_tickets; + Tztest.tztest + "originate with different tickets" + `Quick + test_originate_with_different_tickets; + Tztest.tztest + "originate two contracts with different tickets" + `Quick + test_originate_two_contracts_with_different_tickets; + Tztest.tztest "originate and transfer" `Quick test_originate_and_transfer; + Tztest.tztest + "originate big-map with tickets" + `Quick + test_originate_big_map_with_tickets; + Tztest.tztest + "transfer big-map with tickets" + `Quick + test_transfer_big_map_with_tickets; + Tztest.tztest + "transfer fails on multiple zero tickets" + `Quick + test_transfer_fails_on_multiple_zero_tickets; + Tztest.tztest + "fail in zero-amount tickets" + `Quick + test_fail_on_zero_amount_tickets; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket operations diff", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_scanner.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_scanner.ml new file mode 100644 index 000000000000..d2a3a37ee962 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_scanner.ml @@ -0,0 +1,707 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2024 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Ticket_scanner) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_scanner.ml + Subject: Ticket scanner tests +*) + +open Protocol +open Alpha_context + +let assert_fails ~loc ?error m = + let open Lwt_result_syntax in + let*! res = m in + let rec aux err_res = + match (err_res, error) with + | Environment.Ecoproto_error err' :: rest, Some err -> + if err = err' then return_unit else aux rest + | _, Some _ -> + (* Expected a different error. *) + let msg = + Printf.sprintf "Expected a different error at location %s" loc + in + Stdlib.failwith msg + | _, None -> + (* Any error is ok. *) + return_unit + in + match res with + | Ok _ -> Stdlib.failwith "Expected failure" + | Error err_res -> aux err_res + +let new_ctxt () = + let open Lwt_result_wrap_syntax in + let* block, _contract = Context.init1 () in + let* incr = Incremental.begin_construction block in + return @@ Incremental.alpha_ctxt incr + +let assert_equal_string_list ~loc msg = + Assert.assert_equal_list ~loc String.equal msg Format.pp_print_string + +let string_list_of_ex_tickets ctxt tickets = + let open Lwt_result_wrap_syntax in + let accum (xs, ctxt) + (Ticket_scanner.Ex_ticket + (cty, {Script_typed_ir.ticketer; contents; amount})) = + let*@ x, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Readable + cty + contents + in + let content = + Format.kasprintf Fun.id "%a" Michelson_v1_printer.print_expr x + in + let str = + Format.kasprintf + Fun.id + "(%a, %s, %a)" + Contract.pp + ticketer + content + Z.pp_print + Script_int.(to_zint (amount :> n num)) + in + return (str :: xs, ctxt) + in + let* xs, ctxt = List.fold_left_es accum ([], ctxt) tickets in + return (List.rev xs, ctxt) + +let make_ex_ticket ctxt ~ticketer ~type_exp ~content_exp ~amount = + let open Lwt_result_wrap_syntax in + let*?@ Script_ir_translator.Ex_comparable_ty cty, ctxt = + let node = Micheline.root @@ Expr.from_string type_exp in + Script_ir_translator.parse_comparable_ty ctxt node + in + let*?@ ticketer = Contract.of_b58check ticketer in + let*@ contents, ctxt = + let node = Micheline.root @@ Expr.from_string content_exp in + Script_ir_translator.parse_comparable_data ctxt cty node + in + let amount = Script_int.(abs @@ of_int amount) in + let amount = + WithExceptions.Option.get ~loc:__LOC__ @@ Ticket_amount.of_n amount + in + let ticket = Script_typed_ir.{ticketer; contents; amount} in + return (Ticket_scanner.Ex_ticket (cty, ticket), ctxt) + +let assert_equals_ex_tickets ctxt ~loc ex_tickets expected = + let open Lwt_result_wrap_syntax in + let* str_tickets, ctxt = string_list_of_ex_tickets ctxt ex_tickets in + let* str_tickets_expected, _ctxt = string_list_of_ex_tickets ctxt expected in + assert_equal_string_list + ~loc + "Compare with expected tickets" + (List.sort String.compare str_tickets) + (List.sort String.compare str_tickets_expected) + +let tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp = + let open Lwt_result_wrap_syntax in + let Script_typed_ir.Ex_ty ty, ctxt = + let node = Micheline.root @@ Expr.from_string type_exp in + Result.value_f + ~default:(fun () -> Stdlib.failwith "Failed to parse") + (Script_ir_translator.parse_any_ty ctxt ~legacy:false node) + in + let node = Micheline.root @@ Expr.from_string value_exp in + let*@ value, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:false ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + ty + node + in + let*?@ ht, ctxt = Ticket_scanner.type_has_tickets ctxt ty in + wrap @@ Ticket_scanner.tickets_of_value ctxt ~include_lazy ht value + +let assert_contains_tickets ctxt ~loc ~include_lazy ~type_exp ~value_exp + expected = + let open Lwt_result_wrap_syntax in + let* ex_tickets, _ = + tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp + in + assert_equals_ex_tickets ctxt ~loc ex_tickets expected + +let assert_fail_non_empty_overlay ctxt ~loc ~include_lazy ~type_exp ~value_exp = + let open Lwt_result_syntax in + let*! res = tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp in + match res with + | Error [x] -> + let x = Format.kasprintf Fun.id "%a" Error_monad.pp x in + Assert.equal + ~loc + String.equal + "" + Format.pp_print_string + "Unsupported big-map value with non-empty overlay" + x + | _ -> failwith "Expected an error at %s" loc + +let make_string_tickets ctxt ticketer_amounts = + let open Lwt_result_wrap_syntax in + List.fold_right_es + (fun (ticketer, content, amount) (tickets, ctxt) -> + let* ticket, ctxt = + make_ex_ticket + ctxt + ~ticketer + ~type_exp:"string" + ~content_exp:(Printf.sprintf {|"%s"|} content) + ~amount + in + return (ticket :: tickets, ctxt)) + ticketer_amounts + ([], ctxt) + +let tickets_from_big_map_ref ~pre_populated value_exp = + let open Lwt_result_wrap_syntax in + let* block, source = Context.init1 () in + let* operation, originated = + Op.contract_origination_hash (B block) source ~script:Op.dummy_script + in + let* block = Block.bake ~operation block in + let* inc = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt inc in + let*@ ctxt, big_map_id = Big_map.fresh ~temporary:false ctxt in + let int_ty_expr = Expr.from_string "int" in + let* diffs, ctxt = + let* updates, ctxt = + List.fold_left_es + (fun (kvs, ctxt) (key, value) -> + let*@ key_hash, ctxt = + Script_ir_translator.hash_comparable_data + ctxt + Script_typed_ir.int_t + (Script_int.of_int key) + in + return + ( { + Big_map.key = Expr.from_string @@ string_of_int key; + key_hash; + value = Some (Expr.from_string value); + } + :: kvs, + ctxt )) + ([], ctxt) + pre_populated + in + let alloc = + Big_map. + {key_type = int_ty_expr; value_type = Expr.from_string "ticket string"} + in + return + ( [ + Lazy_storage.make + Lazy_storage.Kind.Big_map + big_map_id + (Update {init = Lazy_storage.Alloc alloc; updates}); + ], + ctxt ) + in + let*@ ctxt = + Contract.update_script_storage ctxt originated int_ty_expr (Some diffs) + in + let value_exp = + value_exp @@ Z.to_string (Big_map.Id.unparse_to_z big_map_id) + in + return (value_exp, ctxt) + +let assert_big_map_int_ticket_string_ref ~loc ~pre_populated ~big_map_exp + ex_tickets = + let open Lwt_result_wrap_syntax in + let* value_exp, ctxt = tickets_from_big_map_ref ~pre_populated big_map_exp in + let* ex_tickets, ctxt = make_string_tickets ctxt ex_tickets in + assert_contains_tickets + ctxt + ~include_lazy:true + ~loc + ~type_exp:"big_map int (ticket string)" + ~value_exp + ex_tickets + +let assert_fail_non_empty_overlay_with_big_map_ref ~loc ~pre_populated + ~big_map_exp = + let open Lwt_result_wrap_syntax in + let* value_exp, ctxt = tickets_from_big_map_ref ~pre_populated big_map_exp in + assert_fail_non_empty_overlay + ctxt + ~include_lazy:true + ~loc + ~type_exp:"big_map int (ticket string)" + ~value_exp + +let assert_string_tickets ~loc ~include_lazy ~type_exp ~value_exp ~expected = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + let* ex_tickets, ctxt = make_string_tickets ctxt expected in + let* () = + assert_contains_tickets + ctxt + ~include_lazy + ~loc + ~type_exp + ~value_exp + ex_tickets + in + assert_contains_tickets + ctxt + ~include_lazy + ~loc + ~type_exp + ~value_exp + ex_tickets + +(** Test that the ticket can be extracted from a a single unit ticket *) +let test_tickets_in_unit_ticket () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + let type_exp = "ticket(unit)" in + let value_exp = + {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" unit Unit 10|} + in + let* ex_ticket, ctxt = + make_ex_ticket + ctxt + ~ticketer:"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" + ~type_exp:"unit" + ~content_exp:"Unit" + ~amount:10 + in + assert_contains_tickets + ctxt + ~loc:__LOC__ + ~include_lazy:false + ~type_exp + ~value_exp + [ex_ticket] + +let assert_string_tickets_fail_on_zero_amount ~loc ~include_lazy ~type_exp + ~value_exp = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + assert_fails ~loc ~error:Script_tc_errors.Forbidden_zero_ticket_quantity + @@ tickets_of_value ctxt ~include_lazy ~type_exp ~value_exp + +let test_tickets_in_list_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"list(ticket(string))" + ~value_exp: + {| + { + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 3; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "orange" 0; + } + |} + +(** Test that all tickets can be extracted from a list of tickets *) +let test_tickets_in_list () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"list(ticket(string))" + ~value_exp: + {| + { + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 3; + } + |} + ~expected: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 2); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", 3); + ] + +let test_tickets_in_pair_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"pair (ticket string) (ticket string) (ticket string)" + ~value_exp: + {| + Pair + (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1) + (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2) + (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 0) + |} + +(** Test that all tickets can be extracted from a pair of tickets *) +let test_tickets_in_pair () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"pair (ticket string) (ticket string)" + ~value_exp: + {| + Pair + (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1) + (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2) + |} + ~expected: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 2); + ] + +let test_tickets_in_map_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"map int (ticket string)" + ~value_exp: + {| + { + Elt 1 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1); + Elt 2 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2); + Elt 3 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 0); + } + |} + +(** Test that all tickets from a map can be extracted. *) +let test_tickets_in_map () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"map int (ticket string)" + ~value_exp: + {| + { + Elt 1 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1); + Elt 2 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2); + } + |} + ~expected: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 2); + ] + +(** Test that all tickets from a big-map with non-empty overlay fails. + If we extend the ticket scanner function to support non-empty overlays + this test needs to be adapted. + *) +let test_tickets_in_big_map () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + assert_fail_non_empty_overlay + ctxt + ~loc:__LOC__ + ~include_lazy:true + ~type_exp:"big_map int (ticket string)" + ~value_exp: + {| + { + Elt 1 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1); + Elt 2 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2); + } + |} + +(** Test that tickets are not extracted from big-map with [include_lazy] set + to false. *) +let test_tickets_in_big_map_strict_only () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"big_map int (ticket string)" + ~value_exp: + {| + { + Elt 1 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1); + Elt 2 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 2); + Elt 3 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 3); + } + |} + ~expected:[] + +(** Test that tickets can be extracted from a list of tickets inside a big-map + This fails due to non-empty overlay. If we extend the ticket scanner + function to support non-empty overlays this test needs to be adapted. +*) +let test_tickets_in_list_in_big_map () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_ctxt () in + assert_fail_non_empty_overlay + ctxt + ~loc:__LOC__ + ~include_lazy:true + ~type_exp:"(big_map int (list(ticket string)))" + ~value_exp: + {| + { + Elt 1 { + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 1 + }; + Elt 2 { + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 1; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "orange" 1 + } + } + |} + +(** Test that tickets can be extracted from a combination of a list and lazy structure + and that only the strict part is considered with [include_lazy] set to fasle *) +let test_tickets_in_pair_big_map_and_list_strict_only () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"pair (big_map int (ticket string)) (list (ticket string))" + ~value_exp: + {| + Pair + { + Elt 1 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1); + Elt 2 (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 1) + } + { + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 1; + Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "orange" 1 + } + |} + ~expected: + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", 1); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "orange", 1); + ] + +(** Test that tickets can be extracted from the left side of an or-expression. *) +let test_tickets_in_or_left () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"or (ticket string) int" + ~value_exp: + {| Left (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1) |} + ~expected:[("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1)] + +(** Test that tickets from the left side of an or-expression with zero amount + are rejected. *) +let test_tickets_in_or_left_with_zero_amount () = + assert_string_tickets_fail_on_zero_amount + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"or (ticket string) int" + ~value_exp: + {| Left (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 0) |} + +(** Test that tickets can be extracted from the right side of an or-expression. *) +let test_tickets_in_or_right () = + assert_string_tickets + ~loc:__LOC__ + ~include_lazy:false + ~type_exp:"or int (ticket string)" + ~value_exp: + {| Right (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1) |} + ~expected:[("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1)] + +(* + Big maps have three possible representations. Either as a list of key-value + pairs, as an identifier (int), or as a pair of identifier and overrides. + Example values: + + 1) { Elt "bar" True ; Elt "foo" False } + 2) 42 + 3) Pair 42 { Elt "foo" (Some False) } + *) + +(** Test tickets from empty big_map when passed by reference. *) +let test_tickets_in_empty_big_map_ref () = + assert_big_map_int_ticket_string_ref + ~loc:__LOC__ + ~pre_populated:[] + ~big_map_exp:(Printf.sprintf "%s") + [] + +(** Test tickets from non-empty big-map when passed by reference. + Here, tickets are scanned from the context. *) +let test_tickets_in_non_empty_big_map_ref () = + assert_big_map_int_ticket_string_ref + ~loc:__LOC__ + ~pre_populated: + [ + (1, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1|}); + (2, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 1|}); + (3, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 1|}); + ] + ~big_map_exp:(Printf.sprintf "%s") + [ + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "red", 1); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "green", 1); + ("KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq", "blue", 1); + ] + +(** Test tickets from empty big-map when passed as a pair of identifier + and overrides. Here, the scanned tickets are only contained in the overlay + why ticket-scanning fails. + + If we extend the ticket scanner function to support non-empty overlays + this test needs to be adapted. + *) +let test_tickets_overlay_in_empty_big_map_ref () = + assert_fail_non_empty_overlay_with_big_map_ref + ~loc:__LOC__ + ~pre_populated:[] + ~big_map_exp: + (Printf.sprintf + {|Pair %s { Elt 1 (Some (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1))}|}) + +(** Test tickets from non-empty big-map when passed as a pair of identifier + and overrides. The scanned tickets are contained in the context as well as + in the overlay. Since overlay is non-empty is non-empty, ticket scanning + fails. + + If we extend the ticket scanner function to support non-empty overlays + this test needs to be adapted + *) +let test_tickets_overlay_in_non_empty_in_big_map_ref () = + assert_fail_non_empty_overlay_with_big_map_ref + ~loc:__LOC__ + ~pre_populated: + [ + (1, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1|}); + (2, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 1|}); + (3, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "blue" 1|}); + ] + ~big_map_exp: + (Printf.sprintf + {| Pair + %s + { Elt 4 (Some (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "orange" 1))} + |}) + +(** Test tickets from non-empty big-map when passed as a pair of identifier + and overrides, and where the override replaces an existing ticket. + Ticket scanning fails due to non-empty overlay. + + If we extend the ticket scanner function to support non-empty overlays + this test needs to be adapted. + *) +let test_tickets_replace_overlay_in_non_empty_in_big_map_ref () = + assert_fail_non_empty_overlay_with_big_map_ref + ~loc:__LOC__ + ~pre_populated: + [(1, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1|})] + ~big_map_exp: + (Printf.sprintf + {| Pair + %s + { Elt 1 (Some (Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "green" 1))} + |}) + +(** Test tickets from non-empty big-map when passed as a pair of identifier + and overrides, and where the override removes an existing ticket. + Ticket scanning fails due to non-empty overlay. + + If we extend the ticket scanner function to support non-empty overlays + this test needs to be adapted. + *) +let test_tickets_remove_overlay_in_non_empty_in_big_map_ref () = + assert_fail_non_empty_overlay_with_big_map_ref + ~loc:__LOC__ + ~pre_populated: + [(1, {|Ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" string "red" 1|})] + ~big_map_exp:(Printf.sprintf {| Pair %s { Elt 1 None} |}) + +let tests = + [ + Tztest.tztest "tickets in unit ticket" `Quick test_tickets_in_unit_ticket; + Tztest.tztest "tickets in list" `Quick test_tickets_in_list; + Tztest.tztest + "tickets in list with zero amount" + `Quick + test_tickets_in_list_with_zero_amount; + Tztest.tztest "tickets in pair" `Quick test_tickets_in_pair; + Tztest.tztest + "tickets in pair with zero amount" + `Quick + test_tickets_in_pair_with_zero_amount; + Tztest.tztest "tickets in map" `Quick test_tickets_in_map; + Tztest.tztest + "tickets in map with zero amount" + `Quick + test_tickets_in_map_with_zero_amount; + Tztest.tztest "tickets in big map" `Quick test_tickets_in_big_map; + Tztest.tztest + "tickets in big map with include lazy set to false" + `Quick + test_tickets_in_big_map_strict_only; + Tztest.tztest + "tickets in list in big map" + `Quick + test_tickets_in_list_in_big_map; + Tztest.tztest + "tickets in a pair of big-map and list with include lazy set to false" + `Quick + test_tickets_in_pair_big_map_and_list_strict_only; + Tztest.tztest "tickets in or left" `Quick test_tickets_in_or_left; + Tztest.tztest + "tickets in or left with zero amount" + `Quick + test_tickets_in_or_left_with_zero_amount; + Tztest.tztest "tickets in or right" `Quick test_tickets_in_or_right; + Tztest.tztest + "tickets in empty big-map ref" + `Quick + test_tickets_overlay_in_empty_big_map_ref; + Tztest.tztest + "tickets in big-map ref" + `Quick + test_tickets_in_empty_big_map_ref; + Tztest.tztest + "tickets in non-empty big-map ref" + `Quick + test_tickets_in_non_empty_big_map_ref; + Tztest.tztest + "tickets in non-empty big-map ref with overlay" + `Quick + test_tickets_overlay_in_non_empty_in_big_map_ref; + Tztest.tztest + "tickets replace existing value from overlay" + `Quick + test_tickets_replace_overlay_in_non_empty_in_big_map_ref; + Tztest.tztest + "tickets remove existing value from overlay" + `Quick + test_tickets_remove_overlay_in_non_empty_in_big_map_ref; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket scanner", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_storage.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_storage.ml new file mode 100644 index 000000000000..f0606352173d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_ticket_storage.ml @@ -0,0 +1,280 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Alpha_context.Ticket_balance) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_ticket_storage.ml + Subject: Ticket storage functions tested using the Ticket_balance module in Alpha_context. +*) + +open Protocol +open Alpha_context + +let make_context () = + let open Lwt_result_wrap_syntax in + let* block, _contract = Context.init1 () in + let* incr = Incremental.begin_construction block in + return (Incremental.alpha_ctxt incr) + +let hash_key ctxt ~ticketer ~ty ~contents ~owner = + let ticketer = Micheline.root @@ Expr.from_string ticketer in + let ty = Micheline.root @@ Expr.from_string ty in + let contents = Micheline.root @@ Expr.from_string contents in + let owner = Micheline.root @@ Expr.from_string owner in + Alpha_context.Ticket_hash.make ctxt ~ticketer ~ty ~contents ~owner + +let assert_balance ctxt ~loc key expected = + let open Lwt_result_wrap_syntax in + let*@ balance, _ = Ticket_balance.get_balance ctxt key in + match balance with + | Some b -> Assert.equal_int ~loc (Z.to_int b) expected + | None -> failwith "Expected balance %d" expected + +let assert_no_balance ctxt key = + let open Lwt_result_wrap_syntax in + let*@ balance, _ = Ticket_balance.get_balance ctxt key in + match balance with + | Some b -> failwith "Expected empty (none) balance but got %d" (Z.to_int b) + | None -> return_unit + +let adjust_balance ctxt key delta = + Ticket_balance.adjust_balance ctxt key ~delta:(Z.of_int delta) + +let assert_non_overlapping_keys ~loc ~ticketer1 ~ticketer2 ~contents1 ~contents2 + ~ty1 ~ty2 ~owner1 ~owner2 = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ k1, ctxt = + hash_key ctxt ~ticketer:ticketer1 ~ty:ty1 ~contents:contents1 ~owner:owner1 + in + let*?@ k2, _ctxt = + hash_key ctxt ~ticketer:ticketer2 ~ty:ty2 ~contents:contents2 ~owner:owner2 + in + Assert.not_equal + ~loc + Ticket_hash.equal + "Keys should not overlap" + Ticket_hash.pp + k1 + k2 + +let make_key ctxt content = + hash_key + ctxt + ~ticketer:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ty:"string" + ~contents:(Printf.sprintf {|"%s"|} content) + ~owner:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + +(** Test that key-hashes constructed from different ticketers don't overlap. *) +let test_non_overlapping_keys_ticketer () = + assert_non_overlapping_keys + ~loc:__LOC__ + ~ticketer1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ticketer2:{|"KT1PWx2mnDueood7fEmfbBDKx1D9BAnnXitn"|} + ~ty1:"nat" + ~ty2:"int" + ~contents1:{|"1"|} + ~contents2:{|"1"|} + ~owner1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~owner2:{|"KT1PWx2mnDueood7fEmfbBDKx1D9BAnnXitn"|} + +(** Test that key-hashes constructed from different contents don't overlap. *) +let test_non_overlapping_keys_contents () = + assert_non_overlapping_keys + ~loc:__LOC__ + ~ticketer1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ticketer2:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ty1:"string" + ~ty2:"string" + ~contents1:{|"red"|} + ~contents2:{|"blue"|} + ~owner1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~owner2:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + +(** Test that key-hashes constructed from different content-types don't overlap. *) +let test_non_overlapping_keys_type () = + assert_non_overlapping_keys + ~loc:__LOC__ + ~ticketer1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ticketer2:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ty1:"nat" + ~ty2:"int" + ~contents1:{|"1"|} + ~contents2:{|"1"|} + ~owner1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~owner2:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + +(** Test that key-hashes constructed from different owners don't overlap. *) +let test_non_overlapping_keys_owner () = + assert_non_overlapping_keys + ~loc:__LOC__ + ~ticketer1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ticketer2:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~ty1:"nat" + ~ty2:"int" + ~contents1:{|"1"|} + ~contents2:{|"1"|} + ~owner1:{|"KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq"|} + ~owner2:{|"KT1PWx2mnDueood7fEmfbBDKx1D9BAnnXitn"|} + +(** Test that updating the ticket balance table has + the intended effect. + *) +let test_ticket_balance_single_update () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + let*@ _, ctxt = adjust_balance ctxt alice_red 1 in + assert_balance ctxt ~loc:__LOC__ alice_red 1 + +(** Test that updating the ticket-balance table with different keys + updates both entries. *) +let test_ticket_balance_different_owners () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + let*?@ alice_blue, ctxt = make_key ctxt "alice_blue" in + let*@ _, ctxt = adjust_balance ctxt alice_red 1 in + let*@ _, ctxt = adjust_balance ctxt alice_blue 1 in + let* () = assert_balance ctxt ~loc:__LOC__ alice_red 1 in + let* () = assert_balance ctxt ~loc:__LOC__ alice_blue 1 in + return_unit + +(** Test updating the same entry with multiple updates yields + the net result of all balance updates *) +let test_ticket_balance_multiple_updates () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + let*@ _, ctxt = adjust_balance ctxt alice_red 1 in + let*@ _, ctxt = adjust_balance ctxt alice_red 2 in + let*@ _, ctxt = adjust_balance ctxt alice_red (-1) in + assert_balance ctxt ~loc:__LOC__ alice_red 2 + +(** Test that with no updates to the table, no balance is present in + the table *) +let test_empty_balance () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + assert_no_balance ctxt alice_red + +(** Test that adding one entry with positive balance and then + updating with a negative balance also removes the entry *) +let test_empty_balance_after_update () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + let*@ _, ctxt = adjust_balance ctxt alice_red 1 in + let*@ _, ctxt = adjust_balance ctxt alice_red (-1) in + assert_no_balance ctxt alice_red + +(** Test that attempting to update an entry with a negative balance + results in an error. *) +let test_negative_balance () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + let*!@ res = adjust_balance ctxt alice_red (-1) in + Assert.proto_error ~loc:__LOC__ res (fun _err -> true) + +(** Test that positive storage spaces are returned for operations + resulting in extra storage space and negative for ones that frees up storage. + *) +let test_storage_space () = + let open Lwt_result_wrap_syntax in + let* ctxt = make_context () in + let*?@ alice_red, ctxt = make_key ctxt "alice_red" in + (* Space for adding an entry is 65 for the key plus 1 for the value. *) + let*@ space, ctxt = adjust_balance ctxt alice_red 1 in + let* () = Assert.equal_int ~loc:__LOC__ 66 (Z.to_int space) in + (* Adding one does not consume additional space. *) + let*@ space, ctxt = adjust_balance ctxt alice_red 1 in + let* () = Assert.equal_int ~loc:__LOC__ 0 (Z.to_int space) in + (* Adding a big balance costs extra. *) + let*@ space, ctxt = adjust_balance ctxt alice_red 1000 in + let* () = Assert.equal_int ~loc:__LOC__ 1 (Z.to_int space) in + (* Reset balance to zero should free up space. + The freed up space is 65 for the key + 2 for the value *) + let*@ b, ctxt = Ticket_balance.get_balance ctxt alice_red in + let*@ space, ctxt = + Ticket_balance.adjust_balance + ctxt + alice_red + ~delta:(Z.neg @@ Option.value ~default:Z.zero b) + in + let* () = Assert.equal_int ~loc:__LOC__ (-67) (Z.to_int space) in + (* Adjusting the space to 0 again should not free anything *) + let*@ space, ctxt = adjust_balance ctxt alice_red 0 in + let* () = Assert.equal_int ~loc:__LOC__ 0 (Z.to_int space) in + (* Adding a balance requiers extra space. *) + let*@ space, _ = adjust_balance ctxt alice_red 10 in + Assert.equal_int ~loc:__LOC__ 66 (Z.to_int space) + +let tests = + [ + Tztest.tztest + "no overlapping keys for ticketer" + `Quick + test_non_overlapping_keys_ticketer; + Tztest.tztest + "no overlapping keys for content" + `Quick + test_non_overlapping_keys_contents; + Tztest.tztest + "no overlapping keys for content type" + `Quick + test_non_overlapping_keys_type; + Tztest.tztest + "no overlapping keys for owner" + `Quick + test_non_overlapping_keys_owner; + Tztest.tztest + "ticket balance single update" + `Quick + test_ticket_balance_single_update; + Tztest.tztest "empty balance" `Quick test_empty_balance; + Tztest.tztest + "empty balance after update" + `Quick + test_empty_balance_after_update; + Tztest.tztest "negative balance" `Quick test_negative_balance; + Tztest.tztest + "ticket balance multiple updates" + `Quick + test_ticket_balance_multiple_updates; + Tztest.tztest + "ticket balance different owners" + `Quick + test_ticket_balance_different_owners; + Tztest.tztest "ticket storage space" `Quick test_storage_space; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("ticket storage", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_typechecking.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_typechecking.ml new file mode 100644 index 000000000000..a31e072f08bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/test_typechecking.ml @@ -0,0 +1,1019 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (type-checking) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/michelson/main.exe \ + -- --file test_typechecking.ml + Subject: Type-checking +*) + +open Protocol +open Alpha_context +open Micheline + +let context_init_with_sc_rollup_arith_enabled tup = + Context.init_with_constants_gen + tup + { + Context.default_test_constants with + consensus_threshold = 0; + sc_rollup = + {Context.default_test_constants.sc_rollup with arith_pvm_enable = true}; + } + +let sc_originate block contract parameters_ty = + let open Lwt_result_syntax in + let kind = Sc_rollup.Kind.Example_arith in + let* operation, rollup = + Sc_rollup_helpers.origination_op ~parameters_ty (B block) contract kind + in + let* incr = Incremental.begin_construction block in + let* incr = Incremental.add_operation incr operation in + let* block = Incremental.finalize_block incr in + return (block, rollup) + +(* Test for Script_ir_translator.parse_and_unparse_script_unaccounted on a + script declaring views. *) +let test_unparse_view () = + let open Lwt_result_wrap_syntax in + let dummy_contract = + "{parameter unit; storage unit; code { CAR; NIL operation; PAIR }; view \ + \"v0\" unit unit { DROP; UNIT }; view \"v1\" nat nat {CAR}}" + in + let contract_expr = Expr.from_string dummy_contract in + let storage_expr = Expr.from_string "Unit" in + let bef = Script.lazy_expr contract_expr |> Data_encoding.force_bytes in + let script = + Script.{code = lazy_expr contract_expr; storage = lazy_expr storage_expr} + in + let* b, _cs = Context.init3 () in + let* v = Incremental.begin_construction b in + let ctx = Incremental.alpha_ctxt v in + let*@ unparsed_script, _ctx = + Script_ir_translator.parse_and_unparse_script_unaccounted + ctx + ~legacy:true + ~allow_forged_tickets_in_storage:false + ~allow_forged_lazy_storage_id_in_storage:false + Readable + ~normalize_types:true + script + in + let aft = Data_encoding.force_bytes unparsed_script.code in + Alcotest.(check bytes) "didn't match" bef aft |> return + +let test_context () = + let open Lwt_result_syntax in + let* b, _cs = Context.init3 ~consensus_threshold:0 () in + let* v = Incremental.begin_construction b in + return (Incremental.alpha_ctxt v) + +let test_context_with_nat_nat_big_map () = + let open Lwt_result_wrap_syntax in + let* b, source = Context.init1 () in + let* operation, originated = + Op.contract_origination_hash (B b) source ~script:Op.dummy_script + in + let* b = Block.bake ~operation b in + let* v = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt v in + let*@ ctxt, id = Big_map.fresh ~temporary:false ctxt in + let nat_ty = Script_typed_ir.nat_t in + let*?@ nat_ty_node, ctxt = + Script_ir_unparser.unparse_ty ctxt ~loc:() nat_ty + in + let nat_ty_expr = Micheline.strip_locations nat_ty_node in + let alloc = Big_map.{key_type = nat_ty_expr; value_type = nat_ty_expr} in + let init = Lazy_storage.Alloc alloc in + let diffs = + [ + Lazy_storage.make + Lazy_storage.Kind.Big_map + id + (Update {init; updates = []}); + ] + in + let*@ ctxt = + Contract.update_script_storage ctxt originated nat_ty_expr (Some diffs) + in + return (ctxt, id) + +let read_file filename = + let ch = open_in filename in + let s = really_input_string ch (in_channel_length ch) in + close_in ch ; + s + +let path = project_root // Filename.dirname __FILE__ + +(** Check that the custom stack overflow exception is triggered when + it should be. *) +let test_typecheck_stack_overflow () = + let open Lwt_result_syntax in + let* ctxt = test_context () in + let storage = "Unit" in + let parameter = "Unit" in + let script = read_file (path // "contracts/big_interpreter_stack.tz") in + let*! result = + Contract_helpers.run_script ctxt script ~storage ~parameter () + in + match result with + | Ok _ -> Alcotest.fail "expected an error" + | Error lst + when List.mem + ~equal:( = ) + (Environment.Ecoproto_error + Script_tc_errors.Typechecking_too_many_recursive_calls) + lst -> + return_unit + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace errs + +(* NOTE: this test fails with an out-of-memory exception. *) +let _test_unparse_stack_overflow () = + let open Lwt_result_syntax in + let* ctxt = test_context () in + (* Meme *) + let enorme_et_seq n = + let rec aux n acc = aux (n - 1) @@ Micheline.Seq (0, [acc]) in + aux n (Micheline.Int (0, Z.zero)) + in + let*! result = + Script_ir_translator.(unparse_code ctxt Readable (enorme_et_seq 10_001)) + in + match result with + | Ok _ -> Alcotest.fail "expected an error" + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect_id = "michelson_v1.unparsing_stack_overflow" in + let expect_descrfiption = + "Too many recursive calls were needed for unparsing" + in + if + Astring.String.is_infix ~affix:expect_id trace_string + && Astring.String.is_infix ~affix:expect_descrfiption trace_string + then return_unit + else + Alcotest.failf + "Unexpected error (%s) at %s" + trace_string + __LOC__ + return_unit + +let location = function + | Prim (loc, _, _, _) + | Int (loc, _) + | String (loc, _) + | Bytes (loc, _) + | Seq (loc, _) -> + loc + +let test_parse_ty (type exp expc) ctxt node + (expected : (exp, expc) Script_typed_ir.ty) = + let open Result_wrap_syntax in + let legacy = false in + let allow_lazy_storage = true in + let allow_operation = true in + let allow_contract = true in + let allow_ticket = true in + let@ result = + let* Script_typed_ir.Ex_ty actual, ctxt = + Script_ir_translator.parse_ty + ctxt + ~legacy + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + node + in + let* eq, ctxt = + Gas_monad.run ctxt + @@ Script_ir_translator.ty_eq + ~error_details:(Informative (location node)) + actual + expected + in + let+ Eq = eq in + ctxt + in + result + +let test_parse_comb_type () = + let open Lwt_result_wrap_syntax in + let open Script in + let open Script_typed_ir in + let nat_prim = Prim (-1, T_nat, [], []) in + let nat_prim_a = Prim (-1, T_nat, [], ["%a"]) in + let nat_prim_b = Prim (-1, T_nat, [], ["%b"]) in + let nat_prim_c = Prim (-1, T_nat, [], ["%c"]) in + let nat_ty = nat_t in + let pair_prim l = Prim (-1, T_pair, l, []) in + let pair_ty ty1 ty2 = pair_t (-1) ty1 ty2 in + let pair_prim2 a b = pair_prim [a; b] in + let pair_nat_nat_prim = pair_prim2 nat_prim nat_prim in + let*?@ (Ty_ex_c pair_nat_nat_ty) = pair_ty nat_ty nat_ty in + let* ctxt = test_context () in + (* pair nat nat *) + let*? ctxt = test_parse_ty ctxt pair_nat_nat_prim pair_nat_nat_ty in + (* pair (pair nat nat) nat *) + let*?@ (Ty_ex_c pair_pair_nat_nat_nat_ty) = pair_ty pair_nat_nat_ty nat_ty in + let*? ctxt = + test_parse_ty + ctxt + (pair_prim2 pair_nat_nat_prim nat_prim) + pair_pair_nat_nat_nat_ty + in + (* pair nat (pair nat nat) *) + let*?@ (Ty_ex_c pair_nat_pair_nat_nat_ty) = pair_ty nat_ty pair_nat_nat_ty in + let*? ctxt = + test_parse_ty + ctxt + (pair_prim2 nat_prim pair_nat_nat_prim) + pair_nat_pair_nat_nat_ty + in + (* pair nat nat nat *) + let*?@ (Ty_ex_c pair_nat_nat_nat_ty) = pair_ty nat_ty pair_nat_nat_ty in + let*? ctxt = + test_parse_ty + ctxt + (pair_prim [nat_prim; nat_prim; nat_prim]) + pair_nat_nat_nat_ty + in + (* pair (nat %a) nat *) + let*?@ (Ty_ex_c pair_nat_a_nat_ty) = pair_t (-1) nat_ty nat_ty in + let*? ctxt = + test_parse_ty ctxt (pair_prim2 nat_prim_a nat_prim) pair_nat_a_nat_ty + in + (* pair nat (nat %b) *) + let*?@ (Ty_ex_c pair_nat_nat_b_ty) = pair_t (-1) nat_ty nat_ty in + let*? ctxt = + test_parse_ty ctxt (pair_prim2 nat_prim nat_prim_b) pair_nat_nat_b_ty + in + (* pair (nat %a) (nat %b) *) + let*?@ (Ty_ex_c pair_nat_a_nat_b_ty) = pair_t (-1) nat_ty nat_ty in + let*? ctxt = + test_parse_ty ctxt (pair_prim2 nat_prim_a nat_prim_b) pair_nat_a_nat_b_ty + in + (* pair (nat %a) (nat %b) (nat %c) *) + let*?@ (Ty_ex_c pair_nat_b_nat_c_ty) = pair_t (-1) nat_ty nat_ty in + let*?@ (Ty_ex_c pair_nat_a_nat_b_nat_c_ty) = + pair_t (-1) nat_ty pair_nat_b_nat_c_ty + in + let*? ctxt = + test_parse_ty + ctxt + (pair_prim [nat_prim_a; nat_prim_b; nat_prim_c]) + pair_nat_a_nat_b_nat_c_ty + in + (* pair (nat %a) (pair %b nat nat) *) + let*?@ (Ty_ex_c pair_b_nat_nat_ty) = pair_t (-1) nat_ty nat_ty in + let*?@ (Ty_ex_c pair_nat_a_pair_b_nat_nat_ty) = + pair_t (-1) nat_ty pair_b_nat_nat_ty + in + let*? (_ : context) = + test_parse_ty + ctxt + (pair_prim2 nat_prim_a (Prim (-1, T_pair, [nat_prim; nat_prim], ["%b"]))) + pair_nat_a_pair_b_nat_nat_ty + in + return_unit + +let test_unparse_ty loc ctxt expected ty = + let open Result_syntax in + let* actual, ctxt = Script_ir_unparser.unparse_ty ctxt ~loc:() ty in + if actual = expected then Ok ctxt + else Alcotest.failf "Unexpected error: %s" loc + +let test_unparse_comb_type () = + let open Lwt_result_wrap_syntax in + let open Script in + let open Script_typed_ir in + let nat_prim = Prim ((), T_nat, [], []) in + let nat_ty = nat_t in + let pair_prim l = Prim ((), T_pair, l, []) in + let pair_ty ty1 ty2 = pair_t (-1) ty1 ty2 in + let pair_prim2 a b = pair_prim [a; b] in + let pair_nat_nat_prim = pair_prim2 nat_prim nat_prim in + let*?@ (Ty_ex_c pair_nat_nat_ty) = pair_ty nat_ty nat_ty in + let* ctxt = test_context () in + (* pair nat nat *) + let*?@ ctxt = + test_unparse_ty __LOC__ ctxt pair_nat_nat_prim pair_nat_nat_ty + in + (* pair (pair nat nat) nat *) + let*?@ (Ty_ex_c pair_pair_nat_nat_nat_ty) = pair_ty pair_nat_nat_ty nat_ty in + let*?@ ctxt = + test_unparse_ty + __LOC__ + ctxt + (pair_prim2 pair_nat_nat_prim nat_prim) + pair_pair_nat_nat_nat_ty + in + (* pair nat nat nat *) + let*?@ (Ty_ex_c pair_nat_nat_nat_ty) = pair_ty nat_ty pair_nat_nat_ty in + let*?@ (_ : context) = + test_unparse_ty + __LOC__ + ctxt + (pair_prim [nat_prim; nat_prim; nat_prim]) + pair_nat_nat_nat_ty + in + return_unit + +let test_unparse_comparable_ty loc ctxt expected ty = + (* unparse_comparable_ty is not exported, the simplest way to call it is to + call parse_ty on a set type *) + let open Result_syntax in + let open Script_typed_ir in + let* set_ty_ty = set_t (-1) ty in + let* actual, ctxt = Script_ir_unparser.unparse_ty ctxt ~loc:() set_ty_ty in + if actual = Prim ((), T_set, [expected], []) then return ctxt + else Alcotest.failf "Unexpected error: %s" loc + +let test_unparse_comb_comparable_type () = + let open Lwt_result_wrap_syntax in + let open Script in + let open Script_typed_ir in + let nat_prim = Prim ((), T_nat, [], []) in + let nat_ty = nat_t in + let pair_prim l = Prim ((), T_pair, l, []) in + let pair_ty ty1 ty2 = comparable_pair_t (-1) ty1 ty2 in + let pair_prim2 a b = pair_prim [a; b] in + let pair_nat_nat_prim = pair_prim2 nat_prim nat_prim in + let*?@ pair_nat_nat_ty = pair_ty nat_ty nat_ty in + let* ctxt = test_context () in + (* pair nat nat *) + let*?@ ctxt = + test_unparse_comparable_ty __LOC__ ctxt pair_nat_nat_prim pair_nat_nat_ty + in + (* pair (pair nat nat) nat *) + let*?@ pair_pair_nat_nat_nat_ty = pair_ty pair_nat_nat_ty nat_ty in + let*?@ ctxt = + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim2 pair_nat_nat_prim nat_prim) + pair_pair_nat_nat_nat_ty + in + (* pair nat nat nat *) + let*?@ pair_nat_nat_nat_ty = pair_ty nat_ty pair_nat_nat_ty in + let*?@ (_ : context) = + test_unparse_comparable_ty + __LOC__ + ctxt + (pair_prim [nat_prim; nat_prim; nat_prim]) + pair_nat_nat_nat_ty + in + return_unit + +let test_parse_data ?(equal = Stdlib.( = )) loc ctxt ty node expected = + let open Lwt_result_wrap_syntax in + let elab_conf = Script_ir_translator_config.make ~legacy:false () in + let allow_forged_tickets = true in + let allow_forged_lazy_storage_id = true in + let*@ actual, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + ty + node + in + if equal actual expected then return ctxt + else Alcotest.failf "Unexpected error: %s" loc + +let test_parse_data_fails loc ctxt ty node = + let open Lwt_result_wrap_syntax in + let elab_conf = Script_ir_translator_config.make ~legacy:false () in + let allow_forged_tickets = false in + let allow_forged_lazy_storage_id = false in + let*! result = + Script_ir_translator.parse_data + ctxt + ~elab_conf + ~allow_forged_tickets + ~allow_forged_lazy_storage_id + ty + node + in + match result with + | Ok _ -> Alcotest.failf "Unexpected typechecking success: %s" loc + | Error trace -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect_id = "michelson_v1.invalid_constant" in + let expect_descrfiption = + "A data expression was invalid for its expected type." + in + if + Astring.String.is_infix ~affix:expect_id trace_string + && Astring.String.is_infix ~affix:expect_descrfiption trace_string + then return_unit + else + Alcotest.failf + "Unexpected error (%s) at %s" + trace_string + __LOC__ + return_unit + +let test_parse_comb_data () = + let open Lwt_result_wrap_syntax in + let open Script in + let open Script_typed_ir in + let z = Script_int.zero_n in + let z_prim = Micheline.Int (-1, Z.zero) in + let nat_ty = nat_t in + let pair_prim l = Prim (-1, D_Pair, l, []) in + let pair_ty ty1 ty2 = pair_t (-1) ty1 ty2 in + let*?@ (Ty_ex_c pair_nat_nat_ty) = pair_ty nat_ty nat_ty in + let pair_prim2 a b = pair_prim [a; b] in + let pair_z_z_prim = pair_prim2 z_prim z_prim in + let*?@ list_nat_ty = list_t (-1) nat_ty in + let*?@ big_map_nat_nat_ty = big_map_t (-1) nat_ty nat_ty in + let* ctxt, big_map_id = test_context_with_nat_nat_big_map () in + (* Pair 0 0 *) + let* ctxt = + test_parse_data __LOC__ ctxt pair_nat_nat_ty pair_z_z_prim (z, z) + in + (* {0; 0} *) + let* ctxt = + test_parse_data + __LOC__ + ctxt + pair_nat_nat_ty + (Micheline.Seq (-1, [z_prim; z_prim])) + (z, z) + in + (* Pair (Pair 0 0) 0 *) + let*?@ (Ty_ex_c pair_pair_nat_nat_nat_ty) = pair_ty pair_nat_nat_ty nat_ty in + let* ctxt = + test_parse_data + __LOC__ + ctxt + pair_pair_nat_nat_nat_ty + (pair_prim2 pair_z_z_prim z_prim) + ((z, z), z) + in + (* Pair 0 (Pair 0 0) *) + let*?@ (Ty_ex_c pair_nat_pair_nat_nat_ty) = pair_ty nat_ty pair_nat_nat_ty in + let* ctxt = + test_parse_data + __LOC__ + ctxt + pair_nat_pair_nat_nat_ty + (pair_prim2 z_prim pair_z_z_prim) + (z, (z, z)) + in + (* Pair 0 0 0 *) + let* ctxt = + test_parse_data + __LOC__ + ctxt + pair_nat_pair_nat_nat_ty + (pair_prim [z_prim; z_prim; z_prim]) + (z, (z, z)) + in + (* {0; 0; 0} *) + let* ctxt = + test_parse_data + __LOC__ + ctxt + pair_nat_pair_nat_nat_ty + (Micheline.Seq (-1, [z_prim; z_prim; z_prim])) + (z, (z, z)) + in + (* Should fail: {0} against pair nat (list nat) *) + let*?@ (Ty_ex_c pair_nat_list_nat_ty) = pair_ty nat_ty list_nat_ty in + let* () = + test_parse_data_fails + __LOC__ + ctxt + pair_nat_list_nat_ty + (Micheline.Seq (-1, [z_prim])) + in + (* Should fail: {0; 0; 0} against pair nat (list nat) *) + let* () = + test_parse_data_fails + __LOC__ + ctxt + pair_nat_list_nat_ty + (Micheline.Seq (-1, [z_prim; z_prim; z_prim])) + in + (* check Pair 0 (Pair 0 {}) against pair nat (big_map nat nat) + so that the following test fails for the good reason and not because + the big map doesn't exist + *) + let id_z = Big_map.Id.unparse_to_z big_map_id in + let id_prim = Int (-1, id_z) in + let expected_big_map = + let open Script_typed_ir in + let diff = {map = Big_map_overlay.empty; size = 0} in + Big_map {id = Some big_map_id; diff; key_type = nat_ty; value_type = nat_ty} + in + let ty_equal : + type a ac1 ac2. + (a, ac1) Script_typed_ir.ty -> (a, ac2) Script_typed_ir.ty -> bool = + fun ty1 ty2 -> + match Script_typed_ir.(is_comparable ty1, is_comparable ty2) with + | Yes, Yes -> ty1 = ty2 + | No, No -> ty1 = ty2 + | Yes, No -> assert false + | No, Yes -> assert false + (* + These last two cases can't happen because the comparable character of a + type is a function of its concrete type. + It is possible to write a function that proves it but it is not needed + in the protocol for the moment. + *) + in + let equal (nat1, Big_map big_map1) (nat2, Big_map big_map2) = + (* Custom equal needed because big maps contain boxed maps containing functional values *) + nat1 = nat2 && big_map1.id = big_map2.id + && big_map1.key_type = big_map2.key_type + && ty_equal big_map1.value_type big_map2.value_type + && big_map1.diff.size = big_map2.diff.size + && Big_map_overlay.bindings big_map1.diff.map + = Big_map_overlay.bindings big_map2.diff.map + in + let*?@ (Ty_ex_c pair_nat_big_map_nat_nat_ty) = + pair_ty nat_ty big_map_nat_nat_ty + in + let* ctxt = + test_parse_data + ~equal + __LOC__ + ctxt + pair_nat_big_map_nat_nat_ty + (pair_prim2 z_prim (pair_prim2 id_prim (Seq (-1, [])))) + (Script_int.zero_n, expected_big_map) + in + (* Should fail: Pair 0 0 {} against pair nat (big_map nat nat) *) + test_parse_data_fails + __LOC__ + ctxt + pair_nat_big_map_nat_nat_ty + (pair_prim [z_prim; id_prim; Seq (-1, [])]) + +let test_parse_address () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let* ctxt, _big_map_id = test_context_with_nat_nat_big_map () in + (* KT1% (empty entrypoint) *) + let*?@ kt1fake = + Contract.of_b58check "KT1FAKEFAKEFAKEFAKEFAKEFAKEFAKGGSE2x" + in + let* ctxt = + test_parse_data + __LOC__ + ctxt + address_t + (String (-1, "KT1FAKEFAKEFAKEFAKEFAKEFAKEFAKGGSE2x%")) + {destination = Contract kt1fake; entrypoint = Entrypoint.default} + in + (* tz1% (empty entrypoint) *) + let*?@ tz1fake = + Contract.of_b58check "tz1fakefakefakefakefakefakefakcphLA5" + in + let* ctxt = + test_parse_data + __LOC__ + ctxt + address_t + (String (-1, "tz1fakefakefakefakefakefakefakcphLA5%")) + {destination = Contract tz1fake; entrypoint = Entrypoint.default} + in + (* scr1% (empty entrypoint) *) + let*?@ scr1 = + Destination.of_b58check "sr1JPVatbbPoGp4vb6VfQ1jzEPMrYFcKq6VG" + in + let* ctxt = + test_parse_data + __LOC__ + ctxt + address_t + (String (-1, "sr1JPVatbbPoGp4vb6VfQ1jzEPMrYFcKq6VG")) + {destination = scr1; entrypoint = Entrypoint.default} + in + (* scr1% (default entrypoint) *) + let+ (_ctxt : context) = + test_parse_data + __LOC__ + ctxt + address_t + (String (-1, "sr1JPVatbbPoGp4vb6VfQ1jzEPMrYFcKq6VG%")) + {destination = scr1; entrypoint = Entrypoint.default} + in + () + +let test_unparse_data loc ctxt ty x ~expected_readable ~expected_optimized = + let open Lwt_result_wrap_syntax in + let*@ actual_readable, ctxt = + Script_ir_translator.unparse_data ctxt Script_ir_unparser.Readable ty x + in + let*@ ctxt = + if actual_readable = Micheline.strip_locations expected_readable then + return ctxt + else Alcotest.failf "Error in readable unparsing: %s" loc + in + let*@ actual_optimized, ctxt = + Script_ir_translator.unparse_data ctxt Script_ir_unparser.Optimized ty x + in + if actual_optimized = Micheline.strip_locations expected_optimized then + return ctxt + else Alcotest.failf "Error in optimized unparsing: %s" loc + +let test_unparse_comb_data () = + let open Lwt_result_wrap_syntax in + let open Script in + let open Script_typed_ir in + let z = Script_int.zero_n in + let z_prim = Micheline.Int (-1, Z.zero) in + let nat_ty = nat_t in + let pair_prim l = Prim (-1, D_Pair, l, []) in + let pair_ty ty1 ty2 = pair_t (-1) ty1 ty2 in + let*?@ (Ty_ex_c pair_nat_nat_ty) = pair_ty nat_ty nat_ty in + let pair_prim2 a b = pair_prim [a; b] in + let pair_z_z_prim = pair_prim2 z_prim z_prim in + let* ctxt = test_context () in + (* Pair 0 0 *) + let* ctxt = + test_unparse_data + __LOC__ + ctxt + pair_nat_nat_ty + (z, z) + ~expected_readable:pair_z_z_prim + ~expected_optimized:pair_z_z_prim + in + (* Pair (Pair 0 0) 0 *) + let*?@ (Ty_ex_c pair_pair_nat_nat_nat_ty) = pair_ty pair_nat_nat_ty nat_ty in + let* ctxt = + test_unparse_data + __LOC__ + ctxt + pair_pair_nat_nat_nat_ty + ((z, z), z) + ~expected_readable:(pair_prim2 pair_z_z_prim z_prim) + ~expected_optimized:(pair_prim2 pair_z_z_prim z_prim) + in + (* Readable: Pair 0 0 0; Optimized: Pair 0 (Pair 0 0) *) + let*?@ (Ty_ex_c pair_nat_pair_nat_nat_ty) = pair_ty nat_ty pair_nat_nat_ty in + let* ctxt = + test_unparse_data + __LOC__ + ctxt + pair_nat_pair_nat_nat_ty + (z, (z, z)) + ~expected_readable:(pair_prim [z_prim; z_prim; z_prim]) + ~expected_optimized:(pair_prim2 z_prim pair_z_z_prim) + in + (* Readable: Pair 0 0 0 0; Optimized: {0; 0; 0; 0} *) + let*?@ (Ty_ex_c pair_nat_pair_nat_pair_nat_nat_ty) = + pair_ty nat_ty pair_nat_pair_nat_nat_ty + in + let* (_ : context) = + test_unparse_data + __LOC__ + ctxt + pair_nat_pair_nat_pair_nat_nat_ty + (z, (z, (z, z))) + ~expected_readable:(pair_prim [z_prim; z_prim; z_prim; z_prim]) + ~expected_optimized:(Micheline.Seq (-1, [z_prim; z_prim; z_prim; z_prim])) + in + return_unit + +(* Generate all the possible syntaxes for pairs *) +let gen_pairs left right = + [Prim ((), Script.D_Pair, [left; right], []); Seq ((), [left; right])] + +(* Generate all the possible syntaxes for combs *) +let rec gen_combs leaf arity = + assert (arity >= 2) ; + if arity = 2 then gen_pairs leaf leaf + else + gen_combs leaf (arity - 1) + |> List.map (fun smaller -> + (match smaller with + | Prim (loc, Script.D_Pair, vs, []) -> + Prim (loc, Script.D_Pair, leaf :: vs, []) + | Seq (loc, vs) -> Seq (loc, leaf :: vs) + | _ -> assert false) + :: gen_pairs leaf smaller) + |> List.flatten + +(* Checks the optimality of the Optimized Micheline representation for combs *) +let test_optimal_comb () = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let leaf_ty = nat_t in + let leaf_mich = Int ((), Z.zero) in + let leaf_v = Script_int.zero_n in + let size_of_micheline mich = + let canonical = Micheline.strip_locations mich in + ( canonical, + Bytes.length + @@ Data_encoding.Binary.to_bytes_exn Script.expr_encoding canonical ) + in + let check_optimal_comb loc ctxt ty v arity = + let*@ unparsed, ctxt = + Script_ir_translator.unparse_data ctxt Script_ir_unparser.Optimized ty v + in + let unparsed_canonical, unparsed_size = + size_of_micheline (Micheline.root unparsed) + in + let*@ () = + List.iter_es (fun other_repr -> + let other_repr_canonical, other_repr_size = + size_of_micheline other_repr + in + if other_repr_size < unparsed_size then + Alcotest.failf + "At %s, for comb of arity %d, representation %a (size %d bytes) \ + is shorter than representation %a (size %d bytes) returned by \ + unparse_data in Optimized mode" + loc + arity + Michelson_v1_printer.print_expr + other_repr_canonical + other_repr_size + Michelson_v1_printer.print_expr + unparsed_canonical + unparsed_size + else return_unit) + @@ gen_combs leaf_mich arity + in + return ctxt + in + let pair_ty ty1 ty2 = pair_t (-1) ty1 ty2 in + let* ctxt = test_context () in + let*?@ (Ty_ex_c comb2_ty) = pair_ty leaf_ty leaf_ty in + let comb2_v = (leaf_v, leaf_v) in + let* ctxt = check_optimal_comb __LOC__ ctxt comb2_ty comb2_v 2 in + let*?@ (Ty_ex_c comb3_ty) = pair_ty leaf_ty comb2_ty in + let comb3_v = (leaf_v, comb2_v) in + let* ctxt = check_optimal_comb __LOC__ ctxt comb3_ty comb3_v 3 in + let*?@ (Ty_ex_c comb4_ty) = pair_ty leaf_ty comb3_ty in + let comb4_v = (leaf_v, comb3_v) in + let* ctxt = check_optimal_comb __LOC__ ctxt comb4_ty comb4_v 4 in + let*?@ (Ty_ex_c comb5_ty) = pair_ty leaf_ty comb4_ty in + let comb5_v = (leaf_v, comb4_v) in + let* (_ : context) = check_optimal_comb __LOC__ ctxt comb5_ty comb5_v 5 in + return_unit + +(* Check that UNPACK on contract is forbidden. + See https://gitlab.com/tezos/tezos/-/issues/301 for the motivation + behind this restriction. +*) +let test_contract_not_packable () = + let open Lwt_result_syntax in + let elab_conf = Script_ir_translator_config.make ~legacy:false () in + let contract_unit = + Prim (0, Script.T_contract, [Prim (0, T_unit, [], [])], []) + in + let* ctxt = test_context () in + (* Test that [contract_unit] is parsable *) + let* () = + match + Script_ir_translator.parse_any_ty ctxt ~legacy:false contract_unit + with + | Ok _ -> Lwt_result_syntax.return_unit + | Error _ -> Alcotest.failf "Could not parse (contract unit)" + in + (* Test that [contract_unit] is not packable *) + let* () = + match + Script_ir_translator.parse_packable_ty ctxt ~legacy:false contract_unit + with + | Ok _ -> + Alcotest.failf + "(contract unit) should not be packable, see \ + https://gitlab.com/tezos/tezos/-/issues/301" + | Error _ -> return_unit + in + (* Test that elaboration of the [UNPACK unit] instruction succeeds *) + let* () = + let*! result = + Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf + (Prim (0, I_UNPACK, [Prim (0, T_unit, [], [])], [])) + (Item_t (Script_typed_ir.bytes_t, Bot_t)) + in + match result with + | Ok _ -> return_unit + | Error _ -> Alcotest.failf "Could not parse UNPACK unit" + in + (* Test that elaboration of the [UNPACK (contract unit)] instruction fails *) + let*! result = + Script_ir_translator.parse_instr + Script_tc_context.data + ctxt + ~elab_conf + (Prim (0, I_UNPACK, [contract_unit], [])) + (Item_t (Script_typed_ir.bytes_t, Bot_t)) + in + match result with + | Ok _ -> + Alcotest.failf + "UNPACK (contract unit) should not be allowed, see \ + https://gitlab.com/tezos/tezos/-/issues/301" + | Error _ -> return_unit + +(* This test function is used to checks forbidden operations in views. *) +let test_forbidden_op_in_view op () = + let open Lwt_result_syntax in + let prefix = path // "contracts/forbidden_op_in_view_" in + let script = read_file (prefix ^ op ^ ".tz") in + let contract_expr = Expr.from_string script in + let* ctxt = test_context () in + let*! result = + Script_ir_translator.typecheck_code + ~legacy:false + ~show_types:false + ctxt + contract_expr + in + match result with + | Ok _ -> + Alcotest.failf + "%s should not be allowed in views, see \ + https://gitlab.com/tezos/tezos/-/issues/1922" + op + | Error _ -> return_unit + +(** Test [parse_contract_data] for rollup with unit type. *) +let test_parse_contract_data_for_unit_rollup () = + let open Lwt_result_wrap_syntax in + let* block, (contract, _) = context_init_with_sc_rollup_arith_enabled T2 in + let* block, rollup = sc_originate block contract "unit" in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let*@ _ctxt, typed_contract = + Script_ir_translator.parse_contract_data + ctxt + (-1) + Script_typed_ir.unit_t + (Destination.Sc_rollup rollup) + ~entrypoint:Entrypoint.default + in + let (Ty_ex_c Script_typed_ir.Unit_t) = + Script_typed_ir.Typed_contract.arg_ty typed_contract + in + let destination = Script_typed_ir.Typed_contract.destination typed_contract in + let entrypoint = Script_typed_ir.Typed_contract.entrypoint typed_contract in + (* Check that the destinations match. *) + let* () = + Assert.equal_string + ~loc:__LOC__ + (Destination.to_b58check destination) + (Sc_rollup.Address.to_b58check rollup) + in + (* Check that entrypoints match. *) + let* () = + Assert.equal_string ~loc:__LOC__ (Entrypoint.to_string entrypoint) "default" + in + return_unit + +(** Test that [parse_contract_data] for rollup with invalid type fails. *) +let test_parse_contract_data_for_rollup_with_invalid_type () = + let open Lwt_result_wrap_syntax in + let* block, (contract, _) = context_init_with_sc_rollup_arith_enabled T2 in + let* block, rollup = sc_originate block contract "string" in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let entrypoint = Entrypoint.of_string_strict_exn "add" in + let*!@ res = + Script_ir_translator.parse_contract_data + ctxt + (-1) + Script_typed_ir.unit_t + (Destination.Sc_rollup rollup) + ~entrypoint + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) (Script_tc_errors.No_such_entrypoint entrypoint)) + +let test_contract path ~ok ~ko () = + let open Lwt_result_syntax in + let contract = path in + let script = read_file contract in + let contract_expr = Expr.from_string script in + let* ctxt = test_context () in + let*! result = + Script_ir_translator.typecheck_code + ~legacy:false + ~show_types:false + ctxt + contract_expr + in + match result with Ok _ -> ok () | Error t -> ko t + +let test_contract_success path = + let open Lwt_result_syntax in + test_contract path ~ok:return ~ko:(fun t -> + Alcotest.failf "Unexpected error: %a" Environment.Error_monad.pp_trace t) + +let test_contract_failure path = + let open Lwt_result_syntax in + test_contract + path + ~ok:(fun () -> + Alcotest.failf + "Unexpected success: typechecking %s should have failed" + path) + ~ko:(fun _ -> return_unit) + +let tests = + [ + Tztest.tztest "unparse view" `Quick test_unparse_view; + Tztest.tztest + "typecheck stack overflow error" + `Quick + test_typecheck_stack_overflow; + Tztest.tztest "comb type parsing" `Quick test_parse_comb_type; + Tztest.tztest "comb type unparsing" `Quick test_unparse_comb_type; + Tztest.tztest + "comb comparable type unparsing" + `Quick + test_unparse_comb_comparable_type; + Tztest.tztest "comb data parsing" `Quick test_parse_comb_data; + Tztest.tztest "comb data unparsing" `Quick test_unparse_comb_data; + Tztest.tztest "optimal comb data unparsing" `Quick test_optimal_comb; + Tztest.tztest "parse address" `Quick test_parse_address; + Tztest.tztest + "unpackability of the contract type" + `Quick + test_contract_not_packable; + Tztest.tztest + "forbidden SELF in view" + `Quick + (test_forbidden_op_in_view "SELF"); + Tztest.tztest + "forbidden SET_DELEGATE in view" + `Quick + (test_forbidden_op_in_view "SET_DELEGATE"); + Tztest.tztest + "forbidden TRANSFER_TOKENS in view" + `Quick + (test_forbidden_op_in_view "TRANSFER_TOKENS"); + Tztest.tztest + "forbidden CREATE_CONTRACT in view" + `Quick + (test_forbidden_op_in_view "CREATE_CONTRACT"); + Tztest.tztest + "parse contract data for rollup" + `Quick + test_parse_contract_data_for_unit_rollup; + Tztest.tztest + "parse contract data for rollup with entrypoint invalid type" + `Quick + test_parse_contract_data_for_rollup_with_invalid_type; + Tztest.tztest + "lambda_rec instruction" + `Quick + (test_contract_success (path // "contracts/rec_fact.tz")); + Tztest.tztest + "lambda_rec instruction with apply" + `Quick + (test_contract_success (path // "contracts/rec_fact_apply.tz")); + Tztest.tztest + "lambda_rec with type error" + `Quick + (test_contract_failure (path // "contracts/fail_rec.tz")); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("typechecking", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune new file mode 100644 index 000000000000..d6f7b59ddcd5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune @@ -0,0 +1,63 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name + src_proto_019_PtParisB_lib_protocol_test_integration_operations_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-alcotezt + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.base-test-helpers + octez-protocol-019-PtParisB-libs.plugin) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB + -open Tezos_019_PtParisB_test_helpers + -open Tezos_base_test_helpers + -open Tezos_protocol_plugin_019_PtParisB) + (modules + test_activation + test_combined_operations + test_failing_noop + test_origination + test_paid_storage_increase + test_reveal + test_sc_rollup_transfer + test_sc_rollup + test_transfer + test_voting + test_zk_rollup + test_transfer_ticket)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_integration_operations_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (deps (glob_files contracts/*)) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_activation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_activation.ml new file mode 100644 index 000000000000..0f943be04e37 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_activation.ml @@ -0,0 +1,603 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (activation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_activation.ml + Subject: The activation operation creates an implicit contract from a + registered commitment present in the context. It is + parametrized by a public key hash (pkh) and a secret. + + The commitments are composed of : + - a blinded pkh that can be revealed by the secret ; + - an amount. + + The commitments and the secrets are generated from + /scripts/create_genesis/create_genesis.py and should be + coherent. +*) + +open Protocol +open Alpha_context +open Test_tez + +(* Generated commitments and secrets *) + +let commitments = + List.map + (fun (bpkh, a) -> + Commitment. + { + blinded_public_key_hash = Blinded_public_key_hash.of_b58check_exn bpkh; + amount = Tez.of_mutez_exn (Int64.of_string a); + }) + [ + ("btz1bRL4X5BWo2Fj4EsBdUwexXqgTf75uf1qa", "23932454669343"); + ("btz1SxjV1syBgftgKy721czKi3arVkVwYUFSv", "72954577464032"); + ("btz1LtoNCjiW23txBTenALaf5H6NKF1L3c1gw", "217487035428349"); + ("btz1SUd3mMhEBcWudrn8u361MVAec4WYCcFoy", "4092742372031"); + ("btz1MvBXf4orko1tsGmzkjLbpYSgnwUjEe81r", "17590039016550"); + ("btz1LoDZ3zsjgG3k3cqTpUMc9bsXbchu9qMXT", "26322312350555"); + ("btz1RMfq456hFV5AeDiZcQuZhoMv2dMpb9hpP", "244951387881443"); + ("btz1Y9roTh4A7PsMBkp8AgdVFrqUDNaBE59y1", "80065050465525"); + ("btz1Q1N2ePwhVw5ED3aaRVek6EBzYs1GDkSVD", "3569618927693"); + ("btz1VFFVsVMYHd5WfaDTAt92BeQYGK8Ri4eLy", "9034781424478"); + ] + +type secret_account = { + account : public_key_hash; + activation_code : Blinded_public_key_hash.activation_code; + amount : Tez.t; +} + +let secrets () = + (* Exported from proto_alpha client - TODO : remove when relocated to lib_crypto *) + let read_key mnemonic email password = + match Tezos_client_base.Bip39.of_words mnemonic with + | None -> assert false + | Some t -> + (* TODO: unicode normalization (NFKD)... *) + let passphrase = Bytes.(cat (of_string email) (of_string password)) in + let sk = Tezos_client_base.Bip39.to_seed ~passphrase t in + let sk = Bytes.sub sk 0 32 in + let sk : Signature.Secret_key.t = + Ed25519 + (Data_encoding.Binary.of_bytes_exn + Signature.Ed25519.Secret_key.encoding + sk) + in + let pk = Signature.Secret_key.to_public_key sk in + let pkh = Signature.Public_key.hash pk in + (pkh, pk, sk) + in + List.map + (fun (mnemonic, secret, amount, pkh, password, email) -> + let pkh', pk, sk = read_key mnemonic email password in + let pkh = Signature.Public_key_hash.of_b58check_exn pkh in + assert (Signature.Public_key_hash.equal pkh pkh') ; + let account = Account.{pkh; pk; sk} in + Account.add_account account ; + { + account = account.pkh; + activation_code = + Stdlib.Option.get + (Blinded_public_key_hash.activation_code_of_hex secret); + amount = + WithExceptions.Option.to_exn + ~none:(Invalid_argument "tez conversion") + (Tez.of_mutez (Int64.of_string amount)); + }) + [ + ( [ + "envelope"; + "hospital"; + "mind"; + "sunset"; + "cancel"; + "muscle"; + "leisure"; + "thumb"; + "wine"; + "market"; + "exit"; + "lucky"; + "style"; + "picnic"; + "success"; + ], + "0f39ed0b656509c2ecec4771712d9cddefe2afac", + "23932454669343", + "tz1MawerETND6bqJqx8GV3YHUrvMBCDasRBF", + "z0eZHQQGKt", + "cjgfoqmk.wpxnvnup@tezos.example.org" ); + ( [ + "flag"; + "quote"; + "will"; + "valley"; + "mouse"; + "chat"; + "hold"; + "prosper"; + "silk"; + "tent"; + "cruel"; + "cause"; + "demise"; + "bottom"; + "practice"; + ], + "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4", + "72954577464032", + "tz1X4maqF9tC1Yn4jULjHRAyzjAtc25Z68TX", + "MHErskWPE6", + "oklmcktr.ztljnpzc@tezos.example.org" ); + ( [ + "library"; + "away"; + "inside"; + "paper"; + "wise"; + "focus"; + "sweet"; + "expose"; + "require"; + "change"; + "stove"; + "planet"; + "zone"; + "reflect"; + "finger"; + ], + "411dfef031eeecc506de71c9df9f8e44297cf5ba", + "217487035428349", + "tz1SWBY7rWMutEuWS54Pt33MkzAS6eWkUuTc", + "0AO6BzQNfN", + "ctgnkvqm.kvtiybky@tezos.example.org" ); + ( [ + "cruel"; + "fluid"; + "damage"; + "demand"; + "mimic"; + "above"; + "village"; + "alpha"; + "vendor"; + "staff"; + "absent"; + "uniform"; + "fire"; + "asthma"; + "milk"; + ], + "08d7d355bc3391d12d140780b39717d9f46fcf87", + "4092742372031", + "tz1amUjiZaevaxQy5wKn4SSRvVoERCip3nZS", + "9kbZ7fR6im", + "bnyxxzqr.tdszcvqb@tezos.example.org" ); + ( [ + "opera"; + "divorce"; + "easy"; + "myself"; + "idea"; + "aim"; + "dash"; + "scout"; + "case"; + "resource"; + "vote"; + "humor"; + "ticket"; + "client"; + "edge"; + ], + "9b7cad042fba557618bdc4b62837c5f125b50e56", + "17590039016550", + "tz1Zaee3QBtD4ErY1SzqUvyYTrENrExu6yQM", + "suxT5H09yY", + "iilkhohu.otnyuvna@tezos.example.org" ); + ( [ + "token"; + "similar"; + "ginger"; + "tongue"; + "gun"; + "sort"; + "piano"; + "month"; + "hotel"; + "vote"; + "undo"; + "success"; + "hobby"; + "shell"; + "cart"; + ], + "124c0ca217f11ffc6c7b76a743d867c8932e5afd", + "26322312350555", + "tz1geDUUhfXK1EMj7VQdRjug1MoFe6gHWnCU", + "4odVdLykaa", + "kwhlglvr.slriitzy@tezos.example.org" ); + ( [ + "shield"; + "warrior"; + "gorilla"; + "birth"; + "steak"; + "neither"; + "feel"; + "only"; + "liberty"; + "float"; + "oven"; + "extend"; + "pulse"; + "suffer"; + "vapor"; + ], + "ac7a2125beea68caf5266a647f24dce9fea018a7", + "244951387881443", + "tz1h3nY7jcZciJgAwRhWcrEwqfVp7VQoffur", + "A6yeMqBFG8", + "lvrmlbyj.yczltcxn@tezos.example.org" ); + ( [ + "waste"; + "open"; + "scan"; + "tip"; + "subway"; + "dance"; + "rent"; + "copper"; + "garlic"; + "laundry"; + "defense"; + "clerk"; + "another"; + "staff"; + "liar"; + ], + "2b3e94be133a960fa0ef87f6c0922c19f9d87ca2", + "80065050465525", + "tz1VzL4Xrb3fL3ckvqCWy6bdGMzU2w9eoRqs", + "oVZqpq60sk", + "rfodmrha.zzdndvyk@tezos.example.org" ); + ( [ + "fiber"; + "next"; + "property"; + "cradle"; + "silk"; + "obey"; + "gossip"; + "push"; + "key"; + "second"; + "across"; + "minimum"; + "nice"; + "boil"; + "age"; + ], + "dac31640199f2babc157aadc0021cd71128ca9ea", + "3569618927693", + "tz1RUHg536oRKhPLFfttcB5gSWAhh4E9TWjX", + "FfytQTTVbu", + "owecikdy.gxnyttya@tezos.example.org" ); + ( [ + "print"; + "labor"; + "budget"; + "speak"; + "poem"; + "diet"; + "chunk"; + "eternal"; + "book"; + "saddle"; + "pioneer"; + "ankle"; + "happy"; + "only"; + "exclude"; + ], + "bb841227f250a066eb8429e56937ad504d7b34dd", + "9034781424478", + "tz1M1LFbgctcPWxstrao9aLr2ECW1fV4pH5u", + "zknAl3lrX2", + "ettilrvh.zsrqrbud@tezos.example.org" ); + ] + +(** Helper: Create a genesis block with predefined commitments, + accounts and balances. *) +let activation_init () = + let open Lwt_result_syntax in + let+ b, c = Context.init1 ~consensus_threshold:0 ~commitments () in + let ss = secrets () in + (b, c, ss) + +(** Verify the genesis block created by [activation_init] can be + baked. *) +let test_simple_init_with_commitments () = + let open Lwt_result_syntax in + let* blk, _contract, _secrets = activation_init () in + let* (_ : Block.t) = Block.bake blk in + return_unit + +(** A single activation *) +let test_single_activation () = + let open Lwt_result_syntax in + let* blk, _contract, secrets = activation_init () in + let ({account; activation_code; amount = expected_amount; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + (* Contract does not exist *) + let* () = + Assert.balance_is ~loc:__LOC__ (B blk) (Contract.Implicit account) Tez.zero + in + let* operation = Op.activation (B blk) account activation_code in + let* blk = Block.bake ~operation blk in + (* Contract does exist *) + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.Implicit account) + expected_amount + +(** 10 activations, one per bake. *) +let test_multi_activation_1 () = + let open Lwt_result_syntax in + let* blk, _contract, secrets = activation_init () in + let* (_ : Block.t) = + List.fold_left_es + (fun blk {account; activation_code; amount = expected_amount; _} -> + let* operation = Op.activation (B blk) account activation_code in + let* blk = Block.bake ~operation blk in + let+ () = + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.Implicit account) + expected_amount + in + blk) + blk + secrets + in + return_unit + +(** All of the 10 activations occur in one bake. *) +let test_multi_activation_2 () = + let open Lwt_result_syntax in + let* blk, _contract, secrets = activation_init () in + let* ops = + List.fold_left_es + (fun ops {account; activation_code; _} -> + let+ op = Op.activation (B blk) account activation_code in + op :: ops) + [] + secrets + in + let* blk = Block.bake ~operations:ops blk in + List.iter_es + (fun {account; amount = expected_amount; _} -> + (* Contract does exist *) + Assert.balance_is + ~loc:__LOC__ + (B blk) + (Contract.Implicit account) + expected_amount) + secrets + +(** Transfer with activated account. *) +let test_activation_and_transfer () = + let open Lwt_result_syntax in + let* blk, bootstrap_contract, secrets = activation_init () in + let ({account; activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let first_contract = Contract.Implicit account in + let* operation = Op.activation (B blk) account activation_code in + let* blk = Block.bake ~operation blk in + let* amount = Context.Contract.balance (B blk) bootstrap_contract in + let half_amount = Test_tez.(amount /! 2L) in + let* activated_amount_before = + Context.Contract.balance (B blk) first_contract + in + let* operation = + Op.transaction (B blk) bootstrap_contract first_contract half_amount + in + let* blk = Block.bake ~operation blk in + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + (Contract.Implicit account) + activated_amount_before + half_amount + +(** Transfer to an unactivated account and then activating it. *) +let test_transfer_to_unactivated_then_activate () = + let open Lwt_result_syntax in + let* blk, bootstrap_contract, secrets = activation_init () in + let ({account; activation_code; amount} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let unactivated_commitment_contract = Contract.Implicit account in + let* b_amount = Context.Contract.balance (B blk) bootstrap_contract in + let b_half_amount = b_amount /! 2L in + let* inc = Incremental.begin_construction blk in + let* op = + Op.transaction + (I inc) + bootstrap_contract + unactivated_commitment_contract + b_half_amount + in + let* inc = Incremental.add_operation inc op in + let* op' = Op.activation (I inc) account activation_code in + let* inc = Incremental.add_operation inc op' in + let* blk2 = Incremental.finalize_block inc in + Assert.balance_was_credited + ~loc:__LOC__ + (B blk2) + (Contract.Implicit account) + amount + b_half_amount + +(****************************************************************) +(* The following test scenarios are supposed to raise errors. *) +(****************************************************************) + +(** Invalid pkh activation: expected to fail as the context does not + contain any commitment. *) +let test_invalid_activation_with_no_commitments () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let secrets = secrets () in + let ({account; activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let* operation = Op.activation (B blk) account activation_code in + let*! res = Block.bake ~operation blk in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_activation _ -> true + | _ -> false) + +(** Wrong activation: wrong secret given in the operation. *) +let test_invalid_activation_wrong_secret () = + let open Lwt_result_syntax in + let* blk, _contract, secrets = activation_init () in + let ({account; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth secrets 0 + in + let ({activation_code; _} as _second_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth secrets 1 + in + let* operation = Op.activation (B blk) account activation_code in + let*! res = Block.bake ~operation blk in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_activation _ -> true + | _ -> false) + +(** Invalid pkh activation : expected to fail as the context does not + contain an associated commitment. *) +let test_invalid_activation_inexistent_pkh () = + let open Lwt_result_syntax in + let* blk, _contract, secrets = activation_init () in + let ({activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let inexistent_pkh = + Signature.Public_key_hash.of_b58check_exn + "tz1PeQHGKPWSpNoozvxgqLN9TFsj6rDqNV3o" + in + let* operation = Op.activation (B blk) inexistent_pkh activation_code in + let*! res = Block.bake ~operation blk in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_activation _ -> true + | _ -> false) + +(** Invalid pkh activation : expected to fail as the commitment has + already been claimed. *) +let test_invalid_double_activation () = + let open Lwt_result_syntax in + let* blk, _contract, secrets = activation_init () in + let ({account; activation_code; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let* inc = Incremental.begin_construction blk in + let* op = Op.activation (I inc) account activation_code in + let* inc = Incremental.add_operation inc op in + let* op' = Op.activation (I inc) account activation_code in + let*! res = Incremental.add_operation inc op' in + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Conflicting_activation _ -> true + | _ -> false) + +(** Transfer from an unactivated commitment account. *) +let test_invalid_transfer_from_unactivated_account () = + let open Lwt_result_syntax in + let* blk, bootstrap_contract, secrets = activation_init () in + let ({account; _} as _first_one) = + WithExceptions.Option.get ~loc:__LOC__ @@ List.hd secrets + in + let unactivated_commitment_contract = Contract.Implicit account in + (* No activation *) + let* operation = + Op.transaction + (B blk) + unactivated_commitment_contract + bootstrap_contract + Tez.one + in + let*! res = Block.bake ~operation blk in + Assert.proto_error_with_info ~loc:__LOC__ res "Empty implicit contract" + +let tests = + [ + Tztest.tztest + "init with commitments" + `Quick + test_simple_init_with_commitments; + Tztest.tztest "single activation" `Quick test_single_activation; + Tztest.tztest "multi-activation one-by-one" `Quick test_multi_activation_1; + Tztest.tztest + "multi-activation all at a time" + `Quick + test_multi_activation_2; + Tztest.tztest "activation and transfer" `Quick test_activation_and_transfer; + Tztest.tztest + "transfer to unactivated account then activate" + `Quick + test_transfer_to_unactivated_then_activate; + Tztest.tztest + "invalid activation with no commitments" + `Quick + test_invalid_activation_with_no_commitments; + Tztest.tztest + "invalid activation with commitments" + `Quick + test_invalid_activation_inexistent_pkh; + Tztest.tztest + "invalid double activation" + `Quick + test_invalid_double_activation; + Tztest.tztest + "wrong activation code" + `Quick + test_invalid_activation_wrong_secret; + Tztest.tztest + "invalid transfer from unactivated account" + `Quick + test_invalid_transfer_from_unactivated_account; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("activation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_combined_operations.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_combined_operations.ml new file mode 100644 index 000000000000..a1e779712cce --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_combined_operations.ml @@ -0,0 +1,449 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (combined operations) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_combined_operations.ml + Subject: Multiple operations can be grouped in one ensuring their + deterministic application. + + If an invalid operation is present in this group of + operations, the previously applied operations are + backtracked leaving the context unchanged and the + following operations are skipped. Fees attributed to the + operations are collected by the baker nonetheless. + + Only manager operations are allowed in multiple transactions. + They must all belong to the same manager as there is only one + signature. +*) + +open Protocol +open Alpha_context + +let ten_tez = Test_tez.of_int 10 + +let gas_limit = Op.Custom_gas (Alpha_context.Gas.Arith.integral_of_int_exn 3000) + +(** Groups ten transactions between the same parties. *) +let test_multiple_transfers () = + let open Lwt_result_syntax in + let* blk, (c1, c2, c3) = Context.init3 () in + let* ops = + List.map_es + (fun _ -> Op.transaction ~gas_limit (B blk) c1 c2 Tez.one) + (1 -- 10) + in + let* operation = Op.combine_operations ~source:c1 (B blk) ops in + let baker_pkh = Context.Contract.pkh c3 in + let* inc = + Incremental.begin_construction ~policy:(By_account baker_pkh) blk + in + let* c1_old_balance = Context.Contract.balance (I inc) c1 in + let* c2_old_balance = Context.Contract.balance (I inc) c2 in + let* inc = Incremental.add_operation inc operation in + let* () = + Assert.balance_was_debited + ~loc:__LOC__ + (I inc) + c1 + c1_old_balance + (Test_tez.of_int 10) + in + let* () = + Assert.balance_was_credited + ~loc:__LOC__ + (I inc) + c2 + c2_old_balance + (Test_tez.of_int 10) + in + return_unit + +(** Groups ten delegated originations. *) +let test_multiple_origination_and_delegation () = + let open Lwt_result_syntax in + let* blk, (c1, c2) = Context.init2 () in + let n = 10 in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (B blk) + in + let delegate_pkh = Context.Contract.pkh c2 in + (* Deploy n smart contracts with dummy scripts from c1 *) + let* originations = + List.map_es + (fun i -> + Op.contract_origination + ~gas_limit + ~delegate:delegate_pkh + ~counter:(Manager_counter.Internal_for_tests.of_int i) + ~fee:Tez.zero + ~script:Op.dummy_script + ~credit:(Test_tez.of_int 10) + (B blk) + c1) + (1 -- n) + in + (* These computed originated contracts are not the ones really created *) + (* We will extract them from the tickets *) + let originations_operations, _ = List.split originations in + let* operation = + Op.combine_operations ~source:c1 (B blk) originations_operations + in + let* inc = Incremental.begin_construction blk in + let* c1_old_balance = Context.Contract.balance (I inc) c1 in + let* inc = Incremental.add_operation inc operation in + (* To retrieve the originated contracts, it is easier to extract them + from the tickets. Else, we could (could we ?) hash each combined + operation individually. *) + let tickets = Incremental.rev_tickets inc in + let open Apply_results in + let tickets = + List.fold_left + (fun acc -> function + | No_operation_metadata -> assert false + | Operation_metadata {contents} -> + to_list (Contents_result_list contents) @ acc) + [] + tickets + |> List.rev + in + let new_contracts = + List.map + (function + | Contents_result + (Manager_operation_result + { + operation_result = + Applied (Origination_result {originated_contracts = [h]; _}); + _; + }) -> + h + | _ -> assert false) + tickets + in + (* Previous balance - (Credit (n * 10tz) + Origination cost (n tz)) *) + let*? origination_burn = + Test_tez.(cost_per_byte *? Int64.of_int origination_size) + in + let*? origination_total_cost = + Test_tez.(origination_burn *? Int64.of_int n) + in + let*? t = Test_tez.( *? ) Op.dummy_script_cost 10L in + let*? t = Test_tez.( +? ) (Test_tez.of_int (10 * n)) t in + let*? total_cost = Test_tez.( +? ) origination_total_cost t in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I inc) c1 c1_old_balance total_cost + in + List.iter_es + (fun c -> + let c = Contract.Originated c in + Assert.balance_is ~loc:__LOC__ (I inc) c (Test_tez.of_int 10)) + new_contracts + +let expect_apply_failure = + let open Lwt_result_syntax in + function + | Environment.Ecoproto_error err :: _ -> + Assert.test_error_encodings err ; + let error_info = + Error_monad.find_info_of_error (Environment.wrap_tzerror err) + in + if error_info.title = "Balance too low" then return_unit + else failwith "unexpected error" + | _ -> failwith "balance too low should fail" + +(** Groups three operations, the middle one failing. + Checks that the receipt is consistent. + Variant without fees. *) +let test_failing_operation_in_the_middle () = + let open Lwt_result_syntax in + let* blk, (c1, c2) = Context.init2 () in + let* op1 = Op.transaction ~gas_limit ~fee:Tez.zero (B blk) c1 c2 Tez.one in + let* op2 = + Op.transaction ~gas_limit ~fee:Tez.zero (B blk) c1 c2 Test_tez.max_tez + in + let* op3 = Op.transaction ~gas_limit ~fee:Tez.zero (B blk) c1 c2 Tez.one in + let operations = [op1; op2; op3] in + let* operation = Op.combine_operations ~source:c1 (B blk) operations in + let* inc = Incremental.begin_construction blk in + let* c1_old_balance = Context.Contract.balance (I inc) c1 in + let* c2_old_balance = Context.Contract.balance (I inc) c2 in + let* inc = Incremental.add_operation ~expect_apply_failure inc operation in + let tickets = Incremental.rev_tickets inc in + let open Apply_results in + let tickets = + List.fold_left + (fun acc -> function + | No_operation_metadata -> assert false + | Operation_metadata {contents} -> + to_list (Contents_result_list contents) @ acc) + [] + tickets + in + (match tickets with + | Contents_result + (Manager_operation_result {operation_result = Backtracked _; _}) + :: Contents_result + (Manager_operation_result {operation_result = Failed (_, trace); _}) + :: Contents_result + (Manager_operation_result {operation_result = Skipped _; _}) + :: _ -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect = + Format.asprintf "Balance of contract %a too low" Context.Contract.pp c1 + in + assert (Astring.String.is_infix ~affix:expect trace_string) + | _ -> assert false) ; + let* () = Assert.balance_is ~loc:__LOC__ (I inc) c1 c1_old_balance in + let* () = Assert.balance_is ~loc:__LOC__ (I inc) c2 c2_old_balance in + return_unit + +(** Groups three operations, the middle one failing. + Checks that the receipt is consistent. + Variant with fees, that should be spent even in case of failure. *) +let test_failing_operation_in_the_middle_with_fees () = + let open Lwt_result_syntax in + let* blk, (c1, c2) = Context.init2 () in + let* op1 = Op.transaction ~fee:Tez.one (B blk) c1 c2 Tez.one in + let* op2 = Op.transaction ~fee:Tez.one (B blk) c1 c2 Test_tez.max_tez in + let* op3 = Op.transaction ~fee:Tez.one (B blk) c1 c2 Tez.one in + let operations = [op1; op2; op3] in + let* operation = Op.combine_operations ~source:c1 (B blk) operations in + let* inc = Incremental.begin_construction blk in + let* c1_old_balance = Context.Contract.balance (I inc) c1 in + let* c2_old_balance = Context.Contract.balance (I inc) c2 in + let* inc = Incremental.add_operation ~expect_apply_failure inc operation in + let tickets = Incremental.rev_tickets inc in + let open Apply_results in + let tickets = + List.fold_left + (fun acc -> function + | No_operation_metadata -> assert false + | Operation_metadata {contents} -> + to_list (Contents_result_list contents) @ acc) + [] + tickets + in + (match tickets with + | Contents_result + (Manager_operation_result {operation_result = Backtracked _; _}) + :: Contents_result + (Manager_operation_result {operation_result = Failed (_, trace); _}) + :: Contents_result + (Manager_operation_result {operation_result = Skipped _; _}) + :: _ -> + let trace_string = + Format.asprintf "%a" Environment.Error_monad.pp_trace trace + in + let expect = + Format.asprintf "Balance of contract %a too low" Context.Contract.pp c1 + in + assert (Astring.String.is_infix ~affix:expect trace_string) + | _ -> assert false) ; + (* In the presence of a failure, all the fees are collected. Even for skipped operations. *) + let* () = + Assert.balance_was_debited + ~loc:__LOC__ + (I inc) + c1 + c1_old_balance + (Test_tez.of_int 3) + in + let* () = Assert.balance_is ~loc:__LOC__ (I inc) c2 c2_old_balance in + return_unit + +let test_wrong_signature_in_the_middle () = + let open Lwt_result_syntax in + let* blk, (c1, c2) = Context.init2 ~consensus_threshold:0 () in + let* op1 = Op.transaction ~gas_limit ~fee:Tez.one (B blk) c1 c2 Tez.one in + let* op2 = Op.transaction ~gas_limit ~fee:Tez.one (B blk) c2 c1 Tez.one in + (* Make legit transfers, performing reveals *) + let* b = Block.bake ~operations:[op1; op2] blk in + (* Make c2 reach counter 5 *) + let* operation = Op.transaction ~gas_limit ~fee:Tez.one (B b) c2 c1 Tez.one in + let* b = Block.bake ~operation b in + let* operation = Op.transaction ~gas_limit ~fee:Tez.one (B b) c2 c1 Tez.one in + let* b = Block.bake ~operation b in + let* operation = Op.transaction ~gas_limit ~fee:Tez.one (B b) c2 c1 Tez.one in + let* b = Block.bake ~operation b in + (* Cook transactions for actual test *) + let* op1 = Op.transaction ~gas_limit ~fee:Tez.one (B b) c1 c2 Tez.one in + let* op2 = Op.transaction ~gas_limit ~fee:Tez.one (B b) c1 c2 Tez.one in + let* op3 = Op.transaction ~gas_limit ~fee:Tez.one (B b) c1 c2 Tez.one in + let* spurious_operation = + Op.transaction ~gas_limit ~fee:Tez.one (B b) c2 c1 Tez.one + in + let operations = [op1; op2; op3] in + + let* operation = + Op.combine_operations ~spurious_operation ~source:c1 (B b) operations + in + let expect_failure = function + | Environment.Ecoproto_error + (Validate_errors.Manager.Inconsistent_sources as err) + :: _ -> + Assert.test_error_encodings err ; + return_unit + | _ -> + failwith + "Packed operation has invalid source in the middle : operation \ + expected to fail." + in + let* inc = Incremental.begin_construction b in + let* (_inc : Incremental.t) = + Incremental.add_operation ~expect_failure inc operation + in + return_unit + +let expect_inconsistent_counters list = + let open Lwt_result_syntax in + if + List.exists + (function + | Environment.Ecoproto_error + Validate_errors.Manager.Inconsistent_counters -> + true + | _ -> false) + list + then return_unit + else + failwith + "Packed operation has inconsistent counters : operation expected to fail \ + but got errors: %a." + Error_monad.pp_print_trace + list + +let test_inconsistent_counters () = + let open Lwt_result_syntax in + let* blk, (c1, c2) = Context.init2 () in + let* op1 = Op.transaction ~gas_limit ~fee:Tez.one (B blk) c1 c2 Tez.one in + let* op2 = Op.transaction ~gas_limit ~fee:Tez.one (B blk) c2 c1 Tez.one in + (* Make legit transfers, performing reveals *) + let* b = Block.bake ~operations:[op1; op2] blk in + (* Now, counter c1 = counter c2 = 1, Op.transaction builds with counter + 1 *) + let* op1 = + Op.transaction + ~gas_limit + ~fee:Tez.one + (B b) + c1 + c2 + ~counter:(Manager_counter.Internal_for_tests.of_int 1) + Tez.one + in + let* op2 = + Op.transaction + ~gas_limit + ~fee:Tez.one + (B b) + c1 + c2 + ~counter:(Manager_counter.Internal_for_tests.of_int 2) + Tez.one + in + let* op2' = + Op.transaction + ~gas_limit + ~fee:Tez.one + (B b) + c1 + c2 + ~counter:(Manager_counter.Internal_for_tests.of_int 2) + (Tez.of_mutez_exn 5_000L) + in + let* op3 = + Op.transaction + ~gas_limit + ~fee:Tez.one + (B b) + c1 + c2 + ~counter:(Manager_counter.Internal_for_tests.of_int 3) + Tez.one + in + let* op4 = + Op.transaction + ~gas_limit + ~fee:Tez.one + (B b) + c1 + c2 + ~counter:(Manager_counter.Internal_for_tests.of_int 4) + Tez.one + in + (* Canari: Check counters are ok *) + let* op = Op.batch_operations ~source:c1 (B b) [op1; op2; op3; op4] in + let* inc = Incremental.begin_construction b in + let* (_ : Incremental.t) = Incremental.add_operation inc op in + (* Gap in counter in the following op *) + let* op = Op.batch_operations ~source:c1 (B b) [op1; op2; op4] in + let* (_ : Incremental.t) = + Incremental.add_operation + ~expect_failure:expect_inconsistent_counters + inc + op + in + (* Same counter used twice in the following op *) + let* op = Op.batch_operations ~source:c1 (B b) [op1; op2; op2'] in + let* (_ : Incremental.t) = + Incremental.add_operation + ~expect_failure:expect_inconsistent_counters + inc + op + in + return_unit + +let tests = + [ + Tztest.tztest "multiple transfers" `Quick test_multiple_transfers; + Tztest.tztest + "multiple originations and delegations" + `Quick + test_multiple_origination_and_delegation; + Tztest.tztest + "Failing operation in the middle" + `Quick + test_failing_operation_in_the_middle; + Tztest.tztest + "Failing operation in the middle (with fees)" + `Quick + test_failing_operation_in_the_middle_with_fees; + Tztest.tztest + "Failing operation (wrong manager in the middle of a pack)" + `Quick + test_wrong_signature_in_the_middle; + Tztest.tztest + "Inconsistent counters in batch" + `Quick + test_inconsistent_counters; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("combined", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_failing_noop.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_failing_noop.ml new file mode 100644 index 000000000000..c29cf6d9d384 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_failing_noop.ml @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_failing_noop.ml + Subject: The Failing_noop operation was added bearing in mind the + possibility for the end user to sign arbitrary bytes, + encapsulate in the operation, with the absolute garanty that + the signed bytes can't be used for something against the + user's will. The Failing_noop operation always fails when + applied. + *) + +(** try to apply a failing_noop and assert that the operation fails *) +let failing_noop_must_fail_when_injected () = + let open Lwt_result_syntax in + let* blk, contract = Context.init1 () in + let source = Context.Contract.pkh contract in + let* operation = Op.failing_noop (B blk) source "tezos" in + let*! res = Block.bake ~operation blk in + Assert.proto_error ~loc:__LOC__ res (function + | Protocol.Validate_errors.Failing_noop_error -> true + | _ -> false) + +let tests = + [Tztest.tztest "injection fails" `Quick failing_noop_must_fail_when_injected] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("failing_noop operation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_origination.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_origination.ml new file mode 100644 index 000000000000..b05f31b3dbae --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_origination.ml @@ -0,0 +1,360 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (origination) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_origination.ml + Subject: On originating contracts. +*) + +open Protocol +open Alpha_context +open Test_tez + +let ten_tez = of_int 10 + +(* The possible fees are: a given credit, an origination burn fee + (constants_repr.default.origination_burn = 257 mtez), a fee that is paid when + creating an originate contract. *) +let total_fees_for_origination ?(fee = Tez.zero) ?(credit = Tez.zero) b = + let open Lwt_result_syntax in + let* {parametric = {origination_size; cost_per_byte; _}; _} = + Context.get_constants (B b) + in + let*? origination_burn = cost_per_byte *? Int64.of_int origination_size in + let*? t = credit +? fee in + let*? t = origination_burn +? t in + let*? total_fee = Op.dummy_script_cost +? t in + return total_fee + +(* [test_origination_balances fee credit spendable delegatable] takes four + optional parameter: fee is the fee that pay if require to create an + originated contract; credit is the amount of tez that will send to this + contract; delegatable default is set to true meaning that this contract is + able to delegate. + + This function creates 2 contracts, one for originating (called source) and + one for baking; get the balance of the source contract, call the + origination operation to create a new originated contract from this contract + with all the possible fees; and check the balance before/after originated + operation valid. + - the source contract has payed all the fees + - the originated has been credited correctly. + Note that we need 2 contracts because in Tenderbake the baker receives the + fees instantaneously. So to see that the fees are subtracted, we need that + the bake is done by another delegated. *) +let test_origination_balances ~loc:_ ?(fee = Tez.zero) ?(credit = Tez.zero) () = + let open Lwt_result_syntax in + let* b, (source, contract_for_bake) = Context.init2 () in + let pkh_for_orig = Context.Contract.pkh source in + let pkh_for_bake = Context.Contract.pkh contract_for_bake in + let* operation, new_contract = + Op.contract_origination (B b) source ~fee ~credit ~script:Op.dummy_script + in + let* total_fee = total_fees_for_origination ~fee ~credit b in + let* b = Block.bake ~operation ~policy:(By_account pkh_for_bake) b in + (* check that after the block has been baked the contract for originating + was debited all the fees *) + let* deposits = Context.Delegate.current_frozen_deposits (B b) pkh_for_orig in + let*? total_fee_plus_deposits = total_fee +? deposits in + let* () = + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + source + Account.default_initial_balance + total_fee_plus_deposits + in + (* check the balance of the originate contract is equal to credit *) + Assert.balance_is ~loc:__LOC__ (B b) new_contract credit + +(** [register_origination fee credit spendable delegatable] takes four + optional parameter: fee for the fee need to be paid if set to + create an originated contract; credit is the amount of tez that + send to this originated contract; spendable default is set to true + meaning that this contract is spendable; delegatable default is + set to true meaning that this contract is able to delegate. *) +let register_origination ?(fee = Tez.zero) ?(credit = Tez.zero) () = + let open Lwt_result_syntax in + let* b, (source, contract_for_bake) = Context.init2 () in + let source_pkh = Context.Contract.pkh source in + let pkh_for_bake = Context.Contract.pkh contract_for_bake in + let* operation, originated = + Op.contract_origination (B b) source ~fee ~credit ~script:Op.dummy_script + in + let* b = Block.bake ~operation ~policy:(By_account pkh_for_bake) b in + (* fee + credit were debited from source *) + let* total_fee = total_fees_for_origination ~fee ~credit b in + let* deposits = Context.Delegate.current_frozen_deposits (B b) source_pkh in + let*? total_fee_plus_deposits = total_fee +? deposits in + let* () = + Assert.balance_was_debited + ~loc:__LOC__ + (B b) + source + Account.default_initial_balance + total_fee_plus_deposits + in + (* originated contract has been credited *) + let+ () = + Assert.balance_was_credited ~loc:__LOC__ (B b) originated Tez.zero credit + in + (* TODO spendable or not and delegatable or not if relevant for some + test. Not the case at the moment, cf. uses of + register_origination *) + (b, source, originated) + +(******************************************************) +(* Tests *) +(******************************************************) + +(** Basic test. A contract is created as well as the newly originated + contract (called from origination operation). The balance + before/after are checked. *) +let test_balances_simple () = test_origination_balances ~loc:__LOC__ () + +(** Same as [balances_simple] but credits 10 tez to the originated + contract (no fees). *) +let test_balances_credit () = + test_origination_balances ~loc:__LOC__ ~credit:ten_tez () + +(** Same as [balances_credit] with 10 tez fees. *) +let test_balances_credit_fee () = + test_origination_balances ~loc:__LOC__ ~credit:(of_int 2) ~fee:ten_tez () + +(** Ask source contract to pay a fee when originating a contract. *) +let test_pay_fee () = + let open Lwt_result_syntax in + let* _b, _contract, _new_contract = + register_origination ~credit:(of_int 2) ~fee:ten_tez () + in + return_unit + +(******************************************************) +(** Errors *) + +(******************************************************) + +(** Create an originate contract where the contract does not have + enough tez to pay for the fee. *) +let test_not_tez_in_contract_to_pay_fee () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 ~consensus_threshold:0 () in + (* transfer everything but one tez from 1 to 2 and check balance of 1 *) + let* balance = Context.Contract.balance (B b) contract_1 in + let*? amount = balance -? Tez.one in + let* operation = Op.transaction (B b) contract_1 contract_2 amount in + let pkh1 = Context.Contract.pkh contract_1 in + let* b = Block.bake ~policy:(Excluding [pkh1]) ~operation b in + let* () = + Assert.balance_was_debited ~loc:__LOC__ (B b) contract_1 balance amount + in + (* use this source contract to create an originate contract where it requires + to pay a fee and add an amount of credit into this new contract *) + let* op, _ = + Op.contract_origination + (B b) + ~fee:ten_tez + ~credit:Tez.one + contract_1 + ~script:Op.dummy_script + in + let* inc = Incremental.begin_construction b in + let*! inc = Incremental.add_operation inc op in + Assert.proto_error_with_info ~loc:__LOC__ inc "Balance too low" + +(* Set the attester of the block as manager/delegate of the originated + account. *) +let register_contract_get_attester () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 () in + let* inc = Incremental.begin_construction b in + let+ account_attester, _slots = Context.get_attester (I inc) in + (inc, contract, account_attester) + +(* Create multiple originated contracts and ask contract to pay the fee. *) +let n_originations n ?credit ?fee () = + let open Lwt_result_syntax in + List.fold_left_es + (fun new_contracts _ -> + let+ _b, _source, new_contract = register_origination ?fee ?credit () in + new_contract :: new_contracts) + [] + (1 -- n) + +(** Create 100 originations. *) +let test_multiple_originations () = + let open Lwt_result_syntax in + let* contracts = n_originations 100 ~credit:(of_int 2) ~fee:ten_tez () in + Assert.equal_int ~loc:__LOC__ (List.length contracts) 100 + +(** Cannot originate two contracts with the same context's counter. *) +let test_counter () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 ~consensus_threshold:0 () in + let* op1, _ = + Op.contract_origination + (B b) + ~credit:Tez.one + contract + ~script:Op.dummy_script + in + let* op2, _ = + Op.contract_origination + (B b) + ~credit:Tez.one + contract + ~script:Op.dummy_script + in + let* b = Block.bake ~operation:op1 b in + let* inc = Incremental.begin_construction b in + let*! res = Incremental.add_operation inc op2 in + Assert.proto_error_with_info + ~loc:__LOC__ + res + "Invalid counter (already used) in a manager operation" + +let test_unparsable_script () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 ~consensus_threshold:0 () in + let open Alpha_context in + (* Craft an ill-typed origination's contract. *) + let pkh = + match contract with Implicit pkh -> pkh | Originated _ -> assert false + in + let dummy_expr = + Script.lazy_expr + Environment.Micheline.(strip_locations (Int ((), Z.of_int 123))) + in + let script = Script.{code = dummy_expr; storage = dummy_expr} in + let origination = Origination {delegate = None; script; credit = Tez.one} in + let gas_limit = + Gas.Arith.integral_of_int_exn + (49_000 + + Michelson_v1_gas.Internal_for_tests.int_cost_of_manager_operation) + in + let op = + Contents_list + (Single + (Manager_operation + { + source = pkh; + fee = Tez.one; + counter = Manager_counter.Internal_for_tests.of_int 1; + operation = origination; + gas_limit; + storage_limit = Z.zero; + })) + in + let encoded_op = + Data_encoding.Binary.to_bytes_exn Operation.contents_list_encoding op + |> Bytes.to_string + in + let* account = Account.find pkh in + let ill_typed_op = + Data_encoding.Binary.of_string_exn + Operation.contents_list_encoding + encoded_op + |> Op.sign account.sk (Context.branch (B b)) + in + (* Ensure that the application fails with [Ill_typed_contract]. *) + let* i = Incremental.begin_construction b in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure:(function + | Environment.Ecoproto_error (Script_tc_errors.Ill_typed_contract _) + :: _ -> + return_unit + | trace -> + failwith + "Expected error trace [Ill_typed_contract], but got:@\n%a" + pp_print_trace + trace) + i + ill_typed_op + in + (* Craft an unparsable lazy expr. *) + let encoded_dummy_expr = + let b = + Data_encoding.Binary.to_bytes_exn Script.lazy_expr_encoding dummy_expr + in + assert (Hex.to_bytes_exn (`Hex "0000000300bb01") = b) ; + Bytes.to_string b + in + let unparsable_dummy_expr = + Hex.to_bytes_exn (`Hex "00000003ffffff") |> Bytes.to_string + in + let unparsable_operation = + let encoded_bad_op = + Re.( + replace_string + ~all:true + (compile (str encoded_dummy_expr)) + encoded_op + ~by:unparsable_dummy_expr) + in + Data_encoding.Binary.of_string_exn + Operation.contents_list_encoding + encoded_bad_op + |> Op.sign account.sk (Context.branch (B b)) + in + (* Ensure that the operation is valid but the application fails with + [Lazy_script_decode]. *) + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure:(function + | [Environment.Ecoproto_error Script.Lazy_script_decode] -> return_unit + | trace -> + failwith + "Expected error trace [Lazy_script_decode], but got:@\n%a" + pp_print_trace + trace) + i + unparsable_operation + in + return_unit + +(******************************************************) + +let tests = + [ + Tztest.tztest "balances_simple" `Quick test_balances_simple; + Tztest.tztest "balances_credit" `Quick test_balances_credit; + Tztest.tztest "balances_credit_fee" `Quick test_balances_credit_fee; + Tztest.tztest "pay_fee" `Quick test_pay_fee; + Tztest.tztest + "not enough tez in contract to pay fee" + `Quick + test_not_tez_in_contract_to_pay_fee; + Tztest.tztest "multiple originations" `Quick test_multiple_originations; + Tztest.tztest "counter" `Quick test_counter; + Tztest.tztest "unparsable script" `Quick test_unparsable_script; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("orgination", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_paid_storage_increase.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_paid_storage_increase.ml new file mode 100644 index 000000000000..f1559d540ca1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_paid_storage_increase.ml @@ -0,0 +1,246 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (increase_paid_storage) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_paid_storage_increase.ml + Subject: On increasing a paid amount of contract storage. +*) + +open Protocol +open Alpha_context + +let ten_tez = Test_tez.of_int 10 + +let dummy_script = + "{parameter unit; storage unit; code { CAR ; NIL operation ; PAIR }}" + +let contract_originate block ?(script = dummy_script) + ?(storage = Expr.from_string "Unit") account = + let open Lwt_result_syntax in + let code = Expr.from_string script in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + let source_contract = account in + let baker = Context.Contract.pkh account in + let* op, dst = + Op.contract_origination_hash (B block) source_contract ~fee:Tez.zero ~script + in + let* inc = + Incremental.begin_construction ~policy:Block.(By_account baker) block + in + let* inc = Incremental.add_operation inc op in + let+ b = Incremental.finalize_block inc in + (b, dst) + +(** [test_balances] runs a simple [increase_paid_storage] and verifies that the + source contract balance is correct and that the storage of the + destination contract has been increased by the right amount. *) +let test_balances ~amount = + let open Lwt_result_wrap_syntax in + let* b, source = Context.init1 () in + let* b, destination = contract_originate b source in + let* inc = Incremental.begin_construction b in + let* balance_before_op = Context.Contract.balance (I inc) source in + let contract_dst = Contract.Originated destination in + let*@ storage_before_op = + Contract.Internal_for_tests.paid_storage_space + (Incremental.alpha_ctxt inc) + contract_dst + in + let* op = + Op.increase_paid_storage ~fee:Tez.zero (I inc) ~source ~destination amount + in + let* inc = Incremental.add_operation inc op in + (* check that after the block has been baked, the source was debited of all + the burned tez *) + let* {parametric = {cost_per_byte; _}; _} = Context.get_constants (I inc) in + let burned_tez = Test_tez.(cost_per_byte *! Z.to_int64 amount) in + let* () = + Assert.balance_was_debited + ~loc:__LOC__ + (I inc) + source + balance_before_op + burned_tez + in + (* check that the storage has been increased by the right amount *) + let*@ storage = + Contract.Internal_for_tests.paid_storage_space + (Incremental.alpha_ctxt inc) + contract_dst + in + let storage_minus_amount = Z.sub storage amount in + Assert.equal_int + ~loc:__LOC__ + (Z.to_int storage_before_op) + (Z.to_int storage_minus_amount) + +(******************************************************) +(* Tests *) +(******************************************************) + +(** Basic test. We test balances in simple cases. *) +let test_balances_simple () = test_balances ~amount:(Z.of_int 100) + +(******************************************************) +(* Errors *) +(******************************************************) + +(** We test the operation when the amount given is null. *) +let test_null_amount () = + let open Lwt_result_syntax in + let*! result = test_balances ~amount:Z.zero in + Assert.proto_error ~loc:__LOC__ result (function + | Fees_storage.Negative_storage_input -> true + | _ -> false) + +(** We test the operation when the amount given is negative. *) +let test_negative_amount () = + let open Lwt_result_syntax in + let amount = Z.of_int (-10) in + let*! result = test_balances ~amount in + Assert.proto_error ~loc:__LOC__ result (function + | Fees_storage.Negative_storage_input -> true + | _ -> false) + +(** We create an implicit account with not enough tez to pay for the + storage increase. *) +let test_no_tez_to_pay () = + let open Lwt_result_syntax in + let* b, (source, baker, receiver) = Context.init3 ~consensus_threshold:0 () in + let* b, destination = contract_originate b source in + let pkh_for_bake = Context.Contract.pkh baker in + let* inc = + Incremental.begin_construction ~policy:Block.(By_account pkh_for_bake) b + in + let* {parametric = {cost_per_byte; _}; _} = Context.get_constants (I inc) in + let increase_amount = + Z.div (Z.of_int 2_000_000) (Z.of_int64 (Tez.to_mutez cost_per_byte)) + in + let* balance = Context.Contract.balance (I inc) source in + let*? tez_to_substract = Test_tez.(balance -? Tez.one) in + let* op = + Op.transaction (I inc) ~fee:Tez.zero source receiver tez_to_substract + in + let* inc = Incremental.add_operation inc op in + let* b = Incremental.finalize_block inc in + let* inc = + Incremental.begin_construction ~policy:Block.(By_account pkh_for_bake) b + in + let* op = + Op.increase_paid_storage (I inc) ~source ~destination increase_amount + in + let*! inc = Incremental.add_operation inc op in + Assert.proto_error ~loc:__LOC__ inc (function + | Fees_storage.Cannot_pay_storage_fee -> true + | _ -> false) + +(** To test when there is no smart contract at the address given. *) +let test_no_contract () = + let open Lwt_result_syntax in + let* b, source = Context.init1 () in + let* inc = Incremental.begin_construction b in + let destination = Contract_helpers.fake_KT1 in + let* op = Op.increase_paid_storage (I inc) ~source ~destination Z.zero in + let*! inc = Incremental.add_operation inc op in + Assert.proto_error ~loc:__LOC__ inc (function + | Raw_context.Storage_error (Missing_key (_, Raw_context.Get)) -> true + | _ -> false) + +(** To test if the increase in storage is effective. *) +let test_effectiveness () = + let open Lwt_result_syntax in + let* b, (source, _contract_source) = + Context.init2 ~consensus_threshold:0 () + in + let script = + "{parameter unit; storage int; code { CDR ; PUSH int 65536 ; MUL ; NIL \ + operation ; PAIR }}" + in + let storage = + Tezos_micheline.Micheline.strip_locations (Expr_common.int Z.one) + in + let* b, destination = contract_originate ~script ~storage b source in + let* inc = Incremental.begin_construction b in + (* We ensure that the transaction can't be made with a 0 burn cap. *) + let contract_dst = Contract.Originated destination in + let* op = + Op.transaction + ~storage_limit:Z.zero + ~fee:Tez.zero + (I inc) + source + contract_dst + Tez.zero + in + let*! inc_test = Incremental.add_operation inc op in + let* () = + Assert.proto_error ~loc:__LOC__ inc_test (function + | Fees.Operation_quota_exceeded -> true + | _ -> false) + in + let* b = Incremental.finalize_block inc in + let* inc = Incremental.begin_construction b in + let* op = + Op.increase_paid_storage + (I inc) + ~fee:Tez.zero + ~source + ~destination + (Z.of_int 10) + in + let* inc = Incremental.add_operation inc op in + let* b = Incremental.finalize_block inc in + let* inc = Incremental.begin_construction b in + (* We test the same transaction to see if increase_paid_storage worked. *) + let* op = + Op.transaction + ~storage_limit:Z.zero + ~fee:Tez.zero + (I inc) + source + contract_dst + Tez.zero + in + let+ (_inc : Incremental.t) = Incremental.add_operation inc op in + () + +let tests = + [ + Tztest.tztest "balances simple" `Quick test_balances_simple; + Tztest.tztest "null amount" `Quick test_null_amount; + Tztest.tztest "negative amount" `Quick test_negative_amount; + Tztest.tztest "not enough tez to pay" `Quick test_no_tez_to_pay; + Tztest.tztest "no contract to bump its paid storage" `Quick test_no_contract; + Tztest.tztest "effectiveness" `Quick test_effectiveness; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("paid storage increase", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_reveal.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_reveal.ml new file mode 100644 index 000000000000..a0b4206392e1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_reveal.ml @@ -0,0 +1,839 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2022 Nomadic Labs. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (revelation) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_reveal.ml + Subject: On the reveal operation. +*) + +(** Protocol integration tests for the [Reveal] operation. *) + +open Protocol +open Alpha_context +open Test_tez + +let ten_tez = of_int 10 + +let test_simple_reveal () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then Stdlib.failwith "Unexpected revelation" + in + (* Reveal the contract *) + let* operation = Op.revelation (B blk) new_c.pk in + let* blk = Block.bake blk ~operation in + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if not is_revealed then Stdlib.failwith "New contract revelation failed." + +let test_empty_account_on_reveal () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.Implicit new_c.pkh in + let amount = Tez.one_mutez in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract amount in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expecting fresh pkh" + in + (* Reveal the contract *) + let* operation = Op.revelation ~fee:amount (B blk) new_c.pk in + let* inc = Incremental.begin_construction blk in + let expect_apply_failure = function + | [ + Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract pkh); + ] + when pkh = new_c.pkh -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_apply_failure inc operation in + let* balance = Context.Contract.balance (I inc) new_contract in + let* () = Assert.equal_tez ~loc:__LOC__ balance Tez.zero in + let+ is_revealed = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + if is_revealed then + Stdlib.failwith "Empty account still exists and is revealed." + +let test_not_enough_funds_for_reveal () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 () in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one_mutez in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then Stdlib.failwith "Unexpected revelation" + in + (* Reveal the contract *) + let* operation = Op.revelation ~fee:Tez.fifty_cents (B blk) new_c.pk in + let*! res = Block.bake blk ~operation in + Assert.proto_error_with_info ~loc:__LOC__ res "Balance too low" + +let test_transfer_fees_emptying_after_reveal_batched () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 () in + let new_c = Account.new_account () in + let new_contract = Alpha_context.Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* inc = Incremental.begin_construction blk in + let* reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* tmp_inc = Incremental.add_operation inc reveal in + let* transaction = + Op.transaction ~fee:Tez.one (I tmp_inc) new_contract c Tez.one + in + let* op = + Op.batch_operations ~source:new_contract (I inc) [reveal; transaction] + in + let expect_apply_failure = function + | [ + Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract pkh); + ] + when pkh = new_c.pkh -> + return_unit + | _ -> assert false + in + let* (_inc : Incremental.t) = + Incremental.add_operation ~expect_apply_failure inc op + in + return_unit + +(* We assert that the changes introduced in !5182, splitting the + application of Reveal operations into a pre-checking and + an application phase, do not allow to forge dishonest revelations. *) +let test_reveal_with_fake_account () = + let open Lwt_result_syntax in + let* blk, bootstrap = Context.init1 ~consensus_threshold:0 () in + (* Create two fresh, unrevealed, accounts a and b. *) + let account_a = Account.new_account () in + let a_pkh = account_a.pkh in + let a_contract = Contract.Implicit a_pkh in + let account_b = Account.new_account () in + let b_pkh = account_b.pkh in + let b_contract = Contract.Implicit b_pkh in + (* Assert a and b are fresh.*) + (* TODO tezos/tezos#2996 + + These preambles are too verbose and boilerplate. We should factor + out revealing fresh unrevealed accounts. *) + let* () = + when_ (Signature.Public_key_hash.equal a_pkh b_pkh) (fun () -> + failwith + "Expected different pkhs: got %a %a" + Signature.Public_key_hash.pp + a_pkh + Signature.Public_key_hash.pp + b_pkh) + in + let* oa = Op.transaction (B blk) bootstrap a_contract Tez.one in + let* ob = Op.transaction (B blk) bootstrap b_contract Tez.one in + let* batch = + Op.batch_operations + ~recompute_counters:true + ~source:bootstrap + (B blk) + [oa; ob] + in + let* b = Block.bake blk ~operation:batch in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) a_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) b_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + (* get initial balance of account_a *) + let* a_balance_before = Context.Contract.balance (B b) a_contract in + (* We will attempt to forge a reveal with a fake account that + impersonates account_a but uses account_b's public and secret + keys, e.g. + + fake_a = Account.{pkh = account_a.pkh; pk = account_b.pk; sk = + account_b.sk} + + and we will attempt to reveal the public key of b with a's + pkh. This operation should fail without updating account_a's + balance *) + let* operation = + Op.revelation ~fee:Tez.one_mutez ~forge_pkh:(Some a_pkh) (B b) account_b.pk + in + let* i = Incremental.begin_construction b in + let* i = + Incremental.add_operation + ~expect_failure:(function + | [ + Environment.Ecoproto_error + (Contract_manager_storage.Inconsistent_hash _); + ] -> + return_unit + | errs -> + failwith + "Expected an Contract_manager_storage.Inconsistent_hash error \ + but got %a" + Error_monad.pp_print_trace + errs) + i + operation + in + let* a_balance_after = Context.Contract.balance (I i) a_contract in + unless (Tez.equal a_balance_after a_balance_before) (fun () -> + failwith + "Balance of contract_a should have not changed: expected %atz, got %atz" + Tez.pp + a_balance_before + Tez.pp + a_balance_after) + +(* On the following test, we create an account a, fund it, reveal it, + and get its balance. Then we attempt to forge a reveal for another + account b, using a's pkh. *) +let test_reveal_with_fake_account_already_revealed () = + let open Lwt_result_syntax in + let* blk, bootstrap = Context.init1 ~consensus_threshold:0 () in + (* Create two fresh, unrevealed, accounts a and b. *) + let account_a = Account.new_account () in + let a_pkh = account_a.pkh in + let a_contract = Contract.Implicit a_pkh in + let account_b = Account.new_account () in + let b_pkh = account_b.pkh in + let b_contract = Contract.Implicit b_pkh in + (* Assert a and b are fresh.*) + (* TODO tezos/tezos#2996 + + These preambles are too verbose and boilerplate. We should factor + out revealing fresh unrevealed accounts. *) + let* () = + when_ (Signature.Public_key_hash.equal a_pkh b_pkh) (fun () -> + failwith + "Expected different pkhs: got %a %a" + Signature.Public_key_hash.pp + a_pkh + Signature.Public_key_hash.pp + b_pkh) + in + let* oa = Op.transaction (B blk) bootstrap a_contract Tez.one in + let* ob = Op.transaction (B blk) bootstrap b_contract Tez.one in + let* batch = + Op.batch_operations + ~recompute_counters:true + ~source:bootstrap + (B blk) + [oa; ob] + in + let* b = Block.bake blk ~operation:batch in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) a_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) b_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + (* We first reveal a in a block *) + let* operation = Op.revelation ~fee:Tez.one_mutez (B b) account_a.pk in + let* b = Block.bake ~operation b in + let* a_balance_before = Context.Contract.balance (B b) a_contract in + (* Reveal the public key of b while impersonating account_a. This + operation should fail without updating account_a's balance *) + let* operation = + Op.revelation ~fee:Tez.one_mutez ~forge_pkh:(Some a_pkh) (B b) account_b.pk + in + let* i = Incremental.begin_construction b in + let* i = + Incremental.add_operation + ~expect_failure:(function + | [ + Environment.Ecoproto_error + (Contract_manager_storage.Inconsistent_hash _); + ] -> + return_unit + | errs -> + failwith + "Expected a Previously_revealed_key error but got %a" + Error_monad.pp_print_trace + errs) + i + operation + in + let* a_balance_after = Context.Contract.balance (I i) a_contract in + unless (Tez.equal a_balance_after a_balance_before) (fun () -> + failwith + "Balance of contract_a should have not changed: expected %atz, got %atz" + Tez.pp + a_balance_before + Tez.pp + a_balance_after) + +(* cf: #2386 + + On tezos/tezos!5182 we have reverted the behaviour implemented by + tezos/tezos!587, which explicitly avoided marking reveal operations + as backtracked to reflect the fact that a reveal in a failing batch + did still take effect (cf #338). + + We test that backtracked reveals stay backtracked. *) +let test_backtracked_reveal_in_batch () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* inc = Incremental.begin_construction blk in + let* op_reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* op_transfer = + Op.transaction + ~force_reveal:false + ~fee:Tez.zero + (I inc) + new_contract + new_contract + (Tez.of_mutez_exn 1_000_001L) + in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (I inc) + [op_reveal; op_transfer] + in + let expect_apply_failure = function + | [ + Environment.Ecoproto_error (Contract_storage.Balance_too_low _); + Environment.Ecoproto_error (Tez_repr.Subtraction_underflow _); + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + let* inc = + Incremental.add_operation ~expect_apply_failure inc batched_operation + in + (* We assert the manager key is still unrevealed, as the batch has failed *) + let* revelead = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + when_ revelead (fun () -> + failwith "Unexpected contract revelation: reveal was expected to fail") + +(* Asserts that re-revealing an already revealed manager will make the + whole batch fail. *) +let test_already_revealed_manager_in_batch () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expecting fresh pkh" + in + (* Reveal the contract *) + let* operation = Op.revelation (B blk) new_c.pk in + let* blk = Block.bake blk ~operation in + (* We pack a correct batch of operations attempting to re-reveal the contract *) + let* inc = Incremental.begin_construction blk in + let* op_reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* op_transfer = + Op.transaction + ~force_reveal:false + ~fee:Tez.zero + (I inc) + new_contract + new_contract + (Tez.of_mutez_exn 1_000_001L) + in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (B blk) + [op_reveal; op_transfer] + in + let expect_apply_failure = function + | [ + Environment.Ecoproto_error + (Contract_manager_storage.Previously_revealed_key _); + ] -> + return_unit + | _ -> assert false + in + let* inc = + Incremental.add_operation ~expect_apply_failure inc batched_operation + in + (* We assert the manager key is still revealed. *) + let* revelead = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + unless revelead (fun () -> + Stdlib.failwith + "Unexpected unrevelation: failing batch shouldn't unreveal the manager") + +(* cf: #2386 + + We imitate the behaviour of + + https://tzkt.io/ooSocfx3xxzDo7eFyGu6ZDR1svzMrbaJtBikQanXXhwrqMuWfGz + + which provides evidence of a failing reveal with a gas exhaustion + error due to an incorrect gas limit of 0, which still takes effect + as witnessed by the subsequent (reveal-less) transfer + + https://tzkt.io/opBQQJQ5senPP5v8PfPFf4uVQqKRE5RVjbwx8uD4SqeRs2JGcVw + + This showcases a bad separation of concerns between pre-checking + and the application of manager operations per-se within + [Protocol.Apply.apply_operation]. The situation originated because + [precheck_manager_contents_lists] would reveal the manager by + calling [Protocol.Alpha_context.Contract.reveal_manager_key] before + [prepare_apply_manager_operation_content] has consumed the declared + gas. + + With !5182 we have fixed this situation by revealing the manager + contract at application time. The following test isolates the + failing reveal and asserts that the manager is not revealed after + the failing op. + + As of !5506, the reveal operation does not pass precheck + anyway. Unfortunately, this means that this test has lost some of + its original purpose. Fortunately, {!test_empty_account_on_reveal} + offers a similar scenario to what this test was supposed to do: a + reveal fails during application and we check that the contract is + not revealed afterward. *) +let test_no_reveal_when_gas_exhausted () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Fund the contract with a sufficient balance *) + let* operation = + Op.transaction (B blk) c new_contract (Tez.of_mutez_exn 1_000L) + in + (* Create the contract *) + let* blk = Block.bake blk ~operation in + (* Assert that the account has not been revealed yet *) + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + (* We craft a new (bad) reveal operation with a 0 gas_limit *) + let* op = Op.revelation ~fee:Tez.zero ~gas_limit:Zero (B blk) new_c.pk in + let* inc = Incremental.begin_construction blk in + (* The application of this operation is expected to fail with a + {! Protocol.Raw_context.Operation_quota_exceeded} error *) + let expect_failure = function + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Insufficient_gas_for_manager; + Environment.Ecoproto_error Raw_context.Operation_quota_exceeded; + ] -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_failure inc op in + (* We assert the manager key is still unrevealed, as the operation has failed *) + let* revelead = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + when_ revelead (fun () -> + failwith "Unexpected revelation: reveal operation failed") + +(* Fix #2774 + + We test that reveals can only succeed if they are placed at the + first position in a batch of manager operations, and that moreover + reveal operations occur uniquely in batches. + + - First, [test_reveal_incorrect_position_in_batch] asserts that a + [[transfer; reveal]] batch where a valid reveal follows another + valid op (different from a reveal, so here a transfer) fails with + an [Apply.Incorrect_reveal_position] error. + + - Second, we test a batch consisting of duplicate (potentially) + valid reveal operations. We assert the second reveal to fail again + with an [Apply.Incorrect_reveal_position] error, and for the first + reveal to be backtracked. + + - Then, we test batches with duplicate reveals which follow a + failing one and we assert again the second reveal fails skipped. We + do this for the 3 different reasons a well-placed reveal might fail + (as tested above): gas exhaustion, insolvency, and emptying the + balance while revealing. +*) +let test_reveal_incorrect_position_in_batch () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* inc = Incremental.begin_construction blk in + let* op_transfer = + Op.transaction + ~force_reveal:false + ~fee:Tez.zero + (I inc) + new_contract + new_contract + (Tez.of_mutez_exn 1L) + in + let* op_reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (I inc) + [op_transfer; op_reveal] + in + let expect_failure = function + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_failure inc batched_operation in + (* We assert the manager key is still unrevealed, as the operation has failed *) + let* revelead = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + when_ revelead (fun () -> + failwith "Unexpected revelation: reveal operation was expected to fail") + +(* Test that a batch [reveal pk; reveal pk] where the first reveal + succeeds but the second one results in the second one failing, and + then first reveal being backtracked. *) +let test_duplicate_valid_reveals () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* inc = Incremental.begin_construction blk in + let* op_rev1 = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* op_rev2 = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (I inc) + [op_rev1; op_rev2] + in + let expect_failure = function + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_failure inc batched_operation in + (* We assert the manager key is still unrevealed, as the operation has failed *) + let* revelead = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + when_ revelead (fun () -> + failwith "Unexpected contract revelation: backtracking expected") + +(* Test that a batch [failed_reveal pk; reveal pk] where the first + reveal fails with a gas exhaustion results in the second one + failing due to not being well-placed at the beginnning of the + batch. *) +let test_valid_reveal_after_gas_exhausted_one () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* inc = Incremental.begin_construction blk in + (* We first craft a (bad) reveal operation with a 0 gas_limit *) + let* bad_reveal = + Op.revelation ~fee:Tez.zero ~gas_limit:Zero (B blk) new_c.pk + in + (* While the second is a valid one *) + let* good_reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (I inc) + [bad_reveal; good_reveal] + in + let expect_failure = function + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_failure inc batched_operation in + (* We assert the manager key is still unrevealed, as the batch has failed *) + let+ revealed = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + if revealed then + Stdlib.failwith "Unexpected contract revelation: no valid reveal in batch" + +(* Test that a batch [failed_reveal pk; reveal pk; transfer] where the + first reveal fails with insufficient funds results in the second + one failing due to not being well-placed at the beginnning of the + batch. We add the trailing transfer to ensure covering all branches + of `check_batch_tail_sanity` in `find_manager_public_key` when + calling {!Apply.check_manager_signature} to verify the manager's pk + while processing the second reveal. *) +let test_valid_reveal_after_insolvent_one () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract Tez.one in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then + Stdlib.failwith "Unexpected revelation: expected fresh pkh" + in + let* inc = Incremental.begin_construction blk in + (* We first craft an insolvent reveal operation *) + let* bad_reveal = Op.revelation ~fee:ten_tez (B blk) new_c.pk in + (* While the second is a free valid one *) + let* good_reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* transfer = Op.transaction ~fee:Tez.zero (I inc) new_contract c Tez.one in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (I inc) + [bad_reveal; good_reveal; transfer] + in + let expect_failure = function + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_failure inc batched_operation in + (* We assert the manager key is still unrevealed, as the batch has failed *) + let+ revealed = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + if revealed then + Stdlib.failwith "Unexpected contract revelation: no valid reveal in batch" + +(* Test that a batch [failed_reveal pk; reveal pk] where the first + reveal fails with insufficient funds results in the second one + failing due to not being well-placed at the beginnning of the + batch. *) +let test_valid_reveal_after_emptying_balance () = + let open Lwt_result_syntax in + let* blk, c = Context.init1 ~consensus_threshold:0 () in + let new_c = Account.new_account () in + let new_contract = Contract.Implicit new_c.pkh in + let amount = Tez.one_mutez in + (* Create the contract *) + let* operation = Op.transaction (B blk) c new_contract amount in + let* blk = Block.bake blk ~operation in + let* () = + let+ is_revealed = + Context.Contract.is_manager_key_revealed (B blk) new_contract + in + if is_revealed then Stdlib.failwith "Unexpected revelation" + in + let* inc = Incremental.begin_construction blk in + (* Reveal the contract, spending all its balance in fees *) + let* bad_reveal = Op.revelation ~fee:amount (B blk) new_c.pk in + (* While the second is a free valid one *) + let* good_reveal = Op.revelation ~fee:Tez.zero (I inc) new_c.pk in + let* batched_operation = + Op.batch_operations + ~recompute_counters:true + ~source:new_contract + (I inc) + [bad_reveal; good_reveal] + in + let expect_failure = function + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | _ -> assert false + in + let* inc = Incremental.add_operation ~expect_failure inc batched_operation in + (* We assert the manager key is still unrevealed, as the batch has failed *) + let+ revealed = + Context.Contract.is_manager_key_revealed (I inc) new_contract + in + if revealed then + Stdlib.failwith "Unexpected contract revelation: no valid reveal in batch" + +let tests = + [ + Tztest.tztest "simple reveal" `Quick test_simple_reveal; + Tztest.tztest "empty account on reveal" `Quick test_empty_account_on_reveal; + Tztest.tztest + "not enough funds for reveal" + `Quick + test_not_enough_funds_for_reveal; + Tztest.tztest + "transfer fees emptying balance after reveal in batch" + `Quick + test_transfer_fees_emptying_after_reveal_batched; + Tztest.tztest + "cannot forge reveal with fake keys and signature" + `Quick + test_reveal_with_fake_account; + Tztest.tztest + "cannot re-reveal an account with fake keys and signature" + `Quick + test_reveal_with_fake_account_already_revealed; + Tztest.tztest + "a backtracked reveal in a batch doesn't take effect" + `Quick + test_backtracked_reveal_in_batch; + Tztest.tztest + "cannot re-reveal a manager in a batch" + `Quick + test_already_revealed_manager_in_batch; + Tztest.tztest + "do not reveal when gas exhausted" + `Quick + test_no_reveal_when_gas_exhausted; + Tztest.tztest + "incorrect reveal position in batch" + `Quick + test_reveal_incorrect_position_in_batch; + Tztest.tztest + "cannot duplicate valid reveals in batch" + `Quick + test_duplicate_valid_reveals; + Tztest.tztest + "cannot batch a good reveal after a gas-exhausted one" + `Quick + test_valid_reveal_after_gas_exhausted_one; + Tztest.tztest + "cannot batch a good reveal after an insolvent one" + `Quick + test_valid_reveal_after_insolvent_one; + Tztest.tztest + "cannot batch a good reveal after one emptying account" + `Quick + test_valid_reveal_after_emptying_balance; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("revelation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup.ml new file mode 100644 index 000000000000..37510bf0d86c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup.ml @@ -0,0 +1,3822 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Rollup layer 1 logic + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_sc_rollup.ml + Subject: Test smart contract rollup +*) + +open Protocol +open Alpha_context + +exception Sc_rollup_test_error of string + +let err x = Exn (Sc_rollup_test_error x) + +let assert_fails ~loc ?error m = + let open Lwt_result_syntax in + let*! res = m in + match res with + | Ok _ -> Stdlib.failwith "Expected failure" + | Error err_res -> ( + match (err_res, error) with + | Environment.Ecoproto_error err' :: _, Some err when err = err' -> + (* Matched exact error. *) + return_unit + | Environment.Ecoproto_error err' :: _, Some err -> + let msg = + Format.asprintf + "Expected error [%a] but got [%a] at location %s" + Environment.Error_monad.pp + err' + Environment.Error_monad.pp + err + loc + in + Stdlib.failwith msg + | _, Some _ -> + (* Expected a different error. *) + let msg = + Printf.sprintf "Expected a different error at location %s" loc + in + Stdlib.failwith msg + | _, None -> + (* Any error is ok. *) + return_unit) + +let assert_equal_z ~loc x y = + Assert.equal ~loc Z.equal "Compare Z.t" Z.pp_print x y + +let get_game_status_result incr = + match Incremental.rev_tickets incr with + | [] -> + Stdlib.failwith + "Failed to find an applied operation result in the metadata" + | operations -> ( + List.find_map + (function + | Apply_results.Operation_metadata + { + contents = + Single_result + (Manager_operation_result + {operation_result = Applied op; _}); + } -> ( + match op with + | Sc_rollup_refute_result {game_status; _} -> + Some (game_status, `Refute) + | Sc_rollup_timeout_result {game_status; _} -> + Some (game_status, `Timeout) + | _ -> None) + | _ -> None) + operations + |> function + | None -> + Stdlib.failwith + "No operation [Sc_rollup_refute_result] or \ + [Sc_rollup_timeout_result] found" + | Some x -> x) + +let assert_equal_game_status ?game_status actual_game_status = + let open Lwt_result_syntax in + match game_status with + | None -> return_unit + | Some game_status -> + if game_status = actual_game_status then return_unit + else + let msg = + Format.asprintf + "Expected game status [%a] but got [%a]" + Sc_rollup.Game.pp_status + game_status + Sc_rollup.Game.pp_status + actual_game_status + in + Stdlib.failwith msg + +let assert_game_exists incr rollup game_index ~exists = + let open Lwt_result_wrap_syntax in + let ctxt = Incremental.alpha_ctxt incr in + let*@ _ctxt, game_opt = + Sc_rollup.Refutation_storage.find_game ctxt rollup game_index + in + match game_opt with + | Some _ when exists -> return_unit + | Some _ -> Stdlib.failwith "Found game but expected no game." + | None when not exists -> return_unit + | None -> Stdlib.failwith "No game game but expected one." + +let assert_refute_result ?game_status incr rollup game_index = + let open Lwt_result_syntax in + let* () = assert_game_exists incr rollup game_index ~exists:false in + let actual_game_status, op_type = get_game_status_result incr in + assert (op_type = `Refute) ; + assert_equal_game_status ?game_status actual_game_status + +let assert_timeout_result ?game_status incr rollup game_index = + let open Lwt_result_syntax in + let* () = assert_game_exists incr rollup game_index ~exists:false in + let actual_game_status, op_type = get_game_status_result incr in + assert (op_type = `Timeout) ; + assert_equal_game_status ?game_status actual_game_status + +let bake_timeout_period ?timeout_period_in_blocks block = + let open Lwt_result_syntax in + let* timeout_period_in_blocks = + match timeout_period_in_blocks with + | Some v -> return v + | None -> + let* constants = Context.get_constants (B block) in + let Constants.Parametric.{timeout_period_in_blocks; _} = + constants.parametric.sc_rollup + in + return timeout_period_in_blocks + in + Block.bake_n timeout_period_in_blocks block + +(** [context_init tup] initializes a context and returns the created + context and contracts. *) +let context_init ?commitment_period_in_blocks + ?(sc_rollup_challenge_window_in_blocks = 10) + ?(timeout_period_in_blocks = 10) ?hard_gas_limit_per_operation + ?hard_gas_limit_per_block tup = + Context.init_with_constants_gen + tup + { + Context.default_test_constants with + consensus_threshold = 0; + hard_gas_limit_per_operation = + Option.value + hard_gas_limit_per_operation + ~default:Context.default_test_constants.hard_gas_limit_per_operation; + hard_gas_limit_per_block = + Option.value + hard_gas_limit_per_block + ~default:Context.default_test_constants.hard_gas_limit_per_block; + sc_rollup = + { + Context.default_test_constants.sc_rollup with + arith_pvm_enable = true; + private_enable = true; + challenge_window_in_blocks = sc_rollup_challenge_window_in_blocks; + commitment_period_in_blocks = + Option.value + ~default: + Context.default_test_constants.sc_rollup + .commitment_period_in_blocks + commitment_period_in_blocks; + timeout_period_in_blocks; + }; + } + +(** [test_disable_arith_pvm_feature_flag ()] tries to originate a Arith smart + rollup when the Arith PVM feature flag is deactivated and checks that it + fails. *) +let test_disable_arith_pvm_feature_flag () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 ~sc_rollup_arith_pvm_enable:false () in + let* i = Incremental.begin_construction b in + let kind = Sc_rollup.Kind.Example_arith in + let* op, _ = Sc_rollup_helpers.origination_op (B b) contract kind in + let expect_failure = function + | Environment.Ecoproto_error + (Validate_errors.Manager.Sc_rollup_arith_pvm_disabled as e) + :: _ -> + Assert.test_error_encodings e ; + return_unit + | _ -> failwith "It should have failed with [Sc_rollup_arith_pvm_disabled]" + in + let* (_ : Incremental.t) = Incremental.add_operation ~expect_failure i op in + return_unit + +(** [test_disable_riscv_pvm_feature_flag ()] tries to originate a Riscv smart + rollup when the Riscv PVM feature flag is deactivated and checks that it + fails. *) +let test_disable_riscv_pvm_feature_flag () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 ~sc_rollup_riscv_pvm_enable:false () in + let* i = Incremental.begin_construction b in + let kind = Sc_rollup.Kind.Riscv in + let* op, _ = Sc_rollup_helpers.origination_op (B b) contract kind in + let expect_failure = function + | Environment.Ecoproto_error + (Validate_errors.Manager.Sc_rollup_riscv_pvm_disabled as e) + :: _ -> + Assert.test_error_encodings e ; + return_unit + | _ -> failwith "It should have failed with [Sc_rollup_riscv_pvm_disabled]" + in + let* (_ : Incremental.t) = Incremental.add_operation ~expect_failure i op in + return_unit + +(** Initializes the context and originates a SCORU. *) +let sc_originate ?boot_sector ?parameters_ty ?whitelist block contract = + let open Lwt_result_syntax in + let kind = Sc_rollup.Kind.Example_arith in + let* operation, rollup = + Sc_rollup_helpers.origination_op + ?boot_sector + ?parameters_ty + ?whitelist + (B block) + contract + kind + in + let* block = Block.bake ~operation block in + return (block, rollup) + +(** Initializes the context and originates a SCORU. *) +let init_and_originate ?boot_sector ?parameters_ty ?commitment_period_in_blocks + ?sc_rollup_challenge_window_in_blocks tup = + let open Lwt_result_syntax in + let* block, contracts = + context_init + ?commitment_period_in_blocks + ?sc_rollup_challenge_window_in_blocks + tup + in + let contract = Context.tup_hd tup contracts in + let* block, rollup = + sc_originate ?boot_sector ?parameters_ty block contract + in + return (block, contracts, rollup) + +let number_of_ticks_exn n = + match Sc_rollup.Number_of_ticks.of_value n with + | Some x -> x + | None -> Stdlib.failwith "Bad Number_of_ticks" + +let next_inbox_level ?predecessor ctxt rollup = + let open Lwt_result_syntax in + let* genesis_info = Context.Sc_rollup.genesis_info ctxt rollup in + let+ constants = Context.get_constants ctxt in + let commitment_freq = + constants.parametric.sc_rollup.commitment_period_in_blocks + in + let pred_level = + Option.fold + ~none:genesis_info.level + ~some:(fun pred -> pred.Sc_rollup.Commitment.inbox_level) + predecessor + in + Raw_level.Internal_for_tests.add pred_level commitment_freq + +let dummy_commitment ?predecessor ?compressed_state ?(number_of_ticks = 3000L) + ?inbox_level ctxt rollup = + let open Lwt_result_syntax in + let* genesis_info = Context.Sc_rollup.genesis_info ctxt rollup in + let predecessor_hash = + match predecessor with + | Some pred -> Sc_rollup.Commitment.hash_uncarbonated pred + | None -> genesis_info.commitment_hash + in + let* compressed_state = + match compressed_state with + | None -> + let* {compressed_state; _} = + Context.Sc_rollup.commitment ctxt rollup predecessor_hash + in + return compressed_state + | Some compressed_state -> return compressed_state + in + let* inbox_level = + match inbox_level with + | Some inbox_level -> return inbox_level + | None -> next_inbox_level ?predecessor ctxt rollup + in + return + Sc_rollup.Commitment. + { + predecessor = predecessor_hash; + inbox_level; + number_of_ticks = number_of_ticks_exn number_of_ticks; + compressed_state; + } + +(* Bakes blocks to satisfy requirement of next_commitment.inbox_level <= current_level *) +let bake_blocks_until_next_inbox_level ?predecessor block rollup = + let open Lwt_result_syntax in + let* next_level = next_inbox_level ?predecessor (B block) rollup in + Block.bake_until_level next_level block + +let bake_blocks_until_inbox_level block commitment = + Block.bake_until_level commitment.Sc_rollup.Commitment.inbox_level block + +let publish_op_and_dummy_commitment ~sender ?compressed_state ?predecessor + rollup block = + let open Lwt_result_syntax in + let compressed_state = + Option.map + (fun s -> + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string [s])) + compressed_state + in + let* commitment = + dummy_commitment ?compressed_state ?predecessor (B block) rollup + in + let* publish = Op.sc_rollup_publish (B block) sender rollup commitment in + return (publish, commitment) + +(* Verify that parameters and unparsed parameters match. *) +let verify_params ctxt ~parameters_ty ~parameters ~unparsed_parameters = + let open Lwt_result_wrap_syntax in + let show exp = Expr.to_string @@ exp in + let unparse ctxt parameters = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized + parameters_ty + parameters + in + let*@ unparsed_parameters, ctxt = + (* Make sure we can parse the unparsed-parameters with the given parameters + type. *) + let* parsed_unparsed_parameters, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:true ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + parameters_ty + (Environment.Micheline.root unparsed_parameters) + in + (* Un-parse again to get back to Micheline. *) + unparse ctxt parsed_unparsed_parameters + in + (* Un-parse the parsed parameters. *) + let*@ expected_unparsed_parameters, _ctxt = unparse ctxt parameters in + (* Verify that both version match. *) + Assert.equal_string + ~loc:__LOC__ + (show unparsed_parameters) + (show expected_unparsed_parameters) + +(* Verify that the given list of transactions and transaction operations match. + Also checks each transaction operation for type mismatches etc. *) +let verify_execute_outbox_message_operations ctxt rollup ~loc ~operations + ~expected_transactions = + let open Lwt_result_wrap_syntax in + let* incr = + Context.( + match ctxt with + | I incr -> return incr + | B block -> Incremental.begin_construction block) + in + let alpha_ctxt = Incremental.alpha_ctxt incr in + let validate_and_extract_operation_params ctxt op = + match op with + | Script_typed_ir.Internal_operation + { + sender = op_sender; + operation = + Transaction_to_smart_contract + { + destination; + amount; + entrypoint; + location = _; + parameters_ty; + parameters; + unparsed_parameters; + }; + nonce = _; + } -> + (* Check that the parameters match. *) + let* () = + verify_params ctxt ~parameters_ty ~parameters ~unparsed_parameters + in + let* () = + (* Check that the senders match. *) + Assert.equal_string + ~loc + (Destination.to_b58check (Sc_rollup rollup)) + (Destination.to_b58check op_sender) + in + (* Assert that the amount is 0. *) + let* () = Assert.equal_tez ~loc amount Tez.zero in + (* Load the arg-type and entrypoints of the destination script. *) + let* ( Script_ir_translator.Ex_script (Script {arg_type; entrypoints; _}), + ctxt ) = + let*@ ctxt, _cache_key, cached = Script_cache.find ctxt destination in + match cached with + | Some (_script, ex_script) -> return (ex_script, ctxt) + | None -> failwith "Could not load script at %s" loc + in + (* Find the script parameters ty of the script. *) + let*?@ entrypoint_res, ctxt = + Gas_monad.run + ctxt + (Script_ir_translator.find_entrypoint + ~error_details:(Informative ()) + arg_type + entrypoints + entrypoint) + in + let*?@ (Ex_ty_cstr {ty = script_parameters_ty; _}) = entrypoint_res in + (* Check that the script parameters type matches the one from the + transaction. *) + let*?@ ctxt = + let open Result_syntax in + let* eq, ctxt = + Gas_monad.run + ctxt + (Script_ir_translator.ty_eq + ~error_details:(Informative (-1)) + script_parameters_ty + parameters_ty) + in + let+ Eq = eq in + ctxt + in + return (ctxt, (destination, entrypoint, unparsed_parameters)) + | _ -> + failwith + "Expected an internal transaction operation to a smart-contract, \ + called from %s" + loc + in + let* _alpha_ctxt, operations_data = + List.fold_left_map_es + validate_and_extract_operation_params + alpha_ctxt + operations + in + let compare_data (d1, e1, p1) (d2, e2, p2) = + Contract_hash.equal d1 d2 + && Entrypoint_repr.(e1 = e2) + && String.equal (Expr.to_string p1) (Expr.to_string p2) + in + let pp_data fmt (d, e, p) = + Format.fprintf + fmt + "(%a, %a, %s)" + Contract_hash.pp + d + Entrypoint_repr.pp + e + (Expr.to_string p) + in + let transactions_data = + let data_of_transaction (contract, entrypoint, params) = + let params = Expr.from_string params in + (contract, entrypoint, params) + in + List.map data_of_transaction expected_transactions + in + Assert.assert_equal_list + ~loc + compare_data + "Compare operations data" + pp_data + operations_data + transactions_data + +let verify_whitelist ~loc ~expected_whitelist rollup ctxt = + let open Lwt_result_syntax in + let* found_whitelist = Context.Sc_rollup.whitelist ctxt rollup in + let sort_whitelist = + Option.map (List.sort Signature.Public_key_hash.compare) + in + let found_sorted = sort_whitelist found_whitelist in + let expected_sorted = sort_whitelist expected_whitelist in + Assert.(assert_equal_list_opt ~loc Signature.Public_key_hash.equal) + "whitelist" + Signature.Public_key_hash.pp + expected_sorted + found_sorted + +(* Helper functions to create output used for executing outbox messages. *) +let make_output ~outbox_level ~message_index message = + let outbox_level = Raw_level.of_int32_exn (Int32.of_int outbox_level) in + let message_index = Z.of_int message_index in + Sc_rollup.{outbox_level; message_index; message} + +let make_transaction_output ~outbox_level ~message_index transactions = + let transactions = + List.map + (fun (destination, entrypoint, parameters) -> + let unparsed_parameters = Expr.from_string parameters in + {Sc_rollup.Outbox.Message.unparsed_parameters; destination; entrypoint}) + transactions + in + let message = + Sc_rollup.Outbox.Message.Atomic_transaction_batch {transactions} + in + make_output ~outbox_level ~message_index message + +let make_whitelist_update_output ~outbox_level ~message_index + (whitelist_opt : Sc_rollup.Whitelist.t option) = + make_output ~outbox_level ~message_index + @@ Sc_rollup.Outbox.Message.Whitelist_update whitelist_opt + +let string_ticket_token ticketer content = + let open Lwt_result_wrap_syntax in + let contents = + Result.value_f ~default:(fun _ -> assert false) + @@ Script_string.of_string content + in + let*?@ ticketer = Contract.of_b58check ticketer in + return + (Ticket_token.Ex_token + {ticketer; contents_type = Script_typed_ir.string_t; contents}) + +let originate_contract block ~script ~baker ~storage ~source_contract = + let open Lwt_result_syntax in + let* contract, _, block = + Contract_helpers.originate_contract_from_string_hash + ~script + ~storage + ~source_contract + ~baker + block + in + return (contract, block) + +let hash_commitment commitment = + Sc_rollup.Commitment.hash_uncarbonated commitment + +let publish_commitment source rollup block commitment = + let open Lwt_result_syntax in + let* block = bake_blocks_until_inbox_level block commitment in + let* operation = Op.sc_rollup_publish (B block) source rollup commitment in + Block.bake ~operation block + +let publish_commitments block source rollup commitments = + List.fold_left_es (publish_commitment source rollup) block commitments + +let cement_commitment ?challenge_window_in_blocks block rollup staker = + let open Lwt_result_syntax in + let* challenge_window_in_blocks = + match challenge_window_in_blocks with + | Some x -> return x + | None -> + let* constants = Context.get_constants (B block) in + return constants.parametric.sc_rollup.challenge_window_in_blocks + in + let* block = Block.bake_n challenge_window_in_blocks block in + let* cement = Op.sc_rollup_cement (B block) staker rollup in + Block.bake ~operation:cement block + +let cement_commitments ?challenge_window_in_blocks block rollup staker hashes = + (* [hashes] is useful to know the number of commitments we expect to cement. *) + List.fold_left_es + (fun block _hash -> + cement_commitment ?challenge_window_in_blocks block rollup staker) + block + hashes + +let publish_and_cement_commitment block ~originator rollup commitment = + let open Lwt_result_wrap_syntax in + let* block = publish_commitment originator rollup block commitment in + let* constants = Context.get_constants (B block) in + let* block = + Block.bake_n constants.parametric.sc_rollup.challenge_window_in_blocks block + in + let hash = hash_commitment commitment in + let* cement_op = Op.sc_rollup_cement (B block) originator rollup in + let* block = Block.bake ~operation:cement_op block in + return (hash, block) + +let publish_and_cement_commitments block ~originator rollup commitments = + let open Lwt_result_syntax in + List.fold_left_es + (fun block commitment -> + let* _hash, block = + publish_and_cement_commitment block ~originator rollup commitment + in + return block) + block + commitments + +let publish_and_cement_dummy_commitment block ~originator rollup = + let open Lwt_result_syntax in + let* commitment = dummy_commitment (B block) rollup in + publish_and_cement_commitment block ~originator rollup commitment + +(* Publishes repeated cemented commitments until a commitment with + [inbox_level >= min_inbox_level] is found (such a commitment + is also published and cemented). *) +let publish_commitments_until_min_inbox_level block rollup ~originator + ~min_inbox_level ~cemented_commitment_hash ~cemented_commitment = + let rec aux block hash ({Sc_rollup.Commitment.inbox_level; _} as commitment) = + let open Lwt_result_syntax in + let level = Raw_level.to_int32 inbox_level in + if level >= Int32.of_int min_inbox_level then return (hash, block) + else + let* commitment = + dummy_commitment ~predecessor:commitment (B block) rollup + in + let* hash, block = + publish_and_cement_commitment block ~originator rollup commitment + in + aux block hash commitment + in + aux block cemented_commitment_hash cemented_commitment + +let adjust_ticket_token_balance_of_rollup block rollup ticket_token ~delta = + let open Lwt_result_syntax in + let* incr = Incremental.begin_construction block in + let alpha_ctxt = Incremental.alpha_ctxt incr in + let* hash, alpha_ctxt = + Ticket_helpers.adjust_ticket_token_balance + alpha_ctxt + (Destination.Sc_rollup rollup) + ticket_token + ~delta + in + let incr = Incremental.set_alpha_ctxt incr alpha_ctxt in + let* block = Incremental.finalize_block incr in + return (hash, block) + +(** A version of execute outbox message that output ignores proof validation. *) +let execute_outbox_message_without_proof_validation block rollup + ~cemented_commitment outbox_message = + let open Lwt_result_wrap_syntax in + let* incr = Incremental.begin_construction block in + let*@ res, alpha_ctxt = + Sc_rollup_operations.Internal_for_tests.execute_outbox_message + (Incremental.alpha_ctxt incr) + ~validate_and_decode_output_proof: + (fun ctxt ~cemented_commitment:_ _rollup ~output_proof:_ -> + return (outbox_message, ctxt)) + rollup + ~cemented_commitment + ~output_proof:"Not used" + in + let incr = Incremental.set_alpha_ctxt incr alpha_ctxt in + let* block = Incremental.finalize_block incr in + return (res, block) + +let execute_outbox_message block ~originator rollup ~output_proof + ~commitment_hash = + let open Lwt_result_syntax in + let* batch_op = + Op.sc_rollup_execute_outbox_message + (B block) + originator + rollup + commitment_hash + ~output_proof + in + Block.bake ~operation:batch_op block + +let assert_ticket_token_balance ~loc ctxt token owner expected = + let open Lwt_result_wrap_syntax in + let* incr = + Context.( + match ctxt with + | I incr -> return incr + | B block -> Incremental.begin_construction block) + in + let alpha_ctxt = Incremental.alpha_ctxt incr in + let*@ balance, _ = + let* key_hash, ctxt = + Ticket_balance_key.of_ex_token alpha_ctxt ~owner token + in + Ticket_balance.get_balance ctxt key_hash + in + match (balance, expected) with + | Some b, Some e -> Assert.equal_int ~loc (Z.to_int b) e + | Some b, None -> + failwith "%s: Expected no balance but got some %d" loc (Z.to_int b) + | None, Some b -> failwith "%s: Expected balance %d but got none" loc b + | None, None -> return_unit + +(** Assert that the computation fails with the given message. *) +let assert_fails_with ~__LOC__ k expected_err = + let open Lwt_result_syntax in + let*! res = k in + Assert.proto_error ~loc:__LOC__ res (( = ) expected_err) + +let verify_can_publish_commit ~__LOC__ ~succeed rollup account block = + let open Lwt_result_syntax in + let* dummy_commitment = dummy_commitment (B block) rollup in + let block_res = publish_commitment account rollup block dummy_commitment in + if succeed then + let* _block = block_res in + return_unit + else + assert_fails_with + ~__LOC__ + block_res + Sc_rollup_errors.Sc_rollup_staker_not_in_whitelist + +type balances = {liquid : Tez.t; frozen : Tez.t} + +let balances ctxt contract = + let open Lwt_result_syntax in + let* liquid = Context.Contract.balance ctxt contract in + let* frozen = Context.Contract.frozen_bonds ctxt contract in + return {liquid; frozen} + +let check_balances_evolution bal_before {liquid; frozen} ~action = + let open Lwt_result_wrap_syntax in + let* {liquid = expected_liquid; frozen = expected_frozen} = + match action with + | `Freeze amount -> + let*?@ liquid = Tez.( -? ) bal_before.liquid amount in + let*?@ frozen = Tez.( +? ) bal_before.frozen amount in + return {liquid; frozen} + | `Unfreeze amount -> + let*?@ liquid = Tez.( +? ) bal_before.liquid amount in + let*?@ frozen = Tez.( -? ) bal_before.frozen amount in + return {liquid; frozen} + in + let* () = Assert.equal_tez ~loc:__LOC__ expected_liquid liquid in + let* () = Assert.equal_tez ~loc:__LOC__ expected_frozen frozen in + return_unit + +(* Generates a list of cemented dummy commitments. *) +let gen_commitments ctxt rollup ~predecessor ~num_commitments = + let open Lwt_result_syntax in + let* constants = Context.get_constants ctxt in + let delta = constants.parametric.sc_rollup.commitment_period_in_blocks in + let rec aux predecessor n acc = + if n <= 0 then return (List.rev acc) + else + let inbox_level = + Raw_level.Internal_for_tests.add + predecessor.Sc_rollup.Commitment.inbox_level + delta + in + let* commitment = + dummy_commitment + ~predecessor + ~inbox_level + ~compressed_state:predecessor.compressed_state + ctxt + rollup + in + let hash = Sc_rollup.Commitment.hash_uncarbonated commitment in + aux commitment (n - 1) ((commitment, hash) :: acc) + in + aux predecessor num_commitments [] + +let attempt_to_recover_bond ?policy block contract ?staker rollup = + let open Lwt_result_syntax in + (* Recover its own bond by default. *) + let staker = + match staker with + | Some staker -> staker + | None -> Account.pkh_of_contract_exn contract + in + let* recover_bond_op = + Op.sc_rollup_recover_bond (B block) contract rollup staker + in + Block.bake ?policy ~operation:recover_bond_op block + +let recover_bond_not_lcc block contract rollup = + assert_fails_with + ~__LOC__ + (attempt_to_recover_bond block contract rollup) + Sc_rollup_errors.Sc_rollup_not_staked_on_lcc_or_ancestor + +let recover_bond_not_staked block contract rollup = + assert_fails_with + ~__LOC__ + (attempt_to_recover_bond block contract rollup) + Sc_rollup_errors.Sc_rollup_not_staked + +let recover_bond_with_success ?policy block contract rollup = + let open Lwt_result_syntax in + let* bal_before = balances (B block) contract in + let* b = attempt_to_recover_bond ?policy block contract rollup in + let* bal_after = balances (B b) contract in + let* constants = Context.get_constants (B b) in + let* () = + check_balances_evolution + bal_before + bal_after + ~action:(`Unfreeze constants.parametric.sc_rollup.stake_amount) + in + return b + +(** [test_publish_cement_and_recover_bond] creates a rollup, publishes a + commitment and then [challenge_window_in_blocks] blocks later cements + that commitment. + The comitter tries to withdraw stake before and after cementing. Only the + second attempt is expected to succeed. *) +let test_publish_cement_and_recover_bond () = + let open Lwt_result_wrap_syntax in + let* block, contracts, rollup = init_and_originate Context.T2 in + let _, contract = contracts in + let* block = bake_blocks_until_next_inbox_level block rollup in + (* not staked yet *) + let* () = recover_bond_not_staked block contract rollup in + let* c = dummy_commitment (B block) rollup in + let* operation = Op.sc_rollup_publish (B block) contract rollup c in + let* b = Block.bake ~operation block in + let* constants = Context.get_constants (B b) in + let* b = + Block.bake_n constants.parametric.sc_rollup.challenge_window_in_blocks b + in + (* stake not on LCC *) + let* () = recover_bond_not_lcc b contract rollup in + let* cement_op = Op.sc_rollup_cement (B b) contract rollup in + let* b = Block.bake ~operation:cement_op b in + (* recover bond should succeed *) + let* b = + recover_bond_with_success + (* We forbid the stake owner from baker to correctly check the + unfrozen amount below. *) + ~policy:(Excluding [Account.pkh_of_contract_exn contract]) + b + contract + rollup + in + (* not staked anymore *) + let* () = recover_bond_not_staked b contract rollup in + return_unit + +(** [test_publish_fails_on_double_stake] creates a rollup and then + publishes two different commitments with the same staker. We check + that the second publish fails. *) +let test_publish_fails_on_double_stake () = + let open Lwt_result_syntax in + let* block, contracts, rollup = init_and_originate Context.T2 in + let* block = bake_blocks_until_next_inbox_level block rollup in + let _, contract = contracts in + let* commitment1 = dummy_commitment (B block) rollup in + let commitment2 = + {commitment1 with number_of_ticks = number_of_ticks_exn 3001L} + in + let* operation1 = + Op.sc_rollup_publish (B block) contract rollup commitment1 + in + let* block = Block.bake ~operation:operation1 block in + let* operation2 = + Op.sc_rollup_publish (B block) contract rollup commitment2 + in + assert_fails_with + ~__LOC__ + (Block.bake ~operation:operation2 block) + Sc_rollup_errors.Sc_rollup_staker_double_stake + +(** [test_cement_fails_on_conflict] creates a rollup and then publishes + two different commitments. It waits 20 blocks and then attempts to + cement one of the commitments; it checks that this fails because the + commitment is contested. *) +let test_cement_fails_on_conflict () = + let open Lwt_result_wrap_syntax in + let* b, contracts, rollup = init_and_originate Context.T3 in + let* b = bake_blocks_until_next_inbox_level b rollup in + let _, contract1, contract2 = contracts in + let* commitment1 = dummy_commitment (B b) rollup in + let commitment2 = + {commitment1 with number_of_ticks = number_of_ticks_exn 3001L} + in + let* operation1 = Op.sc_rollup_publish (B b) contract1 rollup commitment1 in + let* b = Block.bake ~operation:operation1 b in + let* operation2 = Op.sc_rollup_publish (B b) contract2 rollup commitment2 in + let* b = Block.bake ~operation:operation2 b in + let* constants = Context.get_constants (B b) in + let* b = + Block.bake_n constants.parametric.sc_rollup.challenge_window_in_blocks b + in + let* cement_op = Op.sc_rollup_cement (B b) contract1 rollup in + let block_res = Block.bake ~operation:cement_op b in + assert_fails_with ~__LOC__ block_res Sc_rollup_errors.Sc_rollup_disputed + +let commit_and_cement_after_n_bloc ?expected_error b contract rollup n = + let open Lwt_result_wrap_syntax in + let* b = bake_blocks_until_next_inbox_level b rollup in + let* commitment = dummy_commitment (B b) rollup in + let* operation = Op.sc_rollup_publish (B b) contract rollup commitment in + let* b = Block.bake ~operation b in + (* This pattern would add an additional block, so we decrement [n] by one. *) + let* b = Block.bake_n (n - 1) b in + let* cement_op = Op.sc_rollup_cement (B b) contract rollup in + let block = Block.bake ~operation:cement_op b in + match expected_error with + | Some error -> assert_fails_with ~__LOC__ block error + | None -> + let* _block = block in + return_unit + +(** [test_challenge_window_period_boundaries] checks that cementing a commitment + without waiting for the whole challenge window period fails. Whereas, + succeeds when the period is over. *) +let test_challenge_window_period_boundaries () = + let commitment_period_in_blocks = 10 in + let sc_rollup_challenge_window_in_blocks = 10 in + let open Lwt_result_syntax in + let* block, contract, rollup = + init_and_originate + ~commitment_period_in_blocks + ~sc_rollup_challenge_window_in_blocks + Context.T1 + in + (* Should fail because the waiting period is not strictly greater than the + challenge window period. *) + let* () = + let*? current_level = Context.get_level (B block) in + let level_of_cement_submit = + Int32.to_int (Raw_level.to_int32 current_level) + + commitment_period_in_blocks + sc_rollup_challenge_window_in_blocks + |> Int32.of_int |> Raw_level_repr.of_int32_exn + in + let min_level = Raw_level_repr.succ level_of_cement_submit in + commit_and_cement_after_n_bloc + ~expected_error: + (Sc_rollup_errors.Sc_rollup_commitment_too_recent + {current_level = level_of_cement_submit; min_level}) + block + contract + rollup + (sc_rollup_challenge_window_in_blocks - 1) + in + (* Succeeds because the challenge period is over. *) + let* () = + commit_and_cement_after_n_bloc + block + contract + rollup + sc_rollup_challenge_window_in_blocks + in + return_unit + +(** Test originating with bad type. *) +let test_originating_with_invalid_types () = + let open Lwt_result_syntax in + let* block, (contract, _, _) = context_init Context.T3 in + let assert_fails_for_type parameters_ty = + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_operations.Sc_rollup_invalid_parameters_type + (sc_originate block contract ~parameters_ty) + in + (* Following types fail at validation time. *) + let* () = + [ + "mutez"; + "big_map string nat"; + "contract string"; + "sapling_state 2"; + "sapling_transaction 2"; + "lambda string nat"; + "or (nat %deposit) (string %name)"; + ] + |> List.iter_es assert_fails_for_type + in + (* Operation fails with a different error as it's not "passable". *) + assert_fails + ~loc:__LOC__ + (sc_originate block contract ~parameters_ty:"operation") + +let assert_equal_expr ~loc e1 e2 = + let s1 = Format.asprintf "%a" Michelson_v1_printer.print_expr e1 in + let s2 = Format.asprintf "%a" Michelson_v1_printer.print_expr e2 in + Assert.equal_string ~loc s1 s2 + +let test_originating_with_valid_type () = + let open Lwt_result_wrap_syntax in + let* block, contract = context_init Context.T1 in + let assert_parameters_ty parameters_ty = + let* block, rollup = sc_originate block contract ~parameters_ty in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let*@ expr, _ctxt = Sc_rollup.parameters_type ctxt rollup in + let expr = WithExceptions.Option.get ~loc:__LOC__ expr in + let*?@ expr, _ctxt = + Script.force_decode_in_context + ~consume_deserialization_gas:When_needed + ctxt + expr + in + assert_equal_expr ~loc:__LOC__ (Expr.from_string parameters_ty) expr + in + [ + "unit"; + "int"; + "nat"; + "signature"; + "string"; + "bytes"; + "key_hash"; + "key"; + "timestamp"; + "address"; + "bls12_381_fr"; + "bls12_381_g1"; + "bls12_381_g2"; + "bool"; + "never"; + "chain_id"; + "ticket string"; + "set nat"; + "option (ticket string)"; + "list nat"; + "pair nat unit"; + "or nat string"; + "map string int"; + "map (option (pair nat string)) (list (ticket nat))"; + ] + |> List.iter_es assert_parameters_ty + +(* A contract that receives a pair of nat and a ticket and stores the ticket + with previously stored tickets. *) +let ticket_receiver = + {| + { parameter (pair nat (ticket string)); + storage (list (ticket string)); + code { UNPAIR; # [(nat, ticket) ; list] + CDR; # [ticket ; list] + CONS; # [ticket :: list] + NIL operation ; # [[] ; ticket :: list] + PAIR; # [([], ticket :: list)] + } + } + |} + +(* A contract that receives a string. *) +let string_receiver = + {| + { parameter string; + storage string; + code { CDR ; NIL operation; PAIR } } + |} + +(* A contract that receives a mutez. *) +let mutez_receiver = + {| + { parameter mutez; + storage mutez; + code { CDR ; NIL operation; PAIR } } + |} + +let test_single_transaction_batch () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* ticket_receiver, block = + originate_contract + block + ~script:ticket_receiver + ~storage:"{}" + ~source_contract:originator + ~baker + in + (* Ticket-token with content "red". *) + let* red_token = + string_ticket_token "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + (* Create an atomic batch message. *) + let transactions = + [ + ( ticket_receiver, + Entrypoint.default, + {|Pair 42 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1)|} ); + ] + in + let output = + make_transaction_output ~outbox_level:0 ~message_index:0 transactions + in + (* Set up the balance so that the self contract owns one ticket. *) + let* _ticket_hash, block = + adjust_ticket_token_balance_of_rollup block rollup red_token ~delta:Z.one + in + let* Sc_rollup_operations.{operations; _}, block = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output + in + (* Confirm that each transaction maps to one operation. *) + let* () = + verify_execute_outbox_message_operations + ~loc:__LOC__ + (B block) + rollup + ~operations + ~expected_transactions:transactions + in + (* Verify that the balance has moved to ticket-receiver. *) + let* () = + assert_ticket_token_balance + ~loc:__LOC__ + (B block) + red_token + (Destination.Sc_rollup rollup) + None + in + assert_ticket_token_balance + ~loc:__LOC__ + (B block) + red_token + (Destination.Contract (Originated ticket_receiver)) + (Some 1) + +(** Test that checks that an outbox message can be executed against all stored + cemented commitments but not against an outdated one. *) +let test_older_cemented_commitment () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* ticket_receiver, block = + originate_contract + block + ~script:ticket_receiver + ~storage:"{}" + ~source_contract:originator + ~baker + in + (* Ticket-token with content "red". *) + let* red_token = + string_ticket_token "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" + in + let verify_outbox_message_execution block cemented_commitment = + (* Set up the balance so that the self contract owns one ticket. *) + let* _ticket_hash, block = + adjust_ticket_token_balance_of_rollup block rollup red_token ~delta:Z.one + in + (* Create an atomic batch message. *) + let transactions = + [ + ( ticket_receiver, + Entrypoint.default, + {|Pair 42 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1)|} ); + ] + in + let output = + make_transaction_output ~outbox_level:0 ~message_index:0 transactions + in + let* Sc_rollup_operations.{operations; _}, block = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output + in + (* Confirm that each transaction maps to one operation. *) + let* () = + verify_execute_outbox_message_operations + ~loc:__LOC__ + (B block) + rollup + ~operations + ~expected_transactions:transactions + in + (* Verify that the balance has moved to ticket-receiver. *) + let* () = + assert_ticket_token_balance + ~loc:__LOC__ + (B block) + red_token + (Destination.Sc_rollup rollup) + None + in + assert_ticket_token_balance + ~loc:__LOC__ + (B block) + red_token + (Destination.Contract (Originated ticket_receiver)) + (Some 1) + in + let* max_num_stored_cemented_commitments = + let* constants = Context.get_constants (B block) in + return + constants.parametric.sc_rollup.max_number_of_stored_cemented_commitments + in + (* Publish and cement a commitment. *) + let* first_commitment_hash, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + let* first_commitment = + Context.Sc_rollup.commitment (B block) rollup first_commitment_hash + in + (* Generate a list of commitments that exceed the maximum number of stored + ones by one. *) + let* commitments_and_hashes = + gen_commitments + (B block) + rollup + ~predecessor:first_commitment + ~num_commitments:(max_num_stored_cemented_commitments + 1) + in + let commitments, commitment_hashes = List.split commitments_and_hashes in + let* block = + publish_and_cement_commitments block ~originator rollup commitments + in + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/4469 + The test actually do not test the good "too old" commitment. *) + let commitment_hashes = first_commitment_hash :: commitment_hashes in + match commitment_hashes with + | too_old_commitment :: stored_hashes -> + (* Executing outbox message for the old non-stored commitment should fail. *) + let* () = + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_operations.Sc_rollup_invalid_last_cemented_commitment + (verify_outbox_message_execution block too_old_commitment) + in + (* Executing outbox message for the recent ones should succeed. *) + List.iter_es (verify_outbox_message_execution block) stored_hashes + | _ -> failwith "Expected non-empty list of commitment hashes." + +let test_multi_transaction_batch () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* ticket_receiver, block = + originate_contract + block + ~script:ticket_receiver + ~storage:"{}" + ~source_contract:originator + ~baker + in + (* Originate a contract that accepts a string as input. *) + let* string_receiver, block = + originate_contract + block + ~script:string_receiver + ~storage:{|""|} + ~source_contract:originator + ~baker + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + (* Ticket-token with content "red". *) + let* red_token = + string_ticket_token "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" + in + let transactions = + [ + (* A transaction to the ticket-receiver contract. *) + ( ticket_receiver, + Entrypoint.default, + {|Pair 1 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 4)|} ); + (* Another transaction to the ticket-receiver contract. *) + ( ticket_receiver, + Entrypoint.default, + {|Pair 2 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 6)|} ); + (* A transaction to the string-receiver contract. *) + (string_receiver, Entrypoint.default, {|"Hello"|}); + (* Another transaction to the string-receiver contract. *) + (string_receiver, Entrypoint.default, {|"Hello again"|}); + ] + in + (* Create an atomic batch message. *) + let output = + make_transaction_output ~outbox_level:0 ~message_index:0 transactions + in + (* Set up the balance so that the rollup owns 10 units of red tokens. *) + let* _ticket_hash, block = + adjust_ticket_token_balance_of_rollup + block + rollup + red_token + ~delta:(Z.of_int 10) + in + let* Sc_rollup_operations.{operations; _}, block = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output + in + (* Confirm that each transaction maps to one operation. *) + let* () = + verify_execute_outbox_message_operations + ~loc:__LOC__ + (B block) + rollup + ~operations + ~expected_transactions:transactions + in + (* Verify that the balance has moved to ticket-receiver. *) + let* () = + assert_ticket_token_balance + ~loc:__LOC__ + (B block) + red_token + (Destination.Sc_rollup rollup) + None + in + assert_ticket_token_balance + ~loc:__LOC__ + (B block) + red_token + (Destination.Contract (Originated ticket_receiver)) + (Some 10) + +(** Test that executing an L2 to L1 transaction that involves an invalid + parameter (mutez) fails. *) +let test_transaction_with_invalid_type () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + let* mutez_receiver, block = + originate_contract + block + ~script:mutez_receiver + ~storage:"0" + ~source_contract:originator + ~baker + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + let transactions = [(mutez_receiver, Entrypoint.default, "12")] in + (* Create an atomic batch message. *) + let output = + make_transaction_output ~outbox_level:0 ~message_index:1 transactions + in + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_operations.Sc_rollup_invalid_parameters_type + (execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output) + +(** Test that executing the same outbox message for the same twice fails. *) +let test_execute_message_twice () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* string_receiver, block = + originate_contract + block + ~script:string_receiver + ~storage:{|""|} + ~source_contract:originator + ~baker + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + (* Create an atomic batch message. *) + let transactions = [(string_receiver, Entrypoint.default, {|"Hello"|})] in + let output = + make_transaction_output ~outbox_level:0 ~message_index:1 transactions + in + (* Execute the message once - should succeed. *) + let* Sc_rollup_operations.{operations; _}, block = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output + in + (* Confirm that each transaction maps to one operation. *) + let* () = + verify_execute_outbox_message_operations + ~loc:__LOC__ + (B block) + rollup + ~operations + ~expected_transactions:transactions + in + (* Execute the same message again should fail. *) + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_errors.Sc_rollup_outbox_message_already_applied + (execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output) + +(** Verifies that it is not possible to execute the same message twice from + different commitments. *) +let test_execute_message_twice_different_cemented_commitments () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* string_receiver, block = + originate_contract + block + ~script:string_receiver + ~storage:{|""|} + ~source_contract:originator + ~baker + in + (* Publish and cement a commitment. *) + let* first_cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + let* predecessor = + Context.Sc_rollup.commitment (B block) rollup first_cemented_commitment + in + let* commitment = dummy_commitment ~predecessor (B block) rollup in + let* second_cemented_commitment, block = + publish_and_cement_commitment block ~originator rollup commitment + in + (* Create an atomic batch message. *) + let transactions = [(string_receiver, Entrypoint.default, {|"Hello"|})] in + let output = + make_transaction_output ~outbox_level:0 ~message_index:1 transactions + in + (* Execute the message once - should succeed. *) + let* Sc_rollup_operations.{operations; _}, block = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment:first_cemented_commitment + output + in + (* Confirm that each transaction maps to one operation. *) + let* () = + verify_execute_outbox_message_operations + ~loc:__LOC__ + (B block) + rollup + ~operations + ~expected_transactions:transactions + in + (* Execute the same message again should fail. *) + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_errors.Sc_rollup_outbox_message_already_applied + (execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment:second_cemented_commitment + output) + +let test_zero_amount_ticket () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* ticket_receiver, block = + originate_contract + block + ~script:ticket_receiver + ~storage:"{}" + ~source_contract:originator + ~baker + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + (* Create an atomic batch message. *) + let transactions = + [ + ( ticket_receiver, + Entrypoint.default, + {|Pair 42 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 0)|} ); + ] + in + let output = + make_transaction_output ~outbox_level:0 ~message_index:0 transactions + in + let*! result = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment + output + in + match result with + | Error e -> + if + Option.is_some + @@ List.find + (function + | Environment.Ecoproto_error + Script_tc_errors.Forbidden_zero_ticket_quantity -> + true + | _ -> false) + e + then return_unit + else Stdlib.failwith "Expected failure" + | Ok _ -> Stdlib.failwith "Expected failure" + +(* Check that executing an outbox message fails when the inclusion proof in + invalid. *) +let test_invalid_output_proof () = + let open Lwt_result_syntax in + let* block, originator = context_init Context.T1 in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_operations.Sc_rollup_invalid_output_proof + (execute_outbox_message + block + rollup + ~originator + ~output_proof:"No good" + ~commitment_hash:cemented_commitment) + +let test_execute_message_override_applied_messages_slot () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* string_receiver, block = + originate_contract + block + ~script:string_receiver + ~storage:{|""|} + ~source_contract:originator + ~baker + in + let* constants = Context.get_constants (B block) in + let max_active_levels = + constants.parametric.sc_rollup.max_active_outbox_levels |> Int32.to_int + in + let execute_message incr ~outbox_level ~message_index + ~cemented_commitment_hash = + let transactions = [(string_receiver, Entrypoint.default, {|"Hello"|})] in + let output = + make_transaction_output ~outbox_level ~message_index transactions + in + let* ( Sc_rollup_operations. + { + operations = _; + ticket_receipt = _; + whitelist_update = _; + paid_storage_size_diff; + }, + incr ) = + execute_outbox_message_without_proof_validation + incr + rollup + ~cemented_commitment:cemented_commitment_hash + output + in + return (paid_storage_size_diff, incr) + in + let* cemented_commitment = dummy_commitment (B block) rollup in + let* cemented_commitment_hash, block = + publish_and_cement_commitment block rollup ~originator cemented_commitment + in + (* Execute a message. *) + let* _, block = + execute_message + block + ~outbox_level:0 + ~message_index:0 + ~cemented_commitment_hash + in + (* Publish a bunch of commitments until the inbox level of the lcc is greater + than [max_active_levels]. *) + let* cemented_commitment_hash, block = + publish_commitments_until_min_inbox_level + block + rollup + ~originator + ~min_inbox_level:(max_active_levels + 10) + ~cemented_commitment_hash + ~cemented_commitment + in + (* Execute the message again but at [max_active_levels] outbox-level. *) + let* paid_storage_size_diff, incr = + execute_message + block + ~outbox_level:max_active_levels + ~message_index:1 + ~cemented_commitment_hash + in + (* Since bitset has already been created for the slot, there should be no + extra storage space. *) + let* () = assert_equal_z ~loc:__LOC__ paid_storage_size_diff Z.zero in + (* Execute a message at index 99. *) + let* paid_storage_size_diff, incr = + execute_message + incr + ~outbox_level:max_active_levels + ~message_index:99 + ~cemented_commitment_hash + in + (* A message at slot 99 is now recorded which expands the size of the bitset. + We therefore see an increase in size. + *) + let* () = assert_equal_z ~loc:__LOC__ paid_storage_size_diff (Z.of_int 14) in + (* Execute at index 98. *) + let* paid_storage_size_diff, incr = + execute_message + incr + ~outbox_level:max_active_levels + ~message_index:98 + ~cemented_commitment_hash + in + (* The bitset is not expanded so we don't pay anything. *) + let* () = assert_equal_z ~loc:__LOC__ paid_storage_size_diff Z.zero in + (* If we now try to record a message at level 0 it should fail since it + expired. *) + let* () = + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_operations.Sc_rollup_invalid_outbox_level + (execute_message + incr + ~outbox_level:0 + ~message_index:0 + ~cemented_commitment_hash) + in + let* _paid_storage_size_diff, _incr = + execute_message + incr + ~outbox_level:(max_active_levels + 5) + ~message_index:0 + ~cemented_commitment_hash + in + (* This should fail even if no message exists for the corresponding slot. + The reason is that outbox-level is smaller than the minimum level: + [last-cemented-commitment-level - max-active-levels]. + *) + let* () = + assert_fails + ~loc:__LOC__ + ~error:Sc_rollup_operations.Sc_rollup_invalid_outbox_level + (execute_message + incr + ~outbox_level:1 + ~message_index:0 + ~cemented_commitment_hash) + in + return_unit + +(** Test that a transaction fails if it attempts to transfer more tickets than + allowed. *) +let test_insufficient_ticket_balances () = + let open Lwt_result_syntax in + let* block, (baker, originator) = context_init Context.T2 in + let baker = Context.Contract.pkh baker in + (* Originate a rollup that accepts a list of string tickets as input. *) + let* block, rollup = + sc_originate block originator ~parameters_ty:"list (ticket string)" + in + (* Originate a contract that accepts a pair of nat and ticket string input. *) + let* ticket_receiver, block = + originate_contract + block + ~script:ticket_receiver + ~storage:"{}" + ~source_contract:originator + ~baker + in + (* Originate a contract that accepts a string as input. *) + let* string_receiver, block = + originate_contract + block + ~script:string_receiver + ~storage:{|""|} + ~source_contract:originator + ~baker + in + (* Publish and cement a commitment. *) + let* cemented_commitment, block = + publish_and_cement_dummy_commitment block ~originator rollup + in + (* Ticket-token with content "red". *) + let* red_token = + string_ticket_token "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" + in + let transactions = + [ + (* A transaction to the ticket-receiver contract. *) + ( ticket_receiver, + Entrypoint.default, + {|Pair 1 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 4)|} ); + (* Another transaction to the ticket-receiver contract. *) + ( ticket_receiver, + Entrypoint.default, + {|Pair 2 (Pair "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 6)|} ); + (* A transaction to the string-receiver contract. *) + (string_receiver, Entrypoint.default, {|"Hello"|}); + (* Another transaction to the string-receiver contract. *) + (string_receiver, Entrypoint.default, {|"Hello again"|}); + ] + in + (* Create an atomic batch message. *) + let output = + make_transaction_output ~outbox_level:0 ~message_index:0 transactions + in + (* Set up the balance so that the rollup owns 7 units of red tokens. + This is insufficient wrt the set of transactions above. + *) + let* ticket_hash, incr = + adjust_ticket_token_balance_of_rollup + block + rollup + red_token + ~delta:(Z.of_int 7) + in + (* Executing the batch fails because the rollup only has 7 units of tickets + but attempts to transfer 10 units. *) + assert_fails + ~loc:__LOC__ + ~error: + (Ticket_balance.Negative_ticket_balance + {key = ticket_hash; balance = Z.of_int (-3)}) + (execute_outbox_message_without_proof_validation + incr + rollup + ~cemented_commitment + output) + +let test_inbox_max_number_of_messages_per_level () = + let open Lwt_result_syntax in + let* block, (account1, account2) = + (* set sort of unlimited gas or we are going to hit gas exhaustion. *) + context_init + ~hard_gas_limit_per_operation:(Gas.Arith.integral_of_int_exn 100_000_000) + ~hard_gas_limit_per_block: + (Gas.Arith.integral_of_int_exn Int.(max_int / 1000)) + Context.T2 + in + (* we need to bake block because we are at the migration level and there is an additional msg in the inbox *) + let* block = Block.bake block in + let max_number_of_messages_per_level = + Constants.sc_rollup_max_number_of_messages_per_level + in + let* incr = Incremental.begin_construction block in + (* This just one message below the limit *) + let messages = + List.repeat (Z.to_int max_number_of_messages_per_level) "foo" + in + let* op = + Op.sc_rollup_add_messages ~gas_limit:Max (I incr) account1 messages + in + let* incr = Incremental.add_operation ~check_size:false incr op in + (* This break the limit *) + let* op = Op.sc_rollup_add_messages (I incr) account2 ["foo"] in + let* (_incr : Incremental.t) = + let expect_apply_failure = function + | Environment.Ecoproto_error + (Sc_rollup_inbox_repr.Inbox_level_reached_messages_limit as e) + :: _ -> + Assert.test_error_encodings e ; + return_unit + | _ -> + failwith + "It should have failed with [Inbox_level_reached_messages_limit]" + in + + Incremental.add_operation ~expect_apply_failure incr op + in + return_unit + +let add_publish ~rollup block account commitment = + let open Lwt_result_syntax in + let* block = bake_blocks_until_inbox_level block commitment in + let* publish = Op.sc_rollup_publish (B block) account rollup commitment in + Block.bake ~operation:publish block + +(** [test_number_of_parallel_games_bounded] checks that one cannot + play an arbitrary number of games. *) +let test_number_of_parallel_games_bounded () = + let open Lwt_result_syntax in + let max_number_of_parallel_games = + Context.default_test_constants.sc_rollup.max_number_of_parallel_games + in + let nb_accounts = max_number_of_parallel_games + 2 in + let* block, accounts = + context_init + ~sc_rollup_challenge_window_in_blocks:100 + (Context.TList nb_accounts) + in + let* block, rollup = sc_originate block (Stdlib.List.hd accounts) in + let* dummy_commitment = dummy_commitment (B block) rollup in + + let commitments = + List.mapi + (fun i _ -> + { + dummy_commitment with + number_of_ticks = number_of_ticks_exn (Int64.of_int (i + 1)); + }) + accounts + in + let* block = + List.fold_left2_es + ~when_different_lengths:[] + (fun block account commitment -> + add_publish ~rollup block account commitment) + block + accounts + commitments + in + let staker, opponents = + match accounts with + | staker :: opponents -> (staker, opponents) + | [] -> + (* Because [max_number_of_parallel_games] is strictly positive. *) + assert false + in + let staker_commitment, opponents_commitments = + match commitments with + | staker_commitment :: opponents_commitments -> + (staker_commitment, opponents_commitments) + | [] -> + (* Because [max_number_of_parallel_games] is strictly positive. *) + assert false + in + let expect_apply_failure = function + | Environment.Ecoproto_error + (Sc_rollup_errors.Sc_rollup_max_number_of_parallel_games_reached + xstaker) + :: _ -> + assert ( + Signature.Public_key_hash.( + xstaker = Account.pkh_of_contract_exn staker)) ; + return_unit + | _ -> + failwith + "It should have failed with \ + [Sc_rollup_max_number_of_parallel_games_reached]" + in + let* incr = Incremental.begin_construction block in + let* _block, _counter = + List.fold_left2_es + ~when_different_lengths:[] + (fun (block, counter) opponent opponent_commitment -> + let addr = Account.pkh_of_contract_exn staker in + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = hash_commitment opponent_commitment; + opponent_commitment_hash = hash_commitment staker_commitment; + } + in + let* op = + Op.sc_rollup_refute (I block) opponent rollup addr refutation + in + let* incr = + if counter = max_number_of_parallel_games then + Incremental.add_operation ~expect_apply_failure block op + else Incremental.add_operation block op + in + return (incr, counter + 1)) + (incr, 0) + opponents + opponents_commitments + in + return_unit + +(** [test_timeout] test multiple cases of the timeout logic. +- Test to timeout a player before it's allowed and fails. +- Test that the timeout left by player decreases as expected. +- Test another account can timeout a late player. +*) +let test_timeout () = + let open Lwt_result_syntax in + let* block, (account1, account2, account3) = context_init Context.T3 in + let pkh1 = Account.pkh_of_contract_exn account1 in + let pkh2 = Account.pkh_of_contract_exn account2 in + let* block, rollup = sc_originate block account1 in + let* constants = Context.get_constants (B block) in + let Constants.Parametric.{timeout_period_in_blocks; _} = + constants.parametric.sc_rollup + in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + let* dummy_commitment = dummy_commitment (B block) rollup in + let commitment1 = + { + dummy_commitment with + number_of_ticks = number_of_ticks_exn 4L; + compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["first"]); + } + in + let commitment2 = + { + dummy_commitment with + number_of_ticks = number_of_ticks_exn 4L; + compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["second"]); + } + in + + let* block = add_publish ~rollup block account1 commitment1 in + let* block = add_publish ~rollup block account2 commitment2 in + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated commitment1; + opponent_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated commitment2; + } + in + let* start_game_op = + Op.sc_rollup_refute (B block) account1 rollup pkh2 refutation + in + let* block = Block.bake ~operation:start_game_op block in + let* block = Block.bake_n (timeout_period_in_blocks - 1) block in + let game_index = Sc_rollup.Game.Index.make pkh1 pkh2 in + (* Testing to send a timeout before it's allowed. There is one block left + before timeout is allowed, that is, the current block. *) + let* () = + let blocks_left = 0l in + let* timeout = Op.sc_rollup_timeout (B block) account3 rollup game_index in + let block_res = Block.bake ~operation:timeout block in + assert_fails_with + ~__LOC__ + block_res + (Sc_rollup_errors.Sc_rollup_timeout_level_not_reached (blocks_left, pkh1)) + in + let* refute = + let tick = + WithExceptions.Option.get ~loc:__LOC__ (Sc_rollup.Tick.of_int 0) + in + let* {compressed_state; _} = + Context.Sc_rollup.commitment (B block) rollup genesis_info.commitment_hash + in + let first_chunk = + Sc_rollup.Dissection_chunk.{state_hash = Some compressed_state; tick} + in + let* rest = + List.init_es ~when_negative_length:[] 4 (fun i -> + let state_hash = None in + let tick = + WithExceptions.Option.get + ~loc:__LOC__ + (Sc_rollup.Tick.of_int (i + 1)) + in + return Sc_rollup.Dissection_chunk.{state_hash; tick}) + in + let step = Sc_rollup.Game.Dissection (first_chunk :: rest) in + let refutation = Sc_rollup.Game.(Move {choice = tick; step}) in + Op.sc_rollup_refute (B block) account1 rollup pkh2 refutation + in + let* block = Block.bake ~operation:refute block in + let* pkh1_timeout, pkh2_timeout = + let+ timeout = Context.Sc_rollup.timeout (B block) rollup pkh1 pkh2 in + let timeout = WithExceptions.Option.get ~loc:__LOC__ timeout in + if game_index.alice = pkh1 then (timeout.alice, timeout.bob) + else (timeout.bob, timeout.alice) + in + let* () = Assert.equal_int ~loc:__LOC__ pkh1_timeout 0 in + let* () = + Assert.equal_int ~loc:__LOC__ pkh2_timeout timeout_period_in_blocks + in + let* block = Block.bake_n timeout_period_in_blocks block in + let* timeout = Op.sc_rollup_timeout (B block) account3 rollup game_index in + let* incr = Incremental.begin_construction block in + let* incr = Incremental.add_operation incr timeout in + let expected_game_status : Sc_rollup.Game.status = + Ended (Loser {reason = Timeout; loser = pkh2}) + in + assert_timeout_result ~game_status:expected_game_status incr rollup game_index + +let start_game block rollup (first_player, commitment1) (pkh2, commitment2) = + let open Lwt_result_syntax in + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated commitment1; + opponent_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated commitment2; + } + in + let* start_game_op = + Op.sc_rollup_refute (B block) first_player rollup pkh2 refutation + in + Block.bake ~operation:start_game_op block + +let create_conflicting_commitment block rollup first_player second_player = + let open Lwt_result_syntax in + let compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["first"]) + in + let* commitment1 = + dummy_commitment ~compressed_state ~number_of_ticks:1L (B block) rollup + in + let compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["second"]) + in + let* commitment2 = + dummy_commitment ~compressed_state ~number_of_ticks:1L (B block) rollup + in + let* block = add_publish ~rollup block first_player commitment1 in + let* block = add_publish ~rollup block second_player commitment2 in + return (block, commitment1, commitment2) + +let create_conflict block rollup ~first_player ~second_player = + let open Lwt_result_syntax in + let pkh2 = Account.pkh_of_contract_exn second_player in + let* block, commitment1, commitment2 = + create_conflicting_commitment block rollup first_player second_player + in + let* block = + start_game block rollup (first_player, commitment1) (pkh2, commitment2) + in + return block + +let init_with_conflict () = + let open Lwt_result_syntax in + let* block, (account1, account2) = context_init Context.T2 in + let pkh1 = Account.pkh_of_contract_exn account1 in + let pkh2 = Account.pkh_of_contract_exn account2 in + let* block, rollup = sc_originate block account1 in + let* block = + create_conflict block rollup ~first_player:account1 ~second_player:account2 + in + return (block, (account1, pkh1), (account2, pkh2), rollup) + +module Arith_pvm = Sc_rollup_helpers.Arith_pvm + +let dumb_proof ~choice = + let open Lwt_result_wrap_syntax in + let context_arith_pvm = Arith_pvm.make_empty_context () in + let empty = Arith_pvm.make_empty_state () in + let*! arith_state = Arith_pvm.initial_state ~empty in + let*! arith_state = Arith_pvm.install_boot_sector arith_state "" in + let input = Sc_rollup_helpers.make_external_input "c4c4" in + let*@ pvm_step = + Arith_pvm.produce_proof + context_arith_pvm + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + (Some input) + arith_state + in + let pvm_step = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Sc_rollup.Proof.serialize_pvm_step ~pvm:(module Arith_pvm) pvm_step + in + let inbox_proof = + Sc_rollup.Proof.Inbox_proof + { + level = Raw_level.root; + message_counter = Z.zero; + proof = + Sc_rollup.Inbox.Internal_for_tests.serialized_proof_of_string + "dummy proof"; + } + in + let proof = Sc_rollup.Proof.{pvm_step; input_proof = Some inbox_proof} in + return Sc_rollup.Game.(Move {choice; step = Proof proof}) + +(** Test that two invalid proofs from the two players lead to a draw + in the refutation game. *) +let test_draw_with_two_invalid_moves () = + let open Lwt_result_syntax in + let* block, (p1, p1_pkh), (p2, p2_pkh), rollup = init_with_conflict () in + + (* Player1 will play an invalid final move. *) + let* block = + let* p1_refutation = + let choice = Sc_rollup.Tick.initial in + dumb_proof ~choice + in + let* p1_final_move_op = + Op.sc_rollup_refute (B block) p1 rollup p2_pkh p1_refutation + in + Block.bake ~operation:p1_final_move_op block + in + + (* Get the frozen bonds for the two players before the draw. *) + let* frozen_bonds_p1 = Context.Contract.frozen_bonds (B block) p1 in + let* frozen_bonds_p2 = Context.Contract.frozen_bonds (B block) p2 in + + (* Player2 will also send an invalid final move. *) + let* incr = + let* p2_refutation = + let choice = Sc_rollup.Tick.initial in + dumb_proof ~choice + in + let* p2_final_move_op = + Op.sc_rollup_refute (B block) p2 rollup p1_pkh p2_refutation + in + let* incr = Incremental.begin_construction block in + Incremental.add_operation incr p2_final_move_op + in + + (* As both players played invalid moves, the game ends in a draw. *) + let expected_game_status : Sc_rollup.Game.status = Ended Draw in + let* () = + assert_refute_result + ~game_status:expected_game_status + incr + rollup + (Sc_rollup.Game.Index.make p1_pkh p2_pkh) + in + + (* The two players should have been slashed. *) + let* constants = Context.get_constants (I incr) in + let stake_amount = constants.parametric.sc_rollup.stake_amount in + let* () = + Assert.frozen_bonds_was_debited + ~loc:__LOC__ + (I incr) + p1 + frozen_bonds_p1 + stake_amount + in + let* () = + Assert.frozen_bonds_was_debited + ~loc:__LOC__ + (I incr) + p2 + frozen_bonds_p2 + stake_amount + in + return_unit + +let play_conflict_until_draw block (p1, p1_pkh) p2_pkh rollup = + let open Lwt_result_syntax in + (* Player1 will play an invalid final move. *) + let* block = + let* p1_refutation = + let choice = Sc_rollup.Tick.initial in + dumb_proof ~choice + in + + let* p1_final_move_op = + Op.sc_rollup_refute (B block) p1 rollup p2_pkh p1_refutation + in + Block.bake ~operation:p1_final_move_op block + in + + (* Player2 will not play and it will be timeout. *) + let* incr = + let* block = bake_timeout_period block in + let game_index = Sc_rollup.Game.Index.make p1_pkh p2_pkh in + let* timeout = Op.sc_rollup_timeout (B block) p1 rollup game_index in + let* incr = Incremental.begin_construction block in + Incremental.add_operation incr timeout + in + + (* As the player1 played an invalid move, the timeout is counted + as an invalid one too. The game ends in a draw. *) + let expected_game_status : Sc_rollup.Game.status = Ended Draw in + let* () = + assert_timeout_result + ~game_status:expected_game_status + incr + rollup + (Sc_rollup.Game.Index.make p1_pkh p2_pkh) + in + Incremental.finalize_block incr + +let play_conflict_with_timeout block (p1, p1_pkh) p2_pkh rollup = + let open Lwt_result_syntax in + (* Player1 will not play and it will be timeout. *) + let game_index = Sc_rollup.Game.Index.make p1_pkh p2_pkh in + let* incr = + let* block = bake_timeout_period block in + let* timeout = Op.sc_rollup_timeout (B block) p1 rollup game_index in + let* incr = Incremental.begin_construction block in + Incremental.add_operation incr timeout + in + (* The game ends with p2 as a winner. *) + let expected_game_status : Sc_rollup.Game.status = + Ended (Loser {reason = Timeout; loser = p1_pkh}) + in + let* () = + assert_timeout_result + ~game_status:expected_game_status + incr + rollup + game_index + in + let* () = assert_game_exists incr rollup game_index ~exists:false in + Incremental.finalize_block incr + +(** Test that timeout a player during the final move ends the game if + the other player played. *) +let test_timeout_during_final_move () = + let open Lwt_result_syntax in + let* block, (p1, p1_pkh), (_p2, p2_pkh), rollup = init_with_conflict () in + let* _block = play_conflict_until_draw block (p1, p1_pkh) p2_pkh rollup in + return_unit + +(** Test that timeout a player during the final move ends the game if + the other player played. *) +let test_draw_with_parallel_game () = + let open Lwt_result_syntax in + let* block, (account1, account2, account3) = context_init Context.T3 in + let pkh1 = Account.pkh_of_contract_exn account1 in + let pkh2 = Account.pkh_of_contract_exn account2 in + let pkh3 = Account.pkh_of_contract_exn account3 in + let* block, rollup = sc_originate block account1 in + let compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["first"]) + in + let* commitment1 = + dummy_commitment ~compressed_state ~number_of_ticks:1L (B block) rollup + in + let compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["second"]) + in + let* commitment2 = + dummy_commitment ~compressed_state ~number_of_ticks:1L (B block) rollup + in + let compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["third"]) + in + let* commitment3 = + dummy_commitment ~compressed_state ~number_of_ticks:1L (B block) rollup + in + let* block = add_publish ~rollup block account1 commitment1 in + let* block = add_publish ~rollup block account2 commitment2 in + let* block = add_publish ~rollup block account3 commitment3 in + let* block = + start_game block rollup (account1, commitment1) (pkh2, commitment2) + in + let* block = + start_game block rollup (account3, commitment3) (pkh2, commitment2) + in + let* block = + start_game block rollup (account3, commitment3) (pkh1, commitment1) + in + let* block = play_conflict_with_timeout block (account1, pkh1) pkh2 rollup in + let* block = play_conflict_with_timeout block (account3, pkh3) pkh2 rollup in + + (* [pkh1] and [pkh3] were both slashed, any move in their game will + result in a draw. *) + let* incr = Incremental.begin_construction block in + let* incr = + let* refutation = + let choice = Sc_rollup.Tick.initial in + dumb_proof ~choice + in + let* final_move_op = + Op.sc_rollup_refute (B block) account3 rollup pkh1 refutation + in + Incremental.add_operation incr final_move_op + in + let expected_game_status : Sc_rollup.Game.status = Ended Draw in + let game_index = Sc_rollup.Game.Index.make pkh1 pkh3 in + let* () = + assert_refute_result + ~game_status:expected_game_status + incr + rollup + game_index + in + let* () = assert_game_exists incr rollup game_index ~exists:false in + return_unit + +(** Test that playing a dissection during a final move is rejected. *) +let test_dissection_during_final_move () = + let open Lwt_result_syntax in + let* block, (p1, p1_pkh), (p2, p2_pkh), rollup = init_with_conflict () in + + (* Player1 will play an invalid final move. *) + let* block = + let* p1_refutation = + let choice = Sc_rollup.Tick.initial in + dumb_proof ~choice + in + + let* p1_final_move_op = + Op.sc_rollup_refute (B block) p1 rollup p2_pkh p1_refutation + in + Block.bake ~operation:p1_final_move_op block + in + + (* Player2 will play a dissection. *) + let dumb_dissection = + let choice = Sc_rollup.Tick.initial in + Sc_rollup.Game.(Move {choice; step = Dissection []}) + in + let* p2_op = Op.sc_rollup_refute (B block) p2 rollup p1_pkh dumb_dissection in + (* Dissecting is no longer accepted. *) + let block_res = Block.bake ~operation:p2_op block in + assert_fails_with + ~__LOC__ + block_res + Sc_rollup_game_repr.Dissecting_during_final_move + +let init_arith_state ~boot_sector = + let open Lwt_syntax in + let context = Arith_pvm.make_empty_context () in + let empty = Arith_pvm.make_empty_state () in + let* state = Arith_pvm.initial_state ~empty in + let* state = Arith_pvm.install_boot_sector state boot_sector in + return (context, state) + +(** [make_arith_state ?boot_sector metadata] initializes an arith PVM + waiting to read its first input, after evaluating the boot sector + and the [metadata]. + + [boot_sector] defaults to [""]. +*) +let make_arith_state ?(boot_sector = "") metadata = + let open Lwt_syntax in + let* context, state = init_arith_state ~boot_sector in + let* state_hash1 = Arith_pvm.state_hash state in + + (* 1. We evaluate the boot sector. *) + let* input_required = + Arith_pvm.is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + assert (input_required = Sc_rollup.No_input_required) ; + let* state = Arith_pvm.eval state in + let* state_hash2 = Arith_pvm.state_hash state in + (* 2. The state now needs the metadata. *) + let* input_required = + Arith_pvm.is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + assert (input_required = Sc_rollup.Needs_reveal Reveal_metadata) ; + (* 3. We feed the state with the metadata. *) + let input = Sc_rollup.(Reveal (Metadata metadata)) in + let* state = Arith_pvm.set_input input state in + let* state_hash3 = Arith_pvm.state_hash state in + let* input_required = + Arith_pvm.is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + assert (input_required = Sc_rollup.Initial) ; + + return (context, state, state_hash1, state_hash2, state_hash3) + +let make_set_input_refutation context state input input_proof = + let open Lwt_syntax in + let* proof = + Arith_pvm.produce_proof + context + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + (Some input) + state + in + let pvm_step = WithExceptions.Result.get_ok ~loc:__LOC__ proof in + let pvm_step = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Sc_rollup.Proof.serialize_pvm_step ~pvm:(module Arith_pvm) pvm_step + in + let choice = Sc_rollup.Tick.(next initial) in + let step : Sc_rollup.Game.step = + Proof {pvm_step; input_proof = Some input_proof} + in + return Sc_rollup.Game.(Move {choice; step}) + +(** [test_refute_set_input p1_info p2_info make_state_before] creates + a refutation game where the final tick refuted is a [set_input] + step. It uses [p1_info] (and respectively [p2_info]) to create + the input (and the input proof) executed. [make_state_before] + initializes the context and the state before the divergence + between the two players. + + The first player will be expected to win the game. *) +let test_refute_set_input + (p1_info : + Sc_rollup.t -> + Sc_rollup.Commitment.genesis_info -> + Sc_rollup.input * Sc_rollup.Proof.input_proof) p2_info + (make_state_before : + Sc_rollup.t -> + Sc_rollup.Commitment.genesis_info -> + (Arith_pvm.context * Arith_pvm.state) tzresult Lwt.t) = + let open Lwt_result_syntax in + let* block, (p1, p2) = context_init Context.T2 in + let pkh1 = Account.pkh_of_contract_exn p1 in + let pkh2 = Account.pkh_of_contract_exn p2 in + let* block, rollup = sc_originate block p1 in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + let* genesis_commitment = + Context.Sc_rollup.commitment (B block) rollup genesis_info.commitment_hash + in + + let p1_input, p1_input_proof = p1_info rollup genesis_info in + let p2_input, p2_input_proof = p2_info rollup genesis_info in + let* context, prior_state = make_state_before rollup genesis_info in + + let post_commitment_from_set_input block account input = + let* inbox_level = next_inbox_level (B block) rollup in + let*! state_hash1 = Arith_pvm.state_hash prior_state in + let*! state = Arith_pvm.set_input input prior_state in + let*! state_hash2 = Arith_pvm.state_hash state in + let commitment : Sc_rollup.Commitment.t = + { + predecessor = genesis_info.commitment_hash; + inbox_level; + number_of_ticks = number_of_ticks_exn 2L; + compressed_state = state_hash2; + } + in + let* block = add_publish ~rollup block account commitment in + return (commitment, block, state, state_hash1, state_hash2) + in + + let* commitment1, block, _state, state_hash1, p1_state_hash2 = + post_commitment_from_set_input block p1 p1_input + in + let* commitment2, block, _, _, _ = + post_commitment_from_set_input block p2 p2_input + in + + (* [p1] starts a game. + + The dissection is: + 0 -> predecessor state hash + 1 -> state just before the [set_input] + 2 -> tick in conflict with different evaluations of [set_input] + *) + let* start_game_op = + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated commitment1; + opponent_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated commitment2; + } + in + Op.sc_rollup_refute (B block) p1 rollup pkh2 refutation + in + let* dissection_op = + let dissection : Sc_rollup.Game.refutation = + let choice = Sc_rollup.Tick.initial in + let step : Sc_rollup.Game.step = + let zero = Sc_rollup.Tick.initial in + let one = Sc_rollup.Tick.next zero in + let two = Sc_rollup.Tick.next one in + Dissection + [ + {tick = zero; state_hash = Some genesis_commitment.compressed_state}; + {tick = one; state_hash = Some state_hash1}; + {tick = two; state_hash = Some p1_state_hash2}; + ] + in + Move {choice; step} + in + Op.sc_rollup_refute (B block) p1 rollup pkh2 dissection + in + let* p1_moves = + Op.batch_operations + ~recompute_counters:true + ~source:p1 + (B block) + [start_game_op; dissection_op] + in + let* block = Block.bake ~operation:p1_moves block in + + (* [p2] plays its [set_input], he is expected to play an invalid one. *) + let* p2_final_move_op = + let*! proof = + make_set_input_refutation context prior_state p2_input p2_input_proof + in + Op.sc_rollup_refute (B block) p2 rollup pkh1 proof + in + (* [p1] plays it [set_input] too. *) + let* p1_final_move_op = + let*! proof = + make_set_input_refutation context prior_state p1_input p1_input_proof + in + Op.sc_rollup_refute (B block) p1 rollup pkh2 proof + in + let* incr = Incremental.begin_construction block in + let* incr = Incremental.add_operation incr p2_final_move_op in + let* incr = Incremental.add_operation incr p1_final_move_op in + let expected_game_status : Sc_rollup.Game.status = + Ended (Loser {reason = Conflict_resolved; loser = pkh2}) + in + assert_refute_result + ~game_status:expected_game_status + incr + rollup + (Sc_rollup.Game.Index.make pkh1 pkh2) + +let test_refute_invalid_metadata () = + let open Lwt_result_syntax in + let p1_info rollup (genesis_info : Sc_rollup.Commitment.genesis_info) = + let metadata = + Sc_rollup.Metadata. + {address = rollup; origination_level = genesis_info.level} + in + Sc_rollup.(Reveal (Metadata metadata), Proof.Reveal_proof Metadata_proof) + in + let p2_info rollup _genesis_info = + let invalid_metadata = + Sc_rollup.Metadata. + {address = rollup; origination_level = Raw_level.of_int32_exn 42l} + in + Sc_rollup. + (Reveal (Metadata invalid_metadata), Proof.Reveal_proof Metadata_proof) + in + let make_state_before _rollup _genesis_info = + let*! context, state = init_arith_state ~boot_sector:"" in + let*! state = Arith_pvm.eval state in + return (context, state) + in + test_refute_set_input p1_info p2_info make_state_before + +(** [arith_state_before_reveal metadata hash] initializes an arith PVM waiting + for the data associated to [hash] to be revealed. + + Starts by creating a state with {!make_arith_state}, then triggers the + [Needs_reveal] state through an external message annoucing the [hash]. +*) +let arith_state_before_reveal metadata hash = + let open Lwt_result_syntax in + let*! context, state, _, _, _ = make_arith_state metadata in + let input = + Sc_rollup_helpers.make_external_input + ~inbox_level:Raw_level.root + ~message_counter:Z.zero + ("hash:" ^ hash) + in + let*! state = Arith_pvm.set_input input state in + let rec eval_until_needs_reveal state = + let*! input_request = + Arith_pvm.is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + match input_request with + | Needs_reveal _ -> return state + | _ -> + let*! state = Arith_pvm.eval state in + eval_until_needs_reveal state + in + let* state = eval_until_needs_reveal state in + return (context, state) + +let test_refute_invalid_reveal () = + let data = String.make Constants_repr.sc_rollup_message_size_limit 'f' in + let invalid_data = "foo" in + let hash = + Sc_rollup_reveal_hash.(hash_string ~scheme:Blake2B [data] |> to_hex) + in + let p1_info _rollup _genesis_info = + Sc_rollup.(Reveal (Raw_data data), Proof.Reveal_proof (Raw_data_proof data)) + in + let p2_info _rollup _genesis_info = + Sc_rollup. + ( Reveal (Raw_data invalid_data), + Proof.Reveal_proof (Raw_data_proof invalid_data) ) + in + let make_state_before rollup + (genesis_info : Sc_rollup.Commitment.genesis_info) = + let metadata = + Sc_rollup.Metadata. + {address = rollup; origination_level = genesis_info.level} + in + arith_state_before_reveal metadata hash + in + test_refute_set_input p1_info p2_info make_state_before + +let full_history_inbox (genesis_predecessor_timestamp, genesis_predecessor) + all_external_messages = + let open Sc_rollup_helpers in + let payloads_per_levels = + List.map + (fun (pred_info, level, external_messages) -> + wrap_messages ~pred_info level external_messages) + all_external_messages + in + Sc_rollup_helpers.Node_inbox.construct_inbox + ~genesis_predecessor_timestamp + ~genesis_predecessor + payloads_per_levels + +let input_included ~snapshot ~full_history_inbox (l, n) = + let open Lwt_result_wrap_syntax in + let open Sc_rollup_helpers in + let Sc_rollup_helpers.Node_inbox.{payloads_histories; history; inbox} = + full_history_inbox + in + let history_proof = Sc_rollup.Inbox.old_levels_messages inbox in + (* Create an inclusion proof of the inbox message at [(l, n)]. *) + let*@ proof, _ = + Sc_rollup.Inbox.produce_proof + ~get_payloads_history:(get_payloads_history payloads_histories) + ~get_history:(get_history history) + history_proof + (l, n) + in + let*?@ inbox_message_verified = + Sc_rollup.Inbox.verify_proof (l, n) snapshot proof + in + return + @@ Option.map + (fun inbox_message -> Sc_rollup.Inbox_message inbox_message) + inbox_message_verified + +(** Test that the protocol adds a [SOL], [Info_per_level] and [EOL] for each + Tezos level, even if no messages are added to the inbox. *) +let test_automatically_added_internal_messages () = + let open Lwt_result_syntax in + let assert_input_included ~__LOC__ ~snapshot ~full_history_inbox (l, n) input + = + let* input_verified = input_included ~snapshot ~full_history_inbox (l, n) in + Assert.equal + ~loc:__LOC__ + (Option.equal Sc_rollup.input_equal) + "Input found with the proof is different from input provided" + (fun ppf v -> + match v with + | None -> Format.pp_print_string ppf "None" + | Some v -> Sc_rollup.pp_input ppf v) + input_verified + input + in + + let assert_sol ~snapshot ~full_history_inbox ~inbox_level = + let sol = Sc_rollup_helpers.make_sol ~inbox_level in + assert_input_included + ~snapshot + ~full_history_inbox + (inbox_level, Z.zero) + (Some sol) + in + + let assert_ipl ~snapshot ~full_history_inbox ~level_info ~inbox_level = + let predecessor_timestamp, predecessor = level_info in + let info_per_level = + Sc_rollup_helpers.make_info_per_level + ~inbox_level + ~predecessor_timestamp + ~predecessor + in + assert_input_included + ~snapshot + ~full_history_inbox + (inbox_level, Z.one) + (Some info_per_level) + in + + let assert_protocol_migration ~snapshot ~full_history_inbox ~inbox_level = + let protocol_migration = + Sc_rollup_helpers.make_protocol_migration ~inbox_level + in + assert_input_included + ~snapshot + ~full_history_inbox + (inbox_level, Z.(succ one)) + (Some protocol_migration) + in + + let assert_eol ~snapshot ~full_history_inbox ~inbox_level ~message_counter = + let eol = Sc_rollup_helpers.make_eol ~inbox_level ~message_counter in + assert_input_included + ~snapshot + ~full_history_inbox + (inbox_level, message_counter) + (Some eol) + in + + let assert_no_message ~snapshot ~full_history_inbox ~inbox_level + ~message_counter = + assert_input_included + ~snapshot + ~full_history_inbox + (inbox_level, message_counter) + None + in + + let info_per_block (block : Block.t) = + (block.header.shell.timestamp, block.hash) + in + + (* Create the first block. *) + let* block, account = context_init Context.T1 in + + let level_zero_info = + ( Time.Protocol.epoch, + Block_hash.of_b58check_exn + "BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU" ) + in + + let level_one_info = info_per_block block in + (* Bake a second block. *) + let* block = Block.bake block in + + let level_two_info = info_per_block block in + (* Bake a third block where a message is added. *) + let* operation = Op.sc_rollup_add_messages (B block) account ["foo"] in + let* block = Block.bake ~operation block in + + let* inbox = Context.Sc_rollup.inbox (B block) in + let snapshot = Sc_rollup.Inbox.take_snapshot inbox in + + let level_zero = Raw_level.of_int32_exn 0l in + let level_one = Raw_level.of_int32_exn 1l in + let level_two = Raw_level.of_int32_exn 2l in + let*? ({inbox; _} as full_history_inbox) = + full_history_inbox + level_zero_info + [(level_one_info, level_one, []); (level_two_info, level_two, ["foo"])] + in + + (* Assertions about level 0. *) + let* () = + assert_sol ~__LOC__ ~snapshot ~full_history_inbox ~inbox_level:level_zero + in + let* () = + assert_ipl + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_zero + ~level_info:level_zero_info + in + let* () = + assert_protocol_migration + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_zero + in + let* () = + assert_eol + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_zero + ~message_counter:(Z.of_int 3) + in + + (* Assertions about level 1. *) + let* () = + assert_sol ~__LOC__ ~snapshot ~full_history_inbox ~inbox_level:level_one + in + let* () = + assert_ipl + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_one + ~level_info:level_one_info + in + let* () = + assert_protocol_migration + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_zero + in + let* () = + assert_eol + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_one + ~message_counter:(Z.of_int 3) + in + + (* Assertions about level 2. *) + let* () = + assert_sol ~__LOC__ ~snapshot ~full_history_inbox ~inbox_level:level_two + in + let* () = + assert_ipl + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_two + ~level_info:level_two_info + in + let* () = + assert_eol + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_two + ~message_counter:(Z.of_int 3) + in + let* () = + assert_no_message + ~__LOC__ + ~snapshot + ~full_history_inbox + ~inbox_level:level_two + ~message_counter:(Z.of_int 4) + in + + (* Assert the computed inbox and protocol's inbox are equal. *) + let history_proof = Sc_rollup.Inbox.old_levels_messages inbox in + Assert.equal + ~loc:__LOC__ + Sc_rollup.Inbox.equal_history_proof + "Computed and protocol inboxes aren't equal" + Sc_rollup.Inbox.pp_history_proof + snapshot + history_proof + +(** With [Start_of_level] and [End_of_level] inbox messages in each inbox level, + it's impossible to give a valid commitment with 0 ticks. *) +let test_zero_tick_commitment_fails () = + let open Lwt_result_syntax in + let* block, contract, rollup = init_and_originate Context.T1 in + let* commitment = dummy_commitment (B block) rollup in + let commitment = {commitment with number_of_ticks = number_of_ticks_exn 0L} in + let* publish_commitment = + Op.sc_rollup_publish (B block) contract rollup commitment + in + let block_res = Block.bake ~operation:publish_commitment block in + assert_fails_with + ~__LOC__ + block_res + Sc_rollup_errors.Sc_rollup_zero_tick_commitment + +(** [test_curfew] creates a rollup, publishes two conflicting + commitments. Branches are expected to continue (commitment are able to be + published). Tries to publish another commitment at the same initial + `inbox_level` after [challenge_window_in_blocks - 1] and after + [challenge_window_in_blocks] blocks. Only the first attempt is expected to + succeed. *) +let test_curfew () = + let open Lwt_result_syntax in + let* block, (account1, account2, account3), rollup = + (* sc_rollup_challenge_window_in_blocks should be at least commitment period *) + init_and_originate ~sc_rollup_challenge_window_in_blocks:90 Context.T3 + in + let* constants = Context.get_constants (B block) in + let challenge_window = + constants.parametric.sc_rollup.challenge_window_in_blocks + in + let* publish1, commitment1 = + publish_op_and_dummy_commitment + ~sender:account1 + ~compressed_state:"first" + rollup + block + in + let* publish2, commitment2 = + publish_op_and_dummy_commitment + ~sender:account2 + ~compressed_state:"second" + rollup + block + in + let* block = bake_blocks_until_inbox_level block commitment1 in + let* block = Block.bake ~operations:[publish1; publish2] block in + let* block = Block.bake_n (challenge_window - 1) block in + + let* publish11, commitment11 = + publish_op_and_dummy_commitment + ~sender:account1 + ~predecessor:commitment1 + rollup + block + in + let* publish21, commitment21 = + publish_op_and_dummy_commitment + ~sender:account2 + ~predecessor:commitment2 + rollup + block + in + let* publish3, _commitment3 = + publish_op_and_dummy_commitment + ~sender:account3 + ~compressed_state:"third" + rollup + block + in + let* block = bake_blocks_until_inbox_level block commitment11 in + let* block = Block.bake ~operations:[publish11; publish21; publish3] block in + let* publish111, commitment111 = + publish_op_and_dummy_commitment + ~sender:account1 + ~predecessor:commitment11 + rollup + block + in + let* publish211, _commitment211 = + publish_op_and_dummy_commitment + ~sender:account2 + ~predecessor:commitment21 + rollup + block + in + let* publish4, _commitment4 = + publish_op_and_dummy_commitment + ~sender:account3 + ~compressed_state:"fourth" + rollup + block + in + let* block = bake_blocks_until_inbox_level block commitment111 in + let* incr = Incremental.begin_construction block in + let* incr = Incremental.add_operation incr publish111 in + let* incr = Incremental.add_operation incr publish211 in + let expect_apply_failure = function + | Environment.Ecoproto_error + (Sc_rollup_errors.Sc_rollup_commitment_past_curfew as e) + :: _ -> + Assert.test_error_encodings e ; + return_unit + | _ -> + failwith "It should have failed with [Sc_rollup_commitment_past_curfew]" + in + let* _incr = Incremental.add_operation ~expect_apply_failure incr publish4 in + return_unit + +(** [test_curfew_period_is_started_only_after_first_publication checks that + publishing the first commitment of a given [inbox_level] after + [inbox_level + challenge_window] is still possible. *) +let test_curfew_period_is_started_only_after_first_publication () = + let open Lwt_result_syntax in + let* block, account1, rollup = init_and_originate Context.T1 in + let* constants = Context.get_constants (B block) in + let challenge_window = + constants.parametric.sc_rollup.challenge_window_in_blocks + in + let commitment_period = + constants.parametric.sc_rollup.commitment_period_in_blocks + in + let* block = Block.bake_n commitment_period block in + let* block = Block.bake_n challenge_window block in + let* commitment = dummy_commitment (B block) rollup in + let* operation = Op.sc_rollup_publish (B block) account1 rollup commitment in + let* _block = Block.bake ~operation block in + return_unit + +let test_offline_staker_does_not_prevent_cementation () = + let open Lwt_result_syntax in + let* ctxt, contracts, rollup = init_and_originate Context.T2 in + let contract1, contract2 = contracts in + let* ctxt = bake_blocks_until_next_inbox_level ctxt rollup in + (* A publishes a commitment on C1. *) + let* commitment1 = dummy_commitment (B ctxt) rollup in + let* operation = Op.sc_rollup_publish (B ctxt) contract1 rollup commitment1 in + let* b = Block.bake ~operation ctxt in + + (* We cement C1. *) + let* constants = Context.get_constants (B b) in + let* b = + Block.bake_n constants.parametric.sc_rollup.challenge_window_in_blocks b + in + let* cement_op = Op.sc_rollup_cement (B b) contract1 rollup in + let* b = Block.bake ~operation:cement_op b in + + (* A now goes offline, B takes over. *) + let* commitment2 = dummy_commitment ~predecessor:commitment1 (B b) rollup in + let* operation2 = + Op.sc_rollup_publish (B ctxt) contract2 rollup commitment2 + in + let* b = bake_blocks_until_inbox_level b commitment2 in + let* b = Block.bake ~operation:operation2 b in + + (* We cement C2. *) + let* constants = Context.get_constants (B b) in + let* b = + Block.bake_n constants.parametric.sc_rollup.challenge_window_in_blocks b + in + let* cement_op = Op.sc_rollup_cement (B b) contract2 rollup in + let* _b = Block.bake ~operation:cement_op b in + return_unit + +let init_with_4_conflicts () = + let open Lwt_result_syntax in + let dumb_compressed_state s = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string [s]) + in + let* block, players = context_init (Context.TList 4) in + let pA, pB, pC, pD = + match players with + | [pA; pB; pC; pD] -> (pA, pB, pC, pD) + | _ -> assert false + in + let pA_pkh = Account.pkh_of_contract_exn pA in + let pB_pkh = Account.pkh_of_contract_exn pB in + let pC_pkh = Account.pkh_of_contract_exn pC in + let pD_pkh = Account.pkh_of_contract_exn pD in + let* block, rollup = sc_originate block pA in + + (* The four players stake on a conflicting commitment. *) + let* pA_commitment = + dummy_commitment + ~number_of_ticks:1L + ~compressed_state:(dumb_compressed_state "A") + (B block) + rollup + in + let* pB_commitment = + dummy_commitment + ~number_of_ticks:1L + ~compressed_state:(dumb_compressed_state "B") + (B block) + rollup + in + let* pC_commitment = + dummy_commitment + ~number_of_ticks:1L + ~compressed_state:(dumb_compressed_state "C") + (B block) + rollup + in + let* pD_commitment = + dummy_commitment + ~number_of_ticks:1L + ~compressed_state:(dumb_compressed_state "D") + (B block) + rollup + in + let* block = + List.fold_left_es + (fun block (player, commitment) -> + add_publish ~rollup block player commitment) + block + [ + (pA, pA_commitment); + (pB, pB_commitment); + (pC, pC_commitment); + (pD, pD_commitment); + ] + in + return (block, rollup, (pA, pA_pkh), (pB, pB_pkh), (pC, pC_pkh), (pD, pD_pkh)) + +let start_refutation_game_op block rollup (p1, p1_pkh) p2_pkh = + let open Lwt_result_wrap_syntax in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let*@ (p1_point, p2_point), _ctxt = + Sc_rollup.Refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + p1_pkh + p2_pkh + in + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = p1_point.hash; + opponent_commitment_hash = p2_point.hash; + } + in + Op.sc_rollup_refute (B block) p1 rollup p2_pkh refutation + +(** Test that when A plays against B, C, D and if A losts the game against + one of them, the others can win against A for free. *) +let test_winner_by_forfeit () = + let open Lwt_result_syntax in + let* block, rollup, (pA, pA_pkh), (pB, pB_pkh), (pC, pC_pkh), (pD, pD_pkh) = + init_with_4_conflicts () + in + + (* Refutation game starts: A against B, C and D. *) + (* A starts against B and D so it can be timeouted. *) + let* pA_against_pB_op = + start_refutation_game_op block rollup (pA, pA_pkh) pB_pkh + in + let* pA_against_pD_op = + start_refutation_game_op block rollup (pA, pA_pkh) pD_pkh + in + let* pA_op = + Op.batch_operations + ~recompute_counters:true + ~source:pA + (B block) + [pA_against_pB_op; pA_against_pD_op] + in + (* C starts against A so it can win through a move. *) + let* pC_against_pA_op = + start_refutation_game_op block rollup (pC, pC_pkh) pA_pkh + in + let* block = Block.bake block ~operations:[pA_op; pC_against_pA_op] in + let* block = bake_timeout_period block in + + (* B timeouts A. *) + let game_index = Sc_rollup.Game.Index.make pA_pkh pB_pkh in + let* pB_timeout = Op.sc_rollup_timeout (B block) pB rollup game_index in + let* block = Block.bake block ~operation:pB_timeout in + + (* C sends a dumb move but A was already slashed. *) + let dumb_dissection = + let choice = Sc_rollup.Tick.initial in + Sc_rollup.Game.(Move {choice; step = Dissection []}) + in + let* pC_move = + Op.sc_rollup_refute (B block) pC rollup pA_pkh dumb_dissection + in + + (* D timeouts A. *) + let game_index = Sc_rollup.Game.Index.make pA_pkh pD_pkh in + let* pD_timeout = Op.sc_rollup_timeout (B block) pD rollup game_index in + + (* Both operation fails with [Unknown staker], because pA was removed when + it lost against B. *) + let* _block = Block.bake ~operations:[pC_move; pD_timeout] block in + return_unit + +(** Test the same property as in {!test_winner_by_forfeit} but where two + players slashed eachother with a draw. *) +let test_winner_by_forfeit_with_draw () = + let open Lwt_result_syntax in + let* block, rollup, (pA, pA_pkh), (pB, pB_pkh), (pC, pC_pkh), (_pD, _pD_pkh) = + init_with_4_conflicts () + in + let* constants = Context.get_constants (B block) in + let Constants.Parametric.{timeout_period_in_blocks; stake_amount; _} = + constants.parametric.sc_rollup + in + + (* A and B starts a refutation game against C. *) + let* pA_against_pC_op = + start_refutation_game_op block rollup (pA, pA_pkh) pC_pkh + in + let* pB_against_pC_op = + start_refutation_game_op block rollup (pB, pB_pkh) pC_pkh + in + + let* block = Block.bake block ~operation:pA_against_pC_op in + let* block = Block.bake block ~operation:pB_against_pC_op in + + (* A starts a refutation against B. *) + let* frozen_bonds_pA = Context.Contract.frozen_bonds (B block) pA in + let* frozen_bonds_pB = Context.Contract.frozen_bonds (B block) pB in + let* pA_against_pB_op = + start_refutation_game_op block rollup (pA, pA_pkh) pB_pkh + in + let* block = Block.bake block ~operation:pA_against_pB_op in + + (* A and B will both make an invalid move and ends up in a draw. *) + let* dumb_move = + let choice = Sc_rollup.Tick.initial in + dumb_proof ~choice + in + let* pA_dumb_move_op = + Op.sc_rollup_refute (B block) pA rollup pB_pkh dumb_move + in + let* block = Block.bake block ~operation:pA_dumb_move_op in + let* pB_dumb_move_op = + Op.sc_rollup_refute (B block) pB rollup pA_pkh dumb_move + in + let* block = Block.bake block ~operation:pB_dumb_move_op in + + (* Assert the draw by checking the frozen bonds. *) + let* () = + Assert.frozen_bonds_was_debited + ~loc:__LOC__ + (B block) + pA + frozen_bonds_pA + stake_amount + in + let* () = + Assert.frozen_bonds_was_debited + ~loc:__LOC__ + (B block) + pB + frozen_bonds_pB + stake_amount + in + + (* Now C will win the game against A and B with a timeout. *) + let* block = bake_timeout_period ~timeout_period_in_blocks block in + + (* C timeouts A. *) + let game_index = Sc_rollup.Game.Index.make pC_pkh pA_pkh in + let* pC_timeout_pA = Op.sc_rollup_timeout (B block) pC rollup game_index in + let* block = Block.bake block ~operation:pC_timeout_pA in + + (* C timeouts B. *) + let game_index = Sc_rollup.Game.Index.make pC_pkh pB_pkh in + let* pC_timeout_pB = Op.sc_rollup_timeout (B block) pC rollup game_index in + let* _block = Block.bake block ~operation:pC_timeout_pB in + + return_unit + +let test_conflict_point_on_a_branch () = + let open Lwt_result_wrap_syntax in + let* block, (pA, pB), rollup = + init_and_originate ~sc_rollup_challenge_window_in_blocks:1000 Context.T2 + in + let pA_pkh = Account.pkh_of_contract_exn pA in + let pB_pkh = Account.pkh_of_contract_exn pB in + (* pA stakes on a whole branch. *) + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + let* predecessor = + Context.Sc_rollup.commitment (B block) rollup genesis_info.commitment_hash + in + let* commitments_and_hashes = + gen_commitments (B block) rollup ~predecessor ~num_commitments:10 + in + let commitments, _ = List.split commitments_and_hashes in + let* block = publish_commitments block pA rollup commitments in + (* pB stakes on only one commitment. *) + let pA_commitment, pB_commitment = + let commitment = Stdlib.List.nth commitments 8 in + ( commitment, + { + commitment with + compressed_state = + Sc_rollup.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["foo"]); + } ) + in + let* block = publish_commitments block pB rollup [pB_commitment] in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let*@ ( ( {commitment = _; hash = conflict_pA_hash}, + {commitment = _; hash = conflict_pB_hash} ), + _ctxt ) = + Sc_rollup.Refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + pA_pkh + pB_pkh + in + let pA_hash = hash_commitment pA_commitment in + let pB_hash = hash_commitment pB_commitment in + let expected_conflict = + Sc_rollup.Commitment.Hash.( + equal conflict_pA_hash pA_hash && equal conflict_pB_hash pB_hash) + in + Assert.equal_bool ~loc:__LOC__ true expected_conflict + +let test_agreeing_stakers_cannot_play () = + let open Lwt_result_syntax in + let* block, (pA, pB), rollup = + init_and_originate ~sc_rollup_challenge_window_in_blocks:1000 Context.T2 + in + let pB_pkh = Account.pkh_of_contract_exn pB in + (* pA stakes on a whole branch. *) + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + let* predecessor = + Context.Sc_rollup.commitment (B block) rollup genesis_info.commitment_hash + in + let* commitments_and_hashes = + gen_commitments (B block) rollup ~predecessor ~num_commitments:10 + in + let commitments, _ = List.split commitments_and_hashes in + let* block = publish_commitments block pA rollup commitments in + let* block = publish_commitments block pB rollup commitments in + let _, agreed_commitment_hash = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.last_opt commitments_and_hashes + in + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = agreed_commitment_hash; + opponent_commitment_hash = agreed_commitment_hash; + } + in + let* operation = Op.sc_rollup_refute (B block) pA rollup pB_pkh refutation in + let block_res = Block.bake ~operation block in + assert_fails_with ~__LOC__ block_res Sc_rollup_errors.Sc_rollup_no_conflict + +let test_start_game_on_cemented_commitment () = + let open Lwt_result_syntax in + let* block, (pA, pB), rollup = + init_and_originate ~sc_rollup_challenge_window_in_blocks:1000 Context.T2 + in + let* constants = Context.get_constants (B block) in + let pA_pkh = Account.pkh_of_contract_exn pA in + let pB_pkh = Account.pkh_of_contract_exn pB in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + let* predecessor = + Context.Sc_rollup.commitment (B block) rollup genesis_info.commitment_hash + in + let* commitments_and_hashes = + gen_commitments (B block) rollup ~predecessor ~num_commitments:10 + in + (* pA and pB publishes and cements 10 commitments. *) + let commitments, hashes = List.split commitments_and_hashes in + let* block = publish_commitments block pA rollup commitments in + let* block = publish_commitments block pB rollup commitments in + let* block = + cement_commitments + ~challenge_window_in_blocks: + constants.parametric.sc_rollup.challenge_window_in_blocks + block + rollup + pA + hashes + in + + (* We now check that pA and pB cannot start a refutation against on + cemented commitments. *) + List.iter_es + (fun hash -> + (* The refutation game checks that [pA] stakes on [hash] and + [pB] on [hash]. As the storage keeps in the storage only + the metadata for active commitments, any game started on a cemented + commitment will fail with " not staked on ". *) + let refutation = + Sc_rollup.Game.Start + {player_commitment_hash = hash; opponent_commitment_hash = hash} + in + let* pA_against_pB = + Op.sc_rollup_refute (B block) pA rollup pB_pkh refutation + in + let* pB_against_pA = + Op.sc_rollup_refute (B block) pB rollup pA_pkh refutation + in + (* Even if there is no conflict, the refutation game will reject + it before that. This test behaves as a regression test to prevent + to break this property. *) + let wrong_staker_error pkh = + Sc_rollup_errors.Sc_rollup_wrong_staker_for_conflict_commitment + (pkh, hash) + in + let* () = + let block_res = Block.bake ~operation:pA_against_pB block in + assert_fails_with ~__LOC__ block_res (wrong_staker_error pA_pkh) + in + let* () = + let block_res = Block.bake ~operation:pB_against_pA block in + assert_fails_with ~__LOC__ block_res (wrong_staker_error pB_pkh) + in + return_unit) + hashes + +let test_origination_fails_with_empty_whitelist () = + let open Lwt_result_syntax in + let* b, contract = + Context.init1 + ~sc_rollup_arith_pvm_enable:true + ~sc_rollup_private_enable:true + () + in + let kind = Sc_rollup.Kind.Example_arith in + let* operation, _rollup = + Sc_rollup_helpers.origination_op (B b) contract kind ~whitelist:[] + in + let*! b = Block.bake ~operation b in + Assert.proto_error_with_info + ~loc:__LOC__ + b + "Invalid whitelist: whitelist cannot be empty" + +let test_private_rollup_can_be_deactivated () = + let open Lwt_result_syntax in + let* b, contract = + Context.init1 + ~sc_rollup_arith_pvm_enable:true + ~sc_rollup_private_enable:false + () + in + let kind = Sc_rollup.Kind.Example_arith in + let* operation, _rollup = + Sc_rollup_helpers.origination_op (B b) contract kind ~whitelist:[] + in + let*! b = Block.bake ~operation b in + Assert.proto_error_with_info + ~loc:__LOC__ + b + "Invalid whitelist: must be None when the feature is deactivated" + +let test_private_rollup_publish_succeeds_with_whitelisted_staker () = + let open Lwt_result_syntax in + let* b, contract = + Context.init1 + ~sc_rollup_arith_pvm_enable:true + ~sc_rollup_private_enable:true + () + in + let kind = Sc_rollup.Kind.Example_arith in + let staker_pkh = Account.pkh_of_contract_exn contract in + let* operation, rollup = + Sc_rollup_helpers.origination_op (B b) contract kind ~whitelist:[staker_pkh] + in + let* b = Block.bake ~operation b in + let* commitment = dummy_commitment (B b) rollup in + let* operation = Op.sc_rollup_publish (B b) contract rollup commitment in + let*! _b = Block.bake ~operation b in + return_unit + +let test_private_rollup_publish_fails_with_non_whitelisted_staker () = + let open Lwt_result_syntax in + let* b, (contract1, contract2) = + Context.init2 + ~sc_rollup_arith_pvm_enable:true + ~sc_rollup_private_enable:true + () + in + let kind = Sc_rollup.Kind.Example_arith in + let* operation, rollup = + Sc_rollup_helpers.origination_op + (B b) + contract1 + kind + ~whitelist:[Context.Contract.pkh contract2] + in + let* b = Block.bake ~operation b in + let* commitment = dummy_commitment (B b) rollup in + let* operation = Op.sc_rollup_publish (B b) contract1 rollup commitment in + let*! b = Block.bake ~operation b in + let* () = + Assert.proto_error + ~loc:__LOC__ + b + (( = ) Sc_rollup_errors.Sc_rollup_staker_not_in_whitelist) + in + return_unit + +let test_private_rollup_whitelist_cannot_contain_key_duplication () = + let open Lwt_result_syntax in + let* block, (account1, account2) = context_init Context.T2 in + let account2_pkh = Account.pkh_of_contract_exn account2 in + let originate_with_whitelist ~whitelist block = + sc_originate ?whitelist block account1 + in + let whitelist = Some [account2_pkh; account2_pkh] in + let block_rollup_res = originate_with_whitelist ~whitelist block in + assert_fails_with + ~__LOC__ + block_rollup_res + Sc_rollup_errors.Sc_rollup_duplicated_key_in_whitelist + +let update_whitelist ?(message_index = 1) + ~(genesis_info : Sc_rollup.Commitment.genesis_info) block rollup + updated_whitelist = + let open Lwt_result_syntax in + let output = + make_whitelist_update_output + ~outbox_level:Raw_level.(Int32.to_int @@ to_int32 @@ genesis_info.level) + ~message_index + updated_whitelist + in + let* _res, block = + execute_outbox_message_without_proof_validation + block + rollup + ~cemented_commitment:genesis_info.commitment_hash + output + in + return block + +let verify_whitelist ~__LOC__ block rollup expected_whitelist = + verify_whitelist ~loc:__LOC__ rollup (B block) ~expected_whitelist + +let verify_can_publish_commit_accounts block rollup accounts = + Tezos_base.TzPervasives.List.iter_es + (fun (account, succeed) -> + verify_can_publish_commit ~__LOC__ ~succeed rollup account block) + accounts + +let test_check_initial_whitelist () = + let open Lwt_result_syntax in + let* block, (account1, account2, account3) = context_init Context.T3 in + let account1_pkh = Account.pkh_of_contract_exn account1 in + let whitelist = Some [account1_pkh] in + let* block, rollup = sc_originate ?whitelist block account1 in + (* check initial whitelist *) + let* () = verify_whitelist ~__LOC__ block rollup whitelist in + verify_can_publish_commit_accounts + block + rollup + [(account1, true); (account2, false); (account3, false)] + +let test_whitelist_update_duplicated_keys () = + let open Lwt_result_syntax in + let* block, (account1, account2) = context_init Context.T2 in + let account1_pkh = Account.pkh_of_contract_exn account1 in + let account2_pkh = Account.pkh_of_contract_exn account2 in + let whitelist = Some [account1_pkh] in + let* block, rollup = sc_originate ?whitelist block account1 in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + (* replace whitelist with twice the same keys fails *) + let updated_whitelist = Some [account2_pkh; account2_pkh] in + let block_rollup_res = + update_whitelist ~genesis_info block rollup updated_whitelist + in + assert_fails_with + ~__LOC__ + block_rollup_res + Sc_rollup_errors.Sc_rollup_duplicated_key_in_whitelist + +let test_whitelist_update_empty_list () = + let open Lwt_result_syntax in + let* block, account = context_init Context.T1 in + let account_pkh = Account.pkh_of_contract_exn account in + let whitelist = Some [account_pkh] in + let* block, rollup = sc_originate ?whitelist block account in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + (* update to empty list fails *) + let updated_whitelist = Some [] in + let block_res = + update_whitelist ~genesis_info block rollup updated_whitelist + in + assert_fails_with + ~__LOC__ + block_res + Sc_rollup_errors.Sc_rollup_empty_whitelist + +let test_whitelist_update_two_keys () = + let open Lwt_result_syntax in + let* block, (account1, account2, account3) = context_init Context.T3 in + let account1_pkh = Account.pkh_of_contract_exn account1 in + let account2_pkh = Account.pkh_of_contract_exn account2 in + let account3_pkh = Account.pkh_of_contract_exn account3 in + let whitelist = Some [account1_pkh] in + let* block, rollup = sc_originate ?whitelist block account1 in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + + (* replace whitelist with two keys succeed *) + let updated_whitelist = Some [account2_pkh; account3_pkh] in + let* block = update_whitelist ~genesis_info block rollup updated_whitelist in + let* () = verify_whitelist ~__LOC__ block rollup updated_whitelist in + verify_can_publish_commit_accounts + block + rollup + [(account1, false); (account2, true); (account3, true)] + +let test_whitelist_update_make_rollup_public () = + let open Lwt_result_syntax in + let* block, (account1, account2, account3) = context_init Context.T3 in + let account1_pkh = Account.pkh_of_contract_exn account1 in + let account2_pkh = Account.pkh_of_contract_exn account2 in + let account3_pkh = Account.pkh_of_contract_exn account3 in + let whitelist = Some [account1_pkh] in + let* block, rollup = sc_originate ?whitelist block account1 in + let* genesis_info = Context.Sc_rollup.genesis_info (B block) rollup in + + let* block = + (* replace whitelist with two keys succeed *) + let updated_whitelist = Some [account2_pkh; account3_pkh] in + let* block = + update_whitelist ~genesis_info block rollup updated_whitelist + in + let* () = verify_whitelist ~__LOC__ block rollup updated_whitelist in + let* () = + verify_can_publish_commit_accounts + block + rollup + [(account1, false); (account2, true); (account3, true)] + in + return block + in + (* second update succeed and make the rollup public *) + let updated_whitelist = None in + let* block = + update_whitelist + ~genesis_info + ~message_index:2 + block + rollup + updated_whitelist + in + let* () = verify_whitelist ~__LOC__ block rollup updated_whitelist in + let* () = + verify_can_publish_commit_accounts + block + rollup + [(account1, true); (account2, true); (account3, true)] + in + return_unit + +let tests = + [ + Tztest.tztest + "check effect of disabled arith pvm flag" + `Quick + test_disable_arith_pvm_feature_flag; + Tztest.tztest + "check effect of disabled RISC-V pvm flag" + `Quick + test_disable_riscv_pvm_feature_flag; + Tztest.tztest + "can publish a commit, cement it and withdraw stake" + `Quick + test_publish_cement_and_recover_bond; + Tztest.tztest + "publish will fail if staker is double staking" + `Quick + test_publish_fails_on_double_stake; + Tztest.tztest + "cement will fail if commitment is contested" + `Quick + test_cement_fails_on_conflict; + Tztest.tztest + "check the challenge window period boundaries" + `Quick + test_challenge_window_period_boundaries; + Tztest.tztest + "originating with invalid types" + `Quick + test_originating_with_invalid_types; + Tztest.tztest + "originating with valid type" + `Quick + test_originating_with_valid_type; + Tztest.tztest + "single transaction atomic batch" + `Quick + test_single_transaction_batch; + Tztest.tztest + "execute outbox message against older cemented commitment" + `Quick + test_older_cemented_commitment; + Tztest.tztest + "multi-transaction atomic batch" + `Quick + test_multi_transaction_batch; + Tztest.tztest + "transaction with invalid type" + `Quick + test_transaction_with_invalid_type; + Tztest.tztest "execute same message twice" `Quick test_execute_message_twice; + Tztest.tztest + "execute same message twice against different cemented commitments" + `Quick + test_execute_message_twice_different_cemented_commitments; + Tztest.tztest + "transaction with zero amount ticket" + `Quick + test_zero_amount_ticket; + Tztest.tztest "invalid output proof" `Quick test_invalid_output_proof; + Tztest.tztest + "outbox message that overrides an old slot" + `Quick + test_execute_message_override_applied_messages_slot; + Tztest.tztest + "insufficient ticket balances" + `Quick + test_insufficient_ticket_balances; + Tztest.tztest + "inbox max number of messages per inbox level" + `Quick + test_inbox_max_number_of_messages_per_level; + Tztest.tztest + "a player can't timeout another player before timeout period and related \ + timeout value." + `Quick + test_timeout; + Tztest.tztest + "a player cannot play more than max_number_of_parallel_games games in \ + parallel." + `Quick + test_number_of_parallel_games_bounded; + Tztest.tztest + "Two invalid final moves end the game in a draw situation" + `Quick + test_draw_with_two_invalid_moves; + Tztest.tztest + "Timeout during the final move can end the game in a draw situation" + `Quick + test_timeout_during_final_move; + Tztest.tztest + "Multiple draw in parallel game are valid" + `Quick + test_draw_with_parallel_game; + Tztest.tztest + "Cannot play a dissection when the final move has started" + `Quick + test_dissection_during_final_move; + Tztest.tztest + "Invalid metadata initialization can be refuted" + `Quick + test_refute_invalid_metadata; + Tztest.tztest + "Invalid reveal can be refuted" + `Quick + test_refute_invalid_reveal; + Tztest.tztest + "SOL/Info_per_level/EOL are added in the inbox" + `Quick + test_automatically_added_internal_messages; + Tztest.tztest + "0-tick commitments are forbidden" + `Quick + test_zero_tick_commitment_fails; + Tztest.tztest "the curfew functionality" `Quick test_curfew; + Tztest.tztest + "a commitment can be published after the inbox_level + challenge window \ + is passed." + `Quick + test_curfew_period_is_started_only_after_first_publication; + Tztest.tztest + "An offline staker should not prevent cementation" + `Quick + test_offline_staker_does_not_prevent_cementation; + Tztest.tztest "win refutation game by forfeit" `Quick test_winner_by_forfeit; + Tztest.tztest + "win refutation game by forfeit with draw" + `Quick + test_winner_by_forfeit_with_draw; + Tztest.tztest + "cannot start a game with agreeing stakers" + `Quick + test_agreeing_stakers_cannot_play; + Tztest.tztest + "find conflict point with incomplete branch" + `Quick + test_conflict_point_on_a_branch; + Tztest.tztest + "cannot start a game on a cemented commitment" + `Quick + test_start_game_on_cemented_commitment; + Tztest.tztest + "Origination fails with empty whitelist" + `Quick + test_origination_fails_with_empty_whitelist; + Tztest.tztest + "Origination can be deactivated" + `Quick + test_private_rollup_can_be_deactivated; + Tztest.tztest + "Submit a commitment with a whitelisted staker" + `Quick + test_private_rollup_publish_succeeds_with_whitelisted_staker; + Tztest.tztest + "Submit a commitment with a non-whitelisted staker" + `Quick + test_private_rollup_publish_fails_with_non_whitelisted_staker; + Tztest.tztest + "Originate a rollup with duplicated key in the whitelist fails" + `Quick + test_private_rollup_whitelist_cannot_contain_key_duplication; + Tztest.tztest "Check initial whitelist" `Quick test_check_initial_whitelist; + Tztest.tztest + "Update the whitelist with duplicated keys" + `Quick + test_whitelist_update_duplicated_keys; + Tztest.tztest + "Update the whitelist with an empty list" + `Quick + test_whitelist_update_empty_list; + Tztest.tztest + "Update the whitelist with two distinct keys" + `Quick + test_whitelist_update_two_keys; + Tztest.tztest + "Update the whitelist to make the rollup public" + `Quick + test_whitelist_update_make_rollup_public; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml new file mode 100644 index 000000000000..9922bd9114a4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_sc_rollup_transfer.ml @@ -0,0 +1,430 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Sc rollup L1/L2 communication + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_sc_rollup_transfer.ml + Subject: Test transfers from Michelson to smart contract rollups +*) + +open Protocol +open Alpha_context + +(* Helpers *) + +exception Unexpected_error + +let check_proto_error ~loc ~exp f trace = + let open Lwt_result_syntax in + let*? proto_trace = + List.map_e + (function + | Environment.Ecoproto_error e -> Ok e + | e -> + error_with + "At %s, expected protocol error %s, got non-protocol error %a in \ + trace %a" + loc + exp + Error_monad.pp + e + Error_monad.pp_print_trace + trace) + trace + in + try f proto_trace + with Unexpected_error -> + failwith + "At %s, expected error %s, got %a" + loc + exp + Error_monad.pp_print_trace + trace + +let sc_originate = Test_sc_rollup.sc_originate + +(* A contract with four entrypoints: + - [transfer_non_zero] takes a [contract int] and attempts to transfer with a + non-zero amount to it. Expected to fail. + + - [transfer_int] takes a [contract int] and transfers an int to it. Expected + to succeed. + + - [transfer_zero_ticket] takes a [contract (ticket string)] and transfers a + zero-amount ticket to it. Expected to fail. + + - [transfer_ticket] takes a [contract (ticket string)] and transfers a + ticket to it. Expected to succeed. +*) +let contract_originate block account = + let script = + {| + parameter (or (contract %transfer_non_zero int) + (or (contract %transfer_int int) + (or (contract %transfer_zero_ticket (ticket string)) + (or (contract %transfer_ticket (ticket string)) + never)))); + storage unit; + code { + UNPAIR; + IF_LEFT { + # transfer_non_zero + PUSH mutez 1; + PUSH int 42; + TRANSFER_TOKENS; + } { + IF_LEFT { + # transfer_int + PUSH mutez 0; + PUSH int 42; + TRANSFER_TOKENS; + } { + IF_LEFT { + # transfer_zero_ticket + PUSH mutez 0; + PUSH nat 0; + PUSH string "ticket payload"; + TICKET; + ASSERT_SOME; + TRANSFER_TOKENS; + } { + IF_LEFT { + # transfer ticket + PUSH mutez 0; + PUSH nat 137; + PUSH string "G"; + TICKET; + ASSERT_SOME; + TRANSFER_TOKENS; + } { + NEVER + } + } + } + }; + NIL operation; + SWAP; + CONS; + PAIR } +|} + in + Contract_helpers.originate_contract_from_string_hash + ~baker:(Context.Contract.pkh account) + ~source_contract:account + ~script + ~storage:"Unit" + block + +let context_init parameters_ty = + let open Lwt_result_syntax in + let* b, c = Test_sc_rollup.context_init T1 in + let* contract, _script, b = contract_originate b c in + let* b, rollup = sc_originate b c ~parameters_ty in + return (b, c, contract, rollup) + +let transfer ?expect_apply_failure b ~from ~to_ ~param ~entrypoint = + let open Lwt_result_syntax in + let parameters = Script.lazy_expr (Expr.from_string param) in + let* op = + Op.transaction + (B b) + from + (Contract.Originated to_) + Tez.zero + ~parameters + ~entrypoint:(Entrypoint.of_string_strict_exn entrypoint) + ~gas_limit:High + in + let* inc = Incremental.begin_construction b in + let* inc = Incremental.add_operation ?expect_apply_failure inc op in + Incremental.finalize_block inc + +(* Tests *) + +(* Test parsing a [contract] with a badly formatted sr1 address. *) +let test_transfer_to_bad_sc_rollup_address () = + let open Lwt_result_syntax in + let* b, c, contract, _rollup = context_init "unit" in + let not_an_sc_rollup_address = {|"sr1Fq8fPi2NjhWUXtcXBggbL6zFjZctDamso"|} in + let* (_b : Block.t) = + transfer + b + ~from:c + ~to_:contract + ~param:not_an_sc_rollup_address + ~entrypoint:"transfer_non_zero" + ~expect_apply_failure: + (check_proto_error ~loc:__LOC__ ~exp:"Invalid_destination_b58check" + @@ function + | [ + Script_interpreter.Bad_contract_parameter _; + Script_tc_errors.Invalid_constant (_loc, _expr, ty); + Destination_repr.Invalid_destination_b58check _; + ] -> + Assert.equal_string + ~loc:__LOC__ + "(contract int)" + (Expr.to_string ty) + | _ -> raise Unexpected_error) + in + return_unit + +(* Now, the address is well-formatted but the rollup does not exist. *) +let test_transfer_to_unknown_sc_rollup_address () = + let open Lwt_result_syntax in + let* b, c, contract, _rollup = context_init "unit" in + let unknown_sc_rollup_address = {|"sr1Fq8fPi2NjhWUXtcXBggbL6zFjZctGkmso"|} in + let* (_b : Block.t) = + transfer + b + ~from:c + ~to_:contract + ~param:unknown_sc_rollup_address + ~entrypoint:"transfer_non_zero" + ~expect_apply_failure: + (check_proto_error ~loc:__LOC__ ~exp:"Sc_rollup_does_not_exist" + @@ function + | [ + Script_interpreter.Bad_contract_parameter _; + Script_tc_errors.Invalid_constant _; + Sc_rollup_errors.Sc_rollup_does_not_exist _; + ] -> + return_unit + | _ -> raise Unexpected_error) + in + return_unit + +(* Now, let's originate an sc rollup, use its address but with a wrong type. *) +let test_transfer_to_wrongly_typed_sc_rollup () = + let open Lwt_result_syntax in + let* b, c, contract, rollup = context_init "unit" in + let param = Format.sprintf "%S" (Sc_rollup.Address.to_b58check rollup) in + let* (_b : Block.t) = + transfer + b + ~from:c + ~to_:contract + ~param + ~entrypoint:"transfer_non_zero" + ~expect_apply_failure: + (check_proto_error ~loc:__LOC__ ~exp:"Inconsistent_types" @@ function + | [ + Script_interpreter.Bad_contract_parameter _; + Script_tc_errors.Invalid_constant _; + Script_tc_errors.Inconsistent_types _; + Script_tc_errors.Inconsistent_types _; + ] -> + return_unit + | _ -> raise Unexpected_error) + in + return_unit + +(* Use the correct type but with a non-zero amount. *) +let test_transfer_non_zero_amount () = + let open Lwt_result_syntax in + let* b, c, contract, rollup = context_init "int" in + let param = Format.sprintf "%S" (Sc_rollup.Address.to_b58check rollup) in + let* (_b : Block.t) = + transfer + b + ~from:c + ~to_:contract + ~param + ~entrypoint:"transfer_non_zero" + ~expect_apply_failure: + (check_proto_error ~loc:__LOC__ ~exp:"Rollup_invalid_transaction_amount" + @@ function + | [ + Script_interpreter.Runtime_contract_error _; + Script_interpreter_defs.Rollup_invalid_transaction_amount; + ] -> + return_unit + | _ -> raise Unexpected_error) + in + return_unit + +(* Use the correct type through an entrypoint but with a non-zero amount. *) +let test_transfer_non_zero_amount_via_entrypoint () = + let open Lwt_result_syntax in + let* b, c, contract, rollup = context_init "int" in + let param = Format.sprintf "%S" (Sc_rollup.Address.to_b58check rollup) in + let* (_b : Block.t) = + transfer + b + ~from:c + ~to_:contract + ~param + ~entrypoint:"transfer_non_zero" + ~expect_apply_failure: + (check_proto_error ~loc:__LOC__ ~exp:"Rollup_invalid_transaction_amount" + @@ function + | [ + Script_interpreter.Runtime_contract_error _; + Script_interpreter_defs.Rollup_invalid_transaction_amount; + ] -> + return_unit + | _ -> raise Unexpected_error) + in + return_unit + +(* Now, transfer with a zero-amount and check that the inbox has been updated correctly. *) +let test_transfer_works () = + let open Lwt_result_wrap_syntax in + let* b, c, contract, rollup = context_init "int" in + let* inbox_before = Context.Sc_rollup.inbox (B b) in + let* expected_inbox_after = + let* inc = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt inc in + let payload = Expr.from_string "42" in + let*@ ctxt = + Sc_rollup.Inbox.add_deposit + ctxt + ~destination:rollup + ~payload + ~sender:contract + ~source:(Context.Contract.pkh c) + in + let incr = Incremental.set_alpha_ctxt inc ctxt in + let* block = Incremental.finalize_block incr in + let* expected_inbox_after = Context.Sc_rollup.inbox (B block) in + return expected_inbox_after + in + let param = Format.sprintf "%S" (Sc_rollup.Address.to_b58check rollup) in + let* b = transfer b ~from:c ~to_:contract ~param ~entrypoint:"transfer_int" in + let* inbox_after = Context.Sc_rollup.inbox (B b) in + let* () = + Assert.not_equal_with_encoding + ~loc:__LOC__ + Sc_rollup.Inbox.encoding + inbox_before + inbox_after + in + Assert.equal_with_encoding + ~loc:__LOC__ + Sc_rollup.Inbox.encoding + inbox_after + expected_inbox_after + +(* Transfer of zero-amount ticket fails. *) +let test_transfer_zero_amount_ticket () = + let open Lwt_result_syntax in + let* b, c, contract, rollup = context_init "ticket string" in + let param = Format.sprintf "%S" (Sc_rollup.Address.to_b58check rollup) in + let* (_b : Block.t) = + transfer + b + ~from:c + ~to_:contract + ~param + ~entrypoint:"transfer_zero_ticket" + ~expect_apply_failure: + (check_proto_error ~loc:__LOC__ ~exp:"Script_rejected" @@ function + | [ + Script_interpreter.Runtime_contract_error _; + Script_interpreter.Reject _; + ] -> + return_unit + | _ -> raise Unexpected_error) + in + return_unit + +(* Transfer of a non-zero-amount ticket works and the balance table is correctly updated. *) +let test_transfer_non_zero_amount_ticket () = + let open Lwt_result_wrap_syntax in + let* b, c, contract, rollup = context_init "ticket string" in + let param = Format.sprintf "%S" (Sc_rollup.Address.to_b58check rollup) in + let* b = + transfer b ~from:c ~to_:contract ~param ~entrypoint:"transfer_ticket" + in + let* ticket_key_for_contract, ticket_key_for_rollup, ctxt = + let* ticket_token = + Ticket_helpers.string_ticket_token + (Contract_hash.to_b58check contract) + "G" + in + let* inc = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt inc in + let*@ ticket_key_for_contract, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract (Originated contract)) + ticket_token + in + let*@ ticket_key_for_rollup, _ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Sc_rollup rollup) + ticket_token + in + return (ticket_key_for_contract, ticket_key_for_rollup, ctxt) + in + (* The rollup is the owner of the tickets *) + let* () = + Ticket_helpers.assert_balance + ctxt + ~loc:__LOC__ + ticket_key_for_rollup + (Some 137) + in + (* The contract didn't retain any ticket in the operation *) + let* () = + Ticket_helpers.assert_balance ctxt ~loc:__LOC__ ticket_key_for_contract None + in + return_unit + +let tests = + [ + Tztest.tztest + "Transfer to a bad sc rollup address" + `Quick + test_transfer_to_bad_sc_rollup_address; + Tztest.tztest + "Transfer to an unknown rollup address" + `Quick + test_transfer_to_unknown_sc_rollup_address; + Tztest.tztest + "Transfer with a wrong type" + `Quick + test_transfer_to_wrongly_typed_sc_rollup; + Tztest.tztest + "Transfer with a non-zero amount" + `Quick + test_transfer_non_zero_amount_via_entrypoint; + Tztest.tztest "Transfer works" `Quick test_transfer_works; + Tztest.tztest + "Transfer of zero-amount ticket" + `Quick + test_transfer_zero_amount_ticket; + Tztest.tztest + "Transfer of non-zero-amount ticket" + `Quick + test_transfer_non_zero_amount_ticket; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup transfer", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer.ml new file mode 100644 index 000000000000..8745c95d4e1e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer.ml @@ -0,0 +1,979 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (transfer) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_transfer.ml + Subject: Quantities transfer between contracts. +*) + +open Protocol +open Alpha_context +open Test_tez +open Transfers + +(*********************************************************************) +(* Utility functions *) +(*********************************************************************) + +(** + [transfer_to_itself_and_check_balances b fee contract amount] + this function takes a block, an optional parameter fee, + a contract that is a source and a destination contract, + and an amount of tez that one wants to transfer. + + 1- Transfer the amount of tez (w/wo transfer fee) from/to a contract itself. + + 2- Check the equivalent of the balance of the contract before + and after transfer. + + This function returns a pair: + - a block that added the valid transaction + - an valid transaction *) +let transfer_to_itself_and_check_balances ~loc ?policy b ?(fee = Tez.zero) + contract amount = + let open Lwt_result_syntax in + let* bal = Context.Contract.balance (B b) contract in + let* operation = Op.transaction (B b) ~fee contract contract amount in + let* b = Block.bake ?policy ~operation b in + let+ () = Assert.balance_was_debited ~loc (B b) contract bal fee in + (b, operation) + +let ten_tez = of_int 10 + +(*********************************************************************) +(* Tests *) +(*********************************************************************) + +(** Compute a fraction of 2/[n] of the balance of [contract] *) +let two_over_n_of_balance ctxt contract n = + let open Lwt_result_syntax in + let* balance = Context.Contract.balance ctxt contract in + let res = balance /! n in + let res = res *? 2L in + Lwt.return res + +(********************) +(** Single transfer *) + +(********************) + +let single_transfer ?fee ?expect_apply_failure amount = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 () in + let* b = Incremental.begin_construction b in + let* b, _ = + transfer_and_check_balances + ~loc:__LOC__ + ?fee + ?expect_apply_failure + b + contract_1 + contract_2 + amount + in + let* (_ : Block.t) = Incremental.finalize_block b in + return_unit + +(** Single transfer without fee. *) +let test_block_with_a_single_transfer () = single_transfer Tez.one + +(** Single transfer with fee. *) +let test_block_with_a_single_transfer_with_fee () = + single_transfer ~fee:Tez.one Tez.one + +(** Single transfer without fee. *) +let test_transfer_zero_tez () = + let open Lwt_result_syntax in + let expect_apply_failure = function + | Environment.Ecoproto_error (Apply.Empty_transaction _ as err) :: _ -> + Assert.test_error_encodings err ; + return_unit + | _ -> failwith "Empty transaction should fail" + in + single_transfer ~expect_apply_failure Tez.zero + +(** Transfer zero tez from an implicit contract. *) +let test_transfer_zero_implicit () = + let open Lwt_result_syntax in + let* b, dest = Context.init1 () in + let account = Account.new_account () in + let* i = Incremental.begin_construction b in + let src = Contract.Implicit account.Account.pkh in + let* op = Op.transaction (I i) src dest Tez.zero in + let*! res = Incremental.add_operation i op in + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Empty_implicit_contract _ as err -> + Assert.test_error_encodings err ; + true + | _ -> false) + +(** Transfer to originated contract. *) +let test_transfer_to_originate_with_fee () = + let open Lwt_result_syntax in + let* b, contract = Context.init1 ~consensus_threshold:0 () in + let* fee = two_over_n_of_balance (B b) contract 10L in + (* originated contract, paying a fee to originated this contract *) + let* operation, new_contract = + Op.contract_origination (B b) ~fee:ten_tez contract ~script:Op.dummy_script + in + let* b = Block.bake ~operation b in + let* amount = two_over_n_of_balance (B b) contract 3L in + let* i = Incremental.begin_construction b in + let* i, _ = + transfer_and_check_balances ~loc:__LOC__ i ~fee contract new_contract amount + in + let* (_ : Block.t) = Incremental.finalize_block i in + return_unit + +(** Transfer from balance. *) +let test_transfer_amount_of_contract_balance () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 () in + let pkh1 = Context.Contract.pkh contract_1 in + (* given that contract_1 no longer has a sufficient balance to bake, + make sure it cannot be chosen as baker *) + let* b = Incremental.begin_construction b ~policy:(Block.Excluding [pkh1]) in + (* get the balance of the source contract *) + let* balance = Context.Contract.balance (I b) contract_1 in + (* transfer all the tez inside contract 1 *) + let* b, _ = + transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 balance + in + let* (_ : Block.t) = Incremental.finalize_block b in + return_unit + +(** Transfer to oneself. *) +let test_transfers_to_self () = + let open Lwt_result_syntax in + let* b, (contract, _) = Context.init2 ~consensus_threshold:0 () in + let* amount = two_over_n_of_balance (B b) contract 3L in + let pkh1 = Context.Contract.pkh contract in + let* b, _ = + transfer_to_itself_and_check_balances + ~loc:__LOC__ + ~policy:(Block.Excluding [pkh1]) + b + contract + amount + in + let* fee = two_over_n_of_balance (B b) contract 5L in + let* _, _ = + transfer_to_itself_and_check_balances + ~loc:__LOC__ + b + ~policy:(Block.Excluding [pkh1]) + ~fee + contract + ten_tez + in + return_unit + +(** Forgot to add the valid transaction into the block. *) +let test_missing_transaction () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 ~consensus_threshold:0 () in + (* given that contract_1 no longer has a sufficient balance to bake, + make sure it cannot be chosen as baker *) + let pkh1 = Context.Contract.pkh contract_1 in + let* i = Incremental.begin_construction b ~policy:(Block.Excluding [pkh1]) in + let* amount = two_over_n_of_balance (B b) contract_1 6L in + (* Do the transfer 3 times from source contract to destination contract *) + let* i = n_transactions 3 i contract_1 contract_2 amount in + (* do the fourth transfer from source contract to destination contract *) + let* (_ : packed_operation) = + Op.transaction (I i) contract_1 contract_2 amount + in + let* (_ : Block.t) = Incremental.finalize_block i in + return_unit + +(** Transfer zero tez to an implicit contract, with fee equals balance of src. *) +let test_transfer_zero_implicit_with_bal_src_as_fee () = + let open Lwt_result_syntax in + let* b, dest = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let src_pkh = account.Account.pkh in + let src = Contract.Implicit src_pkh in + let* operation = + Op.transaction ~force_reveal:true (B b) dest src (Tez.of_mutez_exn 100L) + in + let* b = Block.bake ~operation b in + let* bal_src = Context.Contract.balance (B b) src in + let* () = Assert.equal_tez ~loc:__LOC__ bal_src (Tez.of_mutez_exn 100L) in + let* op = + Op.transaction ~force_reveal:true (B b) ~fee:bal_src src dest Tez.zero + in + (* Transferring zero tez should result in an application failure as + the implicit contract has been depleted. *) + let expect_apply_failure = function + | [ + Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract pkh); + ] + when pkh = src_pkh -> + return_unit + | _ -> assert false + in + let* i = Incremental.begin_construction b in + let* inc = Incremental.add_operation ~expect_apply_failure i op in + let* balance = Context.Contract.balance (I inc) src in + (* We assert that the failing operation was included and that the + fees were taken, effectively depleting the contract. *) + let* () = Assert.equal_tez ~loc:__LOC__ balance Tez.zero in + (* Empty contracts should be unrevealed *) + let* revelead = Context.Contract.is_manager_key_revealed (I inc) src in + when_ revelead (fun () -> + Stdlib.failwith "Empty account still exists and is revealed.") + +(** Transfer zero tez to an originated contract, with fee equals balance of src. *) +let test_transfer_zero_to_originated_with_bal_src_as_fee () = + let open Lwt_result_syntax in + let* b, dest = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let src = Contract.Implicit account.Account.pkh in + let* operation = Op.transaction (B b) dest src (Tez.of_mutez_exn 100L) in + let* b = Block.bake ~operation b in + let* operation, new_contract = + Op.contract_origination (B b) dest ~script:Op.dummy_script + in + let* b = Block.bake ~operation b in + let* bal_src = Context.Contract.balance (B b) src in + let* operation = Op.revelation (B b) ~fee:Tez.zero account.pk in + let* b = Block.bake ~operation b in + let* operation = + Op.transaction (B b) ~fee:bal_src src new_contract Tez.zero + in + let* () = Assert.equal_tez ~loc:__LOC__ bal_src (Tez.of_mutez_exn 100L) in + let* (_ : Block.t) = Block.bake ~operation b in + return_unit + +(** Transfer one tez to an implicit contract, with fee equals balance of src. *) +let test_transfer_one_to_implicit_with_bal_src_as_fee () = + let open Lwt_result_syntax in + let* b, dest = Context.init1 ~consensus_threshold:0 () in + let account = Account.new_account () in + let src = Contract.Implicit account.Account.pkh in + let* operation = Op.transaction (B b) dest src (Tez.of_mutez_exn 100L) in + let* b = Block.bake ~operation b in + let* bal_src = Context.Contract.balance (B b) src in + let* () = Assert.equal_tez ~loc:__LOC__ bal_src (Tez.of_mutez_exn 100L) in + let* operation = Op.revelation (B b) ~fee:Tez.zero account.pk in + let* b = Block.bake ~operation b in + let* op = Op.transaction (B b) ~fee:bal_src src dest Tez.one in + let* i = Incremental.begin_construction b in + let* (_ : Incremental.t) = + Incremental.add_operation i op ~expect_apply_failure:(function + | Environment.Ecoproto_error (Contract_storage.Balance_too_low _ as err) + :: _ -> + Assert.test_error_encodings err ; + return_unit + | t -> failwith "Unexpected error: %a" Error_monad.pp_print_trace t) + in + return_unit + +(********************) +(* The following tests are for different kind of contracts: + - implicit to implicit + - implicit to originated + - originated to implicit + - originated to originated *) + +(********************) + +(** Implicit to Implicit. *) +let test_transfer_from_implicit_to_implicit_contract () = + let open Lwt_result_syntax in + let* b, bootstrap_contract = Context.init1 ~consensus_threshold:0 () in + let account_a = Account.new_account () in + let account_b = Account.new_account () in + let src = Contract.Implicit account_a.Account.pkh in + let* amount1 = two_over_n_of_balance (B b) bootstrap_contract 3L in + let* fee1 = two_over_n_of_balance (B b) bootstrap_contract 10L in + let* i = Incremental.begin_construction b in + let* i, _ = + transfer_and_check_balances + ~with_burn:true + ~loc:__LOC__ + ~fee:fee1 + i + bootstrap_contract + src + amount1 + in + let* b = Incremental.finalize_block i in + let* i = Incremental.begin_construction b in + (* Create an implicit contract as a destination contract. *) + let dest = Contract.Implicit account_b.pkh in + let* amount2 = two_over_n_of_balance (I i) bootstrap_contract 4L in + let* fee2 = two_over_n_of_balance (I i) bootstrap_contract 10L in + (* Transfer from implicit contract to another implicit contract. *) + let* b, _ = + transfer_and_check_balances + ~with_burn:true + ~loc:__LOC__ + ~fee:fee2 + i + src + dest + amount2 + in + let* (_ : Block.t) = Incremental.finalize_block b in + return_unit + +(** Implicit to originated. *) +let test_transfer_from_implicit_to_originated_contract () = + let open Lwt_result_syntax in + let* b, bootstrap_contract = Context.init1 ~consensus_threshold:0 () in + let contract = bootstrap_contract in + let account = Account.new_account () in + let src = Contract.Implicit account.Account.pkh in + let* amount1 = two_over_n_of_balance (B b) bootstrap_contract 3L in + let* i = Incremental.begin_construction b in + (* transfer the money to implicit contract *) + let* i, _ = + transfer_and_check_balances + ~with_burn:true + ~loc:__LOC__ + i + bootstrap_contract + src + amount1 + in + let* b = Incremental.finalize_block i in + let* i = Incremental.begin_construction b in + (* originated contract *) + let* operation, new_contract = + Op.contract_origination + ~force_reveal:true + (I i) + contract + ~script:Op.dummy_script + in + let* i = Incremental.add_operation i operation in + let* amount2 = two_over_n_of_balance (I i) bootstrap_contract 4L in + (* transfer from implicit contract to originated contract *) + let* i, _ = + transfer_and_check_balances ~loc:__LOC__ i src new_contract amount2 + in + let* (_ : Block.t) = Incremental.finalize_block i in + return_unit + +(********************) +(* Slow tests case *) + +(********************) + +let multiple_transfer n ?fee amount = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 ~consensus_threshold:0 () in + let* b = Incremental.begin_construction b in + let* b = n_transactions n b ?fee contract_1 contract_2 amount in + let* (_ : Block.t) = Incremental.finalize_block b in + return_unit + +(** 1- Create a block with two contracts; + 2- Apply 100 transfers. +*) +let test_block_with_multiple_transfers () = multiple_transfer 99 (of_int 1000) + +(** 1- Create a block with two contracts; + 2- Apply 100 transfers with 10tz fee. *) +let test_block_with_multiple_transfers_pay_fee () = + multiple_transfer 10 ~fee:ten_tez (of_int 1000) + +(* TODO : increase the number of operations and add a `Slow tag to it in `tests` *) + +(** 1- Create a block with 8 contracts; + 2- Apply multiple transfers without fees; + 3- Apply multiple transfers with fees. *) +let test_block_with_multiple_transfers_with_without_fee () = + let open Lwt_result_syntax in + let* b, contracts = Context.init_n ~consensus_threshold:0 8 () in + let contracts = Array.of_list contracts in + let* b = Incremental.begin_construction b in + let hundred = of_int 100 in + let ten = of_int 10 in + let twenty = of_int 20 in + let* b = n_transactions 10 b contracts.(0) contracts.(1) Tez.one in + let* b = n_transactions 30 b contracts.(1) contracts.(2) hundred in + let* b = n_transactions 30 b contracts.(1) contracts.(3) hundred in + let* b = n_transactions 30 b contracts.(4) contracts.(3) hundred in + let* b = n_transactions 20 b contracts.(0) contracts.(1) hundred in + let* b = n_transactions 10 b contracts.(1) contracts.(3) hundred in + let* b = n_transactions 10 b contracts.(1) contracts.(3) hundred in + let* b = n_transactions 20 ~fee:ten b contracts.(3) contracts.(4) ten in + let* b = n_transactions 10 ~fee:twenty b contracts.(4) contracts.(5) ten in + let* b = n_transactions 70 ~fee:twenty b contracts.(6) contracts.(0) twenty in + let* b = + n_transactions 550 ~fee:twenty b contracts.(6) contracts.(4) twenty + in + let* b = n_transactions 50 ~fee:ten b contracts.(7) contracts.(5) twenty in + let* b = n_transactions 30 ~fee:ten b contracts.(0) contracts.(7) hundred in + let* b = n_transactions 20 ~fee:ten b contracts.(1) contracts.(0) twenty in + let* (_ : Block.t) = Incremental.finalize_block b in + return_unit + +(** Build a chain that has 10 blocks. *) +let test_build_a_chain () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 ~consensus_threshold:0 () in + let ten = of_int 10 in + let* (_ : Block.t) = + List.fold_left_es + (fun b _ -> + let* b = Incremental.begin_construction b in + let* b, _ = + transfer_and_check_balances ~loc:__LOC__ b contract_1 contract_2 ten + in + Incremental.finalize_block b) + b + (1 -- 10) + in + return_unit + +(*********************************************************************) +(* Expected error test cases *) +(*********************************************************************) + +(** Transferring zero tez is forbidden in implicit contract. *) +let test_empty_implicit () = + let open Lwt_result_syntax in + let* b, dest = Context.init1 () in + let account = Account.new_account () in + let src = Contract.Implicit account.Account.pkh in + let* amount = two_over_n_of_balance (B b) dest 3L in + (* Transfer zero tez from an implicit contract. *) + let* op = Op.transaction (B b) src dest amount in + let* incr = Incremental.begin_construction b in + let*! res = Incremental.add_operation incr op in + Assert.proto_error ~loc:__LOC__ res (function + | Contract_storage.Empty_implicit_contract _ as err -> + Assert.test_error_encodings err ; + true + | _ -> false) + +(** Balance is too low to transfer. *) +let test_balance_too_low fee () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 ~consensus_threshold:0 () in + let* balance1 = Context.Contract.balance (B b) contract_1 in + let* balance2 = Context.Contract.balance (B b) contract_2 in + (* transfer the amount of tez that is bigger than the balance in the source contract *) + let* op = Op.transaction ~fee (B b) contract_1 contract_2 max_tez in + let expect_failure = function + | Environment.Ecoproto_error (Contract_storage.Balance_too_low _ as err) + :: _ -> + Assert.test_error_encodings err ; + return_unit + | t -> failwith "Unexpected error: %a" Error_monad.pp_print_trace t + in + let* i = Incremental.begin_construction b in + if fee > balance1 then + (* The fee is higher than the balance, so the operation validation + fails with the [Balance_too_low] error. *) + let* (_res : Incremental.t) = + Incremental.add_operation ~expect_failure i op + in + return_unit + else + (* The fee is smaller than or equal to the balance, so the + operation is successfully validated and its fees are + taken. However, since the amount to transfer exceeds the + balance, the application has no further effects and the + operation is marked with the [Balance_too_low] error. *) + let* i = + Incremental.add_operation ~expect_apply_failure:expect_failure i op + in + (* contract_1 loses the fees *) + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) contract_1 balance1 fee + in + (* contract_2 is not credited *) + Assert.balance_was_credited ~loc:__LOC__ (I i) contract_2 balance2 Tez.zero + +(** 1- Create a block, and three contracts; + 2- Add a transfer that at the end the balance of a contract is + zero into this block; + 3- Add another transfer that send tez from a zero balance contract; + 4- Catch the expected error: Balance_too_low. *) +let test_balance_too_low_two_transfers fee () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2, contract_3) = + Context.init3 ~consensus_threshold:0 () + in + let* i = Incremental.begin_construction b in + let* balance = Context.Contract.balance (I i) contract_1 in + let res = balance /! 3L in + let*? two_third_of_balance = res *? 2L in + let* i, _ = + transfer_and_check_balances + ~loc:__LOC__ + i + contract_1 + contract_2 + two_third_of_balance + in + let* b = Incremental.finalize_block i in + let* balance1 = Context.Contract.balance (B b) contract_1 in + let* balance3 = Context.Contract.balance (B b) contract_3 in + let* operation = + Op.transaction ~fee (B b) contract_1 contract_3 two_third_of_balance + in + let expect_apply_failure = function + | Environment.Ecoproto_error (Contract_storage.Balance_too_low _ as err) + :: _ -> + Assert.test_error_encodings err ; + return_unit + | t -> failwith "Unexpected error: %a" Error_monad.pp_print_trace t + in + let* i = Incremental.begin_construction b in + let* i = Incremental.add_operation ~expect_apply_failure i operation in + (* contract_1 loses the fees *) + let* () = + Assert.balance_was_debited ~loc:__LOC__ (I i) contract_1 balance1 fee + in + (* contract_3 is not credited *) + Assert.balance_was_credited ~loc:__LOC__ (I i) contract_3 balance3 Tez.zero + +(** The counter is already used for the previous operation. *) +let invalid_counter () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 ~consensus_threshold:0 () in + let* op1 = Op.transaction (B b) contract_1 contract_2 Tez.one in + let* op2 = Op.transaction (B b) contract_1 contract_2 Tez.one in + let* b = Block.bake ~operation:op1 b in + let* i = Incremental.begin_construction b in + let*! b = Incremental.add_operation i op2 in + Assert.proto_error ~loc:__LOC__ b (function + | Contract_storage.Counter_in_the_past _ as err -> + Assert.test_error_encodings err ; + true + | _ -> false) + +(** Same as before but through a different way to perform this + error. *) +let test_add_the_same_operation_twice () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 () in + let* i = Incremental.begin_construction b in + let* i, op_transfer = + transfer_and_check_balances ~loc:__LOC__ i contract_1 contract_2 ten_tez + in + let* b = Incremental.finalize_block i in + let* i = Incremental.begin_construction b in + let* (_ : packed_operation) = + Op.transaction (I i) contract_1 contract_2 ten_tez + in + let*! b = Incremental.add_operation i op_transfer in + Assert.proto_error ~loc:__LOC__ b (function + | Contract_storage.Counter_in_the_past _ as err -> + Assert.test_error_encodings err ; + true + | _ -> false) + +(** The counter is in the future *) +let invalid_counter_in_the_future () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 () in + let* b = Incremental.begin_construction b in + let* cpt = Context.Contract.counter (I b) contract_1 in + let counter = Manager_counter.Internal_for_tests.add cpt 10 in + let* op = Op.transaction (I b) contract_1 contract_2 Tez.one ~counter in + let*! b = Incremental.add_operation b op in + Assert.proto_error ~loc:__LOC__ b (function + | Contract_storage.Counter_in_the_future _ as err -> + Assert.test_error_encodings err ; + true + | _ -> false) + +(** Check ownership. *) +let test_ownership_sender () = + let open Lwt_result_syntax in + let* b, (contract_1, contract_2) = Context.init2 () in + let* b = Incremental.begin_construction b in + (* get the manager of the contract_1 as a sender *) + let* manager = Context.Contract.manager (I b) contract_1 in + let imcontract_1 = Alpha_context.Contract.Implicit manager.pkh in + let* b, _ = + transfer_and_check_balances ~loc:__LOC__ b imcontract_1 contract_2 Tez.one + in + let* (_ : Block.t) = Incremental.finalize_block b in + return_unit + +(*********************************************************************) +(* Random transfer *) + +(* Return a pair of minimum and maximum random number. *) +let random_range (min, max) = + let interv = max - min + 1 in + let init = + Random.self_init () ; + Random.int interv + min + in + init + +(* Return a random contract. *) +let random_contract contract_array = + let i = Random.int (Array.length contract_array) in + contract_array.(i) + +(** Transfer by randomly choose amount 10 contracts, and randomly + choose the amount in the source contract. *) +let test_random_transfer () = + let open Lwt_result_syntax in + let* b, contracts = Context.init_n 10 () in + let contracts = Array.of_list contracts in + let source = random_contract contracts in + let dest = random_contract contracts in + let source_pkh = Context.Contract.pkh source in + (* given that source may not have a sufficient balance for the transfer + to bake, + make sure it cannot be chosen as baker *) + let* amount = Context.Contract.balance (B b) source in + if source = dest then + let* _, _ = + transfer_to_itself_and_check_balances + ~loc:__LOC__ + ~policy:(Block.Excluding [source_pkh]) + b + source + amount + in + return_unit + else + let* i = + Incremental.begin_construction ~policy:(Block.Excluding [source_pkh]) b + in + let* _, _ = transfer_and_check_balances ~loc:__LOC__ i source dest amount in + return_unit + +(** Transfer random transactions. *) +let test_random_multi_transactions () = + let n = random_range (1, 100) in + multiple_transfer n (of_int 100) + +(*********************************************************************) + +let test_bad_entrypoint () = + let open Lwt_result_syntax in + let* b, _c = Context.init1 () in + let* v = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt v in + let storage = "Unit" in + let parameter = "Unit" in + let entrypoint = Entrypoint.of_string_strict_exn "bad entrypoint" in + (* bad entrypoint *) + let*! result = + Contract_helpers.run_script + ctxt + "{parameter unit; storage unit; code { CAR; NIL operation; PAIR }}" + ~entrypoint + ~storage + ~parameter + () + in + match result with + | Ok _ -> Alcotest.fail "expected error" + | Error lst + when List.mem + ~equal:( = ) + (Environment.Ecoproto_error + (Script_tc_errors.No_such_entrypoint entrypoint)) + lst -> + return_unit + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace errs + +let test_bad_parameter () = + let open Lwt_result_syntax in + let* b, _c = Context.init1 () in + let* v = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt v in + let storage = "Unit" in + let parameter = "1" in + (* bad parameter *) + let*! result = + Contract_helpers.run_script + ctxt + "{parameter unit; storage unit; code { CAR; NIL operation; PAIR }}" + ~storage + ~parameter + () + in + match result with + | Ok _ -> Alcotest.fail "expected error" + | Error lst + when List.mem + ~equal:( = ) + (Environment.Ecoproto_error + (Script_interpreter.Bad_contract_parameter + (Contract.Originated Contract_helpers.default_self))) + lst -> + return_unit + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace errs + +let transfer_to_itself_with_no_such_entrypoint () = + let open Lwt_result_syntax in + let entrypoint = Entrypoint.of_string_strict_exn "bad entrypoint" in + let* b, addr = Context.init1 () in + let* i = Incremental.begin_construction b in + let* transaction = Op.transaction (B b) addr addr Tez.one ~entrypoint in + let expect_apply_failure = function + | Environment.Ecoproto_error (Script_tc_errors.No_such_entrypoint _ as e) + :: _ -> + Assert.test_error_encodings e ; + return_unit + | _ -> failwith "no such entrypoint should fail" + in + let* (_res : Incremental.t) = + Incremental.add_operation ~expect_apply_failure i transaction + in + return_unit + +(** Originates a contract with a [script] and an initial [credit] and + [storage]. *) +let contract_originate ~baker ~block ~script ~credit ~storage ~source = + let open Lwt_result_syntax in + let code = Expr.from_string script in + let script = + Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} + in + let* op, dst = + Op.contract_origination_hash (B block) source ~fee:Tez.zero ~script ~credit + in + let+ state = + Block.bake ~policy:Block.(By_account baker) ~operations:[op] block + in + (state, dst) + +(** Runs a transaction from a [source] to a [destination]. *) +let transfer ?force_reveal ?parameters ~baker ~block ~source ~destination amount + = + let open Lwt_result_syntax in + let* operation = + Op.transaction + ?force_reveal + ?parameters + ~fee:Tez.zero + (B block) + source + destination + amount + in + Block.bake ~policy:Block.(By_account baker) ~operations:[operation] block + +(** The script of a contract that transfers its balance to the caller, and + stores the parameter of the call. *) +let script = + {| { parameter string ; + storage string ; + code { + CAR ; + SOURCE ; + CONTRACT unit ; + ASSERT_SOME ; + BALANCE ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } +} |} + +(** The tested scenarios are the following : + + - originate a contract with the above [script] and no initial balance, + call it from an account short of sufficient funds to cover storage fees, + and check that this indeed fails. + + - originate a contract with the above [script] and sufficient balance to + cover storage fees of a subsequent call, call the originated contract from + an account short of sufficient funds to cover storage fees, as expected, + this succeeds since the caller receives the originated contract's initial + balance. *) +let test_storage_fees_and_internal_operation () = + let open Lwt_result_syntax in + let* initial_block, contract = Context.init1 ~consensus_threshold:0 () in + let null_string = Expr.from_string "\"\"" in + let caller = Account.new_account () in + (* Initialize a caller account. *) + let* initial_block = + transfer + ~block:initial_block + ~baker:(Context.Contract.pkh contract) + ~source:contract + ~destination:(Contract.Implicit caller.pkh) + Tez.one_mutez + in + (* [originate_and_call] first, originates a contract with an empty string as + initial storage, and an initial credit of [initial_amount]. And then, calls + the originated contract from [caller] with a parameter that allocates + additional storage. *) + let originate_and_call ~initial_block ~initial_amount = + let* block, contract_hash = + contract_originate + ~block:initial_block + ~baker:(Context.Contract.pkh contract) + ~script + ~source:contract + ~credit:initial_amount + ~storage:null_string + in + let random_string = Expr.from_string "\"Abracadabra\"" in + transfer + ~force_reveal:true + ~parameters:(Alpha_context.Script.lazy_expr random_string) + ~block + ~baker:(Context.Contract.pkh contract) + ~source:(Contract.Implicit caller.pkh) + ~destination:(Contract.Originated contract_hash) + Tez.zero + in + (* Ensure failure when the initial balance of the originated contract is not + sufficient to pay storage fees. *) + let*! res = originate_and_call ~initial_block ~initial_amount:Tez.one_mutez in + let* () = + Assert.proto_error_with_info ~loc:__LOC__ res "Cannot pay storage fee" + in + (* Ensure success when the initial balance of the originated contract is + sufficient to pay storage fees. *) + let+ (_ : Block.t) = + originate_and_call ~initial_block ~initial_amount:Tez.one_cent + in + () + +let tests = + [ + (* single transfer *) + Tztest.tztest "single transfer" `Quick test_block_with_a_single_transfer; + Tztest.tztest + "single transfer with fee" + `Quick + test_block_with_a_single_transfer_with_fee; + (* transfer zero tez *) + Tztest.tztest "single transfer zero tez" `Quick test_transfer_zero_tez; + Tztest.tztest + "transfer zero tez from implicit contract" + `Quick + test_transfer_zero_implicit; + Tztest.tztest + "transfer zero tez to an implicit contract with balance of src as fee" + `Quick + test_transfer_zero_implicit_with_bal_src_as_fee; + (* transfer to originated contract *) + Tztest.tztest + "transfer to originated contract paying transaction fee" + `Quick + test_transfer_to_originate_with_fee; + Tztest.tztest + "transfer zero tez to an originated contract with balance of src as fee" + `Quick + test_transfer_zero_to_originated_with_bal_src_as_fee; + (* transfer by the balance of contract *) + Tztest.tztest + "transfer the amount from source contract balance" + `Quick + test_transfer_amount_of_contract_balance; + (* transfer to itself *) + Tztest.tztest "transfers to itself" `Quick test_transfers_to_self; + (* missing operation *) + Tztest.tztest "missing transaction" `Quick test_missing_transaction; + (* transfer from/to implicit/originated contracts*) + Tztest.tztest + "transfer from an implicit to implicit contract" + `Quick + test_transfer_from_implicit_to_implicit_contract; + Tztest.tztest + "transfer from an implicit to an originated contract" + `Quick + test_transfer_from_implicit_to_originated_contract; + (* Slow tests *) + Tztest.tztest + "block with multiple transfers" + `Slow + test_block_with_multiple_transfers; + (* TODO increase the number of transaction times *) + Tztest.tztest + "block with multiple transfer paying fee" + `Slow + test_block_with_multiple_transfers_pay_fee; + Tztest.tztest + "block with multiple transfer without paying fee" + `Slow + test_block_with_multiple_transfers_with_without_fee; + (* build the chain *) + Tztest.tztest "build a chain" `Quick test_build_a_chain; + (* Erroneous *) + Tztest.tztest "empty implicit" `Quick test_empty_implicit; + Tztest.tztest + "balance too low - transfer zero" + `Quick + (test_balance_too_low Tez.zero); + Tztest.tztest "balance too low" `Quick (test_balance_too_low Tez.one); + Tztest.tztest + "balance too low (max fee)" + `Quick + (test_balance_too_low max_tez); + Tztest.tztest + "balance too low with two transfers - transfer zero" + `Quick + (test_balance_too_low_two_transfers Tez.zero); + Tztest.tztest + "balance too low with two transfers" + `Quick + (test_balance_too_low_two_transfers Tez.one); + Tztest.tztest + "transfer one tez to an implicit contract with balance of src as fee" + `Quick + test_transfer_one_to_implicit_with_bal_src_as_fee; + Tztest.tztest "invalid_counter" `Quick invalid_counter; + Tztest.tztest + "add the same operation twice" + `Quick + test_add_the_same_operation_twice; + Tztest.tztest + "invalid_counter_in_the_future" + `Quick + invalid_counter_in_the_future; + Tztest.tztest "ownership sender" `Quick test_ownership_sender; + (* Random tests *) + Tztest.tztest "random transfer" `Quick test_random_transfer; + Tztest.tztest "random multi transfer" `Quick test_random_multi_transactions; + Tztest.tztest "bad entrypoint" `Quick test_bad_entrypoint; + Tztest.tztest "bad parameter" `Quick test_bad_parameter; + Tztest.tztest + "no such entrypoint" + `Quick + transfer_to_itself_with_no_such_entrypoint; + Tztest.tztest + "storage fees after contract call and allocation" + `Quick + test_storage_fees_and_internal_operation; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("transfer", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer_ticket.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer_ticket.ml new file mode 100644 index 000000000000..234d40a59660 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_transfer_ticket.ml @@ -0,0 +1,346 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Transfer_ticket logic + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_transfer_ticket.ml + Subject: Test ticket transfers +*) + +open Protocol +open Alpha_context +open Tezos_micheline + +(* In this test, a ticketer contract mints and transfers a ticket to an implicit account, + who further transfers it to another implicit account. + The ticket balance is inspected for correctness. +*) +let test_mint_deposit_withdraw_implicit_transfer () = + let open Lwt_result_wrap_syntax in + let* block, (account, another_account) = + Context.init2 ~consensus_threshold:0 () + in + let baker = Context.Contract.pkh account in + let* ticketer, _, block = + Contract_helpers.originate_contract_from_string + ~script: + {| + parameter (pair nat nat address) ; + storage unit ; + code { CAR ; + UNPAIR 3 ; + DIG 2 ; + CONTRACT (ticket nat) ; + ASSERT_SOME ; + # contract : nat %ct : nat %qty + PUSH mutez 0 ; + # tez : contract : nat %ct : nat %qty + DIG 3 ; + # nat %qty : tez : contract : nat %ct + DIG 3 ; + # nat %ct : nat %qty : tez : contract + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + UNIT ; + SWAP ; + PAIR } + |} + ~storage:"Unit" + ~source_contract:account + ~baker + block + in + let contents = 42 in + let* block = + let* operation = + Op.transaction + (B block) + ~entrypoint:Entrypoint.default + ~parameters: + (Expr_common.( + pair_n [int (Z.of_int contents); int (Z.of_int 1); address account]) + |> Micheline.strip_locations |> Script.lazy_expr) + ~fee:Tez.one + account + ticketer + (Tez.of_mutez_exn 0L) + in + Block.bake ~operation block + in + let ty = Expr.from_string "nat" in + let* block = + let* operation = + Op.transfer_ticket + (B block) + ~entrypoint:Entrypoint.default + ~source:account + ~ty:(Script.lazy_expr ty) + ~contents: + (Script.lazy_expr @@ Expr.from_string @@ string_of_int contents) + ~amount: + (WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_zint @@ Z.of_int 1) + ~destination:another_account + ~ticketer + in + Block.bake ~operation block + in + let make_ex_token ctxt ~ticketer ~ty ~content = + let*?@ Script_ir_translator.Ex_comparable_ty cty, ctxt = + Script_ir_translator.parse_comparable_ty ctxt @@ Micheline.root ty + in + let*@ contents, ctxt = + Script_ir_translator.parse_comparable_data ctxt cty + @@ Micheline.root content + in + return + (Ticket_token.Ex_token {contents_type = cty; ticketer; contents}, ctxt) + in + let* ctxt = + let+ result = Incremental.begin_construction block in + Incremental.alpha_ctxt result + in + let* token, ctxt = + make_ex_token + ctxt + ~ticketer + ~ty + ~content:(Expr.from_string @@ string_of_int contents) + in + let*@ key, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:(Contract another_account) token + in + let*@ amount, _ = Ticket_balance.get_balance ctxt key in + match amount with + | Some amount -> Assert.equal_int ~loc:__LOC__ (Z.to_int amount) 1 + | _ -> return_unit + +(* In this test, a ticketer contract is called to mint and send a ticket + to an implicit account and a contract. Both destinations are given + in a `contract (ticket nat)` value. + Transfer should be possible since the target contract has the right + parameter type under the given entrypoint. +*) +let test_contract_as_ticket_transfer_destination () = + let open Lwt_result_wrap_syntax in + let* block, (account, another_account) = + Context.init2 ~consensus_threshold:0 () + in + let baker = Context.Contract.pkh account in + let* ticketer, _, block = + Contract_helpers.originate_contract_from_string + ~script: + {| + parameter (pair (contract (ticket nat)) nat nat) ; + storage unit ; + code { CAR ; + UNPAIR 3 ; + # contract (ticket nat) : nat %ct : nat %qty + PUSH mutez 0 ; + # tez : contract (ticket nat) : nat %ct : nat %qty + DIG 3 ; + # nat %qty : tez : contract (ticket nat) : nat %ct + DIG 3 ; + # nat %ct : nat %qty : tez : contract (ticket nat) + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + UNIT ; + SWAP ; + PAIR } + |} + ~storage:"Unit" + ~source_contract:account + ~baker + block + in + let* bag, _, block = + Contract_helpers.originate_contract_from_string + ~script: + {| + parameter (or (ticket %save nat) (address %send)); + storage (list (ticket nat)); + code { UNPAIR ; + IF_LEFT + { CONS ; NIL operation ; PAIR } + { SWAP ; + IF_CONS + { DIG 2 ; + CONTRACT %ticket (ticket nat) ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } + { PUSH string "no ticket to send" ; FAILWITH }}} + |} + ~storage:"{}" + ~source_contract:account + ~baker + block + in + let contents = 42 in + let* block = + let* operation = + Op.transaction + (B block) + ~entrypoint:Entrypoint.default + ~parameters: + (Expr_common.( + pair_n + [ + string + (Destination.(to_b58check (Contract account)) + ^ Entrypoint.(to_address_suffix default)); + int (Z.of_int contents); + int (Z.of_int 1); + ]) + |> Micheline.strip_locations |> Script.lazy_expr) + ~fee:Tez.one + account + ticketer + (Tez.of_mutez_exn 0L) + in + Block.bake ~operation block + in + let ty = Expr.from_string "nat" in + let* block = + let* operation = + Op.transfer_ticket + (B block) + ~entrypoint:Entrypoint.default + ~source:account + ~ty:(Script.lazy_expr ty) + ~contents: + (Script.lazy_expr @@ Expr.from_string @@ string_of_int contents) + ~amount: + (WithExceptions.Option.get ~loc:__LOC__ + @@ Ticket_amount.of_zint @@ Z.of_int 1) + ~destination:another_account + ~ticketer + in + Block.bake ~operation block + in + let make_ex_token ctxt ~ticketer ~ty ~content = + let*?@ Script_ir_translator.Ex_comparable_ty cty, ctxt = + Script_ir_translator.parse_comparable_ty ctxt @@ Micheline.root ty + in + let*@ contents, ctxt = + Script_ir_translator.parse_comparable_data ctxt cty + @@ Micheline.root content + in + return + (Ticket_token.Ex_token {contents_type = cty; ticketer; contents}, ctxt) + in + let* ctxt = + let+ result = Incremental.begin_construction block in + Incremental.alpha_ctxt result + in + let* token, ctxt = + make_ex_token + ctxt + ~ticketer + ~ty + ~content:(Expr.from_string @@ string_of_int contents) + in + let*@ key, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:(Contract another_account) token + in + let*@ amount, _ = Ticket_balance.get_balance ctxt key in + let* () = + match amount with + | Some amount -> Assert.equal_int ~loc:__LOC__ (Z.to_int amount) 1 + | _ -> return_unit + in + let* block = + let* operation = + Op.transaction + (B block) + ~entrypoint:Entrypoint.default + ~parameters: + (Expr_common.( + pair_n + [ + string + (Destination.(to_b58check (Contract bag)) + ^ Entrypoint.( + to_address_suffix @@ of_string_strict_exn "save")); + int (Z.of_int contents); + int (Z.of_int 1); + ]) + |> Micheline.strip_locations |> Script.lazy_expr) + ~fee:Tez.one + account + ticketer + (Tez.of_mutez_exn 0L) + in + Block.bake ~operation block + in + let* ctxt = + let+ result = Incremental.begin_construction block in + Incremental.alpha_ctxt result + in + let* token, ctxt = + make_ex_token + ctxt + ~ticketer + ~ty + ~content:(Expr.from_string @@ string_of_int contents) + in + let*@ key, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:(Contract bag) token + in + let*@ amount, _ = Ticket_balance.get_balance ctxt key in + match amount with + | Some amount -> Assert.equal_int ~loc:__LOC__ (Z.to_int amount) 1 + | _ -> return_unit + +let tests = + [ + Tztest.tztest + "ticket transfer operations" + `Quick + test_mint_deposit_withdraw_implicit_transfer; + Tztest.tztest + "'contract (ticket cty)' as transfer destination" + `Quick + test_contract_as_ticket_transfer_destination; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("transfer ticket", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_voting.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_voting.ml new file mode 100644 index 000000000000..32f2fd0b7048 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_voting.ml @@ -0,0 +1,2275 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (voting) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_voting.ml + Subject: On the voting process. + +*) + +open Protocol +open Alpha_context + +(** {2 Constants and ratios used in voting} + + percent_mul denotes the percent multiplier + initial_participation is 7000 that is, 7/10 * percent_mul + the participation EMA ratio pr_ema_weight / den = 7 / 10 + the participation ratio pr_num / den = 2 / 10 + note: we use the same denominator for both participation EMA and participation rate. + supermajority rate is s_num / s_den = 8 / 10 *) +let percent_mul = 100_00 + +let den = 10 + +let initial_participation_num = 7 + +let initial_participation = initial_participation_num * percent_mul / den + +let pr_ema_weight = 8 + +let pr_num = den - pr_ema_weight + +let s_num = 8 + +let s_den = 10 + +let qr_min_num = 2 + +let qr_max_num = 7 + +let expected_qr_num participation_ema = + let participation_ema = Int32.to_int participation_ema in + let participation_ema = participation_ema * den / percent_mul in + Float.( + of_int qr_min_num + +. of_int participation_ema + *. (of_int qr_max_num -. of_int qr_min_num) + /. of_int den) + +(* Protocol_hash.zero is "PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i" *) +let protos = + Array.map + (fun s -> Protocol_hash.of_b58check_exn s) + [| + "ProtoALphaALphaALphaALphaALphaALphaALpha61322gcLUGH"; + "ProtoALphaALphaALphaALphaALphaALphaALphabc2a7ebx6WB"; + "ProtoALphaALphaALphaALphaALphaALphaALpha84efbeiF6cm"; + "ProtoALphaALphaALphaALphaALphaALphaALpha91249Z65tWS"; + "ProtoALphaALphaALphaALphaALphaALphaALpha537f5h25LnN"; + "ProtoALphaALphaALphaALphaALphaALphaALpha5c8fefgDYkr"; + "ProtoALphaALphaALphaALphaALphaALphaALpha3f31feSSarC"; + "ProtoALphaALphaALphaALphaALphaALphaALphabe31ahnkxSC"; + "ProtoALphaALphaALphaALphaALphaALphaALphabab3bgRb7zQ"; + "ProtoALphaALphaALphaALphaALphaALphaALphaf8d39cctbpk"; + "ProtoALphaALphaALphaALphaALphaALphaALpha3b981byuYxD"; + "ProtoALphaALphaALphaALphaALphaALphaALphaa116bccYowi"; + "ProtoALphaALphaALphaALphaALphaALphaALphacce68eHqboj"; + "ProtoALphaALphaALphaALphaALphaALphaALpha225c7YrWwR7"; + "ProtoALphaALphaALphaALphaALphaALphaALpha58743cJL6FG"; + "ProtoALphaALphaALphaALphaALphaALphaALphac91bcdvmJFR"; + "ProtoALphaALphaALphaALphaALphaALphaALpha1faaadhV7oW"; + "ProtoALphaALphaALphaALphaALphaALphaALpha98232gD94QJ"; + "ProtoALphaALphaALphaALphaALphaALphaALpha9d1d8cijvAh"; + "ProtoALphaALphaALphaALphaALphaALphaALphaeec52dKF6Gx"; + "ProtoALphaALphaALphaALphaALphaALphaALpha841f2cQqajX"; + |] + +(** {2 Helper functions} *) + +let assert_period_kinds expected_kinds kind loc = + let open Lwt_result_syntax in + if + List.exists + (fun expected_kind -> Stdlib.(expected_kind = kind)) + expected_kinds + then return_unit + else + Alcotest.failf + "%s - Unexpected voting period kind - expected %a, got %a" + loc + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " or ") + Voting_period.pp_kind) + expected_kinds + Voting_period.pp_kind + kind + +let assert_period_kind expected_kind = assert_period_kinds [expected_kind] + +let assert_period_index expected_index index loc = + let open Lwt_result_syntax in + if expected_index = index then return_unit + else + Alcotest.failf + "%s - Unexpected voting period index - expected %ld, got %ld" + loc + expected_index + index + +let assert_period_position expected_position position loc = + let open Lwt_result_syntax in + if position = expected_position then return_unit + else + Alcotest.failf + "%s - Unexpected voting period position blocks - expected %ld, got %ld" + loc + expected_position + position + +let assert_period_remaining expected_remaining remaining loc = + let open Lwt_result_syntax in + if remaining = expected_remaining then return_unit + else + Alcotest.failf + "%s - Unexpected voting period remaining blocks - expected %ld, got %ld" + loc + expected_remaining + remaining + +let assert_period ?expected_kind ?expected_kinds ?expected_index + ?expected_position ?expected_remaining b loc = + let open Lwt_result_syntax in + let* {voting_period; position; remaining} = + Context.Vote.get_current_period (B b) + in + let* () = + match (expected_kind, expected_kinds) with + | None, None -> return_unit + | Some expected_kind, None -> + assert_period_kind expected_kind voting_period.kind loc + | None, Some expected_kinds -> + assert_period_kinds expected_kinds voting_period.kind loc + | Some _, Some _ -> + invalid_arg + "assert_period: arguments expected_kind and expected_kinds should \ + not both be provided." + in + let* () = + match expected_index with + | Some expected_index -> + assert_period_index expected_index voting_period.index loc + | None -> return_unit + in + let* () = + match expected_position with + | Some expected_position -> + assert_period_position expected_position position loc + | None -> return_unit + in + match expected_remaining with + | Some expected_remaining -> + assert_period_remaining expected_remaining remaining loc + | None -> return_unit + +let assert_ballots expected_ballots b loc = + let open Lwt_result_syntax in + let* ballots = Context.Vote.get_ballots (B b) in + Assert.equal + ~loc + Vote.equal_ballots + "Unexpected ballots" + Vote.pp_ballots + ballots + expected_ballots + +let assert_empty_ballots b loc = + let open Lwt_result_syntax in + let* () = assert_ballots Vote.ballots_zero b loc in + let* l = Context.Vote.get_ballot_list (B b) in + match l with + | [] -> return_unit + | _ -> failwith "%s - Unexpected ballot list" loc + +let mk_contracts_from_pkh pkh_list = + List.map (fun c -> Contract.Implicit c) pkh_list + +(* get the list of delegates and the list of their voting power from listings *) +let get_delegates_and_power_from_listings b = + let open Lwt_result_syntax in + let+ l = Context.Vote.get_listings (B b) in + (mk_contracts_from_pkh (List.map fst l), List.map snd l) + +(* compute the voting power of each delegate *) +let get_power b delegates loc = + let open Lwt_result_syntax in + List.map_es + (fun delegate -> + let pkh = Context.Contract.pkh delegate in + let* info = Context.Delegate.voting_info (B b) pkh in + match info.voting_power with + | None -> failwith "%s - Missing delegate" loc + | Some power -> return power) + delegates + +(* Checks that the listings are populated *) +let assert_listings_not_empty b ~loc = + let open Lwt_result_syntax in + let* l = Context.Vote.get_listings (B b) in + match l with + | [] -> failwith "Unexpected empty listings (%s)" loc + | _ -> return_unit + +let equal_delegate_info a b = + Option.equal Int64.equal a.Vote.voting_power b.Vote.voting_power + && Option.equal Vote.equal_ballot a.current_ballot b.current_ballot + && List.equal + Protocol_hash.equal + (List.sort Protocol_hash.compare a.current_proposals) + (List.sort Protocol_hash.compare b.current_proposals) + && Int.equal a.remaining_proposals b.remaining_proposals + +let assert_equal_info ~loc a b = + Assert.equal + ~loc + equal_delegate_info + "delegate_info" + Vote.pp_delegate_info + a + b + +let bake_until_first_block_of_next_period ?policy b = + let open Lwt_result_syntax in + let* {remaining; _} = Context.Vote.get_current_period (B b) in + Block.bake_n ?policy Int32.(add remaining one |> to_int) b + +let context_init_tup tup ?(blocks_per_cycle = 4l) = + (* Note that some of these tests assume (more or less) that the + accounts remain active during a voting period, which roughly + translates to the following condition being assumed to hold: + `blocks_per_voting_period <= consensus_rights_delay * blocks_per_cycle.` + We also set baking and attesting rewards to zero in order to + ease accounting of exact baker stake. *) + Context.init_gen + tup + ~blocks_per_cycle + ~cycles_per_voting_period:1l + ~consensus_threshold:0 + ~issuance_weights: + { + base_total_issued_per_minute = Tez.zero; + attesting_reward_weight = 1; + baking_reward_bonus_weight = 1; + baking_reward_fixed_portion_weight = 1; + seed_nonce_revelation_tip_weight = 1; + vdf_revelation_tip_weight = 1; + } + ~nonce_revelation_threshold:2l + +(** [context_init n ()] returns [(block, contracts)] where [block] is + an initial block with [n] bootstrap accounts, and [contracts] is + the list of associated implicit contracts. + + See {!context_init_tup} and {!Context.init_gen} for optional + arguments. *) +let context_init n = context_init_tup (Context.TList n) + +(** [context_init1 ()] returns [(block, contract)] where [block] is an + initial block with one bootstrap account, and [contract] is the + associated implicit contract. *) +let context_init1 = context_init_tup Context.T1 + +(** [context_init2 ()] returns [(block, contracts)] where [block] is + an initial block with two bootstrap accounts, and [contracts] is + the pair of associated implicit contracts. *) +let context_init2 = context_init_tup Context.T2 + +(** Call {!context_init2}, then inject a Proposals operation and bake + blocks in order to move on to an Exploration period. Return a + block, a delegate (distinct from the one who submitted the + Proposals), and the current proposal. *) +let context_init_exploration ?(proposal = protos.(0)) ?blocks_per_cycle () = + let open Lwt_result_syntax in + let* block, (proposer, other_delegate) = context_init2 ?blocks_per_cycle () in + let* operation = Op.proposals (B block) proposer [proposal] in + let* block = Block.bake block ~operation in + let* block = bake_until_first_block_of_next_period block in + let* () = assert_period ~expected_kind:Exploration block __LOC__ in + return (block, other_delegate, proposal) + +let append_loc ~caller_loc loc = + Format.sprintf "%s@.Called from %s" loc caller_loc + +(** {3 Expected protocol errors} *) + +let wrong_error expected_error_name actual_error_trace loc = + failwith + "%s:@,Expected error trace [%s], but got:@,%a" + loc + expected_error_name + Error_monad.pp_print_trace + actual_error_trace + +let missing_signature loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error Operation.Missing_signature] -> return_unit + | err -> wrong_error "Missing_signature" err loc + +let invalid_signature loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error Operation.Invalid_signature] -> return_unit + | err -> wrong_error "Invalid_signature" err loc + +open Validate_errors.Voting + +let wrong_voting_period_index ~current_index ~op_index loc = function + | [ + Environment.Ecoproto_error (Wrong_voting_period_index {expected; provided}); + ] -> + let open Lwt_result_syntax in + let make_loc = append_loc ~caller_loc:loc in + let* () = + Assert.equal_int32 ~loc:(make_loc __LOC__) expected current_index + in + Assert.equal_int32 ~loc:(make_loc __LOC__) provided op_index + | err -> wrong_error "Wrong_voting_period_index" err loc + +let wrong_voting_period_kind loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error (Wrong_voting_period_kind _)] -> return_unit + | err -> wrong_error "Wrong_voting_period_kind" err loc + +let proposals_from_unregistered_delegate loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error (Proposals_from_unregistered_delegate _)] -> + return_unit + | err -> wrong_error "Proposals_from_unregistered_delegate" err loc + +let ballot_from_unregistered_delegate loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error (Ballot_from_unregistered_delegate _)] -> + return_unit + | err -> wrong_error "Ballot_from_unregistered_delegate" err loc + +let source_not_in_vote_listings loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error Source_not_in_vote_listings] -> return_unit + | err -> wrong_error "Source_not_in_vote_listings" err loc + +let empty_proposals loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error Empty_proposals] -> return_unit + | err -> wrong_error "Empty_proposals" err loc + +let proposals_contain_duplicate duplicate_proposal loc = function + | [Environment.Ecoproto_error (Proposals_contain_duplicate {proposal})] -> + Assert.equal_protocol_hash + ~loc:(append_loc ~caller_loc:loc __LOC__) + proposal + duplicate_proposal + | err -> wrong_error "Proposals_contain_duplicate" err loc + +let too_many_proposals loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error (Too_many_proposals _)] -> return_unit + | err -> wrong_error "Too_many_proposals" err loc + +let already_proposed already_proposed_proposal loc = function + | [Environment.Ecoproto_error (Already_proposed {proposal; _})] -> + Assert.equal_protocol_hash + ~loc:(append_loc ~caller_loc:loc __LOC__) + proposal + already_proposed_proposal + | err -> wrong_error "Already_proposed" err loc + +let conflicting_proposals loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error (Conflicting_proposals _)] -> return_unit + | err -> wrong_error "Conflicting_proposals" err loc + +let ballot_for_wrong_proposal ~current_proposal ~op_proposal loc = function + | [ + Environment.Ecoproto_error (Ballot_for_wrong_proposal {current; submitted}); + ] -> + let open Lwt_result_syntax in + let* () = + Assert.equal_protocol_hash + ~loc:(append_loc ~caller_loc:loc __LOC__) + current_proposal + current + in + Assert.equal_protocol_hash + ~loc:(append_loc ~caller_loc:loc __LOC__) + op_proposal + submitted + | err -> wrong_error "Ballot_for_wrong_proposal" err loc + +let already_submitted_a_ballot loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error Already_submitted_a_ballot] -> return_unit + | err -> wrong_error "Already_submitted_a_ballot" err loc + +let conflicting_ballot loc = + let open Lwt_result_syntax in + function + | [Environment.Ecoproto_error (Conflicting_ballot _)] -> return_unit + | err -> wrong_error "Conflicting_ballot" err loc + +let assert_validate_proposals_fails ~expected_error ~proposer ~proposals ?period + block loc = + let open Lwt_result_syntax in + let* operation = Op.proposals (B block) proposer ?period proposals in + Incremental.assert_validate_operation_fails + (expected_error loc) + operation + block + +let assert_validate_ballot_fails ~expected_error ~voter ~proposal ~ballot + ?period block loc = + let open Lwt_result_syntax in + let* operation = Op.ballot (B block) voter ?period proposal ballot in + Incremental.assert_validate_operation_fails + (expected_error loc) + operation + block + +(** {2 Scenarized tests} *) + +(** A normal and successful vote sequence. *) +let test_successful_vote num_delegates () = + let open Lwt_result_syntax in + let open Alpha_context in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + let* b, (_ : Contract.t list) = + context_init ~min_proposal_quorum num_delegates () + in + (* no ballots in proposal period *) + let* () = assert_empty_ballots b __LOC__ in + (* Last baked block is first block of period Proposal *) + let* () = + assert_period + ~expected_kind:Proposal + ~expected_index:0l + ~expected_position:0l + b + __LOC__ + in + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* participation EMA starts at initial_participation *) + let* v = Context.Vote.get_participation_ema b in + let* () = + Assert.equal_int ~loc:__LOC__ initial_participation (Int32.to_int v) + in + (* listings must be populated in proposal period *) + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* beginning of proposal, denoted by _p1; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p1, power_p1 = get_delegates_and_power_from_listings b in + (* no proposals at the beginning of proposal period *) + let* ps = Context.Vote.get_proposals (B b) in + let* () = + if Environment.Protocol_hash.Map.is_empty ps then return_unit + else failwith "%s - Unexpected proposals" __LOC__ + in + (* no current proposal during proposal period *) + let* () = + let* proposal = Context.Vote.get_current_proposal (B b) in + match proposal with + | None -> return_unit + | Some _ -> failwith "%s - Unexpected proposal" __LOC__ + in + let del1 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates_p1 0 + in + let del2 = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates_p1 1 + in + let pkh1 = Context.Contract.pkh del1 in + let pkh2 = Context.Contract.pkh del2 in + let pow1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth power_p1 0 in + let pow2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth power_p1 1 in + let props = + List.map (fun i -> protos.(i)) (2 -- Constants.max_proposals_per_delegate) + in + let* ops1 = Op.proposals (B b) del1 (Protocol_hash.zero :: props) in + let* ops2 = Op.proposals (B b) del2 [Protocol_hash.zero] in + let* b = Block.bake ~operations:[ops1; ops2] b in + let* info1 = Context.Delegate.voting_info (B b) pkh1 in + let* info2 = Context.Delegate.voting_info (B b) pkh2 in + let* () = + assert_equal_info + ~loc:__LOC__ + info1 + { + voting_power = Some pow1; + current_ballot = None; + current_proposals = Protocol_hash.zero :: props; + remaining_proposals = 0; + } + in + let* () = + assert_equal_info + ~loc:__LOC__ + info2 + { + voting_power = Some pow2; + current_ballot = None; + current_proposals = [Protocol_hash.zero]; + remaining_proposals = Constants.max_proposals_per_delegate - 1; + } + in + (* proposals are now populated *) + let* ps = Context.Vote.get_proposals (B b) in + (* correctly count the double proposal for zero *) + let* () = + let weight = + Int64.add + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth power_p1 0) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth power_p1 1) + in + match Environment.Protocol_hash.(Map.find zero ps) with + | Some v -> + if v = weight then return_unit + else failwith "%s - Wrong count %Ld is not %Ld" __LOC__ v weight + | None -> failwith "%s - Missing proposal" __LOC__ + in + (* proposing more than maximum_proposals fails *) + let* () = + assert_validate_proposals_fails + ~expected_error:too_many_proposals + ~proposer:del1 + ~proposals:(Protocol_hash.zero :: props) + b + __LOC__ + in + (* proposing less than one proposal fails *) + let* () = + assert_validate_proposals_fails + ~expected_error:empty_proposals + ~proposer:del1 + ~proposals:[] + b + __LOC__ + in + (* first block of exploration period *) + let* b = bake_until_first_block_of_next_period b in + (* next block is first block of exploration *) + let* () = + assert_period ~expected_kind:Exploration ~expected_index:1l b __LOC__ + in + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* listings must be populated in proposal period before moving to exploration period *) + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p2, power_p2 = get_delegates_and_power_from_listings b in + (* no proposals during exploration period *) + let* ps = Context.Vote.get_proposals (B b) in + let* () = + if Environment.Protocol_hash.Map.is_empty ps then return_unit + else failwith "%s - Unexpected proposals" __LOC__ + in + (* current proposal must be set during exploration period *) + let* () = + let* v_opt = Context.Vote.get_current_proposal (B b) in + match v_opt with + | Some v -> + if Protocol_hash.(equal zero v) then return_unit + else failwith "%s - Wrong proposal" __LOC__ + | None -> failwith "%s - Missing proposal" __LOC__ + in + (* unanimous vote: all delegates --active when p2 started-- vote *) + let* operations = + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + delegates_p2 + in + let* b = Block.bake ~operations b in + let* info1 = Context.Delegate.voting_info (B b) pkh1 in + let* () = + assert_equal_info + ~loc:__LOC__ + info1 + { + voting_power = Some pow1; + current_ballot = Some Yay; + current_proposals = []; + remaining_proposals = 0; + } + in + (* Submitting a second ballot for [del1] fails (indeed, [del1] + belongs to [delegates_p2], so they have already sent a ballot + during the unanimous vote right above). *) + let* () = + assert_validate_ballot_fails + ~expected_error:already_submitted_a_ballot + ~voter:del1 + ~proposal:Protocol_hash.zero + ~ballot:Vote.Nay + b + __LOC__ + in + (* Allocate votes from weight of active delegates *) + List.fold_left (fun acc v -> Int64.(add v acc)) 0L power_p2 + |> fun power_sum -> + (* # of Yay in ballots matches votes of the delegates *) + let* () = + assert_ballots Vote.{yay = power_sum; nay = 0L; pass = 0L} b __LOC__ + in + (* One Yay ballot per delegate *) + let* () = + let* l_opt = Context.Vote.get_ballot_list (B b) in + match l_opt with + | [] -> failwith "%s - Unexpected empty ballot list" __LOC__ + | l -> + List.iter_es + (fun delegate -> + let pkh = Context.Contract.pkh delegate in + match List.find_opt (fun (del, _) -> del = pkh) l with + | None -> failwith "%s - Missing delegate" __LOC__ + | Some (_, Vote.Yay) -> return_unit + | Some _ -> failwith "%s - Wrong ballot" __LOC__) + delegates_p2 + in + (* skip to cooldown period *) + let* b = bake_until_first_block_of_next_period b in + let* () = + assert_period ~expected_index:2l ~expected_kind:Cooldown b __LOC__ + in + (* no ballots in cooldown period *) + let* () = assert_empty_ballots b __LOC__ in + (* listings must be populated in cooldown period before moving to promotion_vote period *) + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* skip to promotion period *) + let* b = bake_until_first_block_of_next_period b in + let* () = + assert_period ~expected_kind:Promotion ~expected_index:3l b __LOC__ + in + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* period 3 *) + (* listings must be populated in promotion period *) + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* beginning of promotion period, denoted by _p4; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p4, power_p4 = get_delegates_and_power_from_listings b in + (* no proposals during promotion period *) + let* ps = Context.Vote.get_proposals (B b) in + let* () = + if Environment.Protocol_hash.Map.is_empty ps then return_unit + else failwith "%s - Unexpected proposals" __LOC__ + in + (* current proposal must be set during promotion period *) + let* () = + let* v_opt = Context.Vote.get_current_proposal (B b) in + match v_opt with + | Some v -> + if Protocol_hash.(equal zero v) then return_unit + else failwith "%s - Wrong proposal" __LOC__ + | None -> failwith "%s - Missing proposal" __LOC__ + in + (* unanimous vote: all delegates --active when p4 started-- vote *) + let* operations = + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + delegates_p4 + in + let* b = Block.bake ~operations b in + List.fold_left (fun acc v -> Int64.(add v acc)) 0L power_p4 + |> fun power_sum -> + (* # of Yays in ballots matches voting power of the delegate *) + let* () = + assert_ballots Vote.{yay = power_sum; nay = 0L; pass = 0L} b __LOC__ + in + (* One Yay ballot per delegate *) + let* () = + let* l_opt = Context.Vote.get_ballot_list (B b) in + match l_opt with + | [] -> failwith "%s - Unexpected empty ballot list" __LOC__ + | l -> + List.iter_es + (fun delegate -> + let pkh = Context.Contract.pkh delegate in + match List.find_opt (fun (del, _) -> del = pkh) l with + | None -> failwith "%s - Missing delegate" __LOC__ + | Some (_, Vote.Yay) -> return_unit + | Some _ -> failwith "%s - Wrong ballot" __LOC__) + delegates_p4 + in + (* skip to end of promotion period and activation*) + let* b = bake_until_first_block_of_next_period b in + let* () = + assert_period ~expected_kind:Adoption ~expected_index:4l b __LOC__ + in + (* skip to end of Adoption period and bake 1 more to activate *) + let* b = bake_until_first_block_of_next_period b in + let* () = + assert_period ~expected_kind:Proposal ~expected_index:5l b __LOC__ + in + let* () = assert_listings_not_empty b ~loc:__LOC__ in + (* zero is the new protocol (before the vote this value is unset) *) + let*! p = Context.Vote.get_protocol b in + let* () = + Assert.equal + ~loc:__LOC__ + Protocol_hash.equal + "Unexpected proposal" + Protocol_hash.pp + p + Protocol_hash.zero + in + return_unit + +(* given a list of active delegates, + return the first k active delegates with which one can have quorum, that is: + their voting power divided by the total voting power is bigger than pr_ema_weight/den *) +let get_smallest_prefix_voters_for_quorum active_delegates active_power + participation_ema = + let expected_quorum = expected_qr_num participation_ema in + List.fold_left (fun acc v -> Int64.(add v acc)) 0L active_power + |> fun active_power_sum -> + let rec loop delegates power sum selected = + match (delegates, power) with + | [], [] -> selected + | del :: delegates, del_power :: power -> + if + den * sum + < Float.to_int (expected_quorum *. Int64.to_float active_power_sum) + then + loop delegates power (sum + Int64.to_int del_power) (del :: selected) + else selected + | _, _ -> [] + in + loop active_delegates active_power 0 [] + +let get_expected_participation_ema power voter_power old_participation_ema = + (* formula to compute the updated participation_ema *) + let get_updated_participation_ema old_participation_ema participation = + ((pr_ema_weight * Int32.to_int old_participation_ema) + + (pr_num * participation)) + / den + in + List.fold_left (fun acc v -> Int64.(add v acc)) 0L power |> fun power_sum -> + List.fold_left (fun acc v -> Int64.(add v acc)) 0L voter_power + |> fun voter_power_sum -> + let participation = + Int64.(to_int (div (mul voter_power_sum (of_int percent_mul)) power_sum)) + in + get_updated_participation_ema old_participation_ema participation + +(** If not enough quorum + -- get_updated_participation_ema < pr_ema_weight/den -- + in exploration, go back to proposal period. *) +let test_not_enough_quorum_in_exploration num_delegates () = + let open Lwt_result_syntax in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + let* b, delegates = context_init ~min_proposal_quorum num_delegates () in + (* proposal period *) + let open Alpha_context in + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + let* operation = Op.proposals (B b) proposer [Protocol_hash.zero] in + let* b = Block.bake ~operation b in + (* skip to exploration period *) + let* b = bake_until_first_block_of_next_period b in + (* we moved to an exploration period with one proposal *) + let* () = assert_period ~expected_kind:Exploration b __LOC__ in + let* initial_participation_ema = Context.Vote.get_participation_ema b in + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p2, power_p2 = get_delegates_and_power_from_listings b in + let* participation_ema = Context.Vote.get_participation_ema b in + get_smallest_prefix_voters_for_quorum delegates_p2 power_p2 participation_ema + |> fun voters -> + (* take the first two voters out so there cannot be quorum *) + let voters_without_quorum = + WithExceptions.Option.get ~loc:__LOC__ @@ List.tl voters + in + let* voters_power_in_exploration = + get_power b voters_without_quorum __LOC__ + in + (* all voters_without_quorum vote, for yays; + no nays, so supermajority is satisfied *) + let* operations = + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + voters_without_quorum + in + let* b = Block.bake ~operations b in + (* bake to next period *) + let* b = bake_until_first_block_of_next_period b in + (* we move back to the proposal period because not enough quorum *) + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + (* check participation_ema update *) + get_expected_participation_ema + power_p2 + voters_power_in_exploration + initial_participation_ema + |> fun expected_participation_ema -> + let* new_participation_ema = Context.Vote.get_participation_ema b in + (* assert the formula to calculate participation_ema is correct *) + let* () = + Assert.equal_int + ~loc:__LOC__ + expected_participation_ema + (Int32.to_int new_participation_ema) + in + return_unit + +(** If not enough quorum + -- get_updated_participation_ema < pr_ema_weight/den -- + In promotion period, go back to proposal period. *) +let test_not_enough_quorum_in_promotion num_delegates () = + let open Lwt_result_syntax in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + let* b, delegates = context_init ~min_proposal_quorum num_delegates () in + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + let* operation = Op.proposals (B b) proposer [Protocol_hash.zero] in + let* b = Block.bake ~operation b in + (* skip to exploration period *) + let* b = bake_until_first_block_of_next_period b in + (* we moved to an exploration period with one proposal *) + let* () = assert_period ~expected_kind:Exploration b __LOC__ in + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p2, power_p2 = get_delegates_and_power_from_listings b in + let* participation_ema = Context.Vote.get_participation_ema b in + get_smallest_prefix_voters_for_quorum delegates_p2 power_p2 participation_ema + |> fun voters -> + let open Alpha_context in + (* all voters vote, for yays; + no nays, so supermajority is satisfied *) + let* operations = + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + voters + in + let* b = Block.bake ~operations b in + (* skip to first block cooldown period *) + let* b = bake_until_first_block_of_next_period b in + (* we move to cooldown because we have supermajority and enough quorum *) + let* () = assert_period ~expected_kind:Cooldown b __LOC__ in + (* skip to first block of promotion period *) + let* b = bake_until_first_block_of_next_period b in + let* () = + assert_period ~expected_kind:Promotion b __LOC__ + (* let* b = bake_until_first_block_of_next_period ~offset:1l b + * in assert_period ~expected_kind:Promotion b __LOC__ *) + in + let* initial_participation_ema = Context.Vote.get_participation_ema b in + (* beginning of promotion period, denoted by _p4; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p4, power_p4 = get_delegates_and_power_from_listings b in + let* participation_ema = Context.Vote.get_participation_ema b in + get_smallest_prefix_voters_for_quorum delegates_p4 power_p4 participation_ema + |> fun voters -> + (* take the first voter out so there cannot be quorum *) + let voters_without_quorum = + WithExceptions.Option.get ~loc:__LOC__ @@ List.tl voters + in + let* voter_power = get_power b voters_without_quorum __LOC__ in + (* all voters_without_quorum vote, for yays; + no nays, so supermajority is satisfied *) + let* operations = + List.map_es + (fun del -> Op.ballot (B b) del Protocol_hash.zero Vote.Yay) + voters_without_quorum + in + let* b = Block.bake ~operations b in + (* skip to end of promotion period *) + let* b = bake_until_first_block_of_next_period b in + get_expected_participation_ema power_p4 voter_power initial_participation_ema + |> fun expected_participation_ema -> + let* new_participation_ema = Context.Vote.get_participation_ema b in + (* assert the formula to calculate participation_ema is correct *) + let* () = + Assert.equal_int + ~loc:__LOC__ + expected_participation_ema + (Int32.to_int new_participation_ema) + in + (* we move back to the proposal period because not enough quorum *) + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + let* () = assert_listings_not_empty b ~loc:__LOC__ in + return_unit + +(** Assume the initial balance of accounts allocated by Context.init_n is at + least 4 times the value of the minimal_stake constant. *) +let test_supermajority_in_proposal there_is_a_winner () = + let open Lwt_result_syntax in + let min_proposal_quorum = 0l in + let initial_balance = 1L in + let* b, delegates = + context_init + ~min_proposal_quorum + ~bootstrap_balances:[initial_balance; initial_balance; initial_balance] + 10 + () + in + let* { + parametric = + { + minimal_stake; + minimal_frozen_stake; + adaptive_issuance = {autostaking_enable; _}; + _; + }; + _; + } = + Context.get_constants (B b) + in + let del1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 in + let del2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 1 in + let del3 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 2 in + let pkhs = + List.map (fun del -> Context.Contract.pkh del) [del1; del2; del3] + in + let policy = Block.Excluding pkhs in + let* op1 = + Op.transaction + (B b) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 3) + del1 + minimal_stake + in + let* op2 = + Op.transaction + (B b) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 4) + del2 + minimal_stake + in + let*? bal3 = + if there_is_a_winner then Test_tez.( *? ) minimal_stake 3L + else + let open Result_syntax in + let* t = Test_tez.( *? ) minimal_stake 2L in + Test_tez.( +? ) (Test_tez.of_mutez_exn initial_balance) t + in + let* op3 = + Op.transaction + (B b) + (WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 5) + del3 + bal3 + in + let* staking_ops = + if autostaking_enable then return_nil + else + let* op4 = + Adaptive_issuance_helpers.stake (B b) del1 minimal_frozen_stake + in + let* op5 = + Adaptive_issuance_helpers.stake (B b) del2 minimal_frozen_stake + in + let* op6 = + Adaptive_issuance_helpers.stake (B b) del3 minimal_frozen_stake + in + return [op4; op5; op6] + in + let* b = Block.bake ~policy ~operations:([op1; op2; op3] @ staking_ops) b in + let* b = bake_until_first_block_of_next_period ~policy b in + (* make the proposals *) + let* ops1 = Op.proposals (B b) del1 [protos.(0)] in + let* ops2 = Op.proposals (B b) del2 [protos.(0)] in + let* ops3 = Op.proposals (B b) del3 [protos.(1)] in + let* b = Block.bake ~policy ~operations:[ops1; ops2; ops3] b in + let* b = bake_until_first_block_of_next_period ~policy b in + (* we remain in the proposal period when there is no winner, + otherwise we move to the exploration period *) + let* () = + if there_is_a_winner then assert_period ~expected_kind:Exploration b __LOC__ + else assert_period ~expected_kind:Proposal b __LOC__ + in + return_unit + +(** After one voting period, if [has_quorum] then the period kind must + have been the cooldown vote. Otherwise, it should have remained in + place in the proposal period. *) +let test_quorum_in_proposal has_quorum () = + let open Lwt_result_syntax in + let total_tokens = 32_000_000_000_000L in + let half_tokens = Int64.div total_tokens 2L in + let* b, delegates = + context_init ~bootstrap_balances:[1L; half_tokens; half_tokens] 3 () + in + let* { + parametric = + {min_proposal_quorum; adaptive_issuance = {autostaking_enable; _}; _}; + _; + } = + Context.get_constants (B b) + in + let del1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 in + let del2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 1 in + let pkhs = List.map (fun del -> Context.Contract.pkh del) [del1; del2] in + let policy = Block.Excluding pkhs in + let quorum = + if has_quorum then Int64.of_int32 min_proposal_quorum + else Int64.(sub (of_int32 min_proposal_quorum) 10L) + in + let bal = + Int64.(div (mul total_tokens quorum) 100_00L) |> Test_tez.of_mutez_exn + in + let* op2 = Op.transaction (B b) del2 del1 bal in + let* b = Block.bake ~policy ~operation:op2 b in + let* b = + if autostaking_enable then return b + else + let* stake = Adaptive_issuance_helpers.stake (B b) del1 bal in + Block.bake ~policy ~operation:stake b + in + let* b = bake_until_first_block_of_next_period b in + (* make the proposal *) + let* operation = Op.proposals (B b) del1 [protos.(0)] in + let* b = Block.bake ~policy ~operation b in + let* b = bake_until_first_block_of_next_period b in + (* we remain in the proposal period when there is no quorum, + otherwise we move to the cooldown vote period *) + let* () = + if has_quorum then assert_period ~expected_kind:Exploration b __LOC__ + else assert_period ~expected_kind:Proposal b __LOC__ + in + return_unit + +(** If a supermajority is reached, then the voting period must be + reached. Otherwise, it remains in proposal period. *) +let test_supermajority_in_exploration supermajority () = + let open Lwt_result_syntax in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / 100)) in + let* b, delegates = context_init ~min_proposal_quorum 100 () in + let del1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 in + let proposal = protos.(0) in + let* operation = Op.proposals (B b) del1 [proposal] in + let* b = Block.bake ~operation b in + let* b = bake_until_first_block_of_next_period b in + (* move to exploration *) + let* () = assert_period ~expected_kind:Exploration b __LOC__ in + (* assert our proposal won *) + let* () = + let* v_opt = Context.Vote.get_current_proposal (B b) in + match v_opt with + | Some v -> + if Protocol_hash.(equal proposal v) then return_unit + else failwith "%s - Wrong proposal" __LOC__ + | None -> failwith "%s - Missing proposal" __LOC__ + in + (* beginning of exploration period, denoted by _p2; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p2, _power_p2 = get_delegates_and_power_from_listings b in + (* supermajority means [num_yays / (num_yays + num_nays) >= s_num / s_den], + which is equivalent with [num_yays >= num_nays * s_num / (s_den - s_num)] *) + let num_delegates = List.length delegates_p2 in + let num_nays = num_delegates / 5 in + (* any smaller number will do as well *) + let num_yays = num_nays * s_num / (s_den - s_num) in + (* majority/minority vote depending on the [supermajority] parameter *) + let num_yays = if supermajority then num_yays else num_yays - 1 in + let open Alpha_context in + let nays_delegates, rest = List.split_n num_nays delegates_p2 in + let yays_delegates, _ = List.split_n num_yays rest in + let* operations_yays = + List.map_es + (fun del -> Op.ballot (B b) del proposal Vote.Yay) + yays_delegates + in + let* operations_nays = + List.map_es + (fun del -> Op.ballot (B b) del proposal Vote.Nay) + nays_delegates + in + let operations = operations_yays @ operations_nays in + let* b = Block.bake ~operations b in + let* b = bake_until_first_block_of_next_period b in + let* () = + if supermajority then assert_period ~expected_kind:Cooldown b __LOC__ + else assert_period ~expected_kind:Proposal b __LOC__ + in + return_unit + +(** Test also how the selection scales: all delegates propose max + proposals. *) +let test_no_winning_proposal num_delegates () = + let open Lwt_result_syntax in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + let* b, _ = context_init ~min_proposal_quorum num_delegates () in + (* beginning of proposal, denoted by _p1; + take a snapshot of the active delegates and their voting power from listings *) + let* delegates_p1, _power_p1 = get_delegates_and_power_from_listings b in + let open Alpha_context in + let props = + List.map (fun i -> protos.(i)) (1 -- Constants.max_proposals_per_delegate) + in + (* all delegates active in p1 propose the same proposals *) + let* operations = + List.map_es (fun del -> Op.proposals (B b) del props) delegates_p1 + in + let* b = Block.bake ~operations b in + (* skip to exploration period *) + let* b = bake_until_first_block_of_next_period b in + (* we stay in the same proposal period because no winning proposal *) + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + return_unit + +(** Vote to pass with maximum possible participation_ema (100%), it is + sufficient for the vote quorum to be equal or greater than the + maximum quorum cap. *) +let test_quorum_capped_maximum num_delegates () = + let open Lwt_result_syntax in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + let* b, delegates = context_init ~min_proposal_quorum num_delegates () in + (* set the participation EMA to 100% *) + let*! b = Context.Vote.set_participation_ema b 100_00l in + let* {parametric = {quorum_max; _}; _} = Context.get_constants (B b) in + (* proposal period *) + let open Alpha_context in + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + (* propose a new protocol *) + let protocol = Protocol_hash.zero in + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + let* operation = Op.proposals (B b) proposer [protocol] in + let* b = Block.bake ~operation b in + (* skip to exploration period *) + let* b = bake_until_first_block_of_next_period b in + (* we moved to an exploration period with one proposal *) + let* () = assert_period ~expected_kind:Exploration b __LOC__ in + (* take percentage of the delegates equal or greater than quorum_max *) + let minimum_to_pass = + Float.of_int (List.length delegates) + *. Int32.(to_float quorum_max) + /. 100_00. + |> Float.ceil |> Float.to_int + in + let voters = List.take_n minimum_to_pass delegates in + (* all voters vote for yays; no nays, so supermajority is satisfied *) + let* operations = + List.map_es (fun del -> Op.ballot (B b) del protocol Vote.Yay) voters + in + let* b = Block.bake ~operations b in + (* skip to next period *) + let* b = bake_until_first_block_of_next_period b in + (* expect to move to cooldown because we have supermajority and enough quorum *) + assert_period ~expected_kind:Cooldown b __LOC__ + +(** Vote to pass with minimum possible participation_ema (0%), it is + sufficient for the vote quorum to be equal or greater than the + minimum quorum cap. *) +let test_quorum_capped_minimum num_delegates () = + let open Lwt_result_syntax in + let min_proposal_quorum = Int32.(of_int @@ (100_00 / num_delegates)) in + let* b, delegates = context_init ~min_proposal_quorum num_delegates () in + (* set the participation EMA to 0% *) + let*! b = Context.Vote.set_participation_ema b 0l in + let* {parametric = {quorum_min; _}; _} = Context.get_constants (B b) in + (* proposal period *) + let open Alpha_context in + let* () = assert_period ~expected_kind:Proposal b __LOC__ in + (* propose a new protocol *) + let protocol = Protocol_hash.zero in + let proposer = + WithExceptions.Option.get ~loc:__LOC__ @@ List.nth delegates 0 + in + let* operation = Op.proposals (B b) proposer [protocol] in + let* b = Block.bake ~operation b in + (* skip to exploration period *) + let* b = bake_until_first_block_of_next_period b in + (* we moved to an exploration period with one proposal *) + let* () = assert_period ~expected_kind:Exploration b __LOC__ in + (* take percentage of the delegates equal or greater than quorum_min *) + let minimum_to_pass = + Float.of_int (List.length delegates) + *. Int32.(to_float quorum_min) + /. 100_00. + |> Float.ceil |> Float.to_int + in + let voters = List.take_n minimum_to_pass delegates in + (* all voters vote for yays; no nays, so supermajority is satisfied *) + let* operations = + List.map_es (fun del -> Op.ballot (B b) del protocol Vote.Yay) voters + in + let* b = Block.bake ~operations b in + (* skip to next period *) + let* b = bake_until_first_block_of_next_period b in + (* expect to move to cooldown because we have supermajority and enough quorum *) + assert_period ~expected_kind:Cooldown b __LOC__ + +(* gets the voting power *) +let get_voting_power block pkhash = + let ctxt = Context.B block in + Context.get_voting_power ctxt pkhash + +(** Test that the voting power changes if the balance between bakers changes + and the blockchain moves to the next voting period. It also checks that + the total voting power coincides with the addition of the voting powers + of bakers *) +let test_voting_power_updated_each_voting_period () = + let open Lwt_result_syntax in + let init_bal1 = 80_000_000_000L in + let init_bal2 = 48_000_000_000L in + let init_bal3 = 40_000_000_000L in + (* Create three accounts with different amounts *) + let* genesis, contracts = + context_init ~bootstrap_balances:[init_bal1; init_bal2; init_bal3] 3 () + in + let con1 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 0 in + let con2 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 1 in + let con3 = WithExceptions.Option.get ~loc:__LOC__ @@ List.nth contracts 2 in + (* Get the key hashes of the bakers *) + let baker1 = Context.Contract.pkh con1 in + let baker2 = Context.Contract.pkh con2 in + let baker3 = Context.Contract.pkh con3 in + (* Retrieve balance of con1 *) + let open Test_tez in + let* balance1 = Context.Contract.balance (B genesis) con1 in + let* frozen_deposits1 = + Context.Delegate.current_frozen_deposits (B genesis) baker1 + in + let*? full_balance1 = balance1 +? frozen_deposits1 in + let* () = + Assert.equal_tez ~loc:__LOC__ full_balance1 (of_mutez_exn init_bal1) + in + (* Retrieve balance of con2 *) + let* balance2 = Context.Contract.balance (B genesis) con2 in + let* frozen_deposits2 = + Context.Delegate.current_frozen_deposits (B genesis) baker2 + in + let*? full_balance2 = balance2 +? frozen_deposits2 in + let* () = + Assert.equal_tez ~loc:__LOC__ full_balance2 (of_mutez_exn init_bal2) + in + (* Retrieve balance of con3 *) + let* balance3 = Context.Contract.balance (B genesis) con3 in + let* frozen_deposits3 = + Context.Delegate.current_frozen_deposits (B genesis) baker3 + in + let*? full_balance3 = balance3 +? frozen_deposits3 in + let* () = + Assert.equal_tez ~loc:__LOC__ full_balance3 (of_mutez_exn init_bal3) + in + (* Auxiliary assert_voting_power *) + let assert_voting_power ~loc n block baker = + let* voting_power = get_voting_power block baker in + Assert.equal_int64 ~loc n voting_power + in + (* Auxiliary assert_total_voting_power *) + let assert_total_voting_power ~loc n block = + let* total_voting_power = Context.get_total_voting_power (B block) in + Assert.equal_int64 ~loc n total_voting_power + in + let expected_power_of_baker_1 = Tez.to_mutez full_balance1 in + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_1 genesis baker1 + in + let expected_power_of_baker_2 = Tez.to_mutez full_balance2 in + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_2 genesis baker2 + in + (* Assert total voting power *) + let expected_power_of_baker_3 = Tez.to_mutez full_balance3 in + let* () = + assert_total_voting_power + ~loc:__LOC__ + Int64.( + add + (add expected_power_of_baker_1 expected_power_of_baker_2) + expected_power_of_baker_3) + genesis + in + (* Create policy that excludes baker1 and baker2 from baking *) + let policy = Block.Excluding [baker1; baker2] in + (* Transfer 30,000 tez from baker1 to baker2 *) + let amount = Tez.of_mutez_exn 30_000_000_000L in + let* operation = Op.transaction (B genesis) con1 con2 amount in + (* Bake the block containing the transaction *) + let* block = Block.bake ~policy ~operation genesis in + (* Retrieve balance of con1 *) + let* balance1 = Context.Contract.balance (B block) con1 in + (* Assert balance has changed by deducing the amount *) + let*? balance1_after_deducing_amount = of_mutez_exn init_bal1 -? amount in + let* frozen_deposit1 = + Context.Delegate.current_frozen_deposits (B block) baker1 + in + let* () = + let*? t = balance1_after_deducing_amount -? frozen_deposit1 in + Assert.equal_tez ~loc:__LOC__ balance1 t + in + (* Retrieve balance of con2 *) + let* balance2 = Context.Contract.balance (B block) con2 in + (* Assert balance has changed by adding amount *) + let*? balance2_after_adding_amount = of_mutez_exn init_bal2 +? amount in + let* frozen_deposit2 = + Context.Delegate.current_frozen_deposits (B block) baker2 + in + let* () = + let*? t = balance2_after_adding_amount -? frozen_deposit2 in + Assert.equal_tez ~loc:__LOC__ balance2 t + in + let* block = Block.bake ~policy block in + (* Assert voting power (and total) remains the same before next voting period *) + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_1 block baker1 + in + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_2 block baker2 + in + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_3 block baker3 + in + let* () = + assert_total_voting_power + ~loc:__LOC__ + Int64.( + add + (add expected_power_of_baker_1 expected_power_of_baker_2) + expected_power_of_baker_3) + block + in + let* block = bake_until_first_block_of_next_period block in + (* Assert voting power of baker1 has decreased by [amount] *) + let expected_power_of_baker_1 = + Int64.sub expected_power_of_baker_1 (Tez.to_mutez amount) + in + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_1 block baker1 + in + (* Assert voting power of baker2 has increased by [amount] *) + let expected_power_of_baker_2 = + Int64.add expected_power_of_baker_2 (Tez.to_mutez amount) + in + let* () = + assert_voting_power ~loc:__LOC__ expected_power_of_baker_2 block baker2 + in + (* Retrieve voting power of baker3 *) + let* power = get_voting_power block baker3 in + let power_of_baker_3 = power in + (* Assert total voting power *) + assert_total_voting_power + ~loc:__LOC__ + Int64.( + add + (add expected_power_of_baker_1 expected_power_of_baker_2) + power_of_baker_3) + block + +let test_voting_period_pp () = + let vp = + Voting_period_repr. + { + index = Int32.of_int 123; + kind = Proposal; + start_position = Int32.of_int 321; + } + in + Assert.equal + ~loc:__LOC__ + ( = ) + "Unexpected pretty printing of voting period" + Format.pp_print_string + (Format.asprintf "%a" Voting_period_repr.pp vp) + "index: 123, kind:proposal, start_position: 321" + +(** {2 Validity tests} + + For each vote operation (Proposals and Ballot), we define a serie + of negative tests and a positive test. + + Negative tests target errors that can occur during + application. They check that the appropriate error is triggered. + + If the operation is valid, then its application must succeed when + it is baked into a block. Positive tests observe the effects of the + operation application by comparing the states before and after the + block. *) + +(** {3 Proposal -- Negative tests} *) + +(** Test that a Proposals operation fails when it is unsigned. *) +let test_proposals_missing_signature () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let* contents = Op.proposals_contents (B block) proposer [protos.(0)] in + let op = Op.pack_operation (B block) None contents in + Incremental.assert_validate_operation_fails + (missing_signature __LOC__) + op + block + +(** Test that a Proposals operation fails when its signature is invalid. *) +let test_proposals_invalid_signature () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let* contents = Op.proposals_contents (B block) proposer [protos.(0)] in + let op = Op.pack_operation (B block) (Some Signature.zero) contents in + Incremental.assert_validate_operation_fails + (invalid_signature __LOC__) + op + block + +(** Test that a Proposals operation fails when the period index + provided in the operation is not the current voting period index. *) +let test_proposals_wrong_voting_period_index () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let* current_period = Context.Vote.get_current_period (B block) in + let current_index = current_period.voting_period.index in + let op_index = Int32.succ current_index in + assert_validate_proposals_fails + ~expected_error:(wrong_voting_period_index ~current_index ~op_index) + ~proposer + ~proposals:[Protocol_hash.zero] + ~period:op_index + block + __LOC__ + +(** Test that a Proposals operation fails when it occurs in a + non-Proposal voting period. *) +let test_proposals_wrong_voting_period_kind () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let proposal = protos.(0) in + let assert_proposals_fails_with_unexpected_proposal = + assert_validate_proposals_fails + ~expected_error:wrong_voting_period_kind + ~proposer + ~proposals:[proposal] + in + (* End the initial Proposals period with a submitted + proposal, to move on to an Exploration period. *) + let* operation = Op.proposals (B block) proposer [proposal] in + let* block = Block.bake block ~operation in + let* block = bake_until_first_block_of_next_period block in + (* Proposals during Exploration. *) + let* () = assert_period ~expected_kind:Exploration block __LOC__ in + let* () = assert_proposals_fails_with_unexpected_proposal block __LOC__ in + (* End the Exploration period with enough votes to move on to a + Cooldown period. *) + let* operation = Op.ballot (B block) proposer proposal Vote.Yay in + let* block = Block.bake ~operation block in + let* block = bake_until_first_block_of_next_period block in + (* Proposals during Cooldown. *) + let* () = assert_period ~expected_kind:Cooldown block __LOC__ in + let* () = assert_proposals_fails_with_unexpected_proposal block __LOC__ in + (* Proposals during Promotion. *) + let* block = bake_until_first_block_of_next_period block in + let* () = assert_period ~expected_kind:Promotion block __LOC__ in + let* () = assert_proposals_fails_with_unexpected_proposal block __LOC__ in + (* End the Promotion period with enough votes to move on to an + Adoption period. *) + let* operation = Op.ballot (B block) proposer proposal Vote.Yay in + let* block = Block.bake ~operation block in + let* block = bake_until_first_block_of_next_period block in + (* Proposals during Adoption. *) + let* () = assert_period ~expected_kind:Adoption block __LOC__ in + assert_proposals_fails_with_unexpected_proposal block __LOC__ + +(** Test that a Proposals operation fails when the proposer is not in + the vote listings (with the same error, no matter how far the + source is from being a delegate with voting rights). *) +let test_proposals_source_not_in_vote_listings () = + let open Lwt_result_syntax in + (* The chosen [blocks_per_cycle] is an arbitrary value that we will + not reach with the blocks baked in this test. *) + let* block, funder = context_init1 ~blocks_per_cycle:10l () in + let fresh_account = Account.new_account () in + let proposer = Contract.Implicit fresh_account.pkh in + let assert_fails_with_unregistered_delegate block = + assert_validate_proposals_fails + ~expected_error:proposals_from_unregistered_delegate + ~proposer + ~proposals:[Protocol_hash.zero] + block + in + let assert_fails_with_source_not_in_vote_listings block = + assert_validate_proposals_fails + ~expected_error:source_not_in_vote_listings + ~proposer + ~proposals:[Protocol_hash.zero] + block + in + (* Fail when the source has no contract in the storage. *) + let* () = assert_fails_with_unregistered_delegate block __LOC__ in + let* operation = Op.transaction (B block) funder proposer Tez.one in + let* block = Block.bake block ~operation in + (* Fail when the contract's public key is unreavealed. *) + let* () = assert_fails_with_unregistered_delegate block __LOC__ in + let* operation = Op.revelation (B block) fresh_account.pk in + let* block = Block.bake block ~operation in + (* Fail when the source is not a delegate. *) + let* () = assert_fails_with_unregistered_delegate block __LOC__ in + let* operation = Op.delegation (B block) proposer (Some fresh_account.pkh) in + let* block = Block.bake block ~operation in + (* Fail when the source is a delegate, but not yet in the vote listings. *) + assert_fails_with_source_not_in_vote_listings block __LOC__ + +(** Test that a Proposals operation fails when its proposal list is + empty. *) +let test_empty_proposals () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + assert_validate_proposals_fails + ~expected_error:empty_proposals + ~proposer + ~proposals:[] + block + __LOC__ + +(** Test that a Proposals operation fails when its proposal list + contains multiple occurrences of the same proposal. *) +let test_proposals_contain_duplicate () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + assert_validate_proposals_fails + ~expected_error:(proposals_contain_duplicate protos.(1)) + ~proposer + ~proposals:[protos.(0); protos.(1); protos.(2); protos.(1); protos.(3)] + block + __LOC__ + +(** Test that a Proposals operation fails when it would make the total + count of proposals submitted by the proposer exceed the + [max_proposals_per_delegate] protocol constant. *) +let test_too_many_proposals () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + assert (Array.length protos >= Constants.max_proposals_per_delegate + 1) ; + let proposals = + List.map (Array.get protos) (1 -- Constants.max_proposals_per_delegate) + in + let* operation = Op.proposals (B block) proposer proposals in + let* block = Block.bake block ~operation in + assert_validate_proposals_fails + ~expected_error:too_many_proposals + ~proposer + ~proposals:[protos.(0)] + block + __LOC__ + +(** Test that a Proposals operation fails when one of its proposals has + already been submitted by the same proposer in an earlier block. *) +let test_already_proposed () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let* operation = Op.proposals (B block) proposer [protos.(0); protos.(1)] in + let* block = Block.bake block ~operation in + (* The [proposer] cannot submit protocol [0] again. *) + let* () = + assert_validate_proposals_fails + ~expected_error:(already_proposed protos.(0)) + ~proposer + ~proposals:[protos.(0)] + block + __LOC__ + in + (* The [proposer] cannot submit protocol [1] again, even among other + new proposals. *) + let* () = + assert_validate_proposals_fails + ~expected_error:(already_proposed protos.(1)) + ~proposer + ~proposals:[protos.(2); protos.(1); protos.(3)] + block + __LOC__ + in + (* The initial [operation] cannot be replayed. *) + let* () = + Incremental.assert_validate_operation_fails + (already_proposed protos.(0) __LOC__) + operation + block + in + let* block = bake_until_first_block_of_next_period block in + Incremental.assert_validate_operation_fails + (wrong_voting_period_index ~current_index:1l ~op_index:0l __LOC__) + operation + block + +(** Test that a Proposals operation fails when it would make the total + count of proposals submitted by the proposer exceed the + [max_proposals_per_delegate] protocol constant, because of + previously validated operations in the current block/mempool. *) +let test_conflict_too_many_proposals () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let n_proposals_in_previous_blocks = 5 in + assert (Array.length protos >= Constants.max_proposals_per_delegate + 1) ; + let proposals_in_previous_blocks = + List.map (Array.get protos) (1 -- n_proposals_in_previous_blocks) + in + let* operation = + Op.proposals (B block) proposer proposals_in_previous_blocks + in + let* block = Block.bake block ~operation in + let* current_block_state = Incremental.begin_construction block in + let proposals_in_current_block = + List.map + (Array.get protos) + (n_proposals_in_previous_blocks + 1 + -- Constants.max_proposals_per_delegate) + in + let* op_in_current_block = + Op.proposals (B block) proposer proposals_in_current_block + in + let* current_block_state = + Incremental.validate_operation current_block_state op_in_current_block + in + let* op = Op.proposals (B block) proposer [protos.(0)] in + let* (_i : Incremental.t) = + Incremental.validate_operation + ~expect_failure:(conflicting_proposals __LOC__) + current_block_state + op + in + return_unit + +(** Test that a Proposals operation fails when its source has already + submitted a Proposals operation in the current block/mempool. *) +let test_conflicting_proposal () = + let open Lwt_result_syntax in + let* block, proposer = context_init1 () in + let proposal = protos.(0) in + let* current_block_state = Incremental.begin_construction block in + let* op_in_current_block = Op.proposals (B block) proposer [proposal] in + let* current_block_state = + Incremental.validate_operation current_block_state op_in_current_block + in + let* op = Op.proposals (B block) proposer [proposal] in + let* (_i : Incremental.t) = + Incremental.validate_operation + ~expect_failure:(conflicting_proposals __LOC__) + current_block_state + op + in + let proposal' = protos.(1) in + let* op' = Op.proposals (B block) proposer [proposal'] in + let* (_i : Incremental.t) = + Incremental.validate_operation + ~expect_failure:(conflicting_proposals __LOC__) + current_block_state + op' + in + return_unit + +(** {3 Proposals -- Positive test} + + A Proposals operation is valid when: + + - its source is a registered delegate and belongs to the voting + listings, + + - the current voting period is a Proposal period and has the same + index as the period provided in the operation, + + - its list of proposals is not empty, + + - it won't make the total proposal count of the proposer exceed + the [max_proposals_per_delegate] protocol constant, and + + - its signature is valid. + + We can observe the successful application of the Proposals + operation from a pre-state to a post-state as follows: + + - the proposal count of the proposer has been incremented by the + number of proposals in the operation, + + - the operation proposals have been added to the recorded + proposals of the proposer, and + + - the total weight supporting each of the proposals has been + incremented by the voting power of the proposer. *) + +let observe_proposals pre_state post_state op caller_loc = + let open Lwt_result_syntax in + let make_loc = append_loc ~caller_loc in + let* (Proposals {source; period; proposals}) = + let (Operation_data {contents; _}) = op.protocol_data in + match contents with + | Single (Proposals _ as contents) -> return contents + | _ -> failwith "%s - Expected a Proposals operation" (make_loc __LOC__) + in + + (* Validity conditions *) + let proposals_num = List.length proposals in + let* () = Assert.not_equal_int ~loc:(make_loc __LOC__) 0 proposals_num in + let* () = + assert_period ~expected_kind:Proposal pre_state (make_loc __LOC__) + in + let* pre_period = Context.Vote.get_current_period (B pre_state) in + let* () = + Assert.equal_int32 + ~loc:(make_loc __LOC__) + period + pre_period.voting_period.index + in + let* del = + Context.Contract.delegate (B pre_state) (Contract.Implicit source) + in + let* () = Assert.equal_pkh ~loc:(make_loc __LOC__) source del in + let* dels, _powers = get_delegates_and_power_from_listings pre_state in + assert (List.mem ~equal:Contract.equal (Contract.Implicit source) dels) ; + let* pre_voting_infos = Context.Delegate.voting_info (B pre_state) source in + let* () = + Assert.not_equal_int + ~loc:(make_loc __LOC__) + 0 + pre_voting_infos.remaining_proposals + in + let* () = + Assert.leq_int + ~loc:(make_loc __LOC__) + proposals_num + pre_voting_infos.remaining_proposals + in + + (* Observations *) + (* Check [voting_info] update. *) + let* post_voting_infos = Context.Delegate.voting_info (B post_state) source in + let* () = + Assert.equal_int + ~loc:(make_loc __LOC__) + post_voting_infos.remaining_proposals + (pre_voting_infos.remaining_proposals - proposals_num) + in + assert ( + List.for_all + (fun a -> Stdlib.List.mem a post_voting_infos.current_proposals) + proposals) ; + (* Check [Storage.Vote.Proposals_count] update. *) + let* proposal_count_pre = + Context.Vote.get_delegate_proposal_count (B pre_state) source + in + let* proposal_count_post = + Context.Vote.get_delegate_proposal_count (B post_state) source + in + let* () = + Assert.equal_int + ~loc:(make_loc __LOC__) + (proposal_count_pre + proposals_num) + proposal_count_post + in + (* Check the update of the total weight of supporters for each proposal. *) + let* proposal_weights_pre = Context.Vote.get_proposals (B pre_state) in + let* proposal_weights_post = Context.Vote.get_proposals (B post_state) in + let* source_power = + Assert.get_some ~loc:(make_loc __LOC__) pre_voting_infos.voting_power + in + List.iter_es + (fun proposal -> + let weight_pre = + Environment.Protocol_hash.Map.find proposal proposal_weights_pre + |> Option.value ~default:Int64.zero + in + let* weight_post = + Assert.get_some + ~loc:(make_loc __LOC__) + (Environment.Protocol_hash.Map.find proposal proposal_weights_post) + in + Assert.equal_int64 + ~loc:(make_loc __LOC__) + weight_post + (Int64.add weight_pre source_power)) + proposals + +let test_too_many_proposals_in_one_operation () = + let open Lwt_result_syntax in + let* b0, proposer0 = context_init1 () in + let protos = Array.to_list protos in + Lwt.catch + (fun () -> + let* (_ : packed_operation) = Op.proposals (B b0) proposer0 protos in + failwith + "Encoding of proposals operation with too many proposals should fail") + (function + | Data_encoding.Binary.(Write_error List_invalid_length) -> return_unit + | exn -> Lwt.reraise exn) + +(* Bake blocks with various valid Proposals operations, and observe + that their effects are correctly applied. *) +let test_valid_proposals () = + let open Lwt_result_syntax in + (* We use a higher [blocks_per_cycle] than the + {!default_blocks_per_cycle} (which is [4l]), so that we can bake + each operation in a separate block without reaching the end of + the voting cycle. *) + let* b0, (proposer0, proposer1) = context_init2 ~blocks_per_cycle:10l () in + let* op0 = Op.proposals (B b0) proposer0 [protos.(0)] in + let* b1 = Block.bake b0 ~operation:op0 in + let* () = observe_proposals b0 b1 op0 __LOC__ in + let* op1 = + Op.proposals (B b1) proposer0 [protos.(1); protos.(2); protos.(3)] + in + let* b2 = Block.bake b1 ~operation:op1 in + let* () = observe_proposals b1 b2 op1 __LOC__ in + let* op2 = + Op.proposals + (B b2) + proposer1 + [protos.(0); protos.(2); protos.(4); protos.(5)] + in + let* b3 = Block.bake b2 ~operation:op2 in + let* () = observe_proposals b2 b3 op2 __LOC__ in + let* op3 = Op.proposals (B b3) proposer0 [protos.(5); protos.(6)] in + let* b4 = Block.bake b3 ~operation:op3 in + observe_proposals b3 b4 op3 __LOC__ + +(** {3 Ballot -- Negative tests} *) + +(** Test that a Ballot operation fails when it is unsigned. *) +let test_ballot_missing_signature () = + let open Lwt_result_syntax in + let* block, voter, proposal = context_init_exploration () in + let* contents = Op.ballot_contents (B block) voter proposal Vote.Yay in + let op = Op.pack_operation (B block) None contents in + Incremental.assert_validate_operation_fails + (missing_signature __LOC__) + op + block + +(** Test that a Ballot operation fails when its signature is invalid. *) +let test_ballot_invalid_signature () = + let open Lwt_result_syntax in + let* block, voter, proposal = context_init_exploration () in + let* contents = Op.ballot_contents (B block) voter proposal Vote.Yay in + let op = Op.pack_operation (B block) (Some Signature.zero) contents in + Incremental.assert_validate_operation_fails + (invalid_signature __LOC__) + op + block + +(** Test that a Ballot operation fails when the period index provided + in the operation is not the current voting period index. *) +let test_ballot_wrong_voting_period_index () = + let open Lwt_result_syntax in + let* block, voter = context_init1 () in + let* current_period = Context.Vote.get_current_period (B block) in + let current_index = current_period.voting_period.index in + let op_index = Int32.succ current_index in + assert_validate_ballot_fails + ~expected_error:(wrong_voting_period_index ~current_index ~op_index) + ~voter + ~proposal:protos.(0) + ~ballot:Vote.Yay + ~period:op_index + block + __LOC__ + +(** Test that a Ballot operation fails when it occurs outside of an + Exploration or Promotion voting period. *) +let test_ballot_wrong_voting_period_kind () = + let open Lwt_result_syntax in + let* block, voter = context_init1 () in + let proposal = protos.(0) in + let assert_ballot_fails_with_unexpected_ballot = + assert_validate_ballot_fails + ~expected_error:wrong_voting_period_kind + ~voter + ~proposal + ~ballot:Vote.Nay + in + (* Ballot during Proposals. *) + let* () = assert_period ~expected_kind:Proposal block __LOC__ in + let* () = assert_ballot_fails_with_unexpected_ballot block __LOC__ in + (* End the Proposals period with a submitted proposal, to move on to + an Exploration period. *) + let* operation = Op.proposals (B block) voter [proposal] in + let* block = Block.bake block ~operation in + let* block = bake_until_first_block_of_next_period block in + (* End the Exploration period with enough votes to move on to a + Cooldown period. *) + let* operation = Op.ballot (B block) voter proposal Vote.Yay in + let* block = Block.bake block ~operation in + let* block = bake_until_first_block_of_next_period block in + (* Ballot during Cooldown. *) + let* () = assert_period ~expected_kind:Cooldown block __LOC__ in + let* () = assert_ballot_fails_with_unexpected_ballot block __LOC__ in + (* End the Cooldown period, then end the Promotion period with + enough votes to move on to an Adoption period. *) + let* block = bake_until_first_block_of_next_period block in + let* operation = Op.ballot (B block) voter proposal Vote.Yay in + let* block = Block.bake ~operation block in + let* block = bake_until_first_block_of_next_period block in + (* Ballot during Adoption. *) + let* () = assert_period ~expected_kind:Adoption block __LOC__ in + assert_ballot_fails_with_unexpected_ballot block __LOC__ + +(** Test that a Ballot operation fails when its proposal is not the + current proposal. *) +let test_ballot_for_wrong_proposal () = + let open Lwt_result_syntax in + let* block, voter, current_proposal = + context_init_exploration ~proposal:protos.(0) () + in + let op_proposal = protos.(1) in + assert_validate_ballot_fails + ~expected_error:(ballot_for_wrong_proposal ~current_proposal ~op_proposal) + ~voter + ~proposal:op_proposal + ~ballot:Vote.Yay + block + __LOC__ + +(** Test that a Ballot operation fails when its source has already + submitted a Ballot. *) +let test_already_submitted_a_ballot () = + let open Lwt_result_syntax in + let* block, voter, proposal = context_init_exploration () in + let* operation = Op.ballot (B block) voter proposal Vote.Yay in + let* block = Block.bake ~operation block in + assert_validate_ballot_fails + ~expected_error:already_submitted_a_ballot + ~voter + ~proposal + ~ballot:Vote.Nay + block + __LOC__ + +(** Test that a Ballot operation fails when its source is not in the + vote listings (with the same error, no matter how far the source is + from being a delegate with voting rights). *) +let test_ballot_source_not_in_vote_listings () = + let open Lwt_result_syntax in + let* block, funder, proposal = + (* The chosen [blocks_per_cycle] is an arbitrary value that we + will not reach with the blocks baked in this test. *) + context_init_exploration ~blocks_per_cycle:10l () + in + let fresh_account = Account.new_account () in + let voter = Contract.Implicit fresh_account.pkh in + let assert_fails_with_source_not_in_vote_listings block = + assert_validate_ballot_fails + ~expected_error:source_not_in_vote_listings + ~voter + ~proposal + ~ballot:Vote.Yay + block + in + let assert_fails_with_unregistered_delegate block = + assert_validate_ballot_fails + ~expected_error:ballot_from_unregistered_delegate + ~voter + ~proposal + ~ballot:Vote.Yay + block + in + (* Fail when the source has no contract in the storage. *) + let* () = assert_fails_with_unregistered_delegate block __LOC__ in + let* operation = Op.transaction (B block) funder voter Tez.one in + let* block = Block.bake block ~operation in + (* Fail when the contract's public key is unreavealed. *) + let* () = assert_fails_with_unregistered_delegate block __LOC__ in + let* operation = Op.revelation (B block) fresh_account.pk in + let* block = Block.bake block ~operation in + (* Fail when the source is not a delegate. *) + let* () = assert_fails_with_unregistered_delegate block __LOC__ in + let* operation = Op.delegation (B block) voter (Some fresh_account.pkh) in + let* block = Block.bake block ~operation in + (* Fail when the source is a delegate, but not yet in the vote listings. *) + assert_fails_with_source_not_in_vote_listings block __LOC__ + +(** Test that a Ballot operation fails when its source has already + submitted a Ballot in a previously validated operation of the + current block. *) +let test_conflicting_ballot () = + let open Lwt_result_syntax in + let* block, voter, proposal = context_init_exploration () in + let* current_block_state = Incremental.begin_construction block in + let* op_in_current_block = Op.ballot (B block) voter proposal Vote.Yay in + let* current_block_state = + Incremental.validate_operation current_block_state op_in_current_block + in + let* op = Op.ballot (B block) voter proposal Vote.Nay in + let* (_i : Incremental.t) = + Incremental.validate_operation + ~expect_failure:(conflicting_ballot __LOC__) + current_block_state + op + in + return_unit + +(** {3 Ballot -- Positive test} + + A Ballot operation is valid when: + + - its source is a registered delegate and belongs to the voting + listings, + + - the current voting period is an Exploration or Promotion period, + and has the same index as the period provided in the operation, + + - its proposal is the current proposal in the context, + + - the voter had submitted no ballot in the current voting period + yet, and + + - its signature is valid. + + We can observe the successful application of a Ballot operation by + checking that: + + - the ballot has been recorded for the voter in the post-state, + and + + - the score of the ballot's vote (yay/nay/pass) has been + incremented by the voting power of the source. *) + +let observe_ballot pre_state post_state op caller_loc = + let open Lwt_result_syntax in + let make_loc = append_loc ~caller_loc in + let* (Ballot {source; period; proposal; ballot}) = + let (Operation_data {contents; _}) = op.protocol_data in + match contents with + | Single (Ballot _ as contents) -> return contents + | _ -> failwith "%s - Expected a Ballot operation" (make_loc __LOC__) + in + (* Validity conditions *) + let* () = + assert_period + ~expected_kinds:[Exploration; Promotion] + pre_state + (make_loc __LOC__) + in + let* pre_period = Context.Vote.get_current_period (B pre_state) in + let* () = + Assert.equal_int32 + ~loc:(make_loc __LOC__) + period + pre_period.voting_period.index + in + let* del = + Context.Contract.delegate (B pre_state) (Contract.Implicit source) + in + let* () = Assert.equal_pkh ~loc:(make_loc __LOC__) source del in + let* dels, _powers = get_delegates_and_power_from_listings pre_state in + assert (List.mem ~equal:Contract.equal (Contract.Implicit source) dels) ; + let* pre_voting_infos = Context.Delegate.voting_info (B pre_state) source in + let* () = + Assert.is_none + ~loc:(make_loc __LOC__) + ~pp:(fun fmt _ -> Format.fprintf fmt "Voter already has a ballot.@.") + pre_voting_infos.current_ballot + in + let* current_proposal = Context.Vote.get_current_proposal (B pre_state) in + let* current_proposal = + Assert.get_some ~loc:(make_loc __LOC__) current_proposal + in + assert (Protocol_hash.equal proposal current_proposal) ; + (* Observations *) + let* post_voting_infos = Context.Delegate.voting_info (B post_state) source in + let* recorded_ballot = + Assert.get_some ~loc:(make_loc __LOC__) post_voting_infos.current_ballot + in + let* () = + Assert.equal + ~loc:(make_loc __LOC__) + Vote.equal_ballot + "Wrong ballot recorded" + Vote.pp_ballot + ballot + recorded_ballot + in + let* ballots_pre = Context.Vote.get_ballots (B pre_state) in + let* source_power = + Assert.get_some ~loc:(make_loc __LOC__) pre_voting_infos.voting_power + in + let expected_ballots_post = + match ballot with + | Yay -> {ballots_pre with yay = Int64.add ballots_pre.yay source_power} + | Nay -> {ballots_pre with nay = Int64.add ballots_pre.nay source_power} + | Pass -> {ballots_pre with pass = Int64.add ballots_pre.pass source_power} + in + assert_ballots expected_ballots_post post_state (make_loc __LOC__) + +let test_valid_ballot () = + let open Lwt_result_syntax in + (* The chosen [blocks_per_cycle] is an arbitrary value that we will + not reach with the blocks baked in this test. *) + let* block, delegates = context_init ~blocks_per_cycle:10l 4 () in + let* proposer, voter1, voter2, voter3 = + match delegates with + | [a; b; c; d] -> return (a, b, c, d) + | _ -> failwith "%s@,[context_init n] should return [n] delegates" __LOC__ + in + let proposal = protos.(0) in + let* operation = Op.proposals (B block) proposer [proposal] in + let* block = Block.bake block ~operation in + let* b0 = bake_until_first_block_of_next_period block in + let* operation = Op.ballot (B b0) voter1 proposal Vote.Yay in + let* b1 = Block.bake b0 ~operation in + let* () = observe_ballot b0 b1 operation __LOC__ in + let* operation = Op.ballot (B b1) voter2 proposal Vote.Nay in + let* b2 = Block.bake b1 ~operation in + let* () = observe_ballot b1 b2 operation __LOC__ in + let* operation = Op.ballot (B b2) voter3 proposal Vote.Pass in + let* b3 = Block.bake b2 ~operation in + observe_ballot b2 b3 operation __LOC__ + +let tests = + [ + (* Scenarized tests *) + Tztest.tztest "voting successful_vote" `Quick (test_successful_vote 137); + Tztest.tztest + "voting cooldown, not enough quorum" + `Quick + (test_not_enough_quorum_in_exploration 245); + Tztest.tztest + "voting promotion, not enough quorum" + `Quick + (test_not_enough_quorum_in_promotion 432); + Tztest.tztest + "voting proposal, with supermajority" + `Quick + (test_supermajority_in_proposal true); + Tztest.tztest + "voting proposal, without supermajority" + `Quick + (test_supermajority_in_proposal false); + Tztest.tztest + "voting proposal, with quorum" + `Quick + (test_quorum_in_proposal true); + Tztest.tztest + "voting proposal, without quorum" + `Quick + (test_quorum_in_proposal false); + Tztest.tztest + "voting cooldown, with supermajority" + `Quick + (test_supermajority_in_exploration true); + Tztest.tztest + "voting cooldown, without supermajority" + `Quick + (test_supermajority_in_exploration false); + Tztest.tztest + "voting proposal, no winning proposal" + `Quick + (test_no_winning_proposal 400); + Tztest.tztest + "voting quorum, quorum capped maximum" + `Quick + (test_quorum_capped_maximum 400); + Tztest.tztest + "voting quorum, quorum capped minimum" + `Quick + (test_quorum_capped_minimum 401); + Tztest.tztest + "voting power updated in each voting period" + `Quick + test_voting_power_updated_each_voting_period; + Tztest.tztest "voting period pretty print" `Quick test_voting_period_pp; + (* Validity tests on Proposals *) + Tztest.tztest + "Proposals missing signature" + `Quick + test_proposals_missing_signature; + Tztest.tztest + "Proposals invalid signature" + `Quick + test_proposals_invalid_signature; + Tztest.tztest + "Proposals wrong voting period index" + `Quick + test_proposals_wrong_voting_period_index; + Tztest.tztest + "Proposals wrong voting period kind" + `Quick + test_proposals_wrong_voting_period_kind; + Tztest.tztest + "Proposals source not in vote listings" + `Quick + test_proposals_source_not_in_vote_listings; + Tztest.tztest "Empty proposals" `Quick test_empty_proposals; + Tztest.tztest + "Proposals contain a duplicate proposal" + `Quick + test_proposals_contain_duplicate; + Tztest.tztest + "Too many proposals (over one operation)" + `Quick + test_too_many_proposals_in_one_operation; + Tztest.tztest + "Too many proposals (over two operations)" + `Quick + test_too_many_proposals; + Tztest.tztest + "A proposal had already been proposed" + `Quick + test_already_proposed; + Tztest.tztest + "Conflict: too many proposals in current block/mempool" + `Quick + test_conflict_too_many_proposals; + Tztest.tztest + "Conflicting proposals in current block/mempool" + `Quick + test_conflicting_proposal; + Tztest.tztest "Valid Proposals operations" `Quick test_valid_proposals; + (* Validity tests on Ballot *) + Tztest.tztest + "Ballot missing signature" + `Quick + test_ballot_missing_signature; + Tztest.tztest + "Ballot invalid signature" + `Quick + test_ballot_invalid_signature; + Tztest.tztest + "Ballot wrong voting period index" + `Quick + test_ballot_wrong_voting_period_index; + Tztest.tztest + "Ballot wrong voting period kind" + `Quick + test_ballot_wrong_voting_period_kind; + Tztest.tztest + "Ballot for wrong proposal" + `Quick + test_ballot_for_wrong_proposal; + Tztest.tztest + "Delegate has already submitted a ballot" + `Quick + test_already_submitted_a_ballot; + Tztest.tztest + "Ballot source not in vote listings" + `Quick + test_ballot_source_not_in_vote_listings; + Tztest.tztest + "Conflicting ballot in current block/mempool" + `Quick + test_conflicting_ballot; + Tztest.tztest "Valid Ballot operations" `Quick test_valid_ballot; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("voting", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_zk_rollup.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_zk_rollup.ml new file mode 100644 index 000000000000..4808b4444910 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/test_zk_rollup.ml @@ -0,0 +1,1293 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Rollup layer 1 logic + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/operations/main.exe \ + -- --file test_zk_rollup.ml + Subject: Test zk rollup +*) + +open Protocol +open Alpha_context + +exception Zk_rollup_test_error of string + +(* Number of operations in each private batch *) +let batch_size = 10 + +module Operator = Dummy_zk_rollup.Operator (struct + let batch_size = batch_size +end) + +(* Operation with payload = 1 *) +let true_op l1_dst rollup_id = + Zk_rollup.Operation. + { + op_code = 0; + price = Operator.Internal_for_tests.true_op.price; + l1_dst; + rollup_id; + payload = [|Bls12_381.Fr.one|]; + } + +let of_plonk_smap s = Zk_rollup.Account.SMap.of_seq @@ Kzg.SMap.to_seq s + +(* Operation with payload = 0 *) +let false_op l1_dst rollup_id = + {(true_op l1_dst rollup_id) with payload = [|Bls12_381.Fr.zero|]} + +(** [check_proto_error_f f t] checks that the first error of [t] + satisfies the boolean function [f]. *) +let check_proto_error_f f t = + let open Lwt_result_syntax in + match t with + | Environment.Ecoproto_error e :: _ when f e -> + Assert.test_error_encodings e ; + return_unit + | _ -> failwith "Unexpected error: %a" Error_monad.pp_print_trace t + +(** [check_proto_error e t] checks that the first error of [t] + equals [e]. *) +let check_proto_error e t = check_proto_error_f (( = ) e) t + +(* Check that originating a ZKRU fails when the feature flag is disabled. *) +let test_disable_feature_flag () = + let open Lwt_result_syntax in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let* b, contract = + Context.init_with_constants1 + { + Context.default_test_constants with + zk_rollup = + {Context.default_test_constants.zk_rollup with enable = false}; + } + in + let* i = Incremental.begin_construction b in + let* op, _zk_rollup = + Op.zk_rollup_origination + (I i) + contract + ~public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_failure: + (check_proto_error Validate_errors.Manager.Zk_rollup_feature_disabled) + i + op + in + return_unit + +(** [context_init n] initializes a context for testing in which the + [zk_rollup_enable] constant is set to true. It returns the created + context and [n] contracts. *) +let context_init = + Context.init_with_constants_n + { + Context.default_test_constants with + zk_rollup = {Context.default_test_constants.zk_rollup with enable = true}; + consensus_threshold = 0; + } + +(* Check that the expected origination fees are paid. *) +let test_origination_fees () = + let open Lwt_result_syntax in + let* ctxt, contracts = context_init 1 in + let* constants = Context.get_constants (B ctxt) in + let contract = Stdlib.List.hd contracts in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let expected_size = + let origination_size = constants.parametric.zk_rollup.origination_size in + let init_account = + Zk_rollup.Account. + { + static = + { + public_parameters; + state_length = 1; + circuits_info = of_plonk_smap Operator.circuits; + nb_ops = 1; + }; + dynamic = + { + state = Operator.init_state; + paid_l2_operations_storage_space = Z.of_int origination_size; + used_l2_operations_storage_space = Z.zero; + }; + } + in + let init_pl = Zk_rollup.(Empty {next_index = 0L}) in + origination_size + Zk_rollup.Address.size + + Data_encoding.Binary.length Zk_rollup.Account.encoding init_account + + Data_encoding.Binary.length Zk_rollup.pending_list_encoding init_pl + in + let expected_fees = + Test_tez.(constants.parametric.cost_per_byte *! Int64.of_int expected_size) + in + let* operation, _rollup = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* balance_before = Context.Contract.balance (B ctxt) contract in + let* i = Incremental.begin_construction ctxt in + let* i = Incremental.add_operation i operation in + Assert.balance_was_debited + ~loc:__LOC__ + (I i) + contract + balance_before + expected_fees + +let test_origination_negative_nb_ops () = + let open Lwt_result_syntax in + let* ctxt, contracts = context_init 1 in + let contract = Stdlib.List.hd contracts in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let* operation, _rollup = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:(-1) + in + let* i = Incremental.begin_construction ctxt in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup_apply.Zk_rollup_negative_nb_ops) + i + operation + in + return_unit + +(** Initializes the context and originates a ZKRU. *) +let init_and_originate n = + let open Lwt_result_syntax in + let* ctxt, contracts = context_init n in + let contract = Stdlib.List.hd contracts in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let* operation, rollup = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* b = Block.bake ~operation ctxt in + return (b, contracts, rollup) + +let no_ticket op = (op, None) + +(* Checks that originating two ZK rollups leads to different + rollup addresses. *) +let test_originate_two_rollups () = + let open Lwt_result_syntax in + let* ctxt, contracts, zk_rollup1 = init_and_originate 1 in + let contract = Stdlib.List.hd contracts in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let* operation, zk_rollup2 = + Op.zk_rollup_origination + (B ctxt) + contract + ~public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* (_b : Block.t) = Block.bake ~operation ctxt in + assert (zk_rollup1 <> zk_rollup2) ; + return_unit + +(* Initializes the context and originates a ZKRU with [n_pending] + operations. *) +let init_with_pending ?(n_pending = 1) n = + let open Lwt_result_syntax in + let* ctxt, contracts, zk_rollup = init_and_originate n in + let contract = Stdlib.List.hd contracts in + let pkh = match contract with Implicit pkh -> pkh | _ -> assert false in + let* operation = + Op.zk_rollup_publish + (B ctxt) + contract + ~zk_rollup + ~ops: + (Stdlib.List.init n_pending (fun i -> + no_ticket + @@ + if i mod 2 = 0 then false_op pkh zk_rollup + else true_op pkh zk_rollup)) + in + let* b = Block.bake ~operation ctxt in + return (b, contracts, zk_rollup, pkh) + +(* Test for an invalid append: + The operation being appended has an invalid op code. +*) +let test_append_out_of_range_op_code () = + let open Lwt_result_syntax in + let* ctxt, contracts, zk_rollup = init_and_originate 1 in + let contract = Stdlib.List.hd contracts in + let pkh = match contract with Implicit pkh -> pkh | _ -> assert false in + let l2_op = false_op pkh zk_rollup in + let* i = Incremental.begin_construction ctxt in + let* operation = + Op.zk_rollup_publish + (I i) + contract + ~zk_rollup + ~ops:[no_ticket {l2_op with op_code = 1}] + in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error (Zk_rollup_storage.Zk_rollup_invalid_op_code 1)) + i + operation + in + return_unit + +(* Test for an invalid append: + The operation being appended through an external op has positive price. +*) +let test_append_external_deposit () = + let open Lwt_result_syntax in + let* ctxt, contracts, zk_rollup = init_and_originate 1 in + let contract = Stdlib.List.hd contracts in + let pkh = match contract with Implicit pkh -> pkh | _ -> assert false in + let l2_op = false_op pkh zk_rollup in + let* i = Incremental.begin_construction ctxt in + let* operation = + Op.zk_rollup_publish + (I i) + contract + ~zk_rollup + ~ops: + [no_ticket {l2_op with price = {l2_op.price with amount = Z.of_int 10}}] + in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Deposit_as_external) + i + operation + in + return_unit + +(* ------------------------- TESTS WITH TICKETS ------------------------- *) + +(** [make_ticket_key ty contents ticketer zk_rollup] computes the ticket hash + of the ticket containing [contents] of type [ty], crafted by [ticketer] and + owned by [zk_rollup]. *) +let make_ticket_key ctxt ~ty ~contents ~ticketer zk_rollup = + let open Lwt_result_wrap_syntax in + let* incr = + match ctxt with + | Context.B block -> Incremental.begin_construction block + | Context.I incr -> return incr + in + let ctxt = Incremental.alpha_ctxt incr in + let*?@ Ex_comparable_ty contents_type, ctxt = + Script_ir_translator.parse_comparable_ty ctxt ty + in + let*@ contents, ctxt = + Script_ir_translator.parse_comparable_data ctxt contents_type contents + in + let+@ ticket_key, _ = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Zk_rollup zk_rollup) + (Ticket_token.Ex_token {ticketer; contents_type; contents}) + in + ticket_key + +module Make_ticket (T : sig + val ty_str : string + + type contents + + type contents_type + + val contents_type : contents_type Script_typed_ir.comparable_ty + + val contents_to_micheline : contents -> contents_type + + val contents_to_string : contents -> string +end) (C : sig + val contents : T.contents +end) = +struct + include T + include C + + let ty = Expr.from_string ty_str + + let ex_token ~ticketer = + Ticket_token.Ex_token + {ticketer; contents_type; contents = contents_to_micheline contents} + + let contents_string = contents_to_string contents + + let contents_expr = Expr.from_string contents_string + + let ticket_hash ctxt ~ticketer ~zk_rollup = + make_ticket_key + ctxt + ~ty:(Tezos_micheline.Micheline.root ty) + ~contents:(Tezos_micheline.Micheline.root contents_expr) + ~ticketer + zk_rollup + + let zkru_ticket ~ticketer : Zk_rollup.Ticket.t = + Zk_rollup.Ticket.{contents = contents_expr; ty; ticketer} + + let init_deposit_contract amount block account = + let script = + Format.asprintf + {| parameter (pair address bytes); + storage unit; + code { + # cast the address to contract type + CAR; + UNPAIR; + CONTRACT %%deposit (pair (ticket %s) bytes); + ASSERT_SOME; + SWAP; + PUSH mutez 0; + SWAP; + # create a ticket + PUSH nat %a; + PUSH %s %s; + TICKET; + ASSERT_SOME; + PAIR ; + TRANSFER_TOKENS; + PUSH unit Unit; + NIL operation; + DIG 2 ; + CONS; + PAIR } |} + ty_str + Z.pp_print + amount + ty_str + contents_string + in + Contract_helpers.originate_contract_from_string + ~baker:(Context.Contract.pkh account) + ~source_contract:account + ~script + ~storage:"Unit" + block + + let deposit_op ~block ~zk_rollup ~(zk_op : Zk_rollup.Operation.t) ~account + ~deposit_contract = + let zk_op_literal = + let bytes = + Data_encoding.Binary.to_bytes_exn Zk_rollup.Operation.encoding zk_op + in + let (`Hex hex) = Hex.of_bytes bytes in + "0x" ^ String.uppercase_ascii hex + in + Op.transaction + (B block) + ~entrypoint:Entrypoint.default + ~parameters: + (Script.lazy_expr @@ Expr.from_string + @@ Printf.sprintf + {| Pair %S %s |} + (Zk_rollup.Address.to_b58check zk_rollup) + zk_op_literal) + ~fee:Tez.one + account + deposit_contract + (Tez.of_mutez_exn 0L) + + (** Return an operation to originate a contract that will deposit [amount] + tickets with l2 operation [op] on [zk_rollup] *) + let init_deposit ~block ~amount ~zk_op ~zk_rollup ~account = + let open Lwt_result_syntax in + let* deposit_contract, _script, block = + init_deposit_contract amount block account + in + let+ op = deposit_op ~block ~zk_rollup ~zk_op ~account ~deposit_contract in + (block, op, deposit_contract) +end + +module Nat_ticket = Make_ticket (struct + let ty_str = "nat" + + type contents = int + + type contents_type = Script_int.n Script_int.num + + let contents_type = Script_typed_ir.nat_t + + let contents_to_string = string_of_int + + let contents_to_micheline c = + WithExceptions.Option.get ~loc:__LOC__ @@ Script_int.(of_int c |> is_nat) +end) + +module String_ticket = Make_ticket (struct + let ty_str = "string" + + type contents = string + + type contents_type = Script_string.t + + let contents_type = Script_typed_ir.string_t + + let contents_to_string s = "\"" ^ s ^ "\"" + + let contents_to_micheline c = + WithExceptions.Result.get_ok ~loc:__LOC__ Script_string.(of_string c) +end) + +let test_append_errors () = + let open Lwt_result_syntax in + let open Zk_rollup.Operation in + (* Create two accounts and 1 zk rollup *) + let* block, contracts, zk_rollup = init_and_originate 2 in + let contract0 = Stdlib.List.nth contracts 0 in + let contract1 = Stdlib.List.nth contracts 1 in + (* Create and originate the deposit contract *) + let module Nat_ticket = Nat_ticket (struct + let contents = 1 + end) in + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + (* Preparing operation and ticket for tests *) + let op = + let pkh = match contract0 with Implicit pkh -> pkh | _ -> assert false in + false_op pkh zk_rollup + in + let* ticket_hash = + Nat_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let ticket = Nat_ticket.zkru_ticket ~ticketer:contract0 in + (* Start generating block *) + let* i = Incremental.begin_construction block in + (* Send ticket but price = 0 *) + let* operation = + let price = {id = ticket_hash; amount = Z.zero} in + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup + ~ops:[({op with price}, Some ticket)] + in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + (* None ticket, price < 0 *) + let* operation = + let price = {id = ticket_hash; amount = Z.of_string "-10"} in + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup + ~ops:[no_ticket {op with price}] + in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + (* Some ticket, price < 0, op.price ≠ hash(ticket, zkru) *) + let* operation = + let price = + { + id = Ticket_hash.of_bytes_exn (Bytes.create 32); + amount = Z.of_string "-10"; + } + in + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup + ~ops:[({op with price}, Some ticket)] + in + let* (_i : Incremental.t) = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_ticket) + i + operation + in + return_unit + +let assert_ticket_balance ~loc incr token owner expected = + let open Lwt_result_wrap_syntax in + let ctxt = Incremental.alpha_ctxt incr in + let*@ key_hash, ctxt = Ticket_balance_key.of_ex_token ctxt ~owner token in + let*@ balance, _ = Ticket_balance.get_balance ctxt key_hash in + match (balance, expected) with + | Some b, Some e -> Assert.equal_int ~loc (Z.to_int b) e + | Some b, None -> + failwith "%s: Expected no balance but got some %d" loc (Z.to_int b) + | None, Some b -> failwith "%s: Expected balance %d but got none" loc b + | None, None -> return_unit + +let test_invalid_deposit () = + let open Lwt_result_syntax in + (* Create 2 accounts and one zk rollups *) + let* block, contracts, zk_rollup = init_and_originate 5 in + let contract0 = Stdlib.List.nth contracts 0 in + let contract1 = Stdlib.List.nth contracts 1 in + let contract2 = Stdlib.List.nth contracts 2 in + let contract3 = Stdlib.List.nth contracts 3 in + let contract4 = Stdlib.List.nth contracts 4 in + (* Create and originate the deposit contract *) + let module Nat_ticket = Nat_ticket (struct + let contents = 1 + end) in + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + let token = Nat_ticket.ex_token ~ticketer:deposit_contract in + (* Generate ticket created by deposit contract and owned by rollup *) + let* ticket_hash = + Nat_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let pkh = match contract0 with Implicit pkh -> pkh | _ -> assert false in + (* ----- Start generating block *) + let* i = Incremental.begin_construction block in + (* check rollup exists with none of these particular tokens *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- op.price = 0 *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 0}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract0 + ~deposit_contract + in + let* i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- hash(ticket, zkru) <> op.price *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = + {id = Ticket_hash.of_bytes_exn (Bytes.create 32); amount = Z.of_int 10}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract1 + ~deposit_contract + in + let* i = + Incremental.add_operation + i + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_ticket) + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- op.price <> ticket amount *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 12}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract2 + ~deposit_contract + in + let* i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_deposit_amount) + i + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- ticket amount = 0 *) + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 0) block contract0 + in + (* Create append/deposit operation with ticket *) + let zk_op = + {(false_op pkh zk_rollup) with price = {id = ticket_hash; amount = Z.zero}} + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract3 + ~deposit_contract + in + let* i = Incremental.begin_construction block in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + let* i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error_f (function + | Script_interpreter.Runtime_contract_error _ -> true + | _ -> false)) + i + operation + in + + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- ticket size > Constants.tx_rollup_max_ticket_payload_size *) + (* Contents size is such that, together with the ticketer address, + they exceed the maximum size of an operation *) + let contents_size = 15_000 in + let module String_ticket = String_ticket (struct + let contents = String.make contents_size 'a' + end) in + let* deposit_contract, _script, block = + String_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + let* ticket_hash = + String_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let token = String_ticket.ex_token ~ticketer:deposit_contract in + (* Create append/deposit operation with ticket *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 10}; + } + in + let* operation = + String_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract4 + ~deposit_contract + in + let* i = Incremental.begin_construction block in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + let* limit = + let* constants = Context.get_constants (I i) in + constants.parametric.zk_rollup.max_ticket_payload_size |> return + in + let* (_i : Incremental.t) = + let payload_size = Saturation_repr.safe_int (contents_size + 216) in + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error + (Zk_rollup.Errors.Ticket_payload_size_limit_exceeded + {payload_size; limit})) + i + operation + in + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + return_unit + +(* Test for a valid update: + - 1 private batch of 10 "true" operations + - 1 public "false" operation + On a ZKRU with the initial state and a pending list with + 1 operation ("false"). +*) +let test_update () = + let open Lwt_result_syntax in + let* b, contracts, zk_rollup, pkh = init_with_pending 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let n_batches = 2 in + let _, update = + Operator.( + craft_update + init_state + ~zk_rollup + ~private_ops: + (Stdlib.List.init n_batches (fun batch -> + Stdlib.List.init batch_size + @@ Fun.const + @@ (if batch mod 2 = 0 then true_op else false_op) pkh zk_rollup)) + [false_op pkh zk_rollup]) + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = Incremental.add_operation i operation in + return_unit + +(* Test for an invalid update: + - 1 public "true" operation + On a ZKRU with the initial state and a pending list with + 1 operation ("false"). + The public operation proved is different from the one in the pending list. +*) +let test_update_false_proof () = + let open Lwt_result_syntax in + let* b, contracts, zk_rollup, pkh = init_with_pending 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + (* Testing with proof on incorrect statement *) + let _, update = + Operator.(craft_update init_state ~zk_rollup [true_op pkh zk_rollup]) + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + i + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_verification) + operation + in + (* Testing with proof with incorrect private inputs *) + let update = + let _, Zk_rollup.Update.{pending_pis; private_pis; fee_pi; proof} = + Operator.(craft_update init_state ~zk_rollup [true_op pkh zk_rollup]) + in + let private_pis = List.rev private_pis in + Zk_rollup.Update.{pending_pis; private_pis; fee_pi; proof} + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + i + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_verification) + operation + in + return_unit + +(* Test for an invalid update: + A set of inputs for a public circuit is included in the list of + inputs for private batches. +*) +let test_update_public_in_private () = + let open Lwt_result_syntax in + let* b, contracts, zk_rollup, pkh = init_with_pending 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.(craft_update init_state ~zk_rollup [true_op pkh zk_rollup]) + in + let update = + (* Circuit ID and inputs for a public circuit, which will be added to the + [private_pis] list *) + let name, op_pi = Stdlib.List.hd update.pending_pis in + { + update with + private_pis = + (name, {new_state = op_pi.new_state; fees = op_pi.fee}) + :: update.private_pis; + } + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + i + ~expect_apply_failure:(check_proto_error Zk_rollup.Errors.Invalid_circuit) + operation + in + return_unit + +(* Test for an invalid update: + Two ZKRUs are originated: [zk_rollup1] and [zk_rollup2]. + An L2 [op] for [zk_rollup2] is appended to [zk_rollup1]'s pending list. + This operation must be discarded, but a malicious validator tries to process + it by making a proof for an update in which [op]'s [rollup_id] is changed + from [zk_rollup2] to [zk_rollup1]. The verification must fail, because + the Protocol uses the actual [op] from the pending list as input. +*) +let test_update_for_another_rollup () = + let open Lwt_result_syntax in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let* b, contracts, zk_rollup1, pkh = init_with_pending 3 in + let contract0 = Stdlib.List.hd contracts in + let contract1 = Stdlib.List.nth contracts 1 in + let contract2 = Stdlib.List.nth contracts 2 in + let* i = Incremental.begin_construction b in + (* Originate [zk_rollup2] *) + let* operation, zk_rollup2 = + Op.zk_rollup_origination + (I i) + contract0 + ~public_parameters + ~circuits_info:(of_plonk_smap Operator.circuits) + ~init_state:Operator.init_state + ~nb_ops:1 + in + let* i = Incremental.add_operation i operation in + (* Append to [zk_rollup1] an op for [zk_rollup2] *) + let* operation = + Op.zk_rollup_publish + (I i) + contract1 + ~zk_rollup:zk_rollup1 + ~ops:[no_ticket @@ true_op pkh zk_rollup2] + in + let* i = Incremental.add_operation i operation in + (* Craft the update, changing the "true" op to have zk_rollup1 as + [rollup_id] *) + let _, update = + Operator.( + craft_update + init_state + ~zk_rollup:zk_rollup1 + [false_op pkh zk_rollup1; true_op pkh zk_rollup1]) + in + let* operation = + Op.zk_rollup_update (I i) contract2 ~zk_rollup:zk_rollup1 ~update + in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Invalid_verification) + i + operation + in + return_unit + +(* Test for an invalid update: + The update sent by the prover processes more public operations than + those in the pending list. +*) +let test_update_more_public_than_pending () = + let open Lwt_result_syntax in + (* test with number of pending operations < min_pending_to_process. *) + let* b, contracts, zk_rollup, pkh = init_with_pending 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.( + craft_update + init_state + ~zk_rollup + [false_op pkh zk_rollup; true_op pkh zk_rollup]) + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup_storage.Zk_rollup_pending_list_too_short) + i + operation + in + (* test with number of pending operations >= min_pending_to_process. *) + let* constants = Context.get_constants (I i) in + let min_pending_to_process = + constants.parametric.zk_rollup.min_pending_to_process + in + let* b, contracts, zk_rollup, pkh = + init_with_pending ~n_pending:min_pending_to_process 1 + in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.( + craft_update + init_state + ~zk_rollup + (Stdlib.List.init (min_pending_to_process + 1) (fun i -> + if i mod 2 = 0 then false_op pkh zk_rollup + else true_op pkh zk_rollup))) + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup_storage.Zk_rollup_pending_list_too_short) + i + operation + in + return_unit + +(* Test for an invalid update: + The update sent by the prover contains a set of circuit inputs in which + the [new_state] is larger than the ZKRU's [state_length]. +*) +let test_update_inconsistent_state () = + let open Lwt_result_syntax in + let* b, contracts, zk_rollup, pkh = init_with_pending 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.(craft_update init_state ~zk_rollup [false_op pkh zk_rollup]) + in + let open Zk_rollup.Update in + let update = + { + update with + pending_pis = + List.map + (fun (s, (op_pi : op_pi)) -> + ( s, + { + op_pi with + new_state = Array.append op_pi.new_state op_pi.new_state; + } )) + update.pending_pis; + } + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + ~expect_apply_failure: + (check_proto_error Zk_rollup.Errors.Inconsistent_state_update) + i + operation + in + return_unit + +(* Test for an invalid update: + The update sent by the prover processes fewer pending operations (p.o.) than + allowed (the exact number of p.o. or at least min_pending_to_process). + The pending list has a length of 2, while only 1 is processed. +*) +let test_update_not_enough_pending () = + let open Lwt_result_syntax in + let* b, contracts, zk_rollup, pkh = init_with_pending ~n_pending:2 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.(craft_update init_state ~zk_rollup [false_op pkh zk_rollup]) + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = + Incremental.add_operation + ~expect_apply_failure:(check_proto_error Zk_rollup.Errors.Pending_bound) + i + operation + in + return_unit + +(* Test for a valid update: + The update sent by the prover processes a prefix of the pending list, + of the minimum length allowed. +*) +let test_update_valid_prefix () = + let open Lwt_result_syntax in + (* Checking when pending list has more than min_pending_to_process *) + let min_pending_to_process = + Context.default_test_constants.zk_rollup.min_pending_to_process + in + let* b, contracts, zk_rollup, pkh = + init_with_pending ~n_pending:(min_pending_to_process + 1) 1 + in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.( + craft_update + init_state + ~zk_rollup + (Stdlib.List.init min_pending_to_process (fun i -> + if i mod 2 = 0 then false_op pkh zk_rollup + else true_op pkh zk_rollup))) + in + (* Checking when pending list has less than min_pending_to_process *) + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = Incremental.add_operation i operation in + let* b, contracts, zk_rollup, pkh = init_with_pending ~n_pending:2 1 in + let contract = Stdlib.List.hd contracts in + let* i = Incremental.begin_construction b in + let _, update = + Operator.( + craft_update + init_state + ~zk_rollup + [false_op pkh zk_rollup; true_op pkh zk_rollup]) + in + let* operation = Op.zk_rollup_update (I i) contract ~zk_rollup ~update in + let* _i = Incremental.add_operation i operation in + return_unit + +let test_valid_deposit_and_withdrawal () = + let open Lwt_result_syntax in + (* Create 2 accounts and one zk rollups *) + let* block, contracts, zk_rollup = init_and_originate 2 in + let contract0 = Stdlib.List.nth contracts 0 in + let contract1 = Stdlib.List.nth contracts 1 in + (* Create and originate the deposit contract *) + let module Nat_ticket = Nat_ticket (struct + let contents = 1 + end) in + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + let token = Nat_ticket.ex_token ~ticketer:deposit_contract in + (* Generate ticket created by deposit contract and owned by rollup *) + let* ticket_hash = + Nat_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let pkh = match contract0 with Implicit pkh -> pkh | _ -> assert false in + (* Create append/deposit operation with ticket *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 10}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract0 + ~deposit_contract + in + (* ----- Start generating block *) + let* i = Incremental.begin_construction block in + (* check rollup exists with none of these particular tokens *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- Add deposit operation to block*) + let* i = Incremental.add_operation i operation in + (* check *rollup* has 10 of these particular tokens (deposit has been processed) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) (Some 10) + in + (* check *contract* has no tokens (deposit has been processed) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Contract contract0) None + in + (* Create update operation to process the zk operation (which is a + "deposit-withdrawal" for dummy rollup) *) + let _, update = + Operator.(craft_update init_state ~zk_rollup ~private_ops:[] [zk_op]) + in + let* operation = Op.zk_rollup_update (I i) contract1 ~zk_rollup ~update in + (* ----- Add update operation to block) *) + let* i = Incremental.add_operation i operation in + (* check *rollup* has no tokens (deposit was withdrawn) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* check *contract* has 10 of these particular tokens (deposit was withdrawn) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Contract contract0) (Some 10) + in + return_unit + +let test_valid_deposit_and_external_withdrawal () = + let open Lwt_result_syntax in + (* Create 2 accounts and one zk rollups *) + let* block, contracts, zk_rollup = init_and_originate 4 in + let contract0 = Stdlib.List.nth contracts 0 in + let contract1 = Stdlib.List.nth contracts 1 in + let contract2 = Stdlib.List.nth contracts 2 in + let contract3 = Stdlib.List.nth contracts 3 in + (* Create and originate the deposit contract *) + let module Nat_ticket = Nat_ticket (struct + let contents = 1 + end) in + let* deposit_contract, _script, block = + Nat_ticket.init_deposit_contract (Z.of_int 10) block contract0 + in + let token = Nat_ticket.ex_token ~ticketer:deposit_contract in + (* Generate ticket created by deposit contract and owned by rollup *) + let* ticket_hash = + Nat_ticket.ticket_hash (B block) ~ticketer:deposit_contract ~zk_rollup + in + let pkh = match contract0 with Implicit pkh -> pkh | _ -> assert false in + (* Create append/deposit operation with ticket *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int 10}; + } + in + let* operation = + Nat_ticket.deposit_op + ~block + ~zk_rollup + ~zk_op + ~account:contract0 + ~deposit_contract + in + (* ----- Start generating block *) + let* i = Incremental.begin_construction block in + (* check rollup exists with none of these particular tokens *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* ----- Add deposit operation to block*) + let* i = Incremental.add_operation i operation in + (* check *rollup* has 10 of these particular tokens (deposit has been processed) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) (Some 10) + in + (* check *contract* has no tokens (deposit has been processed) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Contract contract0) None + in + (* Create update operation to process the zk operation (which is a + "deposit" for dummy rollup) *) + let s, update = + Operator.( + craft_update + init_state + ~zk_rollup + ~private_ops:[] + ~exit_validities:[false] + [zk_op]) + in + let* operation = Op.zk_rollup_update (I i) contract1 ~zk_rollup ~update in + (* ----- Add update operation to block) *) + let* i = Incremental.add_operation i operation in + (* check *rollup* has 10 of these particular tokens (deposit has been processed) *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) (Some 10) + in + (* Create withdrawal operation with ticket *) + let zk_op = + { + (false_op pkh zk_rollup) with + price = {id = ticket_hash; amount = Z.of_int (-10)}; + } + in + let ticket = Nat_ticket.zkru_ticket ~ticketer:deposit_contract in + let* operation = + Op.zk_rollup_publish (I i) contract2 ~zk_rollup ~ops:[(zk_op, Some ticket)] + in + let* i = Incremental.add_operation i operation in + (* Create update to process the withdrawal *) + let _, update = + Operator.( + craft_update s ~zk_rollup ~private_ops:[] ~exit_validities:[true] [zk_op]) + in + let* operation = Op.zk_rollup_update (I i) contract3 ~zk_rollup ~update in + let* i = Incremental.add_operation i operation in + (* check *rollup* has no tokens *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Zk_rollup zk_rollup) None + in + (* check *contract* has 10 of these particular tokens *) + let* () = + assert_ticket_balance ~loc:__LOC__ i token (Contract contract0) (Some 10) + in + return_unit + +let tests = + [ + Tztest.tztest + "check feature flag is disabled" + `Quick + test_disable_feature_flag; + Tztest.tztest "origination fees" `Quick test_origination_fees; + Tztest.tztest "originate two rollups" `Quick test_originate_two_rollups; + Tztest.tztest + "origination negative nb_ops" + `Quick + test_origination_negative_nb_ops; + Tztest.tztest + "append with invalid op code" + `Quick + test_append_out_of_range_op_code; + Tztest.tztest "append external deposit" `Quick test_append_external_deposit; + Tztest.tztest "append check errors" `Quick test_append_errors; + Tztest.tztest "invalid deposit" `Quick test_invalid_deposit; + Tztest.tztest "update" `Quick test_update; + Tztest.tztest "update with false proof" `Quick test_update_false_proof; + Tztest.tztest + "update with invalid circuit" + `Quick + test_update_public_in_private; + Tztest.tztest + "update with op for another rollup" + `Quick + test_update_for_another_rollup; + Tztest.tztest + "update with more public operations than pending" + `Quick + test_update_more_public_than_pending; + Tztest.tztest + "update with inconsistent state" + `Quick + test_update_inconsistent_state; + Tztest.tztest + "update with not enough pending" + `Quick + test_update_not_enough_pending; + Tztest.tztest "update with valid prefix" `Quick test_update_valid_prefix; + Tztest.tztest "valid deposit" `Quick test_valid_deposit_and_withdrawal; + Tztest.tztest + "valid deposit and external withdrawal" + `Quick + test_valid_deposit_and_external_withdrawal; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("zk rollup", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_launch.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_launch.ml new file mode 100644 index 000000000000..9768881e1819 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_launch.ml @@ -0,0 +1,604 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Adaptive Issuance, launch vote + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_adaptive_issuance_launch.ml + Subject: Test the launch vote feature of Adaptive Issuance. +*) + +open Adaptive_issuance_helpers + +let assert_level ~loc (blk : Block.t) expected = + let current_level = blk.header.shell.level in + Assert.equal_int32 ~loc current_level expected + +let assert_is_not_yet_set_to_launch ~loc blk = + let open Lwt_result_syntax in + let* launch_cycle_opt = Context.get_adaptive_issuance_launch_cycle (B blk) in + Assert.is_none + ~loc + ~pp:(fun fmt cycle -> + Format.fprintf + fmt + "Activation cycle is set to %a but we expected it to be unset" + Protocol.Alpha_context.Cycle.pp + cycle) + launch_cycle_opt + +let assert_cycle_eq ~loc c1 c2 = + Assert.equal + ~loc + Protocol.Alpha_context.Cycle.( = ) + "cycle equality" + Protocol.Alpha_context.Cycle.pp + c1 + c2 + +let assert_current_cycle ~loc (blk : Block.t) expected = + let current_cycle = Block.current_cycle blk in + assert_cycle_eq ~loc current_cycle expected + +(** Assert that the staking balance is the expected one. *) +let assert_total_frozen_stake ~loc block expected = + let open Lwt_result_syntax in + let* actual = Context.get_total_frozen_stake (B block) in + Assert.equal_tez ~loc actual expected + +(* Assert that the current voting power of a delegate is the expected + one. The expectation is computed based on the expected self-staked, + delegated, and staked tez. The delegate's own liquid balance is + measured. *) +let assert_voting_power ~loc block delegate ~ai_enabled ~expected_staked + ~expected_delegated ~expected_ext_staked = + let open Lwt_result_syntax in + let* balance = Context.Contract.balance (B block) (Implicit delegate) in + let balance = Protocol.Alpha_context.Tez.to_mutez balance in + let expected_liquid = Int64.add balance expected_delegated in + let expected_frozen = Int64.add expected_staked expected_ext_staked in + let* constants = Context.get_constants (B block) in + let edge_of_staking_over_delegation = + Int64.of_int + constants.parametric.adaptive_issuance.edge_of_staking_over_delegation + in + let expected_voting_power = Int64.add expected_frozen expected_liquid in + let expected_baking_power = + if ai_enabled then + Int64.add + expected_frozen + (Int64.div expected_liquid edge_of_staking_over_delegation) + else expected_voting_power + in + let* actual_voting_power = + Context.get_current_voting_power (B block) delegate + in + let* () = Assert.equal_int64 ~loc actual_voting_power expected_voting_power in + let* actual_baking_power = + Context.get_current_baking_power (B block) delegate + in + Assert.equal_int64 ~loc actual_baking_power expected_baking_power + +(* Test that: + - the EMA of the adaptive issuance vote reaches the threshold after the + expected duration, + - the launch cycle is set as soon as the threshold is reached, + - the launch cycle is not reset before it is reached, + - once the launch cycle is reached, staking is allowed, + - staking increases total_frozen_stake. *) +let test_launch threshold expected_vote_duration () = + let open Lwt_result_wrap_syntax in + let assert_ema_above_threshold ~loc + (metadata : Protocol.Main.block_header_metadata) = + let ema = + Protocol.Alpha_context.Per_block_votes.Adaptive_issuance_launch_EMA + .to_int32 + metadata.adaptive_issuance_vote_ema + in + Assert.lt_int32 ~loc threshold ema + in + (* Initialize the state with a single delegate. *) + let constants = + let default_constants = Default_parameters.constants_test in + let default_constants = + { + default_constants with + dal = + { + default_constants.dal with + cryptobox_parameters = + { + default_constants.dal.cryptobox_parameters with + (* Computing the DAL committee takes a bit of time, around 1ms + for [number_of_shards] = 2048, and this adds up when baking + for a long time. As this issue is orthogonal to this test, we + simply pick a lower value. *) + number_of_shards = 32; + }; + }; + } + in + let adaptive_issuance = + { + default_constants.adaptive_issuance with + launch_ema_threshold = threshold; + activation_vote_enable = true; + autostaking_enable = false; + } + in + let cost_per_byte = Tez.zero in + let issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + } + in + let consensus_threshold = 0 in + { + default_constants with + consensus_threshold; + adaptive_issuance; + issuance_weights; + cost_per_byte; + } + in + let delay = constants.consensus_rights_delay in + let* block, delegate = Context.init_with_constants1 constants in + let delegate_pkh = Context.Contract.pkh delegate in + let* () = assert_is_not_yet_set_to_launch ~loc:__LOC__ block in + let* () = + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 200_000_000_000L) + in + + (* To test that adaptive issuance is active, we test that + staking, a feature only available after the activation, is + allowed. But by default, delegates reject stakers, they must + explicitely set a positive limit_of_staking_over_baking to allow + them. Setting this limit does not immediately take effect but can + be done before the activation. For these reasons, we set it at + the beginning. + + The baking_over_staking_edge indicates the portion of the rewards + sent to the delegate's liquid balance. It's expressed in + billionth, with 0 meaning that everything is frozen and one + billion meaning that everything is liquid. We send all rewards to + the liquid part to ease reasoning about the total frozen + stake. *) + let* block = + let* operation = + set_delegate_parameters + (B block) + delegate + ~parameters: + { + limit_of_staking_over_baking = Q.one; + edge_of_baking_over_staking = Q.one; + } + in + Block.bake ~operation ~adaptive_issuance_vote:Per_block_vote_on block + in + + (* Initialization of a delegator account which will attempt to + stake. *) + let wannabe_staker_account = Account.new_account () in + let wannabe_staker = + Protocol.Alpha_context.Contract.Implicit + Account.(wannabe_staker_account.pkh) + in + + (* To set up the wannabe staker, we need three operations: a + transfer from the delegate to initialize its balance, a + revelation of its public key, and a delegation toward the + delegate. For simplicity we put these operations in different + blocks. *) + let* block = + let* operation = + Op.transaction + (B block) + delegate + wannabe_staker + (Protocol.Alpha_context.Tez.of_mutez_exn 2_000_000_000_000L) + in + Block.bake ~operation ~adaptive_issuance_vote:Per_block_vote_on block + in + let* block = + let* operation = + Op.revelation + ~fee:Protocol.Alpha_context.Tez.zero + (B block) + wannabe_staker_account.pk + in + Block.bake ~operation ~adaptive_issuance_vote:Per_block_vote_on block + in + let* block = + let* operation = + Op.delegation + ~fee:Protocol.Alpha_context.Tez.zero + (B block) + wannabe_staker + (Some delegate_pkh) + in + Block.bake ~operation ~adaptive_issuance_vote:Per_block_vote_on block + in + (* Self-staking most of the remaining balance. *) + let* block = + let* operation = + stake + (B block) + delegate + (Protocol.Alpha_context.Tez.of_mutez_exn 1_800_000_000_000L) + in + Block.bake ~operation ~adaptive_issuance_vote:Per_block_vote_on block + in + + (* We are now ready to activate the feature through by baking many + more blocks voting in favor of the activation until the EMA + threshold is reached. *) + let* () = assert_is_not_yet_set_to_launch ~loc:__LOC__ block in + + let* block, _ = + Block.bake_while_with_metadata + ~adaptive_issuance_vote:Per_block_vote_on + (fun _block metadata -> + let ema = + Protocol.Alpha_context.Per_block_votes.Adaptive_issuance_launch_EMA + .to_int32 + metadata.adaptive_issuance_vote_ema + in + let launch_cycle = metadata.adaptive_issuance_launch_cycle in + let cond = Compare.Int32.(ema < threshold) in + assert ( + if cond then Option.is_none launch_cycle + else Option.is_some launch_cycle) ; + cond) + block + in + (* At this point we are on the last block before the end of the vote. *) + let* () = + assert_level ~loc:__LOC__ block (Int32.pred expected_vote_duration) + in + let* () = assert_is_not_yet_set_to_launch ~loc:__LOC__ block in + (* We bake one more block to end the vote and set the feature to launch. *) + let* block, (metadata, _) = + Block.bake_n_with_metadata ~adaptive_issuance_vote:Per_block_vote_on 1 block + in + let* () = assert_ema_above_threshold ~loc:__LOC__ metadata in + let* () = assert_level ~loc:__LOC__ block expected_vote_duration in + (* At this point the feature is not launched yet, it is simply + planned to be launched. *) + (* We check that the feature is not yet active by attempting a + stake operation. *) + let* () = + let* operation = + stake + (B block) + wannabe_staker + (Protocol.Alpha_context.Tez.of_mutez_exn 10L) + in + let* i = Incremental.begin_construction block in + let*! i = Incremental.add_operation i operation in + Assert.proto_error_with_info + ~loc:__LOC__ + i + "Staking for a delegator while external staking is disabled" + in + let* () = + assert_voting_power + ~loc:__LOC__ + block + delegate_pkh + ~ai_enabled:false + ~expected_staked:2_000_000_000_000L + ~expected_delegated:2_000_000_000_000L + ~expected_ext_staked:0L + in + + let* launch_cycle = get_launch_cycle ~loc:__LOC__ block in + let* () = + (* Check that the block metadata information about the launch cycle + is consistent with the RPC. *) + let* cycle = + Assert.get_some ~loc:__LOC__ metadata.adaptive_issuance_launch_cycle + in + assert_cycle_eq ~loc:__LOC__ launch_cycle cycle + in + (* Bake until the activation. *) + let* block = Block.bake_until_cycle launch_cycle block in + let* block, (metadata, _) = Block.bake_n_with_metadata 1 block in + let* () = assert_ema_above_threshold ~loc:__LOC__ metadata in + (* Check that keeping the EMA above the threshold did not postpone + the activation. *) + let* launch_cycle_bis = get_launch_cycle ~loc:__LOC__ block in + let* () = assert_cycle_eq ~loc:__LOC__ launch_cycle launch_cycle_bis in + (* Check that the current cycle is the one at which the launch is + planned to happen. *) + let* () = assert_current_cycle ~loc:__LOC__ block launch_cycle in + (* At this point, only the delegate has frozen any stake and its + frozen balance is about 2 million tez (it started with 4 million, + sent half to its delegate, and staked the rest). *) + let* () = + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 2_000_000_000_000L) + in + let* () = + assert_voting_power + ~loc:__LOC__ + block + delegate_pkh + ~ai_enabled:true + ~expected_staked:2_000_000_000_000L + ~expected_delegated:2_000_000_000_000L + ~expected_ext_staked:0L + in + + (* Test that the wannabe staker is now allowed to stake almost all + its balance. It cannot totally stake it however because this is + considered by the protocol as an attempt to empty the account, and + emptying delegated accounts is forbidden. *) + let* balance = Context.Contract.balance (B block) wannabe_staker in + let*?@ balance_to_stake = Protocol.Alpha_context.Tez.(balance -? one) in + let* operation = stake (B block) wannabe_staker balance_to_stake in + let* block = Block.bake ~operation block in + (* The staking operation leads to an increase of the + total_frozen_stake but only consensus_rights_delay after the + operation. *) + let start_cycle = Block.current_cycle block in + let* block = + Block.bake_while + ~invariant:(fun block -> + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 2_000_000_000_000L)) + (fun block -> + let current_cycle = Block.current_cycle block in + Protocol.Alpha_context.Cycle.(current_cycle <= add start_cycle delay)) + block + in + let* block = Block.bake block in + let* () = + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 3_999_999_000_000L) + in + let* () = + assert_voting_power + ~loc:__LOC__ + block + delegate_pkh + ~ai_enabled:true + ~expected_staked:2_000_000_000_000L + ~expected_delegated:1_000_000L + ~expected_ext_staked:1_999_999_000_000L + in + return_unit + +(* Test that, with the feature flag unset: + - the EMA of the adaptive issuance vote reaches the threshold after the + expected duration, + - the feature does not activate. *) +let test_does_not_launch_without_feature_flag threshold vote_duration () = + let open Lwt_result_wrap_syntax in + let assert_ema_above_threshold ~loc + (metadata : Protocol.Main.block_header_metadata) = + let ema = + Protocol.Alpha_context.Per_block_votes.Adaptive_issuance_launch_EMA + .to_int32 + metadata.adaptive_issuance_vote_ema + in + Assert.lt_int32 ~loc threshold ema + in + (* Initialize the state with a single delegate. *) + let constants = + let default_constants = Default_parameters.constants_test in + let default_constants = + { + default_constants with + dal = + { + default_constants.dal with + cryptobox_parameters = + { + default_constants.dal.cryptobox_parameters with + (* same reasoning as for [test_launch] *) + number_of_shards = 32; + }; + }; + } + in + let adaptive_issuance = + { + default_constants.adaptive_issuance with + launch_ema_threshold = threshold; + activation_vote_enable = false; + } + in + let consensus_threshold = 0 in + {default_constants with consensus_threshold; adaptive_issuance} + in + let* block, _delegate = Context.init_with_constants1 constants in + let* () = assert_is_not_yet_set_to_launch ~loc:__LOC__ block in + let* () = + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 200_000_000_000L) + in + (* Bake many more blocks voting in favor of the activation until the + EMA threshold is reached. *) + let* () = assert_is_not_yet_set_to_launch ~loc:__LOC__ block in + let* block, _ = + Block.bake_while_with_metadata + ~adaptive_issuance_vote:Per_block_vote_on + (fun _block metadata -> + let ema = + Protocol.Alpha_context.Per_block_votes.Adaptive_issuance_launch_EMA + .to_int32 + metadata.adaptive_issuance_vote_ema + in + let launch_cycle = metadata.adaptive_issuance_launch_cycle in + let cond = Compare.Int32.(ema < threshold) in + assert (Option.is_none launch_cycle) ; + cond) + block + in + (* At this point we are on the last block before the end of the vote. *) + let* () = assert_level ~loc:__LOC__ block (Int32.pred vote_duration) in + let* () = assert_is_not_yet_set_to_launch ~loc:__LOC__ block in + (* We bake one more block, this would set the feature to launch if + the vote was taken into account. *) + let* block, (metadata, _) = + Block.bake_n_with_metadata ~adaptive_issuance_vote:Per_block_vote_on 1 block + in + let* () = assert_ema_above_threshold ~loc:__LOC__ metadata in + let* () = assert_level ~loc:__LOC__ block vote_duration in + let* launch_cycle_opt = + Context.get_adaptive_issuance_launch_cycle (B block) + in + let* () = Assert.is_none ~loc:__LOC__ ~pp:Cycle.pp launch_cycle_opt in + let* () = + Assert.is_none + ~loc:__LOC__ + ~pp:Cycle.pp + metadata.adaptive_issuance_launch_cycle + in + return_unit + +(* Test that with force_activation feature flag set, the feature activates + without waiting for the activation vote *) +let test_launch_without_vote () = + let open Lwt_result_wrap_syntax in + (* Initialize the state with a single delegate. *) + let constants = + let default_constants = Default_parameters.constants_test in + let issuance_weights = + { + Default_parameters.constants_test.issuance_weights with + base_total_issued_per_minute = Tez.zero; + } + in + let adaptive_issuance = + {default_constants.adaptive_issuance with force_activation = true} + in + let consensus_threshold = 0 in + { + default_constants with + consensus_threshold; + issuance_weights; + adaptive_issuance; + } + in + let* block, delegate = Context.init_with_constants1 constants in + let delegate_pkh = Context.Contract.pkh delegate in + let* block = Block.bake block in + + (* AI should be activated and launch cycle is current cycle (0) *) + let* launch_cycle_opt = + Context.get_adaptive_issuance_launch_cycle (B block) + in + let* launch_cycle = Assert.get_some ~loc:__LOC__ launch_cycle_opt in + let* () = Assert.equal_int32 ~loc:__LOC__ (Cycle.to_int32 launch_cycle) 0l in + + let* () = + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 200_000_000_000L) + in + (* feature flag is set, AI should be active, let's use the stake function to check *) + let* operation = + stake + (B block) + delegate + (Protocol.Alpha_context.Tez.of_mutez_exn 180_000_000_000L) + in + let* block = Block.bake ~operation block in + (* Wait until total frozen stake is updated *) + let start_cycle = Block.current_cycle block in + let* block = + Block.bake_while + ~invariant:(fun block -> + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 200_000_000_000L)) + (fun block -> + let current_cycle = Block.current_cycle block in + Protocol.Alpha_context.Cycle.( + current_cycle <= add start_cycle constants.consensus_rights_delay)) + block + in + let* block = Block.bake block in + + let* () = + assert_total_frozen_stake + ~loc:__LOC__ + block + (Protocol.Alpha_context.Tez.of_mutez_exn 380_000_000_000L) + in + let* () = + assert_voting_power + ~loc:__LOC__ + block + delegate_pkh + ~ai_enabled:true + ~expected_staked:380_000_000_000L + ~expected_delegated:0L + ~expected_ext_staked:0L + in + return_unit + +let tests = + [ + Tztest.tztest + "Launch with force_activation feature flag set activates AI immediately" + `Quick + test_launch_without_vote; + Tztest.tztest + "the EMA reaches the vote threshold at the expected level and adaptive \ + issuance launches (very low threshold, vote enabled)" + `Quick + (test_launch + 1000000l (* This means that the threshold is set at 0.05% *) + 88l); + Tztest.tztest + "the EMA reaches the vote threshold at the expected level and adaptive \ + issuance does not launch (very low threshold, vote disabled)" + `Quick + (test_does_not_launch_without_feature_flag + 1000000l (* This means that the threshold is set at 0.05% *) + 88l); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("adaptive issuance launch", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml new file mode 100644 index 000000000000..067bb40656f8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml @@ -0,0 +1,2952 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Adaptive Issuance, launch vote + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_adaptive_issuance_roundtrip.ml + Subject: Test staking stability under Adaptive Issuance. +*) + +open Adaptive_issuance_helpers + +let fs = Format.asprintf + +(** Returns when the number of bootstrap accounts created by [Context.init_n n] is not equal to [n] *) +type error += Inconsistent_number_of_bootstrap_accounts + +(** For [assert_failure], when expected error does not match the actual error. *) +type error += Unexpected_error + +let default_param_wait, default_unstake_wait = + let constants = Default_parameters.constants_test in + let crd = constants.consensus_rights_delay in + let dpad = constants.delegate_parameters_activation_delay in + let msp = Protocol.Constants_repr.max_slashing_period in + (dpad, crd + msp) + +(** Contains the functions and constants relative to logging.*) +module Log_module = struct + let begin_end_color = Log.Color.(BG.bright_white ++ FG.black ++ bold) + + let time_color = Log.Color.FG.yellow + + let action_color = Log.Color.FG.green + + let event_color = Log.Color.FG.blue + + let warning_color = Log.Color.FG.red + + let low_debug_color = Log.Color.FG.gray + + let assert_block_color = Log.Color.(BG.blue ++ FG.gray) + + let tez_color = Log.Color.FG.bright_white + + let log_debug_balance account_name account_map : unit = + let balance, total_balance = + balance_and_total_balance_of_account account_name account_map + in + Log.debug + "Model balance of %s:\n%aTotal balance: %a\n" + account_name + balance_pp + balance + Tez.pp + total_balance + + let log_debug_rpc_balance name contract block : unit tzresult Lwt.t = + let open Lwt_result_syntax in + let* balance, total_balance = get_balance_from_context (B block) contract in + Log.debug + "RPC balance of %s:\n%aTotal balance: %a\n" + name + balance_pp + balance + Tez.pp + total_balance ; + return_unit + + let log_debug_balance_update account_name old_account_map new_account_map : + unit = + let old_balance, old_total_balance = + balance_and_total_balance_of_account account_name old_account_map + in + let new_balance, new_total_balance = + balance_and_total_balance_of_account account_name new_account_map + in + Log.debug + "Balance update of %s:\n%aTotal balance: %a -> %a\n" + account_name + balance_update_pp + (old_balance, new_balance) + Tez.pp + old_total_balance + Tez.pp + new_total_balance + + (* end module Log_module *) +end + +open Log_module + +(** Aliases for tez values *) +type tez_quantity = + | Half + | All + | All_but_one + | Nothing + | Max_tez + | Amount of Tez.t + +let tez_quantity_pp fmt value = + let s = + match value with + | Nothing -> "Zero" + | All -> "All" + | All_but_one -> "All but 1µꜩ" + | Half -> "Half" + | Max_tez -> "Maximum" + | Amount a -> Format.asprintf "%aꜩ" Tez.pp a + in + Format.fprintf fmt "%s" s + +(* [all] is the amount returned when [qty = All]. If [qty = Half], returns half of that. *) +let quantity_to_tez all qty = + match qty with + | Nothing -> Tez.zero + | All -> all + | All_but_one -> + if Tez.(equal all zero) then Tez.zero else Tez.(all -! one_mutez) + | Half -> Test_tez.(all /! 2L) + | Max_tez -> Tez.max_mutez + | Amount a -> a + +let default_params = + let Protocol.Staking_parameters_repr. + { + limit_of_staking_over_baking_millionth; + edge_of_baking_over_staking_billionth; + } = + Protocol.Staking_parameters_repr.default + in + { + limit_of_staking_over_baking = + Q.(Int32.to_int limit_of_staking_over_baking_millionth // 1_000_000); + edge_of_baking_over_staking = + Q.(Int32.to_int edge_of_baking_over_staking_billionth // 1_000_000_000); + } + +type double_signing_state = { + culprit : Signature.Public_key_hash.t; + kind : Protocol.Misbehaviour_repr.kind; + evidence : Context.t -> Protocol.Alpha_context.packed_operation; + denounced : bool; + level : Int32.t; +} + +(** Module for the [State.t] type of asserted information about the system during a test. *) +module State = struct + (** Type of the state *) + type t = { + account_map : account_map; + total_supply : Tez.t; + constants : Protocol.Alpha_context.Constants.Parametric.t; + param_requests : (string * staking_parameters * int) list; + activate_ai : bool; + baking_policy : Block.baker_policy option; + last_level_rewards : Protocol.Alpha_context.Raw_level.t; + snapshot_balances : (string * balance) list String.Map.t; + saved_rate : Q.t option; + burn_rewards : bool; + pending_operations : Protocol.Alpha_context.packed_operation list; + pending_slashes : + (Signature.Public_key_hash.t * Protocol.Denunciations_repr.item) list; + double_signings : double_signing_state list; + } + + (** Expected number of cycles before staking parameters get applied *) + let param_wait state = + state.constants.delegate_parameters_activation_delay + 1 + + (** Expected number of cycles before staking unstaked funds get unfrozen *) + let unstake_wait state = + let pc = state.constants.consensus_rights_delay in + let msp = Protocol.Constants_repr.max_slashing_period in + pc + msp + + (** From a name, returns the corresponding account *) + let find_account (account_name : string) (state : t) : account_state = + match String.Map.find account_name state.account_map with + | None -> raise Not_found + | Some r -> r + + let find_account_from_pkh (pkh : Signature.public_key_hash) (state : t) : + string * account_state = + String.Map.filter + (fun _ acc -> Signature.Public_key_hash.equal pkh acc.pkh) + state.account_map + |> String.Map.choose + |> function + | None -> raise Not_found + | Some (name, acc) -> (name, acc) + + let liquid_delegated ~name state = + let open Result_syntax in + String.Map.fold_e + (fun _delegator account acc -> + match account.delegate with + | Some delegate when not @@ String.equal delegate name -> return acc + | None -> return acc + | _ -> Tez.(acc +? account.liquid)) + state.account_map + Tez.zero + + (** Returns true iff account is a delegate *) + let is_self_delegate (account_name : string) (state : t) : bool = + let acc = find_account account_name state in + match acc.delegate with + | None -> false + | Some del_name -> String.equal del_name account_name + + let update_map ?(log_updates = []) ~(f : account_map -> account_map) + (state : t) : t = + let log_updates = List.sort_uniq String.compare log_updates in + let new_state = {state with account_map = f state.account_map} in + List.iter + (fun x -> + log_debug_balance_update x state.account_map new_state.account_map) + log_updates ; + new_state + + let apply_burn amount src_name (state : t) : t = + let f = apply_burn amount src_name in + let state = update_map ~log_updates:[src_name] ~f state in + {state with total_supply = Tez.(state.total_supply -! amount)} + + let apply_transfer amount src_name dst_name (state : t) : t = + let f = apply_transfer amount src_name dst_name in + update_map ~log_updates:[src_name; dst_name] ~f state + + let apply_stake amount current_cycle staker_name (state : t) : t = + let f = + apply_stake + amount + current_cycle + state.constants.consensus_rights_delay + staker_name + in + update_map ~log_updates:[staker_name] ~f state + + let apply_unstake cycle amount staker_name (state : t) : t = + let f = apply_unstake cycle amount staker_name in + update_map ~log_updates:[staker_name] ~f state + + let apply_finalize staker_name (state : t) : t = + let f = apply_finalize staker_name in + update_map ~log_updates:[staker_name] ~f state + + let apply_unslashable current_cycle account_name (state : t) : t = + let unstake_wait = unstake_wait state in + match Cycle.sub current_cycle unstake_wait with + | None -> state + | Some cycle -> + let f = apply_unslashable cycle account_name in + update_map ~log_updates:[account_name] ~f state + + let apply_unslashable_for_all current_cycle (state : t) : t = + let unstake_wait = unstake_wait state in + match Cycle.sub current_cycle unstake_wait with + | None -> state + | Some cycle -> + let f = apply_unslashable_for_all cycle in + (* no log *) + update_map ~f state + + let apply_rewards ~(baker : string) block (state : t) : t tzresult Lwt.t = + let open Lwt_result_syntax in + let {last_level_rewards; total_supply; constants = _; _} = state in + let*? current_level = Context.get_level (B block) in + let current_cycle = Block.current_cycle block in + (* We assume one block per minute *) + let* rewards_per_block = Context.get_issuance_per_minute (B block) in + if Tez.(rewards_per_block = zero) then return state + else + let delta_time = + Protocol.Alpha_context.Raw_level.diff current_level last_level_rewards + |> Int64.of_int32 + in + let {parameters = _; pkh; _} = find_account baker state in + let delta_rewards = Test_tez.(rewards_per_block *! delta_time) in + if delta_time = 1L then + Log.info ~color:tez_color "+%aꜩ" Tez.pp rewards_per_block + else assert false ; + let* to_liquid = + portion_of_rewards_to_liquid_for_cycle + ?policy:state.baking_policy + (B block) + current_cycle + pkh + delta_rewards + in + let to_frozen = Tez.(delta_rewards -! to_liquid) in + let state = update_map ~f:(add_liquid_rewards to_liquid baker) state in + let state = update_map ~f:(add_frozen_rewards to_frozen baker) state in + let* total_supply = Tez.(total_supply + delta_rewards) in + return {state with last_level_rewards = current_level; total_supply} + + (** [apply_staking_abstract_balance_updates] updates a state based on balance + updates (found in block application metadata). + It first collect all changes on pseudotokens, then apply them on + accounts. *) + let apply_staking_abstract_balance_updates balance_updates state = + let update_staking_delegator_numerator delta account_state = + let staking_delegator_numerator = + Z.add delta account_state.staking_delegator_numerator + in + {account_state with staking_delegator_numerator} + in + let update_staking_delegate_denominator delta account_state = + let staking_delegate_denominator = + Z.add delta account_state.staking_delegate_denominator + in + {account_state with staking_delegate_denominator} + in + let add_change pkh update ~f changes = + let delta_pt, delta_mul = + match + (update + : Protocol.Alpha_context.Staking_pseudotoken.t + Protocol.Alpha_context.Receipt.balance_update) + with + | Credited pt -> (pt, Z.one) + | Debited pt -> (pt, Z.minus_one) + in + let delta = + Z.mul delta_mul + @@ Protocol.Alpha_context.Staking_pseudotoken.Internal_for_tests.to_z + delta_pt + in + let f = f delta in + Signature.Public_key_hash.Map.update + pkh + (function + | None -> Some f + | Some existing_change -> + Some (fun account_state -> f (existing_change account_state))) + changes + in + let changes = + List.fold_left + (fun changes balance_update -> + let (Protocol.Alpha_context.Receipt.Balance_update_item + (balance, update, _origin)) = + balance_update + in + match balance with + | Staking_delegator_numerator {delegator} -> ( + match delegator with + | Originated _ -> assert false + | Implicit pkh -> + add_change + pkh + update + changes + ~f:update_staking_delegator_numerator) + | Staking_delegate_denominator {delegate} -> + add_change + delegate + update + changes + ~f:update_staking_delegate_denominator + | _ -> ( + match Protocol.Alpha_context.Receipt.token_of_balance balance with + | Tez -> changes + | Staking_pseudotoken -> assert false)) + Signature.Public_key_hash.Map.empty + balance_updates + in + let update_account account_state = + match Signature.Public_key_hash.Map.find account_state.pkh changes with + | None -> account_state + | Some f -> f account_state + in + let log_updates = + List.map + (fun (x, _) -> fst @@ find_account_from_pkh x state) + (Signature.Public_key_hash.Map.bindings changes) + in + update_map ~log_updates ~f:(String.Map.map update_account) state + + let apply_slashing + ( culprit, + Protocol.Denunciations_repr.{rewarded; misbehaviour; operation_hash} ) + (state : t) : t * Tez.t = + let account_map, total_burnt = + apply_slashing + (culprit, {rewarded; misbehaviour; operation_hash}) + state.constants + state.account_map + in + (* TODO: add culprit's stakers *) + let log_updates = + List.map + (fun x -> fst @@ find_account_from_pkh x state) + [culprit; rewarded] + in + let state = update_map ~log_updates ~f:(fun _ -> account_map) state in + (state, total_burnt) + + let apply_all_slashes_at_cycle_end current_cycle (state : t) : t = + let to_slash_later, to_slash_now = + if + not + state.constants + .Protocol.Alpha_context.Constants.Parametric.adaptive_issuance + .ns_enable + then ([], state.pending_slashes) + else + List.partition + (fun (_, Protocol.Denunciations_repr.{misbehaviour; _}) -> + let cycle = + Block.current_cycle_of_level + ~blocks_per_cycle: + state.constants + .Protocol.Alpha_context.Constants.Parametric + .blocks_per_cycle + ~current_level: + (Protocol.Raw_level_repr.to_int32 misbehaviour.level) + in + Cycle.(cycle = current_cycle)) + state.pending_slashes + in + let state, total_burnt = + List.fold_left + (fun (acc_state, acc_total) x -> + let state, burnt = apply_slashing x acc_state in + (state, Tez.(acc_total +! burnt))) + (state, Tez.zero) + to_slash_now + in + let total_supply = Tez.(state.total_supply -! total_burnt) in + {state with pending_slashes = to_slash_later; total_supply} + + (** Given an account name and new account state, updates [state] accordingly + Preferably use other specific update functions *) + let update_account (account_name : string) (value : account_state) (state : t) + : t = + let account_map = String.Map.add account_name value state.account_map in + {state with account_map} + + let update_delegate account_name delegate_name_opt state : t = + let account = find_account account_name state in + update_account + account_name + {account with delegate = delegate_name_opt} + state + + let add_pending_operations operations state = + {state with pending_operations = state.pending_operations @ operations} + + let pop_pending_operations state = + ({state with pending_operations = []}, state.pending_operations) + + let log_model_autostake name pkh old_cycle op ~optimal amount = + Log.debug + "Model Autostaking: at end of cycle %a, %s(%a) to reach optimal stake %a \ + %s %a" + Cycle.pp + old_cycle + name + Signature.Public_key_hash.pp + pkh + Tez.pp + optimal + op + Tez.pp + (Tez.of_mutez_exn amount) + + let apply_autostake ~name ~old_cycle + ({ + pkh; + contract = _; + delegate; + parameters = _; + liquid; + bonds = _; + frozen_deposits; + unstaked_frozen; + unstaked_finalizable; + staking_delegator_numerator = _; + staking_delegate_denominator = _; + frozen_rights = _; + slashed_cycles = _; + } : + account_state) state = + let open Result_syntax in + if Some name <> delegate then ( + Log.debug + "Model Autostaking: %s <> %s, noop@." + name + (Option.value ~default:"None" delegate) ; + return state) + else + let* current_liquid_delegated = liquid_delegated ~name state in + let current_frozen = Frozen_tez.total_current frozen_deposits in + let current_unstaked_frozen_delegated = + Unstaked_frozen.sum_current unstaked_frozen + in + let current_unstaked_final_delegated = + Unstaked_finalizable.total unstaked_finalizable + in + let power = + Tez.( + current_liquid_delegated +! current_frozen + +! current_unstaked_frozen_delegated + +! current_unstaked_final_delegated + |> to_mutez |> Z.of_int64) + in + let optimal = + Tez.of_z + (Z.cdiv + power + (Z.of_int (state.constants.limit_of_delegation_over_baking + 1))) + in + let autostaked = + Int64.(sub (Tez.to_mutez optimal) (Tez.to_mutez current_frozen)) + in + let state = apply_unslashable (Cycle.succ old_cycle) name state in + let state = apply_finalize name state in + (* stake or unstake *) + let new_state = + if autostaked > 0L then ( + log_model_autostake ~optimal name pkh old_cycle "stake" autostaked ; + apply_stake + Tez.(min liquid (of_mutez autostaked)) + (Cycle.succ old_cycle) + name + state) + else if autostaked < 0L then ( + log_model_autostake + ~optimal + name + pkh + old_cycle + "unstake" + (Int64.neg autostaked) ; + apply_unstake + (Cycle.succ old_cycle) + (Test_tez.of_mutez_exn Int64.(neg autostaked)) + name + state) + else ( + log_model_autostake + ~optimal + name + pkh + old_cycle + "only finalize" + autostaked ; + state) + in + return new_state + + (** Applies when baking the last block of a cycle *) + let apply_end_cycle current_cycle block state : t tzresult Lwt.t = + let open Lwt_result_wrap_syntax in + Log.debug ~color:time_color "Ending cycle %a" Cycle.pp current_cycle ; + let* launch_cycle_opt = + Context.get_adaptive_issuance_launch_cycle (B block) + in + (* Apply all slashes *) + let state = apply_all_slashes_at_cycle_end current_cycle state in + (* Sets initial frozen for future cycle *) + let state = + update_map + ~f: + (update_frozen_rights_cycle + (Cycle.add + current_cycle + (state.constants.consensus_rights_delay + 1))) + state + in + (* Apply autostaking *) + let*?@ state = + if not state.constants.adaptive_issuance.autostaking_enable then Ok state + else + match launch_cycle_opt with + | Some launch_cycle when Cycle.(current_cycle >= launch_cycle) -> + Ok state + | None | Some _ -> + String.Map.fold_e + (fun name account state -> + apply_autostake ~name ~old_cycle:current_cycle account state) + state.account_map + state + in + (* Apply parameter changes *) + let state, param_requests = + List.fold_left + (fun (state, remaining_requests) (name, params, wait) -> + if wait > 0 then + (state, (name, params, wait - 1) :: remaining_requests) + else + let src = find_account name state in + let state = + update_account name {src with parameters = params} state + in + (state, remaining_requests)) + (state, []) + state.param_requests + in + return {state with param_requests} + + (** Applies when baking the first block of a cycle. + Technically nothing special happens, but we need to update the unslashable unstakes + since it's done lazily *) + let apply_new_cycle new_cycle state : t = + apply_unslashable_for_all new_cycle state + + (* end module State *) +end + +(* ======== Scenarios ======== *) + +(** Usual threaded state for the tests. Contains the current block, pending operations + and the known [State.t] *) +type t = Block.t * State.t + +(** A scenario is a succession of actions. We define a branching path as a way to create multiple tests + from the same point. This allows easy compositionality of behaviors with minimal code sharing. + The [Tag] allows to give meaningful identifiers to the branches. It is good practice to tag each + case in a branch (it's not necessary, but since test names must be unique, at most one branch can + remain unnamed, and even then it can create conflicting names.) + *) +type ('input, 'output) scenarios = + | Action : ('input -> 'output tzresult Lwt.t) -> ('input, 'output) scenarios + | Empty : ('t, 't) scenarios + | Concat : (('a, 'b) scenarios * ('b, 'c) scenarios) -> ('a, 'c) scenarios + | Branch : (('a, 'b) scenarios * ('a, 'b) scenarios) -> ('a, 'b) scenarios + | Tag : (* Name for test branch *) string -> ('t, 't) scenarios + | Slow : (* If in scenario branch, makes the test `Slow *) + ('t, 't) scenarios + +(** Unfolded scenario type *) +type ('input, 'output) single_scenario = + | End_scenario : ('t, 't) single_scenario + | Cons : + (('input -> 't tzresult Lwt.t) * ('t, 'output) single_scenario) + -> ('input, 'output) single_scenario + +let rec cat_ss : + type a b c. + (a, b) single_scenario -> (b, c) single_scenario -> (a, c) single_scenario = + fun a b -> + match a with End_scenario -> b | Cons (act, a') -> Cons (act, cat_ss a' b) + +let combine f l1 l2 = + List.map (fun a -> List.map (fun b -> f a b) l2) l1 |> List.flatten + +let rec unfold_scenarios : + type input output. + (input, output) scenarios -> + ((input, output) single_scenario * string list * bool) list = function + | Slow -> [(End_scenario, [], true)] + | Tag s -> [(End_scenario, [s], false)] + | Empty -> [(End_scenario, [], false)] + | Action a -> [(Cons (a, End_scenario), [], false)] + | Branch (left, right) -> unfold_scenarios left @ unfold_scenarios right + | Concat (left, right) -> + let l = unfold_scenarios left in + let r = unfold_scenarios right in + combine + (fun (sl, tl, bl) (sr, tr, br) -> (cat_ss sl sr, tl @ tr, bl || br)) + l + r + +let rec run_scenario : + type input output. + (input, output) single_scenario -> input -> output tzresult Lwt.t = + let open Lwt_result_syntax in + fun scenario input -> + match scenario with + | End_scenario -> return input + | Cons (action, next) -> + let* result = action input in + run_scenario next result + +let unfolded_to_test : + (unit, unit) single_scenario * string list * bool -> + unit Alcotest_lwt.test_case = + fun (s, name, b) -> + let speed = if b then `Slow else `Quick in + let name = + match name with + | [] -> "" + | [n] -> n + | title :: tags -> + (* We chose to separate all tags with a comma, and use the head tag as a title for the test *) + title ^ ": " ^ String.concat ", " tags + in + Tztest.tztest name speed (run_scenario s) + +(** Useful aliases and operators *) + +(* Aliases for [Empty]. Can be used as first component of a scenario instead of a tag if its not needed. *) +let noop = Empty + +let no_tag = Empty + +let concat : + type a b c. (a, b) scenarios -> (b, c) scenarios -> (a, c) scenarios = + fun a b -> + match (a, b) with + | Empty, Empty -> Empty + | _, Empty -> a + | Empty, _ -> b + | _ -> Concat (a, b) + +let branch : type a b. (a, b) scenarios -> (a, b) scenarios -> (a, b) scenarios + = + fun a b -> match (a, b) with Empty, Empty -> Empty | _ -> Branch (a, b) + +(** Continuation connector: execute a then b *) +let ( --> ) a b = concat a b + +(** Branching connector: creates two tests with different execution paths *) +let ( |+ ) a b = branch a b + +let list_to_branch (list : (string * 'a) list) : (unit, 'a) scenarios = + match list with + | [] -> + Stdlib.failwith + (Format.asprintf + "%s: Cannot build scenarios from\n empty list" + __LOC__) + | (tag, h) :: t -> + List.fold_left + (fun scenarios (tag, elt) -> + scenarios + |+ Tag tag --> Action (fun () -> Lwt_result_syntax.return elt)) + (Tag tag --> Action (fun () -> Lwt_result_syntax.return h)) + t + +(** Ends the test. Dump the state, returns [unit] *) +let end_test : ('a, unit) scenarios = + let open Lwt_result_syntax in + Action + (fun _ -> + Log.info ~color:begin_end_color "-- End test --" ; + return_unit) + +(** Transforms scenarios into Alcotest tests *) +let tests_of_scenarios : + (string * (unit, 't) scenarios) list -> unit Alcotest_lwt.test_case list = + fun scenarios -> + List.map (fun (s, x) -> Tag s --> x --> end_test) scenarios |> function + | [] -> [] + | a :: t -> + List.fold_left ( |+ ) a t |> unfold_scenarios |> List.map unfolded_to_test + +(** Arbitrary execution *) +let exec f = Action f + +(** Execute a function that does not modify the block, only the state *) +let exec_state f = + let open Lwt_result_syntax in + Action + (fun ((block, _state) as input) -> + let* state = f input in + return (block, state)) + +(** Execute a function that does not modify neither the block nor the state. + Usually used for checks/asserts *) +let exec_unit f = + let open Lwt_result_syntax in + Action + (fun input -> + let* () = f input in + return input) + +(* ======== Baking ======== *) + +(** After baking and applying rewards in state *) +let check_all_balances block state : unit tzresult Lwt.t = + let open Lwt_result_syntax in + let State.{account_map; total_supply; _} = state in + let* actual_total_supply = Context.get_total_supply (B block) in + let*! r1 = + String.Map.fold_s + (fun name account acc -> + log_debug_balance name account_map ; + let* () = log_debug_rpc_balance name (Implicit account.pkh) block in + let*! r = + assert_balance_check ~loc:__LOC__ (B block) name account_map + in + join_errors r acc) + account_map + Result.return_unit + in + let*! r2 = + Assert.equal + ~loc:__LOC__ + Tez.equal + "Total supplies do not match" + Tez.pp + actual_total_supply + total_supply + in + join_errors r1 r2 + +let check_issuance_rpc block : unit tzresult Lwt.t = + let open Lwt_result_syntax in + (* We assume one block per minute *) + let* rewards_per_block = Context.get_issuance_per_minute (B block) in + let* total_supply = Context.get_total_supply (B block) in + let* expected_issuance = Context.get_ai_expected_issuance (B block) in + let* () = + match expected_issuance with + | ei :: _ -> + (* We assume only the fixed portion is issued *) + Assert.equal_tez + ~loc:__LOC__ + rewards_per_block + ei.baking_reward_fixed_portion + | _ -> failwith "expected_issuance rpc: unexpected value" + in + let* yearly_rate = Context.get_ai_current_yearly_rate (B block) in + let* yearly_rate_exact = Context.get_ai_current_yearly_rate_exact (B block) in + let yr = float_of_string yearly_rate in + let yre = Q.to_float yearly_rate_exact in + (* Precision for yearly rate is 0.001 *) + let* () = + Assert.equal + ~loc:__LOC__ + (fun x y -> Float.(abs (x -. y) <= 0.001)) + "Yearly rate (float)" + Format.pp_print_float + yr + yre + in + (* Divided by 525_600 minutes per year, x100 because rpc returns a pct *) + let issuance_from_rate = + Tez.( + mul_q total_supply Q.(div yearly_rate_exact ~$525_600_00) + |> of_q ~round_up:false) + in + let* () = + Assert.equal + ~loc:__LOC__ + Tez.equal + "Issuance" + Tez.pp + rewards_per_block + issuance_from_rate + in + return_unit + +(** Bake a block, with the given baker and the given operations. *) +let bake ?baker : t -> t tzresult Lwt.t = + fun (block, state) -> + let open Lwt_result_wrap_syntax in + Log.info + ~color:time_color + "Baking level %d" + (Int32.to_int (Int32.succ Block.(block.header.shell.level))) ; + let current_cycle = Block.current_cycle block in + let adaptive_issuance_vote = + if state.activate_ai then + Protocol.Alpha_context.Per_block_votes.Per_block_vote_on + else Per_block_vote_pass + in + let policy = + match baker with + | None -> state.baking_policy + | Some baker -> + let {pkh; _} = + try State.find_account baker state + with Not_found -> + Log.info + ~color:warning_color + "Invalid baker: %s not found. Aborting" + baker ; + assert false + in + Some (Block.By_account pkh) + in + let* baker, _, _, _ = Block.get_next_baker ?policy block in + let baker_name, {contract = baker_contract; _} = + State.find_account_from_pkh baker state + in + let* () = check_issuance_rpc block in + let state, operations = State.pop_pending_operations state in + let* block, state = + let* block', metadata = + Block.bake_with_metadata ?policy ~adaptive_issuance_vote ~operations block + in + let balance_updates = Block.get_balance_updates_from_metadata metadata in + let state = + State.apply_staking_abstract_balance_updates balance_updates state + in + if state.burn_rewards then + (* Incremental mode *) + let* i = + Incremental.begin_construction ?policy ~adaptive_issuance_vote block + in + let* block_rewards = Context.get_issuance_per_minute (B block') in + let ctxt = Incremental.alpha_ctxt i in + let*@ context, _ = + Protocol.Alpha_context.Token.transfer + ctxt + (`Contract baker_contract) + `Burned + block_rewards + in + let i = Incremental.set_alpha_ctxt i context in + let* i = List.fold_left_es Incremental.add_operation i operations in + let* block = Incremental.finalize_block i in + let state = State.apply_burn block_rewards baker_name state in + return (block, state) + else return (block', state) + in + let* state = State.apply_rewards ~baker:baker_name block state in + (* First block of a new cycle *) + let new_current_cycle = Block.current_cycle block in + let* state = + if Protocol.Alpha_context.Cycle.(current_cycle = new_current_cycle) then + return state + else ( + Log.info + ~color:time_color + "Cycle %d" + (Protocol.Alpha_context.Cycle.to_int32 new_current_cycle |> Int32.to_int) ; + return @@ State.apply_new_cycle new_current_cycle state) + in + (* Dawn of a new cycle *) + let* state = + if not (Block.last_block_of_cycle block) then return state + else State.apply_end_cycle current_cycle block state + in + let* () = check_all_balances block state in + return (block, state) + +(** Bake until a cycle is reached, using [bake] instead of [Block.bake] + Should be slower because checks balances at the end of every block (avoidable in some cases) *) +let bake_until_next_cycle : t -> t tzresult Lwt.t = + fun (init_block, init_state) -> + let open Lwt_result_syntax in + let current_cycle = Block.current_cycle init_block in + let rec step (old_block, old_state) = + let step_cycle = Block.current_cycle old_block in + if Protocol.Alpha_context.Cycle.(step_cycle > current_cycle) then + return (old_block, old_state) + else + let* new_block, new_state = bake (old_block, old_state) in + step (new_block, new_state) + in + step (init_block, init_state) + +(* ======== State updates ======== *) + +(** Sets the de facto baker for all future blocks *) +let set_baker baker : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + let {pkh; _} = State.find_account baker state in + return {state with State.baking_policy = Some (Block.By_account pkh)}) + +(** Exclude a list of delegates from baking *) +let exclude_bakers bakers : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + let bakers_pkh = + List.map (fun baker -> (State.find_account baker state).pkh) bakers + in + return + {state with State.baking_policy = Some (Block.Excluding bakers_pkh)}) + +(** Unsets the baking policy, it returns to default ([By_round 0]) *) +let unset_baking_policy : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + return {state with State.baking_policy = None}) + +(** Creates a snapshot of the current balances for the given account names. + Can be used to check that balances at point A and B in the execution of a test + are the same (either nothing happened, or a succession of actions resulted in + getting the same values as before *) +let snapshot_balances snap_name names_list : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + Log.debug + ~color:low_debug_color + "Snapshoting balances as \"%s\"" + snap_name ; + let balances = + List.map + (fun name -> (name, balance_of_account name state.State.account_map)) + names_list + in + let snapshot_balances = + String.Map.add snap_name balances state.snapshot_balances + in + return {state with snapshot_balances}) + +(** Check balances against a previously defined snapshot *) +let check_snapshot_balances + ?(f = + fun ~name ~old_balance ~new_balance -> + assert_balance_equal ~loc:__LOC__ name old_balance new_balance) + snap_name : (t, t) scenarios = + let open Lwt_result_syntax in + exec_unit (fun (_block, state) -> + Log.debug + ~color:low_debug_color + "Checking evolution of balances between \"%s\" and now" + snap_name ; + let snapshot_balances = + String.Map.find snap_name state.State.snapshot_balances + in + match snapshot_balances with + | None -> + Log.debug + ~color:warning_color + "\"%s\" snapshot not found..." + snap_name ; + return_unit + | Some snapshot_balances -> + let* () = + List.iter_es + (fun (name, old_balance) -> + let new_balance = + balance_of_account name state.State.account_map + in + f ~name ~old_balance ~new_balance) + snapshot_balances + in + return_unit) + +(** Save the current issuance rate for future use *) +let save_current_rate : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (block, state) -> + let* rate = Context.get_ai_current_yearly_rate_exact (B block) in + return {state with State.saved_rate = Some rate}) + +(** Check that [f saved_rate current_rate] is true. [f] is typically a comparison function *) +let check_rate_evolution (f : Q.t -> Q.t -> bool) : (t, t) scenarios = + let open Lwt_result_syntax in + exec_unit (fun (block, state) -> + let* new_rate = Context.get_ai_current_yearly_rate_exact (B block) in + let previous_rate = state.State.saved_rate in + match previous_rate with + | None -> failwith "check_rate_evolution: no rate previously saved" + | Some previous_rate -> + if f previous_rate new_rate then return_unit + else + failwith + "check_rate_evolution: assertion failed@.previous rate: %a@.new \ + rate: %a" + Q.pp_print + previous_rate + Q.pp_print + new_rate) + +(* ======== Operations ======== *) + +(** Bake a single block *) +let next_block = + exec (fun input -> + Log.info ~color:action_color "[Next block]" ; + bake input) + +(** Bake a single block with a specific baker *) +let next_block_with_baker baker = + exec (fun input -> + Log.info ~color:action_color "[Next block (baker %s)]" baker ; + bake ~baker input) + +(** Bake until the end of a cycle *) +let next_cycle = + exec (fun input -> + Log.info ~color:action_color "[Next cycle]" ; + bake_until_next_cycle input) + +(** Executes an operation: f should return a new state and a list of operations, which are then applied *) +let exec_op f = + let open Lwt_result_syntax in + Action + (fun ((block, _state) as input) -> + let* state, ops = f input in + let state = State.add_pending_operations ops state in + return (block, state)) + --> next_block + +(* ======== Definition of basic actions ======== *) + +(** Initialize the test, given some initial parameters *) +let begin_test ~activate_ai ?(burn_rewards = false) ?(ns_enable_fork = false) + ?(constants : Protocol.Alpha_context.Constants.Parametric.t option) + ?(constants_list : + (string * Protocol.Alpha_context.Constants.Parametric.t) list option) + delegates_name_list : (unit, t) scenarios = + let f ns_enable = + (match (constants, constants_list) with + | None, None -> Stdlib.failwith "No constants provided to begin_test" + | Some _, Some _ -> + Stdlib.failwith + "You cannot provide ~constants and ~constants_list to begin_test" + | None, Some constants_list -> list_to_branch constants_list + | Some constants, None -> + Action (fun () -> Lwt_result_syntax.return constants)) + --> exec (fun (constants : Protocol.Alpha_context.Constants.Parametric.t) -> + let open Lwt_result_syntax in + Log.info ~color:begin_end_color "-- Begin test --" ; + let bootstrap = "__bootstrap__" in + let delegates_name_list = bootstrap :: delegates_name_list in + (* Override threshold value if activate *) + let constants = + if activate_ai then ( + Log.info ~color:event_color "Setting ai threshold to 0" ; + { + constants with + adaptive_issuance = + { + constants.adaptive_issuance with + launch_ema_threshold = 0l; + activation_vote_enable = true; + ns_enable; + }; + }) + else constants + in + let n = List.length delegates_name_list in + let* block, delegates = Context.init_with_constants_n constants n in + let*? init_level = Context.get_level (B block) in + let init_staked = Tez.of_mutez 200_000_000_000L in + let*? account_map = + List.fold_left2 + ~when_different_lengths: + [Inconsistent_number_of_bootstrap_accounts] + (fun account_map name contract -> + let liquid = + Tez.(Account.default_initial_balance -! init_staked) + in + let frozen_deposits = Frozen_tez.init init_staked name name in + let frozen_rights = + List.fold_left + (fun map cycle -> CycleMap.add cycle init_staked map) + CycleMap.empty + Cycle.( + root ---> add root constants.consensus_rights_delay) + in + let pkh = Context.Contract.pkh contract in + let account = + init_account + ~delegate:name + ~pkh + ~contract + ~parameters:default_params + ~liquid + ~frozen_deposits + ~frozen_rights + () + in + let account_map = String.Map.add name account account_map in + let balance, total_balance = + balance_and_total_balance_of_account name account_map + in + Log.debug + "Initial balance for %s:\n%a" + name + balance_pp + balance ; + Log.debug "Initial total balance: %a" Tez.pp total_balance ; + account_map) + String.Map.empty + delegates_name_list + delegates + in + let* total_supply = Context.get_total_supply (B block) in + let state = + State. + { + account_map; + total_supply; + constants; + param_requests = []; + activate_ai; + baking_policy = None; + last_level_rewards = init_level; + snapshot_balances = String.Map.empty; + saved_rate = None; + burn_rewards; + pending_operations = []; + pending_slashes = []; + double_signings = []; + } + in + let* () = check_all_balances block state in + return (block, state)) + in + if ns_enable_fork then + Tag "ns_enable = true" --> f true |+ Tag "ns_enable = false" --> f false + else f false + +(** Set delegate parameters for the given delegate *) +let set_delegate_params delegate_name parameters : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + (* Simple example of action_atom definition: *) + let delegate = State.find_account delegate_name state in + Log.info + ~color:action_color + "[Set delegate parameters for \"%s\"]" + delegate_name ; + (* Define the operation *) + let* operation = + set_delegate_parameters (B block) delegate.contract ~parameters + in + (* Update state *) + let wait = state.constants.delegate_parameters_activation_delay - 1 in + let state = + { + state with + param_requests = + (delegate_name, parameters, wait) :: state.param_requests; + } + in + (* Return both *) + return (state, [operation])) + +(** Add a new account with the given name *) +let add_account name : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + Log.info ~color:action_color "[Add account \"%s\"]" name ; + let new_account = Account.new_account () in + let pkh = new_account.pkh in + let contract = Protocol.Alpha_context.Contract.Implicit pkh in + let account_state = + init_account ~pkh ~contract ~parameters:default_params () + in + let state = State.update_account name account_state state in + return state) + +(** Reveal operation *) +let reveal name : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + let account = State.find_account name state in + Log.info ~color:action_color "[Reveal \"%s\"]" name ; + let* acc = Account.find account.pkh in + let* operation = + Op.revelation ~fee:Protocol.Alpha_context.Tez.zero (B block) acc.pk + in + return (state, [operation])) + +(** Transfer from src to dst *) +let transfer src_name dst_name amount : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + let src = State.find_account src_name state in + let dst = State.find_account dst_name state in + let amount = quantity_to_tez src.liquid amount in + Log.info + ~color:action_color + "[Transfer \"%s\" -> \"%s\" (%aꜩ)]" + src_name + dst_name + Tez.pp + amount ; + let* operation = + Op.transaction ~fee:Tez.zero (B block) src.contract dst.contract amount + in + let state = State.apply_transfer amount src_name dst_name state in + return (state, [operation])) + +(** Set delegate for src. If [delegate_name_opt = None], then unset current delegate *) +let set_delegate src_name delegate_name_opt : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + let src = State.find_account src_name state in + let delegate_pkh_opt = + match delegate_name_opt with + | None -> + Log.info ~color:action_color "[Unset delegate of \"%s\"]" src_name ; + None + | Some delegate_name -> + let delegate = State.find_account delegate_name state in + Log.info + ~color:action_color + "[Set delegate \"%s\" for \"%s\"]" + delegate_name + src_name ; + Some delegate.pkh + in + let cycle = Block.current_cycle block in + let* operation = + Op.delegation ~fee:Tez.zero (B block) src.contract delegate_pkh_opt + in + let balance = balance_of_account src_name state.account_map in + let state = + if Q.(equal balance.staked_b zero) then state + else + let state = State.apply_unstake cycle Tez.max_mutez src_name state in + (* Changing delegate applies finalize if unstake happened *) + State.apply_finalize src_name state + in + let state = State.update_delegate src_name delegate_name_opt state in + return (state, [operation])) + +(** Stake operation *) +let stake src_name stake_value : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + let src = State.find_account src_name state in + Log.info + ~color:action_color + "[Stake for \"%s\" (%a)]" + src_name + tez_quantity_pp + stake_value ; + (* Stake applies finalize *before* the stake *) + let state = State.apply_finalize src_name state in + let amount = quantity_to_tez src.liquid stake_value in + let current_cycle = Block.current_cycle block in + let* operation = stake (B block) src.contract amount in + let state = State.apply_stake amount current_cycle src_name state in + return (state, [operation])) + +(** unstake operation *) +let unstake src_name unstake_value : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + let src = State.find_account src_name state in + Log.info + ~color:action_color + "[Unstake for \"%s\" (%a)]" + src_name + tez_quantity_pp + unstake_value ; + let stake_balance = + (balance_of_account src_name state.account_map).staked_b + |> Partial_tez.to_tez ~round_up:false + in + let amount = quantity_to_tez stake_balance unstake_value in + let* operation = unstake (B block) src.contract amount in + let cycle = Block.current_cycle block in + let balance = balance_of_account src_name state.account_map in + let state = + if Q.(equal balance.staked_b zero) then state + else + let state = State.apply_unstake cycle amount src_name state in + State.apply_finalize src_name state + in + return (state, [operation])) + +(** finalize unstake operation *) +let finalize_unstake src_name : (t, t) scenarios = + exec_op (fun (block, state) -> + let open Lwt_result_syntax in + let src = State.find_account src_name state in + Log.info ~color:action_color "[Finalize_unstake for \"%s\"]" src_name ; + let* operation = finalize_unstake (B block) src.contract in + let state = State.apply_finalize src_name state in + return (state, [operation])) + +(* ======== Slashing ======== *) + +let check_pending_slashings (block, state) : unit tzresult Lwt.t = + let open Lwt_result_syntax in + let open Protocol.Denunciations_repr in + let* denunciations_rpc = Context.get_denunciations (B block) in + let denunciations_obj_equal (pkh_1, {rewarded = r1; misbehaviour = m1; _}) + (pkh_2, {rewarded = r2; misbehaviour = m2; _}) = + Signature.Public_key_hash.equal pkh_1 pkh_2 + && Signature.Public_key_hash.equal r1 r2 + && Stdlib.(m1.kind = m2.kind) + in + let compare_denunciations (pkh_1, {rewarded = r1; misbehaviour = m1; _}) + (pkh_2, {rewarded = r2; misbehaviour = m2; _}) = + let c1 = Signature.Public_key_hash.compare pkh_1 pkh_2 in + if c1 <> 0 then c1 + else + let c2 = Signature.Public_key_hash.compare r1 r2 in + if c2 <> 0 then c2 + else Protocol.Misbehaviour_repr.compare_kind m1.kind m2.kind + in + let denunciations_rpc = List.sort compare_denunciations denunciations_rpc in + let denunciations_state = + List.sort compare_denunciations state.State.pending_slashes + in + let denunciations_equal = List.equal denunciations_obj_equal in + let denunciations_obj_pp fmt + (pkh, {rewarded; misbehaviour; operation_hash = _}) = + Format.fprintf + fmt + "slashed: %a; rewarded: %a; kind: %s@." + Signature.Public_key_hash.pp + pkh + Signature.Public_key_hash.pp + rewarded + (match misbehaviour.kind with + | Double_baking -> "double baking" + | Double_attesting -> "double attesting" + | Double_preattesting -> "double preattesting") + in + let denunciations_pp = Format.pp_print_list denunciations_obj_pp in + let* () = + Assert.equal + ~loc:__LOC__ + denunciations_equal + "Denunciations are not equal" + denunciations_pp + denunciations_rpc + denunciations_state + in + return_unit + +(** Double attestation helpers *) +let order_attestations ~correct_order op1 op2 = + let oph1 = Protocol.Alpha_context.Operation.hash op1 in + let oph2 = Protocol.Alpha_context.Operation.hash op2 in + let c = Operation_hash.compare oph1 oph2 in + if correct_order then if c < 0 then (op1, op2) else (op2, op1) + else if c < 0 then (op2, op1) + else (op1, op2) + +let op_double_attestation ?(correct_order = true) op1 op2 ctxt = + let e1, e2 = order_attestations ~correct_order op1 op2 in + Op.double_attestation ctxt e1 e2 + +let op_double_preattestation ?(correct_order = true) op1 op2 ctxt = + let e1, e2 = order_attestations ~correct_order op1 op2 in + Op.double_preattestation ctxt e1 e2 + +let order_block_hashes ~correct_order bh1 bh2 = + let hash1 = Protocol.Alpha_context.Block_header.hash bh1 in + let hash2 = Protocol.Alpha_context.Block_header.hash bh2 in + let c = Block_hash.compare hash1 hash2 in + if correct_order then if c < 0 then (bh1, bh2) else (bh2, bh1) + else if c < 0 then (bh2, bh1) + else (bh1, bh2) + +let op_double_baking ?(correct_order = true) bh1 bh2 ctxt = + let bh1, bh2 = order_block_hashes ~correct_order bh1 bh2 in + Op.double_baking ctxt bh1 bh2 + +let double_bake_ delegate_name (block, state) = + let open Lwt_result_syntax in + Log.info ~color:Log_module.event_color "Double baking with %s" delegate_name ; + let delegate = State.find_account delegate_name state in + let* operation = + Adaptive_issuance_helpers.unstake (B block) delegate.contract Tez.one_mutez + in + let* forked_block = + Block.bake ~policy:(By_account delegate.pkh) ~operation block + in + (* includes pending operations *) + let* main_branch, state = bake ~baker:delegate_name (block, state) in + let evidence = op_double_baking main_branch.header forked_block.header in + let dss = + { + culprit = delegate.pkh; + denounced = false; + evidence; + kind = Double_baking; + level = block.header.shell.level; + } + in + let state = + {state with double_signings = dss :: state.State.double_signings} + in + return (main_branch, state) + +(* Note: advances one block *) +let double_bake delegate_name : (t, t) scenarios = + exec (double_bake_ delegate_name) + +(* [other_bakers] can be used to force using specific bakers to avoid + reusing forbidden ones *) +let double_attest_op ?other_bakers ~op ~op_evidence ~kind delegate_name + (block, state) = + let open Lwt_result_syntax in + Log.info + ~color:Log_module.event_color + "Double %s with %s" + (match kind with + | Protocol.Misbehaviour_repr.Double_preattesting -> "preattesting" + | Double_attesting -> "attesting" + | Double_baking -> assert false) + delegate_name ; + let delegate = State.find_account delegate_name state in + let* baker, _, _, _ = + Block.get_next_baker ?policy:state.baking_policy block + in + let* other_baker1, other_baker2 = + match other_bakers with + | Some (ob1, ob2) -> + let ob1 = (State.find_account ob1 state).pkh in + let ob2 = (State.find_account ob2 state).pkh in + return (ob1, ob2) + | None -> Context.get_first_different_bakers (B block) + in + let other_baker = + if not (Signature.Public_key_hash.equal baker other_baker2) then + other_baker2 + else other_baker1 + in + let* forked_block = Block.bake ~policy:(By_account other_baker) block in + let* forked_block = Block.bake ?policy:state.baking_policy forked_block in + (* includes pending operations *) + let* block, state = bake (block, state) in + let* main_branch, state = bake (block, state) in + let* attestation_a = op ~delegate:delegate.pkh forked_block in + let* attestation_b = op ~delegate:delegate.pkh main_branch in + let evidence = op_evidence attestation_a attestation_b in + let dss = + { + culprit = delegate.pkh; + denounced = false; + evidence; + kind; + level = block.header.shell.level; + } + in + let state = + {state with double_signings = dss :: state.State.double_signings} + in + return (main_branch, state) + +let double_attest_ = + double_attest_op + ~op:(fun ~delegate block -> Op.raw_attestation ~delegate block) + ~op_evidence:op_double_attestation + ~kind:Double_attesting + +(* Note: advances two blocks *) +let double_attest ?other_bakers delegate_name : (t, t) scenarios = + exec (double_attest_ ?other_bakers delegate_name) + +let double_preattest_ = + double_attest_op + ~op:(fun ~delegate block -> Op.raw_preattestation ~delegate block) + ~op_evidence:op_double_preattestation + ~kind:Double_preattesting + +(* Note: advances two blocks *) +let double_preattest ?other_bakers delegate_name : (t, t) scenarios = + exec (double_preattest_ ?other_bakers delegate_name) + +let cycle_from_level blocks_per_cycle level = + let current_cycle = Int32.div level blocks_per_cycle in + let current_cycle = Cycle.add Cycle.root (Int32.to_int current_cycle) in + current_cycle + +let pct_from_kind (block : Block.t) = function + | Protocol.Misbehaviour_repr.Double_baking -> + Protocol.Percentage.to_q + block.constants.percentage_of_frozen_deposits_slashed_per_double_baking + |> Q.(mul (100 // 1)) + |> Q.to_int + | Double_attesting | Double_preattesting -> + Protocol.Percentage.to_q + block.constants + .percentage_of_frozen_deposits_slashed_per_double_attestation + |> Q.(mul (100 // 1)) + |> Q.to_int + +let get_pending_slashed_pct_for_delegate (block, state) delegate = + let rec aux r = function + | [] -> r + | (culprit, {Protocol.Denunciations_repr.misbehaviour; _}) :: t -> + if Signature.Public_key_hash.equal delegate culprit then + let new_r = r + pct_from_kind block misbehaviour.kind in + if new_r >= 100 then 100 else aux new_r t + else aux r t + in + aux 0 state.State.pending_slashes + +let update_state_denunciation (block, state) + {culprit; denounced; evidence = _; kind; level} = + let open Lwt_result_syntax in + if denounced then + (* If the double signing has already been denounced, a second denunciation should fail *) + return (state, denounced) + else + let*? block_level = Context.get_level (B block) in + let next_level = + Protocol.Alpha_context.Raw_level.(to_int32 @@ succ block_level) + in + if level > next_level then + (* The denunciation is trying to be included too early *) + return (state, denounced) + else + let inclusion_cycle = + cycle_from_level block.constants.blocks_per_cycle next_level + in + let ds_cycle = cycle_from_level block.constants.blocks_per_cycle level in + if Cycle.(succ ds_cycle < inclusion_cycle) then + (* denunciation is too late, gets refused *) + return (state, denounced) + else if get_pending_slashed_pct_for_delegate (block, state) culprit >= 100 + then + (* Culprit has been slashed too much, a denunciation is not added to the list. + TODO: is the double signing treated as included, or can it be included in the + following cycle? *) + return (state, denounced) + else + let misbehaviour = + { + (* Fields level and round are unused for now. *) + level = Protocol.Raw_level_repr.of_int32_exn level; + round = Protocol.Round_repr.zero; + Protocol.Misbehaviour_repr.kind; + } + in + (* for simplicity's sake (lol), the block producer and the payload producer are the same + We also assume that the current state baking policy will be used for the next block *) + let* rewarded, _, _, _ = + Block.get_next_baker ?policy:state.baking_policy block + in + let culprit_name, culprit_account = + State.find_account_from_pkh culprit state + in + let state = + State.update_account + culprit_name + { + culprit_account with + slashed_cycles = inclusion_cycle :: culprit_account.slashed_cycles; + } + state + in + let new_pending_slash = + ( culprit, + { + Protocol.Denunciations_repr.rewarded; + misbehaviour; + operation_hash = Operation_hash.zero; + (* unused *) + } ) + in + (* TODO: better log... *) + Log.info + ~color:Log_module.event_color + "Including denunciation (misbehaviour cycle %a)" + Cycle.pp + ds_cycle ; + let state = + State. + { + state with + pending_slashes = new_pending_slash :: state.pending_slashes; + } + in + return (state, true) + +let make_denunciations_ ?(filter = fun {denounced; _} -> not denounced) + (block, state) = + let open Lwt_result_syntax in + let* () = check_pending_slashings (block, state) in + let make_op state ({evidence; _} as dss) = + if filter dss then + let* state, denounced = update_state_denunciation (block, state) dss in + return (Some (evidence (B block), {dss with denounced}, state)) + else return None + in + let rec make_op_list dss_list state r_op r_dss = + match dss_list with + | d :: t -> ( + let* new_op = make_op state d in + match new_op with + | None -> make_op_list t state r_op (d :: r_dss) + | Some (op, p_dss, new_state) -> + make_op_list t new_state (op :: r_op) (p_dss :: r_dss)) + | [] -> return @@ (state, List.rev r_op, List.rev r_dss) + in + let* state, operations, double_signings = + make_op_list state.double_signings state [] [] + in + let state = {state with double_signings} in + return (state, operations) + +(* Important note: do not change the baking policy behaviour once denunciations are made, + until the operations are included in a block (by default the next block) *) +let make_denunciations ?filter () = exec_op (make_denunciations_ ?filter) + +(* ======== Misc functions ========*) + +let check_failure_aux ?expected_error : + ('a -> 'b tzresult Lwt.t) -> 'a -> 'a tzresult Lwt.t = + let open Lwt_result_syntax in + fun f input -> + Log.info ~color:assert_block_color "Entering failing scenario..." ; + let*! output = f input in + match output with + | Ok _ -> failwith "Unexpected success" + | Error e -> ( + match expected_error with + | None -> + Log.info ~color:assert_block_color "Rollback" ; + return input + | Some exp_e -> + let exp_e = exp_e input in + if e = exp_e then ( + Log.info ~color:assert_block_color "Rollback" ; + return input) + else ( + Log.info + ~color:Log.Color.FG.red + "Unexpected error:@.%a@.Expected:@.%a@." + (Format.pp_print_list pp) + e + (Format.pp_print_list pp) + exp_e ; + tzfail Unexpected_error)) + +let check_fail_and_rollback ?expected_error : + ('a, 'b) single_scenario -> 'a -> 'a tzresult Lwt.t = + fun sc input -> check_failure_aux ?expected_error (run_scenario sc) input + +(** Useful function to test expected failures: runs the given branch until it fails, + then rollbacks to before execution. Fails if the given branch Succeeds *) +let assert_failure ?expected_error : ('a, 'b) scenarios -> ('a, 'a) scenarios = + fun scenarios -> + match unfold_scenarios scenarios with + | [] -> Empty + | [(sc, _, _)] -> exec (check_fail_and_rollback ?expected_error sc) + | _ -> + exec (fun _ -> + failwith "Error: assert_failure used with branching scenario") + +(** Loop *) +let rec loop n : ('a, 'a) scenarios -> ('a, 'a) scenarios = + fun scenario -> + (* If branching scenarios with k branches, returns a scenario with k^n branches *) + if n = 0 then Empty + else if n = 1 then scenario + else loop (n - 1) scenario --> scenario + +let rec loop_action n : ('a -> 'a tzresult Lwt.t) -> ('a, 'a) scenarios = + fun f -> + if n = 0 then Empty + else if n = 1 then exec f + else loop_action (n - 1) f --> exec f + +(** Check a specific balance field for a specific account is equal to a specific amount *) +let check_balance_field src_name field amount : (t, t) scenarios = + let open Lwt_result_syntax in + let check = Assert.equal_tez ~loc:__LOC__ amount in + let check' a = check (Partial_tez.to_tez ~round_up:false a) in + exec_state (fun (block, state) -> + let src = State.find_account src_name state in + let src_balance, src_total = + balance_and_total_balance_of_account src_name state.account_map + in + let* rpc_balance, rpc_total = + get_balance_from_context (B block) src.contract + in + let* () = + match field with + | `Liquid -> + let* () = check rpc_balance.liquid_b in + check src_balance.liquid_b + | `Bonds -> + let* () = check rpc_balance.bonds_b in + check src_balance.bonds_b + | `Staked -> + let* () = check' rpc_balance.staked_b in + check' src_balance.staked_b + | `Unstaked_frozen_total -> + let* () = check rpc_balance.unstaked_frozen_b in + check src_balance.unstaked_frozen_b + | `Unstaked_finalizable -> + let* () = check rpc_balance.unstaked_finalizable_b in + check src_balance.unstaked_finalizable_b + | `Total -> + let* () = check rpc_total in + check src_total + in + return state) + +(** Waiting functions *) +let rec wait_n_cycles n = + if n <= 0 then noop + else if n = 1 then next_cycle + else wait_n_cycles (n - 1) --> next_cycle + +let rec wait_n_blocks n = + if n <= 0 then noop + else if n = 1 then next_block + else wait_n_blocks (n - 1) --> next_block + +(** Wait until we are in a cycle satifying the given condition. + Fails if AI_activation is requested and AI is not set to be activated in the future. *) +let wait_cycle condition = + exec (fun (block, state) -> + let open Lwt_result_syntax in + let rec stopper condition = + match condition with + | `AI_activation -> + if state.State.activate_ai then + let* launch_cycle = get_launch_cycle ~loc:__LOC__ block in + return + @@ ( (fun block _state -> + let current_cycle = Block.current_cycle block in + Cycle.(current_cycle >= launch_cycle)), + "AI activation", + "AI activated" ) + else assert false + | `delegate_parameters_activation -> + let init_cycle = Block.current_cycle block in + let cycles_to_wait = + state.constants.delegate_parameters_activation_delay + in + return + @@ ( (fun block _state -> + Cycle.( + Block.current_cycle block >= add init_cycle cycles_to_wait)), + "delegate parameters activation", + "delegate parameters activated" ) + | `And (cond1, cond2) -> + let* stop1, to1, done1 = stopper cond1 in + let* stop2, to2, done2 = stopper cond2 in + return + @@ ( (fun block state -> stop1 block state && stop2 block state), + to1 ^ " and " ^ to2, + done1 ^ " and " ^ done2 ) + in + let* stopper, to_, done_ = stopper condition in + Log.info ~color:time_color "Fast forward to %s" to_ ; + let* output = + let rec bake_while (block, state) = + if stopper block state then return (block, state) + else + let* input = bake_until_next_cycle (block, state) in + bake_while input + in + bake_while (block, state) + in + Log.info ~color:event_color "%s" done_ ; + return output) + +(** Wait until AI activates. + Fails if AI is not set to be activated in the future. *) +let wait_ai_activation = wait_cycle `AI_activation + +(** wait delegate_parameters_activation_delay cycles *) +let wait_delegate_parameters_activation = + wait_cycle `delegate_parameters_activation + +(** Create an account and give an initial balance funded by [source] *) +let add_account_with_funds name source amount = + add_account name --> transfer source name amount --> reveal name + +(* ======== Scenarios ======== *) + +let test_expected_error = + assert_failure + ~expected_error:(fun _ -> [Exn (Failure "")]) + (exec (fun _ -> failwith "")) + --> assert_failure + ~expected_error:(fun _ -> [Unexpected_error]) + (assert_failure + ~expected_error:(fun _ -> + [Inconsistent_number_of_bootstrap_accounts]) + (exec (fun _ -> failwith ""))) + +let init_constants ?reward_per_block ?(deactivate_dynamic = false) + ?blocks_per_cycle ?delegate_parameters_activation_delay ~autostaking_enable + () = + let reward_per_block = Option.value ~default:0L reward_per_block in + let base_total_issued_per_minute = Tez.of_mutez reward_per_block in + let default_constants = Default_parameters.constants_test in + (* default for tests: 12 *) + let blocks_per_cycle = + Option.value ~default:default_constants.blocks_per_cycle blocks_per_cycle + in + let delegate_parameters_activation_delay = + Option.value + ~default:default_constants.delegate_parameters_activation_delay + delegate_parameters_activation_delay + in + let issuance_weights = + Protocol.Alpha_context.Constants.Parametric. + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight = 1; + baking_reward_bonus_weight = 0; + attesting_reward_weight = 0; + seed_nonce_revelation_tip_weight = 0; + vdf_revelation_tip_weight = 0; + } + in + let liquidity_baking_subsidy = Tez.zero in + let minimal_block_delay = Protocol.Alpha_context.Period.one_minute in + let cost_per_byte = Tez.zero in + let consensus_threshold = 0 in + let adaptive_issuance = default_constants.adaptive_issuance in + let adaptive_rewards_params = + if deactivate_dynamic then + { + adaptive_issuance.adaptive_rewards_params with + max_bonus = + Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn Q.zero; + } + else adaptive_issuance.adaptive_rewards_params + in + let adaptive_issuance = + {adaptive_issuance with adaptive_rewards_params; autostaking_enable} + in + { + default_constants with + delegate_parameters_activation_delay; + consensus_threshold; + issuance_weights; + minimal_block_delay; + cost_per_byte; + adaptive_issuance; + blocks_per_cycle; + liquidity_baking_subsidy; + } + +(** Initialization of scenarios with 3 cases: + - AI activated, staker = delegate + - AI activated, staker != delegate + - AI not activated (and staker = delegate) + Any scenario that begins with this will be triplicated. + *) +let init_scenario ?(force_ai = true) ?reward_per_block () = + let constants = + init_constants ?reward_per_block ~autostaking_enable:false () + in + let init_params = + {limit_of_staking_over_baking = Q.one; edge_of_baking_over_staking = Q.one} + in + let begin_test ~activate_ai ~self_stake = + let name = if self_stake then "staker" else "delegate" in + begin_test ~activate_ai ~constants [name] + --> set_delegate_params name init_params + --> set_baker "__bootstrap__" + in + let ai_activated = + Tag "AI activated" + --> (Tag "self stake" --> begin_test ~activate_ai:true ~self_stake:true + |+ Tag "external stake" + --> begin_test ~activate_ai:true ~self_stake:false + --> add_account_with_funds + "staker" + "delegate" + (Amount (Tez.of_mutez 2_000_000_000_000L)) + --> set_delegate "staker" (Some "delegate")) + --> wait_ai_activation + in + + let ai_deactivated = + Tag "AI deactivated, self stake" + --> begin_test ~activate_ai:false ~self_stake:true + in + (if force_ai then ai_activated else ai_activated |+ ai_deactivated) + --> next_block + +module Roundtrip = struct + let stake_init = + stake "staker" Half + --> (Tag "no wait after stake" --> Empty + |+ Tag "wait after stake" --> wait_n_cycles 2) + + let wait_for_unfreeze_and_check wait = + snapshot_balances "wait snap" ["staker"] + --> wait_n_cycles (wait - 1) + (* Balance didn't change yet, but will change next cycle *) + --> check_snapshot_balances "wait snap" + --> next_cycle + --> assert_failure (check_snapshot_balances "wait snap") + + let finalize staker = + assert_failure (check_balance_field staker `Unstaked_finalizable Tez.zero) + --> finalize_unstake staker + --> check_balance_field staker `Unstaked_finalizable Tez.zero + + let simple_roundtrip = + stake_init + --> (Tag "full unstake" --> unstake "staker" All + |+ Tag "half unstake" --> unstake "staker" Half) + --> wait_for_unfreeze_and_check default_unstake_wait + --> finalize "staker" --> next_cycle + + let double_roundtrip = + stake_init --> unstake "staker" Half + --> (Tag "half then full unstake" --> wait_n_cycles 2 + --> unstake "staker" All + |+ Tag "half then half unstake" --> wait_n_cycles 2 + --> unstake "staker" Half) + --> wait_for_unfreeze_and_check (default_unstake_wait - 2) + --> wait_for_unfreeze_and_check 2 + --> finalize "staker" --> next_cycle + + let shorter_roundtrip_for_baker = + let constants = init_constants ~autostaking_enable:false () in + let amount = Amount (Tez.of_mutez 333_000_000_000L) in + let consensus_rights_delay = constants.consensus_rights_delay in + begin_test ~activate_ai:true ~constants ["delegate"] + --> next_block --> wait_ai_activation + --> stake "delegate" (Amount (Tez.of_mutez 1_800_000_000_000L)) + --> next_cycle + --> snapshot_balances "init" ["delegate"] + --> unstake "delegate" amount + --> List.fold_left + (fun acc i -> acc |+ Tag (fs "wait %i cycles" i) --> wait_n_cycles i) + (Tag "wait 0 cycles" --> Empty) + (Stdlib.List.init (consensus_rights_delay + 1) (fun i -> i + 1)) + --> stake "delegate" amount + --> check_snapshot_balances "init" + + let status_quo_rountrip = + let full_amount = Tez.of_mutez 10_000_000L in + let amount_1 = Tez.of_mutez 2_999_999L in + let amount_2 = Tez.of_mutez 7_000_001L in + snapshot_balances "init" ["staker"] + --> stake "staker" (Amount full_amount) + --> next_cycle + --> (Tag "1 unstake" --> unstake "staker" (Amount full_amount) + |+ Tag "2 unstakes" + --> unstake "staker" (Amount amount_1) + --> next_cycle + --> unstake "staker" (Amount amount_2)) + --> wait_n_cycles default_unstake_wait + --> finalize "staker" + --> check_snapshot_balances "init" + + let scenario_finalize = + no_tag --> stake "staker" Half --> next_cycle --> unstake "staker" Half + --> wait_n_cycles (default_unstake_wait + 2) + --> assert_failure + (check_balance_field "staker" `Unstaked_finalizable Tez.zero) + --> (Tag "finalize with finalize" --> finalize_unstake "staker" + |+ Tag "finalize with stake" --> stake "staker" (Amount Tez.one_mutez) + |+ Tag "finalize with unstake" + --> unstake "staker" (Amount Tez.one_mutez)) + --> check_balance_field "staker" `Unstaked_finalizable Tez.zero + + (* Finalize does not go through when unstake does nothing *) + (* Todo: there might be other cases... like changing delegates *) + let scenario_not_finalize = + no_tag --> stake "staker" Half --> next_cycle --> unstake "staker" All + --> wait_n_cycles (default_unstake_wait + 2) + --> assert_failure + (check_balance_field "staker" `Unstaked_finalizable Tez.zero) + --> snapshot_balances "not finalize" ["staker"] + --> (Tag "no finalize with unstake if staked = 0" + --> unstake "staker" (Amount Tez.one_mutez)) + --> assert_failure + (check_balance_field "staker" `Unstaked_finalizable Tez.zero) + --> check_snapshot_balances "not finalize" + + (* TODO: there's probably more... *) + let scenario_forbidden_operations = + let open Lwt_result_syntax in + let fail_if_staker_is_self_delegate staker = + exec (fun ((_, state) as input) -> + if State.(is_self_delegate staker state) then + failwith "_self_delegate_exit_" + else return input) + in + no_tag + (* Staking everything works for self delegates, but not for delegated accounts *) + --> assert_failure + (fail_if_staker_is_self_delegate "staker" --> stake "staker" All) + (* stake is always forbidden when amount is zero *) + --> assert_failure (stake "staker" Nothing) + (* One cannot stake more that one has *) + --> assert_failure (stake "staker" Max_tez) + (* unstake is actually authorized for amount 0, but does nothing (doesn't even finalize if possible) *) + --> unstake "staker" Nothing + + let full_balance_in_finalizable = + add_account_with_funds "dummy" "staker" (Amount (Tez.of_mutez 10_000_000L)) + --> stake "staker" All_but_one --> next_cycle --> unstake "staker" All + --> wait_n_cycles (default_unstake_wait + 2) + (* At this point, almost all the balance (but one mutez) of the stake is in finalizable *) + (* Staking is possible, but not transfer *) + --> assert_failure + (transfer "staker" "dummy" (Amount (Tez.of_mutez 10_000_000L))) + --> stake "staker" (Amount (Tez.of_mutez 10_000_000L)) + (* After the stake, transfer is possible again because the funds were finalized *) + --> transfer "staker" "dummy" (Amount (Tez.of_mutez 10_000_000L)) + + (* Stress test: what happens if someone were to stake and unstake every cycle? *) + let odd_behavior = + let one_cycle = + no_tag --> stake "staker" Half --> unstake "staker" Half --> next_cycle + in + loop 20 one_cycle + + let change_delegate = + let constants = init_constants ~autostaking_enable:false () in + let init_params = + { + limit_of_staking_over_baking = Q.one; + edge_of_baking_over_staking = Q.one; + } + in + begin_test ~activate_ai:true ~constants ["delegate1"; "delegate2"] + --> set_delegate_params "delegate1" init_params + --> set_delegate_params "delegate2" init_params + --> add_account_with_funds + "staker" + "delegate1" + (Amount (Tez.of_mutez 2_000_000_000_000L)) + --> set_delegate "staker" (Some "delegate1") + --> wait_ai_activation --> next_cycle --> stake "staker" Half --> next_cycle + --> set_delegate "staker" (Some "delegate2") + --> next_cycle + --> assert_failure (stake "staker" Half) + --> wait_n_cycles (default_unstake_wait + 1) + --> stake "staker" Half + + let unset_delegate = + let constants = init_constants ~autostaking_enable:false () in + let init_params = + { + limit_of_staking_over_baking = Q.one; + edge_of_baking_over_staking = Q.one; + } + in + begin_test ~activate_ai:true ~constants ["delegate"] + --> set_delegate_params "delegate" init_params + --> add_account_with_funds + "staker" + "delegate" + (Amount (Tez.of_mutez 2_000_000_000_000L)) + --> add_account_with_funds + "dummy" + "delegate" + (Amount (Tez.of_mutez 2_000_000L)) + --> set_delegate "staker" (Some "delegate") + --> wait_ai_activation --> next_cycle --> stake "staker" Half + --> unstake "staker" All --> next_cycle --> set_delegate "staker" None + --> next_cycle + --> transfer "staker" "dummy" All + (* staker has an empty liquid balance, but still has unstaked frozen tokens, + so it doesn't get deactivated *) + --> wait_n_cycles (default_unstake_wait + 1) + --> finalize_unstake "staker" + + let forbid_costaking = + let default_constants = + ("default protocol constants", init_constants ~autostaking_enable:false ()) + in + let small_delegate_parameter_constants = + ( "small delegate parameters delay", + init_constants + ~delegate_parameters_activation_delay:0 + ~autostaking_enable:false + () ) + in + let large_delegate_parameter_constants = + ( "large delegate parameters delay", + init_constants + ~delegate_parameters_activation_delay:10 + ~autostaking_enable:false + () ) + in + let init_params = + { + limit_of_staking_over_baking = Q.one; + edge_of_baking_over_staking = Q.one; + } + in + let no_costake_params = + { + limit_of_staking_over_baking = Q.zero; + edge_of_baking_over_staking = Q.one; + } + in + let amount = Amount (Tez.of_mutez 1_000_000L) in + (* init *) + begin_test + ~activate_ai:true + ~constants_list: + [ + default_constants; + small_delegate_parameter_constants; + large_delegate_parameter_constants; + ] + ["delegate"] + --> set_delegate_params "delegate" init_params + --> add_account_with_funds + "staker" + "delegate" + (Amount (Tez.of_mutez 2_000_000_000_000L)) + --> set_delegate "staker" (Some "delegate") + --> wait_cycle (`And (`AI_activation, `delegate_parameters_activation)) + --> next_cycle + (* try stake in normal conditions *) + --> stake "staker" amount + (* Change delegate parameters to forbid staking *) + --> set_delegate_params "delegate" no_costake_params + (* The changes are not immediate *) + --> stake "staker" amount + (* The parameters change is applied exactly + [delegate_parameters_activation_delay] after the request *) + --> wait_delegate_parameters_activation + (* Not yet... *) + --> stake "staker" amount + --> next_cycle + (* External staking is now forbidden *) + --> assert_failure (stake "staker" amount) + (* Can still self-stake *) + --> stake "delegate" amount + (* Can still unstake *) + --> unstake "staker" Half + --> wait_n_cycles (default_unstake_wait + 1) + --> finalize_unstake "staker" + (* Can authorize stake again *) + --> set_delegate_params "delegate" init_params + --> wait_delegate_parameters_activation + (* Not yet... *) + --> assert_failure (stake "staker" amount) + --> next_cycle + (* Now possible *) + --> stake "staker" amount + + let tests = + tests_of_scenarios + @@ [ + ("Test simple roundtrip", init_scenario () --> simple_roundtrip); + ("Test double roundtrip", init_scenario () --> double_roundtrip); + ("Test preserved balance", init_scenario () --> status_quo_rountrip); + ("Test finalize", init_scenario () --> scenario_finalize); + ("Test no finalize", init_scenario () --> scenario_not_finalize); + ( "Test forbidden operations", + init_scenario () --> scenario_forbidden_operations ); + ( "Test full balance in finalizable", + init_scenario () --> full_balance_in_finalizable ); + ("Test stake unstake every cycle", init_scenario () --> odd_behavior); + ("Test change delegate", change_delegate); + ("Test unset delegate", unset_delegate); + ("Test forbid costake", forbid_costaking); + ("Test stake from unstake", shorter_roundtrip_for_baker); + ] +end + +module Rewards = struct + let test_wait_with_rewards = + let constants = + init_constants + ~reward_per_block:1_000_000_000L + ~autostaking_enable:false + () + in + begin_test ~activate_ai:true ~constants ["delegate"] + --> (Tag "block step" --> wait_n_blocks 200 + |+ Tag "cycle step" --> wait_n_cycles 20 + |+ Tag "wait AI activation" --> next_block --> wait_ai_activation + --> (Tag "block step" --> wait_n_blocks 100 + |+ Tag "cycle step" --> wait_n_cycles 10)) + + let test_ai_curve_activation_time = + let constants = + init_constants + ~reward_per_block:1_000_000_000L + ~deactivate_dynamic:true + ~autostaking_enable:false + () + in + let pc = constants.consensus_rights_delay in + begin_test ~activate_ai:true ~burn_rewards:true ~constants [""] + --> next_block --> save_current_rate (* before AI rate *) + --> wait_ai_activation + (* Rate remains unchanged right after AI activation, we must wait [pc + 1] cycles *) + --> check_rate_evolution Q.equal + --> wait_n_cycles pc + --> check_rate_evolution Q.equal + --> next_cycle + (* The new rate should be active now. With the chosen constants, it should be lower. + We go from 1000tz per day to (at most) 5% of 4_000_000tz per year *) + --> check_rate_evolution Q.gt + + let test_static = + let constants = + init_constants + ~reward_per_block:1_000_000_000L + ~deactivate_dynamic:true + ~autostaking_enable:false + () + in + let rate_var_lag = constants.consensus_rights_delay in + let init_params = + { + limit_of_staking_over_baking = Q.one; + edge_of_baking_over_staking = Q.one; + } + in + let delta = Amount (Tez.of_mutez 20_000_000_000L) in + let cycle_stake = + save_current_rate --> stake "delegate" delta --> next_cycle + --> check_rate_evolution Q.gt + in + let cycle_unstake = + save_current_rate --> unstake "delegate" delta --> next_cycle + --> check_rate_evolution Q.lt + in + let cycle_stable = + save_current_rate --> next_cycle --> check_rate_evolution Q.equal + in + begin_test ~activate_ai:true ~burn_rewards:true ~constants ["delegate"] + --> set_delegate_params "delegate" init_params + --> save_current_rate --> wait_ai_activation + (* We stake about 50% of the total supply *) + --> stake "delegate" (Amount (Tez.of_mutez 1_800_000_000_000L)) + --> stake "__bootstrap__" (Amount (Tez.of_mutez 1_800_000_000_000L)) + --> (Tag "increase stake, decrease rate" --> next_cycle + --> loop rate_var_lag (stake "delegate" delta --> next_cycle) + --> loop 10 cycle_stake + |+ Tag "decrease stake, increase rate" --> next_cycle + --> loop rate_var_lag (unstake "delegate" delta --> next_cycle) + --> loop 10 cycle_unstake + |+ Tag "stable stake, stable rate" --> next_cycle + --> wait_n_cycles rate_var_lag --> loop 10 cycle_stable + |+ Tag "test timing" --> wait_n_cycles rate_var_lag + --> check_rate_evolution Q.equal + --> next_cycle --> check_rate_evolution Q.gt --> save_current_rate + --> (Tag "increase stake" --> stake "delegate" delta + --> wait_n_cycles rate_var_lag + --> check_rate_evolution Q.equal + --> next_cycle --> check_rate_evolution Q.gt + |+ Tag "decrease stake" --> unstake "delegate" delta + --> wait_n_cycles rate_var_lag + --> check_rate_evolution Q.equal + --> next_cycle --> check_rate_evolution Q.lt)) + + let tests = + tests_of_scenarios + @@ [ + ("Test wait with rewards", test_wait_with_rewards); + ("Test ai curve activation time", test_ai_curve_activation_time); + (* ("Test static rate", test_static); *) + ] +end + +module Autostaking = struct + let assert_balance_evolution ~loc ~for_accounts ~part ~name ~old_balance + ~new_balance compare = + let open Lwt_result_syntax in + let old_b, new_b = + match part with + | `liquid -> + ( Q.of_int64 @@ Tez.to_mutez old_balance.liquid_b, + Q.of_int64 @@ Tez.to_mutez new_balance.liquid_b ) + | `staked -> (old_balance.staked_b, new_balance.staked_b) + | `unstaked_frozen -> + ( Q.of_int64 @@ Tez.to_mutez old_balance.unstaked_frozen_b, + Q.of_int64 @@ Tez.to_mutez new_balance.unstaked_frozen_b ) + | `unstaked_finalizable -> + ( Q.of_int64 @@ Tez.to_mutez old_balance.unstaked_finalizable_b, + Q.of_int64 @@ Tez.to_mutez new_balance.unstaked_finalizable_b ) + in + if List.mem ~equal:String.equal name for_accounts then + if compare new_b old_b then return_unit + else ( + Log.debug ~color:Log_module.warning_color "Balances changes failed:@." ; + Log.debug "@[Old Balance@ %a@]@." balance_pp old_balance ; + Log.debug "@[New Balance@ %a@]@." balance_pp new_balance ; + failwith "%s Unexpected stake evolution for %s" loc name) + else raise Not_found + + let delegate = "delegate" + + and delegator1 = "delegator1" + + and delegator2 = "delegator2" + + let setup ~activate_ai = + let constants = init_constants ~autostaking_enable:true () in + begin_test ~activate_ai ~constants [delegate] + --> add_account_with_funds + delegator1 + "__bootstrap__" + (Amount (Tez.of_mutez 2_000_000_000L)) + --> add_account_with_funds + delegator2 + "__bootstrap__" + (Amount (Tez.of_mutez 2_000_000_000L)) + --> next_cycle + --> (if activate_ai then wait_ai_activation else next_cycle) + --> snapshot_balances "before delegation" [delegate] + --> set_delegate delegator1 (Some delegate) + --> check_snapshot_balances "before delegation" + --> next_cycle + + let test_autostaking = + Tag "No Ai" --> setup ~activate_ai:false + --> check_snapshot_balances + ~f: + (assert_balance_evolution + ~loc:__LOC__ + ~for_accounts:[delegate] + ~part:`staked + Q.gt) + "before delegation" + --> snapshot_balances "before second delegation" [delegate] + --> (Tag "increase delegation" + --> set_delegate delegator2 (Some delegate) + --> next_cycle + --> check_snapshot_balances + ~f: + (assert_balance_evolution + ~loc:__LOC__ + ~for_accounts:[delegate] + ~part:`staked + Q.gt) + "before second delegation" + |+ Tag "constant delegation" + --> snapshot_balances "after stake change" [delegate] + --> wait_n_cycles 8 + --> check_snapshot_balances "after stake change" + |+ Tag "decrease delegation" + --> set_delegate delegator1 None + --> next_cycle + --> check_snapshot_balances + ~f: + (assert_balance_evolution + ~loc:__LOC__ + ~for_accounts:[delegate] + ~part:`staked + Q.lt) + "before second delegation" + --> check_snapshot_balances + ~f: + (assert_balance_evolution + ~loc:__LOC__ + ~for_accounts:[delegate] + ~part:`unstaked_frozen + Q.gt) + "before second delegation" + --> snapshot_balances "after unstake" [delegate] + --> next_cycle + --> check_snapshot_balances "after unstake" + --> wait_n_cycles 4 + --> check_snapshot_balances + ~f: + (assert_balance_evolution + ~loc:__LOC__ + ~for_accounts:[delegate] + ~part:`unstaked_frozen + Q.lt) + "after unstake" + (* finalizable are auto-finalize immediately *) + --> check_snapshot_balances + ~f: + (assert_balance_evolution + ~loc:__LOC__ + ~for_accounts:[delegate] + ~part:`liquid + Q.lt) + "before finalisation") + |+ Tag "Yes AI" --> setup ~activate_ai:true + --> check_snapshot_balances "before delegation" + + let test_overdelegation = + (* This test assumes that all delegate accounts created in [begin_test] + begin with 4M tz, with 5% staked *) + let constants = init_constants ~autostaking_enable:true () in + begin_test + ~activate_ai:false + ~constants + ["delegate"; "faucet1"; "faucet2"; "faucet3"] + --> add_account_with_funds + "delegator_to_fund" + "delegate" + (Amount (Tez.of_mutez 3_600_000_000_000L)) + (* Delegate has 200k staked and 200k liquid *) + --> set_delegate "delegator_to_fund" (Some "delegate") + (* Delegate stake will not change at the end of cycle: same stake *) + --> next_cycle + --> check_balance_field "delegate" `Staked (Tez.of_mutez 200_000_000_000L) + --> transfer + "faucet1" + "delegator_to_fund" + (Amount (Tez.of_mutez 3_600_000_000_000L)) + (* Delegate is not overdelegated, but will need to freeze 180k *) + --> next_cycle + --> check_balance_field "delegate" `Staked (Tez.of_mutez 380_000_000_000L) + --> transfer + "faucet2" + "delegator_to_fund" + (Amount (Tez.of_mutez 3_600_000_000_000L)) + (* Delegate is now overdelegated, it will freeze 100% *) + --> next_cycle + --> check_balance_field "delegate" `Staked (Tez.of_mutez 400_000_000_000L) + --> transfer + "faucet3" + "delegator_to_fund" + (Amount (Tez.of_mutez 3_600_000_000_000L)) + (* Delegate is overmegadelegated *) + --> next_cycle + --> check_balance_field "delegate" `Staked (Tez.of_mutez 400_000_000_000L) + + let tests = + tests_of_scenarios + [ + ("Test auto-staking", test_autostaking); + ("Test auto-staking with overdelegation", test_overdelegation); + ] +end + +module Slashing = struct + let test_simple_slash = + let constants = init_constants ~autostaking_enable:false () in + let any_slash delegate = + Tag "double baking" --> double_bake delegate + |+ Tag "double attesting" + --> double_attest ~other_bakers:("bootstrap2", "bootstrap3") delegate + |+ Tag "double preattesting" + --> double_preattest + ~other_bakers:("bootstrap2", "bootstrap3") + delegate + in + begin_test + ~activate_ai:true + ~ns_enable_fork:true + ~constants + ["delegate"; "bootstrap1"; "bootstrap2"; "bootstrap3"] + --> (Tag "No AI" --> next_cycle + |+ Tag "Yes AI" --> next_block --> wait_ai_activation) + --> any_slash "delegate" + --> snapshot_balances "before slash" ["delegate"] + --> ((Tag "denounce same cycle" + --> make_denunciations () + (* delegate can be forbidden in this case, so we set another baker *) + --> exclude_bakers ["delegate"] + |+ Tag "denounce next cycle" --> next_cycle --> make_denunciations () + (* delegate can be forbidden in this case, so we set another baker *) + --> exclude_bakers ["delegate"]) + --> (Empty + |+ Tag "another slash" --> any_slash "bootstrap1" + --> make_denunciations () + (* bootstrap1 can be forbidden in this case, so we set another baker *) + --> exclude_bakers ["delegate"; "bootstrap1"]) + --> check_snapshot_balances "before slash" + --> exec_unit check_pending_slashings + --> next_cycle + --> assert_failure + (exec_unit (fun (_block, state) -> + if state.State.constants.adaptive_issuance.ns_enable then + failwith "ns_enable = true: slash not applied yet" + else Lwt_result_syntax.return_unit) + --> check_snapshot_balances "before slash") + --> exec_unit check_pending_slashings + --> next_cycle + |+ Tag "denounce too late" --> next_cycle --> next_cycle + --> assert_failure + ~expected_error:(fun (_block, state) -> + let ds = state.State.double_signings in + let ds = match ds with [a] -> a | _ -> assert false in + let level = + Protocol.Alpha_context.Raw_level.of_int32_exn + (Int32.succ ds.level) + in + let last_cycle = + Cycle.add + (Block.current_cycle_of_level + ~blocks_per_cycle: + state.State.constants.blocks_per_cycle + ~current_level:ds.level) + Protocol.Constants_repr.max_slashing_period + in + let (kind : Protocol.Alpha_context.Misbehaviour.kind) = + (* This conversion would not be needed if + Misbehaviour_repr.kind were moved to a + separate file that doesn't have under/over + Alpha_context versions. *) + match ds.kind with + | Double_baking -> Double_baking + | Double_attesting -> Double_attesting + | Double_preattesting -> Double_preattesting + in + [ + Environment.Ecoproto_error + (Protocol.Validate_errors.Anonymous.Outdated_denunciation + {kind; level; last_cycle}); + ]) + (make_denunciations ()) + --> check_snapshot_balances "before slash") + + let check_is_forbidden baker = assert_failure (next_block_with_baker baker) + + let check_is_not_forbidden baker = + let open Lwt_result_syntax in + exec (fun ((block, state) as input) -> + let baker = State.find_account baker state in + let*! _ = Block.bake ~policy:(By_account baker.pkh) block in + return input) + + let test_delegate_forbidden = + let constants = + init_constants ~blocks_per_cycle:30l ~autostaking_enable:false () + in + begin_test + ~activate_ai:false + ~ns_enable_fork:true + ~constants + ["delegate"; "bootstrap1"; "bootstrap2"] + --> set_baker "bootstrap1" + --> (Tag "Many double bakes" + --> loop_action 14 (double_bake_ "delegate") + --> (Tag "14 double bakes are not enough to forbid a delegate" + (* 7*14 = 98 *) + --> make_denunciations () + --> check_is_not_forbidden "delegate" + |+ Tag "15 double bakes is one too many" + (* 7*15 = 105 > 100 *) + --> double_bake "delegate" + --> make_denunciations () + --> check_is_forbidden "delegate") + |+ Tag "Is forbidden after first denunciation" + --> double_attest "delegate" + --> (Tag "very early first denounce" --> make_denunciations () + --> (Tag "in same cycle" --> Empty + |+ Tag "next cycle" --> next_cycle) + --> check_is_forbidden "delegate") + |+ Tag "Is unforbidden after 7 cycles" --> double_attest "delegate" + --> make_denunciations () + --> exclude_bakers ["delegate"] + --> check_is_forbidden "delegate" + --> stake "delegate" Half + --> check_is_not_forbidden "delegate" + |+ Tag + "Two double attestations, in consecutive cycles, denounce out of \ + order" --> double_attest "delegate" --> next_cycle + --> double_attest "delegate" + --> make_denunciations + ~filter:(fun {level; denounced; _} -> + (not denounced) && level > 10l) + () + --> make_denunciations + ~filter:(fun {level; denounced; _} -> + (not denounced) && level <= 10l) + () + --> check_is_forbidden "delegate") + + let test_slash_unstake = + let constants = init_constants ~autostaking_enable:false () in + begin_test + ~activate_ai:false + ~ns_enable_fork:true + ~constants + ["delegate"; "bootstrap1"; "bootstrap2"] + --> set_baker "bootstrap1" --> next_cycle --> unstake "delegate" Half + --> next_cycle --> double_bake "delegate" --> make_denunciations () + --> (Empty |+ Tag "unstake twice" --> unstake "delegate" Half) + --> wait_n_cycles 5 + --> finalize_unstake "delegate" + + let test_slash_monotonous_stake = + let scenario ~offending_op ~op ~early_d = + let constants = + init_constants ~blocks_per_cycle:16l ~autostaking_enable:false () + in + begin_test + ~activate_ai:false + ~ns_enable_fork:true + ~constants + ["delegate"; "bootstrap1"] + --> next_cycle + --> loop + 6 + (op "delegate" (Amount (Tez.of_mutez 1_000_000_000L)) --> next_cycle) + --> offending_op "delegate" + --> (op "delegate" (Amount (Tez.of_mutez 1_000_000_000L)) + --> loop + 2 + (op "delegate" (Amount (Tez.of_mutez 1_000_000_000L)) + --> + if early_d then + make_denunciations () + --> exclude_bakers ["delegate"] + --> next_block + else offending_op "delegate" --> next_block)) + in + Tag "slashes with increasing stake" + --> (Tag "denounce early" + --> (Tag "Double Bake" + --> scenario ~offending_op:double_bake ~op:stake ~early_d:true + |+ Tag "Double attest" + --> scenario ~offending_op:double_attest ~op:stake ~early_d:true + ) + |+ Tag "denounce late" + --> (Tag "Double Bake" + --> scenario ~offending_op:double_bake ~op:stake ~early_d:false + |+ Tag "Double attest" + --> scenario + ~offending_op:double_attest + ~op:stake + ~early_d:false) + --> make_denunciations ()) + |+ Tag "slashes with decreasing stake" + --> (Tag "Double Bake" + --> scenario ~offending_op:double_bake ~op:unstake ~early_d:true + |+ Tag "Double attest" + --> scenario ~offending_op:double_attest ~op:unstake ~early_d:true + ) + |+ Tag "denounce late" + --> (Tag "Double Bake" + --> scenario ~offending_op:double_bake ~op:unstake ~early_d:false + |+ Tag "Double attest" + --> scenario + ~offending_op:double_attest + ~op:unstake + ~early_d:false) + --> make_denunciations () + + let test_slash_timing = + let constants = + init_constants ~blocks_per_cycle:8l ~autostaking_enable:false () + in + begin_test ~activate_ai:false ~ns_enable_fork:true ~constants ["delegate"] + --> next_cycle + --> (Tag "stake" --> stake "delegate" Half + |+ Tag "unstake" --> unstake "delegate" Half) + --> (Tag "with a first slash" --> double_bake "delegate" + --> make_denunciations () + |+ Tag "without another slash" --> Empty) + --> List.fold_left + (fun acc i -> + acc |+ Tag (string_of_int i ^ " cycles lag") --> wait_n_cycles i) + Empty + [3; 4; 5; 6] + --> double_bake "delegate" --> make_denunciations () --> next_cycle + + let init_scenario_with_delegators delegate_name faucet_name delegators_list = + let constants = init_constants ~autostaking_enable:false () in + let rec init_delegators = function + | [] -> Empty + | (delegator, amount) :: t -> + add_account_with_funds + delegator + faucet_name + (Amount (Tez.of_mutez amount)) + --> set_delegate delegator (Some delegate_name) + --> init_delegators t + in + let init_params = + { + limit_of_staking_over_baking = Q.one; + edge_of_baking_over_staking = Q.one; + } + in + begin_test + ~activate_ai:true + ~ns_enable_fork:true + ~constants + [delegate_name; faucet_name] + --> set_baker faucet_name + --> set_delegate_params "delegate" init_params + --> init_delegators delegators_list + --> next_block --> wait_ai_activation + + let test_many_slashes = + let rec stake_unstake_for = function + | [] -> Empty + | staker :: t -> + stake staker Half --> unstake staker Half --> stake_unstake_for t + in + let slash delegate = double_bake delegate --> make_denunciations () in + Tag "double bake" + --> (Tag "solo delegate" + --> init_scenario_with_delegators + "delegate" + "faucet" + [("delegator", 1_234_567_891L)] + --> loop + 10 + (stake_unstake_for ["delegate"] + --> slash "delegate" --> next_cycle)) + (* |+ Tag "delegate with one staker" + --> init_scenario_with_delegators + "delegate" + "faucet" + [("staker", 1_234_356_891L)] + --> loop + 10 + (stake_unstake_for ["delegate"; "staker"] + --> slash "delegate" --> next_cycle) + |+ Tag "delegate with three stakers" + --> init_scenario_with_delegators + "delegate" + "faucet" + [ + ("staker1", 1_234_356_891L); + ("staker2", 1_234_356_890L); + ("staker3", 1_723_333_111L); + ] + --> loop + 10 + (stake_unstake_for + ["delegate"; "staker1"; "staker2"; "staker3"] + --> slash "delegate" --> next_cycle))*) + + let test_no_shortcut_for_cheaters = + let constants = init_constants ~autostaking_enable:false () in + let amount = Amount (Tez.of_mutez 333_000_000_000L) in + let consensus_rights_delay = constants.consensus_rights_delay in + begin_test + ~activate_ai:true + ~ns_enable_fork:false + ~constants + ["delegate"; "bootstrap1"] + --> next_block --> wait_ai_activation + --> stake "delegate" (Amount (Tez.of_mutez 1_800_000_000_000L)) + --> next_cycle --> double_bake "delegate" --> make_denunciations () + --> set_baker "bootstrap1" (* exclude_bakers ["delegate"] *) + --> next_cycle + --> snapshot_balances "init" ["delegate"] + --> unstake "delegate" amount + --> (List.fold_left + (fun acc i -> acc |+ Tag (fs "wait %i cycles" i) --> wait_n_cycles i) + (Tag "wait 0 cycles" --> Empty) + (Stdlib.List.init (consensus_rights_delay - 1) (fun i -> i + 1)) + --> stake "delegate" amount + --> assert_failure (check_snapshot_balances "init") + |+ Tag "wait enough cycles (consensus_rights_delay + 1)" + --> wait_n_cycles (consensus_rights_delay + 1) + --> stake "delegate" amount + --> check_snapshot_balances "init") + + let test_slash_correct_amount_after_stake_from_unstake = + let constants = init_constants ~autostaking_enable:false () in + let amount_to_unstake = Amount (Tez.of_mutez 200_000_000_000L) in + let amount_to_restake = Amount (Tez.of_mutez 100_000_000_000L) in + let amount_expected_in_unstake_after_slash = Tez.of_mutez 50_000_000_000L in + let consensus_rights_delay = constants.consensus_rights_delay in + begin_test + ~activate_ai:true + ~ns_enable_fork:false + ~constants + ["delegate"; "bootstrap1"] + --> next_block --> wait_ai_activation + --> stake "delegate" (Amount (Tez.of_mutez 1_800_000_000_000L)) + --> next_cycle + --> unstake "delegate" amount_to_unstake + --> stake "delegate" amount_to_restake + --> List.fold_left + (fun acc i -> acc |+ Tag (fs "wait %i cycles" i) --> wait_n_cycles i) + (Tag "wait 0 cycles" --> Empty) + (Stdlib.List.init (consensus_rights_delay - 2) (fun i -> i + 1)) + --> double_attest "delegate" --> make_denunciations () + --> exclude_bakers ["delegate"] + --> next_cycle + --> check_balance_field + "delegate" + `Unstaked_frozen_total + amount_expected_in_unstake_after_slash + + (* Test a non-zero request finalizes for a non-zero amount if it hasn't been slashed 100% *) + let test_mini_slash = + let constants = init_constants ~autostaking_enable:false () in + (Tag "Yes AI" + --> begin_test + ~activate_ai:true + ~ns_enable_fork:false + ~constants + ["delegate"; "baker"] + --> next_block --> wait_ai_activation + |+ Tag "No AI" + --> begin_test + ~activate_ai:false + ~ns_enable_fork:false + ~constants + ["delegate"; "baker"]) + --> unstake "delegate" (Amount Tez.one_mutez) + --> set_baker "baker" --> next_cycle + --> (Tag "5% slash" --> double_bake "delegate" --> make_denunciations () + |+ Tag "95% slash" --> next_cycle --> double_attest "delegate" + --> loop 9 (double_bake "delegate") + --> make_denunciations ()) + (* Wait two cycles because of ns_enable *) + --> next_cycle + --> next_cycle + --> check_balance_field "delegate" `Unstaked_frozen_total Tez.zero + --> wait_n_cycles (constants.consensus_rights_delay + 1) + + let test_slash_rounding = + let constants = init_constants ~autostaking_enable:false () in + begin_test + ~activate_ai:true + ~ns_enable_fork:true + ~constants + ["delegate"; "baker"] + --> set_baker "baker" --> next_block --> wait_ai_activation + --> unstake "delegate" (Amount (Tez.of_mutez 2L)) + --> next_cycle --> double_bake "delegate" --> double_bake "delegate" + --> make_denunciations () --> wait_n_cycles 7 + --> finalize_unstake "delegate" + + (* TODO #6645: reactivate tests *) + let tests = + tests_of_scenarios + @@ [ + ("Test simple slashing", test_simple_slash); + ("Test slashed is forbidden", test_delegate_forbidden); + ("Test slash with unstake", test_slash_unstake); + (* TODO: make sure this test passes with blocks_per_cycle:8l + https://gitlab.com/tezos/tezos/-/issues/6904 *) + ("Test slashes with simple varying stake", test_slash_monotonous_stake); + (* This test has been deactivated following the changes of the + forbidding mechanism that now forbids delegates right after the + first denunciation, it should be fixed and reactivated + https://gitlab.com/tezos/tezos/-/issues/6904 *) + (* ( "Test multiple slashes with multiple stakes/unstakes", *) + (* test_many_slashes ); *) + (* ("Test slash timing", test_slash_timing); *) + ( "Test stake from unstake deactivated when slashed", + test_no_shortcut_for_cheaters ); + ( "Test stake from unstake reduce initial amount", + test_slash_correct_amount_after_stake_from_unstake ); + ("Test unstake 1 mutez then slash", test_mini_slash); + ("Test slash rounding", test_slash_rounding); + ] +end + +let tests = + let open Lwt_result_syntax in + (tests_of_scenarios + @@ [ + ("Test expected error in assert failure", test_expected_error); + ("Test init", init_scenario () --> Action (fun _ -> return_unit)); + ]) + @ Roundtrip.tests @ Rewards.tests @ Autostaking.tests @ Slashing.tests + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("adaptive issuance roundtrip", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_constants.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_constants.ml new file mode 100644 index 000000000000..ad3be74d5432 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_constants.ml @@ -0,0 +1,275 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* Copyright (c) 2022 Trilitech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (baking) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_constants.ml + Subject: the consistency of parametric constants + *) + +open Test_tez + +let test_sc_rollup_constants_consistency () = + let open Protocol.Alpha_context in + let to_string c = + Data_encoding.Json.( + to_string ~minify:true + @@ construct Constants.Parametric.Internal_for_tests.sc_rollup_encoding c) + in + (* We do not necessarily need to update this value when the block time + changes. The goal is to witness the consistency of the “symbolic” + computations in [Default_parameters] and [Raw_context].. *) + let block_time = 10 in + let sc_rollup = + Default_parameters.Internal_for_tests.make_sc_rollup_parameter + ~dal_attested_slots_validity_lag:241_920 + (* 4 weeks with a 10 secs block time. *) + ~dal_activation_level:Raw_level.root + block_time + in + let sc_rollup' = + Constants.Parametric.update_sc_rollup_parameter sc_rollup ~block_time + in + Assert.equal + ~loc:__LOC__ + (fun s1 s2 -> String.equal (to_string s1) (to_string s2)) + "sc_rollup_parameter update" + (fun fmt sc_rollup -> Format.pp_print_string fmt @@ to_string sc_rollup) + sc_rollup + sc_rollup' + +let test_constants_consistency () = + let open Default_parameters in + List.iter_es + Block.check_constants_consistency + [constants_mainnet; constants_sandbox; constants_test] + +let test_max_operations_ttl () = + let open Lwt_result_wrap_syntax in + let open Protocol in + (* We check the rationale that the value for [max_operations_time_to_live] is the following: + + [minimal_time_between_blocks * max_operations_time_to_live = 3600] *) + let constants = Default_parameters.constants_mainnet in + let*?@ result = + Alpha_context.Period.mult + (Int32.of_int constants.max_operations_time_to_live) + constants.minimal_block_delay + in + Assert.equal + ~loc:__LOC__ + (fun x y -> Alpha_context.Period.compare x y = 0) + "max_operations_ttl" + Alpha_context.Period.pp + Alpha_context.Period.one_hour + result + +(* Check that + [sc_rollup_challenge_window_in_blocks < sc_rollup_max_lookahead_in_blocks] + + Otherwise committers would be forced to commit at an artificially slow rate, affecting + the throughput of the rollup. *) +let test_sc_rollup_challenge_window_lt_max_lookahead () = + let constants = Default_parameters.constants_mainnet in + let max_lookahead = constants.sc_rollup.max_lookahead_in_blocks in + let challenge_window = + Int32.of_int constants.sc_rollup.challenge_window_in_blocks + in + Assert.lt_int32 ~loc:__LOC__ challenge_window max_lookahead + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4481 + Improve this to catch more regressions in term of storage consumption *) + +(* Check that + [commitment_storage_cost * max_lookahead / commitment_period < stake_amount] + + Otherwise storage could be overallocated - since backtracking is not allowed, a staker + can allocated at most [d] nodes (where [d] is the tree depth) - the maximum storage cost + of these commitments must be at most the size of the staker's deposit. *) +let test_sc_rollup_max_commitment_storage_cost_lt_deposit () = + let constants = Default_parameters.constants_mainnet in + let open Protocol in + let cost_per_byte_mutez = + Alpha_context.Tez.to_mutez constants.cost_per_byte + in + let commitment_storage_size = + Int64.of_int + Sc_rollup_stake_storage.Internal_for_tests + .max_commitment_storage_size_in_bytes + in + let commitment_storage_cost = + Int64.mul cost_per_byte_mutez commitment_storage_size + in + let max_lookahead = + Int64.of_int32 constants.sc_rollup.max_lookahead_in_blocks + in + let commitment_period = + Int64.of_int constants.sc_rollup.commitment_period_in_blocks + in + let stake_amount = + Alpha_context.Tez.to_mutez constants.sc_rollup.stake_amount + in + Assert.leq_int64 + ~loc:__LOC__ + (Int64.mul + commitment_storage_cost + (Int64.div max_lookahead commitment_period)) + stake_amount + +(* Check that + [{!Sc_rollup_stake_storage.commitment_storage_size_in_bytes} = + commitments_entry_size + commitment_stake_count_entry_size + + commitment_added_entry_size] + + Required to ensure [sc_rollup_stake_amount] and [sc_rollup_max_lookahead] are + correctly scaled with respect to each other - see + {!test_sc_rollup_max_commitment_storage_cost_lt_deposit} +*) +let test_sc_rollup_max_commitment_storage_size () = + let open Lwt_result_syntax in + let open Protocol in + let* number_of_ticks = + Assert.get_some + ~loc:__LOC__ + (Sc_rollup_repr.Number_of_ticks.of_value 1232909L) + in + let commitment = + Sc_rollup_commitment_repr. + { + predecessor = Sc_rollup_commitment_repr.Hash.zero; + inbox_level = Raw_level_repr.of_int32_exn 21l; + number_of_ticks; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let versioned_commitment = + Sc_rollup_commitment_repr.to_versioned commitment + in + let commitment_length = + Data_encoding.Binary.length + Sc_rollup_commitment_repr.versioned_encoding + versioned_commitment + in + let commitment_hash = + Sc_rollup_commitment_repr.hash_uncarbonated commitment + in + let level = Alpha_context.Raw_level.of_int32_exn 5l in + (* One for the first publication level, and one for the published level. *) + let levels_length = + Data_encoding.Binary.length Alpha_context.Raw_level.encoding level * 2 + in + let staker_index = + Sc_rollup_staker_index_repr.Internal_for_tests.of_z (Z.of_int 94323442) + in + let stakers_index_length = + Data_encoding.( + Binary.length (list Sc_rollup_staker_index_repr.encoding) [staker_index]) + in + let commitment_hashes_length = + Data_encoding.( + Binary.length + (list Sc_rollup_commitment_repr.Hash.encoding) + [commitment_hash]) + in + let max_expected = + Sc_rollup_stake_storage.Internal_for_tests + .max_commitment_storage_size_in_bytes + in + let total_computed = + commitment_length + levels_length + stakers_index_length + + commitment_hashes_length + in + Assert.leq_int ~loc:__LOC__ total_computed max_expected + +(** Test that the amount of the liquidity baking subsidy is epsilon smaller than + 1/16th of the maximum reward. *) +let liquidity_baking_subsidy_param () = + let open Lwt_result_wrap_syntax in + let constants = Default_parameters.constants_mainnet in + let get_reward = + Protocol.Alpha_context.Delegate.Rewards.For_RPC.reward_from_constants + constants + in + let*?@ baking_reward_bonus_per_slot = + get_reward ~reward_kind:Baking_reward_bonus_per_slot + in + let*? baking_reward_bonus = + baking_reward_bonus_per_slot + *? Int64.of_int (constants.consensus_committee_size / 3) + in + let*?@ baking_reward_fixed_portion = + get_reward ~reward_kind:Baking_reward_fixed_portion + in + let*? baking_rewards = baking_reward_fixed_portion +? baking_reward_bonus in + let*?@ attesting_reward_per_slot = + get_reward ~reward_kind:Attesting_reward_per_slot + in + let*? validators_rewards = + attesting_reward_per_slot *? Int64.of_int constants.consensus_committee_size + in + let*? total_rewards = baking_rewards +? validators_rewards in + let expected_subsidy = total_rewards /! 16L in + let*?@ liquidity_baking_subsidy = + Protocol.Alpha_context.Delegate.Rewards.For_RPC + .liquidity_baking_subsidy_from_constants + constants + in + let*? diff = liquidity_baking_subsidy -? expected_subsidy in + let max_diff = 1000 (* mutez *) in + Assert.leq_int ~loc:__LOC__ (Int64.to_int (to_mutez diff)) max_diff + +let tests = + [ + Tztest.tztest + "sc_rollup constants consistency" + `Quick + test_sc_rollup_constants_consistency; + Tztest.tztest "constants consistency" `Quick test_constants_consistency; + Tztest.tztest "max_operations_ttl" `Quick test_max_operations_ttl; + Tztest.tztest + "sc rollup challenge window less than max lookahead" + `Quick + test_sc_rollup_challenge_window_lt_max_lookahead; + Tztest.tztest + "sc rollup max commitment storage cost less than deposit" + `Quick + test_sc_rollup_max_commitment_storage_cost_lt_deposit; + Tztest.tztest + "sc rollup commitment storage size correct" + `Quick + test_sc_rollup_max_commitment_storage_size; + Tztest.tztest + "test liquidity_baking_subsidy parameter is 1/16th of total baking \ + rewards" + `Quick + liquidity_baking_subsidy_param; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("test constants", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_frozen_bonds.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_frozen_bonds.ml new file mode 100644 index 000000000000..07aaef27c6c7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_frozen_bonds.ml @@ -0,0 +1,768 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (token) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_frozen_bonds.ml + Subject: Frozen bonds applicable to contracts and part of their stake. +*) + +open Protocol +open Alpha_context +open Test_tez + +let big_random_amount () = + match Tez.of_mutez (Int64.add 100_000L (Random.int64 1_000_000L)) with + | None -> assert false + | Some x -> x + +let small_random_amount () = + match Tez.of_mutez (Int64.add 1_000L (Random.int64 10_000L)) with + | None -> assert false + | Some x -> x + +let very_small_random_amount () = + match Tez.of_mutez (Int64.add 1L (Random.int64 100L)) with + | None -> assert false + | Some x -> x + +let nonce_zero = + Origination_nonce.Internal_for_tests.initial Operation_hash.zero + +let mk_sc_rollup ?(nonce = nonce_zero) () = + ( Sc_rollup.Internal_for_tests.originated_sc_rollup nonce, + Origination_nonce.Internal_for_tests.incr nonce ) + +(** Creates a context with a single account. Returns the context and the public + key hash of the account. *) +let create_context () = + let open Lwt_result_syntax in + let (Parameters.{public_key_hash; _} as bootstrap_account) = + Account.(new_account () |> make_bootstrap_account) + in + let+ ctxt = Block.alpha_context [bootstrap_account] in + (ctxt, public_key_hash) + +(** Creates a context, a user contract, and a delegate. + Returns the context, the user contract, the user account, and the + delegate's pkh. *) +let init_test ~user_is_delegate = + let open Lwt_result_wrap_syntax in + let* ctxt, _ = create_context () in + let delegate, delegate_pk, _ = Signature.generate_key () in + let delegate_contract = Contract.Implicit delegate in + let delegate_account = `Contract (Contract.Implicit delegate) in + let user_contract = + if user_is_delegate then delegate_contract + else + let user, _, _ = Signature.generate_key () in + Contract.Implicit user + in + let user_account = `Contract user_contract in + (* Allocate contracts for user and delegate. *) + let user_balance = big_random_amount () in + let*@ ctxt, _ = Token.transfer ctxt `Minted user_account user_balance in + let delegate_balance = big_random_amount () in + let*@ ctxt, _ = + Token.transfer ctxt `Minted delegate_account delegate_balance + in + (* Configure delegate, as a delegate by self-delegation, for which + revealing its manager key is a prerequisite. *) + let*@ ctxt = Contract.reveal_manager_key ctxt delegate delegate_pk in + let*@ ctxt = Contract.Delegate.set ctxt delegate_contract (Some delegate) in + return (ctxt, user_contract, user_account, delegate) + +(** Tested scenario : + 1. user contract delegates to 'delegate', + 2. freeze a deposit, + 3. check that staking balance of delegate has not changed, + 4. remove delegation, + 5. check staking balance decreased accordingly, + 6. unfreeze the deposit, + 7. check that staking balance is unchanged, + 8. check that user's balance is unchanged. *) +let test_delegate_then_freeze_deposit () = + let open Lwt_result_wrap_syntax in + let* ctxt, user_contract, user_account, delegate = + init_test ~user_is_delegate:false + in + (* Fetch user's initial balance before freeze. *) + let*@ ctxt, user_balance = + Token.Internal_for_tests.balance ctxt user_account + in + (* Let user delegate to "delegate". *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract (Some delegate) in + (* Fetch staking balance after delegation and before freeze. *) + let*@ staking_balance = Delegate.For_RPC.staking_balance ctxt delegate in + (* Freeze a sc-rollup deposit. *) + let sc_rollup, _ = mk_sc_rollup () in + let bond_id = Bond_id.Sc_rollup_bond_id sc_rollup in + let deposit_amount = small_random_amount () in + let deposit_account = `Frozen_bonds (user_contract, bond_id) in + let*@ ctxt, _ = + Token.transfer ctxt user_account deposit_account deposit_amount + in + (* Fetch staking balance after freeze. *) + let*@ staking_balance' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Ensure staking balance did not change. *) + let* () = Assert.equal_tez ~loc:__LOC__ staking_balance' staking_balance in + (* Remove delegation. *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract None in + (* Fetch staking balance after delegation removal. *) + let*@ staking_balance'' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Ensure staking balance decreased by user's initial balance. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + staking_balance'' + (staking_balance' -! user_balance) + in + (* Unfreeze the deposit. *) + let*@ ctxt, _ = + Token.transfer ctxt deposit_account user_account deposit_amount + in + (* Fetch staking balance of delegate. *) + let*@ staking_balance''' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Ensure that staking balance is unchanged. *) + let* () = + Assert.equal_tez ~loc:__LOC__ staking_balance''' staking_balance'' + in + (* Fetch user's balance again. *) + let*@ _, user_balance' = Token.Internal_for_tests.balance ctxt user_account in + (* Ensure user's balance is unchanged. *) + Assert.equal_tez ~loc:__LOC__ user_balance' user_balance + +(** Tested scenario: + 1. freeze a deposit, + 2. user contract delegate to 'delegate', + 3. check that staking balance of delegate has increased as expected, + 4. unfreeze the deposit, + 5. check that staking balance has not changed, + 6. remove delegation, + 7. check that staking balance has decreased as expected, + 8. check that the user's balance is unchanged. *) +let test_freeze_deposit_then_delegate () = + let open Lwt_result_wrap_syntax in + let* ctxt, user_contract, user_account, delegate = + init_test ~user_is_delegate:false + in + (* Fetch user's initial balance before freeze. *) + let*@ ctxt, user_balance = + Token.Internal_for_tests.balance ctxt user_account + in + (* Freeze a sc-rollup deposit. *) + let sc_rollup, _ = mk_sc_rollup () in + let bond_id = Bond_id.Sc_rollup_bond_id sc_rollup in + let deposit_amount = small_random_amount () in + let deposit_account = `Frozen_bonds (user_contract, bond_id) in + let*@ ctxt, _ = + Token.transfer ctxt user_account deposit_account deposit_amount + in + (* Here, user balance has decreased. + Now, fetch staking balance before delegation and after freeze. *) + let*@ staking_balance = Delegate.For_RPC.staking_balance ctxt delegate in + (* Let user delegate to "delegate". *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract (Some delegate) in + (* Fetch staking balance after delegation. *) + let*@ staking_balance' = Delegate.For_RPC.staking_balance ctxt delegate in + (* ensure staking balance increased by the user's balance. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + staking_balance' + (user_balance +! staking_balance) + in + (* Unfreeze the deposit. *) + let*@ ctxt, _ = + Token.transfer ctxt deposit_account user_account deposit_amount + in + (* Fetch staking balance after unfreeze. *) + let*@ staking_balance'' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Ensure that staking balance is unchanged. *) + let* () = Assert.equal_tez ~loc:__LOC__ staking_balance'' staking_balance' in + (* Remove delegation. *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract None in + (* Fetch staking balance. *) + let*@ staking_balance''' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Check that staking balance has decreased by the user's initial balance. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + staking_balance''' + (staking_balance'' -! user_balance) + in + (* Fetch user's balance. *) + let*@ _, user_balance' = Token.Internal_for_tests.balance ctxt user_account in + (* Ensure user's balance is unchanged. *) + Assert.equal_tez ~loc:__LOC__ user_balance' user_balance + +(** Tested scenario: + 1. freeze a deposit (with deposit amount = balance), + 2. check that the user contract is still allocated, + 3. punish the user contract, + 4. check that the user contract is unallocated, except if it's a delegate. *) +let test_allocated_when_frozen_deposits_exists ~user_is_delegate () = + let open Lwt_result_wrap_syntax in + let* ctxt, user_contract, user_account, _delegate = + init_test ~user_is_delegate + in + (* Fetch user's initial balance before freeze. *) + let*@ ctxt, user_balance = + Token.Internal_for_tests.balance ctxt user_account + in + let* () = Assert.equal_bool ~loc:__LOC__ Tez.(user_balance > zero) true in + (* Freeze a sc-rollup deposit. *) + let sc_rollup, _ = mk_sc_rollup () in + let bond_id = Bond_id.Sc_rollup_bond_id sc_rollup in + let deposit_amount = user_balance in + let deposit_account = `Frozen_bonds (user_contract, bond_id) in + let*@ ctxt, _ = + Token.transfer ctxt user_account deposit_account deposit_amount + in + (* Check that user contract is still allocated, despite a null balance. *) + let*@ ctxt, balance = Token.Internal_for_tests.balance ctxt user_account in + let* () = Assert.equal_tez ~loc:__LOC__ balance Tez.zero in + let*@ ctxt, user_allocated = + Token.Internal_for_tests.allocated ctxt (user_account :> Token.container) + in + let*@ ctxt, dep_allocated = + Token.Internal_for_tests.allocated ctxt deposit_account + in + let* () = + Assert.equal_bool ~loc:__LOC__ (user_allocated && dep_allocated) true + in + (* Punish the user contract. *) + let*@ ctxt, _ = Token.transfer ctxt deposit_account `Burned deposit_amount in + (* Check that user and deposit accounts have been unallocated. *) + let*@ ctxt, user_allocated = + Token.Internal_for_tests.allocated ctxt (user_account :> Token.container) + in + let*@ _, dep_allocated = + Token.Internal_for_tests.allocated ctxt deposit_account + in + if user_is_delegate then + Assert.equal_bool ~loc:__LOC__ (user_allocated && not dep_allocated) true + else Assert.equal_bool ~loc:__LOC__ (user_allocated || dep_allocated) false + +(** Tested scenario: + 1. freeze two deposits for the user contract, + 2. check that the stake of the user contract is balance + two deposits, + 3. punish for one of the deposits, + 4. check that the stake of the user contract balance + deposit, + 5. punish for the other deposit, + 6. check that the stake of the user contract is equal to balance. *) +let test_total_stake ~user_is_delegate () = + let open Lwt_result_wrap_syntax in + let* ctxt, user_contract, user_account, _delegate = + init_test ~user_is_delegate + in + (* Fetch user's initial balance before freeze. *) + let*@ ctxt, user_balance = + Token.Internal_for_tests.balance ctxt user_account + in + let* () = Assert.equal_bool ~loc:__LOC__ Tez.(user_balance > zero) true in + (* Freeze 2 sc-rollup deposits. *) + let sc_rollup, nonce = mk_sc_rollup () in + let bond_id1 = Bond_id.Sc_rollup_bond_id sc_rollup in + let sc_rollup, _ = mk_sc_rollup ~nonce () in + let bond_id2 = Bond_id.Sc_rollup_bond_id sc_rollup in + let deposit_amount = small_random_amount () in + let deposit_account1 = `Frozen_bonds (user_contract, bond_id1) in + let*@ ctxt, _ = + Token.transfer ctxt user_account deposit_account1 deposit_amount + in + let deposit_account2 = `Frozen_bonds (user_contract, bond_id2) in + let*@ ctxt, _ = + Token.transfer ctxt user_account deposit_account2 deposit_amount + in + (* Test folding on bond ids. *) + let*! bond_ids = + Bond_id.Internal_for_tests.fold_on_bond_ids + ctxt + user_contract + ~init:[] + ~order:`Sorted + ~f:(fun id l -> Lwt.return (id :: l)) + in + let* () = + Assert.assert_equal_list + ~loc:__LOC__ + (fun id1 id2 -> Bond_id.compare id1 id2 = 0) + "Unexpected bond identifiers." + Bond_id.pp + (List.sort Bond_id.compare bond_ids) + (List.sort Bond_id.compare [bond_id1; bond_id2]) + in + (* Check that the stake of user contract is balance + two deposits. *) + let*@ stake = Contract.get_balance_and_frozen_bonds ctxt user_contract in + let*@ frozen_bonds = Contract.get_frozen_bonds ctxt user_contract in + let*@ ctxt, balance = Token.Internal_for_tests.balance ctxt user_account in + let* () = Assert.equal_tez ~loc:__LOC__ (stake -! balance) frozen_bonds in + let* () = + Assert.equal_tez ~loc:__LOC__ (stake -! balance) (deposit_amount *! 2L) + in + (* Punish for one deposit. *) + let*@ ctxt, _ = Token.transfer ctxt deposit_account2 `Burned deposit_amount in + (* Check that stake of contract is balance + deposit. *) + let*@ stake = Contract.get_balance_and_frozen_bonds ctxt user_contract in + let*@ frozen_bonds = Contract.get_frozen_bonds ctxt user_contract in + let* () = Assert.equal_tez ~loc:__LOC__ (stake -! balance) frozen_bonds in + let* () = Assert.equal_tez ~loc:__LOC__ (stake -! balance) deposit_amount in + (* Punish for the other deposit. *) + let*@ ctxt, _ = Token.transfer ctxt deposit_account1 `Burned deposit_amount in + (* Check that stake of contract is equal to balance. *) + let*@ stake = Contract.get_balance_and_frozen_bonds ctxt user_contract in + Assert.equal_tez ~loc:__LOC__ stake balance + +let check_delegated_balance_is ctxt ~loc delegate expected_balance = + let open Lwt_result_wrap_syntax in + (* Fetch the delegated balance of d. *) + let*@ delegated_balance = Delegate.For_RPC.delegated_balance ctxt delegate in + (* Check that the delegated balance of [delegate] is as explected. *) + Assert.equal_tez ~loc delegated_balance expected_balance + +(** Tested scenario: + 1. freeze some bonds for the delegate, + 2. check that the delegated balance is null, + 3. let user contract delegate to 'delegate', + 4. check that the staking balance of 'delegate' has increased as expected, + 5. check that the delegated balance of 'delegate' is equal to the balance of the delegator, + 6. unfreeze the bonds, + 7. check that the staking balance has not changed, + 8. check that the delegated balance of 'delegate' is equal to the balance of the delegator, + 9. remove the delegation, + 10. check that staking balance has decreased as expected, + 11. check that the delegated balance is null, + 12. check that the user's balance is unchanged. *) +let test_delegated_balance () = + let open Lwt_result_wrap_syntax in + let* ctxt, user_contract, user_account, delegate = + init_test ~user_is_delegate:false + in + let delegate_contract = Contract.Implicit delegate in + let delegate_account = `Contract delegate_contract in + (* Fetch user's initial balance before freeze. *) + let*@ ctxt, user_balance = + Token.Internal_for_tests.balance ctxt user_account + in + (* Fetch staking balance before freeze. *) + let*@ staking_balance = Delegate.For_RPC.staking_balance ctxt delegate in + (* Freeze a sc-rollup deposit for the delegate. *) + let sc_rollup, _ = mk_sc_rollup () in + let bond_id = Bond_id.Sc_rollup_bond_id sc_rollup in + let deposit_amount = small_random_amount () in + let deposit_account = `Frozen_bonds (delegate_contract, bond_id) in + let*@ ctxt, _ = + Token.transfer ctxt delegate_account deposit_account deposit_amount + in + (* Check that the delegated balance of [delegate] is null. *) + let* () = check_delegated_balance_is ctxt ~loc:__LOC__ delegate Tez.zero in + (* Let user delegate to "delegate". *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract (Some delegate) in + (* Fetch staking balance after delegation. *) + let*@ staking_balance' = Delegate.For_RPC.staking_balance ctxt delegate in + (* ensure staking balance increased by the user's balance. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + staking_balance' + (user_balance +! staking_balance) + in + (* Check that the delegated balance of [delegate] is equal to [user_balance]. *) + let* () = + check_delegated_balance_is ctxt ~loc:__LOC__ delegate user_balance + in + (* Unfreeze the deposit. *) + let*@ ctxt, _ = + Token.transfer ctxt deposit_account delegate_account deposit_amount + in + (* Fetch staking balance after unfreeze. *) + let*@ staking_balance'' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Ensure that staking balance is unchanged. *) + let* () = Assert.equal_tez ~loc:__LOC__ staking_balance'' staking_balance' in + (* Check that the delegated balance of [delegate] is equal to [user_balance]. *) + let* () = + check_delegated_balance_is ctxt ~loc:__LOC__ delegate user_balance + in + (* Remove delegation. *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract None in + (* Fetch staking balance. *) + let*@ staking_balance''' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Check that staking balance has decreased by the user's initial balance. *) + let* () = + Assert.equal_tez + ~loc:__LOC__ + staking_balance''' + (staking_balance'' -! user_balance) + in + (* Check that the delegated balance of [delegate] is null. *) + let* () = check_delegated_balance_is ctxt ~loc:__LOC__ delegate Tez.zero in + (* Fetch user's balance. *) + let*@ _, user_balance' = Token.Internal_for_tests.balance ctxt user_account in + (* Ensure user's balance is unchanged. *) + Assert.equal_tez ~loc:__LOC__ user_balance' user_balance + +(** Tests that the rpcs [contract/pkh/frozen_bonds] and + [contract/pkh/balance_and_frozen_bonds] can be called successfully. + These rpcs call the functions [Contract.get_frozen_bonds] and + [Contract.get_balance_and_frozen_bonds] already tested in previous tests. *) +let test_rpcs () = + let open Lwt_result_syntax in + let* blk, contract = Context.init1 () in + let* frozen_bonds = Context.Contract.frozen_bonds (B blk) contract in + let* () = Assert.equal_tez ~loc:__LOC__ frozen_bonds Tez.zero in + let* balance_and_frozen_bonds = + Context.Contract.balance_and_frozen_bonds (B blk) contract + in + let* balance = Context.Contract.balance (B blk) contract in + Assert.equal_tez ~loc:__LOC__ balance_and_frozen_bonds balance + +(** A helper to test a particular delegation/freezing scenario *) +let test_scenario scenario = + let open Lwt_result_wrap_syntax in + let* ctxt, user_contract, user_account, delegate1 = + init_test ~user_is_delegate:false + in + let delegate2, delegate_pk2, _ = Signature.generate_key () in + let delegate_contract2 = Contract.Implicit delegate2 in + let delegate_account2 = `Contract delegate_contract2 in + let delegate_balance2 = big_random_amount () in + let*@ ctxt, _ = + Token.transfer ctxt `Minted delegate_account2 delegate_balance2 + in + (* Configure delegate, as a delegate by self-delegation, for which + revealing its manager key is a prerequisite. *) + let*@ ctxt = Contract.reveal_manager_key ctxt delegate2 delegate_pk2 in + let*@ ctxt = Contract.Delegate.set ctxt delegate_contract2 (Some delegate2) in + let sc_rollup1, nonce = mk_sc_rollup () in + let sc_rollup2, _ = mk_sc_rollup ~nonce () in + let bond_id1 = Bond_id.Sc_rollup_bond_id sc_rollup1 in + let bond_id2 = Bond_id.Sc_rollup_bond_id sc_rollup2 in + let deposit_amount = Tez.of_mutez_exn 1000L in + let deposit_account1 = `Frozen_bonds (user_contract, bond_id1) in + let deposit_account2 = `Frozen_bonds (user_contract, bond_id2) in + let do_delegate ?(delegate = delegate1) ctxt = + (* Fetch staking balance before delegation *) + let*@ staking_balance = Delegate.For_RPC.staking_balance ctxt delegate in + (* Fetch user's initial balance before delegate. *) + let*@ user_balance = + Contract.get_balance_and_frozen_bonds ctxt user_contract + in + (* Let user delegate to "delegate". *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract (Some delegate) in + (* Fetch staking balance after delegation *) + let*@ staking_balance' = Delegate.For_RPC.staking_balance ctxt delegate in + let+ () = + Assert.equal_tez + ~loc:__LOC__ + staking_balance' + (staking_balance +! user_balance) + in + (ctxt, user_balance) + in + let do_freeze ?(deposit_account = deposit_account1) ctxt = + (* Fetch staking balance before freeze *) + let*@ staking_balance1 = Delegate.For_RPC.staking_balance ctxt delegate1 in + let*@ staking_balance2 = Delegate.For_RPC.staking_balance ctxt delegate2 in + (* Freeze a sc-rollup deposit. *) + let*@ ctxt, _ = + Token.transfer ctxt user_account deposit_account deposit_amount + in + (* Fetch staking balance after freeze. *) + let*@ staking_balance1' = Delegate.For_RPC.staking_balance ctxt delegate1 in + let*@ staking_balance2' = Delegate.For_RPC.staking_balance ctxt delegate2 in + (* Ensure staking balance did not change. *) + let* () = + Assert.equal_tez ~loc:__LOC__ staking_balance1' staking_balance1 + in + let+ () = + Assert.equal_tez ~loc:__LOC__ staking_balance2' staking_balance2 + in + ctxt + in + let do_unfreeze ?(deposit_account = deposit_account1) ctxt = + (* Fetch staking balance before unfreeze *) + let*@ staking_balance1 = Delegate.For_RPC.staking_balance ctxt delegate1 in + let*@ staking_balance2 = Delegate.For_RPC.staking_balance ctxt delegate2 in + (* Unfreeze the deposit *) + let*@ ctxt, _ = + Token.transfer ctxt deposit_account user_account deposit_amount + in + (* Fetch staking balance after unfreeze. *) + let*@ staking_balance1' = Delegate.For_RPC.staking_balance ctxt delegate1 in + let*@ staking_balance2' = Delegate.For_RPC.staking_balance ctxt delegate2 in + (* Ensure staking balance did not change. *) + let* () = + Assert.equal_tez ~loc:__LOC__ staking_balance1' staking_balance1 + in + let+ () = + Assert.equal_tez ~loc:__LOC__ staking_balance2' staking_balance2 + in + ctxt + in + let do_slash ?(deposit_account = deposit_account1) + ?(current_delegate = Some delegate1) ctxt = + (* Fetch staking balance before slash *) + let*@ staking_balance = + match current_delegate with + | None -> return Tez.zero + | Some current_delegate -> + Delegate.For_RPC.staking_balance ctxt current_delegate + in + (* Slash the deposit *) + let*@ ctxt, _ = + Token.transfer + ctxt + deposit_account + `Sc_rollup_refutation_punishments + deposit_amount + in + (* Fetch staking balance after slash. *) + let+ () = + match current_delegate with + | None -> return_unit + | Some current_delegate -> + let*@ staking_balance' = + Delegate.For_RPC.staking_balance ctxt current_delegate + in + (* Ensure balance slashed *) + Assert.equal_tez + ~loc:__LOC__ + staking_balance' + (staking_balance -! deposit_amount) + in + ctxt + in + let do_undelegate ?(delegate = delegate1) ctxt amount = + (* Fetch staking balance before undelegate *) + let*@ staking_balance = Delegate.For_RPC.staking_balance ctxt delegate in + (* Fetch user's initial balance before undelegate. *) + let*@ _, user_balance = + Token.Internal_for_tests.balance ctxt user_account + in + (* Remove delegation. *) + let*@ ctxt = Contract.Delegate.set ctxt user_contract None in + (* Fetch staking balance after delegation removal. *) + let*@ staking_balance' = Delegate.For_RPC.staking_balance ctxt delegate in + (* Ensure staking balance decreased by delegation amount *) + let* () = + Assert.equal_tez ~loc:__LOC__ staking_balance' (staking_balance -! amount) + in + (* Fetch user's balance again. *) + let*@ _, user_balance' = + Token.Internal_for_tests.balance ctxt user_account + in + (* Ensure user's balance unchanged. *) + let+ () = Assert.equal_tez ~loc:__LOC__ user_balance' user_balance in + ctxt + in + let initial_ctxt = ctxt in + (* delegate-then-freeze *) + let* ctxt, amount_delegated = do_delegate ctxt in + let* ctxt = do_freeze ctxt in + let* () = + scenario + ctxt + ~accounts:(deposit_account1, deposit_account2) + ~delegates:(delegate1, delegate2) + amount_delegated + ~do_delegate + ~do_undelegate + ~do_freeze + ~do_unfreeze + ~do_slash + in + (* freeze-then-delegate *) + let ctxt = initial_ctxt in + let* ctxt = do_freeze ctxt in + let* ctxt, amount_delegated = do_delegate ctxt in + scenario + ctxt + ~accounts:(deposit_account1, deposit_account2) + ~delegates:(delegate1, delegate2) + amount_delegated + ~do_delegate + ~do_undelegate + ~do_freeze + ~do_unfreeze + ~do_slash + +let test_delegate_freeze_unfreeze_undelegate () = + let open Lwt_result_syntax in + test_scenario + (fun + ctxt + ~accounts:_ + ~delegates:_ + amount_delegated + ~do_delegate:_ + ~do_undelegate + ~do_freeze:_ + ~do_unfreeze + ~do_slash:_ + -> + let* ctxt = do_unfreeze ctxt in + let* (_ : context) = do_undelegate ctxt amount_delegated in + return_unit) + +let test_delegate_freeze_undelegate_unfreeze () = + let open Lwt_result_syntax in + test_scenario + (fun + ctxt + ~accounts:_ + ~delegates:_ + amount_delegated + ~do_delegate:_ + ~do_undelegate + ~do_freeze:_ + ~do_unfreeze + ~do_slash:_ + -> + let* ctxt = do_undelegate ctxt amount_delegated in + let* (_ : context) = do_unfreeze ctxt in + return_unit) + +let test_delegate_double_freeze_undelegate_unfreeze () = + let open Lwt_result_syntax in + test_scenario + (fun + ctxt + ~accounts:(deposit_account1, deposit_account2) + ~delegates:_ + amount_delegated + ~do_delegate:_ + ~do_undelegate + ~do_freeze + ~do_unfreeze + ~do_slash:_ + -> + let* ctxt = do_freeze ~deposit_account:deposit_account2 ctxt in + let* ctxt = do_undelegate ctxt amount_delegated in + let* (_ : context) = do_unfreeze ~deposit_account:deposit_account1 ctxt in + return_unit) + +let test_delegate_freeze_redelegate_unfreeze () = + let open Lwt_result_syntax in + test_scenario + (fun + ctxt + ~accounts:_ + ~delegates:(_delegate1, delegate2) + _amount_delegated + ~do_delegate + ~do_undelegate + ~do_freeze:_ + ~do_unfreeze + ~do_slash:_ + -> + let* ctxt, amount2 = do_delegate ~delegate:delegate2 ctxt in + let* ctxt = do_unfreeze ctxt in + let* (_ : context) = do_undelegate ~delegate:delegate2 ctxt amount2 in + return_unit) + +let test_delegate_freeze_unfreeze_freeze_redelegate () = + let open Lwt_result_syntax in + test_scenario + (fun + ctxt + ~accounts:_ + ~delegates:(_delegate1, delegate2) + _amount_delegated + ~do_delegate + ~do_undelegate + ~do_freeze + ~do_unfreeze + ~do_slash:_ + -> + let* ctxt = do_unfreeze ctxt in + let* ctxt = do_freeze ctxt in + let* ctxt, amount2 = do_delegate ~delegate:delegate2 ctxt in + let* (_ : context) = do_undelegate ~delegate:delegate2 ctxt amount2 in + return_unit) + +let test_delegate_freeze_slash_undelegate () = + let open Lwt_result_syntax in + let slash_amount = Tez.of_mutez_exn 1000L in + test_scenario + (fun + ctxt + ~accounts:_ + ~delegates:_ + amount_delegated + ~do_delegate:_ + ~do_undelegate + ~do_freeze:_ + ~do_unfreeze:_ + ~do_slash + -> + let* ctxt = do_slash ctxt in + let* (_ : context) = + do_undelegate ctxt (amount_delegated -! slash_amount) + in + return_unit) + +let tests = + Tztest. + [ + tztest + "frozen bonds - delegate then freeze" + `Quick + test_delegate_then_freeze_deposit; + tztest + "frozen bonds - freeze then delegate" + `Quick + test_freeze_deposit_then_delegate; + tztest + "frozen bonds - contract remains allocated, user is not a delegate" + `Quick + (test_allocated_when_frozen_deposits_exists ~user_is_delegate:false); + tztest + "frozen bonds - contract remains allocated, user is a delegate" + `Quick + (test_allocated_when_frozen_deposits_exists ~user_is_delegate:true); + tztest + "frozen bonds - total stake, user is not a delegate" + `Quick + (test_total_stake ~user_is_delegate:false); + tztest + "frozen bonds - total stake, user is a delegate" + `Quick + (test_total_stake ~user_is_delegate:true); + tztest "frozen bonds - delegated balance" `Quick test_delegated_balance; + tztest "frozen bonds - test rpcs" `Quick test_rpcs; + tztest + "delegate, freeze, unfreeze, undelegate" + `Quick + test_delegate_freeze_unfreeze_undelegate; + tztest + "delegate, freeze, undelegate, unfreeze" + `Quick + test_delegate_freeze_undelegate_unfreeze; + tztest + "delegate, double freeze, undelegate, unfreeze" + `Quick + test_delegate_double_freeze_undelegate_unfreeze; + tztest + "delegate, freeze, redelegate, unfreeze" + `Quick + test_delegate_freeze_redelegate_unfreeze; + tztest + "delegate, freeze, unfreeze, freeze, redelegate" + `Quick + test_delegate_freeze_unfreeze_freeze_redelegate; + tztest + "delegate, freeze, slash, undelegate" + `Quick + test_delegate_freeze_slash_undelegate; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("frozen bonds", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_liquidity_baking.ml new file mode 100644 index 000000000000..198579d3a511 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_liquidity_baking.ml @@ -0,0 +1,657 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: liquidity baking + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_liquidity_baking.ml + Subject: Test liquidity baking subsidies, CPMM storage updates, + and toggle vote. +*) + +open Liquidity_baking_machine +open Protocol +open Test_tez + +let generate_init_state () = + let open Lwt_result_syntax in + let cpmm_min_xtz_balance = 10_000_000L in + let cpmm_min_tzbtc_balance = 100_000 in + let accounts_balances = + [ + {xtz = 1_000_000L; tzbtc = 1; liquidity = 100}; + {xtz = 1_000L; tzbtc = 1000; liquidity = 100}; + {xtz = 40_000_000L; tzbtc = 350000; liquidity = 300}; + ] + in + let* _, _ = + ValidationMachine.build + {cpmm_min_xtz_balance; cpmm_min_tzbtc_balance; accounts_balances} + in + return_unit + +(* The script hash of + + https://gitlab.com/dexter2tz/dexter2tz/-/blob/d98643881fe14996803997f1283e84ebd2067e35/dexter.liquidity_baking.mligo.tz +*) +let expected_cpmm_hash = + Script_expr_hash.of_b58check_exn + "exprvEBYbxZruLZ9aUDEC9cUxn5KUj361xsaZXGfCxogFoKQ1er9Np" + +(* The script hash of + + https://gitlab.com/dexter2tz/dexter2tz/-/blob/d98643881fe14996803997f1283e84ebd2067e35/lqt_fa12.mligo.tz +*) +let expected_lqt_hash = + Script_expr_hash.of_b58check_exn + "exprufAK15C2FCbxGLCEVXFe26p3eQdYuwZRk1morJUwy9NBUmEZVB" + +(* Test that the scripts of the Liquidity Baking contracts (CPMM and LQT) have the expected hashes. *) +let liquidity_baking_origination () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* cpmm_address = Context.get_liquidity_baking_cpmm_address (B blk) in + let* cpmm_hash = Context.Contract.script_hash (B blk) cpmm_address in + let lqt_address = + Contract_hash.of_b58check_exn "KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + in + let* lqt_hash = Context.Contract.script_hash (B blk) lqt_address in + let* () = + Assert.equal + ~loc:__LOC__ + Script_expr_hash.equal + "Unexpected CPMM script." + Script_expr_hash.pp + cpmm_hash + expected_cpmm_hash + in + let* () = + Assert.equal + ~loc:__LOC__ + Script_expr_hash.equal + "Unexpected LQT script." + Script_expr_hash.pp + lqt_hash + expected_lqt_hash + in + return_unit + +(* Test that the CPMM address in storage is correct *) +let liquidity_baking_cpmm_address () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let* () = + Assert.equal + ~loc:__LOC__ + String.equal + "CPMM address in storage is incorrect" + Format.pp_print_string + (Contract_hash.to_b58check liquidity_baking) + "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" + in + return_unit + +(* Test that after [n] blocks, the liquidity baking CPMM contract is credited [n] times the subsidy amount. *) +let liquidity_baking_subsidies n () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let liquidity_baking = Alpha_context.Contract.Originated liquidity_baking in + let* old_balance = Context.Contract.balance (B blk) liquidity_baking in + let* blk = Block.bake_n n blk in + let* liquidity_baking_subsidy = + Context.get_liquidity_baking_subsidy (B blk) + in + let*? expected_credit = liquidity_baking_subsidy *? Int64.(of_int n) in + let* () = + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + liquidity_baking + old_balance + expected_credit + in + return_unit + +(* Test that subsidy shuts off at correct level alternating baking + blocks with liquidity_baking_toggle_vote set to [Per_block_vote_on], [Per_block_vote_off], and [Per_block_vote_pass] followed by [bake_after_toggle] blocks with it set to [Per_block_vote_pass]. *) +(* Expected level is roughly 2*(log(1-1/(2*p)) / log(0.999)) where [p] is the proportion [Per_block_vote_off / (Per_block_vote_on + Per_block_vote_off)]. *) +let liquidity_baking_toggle ~n_vote_on ~n_vote_off ~n_vote_pass expected_level + bake_after () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let liquidity_baking = Alpha_context.Contract.Originated liquidity_baking in + let* old_balance = Context.Contract.balance (B blk) liquidity_baking in + let* liquidity_baking_subsidy = + Context.get_liquidity_baking_subsidy (B blk) + in + let rec bake_stopping blk i = + if i < expected_level then + let* blk = + Block.bake_n + ~liquidity_baking_toggle_vote:Per_block_vote_on + n_vote_on + blk + in + let* blk = + Block.bake_n + ~liquidity_baking_toggle_vote:Per_block_vote_off + n_vote_off + blk + in + let* blk = + Block.bake_n + ~liquidity_baking_toggle_vote:Per_block_vote_pass + n_vote_pass + blk + in + bake_stopping blk (i + n_vote_on + n_vote_off + n_vote_pass) + else return blk + in + let* blk = bake_stopping blk 0 in + let* balance = Context.Contract.balance (B blk) liquidity_baking in + let* blk = + Block.bake_n + ~liquidity_baking_toggle_vote:Per_block_vote_pass + bake_after + blk + in + let* () = Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance in + let*? expected_final_balance = + liquidity_baking_subsidy *? Int64.of_int (expected_level - 1) + in + let* () = + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + liquidity_baking + old_balance + expected_final_balance + in + return_unit + +(* 100% of blocks have liquidity_baking_toggle_vote = Per_block_vote_off *) +let liquidity_baking_toggle_100 n () = + liquidity_baking_toggle ~n_vote_on:0 ~n_vote_off:1 ~n_vote_pass:0 1386 n () + +(* 80% of blocks have liquidity_baking_toggle_vote = Per_block_vote_off *) +let liquidity_baking_toggle_80 n () = + liquidity_baking_toggle ~n_vote_on:1 ~n_vote_off:4 ~n_vote_pass:0 1963 n () + +(* 60% of blocks have liquidity_baking_toggle_vote = Per_block_vote_off *) +let liquidity_baking_toggle_60 n () = + liquidity_baking_toggle ~n_vote_on:2 ~n_vote_off:3 ~n_vote_pass:0 3583 n () + +(* 50% of blocks have liquidity_baking_toggle_vote = Per_block_vote_off. + Subsidy should not be stopped. + Bakes until 100 blocks after the test sunset level of 4096 used in previous protocols. *) +let liquidity_baking_toggle_50 () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let liquidity_baking = Alpha_context.Contract.Originated liquidity_baking in + let* old_balance = Context.Contract.balance (B blk) liquidity_baking in + let* liquidity_baking_subsidy = + Context.get_liquidity_baking_subsidy (B blk) + in + let rec bake_stopping blk i = + if i < 4196 then + let* blk = + Block.bake ~liquidity_baking_toggle_vote:Per_block_vote_on blk + in + let* blk = + Block.bake ~liquidity_baking_toggle_vote:Per_block_vote_off blk + in + bake_stopping blk (i + 2) + else return blk + in + let* blk = bake_stopping blk 0 in + let* balance = Context.Contract.balance (B blk) liquidity_baking in + let* () = Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance in + let*? expected_final_balance = + liquidity_baking_subsidy *? Int64.of_int 4196 + in + let* () = + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + liquidity_baking + old_balance + expected_final_balance + in + return_unit + +(* Test that the subsidy can restart if Per_block_vote_on votes regain majority. + Bake n_votes with Per_block_vote_off, check that the subsidy is paused, bake + n_votes with Per_block_vote_on, check that the subsidy flows. +*) +let liquidity_baking_restart n_votes n () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let liquidity_baking = Alpha_context.Contract.Originated liquidity_baking in + let* blk = + Block.bake_n ~liquidity_baking_toggle_vote:Per_block_vote_off n_votes blk + in + let* balance_when_paused = + Context.Contract.balance (B blk) liquidity_baking + in + let* blk = + Block.bake_n ~liquidity_baking_toggle_vote:Per_block_vote_pass n blk + in + let* () = + Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance_when_paused + in + let* blk = + Block.bake_n ~liquidity_baking_toggle_vote:Per_block_vote_on n_votes blk + in + let* balance_when_restarted = + Context.Contract.balance (B blk) liquidity_baking + in + let* blk = + Block.bake_n ~liquidity_baking_toggle_vote:Per_block_vote_pass n blk + in + let* liquidity_baking_subsidy = + Context.get_liquidity_baking_subsidy (B blk) + in + let*? expected_balance = liquidity_baking_subsidy *? Int64.of_int n in + let* () = + Assert.balance_was_credited + ~loc:__LOC__ + (B blk) + liquidity_baking + balance_when_restarted + expected_balance + in + return_unit + +(* Test that the toggle EMA in block metadata is correct. *) +let liquidity_baking_toggle_ema n_vote_on n_vote_off level bake_after + expected_toggle_ema () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let rec bake_escaping blk i = + if i < level then + let* blk = + Block.bake_n + ~liquidity_baking_toggle_vote:Per_block_vote_on + n_vote_on + blk + in + let* blk = + Block.bake_n + ~liquidity_baking_toggle_vote:Per_block_vote_off + n_vote_off + blk + in + bake_escaping blk (i + n_vote_on + n_vote_off) + else return blk + in + let* blk = bake_escaping blk 0 in + (* We only need to return the toggle EMA at the end. *) + let* _blk, toggle_ema = + Block.bake_n_with_liquidity_baking_toggle_ema bake_after blk + in + let* () = + Assert.leq_int + ~loc:__LOC__ + (toggle_ema + |> Alpha_context.Per_block_votes.Liquidity_baking_toggle_EMA.to_int32 + |> Int32.to_int) + expected_toggle_ema + in + return_unit + +(* With no bakers setting the toggle vote, EMA should be zero. *) +let liquidity_baking_toggle_ema_zero () = + liquidity_baking_toggle_ema 0 0 0 100 0 () + +(* The EMA should be not much over the threshold after the subsidy has been stopped by a toggle vote. We add 1_000_000 to the constant to give room for the last update. *) +let liquidity_baking_toggle_ema_threshold () = + liquidity_baking_toggle_ema 0 1 1386 1 1_001_000_000 () + +let liquidity_baking_storage n () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let* subsidy = Context.get_liquidity_baking_subsidy (B blk) in + let expected_storage = + Expr.from_string + (Printf.sprintf + "Pair 1\n\ + \ %d\n\ + \ 100\n\ + \ \"KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN\"\n\ + \ \"KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo\"" + (100 + (n * Int64.to_int (to_mutez subsidy)))) + in + let* blk = Block.bake_n n blk in + let* storage = Context.Contract.storage (B blk) liquidity_baking in + let to_string expr = + Format.asprintf "%a" Michelson_v1_printer.print_expr expr + in + let* () = + Assert.equal + ~loc:__LOC__ + String.equal + "Storage isn't equal" + Format.pp_print_string + (to_string storage) + (to_string expected_storage) + in + return_unit + +let liquidity_baking_balance_update () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 ~consensus_threshold:0 () in + let* liquidity_baking = Context.get_liquidity_baking_cpmm_address (B blk) in + let* subsidy = Context.get_liquidity_baking_subsidy (B blk) in + let* _blk, balance_updates = Block.bake_n_with_all_balance_updates 128 blk in + let liquidity_baking_updates = + List.filter + (fun el -> + match el with + | Alpha_context.Receipt.Balance_update_item + (Contract (Originated contract), Credited _, Subsidy) -> + Contract_hash.(contract = liquidity_baking) + | _ -> false) + balance_updates + in + let*? credits = + List.fold_left_e + (fun accum + (Alpha_context.Receipt.Balance_update_item (balance, update, _)) -> + match Alpha_context.Receipt.token_of_balance balance with + | Tez -> ( + match update with + | Credited x -> accum +? x + | Debited _ -> assert false) + | _ -> assert false) + (of_int 0) + liquidity_baking_updates + in + let* () = + Assert.equal_int + ~loc:__LOC__ + (Int64.to_int (to_mutez credits)) + (128 * Int64.to_int (to_mutez subsidy)) + in + return_unit + +let get_cpmm_result results = + match results with + | cpmm_result :: _results -> cpmm_result + | _ -> assert false + +let get_lqt_result results = + match results with + | _cpmm_result :: lqt_result :: _results -> lqt_result + | _ -> assert false + +let get_address_in_result result = + match result with + | Apply_results.Origination_result {originated_contracts; _} -> ( + match originated_contracts with [c] -> c | _ -> assert false) + +let get_balance_updates_in_result result = + match result with + | Apply_results.Origination_result {balance_updates; _} -> balance_updates + +let get_balance_update_in_result result = + match get_balance_updates_in_result result with + | [Balance_update_item (Contract _, Credited balance, Protocol_migration)] -> + (balance : Alpha_context.Tez.t) + | [ + _; + _; + _; + _; + _; + Balance_update_item (Contract _, Credited balance, Protocol_migration); + ] -> + balance + | _ -> assert false + +let liquidity_baking_origination_result_cpmm_address () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* cpmm_address_in_storage = + Context.get_liquidity_baking_cpmm_address (B blk) + in + let* _blk, origination_results = + Block.bake_n_with_origination_results 1 blk + in + let result = get_cpmm_result origination_results in + let address = get_address_in_result result in + let* () = + Assert.equal + ~loc:__LOC__ + Contract_hash.equal + "CPMM address in storage is not the same as in origination result" + Contract_hash.pp + address + cpmm_address_in_storage + in + return_unit + +let liquidity_baking_origination_result_cpmm_balance () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* _blk, origination_results = + Block.bake_n_with_origination_results 1 blk + in + let result = get_cpmm_result origination_results in + let balance_update = get_balance_update_in_result result in + let* () = Assert.equal_tez ~loc:__LOC__ balance_update (of_mutez_exn 100L) in + return_unit + +let liquidity_baking_origination_result_lqt_address () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* _blk, origination_results = + Block.bake_n_with_origination_results 1 blk + in + let result = get_lqt_result origination_results in + let address = get_address_in_result result in + let* () = + Assert.equal + ~loc:__LOC__ + String.equal + "LQT address in origination result is incorrect" + Format.pp_print_string + (Contract_hash.to_b58check address) + "KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + in + return_unit + +let liquidity_baking_origination_result_lqt_balance () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* _blk, origination_results = + Block.bake_n_with_origination_results 1 blk + in + let result = get_lqt_result origination_results in + let balance_updates = get_balance_updates_in_result result in + match balance_updates with + | [ + Balance_update_item + (Liquidity_baking_subsidies, Debited am1, Protocol_migration); + Balance_update_item (Storage_fees, Credited am2, Protocol_migration); + Balance_update_item + (Liquidity_baking_subsidies, Debited am3, Protocol_migration); + Balance_update_item (Storage_fees, Credited am4, Protocol_migration); + ] -> + let* () = Assert.equal_tez ~loc:__LOC__ am1 am2 in + let* () = Assert.equal_tez ~loc:__LOC__ am3 am4 in + let* () = Assert.equal_tez ~loc:__LOC__ am1 (of_mutez_exn 64_250L) in + Assert.equal_tez ~loc:__LOC__ am3 (of_mutez_exn 494_500L) + | _ -> failwith "Unexpected balance updates (%s)" __LOC__ + +(* Test that with no contract at the tzBTC address and the level low enough to indicate we're not on mainnet, three contracts are originated in stitching. *) +let liquidity_baking_origination_test_migration () = + let open Lwt_result_syntax in + let* blk, _contract = Context.init1 () in + let* _blk, origination_results = + Block.bake_n_with_origination_results 1 blk + in + let num_results = List.length origination_results in + Assert.equal_int ~loc:__LOC__ num_results 3 + +(* Test that with no contract at the tzBTC address and the level high enough to indicate we could be on mainnet, no contracts are originated in stitching. *) +let liquidity_baking_origination_no_tzBTC_mainnet_migration () = + let open Lwt_result_syntax in + let* blk, _contract = + Context.init1 ~consensus_threshold:0 ~level:1_437_862l () + in + (* By baking a bit we also check that the subsidy application with no CPMM present does nothing rather than stopping the chain.*) + let* _blk, origination_results = + Block.bake_n_with_origination_results 64 blk + in + let num_results = List.length origination_results in + Assert.equal_int ~loc:__LOC__ num_results 0 + +let tests = + [ + Tztest.tztest + "liquidity baking script hashes" + `Quick + liquidity_baking_origination; + Tztest.tztest + "liquidity baking cpmm is originated at the expected address" + `Quick + liquidity_baking_cpmm_address; + Tztest.tztest "Init Context" `Quick generate_init_state; + Tztest.tztest + "liquidity baking subsidy is correct" + `Quick + (liquidity_baking_subsidies 64); + Tztest.tztest + "liquidity baking toggle vote with 100% of bakers voting \ + Per_block_vote_off baking one block longer" + `Quick + (liquidity_baking_toggle_100 1); + Tztest.tztest + "liquidity baking toggle vote with 100% of bakers voting \ + Per_block_vote_off baking two blocks longer" + `Quick + (liquidity_baking_toggle_100 2); + Tztest.tztest + "liquidity baking toggle vote with 100% of bakers voting \ + Per_block_vote_off baking 100 blocks longer" + `Quick + (liquidity_baking_toggle_100 100); + Tztest.tztest + "liquidity baking toggle vote with 80% of bakers voting \ + Per_block_vote_off baking one block longer" + `Quick + (liquidity_baking_toggle_80 1); + Tztest.tztest + "liquidity baking toggle vote with 80% of bakers voting \ + Per_block_vote_off baking two blocks longer" + `Quick + (liquidity_baking_toggle_80 2); + Tztest.tztest + "liquidity baking toggle vote with 80% of bakers voting \ + Per_block_vote_off baking 100 blocks longer" + `Quick + (liquidity_baking_toggle_80 100); + Tztest.tztest + "liquidity baking toggle vote with 60% of bakers voting \ + Per_block_vote_off baking one block longer" + `Quick + (liquidity_baking_toggle_60 1); + Tztest.tztest + "liquidity baking toggle vote with 60% of bakers voting \ + Per_block_vote_off baking two blocks longer" + `Quick + (liquidity_baking_toggle_60 2); + Tztest.tztest + "liquidity baking toggle vote with 60% of bakers voting \ + Per_block_vote_off baking 100 blocks longer" + `Quick + (liquidity_baking_toggle_60 100); + Tztest.tztest + "liquidity baking does not shut off with toggle vote at 50% and baking \ + 100 blocks longer than sunset level in previous protocols" + `Quick + liquidity_baking_toggle_50; + Tztest.tztest + "liquidity baking restart with 100% of bakers voting off, then pass, \ + then on" + `Quick + (liquidity_baking_restart 2000 1); + Tztest.tztest + "liquidity baking toggle ema in block metadata is zero with no bakers \ + voting Per_block_vote_off." + `Quick + liquidity_baking_toggle_ema_zero; + Tztest.tztest + "liquidity baking toggle ema is equal to the threshold after the subsidy \ + has been stopped by a toggle vote" + `Quick + liquidity_baking_toggle_ema_threshold; + Tztest.tztest + "liquidity baking storage is updated" + `Quick + (liquidity_baking_storage 64); + Tztest.tztest + "liquidity baking balance updates" + `Quick + liquidity_baking_balance_update; + Tztest.tztest + "liquidity baking CPMM address in storage matches address in the \ + origination result" + `Quick + liquidity_baking_origination_result_cpmm_address; + Tztest.tztest + "liquidity baking CPMM balance in origination result is 100 mutez" + `Quick + liquidity_baking_origination_result_cpmm_balance; + Tztest.tztest + "liquidity baking LQT contract is originated at expected address" + `Quick + liquidity_baking_origination_result_lqt_address; + Tztest.tztest + "liquidity baking LQT balance in origination result is 0 mutez" + `Quick + liquidity_baking_origination_result_lqt_balance; + Tztest.tztest + "liquidity baking originates three contracts when tzBTC does not exist \ + and level indicates we are not on mainnet" + `Quick + liquidity_baking_origination_test_migration; + Tztest.tztest + "liquidity baking originates three contracts when tzBTC does not exist \ + and level indicates we might be on mainnet" + `Quick + liquidity_baking_origination_no_tzBTC_mainnet_migration; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("liquidity baking", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_storage.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_storage.ml new file mode 100644 index 000000000000..f5158271a4eb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_storage.ml @@ -0,0 +1,242 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Context Storage + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_storage.ml + Subject: Test the correctnesss of debug message from storage_functor + *) + +open Protocol +open Storage_functors +open Storage_sigs + +module Int32 = struct + type t = int32 + + let encoding = Data_encoding.int32 + + module Index = struct + type t = int + + let path_length = 1 + + let to_path c l = string_of_int c :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [c] -> int_of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } + end +end + +module Int64 = struct + type t = int64 + + let encoding = Data_encoding.int64 + + module Index = struct + type t = int64 + + let path_length = 1 + + let to_path c l = Int64.to_string c :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [c] -> Int64.of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.int64; + encoding = Data_encoding.int64; + compare = Compare.Int64.compare; + } + end +end + +let create_context name : (module Raw_context.T with type t = Raw_context.t) = + (module Make_subcontext (Registered) (Raw_context) + (struct + let name = [name] + end)) + +let create_subcontext name + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Raw_context.T with type t = Raw_context.t) = + (module Make_subcontext (Registered) (Context) + (struct + let name = [name] + end)) + +let create_single_data_storage name + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Single_data_storage with type t = Context.t and type value = Int32.t) + = + (module Make_single_data_storage (Registered) (Context) + (struct + let name = [name] + end) + (Int32)) + +let create_indexed_subcontext_int32 + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Data_set_storage with type t = Raw_context.t) = + (module Make_data_set_storage (Context) (Int32.Index)) + +let create_indexed_subcontext_int64 + (module Context : Raw_context.T with type t = Raw_context.t) : + (module Data_set_storage with type t = Raw_context.t) = + (module Make_data_set_storage (Context) (Int64.Index)) + +let must_failwith f_prog error = + try + let () = f_prog () in + Alcotest.fail "Unexpected successful result" + with exc -> + if exc = error then Lwt.return_unit + else Alcotest.fail "Unexpected error result" + +(** Test: + + This test check that creating value where value already exists + fails*) +let test_register_single_data () = + let f_prog () = + let context = create_context "context1" in + (create_single_data_storage "single_data" context + :> (module Single_data_storage)) + |> ignore ; + (create_single_data_storage "single_data" context + :> (module Single_data_storage)) + |> ignore + in + let error = + Invalid_argument + "Could not register a value at [context1 / single_data] because of an \ + existing Value." + in + must_failwith f_prog error + +(** Test: + + This test check that creating a subcontext where a value already exists + fails*) +let test_register_named_subcontext () = + let f_prog () = + let context = create_context "context2" in + let subcontext = create_subcontext "sub_context" context in + (create_single_data_storage "error_register" subcontext + :> (module Single_data_storage)) + |> ignore ; + let subcontext = create_subcontext "error_register" subcontext in + (create_single_data_storage "single_data2" subcontext + :> (module Single_data_storage)) + |> ignore + in + let error = + Invalid_argument + "Could not register a named subcontext at [context2 / sub_context / \ + error_register] because of an existing Value." + in + must_failwith f_prog error + +(** Test: + + This test check that creating a indexed subcontext where a value already + exists fails*) +let test_register_indexed_subcontext () = + let f_prog () = + let context = create_context "context3" in + (create_single_data_storage "single_value" context + :> (module Single_data_storage)) + |> ignore ; + (create_indexed_subcontext_int32 context :> (module Data_set_storage)) + |> ignore + in + let error = + Invalid_argument + "Could not register an indexed subcontext at [context3] because of an \ + existing \n\ + single_value Value." + in + must_failwith f_prog error + +(** Test: + + This test check that creating a indexed subcontext where an indexed + subcontext already exists fails*) +let test_register_indexed_subcontext_2 () = + let f_prog () = + let context = create_context "context4" in + (create_indexed_subcontext_int32 context :> (module Data_set_storage)) + |> ignore ; + (create_indexed_subcontext_int64 context :> (module Data_set_storage)) + |> ignore + in + let error = + Invalid_argument + "An indexed subcontext at [context4] already exists but has a different \ + argument: `int64` <> `int`." + in + must_failwith f_prog error + +let tests = + [ + Alcotest_lwt.test_case + "register single data in existing path" + `Quick + (fun _ -> test_register_single_data); + Alcotest_lwt.test_case + "register named subcontext in existing path" + `Quick + (fun _ -> test_register_named_subcontext); + Alcotest_lwt.test_case + "register indexed subcontext in existing path" + `Quick + (fun _ -> test_register_indexed_subcontext); + Alcotest_lwt.test_case + "register indexed subcontext with existing indexed subcontext" + `Quick + (fun _ -> test_register_indexed_subcontext_2); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("storage description", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_storage_functions.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_storage_functions.ml new file mode 100644 index 000000000000..96fcfb175c5d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_storage_functions.ml @@ -0,0 +1,240 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Context Storage + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_storage_functions.ml + Subject: Test storage functions. + *) + +open Protocol +open Storage_functors + +let assert_length ~loc ctxt key expected = + let open Lwt_result_syntax in + let*! length = Raw_context.length ctxt key in + let* () = Assert.equal_int ~loc length expected in + let*! list = Raw_context.list ctxt key in + let list_length = List.length list in + Assert.equal_int ~loc length list_length + +module Int32 = struct + type t = int32 + + let encoding = Data_encoding.int32 + + module Index = struct + type t = int + + let path_length = 1 + + let to_path c l = string_of_int c :: l + + let of_path = function + | [] | _ :: _ :: _ -> None + | [c] -> int_of_string_opt c + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.int; + encoding = Data_encoding.int31; + compare = Compare.Int.compare; + } + end +end + +module String = struct + type t = string + + let encoding = Data_encoding.string +end + +module Root_raw_context = + Make_subcontext (Registered) (Raw_context) + (struct + let name = ["test_storage_functors"] + end) + +module Indexed_context = + Make_indexed_subcontext + (Make_subcontext (Registered) (Root_raw_context) + (struct + let name = ["index"] + end)) + (Int32.Index) + +module Table = + Make_carbonated_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["table"] + end)) + (Int32.Index) + +module Indexed_table = + Make_carbonated_data_set_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["table2"] + end)) + (Int32.Index) + +(** Test: + This test checks that it is possible to add values to a + Carbonated_data_set_storage and iterate over them. *) +let test_fold_keys_unaccounted () = + let open Lwt_result_wrap_syntax in + let* ctxt = Context.default_raw_context () in + let*@ ctxt, _ = Table.init ctxt 1 in + let*@ ctxt, _ = Table.init ctxt 2 in + let*! items = + Table.fold_keys_unaccounted + ctxt + ~order:`Undefined + ~f:(fun x acc -> Lwt.return @@ (x :: acc)) + ~init:[] + in + let items = List.sort Compare.Int.compare items in + Assert.assert_equal_list + ~loc:__LOC__ + Int.equal + "Compare items" + Format.pp_print_int + [1; 2] + items + +(** Test that [length] returns the number of elements for a given path. *) +let test_length () = + let open Lwt_result_wrap_syntax in + let* ctxt = Context.default_raw_context () in + (* Add a tree to the context: + root: + left: + l1 : V1 + l2 : V2 + l3 : V3 + right: + r1 : V4 + r2 : V5 + file : V6 + *) + let*! tree = + let*! tree_left = + let tree = Raw_context.Tree.empty ctxt in + let*! tree = Raw_context.Tree.add tree ["l1"] (Bytes.of_string "V1") in + let*! tree = Raw_context.Tree.add tree ["l2"] (Bytes.of_string "V2") in + Raw_context.Tree.add tree ["c"] (Bytes.of_string "V3") + in + let*! tree_right = + let tree = Raw_context.Tree.empty ctxt in + let*! tree = Raw_context.Tree.add tree ["r1"] (Bytes.of_string "V4") in + Raw_context.Tree.add tree ["r2"] (Bytes.of_string "V5") + in + let tree = Raw_context.Tree.empty ctxt in + let*! tree = Raw_context.Tree.add_tree tree ["left"] tree_left in + let*! tree = Raw_context.Tree.add_tree tree ["right"] tree_right in + Raw_context.Tree.add tree ["file"] (Bytes.of_string "V6") + in + let*@ ctxt = Raw_context.init_tree ctxt ["root"] tree in + (* The root node contains 3 elements. *) + let* () = assert_length ctxt ~loc:__LOC__ ["root"] 3 in + (* The left branch contains 3 elements. *) + let* () = assert_length ctxt ~loc:__LOC__ ["root"; "left"] 3 in + (* The right branch contains 2 elements. *) + let* () = assert_length ctxt ~loc:__LOC__ ["root"; "right"] 2 in + (* Path [root/left/l1] is a leaf and thus returns length 0. *) + let* () = assert_length ctxt ~loc:__LOC__ ["root"; "left"; "l1"] 0 in + (* The length of a non-existing path also returns 0. *) + assert_length ctxt ~loc:__LOC__ ["root"; "right"; "non_existing"] 0 + +let test_is_empty_carbonated_data_set () = + let open Lwt_result_wrap_syntax in + let* ctxt = Context.default_raw_context () in + let*@ ctxt, is_empty = Table.is_empty ctxt in + (* Test is_empty on uninitialized Table. *) + let* () = Assert.equal_bool ~loc:__LOC__ is_empty true in + + let*@ ctxt, _ = Table.init ctxt 1 in + let*@ ctxt, is_empty = Table.is_empty ctxt in + (* Test empty after adding an element to the Table. *) + let* () = Assert.equal_bool ~loc:__LOC__ is_empty false in + + let*@ ctxt, _, _ = Table.remove ctxt 1 in + let*@ _ctxt, is_empty = Table.is_empty ctxt in + (* Test empty after removing the element from the Table. *) + Assert.equal_bool ~loc:__LOC__ is_empty true + +let test_clear_carbonated_data_set () = + let open Lwt_result_wrap_syntax in + let* ctxt = Context.default_raw_context () in + (* Test clear on uninitialized Table. *) + let*@ ctxt = Table.clear ctxt in + let*@ ctxt, is_empty = Table.is_empty ctxt in + let* () = Assert.equal_bool ~loc:__LOC__ is_empty true in + + let*@ ctxt, _ = Table.init ctxt 1 in + let*@ ctxt, is_empty = Table.is_empty ctxt in + let* () = Assert.equal_bool ~loc:__LOC__ is_empty false in + + (* Test clear on non-empty Table. *) + let*@ ctxt = Table.clear ctxt in + let*@ _ctxt, is_empty = Table.is_empty ctxt in + let* () = Assert.equal_bool ~loc:__LOC__ is_empty true in + + (* Test clear on indexed table. Check that only the cleared indexed + table is cleared. *) + let*@ ctxt, _ = Indexed_table.init (ctxt, 0) 0 in + let*@ ctxt, _ = Indexed_table.init (ctxt, 1) 1 in + let*@ ctxt = Indexed_table.clear (ctxt, 0) in + let*@ ctxt, is_empty0 = Indexed_table.is_empty (ctxt, 0) in + let*@ _ctxt, is_empty1 = Indexed_table.is_empty (ctxt, 1) in + let* () = Assert.equal_bool ~loc:__LOC__ is_empty0 true in + Assert.equal_bool ~loc:__LOC__ is_empty1 false + +let tests = + [ + Tztest.tztest + "fold_keys_unaccounted smoke test" + `Quick + test_fold_keys_unaccounted; + Tztest.tztest "length test" `Quick test_length; + Tztest.tztest + "test empty carbonated data set" + `Quick + test_is_empty_carbonated_data_set; + Tztest.tztest + "test clear carbonated data set" + `Quick + test_clear_carbonated_data_set; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("storage tests", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/test_token.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/test_token.ml new file mode 100644 index 000000000000..b27d0448fd40 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/test_token.ml @@ -0,0 +1,789 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (token) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/main.exe \ + -- --file test_token.ml + Subject: Token movements in the protocol. +*) + +open Protocol +open Alpha_context +open Test_tez + +(** Creates a context with a single account. Returns the context and the public + key hash of the account. *) +let create_context () = + let open Lwt_result_syntax in + let (Account.{pkh; _} as account) = Account.new_account () in + let bootstrap_account = Account.make_bootstrap_account account in + let* ctxt = Block.alpha_context [bootstrap_account] in + return (ctxt, pkh) + +let random_amount () = + match Tez.of_mutez (Int64.add 1L (Random.int64 100L)) with + | None -> assert false + | Some x -> x + +let nonce = Origination_nonce.Internal_for_tests.initial Operation_hash.zero + +let sc_rollup () = Sc_rollup.Internal_for_tests.originated_sc_rollup nonce + +(** Check balances for a simple transfer from [bootstrap] to new [Implicit]. *) +let test_simple_balances () = + let open Lwt_result_wrap_syntax in + Random.init 0 ; + let* ctxt, pkh = create_context () in + let giver = `Contract (Contract.Implicit pkh) in + let pkh, _pk, _sk = Signature.generate_key () in + let receiver = `Contract (Contract.Implicit pkh) in + let amount = Tez.one in + let*@ ctxt', _ = Token.transfer ctxt giver receiver amount in + let*@ ctxt, bal_giver = Token.Internal_for_tests.balance ctxt giver in + let*@ ctxt', bal_giver' = Token.Internal_for_tests.balance ctxt' giver in + let*@ _, bal_receiver = Token.Internal_for_tests.balance ctxt receiver in + let*@ _, bal_receiver' = Token.Internal_for_tests.balance ctxt' receiver in + let*? add_bal_giver'_amount = bal_giver' +? amount in + let*? add_bal_receiver_amount = bal_receiver +? amount in + let* () = Assert.equal_tez ~loc:__LOC__ bal_giver add_bal_giver'_amount in + Assert.equal_tez ~loc:__LOC__ bal_receiver' add_bal_receiver_amount + +(** Check balance updates for a simple transfer from [bootstrap] to new + [Implicit]. *) +let test_simple_balance_updates () = + let open Lwt_result_wrap_syntax in + Random.init 0 ; + let* ctxt, pkh = create_context () in + let giver = Contract.Implicit pkh in + let pkh, _pk, _sk = Signature.generate_key () in + let receiver = Contract.Implicit pkh in + let amount = Tez.one in + let*@ _, bal_updates = + Token.transfer ctxt (`Contract giver) (`Contract receiver) amount + in + Alcotest.( + check + bool + "Missing balance update for giver contract." + (List.mem + ~equal:( = ) + (Receipt.item (Contract giver) (Debited amount) Block_application) + bal_updates) + true) ; + Alcotest.( + check + bool + "Missing balance update for receiver contract." + (List.mem + ~equal:( = ) + (Receipt.item (Contract receiver) (Credited amount) Block_application) + bal_updates) + true) ; + return_unit + +let test_allocated_and_deallocated ctxt receiver initial_status + status_when_empty = + let open Lwt_result_wrap_syntax in + let receiver_container = (receiver :> Token.container) in + let*@ ctxt, allocated = + Token.Internal_for_tests.allocated ctxt receiver_container + in + let* () = Assert.equal_bool ~loc:__LOC__ allocated initial_status in + let amount = Tez.one in + let*@ ctxt', _ = Token.transfer ctxt `Minted receiver_container amount in + let*@ ctxt', allocated = + Token.Internal_for_tests.allocated ctxt' receiver_container + in + let* () = Assert.equal_bool ~loc:__LOC__ allocated true in + let*@ ctxt', bal_receiver' = + Token.Internal_for_tests.balance ctxt' receiver + in + let*@ ctxt', _ = + Token.transfer ctxt' receiver_container `Burned bal_receiver' + in + let*@ _, allocated = + Token.Internal_for_tests.allocated ctxt' receiver_container + in + let* () = Assert.equal_bool ~loc:__LOC__ allocated status_when_empty in + return_unit + +let test_allocated_and_deallocated_when_empty ctxt receiver = + test_allocated_and_deallocated ctxt receiver false false + +let test_allocated_and_still_allocated_when_empty ctxt receiver initial_status = + test_allocated_and_deallocated ctxt receiver initial_status true + +let test_allocated () = + let open Lwt_result_syntax in + Random.init 0 ; + let* ctxt, baker_pkh = create_context () in + let receiver = `Contract (Contract.Implicit baker_pkh) in + let* () = test_allocated_and_still_allocated_when_empty ctxt receiver true in + (* Generate a fresh, empty, non-allocated implicit account. *) + let pkh, _pk, _sk = Signature.generate_key () in + let receiver = `Contract (Contract.Implicit pkh) in + let* () = test_allocated_and_deallocated_when_empty ctxt receiver in + let receiver = `Collected_commitments Blinded_public_key_hash.zero in + let* () = test_allocated_and_deallocated_when_empty ctxt receiver in + let receiver = `Block_fees in + let* () = test_allocated_and_still_allocated_when_empty ctxt receiver true in + let receiver = + let bond_id = Bond_id.Sc_rollup_bond_id (sc_rollup ()) in + `Frozen_bonds (Contract.Implicit pkh, bond_id) + in + test_allocated_and_deallocated_when_empty ctxt receiver + +let check_receiver_balances ctxt ctxt' receiver amount = + let open Lwt_result_wrap_syntax in + let*@ _, bal_receiver = Token.Internal_for_tests.balance ctxt receiver in + let*@ _, bal_receiver' = Token.Internal_for_tests.balance ctxt' receiver in + let*? add_bal_receiver_amount = bal_receiver +? amount in + Assert.equal_tez ~loc:__LOC__ bal_receiver' add_bal_receiver_amount + +let test_transferring_to_receiver ctxt receiver amount expected_bupds = + let open Lwt_result_wrap_syntax in + (* Transferring zero must be a noop, and must not return balance updates. *) + let*@ ctxt', bupds = Token.transfer ctxt `Minted receiver Tez.zero in + let* () = Assert.equal_bool ~loc:__LOC__ (ctxt == ctxt' && bupds = []) true in + (* Test transferring a non null amount. *) + let*@ ctxt', bupds = Token.transfer ctxt `Minted receiver amount in + let* () = check_receiver_balances ctxt ctxt' receiver amount in + let expected_bupds = + Receipt.item Minted (Debited amount) Block_application :: expected_bupds + in + Alcotest.( + check bool "Balance updates do not match." (bupds = expected_bupds) true) ; + (* Test transferring to go beyond capacity. *) + let*@ ctxt', bal = Token.Internal_for_tests.balance ctxt' receiver in + let amount = Tez.of_mutez_exn Int64.max_int -! bal +! Tez.one_mutez in + let*!@ res = Token.transfer ctxt' `Minted receiver amount in + Assert.proto_error_with_info ~loc:__LOC__ res "Overflowing tez addition" + +let test_transferring_to_contract ctxt = + let pkh, _pk, _sk = Signature.generate_key () in + let receiver = Contract.Implicit pkh in + let amount = random_amount () in + test_transferring_to_receiver + ctxt + (`Contract receiver) + amount + Receipt.[item (Contract receiver) (Credited amount) Block_application] + +let test_transferring_to_collected_commitments ctxt = + let amount = random_amount () in + let bpkh = Blinded_public_key_hash.zero in + test_transferring_to_receiver + ctxt + (`Collected_commitments bpkh) + amount + Receipt.[item (Commitments bpkh) (Credited amount) Block_application] + +let test_transferring_to_collected_fees ctxt = + let amount = random_amount () in + test_transferring_to_receiver + ctxt + `Block_fees + amount + Receipt.[item Block_fees (Credited amount) Block_application] + +let test_transferring_to_burned ctxt = + let open Lwt_result_wrap_syntax in + let amount = random_amount () in + let minted_bupd = Receipt.item Minted (Debited amount) Block_application in + let*@ _, bupds = Token.transfer ctxt `Minted `Burned amount in + let* () = + Assert.equal_bool + ~loc:__LOC__ + (bupds + = Receipt.[minted_bupd; item Burned (Credited amount) Block_application]) + true + in + let*@ _, bupds = Token.transfer ctxt `Minted `Storage_fees amount in + let* () = + Assert.equal_bool + ~loc:__LOC__ + (bupds + = Receipt. + [minted_bupd; item Storage_fees (Credited amount) Block_application]) + true + in + let*@ _, bupds = + Token.transfer ctxt `Minted `Double_signing_punishments amount + in + let* () = + Assert.equal_bool + ~loc:__LOC__ + (bupds + = Receipt. + [ + minted_bupd; + item Double_signing_punishments (Credited amount) Block_application; + ]) + true + in + let pkh = Signature.Public_key_hash.zero in + let p, r = (Random.bool (), Random.bool ()) in + let*@ _, bupds = + Token.transfer ctxt `Minted (`Lost_attesting_rewards (pkh, p, r)) amount + in + let* () = + Assert.equal_bool + ~loc:__LOC__ + (bupds + = Receipt. + [ + minted_bupd; + item + (Lost_attesting_rewards (pkh, p, r)) + (Credited amount) + Block_application; + ]) + true + in + let*@ _, bupds = + Token.transfer ctxt `Minted `Sc_rollup_refutation_punishments amount + in + Assert.equal_bool + ~loc:__LOC__ + (bupds + = Receipt. + [ + minted_bupd; + item + Sc_rollup_refutation_punishments + (Credited amount) + Block_application; + ]) + true + +let test_transferring_to_frozen_bonds ctxt = + let pkh, _pk, _sk = Signature.generate_key () in + let contract = Contract.Implicit pkh in + let sc_rollup = sc_rollup () in + let bond_id = Bond_id.Sc_rollup_bond_id sc_rollup in + let amount = random_amount () in + test_transferring_to_receiver + ctxt + (`Frozen_bonds (contract, bond_id)) + amount + Receipt. + [ + item + (Frozen_bonds (contract, bond_id)) + (Credited amount) + Block_application; + ] + +let test_transferring_to_receiver () = + let open Lwt_result_syntax in + Random.init 0 ; + let* ctxt, _ = create_context () in + let* () = test_transferring_to_contract ctxt in + let* () = test_transferring_to_collected_commitments ctxt in + let* () = test_transferring_to_collected_fees ctxt in + let* () = test_transferring_to_burned ctxt in + test_transferring_to_frozen_bonds ctxt + +let check_giver_balances ctxt ctxt' giver amount = + let open Lwt_result_wrap_syntax in + let*@ _, bal_giver = Token.Internal_for_tests.balance ctxt giver in + let*@ _, bal_giver' = Token.Internal_for_tests.balance ctxt' giver in + let*? add_bal_giver'_amount = bal_giver' +? amount in + Assert.equal_tez ~loc:__LOC__ bal_giver add_bal_giver'_amount + +let test_transferring_from_infinite_source ctxt giver expected_bupds = + let open Lwt_result_wrap_syntax in + (* Transferring zero must not return balance updates. *) + let*@ _, bupds = Token.transfer ctxt giver `Burned Tez.zero in + let* () = Assert.equal_bool ~loc:__LOC__ (bupds = []) true in + (* Test transferring a non null amount. *) + let amount = random_amount () in + let*@ _, bupds = Token.transfer ctxt giver `Burned amount in + let expected_bupds = + expected_bupds amount + @ Receipt.[item Burned (Credited amount) Block_application] + in + let* () = Assert.equal_bool ~loc:__LOC__ (bupds = expected_bupds) true in + return_unit + +(* Returns the balance of [account] if [account] is allocated, and returns + [Tez.zero] otherwise. *) +let balance_no_fail ctxt account = + let open Lwt_result_wrap_syntax in + let*@ ctxt, allocated = + Token.Internal_for_tests.allocated ctxt (account :> Token.container) + in + if allocated then wrap (Token.Internal_for_tests.balance ctxt account) + else return (ctxt, Tez.zero) + +let test_transferring_from_container ctxt giver amount expected_bupds = + let open Lwt_result_wrap_syntax in + let* ctxt, balance = balance_no_fail ctxt giver in + let* () = Assert.equal_tez ~loc:__LOC__ balance Tez.zero in + (* Test transferring from an empty account. *) + let*!@ res = Token.transfer ctxt giver `Burned Tez.one in + let error_title = + match giver with + | `Contract _ -> "Balance too low" + | `Frozen_bonds _ -> "Storage error (fatal internal error)" + | _ -> "Underflowing tez subtraction" + in + let* () = Assert.proto_error_with_info ~loc:__LOC__ res error_title in + (* Transferring zero must be a noop, and must not return balance updates. *) + let*@ ctxt', bupds = Token.transfer ctxt giver `Burned Tez.zero in + let* () = Assert.equal_bool ~loc:__LOC__ (ctxt == ctxt' && bupds = []) true in + (* Test transferring everything. *) + let*@ ctxt, _ = Token.transfer ctxt `Minted giver amount in + let*@ ctxt', bupds = Token.transfer ctxt giver `Burned amount in + let* () = check_giver_balances ctxt ctxt' giver amount in + let expected_bupds = + expected_bupds @ Receipt.[item Burned (Credited amount) Block_application] + in + let* () = Assert.equal_bool ~loc:__LOC__ (bupds = expected_bupds) true in + (* Test transferring a smaller amount. *) + let*@ ctxt, _ = Token.transfer ctxt `Minted giver amount in + let* () = + match giver with + | `Frozen_bonds _ -> + let*!@ res = Token.transfer ctxt giver `Burned amount in + let error_title = "Partial spending of frozen bonds" in + Assert.proto_error_with_info ~loc:__LOC__ res error_title + | _ -> + let*@ ctxt', bupds = Token.transfer ctxt giver `Burned amount in + let* () = check_giver_balances ctxt ctxt' giver amount in + Assert.equal_bool ~loc:__LOC__ (bupds = expected_bupds) true + in + (* Test transferring more than available. *) + let*@ ctxt, balance = Token.Internal_for_tests.balance ctxt giver in + let*!@ res = Token.transfer ctxt giver `Burned (balance +! Tez.one) in + let error_title = + match giver with + | `Contract _ -> "Balance too low" + | `Frozen_bonds _ -> "Partial spending of frozen bonds" + | _ -> "Underflowing tez subtraction" + in + Assert.proto_error_with_info ~loc:__LOC__ res error_title + +let test_transferring_from_contract ctxt = + let pkh, _pk, _sk = Signature.generate_key () in + let giver = Contract.Implicit pkh in + let amount = random_amount () in + test_transferring_from_container + ctxt + (`Contract giver) + amount + Receipt.[item (Contract giver) (Debited amount) Block_application] + +let test_transferring_from_collected_commitments ctxt = + let amount = random_amount () in + let bpkh = Blinded_public_key_hash.zero in + test_transferring_from_container + ctxt + (`Collected_commitments bpkh) + amount + Receipt.[item (Commitments bpkh) (Debited amount) Block_application] + +let test_transferring_from_collected_fees ctxt = + let amount = random_amount () in + test_transferring_from_container + ctxt + `Block_fees + amount + Receipt.[item Block_fees (Debited amount) Block_application] + +let test_transferring_from_frozen_bonds ctxt = + let pkh, _pk, _sk = Signature.generate_key () in + let contract = Contract.Implicit pkh in + let sc_rollup = sc_rollup () in + let bond_id = Bond_id.Sc_rollup_bond_id sc_rollup in + let amount = random_amount () in + test_transferring_from_container + ctxt + (`Frozen_bonds (contract, bond_id)) + amount + Receipt. + [ + item + (Frozen_bonds (contract, bond_id)) + (Debited amount) + Block_application; + ] + +let test_transferring_from_giver () = + let open Lwt_result_wrap_syntax in + Random.init 0 ; + let* ctxt, _ = create_context () in + let* () = + test_transferring_from_infinite_source ctxt `Invoice (fun am -> + Receipt.[item Invoice (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Bootstrap (fun am -> + Receipt.[item Bootstrap (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Initial_commitments (fun am -> + Receipt.[item Initial_commitments (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Revelation_rewards (fun am -> + Receipt.[item Nonce_revelation_rewards (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Attesting_rewards (fun am -> + Receipt.[item Attesting_rewards (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Baking_rewards (fun am -> + Receipt.[item Baking_rewards (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Baking_bonuses (fun am -> + Receipt.[item Baking_bonuses (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source ctxt `Minted (fun am -> + Receipt.[item Minted (Debited am) Block_application]) + in + let* () = + test_transferring_from_infinite_source + ctxt + `Liquidity_baking_subsidies + (fun am -> + Receipt.[item Liquidity_baking_subsidies (Debited am) Block_application]) + in + let* () = test_transferring_from_contract ctxt in + let* () = test_transferring_from_collected_commitments ctxt in + let* () = test_transferring_from_collected_fees ctxt in + test_transferring_from_frozen_bonds ctxt + +let cast_to_container_type x = + match x with + | `Burned | `Invoice | `Bootstrap | `Initial_commitments | `Minted + | `Liquidity_baking_subsidies -> + None + | `Contract _ as x -> Some x + | `Collected_commitments _ as x -> Some x + | `Block_fees as x -> Some x + | `Frozen_bonds _ as x -> Some x + +(** Generates all combinations of constructors. *) +let build_test_cases () = + let open Lwt_result_wrap_syntax in + let* ctxt, pkh = create_context () in + let origin = `Contract (Contract.Implicit pkh) in + let user1, _, _ = Signature.generate_key () in + let user1c = `Contract (Contract.Implicit user1) in + let user2, _, _ = Signature.generate_key () in + let user2c = `Contract (Contract.Implicit user2) in + let baker1, baker1_pk, _ = Signature.generate_key () in + let baker1c = `Contract (Contract.Implicit baker1) in + let baker2, baker2_pk, _ = Signature.generate_key () in + let baker2c = `Contract (Contract.Implicit baker2) in + (* Allocate contracts for user1, user2, baker1, and baker2. *) + let*@ ctxt, _ = Token.transfer ctxt origin user1c (random_amount ()) in + let*@ ctxt, _ = Token.transfer ctxt origin user2c (random_amount ()) in + let*@ ctxt, _ = Token.transfer ctxt origin baker1c (random_amount ()) in + let*@ ctxt, _ = Token.transfer ctxt origin baker2c (random_amount ()) in + (* Configure baker1, and baker2 as delegates by self-delegation, for which + revealing their manager key is a prerequisite. *) + let*@ ctxt = Contract.reveal_manager_key ctxt baker1 baker1_pk in + let*@ ctxt = + Contract.Delegate.set ctxt (Contract.Implicit baker1) (Some baker1) + in + let*@ ctxt = Contract.reveal_manager_key ctxt baker2 baker2_pk in + let*@ ctxt = + Contract.Delegate.set ctxt (Contract.Implicit baker2) (Some baker2) + (* Let user1 delegate to baker2. *) + in + let*@ ctxt = + Contract.Delegate.set ctxt (Contract.Implicit user1) (Some baker2) + in + let sc_rollup1 = sc_rollup () in + let bond_id1 = Bond_id.Sc_rollup_bond_id sc_rollup1 in + let sc_rollup2 = sc_rollup () in + let bond_id2 = Bond_id.Sc_rollup_bond_id sc_rollup2 in + let user1ic = Contract.Implicit user1 in + let baker2ic = Contract.Implicit baker2 in + let giver_list = + [ + (`Invoice, random_amount ()); + (`Bootstrap, random_amount ()); + (`Initial_commitments, random_amount ()); + (`Minted, random_amount ()); + (`Liquidity_baking_subsidies, random_amount ()); + (`Collected_commitments Blinded_public_key_hash.zero, random_amount ()); + (`Block_fees, random_amount ()); + (user1c, random_amount ()); + (user2c, random_amount ()); + (baker1c, random_amount ()); + (baker2c, random_amount ()); + (`Frozen_bonds (user1ic, bond_id1), random_amount ()); + (`Frozen_bonds (baker2ic, bond_id2), random_amount ()); + ] + in + let receiver_list = + [ + `Collected_commitments Blinded_public_key_hash.zero; + `Block_fees; + user1c; + user2c; + baker1c; + baker2c; + `Frozen_bonds (user1ic, bond_id1); + `Frozen_bonds (baker2ic, bond_id2); + `Burned; + ] + in + return (ctxt, List.product giver_list receiver_list) + +let check_giver_balances ctxt ctxt' giver amount = + let open Lwt_result_syntax in + match cast_to_container_type giver with + | None -> return_unit + | Some giver -> check_giver_balances ctxt ctxt' giver amount + +let check_receiver_balances ctxt ctxt' receiver amount = + let open Lwt_result_syntax in + match cast_to_container_type receiver with + | None -> return_unit + | Some receiver -> check_receiver_balances ctxt ctxt' receiver amount + +let check_balances ctxt ctxt' giver receiver amount = + let open Lwt_result_wrap_syntax in + match (cast_to_container_type giver, cast_to_container_type receiver) with + | None, None -> return_unit + | Some giver, Some receiver when giver = receiver -> + (* giver and receiver are the same contract *) + let*@ _, bal_receiver = Token.Internal_for_tests.balance ctxt receiver in + let*@ _, bal_receiver' = + Token.Internal_for_tests.balance ctxt' receiver + in + Assert.equal_tez ~loc:__LOC__ bal_receiver bal_receiver' + | Some giver, None -> check_giver_balances ctxt ctxt' giver amount + | None, Some receiver -> check_receiver_balances ctxt ctxt' receiver amount + | Some giver, Some receiver -> + let* () = check_giver_balances ctxt ctxt' giver amount in + check_receiver_balances ctxt ctxt' receiver amount + +let test_all_combinations_of_givers_and_receivers () = + let open Lwt_result_wrap_syntax in + Random.init 0 ; + let* ctxt, cases = build_test_cases () in + List.iter_es + (fun ((giver, amount), receiver) -> + let* ctxt = + match cast_to_container_type giver with + | None -> return ctxt + | Some giver -> + let*@ ctxt, _ = Token.transfer ctxt `Minted giver amount in + return ctxt + in + let*@ ctxt', _ = Token.transfer ctxt giver receiver amount in + check_balances ctxt ctxt' giver receiver amount) + cases + +(** [coalesce (account, Credited am1, origin) (account, Credited am2, origin) + = Some (account, Credited (am1+am2), origin)] + + [coalesce (account, Debited am1, origin) (account, Debited am2, origin) + = Some (account, Debited (am1+am2), origin)] + + Fails if bu1 and bu2 have different accounts or different origins, or + if one is a credit while the other is a debit. *) +let coalesce_balance_updates bu1 bu2 = + let open Receipt in + let (Balance_update_item (bu1_bal, bu1_balupd, bu1_origin)) = bu1 in + let (Balance_update_item (bu2_bal, bu2_balupd, bu2_origin)) = bu2 in + assert (bu1_origin = bu2_origin) ; + let token1 = token_of_balance bu1_bal in + let token2 = token_of_balance bu2_bal in + let Refl = + match Receipt.Token.eq token1 token2 with + | None -> assert false + | Some refl -> refl + in + assert (bu1_bal = bu2_bal) ; + match (bu1_balupd, bu2_balupd) with + | Credited bu1_am, Credited bu2_am -> + let bu_am = + match Receipt.Token.add token1 bu1_am bu2_am with + | Ok am -> am + | _ -> assert false + in + item bu1_bal (Credited bu_am) bu1_origin + | Debited bu1_am, Debited bu2_am -> + let bu_am = + match Receipt.Token.add token1 bu1_am bu2_am with + | Ok am -> am + | _ -> assert false + in + item bu1_bal (Debited bu_am) bu1_origin + | Credited _, Debited _ | Debited _, Credited _ -> assert false + +(** Check that elt has the same balance in ctxt1 and ctxt2. *) +let check_balances_are_consistent ctxt1 ctxt2 elt = + let open Lwt_result_syntax in + match elt with + | #Token.Internal_for_tests.container_with_balance as elt -> + let* _, elt_bal1 = Token.Internal_for_tests.balance ctxt1 elt in + let* _, elt_bal2 = Token.Internal_for_tests.balance ctxt2 elt in + assert (elt_bal1 = elt_bal2) ; + return_unit + | `Frozen_deposits _ | `Unstaked_frozen_deposits _ | `Invoice | `Bootstrap + | `Initial_commitments | `Minted | `Liquidity_baking_subsidies | `Burned -> + return_unit + +(** Test that [transfer_n] is equivalent to n debits followed by n credits. *) +let test_transfer_n ctxt (giver : ([< Token.container] * Tez.t) list) + (receiver : [< Token.container]) = + let open Lwt_result_syntax in + (* Run transfer_n. *) + let* ctxt1, bal_updates1 = Token.transfer_n ctxt giver receiver in + (* Debit all givers. *) + let* ctxt, debit_logs = + List.fold_left_es + (fun (ctxt, bal_updates) (giver, am) -> + let* ctxt, debit_logs = Token.transfer ctxt giver `Burned am in + return (ctxt, bal_updates @ debit_logs)) + (ctxt, []) + giver + in + (* remove burning balance updates *) + let debit_logs = + List.filter + (fun b -> + match b with + | Receipt.Balance_update_item (Burned, _, _) -> false + | _ -> true) + debit_logs + in + (* Credit the receiver for each giver. *) + let* ctxt2, credit_logs = + List.fold_left_es + (fun (ctxt, bal_updates) (_, am) -> + let* ctxt, credit_logs = Token.transfer ctxt `Minted receiver am in + return (ctxt, bal_updates @ credit_logs)) + (ctxt, []) + giver + in + (* remove minting balance updates *) + let credit_logs = + List.filter + (fun b -> + match b with + | Receipt.Balance_update_item (Minted, _, _) -> false + | _ -> true) + credit_logs + in + (* Check equivalence of balance updates. *) + let credit_logs = + match credit_logs with + | [] -> [] + | head :: tail -> [List.fold_left coalesce_balance_updates head tail] + in + assert (bal_updates1 = debit_logs @ credit_logs) ; + (* Check balances are the same in ctxt1 and ctxt2. *) + let* () = + List.(iter_es (check_balances_are_consistent ctxt1 ctxt2) (map fst giver)) + in + check_balances_are_consistent ctxt1 ctxt2 receiver + +let test_transfer_n_with_no_giver () = + let open Lwt_result_wrap_syntax in + Random.init 0 ; + let* ctxt, pkh = create_context () in + let*@ () = test_transfer_n ctxt [] `Block_fees in + let receiver = `Contract (Contract.Implicit pkh) in + let*@ () = test_transfer_n ctxt [] receiver in + return_unit + +let test_transfer_n_with_several_givers () = + let open Lwt_result_wrap_syntax in + Random.init 0 ; + let* ctxt, pkh = create_context () in + let origin = `Contract (Contract.Implicit pkh) in + let user1, _, _ = Signature.generate_key () in + let user1c = `Contract (Contract.Implicit user1) in + let user2, _, _ = Signature.generate_key () in + let user2c = `Contract (Contract.Implicit user2) in + let user3, _, _ = Signature.generate_key () in + let user3c = `Contract (Contract.Implicit user3) in + let user4, _, _ = Signature.generate_key () in + let user4c = `Contract (Contract.Implicit user4) in + (* Allocate contracts for user1, user2, user3, and user4. *) + let amount = + match Tez.of_mutez 1000L with None -> assert false | Some x -> x + in + let*@ ctxt, _ = Token.transfer ctxt origin user1c amount in + let*@ ctxt, _ = Token.transfer ctxt origin user2c amount in + let*@ ctxt, _ = Token.transfer ctxt origin user3c amount in + let*@ ctxt, _ = Token.transfer ctxt origin user4c (random_amount ()) in + let givers = + [ + (user2c, random_amount ()); + (user3c, random_amount ()); + (user4c, random_amount ()); + ] + in + let*@ () = test_transfer_n ctxt givers user1c in + let*@ () = + test_transfer_n ctxt ((user1c, random_amount ()) :: givers) user1c + in + return_unit + +let tests = + Tztest. + [ + tztest "transfer - balances" `Quick test_simple_balances; + tztest "transfer - balance updates" `Quick test_simple_balance_updates; + tztest "transfer - test allocated" `Quick test_allocated; + tztest + "transfer - test transfer to receiver" + `Quick + test_transferring_to_receiver; + tztest + "transfer - test transfer from giver" + `Quick + test_transferring_from_giver; + tztest + "transfer - test all (givers x receivers)" + `Quick + test_all_combinations_of_givers_and_receivers; + tztest + "transfer - test from no giver to a receiver" + `Quick + test_transfer_n_with_no_giver; + tztest + "transfer - test from n givers to a receiver" + `Quick + test_transfer_n_with_several_givers; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("token movements", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune new file mode 100644 index 000000000000..7b81904f2c9e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune @@ -0,0 +1,65 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_protocol_test_integration_validate_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-alcotezt + octez-libs.base + tezos-protocol-019-PtParisB.protocol + qcheck-alcotest + octez-protocol-019-PtParisB-libs.client + octez-libs.test-helpers + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.base-test-helpers + tezos-protocol-019-PtParisB.parameters + octez-protocol-019-PtParisB-libs.plugin) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Octez_alcotezt + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB + -open Tezos_test_helpers + -open Tezos_019_PtParisB_test_helpers + -open Tezos_base_test_helpers + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_plugin_019_PtParisB) + (modules + generator_descriptors + generators + manager_operation_helpers + test_1m_restriction + test_covalidity + test_manager_operation_validation + test_mempool + test_sanity + test_validation_batch + valid_operations_generators + validate_helpers)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_integration_validate_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.ml new file mode 100644 index 000000000000..a6261135a257 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.ml @@ -0,0 +1,873 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Validate_helpers + +type dbl_attestation_state = { + temporary : (Block.t * Block.t) option; + slashable_preattestations : + (Kind.preattestation operation * Kind.preattestation operation) list; + slashable_attestations : + (Kind.attestation operation * Kind.attestation operation) list; +} + +type state = { + block : Block.t; + pred : Block.t option; + bootstraps : public_key_hash list; + delegates : (public_key_hash * public_key_hash option) list; + voters : Contract.t list; + seed_nonce_to_reveal : (Raw_level.t * Nonce_hash.t) list; + commitments : secret_account list; + protocol_hashes : Protocol_hash.t list; + slashable_bakes : (block_header * block_header) list; + vdf : bool; + dbl_attestation : dbl_attestation_state; + manager : Manager.infos; +} + +let init_manager_state bootstraps block = + let open Manager in + let ctxt = + { + block; + bootstraps; + originated_contract = None; + sc_rollup = None; + zk_rollup = None; + } + in + let accounts = + {sources = []; dest = None; del = None; sc = None; zk = None} + in + {ctxt; accounts; flags = all_enabled} + +let init_dbl_attestation_state = + { + temporary = None; + slashable_preattestations = []; + slashable_attestations = []; + } + +(** Initialize the state according to [state] initialisation + for each operation kind. + + When adding a new operation kind, if such an initialization is + required, it should occur here. *) +let init_state block ~voters ~(bootstraps : Contract.t list) = + let bootstraps = + List.map + (function Contract.Implicit pkh -> pkh | _ -> assert false) + bootstraps + in + { + block; + pred = None; + bootstraps; + delegates = List.map (fun pkh -> (pkh, None)) bootstraps; + voters; + seed_nonce_to_reveal = []; + commitments = []; + protocol_hashes = []; + slashable_bakes = []; + vdf = false; + dbl_attestation = init_dbl_attestation_state; + manager = init_manager_state bootstraps block; + } + +type cycle_index = On of int | From of int + +type descriptor = { + parameters : Parameters.t -> Parameters.t; + required_cycle : Parameters.t -> int; + required_block : Parameters.t -> int; + prelude : + cycle_index * (state -> (packed_operation list * state) tzresult Lwt.t); + opt_prelude : + (cycle_index * (state -> (packed_operation list * state) tzresult Lwt.t)) + option; + candidates_generator : state -> packed_operation list tzresult Lwt.t; +} + +(** Each voting period lasts a whole cycle in the generation of valid operations. *) +let voting_context_params params = + let cycles_per_voting_period = 1l in + let constants = Parameters.{params.constants with cycles_per_voting_period} in + {params with constants} + +let ballot_exploration_prelude state = + let open Lwt_result_syntax in + let* ctxt = + let+ i = Incremental.begin_construction state.block in + Incremental.alpha_ctxt i + in + let blocks_per_cycle = Alpha_context.Constants.blocks_per_cycle ctxt in + let rem = + Int32.rem state.block.Block.header.Block_header.shell.level blocks_per_cycle + in + if rem = 0l then + match state.voters with + | voter :: voters -> + let* prop = Op.proposals (B state.block) voter [get_n protos 0] in + let* props = + List.map_es + (fun voter -> + Op.proposals (B state.block) voter [Protocol_hash.zero]) + voters + in + return (prop :: props, state) + | _ -> assert false + else return ([], state) + +let activate_descriptor = + let open Lwt_result_syntax in + { + parameters = + (fun params -> + let commitments = + List.map + (fun {blinded_public_key_hash; amount; _} -> + Commitment.{blinded_public_key_hash; amount}) + secrets + in + {params with commitments}); + required_cycle = (fun _params -> 1); + required_block = (fun _params -> 0); + prelude = + (On 1, fun state -> return ([], {state with commitments = secrets})); + opt_prelude = None; + candidates_generator = + (fun state -> + let gen s = + Op.activation (B state.block) (Ed25519 s.account) s.activation_code + in + List.map_es gen state.commitments); + } + +(** During the first voting period in the setup of valid operations generations, + a proposal must win the proposal period -- hence [ballot_exploration_prelude] + takes place during the first cycle. *) +let ballot_exploration_descriptor = + { + parameters = voting_context_params; + required_cycle = + (fun params -> Int32.to_int params.constants.cycles_per_voting_period); + required_block = (fun _params -> 0); + prelude = (On 1, ballot_exploration_prelude); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen contract = + let* voting_period_info = + Context.Vote.get_current_period (B state.block) + in + assert (voting_period_info.voting_period.kind = Exploration) ; + let ballot = pick_one ballots in + Op.ballot (B state.block) contract Protocol_hash.zero ballot + in + List.map_es gen state.voters); + } + +let proposal_descriptor = + let open Lwt_result_syntax in + { + parameters = voting_context_params; + required_cycle = (fun _ -> 0); + required_block = (fun _ -> 0); + prelude = + (On 0, fun state -> return ([], {state with protocol_hashes = protos})); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen contract = + let* voting_period_info = + Context.Vote.get_current_period (B state.block) + in + assert (voting_period_info.voting_period.kind = Proposal) ; + Op.proposals (B state.block) contract [Protocol_hash.zero] + in + List.map_es gen state.voters); + } + +(** [Promotion] is the 4th voting period, it requires 3 voting period + to last and be successful. [voting_context_params] set a + voting_period to 1 cycle. To generate a [Ballot] for this + promotion period: + + - the first period should conclude in a proposal wining -- 3 cycles + before generating the [Ballot], the proposal period must succeed:[ + ballot_exploration_prelude], + + - the exploration must conclude in a supermajority for this + proposal -- 2 cycles before generating the [Ballot], the + exploration period must succeed., and + + - the cooldown must last -- 1 cycle before generating the + [Ballot]. *) +let ballot_promotion_descriptor = + { + parameters = voting_context_params; + required_cycle = + (fun params -> 3 * Int32.to_int params.constants.cycles_per_voting_period); + required_block = (fun _ -> 0); + prelude = (On 3, ballot_exploration_prelude); + opt_prelude = + Some + ( On 2, + fun state -> + let open Lwt_result_syntax in + let* ctxt = + let+ incr = Incremental.begin_construction state.block in + Incremental.alpha_ctxt incr + in + let blocks_per_cycle = + Alpha_context.Constants.blocks_per_cycle ctxt + in + let rem = + Int32.rem + state.block.Block.header.Block_header.shell.level + blocks_per_cycle + in + if rem = 0l then + let* ops = + List.map_es + (fun voter -> + Op.ballot (B state.block) voter Protocol_hash.zero Vote.Yay) + state.voters + in + return (ops, state) + else return ([], state) ); + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen contract = + let* voting_period_info = + Context.Vote.get_current_period (B state.block) + in + assert (voting_period_info.voting_period.kind = Promotion) ; + let ballot = Stdlib.List.hd ballots in + Op.ballot (B state.block) contract Protocol_hash.zero ballot + in + List.map_es gen state.voters); + } + +let seed_nonce_descriptor = + { + parameters = + (fun params -> + assert (params.constants.blocks_per_cycle > 3l) ; + let blocks_per_commitment = + Int32.(div params.constants.blocks_per_cycle 3l) + in + let constants = {params.constants with blocks_per_commitment} in + {params with constants}); + required_cycle = (fun _ -> 1); + required_block = (fun _ -> 0); + prelude = + ( On 1, + fun state -> + let open Lwt_result_syntax in + let b = state.block in + let* seed_nonce_to_reveal = + match + b.Block.header.Block_header.protocol_data.contents.seed_nonce_hash + with + | None -> return state.seed_nonce_to_reveal + | Some nonce_hash -> + let level = + Raw_level.of_int32_exn b.Block.header.Block_header.shell.level + in + return ((level, nonce_hash) :: state.seed_nonce_to_reveal) + in + return ([], {state with seed_nonce_to_reveal}) ); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen (level, nonce_hash) = + assert (List.length state.seed_nonce_to_reveal >= 3) ; + let nonce = + WithExceptions.Option.to_exn ~none:Not_found + @@ Registered_nonces.get nonce_hash + in + return (Op.seed_nonce_revelation (B state.block) level nonce) + in + List.map_es gen state.seed_nonce_to_reveal); + } + +(** The heads on which two slashable attestations or preattestation + should be made are from the previous level. Hence, the temporary + field of a double_evidence_state is used to transmit them to the + next level in order to make the slashable operations. *) +let register_temporary ba bb state : (Block.t * Block.t) option * state = + let pred_forks = state.dbl_attestation.temporary in + let temporary = Some (ba, bb) in + let dbl_attestation = {state.dbl_attestation with temporary} in + (pred_forks, {state with dbl_attestation}) + +(** During the slashable period, at each level, two different heads + for the same round are baked by the same baker. At the next level, + a delegate that either preattests or attests both heads makes a + pair of slashable pre- or attestations. + + The pair of heads is placed in the temporary of the + double_evidence_state. If a pair of heads was already in this + field, hence they were baked at the previous level. + + Consequently, two pairs of slashable operations: two attestations + and two preattestation, can be made by two distinct attestations. Each + pair is ordered in operation_hash order. Consequently, each pair + can appear in a denunciation operation and will be valid. *) +let dbl_attestation_prelude state = + let open Lwt_result_syntax in + let* head_A = Block.bake ~policy:(By_round 0) state.block in + let* addr = pick_addr_attester (B state.block) in + let ctr = Contract.Implicit addr in + let* operation = Op.transaction (B state.block) ctr ctr Tez.one_mutez in + let* head_B = Block.bake ~policy:(By_round 0) state.block ~operation in + let heads, state = register_temporary head_A head_B state in + match heads with + | None -> return ([], state) + | Some (b1, b2) -> + let* delegate1, delegate2 = pick_two_attesters (B b1) in + let* op1 = Op.raw_preattestation ~delegate:delegate1 b1 in + let* op2 = Op.raw_preattestation ~delegate:delegate1 b2 in + let op1, op2 = + let comp = + Operation_hash.compare (Operation.hash op1) (Operation.hash op2) + in + assert (comp <> 0) ; + if comp < 0 then (op1, op2) else (op2, op1) + in + let slashable_preattestations = + (op1, op2) :: state.dbl_attestation.slashable_preattestations + in + let* op3 = Op.raw_attestation ~delegate:delegate2 b1 in + let* op4 = Op.raw_attestation ~delegate:delegate2 b2 in + let op3, op4 = + let comp = + Operation_hash.compare (Operation.hash op3) (Operation.hash op4) + in + assert (comp <> 0) ; + if comp < 0 then (op3, op4) else (op4, op3) + in + let slashable_attestations = + (op3, op4) :: state.dbl_attestation.slashable_attestations + in + let dbl_attestation = + { + state.dbl_attestation with + slashable_preattestations; + slashable_attestations; + } + in + return ([], {state with dbl_attestation}) + +let double_consensus_descriptor = + { + parameters = Fun.id; + required_cycle = (fun _params -> 2); + required_block = (fun _ -> 0); + prelude = (From 2, dbl_attestation_prelude); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen_dbl_pre (op1, op2) = + Op.double_preattestation (Context.B state.block) op1 op2 + in + let gen_dbl_end (op1, op2) = + Op.double_attestation (Context.B state.block) op1 op2 + in + let candidates_pre = + List.map gen_dbl_pre state.dbl_attestation.slashable_preattestations + in + let candidates_end = + List.map gen_dbl_end state.dbl_attestation.slashable_attestations + in + return (candidates_pre @ candidates_end)); + } + +let double_baking_descriptor = + { + parameters = Fun.id; + required_cycle = (fun _params -> Constants_repr.max_slashing_period); + required_block = (fun _ -> 0); + prelude = + ( From 2, + fun state -> + let open Lwt_result_syntax in + let order_block_header bh1 bh2 = + let hash1 = Block_header.hash bh1 in + let hash2 = Block_header.hash bh2 in + let c = Block_hash.compare hash1 hash2 in + if c < 0 then (bh1, bh2) else (bh2, bh1) + in + let* ctxt = + let+ incr = Incremental.begin_construction state.block in + Incremental.alpha_ctxt incr + in + let blocks_per_cycle = + Alpha_context.Constants.blocks_per_cycle ctxt + in + let rem = + Int32.rem + state.block.Block.header.Block_header.shell.level + blocks_per_cycle + in + if rem = 0l then return ([], state) + else + let* baker1, _baker2 = + Context.get_first_different_bakers (B state.block) + in + let* addr = pick_addr_attester (B state.block) in + let ctr = Contract.Implicit addr in + let* operation = + Op.transaction (B state.block) ctr ctr Tez.one_mutez + in + let* ba = + Block.bake ~policy:(By_account baker1) ~operation state.block + in + let* bb = Block.bake ~policy:(By_account baker1) state.block in + let ba, bb = order_block_header ba.Block.header bb.Block.header in + let slashable_bakes = (ba, bb) :: state.slashable_bakes in + return ([], {state with slashable_bakes}) ); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen (bh1, bh2) = + return (Op.double_baking (B state.block) bh1 bh2) + in + List.map_es gen state.slashable_bakes); + } + +(** A drain delegate operation is valid when, preserved_cycle before, the + delegate has updated its key. This key must then has enough fund in order to + be revealed. + + At the first level of preserved cycle in the past, the key is funded by a + bootstrap account. At the second level, it reveals and at the third the + delegate updates its key to this key. *) +let drain_delegate_prelude state = + let open Lwt_result_syntax in + let* ctxt = + let+ incr = Incremental.begin_construction state.block in + Incremental.alpha_ctxt incr + in + let blocks_per_cycle = Alpha_context.Constants.blocks_per_cycle ctxt in + let rem = + Int32.rem state.block.Block.header.Block_header.shell.level blocks_per_cycle + in + if rem = 0l then + (* Create (n / 2) consensus keys *) + let delegates = + List.mapi + (fun i -> function + | (delegate, None) as del -> + if i mod 2 = 0 then + let acc = Account.new_account () in + (delegate, Some acc.pkh) + else del + | del -> del (* should not happen but apparently does...*)) + state.delegates + in + let dels = + List.filter_map + (function _del, None -> None | del, Some ck -> Some (del, ck)) + delegates + in + let* ops = + List.fold_left_es + (fun ops (del, ck) -> + let* {Account.pk; _} = Account.find ck in + let* op = + Op.update_consensus_key (B state.block) (Contract.Implicit del) pk + in + return (op :: ops)) + [] + dels + in + let state = {state with delegates} in + return (ops, state) + else return ([], state) + +let drain_delegate_descriptor = + { + parameters = Fun.id; + required_cycle = (fun params -> params.constants.consensus_rights_delay + 1); + required_block = (fun _ -> 0); + prelude = + ( On (init_params.constants.consensus_rights_delay + 1), + drain_delegate_prelude ); + opt_prelude = None; + candidates_generator = + (fun state -> + let gen (delegate, consensus_key_opt) = + let open Lwt_result_syntax in + match consensus_key_opt with + | None -> return_none + | Some consensus_key -> + let* op = + Op.drain_delegate + (B state.block) + ~consensus_key + ~delegate + ~destination:consensus_key + in + return_some op + in + List.filter_map_es gen state.delegates); + } + +let vdf_revelation_descriptor = + let open Lwt_result_syntax in + { + parameters = + (fun params -> + {params with constants = {params.constants with vdf_difficulty = 750L}}); + required_cycle = (fun _ -> 1); + required_block = + (fun params -> Int32.to_int params.constants.nonce_revelation_threshold); + prelude = (On 2, fun state -> return ([], {state with vdf = true})); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let* seed_status = Context.get_seed_computation (B state.block) in + let* csts = Context.get_constants (B state.block) in + match seed_status with + | Nonce_revelation_stage | Computation_finished -> assert false + | Vdf_revelation_stage info -> + (* generate the VDF discriminant and challenge *) + let discriminant, challenge = + Alpha_context.Seed.generate_vdf_setup + ~seed_discriminant:info.seed_discriminant + ~seed_challenge:info.seed_challenge + in + (* compute the VDF solution (the result and the proof ) *) + let solution = + (* generate the result and proof *) + Environment.Vdf.prove + discriminant + challenge + csts.parametric.vdf_difficulty + in + return [Op.vdf_revelation (B state.block) solution]); + } + +let preattestation_descriptor = + let open Lwt_result_syntax in + { + parameters = Fun.id; + required_cycle = (fun _ -> 1); + required_block = (fun _ -> 1); + prelude = (On 1, fun state -> return ([], state)); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen (delegate, ck_opt) = + let* slots_opt = Context.get_attester_slot (B state.block) delegate in + let delegate = Option.value ~default:delegate ck_opt in + match slots_opt with + | None -> return_none + | Some slots -> ( + match slots with + | [] -> return_none + | _ :: _ -> + let* op = Op.preattestation ~delegate state.block in + return_some op) + in + List.filter_map_es gen state.delegates); + } + +let attestation_descriptor = + let open Lwt_result_syntax in + { + parameters = Fun.id; + required_cycle = (fun _ -> 1); + required_block = (fun _ -> 1); + prelude = (On 1, fun state -> return ([], state)); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let gen (delegate, ck_opt) = + let* slots_opt = Context.get_attester_slot (B state.block) delegate in + let delegate = Option.value ~default:delegate ck_opt in + match slots_opt with + | None -> return_none + | Some slots -> ( + match slots with + | [] -> return_none + | _ :: _ -> + let* op = Op.attestation ~delegate state.block in + return_some op) + in + List.filter_map_es gen state.delegates); + } + +module Manager = Manager_operation_helpers + +let required_nb_account = 7 + +(** Convertion from [manager_state] to a {! Manager_operation_helper.infos}. *) +let infos_of_state source block infos : Manager.infos = + let open Manager in + let ({ctxt; accounts; flags} : infos) = infos in + let ctxt : ctxt = {ctxt with block} in + let accounts = {accounts with sources = [source]} in + {ctxt; accounts; flags} + +(** Updating a [manager_state] according to a {! Manager_operation_helper.infos}. *) +let update_state_with_infos {Manager.ctxt; accounts; flags} + {Manager.ctxt = ctxt2; accounts = accounts2; _} = + let ctxt = + { + ctxt with + originated_contract = ctxt2.originated_contract; + sc_rollup = ctxt2.sc_rollup; + zk_rollup = ctxt2.zk_rollup; + } + in + let accounts = + { + accounts with + dest = accounts2.dest; + del = accounts2.del; + sc = accounts2.sc; + zk = accounts2.zk; + } + in + {Manager.ctxt; accounts; flags} + +(** According to a [Manager.infos] and a block [b], create and fund + the required contracts and accounts on [b]. In additions to the + initiation performed by {! Manager_operation_helper.init_infos}, it + registers a list of funded sources. *) +let manager_prelude (infos : Manager.infos) b = + let open Lwt_result_syntax in + let nb_sources = List.length infos.ctxt.bootstraps in + let* ops_by_bootstrap = + List.map_es + (fun bootstrap -> + let bootstrap = Contract.Implicit bootstrap in + let* counter = Context.Contract.counter (B b) bootstrap in + return (bootstrap, counter, [])) + (List.take_n nb_sources infos.ctxt.bootstraps) + in + let add bootstrap counter ops ops_by_bootstrap = + List.map + (fun (bootstrap', counter', ops') -> + if bootstrap' = bootstrap then + (bootstrap, Manager_counter.succ counter, ops) + else (bootstrap', counter', ops')) + ops_by_bootstrap + in + let batches block ops_by_bootstrap = + List.fold_left_es + (fun acc (source, _counter, operations) -> + match operations with + | [] -> return (List.rev acc) + | _ -> + let* batch = Op.batch_operations ~source (B block) operations in + return (batch :: acc)) + [] + ops_by_bootstrap + in + let create_and_fund sources ops_by_bootstrap = + let account = Account.new_account () in + let n = nb_sources - Stdlib.List.length sources in + let bootstrap, counter, ops = Stdlib.List.nth ops_by_bootstrap (n - 1) in + let amount = Tez.of_mutez (Int64.of_int 150000) in + let+ op, counter = + Manager.fund_account_op b bootstrap account.pkh amount counter + in + (account :: sources, add bootstrap counter (op :: ops) ops_by_bootstrap) + in + let* sources, src_operations = + List.fold_left_es + (fun (acc_accounts, acc_ops) _ -> create_and_fund acc_accounts acc_ops) + ([], ops_by_bootstrap) + (1 -- nb_sources) + in + let* operations = batches b src_operations in + let infos = {infos with accounts = {infos.accounts with sources}} in + let* infos2 = + Manager.init_infos + Manager.ctxt_req_default + b + (List.take_n required_nb_account infos.ctxt.bootstraps) + in + let state = update_state_with_infos infos infos2 in + return (operations, state) + +(** Build a manager operation according to the information in [infos] + on [block] for each source in the [manager_state] guaranteeing + that they are not conflicting. *) +let manager_candidates block infos batch_max_size = + let open Lwt_result_syntax in + let params = + List.map + (fun src -> + let m = gen_bounded_int 1 batch_max_size in + let kd = pick_n m Manager.revealed_subjects in + (src, kd)) + infos.Manager.accounts.sources + in + let gen (source, ks) = + let infos = infos_of_state source block infos in + let* reveal = + Manager.mk_reveal (Manager.operation_req_default Manager.K_Reveal) infos + in + let* operations = + List.map_es + (fun kd -> Manager.select_op (Manager.operation_req_default kd) infos) + ks + in + let* operations = return (reveal :: operations) in + Op.batch_operations + ~recompute_counters:true + ~source:(Contract.Implicit source.pkh) + (B block) + operations + in + List.map_es gen params + +let manager_descriptor max_batch_size nb_accounts = + { + parameters = + (fun params -> + let ctxt_req_default = Manager.ctxt_req_default in + let hard_gas_limit_per_block = + Some (Gas.Arith.integral_of_int_exn ((nb_accounts + 1) * 5_200_000)) + in + let ctxt_req = {ctxt_req_default with hard_gas_limit_per_block} in + Manager.manager_parameters params ctxt_req); + required_cycle = (fun _ -> 1); + required_block = (fun _ -> 1); + prelude = + ( On 1, + fun state -> + let open Lwt_result_syntax in + let* ops, manager = manager_prelude state.manager state.block in + let state = {state with manager} in + return (ops, state) ); + opt_prelude = None; + candidates_generator = + (fun state -> manager_candidates state.block state.manager max_batch_size); + } + +type op_kind = + | KAttestation + | KPreattestation + | KBallotExp + | KBallotProm + | KProposals + | KNonce + | KVdf + | KActivate + | KDbl_consensus + | KDbl_baking + | KDrain + | KManager + +let op_kind_of_packed_operation op = + let (Operation_data {contents; _}) = op.protocol_data in + match contents with + | Single (Preattestation _) -> KPreattestation + | Single (Attestation _) -> KAttestation + | Single (Seed_nonce_revelation _) -> KNonce + | Single (Vdf_revelation _) -> KVdf + | Single (Double_attestation_evidence _) -> KDbl_consensus + | Single (Double_preattestation_evidence _) -> KDbl_consensus + | Single (Double_baking_evidence _) -> KDbl_baking + | Single (Activate_account _) -> KActivate + | Single (Proposals _) -> KProposals + | Single (Ballot _) -> KBallotExp + | Single (Drain_delegate _) -> KDrain + | Single (Manager_operation _) -> KManager + | Cons (Manager_operation _, _) -> KManager + | Single (Failing_noop _) -> assert false + +let pp_op_kind fmt kind = + Format.fprintf + fmt + (match kind with + | KManager -> "manager" + | KAttestation -> "attestation" + | KPreattestation -> "preattestation" + | KBallotExp -> "ballot" + | KBallotProm -> "ballot" + | KProposals -> "proposals" + | KNonce -> "nonce" + | KVdf -> "vdf_revelation" + | KActivate -> "activate_account" + | KDbl_consensus -> "double_consensus" + | KDbl_baking -> "double_baking" + | KDrain -> "drain_delegate") + +let descriptor_of ~nb_bootstrap ~max_batch_size = function + | KManager -> manager_descriptor max_batch_size nb_bootstrap + | KAttestation -> attestation_descriptor + | KPreattestation -> preattestation_descriptor + | KBallotExp -> ballot_exploration_descriptor + | KBallotProm -> ballot_promotion_descriptor + | KProposals -> proposal_descriptor + | KNonce -> seed_nonce_descriptor + | KVdf -> vdf_revelation_descriptor + | KActivate -> activate_descriptor + | KDbl_consensus -> double_consensus_descriptor + | KDbl_baking -> double_baking_descriptor + | KDrain -> drain_delegate_descriptor + +let descriptors_of ~nb_bootstrap ~max_batch_size = + List.map (descriptor_of ~nb_bootstrap ~max_batch_size) + +(** A context is in a unique voting period. *) +let voting_kinds = [KProposals; KBallotExp; KBallotProm] + +(** A context either wait for nonce revelation or vdf revelation + but not both at the same time. *) +let nonce_generation_kinds = [KNonce; KVdf] + +(** All kind list, used in the sanity check.*) +let non_exclusive_kinds = + [ + KManager; + KAttestation; + KPreattestation; + KActivate; + KDbl_consensus; + KDbl_baking; + KDrain; + ] + +let all_kinds = voting_kinds @ nonce_generation_kinds @ non_exclusive_kinds diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.mli b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.mli new file mode 100644 index 000000000000..f9931fee84e2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generator_descriptors.mli @@ -0,0 +1,161 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Validate_helpers + +(** {2 Generation state} *) + +(** The state to generate valid double pre- and attestation evidence + contains a temporary state for making the slashable evidence, and + the lists of slashables operations, one for each kind: + preattestation and attestation. *) +type dbl_attestation_state = { + temporary : (Block.t * Block.t) option; + slashable_preattestations : + (Kind.preattestation operation * Kind.preattestation operation) list; + slashable_attestations : + (Kind.attestation operation * Kind.attestation operation) list; +} + +(** Generic generation state collecting + information to generate any kind of operation. + + For example, {!Manager.infos} for manager + or voters (Contract.t list) for voting operations... + + When adding a new operation kind, [state] might be extended if a + new kind of information is required for this new kind valid + operations generation. *) +type state = { + block : Block.t; + pred : Block.t option; + bootstraps : public_key_hash list; + delegates : (public_key_hash * public_key_hash option) list; + voters : Contract.t list; + seed_nonce_to_reveal : (Raw_level.t * Nonce_hash.t) list; + commitments : secret_account list; + protocol_hashes : Protocol_hash.t list; + slashable_bakes : (block_header * block_header) list; + vdf : bool; + dbl_attestation : dbl_attestation_state; + manager : Manager.infos; +} + +(** The initialization of a [state] requires the [voters] contracts -- + the contracts allowed to vote -- and the [bootstraps] contracts. *) +val init_state : + Block.t -> voters:Contract.t list -> bootstraps:Contract.t list -> state + +(** {2 Descriptor for valid operations generation} *) + +(** Each prelude action either takes place on a specific cycle or + from a specific cycle to the end a the context setting. *) +type cycle_index = On of int | From of int + +(** Descriptors are specific to operation kinds, [op_kind]. A + descriptor provides the information and functions used in the + context setup to generate valid operations of its kind and a + generator for such operations. + + - [parameters] enables setting constants in the initial context. + + - [required_cycle] is the number of cycles in the context setup + before generating valid operations of this kind. + + - [required_block] the number of blocks in the last cycle. + + - [prelude] is a set of actions that either gather information in + the setup [state] or perform operations in the setup blocks or both + that have to be performed according to a [cycle_index]. + + - [opt_prelude] is an optional prelude. + + - [candidates_generator] generates operations of the descriptor + [op_kind] according to the information in [state] that are valid + upon [state.block]. *) +type descriptor = { + parameters : Parameters.t -> Parameters.t; + required_cycle : Parameters.t -> int; + required_block : Parameters.t -> int; + prelude : + cycle_index * (state -> (packed_operation list * state) tzresult Lwt.t); + opt_prelude : + (cycle_index * (state -> (packed_operation list * state) tzresult Lwt.t)) + option; + candidates_generator : state -> packed_operation list tzresult Lwt.t; +} + +(** {2 Operation kinds} *) + +(** When adding a new operation: + - a new op_kind [k] should extend the [op_kind] type, + - a [descriptor] defined, + - [descriptor_of] must associate this new descriptor to [k], + - [k] must be added to [all_kinds], + - If the validity of [k] operations is not exclusive with the + validity of other [op_kind], [k] must be added to + [non_exclusive_kinds]. Otherwise, see, for example, how voting + operation op_kinds are handled in {! test_covalidity.tests}. *) +type op_kind = + | KAttestation + | KPreattestation + | KBallotExp + | KBallotProm + | KProposals + | KNonce + | KVdf + | KActivate + | KDbl_consensus + | KDbl_baking + | KDrain + | KManager + +val pp_op_kind : Format.formatter -> op_kind -> unit + +(** This sanity function returns the [op_kind] associated to + an [packed_operation].*) +val op_kind_of_packed_operation : packed_operation -> op_kind + +(** Associate to each [op_kind] a [descriptor]. Some descriptors are + parametrized by the number of bootstraps and the maximum size of a + batch.*) +val descriptor_of : + nb_bootstrap:int -> max_batch_size:int -> op_kind -> descriptor + +(** Given a list of [op_kind] returns the list of corresponding + descriptors as provided by [descriptor_of] for each [op_kind]. + Some descriptors are parametrized by the number of bootstraps and + the maximum size of a batch.*) +val descriptors_of : + nb_bootstrap:int -> max_batch_size:int -> op_kind list -> descriptor list + +(** List of all [op_kind] that are non exclusive (i.e. no voting +operation kind or nonce revelation kind) *) +val non_exclusive_kinds : op_kind trace + +(** List of all [op_kind] used for sanity check. *) +val all_kinds : op_kind list diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generators.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generators.ml new file mode 100644 index 000000000000..60f1659e74a4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/generators.ml @@ -0,0 +1,258 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Manager_operation_helpers + +let lwt_run f = + match Lwt_main.run f with + | Error err -> + QCheck.Test.fail_reportf "@.Lwt_main.run error: %a@." pp_print_trace err + | Ok v -> v + +(** {2 Datatypes} *) + +(** Constraints on generated values. + + {ul + {li [Free] states that nothing has to be generated} + + {li [Pure n] generate n} + + {li [Less {n;origin}] (resp Greater) states the expected + constraints for the generated values that must be lesser (resp + greater) than [n] and shrink toward [origin] in case of error} + + {li [Range {min;max;origin}] states the expected constraints for + the generated values that must be between [min] and [max] and + shrink toward [origin] in case of error.}} *) +type cstrs = + | Free + | Pure of int + | Less of {n : int; origin : int} + | Greater of {n : int; origin : int} + | Range of {min : int; max : int; origin : int} + +(** Gas frequency. *) +type gas_freq = { + low : int; + max : int; + high : int; + zero : int; + custom : int * cstrs; +} + +(** Operation constraints. *) +type operation_cstrs = { + counter : cstrs; + fee : cstrs; + gas_limit : gas_freq; + storage_limit : cstrs; + force_reveal : bool option; + amount : cstrs; +} + +(** Context constraints. *) +type ctxt_cstrs = { + hard_gas_limit_per_block : cstrs; + src_cstrs : cstrs; + dest_cstrs : cstrs; + del_cstrs : cstrs; + sc_cstrs : cstrs; + zk_cstrs : cstrs; +} +(** {2 Default values} *) + +(** Default constraint. *) +let default_cstrs = Free + +(** Default gas frequency. *) +let default_gas_freq = + {low = 0; max = 0; high = 1; zero = 0; custom = (0, Free)} + +(** Default constraints for operation. *) +let default_operation_cstrs = + { + counter = default_cstrs; + fee = default_cstrs; + gas_limit = default_gas_freq; + storage_limit = default_cstrs; + force_reveal = None; + amount = default_cstrs; + } + +(** Default constraints for context. *) +let default_ctxt_cstrs = + { + hard_gas_limit_per_block = default_cstrs; + src_cstrs = default_cstrs; + dest_cstrs = default_cstrs; + del_cstrs = default_cstrs; + sc_cstrs = default_cstrs; + zk_cstrs = default_cstrs; + } + +(** {2 Generators} *) + +(** Generator of positive integers. *) +let gen_pos : cstrs -> int option QCheck2.Gen.t = + fun c -> + let open QCheck2.Gen in + match c with + | Free -> pure None + | Pure n -> pure (Some n) + | Less {n; origin} -> + let+ v = int_range ~origin 0 n in + Some v + | Greater {n; origin} -> + let+ v = int_range ~origin n max_int in + Some v + | Range {min; max; origin} -> + let+ v = int_range ~origin min max in + Some v + +(** Generator for Z.t that is used for gas limit. *) +let gen_z : cstrs -> Z.t option QCheck2.Gen.t = + fun cstrs -> + let open QCheck2.Gen in + let+ v = gen_pos cstrs in + Option.map Z.of_int v + +(** Generator for Manager_counter.t. *) +let gen_counter : cstrs -> Manager_counter.t option QCheck2.Gen.t = + fun cstrs -> + let open QCheck2.Gen in + let+ v = gen_pos cstrs in + Option.map Manager_counter.Internal_for_tests.of_int v + +(** Generator for Tez.t. *) +let gen_tez : cstrs -> Tez.t option QCheck2.Gen.t = + fun cstrs -> + let open QCheck2.Gen in + let+ amount = gen_pos cstrs in + match amount with + | Some amount -> + let amount = Int64.of_int amount in + Tez.of_mutez amount + | None -> None + +(** Generator for gas integral. *) +let gen_gas_integral : cstrs -> Gas.Arith.integral option QCheck2.Gen.t = + fun cstrs -> + let open QCheck2.Gen in + let+ v = gen_pos cstrs in + Option.map Gas.Arith.integral_of_int_exn v + +(** Generator for Op.gas_limit. *) +let gen_gas_limit : gas_freq -> Op.gas_limit option QCheck2.Gen.t = + fun gas_freq -> + let open QCheck2.Gen in + frequency + [ + (gas_freq.low, return (Some Op.Low)); + (gas_freq.max, return (Some Op.Max)); + (gas_freq.high, return (Some Op.High)); + (gas_freq.zero, return (Some Op.Zero)); + (let freq, cstrs = gas_freq.custom in + ( freq, + let+ gas = gen_gas_integral cstrs in + match gas with None -> None | Some g -> Some (Op.Custom_gas g) )); + ] + +(** Generator for manager_operation_kind. *) +let gen_kind : + manager_operation_kind list -> manager_operation_kind QCheck2.Gen.t = + fun subjects -> QCheck2.Gen.oneofl subjects + +(** Generator for mode. *) +let gen_mode : mode QCheck2.Gen.t = + QCheck2.Gen.oneofl [Construction; Mempool; Application] + +(** Generator for operation requirements. *) +let gen_operation_req : + operation_cstrs -> + manager_operation_kind list -> + operation_req QCheck2.Gen.t = + fun {counter; fee; gas_limit; storage_limit; force_reveal; amount} subjects -> + let open QCheck2.Gen in + let* kind = gen_kind subjects in + let* counter = gen_counter counter in + let* fee = gen_tez fee in + let* gas_limit = gen_gas_limit gas_limit in + let* storage_limit = gen_z storage_limit in + let+ amount = gen_tez amount in + {kind; counter; fee; gas_limit; storage_limit; force_reveal; amount} + +(** Generator for a pair of operations with the same source and + sequential counters.*) +let gen_2_operation_req : + operation_cstrs -> + manager_operation_kind list -> + (operation_req * operation_req) QCheck2.Gen.t = + fun op_cstrs subjects -> + let open QCheck2.Gen in + let* op1 = + gen_operation_req {op_cstrs with force_reveal = Some true} subjects + in + let counter = + match op1.counter with + | Some x -> Manager_counter.Internal_for_tests.to_int x + | None -> 1 + in + let op_cstr = + { + {op_cstrs with counter = Pure (counter + 2)} with + force_reveal = Some false; + } + in + let+ op2 = gen_operation_req op_cstr subjects in + (op1, op2) + +(** Generator for context requirement. *) +let gen_ctxt_req : ctxt_cstrs -> ctxt_req QCheck2.Gen.t = + fun { + hard_gas_limit_per_block; + src_cstrs; + dest_cstrs; + del_cstrs; + sc_cstrs; + zk_cstrs; + } -> + let open QCheck2.Gen in + let* hard_gas_limit_per_block = gen_gas_integral hard_gas_limit_per_block in + let* fund_src = gen_tez src_cstrs in + let* fund_dest = gen_tez dest_cstrs in + let* fund_del = gen_tez del_cstrs in + let* fund_sc = gen_tez sc_cstrs in + let+ fund_zk = gen_tez zk_cstrs in + { + hard_gas_limit_per_block; + fund_src; + fund_dest; + fund_del; + reveal_accounts = true; + fund_sc; + fund_zk; + flags = all_enabled; + } + +(** {2 Wrappers} *) + +let wrap ~name ?print ?(count = 1) ?check ~(gen : 'a QCheck2.Gen.t) + (f : 'a -> bool tzresult Lwt.t) = + Qcheck2_helpers.qcheck_make_result_lwt + ~name + ?print + ~count + ?check + ~extract:Lwt_main.run + ~pp_error:pp_print_trace + ~gen + f + +let wrap_mode infos op mode = validate_diagnostic ~mode infos op diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/manager_operation_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/manager_operation_helpers.ml new file mode 100644 index 000000000000..a13fe3bdb662 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/manager_operation_helpers.ml @@ -0,0 +1,1391 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Test_tez + +(** {2 Constants} *) + +(** Hard gas limit *) + +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. *) +type ctxt = { + block : Block.t; + bootstraps : public_key_hash list; + originated_contract : Contract_hash.t option; + sc_rollup : Sc_rollup.t option; + zk_rollup : Zk_rollup.t option; +} + +(** Accounts manipulated in the tests. By convention, each field name + specifies the role of the account in a test. It is the case in most + of the tests. In operations smart contructors, it happens that in + impossible case, [source] is used as a dummy value. In some test that + requires a second source, [del] will be used as the second source. *) +type accounts = { + sources : Account.t list; + dest : Account.t option; + del : Account.t option; + sc : Account.t option; + zk : Account.t option; +} + +(** Feature flags requirements for a context setting for a test. *) +type feature_flags = {dal : bool; scoru_arith : bool; zkru : bool} + +(** Infos describes the information of the setting for a test: the + context and used accounts. *) +type infos = {ctxt : ctxt; accounts : accounts; flags : feature_flags} + +(** This type should be extended for each new manager_operation kind + added in the protocol. See + [test_manager_operation_validation.ensure_kind] for more + information on how we ensure that this type is extended for each + new manager_operation kind. *) +type manager_operation_kind = + | K_Transaction + | K_Origination + | K_Register_global_constant + | K_Delegation + | K_Undelegation + | K_Self_delegation + | K_Set_deposits_limit + | K_Update_consensus_key + | K_Increase_paid_storage + | K_Reveal + | K_Transfer_ticket + | K_Sc_rollup_origination + | K_Sc_rollup_publish + | K_Sc_rollup_cement + | K_Sc_rollup_add_messages + | K_Sc_rollup_refute + | K_Sc_rollup_timeout + | K_Sc_rollup_execute_outbox_message + | K_Sc_rollup_recover_bond + | K_Dal_publish_commitment + | K_Zk_rollup_origination + | K_Zk_rollup_publish + | K_Zk_rollup_update + +(** The requirements for a tested manager operation. *) +type operation_req = { + kind : manager_operation_kind; + counter : Manager_counter.t option; + fee : Tez.t option; + gas_limit : Op.gas_limit option; + storage_limit : Z.t option; + force_reveal : bool option; + amount : Tez.t option; +} + +(** The requirements for a context setting for a test. *) +type ctxt_req = { + hard_gas_limit_per_block : Gas.Arith.integral option; + fund_src : Tez.t option; + fund_dest : Tez.t option; + fund_del : Tez.t option; + reveal_accounts : bool; + fund_sc : Tez.t option; + fund_zk : Tez.t option; + flags : feature_flags; +} + +(** Validation mode. + + FIXME: https://gitlab.com/tezos/tezos/-/issues/3365 + This type should be replaced by the one defined + in validation, type mode in `validate_operation`, when it would + include the distinction between Contruction and Application. *) +type mode = Construction | Mempool | Application + +(** {2 Default values} *) +let all_enabled = {dal = true; scoru_arith = true; zkru = true} + +let disabled_dal = {all_enabled with dal = false} + +let disabled_scoru_arith = {all_enabled with scoru_arith = false} + +let disabled_zkru = {all_enabled with zkru = false} + +let ctxt_req_default_to_flag flags = + { + hard_gas_limit_per_block = None; + fund_src = Some default_fund; + fund_dest = Some Tez.one; + fund_del = Some default_fund; + reveal_accounts = true; + fund_sc = Some Tez.one; + fund_zk = Some Tez.one; + flags; + } + +let ctxt_req_default = ctxt_req_default_to_flag all_enabled + +let operation_req_default kind = + { + kind; + counter = None; + fee = None; + gas_limit = None; + storage_limit = None; + force_reveal = None; + amount = None; + } + +(** {2 String_of data} *) +let kind_to_string = function + | K_Transaction -> "Transaction" + | K_Delegation -> "Delegation" + | K_Undelegation -> "Undelegation" + | K_Self_delegation -> "Self-delegation" + | K_Set_deposits_limit -> "Set deposits limit" + | K_Update_consensus_key -> "Update consensus key" + | K_Origination -> "Origination" + | K_Register_global_constant -> "Register global constant" + | K_Increase_paid_storage -> "Increase paid storage" + | K_Reveal -> "Revelation" + | K_Transfer_ticket -> "Transfer_ticket" + | K_Sc_rollup_origination -> "Sc_rollup_origination" + | K_Sc_rollup_publish -> "Sc_rollup_publish" + | K_Sc_rollup_cement -> "Sc_rollup_cement" + | K_Sc_rollup_timeout -> "Sc_rollup_timeout" + | K_Sc_rollup_refute -> "Sc_rollup_refute" + | K_Sc_rollup_add_messages -> "Sc_rollup_add_messages" + | K_Sc_rollup_execute_outbox_message -> "Sc_rollup_execute_outbox_message" + | K_Sc_rollup_recover_bond -> "Sc_rollup_recover_bond" + | K_Dal_publish_commitment -> "Dal_publish_commitment" + | K_Zk_rollup_origination -> "Zk_rollup_origination" + | K_Zk_rollup_publish -> "Zk_rollup_publish" + | K_Zk_rollup_update -> "Zk_rollup_update" + +(** {2 Pretty-printers} *) +let pp_opt pp v = + let open Format in + pp_print_option ~none:(fun fmt () -> fprintf fmt "None") pp v + +let pp_operation_req pp + {kind; counter; fee; gas_limit; storage_limit; force_reveal; amount} = + Format.fprintf + pp + "@[Operation_req:@,\ + kind: %s@,\ + counter: %a@,\ + fee: %a@,\ + gas_limit: %a@,\ + storage_limit: %a@,\ + force_reveal: %a@,\ + amount: %a@,\ + @]" + (kind_to_string kind) + (pp_opt Manager_counter.pp) + counter + (pp_opt Tez.pp) + fee + (pp_opt Op.pp_gas_limit) + gas_limit + (pp_opt Z.pp_print) + storage_limit + (pp_opt (fun fmt -> Format.fprintf fmt "%b")) + force_reveal + (pp_opt Tez.pp) + amount + +let pp_2_operation_req pp (op_req1, op_req2) = + Format.fprintf + pp + "[ %a,@ and %a,@ @]" + pp_operation_req + op_req1 + pp_operation_req + op_req2 + +let pp_ctxt_req pp + { + hard_gas_limit_per_block; + fund_src; + fund_dest; + fund_del; + reveal_accounts; + fund_sc; + fund_zk; + flags; + } = + Format.fprintf + pp + "@[Ctxt_req:@,\ + hard_gas_limit_per_block:%a@,\ + fund_src: %a tz@,\ + fund_dest: %a tz@,\ + fund_del: %a tz@,\ + reveal_accounts: %b tz@,\ + fund_sc: %a tz@,\ + fund_zk: %a tz@,\ + dal_flag: %a@,\ + scoru_arith_flag: %a@,\ + zkru_flag: %a@,\ + @]" + (pp_opt Gas.Arith.pp_integral) + hard_gas_limit_per_block + (pp_opt Tez.pp) + fund_src + (pp_opt Tez.pp) + fund_dest + (pp_opt Tez.pp) + fund_del + reveal_accounts + (pp_opt Tez.pp) + fund_sc + (pp_opt Tez.pp) + fund_zk + Format.pp_print_bool + flags.dal + Format.pp_print_bool + flags.scoru_arith + Format.pp_print_bool + flags.zkru + +let pp_mode pp = function + | Construction -> Format.fprintf pp "Construction" + | Mempool -> Format.fprintf pp "Mempool" + | Application -> Format.fprintf pp "Block" + +(** {2 Short-cuts} *) +let contract_of (account : Account.t) = Contract.Implicit account.pkh + +(** Make a [mempool_mode], aka a boolean, as used in incremental from + a [mode]. *) +let mempool_mode_of = function Mempool -> true | _ -> false + +let get_pk infos source = + let open Lwt_result_syntax in + let+ account = Context.Contract.manager infos source in + account.pk + +(** Operation for specific context. *) +let self_delegate block pkh = + let open Lwt_result_syntax in + let contract = Contract.Implicit pkh in + let* operation = + Op.delegation ~force_reveal:true (B block) contract (Some pkh) + in + let* block = Block.bake block ~operation in + let* del_opt_new = Context.Contract.delegate_opt (B block) contract in + let* del = Assert.get_some ~loc:__LOC__ del_opt_new in + let+ () = Assert.equal_pkh ~loc:__LOC__ del pkh in + block + +let delegation block source delegate = + let open Lwt_result_syntax in + let delegate_pkh = delegate.Account.pkh in + let contract_source = contract_of source in + let* operation = + Op.delegation + ~force_reveal:true + (B block) + contract_source + (Some delegate_pkh) + in + 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 + return block + +let originate_sc_rollup block rollup_account = + let open Lwt_result_syntax in + let rollup_contract = contract_of rollup_account in + let kind = Sc_rollup.Kind.Example_arith in + let* rollup_origination, sc_rollup = + Sc_rollup_helpers.origination_op + ~force_reveal:true + (B block) + rollup_contract + kind + in + let+ block = + Block.bake ~allow_manager_failures:true ~operation:rollup_origination block + in + (block, sc_rollup) + +module ZKOperator = Dummy_zk_rollup.Operator (struct + let batch_size = 10 +end) + +let originate_zk_rollup block rollup_account = + let open Lwt_result_syntax in + let rollup_contract = contract_of rollup_account in + let _prover_pp, public_parameters = Lazy.force ZKOperator.lazy_pp in + let* rollup_origination, zk_rollup = + Op.zk_rollup_origination + ~force_reveal:true + (B block) + rollup_contract + ~public_parameters + ~circuits_info: + (Zk_rollup.Account.SMap.of_seq @@ Kzg.SMap.to_seq ZKOperator.circuits) + ~init_state:ZKOperator.init_state + ~nb_ops:1 + in + let+ block = + Block.bake ~allow_manager_failures:true ~operation:rollup_origination block + in + (block, zk_rollup) + +(** {2 Setting's context construction} *) + +let fund_account_op block bootstrap account fund counter = + let open Lwt_result_wrap_syntax in + let* fund = + match fund with + | None -> return Tez.one + | Some fund -> + let* source_balance = Context.Contract.balance (B block) bootstrap in + if Tez.(fund > source_balance) then + let*?@ result = Tez.(source_balance -? one) in + return result + else return fund + in + let+ op = + Op.transaction + ~counter + ~gas_limit:Op.High + (B block) + bootstrap + (Contract.Implicit account) + fund + in + (op, Manager_counter.succ counter) + +let fund_account block bootstrap account fund = + let open Lwt_result_syntax in + let* counter = Context.Contract.counter (B block) bootstrap in + let* operation, (_counter : Manager_counter.t) = + fund_account_op block bootstrap account fund counter + in + let*! b = Block.bake ~operation block in + match b with Error _ -> failwith "Funding account error" | Ok b -> return b + +(** Set the constants according to a [ctxt_req] in an existing parameters. *) +let manager_parameters : Parameters.t -> ctxt_req -> Parameters.t = + fun params {hard_gas_limit_per_block; flags; _} -> + let hard_gas_limit_per_block = + match hard_gas_limit_per_block with + | Some gb -> gb + | None -> Default_parameters.constants_mainnet.hard_gas_limit_per_block + in + let dal = {params.constants.dal with feature_enable = flags.dal} in + let sc_rollup = + {params.constants.sc_rollup with arith_pvm_enable = flags.scoru_arith} + in + let zk_rollup = {params.constants.zk_rollup with enable = flags.zkru} in + let constants = + {params.constants with hard_gas_limit_per_block; dal; zk_rollup; sc_rollup} + in + {params with constants} + +(** Initialize a context with the constants extracted from a context requirements + and 7 bootstrap accounts. *) +let init_ctxt_only ctxtreq = + let open Lwt_result_syntax in + let initial_params = + Tezos_protocol_020_PsParisC_parameters.Default_parameters + .parameters_of_constants + {Context.default_test_constants with consensus_threshold = 0} + in + let*? _cryptobox = + Dal_helpers.mk_cryptobox initial_params.constants.dal.cryptobox_parameters + in + let* block, contracts = + Context.init_with_parameters_n (manager_parameters initial_params ctxtreq) 7 + in + return + ( block, + List.map + (function Contract.Implicit pkh -> pkh | Originated _ -> assert false) + contracts ) + +(** Build a generic setting for a test according to a context requirement + on an existing context with 7 bootstraps accounts. *) +let init_infos : + ctxt_req -> Block.t -> public_key_hash list -> infos tzresult Lwt.t = + fun ctxtreq block bootstraps -> + let { + fund_src; + fund_dest; + fund_del; + fund_sc; + fund_zk; + flags; + reveal_accounts; + _; + } = + ctxtreq + in + let open Lwt_result_syntax in + let create_and_fund ?originate_rollup block bootstrap fund = + match fund with + | None -> return (block, None, None) + | Some _ -> + let account = Account.new_account () in + let* block = fund_account block bootstrap account.pkh fund in + let* block, rollup = + match originate_rollup with + | None -> return (block, None) + | Some f -> + let+ block, rollup = f block account in + (block, Some rollup) + in + return (block, Some account, rollup) + in + let reveal_accounts_operations b l = + List.filter_map_es + (function + | None -> return_none + | Some account -> + let* op = Op.revelation ~gas_limit:Low (B b) account.Account.pk in + return_some op) + l + in + let get_bootstrap bootstraps n = + Contract.Implicit (Stdlib.List.nth bootstraps n) + in + let source = Account.new_account () in + let* block = + fund_account block (get_bootstrap bootstraps 0) source.pkh fund_src + in + let* block, dest, _ = + create_and_fund block (get_bootstrap bootstraps 1) fund_dest + in + let* block, del, _ = + create_and_fund block (get_bootstrap bootstraps 2) fund_del + in + let* block, sc, sc_rollup = + if flags.scoru_arith then + create_and_fund + ~originate_rollup:originate_sc_rollup + block + (get_bootstrap bootstraps 4) + fund_sc + else return (block, None, None) + in + let* block, zk, zk_rollup = + if flags.zkru then + create_and_fund + ~originate_rollup:originate_zk_rollup + block + (get_bootstrap bootstraps 5) + fund_zk + else return (block, None, None) + in + let* create_contract_hash, originated_contract = + Op.contract_origination_hash + (B block) + (get_bootstrap bootstraps 6) + ~fee:Tez.zero + ~script:Op.dummy_script + in + let* reveal_operations = + if reveal_accounts then + reveal_accounts_operations block [Some source; dest; del] + else return_nil + in + let operations = create_contract_hash :: reveal_operations in + let+ block = Block.bake ~operations block in + let ctxt = + { + block; + bootstraps; + originated_contract = Some originated_contract; + sc_rollup; + zk_rollup; + } + in + {ctxt; accounts = {sources = [source]; dest; del; sc; zk}; flags} + +(** The generic setting for a test is built up according to a context + requirement. It provides a context and accounts where the accounts + have been created and funded according to the context + requirements.*) +let init_ctxt : ctxt_req -> infos tzresult Lwt.t = + fun ctxtreq -> + let open Lwt_result_syntax in + let* block, bootstraps = init_ctxt_only ctxtreq in + init_infos ctxtreq block bootstraps + +(** return the first source from the list of sources in [infos] accounts. *) +let get_source infos = + match infos.accounts.sources with source :: _ -> source | [] -> assert false + +(** In addition of building up a context according to a context + requirement, source is self-delegated. + + see [init_ctxt] description. *) +let ctxt_with_self_delegation : ctxt_req -> infos tzresult Lwt.t = + fun ctxt_req -> + let open Lwt_result_syntax in + let* infos = init_ctxt ctxt_req in + let+ block = self_delegate infos.ctxt.block (get_source infos).pkh in + let ctxt = {infos.ctxt with block} in + {infos with ctxt} + +(** In addition of building up a context accordning to a context + requirement, source delegates to del. + + See [init_ctxt] description. *) +let ctxt_with_delegation : ctxt_req -> infos tzresult Lwt.t = + fun ctxt_req -> + let open Lwt_result_syntax in + let* infos = init_ctxt ctxt_req in + let* delegate = + match infos.accounts.del with + | None -> failwith "Delegate account should be funded" + | Some a -> return a + in + let* block = delegation infos.ctxt.block delegate delegate in + let+ block = delegation block (get_source infos) delegate in + let ctxt = {infos.ctxt with block} in + {infos with ctxt} + +let default_init_ctxt () = init_ctxt ctxt_req_default + +let default_init_with_flags flags = init_ctxt (ctxt_req_default_to_flag flags) + +let default_ctxt_with_self_delegation () = + ctxt_with_self_delegation ctxt_req_default + +let default_ctxt_with_delegation () = ctxt_with_delegation ctxt_req_default + +(** {2 Smart constructors} *) + +(** Smart constructors to forge manager operations according to + operation requirements in a test setting. *) + +let mk_transaction (oinfos : operation_req) (infos : infos) = + Op.transaction + ?force_reveal:oinfos.force_reveal + ?counter:oinfos.counter + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + (contract_of (get_source infos)) + (contract_of + (match infos.accounts.dest with + | None -> get_source infos + | Some dest -> dest)) + (match oinfos.amount with None -> Tez.zero | Some amount -> amount) + +let mk_delegation (oinfos : operation_req) (infos : infos) = + Op.delegation + ?force_reveal:oinfos.force_reveal + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + (contract_of (get_source infos)) + (Some + (match infos.accounts.del with + | None -> (get_source infos).pkh + | Some delegate -> delegate.pkh)) + +let mk_undelegation (oinfos : operation_req) (infos : infos) = + Op.delegation + ?force_reveal:oinfos.force_reveal + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + (contract_of (get_source infos)) + None + +let mk_self_delegation (oinfos : operation_req) (infos : infos) = + Op.delegation + ?force_reveal:oinfos.force_reveal + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + (contract_of (get_source infos)) + (Some (get_source infos).pkh) + +let mk_origination (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let+ op, _ = + Op.contract_origination + ?force_reveal:oinfos.force_reveal + ?counter:oinfos.counter + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + ~script:Op.dummy_script + (B infos.ctxt.block) + (contract_of (get_source infos)) + in + op + +let mk_register_global_constant (oinfos : operation_req) (infos : infos) = + Op.register_global_constant + ?force_reveal:oinfos.force_reveal + ?counter:oinfos.counter + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + ~source:(contract_of (get_source infos)) + ~value:(Script_repr.lazy_expr (Expr.from_string "Pair 1 2")) + +let mk_set_deposits_limit (oinfos : operation_req) (infos : infos) = + Op.set_deposits_limit + ?force_reveal:oinfos.force_reveal + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + ?counter:oinfos.counter + (B infos.ctxt.block) + (contract_of (get_source infos)) + None + +let mk_update_consensus_key (oinfos : operation_req) (infos : infos) = + Op.update_consensus_key + ?force_reveal:oinfos.force_reveal + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + ?counter:oinfos.counter + (B infos.ctxt.block) + (contract_of (get_source infos)) + (match infos.accounts.dest with + | None -> (get_source infos).pk + | Some dest -> dest.pk) + +let mk_increase_paid_storage (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* destination = + match infos.ctxt.originated_contract with + | None -> + failwith + "infos should be initialized with an origniated contract to be able \ + to add an increase_paid_storage operation." + | Some c -> return c + in + Op.increase_paid_storage + ?force_reveal:oinfos.force_reveal + ?counter:oinfos.counter + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + ~source:(contract_of (get_source infos)) + ~destination + Z.one + +let mk_reveal (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* pk = get_pk (B infos.ctxt.block) (contract_of (get_source infos)) in + Op.revelation + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + pk + +let sc_rollup_of = + let open Lwt_result_syntax in + function + | Some sc_rollup -> return sc_rollup + | None -> failwith "Sc_rollup not created in this context" + +let zk_rollup_of = + let open Lwt_result_syntax in + function + | Some zk_rollup -> return zk_rollup + | None -> failwith "Zk_rollup not created in this context" + +let mk_transfer_ticket (oinfos : operation_req) (infos : infos) = + Op.transfer_ticket + ?fee:oinfos.fee + ?force_reveal:oinfos.force_reveal + ?counter:oinfos.counter + ?gas_limit:oinfos.gas_limit + ?storage_limit:oinfos.storage_limit + (B infos.ctxt.block) + ~source:(contract_of (get_source infos)) + ~contents:(Script.lazy_expr (Expr.from_string "1")) + ~ty:(Script.lazy_expr (Expr.from_string "nat")) + ~ticketer: + (contract_of + (match infos.accounts.sc with + | None -> get_source infos + | Some tx -> tx)) + ~amount:Ticket_amount.one + ~destination: + (contract_of + (match infos.accounts.dest with + | None -> get_source infos + | Some dest -> dest)) + ~entrypoint:Entrypoint.default + +let mk_sc_rollup_origination (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let+ op, _ = + let kind = Sc_rollup.Kind.Example_arith in + Sc_rollup_helpers.origination_op + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + kind + in + op + +let sc_dummy_commitment = + let number_of_ticks = + match Sc_rollup.Number_of_ticks.of_value 3000L with + | None -> assert false + | Some x -> x + in + Sc_rollup.Commitment. + { + predecessor = Sc_rollup.Commitment.Hash.zero; + inbox_level = Raw_level.of_int32_exn Int32.zero; + number_of_ticks; + compressed_state = Sc_rollup.State_hash.zero; + } + +let mk_sc_rollup_publish (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* sc_rollup = sc_rollup_of infos.ctxt.sc_rollup in + Op.sc_rollup_publish + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + sc_rollup + sc_dummy_commitment + +let mk_sc_rollup_cement (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* sc_rollup = sc_rollup_of infos.ctxt.sc_rollup in + Op.sc_rollup_cement + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + sc_rollup + +let mk_sc_rollup_refute (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* sc_rollup = sc_rollup_of infos.ctxt.sc_rollup in + let refutation : Sc_rollup.Game.refutation = + Move {choice = Sc_rollup.Tick.initial; step = Dissection []} + in + Op.sc_rollup_refute + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + sc_rollup + (match infos.accounts.dest with + | None -> (get_source infos).pkh + | Some dest -> dest.pkh) + refutation + +let mk_sc_rollup_add_messages (oinfos : operation_req) (infos : infos) = + Op.sc_rollup_add_messages + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + [""] + +let mk_sc_rollup_timeout (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* sc_rollup = sc_rollup_of infos.ctxt.sc_rollup in + Op.sc_rollup_timeout + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + sc_rollup + (Sc_rollup.Game.Index.make + (get_source infos).pkh + (match infos.accounts.dest with + | None -> (get_source infos).pkh + | Some dest -> dest.pkh)) + +let mk_sc_rollup_execute_outbox_message (oinfos : operation_req) (infos : infos) + = + let open Lwt_result_syntax in + let* sc_rollup = sc_rollup_of infos.ctxt.sc_rollup in + Op.sc_rollup_execute_outbox_message + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + sc_rollup + (Sc_rollup.Commitment.hash_uncarbonated sc_dummy_commitment) + ~output_proof:"" + +let mk_sc_rollup_return_bond (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* sc_rollup = sc_rollup_of infos.ctxt.sc_rollup in + let source, staker = + match contract_of (get_source infos) with + | Implicit staker as source -> (source, staker) + | _ -> assert false + in + Op.sc_rollup_recover_bond + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + source + sc_rollup + staker + +let mk_dal_publish_commitment (oinfos : operation_req) (infos : infos) = + let slot_index = Alpha_context.Dal.Slot_index.zero in + let commitment = Alpha_context.Dal.Slot.Commitment.zero in + let commitment_proof = Alpha_context.Dal.Slot.Commitment_proof.zero in + let slot = + Dal.Operations.Publish_commitment.{slot_index; commitment; commitment_proof} + in + Op.dal_publish_commitment + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + slot + +let mk_zk_rollup_origination (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let _prover_pp, public_parameters = Lazy.force ZKOperator.lazy_pp in + let* op, _ = + Op.zk_rollup_origination + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + ~public_parameters + ~circuits_info: + (Zk_rollup.Account.SMap.of_seq @@ Kzg.SMap.to_seq ZKOperator.circuits) + ~init_state:ZKOperator.init_state + ~nb_ops:1 + in + return op + +let mk_zk_rollup_publish (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let open Zk_rollup.Operation in + let* zk_rollup = zk_rollup_of infos.ctxt.zk_rollup in + let l2_op = + {ZKOperator.Internal_for_tests.false_op with rollup_id = zk_rollup} + in + let* op = + Op.zk_rollup_publish + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + ~zk_rollup + ~ops:[(l2_op, None)] + in + return op + +let mk_zk_rollup_update (oinfos : operation_req) (infos : infos) = + let open Lwt_result_syntax in + let* zk_rollup = zk_rollup_of infos.ctxt.zk_rollup in + let update = Lazy.force ZKOperator.Internal_for_tests.lazy_update_data in + let* op = + Op.zk_rollup_update + ?fee:oinfos.fee + ?gas_limit:oinfos.gas_limit + ?counter:oinfos.counter + ?storage_limit:oinfos.storage_limit + ?force_reveal:oinfos.force_reveal + (B infos.ctxt.block) + (contract_of (get_source infos)) + ~zk_rollup + ~update + in + return op + +(** {2 Helpers for generation of generic check tests by manager operation} *) + +(** Generic forge for any kind of manager operation according to + operation requirements in a specific test setting. *) +let select_op (op_req : operation_req) (infos : infos) = + let mk_op = + match op_req.kind with + | K_Transaction -> mk_transaction + | K_Origination -> mk_origination + | K_Register_global_constant -> mk_register_global_constant + | K_Delegation -> mk_delegation + | K_Undelegation -> mk_undelegation + | K_Self_delegation -> mk_self_delegation + | K_Set_deposits_limit -> mk_set_deposits_limit + | K_Update_consensus_key -> mk_update_consensus_key + | K_Increase_paid_storage -> mk_increase_paid_storage + | K_Reveal -> mk_reveal + | K_Transfer_ticket -> mk_transfer_ticket + | K_Sc_rollup_origination -> mk_sc_rollup_origination + | K_Sc_rollup_publish -> mk_sc_rollup_publish + | K_Sc_rollup_cement -> mk_sc_rollup_cement + | K_Sc_rollup_refute -> mk_sc_rollup_refute + | K_Sc_rollup_add_messages -> mk_sc_rollup_add_messages + | K_Sc_rollup_timeout -> mk_sc_rollup_timeout + | K_Sc_rollup_execute_outbox_message -> mk_sc_rollup_execute_outbox_message + | K_Sc_rollup_recover_bond -> mk_sc_rollup_return_bond + | K_Dal_publish_commitment -> mk_dal_publish_commitment + | K_Zk_rollup_origination -> mk_zk_rollup_origination + | K_Zk_rollup_publish -> mk_zk_rollup_publish + | K_Zk_rollup_update -> mk_zk_rollup_update + in + mk_op op_req infos + +let make_tztest ?(fmt = Format.std_formatter) name test subjects info_builder = + let open Lwt_result_syntax in + Tztest.tztest name `Quick (fun () -> + let* infos = info_builder () in + List.iter_es + (fun kind -> + Format.fprintf fmt "%s: %s@." name (kind_to_string kind) ; + test infos kind) + subjects) + +let make_tztest_batched ?(fmt = Format.std_formatter) name test subjects + info_builder = + let open Lwt_result_syntax in + Tztest.tztest name `Quick (fun () -> + let* infos = info_builder () in + List.iter_es + (fun kind1 -> + let k1s = kind_to_string kind1 in + List.iter_es + (fun kind2 -> + Format.fprintf + fmt + "%s: [%s ; %s]@." + name + k1s + (kind_to_string kind2) ; + test infos kind1 kind2) + subjects) + subjects) + +(** {2 Diagnostic helpers.} *) + +(** The purpose of diagnostic helpers is to state the correct + observation according to the validate result of a test. *) + +(** For a manager operation a [probes] contains the values required + for observing its validate success. Its source, fees (sum for a + batch), gas_limit (sum of gas_limit of the batch), and the + increment of the counters aka 1 for a single operation, n for a + batch of n manager operations. *) +type probes = { + source : Signature.Public_key_hash.t; + fee : Tez.t; + gas_limit : Gas.Arith.integral; + nb_counter : int; +} + +let rec contents_infos : + type kind. kind Kind.manager contents_list -> probes tzresult Lwt.t = + fun op -> + let open Lwt_result_syntax in + match op with + | Single (Manager_operation {source; fee; gas_limit; _}) -> + return {source; fee; gas_limit; nb_counter = 1} + | Cons (Manager_operation manop, manops) -> + let* probes = contents_infos manops in + 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 + return {fee; source = probes.source; gas_limit; nb_counter} + +(** Computes a [probes] from a list of manager contents. *) +let manager_content_infos op = + let (Operation_data {contents; _}) = op.protocol_data in + match contents with + | Single (Manager_operation _) as op -> contents_infos op + | Cons (Manager_operation _, _) as op -> contents_infos op + | _ -> failwith "Should only handle manager operation" + +(** We need a way to get the available gas in a context of type + block. *) +let available_gas = function + | Context.I inc -> Some (Gas.block_level (Incremental.alpha_ctxt inc)) + | B _ -> None + +(** Computes the witness value in a state. The witness values are the + the initial balance of source, its initial counter and the + available gas in the state. The available gas is computed only + when the context is an incremental one. *) +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 g_in = available_gas ctxt 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, 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.*) +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 = + Manager_counter.Internal_for_tests.add c_in probes.nb_counter + in + 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)) + | _, Mempool -> + let* c = Context.get_constants ctxt in + return_some + (Gas.Arith.sub + (Gas.Arith.fp c.parametric.hard_gas_limit_per_block) + (Gas.Arith.fp probes.gas_limit)) + | None, Application -> return_none + | Some _, Application -> + failwith "In application mode witness should not care about gas level" + | None, Construction -> + failwith "In Construction mode the witness should return a gas level" + in + 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) 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. + + 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 the + application has succeeded, + + Its counter in the pre-state increases by the number of counter of + probes. + + 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. + + In the [Application] mode, we do not perform any check on the + available gas. *) +let observe ~mode ~deallocated ctxt_pre ctxt_post op = + let open Lwt_result_wrap_syntax in + let check_deallocated ctxt contract = + let* actxt = + let+ i = + match ctxt with + | Context.B b -> Incremental.begin_construction b + | I i -> return i + in + Incremental.alpha_ctxt i + in + let*!@ res = Contract.must_be_allocated actxt contract in + match res with + | Ok () -> + failwith + "%a should have been deallocated@." + 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 + 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__ + 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_effects inc_in ops = + let open Lwt_result_syntax in + List.fold_left_es + (fun inc op -> + let* inc_out = + Incremental.add_operation ~allow_manager_failure:true inc op + in + return inc_out) + inc_in + ops + +(** In [Construction] and [Mempool] mode, the pre-state provide an + incremental, whereas in the [Application] mode, it is the block in + the setting context of the test. *) +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 + 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 open Lwt_result_syntax in + match (mode, ctxt) with + | (Construction | Mempool), Context.I inc_pre -> + 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:true + ~baking_mode:Application + ~operations:ops + b + in + (Context.B block, {infos with ctxt = {infos.ctxt with block}}) + | Application, Context.I _ -> + failwith "In Application mode, context should not be an Incremental" + | (Construction | Mempool), Context.B _ -> + failwith "In (Partial) Contruction mode, context should not be a Block" + +(** 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 [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. + + 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 ~mode ~deallocated ctxt_pre ctxt_post ops in + return infos + +let add_operations ~expect_failure inc_in ops = + let open Lwt_result_syntax in + let* last, ops = + match List.rev ops with + | op :: rev_ops -> return (op, List.rev rev_ops) + | [] -> failwith "Empty list of operations given to add_operations" + in + let* inc = + List.fold_left_es + (fun inc op -> + let* inc = Incremental.validate_operation inc op in + return inc) + inc_in + ops + in + Incremental.validate_operation inc last ~expect_failure + +(** [validate_ko_diagnostic] wraps the [expect_failure] when [op] + validate failed. It is used in test that expects validate of the + last operation of a list of operations to fail. *) +let validate_ko_diagnostic ?(mode = Construction) (infos : infos) ops + expect_failure = + let open Lwt_result_syntax in + match mode with + | Construction | Mempool -> + let* i = + Incremental.begin_construction + infos.ctxt.block + ~mempool_mode:(mempool_mode_of mode) + in + let* (_ : Incremental.t) = add_operations ~expect_failure i ops in + return_unit + | Application -> ( + let*! res = + Block.bake + ~allow_manager_failures:true + ~baking_mode:Application + ~operations:ops + infos.ctxt.block + in + match res with + | Error tr -> expect_failure tr + | _ -> failwith "Block application was expected to fail") + +(** List of operation kinds that must run on generic tests. This list + should be extended for each new manager_operation kind. *) +let subjects = + [ + K_Transaction; + K_Origination; + K_Register_global_constant; + K_Delegation; + K_Undelegation; + K_Self_delegation; + K_Set_deposits_limit; + K_Update_consensus_key; + K_Increase_paid_storage; + K_Reveal; + K_Transfer_ticket; + K_Sc_rollup_origination; + K_Sc_rollup_publish; + K_Sc_rollup_cement; + K_Sc_rollup_add_messages; + K_Sc_rollup_refute; + K_Sc_rollup_timeout; + K_Sc_rollup_execute_outbox_message; + K_Sc_rollup_recover_bond; + K_Dal_publish_commitment; + K_Zk_rollup_origination; + K_Zk_rollup_publish; + K_Zk_rollup_update; + ] + +let is_consumer = function + | K_Set_deposits_limit | K_Update_consensus_key | K_Increase_paid_storage + | K_Reveal | K_Self_delegation | K_Delegation | K_Undelegation + | K_Sc_rollup_add_messages | K_Sc_rollup_origination | K_Sc_rollup_refute + | K_Sc_rollup_timeout | K_Sc_rollup_cement | K_Sc_rollup_publish + | K_Sc_rollup_execute_outbox_message | K_Sc_rollup_recover_bond + | K_Dal_publish_commitment | K_Zk_rollup_origination | K_Zk_rollup_publish + | K_Zk_rollup_update -> + false + | K_Transaction | K_Origination | K_Register_global_constant + | K_Transfer_ticket -> + true + +let gas_consumer_in_validate_subjects, not_gas_consumer_in_validate_subjects = + List.partition is_consumer subjects + +let revealed_subjects = + List.filter (function K_Reveal -> false | _ -> true) subjects + +let is_disabled flags = function + | K_Transaction | K_Origination | K_Register_global_constant | K_Delegation + | K_Undelegation | K_Self_delegation | K_Set_deposits_limit + | K_Update_consensus_key | K_Increase_paid_storage | K_Reveal + | K_Transfer_ticket -> + false + | K_Sc_rollup_origination | K_Sc_rollup_publish | K_Sc_rollup_cement + | K_Sc_rollup_add_messages | K_Sc_rollup_refute | K_Sc_rollup_timeout + | K_Sc_rollup_execute_outbox_message | K_Sc_rollup_recover_bond -> + flags.scoru_arith = false + | K_Dal_publish_commitment -> flags.dal = false + | K_Zk_rollup_origination | K_Zk_rollup_publish | K_Zk_rollup_update -> + flags.zkru = false diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_1m_restriction.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_1m_restriction.ml new file mode 100644 index 000000000000..591b39e74e3b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_1m_restriction.ml @@ -0,0 +1,213 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (validate manager) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/validate/main.exe \ + -- --file test_1m_restriction.ml + Subject: 1M restriction in validation of manager operation. +*) + +open Protocol +open Manager_operation_helpers +open Generators + +let count = 100 + +(** Local default values for the tests. *) +let ctxt_cstrs_default = + { + default_ctxt_cstrs with + src_cstrs = Pure 1500000; + dest_cstrs = Pure 15000; + del_cstrs = Pure 150000; + sc_cstrs = Pure 15000; + zk_cstrs = Pure 15000; + } + +let op_cstrs_default b = + { + default_operation_cstrs with + fee = Range {min = 0; max = 1_000; origin = 1_000}; + force_reveal = Some b; + amount = Range {min = 0; max = 10_000; origin = 10_000}; + } + +let print_one_op (ctxt_req, op_req, mode) = + Format.asprintf + "@[Generator printer:@,%a@,%a@,%a@]" + pp_ctxt_req + ctxt_req + pp_operation_req + op_req + pp_mode + mode + +let print_two_ops (ctxt_req, op_req, op_req', mode) = + Format.asprintf + "@[Generator printer:@,%a@,%a@,%a@,%a@]" + pp_ctxt_req + ctxt_req + pp_operation_req + op_req + pp_operation_req + op_req' + pp_mode + mode + +let print_ops_pair (ctxt_req, op_req, mode) = + Format.asprintf + "@[Generator printer:@,%a@,%a@,%a@]" + pp_ctxt_req + ctxt_req + pp_2_operation_req + op_req + pp_mode + mode + +(** The application of a valid operation succeeds, at least, to perform + the fee payment. *) +let positive_tests = + let gen = + QCheck2.Gen.triple + (Generators.gen_ctxt_req ctxt_cstrs_default) + (Generators.gen_operation_req (op_cstrs_default true) subjects) + Generators.gen_mode + in + wrap + ~count + ~print:print_one_op + ~name:"positive validated op" + ~gen + (fun (ctxt_req, operation_req, mode) -> + let open Lwt_result_syntax in + let* infos = init_ctxt ctxt_req in + let* op = select_op operation_req infos in + let* (_ : infos) = wrap_mode infos [op] mode in + return_true) + +(** Under 1M restriction, neither a block nor a prevalidator's valid + pool should contain two operations with the same manager. It + raises a Manager_restriction error. *) +let two_op_from_same_manager_tests = + let open Lwt_result_syntax in + let gen = + QCheck2.Gen.quad + (Generators.gen_ctxt_req ctxt_cstrs_default) + (Generators.gen_operation_req (op_cstrs_default true) subjects) + (Generators.gen_operation_req (op_cstrs_default false) revealed_subjects) + Generators.gen_mode + in + let expect_failure = function + | [ + Environment.Ecoproto_error + (Validate_errors.Manager.Manager_restriction _); + ] -> + return_unit + | err -> + failwith + "Error trace:@,\ + \ %a does not match the \ + [Validate_errors.Manager.Manager_restriction] error" + Error_monad.pp_print_trace + err + in + wrap + ~count + ~print:print_two_ops + ~name:"check conflicts between managers." + ~gen + (fun (ctxt_req, operation_req, operation_req2, mode) -> + let* infos = init_ctxt ctxt_req in + let* op1 = select_op operation_req infos in + let* op2 = select_op operation_req2 infos in + let* () = validate_ko_diagnostic ~mode infos [op1; op2] expect_failure in + return_true) + +(** Under 1M restriction, a batch of two operations cannot be replaced + by two single operations. *) +let batch_is_not_singles_tests = + let open Lwt_result_syntax in + let gen = + QCheck2.Gen.triple + (Generators.gen_ctxt_req ctxt_cstrs_default) + (Generators.gen_2_operation_req + (op_cstrs_default false) + revealed_subjects) + Generators.gen_mode + in + let expect_failure _ = return_unit in + wrap + ~count + ~print:print_ops_pair + ~name:"batch is not sequence of Single" + ~gen + (fun (ctxt_req, operation_req, mode) -> + let* infos = init_ctxt ctxt_req in + let* op1 = select_op (fst operation_req) infos in + let* op2 = select_op (snd operation_req) infos in + let source = contract_of (get_source infos) in + let* batch = + Op.batch_operations ~source (B infos.ctxt.block) [op1; op2] + in + let* (_ : infos) = validate_diagnostic ~mode infos [batch] in + let* () = validate_ko_diagnostic ~mode infos [op1; op2] expect_failure in + return_true) + +(** The applications of two covalid operations in a certain context + succeed, at least, to perform the fee payment of both, in whatever + application order. *) +let conflict_free_tests = + let gen = + QCheck2.Gen.quad + (Generators.gen_ctxt_req ctxt_cstrs_default) + (Generators.gen_operation_req (op_cstrs_default true) revealed_subjects) + (Generators.gen_operation_req (op_cstrs_default true) revealed_subjects) + Generators.gen_mode + in + wrap + ~count + ~print:print_two_ops + ~name:"under 1M, co-valid ops commute" + ~gen + (fun (ctxt_req, operation_req, operation_req', mode) -> + let open Lwt_result_syntax in + let* infos = init_ctxt ctxt_req in + let* op1 = select_op operation_req infos in + let infos2 = + { + infos with + accounts = + { + infos.accounts with + sources = + (match infos.accounts.del with + | None -> assert false + | Some s -> [s]); + }; + } + in + let* op2 = select_op operation_req' infos2 in + let* (_ : infos) = validate_diagnostic ~mode infos [op1; op2] in + let* (_ : infos) = validate_diagnostic ~mode infos [op2; op1] in + return_true) + +open Qcheck2_helpers + +let tests : (string * [`Quick | `Slow] * (unit -> unit Lwt.t)) trace = + qcheck_wrap_lwt + [ + positive_tests; + two_op_from_same_manager_tests; + batch_is_not_singles_tests; + conflict_free_tests; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("one-manager restriction", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_covalidity.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_covalidity.ml new file mode 100644 index 000000000000..b8488c54552c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_covalidity.ml @@ -0,0 +1,142 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (validate manager) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/validate/main.exe \ + -- --file test_covalidity.ml + Subject: Validation of operation. +*) +open Validate_helpers + +open Generator_descriptors +open Valid_operations_generators +open Protocol +open Alpha_context + +(** Values of number of bootstraps to create.*) + +let default_nb_bootstrap = 7 + +let nb_permutations = 30 + +let op_of_voting_period : Voting_period.kind -> op_kind = + let open Voting_period in + function + | Proposal -> KProposals + | Exploration -> KBallotExp + | Promotion -> KBallotProm + | _ -> assert false + +type seed_gen = Nonce | Vdf + +let pp_seed fmt = function + | Nonce -> Format.fprintf fmt "nonce" + | Vdf -> Format.fprintf fmt "vdf" + +let op_of_seed_gen = function Nonce -> KNonce | Vdf -> KVdf + +let is_not_preattestation op = + let open Protocol.Alpha_context in + let (Operation_data {contents; _}) = op.protocol_data in + match contents with Single (Preattestation _) -> false | _ -> true + +module OpkindMap = Map.Make (struct + type t = op_kind + + let compare = compare +end) + +let partition_op_kind op_kinds = + List.fold_left + (fun map op_kind -> + OpkindMap.update + op_kind + (function None -> Some 1 | Some c -> Some (succ c)) + map) + OpkindMap.empty + op_kinds + +let print_candidates candidates = + Format.printf + "@\n@[%d operations generated:@ %a@]@." + (List.length candidates) + Format.( + pp_print_list ~pp_sep:pp_print_cut (fun fmt (op, c) -> + Format.fprintf fmt "%d: %a" c pp_op_kind op)) + (List.map op_kind_of_packed_operation candidates + |> partition_op_kind |> OpkindMap.bindings) + +(** Test that for the set of covalid operations which kinds belongs to [ks] in a + state, any permutation is covalid and can be baked into a valid block. *) +let covalid_permutation_and_bake ks nb_bootstrap = + let open Lwt_result_syntax in + let* state, candidates = + covalid ks ~nb_bootstrap ~max_batch_size:Operation_generator.max_batch_size + in + print_candidates candidates ; + let* () = sequential_validate state.block candidates in + let rec loop = function + | 0 -> return_unit + | n -> + let operations = + QCheck2.Gen.shuffle_l candidates + |> QCheck2.Gen.generate1 + |> List.sort Protocol.Alpha_context.Operation.compare_by_passes + |> List.rev_filter is_not_preattestation + in + (* Ensure that we can validate and apply this permutation *) + let* (_ : Block.t) = + Block.bake ~allow_manager_failures:true state.block ~operations + in + loop (pred n) + in + loop nb_permutations + +(** {2 Tests} *) + +let name voting_period reveal = + Format.asprintf + "scenario: '%a' period, '%a' seed" + Voting_period.pp_kind + voting_period + pp_seed + reveal + +(** Test [covalid_permutation_and_bake]. *) +let test_covalid voting_period seed_gen = + Generators.wrap + ~name:(name voting_period seed_gen) + ~gen:QCheck2.Gen.unit + (fun () -> + let open Lwt_result_syntax in + let ks = + op_of_voting_period voting_period + :: op_of_seed_gen seed_gen :: non_exclusive_kinds + in + let* () = covalid_permutation_and_bake ks default_nb_bootstrap in + return_true) + +let tests = + (* Create a list of all permutation of voting period and all + possible nonce generation *) + let voting_periods = [Voting_period.Proposal; Exploration; Promotion] in + let nonce_gens = [Nonce; Vdf] in + List.fold_left + (fun acc voting_period -> + List.fold_left + (fun acc nonce_gen -> test_covalid voting_period nonce_gen :: acc) + acc + nonce_gens) + [] + voting_periods + |> Qcheck2_helpers.qcheck_wrap_lwt + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("covalidity", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_manager_operation_validation.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_manager_operation_validation.ml new file mode 100644 index 000000000000..046cf0c230e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_manager_operation_validation.ml @@ -0,0 +1,619 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (validate manager) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/validate/main.exe \ + -- --file test_manager_operation_validation.ml + Subject: Validation of manager operation. +*) + +open Protocol +open Alpha_context +open Manager_operation_helpers + +(** {2 Negative tests assert the case where validate must fail} *) + +(** Validate fails if the gas limit is too low. + + This test asserts that the validation of a manager operation + with a too low gas limit fails at validate with an + [Gas_quota_exceeded_init_deserialize] error. + This test applies on manager operations that do not + consume gas in their specific part of validate. *) +let low_gas_limit_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Gas_quota_exceeded_init_deserialize; + Environment.Ecoproto_error Raw_context.Operation_quota_exceeded; + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_low_gas_limit infos kind = + let open Lwt_result_syntax in + let* op = + select_op + { + (operation_req_default kind) with + gas_limit = Some Op.Low; + force_reveal = Some true; + } + infos + in + low_gas_limit_diagnostic infos [op] + +(** Validate fails if the gas limit is too high. + + This test asserts that the validation of a manager operation with + a gas limit too high fails at validate with an [Gas_limit_too_high] + error. It applies on every kind of manager operation. *) +let high_gas_limit_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error Gas.Gas_limit_too_high] -> return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_high_gas_limit infos kind = + let open Lwt_result_syntax in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + gas_limit = + Some (Op.Custom_gas (Gas.Arith.integral_of_int_exn 10_000_000)); + } + infos + in + high_gas_limit_diagnostic infos [op] + +(** Validate fails if the storage limit is too high. + + This test asserts that a manager operation with a storage limit + too high fails at validation with [Storage_limit_too_high] error. + It applies to every kind of manager operation. *) +let high_storage_limit_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error Fees_storage.Storage_limit_too_high] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_high_storage_limit infos kind = + let open Lwt_result_syntax in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + storage_limit = Some (Z.of_int max_int); + } + infos + in + high_storage_limit_diagnostic infos [op] + +(** Validate fails if the counter is in the future. + + This test asserts that the validation of + a manager operation with a counter in the + future -- aka greater than the successor of the manager counter + stored in the current context -- fails with [Counter_in_the_future] error. + It applies to every kind of manager operation. *) +let high_counter_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error (Contract_storage.Counter_in_the_future _)] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_high_counter infos kind = + let open Lwt_result_syntax in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + counter = Some (Manager_counter.Internal_for_tests.of_int max_int); + } + infos + in + high_counter_diagnostic infos [op] + +(** Validate fails if the counter is in the past. + + This test asserts that the validation of a manager operation with a + counter in the past -- aka smaller than the successor of the + manager counter stored in the current context -- fails with + [Counter_in_the_past] error. It applies to every kind of manager + operation. *) +let low_counter_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error (Contract_storage.Counter_in_the_past _)] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_low_counter infos kind = + let open Lwt_result_syntax in + let* current_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 (Manager_counter.Internal_for_tests.add current_counter (-1)); + } + infos + in + low_counter_diagnostic infos [op] + +(** Validate fails if the source is not allocated. + + This test asserts that the validation of a manager operation which + manager contract is not allocated fails with + [Empty_implicit_contract] error. It applies on every kind of + manager operation. *) +let not_allocated_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract _)] + -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_not_allocated infos kind = + let open Lwt_result_syntax in + let* op = + select_op + {(operation_req_default kind) with force_reveal = Some false} + { + infos with + accounts = {infos.accounts with sources = [Account.(new_account ())]}; + } + in + not_allocated_diagnostic infos [op] + +(** Validate fails if the source is unrevealed. + + This test asserts that a manager operation with an unrevealed source + contract fails at validation with [Unrevealed_manager_key]. + It applies on every kind of manager operation except [Revelation]. *) +let unrevealed_key_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [ + Environment.Ecoproto_error + (Contract_manager_storage.Unrevealed_manager_key _); + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_unrevealed_key infos kind = + let open Lwt_result_syntax in + let* op = + select_op + {(operation_req_default kind) with force_reveal = Some false} + infos + in + unrevealed_key_diagnostic infos [op] + +(** Validate fails if the source balance is not enough to pay the fees. + + This test asserts that validation of a manager operation fails if the + source balance is lesser than the manager operation fee. + It applies on every kind of manager operation. *) +let high_fee_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [ + Environment.Ecoproto_error (Contract_storage.Balance_too_low _); + Environment.Ecoproto_error (Tez_repr.Subtraction_underflow _); + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_high_fee infos kind = + let open Lwt_result_wrap_syntax in + let*?@ fee = Tez.(one +? default_fund) in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + fee = Some fee; + } + infos + in + high_fee_diagnostic infos [op] + +(** Validate fails if the fee payment empties the balance of a + delegated implicit contract. + + This test asserts that in case that: + - the source is a delegated implicit contract, and + - the fee is the exact balance of source. + then, validate fails with [Empty_implicit_delegated_contract] error. + It applies to every kind of manager operation except [Revelation].*) +let emptying_delegated_implicit_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [ + Environment.Ecoproto_error + (Contract_storage.Empty_implicit_delegated_contract _); + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let test_empty_implicit infos kind = + let open Lwt_result_syntax in + let* fee = + Context.Contract.balance + (B infos.ctxt.block) + (contract_of (get_source infos)) + in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some false; + fee = Some fee; + } + infos + in + emptying_delegated_implicit_diagnostic infos [op] + +(** Validate fails if there is not enough available gas in the block. + + This test asserts that validate fails with: + - [Gas_limit_too_high;Block_quota_exceeded] in mempool mode, + - [Block_quota_exceeded] in other mode + with gas limit exceeds the available gas in the block. + It applies to every kind of manager operation. *) +let exceeding_block_gas_diagnostic ~mode (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match (errs, mode) with + | ( [Environment.Ecoproto_error Gas.Block_quota_exceeded], + (Construction | Application) ) -> + return_unit + | ( [ + Environment.Ecoproto_error Gas.Gas_limit_too_high; + Environment.Ecoproto_error Gas.Block_quota_exceeded; + ], + Mempool ) -> + (* In mempool_mode, batch that exceed [operation_gas_limit] needs + to be refused. [Gas.Block_quota_exceeded] only return a + temporary error. [Gas.Gas_limit_too_high], which is a + permanent error, is added to the error trace to ensure that + the batch is refused. *) + return_unit + | err, _ -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure ~mode + +let test_exceeding_block_gas ~mode infos kind = + let open Lwt_result_syntax in + let* operation = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + gas_limit = + Some + (Op.Custom_gas + (Gas.Arith.add gb_limit Gas.Arith.(integral_of_int_exn 1))); + } + infos + in + exceeding_block_gas_diagnostic ~mode infos [operation] + +(** {2 Positive tests} *) + +(** Tests that validate succeeds when: + - it empties the balance of a self_delegated implicit source, + - it empties the balance of an undelegated implicit source, and + - in case: + - the counter is the successor of the one stored in the context, + - the fee is lesser than the balance, + - the storage limit is lesser than the maximum authorized storage, + - the gas limit is: + - lesser than the available gas in the block, + - less than the maximum gas consumable by an operation, and + - greater than the minimum gas consumable by an operation. + + Notice that in the first two cases only validate succeeds while + in the last case, the full application also succeeds. + 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 at least gas limit. *) + +(** Fee payment*) +let test_validate infos kind = + let open Lwt_result_syntax in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + amount = Some Tez.one; + } + infos + in + let* (_ : infos) = validate_diagnostic infos [op] in + return_unit + +(** Fee payment that emptying a self_delegated implicit. *) +let test_emptying_self_delegate infos kind = + let open Lwt_result_syntax in + let* fee = + Context.Contract.balance + (B infos.ctxt.block) + (contract_of (get_source infos)) + in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some false; + fee = Some fee; + } + infos + in + let* (_ : infos) = validate_diagnostic infos [op] in + return_unit + +let test_empty_undelegate infos kind = + let open Lwt_result_syntax in + let* fee = + Context.Contract.balance + (B infos.ctxt.block) + (contract_of (get_source infos)) + in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + fee = Some fee; + gas_limit = Some Op.High; + } + infos + in + let* (_ : infos) = validate_diagnostic ~deallocated:true infos [op] in + return_unit + +(** No gas consumer with the minimal gas limit for manager operations + passes validate. *) +let test_low_gas_limit_no_consumer infos kind = + let open Lwt_result_syntax in + let* op = + select_op + { + (operation_req_default kind) with + force_reveal = Some true; + gas_limit = Some Op.Low; + } + infos + in + let* (_ : infos) = validate_diagnostic infos [op] in + return_unit + +(* Feature flags.*) + +(* Select the error according to the positionned flag. + We assume that only one feature is disabled. *) +let flag_expect_failure flags errs = + let open Lwt_result_syntax in + match errs with + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Sc_rollup_arith_pvm_disabled; + ] + when flags.scoru_arith = false -> + return_unit + | [Environment.Ecoproto_error Dal_errors.Dal_feature_disabled] + when flags.dal = false -> + return_unit + | [ + Environment.Ecoproto_error Validate_errors.Manager.Zk_rollup_feature_disabled; + ] + when flags.zkru = false -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + +(* Tests that operations depending on feature flags are not valid + when the flag is set as disable. + + See [is_disabled] and the [flags] in `manager_operation_helpers`. + We assume that only one flag is set at false in flag. + + In order to forge Scoru or Dal operation when the corresponding + feature is disable, we use a [infos_op] with default requirements, + so that we have a Sc_rollup.t. *) +let test_feature_flags 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} with + counter = Some counter; + } + infos + in + let flags = infos.flags in + if is_disabled flags kind then + validate_ko_diagnostic infos [op] (flag_expect_failure flags) + else + let* (_ : infos) = validate_diagnostic infos [op] in + return_unit + +let tests = + let mk_default () = default_init_ctxt () in + let mk_reveal () = + init_ctxt {ctxt_req_default with reveal_accounts = false} + in + let mk_deleg () = default_ctxt_with_delegation () in + let mk_gas () = + init_ctxt {ctxt_req_default with hard_gas_limit_per_block = Some gb_limit} + in + let mk_self_deleg () = default_ctxt_with_self_delegation () in + let mk_flags flags () = + let open Lwt_result_syntax in + let* infos_op = default_init_ctxt () in + let* infos = default_init_with_flags flags in + let infos = + { + infos with + ctxt = + { + infos.ctxt with + sc_rollup = infos_op.ctxt.sc_rollup; + zk_rollup = infos_op.ctxt.zk_rollup; + }; + } + in + return infos + in + let all = subjects in + let gas_consum = gas_consumer_in_validate_subjects in + let not_gas_consum = not_gas_consumer_in_validate_subjects in + let revealed = revealed_subjects in + List.map + (fun (name, f, subjects, info_builder) -> + make_tztest name f subjects info_builder) + [ + (* Expected validation failure *) + ("gas limit too low", test_low_gas_limit, gas_consum, mk_default); + ("gas limit too high", test_high_gas_limit, all, mk_default); + ("storage limit too high", test_high_storage_limit, all, mk_default); + ("counter too high", test_high_counter, all, mk_default); + ("counter too low", test_low_counter, all, mk_default); + ("unallocated source", test_not_allocated, all, mk_default); + ("unrevealed source", test_unrevealed_key, revealed, mk_reveal); + ("balance too low for fee payment", test_high_fee, all, mk_default); + ("empty delegate source", test_empty_implicit, revealed, mk_deleg); + ( "too much gas consumption in block", + test_exceeding_block_gas ~mode:Construction, + all, + mk_gas ); + (* Expected validation success *) + ("fees are taken when valid", test_validate, all, mk_default); + ("empty self-delegate", test_emptying_self_delegate, all, mk_self_deleg); + ( "too much gas consumption in mempool", + test_exceeding_block_gas ~mode:Mempool, + all, + mk_gas ); + ("empty undelegated source", test_empty_undelegate, all, mk_default); + ( "minimal gas for manager", + test_low_gas_limit_no_consumer, + not_gas_consum, + mk_default ); + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6967 + Delete the test when not useful for sure. *) + (* ("dal disabled", test_feature_flags, all, mk_flags disabled_dal); *) + ( "scoru arith disabled", + test_feature_flags, + [K_Sc_rollup_origination], + mk_flags disabled_scoru_arith ); + ("zkru disabled", test_feature_flags, all, mk_flags disabled_zkru); + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("single manager validation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_mempool.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_mempool.ml new file mode 100644 index 000000000000..716358165057 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_mempool.ml @@ -0,0 +1,395 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/validate/main.exe \ + -- --file test_mempool.ml + Subject: Integration > Validate > Mempool mode +*) + +open Protocol +open Alpha_context +module Mempool = Mempool_validation + +let extract_values ctxt (b : Block.t) = + let predecessor_level = + Level.from_raw ctxt (Raw_level.of_int32_exn b.header.shell.level) + in + let fitness = + Fitness.from_raw b.header.shell.fitness |> function + | Ok v -> v + | Error _ -> assert false + in + let predecessor_round = Fitness.round fitness in + let predecessor_hash = b.header.shell.predecessor in + (predecessor_level, predecessor_round, predecessor_hash) + +let op_with_hash op = (Operation.hash_packed op, op) + +let expect_ok_added ~__LOC__ x = + match x with + | Ok (mempool, Mempool.Added) -> mempool + | _ -> Format.kasprintf Stdlib.failwith "%s: expected added" __LOC__ + +let expect_conflict ~__LOC__ x = + match (x : ('a, Mempool.add_error) result) with + | Error (Add_conflict _) -> () + | _ -> Format.kasprintf Stdlib.failwith "%s: expected conflict" __LOC__ + +let expect_conflict_handled ~__LOC__ kind x = + match (x : (Mempool.t * Mempool.add_result, Mempool.add_error) result) with + | Ok (mempool, kind') when kind = kind' -> mempool + | _ -> + Format.kasprintf Stdlib.failwith "%s: expected handled conflict" __LOC__ + +let handler_always_keep ~existing_operation:_ ~new_operation:_ = `Keep + +let handler_always_replace ~existing_operation:_ ~new_operation:_ = `Replace + +let assert_empty_mempool ~__LOC__ mempool = + let operations = Mempool.operations mempool in + Assert.equal_bool + ~loc:__LOC__ + true + (Environment.Operation_hash.Map.is_empty operations) + +let assert_operation_present_in_mempool ~__LOC__ mempool ophl = + let operations = Mempool.operations mempool in + let resulting_mempool_operations = + Environment.Operation_hash.Map.bindings operations + |> List.map fst + |> List.sort Operation_hash.compare + in + let expected_operations = List.sort Operation_hash.compare ophl in + Assert.assert_equal_list + ~loc:__LOC__ + Operation_hash.equal + "operations present in mempool" + Operation_hash.pp + resulting_mempool_operations + expected_operations + +let test_simple () = + let open Lwt_result_syntax in + let* block, (c1, c2) = Context.init2 () in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash = + extract_values ctxt block + in + let vs, mempool = + Mempool.init + ctxt + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash + in + let* op1 = Op.transaction (B block) c1 c2 Tez.one_cent in + let op1 = op_with_hash op1 in + let* op1' = Op.transaction (B block) c1 c2 Tez.one in + let op1' = op_with_hash op1' in + let* op2 = Op.transaction (B block) c2 c1 Tez.one in + let op2 = op_with_hash op2 in + let*! res = Mempool.add_operation vs mempool op1 in + let mempool = expect_ok_added ~__LOC__ res in + let*! res = Mempool.add_operation vs mempool op2 in + let mempool = expect_ok_added ~__LOC__ res in + let*! res = Mempool.add_operation vs mempool op1' in + let () = expect_conflict ~__LOC__ res in + return_unit + +let test_imcompatible_mempool () = + let open Lwt_result_syntax in + let* block, _ = Context.init1 ~consensus_threshold:0 () in + let* block = Block.bake block in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash = + extract_values ctxt block + in + let (_vs : Mempool.validation_info), mempool1 = + Mempool.init + ctxt + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash + in + (* Create a second mempool on a different block *) + let* block2 = Block.bake block in + let* ctxt2 = + let+ incr = Incremental.begin_construction block2 in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash2 = + extract_values ctxt2 block2 + in + let (_vs : Mempool.validation_info), mempool2 = + Mempool.init + ctxt2 + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash:predecessor_hash2 + in + let () = + match Mempool.merge mempool1 mempool2 with + | Error Mempool.Incompatible_mempool -> () + | Error (Merge_conflict _) -> + Format.kasprintf + Stdlib.failwith + "%s: expected incompatible mempool" + __LOC__ + | Ok _ -> Format.kasprintf Stdlib.failwith "%s: expected conflict" __LOC__ + in + return_unit + +let test_merge () = + let open Lwt_result_syntax in + let* block, (c1, c2) = Context.init2 () in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash = + extract_values ctxt block + in + let vs, mempool_i = + Mempool.init + ctxt + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash + in + (* Build two mempool with a conflicting operation and check that the + merge fails and succeeds when a conflict handler is provided *) + let* op1 = Op.transaction (B block) c1 c2 Tez.one_cent in + let op1 = op_with_hash op1 in + let* op2 = Op.transaction (B block) c2 c1 Tez.one in + let op2 = op_with_hash op2 in + let*! res = Mempool.add_operation vs mempool_i op1 in + let mempool1 = expect_ok_added ~__LOC__ res in + let*! res = Mempool.add_operation vs mempool_i op2 in + let mempool2 = expect_ok_added ~__LOC__ res in + let merged_non_conflicting_mempool = + match Mempool.merge mempool1 mempool2 with + | Ok mempool -> mempool + | _ -> + Format.kasprintf Stdlib.failwith "%s: expected succesful merge" __LOC__ + in + let* op1' = Op.transaction (B block) c1 c2 Tez.one in + let op1' = op_with_hash op1' in + let*! res = Mempool.add_operation vs mempool_i op1' in + let mempool3 = expect_ok_added ~__LOC__ res in + let*! res = Mempool.add_operation vs mempool3 op2 in + let mempool3 = expect_ok_added ~__LOC__ res in + let () = + match Mempool.merge merged_non_conflicting_mempool mempool3 with + | Error (Merge_conflict _) -> () + | _ -> Format.kasprintf Stdlib.failwith "%s: expected conflict" __LOC__ + in + let merged_mempool_replace = + match + Mempool.merge + ~conflict_handler:handler_always_replace + merged_non_conflicting_mempool + mempool3 + with + | Ok mempool -> mempool + | _ -> + Format.kasprintf Stdlib.failwith "%s: expected succesful merge" __LOC__ + in + let* () = + assert_operation_present_in_mempool + ~__LOC__ + merged_mempool_replace + (List.map fst [op1'; op2]) + in + let merged_mempool_keep = + match + Mempool.merge + ~conflict_handler:handler_always_keep + merged_non_conflicting_mempool + mempool3 + with + | Ok mempool -> mempool + | _ -> + Format.kasprintf Stdlib.failwith "%s: expected succesful merge" __LOC__ + in + let* () = + assert_operation_present_in_mempool + ~__LOC__ + merged_mempool_keep + (List.map fst [op1; op2]) + in + (* Check that merging a mempool with itself is a success and returns + the identity *) + let* () = + match Mempool.merge mempool1 mempool1 with + | Ok mempool -> + let expected_operations = + Environment.Operation_hash.Map.bindings (Mempool.operations mempool1) + |> List.map fst + in + assert_operation_present_in_mempool ~__LOC__ mempool expected_operations + | Error _ -> assert false + in + return_unit + +let test_add_invalid_operation () = + let open Lwt_result_syntax in + let* block, c1 = Context.init1 () in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash = + extract_values ctxt block + in + let vs, mempool_i = + Mempool.init + ctxt + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash + in + let* op1 = Op.transaction (B block) c1 c1 ~gas_limit:Zero Tez.one_cent in + let op1 = op_with_hash op1 in + let*! res = Mempool.add_operation vs mempool_i op1 in + match res with + | Error (Mempool.Validation_error _) -> return_unit + | Error _ -> Stdlib.failwith "unexpected error" + | Ok _ -> Stdlib.failwith "unexpected success" + +let test_add_and_replace () = + let open Lwt_result_syntax in + let* block, (c1, c2) = Context.init2 () in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash = + extract_values ctxt block + in + let info, mempool_i = + Mempool.init + ctxt + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash + in + (* Try adding a conflicting operation using both handler strategy *) + let* op1 = Op.transaction (B block) c1 c2 Tez.one_cent in + let op1 = op_with_hash op1 in + let* op1' = Op.transaction (B block) c1 c2 Tez.one in + let op1' = op_with_hash op1' in + let*! res = Mempool.add_operation info mempool_i op1 in + let mempool = expect_ok_added ~__LOC__ res in + let*! res = Mempool.add_operation info mempool op1' in + let () = expect_conflict ~__LOC__ res in + let*! res = + Mempool.add_operation + ~conflict_handler:handler_always_keep + info + mempool + op1' + in + let final_mempool = expect_conflict_handled ~__LOC__ Unchanged res in + let* () = + assert_operation_present_in_mempool ~__LOC__ final_mempool [fst op1] + in + let*! res = + Mempool.add_operation + ~conflict_handler:handler_always_replace + info + mempool + op1' + in + let final_mempool = + expect_conflict_handled ~__LOC__ (Replaced {removed = fst op1}) res + in + let* () = + assert_operation_present_in_mempool ~__LOC__ final_mempool [fst op1'] + in + return_unit + +let test_remove_operation () = + let open Lwt_result_syntax in + let* block, (c1, c2) = Context.init2 () in + let* ctxt = + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let predecessor_level, predecessor_round, predecessor_hash = + extract_values ctxt block + in + let info, mempool_i = + Mempool.init + ctxt + Chain_id.zero + ~predecessor_level + ~predecessor_round + ~predecessor_hash + in + let* op1 = Op.transaction (B block) c1 c2 Tez.one_cent in + let op1 = op_with_hash op1 in + let* op2 = Op.transaction (B block) c1 c2 Tez.one in + let op2 = op_with_hash op2 in + (* Add one operation to the mempoolg *) + let*! res = Mempool.add_operation info mempool_i op1 in + let mempool = expect_ok_added ~__LOC__ res in + let* () = assert_operation_present_in_mempool ~__LOC__ mempool [fst op1] in + (* Try removing unknown operation and check that the mempool is unchanged *) + let mempool = Mempool.remove_operation mempool (fst op2) in + let* () = assert_operation_present_in_mempool ~__LOC__ mempool [fst op1] in + (* Try removing known operation and ensure that the mempool is empty *) + let empty_mempool = Mempool.remove_operation mempool (fst op1) in + assert_empty_mempool ~__LOC__ empty_mempool + +let tests = + [ + Tztest.tztest "simple" `Quick test_simple; + Tztest.tztest "incompatible mempool" `Quick test_imcompatible_mempool; + Tztest.tztest "merge" `Quick test_merge; + Tztest.tztest "adding invalid operation" `Quick test_add_invalid_operation; + Tztest.tztest + "adding operation with conflict handler" + `Quick + test_add_and_replace; + Tztest.tztest "remove operations" `Quick test_remove_operation; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("mempool", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_sanity.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_sanity.ml new file mode 100644 index 000000000000..da7aa305f523 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_sanity.ml @@ -0,0 +1,147 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (validate manager) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/validate/main.exe \ + -- --file test_sanity.ml + Subject: Validation of operation. +*) + +open Protocol +open Alpha_context +open Manager_operation_helpers + +(** The goal of this test is to ensure that [select_op] generate the + wanted kind of manager operation + + Note: if a new manager operation kind is added in the protocol, + [Manager_operation_helpers.manager_operation_kind] should be + extended. You will also have to extend + [Manager_operation_helpers.select_op] with a new `mk` for this new + operation. Finally the list [Manager_operation_helpers.subjects] + should also be extended to run the validate test on the new manager + operation kind. *) +let ensure_kind infos kind = + let open Lwt_result_syntax in + let* op = + select_op + {(operation_req_default kind) with force_reveal = Some false} + infos + in + let (Operation_data {contents; _}) = op.protocol_data in + match contents with + | Single (Manager_operation {operation; _}) -> ( + match (operation, kind) with + | Transaction _, K_Transaction + | Reveal _, K_Reveal + | Origination _, K_Origination + | Delegation _, K_Delegation + | Delegation _, K_Undelegation + | Delegation _, K_Self_delegation + | Register_global_constant _, K_Register_global_constant + | Set_deposits_limit _, K_Set_deposits_limit + | Update_consensus_key _, K_Update_consensus_key + | Increase_paid_storage _, K_Increase_paid_storage + | Transfer_ticket _, K_Transfer_ticket + | Sc_rollup_originate _, K_Sc_rollup_origination + | Sc_rollup_add_messages _, K_Sc_rollup_add_messages + | Sc_rollup_cement _, K_Sc_rollup_cement + | Sc_rollup_publish _, K_Sc_rollup_publish + | Sc_rollup_refute _, K_Sc_rollup_refute + | Sc_rollup_timeout _, K_Sc_rollup_timeout + | Sc_rollup_execute_outbox_message _, K_Sc_rollup_execute_outbox_message + | Sc_rollup_recover_bond _, K_Sc_rollup_recover_bond + | Dal_publish_commitment _, K_Dal_publish_commitment + | Zk_rollup_origination _, K_Zk_rollup_origination + | Zk_rollup_publish _, K_Zk_rollup_publish + | Zk_rollup_update _, K_Zk_rollup_update -> + return_unit + | ( ( Transaction _ | Origination _ | Register_global_constant _ + | Delegation _ | Set_deposits_limit _ | Update_consensus_key _ + | Increase_paid_storage _ | Reveal _ | Transfer_ticket _ + | Sc_rollup_originate _ | Sc_rollup_publish _ | Sc_rollup_cement _ + | Sc_rollup_add_messages _ | Sc_rollup_refute _ | Sc_rollup_timeout _ + | Sc_rollup_execute_outbox_message _ | Sc_rollup_recover_bond _ + | Dal_publish_commitment _ | Zk_rollup_origination _ + | Zk_rollup_publish _ | Zk_rollup_update _ ), + _ ) -> + assert false) + | Single _ -> assert false + | Cons _ -> assert false + +let ensure_manager_operation_coverage () = + let open Lwt_result_syntax in + let* infos = default_init_ctxt () in + List.iter_es (fun kind -> ensure_kind infos kind) subjects + +open Generator_descriptors +open Valid_operations_generators + +(** This test ensures that it exists a valid operation generator for + each operation. + + Note: When adding a new operation, one should refer to {! + Generator_descriptor} to see how to add its valid operation + generator. *) +let covalidation_sanity () = + let open Lwt_result_syntax in + let max_batch_size = 1 in + let nb_bootstrap = 7 in + List.iter_es + (fun kind -> + let* _, candidates = covalid [kind] ~nb_bootstrap ~max_batch_size in + match List.hd candidates with + | None -> + failwith "no candidates was generated for kind '%a'" pp_op_kind kind + | Some {protocol_data = Operation_data {contents; _}; _} -> ( + match (contents, kind) with + | Single (Preattestation _), KPreattestation -> return_unit + | Single (Preattestation _), _ -> assert false + | Single (Attestation _), KAttestation -> return_unit + | Single (Attestation _), _ -> assert false + | Single (Seed_nonce_revelation _), KNonce -> return_unit + | Single (Seed_nonce_revelation _), _ -> assert false + | Single (Vdf_revelation _), KVdf -> return_unit + | Single (Vdf_revelation _), _ -> assert false + | Single (Double_attestation_evidence _), KDbl_consensus -> + return_unit + | Single (Double_attestation_evidence _), _ -> assert false + | Single (Double_preattestation_evidence _), KDbl_consensus -> + return_unit + | Single (Double_preattestation_evidence _), _ -> assert false + | Single (Double_baking_evidence _), KDbl_baking -> return_unit + | Single (Double_baking_evidence _), _ -> assert false + | Single (Activate_account _), KActivate -> return_unit + | Single (Activate_account _), _ -> assert false + | Single (Proposals _), KProposals -> return_unit + | Single (Proposals _), _ -> assert false + | Single (Ballot _), (KBallotExp | KBallotProm) -> return_unit + | Single (Ballot _), _ -> assert false + | Single (Drain_delegate _), KDrain -> return_unit + | Single (Drain_delegate _), _ -> assert false + | Single (Manager_operation _), KManager + | Cons (Manager_operation _, _), KManager -> + return_unit + | Single (Manager_operation _), _ | Cons (Manager_operation _, _), _ + -> + assert false + | Single (Failing_noop _), _ -> assert false)) + all_kinds + +let tests = + List.map + (fun (name, f) -> Tztest.tztest name `Quick f) + [ + ("manager operation coverage", ensure_manager_operation_coverage); + ("covalidation coverage", covalidation_sanity); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sanity checks", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_validation_batch.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_validation_batch.ml new file mode 100644 index 000000000000..26d878ec0aef --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/test_validation_batch.ml @@ -0,0 +1,615 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (validate manager) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/integration/validate/main.exe \ + -- --file test_validation_batch.ml + Subject: Validation of batched manager operation. +*) + +open Protocol +open Alpha_context +open Manager_operation_helpers + +(** {2 Tests on operation batches} *) + +(** Revelation should not occur elsewhere than in first position + in a batch.*) +let batch_reveal_in_the_middle_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let batch_in_the_middle infos kind1 kind2 = + let open Lwt_result_syntax in + let* counter = + Context.Contract.counter + (B infos.ctxt.block) + (contract_of (get_source infos)) + in + let counter = Manager_counter.succ counter in + let* operation1 = + select_op + { + (operation_req_default kind1) with + force_reveal = Some false; + counter = Some counter; + } + infos + in + let counter = Manager_counter.succ counter in + let* reveal = + mk_reveal + { + (operation_req_default K_Reveal) with + fee = Some Tez.one_mutez; + counter = Some counter; + } + infos + in + let counter = Manager_counter.succ counter in + let* operation2 = + select_op + { + (operation_req_default kind2) with + force_reveal = Some false; + counter = Some counter; + } + infos + in + let* batch = + Op.batch_operations + ~recompute_counters:false + ~source:(contract_of (get_source infos)) + (Context.B infos.ctxt.block) + [operation1; reveal; operation2] + in + batch_reveal_in_the_middle_diagnostic infos [batch] + +(** A batch of manager operation contains at most one Revelation.*) +let batch_two_reveals_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expected_failure errs = + match errs with + | [ + Environment.Ecoproto_error + Validate_errors.Manager.Incorrect_reveal_position; + ] -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expected_failure + +let batch_two_reveals infos kind = + let open Lwt_result_syntax in + let* counter = + Context.Contract.counter + (B infos.ctxt.block) + (contract_of (get_source infos)) + in + let counter = Manager_counter.succ counter in + let* reveal = + mk_reveal + { + (operation_req_default K_Reveal) with + fee = Some Tez.one_mutez; + counter = Some counter; + } + infos + in + let counter = Manager_counter.succ counter in + let* reveal1 = + mk_reveal + { + (operation_req_default K_Reveal) with + fee = Some Tez.one_mutez; + counter = Some counter; + } + infos + in + let counter = Manager_counter.succ counter in + let* operation = + select_op + { + (operation_req_default kind) with + force_reveal = Some false; + counter = Some counter; + } + infos + in + let* batch = + Op.batch_operations + ~recompute_counters:false + ~source:(contract_of (get_source infos)) + (Context.B infos.ctxt.block) + [reveal; reveal1; operation] + in + batch_two_reveals_diagnostic infos [batch] + +(** Every manager operation in a batch concerns the same source.*) +let batch_two_sources_diagnostic (infos : infos) op = + let open Lwt_result_syntax in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error Validate_errors.Manager.Inconsistent_sources] + -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + validate_ko_diagnostic infos op expect_failure + +let batch_two_sources infos kind1 kind2 = + let open Lwt_result_syntax in + let source = contract_of (get_source infos) in + let* counter = Context.Contract.counter (B infos.ctxt.block) source in + let counter = Manager_counter.succ counter in + let* operation1 = + select_op + { + (operation_req_default kind1) with + force_reveal = Some true; + counter = Some counter; + } + infos + in + let infos = + let source2 = + match infos.accounts.del with None -> assert false | Some s -> s + in + {infos with accounts = {infos.accounts with sources = [source2]}} + in + let* operation2 = + select_op + {(operation_req_default kind2) with force_reveal = Some false} + infos + in + let* batch = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [operation1; operation2] + in + batch_two_sources_diagnostic infos [batch] + +(** Counters in a batch should be a sequence from the successor of + the stored counter associated to source in the initial context. *) +let batch_incons_counters infos kind1 kind2 = + let open Lwt_result_syntax in + let source = contract_of (get_source infos) in + let* counter = Context.Contract.counter (B infos.ctxt.block) source in + let fee = Some Tez.one_mutez in + let op_infos = operation_req_default K_Reveal in + let op_infos = {{op_infos with fee} with counter = Some counter} in + let* reveal = mk_reveal op_infos infos in + let counter0 = counter in + let counter = Manager_counter.succ counter in + let counter2 = Manager_counter.succ counter in + let counter3 = Manager_counter.succ counter2 in + let operation counter kind = + select_op + { + (operation_req_default kind) with + counter = Some counter; + force_reveal = Some false; + } + infos + in + let op_counter = operation counter in + let op_counter0 = operation counter0 in + let op_counter2 = operation counter2 in + let op_counter3 = operation counter3 in + let* op1 = op_counter kind1 in + let* op2 = op_counter kind2 in + let* batch_same = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op1; op2] + in + let* op1 = op_counter2 kind1 in + let* op2 = op_counter3 kind2 in + let* batch_in_the_future = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op1; op2] + in + let* op1 = op_counter kind1 in + let* op2 = op_counter3 kind2 in + let* batch_missing_one = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op1; op2] + in + let* op1 = op_counter2 kind1 in + let* op2 = op_counter kind2 in + let* batch_inverse = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op1; op2] + in + let* op1 = op_counter0 kind1 in + let* op2 = op_counter kind2 in + let* batch_in_the_past = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op1; op2] + in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error Validate_errors.Manager.Inconsistent_counters] + -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + let* i = Incremental.begin_construction infos.ctxt.block in + let* (_ : Incremental.t) = + Incremental.add_operation ~expect_failure i batch_same + in + let* (_ : Incremental.t) = + Incremental.add_operation ~expect_failure i batch_in_the_future + in + let* (_ : Incremental.t) = + Incremental.add_operation ~expect_failure i batch_missing_one + in + let* (_ : Incremental.t) = + Incremental.add_operation ~expect_failure i batch_inverse + in + let* (_ : Incremental.t) = + Incremental.add_operation ~expect_failure i batch_in_the_past + in + return_unit + +(** A batch that consumes all the balance for fees can only face the total + consumption at the end of the batch. *) +let batch_emptying_balance_in_the_middle infos kind1 kind2 = + let open Lwt_result_syntax in + let source = contract_of (get_source infos) in + let* counter = Context.Contract.counter (B infos.ctxt.block) source in + let* init_bal = Context.Contract.balance (B infos.ctxt.block) source in + let counter = counter in + let* reveal = + mk_reveal + {(operation_req_default K_Reveal) with counter = Some counter} + infos + in + let counter = Manager_counter.succ counter in + let operation fee = + select_op + { + (operation_req_default kind1) with + force_reveal = Some false; + counter = Some counter; + fee = Some fee; + } + infos + in + let counter = Manager_counter.succ counter in + let operation2 fee = + select_op + { + (operation_req_default kind2) with + force_reveal = Some false; + counter = Some counter; + fee = Some fee; + } + infos + in + let* op_case1 = operation init_bal in + let* op2_case1 = operation2 Tez.zero in + let* case1 = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op_case1; op2_case1] + in + let* i = Incremental.begin_construction infos.ctxt.block in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error (Contract_storage.Empty_implicit_contract _)] + -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + let* (_ : Incremental.t) = + Incremental.add_operation i case1 ~expect_failure + in + return_unit + +(** A batch that consumes all the balance for fees only at the end of + the batch passes validate.*) +let batch_empty_at_end infos kind1 kind2 = + let open Lwt_result_wrap_syntax in + let source = contract_of (get_source infos) in + let* counter = Context.Contract.counter (B infos.ctxt.block) source in + let* init_bal = Context.Contract.balance (B infos.ctxt.block) source in + let half_init_bal = Test_tez.(init_bal /! 2L) in + let* reveal = + mk_reveal + {(operation_req_default K_Reveal) with counter = Some counter} + infos + in + let counter = Manager_counter.succ counter in + let operation fee = + select_op + { + (operation_req_default kind1) with + force_reveal = Some false; + counter = Some counter; + fee = Some fee; + } + infos + in + let counter = Manager_counter.succ counter in + let operation2 fee = + select_op + { + (operation_req_default kind2) with + force_reveal = Some false; + counter = Some counter; + fee = Some fee; + } + infos + in + let* op_case2 = operation Tez.zero in + let* op2_case2 = operation2 init_bal in + let* op_case3 = operation half_init_bal in + let* op2_case3 = operation2 half_init_bal in + let* case3 = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op_case3; op2_case3] + in + let* case2 = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op_case2; op2_case2] + 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. *) +let batch_reveal_transaction infos = + let open Lwt_result_syntax in + let source = contract_of (get_source infos) in + let* counter = Context.Contract.counter (B infos.ctxt.block) source in + let counter = counter in + let fee = Tez.one_mutez in + let* reveal = + mk_reveal + { + (operation_req_default K_Reveal) with + fee = Some fee; + counter = Some counter; + } + infos + in + let counter = Manager_counter.succ counter in + let* transaction = + mk_transaction + { + (operation_req_default K_Reveal) with + counter = Some counter; + force_reveal = Some false; + } + infos + in + let* batch = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; transaction] + in + let* (_ : Incremental.t) = Incremental.begin_construction infos.ctxt.block in + let* (_ : infos) = validate_diagnostic infos [batch] in + return_unit + +(** A batch of manager operation must not exceed the initial available gas in the block. *) +let batch_exceeding_block_gas ~mempool_mode infos kind1 kind2 = + let open Lwt_result_syntax in + let source = contract_of (get_source infos) in + let* counter = Context.Contract.counter (B infos.ctxt.block) source in + let g_limit = Gas.Arith.add gb_limit Gas.Arith.(integral_of_int_exn 1) in + let half_limit = + Gas.Arith.add half_gb_limit Gas.Arith.(integral_of_int_exn 1) + in + let* reveal = + mk_reveal + {(operation_req_default K_Reveal) with counter = Some counter} + infos + in + let counter = Manager_counter.succ counter in + let operation gas_limit = + select_op + { + (operation_req_default kind1) with + force_reveal = Some false; + counter = Some counter; + gas_limit = Some (Custom_gas gas_limit); + } + infos + in + let counter = Manager_counter.succ counter in + let operation2 gas_limit = + select_op + { + (operation_req_default kind2) with + force_reveal = Some false; + counter = Some counter; + gas_limit = Some (Custom_gas gas_limit); + } + infos + in + let* op_case1 = operation g_limit in + let* op2_case1 = operation2 Gas.Arith.zero in + let* op_case2 = operation half_limit in + let* op2_case2 = operation2 g_limit in + let* op_case3 = operation half_limit in + let* op2_case3 = operation2 half_limit in + let* case1 = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op_case1; op2_case1] + in + let* case3 = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op_case3; op2_case3] + in + let* case2 = + Op.batch_operations + ~recompute_counters:false + ~source + (Context.B infos.ctxt.block) + [reveal; op_case2; op2_case2] + in + let* i = Incremental.begin_construction infos.ctxt.block ~mempool_mode in + let expect_failure errs = + match errs with + | [Environment.Ecoproto_error Gas.Block_quota_exceeded] + when not mempool_mode -> + return_unit + | [ + Environment.Ecoproto_error Gas.Gas_limit_too_high; + Environment.Ecoproto_error Gas.Block_quota_exceeded; + ] + when mempool_mode -> + return_unit + | err -> + failwith + "Error trace:@, %a does not match the expected one" + Error_monad.pp_print_trace + err + in + let* (_ : Incremental.t) = + Incremental.add_operation i case1 ~expect_failure + in + let* (_ : Incremental.t) = + Incremental.add_operation i case3 ~expect_failure + in + let* (_ : Incremental.t) = + Incremental.add_operation i case2 ~expect_failure + in + return_unit + +let make_tztest_batched ?(fmt = Format.std_formatter) name test subjects + info_builder = + let open Lwt_result_syntax in + Tztest.tztest name `Quick (fun () -> + let* infos = info_builder () in + List.iter_es + (fun kind1 -> + let k1s = kind_to_string kind1 in + List.iter_es + (fun kind2 -> + Format.fprintf + fmt + "%s: [%s ; %s]@." + name + k1s + (kind_to_string kind2) ; + test infos kind1 kind2) + subjects) + subjects) + +let tests = + let open Lwt_result_syntax in + let mk_default () = default_init_ctxt () in + let mk_high_gas_limit () = + init_ctxt {ctxt_req_default with hard_gas_limit_per_block = Some gb_limit} + in + let revealed = revealed_subjects in + [ + ( Tztest.tztest "batch reveal and transaction" `Quick @@ fun () -> + let* infos = mk_default () in + batch_reveal_transaction infos ); + ] + @ List.map + (fun (name, f, subjects, info_builder) -> + make_tztest name f subjects info_builder) + [("batch two reveals", batch_two_reveals, revealed, mk_default)] + @ List.map + (fun (name, f, subjects, info_builder) -> + make_tztest_batched name f subjects info_builder) + [ + ("reveal in the middle", batch_in_the_middle, revealed, mk_default); + ("batch two sources", batch_two_sources, revealed, mk_default); + ("batch incons. counters", batch_incons_counters, revealed, mk_default); + ( "empty balance in middle of batch", + batch_emptying_balance_in_the_middle, + revealed, + mk_default ); + ( "empty balance at end of batch", + batch_empty_at_end, + revealed, + mk_default ); + ( "too much gas consumption", + batch_exceeding_block_gas ~mempool_mode:false, + revealed, + mk_high_gas_limit ); + ( "too much gas consumption (mempool)", + batch_exceeding_block_gas ~mempool_mode:true, + revealed, + mk_high_gas_limit ); + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("batched managers validation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/valid_operations_generators.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/valid_operations_generators.ml new file mode 100644 index 000000000000..896d794b52b7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/valid_operations_generators.ml @@ -0,0 +1,243 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Generator_descriptors + +(** {2 Building the Setup} *) + +(** Setup for generating valid operation of several kind of + operations. It gathers the following information to setup + {! Generator_descriptor.state} into which valid operations + can be generated: + - [nb_cycles] the total number of cycles to bake, + - [nb_blocks] the number of blocks to bake in the last cycle, + - [params] the constants required, and + - [prelude] that associates to each cycle to bake a list of + {! Generator_descriptors.descriptor} prelude functions. *) +type setup = { + prelude : + (int * (state -> (packed_operation list * state) tzresult Lwt.t) list) list; + nb_cycles : int; + nb_blocks : int; + params : Parameters.t; +} + +(** Select the prelude actions of a specific cycle in a setup prelude. *) +let prelude_on_cycle (c : int) + (actions : + (int * (state -> (packed_operation list * state) tzresult Lwt.t) list) + list) : (state -> (packed_operation list * state) tzresult Lwt.t) list = + match List.filter (fun (c1, _actions) -> c = c1) actions with + | (c1, actions) :: _ -> + assert (c = c1) ; + actions + | [] -> [] + +(** Knowing the total number of required cycles, normalize a prelude + on the list of the pair of a cycle and prelude actions. *) +let normalize_preludes nb_cycles (descr : descriptor) = + let normalize prelude = + match prelude with + | On n, actions -> [(nb_cycles - n, actions)] + | From n, actions -> + List.fold_left + (fun acc i -> acc @ [(nb_cycles - n + i, actions)]) + [] + (1 -- n) + in + let prim = normalize descr.prelude in + match descr.opt_prelude with + | Some prelude -> normalize prelude @ prim + | None -> prim + +(** Insert a normalized prelude in a prelude of a setup.*) +let rec insert_normalize_preludes + ((n, action) : + int * (state -> (packed_operation list * state) tzresult Lwt.t)) + (preludes : + (int * (state -> (packed_operation list * state) tzresult Lwt.t) list) + list) = + match preludes with + | [] -> [(n, [action])] + | (m, actions) :: rest -> + if m = n then (m, actions @ [action]) :: rest + else (m, actions) :: insert_normalize_preludes (n, action) rest + +(** Produce a setup prelude from a list of descriptor and a nb of + cycles*) +let compose_preludes nb_cycles descrs = + let normalized_preludes = List.map (normalize_preludes nb_cycles) descrs in + List.fold_left + (fun acc pre -> + List.fold_left (fun acc pr -> insert_normalize_preludes pr acc) acc pre) + [] + normalized_preludes + +(** Agregate the parameters of several {! Generator_descriptors.descriptor}.*) +let initiated_params descrs nb_accounts = + let consensus_committee_size = nb_accounts in + let initial_params = + Tezos_protocol_020_PsParisC_parameters.Default_parameters + .parameters_of_constants + { + Context.default_test_constants with + consensus_threshold = 0; + consensus_committee_size; + } + in + let descrs_params = List.map (fun descr -> descr.parameters) descrs in + List.fold_left (fun acc f -> f acc) initial_params descrs_params + +(** Make a [setup] from a list of {! Generator_descriptors.descriptor}. The required number of + cycles and number of blocks in the last cycle are the maximum of + required cycle and number of block in the descriptors list. The + prelude is the composition of the composition of the descriptors + preludes list -- see [compose_preludes]. The parameters are the agregation of the + descriptors parameters -- see [initiated_params]. *) +let setup_of descrs nb_accounts = + let params = initiated_params descrs nb_accounts in + let max_list l = List.fold_left max 0 l in + let required_cycle_list l = + List.map (fun descr -> descr.required_cycle params) l + in + let required_block_list l = + List.map (fun descr -> descr.required_block params) l + in + let sorted_descrs = + List.sort + (fun pre1 pre2 -> + Int.compare (pre1.required_cycle params) (pre2.required_cycle params)) + descrs + in + let nb_cycles = max_list (required_cycle_list descrs) in + let nb_blocks = max_list (required_block_list descrs) in + let prelude = compose_preludes nb_cycles sorted_descrs in + {prelude; nb_cycles; nb_blocks; params} + +(** From a number of accounts and a list of descriptors set up the + prelude state. + + Thanks to the setup computing for the list of descriptors -- see [setup_of] --, + initiates a context with the setup parameters, and the number of + accounts. Initiate a state that will be fulfilled during the + preludes. During the required number of cycles of the setup, bakes + each cycle with the setup prelude by selecting the actions to + perform on it. On the last cycle, bake the required number of + blocks of the setup. Finally, adds the delegates at the end of + the prelude in the state. *) +let init nb_accounts descrs = + let open Lwt_result_syntax in + let setup = setup_of descrs nb_accounts in + let* initial_block, bootstraps = + Context.init_with_parameters_n setup.params nb_accounts + in + let* voters = Context.Vote.get_listings (B initial_block) in + let* initial_voters = + List.map_es (fun (c, _) -> return (Contract.Implicit c)) voters + in + let my_bake selected_preludes_for_cycle state = + let* state, operations = + List.fold_left_es + (fun (state, ops) prelude -> + let+ ops', state = prelude state in + let ops = ops' @ ops in + (state, ops)) + (state, []) + selected_preludes_for_cycle + in + let b = state.block in + let operations = + List.sort (fun op1 op2 -> Operation.compare_by_passes op2 op1) operations + in + let+ block = Block.bake ~operations b in + {state with block; pred = Some b} + in + let my_bake_n cycle n state = + List.fold_left_es + (fun state _ -> + let selected_preludes = prelude_on_cycle cycle setup.prelude in + my_bake selected_preludes state) + state + (1 -- n) + in + let my_bake_until_cycle_end cycle state = + let current_level = state.block.Block.header.shell.level in + let current_level = + Int32.rem current_level setup.params.constants.blocks_per_cycle + in + let delta = + Int32.sub setup.params.constants.blocks_per_cycle current_level + in + my_bake_n cycle (Int32.to_int delta) state + in + let* state = + List.fold_left_es + (fun state cycle -> my_bake_until_cycle_end cycle state) + (init_state initial_block ~voters:initial_voters ~bootstraps) + (Stdlib.List.init setup.nb_cycles Fun.id) + in + let my_bake_n_default n state = + List.fold_left_es + (fun state _ -> + let pred = state.block in + let+ block = Block.bake state.block in + {state with block; pred = Some pred}) + state + (1 -- n) + in + let* state = + if setup.nb_blocks >= 1 then my_bake_n_default setup.nb_blocks state + else return state + in + return state + +(** In a state, generates all the valid operations of a list of kinds. *) +let candidates state kinds nb_bootstrap max_batch_size = + let open Lwt_result_syntax in + let* candidates = + List.fold_left_es + (fun acc k -> + let* candidates = + (descriptor_of k ~nb_bootstrap ~max_batch_size).candidates_generator + state + in + let acc = acc @ candidates in + return acc) + [] + kinds + in + return candidates + +(** From a list of kind of operations generates all the valid + operations of this kind and the generation state. *) +let covalid ks ~nb_bootstrap ~max_batch_size = + let open Lwt_result_syntax in + let* state = + init nb_bootstrap (descriptors_of ~nb_bootstrap ~max_batch_size ks) + in + let* candidates = candidates state ks nb_bootstrap max_batch_size in + return (state, candidates) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/validate_helpers.ml b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/validate_helpers.ml new file mode 100644 index 000000000000..13016b83dc0d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/validate_helpers.ml @@ -0,0 +1,399 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Registered_nonces = Nonce +open Protocol +open Alpha_context +module Manager = Manager_operation_helpers + +(** {2 Helpers} *) + +(** {3 Randomness } *) + +let gen_bounded_int min max = QCheck2.Gen.(generate1 @@ int_range min max) + +let pick_one l = QCheck2.Gen.(generate1 @@ oneofl l) + +let pick_n (n : int) (l : 'a list) : 'a list = + List.take_n n QCheck2.Gen.(generate1 @@ shuffle_l l) + +(** {3 Helpers for lists } *) + +let get_n l n = + assert (List.length l > n) ; + Stdlib.List.nth l n + +let mycombine l1 l2 = + let sz_dels = List.length l1 in + let sz_phs = List.length l2 in + let dels, phs = + if sz_dels = sz_phs then (l1, l2) + else if sz_dels < sz_phs then (l1, List.take_n sz_dels l2) + else (List.take_n sz_phs l1, l2) + in + Stdlib.List.combine dels phs + +(** {3 Global Values}*) + +let ballots = Vote.[Yay; Nay; Pass] + +let protos = + List.map + (fun s -> Protocol_hash.of_b58check_exn s) + [ + "ProtoALphaALphaALphaALphaALphaALphaALpha61322gcLUGH"; + "ProtoALphaALphaALphaALphaALphaALphaALphabc2a7ebx6WB"; + "ProtoALphaALphaALphaALphaALphaALphaALpha84efbeiF6cm"; + "ProtoALphaALphaALphaALphaALphaALphaALpha91249Z65tWS"; + "ProtoALphaALphaALphaALphaALphaALphaALpha537f5h25LnN"; + "ProtoALphaALphaALphaALphaALphaALphaALpha5c8fefgDYkr"; + "ProtoALphaALphaALphaALphaALphaALphaALpha3f31feSSarC"; + "ProtoALphaALphaALphaALphaALphaALphaALphabe31ahnkxSC"; + "ProtoALphaALphaALphaALphaALphaALphaALphabab3bgRb7zQ"; + "ProtoALphaALphaALphaALphaALphaALphaALphaf8d39cctbpk"; + "ProtoALphaALphaALphaALphaALphaALphaALpha3b981byuYxD"; + "ProtoALphaALphaALphaALphaALphaALphaALphaa116bccYowi"; + "ProtoALphaALphaALphaALphaALphaALphaALphacce68eHqboj"; + "ProtoALphaALphaALphaALphaALphaALphaALpha225c7YrWwR7"; + "ProtoALphaALphaALphaALphaALphaALphaALpha58743cJL6FG"; + "ProtoALphaALphaALphaALphaALphaALphaALphac91bcdvmJFR"; + "ProtoALphaALphaALphaALphaALphaALphaALpha1faaadhV7oW"; + "ProtoALphaALphaALphaALphaALphaALphaALpha98232gD94QJ"; + "ProtoALphaALphaALphaALphaALphaALphaALpha9d1d8cijvAh"; + "ProtoALphaALphaALphaALphaALphaALphaALphaeec52dKF6Gx"; + "ProtoALphaALphaALphaALphaALphaALphaALpha841f2cQqajX"; + ] + +type secret_account = { + blinded_public_key_hash : Blinded_public_key_hash.t; + account : Signature.Ed25519.Public_key_hash.t; + activation_code : Blinded_public_key_hash.activation_code; + amount : Tez.t; +} + +let secrets = + (* Exported from proto_alpha client - TODO : remove when relocated to lib_crypto *) + let read_key mnemonic email password = + match Tezos_client_base.Bip39.of_words mnemonic with + | None -> assert false + | Some t -> + (* TODO: unicode normalization (NFKD)... *) + let passphrase = Bytes.(cat (of_string email) (of_string password)) in + let sk = Tezos_client_base.Bip39.to_seed ~passphrase t in + let sk = Bytes.sub sk 0 32 in + let sk : Signature.Secret_key.t = + Ed25519 + (Data_encoding.Binary.of_bytes_exn + Signature.Ed25519.Secret_key.encoding + sk) + in + let pk = Signature.Secret_key.to_public_key sk in + let pkh = Signature.Public_key.hash pk in + (pkh, pk, sk) + in + List.map + (fun (mnemonic, secret, amount, pkh, password, email) -> + let pkh', pk, sk = read_key mnemonic email password in + let pkh = Signature.Ed25519.Public_key_hash.of_b58check_exn pkh in + assert (Signature.Public_key_hash.equal (Ed25519 pkh) pkh') ; + let activation_code = + Stdlib.Option.get + (Blinded_public_key_hash.activation_code_of_hex secret) + in + let bpkh = Blinded_public_key_hash.of_ed25519_pkh activation_code pkh in + let account = Account.{pkh = Ed25519 pkh; pk; sk} in + Account.add_account account ; + { + blinded_public_key_hash = bpkh; + account = pkh; + activation_code; + amount = + WithExceptions.Option.to_exn + ~none:(Invalid_argument "tez conversion") + (Tez.of_mutez (Int64.of_string amount)); + }) + [ + ( [ + "envelope"; + "hospital"; + "mind"; + "sunset"; + "cancel"; + "muscle"; + "leisure"; + "thumb"; + "wine"; + "market"; + "exit"; + "lucky"; + "style"; + "picnic"; + "success"; + ], + "0f39ed0b656509c2ecec4771712d9cddefe2afac", + "23932454669343", + "tz1MawerETND6bqJqx8GV3YHUrvMBCDasRBF", + "z0eZHQQGKt", + "cjgfoqmk.wpxnvnup@tezos.example.org" ); + ( [ + "flag"; + "quote"; + "will"; + "valley"; + "mouse"; + "chat"; + "hold"; + "prosper"; + "silk"; + "tent"; + "cruel"; + "cause"; + "demise"; + "bottom"; + "practice"; + ], + "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4", + "72954577464032", + "tz1X4maqF9tC1Yn4jULjHRAyzjAtc25Z68TX", + "MHErskWPE6", + "oklmcktr.ztljnpzc@tezos.example.org" ); + ( [ + "library"; + "away"; + "inside"; + "paper"; + "wise"; + "focus"; + "sweet"; + "expose"; + "require"; + "change"; + "stove"; + "planet"; + "zone"; + "reflect"; + "finger"; + ], + "411dfef031eeecc506de71c9df9f8e44297cf5ba", + "217487035428349", + "tz1SWBY7rWMutEuWS54Pt33MkzAS6eWkUuTc", + "0AO6BzQNfN", + "ctgnkvqm.kvtiybky@tezos.example.org" ); + ( [ + "cruel"; + "fluid"; + "damage"; + "demand"; + "mimic"; + "above"; + "village"; + "alpha"; + "vendor"; + "staff"; + "absent"; + "uniform"; + "fire"; + "asthma"; + "milk"; + ], + "08d7d355bc3391d12d140780b39717d9f46fcf87", + "4092742372031", + "tz1amUjiZaevaxQy5wKn4SSRvVoERCip3nZS", + "9kbZ7fR6im", + "bnyxxzqr.tdszcvqb@tezos.example.org" ); + ( [ + "opera"; + "divorce"; + "easy"; + "myself"; + "idea"; + "aim"; + "dash"; + "scout"; + "case"; + "resource"; + "vote"; + "humor"; + "ticket"; + "client"; + "edge"; + ], + "9b7cad042fba557618bdc4b62837c5f125b50e56", + "17590039016550", + "tz1Zaee3QBtD4ErY1SzqUvyYTrENrExu6yQM", + "suxT5H09yY", + "iilkhohu.otnyuvna@tezos.example.org" ); + ( [ + "token"; + "similar"; + "ginger"; + "tongue"; + "gun"; + "sort"; + "piano"; + "month"; + "hotel"; + "vote"; + "undo"; + "success"; + "hobby"; + "shell"; + "cart"; + ], + "124c0ca217f11ffc6c7b76a743d867c8932e5afd", + "26322312350555", + "tz1geDUUhfXK1EMj7VQdRjug1MoFe6gHWnCU", + "4odVdLykaa", + "kwhlglvr.slriitzy@tezos.example.org" ); + ( [ + "shield"; + "warrior"; + "gorilla"; + "birth"; + "steak"; + "neither"; + "feel"; + "only"; + "liberty"; + "float"; + "oven"; + "extend"; + "pulse"; + "suffer"; + "vapor"; + ], + "ac7a2125beea68caf5266a647f24dce9fea018a7", + "244951387881443", + "tz1h3nY7jcZciJgAwRhWcrEwqfVp7VQoffur", + "A6yeMqBFG8", + "lvrmlbyj.yczltcxn@tezos.example.org" ); + ( [ + "waste"; + "open"; + "scan"; + "tip"; + "subway"; + "dance"; + "rent"; + "copper"; + "garlic"; + "laundry"; + "defense"; + "clerk"; + "another"; + "staff"; + "liar"; + ], + "2b3e94be133a960fa0ef87f6c0922c19f9d87ca2", + "80065050465525", + "tz1VzL4Xrb3fL3ckvqCWy6bdGMzU2w9eoRqs", + "oVZqpq60sk", + "rfodmrha.zzdndvyk@tezos.example.org" ); + ( [ + "fiber"; + "next"; + "property"; + "cradle"; + "silk"; + "obey"; + "gossip"; + "push"; + "key"; + "second"; + "across"; + "minimum"; + "nice"; + "boil"; + "age"; + ], + "dac31640199f2babc157aadc0021cd71128ca9ea", + "3569618927693", + "tz1RUHg536oRKhPLFfttcB5gSWAhh4E9TWjX", + "FfytQTTVbu", + "owecikdy.gxnyttya@tezos.example.org" ); + ( [ + "print"; + "labor"; + "budget"; + "speak"; + "poem"; + "diet"; + "chunk"; + "eternal"; + "book"; + "saddle"; + "pioneer"; + "ankle"; + "happy"; + "only"; + "exclude"; + ], + "bb841227f250a066eb8429e56937ad504d7b34dd", + "9034781424478", + "tz1M1LFbgctcPWxstrao9aLr2ECW1fV4pH5u", + "zknAl3lrX2", + "ettilrvh.zsrqrbud@tezos.example.org" ); + ] + +(** {3 Context Manipulations } *) + +let pick_two_attesters ctxt = + let open Lwt_result_syntax in + let module V = Plugin.RPC.Validators in + let* attesters = Context.get_attesters ctxt in + match attesters with + | a :: b :: _ -> return (a.V.consensus_key, b.V.consensus_key) + | _ -> assert false + +let pick_addr_attester ctxt = + let open Lwt_result_syntax in + let module V = Plugin.RPC.Validators in + let* attesters = Context.get_attesters ctxt in + match attesters with a :: _ -> return a.V.consensus_key | _ -> assert false + +let init_params = + Tezos_protocol_020_PsParisC_parameters.Default_parameters + .parameters_of_constants + {Context.default_test_constants with consensus_threshold = 0} + +let delegates_of_block block = + let open Lwt_result_syntax in + let+ validators = Context.get_attesters (B block) in + List.map + (fun Plugin.RPC.Validators.{consensus_key; slots; _} -> + (consensus_key, slots)) + validators + +(** Sequential validation of an operation list. *) +let sequential_validate ?(mempool_mode = true) block operations = + let open Lwt_result_syntax in + let* inc = Incremental.begin_construction ~mempool_mode block in + let* (_inc : Incremental.t) = + List.fold_left_es + (fun acc op -> Incremental.validate_operation acc op) + inc + operations + in + return_unit diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/README.md b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/README.md new file mode 100644 index 000000000000..62f2267ad645 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/README.md @@ -0,0 +1,73 @@ +# About +This folder contains example test kernels, used for running `SCORU WASM` integration tests. + +The test kernels have been built from [tezos/kernel](https://gitlab.com/trili/kernel.git), then manually edited to take into account a change in naming introduced by [this MR](https://gitlab.com/tezos/tezos/-/merge_requests/6914). + +```terminal +wasm2wat ${OLD_KERNEL} -o tmp.wat +sed -i -e 's/kernel_next/kernel_run/g' -e 's/rollup_safe_core/smart_rollup_core/g' tmp.wast +wat2wasm tmp.wat -o {OLD_KERNEL} +``` + +# Available kernels +It is possible to build the test kernels manually, and verify that they are bit-for-bit identical. + +## Prerequisites +You will need `docker`, `git` and `wasm-strip` installed, alongside either `bash` or `zsh`. +- `wasm-strip` is part of the [WebAssembly Binary Toolkit](https://github.com/WebAssembly/wabt). + +Next, clone the *tezos/kernel* repository: +``` shell +git clone https://gitlab.com/tezos/kernel.git wasm_kernel +cd wasm_kernel +``` +and then follow the instructions below for the required kernel. + +## [computation.wasm](./computation.wasm) +The computation kernel performs a simple computation (addition) on each call to its `kernel_run` entrypoint. +It keeps the result on the heap, and therefore uses the allocator. It makes no use of any *PVM host-capabilities*. + +It is designed to be small enough to be able to originate directly within a boot sector, but also large enough to be +used with the *gather-floppies* mechanism. + +To build the `computation.wasm` kernel, run the following from the checked-out `tezos/kernel` repo: +``` shell +git checkout 60e2dedc2b5debb9a6add98038e52e4cd0a358a6 + +# Load the required rust toolchain dockerfile +source scripts/cargo-docker.sh + +cargo build -p test_kernel --target wasm32-unknown-unknown --release \ + --no-default-features --features none,wee_alloc + +# computation_kernel.wasm is a 1.6M wasm binary. +cp target/wasm32-unknown-unknown/release/test_kernel.wasm computation_kernel.wasm + +# Strips binary down to 9.7K +wasm-strip computation_kernel.wasm +``` +# echo.wasm + +`echo.wasm` is the result of `wat2wasm echo.wast`. + +This simple kernel writes the external messages it receives in its outbox. + +To achieve that, it needs to take the encoding of the inputs into +account to extract the payload to push into the outbox. + +# tx-kernel.wasm +The `tx-kernel` is a TORU-like program for transacting in a wasm rollup. + +To build, run the following from the checked-out `tezos/kernel` repo: +```shell +git checkout 69f69144764dcd59dcc1fd144bf6e8f707f0431e + +# Load the required rust toolchain dockerfile +source scripts/cargo-docker.sh + +cargo make wasm-tx-kernel + +cp target/wasm32-unknown-unknown/release/kernel_core.wasm tx-kernel.wasm + +wasm-strip tx-kernel.wasm +``` diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/computation.wasm b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/computation.wasm new file mode 100644 index 0000000000000000000000000000000000000000..1ea01d0f154dfd5fe8b8d2f6f0738629ccb9b23f GIT binary patch literal 9199 zcmZQbEY4+QU|?YM;z?ktuV<_WkqimU^~RN%ErjR%ErRZz`@DH4x*SjSXfwC*%`UG7+6>tI2ajO7#SHExfz)l z7#JBDnHd=wSeRHDnYb7jI5;>MxEYw3SXdbg7-eNynHd=b*(90k866uM4lr=nGdND^ zfzS&;G`kTCTW)G@eo-Y816OuxQC@0Jd{Jp00|Qrld`ed*gCiri45JMv7dMZfkg$NVxQv*rgqpgBrjD+jsiUo#HP>TDx66!-to6za zjsn?A3@Qu)B1{fU4vq{OOb?nJco`fS9P7rZ*rq$ixTD4vvgjU^gf*I0|H`Fz|CbZfQ8c;3%NL z;K-5Xcm%{=(r|!5z=;83uOS0B69YFtBV)Y+g94)fnOb!qg%nD2bd`c{! z@L*A3P+(SIRA5wK_LdfKm4YZ>0C`Y=pId?ly8#O%ai&dlJ*pa{~> zV8+Cuz^uTmz~b1@P*a%Y$W&y;#J~-5iy0HhNubc>W@T_}VBux~C5P86j2!hK7icgs zD6xVZ&gfX5rO2kh;K)>>$PS9AY()-c2L)C~jx0q^P_!$sYA|sqaXB&;@-ir}Dl+mg zax*(9a4K*)))ksDF~F3tC~-N~6e@9o5)D|9BZC5`0;etmgCk?1v?3!nlLN>k1|@Eg zG9FiuIt3mDZbzmlh_%n4G%slW+Jc+7=h zvm9#*LH-4?Sroar6<8Ix9GMHjdO>0gN}OOW1CxUSrz2A#$N)x2%7um#lLDg|6N3UH z*s}_ZimV`6m}j{`wt~}nO`#GOSdkKIwgS5+FVxct%nA$&EE-G#f()SG%W~w%Qs7cx z&sN|lRO0gGWl&&KU@hcjQec8Ox&{fXPVt@oND5xA66u1?*z#+#4@)VZ>7c}HpK_LeU2vFdGf)Zp83n(H$ zmVzS;>H=`sD6keOals-H6hxpX)?i`)N1y_u0+(Yg*wL)u;B;gvQUZk+$b3dekjV_( z;Do}@t-u6wB8L(yC^%Vp8MwI}8Mxb+8JVF)3$qF&%ouqY6qulFk|8Yr7BS7apcKT zU3Z$L!>uM)^2X0V6?s{)gNpd*7KqXM%A69dRxP{IQ9cp&+Q(Ts@)q)dSs%@{>S za9+}2;xS`l0L2uu0;au=S3pG&h!6nV%jBTI0!rhI3QX_}&Z5Amz=D>+86g=Q7TBQ7 zjc^pWpakh+M9tfvLI&Bj$d;qH7F=9psW2!oa$jR*WP`>73n(5Gz$G}7D<~Z+Fhc^K z$&oqBk*N$6{LIkc2Ri{2^c7i3ObSeh1jM2M3VBc=;|PfraAYVlgNp(dN1iMJVX)bt zbn94?rNj!-T2rXR21=`Jppu6jT$+H?gQ6ZJ!T}C3P@Ylb1O+skA}1)W6*$1DoCBnj zLxBUD%Gp4v9GoPT7(x0tU3nQH4y-9uWCZ6nMRsllP6b8e$<2Ol%orOcqPR$u`)1VB~lPew*2MABAZ0hK}w-~T!agNBA6MJ7X-LLrJExosG*Z3AjRYWO0i%Ufl79e ze;7b1m01JSv=K05;0DRFC^CVa0;$O%DMW$UQ32di6fk1oUJLRB$SJ5;0TkDcjEXFv zHmL_Mxa0*liI~8qDlzl2DlqagD=;ZC^RR%TfYFSJ1*D!E6em1v+zO!V29jk2H)92u zKNTsQe zt;7T=tR2A(L~LOWYH%{+3UempFlSO=0fjjexMVS70*5&hG|ZV47#%@%l>j8nK?MOQ z&X^EM0$jMVC@_G-oJoU;MUfdL%$Y%6U_uIW9tNjxkA7_Y^l<%iR&HJfr;F=m9GTg? z>3d5(_kAXa{{*1^gT#sgqhkZuhhRs6vQC45Kd4YwV05%EbZlTOvSQ!`r7=ggGRFfT z9*-lFA}FYt96)~JP=dHfgNeZ%lr|NZ1*E~^ph#g*U;f*LcRh88#xGYZHv za8GAqVyS1WQ)X~904GvVL7oL_-hgTs7HH>JkwpQNLmWA>lvqI?WKdvoVl-#w0F~g5 z99iJp<|vWnD3Ap%ur--L-8Ka#kPrt*h$9Ooq`(4ZNhmNmiex#S0fi1onShlPwEYS$ zCP9gTNt2nw9Mr!9$%AZW0jq$@Gdl8QL0rPD$;6<@roiaLXwC$xQrOIyC72u>c_5u~ zUIs7=RDLolFljPNfchJtE)Y1OfufPYv8Cw%15%a43dpg{AU{BY1=-!;=!Cl4m653)9CwP~ zZVCe^E*&}Gp#fq+Lj&YzNJ~wD!Ep*oAaDzV@(r5Ue`ts(WGk_%fI91Jjtrpm*wW*m z#11ZWT6!Ennaq(vm!YG_0o?7?V4Bba8r4u_0}YihI5Jv+q_{y1Br}i{NWB8PBZCL1 zIqb*;>I$(cuvjrjD6oPWks_e3iW!pt$ethFAbaY4z`bdZg-YyZOh3AzV>k^x4&WvY zNadey2Ss)TR?r{_sK?3(YR9r_GBbdZEIYUt2Wml!2r`1*{{y5Nl7s>SC^zzek`-8h16<%c&S^ftAYchMNgvKq zVc-T;WExBiQq1){4BVjB?jCkVwt7&}D*#HtpkxBUAR!JV7Dq-mQ18}}(H+$0UPUnFChF z?4SUuU0L0DnLxHFFzYZdC~-J~(j2&61$Q`@927Vl6Tp$^$drW;Du4(vLxezWekM>g z%2onmf~$6(k|GeB+0nkRNP)xgKVzYz5NK5F14ChvV?)Cc1~*<%Kb|E^k%L=-U4c1U zfg?+iU4aeMQ)L4UG$?Q=u)2Y}vK%0nF+0|KfkPnyRI4*P7Jw)YT?UxF9J&l}dpUF& zAohZ~yqNZa#;m|zW(Q?2n5Wnkm^{IJP}`70fn9;g4cz8)WKd*QU{?h7n%J{+7#JKK zJV4RF0S;_tklUFQn599(cA!B*=!h7oHo+bT{M-r*jy#|^fpi2x6+Fl*j0#Kw&M>zy zfgQpDs-T%1nF|%!!OmrJtj}^}_J_zRFhT|onLwR8Hb(}K0~MJ;kqVAU$NlwQppg?s zu#=%2CS(pXoTJF00Lr|I%nEFvE-57R*X0iCvKmB_Jf+_3JeMy3hbbAj{(%5;C5u>2X(xd z6*!_LO!3e1jcz$Jo!0yC(H0JW4D&6s2$Z7K=S@UEi-sMu2g4L4gdaNEJn0T;QT z>O%rlU4ok&ppqBV$K3-ql1G6FYB;ED1PETD>k8DyLSsHdU;?x9IQC;>>sLB?)4lvqK7da&{Z)I$SxAwWf^29tmy z130TX{{R0Ul(iYNlvotmzyZq$sRxum2?*5XQUKM^44^Eo!K4Byhj>99FHj}G3>sQx zfM^h8VBiHc_BpZ?LH${dEJa4J6-sQppf)|IB@E6s&@QhdYY8Y(fU?B@|Nrd^L6a6N zpsJ2Rk%`KqBf#enj5F6$eW>D{xRe>!_36$h?85qEU1?~rFGBG$QbbTiM`Jn2(u}fr*hDG`dov$m7VM$gaSpz>}rK0~+6waOY)I z;L%_LRhEjJpk&GpvY8VUz03;iW=x=o4*{?(2xGxMh8fH5$XuexslcVcnWe-DHxe{( z4jS2E2N}r?GLjvV%DBy#Bow$n*@wZAxg-nJ!Uy%3II=)OETG^9^^L&c%%Q;MsF0<^ z<_^l!jtq*R=^9Xf&=WM(1MWgAfIJQwqhKxp57tU6fkx0lQOkl9n68k44^SNsZdocY zaPu%YHSSn7`RnJWZ$!9dz!OXo;I!+=r@)9@IdKbsW>r9;19qQ)IX64FF~9+(dBC(T zg8(j0|R#*B=;O(0Jqpc zjXQwGL_nQ$W~996Epvg8+=Mow&YzhonpqVa3CIvP{P}K#k zW|bHn>x&)P%M=(L*~*F>8=G1<3c+nO(7+RRIp`o8Hhs7>F=b_CfdUjXm#M^{zz)ty z3Tz6Tpwf(4fhAiJGyuv`=J>zy4||~k6NJukY;0i3aTF*6HGVk2LCUSb2ATpY0qJ7} z7q85q=@d{o%Uq}gieK=^Hl(2lnu&n42Owk7j(`6D|Ic0sE&-XC9bhdDC3dJ+*s%lw zb~#88V3h*}0X7NbAOIKPHCdqP8t`-*c%+)ev9Y0{p(aa_5#%)7#(+BWjx3-608L^- z%m8&d@B|(|H)v7<)C}S029IPbLK?Lo1K>?2P;&}2uK*4n&}1lw0s}PNW`TxA;SD0t ztSK@FDd&Ki_fV(7yayg}1UHr7rh#iFMvxCcZ8jw)a0cVxKF9=~r3KZmj{Kkk0n{P~ z4I?@-C@^F@G8ZbbWPw_R3gD?{P`i^6RFNq#D}bgWtQbIbE+c4G7c}mr#H_&T2{xEj zfk}ZSTZtVsSHJ-t&;SL70!tQnE)Z0#a5yr8hC(?VnM;(|93=`BnG`rds<}YH44V63 z%La+EfaV*)b*BQW0-FL;8K`_`P-0VHDFIIwfU0&yMg>+!mMkS!1!hlZ#SAu`L4gw- zuaF5&P?3tMnwuLuZv(O&l;A<_aB$#(T0mKfte}>i0wcHv2DJbfK`j7OpE7WBf#>fP zm;_w7xnD6eGC&qqJYd!@EiTe8E=tyiE~7}zD=Df33nV8dXQb*C6*Dj}FbFUxF)%O) zGcYhHFfcGA<`ktSrc^2<4`N6&ig#g4af(#4{LTGA0;UWSR1L*-_Q3eJEF$M+( zaRvqknBx+2a`KbG&MQhRk1tD2)+;JbPAo`F&Mc`^$S+GRO3TSFXJBAxU=&~g*^|Nu vaW@+i0|O`woxtJkTUz2;RFq%Dz#xqjZXo|zDKIdsVH5z1o?#SV0L29W)k`Tp literal 0 HcmV?d00001 diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wasm b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wasm new file mode 100644 index 0000000000000000000000000000000000000000..383db3bebf9adb36eac791f54ea6a70e18835827 GIT binary patch literal 408 zcmZQbEY4+QU|?X>U{7GKudipUPhbL*to0zkSf9XH&yc_f6=z6bU|>pQ7A($9EGmgF z%FoFuEr?IfFG}SqN=;0O&&(?*En#55l;$Zf$}CBZ&o3r`@ z%*w*d!pg?V%*epVF2cl|o0`kSz?Gd^l$V+lUsRgMz{a(NkwuGpvd6Z!lb|;!0On-B*4tgZNUn11-Fns#PRy6d1d-VsY&_yB@B)~7`T}j Y7#SRYfoLWM$3GyNfx+<~12-ch0Av4MZU6uP literal 0 HcmV?d00001 diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wast b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wast new file mode 100644 index 000000000000..99026dba63a0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/echo.wast @@ -0,0 +1,106 @@ +(module + + (type $read_t (func (param i32 i32 i32) (result i32))) + (type $write_t (func (param i32 i32) (result i32))) + (type $store_w_t (func (param i32 i32 i32 i32 i32) (result i32))) + + (import "smart_rollup_core" "read_input" (func $read_input (type $read_t))) + (import "smart_rollup_core" "write_output" (func $write_output (type $write_t))) + (import "smart_rollup_core" "store_write" + (func $store_write (type $store_w_t))) + + (data (i32.const 100) "/kernel/env/reboot") + (data (i32.const 120) "\00\01") ;;Start_of_level + (data (i32.const 122) "\00\02") ;;End_of_level + (data (i32.const 124) "\00\00") ;;Internal Transfer + (data (i32.const 126) "\01") ;;External + + (memory 1) + (export "mem" (memory 0)) + + (func $set_reboot_flag (param $input_offset i32) ;;location of input + (local $eol i32) + (local $input_header i32) + + (local.set $eol (i32.load16_u (i32.const 122))) + (local.set $input_header + (i32.load16_u (local.get $input_offset))) + (i32.ne (local.get $eol) (local.get $input_header)) + (if (then + (call $store_write + (i32.const 100) ;; offset + (i32.const 18) ;; key size + (i32.const 0) ;; offset in the durable storage page + (i32.const 100) ;; offset in memory for the value (placeholder here) + (i32.const 0)) ;; size of the value in memory (placeholder here) + (drop))) + ) + + ;; Internal message representation + ;; (see Data_encoding.Binary.describe Sc_rollup_inbox_message_repr.encoding): + ;; - Tag (1B) `t1` + ;; - Tag (1B) `t2` + ;; - Payload (variable) `payload`, expected as a Byte + ;; + Tag (1B) `tb` + ;; + Size (4B) `size_b` + ;; + bytes (variable) + ;; - Sender (20B) `sender` + ;; - Source (21B) `source` + ;; - Destination (20B) `destination` + ;; + ;; payload = len - (t1 + t2 + tb + size_b + sender + source + destination) + ;; ==> payload = len - (1 + 1 + 1 + 4 + 20 + 21 + 20) + ;; ==> payload = len - 68 + ;; and starts at offset 7 from the input + + (func $internal_payload_size (param $input_size i32) (result i32) + (i32.sub (local.get $input_size) (i32.const 68))) ;; tag + + (func $write_message (param $input_offset i32) (param $size i32) + (local $internal i32) + (local $external i32) + (local $message_tag i32) + (local $internal_transfer_tag i32) + (local $payload_size i32) + + (local.set $external (i32.load8_u (i32.const 126))) + (local.set $internal (i32.load16_u (i32.const 124))) + (local.set $message_tag + (i32.load8_u (local.get $input_offset))) + (local.set $internal_transfer_tag + (i32.load16_u (local.get $input_offset))) + (local.set $payload_size + (call $internal_payload_size (local.get $size))) + + (if + (i32.eq (local.get $message_tag) (local.get $external)) + (then + (call $write_output + (i32.add (local.get $input_offset) (i32.const 1)) ;;Remove the header + (i32.sub (local.get $size) (i32.const 1))) ;;Size without the header + (drop)) + (else + (if + (i32.eq (local.get $internal_transfer_tag) (local.get $internal)) + (then + (call $write_output ;;See comment for the internal message representation + (i32.add (local.get $input_offset) (i32.const 7)) + (local.get $payload_size)) + (drop)) + ) + ) + ) + ) + + (func (export "kernel_run") + (local $size i32) + (local.set $size (call $read_input + (i32.const 220) ;; info_addr + (i32.const 260) ;; dst + (i32.const 3600))) ;; max_bytes + + (call $write_message (i32.const 260) + (local.get $size)) + (call $set_reboot_flag (i32.const 260)) + ) +) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_bad_fingerprint.wasm b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_bad_fingerprint.wasm new file mode 100644 index 0000000000000000000000000000000000000000..fba1f191b6ed6a5ddb68d628afa7d2ff06255a6f GIT binary patch literal 9863 zcmZQbRLEsyU|?YM;z?ktuV<_WkqimU^~RN%ErjR%ErRZz`@DH4x*SjSXfwC*%`UG7+6>tI2ajO7#SHExfz)l z7#JBDnHd=wSeRHDnYb7jI5;>MxEYw3SXdbg7-eNynHd=b*(90k866uM4lr=nGdND^ zfzS&;G`leiTW)G@eo-Y819x_6QC@0Jd|qlr2?GOHe0)k`Nn(6zUJ5fKcYJ(CYGOfr zQetr`GZUv0BZDI&w+y2VCl@!5ppdYDvbcM%H@e zhK7a)21kKxB?c8RQ(y{6fXRW$!I43O=|S^>1_oXRM+V1wGYAJJ^8_TL#OTV)puniX z#Nf!7rN{)*@dhNW$P8k>05e&57`Yu;99aaKKn8@-KlEU3E_7#sz%AYS0- zcHGi%0OTtL21kx8$0K0Q5)dhH2;>L`h=Vpl*h~!E!iLSkRS`v7X5Rs+L)S38Ges1r(kv3JeO&3XBSj3e4Wp0!KmWrJyPqKw$$lLV<;w ziGjNuY!H)!0+SIz@ zkt2fwrvj%g1A`-Dp|m0+HPatO2N#9V6z-+3PJt_u~`(kxD{9xxEz@a!FoYr3`(3} zE(4Q;0;eNWA;&?B}T{pjNZJUOa@Kspx9z6 z$#P`L0wq?*1}0BwB?b*91~VoePznQOBuAbs1!hob@&;Uv^n!Aw638}Yu&@HF0+YZ* zkf0-jBBKJc1``9w0#IrL^LQYciqVXT2c%Si8Jl^EjNn|R!Ng<6!~lvvW(7=FI9>rc z0744Dox$Xwzyitxj0#Nf0)Rz23gF6v$rY6H6__E>!{o@E<;YY9iX>)eB!L|T zilB-tB_;(XL~>(M0L2feSaO8K9XQGqnZfCR#gQjVU@|B^z~+Nex?@e25-Ui1O`#GS zD0Q=e$}4to83fV;N+ci=4sbYva+xA0C=%EdIYFsHfdiZ`I6yi%6gZ&yf(?`}z=>Fi z5u}gPm6s9X$eKb$MsWUAWan1kRA5wKcVvc_EDWFkV^v^;6eS7}e<{JZjNo#GQGrbX z7#fkS~&0aWaQ z%Qlc|Q1G#n8hl`vfr82rRD#0Y!>GWF6mrankYh%K9D@R=00Mc35zJCx05?&%6`#|8lf5aBJY#OTPP07|=#EsdZS z448yuF(pt=QD6nt4Y1;Y1)@rU(UC=<3zXKu2D4}|F@QoDRVk<>VuEVsP+$Q$p9iE7 zhi!^X2&)vBcp14J86l-A6Q~+t0i{?4MsU6Z*Lt8r4^(zBf$B+c%Z>p#Xjm8&7(s0X z22dceFff2=EpW?4fx(d_3zY4^r2(k8Qv$mll;ar%nnAwe=7uQ+c>PBq$h} z9R)xYup_8~0yT=vm_$HzG`MyU0Hp|KQ05Wf1{IQyjG*>ZmcT5KvzZ(~$sFuLP{jfA zBLgUTGi!iaQ3BA`CrAy8A`>_mAPomd(o$e{RDhPD{M-VYKn5~!Zv}Y{ixIhQD#F)UQD>3u3DlqagD=;ZC^RR%TiP4OS1*D!E6mL9i+zO!l3X)|6 zH@+cFbx=#3*_D@(hY3_KgIbe}0xckSC^7SbD=LsFu*w$PR%Zb<>_O(UfC?T^+Z*g7 z?%Rxr`dT4di3w2yID*@$*y04#0A|J&Crrq3!lb|giW4SqQDw#ijuR$moG>XcI)bW1 z0YsdDN*7SPG9i)>xWr~rV1UO7lLixuA~Q;yFoV3rge6XR7@WR6`myoT!}ZTuxp^6! zF0Pw#WM=cG?=AJ*-+U?MM5ALEVfyyi;=4=HUV&8M*(t?d32B>(B zL`k@ekbqTS5ZDh=;P?b=>_QM5RB{P`{U)#o%m?LLCQxIS5flQT#w0lBFbd2ENi%S7 zWMX2eXRL$9fdM>Mfa;`iG$U7&P>uz~I;dauO)zKx{@kOX)LL4#=mhz%OkVgrp{F*q_>L8Q4sO-D0`G)SKUyCZ`K zsH@<}1nN+-DzI2FNGPy^8rUMBex4bV04SsV0B1CI$9f;|2nEP;C3Z6=urOqxtpQ{q zxQPc+{|BUAkzIimG>ilq3xH%y1y%)CO=bpA24DyGk3l^R5ooRj=>r?6$PRKPyJLM8 z)CL7MM{swSg_n_=0aQvTFbb>&C3^;LLqYIUW$Q% zJA#o3G}Z%ds4+tdNpRMH6yXfn3QV9P95jf*B!EQ2Fi1 zz%2wVvl#{Ef$ef+;4VS94$*8-fK~L+vOyqA0VOGeQ$MH~2T$D!jNqgU@(Bwf?{j29 z^1dP{%fOmi3XHJvybT~nFu-`ND7?)Oo*#YN|1VXmG)trN|1a?3CC*T}VZC1x7^aQzQ0s!N1jGcldU#5TKx}45`@$jx4#)qDg^og?@yrhlg+-1H z4M!N{&Vt42}*Sps3&g2RJjx?Mw>H(x3rX&^Rx2EE81k;f@D>ZUqKM z9&kg273>fuM*)y`7!{ZV4ufI}<|ZbvgTTFSCP(H%MRus_`YcCge~6p{BV_oO3DnVM zb7TNHRFN4Jx!@Re++Xhn8t-BRI~~elLgp~TIf@(#pn^b=S%D2SJOGIWc2`~oRMWu9 z7_&g30*WklP-KAz*EoE^PGVMIRp7{0Vpn7XxfWC^Dlq6WC@66#a5yr%NjowZ@-Z_p zFfxHsBAWs`#QE%wjAdXG8M8nvHqg)$*bY!G1PvargE9n*BDe`Gp~%4G!0e#F46+~8 zvr%AB;80)(m9LPoR##pIZbwFbP+yl>fdiV{7(r#Q0ux9bEJJ`Z4l}a@lY;`A0yC)b z&8EQS$&auc(^#;j5Jh++n3+2SrBs2nP?Mf1)G%WbP+$g?DxkI_qZyM7 zqzNej8o76r0F|i5p)oT)v;$8$)u7V6@a@+$kpGScSW)-OD zHeOI~iCY2G>40|MK`jo}5>R?_tj_|u#l8^KOkjb!)R6(rO_1)t1{2gx3?TO*yNMap zV_;Qa%TfZRSX~ANaKM3ko|;SyP70l%z+-Tf0Oxv6kSzj=T#gKipj-gX)}R(YB*gfb z85x)uxj_SEC5k+b42tXuTnao{N<5&U${C=jbLVAL-~kuy42qnfRL%~vofFiIW>#Pa zMLuW}4V-Nt@d7JvU`De$GM6ZFDsU-qW+`!^7z>&~0c!*q%MCJ?9g-%wLDe4@C>Js~ zGM8k5x=WyL5l0qChy@n>pk63A+&L8392K&Z*xW(IgCm0?XyOml8}|fF9D)Zn6hMIh z8eL*80gu*8D}km{KvB+u7PzjEVJlG61KyZcVBqFqaBAGKYVz05Pv3}egJN8RNdl74 z9r+X(9c4g4jYu`1Mkb`E2X?T)c2Gcavx6He98j7EOzScTz&oB`9V{SIKv{r+fqOC| zA_pE|fHzA)(=ni?7AvHwh0<_TV0F~Vas&<0DzG}*WI2LcQ=ry1s}qwslZ*nZ;{`}Y zl~7=H1dlkGF`0mxh>iwXW=tAjmOz#nlLeRs>Ma>4usTX)DX_p=9E&*^IqN|&t-t^p zcdsc_Vp3qpR$^8FHy4>5SwL-CMg`_ND4Dj9izbD zSYHgUW*8M1AVbcep;yp2up(H5*#Xqh09A_MnuW;`shR-|iz3M&RWqP=8cUWUlL7~* zn&AK?5Cu?{M>P%HoMQwj1GRvaz|{CCqap)rZ7v132Kibn*uAO!NjJ( zq{F}nuKd7)OrTa2Sda-S2paKa0#!L|3XECcNlj4ykJ*(MG;?|YH2imf(NkIp5>N^( zpb1dOgeQyRAI3r@F3=<`sQV5L7d8ckEYJ+8B9j7}BB;WIR`5!Uj`hWk>}3j!j%;N` zj*U$%9EIQ}Bd8d{E(aY&#ikFJCZ?>cEKo>+a=j9R0y{Xw22H(zifZOUB~bi= z=QbcsRnQC-q!q#h8c1Pu{PX|+fA&H}M$r5-vjeQmQDTRBg&j)}V3&gg0aiIs5MYx) z4gyeF07_bnpri#$+$@fuzE@3_A|uFYxQzh~ggCN*0su7m4VoF`22~vR0*{{?G%W>c z{P1&w=Q0!_O=^$<@P-;Bh(NO;phgq+q!P0Nt0&lCRs|*nmTV<<&}|fI*2(fu#gIT?A?!C^9OrIIHzu+d<8%EJapOds2ZBTycXM4~(G31FBCMxcR_KL=>0=j({rRt&&sMaue>O+KtnS@AwN$cQ6a%EKQA>wp)4_{G&LtP zsVEWT@RAg;;|mh=GLy42^U^^cIL;uzAj81G;KszjAkVP`82j{9xaMLIC0yK?Vi}Av86ha1nuuf%Jf|C<6n77y|=?I0FL%%yEf1Ir+(8 z=M^QE$Csrh>lGCzCl(|oXO>hdxurRC(8GcYhTFbXh$>`7sSxSNfMfdLeTPT=tN jEiG{^D#|ZnV30-%H<16V6c`xRFbaT0&oBxwfZ_rGXd!i+ literal 0 HcmV?d00001 diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_random.wasm b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_random.wasm new file mode 100644 index 000000000000..a817ec8df9ad --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/no_parse_random.wasm @@ -0,0 +1 @@ +2@Cϯ(haSPi9 g&4 \ No newline at end of file diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/tx-kernel.wasm b/src/proto_020_PsParisC/lib_protocol/test/integration/wasm_kernel/tx-kernel.wasm new file mode 100644 index 0000000000000000000000000000000000000000..c67d6bbf46747fc97bb6e61658835c100d17bf98 GIT binary patch literal 382363 zcmZQbEY4+QU|?W;!6=`=Twh<$kib~akib-5&sYy48Nh;!^$D!?Ai!9kz=BLeRMsUh zfV45zCvboyL6`xmt`4HH4#KZvfN<*>5*Qfk6Bz42L_K3&0vkwA9oXVJ1_%%A0JpgiK!!3sW#Ser&P^;Ti7(2} z$tf*}PtGq&>M0S92^X+Ow3FS3`|T+>`Y9IjEs!z3{0F%APEL$b|xk!P@-gDXJ_JqC}QMhU3ut8JSp6H83(Vv9q%?pbLW>$-uzQ45lIW zgN$L|<>g~%;Aa546l4v^dE(T^XMlN8JYLBYhp0HPR~m>BsPK_cwTjN+gOVdr9ogfA%c*g;{)d6w-{NO85soGB$?|O9UB@B zFmTs1I9{1}2uwc!(dIAR@t|xQpPHA#%*Y)d zpOKna5TBG-oXX6^IgOc-!I6>sCgVIdMW-2zFBoM~v{y22WYoRR_=@ow<7T!;Y{wa= zFt26&$ZT#jk?|ID=48fAj4N2yGj3p9$9R{`C4M>MYQ`0eY10^kS1|_MV#`>=IGfS= z2IEV{?4wLgj0Wi~jK#_NiBlQdm<};o_A&M|PGHorddN13F?AN>JjSJr%NTnZ=Q2KF zd&1Pfw2`@k@c`py#-PB1jE5OdFrH*=VDx^#e24iY(@e&!BaBlRlb$n9XPnQNkYD(W z@jc@~rejRUnNBg?X1d38n&|=4eWuCGjm*=Tr!t>rUdDWsc@6VU=1t7!nU6CcV?M;Z zmiY+tVditp2bp&UWSPn`fn_pF7t3mv z%`973wz3>zIn1(`Wev-ImisJ6S^ltIVmZR{faMPBb=LQ+Cs=>8{$u^idYbhvYa`o# z)*GxhS`5z#uTEt)YQ|fm?wYWC1(aZZ=*9kUo&LtP1RoOeI;4 zJ&ai(AFwzwD6%WCIo4-EY-Mw-%TnZEa!_D$WG__Wbme7W2C?h26qyuQG?;oA6`<8MwI>I2_qM!Aih#AbDI^kwt;Yu_8-}39OGnf!U0SLxDko)r^TnfkA=IjEO;k zQGp#K$f&>q5@d8_Fk@oie#g(sRS#;oFxD~ED>pPWG%z>{WGgYNfSI5`=TKw;Q4ET# zAirYAAO$Q+Y@k3>Vszy8Fgn&3XDP8*Gj=g5usHJg^D--d1R1lGxU&^l+<93P*c@51 zlt5xUIax|PnoKN;yb3&^aOY9rbY#g=;8NgrCO@O2y%^-0-FLO*hEeRHU$o8 zB|b-%EJa2p2L*OV#w;Zc1wODRSiE^b0mcE=&8WZ*rdbr&vmJSI1YUy;;symMNL-0g zfk~5z!5kFCjvQGEOc4Kqf}Br*#gQ=!Y#kdYeKPVgIx;A7@Njd3ovz5qy zvXK*N6DQckSqh8_EGRZY#g#bWHgclb2#az^STZ>BWPzfaL4g6J4x9|w6d2)dQse_U zg;kNmkwKA#*+GFvkx7A9kzavRkz0XHkyC+DkxhXE64V@^TT@Pfn=CoHxZ zVX>{j#Gwd{Y5{0eLt<1>5R?UxqMVJ0C})R7IV(8IIl$qDKgwA_kpd1tj3|f1EyyQa zAO-%soC<;pjM++z3S92ITne0^Y^%VgzzWO43XG0SB~Viw89>Q|*+GF5EDFowO01yt z)WN90s=x_~az+Ife_lof5M=SpQesqK@dal|P;wKHR$@g-ZY+?3Mu`g)`QSvJ1B!G= za^pfvZd@RD3nHaDesd-k1x5uXkhQEJr-K{_Du1$+1QfU&nX;6aKt&~^f&j=rpu_~G z!R9iRASGiKusAo^90fs8as{PJ1(0qg2L+INC2mK?EJx--NGS#@2o4BtM`lp@z~ac9rO4=5r@)o1$gaSu0Ct1p z48|;QLS%6)0hJj_ObU#SwOL?unIPt}I99-A>d<6r;4<~7GN8Q21dS)SIRaUVEDG#k zhbnar$8k%W0oSM=;wrFTowgJP^wd6Q2<8@ z3nWt5z>&fNsux%kpve-hkQ0>fxDe%u0;*n6%2NOvpu~~|%Df;Gm`buh5sQdBm>@Xr z*c8~IamT8_>ByAj&&$9BPOjNXptJ*zK2Qk&s-r;B2g>!}s*_!T6&%d$kjjDu;!{>o znqyU90#!+ns)Y*@eXOA9V{xog;LHY9nvP5*3T#>6=;H)s5oq**q7@o_tPpcKq0tAD zfkq!(1`>TB8EEvuWI)l!3Qb-xF-L(cMNS1K1&~8QA;b)cJ_ZF2Q0>NmRQ@r7(lxyN z|u0d5$FV!;tbphERNicEub1+U=~EgaS4d$sNr}9M8oQP$30D;R)DGF7Z8mQ zCBrBME=L~6DPY6#S_!Ye9id*3$%2$I42}|6Ab*02b%87eUQpEoF6wzuyvnV>pulIw zq@cj;D3ArI(7C@dGP2i$ie*qbX9iW3tV|BzHV8|WBC`S$xP)YLjielk}OcM@5qy-$n03Jz^cHdz@oqj!k*FsuRtNI z1Qy9w;F4D2bYyS`75*L|CZiiK1GfUF9(d@0s$)-NnYOz^cHkz@)$^&V*<4gSwM!fz+(;+*W4c&8JS_t zF$H*Y4AdA_02S*BjG!Wv!I1@A;ITL|mVg=|pt`_YT8YsSR2s2>S^xk4|Ib{g!06`4 zRH6tfOqog`?KlM%P=lA*Q6kF`Y&A2u05)S1QD9bJ&|qRPV-f%rTg;$*B)|=75i2l( z(~&?QsEx?v016-mh#BDKof3m9B>Y$u7~pve+~8wU067#C01OHYkb;rfQ30AD`MCwU zK#7Ba`!*?ZoGBMXP z))DJHMo^5hfJ!$7CU0paCPz@~9u%XjYn@Io)G4t!DReA%bz}y`Dcf>I7EsCtB|HYO zFC00t963PgiCKZs@dQH-o>&Fh0V*9xk5xuUtg?da0jF+|-I%fZiFzLAf%_YrmeKu< zNXek8cp&}!g^`H`C9;_yg)b=kf;t(@sM!}9*~|(o3e4WpO3aQd3e1ks$i9GxY^D-L zW(8DFGr_YjC~IGU#55Cf{$+yZUnY>@3QUdyS@4)<(qIDTUubs)l7E>rK>bB{{snOr zvBWeJmi+sXk&y+d$inYuXpzONzzFs;&LRtxf>DbsWIu!2jG&0d;bn07OqQ3KA&DDQ z6f1!H(hLgNy!?rJ5iNq8xberc2slII@H1%ef~L`Y8?|O4F`BUy(;(M^N-S_-GeL@J z9G(Le(;(%fr(q%^l!`g`3<){+%)sW{@6=1isFf3DI)>E9;K~V9WI-z@9MMhlv`oeP zi&8mZ`Wsd`fjrGKp!t`Ik^KUZ#F?>GPH2(+VqjBwEVu^%t{jyZbs0Du`3fD`+(E;9 zjsoCjG^j5C>Yal)py6Z0;4q^GlLV+m$>=DNB`_P*{^bUn<0yj|LT2FZWM*W;tN_8o zfeMTQzd)S?P&*A7D==v=@hCBa`W_4*HV3pR#|-WOfyc3#9T}k=307BLHqf}XKo)4Y zM1dJHE~Uh(z$|bH)Px2ZAi&G)$O9i%WpU+Y1NTtCmV@M3l)xPwuw@L2Yzm+ONk&C> z9wvA*95mDcwUFJFmz7(A9W-JJu?sYw4r<49D6oJi76lear=G!4B+IF>p`k$l(i0Vc z4?6N>!TMwzFcxSS2h{Ch<^lKhm_Y%{3K~s^hPMKP6N5Pu3#bDK>KHMD8koqHFIXwG z^A7ealnr(`l-zy& zEXh(}7TD6*(7>R;qRU{w3mTh~0F5IXWI6JHw1Hg3qQIibWMa-NpuhqipaC^CCN_ih zfCfPs6<8El;9?+qL2&^Z=4TP;04Wpr4@whCY|CAF8Jrju*_}W`!;IVt;MTn(bBW`E z_5%$JS(?lYiX2W1itM1SF^2-16KH6@pt(hXy+z;v$OKRbvS=_#C^CW!7g1yeQ38sr zJS?EDDl4czq`@Sj#K_A4>YuV`FbROe3Ox4#>R&TBGFdUOfVz8N-x>-W0-0*g#KP^! zsK^KrhfE}ZhLgedGqd?K)DMX3rY-*OIkp)E?Yry0h%|_Wl-Q{P+$TLfUAIl zo(bGCgGGvjBLip@1JvqO0Ck5Q1wiBR3R#XU0^dOSR*41FbAok&m-8|>f#!Qy9a-FY z89^ydfytCf0qhvioRDLwJ2)dUJ28O8z=pF590moCA`2)wm_Pvwo;zX!1uLr~BP>gkp(<{pv#~Li6li9 zPy{l8GMNITqye{&AgPcElnTLN1y6-e;1WiG5!4aa0F6FCLXSnD3!EVTfqVu@kPtgT zy#fXW2Dq0&Wr&C(1GfUWw-5F+1I*8$gu;a6GEiA%08I`GEZlQA!3ly5(K9;02u~3T zpg{siegw^{nK7k+f(e2ZkWvU}luL;fH2lM+z~uOYA^j&}b5a8Pfz14c2MK)B#~XVaPILn!%{R ze#TIk^>>K(lXK zKz4ANF>PQ};8fsHV22c|QV_`Cc03QUeG7(uRS0Z%J} z3LkI|s4-_=0Mc~>tZM;dmH<5FW00H|p~$Jg4o=`)$R$0(iCnI{?A!`m3Y;(}frnPv z&6pZM4rVt41tVza5fp?Mz;=Ox1#VY>BD(^U;|Wv=Xh?x31ei3Kd{Bx!7H}CR5CWQq zT@D)bQ(yuW9gw`w1}c7)*b!cF0B327ECrYtBWU1FgUJTFnJfw{%XvWqCI$!{Od3oE zAU`>3z{MO(6`4Ujas^IMZ0cY)iveU7r1J;2ok@d90qi0PxLF_*WWa#{E^kl*M*wUu zXdn`lUZK7M`G6f_Gmk(oD5eDkeD=(`8xRg?22G_sLu*?Utq(+GyT&`#^Re&Ze zA%zX3B4yHG0?RUh)FH`oJ25Jm;sbZ zVHuoTfyJqzu33>ATn1?}SAZsVG?*F~!Sk4)@?41>T%s#5K$=vb))lCEG82^R6hLy| zflm!49&k)&DKUT&6=^ZUtBs&CIR9 z3{J7^;56>|05gaaz>bELpYUvp?(!G{F2`CVf`S&UNCbtF57@#34DetA2|6f(sxu3? z7~Hcg3Tz;G8-X4YJq*nvHINFN2~=LdD{4@vfbs)-3n)8+t3OEVSb>=zly7<%vp@|f zP_cIdQgwprMkhvaa&_!zJ1e!8) zWCRrj3g8|#6TD%>3Y{qfEf4|~I0CImi5%Psf=uTyIViA!q6gGjWl&^sWKv`VbveNE zR^X`z7Ldu{G7DB!f$}@E1``ixF&C&6%&x!;>aj|I8V;ZlV`fk~8q$h$>lCeU(3TlS2f&v&c6#&x*QVp6T22F56>Kz6Ja3#ZnQuwlh5~d@A z0_$>Va4Q2oF`&T0y&1*Li0&VF9zu!PiNTy1lw~=xlvto_Fa=IKpz1|JpdTqgKwT)2 z1*#~RHJPEhB|vk03M??b0uz`e0U5vt1&%;7$PiFJ6_h9#6hJPv1CK9&QxUl13Mx(@ zQOCWLi4mTj5l#lV353Co1U_a4Mo{Wta+Jw}%r1g63y%Vm;|x%b9kj}h$*~#K=rLnb z0e5XUvdoxt6d-+7GbRZzOD797HxKeCN0z_|P=Zoq0Jp3#jh%onwguT(7GjMBFNnl& z?Ta>WQO=>jXc-`j z0yuGi`Jh23#A-Z7(BKYey@DANcnK!NTqejYI>=lm1r~uRAX}k{AKYpNnG0HX!wzcB zF@a^kO;ipAHbqeN%nDg}0-8mICZUT=j9f&811LmzKr1HLKrGO*IR*_T0YwgG2L+I= zELlq6C1s$tr6QLCn*#ec5Pw-kpP+<*T9{^e( z2?~BlV1R~ZK;g*=T2>2-Cng0>nkn)3D z<_rpq0{cO^nR`1UB9{ulTNt2FWB^sJ3XG0lK^2uFx4>yo#sU{K3JhjUpgh_DO7)JQ z<{3|xV+V*MumYqA)C~uXYe7`a07-!7-FdPc=YTlKswA=?s@8xcU}kLrap0;1c7O~8 zxdu_9GjJn3vI3OQxZg5iRH4wJO3*@P1r|_4j6;FNiP4-H+SrGMG#hBx4-}A!ObTp{ z7Z`FBS(!nrNkKhO1r~u$(100uAW(^o7gX?EU;r&LW_8?9p9NYc%?*;{P-F!~xd3QH znOR^fC}=^#0!pAx3OA^aA_7|H1`=a|Ed2weMQ{xW9zEn%U{PQVsFB`}p@G?r!3^yp1fENcVae#V_OxYk=4kcF5nnlpU8diY` zpdeBJ$tptD9Wf{{f!0T|!p2QF6qpoPq1{DrcrYrk!I}Wv3Xnx$AP>T7airki0dg4< ze4+~Htpo-9WeM-EVm=8?_xe8bsVw$4@h=XpR0Z0&HA82hMgvFr2q@w^@!Ui#l`yiXZbk3hQy=a~^T6lOaT z6c(Vo&A`XXz{teR!T@SY$)L9;C-lPGXI-EI1=gA*y4eRB_rq*WKInlP+l_22(T!AQ ztghXIFt!KTSfX9a1T_{idhZB{Y*1qv)D;ES+%Ox^8qL^Sw>P@s-t0wo53$|^xds-u z3Jl!ewAeZ78S6mv7ohPCcqiciOSTdNq~#~j0;)t57(j#djuSS3=B?&}YzDN2#jfR+S<*p3}6S+GJ~gQr}1CS)R%L+~cjs~FaESMjlzyL}f zkl8H;#~zj}M{s)xT$X{Rw!p5M(gF4X$W<_Dkk6p@vJ{yyfjp-G4i0#HT>#B-b%3HA zOMI3MM5MQ2Zgq8+fiB6wuJp7F5m(fP8U*Axq#7w9*AlRDrrNAiW|2M?qBu zB<;gUkOVXjtY89p7i5p)9ca1+rE!q3K$a4#0)yid_=FeO3yz@rU4g;z10%Q$2jv@Z zk{8HQ0yRT^AcPed9Irr)1VxPkgX0URBq%@}FM!QeWLIEtJOLJ0^&SY53l!~)p!fpKKZ5*zgBk369t8%+1x#=UDKI$Bfbzh3VhR(ua^zKDaGU^P z@+mMlc7T;A@+&Ynwm?Kd!%+cSX-ENFjdCe43p@nHEHo}bX@3JGl)za6RA7N}JxCw46$V2 zKp8-*{XofBf!PdH#xT0_f|oKgLsplAN(iuGM;34?2`;TbTEH>bzyeBn4J=s#yTLAD zcI3%YVg~med6>9C`!jj6K;0V#&`{q7P#CRX%o6AUspSFH_F%UOWGS(LCT2k)wgM91 z9FT?)h$oT-3bhH0pvfr)P?7<0Dt{nSqN7G#Cet5|$!?%^oBvXL~BthGQKz#^iS6&WK{}R+-gPOs^0m{RWvIZ2f6F_}z1qR16 zkdUf?#QFgc51jXqqTvKw5Glg0fCUi|29DZ0a6w3ffdoMbZVQtFg93*+xViyFAgGLT zd;u;Fp>YRaX2bxhtaHqnUx0EMxO4>-c>>EpfdmOaQ2z)VM4)EE22hbTg#{yWd%D0i z1vu|a0_jDq%At|F0aUGnBNvoJrhxPy)n%Z-0#{qGq7{^SL4x2~;10M10H9{$K*t36RK7~y>0p8U3pNLwI6&q=vH)Bh53{j(E{W%C1Hrn21sN;O$YG=;H5l>Cjr{#3pEAAR{%9eAbO!OD3PVa zt;x&)av&&gDR7uGgR?2fd60ArYD0i{JXuOynoJDf)(9lKfZHe_DM-(nQvuvhP!s_* zIv@@MZB+%wCbarr0NN)H9yw-EV7Fpe4XQ&$tQl5m5!JzojWCk?= z7!x%y{tT)+&f#y}P7MM%`>GBmI#u{d(M^D;4k*7kwTbrb=` z*#<@>W@%801J&o?0t2*A%TYi9A`03f3>nG+O<#hWW6%N{T%;XAF4sXuYcMTghSv!T zK-~anc@EaD!88RSI{{f1l0z0V1lv1+yCDKzMTC0jt$uI>M;H16Kgr?N$O>g#(JvCCo}NMGKgb6>%#t z7b!A3GAn|%azkIOnQRMWOaYv8pbe1~pk-i4xdo+_ zNlI>k)RB;Uv4WA01v1>z!6kcuT9(Ar6;PS6?*h|V>Pd`#?&;KOAYbQyLq!uK06zzhQCPh^9@ z69y+3U3uAfSiz}^G=01*U~LfVH!$)sF))HQE^9FDU<3_rvx3|W@dB8MY%>olc=Tlp zBQJ{rD`Kc+57@(?9zP3ss0G{@+5z%9Y^Vj)0s{5+z)esMrY&F%pkkK^tO48<*?_D8 zv|U@5VFRNhrzdE@UYB7DBY2pH3DaKChGU4m;0;13_A+rh&H#;$I%-2ICdVUS-V$(w zbqi?bje%Q%R{$~(0}2txI}G4D2t0L=EQ2(-SR5G~zku{OG9s_xP=c?MV^H7#E$xT23_%llpe%=NXz2|kM}X@UNVgVL zv%>3!1{O%&(7^(!8$hmWVZl{1$bhOiaMF@M@*+40z{|@a`WQ5rR6rXAKs)_eKu0Kn zhSR_S1nH=OracgSHPCWR(D4AEV>y&qK<8wD%+p}ffY=3EvJYW_j0Kqlt={4kbWL?lN-kVPg_N zEPYcz%u9pTp@7%6C@_JS+#Fy4ulRRjF=yrgElPl#u#~OD?D&Eq54=E-1GJVMyl4uX zU_p~VjtmMc0+T@HlLBa+4~URaV$KGgHv^g;5y=9dxda}@1fM?uT7$$Yuo9#JRN8?s zNRNOLXfdi1yCYAYBXfxo2Y8VdNP+{jP+5aXMv)7|lTZY&eh^XQ0r7YgdBH2lSrqw@ zSCDhSw;J(*R&j%^-~_EA&r;$CZJl5MZyx~*gDiC{$x;$<ztl)iL3e1o#L0|>o&;zkRXC%PXfWjCt zqr?bWi3DD>$n2;B$~%f6b7Vjk>43N(-JmUF5W5&16(FuP01Z=tf`^-10Td95jGz_E zLQaf|!l0010yUo*75Eew9bbUUG;IYQaD(9#Xz7O%3m+T!979GXZl?w&MIk2!MPVMW z3Bpbcib5dIvx71jp8_ayAo+>OL4g}2#_h;d0-CX9P~ZWD2sD#|me+w~K{2GrtiTC6 z(g(Ec2C^;&w4{~+ltvkl#%{pD1)lgT$x>p5mIu5bLwFr|av)ZK7n(q=0Piw^%#kPv zDX^?{QfO;Y5C$#B200QsWA=#^Pws&)7sHZ&U>je+c}8FrW`bt{If@mU;MtH8JZRej zWD*m4Dj9e$fCwZ9@F;RCu<|lGvMBN(r+GGbn&*M1d3MmLM_Ed|XlWi~FDT9Pfzmub zQkv&cWK>{BO7j8=P!U*~7X-x*C?O%GSnvoUqa$*f7XTgkCIAh8K9n>M+T+E7W&(IP z5|-vc3V1*Y!2L={TIGNaS;EphNR0?c4R}QXM2!GkjS47{D}vO>fYj)KxDYiGP&KG& z9uz#>+zOz8z@FwosS=jv!6(ZIK+?P*;WQ7fwRk|MgF%xV=;R|%g5-p!dC)m=&}IuL zmw*pI0mYCavjRI>ng=(@!3zbDx<-tkm0F;t3{skhW-C~l2cISdbpUFb7eq?)pcDj6 z^G%?|0-zN=jt>|>TL(ZZ4ip$2A27gHxPVHz2cYR1P%XBg9&}_DgCY|TBe&xN1_h>U zflHu~BPj(2N3;b7pm+cq23l6&$fyV!Zvq`b1DfUr34xnD;Q4LtQ*bvJAe^Adz+evQ zA}BCA8f1Z|#T`wu6c`;fvS2cfIv~CRg0BMNOCb0%Aie;CF9PCo!1zp#0a=Qm)9}Ea zF`$xPo*zjf~jISUwKm&-5j36bTC4K)H3#}L! z6~L=YKxbP(JN2Nx9+NHuqrexi7Em7yss-FQwqgL!aKjoZ-1nFeM{O8j>}>@vj#pxZ z6my^gj8Tyd2!*L8}x&^&1N;nJBP38e}Q4gVw|{gLYrBAd(R16d(l_ zM|ctfl{yM6pye5m#0Ogc2i`#oH4D@N051-O@IgB?71*=E$J8k>D6lIqAsmM8BG6t? zM3!P#01d@(fOq{uY9)SdaIipgB!c%rnK8*IFgY=sgH{4N&Y1unga_@_glgb{uMY-oZUD9O%$N+o>w|5w z%$NkgESW4&@PXQ@3W$}$;6)fjTYRRUY8Hc*X@D1OnSu6WfP4!cW&m%uR8e4Z{L=@w zY8I$22Dh5Qbu_ZiI6zV2h~yt|5;uWPTYwi-gA99sFbur$9%2}1JsH?`g2sXtalkhv zD+F$G3$CI;^P%uI}kK0*T{@^UK%D+Ue)W=GI&Byd`1RA3VL4YCCy2w8Fm zYIbQb#Xt_ng`C3`0jlUgxd~K6fg=OV5dqc8H^6&jHJKQcz&fbAvZzRJuDia_}KAJiyh9K=y*2a0H{Q3y_Lpq(C{z@z!l(1(O0ym<&3 z)d8mx@FbT2M3%UC1P$new?i_6rWXX1SkU7U5(SPTka0>_Jc3#^5NqJ=Pw?^saQq@g zC^Ukhy+d%b2b5gE5e)J#=r9S;G6oPERAYk{N`Ue(adV9wkCYS9X0fvRSx%>r4D3RwzJ>jbhuXH7!w5CBbd zDhVn;jRv3Zq9g=a@W8Af0Lk1S-z#J(F~Up$@g=g9gcYEMfcP3&N+JqS>p*;gEG1Eh zsZ3DQ!2So9Qy_V8UIs-cIK~`RK;;)mTm|GKgt!h&TnE+_0lUgU0hH{RLd=<_fcn)! z&}l6m1wm+v0ZB7M!a@YTVun$H1FBG1feXqKRe-ITVN&3Oih(sZFq(rmZ9tk&pkp$a zHJKeiE&~@%;7v*3vPULMK@_AB%u&fw5QcL=&1pEtBuhaA!T~Mf12qpJJ_jwX2hF^o zrV~(lc7(((B-$Xc%MFfQa1qB2cM2zj#gnDL4Q7D`CqVfFwEhCzAAs}>z?F zLSF}w9W=n%;R6FG!6|``s0FVn2DKbP)e}fu0FoUb$s6KPN02xNBs)L?0Fufe0l;I< zT%Z6d+dyd;ynhGG0WIf+WDd|liJ*W0*HS#7!8niykW_1cQamIjvp^CsmjXAq90l79 zE_gIRhfsjZL?&=u2RaglsYZbryzmdaTn(0bAVLzLB}cF+TZoWAmJ&NWwJ|I3m@@|; z&VGf|RsrD10u_+pC0^j{=ah7ovIYbqn6fhdp-J4VP6%@-gCD=-V}0M(x8 zZUwmr)T>lr7B~sc57clLDZ3P*ZFSHBY8B+>wTJ?f;|@^Zfx8)wb3u-S?NZbL?@a`4 z8{)|_W6}V%XhAz07&b&FEb-HJAihlGeXj<0%)KE z)bs=u*wA``5w!A($DG+ffe~7hg9}GwSq4zK4;qvM>xZZl055+BrDY9RD;=6BK>OuD z%W=TlbU~#$g9ej?66lm%&=>=w0wdBmGPubD**?Lb$c}t;K7%W0<_t9a&;w4}phLf* zo1H*2Q=rB%iz5U0G;bDA*9257fp!amnmp_ZZ0?{XG~jcdSsb~%c|i*{LAMkrfe#M{ zZ{Y%OqXboApfj?R*dYB5kZ#awIt4apS;qi6i5Yan5Trd%|Odfiv2E>=pUby4yMvxK%$2lk`Zl4B=Dmbn| z7QK#|P0>2+knTEc*RBGif+VFtr3PsD zr~xGA$cal!4@erO1)Po<9p8Yw=E#Ce%LkA&R13EPlfW*Jec)avtn^V};C{};h~-`m zNOFRapp?b{+my`g2q_Sm1WteoK}b`R0W@g`9-d;!QeYBT43Yu0M!`c{pi?pwn85>E zpc5CtH9x4zeE{;3qnN-3kZRBbF*CHV#%J^rkYa*Hp8y*z0X3Qhv{?5zNJs&n(MyRk zdJD)LM`5VZpxI{d%qu7w!Gm0oA|EUUvKAK9+^^Ze$5SD-Z$O0uw0#2$X#@>AaR8LB z7v#pXCT1Eo5-y&2nV01`V*H58T3b zhQSnqYHBkk2GAMrIijpGLoErG||Kn)()W(`pB2RiTxBq6X59NY|W=Yv)PF*^!_20WM@!J!P= zk^<7M08$UCA_RVbDnJF0J3%vMpmhV_rXOfQ8)!!uxb+8;0Uxxk18D+kfOgt}jBx}v z_&_C|qehk^xXBMXQ65yz89>GyG(gEz2fXG8)b;^4M?j4=aMu#NFOCBu1{xUvwbH=b zw7>%*;Dg6OJ03thNMe?NcmlUV|^jSzI$ z7U;N0Hqe|0qatWQ3rs1fQ3u(N04cM;)3G=#0OfV~u_s8|e$Rq32zLTXBM(}8fNKp< zd91+bxB*mFJMtika>zI&xVG2>l7p7x@M0V^@CPef6c`Cxa0XG;#s2E)24jI3N`+sMu0qQegAsWpF$*f-ar_QdEDcl42|DgWiA#YMw7Hc7l=oN^xC9=8w*G)E;m~D};AK$YfVN{m zClG*>8z?t$gLZPu@G>fJfVO+cC~zongR&j?STN8vLm=Y>9)XMkDP#ck3_bjx<^br%-oLV zifoRPrh)?lR5^ehB?57jfC9)Z3LKy&?_-#QWIziIA)W*+eBpLf1g*Db1>Ii*+6K=B zIyM1(=@=Kti4x%5_{@%qpjA#BAnO?wxWMPOf~QCXu7J{=0<&X0Xju)bqhgjKD@Yp$ zc!xJQq<9qBK%1bM6}bI*89@hmGVw5RJH7#x_KxCU2RhD~4r<1%0Y#Dkbj_3F8nBqM z;~uamv|RLRD)`C{P-|0(5j0x@Uibkz`3ZWy z2Y99cd~~D|OSS?y{eTX|XN1lffzOl#ZI=bDL}JN8oOuhHTLl+1;9efs9JFs4GzACV2>{;P0y<6+bi$FqUXUqF4sb!x&1j&lZlJQ*ktYjzei_uo z2i1w-xhhcK9yCA-FP}lDJAg`MPzZo>31|+JrAP^K-x)|k26SK+cpwr|@QQ%=;1L=K zAGBc_GBjllKGY9L>zTe*zjpf=%~>j==&oqCo92(BLL$(h=H=0}m*J zCmor=SGa+?f1p$d3Iuo$Qi1BC!6@IXTbA7F=Sai3v9T;2kj zK76&x zATee~Mqge=ZUxY~DbQ>b6R5ha%Mv&Sif;v2s$m09nu3a4(7JKh%52aX#UL^8MT0D$ zleOT<1Kd2=4r(4C(hSn52q=j_eJ=nz#TnE)1TTGph96{h2RtmL06HfbGW!GOYk>IR z<{TtR7=ZZjky{2w3lLuiHj>K#>S-&mIGP{?z=;pkk_TP(L`mWUrz%iG6guq=T2l>* zK5)t=CSBkO1w^`F1a-h62RVSd`0y4q`YH{OzZAe}3pDHmX$*nNXHaT_&slP}u`z=V z8H3-g0qT~Zrzj3kDUB~haez_}t0U;DCD7sraEjstiJ_z@M=mP{0|h2WrYun93o#RH zYF!p&O&6;!0|RJ}2V?~UC>=6_9BTm@)m2~tE$f67O_0q>Ea1sCO(qv5Hc-s7fW|1n zK4n`DD!U*H=@i)=85KeI4{|y(C~|=U43tp8Q}YT;j?AD0UYjNGADX~bK&=7rx>W@* zi(LU^2{c(lI}o5t62X&JsKuuS6OSTz3m}Ip_&9G3umN14G@y_LTT~Bfzk+i&sA&Tp zF$R|hpjd$vkdSRPpwtgaIFLAl)qgkG2m>*fixBkJ`n)q3P=Y86b10i1}XeN&V(dXP-PCf zgoC9>i5YAn$S0t{0IkM=+-(UC2v8>yEDtIkK_k=fvK@4Wu>zws=!_N6;l@k~jMAV| z7gAt@q7~7TBqbjp+U#4Aj@L&ldI6o?2O6{l-?*m%K5<=#~Xq)9&~ce5ogsPi2Z?bguxBZPG6QH~6zG0JPhQX&%8a0U_81k}L9^4GkP-%T{xBr5ioh>C z!&7B}yaS4H(9ypamVidxW`ahXKwBHY85KF1h=9suq%s_bv5>S1PWhnK@gTQ>vjq#H zfw>B)GDL|sMsQt7t&$5={5qmnhv3`*DjXnj4sA+-Dn)SC0m*>U1$Y(+!~s{0Jg}+} zlvzR92V6TI1rVUDIcKu7&HI@i5hT|3v3-c-@r02QuudF zLvNsL2Cl|HOK}yL!Po0DgQ_HOoPrmVL2D#Px&)QI5};)ypwk{e3lt%d1ll?UDIZam zQG#LxTLrCvD9b=48>saN>IH!6s`@N}H_(Dd0#p`*k`*ZRfsd^OaX>Ye1ZX}K!~rcq zgZGcYry$CJW(+{(68ORq@B#>s@sPR_;#hEsk^qe{!6*Mvk{~2gf~qL!K}Mic5W!ku z11F%c03R9-3RMMgdVz%~c)cN(5Cxb1ESgLbkYEC>nsJ1=9Bek~I3});1K+U#u5wtI z93X`(qarivA>)t>w?F|4wiJ;Lv3kt09^5Ab?SKGv??Lqz$Z}8`K(wL$u^>*S1SKly zoDXQJy#^EXWIONzM(}5RTrS(05SRxq(!hIPn9P_sKz;$u5jnCHDT2nbAXjdJ7G8iHuK|t)R?q-GGpKD3Isy{3 ziIx$3bT}xvGdR|RTVx6hpj*R1@da9J01^ZrYTN@_-pdTSq7}RpUx5{NYd90G+rnYu z;AO!TSxO9`CFBslh=7Va(BL5>=*&S5(CwR`2D>()C!^e5RElX~YSTYl=aDxhI&{5CO9IwC*O1bO`Y~ZVmVfSc*M;Jj;f88g&g7u%6y>1AHi4ILvM6u5;y~@q@_TEQH-FrKPa_;>UVf=4|E+1WOzn_k)In9 zp3sq*IiPbHp$l7(7LJ3`GGyEjJQ@t@k1H@bz5oq%IdZ@UYnefLA2M0)_yHsb9jpcA zd(hnBX^@yB7gqH*Kypy^IA;M7r-sf3jjD0iqD%@RjaP%WX@k-c=-L-XfwQ0n9{A)? za48Q;%Al}>PjsFEjV2200jUCwb3sxtq99=s*b9;Zje#S!xgoEiy$1?#ZfEdrLk7^P z=n9MiCqY_3EolWtfm0B+0_fn@#~?Q7WJ3i;fd@$J`ye*bi2Pr$51Vkr2dI<*FFc2r z)SzXHwDG45#9!cZ=)ubpK&2X^zYxS#vjU4bvj(Km3~G-++F6jwUV#v44W96x5tdp!~s)NtVTwq2F z`+~L*g0d?ssL0(iF*s6_!jF#ZHXjv|Kwo1;jUBIxpUZcxz< z+WzEN0y-iGG$;(Zc}9WLu{29yKPb{cyK62y{pUq&ngT-&Dh`z@xwm+hxJ4$OD=d;Q`G|vw&uL zK%H}5D+V0}76o2Mfifj-YeqdVo1@H%K^M}sdc&jy-bKg)b})+u(+egAUIoyW5drWK zjvyCSfII}cbq3UR1}g;3u7K1)TKb?U1KrHVtN}Xgj1zS1o+4;S=mis~PYb%^<1Q!+ zq!c(DchqMoaeymp7SP#C0(U?XkTaJB6j+=%Knnsv^&TjOctK|zE3krwq_aThaDuPC zQvi7YG>r`ANr2*oM}Y-&%o}L07>K!p3DgS!4Lmt+Va!tGQ-HXbGfR=nkwK9kbYimt z8_12I49cdW_0<`Fm%~26WP#{Z5P=U=+5=D?BOG!w9%~238 zsKDmP3E@B^wE=V$h5#tMxj+ZjX@Itlae<-*yw;Y1L4gZ2H!BG0uYftAkqbCSAxi;# z(hOJzGd)TX;c9mqY7Mz1pk7G7u>)9!lWn+N=F}< zASwP0lOp)SE*4OuSP7iwr9tv7jEdj}6v#A3Mu-|jisuC1n8m38I%EJkL&d8o3`+6B zW=tnQ!NF<9bO1#2S}_~})1X8zV$FCA!U3iFqaY>==p+v_rWK%J2}U!fKTHas)4rMB zFe$J&-dGRbO7jB5hHih^1G*=g#c>DdV3{AF87vmZ6(IHwkp3OuH2#7KdSw|T5I_si zMHN^aK}nG#OGymc?+53R9ZcYJ#lT4xqFP`QsN_-*gC=8+EG2Pd4HKBmnRkGk1IbQ1 zm|z!`vFI|qU;>pXps@SGq$FX+bOY=?4W z1tw4;tPnT{>4<|IrX&a&wg&gGw=gP6f%NZTRN{3!!;quInWYGh@EwebG77xBEDBPJ zygaI>|g{HQeb8aBhpDZV%!P>P8uD{6*&|HK-1)k zf(io56@?uc6?q*Q6geGv6nS`rK!>U`A7E6%p%OIi2QH6KFe*xbbn*y-da^Gd2R5=e z{sEs42`%Crzc7I(NtiPfSo9fQGJ#zDnhAWo8fahva+(~d>;jkcZ4FNJ(7AsF1x`muJ*%j|2|X%WNr4kONYAgp37z9qR^WsV%&CBG z8~~fgrU1HY0OWKb1y0D6AZSz$J<}_Ij;REf@F1nC3Y?%B2oO_EffH0(f|%+GETEkU z6F}L9-HfRRM9Y~mb%1DjGo}_0EojEn0HPHj*-t^yj0v2zl+2jEfU+3B8Pf+4t!xI) zmI^9npo$5cqoA3l4U*I}n07GnGAi&Wa6kw9ctC|9X!;+{7svvyD}eJQKz#7ZCupo{ zFr8pBW10c7k42OD0O){EM1GsVlqJv#v+E0!B0E|R0qJ5lV>$rxjet2bxKIG)D|o&D z6&#@4F@Z@*K;R6-B$NyS>N$eSAjb>S!DSC9AV5d=fXkyZGr(ft@(81>(O}xcqzJxN zUDcx?Ru;>cg{Mrn2hZrJ`#DA+ff2k6@d#T&>RHhx)+Fy zK$a3ew0Hs^LIrB$i7JSLstr&z2=N}MT!S0-L}qP$BNh%L1y9*vyzZKkTWf)_}l?H6K3FY2&l$jH)C1=%^@?GA;|?)$0)FXPDwRm z+5)OdiKvRtfXrZVJOQeHLD@us#c>OWeFCH(J$r~MV6S+0FoT+xW$J z?qJ4S?SgJ%X3=2!!la~O#WyeH9RU?G0?QRO!RKIzV%BjiptCMPB`q7My3=%IRpj9THH1JdY6Wi4 zWxk+`xIlM$DuA0Rh-;N!Fo7#`U51xTkh>?91e`cJ6t%b&w4DA!0YkHrHt5O%0niPO zEz1=(6||frI+iO6Drkf2SPpQt%FnH!JIZFXrI)aK2SosK=+hYM;#|SFa$*zmRO$%_~ zKq?S~g=bNVV>eK1igN2f-7wN3nT5DWW&)St)M=TpgCYx5I_zOq;snpnYcTC#R^WtH z7vR|n1%3r31r=$K0tN+T1%3q;X@m+;Q78x+@lyaDssovJ=2j4LRzgi+ z%5nsqT*wJN&k#{Cg92s)xTOZMi3N1tJ*rdHKu%RxP=k4pTS3T`7c_t%1QX!_onfuO zBmmy&q9m|f2|SMK$N@QFlLb`ULfrvsbs$*|O0pVEYru5|11L;aAk`UQuW2yNLCDU) zlwH6CsWF#;J4`c}Kns*W6XGDl<}fL6gXZ=@cXq%}7h=(1+Q0;N%^D^o*C?<#3Y018 zC}@GRHpqk)gvtgKm8{?vDXRjgO`4_1tH253D@cQ;#TBF#c|oUkvnX&|F}wifUjZkJ z4jYE|5T-_lEyG&~lcU3q;U$yfe^BeiQ4`WUb38K_G@-Bp)Ovv}lms{2p@Y8){3zuH zsKL$+KJZreCw>0DcNfr&JIZO(i3f$7*L!ls108+UD;ifg{ZfZfu zH6Y7@`y~tttl5rd7;-_~UC;;ysG)L(AxDuL)FDvd%o6wlZYps@;zNlO6d$1VsJu)L z3NoN%ECcCAftXUD<~k(vDX=R_fOai_C^l{dX$9VFB~Xk)?BN8d<_2j5k6H0TEkQ&* zxFZ4@n?bb&JUk?&zzd&vfu!~?;652R&_5vc$-oi!06es%%kYE|G!CT8@RU(eR)IyI z@fo9{E-2t$Fe++7Ou51cPs0~LjX~JN0Yvr)LiPZm7Xp=w-baf>Q=!$4?$bV@}z|&;X0X38~m^2hYXJVn`Ar@VRN=05rX0RJU z^&50JjRDl^g&wxRlcm4|Y8Epna9J~QDKIGTS}}kwTj0n7g$8I%5qKz=9kL!2e99Pj zAkvkWQ-K%cQ&7*FQ-Mu^*AePuP@$lyC=3a}FN_c`v1l-TU_{E6pkxjzlOHf5aZ{S@&0x&$~vKxvH!d`b~$l^(2>18stWN5BQwf|_7X3T+A; zYn?Pe=eMnG0S(TBmL~{wL7Fa(9MAv;xt0gyLMBAKfh!XZq^M)!7J!{egk%V4X$><6 zWC8#(rwLlhzycW~FazDY$>Ml{8Fo5kKL=v#254p5(oYRAGnhh6dDig!l4U`(o z2{KkB%W(~;NCrh56KE$GXlew!ixK1~&}l09%fgG^|VJvxB0<=_@U@xX9E*4 z;1kCo>w$=GE`YKxav`>qg^97AxemIbV*wM=iVn~nNuVWq0{cNtE>Q6W!k~?CE5LiJ zm_Z6av(KRAg`itFIKVS1OfXez82Ol)85lvE?LecQptcogApvwgg4uBj6KMH7dEzKt_TWNrRS`fR0Gu03QzoImAZ+6wZi+Fd((y*$K#MV~85?1q$FBj1Y@U zK+AbS?Pzd639`%tWE*(P4ET^5)YF-mL08Q|7O^3%4|)em%-qzvz4#N@H1LWyM;Sy< zn}Pd0=u985IA}T!y!!>zKLah31c`#Sq#^a086a1FKw9q7SxQWh1saeYeXwnrh*RG| zs~#bN<0jl4OyJE`@WcER5KD7FT@nRG=zRbz8cd+w=%8K*ObnEvKn?eXNp z5$FJ=e}Vs?zM2vnc=t4;A}eT(CTKk(WZx@0NRI*=XyBTUg^7WY0X&4t0Xk3q7f2td z*TezZ>It(0bP5zmki`+So{w3e6KuynkXj`+@JZMO%?fPG9U0u$wtx?L1=$C>IGh{2 z>Fh!sjADc`6j-G}h+P`Aksh=Q5|WY>*oX*;i6F~Cu0aY3uo%c!)C&o)ksxbeApsF! zfP^z0LZXX<5x&`O0uyqA0Igk9U>5iQ${r9;qmp1(gGX*eK#3HzPYtxdnbmOtlOu-! zWT_Mr=ss)~M;0@t6b106r3BD&1<>{jl){PybeKnm0t@K0E(KPYr63CmK*QspWyY-F z7zeokB+TOongRr8SBOPyuDqZ%wk)udEYZ(;S zK$DZ8y)Td%d{9S|4K$1c76O-mpb`tTDIc<51zgaXGeOQ)fe4Ymg$2Bp+Kh<-bUz>1 z|BeD#itM13QW{JZkV&Z;@czLQj9CiohyosTO0fbnXj48LIK-fHpv=%goD3!K@{bgd z0v6D!Jq2dOByffzXxE4aQ-T6`(=m#(trY+BC7)Ex>OborUF;c zU?nIfN~PDBr-G*aGH( zcGkd#Cs{z}%PE0Q)8u91Vc~}4E9f9TIO#*#3QPjvIt;V`8*C|bK#@g*DFtFW6L>Tc zTz9a5q8*e$A$0;|WdWpILrd14S(1Ri$Lr$$A*8*g`h)n%8H7Vm_b9k;0u;PAp|Doc>IV}lmaf`q_D5?DQG zi3bA@6Et5yF3o~xT5`94f;aVmOa<-wgzQg5*-O=M0<`lTvdR~_Ne)z;LL3CjDWJH* zlg#x{ODJ$M2er{a|NMfU+lc+t(|;JASaer*GI@hpoIi#Zby=-3m`J``|W z4+`gfkZ=Y?FbIRf8@v&V8Jy8UXV55swlTwsBN<3>qyVb3!6h}j;~7|c6Lca0tT+N0 zjaD29K#C(CNO1&eu?kEF)hi$?1)!x7=rHIr3^}0E2yQIAGy<&+1r6jXunK@(t-z+p zq`(TPb3kqe-%G}#!6XAJjzDP*6v*Ixz7koW4Th}X_B<%x%48|9g4Wm|?ek@Y95M>Y zxuDIA@O{3Zjun<157`3^>P@g{f<|va7Q#{9=wzca{K`cWHlM+ z!cObtz%u^R z#R)XnDPYcIqQC-Pti-0kDgbs9$bJV6P|xJUq18yZX)tqE38YXW?T7HS&; z8t+)z5TGOlaUr;81j^{3R0R=&w;@oMQ3<*0uv+&Ilx;ZE}-m>(i#Ezo(`=MXv*M#wliTKeUNq0NSGo z2`f-q1`QT~POac8bYz1>!41geW01Pv@d}uS+Q@jokcHI90B1#LX2;RU09mBLWC3zM zXd|jf4x|`10A1F@1ln~4@inN03SB`0EpI@61~Wlz8UG?oKydR5m6T^WGf;La{}!j1swvypg`0PY7s(vcBz$yI%pA{(eP3Thrhj|Bi7KLy>wi*lR*qBQ{7 z{R28~22qJ13U~0HWAMIiNbGX|U}XXw*$y2g1MPc)mc5{Y7IX_8E!$@n;3KXbS-_cA z;5(>{hiuCL4JbKUfOdUAoCyjv5FgScW7be$0r4QkJ$Opg1~ireO+nz!BltKK@UmFg zIeehP6TDtu!<^Xyl!`#3AE53#xG4udPAHqd{#G z*!o|HGc-W?9aL*TdKzHopzi>J`We*ffwpwPH$H)agMw2|$ZO_86E?^#6f|?;JI%On zf{wcdZQDcXgRm%&)CU2DJt$hBeGryxB_;(X1xOzR(uijO?OX))`=MDBe3%zY79`Ta zr7#PYJ_x9c25SVz0O$w6tJh66qq3$FD9gp7ib5P0;>X( zztV@K`BFl1=^@( z26v;tV~ya11J2Xnk`tsB5tyKUH^?tMSqflTaEvf3FhMgOEBKZp(9&RNM1Ud&RGWg1 zOo9ZT3}|l$Brky*>&QphyG!I}7yqV8}ufd?(3(GO#10ECjDb z0r?!fe4>C?HkVX$I|0xwUuW{iNGjl}}KCI~!0 z06Gi*E;O+kfKJYZrB4IUAt4|RXgiPrv`PZ4<8m|rO_x@B3YolpP)ilAPbUmSwKs` zKwBdjpeJL1;{=p8A;-1A>M>Xy0ZxbDRb%k{!J)tjI;c|`QiX9rRzt!^vOu*P2QR3T z2!2issJGG(Ycr6J z!C-=45)NK$0_qFg0Zl4`!ko!*3aDuX+G7hj1_FE`8i8xJRxlwBU^GC!g;xif2ALe8 z7HB{g*~lm`Ievgx3EFkX44OYu0A1P(xyB2c@oPDvj{jx^ zokPY1D#k#|Wqv@61Faxq1iKz)rGx^LBlwna&|%G>1{i2HmIl~ckYl+)i+m)Y_q_3f zrdt_7XT-9Aj%5H}y{y3Gh|eE$=7E?0NPs4Z9bx7ug6`J^9litVS-^(N6qvbf7{G01 z_^A!>GaDGeXEq=oUjRO`093ClFbaT=GT@$qdbAgG>74>Nn{X&V$2dU)6`&ocpxX|? zH?)8@P%(k;X8~=m1_d&x(U~PMqotvN0aU(#u0#NjS~EC;&W!+{?+bD^__!g^kpc`5 zBbYz~P0SJ?Eg*kR2kBR0bZlri0zQQeH2bayzSV1}Mh3z7hhcVU}0JhT+G~o?eaG-#2 zmOfaCP?_Tguo5s2$ysn$!;N%gQDlS`CE#?+0lG4p5j+SDn$(9Le+zOGvQt4xOo0)$ zt{8N-0%%Dec>Rn-mH={4gI9xtubhO8j&X~CtpO7p3XB35Ks(X6|1cpRe2bDNLDc{_ z7czso&I+K_2cRaQz*SJb2SpnMgKpwf0NphVIw?U$kr{lwD(u1xB^CuHfvw>ANhS>@ z1tmsaM$q983QPjvJ7OSe!Ch=74JHnOUl5hL3<{t~2OWL~IvEC12`Vv~F@i?anKYSH zlvvFfMIeI=U{MAIR&z#B+W=f!F@cWgVF1sMfM!w{;2SqsKr>jNwz4LZ3aD`fZnHod z7ob!9K?Z;t7m!vDx;l^yC<|FJz}10DUQmZ!(Taf;)G$X#fv@Oh0UgK$J_rib7=+Eg zBS*S$pCaf8T}aaxbVMPf zt<3>G1`E`50A275K7K<&usAY-P9S45Wnuv>H|B3qS4-kP{65zHVFQ|TD09|7XuA&)09Sm-Wm`auc zAB4q`1-_6BT<)cy%=B7!Cyv1zu^$`Kde# zoC>_s;1i)CBQ{J9kej*rkao;)&j$7Gpraayvxq4|A=T&^i$F%Jq8bgFVgofLK>L_Llc_9@3ZUu-WSyhD0*k;pm^%a%!8dj>YB0Hg zkEl_|0<8^zlxX01XNHt&;6)IyQVkTVpv&h#g^UR3wjD+@CIQHi72pg)WT5N?yBsA@ z7(syouErTaRTStPA135Wvp{WY(AhaqG0^P`Ajcr91Bro_PQlt5+!q-cS?j@NDY&o% zUGK%1tpu8e%>^B>1-(xNG%E`}B99q#@Tvl%0yAXUkS+rQsGI;zaex96Toi!PEXXWY zSiuWwB-msru|no`!0mzq;L%-BKLM23ptINv3ZT>8L6fVH5oXXPY0$KPmJ(?70C?UE zbi@=)7j%FOT%&fkbe0k;bW|98;2YR+Y;aG3{heSmT{8=9a)AyU z2AweoDuxsoz@y2q_7-TQ9CSl9gChfXBT}h|RN#Vq3_5TPR62k#s4p(Fk;5Exl02x~Unnk51#|gM#D~?L!1&f1yp|^tpaTX4FVzY+rj*7g!3^H5IDFG zfhuQ5S%K4_gbnFiK~7n8ybqRPRR9&Wj!!@wffXP{QVL80J3tI@Hh=|{0webhtW6hC zxd1v;71Rcq0j`53uvoSMEW-t{Y!8S7w@d+amN~dN;dlll;Rq_~d9oazfSMf0s*W&Z zL6ltwD}x&L1jKCdaLy)(YsfFedQ%f#3lGaAyQ`@eQc&uLHhk5!B=7fcE$yEdeG>V^1KA z-G*!|D8+)hr=TtjK4U>a2CIz~7`g8t`42SC4(q)$IT~bv;|rSdAk8VqIR`)uxM`q1 zwgMAq83Cxd1yT!I7y_A`VNzfM&BTJHJ3)6TfK>@JgOZ>E(g=^^c8KFa+te6AyZqo| zG2mX8qe2$U6BvU$pn48;1|g&=puwa7>I^~aKm{hyL@%TZs=&yNE%!irqE(38fQVMG zhr!2OV#MYhP!a>J5n^&|g}7V=wAGHds6^_7DKJuPdG;Jom~w;N44#jMb|o0Nl^Geq zl@O%vqGus~Bc@Ln#`&@ex!0nGs#Nn=o8QvhwH0ht9_vI0>J zzfA~KX0Rx5K<1}FV{i=Mjy+^v7BtTY>NSA-2(YOw&@>&`5Ct{`(C$x=!JwW#s6P%G zX$A2KIT~ycxM2V@71V?0=T-pCiabER2;ny)6VgGd6Ohj71TUafU<8%Q4;TbagNi|L zb^#rf1HOz0>^0EAb&dz%!)7dwHyA<9i#wnS1>_6xJUQqbJdl$>XW%I?K@STA4f8UU zWSKFYVT70qG4BLpmcSlRDpg{2Vr&j@7zNaWGS#Z zDRkH|F*vd*f`^Pi}$|5%nHobjDC&`prw+a0C8k+ zY)}w*18O};ftw$Spo0z>vp}NAH_)+zwn>1pgaSKgHwEY@2}Z|81%L46EgKj?rzSyy z7kvAi0*fxg21Z`UHYXMhrY(?I*#TZc40Z*J;~p@_j41?k6O$QJ0Az^-3#j6N+&c&I zBxv@CM}Zk~nvi0S5~HJH7O2w>nQsFhzQCB}s3>q36saJ^5w5(T^PU0RKUgC4HQ;&=|!;sb{m=v-qK(2e!b z>r7cRm?A(iufY@pnaoU3Waf5cR%GMh;C2*IWOfvBWQ1;MUX4k2Z9WYA>T0Of&9auiWy0wqk)+Lt%rp$5>kt03MD2GAW3;J%~+ zXd4+QVK8Qa(*6SmSmFmw973}R=yEyGM5h@O$h!(mj^L3VaCT{Uz~Bf%@ zr3^}}pgm5YCH4ZKh7@=<8#MO{?v_CIVt@-(4JJgn3Yt0xE#3l`hoBM^e1wDuc+o3Z zoJE640C`vdyaf%cNCh;`3{GB14KE&cZdh>uTOx=320|9l8I>Cutr;U6zpMa_m1%>5 zgdxju!AcNs0Vq^qXY)8-03~rpbC8OM3|Wp(z#6WANVpPE7cG5sMH1z-?Kqj zpqfL073O0|!wYnz;6vCBbnd&%OiV~yH<^*QZi-|%f)@BIFoW*k1D_el?D!Cp$^{gd z9d|>RpjF?}prK}F#|01(&{o44jG*ym@VVWfe6GOkID-+C#6SmggPE`uWy~5(a~L7Z z{Xm15Ge89)c+;Q)qvIdg;&jk%1kh&41x#5ef?!)f7keP9+ymYc`T$8UNE>L$I!Gnh zUQpU%S5GE0~laj| z^MKq2@*i9dl!rid8N?DqSqj=+2?`#NL5R{+i49c7GK0%gC3djw;0Xcf_DaxoDUgX7 z(9#(&3v4qe1AtbufMXdP?cl{B%#I7-wd6Ux&1dKc5FZQZECEp4584vdQNYrnTL4Pr zke&tj{ys=Qkw7;NT-hV_CP6I{uyf(v&p(hf1L}Sr2Q?jtG!`_b3u<&Q3V`>LDuT-o zEUrc}{sh8!(C`aUT_RARz%PeVVBijhj+;T+!{Aa$2{a<6!~z{M11&XTf)3w+Boslj zYoJOA)QC}Ff(@C0PC0}Pnf*eV{zr^>fQn5B9vv%V0T2FyQaH88$`FH7uh0gko`CuF zh~6h^)PQ@Q;4ugAwK+$?wE~O4aZob{Iwk_ThZ!n-1|$sWhl2(Q!Q)d~KyuLOEBG7} zxZegJ=3zt{9D4|M55m3A(fFUy_#e^uFVXmq(fH5M_~7OllKpSM@=OfemqC3(=yV_G z2qVPAmjtNy0NMV^tidD$-rEkUp9H{Ski-lkL1XtCOd?rIET9wn85CG}89}SDc~A~m zg0*#6L04sgo8!!&My3X6`x&Sw%M2<4RltMR3XBjNK=lWQB0H$v2x9U;u3ZMtE5TQ0 zfFx8vE(2ZE%?jdafc6%%DzIgNF0Vu6Pd3mMdTgNf5wijl!h8mB6Q4zaEgPhlMTrHp zGy!AYQjYF(`3@8#bUWD`-&_XyFBTQI!%mSRB&e;elM>!U67(LJfjU zc|mnUCcB_octFdrz>Wpo$^gzIpo=5~vJ}9oSrowPxD>eUK+QR@%_5-Y8S+|TW(A0y zph;m9bEX*3xdosWEVxU;18!h}8iri(Cb&$N0tcLIG?*a-Cq*fl- z4UphKYUS}Dd72aCX>cQt8*U%eW*(4NKrMgJ&;;sf8lWl=(%xqV?caoqA9HVDAapMF+(?_{wc)tb<(cD3GNDn)L%8+@iz_4j8aF zN0t&FY+h4|A1n?@B?9Km1>i)gzz!A#joCx(k;sBXI%uJS5~BjtG!D>#>`)T~AX*H- zt5>1Az^jd68V#~Q%W0q{gS%f4V_3k;X%rxSkpZP6@QP(nN0|xcbrq;E{ElddY8|Ms z4yf@0PN$%Q*$qI8J2aVG%t3<#d39OvBvN1!*aE8I6u|X8hXOO`Vn0w=gIue? z3|sL6Ntgmkkp7}T7N{KOfG?|K)?k84fv%iq0ZB4|k~3%(1t>niQ{&)qAtgp|P0pdj z4ywtS6c`oQq18AjlY>Sk!3*&iL3@PQVO2OANEzrNM^FV08pB7qw+*@!1w5$94BCLk z1ezfScYBzji|`o0E<&CV0@eG_{QMiV`VfAc(gT#^ls+(klGP1R7gvEv;2Nk)15KSg zkPUc{7z7Q`gMD2B@--x^3c#881tVx4`3<6XtibH}f-%bxCZfa$%7+S!Z~-aM4RVa2 zU3K7m2^p;ct#AS*JmwdmrA{FIpoM{sh)y@m6p$3mXepE=4OW4$1<_*$X#q7GA$z)^ zePgg2K?^M*jG*}z1r`M!kYe!NKajhG%$T--GpQNV zA7=14HPai=FeU8DA`lyTpyL_H=;jI5EHkDbppH6=;}#J61W5k{R?tZP3uf4rMNlzN z>xL1UHNZO`FR+?3zW^D!1FivbVFGA)7!;%6Km`@}VC6el&6zKN%z6R7U*Q64mcS%% zAqcvsh?y58bAt(VoVx;-BTJS(BZCs7H6v)OflGstK}pDr=>~Xj<{M_vWl{Q!AD9(I z6gU-xKw$&AkVXNjTEv?14Cvf((4|jIpdv^_iIJDtiAhluywOTQz>z1*j0t>U66it+ zLIDLbipB8+XdnX`P&+{E6QJGypdtz!k64a?g~oQApRF-=+!);=FA|Ap|1YGl%>EVZ~;6p%A(2q zfmu-$G%WstIRJES1dAgmL+~LLrXUkRK?IsW0?Q)gKot=9CJpcsGtf!Wpj9jIRn?$# z_gO)i9DM)N4pzj}I*%A=>=}B7GE0_%D5xrjD;EK|9!0qbH@Lt6HTD@n-F6Tcvcy^d z6aos2ybO+v;9F6_c0eZE*j#zJxfR$HKoe}>RZEHjkoi(ZGX~I@HK?fpVX2tZg2 zpeaJo#Z#bQ0Oe^uP?68fpd1}W@e^|QckP`gP<6f{ZA3ra?a$P$IjNrTR52c-z; zkO}Og0 zkbHgy96;c(I)M~G+zO)LQ~=7fd%#M-XL#&DQUW@a3*vS$Kf_E}qVB}%o2D|PJBts(NAJj?*wX`0v!Wx9r_`qi_^24^$ZU8M9hP2cn1s|vx z!o&bRCK4n7YHY7{y1-DU!~$9p0BRU6S7HSfnGE0)dLV@i{6=i><}T3P(BLUMCeVR) zETC2)1L$}P5QD`Gv=9i?db0)+HS|>_y9DI4{E-FW@JDOIna!X z0;u{_DZ# zV0DCaZ$Y(xL}4z>!k zDi30519WK$co_!&R?GyJab(O=Vl`s|UylJk?NT5F6#GsJ z9U$*&FqMEO2Ed!3N)&}aS_%{eKv%Yam>i1WbD1ICHzi>O*u`s1j-W*pU{8Y1^MSU7 zz>60f7(rcf@U_4U=AdO4;1dq{pi0;jm^7IK%)tlOv4d=20d4nVQeYRD49-cQtz}?4 zL9A|c8jG&b=jG*av1MvEG1z}L%j|sHoKqgCpA8H{Z zXm64rs32qn4W@vm?!lY16u?)@F@gqc1VC}f2)b?#cHehje z;bR093ks0L4IVfIHB!KV%>fE*cJOp0XagoI$b&MV%RiX85!W<;4#a|%;0mC<7y{kk zstXpR;6VVWE09vsF-Yh5p@~DJB z8^|63$dR%vpoLZn;8IqJ6?DBamJ_refQFPn^F>UKmmnT2Q2==m>??=|7l4)|7ZBw^ zkQ=ah58`pivJ{XSlqD(PXclOKd3^~Z$nVSwte`9hVKQkjEnoy!4&cz@VdjP;KzP~( zB>|8NG0vFpK*Zl9i1%7RhmL?F3v`t=+^f)(=eP%?L0~>;J`&Wohiq?AfNgF8r*&4) zt|pMfpqpDzj(OSuAH%!Ig1mC10cDg*B+F42l-0p2MfL1Uf&RB)5 z8`;5_g(3*H1GE|haojeuBS?`6Xmkx^38YQ~kMV-U!GpOVaY)4n7YC31g2W-UBV1et zW)A$w5{UWWsR)pI_%V18aV)D-K-L}skM@DoAAv5{f-F&C$}wj;0@^bSS*@}I!epAm zXwLM7Q2`uc3J`-49ziJ(Pmr_~gBUrD0H>`7j9HEr zkm(N#&=@i#S%X9kKzEZfIvRi)CQ2NTFawEeWGR8V0+7iPE`+#3mJ(=OO#!SPGAjhS z<`pzq!m9w9QUi@@@*&iNZ;*vesX^y5K<0y|IG{}*B_XhSNUR8(Gd}>O1Bon01JEf} z%%F@V0c!3kK%F50o(h55Edic-gIXv7I%@?qRRPrl8n97-7!JxYpi5&xg8(96?<)wK zGfOBigAR8Aoxuz>0u+`4Suis|JcTUKlpDxI5Kkiu<_r)I;X)A4B1-{mGz-j5kVnDU z1|*A=Z9wASYz7iX%4Q&OaJB@ABV|jFI5-=F#F4TwNF1E)LE?yP5Asz(EZ+4N!vNL=jQ|r50`!Aqh}I z;YAS=0HqOFBM@REN0t&Ve8vd0l@`2G4RrJcE2tC&&t5WXGJ~3HpurW9ECsNUpotmK zOcB^hFh>P+H$5{0B){rFukr=UAZCgb7(gvE7Lc33GN7UeI&g<5EeWc<7 zlHwoK0Z*11#ZXc*pxxoM%dIpblfogm3W?+GRpq7yW;z(jpx0=~e%8bcJ zf!T2h#9|LfR)rb{TAle3sU%bYm1^J(-Jq-hK8Z?^4Wa{j`8jAMBuEZ&$^xi_0r4Qi zfS{W!Ks-qG%nlmLic#bM^@cT=B0wW-%%FHpP+(SIGiQ!a0H*!fAyzm*h zF8oe_+hGP-a77ou0s^2K6)wgB9SndcO;BY43PMDic|R))2e^R)Uy%bk_8VGefg7ui z!XSr(?FV<8!7b>QkkkgMK7T`)A_~lomm%c^sBr@x{bF{!0g(i$djWDFxUKUKlp;Z8 zAt*;?fLk)ql^&p(Uj|U70eJyjV}VybD1pY9KnDwJfc*=T0I&C92A_iq2?&@3xITkO zSfJ?80IdmuNE~25kud<(cMzEq$PHVt>5y<|Hh?-0Qo4Z38jzbfAV=LQazSOmhvO-N zLK!^Pr3Bgw15$Sd!`L&>%naHM0E$meXdwZ~&sw8SY#kq>+g17zh8cyu1R z=tv+-ffrm-DDasxfvQ~4vTB$z*oFdT#{=+A-#^fnGx*X3)a9Q7pb`Lb&a41t(wdX zujepe4Z@FGaxy*1>k)mNV0cOWCeDC#sEOBc7(4t zW}wXaH7FK+#P}SlVMhZI(5)xRvQovZg!U-CV z1@C+XAGZp22efqrI%x=0Yk&(ECI!%N7HBS(3DiypP5*)FAxIenZCF8bHmKBm0MFVJ z*qN9S3tu*{!k1-%0vQ>jx2Hj4^5A2%nH)jQYDX5(neKc{j4YtS1lpzs=W7bu)NCNP z&R~JGu`Yq4A5@#oU;zz$GCR&-L2NBzffp_yH-l8oVc}zDWng3l88Lwsq!Kh62X5Jc z$7`0bf)>0%W)(mJpz?15E9kU2Q1g&!3aC0<0AAFi!0ZSz;K&Bh7BDG+J)jmhXcG=- zat$H{3R%b~38+|QcBIg3(208B?!+1vcz0q65)5D#D?}L z_JB7tIfB<_tbk+!X2>!R@Kzzv-Yga@or(p_S!kUKW(LqQ5wIrEKr)PP1f%Jeudz)b$8Bh}40H1lhPS)lv ztj8ZLSr6`bf@UsmLYj?49e)76>=JQ|z=U;RQxw4GAA)8j9nZkb1x;)qju8L_E)&xE z1DG0j;Lr%3`T!MV;F<$u1USyX+r>cV79e@#7V#bd&2}OkYp@jQFcEC0YKUYxg11+K zPWyBe$#T36u?chpi%OQ`9XJnkDGz8Oa|a|`Ky!}_prJ6(t`SfQI02eE0nM%4g=moh zZ2@w$fliQuOgCc^05{T4z$;@UXLb;9rc9P2DB(g5SiJ|afGx0Wkv(nVSQTj43gL zC=P-5pi&Vc4moBEH2LWW8gJ%++>Hae_Ctdy1vJYFE~1$o&=-`Ww1W* zA)Am9J5U1~EC!wyRsk2{a53;m6gbC%n&_alPT;%>;($+ZTUIjG023`mbYEyzUCul<Y9K?=OCqr z0j#eH+7ktuhXt?11g*3HmG$s>H&8wV9c&A(eg)v>pqy|48cqQ%f`V*m1Z|oI%`t!u zOaML2F)F963M{%p;wp1lm3cYKeo_m4Z)fL2S7P8>Ip&{~<2hWla2!D9wD&3piN6mpjw8>(FPRFka2a;G%b?}WLpVrs0-{l z(DgH*Di<7tptxglfGm4uS3tN8KFI z>QxE?&x&u$6g0`%I>Mqa`4&Xgk;Eq0Y7L^$^rVg%d zK=<5$o2;N12KOBuAY24v|8TmuJa*#yW$P`%0kT|x@ZW6Zh? z65w7KI5~nH09u{_TG|fN%_IZbW(L*`s>2PStIv?NgHKG9fuv(ly^7jhWdI#6EosF7 zYRf{GXE`z|f*OIKa09P+Hvy#y@J=<*hBoLbMNmv*(FVqtpnVh!j$qS3Q3hTM3ko0xu(_Z(VpU)<2c7l< z%9Nlmf^Ldr)nMXKWL98RK!`bVfpT***u|HU}Erg5J;szVQIG4+d1u3v5L%U_gsAbs0dLj3B#hvtNeO!;wK?DUoFngCn~Y0|R&oC%9|?uNOrs8$jh1gChrMF⪙ z1utX(m#EC3<{*m(6IdH~$tsdI(8^E5rs#Q0$meT;)_o$91Gq?W{DYbvKrsX=PC%#H zD6k-vCEzp=0!{;<X*Re=#beBc!_ zvo6C8P=y0+!zeI2J^>%(1j;XdJ@JttYtpt3I1SAX^ z?*}#9z#RZkf`S+V9?J%=pFmL!ZNP!Xg&;>yg1iWtyI%onXn{fsq8+v~idlo{1|u(M zoc{)R-<>W419(sqG;6`^_>eKn@jmKM2c+f)?UMxEb_qHQ543I)SrsTqz=Jp7hSp6+ zNGpxWiUD%*1$bZw+;Rt%CJGE-Ppk{drs09Yfo@Pu53apOMyzq|mjk|?NYzzkY_3o;p05`Y!M8tCAaeb7-zxat6N<_6Fb zKhVlEuz8UEUGN;is>=ZC1cTZLj$9y@ykh`u^8#)1VgxL6tP9Bh8fs+UCZ{ z2Rh_IpOL|ukq2ZB_}EfVzlxcc!HG$c9TdJ`hbb^S^5lS)B|^5Afb4+oECJaH+E~J> z%a91!R{~lQ%;3lhDL7dm!Mi6o4n|%$Pc0US$zz1yz<% zS(YN`xo)f)ObMVR0g$#7Xjl-ux)(I625J?9ZWRUf_dxfIzGeV90=)i$6XYsZ1rBqD zWYA7hO@;(>2GH6wPEdG(!i6IXzTpJCe*HZ|mIecZ83XumAkYP`kOBeT%L301F@Snm zkZ=M=i~`8*65y-A83fLPTo1Y$S(hO}i5axn1$6N>t0qGt#A>iLAgcusR>Pgc2^WJL zPRXjlBm>C^tQt%bp#BY{_X&z9NYfi+6I2nnt%9ToRN1p?Ftsp(OaMzZfcy^4OW-yR zIF~VjQVVh}V*<+&)CV>aNgt?njp!1$vonJx2jEL>kmhATNe>yLPY-~$iy}`CfUkVz zV_{)tLtbng#t5Z1v}`zbLbd(0cZdh)Zj2<$^m!R zUw{gO2Jm7^N6@Mp&06cP~$PStvDp3SQ3us*jXfFbEQwDeh33LJm zWWN%4u1|p-vVsOQyaVcVGJx){gbgi&?w@B=WCi70W=A=Q`|Do zhPOH4d(J^a{-C*dkek8z3bJ^z1l$2+)?g|CWpnUM8pM~7;W>P+2c6^rDmKB(*`QP9 z(3v*SB~Or*ZlFP7P^|=B*#mL|Xqcb}ydnj(egxF%fSfpoyvCIkl+keMfUNuhg*d3R z2N?>svsJm=w&Je}Ib-P38-X=FA5`Ghra(L5nCM8j#j=g98NAE`Z2904F(cJc4rn z5k_;SEufJUW=-Y?jONT2KxRRL3}hlA%uv^NgB%5y15Ir~(mqHFc$geK-3dF55F`p( zy$EWdVy^H00jg&xSl^8}Tj2{63#5k)AHf41Kk8*;01K`tQAXh^n){JOCqa3tm1e6uv7o>uk z;^1?SKv^F&U8w<01=tpkfNLuO&}uX=3v_`n%7PVeqJv%VNxbFY@fc9~rOBkD$d0~d z2Ral3wiZ-?f<^^#uUSF52b2{toQ;_60tFZ*2H)7k#|1hMl7*Fxor4p603zc4KIlZA z24n^hbPwT~t>8KY?fyOn&^A}lt!$9_2_{EOjSFyS1mD_*&&CcM8o~SL@M-+A1-nz( zK*Rs|G@ihrk(H3fIXE=35YpIyLnC-X7N1ieY{u?K(E0eFS)4VH_6}%%PbUjHeF&~{ zKr@lxsY6ht?tq!XZTXJQqlc0n{*ZgkRzaZg%5O z1RXGoKof8XjiBH`ntr^4G$Dg}3?pU=W^%xmh8Z1KYzHmc;Desf$iTzJtpM5{-2)cp zL9Ewu1fAOsKcsO6NE*7LiU*W36&M{qYy+9ZiKGRz;s&ne4@erOg&nld;}J;25n(l0 z@B&y+2<{$GB2-{>+z1xN>7D~1X_(kekP-OxNy(?e?`H&1m3B4yEX{donH?)Cb7irDeeMUwm*b;t3 z`2=262cBt!_8CF*jJ%+9i*e`014uI#wBh+7Bzc3Tx0#7L;1zt48EBdp)HeW4o-;xw z&krEX1nxIt71b`*xCu5598gFXYdmFSWC30C#gYYTgM%^% zSOs{-2h^qpjSzrGa+w@Oauk_Ck}QrKS&B@cn@|LrLE98T1GCWSVDM!JEZ`l1U?ynB z5Hz?9>A8YDDgxR{!R(lm1-k8$8`Lrew+cZ+j-YZuBu9yfmyri_w;Z^ffm;vSOrik4 z1sS9da!3agXkLp6G%E~dfttvm{r*tp&<+!H}%0?2o$7?SyU7#KM?n3y>@z?B%t zY>1l}U3o#(DtNLSd`t;=su_Gc16%QnrmkT2Oelv84?^| zbu6G8FL*)SF3`>?=$2Plz=QAKWN>6D0rlb``}{%HA!!G@!;#4oJfjHiZGmh89Z~@v zTS2%Q)cpZTbtOi);~_Bv9;bsj z9=bUcK3~tz&3%xWkp(FuBL>SM4K)R3fnT8P2}(Y&%e_G-1%c0cgtWRq2@$$z1ax~n z_~1v740vps2U-w-E;RtBW>7DK0W<&z3T(t8NYI!JsQC=?4fsF^M+R_X3UoR?XtM|t zw<9B10DL7pXeBqKkpl9wBjh@7uvSnX6P#p0R)DYi1@&dYxrRvrwAEgbk=a3k5uRmW zn`psvnV>y6Ip8xPK#L|oohjHoe2~+#K=oZtmJ$;$=pYKv8MmMl7{DinfNxQO-3+TbW=Qd(GFxF6l8<~n*yuAd8oTFR4K4HLKcv7g6E_lODjN2 zSv8nI3&=qi4S;8^*g@+bSiqO2J2EJ8Ix;A7gJOwAfeX|W0=oz_feo4}0k2t7g4_(k zqrkpgkqfjK1w4BX+D0Ri1=0iZHFyRHoby2m7i_qQ0`zJU(A*Jd+CTzysF@j)h9e`` zZ{V141Rdt5z$^e>pr*j$XaO2_2A!C~0L@?!<5(Q8KsP^FKqbL;fkI1z$p7`wbUpjt?|q!~hCl&>@D<3uh4%pF4!5$py5{*4alf9n*ew=ft$$zT|@9ym=cMROpuvaP*VuC4271aJXxS36BL>pS)hCXngL)p11)P&WCB&fESgL_;2~PX z{!o!D(9kPLi$IoRBNIx5Lds&0*`U=?pnx`G0v+WI*%1jY)Zqmmc=Qk~1TG{YgN&f@ z8%Uh;z<0)>xr`CAfe7SV*clQGkVROaDSl|Y?OgP~5YD&I{B4bydLe3Yx`jY-nf@fTR!wSULsO zG7YHZi2@rak%N)}$TLjfNny~~*9y?}9s;vKxr+hRGGGFgS&)-#!2?l9Z6wh0dB_Yf zC>4X#Ggua9QN;mrGPqcRG(j9eCqqEQ5cLPBJ)p^~0r3I24FDdFgSZk@n<7@~oaAN) z9c<22&j@a*Fv1$0sKen6R~W1rLGvl#!9q63-VsQ%1$=%uq__c}k_$cH9F$x^7(9>& ziZR%}d&mM@2u}nw&Wv)JIC$?rcz#AB3o$(dQ4K0QKxr1-XaV^RybF2>xZ4R@{MIzW)OBg}Bu{D?$fLgksJ)xkBg+aUVpy?8{L|_LaXk{{FwZscV2?dIRN(%z_TYH9=JjQ?QH@F4Y=b1+OY{LC^;2)mMgL;usSljfli}k z09BPpEejRM>P1Ll2wrXtuGpZ}BWPn3$Q|Ic1Wi>u&{hCnh8+QL3XdOWjQhyfkwHY?O$flt{Oh_`e#+(2G#Sdpb%jJl~v&20L@Qg);aLjrz29G1F9lG zkp`ay;^zii3~iTm@G!9;miB;-+lDXg0d*Id6<7owff6++Kfy3~g##Zm10!ew0juKy z@bS?cplb{r5l4-)g68EwITf_*nmJ40F~}51t;Om%0bZgpfVOmZfN%DNRCb_N21GAt zos1((5z>WYtd1L4K}*Gyn8C}U6d-(sEG6*DPS65#kUXdXfh;eOrNoZR=g3mxfbv1q z23DBAzzeVr>^jf@Gs!^UE2!P9#JL>2M!ACtWH~4qfbVH!bp#23x{jbak{P54Bp`v< zvJO!pfY{Iu5#WH{4FJ*t^8N-^bLI}vVQi3)1Q`NbipHwJbO3zxEUPKg5oRZaHYdgw z$Wa)O1YXdr$O%jA1zEqH7hus z{{R2~pTAjw3w-=7Gq(b(KH~vq@Ji$tOrV8A2Ut*SR^T#c>S2PUY;Yieybo$vJHB8- zRR|6|Go}roRanrF04jQIKZsL;>hg=jN zr3?dE3>t3(CmPf;43s>J9^&pmzbufbZ zpHNu^R?x+apxz32I~HPN7OMu+6p%vb*gIqw39$x&I>Aif;coB>Gh~B6OUxd?ce}o3 zK}-W7EiVJ@!&YDtcmN74q=FK(6caSn4{EBjm@(Y|b>uvA( zpac(TfiXjy=isAD7Jyc_I6@j=V1XH60dS!Ou8BeI3l>n51kz{$t*QYhPtc7d;N$lk zKY&Uq@ZGM=j?Y0wHNEbMPe;t4 z`+%{gBT!`u3Ivd^Cou9cu|h7!1)q5Y8pVf=WHCD~0oQP#Sq9M9^8zprIj+I&1n~WJ zuDqbp2T&scbaE28rocjZ34942Xc6udP&BOA4bDj5M&%1gAZ>vJ%mz@vEP$|YfY=*A z>JNaUVFDv;OFFX#(*bB8oq!%R3iAIEMkVm}f6z!0G^>F!69b~D1)3~ufL(75ZiB#= zQBC4uya;UImi$?NRARas2|Cyzz!SH2lcJN2giVmPf!CB(tUuAiGozZuLEHKwP`@3 zwBT`X4$%3{ppH9ewhq)GHULXAE3kqF%Roa9Ob!a{pbP*Wv110=3EDXcDr`YnLxCMq zA%plV3Or^^2B4$_n(I?w6aXI;u-p-J*E$EtZ{Ptw$SqA^E5SWFP)P%k03SsMK2VOC z0d%xB`0$$o$l$U9SP7`W(Eab1uoF~D~JpW?d3G3{Z5xPJ{Ov44Pg0Ce59<4aIbnK3PaTr>?n$#w^X4L;x&d=>Wu@Ri#u;Q5IK zRGce(C^UgA2H6CUIZ)mJt%J;P> zP$>X*^^Be1QUL5~&=!gXAU^ycS{6sp+FelH47#laQX7MA$p&dJQDAXA15$0q1PTt& zO4BPKE?hG^_&OR;r4C{#u`7U5Ft-BuL~RZQ_G~3aN0D4bP+|l3fxt6(j0)_aY{bs& zpui4^NKod1PI`m;>`dU;1T#UI3UpXBBsRGfK-MUN?!N&YnGKr3gKah@Ima`C@-bvy z13ZY0NE_gE30lVr9ia!cq(FHMS`cVbFLWXhuT;5|ZG0iUk&WJ&~HP z7hy5U0vb(&j)$-0X9XQ6$z9J}2cO2ifH;2$QdojW^cC*x3Xqd;Ky&l(MHgU&EPPB1 zjNr3tKY;c1PlvE*MRKmy1!oUbV0cHbu0sA^hg3n{2ah6x$`G(HcLvlH2R2d$1f{-&= zK@rCd33E{pWv3_xqU=E<>$(h%koa(d#Evs)#2FNi;FxoR#G^YXMd&hkLgLs96yuq_8b1Iv2tlO+AE-eE?)`u#xFE#_hz~j!fdM?NpvmB^$fh6y+MX=5 zT#-*fc)6kk=&lTSa6@-zfN~V5l?`4e4?3R`Y#rD#1!heKZ_s&Y3JOR809wfoPOhLe z0HASD1L&#+kjFrQF9F&D2l2WWc!m`e8=4G?pg?6%V6$P6R$x%zuwnq6_ypPu1DR(9 zO(cQJ5bzW_IA%aK3#ed(Clt_71N3Ava5J2OjYr@D4%B!7SGgz~kG?=UK1dsn-ateO zKvO-Siogt9Kto2@!BsJ6f`vWHj0sePJAyYlAZlW;FF?&`P!PgS<^qjuKu&)Ebs#`v z9iSWs3KuSLxPWq;qyhsdpMkO=FC-iCfwLhfcY!jW03`DXf-|3j7$nPyLb99$ILm>? z968JxR29I(>EHweUU>jMIsiOD1If;yc@6O0(%=aiXeI>>rh!rcgQG5J>I^oj4Y?`G z6e`VJ8S4NrpO4>ZaQ8uJ1*3qc9%0=)Zn47B)9xd9Y}j)*0rpqd4NL2L6E_}Cyz z+0mA>dI?0V?pbD z9We~+Kp6HKVHjw+AmnNxg2sZf3#hPQ6j%bP!4)wUc4LO;15kx%#)KZ8parAwm9Y%m zSFoON1&Tv(?19H8Kx=+MYb3M4fsA<~*c3?2fsQtV1{D!Un}O$F!6%d57 z3o>jDB&a}!L4pbrof=u7+eAR&4nOV;bY__&+*io!eUE}x({c+jIBo!Cd`EKyMu7{U zRy8+21K5KKi~>i%N)Y^~pb+Ms208^3zBU7KMXmy~z+2Fg2~bDfiUEA{9;l52I>zNX zNL-0Ufyo;*E(Yp3fbN`s2NDIfHw8dTL_wv#0%#%`(ntc`Rs?BOF$;i7XV6$3s4!Px z$%bY?1yBkFb89_rXEDB870+&D*feK>8Dj3jWCOxo0ppkh{qYF}H zgM%Eg01A|~6`;3m@pC&q*bi!OngnKwTb2T?WL=BM^Gh;JZ1=L+kxx@_q0K^0LVW0LTb>gjZ79eTf6dt z4)+DQ*^vj-EP>CZl3)U;x`R5In~8zDmkBX~jJym@;3*<$aDco38g_Ez$P$2L8CC^m zP?iBL=>Z*yBml`Wpmk@UmDiwR8q^-uWP%>Y2I?w65;dq%rN9c!DohHXJ7QTJ8K4tj z3e504fp-NJxK;<-4O)o-nn7oQ_aZ>6zCjIJP`?_q77%HrE>cDTuZe=>l?ljc0{Qqz zq}5%JrF5VrT6;l}4GIrXCm(cAFQ}XYOM|98kHD6Qz>cE^ITCaa4|L5oq!G&u(htHQ zGkCz0vY_QdpxOfDVz6E&&>#osa3Ro{VTfK9c=;#z^kYyPlnFGB$ZW4EMh2QN8eP+;X{0NoDl$f(Hb*l>aYwpJNDEUW|S zV1ZH^XnY3JD*=u4Kz1~Om$J!#RDf5{g4ef#I(nR-p=Z!2p#fNqO#yT^7bnJMyAT0Z>`OqRAwp z$c3_Q47Au8+-?W0Nh4}WBgF-fK@{kD z>B=jDZ)_jAH?9qClQZ2A9O(;b!o(D5x+8l@}=GHw&Kf8#D%jp0-** z+YivvRslS1mB7*#c=!+84$xr2D8H#}F7C92ILxF2srLxlfDR8#P^|^Zv{#VB6H+mP zmf1LRARQwB?)8E~5iw*BYVJU)Pe^YTwl^HC3N}=ahzIcUcSZ7QQ}D0}Xi5S$!N=kV zI$HpA$tAe%gjS{o@W=oi=LfD;46<<7rBpQ)cT6C*rsK@zpN3d2-wk#zBX|!1NiDVu z$hjP6aJ&W^|DUnYieY#+U^gHK#|cJ8Mo_PY*^$K)Jgd&6!N8!z;wS-{5#%UwY-sqy zURVUmab=DT|CkFESR5tFii(sV`zn3GSH#n&O3mSt0s|3X^O2Y=+%Y}?QVregd#^)HgXA5#d?)?E> zY6!Z_kf}}tw)|iNGg7kwxp!{?ZTwhZbW|*|5FHgrgVI6?yaW}rvjVia0W@I=Y8PrS z*?^Z1wDVar_JK;815BWLp^ph{0BCIkYqr1*NHZ05-WsTR&#b@#W^!aHA@)cdVFFF4 zfZDPLm_WPW92>yPyOcnEcgXdI;Hv~#z~Ty^d+L}$M`klID1om8gosOkZfXXd#|IiR z2VY|d5eKh@1C2_6#05c1Zy@3vSxTT$VaU;7!eDXGNIHX(h&giu$e9zs3nG<7A$JS1 zID+^JSxRCGP)k94i7X{?$W4S0c>&ORJg6lgd5$b43D8}Cpb}HWoOuE?lpGbZlq6y1 z9AE;ic~g>tnFHc$WGP9*>;>@!vXo>Lz~*v6jRS{;OqP-?G(cstl;mKAGgwX~OGzFo zr;??lfFh@prKAXz)5%g&f-ab5Q4j&2CIi}T!gPhnoM{TPf{=m)bZ!_jiwa7)AbI8q zOweGu0Y2YQNm&8DV8an4q>!bg0=Xd&+^ql!Nn|Oh!f&1i-%<}+0-^?4O$b-Tk)@=r zAOy7(Y*hoZIr9xruLCr*uaTvsp`Z+t2A{5|kfo%opn@VK0kT~cMMwZ-yBdlRN0ySB zf;vnHG|7E~(VTe&qk^b{254n8IMs=PZG)sVaj-Q?;MB#e05V?*94QhCAcK{lsfb0B zc?BaV8BJhPfW|U3a-ngG8kMpNu!xgafJKv{0%ei%g8{TYQi&NUQb0lqpybF4^DyYp zDNsmpBSi{Gl>jJ*ftPrKBLyS`+H8&)DHRIrpxz89aWk1Q*(k6$zF`38Dv%AJE;ne) zs17JgfD;i+LA0vT}jfFuGg@a3FHiGTx?1`dFRctAV$Ksg88hJ$ni9YJHB5HZlQTrdmN9RyVe z5?Kl&AYX#}&EQEs@TL<%h?oKB?o;r@l0_EiW-U;I9JDhII)cOinyO(24T^vwP9RGO zw8;T7*9;COkSJ(u2|A9X2G8kv95+`y!y2RRE3gfE>*X zx`BoVx(ORxdqa94;55hq^DTVF6O{BeFhhsjxqH}IK&PvMPUeCRX`zl}fLj~P0w+Kd z6`&Lc!l0Ib1-Kyq9(jUoJy&7{70PVjsv5LV3FItx$WkT9CNL%i7J<8Oss&{Q z@OEva*Z_MMDL%jn1bpup=z0}UA_Dhlp)1$3(=m<22PKsJEZ+JSQyXt+~@ z336dGs4C$Bt)l>`P+$Qc$qNn_u+`v60gyE;;FSfS>81p5I~p|03o0N%`&Pgffd&=9 z_oRX57C_@0kP&uJ%bY_2ba53(HMk4~t+7FxdjgNMYe2Ia=(q$X(EKI~Xo(1DKNBdT zKz&~h1(dQ3*`?rO2JTXDfPlS;p7|_50|D?h8CVH;jS|FHte|8EtyI8a0rm(qWI-Jg zP%yyeznB?7xe+n&)y@OXjYvD{KQJM65J2~YgTh4ME^>B+bOIiLwuwT*9UKoVAjRNo zK0rkx*nUuJjp+#^=(LR#1s2CI;C11ko&sp;3&`1^g6IKbmIC{7c({OfQ48z^_Y&AZ zXIQXkFg;-81vU3TiJAq}0|Q+I%~Is}0ydth0N#1c3CeOQirk>1EF2#|<&>B}&H`V- z1KD^l1!iX{a4T>M%mQb3@QpyA!-Fn>cPc{UAuIJkAq=`_i3yy%Ac4+q&U}GUfk~4o zMGzzUxyjEK?);z-b5de8&_=!^md z7Epr&G#3wQ=YZ;E(11Pqhz__V2UY;e!Q8PtwI9XaBGj~v|t74;LqBS-f@BmN4kXd_3UaTJ~`MNr)VVxo*3 zO#zP_fgGd3GyyVp1WFJZpxz_s7zR+tLQ^nE9NX9tNF3YP5lCDhO9`}e5}dS@gdh!1 zkT^${k}!B@HOPDsusEa-B?>-57gAhnfX0fTmV=5M1<+U#bnFPkmjHD{!9xiU_2981 zs3jnI4$v48)NoOA<_FMl0*xI>!N!h20U`k!D}tH>;%k7$ilFv__yV9oBCxq!paCAx z<_eG>Km$e!kWnj{EG2nphGGF_5=YR05mZhkOGyz$4m4l{mD9;mQiiuvL?Odl3M`sT zOPI`=o-ip0D@cN>FlGh?LC_i@a771dBEU`>W&w}hXn=-lxS@_$;YU#=02(L~L=oZu4Gsyzgg~PO7nmTuT2TG!sF9_l2_C@##~4@$JWK@|$Uz86 zfNTei=OBaxK(@mNiohDd!&IPABCsluRVx_HnJW~;6f{BYVsQ9Fhl{{*E&&-X0>=|G zWVi?%Cz9X+D9}g&sPbjeWUf$xL^d>zr6I$DGN5ibgMzFASQ9iNB9O_3ks49MASVhZ5#X+ek>xapzDt{@3&#fn43AWPIG6}UlS!Vod= zMm9xm1zwOC=)^Ek!N#P(DzFXQz-0lKQlN|s$>7j@1m2hcSuO{vd_kEOQu*>hvb`qL z6edLhsAAY?5eujcm;mYsAPxT5WPuxf3JjoCBG6+dOtKWj!1V)Y$*&-Ur31g=Q6o!1 z93rNYr637mDP$=KLs&BKV=E-!2ce*}YS9O?6a*l0K3{|bxa5~eH#c*+2cOo2w^L7CUXoM{TExdvW83<+saQvtKJ20nlQQfz`pra&G6 zw?sini*gH?6v0DxU}u2()6jGZZrCdFK@u6bZLA2oSPDE=10MH;7Q^5cH1wP%0r==3 ze2fN^IN%L3utku70v%Nap5K5p$e2Lk3&Nmg@f4&XK(MnwU3E~mf(a7Tpt=OK2pbg4 zpyn2=enD-Nv4C`e+s3S*m}LUDjUmQ?s~k{ZW46nnD@15#1+;Mt&y5_Qkw8!v9hzXF zrwT%6;lb@(j4%gfS@3K-s4>6;$+4ixd`MV=n#-V|faE6vjbtVVP^GEBB@NkH&8;A; zz$FcuP=xL%V{%Xs1g(H#R}h4a8FGUfdZ4`ykZtfx3jCnu%n5q^U;-3+5R;%|FCaZUSxTUeCTPPNr0u|T1U~ixG6ZxK45%Ig9WVzv z_J;{ncd|IXhwq$WQDD($$hBq!ZITBm1U0ci8ez2IPX<0JH;&1#~tJvM2{=W)|Xl$T=P$L!bjdkfg*6I^EAC%MmnhpvwTd=@c|y zpwGB~(VEc&Qs{AHA`QGo|04=Ug-AY=BRq`&H4h`;QfFl}IOmn~&*MO=3P^^GQ5im0*=)_jYa!GI@ zggQb&k-fJP|&`1@c1Hlq!WBk7kFJWWJC>gk`$;;11&5C zg&yoY6a^M=`T_6hXeA!Bj3XBRo-qN6g z5gcSJMT$&3+@RtMgV!7#$nHb2y;cdPZpF1U3vR z0B$FmGdF_4H1Gq=lz+}#RfDyFy7!+v@ zh|Tt(1$2;8tHG1IpjsSM!9(H=be0#0$7sd`8t*;8m?h8%890X64>@Io$?*(B4ur`9 zI&1^9?gdgmfr5e2j41)M>yyP1H0A~x8U^k2gX9#*qBHOc4N%OofDYP3UDC~E#soT` z8B`3KgD0S&4g-ZXD2wwbK({EMk6cpUXz&Oo3;0Mv9QguVbHFnL`1Aybb3qL~&_ou9 z2T2mp#vMlb7eJm-gp35CjBm1of)r#7sBNmrd;nY@fT9Q_CX%JV4~ulLTR_PaoR~l* zI(U8^e8(3k@IcLQJ_Vj^Xr=}!KpJHQUkeDXb2J!>%$Pu4fo5MZ(56ajM(~jlTnao{ zN?eeI0Tx+~Vp*Upxr7n4nu!IJKo&5XF?uPmfOn2_Kx!G-6baZ>(3$uRpeEE6hAagh zsN)&H>3~I(c>^OTS%BNT&{9DG-v5F3TtJqZSTjf}FgQwsYGE^25eA-&2j_lpxdIJq z4tPHYRA*~4LytcOSM1>SDyUKcHw3|L0B}tN7XmjIz?BhP2$aykWj>_p1M38hgh0~# z0fsD4CItmAsAK@2X(+D94;%7?6uRIRCn$4+i&=2cfTIuGI0cD=(-frU1I05W?i-ju zfderCH2R6q2in34Emoi*$^y#Cpezi^ji7BiEE-HHN}#o=5dADg0`EX=Cs3h-#lOvu5fz~RW`2A(ehcB^!YLx>ZJ|Fn_Cs4T#E}}J< zL=-@KnUF`1dBL7`#I$GuBiL-vDG;D(M;1*+ko!UT2ET2v39h)&=DIJu+$Wj7r0|mGFAj^j!=7U!yf~Gz|ok{3=GEnUX8X%ki zYM+A+5H!eA5>)^n+sOhxr4c;R40Q}h9z4M zf%pblN(wN?gZLJpwTNJQSYd7e1&|16RGY;Sq(UT1NeMh?0Lrx>IT_G`KZu-6mXZpJ zoC;|479yvTrKE-;rvn->hREq;DQTd{nSjQIA#x^JN?I^Ekk?Ouru0}e!Am0NfR;pp zvK=V zAv!EzRT5cB`U;3X4#+HlEF}X4&|$Wagai`e$Wk%{FHQpsfqFUi{pc>|j!Wrb<}_aAJg}L3stR$J6Exq;peO|HGl8laG0>5h z42q!fbpudwtjG!uIYrPl_K;C|2?Y+2LeN+^xG|*24jHBw1+C5pYvBMl6BQ-F%a%ZD zxfJ+76c6aEU(oswQ2hk%!9q9aGJ!Vef@*p;1ttOb?py{X8D1u&1!16K2iw3D>>w>A zA$Z3GlBdBD0q=~1#6W9E7(jJN2go)~@C6}|I!S>IHt7v&DS~?cNaL%Z#gq_RkcOG> zFl9la7!~LLSOeN0bPs*8Y*E1 zZMgv7)B~y{K(z+AQUkADK^w$}jAY6{(<*ofQw~}xFhPdZM%+QM z3rY^KnGNufwD5!lihpoJ19U?b@=_FLGbT{21Wt6|mHgnO1#V=3T9lY$?XZar+L#ZY z*MNjDXyplr1xX&D5CBbNfk#8(Bcb5r0qvE6j!y?C3Q)fka&SK=T;RzA93S9*4Jb@S zpaY}e6a`+T1PgX0@a6CPAfrH)H`5s=C0@{k705jxS4hLl5qSl0+=50Ea15-aO;43Ia13MWDzqcNkH1AAQn7v zfS06!H+8&V0+nZ=d;)Kz$$=)Om_a2x+y;opz&Q+3>w_v>Pz#^~F^Pkg97+gEgl7w>$KPv1Qa-+^Jt<9>%2;ImD;KpO|4^Gt~QV!;QOfO0ly0UD#@*H+N!GTZ{EK_|(+Ro?6|}Sz zyulhI3sDC-y%cl`C3Nr>e7cGVXl?);=b%bcgNZ>}i3Oq(a$^JwXwLyFa%6!8zqowXF#U0Fgt+r2q>y746+zc|GDDLgBq+ey3&Ld9V6s76>Iyo12bwI;Gh)k|ilAh9 zf+0td88j~fju9pW#w;ZUM;=GeECG1JM>>m8t^*a-ptysi97sKlns^u-O+XC}^t=We zy#puT1K=CRU`lL2>X8fq9i|Uj!lT3p4h-&N*gXVF5iBL3>rFvTW01KTObmQ1j7&_R zQ&d4Sdmx8Gujhr_DT`9Qf-(WrEM;>^@gSR;;g4|e;rNjs>FM5!!kVY%;L5EF&&cFfXMNnC* zz$kDQRPLHHgDeLRfigQ@0L32Y{$pqr04db(Og_-SAg~9d8njp70z;M}=rH{a^{}gs znFRKNBtgbHA{F7njEwaP3<`__J)o&JMJ5F%es0hKZ{Q=*dqHCS+~QC*;JqAuATdQ2 z1r~m8xZZxS7+5bTl`Aj`^n&c-=gveNa)t1!z+RAYaGyh9ABYL69>Dnxe6cUH0;2+h zz;v(#cw+#w0)xN=2p4po4Meh?4bLx!Akq`=7S!U(@vO(0u|86pm~3A6wVVv_=c zz%;O4un@!;P&ouq&OH@1YM^IrKurPlcp#>L${bK)Q($rgyO@5x3Pr?dw6R24L_Zz4O0dbT96ZafcXE8w}pw0q~?n0f# z40aSF#8G&I5fs|4;A0Ay1$KiR2x_b_3akY&1r~!y(0yl&jtmM60&hT3DTO=apDQs5 zA+BabL^H@SAbT9YGJ5hd2&@5_3NCh76hJ43atO=>i8zWlLRndk0&r%w`hrO3|h$e_TS4Uc061$IZK zk}S}2CQv~Fu40)L*ahZ*TwkKd0lin31zeUg3akeS3(NzNpsli?o2t1Kn6s6*6j=Rv z85Fn_Srr%+SroXy^ZQ^nXfOg+)p99tDsU+f!SYy6Xb4A1y;{OB@Sst76ncPRs{}ekOu_Tfy@GzX9_H!)2krG?gVDg zJ#8Q_vnntuFlYON&b4BJ1PMq+U?oT!Xf=ici@-z>8FK%$`bJLn=Q<}xJ~N9GbxM-~!mpftds#No)Oz*3^bQV0qoRt+W& zMHWzZiUG7>qX^VzU{z${R$v8f3IPrIaDv*?oS;RVJPMqk>+d)~su@8kElXf2$Ubfb zMuF8J2B^jY1-T<=*n{7aDd z1ZH1eb_LK*H3m@i0=fKM0b8s=0~C_Rpea>>1r{Z)ybPcig#%mIofE*@rXP@sXTCCB<=Q0`;}l>*Eqpmqs(HJK74qR6}1if{ll zoIpt&oEN~?LNS+sGa5XpGiWePV21WSAZdjIWIN~z2v$&-&0vOBn4o5Y5|<;R0!N7w z2O^n+6E1@SmjVYgnR9@WIWy>FUk=c)3+SRqR#0jO-yX>UYBRE!G0k8GG7vB9z&ubyBV&*U zCoqE!I0qG%3>r*Rz=eu8FAJzctH2DYN0b<|LAMJ)s*o(~b%-NJmSaN$3q*~;Hc-ZO zWKd)QHR>2Zy-98mi$f9QLk10|1ppP0F{h9EZp26&&*&}WCWF8pg2Y<>A=1N zjZuKY9Tef9std%Q0IIl|F_I}aH#nbxQw=EVfC{P!AXh@7jzxhLl77IdAh{6{ji4Lo zG??}nFoN7Yhgo0?NC-2Bk^{aE%3CkPl9!EDBuU;9`ZwA|pHoSQI#+VjOTWF3{zR3XIvH$xLR5pAD6?@Q4yVxV8$2tX0N9HnUwZo~v z4BGCa@!v^qV#taWm76oQVGDGqfGpOtbH^!J@6)aMM<8)+H zU@lQ&MkF}!oEE47$_!0#%%DP<1yr$uuU-b#hu{PUJ~)K~$tKX*ypI3n&6o~=$^uq1 zCUDNen(siXc0r>SO3=MfGN1uF(5YjfCM!63gN~F?0f|avK@@R9hWQylqwAoN8Bh%d zy4DeD0(i(z16{2R$OHp$tRtxfP2q!fd!ZQ&8vh3mSD_gVT1UwM9;5-=1$W2=22g1W z7GnUeUF0C7SGBa(ZjFlK>D4^Z&VVFZQF1duL}LU^z*0gKN7=>mzv{ksM% zz5ql07O?mV4E1}!;u|p39|4Q+z)*h%EPen({S~nI2@Lgjz~UD$)IR}>-@s7+1}y#n zL;V-9_zMj6f574&Fx0m&fx_(vhWZ|`cmor9a_eA%L^ZVb0RWGA}Zh2WhT?&vOJ7f-qa51stMlMNEka8gqdU)v<7&1I@O8 zN=*sS`G(+{kx^g+sGw8;4UvM5AprMCLA!lGqXsO}pb=FiR$kCh268zlUJ3!$HIs+ecYapbeaFhof)(syeVsc~y4O5n-D=|YxiI^Q3A)`c~ zlHZBJoJjx_$!1J4u<;Xc(;V(k*l+}B69%YaR$_zHDeT}n1-zmZG{46z03A$%OcgOG zu|oRRkTwB$o=E{J1R9*?Py$zqpl%$v?g7^}pt=Wq9VjCx_$By3OJ!xtz+=FSC7>In zLGzE`0VO5SOotK!II18O2O}t8BtX42(5^UkNaY3=1N9Zaoo5zMa{)9=!eYk60~#k~ zsRs>YLfc2ouzU+@BEXtOjGz-cKmttAHUlJMg3h7R zdOm3Rj}4SY6qup;?-M&CM?J(?$Uq}F@lk8Ak;#{r!4b5|7JbBr32DR!l(WF2sEW*> zQBFt;m&a8JCw` zfgNfjhXPxc5}N|6C%C1}nhhQr1huI_11{{)wj(RI0y9LtBAWs$IEk}?u73o#)j?xz zYznN|j*Sf*p1k1388c{-jX{Y$TY*i19W?l;1ZvjHXDKiU>;c&i=}UuBvA}i^AJmNo zMFBf#e<2&__DUwlf-F$c#scXbfbO|dfc6^=%j8&+1qlyON(DI=(*0&r05zPM z%s^dnaB;Z@d}}r+hM^r!u;>zyC};^S6G(IkGYWKqu-!XGTEdAqtGJ=^D^bEvVFo<`*diW=PS)-NniXE{d3-!37R+P^}=a02Dx= zp$*V73KmeVQ(%PWHWme@EYMu20*k;ZkUG%ZIH+&t&I>-6mc@~|(2?1lmkCscfx;D3 z1Sv2>`W2v~l@%BjSh7KTD#5vgQD7&?5YPxFIE^k~R$$BqC1ie3Y_Nbc9;gn(+NWa$ zjbwo#;lkSwU^ zn8OS*4?JcygBj#822d76>Psl$U2PgQ^`!)PgQ|%7V00K}FKEF88vRp%&iRAJ`kIP{^LTf?#CrWq$0?k9~>?o506KK2|JW35}OMo`ZLQMzFn?NdYMP`KA ziYTou&>%TvK5q)M61buR4XI>jWhpU&x;3CHlb^FF8EqE z*Z?jQmH}Ll9SZQ#XD|=6Mgn~9sv~2Wz%EE}3R)XaEyj)-7NL-;V_v`UlNA zC^A9Pry{5w%LpG)hBsG1En8?)7c?jW9!g^Z&lZArxgr;skS3`TTq{aT7pd6-x~5wJ zR#bpmx;vOb;S3tz1r5=F;(`U%*i`_}Ub28^=x2a@mkloAK`vKdaD*f)UtX9Y^=3>A z;LCtOEkuZipk<;0*zX6J9qYk;^8?JFsbvKQ0kD};{M@uIGjA|6GS@RXAetPYNqwaG zenm!ZNbtd0^q^)n3E2bB;(=@hP?H{1loM*!E3qPHKgXIZXp082A_uZ;0$SHGf&!97 z0X(q_x>FjofLDPz%aK8WF}o0|k{RJ!(0ml6!c<@esR3OAm94)CC6>0iX#6(8vIXA|q($4hyKy0&2T~drhD=He?VSxqMJy zh0iR3x<+7UD8WbT!5s%g!C~yjZ+a#c7 zKR636U{+uQw;4gDH)u$i4LoiSl4k|o?#1HBm<0-9P`@3tj`hF10*m8+c~B?l0J8!! zw*a_-ndMjyO>5v)T#k$-N(`VfBD;v23&K!fC1mnT5MUCt-#{M|i(^G0H^`N`3@naJg^rA6a0$jju(6<$k;SpD(2R)%tWbjq++b#O=jLWmU;t@j zE_CHq2e}A5Yy(201WJz#;N^x86TssD+;SjwjE6AxI21``J~Xm}hM3lYpRZZ$@xdeAyBNGf4a zVpd=TO=^N0<1C;>BA_T`f(9NW)U&uPLF??890kf87(l%rP-}q$l$aEl92**H3Kf_g z>)n)?q`{#GTBPJCP@(|hGJyPmjbP+v15FUJfG(WmU~qiUd#Hf{#5RGr4m2;#u-uUm zvmie%^ufT#0lDg!jUCjac9h8i`4zM}`UvP6RnS$u;M;{k zOV`gF0`HUI05$nRM}(dLEk{#i1WjKv;nlbVhekHguqr+qzZ}GFBlvn{d>S9%(8xl_ z#uYd;g0D!%XX6wc8kq>$_y7{l7@-P2Ru`X*d$4N+*$2B9SAmgx3(^&E=qmz|69XuF z=rW)t2S&$>he3N9gawX+qnZIU!o%oz6fDRC7X;1bI_?1ra>51KK%>4Zz=9%hK~TIY zFgo^wg*gSzfJ_A~CUInh?0bMLpq&Ad7T5`rlma!@866uzB944;b3kLhjvqj&%25z5 z2nuNhM#n2)VICyIL6;HpfG^eN$#Q%El7<@2t-vI(3uFzrJBhp&7qspcwElrnUE&P_bh{kt5_f+pfjsL zBg+R^8QI_`G%&!+4Uqq`6c{v_83bN~{0{On41;D1K!=HdR=$FkUxAifgW6G$n>RrV zoHdwu6j?z{DbN}qaHm2Eyx9u8YX)@ZIcO9c)Sv;?vmj#x-heCttq=tbyMQVa2GDW* zOrTM3P$YuZ4=6B!*5ErXIRZ+Ypn+Pj#0*$P&=DVo)GDGH5ca0SQ2^oM+Hv z0K35)yds^&5j?cQ3Msfjt9L-b0UF0eUAfK->J1@Qu7ee!tz1W1w(ckhz8Tn2Op)19 z%#l$5#ff}bAQ#O-xCnIck0!$ugaCskLl2Y(I$VU=jL8GEMB0qW1(fg1Kn+?@(G8vy zW^!UOX95-Ue?Zv{5+NTzr*MEy`T?D_ZIK184&=3GP9>LK9yW<=*PXZcBV?k&Km1ywG{}dSbxxsPO z3Cg$(+~7cgvPHnvH<;jnnaAx6<}-lzZZHa*1nB}Vw`LSL1!04lC<2#3Y;X^YQQ$5T z`#OlteH&@nH{w=x(AXw;P)-4~tQs_{0~$e4VgWVvKy7_S1txFM<{}PIvEVHYS)2u0 zr3=~)0KVPA5ghK|6$>H?;1&sk8Iu4gxR^oJumCrxzYm(I0^QVp7L=kvqcs{#(2Y9a z&;*?*2^lF>V1V5(3r=*PZnGn(g#*s!py4r)y|Ai*AAbMsI*{jJIT}HOc0e+K3lv62 z1`o(!EO@mZcxr-0i5axun-{t;ksKS0*z$GJ>rT=mNzl12=e!AS636x`Ni$f#Qr6vKc@T)LloM?g>4H z7IMo2IL<(&0cZ>!a>)p&00S*u0w3?h2wvlfdX2XPXyjE7l%>E^ge;)(YH+lG7J@;? zRiF!L;hSthBRZgv0R;hgkray~BJ#kFhbH@Y$Sv;BU2LGlmIc}w!=S{Pt-uVL;a~&} zh6tPiMFnV2G6QIW7(6h;nguEhAYPUN4GM!AwBSWlpl&Lt!3zrTu3Nfi8(+Wdk)Y#X-6(aNSBn!al$zUkXM<&=7GeS zK?M*;mI8a05{F|A$fICIc}lDxwK^5!3xopushadDS}QI`hW1czPBQW0;?jE0@zv5boZD66dJ6M9Vg77 zm}YmZ%Ti*`0N=qp$`;U=BrhryIsz?;gjlq?*hB@1Xxz`#~RgDtVJ;i!h#M-$6v zVsTJlLTTKB$BnU+EKH+`Wi+v%Cl(GIB@5?hVi`>==!u0DM`8gjR~&8NBD%l>(siaw zn`IK{$R6m~Q&`4Wz9WsX3_vvm>Z5|jdcbLs-4Q&n;m8EO?GZFD$>qrl8e9X7`LUyo zP;i2d1^}&CfXrut23y#n-DJi>bhV)2GX-|gd@MN1S&I~y9I+2)fck+-oY~+Wpb|S| zID=Dx9Xgx=l2zn{>@if}gbimDDX_yvy4Vyr71&XSGuSbQGa85(&H#l7Xs8i9egPUi z0k;o8`w5iTKvMvW3ZP?(AOl+jxdR;3=mT18 zumLT$EG5v;6L>;v!Z`-SfEEX2oC*}im;+j%p(h0n1$+ZqY@h)x&^8OmfEGJ=jDj6B zbOMTh1y)GBgGAxOPHdn7EjH2zw7~kn!&PWwUq~j`XDNYIU{3+;ptaO&r~_J{gI*y) z4U$y^O+kX9gbkJgvJ~J0TA&qNga@=X@G`O>jeN2}j(bsH0}ak|D6ly(f{z0Ng$^+o zJfg0^0-D+bP4+b~HV1%K2C_Ob7J}xem<67Lb2)gJ(w~El7GyF3apMC zWl9{5{~Q0X7ZxdT3VZ~q2B$w31vW;a*q9&_HjYw6j%g4qwC{_$~jKJ z)W-vrQ(zJJg07DjDu+!UA5>0(Mc^yCK7Iujfo~u|S6(3)Q;`X(!Eqv{BLvVR7o7FD z@|2hzxpJ~W$A&m^74U-Q!a!M%8N>n2mc3vHt0>@QRscsSlm|NcZ$U2`lm|NE??8(! zln2Uu4Qn5ec??KXz5+zDZjuNE`OpfxUN}y{Sijm6$c$UJFubH9Q zO@UM317V{;^YK``2o6G!gB&M;T#e#bS6+}67^#HR@WqT{Mo3(Mf}R0Ha0pBUO(%k9 ze-%KE6nF~q5NK}~Xr3Rm@e-sAw4w@j;vQ%<8mOLQ(_j(-Ptt;}GzZxPK4TlaU;{K; z3tDZ;hSLm2P&0`Eqz;sI;8QS64BTOe)n5YHN{o;?3$(mPgNegY(T$hEaSAxNq`)(U zj!(dx3m{Tp3&<-B;N7zf;G^>3dtMp17a~o&USNPv1A^y@K#M!TxtiJW0mvZGh74v$ zMbLaF=(1+88t}C5IZ)UrFoUu+2WVX_NY)X2wj(HmgZ2k%fNo<49gD#%p#YWzPjV|V zfu^)|Kr3(|GvFGaRgsQ7SqjXW%o5-r1MSuawWUA?fp=ws=8wUr)`2$SL(Br75eZfR zIzt$2JmiFB@ck(wkh>8f^2kPm)}DZ-x4{P)A*O%9M_7YS0ffzeF)?sAVLd|@oCU$# zP8oC=7(hFr96OGKDrFYv>Lsu{K?kUP0R^8U3)1Q(l%-KWK+@3FOA4^XOW>7a@R(u* zEh~J<1YXMxwwH;Q0eo}?hy%jl8`G4S`Is0OLF=(V^JC1QyU~~w7&RCeK{>hvwC1P8 zv7rIf(g3khuS8=4ZK7oXovsh6=4wEVf6$rBYd}5{mX(r0CdA3XcdPelNAFa zXvG0OJ)ql~Ky%zy43H(zU_DISpgC*DJ;U;tfU$PAi$204bo-HHK}6dV~rGp&$C zvEUTT!0pJ$RIk7QO8EkyWhJ0CD%8O|;KaqE#OSD4paeO`8nj_K8?<8qwAL1M_NN&W z2X`$>?nPR=30|!Ux&{ffCW_JVF35q7T!@4M%5$Lj;K_1)0g^*cC7?tAIt>^khgdZS zT3Z88It<+NU~56Z3n@Sy8%TLRJ1H@Of)Jb!K?^+~7Q*&QFv1qLd}U&0s%NSL9hB+# z@aMGpEa;*d2FKQgKT5J3Ctf_14VpD)1obf;)3cNq9Pcb`smxVia6I|#9%C-(kX+DR z^dM;k2JrG`$F*~ra+MfBR8F>|d?{EM%u`}?oKv5hr2sN4-%-9SOA(w+8P_;HVW@LT zuTf%l0vTGrT#3Q4CKs$v0dyJzSYCm-Mu}O0*=g-urg|kXRafg|-wqZA3DzmGI6Yx# zbh7VIU~!sLUthBvbYc?oaz)VGJt)vYCAPp%P`2bw%}WI(8W2Un}W=y;z z89_&>Fl0G$f{FpqWOfmFg|#DRDYqF);)GT$;A%vHLEt6Gt)Rk%1HI~a0NGgr@fA9$ zz~~6}l>(z9XDP(Pj$%1V%#J-L4m2=;Zkgacsa4X9J7>17#+N6QS;52aEr~5a$4k|H2UG z1dIQGi!(#b;c{ez+$Raz-Kxmw$fL-_!v%^MmTW~vM{Y$X9?q5{u&m8Q6Luo4mD78f^;9jy45roebJq6j(qD z^jjc}6;Ry+&Q=;skc|wQOf2AyBaV>zLV?koi3PIF0UQzy|NgTVI&zeO_bEVXW=8=S zud#`x(2>ENn}b1t!AYTGIfS7BV;FQS=VoP4U|7yA&EUxB$m9q*OANFo3v}?0C+PTm zE>CH0O-9CgM+QfE1%`C+?WT_M-qMcDC5{_Fft{tv%%H%qwgzmvDp)0`n$Y1DM1lgp3QZE)UAhJEUBI9EPZ#!TBtrCB63e*&WE*%F&lH*;l2sfm0 z1Qxjn7J;rg2a6m8iwGd8*#H)SE(qtA1aC5d91{sz)&^>XFoEtb;MM}kFhRw@$p~_v z2NP(EhX7=-2yzbxw>YR#QK7)#Smq@SiapR4owBtp+{YLhnd%?|IrWN+P7IJOX9zzc zvlJK{IkWh9**Vx)nOT?^8F)CkxH-7NnhU_YC&0`EMbNrQFf%|AbS@Z}xuISW)QkbM z9TXXPm?8QWfP|SK>jhy*;rYanHU*3K=IUc1{6=oA^!O^NQ56L4xWNVpeyyk@pKt1 zB7~%7FIYqjNn{mR1iH-ttZO=kNHbUjx|aZ~<|8=1p(Z0O(Qg1R*%t)GGH6wqqlf_b z_9yNLu!trDgE<3eeK)AN4@w>k3}y_VXa=>=KzH4Ptzky^ z1;LDtpbLUQ3nZBsxcNZaLP2}~K;g>(+9}1Tz$5@ZtsKMw9qZTxT1pM#fMlA%93iMK z1<;8BU?Co`DuFgIM*z%GU{+ueXh#?5Ko{r)3qbXEfjKf@uVHU%LHBfNfU*g= z(FV;0k3q-tfLny%od)oO9YA}1S@@Wk7(s0o(2`cro;T15?)vV$435l-pqq^x89}EK zIeuaUHCdQItwyK<(0CbRmLllb*!nC*Hb;HP;YOfw3eY)zptbqTOb!Yxjv&Jnm_g!T zCfHoiv9u5|B^F10(6&Ej$AB!b8tAIY{q+#86sS4K>^L8p%i^d9(!%0+p8-Paf_lX) zir~}mSV6n{Kx3!%SxRi+Eq>rd)bJ34CKE`|z`GBQ%#KV7Okl6MNh?B*v$J9VZR-Lh zK~O&cvWE@SWdLpe1)XvYxo!ir_YYKsGBI#31+~7RlR%hzbs*W28+86Is4c|gDGj?^ zjM4EZIBPX z=rm>pHh*3w(1}N&W2!(Z*g+`)9Ey(eg`jQ;C@?r6M}@F}=2<`)Y#}J$gC#&U5U9JY z0J@6^EX zr6X$@XiYfiEDA1=6%2|TpyCp=Y*~T11hj3B3#5S^qz~$71y0BM;zC6(&`=K+$s))Z zzF-%EPJ;n0&Ifmx>%o^SfTzA7V>kTVj;GFp3R-Q)4d+023(SG^u^oFrJV!yt1t3~r zB}7z#$x$cE@dqfggX%W$&OC6N0=~WD%vtb|E2v4zV#cJQzywpR0v^~_fba4EE$~$U z_5ZUR?|}3O%!gXRsKDj;2P`rJN#qT(hz&UY72rEA6kz);Ky5}wfq5W(kj|gLO(ga` z5Sx3e3?nxzc{MO1#+n#)8F(OLK%l@U4THNW8cYnlpiK>|j-dNnAU#z!(Bumnq@l?S z8c2vyU5qc&)XtjQs<3G@m_l4PtTncQ8jG!&npv1=wD(H9=K$q8ZW-0MPF0)tQ zRp0@QHh}K7R|K_Mc|l4MlH6cPMke}|N1;FasJXaO0^15w53Sd|4@qN~8D1YW$)=*U{8#0yfu z;m^y#qZ}l|o&#>iDsW~wvgc)iRDsSsbYv}4V04rRHJ7tMZesx# z5lY;SEYK|}oUXiF3e2Fn3=Poc8#5*q1!mA$lnM&WjyhS2te|)X^`UqbxD|Ln861?! zm_hrRdBA%cK*bZt3mi(kppkiI1zyMcEYQFXs5k%}(hRyU0JKepgWC~w;SnSaGP?5e zgAOtR)nKlUj3r=0VYd>RKpbMAzzpgf*eGx~vVjgIV|KL3QshzKaIDT!`K}oZuMbQ~)iXaI8~c1fQ3r zzzZ6f2c>33aP-?KGV(BRbE5}1Xo?6F;GoTlFeigUA7r$GA}5H_0J)75!}S`VoWcz% z)|fSzbd(T|2dz%vG-J|%INku_cs2!uyV*geDxkU>RQ!Vu;e&)H$T(2^LU3zTOd5*ZV3#U#f^r(@ z=mF6DF$2gazPvmje}O_CH1Q2ipNia|a*P{PJE2MzDROheR4Z_sF)^T~M;_2I7@(bh z%ubBvOh{>v0knCL8MH&o2YdpEK^ACJAv5UgS@2aJpo43f9Tl4798aJw9Ww)H6o?r# zS)^djEC8~>1XTJng0m-t1uYAqH?@KC45U6}hSYxw-~tpZB(MUJunAR&3ZOfUKx^(n z+R>b1V9pHM;iD@1 z4U|VY&6o@zyb?(MEdb|HP@Ap-Qo%cd_6URP7qFKcK^GIoKw>6Bf!Xl`184vQRPC<> z`4SXV28z7k=^W^lU7%hcV>U>_LWvW!^omIVbfWn@uyXKeZJ-G$Q2E0M%ITc20e`SE zP*n)(G=Uueb~~g107nP7c?GJFU^Arx0<$Bu{T%_?KWfGViWX>Vy#yRr9~iRCm@>djP|;cdjW*O4 zIHv-)BT9Q4M`wUe&H)vD=p6!d2ZCBVu&_gBQzIOC@P{KP`Qr{pG>1FFXPf8|rdL3* zjmvF3sJ*NKcMp1$QX}eE@kbpg;WLYskqg#sG=T36hjiCjL2YAD1BBI)CrgnHbV31x zBKTZi7SPsRN0ux|dy2^cvF(&cf!&uEv}T62Oo;(>K|OfE47_Mqf?PD9bYZ|-RvBQ; zFm}+jW}wcCA{S&?2!j#>Y#0M{8!WkDIPU;&**0UoYk0Tq`#3M{bV5_IG>8>r>Xf*7s!14xlWc0Zn2lFbS*z*Px)K&!DZYpi8nOvK&RS zKqHULpi|z!%VxkgTbna;z!%Yg4i|wekCA~Ma?Y&5B*6j4%tnc1DX^I{fzEgY&v1h+0$CqcAtPDbkth?$uwg^csN@k)W^!c1Ix4vZB!@97iG1rM1NTQp zMrK&vC;f;H&@ccC_^^)u|3OpU3XE=!OeLVB`#=;cxJ?GWVHF%SkflxvERIYiptEUk z9NYn!Iu^(hmtSmq4>MIQ=n!md=6G9~0;lYH<1kACC$VV`U9QZ2cG{%92^5)ti*(L_6TgX z&u!E!2hGi(dKOd}F@r{oKqV%)+W45sZ;Nx^aGgHh0kp3=67Iat*DEWa-OaWbP z^%2yC1YP|MTI2y5js}^<3|gzmJ>2bMV&E=ARPhSgO01BIUx5{}5Rer#P!75&mIHKJ zKX}Lk+Pq-}Wqc0M*aHWw#ls3&mca}<1DcowPxXP)w6X|lb~Z?s1G4=L)ZAhhm;*{jpuq?R&@Bm|f(zV8$O4_8 z+z04pJ!5h&)2jzoW8K6~v(DRWPKnacwe7h#}JSTAK1G$kIY7+~n zum?}rC3Xdl640nO=w6O8aE<`Gg&h_Mpq>hY0y}hM9wY}o4+hkS0$*4O>M}8v zWPz4VgH{`W6o6_3cF2108t6UfpfM%T+9r@U*+KOZNE>9XgrD27<05EANZawn1*93z zJ?xBv^`O}}&_QdU)|mzq3+Q4$NXQ{bkhfTrpx4^6g8FcvbErV47&|hTKze-~iX33i zf~KV$85Fr3!5tw5c2GBu0hH-^l)wi{v4f_nz*`A9{CSyCdU>F{ufPrKCb2t86v8@s zj_f6h+@KLBc96e$6c8qHfh^_l=Vie(i3?^DkE0~QB(@SoF3@xluOovZXoiX1kts`w z56MIxsEMqYCi1{c^8P6B_SlY2|!Kc#57R=W}=Xz9KuA#5=8-s+t^V}f~+j_=jFmQ z2|flO1WOu74M;W^v_Za%6C1Qs8i8ERxFl$87^uAfI$R!f+gDwd5-W672WvJcg>phyb?|`W5M&Cw0;__6 z0tTZ2mwd95@`P{bD0ub7UUpEL=ynQ z0xezw4T*x9VxXK2x^D{Np{*tU$R9T*lXBDe^0DDzJc-pel0m zut7$(c@(&_LAOwV)}t~g^6@ZoJN{=>;BaIwEOV?ccKpX!sK5E04)@91TXysm50pm5pD1U zAZS^|hfB}}c+8Fsm%&U81!kBI(0U`#`U22V%b*olkWp=BQ1|E$NHJ^?p5qk|&r!nh z4Ty%-{@_(gFrz?A3T2RIA3>JyxB|8jG=NOdax*5-Djbe1#}gn;aGMzv`9K5ipw+Jb zK{XFoHb#IJg7Q3aXen@lR{nrv7ZM3PAU&XP=TrbKP*dOoYk_1`P*n$xduULDBNLLN z!5t*WA#}|oRF{p)k>T^tYFI^SpYN{q{s(e1qjLs zpp|a*plkwKBMr*C3S6M#i35@ac%WGTl+{5AADjiaKrBTbZUqiSkkO!;F$-*BJ!oYa zsEFj^1?3uW7T|MaP~e5QMT&=s8+$SYbygHO6gc2Xgc~J^fGq^aH?nDJ6*jD(9f{1KQ$0XS5J4{URAQA@ z;C2MvO2Z0D6QDLfXrn!&w=}5Z?#NyUIz}Hvu`@d;aDr}-0o79spaPXi8nhs>ff00b zlp}kg0+Tdo60Z!h83o)X1UU(G^Q5N|hjf-M1IQM3kV+1)$`Z#0$YB5=879zTM#w%d zQ2SbesR%SI!m0q;-vw@|fcnj#hAwEoIkZ;-YAL{GxcG4-1;QoL7f|5>s@L$AfuQA> z%0DMg-Gw8ZmM;1gQ1vHois@Ortb1Q(?41;!Ffr@+q zb0*Nv3DB51cPZE$a5qy4JirecwE&HsFe%G^NCXXn8^g zF~LKOp#4VR`E>@+gb{-RXm*I;&L{>3?uP_#p8*ZkF(7sWf~JBOTmudLA#G3r+YGw= zgUOL6%W(xr8af*c+Tst=(gqT9M7~i5)NF!lnE;Z8Y5}D;@S-=YvY`8BKnDH+r61(& z^{8%m1CoXs2-<7|(((W#=7{s+85Av`6>+xDk`ysJ2`HNkeTxx~m3t;(H>} zZBL*v75Fq9B=dnt^e}cb$pU2;21s^MQDAbsaUI+!1a0iVYbB@D3D^b$bxjK{bFP z15}1#w@v_Tu?#kg!51@O_-6vbf+mQIAQph!VFNadfPX-j31J4)2T(c!7a)%084HSc zOk+5q+zyz zN-G6M#~zRv?n(nX-1St*+ax^(kRWYBaN`oR z@D$Y7M%eThTr+^Swma?zM2|OP@<|};!6L}!tOSc7`+XT$1li=- zU=d`WP6dk~>*@iEAg8ECun4lQU*J$hcHt+m2(o)#fJKn~eh)+BCRhYH1}}j{pe94k z<9Wr#$XX96S`?UIBgssV;Zd2f05(90&Vg*lZfd&FWjwn-LcjPa0WGN|9Vs~UJb2KhgV0Sbw zbYubxFqS!9WdMm>WdI%2T?FdxgXTs+bMNeqEF@~?C{X~-Pm*qJ5qL%vWGM^CQWltt zS)eXvfw`CkG$jjiF$>7uj*KNmjshh`ka;H1fk)s988l?Vpuj9}1ytdH>u>N`9iUo- z8MNpFG$98X^98jkKx1pnpkYZ?(84C96G1@TE#^Wc7G4&9&?SP*S&FQnF#u4ID}rZJ zAxDUSt^s6nd~z2wP>DDufyuF^FiQz^Qiu{O$V03!53xc$#0v8eE6hWzFb{zbOJM}< z{btf-U{qoQ>1TuKXM^fzgXw33>1TuKcjPEhU@Zch!UQ#iNr?$$3KPr}P|5-&1SXg% zOfXZJ;HC&bOaTr49{~BzQPA-Uh=$KWff6{huLqi<2X*v7okN0w55DCP+>C+^Ssg-J zRgK&$L0MG|8DIbp;4860F5hGZovnzrvYM#`bky8`#PWVn{DbC=SfxSPrNog%;3_Ct zfYzl!_i=z0fP$NCpjm6s(rBcW`XDaoXdCdTE9CA(0T;V+H|Pc|~PaW@bhvX3%s2QyKojH%W~e6^6xhHgakBF;!7p_M9j6UF(SqHTR|UIA9CzP4 z(7*t?NDq99q3mXR)H!mNgEh{c5Ei2Ecpvn#1w9BK;?f4hs2=H1BcV1-$ zCdYjsa~uya2)qI{++BI)!BrEpA|p&K56A@yID?7>$)^lppK?3y1evMG0SajzMQ+C} z5H9GX6v*rZu3+auGK&Lh)+UH%uvv1TumFuL;W9u3$p8VU0UMAEkO3JW0a~eyBjRO{ z43K~tunx%pDQ?Hr5H9E_chIe_xI;z-$t(q^St}u$!M+jac3cMG@`!=lrGdv?I!I<| zK+ReL(F`_Agxhf;gv%q$?Klt06ykQA4P^>)JI;VI1-KojLYe#^dksML;z-9PNcI{) z?VSkG?8u_X$ioXVzygl}Hb@3oKn>_cGJqRozyW+&$py&-2dD|1NG5QCOgMqh1Ro?5 zJfJ4DBALJrGT{Q)1Xk?XIRwds0H_HKP!m|eNB%kfg5)gFXgZ7I3x+I5u)HIyz;{UL zqQL|@F%W$2Iee2cIHyBvTgUBC^OzJFL6rup0vlxB31S-PkgWeOlQI<96<9z9vT}nK z0D{)2Gs5PdKvw`WW`T|-E&wewV9{X8Q2=fE2TfstjRIA#0&t@WKnIzyXfS1fj=u#R zf(Kpa&H_@F1v>4xK!L^a2SXOf!VCpwfksgOAG9_>gQ)^s(I~KJGFOKM@XS05X!f^Neu0Wy+>m|y@mh(PU7 zknIehbBMqPzk}NM@bh1x6Ye}&kU0s27ADY9T}+N=o`O=wERanMAe*qM2e-ahL1`a! z&kHm`gNhK?72n+80kk8aMCJ(X>Vn%}psot2cLKlP{tVI-E9hK)==>jO=s;O&GQSrEnGRaKx2$K-g1Aq$eDm=u^anK?k)hM64uA#+nE zkZD631t!M}Am^DeS%7EMB(gwfkAUV1LC02jfT!p!;4_2}OJyL3bTDZ!Ngy>WK_(%l zuRzBmI)ZmTL!IDg0nXvzJPn@Umr-DXWoZcoCP!$FHc?=5gl1?DgcIk0LICDOki#^< zjp11<>J;;9fZcXnT&M0(=cII88A)EdU+%$pTsN z0a}s|N_o&M0t#3KMn`xO2W@SHOjJRR7X|e!z#Ca0>iN0BrbCNy76t_dZoKij1LS6K z{{=*h#%mU6Ee9y+A;s$nP#D4Dbth6TdB6Z)paM?#3XG0BL24cOVN*JwWPvA$B_LVn z1Os@HG$^VOl@&O{NSHHwK#XPrAB%MZlusbjC<41c<$@wOg=sMP!1IF#YJPZtmLD|0 zSpZy;K#UZDo(BQW5ITqq0XohRnju^e86pCbA$$~=9HAM)1Dp*GfKDHQWZx4Yrh@{L zqehk^O3<+|ICA4pjWr ze`@>z3cbE&D?;dH9;$QIbi*B@VQ_3 zHGToP22&$wHWW5!p}+{4B4=T6WI`XUfGl@{u8@aLGl4e1z)tGO22E0f=3ZG8n4m+8 z%%Jfw7RYsk;3emX`+Gqv;Ml+jS|6XF#FDMV zssK7h10=1$;@AjYl@Ge$3p9Gf0vexVg$;s&Pw7Yio!_F#?4ZQ%)WBF{4%$Es>d}F= zRD!O=VR!mp7q+$ryklK~&9MP=JnJ&>@E#NBRCp%PUhZrqX2(WGPhRkm?+T2lhJpAV z3UFf}qbA74I5se5fsS``Yye*l&;Yvqn}-QJ;@!aLxZ@e99S6O059~$IVl8Iy{$K@W z&~7DGN01iKev)mLm)B71WpEw3e1jAz|x>;9Z-s4%0_h~J1Bk`1R(Lt?sx#S zw6K9C%aKE1G1zaQ;T{EM$3HCK)yNE>eH!3-rY}eW;1h1%AOt{1+&p1{tjXobf{!Rc zRuF<`WXFV0Ad&7yx-1T32IY3IU+9`I{+4eE`s8Q+}s6OqX1otq`(By37&EW zT_6WKa0z@sHHZTq#e$>AUV+1C-7)IctD+dP@EIk z0Ls#!)hp1YAm9b}Obn1i^O!Y2yZjLQ0YS$QK~|wavn<#n;N!<(xfbTvb)dD(pu!9l z!&ZZU_6ah8SA&37VX%Uhgn%qlV#cyAgatIk2VNHfKI%__k!F~tBcSO%$Y?xh@dJFn3#g_-B&oZgi*KRM z19fY+NTu)sqcJgEg;O9(nC4bm@Q zHDdy8yac%y9M#+kjNrvh;A{#%k^>Z#umTSGhT|JZ!|3SSJV71;wL>+SkoWU}Hibb; zx+O2b<(dGbEy|+6RlI1uF zGQkB}#wCKbc})Ydc@5;~KcMmv6qrmf4Km=}DWDx?kWHqbnJ`eaf^K30?-m1(s+%!M zfaeDVz?)6M8w-%Ok}@%HQ)4RtHO!#lA%1^AK@L7`$PvZ_B~92NeoPG9*(iIRV3V1k zm1v+418s7730nEgE^r#u+yOPbVcR+!Cxc}`QN)wwI0M8HSOHQbrNAVx1H@1Sb$Q^M zIT*QHnGt8U8o*bsfewkXVqk|RXYj>ypw$PUlL-_QnDdlaL46=*M@4_|Spck{2xbA5 z_cEZpy`YL5bXo}LP(KyWNe-ZWRuWkPQ^2JRiw2W`5)=4HVbB~qk0NBM9dvdLvx5RF z=yp6%%NEoWtpQz)$LLrOYW%Y+FoVwMgVaQzbLBu)t^#PmCulJ+=u%fk&@v4+1yJWe z0m27K!;akq?O$h6WKv)S<#h02PmmRTpb{0#RbYlz9ZasgEZho=ir^K3j3AGK_v(SR zw1X!&S>U^$`MDi8fP&aj(s9WvP$vX>DH*7^GGmf(WCVNOaSKRJfdw?7w&FENSqCT} zz+3j=`{_Gbm|5zX>sUbdz%qeOFn|O%BVtu;GFO_ST?pDs z2|8~9bcrDNh-vWV9MJ0Jeoz>K#!fg8tCzDBSU|l5$P65O=`xc7R~h(#vj2>Q3T&W@ zX%u)sRW*+SFX&_`P^tmnu?3pYhFMFjec1llwYS{kju;&=iS{{qn7BKYPF zXte@QJv+cEps8mNpW@vI3iQziA*gkZe9$_yga(yJ;8aJSQ=egx0XjPYlIg(hHc0Cn zv@#oWp*Cp93D!CXA98{1NNXkr?sZHo%=L_QjP;N)B=Fg>kc;OW89-Ud33Sxcf95b= zMg>ME)(+6!&!F`E{24)8^6V&PiZ9rg9V0B8U0k@lxYtrEKeW32*f5NNGmtpZ~h_y8C_CPpR(Zbt@?BS9F&f1o36 zAwFaPouCT32>?>aLVe~6Iv<9Ky9=qei&&x$S_;QNYaVov6eGyOJS8>-(4tS~oNSQQN^GDNo1i@oYy!QY z@(Yw0KqudV!UuF_FS`N|r4caB5z?B8s&BWxOzyqp+ z<;Yy9$PKycR=!Y?(Gj!`5#kFj$NDTsW>A}i%drMj2|}fq9YE_)OBC20>p^>uiWC?@ z>^dZNEfO1a7_lw`Ly;orrly)KB`#2P0y;Plbk16RmLljJBsQ=SP*osf71&avW9-~?qKP6bx56nJeR2S2ythqs_iBk6bpM8h%-ylcgVIPM3#${tWZ z9@^1FO7@_DRRXOD1l8u?TAKmVZpE@K8FWZ9xYC6lw*lTK{|3}T7JzR{W`S%=hMk$L zfMZ*-3TU{hq2UPFB=AB-&_*&)2Oc!Gq5v8xXW`BUZT@8dt?*=2U~q)01{d5QHfT*L zh=yEq%b)~4g`Nd8p8(2aprx;%!Ffua+`x3 z1nS3vhxlQ~Lx6G%L$)Jh35dZ1c7l5mXqhp{Xpn0`wF?t$Hwo$2cwo6x0MzdWot+0V z9khQ2&xIYJI|V?>1!jS=%4k&&ij0A;>S2*V?W+Db6C2nYg0i>g_%KHf*2H- z!JPmW_MtQgEXK#2H`V-W|Wx_ zd}a`z8NmllpE$B0_^cp#Rs^37#AieB*+G1E1fK(R5G|+|2Fmc@?gD7W*^CL~K~R8n zg8I}9-1k@+IqMx6Kr7b4qnMyMG6k?Rco`KyHLeC^*Qee(@>|)Gu ze8P|iI@mW0v~N!UGHeVACIx2DWFVsgGiZ+j=%#J3nP8`Zj&TOXnF5Of2dG)X0=ZzD zMUe}1d>|t?IE1-C_XD#jaAhfRD}XLocH}5g-~@9Vt@4yO9j$V*K|u(vuNV}#q?Nc7 zI6%Xg+>Vys;97!9kpq0@of11ZVtJUkxfQq+SRJpt1NC8HyE$1A+} z$P~B~*dco-*#%~UiYD+G^`Ps+LA8wnSC*q8$Tu8dVNfHS3)EHs^;W@kBILSQ21Rzz zO}n6=1D$8Azyk6w8|XAi(8XGu*`S^#Xpj#0%=#^ zbbJB|hAbWMDctp5ybKDQj`oF)4fREe%nF>22N*%;ayvQ{fr12btpHcHBY13rL4nJW zNnj?}6X1)hxS+GUTvhc$wG{H+L;y zf?r1tIvW~th#=~GW)EW)$_ytXyd-c1H=|fU11zA31s#123Pg6tdLLfU;YEy~o9Wm= zLm<%Ih`J1nj`oG%#3)|~2~Nj&P|R^UvXv-s6e+TU#(A<7!7VcmkQkdT1CyhDVG$_T zD6l&gfEs|HCJ;{vL@_g(VrGzH1x`ny632#y4-AE%z2Kl`fEzE90vo8|#Kx__?q~>V zwt`9^MHU4%1@NiV+zQN&6F^0f0;|9rP=tcg1_&##fHE(r_rR>dG=oVAw0Q<}nk5J5 z}3Kf`5nL3z2sUO7ZVREvnQ{bvm;<97v0nN*EIVp5F z**7b2J6Y9%MLS@kAmuF}g&!ab-+>F?K^DFN7ruckd<8Ci1zGq4 zT=)XA@EN%98D!xTaN!fk!bjl3N05aNz=aPW3-5so??D#c0T#Ad$ihqD!b^~a7r=!VAPdid3(r9oo&gu0fh;@)E<6QUcmiB_0J@Yx1GwqK%c8*M2x)CFg9|K>I*?Pr4IN%a1$IZ!;qVG(P-lOOYKk_XN7QM3Eg7IP8whATcITp~nPbF@ji(S&+^$3+RyFRz`nb zM#mOL1@>%3&;=DN-~)bJ7(rbn#P)F(P!}FFl>nMaWzSMzgU-u=Dt8`8VFqplfQvN+ zcsU22DuV|+co`pZz=I0i1x(PB{`f&oYhiS}@BvhRL6?7kLI^f7eNm5zv0eps=VSvT z{5mF3lf$tA)XuFvLBVpm|$WL8k( z08tD|oHZa(1|_ZK^iUG0 zQ2?_nlmtQUw@{J*Q4(M)4U~jxlq72uB%OX9`Z0Ur;>{m!L!2+^^zrSNA4`}2UB0xw zMoCIR0&JOdjgpLlWUG@wr;;StO|l>>G?c_aCK@QofhYm6!3s(eHA?a|3i6;Ci~5>Y zr`NyQZtdUt?VvnZpS;uR50}5Jf4675O^uR*f*ja%xf&%!1$nUP@(KzyN(wbfN(y3N zDdid^6_8a0N@6t%G79_(JYZ$~3cNK+stSCqPK=#Oyfq49HA;LSWfe+1H41znvlKd& z_!LAz!NLnRh!^AoKCotaxHw~{l3I#$QX46UIpPA1+cpqJC%fMl;l8i5lVbD z3UUhkU?1=+NGeEy!cIv_K^Sbb9LOj9V52p_O27stDDf*O)+k6SNP`_IS)(KkGAlz# zxJE%*K?JN&L_rlKED1J75)=v|U}HoSq-&I5Sc!^)qJlt;f)pr189SAvKmo@C3NuKo%YkB5UO@`% z8Yz&g<-lH$Q;-KG79~XmxI;A*_-Yh171Y7<>Y(sZRZs&vOHDz%MnSelNmhZQMnM*2 zlR~GGEF>-=!6a9sqy`Thus`L%I^{sY#|AQ1S%C|bG^N18QZ-8Q3fv&RI@lBP3epNP z;Bc2gI8_;xm<&3VARbXyPyo448k83pJC(p8B?t;B?D44piVbiEg~ca4!D}k;f?|um zMnOYC1?*X61w~K_Py)LR95q~^sDYUb_76OmRNyAV#3Avip&$k_QB8pdZnPi2(&R8vp@g*G@GAn_>!3Mm;-=qhw7$$*?HiwGnI1sSjxWWezQ z^@RpFfoUiRg8V4}3VleVDnlX_9yRI;5;Y3yAQQkQgZ%>!Ca|~x$VQkrW2X{0KEWoc zK+*y{K4lezKxqTwPgwltErF=v0CvZ50Itko!>LlN}Utuuw!N{BzD6=XsF zlm+<{M|^_PtuQELkV1+d#Fqi52$JGc0OU^|P<+DDttzM-fybvRs2ozo5uadjtntYO zG7*x;K?w_z>SRH=L{rZeU2rgGiDsKfr@d>VzP~wx9r1%7-TQN}lA;l-S{3Rnkg+cxVw_afB z7BxOqL3IPTT*VTfU~#PZ6Wq*FgVdKut^~KOAnBHf{0U080-%sVicfA3pN#kv2l*2c z`p|TX8lUQ*rVY4U#S))jajf~13lyKKpmqXEe1csK@h1`a6O?YjB^Odiv4i55jQA7+ zWh6DQ7u8UTT2P6u3~I-NTZS-`!R-Nfdq^2n4r7f^aE+`EYWJb!PjIcE2Cn6?#wWbN z3|0b4x8U*>DL%pFFB$R452`i5tx-t2RRuK~!7Y7A(?$(c4w0Texk2#>ZpWjrpE$b*{8^6+X(1*O%8XwZN zW2DfjB(DH*C@4yh+PBaF1F&1+?Ra>6N`p!^X;5xa=v0yhIThTQfp}B_*4csfgTSd0 z)?WeFE5e{ig=A7?1$9ur65hU52lXM6gMafxGXT3aX$q4|WKo z)g}Wf(`2Car;LI;wErZJh!c2*2m2FL4uR7tJfvh5z~vGwf2yGb5+XT(`pr;Zz}mOq z(E@O8g0080$)O^B>4)EAKWQ~~uaWk6X_13GxZ4odVAppg~EP9<=lu+=CiLJJNy zQ2G=BWe<%`B~egdvVo0eQxK_95>XHZ4?>87LXy8mK~(|lB}kg%2aP)l)hGxnu!9}R zt{?^)9TKWh5(ABpX>=-qRj`ANV^>fFE0R=D0Hu5(kY5-(l>|V;m^?KKLeNkbQjn-o zk^l{0YJeqq6okOqA>yD>R8jEIktisDI9nBXKusQY(5N3f$WF+pCl4r%@hGr?Eo6fa zlL;y)*C_FT#s?uIiefcN{2)aJol0y9d^JjZt)O-F3<^@9)N0VF#0eT&_!g}Se4t@T#?DrAW(x(-6?ftaJfJQk*Z~T{HA>>3Ay*-=3phX_DFjll z(WxX33LOSbW{Fk>ZUq@o0Rr|dV<%`VS)fKi05p=T(5b|&z+R)ouD}KMEmw__0BC^O z04ClFI+~0@ffo`zASY?GDzLShGixX?C||A7Q)C5i zg7W5N1)n*s096V*j#80{hn*W_mg9|&pxF-CvUJdK=_kM_dnU)Q658AO(&ZjvGKU zY~3Wty&&g+as(*GKzpALGJy72n3ReJ49D;bDr87(lETGv#4)9s{%%E*BpdBmV^N}k+d-|EPz&Dy}GBbd7 zT7%9H2Bj`HUeH7-vm@x9bH@rt2FDYixiA5k-$6S*K}Invuz`*z1#1N@4+I_h4Vu(r z1N4M4;`8khL_5JdO;Cyvz;?yp9f_ zRUEvI2N<%H_&_;`*^vQs;khG&;{n9}dj&=X-Yg|v4F(1!0np5?0Mg8@fFlQV=2pNF zG;^yY2ueZB3cMN&EQD2qHphU~auA~ybfG4%1_KWD4F(Nj)PgQh<<(%&Ax5nZ#0>_-s5OA7 zH6cc=2}G?0F={O!YHgHwL8+1#DOK{qQzb7rRe~-J6jT%dtrk$=&r$*>cm-ZZ70_w~ z1%WIDUPlWMQ%S&)zg$7Uk+-~9LBNr#tQaH%z7|4>*HN-uf!C3*yjX$Pk-4lm3zW=x z6$KRdLA#~+9S?v?8_?Q3UIkV~Aq6%?VFh+Y5d{uK0R>J)Q3W1Feg$qtF$FF~aV7_5 z2L&+&{vrkOLJ(b8q`>beSFXVCC|q8w!0*UaUYw;Mq#&53Afg~#tRPURAY7cKAmAtk za+xUDW$Yj&ypAnjp@-XMDM@5034x3hD^w6t;4dsv5CRz~1U6C#VkEC)2TZ+!a26=& zvXlfJ!M@8IkwAWQDMTP>}+Ep@Oi2P+^gR zFvtpFuoc2ED|+Boh-4`ULiXo@Oc&2m5?2sa5GXEG5Gc-45C@qq4mMpJZn}tqaFK#g zA;{Z>MG7Jy(?!6hi@;2u05@F#WIFgTBarE0SxRCG;tHb0g$km@Sqfqx)5XB1i@{A7 zP!K6n5H3^@P!K6BQV;-{E&w)N0A~6Wxap!G(*-~&0%SUWmJ+{$n1Xn5p@MjEmI6P> zbbheu{BYAn6$FYDL<&J(EG$wG1(_}iHeD2E`V6?~;vmySV5SR!V@^S=xKKe16!9R_ zg}|l@!A%!e5G?{F1aSq?!XgE6km=%J)5RgC3qtNYRN!@-1G6PdK@8+};VdO#P>Lun zRNybpQV<52E(|tZ7;d_lf_RaFC@3w87ZxdqflL1zyJm2-EpNri)}L ziGUJAaiM}xah8Gz$aE2~=^`-G75Nn;6a=yq1r&H4A25QJ^6@$gIHe8A+aAzrTgDMsV(8`A_B_2>t%2$EWaesZ5qXTIF3X|gj247xA$2~tlt79}BUw~*>W5@9m zNVlW8;~Hd91qLSu(D^_NjtrX24d4blsGs2|kOdOxfCzwgMM!`JCLjb9zydQ60vcd} z1qcBHu)qq0fCX4!147^gLl($-&^`*LwN4yu3XE%8ojN9cp9)!Z1M1Lmi-BYrK&=7L zK@1Aa0`tMG@1v|tEcJ}ARYHipETAv}VbBWn9MGX9psNoVz{k1sfR8SAc<7sLc*)N`sD004*d3HAq1{22ExLB{nDPHU%~(?Kbd2wT6ZR z{~4NF6xf`kp#l%=n-$ocxFNg`^35$EN!AXK>L2_dDNzvn4?9?sYKK$9KW309bDNVz zM@vf!sG-NG!NlQsfWe&?)COY!B_I%k2Xx{&wC&62$Y{lo16t3|2s(_H1ys|pAk{Q1 z@S27NQqwSi!jRGN0s|;@D-od{)DUHKyh5~kP}h{v@dnZAc|aR{9PbdV9+bHlL5DDb zb|n+xeo)2)pN~bPdI_+5UO?Q#2ntU|r0`^fhbJR6JV9r9!*=k2j`C1oMeBlq(hpP! znqM6sfVvZoYK|SChBqu%ZiM7wP>O|NP~(_^j{|l~ANb73tFgSI+zwveM(Ff1%xOo|zo_srT z;>r47hd0!NF4pB`aJsl|#*vxLo4&WygQS=LI?%NA<#sJO|o7L*$_!k3edncYb2t|4EHQKTM(bKY_A2gJV5t zF)KKYu_%EKp#W95jEaH_@kI(>j`W+cS8$}qQC-i_j z&LCL@CfEfbpnbO@SpsiB$yj#JO=qf z0c0t}TzFZ-sKF$`$Hc(M%njPyD1#OjAV;}_&Tw*+$x>tj?W1MXV8X75QGpSx2z1}> zc93nLFk{qU(tsX|p~0j8J`j)@e5)-ekU?<<-boI<&=q|7ASj4H16wekfX|}`Ypj6Y zaSPhF2I(Y0F3A92S_lqCMhzy=Rq(KA1_c<%4kk#bfn%9Pi5VQrpi}k0aRzEKAtJ3C z>1Y*&Y$Zm>@TmeLsIX#CVgj`kKs)F_12~SLOFJOm;DLCNNrOoMB?56oL+Pm&g*>1y%?;QV5qq&<r%g`g9Ka47_pxe{3ddq4_7Q41P> z17#UdmV*W@12kwEAlZire0w_ha3)ZahMl$v-e(AE);NNO+gP$3-%LN)0Ag}vIeq{! z1vY`~VBqcqjWI&^Dr1QZ(As-Y^fH(+v4BDmyg9g`0W>TIYA9+jO<+_4$tf^^2h5lp zTNuHu9|l)m&=y7Tj$&p727wnK+Y}faMPSK5ff;nCGH62`DB@5O4~7p9fNrFLW;z8% zN1T3q(F*tD8xT`qBgj^8)s7q#cbehK{(zN1gW?4fBO7e+4NFjf3Kx)9LBRk@^^TxX ze?&k?z{3F&FfuScD3x$zLAF3@F!3mXQZ8sGBKS6F&>nhFx@S=WU-$yu9S%z1;JuEZ z0b*DJM=o6zSU@4C!0adsEy4%~q6RGF@g|ci-SDuv0b=3^!Vhh5WiPIBvV5Og$z0)xOEP!vIe6hwl;f&rF888nz!l)$I6GC*q@Pzna;P|y?t zB!_}(K3wV`gWZq}iccMA&pQh=f8tXI>Y}m0vM2mnL=7euP=q00iwKJ|Zc9YFNdRd^ zNP$UUHK^K#_B%jTD7XOz8j)WI3K0hG7IqeI$H{49tTJz2VA8Bqb3uB5(}uQ#soSU zfE5%$Ff6bMR9z~uIaU-ZF@pC-gQ^Tr#lq;w0o|_4>YNfgLZ zvXnsk(%1!Vfn-627N~Mz1&ttpidR+zRxlr2#et3@Wrb97oC4cG>cMG3L1nm}xH`723Oz=hb zOpvk-G8_bJ39%?LJ95CUYzCi}$fy8nynyNe(C8C`;}wvhpbX9c?j`Ya3p@aY2Lm@) zBQ!KsL7oL!!^;4ZR>088?SfL6z>5L}M#l;NK|MBZ*l9YTe8rI^upQ(Fke3}{y=VnS zQ15XksO*KLcn~?1%3N0l@K_pXsKrqOG^_z(gKXzx0m(uqoFUWQpvFFQM zAYjhK;0R9koSX^ZY+kyt*KsGf(ZGsr9qQL3Mk)^=tD3B#^8x+6_oS@o?8$@v^@+fdAaDfUDUU1RR zpuh{NoIr&RsO_(W5UuwCZ!YJsVhB;-1nm%a0Btn~O&5WA77$07K576k@@ zMWE~t5&;*pJS^PcfQA+X3=G`hV1ROw*$SMF8d(CXLAo6eK#y{j0(FwWCNn572&@EI zr^p9q@k1h#$w7e+xoY5LP~bJqV*|JX({|hgHX1qs4i`OxEULh%zzOPz-vxOC6q^i6?4Y`w6EuGfDR)7k z$jbmqx8QBYj;x@A8$rRc6J(#XA{V&R1Zs_eIv@(54YjbQ80c7GP`Ut}2xZ0uDsS1L zm5ZZF7Odvr)L>FT>l1=P7^YAGp%COyaNiQ*=3@{ygVH3pMGHxuU{TOP5+7Kg^^gJ= zKeyu#aA~a#Nhyv?8V)uvIKBXh2|#O|~Lo>g4*GrB_vABpc)RPcTi@qF@ugPL_VhpnvxVii&a3SD5xI+I$E2F0d%eoxI-WS zx|tW0kY9q+G$ZK3PuPeR=$H>PCI&|aMU>6}Qt+@iGG*~GaWXQ1E-VH2klnzS%7PB- zX7Jl6zzQ8AVMPp)fZ77!8wp_d|AHEn%%EM-pe6^X zq(cb`a0v;?Ip6?c00)gCXy6o-{h%#Un76@IKG@sf0|G(b=2Tz@d7A^&qXK&yJjaUg zHdq4OrDKG6n~6+sv4Dp4n7~W>K&30FRAvMp$H)lrGBme?qZf3-J*WtP4F7;apV^V6 zNZ>3eZGuKJnA|`M`yh=c(9s0oFhUw4a{L2IXO2pa3y>q`6+6o5&WKzA>MRRf02vNR z)1cu&2}tqJtidD$8d_uoO$jn?A7nLS5`owOAwg#lDljUrfSM4DpzbXjq{ATqomvGA1=SZrJ4lcrbdW{`R!GhO zoq&YMBp^qyf*L-|pd%l%9T`1%!6!{JfJ|owSt0;ECmD3sG=mZ=q{rn5I%6K(=VAlr z9|7_SuAn)*igh2fa@L~ypCm{dwf{yhEPnNPeGG!?-nKAi* zoCrR$2U-+>`nwE%yo`=tT0r?h%5egC1PbROtjLLJp$>hXAA;VRjI>267@;nwJ55OAh!Fp8!xX1HK~x zwCDgl#>$`sI&Te>kl3Ix5320JK>^Kl0-#GSKy`|M0xRe+BG5sXETCcv?nXw?+&+>U z7l6G9ACJ^v0*#D<#{3|iS&%)Tdl10M?-eNdfx;M^@IaHq%$iIx;H$$xb~1qC18xyB z=oot>iynZJIdnJVgz=6KKDmfMhS8U_!1Tz(pxIYo7s6 ztHTNdCQw3W08OUwC^7Rgg3>0aP*GxbY-l*Z-~-C3ka`{5-cn!!2Q{7*n7pKwn6g1@aKI8iO6;IELw1%KlaB&B%wn)xz?t2Q$p<{$B>#jo(*CmM;54#1PvI&+MuA*d_Zkdgbbun3QA4jzAC6m!U8&x2~#COGZ-8} zmv<;Y#uB*Cvoo{RGuE+SnayATtv3OsLy*(XFk~q)L1GTvSO7;g185|U*-eQ>8j{9A zPJ$`|CkjWFB1Km4A|KExPtX>z5(_9_f`-LF;Q_&5BSB3w1_f}_3^eEqX^DUeN6>mM zP{j@!h6R#XvEY1>y!JoZ6Ta zI3bf7DB73_X=7C2gv>#rXk#LzjX{AEIwOg!57hYL$O4}$35q^O1x8I~0VQ^GW^geA z3RVU7cdZ4fb z-TMHtl?7CBGApn_1Ca@o+E_sb;Z)3|zy=LEuwrmAfKxG}0vj~Iz=|QG@1T^)0%`3AjXn@WPB8NerMvF+ph+TxoKEPP5H2 zV*<4lSRL!Zt#(jjA3D1r0BVhb@2>>uU=er(iccv>n1S`fCqh9^1SNii*FX*cr7%`U zuzNvAufm(tpcydGA{40Y5}?ioXbxI|QQ!HuX}b4 z$;HgN43L(mE`ubfR)7}s1iELA99f7S8V{(I2X5ejnl|8r`~|?>4oFIXke~pA^v(o8 zu?xDL2i$$&QD6j}&Rh%<0& z;M*=h`}`P-6+xQ;6&M{6!rY)MO|2L}8(J70WwSt6{dDwzqE}l1)M;?s0_L0n$24@L z6Wq1q#%V9;ZZlBr4w`QS6(6#YeglURiz9;qOE!prl&9X(N^FjdSy`Zn;{b<03q%6c zWMOp#cRAmHEOwM~>;NxCfOUqD@(48US-?GW&=L!9_lOMow zVB!JYqfiH0ht3FUCW7{JvGA~QJI(-k%2Ctt2#AK|BL!whoh(R^#O$b%<=D`1umRMR zRA2_3HZ23%nF=a9vHK0I80I&}2_UVG5{@fCG{SrhCIOV5B)W~@`D>7W;5N?q2fpbI z-jV+TnjeLvj|T7<_y$n+X5e-hlY!zL-ivHzK`ahJUx6k ztt*2m2DOeQl$b#+76$N8m;y6si68^yMov(-3_MUSqX@dzPl3tN1{#q}uvoN!+?A)J zz~p!V6e(s*8sK#ljyFI&*wxSqOpf3Y8qhc(Xqt=_+$ZCKcLc%3H)sV2xHyAk9Z)9` zxeLgn#HPRo?gFxTNh`5sgBslsec&!28>kBiIujk-?Q;h;v=NyKZe6_>FQelNkkcGB z9jA1Hs%&T$gd}VZM1Ey(WVB`kjnRPp0}C)jxN3kKl?;$0$w7S!9mr4|sI3EPP%was z4A7b$&`wxTzhDW-I!6u1GawqCco{$?3aA?dT7wHpqo74akX{?;mNn4I5gt%%z^{|! z-i_3bGC-_c1TTga0j<-^0v8<+mx9s&9}^=3GkEJI2l%2Na0r1G{XiRf;9+af;y2I= zK?XlwCU`!Z04`aeAp{u-1g%O@$pZIP6&OJoSVV!*@dwCDpo)vp5j0K8V8)~aDkB{= zvOt&5f!2$HF4fUc01rqtfDN4wS{48bJxId?JkbMgcrZf7h(RNc0$H%O2YA>3>_Z07 z!d%eEBdD7RZn=PF2_WNQ3XI6NzhTX~t3k`_Kw3dH1n7>DhK34Iw~hmp5kU+dB_=l| zW@$*{2sDEPO+{{?3z0x)qJtE%D1k-^lo&z%WJrnui9*bPX;)wd@9F>twmamaS#WC= zbQ&*cJQ-9bfTpTgK>bT_x(8jY3hwlQ+t(m9pym#!FaV2!Ixd*&@tDEwLGauYC<%iU zf!Bb64TFqVgOU&Ej&2@CZjvUSxQFl(jeR_ftgwNH35;m%YEaey6~_#GEX<(27vSQ7 zMTymM3M2UJX3&b>7Ytbn;AuSY)rl#fb}gtrHDgLp0JYx1`_n;JCq7`v5;zB{EI_SN z1xF^(#SY-clL|yBNFLFEPC#2X1Zk;)>;tI-r(#gq!2+7(26a2ZvttU(0#{%*=zunN zYcOdjGJ%SeBjC1-hU1=Il#&eOKU^5(Zx$ss4JHxLGy-HTETlKV?#j!hzz!;o1Qgi8 z1CHP^28bkwD=)VK2SkzsED7R)%3yZz#FQgsc`QURt1B<)IzjL_KdVy%qdBvO0xM{B zgNp(yNVNm#{#;F_1aqbkhR#VVj#4bYq*6KE#~=z@5N zAY^+7Snv%4G$tG&D-6McU*Lj}m55-$KVZQQ@bX|#VGE9OkgpgNSV2oldKeX0p({eb zyF^$t8BEL>rh=R^ml0%%3D`9Z;Jx;&j!R);0$G|cv9&NU353{In3w`WY!6uMHUsEp zUC?>s(54qVcoYtNlavoHFZg0g1vb#SNYK*1=dffT0jku&!$e?7P!C?7H=T7nI}gc&*l#qGGY58O|2JcFE_ zL6dD9poO2HTn9P|pBYlbFoFUS>@r00VuG`Hfq4K_y0C)Q(<`xqT6dt+=fO1;C^Nuo zIwo*U0^VZ724erpbVO`f>z#xoyK6sG=UK`a>EW8&oNOT%4MJ{sNpVS;&z0U zXKzpg0Mt{y4ocmiI0HrCO%R8Nl^a|@bwXMaC~Qb+1eF0TXTm-+4jt}=juNmqPJkan zbBCLe9aeu}zegHh0n5P0!obMH4_!tDDHNGqd08Rr)))j{gGN*oSp=SeX;w$jvUrFp zHdkIYM+We%DGXK&Dhh0%j+24{8)#Q)gMvAegaR9=oDxuAgBDXvpo3~uvy?a#SV5Nv zu@qT@?k-SZUJH@01C5e#fSRHVptNSiprOFR3%Zj9bbk($1I|9LBV#e>MgbN_IdF~0 zp#WaX4BDdtYLSB4B=tVLoS;h-K?~10vK&D}n&9FIcF_`eLIu=C1TT374GSwUD{v^V z3tR?A9t&gy2I6aGS6)t{!iJ0HVZ#kBP(eE)hz%PatYO0eDG!)I2LOSZ!{7xW8VbzN zHU?-(853yD7HaN2f(l(M-1rrAvRDc2wi2P zzyh*_1>y~m@k}7&!9^Z;qyn_GfDvRncnu{JXl_FUR2`Wy2_SNa0y8K>Ff)PHI)Y0xCeW&6NXHS@;%5TwCjh`9*8^QH2H6;;0WFR}r5OvjGy}EA z6+s;)@=G%oXlVu>;)RrEyr2XQ>(UZ*8EB6U++{dRGti*20JJm%b&CZcg&8*_KR}Bt zaESnAD=>kseg}`3fc7OoR^x-pYbHqdi^&l>njzo_n$Xe6a)gX#fDCs;8O=~&QeX!S zxiNtnVFHe@VKJ~m$gtQ0@L)G|SPWEdf)=(x-7zTK1g|3QAXgFCmkubvt_BCyoS>kA zkE6Uo+HWQR??NNeD|9{)o@l{K>_B@0L04shOat9}3QoC89dghn#U92i&=fiN8cs-O5)`@6zNs58s4|A_Ma5ScgKofK1Z`&n)ff{P z6(F-4Am@R)>^$(64tQ}HHs^sx|6ywvkUJNsl`$wNkm_Slj~=p)8+6|~Xn_a%^0Pmz zjPSL8=rt**KMf0YP1-2b>lniK(5@`I2 z5j6A-b|SL^6Osj>v&6C>ZafdN0bJO+@b1g$k?@|1>-yMe|C`Is2k z7!d8B9#BINK12j=$_jvH^ufg|18DpntK}R}yPqN14N5-X^(FZ1W<|1l4qm&#U1bK) zNIqy03NvV|26Si{6R33o-f{wQA}mrtv;qq#A2Bh5w&8#Zf6#_pP~i`iV`gOpS-)l) zsO_uaxCgv16gK1pS|kLT83Cnf9?+;Mc-a?t?=5(BKFBO+^I3rjT9UGYhD;AIWC>h^ z1Orr<1tiRoC2#{plo=}e2qX&H&<7}P?8hX+gm77|E&NEq;QJ7V=Y?tMRNKqS35q4J> zqoW3BsfZ$rBcmd_BLnyjLq zv22PA3ZUgIY>Et+nU_(4O%b+w1~g~FXvF|JGL`{c--AYkp(}krZUV2%0e90t&H||h zA10{8sw&17&Qbi4zi zVeJmb2_T-MrQ?rD$Q}Z%D^uhIt&9fc!l$4S3?=AfHE4872V|KegL@IU3=+sv;sA{^ zae?w5tO(=cV`gMvVnh@gQ&2(-l$Swz*um2|pgImTHA!T72O2Q3VgPNd0uQf&SD8zI zGZ(D;23jTzn(P4u9@_dG)Ol|3idtsS;2oI;Fl#W0fVLJffGQl&d>F_|XdHsZ4neb5 zpq10msddQKAy7dNS`wNCS|19UAA^ieGb7Dxfd+CM&wwHab|L00cGP+i>EH+kT?Q8L ztRJHl0}H6R2C5gCz(E8`N1!$^_|9J@0<|F%WTI1%S%Cpo8$$Ghnlz9a5Ih^kXvJUx zTCw2BqR8sVpa>q!0xJP03{YZaa8$?wO+Y|Lxj-d0gCqEeKhP1fjuOx$!>YjH#9|H_ zGGNeT0+sQg=uv zkR~$+s5%2Li{^o?BIE!sKW9(?senm?x-u+9kaPi(0FMnh%0MUI89_Te;3YnI5*F0O zgN_1#*03=`hX6p`QnVoeMg=A-2GD{bX3!BCu;L!95K{Xr0XrXB+{2Owv4I8}I2M4E z381}?;9Jo_r=Ea2Z?GJQrGpGkA>dPbKrVrJoLhkrW)$e05zxp#DEWYkY*0zVf!w9# zP{P)w1+Bb;^|(Qc1i@LF-I2LOkx7A7kpa~G1WnvBfEV9`a~){Z5_Ebq$R^OV9JF%* zO8gvI;NE{l7HF#?H@5HNv_zxO_9%%!~OA1V&JcJ|1 zvM4ZtcfOFGQ=vVAENF1DfJWXxH5p_A1wNyWH4+?ufYO7bq2n5qS^zv@4M}P&S&mmg zYQS;qcmu?QE!a^2WgrbE23KAt$2}nZj#`c{Ks2n50iPrVF5(r4N!2W{u`N(4AvIyY z0K1ILgbl85Ap;%oQ)7nkrp)_DYe*DOX2(Hob{X=3kI#l2kj&P&5tRt@-eeAgDUtpQ$g(tJ;ynq&OJQNSwQn*917rpQ0SN$3urwv z>S!;hC;^q0ph-J;9tI8gGJ=i(-~qW4RIxESF`0umQiGQLg9JGgnL%3}VSU&q$W}YT zMj5Ukiz=|di&hrL4v>>UOW{~RqpLg$ERGEj5r~5w?|^vlbxrVoKXiR5>{KZ3FRX~g zqYCg|Dk4A`ctLY0$SXiOKs5x&0}M*6pdKJ-y%Q^F_XB9PBzQ#+Xr&&grv_@M!{!_? z<|>ieFd$Pz&?YrO^8=u%Swy=7a%u#kqY7%ZfZDa_+v*rWj)%I>k=dV@L4g%|P8{fz z7*Nv&w2++D4di5K(^-LukC~ALRE0BxS~C)$(^o(Wp{q(^iysh921Oh!iteBcyMWUm zIDzmef(9zVNfBx)Xj~QCxdyGflmS&)j&+6LB&@&$J&6r8;wF(L@B}o<1FB5H6Mvw6 zFrYLGX?U@kF@aZmf&35Y@Iie6_cwUXoq-#kh`yjCA_h>hgc%7=r=SrskXymq%9%i$ zSwUlmAQ6!3QQV2La|Wy#x?m1;qXIa;fez&Y&60qYih&#r@&zbRz@Y)Qfe{uDte}7e z#{*~~H^@H7uqaluK=TTa4h8{5pn)=2^5#bbLJM*a!COp2gAETHxSToEL_fp+SG_bq@E9Y`-M7`gu=MhC&|5b%;h&;~BZa5JcF0Y29R zG)xF8aUsnMP;`M-38HON0V#rQQvszG@J4p5%_3$6M#x?j(BPjV2l$972COQX6c`~J zRS2qNRA7YcQX#04L4gsnMTMW6`w8fb2~cE!+a5>2y9bp(2d13>GeJEhaJ!C0iP?w6v>*|77!>z2 zW=7EYr3wt1%nAxjYirDz6+poUYJf9nFlB(7=8)Tdn6s5w6u`IrFeor*Icj8qrehRY znH@lb5xNYZP8(>7I14-v4BF}h+83Rr#L5fmMuXB#2KY*w3~&n7$Wmm3btxD?X0aF1oH-hc?ZFKfM7mBFd594GC(5- z*`OK&bR7+-OAHEWN47G^Q7MqU6rkOY%uvrUIocP33PuGcM~A{JMUW0iBZL9egv(F> z2OKjo5x~uTkd=wCj;S8BLl1O3ETf}FmJ)acL531b7UaGlP<%KtW;t4dmW_ZW^I?Gu z?rngU55qPRfEM~f!VWb04r751od*RnBRr5nXLdqEmeCO&$c&EgKn5Qy0@Du$HrJ{%sj36}`9;Dg~o+kA;o3qBMcG@M3+TJVAJptEg>Pzyc`9<a4YgDa4GUDa4HHYa3~5YutP6#VO11ic2E#e6jfkW;K@>8RNw)v7gZ7g zom(%0bZ)%}{M>pG@VWI$VxWw`tAu`yiGqlNsDiK(_%aa%(Zb>^1wkbV(7hQF;CnM9 zK=)=S@MS6RD@iIyIM##iOHqnWcU?Cm4rZ-i74{9=%&a6tuw&~X7Va9=d4xYQ{bvo;9Xneq|l+r&*Y%M1L`P(f&w&^!K=UyN#CH$ zzZ3*anHUuK>OdEAvYIk6)F|=WF@cWCV*w>BXz;N@wDNxD6kfS3JwMZ-oheKMg}$a6+tUKS+W$_ zAaMdde3^Ro*E?{P`t2#{K2Nc1BwYA1<)L=5*H|Z zI6(a?HU*yLid@{F^_^Ktyr6>=LBks?S&Dq%HkcwmXe@$Zt)hSv132IWKv&k~tX1N! zQ{Vu_2iQ=E^BkG{c^MoT71=;8h{ z{s21`q!=8$5W^KXL5ZCcoY=uf&IvA85XuIf3RDb^CkF7T2MTP^gu;cAP&hy?-~fj` zxc$q`4<5__MLsCHK|#x;zzGTtP>u#C0R=`yE(K7%#R_&an*tZe&ENz8b~QAhpw5Ll z9vo~u3hW@Kf?lPx1zvCnBLWO^&(cW&#HiQ>=4>Sn$cQSF1L)`$@REKGP)kZf zfdk&0=5PevEd zIn4pO)CMLBZ%%W7uA+g7!kg0^phaH_3LH+WH~0UUxOnr2+YF$4UOAlpFWK2~bmFb1 z+4Z0UL^zy2J=^_w@$$dRm)3($u;y@jerEZFYZqQ`-dzvss&Rli9-NS=r3{d>mVm}f z1qEJ%yB45D*X%I1;|As|1rC8XAQ?vmMRo-akO(+kgDzE7V0V1Qkfp>0YNso4J33@3 zfe%4tfSi8H0--n{6c2Khgp!!CM6V(3YL~8$X!rQ-`;Px+QM-{k)WFbZ^sKLYmnt~w0Tu>K>1JuPK zLM^C)#sTW$5TRB8bU8Jsi$jE3aDx!k#UVm1s3FM#>f#Wg7BqOy=qR7%$XW(2(INL| zP+ZDEnlc<3OdFVs&6o-lK&z+07e9h(i!C6r60jI}1R5l^10+@f76V_h2ol=^5~~4= zfd~6RVh2EC4UAwx@XS9*@CZn-1tJJp`of{XbOI#U0TBeRH2|qR0}|{333BK%OaL9z zZ^bYH%mrl)1$deRqr?Ep!3;<_m;s)H8Q?h>w4NQgZQ*!<8G3{<_cm5$#(Ks& z}EqQzi`*Sq&v_h^z)kuLhG2SQgai%m&Sb=qNE~ zgElNd4oL!?bO~BEs=x_q+bghvR6q`&0kI&PoIorFC7vP#03Egmx`M5~xX`h_*ipVr zfvHdlbdz+U0*?Y{2tbJm+FVrtEhkf8E(Dpuq5u{J6~>_XV5leuL=;r)g7%+6MR_2i zpaPafgGm4?DgY4$6{Rd1Od?QG5r`vw-fH zg1AfpBB}to16+ei1*%pBBB}xr)qsj>KtwelqB>Af9f+t7w*V-=*Jmj(fQAqp<;%D) zvocCRdv1;o7_yaMH!3h9_BDa_@^>(1fzBHSpXda--w3jQ6SNMdfiVkwNE>*e?H`6L zC2mlU3^WDyg8_7HHWPy)p8})f7lte)evl04WQ7k5SxSN+j*tSQ;~R!7C1DT;bd3t^Y!ol zVn-f<_h4DjU@{XHanMvT6R2g6MGMF{(D<$bHjUsR&IHH5|GA45SQOY4I25=Pcog^) z1Qdi6L=?mnBorhO$*>4~VUGeMB&bW37z@D~L3?%?K&>|gkl!2|8kTHeFIHeIgt9<= z4F>Q|X;3&gHZ^QmPy?2RuprW)E$5&xbL?)oaK8>L4Pil~KQLq|fWp^t*T%W?Si#Z| z7DO7fHysogj@LIV`UR1OuprVu7_t<2L9%l)%^im?(j-{V`DDLrz!xpl$#^WVcpv zp#n23KvRmT2)wWtLNH*7T5#qE5sn|g{b8_v zfp6d>0b1i}kOi8n#->q&$v_cYLVyo&*I+VH1kW&mH->01S%9XpKs%7YwU`ZL%RY}H zxDs;!Z6W~8|8s##Iu}LoJ|_{-0H+3%haxXXPy$qpYB2dI@`HFXir{K60CF>vf}#*e zFho%pM5!o>fT##XQ4pn}Csp6ITF>D}cp8 z4Ih}e3RqkPEDmb&z{EAc;u>Ia4NxcANudMeUmdWx4p>|VR8NDNji9z;tr8ok*~p;4 zV#>s#zy@nJGJ~6qY@lW%Sc(HhiUX_*+&(d7;z5z(0ZV}!DWGN}vVj6%DR4{0lt~0d zmk3x2+*~mQZ}^9{UYSjqB*0SOHj62f42mupuoSrAV#)+MF#w@Up;n1)Ip`#GSOZ3h zeJzS!6|e#h(5?Y+vrj{b6IFo*SOFJk3gDvyF8*#6D0G;RFeALHMAi9Xp86 z0pWuifFM2-gs;FogN>P|p0SR*9yGrW8VzIAVA27t?*pCO!wM<}R20F55NIF|bk8cJ z5R!ltLL#7+9H=Y;7eYLcLWl!W2(ds4AqGW$W(NfZ1%5}y5+%m9;EqqNk^m&}@;Ne= zDDXSVmlY`qu2m2~O~nF`RLl!f!v|I)gsO%EYz`>oc|dA-!D@t2)$oATfZ~B0q=pBq zMg&!j09XwuR=7ZFxWQ^fQPqfm)qvuN6QqUypsLoXRRTo=Buj8Wvjhh;ODOS!T2BlLf(j5B7Emfu;sfpX zWl#`;3WAfG5-(()PZ%l)&JRjFkd;OvP(cB(c5cvyI|c<&sGtZ~kP9-EC}+$5hXOTswiz1vF*S0bPV>%A^6hTG5nA1#~~7DU$-|enwL! z8OZD-XzrZJlu1O98&qQnDDr?P9?;E69W zPf!ZiDF`bF)F}vo=O}AH^#Mzbk_ag4uqf~;2-hiyI4N|1#W}#@pc;`EMVtpL4yqA( zP{akm;-DIl8%12CMoH9;2~;C;fy6~&=1bHliPgUSqXY|;{7X;5(?flXSbR!Mld zk`O3WGAKx5Q=tG>!3;^vEE-HIO44gloUZ~_AOlJNETCgbWKk7pfECC=vJ7|)AGprc zQIbbhr&Fs03N=uvpd^^B#0V`HAn|}wRYIg#6a+z{p!x|sJ^~TtfQW)Z8$3P&5#@o1 zf&v*lJ^~RHfQW*^7Cb%z5fy=mf`Sx0J^~SyfQW)Z5hyW1b z10p;?gbRpp01-AI!U9B?fCvK+p#vf`K!gg2Pyi7!AObv+0dAgy+wb6g1mGS33rLm$ zsZEW{gbiplfNrG#4Qhc7wgzoT1K<2e;vJBV2N)HZAycr7h+d4q4^RikQD2eS@dp#A z5dvO~$O@VVa;zx??WzPF23H84g<^56$O7E}3tOF74_ciFI>#F{^@BVRBk&7kC}`83 zE(3T*zQj?Xu*k8Yz6f;i4}$_TXwC*S5CiFrAQ#WDRU+U)DcIdajG$7Q1yp8gfI3s4 zQko6K1Gi&9r8EbK2X4oJN@*?-PXN@JGGzj{V?d=eFGvvFjseX*^E>i@mu4_4@PVfZ zlmr!+a@Hyd)hP%m@Yg8_LQ81|QzjO0sb!$RtiY=vR0qzIH3|%-OdMcw6VM7G6mcG~ zxP=0<0ym1d09f2cfmwkIMO*}2dV>~|a)QJmwE%-DlLWZ*b^#xfBvhvWDZLp?nPkAF zw}%3=0y{`Or1WMmWl{i_-aZP<3Tz;8Na@XB%A^7=y#qk|o55fDDF7anyop4A9lU!mu(BSsGSCGb>;g;EbkBuo9YC0kZ&SG-ZO7(98;$ z1vn$P4#8OI%b_&gUJP| zRsP8ho&7F!7Cpb zbr~3xSR5M|L6<&&m+l^505KI0z_~?*ftGZc(Fi(~n%R*N)X8Hlb7U+m zhB#5+BglNvfVmEc&;SuCAVL8|$bbk55Fr901V982h~NMbEFc28!2xSzfM(6)OC6aD zL3K0};!sKjX71ByW3A8}2@W&`MuEMcYz*Om!yUXTZQ38shAc{v(3`B7#ii0Q?MF|kapePC6c>wmP zBl-xpL6#%>Ah$sl=wM)G2FO+v@Hn?Y7Ia|?e5hNK*#ayN+WTk#Vj<0EC@?GVfd*dr zixpTE1VH1kg2kX(A2cj0T&%#UAOaet6)jfaRuBUX+KLw|@G3|YD=;cZqKwjlI>Mm& z&*DPR%pVV^U&Sc!50r$sFK{51#vzrp;K>YdNz3f`fUyvKqb)PMtYHC_HK^qbvm-}| z0_cW}BG8s8&~7tENK>&s3zR>>oTbba*0xqXOWA?-t0X~xqR#bu9 z14&knm<1K+HbXe9|$9$e;v=3$|HaJlRF1Fjxi_B#H7^TFk>V*~iGYLI>4 zG8i=X3)K%UhaDk@S%c)kWie>h7%Gp`tDr~*MLEtQnOT7ummH|daWu#h_zFt3ybO*^ ziY(B5b)dre0Rv>oALyJJ@afD9MW8`d4lv0BCI!Hx2$+-rlQLjZ0ZgiZNewWmQ=|lH z5`dOFgE9=bL}Y<%S7wGbI}|{3Qolh?Q3T0=uMP$6(*n0cm_h9j@Z~Zfad10?1x?>pH^Z-p{fw$Q*fEI&-Rxp8g0fKphqagyCm4hE( ztiZy(h>KAcHUad28NLTy0lcsPG^r0=Rsdpx_Q$q>6B?+Tho(7DSr1K)pz_o3+X^3QRCB zf)1bj0M3%&)en%|tth3y1oNUaym(NQ0p-F3MOg)A#}AC4*;G)0BBvmS)r%8AbLn7p z_~b#VK*co{BS8LV2DJ_#asmzD${!>u2o-@$nKC;bU<9q`2RjNPgBIH0t!R*t#wpJX zS_cg}QJ4|B&I4*6s86Z@lLRfE1;++-wiYUB09p%#JS+ikjDQLnknJFaSgi*6AM8m5 zW~}m{gkq4TBoA>JxQC2Oor0hOG+@xYe}M_)J_reMJtQcZLCH`7Ldru-g?k#J8bqSX z$SZ)H0&*3yNgz>dc7w#hzC$q`yQrXo04yazLl-HkQG5gvX9i_56jLFhAJC!?A_|W; z6mwWW*ETD#D{v@qDsU-qEAS}rD)1@rBaMqGfyOF9`&q!{vm$5_jxczKnV5n&Xeo|@ zl!CN^jDjp~Epm>K4Iz+F76iqlJZRgNyaJYBjyIDXp0Sutw6cz;* z*f;`Yyqg6yngW*MK#}68RbsJY0*$~jf@Xk`b@70uK*O-0aT63>0$?f7SS)DF1Vu^& zECm{n1&x=WNJ)UDK%=stkq;Cp8L$*+7K{-z1B~np1+Wxo`WG}Jf}%?WECm{yWdyAh zMAoGNmI4jqg2w$&bm@SlKqI~kpr8XCzYV$v%}JpHG?W4w%wAgq3KUQi7i1)8ppK;m zG;9Hy-h#-12eLs^^58){kQ`{13nB*!Oqf0%us+aa7eo#enlL#5upDU43nB*!PMDks zSPnGx1(5@VCrnNPEC-qagUEpb6ecGFmXlFnEQH8`LKG&a0G3mL%YlLvCZ__HQ-RBY z!W1T_0hZH%%Yg!w0krlKq+mICRh5ncV_}vVlMZ(qFQXi+;@$w-^bQ%EgiCub_!ISdGc6zyxa)@F_6C8U_4_8WVIz!xKoA3hn?VC<-aCfXXWc zaFtib6gU#bW)b^%isDB*$jC}E2&4h7J8Ngzd# z>_H$zs2Zs=+0w+#6u!#yR5P4|AM9T(9qS(v%LtP0GEoXp^BzCfu7ya0#;ypfp& zv@sQQc`r+rBC7&u!H*&bVyCMD)Eq7aHqep~MOFoN&{4CXlM+DX0jQzAkZaC;LW{I)1aGXAw&N# z)4&_3!9fV}Is73qS^kc_4$s9H4GG=;SpikYNmp(xCP} z=x`NS!4ECYK|M|-8St>*28?YBG72(~YzS{QK_(}ZWEEr~5>Qj%jSWzv0NU69H430( zDGCaVux67YqOqZbXly7W8XGEz#)c}Qv7v@&Y^Wm|8{mZv35uEu;LamtJ+YFOf)>PW zC}ka31*oP5U4INJNUR?vod3`H|Y95MO;Exo`dLT$#jMFT7ku1s~Hs-RUeG|a&A zXfm)4H>lEuj0fOyDzpitproLzprW9vpr)X%prN3NRL3c4fvPwySQRG+TKEgvjEvro zg|xjCFgmPAMjn4G|<#D?rzBsQAEWgQt5wLnKUfh#mE z(8!P$sHO*PlTZM&iWOuF6p)%#kZp07=c9P>VQi1fTSS1#9&fAP^k$Z zDaZ~nnA8NQ)D(~uWOo=$Y6?_p21p9Jn+WQR8BnP?ASuYMFqp16P^kqVDaej6nA8HO z)Dn;sWH%U0Y6(z729sI?nsoscG7Jh@py4@C3lvg)}J&87IIo9^a+`$#65EW zof}s`t+c?V!U-%%7%m5K97F{q5rXZ45nu;l5r++rLn}$}NC>h~@RkT@2?MB#1gn5p zgHmUMM%+M-fk;7Z!Y&A|q(K8hpwSf29TE`7LC2NA&3&*4ius`MgXPihpqV%DA>W{` z1*k6%-OmNJ7PM*tmpdVHVDq7>k(N4eA7*8gfi*f8Fd=ruGQehbK1yDLV0Gka!H35801bn6d zRSsk>s5vPMj&^uE8P$C74n0uA5vvPj6=W5dK(55%dPqXWZa1F-KbAI|6jDu)qnh0OUSvu)qPZ0OZzduz&@~2oAUr3XEXG48UC)1JK!;&|HcZe;b%VO$g9| z*xX9CTZDS-x#phF<&dYM7vk)VlYtoE{iuCQf; zmAYtp4}i9~D}XM9!KSx?IZKI40kjn!o9qQv(1|#pE26N;P5_-zr~ta63acz5=rl9X zqH1ii2UxO{_&~jWEa{j@0sBx9lj8!`EG2#gP$`1V%mqwYN&=u`TCtc38ohxI521z+ zILhIs2^;|r^h37Tk2FziLwAEaB)G7|G%Z~`m{SmRPHG6HZazB49#YARl+U4URf@t5 zYpFd*N)~K`<+RKr*h3k+=wNmmJIzw(U`{QABc29xx}bNRgFQyDi}KSf&0=j250VlN zdstu>9n2{UyNd@$Es1R^c(fKNMruc3k3DQlbZHrGw5zqS`;S(l^bWVta$#`we0iu) zlMRk`*3j#h4dz}h_VQ*hmwJPv{-$?%ianmFk*l$rOp55>a0MwY#;$hg)mgk$DAlot z#b6K}96dwYrHa8(pHd#vw2P;q7ea%%<{Zp1O}X0!b6H4@F>%U6Xk@x#wEQO26CKPs z2Yad?nJIa2gaz$td+h!jdj0*ukva!Q4|Q;a#i%O~b--v?3|v^yt}TMS>?B2$-mL&^ zqoSaD<1yU~T89Z;%L`gn0-YnmEsAw+)v?nMZTK!w>sXILYI1)#zlp!2Q~ z!aPu6PSDxd2w@JWFc;_?ZGj;(6QX$Qz5_??LbbT zW(1vdDgfFL$OF0|!jwq>bVCH_OjKczpakfK2+(<{q9C3EXd@da98{FVLE*p*4gzM- z3B#b{8bBM{K(ZQ2k|0@eu&g-fcwx|q4WLEAAXyzH29T^ISXL5zgA?fDCCRl4;%gO{ z*DA2CRbX4Iz`j<2W32+`S_Q7P3fyZIc-AWLu2tZxg`IQ34`&I$S%Pqu5S%3pXNkaB zqHvZNoFxHgNx@m5vm`(q&{oB4N2WqhBo`JrG8J<-ATRe9&Q@Z9F1Te;U=-*CEoyWG zEn8(RP+}}`tj|(p1s{&atiYJ9#0c8<4w9_Ta%3(89r6S^1`TvQ4EShVh)|INvm<+9 z8RS4eCh(nwC7>hrK!=|*E3g)VuAXNs6X*ij#N?m=Hj~k@DoYV`!##rngFp*NMuA8c z#Bq-GZc2=hQ`;O_QQgK2bt%kQtl*O*q0V9jZA5Pn$^xxscC;^4Vs&IK1Ks@!I$x17 z%aO56iM7y?L4h^fkwJkiyRZo1YF={y)z_BA)i@enCT27yM9 zcR=<`5Qb&b|BQ?*^`P@m949bBPx4{_ZLS9G+kkl=v=SP;MwkI=JOgOQ2I#UKxC+q9 zSQgMKa<~f6DqJQ7M!1RxY*|XI;G;(&PGoTWzz$k@%nVo2zzOm^Gu(s;Tv-Y%aM=ai zS)f(2aM=w!Sqe;W*#o>;3akoDaM=rdSqiLh*$4cfO>eAl*$)C)Fqd(+Ff+2&Lr(St zZHXP+Cw@WPnE;_uAXEl~%7IV?5UK=1RY0g32-N_(ONYUXsRc@RKfHn~;vB8cC zU<9QgMbIS)j9E%7j)LF?^$eg*1Z)ay3QVBOCK(GMqw0|JG`X)!Fp9wz&VS%V99_n& zz$nlIO0}R<=s;PXL4gS(0NRkIz~Fdc>A?nA!ggH1st76)7I0*N7hN+#b^?R;&p|8$ zRcwfps2nHof|4YB8w{H410K-f2#gBYs!(Rf4LqRmK%BOMyd8qs5#)jg%%BDCtgvHO z&`bxZ04>Z1-I|N7^93;jve2DP0o#BlL$B{w_qyn@YpAWR17N;4YZHL$wz(d>#+Q7uAfUR2#kvGUv;KD7f0NU4&&2gY} zw?F~S@3>&~!3GAby9vN2O@T`+0ml!kK&r4uDab5PfD1Yv0IR|tEg)5(Ko@eH09J)P zYCx($0Wa+MU?s>#Y%7rJ7h&ncaRbdZAkc|@Dy{e__W3U^#4=Uc~Xk zT97_$SzXle09X!N1{ZUj0G7j+t;HQ5tO1#cEi+3vZUD>S&cY2~dF;6tw5gC8cFHC+ z#K7l8LXWb^n+sot-eFZqvs!l3?Vzw^AGVl(en@SI??kF@jB7- z5AizD^AGVl(en@SIx+JPEH*)AV97(^10_JmVKRZwJq2Ya@WyY@C6dqsLs60dlVd=Z z5|d*9xGe}dp_JKi!`6chNP`YYtq#x$rZ82Yjsi3{LQ<;Z2Np#pumg~lVM}(%@({V41|1WC&0f$( zQtaZakWvSWU7!=a!07;s9D@S0Krg6s0Pf^6!#cPivv^_s+g^S~Nm$1Md0ROXxD>v&z1VUNWTQBpd%rb1V9`?$Yy&b zArMCxvfW-u1jG?l0AIGOBnIM$D}XO%R+0d5BtgSk2};Ntyg`RpfsQnTT#=x}QmDWR z>2QMkJZCQL>8mYPU?~KPfsU=^bo{k@@n%N280Z*VZpUqJ*KcHji-C@{<#n94^wno3 zxEN@wIltq=x9@rp>Oe;|3OdeuJ@XbqOh^HASmn203y(9y^@@NGfBe(^w7nWG20F-5 z-0|s`$8!;Gkx-CSkaS!yckXX?xH<*}DFrFVAB&D2se+0nK(@+*`nOo)A9S`dL9j3akPLL1hN$HZ9PQ5sqUCm=stYAAs@@7Be7Q zA+R4=0FuL2rZRvIC!4^i#12a048@?MbF)FI88UnVmYo8X1t&HIkOb(wTqX^s8Bhrh zPznJ{fDX%L(qNhcmEeI(fKJL~(qLKul@NeSfR4#!(qLKwl@NhTfX>Ke(qLKvm5_i- zfDXuI(qLKxm5_l;fKJC{(qP&El~907fR4sx(qP&Gl~938fX>Bb(qP&FmC%4ofDXlF z(qP&HmC%7pfX*3a0u>41@G^jlgKqLM0gb$XE@n{T1m9~8mgEGN01S>6P)QDKk~UCD z9&C~a7@)EO*kq5uWJR#ao`A_pV3R!qla;|HdjTe^fKB!aOjZS(>vm??;8r=I>L4(!sQDN}FGj#Y4WHfBV z7J2Ahfe~J@6C8*qMJ+bFh!vxkJ;b_aXsa7Kp~*cFX~OCOL$(qJbixXB771I45@)s& z7gU5xffIa_BZC5yG-yr-bReN4g94khzz6UY4QLV)eBBuf=z0;*p|{}c&cHk#1u!K5 zp+HCFGJxhg!GbanK?Mk<0--b@ln#V4fKVn7$^t^!Kqvodpl{(rhGAVF@rv+FPn80_PaeyY@*mM~fia_`Of^S>S0-X)&SP$y+ zLGGyp-AsgBZoC5r1GpKo8+$Jh)EZD^P~dVrz>o#Ld89rIG_}SJn!$qKTE~5b4g0}S zjE-}dK(iEz%nFQ-GayXR(N|L-OwhSB6Cg~`Av8S@Cg{YO4hRzzr7aL9=q#BA2orR0 z%pdRxLf{Kfen6N!ptGJJOwhqmpfO!gi&znKUep_iIOx2n7Z4`syr?G-Cg{AV2N0&P z0;A&{2orQ()C~v|bY9dI2orQ()CC9=bY9dM2orR?`3VRUbiDZy2vZ7l<)}31g3|+x zpj%2Hy&X_n2XrDHwl)n&PJvGW+gL8R4+J{n9o&yWZ?l10S`b-*FW@+ZwC->p`2>~+ z%?8OTfX<7D8;DY&fDT@TR#1>RB8U~B4mU#Rsy zDurSVAHvTt!{8QScNha`niCO%0uw;3Nd-{558^L)8i&e&dt{IkTTwQBL-aAj$_52c z?*-Ib0rgI>9eX9IAf+IKbo3Q6Q%M$d7L_dI7^+f5KJbj4be4j&W6SJ=4dBDglw=hc z6{JBKqF8|sb_Aj{=*TN+#|2E_Q5ocl`i&ebV?9$Hb3IcX8?65fI*^YQTD-A>mN9_W zKp500vDq;tfUXV!UF`t6hO|b3(a|K!l!*Z>m4YP20g|$SOJyKQ@qnak;8HnAQUV~U z0}ODv0wg&RklYc3TnUn#1W4`#LaqWyP6i}*1|e62B&Pt9yMT~uU__Es0ZCp#NVXtL zYJenfAS64GC3QfOcMy_2AW2qJrUcM^t_-zG>~>5B3ap^Ru2U4)VGA^v!543{+cB9y zq%u&XIKa9rAW}IfQaoTO8;Dc^ij)9Y3UpdGt0_|nij)Xg$_1jU0!2y!Ead@_szH&G z0ZaLSq%@ck6xcwwf`E?K?qO8oSPNowFe-6^87+)TTx&sIY+yt&L7`R&qzimYD>L{G zSL6`Ts8!-d3J{%ICD_r|*-E^HAPWo>cpdADmH0qMTZ02pgDFJ;B4wfg76pf&22%!9 z)B++34mu5{9H^)bL=+rq8cYRHQ3r@9IKVWRN}!@H5K(YgX)sklMLi&*;9$~Vs)367 zKtz2&PHkXRW)NPrD05CH1E zf=&u&GG#)`gP_Z6Y805Td0+S=QJjevPR9S(^5o;b~0^O{vz~p!Zk&_U4kja!u1LPX4 zd5{To$Fc&GBmO+d07}NDOxW@u=z=6xQzmSAkOQI%TOQ8X^x0Kt#a-hRA~= z5K(YgA@ZOEL=+rMh&(6*5e47TiY*W7pyxpi^gO77o(B~`p{)SAQxU#A?dqf+AG{mI93pv6?b@ph#7K zr9h)YtfovpC{i_GDbV;3t0_|eic|w5SPnEq#A?bEf+E)fkpqnqv6?bPpvZMVBh2pA#G8dM}VD@|{#LIZ$}Q3j=V8~5-AHx zG?;+pK^-{@(BYY^rc4|t@)mG;8_@BYte_jyKo-K%wGCVzGz7;2vOoaE00+1N&?p=S zNP!570vEUf&_Em~NPz^30uQ(X&{!N7NP!HB0w1^n&~O|-NPz;1f&jPz(1@G>NP!B9 zf)Ka@(4d?kNPz~5f(W<*(72osNP!NDf*6Saso(lkoZ*KfXRs< z$#Fu=EKuU~(!*a)Jf)ua}phIKPr62_?186-Qx)h{4MmJ?z}qfhW1(XhNVCq+5e_6-#|Mb9JgE7g)dCatz(@F? zqKu9p`@mx(N}!Y7K}#30c@T6B57-xQ4}y;xhYO>44xCUS&WBk84MH3q1Dy%($N*mM z&!_+%CV_bpGEl-?qzG~xOO_JIrQkslM$l?_X!L;YOj2NmjJlL@Ul(F$tmmm?uIH#@ zu4k+hL>@MQU7-Zp3ZcjX$|f3$;2{(h(DlovObVc@mqFV@I6!g|pevU_TSvG+JOR*1 zqbU;)=$d8FCKFzeAPeYvWm6^wMSe#fMF9oqovI3a3WA_nGa&`0oV7~Abqc}?{B;UK zYipboI%*UIO_^9~lte&-HOvaU3c_^?A~10duy~3BvjPu_I1gAnLxEX=8%10IES{sl ztiXjLE>fc;YR6Qdz^uRt5*LM;FHxf;X2(>bz^uRl5*LGs%hV`|+c8xrFe|Ww#KmFa z3N=a+c1$%2%nEEEaS52XN{y1F9a96N04jNDsu2YbLN$Aul z3EMGsfOH5uDRkH|^+1<}D+($IfX1fiUTagp}?#l;`IOj|Ns2WV5?!$Jhh%c|5Wfua=Ve2rQqP)x$OI<-om2n1CPN&?wRf`tk~&>#kl z$}oUdG=O@9f`uSgu_y?DM8Say>JdUjIUu5-@MH${2qB_85K&MtGJ|@A5K#e$C@A!p zK|Ml|z(pvePJ2A2bk;tQ-*WCdk((9$ynevC{mha;2o zf$|6_0>POdk;zdrKO&QZ^AudY05~&)GC8W(H+) zaG?N73t({>aApQ&a&Vyl&&&$o%nZup;6eeOmsP-d8Jx+%r2;6wfeq3C-!R+)%FEzl z0d$ovSc1q*?q~u!Yo8f3w!^H!l%OQP78KH$nH_v1G&5)|fe<2FgDiukbPjONV^Cmr zw8>Ipz@E1uSs$bZ)UA=mlEYcyrhxi2GT1XYqznKV1M1tzDqzjEkdgpA9515?-(kqC z!PLU2r~vY#ilR6unRhTMDuTEgiV`4h52K z0xHIYKrYAtWh`)e9waUR5(k%SIUsQc4JHN!kT|&5lLo0T0EtV(#KBXm;H+H&5|@FA zOM}dj1*xw9iOa&oWkBN03i2R9Ww6Pzps-*D4Nrnp*MKCLz(t0VJXoy;Qv;)-vH~+` zG*LkbA`L1yl$5~I;2S>_A;O^ILrD=Le1#!PK>;ERDnyhNAi|*QK$IcEprQm66QBZ< zQJ@_(y`(6p0J^?V0mfwlIf+3Ld=VUrqAG~Tp{NF;cofw^lz^fJh!O$a7znyP5qwpe zjG{J3P(e`#M5!q1f+!6|JrJd%s1I3J3T@gjDd;QcDd;NbC}=BaDQGHaD5xu_DX1zi zB27Cfp|pRLmX36ixgyv6y%E(l#3J;iWC%!6qJgTK((%d zfMY{LLqkPzp^|{3e3@f?R-po@K9(y3Z450eQUH0FF{{v#v9O5yIX5FKtTA-~aW#-5 zqarhCVp^90v_-dpvCx&5feAFfeSiVPRA6zmFH{6?U<0XSc2HncUv zWXw`xc7$AX2U4KG=J=nn5Hyblx~H?yvEGZ95!5z>?41J*Z;a5rfefGp3KO7v1*bsi z8Blr-lwJU(mq6(iPYsEB}7#u;(JH|qgrJ!xb6Xv0HX&mbn*}z+XnH(WkIVphFs1<|A z1Q5YcTm-)n9mMAV^WQ*v9ZVWbJYYWLnkbOG0GJQCx(dV>0rMf3OM&yF=jp8Cu#s@Dw)G024WoBr$1SNmSK>-F?j#&K)GQ$K! zuz>w&0AhmusKI0bVuSss!DItsgZ-uf+QX^A1ooE(lM6^3>?aK-4-gyd9}OlS5F6|l z4W<0~|2oM|Oe$b7yAU00-gOUs=&K(ylf=3rhml3oA9G4t;J{-Ib z6}GPs+N*>uh%f+M$b{TG1+Rrr0&Q_cNTFB<+W(5Ol>ux#=!z}Sc4|=960-UL(uqaU z3hKFoy#lrnBn9n$gF4ul-EKAoHb;zZHbvL2N;pB&jJM}ED{`%_u7K8BA&aiV0ZhW z4lRI!5ghOWe?U%@QUG022oi(@J9MZ4BmiFP0bA7wi+xavGXUM5s=>qnPWv%RtRS%n zP|RyEg($IucmYZrAj$`H>AeP%hZ6WYWEUmyb;u4%JRmt6CGd5~7N8X>8cZfi{0c0{ z)ho23gf4v-fLzfEy6%f#0eo>XOR<7LVX+yLi2@U76${8j4ycfY0+Rx-0@!pOsE~~U zlLC(d*j@pskb?q~0=EL#MIulk7X>EJz$3^k38;{V0{Ct#kdO>i$VY(*G^hy@Qh*8t zC@_JRF=;UAK!sw!F##r^!G8dh-k=M8K#>4h zuq_1<0gZ$Sz&6JSK$Hq72tXy_c>_Ll1zwZ`kwvltB@KbnKWGdLqLfkK5XgSerPQDy zHfVcDfSU(2y2L0j4J65Zl@HM*`G82N;PRgl)F5GYe85-;ItBt$^dv zjUpRXgFr))L>e}M5tnN~<`ZQIq;_Qmt%*RbUD>eIIE-MY51E>k72L4^rSc*rPZYelI7Da;i;MM|ky(EYaZZSAQmQsTF;8uep zWR)d|4{kX)LKa|x_~6!qBV=tRh!1K(;PNYIY?=|PU#EaqTY~gM{5k>2uQT9s5WmiW z^C5m+0Ov#ex&+RL_;m%G5Ao|7I3MEI4RAihuUp`Jh+lWW`4GSEf%9?tm0)WL)TqGK zTEf?o0yR-^=mRwh9SyPsCW6XUUIs@dMHU_=(6Ke(`~ho|NI5bnvhXl+gBmc7kggtR z?|{H$kS?$c=j~UeW1Kml?3K9qR{aC<#Kh`2eR?zuFpmRwMFoL=ZAO#An zu)ZItOAGG%F@S6w?fcQT?+0oCeqe+(09m;I3o+Wldio1E5XZp4*K)HU)^dXua6{K} zgBEZ@*K&gva6{K}gBEZ@*K&gva6{K}gBEZ@*K&id`Gl_J1})%*uH^3IQQbrN9fE!W(fzJAZmQA41IB2n@2wK1mDbW-` z3%DVLog!!fH>4a?1TEl(6p@Nj3XIT_R1vX^o7wRLJE+S6Dtu)X_@T`u$nDL{jtAJY z6cD12_0Pq?i(9&N~7t}3> zM7W*;6D&6ML5_!r8i1AzLYRgMOt9EA0xdy=h#G_XF%YH+XhkE0X$o5S2w|EjFu`Ke z98_BzU{tgKZBu3k?VSh3rlkV(c6(?a103)Q2vJyUK41pNrWHa86yos4u9bq7f)ymZ z;RZcmCL%V$XR&}(T0(S#Oohf4@_8%ZnO+PPpqK`$g2+I-PmnYM+6rN4pdF0@f^0TV4s|E>IMJU5Bs*t`6i=c?I-H1Njmm3h^N%O@IR&E(Nj@?oCicpah5UWmJK~@2pr=cZ+wE{mzVFL!=)yGnkov=6PDnj57rN9VlbZRRw!Wx}A3XHHur>+7ctkJ25*bb@>S%9Ww0E#t31x8q-(@234)`c)u zV1zX~O+d@fAWcS7#CA|K1x8q-(_DcOIw+!Op}+_oFHy8qV1y2(C|W5nLPuE?tr1-a z8_*h(1B{Bc&{z{yFhC1tP`*Tn!s2TI6S%o)rvR4%g(y6Wfhr+b1q#cWpo4+%XH3{8 zN6?Wgpd(g5N2-V@fDTLn9grfWAgv&yAgds!AP*^Fkqb*Cwvqv;I5q$k$BNu2C9pQU z3`Q$~6)Y936s#3&6l{^qL1rSG$pac{0G&7r^9;yi=$-|I8Vk4;1(Sh=94MuO3J=g; zY$Tm1!DpagfDsQMeV`JF3mQ}4oCJw06un#uTv*y{>^U*k{lH zgQx*5PPM}*i$Dz5n1`43UL&-pa5n@EKf@q+;b6V|2z`wczKi7J4a8A_svG{;=1Ac`~1F(|NtYH3J<1vOVe6CB|5UaY`XsKAJ+ z5#(`pSgW%^fKdgx)d^iK4H|)kI*dty1)O`J!?!Gm;agD0A9OAOEW1Nv5OR7UXbc&2 z%o$3OV+J=HK_~fxlL%Y`C_y7c!NCGq5(S#pg+&oc#DfY~STI7e1-Of>#17KO4r+&! z-!uiSUjbDF=uJ~lZx%GA3~n=n@&>Xe;Ef#6C@1vH3(zPhylDz=Z8fdr^-ZX_bazN)*Ku6X$X7G#0dN+|J+5QW7v zsE9GhQc_lcOQA$HC{M!j8Z4?or6MFTF@wqrNFqbg1?kCyqEQ9Z&0+#&5^#KhR6%nm zsPx6mvmjBV(Kcwlg_sAb6jecM@jz(+Vk@#d)F$YX2PB&yxT3`ff?m*Hd$TVm=2i4c$ zaWN&##J~d9g{{^Gt$I?!Fbm>O6$Mp@3_SgU{D=^R_>bA~1E{eD8m57$2Du6DL(u9a z=%@qS6i`${Y{2D9aPkJ#Jm8rUaE^xNK#+N;bvFz6JXN^gpz4?%K^J6zn#VBPA+80f zRzbKE8g?L2)EXS56IS(rbwbk_#ARR)gO(tG7AC>csc0ee>`ZLw6tqqjl;&7L>68i7 z$!AakRfgcxNkLUFxYfyooX%0wDuV(zC_q66PTHXRLtqwj6)K=;geTSm@D{*xPDXZE z3!s4+dF2=AoLxppafG^W4YE29w3!Dv{K4Z9pdoqCZ6r_)C=m_{N@xOvMmSgtXa)y- zk};?V1RIE=i^&n}4sdS=H1P;3f?>fAsSY5{fnWCkjb`wYB9L>~K_|!{;uW6$K)C`I zvoM1|a|RF#!G>bd1(OA-MAr?<`(SHfcS69OVgS0(0!0eNkC?3)CW4^?asb3c)T#vJ zEokV&Lm3o;5VgcQnH}1%gsMkzEyxC_INSz^YasUEibseV2nio7h6WMHOjz0gXDX=u z5LZJhR3x>q6o5@Fe8L6lI*{4u?giD4;M50=V#Kf{)D`f7N?3%0bU@{x=7N(5KH6xKUp#&kQY( z33^kP0Xn=4YFdJd0C2X1dK;9Dp(Q8CPtbA_lwe^#`VLy!2_ExB6#?z!1YJA?_J;y= zH!IX9kgJav6hIAlh;0!6fKJjzj;O!?i=j3`WRTT@{EnV58kk{So%5WGrm%wU01Kj^ zV}Q+xgZ7(3Tkb3h46xxzRs{yw@Fbf818jH_bVxIFP?IOhNE}(7z zbaWQf4S;rBK-~bS_d(qNXvaknF*>V+7@Y;RXrbN*jS@pUE}*eskoVOkepWr#J< zf)zyvL7J4XZKs_?hWkH~7z!VZN zNb+h5;AJJuNV7^%dqH^{658l4LL0P(P7A^&1rbBikZC~^NScwEifWDw;EgW~%%DZy;Cu+JB*5%q1%@I;PzbPODS`UQpoMTCc@}6nrN98{ zS22LbBo+8TOg=DE4a8IfF^fTjqkI|ncUDGDSb?@c4Qa+ufl**CXxa_w3O{?4EBx3% zqwApiy3nrhV*~94M87K!yx{=p3O~g4ePC}wF6?8@0xeeq?UiH!?d^iLGZ{g5o3Vp- z6FD*}axgn6a44|D?leH5Hf$x^@`@?gIy zGApoyVt@@4`k+_<#{e6841m=tP#g=8u};=9N5(=WSiKL42c#Jj$bq6v4hrCK0%dBj z?E=%mq0Ix{6$4s=3OceD6eA1*Ge9z+b7vQ*L30Q<;^xE!Oz@i%L3e(EZasv?ny`lBoCtGagEZvkM40RXS^neNsP*W4X zOBR5x)PZ&8K;}X#Bk%wdsJc_)a9nTn15o&2jVaL5 zO3*pf$QD7?GlD}0JgCpBfbI#fE>PnR%TzB|H)!A)yu1@+JF?jzPoTOTSv{uvIUFCH z!tOIh#|E$ru5`2DBuF2wbOUPSF*_bOjXm8!WI-f)x&bx%z##*_GZGp*;6?wpsv6cyvU}3G8}Xi5Xnpq#|LLYfrT0TjE)Up z8JvN92BZ&HAcIDHm=(~25HtW{02({yMOzX8YQ})(roh@DSrN&R$g-$G2pV!k4?>6; z5E7jJaF~Rd%|NE1rclrk+R(8L9Hw9f91A=LfV_+00(h~4Ll!n-f?^-2GzRUx1Dgho za9ni|sOVwBQU8Ga19dUf6i^`uG97FhBIMyU7ARSP^C?0OTE0MJK)C|!DkS%UF2MrV z$Ka!9lt3dOuxNv{dq5`_96+4Eg{&3S>;zAbqUiwlpFqpr797Twalzvz=~xfA}EVLIEXE) zLVOD$q1{hVz(PwE$N&?&V*@l`L7{*iundsFDJ2%iLrcy|6f3|6Dis)@TX*1tl%Sq2 zcn}XhK&ik0T|EgOoK#?duAGDqOoA?u0}n~S2PHul$H7D(<8ko8NYG_*Fe%7LoB{)M zqZND*Qh@=wLJ~dz2_Jrh4?aSM9>JH}p=`NF9zuZ~hyj@pR^o(gzdryvO$0Pi#sQir z1E06XpaeR~xdjyd@KFP18i_zIvU&EW8drb||Y2q@Oz zi3*f#$ViF`p!pPRaSTqLkZu`hKNXgNFNoVg7rQ{*2T8sVS0h9r{UPwcIyn0&z@<=} zkF^Y701ZceU;&Y!P6OB)6kT9r;S(}&Z$NVg$V~Jg0gdiKbYUiah?l{c26+G!nlT`{ zU?eeifn5$hU;sYsfE-4k{wCN<(3l0!+CahxE`{P-kblsV2&kC_i3o7OLrMn}U0`3q z!w764NFMGhhzSr9?kf}(V1Iz-?-d|Ugqs0Rd|!2uK%NNxgccmSL4cmcZ_(EK>)mKF`B3#_2k z8yZX>SU}hCF=vAgt^zIK_`m{@zXFy2!cwfjT&Mt&`T~`@0hRiJkop0Yx&xK^gOK_I zm3jb`YG8#M*uV<0>j_k<1tHY}m3je{>Oe?!K&9S5rFsxjJy59+P^k$BsR>Z2FHor| z2&pMhsUJ|O83?HvP^mvqsW}L#IZ&wuP^kxOaDP2ugZOI+RO$&r>Iqb81yt$H|XR15|1YRO$;t>I+nA2UO|@Lh1)pY7bQE4?^k>RO$d!s(~Hu zuLgFAzm7nqS`bn#P^lA8sSbox2UO||RH_Fd)dLzkWdbb`0@WiN3ebf?;EVuUHvvt2 zpixNhf=9@L3rGfnlh{`nLNY1Dd`Q*-XI6OW1IeI}toH%daDio0(CUvbEU-+X#90Iq z_`#yY3TFIaQDOr#8d#OMz>F4FC2laIgH?$K%;;fN;srA%uqyF^8Br;B=m^e|pq?U=2GbGny_m&jOyJB2ssfobm`=b1!PyWr z&c>v{bOt5}&VZnCUnUKv3ot=&)&mU_GifkgfeC^$9cbA(lLiy$E?n@9vf%6nT4c+l z!E^_v5}eUMw?;8(Fg<_?g0mR(RGud=L2%{*A5Ejd^a3Ub&Q^j7f*_B+feC^#6u700 z9958`Z6LGNpcAD&z)DRiP(zC`3v{56;|BP^1VlN=v(U+BP_Yg#Ai*I6vI0w`0g?k* z(7=`jIr>HlG;0p3MPP=b7zMHdQqqEx6uKN*UkYS6xK=_~46ltq$q!^P_IW&zEF=L# zdru&nAbLS%Ie3BuyrvG)x`nJd;sj?TaJB`dAM~sP4o&c~d{7e(yw(Y{cL8J-QTjo? zL3R!JWGvXZR$%vmML@S^!dAIK<{H3fD#7Y=c)uLWP$9?$=%4}EJjhO6CeV^)$Vo)- zD>R{B zMrc8D*vD)b9Vf70wON4yI-UYvo2>-uctgtrXg+5I+loyb{G6q%q?`jEM9NH-XKKs_U9avDC14?4jHb|`%*_`onm=o$df zun1^_A?U(+P)`+f@V)}r9Pky&kUlHaFj!kdU?JGSjF9dCqzF=AjPRx35sB7eFbZMfI1)G0Z7nME}&=vo#WELoTUUEP)AV* z8h-`tbpX+zjSd@_(dTTyE&};n3AE(_H1`ME@9=;*O9}P-6o@)d&m6S#0YrnY=>#PM zAxPB)w-+>u#IJxM%9y1jtbh=Q^@V3JWhsHS?!I8jQWDiT#n476_s76-Wt)W-k^1BinbM<5@A=C&BYgZxa;foG@*5RK5X zRsbdWKz0X!t$?kIgZm2MDCix)P~*U=!KaxsJAw)^L1+;K5eJ=H&g=*(#)MGBPk@ij z0TpDzDB=ge;-I2T1V!8;OMw|ymNA2vpi=AuXmvj*5Em<+^hunagF5D@@cV-AV{M9_moKtYcPbdU%r z&=J8662ThW6F}u2G*F=ag18Fg16b~ch=5%Kx`zx!9fyJ_`dl;UR9F->+zMg}sJR8y z!~w5o0@eDk`6Q(L0xF{*0S=BPcw~U`9cYdfRvAIU38EU5`jJ(G)S-qaL>(foApQcW zgT)m@1hkqEk~QGnRA`m~RTUU@A$YeDwAh;>!6*(Z_8zby&#HmujX;egY_n>NpcPlp zQUmH&CeUFppke^DPz)*s3Ltp*9+dE4y-SF*!CD}L`H(p+NF<=>0{6>7tEHKW-h2Z`=F6V&KfD#92+c881G_1io!A)yU(49bN zav(=SYEWqDkE{#ieU>bEAr46;5c6(;CmleOavE9C(g-2}%2W_%DxgY$@)krw0#yQ( z#UK&_s1g=gpf=eFMsOny#5}-g&b$G%Ed!JYz}A5pBCN1792R|`lxYAOX<-%X$DZ23exF^wX7j7 zVFI~AK?vRzf#_jDh@iL)XHo`DPGTK~1>4RH>RUnvD`5Mtk!=@&?|p~Z&aMC#L9rcY zQpRmNI2ns62q}m_LK+^~pjNTCf-u}>WcOe#qtOyK#HCD*kmL&*-$qKpkmL&zL`uSt zo+PQu`#9VCd9gdxdy2OB*7ZeTNK1|6sm9tpxIf(<~uaS61hCnR3Q6vWZ|4H`p6 zh(dfJ4m#Bcq7Egz#TCTS^n=C%Hn4#vzd=iMz(pvE4lxCg3Pjd|nJ*4^9Yh484n6IH z>_bhvpfLzg{R11kg6IadXq4CyCksKFAE0g{bOs$7&6o)Wqy}7>LA;Bk4z)i8X?cSd zB7jN@)NUoDea)gEh?Z$EZNtniAT^LO6dZU^`$6giQCtLRY=Y+HV2x0i*Fkjwi-H8a z?1hMf%!LIVBq@W;gcTSN5s(^a-HBwc1d6?o_8208Ky-ql3zm=|_Axo`0GH~Zs76Zo z8{mRS34aA#5Gmm=fD0le{23rYP39G>pp-8TYK1HSGr{99O6&?^XiJa5BQZ)W3gWPO z7wRvNPl*W)F%-XpLJa0hh`+&OI!f$_1E-+oGdP0UpezcUXq|Op?M3aRfb2zW>43+F zl-L#c(TXkb2$2%#?p)Mj6w_W%I>*cl=v@W|jB4!x8*Hsz7Y8E`tXBY9Ylj#N0ks|& z;p1hHg}C6+YS3LHpkYxZR_OQ{vjTdL7&IyY-X#w@Fa-!J z1$6oysN(?&e>7Q8J_QXfgASfX?*c(i*@4{U3a*Aw^g>b>X!{Fv=ms9kpjIDfSOH~6F|ut!^yBn1{Vh)Q()_v;MRjibwQ0@&`~E$ zpus^DXM=l&(0~TBLCrd-3P>geB`okz3aD8FOJNWxP*)iu1sbw~m3IX7ie5UG6$&6Q{V(O zbU@Q0@FW5nbpoBR2lCVg6d6#WYPJ7 zilGV=@t_ej&}KDGnCnnffzD9@?PLUXKp}>}9S<6_Vup|Mz~cA^_yF+^_ADiCXh)ja z@dH?_fjvu!2QKykEcSyfONkdQ_5dvQfh|jk4=#2CBnFE^@OU674lgh%fI7|(7$7rZ z;OqN9Z6;7;L4ySDPEa&4fjU&6l`@Q|y=zFp1lmLl%e=4%0~Ji5p%Bo0Q=r)h6wgBn zCeS!B$U@Y55K<_CrmR2~GvX+eKvPwqlmg3kFl#{t66h2JPa7T>zQ00M(kPxd%xSZJ>@Bw8~t8*|CEWQRGhm6%LLKNFp6zksk~QH4R{q z4@e?EK$9h!%o(62Ft|iX01sY38%JnGH(1mWTnd1R31}q<=1c>)0R}p65On-Anrd(i zE5Rl+kOpv}g*T`+giQ5-!w%N%0+n8%gS8P z9u)^CHi1>(8V@wQ0ji&vVSG@T2O25>ZxaSzz^DXGicpI|TUY^+0zhIG zpiwt?GGKxwg9cEx0^N83^Dsy)a-@QS2Hkz2Sil(X1;+qF6y}!+u+WD~fx-!I$WMUW zFazFJae)Kc3PRBZ3tx~*^mqe_ftMb_*Cil31vEm32vm^cK*Mv0AO(ql#^w+K3K9X0 zDQ1vLerO==W_LGrL|Y@l@?7`j2e1r6VzHt(1mLH+^t zWSVQ9h zw8{u%F4!C_z5%%mlC~gjftinJCPPFZ>d@7|LJnCCC`q8JL+utr%tFLDL^sIou&9QJ zK%yFwMqo0KPysb-LFor33Q^AhoteAA3?1uX0xfn1)%;A37eL21ff~zTF;LylZYe0SXOjQ1?O!wV3czRrO-P6@OIoCS1IDMS(Y1mOit zIoV2VN-Ri14;XT?mDnKypu@jFSb>?3iHQMxj2Gy#XwZ3QjF1gw3LHg>pxZdWd&wY& zRD(`v(qM`KZAOX!5g{NV07UqJ2oDh90wNqhgbj$W01@CDiVZ+49T1@bB2++x0*H_S z5fUIm1Vjjc2=Kk*;0w`NKwJjooz_Tf*nY5vhK7cU;z9)u(1CLtu;aapKzApDk{dY0 z91pNS#sQ^xn7I|0U3nR~6&Mvc6xbD66xb9w6_^#dKKaC3vt^Oq?f|C}g+{7*mD(^u#oE=ntL$d;!0ico_ z)H}o?i?n|Va$p|pL}(W9Ms)@SR)nWHK!eF(0nlZDkN{WY1znEg$mGcj+Tgu_DNB(_ zfgR*xMbPTO`Yc7zse|B6qEOF*yvgDi0H2FMaVp4{&^ZbeaghJ8I39Fh2W+$kMLnn* zV-;8q4qfmSVc;9XA+7@*XQ;#gjsy+`HU&oT39n27>%fW;BFq>foERbs7$O2N5m1a{ zIZuTH+(yDocDxF_XggatK=m$G6F{vaOcOXjlUJDPxfQ@C6haCH?sNQ%e6Z$G0~_)r z1GvEq*|ZJ~XlMZiKA=Vcl$Ifx0aEmXM{z(24ivRe4Ja`H8hU~@Z{P-j4)=hZrUo_? zQkbLYg2;kvAka-4pmd}JP4#e7K-;_7;I%f)IiQ(A@DWFFDHMZ22?ADmL9#P=kWB$% zAtC30vKVMy2$YXt)d$QJkaIve8#Q!51L6i*O5C7p2C?`Pl%8ReelUYTT?k^F193RI zXF$$Cm4Sr}sG9^jz6>%z2OBCz2^~<`0PQy-f*Cw&3Q88ZLkBe23p%p^6!;MT!#%?Y z9-QG-V1Zc(HyC0hNGoiZ3Z@C-2V@zDA9$f7j8OF`P6zGDg^I&%0GU82Bq3@bBw{KX zW*=gr4kCg)C=H&Bhr}tguK;obEcmdgM{fmy)T6r@)VhLXDsVu;Py2?AJ}dFTn!iX= zke~!+gg3f&e*PReih^xT8GSJFCSg1gS6+q+Uh|q(Gf>z(5 zsRJ3P#HYXp?}$KB6nHU$5(~yfXpppl?lf>RM{+R4HWq{kN;rXrn4#q!)N6bM3KP)a zD>#Ruq#cksu)GYh5uy%MfFK7ENFA)ifT#nfL+E5LtVatu=$uD^#}QQoHg5w-$FQCe z#2mN`NxL1G0G&InP6 zZA=Pq5s*#r)CHPDL`zu&!WlB*hMuQE=D_MBh>Z|+5SKwjKx$xVA0h&dFG#`Z2y+D_ zj6nyHp^8AvLllJ&6F_F7#xJ-h0^08c-fjYqXOOR<;S28ZDuB`xHd*kIWYGHj88ai| z#AT*zB{qmSlY;^a=(JTf#}ABIitGw(pbVnOp}+>JP!&NdszB{iE(K;qP&1iFfkly* z*+GE~+?-+(*a&V3ftq5_1P5{&JVHS2H*Dgd8kQTB>7hjtiY8Dm4VyS9%-EpqG;UBU zSP`_m8`Mq%?WQ`w2x?98g3f^E1+~|h928iI@D}(u00x1@U~hoVELLQN1qi~!OfU~a zo26uX7g`iyco&;Ee(%<2DKUY(slW;**+5N5NPKdCQAAu7&>)07QP#i-T8stn{(!c5 zaAtvYDuK#vSWbry6@muJa5O-{gJ_`kJ!qB@ttkqT0}a-JMxC&k32KspF4@H<2O6{k zfh;A^Ee8T{Q3VD^4hZK2=u{pCu*nBNW1%3U4YHI#Hz62gp`OtVnr~#u z0?j=u@qx}VV}zIhayUp=17nsFKj=g=H1Qwc`6dQO(0nwq2R?x3oERKIv(m`oFTjh) z8600Qz|B`+&}2$5XI=oB7X(=anh6A5xd0mTf-OIU#V<(y1tVxqiUD+`EZAo-Cq7^V z?UDoE+JGW{gAueT4t#F|iueV_EG5u&4HwY7bb=AI78-na157>0iJ-kK;30aD8$bCwb@Fl8ypDKI$hKoj4lXs`M1}2&5{|QUrYkea8joQPL$e?SgE@E(5X^ zy9}sW0EaH39qqDc7NH07n9(3WWuuBP3u!GkDPGfa-uog#r^a3h3&7@IWRg z`XN;%UF`;i8mOHIy099(PH*4@-(P_>se$A`b(4XD0cd<3eD(!M3{)?ni-GDSbTLqU zgf0fEi;%=X!|w;U%$W~>CQw0UgX$q%?gZ6Apu2DuT*8)*!FdVPY*qrPd4Qv|0GW+T z4q^hR4nlGvIPgIA54sqr?m-s=)jQ~7pgIRh4CLbl+~&*+AeSAZ#s_BRfVc@%hO;QJ zpu_^G{6-f8mEGuKpmG~s3{++##Mt3WX)rS$C<9{;Z&0?y6_OxxaLIv^e!~T9F$l5? zy9~%K>@p$>u)Xo3NT+LvK|@L$>6{G-s2F(3PXn7da|4?K?iLNX?HCya8K^z73bIg^ zoPr#bC9fb4Whp2qKv|3m;Mpr?1_fOOU8tCjf)13Wt)LBMX(?zyS(*x(P!`xPpf#%x z*c3qZ81~i~Bbl`)b?Z!UN`@5G&;l7!6hez|+{L#eyg&!(lmG z4#OL8o;Ya13Y-TzmFNVV2et;<_Ll@XhY{U7pj`0)YYqkFiUu4dE2wpkOHM|C3EZZK z1cEFm9+_avedQFG!0mU4oIGf40bEW&feGAJhsc3l4sEL|Vl;u2Kx&y`rYeJ`pW!?e z1t!NCaGokCbm2VEbzz{kHpC8f1tVxQYG5>)G(pkK0<%F26wPp+HYl3mX6k^#70%NI zMKheos9*xMK@X#u1}Hg9eC|V5@~73KHLEehB- zv$HsYDqPT^`6!c1(9Sdq_zXAjB!m(NeEth@<0?cRMq)Psw73sq3v9R^GBD2q8ter1 zV>lJS(y(pc#elc>f`%+17DIvxbKV&=`30RQfKID{hG?-n zfd!nD;S1nl>cPnuAquexJj2MO02fAy4A2}6EO9`>3%sQoPqGEgb%DbO8UYYXK;}S1 zL6fW~QVKwEYL- zUWjT)&O?Yo!XC7>99jZ`d;uRN28Ab79GXDDOIh&5EhJ*#g$Xn@gUo@gM1j}{RR`a( z4iN>ZgJo=p2srU7@W9p=gIouVDRB5IfR>Aa{f8n0TA2XR304ISFNlet{E8Y2pu?@< zI-qJHp#_?US3qCN2AN<4Wm?E0E-6rAf}cvj%Ha4xg4+Pp-eNXm0?nN;m@%fVi$1o`IIx-dVg3RT0 zWGqtRHDh9cEK>wc>M?^BA2Mq&MJO<9Fol4K01)8=B0NBZ3y5$45jG&g0z{aA2m=tI zqr?ZIG?e&3l!}r7h*D4z1W__dLLf>)Nf<g`$tIZi7S=2U5vcg}4U2xk%-_J8r68)nQ|P#B z03*ghRp!5i8^7n#=v$??=zPJToyaqPVj2#bJg9)k!9>hvKp!s4Y z&`pV;IUUgI<^@YpdM5BP0JOLcmmFxV#0AzYfmV=HTzQ$m30097bVd3FmMn16<#iM& zbme7$&pv}vDWwL=Exw>2om98;sy&c3p9hdjG(Jzc^w5n;e%ox z4>SqE&EjDM>4X?Iff1TbxtSak767RbRI;K^PsH)%ya&?Uwod1eRD z;u+A<&I&w5ilEX5d=D~wtuJaic4YA5WpHEz8w*+p4E7@U&Toj#-~*?b37V?_H5GDC zk|Jny12l&ZT6_#TshULre1jr*#V*KYN<1((7Ax=;D)4~Q7xa2%)I+Di3wjwen0OSK z!6gO*=!)V444`OH;C5sJt+E5(lFg^UEYJrEX$5GaQUEPU5aU8W@YWs%N6@(iJfQesQ35Tr$pO#I!{QE9SPH?; zw#>N8`9kc z`3xk6stDu|21f-@QsV}t3Q*ExHe&)s1`iJ-w^Q%vB>R>E4sGr~%ErXnRi79hd|L>Pbw9nkUU8cZ5W0wA7> zk`Rbe0NqTj!6c)^2jWR6@q;K4B|#7+pd<{Uc$7py6o-;1h+h(U5*tfZ ziYSCYiI)SE*%g=|nGn=X1hs4-DL_gAQor(oD;OO0s{mLMqke_em+18?3sgCJ{R+D7 z9#pZR*RQbZ8@+yo)zj$pt1!qA^!gQ68Kc*);K~@ieiZ|mfLyiHfG7m(VgnVq57@E<`ayb8DqnCZ4&IW7NL_c>vOvjK zM~Mg8ZUgaRKtu$H2mukq=PDkMat$SB5TydiUJ8)x1!|izYA{JavX=VZw;D_wN}M1bixL-zVo+j4%0$RaScZa>dFU<98{k_&!EH@YG6FLo?Yt{&Sqi+4 zkn8}Gg0LWR7uY}zQb?8n$w62Uxif5_#wR3OfaD-7h};Qq2MdxlKynZkMD7Uqa6?G; z0LejE5V-?vpyPSLxuh5*2Vp_v_ON9sa5zG83P=vZg2?S)%TnNkG)Tevz*z@edUHE& zVFPVY2Im{F9E1hdr@-h4$~z#_K(rat1~y2=3?)GYH>7C?Nh4qqTHk}&ijZ{82C9!4 zG?-YFKouFdb_ZR?1=}tJx~A!a5NKf;sL={;7r-|SF*zvkI5K7_@!+WVnH6|ZD}KSdbj8RXQD6XVPhtU`6AZsCg_{T5UJ=*@cI0#x#KkF~ z5l`sWUr^Hr;!p-97Duq-z;0y()hpnIF`#xXbft_G4pxWM%xzMpbi;szc zk%b%F=e@v^1x*5A?T#(8A$QR-LOcno)j?fjkTP&t1DZPmZw&r26VyL}DPsgp7J`Nf z!L1L(4mObR0Z?OIff=m}1m30%YWQJ@FJJ{FKuq-)aEODtSfH76*vJTM{on?0LdG-) zG~fvKEV%6ni95Kr7BFQAtOrGbBZDHSZvtxSLw7QQTX|58Aa=0=_?8+5P?HZdf(YJY z#td!gDS}owHZW&_FRB3<1iGw-MS%gNQGu~Y5tO7@vXnq)`a$*8XDP52Dlj_M7lX;H zLPz;BMP^U{B3iY~+#;aSaY!UFIzmGqEU3Wfh!Q2-Cj${f7@+M@&?E$!?qdZt=8;yR zP5=uaEkNx63m~mMZ2$`(mYq8OU;&u{U3$s@x&#HheiD4K9U^MsLqYKFD|joh5@;M0 zx~LyCP=q84S||x>v_pq5(PRxk2fBk6w_-CGw3ZFD1rEBC0Zl7tCIWP>J2aJ`$%4`- zc)J{Aya`Pfv`Upz0kmx#o4ps9Knr+52hU-ZWd$wd1?}s`CJUMe;ZXn`pN3VI0aVO_ ziV1A8pt%x0a5o8ytO6%&j33P}pxni;0J6iUvXB~M;*^Kb$aKYM`AujJb};80?5TcarsTm97PPDFvHNf6_4fxy>Kq(B z)WH!Jqpm>I0i$6taA85awg~pJlN3>Uw*s(@ih|Y-BDoncrUBaetkTfX(7?bw6?8Hz z_-bgT5+zp0nk*$Y&^k&bb_Hey2#cdgi4(M$krTT7vQQCpy$`En1yrdbs{$iLsUjPA z9c*ou5;thkEF);kRf!U4cbo#V0!tQnOAnW$d@1;-Wwzo%1@>Ykb_Es%Rs{~wy$!`m z*sNkv;MHJaP+%=CRA4Oz-EX151LA|UvlT0{DeySfWGV6}@Pa7NCcpYDC2sJ!s0`p$ z@Sx?}pj$TB6u2Da%N!XLI2{GblvuJs&fswrC@gYhP+(Eu1TFYh;4D^RapWjd;sML@ zI&y$zc@$W{+s;@(vMdN$7ED3)hUA`Nr_EL0dz|yW0n%TBU6bZf0koGp%O>75~l)3Hb|05 zgNZ>29J1UBT*V69*`WQ1psfqwJ%Eg$oj}}}@3apBJ%nk}1;NVfic;8EZ%%m#U$1>|~0 zP=xR)FcvHDWh-)nR$fEg5B4}yNtPpn0=EJmSOdsAd?4>|D6oOu0XmeJ5ge8Ze8p=O zIAGoZZ4p!i-GdDF705x$6*<5=zLY@c1S@dEyaO=?v>usJ0l#;cL1DoR@(w6MKpx>= z4tJOWJ9z>0QBUA~P(Uz#A<2!N%4ou$eM3pav5gD6HAQVXero05_gnfm4Ht0lcvZ zyv2|cqzoM93Ji*D;4_Jt9p%cvaj3-X$W#K_z6XmxsF|RPP#{4MN*{_`pjGLh`>Ewi zmDq|E*dSrA01ABt7#|eopsdRV3SQ8%Y6kGydIh%PwF-=|Uc{wQjK|umN zikSNf3oBziV;yTfV;y5XXe&4Ogtpb)9ffr3d#kqdOo5ok9BqoaHYICdNv%fPV@jw=o&Zjd-5L=Y5;pzW|qV8z@J zK~V59fHn^ys|1A`CrBp;L=nhM93VbBgb(rpJBZH);e&k42I8|q_@Dsd0>@^J0u$Wz zOdu7U5EUBWliL}~z>1bT%7c=ujsoc77>GYal$an2K~VwL2z9Rj_aSCR3HXr#49Le? zgKpXt*b6F9!K-~hT*Ts9M1=>I#9WlksKKNIDj+nNG!$7tc}WFSnQ1U7D6)ZgGK%2s zRT7HevQk75yuC_55xl*M2XrL51`~%O4@f18A}@$yP-Fz9VjV?35T&8W5292Q!M7PH zC<=mjGKxYVNM2RRut~*i`1@U+k#XuB?qBw|RQ3T(I#GnW|AXx)+lc_-#=zMEt z2Jo#{jtWpA$f0uJvlc*yEP(EPg&Zvh77~D}f*ddh76M(>s>y5tHU)IroB@ahI^+R* zo|Xc$0$;HLivoYK0;_^Ru>zZdV6g(bf>5ynhk|gi0;hsVu>zNZXt4sff*7cV6E9Za zRgfrFU{sJSM%rhl!~|+JFo8B*ILeoCFXv*Eg~cKGt|~|a1bWyE=ypQT4g^T#K~LZS zZDoMAYoMoVK+d=TUu?&Oe9jL%ra|{~L%X;zLqIzdp|)Tf00*5O3%Zs9x`YgF5%>rr zHU-cf%}UVaMKC!HrWi#gP{A1iYL93zg(z}@cmaxBAj(IP8$@|1@_;B8MP3l)pvVWJ zY!vxHl!c-Ih%!+W1W^WxLLf>BLo5XGP<2k|q;-BalPg&hCEuE2(N0SgOgb1(~Nb1(~Nb1(~N zb1(~Nb1;hrlLyEO7ZBk9B5Xi}1&A;K5e6Va2SjLq2o(^a03yH+g!ll&1&0ARkT^hG z77&5+k}r8sVv>h7L6sC7|1S>2RvXxjB*%VlzcK{$Or0$WGnGQv_sqAEZ{x_H>lCg3AzLgw)L4yfk}ZK z#^H1P_y7NY=0YV7Q0tLLkyU|15!8HS1#QLzRq-rYpqdrbQe*@*o_QP@LHUSRk(Jp& z0aX#K)yl)f4Z7n4q>fvG#gVNpgRioyzPjx0rr zB907-qM+8XqePYh=>8G`(1pA#0{cKM1ji&rF$FdaCJ9AW5Ctkz*)*60K=++!Fo`HK zIx;FsI5H?oIx;9qIWj6rGdn0qD@YbAh_6*(1f6l=2x_}B6|SvSU|kD3jj3>Lt&)tB zLWdJ$bFGrBlR}4*+;S!PLL~)|CItoQVkKz>rowDRPyr+XDm|1GK-Hvzf>g1R6j(+= zK^)ZMkuOwWEC#it6*xf36gY|%ITWNpF(R!X1)`)B#2gtxrIMJxB9j8EqL_l5f{fGu z|NsBHEfgc|K z+zR{(JfJXTP~ZhoEDC%AMrT0snFyh(y0Oj1DtL`e`8Phx2CBo4|Z z;=Bx?9N-A`6WD)@iqhN)YzmT)2$XN*r}coS;wx)p;Cs3Y<;~9W_d9c1)nV#W+CyH;y_5Hn1S49TNxmC?ZBv zCLWkdE;}Y3n4mzN0vA{%w;huJOi-jwfg3EyW5*-{6O^b^-~kKr+A&GM1ZCWs33#)eFpH0l%tz={QyD+z&mp-^!h zm^jCBC1Eor9gsPoks>7#GbRHCW>Y2|MNtr?p(qBTR20QQl!BrJh>}s11W^)-QXoo1 zQ5r-ED9V5+9z|IY#i1w%qF5B=K@@|cf&x1zx3fC3fQCbu9l%XHRt1)vwMray3StTz zbqeAjLIOlcf(R)PAq^sAK!hxakOL9&AVL8|u&%8E`AvZhT8h>vfulu%6V3<6odOq} z4~`54Za5zt4+=bRJ~#>#c;S3-=qvES`QU(8;D_@;!%;N~f@^D(z@e-lw6;b`5$q=6 zwKYmgpb!OBYs`)YZoJS@DJBKxEJ!LtcK32ff>Z%{i_w$`>^(+PCa~8TO_{*K!f47Q z0+knl(mYU_14^@iX!JmU@DYIk2^2&iKmr932#`QQ1Og;b5P<**6ht6E0!08VP!!>O zf#r&VplqW7avUU_l#nHbK$1ELNl?&nELRj(-~ff6qKE>d#Nh$mq|2_r3CW0Tpd88o zxqW~MG&al)$#z_zED5^v2_(e<>J+mp@Ivw#4=4|UkIrJ(WEOx(@k25eA1Kp-E|UW3 zl7L7l+A*mpuqz0FavA9MDUg%`L<*W?lfE3abna|L4h8TiG?N0)a!|vfFk6vDfgRND z0pGd|9l-?+NHf9Q2#G$}xF*Q-<%&!STp%}su1AKtkx79A=0=EdNF%v8-3T9Q1-XVv zfuk@RG)2J(@+tUYI3CDgtpYo^<^YEnbX=7kR2Q-hP0^_m=zd6qlL^0jG!?^W(6iQCQu?(0M(Kr*=9@v3e2EkQVk{%flr{* z;v5-^vq9B8vj&rlB6z+)L=hZN5{e8UJv^Z6lR=GGRt08wy#WP$$cW?~#EBJ0t{rS(0JR~QKu!Z4wa$^{C;&Qv0_jK!jx0wGkPyb96daBq9Y5|t zPBvl5a)dECvK-$$KiI$^u(7S7fq{XWiGkaW5i}$WD$5x`2d(HbfV&nNOgknXYG7~# zwPx8thu8_60<|1@L9-EzRt%sEx*Zv;7#O%s7?>O!8FU#=fRwv}(!K`M1u&bR+mXSM z(F!8t2tEJ?EaAw=t;NV#53Hk(q}DbXE}~=&T|} zMHbMhg^WCG+@K>b!LpzNJ5Djboo02C?m2c zFe!p3$ru!%2OomXX94>Iobb(<7`Shv=4faR0>ufa)55I4h$T*#K?hgjiW4T}IAMas z3FKT+Xq+%X;{Z@bsZ?daO1R)7gXdyiY6v-5djJaL^4MS6^SfIXuvQa0%i-SUcAY(M2i&zJ1Be;ds$5sPF9xab4tK_yUlDlj`Sm@`X&3K(eN z1Fr29Sj?F@6qubF8yXq}%)ys^!GcnO8QijgB{3#P_DjZ^i`XfT|r0rUM{xCGh!~jtmNn0+&EBro?Cl zkpLwzMo?kQ$z=6Dyo{jW(14f%76+TBzz9mHpdlsjfqtN=4<T01_|<3ovLhtbp;DoTfB1G#p?8)kWZ@E$IAwjVwozEJsjfroiN=lI1u7 zv<3>4T9}-e&6z;=C(VHbi-rP|ASRfN+( zO(1CaDuF6?Q1g#Pfl=TB#O07W6VgrwOEZEMXfO!~Hi3ePK@k)~jt3Z^qhksT{M_J3 zf)=q%4B*4^K>bWmQy6A2HxGl;w?{uVetNk6IV(3WgVV)zGmgw`-t@ht9(FF{ZBQEL ze!zlAEe7zKkEp}~3M59y7k5C_I+MU@kblgXLHAb(WI4V9i-HceUT0OAO&04V@R zfQA(V=)&IZAYn(48u={8Js=KL4I|itkV=ffm6wuKr~-;eP|9I+JOi@9kzE1Q5OZt* zB{+z60y|(1(_m78ry&JU^~ns%d5+Nj0VoYIfpQL`6$8kZ3ZO>B6R@Ey0%t&GfQ<&X z7@^+T2@)091tJwe1Iyr6A*d?`S|iBlxCyM86&7@$3(yp@9AUu%E>w_$1?~X`$15O> zsIEs!N1!lPV03%~F3{PKOa~Xkp!y#i1TcF*EnLStAjJ?9r655D@uK5(kc1L1C&gmNuL{2{5&Y2xW6+Y8pQ$_DH3!w8o135 zZl;48ybS{Wyx@MAqkW-c17ndD123q*;mB6zcmTxXaRl`hyxr zs=zt0UqBLIzktG<8MGFKCrbf-)IF&30r?PIun0h7&5?mSnUSd;>}e%NP&hGx3RMOy zZ3zt~4rp@%)DZ`@Y#1Dod*h%fZcuNW3Dz4IaAbiL!`$2~3=9n16HsFq+Uo zOrS;)Xb1$_9Attw2cd3e1~>aaF^Ri5$mGh)PCduL~AvNNp%aM^f8RV9TMUxFsU!6&Q6Hc$63&85J0%LCqvaS4AdJ z(gQ`Y1`{X+J4$2;Tm;24w*nJ)9-^TkkgWs_N(DyHs1o>M7hMJ(UIu0dfy*Ebpw=Oe zE(4D%c*=!QgNa88k~x(a9P2?1Xi$VgVvW&}CrjWyNE4`^1@kcXbVh`Ih#?XM@BkYN zNH@fE@W=#Cvq4Q4nAwQ&Ge<^#ZUts|yOJ5v;9`a}_Lv=?fSMVg_8Pd2GzZlDf;G5e z7@6upDF~W?K`BI$0bD48Jk6p6YJEW4`QV`{&{@Thl9sTAJnv3q1u!ZV5Q47jSH}I=x zf(8>41Gfz5HWmg%cq%Z$db@jAS4}EfXqcwz{J3<3Ldir&HrmKtpN7`nH<-G zT4oAN(t^$4W)TAecO*(Z0ZaM}0_#BDaGU`)_ASUWps^H)HwE5-`Je$J(3k`ypMXX} zz(X{Q0xv+)4BQ);m{<@40*Gc2WJsJDlpQsgSU_DyP!a;QV8BDQO3*bGpoS$g2e{b^ zYOI2;a+Ls&?y@){jqXZ-h6WW_5UqSB1r~5CUqXQi)L#Aqs(BSa{cnKRzx}N-SU%;D$V?l;VMo5;1EsF@Tm@k;Xd&LmBoypyu$=4I>5`p z9XU_}3&cYTEKrCrf~p8mBj*Ha7=c^oj_87`k!nEDN+Za?h$EvS8)WPPJiMU94z9+) zY*5w*4M$-N!-H16vw<#*L5#(7J2EJ+nL$SBLHZQfK_j~i3T%!{-n^h&V_2*hBotUd z4i-^h1&tUBfa=^e;EcxZSnmTWJQYBeE3um~frTN19$UaFK7c@l!?__dh2{ePV2?GOn1h_H)m9Gp+pvnf^407big0z?zvK5#>Ehc8r z(rDxs69YG>-eOQ-0Bw|D68H!wh=DQOv5Ie7&|C1n*=HFXW}Q1oj zN#xrTP!~}UN#r?Lgda)d28PHnu!sM%@3X^ z6S#@Qz6WB1D+5qr1Rbh@ba6qpAx0BSJUFen>r2{%8) z3o9P~GcwhK7NSFzz9}#|vVw+u7(wgcK)KSf zI*X5qi4k1;Rc3(~!ZJCsfoDG*8K7KN@aPMuX$5LMfLoZL;XLq!F!yQ}Mh>J|G3b=G z0wZL_17v3u1Ej|X?r?zma;%QbC7@=RBB-qgUiJcBy1`foZX_zPIkFcja)6ox3ha*T z{t%T4EQ;*l4xyt>mLj_Xo8u4gYH{$s3(#gp&;maNcE<|P;I;z0V*!-TfYJ$2Is!@u zKxq#!&6WiPifjt(py6pnb_Gt*?qp8TB4Tz&mn=ngZUykdbjZpbW(V+!LIt)gunrE8 zlVGdPxuIK6K{=b3L4ghIZrH9!7D!i%%~8OUmkG2Imn}<)U4hM$ml3oCfeq?u&_%CI z4hrnN433P79H6BN?C_Zk4$v45yCNG8Gki4!sCf&UvIl8!WKd)SP4_T>Mi;=%XHdj( zfVw^47ADEM0jBB%V=59%kGlrQIMOfST3#MoK|9 z{3tNO?Zh@13%XnhNeNjas9;w@78rpGFG$-Sbu_dc>|Rg@5S$-DH7{|aq1@Y%X0AcY zjS(|=pt4tiN#F|DXl77{fdfSF2wa7UfO|inC1nO#3ZNB00@pw?kmv%DAms*1kOe{- zOeUa}WsWwWOa;2%7PKG*JdDHO2raEav(Dgq%)sL|@L~jf7Z%t!CP?>=i5Ik&f|Z8} zk;s|gSpc-42b^6X!#WBI%%Is<(7FI7GbR~Ov8KS}%L^LjkpOM_W)y$~9W!L#1~Yhb zCO7Do%Pi2%<*=?1vjUp}V-{#^O#zg3HJD@+n6e?gOlHtt5GF@vgh2|5OyK^Ngc2KQ zITfQLgFeFxP_kEIw`Ks1S1@IPdbqE^LL62MplMGgM`noepoH@pi}~?_(9jL!e#`) z%QYBbg_#VvwFnv(f$cg44VZxYqNMeUAqfDScL?{31tHB#1xA4hptMe_ZZUdciry^- z)#DmW3{uSXptZ+L4BU-K!_@|eQC09lP^6(y8R+aZv!hOyBWO(wIIA%`fv2&V9oM`E zH=969HlUI!p!Ddd0G^3v1`VWWfCV6v)Zk${CRj6yI!@T}m4Fi*L3V>(0h;Zkg%fU2 z;)EOQjBMb^B>_k?3RG}`Ft{>NVsT^yt>$C~O+7Gzat5P2FL;a=w0{k@5|j?;y0UD_UH*modBRqmF;GtnfW*%lxS;wxx2;K|>x__J1jh6{*AF~bvgAxaL zkPCE!UzQ>VxFA*Fa7+M?2{|$$2^Bzum?1(6%(@Irpn8q11jGbaaXckOAU3n3ePNLT zhvR?7LPwzz$A*Rv424CG4Gl*a+;~AZ`LSdva&RlKD==p(fEzw+ptaO&;8_?B1y(oE zDl!EQkjt1I>%G9mZ~~~!$?RAFqBs!ta_BO^?d8yAfY{57)n3qiA=t~HHW35NpX>@u zp5W#oXh|n%h>ppPmyw4F6kf~pyVwk(GNBe;RBz~op{2pS{>IaCp};G9DN6r+y&>%Bk)BqP}AP!1C^hZ)XM1m$Cv zEJbDoHt@ka;8v6?6^^JLvcwP%t|( zfX2@hlsFVP9GTsu9hnRHn3)(D!6D10zz%Uf=vW6uW>DiZ%aO4R)Z_$BRf5-2%7Dst zMRrhzU{M55K1+Z`1VB|9D6xPS^D!uJfEv*P(0)5;8V@vU=E$hXtiSf zfjgko%I$;VQ&_hRyi!mC)XWAgumpD&KuaecKs*iFl>zlXbXxEuq?5Uqm5~e92}G`$ z996Qwy+j3OM`kMq4FzT=&{pvV$a+oCtgeD118DaFXyQZy(wGwfB|i`bP1tjQwnKm? zkU-r=Hc-z8)OQBel%Nd@pjm+WENI^mw1S!ibgm7k{Re4ED}gcss41cVp8Eh5SsF|# zNJ$B_MjPCY294}PS0g}^BQI#xGe?#ps4d35a2`G^} zLfm3s2%5%V0l6R4g9e|qgXAX2I(Q8xsGGoBFp%BE3|c_Xs=x-ieN+atBpDoV;F(fQ zCI%;kPS9dk&^krXY#k@a76C;rM+QYup$9H&Kr@n%-ZvjJBLfp7w*sdlbBQ94BZDHl z0+#|$mJ*K!6N}?X&=jOQFC+LYEU;PJj*OsgF0%qBDDs&V*g>mnKs%N|vIwKWg&@pm zc97Aa;}bZulsHk01sy&F)(A3|8{{c=NJilXEj8l;6%7oI%q3ZnQ9NdF3}`U1z=9vN zo&+53915V_luB%%a}q#)1f8`7T9)n!THOR*;jaJ+1kk=sX7CwLjMAVbAK+;m7Et6P z1up1pB}YckA~aCD8`3FNVBqd$WMqLQU&OQrs2~D`r2?bCB2bnAjgC4(3O4XTFQ7f( zOz;_gCRoXUw8(i5B-?N(uqr^h+>rSXP{YmPzahNH$~3giVUDZ1JDvY@KideZUOE5bNtVcsKzY+wW>#zsca(j-PlM#mMOKtti6 z-Z*m>ND{Q&C|h73D3BBxKr72|S!}Mr;7BujnLtAx4UCR6K&}&*333f+>dg^DhzaCo zXlOHl))qGIST*_U=cjK(xIx)ngGs`12`J_qLD#T?BOFm=a9?BwFRyp}!l20P$OIYK z0u@&Xtib44p2a86!NkhS$chCpgTz=ExE=3+mP#`^-eGX#W#wVvcKpNu-j?F{4n%_n z9zdfWg|57ej!KHmpjIN2V*?Xtdy}I&xB><@LKr~;3XB5FK>h`7=U{YXEJ}A|DsyBn zUJEX6FEF$yf;!SL7lH;^APc`39UB@rAd%YN0NOyM<@gv(A7FG`+yoNX#w@TLWH2w- zen!U+zd$js;dtOTh+e?t_~0*yv7QN{%oW`F0$p$a|35>aiDGv;Vj`Kc1r7k=w$#N`&NHt6-$#Q&<4&^kIWI4_)fpY%2XE~l)5(43UXtn?i zn1MD?VfQLz3y>l+=*S62X3%yZP$mPfcmj=tA$H}knuGdP%#5t{3Ji|iC5nvTp;84! zW=91`)PmX>psunbV;QKQ4>~5zaYFkc$Z;-?+$Bn^kWD+R3XI^!u_Ac51KbW`;s)jV zY(-`eVpipCWoC3E;v<$jM2^{71 zpko{$v)_&ipiwba(20HsSN#VCKD14%z>MTv(K65ixZ*5OGGS0)%m&q?j)y_ZArG^9 zOM@H=Dg;roiOJ%K~z|p|5IBv?QW1g)!JEXe{_ ztPTH|3mrMiz=OS93Jjng0_cE0(7AYyOrWD1xj+le7?qf^6nR0#qb>u35~BhqC>R+P zIK6q96?hf76nGRtCkAr3^D;t)1$h;?KrMJ)1r~2!CIw~%t}M`YH_%pBa6 z89>K%f$DTd&@n+EAA_n=9#(ElQ@Itm6nGskfO3hzT&Vwf6NuJkrk23({$O&HC~=f1RpNyVjBzQlf`-Al6u8}ZnG|>(LHUfM zM1fV8fw2g*R~Hl>te~wVOxa3|AT3Ow26{1gX#=-ABo#Vt0vB)Ejt{^Nodb0iyCY*E z_iJV*)_T~fk>JA#peMtC)^mWWL-3wUQ15^h)U^Ru<4T|dACx#9Sqi}e)@+~yAS4{m zegqW_=Ru?bJ1EMO*rgqr9GMl^r4=|J6)B=z1rPT@G=lrV92!hASY;h=d;l5C1hNA~ zg#xnz_zWo6JRo>-0W^pXvKrZ4CqOQ81obh{%648xkf98UoS+s9=xjztD+bU3C?;8s zZ$OrUn)R%peXXpH;-DoI3ap@(k_71NQB5WZP_v9flZiu-OMyd^Nk9=az{sJ?pkT#d z0aBsC!~$ymuqtqyGixZYDsY)ID}Yv)ID!^c87P3)mVo+_TS1WlTG#?wf(iAj08Efs zffY0o$pQ+QCh+h8NTmjof#Yegryzbw4<=6qp1yKy_6uyGDL9oOrGD-b#C{J%!(9QirxeunUcfC4LMFc!3ISAi9@We1)PSV6?u+2r5=V!-ZU+W){066G)H=BFF?&$qW)?h6pml z1X)0WED%8!m>?@ikQE}x3KL`l39>;1*&Mmtd0D}I8St#K5~nvWXbckU1BNUm(CJZ1 z+>Z6d3fzueQ&wDHD0ck+_jh?#p#m3l?12j;$%QIeXca1(FE6tK z8>l0szy=*=^xMb6_^y*{K1Z91@Bx|U{Yk`R$v0}(_wQ14YPt;ZlIx= z6`%wrunkljFo4_vTABhDa6t>&6&T>wGlLp544_dMCI!$Y zK#=v044?&iAbkolb92%1K8=Vb=f|BR3lfWeGO z05m5L86p6$2LR1JB1y6;vN_KAaj<~_Gyua2TJS2PzzQ0G0o8Sk-b!q|jG!Gc-n^h= zFPIdVy+K(I)ERIEF+k&Wpm=2jwb&U!Jw*lu$apbi+?yHHJ_mbS0W|as(g)dQ1KMe< z#0J`Y;#ixd1lk}5I{ks!lNYr6fmwkK)PQDCV9Nq+7RgfL$cBUrs3XJ)8dcv9T3xFE z8W@B4i5X-+XyF&=P(mdpWF>W35G5Q4C3RV-N@_8c)S@Y=K~bW>=2#70n8B{VoTUh! z>1T$72lONbW>BY$k%t|W8DK-^KD=z8u_#72kRKtD5Ahwyxk`+X84D&*Nn>9K$^?$` zg`nl;j`5&g51S)fi2_5BA`>W#Srr&TO-nN-6-P!zNT`FPnIQ8UMWFF+1x82ktP3bN z@RWe`f#<&2N)(u2(;aMxDHbIr=%_avDD5yo4ORdRSAb?Yn7|cT18CO4kr}+x5VU^_ zGAY#V4rT6Ofk38CX+=6#))&6!LTSRJqY1dl+2Y98nav=6w7I>C@-2C7-WjZ;uN1yo0Y>h=V%v__U0Qv{f$ zl4Zse0A_*O03He;S0ZXK1y)Dw4uiJ-KrRQhNuYLvxCY=R6u7;@3Tl9WT-iXJDLL3NkDkShg0gB;3&;-y7aCZ*c?}T;o6j%`3Q9!d@poOn^#qxHEILFz#kf(CP}82G^lYA7%|@`F2Aj0((}pq>>d^e=&pU`F(X zK<>B-76gw1BXtHr#T|nJ6R5uf+H(Qz2QYySR03@Z1RaV1Dn~&c0`Ofyxa>26yhM z7@cisp9@qlf%@3sC1;@ZwTdi`jF6r`ga_)0g9d@wKm84sxyn3#iY{ zsK6qvz=ql92Hm;=8a#*hnL%RN<)xCK>HvV z6+y>HfqTx(j>tV{(BdHlW@yhDJh=dxE@K17FNXpfsOJo(1Qa3M}Y<8Wbm*Uj0w^Y8cdLIdf-C#$3R z5HdClR>%x$Yl>w`auw7=*co%qN1?&d!$O<@NfYyw# z6HFiA@&Yktf|fqOBe>uZPDGMY1kDtJTn*~8uz(5{X2d`Ww*YvVk^+;!ZctlSfq~nc zkr6bS2`yxx3kw)PGhGsnf1u&XfHJ}bid{zT77j*sNGA?-dYGd&xIF+$e+-~Kw1rA+ z(x9cU3arp29IT+BLh$T5XrfV9ksZA9RDls3si2W;a9IokrQ0*fR43;tyKW^1Hq*mGia>>Xr2))0y-aAff3Tc^8y_mfV5VD(Gk-2 z1TS1*bc8j$yg*B3p$7(Xfz~R3PT%8J;B*DARbWGy25xRKW+^g)&$d^@*FZ2cGBJZj2hnW?cd;eF_Yi>&lR>Ex!To8_ zd9>hg1l?o-_8KF2(F8a%gFOq?r^pG4Z_v@Oprs1XjvnYpILLG-mjWB;0AnnRCKwgi zz{v%4)FTtR^bwhcgA2^n-56cl;DB_IPR1A#9A0jESroH2lwnZv@I84^F(LLRpI zgc)>k5NHG(Eg(T%M5rqvQ4jGIMF9yO!Gy*tYQTYIWE2@eaU}tse&+-QoB}gw(gBok z8M72Yv*O@8Ku{wK9QpNG3e4asECvN0D+W-QaDz^w19xe;o0$*;nTS==3Xn4*ARz>r zg*_rbZ9~v-2WZs_&q#?6+UyJ^5G5v{g$m5z3<93Y zZeRf&a|_AaPzK1*q!M`0h#53-30f1*0vcyx zRAA0lVsQkYf5HMdq;!frcsBK@AYlKqBZUTxfmE=vZIu$X=$v=*U)9TA;}tip2`Qynxb;x&aC{Bx1wk5Xh`@u`qYD~EX3%8-%_uQCt_DqsII=<}mO-Qb zj?2L!u&L%{9E|+10e{4CGoY>}ID(lpm?V@~9hDS7tMx!xh7EK+GdpahA#@8gxcCAm zOa@RP$f>{pZr6c|cW~E%*+GE|dM73qXmL9eWZ6Av(nXOAREmHu#{@M@xuAo`e4v#) zg^K*3F(uIOF@pj>XndHjNRd~83$#pw3#6J4B*q0BGv)&;29Fu@Deyaj#*9IVnX?p8 z6f=WY=<_2D9rHrl{>;DP&j}vXcU4$iHVPek%E;h3U z69;I?KTj5D(*h&60=EK(CogEU4>a-w=?8#j7C0ay>ENLg4)C;$g9k4QH}nP;5Cxk0 z0Nt<22%0tnk9Bc_)q&;+SU}_13j&+oU{>UF{K}xn0n!E9Ex@G6=lC14slbuRkx@ZFT9FTIy@G%v zQ%RX4W1*u#ks^nJ0BD6T14vo`JL%(;P<4xu>}9O(RfEUb*o46OK^3wA6k z=oCwKZb!I-ShyWg9LtR45%6MsCIvz8UIT=?!OJ@Zp)ThyRN??H@&xssal4EYbaFt1c8`K*I-IafKGpdy16USxopgc?i?j*U!^`~_YRuFC*wH8DYs(*{kHf=1542dIN`HR$|t*tQ06 z>rRmYlpvvliJ)`>8kpc?VP|A!VCPm~11D@y@0iVzS&r4%+$ z(ghu74p#ORv@DewygS&DMUf3`11O0zfbQf4uNnoX6n1GvHpoI?4h7JCz-6Fixy;~{ z0-8z#?-FrjP+*q^%}0VZIl#OQO6g48p!*;g(cG`V0MC@T-41a*Ql^BukQtQD89|wn z*%9P=CM2IRawD7!+JppkFeFog76{aXHhE%oDmN%Kf=}`W#U#uRptYc&b0VS1g_-*< zD>LY}Sm(8i9T(KQ z^KwG$Sy1oC3#$0Riv{H&cJhE~J$A>sLdQIJUJlT8Azon0!5^$tfeX}B zwP0}M%u?X61)o&Rk)^;1TDi{vJ^&chA_c8K0`0N|Ezko^{DOPP4B&wcLk8r{Ki~mt zCh+haNDl*K1RGi4FsN(Vs_9ZB`lzG)>%NiHaHxi$rH3_UxC9Blsq9Jsle`tEqStl zZbp zGZq;@%cekwgY#rLZUN~R0G|ad1zN?z0iGfSZO8(hF%6oi|Ib*c2|4OLiDD7Z0=!)kK{QZfw5HiOQ%z}!ED zC7XfPC?PV@OD1N}6(sP>s}Ng49o0cwTtKZrrwQj6qCle(;8hJEanP0%Q1!-=r3Bi` z3|ct~Qq-Wt3Zm+2mn*S5g7!){K4HjH;&5avaa;x3>6N9=zyLaOgUzun3v`d5;}eFQ zY=}a1B`l6LS)k2rPX7;H*AD{?kSa1LfH$s#mM<+=Vsm`V09uC040eWNU6v9{mICW? z@C+c_W;WawfX4|G*c`#zN>B`8Lw7Eu5x|+HzyjJ2&61_S=4b%ghX=aAfDy7z5VWff z?2s%+bp;k!fdyKt06X1NfrWbmuF{Dr2?i8V;NppjCG0v}F2+%wlCo!z7RBjLMrP0j zp76wsQjuvggDSEH$W;stj9HM>4eA$w3O`2%$aY9j97B3r%*&NnK{XsGjYuo7fnprw zW+#CVUeJO>nWChoEY>o>UJwYpXSjs?36&M`rKqHyVP7O>UifjtZP8=PeL3_y3 z3ec2meHLgl0@0NTxU^BgSs8w(n%B)0i1WF*!l3XtXe!W{5xEth3LYC}P-0lCz~ES4 zyvB*K2E_1EVvq)(lnB{Wugu6)r@)}e%%H@iz~p4#uEboUz}%|99|AizGEc*ZO~XA_c^Q;Jg8v{nvP~r0#&P^&B`EKZh~!L z!L05fbM@dufh8QT;!=gHQ2?IL2i+e6I(i>;bp~idyyF|tpe{<=05Y};X&rzId+-_v z(28o%)@Ay(4PXrd^mYQ|T+9ogfg(pH$QU#CZ0s|?Oz?qn(D0DsBXF>BVg|0X0^`~i z@J&>py&#}t6JCRrf=;*Q$#UES+ByWec>*-C2j1HcYGN@uegiAx1P>=UHh}hjLX?5x zlm*<8(OWD#3~iVr*qpui;X0h}D++;^zl_h9ZpCPog(k|ri_t6c%K zxfwJ*3_4;2G%TV7y4M}F<`6XL3f>V7I>Z681Q2v-Bj_w;(7Yw6%dEt#zzVw88#FM; zq`;D`#O_#AsKk*4Ife(cvNcPI(~%jxC7Q#L(Sw%}eD(ooT&7TwNr4lj8nizHG%KgT zmhC7}sK^4k0UUfr187OU0#g~NnarTXrod8C1nNUWS1f_;P?kfR@vNT>!d*6m+#cZ0v~*boNTN5;)*kvlUq!LHBcmHU@!qTV^S7K*O3Hv}~RU zbXH7>5-TWFLF^jP#4u=z5v&O$$_xo>kiDQ5o)Q~q;d%);@RV2;n98654$=c!Y7N>m z%?u8|dM{8+Dlle&8gQU1y`kDc*QG&%9a#?(Xr2?4Az%p(+$Cm!CphLT(7**`A{2D| z2qQSbu_&-Xqk#>yj)+YGG{T|8f}G%(vz0hNNr)3#&x6*UW+|~l1A!Bg;6Nv0z!Drd zd7>paXdr;jtYlSSLrQSW*b*FQ3=n+c2-tK6&|SB95*$c1Hz;v}6CAq&XBN1y1I^>J zfKmx42z01Ie$JTs(}0404z&~AIoEC&hz^o-`k$P79w6>JN5BME5U z9yGEA2{R>D&~YiC*=bN64oW1TNmkG`#jeo(Yb*+^*`U#7W^Q<)_!e9Wa=+_kVq$P? zXgI*YeYuxOzo@jhBw63w+}J$TAjve@#L&Rl$j~gsEG@+%InC0vE>0~1xkDi>F*7GM#Y!PFr9#0*!Pzmu(b+R3 z5>q}kB|TLyBQ-NUqeQ{hR-rgGCk@8cRWM{IU=U!4W?*2bXJTOBWMF{vo1uK-49o+$ z4r&R=RD?P6nNiL4Wno|tL$ap}%Ez>)xF}gKCpAw)6Xfia;t~i4=H63m3=FIc3=GMM zIXS5*3JLxNpir^0D$Oe|N-WUOOi;+rQ%F=u@XOCjO;9LH%qdOP&rU7MOU=DDFy&i@;G{l3JBt9AA{5lT%s{UtE%3l$f3hmVmPL zii-6Z7#Jd$1QQg40e8lK_JZ0|SE&lK_Jb z0|UcK1_lN}1_lO%9*}iOiOJc>x)>N1FbOcoA?e!&)rah%qSU1P{1OI+8%zQWLLdjZ zq$cO5q`DRrhWwI@)FL#spmY(E znVg+kqL7%IUz%528ObxABqR8UAPQOHRxOU+SWU|{&bEWjYn zz`(%HBEY}}cXI(kXGUsbN@|fpL1JZ2eqxG(3JYiyA33ga6N|DHGV+T{6w>mG6ky@+ z!vcvbPztC_Em6qKEyzjDP0cF-H6;dXE(j^Fk;sxOcXq+gdR-oE%rLct+IlX}r z0?5J8^p>9obr1u?16D|!c;=NQ=47TQWWs!s2?{`%e{>X5p$`OSq*fI*6ZfuS@nF)0U}B?=OYic=M!NeIOjP}<926JSt9D!YPGi%WA#(95no zg#_24B52tKj(1RQ0A&pc1_lPFoMK2eV_;yo!UhRbC!gT>U{CjWC!b(LBV!9gccb_S zUl*%j4@X@iQ?vNs;PBA+ApdyBQ1^IfcFs=&XHx}4)=ErCQOHXzS4f0ruar`Vhl*0m zGV@D|;o^xU3W+HxMXANb3Jgl@0t~hc3=H66FC#T4MIosYrcjt2k|s0Q1sFsa7#M<5 zbMwnU(F83?6w-?Fa}`o6GK)(9t1BU=Z0w|3!GBAMZ6yMC`jMSXWyj0J;5=EpkTZw^z0WKF@ zQk0pO&VVcr$~OTMK}W}-GkCE2!q5x7{mq@{Up@kDDDK6 zfyjPUXJBA(FHI~;%qvMvO#zjENvR5{6^Y3udiq$a_0+uNd{D9h*Xt>X$$CY_%v=Ht znhXpK-xwGev>6x}V0;lq25_C_;^?eUP?VaPn+U4>ic(V*KowhJW?nJ4Qp`=vtAtcC z#d?S$tSGglC^NMz6|OTBUQ(oht7!$Wv5D!aRtk`M8&pQ+D+K3cCZ`5~Y=X4*7#aMF zGSf5j5=&B37#J8dkkSUo&7QdhIho0sCCK7hpf(My+rQk9_U{e`1_n?ZkP@FDw}R3E zs9XbuH)cC9H#0@S2HJ21w+9&@?KnjJ2rgjtVfBN4nW27JYEfodCa5&lD=H2Fwe=t^ zDo|Tb0o-m#EdrH%&@@t7kOB(Q3)}(>`k?xdkpbM^D$gv*NGVDz2Nf)kT7`kZf(O#R zg4HFU_OvdzjhB{M1ZrWxOGO5T5FP<=dJO?JGa*etSZYa4QOGULDakCzNma-%NG(bP zwO)(CEeTl3%fQgUBfwzBz`)=SQ=pKT4oYbyu)-BuN`evxs2)1NBLHp}1ZSq_C6<&H zr7A$eAsK8sw8sEy`|t=b$b#DskovF~u0Fp=p#Yrm6|z$+6(o2eZ5~8w%}hznE6Gf& zgjRkE3=9sukh%{R9*}TSC`v6TN-a*!D}h+ez>vZVse=(_CFkdrr51tP$so1GsVT^I zm*gw>Bvz&t86m0}h8|u4(69-EBeZUU2OK;~6H63yATbRM?u^6~1%?Z}5dXgAg~Xj- zKC(?YnR(fe(gGHB0(=mE`{ly}It|p0L5^MvK1f?0;U7>LG2`C1_p*Ze2_W{QlWdM zfb!E5K1h22l&?VLE~vc#D{nz!AU3Gn1(g{R`~nQ1ya#HnBisez!QwcnvLqGMYG+{3 z;D>}GLS1ocQD$OJW>qRoF~}1j&6#=WRtf?90^l+VRE2=*Dhs6Y$`V{JL3D%D2m=EH zvb+_jtqkcoKF*mgY z+%H8o*Ny?y7Xmeuz##^1K7gChXkllM?k^-4TUjAY$7R2jRZ1${7Tk((+V21ge^48h zfq@|)u?XA|1678lMX8`-ilIhO0Nn3|$$=ZPRtgL=1R-rjn0QfYVQFSjYO#U>I1TD2 zXC#8U>I@s8`VR^UFz_JR0au@!UzDl<>J%|BJP?GGPv8bXa$-?>zJ5_^dS-D+Q6;$6 zPtPpLC{5B!&d=2~OifNUGqSWyNwQ2$wlFf*&&$u%HPbWFGX$$FDN4*NDF$`KScC)^ zyg_-7i2>Y)gz;ZP`2^~xl*HtCXs-%n8UsUtkN|@&0|P@11El>Ing{QRfbx<;L1KEU ztG|yzQEFmxMrw*ec}8YVssgl80jiw9sz6x}(gjn{QvhW-us&!lm#>hPS`K1oq!u$A zf!g;`2vR14!aFs^B{3P=Teh+)%Fi!}2bqc~m6)DhlnNU8N{NTp8 zL2(T#bArGBD$1kX?^I~8Chq(^} z14E*MOJ;FFPGTjZcMZ-EpdcwN%1cdANX%161&w?tl){5Dr;_qvxngje8ysouB9JtY z#>oKgKlp+?$pCS;ABlZCkX}%k3@V5HLFHn8ZYoF&VtrVnCou=? zPXSR#odpViUQizeKDGdEJfm9z&fh+wkaiEGuTq?!=bWEcQk0ks8iNV}#WNIx%4xWo zfW%DDxD&E`C<6lnG9NUyip&p3laBzEd$6_=EUZuqGfY`Xg9YBiLTE!2Z*WO)IhvMQ zgxySpEW}KM3I+y-axvoiKyW)iVU?O!Vr2z04pRo^M!1ZX6(}pF79j~h8@VVVkO4Rb z2AIhT)y1ixuC80} z(((gRi+sRiYSjfrsVS+Taku=U_>#=r)Z&uF+yan+ND@{G5#o?GO|3YjtcRH;AP#BA zxaOt!r}=Is-S^oF^IBxEec z89ZhK8u?65%>(sm;LSo%Rl>lK0X4@NG;o_*gcxrt$yZ29RnSpLDlJh^C{G0SgG%#K z7$!i?T`nmA9=l#E2}y@A{jf2d3zCpAAxIlo0oGoGj_@!rypV*95d}j=@fAR=ad7p( zz`(#E1!;@;Cg!B&7v-j=fX3}%{ShahULLb)8YzhTgG%#283ZQGFhNRy0aUia`ZX!}sl|}7 zwEUbDh19(K()0|4w9>qkVg`m4P&YvQ>Iv?Tl~gh?BtgqmP<@dMnNt9ba{6W#=YpE2 zDDt4O185lfLj%bXJgyJpK?4fhE@MD7I~6nr1q&;9M-v_*VW5c?ke{*XO#_YpLHrJu zMs~9s0|SF!eu*pCvu+T-;;pA(-TioQ?_aN|7&hz-9!r6?uR#5K==h8Rq>Sb06gvo3Lj8A2%!&i4rzl7q~8hC6UV>+ZacxF0=3VdpQZrrYCt>xRtisKAbm1@ zNZ{&crZ6yw$U@R3Obj#<2C=y$HC5k$K|>ajzrm5F02Kwrb-w*WCg(E zK(Mfes{r-JOY=%WUHzie+{Da0kU8MCJ-FRaAq!~-qxAG3!vw{d`FRSUc4rZ2yiOr0 zGaa7k5=%-_a|=pRQ$WQz!*f~U%5zY7fhuxHS>^~C%7zI#6fv1d85|crNNp5CINh-MGlOYF*Z!~qF#8FzHkO`hAnIH%0uec;8E5MuD zh(ZW8c9Gi9TjU^Nhd+)O7~VkL07^fgCM#0EC_S@8KRF{cIXl0!q*%WswF)$KtZR~- zYG9C>YGRgVVPKMGVxe!IW|C@{oB~piU#t&q1!m@@gS$w1`MID*ql~-&Lofpa!&hi~ z7{>pH#{ZAT2Q~UZZD5#sMn*_`8pdZr<8wm!u<=G>=23D$o`%{B8W%AzG%_|ZH8Z!c zOiW5nNlgQl%|)5Hsj$LXM*%WF0In+`ZDjap6RiGmQGn!0Us$=QU~Ht2U!;J$c3@!0 zP=JgxgUU*nU2_y5`Oq(4A-S}uC>1o(iZpask`GNzAhSV#WA7K6(4KMIg`8LWt5_mj`fdNCifq{Xcfsui+fr){s zfti81frWvkp@E^Hp^>4np^2fXp_!q%p@pHPk%5t+k&%(Hk%^J1k(rUXk%f_^v4OFn zv5~Q{v5B#%v6->Cv4ydviGhisiIIu1iHV7+iJ6JHiG_)!se!4XsgbF%sfnqnshO#{ zsfDSfnSq(1nUR^XnTeUHnVFfnnT469xq-Q%xskcCxrw={xtY1SxrMokdt(G?Kn>gns~?i%mm80--r>>1^XvhV>VdxPo)&;X2{GGu&oA_D_>tpTWY zSBR9aK;!tq`MKbA1fcc^2!q<)pgt@i(|e$1-(+9_&y&OW9E=b?H0pyht5O4sQqwXk zpaLO@=?tL$CCDxiE@c4C*H|+|F;p;2XV}Vch2b-UAfo}JAEP{j4MQ|TCBqDcZ46f# zzAy+e8Z!Db!qWwkKR`@Sc?6@s{r~?T#s~G+LE<2K&j0`aK{SXD8drtU5`X^xhw(vf z0*NEjA8!2r595Q@vVi14bVB97{~#K~2d&S5(FgW^_z&ZQ)^C8sk?Dra^#3qEsGkOs z2h;LgzrZvDWGxOz9JHo`!7TL%m}X!AuYmxGb0OvhoGMFFJ@bM~QVXDA?3!CpQi;R| z_sc+;FC;(TCqFM8#DuEJFG>wcO-#wp%c%tCd3R8UATt?ikYh5apXdo%mf~MpQczj~ zG61xiz&ABFzo-&L6)4}Qg3SQMxobsoYHCVq3Ro0VonL;5BSdXUei5vg@J_7+EB8*V zgxTYfUtHo^1R8HBLn^yK^UGkBKAFWOo_Q&$75=3q{%KC2v43zO zNnmNDdX(t##iYy<-LlkVT?0KcJ!5bM3R&ra#ds?P1v^{NSpEhz$XL%&H39Hio)k3! z2GE$8G<3Zdj4#i`0A7;-<10Y<&WQzy$(bdU3b4uxG^PwS!m6d@3G)9i( zH_F=xsd=DjRt5)kNE_iG0|R*c9>#wNT1Nm{CxR3&RSXOaQHe#FB^j`qo`}_63=9m_ zNM?Y>RTF0p+<*BK83dNwQ;9>>% z5O-=}X=08-PHJ9yNd~BF-J$_$1CZ$VyIrw_!_9}2jMzUn$OGw&kd(mfM&U@6qaZ~ z#xy`Qs9bg~EiTE=1-I@QT9DFpD+2>V7^E8lmPD3o1C7^arskx8Wx&NJXiywQKPX># z`hyjqh_{2rQbB70A&paT|I9)gGEMDAp?TSP`Q>>biRsV~Wne&20}oH9%o0$ZL)PC7 zn(qSD1c^nJ$l^T=3=E+qX%@(0y=dn4f!n^h;NVD2ajDEp%*{*&)j^OoK8Ttq2sHQU zoRL@*oLG`soL1?Ulb=}Po0wN=2ySqLSO#Dgteyjpd4%MLBxa|EgC>o9{Xoo+%$yv< zFwhc-%7E0O+)~ISyvGSf3lJW?yb zG?)M@2uVzL&dDz>ElNc)3*`9FypqfuaEO7z4iqjR+7Lt-1gC;#N=s5xVBrCd5ttx| z<5}$JSqy4&LG1~SV#tnC4KL5oypm*_$28c#+B26NC{Ig}s5 z$N*l$!dTXFv-PFxos}$2+MHj{wh3u}^J8b;)LqZ~?@<^pzv@l4h0E9$E@4}^kZs|7 zrl`u9>9X^;v2K^0pUYa}f1GI*W7elvKN(HJLFGQE{2?F1S6hOIT&)y9YhjC0Qxr<` z!1I})MLG(grOH+cb^4IGCQ!ar02idi8So)xNLi}@Dr(D9Qxpu1EFiPOp#HBuM%_nZ zJ0-cOvY;d%T=juEGkQhEFZ3bdyA!$=2-?;J6`~9vIZ${^0G0F5@&(iv3aKneO#x4` zDnK2cm{XouSq$oDAr{1dmWXENDI_HprN1VhNUI=Em~NKVX2E(I0wdFcu%ndzy;B{hbSIu%s^f!Yj&Flcs2 zgn@wp9fS0N)&PPqhz(kM0Ky_En#z7?on2Ew3z8%Pes#)m=bKp3P3M8hzQ zk4%Hu$e8kpXHdH*H$O$MsJOuhk}fUS8Nh4p$thK^u1YP+CnvJ=N^^CSK#N98bPe>3q5aIH%=FUCyb^uL;ChK(QSnI= zNL+*FRYCa%3*_aMp)>1R;W zyP0_)UotT4FopDGlvx-U96@V`a!QN+@<9XtzL|NY#ZH;&o_QspIX?ylhM7q5GYi!J zNi0c37MqQ<&Vz^^DV2gNvm~_$+%02hHxpn0tu<+5g^Z1X;tYhTntmV&T-QL)P|pBd zP(a2gIL#sJUqEdSPQlPVeNx}?_Ow25-Z0sCRU7TFp zJiL7T0{;btghfREi-}7}N=eJe%E>E06eubwtEj4}YiMd||JTvg(??7afaPKCSpX_O zKx+#?i_1w|TZXj^h6t9HWafY)IKe^yyq|C`biWsjzX*-LmVp7hZwMy86*|s`%m=Nf zOvJi*&w7h&<;L71_qe9r=aFy z>Vt3d1L+8kQqWQW?_Gmz{e$aQhtA*N)32ov90f82n|>FlesaneNEG3yJBu?Cjr2h~ zzKl%G^ovr{Qj1dal0n-x85m~hcR5XTF)uv-`@q(vx3|8GJ``s8QSf8rk|z5}SL0+> z&sfENgE6{UXkV+L%Hdj`(304FMgKP5Ygo>9XLiZQ*#{41&VJJ7zVH39xd-{rEaXwi z*LkVCs-?v1&dLojw>o~71qIs8$USDb;)FW$hU4{-`#*C(IOaZa`PIPWQ*7y)nj)=S z+tn=;rS<;g>i7!tS_Fp_bEWR)$|}=4d8n~fr)bi`7yB1^r%A0S==MIeI56k9^5XSiW6Hmx&v`Z<&1B=PzWOh{*z{~| zeGp%ue2$%VPX_Dk?7fb^SKn-wuT-oPmOT3)8l)Gb52OdA9;6ne4x|PoPfi#njl|*LYvgU|+`& zXAiJ&fWN0-NW7naNW7IGESRgpm+1WKX zn3QqXIY@OrsN6;7&tqUz5}M=j!X}>6hjemlhP{7nP)@=!5OiD=Jp7hwN_y?N0;c zi-7#h;(W-E9rcnh0|Ucsd(^Ok#d{DD`zx1$!VFq3EXSJfHMB|+GjlZczsvu(5va|BS)yrZ<)v1XAi1YFKQ~na zw5J267jz~8cD;F^*(3w%IlZ`~C^Zqh_CvxEGOq&~Ch*5B}dZ21ydY3@W zB6h?Krf(}FWUh~afuR8=c9ap)hl25sLHSgS^NhrzRM3zF1CKK#&Ovo1XdDI#vj78Vts~6t-wcpC4Kr>a z`2nVm2fEfEGY^zDGK)dy7AV--DS(!lf%eB+xIpG$Vd_m7A$u_~&4r{h%+$mH4>K>g zUC`a_1V%|=c1AHWfX5A!5>piNN^_G^i$IH6k~0$X@=|k(6>?J3N)+z6K-ML}^pr3{ z`t2}&Ei}Dhx*L(-U}_gb(+`Y)h!L_E4aUC+P0N^OA<{ie?Nyv=wLlAAZEY0{6l!V| zU>sf0zGax+M^HC|(mG7+1De}DqVYdL`J~hbE0F3_&^aB%=1FiWB;%|ZL|qE64)Q^n zE5{8opJ~qw*}Dznn=vzh&k%v}3(@48(fBi1Ap4nN>L;V|ds!gn1*hggrVC+#MZ~}c z{lliX60(YbfuX})fFY29fdRDs2(*tM#s{tc0o6Y+KB#U%mIuw{f%dt> z({FldVo?gHGph%hk^t2QkmRY6lA4$T+NBSw${=+wsB58Eo}Zl>Us@2Km{yWn6knd0 z2|Cz76J`%+Y#vlc!T5gAvIE9%g1Q67pTP(j=Y{d7Le+!HSeV#yX!?fnS3u3cHEjM^iJHr%j$bKN0y3-7hGy~)Rfvz=#@qaKt)+)jHlF&2;nwNoz zSwhnxETV}h%CH4r9#R_{l251?k;MhY$?!IRpbw0J$tM=_q@ zzZ2Rw$9(-?HZ%Q?c*Vhm)*{EJ`ir_hzwr5N*18W4Uv4X&$vgM9^f&iB$8tuYLZ# z+tRM~`|IY0r&@MfC$Cuea-EIT+?i8mWSb>RByUg8zrH8HdD6s2R<>`-^GXk_TzWX+ z?4G$t7p!8dXnQ14x6wL%vt#R-ZBo+it)id!-flbe`E5cmr`9AvFCWi@A6&&gQFF}V zNx@8#C_yBDdx|4_Q}GW*k84Rw8gn;Bv^q}-qM=fK)Ki6Yuu z>Z>FcynbSxwPtOb)neO|elebvZ%^4Q35XDX{z>{?^1?&fB>NXs&XJ2(uL2D-|J(Wh zfAGeC|5wYYeB1DC!6k$A{X(suTfECtuCMWS-nLxYd)Bjh%U6PoQl!QOx$YX(H#|eY zP25DrME?Glk1Q8Cmpv=vy1H$uPmcT3-UH2ZC$H>yovu4oa%-zy<*ZeYPfdE-KSOY& zk7aupIqUj|xdwq&%j>!Xhk*9(Bd3hd|3Rk`sITH;F!^J|a3;9Efh)V}WxxA%m0i#F z)m`4Gzq(?-b@9o*x_iyGfv(p$3qKULJvqsI_R`X`@@`72W2Z{DUS9815HaucF2;R) z+xjjATxia#{mJauo*a^@@IfMQ)z?{kt5Wq3i?zt<`na_{GTgg;;?tNNHGZGAPLz45 zZYuF7`&OR0Myo9Q)5D=5qEQT7sUJgUcGl%TU07SR>-CxJr7tgZLfim&$AADvAov zk+u&Fc(ILZpMGHvyL`OjSKl3E!Sa|0YjY{3W?gvfk}utA;(x=Kr5eUfod+VL0&rQbhE{ zFZ&d@6!r;ocJI9%W6|2#xhn1EahoTVHde}Kzf68OU39H-ny=h@^S0_H-b?RvHwmt7 zX`gwtnv>l-joZU2!fENTjHhY`G7JAK+j_&#@cp9b=O35?4@?Y+u4K@vEtr{iUnMl* zx}0bWyQBK|0u4n!Pep?zd-b2rUTy31cuHmXSG9z_@3mh1o6FJ}6rfRY_g3m_DaKcZ zS0?kh`YylbUH)!D>&E?#T{5?-Qog8e4(^oVk7;-!t*GK7&|mdR^0MVbv2WVJeQWtX zac);L`|@b=-Q2y`&n%p! zwt|h{^TU_Q#=iy)E2jKt6-epc7-DcsD3!N^HMM@}qmK+v5_Oi!>)8yI{poapXkg|n%sTwyLS)gam|~x zb%`6El@(u#4|38G9Z}if%p1iIgK;~AipsT_gpGgL;Z_j;fe0#0gnB&iz`7X;2wa)lp zTz>gXh_;v0L5udk^KXg&{k7RhefjSNLK)sq&HT;&KT>8*vpJ~A@A#pjN$`y4&1zA-eDeMw(K*+&S2{nbcHHAqp(DfN!v3WtkV&YT^>o&{)cOc{1&2VR z_bwuyw+e)wPyPAZDa*Mif$i3rP1zFs{u4M#L=Sv>n{2aFSV2TeXnoIitsFM(Q-bZ8`=k5C#a=x4^5OcOWkTsi&5u6UhiRuTkJuSL&sVm%crVMV zex`HxFXwP`EjBzeSuL|^nM8H10JGK=7j^?)drzmO@u7!iR{SXOI1^m|uPb4Ce|N%% z*b|=GtVR|OM3!8wow`gdxggZl@zBk+yYn@L>^5%uz^?ztlei=Qo;y|a*vH$DVa1Lq=ZxNG$J-W8 zUC?qrccS8q4L;{yrSx`4r`jmCG2h)IEojJPxU{KL`n8K2b)GNk01gWbux-QTP8c2HaeJeM8aGR7orM=0@F^M|*4APd|VC=g@}ES!Fqw zH?jVnm-j+?n$Rx!d-o4&O21}TIeX-L(bNZ%Ck9lOO_=0owl#2lMx9$`E5FHC%PA{r zm!$YUX=<4G>q})+=Cj4xSGhvsdHq^6MJ5_=$_`u{Xn!FsFW4chF2c6SWckX)m)d@r zhra!|_A1}X$;EM5MswzfNKF#5*|1OBP25YJ>(|#=ciz4>d$G4Kbe7vXf2of@=A|Uv zvC&R_$k2HD*2F_edy^#8bUt>T+HsQAf6dO7{9;oWb$(T5MA@cf&3)+BaW^_mWdAq& z^})QdyPqa?ZaVz%xRAJA7x#qyaa)ftPLg_4e&^p8U#V9Dx7p==Bc+bSUi{5FG1$xa zllxSQC4~`UGv+%oDg1F|XIL+`Nlk8MUHLd(5{(+INHmCLLbAD$rf0q39*Ue8pIl|sW zp8GGHKOdRN;uh?X=iOWKs{bmJ&K&la6C-EmPD%A-bA0!3_oa`9=?kRo7pFg({)0W9 zPf?OnQ(Rzrz>M01%e30H!cv69g3r8T3i$fJ>hXGZi;R6wD<+hNtT@wkTU2-Fk)6V_ zTQ9cf3dm?bb)RdR^E$ydS)eQay+mE~+>Ql>zwRmv|2cZ6(5@&mhIczd_?MuM6U&~+ z&FJR(z0)+*-zFfw^CysAN7g<6rpx(@xS{4c4h2g%1iGUXW9MBuKxah zE&m+Wf-kw-UTQm~UtSz}aFL3+7SF}1eX)YR9Z&UAy^^$2tGP7A-%- z*tWRT`u&gUPxkC5%Sz0;JLCQId$RRBRMS#N&nx+t0?!V}IVuOBTJ{*B`XbX4cx3S+k#=+4y^kZu0KQ&MYsE zZ+-XvTi&tI-9>jh52?(Mogw-0(vppZXCyg)uR7>2ps~#9CgXiizAHsW<(yVIoL}Cr zjejk;XVwRe@D8q}cZ__BGewIQ%m3cYminqNY5S4BqH{Atm#1BMyUiy)RA_woGoRj?Z=P4= zU)C8^neL3)d-Z99aJJ;q9; z_v%h@gB783@2s0r!MgW`XX%d{6KoSDTg16MqhIfhd--SH5&KW;{-?7@$6M57%_}>| zEOX!$@8ms|TOYqwjyj$g;>x2OGp|V@?`*JExg39A)BkEA&*ks41i22nsP7k$5ePBN zvSRK1xSQ#l+J||c-z*3Yyfe*nF2kS89DA>FGBND5xz6MMBz~U6rMU2gIU#%NLZvxm zXGGOLQ9N~Jo9ebr;b#g8r+iXlT~>NQXO%@?=+jNhT3d=D1-+{|9%@%G2s<;-%; z@rHLb;}W$@gJ&g*%T0>&J7A*WUX*HjMM%{*wsc~G$uh3bB(}FnRgc`ZCx(64wY2TY zN#4$@OIwYCl|F0f)Xg?X*{LG2!+j{|`?@tXfk#ss?(y?*Fz)^4@c8z;j^~VQhH8Q4f!wQIj*ExSxW<$o@~ZOX76tHe;K=$3 zu`?sy{Q3X?$d$^!(U;zRUM!pbKVSH$@rwGrJRxU|Mbsj7GFr6b`CUDXCr#bY5c_~V zCiLh3|NmdN|N7s5>*@de)Js;ET_=}Z;QvyV%9i{r@aE-)myWhln)i5F{?+=ViE^x4 z_2>Wp|6iT|{&#=->Hl`4%(*WYd0M?-ui9P4Ii{X=y!u^1rd=x6llZ`H4H^ zT3?r_vV=_%s(iWVcHhG1oGYh3N&mjXwb6Q!?)}{Te1;n4vFF7OelbgO*(dmbqxE&* zj=EJPlV>D+{u?5rcTDX0G5z`z%m2-j|GiFyF{aJsMe@EMo1#9~MU~fY;o$n-)4W$( z_=%)WdGngg>x`~?he}>vvt9AOcSHH}!+m=e$DY??Ib?cZe*j1QOHE65Qse8=h8sWs z|L^Ro{N`?F$tJ`eewS@g;or|%XB%pgF67L6#oWm9&HTcNHDazu9bYMMhW0lI zld2v)d>3=IwC;aaz9p1c49&+X}zm9kUxe{Yn@bA0c_KJD_CFxEql92mA+TQ)vT zte7kE!eZH~RjWR&4-DNp@!kLV&OJ5eH+dGDZe6s*nZ?QF;ehVIElayZ?)26aPei;@Bi)6%p13d$o>Aa(IN5S7Vdh^ zeT~eup*Q~j|KCx1|37zL%Ky)fr?Q;ZTzawb`;Tq6jm}DyY?hDE_1O9K*2^7+CA%I3 z*Ng2d|FgH{+l^_DE~Ht1d1A2jZ_qUJ{~cZu4_RLPdZTKJ35d zkuw{a%=^}?TD6MxQCMhY20O!@KX=VVyQCPW@#Hxqe@tGk*OQewU<64{r~xW4^f zvsd`$W4@#RL94qrrWr82NqNp7a+>Yp()_J)cFR|C{#zh?vZYhFer?5Xu7`p_{S)o@ z<~p%HTXp3B|Np+h=l`esi2t7+EUU`h{<`?neo@Z$pu(n4w+`#hJGE<$m8D1cyI;3U z_KBokk=z_Km4jWlnQQB$_{?MdO5zvK*u0qjPV>&DQ|qD^`<`1B`)cxInb&E*H}ETc z;&8k6)Msthw@q(qJpW`baEh36d8X=>sUGJqyjbC|YmW56&U*`FDIe3*Nrh31-mXdp9yv);;XuPRxPqRLe*NZ3j)wQvjX)Sd?Fx zngU(mrVm>I1kt4rS;)>XFH3*{bXNN!CI;|%f{-J>KwHD$XDpWHWfp>N=>WS-!PCVG zbS7ajXp6K$YDGq3X>mzv3d5N!0q{Oyn0W#$kadeNz8DL1{R{M9sHFU&qWtpI6o)L( z&P(v+Cdr8YV)KY{(IP;9bTbGZd0aiz|y#A;+D9IbczcvEU1hK)mA0 z;*!){g~HPOl0@hk52-1|sj1nZ#T=!1AQs%bJouSg3g94zoV*KKtO7bwCXzqDn-(L9S;>$^iv%UJ2+t8Q6(p;HzAUlZx`QQ}YxGG7C~+ zzDmh2&x4(?4>q?fF*64gjxfQ@JcZKYRFG71eqJ8<3Lz*1bogIl5_nNL%rvCk8*1jOEt;aN?I39GY zV}71Kq>PEr%uCDHD=Pk;2RVxlv`z=K7oCLlGU#>`B<5u%XJ_W6gIov-BTyKC@D>Kt zZ~^U6i_V9vPjzDgoz=y_0OPweLGIr`4!3Pk{jf0K&cMI`x^DzjI)TjJ$-uy{3r)># z1_p*bP%%&)2a3bJNP9MkS@;E7zXY=rwEry>vA+Ra@FDy00O;IR@Hs80eg&Ozbclh0 z;V|edkUXSf6uhz7A9ThPmkRGSf;>sXsDF|YN#6Tv44&ef^ zAtgp2s04I{p6=t9UlN>}nhi1mbVycWda7G#PEI)Jr17ZKqWqA|+|(5R(h{h{KsT;I znc#E2fOS_{|v-}Sml$SUjRBW%s(%u5+UjWF6r`%DnUoXf=(avEOtZ| zLvX@D2Sqr6$|FZe4dx2EQmWVqTn+_f7NkP$cF8Z#1D*B>I<^B=0D<`6a|QkKOPpav z50sIapXUfEd7uV_B95&9og#+BMd%1hEl!1*l$oCwlnO3&KxeH$N*$L}P@w}mO)Mxi zxeQ$3Ad1)G(qzyHX=$LtPI6PhenFW;2iy-GWqGw24 zdvidw6DW_qDT3U216pqeT9*nsA+Rj5NCC8N6>KkjI}ZbcPBG+MCt~e@ngz0kA)pv? zj~Z+b5TWf!Q;H#blZdqow%2G+u>klCGnhSC^rIDm1&Kx3sYUwW=2Ry5Y_dPakTW?H zq4(^e>;nKPS12w?EJC=meP{{T}D+B*-j7okJ}v>-nneAo%>N{5_EhJq5v`M@xJ zpt~SJomLckz*d0I=gb3{x1t16R>Jgv)>(oEc42(b*@vJz6_LxMBcL03bF+llCuREBC-V-T(bojVCe{S{tVP0LE9{#{j4B9sD1=t(0=XX3=9k>plbB=7#JkVA?GDK zf!q7OrJ!RG^NUDm0WdHyoP(MNs$b7DK+FUQWnvzaXa(*Vf%ea4g06Kb1+AG*Re&hW zELLD(s3?cz`x)hsy9YpKgWL|n7eMVV$mvmvwzjsI%VQHX!24blia@vBY9??gfcL>z zDI_H5a6tq?Y|s&84A;vc=dyi(+QU=@XrB@;H6|61HX6tvQ22rT8c_iW zN056#`2*zMiwq15mlzlrE`!>93JS2TO#1NiFVb>L^pi?6b5c@^ia~3+Dd zJt&sumFDUd75}Xe0N?!yI13Vw21P7$A zT~bt$ zW*Ag&6oIY_NJ*_w0Cf#PePf6W==L74As`{hv5pEYRggR|tqOAQ07NCIOAW~|C#oQ4 z)WGB+`XO?~pgS{)K{u9xZ&gUmO968jUQ|KO-uqVtIroNffB`7)P==ZC0%kP80s=@D zM(gS6#e$BYhZaJh;T-5-MiS^azhY2)Brq^2);gN2Au(tCjS%>OypR#bNPE;0y@=O)G0x&+zD&xcHRR-ia%>?Am?wb}w1BZ~xKb=g!}{?J;BT*<_VsVvwtfG>W5=%xiitI@|Uih`|sx;70u4UFQBgf?tNaqxvjmE>x7BH>7^%5 zUbuMU=JS9585H7`n(nhSxo}9cun9J<;cHmUD$m&{%`C~m$fD0;!otqX$j-(t$Q8gZ z#2(7d%p$|Z$;`pb&dkKj%*?~W%FNBi$S2C`$1cqt&d$Up#v8!m%&g1I$Rfzb&tt_R zs~WG6%aWzqaDugI1G5xc(_iLDb}>!~P7xjvo-8&lHYv79c5PNSE*%yg7Di@6ZXFgW zHg4vIHEdjL`i8#D4NEv|nE9D)*ey7;S)2X~N^s~4>M|?xEAlt=ury7V`#hiKGMjTY#)vfR;Al9_$|YgV%*AHG;l{zkR>CdE z9K{mJ+0ZN@!zIS)!_v^jwt5MVIE&#zmd0CZ>^!Wj4a)=?zp^tbXtDXQH1x7G>|>T@ z=I3Q#V`OAzWMN`uXJ_Kz;AG-r^np-&XWu+{N(3cDKmU}}m~GpoW!O2m zxJAUxEUi|oym6D$e8R*P>|EA%X_@_#^5gfvdmokb<sIBi>vTFT?0~gk<&&!`2r&P_#%%aPj#>}X%*U%)(Y{)OeqQWW1s?F-c!l%`+ zicN(@g++tIgxk-#(VSC^i$lWN)si`xgVR8aRgqbmmC?b1#hX>1g^Qh&-9bT}g@@CO z*@{()orQ-zz|-8A*O*<8gR4<3$WMbqOH4{lMns&`k41&kg;$cDi_L>WowJnN-cgIq znw5(!kd2X5fSI+SJ4w!igR5a#oRTXy7aOmz6&shC4vTohPMefq9uH0~H&sUu<$;xUeu&mTXpDW=?j2NeS+p zB{mJ;xQaOnMBN%@iSUGTN;b4Nx-+*r@r$+u$TvLHZn&z;EXBgq=pZj>#md<7py9iw z4+|FyQ?sCpk8Q&t8#YFkP*!OZrba#;mK2^au7-6Mvb;Jhoa{_|Yz?!TZ?Fn5^D>w4 zM6&a+F!J-TSa5K$X>cg{HHPqrGP5$XbILMvv$AnRj2RckE5_IK$C+IQ!Q!tzNKf&xT<3lq>E=6+{-iPL^ z`4TPlB^Fv5$UJoaET`!6A?u;Pf4*YC+&v2e7|tgKre0ha$Z$(Bh~dG*V1tK=q3a$k z47>2+VVD9#Uib&b|KSV;4D1ZLjEsy-j7*G-9^3|^0*tBbOl(X{j4aBGa?;VEYt zI}JN7CPqdks4cRL9*iuEOw5do9E^dCOzb=yNsLUK+-zP<(%?3n zIUge{BNHn(qY5Wu8Ve&EBNG#oBohm>01Gc86B8RFKO+M(1G6lX9FrWA0}~@V2O|?V zC!;PiBV#F(5@Q)N3lk?J8}n@@CXj2{K}IrhuyHXl8ps>67_c)kvNCFL@-Qi|FflPQ zTQGth!feIC#59AMk(ZGjWFa%tF$V_5!-@>dy^IM83~ZT93@nUX3QPe^44?v+QId(3 zaXOQf5HF(|ha|TivjHP0$kZ8~*+5M=9!3sEeMVzOMrI}^RwhP9EhY}ecZ^JoEQ}0{ z3<3fI3``7+j~J)2GB7hTv9f3|voJ1YVqjrln#pa*Qq5?_ugS>7#KmmL!o8aD5(Fqsyk=x# zVPj%sl4c6!0O`vD#WfovV=6Nf3nME7CnM8WMlL2sMi#~iEKE!+j0#*DY~Wa8V`A3h zWn^MtXJlh!3=(5v2bosI#tbr;osrQ4WECR=69cO?I|HLVOCX4?$0W|c$jHpX%E7_J zF2^#3nZcaJh=Y-jQH+(5pMjlG5Nrx713LqwEeivCE;~a)!v_Wi#~Zze7`Q>VVt^a7 E0L!MzhyVZp literal 0 HcmV?d00001 diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/dune b/src/proto_020_PsParisC/lib_protocol/test/pbt/dune new file mode 100644 index 000000000000..750b149398e7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/dune @@ -0,0 +1,84 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_protocol_test_pbt_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-libs.micheline + octez-protocol-019-PtParisB-libs.client + tezos-protocol-019-PtParisB.protocol + octez-libs.tezos-context.merkle_proof_encoding + octez-libs.test-helpers + octez-protocol-019-PtParisB-libs.test-helpers + octez-alcotezt + qcheck-alcotest + tezos-benchmark + tezos-benchmark-019-PtParisB + tezos-benchmark-type-inference-019-PtParisB + octez-protocol-019-PtParisB-libs.smart-rollup + octez-libs.crypto-dal + octez-libs.base-test-helpers + tezos-protocol-019-PtParisB.parameters) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_micheline + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_test_helpers + -open Tezos_019_PtParisB_test_helpers + -open Octez_alcotezt + -open Tezos_benchmark_019_PtParisB + -open Tezos_benchmark_type_inference_019_PtParisB + -open Tezos_smart_rollup_019_PtParisB + -open Tezos_crypto_dal + -open Tezos_base_test_helpers + -open Tezos_protocol_019_PtParisB_parameters) + (modules + liquidity_baking_pbt + saturation_fuzzing + test_merkle_list + test_gas_properties + test_sampler + test_script_comparison + test_script_roundtrip + test_tez_repr + test_bitset + test_sc_rollup_tick_repr + test_sc_rollup_encoding + test_sc_rollup_inbox + test_refutation_game + test_carbonated_map + test_zk_rollup_encoding + test_dal_slot_proof + test_compare_operations + test_operation_encoding + test_balance_updates_encoding + test_bytes_conversion)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_pbt_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/liquidity_baking_pbt.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/liquidity_baking_pbt.ml new file mode 100644 index 000000000000..7eb90fe4ef0a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/liquidity_baking_pbt.ml @@ -0,0 +1,327 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: pbt for liquidity baking + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file liquidity_baking_pbt.ml + Subject: Test liquidity baking contracts using randomly generated inputs. +*) + +open Protocol +open Alpha_context +open Liquidity_baking_machine + +(** We use the “machines” provided by the {! Liquidity_baking_machine} + module. Because using the [ConcreteMachine] (hence, the {! + ValidationMachine} too) is slow, we implement the following + test-suit architecture: + + - One {v QCheck2 v}-based test is used to validate consistency of + the {! SymbolicMachine} wrt. the [ConcreteMachine], thanks to + the {! ValidationMachine}. + - The rest of the tests use the {! SymbolicMachine} in order to be + more effective. *) + +(** [all_true l] waits for all promises of [l], and returns [true] iff + they all resolve to [true]. *) +let all_true = List.for_all_ep Fun.id + +let extract_qcheck_tzresult : unit tzresult Lwt.t -> bool = + fun p -> + match Lwt_main.run p with + | Ok () -> true + | Error err -> QCheck2.Test.fail_reportf "@\n%a@." pp_print_trace err + +let rec run_and_check check scenarios env state = + match scenarios with + | step :: rst -> + let state' = SymbolicMachine.step step env state in + assert (check state state') ; + run_and_check check rst env state' + | [] -> state + +let one_balance_decreases c env state state' = + let xtz = SymbolicMachine.get_xtz_balance c state in + let tzbtc = SymbolicMachine.get_tzbtc_balance c env state in + let lqt = SymbolicMachine.get_liquidity_balance c env state in + let xtz' = SymbolicMachine.get_xtz_balance c state' in + let tzbtc' = SymbolicMachine.get_tzbtc_balance c env state' in + let lqt' = SymbolicMachine.get_liquidity_balance c env state' in + xtz' < xtz || tzbtc' < tzbtc || lqt' < lqt + || (xtz' = xtz && tzbtc' = tzbtc && lqt' = lqt) + +let get_float_balances env state = + let xtz = + Int64.to_float @@ SymbolicMachine.get_xtz_balance env.cpmm_contract state + in + let tzbtc = + Int.to_float + @@ SymbolicMachine.get_tzbtc_balance env.cpmm_contract env state + in + let lqt = + Int.to_float @@ SymbolicMachine.get_cpmm_total_liquidity env state + in + (xtz, tzbtc, lqt) + +(** [is_remove_liquidity_consistent env state state'] returns [true] + iff, when the liquidity pool decreased in [state'], then the + fraction of tzbtc and xtz returned to the liquidity provider is + lesser or equal than the fraction of lqt burnt. *) +let is_remove_liquidity_consistent env state state' = + let xtz, tzbtc, lqt = get_float_balances env state in + let xtz', tzbtc', lqt' = get_float_balances env state' in + if lqt' < lqt then + let flqt = (lqt -. lqt') /. lqt in + let fxtz = (xtz -. xtz') /. xtz in + let ftzbtc = (tzbtc -. tzbtc') /. tzbtc in + fxtz <= flqt && ftzbtc <= flqt + else true + +(** [is_share_price_increasing env state state'] returns [true] iff + the product of supplies (tzbtc, and xtz) increases. + + See https://blog.nomadic-labs.com/progress-report-on-the-verification-of-liquidity-baking-smart-contracts.html#evolution-of-the-product-of-supplies *) +let is_share_price_increasing env state state' = + let xtz, tzbtc, lqt = get_float_balances env state in + let xtz', tzbtc', lqt' = get_float_balances env state' in + xtz *. tzbtc /. (lqt *. lqt) <= xtz' *. tzbtc' /. (lqt' *. lqt') + +(** [positive_pools env state] returns [true] iff the three pools of + the CPMM (as identified in [env]) are strictly positive in + [state]. *) +let positive_pools env state = + let xtz = SymbolicMachine.get_xtz_balance env.cpmm_contract state in + let tzbtc = SymbolicMachine.get_tzbtc_balance env.cpmm_contract env state in + let lqt = SymbolicMachine.get_cpmm_total_liquidity env state in + 0L < xtz && 0 < tzbtc && 0 < lqt + +(** [validate_xtz_balance c env (blk, state)] returns [true] iff the + tez balance for the contract [c] is the same in [blk] and in + [state]. *) +let validate_xtz_balance : + Contract.t -> ValidationMachine.t -> bool tzresult Lwt.t = + fun contract state -> + let open Lwt_result_syntax in + let* expected = ValidationMachine.Symbolic.get_xtz_balance contract state in + let* amount = ValidationMachine.Concrete.get_xtz_balance contract state in + return (amount = expected) + +(** [validate_tzbtc_balance c env (blk, state)] returns [true] iff the + tzbtc balance for the contract [c] is the same in [blk] and in + [state]. *) +let validate_tzbtc_balance : + Contract.t -> Contract.t env -> ValidationMachine.t -> bool tzresult Lwt.t = + fun contract env state -> + let open Lwt_result_syntax in + let* expected = + ValidationMachine.Symbolic.get_tzbtc_balance contract env state + in + let* amount = + ValidationMachine.Concrete.get_tzbtc_balance contract env state + in + return (expected = amount) + +(** [validate_liquidity_balance c env (blk, state)] returns [true] if + the contract [c] holds the same amount of liquidity in [blk] and + [state]. *) +let validate_liquidity_balance : + Contract.t -> Contract.t env -> ValidationMachine.t -> bool tzresult Lwt.t = + fun contract env state -> + let open Lwt_result_syntax in + let* expected = + ValidationMachine.Symbolic.get_liquidity_balance contract env state + in + let* amount = + ValidationMachine.Concrete.get_liquidity_balance contract env state + in + return (expected = amount) + +(** [validate_balances c env (blk, state)] returns true iff the + contract [c] holds the same amount of tez, tzbtc and liquidity in + [blk] and [state]. *) +let validate_balances : + Contract.t -> Contract.t env -> ValidationMachine.t -> bool tzresult Lwt.t = + fun contract env combined_state -> + all_true + [ + validate_xtz_balance contract combined_state; + validate_tzbtc_balance contract env combined_state; + validate_liquidity_balance contract env combined_state; + ] + +(** [validate_cpmm_total_liquidity env state] returns true iff the + CPMM has distributed the same amount of liquidity tokens in its + concrete and symbolic parts of [state]. *) +let validate_cpmm_total_liquidity env state = + let open Lwt_result_syntax in + let* concrete_cpmm_total_liquidity = + ValidationMachine.Concrete.get_cpmm_total_liquidity env state + in + let* ghost_cpmm_total_liquidity = + ValidationMachine.Symbolic.get_cpmm_total_liquidity env state + in + return (concrete_cpmm_total_liquidity = ghost_cpmm_total_liquidity) + +(** [validate_consistency env (blk, state)] checks if the accounts in + [env] (the CPMM and the implicit accounts) share the same balances + in [blk] and [state]. *) +let validate_consistency : + Contract.t env -> ValidationMachine.t -> bool tzresult Lwt.t = + (* We do not try to validate the xtz balance of [holder] in this + function. Indeed, they are hard to predict due to allocation + fees, and security deposits. *) + fun env state -> + all_true + (validate_cpmm_total_liquidity env state + :: validate_balances env.cpmm_contract env state + :: List.map + (fun account -> validate_balances account env state) + env.implicit_accounts) + +(** [validate_storage env blk] returns [true] iff the storage of the + CPMM contract is consistent wrt. to its actual balances (tez, + tzbtc, and liquidity). *) +let validate_storage : + Contract.t env -> ConcreteMachine.t -> bool tzresult Lwt.t = + fun env blk -> + let open Lwt_result_syntax in + let* cpmm_storage = + Cpmm_repr.Storage.get (B blk) ~contract:env.cpmm_contract + in + all_true + [ + (* 1. Check the CPMM's [xtzPool] is equal to the actual CPMM balance *) + (let* cpmm_xtz = ConcreteMachine.get_xtz_balance env.cpmm_contract blk in + return (cpmm_xtz = Tez.to_mutez cpmm_storage.xtzPool)); + (* 2. Check the CPMM’s [lqtTotal] is correct wrt. liquidity contract *) + (let* liquidity_storage = + Lqt_fa12_repr.Storage.get (B blk) ~contract:env.liquidity_contract + in + return (cpmm_storage.lqtTotal = liquidity_storage.totalSupply)); + (* 3. Check the CPMM’s [tokenPool] is correct *) + (let* cpmm_tzbtc = + ConcreteMachine.get_tzbtc_balance env.cpmm_contract env blk + in + return (Z.to_int cpmm_storage.tokenPool = cpmm_tzbtc)); + ] + +(** [machine_validation_tests] is a list of asynchronous tests aiming + at asserting the correctness and consistencies of the machines + themselves. *) +let machine_validation_tests = + let open Lwt_result_syntax in + [ + QCheck2.Test.make + ~count:10 + ~name:"Concrete/Symbolic Consistency" + ~print:Liquidity_baking_generator.print_scenario + (Liquidity_baking_generator.gen_scenario 1_000_000 1_000_000 10) + (fun (specs, scenario) -> + extract_qcheck_tzresult + (let invariant = validate_consistency in + let* state, env = ValidationMachine.build ~invariant specs in + let* (_ : ValidationMachine.t) = + ValidationMachine.run ~invariant scenario env state + in + return_unit)); + QCheck2.Test.make + ~count:10 + ~name:"Storage consistency" + ~print:Liquidity_baking_generator.print_scenario + (Liquidity_baking_generator.gen_scenario 1_000_000 1_000_000 10) + (fun (specs, scenario) -> + extract_qcheck_tzresult + (let invariant = validate_storage in + let* state, env = ConcreteMachine.build ~invariant specs in + let* (_ : Block.t) = + ConcreteMachine.run ~invariant scenario env state + in + return_unit)); + QCheck2.Test.make + ~count:50_000 + ~name:"Positive pools" + ~print:Liquidity_baking_generator.print_scenario + (Liquidity_baking_generator.gen_scenario 1_000_000 1_000_000 50) + (fun (specs, scenario) -> + extract_qcheck_tzresult + (let invariant = positive_pools in + let state, env = SymbolicMachine.build ~invariant specs in + let (_ : SymbolicMachine.t) = + SymbolicMachine.run ~invariant scenario env state + in + return_unit)); + ] + +(** [economic_tests] is a list of asynchronous tests aiming at + asserting the good economic properties of the Liquidity Baking + feature. *) +let economic_tests = + [ + QCheck2.Test.make + ~count:50_000 + ~name:"No global gain" + ~print:Liquidity_baking_generator.print_adversary_scenario + (Liquidity_baking_generator.gen_adversary_scenario 1_000_000 1_000_000 50) + (fun (specs, attacker, scenario) -> + let state, env = SymbolicMachine.build ~subsidy:0L specs in + let (_ : SymbolicMachine.t) = + run_and_check (one_balance_decreases attacker env) scenario env state + in + true); + QCheck2.Test.make + ~count:50_000 + ~name:"Remove liquidities is consistent" + ~print:Liquidity_baking_generator.print_scenario + (Liquidity_baking_generator.gen_scenario 1_000_000 1_000_000 50) + (fun (specs, scenario) -> + let state, env = SymbolicMachine.build ~subsidy:0L specs in + let (_ : SymbolicMachine.t) = + run_and_check (is_remove_liquidity_consistent env) scenario env state + in + true); + QCheck2.Test.make + ~count:50_000 + ~name:"Share price only increases" + ~print:Liquidity_baking_generator.print_scenario + (Liquidity_baking_generator.gen_scenario 1_000_000 1_000_000 50) + (fun (specs, scenario) -> + let state, env = SymbolicMachine.build ~subsidy:0L specs in + let (_ : SymbolicMachine.t) = + run_and_check (is_share_price_increasing env) scenario env state + in + true); + ] + +let () = + let open Qcheck2_helpers in + Alcotest.run + ~__FILE__ + Protocol.name + [ + ("Machines Cross-Validation", qcheck_wrap machine_validation_tests); + ("Economic Properties", qcheck_wrap economic_tests); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/saturation_fuzzing.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/saturation_fuzzing.ml new file mode 100644 index 000000000000..1aea011452f2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/saturation_fuzzing.ml @@ -0,0 +1,202 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file saturation_fuzzing.ml + Subject: Operations in Saturation_repr +*) + +open Protocol.Saturation_repr +open Qcheck2_helpers + +(** A generator that returns a [t] that cannot be [saturated] *) +let unsatured_gen = of_option_gen @@ QCheck2.Gen.(map of_int_opt int) + +(** The general generator for [t]: generates both unsaturated values + and [saturated]. *) +let t_gen : may_saturate t QCheck2.Gen.t = + QCheck2.Gen.(frequency [(1, return saturated); (4, unsatured_gen)]) + +(* Test. + * Tests that [add] commutes. + *) +let test_add_commutes = + QCheck2.Test.make + ~name:"t1 + t2 = t2 + t1" + (QCheck2.Gen.pair t_gen t_gen) + (fun (t1, t2) -> + let t1_plus_t2 = add t1 t2 in + let t2_plus_t1 = add t2 t1 in + qcheck_eq ~pp t1_plus_t2 t2_plus_t1) + +(* Test. + * Tests that [mul] commutes. + *) +let test_mul_commutes = + QCheck2.Test.make + ~name:"t1 * t2 = t2 * t1" + (QCheck2.Gen.pair t_gen t_gen) + (fun (t1, t2) -> + let t1_times_t2 = mul t1 t2 in + let t2_times_t1 = mul t2 t1 in + qcheck_eq ~pp t1_times_t2 t2_times_t1) + +(* Test. + * Tests that [zero] is neutral for [add]. + *) +let test_add_zero = + QCheck2.Test.make ~name:"t + 0 = t" t_gen (fun t -> + let t_plus_zero = add t zero in + qcheck_eq' ~pp ~expected:t ~actual:t_plus_zero ()) + +(* Test. + * Tests that t1 + t2 >= t1 + *) +let test_add_neq = + QCheck2.Test.make + ~name:"t1 + t2 >= t1" + (QCheck2.Gen.pair t_gen t_gen) + (fun (t1, t2) -> + let t1_plus_t2 = add t1 t2 in + t1_plus_t2 >= t1) + +(* Test. + * Tests that 1 is neutral for [mul]. + *) +let test_mul_one = + let one = safe_int 1 in + QCheck2.Test.make ~name:"t * 1 = t" t_gen (fun t -> + let t_times_one = mul t one in + qcheck_eq' ~pp ~expected:t ~actual:t_times_one ()) + +(* Test. + * Tests that [t] times [0] equals [0]. + *) +let test_mul_zero = + QCheck2.Test.make ~name:"t * 0 = 0" t_gen (fun t -> + let t_times_zero = mul t zero in + qcheck_eq' ~pp ~expected:zero ~actual:t_times_zero ()) + +(* Test. + * Tests that [t] [sub] [zero] equals [t]. + *) +let test_sub_zero = + QCheck2.Test.make ~name:"t - 0 = t" t_gen (fun t -> + let t_sub_zero = sub t zero in + qcheck_eq' ~pp ~expected:t ~actual:t_sub_zero ()) + +(* Test. + * Tests that [t] [sub] [t] equals [zero]. + *) +let test_sub_itself = + QCheck2.Test.make ~name:"t - t = 0" t_gen (fun t -> + let t_sub_t = sub t t in + qcheck_eq' ~pp ~expected:zero ~actual:t_sub_t ()) + +(* Test. + * Tests that t1 - t2 <= t1 + *) +let test_sub_neq = + QCheck2.Test.make + ~name:"t1 - t2 <= t1" + (QCheck2.Gen.pair t_gen t_gen) + (fun (t1, t2) -> + let t1_minus_t2 = sub t1 t2 in + t1_minus_t2 <= t1) + +(* Test. + * Tests that (t1 + t2) - t2 <= t1 + *) +let test_add_sub = + QCheck2.Test.make + ~name:"(t1 + t2) - t2 <= t1" + (QCheck2.Gen.pair t_gen t_gen) + (fun (t1, t2) -> + let lhs = sub (add t1 t2) t2 in + lhs <= t1) + +(* Test. + * Tests that (t1 - t2) + t2 >= t1 + *) +let test_sub_add = + QCheck2.Test.make + ~name:"(t1 - t2) + t2 >= t1" + (QCheck2.Gen.pair t_gen t_gen) + (fun (t1, t2) -> + let lhs = add (sub t1 t2) t2 in + lhs >= t1) + +(* Test. + * Tests that [saturated] >= t + *) +let test_leq_saturated = + QCheck2.Test.make ~name:"t <= saturated" t_gen (fun t -> saturated >= t) + +(* Test. + * Tests that [zero] <= t + *) +let test_geq_zero = QCheck2.Test.make ~name:"t >= 0" t_gen (fun t -> zero <= t) + +(* Test. + * Tests that [sqrt (t * t) = t] + *) +let test_squared_sqrt = + QCheck2.Test.make ~name:"sqrt t² = t" t_gen (fun t -> + mul t t = saturated || sqrt (mul t t) = t) + +(* Test. + * Tests that [(sqrt t) * (sqrt t) <= t] + *) +let test_sqrt_squared = + QCheck2.Test.make ~name:"(sqrt t)² <= t <= (succ (sqrt t))²" t_gen (fun t -> + mul (sqrt t) (sqrt t) <= t && t <= mul (succ (sqrt t)) (succ (sqrt t))) + +let tests_add = [test_add_commutes; test_add_zero; test_add_neq] + +let tests_mul = [test_mul_commutes; test_mul_one; test_mul_zero] + +let tests_sub = [test_sub_zero; test_sub_itself; test_sub_neq] + +let tests_add_sub = [test_add_sub; test_sub_add] + +let tests_boundaries = [test_leq_saturated; test_geq_zero] + +let tests_sqrt = [test_sqrt_squared; test_squared_sqrt] + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [ + ("add", qcheck_wrap tests_add); + ("mul", qcheck_wrap tests_mul); + ("sub", qcheck_wrap tests_sub); + ("add and sub", qcheck_wrap tests_add_sub); + ("sqrt", qcheck_wrap tests_sqrt); + ("<= and >=", qcheck_wrap tests_boundaries); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_balance_updates_encoding.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_balance_updates_encoding.ml new file mode 100644 index 000000000000..5e4fb876d0aa --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_balance_updates_encoding.ml @@ -0,0 +1,208 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_balance_updates_encoding.ml + Subject: Encoding for balance_updates +*) + +open Protocol +open QCheck2 +open Qcheck2_helpers + +(** {2 Generators} *) +let default_delegate = + let pkh, _, _ = Signature.generate_key () in + pkh + +let default_contract = + let pkh, _, _ = Signature.generate_key () in + Contract_repr.Implicit pkh + +let contract = Receipt_repr.Contract default_contract + +let unstaked_frozen_staker = + let open Gen in + oneofl + [ + Unstaked_frozen_staker_repr.Shared default_delegate; + Unstaked_frozen_staker_repr.Single + (Contract_repr.Implicit default_delegate, default_delegate); + Unstaked_frozen_staker_repr.Single (default_contract, default_delegate); + ] + +let frozen_staker = + let open Gen in + oneofl + [ + Frozen_staker_repr.shared_between_stakers ~delegate:default_delegate; + Frozen_staker_repr.baker default_delegate; + Frozen_staker_repr.single_staker + ~staker:default_contract + ~delegate:default_delegate; + Frozen_staker_repr.baker_edge default_delegate; + ] + +let deposits = + let open Gen in + let+ staker = frozen_staker in + Receipt_repr.Deposits staker + +let lost_attesting_rewards = + let pkh, _, _ = Signature.generate_key () in + Receipt_repr.Lost_attesting_rewards (pkh, false, false) + +let unstaked_deposits = + let open Gen in + let+ staker = unstaked_frozen_staker in + Receipt_repr.Unstaked_deposits (staker, Cycle_repr.root) + +let commitments = Receipt_repr.Commitments Blinded_public_key_hash.zero + +let frozen_bonds = + let pkh, _, _ = Signature.generate_key () in + let bond_id = + Bond_id_repr.Sc_rollup_bond_id + (Sc_rollup_repr.Address.of_b58check_exn + "sr1JPVatbbPoGp4vb6VfQ1jzEPMrYFcKq6VG") + in + Receipt_repr.Frozen_bonds (Contract_repr.Implicit pkh, bond_id) + +let generate_balance = + let open Gen in + let open Receipt_repr in + oneof + [ + return contract; + return Block_fees; + deposits; + unstaked_deposits; + return Nonce_revelation_rewards; + return Attesting_rewards; + return Baking_rewards; + return Baking_bonuses; + return Storage_fees; + return Double_signing_punishments; + return lost_attesting_rewards; + return Liquidity_baking_subsidies; + return Burned; + return commitments; + return Bootstrap; + return Invoice; + return Initial_commitments; + return Minted; + return frozen_bonds; + return Sc_rollup_refutation_punishments; + return Sc_rollup_refutation_rewards; + ] + +let generate_balance_update = + let open Gen in + let open Receipt_repr in + let* i = big_nat in + let tez = Tez_repr.of_mutez_exn (Int64.of_int i) in + oneofl [Debited tez; Credited tez] + +let generate_update_origin = + let open Gen in + let open Receipt_repr in + oneofl [Block_application; Protocol_migration; Subsidy; Simulation] + +let generate_balance_updates : Receipt_repr.balance_updates Gen.t = + Gen.list + (Gen.map + (fun (balance, balance_update, update_origin) -> + Receipt_repr.item balance balance_update update_origin) + (Gen.tup3 + generate_balance + generate_balance_update + generate_update_origin)) + +(** {2 Tests} *) +let eq balance_updates1 balance_updates2 = + let open Receipt_repr in + let res = + List.for_all2 + ~when_different_lengths:() + (fun (Balance_update_item (b1, bu1, uo1)) + (Balance_update_item (b2, bu2, uo2)) -> + (let token1 = token_of_balance b1 in + let token2 = token_of_balance b2 in + match Token.eq token1 token2 with + | None -> false + | Some Refl -> ( + compare b1 b2 = 0 + && + match (bu1, bu2) with + | Debited tz1, Debited tz2 | Credited tz1, Credited tz2 -> + Token.equal token1 tz1 tz2 + | Debited tz1, Credited tz2 | Credited tz1, Debited tz2 -> + Token.is_zero token1 tz1 && Token.is_zero token1 tz2)) + && compare_update_origin uo1 uo2 = 0) + balance_updates1 + balance_updates2 + in + match res with Ok b -> b | Error _ -> false + +let test_balance_updates encoding = + let gen = generate_balance_updates in + test_roundtrip ~count:2000 ~title:"Balance_updates" ~gen ~eq encoding + +let test_binary_balance_updates encoding1 encoding2 = + let gen = generate_balance_updates in + test_roundtrip_through_binary + ~count:2000 + ~title:"Balance_updates" + ~gen + ~eq + encoding1 + encoding2 + +let () = + let qcheck_wrap = qcheck_wrap ~rand:(Random.State.make_self_init ()) in + Alcotest.run + ~__FILE__ + (Protocol.name ^ ": Operation_encoding") + [ + ( "roundtrip", + qcheck_wrap [test_balance_updates Receipt_repr.balance_updates_encoding] + ); + ( "legacy : roundtrip", + qcheck_wrap + [ + test_balance_updates + Receipt_repr.balance_updates_encoding_with_legacy_attestation_name; + ] ); + ( "roundtrip 2 encodings", + qcheck_wrap + [ + test_binary_balance_updates + Receipt_repr.balance_updates_encoding + Receipt_repr.balance_updates_encoding_with_legacy_attestation_name; + ] ); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_bitset.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_bitset.ml new file mode 100644 index 000000000000..a3a5e86b8cce --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_bitset.ml @@ -0,0 +1,125 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_bitset.ml + Subject: Bitset structure +*) + +open Qcheck2_helpers +open Protocol.Bitset + +let gen_ofs = QCheck2.Gen.int_bound (64 * 10) + +let value_of res = + match res with + | Ok v -> v + | Error e -> + Alcotest.failf + "An unxpected error %a occurred when generating Bitset.t" + Environment.Error_monad.pp_trace + e + +let gen_storage = + let open QCheck2.Gen in + let* int_vector = list @@ int_bound 64 in + from_list int_vector |> value_of |> return + +let test_get_set (c, ofs) = + List.for_all + (fun ofs' -> + let open Result_syntax in + value_of + @@ let* c' = add c ofs in + let* v = mem c ofs' in + let* v' = mem c' ofs' in + return (if ofs = ofs' then v' = true else v = v')) + (0 -- 63) + +let test_inter (c1, c2) = + let c3 = inter c1 c2 in + List.for_all + (fun ofs -> + let open Result_syntax in + value_of + @@ let* v1 = mem c1 ofs in + let* v2 = mem c2 ofs in + let* v3 = mem c3 ofs in + return ((v1 && v2) = v3)) + (0 -- 63) + +let test_diff (c1, c2) = + let c3 = diff c1 c2 in + List.for_all + (fun ofs -> + let open Result_syntax in + value_of + @@ let* v1 = mem c1 ofs in + let* v2 = mem c2 ofs in + let* v3 = mem c3 ofs in + return ((v1 && not v2) = v3)) + (0 -- 63) + +let test_fill = + let two = Z.of_int 2 in + fun length -> + let f1 = fill ~length |> value_of |> to_z in + let f2 = from_list (0 -- (length - 1)) |> value_of |> to_z in + let f3 = Z.(pow two length |> pred) in + Z.equal f1 f2 && Z.equal f2 f3 + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [ + ( "quantity", + qcheck_wrap + [ + QCheck2.Test.make + ~count:10000 + ~name:"get set" + QCheck2.Gen.(pair gen_storage gen_ofs) + test_get_set; + QCheck2.Test.make + ~count:10000 + ~name:"inter" + QCheck2.Gen.(pair gen_storage gen_storage) + test_inter; + QCheck2.Test.make + ~count:10000 + ~name:"diff" + QCheck2.Gen.(pair gen_storage gen_storage) + test_diff; + QCheck2.Test.make + ~count:10000 + ~name:"fill" + QCheck2.Gen.(small_nat) + test_fill; + ] ); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_bytes_conversion.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_bytes_conversion.ml new file mode 100644 index 000000000000..f5477dc7f991 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_bytes_conversion.ml @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 DaiLambda, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: pbt for bytes <=> nat/int conversions + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_bytes_conversion.ml + Subject: Test the conversions between bytes and int/nat +*) + +let failwith = Stdlib.failwith + +open Protocol +open Script_int +open Script_bytes + +let gen_n = + let open QCheck2.Gen in + let* n1 = int in + let+ n2 = int in + Z.(abs (of_int n1 * of_int n2)) + +let gen_z = + let open QCheck2.Gen in + let* n1 = int in + let+ n2 = int in + Z.(of_int n1 * of_int n2) + +let gen_bytes = + let open QCheck2.Gen in + bytes_size small_nat + +let test_bytes_nat_conversion_unit () = + let test z h = + (* nat => bytes *) + let (`Hex h') = Hex.of_bytes (bytes_of_nat_be (abs (of_zint z))) in + if h <> h' then + failwith (Format.asprintf "%a => %s <> %s" Z.pp_print z h' h) ; + (* bytes => nat *) + let z' = to_zint @@ nat_of_bytes_be (Hex.to_bytes_exn (`Hex h)) in + if Z.Compare.(z <> z') then + failwith (Format.asprintf "%a <> %a <= %s" Z.pp_print z Z.pp_print z' h) ; + (* "00" ^ bytes => nat *) + let h'' = "00" ^ h in + let z'' = to_zint @@ nat_of_bytes_be (Hex.to_bytes_exn (`Hex h'')) in + if Z.Compare.(z <> z'') then + failwith (Format.asprintf "%a <> %a <= %s" Z.pp_print z Z.pp_print z' h) + in + let test' h = test (Z.of_string ("0x" ^ h)) h in + test (Z.of_int 0) "" ; + test' "123456" ; + test' "010000000000000000" + +(* Tests of nat => bytes *) +let test_bytes_of_nat_random () = + let gen = + let open QCheck2.Gen in + let* n = gen_n in + let+ leading_bytes = small_nat in + (n, leading_bytes) + in + QCheck_alcotest.to_alcotest + @@ QCheck2.Test.make ~name:"bytes_of_nat" gen + @@ fun (n, leading_zeros) -> + let bytes = bytes_of_nat_be @@ abs (of_zint n) in + (* [bytes_of_nat] encodes any [nat] to the shortest representation in [bytes], + without leading zeros. *) + if Bytes.length bytes > 0 then assert (Bytes.get bytes 0 <> '\000') ; + (* [nat_of_bytes @@ bytes_of_nat n = n] *) + Z.Compare.(to_zint (nat_of_bytes_be bytes) = n) + (* Leading zero chars do not affect the decoding *) + && + let leading_zeros = Bytes.make leading_zeros '\000' in + Z.Compare.(to_zint (nat_of_bytes_be (Bytes.cat leading_zeros bytes)) = n) + +(* Tests of bytes => nat *) +let test_nat_of_bytes_random () = + QCheck_alcotest.to_alcotest + @@ QCheck2.Test.make ~name:"nat_of_bytes" gen_bytes + @@ fun b -> + (* [nat_of_bytes] decodes any [bytes] to a [nat] *) + let n = nat_of_bytes_be b in + (* [bytes_of_nat] encodes the [nat] back to the original [bytes] + but without its leading zeros. + *) + Z.Compare.(to_zint n >= Z.zero) + && + let b' = bytes_of_nat_be n in + let diff = Bytes.length b - Bytes.length b' in + let leading_zeros = Bytes.make diff '\000' in + b = Bytes.cat leading_zeros b' + +let test_bytes_int_conversion_unit () = + let test z h = + let z = Z.of_string z in + (* int => bytes *) + let (`Hex h') = Hex.of_bytes (bytes_of_int_be (of_zint z)) in + if h <> h' then + failwith (Format.asprintf "%a => %s <> %s" Z.pp_print z h' h) ; + (* bytes => int *) + let z' = to_zint @@ int_of_bytes_be (Hex.to_bytes_exn (`Hex h)) in + if Z.Compare.(z <> z') then + failwith (Format.asprintf "%a <> %a <= %s" Z.pp_print z Z.pp_print z' h) ; + (* ("00"|"ff") ^ bytes => int + Adding 00 or ff prefixes (00 for positive and ff for negative ints) + must not change the decoding. *) + let h'' = if Z.Compare.(z < Z.zero) then "ff" ^ h else "00" ^ h in + let z'' = to_zint @@ int_of_bytes_be (Hex.to_bytes_exn (`Hex h'')) in + if Z.Compare.(z <> z'') then + failwith (Format.asprintf "%a <> %a <= %s" Z.pp_print z Z.pp_print z' h) + in + test "0" "" ; + test "1" "01" ; + test "-1" "ff" ; + test "127" "7f" ; + test "-128" "80" ; + test "128" "0080" ; + test "-129" "ff7f" ; + test "0x8000" "008000" ; + test "-33024" "ff7f00" ; + test "0x010000000000000000" "010000000000000000" ; + test "-0x010000000000000000" "ff0000000000000000" ; + test "0xcd9e7dbee9425ffc" "00cd9e7dbee9425ffc" (* once failed due to a bug *) + +(* Tests of int => bytes *) +let test_bytes_of_int_random () = + let gen = + let open QCheck2.Gen in + let* z = gen_z in + let+ leading_bytes = small_nat in + (z, leading_bytes) + in + QCheck_alcotest.to_alcotest + @@ QCheck2.Test.make ~name:"bytes_of_int" gen + @@ fun (z, leading_bytes) -> + (* [bytes_of_int] must encode any [int] to [bytes]. *) + let bytes = bytes_of_int_be @@ of_zint z in + (* [bytes_of_int] must return the shortest encoding: at most 1 char of zero + or '\255's at the head. *) + (if Bytes.length bytes >= 2 then + match (Bytes.get bytes 0, Bytes.get bytes 1) with + | '\000', '\000' | '\255', '\255' -> assert false + | _ -> ()) ; + (* [int_of_bytes @@ bytes_of_int z = z] *) + (let z' = to_zint @@ int_of_bytes_be bytes in + Z.Compare.(z = z')) + (* [int_of_bytes] must ignore the leading zeros for 0 and positive ints + and '\255's for negatives *) + && + let leading_bytes = + Bytes.make leading_bytes (if Z.Compare.(z < Z.zero) then '\255' else '\000') + in + Z.Compare.(to_zint @@ int_of_bytes_be (Bytes.cat leading_bytes bytes) = z) + +(* Tests of bytes => int *) +let test_int_of_bytes_random () = + QCheck_alcotest.to_alcotest + @@ QCheck2.Test.make ~name:"int_of_bytes" gen_bytes + @@ fun b -> + (* [int_of_bytes] decodes any [bytes] to a [int] *) + let i = int_of_bytes_be b in + (* [bytes_of_int] must encode the [int] back to the original [bytes] + but without its leading zeros for 0 and positive [int]s and '\255' + for negatives. *) + let b' = bytes_of_int_be i in + let diff = Bytes.length b - Bytes.length b' in + let leading_bytes = + Bytes.make diff (if Z.Compare.(to_zint i < Z.zero) then '\255' else '\000') + in + b = Bytes.cat leading_bytes b' + +let tests = + [ + ( "bytes_nat_conv", + [ + ("unit", `Quick, test_bytes_nat_conversion_unit); + test_bytes_of_nat_random (); + test_nat_of_bytes_random (); + ] ); + ( "bytes_int_conv", + [ + ("unit", `Quick, test_bytes_int_conversion_unit); + test_bytes_of_int_random (); + test_int_of_bytes_random (); + ] ); + ] + +let () = + Alcotest.run + ~__FILE__ + (Protocol.name ^ ": bytes and int/nat conversion ") + tests diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_carbonated_map.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_carbonated_map.ml new file mode 100644 index 000000000000..cbef6686cda8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_carbonated_map.ml @@ -0,0 +1,547 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_carbonated_map.ml + Subject: Operations in Carbonated_map +*) + +open Qcheck2_helpers +open QCheck2 +open Protocol + +let new_ctxt () = + let open Lwt_result_syntax in + let* block, _contract = Context.init1 () in + let* incr = Incremental.begin_construction block in + return @@ Incremental.alpha_ctxt incr + +module Compare_int = struct + type t = int + + let compare = Int.compare + + let compare_cost _ = Saturation_repr.safe_int 10 +end + +module CM = + Carbonated_map.Make + (struct + type context = Alpha_context.context + + let consume = Alpha_context.Gas.consume + end) + (Compare_int) + +let unsafe_new_context () = + Result.value_f + ~default:(fun () -> Stdlib.failwith "Failed to create context") + (Lwt_main.run @@ new_ctxt ()) + +let int_map_gen = + let ctxt = unsafe_new_context () in + Gen.small_list (Gen.pair Gen.small_int Gen.small_int) + |> Gen.map (fun kvs -> + let merge_overlap ctxt x y = Ok (x + y, ctxt) in + match CM.of_list ctxt ~merge_overlap kvs with + | Ok (map, _) -> map + | Error _ -> Stdlib.failwith "Failed to construct map") + +let pp_int_map fmt map = + let open Lwt_result_wrap_syntax in + let pp = + Assert.pp_print_list (fun fmt (k, v) -> Format.fprintf fmt "(%d, %d)" k v) + in + Lwt_main.run + (let open Lwt_result_syntax in + let* ctxt = new_ctxt () in + let*?@ kvs, _ = CM.to_list ctxt map in + return kvs) + |> Result.value_f ~default:(fun () -> assert false) + |> Format.fprintf fmt "%a" pp + +let int_map_test name f = + Test.make + ~print:(Format.asprintf "%a" pp_int_map) + ~count:100 + ~name + int_map_gen + (fun map -> match f map with Ok b -> b | Error _ -> false) + +let int_map_pair_test name f = + Test.make + ~print:(fun (map1, map2) -> + Format.asprintf "(%a, %a)" pp_int_map map1 pp_int_map map2) + ~count:100 + ~name + (Gen.pair int_map_gen int_map_gen) + (fun (map1, map2) -> match f map1 map2 with Ok b -> b | Error _ -> false) + +let unit_test name f = + Alcotest.test_case name `Quick (fun () -> + match f () with Ok b -> assert b | _ -> assert false) + +type Environment.Error_monad.error += Dummy_error + +let dummy_fail = Error (Environment.Error_monad.trace_of_error Dummy_error) + +let assert_map_contains ctxt map expected = + let open Result_syntax in + let* kvs, _ctxt = CM.to_list ctxt map in + Ok (List.sort compare kvs = List.sort compare expected) + +let assert_equal_map ctxt map expected = + let open Result_syntax in + let* kvs, ctxt = CM.to_list ctxt expected in + assert_map_contains ctxt map kvs + +(** Test that the size of an empty map is 0. *) +let test_empty = + unit_test "Size of empty map is 0" (fun () -> Ok (CM.size CM.empty = 0)) + +(** Test adding a new element *) +let test_update_add = + let open Result_syntax in + unit_test "Update add" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(1, 1); (2, 2); (3, 3)] + in + let update_replace ctxt key value map = + CM.update ctxt key (fun ctxt _ -> Ok (Some value, ctxt)) map + in + let* map, ctxt = update_replace ctxt 4 4 map in + assert_map_contains ctxt map [(1, 1); (2, 2); (3, 3); (4, 4)] + +(** Test replacing an existing element. *) +let test_update_replace = + let open Result_syntax in + unit_test "Update replace" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(1, 1); (2, 2); (3, 3)] + in + let update_replace ctxt key value map = + CM.update ctxt key (fun ctxt _ -> Ok (Some value, ctxt)) map + in + let* map, ctxt = update_replace ctxt 1 42 map in + assert_map_contains ctxt map [(1, 42); (2, 2); (3, 3)] + +(** Test merging when ignoring new overlapping keys. *) +let test_merge_overlaps_left = + let open Result_syntax in + unit_test "Merge overlaps left" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun ctxt left _ -> Ok (left, ctxt)) + [(1, 1); (2, 2); (3, 3); (1, 11); (2, 22); (3, 33); (4, 44)] + in + assert_map_contains ctxt map [(1, 1); (2, 2); (3, 3); (4, 44)] + +(** Test merging when replacing the element of a new overlapping key. *) +let test_merge_overlaps_right = + let open Result_syntax in + unit_test "Merge overlap replace" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun ctxt _ right -> Ok (right, ctxt)) + [(1, 1); (2, 2); (3, 3); (1, 11); (2, 22); (3, 33); (4, 44)] + in + assert_map_contains ctxt map [(1, 11); (2, 22); (3, 33); (4, 44)] + +(** Test merging when combining elements of overlapping keys. *) +let test_merge_overlaps_add = + let open Result_syntax in + unit_test "Merge overlap by adding" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun ctxt left right -> Ok (left + right, ctxt)) + [(1, 1); (2, 2); (3, 3); (1, 1); (2, 2); (3, 3); (4, 4)] + in + assert_map_contains ctxt map [(1, 2); (2, 4); (3, 6); (4, 4)] + +(** Test update with merging elements of new and existing keys by adding them. *) +let test_update_merge = + let open Result_syntax in + unit_test "Update with merge add" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(1, 1); (2, 2); (3, 3)] + in + let update_merge ctxt key new_value map = + CM.update + ctxt + key + (fun ctxt existing -> + match existing with + | None -> Ok (Some new_value, ctxt) + | Some old_value -> Ok (Some (new_value + old_value), ctxt)) + map + in + let* map, ctxt = update_merge ctxt 1 1 map in + let* map, ctxt = update_merge ctxt 4 4 map in + assert_map_contains ctxt map [(1, 2); (2, 2); (3, 3); (4, 4)] + +(** Test merging two maps when keeping the original value for overlapping keys. *) +let test_merge_map_keep_existing = + let open Result_syntax in + unit_test "Merge overlap keep existing" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map1, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(1, "a"); (2, "b"); (3, "c")] + in + let* map2, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(2, "b'"); (3, "c'"); (4, "d'")] + in + let* map, ctxt = + CM.merge ctxt ~merge_overlap:(fun ctxt left _ -> Ok (left, ctxt)) map1 map2 + in + assert_map_contains ctxt map [(1, "a"); (2, "b"); (3, "c"); (4, "d'")] + +(** Test merging two maps when replacing the value for overlapping keys. *) +let test_merge_map_replace_existing = + let open Result_syntax in + unit_test "Merge overlap replace existing" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map1, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(1, "a"); (2, "b"); (3, "c")] + in + let* map2, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(2, "b'"); (3, "c'"); (4, "d'")] + in + let* map, ctxt = + CM.merge + ctxt + ~merge_overlap:(fun ctxt _ right -> Ok (right, ctxt)) + map1 + map2 + in + assert_map_contains ctxt map [(1, "a"); (2, "b'"); (3, "c'"); (4, "d'")] + +(** Test deleting existing and non-existing keys. *) +let test_update_delete = + let open Result_syntax in + unit_test "Update delete" @@ fun () -> + let ctxt = unsafe_new_context () in + let* map, ctxt = + CM.of_list + ctxt + ~merge_overlap:(fun _ _ _ -> dummy_fail) + [(1, 1); (2, 2); (3, 3)] + in + let delete ctxt key map = + CM.update ctxt key (fun ctxt _ -> Ok (None, ctxt)) map + in + let* map, ctxt = delete ctxt 1 map in + let* map, ctxt = delete ctxt 4 map in + assert_map_contains ctxt map [(2, 2); (3, 3)] + +(** Test that merging [empty] with a map returns the same map. *) +let test_empty_left_identity_for_merge = + let open Result_syntax in + int_map_test "Empty map is left identity for merge" @@ fun map -> + let ctxt = unsafe_new_context () in + let* map', ctxt = + CM.merge ctxt ~merge_overlap:(fun _ _ _ -> dummy_fail) map CM.empty + in + assert_equal_map ctxt map map' + +(** Test that merging a map with [empty] returns the same map. *) +let test_empty_right_identity_for_merge = + let open Result_syntax in + int_map_test "Empty map is right identity for merge" @@ fun map -> + let ctxt = unsafe_new_context () in + let* map', ctxt = + CM.merge ctxt ~merge_overlap:(fun _ _ _ -> dummy_fail) CM.empty map + in + assert_equal_map ctxt map map' + +(** Test that [size] returns the number of key value pairs of a map. *) +let test_size = + let open Result_syntax in + int_map_test "Size returns the number of elements" @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, _ = CM.to_list ctxt map in + return Compare.List_length_with.(kvs = CM.size map) + +(** Test that all keys of a map are found. *) +let test_find_existing = + let open Result_syntax in + int_map_test "Find all elements" @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, _ = CM.to_list ctxt map in + let* (_ : CM.context) = + List.fold_left_e + (fun ctxt (k, v) -> + let* v_opt, ctxt = CM.find ctxt k map in + match v_opt with Some v' when v = v' -> Ok ctxt | _ -> dummy_fail) + ctxt + kvs + in + return_true + +(** Test that find returns [None] for non-existing keys. *) +let test_find_non_existing = + let open Result_syntax in + int_map_test "Should not find non-existing" @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, _ = CM.to_list ctxt map in + let key = 42 in + let* v_opt, _ = CM.find ctxt key map in + match List.find_opt (fun (k, _) -> k = key) kvs with + | Some (_, value) -> Ok (Some value = v_opt) + | None -> Ok (None = v_opt) + +(** Test that [to_list] followed by [of_list] returns the same map. *) +let test_to_list_of_list = + let open Result_syntax in + int_map_test "To-list/of-list roundtrip" @@ fun map -> + let ctxt = unsafe_new_context () in + let merge_overlap ctxt x y = Ok (x + y, ctxt) in + let* kvs, ctxt = CM.to_list ctxt map in + let* map', ctxt = CM.of_list ctxt ~merge_overlap kvs in + assert_equal_map ctxt map map' + +(** Test that merging two maps is equivalent to merging the concatenated + key-value lists of both maps. *) +let test_merge_against_list = + let open Result_syntax in + int_map_pair_test "Merge compared with list operation" @@ fun map1 map2 -> + let ctxt = unsafe_new_context () in + let merge_overlap ctxt x y = Ok (x + y, ctxt) in + let* kvs1, ctxt = CM.to_list ctxt map1 in + let* kvs2, ctxt = CM.to_list ctxt map2 in + let* map_merged1, ctxt = CM.merge ctxt ~merge_overlap map1 map2 in + let* map_merged2, ctxt = CM.of_list ~merge_overlap ctxt (kvs1 @ kvs2) in + assert_equal_map ctxt map_merged1 map_merged2 + +(** Test that merging a map with itself does not alter its size. *) +let test_size_merge_self = + let open Result_syntax in + int_map_test "Size should not change when map is merging with itself" + @@ fun map -> + let ctxt = unsafe_new_context () in + let size1 = CM.size map in + let* map2, _ = + CM.merge + ctxt + ~merge_overlap:(fun ctxt left right -> Ok (left + right, ctxt)) + map + map + in + let size2 = CM.size map2 in + Ok (size1 = size2) + +(** Test that merging with a failing merge operation yields an error. *) +let test_merge_fail = + int_map_test "Merging with failing merge-overlap" @@ fun map -> + let ctxt = unsafe_new_context () in + Result.return + (match CM.merge ctxt ~merge_overlap:(fun _ _ _ -> dummy_fail) map map with + | Ok _ when CM.size map = 0 -> true + | Ok _ -> false + | Error _ -> true) + +(** Test that adding one key-value pair to a map increases its size by one iff + the key already exists. *) +let test_size_add_one = + let open Result_syntax in + int_map_test "Add a new element increases size by one" @@ fun map -> + let ctxt = unsafe_new_context () in + let key = 42 in + let* val_opt, ctxt = CM.find ctxt key map in + let* map', _ctxt = + CM.update + ctxt + key + (fun ctxt existing -> + match existing with + | None -> Ok (Some 42, ctxt) + | Some old_value -> Ok (Some old_value, ctxt)) + map + in + let size = CM.size map in + let size' = CM.size map' in + match val_opt with + | None -> Ok (size' = size + 1) + | Some _ -> Ok (size' = size) + +(** Test that mapping over a map is equivalent to mapping over the list of + key-value pairs and reconstructing the map. That is, the following diagram + commutes: + + [map] ----to_list---> [list] + | | + [map_e f] [List.map f] + | | + v v + [map] --- to_list --> [list] +*) +let test_map = + let open Result_syntax in + int_map_test "Test that map commutes with mapping over list" @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, ctxt = CM.to_list ctxt map in + let* map', ctxt = CM.map_e ctxt (fun ctxt _ x -> Ok (x + 1, ctxt)) map in + let kvs' = List.map (fun (k, v) -> (k, v + 1)) kvs in + assert_map_contains ctxt map' kvs' + +(** Test that folding over an empty map does not invoke the accumulator + function. *) +let test_fold_empty = + let open Result_syntax in + unit_test "Fold empty" @@ fun () -> + let ctxt = unsafe_new_context () in + let* x, _ = CM.fold_e ctxt (fun _ctxt _acc _k _v -> dummy_fail) 0 CM.empty in + Ok (x = 0) + +(** Test that folding over a map is equivalent to folding over the corresponding + list of key-value pairs. That is, the following diagram commutes: + + [map] -- to_list --> [list] + | | + [fold_e f z] [List.fold_left f z] + | | + res <----- id -----> res +*) +let test_fold = + let open Result_syntax in + int_map_test "Test that fold commutes with folding over a list" @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, ctxt = CM.to_list ctxt map in + let sum = List.fold_left (fun sum (k, v) -> k + v + sum) 0 kvs in + let* sum', _ = + CM.fold_e ctxt (fun ctxt sum k v -> Ok (k + v + sum, ctxt)) 0 map + in + Ok (sum = sum') + +(** Test that all key-value pairs can be collected by a fold. And that the + order is the same as for [to_list]. *) +let test_fold_to_list = + let open Result_syntax in + int_map_test "Test that fold collecting the elements agrees with to-list" + @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, ctxt = CM.to_list ctxt map in + let* kvs', _ = + CM.fold_e ctxt (fun ctxt kvs k v -> Ok ((k, v) :: kvs, ctxt)) [] map + in + Ok (kvs = List.rev kvs') + +(** Test that mapping with a failing function fails iff the list is non-empty. *) +let test_map_fail = + int_map_test "Test map with failing function" @@ fun map -> + let ctxt = unsafe_new_context () in + Result.return + (match CM.map_e ctxt (fun _ctxt _key _val -> dummy_fail) map with + | Ok _ when CM.size map = 0 -> true + | Error _ -> true + | Ok _ -> false) + +(** Test that removing an existing key from a map decreases its size by one. *) +let test_size_remove_one = + let open Result_syntax in + int_map_test "Remove new element decreases size by one" @@ fun map -> + let ctxt = unsafe_new_context () in + let* kvs, ctxt = CM.to_list ctxt map in + let key = match kvs with (k, _) :: _ -> k | _ -> 42 in + let* val_opt, ctxt = CM.find ctxt key map in + let* map', _ctxt = CM.update ctxt key (fun ctxt _ -> Ok (None, ctxt)) map in + let size = CM.size map in + let size' = CM.size map' in + match val_opt with + | None -> Ok (size' = size) + | Some _ -> Ok (size' = size - 1) + +let qcheck_tests = + [ + test_size; + test_to_list_of_list; + test_empty_left_identity_for_merge; + test_empty_right_identity_for_merge; + test_size_merge_self; + test_size_add_one; + test_size_remove_one; + test_merge_against_list; + test_merge_fail; + test_find_non_existing; + test_find_existing; + test_map; + test_fold; + test_fold_to_list; + test_map_fail; + ] + +let unit_tests = + [ + test_empty; + test_update_add; + test_update_replace; + test_merge_overlaps_left; + test_merge_overlaps_right; + test_merge_overlaps_add; + test_update_merge; + test_merge_map_keep_existing; + test_merge_map_replace_existing; + test_update_delete; + test_fold_empty; + ] + +let tests ~rand = qcheck_wrap ~rand qcheck_tests @ unit_tests + +let () = + (* Ensure deterministic results. *) + let rand = Random.State.make [|0x1337533D; 71287309; 397060904|] in + Alcotest.run ~__FILE__ Protocol.name [("Carbonated map", tests ~rand)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_compare_operations.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_compare_operations.ml new file mode 100644 index 000000000000..f91521772d3e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_compare_operations.ml @@ -0,0 +1,102 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Operation compare) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_compare_operations.ml + Subject: Valid operations Comparison +*) + +open Protocol +open Alpha_context +open Operation_generator +open QCheck2 + +let lt = -1 + +let gt = 1 + +let eq = 0 + +let cmp_op op1 op2 res = Compare.Int.equal (Operation.compare op1 op2) res + +(** A strict order has an equality predicate that is symmetric, + reflexive and transitive and an lt (and gt) predicates that is + antisymmetric and transitive. + + Testing that Operation.compare is a strict order on + operations is then testing that it is symmetric, transitive and + reflexive, when Operation.compare x y = 0; that it is transitive + when Operation.compare x y = -1 and Operation.compare x y = -1; and + that Operation.compare x y = - (Operation.compare y x) when differ + from 0. *) +let eq_sym op1 op2 = if cmp_op op1 op2 eq then assert (cmp_op op2 op1 eq) + +let eq_refl op = assert (cmp_op op op eq) + +let eq_trans op1 op2 op3 = + if cmp_op op1 op2 eq && cmp_op op2 op3 eq then assert (cmp_op op1 op3 eq) + +let lt_antisym op1 op2 = if cmp_op op1 op2 lt then assert (cmp_op op2 op1 gt) + +let lt_trans op1 op2 op3 = + if cmp_op op1 op2 lt && cmp_op op2 op3 lt then assert (cmp_op op1 op3 lt) + +let gt_trans op1 op2 op3 = + if cmp_op op1 op2 gt && cmp_op op2 op3 gt then assert (cmp_op op1 op3 gt) + +let gt_antisym op1 op2 = if cmp_op op1 op2 gt then assert (cmp_op op2 op1 lt) + +(** Testing that Operation.compare is a strict order on operations. *) +let strorder op1 op2 op3 = + eq_sym op1 op2 ; + eq_refl op1 ; + eq_trans op1 op2 op3 ; + lt_antisym op1 op2 ; + lt_trans op1 op2 op3 ; + gt_trans op1 op2 op3 ; + gt_antisym op1 op2 + +let test_compare_is_strorder = + Test.make + ~name:"Compare operations is a strict total order" + (Gen.triple generate_operation generate_operation generate_operation) + (fun ((k1, op1), (k2, op2), (k3, op3)) -> + try + strorder op1 op2 op3 ; + true + with exn -> + Format.eprintf "%a vs. %a vs. %a@." pp_kind k1 pp_kind k2 pp_kind k3 ; + raise exn) + +let tests = [test_compare_is_strorder] + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [("Compare_operations", Qcheck2_helpers.qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_dal_slot_proof.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_dal_slot_proof.ml new file mode 100644 index 000000000000..3c343c6b3b72 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_dal_slot_proof.ml @@ -0,0 +1,261 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: PBT for refutation proofs of Dal + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_dal_slot_proof.ml + Subject: Refutation proof-related functions of Dal +*) + +open Protocol + +module Make (Parameters : sig + val name : string + + val count : int + + val dal_parameters : Alpha_context.Constants.Parametric.dal +end) = +struct + module ARG = struct + include Parameters + + let cryptobox = + Lazy.from_fun @@ fun () -> + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Dal_helpers.mk_cryptobox Parameters.dal_parameters.cryptobox_parameters + end + + open Dal_helpers.Make (ARG) + + (* Introduce some intermediate types. *) + + (** The slot is not confirmed (skipped) iff the boolean is [true]. *) + type slot_skipped = bool + + type level = int + + type slots = level * slot_skipped list + + type levels = slots list + + (** Given a list of {!levels}, where each element is of type {!slots} = {!slot} + list, and where each slot is a boolean, this function populates an + empty slots_history skip list and a corresponding history_cache as follows: + - the function starts from a given [start_level] (default is 1) + - levels are incremented by 2 (to allow having levels without confirmed slots + for test purpose). + - every element in the list of levels represents the slots of a single level. + - each slot of a given level is not confirmed iff the boolean is true. *) + let populate_slots_history (levels_data : levels) = + let open Result_wrap_syntax in + (* Make and insert a slot. *) + let slot_data = + Bytes.init + Parameters.(dal_parameters.cryptobox_parameters.slot_size) + (fun _i -> 'x') + in + let* polynomial = dal_mk_polynomial_from_slot slot_data in + let cryptobox = Lazy.force ARG.cryptobox in + let* commitment = dal_commit cryptobox polynomial in + (* Insert the slots of a level. *) + let add_slots (cell, cache, slots_info) (level, slots_data) = + let curr_level = Raw_level_repr.of_int32_exn (Int32.of_int level) in + let slots_headers = + List.mapi + (fun sindex skip_slot -> + let index = + Option.value_f + (Dal_slot_index_repr.of_int_opt + ~number_of_slots:Parameters.(dal_parameters.number_of_slots) + sindex) + ~default:(fun () -> assert false) + in + ( Dal_slot_repr.Header. + {id = {published_level = curr_level; index}; commitment}, + skip_slot )) + slots_data + in + let attested_slots_headers = + List.filter_map + (fun (slot, skip_slot) -> if skip_slot then None else Some slot) + slots_headers + in + let*@ cell, cache = + Dal_slot_repr.History.add_confirmed_slot_headers + ~number_of_slots:Parameters.dal_parameters.number_of_slots + cell + cache + curr_level + attested_slots_headers + in + let slots_info = + List.fold_left + (fun slots_info (slot, skip_slot) -> + (polynomial, slot, skip_slot) :: slots_info) + slots_info + slots_headers + in + return (cell, cache, slots_info) + in + + (* Insert the slots of all the levels. *) + let add_levels = List.fold_left_e add_slots in + add_levels (genesis_history, genesis_history_cache, []) levels_data + + (** This function returns the (correct) information of a page to + prove that it is confirmed, or None if the page's slot is skipped. *) + let request_confirmed_page (poly, slot, skip_slot) = + let open Result_syntax in + if skip_slot then + (* We cannot check that a page of an unconfirmed slot is confirmed. *) + return_none + else + let* page_info, page_id = mk_page_info slot poly in + return_some (page_info, page_id) + + (** This function returns information of a page to prove that it is + unconfirmed, if the page's slot is skipped, the information look correct + (but the slot is not confirmed). Otherwise, we increment the publish_level + field to simulate a non confirmed slot (as for even levels, no slot is + confirmed. See {!populate_slots_history}). *) + let request_unconfirmed_page (poly, slot, skip_slot) = + let open Result_syntax in + let open Dal_slot_repr.Header in + if skip_slot then + let level = slot.id.published_level in + let* _page_info, page_id = mk_page_info ~level slot poly in + (* We should not provide the page's info if we want to build an + unconfirmation proof. *) + return_some (None, page_id) + else return_none + + (** This helper function allows to test DAL's {!produce_proof} and + {!verify_proof} functions, using the data constructed from + {!populate_slots_history} above. *) + let helper_check_pbt_pages last_cell last_cache slots_info ~page_to_request + ~check_produce ~check_verify = + let open Lwt_result_syntax in + List.iter_es + (fun item -> + let*? mk_test = page_to_request item in + match mk_test with + | None -> return_unit + | Some (page_info, page_id) -> + produce_and_verify_proof + last_cell + ~get_history:(get_history last_cache) + ~page_info + ~page_id + ~check_produce + ~check_verify) + slots_info + + (** Making some confirmation pages tests for slots that are confirmed. *) + let test_confirmed_pages (levels_data : levels) = + let open Lwt_result_syntax in + let*? last_cell, last_cache, slots_info = + populate_slots_history levels_data + in + helper_check_pbt_pages + last_cell + last_cache + slots_info + ~page_to_request:request_confirmed_page + ~check_produce:(successful_check_produce_result ~__LOC__ `Confirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Confirmed) + + (** Making some unconfirmation pages tests for slots that are confirmed. *) + let test_unconfirmed_pages (levels_data : levels) = + let open Lwt_result_syntax in + let*? last_cell, last_cache, slots_info = + populate_slots_history levels_data + in + helper_check_pbt_pages + last_cell + last_cache + slots_info + ~page_to_request:request_unconfirmed_page + ~check_produce:(successful_check_produce_result ~__LOC__ `Unconfirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Unconfirmed) + + let tests = + let gen_dal_config : levels QCheck2.Gen.t = + QCheck2.Gen.( + let nb_slots = 0 -- Parameters.(dal_parameters.number_of_slots) in + let nb_levels = 4 -- 30 in + let* start_level = small_nat in + (* The slot is confirmed iff the boolean is true *) + let slot = bool in + let slots = list_size nb_slots slot in + (* For each level, we generate the gap/delta w.r.t. the previous level, + and the slots' flags (confirmed or not). *) + let* list = list_size nb_levels slots in + List.mapi + (fun i slots -> + let level = start_level + i in + (level, slots)) + list + |> return) + in + [ + Tztest.tztest_qcheck2 + ~name:"Pbt tests: confirmed pages" + ~count:Parameters.count + gen_dal_config + test_confirmed_pages; + Tztest.tztest_qcheck2 + ~name:"Pbt tests: unconfirmed pages" + ~count:Parameters.count + gen_dal_config + test_unconfirmed_pages; + ] + + let tests = + [ + ( Format.sprintf + "[%s: %s] Dal slots refutation" + Protocol.name + Parameters.name, + tests ); + ] +end + +let () = + let open Tezos_protocol_020_PsParisC_parameters.Default_parameters in + let module Test = Make (struct + let name = "test" + + let count = 5 + + let dal_parameters = {constants_test.dal with number_of_slots = 24} + end) in + Alcotest_lwt.run + ~__FILE__ + (Protocol.name ^ ": Dal slots refutation game") + Test.tests + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_gas_properties.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_gas_properties.ml new file mode 100644 index 000000000000..8d7d19a88e57 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_gas_properties.ml @@ -0,0 +1,144 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (gas properties) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_gas_properties.ml + Subject: Arithmetic properties around gas. +*) + +open Protocol +open Qcheck2_helpers + +(** Extract a Tezos result for compatibility with QCheck2. *) +let extract_qcheck_result = function + | Ok pure_result -> pure_result + | Error err -> + Format.printf "@\n%a@." Environment.Error_monad.pp_trace err ; + false + +(** [Gas.free] is the neutral element of gas addition: [any_cost +@ Gas.free = Gas.free +@ any_cost = any_cost]. *) +let test_free_neutral (start, any_cost) = + let open Alpha_context in + extract_qcheck_result + (let open Result_syntax in + let* free_first = Gas.consume start Gas.free in + let* branch1 = Gas.consume free_first any_cost in + let* cost_first = Gas.consume start any_cost in + let+ branch2 = Gas.consume cost_first Gas.free in + let equal_consumption_from_start t1 t2 = + Gas.Arith.( + qcheck_eq + ~pp + ~eq:equal + (Gas.consumed ~since:start ~until:t1) + (Gas.consumed ~since:start ~until:t2)) + in + equal_consumption_from_start branch1 branch2 + && equal_consumption_from_start branch1 cost_first) + +(** Consuming [Gas.free] is equivalent to consuming nothing. *) +let test_free_consumption start = + let open Alpha_context in + extract_qcheck_result + (let open Result_syntax in + let+ after_empty_consumption = Gas.consume start Gas.free in + Gas.Arith.( + qcheck_eq + ~pp + ~eq:equal + (Gas.consumed ~since:start ~until:after_empty_consumption) + zero)) + +(** Consuming [cost1] then [cost2] is equivalent to consuming + [Gas.(cost1 +@ cost2)]. *) +let test_consume_commutes (start, cost1, cost2) = + let open Alpha_context in + extract_qcheck_result + (let open Result_syntax in + let* after_cost1 = Gas.consume start cost1 in + let* branch1 = Gas.consume after_cost1 cost2 in + let+ branch2 = Gas.consume start Gas.(cost1 +@ cost2) in + Gas.Arith.( + qcheck_eq + ~pp + ~eq:equal + (Gas.consumed ~since:start ~until:branch1) + (Gas.consumed ~since:start ~until:branch2))) + +(** Arbitrary context with a gas limit of 100_000_000. *) +let context_gen : Alpha_context.t QCheck2.Gen.t = + QCheck2.Gen.return + (Lwt_main.run + (let open Lwt_result_syntax in + let* b, _contract = Context.init1 () in + let+ inc = Incremental.begin_construction b in + Alpha_context.Gas.set_limit + (Incremental.alpha_ctxt inc) + Alpha_context.Gas.Arith.(fp (integral_of_int_exn 100_000_000))) + |> function + | Ok a -> a + | Error _ -> assert false) + +(** This arbitrary could be improved (pretty printer and shrinker) if there was a way to convert a [cost] back to an [int]. Otherwise one needs to write a custom [arbitrary] instance, but I wanted to stick to the former design of this test for the time being. *) +let gas_cost_gen : Alpha_context.Gas.cost QCheck2.Gen.t = + let open Alpha_context.Gas in + let open QCheck2.Gen in + let rand = 0 -- 1000 in + let safe_rand = map Saturation_repr.safe_int rand in + oneof + [ + map atomic_step_cost safe_rand; + map step_cost safe_rand; + map alloc_cost safe_rand; + map alloc_bytes_cost rand; + map alloc_mbytes_cost rand; + map read_bytes_cost rand; + map write_bytes_cost rand; + ] + +let tests = + [ + QCheck2.Test.make + ~count:1000 + ~name:"Consuming commutes" + QCheck2.Gen.(triple context_gen gas_cost_gen gas_cost_gen) + test_consume_commutes; + QCheck2.Test.make + ~count:1000 + ~name:"Consuming [free] consumes nothing" + context_gen + test_free_consumption; + QCheck2.Test.make + ~count:1000 + ~name:"[free] is the neutral element of Gas addition" + QCheck2.Gen.(pair context_gen gas_cost_gen) + test_free_neutral; + ] + +let () = + Alcotest.run ~__FILE__ Protocol.name [("gas properties", qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_merkle_list.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_merkle_list.ml new file mode 100644 index 000000000000..b59e3f817ffa --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_merkle_list.ml @@ -0,0 +1,144 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_merkle_list.ml + Subject: Tx rollup l2 encoding +*) + +open Qcheck2_helpers + +(* ------ generators -------------------------------------------------------- *) + +let input : bytes list QCheck2.Gen.t = + let open QCheck2.Gen in + list_size (2 -- 100) bytes_gen + +let valid_pos l = + let open QCheck2.Gen in + let* pos = 0 -- (List.length l - 1) in + return pos + +let invalid_pos l = + let open QCheck2.Gen in + let* choice = bool in + let* pos = + if choice then -20 -- -1 + else + let len = List.length l in + len -- (2 * len) + in + return pos + +let input_and_pos : (int * bytes list) QCheck2.Gen.t = + let open QCheck2.Gen in + let* l = input in + let* pos = valid_pos l in + return (pos, l) + +let input_and_pos_and_wrong_pos : (int * int * bytes list) QCheck2.Gen.t = + let open QCheck2.Gen in + let* l = input in + let* pos = valid_pos l in + let* wrong_pos = invalid_pos l in + return (pos, wrong_pos, l) + +(* ------ tests ------------------------------------------------------------- *) + +let test_scons_scons_tr_equiv ~count = + let open Merkle_list_helper in + QCheck2.Test.make ~count ~name:"scons_scons_tr_equiv" input (fun input -> + let snoc = List.fold_left snoc nil input in + let snoc_tr = List.fold_left snoc_tr nil input in + Internal_for_tests.equal snoc snoc_tr) + +let test_scons_compute_equiv ~count = + let open Merkle_list_helper in + QCheck2.Test.make ~count ~name:"scons_compute_equiv" input (fun input -> + let snoc = List.fold_left snoc nil input |> root in + let compute = compute input in + Hash.equal snoc compute) + +let test_of_list_compute_equiv ~count = + let open Merkle_list_helper in + QCheck2.Test.make ~count ~name:"of_list_compute_equiv" input (fun input -> + Hash.equal (root (of_list input)) (compute input)) + +let test_of_list_snoc_tr_equiv ~count = + let open Merkle_list_helper in + QCheck2.Test.make ~count ~name:"of_list_snoc_tr_equiv" input (fun input -> + let of_list = of_list input in + let snoc_tr = List.fold_left snoc_tr nil input in + Merkle_list_helper.Internal_for_tests.equal of_list snoc_tr) + +let ok_exn = function Ok x -> x | Error _ -> raise (Invalid_argument "ok_exn") + +let test_check_path ~count = + let open Merkle_list_helper in + QCheck2.Test.make ~count ~name:"check_path" input_and_pos (fun (pos, input) -> + let tree = List.fold_left snoc nil input in + let hash = root tree in + let path = ok_exn @@ compute_path tree pos in + ok_exn @@ check_path path pos (Stdlib.List.nth input pos) hash) + +let test_check_path_wrong ~count = + let open Merkle_list_helper in + QCheck2.Test.make + ~count + ~name:"check_path_wrong" + input_and_pos_and_wrong_pos + (fun (pos, wrong_pos, input) -> + let tree = List.fold_left snoc nil input in + let hash = root tree in + let path = ok_exn @@ compute_path tree pos in + match check_path path wrong_pos (Stdlib.List.nth input pos) hash with + | Ok b -> not b + | Error _ -> true) + +let () = + let qcheck_wrap = qcheck_wrap ~rand:(Random.State.make_self_init ()) in + Alcotest.run + ~__FILE__ + Protocol.name + [ + ( "scons_equiv", + qcheck_wrap + [ + test_scons_scons_tr_equiv ~count:1000; + test_scons_compute_equiv ~count:1000; + ] ); + ( "of_list_equiv", + qcheck_wrap + [ + test_of_list_compute_equiv ~count:1000; + test_of_list_snoc_tr_equiv ~count:1000; + ] ); + ( "check_path", + qcheck_wrap + [test_check_path ~count:1000; test_check_path_wrong ~count:1000] ); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_operation_encoding.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_operation_encoding.ml new file mode 100644 index 000000000000..91596e645e7b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_operation_encoding.ml @@ -0,0 +1,71 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_operation_encoding.ml + Subject: Encoding for operations +*) + +open Protocol +open QCheck2 +open Qcheck2_helpers + +(** {2 Generators} *) +let generate_operation = + let open Gen in + let+ _kind, (_hash, op) = Operation_generator.generate_operation in + op + +(** {2 Tests} *) + +let test_operation encoding = + let open Alpha_context in + let gen = generate_operation in + let eq {shell = s1; protocol_data = Operation_data d1} + {shell = s2; protocol_data = Operation_data d2} = + let o1 : _ Operation.t = {shell = s1; protocol_data = d1} in + let o2 : _ Operation.t = {shell = s2; protocol_data = d2} in + match Operation.equal o1 o2 with None -> false | Some Eq -> true + in + test_roundtrip ~count:2000 ~title:"Operation.t" ~gen ~eq encoding + +let () = + let qcheck_wrap = qcheck_wrap ~rand:(Random.State.make_self_init ()) in + Alcotest.run + ~__FILE__ + (Protocol.name ^ ": Operation_encoding") + [ + ( "roundtrip", + qcheck_wrap [test_operation Alpha_context.Operation.encoding] ); + ( "legacy : roundtrip", + qcheck_wrap + [ + test_operation + Alpha_context.Operation.encoding_with_legacy_attestation_name; + ] ); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_refutation_game.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_refutation_game.ml new file mode 100644 index 000000000000..7513484c30e3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_refutation_game.ml @@ -0,0 +1,1648 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: PBT for the SCORU refutation game + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_refutation_game.ml + Subject: SCORU refutation game +*) +open Protocol + +open Alpha_context +open Sc_rollup +open Qcheck2_helpers +open Sc_rollup_helpers + +(** {2 Utils} *) + +let qcheck_make_lwt = qcheck_make_lwt ~extract:Lwt_main.run + +let qcheck_make_lwt_res ?print ?count ~name ~gen f = + qcheck_make_result + ~pp_error:Error_monad.pp_print_trace + ?print + ?count + ~name + ~gen + (fun a -> Lwt_main.run (f a)) + +let tick_to_int_exn ?(__LOC__ = __LOC__) t = + WithExceptions.Option.get ~loc:__LOC__ (Tick.to_int t) + +let number_of_ticks_of_int64_exn ?(__LOC__ = __LOC__) n = + WithExceptions.Option.get ~loc:__LOC__ (Number_of_ticks.of_value n) + +let game_status_of_refute_op_result = function + | [ + Apply_results.Operation_metadata + { + contents = + Single_result + (Manager_operation_result + { + operation_result = + Applied (Sc_rollup_refute_result {game_status; _}); + _; + }); + }; + ] -> + game_status + | _ -> assert false + +let list_assoc (key : Tick.t) list = List.assoc ~equal:( = ) key list + +let print_dissection_chunk = Format.asprintf "%a" Dissection_chunk.pp + +let print_dissection = Format.asprintf "%a" Game.pp_dissection + +let print_our_states _ = "" + +(** Assert that the computation fails with the given message. *) +let assert_fails_with ~__LOC__ (res : unit Environment.Error_monad.tzresult) + expected_err = + match res with + | Error trace -> + let expected_trace = + Environment.Error_monad.trace_of_error expected_err + in + if expected_trace = trace then Lwt.return_true + else + let pp = Environment.Error_monad.pp_trace in + QCheck2.Test.fail_reportf + "@[Expected reason: %a@;Actual reason: %a@]" + pp + expected_trace + pp + trace + | Ok () -> Lwt.return_false + +let initial_of_dissection dissection = + List.hd dissection |> WithExceptions.Option.get ~loc:__LOC__ + +(** Modify the last section of a dissection. *) +let rec modify_stop f dissection = + match dissection with + | [] -> assert false + | [chunk] -> [f chunk] + | x :: xs -> + let xs = modify_stop f xs in + x :: xs + +(** Modify the first section of a dissection. *) +let modify_start f dissection = + match dissection with + | chunk :: xs -> f chunk :: xs + | [] -> (* The dissection can not be empty. *) assert false + +(** Checks that the [dissection] is valid regarding the function + {!Sc_rollup_game_repr.check_dissection}. *) +let valid_dissection ~default_number_of_sections ~start_chunk ~stop_chunk + dissection = + Game.Internal_for_tests.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + dissection + |> Result.is_ok + +(** [disputed_sections ~our_states dissection] returns the list of sections + in the [dissection] on which the player dissecting disagree with. + It uses [our_states], an assoc list between tick and state hashes to + compare opponent's claims against our point of view. *) +let disputed_sections ~our_states dissection = + let agree_on_state tick their_state = + let our_state = list_assoc tick our_states in + Option.equal State_hash.equal our_state their_state + in + let rec traverse acc = function + | Dissection_chunk.( + {state_hash = their_start_state; tick = start_tick} as a) + :: ({state_hash = their_stop_state; tick = stop_tick} as b) + :: dissection -> + let rst = b :: dissection in + if agree_on_state start_tick their_start_state then + (* It's a disputed section if we agree on the start state but disagree + on the stop. *) + if agree_on_state stop_tick their_stop_state then traverse acc rst + else + let disputed_section = (a, b) in + traverse (disputed_section :: acc) rst + else traverse acc rst + | _ -> acc + in + traverse [] dissection + +let pick_disputed_sections disputed_sections = + QCheck2.Gen.oneofl disputed_sections + +let single_tick_disputed_sections disputed_sections = + List.filter_map + (fun disputed_section -> + let Dissection_chunk.({tick = a_tick; _}, {tick = b_tick; _}) = + disputed_section + in + let distance = Tick.distance a_tick b_tick in + if Z.Compare.(distance = Z.one) then Some disputed_section else None) + disputed_sections + +let final_dissection ~our_states dissection = + let disputed_sections = disputed_sections ~our_states dissection in + let single_tick_disputed_sections = + single_tick_disputed_sections disputed_sections + in + Compare.List_length_with.(single_tick_disputed_sections > 0) + +(** Build a non-random dissection from [start_chunk] to [stop_chunk] using + [our_states] as the state hashes for each tick. *) +let build_dissection ~number_of_sections ~start_chunk ~stop_chunk ~our_states = + let open Lwt_result_syntax in + let state_of_tick ?start_state:_ tick = + return @@ list_assoc tick our_states + in + let state_hash_of_eval_state = Fun.id in + let our_stop_chunk = + Dissection_chunk. + {stop_chunk with state_hash = list_assoc stop_chunk.tick our_states} + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3491 + + This dissection's building does not check the number of sections. Checks should + be added to verify that we don't generate invalid dissection and test the + incorrect cases. *) + Lwt_main.run + @@ let*! r = + Game_helpers.( + make_dissection + ~state_of_tick + ~state_hash_of_eval_state + ~start_chunk + ~our_stop_chunk + @@ default_new_dissection + ~start_chunk + ~our_stop_chunk + ~default_number_of_sections:number_of_sections) + in + Lwt.return @@ WithExceptions.Result.get_ok ~loc:__LOC__ r + +let originate_rollup originator block = + let open Lwt_result_syntax in + let* origination_operation, sc_rollup = + Sc_rollup_helpers.origination_op (B block) originator Kind.Example_arith + in + let* block = Block.bake ~operations:[origination_operation] block in + let* inbox = Context.Sc_rollup.inbox (B block) in + let+ genesis_info = Context.Sc_rollup.genesis_info (B block) sc_rollup in + (block, sc_rollup, inbox, genesis_info) + +(** [create_ctxt ()] creates a context where an arith rollup was originated, + and both [account1] and [account2] owns enough tez to stake on a + commitment. *) +let create_ctxt () = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Lwt_main.run + @@ + let open Lwt_result_syntax in + let* block, (account1, account2, account3) = + Context.init3 + ~sc_rollup_arith_pvm_enable:true + ~consensus_threshold:0 + ~bootstrap_balances:[100_000_000_000L; 100_000_000_000L; 100_000_000_000L] + () + in + let* block, sc_rollup, inbox, genesis_info = + originate_rollup account3 block + in + return (block, sc_rollup, inbox, genesis_info, (account1, account2, account3)) + +(** {2 Context free generators} *) + +(** Generate a {!State_hash.t}. + + We use a dirty hack {!QCheck2.Gen.make_primitive} to remove the + automatic shrinking. Shrinking on the states in a dissection can + be confusing, it can leads to a shrunk list with the same states in + each cell. +*) +let gen_random_hash = + let open QCheck2.Gen in + let gen = + let* x = bytes_fixed_gen 32 in + return @@ State_hash.of_bytes_exn x + in + (* This is not beautiful, but there is currently no other way to + remove the shrinker. *) + make_primitive + ~gen:(fun rand -> generate1 ~rand gen) + ~shrink:(fun _ -> Seq.empty) + +(** Generate the number of sections in the dissection. *) +let gen_num_sections = + let open Tezos_protocol_020_PsParisC_parameters.Default_parameters in + let testnet = constants_test.sc_rollup.number_of_sections_in_dissection in + let mainnet = constants_mainnet.sc_rollup.number_of_sections_in_dissection in + let sandbox = constants_sandbox.sc_rollup.number_of_sections_in_dissection in + QCheck2.Gen.( + frequency + [(5, pure mainnet); (4, pure testnet); (2, pure sandbox); (1, 4 -- 100)]) + +(** Generate a tick. *) +let gen_tick ?(lower_bound = 0) ?(upper_bound = 10_000) () = + let open QCheck2.Gen in + let+ tick = lower_bound -- upper_bound in + tick_of_int_exn ~__LOC__ tick + +(** Generate two chunks consisting in valid boundaries for a dissection *) +let gen_wasm_pvm_dissection_boundaries kind = + let open QCheck2.Gen in + let open Alpha_context in + let* broken = bool in + let* state_hash = gen_random_hash in + let* base = Z.of_int <$> 0 -- 10_000 in + let* len = + Z.of_int + <$> + match kind with + | `Kernel_run -> pure 1 + | `Short -> 2 -- 32 + | `Large -> 1_000 -- 10_000 + in + let+ offset = + if broken then 1 -- Z.to_int Sc_rollup.Wasm_2_0_0PVM.ticks_per_snapshot + else pure 0 + in + let start_tick = + Sc_rollup.Tick.of_z @@ Z.(base * Sc_rollup.Wasm_2_0_0PVM.ticks_per_snapshot) + in + let stop_tick = + Sc_rollup.Tick.of_z + @@ Z.( + ((base + len) * Sc_rollup.Wasm_2_0_0PVM.ticks_per_snapshot) + + Z.of_int offset) + in + let start_chunk = + Sc_rollup.Dissection_chunk. + {tick = start_tick; state_hash = Some State_hash.zero} + in + let stop_chunk = + Sc_rollup.Dissection_chunk.{tick = stop_tick; state_hash = Some state_hash} + in + (start_chunk, stop_chunk) + +(** [gen_arith_pvm_messages ~gen_size] is a `correct list` generator. + It generates a list of strings that are either integers or `+` to be + consumed by the arithmetic PVM. + If a `+` is found then the previous two element of the stack are poped + then added and the result is pushed to the stack. In particular, + lists like `[1 +]` are incorrect. *) +let gen_arith_pvm_messages ~gen_size = + let open QCheck2.Gen in + (* To preserve the correctness invariant, genlist is a recursive generator + that produce a pair `(stack_size, state_list)` where state_list is a + correct list of integers and `+` and consuming it will produce a `stack` + of length `stack_size`. + For example a result can be `(3, [1; 2; +; 3; +; 2; 2; +; 1;]). + Consuming the list will produce the stack`[6; 4; 1]` which has length 3. *) + let produce_inputs self fuel = + match fuel with + | 0 -> map (fun x -> (1, [string_of_int x])) small_nat + | n -> + (* The generator has two branches. + 1. with frequency 1 adds integers to state_list and increases the + corresponding stack_size. + 2. With frequency 2, at each step, it looks at the inductive result + [(self (n - 1)) = (stack_size, state_list)]. + + If the stack_size is smaller than 2 then it adds an integer to the + state_list and increases the stack_size. Otherwise, it adds a plus + to the state_list and decreases the stack_size. *) + frequency + [ + ( 2, + map2 + (fun x (stack_size, state_list) -> + if stack_size >= 2 then (stack_size - 1, "+" :: state_list) + else (stack_size + 1, string_of_int x :: state_list)) + small_nat + (self (n / 2)) ); + ( 1, + map2 + (fun x (i, y) -> (i + 1, string_of_int x :: y)) + small_nat + (self (n / 2)) ); + ] + in + let+ inputs = sized_size gen_size @@ fix produce_inputs in + snd inputs |> List.rev |> String.concat " " + +(** Generate a list of level and associated arith pvm messages. *) +let gen_arith_pvm_payloads_for_levels ~start_level ~max_level = + gen_payloads_for_levels + ~start_level + ~max_level + (gen_arith_pvm_messages ~gen_size:(QCheck2.Gen.pure 0)) + +(** Dissection helpers and tests *) +module Dissection = struct + (** Generate an initial *valid* dissection. The validity comes from a + mirrored implementation of {!Sc_rollup_game_repr.initial}. *) + let gen_initial_dissection ?ticks () = + let open QCheck2.Gen in + let* child_state = gen_random_hash and* parent_state = gen_random_hash in + let* ticks = + let+ ticks = + match ticks with + | None -> frequency [(1, pure 0); (9, 1 -- 1_000)] + | Some distance -> pure distance + in + Z.of_int ticks + in + let* initial_tick = gen_tick () in + if Z.Compare.(ticks = Z.zero) then + pure + [ + Dissection_chunk.{state_hash = Some child_state; tick = initial_tick}; + Dissection_chunk.{state_hash = None; tick = Tick.next initial_tick}; + ] + else + let tick = Tick.jump initial_tick ticks in + pure + [ + Dissection_chunk.{state_hash = Some parent_state; tick = initial_tick}; + Dissection_chunk.{state_hash = Some child_state; tick}; + Dissection_chunk.{state_hash = None; tick = Tick.next tick}; + ] + + (** Generate a *valid* dissection. + It returns the dissection alongside the dissected start_chunk and + stop_chunk, but also the number of sections used to generate the + dissection. *) + let gen_dissection ~number_of_sections ~our_states dissection = + let open QCheck2.Gen in + let disputed_sections = disputed_sections ~our_states dissection in + assert (Compare.List_length_with.(disputed_sections > 0)) ; + let+ start_chunk, stop_chunk = pick_disputed_sections disputed_sections in + let dissection = + build_dissection ~number_of_sections ~start_chunk ~stop_chunk ~our_states + in + (dissection, start_chunk, stop_chunk) + + let gen_initial_dissection_ticks = QCheck2.Gen.(0 -- 1_000) + + let gen_nonfinal_initial_dissection_ticks = QCheck2.Gen.(3 -- 1_000) + + (** Given an initial tick and state_hash: generates random state hashes for + every others [ticks]. + Having [our_states] provide the state hashes you believe to + be true. You can then generate a dissection from another one when + you disagree with some sections. *) + let gen_our_states start_chunk ticks = + let open QCheck2.Gen in + let Dissection_chunk.{tick = initial_tick; state_hash = initial_state_hash} + = + start_chunk + in + let initial_state_hash = + WithExceptions.Option.get ~loc:__LOC__ initial_state_hash + in + let initial_tick_int = tick_to_int_exn initial_tick in + let rec aux acc i = + if i < 0 then return acc + else if i = 0 then return ((initial_tick, initial_state_hash) :: acc) + else + let* state_hash = gen_random_hash in + let tick = tick_of_int_exn (i + initial_tick_int) in + aux ((tick, state_hash) :: acc) (i - 1) + in + aux [] ticks + + (** {3 Dissection tests} *) + + let count = 300 + + (** Test the validity of dissection generated by {!gen_dissection} on + an initial dissection generated by {!gen_initial_dissection}. + It is a self test that'll help detect issues in subsequent tests; + in case the generator does not produce valid dissections. *) + let test_valid_gen_dissection = + let open QCheck2 in + let gen = + let open Gen in + let* number_of_sections = gen_num_sections in + let* ticks = gen_initial_dissection_ticks in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + if final_dissection ~our_states dissection then + (* The initial dissection could not be dissected. *) + return (dissection, None, number_of_sections, our_states) + else + let* new_dissection, start_hash, stop_hash = + gen_dissection ~number_of_sections ~our_states dissection + in + return + ( dissection, + Some (new_dissection, start_hash, stop_hash), + number_of_sections, + our_states ) + in + let print = + Print.( + quad + print_dissection + (option + (triple + print_dissection + print_dissection_chunk + print_dissection_chunk)) + int + print_our_states) + in + qcheck_make_lwt + ~count + ~name:"gen_dissection produces a valid dissection" + ~print + ~gen + (fun (dissection, new_dissection, default_number_of_sections, our_states) + -> + let open Lwt_syntax in + match new_dissection with + | None -> return (final_dissection ~our_states dissection) + | Some (new_dissection, start_chunk, stop_chunk) -> + return + @@ valid_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + new_dissection) + + (** Truncate a [dissection] and expect the + {!Sc_rollup_game_repr.check_dissection} to fail with an invalid + number of sections, where [expected_number_of_sections] is expected. *) + let truncate_and_check_error dissection start_chunk stop_chunk + default_number_of_sections expected_number_of_sections = + let truncated_dissection = + match dissection with + | x :: _ :: z :: rst -> x :: z :: rst + | _ -> + (* If the dissection is valid, this case can not be reached. *) + assert false + in + let expected_len = Z.of_int expected_number_of_sections in + let expected_reason = + Dissection_chunk.Dissection_number_of_sections_mismatch + {expected = expected_len; given = Z.pred expected_len} + in + assert_fails_with + ~__LOC__ + (Game.Internal_for_tests.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + truncated_dissection) + expected_reason + + (** Test that if a dissection is smaller than the default number of + sections, the length is equal to (distance + 1) of the dissected + section. *) + let test_truncated_small_dissection = + let open QCheck2 in + qcheck_make_lwt + ~count + ~name: + "distance < nb_of_sections => (len dissection = succ (dist dissection))" + ~gen: + (let open Gen in + let* number_of_sections = gen_num_sections in + let* ticks = 3 -- (number_of_sections - 1) in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + let* new_dissection, start_hash, stop_hash = + gen_dissection ~number_of_sections ~our_states dissection + in + return (new_dissection, start_hash, stop_hash, number_of_sections, ticks)) + (fun ( dissection, + start_chunk, + stop_chunk, + default_number_of_sections, + distance ) -> + let expected_len = distance in + truncate_and_check_error + dissection + start_chunk + stop_chunk + default_number_of_sections + expected_len) + + (** Test that if the distance in the dissected section is larger than + the default number of sections, the dissection length is exactly the + default number of sections. *) + let test_truncated_large_dissection = + let open QCheck2 in + qcheck_make_lwt + ~count + ~name:"distance >= nb_of_sections => (len dissection = nb_of_sections" + ~gen: + (let open Gen in + let* number_of_sections = gen_num_sections in + let* ticks = number_of_sections -- 1_000 in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + let* new_dissection, start_chunk, stop_chunk = + gen_dissection ~number_of_sections ~our_states dissection + in + return (new_dissection, start_chunk, stop_chunk, number_of_sections)) + (fun (dissection, start_chunk, stop_chunk, default_number_of_sections) -> + truncate_and_check_error + dissection + start_chunk + stop_chunk + default_number_of_sections + default_number_of_sections) + + (** Test that we can not change the start chunk of a section when we produce + a dissection. *) + let test_immutable_start_chunk = + let open QCheck2 in + qcheck_make_lwt + ~count + ~name:"dissection.start_chunk can not change" + ~gen: + (let open Gen in + let* number_of_sections = gen_num_sections in + let* ticks = gen_nonfinal_initial_dissection_ticks in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + let* new_dissection, start_chunk, stop_chunk = + gen_dissection ~number_of_sections ~our_states dissection + in + let* new_state_hash = gen_random_hash in + return + ( new_dissection, + start_chunk, + stop_chunk, + number_of_sections, + new_state_hash )) + (fun ( dissection, + start_chunk, + stop_chunk, + default_number_of_sections, + new_state_hash ) -> + (* Check that we can not change the start hash. *) + let dissection_with_different_start = + modify_start + (fun chunk -> + Dissection_chunk.{chunk with state_hash = Some new_state_hash}) + dissection + in + assert_fails_with + ~__LOC__ + (Game.Internal_for_tests.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + dissection_with_different_start) + (Dissection_chunk.Dissection_start_hash_mismatch + {expected = start_chunk.state_hash; given = Some new_state_hash})) + + (** Test that we can not produce a dissection that agrees with the stop hash. + Otherwise, there would be nothing to dispute. *) + let test_stop_hash_must_change = + let open QCheck2 in + qcheck_make_lwt + ~count + ~name:"dissection.stop_chunk must change" + ~gen: + (let open Gen in + let* number_of_sections = gen_num_sections in + let* ticks = gen_nonfinal_initial_dissection_ticks in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + let* new_dissection, start_chunk, stop_chunk = + gen_dissection ~number_of_sections ~our_states dissection + in + return (new_dissection, start_chunk, stop_chunk, number_of_sections)) + (fun (dissection, start_chunk, stop_chunk, default_number_of_sections) -> + let open Lwt_syntax in + let check_failure_on_same_stop_hash stop_hash = + let invalid_dissection = + modify_stop + (fun chunk -> + Dissection_chunk.{chunk with state_hash = stop_hash}) + dissection + in + let stop_chunk = + Dissection_chunk.{stop_chunk with state_hash = stop_hash} + in + assert_fails_with + ~__LOC__ + (Game.Internal_for_tests.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + invalid_dissection) + (Dissection_chunk.Dissection_stop_hash_mismatch stop_hash) + in + let* b1 = check_failure_on_same_stop_hash None in + let* b2 = check_failure_on_same_stop_hash stop_chunk.state_hash in + return (b1 && b2)) + + (** Test that we can not produce a dissection modifying the starting + end last point of a section. *) + let test_immutable_start_and_stop_ticks = + let open QCheck2 in + qcheck_make_lwt + ~count + ~name: + "start_chunk.tick and stop_chunk.tick can not change in the dissection" + ~gen: + (let open Gen in + let* number_of_sections = gen_num_sections in + let* ticks = gen_nonfinal_initial_dissection_ticks in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + let* new_dissection, start_chunk, stop_chunk = + gen_dissection ~number_of_sections ~our_states dissection + in + return (new_dissection, start_chunk, stop_chunk, number_of_sections)) + (fun (dissection, start_chunk, stop_chunk, default_number_of_sections) -> + let open Lwt_syntax in + let expected_error dissection = + match (List.hd dissection, List.last_opt dissection) with + | Some Dissection_chunk.{tick = a_tick; _}, Some {tick = b_tick; _} -> + Dissection_chunk.Dissection_edge_ticks_mismatch + { + dissection_start_tick = a_tick; + dissection_stop_tick = b_tick; + chunk_start_tick = start_chunk.tick; + chunk_stop_tick = stop_chunk.tick; + } + | _ -> assert false + in + let modify_tick modify_X dissection = + let invalid_dissection = + modify_X + (fun chunk -> + Dissection_chunk.{chunk with tick = Tick.next chunk.tick}) + dissection + in + let expected_error = expected_error invalid_dissection in + assert_fails_with + ~__LOC__ + (Game.Internal_for_tests.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + invalid_dissection) + expected_error + in + (* We modify the start tick and expect the failure. *) + let* b1 = modify_tick modify_start dissection in + (* We modify the stop tick and expect the failure. *) + let* b2 = modify_tick modify_stop dissection in + return (b1 && b2)) + + (** Test that a valid dissection must have a proper distribution of the + sections. That is, a section should not be geq than half of the + dissected section's distance. *) + let test_badly_distributed_dissection = + let open QCheck2 in + qcheck_make_lwt + ~count + ~name:"dissection must be well distributed" + ~gen: + (let open Gen in + (* The test is not general enough to support all kind of number of + sections. *) + let number_of_sections = + Tezos_protocol_020_PsParisC_parameters.Default_parameters + .constants_mainnet + .sc_rollup + .number_of_sections_in_dissection + in + let* picked_section = 0 -- (number_of_sections - 2) in + let* ticks = 100 -- 1_000 in + let* dissection = gen_initial_dissection ~ticks () in + let* our_states = + gen_our_states (initial_of_dissection dissection) (succ ticks) + in + let* new_dissection, start_chunk, stop_chunk = + gen_dissection ~number_of_sections ~our_states dissection + in + return + ( new_dissection, + start_chunk, + stop_chunk, + number_of_sections, + picked_section )) + (fun ( dissection, + start_chunk, + stop_chunk, + default_number_of_sections, + picked_section ) -> + (* We put a distance of [1] in every section. Then, we put the + distance's left in the [picked_section], it will create + an invalid section. *) + let distance = + Z.succ @@ Tick.distance start_chunk.tick stop_chunk.tick + in + let max_section_length = + Z.(distance - of_int default_number_of_sections) + in + let section_length = Z.one in + + (* Replace the distance of the first [k] sections by [section_length]. + In practice, when [k = 0], we're at the last section of the + dissection. *) + let rec replace_distances tick k = function + | a :: b :: xs -> + let b, tick = + if k = 0 then + let tick = Tick.jump tick max_section_length in + (Dissection_chunk.{b with tick}, tick) + else + let tick = Tick.jump tick section_length in + (Dissection_chunk.{b with tick}, tick) + in + a :: replace_distances tick (k - 1) (b :: xs) + | xs -> xs + in + let invalid_dissection = + replace_distances start_chunk.tick picked_section dissection + in + let dist = Tick.distance start_chunk.tick stop_chunk.tick in + let half_dist = Z.div dist (Z.of_int 2) in + assert_fails_with + ~__LOC__ + (Game.Internal_for_tests.check_dissection + ~default_number_of_sections + ~start_chunk + ~stop_chunk + invalid_dissection) + (Dissection_chunk.Dissection_invalid_distribution half_dist)) + + let tests = + ( "Dissection", + qcheck_wrap + [ + test_valid_gen_dissection; + test_truncated_small_dissection; + test_truncated_large_dissection; + test_immutable_start_chunk; + test_stop_hash_must_change; + test_immutable_start_and_stop_ticks; + test_badly_distributed_dissection; + ] ) +end + +(** {2. ArithPVM utils} *) + +let construct_inbox_proto block list_of_messages contract = + Sc_rollup_helpers.Protocol_inbox_with_ctxt.fill_inbox + block + list_of_messages + contract + +(** Construct the inbox for the protocol side. *) +let construct_inbox_proto block list_of_messages contract = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Lwt_main.run + @@ construct_inbox_proto block list_of_messages contract + +(** Kind of strategy a player can play + + The cheaters will have their own version of inputs. This way, they + can produce valid proofs regarding their inboxes, but discarded by + the protocol. +*) +type strategy = + | Random (** A random player will execute its own random vision of inputs. *) + | Perfect + (** A perfect player, never lies, always win. + GSW 73-9 2014-2015 mindset. *) + | Lazy (** A lazy player will not execute all messages. *) + | Eager (** A eager player will not cheat until a certain point. *) + | Keen (** A keen player will execute more messages. *) + | SOL_hater (** A SOL hater will not execute the SOL input. *) + | EOL_hater (** A EOL hater will not execute the EOL input. *) + | Info_hater (** A Info per level hater will corrupt the infos. *) + | Nostalgic + (** A nostalgic player will execute messages at origination level. *) + +let pp_strategy fmt = function + | Random -> Format.pp_print_string fmt "Random" + | Perfect -> Format.pp_print_string fmt "Perfect" + | Lazy -> Format.pp_print_string fmt "Lazy" + | Eager -> Format.pp_print_string fmt "Eager" + | Keen -> Format.pp_print_string fmt "Keen" + | SOL_hater -> Format.pp_print_string fmt "SOL hater" + | EOL_hater -> Format.pp_print_string fmt "EOL hater" + | Info_hater -> Format.pp_print_string fmt "Info per level hater" + | Nostalgic -> Format.pp_print_string fmt "Nostalgic" + +type player = { + pkh : Signature.Public_key_hash.t; + contract : Contract.t; + strategy : strategy; + game_player : Game.player; +} + +let pp_player ppf {pkh; contract = _; strategy; game_player} = + Format.fprintf + ppf + "pkh: %a@,strategy: %a@,game_player: %s" + Signature.Public_key_hash.pp_short + pkh + pp_strategy + strategy + (if Game.player_equal game_player Alice then "Alice" else "Bob") + +type player_client = { + player : player; + states : (Tick.t * State_hash.t) list; + final_tick : Tick.t; + inbox : Sc_rollup_helpers.Node_inbox.t; + payloads_per_levels : payloads_per_level list; + metadata : Metadata.t; + context : Tezos_context_memory.Context_binary.t; +} + +let pp_player_client ppf + { + player; + states = _; + final_tick; + inbox = _; + payloads_per_levels = _; + metadata = _; + context = _; + } = + Format.fprintf + ppf + "@[player:@,%a@]@,final tick: %a@" + pp_player + player + Tick.pp + final_tick + +module Player_client = struct + (** Construct an inbox based on [list_of_messages] in the player context. *) + let construct_inbox ~inbox list_of_messages = + let history = Sc_rollup.Inbox.History.empty ~capacity:10000L in + let payloads_histories = Payloads_histories.empty in + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Sc_rollup_helpers.Node_inbox.fill_inbox + ~inbox_creation_level:Raw_level.root + {inbox; history; payloads_histories} + list_of_messages + + (** Generate [our_states] for [payloads_per_levels] based on the strategy. + It needs [start_level] and [max_level] in case it will need to generate + new inputs. *) + let gen_our_states ~metadata strategy ~start_level ~max_level + payloads_per_levels = + let open QCheck2.Gen in + let eval_inputs (payloads_per_levels : payloads_per_level list) = + Lwt_main.run + @@ + let open Lwt_result_syntax in + let inputs_per_levels = + List.map (fun {inputs; _} -> inputs) payloads_per_levels + in + let*! r = + Sc_rollup_helpers.Arith_pvm_eval.eval_inputs_from_initial_state + ~metadata + inputs_per_levels + in + Lwt.return @@ WithExceptions.Result.get_ok ~loc:__LOC__ r + in + match strategy with + | Perfect -> + (* The perfect player does not lie, evaluates correctly the inputs. *) + let _state, tick, our_states = eval_inputs payloads_per_levels in + return (tick, our_states, payloads_per_levels) + | Random -> + (* Random player generates its own list of inputs. *) + let* new_payloads_per_levels = + gen_arith_pvm_payloads_for_levels ~start_level ~max_level + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) + | Lazy -> + (* Lazy player removes inputs from [payloads_per_levels]. *) + let n = List.length payloads_per_levels in + let* remove_k = 1 -- n in + let new_inputs = List.take_n (n - remove_k) payloads_per_levels in + let _state, tick, our_states = eval_inputs new_inputs in + return (tick, our_states, new_inputs) + | Eager -> + (* Eager player executes correctly the inbox until a certain point. *) + let* corrupt_at_level = 0 -- (List.length payloads_per_levels - 1) in + let payloads_per_level = + Stdlib.List.nth payloads_per_levels corrupt_at_level + |> fun {payloads; _} -> List.length payloads + in + let* corrupt_at_k = 0 -- payloads_per_level in + let payloads_per_levels = + List.mapi + (fun l payloads_per_level -> + if l = corrupt_at_level then + let inputs = + List.mapi + (fun k input -> + if k = corrupt_at_k then + make_input + ~inbox_level:(Raw_level.of_int32_exn 42l) + ~message_counter:(Z.of_int 42) + (make_external_inbox_message "foo") + else input) + payloads_per_level.inputs + in + {payloads_per_level with inputs} + else payloads_per_level) + payloads_per_levels + in + let _state, tick, our_states = eval_inputs payloads_per_levels in + return (tick, our_states, payloads_per_levels) + | Keen -> + (* Keen player will add more inputs. *) + let* offset = 1 -- 5 in + let* new_payloads_per_levels = + gen_arith_pvm_payloads_for_levels + ~start_level:max_level + ~max_level:(max_level + offset) + in + let new_payloads_per_levels = + payloads_per_levels @ new_payloads_per_levels + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) + | SOL_hater -> + let new_payloads_per_levels = + List.map + (fun payloads_per_level -> + { + payloads_per_level with + inputs = Stdlib.List.tl payloads_per_level.inputs; + }) + payloads_per_levels + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) + | EOL_hater -> + let new_payloads_per_levels = + List.map + (fun payloads_per_level -> + let inputs = + let rev_inputs = List.rev payloads_per_level.inputs in + let without_eol = Stdlib.List.tl rev_inputs in + List.rev without_eol + in + {payloads_per_level with inputs}) + payloads_per_levels + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) + | Info_hater -> + let* corrupt_at_l = 0 -- List.length payloads_per_levels in + let dumb_timestamp = Timestamp.of_seconds 42L in + let dumb_predecessor = Block_hash.zero in + + let new_payloads_per_levels = + List.mapi + (fun l payloads_per_level -> + if l = corrupt_at_l then + { + payloads_per_level with + predecessor_timestamp = dumb_timestamp; + predecessor = dumb_predecessor; + } + else payloads_per_level) + payloads_per_levels + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) + | Nostalgic -> + (* [payloads_per_levels] starts at [orignation_level + 1], the nostalgic + player will execute messages at [origination_level]. *) + let* messages = + small_list (gen_arith_pvm_messages ~gen_size:(pure 0)) + in + let payloads_at_origination = + Sc_rollup_helpers.wrap_messages metadata.origination_level messages + in + let new_payloads_per_levels = + payloads_at_origination :: payloads_per_levels + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) + + (** [gen ~inbox ~rollup ~origination_level ~start_level ~max_level player + payloads_per_levels] generates a {!player_client} based on + its {!player.strategy}. *) + let gen ~inbox ~rollup ~origination_level ~start_level ~max_level player + payloads_per_levels = + let open QCheck2.Gen in + let ctxt : Context_helpers.In_memory.Tree.t = + Arith_pvm_eval.make_empty_context () + in + let metadata = Sc_rollup.Metadata.{address = rollup; origination_level} in + let* tick, our_states, payloads_per_levels = + gen_our_states + ~metadata + player.strategy + ~start_level + ~max_level + payloads_per_levels + in + let inbox = construct_inbox ~inbox payloads_per_levels in + return + { + player; + final_tick = tick; + states = our_states; + inbox; + payloads_per_levels; + metadata; + context = ctxt; + } +end + +(** [create_commitment ~predecessor ~inbox_level ~our_states] creates + a commitment using [our_states] as the vision of ticks. *) +let create_commitment ~predecessor ~inbox_level ~our_states = + let open Lwt_syntax in + let inbox_level = Int32.of_int inbox_level |> Raw_level.of_int32_exn in + let+ compressed_state = + match List.last_opt our_states with + | None -> + (* No tick evaluated. *) + Arith_pvm_eval.initial_hash + | Some (_, state) -> return state + in + + let number_of_ticks = + match our_states with + | [] -> Number_of_ticks.zero + | _ -> + List.length our_states - 1 + |> Int64.of_int |> number_of_ticks_of_int64_exn + in + Commitment.{compressed_state; inbox_level; predecessor; number_of_ticks} + +(** [operation_publish_commitment block rollup lcc inbox_level p1_client] + creates a commitment and stake on it. *) +let operation_publish_commitment ctxt rollup predecessor inbox_level + player_client = + let open Lwt_result_syntax in + let*! commitment = + create_commitment ~predecessor ~inbox_level ~our_states:player_client.states + in + let* op = + Op.sc_rollup_publish ctxt player_client.player.contract rollup commitment + in + return (op, commitment) + +(** [build_proof ~player_client start_tick game] builds a valid proof + regarding the vision [player_client] has. The proof refutes the + [start_tick]. *) +let build_proof ~player_client start_tick (game : Game.t) = + let open Lwt_result_syntax in + (* We start a game on a commitment that starts at [Tick.initial], the fuel + is necessarily [start_tick]. *) + let fuel = tick_to_int_exn start_tick in + let metadata = player_client.metadata in + let inputs_per_levels = + List.map (fun {inputs; _} -> inputs) player_client.payloads_per_levels + in + let*! r = + Arith_pvm_eval.eval_inputs_from_initial_state + ~metadata + ~fuel + inputs_per_levels + in + let state, _, _ = WithExceptions.Result.get_ok ~loc:__LOC__ r in + let pvm_with_context_and_state = + Sc_rollup_helpers.make_pvm_with_context_and_state + (module Arith_pvm) + ~state + ~context:player_client.context + ~reveal:(fun _ -> assert false) + ~inbox:player_client.inbox + (* No messages are added between [game.start_level] and the current level + so we can take the existing inbox of players. Otherwise, we should find the + inbox of [start_level]. *) + () + in + let*! proof = + Sc_rollup.Proof.produce + ~metadata + pvm_with_context_and_state + game.inbox_level + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + in + return (WithExceptions.Result.get_ok ~loc:__LOC__ proof) + +(** [next_move ~number_of_sections ~player_client game] produces + the next move in the refutation game. + + If there is a disputed section where the distance is one tick, it + produces a proof. Otherwise, provides another dissection. +*) +let next_move ~player_client (game : Game.t) = + let open Lwt_result_syntax in + match game.game_state with + | Dissecting {dissection; default_number_of_sections} -> ( + let disputed_sections = + disputed_sections ~our_states:player_client.states dissection + in + assert (Compare.List_length_with.(disputed_sections > 0)) ; + let single_tick_disputed_sections = + single_tick_disputed_sections disputed_sections + in + match single_tick_disputed_sections with + | (start_chunk, _stop_chunk) :: _ -> + let tick = start_chunk.tick in + let+ proof = build_proof ~player_client tick game in + Game.(Move {choice = tick; step = Proof proof}) + | [] -> + (* If we reach this case, there is necessarily a disputed section. *) + let start_chunk, stop_chunk = Stdlib.List.hd disputed_sections in + let dissection = + build_dissection + ~number_of_sections:default_number_of_sections + ~start_chunk + ~stop_chunk + ~our_states:player_client.states + in + return + Game.( + Move {choice = start_chunk.tick; step = Dissection dissection})) + | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> + let tick = agreed_start_chunk.tick in + let+ proof = build_proof ~player_client tick game in + Game.(Move {choice = tick; step = Proof proof}) + +type game_result_for_tests = Defender_wins | Refuter_wins + +(** Play until there is an {!game_result_for_tests}. + + A game result can happen if: + - A valid refutation was provided to the protocol and it succeeded to + win the game. + - A player played an invalid refutation and was rejected by the + protocol. +*) +let play_until_game_result ~refuter_client ~defender_client ~rollup block = + let rec play ~player_turn ~opponent block = + let open Lwt_result_syntax in + let* games = + Context.Sc_rollup.ongoing_games_for_staker + (B block) + rollup + player_turn.player.pkh + in + let game_opt = List.hd games in + let game, _, _ = WithExceptions.Option.get ~loc:__LOC__ game_opt in + let* refutation = next_move ~player_client:player_turn game in + let* incr = Incremental.begin_construction block in + let* operation_refutation = + Op.sc_rollup_refute + (I incr) + player_turn.player.contract + rollup + opponent.player.pkh + refutation + in + let* incr = Incremental.add_operation incr operation_refutation in + match game_status_of_refute_op_result (Incremental.rev_tickets incr) with + | Ongoing -> + let* block = Incremental.finalize_block incr in + play ~player_turn:opponent ~opponent:player_turn block + | Ended (Loser {reason = _; loser}) -> + if loser = Account.pkh_of_contract_exn refuter_client.player.contract + then return Defender_wins + else return Refuter_wins + | Ended Draw -> + QCheck2.Test.fail_reportf "Game ended in a draw, which is unexpected" + in + play ~player_turn:refuter_client ~opponent:defender_client block + +(** Generate two {!player}s with a given strategy. *) +let make_players ~p1_strategy ~contract1 ~p2_strategy ~contract2 = + let pkh1 = Account.pkh_of_contract_exn contract1 in + let pkh2 = Account.pkh_of_contract_exn contract2 in + let ({alice; bob = _} : Game.Index.t) = Game.Index.make pkh1 pkh2 in + let player1, player2 = + if Signature.Public_key_hash.equal alice pkh1 then Game.(Alice, Bob) + else Game.(Bob, Alice) + in + ( { + pkh = pkh1; + contract = contract1; + strategy = p1_strategy; + game_player = player1; + }, + { + pkh = pkh2; + contract = contract2; + strategy = p2_strategy; + game_player = player2; + } ) + +(** [gen_game ~p1_strategy ~p2_strategy] generates a context where a rollup + was originated. + It generates inputs for the rollup, and creates the players' interpretation + of these inputs in a {!player_client} for [p1_strategy] and [p2_strategy]. +*) +let gen_game ~p1_strategy ~p2_strategy = + let open QCheck2.Gen in + (* If there is no good player, we do not care about the result. *) + assert (p1_strategy = Perfect || p2_strategy = Perfect) ; + let block, rollup, inbox, genesis_info, (contract1, contract2, contract3) = + create_ctxt () + in + let p1, p2 = make_players ~p1_strategy ~contract1 ~p2_strategy ~contract2 in + + (* Create a context with a rollup originated. *) + let commitment_period = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_mainnet + .sc_rollup + .commitment_period_in_blocks + in + let origination_level = + Raw_level.to_int32 genesis_info.level |> Int32.to_int + in + let start_level = origination_level + 1 in + let max_level = start_level + commitment_period in + let* payloads_per_levels = + gen_arith_pvm_payloads_for_levels ~start_level ~max_level + in + + let block, payloads_per_levels = + construct_inbox_proto block payloads_per_levels contract3 + in + + let* p1_client = + Player_client.gen + ~inbox + ~origination_level:genesis_info.level + ~start_level + ~max_level + ~rollup + p1 + payloads_per_levels + in + let* p2_client = + Player_client.gen + ~inbox + ~origination_level:genesis_info.level + ~start_level + ~max_level + ~rollup + p2 + payloads_per_levels + in + let* p1_start = bool in + let commitment_level = origination_level + commitment_period in + return + ( block, + rollup, + commitment_level, + genesis_info.commitment_hash, + p1_client, + p2_client, + p1_start, + payloads_per_levels ) + +(** Shrinker is really slow. Deactivating it. *) +let gen_game ~p1_strategy ~p2_strategy = + let open QCheck2.Gen in + make_primitive + ~gen:(fun rand -> generate1 ~rand (gen_game ~p1_strategy ~p2_strategy)) + ~shrink:(fun _ -> Seq.empty) + +(** [prepare_game block rollup lcc commitment_level p1_client p2_client contract + list_of_messages] prepares a context where [p1_client] and [p2_client] + are in conflict for one commitment. *) +let prepare_game ~p1_start block rollup lcc commitment_level p1_client p2_client + = + let open Lwt_result_syntax in + let* p1_op, p1_commitment = + operation_publish_commitment (B block) rollup lcc commitment_level p1_client + in + let* p2_op, p2_commitment = + operation_publish_commitment (B block) rollup lcc commitment_level p2_client + in + let commit_then_commit_and_refute ~defender_op ~refuter_op refuter + refuter_commitment defender defender_commitment = + let refutation = + Sc_rollup.Game.Start + { + player_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated refuter_commitment; + opponent_commitment_hash = + Sc_rollup.Commitment.hash_uncarbonated defender_commitment; + } + in + let* start_game = + Op.sc_rollup_refute + (B block) + refuter.player.contract + rollup + defender.player.pkh + refutation + in + let* refuter_batch = + Op.batch_operations + ~recompute_counters:true + ~source:refuter.player.contract + (B block) + [refuter_op; start_game] + in + let* block = Block.bake ~operations:[defender_op; refuter_batch] block in + return (block, refuter, defender) + in + if p1_start then + commit_then_commit_and_refute + ~defender_op:p2_op + ~refuter_op:p1_op + p1_client + p1_commitment + p2_client + p2_commitment + else + commit_then_commit_and_refute + ~defender_op:p1_op + ~refuter_op:p2_op + p2_client + p2_commitment + p1_client + p1_commitment + +let check_distribution = function + | fst :: snd :: rst -> + let open Dissection_chunk in + let dist = Tick.distance fst.tick snd.tick in + let _, min_len, max_len = + List.fold_left + (fun (previous_tick, min_len, max_len) chunk -> + let dist = Tick.distance previous_tick chunk.tick in + (* We only consider length that are greater or equal than + the snapshot size. The last one may not be as big, if + the PVM was stuck. *) + if Compare.Z.(dist < Sc_rollup.Wasm_2_0_0PVM.ticks_per_snapshot) + then (chunk.tick, min_len, max_len) + else (chunk.tick, Z.min min_len dist, Z.max max_len dist)) + (snd.tick, dist, dist) + rst + in + Z.(max_len - min_len <= Sc_rollup.Wasm_2_0_0PVM.ticks_per_snapshot) + | _ -> true + +let test_wasm_dissection name kind = + qcheck_make_lwt_res + ~count:1_000_000 + ~name + ~print:(fun (start_chunk, stop_chunk) -> + Format.asprintf + "dissection from %a to %a" + Dissection_chunk.pp + start_chunk + Dissection_chunk.pp + stop_chunk) + ~gen:(gen_wasm_pvm_dissection_boundaries kind) + (fun (start_chunk, stop_chunk) -> + let open Lwt_result_syntax in + let+ dissection = + Game_helpers.( + make_dissection + ~state_of_tick:(fun ?start_state:_ _ -> + return_some Sc_rollup.State_hash.zero) + ~state_hash_of_eval_state:Fun.id + ~start_chunk + ~our_stop_chunk:stop_chunk + @@ Wasm.new_dissection + ~start_chunk + ~our_stop_chunk:stop_chunk + ~default_number_of_sections:32) + in + if kind <> `Kernel_run then assert (check_distribution dissection) ; + match + Wasm_2_0_0PVM.Protocol_implementation.check_dissection + ~default_number_of_sections:32 + ~start_chunk + ~stop_chunk:{stop_chunk with state_hash = Some State_hash.zero} + dissection + with + | Ok () -> true + | Error e -> + Format.printf + "dissection %a caused errors %a\n" + Game.pp_dissection + dissection + Environment.Error_monad.pp_trace + e ; + false) + +(** Create a test of [p1_strategy] against [p2_strategy]. One of them + must be a {!Perfect} player, otherwise, we do not care about which + cheater wins. *) +let test_game ?(count = 10) ~p1_strategy ~p2_strategy () = + let name = + Format.asprintf + "%a against %a" + pp_strategy + p1_strategy + pp_strategy + p2_strategy + in + qcheck_make_lwt_res + ~print: + (fun ( _block, + _rollup, + _commitment_level, + _lcc, + p1_client, + p2_client, + p1_start, + _payloads_per_levels ) -> + Format.asprintf + "@[@,@[p1:@,%a@]@,@[p2:@,%a@]@,%s@,@]" + pp_player_client + p1_client + pp_player_client + p2_client + (if p1_start then "p1" else "p2")) + ~count + ~name + ~gen:(gen_game ~p1_strategy ~p2_strategy) + (fun ( block, + rollup, + commitment_level, + lcc, + p1_client, + p2_client, + p1_start, + _list_of_messages ) -> + let open Lwt_result_syntax in + (* Otherwise, there is no conflict. *) + QCheck2.assume + (not + (let p1_head = List.last_opt p1_client.states in + let p2_head = List.last_opt p2_client.states in + Option.equal + (fun (t1, state_hash1) (t2, state_hash2) -> + Tick.equal t1 t2 && State_hash.equal state_hash1 state_hash2) + p1_head + p2_head)) ; + let* block, refuter, defender = + prepare_game + ~p1_start + block + rollup + lcc + commitment_level + p1_client + p2_client + in + let* game_result = + play_until_game_result + ~rollup + ~refuter_client:refuter + ~defender_client:defender + block + in + match game_result with + | Defender_wins -> return (defender.player.strategy = Perfect) + | Refuter_wins -> return (refuter.player.strategy = Perfect)) + +let test_perfect_against_random = + test_game ~p1_strategy:Perfect ~p2_strategy:Random () + +let test_perfect_against_lazy = + test_game ~p1_strategy:Perfect ~p2_strategy:Lazy () + +let test_perfect_against_eager = + test_game ~p1_strategy:Perfect ~p2_strategy:Eager () + +let test_perfect_against_keen = + test_game ~p1_strategy:Perfect ~p2_strategy:Keen () + +let test_perfect_against_sol_hater = + test_game ~p1_strategy:Perfect ~p2_strategy:SOL_hater () + +let test_perfect_against_eol_hater = + test_game ~p1_strategy:Perfect ~p2_strategy:EOL_hater () + +let _test_perfect_against_info_hater = + test_game ~p1_strategy:Perfect ~p2_strategy:Info_hater () + +let test_perfect_against_nostalgic = + test_game ~p1_strategy:Perfect ~p2_strategy:Nostalgic ~count:5 () + +(* This test will behave as a regression test. *) +let test_cut_at_level = + let open QCheck2 in + Test.make + ~name:"cut at level properly cuts" + ~print:(fun (origination_level, commit_inbox_level, input_level) -> + Format.asprintf + "origination_level: %a, commit_inbox_level: %a, input_level: %a" + Raw_level_repr.pp + origination_level + Raw_level_repr.pp + commit_inbox_level + Raw_level_repr.pp + input_level) + Gen.( + let level = + map + (fun i -> Raw_level_repr.of_int32_exn (Int32.of_int i)) + (0 -- 1_000_000) + in + triple level level level) + (fun (origination_level, commit_inbox_level, input_level) -> + let input : Sc_rollup_PVM_sig.input = + Inbox_message + { + inbox_level = input_level; + message_counter = Z.zero; + payload = Sc_rollup_inbox_message_repr.unsafe_of_string "foo"; + } + in + let input_cut = + Sc_rollup_proof_repr.Internal_for_tests.cut_at_level + ~origination_level + ~commit_inbox_level + input + in + let should_be_none = + Raw_level_repr.( + input_level <= origination_level || commit_inbox_level < input_level) + in + match input_cut with + | Some _input -> not should_be_none + | None -> should_be_none) + +let tests = + ( "Refutation", + qcheck_wrap + [ + test_wasm_dissection "dissection is one kernel_run" `Kernel_run; + test_wasm_dissection "dissection shorter than 32 kernel_run" `Short; + test_wasm_dissection "dissection larger than 32 kernel_run" `Large; + test_perfect_against_random; + test_perfect_against_lazy; + test_perfect_against_keen; + test_perfect_against_eager; + test_perfect_against_sol_hater; + test_perfect_against_eol_hater; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6839 + an issue with the generator / assume of this test makes it run for ~15 minutes. + Disactivating until we find the root cause. *) + (* test_perfect_against_info_hater; *) + test_perfect_against_nostalgic; + test_cut_at_level; + ] ) + +(** {2 Entry point} *) + +let tests = [tests; Dissection.tests] + +let () = Alcotest.run ~__FILE__ (Protocol.name ^ ": Refutation_game") tests diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sampler.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sampler.ml new file mode 100644 index 000000000000..b4615e71f700 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sampler.ml @@ -0,0 +1,271 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_sampler.ml + Subject: Operations in Saturation_repr +*) + +open Qcheck2_helpers +open Protocol.Sampler + +(* ------------------------------------------------------------------------- *) +(* Helpers *) + +module Int = struct + include Int + + let hash = Hashtbl.hash +end + +let equal_array elt_eq arr1 arr2 = + Array.length arr1 = Array.length arr2 + && Stdlib.List.for_all2 elt_eq (Array.to_list arr1) (Array.to_list arr2) + +(* Support of a distribution on Z (sorted, with potential duplicates) *) +let support cmp array = + Array.to_seq array |> Seq.map fst |> List.of_seq |> List.sort cmp + |> Array.of_list + +(* Support of a distribution on Z (sorted, without duplicates) *) +let support_uniq cmp array = + Array.to_seq array |> Seq.map fst |> List.of_seq |> List.sort_uniq cmp + |> Array.of_list + +module type Std = sig + type t + + val equal : t -> t -> bool + + val compare : t -> t -> int + + val hash : t -> int +end + +module Helpers = struct + let sample_n_times (total : int) sample = + let rec loop n acc = + if n = 0 then acc + else + let res = sample () in + loop (n - 1) (res :: acc) + in + loop total [] + + let empirical_distribution : + type a. + (module Std with type t = a) -> + nsamples:int -> + (unit -> a) -> + (a * int) array = + fun (module H) ~nsamples sampler -> + let module Table = Hashtbl.Make (H) in + let samples = sample_n_times nsamples sampler in + let table = Table.create 127 in + List.iter + (fun sample -> + let count = Option.value ~default:0 (Table.find table sample) in + Table.replace table sample (count + 1)) + samples ; + let result = Table.to_seq table |> Array.of_seq in + (* check that the support of [result] has no duplicate elements (should + be true since we use [replace]). *) + assert ( + equal_array + H.equal + (support H.compare result) + (support_uniq H.compare result)) ; + result +end + +let normalize : ('a * int) array -> ('a * Q.t) array = + fun empirical -> + let total = + Array.fold_left + (fun acc (_, weight) -> Z.add (Z.of_int weight) acc) + Z.zero + empirical + in + Array.map (fun (n, weight) -> (n, Q.(Z.of_int weight /// total))) empirical + +let pp_dist pp fmtr dist = + let l = Array.to_list dist in + Format.pp_print_list + ~pp_sep:(fun fmtr () -> Format.fprintf fmtr ",") + (fun fmtr (elt, w) -> Format.fprintf fmtr "(%a, %f)" pp elt (Q.to_float w)) + fmtr + l + +let linf (dist : ('a * Q.t) array) pmf = + Array.fold_left (fun acc (n, q) -> Q.(max acc (abs (pmf n - q)))) Q.zero dist + +(* ------------------------------------------------------------------------- *) + +let state = + Random.State.make + [| + 0x1337533D; + 71287309; + 666932349; + 719132214; + 461480042; + 387006837; + 443018964; + 450865457; + 901711679; + 833353016; + 397060904; + |] + +module Make_test (Mass : sig + include Internal_for_tests.SMass + + val to_float : t -> float +end) (S : sig + val sample : int_bound:int -> mass_bound:Mass.t -> int * Mass.t +end) = +struct + let make p = + let module Probability = Internal_for_tests.Make (Mass) in + let measure = List.mapi (fun i p -> (i, p)) p in + let total_mass = List.fold_left Mass.add Mass.zero p in + let state = Probability.create measure in + let sampler = Probability.sample state in + let empirical = + normalize + @@ Helpers.empirical_distribution + (module Int) + ~nsamples:5_000_000 + (fun () -> sampler S.sample) + in + (* We need to rescale the empirical to match that the total mass is not necessarily one. *) + let empirical = + let rescaling = Q.of_float (Mass.to_float total_mass) in + Array.map (fun (x, q) -> (x, Q.mul q rescaling)) empirical + in + (* map the mass to Q to better measure the error *) + let truth = + let array = + measure |> List.to_seq + |> Seq.map (fun (_, mass) -> Q.of_float (Mass.to_float mass)) + |> Array.of_seq + in + fun i -> array.(i) + in + let error = linf empirical truth in + let max_error = 0.001 *. Mass.to_float total_mass in + if not Q.(error < Q.of_float max_error) then + QCheck2.Test.fail_reportf + "didn't converge (%f)@.%a" + (Q.to_float error) + (pp_dist Format.pp_print_int) + empirical ; + true +end + +(* Testing the alias sampler with float-valued measures *) + +module Probability_mass_float : Internal_for_tests.SMass with type t = float = +struct + type t = float + + let encoding = Data_encoding.float + + let zero = 0.0 + + let of_int = float_of_int + + let mul = ( *. ) + + let add = ( +. ) + + let sub = ( -. ) + + let ( = ) = Float.equal + + let ( <= ) (x : t) (y : t) = x <= y + + let ( < ) (x : t) (y : t) = x < y +end + +module Test_float = + Make_test + (struct + include Probability_mass_float + + let to_float x = x + end) + (struct + let sample ~int_bound ~mass_bound = + (Random.State.int state int_bound, Random.State.float state mass_bound) + end) + +(* Testing the alias sampler with Z-valued measures *) + +module Probability_mass_z : Internal_for_tests.SMass with type t = Z.t = struct + let encoding = Data_encoding.z + + include Z + include Z.Compare +end + +module Test_z = + Make_test + (struct + include Probability_mass_z + + let to_float = Z.to_float + end) + (struct + let sample ~int_bound ~mass_bound = + ( Random.State.int state int_bound, + Z.of_int64 (Random.State.int64 state (Z.to_int64 mass_bound)) ) + end) + +let qcheck_wrap = qcheck_wrap ~rand:state + +let alias_float_test = + QCheck2.Test.make + ~count:100 + ~name:"alias_float" + QCheck2.Gen.(list_size (int_range 1 20) pfloat) + Test_float.make + +let alias_z_test = + QCheck2.Test.make + ~count:100 + ~name:"alias_z" + QCheck2.Gen.( + list_size (int_range 1 20) (nat >>= fun n -> return (Z.of_int n))) + Test_z.make + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [("sampling", qcheck_wrap [alias_float_test; alias_z_test])] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_encoding.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_encoding.ml new file mode 100644 index 000000000000..ea9e8648dd2b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_encoding.ml @@ -0,0 +1,348 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_sc_rollup_encoding.ml + Subject: SC rollup encoding +*) + +open Protocol +open QCheck2 +open Qcheck2_helpers + +(** {2 Generators} *) + +let gen_state_hash = + let open Gen in + let* bytes = bytes_fixed_gen Sc_rollup_repr.State_hash.size in + return (Sc_rollup_repr.State_hash.of_bytes_exn bytes) + +let gen_inbox_level = + let open Gen in + let* level = map Int32.abs int32 in + (* There is no inbox for level [0l]. *) + let level = if level = 0l then 1l else level in + return (Raw_level_repr.of_int32_exn level) + +let gen_start_level = + let open Gen in + let* level = map Int32.abs int32 in + let start_level = Raw_level_repr.of_int32_exn level in + return start_level + +let gen_commitment_hash = + let open Gen in + let* bytes = bytes_fixed_gen Sc_rollup_commitment_repr.Hash.size in + return (Sc_rollup_commitment_repr.Hash.of_bytes_exn bytes) + +let gen_number_of_ticks = + let open Gen in + let open Sc_rollup_repr.Number_of_ticks in + let* v = int64_range_gen min_value max_value in + return (WithExceptions.Option.get ~loc:__LOC__ (of_value v)) + +let gen_commitment = + let open Gen in + let* compressed_state = gen_state_hash + and* inbox_level = gen_inbox_level + and* predecessor = gen_commitment_hash + and* number_of_ticks = gen_number_of_ticks in + return + Sc_rollup_commitment_repr. + {compressed_state; inbox_level; predecessor; number_of_ticks} + +let gen_versioned_commitment = + let open Gen in + let* commitment = gen_commitment in + return (Sc_rollup_commitment_repr.to_versioned commitment) + +let gen_player = Gen.oneofl Sc_rollup_game_repr.[Alice; Bob] + +let gen_inbox level = + let open Gen in + let gen_msg = small_string ~gen:printable in + let* hd = gen_msg in + let* tail = small_list gen_msg in + let payloads = hd :: tail in + let witness_and_inbox = + let open Result_wrap_syntax in + let inbox = Sc_rollup_helpers.dumb_init_repr level in + wrap + @@ + let witness = Sc_rollup_inbox_repr.init_witness_no_history in + let witness = + Sc_rollup_inbox_repr.add_info_per_level_no_history + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + witness + in + let* input_messages = + List.map_e + (fun msg -> Sc_rollup_inbox_message_repr.(serialize (External msg))) + payloads + in + let* witness = + Sc_rollup_inbox_repr.add_messages_no_history input_messages witness + in + return (Sc_rollup_inbox_repr.finalize_inbox_level_no_history inbox witness) + in + return + @@ (witness_and_inbox |> function + | Ok v -> v + | Error e -> + Stdlib.failwith (Format.asprintf "%a" Error_monad.pp_print_trace e)) + +module Index = Dal_slot_index_repr + +let pack_slots_headers_by_level list = + let module ML = Map.Make (Raw_level_repr) in + let module SSH = Set.Make (struct + include Dal_slot_repr.Header + + let compare a b = Dal_slot_index_repr.compare a.id.index b.id.index + end) in + let map = + List.fold_left + (fun map (Dal_slot_repr.Header.{id = {published_level; _}; _} as sh) -> + let l = + ML.find published_level map |> Option.value ~default:SSH.empty + in + ML.add published_level (SSH.add sh l) map) + ML.empty + list + in + match ML.max_binding_opt map with + | None -> [] (* map is empty *) + | Some (max_level, _) -> + let rec loop counter map = + if Raw_level_repr.(counter >= max_level) then map + else + let counter = Raw_level_repr.succ counter in + let map = + if ML.mem counter map then map else ML.add counter SSH.empty map + in + loop counter map + in + loop Raw_level_repr.root map + |> ML.bindings + |> List.map (fun (k, ssh) -> (k, SSH.elements ssh)) + +let gen_dal_slots_history () = + let open Gen in + let open Dal_slot_repr in + let constants : Alpha_context.Constants.Parametric.t = + Tezos_protocol_020_PsParisC_parameters.Default_parameters.constants_test + in + let number_of_slots = constants.dal.number_of_slots in + (* Generate a list of (level * confirmed slot ID). *) + let* list = small_list (pair small_nat small_nat) in + let list = + List.rev_map + (fun (level, slot_index) -> + let published_level = + Raw_level_repr.( + (* use succ to avoid having a published_level = 0, as it's the + genesis cell's level in the skip list. *) + succ @@ try of_int32_exn (Int32.of_int level) with _ -> root) + in + let index = + Index.of_int_opt ~number_of_slots slot_index + |> Option.value ~default:Index.zero + in + Header.{id = {published_level; index}; commitment = Commitment.zero}) + list + in + let rec loop history = function + | [] -> return history + | (level, slot_headers) :: llist -> ( + let slot_headers = + (* Sort the list in the right ordering before adding slots to slots_history. *) + List.sort_uniq + (fun {Header.id = a; _} {id = b; _} -> + let c = + Raw_level_repr.compare a.published_level b.published_level + in + if c <> 0 then c else Index.compare a.index b.index) + slot_headers + in + History.( + add_confirmed_slot_headers_no_cache + ~number_of_slots + history + level + slot_headers) + |> function + | Ok history -> loop history llist + | Error e -> + return + @@ Stdlib.failwith + (Format.asprintf "%a" Error_monad.pp_print_trace + @@ Environment.wrap_tztrace e)) + in + pack_slots_headers_by_level list |> loop History.genesis + +let gen_inbox_history_proof inbox_level = + let open Gen in + let* inbox = gen_inbox inbox_level in + return (Sc_rollup_inbox_repr.take_snapshot inbox) + +let gen_tick = + let open Gen in + let* t = small_nat in + match Sc_rollup_tick_repr.of_int t with + | None -> assert false + | Some r -> return r + +let gen_dissection_chunk = + let open Gen in + let* state_hash = opt gen_state_hash in + let+ tick = gen_tick in + Sc_rollup_dissection_chunk_repr.{state_hash; tick} + +let gen_dissection = + let open Gen in + small_list gen_dissection_chunk + +let gen_game_state = + let open Sc_rollup_game_repr in + let open Gen in + let gen_dissecting = + let* dissection = gen_dissection in + let+ default_number_of_sections = int_range 4 100 in + Dissecting {dissection; default_number_of_sections} + in + let gen_final_move = + let* agreed_start_chunk = gen_dissection_chunk in + let+ refuted_stop_chunk = gen_dissection_chunk in + Final_move {agreed_start_chunk; refuted_stop_chunk} + in + oneof [gen_dissecting; gen_final_move] + +let gen_game = + let open Gen in + let* turn = gen_player in + let* inbox_level = gen_inbox_level in + let* start_level = gen_start_level in + let* inbox_snapshot = gen_inbox_history_proof inbox_level in + let* dal_snapshot = gen_dal_slots_history () in + let* game_state = gen_game_state in + return + Sc_rollup_game_repr. + {turn; dal_snapshot; inbox_snapshot; start_level; inbox_level; game_state} + +let gen_conflict = + let open Gen in + let other = Sc_rollup_repr.Staker.zero in + let* their_commitment = gen_commitment in + let* our_commitment = gen_commitment in + let* parent_commitment = gen_commitment_hash in + return + Sc_rollup_refutation_storage. + {other; their_commitment; our_commitment; parent_commitment} + +let gen_rollup = + let open QCheck2.Gen in + let* bytes = bytes_fixed_gen Sc_rollup_repr.Address.size in + return (Sc_rollup_repr.Address.hash_bytes [bytes]) + +let gen_inbox_message = + let open Gen in + let open Sc_rollup_inbox_message_repr in + let gen_external = + let+ s = small_string ~gen:printable in + External s + in + let gen_sol = return (Internal Start_of_level) in + let gen_eol = return (Internal End_of_level) in + let gen_deposit = + (* We won't test the encoding of these values. It's out of scope. *) + let payload = Script_repr.unit in + let sender = Contract_hash.zero in + let source = Signature.Public_key_hash.zero in + (* But the encoding of the rollup's address is our problem. *) + let+ destination = gen_rollup in + Internal (Transfer {payload; sender; source; destination}) + in + oneof [gen_external; gen_sol; gen_eol; gen_deposit] + +(** {2 Tests} *) + +let test_commitment = + test_roundtrip + ~count:1_000 + ~title:"Sc_rollup_commitment.t" + ~gen:gen_commitment + ~eq:( = ) + Sc_rollup_commitment_repr.encoding + +let test_versioned_commitment = + test_roundtrip + ~count:1_000 + ~title:"Sc_rollup_commitment.versioned" + ~gen:gen_versioned_commitment + ~eq:( = ) + Sc_rollup_commitment_repr.versioned_encoding + +let test_game = + test_roundtrip + ~count:1_000 + ~title:"Sc_rollup_game.t" + ~gen:gen_game + ~eq:Sc_rollup_game_repr.equal + Sc_rollup_game_repr.encoding + +let test_conflict = + test_roundtrip + ~count:1_000 + ~title:"Sc_rollup_refutation_storage.conflict" + ~gen:gen_conflict + ~eq:( = ) + Sc_rollup_refutation_storage.conflict_encoding + +let test_inbox_message = + test_roundtrip + ~count:1_000 + ~title:"Sc_rollup_inbox_message_repr.t" + ~gen:gen_inbox_message + ~eq:( = ) + Sc_rollup_inbox_message_repr.encoding + +let tests = + [ + test_commitment; + test_versioned_commitment; + test_game; + test_conflict; + test_inbox_message; + ] + +let () = + Alcotest.run + ~__FILE__ + (Protocol.name ^ ": SC rollup encoding") + [(": roundtrip", qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_inbox.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_inbox.ml new file mode 100644 index 000000000000..8c745d74cc25 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_inbox.ml @@ -0,0 +1,77 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_sc_rollup_inbox.ml + Subject: Smart rollup inbox +*) + +open Protocol +open Qcheck2_helpers + +let gen_block_hash = + let open QCheck2.Gen in + let gen = + let+ b = bytes_fixed_gen Block_hash.size in + Block_hash.of_bytes_exn b + in + (* This is not beautiful, but there is currently no other way to + remove the shrinker. *) + make_primitive + ~gen:(fun rand -> generate1 ~rand gen) + ~shrink:(fun _ -> Seq.empty) + +let gen_time = + let open QCheck2.Gen in + let+ s = int64 in + Time.Protocol.of_seconds s + +let gen_add_info_per_level = + let open QCheck2.Gen in + let* predecessor_timestamp = gen_time in + let* predecessor = gen_block_hash in + return (predecessor_timestamp, predecessor) + +let test_add_info_per_level = + QCheck2.Test.make + ~count:10_000 + ~name:"test_add_info_per_level" + gen_add_info_per_level + @@ fun (predecessor_timestamp, predecessor) -> + (* Test that we can indeed serialize the [Info_per_level] message for these + inputs *) + let _bytes = + Sc_rollup_inbox_message_repr.info_per_level_serialized + ~predecessor_timestamp + ~predecessor + in + true + +let tests = [test_add_info_per_level] + +let () = Alcotest.run ~__FILE__ Protocol.name [("safety", qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_tick_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_tick_repr.ml new file mode 100644 index 000000000000..0da6e3b1f84a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_sc_rollup_tick_repr.ml @@ -0,0 +1,110 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_sc_rollup_tick_repr.ml + Subject: Operations in Tick_repr +*) + +open Protocol.Alpha_context.Sc_rollup +open QCheck2 + +(** A generator for ticks *) +let tick = + let open Gen in + let+ n = nat in + Option.value ~default:Tick.initial (Tick.of_int n) + +(** For all x, x = initial \/ x > initial. *) +let test_initial_is_bottom = + Test.make ~name:"x = initial \\/ x > initial" tick @@ fun x -> + Tick.(x = initial || x > initial) + +(** For all x, next x > x. *) +let test_next_is_monotonic = + Test.make ~name:"next x > x" tick @@ fun x -> Tick.(next x > x) + +(** Distance from self to self is zero *) +let test_distance_from_self = + Test.make ~name:"distance from x to x is 0" tick (fun x -> + Z.(equal (Tick.distance x x) zero)) + +(** Distance from non-self is non-zero. *) +let test_distance_from_non_self = + Test.make + ~name:"distance from non-self is non-zero" + (Gen.pair tick tick) + (fun (x, y) -> + let dist = Tick.distance x y in + if x = y then Compare.Z.(dist = Z.zero) else Compare.Z.(dist <> Z.zero)) + +(** Distance is symmetric . *) +let test_distance_symmetry = + Test.make + ~name:"distance is a distance (symmetry)" + (Gen.pair tick tick) + (fun (x, y) -> Z.(equal (Tick.distance x y) (Tick.distance y x))) + +(** Distance satisfies triangular inequality. *) +let test_distance_triangle_inequality = + Test.make + ~name:"distance is a distance (triangle inequality)" + (Gen.triple tick tick tick) + (fun (x, y, z) -> + Tick.(Z.(geq (distance x y + distance y z) (distance x z)))) + +(** Test that [of_int x = Some t] iff [x >= 0] *) +let test_of_int = + Test.make ~name:"of_int only accepts natural numbers" Gen.int (fun x -> + match Tick.of_int x with None -> x < 0 | Some _ -> x >= 0) + +(** Test [of_int o to_int = identity]. *) +let test_of_int_to_int = + Test.make ~name:"to_int o of_int = identity" tick @@ fun x -> + Tick.( + match to_int x with + | None -> (* by the tick generator definition. *) assert false + | Some i -> ( match of_int i with Some y -> y = x | None -> false)) + +let tests = + [ + test_next_is_monotonic; + test_initial_is_bottom; + test_distance_from_self; + test_distance_from_non_self; + test_distance_symmetry; + test_distance_triangle_inequality; + test_of_int; + test_of_int_to_int; + ] + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [("Tick_repr", Qcheck2_helpers.qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_comparison.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_comparison.ml new file mode 100644 index 000000000000..3bed962ca621 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_comparison.ml @@ -0,0 +1,353 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Script_comparison + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_script_comparison.ml + Subject: PBT of the Script_comparable.compare_comparable function. +*) + +open Protocol +open Alpha_context +open Script_typed_ir +open Qcheck2_helpers + +(* Reference implementation *) + +let normalize_compare c = + let open Compare.Int in + if c > 0 then 1 else if c < 0 then -1 else 0 + +(* This reference implementation of the Michelson comparison function is a + simplified version of the Script_ir_translator.compare_comparable function + that was used in the Florence protocol, before a refactoring broke it in + Granada. *) +let rec reference_compare_comparable : type a. a comparable_ty -> a -> a -> int + = + fun ty x y -> + match (ty, x, y) with + | Unit_t, (), () -> 0 + | Never_t, _, _ -> . + | Signature_t, x, y -> normalize_compare @@ Script_signature.compare x y + | String_t, x, y -> normalize_compare @@ Script_string.compare x y + | Bool_t, x, y -> normalize_compare @@ Compare.Bool.compare x y + | Mutez_t, x, y -> normalize_compare @@ Tez.compare x y + | Key_hash_t, x, y -> + normalize_compare @@ Signature.Public_key_hash.compare x y + | Key_t, x, y -> normalize_compare @@ Signature.Public_key.compare x y + | Int_t, x, y -> normalize_compare @@ Script_int.compare x y + | Nat_t, x, y -> normalize_compare @@ Script_int.compare x y + | Timestamp_t, x, y -> normalize_compare @@ Script_timestamp.compare x y + | Address_t, x, y -> + normalize_compare @@ Script_comparable.compare_address x y + | Bytes_t, x, y -> normalize_compare @@ Compare.Bytes.compare x y + | Chain_id_t, x, y -> normalize_compare @@ Script_chain_id.compare x y + | Pair_t (tl, tr, _, YesYes), (lx, rx), (ly, ry) -> + let cl = reference_compare_comparable tl lx ly in + if Compare.Int.(cl = 0) then reference_compare_comparable tr rx ry else cl + | Or_t (tl, _, _, YesYes), L x, L y -> reference_compare_comparable tl x y + | Or_t _, L _, R _ -> -1 + | Or_t _, R _, L _ -> 1 + | Or_t (_, tr, _, YesYes), R x, R y -> reference_compare_comparable tr x y + | Option_t _, None, None -> 0 + | Option_t _, None, Some _ -> -1 + | Option_t _, Some _, None -> 1 + | Option_t (t, _, Yes), Some x, Some y -> reference_compare_comparable t x y + +(* Generation of one to three values of the same comparable type. *) + +type ex_comparable_data = + | Ex_comparable_data : 'a comparable_ty * 'a -> ex_comparable_data + +type ex_comparable_data_2 = + | Ex_comparable_data_2 : 'a comparable_ty * 'a * 'a -> ex_comparable_data_2 + +type ex_comparable_data_3 = + | Ex_comparable_data_3 : + 'a comparable_ty * 'a * 'a * 'a + -> ex_comparable_data_3 + +(* We use the Michelson samplers from lib_benchmark and turn them into QCheck2 + generators *) +module Parameters = struct + let atom_size_range : Tezos_benchmark.Base_samplers.range = + {min = 0; max = 10} + + let other_size : Tezos_benchmark.Base_samplers.range = {min = 0; max = 100} + + let parameters : Michelson_samplers.parameters = + { + base_parameters = + { + int_size = atom_size_range; + string_size = atom_size_range; + bytes_size = atom_size_range; + }; + list_size = other_size; + set_size = other_size; + map_size = other_size; + } +end + +module Crypto_samplers = +Tezos_benchmark.Crypto_samplers.Make_finite_key_pool (struct + let size = 1000 + + let algo = `Default +end) + +module Samplers : Michelson_samplers.S = + Michelson_samplers.Make (Parameters) (Crypto_samplers) + +let ex_comparable_data_sampler : + ex_comparable_data Tezos_benchmark.Base_samplers.sampler = + fun random_state -> + let size = + Tezos_benchmark.Base_samplers.sample_in_interval + ~range:{min = 1; max = 20} + random_state + in + let (Ex_comparable_ty ty) = + Samplers.Random_type.m_comparable_type ~size random_state + in + let x = Samplers.Random_value.comparable ty random_state in + Ex_comparable_data (ty, x) + +let ex_comparable_data_2_sampler : + ex_comparable_data_2 Tezos_benchmark.Base_samplers.sampler = + fun random_state -> + let size = + Tezos_benchmark.Base_samplers.sample_in_interval + ~range:{min = 1; max = 20} + random_state + in + let (Ex_comparable_ty ty) = + Samplers.Random_type.m_comparable_type ~size random_state + in + let x = Samplers.Random_value.comparable ty random_state in + let y = Samplers.Random_value.comparable ty random_state in + Ex_comparable_data_2 (ty, x, y) + +let ex_comparable_data_3_sampler : + ex_comparable_data_3 Tezos_benchmark.Base_samplers.sampler = + fun random_state -> + let size = + Tezos_benchmark.Base_samplers.sample_in_interval + ~range:{min = 1; max = 20} + random_state + in + let (Ex_comparable_ty ty) = + Samplers.Random_type.m_comparable_type ~size random_state + in + let x = Samplers.Random_value.comparable ty random_state in + let y = Samplers.Random_value.comparable ty random_state in + let z = Samplers.Random_value.comparable ty random_state in + Ex_comparable_data_3 (ty, x, y, z) + +let comparable_data_generator = + QCheck2.Gen.make_primitive ~gen:ex_comparable_data_sampler ~shrink:(fun _ -> + Seq.empty) + +let comparable_data_2_generator = + QCheck2.Gen.make_primitive ~gen:ex_comparable_data_2_sampler ~shrink:(fun _ -> + Seq.empty) + +let comparable_data_3_generator = + QCheck2.Gen.make_primitive ~gen:ex_comparable_data_3_sampler ~shrink:(fun _ -> + Seq.empty) + +(* We need a context because packing (used in one of the tests) and unparsing + (used for pretty-printing error messages) Michelson data are carbonated + operations. But since we don't care about gas consumption here we use the + same value of type context everywhere instead of threading it through the + error monad. *) + +let assert_ok = function Ok x -> x | Error _ -> assert false + +let assert_return x = assert_ok (Lwt_main.run x) + +let ctxt = + assert_return + (let open Lwt_result_syntax in + let* b, _cs = Context.init3 () in + let* v = Incremental.begin_construction b in + return (Incremental.alpha_ctxt v)) + +let unparse_comparable_ty ty = + Micheline.strip_locations + (fst (assert_ok Script_ir_unparser.(unparse_ty ~loc:() ctxt ty))) + +let unparse_comparable_data ty x = + fst (assert_return Script_ir_translator.(unparse_data ctxt Readable ty x)) + +let pack_comparable_data ty x = + fst (assert_return Script_ir_translator.(pack_data ctxt ty x)) + +let unpack_comparable_data ty bytes = + fst (assert_return (Script_interpreter_defs.unpack ctxt ~ty ~bytes)) + +let pp_comparable_ty fmt ty = + Michelson_v1_printer.print_expr fmt (unparse_comparable_ty ty) + +let pp_comparable_data ty fmt x = + Michelson_v1_printer.print_expr fmt (unparse_comparable_data ty x) + +let pp ty x y pp_c fmt c = + Format.fprintf + fmt + "Compare(ty=%a, %a, %a) = %a" + pp_comparable_ty + ty + (pp_comparable_data ty) + x + (pp_comparable_data ty) + y + pp_c + c + +let compare_through_pack ty x y = + Bytes.compare (pack_comparable_data ty x) (pack_comparable_data ty y) = 0 + +let qcheck_compare_comparable ~expected ty x y = + qcheck_eq + ~pp:(pp ty x y Format.pp_print_int) + expected + (Script_comparable.compare_comparable ty x y) + +let qcheck_compare_comparable_eq ~expected ty x y = + qcheck_eq + ~pp:(pp ty x y Format.pp_print_bool) + expected + (Script_comparable.compare_comparable ty x y = 0) + +(* Test. + * Tests that compare_comparable returns the same values than the reference + * implementation. + *) +let test_compatible_with_reference = + QCheck2.Test.make + ~name:"compatible_with_reference" + comparable_data_2_generator + (fun (Ex_comparable_data_2 (ty, x, y)) -> + qcheck_compare_comparable + ~expected:(reference_compare_comparable ty x y) + ty + x + y) + +(* Test. + * Tests that compare_comparable returns 0 iff packing then comparing the + * resulting bytes returns 0. + *) +let test_compatible_with_packing = + QCheck2.Test.make + ~name:"compatible_with_packing" + comparable_data_2_generator + (fun (Ex_comparable_data_2 (ty, x, y)) -> + qcheck_compare_comparable_eq + ~expected:(compare_through_pack ty x y) + ty + x + y) + +(* Test. + * Tests that compare_comparable is reflexive. + *) +let test_reflexivity = + QCheck2.Test.make + ~name:"reflexivity" + comparable_data_generator + (fun (Ex_comparable_data (ty, x)) -> + qcheck_compare_comparable ~expected:0 ty x x) + +(* Test. + * Tests that compare_comparable is symmetric. + *) +let test_symmetry = + QCheck2.Test.make + ~name:"symmetry" + comparable_data_2_generator + (fun (Ex_comparable_data_2 (ty, x, y)) -> + qcheck_compare_comparable + ~expected:(-Script_comparable.compare_comparable ty x y) + ty + y + x) + +(* Test. + * Tests that compare_comparable is transitive. + *) +let test_transitivity = + QCheck2.Test.make + ~name:"transitivity" + comparable_data_3_generator + (fun (Ex_comparable_data_3 (ty, x, y, z)) -> + let cxy = Script_comparable.compare_comparable ty x y in + let cyz = Script_comparable.compare_comparable ty y z in + match (cxy, cyz) with + | 0, n | n, 0 -> qcheck_compare_comparable ~expected:n ty x z + | -1, -1 -> qcheck_compare_comparable ~expected:(-1) ty x z + | 1, 1 -> qcheck_compare_comparable ~expected:1 ty x z + | _ -> QCheck2.assume_fail ()) + +(* Test. + * Tests the round-trip property for PACK and UNPACK (modulo compare_comparable). + *) +let test_pack_unpack = + QCheck2.Test.make + ~count:100_000 + (* We run this test on many more cases than the default (100) because this + is a very important property. Packing and then unpacking happens each + time data is sent from a contract to another and also each time storage + is saved at the end of a smart contract call and restored at the next + call of the same contract. Also, injectivity of packing (which is a + direct consequence of this) is an important property for big maps + (because the keys are packed and then hashed). *) + ~name:"pack_unpack" + comparable_data_generator + (fun (Ex_comparable_data (ty, x)) -> + let oty = + match option_t (-1) ty with Ok ty -> ty | Error _ -> assert false + in + qcheck_eq + ~cmp:(Script_comparable.compare_comparable oty) + ~pp:(pp_comparable_data oty) + (Some x) + (unpack_comparable_data ty (pack_comparable_data ty x))) + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [ + ("compatible_with_reference", qcheck_wrap [test_compatible_with_reference]); + ("compatible_with_packing", qcheck_wrap [test_compatible_with_packing]); + ("reflexivity", qcheck_wrap [test_reflexivity]); + ("symmetry", qcheck_wrap [test_symmetry]); + ("transitivity", qcheck_wrap [test_transitivity]); + ("pack_unpack", qcheck_wrap [test_pack_unpack]); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_roundtrip.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_roundtrip.ml new file mode 100644 index 000000000000..a53073f575ad --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_script_roundtrip.ml @@ -0,0 +1,283 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Michelson translator and ir_size + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_script_roundtrip.ml + Subject: PBT of the roundrip property of Michelson storages. +*) + +open Protocol +open Alpha_context +open Script_typed_ir +open Qcheck2_helpers + +(* Generation of a type and value of that type. *) + +type ex_data = Ex_data : ('a, _) ty * 'a -> ex_data + +(* We use the Michelson samplers from lib_benchmark. They are later turned into + QCheck2 generators (see [data_generator]). *) +module Parameters = struct + let atom_size_range : Tezos_benchmark.Base_samplers.range = + {min = 0; max = 10} + + let other_size : Tezos_benchmark.Base_samplers.range = {min = 0; max = 2} + (* Anything larger than max=2 leads to rare very large values which + cannot be packed within Data_encoding limits. *) + + let parameters : Michelson_samplers.parameters = + { + base_parameters = + { + int_size = atom_size_range; + string_size = atom_size_range; + bytes_size = atom_size_range; + }; + list_size = other_size; + set_size = other_size; + map_size = other_size; + } +end + +module Crypto_samplers = +Tezos_benchmark.Crypto_samplers.Make_finite_key_pool (struct + let size = 1000 + + let algo = `Default +end) + +module Samplers : Michelson_samplers.S = + Michelson_samplers.Make (Parameters) (Crypto_samplers) + +let assert_some = function Some x -> x | None -> assert false + +let assert_ok = function Ok x -> x | Error _ -> assert false + +let assert_return x = assert_ok (Lwt_main.run x) + +(* We need a context because we test carbonated functions. But since + we don't care about gas consumption here we use the same value of + type context everywhere instead of threading it through the error + monad. *) + +let ctxt = + assert_return + (let open Lwt_result_syntax in + let* b, _cs = Context.init3 () in + let* v = Incremental.begin_construction b in + return (Incremental.alpha_ctxt v)) + +let ex_data_sampler : ex_data Tezos_benchmark.Base_samplers.sampler = + fun random_state -> + let size = + Tezos_benchmark.Base_samplers.sample_in_interval + ~range:{min = 1; max = 20} + random_state + in + let blacklist = function + | `TUnit | `TInt | `TNat | `TSignature | `TString | `TBytes | `TMutez + | `TKey_hash | `TKey | `TTimestamp | `TAddress | `TBool | `TPair | `TOr + | `TOption | `TList | `TSet | `TMap | `TChain_id | `TBls12_381_g1 + | `TBls12_381_g2 | `TBls12_381_fr | `TBig_map | `TTicket -> + false + | `TOperation (* Forbidden in storage *) + | `TContract (* Forbidden in storage *) + | `TSapling_transaction (* Not yet supported *) + | `TSapling_transaction_deprecated (* Not yet supported *) + | `TSapling_state (* Not yet supported *) + | `TLambda (* Not yet supported *) -> + true + in + let (Ex_ty ty) = + Samplers.Random_type.m_type ~size ~blacklist () random_state + in + let x = Samplers.Random_value.value ty random_state in + Ex_data (ty, x) + +let big_map_data_sampler : ex_data Tezos_benchmark.Base_samplers.sampler = + fun random_state -> + let size = + Tezos_benchmark.Base_samplers.sample_in_interval + ~range:{min = 1; max = 20} + random_state + in + let (Ex_comparable_ty kty) = + Samplers.Random_type.m_comparable_type ~size random_state + in + let (Ex_comparable_ty vty) = + Samplers.Random_type.m_comparable_type ~size random_state + in + let ty = assert_ok @@ big_map_t 0 kty vty in + let x = Samplers.Random_value.value ty random_state in + Ex_data (ty, x) + +(* There is no particular reason not to define proper shrinkers here, + we just haven't needed them yet. *) +let data_generator = + QCheck2.Gen.make_primitive ~gen:ex_data_sampler ~shrink:(fun _ -> Seq.empty) + +let big_map_data_generator = + QCheck2.Gen.make_primitive ~gen:ex_data_sampler ~shrink:(fun _ -> Seq.empty) + +let dummy_code unparsed_ty = + let open Micheline in + let open Michelson_v1_primitives in + strip_locations + @@ Seq + ( (), + [ + Prim ((), K_parameter, [Prim ((), T_never, [], [])], []); + Prim ((), K_storage, [unparsed_ty], []); + Prim + ( (), + K_code, + [ + Seq ((), [Prim ((), I_CAR, [], []); Prim ((), I_NEVER, [], [])]); + ], + [] ); + ] ) + +let roundtrip (ty : ('a, 'ac) ty) (x : 'a) lazy_storage_diff ctxt = + let open Lwt_result_syntax in + let dummy_address = Contract_hash.zero in + let* storage, ctxt = Script_ir_translator.unparse_data ctxt Optimized ty x in + let*? storage_type, ctxt = Script_ir_unparser.unparse_ty ~loc:() ctxt ty in + let storage = Script.lazy_expr storage in + let* code, ctxt = + Script_ir_translator.unparse_code + ctxt + Optimized + (Micheline.root (dummy_code storage_type)) + in + let code = Script.lazy_expr code in + let script = {Script.code; storage} in + let* ctxt = + Contract.raw_originate + ctxt + ~prepaid_bootstrap_storage:false + dummy_address + ~script:(script, lazy_storage_diff) + in + let* ctxt, script = Contract.get_script ctxt dummy_address in + let script = assert_some script in + let elab_conf = Script_ir_translator_config.make ~legacy:true () in + let allow_forged_tickets_in_storage = true in + let allow_forged_lazy_storage_id_in_storage = true in + let* Ex_script (Script {storage_type; storage; _}), ctxt = + Script_ir_translator.parse_script + ctxt + script + ~elab_conf + ~allow_forged_tickets_in_storage + ~allow_forged_lazy_storage_id_in_storage + in + let*? eq, _ctxt = + Gas_monad.run ctxt + @@ Script_ir_translator.ty_eq ~error_details:(Informative 0) ty storage_type + in + let safe_cast (type a ac b bc) (y : b) + (eq : ((a, ac) ty, (b, bc) ty) Script_ir_translator.eq) : a = + let Eq = eq in + y + in + let*? eq in + return @@ safe_cast storage eq + +let unparse_ty ty = + Micheline.strip_locations @@ fst @@ assert_ok + @@ Script_ir_unparser.(unparse_ty ~loc:() ctxt ty) + +let unparse_data ty x = + fst (assert_return Script_ir_translator.(unparse_data ctxt Readable ty x)) + +let value_size ty x = Script_typed_ir_size.value_size ty x + +let pp_ty fmt ty = Michelson_v1_printer.print_expr fmt (unparse_ty ty) + +let pp_data ty fmt x = Michelson_v1_printer.print_expr fmt (unparse_data ty x) + +let pp_data_with_size ty fmt x = + let nodes, size = value_size ty x in + Format.fprintf + fmt + "(%a, ty=%a, nodes=%d, size=%d)" + (pp_data ty) + x + pp_ty + ty + (Cache_memory_helpers.Nodes.to_int nodes) + (Saturation_repr.to_int size) + +let size_compare (nodes1, size1) (nodes2, size2) = + compare + (Cache_memory_helpers.Nodes.to_int nodes1, Saturation_repr.to_int size1) + (Cache_memory_helpers.Nodes.to_int nodes2, Saturation_repr.to_int size2) + +let value_size_compare ty x1 x2 = + size_compare (value_size ty x1) (value_size ty x2) + +let extract_lazy_storage_diff (ty : ('a, 'ac) ty) (x : 'a) ctxt = + let open Lwt_result_syntax in + let*? to_duplicate, ctxt = + Script_ir_translator.collect_lazy_storage ctxt ty x + in + Script_ir_translator.extract_lazy_storage_diff + ctxt + Optimized + ~temporary:false + ~to_duplicate + ~to_update:Script_ir_translator.no_lazy_storage_id + ty + x + +(* Test. + * Tests that round-tripping a contract storage through the context does not + * alter its size. + *) +let test_roundtrip_size = + QCheck2.Test.make + ~count:100 + ~name:"roundtrip_size" + data_generator + (fun (Ex_data (ty, x)) -> + let x, lazy_storage_diff, _ctxt = + assert_return @@ extract_lazy_storage_diff ty x ctxt + in + qcheck_eq + ~cmp:(value_size_compare ty) + ~pp:(pp_data_with_size ty) + x + (assert_return @@ roundtrip ty x lazy_storage_diff ctxt)) + +(* Same but on big maps. + *) +let test_roundtrip_size_big_map = + QCheck2.Test.make + ~count:100 + ~name:"roundtrip_size_big_map" + big_map_data_generator + (fun (Ex_data (ty, x)) -> + let x, lazy_storage_diff, _ctxt = + assert_return @@ extract_lazy_storage_diff ty x ctxt + in + qcheck_eq + ~cmp:(value_size_compare ty) + ~pp:(pp_data_with_size ty) + x + (assert_return @@ roundtrip ty x lazy_storage_diff ctxt)) + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [ + ("roundtrip_size", qcheck_wrap [test_roundtrip_size]); + ("roundtrip_size_big_map", qcheck_wrap [test_roundtrip_size_big_map]); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_tez_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_tez_repr.ml new file mode 100644 index 000000000000..89f3c9adb1f5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_tez_repr.ml @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_tez_repr.ml + Subject: Operations in Tez_repr +*) + +open Protocol.Alpha_context +open Test_tez + +let z_mutez_min = Z.zero + +let z_mutez_max = Z.of_int64 Int64.max_int + +let tez_to_z (tez : Tez.t) : Z.t = Z.of_int64 (Tez.to_mutez tez) + +let z_in_mutez_bounds (z : Z.t) : bool = + Z.Compare.(z_mutez_min <= z && z <= z_mutez_max) + +let compare (c' : Z.t) (c : Tez.t tzresult) : bool = + match (z_in_mutez_bounds @@ c', c) with + | true, Ok c -> + Qcheck2_helpers.qcheck_eq' + ~pp:Z.pp_print + ~expected:c' + ~actual:(tez_to_z c) + () + | true, Error _ -> + QCheck2.Test.fail_reportf + "@[Results are in Z bounds, but tez operation fails.@]" + | false, Ok _ -> + QCheck2.Test.fail_reportf + "@[Results are not in Z bounds, but tez operation did not fail.@]" + | false, Error _ -> true + +(* [prop_binop f f' (a, b)] compares the function [f] in Tez with a model + function function [f'] in [Z]. + + If [f' a' b'] falls outside Tez bounds, it is true if [f a b] has + failed. If not, it it is true if [f a b = f' a' b'] where [a'] + (resp. [b']) are [a] (resp. [b']) in [Z]. *) +let prop_binop (f : Tez.t -> Tez.t -> Tez.t tzresult) (f' : Z.t -> Z.t -> Z.t) + ((a, b) : Tez.t * Tez.t) : bool = + compare (f' (tez_to_z a) (tez_to_z b)) (f a b) + +(* [prop_binop64 f f' (a, b)] is as [prop_binop] but for binary operations + where the second operand is of type [int64]. *) +let prop_binop64 (f : Tez.t -> int64 -> Tez.t tzresult) (f' : Z.t -> Z.t -> Z.t) + ((a, b) : Tez.t * int64) : bool = + compare (f' (tez_to_z a) (Z.of_int64 b)) (f a b) + +(** Generator for int64 by conversion from int32 *) +let gen_int64_of32 : int64 QCheck2.Gen.t = + QCheck2.Gen.(map Int64.of_int32 int32) + +(** Generator for int64 mixing small positive integers, + int64s from int32 and arbitrary int64 with equal frequency *) +let gen_int64_sizes : int64 QCheck2.Gen.t = + let open QCheck2.Gen in + oneof [map Int64.of_int (int_range (-10) 10); gen_int64_of32; int64] + +(** Generator for positive int64, mixing small positive integers, + int64s from int32 and arbitrary int64 with equal frequency *) +let gen_ui64_sizes : int64 QCheck2.Gen.t = + let open QCheck2.Gen in + map + (fun i -> + let v = if i = Int64.min_int then Int64.max_int else Int64.abs i in + assert (v >= 0L) ; + v) + gen_int64_sizes + +(** Generator for tez based on [gen_tez_sizes] *) +let gen_tez_sizes = + let open QCheck2.Gen in + map Tez.of_mutez_exn gen_ui64_sizes + +let test_coherent_mul = + QCheck2.Test.make + ~name:"Tez.(*?) is coherent w.r.t. Z.(*)" + QCheck2.Gen.(pair gen_tez_sizes gen_ui64_sizes) + (prop_binop64 ( *? ) Z.( * )) + +let test_coherent_sub = + QCheck2.Test.make + ~name:"Tez.(-?) is coherent w.r.t. Z.(-)" + QCheck2.Gen.(pair gen_tez_sizes gen_tez_sizes) + (prop_binop ( -? ) Z.( - )) + +let test_coherent_add = + QCheck2.Test.make + ~name:"Tez.(+?) is coherent w.r.t. Z.(+)" + QCheck2.Gen.(pair gen_tez_sizes gen_tez_sizes) + (prop_binop ( +? ) Z.( + )) + +let test_coherent_div = + let ( /! ) a b = Ok (a /! b) in + QCheck2.Test.make + ~name:"Tez.( /! ) is coherent w.r.t. Z.(/)" + QCheck2.Gen.(pair gen_tez_sizes gen_ui64_sizes) + (fun (a, b) -> + QCheck2.assume (b > 0L) ; + prop_binop64 ( /! ) Z.( / ) (a, b)) + +let tests = + [test_coherent_mul; test_coherent_sub; test_coherent_add; test_coherent_div] + +let () = + Alcotest.run + ~__FILE__ + Protocol.name + [("Tez_repr", Qcheck2_helpers.qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/test_zk_rollup_encoding.ml b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_zk_rollup_encoding.ml new file mode 100644 index 000000000000..da833af24728 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/test_zk_rollup_encoding.ml @@ -0,0 +1,230 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Library + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/pbt/main.exe \ + -- --file test_zk_rollup_encoding.ml + Subject: Zk rollup encodings +*) + +open Protocol +open QCheck2 +open Qcheck2_helpers + +(* Generators *) + +let gen_zkr_address = + let open Gen in + let+ bytes = bytes_fixed_gen Zk_rollup_repr.Address.size in + Zk_rollup_repr.Address.of_bytes_exn bytes + +let gen_scalar = + let s = Bls12_381.Fr.random () in + Gen.return s + +let gen_l2_state = + let open Gen in + array gen_scalar + +(* Number of operations in each private batch *) +let batch_size = 10 + +(* We use fixed values for Plonk types, because it's interface + doesn't expose a quick and safe way to create them randomly. *) +module Operator = Dummy_zk_rollup.Operator (struct + let batch_size = batch_size +end) + +let nat64 = int64_range_gen 0L Int64.max_int + +let gen_zkr_account = + let open Gen in + let open Zk_rollup_account_repr in + let* state = gen_l2_state in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let circuits_info = SMap.of_seq (Kzg.SMap.to_seq Operator.circuits) in + let* nb_ops = nat in + let static = + { + public_parameters; + state_length = Array.length state; + circuits_info; + nb_ops; + } + in + let* paid_l2_operations_storage_space = nat in + let+ used_l2_operations_storage_space = + map Z.of_int @@ int_bound paid_l2_operations_storage_space + in + let dynamic = + { + state; + paid_l2_operations_storage_space = + Z.of_int paid_l2_operations_storage_space; + used_l2_operations_storage_space; + } + in + {static; dynamic} + +let gen_ticket_hash = + let open Gen in + let+ bytes = bytes_fixed_gen Script_expr_hash.size in + Ticket_hash_repr.of_bytes_exn bytes + +let gen_pkh = + let pkh, _, _ = Signature.generate_key ~algo:Ed25519 () in + Gen.return pkh + +let gen_z = + let open Gen in + sized @@ fun n -> map Z.of_bits (string_size (return n)) + +let gen_l2_op = + let open Gen in + let* op_code = nat in + let* price = + map2 + (fun id amount -> Zk_rollup_operation_repr.{id; amount}) + gen_ticket_hash + gen_z + in + let* l1_dst = gen_pkh in + let* rollup_id = gen_zkr_address in + let+ payload = array gen_scalar in + Zk_rollup_operation_repr.{op_code; price; l1_dst; rollup_id; payload} + +let gen_pending_list = + let open Gen in + let open Zk_rollup_repr in + let of_length next_index = function + | 0 -> Empty {next_index} + | length -> Pending {next_index; length} + in + map2 of_length nat64 uint16 + +(* Data-encoding roundtrip tests *) + +let test_roundtrip_address = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup.t" + ~gen:gen_zkr_address + ~eq:( = ) + Zk_rollup_repr.Address.encoding + +let test_roundtrip_state = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_state_repr.t" + ~gen:gen_l2_state + ~eq:( = ) + Zk_rollup_state_repr.encoding + +let eq_account acc0 acc1 = + let open Zk_rollup_account_repr in + let pp_to_bytes pp = + Data_encoding.Binary.to_bytes_exn + Environment.Plonk.public_parameters_encoding + pp + in + acc0.dynamic = acc1.dynamic + && acc0.static.state_length = acc1.static.state_length + && acc0.static.circuits_info = acc1.static.circuits_info + && acc0.static.nb_ops = acc1.static.nb_ops + && pp_to_bytes acc0.static.public_parameters + = pp_to_bytes acc1.static.public_parameters + +let test_roundtrip_account = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_account_repr.t" + ~gen:gen_zkr_account + ~eq:eq_account + Zk_rollup_account_repr.encoding + +let test_roundtrip_operation = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_operation_repr.t" + ~gen:gen_l2_op + ~eq:( = ) + Zk_rollup_operation_repr.encoding + +let test_roundtrip_pending_list = + test_roundtrip + ~count:1_000 + ~title:"Zk_rollup_repr.pending_list" + ~gen:gen_pending_list + ~eq:( = ) + Zk_rollup_repr.pending_list_encoding + +let tests_roundtrip = + [ + test_roundtrip_address; + test_roundtrip_state; + test_roundtrip_account; + test_roundtrip_operation; + test_roundtrip_pending_list; + ] + +(* Scalar conversion tests *) + +let test_to_scalar ~count ~title ~gen to_scalar = + QCheck2.Test.make + ~count + ~name:(Format.asprintf "to_scalar %s" title) + gen + (fun input -> + try + ignore @@ to_scalar input ; + true + with _ -> false) + +let test_address_to_scalar = + test_to_scalar + ~count:1_000 + ~title:"Zk_rollup_repr.t" + ~gen:gen_zkr_address + Zk_rollup_repr.to_scalar + +let test_operation_to_scalar = + test_to_scalar + ~count:1_000 + ~title:"Zk_rollup_operation.t" + ~gen:gen_l2_op + Zk_rollup_operation_repr.to_scalar_array + +let tests_to_scalar = [test_address_to_scalar; test_operation_to_scalar] + +let () = + Alcotest.run + ~__FILE__ + (Protocol.name ^ ": ZK rollup encoding") + [ + (": roundtrip", qcheck_wrap tests_roundtrip); + (": to_scalar", qcheck_wrap tests_to_scalar); + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/accounts.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/accounts.tz new file mode 100644 index 000000000000..e18e30ac5d57 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/accounts.tz @@ -0,0 +1,67 @@ +{ parameter + (or (key_hash %Initialize) + (pair %Withdraw (key %from) (pair (mutez %withdraw_amount) (signature %sig)))) ; + storage (map :stored_balance key_hash mutez) ; + code { DUP ; + CAR ; + IF_LEFT + { DUP ; + DIP 2 { CDR %stored_balance ; DUP } ; + DIP { SWAP } ; + GET @opt_prev_balance ; + { IF_NONE + { DIP { AMOUNT ; SOME } ; UPDATE ; NIL operation ; PAIR } + { RENAME @previous_balance ; + AMOUNT ; + ADD ; + SOME ; + SWAP ; + UPDATE ; + NIL operation ; + PAIR } } } + { DUP ; + DUP ; + DUP ; + DUP ; + CAR %from ; + DIP 2 + { { CDR ; CAR %withdraw_amount } ; PACK ; BLAKE2B @signed_amount } ; + DIP { { CDR ; CDR %sig } } ; + CHECK_SIGNATURE ; + IF {} { PUSH string "Bad signature" ; FAILWITH } ; + DIP 2 { CDR %stored_balance ; DUP } ; + CAR %from ; + HASH_KEY @from_hash ; + DUP ; + DIP { DIP { SWAP } ; SWAP } ; + GET ; + IF_NONE + { PUSH string "Account does not exist" ; PAIR ; FAILWITH } + { RENAME @previous_balance ; + DIP { DROP } ; + DUP ; + DIP 2 { DUP ; { CDR ; CAR %withdraw_amount } ; DUP } ; + DIP { { COMPARE ; LT @not_enough } } ; + SWAP ; + IF { PUSH string "Not enough funds" ; FAILWITH } + { SUB_MUTEZ @new_balance ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + DIP { DUP ; DIP { SWAP } } ; + DUP ; + PUSH @zero mutez 0 ; + { COMPARE ; EQ @null_balance } ; + IF { DROP ; NONE @new_balance mutez } { SOME @new_balance } ; + SWAP ; + CAR %from ; + HASH_KEY @from_hash ; + UPDATE ; + SWAP ; + DUP ; + { CDR ; CAR %withdraw_amount } ; + DIP { CAR %from ; HASH_KEY @from_hash ; IMPLICIT_ACCOUNT @from_account } ; + UNIT ; + TRANSFER_TOKENS @withdraw_transfer_op ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } } } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/append.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/append.tz new file mode 100644 index 000000000000..7e57150a302e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/append.tz @@ -0,0 +1,10 @@ +{ parameter (pair (list int) (list int)) ; + storage (list int) ; + code { CAR ; + UNPAIR ; + NIL int ; + SWAP ; + ITER { CONS } ; + ITER { CONS } ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/auction.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/auction.tz new file mode 100644 index 000000000000..cc5d87f8cbec --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/auction.tz @@ -0,0 +1,30 @@ +{ parameter key_hash ; + storage (pair timestamp (pair mutez key_hash)) ; + code { DUP ; + { CDR ; CAR } ; + DUP ; + NOW ; + { COMPARE ; GT } ; + IF { { UNIT ; FAILWITH } } {} ; + SWAP ; + DUP ; + CAR ; + DIP { { CDR ; CDR } } ; + AMOUNT ; + PAIR ; + SWAP ; + DIP { SWAP ; PAIR } ; + DUP ; + CAR ; + AMOUNT ; + { COMPARE ; LE } ; + IF { { UNIT ; FAILWITH } } {} ; + DUP ; + CAR ; + DIP { CDR ; IMPLICIT_ACCOUNT } ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/big_map_union.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/big_map_union.tz new file mode 100644 index 000000000000..c50e2e1d130a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/big_map_union.tz @@ -0,0 +1,14 @@ +{ parameter (list (pair string int)) ; + storage (pair (big_map string int) unit) ; + code { { UNPAIR ; DIP { UNPAIR } } ; + ITER { UNPAIR ; + DUP 3 ; + DUP 2 ; + GET ; + IF_NONE { PUSH int 0 } {} ; + SWAP ; + DIP { ADD ; SOME } ; + UPDATE } ; + PAIR ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/check_signature.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/check_signature.tz new file mode 100644 index 000000000000..35ca4070d450 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/check_signature.tz @@ -0,0 +1,11 @@ +{ parameter key ; + storage (pair signature string) ; + code { DUP ; + DUP ; + DIP { CDR ; DUP ; CAR ; DIP { CDR ; PACK } } ; + CAR ; + CHECK_SIGNATURE ; + IF {} { { UNIT ; FAILWITH } } ; + CDR ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-get.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-get.tz new file mode 100644 index 000000000000..7a6f7b6a361a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-get.tz @@ -0,0 +1,27 @@ +{ parameter (pair nat nat nat unit) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + GET 1 ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + GET 3 ; + PUSH nat 4 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + GET 5 ; + PUSH nat 2 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + GET 6 ; + UNIT ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-set.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-set.tz new file mode 100644 index 000000000000..a8c1dc5c2e7f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/comb-set.tz @@ -0,0 +1,13 @@ +{ parameter unit ; + storage (pair nat nat nat unit) ; + code { CDR ; + PUSH nat 2 ; + UPDATE 1 ; + PUSH nat 12 ; + UPDATE 3 ; + PUSH nat 8 ; + UPDATE 5 ; + UNIT ; + UPDATE 6 ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/concat.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/concat.tz new file mode 100644 index 000000000000..ffc97335652b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/concat.tz @@ -0,0 +1,9 @@ +{ parameter string ; + storage string ; + code { DUP ; + DIP { CDR ; NIL string ; SWAP ; CONS } ; + CAR ; + CONS ; + CONCAT ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/conditionals.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/conditionals.tz new file mode 100644 index 000000000000..7eea2f774d76 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/conditionals.tz @@ -0,0 +1,12 @@ +{ parameter (or string (option int)) ; + storage string ; + code { CAR ; + IF_LEFT + {} + { IF_NONE + { { UNIT ; FAILWITH } } + { PUSH int 0 ; + { COMPARE ; GT } ; + IF { { UNIT ; FAILWITH } } { PUSH string "" } } } ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/cps_fact.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/cps_fact.tz new file mode 100644 index 000000000000..58a77dd722e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/cps_fact.tz @@ -0,0 +1,28 @@ +{ storage nat ; + parameter nat ; + code { UNPAIR ; + DIP { SELF ; + ADDRESS ; + SENDER ; + { COMPARE ; EQ ; IF {} { DROP ; PUSH @storage nat 1 } } } ; + DUP ; + PUSH nat 1 ; + { COMPARE ; + GE ; + IF { DROP ; NIL operation ; PAIR } + { PUSH nat 1 ; + SWAP ; + SUB @parameter ; + ISNAT ; + IF_NONE + { NIL operation ; PAIR } + { DUP ; + DIP { PUSH nat 1 ; ADD ; MUL @storage } ; + SWAP ; + DIP { DIP { SELF ; PUSH mutez 0 } ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS } ; + SWAP ; + PAIR } } } } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dign.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dign.tz new file mode 100644 index 000000000000..bb325b83d979 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dign.tz @@ -0,0 +1,11 @@ +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR ; + UNPAIR ; + UNPAIR ; + UNPAIR ; + UNPAIR ; + DIG 4 ; + DIP { DROP ; DROP ; DROP ; DROP } ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dipn.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dipn.tz new file mode 100644 index 000000000000..a320bd5b60aa --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dipn.tz @@ -0,0 +1,15 @@ +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR ; + UNPAIR ; + UNPAIR ; + UNPAIR ; + UNPAIR ; + DIP 5 { PUSH nat 6 } ; + DROP ; + DROP ; + DROP ; + DROP ; + DROP ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dugn.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dugn.tz new file mode 100644 index 000000000000..17c3aba6949a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/dugn.tz @@ -0,0 +1,14 @@ +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR ; + UNPAIR ; + UNPAIR ; + UNPAIR ; + UNPAIR ; + DUG 4 ; + DROP ; + DROP ; + DROP ; + DROP ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ediv.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ediv.tz new file mode 100644 index 000000000000..018ee512ff47 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ediv.tz @@ -0,0 +1,28 @@ +{ parameter (pair int int) ; + storage + (pair (option (pair int nat)) + (option (pair int nat)) + (option (pair int nat)) + (option (pair nat nat))) ; + code { CAR ; + DUP ; + UNPAIR ; + ABS ; + DIP { ABS } ; + EDIV ; + SWAP ; + DUP ; + UNPAIR ; + ABS ; + EDIV ; + SWAP ; + DUP ; + UNPAIR ; + DIP { ABS } ; + EDIV ; + SWAP ; + UNPAIR ; + EDIV ; + { DIP 2 { PAIR } ; DIP { PAIR } ; PAIR } ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/faucet.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/faucet.tz new file mode 100644 index 000000000000..00c69a330a69 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/faucet.tz @@ -0,0 +1,17 @@ +{ parameter key_hash ; + storage timestamp ; + code { UNPAIR ; + SWAP ; + PUSH int 300 ; + ADD @FIVE_MINUTES_LATER ; + NOW ; + { { COMPARE ; GE } ; IF {} { { UNIT ; FAILWITH } } } ; + IMPLICIT_ACCOUNT ; + PUSH mutez 1000000 ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + DIP { NOW } ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/get_and_update_map.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/get_and_update_map.tz new file mode 100644 index 000000000000..ec3bcd0f60b5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/get_and_update_map.tz @@ -0,0 +1,7 @@ +{ parameter string ; + storage (pair (option nat) (map string nat)) ; + code { { UNPAIR ; DIP { UNPAIR } } ; + GET_AND_UPDATE ; + PAIR ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/if.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/if.tz new file mode 100644 index 000000000000..0b9e463b6440 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/if.tz @@ -0,0 +1,7 @@ +{ parameter bool ; + storage (option bool) ; + code { CAR ; + IF { PUSH bool True } { PUSH bool False } ; + SOME ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/insertion_sort.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/insertion_sort.tz new file mode 100644 index 000000000000..79f41696956f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/insertion_sort.tz @@ -0,0 +1,21 @@ +{ parameter (list int) ; + storage (list int) ; + code { CAR ; + NIL int ; + SWAP ; + ITER { SWAP ; + DIP 2 { NIL int } ; + PUSH bool True ; + LOOP { IF_CONS + { SWAP ; + DIP { DUP ; DIP 2 { DUP } ; DIP { { COMPARE ; LT } } ; SWAP } ; + SWAP ; + IF { DIP { SWAP ; DIP { CONS } } ; PUSH bool True } + { SWAP ; CONS ; PUSH bool False } } + { NIL int ; PUSH bool False } } ; + SWAP ; + CONS ; + SWAP ; + ITER { CONS } } ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/list_map_block.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/list_map_block.tz new file mode 100644 index 000000000000..f2f66dd30766 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/list_map_block.tz @@ -0,0 +1,9 @@ +{ parameter (list int) ; + storage (list int) ; + code { CAR ; + PUSH int 0 ; + SWAP ; + MAP { DIP { DUP } ; ADD ; DIP { PUSH int 1 ; ADD } } ; + NIL operation ; + PAIR ; + DIP { DROP } } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/loop_left.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/loop_left.tz new file mode 100644 index 000000000000..d491a1b32920 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/loop_left.tz @@ -0,0 +1,16 @@ +{ parameter (list string) ; + storage (list string) ; + code { CAR ; + NIL string ; + SWAP ; + PAIR ; + LEFT (list string) ; + LOOP_LEFT + { DUP ; + CAR ; + DIP { CDR } ; + IF_CONS + { SWAP ; DIP { CONS } ; PAIR ; LEFT (list string) } + { RIGHT (pair (list string) (list string)) } } ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/opt_map.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/opt_map.tz new file mode 100644 index 000000000000..51feb91f44ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/opt_map.tz @@ -0,0 +1,12 @@ +{ + parameter int; + storage (option int); + code { + UNPAIR; + SWAP ; + MAP { DIP { DUP } ; ADD ; } ; + DIP { DROP } ; + NIL operation ; + PAIR ; + } +} diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/packunpack.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/packunpack.tz new file mode 100644 index 000000000000..8f08146fe0b6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/packunpack.tz @@ -0,0 +1,13 @@ +{ parameter (pair (pair (pair string (list int)) (set nat)) bytes) ; + storage unit ; + code { CAR ; + UNPAIR ; + DIP { DUP } ; + PACK ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNPACK (pair (pair string (list int)) (set nat)) ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/pexec.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/pexec.tz new file mode 100644 index 000000000000..9211a7b9c7a0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/pexec.tz @@ -0,0 +1,9 @@ +{ parameter nat ; + storage nat ; + code { LAMBDA (pair nat nat) nat { UNPAIR ; ADD } ; + SWAP ; + UNPAIR ; + DIP { APPLY } ; + EXEC ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/rec_id_unit.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/rec_id_unit.tz new file mode 100644 index 000000000000..ae143d1c2a8a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/rec_id_unit.tz @@ -0,0 +1,9 @@ +{parameter unit; + storage unit; + code { CAR ; + LAMBDA_REC unit unit + {DIP {DROP}}; + SWAP; + EXEC; + NIL operation; + PAIR}} diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/reverse_loop.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/reverse_loop.tz new file mode 100644 index 000000000000..c73aa3408bb1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/reverse_loop.tz @@ -0,0 +1,12 @@ +{ parameter (list string) ; + storage (list string) ; + code { CAR ; + NIL string ; + SWAP ; + PUSH bool True ; + LOOP { IF_CONS + { SWAP ; DIP { CONS } ; PUSH bool True } + { NIL string ; PUSH bool False } } ; + DROP ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/set_delegate.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/set_delegate.tz new file mode 100644 index 000000000000..560682be4b51 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/set_delegate.tz @@ -0,0 +1,3 @@ +{ parameter (option key_hash) ; + storage unit ; + code { UNPAIR ; SET_DELEGATE ; DIP { NIL operation } ; CONS ; PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/shifts.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/shifts.tz new file mode 100644 index 000000000000..94886af646e4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/shifts.tz @@ -0,0 +1,7 @@ +{ parameter (or (pair nat nat) (pair nat nat)) ; + storage (option nat) ; + code { CAR ; + IF_LEFT { UNPAIR ; LSL } { UNPAIR ; LSR } ; + SOME ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/spawn_identities.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/spawn_identities.tz new file mode 100644 index 000000000000..00480de0ef08 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/spawn_identities.tz @@ -0,0 +1,28 @@ +{ parameter nat ; + storage (list address) ; + code { DUP ; + CAR ; + DIP { CDR ; NIL operation } ; + PUSH bool True ; + LOOP { DUP ; + PUSH nat 0 ; + { COMPARE ; EQ } ; + IF { PUSH bool False } + { PUSH nat 1 ; + SWAP ; + SUB ; + ABS ; + PUSH string "init" ; + PUSH mutez 5000000 ; + NONE key_hash ; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } ; + SWAP ; + DIP { SWAP ; DIP { CONS } } ; + SWAP ; + DIP { SWAP ; DIP { CONS } } ; + PUSH bool True } } ; + DROP ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_join.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_join.tz new file mode 100644 index 000000000000..b29c396b8497 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_join.tz @@ -0,0 +1,10 @@ +{ parameter (ticket nat) ; + storage (option (ticket nat)) ; + code { UNPAIR ; + SWAP ; + IF_NONE + {} + { PAIR ; JOIN_TICKETS ; { IF_NONE { { UNIT ; FAILWITH } } {} } } ; + SOME ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_split.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_split.tz new file mode 100644 index 000000000000..817c1711331f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/ticket_split.tz @@ -0,0 +1,21 @@ +{ parameter (ticket nat) ; + storage unit ; + code { CAR ; + PUSH (pair nat nat) (Pair 1 2) ; + SWAP ; + SPLIT_TICKET ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + UNPAIR ; + READ_TICKET ; + { CDR ; CDR } ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DROP ; + READ_TICKET ; + { CDR ; CDR } ; + PUSH nat 2 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_fib.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_fib.tz new file mode 100644 index 000000000000..51b308e07948 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_fib.tz @@ -0,0 +1,6 @@ +{ parameter (pair nat address) ; + storage nat ; + code { CAR ; + UNPAIR ; + VIEW "fib" nat ; + { IF_NONE { { UNIT ; FAILWITH } } { NIL operation ; PAIR } } } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_toplevel_lib.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_toplevel_lib.tz new file mode 100644 index 000000000000..4cefa5f7fd62 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/view_toplevel_lib.tz @@ -0,0 +1,80 @@ +{ parameter nat ; + storage nat ; + code { CAR ; NIL operation ; PAIR } ; + view "add" nat nat { UNPAIR ; ADD } ; + view "id" nat (pair nat nat) {} ; + view "test_failwith" nat (pair nat nat) { FAILWITH } ; + view "step_constants" + unit + (pair (pair mutez mutez) (pair (pair address address) address)) + { DROP ; + SOURCE ; + SENDER ; + SELF_ADDRESS ; + PAIR ; + PAIR ; + BALANCE ; + AMOUNT ; + PAIR ; + PAIR } ; + view "succ" + (pair nat address) + nat + { CAR ; + UNPAIR ; + PUSH nat 1 ; + ADD ; + PAIR ; + DUP ; + CDR ; + SWAP ; + VIEW "is_twenty" nat ; + { IF_NONE { { UNIT ; FAILWITH } } {} } } ; + view "is_twenty" + (pair nat address) + nat + { CAR ; + DUP ; + CAR ; + PUSH nat 20 ; + COMPARE ; + EQ ; + IF { CAR } + { DUP ; + CDR ; + SWAP ; + VIEW "succ" nat ; + { IF_NONE { { UNIT ; FAILWITH } } {} } } } ; + view "fib" + nat + nat + { CAR ; + DUP ; + PUSH nat 0 ; + COMPARE ; + EQ ; + IF {} + { DUP ; + PUSH nat 1 ; + COMPARE ; + EQ ; + IF {} + { DUP ; + PUSH nat 1 ; + SWAP ; + SUB ; + ABS ; + SELF_ADDRESS ; + SWAP ; + VIEW "fib" nat ; + { IF_NONE + { { UNIT ; FAILWITH } } + { SWAP ; + PUSH nat 2 ; + SWAP ; + SUB ; + ABS ; + SELF_ADDRESS ; + SWAP ; + VIEW "fib" nat ; + { IF_NONE { { UNIT ; FAILWITH } } { ADD } } } } } } } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/xor.tz b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/xor.tz new file mode 100644 index 000000000000..6989394c9992 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/contracts/xor.tz @@ -0,0 +1,7 @@ +{ parameter (or (pair bool bool) (pair nat nat)) ; + storage (option (or bool nat)) ; + code { CAR ; + IF_LEFT { UNPAIR ; XOR ; LEFT nat } { UNPAIR ; XOR ; RIGHT bool } ; + SOME ; + NIL operation ; + PAIR } } diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/dune b/src/proto_020_PsParisC/lib_protocol/test/regression/dune new file mode 100644 index 000000000000..ee981591859d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/dune @@ -0,0 +1,52 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_protocol_test_regression_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + tezt-tezos + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.client + octez-protocol-019-PtParisB-libs.plugin + octez-protocol-019-PtParisB-libs.test-helpers + octez-libs.micheline) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezt_tezos + -open Tezos_protocol_019_PtParisB + -open Tezos_client_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_019_PtParisB_test_helpers + -open Tezos_micheline) + (modules test_logging)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_regression_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (deps + (glob_files contracts/*.tz) + (glob_files expected/test_logging.ml/*.out)) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/accounts.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/accounts.out new file mode 100644 index 000000000000..6ce81da765a4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/accounts.out @@ -0,0 +1,149 @@ + +trace + - DUP (interp) @ location: 15 + [ (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - DUP (entry) @ location: 15 + [ (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - log/CAR (exit) @ location: 15 + [ (Pair (Left "[PUBLIC_KEY_HASH]") {}) + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - CAR (entry) @ location: 16 + [ (Pair (Left "[PUBLIC_KEY_HASH]") {}) + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - log/IF_LEFT (exit) @ location: 16 + [ (Left "[PUBLIC_KEY_HASH]") + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - IF_LEFT (entry) @ location: 17 + [ (Left "[PUBLIC_KEY_HASH]") + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - log/DUP (exit) @ location: 17 + [ "[PUBLIC_KEY_HASH]" + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - DUP (entry) @ location: 19 + [ "[PUBLIC_KEY_HASH]" + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - log/DIP (exit) @ location: 19 + [ "[PUBLIC_KEY_HASH]" + "[PUBLIC_KEY_HASH]" + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - DIP (entry) @ location: 20 + [ "[PUBLIC_KEY_HASH]" + "[PUBLIC_KEY_HASH]" + (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - log/CDR (exit) @ location: 20 + [ (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - CDR (entry) @ location: 23 + [ (Pair (Left "[PUBLIC_KEY_HASH]") {}) ] + - log/DUP (exit) @ location: 23 + [ {} ] + - DUP (entry) @ location: 24 + [ {} ] + - log/[halt] (exit) @ location: 24 + [ {} + {} ] + - [halt] (entry) @ location: 22 + [ {} + {} ] + - log/DIP (exit) @ location: 20 + [ "[PUBLIC_KEY_HASH]" + "[PUBLIC_KEY_HASH]" + {} + {} ] + - DIP (entry) @ location: 25 + [ "[PUBLIC_KEY_HASH]" + "[PUBLIC_KEY_HASH]" + {} + {} ] + - log/SWAP (exit) @ location: 25 + [ "[PUBLIC_KEY_HASH]" + {} + {} ] + - SWAP (entry) @ location: 27 + [ "[PUBLIC_KEY_HASH]" + {} + {} ] + - log/[halt] (exit) @ location: 27 + [ {} + "[PUBLIC_KEY_HASH]" + {} ] + - [halt] (entry) @ location: 27 + [ {} + "[PUBLIC_KEY_HASH]" + {} ] + - control: KUndip + - control: KCons + - log/GET (exit) @ location: 25 + [ "[PUBLIC_KEY_HASH]" + {} + "[PUBLIC_KEY_HASH]" + {} ] + - GET (entry) @ location: 28 + [ "[PUBLIC_KEY_HASH]" + {} + "[PUBLIC_KEY_HASH]" + {} ] + - log/IF_NONE (exit) @ location: 28 + [ None + "[PUBLIC_KEY_HASH]" + {} ] + - IF_NONE (entry) @ location: 30 + [ None + "[PUBLIC_KEY_HASH]" + {} ] + - log/DIP (exit) @ location: 30 + [ "[PUBLIC_KEY_HASH]" + {} ] + - DIP (entry) @ location: 32 + [ "[PUBLIC_KEY_HASH]" + {} ] + - log/AMOUNT (exit) @ location: 32 + [ {} ] + - AMOUNT (entry) @ location: 34 + [ {} ] + - log/SOME (exit) @ location: 34 + [ 0 + {} ] + - SOME (entry) @ location: 35 + [ 0 + {} ] + - log/[halt] (exit) @ location: 35 + [ (Some 0) + {} ] + - [halt] (entry) @ location: 33 + [ (Some 0) + {} ] + - control: KUndip + - control: KCons + - log/UPDATE (exit) @ location: 32 + [ "[PUBLIC_KEY_HASH]" + (Some 0) + {} ] + - UPDATE (entry) @ location: 36 + [ "[PUBLIC_KEY_HASH]" + (Some 0) + {} ] + - log/NIL (exit) @ location: 36 + [ { Elt "[PUBLIC_KEY_HASH]" 0 } ] + - NIL (entry) @ location: 37 + [ { Elt "[PUBLIC_KEY_HASH]" 0 } ] + - log/PAIR (exit) @ location: 37 + [ {} + { Elt "[PUBLIC_KEY_HASH]" 0 } ] + - PAIR (entry) @ location: 39 + [ {} + { Elt "[PUBLIC_KEY_HASH]" 0 } ] + - log/[halt] (exit) @ location: 39 + [ (Pair {} { Elt "[PUBLIC_KEY_HASH]" 0 }) ] + - [halt] (entry) @ location: 14 + [ (Pair {} { Elt "[PUBLIC_KEY_HASH]" 0 }) ] + - control: KCons + - log/[halt] (exit) @ location: 30 + [ (Pair {} { Elt "[PUBLIC_KEY_HASH]" 0 }) ] + - [halt] (entry) @ location: 14 + [ (Pair {} { Elt "[PUBLIC_KEY_HASH]" 0 }) ] + - control: KCons + - log/[halt] (exit) @ location: 17 + [ (Pair {} { Elt "[PUBLIC_KEY_HASH]" 0 }) ] + - [halt] (entry) @ location: 14 + [ (Pair {} { Elt "[PUBLIC_KEY_HASH]" 0 }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/append.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/append.out new file mode 100644 index 000000000000..b573fc597191 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/append.out @@ -0,0 +1,135 @@ + +trace + - CAR (interp) @ location: 12 + [ (Pair (Pair { 7 ; 8 ; 9 } { 4 ; 5 ; 6 }) { 1 ; 2 ; 3 }) ] + - CAR (entry) @ location: 12 + [ (Pair (Pair { 7 ; 8 ; 9 } { 4 ; 5 ; 6 }) { 1 ; 2 ; 3 }) ] + - log/UNPAIR (exit) @ location: 12 + [ (Pair { 7 ; 8 ; 9 } { 4 ; 5 ; 6 }) ] + - UNPAIR (entry) @ location: 13 + [ (Pair { 7 ; 8 ; 9 } { 4 ; 5 ; 6 }) ] + - log/NIL (exit) @ location: 13 + [ { 7 ; 8 ; 9 } + { 4 ; 5 ; 6 } ] + - NIL (entry) @ location: 14 + [ { 7 ; 8 ; 9 } + { 4 ; 5 ; 6 } ] + - log/SWAP (exit) @ location: 14 + [ {} + { 7 ; 8 ; 9 } + { 4 ; 5 ; 6 } ] + - SWAP (entry) @ location: 16 + [ {} + { 7 ; 8 ; 9 } + { 4 ; 5 ; 6 } ] + - log/ITER (exit) @ location: 16 + [ { 7 ; 8 ; 9 } + {} + { 4 ; 5 ; 6 } ] + - ITER (entry) @ location: 17 + [ { 7 ; 8 ; 9 } + {} + { 4 ; 5 ; 6 } ] + - control: KIter + - log/CONS (exit) @ location: 17 + [ 7 + {} + { 4 ; 5 ; 6 } ] + - CONS (entry) @ location: 19 + [ 7 + {} + { 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 19 + [ { 7 } + { 4 ; 5 ; 6 } ] + - [halt] (entry) @ location: 17 + [ { 7 } + { 4 ; 5 ; 6 } ] + - control: KIter + - log/CONS (exit) @ location: 17 + [ 8 + { 7 } + { 4 ; 5 ; 6 } ] + - CONS (entry) @ location: 19 + [ 8 + { 7 } + { 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 19 + [ { 8 ; 7 } + { 4 ; 5 ; 6 } ] + - [halt] (entry) @ location: 17 + [ { 8 ; 7 } + { 4 ; 5 ; 6 } ] + - control: KIter + - log/CONS (exit) @ location: 17 + [ 9 + { 8 ; 7 } + { 4 ; 5 ; 6 } ] + - CONS (entry) @ location: 19 + [ 9 + { 8 ; 7 } + { 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 19 + [ { 9 ; 8 ; 7 } + { 4 ; 5 ; 6 } ] + - [halt] (entry) @ location: 17 + [ { 9 ; 8 ; 7 } + { 4 ; 5 ; 6 } ] + - control: KIter + - control: KCons + - log/ITER (exit) @ location: 17 + [ { 9 ; 8 ; 7 } + { 4 ; 5 ; 6 } ] + - ITER (entry) @ location: 20 + [ { 9 ; 8 ; 7 } + { 4 ; 5 ; 6 } ] + - control: KIter + - log/CONS (exit) @ location: 20 + [ 9 + { 4 ; 5 ; 6 } ] + - CONS (entry) @ location: 22 + [ 9 + { 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 22 + [ { 9 ; 4 ; 5 ; 6 } ] + - [halt] (entry) @ location: 20 + [ { 9 ; 4 ; 5 ; 6 } ] + - control: KIter + - log/CONS (exit) @ location: 20 + [ 8 + { 9 ; 4 ; 5 ; 6 } ] + - CONS (entry) @ location: 22 + [ 8 + { 9 ; 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 22 + [ { 8 ; 9 ; 4 ; 5 ; 6 } ] + - [halt] (entry) @ location: 20 + [ { 8 ; 9 ; 4 ; 5 ; 6 } ] + - control: KIter + - log/CONS (exit) @ location: 20 + [ 7 + { 8 ; 9 ; 4 ; 5 ; 6 } ] + - CONS (entry) @ location: 22 + [ 7 + { 8 ; 9 ; 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 22 + [ { 7 ; 8 ; 9 ; 4 ; 5 ; 6 } ] + - [halt] (entry) @ location: 20 + [ { 7 ; 8 ; 9 ; 4 ; 5 ; 6 } ] + - control: KIter + - control: KCons + - log/NIL (exit) @ location: 20 + [ { 7 ; 8 ; 9 ; 4 ; 5 ; 6 } ] + - NIL (entry) @ location: 23 + [ { 7 ; 8 ; 9 ; 4 ; 5 ; 6 } ] + - log/PAIR (exit) @ location: 23 + [ {} + { 7 ; 8 ; 9 ; 4 ; 5 ; 6 } ] + - PAIR (entry) @ location: 25 + [ {} + { 7 ; 8 ; 9 ; 4 ; 5 ; 6 } ] + - log/[halt] (exit) @ location: 25 + [ (Pair {} { 7 ; 8 ; 9 ; 4 ; 5 ; 6 }) ] + - [halt] (entry) @ location: 11 + [ (Pair {} { 7 ; 8 ; 9 ; 4 ; 5 ; 6 }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/auction.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/auction.out new file mode 100644 index 000000000000..ac865144621f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/auction.out @@ -0,0 +1,415 @@ + +trace + - DUP (interp) @ location: 11 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - DUP (entry) @ location: 11 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/CDR (exit) @ location: 11 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - CDR (entry) @ location: 13 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/CAR (exit) @ location: 13 + [ (Pair "[TIMESTAMP]" 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - CAR (entry) @ location: 14 + [ (Pair "[TIMESTAMP]" 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/DUP (exit) @ location: 14 + [ "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - DUP (entry) @ location: 15 + [ "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/NOW (exit) @ location: 15 + [ "[TIMESTAMP]" + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - NOW (entry) @ location: 16 + [ "[TIMESTAMP]" + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/COMPARE (exit) @ location: 16 + [ "[TIMESTAMP]" + "[TIMESTAMP]" + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - COMPARE (entry) @ location: 18 + [ "[TIMESTAMP]" + "[TIMESTAMP]" + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/GT (exit) @ location: 18 + [ -1 + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - GT (entry) @ location: 19 + [ -1 + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/IF (exit) @ location: 19 + [ False + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - IF (entry) @ location: 20 + [ False + "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/[halt] (exit) @ location: 20 + [ "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - [halt] (entry) @ location: 26 + [ "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - control: KCons + - log/SWAP (exit) @ location: 20 + [ "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - SWAP (entry) @ location: 26 + [ "[TIMESTAMP]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") ] + - log/DUP (exit) @ location: 26 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - DUP (entry) @ location: 27 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/CAR (exit) @ location: 27 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - CAR (entry) @ location: 28 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/DIP (exit) @ location: 28 + [ "[PUBLIC_KEY_HASH]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - DIP (entry) @ location: 29 + [ "[PUBLIC_KEY_HASH]" + (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/CDR (exit) @ location: 29 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - CDR (entry) @ location: 32 + [ (Pair "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" + 50000000 + "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/CDR (exit) @ location: 32 + [ (Pair "[TIMESTAMP]" 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - CDR (entry) @ location: 33 + [ (Pair "[TIMESTAMP]" 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/[halt] (exit) @ location: 33 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - [halt] (entry) @ location: 31 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - control: KUndip + - control: KCons + - log/AMOUNT (exit) @ location: 29 + [ "[PUBLIC_KEY_HASH]" + (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - AMOUNT (entry) @ location: 34 + [ "[PUBLIC_KEY_HASH]" + (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/PAIR (exit) @ location: 34 + [ 100000000 + "[PUBLIC_KEY_HASH]" + (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - PAIR (entry) @ location: 35 + [ 100000000 + "[PUBLIC_KEY_HASH]" + (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/SWAP (exit) @ location: 35 + [ (Pair 100000000 "[PUBLIC_KEY_HASH]") + (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - SWAP (entry) @ location: 36 + [ (Pair 100000000 "[PUBLIC_KEY_HASH]") + (Pair 50000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/DIP (exit) @ location: 36 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair 100000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - DIP (entry) @ location: 37 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair 100000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/SWAP (exit) @ location: 37 + [ (Pair 100000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - SWAP (entry) @ location: 39 + [ (Pair 100000000 "[PUBLIC_KEY_HASH]") + "[TIMESTAMP]" ] + - log/PAIR (exit) @ location: 39 + [ "[TIMESTAMP]" + (Pair 100000000 "[PUBLIC_KEY_HASH]") ] + - PAIR (entry) @ location: 40 + [ "[TIMESTAMP]" + (Pair 100000000 "[PUBLIC_KEY_HASH]") ] + - log/[halt] (exit) @ location: 40 + [ (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - [halt] (entry) @ location: 38 + [ (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - control: KUndip + - control: KCons + - log/DUP (exit) @ location: 37 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - DUP (entry) @ location: 41 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/CAR (exit) @ location: 41 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - CAR (entry) @ location: 42 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/AMOUNT (exit) @ location: 42 + [ 50000000 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - AMOUNT (entry) @ location: 43 + [ 50000000 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/COMPARE (exit) @ location: 43 + [ 100000000 + 50000000 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - COMPARE (entry) @ location: 45 + [ 100000000 + 50000000 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/LE (exit) @ location: 45 + [ 1 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - LE (entry) @ location: 46 + [ 1 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/IF (exit) @ location: 46 + [ False + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - IF (entry) @ location: 47 + [ False + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/[halt] (exit) @ location: 47 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - [halt] (entry) @ location: 53 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - control: KCons + - log/DUP (exit) @ location: 47 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - DUP (entry) @ location: 53 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/CAR (exit) @ location: 53 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - CAR (entry) @ location: 54 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/DIP (exit) @ location: 54 + [ 50000000 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - DIP (entry) @ location: 55 + [ 50000000 + (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/CDR (exit) @ location: 55 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - CDR (entry) @ location: 57 + [ (Pair 50000000 "[PUBLIC_KEY_HASH]") + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/IMPLICIT_ACCOUNT (exit) @ location: 57 + [ "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - IMPLICIT_ACCOUNT (entry) @ location: 58 + [ "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/[halt] (exit) @ location: 58 + [ "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - [halt] (entry) @ location: 56 + [ "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - control: KUndip + - control: KCons + - log/UNIT (exit) @ location: 55 + [ 50000000 + "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - UNIT (entry) @ location: 59 + [ 50000000 + "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/TRANSFER_TOKENS (exit) @ location: 59 + [ Unit + 50000000 + "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - TRANSFER_TOKENS (entry) @ location: 60 + [ Unit + 50000000 + "[PUBLIC_KEY_HASH]" + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/NIL (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - NIL (entry) @ location: 61 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/SWAP (exit) @ location: 61 + [ {} + 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - SWAP (entry) @ location: 63 + [ {} + 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + {} + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - CONS (entry) @ location: 64 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + {} + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/PAIR (exit) @ location: 64 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - PAIR (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + (Pair "[TIMESTAMP]" 100000000 "[PUBLIC_KEY_HASH]") ] + - log/[halt] (exit) @ location: 65 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + "[TIMESTAMP]" + 100000000 + "[PUBLIC_KEY_HASH]") ] + - [halt] (entry) @ location: 10 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000180e1eb170000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + "[TIMESTAMP]" + 100000000 + "[PUBLIC_KEY_HASH]") ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/big_map_union.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/big_map_union.out new file mode 100644 index 000000000000..d3d7a2bfc45c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/big_map_union.out @@ -0,0 +1,499 @@ + +trace + - UNPAIR (interp) @ location: 15 + [ (Pair { Pair "string" 12 ; Pair "abc" 99 ; Pair "def" 3 } { Elt "123" 123 } Unit) ] + - UNPAIR (entry) @ location: 15 + [ (Pair { Pair "string" 12 ; Pair "abc" 99 ; Pair "def" 3 } { Elt "123" 123 } Unit) ] + - log/DIP (exit) @ location: 15 + [ { Pair "string" 12 ; Pair "abc" 99 ; Pair "def" 3 } + (Pair { Elt "123" 123 } Unit) ] + - DIP (entry) @ location: 16 + [ { Pair "string" 12 ; Pair "abc" 99 ; Pair "def" 3 } + (Pair { Elt "123" 123 } Unit) ] + - log/UNPAIR (exit) @ location: 16 + [ (Pair { Elt "123" 123 } Unit) ] + - UNPAIR (entry) @ location: 18 + [ (Pair { Elt "123" 123 } Unit) ] + - log/[halt] (exit) @ location: 18 + [ { Elt "123" 123 } + Unit ] + - [halt] (entry) @ location: 18 + [ { Elt "123" 123 } + Unit ] + - control: KUndip + - control: KCons + - log/ITER (exit) @ location: 16 + [ { Pair "string" 12 ; Pair "abc" 99 ; Pair "def" 3 } + { Elt "123" 123 } + Unit ] + - ITER (entry) @ location: 19 + [ { Pair "string" 12 ; Pair "abc" 99 ; Pair "def" 3 } + { Elt "123" 123 } + Unit ] + - control: KIter + - log/UNPAIR (exit) @ location: 19 + [ (Pair "string" 12) + { Elt "123" 123 } + Unit ] + - UNPAIR (entry) @ location: 21 + [ (Pair "string" 12) + { Elt "123" 123 } + Unit ] + - log/DUP (exit) @ location: 21 + [ "string" + 12 + { Elt "123" 123 } + Unit ] + - DUP (entry) @ location: 22 + [ "string" + 12 + { Elt "123" 123 } + Unit ] + - log/DUP (exit) @ location: 22 + [ { Elt "123" 123 } + "string" + 12 + { Elt "123" 123 } + Unit ] + - DUP (entry) @ location: 24 + [ { Elt "123" 123 } + "string" + 12 + { Elt "123" 123 } + Unit ] + - log/GET (exit) @ location: 24 + [ "string" + { Elt "123" 123 } + "string" + 12 + { Elt "123" 123 } + Unit ] + - GET (entry) @ location: 26 + [ "string" + { Elt "123" 123 } + "string" + 12 + { Elt "123" 123 } + Unit ] + - log/IF_NONE (exit) @ location: 26 + [ None + "string" + 12 + { Elt "123" 123 } + Unit ] + - IF_NONE (entry) @ location: 27 + [ None + "string" + 12 + { Elt "123" 123 } + Unit ] + - log/PUSH (exit) @ location: 27 + [ "string" + 12 + { Elt "123" 123 } + Unit ] + - PUSH (entry) @ location: 29 + [ "string" + 12 + { Elt "123" 123 } + Unit ] + - log/[halt] (exit) @ location: 29 + [ 0 + "string" + 12 + { Elt "123" 123 } + Unit ] + - [halt] (entry) @ location: 33 + [ 0 + "string" + 12 + { Elt "123" 123 } + Unit ] + - control: KCons + - log/SWAP (exit) @ location: 27 + [ 0 + "string" + 12 + { Elt "123" 123 } + Unit ] + - SWAP (entry) @ location: 33 + [ 0 + "string" + 12 + { Elt "123" 123 } + Unit ] + - log/DIP (exit) @ location: 33 + [ "string" + 0 + 12 + { Elt "123" 123 } + Unit ] + - DIP (entry) @ location: 34 + [ "string" + 0 + 12 + { Elt "123" 123 } + Unit ] + - log/ADD (exit) @ location: 34 + [ 0 + 12 + { Elt "123" 123 } + Unit ] + - ADD (entry) @ location: 36 + [ 0 + 12 + { Elt "123" 123 } + Unit ] + - log/SOME (exit) @ location: 36 + [ 12 + { Elt "123" 123 } + Unit ] + - SOME (entry) @ location: 37 + [ 12 + { Elt "123" 123 } + Unit ] + - log/[halt] (exit) @ location: 37 + [ (Some 12) + { Elt "123" 123 } + Unit ] + - [halt] (entry) @ location: 35 + [ (Some 12) + { Elt "123" 123 } + Unit ] + - control: KUndip + - control: KCons + - log/UPDATE (exit) @ location: 34 + [ "string" + (Some 12) + { Elt "123" 123 } + Unit ] + - UPDATE (entry) @ location: 38 + [ "string" + (Some 12) + { Elt "123" 123 } + Unit ] + - log/[halt] (exit) @ location: 38 + [ { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 19 + [ { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - control: KIter + - log/UNPAIR (exit) @ location: 19 + [ (Pair "abc" 99) + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - UNPAIR (entry) @ location: 21 + [ (Pair "abc" 99) + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/DUP (exit) @ location: 21 + [ "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - DUP (entry) @ location: 22 + [ "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/DUP (exit) @ location: 22 + [ { Elt "123" 123 ; Elt "string" 12 } + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - DUP (entry) @ location: 24 + [ { Elt "123" 123 ; Elt "string" 12 } + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/GET (exit) @ location: 24 + [ "abc" + { Elt "123" 123 ; Elt "string" 12 } + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - GET (entry) @ location: 26 + [ "abc" + { Elt "123" 123 ; Elt "string" 12 } + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/IF_NONE (exit) @ location: 26 + [ None + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - IF_NONE (entry) @ location: 27 + [ None + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/PUSH (exit) @ location: 27 + [ "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - PUSH (entry) @ location: 29 + [ "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/[halt] (exit) @ location: 29 + [ 0 + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 33 + [ 0 + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - control: KCons + - log/SWAP (exit) @ location: 27 + [ 0 + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - SWAP (entry) @ location: 33 + [ 0 + "abc" + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/DIP (exit) @ location: 33 + [ "abc" + 0 + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - DIP (entry) @ location: 34 + [ "abc" + 0 + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/ADD (exit) @ location: 34 + [ 0 + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - ADD (entry) @ location: 36 + [ 0 + 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/SOME (exit) @ location: 36 + [ 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - SOME (entry) @ location: 37 + [ 99 + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/[halt] (exit) @ location: 37 + [ (Some 99) + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 35 + [ (Some 99) + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - control: KUndip + - control: KCons + - log/UPDATE (exit) @ location: 34 + [ "abc" + (Some 99) + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - UPDATE (entry) @ location: 38 + [ "abc" + (Some 99) + { Elt "123" 123 ; Elt "string" 12 } + Unit ] + - log/[halt] (exit) @ location: 38 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 19 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - control: KIter + - log/UNPAIR (exit) @ location: 19 + [ (Pair "def" 3) + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - UNPAIR (entry) @ location: 21 + [ (Pair "def" 3) + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/DUP (exit) @ location: 21 + [ "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - DUP (entry) @ location: 22 + [ "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/DUP (exit) @ location: 22 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - DUP (entry) @ location: 24 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/GET (exit) @ location: 24 + [ "def" + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - GET (entry) @ location: 26 + [ "def" + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/IF_NONE (exit) @ location: 26 + [ None + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - IF_NONE (entry) @ location: 27 + [ None + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/PUSH (exit) @ location: 27 + [ "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - PUSH (entry) @ location: 29 + [ "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/[halt] (exit) @ location: 29 + [ 0 + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 33 + [ 0 + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - control: KCons + - log/SWAP (exit) @ location: 27 + [ 0 + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - SWAP (entry) @ location: 33 + [ 0 + "def" + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/DIP (exit) @ location: 33 + [ "def" + 0 + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - DIP (entry) @ location: 34 + [ "def" + 0 + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/ADD (exit) @ location: 34 + [ 0 + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - ADD (entry) @ location: 36 + [ 0 + 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/SOME (exit) @ location: 36 + [ 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - SOME (entry) @ location: 37 + [ 3 + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/[halt] (exit) @ location: 37 + [ (Some 3) + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 35 + [ (Some 3) + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - control: KUndip + - control: KCons + - log/UPDATE (exit) @ location: 34 + [ "def" + (Some 3) + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - UPDATE (entry) @ location: 38 + [ "def" + (Some 3) + { Elt "123" 123 ; Elt "abc" 99 ; Elt "string" 12 } + Unit ] + - log/[halt] (exit) @ location: 38 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } + Unit ] + - [halt] (entry) @ location: 19 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } + Unit ] + - control: KIter + - control: KCons + - log/PAIR (exit) @ location: 19 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } + Unit ] + - PAIR (entry) @ location: 39 + [ { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } + Unit ] + - log/NIL (exit) @ location: 39 + [ (Pair { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } Unit) ] + - NIL (entry) @ location: 40 + [ (Pair { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } Unit) ] + - log/PAIR (exit) @ location: 40 + [ {} + (Pair { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } Unit) ] + - PAIR (entry) @ location: 42 + [ {} + (Pair { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } Unit) ] + - log/[halt] (exit) @ location: 42 + [ (Pair {} { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } Unit) ] + - [halt] (entry) @ location: 13 + [ (Pair {} { Elt "123" 123 ; Elt "abc" 99 ; Elt "def" 3 ; Elt "string" 12 } Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/check_signature.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/check_signature.out new file mode 100644 index 000000000000..c817cebfc749 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/check_signature.out @@ -0,0 +1,230 @@ + +trace + - DUP (interp) @ location: 9 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - DUP (entry) @ location: 9 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/DUP (exit) @ location: 9 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - DUP (entry) @ location: 10 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/DIP (exit) @ location: 10 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - DIP (entry) @ location: 11 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/CDR (exit) @ location: 11 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - CDR (entry) @ location: 13 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/DUP (exit) @ location: 13 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - DUP (entry) @ location: 14 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/CAR (exit) @ location: 14 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - CAR (entry) @ location: 15 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/DIP (exit) @ location: 15 + [ "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - DIP (entry) @ location: 16 + [ "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/CDR (exit) @ location: 16 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - CDR (entry) @ location: 18 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/PACK (exit) @ location: 18 + [ "TEZOS" + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - PACK (entry) @ location: 19 + [ "TEZOS" + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/[halt] (exit) @ location: 19 + [ 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - [halt] (entry) @ location: 17 + [ 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 16 + [ "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - [halt] (entry) @ location: 12 + [ "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - control: KUndip + - control: KCons + - log/CAR (exit) @ location: 11 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - CAR (entry) @ location: 20 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/CHECK_SIGNATURE (exit) @ location: 20 + [ "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - CHECK_SIGNATURE (entry) @ location: 21 + [ "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + 0x05010000000554455a4f53 + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/IF (exit) @ location: 21 + [ True + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - IF (entry) @ location: 22 + [ True + (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/[halt] (exit) @ location: 22 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - [halt] (entry) @ location: 28 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - control: KCons + - log/CDR (exit) @ location: 22 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - CDR (entry) @ location: 28 + [ (Pair "[PUBLIC_KEY]" + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/NIL (exit) @ location: 28 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - NIL (entry) @ location: 29 + [ (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/PAIR (exit) @ location: 29 + [ {} + (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - PAIR (entry) @ location: 31 + [ {} + (Pair "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - log/[halt] (exit) @ location: 31 + [ (Pair {} + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - [halt] (entry) @ location: 8 + [ (Pair {} + "edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1" + "TEZOS") ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-get.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-get.out new file mode 100644 index 000000000000..f1ef1d79cf48 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-get.out @@ -0,0 +1,234 @@ + +trace + - CAR (interp) @ location: 11 + [ (Pair (Pair 1 4 2 Unit) Unit) ] + - CAR (entry) @ location: 11 + [ (Pair (Pair 1 4 2 Unit) Unit) ] + - log/DUP (exit) @ location: 11 + [ (Pair 1 4 2 Unit) ] + - DUP (entry) @ location: 12 + [ (Pair 1 4 2 Unit) ] + - log/CAR (exit) @ location: 12 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - CAR (entry) @ location: 13 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - log/PUSH (exit) @ location: 13 + [ 1 + (Pair 1 4 2 Unit) ] + - PUSH (entry) @ location: 14 + [ 1 + (Pair 1 4 2 Unit) ] + - log/COMPARE (exit) @ location: 14 + [ 1 + 1 + (Pair 1 4 2 Unit) ] + - COMPARE (entry) @ location: 19 + [ 1 + 1 + (Pair 1 4 2 Unit) ] + - log/EQ (exit) @ location: 19 + [ 0 + (Pair 1 4 2 Unit) ] + - EQ (entry) @ location: 20 + [ 0 + (Pair 1 4 2 Unit) ] + - log/IF (exit) @ location: 20 + [ True + (Pair 1 4 2 Unit) ] + - IF (entry) @ location: 21 + [ True + (Pair 1 4 2 Unit) ] + - log/[halt] (exit) @ location: 21 + [ (Pair 1 4 2 Unit) ] + - [halt] (entry) @ location: 27 + [ (Pair 1 4 2 Unit) ] + - control: KCons + - log/DUP (exit) @ location: 21 + [ (Pair 1 4 2 Unit) ] + - DUP (entry) @ location: 27 + [ (Pair 1 4 2 Unit) ] + - log/GET (exit) @ location: 27 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - GET (entry) @ location: 28 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - log/PUSH (exit) @ location: 28 + [ 1 + (Pair 1 4 2 Unit) ] + - PUSH (entry) @ location: 30 + [ 1 + (Pair 1 4 2 Unit) ] + - log/COMPARE (exit) @ location: 30 + [ 1 + 1 + (Pair 1 4 2 Unit) ] + - COMPARE (entry) @ location: 35 + [ 1 + 1 + (Pair 1 4 2 Unit) ] + - log/EQ (exit) @ location: 35 + [ 0 + (Pair 1 4 2 Unit) ] + - EQ (entry) @ location: 36 + [ 0 + (Pair 1 4 2 Unit) ] + - log/IF (exit) @ location: 36 + [ True + (Pair 1 4 2 Unit) ] + - IF (entry) @ location: 37 + [ True + (Pair 1 4 2 Unit) ] + - log/[halt] (exit) @ location: 37 + [ (Pair 1 4 2 Unit) ] + - [halt] (entry) @ location: 43 + [ (Pair 1 4 2 Unit) ] + - control: KCons + - log/DUP (exit) @ location: 37 + [ (Pair 1 4 2 Unit) ] + - DUP (entry) @ location: 43 + [ (Pair 1 4 2 Unit) ] + - log/GET (exit) @ location: 43 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - GET (entry) @ location: 44 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - log/PUSH (exit) @ location: 44 + [ 4 + (Pair 1 4 2 Unit) ] + - PUSH (entry) @ location: 46 + [ 4 + (Pair 1 4 2 Unit) ] + - log/COMPARE (exit) @ location: 46 + [ 4 + 4 + (Pair 1 4 2 Unit) ] + - COMPARE (entry) @ location: 51 + [ 4 + 4 + (Pair 1 4 2 Unit) ] + - log/EQ (exit) @ location: 51 + [ 0 + (Pair 1 4 2 Unit) ] + - EQ (entry) @ location: 52 + [ 0 + (Pair 1 4 2 Unit) ] + - log/IF (exit) @ location: 52 + [ True + (Pair 1 4 2 Unit) ] + - IF (entry) @ location: 53 + [ True + (Pair 1 4 2 Unit) ] + - log/[halt] (exit) @ location: 53 + [ (Pair 1 4 2 Unit) ] + - [halt] (entry) @ location: 59 + [ (Pair 1 4 2 Unit) ] + - control: KCons + - log/DUP (exit) @ location: 53 + [ (Pair 1 4 2 Unit) ] + - DUP (entry) @ location: 59 + [ (Pair 1 4 2 Unit) ] + - log/GET (exit) @ location: 59 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - GET (entry) @ location: 60 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - log/PUSH (exit) @ location: 60 + [ 2 + (Pair 1 4 2 Unit) ] + - PUSH (entry) @ location: 62 + [ 2 + (Pair 1 4 2 Unit) ] + - log/COMPARE (exit) @ location: 62 + [ 2 + 2 + (Pair 1 4 2 Unit) ] + - COMPARE (entry) @ location: 67 + [ 2 + 2 + (Pair 1 4 2 Unit) ] + - log/EQ (exit) @ location: 67 + [ 0 + (Pair 1 4 2 Unit) ] + - EQ (entry) @ location: 68 + [ 0 + (Pair 1 4 2 Unit) ] + - log/IF (exit) @ location: 68 + [ True + (Pair 1 4 2 Unit) ] + - IF (entry) @ location: 69 + [ True + (Pair 1 4 2 Unit) ] + - log/[halt] (exit) @ location: 69 + [ (Pair 1 4 2 Unit) ] + - [halt] (entry) @ location: 75 + [ (Pair 1 4 2 Unit) ] + - control: KCons + - log/DUP (exit) @ location: 69 + [ (Pair 1 4 2 Unit) ] + - DUP (entry) @ location: 75 + [ (Pair 1 4 2 Unit) ] + - log/GET (exit) @ location: 75 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - GET (entry) @ location: 76 + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - log/UNIT (exit) @ location: 76 + [ Unit + (Pair 1 4 2 Unit) ] + - UNIT (entry) @ location: 78 + [ Unit + (Pair 1 4 2 Unit) ] + - log/COMPARE (exit) @ location: 78 + [ Unit + Unit + (Pair 1 4 2 Unit) ] + - COMPARE (entry) @ location: 81 + [ Unit + Unit + (Pair 1 4 2 Unit) ] + - log/EQ (exit) @ location: 81 + [ 0 + (Pair 1 4 2 Unit) ] + - EQ (entry) @ location: 82 + [ 0 + (Pair 1 4 2 Unit) ] + - log/IF (exit) @ location: 82 + [ True + (Pair 1 4 2 Unit) ] + - IF (entry) @ location: 83 + [ True + (Pair 1 4 2 Unit) ] + - log/[halt] (exit) @ location: 83 + [ (Pair 1 4 2 Unit) ] + - [halt] (entry) @ location: 89 + [ (Pair 1 4 2 Unit) ] + - control: KCons + - log/DROP (exit) @ location: 83 + [ (Pair 1 4 2 Unit) ] + - DROP (entry) @ location: 89 + [ (Pair 1 4 2 Unit) ] + - log/UNIT (exit) @ location: 89 + [ ] + - UNIT (entry) @ location: 90 + [ ] + - log/NIL (exit) @ location: 90 + [ Unit ] + - NIL (entry) @ location: 91 + [ Unit ] + - log/PAIR (exit) @ location: 91 + [ {} + Unit ] + - PAIR (entry) @ location: 93 + [ {} + Unit ] + - log/[halt] (exit) @ location: 93 + [ (Pair {} Unit) ] + - [halt] (entry) @ location: 10 + [ (Pair {} Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-set.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-set.out new file mode 100644 index 000000000000..87ead45da454 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/comb-set.out @@ -0,0 +1,61 @@ + +trace + - CDR (interp) @ location: 11 + [ (Pair Unit 1 4 2 Unit) ] + - CDR (entry) @ location: 11 + [ (Pair Unit 1 4 2 Unit) ] + - log/PUSH (exit) @ location: 11 + [ (Pair 1 4 2 Unit) ] + - PUSH (entry) @ location: 12 + [ (Pair 1 4 2 Unit) ] + - log/UPDATE (exit) @ location: 12 + [ 2 + (Pair 1 4 2 Unit) ] + - UPDATE (entry) @ location: 15 + [ 2 + (Pair 1 4 2 Unit) ] + - log/PUSH (exit) @ location: 15 + [ (Pair 2 4 2 Unit) ] + - PUSH (entry) @ location: 17 + [ (Pair 2 4 2 Unit) ] + - log/UPDATE (exit) @ location: 17 + [ 12 + (Pair 2 4 2 Unit) ] + - UPDATE (entry) @ location: 20 + [ 12 + (Pair 2 4 2 Unit) ] + - log/PUSH (exit) @ location: 20 + [ (Pair 2 12 2 Unit) ] + - PUSH (entry) @ location: 22 + [ (Pair 2 12 2 Unit) ] + - log/UPDATE (exit) @ location: 22 + [ 8 + (Pair 2 12 2 Unit) ] + - UPDATE (entry) @ location: 25 + [ 8 + (Pair 2 12 2 Unit) ] + - log/UNIT (exit) @ location: 25 + [ (Pair 2 12 8 Unit) ] + - UNIT (entry) @ location: 27 + [ (Pair 2 12 8 Unit) ] + - log/UPDATE (exit) @ location: 27 + [ Unit + (Pair 2 12 8 Unit) ] + - UPDATE (entry) @ location: 28 + [ Unit + (Pair 2 12 8 Unit) ] + - log/NIL (exit) @ location: 28 + [ (Pair 2 12 8 Unit) ] + - NIL (entry) @ location: 30 + [ (Pair 2 12 8 Unit) ] + - log/PAIR (exit) @ location: 30 + [ {} + (Pair 2 12 8 Unit) ] + - PAIR (entry) @ location: 32 + [ {} + (Pair 2 12 8 Unit) ] + - log/[halt] (exit) @ location: 32 + [ (Pair {} 2 12 8 Unit) ] + - [halt] (entry) @ location: 10 + [ (Pair {} 2 12 8 Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/concat.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/concat.out new file mode 100644 index 000000000000..27c3dbb06237 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/concat.out @@ -0,0 +1,69 @@ + +trace + - DUP (interp) @ location: 7 + [ (Pair "abcd" "efgh") ] + - DUP (entry) @ location: 7 + [ (Pair "abcd" "efgh") ] + - log/DIP (exit) @ location: 7 + [ (Pair "abcd" "efgh") + (Pair "abcd" "efgh") ] + - DIP (entry) @ location: 8 + [ (Pair "abcd" "efgh") + (Pair "abcd" "efgh") ] + - log/CDR (exit) @ location: 8 + [ (Pair "abcd" "efgh") ] + - CDR (entry) @ location: 10 + [ (Pair "abcd" "efgh") ] + - log/NIL (exit) @ location: 10 + [ "efgh" ] + - NIL (entry) @ location: 11 + [ "efgh" ] + - log/SWAP (exit) @ location: 11 + [ {} + "efgh" ] + - SWAP (entry) @ location: 13 + [ {} + "efgh" ] + - log/CONS (exit) @ location: 13 + [ "efgh" + {} ] + - CONS (entry) @ location: 14 + [ "efgh" + {} ] + - log/[halt] (exit) @ location: 14 + [ { "efgh" } ] + - [halt] (entry) @ location: 9 + [ { "efgh" } ] + - control: KUndip + - control: KCons + - log/CAR (exit) @ location: 8 + [ (Pair "abcd" "efgh") + { "efgh" } ] + - CAR (entry) @ location: 15 + [ (Pair "abcd" "efgh") + { "efgh" } ] + - log/CONS (exit) @ location: 15 + [ "abcd" + { "efgh" } ] + - CONS (entry) @ location: 16 + [ "abcd" + { "efgh" } ] + - log/CONCAT (exit) @ location: 16 + [ { "abcd" ; "efgh" } ] + - CONCAT (entry) @ location: 17 + [ { "abcd" ; "efgh" } ] + - log/NIL (exit) @ location: 17 + [ "abcdefgh" ] + - NIL (entry) @ location: 18 + [ "abcdefgh" ] + - log/PAIR (exit) @ location: 18 + [ {} + "abcdefgh" ] + - PAIR (entry) @ location: 20 + [ {} + "abcdefgh" ] + - log/[halt] (exit) @ location: 20 + [ (Pair {} "abcdefgh") ] + - [halt] (entry) @ location: 6 + [ (Pair {} "abcdefgh") ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/conditionals.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/conditionals.out new file mode 100644 index 000000000000..cdf6a97298a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/conditionals.out @@ -0,0 +1,66 @@ + +trace + - CAR (interp) @ location: 10 + [ (Pair (Right (Some 23)) "") ] + - CAR (entry) @ location: 10 + [ (Pair (Right (Some 23)) "") ] + - log/IF_LEFT (exit) @ location: 10 + [ (Right (Some 23)) ] + - IF_LEFT (entry) @ location: 11 + [ (Right (Some 23)) ] + - log/IF_NONE (exit) @ location: 11 + [ (Some 23) ] + - IF_NONE (entry) @ location: 14 + [ (Some 23) ] + - log/PUSH (exit) @ location: 14 + [ 23 ] + - PUSH (entry) @ location: 20 + [ 23 ] + - log/COMPARE (exit) @ location: 20 + [ 0 + 23 ] + - COMPARE (entry) @ location: 24 + [ 0 + 23 ] + - log/GT (exit) @ location: 24 + [ -1 ] + - GT (entry) @ location: 25 + [ -1 ] + - log/IF (exit) @ location: 25 + [ False ] + - IF (entry) @ location: 26 + [ False ] + - log/PUSH (exit) @ location: 26 + [ ] + - PUSH (entry) @ location: 32 + [ ] + - log/[halt] (exit) @ location: 32 + [ "" ] + - [halt] (entry) @ location: 35 + [ "" ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ "" ] + - [halt] (entry) @ location: 35 + [ "" ] + - control: KCons + - log/[halt] (exit) @ location: 14 + [ "" ] + - [halt] (entry) @ location: 35 + [ "" ] + - control: KCons + - log/NIL (exit) @ location: 11 + [ "" ] + - NIL (entry) @ location: 35 + [ "" ] + - log/PAIR (exit) @ location: 35 + [ {} + "" ] + - PAIR (entry) @ location: 37 + [ {} + "" ] + - log/[halt] (exit) @ location: 37 + [ (Pair {} "") ] + - [halt] (entry) @ location: 9 + [ (Pair {} "") ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/cps_fact.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/cps_fact.out new file mode 100644 index 000000000000..aba8d782b457 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/cps_fact.out @@ -0,0 +1,276 @@ + +trace + - UNPAIR (interp) @ location: 7 + [ (Pair 2 60) ] + - UNPAIR (entry) @ location: 7 + [ (Pair 2 60) ] + - log/DIP (exit) @ location: 7 + [ 2 + 60 ] + - DIP (entry) @ location: 8 + [ 2 + 60 ] + - log/SELF (exit) @ location: 8 + [ 60 ] + - SELF (entry) @ location: 10 + [ 60 ] + - log/ADDRESS (exit) @ location: 10 + [ "[CONTRACT_HASH]" + 60 ] + - ADDRESS (entry) @ location: 11 + [ "[CONTRACT_HASH]" + 60 ] + - log/SENDER (exit) @ location: 11 + [ "[CONTRACT_HASH]" + 60 ] + - SENDER (entry) @ location: 12 + [ "[CONTRACT_HASH]" + 60 ] + - log/COMPARE (exit) @ location: 12 + [ "[PUBLIC_KEY_HASH]" + "[CONTRACT_HASH]" + 60 ] + - COMPARE (entry) @ location: 14 + [ "[PUBLIC_KEY_HASH]" + "[CONTRACT_HASH]" + 60 ] + - log/EQ (exit) @ location: 14 + [ -1 + 60 ] + - EQ (entry) @ location: 15 + [ -1 + 60 ] + - log/IF (exit) @ location: 15 + [ False + 60 ] + - IF (entry) @ location: 16 + [ False + 60 ] + - log/DROP (exit) @ location: 16 + [ 60 ] + - DROP (entry) @ location: 19 + [ 60 ] + - log/PUSH (exit) @ location: 19 + [ ] + - PUSH (entry) @ location: 20 + [ ] + - log/[halt] (exit) @ location: 20 + [ 1 ] + - [halt] (entry) @ location: 9 + [ 1 ] + - control: KCons + - log/[halt] (exit) @ location: 16 + [ 1 ] + - [halt] (entry) @ location: 9 + [ 1 ] + - control: KUndip + - control: KCons + - log/DUP (exit) @ location: 8 + [ 2 + 1 ] + - DUP (entry) @ location: 23 + [ 2 + 1 ] + - log/PUSH (exit) @ location: 23 + [ 2 + 2 + 1 ] + - PUSH (entry) @ location: 24 + [ 2 + 2 + 1 ] + - log/COMPARE (exit) @ location: 24 + [ 1 + 2 + 2 + 1 ] + - COMPARE (entry) @ location: 28 + [ 1 + 2 + 2 + 1 ] + - log/GE (exit) @ location: 28 + [ -1 + 2 + 1 ] + - GE (entry) @ location: 29 + [ -1 + 2 + 1 ] + - log/IF (exit) @ location: 29 + [ False + 2 + 1 ] + - IF (entry) @ location: 30 + [ False + 2 + 1 ] + - log/PUSH (exit) @ location: 30 + [ 2 + 1 ] + - PUSH (entry) @ location: 37 + [ 2 + 1 ] + - log/SWAP (exit) @ location: 37 + [ 1 + 2 + 1 ] + - SWAP (entry) @ location: 40 + [ 1 + 2 + 1 ] + - log/SUB (exit) @ location: 40 + [ 2 + 1 + 1 ] + - SUB (entry) @ location: 41 + [ 2 + 1 + 1 ] + - log/ISNAT (exit) @ location: 41 + [ 1 + 1 ] + - ISNAT (entry) @ location: 42 + [ 1 + 1 ] + - log/IF_NONE (exit) @ location: 42 + [ (Some 1) + 1 ] + - IF_NONE (entry) @ location: 43 + [ (Some 1) + 1 ] + - log/DUP (exit) @ location: 43 + [ 1 + 1 ] + - DUP (entry) @ location: 49 + [ 1 + 1 ] + - log/DIP (exit) @ location: 49 + [ 1 + 1 + 1 ] + - DIP (entry) @ location: 50 + [ 1 + 1 + 1 ] + - log/PUSH (exit) @ location: 50 + [ 1 + 1 ] + - PUSH (entry) @ location: 52 + [ 1 + 1 ] + - log/ADD (exit) @ location: 52 + [ 1 + 1 + 1 ] + - ADD (entry) @ location: 55 + [ 1 + 1 + 1 ] + - log/MUL (exit) @ location: 55 + [ 2 + 1 ] + - MUL (entry) @ location: 56 + [ 2 + 1 ] + - log/[halt] (exit) @ location: 56 + [ 2 ] + - [halt] (entry) @ location: 51 + [ 2 ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 50 + [ 1 + 2 ] + - SWAP (entry) @ location: 57 + [ 1 + 2 ] + - log/DIP (exit) @ location: 57 + [ 2 + 1 ] + - DIP (entry) @ location: 58 + [ 2 + 1 ] + - log/DIP (exit) @ location: 58 + [ 1 ] + - DIP (entry) @ location: 60 + [ 1 ] + - log/SELF (exit) @ location: 60 + [ ] + - SELF (entry) @ location: 62 + [ ] + - log/PUSH (exit) @ location: 62 + [ "[CONTRACT_HASH]" ] + - PUSH (entry) @ location: 63 + [ "[CONTRACT_HASH]" ] + - log/[halt] (exit) @ location: 63 + [ 0 + "[CONTRACT_HASH]" ] + - [halt] (entry) @ location: 61 + [ 0 + "[CONTRACT_HASH]" ] + - control: KUndip + - control: KCons + - log/TRANSFER_TOKENS (exit) @ location: 60 + [ 1 + 0 + "[CONTRACT_HASH]" ] + - TRANSFER_TOKENS (entry) @ location: 66 + [ 1 + 0 + "[CONTRACT_HASH]" ] + - log/NIL (exit) @ location: 66 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 ] + - NIL (entry) @ location: 67 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 ] + - log/SWAP (exit) @ location: 67 + [ {} + 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 ] + - SWAP (entry) @ location: 69 + [ {} + 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 ] + - log/CONS (exit) @ location: 69 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 + {} ] + - CONS (entry) @ location: 70 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 + {} ] + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } ] + - [halt] (entry) @ location: 59 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 58 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } ] + - SWAP (entry) @ location: 71 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } ] + - log/PAIR (exit) @ location: 71 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2 ] + - PAIR (entry) @ location: 72 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2 ] + - log/[halt] (exit) @ location: 72 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2) ] + - [halt] (entry) @ location: 6 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2) ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2) ] + - [halt] (entry) @ location: 6 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2) ] + - control: KCons + - log/[halt] (exit) @ location: 30 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2) ] + - [halt] (entry) @ location: 6 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf502875890000000100014828e9aa0b3e6e970da0515b5c5d8ccf5028758900ff00000000020001 } + 2) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dign.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dign.out new file mode 100644 index 000000000000..298723394bff --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dign.out @@ -0,0 +1,107 @@ + +trace + - CAR (interp) @ location: 15 + [ (Pair (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) 7) ] + - CAR (entry) @ location: 15 + [ (Pair (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) 7) ] + - log/UNPAIR (exit) @ location: 15 + [ (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) ] + - UNPAIR (entry) @ location: 16 + [ (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) ] + - log/UNPAIR (exit) @ location: 16 + [ (Pair (Pair (Pair 0 1) 2) 3) + 4 ] + - UNPAIR (entry) @ location: 17 + [ (Pair (Pair (Pair 0 1) 2) 3) + 4 ] + - log/UNPAIR (exit) @ location: 17 + [ (Pair (Pair 0 1) 2) + 3 + 4 ] + - UNPAIR (entry) @ location: 18 + [ (Pair (Pair 0 1) 2) + 3 + 4 ] + - log/UNPAIR (exit) @ location: 18 + [ (Pair 0 1) + 2 + 3 + 4 ] + - UNPAIR (entry) @ location: 19 + [ (Pair 0 1) + 2 + 3 + 4 ] + - log/DIG (exit) @ location: 19 + [ 0 + 1 + 2 + 3 + 4 ] + - DIG (entry) @ location: 20 + [ 0 + 1 + 2 + 3 + 4 ] + - log/DIP (exit) @ location: 20 + [ 4 + 0 + 1 + 2 + 3 ] + - DIP (entry) @ location: 22 + [ 4 + 0 + 1 + 2 + 3 ] + - log/DROP (exit) @ location: 22 + [ 0 + 1 + 2 + 3 ] + - DROP (entry) @ location: 24 + [ 0 + 1 + 2 + 3 ] + - log/DROP (exit) @ location: 24 + [ 1 + 2 + 3 ] + - DROP (entry) @ location: 25 + [ 1 + 2 + 3 ] + - log/DROP (exit) @ location: 25 + [ 2 + 3 ] + - DROP (entry) @ location: 26 + [ 2 + 3 ] + - log/DROP (exit) @ location: 26 + [ 3 ] + - DROP (entry) @ location: 27 + [ 3 ] + - log/[halt] (exit) @ location: 27 + [ ] + - [halt] (entry) @ location: 23 + [ ] + - control: KUndip + - control: KCons + - log/NIL (exit) @ location: 22 + [ 4 ] + - NIL (entry) @ location: 28 + [ 4 ] + - log/PAIR (exit) @ location: 28 + [ {} + 4 ] + - PAIR (entry) @ location: 30 + [ {} + 4 ] + - log/[halt] (exit) @ location: 30 + [ (Pair {} 4) ] + - [halt] (entry) @ location: 14 + [ (Pair {} 4) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dipn.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dipn.out new file mode 100644 index 000000000000..25b7ac28edbb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dipn.out @@ -0,0 +1,119 @@ + +trace + - CAR (interp) @ location: 15 + [ (Pair (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) 7) ] + - CAR (entry) @ location: 15 + [ (Pair (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) 7) ] + - log/UNPAIR (exit) @ location: 15 + [ (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) ] + - UNPAIR (entry) @ location: 16 + [ (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) ] + - log/UNPAIR (exit) @ location: 16 + [ (Pair (Pair (Pair 0 1) 2) 3) + 4 ] + - UNPAIR (entry) @ location: 17 + [ (Pair (Pair (Pair 0 1) 2) 3) + 4 ] + - log/UNPAIR (exit) @ location: 17 + [ (Pair (Pair 0 1) 2) + 3 + 4 ] + - UNPAIR (entry) @ location: 18 + [ (Pair (Pair 0 1) 2) + 3 + 4 ] + - log/UNPAIR (exit) @ location: 18 + [ (Pair 0 1) + 2 + 3 + 4 ] + - UNPAIR (entry) @ location: 19 + [ (Pair 0 1) + 2 + 3 + 4 ] + - log/DIP (exit) @ location: 19 + [ 0 + 1 + 2 + 3 + 4 ] + - DIP (entry) @ location: 20 + [ 0 + 1 + 2 + 3 + 4 ] + - log/PUSH (exit) @ location: 20 + [ ] + - PUSH (entry) @ location: 23 + [ ] + - log/[halt] (exit) @ location: 23 + [ 6 ] + - [halt] (entry) @ location: 23 + [ 6 ] + - log/DROP (exit) @ location: 20 + [ 0 + 1 + 2 + 3 + 4 + 6 ] + - DROP (entry) @ location: 26 + [ 0 + 1 + 2 + 3 + 4 + 6 ] + - log/DROP (exit) @ location: 26 + [ 1 + 2 + 3 + 4 + 6 ] + - DROP (entry) @ location: 27 + [ 1 + 2 + 3 + 4 + 6 ] + - log/DROP (exit) @ location: 27 + [ 2 + 3 + 4 + 6 ] + - DROP (entry) @ location: 28 + [ 2 + 3 + 4 + 6 ] + - log/DROP (exit) @ location: 28 + [ 3 + 4 + 6 ] + - DROP (entry) @ location: 29 + [ 3 + 4 + 6 ] + - log/DROP (exit) @ location: 29 + [ 4 + 6 ] + - DROP (entry) @ location: 30 + [ 4 + 6 ] + - log/NIL (exit) @ location: 30 + [ 6 ] + - NIL (entry) @ location: 31 + [ 6 ] + - log/PAIR (exit) @ location: 31 + [ {} + 6 ] + - PAIR (entry) @ location: 33 + [ {} + 6 ] + - log/[halt] (exit) @ location: 33 + [ (Pair {} 6) ] + - [halt] (entry) @ location: 14 + [ (Pair {} 6) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dugn.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dugn.out new file mode 100644 index 000000000000..b782243a82af --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/dugn.out @@ -0,0 +1,97 @@ + +trace + - CAR (interp) @ location: 15 + [ (Pair (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) 7) ] + - CAR (entry) @ location: 15 + [ (Pair (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) 7) ] + - log/UNPAIR (exit) @ location: 15 + [ (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) ] + - UNPAIR (entry) @ location: 16 + [ (Pair (Pair (Pair (Pair 0 1) 2) 3) 4) ] + - log/UNPAIR (exit) @ location: 16 + [ (Pair (Pair (Pair 0 1) 2) 3) + 4 ] + - UNPAIR (entry) @ location: 17 + [ (Pair (Pair (Pair 0 1) 2) 3) + 4 ] + - log/UNPAIR (exit) @ location: 17 + [ (Pair (Pair 0 1) 2) + 3 + 4 ] + - UNPAIR (entry) @ location: 18 + [ (Pair (Pair 0 1) 2) + 3 + 4 ] + - log/UNPAIR (exit) @ location: 18 + [ (Pair 0 1) + 2 + 3 + 4 ] + - UNPAIR (entry) @ location: 19 + [ (Pair 0 1) + 2 + 3 + 4 ] + - log/DUG (exit) @ location: 19 + [ 0 + 1 + 2 + 3 + 4 ] + - DUG (entry) @ location: 20 + [ 0 + 1 + 2 + 3 + 4 ] + - log/DROP (exit) @ location: 20 + [ 1 + 2 + 3 + 4 + 0 ] + - DROP (entry) @ location: 22 + [ 1 + 2 + 3 + 4 + 0 ] + - log/DROP (exit) @ location: 22 + [ 2 + 3 + 4 + 0 ] + - DROP (entry) @ location: 23 + [ 2 + 3 + 4 + 0 ] + - log/DROP (exit) @ location: 23 + [ 3 + 4 + 0 ] + - DROP (entry) @ location: 24 + [ 3 + 4 + 0 ] + - log/DROP (exit) @ location: 24 + [ 4 + 0 ] + - DROP (entry) @ location: 25 + [ 4 + 0 ] + - log/NIL (exit) @ location: 25 + [ 0 ] + - NIL (entry) @ location: 26 + [ 0 ] + - log/PAIR (exit) @ location: 26 + [ {} + 0 ] + - PAIR (entry) @ location: 28 + [ {} + 0 ] + - log/[halt] (exit) @ location: 28 + [ (Pair {} 0) ] + - [halt] (entry) @ location: 14 + [ (Pair {} 0) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ediv.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ediv.out new file mode 100644 index 000000000000..39930f26e25b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ediv.out @@ -0,0 +1,259 @@ + +trace + - CAR (interp) @ location: 25 + [ (Pair (Pair 127 11) None None None None) ] + - CAR (entry) @ location: 25 + [ (Pair (Pair 127 11) None None None None) ] + - log/DUP (exit) @ location: 25 + [ (Pair 127 11) ] + - DUP (entry) @ location: 26 + [ (Pair 127 11) ] + - log/UNPAIR (exit) @ location: 26 + [ (Pair 127 11) + (Pair 127 11) ] + - UNPAIR (entry) @ location: 27 + [ (Pair 127 11) + (Pair 127 11) ] + - log/ABS (exit) @ location: 27 + [ 127 + 11 + (Pair 127 11) ] + - ABS (entry) @ location: 28 + [ 127 + 11 + (Pair 127 11) ] + - log/DIP (exit) @ location: 28 + [ 127 + 11 + (Pair 127 11) ] + - DIP (entry) @ location: 29 + [ 127 + 11 + (Pair 127 11) ] + - log/ABS (exit) @ location: 29 + [ 11 + (Pair 127 11) ] + - ABS (entry) @ location: 31 + [ 11 + (Pair 127 11) ] + - log/[halt] (exit) @ location: 31 + [ 11 + (Pair 127 11) ] + - [halt] (entry) @ location: 31 + [ 11 + (Pair 127 11) ] + - control: KUndip + - control: KCons + - log/EDIV (exit) @ location: 29 + [ 127 + 11 + (Pair 127 11) ] + - EDIV (entry) @ location: 32 + [ 127 + 11 + (Pair 127 11) ] + - log/SWAP (exit) @ location: 32 + [ (Some (Pair 11 6)) + (Pair 127 11) ] + - SWAP (entry) @ location: 33 + [ (Some (Pair 11 6)) + (Pair 127 11) ] + - log/DUP (exit) @ location: 33 + [ (Pair 127 11) + (Some (Pair 11 6)) ] + - DUP (entry) @ location: 34 + [ (Pair 127 11) + (Some (Pair 11 6)) ] + - log/UNPAIR (exit) @ location: 34 + [ (Pair 127 11) + (Pair 127 11) + (Some (Pair 11 6)) ] + - UNPAIR (entry) @ location: 35 + [ (Pair 127 11) + (Pair 127 11) + (Some (Pair 11 6)) ] + - log/ABS (exit) @ location: 35 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) ] + - ABS (entry) @ location: 36 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) ] + - log/EDIV (exit) @ location: 36 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) ] + - EDIV (entry) @ location: 37 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) ] + - log/SWAP (exit) @ location: 37 + [ (Some (Pair 11 6)) + (Pair 127 11) + (Some (Pair 11 6)) ] + - SWAP (entry) @ location: 38 + [ (Some (Pair 11 6)) + (Pair 127 11) + (Some (Pair 11 6)) ] + - log/DUP (exit) @ location: 38 + [ (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - DUP (entry) @ location: 39 + [ (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/UNPAIR (exit) @ location: 39 + [ (Pair 127 11) + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - UNPAIR (entry) @ location: 40 + [ (Pair 127 11) + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/DIP (exit) @ location: 40 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - DIP (entry) @ location: 41 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/ABS (exit) @ location: 41 + [ 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - ABS (entry) @ location: 43 + [ 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/[halt] (exit) @ location: 43 + [ 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - [halt] (entry) @ location: 43 + [ 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - control: KUndip + - control: KCons + - log/EDIV (exit) @ location: 41 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - EDIV (entry) @ location: 44 + [ 127 + 11 + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/SWAP (exit) @ location: 44 + [ (Some (Pair 11 6)) + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - SWAP (entry) @ location: 45 + [ (Some (Pair 11 6)) + (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/UNPAIR (exit) @ location: 45 + [ (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - UNPAIR (entry) @ location: 46 + [ (Pair 127 11) + (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/EDIV (exit) @ location: 46 + [ 127 + 11 + (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - EDIV (entry) @ location: 47 + [ 127 + 11 + (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/DIP (exit) @ location: 47 + [ (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - DIP (entry) @ location: 49 + [ (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/PAIR (exit) @ location: 49 + [ (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - PAIR (entry) @ location: 52 + [ (Some (Pair 11 6)) + (Some (Pair 11 6)) ] + - log/[halt] (exit) @ location: 52 + [ (Pair (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - [halt] (entry) @ location: 52 + [ (Pair (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - log/DIP (exit) @ location: 49 + [ (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Pair (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - DIP (entry) @ location: 53 + [ (Some (Pair 11 6)) + (Some (Pair 11 6)) + (Pair (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - log/PAIR (exit) @ location: 53 + [ (Some (Pair 11 6)) + (Pair (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - PAIR (entry) @ location: 55 + [ (Some (Pair 11 6)) + (Pair (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - log/[halt] (exit) @ location: 55 + [ (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - [halt] (entry) @ location: 55 + [ (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - control: KUndip + - control: KCons + - log/PAIR (exit) @ location: 53 + [ (Some (Pair 11 6)) + (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - PAIR (entry) @ location: 56 + [ (Some (Pair 11 6)) + (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - log/NIL (exit) @ location: 56 + [ (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - NIL (entry) @ location: 57 + [ (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - log/PAIR (exit) @ location: 57 + [ {} + (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - PAIR (entry) @ location: 59 + [ {} + (Pair (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - log/[halt] (exit) @ location: 59 + [ (Pair {} (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - [halt] (entry) @ location: 24 + [ (Pair {} (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6)) (Some (Pair 11 6))) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/faucet.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/faucet.out new file mode 100644 index 000000000000..6909d0ea978a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/faucet.out @@ -0,0 +1,122 @@ + +trace + - UNPAIR (interp) @ location: 7 + [ (Pair "[PUBLIC_KEY_HASH]" "[TIMESTAMP]") ] + - UNPAIR (entry) @ location: 7 + [ (Pair "[PUBLIC_KEY_HASH]" "[TIMESTAMP]") ] + - log/SWAP (exit) @ location: 7 + [ "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" ] + - SWAP (entry) @ location: 8 + [ "[PUBLIC_KEY_HASH]" + "[TIMESTAMP]" ] + - log/PUSH (exit) @ location: 8 + [ "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - PUSH (entry) @ location: 9 + [ "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - log/ADD (exit) @ location: 9 + [ 300 + "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - ADD (entry) @ location: 12 + [ 300 + "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - log/NOW (exit) @ location: 12 + [ "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - NOW (entry) @ location: 13 + [ "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - log/COMPARE (exit) @ location: 13 + [ "[TIMESTAMP]" + "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - COMPARE (entry) @ location: 16 + [ "[TIMESTAMP]" + "[TIMESTAMP]" + "[PUBLIC_KEY_HASH]" ] + - log/GE (exit) @ location: 16 + [ 1 + "[PUBLIC_KEY_HASH]" ] + - GE (entry) @ location: 17 + [ 1 + "[PUBLIC_KEY_HASH]" ] + - log/IF (exit) @ location: 17 + [ True + "[PUBLIC_KEY_HASH]" ] + - IF (entry) @ location: 18 + [ True + "[PUBLIC_KEY_HASH]" ] + - log/[halt] (exit) @ location: 18 + [ "[PUBLIC_KEY_HASH]" ] + - [halt] (entry) @ location: 24 + [ "[PUBLIC_KEY_HASH]" ] + - control: KCons + - log/IMPLICIT_ACCOUNT (exit) @ location: 18 + [ "[PUBLIC_KEY_HASH]" ] + - IMPLICIT_ACCOUNT (entry) @ location: 24 + [ "[PUBLIC_KEY_HASH]" ] + - log/PUSH (exit) @ location: 24 + [ "[PUBLIC_KEY_HASH]" ] + - PUSH (entry) @ location: 25 + [ "[PUBLIC_KEY_HASH]" ] + - log/UNIT (exit) @ location: 25 + [ 1000000 + "[PUBLIC_KEY_HASH]" ] + - UNIT (entry) @ location: 28 + [ 1000000 + "[PUBLIC_KEY_HASH]" ] + - log/TRANSFER_TOKENS (exit) @ location: 28 + [ Unit + 1000000 + "[PUBLIC_KEY_HASH]" ] + - TRANSFER_TOKENS (entry) @ location: 29 + [ Unit + 1000000 + "[PUBLIC_KEY_HASH]" ] + - log/NIL (exit) @ location: 29 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 ] + - NIL (entry) @ location: 30 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 ] + - log/SWAP (exit) @ location: 30 + [ {} + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 ] + - SWAP (entry) @ location: 32 + [ {} + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 ] + - log/CONS (exit) @ location: 32 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + {} ] + - CONS (entry) @ location: 33 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 + {} ] + - log/DIP (exit) @ location: 33 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } ] + - DIP (entry) @ location: 34 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } ] + - log/NOW (exit) @ location: 34 + [ ] + - NOW (entry) @ location: 36 + [ ] + - log/[halt] (exit) @ location: 36 + [ "[TIMESTAMP]" ] + - [halt] (entry) @ location: 36 + [ "[TIMESTAMP]" ] + - control: KUndip + - control: KCons + - log/PAIR (exit) @ location: 34 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + "[TIMESTAMP]" ] + - PAIR (entry) @ location: 37 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + "[TIMESTAMP]" ] + - log/[halt] (exit) @ location: 37 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + "[TIMESTAMP]") ] + - [halt] (entry) @ location: 6 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000001c0843d0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd600 } + "[TIMESTAMP]") ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/get_and_update_map.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/get_and_update_map.out new file mode 100644 index 000000000000..43f1a2d3b72d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/get_and_update_map.out @@ -0,0 +1,53 @@ + +trace + - UNPAIR (interp) @ location: 13 + [ (Pair "abc" (Some 321) { Elt "def" 123 }) ] + - UNPAIR (entry) @ location: 13 + [ (Pair "abc" (Some 321) { Elt "def" 123 }) ] + - log/DIP (exit) @ location: 13 + [ "abc" + (Pair (Some 321) { Elt "def" 123 }) ] + - DIP (entry) @ location: 14 + [ "abc" + (Pair (Some 321) { Elt "def" 123 }) ] + - log/UNPAIR (exit) @ location: 14 + [ (Pair (Some 321) { Elt "def" 123 }) ] + - UNPAIR (entry) @ location: 16 + [ (Pair (Some 321) { Elt "def" 123 }) ] + - log/[halt] (exit) @ location: 16 + [ (Some 321) + { Elt "def" 123 } ] + - [halt] (entry) @ location: 16 + [ (Some 321) + { Elt "def" 123 } ] + - control: KUndip + - control: KCons + - log/GET_AND_UPDATE (exit) @ location: 14 + [ "abc" + (Some 321) + { Elt "def" 123 } ] + - GET_AND_UPDATE (entry) @ location: 17 + [ "abc" + (Some 321) + { Elt "def" 123 } ] + - log/PAIR (exit) @ location: 17 + [ None + { Elt "abc" 321 ; Elt "def" 123 } ] + - PAIR (entry) @ location: 18 + [ None + { Elt "abc" 321 ; Elt "def" 123 } ] + - log/NIL (exit) @ location: 18 + [ (Pair None { Elt "abc" 321 ; Elt "def" 123 }) ] + - NIL (entry) @ location: 19 + [ (Pair None { Elt "abc" 321 ; Elt "def" 123 }) ] + - log/PAIR (exit) @ location: 19 + [ {} + (Pair None { Elt "abc" 321 ; Elt "def" 123 }) ] + - PAIR (entry) @ location: 21 + [ {} + (Pair None { Elt "abc" 321 ; Elt "def" 123 }) ] + - log/[halt] (exit) @ location: 21 + [ (Pair {} None { Elt "abc" 321 ; Elt "def" 123 }) ] + - [halt] (entry) @ location: 11 + [ (Pair {} None { Elt "abc" 321 ; Elt "def" 123 }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/if.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/if.out new file mode 100644 index 000000000000..ab18612e58e6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/if.out @@ -0,0 +1,38 @@ + +trace + - CAR (interp) @ location: 8 + [ (Pair True None) ] + - CAR (entry) @ location: 8 + [ (Pair True None) ] + - log/IF (exit) @ location: 8 + [ True ] + - IF (entry) @ location: 9 + [ True ] + - log/PUSH (exit) @ location: 9 + [ ] + - PUSH (entry) @ location: 11 + [ ] + - log/[halt] (exit) @ location: 11 + [ True ] + - [halt] (entry) @ location: 18 + [ True ] + - control: KCons + - log/SOME (exit) @ location: 9 + [ True ] + - SOME (entry) @ location: 18 + [ True ] + - log/NIL (exit) @ location: 18 + [ (Some True) ] + - NIL (entry) @ location: 19 + [ (Some True) ] + - log/PAIR (exit) @ location: 19 + [ {} + (Some True) ] + - PAIR (entry) @ location: 21 + [ {} + (Some True) ] + - log/[halt] (exit) @ location: 21 + [ (Pair {} (Some True)) ] + - [halt] (entry) @ location: 7 + [ (Pair {} (Some True)) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/insertion_sort.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/insertion_sort.out new file mode 100644 index 000000000000..a0657a59ef13 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/insertion_sort.out @@ -0,0 +1,5949 @@ + +trace + - CAR (interp) @ location: 9 + [ (Pair { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } {}) ] + - CAR (entry) @ location: 9 + [ (Pair { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } {}) ] + - log/NIL (exit) @ location: 9 + [ { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } ] + - NIL (entry) @ location: 10 + [ { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } ] + - log/SWAP (exit) @ location: 10 + [ {} + { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } ] + - SWAP (entry) @ location: 12 + [ {} + { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } ] + - log/ITER (exit) @ location: 12 + [ { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } + {} ] + - ITER (entry) @ location: 13 + [ { 8 ; 3 ; 2 ; 7 ; 6 ; 9 ; 5 ; 1 ; 4 ; 0 } + {} ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 8 + {} ] + - SWAP (entry) @ location: 15 + [ 8 + {} ] + - log/DIP (exit) @ location: 15 + [ {} + 8 ] + - DIP (entry) @ location: 16 + [ {} + 8 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ {} + 8 + {} ] + - PUSH (entry) @ location: 21 + [ {} + 8 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + {} + 8 + {} ] + - LOOP (entry) @ location: 66 + [ True + {} + 8 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ {} + 8 + {} ] + - IF_CONS (entry) @ location: 26 + [ {} + 8 + {} ] + - log/NIL (exit) @ location: 26 + [ 8 + {} ] + - NIL (entry) @ location: 61 + [ 8 + {} ] + - log/PUSH (exit) @ location: 61 + [ {} + 8 + {} ] + - PUSH (entry) @ location: 63 + [ {} + 8 + {} ] + - log/[halt] (exit) @ location: 63 + [ False + {} + 8 + {} ] + - [halt] (entry) @ location: 66 + [ False + {} + 8 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + {} + 8 + {} ] + - [halt] (entry) @ location: 66 + [ False + {} + 8 + {} ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ {} + 8 + {} ] + - SWAP (entry) @ location: 66 + [ {} + 8 + {} ] + - log/CONS (exit) @ location: 66 + [ 8 + {} + {} ] + - CONS (entry) @ location: 67 + [ 8 + {} + {} ] + - log/SWAP (exit) @ location: 67 + [ { 8 } + {} ] + - SWAP (entry) @ location: 68 + [ { 8 } + {} ] + - log/ITER (exit) @ location: 68 + [ {} + { 8 } ] + - ITER (entry) @ location: 69 + [ {} + { 8 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 8 } ] + - [halt] (entry) @ location: 13 + [ { 8 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 3 + { 8 } ] + - SWAP (entry) @ location: 15 + [ 3 + { 8 } ] + - log/DIP (exit) @ location: 15 + [ { 8 } + 3 ] + - DIP (entry) @ location: 16 + [ { 8 } + 3 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 8 } + 3 + {} ] + - PUSH (entry) @ location: 21 + [ { 8 } + 3 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 8 } + 3 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 8 } + 3 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 8 } + 3 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 8 } + 3 + {} ] + - log/SWAP (exit) @ location: 26 + [ 8 + {} + 3 + {} ] + - SWAP (entry) @ location: 28 + [ 8 + {} + 3 + {} ] + - log/DIP (exit) @ location: 28 + [ {} + 8 + 3 + {} ] + - DIP (entry) @ location: 29 + [ {} + 8 + 3 + {} ] + - log/DUP (exit) @ location: 29 + [ 8 + 3 + {} ] + - DUP (entry) @ location: 31 + [ 8 + 3 + {} ] + - log/DIP (exit) @ location: 31 + [ 8 + 8 + 3 + {} ] + - DIP (entry) @ location: 32 + [ 8 + 8 + 3 + {} ] + - log/DUP (exit) @ location: 32 + [ 3 + {} ] + - DUP (entry) @ location: 35 + [ 3 + {} ] + - log/[halt] (exit) @ location: 35 + [ 3 + 3 + {} ] + - [halt] (entry) @ location: 35 + [ 3 + 3 + {} ] + - log/DIP (exit) @ location: 32 + [ 8 + 8 + 3 + 3 + {} ] + - DIP (entry) @ location: 36 + [ 8 + 8 + 3 + 3 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 8 + 3 + 3 + {} ] + - COMPARE (entry) @ location: 39 + [ 8 + 3 + 3 + {} ] + - log/LT (exit) @ location: 39 + [ 1 + 3 + {} ] + - LT (entry) @ location: 40 + [ 1 + 3 + {} ] + - log/[halt] (exit) @ location: 40 + [ False + 3 + {} ] + - [halt] (entry) @ location: 38 + [ False + 3 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 8 + False + 3 + {} ] + - SWAP (entry) @ location: 41 + [ 8 + False + 3 + {} ] + - log/[halt] (exit) @ location: 41 + [ False + 8 + 3 + {} ] + - [halt] (entry) @ location: 30 + [ False + 8 + 3 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ {} + False + 8 + 3 + {} ] + - SWAP (entry) @ location: 42 + [ {} + False + 8 + 3 + {} ] + - log/IF (exit) @ location: 42 + [ False + {} + 8 + 3 + {} ] + - IF (entry) @ location: 43 + [ False + {} + 8 + 3 + {} ] + - log/SWAP (exit) @ location: 43 + [ {} + 8 + 3 + {} ] + - SWAP (entry) @ location: 55 + [ {} + 8 + 3 + {} ] + - log/CONS (exit) @ location: 55 + [ 8 + {} + 3 + {} ] + - CONS (entry) @ location: 56 + [ 8 + {} + 3 + {} ] + - log/PUSH (exit) @ location: 56 + [ { 8 } + 3 + {} ] + - PUSH (entry) @ location: 57 + [ { 8 } + 3 + {} ] + - log/[halt] (exit) @ location: 57 + [ False + { 8 } + 3 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 8 } + 3 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 8 } + 3 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 8 } + 3 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 8 } + 3 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 8 } + 3 + {} ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 8 } + 3 + {} ] + - SWAP (entry) @ location: 66 + [ { 8 } + 3 + {} ] + - log/CONS (exit) @ location: 66 + [ 3 + { 8 } + {} ] + - CONS (entry) @ location: 67 + [ 3 + { 8 } + {} ] + - log/SWAP (exit) @ location: 67 + [ { 3 ; 8 } + {} ] + - SWAP (entry) @ location: 68 + [ { 3 ; 8 } + {} ] + - log/ITER (exit) @ location: 68 + [ {} + { 3 ; 8 } ] + - ITER (entry) @ location: 69 + [ {} + { 3 ; 8 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 3 ; 8 } ] + - [halt] (entry) @ location: 13 + [ { 3 ; 8 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 2 + { 3 ; 8 } ] + - SWAP (entry) @ location: 15 + [ 2 + { 3 ; 8 } ] + - log/DIP (exit) @ location: 15 + [ { 3 ; 8 } + 2 ] + - DIP (entry) @ location: 16 + [ { 3 ; 8 } + 2 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 3 ; 8 } + 2 + {} ] + - PUSH (entry) @ location: 21 + [ { 3 ; 8 } + 2 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 3 ; 8 } + 2 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 3 ; 8 } + 2 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 3 ; 8 } + 2 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 3 ; 8 } + 2 + {} ] + - log/SWAP (exit) @ location: 26 + [ 3 + { 8 } + 2 + {} ] + - SWAP (entry) @ location: 28 + [ 3 + { 8 } + 2 + {} ] + - log/DIP (exit) @ location: 28 + [ { 8 } + 3 + 2 + {} ] + - DIP (entry) @ location: 29 + [ { 8 } + 3 + 2 + {} ] + - log/DUP (exit) @ location: 29 + [ 3 + 2 + {} ] + - DUP (entry) @ location: 31 + [ 3 + 2 + {} ] + - log/DIP (exit) @ location: 31 + [ 3 + 3 + 2 + {} ] + - DIP (entry) @ location: 32 + [ 3 + 3 + 2 + {} ] + - log/DUP (exit) @ location: 32 + [ 2 + {} ] + - DUP (entry) @ location: 35 + [ 2 + {} ] + - log/[halt] (exit) @ location: 35 + [ 2 + 2 + {} ] + - [halt] (entry) @ location: 35 + [ 2 + 2 + {} ] + - log/DIP (exit) @ location: 32 + [ 3 + 3 + 2 + 2 + {} ] + - DIP (entry) @ location: 36 + [ 3 + 3 + 2 + 2 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 3 + 2 + 2 + {} ] + - COMPARE (entry) @ location: 39 + [ 3 + 2 + 2 + {} ] + - log/LT (exit) @ location: 39 + [ 1 + 2 + {} ] + - LT (entry) @ location: 40 + [ 1 + 2 + {} ] + - log/[halt] (exit) @ location: 40 + [ False + 2 + {} ] + - [halt] (entry) @ location: 38 + [ False + 2 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 3 + False + 2 + {} ] + - SWAP (entry) @ location: 41 + [ 3 + False + 2 + {} ] + - log/[halt] (exit) @ location: 41 + [ False + 3 + 2 + {} ] + - [halt] (entry) @ location: 30 + [ False + 3 + 2 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 8 } + False + 3 + 2 + {} ] + - SWAP (entry) @ location: 42 + [ { 8 } + False + 3 + 2 + {} ] + - log/IF (exit) @ location: 42 + [ False + { 8 } + 3 + 2 + {} ] + - IF (entry) @ location: 43 + [ False + { 8 } + 3 + 2 + {} ] + - log/SWAP (exit) @ location: 43 + [ { 8 } + 3 + 2 + {} ] + - SWAP (entry) @ location: 55 + [ { 8 } + 3 + 2 + {} ] + - log/CONS (exit) @ location: 55 + [ 3 + { 8 } + 2 + {} ] + - CONS (entry) @ location: 56 + [ 3 + { 8 } + 2 + {} ] + - log/PUSH (exit) @ location: 56 + [ { 3 ; 8 } + 2 + {} ] + - PUSH (entry) @ location: 57 + [ { 3 ; 8 } + 2 + {} ] + - log/[halt] (exit) @ location: 57 + [ False + { 3 ; 8 } + 2 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 3 ; 8 } + 2 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 3 ; 8 } + 2 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 3 ; 8 } + 2 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 3 ; 8 } + 2 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 3 ; 8 } + 2 + {} ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 3 ; 8 } + 2 + {} ] + - SWAP (entry) @ location: 66 + [ { 3 ; 8 } + 2 + {} ] + - log/CONS (exit) @ location: 66 + [ 2 + { 3 ; 8 } + {} ] + - CONS (entry) @ location: 67 + [ 2 + { 3 ; 8 } + {} ] + - log/SWAP (exit) @ location: 67 + [ { 2 ; 3 ; 8 } + {} ] + - SWAP (entry) @ location: 68 + [ { 2 ; 3 ; 8 } + {} ] + - log/ITER (exit) @ location: 68 + [ {} + { 2 ; 3 ; 8 } ] + - ITER (entry) @ location: 69 + [ {} + { 2 ; 3 ; 8 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 2 ; 3 ; 8 } ] + - [halt] (entry) @ location: 13 + [ { 2 ; 3 ; 8 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 7 + { 2 ; 3 ; 8 } ] + - SWAP (entry) @ location: 15 + [ 7 + { 2 ; 3 ; 8 } ] + - log/DIP (exit) @ location: 15 + [ { 2 ; 3 ; 8 } + 7 ] + - DIP (entry) @ location: 16 + [ { 2 ; 3 ; 8 } + 7 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 2 ; 3 ; 8 } + 7 + {} ] + - PUSH (entry) @ location: 21 + [ { 2 ; 3 ; 8 } + 7 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 2 ; 3 ; 8 } + 7 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 2 ; 3 ; 8 } + 7 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 2 ; 3 ; 8 } + 7 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 2 ; 3 ; 8 } + 7 + {} ] + - log/SWAP (exit) @ location: 26 + [ 2 + { 3 ; 8 } + 7 + {} ] + - SWAP (entry) @ location: 28 + [ 2 + { 3 ; 8 } + 7 + {} ] + - log/DIP (exit) @ location: 28 + [ { 3 ; 8 } + 2 + 7 + {} ] + - DIP (entry) @ location: 29 + [ { 3 ; 8 } + 2 + 7 + {} ] + - log/DUP (exit) @ location: 29 + [ 2 + 7 + {} ] + - DUP (entry) @ location: 31 + [ 2 + 7 + {} ] + - log/DIP (exit) @ location: 31 + [ 2 + 2 + 7 + {} ] + - DIP (entry) @ location: 32 + [ 2 + 2 + 7 + {} ] + - log/DUP (exit) @ location: 32 + [ 7 + {} ] + - DUP (entry) @ location: 35 + [ 7 + {} ] + - log/[halt] (exit) @ location: 35 + [ 7 + 7 + {} ] + - [halt] (entry) @ location: 35 + [ 7 + 7 + {} ] + - log/DIP (exit) @ location: 32 + [ 2 + 2 + 7 + 7 + {} ] + - DIP (entry) @ location: 36 + [ 2 + 2 + 7 + 7 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 2 + 7 + 7 + {} ] + - COMPARE (entry) @ location: 39 + [ 2 + 7 + 7 + {} ] + - log/LT (exit) @ location: 39 + [ -1 + 7 + {} ] + - LT (entry) @ location: 40 + [ -1 + 7 + {} ] + - log/[halt] (exit) @ location: 40 + [ True + 7 + {} ] + - [halt] (entry) @ location: 38 + [ True + 7 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 2 + True + 7 + {} ] + - SWAP (entry) @ location: 41 + [ 2 + True + 7 + {} ] + - log/[halt] (exit) @ location: 41 + [ True + 2 + 7 + {} ] + - [halt] (entry) @ location: 30 + [ True + 2 + 7 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 3 ; 8 } + True + 2 + 7 + {} ] + - SWAP (entry) @ location: 42 + [ { 3 ; 8 } + True + 2 + 7 + {} ] + - log/IF (exit) @ location: 42 + [ True + { 3 ; 8 } + 2 + 7 + {} ] + - IF (entry) @ location: 43 + [ True + { 3 ; 8 } + 2 + 7 + {} ] + - log/DIP (exit) @ location: 43 + [ { 3 ; 8 } + 2 + 7 + {} ] + - DIP (entry) @ location: 45 + [ { 3 ; 8 } + 2 + 7 + {} ] + - log/SWAP (exit) @ location: 45 + [ 2 + 7 + {} ] + - SWAP (entry) @ location: 47 + [ 2 + 7 + {} ] + - log/DIP (exit) @ location: 47 + [ 7 + 2 + {} ] + - DIP (entry) @ location: 48 + [ 7 + 2 + {} ] + - log/CONS (exit) @ location: 48 + [ 2 + {} ] + - CONS (entry) @ location: 50 + [ 2 + {} ] + - log/[halt] (exit) @ location: 50 + [ { 2 } ] + - [halt] (entry) @ location: 50 + [ { 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 7 + { 2 } ] + - [halt] (entry) @ location: 46 + [ 7 + { 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 3 ; 8 } + 7 + { 2 } ] + - PUSH (entry) @ location: 51 + [ { 3 ; 8 } + 7 + { 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 3 ; 8 } + 7 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 8 } + 7 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 3 ; 8 } + 7 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 8 } + 7 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 3 ; 8 } + 7 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 8 } + 7 + { 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 3 ; 8 } + 7 + { 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 3 ; 8 } + 7 + { 2 } ] + - log/SWAP (exit) @ location: 26 + [ 3 + { 8 } + 7 + { 2 } ] + - SWAP (entry) @ location: 28 + [ 3 + { 8 } + 7 + { 2 } ] + - log/DIP (exit) @ location: 28 + [ { 8 } + 3 + 7 + { 2 } ] + - DIP (entry) @ location: 29 + [ { 8 } + 3 + 7 + { 2 } ] + - log/DUP (exit) @ location: 29 + [ 3 + 7 + { 2 } ] + - DUP (entry) @ location: 31 + [ 3 + 7 + { 2 } ] + - log/DIP (exit) @ location: 31 + [ 3 + 3 + 7 + { 2 } ] + - DIP (entry) @ location: 32 + [ 3 + 3 + 7 + { 2 } ] + - log/DUP (exit) @ location: 32 + [ 7 + { 2 } ] + - DUP (entry) @ location: 35 + [ 7 + { 2 } ] + - log/[halt] (exit) @ location: 35 + [ 7 + 7 + { 2 } ] + - [halt] (entry) @ location: 35 + [ 7 + 7 + { 2 } ] + - log/DIP (exit) @ location: 32 + [ 3 + 3 + 7 + 7 + { 2 } ] + - DIP (entry) @ location: 36 + [ 3 + 3 + 7 + 7 + { 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 3 + 7 + 7 + { 2 } ] + - COMPARE (entry) @ location: 39 + [ 3 + 7 + 7 + { 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 7 + { 2 } ] + - LT (entry) @ location: 40 + [ -1 + 7 + { 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 7 + { 2 } ] + - [halt] (entry) @ location: 38 + [ True + 7 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 3 + True + 7 + { 2 } ] + - SWAP (entry) @ location: 41 + [ 3 + True + 7 + { 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 3 + 7 + { 2 } ] + - [halt] (entry) @ location: 30 + [ True + 3 + 7 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 8 } + True + 3 + 7 + { 2 } ] + - SWAP (entry) @ location: 42 + [ { 8 } + True + 3 + 7 + { 2 } ] + - log/IF (exit) @ location: 42 + [ True + { 8 } + 3 + 7 + { 2 } ] + - IF (entry) @ location: 43 + [ True + { 8 } + 3 + 7 + { 2 } ] + - log/DIP (exit) @ location: 43 + [ { 8 } + 3 + 7 + { 2 } ] + - DIP (entry) @ location: 45 + [ { 8 } + 3 + 7 + { 2 } ] + - log/SWAP (exit) @ location: 45 + [ 3 + 7 + { 2 } ] + - SWAP (entry) @ location: 47 + [ 3 + 7 + { 2 } ] + - log/DIP (exit) @ location: 47 + [ 7 + 3 + { 2 } ] + - DIP (entry) @ location: 48 + [ 7 + 3 + { 2 } ] + - log/CONS (exit) @ location: 48 + [ 3 + { 2 } ] + - CONS (entry) @ location: 50 + [ 3 + { 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 7 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 8 } + 7 + { 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ { 8 } + 7 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 8 } + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 8 } + 7 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 8 } + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 8 } + 7 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 8 } + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 8 } + 7 + { 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 8 } + 7 + { 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 8 } + 7 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 26 + [ 8 + {} + 7 + { 3 ; 2 } ] + - SWAP (entry) @ location: 28 + [ 8 + {} + 7 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 28 + [ {} + 8 + 7 + { 3 ; 2 } ] + - DIP (entry) @ location: 29 + [ {} + 8 + 7 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 29 + [ 8 + 7 + { 3 ; 2 } ] + - DUP (entry) @ location: 31 + [ 8 + 7 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 31 + [ 8 + 8 + 7 + { 3 ; 2 } ] + - DIP (entry) @ location: 32 + [ 8 + 8 + 7 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 32 + [ 7 + { 3 ; 2 } ] + - DUP (entry) @ location: 35 + [ 7 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 35 + [ 7 + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 35 + [ 7 + 7 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 32 + [ 8 + 8 + 7 + 7 + { 3 ; 2 } ] + - DIP (entry) @ location: 36 + [ 8 + 8 + 7 + 7 + { 3 ; 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 8 + 7 + 7 + { 3 ; 2 } ] + - COMPARE (entry) @ location: 39 + [ 8 + 7 + 7 + { 3 ; 2 } ] + - log/LT (exit) @ location: 39 + [ 1 + 7 + { 3 ; 2 } ] + - LT (entry) @ location: 40 + [ 1 + 7 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 40 + [ False + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 38 + [ False + 7 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 8 + False + 7 + { 3 ; 2 } ] + - SWAP (entry) @ location: 41 + [ 8 + False + 7 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 41 + [ False + 8 + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 30 + [ False + 8 + 7 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ {} + False + 8 + 7 + { 3 ; 2 } ] + - SWAP (entry) @ location: 42 + [ {} + False + 8 + 7 + { 3 ; 2 } ] + - log/IF (exit) @ location: 42 + [ False + {} + 8 + 7 + { 3 ; 2 } ] + - IF (entry) @ location: 43 + [ False + {} + 8 + 7 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 43 + [ {} + 8 + 7 + { 3 ; 2 } ] + - SWAP (entry) @ location: 55 + [ {} + 8 + 7 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 55 + [ 8 + {} + 7 + { 3 ; 2 } ] + - CONS (entry) @ location: 56 + [ 8 + {} + 7 + { 3 ; 2 } ] + - log/PUSH (exit) @ location: 56 + [ { 8 } + 7 + { 3 ; 2 } ] + - PUSH (entry) @ location: 57 + [ { 8 } + 7 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 57 + [ False + { 8 } + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 8 } + 7 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 8 } + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 8 } + 7 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 8 } + 7 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 8 } + 7 + { 3 ; 2 } ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 8 } + 7 + { 3 ; 2 } ] + - SWAP (entry) @ location: 66 + [ { 8 } + 7 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 66 + [ 7 + { 8 } + { 3 ; 2 } ] + - CONS (entry) @ location: 67 + [ 7 + { 8 } + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 67 + [ { 7 ; 8 } + { 3 ; 2 } ] + - SWAP (entry) @ location: 68 + [ { 7 ; 8 } + { 3 ; 2 } ] + - log/ITER (exit) @ location: 68 + [ { 3 ; 2 } + { 7 ; 8 } ] + - ITER (entry) @ location: 69 + [ { 3 ; 2 } + { 7 ; 8 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 3 + { 7 ; 8 } ] + - CONS (entry) @ location: 71 + [ 3 + { 7 ; 8 } ] + - log/[halt] (exit) @ location: 71 + [ { 3 ; 7 ; 8 } ] + - [halt] (entry) @ location: 69 + [ { 3 ; 7 ; 8 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 2 + { 3 ; 7 ; 8 } ] + - CONS (entry) @ location: 71 + [ 2 + { 3 ; 7 ; 8 } ] + - log/[halt] (exit) @ location: 71 + [ { 2 ; 3 ; 7 ; 8 } ] + - [halt] (entry) @ location: 69 + [ { 2 ; 3 ; 7 ; 8 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 2 ; 3 ; 7 ; 8 } ] + - [halt] (entry) @ location: 13 + [ { 2 ; 3 ; 7 ; 8 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 6 + { 2 ; 3 ; 7 ; 8 } ] + - SWAP (entry) @ location: 15 + [ 6 + { 2 ; 3 ; 7 ; 8 } ] + - log/DIP (exit) @ location: 15 + [ { 2 ; 3 ; 7 ; 8 } + 6 ] + - DIP (entry) @ location: 16 + [ { 2 ; 3 ; 7 ; 8 } + 6 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 2 ; 3 ; 7 ; 8 } + 6 + {} ] + - PUSH (entry) @ location: 21 + [ { 2 ; 3 ; 7 ; 8 } + 6 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 2 ; 3 ; 7 ; 8 } + 6 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 2 ; 3 ; 7 ; 8 } + 6 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 2 ; 3 ; 7 ; 8 } + 6 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 2 ; 3 ; 7 ; 8 } + 6 + {} ] + - log/SWAP (exit) @ location: 26 + [ 2 + { 3 ; 7 ; 8 } + 6 + {} ] + - SWAP (entry) @ location: 28 + [ 2 + { 3 ; 7 ; 8 } + 6 + {} ] + - log/DIP (exit) @ location: 28 + [ { 3 ; 7 ; 8 } + 2 + 6 + {} ] + - DIP (entry) @ location: 29 + [ { 3 ; 7 ; 8 } + 2 + 6 + {} ] + - log/DUP (exit) @ location: 29 + [ 2 + 6 + {} ] + - DUP (entry) @ location: 31 + [ 2 + 6 + {} ] + - log/DIP (exit) @ location: 31 + [ 2 + 2 + 6 + {} ] + - DIP (entry) @ location: 32 + [ 2 + 2 + 6 + {} ] + - log/DUP (exit) @ location: 32 + [ 6 + {} ] + - DUP (entry) @ location: 35 + [ 6 + {} ] + - log/[halt] (exit) @ location: 35 + [ 6 + 6 + {} ] + - [halt] (entry) @ location: 35 + [ 6 + 6 + {} ] + - log/DIP (exit) @ location: 32 + [ 2 + 2 + 6 + 6 + {} ] + - DIP (entry) @ location: 36 + [ 2 + 2 + 6 + 6 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 2 + 6 + 6 + {} ] + - COMPARE (entry) @ location: 39 + [ 2 + 6 + 6 + {} ] + - log/LT (exit) @ location: 39 + [ -1 + 6 + {} ] + - LT (entry) @ location: 40 + [ -1 + 6 + {} ] + - log/[halt] (exit) @ location: 40 + [ True + 6 + {} ] + - [halt] (entry) @ location: 38 + [ True + 6 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 2 + True + 6 + {} ] + - SWAP (entry) @ location: 41 + [ 2 + True + 6 + {} ] + - log/[halt] (exit) @ location: 41 + [ True + 2 + 6 + {} ] + - [halt] (entry) @ location: 30 + [ True + 2 + 6 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 3 ; 7 ; 8 } + True + 2 + 6 + {} ] + - SWAP (entry) @ location: 42 + [ { 3 ; 7 ; 8 } + True + 2 + 6 + {} ] + - log/IF (exit) @ location: 42 + [ True + { 3 ; 7 ; 8 } + 2 + 6 + {} ] + - IF (entry) @ location: 43 + [ True + { 3 ; 7 ; 8 } + 2 + 6 + {} ] + - log/DIP (exit) @ location: 43 + [ { 3 ; 7 ; 8 } + 2 + 6 + {} ] + - DIP (entry) @ location: 45 + [ { 3 ; 7 ; 8 } + 2 + 6 + {} ] + - log/SWAP (exit) @ location: 45 + [ 2 + 6 + {} ] + - SWAP (entry) @ location: 47 + [ 2 + 6 + {} ] + - log/DIP (exit) @ location: 47 + [ 6 + 2 + {} ] + - DIP (entry) @ location: 48 + [ 6 + 2 + {} ] + - log/CONS (exit) @ location: 48 + [ 2 + {} ] + - CONS (entry) @ location: 50 + [ 2 + {} ] + - log/[halt] (exit) @ location: 50 + [ { 2 } ] + - [halt] (entry) @ location: 50 + [ { 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 6 + { 2 } ] + - [halt] (entry) @ location: 46 + [ 6 + { 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 3 ; 7 ; 8 } + 6 + { 2 } ] + - PUSH (entry) @ location: 51 + [ { 3 ; 7 ; 8 } + 6 + { 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 3 ; 7 ; 8 } + 6 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 7 ; 8 } + 6 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 3 ; 7 ; 8 } + 6 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 7 ; 8 } + 6 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 3 ; 7 ; 8 } + 6 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 7 ; 8 } + 6 + { 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 3 ; 7 ; 8 } + 6 + { 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 3 ; 7 ; 8 } + 6 + { 2 } ] + - log/SWAP (exit) @ location: 26 + [ 3 + { 7 ; 8 } + 6 + { 2 } ] + - SWAP (entry) @ location: 28 + [ 3 + { 7 ; 8 } + 6 + { 2 } ] + - log/DIP (exit) @ location: 28 + [ { 7 ; 8 } + 3 + 6 + { 2 } ] + - DIP (entry) @ location: 29 + [ { 7 ; 8 } + 3 + 6 + { 2 } ] + - log/DUP (exit) @ location: 29 + [ 3 + 6 + { 2 } ] + - DUP (entry) @ location: 31 + [ 3 + 6 + { 2 } ] + - log/DIP (exit) @ location: 31 + [ 3 + 3 + 6 + { 2 } ] + - DIP (entry) @ location: 32 + [ 3 + 3 + 6 + { 2 } ] + - log/DUP (exit) @ location: 32 + [ 6 + { 2 } ] + - DUP (entry) @ location: 35 + [ 6 + { 2 } ] + - log/[halt] (exit) @ location: 35 + [ 6 + 6 + { 2 } ] + - [halt] (entry) @ location: 35 + [ 6 + 6 + { 2 } ] + - log/DIP (exit) @ location: 32 + [ 3 + 3 + 6 + 6 + { 2 } ] + - DIP (entry) @ location: 36 + [ 3 + 3 + 6 + 6 + { 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 3 + 6 + 6 + { 2 } ] + - COMPARE (entry) @ location: 39 + [ 3 + 6 + 6 + { 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 6 + { 2 } ] + - LT (entry) @ location: 40 + [ -1 + 6 + { 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 6 + { 2 } ] + - [halt] (entry) @ location: 38 + [ True + 6 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 3 + True + 6 + { 2 } ] + - SWAP (entry) @ location: 41 + [ 3 + True + 6 + { 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 3 + 6 + { 2 } ] + - [halt] (entry) @ location: 30 + [ True + 3 + 6 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 7 ; 8 } + True + 3 + 6 + { 2 } ] + - SWAP (entry) @ location: 42 + [ { 7 ; 8 } + True + 3 + 6 + { 2 } ] + - log/IF (exit) @ location: 42 + [ True + { 7 ; 8 } + 3 + 6 + { 2 } ] + - IF (entry) @ location: 43 + [ True + { 7 ; 8 } + 3 + 6 + { 2 } ] + - log/DIP (exit) @ location: 43 + [ { 7 ; 8 } + 3 + 6 + { 2 } ] + - DIP (entry) @ location: 45 + [ { 7 ; 8 } + 3 + 6 + { 2 } ] + - log/SWAP (exit) @ location: 45 + [ 3 + 6 + { 2 } ] + - SWAP (entry) @ location: 47 + [ 3 + 6 + { 2 } ] + - log/DIP (exit) @ location: 47 + [ 6 + 3 + { 2 } ] + - DIP (entry) @ location: 48 + [ 6 + 3 + { 2 } ] + - log/CONS (exit) @ location: 48 + [ 3 + { 2 } ] + - CONS (entry) @ location: 50 + [ 3 + { 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 6 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 26 + [ 7 + { 8 } + 6 + { 3 ; 2 } ] + - SWAP (entry) @ location: 28 + [ 7 + { 8 } + 6 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 28 + [ { 8 } + 7 + 6 + { 3 ; 2 } ] + - DIP (entry) @ location: 29 + [ { 8 } + 7 + 6 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 29 + [ 7 + 6 + { 3 ; 2 } ] + - DUP (entry) @ location: 31 + [ 7 + 6 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 31 + [ 7 + 7 + 6 + { 3 ; 2 } ] + - DIP (entry) @ location: 32 + [ 7 + 7 + 6 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 32 + [ 6 + { 3 ; 2 } ] + - DUP (entry) @ location: 35 + [ 6 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 35 + [ 6 + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 35 + [ 6 + 6 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 32 + [ 7 + 7 + 6 + 6 + { 3 ; 2 } ] + - DIP (entry) @ location: 36 + [ 7 + 7 + 6 + 6 + { 3 ; 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 7 + 6 + 6 + { 3 ; 2 } ] + - COMPARE (entry) @ location: 39 + [ 7 + 6 + 6 + { 3 ; 2 } ] + - log/LT (exit) @ location: 39 + [ 1 + 6 + { 3 ; 2 } ] + - LT (entry) @ location: 40 + [ 1 + 6 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 40 + [ False + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 38 + [ False + 6 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 7 + False + 6 + { 3 ; 2 } ] + - SWAP (entry) @ location: 41 + [ 7 + False + 6 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 41 + [ False + 7 + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 30 + [ False + 7 + 6 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 8 } + False + 7 + 6 + { 3 ; 2 } ] + - SWAP (entry) @ location: 42 + [ { 8 } + False + 7 + 6 + { 3 ; 2 } ] + - log/IF (exit) @ location: 42 + [ False + { 8 } + 7 + 6 + { 3 ; 2 } ] + - IF (entry) @ location: 43 + [ False + { 8 } + 7 + 6 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 43 + [ { 8 } + 7 + 6 + { 3 ; 2 } ] + - SWAP (entry) @ location: 55 + [ { 8 } + 7 + 6 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 55 + [ 7 + { 8 } + 6 + { 3 ; 2 } ] + - CONS (entry) @ location: 56 + [ 7 + { 8 } + 6 + { 3 ; 2 } ] + - log/PUSH (exit) @ location: 56 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - PUSH (entry) @ location: 57 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 57 + [ False + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 7 ; 8 } + 6 + { 3 ; 2 } ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - SWAP (entry) @ location: 66 + [ { 7 ; 8 } + 6 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 66 + [ 6 + { 7 ; 8 } + { 3 ; 2 } ] + - CONS (entry) @ location: 67 + [ 6 + { 7 ; 8 } + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 67 + [ { 6 ; 7 ; 8 } + { 3 ; 2 } ] + - SWAP (entry) @ location: 68 + [ { 6 ; 7 ; 8 } + { 3 ; 2 } ] + - log/ITER (exit) @ location: 68 + [ { 3 ; 2 } + { 6 ; 7 ; 8 } ] + - ITER (entry) @ location: 69 + [ { 3 ; 2 } + { 6 ; 7 ; 8 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 3 + { 6 ; 7 ; 8 } ] + - CONS (entry) @ location: 71 + [ 3 + { 6 ; 7 ; 8 } ] + - log/[halt] (exit) @ location: 71 + [ { 3 ; 6 ; 7 ; 8 } ] + - [halt] (entry) @ location: 69 + [ { 3 ; 6 ; 7 ; 8 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 2 + { 3 ; 6 ; 7 ; 8 } ] + - CONS (entry) @ location: 71 + [ 2 + { 3 ; 6 ; 7 ; 8 } ] + - log/[halt] (exit) @ location: 71 + [ { 2 ; 3 ; 6 ; 7 ; 8 } ] + - [halt] (entry) @ location: 69 + [ { 2 ; 3 ; 6 ; 7 ; 8 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 2 ; 3 ; 6 ; 7 ; 8 } ] + - [halt] (entry) @ location: 13 + [ { 2 ; 3 ; 6 ; 7 ; 8 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 9 + { 2 ; 3 ; 6 ; 7 ; 8 } ] + - SWAP (entry) @ location: 15 + [ 9 + { 2 ; 3 ; 6 ; 7 ; 8 } ] + - log/DIP (exit) @ location: 15 + [ { 2 ; 3 ; 6 ; 7 ; 8 } + 9 ] + - DIP (entry) @ location: 16 + [ { 2 ; 3 ; 6 ; 7 ; 8 } + 9 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 2 ; 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - PUSH (entry) @ location: 21 + [ { 2 ; 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 2 ; 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 2 ; 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 2 ; 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 2 ; 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - log/SWAP (exit) @ location: 26 + [ 2 + { 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - SWAP (entry) @ location: 28 + [ 2 + { 3 ; 6 ; 7 ; 8 } + 9 + {} ] + - log/DIP (exit) @ location: 28 + [ { 3 ; 6 ; 7 ; 8 } + 2 + 9 + {} ] + - DIP (entry) @ location: 29 + [ { 3 ; 6 ; 7 ; 8 } + 2 + 9 + {} ] + - log/DUP (exit) @ location: 29 + [ 2 + 9 + {} ] + - DUP (entry) @ location: 31 + [ 2 + 9 + {} ] + - log/DIP (exit) @ location: 31 + [ 2 + 2 + 9 + {} ] + - DIP (entry) @ location: 32 + [ 2 + 2 + 9 + {} ] + - log/DUP (exit) @ location: 32 + [ 9 + {} ] + - DUP (entry) @ location: 35 + [ 9 + {} ] + - log/[halt] (exit) @ location: 35 + [ 9 + 9 + {} ] + - [halt] (entry) @ location: 35 + [ 9 + 9 + {} ] + - log/DIP (exit) @ location: 32 + [ 2 + 2 + 9 + 9 + {} ] + - DIP (entry) @ location: 36 + [ 2 + 2 + 9 + 9 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 2 + 9 + 9 + {} ] + - COMPARE (entry) @ location: 39 + [ 2 + 9 + 9 + {} ] + - log/LT (exit) @ location: 39 + [ -1 + 9 + {} ] + - LT (entry) @ location: 40 + [ -1 + 9 + {} ] + - log/[halt] (exit) @ location: 40 + [ True + 9 + {} ] + - [halt] (entry) @ location: 38 + [ True + 9 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 2 + True + 9 + {} ] + - SWAP (entry) @ location: 41 + [ 2 + True + 9 + {} ] + - log/[halt] (exit) @ location: 41 + [ True + 2 + 9 + {} ] + - [halt] (entry) @ location: 30 + [ True + 2 + 9 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 3 ; 6 ; 7 ; 8 } + True + 2 + 9 + {} ] + - SWAP (entry) @ location: 42 + [ { 3 ; 6 ; 7 ; 8 } + True + 2 + 9 + {} ] + - log/IF (exit) @ location: 42 + [ True + { 3 ; 6 ; 7 ; 8 } + 2 + 9 + {} ] + - IF (entry) @ location: 43 + [ True + { 3 ; 6 ; 7 ; 8 } + 2 + 9 + {} ] + - log/DIP (exit) @ location: 43 + [ { 3 ; 6 ; 7 ; 8 } + 2 + 9 + {} ] + - DIP (entry) @ location: 45 + [ { 3 ; 6 ; 7 ; 8 } + 2 + 9 + {} ] + - log/SWAP (exit) @ location: 45 + [ 2 + 9 + {} ] + - SWAP (entry) @ location: 47 + [ 2 + 9 + {} ] + - log/DIP (exit) @ location: 47 + [ 9 + 2 + {} ] + - DIP (entry) @ location: 48 + [ 9 + 2 + {} ] + - log/CONS (exit) @ location: 48 + [ 2 + {} ] + - CONS (entry) @ location: 50 + [ 2 + {} ] + - log/[halt] (exit) @ location: 50 + [ { 2 } ] + - [halt] (entry) @ location: 50 + [ { 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 9 + { 2 } ] + - [halt] (entry) @ location: 46 + [ 9 + { 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - PUSH (entry) @ location: 51 + [ { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 3 ; 6 ; 7 ; 8 } + 9 + { 2 } ] + - log/SWAP (exit) @ location: 26 + [ 3 + { 6 ; 7 ; 8 } + 9 + { 2 } ] + - SWAP (entry) @ location: 28 + [ 3 + { 6 ; 7 ; 8 } + 9 + { 2 } ] + - log/DIP (exit) @ location: 28 + [ { 6 ; 7 ; 8 } + 3 + 9 + { 2 } ] + - DIP (entry) @ location: 29 + [ { 6 ; 7 ; 8 } + 3 + 9 + { 2 } ] + - log/DUP (exit) @ location: 29 + [ 3 + 9 + { 2 } ] + - DUP (entry) @ location: 31 + [ 3 + 9 + { 2 } ] + - log/DIP (exit) @ location: 31 + [ 3 + 3 + 9 + { 2 } ] + - DIP (entry) @ location: 32 + [ 3 + 3 + 9 + { 2 } ] + - log/DUP (exit) @ location: 32 + [ 9 + { 2 } ] + - DUP (entry) @ location: 35 + [ 9 + { 2 } ] + - log/[halt] (exit) @ location: 35 + [ 9 + 9 + { 2 } ] + - [halt] (entry) @ location: 35 + [ 9 + 9 + { 2 } ] + - log/DIP (exit) @ location: 32 + [ 3 + 3 + 9 + 9 + { 2 } ] + - DIP (entry) @ location: 36 + [ 3 + 3 + 9 + 9 + { 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 3 + 9 + 9 + { 2 } ] + - COMPARE (entry) @ location: 39 + [ 3 + 9 + 9 + { 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 9 + { 2 } ] + - LT (entry) @ location: 40 + [ -1 + 9 + { 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 9 + { 2 } ] + - [halt] (entry) @ location: 38 + [ True + 9 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 3 + True + 9 + { 2 } ] + - SWAP (entry) @ location: 41 + [ 3 + True + 9 + { 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 3 + 9 + { 2 } ] + - [halt] (entry) @ location: 30 + [ True + 3 + 9 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 6 ; 7 ; 8 } + True + 3 + 9 + { 2 } ] + - SWAP (entry) @ location: 42 + [ { 6 ; 7 ; 8 } + True + 3 + 9 + { 2 } ] + - log/IF (exit) @ location: 42 + [ True + { 6 ; 7 ; 8 } + 3 + 9 + { 2 } ] + - IF (entry) @ location: 43 + [ True + { 6 ; 7 ; 8 } + 3 + 9 + { 2 } ] + - log/DIP (exit) @ location: 43 + [ { 6 ; 7 ; 8 } + 3 + 9 + { 2 } ] + - DIP (entry) @ location: 45 + [ { 6 ; 7 ; 8 } + 3 + 9 + { 2 } ] + - log/SWAP (exit) @ location: 45 + [ 3 + 9 + { 2 } ] + - SWAP (entry) @ location: 47 + [ 3 + 9 + { 2 } ] + - log/DIP (exit) @ location: 47 + [ 9 + 3 + { 2 } ] + - DIP (entry) @ location: 48 + [ 9 + 3 + { 2 } ] + - log/CONS (exit) @ location: 48 + [ 3 + { 2 } ] + - CONS (entry) @ location: 50 + [ 3 + { 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 9 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 6 ; 7 ; 8 } + 9 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 26 + [ 6 + { 7 ; 8 } + 9 + { 3 ; 2 } ] + - SWAP (entry) @ location: 28 + [ 6 + { 7 ; 8 } + 9 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 28 + [ { 7 ; 8 } + 6 + 9 + { 3 ; 2 } ] + - DIP (entry) @ location: 29 + [ { 7 ; 8 } + 6 + 9 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 29 + [ 6 + 9 + { 3 ; 2 } ] + - DUP (entry) @ location: 31 + [ 6 + 9 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 31 + [ 6 + 6 + 9 + { 3 ; 2 } ] + - DIP (entry) @ location: 32 + [ 6 + 6 + 9 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 32 + [ 9 + { 3 ; 2 } ] + - DUP (entry) @ location: 35 + [ 9 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 35 + [ 9 + 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 35 + [ 9 + 9 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 32 + [ 6 + 6 + 9 + 9 + { 3 ; 2 } ] + - DIP (entry) @ location: 36 + [ 6 + 6 + 9 + 9 + { 3 ; 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 6 + 9 + 9 + { 3 ; 2 } ] + - COMPARE (entry) @ location: 39 + [ 6 + 9 + 9 + { 3 ; 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 9 + { 3 ; 2 } ] + - LT (entry) @ location: 40 + [ -1 + 9 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 38 + [ True + 9 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 6 + True + 9 + { 3 ; 2 } ] + - SWAP (entry) @ location: 41 + [ 6 + True + 9 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 6 + 9 + { 3 ; 2 } ] + - [halt] (entry) @ location: 30 + [ True + 6 + 9 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 7 ; 8 } + True + 6 + 9 + { 3 ; 2 } ] + - SWAP (entry) @ location: 42 + [ { 7 ; 8 } + True + 6 + 9 + { 3 ; 2 } ] + - log/IF (exit) @ location: 42 + [ True + { 7 ; 8 } + 6 + 9 + { 3 ; 2 } ] + - IF (entry) @ location: 43 + [ True + { 7 ; 8 } + 6 + 9 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 43 + [ { 7 ; 8 } + 6 + 9 + { 3 ; 2 } ] + - DIP (entry) @ location: 45 + [ { 7 ; 8 } + 6 + 9 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 45 + [ 6 + 9 + { 3 ; 2 } ] + - SWAP (entry) @ location: 47 + [ 6 + 9 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 47 + [ 9 + 6 + { 3 ; 2 } ] + - DIP (entry) @ location: 48 + [ 9 + 6 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 48 + [ 6 + { 3 ; 2 } ] + - CONS (entry) @ location: 50 + [ 6 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 9 + { 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 7 ; 8 } + 9 + { 6 ; 3 ; 2 } ] + - log/SWAP (exit) @ location: 26 + [ 7 + { 8 } + 9 + { 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 28 + [ 7 + { 8 } + 9 + { 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 28 + [ { 8 } + 7 + 9 + { 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 29 + [ { 8 } + 7 + 9 + { 6 ; 3 ; 2 } ] + - log/DUP (exit) @ location: 29 + [ 7 + 9 + { 6 ; 3 ; 2 } ] + - DUP (entry) @ location: 31 + [ 7 + 9 + { 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 31 + [ 7 + 7 + 9 + { 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 32 + [ 7 + 7 + 9 + { 6 ; 3 ; 2 } ] + - log/DUP (exit) @ location: 32 + [ 9 + { 6 ; 3 ; 2 } ] + - DUP (entry) @ location: 35 + [ 9 + { 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 35 + [ 9 + 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 35 + [ 9 + 9 + { 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 32 + [ 7 + 7 + 9 + 9 + { 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 36 + [ 7 + 7 + 9 + 9 + { 6 ; 3 ; 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 7 + 9 + 9 + { 6 ; 3 ; 2 } ] + - COMPARE (entry) @ location: 39 + [ 7 + 9 + 9 + { 6 ; 3 ; 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 9 + { 6 ; 3 ; 2 } ] + - LT (entry) @ location: 40 + [ -1 + 9 + { 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 38 + [ True + 9 + { 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 7 + True + 9 + { 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 41 + [ 7 + True + 9 + { 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 7 + 9 + { 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 30 + [ True + 7 + 9 + { 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 8 } + True + 7 + 9 + { 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 42 + [ { 8 } + True + 7 + 9 + { 6 ; 3 ; 2 } ] + - log/IF (exit) @ location: 42 + [ True + { 8 } + 7 + 9 + { 6 ; 3 ; 2 } ] + - IF (entry) @ location: 43 + [ True + { 8 } + 7 + 9 + { 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 43 + [ { 8 } + 7 + 9 + { 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 45 + [ { 8 } + 7 + 9 + { 6 ; 3 ; 2 } ] + - log/SWAP (exit) @ location: 45 + [ 7 + 9 + { 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 47 + [ 7 + 9 + { 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 47 + [ 9 + 7 + { 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 48 + [ 9 + 7 + { 6 ; 3 ; 2 } ] + - log/CONS (exit) @ location: 48 + [ 7 + { 6 ; 3 ; 2 } ] + - CONS (entry) @ location: 50 + [ 7 + { 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 7 ; 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 9 + { 7 ; 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 8 } + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/SWAP (exit) @ location: 26 + [ 8 + {} + 9 + { 7 ; 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 28 + [ 8 + {} + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 28 + [ {} + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 29 + [ {} + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DUP (exit) @ location: 29 + [ 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - DUP (entry) @ location: 31 + [ 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 31 + [ 8 + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 32 + [ 8 + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DUP (exit) @ location: 32 + [ 9 + { 7 ; 6 ; 3 ; 2 } ] + - DUP (entry) @ location: 35 + [ 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 35 + [ 9 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 35 + [ 9 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 32 + [ 8 + 8 + 9 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 36 + [ 8 + 8 + 9 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 8 + 9 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - COMPARE (entry) @ location: 39 + [ 8 + 9 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - LT (entry) @ location: 40 + [ -1 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 38 + [ True + 9 + { 7 ; 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 8 + True + 9 + { 7 ; 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 41 + [ 8 + True + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 30 + [ True + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ {} + True + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 42 + [ {} + True + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/IF (exit) @ location: 42 + [ True + {} + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - IF (entry) @ location: 43 + [ True + {} + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 43 + [ {} + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 45 + [ {} + 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/SWAP (exit) @ location: 45 + [ 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 47 + [ 8 + 9 + { 7 ; 6 ; 3 ; 2 } ] + - log/DIP (exit) @ location: 47 + [ 9 + 8 + { 7 ; 6 ; 3 ; 2 } ] + - DIP (entry) @ location: 48 + [ 9 + 8 + { 7 ; 6 ; 3 ; 2 } ] + - log/CONS (exit) @ location: 48 + [ 8 + { 7 ; 6 ; 3 ; 2 } ] + - CONS (entry) @ location: 50 + [ 8 + { 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/NIL (exit) @ location: 26 + [ 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - NIL (entry) @ location: 61 + [ 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/PUSH (exit) @ location: 61 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - PUSH (entry) @ location: 63 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/[halt] (exit) @ location: 63 + [ False + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 66 + [ {} + 9 + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/CONS (exit) @ location: 66 + [ 9 + {} + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - CONS (entry) @ location: 67 + [ 9 + {} + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/SWAP (exit) @ location: 67 + [ { 9 } + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - SWAP (entry) @ location: 68 + [ { 9 } + { 8 ; 7 ; 6 ; 3 ; 2 } ] + - log/ITER (exit) @ location: 68 + [ { 8 ; 7 ; 6 ; 3 ; 2 } + { 9 } ] + - ITER (entry) @ location: 69 + [ { 8 ; 7 ; 6 ; 3 ; 2 } + { 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 8 + { 9 } ] + - CONS (entry) @ location: 71 + [ 8 + { 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 7 + { 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 7 + { 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 6 + { 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 6 + { 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 3 + { 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 3 + { 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 3 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 3 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 2 + { 3 ; 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 2 + { 3 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 13 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 5 + { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } ] + - SWAP (entry) @ location: 15 + [ 5 + { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } ] + - log/DIP (exit) @ location: 15 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 ] + - DIP (entry) @ location: 16 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - PUSH (entry) @ location: 21 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 2 ; 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - log/SWAP (exit) @ location: 26 + [ 2 + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - SWAP (entry) @ location: 28 + [ 2 + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + {} ] + - log/DIP (exit) @ location: 28 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 2 + 5 + {} ] + - DIP (entry) @ location: 29 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 2 + 5 + {} ] + - log/DUP (exit) @ location: 29 + [ 2 + 5 + {} ] + - DUP (entry) @ location: 31 + [ 2 + 5 + {} ] + - log/DIP (exit) @ location: 31 + [ 2 + 2 + 5 + {} ] + - DIP (entry) @ location: 32 + [ 2 + 2 + 5 + {} ] + - log/DUP (exit) @ location: 32 + [ 5 + {} ] + - DUP (entry) @ location: 35 + [ 5 + {} ] + - log/[halt] (exit) @ location: 35 + [ 5 + 5 + {} ] + - [halt] (entry) @ location: 35 + [ 5 + 5 + {} ] + - log/DIP (exit) @ location: 32 + [ 2 + 2 + 5 + 5 + {} ] + - DIP (entry) @ location: 36 + [ 2 + 2 + 5 + 5 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 2 + 5 + 5 + {} ] + - COMPARE (entry) @ location: 39 + [ 2 + 5 + 5 + {} ] + - log/LT (exit) @ location: 39 + [ -1 + 5 + {} ] + - LT (entry) @ location: 40 + [ -1 + 5 + {} ] + - log/[halt] (exit) @ location: 40 + [ True + 5 + {} ] + - [halt] (entry) @ location: 38 + [ True + 5 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 2 + True + 5 + {} ] + - SWAP (entry) @ location: 41 + [ 2 + True + 5 + {} ] + - log/[halt] (exit) @ location: 41 + [ True + 2 + 5 + {} ] + - [halt] (entry) @ location: 30 + [ True + 2 + 5 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + True + 2 + 5 + {} ] + - SWAP (entry) @ location: 42 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + True + 2 + 5 + {} ] + - log/IF (exit) @ location: 42 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 2 + 5 + {} ] + - IF (entry) @ location: 43 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 2 + 5 + {} ] + - log/DIP (exit) @ location: 43 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 2 + 5 + {} ] + - DIP (entry) @ location: 45 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 2 + 5 + {} ] + - log/SWAP (exit) @ location: 45 + [ 2 + 5 + {} ] + - SWAP (entry) @ location: 47 + [ 2 + 5 + {} ] + - log/DIP (exit) @ location: 47 + [ 5 + 2 + {} ] + - DIP (entry) @ location: 48 + [ 5 + 2 + {} ] + - log/CONS (exit) @ location: 48 + [ 2 + {} ] + - CONS (entry) @ location: 50 + [ 2 + {} ] + - log/[halt] (exit) @ location: 50 + [ { 2 } ] + - [halt] (entry) @ location: 50 + [ { 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 5 + { 2 } ] + - [halt] (entry) @ location: 46 + [ 5 + { 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - PUSH (entry) @ location: 51 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 3 ; 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - log/SWAP (exit) @ location: 26 + [ 3 + { 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - SWAP (entry) @ location: 28 + [ 3 + { 6 ; 7 ; 8 ; 9 } + 5 + { 2 } ] + - log/DIP (exit) @ location: 28 + [ { 6 ; 7 ; 8 ; 9 } + 3 + 5 + { 2 } ] + - DIP (entry) @ location: 29 + [ { 6 ; 7 ; 8 ; 9 } + 3 + 5 + { 2 } ] + - log/DUP (exit) @ location: 29 + [ 3 + 5 + { 2 } ] + - DUP (entry) @ location: 31 + [ 3 + 5 + { 2 } ] + - log/DIP (exit) @ location: 31 + [ 3 + 3 + 5 + { 2 } ] + - DIP (entry) @ location: 32 + [ 3 + 3 + 5 + { 2 } ] + - log/DUP (exit) @ location: 32 + [ 5 + { 2 } ] + - DUP (entry) @ location: 35 + [ 5 + { 2 } ] + - log/[halt] (exit) @ location: 35 + [ 5 + 5 + { 2 } ] + - [halt] (entry) @ location: 35 + [ 5 + 5 + { 2 } ] + - log/DIP (exit) @ location: 32 + [ 3 + 3 + 5 + 5 + { 2 } ] + - DIP (entry) @ location: 36 + [ 3 + 3 + 5 + 5 + { 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 3 + 5 + 5 + { 2 } ] + - COMPARE (entry) @ location: 39 + [ 3 + 5 + 5 + { 2 } ] + - log/LT (exit) @ location: 39 + [ -1 + 5 + { 2 } ] + - LT (entry) @ location: 40 + [ -1 + 5 + { 2 } ] + - log/[halt] (exit) @ location: 40 + [ True + 5 + { 2 } ] + - [halt] (entry) @ location: 38 + [ True + 5 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 3 + True + 5 + { 2 } ] + - SWAP (entry) @ location: 41 + [ 3 + True + 5 + { 2 } ] + - log/[halt] (exit) @ location: 41 + [ True + 3 + 5 + { 2 } ] + - [halt] (entry) @ location: 30 + [ True + 3 + 5 + { 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 6 ; 7 ; 8 ; 9 } + True + 3 + 5 + { 2 } ] + - SWAP (entry) @ location: 42 + [ { 6 ; 7 ; 8 ; 9 } + True + 3 + 5 + { 2 } ] + - log/IF (exit) @ location: 42 + [ True + { 6 ; 7 ; 8 ; 9 } + 3 + 5 + { 2 } ] + - IF (entry) @ location: 43 + [ True + { 6 ; 7 ; 8 ; 9 } + 3 + 5 + { 2 } ] + - log/DIP (exit) @ location: 43 + [ { 6 ; 7 ; 8 ; 9 } + 3 + 5 + { 2 } ] + - DIP (entry) @ location: 45 + [ { 6 ; 7 ; 8 ; 9 } + 3 + 5 + { 2 } ] + - log/SWAP (exit) @ location: 45 + [ 3 + 5 + { 2 } ] + - SWAP (entry) @ location: 47 + [ 3 + 5 + { 2 } ] + - log/DIP (exit) @ location: 47 + [ 5 + 3 + { 2 } ] + - DIP (entry) @ location: 48 + [ 5 + 3 + { 2 } ] + - log/CONS (exit) @ location: 48 + [ 3 + { 2 } ] + - CONS (entry) @ location: 50 + [ 3 + { 2 } ] + - log/[halt] (exit) @ location: 50 + [ { 3 ; 2 } ] + - [halt] (entry) @ location: 50 + [ { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 46 + [ 5 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - PUSH (entry) @ location: 51 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ True + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - IF_CONS (entry) @ location: 26 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 26 + [ 6 + { 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - SWAP (entry) @ location: 28 + [ 6 + { 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 28 + [ { 7 ; 8 ; 9 } + 6 + 5 + { 3 ; 2 } ] + - DIP (entry) @ location: 29 + [ { 7 ; 8 ; 9 } + 6 + 5 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 29 + [ 6 + 5 + { 3 ; 2 } ] + - DUP (entry) @ location: 31 + [ 6 + 5 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 31 + [ 6 + 6 + 5 + { 3 ; 2 } ] + - DIP (entry) @ location: 32 + [ 6 + 6 + 5 + { 3 ; 2 } ] + - log/DUP (exit) @ location: 32 + [ 5 + { 3 ; 2 } ] + - DUP (entry) @ location: 35 + [ 5 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 35 + [ 5 + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 35 + [ 5 + 5 + { 3 ; 2 } ] + - log/DIP (exit) @ location: 32 + [ 6 + 6 + 5 + 5 + { 3 ; 2 } ] + - DIP (entry) @ location: 36 + [ 6 + 6 + 5 + 5 + { 3 ; 2 } ] + - log/COMPARE (exit) @ location: 36 + [ 6 + 5 + 5 + { 3 ; 2 } ] + - COMPARE (entry) @ location: 39 + [ 6 + 5 + 5 + { 3 ; 2 } ] + - log/LT (exit) @ location: 39 + [ 1 + 5 + { 3 ; 2 } ] + - LT (entry) @ location: 40 + [ 1 + 5 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 40 + [ False + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 38 + [ False + 5 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 6 + False + 5 + { 3 ; 2 } ] + - SWAP (entry) @ location: 41 + [ 6 + False + 5 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 41 + [ False + 6 + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 30 + [ False + 6 + 5 + { 3 ; 2 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 7 ; 8 ; 9 } + False + 6 + 5 + { 3 ; 2 } ] + - SWAP (entry) @ location: 42 + [ { 7 ; 8 ; 9 } + False + 6 + 5 + { 3 ; 2 } ] + - log/IF (exit) @ location: 42 + [ False + { 7 ; 8 ; 9 } + 6 + 5 + { 3 ; 2 } ] + - IF (entry) @ location: 43 + [ False + { 7 ; 8 ; 9 } + 6 + 5 + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 43 + [ { 7 ; 8 ; 9 } + 6 + 5 + { 3 ; 2 } ] + - SWAP (entry) @ location: 55 + [ { 7 ; 8 ; 9 } + 6 + 5 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 55 + [ 6 + { 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - CONS (entry) @ location: 56 + [ 6 + { 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - log/PUSH (exit) @ location: 56 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - PUSH (entry) @ location: 57 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - log/[halt] (exit) @ location: 57 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - [halt] (entry) @ location: 66 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - SWAP (entry) @ location: 66 + [ { 6 ; 7 ; 8 ; 9 } + 5 + { 3 ; 2 } ] + - log/CONS (exit) @ location: 66 + [ 5 + { 6 ; 7 ; 8 ; 9 } + { 3 ; 2 } ] + - CONS (entry) @ location: 67 + [ 5 + { 6 ; 7 ; 8 ; 9 } + { 3 ; 2 } ] + - log/SWAP (exit) @ location: 67 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + { 3 ; 2 } ] + - SWAP (entry) @ location: 68 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + { 3 ; 2 } ] + - log/ITER (exit) @ location: 68 + [ { 3 ; 2 } + { 5 ; 6 ; 7 ; 8 ; 9 } ] + - ITER (entry) @ location: 69 + [ { 3 ; 2 } + { 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 3 + { 5 ; 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 3 + { 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 13 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 1 + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - SWAP (entry) @ location: 15 + [ 1 + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/DIP (exit) @ location: 15 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 ] + - DIP (entry) @ location: 16 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - PUSH (entry) @ location: 21 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - log/SWAP (exit) @ location: 26 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - SWAP (entry) @ location: 28 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - log/DIP (exit) @ location: 28 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 1 + {} ] + - DIP (entry) @ location: 29 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 1 + {} ] + - log/DUP (exit) @ location: 29 + [ 2 + 1 + {} ] + - DUP (entry) @ location: 31 + [ 2 + 1 + {} ] + - log/DIP (exit) @ location: 31 + [ 2 + 2 + 1 + {} ] + - DIP (entry) @ location: 32 + [ 2 + 2 + 1 + {} ] + - log/DUP (exit) @ location: 32 + [ 1 + {} ] + - DUP (entry) @ location: 35 + [ 1 + {} ] + - log/[halt] (exit) @ location: 35 + [ 1 + 1 + {} ] + - [halt] (entry) @ location: 35 + [ 1 + 1 + {} ] + - log/DIP (exit) @ location: 32 + [ 2 + 2 + 1 + 1 + {} ] + - DIP (entry) @ location: 36 + [ 2 + 2 + 1 + 1 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 2 + 1 + 1 + {} ] + - COMPARE (entry) @ location: 39 + [ 2 + 1 + 1 + {} ] + - log/LT (exit) @ location: 39 + [ 1 + 1 + {} ] + - LT (entry) @ location: 40 + [ 1 + 1 + {} ] + - log/[halt] (exit) @ location: 40 + [ False + 1 + {} ] + - [halt] (entry) @ location: 38 + [ False + 1 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 2 + False + 1 + {} ] + - SWAP (entry) @ location: 41 + [ 2 + False + 1 + {} ] + - log/[halt] (exit) @ location: 41 + [ False + 2 + 1 + {} ] + - [halt] (entry) @ location: 30 + [ False + 2 + 1 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + False + 2 + 1 + {} ] + - SWAP (entry) @ location: 42 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + False + 2 + 1 + {} ] + - log/IF (exit) @ location: 42 + [ False + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 1 + {} ] + - IF (entry) @ location: 43 + [ False + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 1 + {} ] + - log/SWAP (exit) @ location: 43 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 1 + {} ] + - SWAP (entry) @ location: 55 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 1 + {} ] + - log/CONS (exit) @ location: 55 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - CONS (entry) @ location: 56 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - log/PUSH (exit) @ location: 56 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - PUSH (entry) @ location: 57 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - log/[halt] (exit) @ location: 57 + [ False + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - SWAP (entry) @ location: 66 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + {} ] + - log/CONS (exit) @ location: 66 + [ 1 + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - CONS (entry) @ location: 67 + [ 1 + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - log/SWAP (exit) @ location: 67 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - SWAP (entry) @ location: 68 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - log/ITER (exit) @ location: 68 + [ {} + { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - ITER (entry) @ location: 69 + [ {} + { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 13 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 4 + { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - SWAP (entry) @ location: 15 + [ 4 + { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/DIP (exit) @ location: 15 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 ] + - DIP (entry) @ location: 16 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - PUSH (entry) @ location: 21 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 1 ; 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - log/SWAP (exit) @ location: 26 + [ 1 + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - SWAP (entry) @ location: 28 + [ 1 + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + {} ] + - log/DIP (exit) @ location: 28 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 4 + {} ] + - DIP (entry) @ location: 29 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 4 + {} ] + - log/DUP (exit) @ location: 29 + [ 1 + 4 + {} ] + - DUP (entry) @ location: 31 + [ 1 + 4 + {} ] + - log/DIP (exit) @ location: 31 + [ 1 + 1 + 4 + {} ] + - DIP (entry) @ location: 32 + [ 1 + 1 + 4 + {} ] + - log/DUP (exit) @ location: 32 + [ 4 + {} ] + - DUP (entry) @ location: 35 + [ 4 + {} ] + - log/[halt] (exit) @ location: 35 + [ 4 + 4 + {} ] + - [halt] (entry) @ location: 35 + [ 4 + 4 + {} ] + - log/DIP (exit) @ location: 32 + [ 1 + 1 + 4 + 4 + {} ] + - DIP (entry) @ location: 36 + [ 1 + 1 + 4 + 4 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 1 + 4 + 4 + {} ] + - COMPARE (entry) @ location: 39 + [ 1 + 4 + 4 + {} ] + - log/LT (exit) @ location: 39 + [ -1 + 4 + {} ] + - LT (entry) @ location: 40 + [ -1 + 4 + {} ] + - log/[halt] (exit) @ location: 40 + [ True + 4 + {} ] + - [halt] (entry) @ location: 38 + [ True + 4 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 1 + True + 4 + {} ] + - SWAP (entry) @ location: 41 + [ 1 + True + 4 + {} ] + - log/[halt] (exit) @ location: 41 + [ True + 1 + 4 + {} ] + - [halt] (entry) @ location: 30 + [ True + 1 + 4 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + True + 1 + 4 + {} ] + - SWAP (entry) @ location: 42 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + True + 1 + 4 + {} ] + - log/IF (exit) @ location: 42 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 4 + {} ] + - IF (entry) @ location: 43 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 4 + {} ] + - log/DIP (exit) @ location: 43 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 4 + {} ] + - DIP (entry) @ location: 45 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 4 + {} ] + - log/SWAP (exit) @ location: 45 + [ 1 + 4 + {} ] + - SWAP (entry) @ location: 47 + [ 1 + 4 + {} ] + - log/DIP (exit) @ location: 47 + [ 4 + 1 + {} ] + - DIP (entry) @ location: 48 + [ 4 + 1 + {} ] + - log/CONS (exit) @ location: 48 + [ 1 + {} ] + - CONS (entry) @ location: 50 + [ 1 + {} ] + - log/[halt] (exit) @ location: 50 + [ { 1 } ] + - [halt] (entry) @ location: 50 + [ { 1 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 4 + { 1 } ] + - [halt] (entry) @ location: 46 + [ 4 + { 1 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - PUSH (entry) @ location: 51 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - IF_CONS (entry) @ location: 26 + [ { 2 ; 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - log/SWAP (exit) @ location: 26 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - SWAP (entry) @ location: 28 + [ 2 + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 1 } ] + - log/DIP (exit) @ location: 28 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 4 + { 1 } ] + - DIP (entry) @ location: 29 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 4 + { 1 } ] + - log/DUP (exit) @ location: 29 + [ 2 + 4 + { 1 } ] + - DUP (entry) @ location: 31 + [ 2 + 4 + { 1 } ] + - log/DIP (exit) @ location: 31 + [ 2 + 2 + 4 + { 1 } ] + - DIP (entry) @ location: 32 + [ 2 + 2 + 4 + { 1 } ] + - log/DUP (exit) @ location: 32 + [ 4 + { 1 } ] + - DUP (entry) @ location: 35 + [ 4 + { 1 } ] + - log/[halt] (exit) @ location: 35 + [ 4 + 4 + { 1 } ] + - [halt] (entry) @ location: 35 + [ 4 + 4 + { 1 } ] + - log/DIP (exit) @ location: 32 + [ 2 + 2 + 4 + 4 + { 1 } ] + - DIP (entry) @ location: 36 + [ 2 + 2 + 4 + 4 + { 1 } ] + - log/COMPARE (exit) @ location: 36 + [ 2 + 4 + 4 + { 1 } ] + - COMPARE (entry) @ location: 39 + [ 2 + 4 + 4 + { 1 } ] + - log/LT (exit) @ location: 39 + [ -1 + 4 + { 1 } ] + - LT (entry) @ location: 40 + [ -1 + 4 + { 1 } ] + - log/[halt] (exit) @ location: 40 + [ True + 4 + { 1 } ] + - [halt] (entry) @ location: 38 + [ True + 4 + { 1 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 2 + True + 4 + { 1 } ] + - SWAP (entry) @ location: 41 + [ 2 + True + 4 + { 1 } ] + - log/[halt] (exit) @ location: 41 + [ True + 2 + 4 + { 1 } ] + - [halt] (entry) @ location: 30 + [ True + 2 + 4 + { 1 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + True + 2 + 4 + { 1 } ] + - SWAP (entry) @ location: 42 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + True + 2 + 4 + { 1 } ] + - log/IF (exit) @ location: 42 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 4 + { 1 } ] + - IF (entry) @ location: 43 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 4 + { 1 } ] + - log/DIP (exit) @ location: 43 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 4 + { 1 } ] + - DIP (entry) @ location: 45 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 2 + 4 + { 1 } ] + - log/SWAP (exit) @ location: 45 + [ 2 + 4 + { 1 } ] + - SWAP (entry) @ location: 47 + [ 2 + 4 + { 1 } ] + - log/DIP (exit) @ location: 47 + [ 4 + 2 + { 1 } ] + - DIP (entry) @ location: 48 + [ 4 + 2 + { 1 } ] + - log/CONS (exit) @ location: 48 + [ 2 + { 1 } ] + - CONS (entry) @ location: 50 + [ 2 + { 1 } ] + - log/[halt] (exit) @ location: 50 + [ { 2 ; 1 } ] + - [halt] (entry) @ location: 50 + [ { 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 46 + [ 4 + { 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - PUSH (entry) @ location: 51 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - IF_CONS (entry) @ location: 26 + [ { 3 ; 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - log/SWAP (exit) @ location: 26 + [ 3 + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - SWAP (entry) @ location: 28 + [ 3 + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 2 ; 1 } ] + - log/DIP (exit) @ location: 28 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 3 + 4 + { 2 ; 1 } ] + - DIP (entry) @ location: 29 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 3 + 4 + { 2 ; 1 } ] + - log/DUP (exit) @ location: 29 + [ 3 + 4 + { 2 ; 1 } ] + - DUP (entry) @ location: 31 + [ 3 + 4 + { 2 ; 1 } ] + - log/DIP (exit) @ location: 31 + [ 3 + 3 + 4 + { 2 ; 1 } ] + - DIP (entry) @ location: 32 + [ 3 + 3 + 4 + { 2 ; 1 } ] + - log/DUP (exit) @ location: 32 + [ 4 + { 2 ; 1 } ] + - DUP (entry) @ location: 35 + [ 4 + { 2 ; 1 } ] + - log/[halt] (exit) @ location: 35 + [ 4 + 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 35 + [ 4 + 4 + { 2 ; 1 } ] + - log/DIP (exit) @ location: 32 + [ 3 + 3 + 4 + 4 + { 2 ; 1 } ] + - DIP (entry) @ location: 36 + [ 3 + 3 + 4 + 4 + { 2 ; 1 } ] + - log/COMPARE (exit) @ location: 36 + [ 3 + 4 + 4 + { 2 ; 1 } ] + - COMPARE (entry) @ location: 39 + [ 3 + 4 + 4 + { 2 ; 1 } ] + - log/LT (exit) @ location: 39 + [ -1 + 4 + { 2 ; 1 } ] + - LT (entry) @ location: 40 + [ -1 + 4 + { 2 ; 1 } ] + - log/[halt] (exit) @ location: 40 + [ True + 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 38 + [ True + 4 + { 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 3 + True + 4 + { 2 ; 1 } ] + - SWAP (entry) @ location: 41 + [ 3 + True + 4 + { 2 ; 1 } ] + - log/[halt] (exit) @ location: 41 + [ True + 3 + 4 + { 2 ; 1 } ] + - [halt] (entry) @ location: 30 + [ True + 3 + 4 + { 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + True + 3 + 4 + { 2 ; 1 } ] + - SWAP (entry) @ location: 42 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + True + 3 + 4 + { 2 ; 1 } ] + - log/IF (exit) @ location: 42 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 3 + 4 + { 2 ; 1 } ] + - IF (entry) @ location: 43 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 3 + 4 + { 2 ; 1 } ] + - log/DIP (exit) @ location: 43 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 3 + 4 + { 2 ; 1 } ] + - DIP (entry) @ location: 45 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 3 + 4 + { 2 ; 1 } ] + - log/SWAP (exit) @ location: 45 + [ 3 + 4 + { 2 ; 1 } ] + - SWAP (entry) @ location: 47 + [ 3 + 4 + { 2 ; 1 } ] + - log/DIP (exit) @ location: 47 + [ 4 + 3 + { 2 ; 1 } ] + - DIP (entry) @ location: 48 + [ 4 + 3 + { 2 ; 1 } ] + - log/CONS (exit) @ location: 48 + [ 3 + { 2 ; 1 } ] + - CONS (entry) @ location: 50 + [ 3 + { 2 ; 1 } ] + - log/[halt] (exit) @ location: 50 + [ { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 50 + [ { 3 ; 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 48 + [ 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 46 + [ 4 + { 3 ; 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 45 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - PUSH (entry) @ location: 51 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - log/[halt] (exit) @ location: 51 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ True + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - IF_CONS (entry) @ location: 26 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - log/SWAP (exit) @ location: 26 + [ 5 + { 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - SWAP (entry) @ location: 28 + [ 5 + { 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - log/DIP (exit) @ location: 28 + [ { 6 ; 7 ; 8 ; 9 } + 5 + 4 + { 3 ; 2 ; 1 } ] + - DIP (entry) @ location: 29 + [ { 6 ; 7 ; 8 ; 9 } + 5 + 4 + { 3 ; 2 ; 1 } ] + - log/DUP (exit) @ location: 29 + [ 5 + 4 + { 3 ; 2 ; 1 } ] + - DUP (entry) @ location: 31 + [ 5 + 4 + { 3 ; 2 ; 1 } ] + - log/DIP (exit) @ location: 31 + [ 5 + 5 + 4 + { 3 ; 2 ; 1 } ] + - DIP (entry) @ location: 32 + [ 5 + 5 + 4 + { 3 ; 2 ; 1 } ] + - log/DUP (exit) @ location: 32 + [ 4 + { 3 ; 2 ; 1 } ] + - DUP (entry) @ location: 35 + [ 4 + { 3 ; 2 ; 1 } ] + - log/[halt] (exit) @ location: 35 + [ 4 + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 35 + [ 4 + 4 + { 3 ; 2 ; 1 } ] + - log/DIP (exit) @ location: 32 + [ 5 + 5 + 4 + 4 + { 3 ; 2 ; 1 } ] + - DIP (entry) @ location: 36 + [ 5 + 5 + 4 + 4 + { 3 ; 2 ; 1 } ] + - log/COMPARE (exit) @ location: 36 + [ 5 + 4 + 4 + { 3 ; 2 ; 1 } ] + - COMPARE (entry) @ location: 39 + [ 5 + 4 + 4 + { 3 ; 2 ; 1 } ] + - log/LT (exit) @ location: 39 + [ 1 + 4 + { 3 ; 2 ; 1 } ] + - LT (entry) @ location: 40 + [ 1 + 4 + { 3 ; 2 ; 1 } ] + - log/[halt] (exit) @ location: 40 + [ False + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 38 + [ False + 4 + { 3 ; 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 5 + False + 4 + { 3 ; 2 ; 1 } ] + - SWAP (entry) @ location: 41 + [ 5 + False + 4 + { 3 ; 2 ; 1 } ] + - log/[halt] (exit) @ location: 41 + [ False + 5 + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 30 + [ False + 5 + 4 + { 3 ; 2 ; 1 } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 6 ; 7 ; 8 ; 9 } + False + 5 + 4 + { 3 ; 2 ; 1 } ] + - SWAP (entry) @ location: 42 + [ { 6 ; 7 ; 8 ; 9 } + False + 5 + 4 + { 3 ; 2 ; 1 } ] + - log/IF (exit) @ location: 42 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + 4 + { 3 ; 2 ; 1 } ] + - IF (entry) @ location: 43 + [ False + { 6 ; 7 ; 8 ; 9 } + 5 + 4 + { 3 ; 2 ; 1 } ] + - log/SWAP (exit) @ location: 43 + [ { 6 ; 7 ; 8 ; 9 } + 5 + 4 + { 3 ; 2 ; 1 } ] + - SWAP (entry) @ location: 55 + [ { 6 ; 7 ; 8 ; 9 } + 5 + 4 + { 3 ; 2 ; 1 } ] + - log/CONS (exit) @ location: 55 + [ 5 + { 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - CONS (entry) @ location: 56 + [ 5 + { 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - log/PUSH (exit) @ location: 56 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - PUSH (entry) @ location: 57 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - log/[halt] (exit) @ location: 57 + [ False + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ False + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ False + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - [halt] (entry) @ location: 66 + [ False + { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - SWAP (entry) @ location: 66 + [ { 5 ; 6 ; 7 ; 8 ; 9 } + 4 + { 3 ; 2 ; 1 } ] + - log/CONS (exit) @ location: 66 + [ 4 + { 5 ; 6 ; 7 ; 8 ; 9 } + { 3 ; 2 ; 1 } ] + - CONS (entry) @ location: 67 + [ 4 + { 5 ; 6 ; 7 ; 8 ; 9 } + { 3 ; 2 ; 1 } ] + - log/SWAP (exit) @ location: 67 + [ { 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + { 3 ; 2 ; 1 } ] + - SWAP (entry) @ location: 68 + [ { 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + { 3 ; 2 ; 1 } ] + - log/ITER (exit) @ location: 68 + [ { 3 ; 2 ; 1 } + { 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - ITER (entry) @ location: 69 + [ { 3 ; 2 ; 1 } + { 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 3 + { 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 3 + { 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 2 + { 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 2 + { 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/CONS (exit) @ location: 69 + [ 1 + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - CONS (entry) @ location: 71 + [ 1 + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 71 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 69 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 13 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - log/SWAP (exit) @ location: 13 + [ 0 + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - SWAP (entry) @ location: 15 + [ 0 + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/DIP (exit) @ location: 15 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 ] + - DIP (entry) @ location: 16 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 ] + - log/NIL (exit) @ location: 16 + [ ] + - NIL (entry) @ location: 19 + [ ] + - log/[halt] (exit) @ location: 19 + [ {} ] + - [halt] (entry) @ location: 19 + [ {} ] + - log/PUSH (exit) @ location: 16 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - PUSH (entry) @ location: 21 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - log/LOOP (exit) @ location: 21 + [ True + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - LOOP (entry) @ location: 66 + [ True + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 66 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - IF_CONS (entry) @ location: 26 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - log/SWAP (exit) @ location: 26 + [ 1 + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - SWAP (entry) @ location: 28 + [ 1 + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - log/DIP (exit) @ location: 28 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 0 + {} ] + - DIP (entry) @ location: 29 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 0 + {} ] + - log/DUP (exit) @ location: 29 + [ 1 + 0 + {} ] + - DUP (entry) @ location: 31 + [ 1 + 0 + {} ] + - log/DIP (exit) @ location: 31 + [ 1 + 1 + 0 + {} ] + - DIP (entry) @ location: 32 + [ 1 + 1 + 0 + {} ] + - log/DUP (exit) @ location: 32 + [ 0 + {} ] + - DUP (entry) @ location: 35 + [ 0 + {} ] + - log/[halt] (exit) @ location: 35 + [ 0 + 0 + {} ] + - [halt] (entry) @ location: 35 + [ 0 + 0 + {} ] + - log/DIP (exit) @ location: 32 + [ 1 + 1 + 0 + 0 + {} ] + - DIP (entry) @ location: 36 + [ 1 + 1 + 0 + 0 + {} ] + - log/COMPARE (exit) @ location: 36 + [ 1 + 0 + 0 + {} ] + - COMPARE (entry) @ location: 39 + [ 1 + 0 + 0 + {} ] + - log/LT (exit) @ location: 39 + [ 1 + 0 + {} ] + - LT (entry) @ location: 40 + [ 1 + 0 + {} ] + - log/[halt] (exit) @ location: 40 + [ False + 0 + {} ] + - [halt] (entry) @ location: 38 + [ False + 0 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 36 + [ 1 + False + 0 + {} ] + - SWAP (entry) @ location: 41 + [ 1 + False + 0 + {} ] + - log/[halt] (exit) @ location: 41 + [ False + 1 + 0 + {} ] + - [halt] (entry) @ location: 30 + [ False + 1 + 0 + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 29 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + False + 1 + 0 + {} ] + - SWAP (entry) @ location: 42 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + False + 1 + 0 + {} ] + - log/IF (exit) @ location: 42 + [ False + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 0 + {} ] + - IF (entry) @ location: 43 + [ False + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 0 + {} ] + - log/SWAP (exit) @ location: 43 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 0 + {} ] + - SWAP (entry) @ location: 55 + [ { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 1 + 0 + {} ] + - log/CONS (exit) @ location: 55 + [ 1 + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - CONS (entry) @ location: 56 + [ 1 + { 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - log/PUSH (exit) @ location: 56 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - PUSH (entry) @ location: 57 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - log/[halt] (exit) @ location: 57 + [ False + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 43 + [ False + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - control: KCons + - log/[halt] (exit) @ location: 26 + [ False + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - [halt] (entry) @ location: 66 + [ False + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - control: KLoop_in + - control: KCons + - log/SWAP (exit) @ location: 66 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - SWAP (entry) @ location: 66 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + 0 + {} ] + - log/CONS (exit) @ location: 66 + [ 0 + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - CONS (entry) @ location: 67 + [ 0 + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - log/SWAP (exit) @ location: 67 + [ { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - SWAP (entry) @ location: 68 + [ { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } + {} ] + - log/ITER (exit) @ location: 68 + [ {} + { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - ITER (entry) @ location: 69 + [ {} + { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - control: KCons + - log/[halt] (exit) @ location: 69 + [ { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - [halt] (entry) @ location: 13 + [ { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - control: KIter + - control: KCons + - log/NIL (exit) @ location: 13 + [ { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - NIL (entry) @ location: 72 + [ { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/PAIR (exit) @ location: 72 + [ {} + { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - PAIR (entry) @ location: 74 + [ {} + { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 } ] + - log/[halt] (exit) @ location: 74 + [ (Pair {} { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 }) ] + - [halt] (entry) @ location: 8 + [ (Pair {} { 0 ; 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/list_map_block.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/list_map_block.out new file mode 100644 index 000000000000..202f29541787 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/list_map_block.out @@ -0,0 +1,451 @@ + +trace + - CAR (interp) @ location: 9 + [ (Pair { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } {}) ] + - CAR (entry) @ location: 9 + [ (Pair { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } {}) ] + - log/PUSH (exit) @ location: 9 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } ] + - PUSH (entry) @ location: 10 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } ] + - log/SWAP (exit) @ location: 10 + [ 0 + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } ] + - SWAP (entry) @ location: 13 + [ 0 + { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } ] + - log/MAP (exit) @ location: 13 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } + 0 ] + - MAP (entry) @ location: 14 + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 } + 0 ] + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 1 + 0 ] + - DIP (entry) @ location: 16 + [ 1 + 0 ] + - log/DUP (exit) @ location: 16 + [ 0 ] + - DUP (entry) @ location: 18 + [ 0 ] + - log/[halt] (exit) @ location: 18 + [ 0 + 0 ] + - [halt] (entry) @ location: 18 + [ 0 + 0 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 1 + 0 + 0 ] + - ADD (entry) @ location: 19 + [ 1 + 0 + 0 ] + - log/DIP (exit) @ location: 19 + [ 1 + 0 ] + - DIP (entry) @ location: 20 + [ 1 + 0 ] + - log/PUSH (exit) @ location: 20 + [ 0 ] + - PUSH (entry) @ location: 22 + [ 0 ] + - log/ADD (exit) @ location: 22 + [ 1 + 0 ] + - ADD (entry) @ location: 25 + [ 1 + 0 ] + - log/[halt] (exit) @ location: 25 + [ 1 ] + - [halt] (entry) @ location: 21 + [ 1 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 1 + 1 ] + - [halt] (entry) @ location: 14 + [ 1 + 1 ] + - control: KList_exit_body + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 2 + 1 ] + - DIP (entry) @ location: 16 + [ 2 + 1 ] + - log/DUP (exit) @ location: 16 + [ 1 ] + - DUP (entry) @ location: 18 + [ 1 ] + - log/[halt] (exit) @ location: 18 + [ 1 + 1 ] + - [halt] (entry) @ location: 18 + [ 1 + 1 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 2 + 1 + 1 ] + - ADD (entry) @ location: 19 + [ 2 + 1 + 1 ] + - log/DIP (exit) @ location: 19 + [ 3 + 1 ] + - DIP (entry) @ location: 20 + [ 3 + 1 ] + - log/PUSH (exit) @ location: 20 + [ 1 ] + - PUSH (entry) @ location: 22 + [ 1 ] + - log/ADD (exit) @ location: 22 + [ 1 + 1 ] + - ADD (entry) @ location: 25 + [ 1 + 1 ] + - log/[halt] (exit) @ location: 25 + [ 2 ] + - [halt] (entry) @ location: 21 + [ 2 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 3 + 2 ] + - [halt] (entry) @ location: 14 + [ 3 + 2 ] + - control: KList_exit_body + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 3 + 2 ] + - DIP (entry) @ location: 16 + [ 3 + 2 ] + - log/DUP (exit) @ location: 16 + [ 2 ] + - DUP (entry) @ location: 18 + [ 2 ] + - log/[halt] (exit) @ location: 18 + [ 2 + 2 ] + - [halt] (entry) @ location: 18 + [ 2 + 2 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 3 + 2 + 2 ] + - ADD (entry) @ location: 19 + [ 3 + 2 + 2 ] + - log/DIP (exit) @ location: 19 + [ 5 + 2 ] + - DIP (entry) @ location: 20 + [ 5 + 2 ] + - log/PUSH (exit) @ location: 20 + [ 2 ] + - PUSH (entry) @ location: 22 + [ 2 ] + - log/ADD (exit) @ location: 22 + [ 1 + 2 ] + - ADD (entry) @ location: 25 + [ 1 + 2 ] + - log/[halt] (exit) @ location: 25 + [ 3 ] + - [halt] (entry) @ location: 21 + [ 3 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 5 + 3 ] + - [halt] (entry) @ location: 14 + [ 5 + 3 ] + - control: KList_exit_body + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 4 + 3 ] + - DIP (entry) @ location: 16 + [ 4 + 3 ] + - log/DUP (exit) @ location: 16 + [ 3 ] + - DUP (entry) @ location: 18 + [ 3 ] + - log/[halt] (exit) @ location: 18 + [ 3 + 3 ] + - [halt] (entry) @ location: 18 + [ 3 + 3 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 4 + 3 + 3 ] + - ADD (entry) @ location: 19 + [ 4 + 3 + 3 ] + - log/DIP (exit) @ location: 19 + [ 7 + 3 ] + - DIP (entry) @ location: 20 + [ 7 + 3 ] + - log/PUSH (exit) @ location: 20 + [ 3 ] + - PUSH (entry) @ location: 22 + [ 3 ] + - log/ADD (exit) @ location: 22 + [ 1 + 3 ] + - ADD (entry) @ location: 25 + [ 1 + 3 ] + - log/[halt] (exit) @ location: 25 + [ 4 ] + - [halt] (entry) @ location: 21 + [ 4 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 7 + 4 ] + - [halt] (entry) @ location: 14 + [ 7 + 4 ] + - control: KList_exit_body + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 5 + 4 ] + - DIP (entry) @ location: 16 + [ 5 + 4 ] + - log/DUP (exit) @ location: 16 + [ 4 ] + - DUP (entry) @ location: 18 + [ 4 ] + - log/[halt] (exit) @ location: 18 + [ 4 + 4 ] + - [halt] (entry) @ location: 18 + [ 4 + 4 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 5 + 4 + 4 ] + - ADD (entry) @ location: 19 + [ 5 + 4 + 4 ] + - log/DIP (exit) @ location: 19 + [ 9 + 4 ] + - DIP (entry) @ location: 20 + [ 9 + 4 ] + - log/PUSH (exit) @ location: 20 + [ 4 ] + - PUSH (entry) @ location: 22 + [ 4 ] + - log/ADD (exit) @ location: 22 + [ 1 + 4 ] + - ADD (entry) @ location: 25 + [ 1 + 4 ] + - log/[halt] (exit) @ location: 25 + [ 5 ] + - [halt] (entry) @ location: 21 + [ 5 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 9 + 5 ] + - [halt] (entry) @ location: 14 + [ 9 + 5 ] + - control: KList_exit_body + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 6 + 5 ] + - DIP (entry) @ location: 16 + [ 6 + 5 ] + - log/DUP (exit) @ location: 16 + [ 5 ] + - DUP (entry) @ location: 18 + [ 5 ] + - log/[halt] (exit) @ location: 18 + [ 5 + 5 ] + - [halt] (entry) @ location: 18 + [ 5 + 5 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 6 + 5 + 5 ] + - ADD (entry) @ location: 19 + [ 6 + 5 + 5 ] + - log/DIP (exit) @ location: 19 + [ 11 + 5 ] + - DIP (entry) @ location: 20 + [ 11 + 5 ] + - log/PUSH (exit) @ location: 20 + [ 5 ] + - PUSH (entry) @ location: 22 + [ 5 ] + - log/ADD (exit) @ location: 22 + [ 1 + 5 ] + - ADD (entry) @ location: 25 + [ 1 + 5 ] + - log/[halt] (exit) @ location: 25 + [ 6 ] + - [halt] (entry) @ location: 21 + [ 6 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 11 + 6 ] + - [halt] (entry) @ location: 14 + [ 11 + 6 ] + - control: KList_exit_body + - control: KList_enter_body + - log/DIP (exit) @ location: 14 + [ 7 + 6 ] + - DIP (entry) @ location: 16 + [ 7 + 6 ] + - log/DUP (exit) @ location: 16 + [ 6 ] + - DUP (entry) @ location: 18 + [ 6 ] + - log/[halt] (exit) @ location: 18 + [ 6 + 6 ] + - [halt] (entry) @ location: 18 + [ 6 + 6 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 16 + [ 7 + 6 + 6 ] + - ADD (entry) @ location: 19 + [ 7 + 6 + 6 ] + - log/DIP (exit) @ location: 19 + [ 13 + 6 ] + - DIP (entry) @ location: 20 + [ 13 + 6 ] + - log/PUSH (exit) @ location: 20 + [ 6 ] + - PUSH (entry) @ location: 22 + [ 6 ] + - log/ADD (exit) @ location: 22 + [ 1 + 6 ] + - ADD (entry) @ location: 25 + [ 1 + 6 ] + - log/[halt] (exit) @ location: 25 + [ 7 ] + - [halt] (entry) @ location: 21 + [ 7 ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 20 + [ 13 + 7 ] + - [halt] (entry) @ location: 14 + [ 13 + 7 ] + - control: KList_exit_body + - control: KList_enter_body + - control: KCons + - log/NIL (exit) @ location: 14 + [ { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 } + 7 ] + - NIL (entry) @ location: 26 + [ { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 } + 7 ] + - log/PAIR (exit) @ location: 26 + [ {} + { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 } + 7 ] + - PAIR (entry) @ location: 28 + [ {} + { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 } + 7 ] + - log/DIP (exit) @ location: 28 + [ (Pair {} { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 }) + 7 ] + - DIP (entry) @ location: 29 + [ (Pair {} { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 }) + 7 ] + - log/DROP (exit) @ location: 29 + [ 7 ] + - DROP (entry) @ location: 31 + [ 7 ] + - log/[halt] (exit) @ location: 31 + [ ] + - [halt] (entry) @ location: 31 + [ ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 29 + [ (Pair {} { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 }) ] + - [halt] (entry) @ location: 8 + [ (Pair {} { 1 ; 3 ; 5 ; 7 ; 9 ; 11 ; 13 }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/loop_left.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/loop_left.out new file mode 100644 index 000000000000..896f7396ad68 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/loop_left.out @@ -0,0 +1,253 @@ + +trace + - CAR (interp) @ location: 9 + [ (Pair { "abc" ; "xyz" } { "zyx" ; "cba" }) ] + - CAR (entry) @ location: 9 + [ (Pair { "abc" ; "xyz" } { "zyx" ; "cba" }) ] + - log/NIL (exit) @ location: 9 + [ { "abc" ; "xyz" } ] + - NIL (entry) @ location: 10 + [ { "abc" ; "xyz" } ] + - log/SWAP (exit) @ location: 10 + [ {} + { "abc" ; "xyz" } ] + - SWAP (entry) @ location: 12 + [ {} + { "abc" ; "xyz" } ] + - log/PAIR (exit) @ location: 12 + [ { "abc" ; "xyz" } + {} ] + - PAIR (entry) @ location: 13 + [ { "abc" ; "xyz" } + {} ] + - log/LEFT (exit) @ location: 13 + [ (Pair { "abc" ; "xyz" } {}) ] + - LEFT (entry) @ location: 14 + [ (Pair { "abc" ; "xyz" } {}) ] + - log/LOOP_LEFT (exit) @ location: 14 + [ (Left (Pair { "abc" ; "xyz" } {})) ] + - LOOP_LEFT (entry) @ location: 41 + [ (Left (Pair { "abc" ; "xyz" } {})) ] + - control: KLoop_in_left + - log/DUP (exit) @ location: 41 + [ (Pair { "abc" ; "xyz" } {}) ] + - DUP (entry) @ location: 19 + [ (Pair { "abc" ; "xyz" } {}) ] + - log/CAR (exit) @ location: 19 + [ (Pair { "abc" ; "xyz" } {}) + (Pair { "abc" ; "xyz" } {}) ] + - CAR (entry) @ location: 20 + [ (Pair { "abc" ; "xyz" } {}) + (Pair { "abc" ; "xyz" } {}) ] + - log/DIP (exit) @ location: 20 + [ { "abc" ; "xyz" } + (Pair { "abc" ; "xyz" } {}) ] + - DIP (entry) @ location: 21 + [ { "abc" ; "xyz" } + (Pair { "abc" ; "xyz" } {}) ] + - log/CDR (exit) @ location: 21 + [ (Pair { "abc" ; "xyz" } {}) ] + - CDR (entry) @ location: 23 + [ (Pair { "abc" ; "xyz" } {}) ] + - log/[halt] (exit) @ location: 23 + [ {} ] + - [halt] (entry) @ location: 23 + [ {} ] + - control: KUndip + - control: KCons + - log/IF_CONS (exit) @ location: 21 + [ { "abc" ; "xyz" } + {} ] + - IF_CONS (entry) @ location: 24 + [ { "abc" ; "xyz" } + {} ] + - log/SWAP (exit) @ location: 24 + [ "abc" + { "xyz" } + {} ] + - SWAP (entry) @ location: 26 + [ "abc" + { "xyz" } + {} ] + - log/DIP (exit) @ location: 26 + [ { "xyz" } + "abc" + {} ] + - DIP (entry) @ location: 27 + [ { "xyz" } + "abc" + {} ] + - log/CONS (exit) @ location: 27 + [ "abc" + {} ] + - CONS (entry) @ location: 29 + [ "abc" + {} ] + - log/[halt] (exit) @ location: 29 + [ { "abc" } ] + - [halt] (entry) @ location: 29 + [ { "abc" } ] + - control: KUndip + - control: KCons + - log/PAIR (exit) @ location: 27 + [ { "xyz" } + { "abc" } ] + - PAIR (entry) @ location: 30 + [ { "xyz" } + { "abc" } ] + - log/LEFT (exit) @ location: 30 + [ (Pair { "xyz" } { "abc" }) ] + - LEFT (entry) @ location: 31 + [ (Pair { "xyz" } { "abc" }) ] + - log/[halt] (exit) @ location: 31 + [ (Left (Pair { "xyz" } { "abc" })) ] + - [halt] (entry) @ location: 41 + [ (Left (Pair { "xyz" } { "abc" })) ] + - control: KCons + - log/[halt] (exit) @ location: 24 + [ (Left (Pair { "xyz" } { "abc" })) ] + - [halt] (entry) @ location: 41 + [ (Left (Pair { "xyz" } { "abc" })) ] + - control: KLoop_in_left + - log/DUP (exit) @ location: 41 + [ (Pair { "xyz" } { "abc" }) ] + - DUP (entry) @ location: 19 + [ (Pair { "xyz" } { "abc" }) ] + - log/CAR (exit) @ location: 19 + [ (Pair { "xyz" } { "abc" }) + (Pair { "xyz" } { "abc" }) ] + - CAR (entry) @ location: 20 + [ (Pair { "xyz" } { "abc" }) + (Pair { "xyz" } { "abc" }) ] + - log/DIP (exit) @ location: 20 + [ { "xyz" } + (Pair { "xyz" } { "abc" }) ] + - DIP (entry) @ location: 21 + [ { "xyz" } + (Pair { "xyz" } { "abc" }) ] + - log/CDR (exit) @ location: 21 + [ (Pair { "xyz" } { "abc" }) ] + - CDR (entry) @ location: 23 + [ (Pair { "xyz" } { "abc" }) ] + - log/[halt] (exit) @ location: 23 + [ { "abc" } ] + - [halt] (entry) @ location: 23 + [ { "abc" } ] + - control: KUndip + - control: KCons + - log/IF_CONS (exit) @ location: 21 + [ { "xyz" } + { "abc" } ] + - IF_CONS (entry) @ location: 24 + [ { "xyz" } + { "abc" } ] + - log/SWAP (exit) @ location: 24 + [ "xyz" + {} + { "abc" } ] + - SWAP (entry) @ location: 26 + [ "xyz" + {} + { "abc" } ] + - log/DIP (exit) @ location: 26 + [ {} + "xyz" + { "abc" } ] + - DIP (entry) @ location: 27 + [ {} + "xyz" + { "abc" } ] + - log/CONS (exit) @ location: 27 + [ "xyz" + { "abc" } ] + - CONS (entry) @ location: 29 + [ "xyz" + { "abc" } ] + - log/[halt] (exit) @ location: 29 + [ { "xyz" ; "abc" } ] + - [halt] (entry) @ location: 29 + [ { "xyz" ; "abc" } ] + - control: KUndip + - control: KCons + - log/PAIR (exit) @ location: 27 + [ {} + { "xyz" ; "abc" } ] + - PAIR (entry) @ location: 30 + [ {} + { "xyz" ; "abc" } ] + - log/LEFT (exit) @ location: 30 + [ (Pair {} { "xyz" ; "abc" }) ] + - LEFT (entry) @ location: 31 + [ (Pair {} { "xyz" ; "abc" }) ] + - log/[halt] (exit) @ location: 31 + [ (Left (Pair {} { "xyz" ; "abc" })) ] + - [halt] (entry) @ location: 41 + [ (Left (Pair {} { "xyz" ; "abc" })) ] + - control: KCons + - log/[halt] (exit) @ location: 24 + [ (Left (Pair {} { "xyz" ; "abc" })) ] + - [halt] (entry) @ location: 41 + [ (Left (Pair {} { "xyz" ; "abc" })) ] + - control: KLoop_in_left + - log/DUP (exit) @ location: 41 + [ (Pair {} { "xyz" ; "abc" }) ] + - DUP (entry) @ location: 19 + [ (Pair {} { "xyz" ; "abc" }) ] + - log/CAR (exit) @ location: 19 + [ (Pair {} { "xyz" ; "abc" }) + (Pair {} { "xyz" ; "abc" }) ] + - CAR (entry) @ location: 20 + [ (Pair {} { "xyz" ; "abc" }) + (Pair {} { "xyz" ; "abc" }) ] + - log/DIP (exit) @ location: 20 + [ {} + (Pair {} { "xyz" ; "abc" }) ] + - DIP (entry) @ location: 21 + [ {} + (Pair {} { "xyz" ; "abc" }) ] + - log/CDR (exit) @ location: 21 + [ (Pair {} { "xyz" ; "abc" }) ] + - CDR (entry) @ location: 23 + [ (Pair {} { "xyz" ; "abc" }) ] + - log/[halt] (exit) @ location: 23 + [ { "xyz" ; "abc" } ] + - [halt] (entry) @ location: 23 + [ { "xyz" ; "abc" } ] + - control: KUndip + - control: KCons + - log/IF_CONS (exit) @ location: 21 + [ {} + { "xyz" ; "abc" } ] + - IF_CONS (entry) @ location: 24 + [ {} + { "xyz" ; "abc" } ] + - log/RIGHT (exit) @ location: 24 + [ { "xyz" ; "abc" } ] + - RIGHT (entry) @ location: 35 + [ { "xyz" ; "abc" } ] + - log/[halt] (exit) @ location: 35 + [ (Right { "xyz" ; "abc" }) ] + - [halt] (entry) @ location: 41 + [ (Right { "xyz" ; "abc" }) ] + - control: KCons + - log/[halt] (exit) @ location: 24 + [ (Right { "xyz" ; "abc" }) ] + - [halt] (entry) @ location: 41 + [ (Right { "xyz" ; "abc" }) ] + - control: KLoop_in_left + - control: KCons + - log/NIL (exit) @ location: 41 + [ { "xyz" ; "abc" } ] + - NIL (entry) @ location: 41 + [ { "xyz" ; "abc" } ] + - log/PAIR (exit) @ location: 41 + [ {} + { "xyz" ; "abc" } ] + - PAIR (entry) @ location: 43 + [ {} + { "xyz" ; "abc" } ] + - log/[halt] (exit) @ location: 43 + [ (Pair {} { "xyz" ; "abc" }) ] + - [halt] (entry) @ location: 8 + [ (Pair {} { "xyz" ; "abc" }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/opt_map.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/opt_map.out new file mode 100644 index 000000000000..e46a51e6dc9b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/opt_map.out @@ -0,0 +1,82 @@ + +trace + - UNPAIR (interp) @ location: 8 + [ (Pair 7 (Some 3)) ] + - UNPAIR (entry) @ location: 8 + [ (Pair 7 (Some 3)) ] + - log/SWAP (exit) @ location: 8 + [ 7 + (Some 3) ] + - SWAP (entry) @ location: 9 + [ 7 + (Some 3) ] + - log/MAP (exit) @ location: 9 + [ (Some 3) + 7 ] + - MAP (entry) @ location: 11 + [ (Some 3) + 7 ] + - log/DIP (exit) @ location: 11 + [ 3 + 7 ] + - DIP (entry) @ location: 12 + [ 3 + 7 ] + - log/DUP (exit) @ location: 12 + [ 7 ] + - DUP (entry) @ location: 14 + [ 7 ] + - log/[halt] (exit) @ location: 14 + [ 7 + 7 ] + - [halt] (entry) @ location: 14 + [ 7 + 7 ] + - control: KUndip + - control: KCons + - log/ADD (exit) @ location: 12 + [ 3 + 7 + 7 ] + - ADD (entry) @ location: 15 + [ 3 + 7 + 7 ] + - log/[halt] (exit) @ location: 15 + [ 10 + 7 ] + - [halt] (entry) @ location: 11 + [ 10 + 7 ] + - control: KMap_head + - log/DIP (exit) @ location: 11 + [ (Some 10) + 7 ] + - DIP (entry) @ location: 16 + [ (Some 10) + 7 ] + - log/DROP (exit) @ location: 16 + [ 7 ] + - DROP (entry) @ location: 18 + [ 7 ] + - log/[halt] (exit) @ location: 18 + [ ] + - [halt] (entry) @ location: 18 + [ ] + - control: KUndip + - control: KCons + - log/NIL (exit) @ location: 16 + [ (Some 10) ] + - NIL (entry) @ location: 19 + [ (Some 10) ] + - log/PAIR (exit) @ location: 19 + [ {} + (Some 10) ] + - PAIR (entry) @ location: 21 + [ {} + (Some 10) ] + - log/[halt] (exit) @ location: 21 + [ (Pair {} (Some 10)) ] + - [halt] (entry) @ location: 7 + [ (Pair {} (Some 10)) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/packunpack.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/packunpack.out new file mode 100644 index 000000000000..847e8b481add --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/packunpack.out @@ -0,0 +1,103 @@ + +trace + - CAR (interp) @ location: 15 + [ (Pair (Pair (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006) + Unit) ] + - CAR (entry) @ location: 15 + [ (Pair (Pair (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006) + Unit) ] + - log/UNPAIR (exit) @ location: 15 + [ (Pair (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006) ] + - UNPAIR (entry) @ location: 16 + [ (Pair (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006) ] + - log/DIP (exit) @ location: 16 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - DIP (entry) @ location: 17 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/DUP (exit) @ location: 17 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - DUP (entry) @ location: 19 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/[halt] (exit) @ location: 19 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - [halt] (entry) @ location: 19 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - control: KUndip + - control: KCons + - log/PACK (exit) @ location: 17 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - PACK (entry) @ location: 20 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) + 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/COMPARE (exit) @ location: 20 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - COMPARE (entry) @ location: 23 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/EQ (exit) @ location: 23 + [ 0 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - EQ (entry) @ location: 24 + [ 0 + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/IF (exit) @ location: 24 + [ True + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - IF (entry) @ location: 25 + [ True + 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/[halt] (exit) @ location: 25 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - [halt] (entry) @ location: 31 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - control: KCons + - log/UNPACK (exit) @ location: 25 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - UNPACK (entry) @ location: 31 + [ 0x0507070707010000000361626302000000060001000200030200000006000400050006 ] + - log/IF_NONE (exit) @ location: 31 + [ (Some (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 })) ] + - IF_NONE (entry) @ location: 40 + [ (Some (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 })) ] + - log/[halt] (exit) @ location: 40 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) ] + - [halt] (entry) @ location: 46 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) ] + - control: KCons + - log/DROP (exit) @ location: 40 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) ] + - DROP (entry) @ location: 46 + [ (Pair (Pair "abc" { 1 ; 2 ; 3 }) { 4 ; 5 ; 6 }) ] + - log/UNIT (exit) @ location: 46 + [ ] + - UNIT (entry) @ location: 47 + [ ] + - log/NIL (exit) @ location: 47 + [ Unit ] + - NIL (entry) @ location: 48 + [ Unit ] + - log/PAIR (exit) @ location: 48 + [ {} + Unit ] + - PAIR (entry) @ location: 50 + [ {} + Unit ] + - log/[halt] (exit) @ location: 50 + [ (Pair {} Unit) ] + - [halt] (entry) @ location: 14 + [ (Pair {} Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/pexec.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/pexec.out new file mode 100644 index 000000000000..067af7c55351 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/pexec.out @@ -0,0 +1,83 @@ + +trace + - LAMBDA (interp) @ location: 7 + [ (Pair 7 77) ] + - LAMBDA (entry) @ location: 7 + [ (Pair 7 77) ] + - log/SWAP (exit) @ location: 7 + [ { UNPAIR ; ADD } + (Pair 7 77) ] + - SWAP (entry) @ location: 15 + [ { UNPAIR ; ADD } + (Pair 7 77) ] + - log/UNPAIR (exit) @ location: 15 + [ (Pair 7 77) + { UNPAIR ; ADD } ] + - UNPAIR (entry) @ location: 16 + [ (Pair 7 77) + { UNPAIR ; ADD } ] + - log/DIP (exit) @ location: 16 + [ 7 + 77 + { UNPAIR ; ADD } ] + - DIP (entry) @ location: 17 + [ 7 + 77 + { UNPAIR ; ADD } ] + - log/APPLY (exit) @ location: 17 + [ 77 + { UNPAIR ; ADD } ] + - APPLY (entry) @ location: 19 + [ 77 + { UNPAIR ; ADD } ] + - log/[halt] (exit) @ location: 19 + [ { PUSH nat 77 ; PAIR ; { UNPAIR ; ADD } } ] + - [halt] (entry) @ location: 19 + [ { PUSH nat 77 ; PAIR ; { UNPAIR ; ADD } } ] + - control: KUndip + - control: KCons + - log/EXEC (exit) @ location: 17 + [ 7 + { PUSH nat 77 ; PAIR ; { UNPAIR ; ADD } } ] + - EXEC (entry) @ location: 20 + [ 7 + { PUSH nat 77 ; PAIR ; { UNPAIR ; ADD } } ] + - PUSH (entry) @ location: 12 + [ 7 ] + - log/PAIR (exit) @ location: 12 + [ 77 + 7 ] + - PAIR (entry) @ location: 12 + [ 77 + 7 ] + - log/UNPAIR (exit) @ location: 12 + [ (Pair 77 7) ] + - UNPAIR (entry) @ location: 13 + [ (Pair 77 7) ] + - log/ADD (exit) @ location: 13 + [ 77 + 7 ] + - ADD (entry) @ location: 14 + [ 77 + 7 ] + - log/[halt] (exit) @ location: 14 + [ 84 ] + - [halt] (entry) @ location: 12 + [ 84 ] + - control: KReturn + - control: KCons + - log/NIL (exit) @ location: 20 + [ 84 ] + - NIL (entry) @ location: 21 + [ 84 ] + - log/PAIR (exit) @ location: 21 + [ {} + 84 ] + - PAIR (entry) @ location: 23 + [ {} + 84 ] + - log/[halt] (exit) @ location: 23 + [ (Pair {} 84) ] + - [halt] (entry) @ location: 6 + [ (Pair {} 84) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/rec_id_unit.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/rec_id_unit.out new file mode 100644 index 000000000000..8ac716e1d058 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/rec_id_unit.out @@ -0,0 +1,56 @@ + +trace + - CAR (interp) @ location: 7 + [ (Pair Unit Unit) ] + - CAR (entry) @ location: 7 + [ (Pair Unit Unit) ] + - log/LAMBDA_REC (exit) @ location: 7 + [ Unit ] + - LAMBDA_REC (entry) @ location: 8 + [ Unit ] + - log/SWAP (exit) @ location: 8 + [ (Lambda_rec { DIP { DROP } }) + Unit ] + - SWAP (entry) @ location: 15 + [ (Lambda_rec { DIP { DROP } }) + Unit ] + - log/EXEC (exit) @ location: 15 + [ Unit + (Lambda_rec { DIP { DROP } }) ] + - EXEC (entry) @ location: 16 + [ Unit + (Lambda_rec { DIP { DROP } }) ] + - DIP (entry) @ location: 12 + [ Unit + (Lambda_rec { DIP { DROP } }) ] + - log/DROP (exit) @ location: 12 + [ (Lambda_rec { DIP { DROP } }) ] + - DROP (entry) @ location: 14 + [ (Lambda_rec { DIP { DROP } }) ] + - log/[halt] (exit) @ location: 14 + [ ] + - [halt] (entry) @ location: 14 + [ ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 12 + [ Unit ] + - [halt] (entry) @ location: 12 + [ Unit ] + - control: KReturn + - control: KCons + - log/NIL (exit) @ location: 16 + [ Unit ] + - NIL (entry) @ location: 17 + [ Unit ] + - log/PAIR (exit) @ location: 17 + [ {} + Unit ] + - PAIR (entry) @ location: 19 + [ {} + Unit ] + - log/[halt] (exit) @ location: 19 + [ (Pair {} Unit) ] + - [halt] (entry) @ location: 6 + [ (Pair {} Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/reverse_loop.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/reverse_loop.out new file mode 100644 index 000000000000..76ea2381bed3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/reverse_loop.out @@ -0,0 +1,261 @@ + +trace + - CAR (interp) @ location: 9 + [ (Pair { "abc" ; "def" ; "ghi" } {}) ] + - CAR (entry) @ location: 9 + [ (Pair { "abc" ; "def" ; "ghi" } {}) ] + - log/NIL (exit) @ location: 9 + [ { "abc" ; "def" ; "ghi" } ] + - NIL (entry) @ location: 10 + [ { "abc" ; "def" ; "ghi" } ] + - log/SWAP (exit) @ location: 10 + [ {} + { "abc" ; "def" ; "ghi" } ] + - SWAP (entry) @ location: 12 + [ {} + { "abc" ; "def" ; "ghi" } ] + - log/PUSH (exit) @ location: 12 + [ { "abc" ; "def" ; "ghi" } + {} ] + - PUSH (entry) @ location: 13 + [ { "abc" ; "def" ; "ghi" } + {} ] + - log/LOOP (exit) @ location: 13 + [ True + { "abc" ; "def" ; "ghi" } + {} ] + - LOOP (entry) @ location: 33 + [ True + { "abc" ; "def" ; "ghi" } + {} ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 33 + [ { "abc" ; "def" ; "ghi" } + {} ] + - IF_CONS (entry) @ location: 18 + [ { "abc" ; "def" ; "ghi" } + {} ] + - log/SWAP (exit) @ location: 18 + [ "abc" + { "def" ; "ghi" } + {} ] + - SWAP (entry) @ location: 20 + [ "abc" + { "def" ; "ghi" } + {} ] + - log/DIP (exit) @ location: 20 + [ { "def" ; "ghi" } + "abc" + {} ] + - DIP (entry) @ location: 21 + [ { "def" ; "ghi" } + "abc" + {} ] + - log/CONS (exit) @ location: 21 + [ "abc" + {} ] + - CONS (entry) @ location: 23 + [ "abc" + {} ] + - log/[halt] (exit) @ location: 23 + [ { "abc" } ] + - [halt] (entry) @ location: 23 + [ { "abc" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 21 + [ { "def" ; "ghi" } + { "abc" } ] + - PUSH (entry) @ location: 24 + [ { "def" ; "ghi" } + { "abc" } ] + - log/[halt] (exit) @ location: 24 + [ True + { "def" ; "ghi" } + { "abc" } ] + - [halt] (entry) @ location: 33 + [ True + { "def" ; "ghi" } + { "abc" } ] + - control: KCons + - log/[halt] (exit) @ location: 18 + [ True + { "def" ; "ghi" } + { "abc" } ] + - [halt] (entry) @ location: 33 + [ True + { "def" ; "ghi" } + { "abc" } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 33 + [ { "def" ; "ghi" } + { "abc" } ] + - IF_CONS (entry) @ location: 18 + [ { "def" ; "ghi" } + { "abc" } ] + - log/SWAP (exit) @ location: 18 + [ "def" + { "ghi" } + { "abc" } ] + - SWAP (entry) @ location: 20 + [ "def" + { "ghi" } + { "abc" } ] + - log/DIP (exit) @ location: 20 + [ { "ghi" } + "def" + { "abc" } ] + - DIP (entry) @ location: 21 + [ { "ghi" } + "def" + { "abc" } ] + - log/CONS (exit) @ location: 21 + [ "def" + { "abc" } ] + - CONS (entry) @ location: 23 + [ "def" + { "abc" } ] + - log/[halt] (exit) @ location: 23 + [ { "def" ; "abc" } ] + - [halt] (entry) @ location: 23 + [ { "def" ; "abc" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 21 + [ { "ghi" } + { "def" ; "abc" } ] + - PUSH (entry) @ location: 24 + [ { "ghi" } + { "def" ; "abc" } ] + - log/[halt] (exit) @ location: 24 + [ True + { "ghi" } + { "def" ; "abc" } ] + - [halt] (entry) @ location: 33 + [ True + { "ghi" } + { "def" ; "abc" } ] + - control: KCons + - log/[halt] (exit) @ location: 18 + [ True + { "ghi" } + { "def" ; "abc" } ] + - [halt] (entry) @ location: 33 + [ True + { "ghi" } + { "def" ; "abc" } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 33 + [ { "ghi" } + { "def" ; "abc" } ] + - IF_CONS (entry) @ location: 18 + [ { "ghi" } + { "def" ; "abc" } ] + - log/SWAP (exit) @ location: 18 + [ "ghi" + {} + { "def" ; "abc" } ] + - SWAP (entry) @ location: 20 + [ "ghi" + {} + { "def" ; "abc" } ] + - log/DIP (exit) @ location: 20 + [ {} + "ghi" + { "def" ; "abc" } ] + - DIP (entry) @ location: 21 + [ {} + "ghi" + { "def" ; "abc" } ] + - log/CONS (exit) @ location: 21 + [ "ghi" + { "def" ; "abc" } ] + - CONS (entry) @ location: 23 + [ "ghi" + { "def" ; "abc" } ] + - log/[halt] (exit) @ location: 23 + [ { "ghi" ; "def" ; "abc" } ] + - [halt] (entry) @ location: 23 + [ { "ghi" ; "def" ; "abc" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 21 + [ {} + { "ghi" ; "def" ; "abc" } ] + - PUSH (entry) @ location: 24 + [ {} + { "ghi" ; "def" ; "abc" } ] + - log/[halt] (exit) @ location: 24 + [ True + {} + { "ghi" ; "def" ; "abc" } ] + - [halt] (entry) @ location: 33 + [ True + {} + { "ghi" ; "def" ; "abc" } ] + - control: KCons + - log/[halt] (exit) @ location: 18 + [ True + {} + { "ghi" ; "def" ; "abc" } ] + - [halt] (entry) @ location: 33 + [ True + {} + { "ghi" ; "def" ; "abc" } ] + - control: KLoop_in + - log/IF_CONS (exit) @ location: 33 + [ {} + { "ghi" ; "def" ; "abc" } ] + - IF_CONS (entry) @ location: 18 + [ {} + { "ghi" ; "def" ; "abc" } ] + - log/NIL (exit) @ location: 18 + [ { "ghi" ; "def" ; "abc" } ] + - NIL (entry) @ location: 28 + [ { "ghi" ; "def" ; "abc" } ] + - log/PUSH (exit) @ location: 28 + [ {} + { "ghi" ; "def" ; "abc" } ] + - PUSH (entry) @ location: 30 + [ {} + { "ghi" ; "def" ; "abc" } ] + - log/[halt] (exit) @ location: 30 + [ False + {} + { "ghi" ; "def" ; "abc" } ] + - [halt] (entry) @ location: 33 + [ False + {} + { "ghi" ; "def" ; "abc" } ] + - control: KCons + - log/[halt] (exit) @ location: 18 + [ False + {} + { "ghi" ; "def" ; "abc" } ] + - [halt] (entry) @ location: 33 + [ False + {} + { "ghi" ; "def" ; "abc" } ] + - control: KLoop_in + - control: KCons + - log/DROP (exit) @ location: 33 + [ {} + { "ghi" ; "def" ; "abc" } ] + - DROP (entry) @ location: 33 + [ {} + { "ghi" ; "def" ; "abc" } ] + - log/NIL (exit) @ location: 33 + [ { "ghi" ; "def" ; "abc" } ] + - NIL (entry) @ location: 34 + [ { "ghi" ; "def" ; "abc" } ] + - log/PAIR (exit) @ location: 34 + [ {} + { "ghi" ; "def" ; "abc" } ] + - PAIR (entry) @ location: 36 + [ {} + { "ghi" ; "def" ; "abc" } ] + - log/[halt] (exit) @ location: 36 + [ (Pair {} { "ghi" ; "def" ; "abc" }) ] + - [halt] (entry) @ location: 8 + [ (Pair {} { "ghi" ; "def" ; "abc" }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/set_delegate.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/set_delegate.out new file mode 100644 index 000000000000..89bf0cc887b9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/set_delegate.out @@ -0,0 +1,51 @@ + +trace + - UNPAIR (interp) @ location: 8 + [ (Pair (Some "[PUBLIC_KEY_HASH]") Unit) ] + - UNPAIR (entry) @ location: 8 + [ (Pair (Some "[PUBLIC_KEY_HASH]") Unit) ] + - log/SET_DELEGATE (exit) @ location: 8 + [ (Some "[PUBLIC_KEY_HASH]") + Unit ] + - SET_DELEGATE (entry) @ location: 9 + [ (Some "[PUBLIC_KEY_HASH]") + Unit ] + - log/DIP (exit) @ location: 9 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c + Unit ] + - DIP (entry) @ location: 10 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c + Unit ] + - log/NIL (exit) @ location: 10 + [ Unit ] + - NIL (entry) @ location: 12 + [ Unit ] + - log/[halt] (exit) @ location: 12 + [ {} + Unit ] + - [halt] (entry) @ location: 12 + [ {} + Unit ] + - control: KUndip + - control: KCons + - log/CONS (exit) @ location: 10 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c + {} + Unit ] + - CONS (entry) @ location: 14 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c + {} + Unit ] + - log/PAIR (exit) @ location: 14 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c } + Unit ] + - PAIR (entry) @ location: 15 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c } + Unit ] + - log/[halt] (exit) @ location: 15 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c } + Unit) ] + - [halt] (entry) @ location: 7 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000003ff00e7670f32038107a59a2b9cfefae36ea21f5aa63c } + Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/shifts.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/shifts.out new file mode 100644 index 000000000000..73e5b8e24058 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/shifts.out @@ -0,0 +1,44 @@ + +trace + - CAR (interp) @ location: 14 + [ (Pair (Right (Pair 3 2)) None) ] + - CAR (entry) @ location: 14 + [ (Pair (Right (Pair 3 2)) None) ] + - log/IF_LEFT (exit) @ location: 14 + [ (Right (Pair 3 2)) ] + - IF_LEFT (entry) @ location: 15 + [ (Right (Pair 3 2)) ] + - log/UNPAIR (exit) @ location: 15 + [ (Pair 3 2) ] + - UNPAIR (entry) @ location: 20 + [ (Pair 3 2) ] + - log/LSR (exit) @ location: 20 + [ 3 + 2 ] + - LSR (entry) @ location: 21 + [ 3 + 2 ] + - log/[halt] (exit) @ location: 21 + [ 0 ] + - [halt] (entry) @ location: 22 + [ 0 ] + - control: KCons + - log/SOME (exit) @ location: 15 + [ 0 ] + - SOME (entry) @ location: 22 + [ 0 ] + - log/NIL (exit) @ location: 22 + [ (Some 0) ] + - NIL (entry) @ location: 23 + [ (Some 0) ] + - log/PAIR (exit) @ location: 23 + [ {} + (Some 0) ] + - PAIR (entry) @ location: 25 + [ {} + (Some 0) ] + - log/[halt] (exit) @ location: 25 + [ (Pair {} (Some 0)) ] + - [halt] (entry) @ location: 13 + [ (Pair {} (Some 0)) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/spawn_identities.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/spawn_identities.out new file mode 100644 index 000000000000..9f1a07749f23 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/spawn_identities.out @@ -0,0 +1,4341 @@ + +trace + - DUP (interp) @ location: 8 + [ (Pair 7 {}) ] + - DUP (entry) @ location: 8 + [ (Pair 7 {}) ] + - log/CAR (exit) @ location: 8 + [ (Pair 7 {}) + (Pair 7 {}) ] + - CAR (entry) @ location: 9 + [ (Pair 7 {}) + (Pair 7 {}) ] + - log/DIP (exit) @ location: 9 + [ 7 + (Pair 7 {}) ] + - DIP (entry) @ location: 10 + [ 7 + (Pair 7 {}) ] + - log/CDR (exit) @ location: 10 + [ (Pair 7 {}) ] + - CDR (entry) @ location: 12 + [ (Pair 7 {}) ] + - log/NIL (exit) @ location: 12 + [ {} ] + - NIL (entry) @ location: 13 + [ {} ] + - log/[halt] (exit) @ location: 13 + [ {} + {} ] + - [halt] (entry) @ location: 11 + [ {} + {} ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 10 + [ 7 + {} + {} ] + - PUSH (entry) @ location: 15 + [ 7 + {} + {} ] + - log/LOOP (exit) @ location: 15 + [ True + 7 + {} + {} ] + - LOOP (entry) @ location: 76 + [ True + 7 + {} + {} ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 7 + {} + {} ] + - DUP (entry) @ location: 20 + [ 7 + {} + {} ] + - log/PUSH (exit) @ location: 20 + [ 7 + 7 + {} + {} ] + - PUSH (entry) @ location: 21 + [ 7 + 7 + {} + {} ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 7 + 7 + {} + {} ] + - COMPARE (entry) @ location: 25 + [ 0 + 7 + 7 + {} + {} ] + - log/EQ (exit) @ location: 25 + [ -1 + 7 + {} + {} ] + - EQ (entry) @ location: 26 + [ -1 + 7 + {} + {} ] + - log/IF (exit) @ location: 26 + [ False + 7 + {} + {} ] + - IF (entry) @ location: 27 + [ False + 7 + {} + {} ] + - log/PUSH (exit) @ location: 27 + [ 7 + {} + {} ] + - PUSH (entry) @ location: 33 + [ 7 + {} + {} ] + - log/SWAP (exit) @ location: 33 + [ 1 + 7 + {} + {} ] + - SWAP (entry) @ location: 36 + [ 1 + 7 + {} + {} ] + - log/SUB (exit) @ location: 36 + [ 7 + 1 + {} + {} ] + - SUB (entry) @ location: 37 + [ 7 + 1 + {} + {} ] + - log/ABS (exit) @ location: 37 + [ 6 + {} + {} ] + - ABS (entry) @ location: 38 + [ 6 + {} + {} ] + - log/PUSH (exit) @ location: 38 + [ 6 + {} + {} ] + - PUSH (entry) @ location: 39 + [ 6 + {} + {} ] + - log/PUSH (exit) @ location: 39 + [ "init" + 6 + {} + {} ] + - PUSH (entry) @ location: 42 + [ "init" + 6 + {} + {} ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 6 + {} + {} ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 6 + {} + {} ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 6 + {} + {} ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 6 + {} + {} ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 6 + {} + {} ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 6 + {} + {} ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 6 + {} + {} ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 6 + {} + {} ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 6 + {} + {} ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 6 + {} + {} ] + - log/DIP (exit) @ location: 62 + [ 6 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + {} + {} ] + - DIP (entry) @ location: 63 + [ 6 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + {} + {} ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + {} + {} ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + {} + {} ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - [halt] (entry) @ location: 61 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - log/DIP (exit) @ location: 66 + [ 6 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - DIP (entry) @ location: 67 + [ 6 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + {} ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + {} ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + {} ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + {} ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + {} ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 6 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 6 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 6 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 6 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ -1 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ -1 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ False + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ False + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 33 + [ 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 33 + [ 1 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 36 + [ 1 + 6 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/SUB (exit) @ location: 36 + [ 6 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - SUB (entry) @ location: 37 + [ 6 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/ABS (exit) @ location: 37 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - ABS (entry) @ location: 38 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 38 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 39 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 39 + [ "init" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 42 + [ "init" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 62 + [ 5 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 63 + [ 5 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 61 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 66 + [ 5 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 67 + [ 5 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 5 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 5 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 5 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 5 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ -1 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ -1 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ False + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ False + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 33 + [ 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 33 + [ 1 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 36 + [ 1 + 5 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SUB (exit) @ location: 36 + [ 5 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SUB (entry) @ location: 37 + [ 5 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/ABS (exit) @ location: 37 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - ABS (entry) @ location: 38 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 38 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 39 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 39 + [ "init" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 42 + [ "init" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 62 + [ 4 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 63 + [ 4 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 61 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 66 + [ 4 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 67 + [ 4 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 4 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 4 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 4 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 4 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ -1 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ -1 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ False + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ False + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 33 + [ 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 33 + [ 1 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 36 + [ 1 + 4 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SUB (exit) @ location: 36 + [ 4 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SUB (entry) @ location: 37 + [ 4 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/ABS (exit) @ location: 37 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - ABS (entry) @ location: 38 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 38 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 39 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 39 + [ "init" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 42 + [ "init" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 62 + [ 3 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 63 + [ 3 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 61 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 66 + [ 3 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 67 + [ 3 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 3 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 3 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 3 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 3 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ -1 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ -1 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ False + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ False + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 33 + [ 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 33 + [ 1 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 36 + [ 1 + 3 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SUB (exit) @ location: 36 + [ 3 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SUB (entry) @ location: 37 + [ 3 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/ABS (exit) @ location: 37 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - ABS (entry) @ location: 38 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 38 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 39 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 39 + [ "init" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 42 + [ "init" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 62 + [ 2 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 63 + [ 2 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 61 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 66 + [ 2 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 67 + [ 2 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 2 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 2 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 2 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 2 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ -1 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ -1 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ False + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ False + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 33 + [ 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 33 + [ 1 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 36 + [ 1 + 2 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SUB (exit) @ location: 36 + [ 2 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SUB (entry) @ location: 37 + [ 2 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/ABS (exit) @ location: 37 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - ABS (entry) @ location: 38 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 38 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 39 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 39 + [ "init" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 42 + [ "init" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 62 + [ 1 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 63 + [ 1 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 61 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 66 + [ 1 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 67 + [ 1 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ -1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ -1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ False + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ False + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 33 + [ 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 33 + [ 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 36 + [ 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SUB (exit) @ location: 36 + [ 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SUB (entry) @ location: 37 + [ 1 + 1 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/ABS (exit) @ location: 37 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - ABS (entry) @ location: 38 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 38 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 39 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 39 + [ "init" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 42 + [ "init" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/NONE (exit) @ location: 42 + [ 5000000 + "init" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - NONE (entry) @ location: 45 + [ 5000000 + "init" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CREATE_CONTRACT (exit) @ location: 45 + [ None + 5000000 + "init" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CREATE_CONTRACT (entry) @ location: 47 + [ None + 5000000 + "init" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 47 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 59 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + "[CONTRACT_HASH]" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 59 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 60 + [ "[CONTRACT_HASH]" + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 60 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 62 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 62 + [ 0 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 63 + [ 0 + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 63 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 65 + [ 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 65 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 63 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 61 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/SWAP (exit) @ location: 60 + [ "[CONTRACT_HASH]" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 66 + [ "[CONTRACT_HASH]" + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 66 + [ 0 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 67 + [ 0 + "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/SWAP (exit) @ location: 67 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - SWAP (entry) @ location: 69 + [ "[CONTRACT_HASH]" + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/DIP (exit) @ location: 69 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DIP (entry) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/CONS (exit) @ location: 70 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - CONS (entry) @ location: 72 + [ "[CONTRACT_HASH]" + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 72 + [ { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/[halt] (exit) @ location: 70 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 68 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KUndip + - control: KCons + - log/PUSH (exit) @ location: 67 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 73 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 73 + [ True + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ True + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ True + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - log/DUP (exit) @ location: 76 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DUP (entry) @ location: 20 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 20 + [ 0 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 21 + [ 0 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/COMPARE (exit) @ location: 21 + [ 0 + 0 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - COMPARE (entry) @ location: 25 + [ 0 + 0 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/EQ (exit) @ location: 25 + [ 0 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - EQ (entry) @ location: 26 + [ 0 + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/IF (exit) @ location: 26 + [ True + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - IF (entry) @ location: 27 + [ True + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PUSH (exit) @ location: 27 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PUSH (entry) @ location: 29 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 29 + [ False + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ False + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KCons + - log/[halt] (exit) @ location: 27 + [ False + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - [halt] (entry) @ location: 76 + [ False + 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - control: KLoop_in + - control: KCons + - log/DROP (exit) @ location: 76 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - DROP (entry) @ location: 76 + [ 0 + { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/PAIR (exit) @ location: 76 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - PAIR (entry) @ location: 77 + [ { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" } ] + - log/[halt] (exit) @ location: 77 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" }) ] + - [halt] (entry) @ location: 7 + [ (Pair { 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000602c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000502c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000402c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000302c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000202c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000102c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 ; + 0x014828e9aa0b3e6e970da0515b5c5d8ccf5028758900000002c096b102000000001c02000000170500036805010368050202000000080316053d036d0342000000090100000004696e6974 } + { "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" ; + "[CONTRACT_HASH]" }) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_join.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_join.out new file mode 100644 index 000000000000..9b2173a0c4f3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_join.out @@ -0,0 +1,42 @@ + +trace + - UNPAIR (interp) @ location: 10 + [ (Pair (Pair "[CONTRACT_HASH]" 17 3) None) ] + - UNPAIR (entry) @ location: 10 + [ (Pair (Pair "[CONTRACT_HASH]" 17 3) None) ] + - log/SWAP (exit) @ location: 10 + [ (Pair "[CONTRACT_HASH]" 17 3) + None ] + - SWAP (entry) @ location: 11 + [ (Pair "[CONTRACT_HASH]" 17 3) + None ] + - log/IF_NONE (exit) @ location: 11 + [ None + (Pair "[CONTRACT_HASH]" 17 3) ] + - IF_NONE (entry) @ location: 12 + [ None + (Pair "[CONTRACT_HASH]" 17 3) ] + - log/[halt] (exit) @ location: 12 + [ (Pair "[CONTRACT_HASH]" 17 3) ] + - [halt] (entry) @ location: 24 + [ (Pair "[CONTRACT_HASH]" 17 3) ] + - control: KCons + - log/SOME (exit) @ location: 12 + [ (Pair "[CONTRACT_HASH]" 17 3) ] + - SOME (entry) @ location: 24 + [ (Pair "[CONTRACT_HASH]" 17 3) ] + - log/NIL (exit) @ location: 24 + [ (Some (Pair "[CONTRACT_HASH]" 17 3)) ] + - NIL (entry) @ location: 25 + [ (Some (Pair "[CONTRACT_HASH]" 17 3)) ] + - log/PAIR (exit) @ location: 25 + [ {} + (Some (Pair "[CONTRACT_HASH]" 17 3)) ] + - PAIR (entry) @ location: 27 + [ {} + (Some (Pair "[CONTRACT_HASH]" 17 3)) ] + - log/[halt] (exit) @ location: 27 + [ (Pair {} (Some (Pair "[CONTRACT_HASH]" 17 3))) ] + - [halt] (entry) @ location: 9 + [ (Pair {} (Some (Pair "[CONTRACT_HASH]" 17 3))) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_split.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_split.out new file mode 100644 index 000000000000..ae449fe91b48 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/ticket_split.out @@ -0,0 +1,180 @@ + +trace + - CAR (interp) @ location: 8 + [ (Pair (Pair "[CONTRACT_HASH]" 17 3) Unit) ] + - CAR (entry) @ location: 8 + [ (Pair (Pair "[CONTRACT_HASH]" 17 3) Unit) ] + - log/PUSH (exit) @ location: 8 + [ (Pair "[CONTRACT_HASH]" 17 3) ] + - PUSH (entry) @ location: 9 + [ (Pair "[CONTRACT_HASH]" 17 3) ] + - log/SWAP (exit) @ location: 9 + [ (Pair 1 2) + (Pair "[CONTRACT_HASH]" 17 3) ] + - SWAP (entry) @ location: 16 + [ (Pair 1 2) + (Pair "[CONTRACT_HASH]" 17 3) ] + - log/SPLIT_TICKET (exit) @ location: 16 + [ (Pair "[CONTRACT_HASH]" 17 3) + (Pair 1 2) ] + - SPLIT_TICKET (entry) @ location: 17 + [ (Pair "[CONTRACT_HASH]" 17 3) + (Pair 1 2) ] + - log/IF_NONE (exit) @ location: 17 + [ (Some (Pair (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2))) ] + - IF_NONE (entry) @ location: 19 + [ (Some (Pair (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2))) ] + - log/[halt] (exit) @ location: 19 + [ (Pair (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2)) ] + - [halt] (entry) @ location: 25 + [ (Pair (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2)) ] + - control: KCons + - log/UNPAIR (exit) @ location: 19 + [ (Pair (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2)) ] + - UNPAIR (entry) @ location: 25 + [ (Pair (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2)) ] + - log/READ_TICKET (exit) @ location: 25 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - READ_TICKET (entry) @ location: 26 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/CDR (exit) @ location: 26 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - CDR (entry) @ location: 28 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/CDR (exit) @ location: 28 + [ (Pair 17 1) + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - CDR (entry) @ location: 29 + [ (Pair 17 1) + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/PUSH (exit) @ location: 29 + [ 1 + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - PUSH (entry) @ location: 30 + [ 1 + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/COMPARE (exit) @ location: 30 + [ 1 + 1 + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - COMPARE (entry) @ location: 35 + [ 1 + 1 + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/EQ (exit) @ location: 35 + [ 0 + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - EQ (entry) @ location: 36 + [ 0 + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/IF (exit) @ location: 36 + [ True + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - IF (entry) @ location: 37 + [ True + (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/[halt] (exit) @ location: 37 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - [halt] (entry) @ location: 43 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - control: KCons + - log/DROP (exit) @ location: 37 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - DROP (entry) @ location: 43 + [ (Pair "[CONTRACT_HASH]" 17 1) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/READ_TICKET (exit) @ location: 43 + [ (Pair "[CONTRACT_HASH]" 17 2) ] + - READ_TICKET (entry) @ location: 44 + [ (Pair "[CONTRACT_HASH]" 17 2) ] + - log/CDR (exit) @ location: 44 + [ (Pair "[CONTRACT_HASH]" 17 2) + (Pair "[CONTRACT_HASH]" 17 2) ] + - CDR (entry) @ location: 46 + [ (Pair "[CONTRACT_HASH]" 17 2) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/CDR (exit) @ location: 46 + [ (Pair 17 2) + (Pair "[CONTRACT_HASH]" 17 2) ] + - CDR (entry) @ location: 47 + [ (Pair 17 2) + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/PUSH (exit) @ location: 47 + [ 2 + (Pair "[CONTRACT_HASH]" 17 2) ] + - PUSH (entry) @ location: 48 + [ 2 + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/COMPARE (exit) @ location: 48 + [ 2 + 2 + (Pair "[CONTRACT_HASH]" 17 2) ] + - COMPARE (entry) @ location: 53 + [ 2 + 2 + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/EQ (exit) @ location: 53 + [ 0 + (Pair "[CONTRACT_HASH]" 17 2) ] + - EQ (entry) @ location: 54 + [ 0 + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/IF (exit) @ location: 54 + [ True + (Pair "[CONTRACT_HASH]" 17 2) ] + - IF (entry) @ location: 55 + [ True + (Pair "[CONTRACT_HASH]" 17 2) ] + - log/[halt] (exit) @ location: 55 + [ (Pair "[CONTRACT_HASH]" 17 2) ] + - [halt] (entry) @ location: 61 + [ (Pair "[CONTRACT_HASH]" 17 2) ] + - control: KCons + - log/DROP (exit) @ location: 55 + [ (Pair "[CONTRACT_HASH]" 17 2) ] + - DROP (entry) @ location: 61 + [ (Pair "[CONTRACT_HASH]" 17 2) ] + - log/UNIT (exit) @ location: 61 + [ ] + - UNIT (entry) @ location: 62 + [ ] + - log/NIL (exit) @ location: 62 + [ Unit ] + - NIL (entry) @ location: 63 + [ Unit ] + - log/PAIR (exit) @ location: 63 + [ {} + Unit ] + - PAIR (entry) @ location: 65 + [ {} + Unit ] + - log/[halt] (exit) @ location: 65 + [ (Pair {} Unit) ] + - [halt] (entry) @ location: 7 + [ (Pair {} Unit) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_fib.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_fib.out new file mode 100644 index 000000000000..374caebbb378 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_fib.out @@ -0,0 +1,41 @@ + +trace + - CAR (interp) @ location: 9 + [ (Pair (Pair 8 "[CONTRACT_HASH]") 0) ] + - CAR (entry) @ location: 9 + [ (Pair (Pair 8 "[CONTRACT_HASH]") 0) ] + - log/UNPAIR (exit) @ location: 9 + [ (Pair 8 "[CONTRACT_HASH]") ] + - UNPAIR (entry) @ location: 10 + [ (Pair 8 "[CONTRACT_HASH]") ] + - log/VIEW (exit) @ location: 10 + [ 8 + "[CONTRACT_HASH]" ] + - VIEW (entry) @ location: 11 + [ 8 + "[CONTRACT_HASH]" ] + - control: KView_exit + - log/IF_NONE (exit) @ location: 11 + [ (Some 21) ] + - IF_NONE (entry) @ location: 15 + [ (Some 21) ] + - log/NIL (exit) @ location: 15 + [ 21 ] + - NIL (entry) @ location: 21 + [ 21 ] + - log/PAIR (exit) @ location: 21 + [ {} + 21 ] + - PAIR (entry) @ location: 23 + [ {} + 21 ] + - log/[halt] (exit) @ location: 23 + [ (Pair {} 21) ] + - [halt] (entry) @ location: 8 + [ (Pair {} 21) ] + - control: KCons + - log/[halt] (exit) @ location: 15 + [ (Pair {} 21) ] + - [halt] (entry) @ location: 8 + [ (Pair {} 21) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_toplevel_lib.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_toplevel_lib.out new file mode 100644 index 000000000000..8791bd97f511 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/view_toplevel_lib.out @@ -0,0 +1,21 @@ + +trace + - CAR (interp) @ location: 7 + [ (Pair 5 3) ] + - CAR (entry) @ location: 7 + [ (Pair 5 3) ] + - log/NIL (exit) @ location: 7 + [ 5 ] + - NIL (entry) @ location: 8 + [ 5 ] + - log/PAIR (exit) @ location: 8 + [ {} + 5 ] + - PAIR (entry) @ location: 10 + [ {} + 5 ] + - log/[halt] (exit) @ location: 10 + [ (Pair {} 5) ] + - [halt] (entry) @ location: 6 + [ (Pair {} 5) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/xor.out b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/xor.out new file mode 100644 index 000000000000..5eb5063226ee --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/expected/test_logging.ml/xor.out @@ -0,0 +1,48 @@ + +trace + - CAR (interp) @ location: 16 + [ (Pair (Left (Pair True False)) None) ] + - CAR (entry) @ location: 16 + [ (Pair (Left (Pair True False)) None) ] + - log/IF_LEFT (exit) @ location: 16 + [ (Left (Pair True False)) ] + - IF_LEFT (entry) @ location: 17 + [ (Left (Pair True False)) ] + - log/UNPAIR (exit) @ location: 17 + [ (Pair True False) ] + - UNPAIR (entry) @ location: 19 + [ (Pair True False) ] + - log/XOR (exit) @ location: 19 + [ True + False ] + - XOR (entry) @ location: 20 + [ True + False ] + - log/LEFT (exit) @ location: 20 + [ True ] + - LEFT (entry) @ location: 21 + [ True ] + - log/[halt] (exit) @ location: 21 + [ (Left True) ] + - [halt] (entry) @ location: 28 + [ (Left True) ] + - control: KCons + - log/SOME (exit) @ location: 17 + [ (Left True) ] + - SOME (entry) @ location: 28 + [ (Left True) ] + - log/NIL (exit) @ location: 28 + [ (Some (Left True)) ] + - NIL (entry) @ location: 29 + [ (Some (Left True)) ] + - log/PAIR (exit) @ location: 29 + [ {} + (Some (Left True)) ] + - PAIR (entry) @ location: 31 + [ {} + (Some (Left True)) ] + - log/[halt] (exit) @ location: 31 + [ (Pair {} (Some (Left True))) ] + - [halt] (entry) @ location: 15 + [ (Pair {} (Some (Left True))) ] + - control: KNil diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/test_logging.ml b/src/proto_020_PsParisC/lib_protocol/test/regression/test_logging.ml new file mode 100644 index 000000000000..7b2bd7c7dc1f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/test_logging.ml @@ -0,0 +1,398 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (type-checking) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/regression/main.exe + Subject: Type-checking + *) + +open Protocol +open Alpha_context +open Tezt + +module Traced_interpreter = Plugin.RPC.Scripts.Traced_interpreter (struct + let unparsing_mode = Script_ir_unparser.Readable +end) + +type contract = {filename : string; storage : string} + +type transaction = + | Simple of {dst : contract; amount : Tez.t; parameter : string} + | With_lib of { + dst : contract; + lib : contract; + amount : Tez.t; + parameter : Contract_hash.t -> string; + } + +type element_kind = Interp | Entry | Exit + +type log_element = + | With_stack : + context + * ('a, 'b, 'c, 'd) Script_typed_ir.kinstr + * Script.location + * ('e * 'f) + * ('e, 'f) Script_typed_ir.stack_ty + * element_kind + -> log_element + | Ctrl : ('a, 'b, 'c, 'd) Script_typed_ir.continuation -> log_element + +type trace_element = + | TInstr : + Script.location + * Gas.t + * ('a, 'b, 'c, 'd) Script_typed_ir.kinstr + * Script.expr list + * element_kind + -> trace_element + | TCtrl : ('a, 'b, 'c, 'd) Script_typed_ir.continuation -> trace_element + +let transaction ?(amount = Tez.zero) ~parameter ~storage filename = + Simple {amount; parameter; dst = {filename; storage}} + +let with_lib ?(amount = Tez.zero) ~parameter ~storage ~lib ~lib_storage filename + = + With_lib + { + amount; + parameter; + dst = {storage; filename}; + lib = {filename = lib; storage = lib_storage}; + } + +let filename = function + | Simple {dst = {filename; _}; _} | With_lib {dst = {filename; _}; _} -> + filename + +let amount = function Simple {amount; _} | With_lib {amount; _} -> amount + +let storage = function + | Simple {dst = {storage; _}; _} | With_lib {dst = {storage; _}; _} -> storage + +let with_indentation fmt = function + | Interp -> + Format.fprintf + fmt + "- @[%a (interp) @@ location: %d@,[ @[%a ]@]@]" + | Exit -> + Format.fprintf + fmt + "- @[%a (exit) @@ location: %d@,[ @[%a ]@]@]@]" + | Entry -> + Format.fprintf + fmt + "@[- @[%a (entry) @@ location: %d@,[ @[%a ]@]@]" + +let pp_trace fmt = function + | TInstr (loc, _gas, instr, stack, element_kind) -> + with_indentation + fmt + element_kind + Plugin.RPC.Scripts.pp_instr_name + instr + loc + (Format.pp_print_list (fun ppf e -> + Format.fprintf ppf "@[%a@]" Michelson_v1_printer.print_expr e)) + stack + | TCtrl continuation -> ( + Format.fprintf fmt "- @[control: %s@]" + @@ + match continuation with + | KNil -> "KNil" + | KCons _ -> "KCons" + | KReturn _ -> "KReturn" + | KView_exit _ -> "KView_exit" + | KMap_head _ -> "KMap_head" + | KUndip _ -> "KUndip" + | KLoop_in _ -> "KLoop_in" + | KLoop_in_left _ -> "KLoop_in_left" + | KIter _ -> "KIter" + | KList_enter_body _ -> "KList_enter_body" + | KList_exit_body _ -> "KList_exit_body" + | KMap_enter_body _ -> "KMap_enter_body" + | KMap_exit_body _ -> "KMap_exit_body" + | KLog _ -> "KLog") + +let logger () : + (unit -> trace_element list tzresult Lwt.t) * Script_typed_ir.logger = + let open Lwt_result_wrap_syntax in + let open Script_typed_ir in + let log : log_element list ref = ref [] in + let logger = + Script_interpreter_logging.make + (module struct + let log_interp : type a s b f c u. (a, s, b, f, c, u) logging_function = + fun instr ctxt loc sty stack -> + log := With_stack (ctxt, instr, loc, stack, sty, Interp) :: !log + + let log_entry instr ctxt loc sty stack = + log := With_stack (ctxt, instr, loc, stack, sty, Entry) :: !log + + let log_exit instr ctxt loc sty stack = + log := With_stack (ctxt, instr, loc, stack, sty, Exit) :: !log + + let log_control cont = log := Ctrl cont :: !log + + let get_log () = return_none + end) + in + let assemble_log () = + let+ l = + List.map_es + (function + | With_stack (ctxt, instr, loc, stack, stack_ty, indent) -> + let+@ stack = + Traced_interpreter.unparse_stack ctxt (stack, stack_ty) + in + TInstr (loc, Gas.level ctxt, instr, stack, indent) + | Ctrl cont -> return @@ TCtrl cont) + !log + in + List.rev l + in + (assemble_log, logger) + +(* [with_logger ~mask f] creates a fresh logger and passes it to [f]. + After [f] finishes, logs are gathered and each occurrence of each + string in [mask] list is being replaced with asterisks. Thus processed + log is captured as regression output. *) +let with_logger f = + let open Lwt_result_syntax in + let get_log, logger = logger () in + let* () = f logger in + let* log = get_log () in + let capture s = Tezos_regression.replace_variables s |> Regression.capture in + Format.kasprintf + capture + "@,@[trace@,%a@]" + (Format.pp_print_list pp_trace) + log ; + return_unit + +let read_code filename = + let filename = + project_root // Filename.dirname __FILE__ // "contracts" + // (filename ^ ".tz") + in + Contract_helpers.read_file filename + +let run_script transaction () = + let open Lwt_result_syntax in + let script = read_code @@ filename transaction in + let* parameter, ctxt = + match transaction with + | With_lib {lib = {filename; storage}; parameter; _} -> + let* block, baker, _contract, _src2 = Contract_helpers.init () in + let sender = Contract.Implicit baker in + let* src_addr, _script, block = + Contract_helpers.originate_contract_from_string_hash + ~baker + ~source_contract:sender + ~script:(read_code filename) + ~storage + block + in + let* incr = Incremental.begin_construction block in + return (parameter src_addr, Incremental.alpha_ctxt incr) + | Simple {parameter; _} -> + let* b, _contract = Context.init1 ~consensus_threshold:0 () in + let* inc = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt inc in + let ctxt = + Alpha_context.Origination_nonce.init ctxt Operation_hash.zero + in + return (parameter, ctxt) + in + with_logger @@ fun logger -> + let step_constants = + Contract_helpers. + { + default_step_constants with + amount = amount transaction; + now = Script_timestamp.of_int64 1649939559L; + } + in + let* _res, _ctxt = + Contract_helpers.run_script + ctxt + script + ~logger + ~storage:(storage transaction) + ~parameter + ~step_constants + ~internal:true (* Allow for forged values (e.g. tickets). *) + () + in + return_unit + +let fail_on_error f () = + let open Lwt_syntax in + let* result = f () in + match result with + | Ok () -> return_unit + | Error e -> Test.fail "%a" Error_monad.pp_print_trace e + +(* Make sure that after a snapshot the snapshotted version of the test + has a different [~title], because all tests are linked in [tezt/tests/main.exe]. *) +let protocol = + match __FILE__ =~* rex "^src/proto_([0-9a-zA-Z_]*)/" with + | None -> + Stdlib.failwith ("failed to extract protocol name from path: " ^ __FILE__) + | Some name -> name + +let register_script transaction = + (* [~title] must be unique across the codebase, so we prefix it with the protocol name. + [~file] however is better kept the same across protocols to simplify snapshotting. *) + let file = filename transaction in + Regression.register + ~__FILE__ + ~title:(protocol ^ ": " ^ file) + ~tags:["protocol"; "regression"; "logging"] + ~file + (fail_on_error @@ run_script transaction) + +(* These tests should always cover: + - every instruction type, which means an example of each group of instructions + which are similar to each other with respect to logging; no need to cover every + instruction whatsoever, but just every distinct kind ; + - every continuation and control structure in Michelson, because those impact + what is being logged and what is not. + We are not concerned with gas, because that's kept track of by regular regression + tests. Actually, gas is unaccounted for in all the tests in this module. *) +let () = + Array.iter + register_script + [| + transaction + ~storage:"{}" + ~parameter:"Left \"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx\"" + "accounts"; + transaction + ~storage:"{1; 2; 3}" + ~parameter:"Pair {7; 8; 9} {4; 5; 6}" + "append"; + transaction + ~amount:(Tez.of_mutez_exn 100_000_000L) + ~parameter:"\"tz1b7tUupMgCNw2cCLpKTkSD1NZzB5TkP2sv\"" + ~storage: + "Pair \"2099-12-31T23:59:59Z\" (Pair 50000000 \ + \"tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU\")" + "auction"; + transaction + ~parameter:"{Pair \"string\" 12; Pair \"abc\" 99; Pair \"def\" 3}" + ~storage:"Pair { Elt \"123\" 123 } Unit" + "big_map_union"; + transaction + ~parameter:"\"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav\"" + ~storage: + "Pair \ + \"edsigu6Ue4mQgPC5aCFqqjitU9pCs5VErXrfPTAZffyJepccGzDEEBExtuPjGuMc2ZRSTBUDR7tJMLVTeJzZn7p9jN9inh4ooV1\" \ + \"TEZOS\"" + "check_signature"; + transaction ~parameter:"Pair 1 4 2 Unit" ~storage:"Unit" "comb-get"; + transaction ~parameter:"Unit" ~storage:"Pair 1 4 2 Unit" "comb-set"; + transaction ~parameter:"\"abcd\"" ~storage:"\"efgh\"" "concat"; + transaction ~parameter:"Right (Some 23)" ~storage:"\"\"" "conditionals"; + transaction ~parameter:"2" ~storage:"60" "cps_fact"; + transaction + ~parameter:"Pair (Pair (Pair (Pair 0 1) 2) 3) 4" + ~storage:"7" + "dign"; + transaction + ~parameter:"Pair (Pair (Pair (Pair 0 1) 2) 3) 4" + ~storage:"7" + "dipn"; + transaction + ~parameter:"Pair (Pair (Pair (Pair 0 1) 2) 3) 4" + ~storage:"7" + "dugn"; + transaction + ~parameter:"Pair 127 11" + ~storage:"Pair None None None None" + "ediv"; + transaction + ~parameter:"\"tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU\"" + ~storage:"\"2020-01-01T00:00:00Z\"" + "faucet"; + transaction + ~parameter:"\"abc\"" + ~storage:"Pair (Some 321) {Elt \"def\" 123}" + "get_and_update_map"; + transaction ~parameter:"True" ~storage:"None" "if"; + transaction + ~parameter:"{8; 3; 2; 7; 6; 9; 5; 1; 4; 0}" + ~storage:"{}" + "insertion_sort"; + transaction + ~parameter:"{1; 2; 3; 4; 5; 6; 7}" + ~storage:"{}" + "list_map_block"; + transaction + ~parameter:"{\"abc\"; \"xyz\"}" + ~storage:"{\"zyx\"; \"cba\"}" + "loop_left"; + transaction + ~parameter: + "Pair (Pair (Pair \"abc\" {1; 2; 3}) {4; 5; 6}) \ + 0x0507070707010000000361626302000000060001000200030200000006000400050006" + ~storage:"Unit" + "packunpack"; + transaction ~parameter:"7" ~storage:"77" "pexec"; + transaction + ~parameter:"{\"abc\"; \"def\" ; \"ghi\"}" + ~storage:"{}" + "reverse_loop"; + transaction + ~parameter:"Some \"tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN\"" + ~storage:"Unit" + "set_delegate"; + transaction ~parameter:"Right (Pair 3 2)" ~storage:"None" "shifts"; + transaction + ~amount:(Tez.of_mutez_exn 1_200_00L) + ~parameter:"7" + ~storage:"{}" + "spawn_identities"; + transaction + ~parameter:"Pair \"KT1Ln1MPvHDJ1phLL8dNL4jrKF6Q1yQCBG1v\" 17 3" + ~storage:"None" + "ticket_join"; + transaction + ~parameter:"Pair \"KT1Ln1MPvHDJ1phLL8dNL4jrKF6Q1yQCBG1v\" 17 3" + ~storage:"Unit" + "ticket_split"; + transaction ~parameter:"5" ~storage:"3" "view_toplevel_lib"; + transaction ~parameter:"Left (Pair True False)" ~storage:"None" "xor"; + transaction ~parameter:"7" ~storage:"Some 3" "opt_map"; + with_lib + ~parameter:(Format.asprintf "Pair 8 \"%a\"" Contract_hash.pp) + ~storage:"0" + ~lib:"view_toplevel_lib" + ~lib_storage:"0" + "view_fib"; + transaction ~parameter:"Unit" ~storage:"Unit" "rec_id_unit"; + |] diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/dune b/src/proto_020_PsParisC/lib_protocol/test/unit/dune new file mode 100644 index 000000000000..ee17efd40360 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/dune @@ -0,0 +1,97 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_protocol_test_unit_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + octez-libs.base-test-helpers + octez-libs.micheline + octez-protocol-019-PtParisB-libs.client + octez-shell-libs.client-base + tezos-protocol-019-PtParisB.parameters + octez-proto-libs.protocol-environment + octez-libs.stdlib-unix + tezos-protocol-019-PtParisB.protocol + octez-libs.test-helpers + octez-protocol-019-PtParisB-libs.test-helpers + octez-alcotezt + octez-l2-libs.scoru-wasm-helpers + octez-libs.stdlib + octez-libs.crypto-dal + octez-l2-libs.scoru-wasm + octez-l2-libs.webassembly-interpreter-extra) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_base_test_helpers + -open Tezos_micheline + -open Tezos_client_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_019_PtParisB + -open Tezos_test_helpers + -open Tezos_019_PtParisB_test_helpers + -open Octez_alcotezt + -open Tezos_scoru_wasm_helpers + -open Tezos_stdlib + -open Tezos_crypto_dal + -open Tezos_webassembly_interpreter_extra) + (modules + test_bond_id_repr + test_consensus_key + test_contract_repr + test_destination_repr + test_fitness + test_fixed_point + test_gas_monad + test_global_constants_storage + test_level_module + test_liquidity_baking_repr + test_merkle_list + test_operation_repr + test_qty + test_receipt + test_round_repr + test_saturation + test_sc_rollup_arith + test_sc_rollup_game + test_sc_rollup_inbox + test_sc_rollup_management_protocol + test_sc_rollup_storage + test_skip_list_repr + test_tez_repr + test_time_repr + test_zk_rollup_storage + test_sc_rollup_inbox_legacy + test_sc_rollup_wasm + test_local_contexts + test_dal_slot_proof + test_adaptive_issuance + test_adaptive_issuance_ema + test_percentage)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_protocol_test_unit_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-protocol-019-PtParisB-tests) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance.ml new file mode 100644 index 000000000000..935efe7b0e2c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance.ml @@ -0,0 +1,616 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (rewards) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_adaptive_issuance.ml + Subject: Test reward values under adaptive issuance +*) + +open Protocol +open Alpha_context + +let test_reward_coefficient () = + let open Lwt_result_wrap_syntax in + let csts = Default_parameters.constants_test in + let*?@ default = + Delegate.Rewards.For_RPC.( + reward_from_constants csts ~reward_kind:Baking_reward_fixed_portion) + in + let*?@ default_times_4 = + Delegate.Rewards.For_RPC.( + reward_from_constants + ~coeff:(Q.of_int 4) + csts + ~reward_kind:Baking_reward_fixed_portion) + in + Assert.equal_tez ~loc:__LOC__ Test_tez.(default *! 4L) default_times_4 + +let test_reward_coeff_ratio () = + let open Delegate.Rewards.Internal_for_tests in + let open Lwt_result_wrap_syntax in + let assert_eq ~loc a b = Assert.equal ~loc Q.equal "" Q.pp_print a b in + (* Curve tests *) + let curve stake_ratio = + compute_reward_coeff_ratio_without_bonus + ~stake_ratio + ~issuance_ratio_max:(Q.of_int 1_000_000) + ~issuance_ratio_min:(Q.of_int (-1_000_000)) + in + (* Test the curve on some staking points: 1, 1/10, 1/100, 1/2 *) + let* () = assert_eq ~loc:__LOC__ (curve Q.one) Q.(1 // 1600) in + let* () = assert_eq ~loc:__LOC__ (curve Q.(1 // 10)) Q.(1 // 16) in + let* () = assert_eq ~loc:__LOC__ (curve Q.(1 // 100)) Q.(100 // 16) in + let* () = assert_eq ~loc:__LOC__ (curve Q.(1 // 2)) Q.(1 // 400) in + (* Test the curve on extreme values: ε and 1 - ε with ε small *) + let epsilon = Q.(3 // 50000) in + let one_m_e = Q.(one - epsilon) in + let* () = + assert_eq ~loc:__LOC__ (curve epsilon) Q.(1 // 1600 / (epsilon * epsilon)) + in + let* () = + assert_eq ~loc:__LOC__ (curve one_m_e) Q.(1 // 1600 / (one_m_e * one_m_e)) + in + (* Test min max *) + let bound = Q.(1 // 30) in + (* curve(1/10) = 1/16 > 1/30 (max). Expected result: 1/30 *) + let* () = + assert_eq + ~loc:__LOC__ + (compute_reward_coeff_ratio_without_bonus + ~stake_ratio:Q.(1 // 10) + ~issuance_ratio_max:bound + ~issuance_ratio_min:(Q.of_int (-100))) + bound + in + (* curve(1) = 1/1600 < 1/30 (min). Expected result: 1/30 *) + let* () = + assert_eq + ~loc:__LOC__ + (compute_reward_coeff_ratio_without_bonus + ~stake_ratio:Q.one + ~issuance_ratio_max:(Q.of_int 100) + ~issuance_ratio_min:bound) + bound + in + return_unit + +let test_compute_bonus () = + let open Delegate.Rewards.Internal_for_tests in + let open Lwt_result_wrap_syntax in + let assert_fun ~loc ~f a b = + let* a in + Assert.equal ~loc f "" Q.pp_print a b + in + let assert_eq ~loc a b = + let* a in + Assert.equal ~loc Q.equal "" Q.pp_print a b + in + let reward_params = + Default_parameters.constants_test.adaptive_issuance.adaptive_rewards_params + in + (* For simplicity, one cycle = one day *) + let seconds_per_cycle = 86_400L in + let compute_bonus ?(seconds_per_cycle = seconds_per_cycle) stake_ratio + previous_bonus = + let () = assert (Q.(stake_ratio <= one)) in + let*?@ previous_bonus = + Issuance_bonus_repr.of_Q ~max_bonus:reward_params.max_bonus previous_bonus + in + let issuance_ratio_max = reward_params.issuance_ratio_final_max in + let issuance_ratio_min = reward_params.issuance_ratio_final_min in + let base_reward_coeff_ratio = + compute_reward_coeff_ratio_without_bonus + ~stake_ratio + ~issuance_ratio_max + ~issuance_ratio_min + in + let*?@ bonus = + compute_bonus + ~issuance_ratio_max + ~seconds_per_cycle + ~stake_ratio + ~base_reward_coeff_ratio + ~previous_bonus + ~reward_params + in + let full_reward_coeff = Q.add (bonus :> Q.t) base_reward_coeff_ratio in + (* The full coeff should be within the bounds *) + let* () = + assert_fun + ~loc:__LOC__ + ~f:Q.geq + (return full_reward_coeff) + issuance_ratio_min + in + let* () = + assert_fun + ~loc:__LOC__ + ~f:Q.leq + (return full_reward_coeff) + issuance_ratio_max + in + return (bonus :> Q.t) + in + let small_bonus = Q.(1 // 200) (* 0.5% *) in + (* Test deadzone *) + let* () = + assert_eq ~loc:__LOC__ (compute_bonus Q.(48 // 100) small_bonus) small_bonus + in + let* () = + assert_eq ~loc:__LOC__ (compute_bonus Q.(52 // 100) small_bonus) small_bonus + in + let* () = + assert_fun + ~loc:__LOC__ + ~f:Q.gt + (compute_bonus Q.(47_9999 // 100_0000) small_bonus) + small_bonus + in + let* () = + assert_fun + ~loc:__LOC__ + ~f:Q.lt + (compute_bonus Q.(52_0001 // 100_0000) small_bonus) + small_bonus + in + (* Test variation amplitude *) + let variation = Q.(1 // 10_000) (* 0.01% *) in + let* () = + assert_eq + ~loc:__LOC__ + (compute_bonus Q.(47 // 100) small_bonus) + (Q.add small_bonus variation) + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_bonus Q.(40 // 100) small_bonus) + (Q.add small_bonus (Q.mul variation (Q.of_int 8))) + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_bonus Q.(53 // 100) small_bonus) + (Q.sub small_bonus variation) + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_bonus Q.(60 // 100) small_bonus) + (Q.sub small_bonus (Q.mul variation (Q.of_int 8))) + in + (* Test bounds *) + let max_bonus = (reward_params.max_bonus :> Q.t) in + let* () = + assert_eq ~loc:__LOC__ (compute_bonus Q.(60 // 100) Q.zero) Q.zero + in + let* () = + assert_fun + ~loc:__LOC__ + ~f:Q.leq + (compute_bonus Q.(40 // 100) max_bonus) + max_bonus + in + (* Test linearity wrt seconds_per_cycle *) + let compute_growth seconds_per_cycle = + let* computed_bonus = + compute_bonus ~seconds_per_cycle Q.(47 // 100) small_bonus + in + return Q.(sub computed_bonus small_bonus) + in + let* base_growth = compute_growth seconds_per_cycle in + let* () = + assert_eq + ~loc:__LOC__ + (compute_growth (Int64.div seconds_per_cycle 2L)) + Q.(mul (1 // 2) base_growth) + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_growth (Int64.mul seconds_per_cycle 2L)) + Q.(mul (2 // 1) base_growth) + in + return_unit + +let test_compute_coeff () = + let open Delegate.Rewards.Internal_for_tests in + let open Lwt_result_wrap_syntax in + let assert_eq ~loc a b = Assert.equal ~loc Q.equal "" Q.pp_print a b in + let assert_eq_lwt ~loc a b = + let* a in + let* b in + Assert.equal ~loc Q.equal "" Q.pp_print a b + in + let reward_params = + Default_parameters.constants_test.adaptive_issuance.adaptive_rewards_params + in + let base_total_issued_per_minute = + Default_parameters.constants_test.issuance_weights + .base_total_issued_per_minute |> Tez.to_mutez |> Tez_repr.of_mutez_exn + in + let compute_coeff + ?(base_total_issued_per_minute = base_total_issued_per_minute) + ?(q_total_supply = Q.of_int64 1_000_000_000L) () = + compute_coeff + ~issuance_ratio_max:reward_params.issuance_ratio_final_max + ~issuance_ratio_min:reward_params.issuance_ratio_final_min + ~base_total_issued_per_minute + ~q_total_supply + in + (* Test inverse linearity wrt base issuance + Base issuance * Issuance coeff = constant (= issuance per unit of time) + In other words, ∀α>0.αf(αx)=f(x), where x is the base issuance + and f is compute_coeff *) + let* () = + let base_issuance = 20_000_000L in + let compute_coeff base = + compute_coeff + ~base_total_issued_per_minute:(Tez_repr.of_mutez_exn base) + ~base_reward_coeff_ratio:Q.(1 // 100) + ~bonus:Issuance_bonus_repr.zero + () + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_coeff (Int64.div base_issuance 2L)) + Q.(mul (2 // 1) (compute_coeff base_issuance)) + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_coeff (Int64.mul base_issuance 2L)) + Q.(mul (1 // 2) (compute_coeff base_issuance)) + in + (* Test edge case base = 0 *) + let* () = assert_eq ~loc:__LOC__ (compute_coeff 0L) Q.one in + return_unit + in + (* Test linearity wrt total_supply *) + let* () = + let total_supply = Q.of_int64 1_000_000_000L in + let compute_coeff q_total_supply = + compute_coeff + ~q_total_supply + ~base_reward_coeff_ratio:Q.(1 // 100) + ~bonus:Issuance_bonus_repr.zero + () + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_coeff Q.(mul (1 // 2) total_supply)) + Q.(mul (1 // 2) (compute_coeff total_supply)) + in + let* () = + assert_eq + ~loc:__LOC__ + (compute_coeff Q.(mul (2 // 1) total_supply)) + Q.(mul (2 // 1) (compute_coeff total_supply)) + in + return_unit + in + let* () = + let compute_coeff base_reward_coeff_ratio bonus = + (* bonus must be <= 5% *) + let*?@ bonus = + Issuance_bonus_repr.of_Q ~max_bonus:reward_params.max_bonus bonus + in + return @@ compute_coeff ~base_reward_coeff_ratio ~bonus () + in + let q_mul a b = + let* b in + return @@ Q.mul a b + in + let q_add a b = + let* a in + let* b in + return @@ Q.add a b + in + (* Test linearity wrt base_reward_coeff_ratio *) + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff Q.(2 // 99) Q.zero) + (q_mul Q.(2 // 1) (compute_coeff Q.(1 // 99) Q.zero)) + in + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff Q.(3 // 99) Q.zero) + (q_add + (compute_coeff Q.(2 // 99) Q.zero) + (compute_coeff Q.(1 // 99) Q.zero)) + in + (* Test symmetry *) + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff Q.(1 // 99) Q.zero) + (compute_coeff Q.zero Q.(1 // 99)) + in + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff Q.(2 // 99) Q.(1 // 99)) + (compute_coeff Q.(1 // 99) Q.(2 // 99)) + in + (* Test min *) + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff Q.zero Q.zero) + (compute_coeff reward_params.issuance_ratio_final_min Q.zero) + in + (* Test max *) + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff + (Q.add reward_params.issuance_ratio_final_max Q.one) + Q.zero) + (compute_coeff reward_params.issuance_ratio_final_max Q.zero) + in + let* () = + assert_eq_lwt + ~loc:__LOC__ + (compute_coeff reward_params.issuance_ratio_final_max Q.(1 // 100)) + (compute_coeff reward_params.issuance_ratio_final_max Q.zero) + in + return_unit + in + return_unit + +let test_compute_min_max () = + let open Delegate.Rewards.Internal_for_tests in + let open Lwt_result_wrap_syntax in + (* let assert_eq ~loc a b = Assert.equal ~loc Q.equal "" Q.pp_print a b in *) + let assert_eq_list ~loc a b = + Assert.assert_equal_list ~loc Q.equal "" Q.pp_print a b + in + let reward_params = + Default_parameters.constants_test.adaptive_issuance.adaptive_rewards_params + in + let update_reward_params ?issuance_ratio_final_min ?issuance_ratio_final_max + ?issuance_ratio_initial_min ?issuance_ratio_initial_max ?initial_period + ?transition_period + (reward_params : Constants.Parametric.adaptive_rewards_params) = + let issuance_ratio_final_min = + Option.value + ~default:reward_params.issuance_ratio_final_min + issuance_ratio_final_min + in + let issuance_ratio_final_max = + Option.value + ~default:reward_params.issuance_ratio_final_max + issuance_ratio_final_max + in + let issuance_ratio_initial_min = + Option.value + ~default:reward_params.issuance_ratio_initial_min + issuance_ratio_initial_min + in + let issuance_ratio_initial_max = + Option.value + ~default:reward_params.issuance_ratio_initial_max + issuance_ratio_initial_max + in + let initial_period = + Option.value ~default:reward_params.initial_period initial_period + in + let transition_period = + Option.value ~default:reward_params.transition_period transition_period + in + { + reward_params with + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; + } + in + let compute_aux ~f ?issuance_ratio_final_min ?issuance_ratio_final_max + ?issuance_ratio_initial_min ?issuance_ratio_initial_max ?initial_period + ?transition_period ?(launch_cycle = Some 0l) cycle = + let launch_cycle = Option.map Cycle_repr.of_int32_exn launch_cycle in + let new_cycle = Cycle_repr.of_int32_exn (Int32.of_int cycle) in + let reward_params = + update_reward_params + ?issuance_ratio_final_min + ?issuance_ratio_final_max + ?issuance_ratio_initial_min + ?issuance_ratio_initial_max + ?initial_period + ?transition_period + reward_params + in + f ~reward_params ~launch_cycle ~new_cycle + in + let compute_min = compute_aux ~f:compute_min in + let compute_max = compute_aux ~f:compute_max in + let assert_eq_on_interval ~loc ~f ~from ~to_ expected = + assert (List.length expected = to_ - from + 1) ; + let actual = Stdlib.List.init (to_ - from + 1) (fun i -> f (i + from)) in + assert_eq_list ~loc expected actual + in + (* Python-style list generation *) + let ( *+ ) a b = Stdlib.List.init b (fun _ -> a) in + (* Test before launch cycle *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_min ~launch_cycle:(Some 10l)) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_min *+ 11) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_max ~launch_cycle:(Some 10l)) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_max *+ 11) + in + (* Test no launch cycle *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_min ~launch_cycle:None) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_min *+ 11) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_max ~launch_cycle:None) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_max *+ 11) + in + (* From now on, launch_cycle = 0 *) + (* Test initial period *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_min + ~from:0 + ~to_:reward_params.initial_period + (reward_params.issuance_ratio_initial_min + *+ (reward_params.initial_period + 1)) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_max + ~from:0 + ~to_:reward_params.initial_period + (reward_params.issuance_ratio_initial_max + *+ (reward_params.initial_period + 1)) + in + (* Test final period *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_min + ~from:(reward_params.initial_period + reward_params.transition_period + 1) + ~to_:(reward_params.initial_period + reward_params.transition_period + 10) + (reward_params.issuance_ratio_final_min *+ 10) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_max + ~from:(reward_params.initial_period + reward_params.transition_period + 1) + ~to_:(reward_params.initial_period + reward_params.transition_period + 10) + (reward_params.issuance_ratio_final_max *+ 10) + in + (* Test transition period *) + let* () = + let initial_period = 5 in + let transition_period = 5 in + let issuance_ratio_initial_min = Q.(7 // 100) in + let issuance_ratio_final_min = Q.(1 // 100) in + (* Min increases by 1/100th per cycle *) + let issuance_ratio_initial_max = Q.(1 // 10) in + let issuance_ratio_final_max = Q.(7 // 10) in + (* Max increases by 1/10th per cycle *) + let compute_min = + compute_min + ~initial_period + ~transition_period + ~issuance_ratio_initial_max + ~issuance_ratio_initial_min + ~issuance_ratio_final_max + ~issuance_ratio_final_min + in + let compute_max = + compute_max + ~initial_period + ~transition_period + ~issuance_ratio_initial_max + ~issuance_ratio_initial_min + ~issuance_ratio_final_max + ~issuance_ratio_final_min + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_min + ~from:0 + ~to_:15 + ((issuance_ratio_initial_min *+ 6) + @ Q.[6 // 100; 5 // 100; 4 // 100; 3 // 100; 2 // 100] + @ (issuance_ratio_final_min *+ 5)) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_max + ~from:0 + ~to_:15 + ((issuance_ratio_initial_max *+ 6) + @ Q.[2 // 10; 3 // 10; 4 // 10; 5 // 10; 6 // 10] + @ (issuance_ratio_final_max *+ 5)) + in + return_unit + in + return_unit + +let tests = + Tztest. + [ + tztest + "adaptive issuance - application of coefficient to rewards" + `Quick + test_reward_coefficient; + tztest + "adaptive issuance - reward coeff ratio computation" + `Quick + test_reward_coeff_ratio; + tztest + "adaptive issuance - reward bonus computation" + `Quick + test_compute_bonus; + tztest + "adaptive issuance - reward coeff computation" + `Quick + test_compute_coeff; + tztest + "adaptive issuance - min/max coeff computation" + `Quick + test_compute_min_max; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("adaptive issuance", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance_ema.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance_ema.ml new file mode 100644 index 000000000000..6c50bcae9d27 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_adaptive_issuance_ema.ml @@ -0,0 +1,310 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol, Adaptive Issuance + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_adaptive_issuance_ema.ml + Subject: Tests for the update functions of the EMA of the launch vote of + Adaptive Issuance +*) + +open Protocol +module Votes_EMA = Per_block_votes_repr.Adaptive_issuance_launch_EMA + +let ema_of_int32 ema = + let open Lwt_result_wrap_syntax in + let*@ result = Votes_EMA.of_int32 ema in + return result + +let ema_to_int32 = Votes_EMA.to_int32 + +let compute_new_ema ~per_block_vote ema = + Per_block_votes_repr.compute_new_adaptive_issuance_ema ~per_block_vote ema + |> ema_to_int32 + +(* Folds compute_new_ema on a list of votes *) +let compute_new_ema_n per_block_votes initial_ema = + List.fold_left + (fun ema per_block_vote -> + Per_block_votes_repr.compute_new_adaptive_issuance_ema ~per_block_vote ema) + initial_ema + per_block_votes + |> ema_to_int32 + +let ema_range = + [ + 0l; + 1l; + 10l; + 100l; + 1000l; + 10_000l; + 100_000l; + 1_000_000l; + 10_000_000l; + 100_000_000l; + 200_000_000l; + 300_000_000l; + 400_000_000l; + 500_000_000l; + 600_000_000l; + 760_000_000l; + 800_000_000l; + 900_000_000l; + 1_000_000_000l; + 1_100_000_000l; + 1_200_000_000l; + 1_300_000_000l; + 1_400_000_000l; + 1_500_000_000l; + 1_600_000_000l; + 1_700_000_000l; + 1_800_000_000l; + 1_900_000_000l; + 1_990_000_000l; + 1_999_000_000l; + 1_999_900_000l; + 1_999_990_000l; + 1_999_999_000l; + 1_999_999_900l; + 1_999_999_990l; + 1_999_999_999l; + 2_000_000_000l; + ] + +(* Test that new_ema = old_ema when voting Pass. *) +let test_ema_pass () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.equal_int32 + ~loc:__LOC__ + (compute_new_ema ~per_block_vote:Per_block_vote_pass ema) + old_ema) + ema_range + +(* Test that new_ema is still between 0 and 2,000,000,000 after an On vote. *) +let test_ema_in_bound_on () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + let new_ema = compute_new_ema ~per_block_vote:Per_block_vote_on ema in + let* () = Assert.leq_int32 ~loc:__LOC__ 0l new_ema in + Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) + ema_range + +(* Test that new_ema > old_ema when voting On, except if old_ema is + already very close to the upper bound. *) +let test_ema_increases_on () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.lt_int32 + ~loc:__LOC__ + old_ema + (compute_new_ema ~per_block_vote:Per_block_vote_on ema)) + (List.filter (fun ema -> Compare.Int32.(ema < 1_999_000_000l)) ema_range) + +(* Test that the increase in EMA caused by an On vote is bounded by 1,000,000 *) +let test_ema_increases_on_bound () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.leq_int32 + ~loc:__LOC__ + (Int32.sub + (compute_new_ema ~per_block_vote:Per_block_vote_on ema) + old_ema) + 1_000_000l) + ema_range + +(* Test that new_ema is still between 0 and 2,000,000,000 after an Off vote. *) +let test_ema_in_bound_off () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + let new_ema = compute_new_ema ~per_block_vote:Per_block_vote_off ema in + let* () = Assert.leq_int32 ~loc:__LOC__ 0l new_ema in + Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) + ema_range + +(* Test that new_ema < old_ema when voting Off, except if old_ema is + already very close to the lower bound. *) +let test_ema_decreases_off () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.lt_int32 + ~loc:__LOC__ + (compute_new_ema ~per_block_vote:Per_block_vote_off ema) + old_ema) + (List.filter (fun ema -> Compare.Int32.(ema > 1_000_000l)) ema_range) + +(* Test that the decrease in EMA caused by an Off vote is bounded by 1,000,000 *) +let test_ema_decreases_off_bound () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.leq_int32 + ~loc:__LOC__ + (Int32.sub + (compute_new_ema ~per_block_vote:Per_block_vote_off ema) + old_ema) + 1_000_000l) + ema_range + +(* Test that 120961 On votes are needed to move from 0% to 50%. *) +let test_ema_many_on () = + let open Lwt_result_syntax in + let open Per_block_votes_repr in + let* initial_ema = ema_of_int32 0l in + let* () = + Assert.leq_int32 + ~loc:__LOC__ + (compute_new_ema_n + (Stdlib.List.init 80321 (fun _ -> Per_block_vote_on)) + initial_ema) + 1_000_000_000l + in + Assert.leq_int32 + ~loc:__LOC__ + 1_000_000_000l + (compute_new_ema_n + (Stdlib.List.init 120961 (fun _ -> Per_block_vote_on)) + initial_ema) + +(* Test that 120961 Off votes are needed to move from 100% to 50%. *) +let test_ema_many_off () = + let open Lwt_result_syntax in + let open Per_block_votes_repr in + let* initial_ema = ema_of_int32 2_000_000_000l in + let* () = + Assert.leq_int32 + ~loc:__LOC__ + 1_000_000_000l + (compute_new_ema_n + (Stdlib.List.init 80321 (fun _ -> Per_block_vote_off)) + initial_ema) + in + Assert.leq_int32 + ~loc:__LOC__ + (compute_new_ema_n + (Stdlib.List.init 120961 (fun _ -> Per_block_vote_off)) + initial_ema) + 1_000_000_000l + +(* Test that 187259 On votes are needed to move from 0% to 80%. *) +let test_ema_many_many_on () = + let open Lwt_result_syntax in + let open Per_block_votes_repr in + let* initial_ema = ema_of_int32 0l in + let* () = + Assert.leq_int32 + ~loc:__LOC__ + (compute_new_ema_n + (Stdlib.List.init 187258 (fun _ -> Per_block_vote_on)) + initial_ema) + 1_600_000_000l + in + Assert.leq_int32 + ~loc:__LOC__ + 1_600_000_000l + (compute_new_ema_n + (Stdlib.List.init 280894 (fun _ -> Per_block_vote_on)) + initial_ema) + +(* Test that the EMA update function is symmetric: + from two dual values of the EMA (that is, two values x and y such that + x + y = 2,000,000,000), voting Off on the first one decreases it by as + much than voting On on the second one increases it. +*) +let test_ema_symmetry () = + let open Lwt_result_syntax in + List.iter_es + (fun ema -> + let opposite_ema = Int32.(sub 2_000_000_000l ema) in + let* ema = ema_of_int32 ema in + let* opposite_ema = ema_of_int32 opposite_ema in + let new_ema = compute_new_ema ~per_block_vote:Per_block_vote_off ema in + let new_opposite_ema = + compute_new_ema ~per_block_vote:Per_block_vote_on opposite_ema + in + Assert.equal_int32 + ~loc:__LOC__ + Int32.(add new_ema new_opposite_ema) + 2_000_000_000l) + ema_range + +let tests = + [ + Tztest.tztest "EMA does not change when vote is Pass" `Quick test_ema_pass; + Tztest.tztest + "EMA remains in bounds when vote is On" + `Quick + test_ema_in_bound_on; + Tztest.tztest "EMA increases when vote is On" `Quick test_ema_increases_on; + Tztest.tztest + "EMA does not increase too much when vote is On" + `Quick + test_ema_increases_on_bound; + Tztest.tztest + "EMA remains in bounds when vote is Off" + `Quick + test_ema_in_bound_off; + Tztest.tztest "EMA decreases when vote is Off" `Quick test_ema_decreases_off; + Tztest.tztest + "EMA does not decrease too much when vote is Off" + `Quick + test_ema_decreases_off_bound; + Tztest.tztest + "EMA goes from 0% to 50% in 120961 On votes" + `Quick + test_ema_many_on; + Tztest.tztest + "EMA goes from 100% to 50% in 120961 Off votes" + `Quick + test_ema_many_off; + Tztest.tztest + "EMA goes from 0% to 80% in 280894 On votes" + `Quick + test_ema_many_many_on; + Tztest.tztest + "voting On and Off have symmetric effects on the EMA" + `Quick + test_ema_symmetry; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("adaptive issuance ema", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_alpha_context.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_alpha_context.ml new file mode 100644 index 000000000000..60fbdb579d51 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_alpha_context.ml @@ -0,0 +1,296 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Testing + ------- + Component: Alpha_context + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_alpha_context.ml + Dependencies: helpers/block.ml + Subject: To test the modules (including the top-level) + in alpha_context.ml as individual units, particularly + failure cases. Superficial goal: increase coverage percentage. +*) + +(** Creates an Alpha_context without creating a full-fledged block *) +let create () = + let account = Account.new_account () in + let bootstrap_account = Account.make_bootstrap_account account in + Block.alpha_context [bootstrap_account] + +let assert_equal_key_values ~loc kvs1 kvs2 = + let sort_by_key_hash = + List.sort (fun (k1, _) (k2, _) -> Script_expr_hash.compare k1 k2) + in + Assert.assert_equal_list + ~loc + (fun (k1, v1) (k2, v2) -> + Script_expr_hash.equal k1 k2 + && String.equal (Expr.to_string v1) (Expr.to_string v2)) + "Compare key-value list" + (fun fmt (k, v) -> + Format.fprintf fmt "(%a, %s)" Script_expr_hash.pp k (Expr.to_string v)) + (sort_by_key_hash kvs1) + (sort_by_key_hash kvs2) + +module Test_Script = struct + (** Force serialise of lazy [Big_map.t] in a given [alpha_context] *) + let test_force_bytes_in_context () = + let open Lwt_result_wrap_syntax in + let* alpha_context = create () in + let mbytes_pp ppf t = + Format.pp_print_string ppf (Environment.Bytes.to_string t) + in + let open Alpha_context.Script in + let*?@ bytes, _ = + force_bytes_in_context alpha_context + @@ lazy_expr @@ Micheline.strip_locations + @@ Prim (0, D_Unit, [], []) + in + Assert.equal + ~loc:__LOC__ + Environment.Bytes.equal + "script serialised incorrectly" + mbytes_pp + bytes + (`Hex "030b" |> Hex.to_bytes_exn) +end + +module Test_Big_map = struct + (** Test failure path: look for a non-existent key in a [Big_map] *) + let test_mem () = + let open Lwt_result_wrap_syntax in + let* alpha_context = create () in + let*@ alpha_context, big_map_id = + Big_map.fresh ~temporary:true alpha_context + in + let*@ _alpha_context, is_member = + Big_map.mem + alpha_context + big_map_id + (Script_expr_hash.hash_string ["0"; "0"]) + in + Assert.equal_bool ~loc:__LOC__ is_member false + + (** Test failure code path of [get_opt] by looking for missing key in a [Big_map.t] *) + let test_get_opt () = + let open Lwt_result_wrap_syntax in + let* alpha_context = create () in + let*@ alpha_context, big_map_id = + Big_map.fresh ~temporary:true alpha_context + in + let*@ _alpha_context, value = + Big_map.get_opt + alpha_context + big_map_id + (Script_expr_hash.hash_string ["0"; "0"]) + in + match value with + | Some _ -> + failwith "get_opt should have failed looking for a non-existent key" + | None -> return_unit + + (** Test existence of a non-existent [Big_map] in an [Alpha_context.t] *) + let test_exists () = + let open Lwt_result_wrap_syntax in + let* alpha_context = create () in + let*@ alpha_context, big_map_id = + Big_map.fresh ~temporary:true alpha_context + in + let*@ _alpha_context, value = Big_map.exists alpha_context big_map_id in + match value with + | Some _ -> + failwith "exists should have failed looking for a non-existent big_map" + | None -> return_unit + + (** Test that [Big_map.list_key_values] retrieves hashed keys and values. *) + let test_list_key_values () = + let open Lwt_result_wrap_syntax in + let* block, source = Context.init1 () in + let key_values = + [ + ("1", {|"A"|}); + ("2", {|"B"|}); + ("3", {|"C"|}); + ("4", {|"D"|}); + ("5", {|"E"|}); + ] + |> List.map (fun (k, v) -> (Expr.from_string k, Expr.from_string v)) + in + let* big_map_id, ctxt = + Big_map_helpers.make_big_map + block + ~source + ~key_type:"int" + ~value_type:"string" + key_values + in + let*@ _ctxt, retrieved_key_values = + Big_map.list_key_values ctxt big_map_id + in + let expected_key_hash_values = + List.map + (fun (key, value) -> + let bytes = + Data_encoding.Binary.to_bytes_exn Script_repr.expr_encoding key + in + let key_hash = Script_expr_hash.hash_bytes [bytes] in + (key_hash, value)) + key_values + in + assert_equal_key_values + ~loc:__LOC__ + expected_key_hash_values + retrieved_key_values + + (** Test [Big_map.list_key_values] with [length] and [offset] arguments. *) + let test_list_key_values_parameters () = + let open Lwt_result_wrap_syntax in + let* block, source = Context.init1 () in + let hash_key key = + let bytes = + Data_encoding.Binary.to_bytes_exn Script_repr.expr_encoding key + in + Script_expr_hash.hash_bytes [bytes] + in + let check_key_values ~loc ~num_elements ?offset ?length () = + let key_values = + WithExceptions.List.init ~loc:__LOC__ num_elements (fun n -> + (string_of_int n, Printf.sprintf {|"Value %d"|} n)) + |> List.map (fun (k, v) -> (Expr.from_string k, Expr.from_string v)) + in + let sorted_key_values = + List.sort + (fun (k1, _) (k2, _) -> + Script_expr_hash.compare (hash_key k1) (hash_key k2)) + key_values + in + let* big_map_id, ctxt = + Big_map_helpers.make_big_map + block + ~source + ~key_type:"int" + ~value_type:"string" + key_values + in + let*@ _ctxt, retrieved_key_values = + Big_map.list_key_values ?offset ?length ctxt big_map_id + in + let expected_key_hash_values = + (* A negative length is interpreted as 0 *) + let length = + match length with + | Some l -> max l 0 + | None -> List.length sorted_key_values + in + let offset = match offset with Some o -> max o 0 | None -> 0 in + let expected = + List.take_n length @@ List.drop_n offset sorted_key_values + in + List.map + (fun (key, value) -> + let bytes = + Data_encoding.Binary.to_bytes_exn Script_repr.expr_encoding key + in + let key_hash = Script_expr_hash.hash_bytes [bytes] in + (key_hash, value)) + expected + in + let* () = + assert_equal_key_values + ~loc + retrieved_key_values + expected_key_hash_values + in + return retrieved_key_values + in + (* The following combinations should yield the same key-values. *) + let* kvs1 = check_key_values ~loc:__LOC__ ~num_elements:10 () in + let* kvs2 = check_key_values ~loc:__LOC__ ~num_elements:10 ~offset:0 () in + let* kvs3 = check_key_values ~loc:__LOC__ ~num_elements:10 ~length:10 () in + let* kvs4 = + check_key_values ~loc:__LOC__ ~num_elements:10 ~offset:0 ~length:10 () + in + let* () = assert_equal_key_values ~loc:__LOC__ kvs1 kvs2 in + let* () = assert_equal_key_values ~loc:__LOC__ kvs2 kvs3 in + let* () = assert_equal_key_values ~loc:__LOC__ kvs3 kvs4 in + (* Attempt to consume more elements then the length. *) + let* kvs1 = check_key_values ~loc:__LOC__ ~num_elements:20 () in + let* kvs2 = check_key_values ~loc:__LOC__ ~num_elements:20 ~length:100 () in + let* () = assert_equal_key_values ~loc:__LOC__ kvs1 kvs2 in + let* (_ : _ list) = + check_key_values ~loc:__LOC__ ~num_elements:100 ~offset:100 ~length:1 () + in + (* Offset greater than the length. *) + let* kvs = check_key_values ~loc:__LOC__ ~num_elements:10 ~offset:100 () in + let* () = assert_equal_key_values ~loc:__LOC__ kvs [] in + (* Negative length is treated as zero. *) + let* kvs = check_key_values ~loc:__LOC__ ~num_elements:10 ~length:(-1) () in + let* () = assert_equal_key_values ~loc:__LOC__ kvs [] in + (* Negative offset is treated as zero. *) + let* kvs1 = + check_key_values ~loc:__LOC__ ~num_elements:10 ~offset:(-5) () + in + let* kvs2 = check_key_values ~loc:__LOC__ ~num_elements:10 () in + let* () = assert_equal_key_values ~loc:__LOC__ kvs1 kvs2 in + return_unit +end + +let tests = + [ + Tztest.tztest + "Script.force_bytes_in_context: checks if it serialises a simple \ + michelson expression" + `Quick + Test_Script.test_force_bytes_in_context; + Tztest.tztest + "Big_map.mem: failure case - must return false when starting with an \ + empty map" + `Quick + Test_Big_map.test_mem; + Tztest.tztest + "Big_map.get_opt: failure case - looking up key that doesn't exist" + `Quick + Test_Big_map.test_get_opt; + Tztest.tztest + "Big_map.exists: failure case - looking up big_map that doesn't exist" + `Quick + Test_Big_map.test_exists; + Tztest.tztest + "Big_map.list_key_values basic tests" + `Quick + Test_Big_map.test_list_key_values; + Tztest.tztest + "Big_map.list_key_values: combinations of parameters" + `Quick + Test_Big_map.test_list_key_values_parameters; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("alpha context", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_bond_id_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_bond_id_repr.ml new file mode 100644 index 000000000000..6ecdb5dc0eb8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_bond_id_repr.ml @@ -0,0 +1,118 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trilitech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Bond_id_repr + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_bond_id_repr.ml + Dependencies: -- + Subject: Test bond id representations for RPC definitions. +*) + +open Protocol + +let assert_bond_id_result_equal ~loc = + Assert.equal_result + ~loc + ~pp_ok:Bond_id_repr.pp + ~pp_error:Format.pp_print_string + Bond_id_repr.( = ) + ( = ) + +let test_destruct_sc_bond_id_repr () = + let open Lwt_result_syntax in + let sc_rollup_address1 = "sr1JPVatbbPoGp4vb6VfQ1jzEPMrYFcKq6VG" in + let sc_rollup_address2 = "sr1JtMTWShgi1jLrqeHohMwLYiGizpsyWzXJ" in + let invalid_sc_rollup_address = "sr1RWAV26caoU7oVMvetUPMt8CqvGmKtA8BO" in + let destruct = Bond_id_repr.Internal_for_test.destruct in + let sc_bond id = + match Sc_rollup_repr.Address.of_b58check_opt id with + | Some id -> Ok (Bond_id_repr.Sc_rollup_bond_id id) + | None -> Error "Not an sc address" + in + let* () = + assert_bond_id_result_equal + ~loc:__LOC__ + (destruct sc_rollup_address1) + (sc_bond sc_rollup_address1) + in + let* () = + assert_bond_id_result_equal + ~loc:__LOC__ + (destruct sc_rollup_address2) + (sc_bond sc_rollup_address2) + in + Assert.is_error + ~loc:__LOC__ + ~pp:Bond_id_repr.pp + (destruct invalid_sc_rollup_address) + +let test_destruct_invalid_bond_id_repr () = + let open Lwt_result_syntax in + let invalid_address = "asdfasdfasdf" in + let empty_address = "" in + let destruct = Bond_id_repr.Internal_for_test.destruct in + let* () = + Assert.is_error ~loc:__LOC__ ~pp:Bond_id_repr.pp (destruct invalid_address) + in + Assert.is_error ~loc:__LOC__ ~pp:Bond_id_repr.pp (destruct empty_address) + +let test_roundtrip () = + let open Lwt_result_syntax in + let destruct_for_rountrip v = + let r = + match Bond_id_repr.Internal_for_test.destruct v with + | Ok r -> return r + | _ -> failwith "Destruct failed for %s" v + in + r + in + let rountrip_test loc s = + let* r = destruct_for_rountrip s in + let s2 = Bond_id_repr.Internal_for_test.construct r in + Assert.equal_string ~loc s s2 + in + let sc_rollup_address1 = "sr1JPVatbbPoGp4vb6VfQ1jzEPMrYFcKq6VG" in + let sc_rollup_address2 = "sr1JtMTWShgi1jLrqeHohMwLYiGizpsyWzXJ" in + let* () = rountrip_test __LOC__ sc_rollup_address1 in + rountrip_test __LOC__ sc_rollup_address2 + +let tests = + [ + Tztest.tztest + "Deserializing sc bond ids succeeds only when id is valid" + `Quick + test_destruct_sc_bond_id_repr; + Tztest.tztest + "Deserializing invalid bond ids fails" + `Quick + test_destruct_invalid_bond_id_repr; + Tztest.tztest "Deserialize/serialize roundtrip" `Quick test_roundtrip; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Bond_id_repr.ml", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_consensus_key.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_consensus_key.ml new file mode 100644 index 000000000000..299c08388896 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_consensus_key.ml @@ -0,0 +1,260 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (delegate_consensus_key) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_consensus_key.ml + Subject: Functions from the module `Delegate_consensus_key` +*) + +open Protocol + +let create () = + let open Lwt_result_syntax in + let*? accounts = Account.generate_accounts 2 in + let a1, a2 = match accounts with [a1; a2] -> (a1, a2) | _ -> assert false in + let* ctxt = + Block.alpha_context + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7072 + Adapt the tests to work with the default value of + [consensus_rights_delay]. *) + ~consensus_rights_delay:3 + (Account.make_bootstrap_accounts accounts) + in + return (Alpha_context.Internal_for_tests.to_raw ctxt, a1, a2) + +module Consensus_key = struct + let active_key ctxt pkh = + let open Lwt_result_wrap_syntax in + let*@ result = Delegate_consensus_key.active_key ctxt pkh in + return result + + let active_pubkey ctxt pkh = + let open Lwt_result_wrap_syntax in + let*@ result = Delegate_consensus_key.active_pubkey ctxt pkh in + return result + + let active_pubkey_for_cycle ctxt pkh cycle = + let open Lwt_result_wrap_syntax in + let*@ result = + Delegate_consensus_key.active_pubkey_for_cycle + ctxt + pkh + (Cycle_repr.of_int32_exn (Int32.of_int cycle)) + in + return result + + let pending_updates ctxt pkh = + let open Lwt_result_wrap_syntax in + let*@ result = Delegate_consensus_key.pending_updates ctxt pkh in + return result + + let register_update ctxt pkh pk = + let open Lwt_result_wrap_syntax in + let*@ result = Delegate_consensus_key.register_update ctxt pkh pk in + return result + + let activate ctxt ~new_cycle = Delegate_consensus_key.activate ctxt ~new_cycle +end + +module Assert = struct + include Assert + + let equal_pkh ~__LOC__ a b = + Assert.equal + ~loc:__LOC__ + Signature.Public_key_hash.equal + "pkh" + Signature.Public_key_hash.pp + a + b + + let equal_pk ~__LOC__ a b = + Assert.equal + ~loc:__LOC__ + Signature.Public_key.equal + "pk" + Signature.Public_key.pp + a + b + + let active_keys ~__LOC__ ctxt delegate l = + List.iter_es + (fun (c, pk) -> + let open Lwt_result_syntax in + let* active_pk = + Consensus_key.active_pubkey_for_cycle ctxt delegate c + in + equal_pk ~__LOC__ active_pk.consensus_pk pk) + l +end + +let rec add_cycles ctxt n = + let open Lwt_result_syntax in + if n <= 0 then return ctxt + else + let current_level = Raw_context.current_level ctxt in + let new_cycle = Cycle_repr.succ current_level.cycle in + let*! ctxt = Consensus_key.activate ctxt ~new_cycle in + let ctxt = Raw_context.Internal_for_tests.add_cycles ctxt 1 in + add_cycles ctxt (n - 1) + +let test_consensus_key_storage () = + let open Lwt_result_syntax in + let* ctxt, del1, del2 = create () in + let a1 = Account.new_account () in + let a2 = Account.new_account () in + let consensus_key_activation_delay = + Constants_storage.consensus_key_activation_delay ctxt + in + let* () = Assert.equal_int ~loc:__LOC__ consensus_key_activation_delay 3 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh del1.pkh + in + let* () = + let* active_pk = Consensus_key.active_pubkey ctxt del1.pkh in + Assert.equal_pk ~__LOC__ active_pk.consensus_pk del1.pk + in + let* () = + let* active_pk = Consensus_key.active_pubkey_for_cycle ctxt del1.pkh 3 in + Assert.equal_pk ~__LOC__ active_pk.consensus_pk del1.pk + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh del2.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_active -> true + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del1.pkh a1.pk in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_noop c -> + c = Cycle_repr.of_int32_exn 4l + | _ -> false) + in + let* () = + let*! err = Consensus_key.register_update ctxt del2.pkh a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_active -> true + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del2.pkh del1.pk in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + del1.pkh + [ + (0, del1.pk); + (1, del1.pk); + (2, del1.pk); + (2, del1.pk); + (3, del1.pk); + (4, a1.pk); + (5, a1.pk); + ] + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh del1.pkh + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_noop c -> + c = Cycle_repr.of_int32_exn 4l + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del1.pkh a2.pk in + let* ctxt = Consensus_key.register_update ctxt del2.pkh a1.pk in + let* ctxt = Consensus_key.register_update ctxt del2.pkh del2.pk in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + del1.pkh + [ + (1, del1.pk); + (2, del1.pk); + (2, del1.pk); + (3, del1.pk); + (4, a1.pk); + (5, a2.pk); + (6, a2.pk); + ] + in + let* ctxt = add_cycles ctxt 2 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh del1.pkh + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh a2.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_noop c -> + c = Cycle_repr.of_int32_exn 5l + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del1.pkh a1.pk in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + del1.pkh + [(3, del1.pk); (4, a1.pk); (5, a2.pk); (6, a2.pk); (7, a1.pk); (8, a1.pk)] + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a1.pkh + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a2.pkh + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a2.pkh + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a1.pkh + in + return_unit + +let tests = + [Tztest.tztest "consensus_key_storage" `Quick test_consensus_key_storage] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Delegate consensus key", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_contract_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_contract_repr.ml new file mode 100644 index 000000000000..6aaec0e06f47 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_contract_repr.ml @@ -0,0 +1,124 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Contract_repr + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_contract_repr.ml + Dependencies: contract_hash.ml + Subject: To test the modules (including the top-level) + in contract_repr.ml as individual units, particularly + failure cases. Superficial goal: increase coverage percentage. +*) +open Protocol + +open Tztest + +(* + + TODO: Remove dependence on contract_hash.ml and mock it + + *) + +module Test_contract_repr = struct + (** Assert if [is_implicit] correctly returns the implicit contract *) + open Contract_repr + + let dummy_operation_hash = + Operation_hash.of_bytes_exn + (Bytes.of_string "test-operation-hash-of-length-32") + + let dummy_origination_nonce = Origination_nonce.initial dummy_operation_hash + + let dummy_contract_hash = + (* WARNING: Uses Contract_repr itself, which is yet to be tested. This happened because Contract_hash wasn't mocked *) + let data = + Data_encoding.Binary.to_bytes_exn + Origination_nonce.encoding + dummy_origination_nonce + in + Contract_hash.hash_bytes [data] + + let dummy_implicit_contract = Implicit Signature.Public_key_hash.zero + + let dummy_originated_contract = originated_contract @@ dummy_origination_nonce + + let test_to_b58check_implicit () = + Assert.equal + ~loc:__LOC__ + String.equal + "%s should have been equal to %" + Format.pp_print_string + (to_b58check dummy_implicit_contract) + Signature.Public_key_hash.(to_b58check zero) + + let test_to_b58check_originated () = + Assert.equal + ~loc:__LOC__ + String.equal + "%s should have been equal to %" + Format.pp_print_string + (to_b58check dummy_originated_contract) + Contract_hash.(to_b58check @@ dummy_contract_hash) + + let create_dummy_contracts n = + let since = dummy_origination_nonce in + let rec incr_n_times nonce = function + | 0 -> nonce + | n -> incr_n_times (Origination_nonce.incr nonce) (n - 1) + in + let until = incr_n_times since n in + let contracts = originated_contracts ~since ~until in + contracts + + let test_originated_contracts_basic () = + let n = 5 in + let contracts = create_dummy_contracts n in + Assert.equal_int ~loc:__LOC__ (List.length contracts) n +end + +let tests = + [ + tztest + "Contract_repr.to_b58check: must correctly stringify, b58check encoded, \ + an implicit contract" + `Quick + Test_contract_repr.test_to_b58check_implicit; + tztest + "Contract_repr.originated_contract: must correctly create an originated \ + contract" + `Quick + Test_contract_repr.test_originated_contracts_basic; + tztest + "Contract_repr.to_b58check: must correctly stringify, b58check encoded, \ + an originated contract" + `Quick + Test_contract_repr.test_to_b58check_originated; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Contract_repr.ml", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_dal_slot_proof.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_dal_slot_proof.ml new file mode 100644 index 000000000000..dc132502781f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_dal_slot_proof.ml @@ -0,0 +1,467 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (dal slot proof) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_dal_slot_proof.ml + Subject: These unit tests check proof-related functions of Dal slots. +*) + +open Protocol +module S = Dal_slot_repr +module H = S.Header +module P = S.Page +module Hist = S.History + +module Make (Parameters : sig + val name : string + + val dal_parameters : Alpha_context.Constants.Parametric.dal +end) = +struct + open Dal_helpers.Make (struct + include Parameters + + let cryptobox = + Lazy.from_fun @@ fun () -> + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Dal_helpers.mk_cryptobox Parameters.dal_parameters.cryptobox_parameters + end) + + (* Tests to check insertion of slots in a dal skip list. *) + + (** Check insertion of a new slot in the given skip list. *) + let skip_list_ordering skip_list ~mk_level ~mk_slot_index ~check_result = + let open Lwt_result_wrap_syntax in + let id = + Hist.Internal_for_tests.content skip_list |> Dal_helpers.content_slot_id + in + let level = mk_level id in + let index = mk_slot_index id in + let*? _data, _poly, slot = mk_slot ~level ~index () in + let@ result = + Hist.add_confirmed_slot_headers_no_cache + skip_list + level + [slot] + ~number_of_slots:Parameters.dal_parameters.number_of_slots + in + + check_result result + + (** This test attempts to add a slot on top of genesis cell zero which would + break the ordering. In fact, confirmed slots' skip list is ordered by slots + ID: the slots' level should increase or the level is equal in which case the + slots' index should increase. In the test below, we attempt to insert a slot + where (published_level, slot_index) doesn't increase (is the same as the + genesis cell). *) + let insertion_breaks_skip_list_ordering () = + let open Lwt_result_syntax in + skip_list_ordering + genesis_history + ~mk_level:(fun id -> Raw_level_repr.succ id.H.published_level) + ~mk_slot_index:(fun id -> succ_slot_index id.H.index) + ~check_result:(fun res -> + let* skip_list = Assert.get_ok ~__LOC__ res in + skip_list_ordering + skip_list + ~mk_level:(fun _id -> + Raw_level_repr.root (* Putting root here breaks ordering. *)) + ~mk_slot_index:(fun id -> id.H.index) + ~check_result:(fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Hist.Add_element_in_slots_skip_list_violates_ordering -> true + | _ -> false))) + + (** This test attempts to add a slot on top of genesis cell zero which satisfies + the ordering. *) + let correct_insertion_in_skip_list_ordering_1 () = + let open Lwt_result_syntax in + skip_list_ordering + genesis_history + ~mk_level:(fun id -> Raw_level_repr.succ id.H.published_level) + ~mk_slot_index:(fun id -> id.H.index) + ~check_result:(fun res -> + let* (_skip_list : Hist.t) = Assert.get_ok ~__LOC__ res in + return_unit) + + (** This test attempts to add a slot on top of genesis cell zero which satisfies + the ordering. *) + let correct_insertion_in_skip_list_ordering_2 () = + let open Lwt_result_syntax in + skip_list_ordering + genesis_history + ~mk_level:(fun id -> Raw_level_repr.succ id.H.published_level) + ~mk_slot_index:(fun id -> succ_slot_index id.H.index) + ~check_result:(fun res -> + let* (_skip_list : Hist.t) = Assert.get_ok ~__LOC__ res in + return_unit) + + (** This test attempts to add two slots on top of genesis cell zero which satisfies + the ordering. *) + let correct_insertion_in_skip_list_ordering_3 () = + let open Lwt_result_syntax in + skip_list_ordering + genesis_history + ~mk_level:(fun id -> Raw_level_repr.succ id.H.published_level) + ~mk_slot_index:(fun id -> succ_slot_index id.H.index) + ~check_result:(fun res -> + let* skip_list = Assert.get_ok ~__LOC__ res in + skip_list_ordering + skip_list + ~mk_level:(fun id -> Raw_level_repr.(succ id.H.published_level)) + ~mk_slot_index:(fun id -> id.H.index) + ~check_result:(fun res -> + let* (_skip_list : Hist.t) = Assert.get_ok ~__LOC__ res in + return_unit)) + + (* Tests of construct/verify proofs that confirm/unconfirm pages on top of + genesis skip list (whose unique cell is slot zero). *) + + (** This test attempts to construct a proof to unconfirm a slot page from the + genesis skip list. Proof production is expected to succeed. *) + let unconfirmed_page_on_genesis () = + let Dal_slot_repr.Header.{published_level; index} = + Hist.Internal_for_tests.content genesis_history + |> Dal_helpers.content_slot_id + in + let page_id = mk_page_id published_level index P.Index.zero in + produce_and_verify_proof + genesis_history + ~get_history:(get_history genesis_history_cache) + (* values of level and slot index are equal to slot zero. We would get a + page confirmation proof. But, no proof that confirms the existence of a page + in slot [zero] is possible. *) + ~page_info:None + ~page_id + ~check_produce:(successful_check_produce_result ~__LOC__ `Unconfirmed) + + (** This test attempts to construct a proof to unconfirm a slot page from the + genesis skip list. But there is no cell with the page's level in the + history cache. *) + let unconfirmed_page_on_genesis_bad_cache () = + let Dal_slot_repr.Header.{published_level; index} = + Hist.Internal_for_tests.content genesis_history + |> Dal_helpers.content_slot_id + in + let level, sindex = + if false then (Raw_level_repr.succ published_level, index) + else (published_level, succ_slot_index index) + in + let page_id = mk_page_id level sindex P.Index.zero in + produce_and_verify_proof + genesis_history + ~get_history:(get_history genesis_history_cache) + ~page_info:None + ~page_id + ~check_produce:(bad_history_cache ~__LOC__) + + (* Tests of construct/verify proofs that attempt to confirm pages on top of a + (confirmed) slot added in genesis_history skip list. *) + + (** Helper function that adds a slot a top of the genesis skip list. *) + let helper_confirmed_slot_on_genesis ~level ~mk_page_info ~check_produce + ?check_verify ?index () = + let open Lwt_result_wrap_syntax in + let*? _slot_data, polynomial, slot = mk_slot ~level ?index () in + let*?@ skip_list, cache = + Hist.add_confirmed_slot_headers + ~number_of_slots:Parameters.dal_parameters.number_of_slots + genesis_history + genesis_history_cache + level + [slot] + in + let*? page_info, page_id = mk_page_info slot polynomial in + produce_and_verify_proof + skip_list + ~get_history:(get_history cache) + ~page_info + ~page_id + ?check_verify + ~check_produce + + (** Test where a slot is confirmed, requesting a proof for a confirmed page, + where the correct data and page proof are provided. *) + let confirmed_slot_on_genesis_confirmed_page_good_data = + helper_confirmed_slot_on_genesis + ~level:level_one + ~mk_page_info + ~check_produce:(successful_check_produce_result ~__LOC__ `Confirmed) + ~check_verify:(successful_check_verify_result ~__LOC__ `Confirmed) + + (** Test where a slot is confirmed, requesting a proof for a confirmed page, + where the page data and proof are not given. *) + let confirmed_slot_on_genesis_confirmed_page_no_data = + helper_confirmed_slot_on_genesis + ~level:level_one + ~mk_page_info:(mk_page_info ~custom_data:no_data) + ~check_produce:(slot_confirmed_but_page_data_not_provided ~__LOC__) + + (** Test where a slot is confirmed, requesting a proof for a confirmed page, + where correct data are provided, but the given page proof is wrong. *) + let confirmed_slot_on_genesis_confirmed_page_bad_page_proof = + let open Result_syntax in + helper_confirmed_slot_on_genesis + ~level:level_one + ~mk_page_info:(fun slot poly -> + let* page_info1, _page_id1 = mk_page_info ~page_index:1 slot poly in + let* page_info2, page_id2 = mk_page_info ~page_index:2 slot poly in + assert ( + match (page_info1, page_info2) with + | Some (_d1, p1), Some (_d2, p2) -> not (eq_page_proof p1 p2) + | _ -> false) ; + return (page_info1, page_id2)) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Dal_proof_error + "Wrong page content for the given page index and slot \ + commitment (page id=(published_level: 1, slot_index: 0, \ + page_index: 2)).")) + + (** Test where a slot is confirmed, requesting a proof for a confirmed page, + where correct page proof is provided, but given page data is altered. *) + let confirmed_slot_on_genesis_confirmed_page_bad_data_right_length = + helper_confirmed_slot_on_genesis + ~level:level_one + ~mk_page_info: + (mk_page_info + ~custom_data: + (Some + (fun ~default_char page_size -> + Some + (Bytes.init page_size (fun i -> + if i = 0 then next_char default_char else default_char))))) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Dal_proof_error + "Wrong page content for the given page index and slot \ + commitment (page id=(published_level: 1, slot_index: 0, \ + page_index: 0)).")) + + (** Same as {!confirmed_slot_on_genesis_confirmed_page_bad_data_right_length} + but the data is too short. *) + let confirmed_slot_on_genesis_confirmed_page_bad_data_short = + let page_size = Parameters.dal_parameters.cryptobox_parameters.page_size in + helper_confirmed_slot_on_genesis + ~level:level_one + ~mk_page_info: + (mk_page_info + ~custom_data: + (Some + (fun ~default_char page_size -> + Some (Bytes.make (page_size - 1) default_char)))) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Unexpected_page_size + {expected_size = page_size; page_size = page_size - 1})) + + (** Same as {!confirmed_slot_on_genesis_confirmed_page_bad_data_right_length} + but the data is too long. *) + let confirmed_slot_on_genesis_confirmed_page_bad_data_long = + let page_size = Parameters.dal_parameters.cryptobox_parameters.page_size in + helper_confirmed_slot_on_genesis + ~level:level_one + ~mk_page_info: + (mk_page_info + ~custom_data: + (Some + (fun ~default_char page_size -> + Some (Bytes.make (page_size + 1) default_char)))) + ~check_produce: + (failing_check_produce_result + ~__LOC__ + ~expected_error: + (Hist.Unexpected_page_size + {expected_size = page_size; page_size = page_size + 1})) + + (* Variants of the tests above: Construct/verify proofs that attempt to + unconfirm pages on top of a (confirmed) slot added in genesis_history skip + list. + + All the tests are somehow equivalent when building "Unconfirmed page" proof, + because the page's data & page's proof are ignored in this case. + *) + + (** Specialisation of helper {!helper_confirmed_slot_on_genesis}, where some + parameters are fixed. *) + let helper_confirmed_slot_on_genesis_unconfirmed_page ~check_produce + ?check_verify ~page_level ~mk_page_info = + helper_confirmed_slot_on_genesis + ~level:page_level + ~mk_page_info + ~check_produce + ?check_verify + + let slot_index_2 = + match Dal_slot_index_repr.of_int_opt ~number_of_slots:20 2 with + | None -> assert false + | Some v -> v + + (** Unconfirmation proof for a page with good data. *) + let confirmed_slot_on_genesis_unconfirmed_page_good_data = + helper_confirmed_slot_on_genesis_unconfirmed_page + ~page_level:level_one + ~mk_page_info:(mk_page_info ~slot_index:slot_index_2) + ~check_produce:(slot_not_confirmed_but_page_data_provided ~__LOC__) + + (** Unconfirmation proof for a page with no data. *) + let confirmed_slot_on_genesis_unconfirmed_page_no_data = + helper_confirmed_slot_on_genesis_unconfirmed_page + ~page_level:level_one + ~mk_page_info:(mk_page_info ~custom_data:no_data ~slot_index:slot_index_2) + ~check_produce:(successful_check_produce_result ~__LOC__ `Unconfirmed) + + (** Unconfirmation proof for a page with bad page proof. *) + let confirmed_slot_on_genesis_unconfirmed_page_bad_proof = + let open Result_syntax in + let level = level_one in + helper_confirmed_slot_on_genesis_unconfirmed_page + ~page_level:level + ~mk_page_info:(fun slot poly -> + let* page_info1, _page_id1 = + mk_page_info ~slot_index:slot_index_2 ~page_index:1 slot poly + in + let* _page_info2, page_id2 = + mk_page_info ~slot_index:slot_index_2 ~page_index:2 slot poly + in + assert ( + match (page_info1, _page_info2) with + | Some (_d1, p1), Some (_d2, p2) -> not (eq_page_proof p1 p2) + | _ -> false) ; + return (page_info1, page_id2)) + ~check_produce:(slot_not_confirmed_but_page_data_provided ~__LOC__) + + (** Unconfirmation proof for a page with bad data. *) + let confirmed_slot_on_genesis_unconfirmed_page_bad_data = + let level = level_one in + helper_confirmed_slot_on_genesis_unconfirmed_page + ~page_level:level + ~mk_page_info: + (mk_page_info + ~slot_index:slot_index_2 + ~custom_data: + (Some + (fun ~default_char page_size -> + Some + (Bytes.init page_size (fun i -> + if i = 0 then next_char default_char else default_char))))) + ~check_produce:(slot_not_confirmed_but_page_data_provided ~__LOC__) + + (* The list of tests. *) + let tests = + let mk_title = Format.sprintf "[%s] %s" Parameters.name in + let tztest title test_function = + Tztest.tztest (mk_title title) `Quick test_function + in + let ordering_tests = + [ + tztest + "add a slot on top of genesis that breaks ordering" + insertion_breaks_skip_list_ordering; + tztest + "add a slot on top of genesis that satisfies ordering (1/2)" + correct_insertion_in_skip_list_ordering_1; + tztest + "add a slot on top of genesis that satisfies ordering (2/2)" + correct_insertion_in_skip_list_ordering_2; + tztest + "add two slots on top of genesis that satisfy ordering" + correct_insertion_in_skip_list_ordering_3; + ] + in + let proofs_tests_on_genesis = + [ + tztest "Unconfirmed page on genesis - ok" unconfirmed_page_on_genesis; + tztest + "Unconfirmed page on genesis - bad cache" + unconfirmed_page_on_genesis_bad_cache; + ] + in + + let confirmed_slot_on_genesis_confirmed_page_tests = + [ + tztest + "Confirmed slot on top of genesis: confirmed page with good data" + confirmed_slot_on_genesis_confirmed_page_good_data; + tztest + "Confirmed slot on top of genesis: confirmed page with no data" + confirmed_slot_on_genesis_confirmed_page_no_data; + tztest + "Confirmed slot on top of genesis: confirmed page with bad proof" + confirmed_slot_on_genesis_confirmed_page_bad_page_proof; + tztest + "Confirmed slot on top of genesis: confirmed page with bad data" + confirmed_slot_on_genesis_confirmed_page_bad_data_right_length; + tztest + "Confirmed slot on top of genesis: confirmed page with too short data" + confirmed_slot_on_genesis_confirmed_page_bad_data_short; + tztest + "Confirmed slot on top of genesis: confirmed page with too long data" + confirmed_slot_on_genesis_confirmed_page_bad_data_long; + ] + in + let confirmed_slot_on_genesis_unconfirmed_page_tests = + [ + tztest + "Confirmed slot on top of genesis: unconfirmed page with good data" + confirmed_slot_on_genesis_unconfirmed_page_good_data; + tztest + "Confirmed slot on top of genesis: unconfirmed page with no data" + confirmed_slot_on_genesis_unconfirmed_page_no_data; + tztest + "Confirmed slot on top of genesis: unconfirmed page with bad proof" + confirmed_slot_on_genesis_unconfirmed_page_bad_proof; + tztest + "Confirmed slot on top of genesis: unconfirmed page with bad data \ + (altered)" + confirmed_slot_on_genesis_unconfirmed_page_bad_data; + ] + in + ordering_tests @ proofs_tests_on_genesis + @ confirmed_slot_on_genesis_confirmed_page_tests + @ confirmed_slot_on_genesis_unconfirmed_page_tests +end + +let tests = + let open Tezos_protocol_020_PsParisC_parameters.Default_parameters in + let module Test = Make (struct + let name = "test" + + let dal_parameters = constants_test.dal + end) in + Test.tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("dal slot proof", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_destination_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_destination_repr.ml new file mode 100644 index 000000000000..ac110612ca62 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_destination_repr.ml @@ -0,0 +1,232 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Destination_repr + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_destination_repr.ml + Subject: To test the encoding of [Destination_repr] and assert it is + compatible with [Contract_repr.encoding]. +*) + +open Protocol +open Tztest + +let dummy_operation_hash = + Operation_hash.of_bytes_exn + (Bytes.of_string "test-operation-hash-of-length-32") + +let dummy_origination_nonce = Origination_nonce.initial dummy_operation_hash + +let contracts = + let since = dummy_origination_nonce in + let rec incr_n_times nonce = function + | 0 -> nonce + | n -> incr_n_times (Origination_nonce.incr nonce) (n - 1) + in + let until = incr_n_times since 5 in + Contract_repr.originated_contracts ~since ~until + |> List.map (fun c -> Contract_repr.Originated c) + +let dest x = Destination_repr.Contract x + +let construct = Data_encoding.Json.construct + +let destruct = Data_encoding.Json.destruct + +let to_bytes_exn = Data_encoding.Binary.to_bytes_exn + +let of_bytes_exn = Data_encoding.Binary.of_bytes_exn + +let ( !! ) = function Ok x -> x | Error _ -> raise (Invalid_argument "( !! )") + +(* The following addresses have been extracted from TzKT. *) + +let null_address = "tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU" + +let liquidity_baking_dex = "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" + +(* The following address has been extracted from + [tezt/_regressions/tx_rollup_simple_use_case.out]. *) + +let tx_rollup_address = "txr1YNMEtkj5Vkqsbdmt7xaxBTMRZjzS96UAi" + +(* The following address has been extracted like this: + - [dune exec tezt/tests/main.exe -- -verbose --file sc_rollup.ml + sc_rollup list] +*) +let sc_rollup_address = "sr1BAwv191dVYeZg44ZxVy8dFwfRQKW6bSqc" + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/3731 + Explain how this address was computed *) +let zk_rollup_address = "epx18RJJqrYuJQqhB636BWvukU3XBNQGbtm8C" + +let assert_compat contract destination = + match destination with + | Destination_repr.Contract contract' + when Contract_repr.equal contract contract' -> + () + | _ -> raise (Invalid_argument "assert_compat") + +(** [test_decoding_json_compat str] decodes [str] as both a [Destination_repr.t] + and [Contract_repr.t], and checks the two are equal. *) +let test_decoding_json_compat str () = + let open Lwt_result_syntax in + let json = + !!(Data_encoding.Json.from_string @@ Format.sprintf {|"%s"|} str) + in + let contract = destruct Contract_repr.encoding json in + let destination = destruct Destination_repr.encoding json in + + assert_compat contract destination ; + + return_unit + +(** [test_encode_contract_decode_destination str] interprets [str] as + a [Contract_repr.t], encodes it in a bytes array, then decodes it + as a [Destination_repr.t]. The resulting destination should be + equal to the initial contract. *) +let test_encode_contract_decode_destination str () = + let open Lwt_result_syntax in + let contract = !!(Contract_repr.of_b58check str) in + let bytes = to_bytes_exn Contract_repr.encoding contract in + let destination = of_bytes_exn Destination_repr.encoding bytes in + + assert_compat contract destination ; + + return_unit + +(** [test_encode_destination_decode_contract str] interprets [str] as + a [Destination_repr.t], encodes it in a bytes array, then decodes + it as a [Contract_repr.t]. The resulting contract should be equal + to the initial destination. *) +let test_encode_destination_decode_contract str () = + let open Lwt_result_syntax in + let destination = !!(Destination_repr.of_b58check str) in + let bytes = to_bytes_exn Destination_repr.encoding destination in + let contract = of_bytes_exn Contract_repr.encoding bytes in + + assert_compat contract destination ; + + return_unit + +let encoding_compat ~encode_contract ~decode_contract ~encode_destination + ~decode_destination contract = + let open Lwt_result_syntax in + let destination = dest contract in + + let encoded_contract = encode_contract contract in + let encoded_destination = encode_destination destination in + + let destination_of_contract = decode_destination encoded_contract in + let contract_of_destination = decode_contract encoded_destination in + + assert_compat contract_of_destination destination ; + assert_compat contract destination_of_contract ; + + return_unit + +(** [encoding_json_compat contract] creates a {!Destination_repr.t} using + a dummy contract and ensures that their JSON encodings are compatible with + each other. +*) +let encoding_json_compat contract = + encoding_compat + ~encode_contract:(construct Contract_repr.encoding) + ~decode_contract:(destruct Contract_repr.encoding) + ~encode_destination:(construct Destination_repr.encoding) + ~decode_destination:(destruct Destination_repr.encoding) + contract + +(** [encoding_json_compat contract] creates a {!Destination_repr.t} using + a dummy contract and ensures that their binary encodings are compatible with + each other. +*) +let encoding_binary_compat contract = + encoding_compat + ~encode_contract:(to_bytes_exn Contract_repr.encoding) + ~decode_contract:(of_bytes_exn Contract_repr.encoding) + ~encode_destination:(to_bytes_exn Destination_repr.encoding) + ~decode_destination:(of_bytes_exn Destination_repr.encoding) + contract + +let test_contracts f () = + let open Lwt_result_syntax in + List.iter (fun contract -> ignore (f contract)) contracts ; + + return_unit + +let test_encoding_binary_compat = test_contracts encoding_binary_compat + +let test_encoding_json_compat = test_contracts encoding_json_compat + +let test_compare_destination () = + let open Lwt_result_syntax in + let tz1 = !!(Destination_repr.of_b58check null_address) in + let kt1 = !!(Destination_repr.of_b58check liquidity_baking_dex) in + let scr1 = !!(Destination_repr.of_b58check sc_rollup_address) in + let epx1 = !!(Destination_repr.of_b58check zk_rollup_address) in + + assert (Destination_repr.(tz1 < kt1)) ; + assert (Destination_repr.(kt1 < scr1)) ; + assert (Destination_repr.(scr1 < epx1)) ; + + return_unit + +let tests = + [ + tztest "Json decoding compat implicit contract (null address)" `Quick + @@ test_decoding_json_compat null_address; + tztest "Json decoding compat smart contract (liquidity baking dex)" `Quick + @@ test_decoding_json_compat liquidity_baking_dex; + tztest "Binary Contract_repr to Destination_repr (null address)" `Quick + @@ test_encode_contract_decode_destination null_address; + tztest + "Binary Contract_repr to Destination_repr (liquidity baking dex)" + `Quick + @@ test_encode_contract_decode_destination liquidity_baking_dex; + tztest "Binary Destination_repr to Contract_repr (null address)" `Quick + @@ test_encode_destination_decode_contract null_address; + tztest + "Binary Destination_repr to Contract_repr (liquidity baking dex)" + `Quick + @@ test_encode_destination_decode_contract liquidity_baking_dex; + tztest + "Json encoding compatibility Contract_repr to Destination_repr with \ + dummy contracts" + `Quick + @@ test_encoding_json_compat; + tztest + "Binary encoding compatibility Contract_repr to Destination_repr with \ + dummy contracts" + `Quick + @@ test_encoding_json_compat; + tztest "Comparison of destinations" `Quick test_compare_destination; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Destination_repr.ml", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_fitness.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_fitness.ml new file mode 100644 index 000000000000..8966ffea372e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_fitness.ml @@ -0,0 +1,164 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (committee selection) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_fitness.ml + Subject: test the fitness module +*) + +open Protocol + +let level_zero = Raw_level_repr.of_int32_exn 0l + +let round_of_int32_exn i = + match Round_repr.of_int32 i with + | Ok i -> i + | Error _ -> Stdlib.failwith "Invalid round representation" + +let make_tuple (level, r_opt, r0, r1) = + let r_opt = Option.map round_of_int32_exn r_opt in + let r0 = round_of_int32_exn r0 in + let r1 = round_of_int32_exn r1 in + (level, r_opt, r0, r1) + +let test_cases = + List.map + make_tuple + [ + (3l, Some 1l, 1l, 12l); + (10l, Some 1l, 1l, 12l); + (10l, Some 4l, 2l, 6l); + (10l, Some 4l, 1l, 12l); + (9l, Some 2l, 0l, 3l); + (7l, None, 0l, 3l); + (7l, None, 1l, 3l); + (0l, None, 0l, 0l); + (12l, Some 2l, 8l, 7l); + (10l, Some 0l, 1l, 1l); + (8l, None, 1l, 0l); + (12l, Some 1l, 8l, 7l); + (8l, None, 6l, 0l); + ] + +let rec product l1 l2 = + match l1 with + | [] -> [] + | h :: tl -> List.map (fun x -> (h, x)) l2 @ product tl l2 + +let test_product_cases = product test_cases test_cases + +let tuple_to_fitness (level, locked_round, predecessor_round, round) = + Fitness_repr.create + ~level:(Raw_level_repr.of_int32_exn level) + ~locked_round + ~predecessor_round + ~round + +let tuple_to_fitness_exn tuple = + tuple_to_fitness tuple |> function + | Ok f -> f + | Error err -> + Format.kasprintf + Stdlib.failwith + "cannot create fitness from tuple: %a" + pp_print_trace + (Environment.wrap_tztrace err) + +let test_from_to_raw_fitness tuple = + let fitness = tuple_to_fitness_exn tuple in + Fitness_repr.from_raw (Fitness_repr.to_raw fitness) |> function + | Ok new_fitness -> assert (fitness = new_fitness) + | Error _x -> assert false + +let test_from_to_raw_fitness_all () = + let open Lwt_result_syntax in + List.iter test_from_to_raw_fitness test_cases ; + return_unit + +let test_locked_round () = + let open Lwt_result_wrap_syntax in + let test_bad_cases = + List.map + make_tuple + [ + (8l, Some 7l, 1l, 1l); + (9l, Some 8l, 0l, 3l); + (10l, Some 7l, 2l, 6l); + (11l, Some 5l, 5l, 1l); + (8l, Some 2l, 1l, 1l); + (9l, Some 3l, 0l, 3l); + (11l, Some 5l, 5l, 1l); + (13l, Some 2l, 1l, 1l); + (10l, Some 4l, 1l, 1l); + (8l, Some 7l, 1l, 1l); + (10l, Some 8l, 2l, 6l); + (11l, Some 9l, 5l, 1l); + (12l, Some 10l, 8l, 7l); + (13l, Some 14l, 1l, 1l); + ] + in + List.iter_es + (fun tuple -> + let@ fitness = tuple_to_fitness tuple in + match fitness with + | Error + [ + Environment.Ecoproto_error + (Fitness_repr.Locked_round_not_less_than_round _); + ] -> + return_unit + | Error err -> failwith "unexpected failure: %a" pp_print_trace err + | Ok f -> failwith "unexpected success: %a" Fitness_repr.pp f) + test_bad_cases + +let test_compare (tuple1, tuple2) = + let fitness1 = tuple_to_fitness_exn tuple1 in + let fitness2 = tuple_to_fitness_exn tuple2 in + let raw_fitness1 = Fitness_repr.to_raw fitness1 in + let raw_fitness2 = Fitness_repr.to_raw fitness2 in + let cmp_fitness = Fitness_repr.Internal_for_tests.compare fitness1 fitness2 in + let cmp_raw_fitness = Fitness.compare raw_fitness1 raw_fitness2 in + Assert.equal_int ~loc:__LOC__ cmp_fitness cmp_raw_fitness + +let test_compare_all () = List.iter_es test_compare test_product_cases + +let tests = + [ + Tztest.tztest + "from/to raw fitness is identity" + `Quick + test_from_to_raw_fitness_all; + Tztest.tztest "locked round is smaller than round" `Quick test_locked_round; + Tztest.tztest + "compare fitness = compare raw_fitness" + `Quick + test_compare_all; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("fitness", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_fixed_point.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_fixed_point.ml new file mode 100644 index 000000000000..447c3a55b81f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_fixed_point.ml @@ -0,0 +1,196 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (fixed-point decimals) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_fixed_point.ml + Subject: On fixed-point decimal numbers. +*) + +open Protocol + +exception Fixed_point_test_error of string + +let err x = Exn (Fixed_point_test_error x) + +module type Arith = sig + type t + + val zero : t + + val equal : t -> t -> bool + + val random : unit -> t + + val add : t -> t -> t + + val sub : t -> t -> t +end + +let n = Z.of_int 42 + +let n' = Z.of_int 43 + +let basic_arith name (module A : Arith) = + let open Lwt_result_syntax in + let err msg = err (Format.asprintf "%s test: %s" name msg) in + let x = A.random () in + let* () = fail_unless A.(add zero x = x) (err "zero is neutral for +") in + let x = A.random () in + let y = A.random () in + let* () = fail_unless A.(add x y = add y x) (err "addition is commutative") in + let x = A.random () in + let* () = + fail_unless + A.(sub (add zero x) x = zero) + (err "addition and subtraction cancel") + in + let x = A.random () in + let y = A.random () in + let z = A.random () in + fail_unless + A.(add x (add y z) = add (add x y) z) + (err "addition is associative") + +let arith_from_integral : (module Fixed_point_repr.Full) -> (module Arith) = + fun (module FP) -> + let module Arith = struct + type t = FP.integral + + let zero = FP.zero + + let equal = FP.equal + + let random () = FP.integral_of_int_exn (Random.int 898987) + + let add = FP.add + + let sub = FP.sub + end in + (module Arith) + +let arith_from_fp : (module Fixed_point_repr.Full) -> (module Arith) = + fun (module FP) -> + let module Arith = struct + type t = FP.fp + + let zero = FP.zero + + let equal = FP.equal + + let random () = FP.unsafe_fp (Z.of_int (Random.int 898987)) + + let add = FP.add + + let sub = FP.sub + end in + (module Arith) + +let integral_tests () = + let open Lwt_result_syntax in + let module FP = Gas_limit_repr.Arith in + (* test roundtrips *) + let* () = + fail_unless (FP.(integral_to_z (integral_exn n)) = n) (err "roundtrip > 0") + in + let* () = + fail_unless + (FP.(integral_to_z (integral_exn Z.zero)) = Z.zero) + (err "roundtrip = 0") + in + (* test ceil/floor on integral *) + let* () = + fail_unless + FP.(ceil (fp (integral_exn n)) = integral_exn n) + (err "integral;fp;ceil = integral") + in + let* () = + fail_unless + FP.(floor (fp (integral_exn n)) = integral_exn n) + (err "integral;fp;floor = integral") + in + let* () = + fail_unless + (Format.asprintf "%a" FP.pp FP.(fp (integral_exn n)) + = Format.asprintf "%a" FP.pp_integral (FP.integral_exn n)) + (err "pp_integral(integral) = pp(fp(integral))") + in + basic_arith "integral arith" (arith_from_integral (module FP)) + +let fp_nonzero () = + let open Lwt_result_syntax in + let decimals = 3 in + let module FP = Gas_limit_repr.Arith in + let prefix msg = Format.asprintf "(%d decimals) %s" decimals msg in + let err msg = err (prefix msg) in + let* () = + basic_arith (prefix "integral arith") (arith_from_integral (module FP)) + in + let* () = basic_arith (prefix "fp arith") (arith_from_fp (module FP)) in + let epsilon = FP.unsafe_fp Z.one in + let* () = + fail_unless FP.(ceil epsilon = integral_exn Z.one) (err "ceil eps = 1") + in + let* () = + fail_unless FP.(floor epsilon = integral_exn Z.zero) (err "floor eps = 1") + in + let x = Z.of_int (Random.int 980812) in + fail_unless + FP.( + ceil (add (fp (integral_exn x)) (unsafe_fp Z.one)) + = integral_exn (Z.succ x)) + (err "ceil (x + eps) = x + 1") + +let fp_pp () = + let open Lwt_result_syntax in + let module FP = Gas_limit_repr.Arith in + let prefix msg = Format.asprintf "(%d decimals) %s" 3 msg in + let err msg = err (prefix msg) in + let epsilon = FP.unsafe_fp Z.one in + let ( =:= ) x expected = Format.asprintf "%a" FP.pp x = expected in + let* () = fail_unless (epsilon =:= "0.001") (err "eps = 0.001") in + let* () = + fail_unless (FP.unsafe_fp (Z.of_int 1000) =:= "1") (err "1.000 = 1") + in + let* () = + fail_unless (FP.unsafe_fp (Z.of_int 1001) =:= "1.001") (err "1.001") + in + let* () = + fail_unless (FP.unsafe_fp (Z.of_int 10001) =:= "10.001") (err "10.001") + in + fail_unless (FP.zero =:= "0") (err "0") + +let tests = + [ + Tztest.tztest "Integral tests (3 decimals)" `Quick integral_tests; + Tztest.tztest "FP tests (3 decimals)" `Quick fp_nonzero; + Tztest.tztest "FP pp tests (3 decimals)" `Quick fp_pp; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("fixed point computation", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_full_staking_balance_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_full_staking_balance_repr.ml new file mode 100644 index 000000000000..d996c00ad343 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_full_staking_balance_repr.ml @@ -0,0 +1,125 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: protocol + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_full_staking_balance_repr.ml + Subject: test the Full_staking_balance_repr module +*) + +open Protocol +open Data_encoding + +(* We duplicate the definition of the Full_staking_balance_repr module + from Oxford to test a None case in the current encoding *) +module Full_staking_balance_repr_oxford = struct + type t = { + own_frozen : Tez_repr.t; + staked_frozen : Tez_repr.t; + delegated : Tez_repr.t; + } + + let make ~own_frozen ~staked_frozen ~delegated = + {own_frozen; staked_frozen; delegated} + + let encoding = + let open Data_encoding in + conv + (fun {own_frozen; staked_frozen; delegated} -> + (own_frozen, staked_frozen, delegated)) + (fun (own_frozen, staked_frozen, delegated) -> + {own_frozen; staked_frozen; delegated}) + (obj3 + (req "own_frozen" Tez_repr.encoding) + (req "staked_frozen" Tez_repr.encoding) + (req "delegated" Tez_repr.encoding)) +end + +let equal_full_staking_balance (a : Full_staking_balance_repr.t) + (b : Full_staking_balance_repr.t) = + let open Lwt_result_syntax in + let open Full_staking_balance_repr in + let open Full_staking_balance_repr.Internal_for_tests_and_RPCs in + let equal_tez_repr ~loc a b = + Assert.equal_int64 ~loc (Tez_repr.to_mutez a) (Tez_repr.to_mutez b) + in + let equal_cycle_repr ~loc a b = + Assert.equal_int32 ~loc (Cycle_repr.to_int32 a) (Cycle_repr.to_int32 b) + in + + let* () = equal_tez_repr ~loc:__LOC__ (own_frozen a) (own_frozen b) in + let* () = equal_tez_repr ~loc:__LOC__ (staked_frozen a) (staked_frozen b) in + let* () = + equal_tez_repr ~loc:__LOC__ (current_delegated a) (current_delegated b) + in + let* () = + equal_tez_repr + ~loc:__LOC__ + (min_delegated_in_cycle a) + (min_delegated_in_cycle b) + in + let* () = + let cycle s = + match level_of_min_delegated s with + | None -> Cycle_repr.root + | Some l -> l.cycle + in + equal_cycle_repr ~loc:__LOC__ (cycle a) (cycle b) + in + return_unit + +let equal_full_staking_balance_bytes sb_bytes + (sb_expected : Full_staking_balance_repr.t) = + let open Lwt_result_syntax in + let encoding = Full_staking_balance_repr.encoding in + let* sb = + match Binary.of_bytes encoding sb_bytes with + | Ok x -> return x + | Error e -> + failwith + "Data_encoding.Binary.read shouldn't have failed with \ + Full_staking_balance_repr.encoding: %a" + Binary.pp_read_error + e + in + equal_full_staking_balance sb sb_expected + +let test_encodings () = + let open Lwt_result_syntax in + let own_frozen = Tez_repr.(mul_exn one 1) in + let staked_frozen = Tez_repr.(mul_exn one 2) in + let delegated = Tez_repr.(mul_exn one 5) in + + (* Test a [Some] case for [added_in_p] *) + let staking_balance = + Full_staking_balance_repr.init + ~own_frozen + ~staked_frozen + ~delegated + ~current_level:Level_repr.Internal_for_tests.root + in + let encoding = Full_staking_balance_repr.encoding in + let sb_bytes = Binary.to_bytes_exn encoding staking_balance in + let* () = equal_full_staking_balance_bytes sb_bytes staking_balance in + + (* Test a [None] case for [added_in_p] *) + let staking_balance_o = + Full_staking_balance_repr_oxford.make ~own_frozen ~staked_frozen ~delegated + in + let encoding_o = Full_staking_balance_repr_oxford.encoding in + let sb_o_bytes = Binary.to_bytes_exn encoding_o staking_balance_o in + let* () = equal_full_staking_balance_bytes sb_o_bytes staking_balance in + return_unit + +let tests = + Tztest.[tztest "full staking balance - encoding" `Quick test_encodings] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("full_staking_balance", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_gas_monad.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_gas_monad.ml new file mode 100644 index 000000000000..351348b1699e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_gas_monad.ml @@ -0,0 +1,225 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Gas_monad + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_gas_monad.ml + Subject: Tests for the gas monad module +*) + +open Protocol +open Alpha_context +module GM = Gas_monad + +let ten_milligas = Gas.fp_of_milligas_int 10 + +let new_context ~limit = + let open Lwt_result_syntax in + let* b, _contract = Context.init1 () in + let+ inc = Incremental.begin_construction b in + Gas.set_limit (Incremental.alpha_ctxt inc) limit + +let assert_gas_exhaustion ~loc ctxt gas_monad = + let open Lwt_result_syntax in + match GM.run ctxt gas_monad with + | Error _ -> return_unit + | _ -> failwith "%s: expected gas-exhaustion error" loc + +let assert_equal_gas ~loc g1 g2 = + Assert.equal ~loc Gas.Arith.equal "Compare gas" Gas.Arith.pp g1 g2 + +let assert_inner_errors ~loc ctxt gas_monad ~errors ~remaining_gas = + let open Lwt_result_syntax in + match GM.run ctxt gas_monad with + | Ok (Error e, ctxt) -> + let* () = + Assert.assert_equal_list + ~loc + ( = ) + "Inner error" + Format.pp_print_string + e + errors + in + assert_equal_gas + ~loc + (Gas.remaining_operation_gas ctxt) + (Gas.fp_of_milligas_int remaining_gas) + | _ -> failwith "%s: expected inner error" loc + +let assert_success ~loc ctxt gas_monad ~result ~remaining_gas = + match GM.run ctxt gas_monad with + | Ok (Ok x, ctxt) -> + let open Lwt_result_syntax in + let* () = Assert.equal_int ~loc x result in + assert_equal_gas + ~loc + (Gas.remaining_operation_gas ctxt) + (Gas.fp_of_milligas_int remaining_gas) + | _ -> failwith "%s: expected successful result `%d' but got error" loc result + +let with_context f ~limit = + let open Lwt_result_syntax in + let* ctxt = new_context ~limit in + f ctxt + +(** Test that consuming more gas than remaining results in a gas-exhaustion + error. *) +let test_gas_exhaustion () = + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + let* x = GM.return 1 in + let* () = GM.consume_gas (Saturation_repr.safe_int 10) in + let* y = GM.return 2 in + GM.return (x + y) + in + assert_gas_exhaustion ~loc:__LOC__ ctxt gas_monad + +(** Test that consuming more gas than remaining results in a gas-exhaustion + error before an inner error is produced. *) +let test_gas_exhaustion_before_error () = + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + let* x = GM.return 1 in + let* () = GM.consume_gas (Saturation_repr.safe_int 10) in + let* () = GM.of_result (Result_syntax.tzfail "Oh no") in + let* y = GM.return 2 in + GM.return (x + y) + in + assert_gas_exhaustion ~loc:__LOC__ ctxt gas_monad + +(** Test that consuming all remaining gas is feasible. *) +let test_successful_with_remaining_gas () = + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* x = GM.return 1 in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + let* y = GM.return 2 in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + GM.return (x + y) + in + assert_success ~loc:__LOC__ ctxt gas_monad ~result:3 ~remaining_gas:0 + +(** Test that the context has the expected amount of spare gas after the + computation. *) +let test_successful_with_spare_gas () = + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* x = GM.return 1 in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + let* y = GM.return 2 in + let* () = GM.consume_gas (Saturation_repr.safe_int 3) in + GM.return (x + y) + in + assert_success ~loc:__LOC__ ctxt gas_monad ~result:3 ~remaining_gas:2 + +(** Test that an inner error is produced rather than a gas-exhaustion error. *) +let test_inner_error () = + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* x = GM.return 1 in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + let* () = GM.of_result (Result_syntax.tzfail "Oh no") in + let* y = GM.return 2 in + let* () = GM.consume_gas (Saturation_repr.safe_int 10) in + GM.return (x + y) + in + assert_inner_errors + ~loc:__LOC__ + ctxt + gas_monad + ~errors:["Oh no"] + ~remaining_gas:5 + +(* Test that no gas-exhaustion error is produced and that no gas is consumed + when run in unlimited mode. +*) +let test_unlimited () = + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* x = GM.return 1 in + let* () = GM.consume_gas (Saturation_repr.safe_int 5) in + let* y = GM.return 2 in + let* () = GM.consume_gas (Saturation_repr.safe_int 100) in + let* () = GM.consume_gas (Saturation_repr.safe_int 3) in + GM.return (x + y) + in + assert_success + ~loc:__LOC__ + (Gas.set_unlimited ctxt) + gas_monad + ~result:3 + ~remaining_gas:10 + +let test_syntax_module () = + let open Lwt_result_syntax in + with_context ~limit:ten_milligas @@ fun ctxt -> + let gas_monad = + let open Gas_monad.Syntax in + let* none = return_none in + let* nil = return_nil in + let* t = return_true in + let* f = return_false in + let*? one = Ok 1 in + let+ two = return 2 in + (none, nil, t, f, one, two) + in + match GM.run ctxt gas_monad with + | Ok (Ok (None, [], true, false, 1, 2), _ctxt) -> return_unit + | _ -> failwith "Expected `Ok (None, [], true, false, 1, 2)`" + +let tests = + [ + Tztest.tztest "exhaustion" `Quick test_gas_exhaustion; + Tztest.tztest + "exhaustion before error" + `Quick + test_gas_exhaustion_before_error; + Tztest.tztest + "successful result with remaining gas" + `Quick + test_successful_with_remaining_gas; + Tztest.tztest + "successful result with spare gas" + `Quick + test_successful_with_spare_gas; + Tztest.tztest "inner error" `Quick test_inner_error; + Tztest.tztest "unlimited" `Quick test_unlimited; + Tztest.tztest "syntax module" `Quick test_syntax_module; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("gas monad", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_global_constants_storage.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_global_constants_storage.ml new file mode 100644 index 000000000000..3ba36ea8d6a3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_global_constants_storage.ml @@ -0,0 +1,431 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Global table of constants + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_global_constants_storage.ml + Dependencies: contract_hash.ml + Subject: Test the global table of constants +*) + +open Protocol +open Alpha_context +open Tztest +open Micheline +open QCheck2 +open Qcheck2_helpers +open Michelson_v1_primitives +open Michelson_v1_printer +open Test_global_constants + +(** [get] on a nonexistent global constant + returns an error. *) +let test_get_on_nonexistent_fails = + let open Lwt_result_wrap_syntax in + tztest_qcheck2 + ~name:"get on a nonexistent global constants fails" + (Gen.pair + (Generators.context_gen ()) + (Generators.canonical_without_constant_gen ())) + (fun (context, expr) -> + let*?@ hash = expr_to_hash expr in + let*!@ result = Global_constants_storage.get context hash in + assert_proto_error_id __LOC__ "Nonexistent_global" result) + +(** If registering an expression yields a hash [h] and context [c], + then [get c h] should yield the original expression. *) +let test_get_always_returns_registered_expr = + let open Lwt_result_wrap_syntax in + tztest_qcheck2 + ~name:"get always returned the registered constant" + (Gen.pair + (Generators.context_gen ()) + (Generators.canonical_without_constant_gen ())) + (fun (context, expr) -> + let*@ context, hash, _cost = + Global_constants_storage.register context expr + in + let+@ _context, actual_expr = Global_constants_storage.get context hash in + qcheck_eq ~pp:print_expr actual_expr expr) + +(* Attempts to register an expression that contains references + to expressions not already registered should fail. *) +let test_register_fails_with_unregistered_references = + let open Lwt_result_wrap_syntax in + tztest "register: fails with unregistered references" `Quick (fun () -> + let prim_with_constant = + Expr.from_string + {| Pair 1 + (constant "exprubuoE4JFvkSpxsZJXAvhTdozCNZpgfCnyg6WsiAYX79q4z3bXu")|} + in + let* context = create_context () in + let*!@ result = + Global_constants_storage.register context prim_with_constant + in + assert_proto_error_id __LOC__ "Nonexistent_global" result) + +(** Same test as [test_register_fails_with_unregistered_references] + but with random values. *) +let test_register_fails_with_unregistered_references_pbt = + let open Lwt_result_wrap_syntax in + tztest_qcheck2 + ~name:"register: fails with unregistered references pbt" + (Gen.pair + (Generators.context_gen ()) + (Generators.canonical_with_constant_gen ())) + (fun (context, (_, expr, _)) -> + assume_expr_not_too_large expr ; + let*!@ result = Global_constants_storage.register context expr in + assert_proto_error_id __LOC__ "Nonexistent_global" result) + +let rec grow n node = + match n with n when n <= 0 -> node | n -> grow (n - 1) (Seq ((), [node])) + +(* Any expression with a depth that exceeds + [Global_constants_storage.max_allowed_global_constant_depth] + should be rejected. *) +let test_register_fails_if_too_deep = + let open Lwt_result_wrap_syntax in + tztest "register: fails if expression too deep" `Quick (fun () -> + let vdeep_expr = + grow + (Constants_repr.max_allowed_global_constant_depth + 1) + (Int ((), Z.of_int 1)) + |> Micheline.strip_locations + in + let* context = create_context () in + let*!@ result = Global_constants_storage.register context vdeep_expr in + assert_proto_error_id __LOC__ "Expression_too_deep" result) + +(** [expand] on an expression containing a nonexistent global + constant returns an error. *) +let test_expand_nonexistent_fails = + let open Lwt_result_wrap_syntax in + tztest_qcheck2 + ~name: + "expand on an expression containing a nonexistent global constant fails" + (Gen.pair + (Generators.context_gen ()) + (Generators.canonical_with_constant_gen ())) + @@ fun (context, (_, expr, _)) -> + assume_expr_not_too_large expr ; + let*!@ result = Global_constants_storage.expand context expr in + assert_proto_error_id __LOC__ "Nonexistent_global" result + +(** Expanding an expression without constants should yield the same expression. *) +let test_expand_no_constants = + let open Lwt_result_wrap_syntax in + tztest "expand: no constants case" `Quick (fun () -> + let* context = create_context () in + let expected = Expr.from_string "Pair 1 (Pair 2 3)" in + let*@ (_ : t), result_expr = + Global_constants_storage.expand context expected + in + assert_expr_equal __LOC__ expected result_expr) + +(** Similar to [test_expand_no_constants], but random. *) +let test_register_and_expand_orthogonal = + let open Lwt_result_wrap_syntax in + tztest_qcheck2 + ~name:"register and expand are orthogonal" + (Gen.triple + (Generators.context_gen ()) + (Generators.canonical_without_constant_gen ()) + (Generators.canonical_without_constant_gen ())) + (fun (context, expr1, expr2) -> + assume_expr_not_too_large expr1 ; + assume_expr_not_too_large expr2 ; + let open Michelson_v1_printer in + let*@ context, _hash, _cost = + Global_constants_storage.register context expr1 + in + let+@ (_ : t), expr2_result = + Global_constants_storage.expand context expr2 + in + qcheck_eq ~pp:print_expr expr2 expr2_result) + +(** Expanding should expand constants in the given + expression, then expand any new constants, etc. + recursively until no constants remain. *) +let test_expand_deep_constants = + let open Lwt_result_wrap_syntax in + tztest "expand: deep constants" `Quick (fun () -> + (* Should hold for any n, but this test is very slow, + hence we don't do QCheck2. *) + let n = 1000 in + let expr1 = Expr.from_string "{}" in + let* context = create_context () in + let rec n_constants_deep context node n = + let*@ context, hash, (_ : Z.t) = + Global_constants_storage.register context (strip_locations node) + in + if n <= 1 then return (context, node, hash) + else + let new_node = + Seq + ( -1, + [ + Prim + ( -1, + H_constant, + [String (-1, Script_expr_hash.to_b58check hash)], + [] ); + ] ) + in + n_constants_deep context new_node (n - 1) + in + let* context, _, hash = n_constants_deep context (root expr1) n in + let deep_expr = + Expr.from_string + @@ Format.sprintf + "{constant \"%s\"; CDR; NIL operation; PAIR}" + (Script_expr_hash.to_b58check hash) + in + let*@ (_ : t), result = + Global_constants_storage.expand context deep_expr + in + let seq_n_deep n = + let rec advance n acc = + match n with 0 -> acc | _ -> advance (n - 1) (Seq (-1, [acc])) + in + advance (n - 1) (Seq (-1, [])) + in + let seq_str = Expr.to_string @@ strip_locations @@ seq_n_deep n in + let expected = + Expr.from_string + @@ Format.sprintf "{ %s; CDR; NIL operation; PAIR; }" + @@ seq_str + in + assert_expr_equal __LOC__ expected result) + +(** The [constant] prim is permitted only to have a + single string argument, representing a valid + Script_repr.expr hash, with no annotations *) +let test_expand_reject_ill_formed = + let open Lwt_result_wrap_syntax in + tztest "expand: ill formed constants are rejected" `Quick (fun () -> + (* first, create a context, register a constant and check + that its expansion works well. *) + let* context = create_context () in + let some_expr = Expr.from_string "0" in + let*@ context, hash, (_ : Z.t) = + Global_constants_storage.register context some_expr + in + let hash = Script_expr_hash.to_b58check hash in + (* check that expansion of the registered constant works *) + let*@ context, result = + Global_constants_storage.expand + context + (Expr.from_string @@ Format.sprintf "constant \"%s\"" hash) + in + let* () = assert_expr_equal __LOC__ some_expr result in + let test expr = + let expected = Expr.from_string expr in + let*!@ result = Global_constants_storage.expand context expected in + assert_proto_error_id __LOC__ "Badly_formed_constant_expression" result + in + (* constant with an argument other than String fails *) + let* () = test "constant 9" in + (* same as above but nested *) + let* () = test "Pair 1 (constant (Pair 2 3))" in + (* constant with bad hash fails *) + let* () = test "constant \"foobar\"" in + (* constant with type annot *) + let* () = test @@ Format.sprintf "(constant :a \"%s\")" hash in + (* constant with var annot *) + let* () = test @@ Format.sprintf "(constant @a \"%s\")" hash in + (* constant with field annot *) + test @@ Format.sprintf "(constant %%a \"%s\")" hash) + +(** The [constant] prim is not permitted to have a + [constant] child argument. + + The idea is to have expansion like this: + + constant (constant ) -> constant hash -> value + + But we want to forbid this as a badly formed constant. + Asserting that every constant must be a *static* string + makes it easier to see which constants are used where, because + you can just traverse the AST (no expansion necessary). *) +let test_reject_use_of_inner_constant = + let open Lwt_result_wrap_syntax in + tztest + "expand: use of 'constant (constant ...)' is rejected" + `Quick + (fun () -> + (* First, create a context, register a constant and check + that its expansion works well. *) + let* context = create_context () in + let some_expr = Expr.from_string "0" in + let*@ context, hash, _ = + Global_constants_storage.register context some_expr + in + let hash = Script_expr_hash.to_b58check hash in + (* Next, register the hash itself as a constant. *) + let*@ context, hash, (_ : Z.t) = + Global_constants_storage.register + context + (strip_locations (Micheline.String (-1, hash))) + in + let hash = Script_expr_hash.to_b58check hash in + let*!@ result = + Global_constants_storage.expand + context + (Expr.from_string + @@ Format.sprintf "{ constant (constant \"%s\") } " hash) + in + assert_proto_error_id __LOC__ "Badly_formed_constant_expression" result) + +(** [test_expand] accepts an expression [stored] to be + registered in the store, an expression [expr] that includes a template slot for + the hash of [stored], and an [expected] expression, and generates a test that + asserts the value of [expr] after expansion matches [expected]. *) +let make_expand_test ~stored ~expr ~expected () = + let open Lwt_result_wrap_syntax in + let* context = create_context () in + let stored_expr = Expr.from_string stored in + let*@ context, hash, _ = + Global_constants_storage.register context stored_expr + in + let expected = Expr.from_string expected in + let expr_with_constant = + Format.sprintf expr (Script_expr_hash.to_b58check hash) |> Expr.from_string + in + let*@ (_ : t), result_expr = + Global_constants_storage.expand context expr_with_constant + in + assert_expr_equal __LOC__ expected result_expr + +let test_expand_data_example = + tztest + "expand: data" + `Quick + (make_expand_test + ~stored:"3" + ~expr:"Pair 1 (Pair 2 (constant \"%s\"))" + ~expected:"Pair 1 (Pair 2 3)") + +let test_expand_types_example = + tztest + "expand: types" + `Quick + (make_expand_test + ~stored:"big_map string string" + ~expr:"PUSH (constant \"%s\") {}" + ~expected:"PUSH (big_map string string) {}") + +let test_expand_instr_example = + tztest + "expand: instr" + `Quick + (make_expand_test + ~stored:"PUSH int 3" + ~expr:"{ DROP; constant \"%s\"; DROP }" + ~expected:"{ DROP; PUSH int 3 ; DROP }") + +(** For any expression [e], when replacing any subexpression + [e'] with a constant hash and registering [e'], calling + [expand] on the new expression yields the + original expression [e]*) +let test_expand_pbt = + let open Lwt_result_wrap_syntax in + let open Michelson_v1_printer in + tztest_qcheck2 + ~name:"expand: random" + (Gen.pair + (Generators.context_gen ()) + (Generators.canonical_with_constant_gen ())) + (fun (context, (full_expr, expr_with_constant, sub_expr)) -> + assume_expr_not_too_large full_expr ; + assume_expr_not_too_large expr_with_constant ; + assume_expr_not_too_large sub_expr ; + let*@ context, (_ : Script_expr_hash.t), (_ : Z.t) = + Global_constants_storage.register context sub_expr + in + let+@ (_ : t), result_expr = + Global_constants_storage.expand context expr_with_constant + in + qcheck_eq ~pp:print_expr full_expr result_expr) + +let test_expand_is_idempotent = + let open Lwt_result_wrap_syntax in + tztest_qcheck2 + ~name:"expand is idempotent" + (Gen.pair + (Generators.context_gen ()) + (Generators.canonical_with_constant_gen ())) + (fun (context, (full_expr, expr_with_constant, sub_expr)) -> + assume_expr_not_too_large full_expr ; + let*@ context, _, _ = + Global_constants_storage.register context sub_expr + in + let*@ context, result1 = + Global_constants_storage.expand context expr_with_constant + in + let+@ (_ : t), result2 = + Global_constants_storage.expand context full_expr + in + qcheck_eq ~pp:print_expr result1 result2) + +(** [bottom_up_fold_cps] does not stack overflow even when + given large values. *) +let test_fold_does_not_stack_overflow = + let open Lwt_result_syntax in + tztest "bottom_up_fold_cps: does not stack overflow" `Quick (fun () -> + let node = grow 1_000_000 @@ Int ((), Z.zero) in + return @@ ignore + @@ Global_constants_storage.Internal_for_tests.bottom_up_fold_cps + () + node + (fun _ _ -> ()) + (fun _ node k -> k () node)) + +let tests = + [ + test_get_on_nonexistent_fails; + test_get_always_returns_registered_expr; + test_register_fails_with_unregistered_references; + test_register_fails_with_unregistered_references_pbt; + test_register_fails_if_too_deep; + test_expand_nonexistent_fails; + test_expand_no_constants; + test_register_and_expand_orthogonal; + test_expand_deep_constants; + test_expand_reject_ill_formed; + test_reject_use_of_inner_constant; + test_expand_data_example; + test_expand_types_example; + test_expand_instr_example; + test_expand_pbt; + test_expand_is_idempotent; + test_fold_does_not_stack_overflow; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Global constants storage", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_level_module.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_level_module.ml new file mode 100644 index 000000000000..5ef0e74dd36e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_level_module.ml @@ -0,0 +1,286 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (baking) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_level_module.ml + Subject: some functions in the Level module +*) + +open Protocol + +let test_create_cycle_eras () = + let open Lwt_result_wrap_syntax in + let@ empty_cycle_eras = Level_repr.create_cycle_eras [] in + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + empty_cycle_eras + "Invalid cycle eras" + in + let@ increasing_first_levels = + [ + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn 1l; + first_cycle = Cycle_repr.succ Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + { + first_level = Raw_level_repr.of_int32_exn 9l; + first_cycle = Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + ] + |> Level_repr.create_cycle_eras + in + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + increasing_first_levels + "Invalid cycle eras" + in + let@ increasing_first_cycles = + [ + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn 9l; + first_cycle = Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + { + first_level = Raw_level_repr.of_int32_exn 1l; + first_cycle = Cycle_repr.succ Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + ] + |> Level_repr.create_cycle_eras + in + Assert.proto_error_with_info + ~loc:__LOC__ + increasing_first_cycles + "Invalid cycle eras" + +let test_case_1 = + ( [ + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn 1l; + first_cycle = Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + ], + [ + (1, (1, 0, 0, 0, false)); + (2, (2, 1, 0, 1, true)); + (3, (3, 2, 0, 2, false)); + (8, (8, 7, 0, 7, true)); + (9, (9, 8, 1, 0, false)); + (16, (16, 15, 1, 7, true)); + (17, (17, 16, 2, 0, false)); + (64, (64, 63, 7, 7, true)); + (65, (65, 64, 8, 0, false)); + ] ) + +let test_case_2 = + ( List.rev + [ + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn 1l; + first_cycle = Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + { + first_level = Raw_level_repr.of_int32_exn 17l; + first_cycle = Cycle_repr.of_int32_exn 2l; + blocks_per_cycle = 16l; + blocks_per_commitment = 4l; + }; + ], + [ + (1, (1, 0, 0, 0, false)); + (2, (2, 1, 0, 1, true)); + (3, (3, 2, 0, 2, false)); + (8, (8, 7, 0, 7, true)); + (9, (9, 8, 1, 0, false)); + (16, (16, 15, 1, 7, true)); + (17, (17, 16, 2, 0, false)); + (32, (32, 31, 2, 15, true)); + (33, (33, 32, 3, 0, false)); + (64, (64, 63, 4, 15, true)); + (65, (65, 64, 5, 0, false)); + ] ) + +let test_case_3 = + ( List.rev + [ + Level_repr. + { + first_level = Raw_level_repr.of_int32_exn 1l; + first_cycle = Cycle_repr.root; + blocks_per_cycle = 8l; + blocks_per_commitment = 2l; + }; + { + first_level = Raw_level_repr.of_int32_exn 17l; + first_cycle = Cycle_repr.of_int32_exn 2l; + blocks_per_cycle = 16l; + blocks_per_commitment = 4l; + }; + { + first_level = Raw_level_repr.of_int32_exn 49l; + first_cycle = Cycle_repr.of_int32_exn 4l; + blocks_per_cycle = 6l; + blocks_per_commitment = 3l; + }; + ], + [ + (1, (1, 0, 0, 0, false)); + (2, (2, 1, 0, 1, true)); + (3, (3, 2, 0, 2, false)); + (8, (8, 7, 0, 7, true)); + (9, (9, 8, 1, 0, false)); + (16, (16, 15, 1, 7, true)); + (17, (17, 16, 2, 0, false)); + (32, (32, 31, 2, 15, true)); + (33, (33, 32, 3, 0, false)); + (48, (48, 47, 3, 15, true)); + (49, (49, 48, 4, 0, false)); + (64, (64, 63, 6, 3, false)); + (65, (65, 64, 6, 4, false)); + (66, (66, 65, 6, 5, true)); + (67, (67, 66, 7, 0, false)); + ] ) + +let test_level_from_raw () = + let open Lwt_result_wrap_syntax in + List.iter_es + (fun (cycle_eras, test_cases) -> + List.iter_es + (fun ( input_level, + ( level, + level_position, + cycle, + cycle_position, + expected_commitment ) ) -> + let raw_level = + Raw_level_repr.of_int32_exn (Int32.of_int input_level) + in + let*?@ cycle_eras = Level_repr.create_cycle_eras cycle_eras in + let level_from_raw = + Protocol.Level_repr.level_from_raw ~cycle_eras raw_level + in + let* () = + Assert.equal_int + ~loc:__LOC__ + (Int32.to_int (Raw_level_repr.to_int32 level_from_raw.level)) + level + in + let* () = + Assert.equal_int + ~loc:__LOC__ + (Int32.to_int level_from_raw.level_position) + level_position + in + let* () = + Assert.equal_int + ~loc:__LOC__ + (Int32.to_int (Cycle_repr.to_int32 level_from_raw.cycle)) + cycle + in + let* () = + Assert.equal_int + ~loc:__LOC__ + (Int32.to_int level_from_raw.cycle_position) + cycle_position + in + let* () = + Assert.equal_bool + ~loc:__LOC__ + level_from_raw.expected_commitment + expected_commitment + in + let offset = + Int32.neg (Int32.add Int32.one (Int32.of_int input_level)) + in + let@ res = + Level_repr.level_from_raw_with_offset ~cycle_eras ~offset raw_level + in + Assert.proto_error ~loc:__LOC__ res (fun err -> + let error_info = + Error_monad.find_info_of_error (Environment.wrap_tzerror err) + in + error_info.title = "Negative sum of level and offset")) + test_cases) + [test_case_1; test_case_2; test_case_3] + +let test_first_level_in_cycle () = + let open Lwt_result_wrap_syntax in + let cycle_eras = fst test_case_3 in + let test_cases = + (* cycle, level *) + [ + (0l, 1); + (1l, 9); + (2l, 17); + (3l, 33); + (4l, 49); + (5l, 55); + (6l, 61); + (7l, 67); + ] + in + let f (input_cycle, level) = + let*?@ cycle_eras = Level_repr.create_cycle_eras cycle_eras in + let input_cycle = Cycle_repr.of_int32_exn input_cycle in + let level_res = + Level_repr.first_level_in_cycle_from_eras ~cycle_eras input_cycle + in + Assert.equal_int + ~loc:__LOC__ + (Int32.to_int (Raw_level_repr.to_int32 level_res.level)) + level + in + List.iter_es f test_cases + +let tests = + [ + Tztest.tztest "create_cycle_eras" `Quick test_create_cycle_eras; + Tztest.tztest "level_from_raw" `Quick test_level_from_raw; + Tztest.tztest "first_level_in_cycle" `Quick test_first_level_in_cycle; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("level module", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_liquidity_baking_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_liquidity_baking_repr.ml new file mode 100644 index 000000000000..305bbed7e35a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_liquidity_baking_repr.ml @@ -0,0 +1,282 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Liquidity_baking_repr module + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_liquidity_baking_repr.ml + Subject: Tests for the Liquidity_baking_repr module +*) + +open Protocol +module Votes_EMA = Per_block_votes_repr.Liquidity_baking_toggle_EMA + +let ema_of_int32 ema = Lwt_result_wrap_syntax.wrap @@ Votes_EMA.of_int32 ema + +let ema_to_int32 = Votes_EMA.to_int32 + +let compute_new_ema ~per_block_vote ema = + Per_block_votes_repr.compute_new_liquidity_baking_ema ~per_block_vote ema + |> ema_to_int32 + +(* Folds compute_new_ema on a list of votes *) +let compute_new_ema_n per_block_votes initial_ema = + List.fold_left + (fun ema per_block_vote -> + Per_block_votes_repr.compute_new_liquidity_baking_ema ~per_block_vote ema) + initial_ema + per_block_votes + |> ema_to_int32 + +let ema_range = + [ + 0l; + 1l; + 10l; + 100l; + 1000l; + 10_000l; + 100_000l; + 1_000_000l; + 10_000_000l; + 100_000_000l; + 200_000_000l; + 300_000_000l; + 400_000_000l; + 500_000_000l; + 600_000_000l; + 760_000_000l; + 800_000_000l; + 900_000_000l; + 1_000_000_000l; + 1_100_000_000l; + 1_200_000_000l; + 1_300_000_000l; + 1_400_000_000l; + 1_500_000_000l; + 1_600_000_000l; + 1_700_000_000l; + 1_800_000_000l; + 1_900_000_000l; + 1_990_000_000l; + 1_999_000_000l; + 1_999_900_000l; + 1_999_990_000l; + 1_999_999_000l; + 1_999_999_900l; + 1_999_999_990l; + 1_999_999_999l; + 2_000_000_000l; + ] + +(* Test that new_ema = old_ema when voting Pass. *) +let test_ema_pass () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.equal_int32 + ~loc:__LOC__ + (compute_new_ema ~per_block_vote:Per_block_vote_pass ema) + old_ema) + ema_range + +(* Test that new_ema is still between 0 and 2,000,000,000 after an Off vote. *) +let test_ema_in_bound_off () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + let new_ema = compute_new_ema ~per_block_vote:Per_block_vote_off ema in + let* () = Assert.leq_int32 ~loc:__LOC__ 0l new_ema in + Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) + ema_range + +(* Test that new_ema > old_ema when voting Off, except if old_ema is + already very close to the upper bound. *) +let test_ema_increases_off () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.lt_int32 + ~loc:__LOC__ + old_ema + (compute_new_ema ~per_block_vote:Per_block_vote_off ema)) + (List.filter (fun ema -> Compare.Int32.(ema < 1_999_999_000l)) ema_range) + +(* Test that the increase in EMA caused by an Off vote is bounded by 1,000,000 *) +let test_ema_increases_off_bound () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.leq_int32 + ~loc:__LOC__ + (Int32.sub + (compute_new_ema ~per_block_vote:Per_block_vote_off ema) + old_ema) + 1_000_000l) + ema_range + +(* Test that new_ema is still between 0 and 2,000,000,000 after an Off vote. *) +let test_ema_in_bound_on () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + let new_ema = compute_new_ema ~per_block_vote:Per_block_vote_on ema in + let* () = Assert.leq_int32 ~loc:__LOC__ 0l new_ema in + Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) + ema_range + +(* Test that new_ema < old_ema when voting On, except if old_ema is + already very close to the lower bound. *) +let test_ema_decreases_on () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.lt_int32 + ~loc:__LOC__ + (compute_new_ema ~per_block_vote:Per_block_vote_on ema) + old_ema) + (List.filter (fun ema -> Compare.Int32.(ema > 1000l)) ema_range) + +(* Test that the decrease in EMA caused by an On vote is bounded by 1,000,000 *) +let test_ema_decreases_on_bound () = + let open Lwt_result_syntax in + List.iter_es + (fun old_ema -> + let* ema = ema_of_int32 old_ema in + Assert.leq_int32 + ~loc:__LOC__ + (Int32.sub + (compute_new_ema ~per_block_vote:Per_block_vote_on ema) + old_ema) + 1_000_000l) + ema_range + +(* Test that 1385 Off votes are needed to reach the threshold from 0. *) +let test_ema_many_off () = + let open Lwt_result_syntax in + let open Per_block_votes_repr in + let* initial_ema = ema_of_int32 0l in + let* () = + Assert.leq_int32 + ~loc:__LOC__ + (compute_new_ema_n + (Stdlib.List.init 1385 (fun _ -> Per_block_vote_off)) + initial_ema) + 1_000_000_000l + in + Assert.leq_int32 + ~loc:__LOC__ + 1_000_000_000l + (compute_new_ema_n + (Stdlib.List.init 1386 (fun _ -> Per_block_vote_off)) + initial_ema) + +(* Test that 1385 On votes are needed to reach the threshold from the max value of the EMA (2,000,000,000). *) +let test_ema_many_on () = + let open Lwt_result_syntax in + let open Per_block_votes_repr in + let* initial_ema = ema_of_int32 2_000_000_000l in + let* () = + Assert.leq_int32 + ~loc:__LOC__ + 1_000_000_000l + (compute_new_ema_n + (Stdlib.List.init 1385 (fun _ -> Per_block_vote_on)) + initial_ema) + in + Assert.leq_int32 + ~loc:__LOC__ + (compute_new_ema_n + (Stdlib.List.init 1386 (fun _ -> Per_block_vote_on)) + initial_ema) + 1_000_000_000l + +(* Test that the EMA update function is symmetric: + from two dual values of the EMA (that is, two values x and y such that + x + y = 2,000,000,000), voting On on the first one decreases it by as + much than voting Off on the second one increases it. +*) +let test_ema_symmetry () = + let open Lwt_result_syntax in + List.iter_es + (fun ema -> + let opposite_ema = Int32.(sub 2_000_000_000l ema) in + let* ema = ema_of_int32 ema in + let* opposite_ema = ema_of_int32 opposite_ema in + let new_ema = compute_new_ema ~per_block_vote:Per_block_vote_on ema in + let new_opposite_ema = + compute_new_ema ~per_block_vote:Per_block_vote_off opposite_ema + in + Assert.equal_int32 + ~loc:__LOC__ + Int32.(add new_ema new_opposite_ema) + 2_000_000_000l) + ema_range + +let tests = + [ + Tztest.tztest "EMA does not change when vote is Pass" `Quick test_ema_pass; + Tztest.tztest + "EMA remains in bounds when vote is Off" + `Quick + test_ema_in_bound_off; + Tztest.tztest "EMA increases when vote is Off" `Quick test_ema_increases_off; + Tztest.tztest + "EMA does not increase too much when vote is Off" + `Quick + test_ema_increases_off_bound; + Tztest.tztest + "EMA remains in bounds when vote is On" + `Quick + test_ema_in_bound_on; + Tztest.tztest "EMA decreases when vote is On" `Quick test_ema_decreases_on; + Tztest.tztest + "EMA does not decrease too much when vote is On" + `Quick + test_ema_decreases_on_bound; + Tztest.tztest + "EMA goes from 0 to one billion in 1386 Off votes" + `Quick + test_ema_many_off; + Tztest.tztest + "EMA goes from two billions to one billion in 1386 On votes" + `Quick + test_ema_many_on; + Tztest.tztest + "voting On and Off have symmetric effects on the EMA" + `Quick + test_ema_symmetry; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("liquidity baking", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_local_contexts.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_local_contexts.ml new file mode 100644 index 000000000000..e73d1ad1c5d8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_local_contexts.ml @@ -0,0 +1,144 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 proof ninja, Inc Some x | _ -> None + + type 'a ipath = 'a * t + + let args = + Storage_description.One + { + rpc_arg = Environment.RPC_arg.string; + encoding = Data_encoding.string; + compare; + } +end + +module Indexed_context = Make_indexed_subcontext (Sub) (Index) + +module Value : Storage_sigs.VALUE with type t = bytes = struct + type t = bytes + + let encoding = Data_encoding.bytes +end + +module C = + Indexed_context.Make_map + (Registered) + (struct + let name = ["name"] + end) + (Value) + +let eq_context ctxt1 ctxt2 = + let open Lwt_result_wrap_syntax in + let hash ctxt = + let+@ root = Raw_context.get_tree ctxt [] in + Raw_context.Tree.hash root + in + let* x = hash ctxt1 in + let* y = hash ctxt2 in + Assert.equal + ~loc:__LOC__ + Context_hash.equal + "check context" + Context_hash.pp + x + y + +let write_with_local ctxt local_dir f = + let open Lwt_result_syntax in + let+ ctxt, () = + Indexed_context.with_local_context ctxt local_dir (fun local -> + let+ local = f local in + (local, ())) + in + ctxt + +let test_local_remove_existing () = + let open Lwt_result_wrap_syntax in + let* ctxt = create () in + let subdir = "foo" in + let value = Bytes.of_string "ABCDE" in + (* init *) + let*@ ctxt1 = + write_with_local ctxt subdir (fun local -> C.Local.init local value) + in + let*@ ctxt2 = C.init ctxt subdir value in + let* () = eq_context ctxt1 ctxt2 in + let ctxt = ctxt2 in + (* remove_existing *) + let*@ ctxt1 = write_with_local ctxt subdir C.Local.remove_existing in + let*@ ctxt2 = C.remove_existing ctxt subdir in + eq_context ctxt1 ctxt2 + +let tests = + [ + Tztest.tztest + "Local.remove_existing: check whether local access has the same behavior" + `Quick + test_local_remove_existing; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("local contexts", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_merkle_list.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_merkle_list.ml new file mode 100644 index 000000000000..329199dd506d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_merkle_list.ml @@ -0,0 +1,261 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Merkle list) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_merkle_list.ml + Subject: test the ad-hoc merkle tree structure implemented to encode lists +*) + +open Merkle_list_helper + +let assert_invalid_pos : 'a Environment.Error_monad.tzresult -> _ = function + | Error err -> + let expected_error_msg msg = "Error:\n " ^ msg ^ "\n" in + let actual_error_msg : string = + Format.asprintf "%a" Environment.Error_monad.pp_trace err + in + Log.debug "%s\n" actual_error_msg ; + assert ( + expected_error_msg "Merkle_list_invalid_position" = actual_error_msg) + | _ -> assert false + +(* Check that the result of [compute] is the expected hash *) +let test_compute () = + let open Error_monad.Result_syntax in + let elements = + Stdlib.List.init 5 (fun i -> Bytes.of_string (Int.to_string i)) + in + let element_hashes = List.map (fun e -> Hash.hash_bytes [e]) elements in + let el_hashes_a = Array.of_list element_hashes in + let h01 = hash2 el_hashes_a.(0) el_hashes_a.(1) in + let h23 = hash2 el_hashes_a.(2) el_hashes_a.(3) in + let h4e = hash2 el_hashes_a.(4) empty in + let h03 = hash2 h01 h23 in + let h4ee = hash2 h4e empty in + let expected_root = hash2 h03 h4ee in + assert (Hash.equal (compute elements) expected_root) ; + return_unit + +(* Compare the root of a tree constructed by snoc'ing to the value + given by compute and the values of the leaves *) +let test_snoc () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + + let t = List.fold_left snoc_tr nil elements in + let element_hashes = List.map (fun e -> Hash.hash_bytes [e]) elements in + + assert (Hash.equal (compute elements) (root t)) ; + assert (element_hashes = Internal_for_tests.to_list t) ; + return_unit + +(* Compare the result of the two versions of snoc *) +let test_snoc_non_tr () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let t1 = List.fold_left snoc_tr nil elements in + let t2 = List.fold_left snoc nil elements in + assert (Internal_for_tests.equal t1 t2) ; + return_unit + +(* Check that the path computed is the expected one *) +let test_compute_path () = + let open Error_monad.Result_syntax in + let elements = + Stdlib.List.init 5 (fun i -> Bytes.of_string (Int.to_string i)) + in + let t = List.fold_left snoc_tr nil elements in + + let element_hashes = List.map (fun e -> Hash.hash_bytes [e]) elements in + let el_hashes_a = Array.of_list element_hashes in + let h23 = hash2 el_hashes_a.(2) el_hashes_a.(3) in + let h4e = hash2 el_hashes_a.(4) empty in + let h4ee = hash2 h4e empty in + let expected_path_for_1 = [el_hashes_a.(0); h23; h4ee] in + let* path = compute_path t 1 in + assert (Internal_for_tests.path_to_list path = expected_path_for_1) ; + return_unit + +(* Negative test: pos < 0 *) +let test_compute_path_negative_pos () = + let open Error_monad.Result_syntax in + let n = 10 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let t = List.fold_left snoc_tr nil elements in + assert_invalid_pos @@ compute_path t (-1) ; + return_unit + +(* Negative test: pos >= size tree *) +let test_compute_path_out_of_bounds () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let t = List.fold_left snoc_tr nil elements in + assert_invalid_pos @@ compute_path t n ; + return_unit + +(* Negative test: pos = size tree, when tree is full *) +let test_compute_path_out_of_bounds_full () = + let open Error_monad.Result_syntax in + let n = 4 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let t = List.fold_left snoc_tr nil elements in + assert_invalid_pos @@ compute_path t n ; + return_unit + +(* Check that a computed root (from [check_path]) is the actual root *) +let test_check_path () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let elements_array = Array.of_list elements in + let t = List.fold_left snoc_tr nil elements in + Stdlib.List.init n (fun pos -> + let* path = compute_path t pos in + let* b = check_path path pos elements_array.(pos) (ML.root t) in + assert b ; + return_unit) + |> Environment.Error_monad.Result_syntax.tzjoin + +(* Check that a path is only valid for the position for which it + was computed *) +let test_check_path_wrong_pos () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let elements_array = Array.of_list elements in + let t = List.fold_left snoc_tr ML.nil elements in + let* path = compute_path t (n - 1) in + Stdlib.List.init (n - 2) (fun pos -> + let* b = check_path path pos elements_array.(pos) (ML.root t) in + assert (not b) ; + return_unit) + |> Environment.Error_monad.Result_syntax.tzjoin + +(* Check that a computed path is invalidated by a tree update *) +let test_check_invalidated_path () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let new_el = Bytes.of_string (Int.to_string n) in + let t = List.fold_left snoc_tr ML.nil elements in + let* path = compute_path t 0 in + let t = snoc_tr t new_el in + let* b = check_path path 0 (Stdlib.List.hd elements) (ML.root t) in + assert (not b) ; + return_unit + +(* Negative test: pos < 0 in [check_path] *) +let test_check_path_negative_pos () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let elements_array = Array.of_list elements in + let t = List.fold_left snoc_tr nil elements in + let pos = Random.int n in + let* path = compute_path t pos in + assert_invalid_pos @@ check_path path (-1) elements_array.(pos) (ML.root t) ; + return_unit + +(* Negative test: pos >= 2^depth in [check_path] *) +let test_check_path_out_of_bounds () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let elements_array = Array.of_list elements in + let t = List.fold_left snoc_tr nil elements in + let pos = Random.int n in + let* path = compute_path t pos in + (* NB: for this to be actually invalid, it is not enough to pass + a position larger than [n]. We need pos >= 2^depth. *) + assert_invalid_pos @@ check_path path 32 elements_array.(pos) (ML.root t) ; + return_unit + +(* Encoding roundtrip *) +let test_path_encoding () = + let open Error_monad.Result_syntax in + let n = 20 in + let elements = + Stdlib.List.init n (fun i -> Bytes.of_string (Int.to_string i)) + in + let t = List.fold_left snoc_tr nil elements in + let pos = n / 2 in + let* path = compute_path t pos in + let b = Data_encoding.Binary.to_bytes_exn path_encoding path in + let path' = Data_encoding.Binary.of_bytes_exn path_encoding b in + assert (path' = path) ; + return_unit + +let valid_tests = + [ + ("compute", test_compute); + ("snoc", test_snoc); + ("snoc_non_tr", test_snoc_non_tr); + ("compute_path", test_compute_path); + ("check_path", test_check_path); + ("path_encoding", test_path_encoding); + ("compute_path_negative_pos", test_compute_path_negative_pos); + ("compute_path_out_of_bounds", test_compute_path_out_of_bounds); + ("check_path_negative_pos", test_check_path_negative_pos); + ("check_path_out_of_bounds", test_check_path_out_of_bounds); + ("compute_path_out_of_bounds_full", test_compute_path_out_of_bounds_full); + ("check_path_wrong_pos", test_check_path_wrong_pos); + ("check_invalidated_path", test_check_invalidated_path); + ] + +let wrap (n, f) = + Alcotest_lwt.test_case n `Quick (fun _ () -> + match f () with Ok () -> Lwt.return_unit | Error _ -> assert false) + +let tests = List.map wrap valid_tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("merkle list", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_operation_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_operation_repr.ml new file mode 100644 index 000000000000..5f69a6c13625 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_operation_repr.ml @@ -0,0 +1,192 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Operation_repr + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_operation_repr.ml + Dependencies: -- + Subject: To test the modules (including the top-level) + in operation_repr.ml as individual units, particularly + failure cases. Superficial goal: increase coverage percentage. +*) +open Protocol + +open Tztest + +module Test_operation_repr = struct + open Operation_repr + + let test_of_list_single_case () = + let open Lwt_result_wrap_syntax in + let op = + Manager_operation + { + fee = Obj.magic 0; + operation = Obj.magic 0; + gas_limit = Obj.magic 0; + storage_limit = Obj.magic 0; + counter = Obj.magic 0; + source = Obj.magic 0; + } + in + let*?@ contents_list = of_list [Contents op] in + match contents_list with + | Contents_list (Single op') when Obj.repr op == Obj.repr op' -> return_unit + | _ -> failwith "Unexpected value" + + let test_of_list_multiple_case () = + let open Lwt_result_wrap_syntax in + let op1 = + Manager_operation + { + fee = Obj.magic 0; + operation = Obj.magic 0; + gas_limit = Obj.magic 0; + storage_limit = Obj.magic 0; + counter = Obj.magic 0; + source = Obj.magic 0; + } + in + let op2 = + Manager_operation + { + fee = Obj.magic 1; + operation = Obj.magic 0; + gas_limit = Obj.magic 0; + storage_limit = Obj.magic 0; + counter = Obj.magic 0; + source = Obj.magic 0; + } + in + let*?@ contents_list = of_list [Contents op1; Contents op2] in + match contents_list with + | Contents_list (Cons (op1', Single op2')) + when Obj.repr op1 == Obj.repr op1' && Obj.repr op2 == Obj.repr op2' -> + return_unit + | _ -> failwith "Unexpected value" + + let test_of_list_empty_case () = + let open Lwt_result_syntax in + match of_list [] with + | Ok _ -> failwith "of_list of an empty list was expected to fail" + | Error _ -> return_unit + + let zero_bls = + match Signature.(split_signature (Bls Signature.Bls.zero)) with + | {prefix = None; _} -> assert false + | {prefix = Some prefix; suffix} -> + let prefix = + Data_encoding.Binary.to_bytes_exn Signature.prefix_encoding prefix + in + (Bytes.cat (Bytes.of_string "\255") prefix, suffix) + + let test_split_signatures error assemble = + let open Lwt_result_syntax in + let op_bytes = + Data_encoding.Binary.to_bytes_exn + Operation_repr.contents_encoding + (Contents (Failing_noop "")) + in + let prefix, suffix = zero_bls in + let protocol_data_bytes = + Bytes.(concat empty) (assemble op_bytes prefix suffix) + in + match + Data_encoding.Binary.of_bytes + Operation_repr.protocol_data_encoding + protocol_data_bytes + with + | Ok _ -> failwith "Should have failed with %s" error + | Error (User_invariant_guard e) when e = error -> return_unit + | Error e -> + failwith + "Unexpected error: %a instead of %s" + Data_encoding.Binary.pp_read_error + e + error + + let test_only_signature_prefix () = + test_split_signatures "Operation lists should not be empty." + @@ fun _op_bytes prefix suffix -> [prefix; suffix] + + let test_decoding_empty_list () = + test_split_signatures "Operation lists should not be empty." + @@ fun _op_bytes _prefix suffix -> [suffix] + + let test_multiple_signature_prefix () = + test_split_signatures "Signature prefix must appear last" + @@ fun op_bytes prefix suffix -> [op_bytes; prefix; prefix; suffix] + + let test_signature_prefix_not_final () = + test_split_signatures "Signature prefix must appear last" + @@ fun op_bytes prefix suffix -> [prefix; op_bytes; suffix] + + let test_multiple_non_manager () = + test_split_signatures + "Operation list of length > 1 should only contain manager operations." + @@ fun op_bytes prefix suffix -> [op_bytes; op_bytes; prefix; suffix] +end + +let tests = + [ + tztest + "of_list: single element input list" + `Quick + Test_operation_repr.test_of_list_single_case; + tztest + "of_list: multiple element input list" + `Quick + Test_operation_repr.test_of_list_multiple_case; + tztest + "of_list: empty input list" + `Quick + Test_operation_repr.test_of_list_empty_case; + tztest + "protocol_data_encoding: only signature prefix" + `Quick + Test_operation_repr.test_only_signature_prefix; + tztest + "protocol_data_encoding: empty list" + `Quick + Test_operation_repr.test_decoding_empty_list; + tztest + "protocol_data_encoding: multiple signature prefix" + `Quick + Test_operation_repr.test_multiple_signature_prefix; + tztest + "protocol_data_encoding: signature prefix not final" + `Quick + Test_operation_repr.test_signature_prefix_not_final; + tztest + "protocol_data_encoding: multiple non manager" + `Quick + Test_operation_repr.test_multiple_non_manager; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Operation_repr.ml", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_percentage.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_percentage.ml new file mode 100644 index 000000000000..052047985e21 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_percentage.ml @@ -0,0 +1,173 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (quantities) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_percentage.ml + Subject: On percentages. +*) + +open Protocol + +let pct_of_int n = + Percentage.of_ratio_bounded Ratio_repr.{numerator = n; denominator = 100} + +let assert_equal ~loc n (pct : Percentage.t) = + let pct_q = Percentage.to_q pct in + Assert.equal_q ~loc Q.(n // 100) pct_q + +let assert_equal_tez ~loc t1 t2 = + Assert.equal ~loc Tez_repr.equal "Tez aren't equal" Tez_repr.pp t1 t2 + +let assert_equal_q ~loc q (pct : Percentage.t) = + let pct_q = Percentage.to_q pct in + Assert.equal_q ~loc q pct_q + +let f = Tez_repr.mul_percentage + +let test_constant_values () = + let open Lwt_result_syntax in + let* () = assert_equal ~loc:__LOC__ 0 Percentage.p0 in + let* () = assert_equal ~loc:__LOC__ 5 Percentage.p5 in + let* () = assert_equal ~loc:__LOC__ 50 Percentage.p50 in + let* () = assert_equal ~loc:__LOC__ 51 Percentage.p51 in + let* () = assert_equal ~loc:__LOC__ 100 Percentage.p100 in + return_unit + +let test_neg () = + let open Lwt_result_syntax in + let open Percentage in + let* () = assert_equal ~loc:__LOC__ 95 (neg p5) in + let* () = assert_equal ~loc:__LOC__ 50 (neg p50) in + let* () = assert_equal ~loc:__LOC__ 31 (neg (pct_of_int 69)) in + let* () = assert_equal ~loc:__LOC__ 100 (neg (pct_of_int 0)) in + let* () = assert_equal ~loc:__LOC__ 5 (neg (neg p5)) in + return_unit + +let test_bounded () = + let open Lwt_result_syntax in + let open Percentage in + let* () = assert_equal ~loc:__LOC__ 100 (pct_of_int 200) in + let* () = assert_equal ~loc:__LOC__ 0 (pct_of_int (-100)) in + let* () = assert_equal ~loc:__LOC__ 100 (add_bounded p50 p50) in + let* () = assert_equal ~loc:__LOC__ 100 (add_bounded p50 (neg p5)) in + return_unit + +let test_mul_percentage () = + let open Lwt_result_syntax in + let open Tez_repr in + let rounding = `Down in + let* () = + assert_equal_tez + ~loc:__LOC__ + (of_mutez_exn 50L) + (mul_percentage ~rounding (of_mutez_exn 100L) Percentage.p50) + in + let* () = + assert_equal_tez + ~loc:__LOC__ + (of_mutez_exn 5L) + (mul_percentage ~rounding (of_mutez_exn 100L) Percentage.p5) + in + (* round down *) + let* () = + assert_equal_tez + ~loc:__LOC__ + (of_mutez_exn 49L) + (mul_percentage ~rounding (of_mutez_exn 99L) Percentage.p50) + in + (* round up *) + let* () = + assert_equal_tez + ~loc:__LOC__ + (of_mutez_exn 50L) + (mul_percentage ~rounding:`Up (of_mutez_exn 99L) Percentage.p50) + in + let tz = 123456L in + let* () = + assert_equal_tez + ~loc:__LOC__ + (of_mutez_exn tz) + (mul_percentage ~rounding (of_mutez_exn tz) (pct_of_int 200)) + in + (* no overflow *) + let* () = + assert_equal_tez + ~loc:__LOC__ + (of_mutez_exn 9131138316486228048L) + (mul_percentage ~rounding Tez_repr.max_mutez (pct_of_int 99)) + in + return_unit + +let test_mul () = + let open Lwt_result_syntax in + let mul = Percentage.mul ~round:`Down in + let* () = + assert_equal_q + ~loc:__LOC__ + Q.(25 // 100) + (mul Percentage.p50 Percentage.p50) + in + let* () = + assert_equal_q + ~loc:__LOC__ + Q.(25 // 10000) + (mul Percentage.p5 Percentage.p5) + in + return_unit + +let test_of_q () = + let open Lwt_result_syntax in + let round = `Down in + let of_q = Percentage.of_q_bounded in + let* () = + assert_equal_q ~loc:__LOC__ Q.(11 // 100) (of_q ~round Q.(11 // 100)) + in + let* () = assert_equal_q ~loc:__LOC__ Q.one (of_q ~round Q.(199 // 100)) in + (* round down *) + let* () = + assert_equal_q ~loc:__LOC__ Q.(777 // 10000) (of_q ~round Q.(777 // 9999)) + in + (* round up *) + let* () = + assert_equal_q + ~loc:__LOC__ + Q.(778 // 10000) + (of_q ~round:`Up Q.(777 // 9999)) + in + + (* precision *) + let* () = assert_equal_q ~loc:__LOC__ Q.zero (of_q ~round Q.(1 // 10001)) in + let* () = + assert_equal_q ~loc:__LOC__ Q.(1 // 10000) (of_q ~round Q.(1 // 10000)) + in + let* () = + assert_equal_q ~loc:__LOC__ Q.(1 // 10000) (of_q ~round:`Up Q.(1 // 10001)) + in + (* no overflow *) + let big_z = Z.of_int64 9131138316486228048L in + let* () = + assert_equal_q ~loc:__LOC__ Q.one (of_q ~round Q.(big_z /// Z.one)) + in + return_unit + +let tests = + Tztest. + [ + tztest "Test constant values" `Quick test_constant_values; + tztest "Test neg" `Quick test_neg; + tztest "Test bounded" `Quick test_bounded; + tztest "Test mul_percentage" `Quick test_mul_percentage; + tztest "Test mul" `Quick test_mul; + tztest "Test of_q" `Quick test_of_q; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("percentage", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_qty.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_qty.ml new file mode 100644 index 000000000000..c8e05f3be10f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_qty.ml @@ -0,0 +1,167 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (quantities) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_qty.ml + Subject: On tez quantities. +*) + +open Protocol + +let known_ok_tez_literals = + [ + (0L, "0"); + (10L, "0.00001"); + (100L, "0.0001"); + (1_000L, "0.001"); + (10_000L, "0.01"); + (100_000L, "0.1"); + (1_000_000L, "1"); + (10_000_000L, "10"); + (100_000_000L, "100"); + (1_000_000_000L, "1000"); + (10_000_000_000L, "10000"); + (100_000_000_000L, "100000"); + (1_000_000_000_000L, "1000000"); + (1_000_000_000_001L, "1000000.000001"); + (1_000_000_000_010L, "1000000.00001"); + (1_000_000_000_100L, "1000000.0001"); + (1_000_000_001_000L, "1000000.001"); + (1_000_000_010_000L, "1000000.01"); + (1_000_000_100_000L, "1000000.1"); + (123_123_123_123_123_123L, "123123123123.123123"); + (999_999_999_999_999_999L, "999999999999.999999"); + ] + +let known_bad_tez_literals = + [ + "10000."; + "100,."; + "100,"; + "1,0000"; + "0.0000,1"; + "0.00,1"; + "0,1"; + "HAHA"; + "0.000,000,1"; + "0.0000000"; + "9,999,999,999,999.999,999"; + ] + +let fail expected given msg = + Format.kasprintf + Stdlib.failwith + "@[%s@ expected: %s@ got: %s@]" + msg + expected + given + +let fail_msg fmt = Format.kasprintf (fail "" "") fmt + +let default_printer _ = "" + +(** Literals which are supposed to be parsed correctly. *) +let test_known_tez_literals () = + let open Lwt_result_syntax in + List.iter + (fun (v, s) -> + let vv = Tez_repr.of_mutez v in + let vs = Tez_repr.of_string s in + let vs' = + Tez_repr.of_string (String.concat "" (String.split_on_char ',' s)) + in + let vv = + match vv with None -> fail_msg "could not unopt %Ld" v | Some vv -> vv + in + let vs = + match vs with None -> fail_msg "could not unopt %s" s | Some vs -> vs + in + let vs' = + match vs' with + | None -> fail_msg "could not unopt %s" s + | Some vs' -> vs' + in + assert (vv = vs) ; + assert (vv = vs') ; + assert (Tez_repr.to_string vv = s)) + known_ok_tez_literals ; + List.iter + (fun s -> + let vs = Tez_repr.of_string s in + assert (vs = None)) + known_bad_tez_literals ; + return_unit + +(** Randomly generated tez value which is printed into a string then + parsed again for their equality. *) +let test_random_tez_literals () = + let open Lwt_result_syntax in + for _ = 0 to 100_000 do + let v = Random.int64 12L in + let vv = Tez_repr.of_mutez v in + let vv = + match vv with None -> fail_msg "could not unopt %Ld" v | Some vv -> vv + in + let s = Tez_repr.to_string vv in + let vs = Tez_repr.of_string s in + let s' = String.concat "" (String.split_on_char ',' s) in + let vs' = Tez_repr.of_string s' in + assert (vs <> None) ; + assert (vs' <> None) ; + (match vs with + | None -> assert false + | Some vs -> + let rev = Tez_repr.to_mutez vs in + assert (v = rev)) ; + match vs' with + | None -> assert false + | Some vs' -> + let rev = Tez_repr.to_mutez vs' in + assert (v = rev) + done ; + return_unit + +let tests = + [ + ("tez-literals", fun _ -> test_known_tez_literals ()); + ("rnd-tez-literals", fun _ -> test_random_tez_literals ()); + ] + +let wrap (n, f) = + let open Lwt_syntax in + Alcotest_lwt.test_case n `Quick (fun _ () -> + let+ result = f () in + match result with + | Ok () -> () + | Error error -> + Format.kasprintf Stdlib.failwith "%a" pp_print_trace error) + +let tests = List.map wrap tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("qty", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_raw_level_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_raw_level_repr.ml new file mode 100644 index 000000000000..aa4e93374b27 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_raw_level_repr.ml @@ -0,0 +1,188 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Tztest + +(** Testing + ------- + Component: Raw_level_repr + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_raw_level_repr.ml + Dependencies: -- + Subject: To test the modules (including the top-level) + in raw_level_repr.ml as individual units, particularly + failure cases. Superficial goal: increase coverage percentage. +*) + +module Test_raw_level_repr = struct + (* NOTE: Avoid assertions against too many functions from Raw_level_repr. For instance, + Raw_level_repr contains a [compare] function, but while [Assert]'ing, convert them to + int32 (or any convenient OCaml value) and compare instead of using [Raw_level_repr]'s compare *) + + (** Testing [encoding], int32 underneath, by applying it with Data_encoding *) + let test_encoding () = + let open Lwt_result_syntax in + let encoding = Raw_level_repr.encoding in + let bytes = Bytes.make 4 '0' in + Bytes.set_int32_ne bytes 0 0l ; + let* v = + match Data_encoding.Binary.of_bytes encoding bytes with + | Ok x -> return x + | Error e -> + failwith + "Data_encoding.Binary.read shouldn't have failed with \ + Raw_level_repr.encoding: %a" + Data_encoding.Binary.pp_read_error + e + in + let* () = + Assert.equal_int ~loc:__LOC__ (Int32.to_int (Raw_level_repr.to_int32 v)) 0 + in + Bytes.set_int32_ne bytes 0 (-1l) ; + Data_encoding.Binary.of_bytes encoding bytes |> function + | Error _ -> return_unit + | Ok x -> + failwith + "Data_encoding.Binary.read shouldn't have succeeded with %a" + Raw_level_repr.pp + x + + (* TODO rpc_arg. RPC_arg needs to be unit tested separately. Preferably, with a functor *) + (* let rpc_arg () = () *) + + (** int32 interop tests *) + let test_int32_interop () = + let open Lwt_result_wrap_syntax in + let int32v = 100l in + let*?@ raw_level = Raw_level_repr.of_int32 int32v in + let* () = + Assert.equal_int32 ~loc:__LOC__ (Raw_level_repr.to_int32 raw_level) int32v + in + let int32v = -1l in + let* () = + match Raw_level_repr.of_int32 int32v with + | Ok _ -> failwith "Negative int32s should not be coerced into raw_level" + | Error _ -> return_unit + in + try + let (_ : Raw_level_repr.t) = Raw_level_repr.of_int32_exn int32v in + failwith "Negative int32s should not be coerced into raw_level" + with Invalid_argument _ -> return_unit + + (** Asserting [root]'s runtime value. Expected to be [0l] *) + let test_root () = + let root = Raw_level_repr.root in + Assert.equal_int32 ~loc:__LOC__ (root |> Raw_level_repr.to_int32) 0l + + (** Asserting [succ] which is expected to return successor levels *) + let test_succ () = + let open Lwt_result_syntax in + let next_raw_level = Raw_level_repr.succ Raw_level_repr.root in + let* () = + Assert.equal_int32 + ~loc:__LOC__ + (next_raw_level |> Raw_level_repr.to_int32) + 1l + in + let arbitrary_next_raw_level = + Raw_level_repr.succ (Raw_level_repr.of_int32_exn 99l) + in + Assert.equal_int32 + ~loc:__LOC__ + (arbitrary_next_raw_level |> Raw_level_repr.to_int32) + 100l + + (** Asserting [pred] which is expected to return predecessor levels *) + let test_pred () = + let open Lwt_result_syntax in + let* () = + match Raw_level_repr.pred (Raw_level_repr.of_int32_exn 1l) with + | Some previous_raw_level -> + Assert.equal_int32 + ~loc:__LOC__ + (previous_raw_level |> Raw_level_repr.to_int32) + 0l + | None -> + failwith + "Raw_level_repr.pred should have successfully returned 0l as the \ + predecessor of 1l" + in + Raw_level_repr.pred Raw_level_repr.root |> function + | Some _ -> + failwith + "Raw_level_repr.pred should have returned None when asked for \ + predecessor of [root]" + | None -> return_unit + + let test_skip_succ () = + let int32_limit = 0x7FFFFFFFl in + let overflown_next_raw_level = + Raw_level_repr.succ (Raw_level_repr.of_int32_exn int32_limit) + in + if Int32.compare (Raw_level_repr.to_int32 overflown_next_raw_level) 0l >= 0 + then return_unit + else + failwith + "succ of 0x7FFFFFFFl %a was expected to be non-negative" + Assert.Int32.pp + (overflown_next_raw_level |> Raw_level_repr.to_int32) +end + +let tests = + [ + tztest + "Raw_level_repr.encoding: checks if encoding is int32 as expected" + `Quick + Test_raw_level_repr.test_encoding; + tztest + "Raw_level_repr.root: check if value is 0l" + `Quick + Test_raw_level_repr.test_root; + tztest + "Raw_level_repr.succ: basic assertions" + `Quick + Test_raw_level_repr.test_succ; + tztest + "Raw_level_repr.pred: basic assertions" + `Quick + Test_raw_level_repr.test_pred; + tztest + "Raw_level_repr: int32 interop" + `Quick + Test_raw_level_repr.test_int32_interop; + ] + +let skipped_tests = + [ + tztest + "Raw_level_repr.succ: overflow" + `Quick + Test_raw_level_repr.test_skip_succ; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Raw level", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_receipt.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_receipt.ml new file mode 100644 index 000000000000..e0e561ca0d73 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_receipt.ml @@ -0,0 +1,108 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (token) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_receipt.ml + Subject: Test receipt endocings. +*) + +open Protocol +open Alpha_context +open Data_encoding + +let random_amount () = + match Tez.of_mutez (Int64.add 1L (Random.int64 100L)) with + | None -> assert false + | Some x -> x + +(** Test that [decode (encode balance_updates) = balance_updates]. *) +let test_encodings balance = + let open Lwt_result_syntax in + Random.init 0 ; + let am = random_amount () in + let r1 = Receipt.item balance (Debited am) Protocol_migration in + let r2 = Receipt.item balance (Credited am) Protocol_migration in + let r3 = Receipt.item balance (Debited am) Subsidy in + let r4 = Receipt.item balance (Credited am) Subsidy in + let r5 = Receipt.item balance (Debited am) Simulation in + let r6 = Receipt.item balance (Credited am) Simulation in + let r7 = Receipt.item balance (Debited am) Block_application in + let r8 = Receipt.item balance (Credited am) Block_application in + let coded = + Json.construct + Receipt.balance_updates_encoding + [r1; r2; r3; r4; r5; r6; r7; r8] + in + let decoded = Json.destruct Receipt.balance_updates_encoding coded in + match decoded with + | [r1'; r2'; r3'; r4'; r5'; r6'; r7'; r8'] -> + assert ( + r1' = r1 && r2' = r2 && r3' = r3 && r4' = r4 && r5 = r5' && r6 = r6' + && r7 = r7' && r8 = r8') ; + return_unit + | _ -> assert false + +let test_encodings () = + let open Lwt_result_syntax in + let open Receipt in + let pkh = Signature.Public_key_hash.zero in + let pkh2, _pk, _sk = Signature.generate_key () in + let staker1 = Receipt.frozen_shared_between_stakers ~delegate:pkh in + let staker2 = Receipt.frozen_baker pkh in + let staker3 = + Receipt.frozen_single_staker ~staker:(Contract.Implicit pkh2) ~delegate:pkh + in + let* () = test_encodings (Contract (Contract.Implicit pkh)) in + let* () = test_encodings Block_fees in + let* () = test_encodings (Deposits staker1) in + let* () = test_encodings (Deposits staker2) in + let* () = test_encodings (Deposits staker3) in + let* () = test_encodings Nonce_revelation_rewards in + let* () = test_encodings Attesting_rewards in + let* () = test_encodings Baking_rewards in + let* () = test_encodings Baking_bonuses in + let* () = test_encodings Storage_fees in + let* () = test_encodings Double_signing_punishments in + let* () = + test_encodings + (Lost_attesting_rewards (pkh, Random.bool (), Random.bool ())) + in + let* () = test_encodings Liquidity_baking_subsidies in + let* () = test_encodings Burned in + let* () = test_encodings (Commitments Blinded_public_key_hash.zero) in + let* () = test_encodings Bootstrap in + let* () = test_encodings Invoice in + let* () = test_encodings Initial_commitments in + let* () = test_encodings Minted in + let* () = test_encodings Sc_rollup_refutation_punishments in + test_encodings Sc_rollup_refutation_rewards + +let tests = Tztest.[tztest "receipt - encoding" `Quick test_encodings] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("receipt", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_round_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_round_repr.ml new file mode 100644 index 000000000000..269dff116d87 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_round_repr.ml @@ -0,0 +1,676 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: protocol + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_round_repr.ml + Subject: test the Round_repr module +*) + +open Protocol +open Alpha_context + +type round_test = { + (* input: round; output: round duration *) + round_duration : (int * int) list; + (* input: level offset; output: round, round offset *) + round_and_offset : (int * (int * int)) list; + (* input: pred_ts, pred_round, round; output: ts *) + timestamp_of_round : ((int * int * int) * int) list; + (* input: pred_ts, pred_round, ts; output: round *) + round_of_timestamp : ((int * int * int) * int) list; +} + +(* an association list of the input, output values *) +let case_3_4 = + { + round_duration = [(0, 3); (1, 4); (2, 5); (3, 6)]; + round_and_offset = + [ + (0, (0, 0)); + (1, (0, 1)); + (2, (0, 2)); + (3, (1, 0)); + (4, (1, 1)); + (5, (1, 2)); + (6, (1, 3)); + (7, (2, 0)); + (8, (2, 1)); + ]; + timestamp_of_round = [((100, 0, 6), 136); ((100, 1, 6), 137)]; + round_of_timestamp = + [ + ((100, 0, 121), 4); + ((100, 0, 122), 4); + ((100, 0, 123), 4); + ((100, 0, 124), 4); + ((100, 0, 125), 4); + ((100, 0, 126), 4); + ((100, 1, 121), 3); + ((100, 1, 122), 4); + ((100, 1, 123), 4); + ((100, 1, 124), 4); + ((100, 1, 125), 4); + ((100, 1, 126), 4); + ]; + } + +let case_3_6 = + { + round_duration = + [ + (0, 3); + (1, 6); + (2, 9); + (3, 12); + (4, 15); + (5, 18); + (6, 21); + (7, 24); + (8, 27); + ]; + round_and_offset = + [ + (0, (0, 0)); + (1, (0, 1)); + (2, (0, 2)); + (3, (1, 0)); + (4, (1, 1)); + (5, (1, 2)); + (6, (1, 3)); + (7, (1, 4)); + (8, (1, 5)); + (9, (2, 0)); + (10, (2, 1)); + (11, (2, 2)); + (97, (7, 13)); + ]; + timestamp_of_round = + [ + ((100, 0, 0), 103); + ((100, 1, 0), 106); + ((100, 0, 6), 166); + ((100, 1, 6), 169); + ]; + round_of_timestamp = + [ + ((100, 0, 103), 0); + ((100, 0, 104), 0); + ((100, 0, 105), 0); + ((100, 0, 106), 1); + ((100, 0, 111), 1); + ((100, 0, 112), 2); + ((100, 0, 120), 2); + ((100, 0, 121), 3); + ((100, 0, 132), 3); + ((100, 0, 133), 4); + ((100, 1, 106), 0); + ((100, 1, 107), 0); + ((100, 1, 108), 0); + ((100, 1, 109), 1); + ((100, 1, 114), 1); + ((100, 1, 115), 2); + ]; + } + +let test_cases = + [ + (* (first_round_duration, delay_increment_per_round), test_case_expectations *) + ((3, 1), case_3_4, "case_3_4"); + ((3, 3), case_3_6, "case_3_6"); + ] + +let round_of_int i = Round_repr.of_int i + +let mk_round_durations first_round_duration delay_increment_per_round = + let first_round_duration = + Period_repr.of_seconds_exn @@ Int64.of_int first_round_duration + in + let delay_increment_per_round = + Period_repr.of_seconds_exn @@ Int64.of_int delay_increment_per_round + in + (* We assume test specifications do respect round_durations + invariants and cannot fail *) + Stdlib.Option.get + @@ Round_repr.Durations.create_opt + ~first_round_duration + ~delay_increment_per_round + +let process_test_case (round_durations, ios, _) = + let open Lwt_result_wrap_syntax in + let open Round_repr in + let* () = + List.iter_es + (fun (i, o) -> + let*?@ round = round_of_int i in + let dur = Durations.round_duration round_durations round in + Assert.equal_int64 + ~loc:__LOC__ + (Int64.of_int o) + (Period_repr.to_seconds dur)) + ios.round_duration + in + let open Internal_for_tests in + (* test [round_and_offset] *) + let* () = + List.iter_es + (fun (level_offset, (round, ro)) -> + let level_offset = + Period_repr.of_seconds_exn (Int64.of_int level_offset) + in + let*?@ round_and_offset = + round_and_offset round_durations ~level_offset + in + let* () = + Assert.equal_int32 + ~loc:__LOC__ + (Int32.of_int round) + (Round_repr.to_int32 round_and_offset.round) + in + Assert.equal_int64 + ~loc:__LOC__ + (Int64.of_int ro) + (Period_repr.to_seconds round_and_offset.offset)) + ios.round_and_offset + in + (* test [timestamp_of_round] *) + let* () = + List.iter_es + (fun ((pred_ts, pred_round, round), o) -> + let predecessor_timestamp = + Time_repr.of_seconds (Int64.of_int pred_ts) + in + let*@ ts = + let*? predecessor_round = Round_repr.of_int pred_round in + let*? round = Round_repr.of_int round in + Lwt.return + (timestamp_of_round + round_durations + ~predecessor_timestamp + ~predecessor_round + ~round) + in + Assert.equal_int64 + ~loc:__LOC__ + (Int64.of_int o) + (Time_repr.to_seconds ts)) + ios.timestamp_of_round + in + (* test [round_of_timestamp] *) + List.iter_es + (fun ((pred_ts, pred_round, ts), o) -> + let predecessor_timestamp = Time_repr.of_seconds (Int64.of_int pred_ts) in + let*@ round = + let*? predecessor_round = Round_repr.of_int pred_round in + Lwt.return + (round_of_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round + ~timestamp:(Time_repr.of_seconds (Int64.of_int ts))) + in + Assert.equal_int32 + ~loc:__LOC__ + (Int32.of_int o) + (Round_repr.to_int32 round)) + ios.round_of_timestamp + +let test_round () = + let final_test_cases = + List.map + (fun ((first_round_duration, delay_increment_per_round), ios, name) -> + ( mk_round_durations first_round_duration delay_increment_per_round, + ios, + name )) + test_cases + in + (* TODO this could be run in the error monad instead of lwt *) + List.iter_es process_test_case final_test_cases + +let ts_add ts period = + match Timestamp.(ts +? period) with + | Ok ts' -> ts' + | Error _ -> Environment.Pervasives.failwith "timestamp add" + +let test_round_of_timestamp () = + let open Lwt_result_wrap_syntax in + let duration0 = Period.of_seconds_exn 1L in + let*?@ round_durations = + Round.Durations.create + ~first_round_duration:duration0 + ~delay_increment_per_round:Period.one_second + in + let predecessor_timestamp = Time.Protocol.epoch in + let level_start = ts_add predecessor_timestamp duration0 in + let rec loop ~expected_round ~elapsed_time = + if elapsed_time < 1000 then + let timestamp = + ts_add level_start (Period.of_seconds_exn (Int64.of_int elapsed_time)) + in + match + Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~timestamp + ~predecessor_round:Round.zero + with + | Ok round -> + let* () = + Assert.equal_int32 + ~loc:__LOC__ + (Round.to_int32 round) + (Int32.of_int expected_round) + in + let elapsed_time = elapsed_time + (expected_round + 1) + and expected_round = 1 + expected_round in + loop ~expected_round ~elapsed_time + | Error _ -> failwith "error " + else return_unit + in + loop ~elapsed_time:0 ~expected_round:0 + +let round_of_timestamp_perf (duration0_int64, dipr) = + let open Lwt_result_wrap_syntax in + let duration0 = Period.of_seconds_exn duration0_int64 in + let delay_increment_per_round = Period.of_seconds_exn dipr in + let round_durations = + Stdlib.Option.get + @@ Round.Durations.create_opt + ~first_round_duration:duration0 + ~delay_increment_per_round + in + let predecessor_timestamp = Time.Protocol.epoch in + let level_start = ts_add predecessor_timestamp duration0 in + let max_ts = Int64.(sub (of_int32 Int32.max_int) duration0_int64) in + let rec loop i = + let open Result_syntax in + if i >= 0L then ( + let repeats = 100 in + let rec loop_inner sum j = + if j > 0 then + let timestamp = + ts_add level_start (Period.of_seconds_exn (Int64.sub max_ts i)) + in + let t0 = Unix.gettimeofday () in + let* (_round : Round.t) = + Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~timestamp + ~predecessor_round:Round.zero + in + let t1 = Unix.gettimeofday () in + let time = t1 -. t0 in + loop_inner (sum +. time) (j - 1) + else return sum + in + let* sum = loop_inner 0.0 repeats in + let time = sum /. float_of_int repeats in + assert (time < 0.01) ; + loop (Int64.pred i)) + else return_unit + in + let*?@ () = loop 1000L in + return_unit + +let default_round_durations_list = + [(1L, 1L); (1L, 2L); (1L, 3L); (2L, 3L); (2L, 4L)] + +let test_round_of_timestamp_perf () = + List.iter_es round_of_timestamp_perf default_round_durations_list + +let timestamp_of_round_perf (duration0_int64, dipr) = + let open Lwt_result_wrap_syntax in + let duration0 = Period.of_seconds_exn duration0_int64 in + let delay_increment_per_round = Period.of_seconds_exn dipr in + let round_durations = + Stdlib.Option.get + @@ Round.Durations.create_opt + ~first_round_duration:duration0 + ~delay_increment_per_round + in + let predecessor_timestamp = Time.Protocol.epoch in + let rec loop i = + let open Result_syntax in + if i >= 0l then ( + let* round = Round.of_int32 Int32.(sub max_int i) in + let t0 = Unix.gettimeofday () in + let* (_ts : Timestamp.time) = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp + ~predecessor_round:Round.zero + ~round + in + let t1 = Unix.gettimeofday () in + let time = t1 -. t0 in + assert (time < 0.01) ; + loop (Int32.pred i)) + else return_unit + in + let*?@ () = loop 1000l in + return_unit + +let test_timestamp_of_round_perf () = + List.iter_es timestamp_of_round_perf default_round_durations_list + +let test_error_is_triggered_for_too_high_timestamp () = + let open Result_wrap_syntax in + let round_durations = + Stdlib.Option.get + @@ Round.Durations.create_opt + ~first_round_duration:Period.one_second + ~delay_increment_per_round:Period.one_second + in + + let predecessor_timestamp = Time.Protocol.epoch in + let@ res = + Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round:Round.zero + ~timestamp:(Time_repr.of_seconds Int64.max_int) + in + match res with + | Error _ -> + Assert.proto_error_with_info ~loc:__LOC__ res "level offset too high" + | Ok _ -> Assert.error ~loc:__LOC__ res (fun _ -> false) + +let rec ( --> ) i j = + (* [i; i+1; ...; j] *) + if Compare.Int.(i > j) then [] else i :: (succ i --> j) + +let ts_of_round_inverse (duration0_int64, dipr) round_int = + let open Lwt_result_wrap_syntax in + let first_round_duration = Period.of_seconds_exn duration0_int64 in + let delay_increment_per_round = Period.of_seconds_exn dipr in + let round_durations = + Stdlib.Option.get + @@ Round.Durations.create_opt + ~first_round_duration + ~delay_increment_per_round + in + let predecessor_timestamp = Time.Protocol.epoch in + let predecessor_round = Round.zero in + let*?@ round = Round.of_int round_int in + let*?@ timestamp = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp + ~predecessor_round + ~round + in + let*?@ round' = + Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round + ~timestamp + in + let*?@ round' = Round.to_int round' in + Assert.equal_int ~loc:__LOC__ round_int round' + +(* We restrict to round 134,217,727 as rounds above can lead to + integer overflow in [Round_repr.round_and_offset] and are already prevented + by returning an error. *) +let test_ts_of_round_inverse () = + let open Lwt_result_syntax in + let* () = + List.iter_es + (fun durations -> + List.iter_es + (ts_of_round_inverse durations) + ((0 --> 20) @ (60000 --> 60010))) + default_round_durations_list + in + List.iter_es + (ts_of_round_inverse (1L, 1L)) + (List.map (fun i -> Int32.to_int 134_217_727l - i) (1 --> 20)) + +let round_of_ts_inverse ~first_round_duration ~delay_increment_per_round ts = + let open Lwt_result_wrap_syntax in + Format.printf "ts = %Ld@." ts ; + let first_round_duration = Period.of_seconds_exn first_round_duration in + let delay_increment_per_round = + Period.of_seconds_exn delay_increment_per_round + in + let*?@ round_durations = + Round.Durations.create ~first_round_duration ~delay_increment_per_round + in + let predecessor_timestamp = Time.Protocol.epoch in + let predecessor_round = Round.zero in + let*?@ level_start = + Timestamp.( +? ) predecessor_timestamp first_round_duration + in + let start_of_round timestamp = + let*?@ round = + Round.round_of_timestamp + round_durations + ~predecessor_timestamp + ~predecessor_round + ~timestamp + in + let*?@ t = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp + ~predecessor_round + ~round + in + return (round, t) + in + let*?@ timestamp = Period.of_seconds_exn ts |> Timestamp.( +? ) level_start in + let* round, ts_start_of_round = start_of_round timestamp in + let* () = + Assert.leq_int64 + ~loc:__LOC__ + (Timestamp.to_seconds ts_start_of_round) + (Timestamp.to_seconds timestamp) + in + let pred ts = Period.one_second |> Timestamp.( - ) ts in + let rec iter ts = + let* round', ts_start_of_round' = start_of_round ts in + let* () = + Assert.equal_int64 + ~loc:__LOC__ + (Timestamp.to_seconds ts_start_of_round) + (Timestamp.to_seconds ts_start_of_round') + in + let* () = + Assert.equal_int32 + ~loc:__LOC__ + (Round.to_int32 round) + (Round.to_int32 round') + in + if Timestamp.(ts > ts_start_of_round') then iter (pred ts) else return_unit + in + if Timestamp.(timestamp > ts_start_of_round) then iter (pred timestamp) + else return_unit + +let test_round_of_ts_inverse () = + let open Lwt_result_syntax in + let* () = + List.iter_es + (fun (first_round_duration, delay_increment_per_round) -> + List.iter_es + (fun ts -> + round_of_ts_inverse + ~first_round_duration + ~delay_increment_per_round + (Int64.of_int ts)) + ((0 --> 20) @ (60000 --> 60010))) + default_round_durations_list + in + List.iter_es + (fun ts -> + Format.printf "%Ld@." ts ; + round_of_ts_inverse + ~first_round_duration:1L + ~delay_increment_per_round:2L + ts) + (List.map + (fun i -> Int64.of_int (Int32.to_int Int32.max_int - i)) + (0 --> 20)) + +let test_level_offset_of_round () = + let open Lwt_result_wrap_syntax in + let rd1 = + let first_round_duration = 3 in + let delay_increment_per_round = 1 in + mk_round_durations first_round_duration delay_increment_per_round + in + List.iter_es + (fun (round_durations, tests) -> + List.iter_es + (fun (round, expected_offset) -> + let*?@ round = Round_repr.of_int round in + let*?@ computed_offset = + Round_repr.level_offset_of_round round_durations ~round + in + Assert.equal_int64 + ~loc:__LOC__ + (Period_repr.to_seconds computed_offset) + (Int64.of_int expected_offset)) + tests) + [ + (rd1, [(0, 0); (1, 3); (2, 7)]); + (mk_round_durations 3 3, [(0, 0); (1, 3); (2, 9); (3, 18)]); + ] + +(* This is the previous implementation, serving as an oracle *) +let round_and_offset_oracle (round_durations : Round_repr.Durations.t) + ~level_offset = + let open Result_syntax in + let level_offset_in_seconds = Period_repr.to_seconds level_offset in + (* We have the invariant [round <= level_offset] so there is no need to search + beyond [level_offset]. We set [right_bound] to [level_offset + 1] to avoid + triggering the error level_offset too high when the round equals + [level_offset]. *) + let right_bound = + if Compare.Int64.(level_offset_in_seconds < Int64.of_int32 Int32.max_int) + then Int32.of_int (Int64.to_int level_offset_in_seconds + 1) + else Int32.max_int + in + let rec bin_search min_r max_r = + if Compare.Int32.(min_r >= right_bound) then invalid_arg "foo" + else + let* round = + Round_repr.of_int32 @@ Int32.(add min_r (div (sub max_r min_r) 2l)) + in + let next_round = Round_repr.succ round in + let* next_level_offset = + Round_repr.level_offset_of_round round_durations ~round:next_round + in + if Period_repr.(level_offset >= next_level_offset) then + bin_search (Round_repr.to_int32 next_round) max_r + else + let* current_level_offset = + Round_repr.level_offset_of_round round_durations ~round + in + if Period_repr.(level_offset < current_level_offset) then + bin_search min_r (Round_repr.to_int32 round) + else + return + Round_repr.Internal_for_tests. + { + round; + offset = + Period_repr.of_seconds_exn + (Int64.sub + (Period_repr.to_seconds level_offset) + (Period_repr.to_seconds current_level_offset)); + } + in + bin_search 0l right_bound + +(* Test whether the new version is equivalent to the old one *) +let test_round_and_offset_correction = + let open Lwt_result_wrap_syntax in + Tztest.tztest_qcheck2 + ~name:"round_and_offset is correct" + QCheck2.( + Gen.pair + Qcheck2_helpers.(Gen.pair uint16 uint16) + (Qcheck2_helpers.int64_range_gen 0L 100000L)) + (fun ((first_round_duration, delay_increment_per_round), level_offset) -> + QCheck2.assume (first_round_duration > 0) ; + QCheck2.assume (delay_increment_per_round > 0) ; + let first_round_duration = + Period_repr.of_seconds_exn (Int64.of_int first_round_duration) + and delay_increment_per_round = + Period_repr.of_seconds_exn (Int64.of_int delay_increment_per_round) + and level_offset = Period_repr.of_seconds_exn level_offset in + let round_duration = + Stdlib.Option.get + (Round_repr.Durations.create_opt + ~first_round_duration + ~delay_increment_per_round) + in + let@ expected = round_and_offset_oracle round_duration ~level_offset in + let computed = + Round_repr.Internal_for_tests.round_and_offset + round_duration + ~level_offset + in + match (computed, expected) with + | Error _, Error _ -> return_unit + | Ok {round; offset}, Ok {round = round'; offset = offset'} -> + let* () = + Assert.equal_int32 + ~loc:__LOC__ + (Round_repr.to_int32 round) + (Round_repr.to_int32 round') + in + Assert.equal_int64 + ~loc:__LOC__ + (Period_repr.to_seconds offset) + (Period_repr.to_seconds offset') + | Ok _, Error _ -> failwith "expected error is ok" + | Error _, Ok _ -> failwith "expected ok is error") + +let tests = + Tztest. + [ + tztest "level_offset_of_round" `Quick test_level_offset_of_round; + tztest "Round_duration" `Quick test_round; + tztest "round_of_timestamp" `Quick test_round_of_timestamp; + tztest "round_of_timestamp_perf" `Quick test_round_of_timestamp_perf; + tztest "timestamp_of_round_perf" `Quick test_timestamp_of_round_perf; + tztest + "level offset too high error is triggered" + `Quick + test_error_is_triggered_for_too_high_timestamp; + tztest "round_of_ts (ts_of_round r) = r" `Quick test_ts_of_round_inverse; + tztest + "ts_of_round (round_of_ts ts) <= ts" + `Quick + test_round_of_ts_inverse; + test_round_and_offset_correction; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("round", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_saturation.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_saturation.ml new file mode 100644 index 000000000000..fc5abb60058f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_saturation.ml @@ -0,0 +1,267 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (saturated arithmetic) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_saturation.ml + Subject: The gas is represented using saturated arithmetic. + These unit tests check that saturated arithmetic operations + are correctly implemented. +*) + +open Protocol + +let valid (z : _ Saturation_repr.t) = + let x = z |> Saturation_repr.to_int in + x >= 0 && x < max_int + +exception Saturating_test_error of string + +let err x = Exn (Saturating_test_error x) + +let small_enough (z : _ Saturation_repr.t) = + Saturation_repr.(Compare.Int.((z |> to_int) land 0x7fffffff80000000 = 0)) + +let ok_int x = + match Saturation_repr.of_int_opt x with None -> assert false | Some x -> x + +let n = ok_int 123123 + +let m = ok_int 377337 + +let add () = + let open Lwt_result_syntax in + Saturation_repr.( + let* () = + fail_unless + (add saturated (ok_int 1) = saturated) + (err "saturated + 1 <> saturated") + in + let* () = fail_unless (add zero n = n) (err "zero + n <> n") in + let* () = fail_unless (add n zero = n) (err "n + zero <> n") in + let r = add n m in + fail_unless + (valid r && r = ok_int ((n |> to_int) + (m |> to_int))) + (err "add does not behave like + on small numbers.")) + +let sub () = + let open Lwt_result_syntax in + Saturation_repr.( + let* () = fail_unless (sub zero n = zero) (err "zero - n <> zero") in + let n = max n m and m = min n m in + let r = sub n m in + fail_unless + (valid r && r = ok_int ((n |> to_int) - (m |> to_int))) + (err "sub does not behave like - on small numbers.")) + +let mul_safe_of_int x = + Saturation_repr.( + match mul_safe (ok_int x) with Some x -> x | None -> assert false) + +let n' = mul_safe_of_int 1000 + +let m' = mul_safe_of_int 10000 + +let mul_fast () = + let open Lwt_result_syntax in + Saturation_repr.( + let* () = + fail_unless (mul_fast zero n' = zero) (err "mul_fast zero x <> zero") + in + let* () = + fail_unless (mul_fast n' zero = zero) (err "mul_fast x zero <> zero") + in + let r = mul_fast n' m' in + fail_unless + (valid r && r = ok_int ((n' |> to_int) * (m' |> to_int))) + (err "mul_fast does not behave like * on small numbers.")) + +let scale_fast () = + let open Lwt_result_syntax in + Saturation_repr.( + let* () = + fail_unless (scale_fast zero n = zero) (err "scale_fast zero x <> zero") + in + let* () = + fail_unless (scale_fast n' zero = zero) (err "scale_fast x zero <> zero") + in + let* () = + fail_unless + (scale_fast n' saturated = saturated) + (err "scale_fast x saturated <> saturated") + in + let r = scale_fast n' m in + fail_unless + (valid r && r = ok_int ((n' |> to_int) * (m |> to_int))) + (err "mul_fast does not behave like * on small numbers.")) + +let mul () = + let open Lwt_result_syntax in + Saturation_repr.( + let* () = + fail_unless + (mul saturated saturated = saturated) + (err "saturated * saturated <> saturated") + in + let* () = + fail_unless (mul zero saturated = zero) (err "zero * saturated <> zero") + in + let* () = + fail_unless (mul saturated zero = zero) (err "saturated * zero <> zero") + in + let max_squared = ok_int (1 lsl 31) in + let r = mul max_squared max_squared in + let* () = + fail_unless (r = saturated) (err "2 ^ 31 * 2 ^ 31 should be saturated") + in + let safe_squared = ok_int ((1 lsl 31) - 1) in + let r = mul safe_squared safe_squared in + let* () = + fail_unless + (valid r && r <> saturated) + (err "(2 ^ 31 - 1) * (2 ^ 31 - 1) should not be saturated") + in + let r = mul n m in + fail_unless + (valid r && r = ok_int ((n |> to_int) * (m |> to_int))) + (err "mul does not behave like * on small numbers.")) + +let shift_left () = + let open Lwt_result_syntax in + Saturation_repr.( + let must_saturate flag (k, v) = + fail_unless + (Bool.equal flag (shift_left k v = saturated)) + (err + (Printf.sprintf + "shift_left %d %d %s saturated" + (k |> to_int) + v + (if flag then "<>" else "="))) + in + let* () = + List.iter_es + (must_saturate true) + [(saturated, 1); (shift_right saturated 1, 2); (ok_int 1, 62)] + in + List.iter_es + (must_saturate false) + [ + (ok_int 1, 0); + (ok_int 1, 31); + (ok_int 1, 61); + (ok_int 0, 99); + (ok_int ((1 lsl 62) - 2), 0); + ]) + +let sqrt () = + let open Lwt_result_syntax in + Saturation_repr.( + let* () = + fail_unless + (sqrt saturated = saturated) + (err "sqrt saturated <> saturated") + in + let* () = fail_unless (sqrt zero = zero) (err "sqrt zero <> zero") in + let* () = fail_unless (sqrt one = one) (err "sqrt one <> one") in + let* () = fail_unless (sqrt (ok_int 4) = ok_int 2) (err "sqrt 4 <> 2") in + let* () = + fail_unless + (sqrt (ok_int 5) = ok_int 2) + (err "sqrt 5 <> 2 (sqrt should round down)") + in + let safe_squared = ok_int ((1 lsl 31) - 1) in + let r = mul safe_squared safe_squared in + fail_unless + (sqrt r = safe_squared) + (err "sqrt (2 ^ 31 - 1) * (2 ^ 31 - 1) <> (2 ^ 31 - 1)")) + +let of_z_opt () = + let open Lwt_result_syntax in + let* () = + fail_unless + (Saturation_repr.(of_z_opt (Z.succ (Z.of_int max_int))) = None) + (err + "of_z_opt should saturate when given a z integer greater than max_int.") + in + let* () = + fail_unless + (Saturation_repr.(of_z_opt (Z.pred Z.zero)) = None) + (err "of_z_opt should fail on a z negative integer.") + in + fail_unless + (Saturation_repr.(of_z_opt (Z.of_int min_int)) = None) + (err "of_z_opt should fail on a z negative integer.") + +let encoding encoder () = + let open Lwt_result_syntax in + let check_encode_decode x = + Data_encoding.Binary.( + match to_bytes encoder (ok_int x) with + | Error _ -> + tzfail (err (Printf.sprintf "Problem during binary encoding of %d" x)) + | Ok bytes -> ( + match of_bytes encoder bytes with + | Error _ -> + tzfail + (err (Printf.sprintf "Problem during binary decoding of %d" x)) + | Ok x' -> + fail_unless + (ok_int x = x') + (err + (Printf.sprintf + "decode (encode %d) = %d <> %d" + x + (x' :> int) + x)))) + in + Error_monad.Lwt_result_syntax.tzjoin + (List.map check_encode_decode [0; 7373737373; max_int - 1]) + +let tests = + [ + Tztest.tztest "Addition" `Quick add; + Tztest.tztest "Subtraction" `Quick sub; + Tztest.tztest "Multiplication" `Quick mul; + Tztest.tztest "Multiplication (fast version)" `Quick mul_fast; + Tztest.tztest "Shift left" `Quick shift_left; + Tztest.tztest "Scale fast" `Quick scale_fast; + Tztest.tztest "Square root" `Quick sqrt; + Tztest.tztest "Conversion from Z" `Quick of_z_opt; + Tztest.tztest + "Encoding through z" + `Quick + (encoding Saturation_repr.z_encoding); + Tztest.tztest + "Encoding through n" + `Quick + (encoding Saturation_repr.n_encoding); + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("saturation arithmetic", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_arith.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_arith.ml new file mode 100644 index 000000000000..c2afb1e3785d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_arith.ml @@ -0,0 +1,813 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (saturated arithmetic) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_sc_rollup_arith.ml + Subject: Basic testing of the arithmetic rollup example +*) + +open Protocol +module Context_binary = Tezos_context_memory.Context_binary + +(* We first instantiate an arithmetic PVM capable of generating proofs. *) +module Tree : + Environment.Context.TREE + with type t = Context_binary.t + and type tree = Context_binary.tree + and type key = string list + and type value = bytes = struct + type t = Context_binary.t + + type tree = Context_binary.tree + + type key = Context_binary.key + + type value = Context_binary.value + + include Context_binary.Tree +end + +module Arith_Context = struct + module Tree = Tree + + type tree = Tree.tree + + let hash_tree tree = + Sc_rollup_repr.State_hash.context_hash_to_state_hash (Tree.hash tree) + + type proof = Context_binary.Proof.tree Context_binary.Proof.t + + let proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 + .tree_proof_encoding + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> + Sc_rollup_repr.State_hash.context_hash_to_state_hash hash + + let proof_before proof = + kinded_hash_to_state_hash proof.Context_binary.Proof.before + + let proof_after proof = + kinded_hash_to_state_hash proof.Context_binary.Proof.after + + let produce_proof context tree step = + let open Lwt_syntax in + (* FIXME: With on-disk context, we cannot commit the empty + context. Is it also true in our case? *) + let* context = Context_binary.add_tree context [] tree in + let* (_hash : Context_hash.t) = + Context_binary.commit ~time:Time.Protocol.epoch context + in + let index = Context_binary.index context in + match Context_binary.Tree.kinded_key tree with + | Some k -> + let* p = Context_binary.produce_tree_proof index k step in + return_some p + | None -> return_none + + let verify_proof proof step = + let open Lwt_syntax in + let* result = Context_binary.verify_tree_proof proof step in + match result with + | Ok v -> return_some v + | Error _ -> + (* We skip the error analysis here since proof verification is not a + job for the rollup node. *) + return_none +end + +module FullArithPVM = Sc_rollup_arith.Make (Arith_Context) +open FullArithPVM + +let setup boot_sector f = + let open Lwt_syntax in + let* index = Context_binary.init "/tmp" in + let ctxt = Context_binary.empty index in + let empty = Context_binary.Tree.empty ctxt in + let* state = initial_state ~empty in + let* state = install_boot_sector state boot_sector in + f ctxt state + +let pre_boot boot_sector f = + parse_boot_sector boot_sector |> function + | None -> failwith "Invalid boot sector" + | Some boot_sector -> setup boot_sector @@ f + +let test_preboot () = + let open Lwt_result_syntax in + [""; "1"; "1 2 +"] + |> List.iter_es (fun boot_sector -> + pre_boot boot_sector @@ fun _ctxt _state -> return_unit) + +let boot boot_sector f = + let open Lwt_result_syntax in + pre_boot boot_sector @@ fun ctxt state -> + let*! state = eval state in + f ctxt state + +let test_boot () = + let open Lwt_result_syntax in + let open Sc_rollup_helpers.Arith_pvm in + boot "" @@ fun _ctxt state -> + let*! result = + is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + match result with + | Needs_reveal Reveal_metadata -> return_unit + | Initial | Needs_reveal _ | First_after _ -> + failwith "After booting, the machine should be waiting for the metadata." + | No_input_required -> + failwith "After booting, the machine must be waiting for input." + +let test_metadata () = + let open Sc_rollup_helpers.Arith_pvm in + let open Alpha_context in + let open Alpha_context.Sc_rollup in + let open Lwt_result_syntax in + boot "" @@ fun _ctxt state -> + let metadata = + Metadata. + { + address = Sc_rollup_repr.Address.zero; + origination_level = Raw_level.root; + } + in + let input = Reveal (Metadata metadata) in + let*! state = set_input input state in + let*! input_request = + is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + match input_request with + | Initial -> return_unit + | Needs_reveal _ | First_after _ | No_input_required -> + failwith + "After evaluating the metadata, the machine must be in the [Initial] \ + state." + +let test_input_message () = + let open Lwt_result_syntax in + let open Sc_rollup_helpers.Arith_pvm in + boot "" @@ fun _ctxt state -> + let input = Sc_rollup_helpers.make_external_input "MESSAGE" in + let*! state = set_input input state in + let*! state = eval state in + let*! result = + is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + match result with + | Initial | Needs_reveal _ | First_after _ -> + failwith + "After receiving a message, the rollup must not be waiting for input." + | No_input_required -> return_unit + +let go ?(is_reveal_enabled = fun ~current_block_level:_ _ -> true) ~max_steps + target_status state = + let open Lwt_result_syntax in + let rec aux i state = + let*! pp = pp state in + Format.eprintf "%a" pp () ; + if i > max_steps then + failwith "Maximum number of steps reached before target status." + else + let*! current_status = get_status ~is_reveal_enabled state in + if target_status = current_status then return state + else + let*! state = eval state in + aux (i + 1) state + in + aux 0 state + +let test_parsing_message ~valid (source, expected_code) = + let open Lwt_result_syntax in + boot "" @@ fun _ctxt state -> + let input = Sc_rollup_helpers.make_external_input_repr source in + let*! state = set_input input state in + let*! state = eval state in + let* state = go ~max_steps:10000 Evaluating state in + let*! result = get_parsing_result state in + let* () = + Assert.equal + ~loc:__LOC__ + (Option.equal Bool.equal) + "Unexpected parsing result" + (fun fmt r -> + Format.fprintf + fmt + (match r with + | None -> "No parsing running" + | Some true -> "Syntax correct" + | Some false -> "Syntax error")) + (Some valid) + result + in + if valid then + let*! code = get_code state in + Assert.equal + ~loc:__LOC__ + (List.equal equal_instruction) + "The parsed code is not what we expected: " + (Format.pp_print_list pp_instruction) + expected_code + code + else return_unit + +let syntactically_valid_messages = + List.map + (fun nums -> + ( String.concat " " (List.map string_of_int nums), + List.map (fun x -> IPush x) nums )) + [[0]; [42]; [373]; [0; 1]; [0; 123; 42; 73; 34; 13; 31]] + @ [ + ("1 2 +", [IPush 1; IPush 2; IAdd]); + ( "1 2 3 + + 3 +", + [IPush 1; IPush 2; IPush 3; IAdd; IAdd; IPush 3; IAdd] ); + ("1 2+", [IPush 1; IPush 2; IAdd]); + ("1 2 3++3+", [IPush 1; IPush 2; IPush 3; IAdd; IAdd; IPush 3; IAdd]); + ("", []); + ("1 a", [IPush 1; IStore "a"]); + ] + +let syntactically_invalid_messages = + List.map + (fun s -> (s, [])) + ["@"; " @"; " @ "; "---"; "12 +++ --"; "1a"; "a$"] + +let test_parsing_messages () = + let open Lwt_result_syntax in + let* () = + List.iter_es (test_parsing_message ~valid:true) syntactically_valid_messages + in + List.iter_es + (test_parsing_message ~valid:false) + syntactically_invalid_messages + +let test_evaluation_message ~valid + (boot_sector, source, expected_stack, expected_vars) = + let open Lwt_result_syntax in + boot boot_sector @@ fun _ctxt state -> + let input = Sc_rollup_helpers.make_external_input_repr source in + let*! state = set_input input state in + let*! state = eval state in + let* state = go ~max_steps:10000 Waiting_for_input_message state in + if valid then + let*! stack = get_stack state in + let* () = + Assert.equal + ~loc:__LOC__ + (List.equal Compare.Int.equal) + "The stack is not what we expected: " + Format.(pp_print_list (fun fmt -> fprintf fmt "%d;@;")) + expected_stack + stack + in + List.iter_es + (fun (x, v) -> + let*! result = get_var state x in + match result with + | None -> failwith "The variable %s cannot be found." x + | Some v' -> + Assert.equal + ~loc:__LOC__ + Compare.Int.equal + (Printf.sprintf "The variable %s has not the right value: " x) + (fun fmt x -> Format.fprintf fmt "%d" x) + v + v') + expected_vars + else + let*! result = get_evaluation_result state in + match result with + | Some true -> failwith "This code should lead to an evaluation error." + | None -> failwith "We should have reached the evaluation end." + | Some false -> return_unit + +let valid_messages = + [ + ("", "0", [0], []); + ("", "1 2", [2; 1], []); + ("", "1 2 +", [3], []); + ("", "1 2 + 3 +", [6], []); + ("", "1 2 + 3 + 1 1 + +", [8], []); + ("0 ", "", [0], []); + ("1 ", "2", [2; 1], []); + ("1 2 ", "+", [3], []); + ("1 2 + ", "3 +", [6], []); + ("1 2 + ", "3 + 1 1 + +", [8], []); + ("", "1 a", [1], [("a", 1)]); + ("", "1 a 2 + b 3 +", [6], [("a", 1); ("b", 3)]); + ("", "1 a 2 + b 3 + result", [6], [("a", 1); ("b", 3); ("result", 6)]); + ("1 a ", "2 b", [2; 1], [("a", 1); ("b", 2)]); + ("1 a ", "2 a", [2; 1], [("a", 2)]); + ("", "1 a 2 a + a", [3], [("a", 3)]); + ("", "1 a b", [1], [("a", 1); ("b", 1)]); + ("1 a", "", [1], [("a", 1)]); + ] + +let invalid_messages = + List.map + (fun s -> ("", s, [], [])) + ["+"; "1 +"; "1 1 + +"; "1 1 + 1 1 + + +"; "a"] + +let test_evaluation_messages () = + let open Lwt_result_syntax in + let* () = List.iter_es (test_evaluation_message ~valid:true) valid_messages in + List.iter_es (test_evaluation_message ~valid:false) invalid_messages + +let boot_then_reveal_metadata sc_rollup_address origination_level + ~is_reveal_enabled = + let open Sc_rollup_PVM_sig in + let open Lwt_result_syntax in + boot "" @@ fun _ctxt state -> + let metadata = + Sc_rollup_metadata_repr.{address = sc_rollup_address; origination_level} + in + let input = Reveal (Metadata metadata) in + let*! state = set_input input state in + let*! input_state = is_input_state ~is_reveal_enabled state in + match input_state with + | Initial -> return state + | No_input_required | Needs_reveal _ | First_after _ -> + failwith + "After booting, the machine should be waiting for the initial input." + +let test_reveal ~threshold ~inbox_level ~hash ~preimage_reveal_step + ~hash_reveal_step () = + let open Lwt_result_syntax in + let blake2B = Protocol.Raw_level_repr.of_int32_exn threshold in + let inbox_level = Protocol.Raw_level_repr.of_int32_exn inbox_level in + let reveal_enabled : + Constants_parametric_repr.sc_rollup_reveal_activation_level = + { + raw_data = {blake2B}; + metadata = Protocol.Raw_level_repr.root; + dal_page = Protocol.Raw_level_repr.root; + dal_parameters = Protocol.Raw_level_repr.root; + dal_attested_slots_validity_lag = 241_920; + (* 4 weeks with a 10 secs block time. *) + } + in + let is_reveal_enabled = + Sc_rollup_PVM_sig.is_reveal_enabled_predicate reveal_enabled + in + let* state = + boot_then_reveal_metadata + Sc_rollup_repr.Address.zero + Raw_level_repr.root + ~is_reveal_enabled + in + let* state = go ~max_steps:10_000 Waiting_for_input_message state in + let source = "hash:" ^ Sc_rollup_reveal_hash.to_hex hash in + let input = Sc_rollup_helpers.make_external_input_repr ~inbox_level source in + let*! state = set_input input state in + let* state = + go + ~is_reveal_enabled + ~max_steps:10_000 + (Waiting_for_reveal (Reveal_raw_data hash_reveal_step)) + state + in + let*! state = set_input (Reveal (Raw_data preimage_reveal_step)) state in + go ~max_steps:10_000 Waiting_for_input_message state + +let test_reveal_disabled ~threshold ~inbox_level () = + let open Lwt_result_wrap_syntax in + let preimage = "1 1 +" in + let hash = Sc_rollup_reveal_hash.(hash_string ~scheme:Blake2B [preimage]) in + let* state = + test_reveal + ~threshold + ~inbox_level + ~hash + ~hash_reveal_step:Sc_rollup_reveal_hash.well_known_reveal_hash + ~preimage_reveal_step:Sc_rollup_reveal_hash.well_known_reveal_preimage + () + in + let*! stack = get_stack state in + match stack with + | [] -> return_unit + | l -> + failwith + "Expected empty stack, got: %a" + (Format.pp_print_list Format.pp_print_int) + l + +let test_reveal_enabled ~threshold ~inbox_level () = + let open Lwt_result_wrap_syntax in + let preimage = "1 1 +" in + let hash = Sc_rollup_reveal_hash.(hash_string ~scheme:Blake2B [preimage]) in + let* state = + test_reveal + ~threshold + ~inbox_level + ~hash + ~hash_reveal_step:hash + ~preimage_reveal_step:preimage + () + in + let*! stack = get_stack state in + match stack with [2] -> return_unit | _ -> failwith "invalid stack" + +let test_output_messages_proofs ~valid ~inbox_level (source, expected_outputs) = + let open Lwt_result_syntax in + boot "" @@ fun ctxt state -> + let input = + Sc_rollup_helpers.make_external_input_repr + ~inbox_level:(Raw_level_repr.of_int32_exn (Int32.of_int inbox_level)) + source + in + let*! state = set_input input state in + let*! state = eval state in + let* state = go ~max_steps:10000 Waiting_for_input_message state in + let check_output output = + let*! result = produce_output_proof ctxt state output in + if valid then + match result with + | Ok proof -> + let*! output = verify_output_proof proof in + fail_unless + (Result.is_ok output) + (Exn (Failure "An output proof is not valid.")) + | Error _ -> failwith "Error during proof generation" + else + match result with + | Ok proof -> + let*! proof_is_valid = verify_output_proof proof in + fail_when + (Result.is_ok proof_is_valid) + (Exn + (Failure + (Format.asprintf + "A wrong output proof is valid: %s -> %a" + source + Sc_rollup_PVM_sig.pp_output + output))) + | Error _ -> return_unit + in + List.iter_es check_output expected_outputs + +let make_output ~outbox_level ~message_index n = + let open Sc_rollup_outbox_message_repr in + let unparsed_parameters = + Micheline.(Int (dummy_location, Z.of_int n) |> strip_locations) + in + let destination = Contract_hash.zero in + let entrypoint = Entrypoint_repr.default in + let transaction = {unparsed_parameters; destination; entrypoint} in + let transactions = [transaction] in + let message_index = Z.of_int message_index in + let outbox_level = Raw_level_repr.of_int32_exn (Int32.of_int outbox_level) in + let message = Atomic_transaction_batch {transactions} in + Sc_rollup_PVM_sig.{outbox_level; message_index; message} + +let test_valid_output_messages () = + let test inbox_level = + let outbox_level = inbox_level in + [ + ("1", []); + ("1 out", [make_output ~outbox_level ~message_index:0 1]); + ( "1 out 2 out", + [ + make_output ~outbox_level ~message_index:0 1; + make_output ~outbox_level ~message_index:1 2; + ] ); + ( "1 out 1 1 + out", + [ + make_output ~outbox_level ~message_index:0 1; + make_output ~outbox_level ~message_index:1 2; + ] ); + ( "1 out 1 1 + out out", + [ + make_output ~outbox_level ~message_index:0 1; + make_output ~outbox_level ~message_index:1 2; + make_output ~outbox_level ~message_index:2 2; + ] ); + ] + |> List.iter_es (test_output_messages_proofs ~valid:true ~inbox_level) + in + (* Test for different inbox/outbox levels. *) + List.iter_es test [0; 1; 2345] + +let test_invalid_output_messages () = + let inbox_level = 0 in + let outbox_level = inbox_level in + [ + ("1", [make_output ~outbox_level ~message_index:0 1]); + ("1 out", [make_output ~outbox_level ~message_index:1 1]); + ( "1 out 1 1 + out", + [ + make_output ~outbox_level ~message_index:0 0; + make_output ~outbox_level ~message_index:3 2; + ] ); + ( "1 out 1 1 + out out", + [ + make_output ~outbox_level ~message_index:0 42; + make_output ~outbox_level ~message_index:1 32; + make_output ~outbox_level ~message_index:2 13; + ] ); + ] + |> List.iter_es (test_output_messages_proofs ~valid:false ~inbox_level) + +let test_invalid_outbox_level () = + let inbox_level = 42 in + let outbox_level = inbox_level - 1 in + [ + ("1", []); + ("1 out", [make_output ~outbox_level ~message_index:0 1]); + ( "1 out 2 out", + [ + make_output ~outbox_level ~message_index:0 1; + make_output ~outbox_level ~message_index:1 2; + ] ); + ] + |> List.iter_es (test_output_messages_proofs ~valid:false ~inbox_level) + +let dummy_internal_transfer address = + let open Lwt_result_wrap_syntax in + let open Alpha_context.Sc_rollup in + let* ctxt = + let* block, _baker, _contract, _src2 = Contract_helpers.init () in + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + in + let sender = + Contract_hash.of_b58check_exn "KT1BuEZtb68c1Q4yjtckcNjGELqWt56Xyesc" + in + let source = + WithExceptions.Result.get_ok + ~loc:__LOC__ + (Signature.Public_key_hash.of_b58check + "tz1RjtZUVeLhADFHDL8UwDZA6vjWWhojpu5w") + in + let payload = Bytes.of_string "foo" in + let*! result = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized + Bytes_t + payload + in + let*?@ payload, _ctxt = result in + let transfer = + Inbox_message.Internal + (Transfer {payload; sender; source; destination = address}) + in + let*?@ serialized_transfer = Inbox_message.serialize transfer in + return serialized_transfer + +let test_filter_internal_message () = + let open Sc_rollup_PVM_sig in + let open Lwt_result_syntax in + boot "" @@ fun _ctxt state -> + let address = Sc_rollup_repr.Address.zero in + let metadata = + Sc_rollup_metadata_repr.{address; origination_level = Raw_level_repr.root} + in + let input = Reveal (Metadata metadata) in + let*! state = set_input input state in + + (* We will set an input where the destination is the same as the one given + in the static metadata. The pvm should process the input. *) + let* () = + let open Sc_rollup_helpers.Arith_pvm in + let open Alpha_context in + let open Alpha_context.Sc_rollup in + let* internal_transfer = dummy_internal_transfer address in + let input = + Inbox_message + { + inbox_level = Raw_level.root; + message_counter = Z.zero; + payload = internal_transfer; + } + in + let*! state = set_input input state in + let*! input_state = + is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + match input_state with + | No_input_required -> return_unit + | _ -> failwith "The arith pvm should be processing the internal transfer" + in + + (* We will set an input where the destination is *not* the same as the + one given in the static metadata. The pvm should ignore the input. *) + let* () = + let open Sc_rollup_helpers.Arith_pvm in + let open Alpha_context in + let open Alpha_context.Sc_rollup in + let dummy_address = + Sc_rollup_repr.Address.of_b58check_exn + "sr1Fq8fPi2NjhWUXtcXBggbL6zFjZctGkmso" + in + let* internal_transfer = dummy_internal_transfer dummy_address in + let input = + Inbox_message + { + inbox_level = Raw_level.root; + message_counter = Z.zero; + payload = internal_transfer; + } + in + let*! state = set_input input state in + let*! input_state = + is_input_state + ~is_reveal_enabled:Sc_rollup_helpers.is_reveal_enabled_default + state + in + match input_state with + | No_input_required -> + failwith "The arith pvm should avoid ignored the internal transfer" + | _ -> return_unit + in + + return_unit + +module Arith_pvm = Sc_rollup_helpers.Arith_pvm + +(** Instructs the PVM to reveal [hashed_preimage], and providing + [input_preimage] when required. The proof for the reveal step + is generated and then verified. *) +let test_serialized_reveal_proof ~hashed_preimage ~input_preimage () = + let open Lwt_result_wrap_syntax in + let open Alpha_context in + let rollup = Sc_rollup.Address.zero in + let level = Raw_level.root in + + let*? inbox = + Sc_rollup_helpers.Node_inbox.new_inbox ~inbox_creation_level:level () + in + let snapshot = Sc_rollup.Inbox.take_snapshot inbox.inbox in + let dal_snapshot = Dal.Slots_history.genesis in + let constants = Default_parameters.constants_mainnet in + let dal_parameters = constants.dal in + let dal_activation_level = + if constants.dal.feature_enable then + Some constants.sc_rollup.reveal_activation_level.dal_parameters + else None + in + let dal_attested_slots_validity_lag = + constants.sc_rollup.reveal_activation_level.dal_attested_slots_validity_lag + in + let ctxt = Sc_rollup_helpers.Arith_pvm.make_empty_context () in + + let is_reveal_enabled = Sc_rollup_helpers.is_reveal_enabled_default in + let metadata = + Sc_rollup.Metadata.{address = rollup; origination_level = level} + in + let reveal_hash = + Sc_rollup_reveal_hash.( + hash_string ~scheme:Blake2B [hashed_preimage] |> to_hex) + in + + let source = "hash:" ^ reveal_hash in + let input = + Sc_rollup_helpers.make_external_input ~inbox_level:inbox.inbox.level source + in + let* state, _, _ = + Sc_rollup_helpers.Arith_pvm_eval.eval_inputs_from_initial_state + ~metadata + [[input]] + in + + let pvm_with_context_and_state = + Sc_rollup_helpers.make_pvm_with_context_and_state + (module Arith_pvm) + ~state + ~context:ctxt + ~reveal:(fun _ -> Lwt.return_some input_preimage) + ~inbox + () + in + let*@ proof = + Sc_rollup.Proof.produce + ~metadata + pvm_with_context_and_state + Raw_level.root + ~is_reveal_enabled + in + let*?@ pvm_step = + Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module Arith_pvm) proof.pvm_step + in + + wrap + @@ Sc_rollup.Proof.valid + ~pvm:(module Arith_pvm) + ~metadata + snapshot + Raw_level.root + dal_snapshot + dal_parameters.cryptobox_parameters + ~dal_activation_level + ~dal_attested_slots_validity_lag + ~dal_attestation_lag:dal_parameters.attestation_lag + ~dal_number_of_slots:dal_parameters.number_of_slots + ~is_reveal_enabled + {proof with pvm_step} + +(** Test that sending a invalid serialized reveal proof to + {Sc_rollup_proof_repr.valid} is rejected. *) +let test_invalid_serialized_reveal_proof () : (unit, tztrace) result Lwt.t = + let open Lwt_result_syntax in + let*! check = + test_serialized_reveal_proof + ~hashed_preimage:"preimage" + ~input_preimage:"wrong preimage" + () + in + Assert.proto_error + ~loc:__LOC__ + check + (( = ) (Sc_rollup_proof_repr.Sc_rollup_proof_check "Invalid reveal")) + +(** Test that sending a valid serialized reveal proof to + {Sc_rollup_proof_repr.valid} is accepted. *) +let test_valid_serialized_reveal_proof () : (unit, tztrace) result Lwt.t = + let open Lwt_result_syntax in + let hashed_preimage = "preimage" in + let*! _check = + test_serialized_reveal_proof + ~hashed_preimage + ~input_preimage:hashed_preimage + () + in + return_unit + +let tests = + [ + Tztest.tztest "PreBoot" `Quick test_preboot; + Tztest.tztest "Boot" `Quick test_boot; + Tztest.tztest "Metadata" `Quick test_metadata; + Tztest.tztest "Input message" `Quick test_input_message; + Tztest.tztest "Parsing message" `Quick test_parsing_messages; + Tztest.tztest "Evaluating message" `Quick test_evaluation_messages; + Tztest.tztest "Valid output messages" `Quick test_valid_output_messages; + Tztest.tztest "Invalid output messages" `Quick test_invalid_output_messages; + Tztest.tztest "Invalid outbox level" `Quick test_invalid_outbox_level; + Tztest.tztest "Filter internal message" `Quick test_filter_internal_message; + Tztest.tztest + "Reveal below threshold" + `Quick + (test_reveal_disabled ~threshold:10_000l ~inbox_level:1_000l); + Tztest.tztest + "Reveal at threshold (block level zero)" + `Quick + (test_reveal_enabled ~threshold:0l ~inbox_level:0l); + Tztest.tztest + "Reveal below threshold (block level zero)" + `Quick + (test_reveal_disabled ~threshold:10_000l ~inbox_level:0l); + Tztest.tztest + "Reveal at threshold" + `Quick + (test_reveal_enabled ~threshold:10_000l ~inbox_level:10_000l); + Tztest.tztest + "Reveal above threshold" + `Quick + (test_reveal_enabled ~threshold:10_000l ~inbox_level:10_001l); + Tztest.tztest + "Invalid serialized reveal proof" + `Quick + test_invalid_serialized_reveal_proof; + Tztest.tztest + "Valid serialized reveal proof" + `Quick + test_valid_serialized_reveal_proof; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup arith", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_game.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_game.ml new file mode 100644 index 000000000000..74e449f36d15 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_game.ml @@ -0,0 +1,489 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Sc_rollup_refutation_storage + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_sc_rollup_game.ml + Subject: Tests for the SCORU refutation game +*) + +open Protocol +module Commitment_repr = Sc_rollup_commitment_repr +module T = Test_sc_rollup_storage +module R = Sc_rollup_refutation_storage +module D = Sc_rollup_dissection_chunk_repr +module G = Sc_rollup_game_repr +module Tick = Sc_rollup_tick_repr + +(** Assert that the computation fails with the given error. *) +let assert_fails_with ~__LOC__ k expected_err = + let open Lwt_result_syntax in + let*! res = k in + Assert.proto_error ~loc:__LOC__ res (( = ) expected_err) + +let assert_fails_with_f ~__LOC__ k f = + let open Lwt_result_syntax in + let*! res = k in + Assert.proto_error ~loc:__LOC__ res f + +let tick_of_int_exn n = + match Tick.of_int n with None -> assert false | Some t -> t + +let context_hash_of_string s = Context_hash.hash_string [s] + +let hash_string s = + Sc_rollup_repr.State_hash.context_hash_to_state_hash + @@ context_hash_of_string s + +let hash_int n = hash_string (Format.sprintf "%d" n) + +let mk_dissection_chunk (state_hash, tick) = D.{state_hash; tick} + +let init_dissection ~size ?init_tick start_hash = + let default_init_tick i = + let hash = + if i = size - 1 then None + else Some (if i = 0 then start_hash else hash_int i) + in + mk_dissection_chunk (hash, tick_of_int_exn i) + in + let init_tick = + Option.fold + ~none:default_init_tick + ~some:(fun init_tick -> init_tick size) + init_tick + in + Stdlib.List.init (size + 1) init_tick + +let init_refutation ~size ?init_tick start_hash = + let choice = Sc_rollup_tick_repr.initial in + let step = G.Dissection (init_dissection ~size ?init_tick start_hash) in + (choice, step) + +let two_stakers_in_conflict () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, refuter, defender, staker3 = + T.originate_rollup_and_deposit_with_three_stakers () + in + let hash1 = hash_string "foo" in + let hash2 = hash_string "bar" in + let hash3 = hash_string "xyz" in + let parent_commit = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = T.valid_inbox_level ctxt 1l; + number_of_ticks = T.number_of_ticks_exn 152231L; + compressed_state = hash1; + } + in + let level l = T.valid_inbox_level ctxt l in + let*@ parent, _, ctxt = + T.advance_level_n_refine_stake ctxt rollup defender parent_commit + in + let child1 = + Commitment_repr. + { + predecessor = parent; + inbox_level = level 2l; + number_of_ticks = T.number_of_ticks_exn 10000L; + compressed_state = hash2; + } + in + let child2 = + Commitment_repr. + { + predecessor = parent; + inbox_level = level 2l; + number_of_ticks = T.number_of_ticks_exn 10000L; + compressed_state = hash3; + } + in + let ctxt = T.advance_level_for_commitment ctxt child1 in + let*@ _, _, ctxt, _ = + Sc_rollup_stake_storage.publish_commitment ctxt rollup defender child1 + in + let*@ _, _, ctxt, _ = + Sc_rollup_stake_storage.publish_commitment ctxt rollup refuter child2 + in + let defender_commitment_hash = + Sc_rollup_commitment_repr.hash_uncarbonated child1 + in + let refuter_commitment_hash = + Sc_rollup_commitment_repr.hash_uncarbonated child2 + in + return + ( ctxt, + rollup, + refuter, + defender, + staker3, + refuter_commitment_hash, + defender_commitment_hash ) + +(** A dissection is 'poorly distributed' if its tick counts are not +very evenly spread through the total tick-duration. Formally, the +maximum tick-distance between two consecutive states in a dissection +may not be more than half of the total tick-duration. *) +let test_poorly_distributed_dissection () = + let open Lwt_result_wrap_syntax in + let* ( ctxt, + rollup, + refuter, + defender, + _staker3, + refuter_commitment_hash, + defender_commitment_hash ) = + two_stakers_in_conflict () + in + let start_hash = hash_string "foo" in + let init_tick size i = + mk_dissection_chunk + @@ + if i = size then (None, tick_of_int_exn 10000) + else (Some (if i = 0 then start_hash else hash_int i), tick_of_int_exn i) + in + let player = refuter and opponent = defender in + let player_commitment_hash = refuter_commitment_hash + and opponent_commitment_hash = defender_commitment_hash in + let*@ ctxt = + R.start_game + ctxt + rollup + ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash) + in + let size = + Constants_storage.sc_rollup_number_of_sections_in_dissection ctxt + in + let choice, step = init_refutation ~size ~init_tick start_hash in + let*!@ res = + R.game_move ctxt rollup ~player:refuter ~opponent:defender ~step ~choice + in + assert_fails_with_f ~__LOC__ (Lwt.return res) (function + | D.Dissection_invalid_distribution _ -> true + | _ -> false) + +let test_single_valid_game_move () = + let open Lwt_result_wrap_syntax in + let* ( ctxt, + rollup, + refuter, + defender, + _staker3, + refuter_commitment_hash, + defender_commitment_hash ) = + two_stakers_in_conflict () + in + let start_hash = hash_string "foo" in + let size = + Constants_storage.sc_rollup_number_of_sections_in_dissection ctxt + in + let tick_per_state = 10_000 / size in + let dissection = + Stdlib.List.init (size + 1) (fun i -> + mk_dissection_chunk + @@ + if i = 0 then (Some start_hash, tick_of_int_exn 0) + else if i = size then (None, tick_of_int_exn 10000) + else (Some (hash_int i), tick_of_int_exn (i * tick_per_state))) + in + let player = refuter and opponent = defender in + let player_commitment_hash = refuter_commitment_hash + and opponent_commitment_hash = defender_commitment_hash in + + let*@ ctxt = + R.start_game + ctxt + rollup + ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash) + in + let choice, step = (Sc_rollup_tick_repr.initial, G.Dissection dissection) in + let*@ game_result, _ctxt = + R.game_move ctxt rollup ~player:refuter ~opponent:defender ~choice ~step + in + Assert.is_none ~loc:__LOC__ ~pp:Sc_rollup_game_repr.pp_game_result game_result + +module Arith_pvm = Sc_rollup_helpers.Arith_pvm + +(** Test that sending a invalid serialized inbox proof to + {Sc_rollup_proof_repr.valid} is rejected. *) +let test_invalid_serialized_inbox_proof () = + let open Lwt_result_wrap_syntax in + let open Alpha_context in + let rollup = Sc_rollup.Address.zero in + let level = Raw_level.(succ root) in + let inbox = Sc_rollup_helpers.dumb_init level in + let snapshot = Sc_rollup.Inbox.take_snapshot inbox in + let dal_snapshot = Dal.Slots_history.genesis in + let constants = Default_parameters.constants_mainnet in + let dal_parameters = constants.dal in + let dal_activation_level = + if constants.dal.feature_enable then + Some constants.sc_rollup.reveal_activation_level.dal_parameters + else None + in + let dal_attested_slots_validity_lag = + constants.sc_rollup.reveal_activation_level.dal_attested_slots_validity_lag + in + let ctxt = Sc_rollup_helpers.Arith_pvm.make_empty_context () in + let empty = Sc_rollup_helpers.Arith_pvm.make_empty_state () in + let*! state = Arith_pvm.initial_state ~empty in + (* We evaluate the boot sector, so the [input_requested] is a + [First_after]. *) + let*! state = Arith_pvm.eval state in + let is_reveal_enabled = Sc_rollup_helpers.is_reveal_enabled_default in + let*! pvm_step = Arith_pvm.produce_proof ctxt ~is_reveal_enabled None state in + let pvm_step = WithExceptions.Result.get_ok ~loc:__LOC__ pvm_step in + + (* We create an obviously invalid inbox *) + let inbox_proof = + Sc_rollup.Inbox.Internal_for_tests.serialized_proof_of_string + "I am the big bad wolf" + in + let inbox_proof = + Sc_rollup.Proof.Inbox_proof + {level = Raw_level.root; message_counter = Z.zero; proof = inbox_proof} + in + let proof = Sc_rollup.Proof.{pvm_step; input_proof = Some inbox_proof} in + + let metadata = + Sc_rollup.Metadata.{address = rollup; origination_level = level} + in + let*!@ res = + Sc_rollup.Proof.valid + ~pvm:(module Arith_pvm) + ~metadata + snapshot + Raw_level.root + dal_snapshot + dal_parameters.cryptobox_parameters + ~dal_activation_level + ~dal_attested_slots_validity_lag + ~dal_attestation_lag:dal_parameters.attestation_lag + ~dal_number_of_slots:dal_parameters.number_of_slots + ~is_reveal_enabled + proof + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) Sc_rollup_proof_repr.Sc_rollup_invalid_serialized_inbox_proof) + +let test_first_move_with_swapped_commitment () = + let open Lwt_result_wrap_syntax in + let* ( ctxt, + rollup, + refuter, + defender, + _staker3, + refuter_commitment_hash, + defender_commitment_hash ) = + two_stakers_in_conflict () + in + let player = refuter + and opponent = defender + and player_commitment_hash = refuter_commitment_hash + and opponent_commitment_hash = defender_commitment_hash in + let*!@ res = + R.start_game + ctxt + rollup + ~player:(player, opponent_commitment_hash) + ~opponent:(opponent, player_commitment_hash) + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) + (Sc_rollup_errors.Sc_rollup_wrong_staker_for_conflict_commitment + (player, opponent_commitment_hash))) + +let test_first_move_from_invalid_player () = + let open Lwt_result_wrap_syntax in + let* ( ctxt, + rollup, + _refuter, + defender, + staker3, + refuter_commitment_hash, + defender_commitment_hash ) = + two_stakers_in_conflict () + in + let opponent = defender + and player_commitment_hash = refuter_commitment_hash + and opponent_commitment_hash = defender_commitment_hash in + let*!@ res = + R.start_game + ctxt + rollup + ~player:(staker3, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash) + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) + (Sc_rollup_errors.Sc_rollup_wrong_staker_for_conflict_commitment + (staker3, player_commitment_hash))) + +let test_first_move_with_invalid_opponent () = + let open Lwt_result_wrap_syntax in + let* ( ctxt, + rollup, + refuter, + _defender, + staker3, + refuter_commitment_hash, + defender_commitment_hash ) = + two_stakers_in_conflict () + in + let player = refuter + and player_commitment_hash = refuter_commitment_hash + and opponent_commitment_hash = defender_commitment_hash in + let*!@ res = + R.start_game + ctxt + rollup + ~player:(player, player_commitment_hash) + ~opponent:(staker3, opponent_commitment_hash) + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) + (Sc_rollup_errors.Sc_rollup_wrong_staker_for_conflict_commitment + (staker3, opponent_commitment_hash))) + +let test_first_move_with_invalid_ancestor () = + let open Lwt_result_wrap_syntax in + let* ( ctxt, + rollup, + refuter, + defender, + _staker3, + refuter_commitment_hash, + defender_commitment_hash ) = + two_stakers_in_conflict () + in + let*@ inbox_level = T.proper_valid_inbox_level (ctxt, rollup) 3 in + let refuter_commitment = + let context_hash11 = hash_string "child11" in + Commitment_repr. + { + predecessor = refuter_commitment_hash; + inbox_level; + number_of_ticks = T.number_of_ticks_exn 10000L; + compressed_state = context_hash11; + } + in + let defender_commitment = + let context_hash21 = hash_string "child21" in + Commitment_repr. + { + predecessor = defender_commitment_hash; + inbox_level; + number_of_ticks = T.number_of_ticks_exn 10000L; + compressed_state = context_hash21; + } + in + let ctxt = T.advance_level_for_commitment ctxt refuter_commitment in + let*@ _, _, ctxt, _ = + Sc_rollup_stake_storage.publish_commitment + ctxt + rollup + refuter + refuter_commitment + in + let*@ _, _, ctxt, _ = + Sc_rollup_stake_storage.publish_commitment + ctxt + rollup + defender + defender_commitment + in + let refuter_commitment_hash = + Sc_rollup_commitment_repr.hash_uncarbonated refuter_commitment + in + let defender_commitment_hash = + Sc_rollup_commitment_repr.hash_uncarbonated defender_commitment + in + let player = refuter + and opponent = defender + and player_commitment_hash = refuter_commitment_hash + and opponent_commitment_hash = defender_commitment_hash in + let*!@ res = + R.start_game + ctxt + rollup + ~player:(player, player_commitment_hash) + ~opponent:(opponent, opponent_commitment_hash) + in + Assert.proto_error + ~loc:__LOC__ + res + (( = ) + (Sc_rollup_errors.Sc_rollup_not_valid_commitments_conflict + (player_commitment_hash, player, opponent_commitment_hash, opponent))) + +let tests = + [ + Tztest.tztest + "A badly distributed dissection is an invalid move." + `Quick + test_poorly_distributed_dissection; + Tztest.tztest + "A single game move with a valid dissection" + `Quick + test_single_valid_game_move; + Tztest.tztest + "Invalid serialized inbox proof is rejected." + `Quick + test_invalid_serialized_inbox_proof; + Tztest.tztest + "start a game with invalid commitment hash (swap commitment)." + `Quick + test_first_move_with_swapped_commitment; + Tztest.tztest + "start a game with invalid commitment hash (op from outsider)." + `Quick + test_first_move_from_invalid_player; + Tztest.tztest + "start a game with invalid commitment hash (opponent is not in game)." + `Quick + test_first_move_with_invalid_opponent; + Tztest.tztest + "start a game with commitment hash that are not the first conflict." + `Quick + test_first_move_with_invalid_ancestor; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup game", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox.ml new file mode 100644 index 000000000000..e6536d6ca2c0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox.ml @@ -0,0 +1,944 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (smart contract rollup inbox) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_sc_rollup_inbox.ml + Subject: These unit tests check the off-line inbox implementation for + smart contract rollups +*) + +open Protocol + +let opt_get ~__LOC__ = WithExceptions.Option.get ~loc:__LOC__ + +open Sc_rollup_helpers + +module Merkelized_payload_hashes = + Alpha_context.Sc_rollup.Inbox_merkelized_payload_hashes + +module Message = Alpha_context.Sc_rollup.Inbox_message +module Inbox = Alpha_context.Sc_rollup.Inbox +open Alpha_context + +let assert_equal_payload ~__LOC__ found (expected : Message.serialized) = + Assert.equal_string + ~loc:__LOC__ + (Message.unsafe_to_string expected) + (Message.unsafe_to_string found) + +let assert_equal_payload_option ~__LOC__ found expected = + Assert.equal + ~loc:__LOC__ + (Option.equal (fun v1 v2 -> + String.equal + (Message.unsafe_to_string v1) + (Message.unsafe_to_string v2))) + "Input returned by the production is not the expected one" + (Format.pp_print_option + ~none:(fun fmt () -> Format.pp_print_string fmt "None") + (fun fmt v -> + Format.fprintf fmt "Some \"%S\"" (Message.unsafe_to_string v))) + found + expected + +let assert_inbox_message ~__LOC__ found expected = + Assert.equal + ~loc:__LOC__ + (Option.equal Sc_rollup.inbox_message_equal) + "Input returns by the production is not the expected one" + (Format.pp_print_option Sc_rollup.pp_inbox_message) + found + expected + +let assert_equal_payload_hash ~__LOC__ found expected = + Assert.equal + ~loc:__LOC__ + Message.Hash.equal + "Protocol hashes aren't equal" + Message.Hash.pp + expected + found + +let assert_merkelized_payload ~__LOC__ ~payload_hash ~index found = + let open Lwt_result_syntax in + let found_payload_hash = Merkelized_payload_hashes.get_payload_hash found in + let found_index = Merkelized_payload_hashes.get_index found in + let* () = + assert_equal_payload_hash ~__LOC__ found_payload_hash payload_hash + in + Assert.equal_z ~loc:__LOC__ found_index index + +let assert_equal_merkelized_payload ~__LOC__ ~found ~expected = + let payload_hash = Merkelized_payload_hashes.get_payload_hash expected in + let index = Merkelized_payload_hashes.get_index expected in + assert_merkelized_payload ~__LOC__ ~payload_hash ~index found + +let assert_merkelized_payload_proof_error ~__LOC__ expected_msg result = + let open Result_wrap_syntax in + let@ result in + Assert.error ~loc:__LOC__ result (function + | Environment.Ecoproto_error + (Sc_rollup_inbox_merkelized_payload_hashes_repr + .Merkelized_payload_hashes_proof_error msg) -> + expected_msg = msg + | _ -> false) + +let verify_merkelized_payload_proof_fails ~__LOC__ expected_msg proof = + assert_merkelized_payload_proof_error ~__LOC__ expected_msg + @@ Merkelized_payload_hashes.verify_proof proof + +let assert_equal_history_proof ~__LOC__ found expected = + Assert.equal + ~loc:__LOC__ + Inbox.equal_history_proof + "history_proof are not equal" + Inbox.pp_history_proof + expected + found + +let assert_inbox_proof_error ~__LOC__ expected_msg result = + let open Result_wrap_syntax in + let@ result in + Assert.error ~loc:__LOC__ result (function + | Environment.Ecoproto_error (Sc_rollup_inbox_repr.Inbox_proof_error msg) + -> + expected_msg = msg + | _ -> false) + +let verify_payloads_proof_fails ~__LOC__ expected_msg proof head_cell_hash + message_counter = + assert_inbox_proof_error ~__LOC__ expected_msg + @@ Inbox.Internal_for_tests.verify_payloads_proof + proof + head_cell_hash + message_counter + +let verify_inclusion_proof_fails ~__LOC__ expected_msg proof snapshot = + assert_inbox_proof_error ~__LOC__ expected_msg + @@ Inbox.Internal_for_tests.verify_inclusion_proof proof snapshot + +let gen_payload_size = QCheck2.Gen.(1 -- 10) + +let gen_payload_string = + let open QCheck2.Gen in + string_size gen_payload_size + +let gen_payload = + let open QCheck2.Gen in + let+ payload = gen_payload_string in + Message.unsafe_of_string payload + +let gen_payloads ?(min_size = 2) ?(max_size = 50) () = + let open QCheck2.Gen in + list_size (min_size -- max_size) gen_payload + +let gen_index_of_payloads ?(max_index_offset = 0) payloads = + let open QCheck2.Gen in + let max_index = List.length payloads - 1 - max_index_offset in + let+ index = 0 -- max_index in + Z.of_int index + +let gen_payloads_and_index ?min_size ?max_size ?max_index_offset () = + let open QCheck2.Gen in + let* payloads = gen_payloads ?min_size ?max_size () in + let* index = gen_index_of_payloads ?max_index_offset payloads in + return (payloads, index) + +let gen_payloads_for_level ?(inbox_level = Raw_level.(succ root)) () = + gen_messages inbox_level gen_payload_string + +let gen_level ?(inbox_creation_level = 0) ~max_level () = + let open QCheck2.Gen in + let+ int_level = inbox_creation_level -- max_level in + Raw_level.of_int32_exn (Int32.of_int int_level) + +let gen_payloads_and_level ?inbox_creation_level ?(max_level = 100_000) () = + let open QCheck2.Gen in + let* inbox_level = gen_level ?inbox_creation_level ~max_level () in + gen_payloads_for_level ~inbox_level () + +let gen_payloads_and_level_and_index ?inbox_creation_level ?max_level () = + let open QCheck2.Gen in + let* payloads_for_level = + gen_payloads_and_level ?inbox_creation_level ?max_level () + in + let* index = gen_index_of_payloads payloads_for_level.messages in + return (payloads_for_level, index) + +let gen_payloads_for_levels ?(inbox_creation_level = 0) ?(max_level = 15) () = + gen_payloads_for_levels + ~start_level:(inbox_creation_level + 1) + ~max_level + gen_payload_string + +let gen_payloads_for_levels_and_level ?inbox_creation_level ?max_level + ?(level_offset = 1) () = + let open QCheck2.Gen in + let* payloads_for_levels = + gen_payloads_for_levels ?inbox_creation_level ?max_level () + in + let* payloads_index = + 0 -- (List.length payloads_for_levels - 1 - level_offset) + in + let payloads = + opt_get ~__LOC__ @@ List.nth payloads_for_levels payloads_index + in + return (payloads_for_levels, payloads.level) + +let gen_level_and_index payloads_for_levels = + let open QCheck2.Gen in + let* payloads_index = 0 -- (List.length payloads_for_levels - 1) in + let payloads = + opt_get ~__LOC__ @@ List.nth payloads_for_levels payloads_index + in + let* index = gen_index_of_payloads payloads.Sc_rollup_helpers.inputs in + return (payloads.level, index) + +let gen_payloads_for_levels_and_level_and_index ?inbox_creation_level ?max_level + () = + let open QCheck2.Gen in + let* payloads_for_levels = + gen_payloads_for_levels ?inbox_creation_level ?max_level () + in + let* level, index = gen_level_and_index payloads_for_levels in + return (payloads_for_levels, level, index) + +let gen_payloads_for_levels_and_two_levels_and_two_indexes ?inbox_creation_level + ?max_level () = + let open QCheck2.Gen in + let* payloads_for_levels = + gen_payloads_for_levels ?inbox_creation_level ?max_level () + in + let* level, index = gen_level_and_index payloads_for_levels in + let* level', index' = gen_level_and_index payloads_for_levels in + return (payloads_for_levels, level, index, level', index') + +let fill_merkelized_payload history payloads = + let open Lwt_result_wrap_syntax in + let* first, payloads = + match payloads with + | x :: xs -> return (x, xs) + | [] -> failwith "empty payloads" + in + let*?@ history, merkelized_payload = + Merkelized_payload_hashes.genesis history first + in + let*?@ result = + List.fold_left_e + (fun (history, payloads) payload -> + Merkelized_payload_hashes.add_payload history payloads payload) + (history, merkelized_payload) + payloads + in + return result + +let construct_merkelized_payload_hashes payloads = + let history = Merkelized_payload_hashes.History.empty ~capacity:1000L in + fill_merkelized_payload history payloads + +(** The merkelized payload hashes history is correctly filled with all + values. *) +let test_merkelized_payload_hashes_history payloads = + let open Lwt_result_syntax in + let nb_payloads = List.length payloads in + let* history, merkelized_payloads = + construct_merkelized_payload_hashes payloads + in + let* () = + Assert.equal_z + ~loc:__LOC__ + (Z.of_int nb_payloads) + (Z.succ (Merkelized_payload_hashes.get_index merkelized_payloads)) + in + List.iteri_es + (fun index (expected_payload : Message.serialized) -> + let expected_payload_hash = + Message.hash_serialized_message expected_payload + in + let found_merkelized_payload = + opt_get ~__LOC__ + @@ Merkelized_payload_hashes.Internal_for_tests.find_predecessor_payload + history + ~index:(Z.of_int index) + merkelized_payloads + in + let found_payload_hash = + Merkelized_payload_hashes.get_payload_hash found_merkelized_payload + in + assert_equal_payload_hash + ~__LOC__ + found_payload_hash + expected_payload_hash) + payloads + +(** Produce a merkelized payload hashes proof and verify it's valid. *) +let test_merkelized_payload_hashes_proof (payloads, index) = + let open Lwt_result_wrap_syntax in + let* history, merkelized_payload = + construct_merkelized_payload_hashes payloads + in + let ( Merkelized_payload_hashes. + {merkelized = target_merkelized_payload; payload = proof_payload}, + proof ) = + opt_get ~__LOC__ + @@ Merkelized_payload_hashes.produce_proof history ~index merkelized_payload + in + let payload : Message.serialized = + opt_get ~__LOC__ @@ List.nth payloads (Z.to_int index) + in + let payload_hash = Message.hash_serialized_message payload in + let* () = assert_equal_payload ~__LOC__ proof_payload payload in + let* () = + assert_merkelized_payload + ~__LOC__ + ~index + ~payload_hash + target_merkelized_payload + in + let*?@ proof_ancestor_merkelized, proof_current_merkelized = + Merkelized_payload_hashes.verify_proof proof + in + let* () = + assert_equal_merkelized_payload + ~__LOC__ + ~found:proof_ancestor_merkelized + ~expected:target_merkelized_payload + in + let* () = + assert_equal_merkelized_payload + ~__LOC__ + ~found:proof_current_merkelized + ~expected:merkelized_payload + in + return_unit + +(** Verifying an empty merkelized payload hashes proof fails *) +let test_empty_merkelized_payload_hashes_proof_fails () = + verify_merkelized_payload_proof_fails ~__LOC__ "proof is empty" + @@ Merkelized_payload_hashes.Internal_for_tests.make_proof [] + +(* Test multiple cases of invalid proof. This test is more about testing the + skip list than testing merkelized payload. But it was easier to test with a + skip-list with hashes as pointer. *) +let test_invalid_merkelized_payload_hashes_proof_fails (payloads, index) = + let open Lwt_result_wrap_syntax in + let make_proof = Merkelized_payload_hashes.Internal_for_tests.make_proof in + let hd ~__LOC__ l = List.hd l |> opt_get ~__LOC__ in + let tl ~__LOC__ l = List.tl l |> opt_get ~__LOC__ in + let nth ~__LOC__ idx l = List.nth idx l |> opt_get ~__LOC__ in + let* history, merkelized_payload_hash = + construct_merkelized_payload_hashes payloads + in + let Merkelized_payload_hashes.{merkelized = _target; _}, proof = + opt_get ~__LOC__ + @@ Merkelized_payload_hashes.produce_proof + history + ~index + merkelized_payload_hash + in + let proof :> Merkelized_payload_hashes.t list = proof in + (* We need a proof of more than 3 elements otherwise some tests does not make + sense after. *) + QCheck2.assume Compare.List_length_with.(proof > 3) ; + let proof_len = List.length proof in + let payload = Message.unsafe_of_string "I'm a disruptive payload" in + let payloads' = payload :: payloads in + let* history', merkelized_payload' = + construct_merkelized_payload_hashes payloads' + in + let Merkelized_payload_hashes.{merkelized = target'; payload = _}, proof' = + opt_get ~__LOC__ + @@ Merkelized_payload_hashes.produce_proof + history' + ~index + merkelized_payload' + in + let proof' :> Merkelized_payload_hashes.t list = proof' in + let proof_with_invalid_target = + (* change the target cell. *) + let rest = List.rev proof |> tl ~__LOC__ in + make_proof @@ List.rev (target' :: rest) + in + let proof_with_invalid_cell = + (* change the latest cell. *) + let cell = proof' |> hd ~__LOC__ in + let rest = proof |> tl ~__LOC__ in + make_proof @@ (cell :: rest) + in + let proof_with_only_cell_and_target = + let cell = proof |> hd ~__LOC__ in + let target = List.rev proof |> hd ~__LOC__ in + make_proof @@ [cell; target] + in + let proof_with_invalid_cell_in_path = + let idx = proof_len / 2 in + let rev_prefix, suffix = List.rev_split_n idx proof in + let new_cell = nth ~__LOC__ proof' idx in + let prefix = new_cell :: tl ~__LOC__ rev_prefix |> List.rev in + make_proof @@ prefix @ suffix + in + let proof_with_missing_cell = + let idx = proof_len / 2 in + let rev_prefix, suffix = List.rev_split_n idx proof in + let prefix = tl ~__LOC__ rev_prefix |> List.rev in + make_proof @@ prefix @ suffix + in + let proof_with_extra_step = + let idx = proof_len / 2 in + let rev_prefix, suffix = List.rev_split_n idx proof in + let new_cell = nth ~__LOC__ proof' idx in + let prefix = + match rev_prefix with + | cell :: rest -> List.rev (new_cell :: cell :: rest) + | _ -> assert false + in + make_proof @@ prefix @ suffix + in + let assert_fails ~__LOC__ proof = + verify_merkelized_payload_proof_fails ~__LOC__ "invalid proof" proof + in + let* () = assert_fails ~__LOC__ proof_with_missing_cell in + let* () = assert_fails ~__LOC__ proof_with_invalid_cell_in_path in + let* () = assert_fails ~__LOC__ proof_with_invalid_target in + let* () = assert_fails ~__LOC__ proof_with_invalid_cell in + let* () = assert_fails ~__LOC__ proof_with_only_cell_and_target in + let* () = assert_fails ~__LOC__ proof_with_extra_step in + return_unit + +(** A node produces an inbox inclusion proof and the protocol verify it. *) +let test_inclusion_proof_production (payloads_for_levels, level) = + let open Lwt_result_wrap_syntax in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + payloads_for_levels + in + let node_inbox_snapshot = Inbox.old_levels_messages node_inbox.inbox in + let* proof, node_old_level_messages = + Node_inbox.produce_inclusion_proof node_inbox node_inbox_snapshot level + in + let proto_inbox_snapshot = Inbox.take_snapshot proto_inbox in + let*?@ verified_old_levels_messages = + Inbox.Internal_for_tests.verify_inclusion_proof proof proto_inbox_snapshot + in + assert_equal_history_proof + ~__LOC__ + verified_old_levels_messages + node_old_level_messages + +(** A node produces an inclusion proof and the protocol fails to verify it + against the snapshot of the next (empty) level. *) +let test_inclusion_proof_verification (payloads_for_levels, level) = + let open Lwt_result_wrap_syntax in + let inbox_creation_level = Raw_level.root in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox ~inbox_creation_level payloads_for_levels + in + let node_inbox_snapshot = Inbox.old_levels_messages node_inbox.inbox in + let* proof, _node_old_level_messages = + Node_inbox.produce_inclusion_proof node_inbox node_inbox_snapshot level + in + let*? proto_inbox = + Protocol_inbox.add_new_level ~inbox_creation_level proto_inbox [] + in + (* This snapshot is not the same one as node_inbox_snapshot because we + added an empty level. *) + let proto_inbox_snapshot = Inbox.take_snapshot proto_inbox in + verify_inclusion_proof_fails + ~__LOC__ + "invalid inclusion proof" + proof + proto_inbox_snapshot + +(** The protocol fails to verify an empty inclusion proof. *) +let test_empty_inclusion_proof_fails payloads = + let open Lwt_result_syntax in + let*? proto_inbox = + Protocol_inbox.construct_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let proto_inbox_snapshot = Inbox.take_snapshot proto_inbox in + verify_inclusion_proof_fails + ~__LOC__ + "inclusion proof is empty" + [] + proto_inbox_snapshot + +(** A node produces an inbox payloads proof and the protocol verify it. *) +let test_payloads_proof_production + ((payloads : payloads_per_level), message_counter) = + let open Lwt_result_wrap_syntax in + let payloads_for_levels = [payloads] in + let exp_message = + first_after payloads_for_levels payloads.level message_counter |> function + | Some {payload; _} -> Some payload + | None -> None + in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + payloads_for_levels + in + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + (* Produce a payloads proof using the {!Node_inbox}. *) + let* ({payload = proof_input; _} as proof) = + Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + (* Verify the produced proof using the {!Protocol_inbox}. *) + let proto_head_cell_hash = latest_level_proof_hash proto_inbox in + let*?@ verified_input = + Inbox.Internal_for_tests.verify_payloads_proof + proof + proto_head_cell_hash + message_counter + in + let* () = assert_equal_payload_option ~__LOC__ proof_input verified_input in + assert_equal_payload_option ~__LOC__ exp_message verified_input + +(** A node produces a payloads proof and the protocol fails to verify it + against the snapshot of the next (empty) level. *) +let test_payloads_proof_invalid_inbox_snapshot (payloads, message_counter) = + let open Lwt_result_syntax in + let inbox_creation_level = Raw_level.root in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox ~inbox_creation_level [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + let*? proto_inbox = + Protocol_inbox.add_new_level ~inbox_creation_level proto_inbox [] + in + (* As we added one level in the [proto_inbox], it is one level further than + the [node_inbox]. The proof will not match the history. *) + let head_cell_hash = latest_level_proof_hash proto_inbox in + verify_payloads_proof_fails + ~__LOC__ + "message_proof does not match history" + proof + head_cell_hash + message_counter + +(** Fail to verify a payloads proof with an input when none is expected. *) +let test_payloads_proof_no_payload_expected (payloads : payloads_per_level) = + let open Lwt_result_syntax in + let message_counter = Z.of_int (List.length payloads.inputs) in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + let invalid_proof = + let payload = Some (make_internal_inbox_message Start_of_level) in + Inbox.Internal_for_tests.{proof with payload} + in + let head_cell_hash = latest_level_proof_hash proto_inbox in + verify_payloads_proof_fails + ~__LOC__ + "Payload provided but none expected" + invalid_proof + head_cell_hash + message_counter + +(** Fail to verify a payloads proof with no input when one is expected. *) +let test_payloads_proof_payload_expected payloads = + let open Lwt_result_syntax in + let message_counter = Z.zero in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Sc_rollup_helpers.Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + let invalid_proof = Inbox.Internal_for_tests.{proof with payload = None} in + let head_cell_hash = latest_level_proof_hash proto_inbox in + verify_payloads_proof_fails + ~__LOC__ + "Expected a payload but none provided in the proof" + invalid_proof + head_cell_hash + message_counter + +(** Fail to verify a payloads proof about another index. *) +let test_payloads_proof_incorrect_proof payloads = + let open Lwt_result_syntax in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Node_inbox.produce_payloads_proof node_inbox node_head_cell_hash Z.zero + in + let proof = Inbox.Internal_for_tests.{proof with payload = None} in + let head_cell_hash = latest_level_proof_hash proto_inbox in + let invalid_message_counter = Z.of_int (List.length payloads.inputs) in + verify_payloads_proof_fails + ~__LOC__ + "Provided proof is about a unexpected payload" + proof + head_cell_hash + invalid_message_counter + +(** Fail to verify a payloads proof about another payload. *) +let test_payloads_proof_incorrect_payload payloads = + let open Lwt_result_syntax in + let message_counter = Z.zero in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + let invalid_proof = + let payload = Some (make_internal_inbox_message End_of_level) in + Inbox.Internal_for_tests.{proof with payload} + in + let head_cell_hash = latest_level_proof_hash proto_inbox in + verify_payloads_proof_fails + ~__LOC__ + "the payload provided does not match the payload's hash found in the \ + message proof" + invalid_proof + head_cell_hash + message_counter + +(** Fail to verify a valid payloads proof for an invalid message counter. *) +let test_payloads_proof_incorrect_index payloads = + let open Lwt_result_syntax in + let message_counter = Z.zero in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + let head_cell_hash = latest_level_proof_hash proto_inbox in + let invalid_message_counter = Z.succ message_counter in + verify_payloads_proof_fails + ~__LOC__ + "found index in message_proof is incorrect" + proof + head_cell_hash + invalid_message_counter + +(** Fail to verify a payloads proof with an out of bound index. *) +let test_payloads_proof_out_of_bound_index payloads = + let open Lwt_result_syntax in + let message_counter = Z.zero in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + [payloads] + in + let* proof = + let node_head_cell_hash = latest_level_proof_hash node_inbox.inbox in + Node_inbox.produce_payloads_proof + node_inbox + node_head_cell_hash + message_counter + in + let head_cell_hash = latest_level_proof_hash proto_inbox in + let invalid_message_counter = + Z.of_int @@ succ (List.length payloads.inputs) + in + verify_payloads_proof_fails + ~__LOC__ + "Provided message counter is out of the valid range [0 -- (max_index + 1)]" + proof + head_cell_hash + invalid_message_counter + +(** Produce an inbox proof and verify it. *) +let test_inbox_proof_production (payloads_for_levels, level, message_counter) = + let open Lwt_result_wrap_syntax in + let exp_message = first_after payloads_for_levels level message_counter in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + payloads_for_levels + in + let node_inbox_snapshot = Inbox.take_snapshot node_inbox.inbox in + let* proof, input_of_produced_proof = + Node_inbox.produce_proof + node_inbox + node_inbox_snapshot + (level, message_counter) + in + let proto_inbox_snapshot = Inbox.take_snapshot proto_inbox in + let* () = + assert_equal_history_proof ~__LOC__ node_inbox_snapshot proto_inbox_snapshot + in + let*?@ input_in_proof = + Inbox.verify_proof (level, message_counter) proto_inbox_snapshot proof + in + let* () = + assert_inbox_message ~__LOC__ input_of_produced_proof input_in_proof + in + assert_inbox_message ~__LOC__ exp_message input_in_proof + +(** This test first produces two valid inbox proofs [proof1] and + [proof2] for two different levels [l1; l2], and message counters + [i1; i2]. Then combine the two proofs to create two invalid ones + [{proof1.inclusion_proof; proof2.payloads_prof}] and + [{proof2.inclusion_proof; proof1.payloads_prof}]. Both fail with + all combinations of levels [l1, l2] and messages counter [i1, + i2]. *) +let test_invalid_inbox_proof_fails + (payloads_for_levels, level, message_counter, level', message_counter') = + QCheck2.assume + ((not (Raw_level.equal level level')) + && not (Z.equal message_counter message_counter')) ; + let open Lwt_result_wrap_syntax in + let*? node_inbox, proto_inbox = + construct_node_and_protocol_inbox + ~inbox_creation_level:Raw_level.root + payloads_for_levels + in + let node_inbox_snapshot = Inbox.take_snapshot node_inbox.inbox in + let proto_inbox_snapshot = Inbox.take_snapshot proto_inbox in + assert (node_inbox_snapshot = proto_inbox_snapshot) ; + let* invalid_proof = + let* (inclusion_proof, _message_proof), _input = + Node_inbox.produce_and_expose_proof + node_inbox + node_inbox_snapshot + (level, message_counter) + in + let* (_inclusion_proof', message_proof'), _input = + Node_inbox.produce_and_expose_proof + node_inbox + node_inbox_snapshot + (level', message_counter') + in + return @@ Inbox.Internal_for_tests.make_proof inclusion_proof message_proof' + in + let assert_fails ~__LOC__ (level, message_counter) = + assert_inbox_proof_error ~__LOC__ "message_proof does not match history" + @@ Inbox.verify_proof + (level, message_counter) + proto_inbox_snapshot + invalid_proof + in + let* () = assert_fails ~__LOC__ (level, message_counter) in + let* () = assert_fails ~__LOC__ (level', message_counter) in + let* () = assert_fails ~__LOC__ (level, message_counter') in + let* () = assert_fails ~__LOC__ (level', message_counter') in + return_unit + +(** Verify that the inbox history is correctly filled by calling + {!Inbox.add_all_messages}. *) +let test_messages_are_correctly_added_in_history + {predecessor_timestamp; predecessor; messages; _} = + let open Lwt_result_wrap_syntax in + let inbox = dumb_init Raw_level.root in + let messages = List.map (fun message -> Message.External message) messages in + let*?@ payloads_history, _history, _inbox, witness, messages = + Inbox.add_all_messages + ~first_block:false + ~predecessor_timestamp + ~predecessor + (Inbox.History.empty ~capacity:0L) + inbox + messages + in + List.iteri_es + (fun i message -> + let index = Z.of_int i in + let*?@ expected_payload = Message.serialize message in + let expected_hash = Message.hash_serialized_message expected_payload in + let found_merkelized_opt = + Sc_rollup.Inbox_merkelized_payload_hashes.Internal_for_tests + .find_predecessor_payload + payloads_history + ~index + witness + in + let* found_hash = + match found_merkelized_opt with + | Some x -> + return + (Sc_rollup.Inbox_merkelized_payload_hashes.get_payload_hash x) + | None -> + failwith + "The payload was not found in the payloads_history, this is \ + unexpected" + in + Assert.equal + ~loc:__LOC__ + Message.Hash.equal + "The message was not correctly added to the payloads history" + Message.Hash.pp + expected_hash + found_hash) + messages + +let merkelized_payload_hashes_tests = + [ + Tztest.tztest_qcheck2 + ~count:1000 + ~name: + "Add payloads to merkelized payload hashes then retrieve them from \ + history." + (gen_payloads ()) + test_merkelized_payload_hashes_history; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"Produce a merkelized payload hashes proof and verify its validity." + (gen_payloads_and_index ()) + test_merkelized_payload_hashes_proof; + Tztest.tztest + "Empty merkelized payload hashes proof fails." + `Quick + test_empty_merkelized_payload_hashes_proof_fails; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"Invalid merkelized payload hashes proof fails." + (gen_payloads_and_index + ~min_size:20 + ~max_size:100 + ~max_index_offset:10 + ()) + test_invalid_merkelized_payload_hashes_proof_fails; + ] + +let inbox_tests = + [ + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"produce inclusion proof and verifies it." + (gen_payloads_for_levels_and_level ()) + test_inclusion_proof_production; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"negative test of inclusion proof." + (gen_payloads_for_levels_and_level ()) + test_inclusion_proof_verification; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"verify empty inclusion proof fails." + (gen_payloads_and_level ()) + test_empty_inclusion_proof_fails; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"produce payloads proof and verifies it." + (gen_payloads_and_level_and_index ()) + test_payloads_proof_production; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof not using the correct current level proof." + (gen_payloads_and_level_and_index ()) + test_payloads_proof_invalid_inbox_snapshot; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof without the payload." + (gen_payloads_and_level ()) + test_payloads_proof_no_payload_expected; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof with payload when none is expected." + (gen_payloads_and_level ()) + test_payloads_proof_payload_expected; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof with a proof for another payload." + (gen_payloads_and_level ()) + test_payloads_proof_incorrect_proof; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof with another payload." + (gen_payloads_and_level ()) + test_payloads_proof_incorrect_payload; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof with a payload with an incorrect index." + (gen_payloads_and_level ()) + test_payloads_proof_incorrect_index; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"test to verify a proof with an out of bound index." + (gen_payloads_and_level ()) + test_payloads_proof_out_of_bound_index; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"produce inbox proof and verifies it." + (gen_payloads_for_levels_and_level_and_index ()) + test_inbox_proof_production; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"negative test of inbox proof." + (gen_payloads_for_levels_and_two_levels_and_two_indexes ()) + test_invalid_inbox_proof_fails; + Tztest.tztest_qcheck2 + ~count:1000 + ~name:"messages are correctly added in payloads history" + (gen_payloads_for_level ()) + test_messages_are_correctly_added_in_history; + ] + +let tests = + merkelized_payload_hashes_tests @ inbox_tests + @ Test_sc_rollup_inbox_legacy.tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup inbox", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox_legacy.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox_legacy.ml new file mode 100644 index 000000000000..d2eb16ec8815 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_inbox_legacy.ml @@ -0,0 +1,543 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (smart contract rollup inbox) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe + Subject: These unit tests check the off-line inbox implementation for + smart contract rollups +*) + +(* This test file is going to soon disappear. Each tests here are going to be + rewritten in [test_sc_rollup_inbox] in multiples MR. *) +open Protocol +open Sc_rollup_inbox_repr + +exception Sc_rollup_inbox_test_error of string + +let err x = Exn (Sc_rollup_inbox_test_error x) + +let rollup = Sc_rollup_repr.Address.hash_string [""] + +let first_level = Raw_level_repr.(succ root) + +let inbox_message_testable = + Alcotest.testable + Sc_rollup_PVM_sig.pp_inbox_message + Sc_rollup_PVM_sig.inbox_message_equal + +module Payloads_histories = + Map.Make (Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash) + +let get_level_tree_history payloads_histories witness_hash = + Payloads_histories.find witness_hash payloads_histories + |> WithExceptions.Option.get ~loc:__LOC__ + |> Lwt.return + +let make_payload message = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Sc_rollup_inbox_message_repr.(serialize @@ External message) + +let make_message message = Sc_rollup_inbox_message_repr.(External message) + +let payloads_from_messages = + List.map (fun Sc_rollup_helpers.{input_repr = input; _} -> + match input with + | Inbox_message {payload; _} -> payload + | Reveal _ -> assert false) + +let populate_inboxes level history inbox inboxes list_of_messages = + let open Result_wrap_syntax in + let rec aux level history payloads_histories inbox inboxes witness = function + | [] -> return (payloads_histories, witness, history, inbox, inboxes) + | messages :: ps -> + let*@ payloads_history, history, inbox, witness, _messages = + add_all_messages + ~protocol_migration_message:None + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + history + inbox + messages + in + let witness_hash = + Sc_rollup_inbox_merkelized_payload_hashes_repr.hash witness + in + let payloads_histories = + Payloads_histories.add + witness_hash + payloads_history + payloads_histories + in + let level = Raw_level_repr.succ level in + aux + level + history + payloads_histories + inbox + (inbox :: inboxes) + (Some witness) + ps + in + let payloads_histories = Payloads_histories.empty in + aux level history payloads_histories inbox inboxes None list_of_messages + +let inbox = Sc_rollup_helpers.dumb_init_repr + +let setup_inbox_with_messages list_of_payloads f = + let open Lwt_result_syntax in + let inbox = inbox first_level in + let history = History.empty ~capacity:10000L in + let*? payloads_histories, witness, history, inbox, inboxes = + populate_inboxes first_level history inbox [] list_of_payloads + in + match witness with + | None -> tzfail (err "setup_inbox_with_messages called with no messages") + | Some tree -> f payloads_histories tree history inbox inboxes + +(* An external message is prefixed with a tag whose length is one byte, and + whose value is 1. *) +let encode_external_message message = + let prefix = "\001" in + Bytes.of_string (prefix ^ message) + +let check_payload messages external_message = + let open Lwt_result_syntax in + let*! payload_opt = Environment.Context.Tree.find messages ["payload"] in + match payload_opt with + | None -> tzfail (err "No payload in messages") + | Some payload -> + let expected_payload = encode_external_message external_message in + fail_unless + (expected_payload = payload) + (err + (Printf.sprintf + "Expected payload %s, got %s" + (Bytes.to_string expected_payload) + (Bytes.to_string payload))) + +(** This is basically identical to {!setup_inbox_with_messages}, except + that it uses the {!Node} instance instead of the protocol instance. *) +let setup_node_inbox_with_messages list_of_messages f = + let open Lwt_result_wrap_syntax in + let inbox = inbox first_level in + let history = History.empty ~capacity:10000L in + let payloads_histories = Payloads_histories.empty in + let rec aux level history payloads_histories inbox inboxes witness = function + | [] -> return (payloads_histories, witness, history, inbox, inboxes) + | messages :: ps -> + let*?@ payloads_history, history, inbox, witness, _messages = + add_all_messages + ~protocol_migration_message:None + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + history + inbox + messages + in + let witness_hash = + Sc_rollup_inbox_merkelized_payload_hashes_repr.hash witness + in + let payloads_histories = + Payloads_histories.add + witness_hash + payloads_history + payloads_histories + in + let level = Raw_level_repr.succ level in + aux + level + history + payloads_histories + inbox + (inbox :: inboxes) + (Some witness) + ps + in + let* payloads_histories, witness, history, inbox, inboxes = + aux first_level history payloads_histories inbox [] None list_of_messages + in + match witness with + | None -> failwith "setup_inbox_with_messages called with no messages" + | Some tree -> f payloads_histories tree history inbox inboxes + +let level_of_int n = Raw_level_repr.of_int32_exn (Int32.of_int n) + +let level_to_int l = Int32.to_int (Raw_level_repr.to_int32 l) + +let payload_string msg = + Sc_rollup_inbox_message_repr.unsafe_of_string + (Bytes.to_string (encode_external_message msg)) + +let inbox_message_of_input input = + match input with Sc_rollup_PVM_sig.Inbox_message x -> Some x | _ -> None + +let next_inbox_message levels_and_messages l n = + let equal = Raw_level_repr.( = ) in + let messages = + WithExceptions.Option.get ~loc:__LOC__ + @@ List.assoc ~equal l levels_and_messages + in + match List.nth messages (Z.to_int n) with + | Some Sc_rollup_helpers.{input_repr = input; _} -> + inbox_message_of_input input + | None -> ( + (* If no input at (l, n), the next input is (l+1, 0). *) + match List.assoc ~equal (Raw_level_repr.succ l) levels_and_messages with + | None -> None + | Some messages -> + let Sc_rollup_helpers.{input_repr = input; _} = + Stdlib.List.hd messages + in + inbox_message_of_input input) + +let fail_with_proof_error_msg errors fail_msg = + let msg = + List.find_map + (function + | Environment.Ecoproto_error + (Sc_rollup_inbox_repr.Inbox_proof_error msg) -> + Some msg + | Environment.Ecoproto_error + (Sc_rollup_inbox_merkelized_payload_hashes_repr + .Merkelized_payload_hashes_proof_error msg) -> + Some msg + | _ -> None) + errors + in + let msg = Option.(msg |> map (fun s -> ": " ^ s) |> value ~default:"") in + Lwt_result_syntax.tzfail (err (fail_msg ^ msg)) + +(** This helper function initializes inboxes and histories with different + capacities and populates them. *) +let init_inboxes_histories_with_different_capacities + (nb_levels, default_capacity, small_capacity, next_index) = + let open Lwt_result_syntax in + let* () = + fail_when + Int64.(of_int nb_levels <= small_capacity) + (err + (Format.sprintf + "Bad inputs: nb_levels = %d should be greater than small_capacity \ + = %Ld" + nb_levels + small_capacity)) + in + let* () = + fail_when + Int64.(of_int nb_levels >= default_capacity) + (err + (Format.sprintf + "Bad inputs: nb_levels = %d should be smaller than \ + default_capacity = %Ld" + nb_levels + default_capacity)) + in + let*? messages = + List.init ~when_negative_length:[] nb_levels (fun i -> [string_of_int i]) + in + let mk_history ?(next_index = 0L) ~capacity () = + let inbox = inbox first_level in + let history = + Sc_rollup_inbox_repr.History.Internal_for_tests.empty + ~capacity + ~next_index + in + let messages = List.map (List.map make_message) messages in + populate_inboxes first_level history inbox [] messages + in + (* Here, we have `~capacity:0L`. So no history is kept *) + let*? no_history = mk_history ~capacity:0L () in + (* Here, we set a [default_capacity] supposed to be greater than [nb_levels], + and keep the default [next_index]. This history will serve as a witeness *) + let*? big_history = mk_history ~capacity:default_capacity () in + (* Here, we choose a small capacity supposed to be smaller than [nb_levels] to + cover cases where the history is full and older elements should be removed. + We also set a non-default [next_index] value to cover cases where the + incremented index may overflow or is negative. *) + let*? small_history = mk_history ~next_index ~capacity:small_capacity () in + return (no_history, small_history, big_history) + +(** In this test, we mainly check that the number of entries in histories + doesn't exceed their respective capacities. *) +let test_history_length + ((_nb_levels, default_capacity, small_capacity, _next_index) as params) = + let open Lwt_result_syntax in + let module I = Sc_rollup_inbox_repr in + let err expected given ~exact = + err + @@ Format.sprintf + "We expect a history of %Ld capacity (%s), but we got %d elements" + expected + (if exact then "exactly" else "at most") + given + in + let no_capacity = 0L in + let* no_history, small_history, big_history = + init_inboxes_histories_with_different_capacities params + in + let _level_tree_histories0, _level_tree0, history0, _inbox0, _inboxes0 = + no_history + in + let _level_tree_histories1, _level_tree1, history1, _inbox1, _inboxes1 = + small_history + in + let _level_tree_histories2, _level_tree2, history2, _inbox2, _inboxes2 = + big_history + in + let hh0 = I.History.Internal_for_tests.keys history0 in + let hh1 = I.History.Internal_for_tests.keys history1 in + let hh2 = I.History.Internal_for_tests.keys history2 in + (* The first history is supposed to have exactly 0 elements *) + let* () = + let len = List.length hh0 in + fail_unless + Int64.(equal no_capacity (of_int @@ len)) + (err no_capacity len ~exact:true) + in + (* The second history is supposed to have exactly [small_capacity], because + we are supposed to add _nb_level > small_capacity entries. *) + let* () = + let len = List.length hh1 in + fail_unless + Int64.(small_capacity = of_int len) + (err small_capacity len ~exact:false) + in + (* The third history's capacity, named [default_capacity], is supposed to be + greater than _nb_level. So, we don't expect this history to be full. *) + let* () = + let len = List.length hh2 in + fail_unless + Int64.(default_capacity > of_int len) + (err default_capacity len ~exact:true) + in + return_unit + +(** In this test, we check that for two inboxes of the same content, the entries + of the history with the lower capacity, taken in the insertion order, is a + prefix of the entries of the history with the higher capacity. *) +let test_history_prefix params = + let open Lwt_result_syntax in + let module I = Sc_rollup_inbox_repr in + let* no_history, small_history, big_history = + init_inboxes_histories_with_different_capacities params + in + let _level_tree_histories0, _level_tree0, history0, _inbox0, _inboxes0 = + no_history + in + let _level_tree_histories1, _level_tree1, history1, _inbox1, _inboxes1 = + small_history + in + let _level_tree_histories2, _level_tree2, history2, _inbox2, _inboxes2 = + big_history + in + let hh0 = I.History.Internal_for_tests.keys history0 in + let hh1 = I.History.Internal_for_tests.keys history1 in + let hh2 = I.History.Internal_for_tests.keys history2 in + let check_is_suffix sub super = + let rec aux super to_remove = + let* () = + fail_unless + (to_remove >= 0) + (err "A bigger list cannot be a suffix of a smaller one.") + in + if to_remove = 0 then + fail_unless + (List.for_all2 ~when_different_lengths:false I.Hash.equal sub super + = Ok true) + (err "The smaller list is not a prefix the bigger one.") + else + match List.tl super with + | None -> assert false + | Some super -> aux super (to_remove - 1) + in + aux super (List.length super - List.length sub) + in + (* The empty history's hashes list is supposed to be a suffix of a history + with bigger capacity. *) + let* () = check_is_suffix hh0 hh1 in + (* The history's hashes list of the smaller capacity should be a prefix of + the history's hashes list of a bigger capacity. *) + check_is_suffix hh1 hh2 + +(** In this test, we make some checks on production and verification of + inclusion proofs depending on histories' capacity. *) +let test_inclusion_proofs_depending_on_history_capacity + ((_nb_levels, _default_capacity, _small_capacity, _next_index) as params) = + let open Lwt_result_wrap_syntax in + let module I = Sc_rollup_inbox_repr in + let* no_history, small_history, big_history = + init_inboxes_histories_with_different_capacities params + in + let _level_tree_histories0, _level_tree0, history0, inbox0, _inboxes0 = + no_history + in + let _level_tree_histories1, _level_tree1, history1, inbox1, _inboxes1 = + small_history + in + let _level_tree_histories2, _level_tree2, history2, inbox2, _inboxes2 = + big_history + in + let hp0 = I.old_levels_messages inbox0 in + let hp1 = I.old_levels_messages inbox1 in + let (hp2 as hp) = I.old_levels_messages inbox2 in + let pred_level_of_hp = + WithExceptions.Option.get ~loc:__LOC__ + @@ Raw_level_repr.pred + @@ I.Internal_for_tests.get_level_of_history_proof hp + in + let* () = + fail_unless + (I.equal_history_proof hp0 hp1 && I.equal_history_proof hp1 hp2) + (err + "History proof of equal inboxes shouldn't depend on the capacity of \ + history.") + in + let proof s v = + let*!@ v in + match v with + | Ok v -> return v + | Error _ -> tzfail (err (s ^ ": Expecting some inclusion proof.")) + in + let get_history history inbox = History.find inbox history |> Lwt.return in + (* Producing inclusion proofs using history1 and history2 should succeed. + But, we should not be able to produce any proof with history0 as bound + is 0. *) + let*! ip0 = + I.Internal_for_tests.produce_inclusion_proof + (get_history history0) + hp + pred_level_of_hp + in + let* ip1, hp1' = + proof "history1" + @@ I.Internal_for_tests.produce_inclusion_proof + (get_history history1) + hp + pred_level_of_hp + in + let* ip2, hp2' = + proof "history2" + @@ I.Internal_for_tests.produce_inclusion_proof + (get_history history2) + hp + pred_level_of_hp + in + let* () = + fail_unless + (Result.is_error ip0) + (err + "Should not be able to get inbox inclusion proofs without a history \ + (i.e., a history with no capacity). ") + in + let*?@ hp1'' = I.Internal_for_tests.verify_inclusion_proof ip1 hp1 in + let*?@ hp2'' = I.Internal_for_tests.verify_inclusion_proof ip2 hp2 in + fail_unless + (hp1' = hp1'' && hp2' = hp2'' && hp1' = hp2') + (err "Inclusion proofs are expected to be valid.") + +(** This test checks that inboxes of the same levels that are supposed to contain + the same messages are equal. It also check the level trees obtained from + the last calls to add_messages are equal. *) +let test_for_successive_add_messages_with_different_histories_capacities + ((_nb_levels, _default_capacity, _small_capacity, _next_index) as params) = + let open Lwt_result_syntax in + let module I = Sc_rollup_inbox_repr in + let* no_history, small_history, big_history = + init_inboxes_histories_with_different_capacities params + in + let _level_tree_histories0, level_tree0, _history0, _inbox0, inboxes0 = + no_history + in + let _level_tree_histories1, level_tree1, _history1, _inbox1, inboxes1 = + small_history + in + let _level_tree_histories2, level_tree2, _history2, _inbox2, inboxes2 = + big_history + in + (* The latest inbox's value shouldn't depend on the value of [bound]. *) + let eq_inboxes_list = List.for_all2 ~when_different_lengths:false I.equal in + let* () = + fail_unless + (eq_inboxes_list inboxes0 inboxes1 = Ok true + && eq_inboxes_list inboxes1 inboxes2 = Ok true) + (err "Inboxes at the same level with the same content should be equal.") + in + fail_unless + (Option.equal + Sc_rollup_inbox_merkelized_payload_hashes_repr.equal + level_tree0 + level_tree1 + && Option.equal + Sc_rollup_inbox_merkelized_payload_hashes_repr.equal + level_tree1 + level_tree2) + (err "Trees of (supposedly) equal inboxes should be equal.") + +let tests = + let gen_history_params = + QCheck2.Gen.( + (* We fix the number of levels/ inboxes. *) + let* nb_levels = pure 30 in + (* The default capacity is intentionally very big compared to [nb_levels]. *) + let* default_capacity = + frequencyl [(1, Int64.of_int (1000 * nb_levels)); (1, Int64.max_int)] + in + (* The small capacity is intended to be smaller than nb_levels + (but greater than zero). *) + let* small_capacity = 3 -- (nb_levels / 2) in + let* next_index_delta = -5000 -- 5000 in + let big_next_index = Int64.(add max_int (of_int next_index_delta)) in + (* for the [next_index] counter of the history, we test both default values + (i.e., 0L) and values close to [max_int]. *) + let* next_index = frequencyl [(1, 0L); (1, big_next_index)] in + return + (nb_levels, default_capacity, Int64.of_int small_capacity, next_index)) + in + [ + Tztest.tztest_qcheck2 + ~count:10 + ~name:"Checking inboxes history length" + gen_history_params + test_history_length; + Tztest.tztest_qcheck2 + ~count:10 + ~name:"Checking inboxes history content and order" + gen_history_params + test_history_prefix; + Tztest.tztest_qcheck2 + ~count:10 + ~name:"Checking inclusion proofs validity depending on history capacity" + gen_history_params + test_inclusion_proofs_depending_on_history_capacity; + Tztest.tztest_qcheck2 + ~count:10 + ~name: + "Checking results of add_messages when histories have different \ + capacities" + gen_history_params + test_for_successive_add_messages_with_different_histories_capacities; + ] diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml new file mode 100644 index 000000000000..af323fb8ee7b --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_management_protocol.ml @@ -0,0 +1,400 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Rollup Management Protocol) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_sc_rollup_management_protocol.ml + Subject: Sanity checks for the Rollup Management Protocol module. +*) + +open Protocol +open Alpha_context + +let check_encode_decode_inbox_message message = + let open Lwt_result_wrap_syntax in + let open Sc_rollup_management_protocol in + let*?@ bytes = Sc_rollup.Inbox_message.serialize message in + let*?@ message' = Internal_for_tests.deserialize_inbox_message bytes in + let*?@ bytes' = Sc_rollup.Inbox_message.serialize message' in + Assert.equal_string + ~loc:__LOC__ + (Sc_rollup.Inbox_message.unsafe_to_string bytes) + (Sc_rollup.Inbox_message.unsafe_to_string bytes') + +let check_encode_decode_outbox_message_untyped ctxt transactions = + let open Lwt_result_wrap_syntax in + let open Sc_rollup_management_protocol in + let*?@ bytes = + Internal_for_tests.serialize_outbox_transactions_untyped transactions + in + let*?@ message_repr = Sc_rollup.Outbox.Message.deserialize bytes in + let*@ message', _ctxt = + outbox_message_of_outbox_message_repr ctxt message_repr + in + let*?@ bytes' = + match message' with + | Whitelist_update _ -> assert false (* its serialized transaction *) + | Atomic_transaction_batch {transactions} -> + Internal_for_tests.serialize_outbox_transactions_untyped transactions + in + Assert.equal_string + ~loc:__LOC__ + (Sc_rollup.Outbox.Message.unsafe_to_string bytes) + (Sc_rollup.Outbox.Message.unsafe_to_string bytes') + +let check_encode_decode_outbox_message_typed ctxt transactions = + let open Lwt_result_wrap_syntax in + let open Sc_rollup_management_protocol in + let*?@ bytes = + Internal_for_tests.serialize_outbox_transactions_typed transactions + in + let*?@ message_repr = Sc_rollup.Outbox.Message.deserialize bytes in + let*@ message', _ctxt = + outbox_message_of_outbox_message_repr ctxt message_repr + in + let*?@ bytes' = + match message' with + | Whitelist_update _ -> assert false (* its serialized transaction *) + | Atomic_transaction_batch {transactions} -> + Internal_for_tests.serialize_outbox_transactions_typed transactions + in + Assert.equal_string + ~loc:__LOC__ + (Sc_rollup.Outbox.Message.unsafe_to_string bytes) + (Sc_rollup.Outbox.Message.unsafe_to_string bytes') + +let string_ticket ticketer contents amount = + let open WithExceptions in + let amount = + Option.get ~loc:__LOC__ @@ Ticket_amount.of_n @@ Script_int.abs + @@ Script_int.of_int amount + in + let ticketer = Result.get_ok ~loc:__LOC__ (Contract.of_b58check ticketer) in + let contents = + Result.get_ok ~loc:__LOC__ (Script_string.of_string contents) + in + Script_typed_ir.{ticketer; contents; amount} + +let init_ctxt () = + let open Lwt_result_syntax in + let* block, _baker, _contract, _src2 = Contract_helpers.init () in + let+ incr = Incremental.begin_construction block in + Incremental.alpha_ctxt incr + +let assert_encoding_failure ~loc res = + Assert.proto_error_with_info + ~loc + res + "Failed to encode a rollup management protocol inbox message value" + +let test_encode_decode_internal_inbox_message_transfer () = + let open Lwt_result_wrap_syntax in + let open WithExceptions in + let* ctxt = init_ctxt () in + let destination = Sc_rollup.Address.zero in + let sender = + Contract_hash.of_b58check_exn "KT1BuEZtb68c1Q4yjtckcNjGELqWt56Xyesc" + in + let source = + Result.get_ok + ~loc:__LOC__ + (Signature.Public_key_hash.of_b58check + "tz1RjtZUVeLhADFHDL8UwDZA6vjWWhojpu5w") + in + let*?@ (Script_typed_ir.Ty_ex_c pair_nat_ticket_string_ty) = + let open Result_syntax in + let open Script_typed_ir in + let* ticket_t = ticket_t (-1) string_t in + pair_t (-1) nat_t ticket_t + in + let payload = + ( Script_int.(abs @@ of_int 42), + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ) + in + let*@ transfer, ctxt = + Sc_rollup_management_protocol.make_internal_transfer + ctxt + pair_nat_ticket_string_ty + ~payload + ~sender + ~source + ~destination + in + let* () = check_encode_decode_inbox_message transfer in + (* Check that the size of messages that can be encoded is bounded. *) + let msg = String.make 4050 'c' in + let*?@ payload = Script_string.of_string msg in + let*@ transfer, _ctxt = + let open Script_typed_ir in + Sc_rollup_management_protocol.make_internal_transfer + ctxt + String_t + ~payload + ~sender + ~source + ~destination + in + let*! res = check_encode_decode_inbox_message transfer in + assert_encoding_failure ~loc:__LOC__ res + +let test_encode_decode_internal_inbox_message_sol () = + let sol = Sc_rollup.Inbox_message.(Internal Start_of_level) in + check_encode_decode_inbox_message sol + +let test_encode_decode_internal_inbox_message_eol () = + let eol = Sc_rollup.Inbox_message.(Internal End_of_level) in + check_encode_decode_inbox_message eol + +let test_encode_decode_external_inbox_message () = + let open Lwt_result_wrap_syntax in + let assert_prefix message = + let inbox_message = Sc_rollup.Inbox_message.External message in + let*?@ real_encoding = Sc_rollup.Inbox_message.serialize inbox_message in + let real_encoding = + Sc_rollup.Inbox_message.unsafe_to_string real_encoding + in + (* The prefix consists of a tag (0 for internal, 1 for external). *) + let real_prefix = String.get real_encoding 0 in + let expected_prefix = '\001' in + let expected_encoding = Printf.sprintf "%c%s" expected_prefix message in + (* Check that the encode/decode matches. *) + let* () = check_encode_decode_inbox_message inbox_message in + (* Check that the prefix match. *) + let* () = Assert.equal_char ~loc:__LOC__ real_prefix expected_prefix in + (* Check that the encoded string consists of the prefix followed by the + original message. *) + Assert.equal_string ~loc:__LOC__ real_encoding expected_encoding + in + let* () = assert_prefix "" in + let* () = assert_prefix "A" in + let* () = assert_prefix "0123456789" in + let* () = assert_prefix (String.init 256 (Fun.const 'A')) in + let assert_encoding_success message = + let inbox_message = Sc_rollup.Inbox_message.External message in + let*! res = check_encode_decode_inbox_message inbox_message in + assert (Result.is_ok res) ; + return_unit + in + let assert_encoding_failure message = + let inbox_message = Sc_rollup.Inbox_message.External message in + let*! res = check_encode_decode_inbox_message inbox_message in + assert_encoding_failure ~loc:__LOC__ res + in + let max_msg_size = Constants_repr.sc_rollup_message_size_limit in + let message = String.init (max_msg_size - 1) (Fun.const 'A') in + let* () = assert_encoding_success message in + let message = String.init max_msg_size (Fun.const 'b') in + let* () = assert_encoding_failure message in + assert_encoding_failure message + +let init_env () = + let open Lwt_result_syntax in + let* block, baker, contract, _src2 = Contract_helpers.init () in + return (block, baker, contract) + +let ticket_receiver = + {| + { parameter (pair nat (ticket string)); + storage (list (ticket string)); + code { UNPAIR; # [(nat, ticket) ; list] + CDR; # [ticket ; list] + CONS; # [ticket :: list] + NIL operation ; # [[] ; ticket :: list] + PAIR; # [([], ticket :: list)] + } + } + |} + +let add_or_clear = + {| + { parameter (or (pair %add nat string) (unit %clear)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { UNPAIR ; DIG 2 ; SWAP ; DIG 2 ; TICKET ; ASSERT_SOME ; CONS ; NIL operation ; PAIR } + { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } + |} + +let test_encode_decode_outbox_message () = + let open Lwt_result_wrap_syntax in + let* block, baker, source_contract = init_env () in + let* ticket_receiver, _, block = + Contract_helpers.originate_contract_from_string + ~script:ticket_receiver + ~storage:"{}" + ~source_contract + ~baker + block + in + let* add_or_clear, _, block = + Contract_helpers.originate_contract_from_string + ~script:add_or_clear + ~storage:"{}" + ~source_contract + ~baker + block + in + let* incr = Incremental.begin_construction block in + let ctxt = Incremental.alpha_ctxt incr in + let ticket_receiver_destination = + match ticket_receiver with + | Contract.Originated ch -> ch + | Implicit _ -> assert false + in + let add_or_clear_destination = + match add_or_clear with + | Contract.Originated ch -> ch + | Implicit _ -> assert false + in + (* Transaction to ticket receiver. *) + let*?@ (Script_typed_ir.Ty_ex_c pair_nat_ticket_string_ty) = + let open Result_syntax in + let open Script_typed_ir in + let* ticket_t = ticket_t (-1) string_t in + pair_t (-1) nat_t ticket_t + in + let parameters = + ( Script_int.(abs @@ of_int 42), + string_ticket "KT1ThEdxfUcWUwqsdergy3QnbCWGHSUHeHJq" "red" 1 ) + in + let*@ transaction1, ctxt = + Sc_rollup_management_protocol.Internal_for_tests.make_transaction + ctxt + pair_nat_ticket_string_ty + ~parameters + ~destination:ticket_receiver_destination + ~entrypoint:Entrypoint.default + in + (* Transaction to the `add` endpoint of add-or-clear contract. *) + let*@ transaction2, ctxt = + let*? (Script_typed_ir.Ty_ex_c pair_nat_ticket_string_ty) = + Script_typed_ir.(pair_t (-1) nat_t string_t) + in + let*? content = Script_string.of_string "Hello" in + let parameters = (Script_int.(abs @@ of_int 11), content) in + Sc_rollup_management_protocol.Internal_for_tests.make_transaction + ctxt + pair_nat_ticket_string_ty + ~parameters + ~destination:add_or_clear_destination + ~entrypoint:(Entrypoint.of_string_strict_exn "add") + in + (* Transaction to the `clear` endpoint of add-or-clear contract. *) + let*@ transaction3, ctxt = + Sc_rollup_management_protocol.Internal_for_tests.make_transaction + ctxt + Script_typed_ir.unit_t + ~parameters:() + ~destination:add_or_clear_destination + ~entrypoint:(Entrypoint.of_string_strict_exn "clear") + in + let outbox_message = [transaction1; transaction2; transaction3] in + let* () = check_encode_decode_outbox_message_untyped ctxt outbox_message in + check_encode_decode_outbox_message_typed ctxt outbox_message + +let test_whitelist_encoding_size () = + let open Lwt_result_syntax in + let gen_pkh () = + let account = Account.new_account () in + account.pkh + in + (* 6 is for the rest of encoding: size, tag, ... *) + let max_msg_size = Constants_repr.sc_rollup_message_size_limit - 6 in + let encoding_size = + Data_encoding.Binary.length Signature.Public_key_hash.encoding (gen_pkh ()) + in + let max_allowed_whitelist_size = max_msg_size / encoding_size in + let check_encoding ~valid encoding msg = + let res = Data_encoding.Binary.to_bytes encoding msg in + match res with + | Error _ when valid -> fail @@ [error_of_fmt "valid encoding is invalid"] + | Ok _ when not valid -> fail @@ [error_of_fmt "invalid encoding is valid"] + | _ -> return_unit + in + let*? max_whitelist = + List.init + ~when_negative_length:[error_of_fmt "invalid size"] + max_allowed_whitelist_size + (fun _i -> gen_pkh ()) + in + let* () = + let* () = + check_encoding ~valid:true Sc_rollup.Whitelist.encoding max_whitelist + in + Sc_rollup.Outbox.Message.( + check_encoding + ~valid:true + encoding + (Whitelist_update (Some max_whitelist))) + in + let* () = + let too_big_whitelist = gen_pkh () :: max_whitelist in + let* () = + check_encoding ~valid:false Sc_rollup.Whitelist.encoding too_big_whitelist + in + Sc_rollup.Outbox.Message.( + check_encoding + ~valid:false + encoding + (Whitelist_update (Some too_big_whitelist))) + in + return_unit + +let tests = + [ + Tztest.tztest + "Encode/decode internal inbox message transfer" + `Quick + test_encode_decode_internal_inbox_message_transfer; + Tztest.tztest + "Encode/decode internal inbox message start of level" + `Quick + test_encode_decode_internal_inbox_message_sol; + Tztest.tztest + "Encode/decode internal inbox message end of level" + `Quick + test_encode_decode_internal_inbox_message_eol; + Tztest.tztest + "Encode/decode external inbox message" + `Quick + test_encode_decode_external_inbox_message; + Tztest.tztest + "Encode/decode outbox message" + `Quick + test_encode_decode_outbox_message; + Tztest.tztest + "Whitelist size is borned by max_msg_size" + `Quick + test_whitelist_encoding_size; + ] + +let () = + Alcotest_lwt.run + ~__FILE__ + Protocol.name + [("sc rollup management protocol", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_storage.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_storage.ml new file mode 100644 index 000000000000..a4b08a6aa213 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_storage.ml @@ -0,0 +1,2800 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol Sc_rollup_storage + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_sc_rollup_storage.ml + Subject: Tests for the SCORU storage module +*) + +open Protocol +module Commitment_repr = Sc_rollup_commitment_repr + +(** [new_context_n n] creates a context with [n] accounts. *) +let new_context_n nb_stakers = + let open Lwt_result_syntax in + let* b, contracts = Context.init_n nb_stakers () in + let+ inc = Incremental.begin_construction b in + let ctxt = Incremental.alpha_ctxt inc in + (* Necessary to originate rollups. *) + let ctxt = Alpha_context.Origination_nonce.init ctxt Operation_hash.zero in + let ctxt = Alpha_context.Internal_for_tests.to_raw ctxt in + let accounts = + List.map + (function + | Alpha_context.Contract.Implicit key -> key | _ -> assert false) + contracts + in + (ctxt, accounts) + +let new_context () = + let open Lwt_result_syntax in + (* A context needs at least one account to bake. *) + let* ctxt, _accounts = new_context_n 1 in + return ctxt + +let new_context_1 () = + let open Lwt_result_syntax in + let* ctxt, accounts = new_context_n 1 in + match accounts with [account] -> return (ctxt, account) | _ -> assert false + +let new_context_2 () = + let open Lwt_result_syntax in + let* ctxt, accounts = new_context_n 2 in + match accounts with + | [account1; account2] -> return (ctxt, account1, account2) + | _ -> assert false + +let new_sc_rollup ctxt = + let open Lwt_result_wrap_syntax in + let {Michelson_v1_parser.expanded; _}, _ = + Michelson_v1_parser.parse_expression "unit" + in + let parameters_ty = Alpha_context.Script.lazy_expr expanded in + let boot_sector = "" in + let kind = Sc_rollups.Kind.Example_arith in + let*! genesis_commitment = + Sc_rollup_helpers.genesis_commitment_raw + ~boot_sector + ~origination_level:(Raw_context.current_level ctxt).level + kind + in + let* rollup, _size, genesis_hash, ctxt = + Sc_rollup_storage.originate ctxt ~kind ~parameters_ty ~genesis_commitment + in + return (rollup, genesis_hash, ctxt) + +let new_context_with_stakers_and_rollup nb_stakers = + let open Lwt_result_wrap_syntax in + let* ctxt, stakers = new_context_n nb_stakers in + let+@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + (ctxt, rollup, genesis_hash, stakers) + +let new_context_with_rollup () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let+@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + (ctxt, rollup, genesis_hash) + +let equal_tez ~loc = + Assert.equal ~loc Tez_repr.( = ) "Tez aren't equal" Tez_repr.pp + +let assert_not_exist ~loc ~pp comp_lwt = + let open Lwt_result_syntax in + let* _ctxt, res_opt = comp_lwt in + Assert.is_none ~loc ~pp res_opt + +let assert_balance_changed op ctxt ctxt' account amount = + let open Lwt_result_wrap_syntax in + let*@ _, balance = Token.Internal_for_tests.balance ctxt account in + let*@ _, balance' = Token.Internal_for_tests.balance ctxt' account in + let*?@ balance_op_amount = op balance amount in + equal_tez balance' ~loc:__LOC__ balance_op_amount + +let assert_balance_increased ctxt ctxt' account amount = + assert_balance_changed Tez_repr.( +? ) ctxt ctxt' account amount + +let assert_balance_decreased ctxt ctxt' account amount = + assert_balance_changed Tez_repr.( -? ) ctxt ctxt' account amount + +let perform_staking_action_and_check ctxt rollup staker do_and_check = + let staker_contract = Contract_repr.Implicit staker in + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + do_and_check ctxt rollup staker_contract stake + +let number_of_ticks_exn n = + match Sc_rollup_repr.Number_of_ticks.of_value n with + | Some x -> x + | None -> Stdlib.failwith "Bad Number_of_ticks" + +module Zero = struct + let staker = Sc_rollup_repr.Staker.zero + + let commitment = + Commitment_repr. + { + compressed_state = Sc_rollup_repr.State_hash.zero; + inbox_level = Raw_level_repr.root; + predecessor = Hash.zero; + number_of_ticks = number_of_ticks_exn 1L; + } + + let commitment_hash = Commitment_repr.Hash.zero + + let rollup = Sc_rollup_repr.Address.zero +end + +let deposit_stake_and_check_balances ctxt rollup staker = + let open Lwt_result_wrap_syntax in + perform_staking_action_and_check + ctxt + rollup + staker + (fun ctxt rollup staker_contract stake -> + let*@ ctxt', _, _ = + Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + rollup + staker + in + let* () = + assert_balance_decreased ctxt ctxt' (`Contract staker_contract) stake + in + let bond_id = Bond_id_repr.Sc_rollup_bond_id rollup in + let bonds_account = `Frozen_bonds (staker_contract, bond_id) in + let+ () = assert_balance_increased ctxt ctxt' bonds_account stake in + ctxt') + +(** Originate a rollup with [nb_stakers] stakers and make a deposit to the + initial LCC. *) +let originate_rollup_and_deposit_with_n_stakers nb_stakers = + let open Lwt_result_syntax in + let* ctxt, rollup, genesis_hash, stakers = + new_context_with_stakers_and_rollup nb_stakers + in + let deposit ctxt staker = + deposit_stake_and_check_balances ctxt rollup staker + in + let+ ctxt = List.fold_left_es deposit ctxt stakers in + (ctxt, rollup, genesis_hash, stakers) + +(** Originate a rollup with one staker and make a deposit to the initial LCC. *) +let originate_rollup_and_deposit_with_one_staker () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker = new_context_1 () in + let*@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + let+ ctxt = deposit_stake_and_check_balances ctxt rollup staker in + (ctxt, rollup, genesis_hash, staker) + +(** Originate a rollup with two stakers and make a deposit to the initial LCC. +*) +let originate_rollup_and_deposit_with_two_stakers () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker1, staker2 = new_context_2 () in + let*@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + let* ctxt = deposit_stake_and_check_balances ctxt rollup staker1 in + let+ ctxt = deposit_stake_and_check_balances ctxt rollup staker2 in + (ctxt, rollup, genesis_hash, staker1, staker2) + +(** Originate a rollup with three stakers and make a deposit to the initial LCC. +*) +let originate_rollup_and_deposit_with_three_stakers () = + let open Lwt_result_syntax in + let+ ctxt, rollup, genesis_hash, stakers = + originate_rollup_and_deposit_with_n_stakers 3 + in + match stakers with + | [staker1; staker2; staker3] -> + (ctxt, rollup, genesis_hash, staker1, staker2, staker3) + | _ -> assert false + +(** Trivial assertion. + + By convention, context is passed linearly as [ctxt]. This takes a context + argument to allow this. +*) +let assert_true _ctxt = Lwt_result_syntax.return_unit + +(** Assert that the computation fails with the given message. *) +let assert_fails_with ~loc k expected_err = + let open Lwt_result_wrap_syntax in + let*!@ res = k in + Assert.proto_error ~loc res (( = ) expected_err) + +let assert_fails_with_f ~loc k pred = + let open Lwt_result_wrap_syntax in + let*!@ res = k in + Assert.proto_error ~loc res pred + +let assert_fails ~loc k = + let open Lwt_result_wrap_syntax in + let*!@ res = k in + Assert.error ~loc res (fun _ -> true) + +(** Assert operation fails because of missing rollup *) +let assert_fails_with_missing_rollup ~loc op = + let open Lwt_result_syntax in + let* ctxt = new_context () in + assert_fails_with + ~loc + (op ctxt Zero.rollup) + (Sc_rollup_errors.Sc_rollup_does_not_exist Zero.rollup) + +(** Assert commitment hash equality. *) +let assert_commitment_hash_equal ~loc x y = + Assert.equal + ~loc + Commitment_repr.Hash.equal + "Compare commitment hash" + Commitment_repr.Hash.pp + x + y + +let assert_level_equal ~loc = + Assert.equal ~loc Raw_level_repr.equal "Compare raw level" Raw_level_repr.pp + +let commitment_equal + Commitment_repr. + { + compressed_state = c1; + inbox_level = l1; + predecessor = p1; + number_of_ticks = n1; + } + Commitment_repr. + { + compressed_state = c2; + inbox_level = l2; + predecessor = p2; + number_of_ticks = n2; + } = + Sc_rollup_repr.State_hash.equal c1 c2 + && Raw_level_repr.equal l1 l2 + && Commitment_repr.Hash.equal p1 p2 + && Sc_rollup_repr.Number_of_ticks.equal n1 n2 + +let assert_commitment_equal ~loc x y = + Assert.equal ~loc commitment_equal "Compare commitment" Commitment_repr.pp x y + +let assert_commitments_with_levels_equal ~loc cs1 cs2 = + let commitment_with_level_pp ppf (hash, level) = + Format.fprintf + ppf + "(%a, %a)" + Sc_rollup_commitment_repr.Hash.pp + hash + Raw_level_repr.pp + level + in + Assert.assert_equal_list + ~loc + (fun (commitment1, level1) (commitment2, level2) -> + Sc_rollup_commitment_repr.Hash.(commitment1 = commitment2) + && Raw_level_repr.(level1 = level2)) + "Unexpected list of cemented commitments" + commitment_with_level_pp + cs1 + cs2 + +(* Artificially advance current level to make stake refinement possible. + The commitment can be posted after the inbox level commited. For example, + if you post a commitment for the inbox level 32, you will be able to + publish the commitment at level 33. +*) +let advance_level_for_commitment ctxt (commitment : Commitment_repr.t) = + let cur_level = Level_storage.(current ctxt).level in + if cur_level > commitment.inbox_level then ctxt + else + let offset = + let open Raw_level_repr in + let open Int32 in + succ @@ sub (to_int32 commitment.inbox_level) (to_int32 cur_level) + in + Raw_context.Internal_for_tests.add_level ctxt (Int32.to_int offset) + +let advance_level_for_cement ctxt rollup (commitment : Commitment_repr.t) = + let open Lwt_result_syntax in + let* ctxt, commitment_added = + Storage.Sc_rollup.Commitment_added.get + (ctxt, rollup) + (Commitment_repr.hash_uncarbonated commitment) + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let cur_level = Level_storage.(current ctxt).level in + let target_level = Raw_level_repr.add commitment_added challenge_window in + if cur_level > target_level then return ctxt + else + let offset = Raw_level_repr.diff target_level cur_level in + return (Raw_context.Internal_for_tests.add_level ctxt (Int32.to_int offset)) + +let advance_level_n_refine_stake ctxt rollup staker commitment = + let ctxt = advance_level_for_commitment ctxt commitment in + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker + commitment + +let valid_inbox_level ctxt = + let root_level = Level_storage.(current ctxt).level in + let commitment_freq = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + fun i -> + Raw_level_repr.add + root_level + Int32.(to_int (mul (of_int commitment_freq) i)) + +(** A more precise version of {!valid_inbox_level}. Not used everywhere + as it requires more information than {!valid_inbox_level} and is in + the lwt tzresult monad. *) +let proper_valid_inbox_level (ctxt, rollup) i = + let open Lwt_result_syntax in + let+ _, {level = genesis_level; _} = + Sc_rollup_storage.genesis_info ctxt rollup + in + let commitment_freq = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + Raw_level_repr.add genesis_level (commitment_freq * i) + +let commitment ?compressed_state ?predecessor ?inbox_level ?number_of_ticks () = + let commitment = + Commitment_repr. + { + compressed_state = + Option.value + ~default:Zero.commitment.compressed_state + compressed_state; + predecessor = + Option.value ~default:Zero.commitment.predecessor predecessor; + inbox_level = + Option.value ~default:Zero.commitment.inbox_level inbox_level; + number_of_ticks = + Option.value ~default:Zero.commitment.number_of_ticks number_of_ticks; + } + in + (commitment, Commitment_repr.hash_uncarbonated commitment) + +(** [commitments ~predecessor ?start_at_level ctxt n] creates a branch of + commitment starting at [valid_inbox_level ctxt start_at_level] and with + [predecessor] as commitment's predecessor. The branch is [n] elements + deep. *) +let commitments ~predecessor ?(start_at = 1l) ctxt n = + let n = Int32.(add (of_int n) start_at) in + let rec go predecessor acc l = + if n = l then acc + else + let inbox_level = valid_inbox_level ctxt l in + let commitment, hash = commitment ~predecessor ~inbox_level () in + go hash (commitment :: acc) (Int32.succ l) + in + List.rev (go predecessor [] start_at) + +let publish_commitment ctxt rollup staker commitment = + let open Lwt_result_syntax in + let ctxt = advance_level_for_commitment ctxt commitment in + let* _hash, _publication_level, ctxt, _balance_updates = + Sc_rollup_stake_storage.publish_commitment ctxt rollup staker commitment + in + return ctxt + +let publish_commitments ctxt rollup staker commitments = + List.fold_left_es + (fun ctxt commitment -> publish_commitment ctxt rollup staker commitment) + ctxt + commitments + +let cement_commitment ctxt rollup commitment = + let open Lwt_result_syntax in + let* ctxt = advance_level_for_cement ctxt rollup commitment in + let* ctxt, _commitment, _commitment_hash = + Sc_rollup_stake_storage.cement_commitment ctxt rollup + in + return ctxt + +let cement_commitments ctxt rollup commitments = + List.fold_left_es + (fun ctxt commitment -> cement_commitment ctxt rollup commitment) + ctxt + commitments + +let publish_and_cement_commitment ctxt rollup staker commitment = + let open Lwt_result_syntax in + let* ctxt = publish_commitment ctxt rollup staker commitment in + cement_commitment ctxt rollup commitment + +let publish_and_cement_commitments ctxt rollup staker commitments = + List.fold_left_es + (fun ctxt commitment -> + publish_and_cement_commitment ctxt rollup staker commitment) + ctxt + commitments + +let withdraw ctxt rollup staker = + let open Lwt_result_syntax in + let* ctxt, _balance_updates = + Sc_rollup_stake_storage.withdraw_stake ctxt rollup staker + in + return ctxt + +let assert_staker_exists ctxt rollup staker = + let open Lwt_result_wrap_syntax in + (* Assert the stake was frozen from the balance. *) + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + let*@ frozen_balance = + Contract_storage.(get_frozen_bonds ctxt (Contract_repr.Implicit staker)) + in + let* () = equal_tez ~loc:__LOC__ stake frozen_balance in + (* Assert [staker] was given an index. *) + let*@ ctxt, staker_index_opt = + Sc_rollup_staker_index_storage.find_staker_index_unsafe ctxt rollup staker + in + let* staker_index = Assert.get_some ~loc:__LOC__ staker_index_opt in + let*@ _ctxt, exists = + Sc_rollup_staker_index_storage.is_active ctxt rollup staker_index + in + Assert.equal_bool ~loc:__LOC__ true exists + +let assert_staker_dont_exists ctxt rollup staker = + let open Lwt_result_wrap_syntax in + (* Assert no stake was frozen from the balance. *) + let*@ frozen_balance = + Contract_storage.(get_frozen_bonds ctxt (Contract_repr.Implicit staker)) + in + let* () = equal_tez ~loc:__LOC__ Tez_repr.zero frozen_balance in + (* Assert [staker] has no index. *) + let*@ _ctxt, staker_index_opt = + Sc_rollup_staker_index_storage.find_staker_index_unsafe ctxt rollup staker + in + Assert.is_none ~loc:__LOC__ ~pp:Z.pp_print (staker_index_opt :> Z.t option) + +let assert_staked_or_not ~staked ctxt rollup hash staker = + let open Lwt_result_wrap_syntax in + let*@ _ctxt, stakers_index = + Storage.Sc_rollup.Commitment_stakers.get (ctxt, rollup) hash + in + let*@ _ctxt, staker_index = + Sc_rollup_staker_index_storage.get_staker_index_unsafe ctxt rollup staker + in + Assert.equal_bool + ~loc:__LOC__ + staked + (List.mem ~equal:Z.equal (staker_index :> Z.t) (stakers_index :> Z.t list)) + +let assert_staked_on = assert_staked_or_not ~staked:true + +let assert_not_staked_on = assert_staked_or_not ~staked:false + +let assert_commitment_metadata_exists ?publication_level ctxt rollup commitment + staker = + let open Lwt_result_wrap_syntax in + (* Assert the commitment's metadata exists. *) + let hash = Commitment_repr.hash_uncarbonated commitment in + let*@ _ctxt, actual_publication_level = + Storage.Sc_rollup.Commitment_added.get (ctxt, rollup) hash + in + let* () = + match publication_level with + | None -> return_unit + | Some publication_level -> + assert_level_equal + ~loc:__LOC__ + publication_level + actual_publication_level + in + let* () = assert_staked_on ctxt rollup hash staker in + let*@ _ctxt, commitments_hash = + Storage.Sc_rollup.Commitments_per_inbox_level.get + (ctxt, rollup) + commitment.inbox_level + in + Assert.equal_bool + ~loc:__LOC__ + true + (List.mem ~equal:Commitment_repr.Hash.equal hash commitments_hash) + +let assert_commitment_exists ctxt rollup commitment = + let open Lwt_result_wrap_syntax in + (* Assert commitment exists. *) + let hash = Commitment_repr.hash_uncarbonated commitment in + let*@ actual_commitment_opt, _ctxt = + Sc_rollup_commitment_storage.get_commitment_opt_unsafe ctxt rollup hash + in + let* actual_commitment = Assert.get_some ~loc:__LOC__ actual_commitment_opt in + let* () = assert_commitment_equal ~loc:__LOC__ commitment actual_commitment in + return_unit + +let assert_commitment_metadata_dont_exists ctxt rollup commitment = + let open Lwt_result_wrap_syntax in + (* Assert the commitment's metadata dont exists. *) + let hash = Commitment_repr.hash_uncarbonated commitment in + let*@ _ctxt, exists = + Storage.Sc_rollup.Commitment_added.mem (ctxt, rollup) hash + in + let* () = Assert.equal_bool ~loc:__LOC__ false exists in + let*@ _ctxt, exists = + Storage.Sc_rollup.Commitment_stakers.mem (ctxt, rollup) hash + in + let* () = Assert.equal_bool ~loc:__LOC__ false exists in + let*@ _ctxt, exists = + Storage.Sc_rollup.Commitments_per_inbox_level.mem + (ctxt, rollup) + commitment.inbox_level + in + Assert.equal_bool ~loc:__LOC__ false exists + +let assert_commitment_dont_exists ctxt rollup commitment = + let open Lwt_result_wrap_syntax in + let hash = Commitment_repr.hash_uncarbonated commitment in + let*@ commitment_opt, _ctxt = + Sc_rollup_commitment_storage.get_commitment_opt_unsafe ctxt rollup hash + in + Assert.is_none ~loc:__LOC__ ~pp:Commitment_repr.pp commitment_opt + +(** {2. Tests} *) + +module Stake_storage_tests = struct + let test_last_cemented_commitment_hash_with_level_when_genesis () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let*@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + let*@ c1, inbox_level, ctxt = + Sc_rollup_commitment_storage.last_cemented_commitment_hash_with_level + ctxt + rollup + in + let* () = assert_commitment_hash_equal ~loc:__LOC__ genesis_hash c1 in + Assert.equal_int32 + ~loc:__LOC__ + (Raw_level_repr.to_int32 (Raw_context.current_level ctxt).level) + (Raw_level_repr.to_int32 inbox_level) + + (** {2. Deposit unit tests.} *) + + (** Test that deposit initializes the metadata for the staker. *) + let test_deposit () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker = new_context_1 () in + let contract_staker = Contract_repr.Implicit staker in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + let*@ ctxt_after_deposit, _balance_updates, _staker_index = + Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + rollup + staker + in + (* Assert [staker]'s metadata exists. *) + let* () = assert_staker_exists ctxt_after_deposit rollup staker in + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + (* Assert [staker]'s balance decreased of [stake]. *) + let* () = + assert_balance_decreased + ctxt + ctxt_after_deposit + (`Contract contract_staker) + stake + in + let bond_id = Bond_id_repr.Sc_rollup_bond_id rollup in + let bonds_account = `Frozen_bonds (contract_staker, bond_id) in + (* Assert [bond_account]'s balance increased of [stake]. *) + let* () = + assert_balance_increased ctxt ctxt_after_deposit bonds_account stake + in + return_unit + + (** Test that deposit fails if the staker is underfunded. *) + let test_deposit_by_underfunded_staker () = + let open Lwt_result_wrap_syntax in + let* ctxt, sc_rollup, _genesis_hash = new_context_with_rollup () in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn + "tz1hhNZvjed6McQQLWtR7MRzPHpgSFZTXxdW" + in + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + let* () = + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + sc_rollup + staker) + (Sc_rollup_errors.Sc_rollup_staker_funds_too_low + { + staker; + sc_rollup; + staker_balance = Tez_repr.zero; + min_expected_balance = stake; + }) + in + let*?@ staker_balance = Tez_repr.(stake /? 2L) in + let staker_contract = Contract_repr.Implicit staker in + let*@ ctxt, _ = + Token.transfer ctxt `Minted (`Contract staker_contract) staker_balance + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + sc_rollup + staker) + (Sc_rollup_errors.Sc_rollup_staker_funds_too_low + {staker; sc_rollup; staker_balance; min_expected_balance = stake}) + + (** Test that a staker can deposit and then withdraw. *) + let test_deposit_then_withdraw () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, _genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let* () = assert_staker_exists ctxt rollup staker in + let*@ ctxt, _balance_updates = + Sc_rollup_stake_storage.withdraw_stake ctxt rollup staker + in + assert_staker_dont_exists ctxt rollup staker + + (** Test that an account can stake on more than one rollup. *) + let test_deposit_on_two_rollups () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker = new_context_1 () in + let assert_frozen_balance ctxt staker expected = + let*@ frozen_balance = + Contract_storage.(get_frozen_bonds ctxt (Contract_repr.Implicit staker)) + in + equal_tez ~loc:__LOC__ expected frozen_balance + in + let stake = Constants_storage.sc_rollup_stake_amount ctxt in + let* () = assert_frozen_balance ctxt staker Tez_repr.zero in + let*@ rollup1, _genesis_hash, ctxt = new_sc_rollup ctxt in + let*@ ctxt, _balance_updates, _staker_index = + Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + rollup1 + staker + in + let* () = assert_frozen_balance ctxt staker stake in + let*@ rollup2, _genesis_hash, ctxt = new_sc_rollup ctxt in + let*@ ctxt, _balance_updates, _staker_index = + Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + rollup2 + staker + in + let*?@ stake_times_2 = Tez_repr.(stake *? 2L) in + assert_frozen_balance ctxt staker stake_times_2 + + (** Test that deposit twice on the same rollup fails. *) + let test_deposit_twice_fails () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker = new_context_1 () in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + let*@ ctxt, _balance_updates, _staker_index = + Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + rollup + staker + in + assert_fails + ~loc:__LOC__ + (Sc_rollup_stake_storage.Internal_for_tests.deposit_stake + ctxt + rollup + staker) + + (** {2. Publish unit tests.} *) + + (** Test that the staker, the commitment and its metadata exist after + the publish. *) + let test_publish () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker = new_context_1 () in + let*@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment in + (* The staker exists as a stake was deposited. *) + let* () = assert_staker_exists ctxt rollup staker in + (* The commitment and its metadata exists in the storage. *) + let* () = assert_commitment_exists ctxt rollup commitment in + let* () = assert_commitment_metadata_exists ctxt rollup commitment staker in + return_unit + + (** Test that publish twice to the same level is not allowed. *) + let test_publish_twice () = + let open Lwt_result_wrap_syntax in + let* ctxt, staker = new_context_1 () in + let*@ rollup, genesis_hash, ctxt = new_sc_rollup ctxt in + let commitment, hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment in + let* () = assert_commitment_exists ctxt rollup commitment in + let* () = assert_commitment_metadata_exists ctxt rollup commitment staker in + (* Assert that publishing twice the same commitment fails. *) + let* () = + assert_fails_with + ~loc:__LOC__ + (publish_commitment ctxt rollup staker commitment) + (Sc_rollup_errors.Sc_rollup_double_publish hash) + in + (* Assert that publishing twice to the same inbox level but with + distinct commitment fails. *) + let new_commitment = + { + commitment with + compressed_state = + Sc_rollup_repr.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["honest"]); + } + in + let* () = + assert_fails_with + ~loc:__LOC__ + (publish_commitment ctxt rollup staker new_commitment) + Sc_rollup_errors.Sc_rollup_staker_double_stake + in + return_unit + + (** Test that the entrypoint [publish] fails with a nice error if + the rollup is missing. *) + let test_publish_to_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> + Sc_rollup_stake_storage.publish_commitment + ctxt + rollup + Zero.staker + Zero.commitment) + + (** Test that publish to a wrong inbox level is forbidden. *) + let test_publish_wrong_inbox_level () = + let open Lwt_result_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(Raw_level_repr.of_int32_exn 42l) + () + in + assert_fails_with + ~loc:__LOC__ + (publish_commitment ctxt rollup staker commitment) + Sc_rollup_errors.Sc_rollup_bad_inbox_level + + (** Test that two stakers can publish the same commitment. *) + let test_publish_existing_commitment () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = publish_commitment ctxt rollup staker1 commitment in + let*@ ctxt = publish_commitment ctxt rollup staker2 commitment in + (* [staker2] does exist and stakes on [commitment]. *) + let* () = assert_staker_exists ctxt rollup staker2 in + let* () = + assert_commitment_metadata_exists ctxt rollup commitment staker2 + in + let* () = assert_commitment_exists ctxt rollup commitment in + return_unit + + (** Test that publish returns the oldest level at which the commitment + was published. *) + let test_publish_returns_oldest_publish_level () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let ctxt = advance_level_for_commitment ctxt commitment in + let*@ _hash, publish_level, ctxt, _balance_updates = + Sc_rollup_stake_storage.publish_commitment ctxt rollup staker1 commitment + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt 42 in + let*@ _hash, publish_level', _ctxt, _balance_updates = + Sc_rollup_stake_storage.publish_commitment ctxt rollup staker2 commitment + in + Assert.equal_int32 + ~loc:__LOC__ + (Raw_level_repr.to_int32 publish_level) + (Raw_level_repr.to_int32 publish_level') + + (** Test that a commitment can not be published from the future. *) + let test_publish_fails_on_commitment_from_future () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let inbox_level = valid_inbox_level ctxt 1l in + let commitment, _hash = + commitment ~predecessor:genesis_hash ~inbox_level () + in + let* () = + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.publish_commitment + ctxt + rollup + staker + commitment) + (Sc_rollup_errors.Sc_rollup_commitment_from_future + {current_level = Raw_level_repr.of_int32_exn 1l; inbox_level}) + in + let ctxt = advance_level_for_commitment ctxt commitment in + let*@ _hash, _publish_level, ctxt, _balance_updates = + Sc_rollup_stake_storage.publish_commitment ctxt rollup staker commitment + in + let* () = assert_commitment_exists ctxt rollup commitment in + assert_commitment_metadata_exists ctxt rollup commitment staker + + (** Test that a staker can publish a commitment when its last commimtent was + cemented. *) + let test_publish_from_behind_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let level l = valid_inbox_level ctxt l in + let level1 = level 1l in + let level2 = level 2l in + let commitment1, hash = + commitment ~predecessor:genesis_hash ~inbox_level:level1 () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment1 in + let*@ ctxt = cement_commitment ctxt rollup commitment1 in + let commitment2, _hash = + commitment ~predecessor:hash ~inbox_level:level2 () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment2 in + let* () = assert_commitment_exists ctxt rollup commitment2 in + assert_commitment_metadata_exists ctxt rollup commitment2 staker + + (** Test that a staker can join another staker's branch without + staking explicitely on each commitment. *) + let test_publish_anywhere_on_branch () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + (* staker1 creates a first branch. *) + let commitments = commitments ~predecessor:genesis_hash ctxt 10 in + let*@ ctxt = publish_commitments ctxt rollup staker1 commitments in + + (* staker2 will stake on only one commitment. *) + let to_stake_commitment = Stdlib.List.nth commitments 6 in + let not_staked_commitments = + List.filter (( <> ) to_stake_commitment) commitments + in + let*@ ctxt = publish_commitment ctxt rollup staker2 to_stake_commitment in + (* Assert [staker2] is staked on [to_stake_commitment] and not on + other commitments. *) + let* () = + assert_staked_on + ctxt + rollup + (Commitment_repr.hash_uncarbonated to_stake_commitment) + staker2 + in + let* () = + List.iter_es + (fun commitment -> + assert_not_staked_on + ctxt + rollup + (Commitment_repr.hash_uncarbonated commitment) + staker2) + not_staked_commitments + in + return_unit + + (** Test that a commitment needs to have a predecessor. *) + let test_publish_without_predecessor_fails () = + let open Lwt_result_syntax in + let* ctxt, rollup, _genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let commitment, _hash = + commitment ~inbox_level:(valid_inbox_level ctxt 42l) () + in + assert_fails_with + ~loc:__LOC__ + (publish_commitment ctxt rollup staker commitment) + (Sc_rollup_errors.Sc_rollup_unknown_commitment commitment.predecessor) + + (** Test that publishing a commitment at the LCC or behind it fails. *) + let test_publish_behind_or_at_lcc_fails () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let commitments = commitments ~predecessor:genesis_hash ctxt 10 in + let*@ ctxt = + publish_and_cement_commitments ctxt rollup staker commitments + in + let*@ _ctxt, last_cemented_inbox_level, _ = + Sc_rollup_commitment_storage.last_cemented_commitment_hash_with_level + ctxt + rollup + in + (* Trying to publish a commitment behind or at lcc will fail. *) + List.iter_es + (fun commitment -> + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.publish_commitment + ctxt + rollup + staker + commitment) + (Sc_rollup_errors.Sc_rollup_commitment_too_old + { + commitment_inbox_level = commitment.inbox_level; + last_cemented_inbox_level; + })) + commitments + + (** {2. Cement unit tests.} *) + + (** Test that cement cleans the commitment's metadata. *) + let test_cement () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment in + let* () = assert_commitment_exists ctxt rollup commitment in + let* () = assert_commitment_metadata_exists ctxt rollup commitment staker in + let*@ ctxt = cement_commitment ctxt rollup commitment in + assert_commitment_metadata_dont_exists ctxt rollup commitment + + (** Test that the entrypoint [cement] fails with a nice error if + the rollup is missing. *) + let test_cement_to_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> + Sc_rollup_stake_storage.cement_commitment ctxt rollup) + + (** Test that if [n] stakers stake on the same commitment, it can be + cemented. *) + let test_cement_with_n_stakers () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, stakers = + originate_rollup_and_deposit_with_n_stakers 10 + in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = + List.fold_left_es + (fun ctxt staker -> publish_commitment ctxt rollup staker commitment) + ctxt + stakers + in + let*@ ctxt = cement_commitment ctxt rollup commitment in + assert_commitment_metadata_dont_exists ctxt rollup commitment + + (** Create and cement three commitments: + + [c3 -> c2 -> c1 -> Commitment_hash.zero] + + This is useful to catch potential issues with de-allocation of [c2], + as we deallocate the old LCC when a new LCC is cemented. + *) + let test_cement_n_commitments () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let commitments = commitments ~predecessor:genesis_hash ctxt 10 in + let*@ ctxt = publish_commitments ctxt rollup staker commitments in + let*@ ctxt = + advance_level_for_cement + ctxt + rollup + (List.rev commitments |> Stdlib.List.hd) + in + let*@ _ctxt, cemented_commitments = + List.fold_left_es + (fun (ctxt, acc) _commitment -> + let* ctxt, cemented_commitment, _cemented_commitment_hash = + Sc_rollup_stake_storage.cement_commitment ctxt rollup + in + return (ctxt, cemented_commitment :: acc)) + (ctxt, []) + commitments + in + let* () = + List.iter2_es + ~when_different_lengths:[] + (fun commitment cemented_commitment -> + assert_commitment_equal ~loc:__LOC__ commitment cemented_commitment) + commitments + (List.rev cemented_commitments) + in + return_unit + + (** Test that a number of commitments are saved in the storage after + cementation, and other are completely removed. Note that the + metadata for both saved and removed commitments are removed. *) + let test_cement_clean_commitments () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let max_number_of_stored_commitments = + Constants_storage.max_number_of_stored_cemented_commitments ctxt + in + let commitments = + commitments + ~predecessor:genesis_hash + ctxt + (max_number_of_stored_commitments * 2) + in + let*@ ctxt = publish_commitments ctxt rollup staker commitments in + let*@ ctxt = cement_commitments ctxt rollup commitments in + (* Assert that [max_number_of_stored_commitments] cemented commitments + exists, i.e. the commitment and not its metadata. The rest are cleaned. *) + let* () = + List.iter_es + (assert_commitment_metadata_dont_exists ctxt rollup) + commitments + in + let removed_commitments, saved_commitments = + List.split_n max_number_of_stored_commitments commitments + in + let* () = + List.iter_es + (assert_commitment_dont_exists ctxt rollup) + removed_commitments + in + let* () = + List.iter_es + (fun commitment -> assert_commitment_exists ctxt rollup commitment) + saved_commitments + in + return_unit + + let test_cement_conflicted_branches () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2, staker3 = + originate_rollup_and_deposit_with_three_stakers () + in + + (* Create an honest and dishonest branch. *) + let honest_commitment, honest_commitment_hash = + let compressed_state = + Sc_rollup_repr.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["honest"]) + in + commitment + ~predecessor:genesis_hash + ~compressed_state + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let honest_commitments = + honest_commitment + :: commitments ~predecessor:honest_commitment_hash ~start_at:2l ctxt 10 + in + let dishonest_commitment, dishonest_commitment_hash = + let compressed_state = + Sc_rollup_repr.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["dishonest"]) + in + commitment + ~predecessor:genesis_hash + ~compressed_state + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let dishonest_commitments = + dishonest_commitment + :: commitments ~predecessor:dishonest_commitment_hash ~start_at:2l ctxt 10 + in + (* Conflict begins. *) + let*@ ctxt = publish_commitments ctxt rollup staker1 honest_commitments in + let*@ ctxt = + publish_commitments ctxt rollup staker2 dishonest_commitments + in + let*@ ctxt = + publish_commitments ctxt rollup staker3 dishonest_commitments + in + + (* No one can cement their branches. *) + let cant_cement ctxt = + List.iter_es (fun commitment -> + assert_fails_with_f + ~loc:__LOC__ + (cement_commitment ctxt rollup commitment) + (let open Sc_rollup_errors in + function + | Sc_rollup_disputed | Sc_rollup_parent_not_lcc + | Raw_context.Storage_error (Missing_key _) (* missing commitment *) + -> + true + | _ -> false)) + in + let* () = cant_cement ctxt honest_commitments in + let* () = cant_cement ctxt dishonest_commitments in + + (* Simulate a conflict's resolution through [remove_staker]. *) + let*@ ctxt, _balance_updates = + Sc_rollup_stake_storage.remove_staker ctxt rollup staker2 + in + (* [staker1] is not yet able to cement, [staker3] still stake on the + dishonest branch. *) + let* () = cant_cement ctxt honest_commitments in + (* Simulate the second conflict's resolution. *) + let*@ ctxt, _balance_updates = + Sc_rollup_stake_storage.remove_staker ctxt rollup staker3 + in + (* [staker1] can now cement its branch. The dishonest branch can not + be cemented, before and after the honest branch was cemented. *) + let*@ _ctxt = cement_commitments ctxt rollup honest_commitments in + return_unit + + (** {2. Withdraw unit tests.} *) + + (** Test that the entrypoint [withdraw] fails with a nice error if + the rollup is missing. *) + let test_withdraw_to_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> + Sc_rollup_stake_storage.withdraw_stake ctxt rollup Zero.staker) + + (* Test that withdraw fail if the account has not deposited. *) + let test_withdraw_when_not_staked () = + let open Lwt_result_wrap_syntax in + let* ctxt, account = new_context_1 () in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.withdraw_stake ctxt rollup account) + Sc_rollup_errors.Sc_rollup_not_staked + + (** Test that you can withdraw only once (you need to deposit again). *) + let test_withdraw_twice_fails () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, _genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let*@ ctxt, _balance_updates = + Sc_rollup_stake_storage.withdraw_stake ctxt rollup staker + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.withdraw_stake ctxt rollup staker) + Sc_rollup_errors.Sc_rollup_not_staked + + (** Test that withdraw when the stakers's newest staked commitment is + after the LCC fails. *) + let test_withdraw_fails_staked_after_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.withdraw_stake ctxt rollup staker) + Sc_rollup_errors.Sc_rollup_not_staked_on_lcc_or_ancestor + + (** Test that withdraw succeeds when the the staker staked on a branch older + than the LCC. *) + let test_withdraw_staked_before_or_at_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitments = commitments ~predecessor:genesis_hash ctxt 10 in + let commitment, commitments = + match commitments with x :: xs -> (x, xs) | _ -> assert false + in + let*@ ctxt = publish_commitment ctxt rollup staker1 commitment in + let*@ ctxt = publish_commitments ctxt rollup staker2 commitments in + let*@ ctxt = cement_commitment ctxt rollup commitment in + let*@ ctxt = cement_commitments ctxt rollup commitments in + let*@ _ctxt = withdraw ctxt rollup staker1 in + return_unit + + (** Test that [remove_staker] cleans the stakers' metadata. *) + let test_remove_staker () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, _genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let*@ ctxt, _balance_updates = + Sc_rollup_stake_storage.remove_staker ctxt rollup staker + in + assert_staker_dont_exists ctxt rollup staker + + (** Test that a staker can come back after being slashed. *) + let test_come_back_after_remove_staker () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let* () = assert_staker_exists ctxt rollup staker in + let commitment, _hash = + commitment + ~predecessor:genesis_hash + ~inbox_level:(valid_inbox_level ctxt 1l) + () + in + let*@ ctxt = publish_commitment ctxt rollup staker commitment in + let* () = assert_commitment_exists ctxt rollup commitment in + let* () = assert_commitment_metadata_exists ctxt rollup commitment staker in + (* We simulate a conflict resolution through [remove_staker] *) + let*@ ctxt, _balance_updates = + Sc_rollup_stake_storage.remove_staker ctxt rollup staker + in + let* () = assert_staker_dont_exists ctxt rollup staker in + (* The staker can come back through a new index. *) + let new_commitment = + { + commitment with + compressed_state = + Sc_rollup_repr.State_hash.context_hash_to_state_hash + (Context_hash.hash_string ["honest"]); + } + in + let*@ ctxt = publish_commitment ctxt rollup staker new_commitment in + let* () = assert_commitment_exists ctxt rollup new_commitment in + let* () = + assert_commitment_metadata_exists ctxt rollup new_commitment staker + in + let* () = assert_staker_exists ctxt rollup staker in + (* Furthermore, the commitment can be cemented. *) + let*@ _ctxt = cement_commitment ctxt rollup commitment in + return_unit + + let assert_balance_unchanged ctxt ctxt' account = + let open Lwt_result_wrap_syntax in + let*@ _, balance = Token.Internal_for_tests.balance ctxt account in + let*@ _, balance' = Token.Internal_for_tests.balance ctxt' account in + equal_tez ~loc:__LOC__ balance' balance + + let remove_staker_and_check_balances ctxt rollup staker = + let open Lwt_result_wrap_syntax in + perform_staking_action_and_check + ctxt + rollup + staker + (fun ctxt rollup staker_contract stake -> + let*@ ctxt', _ = + Sc_rollup_stake_storage.remove_staker ctxt rollup staker + in + let* () = + assert_balance_unchanged ctxt ctxt' (`Contract staker_contract) + in + let bond_id = Bond_id_repr.Sc_rollup_bond_id rollup in + let bonds_account = `Frozen_bonds (staker_contract, bond_id) in + let+ () = assert_balance_decreased ctxt ctxt' bonds_account stake in + ctxt') + + let produce_and_refine ctxt ~number_of_commitments ?(start_at_level = 1) + ~predecessor staker rollup = + let open Lwt_result_syntax in + let inbox_level = proper_valid_inbox_level (ctxt, rollup) in + let rec aux ctxt n l predecessor result = + if n = 0 then return @@ (List.rev result, ctxt) + else + let* inbox_level = inbox_level l in + let commitment = + Commitment_repr. + { + predecessor; + inbox_level; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* c, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker commitment + in + aux ctxt (n - 1) (l + 1) c (c :: result) + in + aux ctxt number_of_commitments start_at_level predecessor [] + + let rec cement_commitments ctxt commitments rollup = + let open Lwt_result_syntax in + match commitments with + | [] -> return ctxt + | _c :: commitments -> + let* ctxt, _commitment, _commitment_hash = + Sc_rollup_stake_storage.cement_commitment ctxt rollup + in + cement_commitments ctxt commitments rollup + + let test_cement_fail_too_recent () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let level = valid_inbox_level ctxt in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let commitment = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _c1, level, ctxt = + advance_level_n_refine_stake ctxt rollup staker commitment + in + let min_cementation_level = Raw_level_repr.add level challenge_window in + let* () = + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.cement_commitment ctxt rollup) + (Sc_rollup_errors.Sc_rollup_commitment_too_recent + {current_level = level; min_level = min_cementation_level}) + in + let ctxt = + Raw_context.Internal_for_tests.add_level ctxt (challenge_window - 1) + in + let level = (Raw_context.current_level ctxt).level in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.cement_commitment ctxt rollup) + (Sc_rollup_errors.Sc_rollup_commitment_too_recent + {current_level = level; min_level = min_cementation_level}) + + let test_cement_deadline_uses_oldest_add_time () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitment = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = valid_inbox_level ctxt 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + + let*@ c2, _level, _ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment + in + let*@ _ctxt = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + assert_commitment_hash_equal ~loc:__LOC__ c1 c2 + + let test_last_cemented_commitment_hash_with_level () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker = + originate_rollup_and_deposit_with_one_staker () + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let inbox_level = valid_inbox_level ctxt 1l in + let commitment = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker commitment + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + let*@ ctxt, _, _ = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + let*@ c1', inbox_level', _ctxt = + Sc_rollup_commitment_storage.last_cemented_commitment_hash_with_level + ctxt + rollup + in + let* () = assert_commitment_hash_equal ~loc:__LOC__ c1 c1' in + Assert.equal_int32 + ~loc:__LOC__ + (Raw_level_repr.to_int32 inbox_level) + (Raw_level_repr.to_int32 inbox_level') + + let test_cement_with_two_stakers () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _node, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 commitment2 + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + + let*@ ctxt = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + assert_true ctxt + + let test_can_remove_staker () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _node, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 commitment2 + in + let* ctxt = remove_staker_and_check_balances ctxt rollup staker1 in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + (* It needs to have a staker on [c1] to cement it, otherwise it's not + an active commitment. *) + assert_fails + ~loc:__LOC__ + (Sc_rollup_stake_storage.cement_commitment ctxt rollup) + + let test_can_remove_staker2 () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _node, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 commitment2 + in + let* ctxt = remove_staker_and_check_balances ctxt rollup staker2 in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + let*@ ctxt = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + assert_true ctxt + + let test_removed_staker_can_not_withdraw () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _node, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 commitment2 + in + let*@ ctxt, _ = Sc_rollup_stake_storage.remove_staker ctxt rollup staker2 in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.withdraw_stake ctxt rollup staker2) + Sc_rollup_errors.Sc_rollup_not_staked + + let test_no_cement_on_conflict () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 44L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _node, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment2 + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_stake_storage.cement_commitment ctxt rollup) + Sc_rollup_errors.Sc_rollup_disputed + + let test_finds_conflict_point_at_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 55L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _c2, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment2 + in + let*@ (left, _right), _ctxt = + Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2 + in + assert_commitment_hash_equal ~loc:__LOC__ left.hash c1 + + let test_finds_conflict_point_beneath_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c2, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment2 + in + let commitment3 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 7373L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c3, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment3 + in + let*@ (left, right), _ctxt = + Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2 + in + let* () = assert_commitment_hash_equal ~loc:__LOC__ left.hash c2 in + assert_commitment_hash_equal ~loc:__LOC__ right.hash c3 + + let test_conflict_point_is_first_point_of_disagreement () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c2, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment2 + in + let commitment3 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 7373L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c3, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment3 + in + let commitment4 = + Commitment_repr. + { + predecessor = c2; + inbox_level = level 3l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _c4, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment4 + in + let*@ (left, right), _ctxt = + Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2 + in + let* () = assert_commitment_hash_equal ~loc:__LOC__ left.hash c2 in + assert_commitment_hash_equal ~loc:__LOC__ right.hash c3 + + let test_conflict_point_computation_fits_in_gas_limit () = + let open Lwt_result_wrap_syntax in + (* Worst case of conflict point computation: two branches of maximum + length rooted just after the LCC. *) + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let max_commits = + let commitment_freq = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + Int32.div + (Constants_storage.sc_rollup_max_lookahead_in_blocks ctxt) + (Int32.of_int commitment_freq) + in + let root_commitment = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ root_commitment_hash, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 root_commitment + in + let*@ _node, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + root_commitment + in + let rec branch ctxt staker_id predecessor i max acc = + let open Result_syntax in + let commitment = + Commitment_repr. + { + predecessor; + inbox_level = level i; + number_of_ticks = number_of_ticks_exn staker_id; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* ctxt, commitment_hash = + Sc_rollup_commitment_storage.hash ctxt commitment + in + if i = max then + return (List.rev ((commitment, commitment_hash) :: acc), ctxt) + else + branch + ctxt + staker_id + commitment_hash + (Int32.succ i) + max + ((commitment, commitment_hash) :: acc) + in + let*?@ branch_1, ctxt = + branch ctxt 1L root_commitment_hash 2l max_commits [] + in + let*?@ branch_2, ctxt = + branch ctxt 2L root_commitment_hash 2l max_commits [] + in + let both_branches = List.combine_drop branch_1 branch_2 in + let*@ ctxt = + List.fold_left_es + (fun ctxt ((c1, _c1h), (c2, _c2h)) -> + let* _ch, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 c1 + in + let+ _ch, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 c2 + in + ctxt) + ctxt + both_branches + in + let ctxt = + Raw_context.set_gas_limit + ctxt + (Constants_storage.hard_gas_limit_per_operation ctxt) + in + let*@ (left, right), _ctxt = + Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2 + in + let head_hash branch = + match List.hd branch with Some x -> snd x | None -> assert false + in + let* () = + assert_commitment_hash_equal ~loc:__LOC__ left.hash (head_hash branch_1) + in + assert_commitment_hash_equal ~loc:__LOC__ right.hash (head_hash branch_2) + + let test_no_conflict_point_one_staker_at_lcc_preboot () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitment = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = valid_inbox_level ctxt 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2) + Sc_rollup_errors.Sc_rollup_no_conflict + + let test_no_conflict_point_both_stakers_at_lcc_preboot () = + let open Lwt_result_syntax in + let* ctxt, rollup, _genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2) + Sc_rollup_errors.Sc_rollup_no_conflict + + let test_no_conflict_point_one_staker_at_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = c1; + inbox_level = level 2l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _node, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 commitment2 + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + let*@ ctxt, _, _ = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2) + Sc_rollup_errors.Sc_rollup_no_conflict + + let test_no_conflict_point_both_stakers_at_lcc () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = valid_inbox_level ctxt 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ _c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let*@ _node, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment1 + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + let*@ ctxt, _, _ = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2) + Sc_rollup_errors.Sc_rollup_no_conflict + + let test_last_cemented_commitment_of_missing_rollup () = + assert_fails_with_missing_rollup + ~loc:__LOC__ + Sc_rollup_commitment_storage.last_cemented_commitment + + let test_last_cemented_commitment_hash_with_level_of_missing_rollup () = + assert_fails_with_missing_rollup + ~loc:__LOC__ + Sc_rollup_commitment_storage.last_cemented_commitment_hash_with_level + + let test_get_commitment_of_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> + Sc_rollup_commitment_storage.get_commitment + ctxt + rollup + Commitment_repr.Hash.zero) + + let test_get_missing_commitment () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + let commitment_hash = Commitment_repr.Hash.zero in + assert_fails_with + ~loc:__LOC__ + (Sc_rollup_commitment_storage.get_commitment ctxt rollup commitment_hash) + (Sc_rollup_errors.Sc_rollup_unknown_commitment commitment_hash) + + let test_genesis_info_of_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ Sc_rollup_storage.genesis_info + + let test_concurrent_refinement_point_of_conflict () = + let open Lwt_result_wrap_syntax in + let* before_ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level before_ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let commitment2 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 7373L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ (c1, c2), _ctxt = + let* _c1, _level, ctxt = + advance_level_n_refine_stake before_ctxt rollup staker1 commitment1 + in + let* _c2, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker2 commitment2 + in + Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2 + in + let*@ (c1', c2'), _ctxt = + let* _c2, _level, ctxt = + advance_level_n_refine_stake before_ctxt rollup staker2 commitment2 + in + let* _c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + Sc_rollup_refutation_storage.Internal_for_tests.get_conflict_point + ctxt + rollup + staker1 + staker2 + in + let* () = assert_commitment_hash_equal ~loc:__LOC__ c1.hash c1'.hash in + assert_commitment_hash_equal ~loc:__LOC__ c2.hash c2'.hash + + let test_concurrent_refinement_cement () = + let open Lwt_result_wrap_syntax in + let* before_ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let commitment = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = valid_inbox_level before_ctxt 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _ctxt = + let* _c1, _level, ctxt = + advance_level_n_refine_stake before_ctxt rollup staker1 commitment + in + let* _c2, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = + Raw_context.Internal_for_tests.add_level ctxt challenge_window + in + let* ctxt, _, _ = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + Sc_rollup_commitment_storage.last_cemented_commitment ctxt rollup + in + let*@ c2, _ctxt = + let* _c2, _level, ctxt = + advance_level_n_refine_stake before_ctxt rollup staker2 commitment + in + let* _c1, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker1 + commitment + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let ctxt = + Raw_context.Internal_for_tests.add_level ctxt challenge_window + in + let* ctxt, _, _ = Sc_rollup_stake_storage.cement_commitment ctxt rollup in + Sc_rollup_commitment_storage.last_cemented_commitment ctxt rollup + in + assert_commitment_hash_equal ~loc:__LOC__ c1 c2 + + let record ctxt rollup level message_index = + Sc_rollup_outbox_storage.record_applied_message + ctxt + rollup + (Raw_level_repr.of_int32_exn @@ Int32.of_int level) + ~message_index + + (* Recreating the indexing logic to make sure messages are applied. *) + let assert_is_already_applied ~loc ctxt rollup level message_index = + let open Lwt_result_wrap_syntax in + let level = Raw_level_repr.of_int32_exn (Int32.of_int level) in + let level_index = + let max_active_levels = + Constants_storage.sc_rollup_max_active_outbox_levels ctxt + in + Int32.rem (Raw_level_repr.to_int32 level) max_active_levels + in + let*@ _ctxt, level_and_bitset_opt = + Storage.Sc_rollup.Applied_outbox_messages.find (ctxt, rollup) level_index + in + match level_and_bitset_opt with + | Some (existing_level, bitset) when Raw_level_repr.(existing_level = level) + -> + let*?@ is_set = Bitset.mem bitset message_index in + Assert.equal_bool ~loc is_set true + | _ -> Stdlib.failwith "Expected a bitset and a matching level." + + (** Test outbox for applied messages. *) + let test_storage_outbox () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let*@ rollup1, _genesis_hash, ctxt = new_sc_rollup ctxt in + let level1 = 100 in + (* Test that is-applied is false for non-recorded messages. *) + let*@ _size_diff, ctxt = record ctxt rollup1 level1 1 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup1 level1 1 in + (* Record the same level and message twice should fail. *) + let* () = + assert_fails_with + ~loc:__LOC__ + (record ctxt rollup1 level1 1) + Sc_rollup_errors.Sc_rollup_outbox_message_already_applied + in + let*@ _size_diff, ctxt = record ctxt rollup1 level1 2 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup1 level1 2 in + (* Record messages for new level. *) + let level2 = level1 + 3 in + let*@ _size_diff, ctxt = record ctxt rollup1 level2 47 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup1 level2 47 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup1 level1 1 in + (* Record for a new rollup. *) + let*@ rollup2, _genesis_hash, ctxt = new_sc_rollup ctxt in + let*@ _size_diff, ctxt = record ctxt rollup2 level1 1 in + let*@ _size_diff, ctxt = record ctxt rollup2 level1 3 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup2 level1 1 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup2 level1 3 in + assert_is_already_applied ~loc:__LOC__ ctxt rollup1 level1 1 + + (** Test limits for applied outbox messages. *) + let test_storage_outbox_exceed_limits () = + let open Lwt_result_wrap_syntax in + let level = 1234 in + let* ctxt = new_context () in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + (* Assert that recording a message index that exceeds max outbox messages per + level fails. *) + let* () = + let max_message_index = + Constants_storage.sc_rollup_max_outbox_messages_per_level ctxt + in + assert_fails_with + ~loc:__LOC__ + (record ctxt rollup level max_message_index) + Sc_rollup_errors.Sc_rollup_invalid_outbox_message_index + in + let* () = + assert_fails_with + ~loc:__LOC__ + (record ctxt rollup level (-1)) + Sc_rollup_errors.Sc_rollup_invalid_outbox_message_index + in + let max_active_levels = + Int32.to_int @@ Constants_storage.sc_rollup_max_active_outbox_levels ctxt + in + (* Record message 42 at level 15 *) + let*@ _size_diff, ctxt = record ctxt rollup 15 42 in + let* () = assert_is_already_applied ~loc:__LOC__ ctxt rollup 15 42 in + (* Record message 42 at level [max_active_levels + 15] *) + let*@ _size_diff, ctxt = record ctxt rollup (max_active_levels + 15) 42 in + (* Record message 42 at level 15 again should fail as it's expired. *) + let* () = + assert_fails_with + ~loc:__LOC__ + (record ctxt rollup 15 42) + Sc_rollup_errors.Sc_rollup_outbox_level_expired + in + return_unit + + (** Test storage outbox size diff. Note that these tests depend on the constant. + [sc_rollup_max_outbox_messages_per_level] which controls the maximum size + of bitsets required to store applied messages per level. + + Here's a breakdown of the size for applied-outbox-messages storage: + - [size_of_level = 4] + - [max_size_per_level < (2 * (sc_rollup_max_outbox_messages_per_level / 8))] + - [max_size_per_level < size_of_level + size_of_bitset] + - [total_size < sc_rollup_max_active_outbox_levels * max_size_per_level] + *) + let test_storage_outbox_size_diff () = + let open Lwt_result_wrap_syntax in + (* This is the maximum additional storage space required to store one message. + It depends on [sc_rollup_max_outbox_messages_per_level]. *) + let max_size_diff = 19 in + let* ctxt = new_context () in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + let level = 15 in + let max_message_index = + Constants_storage.sc_rollup_max_outbox_messages_per_level ctxt - 1 + in + let max_active_levels = + Int32.to_int @@ Constants_storage.sc_rollup_max_active_outbox_levels ctxt + in + (* Record a new message. *) + let*@ size_diff, ctxt = record ctxt rollup level 1 in + (* Size diff is 11 bytes. 4 bytes for level and 7 bytes for a new Z.t *) + let* () = Assert.equal_int ~loc:__LOC__ (Z.to_int size_diff) 5 in + let*@ size_diff, ctxt = record ctxt rollup level 2 in + (* Recording a new message in the bitset at a lower index does not occupy + any additional space. *) + let* () = Assert.equal_int ~loc:__LOC__ (Z.to_int size_diff) 0 in + (* Record a new message at the highest index at an existing level. This + expands the bitset but does not charge for the level. *) + let*@ size_diff, ctxt = record ctxt rollup level max_message_index in + let* () = Assert.equal_int ~loc:__LOC__ (Z.to_int size_diff) 14 in + (* Record a new message at the highest index at a new level. This charges for + space for level and maximum bitset. *) + let*@ size_diff, ctxt = record ctxt rollup (level + 1) max_message_index in + let* () = + Assert.equal_int ~loc:__LOC__ (Z.to_int size_diff) max_size_diff + in + (* Record a new message for a level that resets an index. This replaces the + bitset with a smaller one. Hence we get a negative size diff. *) + let*@ size_diff, _ctxt = record ctxt rollup (level + max_active_levels) 0 in + let* () = Assert.equal_int ~loc:__LOC__ (Z.to_int size_diff) (-14) in + return_unit + + let test_get_cemented_commitments_with_levels_of_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> + Sc_rollup_commitment_storage.Internal_for_tests + .get_cemented_commitments_with_levels + ctxt + rollup) + + let test_get_cemented_commitments_with_levels () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, c0, staker = + originate_rollup_and_deposit_with_one_staker () + in + let level = valid_inbox_level ctxt in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + (* Produce and stake on n commitments, each on top of the other. *) + (* Fetch number of stored commitments in context. *) + let max_num_stored_cemented_commitments = + (Raw_context.constants ctxt).sc_rollup + .max_number_of_stored_cemented_commitments + in + (* Produce and stake more commitments than the number of cemented + commitments that can be stored. *) + let number_of_commitments = max_num_stored_cemented_commitments + 5 in + let*@ commitments, ctxt = + produce_and_refine + ~number_of_commitments + ~predecessor:c0 + ctxt + staker + rollup + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + (* Cement all commitments that have been produced. *) + let*@ ctxt = cement_commitments ctxt commitments rollup in + (* Add genesis commitment to list of produced commitments. *) + let commitments = c0 :: commitments in + let number_of_cemented_commitments = List.length commitments in + (* Fetch cemented commitments that are kept in context. *) + let*@ cemented_commitments_with_levels, _ctxt = + Sc_rollup_commitment_storage.Internal_for_tests + .get_cemented_commitments_with_levels + ctxt + rollup + in + (* Check that only ctxt.sc_rollup.max_number_of_stored_cemented_commitments + are kept in context. *) + let* () = + Assert.equal_int + ~loc:__LOC__ + (List.length cemented_commitments_with_levels) + max_num_stored_cemented_commitments + in + (* Check that the commitments that are kept in context are the + last [ctxt.sc_rollup.max_number_of_stored_cemented_commitments]. + commitments that have been cemented. *) + let dropped_commitments = + number_of_cemented_commitments - max_num_stored_cemented_commitments + in + let expected_commitments_with_levels = + commitments + |> List.drop_n dropped_commitments + |> List.mapi (fun i c -> + (c, level @@ Int32.of_int (i + dropped_commitments))) + in + assert_commitments_with_levels_equal + ~loc:__LOC__ + cemented_commitments_with_levels + expected_commitments_with_levels + + (* Produces [max_num_stored_cemented_commitments] number of commitments and + verifies that each of them is an ancestor of the last cemented commitment. *) + let test_are_commitments_related_when_related () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, c0, staker = + originate_rollup_and_deposit_with_one_staker () + in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + (* Produce and stake on n commitments, each on top of the other. *) + (* Fetch number of stored commitments in context. *) + let max_num_stored_cemented_commitments = + (Raw_context.constants ctxt).sc_rollup + .max_number_of_stored_cemented_commitments + in + (* Produce and store a number of commitments equal to the maximum number of + cemented commitments that can be stored. *) + let number_of_commitments = max_num_stored_cemented_commitments in + let*@ commitments, ctxt = + produce_and_refine + ~number_of_commitments + ~predecessor:c0 + ctxt + staker + rollup + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + (* Cement all commitments that have been produced. *) + let*@ ctxt = cement_commitments ctxt commitments rollup in + (* Check that check_if_commitments_are_related detects that each + cemented commitment is an ancestor of the last cemented commitment. *) + let*@ lcc, ctxt = + Sc_rollup_commitment_storage.last_cemented_commitment ctxt rollup + in + commitments + |> List.iter_es (fun commitment -> + let*@ is_commitment_cemented, _ctxt = + Sc_rollup_commitment_storage.check_if_commitments_are_related + ctxt + rollup + ~descendant:lcc + ~ancestor:commitment + in + Assert.equal_bool ~loc:__LOC__ is_commitment_cemented true) + + (** Tests that [check_if_commitments_are_related] returns false for two + unrelated commitments. *) + let test_unrelated_commitments () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let level = valid_inbox_level ctxt in + let commitment1 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 1232909L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c1, _level, ctxt = + advance_level_n_refine_stake ctxt rollup staker1 commitment1 + in + let commitment2 = + Commitment_repr. + { + predecessor = genesis_hash; + inbox_level = level 1l; + number_of_ticks = number_of_ticks_exn 44L; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let*@ c2, _level, ctxt = + Sc_rollup_stake_storage.Internal_for_tests.refine_stake + ctxt + rollup + staker2 + commitment2 + in + let*@ are_commitments_related, _ctxt = + Sc_rollup_commitment_storage.check_if_commitments_are_related + ctxt + rollup + ~descendant:c1 + ~ancestor:c2 + in + Assert.equal_bool ~loc:__LOC__ are_commitments_related false + + let test_fresh_index_correctly_increment () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, _genesis_hash, staker1, staker2 = + originate_rollup_and_deposit_with_two_stakers () + in + let assert_staker_index ~__LOC__ ctxt staker expected_index = + let*@ _, (found_index : Sc_rollup_staker_index_repr.t) = + Storage.Sc_rollup.Staker_index.get (ctxt, rollup) staker + in + Assert.equal_z ~loc:__LOC__ (found_index :> Z.t) expected_index + in + let* () = assert_staker_index ~__LOC__ ctxt staker1 Z.zero in + let* () = assert_staker_index ~__LOC__ ctxt staker2 Z.one in + let Account.{pkh; _} = Account.new_account () in + let*@ ctxt, fresh_staker3_index = + Sc_rollup_staker_index_storage.fresh_staker_index ctxt rollup pkh + in + let* () = assert_staker_index ~__LOC__ ctxt pkh Z.(succ one) in + Assert.equal_z ~loc:__LOC__ (fresh_staker3_index :> Z.t) Z.(succ one) + + let tests = + [ + (* Deposit tests: *) + Tztest.tztest "deposit" `Quick test_deposit; + Tztest.tztest + "deposit by underfunded staker" + `Quick + test_deposit_by_underfunded_staker; + Tztest.tztest "deposit then withdraw" `Quick test_deposit_then_withdraw; + Tztest.tztest "deposit on two rollups" `Quick test_deposit_on_two_rollups; + Tztest.tztest "deposit twice fails" `Quick test_deposit_twice_fails; + (* Publish tests: *) + Tztest.tztest "publish" `Quick test_publish; + Tztest.tztest "publish twice" `Quick test_publish_twice; + Tztest.tztest + "publish to missing rollup fails" + `Quick + test_publish_to_missing_rollup; + Tztest.tztest + "publish to wrong inbox level" + `Quick + test_publish_wrong_inbox_level; + Tztest.tztest + "publish existing commitment" + `Quick + test_publish_existing_commitment; + Tztest.tztest + "publish commitment returns level when commitment was first published" + `Quick + test_publish_returns_oldest_publish_level; + Tztest.tztest + "publish from the future is not allowed" + `Quick + test_publish_fails_on_commitment_from_future; + Tztest.tztest + "publish from behind lcc is allowed" + `Quick + test_publish_from_behind_lcc; + Tztest.tztest + "publish to any commitment of a branch" + `Quick + test_publish_anywhere_on_branch; + Tztest.tztest + "publish needs a predecessor" + `Quick + test_publish_without_predecessor_fails; + Tztest.tztest + "publish behind or at LCC" + `Quick + test_publish_behind_or_at_lcc_fails; + (* Cement tests: *) + Tztest.tztest "cement" `Quick test_cement; + Tztest.tztest + "cement to missing rollup fails" + `Quick + test_cement_to_missing_rollup; + Tztest.tztest "cement with n stakers" `Quick test_cement_with_n_stakers; + Tztest.tztest "cement n commitments" `Quick test_cement_n_commitments; + Tztest.tztest + "cement clean commitment(s)" + `Quick + test_cement_clean_commitments; + Tztest.tztest + "cement conflicted branches" + `Quick + test_cement_conflicted_branches; + (* Withdraw tests: *) + Tztest.tztest + "withdraw to missing rollup fails" + `Quick + test_withdraw_to_missing_rollup; + Tztest.tztest + "withdraw when not staked fails" + `Quick + test_withdraw_when_not_staked; + Tztest.tztest "withdraw twice fails" `Quick test_withdraw_twice_fails; + Tztest.tztest + "withdraw fails when staked after LCC" + `Quick + test_withdraw_fails_staked_after_lcc; + Tztest.tztest + "withdraw when staked before or at LCC" + `Quick + test_withdraw_staked_before_or_at_lcc; + (* Remove staker tests: *) + Tztest.tztest "remove staker" `Quick test_remove_staker; + (* Misc tests: *) + Tztest.tztest + "staker come back after being slashed" + `Quick + test_come_back_after_remove_staker; + ] + + (* These tests were written for the old mechanism of staking (calling it + the old design would be a too strong statement). + They need to polished if necessary. + *) + let tests = + tests + @ [ + Tztest.tztest + "cement fails when too recent" + `Quick + test_cement_fail_too_recent; + Tztest.tztest + "cement deadline uses oldest add time" + `Quick + test_cement_deadline_uses_oldest_add_time; + Tztest.tztest + "last cemented commitment hash and level returns correct information" + `Quick + test_last_cemented_commitment_hash_with_level; + Tztest.tztest + "cement with two stakers" + `Quick + test_cement_with_two_stakers; + Tztest.tztest "no cement on conflict" `Quick test_no_cement_on_conflict; + Tztest.tztest + "finds conflict point at LCC" + `Quick + test_finds_conflict_point_at_lcc; + Tztest.tztest + "finds conflict point beneath LCC" + `Quick + test_finds_conflict_point_beneath_lcc; + Tztest.tztest + "finds first point of disagreement when as point of conflict" + `Quick + test_conflict_point_is_first_point_of_disagreement; + Tztest.tztest + "finds no conflict point with two stakers, one of which is at LCC \ + (PVM in preboot)" + `Quick + test_no_conflict_point_one_staker_at_lcc_preboot; + Tztest.tztest + "finds no conflict point when both stakers commit to LCC (PVM in \ + preboot)" + `Quick + test_no_conflict_point_both_stakers_at_lcc_preboot; + Tztest.tztest + "finds no conflict point with two stakers, one of which is at LCC" + `Quick + test_no_conflict_point_one_staker_at_lcc; + Tztest.tztest + "finds no conflict point when both stakers commit to LCC" + `Quick + test_no_conflict_point_both_stakers_at_lcc; + Tztest.tztest + "conflict_point_computation_fits_in_gas_limit" + `Quick + test_conflict_point_computation_fits_in_gas_limit; + Tztest.tztest "can remove staker 1" `Quick test_can_remove_staker; + Tztest.tztest "can remove staker 2" `Quick test_can_remove_staker2; + Tztest.tztest + "removed staker can not withdraw" + `Quick + test_removed_staker_can_not_withdraw; + Tztest.tztest + "fetching last final commitment of missing rollup fails" + `Quick + test_last_cemented_commitment_of_missing_rollup; + Tztest.tztest + "fetching last final commitment hash and level of missing rollup \ + fails" + `Quick + test_last_cemented_commitment_hash_with_level_of_missing_rollup; + Tztest.tztest + "fetching commitment of missing rollup fails" + `Quick + test_get_commitment_of_missing_rollup; + Tztest.tztest + "fetching non-existing commitment of rollup fails" + `Quick + test_get_missing_commitment; + Tztest.tztest + "initial level of missing rollup fails" + `Quick + test_genesis_info_of_missing_rollup; + Tztest.tztest + "Refinement operations are commutative (point of conflict)" + `Quick + test_concurrent_refinement_point_of_conflict; + Tztest.tztest + "Refinement operations are commutative (cement)" + `Quick + test_concurrent_refinement_cement; + Tztest.tztest + "Record messages in storage outbox" + `Quick + test_storage_outbox; + Tztest.tztest + "Record messages in storage outbox limits" + `Quick + test_storage_outbox_exceed_limits; + Tztest.tztest + "Record messages size diffs" + `Quick + test_storage_outbox_size_diff; + Tztest.tztest + "Originating a rollup creates a genesis commitment" + `Quick + test_last_cemented_commitment_hash_with_level_when_genesis; + Tztest.tztest + "Getting cemented commitments with levels of missing rollups fails" + `Quick + test_get_cemented_commitments_with_levels_of_missing_rollup; + Tztest.tztest + "Getting cemented commitments returns multiple cemented commitments" + `Quick + test_get_cemented_commitments_with_levels; + Tztest.tztest + "All cemented commitments are ancestors of last cemented commitment" + `Quick + test_are_commitments_related_when_related; + Tztest.tztest + "Unrelated commitments are classified as such" + `Quick + test_unrelated_commitments; + Tztest.tztest + "fresh index is correcly incremented" + `Quick + test_fresh_index_correctly_increment; + ] +end + +module Rollup_storage_tests = struct + let test_genesis_info_of_rollup () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let level_before_rollup = (Raw_context.current_level ctxt).level in + let*@ rollup, _genesis_hash, ctxt = new_sc_rollup ctxt in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt 10 in + let*@ _ctxt, genesis_info = Sc_rollup_storage.genesis_info ctxt rollup in + let initial_level = genesis_info.level in + Assert.equal_int32 + ~loc:__LOC__ + (Raw_level_repr.to_int32 level_before_rollup) + (Raw_level_repr.to_int32 initial_level) + + let test_initial_state_is_pre_boot () = + let open Lwt_result_wrap_syntax in + let* ctxt, rollup, genesis_hash = new_context_with_rollup () in + let*@ lcc, _ctxt = + Sc_rollup_commitment_storage.last_cemented_commitment ctxt rollup + in + assert_commitment_hash_equal ~loc:__LOC__ lcc genesis_hash + + let test_kind_of_missing_rollup () = + assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> + Sc_rollup_storage.kind ctxt rollup) + + let tests = + [ + Tztest.tztest + "initial_level returns correct level" + `Quick + test_genesis_info_of_rollup; + Tztest.tztest + "rollup starts in pre-boot state" + `Quick + test_initial_state_is_pre_boot; + Tztest.tztest + "kind of missing rollup is None" + `Quick + test_kind_of_missing_rollup; + ] +end + +let tests = Stake_storage_tests.tests @ Rollup_storage_tests.tests + +(* FIXME: https://gitlab.com/tezos/tezos/-/issues/2460 + Further tests to be added. +*) + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup storage", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml new file mode 100644 index 000000000000..be1d6dd2bbb5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml @@ -0,0 +1,435 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Rollup layer 1 logic + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_sc_rollup_wasm.ml + Subject: Unit test for the Wasm PVM +*) + +open Protocol +open Tezos_micheline.Micheline +open Michelson_v1_primitives +open Tezos_webassembly_interpreter +module Context = Tezos_context_memory.Context_binary +open Wasm_utils + +module Proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding + +module Wasm_context = struct + module Tree = struct + include Context.Tree + + type tree = Context.tree + + type t = Context.t + + type key = string list + + type value = bytes + end + + type tree = Context.tree + + type proof = Context.Proof.tree Context.Proof.t + + let verify_proof p f = + Lwt.map Result.to_option (Context.verify_tree_proof p f) + + let produce_proof context tree step = + let open Lwt_syntax in + let* context = Context.add_tree context [] tree in + let* (_hash : Context_hash.t) = + Context.commit ~time:Time.Protocol.epoch context + in + let index = Context.index context in + match Context.Tree.kinded_key tree with + | Some k -> + let* p = Context.produce_tree_proof index k step in + return_some p + | None -> return_none + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> + Sc_rollup_repr.State_hash.context_hash_to_state_hash hash + + let proof_before proof = kinded_hash_to_state_hash proof.Context.Proof.before + + let proof_after proof = kinded_hash_to_state_hash proof.Context.Proof.after + + let proof_encoding = Proof_encoding.V2.Tree2.tree_proof_encoding +end + +module Full_Wasm = + Sc_rollup_wasm.V2_0_0.Make (Environment.Wasm_2_0_0.Make) (Wasm_context) + +let test_metadata_size () = + let address = Sc_rollup_repr.Address.of_bytes_exn (Bytes.make 20 '\000') in + let metadata = + Sc_rollup_metadata_repr.{address; origination_level = Raw_level_repr.root} + in + let bytes = + Data_encoding.Binary.to_bytes_exn Sc_rollup_metadata_repr.encoding metadata + in + assert ( + Bytes.length bytes + = Tezos_scoru_wasm.Host_funcs.Internal_for_tests.metadata_size) ; + Lwt_result_syntax.return_unit + +let test_l1_input_kind () = + let open Lwt_result_wrap_syntax in + let open Sc_rollup_inbox_message_repr in + let open Tezos_scoru_wasm in + let check_msg msg expected = + let*?@ msg = serialize msg in + let msg = unsafe_to_string msg |> Pvm_input_kind.from_raw_input in + assert (msg = expected) ; + return_unit + in + let* () = check_msg (Internal Start_of_level) (Internal Start_of_level) in + let* () = check_msg (Internal End_of_level) (Internal End_of_level) in + let* () = check_msg (External "payload") External in + + return_unit + +let make_transaction value text contract = + let entrypoint = Entrypoint_repr.default in + let destination : Contract_hash.t = + Contract_hash.of_bytes_exn @@ Bytes.of_string contract + in + let unparsed_parameters = + strip_locations + @@ Prim + ( 0, + I_TICKET, + [Prim (0, I_PAIR, [Int (0, Z.of_int32 value); String (1, text)], [])], + [] ) + in + Sc_rollup_outbox_message_repr.{unparsed_parameters; entrypoint; destination} + +let make_transactions () = + let l = + QCheck2.Gen.( + generate1 + @@ list_size + (return 3) + (triple (string_size @@ return 20) int32 (small_string ~gen:char))) + in + List.map (fun (contract, i, s) -> make_transaction i s contract) l + +(* This is simple "echo kernel" it spits out the first four inputs (SOL, + Info_per_level, input, EOL) it receives. It uses the [write_output] host + function and so it is used to test this function. *) +let test_output () = + let open Lwt_result_wrap_syntax in + let level_offset = 20 in + let dst = 60 in + let max_bytes = 3600 in + let dst_without_header = dst + 2 in + let modul = + Format.sprintf + {| + (module + (type $t0 (func (param i32 i32) (result i32))) + (type $t3 (func (param i32 i32 i32) (result i32))) + (import "smart_rollup_core" "read_input" (func $read_input (type $t3))) + (import "smart_rollup_core" "write_output" (func $write_output (type $t0))) + (memory 1) + (export "memory" (memory 0)) + (func (export "kernel_run") + (local $size i32) + (local.set $size (call $read_input + (i32.const %d) + (i32.const %d) + (i32.const %d))) + (call $write_output (i32.const %d) + (i32.sub (local.get $size) (i32.const 2))) + (local.set $size (call $read_input + (i32.const %d) + (i32.const %d) + (i32.const %d))) + (call $write_output (i32.const %d) + (i32.sub (local.get $size) (i32.const 2))) + (local.set $size (call $read_input + (i32.const %d) + (i32.const %d) + (i32.const %d))) + (call $write_output (i32.const %d) + (i32.sub (local.get $size) (i32.const 2))) + (local.set $size (call $read_input + (i32.const %d) + (i32.const %d) + (i32.const %d))) + (call $write_output (i32.const %d) + (local.get $size)) + drop) + ) + + |} + level_offset + dst + max_bytes + dst_without_header + level_offset + dst + max_bytes + dst_without_header + level_offset + dst + max_bytes + dst_without_header + level_offset + dst + max_bytes + dst_without_header + in + + let*! dummy = Context.init "/tmp" in + let dummy_context = Context.empty dummy in + let (empty_tree : Wasm.tree) = Context.Tree.empty dummy_context in + let parsed = Parse.string_to_module modul in + let parsed = + match parsed.it with Script.Textual m -> m | _ -> assert false + in + let*! boot_sector = Encode.encode parsed in + let*! tree = + Wasm.initial_state Sc_rollup_wasm.V2_0_0.current_version empty_tree + in + let*! tree = + Wasm.install_boot_sector + ~ticks_per_snapshot:Sc_rollup_wasm.V2_0_0.ticks_per_snapshot + ~outbox_validity_period:Sc_rollup_wasm.V2_0_0.outbox_validity_period + ~outbox_message_limit:Sc_rollup_wasm.V2_0_0.outbox_message_limit + boot_sector + tree + in + let*! tree = + Wasm.Internal_for_tests.set_max_nb_ticks (Z.of_int64 50_000_000L) tree + in + let transactions = make_transactions () in + let out = + Sc_rollup_outbox_message_repr.(Atomic_transaction_batch {transactions}) + in + let string_input_message = + Data_encoding.Binary.to_string_exn + Sc_rollup_outbox_message_repr.encoding + out + in + let*! tree = eval_until_input_requested tree in + let*! tree = set_full_input_step [string_input_message] 0l tree in + let*! final_tree = eval_until_input_requested tree in + let*! output = Wasm.Internal_for_tests.get_output_buffer final_tree in + let* last_outbox_level = + match output.Tezos_webassembly_interpreter.Output_buffer.last_level with + | Some level -> return level + | None -> failwith "The PVM output buffer does not contain any outbox." + in + let*! last_outbox = + Tezos_webassembly_interpreter.Output_buffer.Internal_for_tests.get_outbox + output + last_outbox_level + in + let* end_of_level_message_index = + match + Output_buffer.Internal_for_tests.get_outbox_last_message_index last_outbox + with + | Some index -> return index + | None -> failwith "The PVM output buffer does not contain any outbox." + in + (* The last message in the outbox corresponds to EOL, due to the nature of the + kernel. As such we must take the one preceding it. *) + let message_index = Z.pred end_of_level_message_index in + + let*! bytes_output_message = + Tezos_webassembly_interpreter.Output_buffer.( + get_message output {outbox_level = last_outbox_level; message_index}) + in + assert (string_input_message = Bytes.to_string bytes_output_message) ; + let message = + Data_encoding.Binary.of_bytes_exn + Sc_rollup_outbox_message_repr.encoding + bytes_output_message + in + assert (message = out) ; + let*?@ outbox_level = Raw_level_repr.of_int32 last_outbox_level in + let output = Sc_rollup_PVM_sig.{outbox_level; message_index; message} in + + let*! pf = Full_Wasm.produce_output_proof dummy_context final_tree output in + + match pf with + | Ok proof -> + let*! valid = Full_Wasm.verify_output_proof proof in + fail_unless + (Result.is_ok valid) + (Exn (Failure "An output proof is not valid.")) + | Error _ -> failwith "Error during proof generation" + +let test_reveal_compat_metadata () = + let open Alpha_context.Sc_rollup in + let open Tezos_scoru_wasm.Wasm_pvm_state in + let (Reveal_raw metadata_scoru_wasm) = reveal_metadata in + let metadata_protocol = + Data_encoding.Binary.to_string_exn reveal_encoding Reveal_metadata + in + Assert.equal_string ~loc:__LOC__ metadata_scoru_wasm metadata_protocol + +let test_reveal_compat_raw_data () = + let open Alpha_context.Sc_rollup in + let open Tezos_scoru_wasm.Wasm_pvm_state in + let hash = Wasm_2_0_0PVM.well_known_reveal_hash in + let hash_string = + Data_encoding.Binary.to_string_exn Sc_rollup_reveal_hash.encoding hash + in + let (Reveal_raw raw_data_scoru_wasm) = reveal_raw_data hash_string in + let raw_data_protocol = + Data_encoding.Binary.to_string_exn reveal_encoding (Reveal_raw_data hash) + in + Assert.equal_string ~loc:__LOC__ raw_data_scoru_wasm raw_data_protocol + +(* When snapshoting a new protocol, to fix this test, the following + action should be done. + + - In [src/lib_scoru_wasm/constants.ml], add a new variable before + [proto_alpha_name] using the name of the new protocol, and whose + value is [Raw_context.version_value]. + - Update [src/lib_scoru_wasm/pvm_input_kind.ml] to add a new case + to the type [protocol], and update the functions + [protocol_from_raw] and [Internal_for_tests.proto_to_binary] + accordingly (by copy/pasting the [Proto_alpha] case and doing + the necessary renaming. + - Update [src/lib_scoru_wasm/wasm_vm.ml], more precisely the + [version_for_protocol] function, to take into account the new + protocol. The expected result is the same as for + [Proto_alpha]. *) +let test_protocol_names () = + let open Alpha_context.Sc_rollup.Inbox_message in + let protocol_migration_message_str = + Data_encoding.Binary.to_string_exn + encoding + (Internal protocol_migration_internal_message) + in + let kind = + Tezos_scoru_wasm.Pvm_input_kind.from_raw_input + protocol_migration_message_str + in + assert (kind = Internal (Protocol_migration Paris)) ; + assert ( + protocol_migration_internal_message + = Protocol_migration Tezos_scoru_wasm.Constants.paris_name) ; + Lwt_result_syntax.return_unit + +let test_reveal_host_function_can_request_dal_pages () = + let open Alpha_context in + let wasm_hex str = + String.concat + "" + (String.fold_right + (fun c hex -> + let x, y = Hex.of_char c in + Format.sprintf "\\%c%c" x y :: hex) + str + []) + in + let request_dal_module level slot_index page_index payload_addr + destination_addr max_bytes = + let payload_value = + Sc_rollup.Request_dal_page + { + slot_id = + {published_level = Raw_level.of_int32_exn level; index = slot_index}; + page_index; + } + in + let payload = + Data_encoding.Binary.to_string_exn Sc_rollup.reveal_encoding payload_value + in + let kernel = + Format.sprintf + {| + (module + (import "smart_rollup_core" "reveal" + (func $reveal (param i32 i32 i32 i32) (result i32))) + (memory 1) + (data (i32.const %ld) "%s") + (export "mem" (memory 0)) + (func (export "kernel_run") + (call $reveal (i32.const %ld) (i32.const %ld) (i32.const %ld) (i32.const %ld)))) + |} + payload_addr + (wasm_hex payload) + payload_addr + (String.length payload |> Int32.of_int) + destination_addr + max_bytes + in + (payload_value, kernel) + in + let payload_value, kernel = + request_dal_module 10l Dal.Slot_index.zero 4 100l 200l 4_096l + in + let* tree = Wasm_utils.initial_tree ~version:V3 kernel in + let* tree = Wasm_utils.set_empty_inbox_step 0l tree in + let* tree = + Wasm_utils.eval_until_input_requested ~reveal_builtins:None tree + in + let* info = Wasm_utils.Wasm.get_info tree in + match info.input_request with + | Reveal_required (Reveal_raw payload) -> ( + match + Data_encoding.Binary.of_string Sc_rollup.reveal_encoding payload + with + | Ok payload -> + assert (payload_value = payload) ; + Lwt_result_syntax.return_unit + | Error _ -> assert false) + | _ -> assert false + +let tests = + [ + Tztest.tztest "size of a rollup metadata" `Quick test_metadata_size; + Tztest.tztest "l1 input kind" `Quick test_l1_input_kind; + Tztest.tztest "output proofs" `Quick test_output; + Tztest.tztest + "lib_scoru_wasm reveal encoding compatibility: Reveal_metadata" + `Quick + test_reveal_compat_metadata; + Tztest.tztest + "lib_scoru_wasm reveal encoding compatibility: Reveal_raw_data" + `Quick + test_reveal_compat_raw_data; + Tztest.tztest "protocol names consistency" `Quick test_protocol_names; + Tztest.tztest + "reveal host function can request DAL pages" + `Quick + test_reveal_host_function_can_request_dal_pages; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("sc rollup wasm", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_skip_list_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_skip_list_repr.ml new file mode 100644 index 000000000000..2cac9c29cc55 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_skip_list_repr.ml @@ -0,0 +1,188 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (skip lists) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_skip_list_repr.ml + Subject: Test skip list implementation +*) + +open Protocol + +exception Skip_list_test_error of string + +let err x = Exn (Skip_list_test_error x) + +(* + + In this test, we check that [best_basis] should be used to optimize + the size of Merkel proofs based on skip lists. In such a context, + the skip lists are referenced by Blake2B hashes (32 bytes-long) and + their contents are also Blake2B hashes. Besides, a Merkel proof is + a list of cells. + + To that end, we consider a deterministic sample of pairs [(n, + target)] when [n] is the length of the skip list and [target] is + the index of a cell in the skip list. Then, for each basis in [2 + .. max_basis] distinct from [best_basis], we check that the largest + proof is larger than the largest proof of [best_basis]. + +*) +let test_skip_list_proof_size () = + let module H = Sc_rollup_inbox_merkelized_payload_hashes_repr.Hash in + (* + + Basis [4] is very close to [3] as the best basis... therefore, we + use a fixed seed for the random number generator to avoid any + flakiness in the test. + + *) + let () = Random.init 0xC0FFEE in + let best_basis = 4 in + + (* + + For the CI, we use relatively small values to avoid slowdowns. + + We choose [max_length] to be of the same order of magnitude as + the longest lists we can meet in practice in the smart rollups + inboxes. + + The real [max_length] can be found in [constants_repr.ml]. At the time + of writing this message, the value is [1_000_000]. + + *) + let max_basis = 7 and nsample = 2048 and max_length = 100_000 in + + (* + + Locally, one can we use large values to get higher confidence: + + *) + (* let max_basis = 13 and nsample = 4096 and max_length = 200_000 in *) + + (* A sample is a pair [(n, k)] where [k <= n]. *) + let samples = + let get () = + let n = 1 + Random.int (max_length - 1) in + let target = Random.int (1 + n) in + (n, Z.of_int target) + in + let rec aux r n = if n = 0 then r else aux (get () :: r) (n - 1) in + aux [] nsample + in + + (* + + For a given [basis], we compute the largest proof when processing + [samples]. The considered lists hold the same contents in each cell, + allowing us to store lists of size [k] in a cache. + + *) + let largest_proof basis = + let module M = Skip_list.Make (struct + let basis = basis + end) in + let cell_encoding = M.encoding H.encoding H.encoding in + let proof_encoding = Data_encoding.list cell_encoding in + let hash_cell cell = + let payload_hash = M.content cell in + let back_pointers_hashes = M.back_pointers cell in + H.to_bytes payload_hash :: List.map H.to_bytes back_pointers_hashes + |> H.hash_bytes + in + let dummy_content = H.hash_string ["HumptyDumpty"] in + let cache = + let cache = Stdlib.Hashtbl.create 13 in + let rec make_list k n map prev_cell = + if n = k then + let prev_cell_ptr = hash_cell prev_cell in + let map = H.Map.add prev_cell_ptr prev_cell map in + Stdlib.Hashtbl.add cache k (map, prev_cell_ptr) + else + let prev_cell_ptr = hash_cell prev_cell in + let next_cell = M.next ~prev_cell ~prev_cell_ptr dummy_content in + let map = H.Map.add prev_cell_ptr prev_cell map in + Stdlib.Hashtbl.add cache k (map, prev_cell_ptr) ; + make_list (succ k) n map next_cell + in + make_list 0 max_length H.Map.empty (M.genesis dummy_content) ; + cache + in + let proof_of_path deref = + List.map (fun ptr -> Stdlib.Option.get (deref ptr)) + in + let proof_size (n, target_index) = + let make_list n = Stdlib.Hashtbl.find cache n in + let map, cell_ptr = make_list n in + let deref ptr = H.Map.find ptr map in + let path = + Stdlib.Option.get @@ M.back_path ~deref ~cell_ptr ~target_index + in + let proof = proof_of_path deref path in + let encoded_proof = + Data_encoding.Binary.to_bytes_exn proof_encoding proof + in + Bytes.length encoded_proof + in + List.map proof_size samples |> List.fold_left max min_int + in + let largest_proofs = + List.map (fun basis -> (basis, largest_proof basis)) (2 -- max_basis) + in + let () = + List.iter + (fun (b, p) -> + Format.eprintf "@[Basis = %d,@, Largest proof = %d@]@;" b p) + largest_proofs + in + let smallest_largest_proofs_basis, _ = + List.fold_left + (fun (b1, p1) (b2, p2) -> if p1 < p2 then (b1, p1) else (b2, p2)) + (Stdlib.List.hd largest_proofs) + (Stdlib.List.tl largest_proofs) + in + fail_unless + (smallest_largest_proofs_basis = best_basis) + (err + (Format.asprintf + "According to the test, %d is the best basis, not %d." + smallest_largest_proofs_basis + best_basis)) + +let tests = + [ + Tztest.tztest + "Skip list: check if the best basis for merkelized skip list is indeed \ + the best" + `Quick + test_skip_list_proof_size; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("skip list", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_tez_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_tez_repr.ml new file mode 100644 index 000000000000..73d2494f2504 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_tez_repr.ml @@ -0,0 +1,208 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Tez_repr + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_tez_repr.ml + Dependencies: -- + Subject: To test the modules (including the top-level) + in tez_repr.ml as individual units, particularly + failure cases. Superficial goal: increase coverage percentage. +*) +open Protocol + +open Tztest + +module Test_tez_repr = struct + (** Testing predefined units: zero, one_mutez etc *) + let test_predefined_values () = + let open Lwt_result_syntax in + let zero_int64 = Tez_repr.to_mutez Tez_repr.zero in + let* () = Assert.equal_int64 ~loc:__LOC__ zero_int64 0L in + let one_mutez_int64 = Tez_repr.to_mutez Tez_repr.one_mutez in + let* () = Assert.equal_int64 ~loc:__LOC__ one_mutez_int64 1L in + let one_cent_int64 = Tez_repr.to_mutez Tez_repr.one_cent in + let* () = Assert.equal_int64 ~loc:__LOC__ one_cent_int64 10000L in + let fifty_cents_int64 = Tez_repr.to_mutez Tez_repr.fifty_cents in + let* () = Assert.equal_int64 ~loc:__LOC__ fifty_cents_int64 500000L in + let one_int64 = Tez_repr.to_mutez Tez_repr.one in + Assert.equal_int64 ~loc:__LOC__ one_int64 1000000L + + let test_subtract () = + let open Lwt_result_wrap_syntax in + let*?@ res = Tez_repr.(one -? zero) in + Assert.equal_int64 ~loc:__LOC__ (Tez_repr.to_mutez res) 1000000L + + let test_substract_underflow () = + let open Lwt_result_syntax in + match Tez_repr.(zero -? one) with + | Ok _ -> failwith "Expected to underflow" + | Error _ -> return_unit + + let test_addition () = + let open Lwt_result_wrap_syntax in + let*?@ res = Tez_repr.(one +? zero) in + Assert.equal_int64 ~loc:__LOC__ (Tez_repr.to_mutez res) 1000000L + + let test_addition_overflow () = + let open Lwt_result_syntax in + match Tez_repr.(of_mutez_exn 0x7fffffffffffffffL +? one) with + | Ok _ -> failwith "Expected to overflow" + | Error _ -> return_unit + + let test_mul () = + let open Lwt_result_wrap_syntax in + let*?@ res = Tez_repr.(zero *? 1L) in + Assert.equal_int64 ~loc:__LOC__ (Tez_repr.to_mutez res) 0L + + let test_mul_overflow () = + let open Lwt_result_syntax in + match Tez_repr.(of_mutez_exn 0x7fffffffffffffffL *? 2L) with + | Ok _ -> failwith "Expected to overflow" + | Error _ -> return_unit + + let test_div () = + let open Lwt_result_wrap_syntax in + let*?@ res = Tez_repr.(one *? 1L) in + Assert.equal_int64 ~loc:__LOC__ (Tez_repr.to_mutez res) 1000000L + + let test_div_by_zero () = + let open Lwt_result_syntax in + match Tez_repr.(one /? 0L) with + | Ok _ -> failwith "Expected to overflow" + | Error _ -> return_unit + + let test_to_mutez () = + let int64v = Tez_repr.(to_mutez one) in + Assert.equal_int64 ~loc:__LOC__ int64v 1000000L + + let test_of_mutez_non_negative () = + match Tez_repr.of_mutez 1000000L with + | Some tz -> + Assert.equal_int64 + ~loc:__LOC__ + (Tez_repr.to_mutez tz) + Tez_repr.(to_mutez one) + | None -> failwith "should have successfully converted 1000000L to tez" + + let test_of_mutez_negative () = + let open Lwt_result_syntax in + match Tez_repr.of_mutez (-1000000L) with + | Some _ -> failwith "should have failed to converted -1000000L to tez" + | None -> return_unit + + let test_of_mutez_exn () = + try + let tz = Tez_repr.of_mutez_exn 1000000L in + Assert.equal_int64 + ~loc:__LOC__ + (Tez_repr.to_mutez tz) + Tez_repr.(to_mutez one) + with e -> + let msg = Printexc.to_string e and stack = Printexc.get_backtrace () in + failwith "Unexpected exception: %s %s" msg stack + + let test_of_mutez_exn_negative () = + let open Lwt_result_syntax in + try + let (_ : Tez_repr.t) = Tez_repr.of_mutez_exn (-1000000L) in + failwith "should have failed to converted -1000000L to tez" + with + | Invalid_argument _ -> return_unit + | e -> + let msg = Printexc.to_string e and stack = Printexc.get_backtrace () in + failwith "Unexpected exception: %s %s" msg stack + + (* NOTE: Avoid assertions against too many functions from Tez_repr. Convert them to + int64 and compare instead of using [Tez_repr]'s compare *) + + (** Testing [encoding], int64 underneath, by applying it with Data_encoding *) + let test_data_encoding () = + let open Lwt_result_syntax in + let encoding = Tez_repr.encoding in + let bytes = + Data_encoding.Binary.to_bytes_exn Data_encoding.n (Z.of_int 1000000) + in + let* v = + match Data_encoding.Binary.of_bytes encoding bytes with + | Ok x -> return x + | Error e -> + failwith + "Data_encoding.Binary.read shouldn't have failed with \ + Tez_repr.encoding: %a" + Data_encoding.Binary.pp_read_error + e + in + Assert.equal_int64 ~loc:__LOC__ (Tez_repr.to_mutez v) 1000000L +end + +let tests = + [ + tztest + "Check if predefined values hold expected values" + `Quick + Test_tez_repr.test_predefined_values; + tztest "Tez.substract: basic behaviour" `Quick Test_tez_repr.test_subtract; + tztest + "Tez.substract: underflow case" + `Quick + Test_tez_repr.test_substract_underflow; + tztest + "Tez.add: basic behaviour (one + zero)" + `Quick + Test_tez_repr.test_addition; + tztest "Tez.add: overflow" `Quick Test_tez_repr.test_addition_overflow; + tztest "Tez.mul: basic case" `Quick Test_tez_repr.test_mul; + tztest "Tez.mul: overflow case" `Quick Test_tez_repr.test_mul_overflow; + tztest "Tez.div: basic case" `Quick Test_tez_repr.test_div; + tztest "Tez.div: division by zero" `Quick Test_tez_repr.test_div_by_zero; + tztest "Tez.to_mutez: basic assertion" `Quick Test_tez_repr.test_to_mutez; + tztest + "Tez.of_mutez: of non-negative ints" + `Quick + Test_tez_repr.test_of_mutez_non_negative; + tztest + "Tez.of_mutez: of negative ints" + `Quick + Test_tez_repr.test_of_mutez_negative; + tztest + "Tez.of_mutez_exn: of non-negative ints" + `Quick + Test_tez_repr.test_of_mutez_non_negative; + tztest + "Tez.of_mutez_exn: of negative ints" + `Quick + Test_tez_repr.test_of_mutez_negative; + tztest + "Tez.data_encoding: must encode tezzies correctly" + `Quick + Test_tez_repr.test_data_encoding; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("Tez_repr.ml", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_time_repr.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_time_repr.ml new file mode 100644 index 000000000000..99714162b083 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_time_repr.ml @@ -0,0 +1,58 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (time repr) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_time_repr.ml + Subject: Error handling of time operations +*) + +open Protocol + +let test_nominal_add () = + let open Result_syntax in + let t = Time_repr.of_seconds (Int64.of_int 2) in + let addition = + let* p = Period_repr.of_seconds Int64.one in + Time_repr.( +? ) t p + in + match addition with + | Ok v -> + Assert.equal + ~loc:__LOC__ + Time_repr.equal + "test_nominal_add" + Time_repr.pp_hum + v + (Time_repr.of_seconds (Int64.of_int 3)) + | Error _ -> failwith "Addition has overflowed" + +let test_overflow_add () = + let open Lwt_result_syntax in + let t = Time_repr.of_seconds Int64.max_int in + match Period_repr.of_seconds Int64.one with + | Error _ -> failwith "period_repr conversion" + | Ok p -> ( + match Time_repr.( +? ) t p with + | Error _ -> return_unit + | Ok tres -> + failwith + "No overflow: %Ld + %Ld = %Ld" + (Time_repr.to_seconds t) + (Period_repr.to_seconds p) + (Time_repr.to_seconds tres)) + +let tests = + [ + Tztest.tztest "non-overflowing addition" `Quick test_nominal_add; + Tztest.tztest "overflowing addition" `Quick test_overflow_add; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("time", tests)] |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_zk_rollup_storage.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_zk_rollup_storage.ml new file mode 100644 index 000000000000..a5266b5e680e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_zk_rollup_storage.ml @@ -0,0 +1,370 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (Zk_rollup) + Invocation: dune exec src/proto_020_PsParisC/lib_protocol/test/unit/main.exe \ + -- --file test_zk_rollup_storage.ml + Subject: On ZK Rollup storage +*) + +open Protocol + +let batch_size = 10 + +module ZKRU = struct + include Alpha_context.Zk_rollup + + type pkh = Signature.Public_key_hash.t + + let pkh_encoding = Signature.Public_key_hash.encoding + + type ticket_hash = Alpha_context.Ticket_hash.t + + let ticket_hash_encoding = Alpha_context.Ticket_hash.encoding +end + +module Operator = Dummy_zk_rollup.Operator (struct + let batch_size = batch_size +end) + +let no_ticket op = (op, None) + +module Raw_context_tests = struct + module Helpers = struct + let is_empty : Zk_rollup_repr.pending_list -> bool = function + | Zk_rollup_repr.Empty _ -> true + | _ -> false + + let pending_length : Zk_rollup_repr.pending_list -> int = + let open Zk_rollup_repr in + function Empty _ -> 0 | Pending {length; _} -> length + + let get_pending_list = + let open Lwt_result_wrap_syntax in + let open Zk_rollup_repr in + fun ctx rollup -> function + | Empty _ -> return (ctx, []) + | Pending {next_index; length} -> + let head = Int64.(sub next_index (of_int length)) in + let to_get = + Stdlib.List.init length (fun x -> Int64.(add (of_int x) head)) + in + let* ctx, ops = + List.fold_left_es + (fun (ctx, acc) i -> + let*@ ctx, op = + Storage.Zk_rollup.Pending_operation.get (ctx, rollup) i + in + return (ctx, op :: acc)) + (ctx, []) + to_get + in + return (ctx, List.rev ops) + end + + let initial_ctx () = + let open Lwt_result_wrap_syntax in + let* b, contract = Context.init1 () in + let*@ ctx = + Raw_context.prepare + b.context + ~level:b.header.shell.level + ~predecessor_timestamp:b.header.shell.timestamp + ~timestamp:b.header.shell.timestamp + ~adaptive_issuance_enable:false + in + let nonce = Operation_hash.hash_string ["nonce_hash"] in + return (Raw_context.init_origination_nonce ctx nonce, contract) + + (* Context with an originated ZKRU *) + let originate_ctx () = + let open Lwt_result_wrap_syntax in + let open Zk_rollup_account_repr in + let* ctx, contract = initial_ctx () in + let _prover_pp, public_parameters = Lazy.force Operator.lazy_pp in + let state = Operator.init_state in + let state_length = Array.length state in + let circuits_info = SMap.of_seq @@ Kzg.SMap.to_seq Operator.circuits in + let nb_ops = 1 in + let*@ ctx, rollup, _size = + Zk_rollup_storage.originate + ctx + {public_parameters; state_length; circuits_info; nb_ops} + ~init_state:state + in + return (ctx, rollup, contract) + + (* Check that the pending list of a new ZKRU is empty *) + let pending_list_origination_is_empty () = + let open Lwt_result_wrap_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let*@ _ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.is_empty pending) ; + return_unit + + (* Check that appending an L2 operation with the [add_to_pending] helper + correctly updates both the pending list descriptor and the actual + operations under the [pending_operations] directory. *) + let pending_list_append () = + let open Lwt_result_wrap_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let pkh, _, _ = Signature.generate_key () in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [||]; + } + in + (* Append first operation *) + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op] in + let*@ ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.pending_length pending = 1) ; + let* ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (List.length ops = 1) ; + (* Append second operation *) + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op] in + let*@ ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + let* _ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (Helpers.pending_length pending = 2) ; + assert (List.length ops = 2) ; + return_unit + + let pending_list_append_errors () = + let open Lwt_result_wrap_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let pkh, _, _ = Signature.generate_key () in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [||]; + } + in + (* Append first operation *) + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op] in + let*@ ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.pending_length pending = 1) ; + let* ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (List.length ops = 1) ; + (* Invalid op code *) + let wrong_op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 1; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [||]; + } + in + let*!@ e = Zk_rollup_storage.add_to_pending ctx rollup [wrong_op] in + let* () = + Assert.proto_error_with_info ~loc:__LOC__ e "Invalid op code in append" + in + (* Invalid rollup address *) + let*?@ _ctx, nonce = Raw_context.increment_origination_nonce ctx in + let*?@ address = + Zk_rollup_repr.Address.from_nonce (Origination_nonce.incr nonce) + in + let*!@ e = Zk_rollup_storage.add_to_pending ctx address [op] in + let expected_message = "Storage error (fatal internal error)" in + Assert.proto_error_with_info ~loc:__LOC__ e expected_message + + (* Check that the [get_prefix] helper actually returns a list of the + desired length. *) + let pending_list_get () = + let open Lwt_result_wrap_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let pkh, _pk, _sk = Signature.generate_key () in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [|Bls12_381.Fr.one|]; + } + in + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op; op] in + let*@ _ctx, prefix = Zk_rollup_storage.get_prefix ctx rollup 1 in + assert (List.length prefix = 1) ; + return_unit + + (* Check the [get_prefix] errors. *) + let pending_list_errors () = + let open Lwt_result_wrap_syntax in + let* ctx, rollup, _contract = originate_ctx () in + let pkh, _pk, _sk = Signature.generate_key () in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [|Bls12_381.Fr.one|]; + } + in + (* Initialise the pending list with 2 operations *) + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op; op] in + (* Check that retrieving too many ops returns an error *) + let*!@ e = Zk_rollup_storage.get_prefix ctx rollup 3 in + let* () = + Assert.proto_error_with_info ~loc:__LOC__ e "Pending list is too short" + in + (* Check that retrieving a negative number of ops returns an error *) + let*!@ e = Zk_rollup_storage.get_prefix ctx rollup (-1) in + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + e + "Negative length for pending list prefix" + in + (* Check that get prefix fails with invalid zkru address *) + let*?@ _ctx, nonce = Raw_context.increment_origination_nonce ctx in + let*?@ address = + Zk_rollup_repr.Address.from_nonce (Origination_nonce.incr nonce) + in + let*!@ e = Zk_rollup_storage.get_prefix ctx address (-1) in + Assert.proto_error_with_info + ~loc:__LOC__ + e + "Storage error (fatal internal error)" + + (* Check that the [update] helper correctly removes a prefix of the + pending list (both in the descriptor and the actual operations storage). + *) + let test_update () = + let open Lwt_result_wrap_syntax in + (* Originate rollup and contract *) + let* ctx, rollup, contract = originate_ctx () in + let pkh = + match contract with Originated _ -> assert false | Implicit pkh -> pkh + in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [|Bls12_381.Fr.one|]; + } + in + (* Populate rollup with 2 ops *) + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op; op] in + let*@ ctx, acc = Storage.Zk_rollup.Account.get ctx rollup in + (* Processing first pending op *) + let*@ ctx = + Zk_rollup_storage.update ctx rollup ~pending_to_drop:1 ~new_account:acc + in + (* Check that op at index 0 has been removed *) + let*@ ctx, opt = + Storage.Zk_rollup.Pending_operation.find (ctx, rollup) 0L + in + assert (Option.is_none opt) ; + (* Check that pending list still has one op *) + let*@ ctx, pending = Storage.Zk_rollup.Pending_list.get ctx rollup in + assert (Helpers.pending_length pending = 1) ; + let* _ctx, ops = Helpers.get_pending_list ctx rollup pending in + assert (List.length ops = 1) ; + return_unit + + let test_update_errors () = + let open Lwt_result_wrap_syntax in + (* Originate rollup and contract *) + let* ctx, rollup, contract = originate_ctx () in + let pkh = + match contract with Originated _ -> assert false | Implicit pkh -> pkh + in + let op = + no_ticket + Zk_rollup_operation_repr. + { + op_code = 0; + price = {id = Ticket_hash_repr.zero; amount = Z.zero}; + l1_dst = pkh; + rollup_id = rollup; + payload = [|Bls12_381.Fr.one|]; + } + in + (* Populate rollup with 2 ops *) + let*@ ctx, _size = Zk_rollup_storage.add_to_pending ctx rollup [op; op] in + let*@ ctx, acc = Storage.Zk_rollup.Account.get ctx rollup in + (* Processing too many ops *) + let*!@ e = + Zk_rollup_storage.update ctx rollup ~pending_to_drop:3 ~new_account:acc + in + let* () = + Assert.proto_error_with_info ~loc:__LOC__ e "Pending list is too short" + in + (* Processing negative number of ops *) + let*!@ e = + Zk_rollup_storage.update ctx rollup ~pending_to_drop:(-3) ~new_account:acc + in + let* () = + Assert.proto_error_with_info + ~loc:__LOC__ + e + "Negative length for pending list prefix" + in + (* Update with wrong address *) + let*?@ _ctx, nonce = Raw_context.increment_origination_nonce ctx in + let*?@ address = + Zk_rollup_repr.Address.from_nonce (Origination_nonce.incr nonce) + in + let*!@ e = + Zk_rollup_storage.update ctx address ~pending_to_drop:1 ~new_account:acc + in + Assert.proto_error_with_info + ~loc:__LOC__ + e + "Storage error (fatal internal error)" +end + +let tests = + [ + Tztest.tztest + "origination_pending_is_empty" + `Quick + Raw_context_tests.pending_list_origination_is_empty; + Tztest.tztest + "pending_list_append" + `Quick + Raw_context_tests.pending_list_append; + Tztest.tztest + "pending_list_append errors" + `Quick + Raw_context_tests.pending_list_append_errors; + Tztest.tztest "pending_list_get" `Quick Raw_context_tests.pending_list_get; + Tztest.tztest + "pending_list_get errors" + `Quick + Raw_context_tests.pending_list_errors; + Tztest.tztest "update" `Quick Raw_context_tests.test_update; + Tztest.tztest "update errors" `Quick Raw_context_tests.test_update_errors; + ] + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("zk rollup storage", tests)] + |> Lwt_main.run diff --git a/src/proto_020_PsParisC/lib_protocol/tez_repr.ml b/src/proto_020_PsParisC/lib_protocol/tez_repr.ml new file mode 100644 index 000000000000..55e695a9d125 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/tez_repr.ml @@ -0,0 +1,326 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let id = "tez" + +let name = "mutez" + +open Compare.Int64 (* invariant: positive *) + +type repr = t + +type t = Tez_tag of repr [@@ocaml.unboxed] + +let wrap t = Tez_tag t [@@ocaml.inline always] + +type error += + | Addition_overflow of t * t (* `Temporary *) + | Subtraction_underflow of t * t (* `Temporary *) + | Multiplication_overflow of t * Z.t (* `Temporary *) + | Negative_multiplicator of t * Z.t (* `Temporary *) + | Invalid_divisor of t * Z.t + +(* `Temporary *) + +let zero = Tez_tag 0L + +(* all other constant are defined from the value of one micro tez *) +let one_mutez = Tez_tag 1L + +let max_mutez = Tez_tag Int64.max_int + +let mul_int (Tez_tag tez) i = Tez_tag (Int64.mul tez i) + +let one_cent = mul_int one_mutez 10_000L + +let fifty_cents = mul_int one_cent 50L + +(* 1 tez = 100 cents = 1_000_000 mutez *) +let one = mul_int one_cent 100L + +let of_string s = + let triplets = function + | hd :: tl -> + let len = String.length hd in + Compare.Int.( + len <= 3 && len > 0 && List.for_all (fun s -> String.length s = 3) tl) + | [] -> false + in + let integers s = triplets (String.split_on_char ',' s) in + let decimals s = + let l = String.split_on_char ',' s in + if Compare.List_length_with.(l > 2) then false else triplets (List.rev l) + in + let parse left right = + let remove_commas s = String.concat "" (String.split_on_char ',' s) in + let pad_to_six s = + let len = String.length s in + String.init 6 (fun i -> if Compare.Int.(i < len) then s.[i] else '0') + in + let prepared = remove_commas left ^ pad_to_six (remove_commas right) in + Option.map wrap (Int64.of_string_opt prepared) + in + match String.split_on_char '.' s with + | [left; right] -> + if String.contains s ',' then + if integers left && decimals right then parse left right else None + else if + Compare.Int.(String.length right > 0) + && Compare.Int.(String.length right <= 6) + then parse left right + else None + | [left] -> + if (not (String.contains s ',')) || integers left then parse left "" + else None + | _ -> None + +let pp ppf (Tez_tag amount) = + let mult_int = 1_000_000L in + let rec left ppf amount = + let d, r = (Int64.div amount 1000L, Int64.rem amount 1000L) in + if Compare.Int64.(d > 0L) then Format.fprintf ppf "%a%03Ld" left d r + else Format.fprintf ppf "%Ld" r + in + let right ppf amount = + let triplet ppf v = + if Compare.Int.(v mod 10 > 0) then Format.fprintf ppf "%03d" v + else if Compare.Int.(v mod 100 > 0) then Format.fprintf ppf "%02d" (v / 10) + else Format.fprintf ppf "%d" (v / 100) + in + let hi, lo = (amount / 1000, amount mod 1000) in + if Compare.Int.(lo = 0) then Format.fprintf ppf "%a" triplet hi + else Format.fprintf ppf "%03d%a" hi triplet lo + in + let ints, decs = + (Int64.div amount mult_int, Int64.(to_int (rem amount mult_int))) + in + left ppf ints ; + if Compare.Int.(decs > 0) then Format.fprintf ppf ".%a" right decs + +let to_string t = Format.asprintf "%a" pp t + +let ( -? ) tez1 tez2 = + let open Result_syntax in + let (Tez_tag t1) = tez1 in + let (Tez_tag t2) = tez2 in + if t2 <= t1 then return (Tez_tag (Int64.sub t1 t2)) + else tzfail (Subtraction_underflow (tez1, tez2)) + +let sub_opt (Tez_tag t1) (Tez_tag t2) = + if t2 <= t1 then Some (Tez_tag (Int64.sub t1 t2)) else None + +let ( +? ) tez1 tez2 = + let open Result_syntax in + let (Tez_tag t1) = tez1 in + let (Tez_tag t2) = tez2 in + let t = Int64.add t1 t2 in + if t < t1 then tzfail (Addition_overflow (tez1, tez2)) else return (Tez_tag t) + +let ( *? ) tez m = + let open Result_syntax in + let (Tez_tag t) = tez in + if m < 0L then tzfail (Negative_multiplicator (tez, Z.of_int64 m)) + else if m = 0L then return (Tez_tag 0L) + else if t > Int64.(div max_int m) then + tzfail (Multiplication_overflow (tez, Z.of_int64 m)) + else return (Tez_tag (Int64.mul t m)) + +let ( /? ) tez d = + let open Result_syntax in + let (Tez_tag t) = tez in + if d <= 0L then tzfail (Invalid_divisor (tez, Z.of_int64 d)) + else return (Tez_tag (Int64.div t d)) + +let div2 (Tez_tag t) = Tez_tag (Int64.div t 2L) + +let mul_exn t m = + match t *? Int64.of_int m with Ok v -> v | Error _ -> invalid_arg "mul_exn" + +let div_exn t d = + match t /? Int64.of_int d with Ok v -> v | Error _ -> invalid_arg "div_exn" + +let mul_ratio_z ~rounding tez ~num ~den = + let open Result_syntax in + let (Tez_tag t) = tez in + if Z.(lt num zero) then tzfail (Negative_multiplicator (tez, num)) + else if Z.(leq den zero) then tzfail (Invalid_divisor (tez, den)) + else + let numerator = Z.(mul (of_int64 t) num) in + let z = + match rounding with + | `Down -> Z.div numerator den + | `Up -> Z.cdiv numerator den + in + if Z.fits_int64 z then return (Tez_tag (Z.to_int64 z)) + else tzfail (Multiplication_overflow (tez, num)) + +let mul_ratio ~rounding tez ~num ~den = + mul_ratio_z ~rounding tez ~num:(Z.of_int64 num) ~den:(Z.of_int64 den) + +let mul_q ~rounding tez {Q.num; den} = mul_ratio_z ~rounding tez ~num ~den + +let mul_percentage ~rounding (Tez_tag t) (percentage : Percentage.t) = + let {Q.num; den} = Percentage.to_q percentage in + (* Guaranteed to produce no errors by the invariants on {!Percentage.t}. *) + let div' = match rounding with `Down -> Z.div | `Up -> Z.cdiv in + Tez_tag Z.(to_int64 (div' (mul (of_int64 t) num) den)) + +let of_mutez t = if t < 0L then None else Some (Tez_tag t) + +let of_mutez_exn x = + match of_mutez x with None -> invalid_arg "Tez.of_mutez" | Some v -> v + +let to_mutez (Tez_tag t) = t + +let encoding = + let open Data_encoding in + let decode (Tez_tag t) = Z.of_int64 t in + let encode = Json.wrap_error (fun i -> Tez_tag (Z.to_int64 i)) in + Data_encoding.def name (check_size 10 (conv decode encode n)) + +let balance_update_encoding = + let open Data_encoding in + conv + (function + | `Credited v -> to_mutez v | `Debited v -> Int64.neg (to_mutez v)) + ( Json.wrap_error @@ fun v -> + if Compare.Int64.(v < 0L) then `Debited (Tez_tag (Int64.neg v)) + else `Credited (Tez_tag v) ) + int64 + +let () = + let open Data_encoding in + register_error_kind + `Temporary + ~id:(id ^ ".addition_overflow") + ~title:("Overflowing " ^ id ^ " addition") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Overflowing addition of %a %s and %a %s" + pp + opa + id + pp + opb + id) + ~description:("An addition of two " ^ id ^ " amounts overflowed") + (obj1 (req "amounts" (tup2 encoding encoding))) + (function Addition_overflow (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Addition_overflow (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".subtraction_underflow") + ~title:("Underflowing " ^ id ^ " subtraction") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Underflowing subtraction of %a %s and %a %s" + pp + opa + id + pp + opb + id) + ~description: + ("A subtraction of two " ^ id + ^ " amounts underflowed (i.e., would have led to a negative amount)") + (obj1 (req "amounts" (tup2 encoding encoding))) + (function Subtraction_underflow (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Subtraction_underflow (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".multiplication_overflow") + ~title:("Overflowing " ^ id ^ " multiplication") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Overflowing multiplication of %a %s and %a" + pp + opa + id + Z.pp_print + opb) + ~description: + ("A multiplication of a " ^ id ^ " amount by an integer overflowed") + (obj2 (req "amount" encoding) (req "multiplicator" z)) + (function Multiplication_overflow (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Multiplication_overflow (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".negative_multiplicator") + ~title:("Negative " ^ id ^ " multiplicator") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Multiplication of %a %s by negative integer %a" + pp + opa + id + Z.pp_print + opb) + ~description:("Multiplication of a " ^ id ^ " amount by a negative integer") + (obj2 (req "amount" encoding) (req "multiplicator" z)) + (function Negative_multiplicator (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Negative_multiplicator (a, b)) ; + register_error_kind + `Temporary + ~id:(id ^ ".invalid_divisor") + ~title:("Invalid " ^ id ^ " divisor") + ~pp:(fun ppf (opa, opb) -> + Format.fprintf + ppf + "Division of %a %s by non positive integer %a" + pp + opa + id + Z.pp_print + opb) + ~description: + ("Multiplication of a " ^ id ^ " amount by a non positive integer") + (obj2 (req "amount" encoding) (req "divisor" z)) + (function Invalid_divisor (a, b) -> Some (a, b) | _ -> None) + (fun (a, b) -> Invalid_divisor (a, b)) + +let compare (Tez_tag x) (Tez_tag y) = compare x y + +let ( = ) (Tez_tag x) (Tez_tag y) = x = y + +let ( <> ) (Tez_tag x) (Tez_tag y) = x <> y + +let ( < ) (Tez_tag x) (Tez_tag y) = x < y + +let ( > ) (Tez_tag x) (Tez_tag y) = x > y + +let ( <= ) (Tez_tag x) (Tez_tag y) = x <= y + +let ( >= ) (Tez_tag x) (Tez_tag y) = x >= y + +let equal (Tez_tag x) (Tez_tag y) = equal x y + +let max (Tez_tag x) (Tez_tag y) = Tez_tag (max x y) + +let min (Tez_tag x) (Tez_tag y) = Tez_tag (min x y) diff --git a/src/proto_020_PsParisC/lib_protocol/tez_repr.mli b/src/proto_020_PsParisC/lib_protocol/tez_repr.mli new file mode 100644 index 000000000000..da09235aaae2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/tez_repr.mli @@ -0,0 +1,115 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Internal representation of the Tez currency. Behaves mostly like a natural + number where number 1 represents 1/1,000,000 Tez (1 micro-Tez or mutez). + It's protected from ever becoming negative and overflowing by special + arithmetic functions, which fail in case something undesired would happen. + When divided, it's always rounded down to 1 mutez. + + Internally encoded as [int64], which may be relevant to guard against + overflow errors. *) +type repr + +(** [t] is made algebraic in order to distinguish it from the other type + parameters of [Script_typed_ir.ty]. *) +type t = Tez_tag of repr [@@ocaml.unboxed] + +type error += + | Addition_overflow of t * t (* `Temporary *) + | Subtraction_underflow of t * t (* `Temporary *) + | Multiplication_overflow of t * Z.t (* `Temporary *) + | Negative_multiplicator of t * Z.t (* `Temporary *) + | Invalid_divisor of t * Z.t (* `Temporary *) + +val zero : t + +val one_mutez : t + +val one_cent : t + +val fifty_cents : t + +val one : t + +val max_mutez : t + +val ( -? ) : t -> t -> t tzresult + +(** Same as ( -? ) but returns None instead of an error. *) +val sub_opt : t -> t -> t option + +val ( +? ) : t -> t -> t tzresult + +val ( *? ) : t -> int64 -> t tzresult + +val ( /? ) : t -> int64 -> t tzresult + +val div2 : t -> t + +(** [mul_ratio ~rounding tez ~num ~den] returns [tez * num / den] without failing + when [tez * num] overflows. + [rounding] controls the rounding of the division. *) +val mul_ratio : + rounding:[`Down | `Up] -> t -> num:int64 -> den:int64 -> t tzresult + +(** [mul_ratio_z] is the same as [mul_ratio], but takes [Z.t] as arguments *) +val mul_ratio_z : + rounding:[`Down | `Up] -> t -> num:Z.t -> den:Z.t -> t tzresult + +(** [mul_q] is the same as [mul_ratio_z], but takes a [Q.t] as an argument *) +val mul_q : rounding:[`Down | `Up] -> t -> Q.t -> t tzresult + +(** [mul_percentage tez percentage] returns [tez * percentage / 100]. + No errors can happen. *) +val mul_percentage : rounding:[`Down | `Up] -> t -> Percentage.t -> t + +val to_mutez : t -> int64 + +(** [of_mutez n] (micro tez) is None if n is negative *) +val of_mutez : int64 -> t option + +(** [of_mutez_exn n] fails if n is negative. + It should only be used at toplevel for constants. *) +val of_mutez_exn : int64 -> t + +(** It should only be used at toplevel for constants. *) +val mul_exn : t -> int -> t + +(** It should only be used at toplevel for constants. *) +val div_exn : t -> int -> t + +val encoding : t Data_encoding.t + +val balance_update_encoding : [`Credited of t | `Debited of t] Data_encoding.t + +include Compare.S with type t := t + +val pp : Format.formatter -> t -> unit + +val of_string : string -> t option + +val to_string : t -> string diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_accounting.ml b/src/proto_020_PsParisC/lib_protocol/ticket_accounting.ml new file mode 100644 index 000000000000..ae2b6f756b90 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_accounting.ml @@ -0,0 +1,296 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Invalid_ticket_transfer of {ticketer : string; amount : Z.t} + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"invalid_ticket_transfer" + ~title:"Invalid ticket transfer" + ~description:"Invalid ticket transfer detected in ticket balance update." + ~pp:(fun ppf (ticketer, amount) -> + Format.fprintf + ppf + "Attempted to send %a unit(s) of a ticket created by %s." + Z.pp_print + amount + ticketer) + (obj2 (req "ticketer" (string Plain)) (req "amount" z)) + (function + | Invalid_ticket_transfer {ticketer; amount} -> Some (ticketer, amount) + | _ -> None) + (fun (ticketer, amount) -> Invalid_ticket_transfer {ticketer; amount}) + +module Ticket_token_map = struct + include Ticket_token_map + + let balance_diff ctxt token map = + let open Lwt_result_syntax in + let+ amnt_opt, ctxt = Ticket_token_map.find ctxt token map in + (Option.value ~default:Z.zero amnt_opt, ctxt) + + let merge_overlap ctxt b1 b2 = + let open Result_syntax in + let+ ctxt = Gas.consume ctxt (Ticket_costs.add_z_cost b1 b2) in + (Z.add b1 b2, ctxt) + + let of_list ctxt token_amounts = + Ticket_token_map.of_list ctxt ~merge_overlap token_amounts + + let add ctxt = Ticket_token_map.merge ctxt ~merge_overlap + + let sub ctxt m1 m2 = + let open Result_syntax in + let* m2, ctxt = + map_e + ctxt + (fun ctxt _ex_token amount -> + let+ ctxt = Gas.consume ctxt (Ticket_costs.negate_cost amount) in + (Z.neg amount, ctxt)) + m2 + in + add ctxt m1 m2 +end + +let ticket_balances_of_value ctxt ~include_lazy ty value = + let open Lwt_result_syntax in + let* tickets, ctxt = + Ticket_scanner.tickets_of_value ~include_lazy ctxt ty value + in + let accum_ticket_balances (acc, ctxt) ticket = + let open Result_syntax in + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in + let+ ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + ( (token, Script_int.to_zint (amount :> Script_int.n Script_int.num)) :: acc, + ctxt ) + in + let*? token_amounts, ctxt = + List.fold_left_e accum_ticket_balances ([], ctxt) tickets + in + Ticket_token_map.of_list ctxt token_amounts + +let update_ticket_balances ctxt ~total_storage_diff token destinations = + let open Lwt_result_syntax in + List.fold_left_es + (fun (tot_storage_diff, ctxt) (owner, delta) -> + let* key_hash, ctxt = Ticket_balance_key.of_ex_token ctxt ~owner token in + let* storage_diff, ctxt = + Ticket_balance.adjust_balance ctxt key_hash ~delta + in + let*? ctxt = + Gas.consume + ctxt + (Ticket_costs.add_z_cost total_storage_diff storage_diff) + in + return (Z.add tot_storage_diff storage_diff, ctxt)) + (total_storage_diff, ctxt) + destinations + +let invalid_ticket_transfer_error + ~ticket_token: + (Ticket_token.Ex_token {ticketer; contents_type = _; contents = _}) + ~amount = + Invalid_ticket_transfer {ticketer = Contract.to_b58check ticketer; amount} + +let update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs = + let open Lwt_result_syntax in + List.fold_left_es + (fun (total_storage_diff, ctxt) (ticket_token, amount) -> + (* Diff is valid iff either: + - the balance has decreased (delta <= 0), or + - the ticket-token was created by the [self] contract. *) + let is_valid_balance_update = + let (Ticket_token.Ex_token {ticketer; _}) = ticket_token in + Compare.Z.(amount <= Z.zero) || Contract.equal ticketer self_contract + in + let*? () = + error_unless + is_valid_balance_update + (invalid_ticket_transfer_error ~ticket_token ~amount) + in + update_ticket_balances + ctxt + ~total_storage_diff + ticket_token + [(Destination.Contract self_contract, amount)]) + (Z.zero, ctxt) + ticket_diffs + +let ticket_diffs_of_lazy_storage_diff ctxt ~storage_type_has_tickets + lazy_storage_diff = + let open Lwt_result_syntax in + (* Only scan lazy-diffs for tickets in case the storage contains tickets. *) + if Ticket_scanner.has_tickets storage_type_has_tickets then + let* diffs, ctxt = + Ticket_lazy_storage_diff.ticket_diffs_of_lazy_storage_diff + ctxt + lazy_storage_diff + in + Ticket_token_map.of_list ctxt diffs + else return (Ticket_token_map.empty, ctxt) + +(* TODO #2465 + Move the docs from HackMd to [docs/alpha] folder. + The documentation referenced here should be moved to a permanent place and + the comment below should be updated. +*) + +(** Description here: + https://hackmd.io/lutm_5JNRVW-nNFSFkCXLQ?view#Implementation + + - [old_storage_strict] the amount S_1^{strict} of ticket-tokens in the strict part of + the old storage. + + - [new_storage_strict] the amount S_2^{strict} of ticket-tokens in the strict part of the + new storage. + + - [lazy_storage_diff] the amount S_{\delta}^{lazy} of ticket-tokens added to the lazy part of + the storage. + + - [arg_tickets] the amount I of ticket-tokens contained in the incoming + arguments. + + We calculate the ticket diff as the following: + [new_storage_strict] + [lazy_storage_diff] - ([old_storage_strict] + [arg_tickets]) + + Additionally, we calculate the ticket receipt as below. + We do not subtract the [arg_tickets] since we only want to display the tickets updated in storage for the receipt. + [new_storage_strict] + [lazy_storage_diff] - [storage_strict] + *) +let ticket_diffs ctxt ~self_contract ~arg_type_has_tickets + ~storage_type_has_tickets ~arg ~old_storage ~new_storage ~lazy_storage_diff + = + let open Lwt_result_syntax in + (* Collect ticket-token balances of the incoming parameters. *) + let* arg_tickets, ctxt = + ticket_balances_of_value ctxt ~include_lazy:true arg_type_has_tickets arg + in + let* lazy_storage_diff, ctxt = + ticket_diffs_of_lazy_storage_diff + ctxt + ~storage_type_has_tickets + lazy_storage_diff + in + let* old_storage_strict, ctxt = + ticket_balances_of_value + ctxt + ~include_lazy:false + storage_type_has_tickets + old_storage + in + let* new_storage_strict, ctxt = + ticket_balances_of_value + ctxt + ~include_lazy:false + storage_type_has_tickets + new_storage + in + let*? additions, ctxt = + Ticket_token_map.add ctxt new_storage_strict lazy_storage_diff + in + let*? total_storage_diff, ctxt = + Ticket_token_map.sub ctxt additions old_storage_strict + in + let*? diff, ctxt = Ticket_token_map.sub ctxt total_storage_diff arg_tickets in + let* ticket_receipt, ctxt = + Ticket_token_map.to_ticket_receipt + ctxt + ~owner:Destination.(Contract self_contract) + total_storage_diff + in + return (diff, ticket_receipt, ctxt) + +let update_ticket_balances ctxt ~self_contract ~ticket_diffs operations = + let open Lwt_result_syntax in + let validate_spending_budget ctxt + (Ticket_token.Ex_token {ticketer; _} as ticket_token) amount = + if Contract.equal ticketer self_contract then + (* It's okay to send any amount of ticket-tokens minted by the current + contract (self). Hence tickets stored by their ticketer are not + stored in the ticket table and don't need to be updated here. *) + return (true, ctxt) + else + let+ balance_diff, ctxt = + Ticket_token_map.balance_diff ctxt ticket_token ticket_diffs + in + (* The balance-diff represents the number of units of a ticket-token, + that is changed for the [self] contract. A negative diff means that + an amount of ticket-tokens were not saved in the storage and are + eligible for transfer to another contract. + + For example, if 5 units of a ticket-token "Alice Red" were pulled from + the storage, the corresponding diff is -5. That means at most 5 units + of "Alice Red" can be transferred. Any amount exceeding that would + result in a validation error. + *) + (Compare.Z.(Script_int.to_zint amount <= Z.neg balance_diff), ctxt) + in + (* Collect diffs from operations *) + let* ticket_op_diffs, ctxt = + Ticket_operations_diff.ticket_diffs_of_operations ctxt operations + in + (* Update balances for self-contract. *) + let*? ticket_diffs, ctxt = Ticket_token_map.to_list ctxt ticket_diffs in + let* total_storage_diff, ctxt = + update_ticket_balances_for_self_contract ctxt ~self_contract ticket_diffs + in + (* Update balances for operations. *) + List.fold_left_es + (fun (total_storage_diff, ctxt) + {Ticket_operations_diff.ticket_token; total_amount; destinations} -> + (* Verify that we are able to spend the given amount of ticket-tokens. *) + let* is_valid_balance_update, ctxt = + validate_spending_budget ctxt ticket_token total_amount + in + let*? () = + error_unless + is_valid_balance_update + (invalid_ticket_transfer_error + ~ticket_token + ~amount:(Script_int.to_zint total_amount)) + in + let*? destinations, ctxt = + List.fold_left_e + (fun (acc, ctxt) (token, (amount : Script_typed_ir.ticket_amount)) -> + (* Consume some gas for traversing the list. *) + let open Result_syntax in + let+ ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + ((token, Script_int.(to_zint (amount :> n num))) :: acc, ctxt)) + ([], ctxt) + destinations + in + update_ticket_balances ctxt ~total_storage_diff ticket_token destinations) + (total_storage_diff, ctxt) + ticket_op_diffs diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_accounting.mli b/src/proto_020_PsParisC/lib_protocol/ticket_accounting.mli new file mode 100644 index 000000000000..621fb196a8ec --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_accounting.mli @@ -0,0 +1,76 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** [ticket_diffs ctxt ~arg_type_has_tickets ~storage_type_has_tickets arg + old_storage new_storage lazy_storage_diff] returns a map from + ticket-tokens to balance-differences that represents the change in balance + for a contract due to changes of tickets in the storage. The assumption is + that before calling [ticket_diffs], all tickets that are owned by a contract + exist either in the [old_storage] or the [arg]. After execution, only + tickets in [new_storage] are owned by the contract. Note that this function + avoids traversing the lazy part of the storage. +*) +val ticket_diffs : + context -> + self_contract:Contract.t -> + arg_type_has_tickets:'arg Ticket_scanner.has_tickets -> + storage_type_has_tickets:'storage Ticket_scanner.has_tickets -> + arg:'arg -> + old_storage:'storage -> + new_storage:'storage -> + lazy_storage_diff:Lazy_storage.diffs_item list -> + (Z.t Ticket_token_map.t * Ticket_receipt.t * context) tzresult Lwt.t + +(** [ticket_balances_of_value ctxt ~include_lazy has_tickets value] + scans all tickets in the given [value] using the type-witness [has_tickets] + and returns a map from ticket-tokens to the amount. *) +val ticket_balances_of_value : + context -> + include_lazy:bool -> + 'a Ticket_scanner.has_tickets -> + 'a -> + (Z.t Ticket_token_map.t * context) tzresult Lwt.t + +(** [update_ticket_balances ctxt ~self_contract ~ticket_diffs operations] updates the + ticket balances according to the [ticket_diffs] map and the set of + operations. The function also returns the storage size diff resulting from + updating the ticket-balance table in the context. + + Invariant: this function must be called after applying the lazy-storage + diffs affecting any contracts in the given operations. + + The function fails in case an invalid ticket-token-balance update is + detected. The [ticket_diffs] argument represents the change of ticket-tokens + for the [self] contract. It also specifies a "budget" for outgoing + ticket-tokens. +*) +val update_ticket_balances : + context -> + self_contract:Contract.t -> + ticket_diffs:Z.t Ticket_token_map.t -> + Script_typed_ir.packed_internal_operation list -> + (Z.t * context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_amount.ml b/src/proto_020_PsParisC/lib_protocol/ticket_amount.ml new file mode 100644 index 000000000000..9bc9cbbfebf6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_amount.ml @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_int + +type t = n num + +let of_n n = + if Compare.Int.(Script_int.(compare n zero_n) > 0) then Some (n : t) else None + +let of_z z = Option.bind (is_nat z) of_n + +let of_zint z = of_z @@ of_zint z + +let add = add_n + +let sub a b = of_z @@ sub a b + +let one = one_n + +let encoding = + let open Data_encoding in + conv_with_guard + to_zint + (fun n -> Option.value_e ~error:"expecting positive number" @@ of_zint n) + n diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_amount.mli b/src/proto_020_PsParisC/lib_protocol/ticket_amount.mli new file mode 100644 index 000000000000..191e0949cc70 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_amount.mli @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Script_int + +(* A type for ticket amount values to ensure positivity *) +type t = private n num + +val encoding : t Data_encoding.t + +(* Converts a natural number to a ticket amount value unless the input is zero *) +val of_n : n num -> t option + +(* Converts a integral number to a ticket amount value unless the input is not positive *) +val of_z : z num -> t option + +val of_zint : Z.t -> t option + +val add : t -> t -> t + +(* Subtract among ticket amount values unless the resultant amount is not positive *) +val sub : t -> t -> t option + +val one : t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_balance_key.ml b/src/proto_020_PsParisC/lib_protocol/ticket_balance_key.ml new file mode 100644 index 000000000000..9d649afba8d2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_balance_key.ml @@ -0,0 +1,92 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let make ctxt ~owner ~ticketer ~contents_type ~contents = + let open Lwt_result_syntax in + let ticketer_address = + Script_typed_ir. + {destination = Contract ticketer; entrypoint = Entrypoint.default} + in + let owner_address = + Script_typed_ir.{destination = owner; entrypoint = Entrypoint.default} + in + let* ticketer, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized_legacy + Script_typed_ir.address_t + ticketer_address + in + let* owner, ctxt = + Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized_legacy + Script_typed_ir.address_t + owner_address + in + Lwt.return + @@ Ticket_hash.make + ctxt + ~ticketer:(Micheline.root ticketer) + ~ty:contents_type + ~contents + ~owner:(Micheline.root owner) + +(* This function extracts nodes of: + - Ticketer + - Type of content + - Content + - Owner + to generate at ticket-balance key-hash.*) +let of_ex_token ctxt ~owner + (Ticket_token.Ex_token {ticketer; contents_type; contents}) = + let open Lwt_result_syntax in + let loc = Micheline.dummy_location in + let*? cont_ty_unstripped, ctxt = + Script_ir_unparser.unparse_ty ~loc ctxt contents_type + in + (* We strip the annotations from the content type in order to map + tickets with the same content type, but with different annotations, to the + same hash. *) + let*? ctxt = + Gas.consume ctxt (Script.strip_annotations_cost cont_ty_unstripped) + in + let ty = Script.strip_annotations cont_ty_unstripped in + let* contents, ctxt = + Script_ir_unparser.unparse_comparable_data + ctxt + Script_ir_unparser.Optimized_legacy + contents_type + contents + in + make + ctxt + ~owner + ~ticketer + ~contents_type:ty + ~contents:(Micheline.root contents) diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_balance_key.mli b/src/proto_020_PsParisC/lib_protocol/ticket_balance_key.mli new file mode 100644 index 000000000000..53af20ca9ada --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_balance_key.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** This module exposes a function for generating a ticket-balance key-hash + given an owner and a ticket-token. The key-hash is used for populating the + global ticket-balance table that tracks ownership of tickets for different tokens. + *) + +(** [make ~owner ~ticketer ~contents_type ~contents] returns [key_hash] of the + given [owner], [ticketer], [contents_type] and [contents]. Note that the + [location] of the [Script.node] values [contents_type] and [contents] are + irrelevant since [Ticket_hash.make] will strip the locations before calculating the hash. *) +val make : + context -> + owner:Destination.t -> + ticketer:Contract.t -> + contents_type:Script.node -> + contents:Script.node -> + (Ticket_hash.t * context) tzresult Lwt.t + +(** [of_ex_token ctxt ~owner ex_token] returns the [key_hash] of the + given [owner] and [ex_token]. *) +val of_ex_token : + context -> + owner:Destination.t -> + Ticket_token.ex_token -> + (Ticket_hash.t * context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_costs.ml b/src/proto_020_PsParisC/lib_protocol/ticket_costs.ml new file mode 100644 index 000000000000..d35ad062d2bb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_costs.ml @@ -0,0 +1,56 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* Copyright (c) 2023 DaiLambda, Inc., *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context +include Ticket_costs_generated + +module Constants = struct + let cost_collect_tickets_step = cost_COLLECT_TICKETS_STEP 1 + + let cost_compare_ticket_hash = cost_COMPARE_TICKET_HASH + + let cost_compare_key_contract = cost_COMPARE_CONTRACT +end + +let consume_gas_steps ctxt ~num_steps = + if Compare.Int.(num_steps <= 0) then Ok ctxt + else + let gas = Gas.atomic_step_cost (cost_COLLECT_TICKETS_STEP num_steps) in + Gas.consume ctxt gas + +let has_tickets_of_ty_cost ty = + cost_TYPE_HAS_TICKETS Script_typed_ir.(ty_size ty |> Type_size.to_int) + +(** Reusing the gas model from [Michelson_v1_gas.Cost_of.neg] *) +let negate_cost z = + Michelson_v1_gas.Cost_of.Interpreter.neg (Script_int.of_zint z) + +(** Reusing the gas model from [Michelson_v1_gas.Cost_of.add] *) +let add_int_cost = Michelson_v1_gas.Cost_of.Interpreter.add_int + +(** Reusing the gas model from [Michelson_v1_gas.Cost_of.add] *) +let add_z_cost z1 z2 = + add_int_cost (Script_int.of_zint z1) (Script_int.of_zint z2) diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_costs.mli b/src/proto_020_PsParisC/lib_protocol/ticket_costs.mli new file mode 100644 index 000000000000..13e999500a3e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_costs.mli @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module contains constants and utility functions for gas metering + functions used for extracting and handling tickets for the global ticket + balance table. *) + +module Constants : sig + val cost_collect_tickets_step : Alpha_context.Gas.cost + + val cost_compare_ticket_hash : Alpha_context.Gas.cost + + val cost_compare_key_contract : Alpha_context.Gas.cost +end + +(** [consume_gas_steps ctxt ~num_steps] consumes gas corresponding to + a given [num_steps] and [step_cost]. It's useful for paying for gas + upfront where the number of steps can be determined. + + This function is generic and should probably be moved. See issue + https://gitlab.com/tezos/tezos/-/issues/1950. + + *) +val consume_gas_steps : + Alpha_context.t -> num_steps:int -> Alpha_context.t tzresult + +(** [has_tickets_of_ty_cost ty] returns the cost of producing a [has_tickets], + used internally in the [Ticket_scanner] module. *) +val has_tickets_of_ty_cost : + ('a, _) Script_typed_ir.ty -> Saturation_repr.may_saturate Saturation_repr.t + +(** [negate_cost z] returns the cost of negating the given value [z]. *) +val negate_cost : Z.t -> Alpha_context.Gas.cost + +(** [add_int_cost n1 n2] returns the cost of adding the values [n1] and [n2]. *) +val add_int_cost : + Script_int.n Script_int.num -> + Script_int.n Script_int.num -> + Alpha_context.Gas.cost + +(** [add_z_cost z1 z2] returns the cost of adding the values [z1] and [z2]. *) +val add_z_cost : Z.t -> Z.t -> Alpha_context.Gas.cost diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_costs_generated.ml b/src/proto_020_PsParisC/lib_protocol/ticket_costs_generated.ml new file mode 100644 index 000000000000..91b95c2651c3 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_costs_generated.ml @@ -0,0 +1,28 @@ +(* Do not edit this file manually. + This file was automatically generated from benchmark models + If you wish to update a function in this file, + a. update the corresponding model, or + b. move the function to another module and edit it there. *) + +[@@@warning "-33"] + +module S = Saturation_repr +open S.Syntax + +(* model tickets/COLLECT_TICKETS_STEP *) +(* fun size -> max 10 (0. + (80. * size)) *) +let cost_COLLECT_TICKETS_STEP size = + let size = S.safe_int size in + S.max (S.safe_int 10) (size * S.safe_int 80) + +(* model tickets/COMPARE_CONTRACT *) +(* max 10 10. *) +let cost_COMPARE_CONTRACT = S.safe_int 10 + +(* model tickets/COMPARE_TICKET_HASH *) +(* max 10 10. *) +let cost_COMPARE_TICKET_HASH = S.safe_int 10 + +(* model tickets/TYPE_HAS_TICKETS *) +(* fun size -> max 10 (10. + (6. * size)) *) +let cost_TYPE_HAS_TICKETS size = (size * S.safe_int 6) + S.safe_int 10 diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.ml b/src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.ml new file mode 100644 index 000000000000..dddb6334db75 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.ml @@ -0,0 +1,83 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += Failed_to_hash_node + +let () = + register_error_kind + `Branch + ~id:"Failed_to_hash_node" + ~title:"Failed to hash node" + ~description:"Failed to hash node for a key in the ticket-balance table" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Failed to hash node for a key in the ticket-balance table") + Data_encoding.empty + (function Failed_to_hash_node -> Some () | _ -> None) + (fun () -> Failed_to_hash_node) + +(* No model is given. The original definition was a copy of + Global_constants_costs.expr_to_address_in_context_cost. +*) +let hash_bytes_cost = Global_constants_costs.expr_to_address_in_context_cost + +let hash_of_node ctxt node = + let open Result_syntax in + let* ctxt = + Raw_context.consume_gas ctxt (Script_repr.strip_locations_cost node) + in + let node = Micheline.strip_locations node in + let* bytes = + Result.of_option + ~error:(Error_monad.trace_of_error Failed_to_hash_node) + (Data_encoding.Binary.to_bytes_opt Script_repr.expr_encoding node) + in + let+ ctxt = Raw_context.consume_gas ctxt (hash_bytes_cost bytes) in + ( Ticket_hash_repr.of_script_expr_hash @@ Script_expr_hash.hash_bytes [bytes], + ctxt ) + +let hash_of_node_uncarbonated node = + let open Result_syntax in + let node = Micheline.strip_locations node in + let+ bytes = + Result.of_option + ~error:(Error_monad.trace_of_error Failed_to_hash_node) + (Data_encoding.Binary.to_bytes_opt Script_repr.expr_encoding node) + in + Ticket_hash_repr.of_script_expr_hash @@ Script_expr_hash.hash_bytes [bytes] + +let make ctxt ~ticketer ~ty ~contents ~owner = + hash_of_node ctxt + @@ Micheline.Seq (Micheline.dummy_location, [ticketer; ty; contents; owner]) + +let make_uncarbonated ~ticketer ~ty ~contents ~owner = + hash_of_node_uncarbonated + @@ Micheline.Seq (Micheline.dummy_location, [ticketer; ty; contents; owner]) + +module Internal_for_tests = struct + let make_uncarbonated = make_uncarbonated +end diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.mli b/src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.mli new file mode 100644 index 000000000000..1ade9e0dda8d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_hash_builder.mli @@ -0,0 +1,47 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [make ctxt ~ticketer ~ty ~contents ~owner] creates a hashed + representation of the given [ticketer], [ty], [contents] and + [owner]. +*) +val make : + Raw_context.t -> + ticketer:Script_repr.node -> + ty:Script_repr.node -> + contents:Script_repr.node -> + owner:Script_repr.node -> + (Ticket_hash_repr.t * Raw_context.t) tzresult + +module Internal_for_tests : sig + (** As [make] but do not account for gas consumption *) + val make_uncarbonated : + ticketer:Script_repr.node -> + ty:Script_repr.node -> + contents:Script_repr.node -> + owner:Script_repr.node -> + Ticket_hash_repr.t tzresult +end diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.ml b/src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.ml new file mode 100644 index 000000000000..21c186911404 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.ml @@ -0,0 +1,38 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Script_expr_hash + +let of_script_expr_hash t = t + +let zero = zero + +include Compare.Make (struct + type nonrec t = t + + let compare = compare +end) + +module Index = Script_expr_hash diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.mli b/src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.mli new file mode 100644 index 000000000000..fa3b36f3029c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_hash_repr.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Ticket hashes are used to uniquely identify pairs made of + Michelson ticktes and their owner. + + They are used by the protocol to keep record of a tickets ledger, + that is how many tickets smart contracts own. More precisely, they + are used as keys for the {!Storage.Ticket_balance} table. *) + +(** A ticket hash is computed by the function [make] and is a + combination of a [ticketer], a [content type], a [content], and an + [owner]. + + {b Note:} This invariant can be invalidated if the [key_hash] is + created from the [encoding]. *) +type t + +val encoding : t Data_encoding.t + +val pp : Format.formatter -> t -> unit + +val to_b58check : t -> string + +val of_b58check_opt : string -> t option + +val of_b58check_exn : string -> t + +val of_bytes_exn : bytes -> t + +val of_bytes_opt : bytes -> t option + +include Compare.S with type t := t + +val zero : t + +val of_script_expr_hash : Script_expr_hash.t -> t + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.ml b/src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.ml new file mode 100644 index 000000000000..79cd92e929f7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.ml @@ -0,0 +1,309 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Failed_to_load_big_map_value_type of Big_map.Id.t + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"Failed_to_load_big_map_value_type" + ~title:"Failed to load big-map value type" + ~description: + "Failed to load big-map value type when computing ticket diffs." + ~pp:(fun ppf big_map_id -> + Format.fprintf + ppf + "Failed to load big-map value type for big-map-id: '%a'" + Z.pp_print + (Big_map.Id.unparse_to_z big_map_id)) + (obj1 (req "big_map_id" Big_map.Id.encoding)) + (function + | Failed_to_load_big_map_value_type big_map_id -> Some big_map_id + | _ -> None) + (fun big_map_id -> Failed_to_load_big_map_value_type big_map_id) + +(** Extracts the ticket-token and amount from an ex_ticket value. *) +let token_and_amount ctxt ex_ticket = + let open Result_syntax in + let+ ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + let token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ex_ticket + in + ((token, Script_int.(to_zint (amount :> n num))), ctxt) + +(** Extracts the ticket-token and amount from an ex_ticket value and returns + the opposite of the amount. This is used to account for removal of tickets inside + big maps when either a ticket is taken out of a big map or a whole big map is + dropped. *) +let neg_token_and_amount ctxt ex_ticket = + let open Result_syntax in + let* (token, amount), ctxt = token_and_amount ctxt ex_ticket in + let+ ctxt = Gas.consume ctxt (Ticket_costs.negate_cost amount) in + ((token, Z.neg amount), ctxt) + +let parse_value_type ctxt value_type = + Script_ir_translator.parse_big_map_value_ty + ctxt + ~legacy:true + (Micheline.root value_type) + +(** Collects all ticket-token balances contained in the given node and prepends + them to the accumulator [acc]. The given [get_token_and_amount] function + extracts the ticket-token and amount (either positive or negative) from an + [ex_ticket] value, depending on whether the diff stems from adding or + removing a value containing tickets. *) +let collect_token_diffs_of_node ctxt has_tickets node ~get_token_and_amount acc + = + let open Lwt_result_syntax in + let* ex_tickets, ctxt = + Ticket_scanner.tickets_of_node + ctxt + (* It's currently not possible to have nested lazy structures, but this is + for future proofing. *) + ~include_lazy:true + has_tickets + (Micheline.root node) + in + let*? result = + let open Result_syntax in + List.fold_left_e + (fun (acc, ctxt) ticket -> + let+ item, ctxt = get_token_and_amount ctxt ticket in + (item :: acc, ctxt)) + (acc, ctxt) + ex_tickets + in + return result + +(** A module for keeping track of script-key-hashes. It's used for looking up + keys for multiple big-map updates referencing the same key. + *) + +module Key_hash_map = + Carbonated_map.Make + (struct + type context = Alpha_context.context + + let consume = Alpha_context.Gas.consume + end) + (struct + type t = Script_expr_hash.t + + let compare = Script_expr_hash.compare + + let compare_cost _ = Ticket_costs.Constants.cost_compare_ticket_hash + end) + +(** Collects all ticket-token diffs from a big-map update and prepends them + to the accumulator [acc]. *) +let collect_token_diffs_of_big_map_update ctxt ~big_map_id has_tickets + {Lazy_storage_kind.Big_map.key = _; key_hash; value} already_updated acc = + let collect_token_diffs_of_node_option ctxt ~get_token_and_amount expr_opt acc + = + match expr_opt with + | Some expr -> + collect_token_diffs_of_node + ctxt + has_tickets + expr + ~get_token_and_amount + acc + | None -> return (acc, ctxt) + in + (* First check if the key-hash has already been updated, in that case pull the + value from the [already_updated] map. Note that this should not happen with + the current implementation of big-map overlays as it guarantees that keys + are unique. The extra check is used for future proofing. + *) + let open Lwt_result_syntax in + let* old_value, ctxt = + let*? val_opt, ctxt = Key_hash_map.find ctxt key_hash already_updated in + match val_opt with + | Some updated_value -> return (updated_value, ctxt) + | None -> + (* Load tickets from the old value that was removed. *) + let+ ctxt, old_value = Big_map.get_opt ctxt big_map_id key_hash in + (old_value, ctxt) + in + let* acc, ctxt = + collect_token_diffs_of_node_option + ctxt + ~get_token_and_amount:neg_token_and_amount + old_value + acc + in + let*? already_updated, ctxt = + Key_hash_map.update + ctxt + key_hash + (fun ctxt _ -> Ok (Some value, ctxt)) + already_updated + in + (* TODO: #2303 + Avoid re-parsing the value. + In order to find tickets from the new value, we need to parse it. It would + be more efficient if the value was already present. + *) + let+ tickets, ctxt = + collect_token_diffs_of_node_option + ctxt + ~get_token_and_amount:token_and_amount + value + acc + in + (tickets, already_updated, ctxt) + +(** Collects all ticket-token diffs from a list of big-map updates and prepends + them to the accumulator [acc]. *) +let collect_token_diffs_of_big_map_updates ctxt big_map_id ~value_type updates + acc = + (* TODO: #2303 + Avoid re-parsing the value type. + We should have the non-serialized version of the value type. + *) + let open Lwt_result_syntax in + let*? Script_typed_ir.Ex_ty value_type, ctxt = + parse_value_type ctxt value_type + in + let*? has_tickets, ctxt = Ticket_scanner.type_has_tickets ctxt value_type in + let+ acc, _already_updated, ctxt = + List.fold_left_es + (fun (acc, already_updated, ctxt) update -> + collect_token_diffs_of_big_map_update + ctxt + ~big_map_id + has_tickets + update + already_updated + acc) + (acc, Key_hash_map.empty, ctxt) + updates + in + (acc, ctxt) + +(** Given a big-map id, this function collects ticket-token diffs and prepends + them to the accumulator [acc]. *) +let collect_token_diffs_of_big_map ctxt ~get_token_and_amount big_map_id acc = + let open Lwt_result_syntax in + let*? ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + let* ctxt, key_val_tys = Big_map.exists ctxt big_map_id in + match key_val_tys with + | Some (_key_ty, value_ty) -> + (* TODO: #2303 + Avoid re-parsing the value type. + In order to find tickets from the value, we need to parse the value + type. It would be more efficient if the value preserved. + *) + let*? Script_typed_ir.Ex_ty value_type, ctxt = + parse_value_type ctxt value_ty + in + let*? has_tickets, ctxt = + Ticket_scanner.type_has_tickets ctxt value_type + in + (* Iterate over big-map items. *) + let* ctxt, exprs = Big_map.list_key_values ctxt big_map_id in + List.fold_left_es + (fun (acc, ctxt) (_key_hash, node) -> + collect_token_diffs_of_node + ctxt + has_tickets + node + ~get_token_and_amount + acc) + (acc, ctxt) + exprs + | None -> tzfail (Failed_to_load_big_map_value_type big_map_id) + +(** Collects ticket-token diffs from a big-map and a list of updates, and + prepends them to the given accumulator [acc]. *) +let collect_token_diffs_of_big_map_and_updates ctxt big_map_id updates acc = + let open Lwt_result_syntax in + let*? ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + let* ctxt, key_val_opt = Big_map.exists ctxt big_map_id in + match key_val_opt with + | Some (_val, value_type) -> + collect_token_diffs_of_big_map_updates + ctxt + big_map_id + ~value_type + updates + acc + | None -> tzfail (Failed_to_load_big_map_value_type big_map_id) + +(** Inspects the given [Lazy_storage.diffs_item] and prepends all ticket-token + diffs, resulting from the updates, to the given accumulator [acc]. *) +let collect_token_diffs_of_big_map_diff ctxt diff_item acc = + let open Lwt_result_syntax in + let*? ctxt = + Gas.consume ctxt Ticket_costs.Constants.cost_collect_tickets_step + in + match diff_item with + | Lazy_storage.Item (Lazy_storage_kind.Big_map, big_map_id, Remove) -> + (* Collect all removed tokens from the big-map. *) + collect_token_diffs_of_big_map + ctxt + ~get_token_and_amount:neg_token_and_amount + big_map_id + acc + | Item (Lazy_storage_kind.Big_map, big_map_id, Update {init; updates}) -> ( + match init with + | Lazy_storage.Existing -> + (* Collect token diffs from the updates to the big-map. *) + collect_token_diffs_of_big_map_and_updates ctxt big_map_id updates acc + | Copy {src} -> + (* Collect tokens diffs from the source of the copied big-map. *) + let* acc, ctxt = + collect_token_diffs_of_big_map + ctxt + ~get_token_and_amount:token_and_amount + src + acc + in + (* Collect token diffs from the updates to the copied big-map. *) + collect_token_diffs_of_big_map_and_updates ctxt src updates acc + | Alloc {key_type = _; value_type} -> + collect_token_diffs_of_big_map_updates + ctxt + big_map_id + ~value_type + updates + acc) + | Item (Sapling_state, _, _) -> return (acc, ctxt) + +let ticket_diffs_of_lazy_storage_diff ctxt diffs_items = + List.fold_left_es + (fun (acc, ctxt) diff_item -> + collect_token_diffs_of_big_map_diff ctxt diff_item acc) + ([], ctxt) + diffs_items diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.mli b/src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.mli new file mode 100644 index 000000000000..726b37539c5e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_lazy_storage_diff.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [ticket_diffs_of_lazy_storage_diff ctxt diffs] returns a list of ticket-token + balance differences, given a list, [diffs], of lazy storage diff items. + *) +val ticket_diffs_of_lazy_storage_diff : + Alpha_context.context -> + Alpha_context.Lazy_storage.diffs_item list -> + ((Ticket_token.ex_token * Z.t) list * Alpha_context.context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.ml b/src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.ml new file mode 100644 index 000000000000..6f5a1febd785 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.ml @@ -0,0 +1,304 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type ticket_transfer = { + destination : Destination.t; + tickets : Ticket_scanner.ex_ticket list; +} + +type ticket_token_diff = { + ticket_token : Ticket_token.ex_token; + total_amount : Script_int.n Script_int.num; + destinations : (Destination.t * Ticket_amount.t) list; +} + +type error += Failed_to_get_script of Contract.t | Contract_not_originated + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"Failed_to_get_script" + ~title:"Failed to get script for contract" + ~description: + "Failed to get script for contract when scanning operations for tickets" + ~pp:(fun ppf contract -> + Format.fprintf + ppf + "Failed to get script for contract %a" + Contract.pp + contract) + (obj1 (req "contract" Contract.encoding)) + (function Failed_to_get_script c -> Some c | _ -> None) + (fun c -> Failed_to_get_script c) ; + register_error_kind + `Permanent + ~id:"contract_not_originated" + ~title:"Contract not originated" + ~description:"Non originated contract detected in ticket update." + ~pp:(fun ppf () -> Format.fprintf ppf "Contract was not pre-originated") + unit + (function Contract_not_originated -> Some () | _ -> None) + (fun () -> Contract_not_originated) + +(** A carbonated map where the keys are destination (contract or tx_rollup). *) +module Destination_map = + Carbonated_map.Make + (struct + type context = Alpha_context.context + + let consume = Alpha_context.Gas.consume + end) + (struct + type t = Destination.t + + let compare = Destination.compare + + (* TODO: #2667 + Change cost-function to one for comparing destinations. + Not expected to have any performance impact but we should update for + completeness. + *) + let compare_cost _ = Ticket_costs.Constants.cost_compare_key_contract + end) + +(** A module for mapping ticket-tokens to a map of contract destinations and + amounts. The values specify how to distribute the spending of a ticket-token + across different contracts. + + In the example below, there is a total of 4 Token1 ticket-tokens + transferred: three units are sent to contract K1 and one unit to K2. + Additionally, there are 12 units of Token2 sent to K2, K7 and K8. And one + unit of Token3 sent to K1. + { + Token1 -> { K1 -> 3, K2 -> 1 } + Token2 -> { K2 -> 1, K7 -> 10, K8 -> 1} + Token3 -> { K1 -> 1 } + } +*) +module Ticket_token_map = struct + include Ticket_token_map + + (** Adds a ticket-token with a destination and an amount to the map. + The layout of the map parameter is as described above. Its type is: + + (n num Destination_map.t) Ticket_token_map.t + + As explained above, the inner map expresses a list of destination + contracts and outgoing amount pairs. + + Invariant: + - The internal contract-indexed map cannot be empty. + + *) + let add ctxt ~ticket_token ~destination ~(amount : Ticket_amount.t) map = + let open Result_syntax in + Ticket_token_map.update + ctxt + ticket_token + (fun ctxt old_val -> + match old_val with + | None -> + (* Create a new map with a single contract-and amount pair. *) + let map = Destination_map.singleton destination amount in + return (Some map, ctxt) + | Some destination_map -> + (* Update the inner contract map *) + let update ctxt prev_amt_opt = + match prev_amt_opt with + | Some (prev_amount : Ticket_amount.t) -> + let+ ctxt = + Gas.consume + ctxt + Script_int.( + Ticket_costs.add_int_cost + (prev_amount :> n num) + (amount :> n num)) + in + (Some (Ticket_amount.add prev_amount amount), ctxt) + | None -> return (Some amount, ctxt) + in + let+ destination_map, ctxt = + Destination_map.update ctxt destination update destination_map + in + (Some destination_map, ctxt)) + map +end + +let tickets_of_transaction ctxt ~destination ~parameters_ty ~parameters = + let open Lwt_result_syntax in + let*? has_tickets, ctxt = + Ticket_scanner.type_has_tickets ctxt parameters_ty + in + let* tickets, ctxt = + Ticket_scanner.tickets_of_value + ~include_lazy:true + ctxt + has_tickets + parameters + in + return (Some {destination; tickets}, ctxt) + +(** Extract tickets of an origination operation by scanning the storage. *) +let tickets_of_origination ctxt ~preorigination ~storage_type ~storage = + (* Extract any tickets from the storage. Note that if the type of the contract + storage does not contain tickets, storage is not scanned. *) + let open Lwt_result_syntax in + let*? has_tickets, ctxt = Ticket_scanner.type_has_tickets ctxt storage_type in + let+ tickets, ctxt = + Ticket_scanner.tickets_of_value ctxt ~include_lazy:true has_tickets storage + in + let destination = Destination.Contract (Originated preorigination) in + (Some {tickets; destination}, ctxt) + +let tickets_of_operation ctxt + (Script_typed_ir.Internal_operation {sender = _; operation; nonce = _}) = + match operation with + | Transaction_to_implicit _ -> return (None, ctxt) + | Transaction_to_implicit_with_ticket + { + destination; + ticket; + ticket_ty = Script_typed_ir.Ticket_t (ty, _); + unparsed_ticket = _; + amount = _; + } -> + return + ( Some + { + destination = Destination.Contract (Implicit destination); + tickets = [Ex_ticket (ty, ticket)]; + }, + ctxt ) + | Transaction_to_smart_contract + { + amount = _; + unparsed_parameters = _; + entrypoint = _; + destination; + location = _; + parameters_ty; + parameters; + } -> + tickets_of_transaction + ctxt + ~destination:(Destination.Contract (Originated destination)) + ~parameters_ty + ~parameters + | Transaction_to_sc_rollup + { + destination; + entrypoint = _; + parameters_ty; + parameters; + unparsed_parameters = _; + } -> + (* Note that zero-amount tickets to a rollup is not permitted. *) + tickets_of_transaction + ctxt + ~destination:(Destination.Sc_rollup destination) + ~parameters_ty + ~parameters + | Transaction_to_zk_rollup + { + destination; + unparsed_parameters = _; + parameters_ty = Pair_t (Ticket_t (ty, _), Bytes_t, _, _); + parameters = ticket, _op; + } -> + let ex_ticket = Ticket_scanner.Ex_ticket (ty, ticket) in + return + ( Some + { + destination = Destination.Zk_rollup destination; + tickets = [ex_ticket]; + }, + ctxt ) + | Origination + { + delegate = _; + code = _; + unparsed_storage = _; + credit = _; + preorigination; + storage_type; + storage; + } -> + tickets_of_origination ctxt ~preorigination ~storage_type ~storage + | Delegation _ | Event _ -> return (None, ctxt) + +let add_transfer_to_token_map ctxt token_map {destination; tickets} = + List.fold_left_es + (fun (token_map, ctxt) ticket -> + let ticket_token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in + Ticket_token_map.add ctxt ~ticket_token ~destination ~amount token_map) + (token_map, ctxt) + tickets + +let ticket_token_map_of_operations ctxt ops = + let open Lwt_result_syntax in + List.fold_left_es + (fun (token_map, ctxt) op -> + let* res, ctxt = tickets_of_operation ctxt op in + match res with + | Some ticket_trans -> + add_transfer_to_token_map ctxt token_map ticket_trans + | None -> return (token_map, ctxt)) + (Ticket_token_map.empty, ctxt) + ops + +(** Traverses a list of operations and scans for tickets. *) +let ticket_diffs_of_operations ctxt operations = + let open Lwt_result_syntax in + let* token_map, ctxt = ticket_token_map_of_operations ctxt operations in + Ticket_token_map.fold_e + ctxt + (fun ctxt acc ticket_token destination_map -> + (* Calculate the total amount of outgoing units for the current + ticket-token. *) + let open Result_syntax in + let* total_amount, ctxt = + Destination_map.fold_e + ctxt + (fun ctxt total_amount _destination (amount : Ticket_amount.t) -> + let+ ctxt = + Gas.consume + ctxt + Script_int.( + Ticket_costs.add_int_cost total_amount (amount :> n num)) + in + (Script_int.(add_n total_amount (amount :> n num)), ctxt)) + Script_int.zero_n + destination_map + in + let+ destinations, ctxt = Destination_map.to_list ctxt destination_map in + ({ticket_token; total_amount; destinations} :: acc, ctxt)) + [] + token_map + |> Lwt.return diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.mli b/src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.mli new file mode 100644 index 000000000000..f7ea7fd7d6f4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_operations_diff.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A module that provides functionality for extracting ticket-token differences + from a list of operations. *) + +(** A type representing ticket-token balance differences. Each value consists + of: + - [ticket_token] - the type of the ticket. + - [total_amount] - the total amount of transferred ticket-tokens. + - [destinations] - a list of amount and contract pairs. + Invariant: [total_amount] is the sum of the amounts in [destinations]. *) +type ticket_token_diff = private { + ticket_token : Ticket_token.ex_token; + total_amount : Script_int.n Script_int.num; + destinations : + (Alpha_context.Destination.t * Script_typed_ir.ticket_amount) list; +} + +(** [ticket_diffs_of_operations ctxt ops] returns a + list of ticket-tokens diffs given a context, [ctxt], and list of packed + operations, [ops]. The diffs result from either a [Transaction] operation + with parameters containing tickets, or an [Origination] operation with the + initial storage containing tickets. + *) +val ticket_diffs_of_operations : + Alpha_context.context -> + Script_typed_ir.packed_internal_operation list -> + (ticket_token_diff list * Alpha_context.context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_receipt.ml b/src/proto_020_PsParisC/lib_protocol/ticket_receipt.ml new file mode 100644 index 000000000000..8f16bf97db82 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_receipt.ml @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type update = {account : Destination.t; amount : Z.t} + +type item = {ticket_token : Ticket_token.unparsed_token; updates : update list} + +type t = item list + +let update_encoding = + let open Data_encoding in + conv + (fun {account; amount} -> (account, amount)) + (fun (account, amount) -> {account; amount}) + (obj2 (req "account" Destination.encoding) (req "amount" z)) + +let item_encoding = + let open Data_encoding in + conv + (fun {ticket_token; updates} -> (ticket_token, updates)) + (fun (ticket_token, updates) -> {ticket_token; updates}) + (obj2 + (req "ticket_token" Ticket_token.unparsed_token_encoding) + (req "updates" (list update_encoding))) + +let encoding = Data_encoding.list item_encoding diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_receipt.mli b/src/proto_020_PsParisC/lib_protocol/ticket_receipt.mli new file mode 100644 index 000000000000..d1397553d26a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_receipt.mli @@ -0,0 +1,42 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** A module for representing the increase/decrease of tickets in the storage. + It will be used to display ticket update information in the operation receipt. *) + +(** Represents that [account]'s storage has delta [amount] for a given ticket *) +type update = {account : Destination.t; amount : Z.t} + +(** List of updates for a [ticket] *) +type item = {ticket_token : Ticket_token.unparsed_token; updates : update list} + +(** A list of ticket tokens and their corresponding updates *) +type t = item list + +val item_encoding : item Data_encoding.t + +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_scanner.ml b/src/proto_020_PsParisC/lib_protocol/ticket_scanner.ml new file mode 100644 index 000000000000..b153202dd92d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_scanner.ml @@ -0,0 +1,575 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* Copyright (c) 2021-2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += + | (* Permanent *) Unsupported_non_empty_overlay + | (* Permanent *) Unsupported_type_operation + +let () = + register_error_kind + `Branch + ~id:"Unsupported_non_empty_overlay" + ~title:"Unsupported non empty overlay" + ~description:"Unsupported big-map value with non-empty overlay" + ~pp:(fun ppf () -> + Format.fprintf ppf "Unsupported big-map value with non-empty overlay") + Data_encoding.empty + (function Unsupported_non_empty_overlay -> Some () | _ -> None) + (fun () -> Unsupported_non_empty_overlay) ; + register_error_kind + `Branch + ~id:"Unsupported_type_operation" + ~title:"Unsupported type operation" + ~description:"Types embedding operations are not supported" + ~pp:(fun ppf () -> + Format.fprintf ppf "Types embedding operations are not supported") + Data_encoding.empty + (function Unsupported_type_operation -> Some () | _ -> None) + (fun () -> Unsupported_type_operation) + +type ex_ticket = + | Ex_ticket : + 'a Script_typed_ir.comparable_ty * 'a Script_typed_ir.ticket + -> ex_ticket + +module Ticket_inspection = struct + (* TODO: 1951 + Replace with use of meta-data for ['a ty] type. + Once ['a ty] values can be extended with custom meta data, this type + can be removed. + *) + (** + Witness flag for whether a type can be populated by a value containing a + ticket. [False_ht] must be used only when a value of the type cannot + contain a ticket. + + This flag is necessary for avoiding ticket collection (see below) to have + quadratic complexity in the order of: size-of-the-type * size-of-value. + + This type is local to the [Ticket_scanner] module and should not be + exported. + + *) + type 'a has_tickets = + | True_ht : _ Script_typed_ir.ticket has_tickets + | False_ht : _ has_tickets + | Pair_ht : + 'a has_tickets * 'b has_tickets + -> ('a, 'b) Script_typed_ir.pair has_tickets + | Or_ht : + 'a has_tickets * 'b has_tickets + -> ('a, 'b) Script_typed_ir.or_ has_tickets + | Option_ht : 'a has_tickets -> 'a option has_tickets + | List_ht : 'a has_tickets -> 'a Script_list.t has_tickets + | Set_ht : 'k has_tickets -> 'k Script_typed_ir.set has_tickets + | Map_ht : + 'k has_tickets * 'v has_tickets + -> ('k, 'v) Script_typed_ir.map has_tickets + | Big_map_ht : + 'k has_tickets * 'v has_tickets + -> ('k, 'v) Script_typed_ir.big_map has_tickets + + (* Returns whether or not a comparable type embeds tickets. Currently + this function returns [false] for all input. + + The only reason we keep this code is so that in the future, if tickets were + ever to be comparable, the compiler would detect a missing pattern match + case. + + Note that in case tickets are made comparable, this function needs to change + so that constructors like [Or_t] and [Pair_t] are traversed + recursively. + *) + let has_tickets_of_comparable : + type a ret. + a Script_typed_ir.comparable_ty -> (a has_tickets -> ret) -> ret = + fun key_ty k -> + let open Script_typed_ir in + match key_ty with + | Unit_t -> (k [@ocaml.tailcall]) False_ht + | Never_t -> (k [@ocaml.tailcall]) False_ht + | Int_t -> (k [@ocaml.tailcall]) False_ht + | Nat_t -> (k [@ocaml.tailcall]) False_ht + | Signature_t -> (k [@ocaml.tailcall]) False_ht + | String_t -> (k [@ocaml.tailcall]) False_ht + | Bytes_t -> (k [@ocaml.tailcall]) False_ht + | Mutez_t -> (k [@ocaml.tailcall]) False_ht + | Bool_t -> (k [@ocaml.tailcall]) False_ht + | Key_hash_t -> (k [@ocaml.tailcall]) False_ht + | Key_t -> (k [@ocaml.tailcall]) False_ht + | Timestamp_t -> (k [@ocaml.tailcall]) False_ht + | Chain_id_t -> (k [@ocaml.tailcall]) False_ht + | Address_t -> (k [@ocaml.tailcall]) False_ht + | Pair_t (_, _, _, YesYes) -> (k [@ocaml.tailcall]) False_ht + | Or_t (_, _, _, YesYes) -> (k [@ocaml.tailcall]) False_ht + | Option_t (_, _, Yes) -> (k [@ocaml.tailcall]) False_ht + + (* Short circuit pairing of two [has_tickets] values. + If neither left nor right branch contains a ticket, [False_ht] is + returned. *) + let pair_has_tickets pair ht1 ht2 = + match (ht1, ht2) with False_ht, False_ht -> False_ht | _ -> pair ht1 ht2 + + let map_has_tickets map ht = + match ht with False_ht -> False_ht | _ -> map ht + + type ('a, 'r) continuation = 'a has_tickets -> 'r tzresult + + (* Creates a [has_tickets] type-witness value from the given ['a ty]. + The returned value matches the given shape of the [ty] value, except + it collapses whole branches where no types embed tickets to [False_ht]. + *) + let rec has_tickets_of_ty : + type a ac ret. + (a, ac) Script_typed_ir.ty -> (a, ret) continuation -> ret tzresult = + fun ty k -> + let open Script_typed_ir in + match ty with + | Ticket_t _ -> (k [@ocaml.tailcall]) True_ht + | Unit_t -> (k [@ocaml.tailcall]) False_ht + | Int_t -> (k [@ocaml.tailcall]) False_ht + | Nat_t -> (k [@ocaml.tailcall]) False_ht + | Signature_t -> (k [@ocaml.tailcall]) False_ht + | String_t -> (k [@ocaml.tailcall]) False_ht + | Bytes_t -> (k [@ocaml.tailcall]) False_ht + | Mutez_t -> (k [@ocaml.tailcall]) False_ht + | Key_hash_t -> (k [@ocaml.tailcall]) False_ht + | Key_t -> (k [@ocaml.tailcall]) False_ht + | Timestamp_t -> (k [@ocaml.tailcall]) False_ht + | Address_t -> (k [@ocaml.tailcall]) False_ht + | Bool_t -> (k [@ocaml.tailcall]) False_ht + | Pair_t (ty1, ty2, _, _) -> + (has_tickets_of_pair [@ocaml.tailcall]) + ty1 + ty2 + ~pair:(fun ht1 ht2 -> Pair_ht (ht1, ht2)) + k + | Or_t (ty1, ty2, _, _) -> + (has_tickets_of_pair [@ocaml.tailcall]) + ty1 + ty2 + ~pair:(fun ht1 ht2 -> Or_ht (ht1, ht2)) + k + | Lambda_t (_, _, _) -> + (* As of H, closures cannot contain tickets because APPLY requires + a packable type and tickets are not packable. *) + (k [@ocaml.tailcall]) False_ht + | Option_t (ty, _, _) -> + (has_tickets_of_ty [@ocaml.tailcall]) ty (fun ht -> + let opt_hty = map_has_tickets (fun ht -> Option_ht ht) ht in + (k [@ocaml.tailcall]) opt_hty) + | List_t (ty, _) -> + (has_tickets_of_ty [@ocaml.tailcall]) ty (fun ht -> + let list_hty = map_has_tickets (fun ht -> List_ht ht) ht in + (k [@ocaml.tailcall]) list_hty) + | Set_t (key_ty, _) -> + (has_tickets_of_comparable [@ocaml.tailcall]) key_ty (fun ht -> + let set_hty = map_has_tickets (fun ht -> Set_ht ht) ht in + (k [@ocaml.tailcall]) set_hty) + | Map_t (key_ty, val_ty, _) -> + (has_tickets_of_key_and_value [@ocaml.tailcall]) + key_ty + val_ty + ~pair:(fun ht1 ht2 -> Map_ht (ht1, ht2)) + k + | Big_map_t (key_ty, val_ty, _) -> + (has_tickets_of_key_and_value [@ocaml.tailcall]) + key_ty + val_ty + ~pair:(fun ht1 ht2 -> Big_map_ht (ht1, ht2)) + k + | Contract_t _ -> (k [@ocaml.tailcall]) False_ht + | Sapling_transaction_t _ -> (k [@ocaml.tailcall]) False_ht + | Sapling_transaction_deprecated_t _ -> (k [@ocaml.tailcall]) False_ht + | Sapling_state_t _ -> (k [@ocaml.tailcall]) False_ht + | Operation_t -> + (* Operations may contain tickets but they should never be passed + why we fail in this case. *) + Result_syntax.tzfail Unsupported_type_operation + | Chain_id_t -> (k [@ocaml.tailcall]) False_ht + | Never_t -> (k [@ocaml.tailcall]) False_ht + | Bls12_381_g1_t -> (k [@ocaml.tailcall]) False_ht + | Bls12_381_g2_t -> (k [@ocaml.tailcall]) False_ht + | Bls12_381_fr_t -> (k [@ocaml.tailcall]) False_ht + | Chest_t -> (k [@ocaml.tailcall]) False_ht + | Chest_key_t -> (k [@ocaml.tailcall]) False_ht + + and has_tickets_of_pair : + type a ac b bc c ret. + (a, ac) Script_typed_ir.ty -> + (b, bc) Script_typed_ir.ty -> + pair:(a has_tickets -> b has_tickets -> c has_tickets) -> + (c, ret) continuation -> + ret tzresult = + fun ty1 ty2 ~pair k -> + (has_tickets_of_ty [@ocaml.tailcall]) ty1 (fun ht1 -> + (has_tickets_of_ty [@ocaml.tailcall]) ty2 (fun ht2 -> + (k [@ocaml.tailcall]) (pair_has_tickets pair ht1 ht2))) + + and has_tickets_of_key_and_value : + type k v vc t ret. + k Script_typed_ir.comparable_ty -> + (v, vc) Script_typed_ir.ty -> + pair:(k has_tickets -> v has_tickets -> t has_tickets) -> + (t, ret) continuation -> + ret tzresult = + fun key_ty val_ty ~pair k -> + (has_tickets_of_comparable [@ocaml.tailcall]) key_ty (fun ht1 -> + (has_tickets_of_ty [@ocaml.tailcall]) val_ty (fun ht2 -> + (k [@ocaml.tailcall]) (pair_has_tickets pair ht1 ht2))) + + let has_tickets_of_ty ctxt ty = + let open Result_syntax in + let* ctxt = Gas.consume ctxt (Ticket_costs.has_tickets_of_ty_cost ty) in + let+ ht = has_tickets_of_ty ty return in + (ht, ctxt) +end + +module Ticket_collection = struct + type accumulator = ex_ticket list + + type 'a continuation = context -> accumulator -> 'a tzresult Lwt.t + + (* Currently this always returns the original list. + + If comparables are ever extended to support tickets, this function + needs to be modified. In particular constructors like [Option] and [Pair] + would have to recurse on their arguments. *) + + let tickets_of_comparable : + type a ret. + context -> + a Script_typed_ir.comparable_ty -> + accumulator -> + ret continuation -> + ret tzresult Lwt.t = + fun ctxt comp_ty acc k -> + let open Script_typed_ir in + match comp_ty with + | Unit_t -> (k [@ocaml.tailcall]) ctxt acc + | Never_t -> (k [@ocaml.tailcall]) ctxt acc + | Int_t -> (k [@ocaml.tailcall]) ctxt acc + | Nat_t -> (k [@ocaml.tailcall]) ctxt acc + | Signature_t -> (k [@ocaml.tailcall]) ctxt acc + | String_t -> (k [@ocaml.tailcall]) ctxt acc + | Bytes_t -> (k [@ocaml.tailcall]) ctxt acc + | Mutez_t -> (k [@ocaml.tailcall]) ctxt acc + | Bool_t -> (k [@ocaml.tailcall]) ctxt acc + | Key_hash_t -> (k [@ocaml.tailcall]) ctxt acc + | Key_t -> (k [@ocaml.tailcall]) ctxt acc + | Timestamp_t -> (k [@ocaml.tailcall]) ctxt acc + | Chain_id_t -> (k [@ocaml.tailcall]) ctxt acc + | Address_t -> (k [@ocaml.tailcall]) ctxt acc + | Pair_t (_, _, _, YesYes) -> (k [@ocaml.tailcall]) ctxt acc + | Or_t (_, _, _, YesYes) -> (k [@ocaml.tailcall]) ctxt acc + | Option_t (_, _, Yes) -> (k [@ocaml.tailcall]) ctxt acc + + let tickets_of_set : + type a ret. + context -> + a Script_typed_ir.comparable_ty -> + a Script_typed_ir.set -> + accumulator -> + ret continuation -> + ret tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt key_ty _set acc k -> + let*? ctxt = Ticket_costs.consume_gas_steps ctxt ~num_steps:1 in + (* This is only invoked to support any future extensions making tickets + comparable. *) + (tickets_of_comparable [@ocaml.tailcall]) ctxt key_ty acc k + + let rec tickets_of_value : + type a ac ret. + include_lazy:bool -> + context -> + a Ticket_inspection.has_tickets -> + (a, ac) Script_typed_ir.ty -> + a -> + accumulator -> + ret continuation -> + ret tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~include_lazy ctxt hty ty x acc k -> + let open Script_typed_ir in + let*? ctxt = Ticket_costs.consume_gas_steps ctxt ~num_steps:1 in + match (hty, ty) with + | False_ht, _ -> (k [@ocaml.tailcall]) ctxt acc + | Pair_ht (hty1, hty2), Pair_t (ty1, ty2, _, _) -> + let l, r = x in + (tickets_of_value [@ocaml.tailcall]) + ~include_lazy + ctxt + hty1 + ty1 + l + acc + (fun ctxt acc -> + (tickets_of_value [@ocaml.tailcall]) + ~include_lazy + ctxt + hty2 + ty2 + r + acc + k) + | Or_ht (htyl, htyr), Or_t (tyl, tyr, _, _) -> ( + match x with + | L v -> + (tickets_of_value [@ocaml.tailcall]) + ~include_lazy + ctxt + htyl + tyl + v + acc + k + | R v -> + (tickets_of_value [@ocaml.tailcall]) + ~include_lazy + ctxt + htyr + tyr + v + acc + k) + | Option_ht el_hty, Option_t (el_ty, _, _) -> ( + match x with + | Some x -> + (tickets_of_value [@ocaml.tailcall]) + ~include_lazy + ctxt + el_hty + el_ty + x + acc + k + | None -> (k [@ocaml.tailcall]) ctxt acc) + | List_ht el_hty, List_t (el_ty, _) -> + let elements = Script_list.to_list x in + (tickets_of_list [@ocaml.tailcall]) + ctxt + ~include_lazy + el_hty + el_ty + elements + acc + k + | Set_ht _, Set_t (key_ty, _) -> + (tickets_of_set [@ocaml.tailcall]) ctxt key_ty x acc k + | Map_ht (_, val_hty), Map_t (key_ty, val_ty, _) -> + (tickets_of_comparable [@ocaml.tailcall]) + ctxt + key_ty + acc + (fun ctxt acc -> + (tickets_of_map [@ocaml.tailcall]) + ctxt + ~include_lazy + val_hty + val_ty + x + acc + k) + | Big_map_ht (_, val_hty), Big_map_t (key_ty, _, _) -> + if include_lazy then + (tickets_of_big_map [@ocaml.tailcall]) ctxt val_hty key_ty x acc k + else (k [@ocaml.tailcall]) ctxt acc + | True_ht, Ticket_t (comp_ty, _) -> + (k [@ocaml.tailcall]) ctxt (Ex_ticket (comp_ty, x) :: acc) + + and tickets_of_list : + type a ac ret. + context -> + include_lazy:bool -> + a Ticket_inspection.has_tickets -> + (a, ac) Script_typed_ir.ty -> + a list -> + accumulator -> + ret continuation -> + ret tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt ~include_lazy el_hty el_ty elements acc k -> + let*? ctxt = Ticket_costs.consume_gas_steps ctxt ~num_steps:1 in + match elements with + | elem :: elems -> + (tickets_of_value [@ocaml.tailcall]) + ~include_lazy + ctxt + el_hty + el_ty + elem + acc + (fun ctxt acc -> + (tickets_of_list [@ocaml.tailcall]) + ~include_lazy + ctxt + el_hty + el_ty + elems + acc + k) + | [] -> (k [@ocaml.tailcall]) ctxt acc + + and tickets_of_map : + type k v vc ret. + include_lazy:bool -> + context -> + v Ticket_inspection.has_tickets -> + (v, vc) Script_typed_ir.ty -> + (k, v) Script_typed_ir.map -> + accumulator -> + ret continuation -> + ret tzresult Lwt.t = + let open Lwt_result_syntax in + fun ~include_lazy ctxt val_hty val_ty map acc k -> + let (module M) = Script_map.get_module map in + let*? ctxt = Ticket_costs.consume_gas_steps ctxt ~num_steps:1 in + (* Pay gas for folding over the values *) + let*? ctxt = Ticket_costs.consume_gas_steps ctxt ~num_steps:M.size in + let values = M.OPS.fold (fun _ v vs -> v :: vs) M.boxed [] in + (tickets_of_list [@ocaml.tailcall]) + ~include_lazy + ctxt + val_hty + val_ty + values + acc + k + + and tickets_of_big_map : + type k v ret. + context -> + v Ticket_inspection.has_tickets -> + k Script_typed_ir.comparable_ty -> + (k, v) Script_typed_ir.big_map -> + accumulator -> + ret continuation -> + ret tzresult Lwt.t = + let open Lwt_result_syntax in + fun ctxt + val_hty + key_ty + (Big_map {id; diff = {map = _; size}; key_type = _; value_type}) + acc + k -> + let*? ctxt = Ticket_costs.consume_gas_steps ctxt ~num_steps:1 in + (* Require empty overlay *) + if Compare.Int.(size > 0) then tzfail Unsupported_non_empty_overlay + else + (* Traverse the keys for tickets, although currently keys should never + contain any tickets. *) + (tickets_of_comparable [@ocaml.tailcall]) + ctxt + key_ty + acc + (fun ctxt acc -> + (* Accumulate tickets from values of the big-map stored in the context *) + match id with + | Some id -> + let accum (values, ctxt) (_key_hash, exp) = + let+ v, ctxt = + Script_ir_translator.parse_data + ~elab_conf: + Script_ir_translator_config.(make ~legacy:true ()) + ctxt + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + value_type + (Micheline.root exp) + in + (v :: values, ctxt) + in + let* ctxt, exps = Big_map.list_key_values ctxt id in + let* values, ctxt = List.fold_left_es accum ([], ctxt) exps in + (tickets_of_list [@ocaml.tailcall]) + ~include_lazy:true + ctxt + val_hty + value_type + values + acc + k + | None -> (k [@ocaml.tailcall]) ctxt acc) + + let tickets_of_value ctxt ~include_lazy ht ty x = + tickets_of_value ctxt ~include_lazy ht ty x [] (fun ctxt ex_tickets -> + return (ex_tickets, ctxt)) +end + +type 'a has_tickets = + | Has_tickets : + 'a Ticket_inspection.has_tickets * ('a, _) Script_typed_ir.ty + -> 'a has_tickets + +let type_has_tickets ctxt ty = + let open Result_syntax in + let+ has_tickets, ctxt = Ticket_inspection.has_tickets_of_ty ctxt ty in + (Has_tickets (has_tickets, ty), ctxt) + +let tickets_of_value ctxt ~include_lazy (Has_tickets (ht, ty)) = + Ticket_collection.tickets_of_value ctxt ~include_lazy ht ty + +let has_tickets (Has_tickets (ht, _)) = + match ht with Ticket_inspection.False_ht -> false | _ -> true + +let tickets_of_node ctxt ~include_lazy has_tickets expr = + let (Has_tickets (ht, ty)) = has_tickets in + let open Lwt_result_syntax in + match ht with + | Ticket_inspection.False_ht -> return ([], ctxt) + | _ -> + let* value, ctxt = + Script_ir_translator.parse_data + ctxt + ~elab_conf:Script_ir_translator_config.(make ~legacy:true ()) + ~allow_forged_tickets:true + ~allow_forged_lazy_storage_id:true + ty + expr + in + tickets_of_value ctxt ~include_lazy has_tickets value + +let ex_ticket_size ctxt (Ex_ticket (ty, ticket)) = + (* type *) + let open Lwt_result_syntax in + let*? ty = Script_typed_ir.ticket_t Micheline.dummy_location ty in + let*? ty', ctxt = Script_ir_unparser.unparse_ty ~loc:() ctxt ty in + let ty_nodes, ty_size = Script_typed_ir_size.node_size ty' in + let ty_size_cost = Script_typed_ir_size_costs.nodes_cost ~nodes:ty_nodes in + let*? ctxt = Gas.consume ctxt ty_size_cost in + (* contents *) + let val_nodes, val_size = Script_typed_ir_size.value_size ty ticket in + let val_size_cost = Script_typed_ir_size_costs.nodes_cost ~nodes:val_nodes in + let*? ctxt = Gas.consume ctxt val_size_cost in + (* gas *) + return (Saturation_repr.add ty_size val_size, ctxt) + +let ex_token_and_amount_of_ex_ticket + (Ex_ticket (contents_type, {Script_typed_ir.ticketer; contents; amount})) = + (Ticket_token.Ex_token {ticketer; contents_type; contents}, amount) diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_scanner.mli b/src/proto_020_PsParisC/lib_protocol/ticket_scanner.mli new file mode 100644 index 000000000000..49d3a11b7eeb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_scanner.mli @@ -0,0 +1,104 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides an API for extracting tickets of arbitrary types + from an OCaml values, given a type-witness. *) + +open Alpha_context + +(** A type for representing existentially quantified tickets (tickets with + different types of payloads). An [ex_ticket] value consists of: + - A type-witness representing the type of the content of the ticket. + - A ticket value of the particular content type. + *) +type ex_ticket = + | Ex_ticket : + 'a Script_typed_ir.comparable_ty * 'a Script_typed_ir.ticket + -> ex_ticket + +(** A type-witness that contains information about which branches of a type ['a] + include tickets. This value is used for traversing only the relevant + branches of values when scanning for tickets. *) +type 'a has_tickets + +(** [type_has_tickets ctxt ty] returns a [has_tickets] witness of the given + shape [ty]. + *) +val type_has_tickets : + context -> ('a, _) Script_typed_ir.ty -> ('a has_tickets * context) tzresult + +(** [tickets_of_value ctxt ~include_lazy ht value] extracts all tickets from + the given [value], using the type-witness [ht]. The [include_lazy] flag + determines whether or not to traverse lazy structures (values from the context). + In case the [include_lazy] flag is [true], any big-map contained in the value + must have an empty overlay or else an error of type + [Unsupported_non_empty_overlay] is returned. The reason for this restriction + is that we assume that all lazy big-map diffs should be applied before + calling this function. Dealing with non-empty overlays would be possible + in theory, but practically difficult. The challenge is to distinguish + between overlapping keys between the context and the overlay. + *) +val tickets_of_value : + context -> + include_lazy:bool -> + 'a has_tickets -> + 'a -> + (ex_ticket list * context) tzresult Lwt.t + +(** [tickets_of_node ctxt ~include_lazy ht node] extracts all tickets from + the given [node], using the type-witness [ht].If [ht] indicates that + values of the corresponding type may not contain tickets, the node value is + not parsed. The [include_lazy] flag determines whether or not to traverse + lazy structures (values from the context). In case the [include_lazy] flag + is [true], any big-map contained in the value must have an empty overlay or + else an error of type [Unsupported_non_empty_overlay] is returned. The + reason for this restriction is that we assume that all lazy big-map diffs + should be applied before calling this function. Dealing with non-empty + overlays would be possible in theory, but practically difficult. The + challenge is to distinguish between overlapping keys between the context and + the overlay. + *) +val tickets_of_node : + context -> + include_lazy:bool -> + 'a has_tickets -> + Script.node -> + (ex_ticket list * context) tzresult Lwt.t + +(** [has_tickets ht] returns whether or not the type of the given [has_tickets] + witness [ht] has tickets. *) +val has_tickets : 'a has_tickets -> bool + +(** [ex_ticket_size ctxt ex_ticket] returns the size of the in-memory representation of + [ex_ticket] in bytes. *) +val ex_ticket_size : + context -> + ex_ticket -> + (Saturation_repr.may_saturate Saturation_repr.t * context) tzresult Lwt.t + +(** [ex_token_and_amount_of_ex_ticket ex_ticket] returns the token and amount of + the given ticket [ex_ticket]. *) +val ex_token_and_amount_of_ex_ticket : + ex_ticket -> Ticket_token.ex_token * Script_typed_ir.ticket_amount diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_storage.ml b/src/proto_020_PsParisC/lib_protocol/ticket_storage.ml new file mode 100644 index 000000000000..4a8bbeb2e09a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_storage.ml @@ -0,0 +1,133 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Negative_ticket_balance of {key : Ticket_hash_repr.t; balance : Z.t} + | Used_storage_space_underflow + +let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"Negative_ticket_balance" + ~title:"Negative ticket balance" + ~description:"Attempted to set a negative ticket balance value" + ~pp:(fun ppf (key, balance) -> + Format.fprintf + ppf + "Attempted to set negative ticket balance value '%a' for key %a." + Z.pp_print + balance + Ticket_hash_repr.pp + key) + (obj2 (req "key" Ticket_hash_repr.encoding) (req "balance" Data_encoding.z)) + (function + | Negative_ticket_balance {key; balance} -> Some (key, balance) + | _ -> None) + (fun (key, balance) -> Negative_ticket_balance {key; balance}) ; + register_error_kind + `Permanent + ~id:"Used_storage_underflow" + ~title:"Ticket balance used storage underflow" + ~description: + "Attempt to free more bytes than allocated for the tickets balance" + empty + (function Used_storage_space_underflow -> Some () | _ -> None) + (fun () -> Used_storage_space_underflow) + +let get_balance ctxt key = + let open Lwt_result_syntax in + let+ ctxt, res = Storage.Ticket_balance.Table.find ctxt key in + (res, ctxt) + +let set_balance ctxt key balance = + let cost_of_key = Z.of_int 65 in + let open Lwt_result_syntax in + let* () = + fail_when + Compare.Z.(balance < Z.zero) + (Negative_ticket_balance {key; balance}) + in + if Compare.Z.(balance = Z.zero) then + let+ ctxt, freed, existed = Storage.Ticket_balance.Table.remove ctxt key in + (* If we remove an existing entry, then we return the freed size for + both the key and the value. *) + let freed = + if existed then Z.neg @@ Z.add cost_of_key (Z.of_int freed) else Z.zero + in + (freed, ctxt) + else + let+ ctxt, size_diff, existed = + Storage.Ticket_balance.Table.add ctxt key balance + in + let size_diff = + let z_diff = Z.of_int size_diff in + (* For a new entry we also charge the space for storing the key *) + if existed then z_diff else Z.add cost_of_key z_diff + in + (size_diff, ctxt) + +let adjust_balance ctxt key ~delta = + let open Lwt_result_syntax in + let* res, ctxt = get_balance ctxt key in + let old_balance = Option.value ~default:Z.zero res in + set_balance ctxt key (Z.add old_balance delta) + +let adjust_storage_space ctxt ~storage_diff = + let open Lwt_result_syntax in + if Compare.Z.(storage_diff = Z.zero) then return (Z.zero, ctxt) + else + let* used_storage = Storage.Ticket_balance.Used_storage_space.find ctxt in + let used_storage = Option.value ~default:Z.zero used_storage in + let* paid_storage = Storage.Ticket_balance.Paid_storage_space.find ctxt in + let paid_storage = Option.value ~default:Z.zero paid_storage in + let new_used_storage = Z.add used_storage storage_diff in + let*? () = + error_when + Compare.Z.(new_used_storage < Z.zero) + Used_storage_space_underflow + in + let*! ctxt = + Storage.Ticket_balance.Used_storage_space.add ctxt new_used_storage + in + let diff = Z.sub new_used_storage paid_storage in + if Compare.Z.(Z.zero < diff) then + let*! ctxt = + Storage.Ticket_balance.Paid_storage_space.add ctxt new_used_storage + in + return (diff, ctxt) + else return (Z.zero, ctxt) + +module Internal_for_tests = struct + let used_storage_space c = + let open Lwt_result_syntax in + let+ value = Storage.Ticket_balance.Used_storage_space.find c in + Option.value ~default:Z.zero value + + let paid_storage_space c = + let open Lwt_result_syntax in + let+ value = Storage.Ticket_balance.Paid_storage_space.find c in + Option.value ~default:Z.zero value +end diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_storage.mli b/src/proto_020_PsParisC/lib_protocol/ticket_storage.mli new file mode 100644 index 000000000000..3aa3cc35a00f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_storage.mli @@ -0,0 +1,75 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Negative_ticket_balance of {key : Ticket_hash_repr.t; balance : Z.t} + | Used_storage_space_underflow + +(** [get_balance ctxt key] receives the ticket balance for the given + [key] in the context [ctxt]. The [key] represents a ticket content and a + ticket creator pair. In case there exists no value for the given [key], + [None] is returned. + *) +val get_balance : + Raw_context.t -> + Ticket_hash_repr.t -> + (Z.t option * Raw_context.t) tzresult Lwt.t + +(** [adjust_balance ctxt key ~delta] adjusts the balance of the + given key (representing a ticket content, creator and owner pair) + and [delta]. The value of [delta] can be positive as well as negative. + If there is no pre-exising balance for the given ticket type and owner, + it is assumed to be 0 and the new balance is [delta]. The function also + returns the difference between the old and the new size of the storage. + Note that the difference may be negative. For example, because when + setting the balance to zero, an entry is removed. + + The function fails with a [Negative_ticket_balance] error + in case the resulting balance is negative. + *) +val adjust_balance : + Raw_context.t -> + Ticket_hash_repr.t -> + delta:Z.t -> + (Z.t * Raw_context.t) tzresult Lwt.t + +(** [adjust_storage_space ctxt ~storage_diff] updates the used storage space + for the ticket-table according to [storage_diff]. The additional positive + amount of unpaid storage is returned. If no unpaid storage is consumed, + this amount is 0. + + Note that when storage space for the ticket table is released we may later + use that space for free. For this reason, the amount returned may be less + than the given (positive) [storage_diff]. *) +val adjust_storage_space : + Raw_context.t -> storage_diff:Z.t -> (Z.t * Raw_context.t) tzresult Lwt.t + +module Internal_for_tests : sig + (** [used_storage_space ctxt] returns the used ticket storage space. *) + val used_storage_space : Raw_context.t -> (Z.t, error trace) result Lwt.t + + (** [paid_storage_space ctxt] returns the paid ticket storage space. *) + val paid_storage_space : Raw_context.t -> (Z.t, error trace) result Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_token.ml b/src/proto_020_PsParisC/lib_protocol/ticket_token.ml new file mode 100644 index 000000000000..ebf39367f0fe --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_token.ml @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type 'a parsed_token = { + ticketer : Contract.t; + contents_type : 'a Script_typed_ir.comparable_ty; + contents : 'a; +} + +type ex_token = Ex_token : 'a parsed_token -> ex_token + +type unparsed_token = { + ticketer : Contract.t; + contents_type : Script.expr; + contents : Script.expr; +} + +let unparsed_token_encoding = + let open Data_encoding in + conv + (fun {ticketer; contents_type; contents} -> + (ticketer, contents_type, contents)) + (fun (ticketer, contents_type, contents) -> + {ticketer; contents_type; contents}) + (obj3 + (req "ticketer" Contract.encoding) + (req "content_type" Script.expr_encoding) + (req "content" Script.expr_encoding)) diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_token.mli b/src/proto_020_PsParisC/lib_protocol/ticket_token.mli new file mode 100644 index 000000000000..b79865fadbf0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_token.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** A module for handling ticket-tokens. A ticket-token represents the + combination of a ticketer (creator of a ticket) and the content. That is, + a ticket comprises a ticket-token and an amount. + *) + +type 'a parsed_token = { + ticketer : Contract.t; + contents_type : 'a Script_typed_ir.comparable_ty; + contents : 'a; +} + +(** A type for representing existentially quantified ticket-tokens. A + ticket-token consists of a pair of ticketer and contents. *) +type ex_token = Ex_token : 'a parsed_token -> ex_token + +(** Unparsed version of [parsed_token]. + Used to encode/decode ticket-token in receipt, RPC, etc. *) +type unparsed_token = { + ticketer : Contract.t; + contents_type : Script.expr; + contents : Script.expr; +} + +val unparsed_token_encoding : unparsed_token Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_token_map.ml b/src/proto_020_PsParisC/lib_protocol/ticket_token_map.ml new file mode 100644 index 000000000000..5a34d9795341 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_token_map.ml @@ -0,0 +1,151 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** A carbonated map where the keys are [Ticket_hash.t] values. *) +module Ticket_token_map = + Carbonated_map.Make + (struct + type context = Alpha_context.context + + let consume = Gas.consume + end) + (struct + type t = Ticket_hash.t + + let compare = Ticket_hash.compare + + let compare_cost _ = Ticket_costs.Constants.cost_compare_ticket_hash + end) + +(** Conceptually a map from [Ticket_token.ex_token] to values. Since + ticket-tokens are expensive to compare we use [Ticket_hash.t] keys instead, + and store the ticket-token along with the value. *) +type 'a t = (Ticket_token.ex_token * 'a) Ticket_token_map.t + +let empty = Ticket_token_map.empty + +let key_of_ticket_token ctxt (Ticket_token.Ex_token {ticketer; _} as token) = + (* We use the [ticket_balance_key] function for generating a key-hash + for comparing tokens. Since an owner contract is required we use [ticketer] + but any dummy value would work as long as it's consistent. + *) + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Destination.Contract ticketer) + token + +let update_context f key ctxt val_opt = + let open Result_syntax in + let+ val_opt, ctxt = + match val_opt with + | Some (_tkn, value) -> f ctxt (Some value) + | None -> f ctxt None + in + (Option.map (fun v -> (key, v)) val_opt, ctxt) + +let update ctxt key f m = + let open Lwt_result_syntax in + let* key_hash, ctxt = key_of_ticket_token ctxt key in + Ticket_token_map.update ctxt key_hash (update_context f key) m |> Lwt.return + +let fold_e ctxt f = + Ticket_token_map.fold_e ctxt (fun ctxt acc _key_hash (tkn, value) -> + f ctxt acc tkn value) + +let fold_es ctxt f = + Ticket_token_map.fold_es ctxt (fun ctxt acc _key_hash (tkn, value) -> + f ctxt acc tkn value) + +let find ctxt ticket_token map = + let open Lwt_result_syntax in + let* key_hash, ctxt = key_of_ticket_token ctxt ticket_token in + let*? val_opt, ctxt = Ticket_token_map.find ctxt key_hash map in + return (Option.map snd val_opt, ctxt) + +let lift_merge_overlap merge_overlap ctxt (tkn1, v1) (_tkn2, v2) = + let open Result_syntax in + let+ v, ctxt = merge_overlap ctxt v1 v2 in + ((tkn1, v), ctxt) + +let of_list ctxt ~merge_overlap token_values = + let open Lwt_result_syntax in + List.fold_left_es + (fun (map, ctxt) (token, value) -> + let* key_hash, ctxt = key_of_ticket_token ctxt token in + Lwt.return + (Ticket_token_map.update + ctxt + key_hash + (fun ctxt old_val -> + match old_val with + | None -> Ok (Some (token, value), ctxt) + | Some old -> + let open Result_syntax in + let+ x, ctxt = + lift_merge_overlap merge_overlap ctxt old (token, value) + in + (Some x, ctxt)) + map)) + (Ticket_token_map.empty, ctxt) + token_values + +let map_e ctxt f = + let open Result_syntax in + Ticket_token_map.map_e ctxt (fun ctxt _key (tkn, value) -> + let+ new_value, ctxt = f ctxt tkn value in + ((tkn, new_value), ctxt)) + +let to_list ctxt map = + let open Result_syntax in + let* list, ctxt = Ticket_token_map.to_list ctxt map in + (* Consume gas for traversing the list again and remove the key-hash. *) + let+ ctxt = + Gas.consume + ctxt + (Carbonated_map_costs.fold_cost ~size:(Ticket_token_map.size map)) + in + (List.map snd list, ctxt) + +let merge ctxt ~merge_overlap = + Ticket_token_map.merge ctxt ~merge_overlap:(lift_merge_overlap merge_overlap) + +let to_ticket_receipt ctxt ~owner ticket_token_map = + let open Lwt_result_syntax in + Ticket_token_map.fold_es + ctxt + (fun ctxt acc _ticket_hash (ex_ticket, amount) -> + if Z.(equal amount zero) then return (acc, ctxt) + else + let* ticket_token, ctxt = + Ticket_token_unparser.unparse ctxt ex_ticket + in + let update = + Ticket_receipt.{ticket_token; updates = [{account = owner; amount}]} + in + return (update :: acc, ctxt)) + [] + ticket_token_map diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_token_map.mli b/src/proto_020_PsParisC/lib_protocol/ticket_token_map.mli new file mode 100644 index 000000000000..19fa9a260355 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_token_map.mli @@ -0,0 +1,123 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** A module exposing a carbonated map where keys are [Ticket_token.ex_token] + values. *) + +(** A map where keys are [Ticket_token.ex_token] values. *) +type 'a t + +(** [empty] is a map without any elements. *) +val empty : 'a t + +(** [update ctxt k f map] updates or adds the value of the key [k] using [f]. + The function accounts for the gas cost for finding the element. [f] must + account for its own gas costs. *) +val update : + context -> + Ticket_token.ex_token -> + (context -> 'a option -> ('a option * context) tzresult) -> + 'a t -> + ('a t * context) tzresult Lwt.t + +(** [fold_e ctxt f z m] folds over the map [m] using the initial value [z] and + the accumulator function [f]. [f] must account for its own gas costs. *) +val fold_e : + context -> + (context -> + 'state -> + Ticket_token.ex_token -> + 'a -> + ('state * context) tzresult) -> + 'state -> + 'a t -> + ('state * context) tzresult + +(** Lwt-aware variant of {!fold_e}. *) +val fold_es : + context -> + (context -> + 'state -> + Ticket_token.ex_token -> + 'a -> + ('state * context) tzresult Lwt.t) -> + 'state -> + 'a t -> + ('state * context) tzresult Lwt.t + +(** [find ctxt k m] looks up the value with key [k] in the given map [m] and + also accounts for the gas cost of finding the key. *) +val find : + context -> + Ticket_token.ex_token -> + 'a t -> + ('a option * context) tzresult Lwt.t + +(** [of_list ctxt ~merge_overlaps m] creates a map from a list of key-value + pairs. In case there are overlapping keys, their values are combined + using the [merge_overlap] function. The function accounts for gas for + traversing the elements. [merge_overlap] should account for its own gas + cost. *) +val of_list : + context -> + merge_overlap:(context -> 'a -> 'a -> ('a * context, error trace) result) -> + (Ticket_token.ex_token * 'a) list -> + ('a t * context) tzresult Lwt.t + +(** [to_list m] transforms a map [m] into a list. It also accounts for the gas + cost for traversing the elements. *) +val to_list : + context -> 'a t -> ((Ticket_token.ex_token * 'a) list * context) tzresult + +(** [map_e ctxt f m] maps over all key-value pairs in the map [m] using the + function [f]. It accounts for gas costs associated with traversing the + elements. [f] must account for its own gas cost. *) +val map_e : + context -> + (context -> Ticket_token.ex_token -> 'a -> ('b * context) tzresult) -> + 'a t -> + ('b t * context) tzresult + +(** [merge ctxt ~merge_overlap m1 m2] merges the maps [m1] and [m2]. In case + there are overlapping keys, their values are combined using the + [merge_overlap] function. Gas costs for traversing all elements from both + maps are accounted for. [merge_overlap] must account for its own gas + costs. *) +val merge : + context -> + merge_overlap:(context -> 'a -> 'a -> ('a * context) tzresult) -> + 'a t -> + 'a t -> + ('a t * context) tzresult + +(** [to_ticket_receipt ctxt ~owner t] converts a ticket token map into a ticket receipt. + It also accounts for the gas cost for traversing map and unparsing the elements. *) +val to_ticket_receipt : + context -> + owner:Destination.t -> + Z.t t -> + (Ticket_receipt.t * context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.ml b/src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.ml new file mode 100644 index 000000000000..0d0a5ab55f73 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.ml @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4167 + + Disclaimer: + A more natural place to place [unparse] would be in [Ticket_token] module. + But unfortunantly, we could not put it there due to circular dependency. + The root cause of this circular dependency is the dependency + from [Script_ir_translator] to [Apply_internal_result], but removing this + dependency would require a relatively large refactor. *) + +let unparse ctxt (Ticket_token.Ex_token {ticketer; contents_type; contents}) = + let open Lwt_result_syntax in + let open Script_ir_unparser in + let* contents, ctxt = + unparse_comparable_data ctxt Optimized_legacy contents_type contents + in + let*? ty_unstripped, ctxt = + unparse_ty ~loc:Micheline.dummy_location ctxt contents_type + in + let*? ctxt = Gas.consume ctxt (Script.strip_annotations_cost ty_unstripped) in + let ty = Script.strip_annotations ty_unstripped in + let*? ctxt = Gas.consume ctxt (Script.strip_locations_cost ty) in + let contents_type = Micheline.strip_locations ty in + let ticket_token = Ticket_token.{ticketer; contents_type; contents} in + return (ticket_token, ctxt) diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.mli b/src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.mli new file mode 100644 index 000000000000..92a27fb35162 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_token_unparser.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** [unparse ctxt ex_token] returns the unparsed version of [ex_token] where + each ticket field is converted to a Micheline representation. The gas is + being consumed from [ctxt]. *) +val unparse : + context -> + Ticket_token.ex_token -> + (Ticket_token.unparsed_token * context) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_transfer.ml b/src/proto_020_PsParisC/lib_protocol/ticket_transfer.ml new file mode 100644 index 000000000000..2c4ecd357846 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_transfer.ml @@ -0,0 +1,152 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Margiold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +let parse_ticket ~consume_deserialization_gas ~ticketer ~contents ~ty ctxt = + let open Lwt_result_syntax in + let*? ty, ctxt = + Script.force_decode_in_context ~consume_deserialization_gas ctxt ty + in + let*? contents, ctxt = + Script.force_decode_in_context ~consume_deserialization_gas ctxt contents + in + let*? Ex_comparable_ty contents_type, ctxt = + Script_ir_translator.parse_comparable_ty ctxt (Micheline.root ty) + in + let* contents, ctxt = + Script_ir_translator.parse_comparable_data + ctxt + contents_type + (Micheline.root contents) + in + let token = Ticket_token.Ex_token {ticketer; contents_type; contents} in + return (ctxt, token) + +let parse_ticket_and_operation ~consume_deserialization_gas ~ticketer ~contents + ~ty ~sender ~destination ~entrypoint ~amount ctxt = + let open Lwt_result_syntax in + let* ( ctxt, + (Ticket_token.Ex_token {contents; contents_type; ticketer} as token) ) + = + parse_ticket ~consume_deserialization_gas ~ticketer ~contents ~ty ctxt + in + let*? ticket_ty = + Script_typed_ir.ticket_t Micheline.dummy_location contents_type + in + let ticket = Script_typed_ir.{ticketer; contents; amount} in + let* unparsed_parameters, ctxt = + Script_ir_translator.unparse_data ctxt Optimized ticket_ty ticket + in + let*? ctxt, nonce = fresh_internal_nonce ctxt in + let op = + Script_typed_ir.Internal_operation + { + sender; + nonce; + operation = + Transaction_to_smart_contract + { + amount = Tez.zero; + unparsed_parameters; + destination; + entrypoint; + location = Micheline.dummy_location; + parameters_ty = ticket_ty; + parameters = ticket; + }; + } + in + return (ctxt, token, op) + +let transfer_ticket_with_hashes ctxt ~sender_hash ~dst_hash + (qty : Ticket_amount.t) = + let qty = Script_int.(to_zint (qty :> n num)) in + let open Lwt_result_syntax in + let* sender_storage_diff, ctxt = + Ticket_balance.adjust_balance ctxt sender_hash ~delta:(Z.neg qty) + in + let* dst_storage_diff, ctxt = + Ticket_balance.adjust_balance ctxt dst_hash ~delta:qty + in + let* diff, ctxt = + Ticket_balance.adjust_storage_space + ctxt + ~storage_diff:(Z.add sender_storage_diff dst_storage_diff) + in + return (ctxt, diff) + +let transfer_ticket ctxt ~sender ~dst ex_token qty = + let open Lwt_result_syntax in + let* sender_hash, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:sender ex_token + in + let* dst_hash, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:dst ex_token + in + transfer_ticket_with_hashes ctxt ~sender_hash ~dst_hash qty + +let transfer_tickets_in_parameters ctxt parameter parameter_ty ~source ~dst = + let open Lwt_result_syntax in + let*? has_tickets, ctxt = Ticket_scanner.type_has_tickets ctxt parameter_ty in + let* tickets, ctxt = + Ticket_scanner.tickets_of_value + ~include_lazy:true + ctxt + has_tickets + parameter + in + let* ctxt, ticket_receipt, paid_storage_diff = + List.fold_left_es + (fun (ctxt, ticket_receipt_acc, paid_storage_diff_acc) ticket -> + let ticket_token, amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ticket + in + let* ctxt, paid_storage_diff = + transfer_ticket ctxt ~sender:source ~dst ticket_token amount + in + let* ticket_token, ctxt = + Ticket_token_unparser.unparse ctxt ticket_token + in + let amount = Script_int.(to_zint (amount :> n num)) in + let ticket_receipt_item = + Ticket_receipt. + { + ticket_token; + updates = [{account = source; amount = Z.neg amount}]; + (* We only handle negation from the [source] in this receipt. + The addition to [dst] will be taken into account in the receipts + generated from the subsequent contract execution. *) + } + in + return + ( ctxt, + ticket_receipt_item :: ticket_receipt_acc, + Z.add paid_storage_diff_acc paid_storage_diff )) + (ctxt, [], Z.zero) + tickets + in + return (ctxt, ticket_receipt, paid_storage_diff) diff --git a/src/proto_020_PsParisC/lib_protocol/ticket_transfer.mli b/src/proto_020_PsParisC/lib_protocol/ticket_transfer.mli new file mode 100644 index 000000000000..09f10cfce59e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/ticket_transfer.mli @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Margiold *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** [parse_ticket ~ticketer ~contents ~ty + ctxt] reconstructs a ticket from individual parts submitted as + part of a layer-1 operation. *) +val parse_ticket : + consume_deserialization_gas:Script.consume_deserialization_gas -> + ticketer:Contract.t -> + contents:Script.lazy_expr -> + ty:Script.lazy_expr -> + context -> + (context * Ticket_token.ex_token, error trace) result Lwt.t + +(** Same as [parse_ticket], but in addition, build a transaction to + let [sender] transfers [amount] units of said ticket to + [destination]. *) +val parse_ticket_and_operation : + consume_deserialization_gas:Script.consume_deserialization_gas -> + ticketer:Contract.t -> + contents:Script.lazy_expr -> + ty:Script.lazy_expr -> + sender:Destination.t -> + destination:Contract_hash.t -> + entrypoint:Entrypoint.t -> + amount:Script_typed_ir.ticket_amount -> + context -> + (context * Ticket_token.ex_token * Script_typed_ir.packed_internal_operation) + tzresult + Lwt.t + +(** [transfer_ticket_with_hashes ctxt ~sender_hash ~dst_hash qty] updates + the table of tickets moves [qty] units of a given ticket from a + sender to a destination, as encoded by [sender_hash] and [dst_hash]. + + Consistency between [sender_hash] and [dst_hash] is the + responsibility of the caller. Whenever possible, [transfer_ticket] + should be preferred, but [transfer_ticket_with_hashes] could be + preferred to reduce gas comsumption (e.g., to reuse hashes already + computed). + + In addition to an updated context, this function returns the + number of bytes that were newly allocated for the table of + tickets. *) +val transfer_ticket_with_hashes : + context -> + sender_hash:Ticket_hash.t -> + dst_hash:Ticket_hash.t -> + Ticket_amount.t -> + (context * Z.t) tzresult Lwt.t + +(** [transfer_ticket ctxt ~sender ~dst ex_token qty] updates the table of + tickets moves [qty] units of [ex_token] from [sender] to [dst], as + encoded by [sender_hash] and [dst_hash]. + + In addition to an updated context, this function returns the + number of bytes that were newly allocated for the table of + tickets. *) +val transfer_ticket : + context -> + sender:Destination.t -> + dst:Destination.t -> + Ticket_token.ex_token -> + Ticket_amount.t -> + (context * Z.t, error trace) result Lwt.t + +(** [transfer_tickets_in_parameters ctxt param param_ty ~source ~dst] + Scans the [param] for tickets and transfers ownership of those tickets + from [source] to [dst] by updating the ticket table. The function returns + the updated context, the ticket receipt, and the number of newly allocated + bytes for the ticket table. *) +val transfer_tickets_in_parameters : + context -> + 'a -> + ('a, 'b) Script_typed_ir.ty -> + source:Destination.t -> + dst:Destination.t -> + (context * Ticket_receipt.t * Z.t, error trace) result Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/time_repr.ml b/src/proto_020_PsParisC/lib_protocol/time_repr.ml new file mode 100644 index 000000000000..724458095f2e --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/time_repr.ml @@ -0,0 +1,74 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +include Time + +type time = Time.t + +type error += Timestamp_add (* `Permanent *) + +type error += Timestamp_sub (* `Permanent *) + +let () = + register_error_kind + `Permanent + ~id:"timestamp_add" + ~title:"Timestamp add" + ~description:"Overflow when adding timestamps." + ~pp:(fun ppf () -> Format.fprintf ppf "Overflow when adding timestamps.") + Data_encoding.empty + (function Timestamp_add -> Some () | _ -> None) + (fun () -> Timestamp_add) ; + register_error_kind + `Permanent + ~id:"timestamp_sub" + ~title:"Timestamp sub" + ~description:"Subtracting timestamps resulted in negative period." + ~pp:(fun ppf () -> + Format.fprintf ppf "Subtracting timestamps resulted in negative period.") + Data_encoding.empty + (function Timestamp_sub -> Some () | _ -> None) + (fun () -> Timestamp_sub) + +let of_seconds_string s = Option.map Time.of_seconds (Int64.of_string_opt s) + +let to_seconds_string s = Int64.to_string (to_seconds s) + +let pp = pp_hum + +let ( +? ) x y = + let open Result_syntax in + let span = Period_repr.to_seconds y in + let t64 = Time.add x span in + (* As long as span and time representations are int64, we cannont overflow if + x is negative. *) + if x < Time.of_seconds 0L then return t64 + else if t64 < Time.of_seconds 0L then tzfail Timestamp_add + else return t64 + +let ( -? ) x y = + record_trace Timestamp_sub (Period_repr.of_seconds (Time.diff x y)) + +let ( - ) x y = + Time.of_seconds Int64.(sub (Time.to_seconds x) (Period_repr.to_seconds y)) diff --git a/src/proto_020_PsParisC/lib_protocol/time_repr.mli b/src/proto_020_PsParisC/lib_protocol/time_repr.mli new file mode 100644 index 000000000000..c35b2da6f283 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/time_repr.mli @@ -0,0 +1,55 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include module type of struct + include Time +end + +(** Internal timestamp representation. *) +type time = t + +(** Pretty-prints the time stamp using RFC3339 format. *) +val pp : Format.formatter -> t -> unit + +(** Parses RFC3339 representation and returns a timestamp. *) +val of_seconds_string : string -> time option + +(** Returns the timestamp encoded in RFC3339 format. *) +val to_seconds_string : time -> string + +(** Adds a time span to a timestamp. + This function fails on integer overflow *) +val ( +? ) : time -> Period_repr.t -> time tzresult + +(** Returns the difference between two timestamps as a time span. + This function fails when the difference is negative *) +val ( -? ) : time -> time -> Period_repr.t tzresult + +(** [t - p] Returns a timestamps [p] seconds before [t]. + + TODO: https://gitlab.com/tezos/tezos/-/issues/2054 + This function should be made available in the environment. + *) +val ( - ) : time -> Period_repr.t -> time diff --git a/src/proto_020_PsParisC/lib_protocol/token.ml b/src/proto_020_PsParisC/lib_protocol/token.ml new file mode 100644 index 000000000000..88eb1f000085 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/token.ml @@ -0,0 +1,284 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type container = + [ `Contract of Contract_repr.t + | `Collected_commitments of Blinded_public_key_hash.t + | `Frozen_deposits of Frozen_staker_repr.t + | `Unstaked_frozen_deposits of Unstaked_frozen_staker_repr.t * Cycle_repr.t + | `Block_fees + | `Frozen_bonds of Contract_repr.t * Bond_id_repr.t ] + +type infinite_source = + [ `Invoice + | `Bootstrap + | `Initial_commitments + | `Revelation_rewards + | `Attesting_rewards + | `Baking_rewards + | `Baking_bonuses + | `Minted + | `Liquidity_baking_subsidies + | `Sc_rollup_refutation_rewards ] + +type giver = [infinite_source | container] + +type infinite_sink = + [ `Storage_fees + | `Double_signing_punishments + | `Lost_attesting_rewards of Signature.Public_key_hash.t * bool * bool + | `Sc_rollup_refutation_punishments + | `Burned ] + +type receiver = [infinite_sink | container] + +let balance ctxt stored = + let open Lwt_result_syntax in + match stored with + | `Collected_commitments bpkh -> + let+ balance = Commitment_storage.committed_amount ctxt bpkh in + (ctxt, balance) + | `Block_fees -> return (ctxt, Raw_context.get_collected_fees ctxt) + +let credit ctxt receiver amount origin = + let open Lwt_result_syntax in + let open Receipt_repr in + let+ ctxt, balance = + match receiver with + | #infinite_sink as infinite_sink -> + let sink = + match infinite_sink with + | `Storage_fees -> Storage_fees + | `Double_signing_punishments -> Double_signing_punishments + | `Lost_attesting_rewards (d, p, r) -> Lost_attesting_rewards (d, p, r) + | `Sc_rollup_refutation_punishments -> + Sc_rollup_refutation_punishments + | `Burned -> Burned + in + let* old_total_supply = Storage.Contract.Total_supply.get ctxt in + let*? new_total_supply = Tez_repr.(old_total_supply -? amount) in + let+ ctxt = + Storage.Contract.Total_supply.update ctxt new_total_supply + in + (ctxt, sink) + | #container as container -> ( + match container with + | `Contract receiver -> + let+ ctxt = + Contract_storage.credit_only_call_from_token ctxt receiver amount + in + (ctxt, Contract receiver) + | `Collected_commitments bpkh -> + let+ ctxt = + Commitment_storage.increase_commitment_only_call_from_token + ctxt + bpkh + amount + in + (ctxt, Commitments bpkh) + | `Frozen_deposits staker -> + let+ ctxt = + Stake_storage.add_frozen_stake_only_call_from_token + ctxt + staker + amount + in + (ctxt, Deposits staker) + | `Unstaked_frozen_deposits (staker, cycle) -> + let+ ctxt = + Unstaked_frozen_deposits_storage.credit_only_call_from_token + ctxt + staker + cycle + amount + in + (ctxt, Unstaked_deposits (staker, cycle)) + | `Block_fees -> + let*? ctxt = + Raw_context.credit_collected_fees_only_call_from_token ctxt amount + in + return (ctxt, Block_fees) + | `Frozen_bonds (contract, bond_id) -> + let* ctxt = + Contract_storage.credit_bond_only_call_from_token + ctxt + contract + bond_id + amount + in + return (ctxt, Frozen_bonds (contract, bond_id))) + in + (ctxt, item balance (Credited amount) origin) + +let spend ctxt giver amount origin = + let open Lwt_result_syntax in + let open Receipt_repr in + let+ ctxt, balance = + match giver with + | #infinite_source as infinite_source -> + let src = + match infinite_source with + | `Bootstrap -> Bootstrap + | `Invoice -> Invoice + | `Initial_commitments -> Initial_commitments + | `Minted -> Minted + | `Liquidity_baking_subsidies -> Liquidity_baking_subsidies + | `Revelation_rewards -> Nonce_revelation_rewards + | `Attesting_rewards -> Attesting_rewards + | `Baking_rewards -> Baking_rewards + | `Baking_bonuses -> Baking_bonuses + | `Sc_rollup_refutation_rewards -> Sc_rollup_refutation_rewards + in + let* old_total_supply = Storage.Contract.Total_supply.get ctxt in + let*? new_total_supply = Tez_repr.(old_total_supply +? amount) in + let+ ctxt = + Storage.Contract.Total_supply.update ctxt new_total_supply + in + (ctxt, src) + | #container as container -> ( + match container with + | `Contract giver -> + let+ ctxt = + Contract_storage.spend_only_call_from_token ctxt giver amount + in + (ctxt, Contract giver) + | `Collected_commitments bpkh -> + let+ ctxt = + Commitment_storage.decrease_commitment_only_call_from_token + ctxt + bpkh + amount + in + (ctxt, Commitments bpkh) + | `Frozen_deposits staker -> + let+ ctxt = + Stake_storage.remove_frozen_stake_only_call_from_token + ctxt + staker + amount + in + (ctxt, Deposits staker) + | `Unstaked_frozen_deposits (staker, cycle) -> + let+ ctxt = + Unstaked_frozen_deposits_storage.spend_only_call_from_token + ctxt + staker + cycle + amount + in + (ctxt, Unstaked_deposits (staker, cycle)) + | `Block_fees -> + let*? ctxt = + Raw_context.spend_collected_fees_only_call_from_token ctxt amount + in + return (ctxt, Block_fees) + | `Frozen_bonds (contract, bond_id) -> + let* ctxt = + Contract_storage.spend_bond_only_call_from_token + ctxt + contract + bond_id + amount + in + return (ctxt, Frozen_bonds (contract, bond_id))) + in + (ctxt, item balance (Debited amount) origin) + +let transfer_n ?(origin = Receipt_repr.Block_application) ctxt givers receiver = + let open Lwt_result_syntax in + let givers = List.filter (fun (_, am) -> Tez_repr.(am <> zero)) givers in + match givers with + | [] -> + (* Avoid accessing context data when there is nothing to transfer. *) + return (ctxt, []) + | _ :: _ -> + (* Withdraw from givers. *) + let* ctxt, amount, debit_logs = + List.fold_left_es + (fun (ctxt, total, debit_logs) (giver, amount) -> + let* ctxt, debit_log = spend ctxt giver amount origin in + let*? total = Tez_repr.(amount +? total) in + return (ctxt, total, debit_log :: debit_logs)) + (ctxt, Tez_repr.zero, []) + givers + in + let* ctxt, credit_log = credit ctxt receiver amount origin in + (* Deallocate implicit contracts with no stake. This must be done after + spending and crediting. If done in between then a transfer of all the + balance from (`Contract c) to (`Frozen_bonds (c,_)) would leave the + contract c unallocated. *) + let+ ctxt = + List.fold_left_es + (fun ctxt (giver, _amount) -> + match giver with + | `Contract contract | `Frozen_bonds (contract, _) -> + Contract_storage.ensure_deallocated_if_empty ctxt contract + | #giver -> return ctxt) + ctxt + givers + in + (* Make sure the order of balance updates is : debit logs in the order of + of the parameter [givers], and then the credit log. *) + let balance_updates = List.rev (credit_log :: debit_logs) in + (ctxt, balance_updates) + +let transfer ?(origin = Receipt_repr.Block_application) ctxt giver receiver + amount = + transfer_n ~origin ctxt [(giver, amount)] receiver + +module Internal_for_tests = struct + let allocated ctxt stored = + let open Lwt_result_syntax in + match stored with + | `Contract contract -> + let*! allocated = Contract_storage.allocated ctxt contract in + return (ctxt, allocated) + | `Collected_commitments bpkh -> + let*! allocated = Commitment_storage.exists ctxt bpkh in + return (ctxt, allocated) + | `Frozen_deposits _ | `Unstaked_frozen_deposits _ | `Block_fees -> + return (ctxt, true) + | `Frozen_bonds (contract, bond_id) -> + Contract_storage.bond_allocated ctxt contract bond_id + + type container_with_balance = + [ `Contract of Contract_repr.t + | `Collected_commitments of Blinded_public_key_hash.t + | `Block_fees + | `Frozen_bonds of Contract_repr.t * Bond_id_repr.t ] + + let balance ctxt (stored : [< container_with_balance]) = + let open Lwt_result_syntax in + match stored with + | (`Collected_commitments _ | `Block_fees) as stored -> balance ctxt stored + | `Contract contract -> + let+ balance = Contract_storage.get_balance ctxt contract in + (ctxt, balance) + | `Frozen_bonds (contract, bond_id) -> + let+ ctxt, balance_opt = + Contract_storage.find_bond ctxt contract bond_id + in + (ctxt, Option.value ~default:Tez_repr.zero balance_opt) +end diff --git a/src/proto_020_PsParisC/lib_protocol/token.mli b/src/proto_020_PsParisC/lib_protocol/token.mli new file mode 100644 index 000000000000..42e0097e01e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/token.mli @@ -0,0 +1,187 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020-2021 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The aim of this module is to manage operations involving tokens such as + minting, transferring, and burning. Every constructor of the types [giver], + [container], or [receiver] represents a kind of account that holds a given (or + possibly infinite) amount of tokens. + + Tokens can be transferred from a [giver] to a [receiver]. To uniformly handle + all cases, special constructors of givers and receivers may be used. For + example, the giver [`Minted] is used to express a transfer of minted tokens + to a receiver, and the receiver [`Burned] is used to express the action of + burning a given amount of tokens taken from a giver. Thanks to uniformity, + it is easier to track transfers of tokens throughout the protocol by running + [grep -R "Token.transfer" src/proto_alpha]. + + For backward compatibility purpose, an ANTI-PATTERN is used to redistribute + slashing to denunciator; this redistribution technic should not be mimicked + if it can be avoided (see https://gitlab.com/tezos/tezos/-/issues/4787). + The anti-pattern works as follows: + The part of slashed amounts that goes to the author of the denunciation are + not directly distributed to him. Tokens are transferred to a burning sink, + then minted from an infinite source ( see `Double_signing_punishments, + and `Sc_rollup_refutation_rewards ). + Again, this is an ANTI-PATTERN that should not be mimicked. +*) + +(** [container] is the type of token holders with finite capacity, and whose assets + are contained in the context. An account may have several token holders, + that can serve as sources and/or sinks. + For example, an implicit account [d] serving as a delegate has a token holder + for its own spendable balance, and another token holder for its frozen deposits. +*) + +type container = + [ `Contract of Contract_repr.t + (** Implicit account's or Originated contract's spendable balance *) + | `Collected_commitments of Blinded_public_key_hash.t + (** Pre-funded account waiting for the commited pkh and activation code to + be revealed to unlock the funds *) + | `Frozen_deposits of Frozen_staker_repr.t + (** Frozen tokens of a staker for consensus security deposits. *) + | `Unstaked_frozen_deposits of Unstaked_frozen_staker_repr.t * Cycle_repr.t + (** Frozen tokens of a contract that have been unstaked at the + given cycle. *) + | `Block_fees (** Current block's fees collection *) + | `Frozen_bonds of Contract_repr.t * Bond_id_repr.t + (** Frozen tokens of a contract for bond deposits (currently used by rollups) *) + ] + +(** [infinite_source] defines types of tokens providers which are considered to be + ** of infinite capacity. *) +type infinite_source = + [ `Invoice + (** Tokens minted during a protocol upgrade, + typically to fund the development of some part of the amendment. *) + | `Bootstrap (** Bootstrap accounts funding *) + | `Initial_commitments + (** Funding of Genesis' prefunded accounts requiring an activation *) + | `Revelation_rewards (** Seed nonce revelation rewards *) + | `Attesting_rewards (** Consensus attesting rewards *) + | `Baking_rewards (** Consensus baking fixed rewards *) + | `Baking_bonuses (** Consensus baking variable bonus *) + | `Minted (** Generic source for test purpose *) + | `Liquidity_baking_subsidies (** Subsidy for liquidity-baking contract *) + | `Sc_rollup_refutation_rewards + (** Sc_rollup refutation rewards (slashing redistribution) *) ] + +(** [giver] is the type of token providers. Token providers that are not + containers are considered to have infinite capacity. *) +type giver = [infinite_source | container] + +type infinite_sink = + [ `Storage_fees (** Fees burnt to compensate storage usage *) + | `Double_signing_punishments (** Consensus slashing *) + | `Lost_attesting_rewards of Signature.Public_key_hash.t * bool * bool + (** Consensus rewards not distributed because the participation of the delegate was too low. *) + | `Sc_rollup_refutation_punishments (** Smart rollups refutation slashing *) + | `Burned (** Generic sink mainly for test purpose *) ] + +(** [receiver] is the type of token receivers. Token receivers that are not + containers are considered to have infinite capacity. *) +type receiver = [infinite_sink | container] + +(** [balance ctxt container] returns a new context because of an access to + carbonated data, and the balance associated to the token holder. + This function may fail if [allocated ctxt container] returns [false]. + Returns an error with the message "get_balance" if [container] refers to an + originated contract that is not allocated. + + This function is only defined on the few cases for which it is + actually needed. *) +val balance : + Raw_context.t -> + [< `Block_fees | `Collected_commitments of Blinded_public_key_hash.t] -> + (Raw_context.t * Tez_repr.t) tzresult Lwt.t + +(** [transfer_n ?origin ctxt givers receiver] transfers [amount] Tez from [giver] to + [receiver] for each [(giver, amount)] pair in [givers], and returns a new + context, and the list of corresponding balance updates. The function behaves + as though [transfer ?origin ctxt giver receiver amount] was invoked for each pair + [(giver, amount)] in [givers], however a single balance update is generated + for the total amount transferred to [receiver]. + When [givers] is an empty list, the function does nothing to the context, + and returns an empty list of balance updates. *) +val transfer_n : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + ([< giver] * Tez_repr.t) list -> + [< receiver] -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** [transfer ?origin ctxt giver receiver amount] transfers [amount] Tez from giver + [giver] to receiver [receiver], and returns a new context, and the list of + corresponding balance updates tagged with [origin]. By default, [~origin] is + set to [Receipt_repr.Block_application]. + Returns {!Storage_Error Missing_key} if [giver] refers to a contract that is + not allocated. + Returns a [Balance_too_low] error if [giver] refers to a contract whose + balance is less than [amount]. + Returns a [Subtraction_underflow] error if [giver] is + not a contract and its balance is less than [amount]. + Returns a [Empty_implicit_delegated_contract] error if [giver] is an + implicit contract that delegates to a different contract, and whose balance + is equal to [amount]. + Returns a [Non_existing_contract] error if + [receiver] refers to an originated contract that is not allocated. + Returns a [Non_existing_contract] error if [amount <> Tez_repr.zero], and + [receiver] refers to an originated contract that is not allocated. + Returns a [Addition_overflow] error if [receiver] refers to a receiver whose balance + is greater than [Int64.max - amount]. + Returns a [Wrong_level] error if [src] or [receiver] refer to a level that is + not the current level. *) +val transfer : + ?origin:Receipt_repr.update_origin -> + Raw_context.t -> + [< giver] -> + [< receiver] -> + Tez_repr.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +module Internal_for_tests : sig + (** [allocated ctxt container] returns a new context because of possible access + to carbonated data, and a boolean that is [true] when + [balance ctxt container] is guaranteed not to fail, and [false] when + [balance ctxt container] may fail. *) + val allocated : + Raw_context.t -> container -> (Raw_context.t * bool) tzresult Lwt.t + + type container_with_balance = + [ `Contract of Contract_repr.t + | `Collected_commitments of Blinded_public_key_hash.t + | `Block_fees + | `Frozen_bonds of Contract_repr.t * Bond_id_repr.t ] + + (** [balance ctxt container] returns a new context because of an access to + carbonated data, and the balance associated to the token holder. + This function may fail if [allocated ctxt container] returns [false]. + Returns an error with the message "get_balance" if [container] refers to an + originated contract that is not allocated. *) + val balance : + Raw_context.t -> + [< container_with_balance] -> + (Raw_context.t * Tez_repr.t) tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.ml b/src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.ml new file mode 100644 index 000000000000..8959062241ae --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.ml @@ -0,0 +1,53 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Bls.Public_key_hash + +type address = t + +let in_memory_size : t -> Cache_memory_helpers.sint = + fun _ -> + let open Cache_memory_helpers in + header_size +! word_size +! string_size_gen Bls.Public_key_hash.size + +let size _ = Bls.Public_key_hash.size + +module Indexable = struct + include Indexable.Make (struct + type nonrec t = t + + let encoding = encoding + + let compare = compare + + let pp = pp + end) + + let in_memory_size x = Indexable.in_memory_size in_memory_size x + + let size x = Indexable.size size x +end diff --git a/src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.mli b/src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.mli new file mode 100644 index 000000000000..534551d427df --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/tx_rollup_l2_address.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Marigold *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Oxhead Alpha *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module introduces the types used to identify ticket holders + within a transaction rollup. *) + +(** The hash of a BLS public key is used as the primary identifier + of ticket holders within a transaction rollup. *) +include module type of Bls.Public_key_hash with type t = Bls.Public_key_hash.t + +type address = t + +(** [in_memory_size a] returns the number of bytes allocated in RAM for [a]. *) +val in_memory_size : t -> Cache_memory_helpers.sint + +(** [size a] returns the number of bytes allocated in an inbox to store [a]. *) +val size : t -> int + +module Indexable : sig + type nonrec 'state t = ('state, address) Indexable.t + + type nonrec index = address Indexable.index + + type nonrec value = address Indexable.value + + type nonrec either = address Indexable.either + + val encoding : either Data_encoding.t + + val index_encoding : index Data_encoding.t + + val compare_values : value -> value -> int + + val value_encoding : value Data_encoding.t + + val compare : 'state t -> 'state' t -> int + + val value : address -> value + + val index : int32 -> index tzresult + + val index_exn : int32 -> index + + val pp : Format.formatter -> 'state t -> unit + + val size : 'state t -> int + + val in_memory_size : 'state t -> Cache_memory_helpers.sint +end diff --git a/src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.ml b/src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.ml new file mode 100644 index 000000000000..046954b03d02 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.ml @@ -0,0 +1,252 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Cannot_unstake_with_unfinalizable_unstake_requests_to_another_delegate + +let () = + register_error_kind + `Permanent + ~id: + "operation.cannot_unstake_with_unfinalizable_unstake_requests_to_another_delegate" + ~title: + "Cannot unstake with unfinalizable unstake requests to another delegate" + ~description: + "Cannot unstake with unfinalizable unstake requests to another delegate" + Data_encoding.unit + (function + | Cannot_unstake_with_unfinalizable_unstake_requests_to_another_delegate + -> + Some () + | _ -> None) + (fun () -> + Cannot_unstake_with_unfinalizable_unstake_requests_to_another_delegate) + +type finalizable = + (Signature.Public_key_hash.t * Cycle_repr.t * Tez_repr.t) list + +let finalizable_encoding = + let open Data_encoding in + let elt_encoding = + obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "cycle" Cycle_repr.encoding) + (req "amount" Tez_repr.encoding) + in + list elt_encoding + +type stored_requests = Storage.Unstake_request.t = { + delegate : Signature.Public_key_hash.t; + requests : (Cycle_repr.t * Tez_repr.t) list; +} + +let stored_requests_encoding = + let open Data_encoding in + let request_encoding = + obj2 (req "cycle" Cycle_repr.encoding) (req "amount" Tez_repr.encoding) + in + conv + (fun {delegate; requests} -> (delegate, requests)) + (fun (delegate, requests) -> {delegate; requests}) + (obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "requests" (list request_encoding))) + +type prepared_finalize_unstake = { + finalizable : finalizable; + unfinalizable : stored_requests; +} + +let prepared_finalize_unstake_encoding : + prepared_finalize_unstake Data_encoding.t = + let open Data_encoding in + conv + (fun {finalizable; unfinalizable} -> (finalizable, unfinalizable)) + (fun (finalizable, unfinalizable) -> {finalizable; unfinalizable}) + (obj2 + (req "finalizable" finalizable_encoding) + (req "unfinalizable" stored_requests_encoding)) + +let apply_slashes ~slashable_deposits_period slashing_history ~from_cycle amount + = + let first_cycle_to_apply_slash = from_cycle in + let last_cycle_to_apply_slash = + Cycle_repr.add from_cycle slashable_deposits_period + in + (* [slashing_history] is sorted so slashings always happen in the same order. *) + List.fold_left + (fun remain (slashing_cycle, slashing_percentage) -> + if + Cycle_repr.( + slashing_cycle >= first_cycle_to_apply_slash + && slashing_cycle <= last_cycle_to_apply_slash) + then + Tez_repr.( + sub_opt + remain + (mul_percentage ~rounding:`Up amount slashing_percentage)) + |> Option.value ~default:Tez_repr.zero + else remain) + amount + slashing_history + +let prepare_finalize_unstake ctxt ~for_next_cycle_use_only_after_slashing + contract = + let open Lwt_result_syntax in + let slashable_deposits_period = + Constants_storage.slashable_deposits_period ctxt + in + let max_slashing_period = Constants_repr.max_slashing_period in + let slashable_plus_denunciation_delay = + slashable_deposits_period + max_slashing_period + in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let current_cycle = + if for_next_cycle_use_only_after_slashing then Cycle_repr.succ current_cycle + else current_cycle + in + let* requests_opt = Storage.Contract.Unstake_requests.find ctxt contract in + match requests_opt with + | None | Some {delegate = _; requests = []} -> return_none + | Some {delegate; requests} -> ( + match Cycle_repr.sub current_cycle slashable_plus_denunciation_delay with + | None (* no finalizable cycle *) -> + return_some {finalizable = []; unfinalizable = {delegate; requests}} + | Some greatest_finalizable_cycle -> + let* slashing_history_opt = + Storage.Slashed_deposits.find ctxt delegate + in + let slashing_history = + Option.value slashing_history_opt ~default:[] + in + (* Oxford values *) + let* slashing_history_opt_o = + Storage.Contract.Slashed_deposits__Oxford.find + ctxt + (Contract_repr.Implicit delegate) + in + let slashing_history_o = + Option.value slashing_history_opt_o ~default:[] + |> List.map (fun (a, b) -> (a, Percentage.convert_from_o_to_p b)) + in + + let slashing_history = + List.fold_left + (fun acc (cycle, percentage) -> + Storage.Slashed_deposits_history.add cycle percentage acc) + slashing_history_o + slashing_history + in + let finalizable, unfinalizable_requests = + List.partition_map + (fun request -> + let request_cycle, request_amount = request in + if Cycle_repr.(request_cycle <= greatest_finalizable_cycle) then + let new_amount = + apply_slashes + ~slashable_deposits_period + slashing_history + ~from_cycle:request_cycle + request_amount + in + Left (delegate, request_cycle, new_amount) + else Right request) + requests + in + let unfinalizable = + Storage.Unstake_request. + {delegate; requests = unfinalizable_requests} + in + return_some {finalizable; unfinalizable}) + +let update = Storage.Contract.Unstake_requests.update + +let add ctxt ~contract ~delegate cycle amount = + let open Lwt_result_syntax in + let* requests_opt = Storage.Contract.Unstake_requests.find ctxt contract in + let*? requests = + match requests_opt with + | None -> Ok [] + | Some {delegate = request_delegate; requests} -> ( + match requests with + | [] -> Ok [] + | _ -> + if Signature.Public_key_hash.(delegate <> request_delegate) then + (* This would happen if the staker was allowed to stake towards + a new delegate while having unfinalizable unstake requests, + which is not allowed: it will fail earlier. Also, unstaking + for 0 tez is a noop and does not change the state of the storage, + so it does not allow to reach this error either. *) + Result_syntax.tzfail + Cannot_unstake_with_unfinalizable_unstake_requests_to_another_delegate + else Ok requests) + in + let*? requests = Storage.Unstake_request.add cycle amount requests in + let unstake_request = Storage.Unstake_request.{delegate; requests} in + let*! ctxt = + Storage.Contract.Unstake_requests.add ctxt contract unstake_request + in + return ctxt + +module For_RPC = struct + let apply_slash_to_unstaked_unfinalizable ctxt {requests; delegate} = + let open Lwt_result_syntax in + let slashable_deposits_period = + Constants_storage.slashable_deposits_period ctxt + in + let* slashing_history_opt = Storage.Slashed_deposits.find ctxt delegate in + let slashing_history = Option.value slashing_history_opt ~default:[] in + + (* Oxford values *) + let* slashing_history_opt = + Storage.Contract.Slashed_deposits__Oxford.find + ctxt + (Contract_repr.Implicit delegate) + in + let slashing_history_o = + Option.value slashing_history_opt ~default:[] + |> List.map (fun (a, b) -> (a, Percentage.convert_from_o_to_p b)) + in + + let slashing_history = + List.fold_left + (fun acc (cycle, percentage) -> + Storage.Slashed_deposits_history.add cycle percentage acc) + slashing_history_o + slashing_history + in + + List.map_es + (fun (request_cycle, request_amount) -> + let new_amount = + apply_slashes + ~slashable_deposits_period + slashing_history + ~from_cycle:request_cycle + request_amount + in + return (request_cycle, new_amount)) + requests +end diff --git a/src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.mli b/src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.mli new file mode 100644 index 000000000000..6b4a7eb8b639 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstake_requests_storage.mli @@ -0,0 +1,97 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Simple abstraction from low-level storage to handle unstake requests. + + This module is responsible for maintaining the + {!Storage.Contract.Unstake_requests} table. *) + +type finalizable = + (Signature.Public_key_hash.t * Cycle_repr.t * Tez_repr.t) list + +type stored_requests = Storage.Unstake_request.t = { + delegate : Signature.Public_key_hash.t; + requests : (Cycle_repr.t * Tez_repr.t) list; +} + +type prepared_finalize_unstake = { + finalizable : finalizable; + unfinalizable : stored_requests; +} + +val prepared_finalize_unstake_encoding : + prepared_finalize_unstake Data_encoding.encoding + +(** [prepare_finalize_unstake ctxt ~for_next_cycle_use_only_after_slashing contract] + preprocesses a [finalize_unstake] for [contract]. It returns a + list of transfers [(d, c, a)] to do from delegate's [d] unstaked frozen + deposits for cycle [c] of amount [a] in the [finalizable_field] as well as + the remaining unfinalizable requests that should be kept in the storage in + [unfinalizable]. + + It returns [None] if there are no unstake requests. + + If [for_next_cycle_use_only_after_slashing] is true, the finalisation is + done for the next cycle. It is meant to be used only at cycle end after the + application of the slashing. + + *) +val prepare_finalize_unstake : + Raw_context.t -> + for_next_cycle_use_only_after_slashing:bool -> + Contract_repr.t -> + prepared_finalize_unstake option tzresult Lwt.t + +(** [update ctxt contract requests] updates unstake requests for [contract]. *) +val update : + Raw_context.t -> + Contract_repr.t -> + stored_requests -> + Raw_context.t tzresult Lwt.t + +(** [add ctxt ~contract ~delegate cycle amount] adds a request from [contract] + to unstake [amount] from [delegate] at cycle [cycle]. + + @raises Assert_failure if [contract] already has unstake requests from another + delegate (broken invariant). *) +val add : + Raw_context.t -> + contract:Contract_repr.t -> + delegate:Signature.Public_key_hash.t -> + Cycle_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +(** Slow functions only used for RPCs *) +module For_RPC : sig + (** Apply current slash history to unfinalizable unstake requests. + [prepare_finalize_unstake] does not compute this value because it is never + used internally. However, we need to apply slashes anyways when trying to + compute the accurate balance of a staker *) + val apply_slash_to_unstaked_unfinalizable : + Raw_context.t -> + stored_requests -> + (Cycle_repr.t * Tez_repr.t) list tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.ml b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.ml new file mode 100644 index 000000000000..8d6db860bb16 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.ml @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Associative list acting like a map. + Invariants: + - the list is sorted by keys, + - not duplicated keys. *) +type t = (Cycle_repr.t * Deposits_repr.t) list + +let rec check_well_formed = function + | [] -> Result_syntax.return_unit + | (c1, _) :: (c2, _) :: _ when Cycle_repr.(c2 <= c1) -> + Error "Malformed unstaked frozen deposits" + | _ :: tl -> check_well_formed tl + +let id_check_well_formed l = + let open Result_syntax in + let+ () = check_well_formed l in + l + +(* A version of {!t} in which all cycles older than [unslashable_cycle] are + squashed together using {!Deposits_repr.(++?)}. *) +type squashed = {unslashable_cycle : Cycle_repr.t option; t : t} + +let empty ~unslashable_cycle = {unslashable_cycle; t = []} + +let encoding = + let open Data_encoding in + conv_with_guard + (fun l -> l) + id_check_well_formed + (list (tup2 Cycle_repr.encoding Deposits_repr.encoding)) + +let squash_unslashable ~unslashable_cycle t = + let open Result_syntax in + match (unslashable_cycle, t) with + | Some unslashable_cycle', (c, unslashable) :: tl + when Cycle_repr.(c <= unslashable_cycle') -> + let rec aux unslashable = function + | (c, d) :: tl when Cycle_repr.(c <= unslashable_cycle') -> + let* unslashable = Deposits_repr.(unslashable ++? d) in + aux unslashable tl + | slashable -> + return + { + unslashable_cycle; + t = (unslashable_cycle', unslashable) :: slashable; + } + in + aux unslashable tl + | _ -> return {unslashable_cycle; t} + +let normalize_cycle cycle ~unslashable_cycle = + match unslashable_cycle with + | None -> cycle + | Some unslashable_cycle -> Cycle_repr.max cycle unslashable_cycle + +let get cycle {unslashable_cycle; t} = + let normalized_cycle = normalize_cycle cycle ~unslashable_cycle in + List.assoc ~equal:Cycle_repr.( = ) normalized_cycle t + |> Option.value ~default:Deposits_repr.zero + +(* not tail-rec *) +let rec update_t ~f ~normalized_cycle l = + let open Result_syntax in + match l with + | (c, d) :: tl when Cycle_repr.(c = normalized_cycle) -> + let+ d = f d in + (c, d) :: tl + | ((c, _) as hd) :: tl when Cycle_repr.(c < normalized_cycle) -> + let+ tl = update_t ~f ~normalized_cycle tl in + hd :: tl + | _ -> + let+ d = f Deposits_repr.zero in + (normalized_cycle, d) :: l + +let update ~f cycle {unslashable_cycle; t} = + let open Result_syntax in + let normalized_cycle = normalize_cycle cycle ~unslashable_cycle in + let+ t = update_t ~f ~normalized_cycle t in + {unslashable_cycle; t} diff --git a/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.mli b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.mli new file mode 100644 index 000000000000..3e0f889edee8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_repr.mli @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Datatype for a map from cycle to deposits, where all unslashable cycles + are squashed. + + Expected to be used for a small number of cycles at a time, typically + bounded by [consensus_rights_delay + max_slashing_period] plus a small constant. + + See {!Unstaked_frozen_deposits_storage} for more info on unstaked frozen + deposits. +*) + +(** Storable version. *) +type t + +(** To be used locally, do not preserve values of this type over cycles. *) +type squashed = private {unslashable_cycle : Cycle_repr.t option; t : t} + +val empty : unslashable_cycle:Cycle_repr.t option -> squashed + +val encoding : t Data_encoding.t + +(** Once read, [t] must be converted to [squashed] with [squash_unslashable] + to be used efficiently. + For a given [unslashable_cycle], [squash_unslashable ~unslashable_cycle] is + idempotent. *) +val squash_unslashable : + unslashable_cycle:Cycle_repr.t option -> t -> squashed tzresult + +val get : Cycle_repr.t -> squashed -> Deposits_repr.t + +val update : + f:(Deposits_repr.t -> Deposits_repr.t tzresult) -> + Cycle_repr.t -> + squashed -> + squashed tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.ml b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.ml new file mode 100644 index 000000000000..782d27216ade --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.ml @@ -0,0 +1,101 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let current_unslashable_cycle ctxt = + let cycle = (Raw_context.current_level ctxt).cycle in + let slashable_deposits_period = + Constants_storage.slashable_deposits_period ctxt + in + let max_slashing_period = Constants_repr.max_slashing_period in + Cycle_repr.sub cycle (slashable_deposits_period + max_slashing_period) + +let get_all ctxt contract = + let open Lwt_result_syntax in + let* unstaked_frozen_deposits_opt = + Storage.Contract.Unstaked_frozen_deposits.find ctxt contract + in + let unslashable_cycle = current_unslashable_cycle ctxt in + match unstaked_frozen_deposits_opt with + | None -> return (Unstaked_frozen_deposits_repr.empty ~unslashable_cycle) + | Some unstaked_frozen_deposits -> + Lwt.return + @@ Unstaked_frozen_deposits_repr.squash_unslashable + ~unslashable_cycle + unstaked_frozen_deposits + +let get ctxt delegate cycle = + let open Lwt_result_syntax in + let contract = Contract_repr.Implicit delegate in + let+ unstaked_frozen_deposits = get_all ctxt contract in + Unstaked_frozen_deposits_repr.get cycle unstaked_frozen_deposits + +let balance ctxt delegate cycle = + let open Lwt_result_syntax in + let+ frozen_deposits = get ctxt delegate cycle in + frozen_deposits.current_amount + +let update_balance ~f ctxt delegate_contract cycle = + let open Lwt_result_syntax in + let* unstaked_frozen_deposits = get_all ctxt delegate_contract in + let*? unstaked_frozen_deposits = + Unstaked_frozen_deposits_repr.update ~f cycle unstaked_frozen_deposits + in + let*! ctxt = + Storage.Contract.Unstaked_frozen_deposits.add + ctxt + delegate_contract + unstaked_frozen_deposits.t + in + return ctxt + +let credit_only_call_from_token ctxt staker cycle amount = + let open Lwt_result_syntax in + let delegate = Unstaked_frozen_staker_repr.delegate staker in + let delegate_contract = Contract_repr.Implicit delegate in + let f deposits = Deposits_repr.(deposits +? amount) in + let* ctxt = Stake_storage.add_delegated_stake ctxt delegate amount in + update_balance ~f ctxt delegate_contract cycle + +let spend_only_call_from_token ctxt staker cycle amount = + let open Lwt_result_syntax in + let delegate = Unstaked_frozen_staker_repr.delegate staker in + let delegate_contract = Contract_repr.Implicit delegate in + let f Deposits_repr.{initial_amount; current_amount} = + let open Result_syntax in + let+ current_amount = Tez_repr.(current_amount -? amount) in + Deposits_repr.{initial_amount; current_amount} + in + let* ctxt = Stake_storage.remove_delegated_stake ctxt delegate amount in + update_balance ~f ctxt delegate_contract cycle + +let decrease_initial_amount_only_for_stake_from_unstake ctxt delegate cycle + amount = + let delegate_contract = Contract_repr.Implicit delegate in + let f Deposits_repr.{initial_amount; current_amount} = + let open Result_syntax in + let+ initial_amount = Tez_repr.(initial_amount -? amount) in + Deposits_repr.{initial_amount; current_amount} + in + update_balance ~f ctxt delegate_contract cycle diff --git a/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.mli b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.mli new file mode 100644 index 000000000000..a1a622059d12 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_deposits_storage.mli @@ -0,0 +1,111 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Simple abstraction from low-level storage to handle unstaked frozen deposits. + + Unstaked frozen deposits are tez coming from frozen deposits that have been + unstaked, either: + - manually with the "unstake" pseudo-operation, + - automatically at cycle ends with the auto-staking mechanism, or + - when a delegator changes delegate. + The amounts are attached to a given cycle, the cycle at which the unstake + happened, and are slashable for another + [consensus_rights_delay + max_slashing_period - 1] cycles. After this, they can be + finalized either with the "finalize_unstake" pseudo-operation, via + auto-staking (for bakers only), or when staking or unstaking. + + Unstaked frozen deposits contain, for each cycle, a [current_amount] and an + [initial_amount]. + Only unstaked frozen deposits for the current cycles can be increased, via + unstaking. + After a cycle has ended, the initial amount becomes the basis for + forthcoming slashings. It can only be decreased by the + "stake from unstake" mechanism. + Slashings only affects the [current_amount] of the slashed cycles. + + Unstaked frozen deposits of finished cycles can be decreased by the + "stake from unstake" mechanism, but only if the cycles haven't been slashed + (to avoid shooting ourselves in the feet). + + To avoid the list of cycles growing unboundedly, amounts for finalizable + cycles are squashed together, lazily, when the list needs to be updated, + only. + + This module is responsible for maintaining the + {!Storage.Contract.Unstaked_frozen_deposits} table. *) + +(** [balance ctxt delegate cycle] returns the amount of unstaked frozen deposits + for [delegate] at [cycle]. + If [cycle] is an unslashable cycle, the returned amount is the squashed + amount of all the unslashable cycles. *) +val balance : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + Tez_repr.t tzresult Lwt.t + +(** [get] acts like [balance] but returns both the initial amount and the + current amount. *) +val get : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + Deposits_repr.t tzresult Lwt.t + +(** [credit_only_call_from_token ctxt staker cycle amount] credits the + unstaked frozen deposits for [staker] at [cycle] by [amount]. + If [cycle] is an unslashable cycle, the credited cycle is the last + unslashable cycle. *) +val credit_only_call_from_token : + Raw_context.t -> + Unstaked_frozen_staker_repr.t -> + Cycle_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [spend_only_call_from_token ctxt staker cycle amount] spends [amount] + from the unstaked frozen deposits for [staker] at [cycle]. + If [cycle] is an unslashable cycle, the amount is spent from the last + unslashable cycle. + The function returns the error [Subtraction_underflow] if the balance is + too low. *) +val spend_only_call_from_token : + Raw_context.t -> + Unstaked_frozen_staker_repr.t -> + Cycle_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [decrease_initial_amount_only_for_stake_from_unstake ctxt staker cycle amount] + decreases [amount] from the unstaked frozen deposits for [staker] at [cycle]. + It is only called if the cycle hasn't been slashed, so the amount removed is + the same as the amount spent in [current_amount]. +*) +val decrease_initial_amount_only_for_stake_from_unstake : + Raw_context.t -> + Signature.public_key_hash -> + Cycle_repr.t -> + Tez_repr.t -> + Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.ml b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.ml new file mode 100644 index 000000000000..4856bd31b5bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.ml @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +type t = + | Single of Contract_repr.t * Signature.public_key_hash + | Shared of Signature.public_key_hash + +let encoding = + let open Data_encoding in + let single_tag = 0 in + let single_encoding = + obj2 + (req "contract" Contract_repr.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + in + let shared_tag = 1 in + let shared_encoding = + obj1 (req "delegate" Signature.Public_key_hash.encoding) + in + def + ~title:"unstaked_frozen_staker" + ~description: + "Abstract notion of staker used in operation receipts for unstaked \ + frozen deposits, either a single staker or all the stakers delegating \ + to some delegate." + "staker" + @@ matching + (function + | Single (contract, delegate) -> + matched single_tag single_encoding (contract, delegate) + | Shared delegate -> matched shared_tag shared_encoding delegate) + [ + case + ~title:"Single" + (Tag single_tag) + single_encoding + (function + | Single (contract, delegate) -> Some (contract, delegate) + | _ -> None) + (fun (contract, delegate) -> Single (contract, delegate)); + case + ~title:"Shared" + (Tag shared_tag) + shared_encoding + (function Shared delegate -> Some delegate | _ -> None) + (fun delegate -> Shared delegate); + ] + +let compare sa sb = + match (sa, sb) with + | Single (ca, da), Single (cb, db) -> + Compare.or_else (Contract_repr.compare ca cb) (fun () -> + Signature.Public_key_hash.compare da db) + | Shared da, Shared db -> Signature.Public_key_hash.compare da db + | Single _, Shared _ -> -1 + | Shared _, Single _ -> 1 + +let delegate = function + | Single (_contract, delegate) -> delegate + | Shared delegate -> delegate diff --git a/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.mli b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.mli new file mode 100644 index 000000000000..b2e48714a17d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/unstaked_frozen_staker_repr.mli @@ -0,0 +1,22 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** Adding and removing unstaked frozen stake can be done from/toward a + delegate, one of its staker, or both the delegate and all its stakers at + once. We need to distinguish these cases to enforce the staking + over baking limit. *) +type t = + | Single of Contract_repr.t * Signature.public_key_hash + (** A single staker, either the delegate itself or one of its staker. *) + | Shared of Signature.public_key_hash + (** The delegate and all its stakers simultaneously. *) + +val encoding : t Data_encoding.t + +val compare : t -> t -> int + +val delegate : t -> Signature.public_key_hash diff --git a/src/proto_020_PsParisC/lib_protocol/validate.ml b/src/proto_020_PsParisC/lib_protocol/validate.ml new file mode 100644 index 000000000000..7915e67fe1db --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/validate.ml @@ -0,0 +1,2922 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Validate_errors +open Alpha_context + +type consensus_info = { + predecessor_level : Raw_level.t; + predecessor_round : Round.t; + preattestation_slot_map : (Consensus_key.pk * int * int) Slot.Map.t option; + attestation_slot_map : (Consensus_key.pk * int * int) Slot.Map.t option; +} + +let init_consensus_info ctxt (predecessor_level, predecessor_round) = + { + predecessor_level; + predecessor_round; + preattestation_slot_map = Consensus.allowed_preattestations ctxt; + attestation_slot_map = Consensus.allowed_attestations ctxt; + } + +(** Map used to detect consensus operation conflicts. Each delegate may + (pre)attest at most once for each level and round, so two attestations + (resp. two DAL attestations or two preattestations) conflict when they have + the same slot, level, and round. + + Note that when validating the mempool, several (DAL/pre)attestations by the + same delegate at the same level and round would not conflict if they have + different Tenderbake slots. + + Note that when validating a block, all attestations (resp. all + preattestations) must have the same level and round anyway, so only + the slot is relevant. Taking the level and round into account is + useful in mempool mode, because we want to be able to accept and + propagate consensus operations for multiple close + past/future/cousin blocks. *) +module Consensus_conflict_map = Map.Make (struct + type t = Slot.t * Raw_level.t * Round.t + + let compare (slot1, level1, round1) (slot2, level2, round2) = + Compare.or_else (Raw_level.compare level1 level2) @@ fun () -> + Compare.or_else (Slot.compare slot1 slot2) @@ fun () -> + Round.compare round1 round2 +end) + +type consensus_state = { + preattestations_seen : Operation_hash.t Consensus_conflict_map.t; + attestations_seen : Operation_hash.t Consensus_conflict_map.t; +} + +let consensus_conflict_map_encoding = + let open Data_encoding in + conv + (fun map -> Consensus_conflict_map.bindings map) + (fun l -> + Consensus_conflict_map.( + List.fold_left (fun m (k, v) -> add k v m) empty l)) + (list + (tup2 + (tup3 Slot.encoding Raw_level.encoding Round.encoding) + Operation_hash.encoding)) + +let consensus_state_encoding = + let open Data_encoding in + def "consensus_state" + @@ conv + (fun {preattestations_seen; attestations_seen} -> + (preattestations_seen, attestations_seen)) + (fun (preattestations_seen, attestations_seen) -> + {preattestations_seen; attestations_seen}) + (obj2 + (req "preattestations_seen" consensus_conflict_map_encoding) + (req "attestations_seen" consensus_conflict_map_encoding)) + +let empty_consensus_state = + { + preattestations_seen = Consensus_conflict_map.empty; + attestations_seen = Consensus_conflict_map.empty; + } + +type voting_state = { + proposals_seen : Operation_hash.t Signature.Public_key_hash.Map.t; + (** To each delegate that has submitted a Proposals operation in a + previously validated operation, associates the hash of this + operation. This includes Proposals from a potential Testnet + Dictator. *) + ballots_seen : Operation_hash.t Signature.Public_key_hash.Map.t; + (** To each delegate that has submitted a ballot in a previously + validated operation, associates the hash of this operation. *) +} + +let voting_state_encoding = + let open Data_encoding in + def "voting_state" + @@ conv + (fun {proposals_seen; ballots_seen} -> (proposals_seen, ballots_seen)) + (fun (proposals_seen, ballots_seen) -> {proposals_seen; ballots_seen}) + (obj2 + (req + "proposals_seen" + (Signature.Public_key_hash.Map.encoding Operation_hash.encoding)) + (req + "ballots_seen" + (Signature.Public_key_hash.Map.encoding Operation_hash.encoding))) + +module Double_baking_evidence_map = struct + include Map.Make (struct + type t = Raw_level.t * Round.t + + let compare (l, r) (l', r') = + Compare.or_else (Raw_level.compare l l') @@ fun () -> + Compare.or_else (Round.compare r r') @@ fun () -> 0 + end) + + let encoding elt_encoding = + Data_encoding.conv + (fun map -> bindings map) + (fun l -> List.fold_left (fun m (k, v) -> add k v m) empty l) + Data_encoding.( + list (tup2 (tup2 Raw_level.encoding Round.encoding) elt_encoding)) +end + +module Double_operation_evidence_map = struct + include Map.Make (struct + type t = Raw_level.t * Round.t * Slot.t * Misbehaviour.kind + + let compare (l, r, s, k) (l', r', s', k') = + Compare.or_else (Raw_level.compare l l') @@ fun () -> + Compare.or_else (Round.compare r r') @@ fun () -> + Compare.or_else (Slot.compare s s') @@ fun () -> + Misbehaviour.compare_kind k k' + end) + + let encoding elt_encoding = + Data_encoding.conv + (fun map -> bindings map) + (fun l -> List.fold_left (fun m (k, v) -> add k v m) empty l) + Data_encoding.( + list + (tup2 + (tup4 + Raw_level.encoding + Round.encoding + Slot.encoding + Misbehaviour.kind_encoding) + elt_encoding)) +end + +(** State used and modified when validating anonymous operations. + These fields are used to enforce that we do not validate the same + operation multiple times. + + Note that as part of {!state}, these maps live + in memory. They are not explicitly bounded here, however: + + - In block validation mode, they are bounded by the number of + anonymous operations allowed in the block. + + - In mempool mode, bounding the number of operations in this map + is the responsability of the prevalidator on the shell side. *) +type anonymous_state = { + activation_pkhs_seen : Operation_hash.t Ed25519.Public_key_hash.Map.t; + double_baking_evidences_seen : Operation_hash.t Double_baking_evidence_map.t; + double_attesting_evidences_seen : + Operation_hash.t Double_operation_evidence_map.t; + seed_nonce_levels_seen : Operation_hash.t Raw_level.Map.t; + vdf_solution_seen : Operation_hash.t option; +} + +let raw_level_map_encoding elt_encoding = + let open Data_encoding in + conv + (fun map -> Raw_level.Map.bindings map) + (fun l -> + Raw_level.Map.(List.fold_left (fun m (k, v) -> add k v m) empty l)) + (list (tup2 Raw_level.encoding elt_encoding)) + +let anonymous_state_encoding = + let open Data_encoding in + def "anonymous_state" + @@ conv + (fun { + activation_pkhs_seen; + double_baking_evidences_seen; + double_attesting_evidences_seen; + seed_nonce_levels_seen; + vdf_solution_seen; + } -> + ( activation_pkhs_seen, + double_baking_evidences_seen, + double_attesting_evidences_seen, + seed_nonce_levels_seen, + vdf_solution_seen )) + (fun ( activation_pkhs_seen, + double_baking_evidences_seen, + double_attesting_evidences_seen, + seed_nonce_levels_seen, + vdf_solution_seen ) -> + { + activation_pkhs_seen; + double_baking_evidences_seen; + double_attesting_evidences_seen; + seed_nonce_levels_seen; + vdf_solution_seen; + }) + (obj5 + (req + "activation_pkhs_seen" + (Ed25519.Public_key_hash.Map.encoding Operation_hash.encoding)) + (req + "double_baking_evidences_seen" + (Double_baking_evidence_map.encoding Operation_hash.encoding)) + (req + "double_attesting_evidences_seen" + (Double_operation_evidence_map.encoding Operation_hash.encoding)) + (req + "seed_nonce_levels_seen" + (raw_level_map_encoding Operation_hash.encoding)) + (opt "vdf_solution_seen" Operation_hash.encoding)) + +let empty_anonymous_state = + { + activation_pkhs_seen = Ed25519.Public_key_hash.Map.empty; + double_baking_evidences_seen = Double_baking_evidence_map.empty; + double_attesting_evidences_seen = Double_operation_evidence_map.empty; + seed_nonce_levels_seen = Raw_level.Map.empty; + vdf_solution_seen = None; + } + +(** Static information used to validate manager operations. *) +type manager_info = { + hard_storage_limit_per_operation : Z.t; + hard_gas_limit_per_operation : Gas.Arith.integral; +} + +let init_manager_info ctxt = + { + hard_storage_limit_per_operation = + Constants.hard_storage_limit_per_operation ctxt; + hard_gas_limit_per_operation = Constants.hard_gas_limit_per_operation ctxt; + } + +(** State used and modified when validating manager operations. *) +type manager_state = { + managers_seen : Operation_hash.t Signature.Public_key_hash.Map.t; + (** To enforce the one-operation-per manager-per-block restriction + (1M). The operation hash lets us indicate the conflicting + operation in the {!Manager_restriction} error. + + Note that as part of {!state}, this map + lives in memory. It is not explicitly bounded here, however: + + - In block validation mode, it is bounded by the number of + manager operations allowed in the block. + + - In mempool mode, bounding the number of operations in this + map is the responsability of the mempool. (E.g. the plugin used + by Octez has a [max_prechecked_manager_operations] parameter to + ensure this.) *) +} + +let manager_state_encoding = + let open Data_encoding in + def "manager_state" + @@ conv + (fun {managers_seen} -> managers_seen) + (fun managers_seen -> {managers_seen}) + (obj1 + (req + "managers_seen" + (Signature.Public_key_hash.Map.encoding Operation_hash.encoding))) + +let empty_manager_state = {managers_seen = Signature.Public_key_hash.Map.empty} + +(** 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; + header_contents : Block_header.contents; +} + +(** 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; + header_contents : Block_header.contents; +} + +(** 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 maps in the {!operation_conflict_state}. *) +type mode = + | 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 + (** 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. *) + +(** {2 Definition and initialization of [info] and [state]} *) + +type info = { + ctxt : t; (** The context at the beginning of the block or mempool. *) + mode : mode; + chain_id : Chain_id.t; (** Needed for signature checks. *) + current_level : Level.t; + 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; +} + +type operation_conflict_state = { + consensus_state : consensus_state; + voting_state : voting_state; + anonymous_state : anonymous_state; + manager_state : manager_state; +} + +let operation_conflict_state_encoding = + let open Data_encoding in + def "operation_conflict_state" + @@ conv + (fun {consensus_state; voting_state; anonymous_state; manager_state} -> + (consensus_state, voting_state, anonymous_state, manager_state)) + (fun (consensus_state, voting_state, anonymous_state, manager_state) -> + {consensus_state; voting_state; anonymous_state; manager_state}) + (obj4 + (req "consensus_state" consensus_state_encoding) + (req "voting_state" voting_state_encoding) + (req "anonymous_state" anonymous_state_encoding) + (req "manager_state" manager_state_encoding)) + +type block_state = { + op_count : int; + remaining_block_gas : Gas.Arith.fp; + recorded_operations_rev : Operation_hash.t list; + last_op_validation_pass : int option; + locked_round_evidence : (Round.t * int) option; + attestation_power : int; +} + +type validation_state = { + info : info; + operation_state : operation_conflict_state; + block_state : block_state; +} + +let ok_unit = Result_syntax.return_unit + +let result_error = Result_syntax.tzfail + +let init_info ctxt mode chain_id ~predecessor_level_and_round = + let consensus_info = + Option.map (init_consensus_info ctxt) predecessor_level_and_round + in + { + ctxt; + mode; + chain_id; + current_level = Level.current ctxt; + consensus_info; + manager_info = init_manager_info ctxt; + } + +let empty_voting_state = + { + proposals_seen = Signature.Public_key_hash.Map.empty; + ballots_seen = Signature.Public_key_hash.Map.empty; + } + +let empty_operation_conflict_state = + { + consensus_state = empty_consensus_state; + voting_state = empty_voting_state; + anonymous_state = empty_anonymous_state; + manager_state = empty_manager_state; + } + +let init_block_state vi = + { + op_count = 0; + remaining_block_gas = + Gas.Arith.fp (Constants.hard_gas_limit_per_block vi.ctxt); + recorded_operations_rev = []; + last_op_validation_pass = None; + locked_round_evidence = None; + attestation_power = 0; + } + +let get_initial_ctxt {info; _} = info.ctxt + +(** Validation of consensus operations (validation pass [0]): + preattestations and attestations. *) +module Consensus = struct + open Validate_errors.Consensus + + let check_delegate_is_not_forbidden ctxt delegate_pkh = + fail_when + (Delegate.is_forbidden_delegate ctxt delegate_pkh) + (Forbidden_delegate delegate_pkh) + + let get_delegate_details slot_map kind slot = + let open Result_syntax in + match slot_map with + | None -> tzfail (Consensus.Slot_map_not_found {loc = __LOC__}) + | Some slot_map -> ( + match Slot.Map.find slot slot_map with + | None -> tzfail (Wrong_slot_used_for_consensus_operation {kind}) + | Some x -> return x) + + (** When validating a block (ie. in [Application], + [Partial_validation], and [Construction] modes), any + preattestations 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) + (Preattestation_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 + result_error + (Consensus_operation_for_old_level {kind; expected; provided}) + else + result_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 ok_unit + else if Round.(expected > provided) then + result_error + (Consensus_operation_for_old_round {kind; expected; provided}) + else + result_error + (Consensus_operation_for_future_round {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}) + + (** Preattestation checks for both [Application] and + [Partial_validation] modes. + + Return the slot owner's consensus key and voting power. *) + let check_preexisting_block_preattestation vi consensus_info block_info + {level; round; block_payload_hash = bph; slot} = + let open Lwt_result_syntax in + let*? locked_round = + match block_info.locked_round with + | Some locked_round -> Ok locked_round + | None -> + (* A preexisting block whose fitness has no locked round + should contain no preattestations. *) + error Unexpected_preattestation_in_block + in + let kind = Preattestation 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 expected_payload_hash = block_info.header_contents.payload_hash in + let*? () = check_payload_hash kind expected_payload_hash bph in + let*? consensus_key, voting_power, _dal_power = + get_delegate_details consensus_info.preattestation_slot_map kind slot + in + return (consensus_key, voting_power) + + (** Preattestation checks for Construction mode. + + Return the slot owner's consensus key and voting power. *) + let check_constructed_block_preattestation vi consensus_info cons_info + {level; round; block_payload_hash = bph; slot} = + let open Lwt_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 preattestations. *) + error_when + Block_payload_hash.(expected_payload_hash = zero) + Unexpected_preattestation_in_block + in + let kind = Preattestation 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 preattestations have the same round in + [check_construction_preattestation_round_consistency] further below. *) + let*? () = check_payload_hash kind expected_payload_hash bph in + let*? consensus_key, voting_power, _dal_power = + get_delegate_details consensus_info.preattestation_slot_map kind slot + in + return (consensus_key, voting_power) + + (** Preattestation/attestation checks for Mempool mode. + + We want this mode to be very permissive, to allow the mempool to + accept and propagate consensus operations even if they point to a + block which is not known to the mempool (e.g. because the block + has just been validated and the mempool has not had time to + switch its head to it yet, or because the block belongs to a + cousin branch). Therefore, we do not check the round nor the + payload, which may correspond to blocks that we do not know of + yet. As to the level, we only require it to be the + [predecessor_level] (aka the level of the mempool's head) plus or + minus one, that is: + [predecessor_level - 1 <= op_level <= predecessor_level + 1] + (note that [predecessor_level + 1] is also known as [current_level]). + + Note that we also don't check whether the slot is normalized + (that is, whether it is the delegate's smallest slot). Indeed, + we don't want to compute the right tables by first slot for all + three allowed levels. Checking the slot normalization is + therefore the responsability of the baker when it selects + the consensus operations to include in a new block. Moreover, + multiple attestations pointing to the same block with different + slots can be punished by a double-(pre)attestation operation. + + Return the slot owner's consensus key and a fake voting power (the + latter won't be used anyway in Mempool mode). *) + let check_mempool_consensus vi consensus_info kind {level; slot; _} = + let open Lwt_result_syntax in + let*? () = + if Raw_level.(succ level < consensus_info.predecessor_level) then + let expected = consensus_info.predecessor_level and provided = level in + result_error + (Consensus_operation_for_old_level {kind; expected; provided}) + else if Raw_level.(level > vi.current_level.level) then + let expected = consensus_info.predecessor_level and provided = level in + result_error + (Consensus_operation_for_future_level {kind; expected; provided}) + else ok_unit + in + let* (_ctxt : t), consensus_key = + Stake_distribution.slot_owner vi.ctxt (Level.from_raw vi.ctxt level) slot + in + return (consensus_key, 0 (* Fake voting power *)) + (* We do not check that the frozen deposits are positive because this + only needs to be true in the context of a block that actually + contains the operation, which may not be the same as the current + mempool's context. *) + + let check_preattestation vi ~check_signature + (operation : Kind.preattestation 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 (Preattestation consensus_content)) = + operation.protocol_data.contents + in + let* consensus_key, voting_power = + match vi.mode with + | Application block_info | Partial_validation block_info -> + check_preexisting_block_preattestation + vi + consensus_info + block_info + consensus_content + | Construction construction_info -> + check_constructed_block_preattestation + vi + consensus_info + construction_info + consensus_content + | Mempool -> + check_mempool_consensus + vi + consensus_info + Preattestation + consensus_content + in + let* () = check_delegate_is_not_forbidden vi.ctxt consensus_key.delegate in + let*? () = + if check_signature then + Operation.check_signature + consensus_key.consensus_pk + vi.chain_id + operation + else ok_unit + in + return voting_power + + let check_preattestation_conflict vs oph (op : Kind.preattestation operation) + = + let (Single (Preattestation {slot; level; round; _})) = + op.protocol_data.contents + in + match + Consensus_conflict_map.find_opt + (slot, level, round) + vs.consensus_state.preattestations_seen + with + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + | None -> ok_unit + + let wrap_preattestation_conflict = function + | Ok () -> ok_unit + | Error conflict -> + result_error + Validate_errors.Consensus.( + Conflicting_consensus_operation {kind = Preattestation; conflict}) + + let add_preattestation vs oph (op : Kind.preattestation operation) = + let (Single (Preattestation {slot; level; round; _})) = + op.protocol_data.contents + in + let preattestations_seen = + Consensus_conflict_map.add + (slot, level, round) + oph + vs.consensus_state.preattestations_seen + in + {vs with consensus_state = {vs.consensus_state with preattestations_seen}} + + let may_update_locked_round_evidence block_state mode + (consensus_content : consensus_content) voting_power = + let locked_round_evidence = + match mode with + | 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) + | Some (_stored_round, evidences) -> + (* [_stored_round] is always equal to [consensus_content.round]. + Indeed, this is ensured by + {!check_preattestation_content_preexisting_block} in + application and partial validation modes, and by + {!check_construction_preattestation_round_consistency} in + construction mode. *) + Some (consensus_content.round, evidences + voting_power)) + in + {block_state with locked_round_evidence} + + (* Hypothesis: this function will only be called in mempool mode *) + let remove_preattestation vs (operation : Kind.preattestation operation) = + (* As we are in mempool mode, we do not update + [locked_round_evidence]. *) + let (Single (Preattestation {slot; level; round; _})) = + operation.protocol_data.contents + in + let preattestations_seen = + Consensus_conflict_map.remove + (slot, level, round) + vs.consensus_state.preattestations_seen + in + {vs with consensus_state = {vs.consensus_state with preattestations_seen}} + + (** Attestation checks for all modes that involve a block: + Application, Partial_validation, and Construction. + Checks regarding the DAL content are done separately. + + Return the slot owner's consensus key and voting power. *) + let check_block_attestation vi consensus_info + {level; round; block_payload_hash = bph; slot} = + let open Lwt_result_syntax in + let*? expected_payload_hash = + match Consensus.attestation_branch vi.ctxt with + | Some ((_branch : Block_hash.t), payload_hash) -> Ok payload_hash + | None -> + (* [Consensus.attestation_branch] only returns [None] when the + predecessor is the block that activates the first protocol + of the Tenderbake family; this block should not be + attested. This can only happen in tests and test + networks. *) + result_error Unexpected_attestation_in_block + in + let kind = Attestation in + let*? () = check_level kind consensus_info.predecessor_level level in + let*? () = check_round kind consensus_info.predecessor_round round in + let*? () = check_payload_hash kind expected_payload_hash bph in + let*? consensus_key, voting_power, _dal_power = + get_delegate_details consensus_info.attestation_slot_map kind slot + in + return (consensus_key, voting_power) + + let check_attestation vi ~check_signature + (operation : Kind.attestation 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 (Attestation {consensus_content; dal_content})) = + operation.protocol_data.contents + in + let* consensus_key, voting_power = + match vi.mode with + | Application _ | Partial_validation _ | Construction _ -> + check_block_attestation vi consensus_info consensus_content + | Mempool -> + check_mempool_consensus + vi + consensus_info + Attestation + consensus_content + in + let* () = check_delegate_is_not_forbidden vi.ctxt consensus_key.delegate in + let* () = + Option.fold + ~none:return_unit + ~some:(fun dal -> + Dal_apply.validate_attestation + vi.ctxt + consensus_content.level + consensus_content.slot + consensus_key + dal.attestation) + dal_content + in + let*? () = + if check_signature then + Operation.check_signature + consensus_key.consensus_pk + vi.chain_id + operation + else ok_unit + in + return voting_power + + let check_attestation_conflict vs oph (operation : Kind.attestation operation) + = + let (Single + (Attestation + {consensus_content = {slot; level; round; _}; dal_content = _})) = + operation.protocol_data.contents + in + match + Consensus_conflict_map.find_opt + (slot, level, round) + vs.consensus_state.attestations_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_attestation_conflict = function + | Ok () -> ok_unit + | Error conflict -> + result_error + Validate_errors.Consensus.( + Conflicting_consensus_operation {kind = Attestation; conflict}) + + let add_attestation vs oph (op : Kind.attestation operation) = + let (Single + (Attestation + {consensus_content = {slot; level; round; _}; dal_content = _})) = + op.protocol_data.contents + in + let attestations_seen = + Consensus_conflict_map.add + (slot, level, round) + oph + vs.consensus_state.attestations_seen + in + {vs with consensus_state = {vs.consensus_state with attestations_seen}} + + let may_update_attestation_power vi block_state voting_power = + match vi.mode with + | Mempool -> (* The block_state is not relevant. *) block_state + | Application _ | Partial_validation _ | Construction _ -> + { + block_state with + attestation_power = block_state.attestation_power + voting_power; + } + + (* Hypothesis: this function will only be called in mempool mode *) + let remove_attestation vs (operation : Kind.attestation operation) = + (* We do not remove the attestation power because it is not + relevant for the mempool mode. *) + let (Single + (Attestation + {consensus_content = {slot; level; round; _}; dal_content = _})) = + operation.protocol_data.contents + in + let attestations_seen = + Consensus_conflict_map.remove + (slot, level, round) + vs.consensus_state.attestations_seen + in + {vs with consensus_state = {vs.consensus_state with attestations_seen}} + + (** In Construction mode, check that the preattestation has the same + round as any previously validated preattestations. + + This check is not needed in other modes because + {!check_preattestation} already checks that all preattestations + have the same expected round (the locked_round in Application and + Partial_validation modes when there is one (otherwise all + preattestations are rejected so the point is moot), or the + predecessor_round in Mempool mode). *) + let check_construction_preattestation_round_consistency vi block_state + (consensus_content : consensus_content) = + let open Result_syntax in + match vi.mode with + | Construction _ -> ( + match block_state.locked_round_evidence with + | None -> + (* This is the first validated preattestation: + there is nothing to check. *) + return_unit + | Some (expected, _power) -> + (* Other preattestations have already been validated: we check + that the current operation has the same round as them. *) + check_round Preattestation expected consensus_content.round) + | Application _ | Partial_validation _ | Mempool -> return_unit + + let validate_preattestation ~check_signature info operation_state block_state + oph (operation : Kind.preattestation operation) = + let open Lwt_result_syntax in + let (Single (Preattestation consensus_content)) = + operation.protocol_data.contents + in + let* voting_power = check_preattestation info ~check_signature operation in + let*? () = + check_construction_preattestation_round_consistency + info + block_state + consensus_content + in + let*? () = + check_preattestation_conflict operation_state oph operation + |> wrap_preattestation_conflict + in + (* We need to update the block state *) + let block_state = + may_update_locked_round_evidence + block_state + info.mode + consensus_content + voting_power + in + let operation_state = add_preattestation operation_state oph operation in + return {info; operation_state; block_state} + + let validate_attestation ~check_signature info operation_state block_state oph + operation = + let open Lwt_result_syntax in + let* power = check_attestation info ~check_signature operation in + let*? () = + check_attestation_conflict operation_state oph operation + |> wrap_attestation_conflict + in + let block_state = may_update_attestation_power info block_state power in + let operation_state = add_attestation operation_state oph operation in + return {info; operation_state; block_state} +end + +(** {2 Validation of voting operations} + + There are two kinds of voting operations: + + - Proposals: A delegate submits a list of protocol amendment + proposals. This operation is only accepted during a Proposal period + (see above). + + - Ballot: A delegate casts a vote for/against the current proposal + (or pass). This operation is only accepted during an Exploration + or Promotion period (see above). *) + +module Voting = struct + open Validate_errors.Voting + + let check_period_index ~expected period_index = + error_unless + Compare.Int32.(expected = period_index) + (Wrong_voting_period_index {expected; provided = period_index}) + + let check_proposals_source_is_registered ctxt source = + let open Lwt_result_syntax in + let*! is_registered = Delegate.registered ctxt source in + fail_unless is_registered (Proposals_from_unregistered_delegate source) + + (** Check that the list of proposals is not empty and does not contain + duplicates. *) + let check_proposal_list_sanity proposals = + let open Result_syntax in + let* () = + match proposals with [] -> tzfail Empty_proposals | _ :: _ -> ok_unit + in + let* (_ : Protocol_hash.Set.t) = + List.fold_left_e + (fun previous_elements proposal -> + let* () = + error_when + (Protocol_hash.Set.mem proposal previous_elements) + (Proposals_contain_duplicate {proposal}) + in + return (Protocol_hash.Set.add proposal previous_elements)) + Protocol_hash.Set.empty + proposals + in + return_unit + + let check_period_kind_for_proposals current_period = + match current_period.Voting_period.kind with + | Proposal -> ok_unit + | (Exploration | Cooldown | Promotion | Adoption) as current -> + result_error (Wrong_voting_period_kind {current; expected = [Proposal]}) + + let check_in_listings ctxt source = + let open Lwt_result_syntax in + let*! in_listings = Vote.in_listings ctxt source in + fail_unless in_listings Source_not_in_vote_listings + + let check_count ~count_in_ctxt ~proposals_length = + (* The proposal count of the proposer in the context should never + have been increased above [max_proposals_per_delegate]. *) + assert (Compare.Int.(count_in_ctxt <= Constants.max_proposals_per_delegate)) ; + error_unless + Compare.Int.( + count_in_ctxt + proposals_length <= Constants.max_proposals_per_delegate) + (Too_many_proposals + {previous_count = count_in_ctxt; operation_count = proposals_length}) + + let check_already_proposed ctxt proposer proposals = + let open Lwt_result_syntax in + List.iter_es + (fun proposal -> + let*! already_proposed = Vote.has_proposed ctxt proposer proposal in + fail_when already_proposed (Already_proposed {proposal})) + proposals + + (** Check that the [apply_testnet_dictator_proposals] function in + {!module:Amendment} will not fail. + + The current function is designed to be exclusively called by + [check_proposals] right below. + + @return [Error Testnet_dictator_multiple_proposals] if + [proposals] has more than one element. *) + let check_testnet_dictator_proposals chain_id proposals = + (* This assertion should be ensured by the fact that + {!Amendment.is_testnet_dictator} cannot be [true] on mainnet + (so the current function cannot be called there). However, we + still double check it because of its criticality. *) + assert (Chain_id.(chain_id <> Constants.mainnet_id)) ; + match proposals with + | [] | [_] -> + (* In [Amendment.apply_testnet_dictator_proposals], the call to + {!Vote.init_current_proposal} (in the singleton list case) + cannot fail because {!Vote.clear_current_proposal} is called + right before. + + The calls to + {!Voting_period.Testnet_dictator.overwrite_current_kind} may + usually fail when the voting period is not + initialized. However, this cannot happen here because the + current function is only called in [check_proposals] after a + successful call to {!Voting_period.get_current}. *) + ok_unit + | _ :: _ :: _ -> result_error Testnet_dictator_multiple_proposals + + (** Check that a Proposals operation can be safely applied. + + @return [Error Wrong_voting_period_index] if the operation's + period and the current period in the {!type:context} do not have + the same index. + + @return [Error Proposals_from_unregistered_delegate] if the + source is not a registered delegate. + + @return [Error Empty_proposals] if the list of proposals is empty. + + @return [Error Proposals_contain_duplicate] if the list of + proposals contains a duplicate element. + + @return [Error Wrong_voting_period_kind] if the voting period is + not of the Proposal kind. + + @return [Error Source_not_in_vote_listings] if the source is not + in the vote listings. + + @return [Error Too_many_proposals] if the operation causes the + source's total number of proposals during the current voting + period to exceed {!Constants.max_proposals_per_delegate}. + + @return [Error Already_proposed] if one of the proposals has + already been proposed by the source in the current voting period. + + @return [Error Testnet_dictator_multiple_proposals] if the + source is a testnet dictator and the operation contains more than + one proposal. + + @return [Error Operation.Missing_signature] or [Error + Operation.Invalid_signature] if the operation is unsigned or + incorrectly signed. *) + let check_proposals vi ~check_signature (operation : Kind.proposals operation) + = + let open Lwt_result_syntax in + let (Single (Proposals {source; period; proposals})) = + operation.protocol_data.contents + in + let* current_period = Voting_period.get_current vi.ctxt in + let*? () = check_period_index ~expected:current_period.index period in + let* () = + if Amendment.is_testnet_dictator vi.ctxt vi.chain_id source then + let*? () = check_testnet_dictator_proposals vi.chain_id proposals in + return_unit + else + let* () = check_proposals_source_is_registered vi.ctxt source in + let*? () = check_proposal_list_sanity proposals in + let*? () = check_period_kind_for_proposals current_period in + let* () = check_in_listings vi.ctxt source in + let* count_in_ctxt = Vote.get_delegate_proposal_count vi.ctxt source in + let proposals_length = List.length proposals in + let*? () = check_count ~count_in_ctxt ~proposals_length in + check_already_proposed vi.ctxt source proposals + in + if check_signature then + (* Retrieving the public key should not fail as it *should* be + called after checking that the delegate is in the vote + listings (or is a testnet dictator), which implies that it + is a manager with a revealed key. *) + let* public_key = Contract.get_manager_key vi.ctxt source in + Lwt.return (Operation.check_signature public_key vi.chain_id operation) + else return_unit + + (** Check that a Proposals operation is compatible with previously + validated operations in the current block/mempool. + + @return [Error Operation_conflict] if the current block/mempool + already contains a Proposals operation from the same source + (regardless of whether this source is a testnet dictator or an + ordinary manager). *) + let check_proposals_conflict vs oph (operation : Kind.proposals operation) = + let open Result_syntax in + let (Single (Proposals {source; _})) = operation.protocol_data.contents in + match + Signature.Public_key_hash.Map.find_opt + source + vs.voting_state.proposals_seen + with + | None -> return_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_proposals_conflict = function + | Ok () -> ok_unit + | Error conflict -> + result_error Validate_errors.Voting.(Conflicting_proposals conflict) + + let add_proposals vs oph (operation : Kind.proposals operation) = + let (Single (Proposals {source; _})) = operation.protocol_data.contents in + let proposals_seen = + Signature.Public_key_hash.Map.add + source + oph + vs.voting_state.proposals_seen + in + let voting_state = {vs.voting_state with proposals_seen} in + {vs with voting_state} + + let remove_proposals vs (operation : Kind.proposals operation) = + let (Single (Proposals {source; _})) = operation.protocol_data.contents in + let proposals_seen = + Signature.Public_key_hash.Map.remove source vs.voting_state.proposals_seen + in + {vs with voting_state = {vs.voting_state with proposals_seen}} + + let check_ballot_source_is_registered ctxt source = + let open Lwt_result_syntax in + let*! is_registered = Delegate.registered ctxt source in + fail_unless is_registered (Ballot_from_unregistered_delegate source) + + let check_period_kind_for_ballot current_period = + match current_period.Voting_period.kind with + | Exploration | Promotion -> ok_unit + | (Cooldown | Proposal | Adoption) as current -> + result_error + (Wrong_voting_period_kind + {current; expected = [Exploration; Promotion]}) + + let check_current_proposal ctxt op_proposal = + let open Lwt_result_syntax in + let* current_proposal = Vote.get_current_proposal ctxt in + fail_unless + (Protocol_hash.equal op_proposal current_proposal) + (Ballot_for_wrong_proposal + {current = current_proposal; submitted = op_proposal}) + + let check_source_has_not_already_voted ctxt source = + let open Lwt_result_syntax in + let*! has_ballot = Vote.has_recorded_ballot ctxt source in + fail_when has_ballot Already_submitted_a_ballot + + (** Check that a Ballot operation can be safely applied. + + @return [Error Ballot_from_unregistered_delegate] if the source + is not a registered delegate. + + @return [Error Wrong_voting_period_index] if the operation's + period and the current period in the {!type:context} do not have + the same index. + + @return [Error Wrong_voting_period_kind] if the voting period is + not of the Exploration or Promotion kind. + + @return [Error Ballot_for_wrong_proposal] if the operation's + proposal is different from the current proposal in the context. + + @return [Error Already_submitted_a_ballot] if the source has + already voted during the current voting period. + + @return [Error Source_not_in_vote_listings] if the source is not + in the vote listings. + + @return [Error Operation.Missing_signature] or [Error + Operation.Invalid_signature] if the operation is unsigned or + incorrectly signed. *) + let check_ballot vi ~check_signature (operation : Kind.ballot operation) = + let open Lwt_result_syntax in + let (Single (Ballot {source; period; proposal; ballot = _})) = + operation.protocol_data.contents + in + let* () = check_ballot_source_is_registered vi.ctxt source in + let* current_period = Voting_period.get_current vi.ctxt in + let*? () = check_period_index ~expected:current_period.index period in + let*? () = check_period_kind_for_ballot current_period in + let* () = check_current_proposal vi.ctxt proposal in + let* () = check_source_has_not_already_voted vi.ctxt source in + let* () = check_in_listings vi.ctxt source in + when_ check_signature (fun () -> + (* Retrieving the public key cannot fail. Indeed, we have + already checked that the delegate is in the vote listings, + which implies that it is a manager with a revealed key. *) + let* public_key = Contract.get_manager_key vi.ctxt source in + Lwt.return (Operation.check_signature public_key vi.chain_id operation)) + + (** Check that a Ballot operation is compatible with previously + validated operations in the current block/mempool. + + @return [Error Operation_conflict] if the current block/mempool + already contains a Ballot operation from the same source. *) + let check_ballot_conflict vs oph (operation : Kind.ballot operation) = + let (Single (Ballot {source; _})) = operation.protocol_data.contents in + match + Signature.Public_key_hash.Map.find_opt source vs.voting_state.ballots_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_ballot_conflict = function + | Ok () -> ok_unit + | Error conflict -> result_error (Conflicting_ballot conflict) + + let add_ballot vs oph (operation : Kind.ballot operation) = + let (Single (Ballot {source; _})) = operation.protocol_data.contents in + let ballots_seen = + Signature.Public_key_hash.Map.add source oph vs.voting_state.ballots_seen + in + let voting_state = {vs.voting_state with ballots_seen} in + {vs with voting_state} + + let remove_ballot vs (operation : Kind.ballot operation) = + let (Single (Ballot {source; _})) = operation.protocol_data.contents in + let ballots_seen = + Signature.Public_key_hash.Map.remove source vs.voting_state.ballots_seen + in + {vs with voting_state = {vs.voting_state with ballots_seen}} +end + +module Anonymous = struct + open Validate_errors.Anonymous + + let check_activate_account vi (operation : Kind.activate_account operation) = + let open Lwt_result_syntax in + let (Single (Activate_account {id = edpkh; activation_code})) = + operation.protocol_data.contents + in + let blinded_pkh = + Blinded_public_key_hash.of_ed25519_pkh activation_code edpkh + in + let*! exists = Commitment.exists vi.ctxt blinded_pkh in + let*? () = error_unless exists (Invalid_activation {pkh = edpkh}) in + return_unit + + let check_activate_account_conflict vs oph + (operation : Kind.activate_account operation) = + let (Single (Activate_account {id = edpkh; _})) = + operation.protocol_data.contents + in + match + Ed25519.Public_key_hash.Map.find_opt + edpkh + vs.anonymous_state.activation_pkhs_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_activate_account_conflict + (operation : Kind.activate_account operation) = function + | Ok () -> ok_unit + | Error conflict -> + let (Single (Activate_account {id = edpkh; _})) = + operation.protocol_data.contents + in + result_error (Conflicting_activation {edpkh; conflict}) + + let add_activate_account vs oph (operation : Kind.activate_account operation) + = + let (Single (Activate_account {id = edpkh; _})) = + operation.protocol_data.contents + in + let activation_pkhs_seen = + Ed25519.Public_key_hash.Map.add + edpkh + oph + vs.anonymous_state.activation_pkhs_seen + in + {vs with anonymous_state = {vs.anonymous_state with activation_pkhs_seen}} + + let remove_activate_account vs (operation : Kind.activate_account operation) = + let (Single (Activate_account {id = edpkh; _})) = + operation.protocol_data.contents + in + let activation_pkhs_seen = + Ed25519.Public_key_hash.Map.remove + edpkh + vs.anonymous_state.activation_pkhs_seen + in + {vs with anonymous_state = {vs.anonymous_state with activation_pkhs_seen}} + + let check_denunciation_age vi kind given_level = + let open Result_syntax in + let current_cycle = vi.current_level.cycle in + let given_cycle = (Level.from_raw vi.ctxt given_level).cycle in + let max_slashing_period = Constants.max_slashing_period in + let last_slashable_cycle = Cycle.add given_cycle max_slashing_period in + let* () = + error_unless + Cycle.(given_cycle <= current_cycle) + (Too_early_denunciation + {kind; level = given_level; current = vi.current_level.level}) + in + error_unless + Cycle.(last_slashable_cycle > current_cycle) + (Outdated_denunciation + {kind; level = given_level; last_cycle = last_slashable_cycle}) + + let check_double_attesting_evidence (type kind) vi + (op1 : kind Kind.consensus Operation.t) + (op2 : kind Kind.consensus Operation.t) = + let open Lwt_result_syntax in + let e1, e2, kind = + match (op1.protocol_data.contents, op2.protocol_data.contents) with + | Single (Preattestation e1), Single (Preattestation e2) -> + (e1, e2, Misbehaviour.Double_preattesting) + | ( Single (Attestation {consensus_content = e1; dal_content = _}), + Single (Attestation {consensus_content = e2; dal_content = _}) ) -> + (e1, e2, Double_attesting) + in + let op1_hash = Operation.hash op1 in + let op2_hash = Operation.hash op2 in + let same_levels = Raw_level.(e1.level = e2.level) in + let same_rounds = Round.(e1.round = e2.round) in + let same_payload = + Block_payload_hash.(e1.block_payload_hash = e2.block_payload_hash) + in + let same_branches = Block_hash.(op1.shell.branch = op2.shell.branch) in + let same_slots = Slot.(e1.slot = e2.slot) in + let ordered_hashes = Operation_hash.(op1_hash < op2_hash) in + let is_denunciation_consistent = + same_levels && same_rounds + (* For the double (pre)attestations to be punishable, they + must point to the same block (same level and round), but + also have at least a difference that is the delegate's + fault: different payloads, different branches, or + different slots. Note that different payloads would + endanger the consensus process, while different branches + or slots could be used to spam mempools with a lot of + valid operations (since the minimality of the slot in not + checked in mempool mode, only in block-related modes). On + the other hand, if the operations have identical levels, + rounds, payloads, branches, and slots, then only their + signatures are different, which is not considered the + delegate's fault and therefore is not punished. *) + && ((not same_payload) || (not same_branches) || not same_slots) + && (* we require an order on hashes to avoid the existence of + equivalent evidences *) + ordered_hashes + in + let*? () = + error_unless is_denunciation_consistent (Invalid_denunciation kind) + in + (* Disambiguate: levels are equal *) + let level = Level.from_raw vi.ctxt e1.level in + let*? () = check_denunciation_age vi kind level.level in + let* ctxt, consensus_key1 = + Stake_distribution.slot_owner vi.ctxt level e1.slot + in + let* ctxt, consensus_key2 = + Stake_distribution.slot_owner ctxt level e2.slot + in + let delegate1, delegate2 = + (consensus_key1.delegate, consensus_key2.delegate) + in + let*? () = + error_unless + (Signature.Public_key_hash.equal delegate1 delegate2) + (Inconsistent_denunciation {kind; delegate1; delegate2}) + in + let delegate_pk, delegate = (consensus_key1.consensus_pk, delegate1) in + let* already_slashed = + Delegate.already_denounced ctxt delegate level e1.round kind + in + let*? () = + error_unless + (not already_slashed) + (Already_denounced {kind; delegate; level}) + in + let*? () = Operation.check_signature delegate_pk vi.chain_id op1 in + let*? () = Operation.check_signature delegate_pk vi.chain_id op2 in + return_unit + + let check_double_preattestation_evidence vi + (operation : Kind.double_preattestation_evidence operation) = + let (Single (Double_preattestation_evidence {op1; op2})) = + operation.protocol_data.contents + in + check_double_attesting_evidence vi op1 op2 + + let check_double_attestation_evidence vi + (operation : Kind.double_attestation_evidence operation) = + let (Single (Double_attestation_evidence {op1; op2})) = + operation.protocol_data.contents + in + check_double_attesting_evidence vi op1 op2 + + let double_operation_conflict_key (type kind) + (op1 : kind Kind.consensus Operation.t) = + let {slot; level; round; block_payload_hash = _}, kind = + match op1.protocol_data.contents with + | Single (Preattestation cc) -> (cc, Misbehaviour.Double_preattesting) + | Single (Attestation {consensus_content; dal_content = _}) -> + (consensus_content, Double_attesting) + in + (level, round, slot, kind) + + let check_double_attesting_evidence_conflict (type kind) vs oph + (op1 : kind Kind.consensus Operation.t) = + match + Double_operation_evidence_map.find + (double_operation_conflict_key op1) + vs.anonymous_state.double_attesting_evidences_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let check_double_preattestation_evidence_conflict vs oph + (operation : Kind.double_preattestation_evidence operation) = + let (Single (Double_preattestation_evidence {op1; _})) = + operation.protocol_data.contents + in + check_double_attesting_evidence_conflict vs oph op1 + + let check_double_attestation_evidence_conflict vs oph + (operation : Kind.double_attestation_evidence operation) = + let (Single (Double_attestation_evidence {op1; _})) = + operation.protocol_data.contents + in + check_double_attesting_evidence_conflict vs oph op1 + + let wrap_denunciation_conflict kind = function + | Ok () -> ok_unit + | Error conflict -> result_error (Conflicting_denunciation {kind; conflict}) + + let add_double_attesting_evidence (type kind) vs oph + (op1 : kind Kind.consensus Operation.t) = + let double_attesting_evidences_seen = + Double_operation_evidence_map.add + (double_operation_conflict_key op1) + oph + vs.anonymous_state.double_attesting_evidences_seen + in + { + vs with + anonymous_state = + {vs.anonymous_state with double_attesting_evidences_seen}; + } + + let add_double_attestation_evidence vs oph + (operation : Kind.double_attestation_evidence operation) = + let (Single (Double_attestation_evidence {op1; _})) = + operation.protocol_data.contents + in + add_double_attesting_evidence vs oph op1 + + let add_double_preattestation_evidence vs oph + (operation : Kind.double_preattestation_evidence operation) = + let (Single (Double_preattestation_evidence {op1; _})) = + operation.protocol_data.contents + in + add_double_attesting_evidence vs oph op1 + + let remove_double_attesting_evidence (type kind) vs + (op : kind Kind.consensus Operation.t) = + let double_attesting_evidences_seen = + Double_operation_evidence_map.remove + (double_operation_conflict_key op) + vs.anonymous_state.double_attesting_evidences_seen + in + let anonymous_state = + {vs.anonymous_state with double_attesting_evidences_seen} + in + {vs with anonymous_state} + + let remove_double_preattestation_evidence vs + (operation : Kind.double_preattestation_evidence operation) = + let (Single (Double_preattestation_evidence {op1; _})) = + operation.protocol_data.contents + in + remove_double_attesting_evidence vs op1 + + let remove_double_attestation_evidence vs + (operation : Kind.double_attestation_evidence operation) = + let (Single (Double_attestation_evidence {op1; _})) = + operation.protocol_data.contents + in + remove_double_attesting_evidence vs op1 + + let check_double_baking_evidence vi + (operation : Kind.double_baking_evidence operation) = + let open Lwt_result_syntax in + let (Single (Double_baking_evidence {bh1; bh2})) = + operation.protocol_data.contents + in + let hash1 = Block_header.hash bh1 in + let hash2 = Block_header.hash bh2 in + let*? bh1_fitness = Fitness.from_raw bh1.shell.fitness in + let round1 = Fitness.round bh1_fitness in + let*? bh2_fitness = Fitness.from_raw bh2.shell.fitness in + let round2 = Fitness.round bh2_fitness in + let*? level1 = Raw_level.of_int32 bh1.shell.level in + let*? level2 = Raw_level.of_int32 bh2.shell.level in + let*? () = + error_unless + (Raw_level.(level1 = level2) + && Round.(round1 = round2) + && (* we require an order on hashes to avoid the existence of + equivalent evidences *) + Block_hash.(hash1 < hash2)) + (Invalid_double_baking_evidence + {hash1; level1; round1; hash2; level2; round2}) + in + let*? () = check_denunciation_age vi Double_baking level1 in + let level = Level.from_raw vi.ctxt level1 in + let committee_size = Constants.consensus_committee_size vi.ctxt in + let*? slot1 = Round.to_slot round1 ~committee_size in + let* ctxt, consensus_key1 = + Stake_distribution.slot_owner vi.ctxt level slot1 + in + let*? slot2 = Round.to_slot round2 ~committee_size in + let* ctxt, consensus_key2 = + Stake_distribution.slot_owner ctxt level slot2 + in + let delegate1, delegate2 = + (consensus_key1.delegate, consensus_key2.delegate) + in + let*? () = + error_unless + Signature.Public_key_hash.(delegate1 = delegate2) + (Inconsistent_denunciation {kind = Double_baking; delegate1; delegate2}) + in + let delegate_pk, delegate = (consensus_key1.consensus_pk, delegate1) in + let* already_slashed = + Delegate.already_denounced ctxt delegate level round1 Double_baking + in + let*? () = + error_unless + (not already_slashed) + (Already_denounced {kind = Double_baking; delegate; level}) + in + let*? () = Block_header.check_signature bh1 vi.chain_id delegate_pk in + let*? () = Block_header.check_signature bh2 vi.chain_id delegate_pk in + return_unit + + let check_double_baking_evidence_conflict vs oph + (operation : Kind.double_baking_evidence operation) = + let (Single (Double_baking_evidence {bh1; _})) = + operation.protocol_data.contents + in + let bh1_fitness = + Fitness.from_raw bh1.shell.fitness |> function + | Ok f -> f + | Error _ -> + (* We assume the operation valid, it cannot fail anymore *) + assert false + in + let round = Fitness.round bh1_fitness in + let level = Fitness.level bh1_fitness in + match + Double_baking_evidence_map.find + (level, round) + vs.anonymous_state.double_baking_evidences_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let add_double_baking_evidence vs oph + (operation : Kind.double_baking_evidence operation) = + let (Single (Double_baking_evidence {bh1; _})) = + operation.protocol_data.contents + in + let bh1_fitness = + Fitness.from_raw bh1.shell.fitness |> function + | Ok f -> f + | Error _ -> assert false + in + let round = Fitness.round bh1_fitness in + let level = Fitness.level bh1_fitness in + let double_baking_evidences_seen = + Double_baking_evidence_map.add + (level, round) + oph + vs.anonymous_state.double_baking_evidences_seen + in + { + vs with + anonymous_state = {vs.anonymous_state with double_baking_evidences_seen}; + } + + let remove_double_baking_evidence vs + (operation : Kind.double_baking_evidence operation) = + let (Single (Double_baking_evidence {bh1; _})) = + operation.protocol_data.contents + in + let bh1_fitness, level = + match + (Fitness.from_raw bh1.shell.fitness, Raw_level.of_int32 bh1.shell.level) + with + | Ok v, Ok v' -> (v, v') + | _ -> + (* The operation is valid therefore decoding cannot fail *) + assert false + in + let round = Fitness.round bh1_fitness in + let double_baking_evidences_seen = + Double_baking_evidence_map.remove + (level, round) + vs.anonymous_state.double_baking_evidences_seen + in + let anonymous_state = + {vs.anonymous_state with double_baking_evidences_seen} + in + {vs with anonymous_state} + + let check_drain_delegate info ~check_signature + (operation : Kind.drain_delegate Operation.t) = + let open Lwt_result_syntax in + let (Single (Drain_delegate {delegate; destination; consensus_key})) = + operation.protocol_data.contents + in + let*! is_registered = Delegate.registered info.ctxt delegate in + let* () = + fail_unless + is_registered + (Drain_delegate_on_unregistered_delegate delegate) + in + let* active_pk = Delegate.Consensus_key.active_pubkey info.ctxt delegate in + let* () = + fail_unless + (Signature.Public_key_hash.equal active_pk.consensus_pkh consensus_key) + (Invalid_drain_delegate_inactive_key + { + delegate; + consensus_key; + active_consensus_key = active_pk.consensus_pkh; + }) + in + let* () = + fail_when + (Signature.Public_key_hash.equal active_pk.consensus_pkh delegate) + (Invalid_drain_delegate_no_consensus_key delegate) + in + let* () = + fail_when + (Signature.Public_key_hash.equal destination delegate) + (Invalid_drain_delegate_noop delegate) + in + let*! is_destination_allocated = + Contract.allocated info.ctxt (Contract.Implicit destination) + in + let* balance = + Contract.get_balance info.ctxt (Contract.Implicit delegate) + in + let*? origination_burn = + if is_destination_allocated then Ok Tez.zero + else + let cost_per_byte = Constants.cost_per_byte info.ctxt in + let origination_size = Constants.origination_size info.ctxt in + Tez.(cost_per_byte *? Int64.of_int origination_size) + in + let* drain_fees = + let*? one_percent = Tez.(balance /? 100L) in + return Tez.(max one one_percent) + in + let*? min_amount = Tez.(origination_burn +? drain_fees) in + let* () = + fail_when + Tez.(balance < min_amount) + (Invalid_drain_delegate_insufficient_funds_for_burn_or_fees + {delegate; destination; min_amount}) + in + let*? () = + if check_signature then + Operation.check_signature active_pk.consensus_pk info.chain_id operation + else ok_unit + in + return_unit + + let check_drain_delegate_conflict state oph + (operation : Kind.drain_delegate Operation.t) = + let (Single (Drain_delegate {delegate; _})) = + operation.protocol_data.contents + in + match + Signature.Public_key_hash.Map.find_opt + delegate + state.manager_state.managers_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_drain_delegate_conflict (operation : Kind.drain_delegate Operation.t) + = + let (Single (Drain_delegate {delegate; _})) = + operation.protocol_data.contents + in + function + | Ok () -> ok_unit + | Error conflict -> + result_error (Conflicting_drain_delegate {delegate; conflict}) + + let add_drain_delegate state oph (operation : Kind.drain_delegate Operation.t) + = + let (Single (Drain_delegate {delegate; _})) = + operation.protocol_data.contents + in + let managers_seen = + Signature.Public_key_hash.Map.add + delegate + oph + state.manager_state.managers_seen + in + {state with manager_state = {managers_seen}} + + let remove_drain_delegate state (operation : Kind.drain_delegate Operation.t) + = + let (Single (Drain_delegate {delegate; _})) = + operation.protocol_data.contents + in + let managers_seen = + Signature.Public_key_hash.Map.remove + delegate + state.manager_state.managers_seen + in + {state with manager_state = {managers_seen}} + + let check_seed_nonce_revelation vi + (operation : Kind.seed_nonce_revelation operation) = + let open Lwt_result_syntax in + let (Single (Seed_nonce_revelation {level = commitment_raw_level; nonce})) = + operation.protocol_data.contents + in + let commitment_level = Level.from_raw vi.ctxt commitment_raw_level in + let* () = Nonce.check_unrevealed vi.ctxt commitment_level nonce in + return_unit + + let check_seed_nonce_revelation_conflict vs oph + (operation : Kind.seed_nonce_revelation operation) = + let (Single (Seed_nonce_revelation {level = commitment_raw_level; _})) = + operation.protocol_data.contents + in + match + Raw_level.Map.find_opt + commitment_raw_level + vs.anonymous_state.seed_nonce_levels_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_seed_nonce_revelation_conflict = function + | Ok () -> ok_unit + | Error conflict -> result_error (Conflicting_nonce_revelation conflict) + + let add_seed_nonce_revelation vs oph + (operation : Kind.seed_nonce_revelation operation) = + let (Single (Seed_nonce_revelation {level = commitment_raw_level; _})) = + operation.protocol_data.contents + in + let seed_nonce_levels_seen = + Raw_level.Map.add + commitment_raw_level + oph + vs.anonymous_state.seed_nonce_levels_seen + in + let anonymous_state = {vs.anonymous_state with seed_nonce_levels_seen} in + {vs with anonymous_state} + + let remove_seed_nonce_revelation vs + (operation : Kind.seed_nonce_revelation operation) = + let (Single (Seed_nonce_revelation {level = commitment_raw_level; _})) = + operation.protocol_data.contents + in + let seed_nonce_levels_seen = + Raw_level.Map.remove + commitment_raw_level + vs.anonymous_state.seed_nonce_levels_seen + in + let anonymous_state = {vs.anonymous_state with seed_nonce_levels_seen} in + {vs with anonymous_state} + + let check_vdf_revelation vi (operation : Kind.vdf_revelation operation) = + let open Lwt_result_syntax in + let (Single (Vdf_revelation {solution})) = + operation.protocol_data.contents + in + let* () = Seed.check_vdf vi.ctxt solution in + return_unit + + let check_vdf_revelation_conflict vs oph = + match vs.anonymous_state.vdf_solution_seen with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_vdf_revelation_conflict = function + | Ok () -> ok_unit + | Error conflict -> result_error (Conflicting_vdf_revelation conflict) + + let add_vdf_revelation vs oph = + { + vs with + anonymous_state = {vs.anonymous_state with vdf_solution_seen = Some oph}; + } + + let remove_vdf_revelation vs = + let anonymous_state = {vs.anonymous_state with vdf_solution_seen = None} in + {vs with anonymous_state} +end + +module Manager = struct + open Validate_errors.Manager + + (** State that simulates changes from individual operations that have + an effect on future operations inside the same batch. *) + type batch_state = { + balance : Tez.t; + (** Remaining balance in the contract, used to simulate the + payment of fees by each operation in the batch. *) + is_allocated : bool; + (** Track whether the contract is still allocated. Indeed, + previous operations' fee payment may empty the contract and + this may deallocate the contract. + + TODO: https://gitlab.com/tezos/tezos/-/issues/3209 Change + empty account cleanup mechanism to avoid the need for this + field. *) + total_gas_used : Gas.Arith.fp; + } + + let check_source_and_counter ~expected_source ~source ~previous_counter + ~counter = + let open Result_syntax in + let* () = + error_unless + (Signature.Public_key_hash.equal expected_source source) + Inconsistent_sources + in + error_unless + Manager_counter.(succ previous_counter = counter) + Inconsistent_counters + + let rec check_batch_tail_sanity : + type kind. + public_key_hash -> + Manager_counter.t -> + kind Kind.manager contents_list -> + unit tzresult = + let open Result_syntax in + fun expected_source previous_counter -> function + | Single (Manager_operation {operation = Reveal _key; _}) -> + tzfail Incorrect_reveal_position + | Cons (Manager_operation {operation = Reveal _key; _}, _res) -> + tzfail Incorrect_reveal_position + | Single (Manager_operation {source; counter; _}) -> + check_source_and_counter + ~expected_source + ~source + ~previous_counter + ~counter + | Cons (Manager_operation {source; counter; _}, rest) -> + let* () = + check_source_and_counter + ~expected_source + ~source + ~previous_counter + ~counter + in + check_batch_tail_sanity source counter rest + + let check_batch : + type kind. + kind Kind.manager contents_list -> + (public_key_hash * public_key option * Manager_counter.t) tzresult = + let open Result_syntax in + fun contents_list -> + match contents_list with + | Single (Manager_operation {source; operation = Reveal key; counter; _}) + -> + return (source, Some key, counter) + | Single (Manager_operation {source; counter; _}) -> + return (source, None, counter) + | Cons + (Manager_operation {source; operation = Reveal key; counter; _}, rest) + -> + let* () = check_batch_tail_sanity source counter rest in + return (source, Some key, counter) + | Cons (Manager_operation {source; counter; _}, rest) -> + let* () = check_batch_tail_sanity source counter rest in + return (source, None, counter) + + (** Check a few simple properties of the batch, and return the + initial {!batch_state} and the contract public key. + + Invariants checked: + + - All operations in a batch have the same source. + + - The source's contract is allocated. + + - The counters in a batch are successive, and the first of them + is the source's next expected counter. + + - A batch contains at most one Reveal operation that must occur + in first position. + + - The source's public key has been revealed (either before the + considered batch, or during its first operation). + + Note that currently, the [op] batch contains only one signature, + so all operations in the batch are required to originate from the + same manager. This may change in the future, in order to allow + several managers to group-sign a sequence of operations. *) + let check_sanity_and_find_public_key vi + (contents_list : _ Kind.manager contents_list) = + let open Lwt_result_syntax in + let*? source, revealed_key, first_counter = check_batch contents_list in + let* balance = Contract.check_allocated_and_get_balance vi.ctxt source in + let* () = Contract.check_counter_increment vi.ctxt source first_counter in + let* pk = + (* Note that it is important to always retrieve the public + key. This includes the case where the key ends up not being + used because the signature check is skipped in + {!validate_manager_operation} called with + [~check_signature:false]. Indeed, the mempool may use + this argument when it has already checked the signature of + the operation in the past; but if there has been a branch + reorganization since then, the key might not be revealed in + the new branch anymore, in which case + {!Contract.get_manager_key} will return an error. *) + match revealed_key with + | Some pk -> return pk + | None -> Contract.get_manager_key vi.ctxt source + in + let initial_batch_state = + { + balance; + (* Initial contract allocation is ensured by the success of + the call to {!Contract.check_allocated_and_get_balance} + above. *) + is_allocated = true; + total_gas_used = Gas.Arith.zero; + } + in + return (initial_batch_state, pk) + + let check_gas_limit info ~gas_limit = + Gas.check_gas_limit + ~hard_gas_limit_per_operation: + info.manager_info.hard_gas_limit_per_operation + ~gas_limit + + let check_storage_limit vi storage_limit = + error_unless + Compare.Z.( + storage_limit <= vi.manager_info.hard_storage_limit_per_operation + && storage_limit >= Z.zero) + Fees.Storage_limit_too_high + + let assert_pvm_kind_enabled vi kind = + let open Result_syntax in + let* () = + error_when + ((not (Constants.sc_rollup_arith_pvm_enable vi.ctxt)) + && Sc_rollup.Kind.(equal kind Example_arith)) + Sc_rollup_arith_pvm_disabled + in + error_when + ((not (Constants.sc_rollup_riscv_pvm_enable vi.ctxt)) + && Sc_rollup.Kind.(equal kind Riscv)) + Sc_rollup_riscv_pvm_disabled + + let assert_not_zero_messages messages = + match messages with + | [] -> result_error Sc_rollup_errors.Sc_rollup_add_zero_messages + | _ -> ok_unit + + let assert_zk_rollup_feature_enabled vi = + error_unless (Constants.zk_rollup_enable vi.ctxt) Zk_rollup_feature_disabled + + let consume_decoding_gas remaining_gas lexpr = + record_trace Gas_quota_exceeded_init_deserialize + @@ (* Fail early if the operation does not have enough gas to + cover the deserialization cost. We always consider the full + deserialization cost, independently from the internal state + of the lazy_expr. Otherwise we might risk getting different + results if the operation has already been deserialized + before (e.g. when retrieved in JSON format). Note that the + lazy_expr is not actually decoded here; its deserialization + cost is estimated from the size of its bytes. *) + Script.consume_decoding_gas remaining_gas lexpr + + let may_trace_gas_limit_too_high info = + match info.mode with + | Application _ | Partial_validation _ | Construction _ -> fun x -> x + | Mempool -> + (* [Gas.check_limit] will only + raise a "temporary" error, however when + {!validate_operation} is called on a batch in isolation + (like e.g. in the mempool) it must "refuse" operations + whose total gas limit (the sum of the [gas_limit]s of each + operation) is already above the block limit. We add the + "permanent" error [Gas.Gas_limit_too_high] on top of the + trace to this effect. *) + record_trace Gas.Gas_limit_too_high + + let check_kind_specific_content (type kind) + (contents : kind Kind.manager contents) remaining_gas vi = + let open Result_syntax in + let (Manager_operation + { + source; + fee = _; + counter = _; + operation; + gas_limit = _; + storage_limit = _; + }) = + contents + in + match operation with + | Reveal pk -> Contract.check_public_key pk source + | Transaction {parameters; _} -> + let* (_ : Gas.Arith.fp) = + consume_decoding_gas remaining_gas parameters + in + return_unit + | Origination {script; _} -> + let* remaining_gas = consume_decoding_gas remaining_gas script.code in + let* (_ : Gas.Arith.fp) = + consume_decoding_gas remaining_gas script.storage + in + return_unit + | Register_global_constant {value} -> + let* (_ : Gas.Arith.fp) = consume_decoding_gas remaining_gas value in + return_unit + | Delegation (Some pkh) -> Delegate.check_not_tz4 pkh + | Update_consensus_key pk -> Delegate.Consensus_key.check_not_tz4 pk + | Delegation None | Set_deposits_limit _ | Increase_paid_storage _ -> + return_unit + | Transfer_ticket {contents; ty; _} -> + let* remaining_gas = consume_decoding_gas remaining_gas contents in + let* (_ : Gas.Arith.fp) = consume_decoding_gas remaining_gas ty in + return_unit + | Sc_rollup_originate {kind; _} -> assert_pvm_kind_enabled vi kind + | Sc_rollup_add_messages {messages; _} -> assert_not_zero_messages messages + | Sc_rollup_cement _ | Sc_rollup_publish _ | Sc_rollup_refute _ + | Sc_rollup_timeout _ | Sc_rollup_execute_outbox_message _ + | Sc_rollup_recover_bond _ -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3063 + Should we successfully precheck Sc_rollup_recover_bond and any + (simple) Sc rollup operation, or should we add some some checks to make + the operations Branch_delayed if they cannot be successfully + prechecked? *) + return_unit + | Dal_publish_commitment slot_header -> + Dal_apply.validate_publish_commitment vi.ctxt slot_header + | Zk_rollup_origination _ | Zk_rollup_publish _ | Zk_rollup_update _ -> + assert_zk_rollup_feature_enabled vi + + let check_contents (type kind) vi batch_state + (contents : kind Kind.manager contents) ~consume_gas_for_sig_check + remaining_block_gas = + let open Lwt_result_syntax in + let (Manager_operation + {source; fee; counter = _; operation = _; gas_limit; storage_limit}) = + contents + in + let*? () = check_gas_limit vi ~gas_limit in + let total_gas_used = + Gas.Arith.(add batch_state.total_gas_used (fp gas_limit)) + in + let*? () = + may_trace_gas_limit_too_high vi + @@ error_unless + Gas.Arith.(fp total_gas_used <= remaining_block_gas) + Gas.Block_quota_exceeded + in + (* Part of the gas cost of the operation which is independent of + the contents of the operation. It is + Michelson_v1_gas.Cost_of.manager_operation constant plus the + cost of checking the signature if the operation is the first of + the batch. *) + let fixed_gas_cost = + let manager_op_cost = Michelson_v1_gas.Cost_of.manager_operation in + match consume_gas_for_sig_check with + | None -> manager_op_cost + | Some gas_for_sig_check -> Gas.(manager_op_cost +@ gas_for_sig_check) + in + let*? remaining_gas = + record_trace + Insufficient_gas_for_manager + (Gas.consume_from (Gas.Arith.fp gas_limit) fixed_gas_cost) + in + let*? () = check_storage_limit vi storage_limit in + let*? () = + (* {!Contract.must_be_allocated} has already been called while + initializing [batch_state]. This checks that the contract has + not been emptied by spending fees for previous operations in + the batch. *) + error_unless + batch_state.is_allocated + (Contract_storage.Empty_implicit_contract source) + in + let*? () = check_kind_specific_content contents remaining_gas vi in + (* Gas should no longer be consumed below this point, because it + would not take into account any gas consumed by + {!check_kind_specific_content}. If you really need to consume gas here, then you + must make {!check_kind_specific_content} return the [remaining_gas].*) + let* balance, is_allocated = + Contract.simulate_spending + vi.ctxt + ~balance:batch_state.balance + ~amount:fee + source + in + return {total_gas_used; balance; is_allocated} + + (** This would be [fold_left_es (check_contents vi) batch_state + contents_list] if [contents_list] were an ordinary [list]. The + [consume_gas_for_sig_check] arg indicates whether or not gas for + checking the signature of the batch should be consumed; it is + [None] if the cost has already been consumed and [Some cost] if + the cost to be consumed is [cost] and remains to be + consumed. This cost is consumed in the first operation of the + batch. *) + let rec check_contents_list : + type kind. + info -> + batch_state -> + kind Kind.manager contents_list -> + consume_gas_for_sig_check:Gas.cost option -> + Gas.Arith.fp -> + Gas.Arith.fp tzresult Lwt.t = + fun vi batch_state contents_list ~consume_gas_for_sig_check remaining_gas -> + let open Lwt_result_syntax in + match contents_list with + | Single contents -> + let* batch_state = + check_contents + vi + batch_state + contents + ~consume_gas_for_sig_check + remaining_gas + in + return batch_state.total_gas_used + | Cons (contents, tail) -> + let* batch_state = + check_contents + vi + batch_state + contents + ~consume_gas_for_sig_check + remaining_gas + in + check_contents_list + vi + batch_state + tail + ~consume_gas_for_sig_check:None + remaining_gas + + let check_manager_operation vi ~check_signature + (operation : _ Kind.manager operation) remaining_block_gas = + let open Lwt_result_syntax in + let contents_list = operation.protocol_data.contents in + let* batch_state, source_pk = + check_sanity_and_find_public_key vi contents_list + in + let signature_checking_gas_cost = + Operation_costs.check_signature_cost + (Michelson_v1_gas.Cost_of.Interpreter.algo_of_public_key source_pk) + operation + in + let* gas_used = + check_contents_list + vi + batch_state + contents_list + ~consume_gas_for_sig_check:(Some signature_checking_gas_cost) + remaining_block_gas + in + let*? () = + if check_signature then + Operation.check_signature source_pk vi.chain_id operation + else ok_unit + in + return gas_used + + let check_manager_operation_conflict (type kind) vs oph + (operation : kind Kind.manager operation) = + let source = + match operation.protocol_data.contents with + | Single (Manager_operation {source; _}) + | Cons (Manager_operation {source; _}, _) -> + source + in + (* One-operation-per-manager-per-block restriction (1M) *) + match + Signature.Public_key_hash.Map.find_opt + source + vs.manager_state.managers_seen + with + | None -> ok_unit + | Some existing -> + Error (Operation_conflict {existing; new_operation = oph}) + + let wrap_check_manager_operation_conflict (type kind) + (operation : kind Kind.manager operation) = + let source = + match operation.protocol_data.contents with + | Single (Manager_operation {source; _}) + | Cons (Manager_operation {source; _}, _) -> + source + in + function + | Ok () -> ok_unit + | Error conflict -> result_error (Manager_restriction {source; conflict}) + + let add_manager_operation (type kind) vs oph + (operation : kind Kind.manager operation) = + let source = + match operation.protocol_data.contents with + | Single (Manager_operation {source; _}) + | Cons (Manager_operation {source; _}, _) -> + source + in + let managers_seen = + Signature.Public_key_hash.Map.add + source + oph + vs.manager_state.managers_seen + in + {vs with manager_state = {managers_seen}} + + (* Return the new [block_state] with the updated remaining gas used: + - In non-mempool modes, this value is + [block_state.remaining_block_gas], in which the gas from the + validated operation has been subtracted. + + - In [Mempool] mode, the [block_state] should remain + unchanged. Indeed, we only want each batch to not exceed the + block limit individually, without taking other operations + into account. *) + let may_update_remaining_gas_used mode (block_state : block_state) + operation_gas_used = + match mode with + | Application _ | Partial_validation _ | Construction _ -> + let remaining_block_gas = + Gas.Arith.(sub block_state.remaining_block_gas operation_gas_used) + in + {block_state with remaining_block_gas} + | Mempool -> block_state + + let remove_manager_operation (type kind) vs + (operation : kind Kind.manager operation) = + let source = + match operation.protocol_data.contents with + | Single (Manager_operation {source; _}) + | Cons (Manager_operation {source; _}, _) -> + source + in + let managers_seen = + Signature.Public_key_hash.Map.remove source vs.manager_state.managers_seen + in + {vs with manager_state = {managers_seen}} + + let validate_manager_operation ~check_signature info operation_state + block_state oph operation = + let open Lwt_result_syntax in + let* gas_used = + check_manager_operation + info + ~check_signature + operation + block_state.remaining_block_gas + in + let*? () = + check_manager_operation_conflict operation_state oph operation + |> wrap_check_manager_operation_conflict operation + in + let operation_state = add_manager_operation operation_state oph operation in + let block_state = + may_update_remaining_gas_used info.mode block_state gas_used + in + return {info; operation_state; block_state} +end + +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 operation_state = empty_operation_conflict_state in + let block_state = init_block_state info in + {info; operation_state; block_state} + +(* Pre-condition: Shell block headers' checks have already been done. + These checks must ensure that: + - the block header level is the succ of the predecessor block level + - the timestamp of the predecessor is lower than the current block's + - the fitness of the block is greater than its predecessor's + - the number of operations by validation passes does not exceed the quota + established by the protocol + - the size of an operation does not exceed [max_operation_data_length] +*) +let begin_any_application ctxt chain_id ~predecessor_level + ~predecessor_timestamp (block_header : Block_header.t) fitness ~is_partial = + let open Lwt_result_syntax in + let predecessor_round = Fitness.predecessor_round fitness in + let round = Fitness.round fitness in + let current_level = Level.current ctxt in + let* ctxt, _slot, block_producer = + Stake_distribution.baking_rights_owner ctxt current_level ~round + in + let*? () = + Block_header.begin_validate_block_header + ~block_header + ~chain_id + ~predecessor_timestamp + ~predecessor_round + ~fitness + ~timestamp:block_header.shell.timestamp + ~delegate_pk:block_producer.consensus_pk + ~round_durations:(Constants.round_durations ctxt) + ~proof_of_work_threshold:(Constants.proof_of_work_threshold ctxt) + ~expected_commitment:current_level.expected_commitment + in + let* () = + Consensus.check_delegate_is_not_forbidden ctxt block_producer.delegate + in + let* ctxt, _slot, _payload_producer = + (* We just make sure that this call will not fail in apply.ml *) + Stake_distribution.baking_rights_owner + ctxt + current_level + ~round:block_header.protocol_data.contents.payload_round + in + let predecessor_hash = block_header.shell.predecessor in + let block_info = + { + round; + locked_round = Fitness.locked_round fitness; + predecessor_hash; + header_contents = block_header.protocol_data.contents; + } + in + let mode = + if is_partial then Partial_validation block_info else Application block_info + in + let validation_state = + init_validation_state + ctxt + mode + chain_id + ~predecessor_level_and_round: + (Some (predecessor_level.Level.level, predecessor_round)) + in + return validation_state + +let begin_partial_validation ctxt chain_id ~predecessor_level + ~predecessor_timestamp block_header fitness = + begin_any_application + ctxt + chain_id + ~predecessor_level + ~predecessor_timestamp + block_header + fitness + ~is_partial:true + +let begin_application ctxt chain_id ~predecessor_level ~predecessor_timestamp + block_header fitness = + begin_any_application + ctxt + chain_id + ~predecessor_level + ~predecessor_timestamp + block_header + fitness + ~is_partial:false + +let begin_full_construction ctxt chain_id ~predecessor_level ~predecessor_round + ~predecessor_timestamp ~predecessor_hash round + (header_contents : Block_header.contents) = + let open Lwt_result_syntax in + let round_durations = Constants.round_durations ctxt in + let timestamp = Timestamp.current ctxt in + let*? () = + Block_header.check_timestamp + round_durations + ~timestamp + ~round + ~predecessor_timestamp + ~predecessor_round + in + let current_level = Level.current ctxt in + let* ctxt, _slot, block_producer = + Stake_distribution.baking_rights_owner ctxt current_level ~round + in + let* () = + Consensus.check_delegate_is_not_forbidden ctxt block_producer.delegate + in + let* ctxt, _slot, _payload_producer = + (* We just make sure that this call will not fail in apply.ml *) + Stake_distribution.baking_rights_owner + ctxt + current_level + ~round:header_contents.payload_round + in + let validation_state = + init_validation_state + ctxt + (Construction {round; predecessor_hash; header_contents}) + chain_id + ~predecessor_level_and_round: + (Some (predecessor_level.Level.level, predecessor_round)) + in + return validation_state + +let begin_partial_construction ctxt chain_id ~predecessor_level + ~predecessor_round = + let validation_state = + init_validation_state + ctxt + Mempool + chain_id + ~predecessor_level_and_round: + (Some (predecessor_level.Level.level, predecessor_round)) + in + validation_state + +let begin_no_predecessor_info ctxt chain_id = + init_validation_state ctxt Mempool chain_id ~predecessor_level_and_round:None + +let check_operation ?(check_signature = true) info (type kind) + (operation : kind operation) : unit tzresult Lwt.t = + let open Lwt_result_syntax in + match operation.protocol_data.contents with + | Single (Preattestation _) -> + let* (_voting_power : int) = + Consensus.check_preattestation info ~check_signature operation + in + return_unit + | Single (Attestation _) -> + let* (_voting_power : int) = + Consensus.check_attestation info ~check_signature operation + in + return_unit + | Single (Proposals _) -> + Voting.check_proposals info ~check_signature operation + | Single (Ballot _) -> Voting.check_ballot info ~check_signature operation + | Single (Activate_account _) -> + Anonymous.check_activate_account info operation + | Single (Double_preattestation_evidence _) -> + Anonymous.check_double_preattestation_evidence info operation + | Single (Double_attestation_evidence _) -> + Anonymous.check_double_attestation_evidence info operation + | Single (Double_baking_evidence _) -> + Anonymous.check_double_baking_evidence info operation + | Single (Drain_delegate _) -> + Anonymous.check_drain_delegate info ~check_signature operation + | Single (Seed_nonce_revelation _) -> + Anonymous.check_seed_nonce_revelation info operation + | Single (Vdf_revelation _) -> Anonymous.check_vdf_revelation info operation + | Single (Manager_operation _) -> + let remaining_gas = + Gas.Arith.fp (Constants.hard_gas_limit_per_block info.ctxt) + in + let* (_remaining_gas : Gas.Arith.fp) = + Manager.check_manager_operation + info + ~check_signature + operation + remaining_gas + in + return_unit + | Cons (Manager_operation _, _) -> + let remaining_gas = + Gas.Arith.fp (Constants.hard_gas_limit_per_block info.ctxt) + in + let* (_remaining_gas : Gas.Arith.fp) = + Manager.check_manager_operation + info + ~check_signature + operation + remaining_gas + in + return_unit + | Single (Failing_noop _) -> tzfail Validate_errors.Failing_noop_error + +let check_operation_conflict (type kind) operation_conflict_state oph + (operation : kind operation) = + match operation.protocol_data.contents with + | Single (Preattestation _) -> + Consensus.check_preattestation_conflict + operation_conflict_state + oph + operation + | Single (Attestation _) -> + Consensus.check_attestation_conflict + operation_conflict_state + oph + operation + | Single (Proposals _) -> + Voting.check_proposals_conflict operation_conflict_state oph operation + | Single (Ballot _) -> + Voting.check_ballot_conflict operation_conflict_state oph operation + | Single (Activate_account _) -> + Anonymous.check_activate_account_conflict + operation_conflict_state + oph + operation + | Single (Double_preattestation_evidence _) -> + Anonymous.check_double_preattestation_evidence_conflict + operation_conflict_state + oph + operation + | Single (Double_attestation_evidence _) -> + Anonymous.check_double_attestation_evidence_conflict + operation_conflict_state + oph + operation + | Single (Double_baking_evidence _) -> + Anonymous.check_double_baking_evidence_conflict + operation_conflict_state + oph + operation + | Single (Drain_delegate _) -> + Anonymous.check_drain_delegate_conflict + operation_conflict_state + oph + operation + | Single (Seed_nonce_revelation _) -> + Anonymous.check_seed_nonce_revelation_conflict + operation_conflict_state + oph + operation + | Single (Vdf_revelation _) -> + Anonymous.check_vdf_revelation_conflict operation_conflict_state oph + | Single (Manager_operation _) -> + Manager.check_manager_operation_conflict + operation_conflict_state + oph + operation + | Cons (Manager_operation _, _) -> + Manager.check_manager_operation_conflict + operation_conflict_state + oph + operation + | Single (Failing_noop _) -> (* Nothing to do *) ok_unit + +let add_valid_operation operation_conflict_state oph (type kind) + (operation : kind operation) = + match operation.protocol_data.contents with + | Single (Preattestation _) -> + Consensus.add_preattestation operation_conflict_state oph operation + | Single (Attestation _) -> + Consensus.add_attestation operation_conflict_state oph operation + | Single (Proposals _) -> + Voting.add_proposals operation_conflict_state oph operation + | Single (Ballot _) -> + Voting.add_ballot operation_conflict_state oph operation + | Single (Activate_account _) -> + Anonymous.add_activate_account operation_conflict_state oph operation + | Single (Double_preattestation_evidence _) -> + Anonymous.add_double_preattestation_evidence + operation_conflict_state + oph + operation + | Single (Double_attestation_evidence _) -> + Anonymous.add_double_attestation_evidence + operation_conflict_state + oph + operation + | Single (Double_baking_evidence _) -> + Anonymous.add_double_baking_evidence + operation_conflict_state + oph + operation + | Single (Drain_delegate _) -> + Anonymous.add_drain_delegate operation_conflict_state oph operation + | Single (Seed_nonce_revelation _) -> + Anonymous.add_seed_nonce_revelation operation_conflict_state oph operation + | Single (Vdf_revelation _) -> + Anonymous.add_vdf_revelation operation_conflict_state oph + | Single (Manager_operation _) -> + Manager.add_manager_operation operation_conflict_state oph operation + | Cons (Manager_operation _, _) -> + Manager.add_manager_operation operation_conflict_state oph operation + | Single (Failing_noop _) -> (* Nothing to do *) operation_conflict_state + +(* Hypothesis: + - the [operation] has been validated and is present in [vs]; + - this function is only valid for the mempool mode. *) +let remove_operation operation_conflict_state (type kind) + (operation : kind operation) = + match operation.protocol_data.contents with + | Single (Preattestation _) -> + Consensus.remove_preattestation operation_conflict_state operation + | Single (Attestation _) -> + Consensus.remove_attestation operation_conflict_state operation + | Single (Proposals _) -> + Voting.remove_proposals operation_conflict_state operation + | Single (Ballot _) -> Voting.remove_ballot operation_conflict_state operation + | Single (Activate_account _) -> + Anonymous.remove_activate_account operation_conflict_state operation + | Single (Double_preattestation_evidence _) -> + Anonymous.remove_double_preattestation_evidence + operation_conflict_state + operation + | Single (Double_attestation_evidence _) -> + Anonymous.remove_double_attestation_evidence + operation_conflict_state + operation + | Single (Double_baking_evidence _) -> + Anonymous.remove_double_baking_evidence operation_conflict_state operation + | Single (Drain_delegate _) -> + Anonymous.remove_drain_delegate operation_conflict_state operation + | Single (Seed_nonce_revelation _) -> + Anonymous.remove_seed_nonce_revelation operation_conflict_state operation + | Single (Vdf_revelation _) -> + Anonymous.remove_vdf_revelation operation_conflict_state + | Single (Manager_operation _) -> + Manager.remove_manager_operation operation_conflict_state operation + | Cons (Manager_operation _, _) -> + Manager.remove_manager_operation operation_conflict_state operation + | Single (Failing_noop _) -> (* Nothing to do *) operation_conflict_state + +let check_validation_pass_consistency vi vs validation_pass = + let open Lwt_result_syntax in + match vi.mode with + | Mempool | Construction _ -> return vs + | Application _ | Partial_validation _ -> ( + match (vs.last_op_validation_pass, validation_pass) with + | None, validation_pass -> + return {vs with last_op_validation_pass = validation_pass} + | Some previous_vp, Some validation_pass -> + let* () = + fail_unless + Compare.Int.(previous_vp <= validation_pass) + (Validate_errors.Block.Inconsistent_validation_passes_in_block + {expected = previous_vp; provided = validation_pass}) + in + return {vs with last_op_validation_pass = Some validation_pass} + | Some _, None -> tzfail Validate_errors.Failing_noop_error) + +(** Increment [vs.op_count] for all operations, and record + non-consensus operation hashes in [vs.recorded_operations_rev]. *) +let record_operation vs ophash validation_pass_opt = + let op_count = vs.op_count + 1 in + match validation_pass_opt with + | Some n when Compare.Int.(n = Operation_repr.consensus_pass) -> + {vs with op_count} + | _ -> + { + vs with + op_count; + recorded_operations_rev = ophash :: vs.recorded_operations_rev; + } + +let validate_operation ?(check_signature = true) + {info; operation_state; block_state} oph + (packed_operation : packed_operation) = + let open Lwt_result_syntax in + let {shell; protocol_data = Operation_data protocol_data} = + packed_operation + in + let validation_pass_opt = Operation.acceptable_pass packed_operation in + let* block_state = + check_validation_pass_consistency info block_state validation_pass_opt + in + let block_state = record_operation block_state oph validation_pass_opt in + let operation : _ operation = {shell; protocol_data} in + match (info.mode, validation_pass_opt) with + | Partial_validation _, Some n + when Compare.Int.(n <> Operation_repr.consensus_pass) -> + (* Do not validate non-consensus operations in + [Partial_validation] mode. *) + return {info; operation_state; block_state} + | (Application _ | Partial_validation _ | Construction _ | Mempool), _ -> ( + match operation.protocol_data.contents with + | Single (Preattestation _) -> + Consensus.validate_preattestation + ~check_signature + info + operation_state + block_state + oph + operation + | Single (Attestation _) -> + Consensus.validate_attestation + ~check_signature + info + operation_state + block_state + oph + operation + | Single (Proposals _) -> + let open Voting in + let* () = check_proposals info ~check_signature operation in + let*? () = + check_proposals_conflict operation_state oph operation + |> wrap_proposals_conflict + in + let operation_state = add_proposals operation_state oph operation in + return {info; operation_state; block_state} + | Single (Ballot _) -> + let open Voting in + let* () = check_ballot info ~check_signature operation in + let*? () = + check_ballot_conflict operation_state oph operation + |> wrap_ballot_conflict + in + let operation_state = add_ballot operation_state oph operation in + return {info; operation_state; block_state} + | Single (Activate_account _) -> + let open Anonymous in + let* () = check_activate_account info operation in + let*? () = + check_activate_account_conflict operation_state oph operation + |> wrap_activate_account_conflict operation + in + let operation_state = + add_activate_account operation_state oph operation + in + return {info; operation_state; block_state} + | Single (Double_preattestation_evidence _) -> + let open Anonymous in + let* () = check_double_preattestation_evidence info operation in + let*? () = + check_double_preattestation_evidence_conflict + operation_state + oph + operation + |> wrap_denunciation_conflict Double_preattesting + in + let operation_state = + add_double_preattestation_evidence operation_state oph operation + in + return {info; operation_state; block_state} + | Single (Double_attestation_evidence _) -> + let open Anonymous in + let* () = check_double_attestation_evidence info operation in + let*? () = + check_double_attestation_evidence_conflict + operation_state + oph + operation + |> wrap_denunciation_conflict Double_attesting + in + let operation_state = + add_double_attestation_evidence operation_state oph operation + in + return {info; operation_state; block_state} + | Single (Double_baking_evidence _) -> + let open Anonymous in + let* () = check_double_baking_evidence info operation in + let*? () = + check_double_baking_evidence_conflict operation_state oph operation + |> wrap_denunciation_conflict Double_baking + in + let operation_state = + add_double_baking_evidence operation_state oph operation + in + return {info; operation_state; block_state} + | Single (Drain_delegate _) -> + let open Anonymous in + let* () = check_drain_delegate info ~check_signature operation in + let*? () = + check_drain_delegate_conflict operation_state oph operation + |> wrap_drain_delegate_conflict operation + in + let operation_state = + add_drain_delegate operation_state oph operation + in + return {info; operation_state; block_state} + | Single (Seed_nonce_revelation _) -> + let open Anonymous in + let* () = check_seed_nonce_revelation info operation in + let*? () = + check_seed_nonce_revelation_conflict operation_state oph operation + |> wrap_seed_nonce_revelation_conflict + in + let operation_state = + add_seed_nonce_revelation operation_state oph operation + in + return {info; operation_state; block_state} + | Single (Vdf_revelation _) -> + let open Anonymous in + let* () = check_vdf_revelation info operation in + let*? () = + check_vdf_revelation_conflict operation_state oph + |> wrap_vdf_revelation_conflict + in + let operation_state = add_vdf_revelation operation_state oph in + return {info; operation_state; block_state} + | Single (Manager_operation _) -> + Manager.validate_manager_operation + ~check_signature + info + operation_state + block_state + oph + operation + | Cons (Manager_operation _, _) -> + Manager.validate_manager_operation + ~check_signature + info + operation_state + block_state + oph + operation + | Single (Failing_noop _) -> tzfail Validate_errors.Failing_noop_error) + +(** Block finalization *) + +open Validate_errors.Block + +let check_attestation_power vi bs = + let open Lwt_result_syntax in + let* are_attestations_required = + (* The migration block (whose level is [first_level_of_protocol]) + is always considered final, and is not attested. Therefore, the + block at the next level does not need to contain attestations. + (Note that the migration block itself is validated by the + previous protocol, so the returned value for it does not matter.) *) + let* first_level_of_protocol = First_level_of_protocol.get vi.ctxt in + let level_position_in_protocol = + Raw_level.diff vi.current_level.level first_level_of_protocol + in + return Compare.Int32.(level_position_in_protocol > 1l) + in + if are_attestations_required then + let required = Constants.consensus_threshold vi.ctxt in + let provided = bs.attestation_power in + fail_unless + Compare.Int.(provided >= required) + (Not_enough_attestations {required; provided}) + else return_unit + +(** Check that the locked round in the fitness and the locked round + observed in the preattestations are the same. + + This check is not called in construction mode because there is + no provided fitness (meaning that we do not know whether the block + should contain any preattestations). + + When the observed locked round is [Some _], we actually already + know that it is identical to the fitness locked round, otherwise + {!Consensus.check_preexisting_block_preattestation} would have + rejected the preattestations. But this check is needed to reject + blocks where the fitness locked round has a value yet there are no + preattestations (ie. the observed locked round is [None]). *) +let check_fitness_locked_round bs fitness_locked_round = + let observed_locked_round = Option.map fst bs.locked_round_evidence in + error_unless + (Option.equal Round.equal observed_locked_round fitness_locked_round) + Fitness.Wrong_fitness + +(** When there are preattestations, check that they point to a round + before the block's round, and that their total power is high enough. + + Note that this function does not check whether the block actually + contains preattestations when they are mandatory. This is checked by + {!check_fitness_locked_round} instead. *) +let check_preattestation_round_and_power vi vs round = + let open Result_syntax in + match vs.locked_round_evidence with + | None -> ok_unit + | Some (preattestation_round, preattestation_count) -> + let* () = + (* Actually, this check should never fail, because we have + already called {!Consensus.check_round_before_block} for + all preattestations in a block. Nevertheless, it does not + cost much to check again here. *) + error_when + Round.(preattestation_round >= round) + (Locked_round_after_block_round + {locked_round = preattestation_round; round}) + in + let consensus_threshold = Constants.consensus_threshold vi.ctxt in + error_when + Compare.Int.(preattestation_count < consensus_threshold) + (Insufficient_locked_round_evidence + {voting_power = preattestation_count; consensus_threshold}) + +let check_payload_hash block_state ~predecessor_hash + (block_header_contents : Block_header.contents) = + let expected = + Block_payload.hash + ~predecessor_hash + ~payload_round:block_header_contents.payload_round + (List.rev block_state.recorded_operations_rev) + in + let provided = block_header_contents.payload_hash in + error_unless + (Block_payload_hash.equal expected provided) + (Invalid_payload_hash {expected; provided}) + +let finalize_block {info; block_state; _} = + let open Lwt_result_syntax in + match info.mode with + | Application {round; locked_round; predecessor_hash; header_contents} -> + let* () = check_attestation_power info block_state in + let*? () = check_fitness_locked_round block_state locked_round in + let*? () = check_preattestation_round_and_power info block_state round in + let*? () = + check_payload_hash block_state ~predecessor_hash header_contents + in + return_unit + | Partial_validation {round; locked_round; _} -> + let* () = check_attestation_power info block_state in + let*? () = check_fitness_locked_round block_state locked_round in + let*? () = check_preattestation_round_and_power info block_state round in + return_unit + | Construction {round; predecessor_hash; header_contents} -> + let* () = check_attestation_power info block_state in + let*? () = check_preattestation_round_and_power info block_state round in + let*? () = + match block_state.locked_round_evidence with + | Some _ -> + check_payload_hash block_state ~predecessor_hash header_contents + | None -> + (* In construction mode, when there is no locked round + evidence (ie. no preattestations), the baker cannot know + the payload hash before selecting the operations. + Therefore, we do not check the initially given payload + hash. The baker will have to patch the resulting block + header with the actual payload hash afterwards. *) + ok_unit + in + return_unit + | Mempool -> + (* There is no block to finalize in mempool mode. *) + return_unit diff --git a/src/proto_020_PsParisC/lib_protocol/validate.mli b/src/proto_020_PsParisC/lib_protocol/validate.mli new file mode 100644 index 000000000000..1afd0828ca0c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/validate.mli @@ -0,0 +1,339 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides functions pertaining to the validation of + blocks and operations. Most elements in this module are either used + or wrapped in the {!Main} module (though some of them are also + directly used by the plugin). + + The purpose of validation is to decide quickly whether a block or + an operation is valid, with minimal computations and without + writing anything in the storage. A block is considered valid if it + can be applied without failure (see {!Apply}). An operation is + valid if it can be safely included in a block without causing it to + fail. Therefore, the current module is responsible for ensuring + that calling functions from {!Apply} on validated blocks and + operations will not fail. + + {2 Block validation} + + The process of validation of a block may be started by calling one + of the following functions, depending on the circumstances (aka + mode): + + - [begin_application] is used for the validation of a preexisting + block, typically received through the network, and usually in + preparation for its future application. + + - [begin_partial_validation] is used to quickly but partially + validate an existing block. It is intended for quickly assessing a + series of blocks in an alternate branch (multipass validation). For + this reason, in this mode, the initial {!Alpha_context.t} may be + based on an ancestor block of the block to validate, instead of + necessarily its predecessor as in other modes. + + - [begin_full_construction] is used for the construction of a new + block, typically by a baker. + + Then, [validate_operation] should be called on every operation in + the block (in order of validation pass: see + {!Operation_repr.acceptable_pass}). Lastly, [finalize_block] + performs final checks on the block; if this function succeeds then + the block is valid. + + {2 Validation state} + + The process of block validation relies on a [validation_state] + transmitted throughout the aforementioned function calls. More + precisely, this immutable functional state is initialized by the + [begin_...] functions, read and updated by [validate_operation] + (as in, a slightly different [validation_state] is returned), and + required by [finalize_block]. It consists in three fields: + + - [info] contains static information required by + [validate_operation] and [finalize_block], notably the initial + {!Alpha_context.t}. It is fully filled in by the [begin_...] + functions, then only read, never updated. + + - [operation_conflict_state] keeps track of every validated + operation in the block, so that it can detect any conflict between + operations (e.g. two manager operations from the same + source). Consequently, it is both filled in and read by + [validate_operation], but not used at all by [finalize_block]. + + - [block_state] registers global block metrics such as total gas + used or attestation power. It is filled in by [validate_operation], + which also uses it, e.g. to immediately return an error if the + block gas limit is exceeded. It is also essential to several checks + in [finalize_block]. + + The immutability of the [validation_state] allows the caller to + pause, replay, or backtrack throughout the steps of the validation + process. + + {2 Operation validation} + + Operations may be validated either as part of the validation of a + block in which they are included (see above), or on their own: + + - [begin_partial_construction] allows to initialize a + [validation_state] for the validation of operations outside of the + process of validation of a block. It is intended for mempools (see + {!Mempool_validation}) and for some RPCs. The global block + properties such as total block gas and attestation power are not + checked. Calling [finalize_block] on such a [validation_state] does + not make much sense and simply returns unit. + + - [begin_no_predecessor_info] is a special weaker version of + [begin_partial_construction]: see its own documentation below. + + Even outside of the context of a given block validation, the + validation of operations aims at deciding whether they could + theoretically be included in a future block. Indeed, for a mempool, + this means that they are worth transmitting to a baker and + propagating to peers; or for the caller of an RPC, it means that + the tested operations may be injected in the node. + + An important property to maintain is that applying (see + {!Apply.apply_operation}) any subset of validated operations should + always succeed, even if they are not applied in the same order as + they were validated (as long as the order of application respects + the validation passes ordering). In other words, for all operations + A and B that have both been validated: if A has an earlier or the + same validation pass as B, then applying A then B must succeed; and + if B has an earlier or the same validation pass as A, then applying + B then A must succeed. Some restrictions, such as + one-operation-per-manager-per-block (1M), have been introduced to + preserve this property, and are enforced with the help of the + [operation_conflict_state]. An important consequence of this + property is that a baker may select any subset of validated + operations to bake into a new block, which is then guaranteed to be + applicable (provided that it verifies some additional global + properties such as including enough (pre)attesting power; the + baker is responsible for ensuring this). + + For a manager operation, validity is mainly solvability, ie. the + operation must be well-formed and we must be able to take its + fees. Indeed, this is sufficient for the safe inclusion of the + operation in a block: even if there is an error during the + subsequent application of the manager operation, this will cause + the operation to have no further effects, but won't impact the + success of the block's application. The solvability of a manager + operation notably requires that it is correctly signed: indeed, we + can't take anything from a manager without having checked their + signature. + + A non-manager operation is only valid if its effects can be fully + applied in an {!Alpha_context.t} without failure. Indeed, any error + during the application of such an operation would cause the whole + block to fail; unlike manager operations, there is no notion of + failing to have an effect without impacting the application of the + whole block. More detailled documentation on checks performed and + potential errors can be found in the [validate.ml] file for some + non-manager operations. *) + +open Alpha_context +open Validate_errors + +(** Static information required to validate blocks and operations. *) +type info + +(** State used to keep track of previously validated operations and + detect potential conflicts. This state is serializable which allows + it to be exchanged with another source. See {!Mempool_validation}. *) +type operation_conflict_state + +(** Encoding for the [operation_conflict_state]. *) +val operation_conflict_state_encoding : operation_conflict_state Data_encoding.t + +(** State used to register global block properties which are relevant + to the validity of a block, e.g. the total gas used in the block so + far. This state is both used and updated by the [validate_operation] + function, and is also required by [finalize_block]. *) +type block_state + +(** Validation state (see above). *) +type validation_state = { + info : info; + operation_state : operation_conflict_state; + block_state : block_state; +} + +(** Return the context stored in the state. + + Note that this is the context at the beginning of the block / + mempool: indeed, it is not modified by [validate_operation]. *) +val get_initial_ctxt : validation_state -> context + +(** Initialize the {!validation_state} for the validation of an + existing block, usually in preparation for its future application. *) +val begin_application : + context -> + Chain_id.t -> + predecessor_level:Level.t -> + predecessor_timestamp:Time.t -> + Block_header.t -> + Fitness.t -> + validation_state tzresult Lwt.t + +(** Initialize the {!validation_state} for the partial validation of + an existing block. + + The partial validation mode is intended for quickly assessing a + series of blocks in a cousin branch (multipass + validation). Therefore, it is the only mode in which the given + {!type-context} may be based on any recent ancestor block of the + block to validate, instead of only its predecessor (where recent + means having a greater level than the [last_allowed_fork_level] of + the current head). *) +val begin_partial_validation : + context -> + Chain_id.t -> + predecessor_level:Level.t -> + predecessor_timestamp:Time.t -> + Block_header.t -> + Fitness.t -> + validation_state tzresult Lwt.t + +(** Initialize the {!validation_state} for the full construction of a + fresh block. *) +val begin_full_construction : + context -> + Chain_id.t -> + predecessor_level:Level.t -> + predecessor_round:Round.t -> + predecessor_timestamp:Time.t -> + predecessor_hash:Block_hash.t -> + Round.t -> + Block_header.contents -> + validation_state tzresult Lwt.t + +(** Initialize the {!validation_state} for the validation of + operations outside of the process of validation of a block. The + partial construction mode is mainly used to implement the mempool + (see {!Mempool_validation}), but may also be used by some RPCs. *) +val begin_partial_construction : + context -> + Chain_id.t -> + predecessor_level:Level.t -> + predecessor_round:Round.t -> + validation_state + +(** Similar to [begin_partial_construction] but do not require + predecessor information that is essential to the validation of + preattestation and attestation operations. As a consequence, the + validation of these operations will always fail. + + This function is used by the plugin RPC [run_operation], which + does not support consensus operations anyway. *) +val begin_no_predecessor_info : context -> Chain_id.t -> validation_state + +(** Check the validity of the given operation and return the updated + {!validation_state}. + + See the documentation at the top of this module on operation validation. + + @param check_signature indicates whether the signature check + should happen. It defaults to [true] because the signature needs to + be correct for the operation to be valid. This argument exists for + special cases where it is acceptable to bypass this check, e.g.: + + - A mempool implementation may keep track of operations whose + signatures have already been checked: if such an operation needs to + be validated again (typically when the head block changes), then + the mempool may call [validate_operation] with + [check_signature:false]. + + - The [run_operation] RPC provided by the plugin explicitly + excludes signature checks: see its documentation in + [lib_plugin/RPC.Scripts.S.run_operation]. *) +val validate_operation : + ?check_signature:bool -> + validation_state -> + Operation_hash.t -> + packed_operation -> + validation_state tzresult Lwt.t + +(** Finish the validation of a block. + + This function should only be used after {!validate_operation} has + been called on every operation in the block. It checks the + consistency of the block_header with the information computed while + validating the block's operations (Attestation power, payload hash, + etc.) Checks vary depending on the mode (ie. which of the + [begin_...] functions above was used to initialize the + [validation_state]). *) +val finalize_block : validation_state -> unit tzresult Lwt.t + +(** The remaining functions are intended for the mempool. + See {!Mempool_validation}. *) + +(** Check the operation validity, similarly to {!validate_operation}. + + However, this function does not check for conflicts with + previously validated operations, nor global block properties such + as the respect of the block gas limit. This allows the function to + only take an {!type-info} as input rather than a full + {!type-validation_state}. + + This function is intended for {!Mempool_validation} exclusively. *) +val check_operation : + ?check_signature:bool -> info -> 'kind operation -> unit tzresult Lwt.t + +(** Check that the operation does not conflict with other operations + already validated and recorded in the {!operation_conflict_state}. + + This function is intended for {!Mempool_validation} exclusively. *) +val check_operation_conflict : + operation_conflict_state -> + Operation_hash.t -> + 'kind operation -> + (unit, operation_conflict) result + +(** Add a valid operation to the {!operation_conflict_state}. + + The operation should have been previously validated by calling + both {!check_operation} and {!check_operation_conflict}. + + This function is intended for {!Mempool_validation} exclusively. *) +val add_valid_operation : + operation_conflict_state -> + Operation_hash.t -> + 'kind operation -> + operation_conflict_state + +(** Remove a valid operation from the {!operation_conflict_state}. + + Preconditions: + - The operation has already been validated and added to the + [operation_conflict_state]. + - The [operation_conflict_state] and other states used to validate + the operation have been initialized by calling + {!begin_partial_construction}. + + This function is intended for {!Mempool_validation}, though it is + also called by the plugin. *) +val remove_operation : + operation_conflict_state -> 'kind operation -> operation_conflict_state diff --git a/src/proto_020_PsParisC/lib_protocol/validate_errors.ml b/src/proto_020_PsParisC/lib_protocol/validate_errors.ml new file mode 100644 index 000000000000..c7ba3d04c201 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/validate_errors.ml @@ -0,0 +1,1377 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type operation_conflict = + | Operation_conflict of { + existing : Operation_hash.t; + new_operation : Operation_hash.t; + } + +let operation_conflict_encoding = + let open Data_encoding in + def + "operation_conflict" + ~title:"Conflict error" + ~description:"Conflict between two operations" + @@ conv + (function + | Operation_conflict {existing; new_operation} -> + (existing, new_operation)) + (fun (existing, new_operation) -> + Operation_conflict {existing; new_operation}) + (obj2 + (req "existing" Operation_hash.encoding) + (req "new_operation" Operation_hash.encoding)) + +module Consensus = struct + type error += Forbidden_delegate of Signature.Public_key_hash.t + + let () = + register_error_kind + `Permanent + ~id:"validate.temporarily_forbidden_delegate" + ~title:"Temporarily forbidden delegate" + ~description:"The delegate has committed too many misbehaviours." + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate %a has committed too many misbehaviours; it is temporarily \ + not allowed to bake/preattest/attest." + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Forbidden_delegate delegate -> Some delegate | _ -> None) + (fun delegate -> Forbidden_delegate delegate) + + (** This type is only used in consensus operation errors to make + them more informative. *) + type consensus_operation_kind = Preattestation | Attestation + + let consensus_operation_kind_encoding = + Data_encoding.string_enum + [("Preattestation", Preattestation); ("Attestation", Attestation)] + + let consensus_operation_kind_pp fmt = function + | Preattestation -> Format.fprintf fmt "Preattestation" + | Attestation -> Format.fprintf fmt "Attestation" + + (** Errors for preattestation and attestation. *) + type error += + | Consensus_operation_for_old_level of { + kind : consensus_operation_kind; + expected : Raw_level.t; + provided : Raw_level.t; + } + | Consensus_operation_for_future_level of { + kind : consensus_operation_kind; + expected : Raw_level.t; + provided : Raw_level.t; + } + | Consensus_operation_for_old_round of { + kind : consensus_operation_kind; + expected : Round.t; + provided : Round.t; + } + | Consensus_operation_for_future_round of { + kind : consensus_operation_kind; + expected : Round.t; + provided : Round.t; + } + | Wrong_payload_hash_for_consensus_operation of { + kind : consensus_operation_kind; + expected : Block_payload_hash.t; + provided : Block_payload_hash.t; + } + | Unexpected_preattestation_in_block + | Unexpected_attestation_in_block + | Preattestation_round_too_high of { + block_round : Round.t; + provided : Round.t; + } + | Wrong_slot_used_for_consensus_operation of { + kind : consensus_operation_kind; + } + | Conflicting_consensus_operation of { + kind : consensus_operation_kind; + conflict : operation_conflict; + } + | Consensus_operation_not_allowed + + let () = + register_error_kind + `Outdated + ~id:"validate.consensus_operation_for_old_level" + ~title:"Consensus operation for old level" + ~description:"Consensus operation for old level." + ~pp:(fun ppf (kind, expected, provided) -> + Format.fprintf + ppf + "%a for old level (expected: %a, provided: %a)." + consensus_operation_kind_pp + kind + Raw_level.pp + expected + Raw_level.pp + provided) + Data_encoding.( + obj3 + (req "kind" consensus_operation_kind_encoding) + (req "expected" Raw_level.encoding) + (req "provided" Raw_level.encoding)) + (function + | Consensus_operation_for_old_level {kind; expected; provided} -> + Some (kind, expected, provided) + | _ -> None) + (fun (kind, expected, provided) -> + Consensus_operation_for_old_level {kind; expected; provided}) ; + register_error_kind + `Temporary + ~id:"validate.consensus_operation_for_future_level" + ~title:"Consensus operation for future level" + ~description:"Consensus operation for future level." + ~pp:(fun ppf (kind, expected, provided) -> + Format.fprintf + ppf + "%a for future level (expected: %a, provided: %a)." + consensus_operation_kind_pp + kind + Raw_level.pp + expected + Raw_level.pp + provided) + Data_encoding.( + obj3 + (req "kind" consensus_operation_kind_encoding) + (req "expected" Raw_level.encoding) + (req "provided" Raw_level.encoding)) + (function + | Consensus_operation_for_future_level {kind; expected; provided} -> + Some (kind, expected, provided) + | _ -> None) + (fun (kind, expected, provided) -> + Consensus_operation_for_future_level {kind; expected; provided}) ; + register_error_kind + `Branch + ~id:"validate.consensus_operation_for_old_round" + ~title:"Consensus operation for old round" + ~description:"Consensus operation for old round." + ~pp:(fun ppf (kind, expected, provided) -> + Format.fprintf + ppf + "%a for old round (expected_min: %a, provided: %a)." + consensus_operation_kind_pp + kind + Round.pp + expected + Round.pp + provided) + Data_encoding.( + obj3 + (req "kind" consensus_operation_kind_encoding) + (req "expected_min" Round.encoding) + (req "provided" Round.encoding)) + (function + | Consensus_operation_for_old_round {kind; expected; provided} -> + Some (kind, expected, provided) + | _ -> None) + (fun (kind, expected, provided) -> + Consensus_operation_for_old_round {kind; expected; provided}) ; + register_error_kind + `Temporary + ~id:"validate.consensus_operation_for_future_round" + ~title:"Consensus operation for future round" + ~description:"Consensus operation for future round." + ~pp:(fun ppf (kind, expected, provided) -> + Format.fprintf + ppf + "%a for future round (expected: %a, provided: %a)." + consensus_operation_kind_pp + kind + Round.pp + expected + Round.pp + provided) + Data_encoding.( + obj3 + (req "kind" consensus_operation_kind_encoding) + (req "expected_max" Round.encoding) + (req "provided" Round.encoding)) + (function + | Consensus_operation_for_future_round {kind; expected; provided} -> + Some (kind, expected, provided) + | _ -> None) + (fun (kind, expected, provided) -> + Consensus_operation_for_future_round {kind; expected; provided}) ; + register_error_kind + (* Note: in Mempool mode this used to be + Consensus_operation_on_competing_proposal (which was + [`Branch] so we kept this classification). *) + `Branch + ~id:"validate.wrong_payload_hash_for_consensus_operation" + ~title:"Wrong payload hash for consensus operation" + ~description:"Wrong payload hash for consensus operation." + ~pp:(fun ppf (kind, expected, provided) -> + Format.fprintf + ppf + "%a with wrong payload hash (expected: %a, provided: %a)." + consensus_operation_kind_pp + kind + Block_payload_hash.pp_short + expected + Block_payload_hash.pp_short + provided) + Data_encoding.( + obj3 + (req "kind" consensus_operation_kind_encoding) + (req "expected" Block_payload_hash.encoding) + (req "provided" Block_payload_hash.encoding)) + (function + | Wrong_payload_hash_for_consensus_operation {kind; expected; provided} + -> + Some (kind, expected, provided) + | _ -> None) + (fun (kind, expected, provided) -> + Wrong_payload_hash_for_consensus_operation {kind; expected; provided}) ; + register_error_kind + `Permanent + ~id:"validate.unexpected_preattestation_in_block" + ~title:"Unexpected preattestation in block" + ~description:"Unexpected preattestation in block." + ~pp:(fun ppf () -> + Format.fprintf ppf "Unexpected preattestation in block.") + Data_encoding.empty + (function Unexpected_preattestation_in_block -> Some () | _ -> None) + (fun () -> Unexpected_preattestation_in_block) ; + register_error_kind + `Permanent + ~id:"validate.unexpected_attestation_in_block" + ~title:"Unexpected attestation in block" + ~description:"Unexpected attestation in block." + ~pp:(fun ppf () -> Format.fprintf ppf "Unexpected attestation in block.") + Data_encoding.empty + (function Unexpected_attestation_in_block -> Some () | _ -> None) + (fun () -> Unexpected_attestation_in_block) ; + register_error_kind + `Permanent + ~id:"validate.preattestation_round_too_high" + ~title:"Preattestation round too high" + ~description:"Preattestation round too high." + ~pp:(fun ppf (block_round, provided) -> + Format.fprintf + ppf + "Preattestation round too high (block_round: %a, provided: %a)." + Round.pp + block_round + Round.pp + provided) + Data_encoding.( + obj2 (req "block_round" Round.encoding) (req "provided" Round.encoding)) + (function + | Preattestation_round_too_high {block_round; provided} -> + Some (block_round, provided) + | _ -> None) + (fun (block_round, provided) -> + Preattestation_round_too_high {block_round; provided}) ; + register_error_kind + `Permanent + ~id:"validate.wrong_slot_for_consensus_operation" + ~title:"Wrong slot for consensus operation" + ~description:"Wrong slot used for a preattestation or attestation." + ~pp:(fun ppf kind -> + Format.fprintf + ppf + "Wrong slot used for a %a." + consensus_operation_kind_pp + kind) + Data_encoding.(obj1 (req "kind" consensus_operation_kind_encoding)) + (function + | Wrong_slot_used_for_consensus_operation {kind} -> Some kind + | _ -> None) + (fun kind -> Wrong_slot_used_for_consensus_operation {kind}) ; + register_error_kind + `Branch + ~id:"validate.double_inclusion_of_consensus_operation" + ~title:"Double inclusion of consensus operation" + ~description:"Double inclusion of consensus operation." + ~pp:(fun ppf (kind, Operation_conflict {existing; new_operation}) -> + Format.fprintf + ppf + "%a operation %a conflicts with existing %a" + consensus_operation_kind_pp + kind + Operation_hash.pp + new_operation + Operation_hash.pp + existing) + Data_encoding.( + obj2 + (req "kind" consensus_operation_kind_encoding) + (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_consensus_operation {kind; conflict} -> + Some (kind, conflict) + | _ -> None) + (fun (kind, conflict) -> Conflicting_consensus_operation {kind; conflict}) ; + register_error_kind + `Branch + ~id:"validate.consensus_operation_not_allowed" + ~title:"Consensus operation not allowed" + ~description:"Consensus operation not allowed." + ~pp:(fun ppf () -> + Format.fprintf ppf "Validation of consensus operation if forbidden ") + Data_encoding.empty + (function Consensus_operation_not_allowed -> Some () | _ -> None) + (fun () -> Consensus_operation_not_allowed) +end + +module Voting = struct + type error += + | (* Shared voting errors *) + Wrong_voting_period_index of { + expected : int32; + provided : int32; + } + | Wrong_voting_period_kind of { + current : Voting_period.kind; + expected : Voting_period.kind list; + } + | Source_not_in_vote_listings + | (* Proposals errors *) + Empty_proposals + | Proposals_contain_duplicate of {proposal : Protocol_hash.t} + | Already_proposed of {proposal : Protocol_hash.t} + | Too_many_proposals of {previous_count : int; operation_count : int} + | Conflicting_proposals of operation_conflict + | Testnet_dictator_multiple_proposals + | Proposals_from_unregistered_delegate of Signature.Public_key_hash.t + | (* Ballot errors *) + Ballot_for_wrong_proposal of { + current : Protocol_hash.t; + submitted : Protocol_hash.t; + } + | Already_submitted_a_ballot + | Ballot_from_unregistered_delegate of Signature.Public_key_hash.t + | Conflicting_ballot of operation_conflict + + let () = + (* Shared voting errors *) + register_error_kind + `Temporary + ~id:"validate.operation.wrong_voting_period_index" + ~title:"Wrong voting period index" + ~description: + "The voting operation contains a voting period index different from \ + the current one." + ~pp:(fun ppf (expected, provided) -> + Format.fprintf + ppf + "The voting operation is meant for voting period %ld, whereas the \ + current period is %ld." + provided + expected) + Data_encoding.( + obj2 (req "current_index" int32) (req "provided_index" int32)) + (function + | Wrong_voting_period_index {expected; provided} -> + Some (expected, provided) + | _ -> None) + (fun (expected, provided) -> + Wrong_voting_period_index {expected; provided}) ; + register_error_kind + `Temporary + ~id:"validate.operation.wrong_voting_period_kind" + ~title:"Wrong voting period kind" + ~description: + "The voting operation is incompatible the current voting period kind." + ~pp:(fun ppf (current, expected) -> + Format.fprintf + ppf + "The voting operation is only valid during a %a voting period, but \ + we are currently in a %a period." + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " or ") + Voting_period.pp_kind) + expected + Voting_period.pp_kind + current) + Data_encoding.( + obj2 + (req "current" Voting_period.kind_encoding) + (req "expected" (list Voting_period.kind_encoding))) + (function + | Wrong_voting_period_kind {current; expected} -> + Some (current, expected) + | _ -> None) + (fun (current, expected) -> Wrong_voting_period_kind {current; expected}) ; + let description = "The delegate is not in the vote listings." in + register_error_kind + `Temporary + ~id:"validate.operation.source_not_in_vote_listings" + ~title:"Source not in vote listings" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Source_not_in_vote_listings -> Some () | _ -> None) + (fun () -> Source_not_in_vote_listings) ; + + (* Proposals errors *) + let description = "Proposal list cannot be empty." in + register_error_kind + `Permanent + ~id:"validate.operation.empty_proposals" + ~title:"Empty proposals" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Empty_proposals -> Some () | _ -> None) + (fun () -> Empty_proposals) ; + register_error_kind + `Permanent + ~id:"validate.operation.proposals_contain_duplicate" + ~title:"Proposals contain duplicate" + ~description:"The list of proposals contains a duplicate element." + ~pp:(fun ppf proposal -> + Format.fprintf + ppf + "The list of proposals contains multiple occurrences of the proposal \ + %a." + Protocol_hash.pp + proposal) + Data_encoding.(obj1 (req "proposal" Protocol_hash.encoding)) + (function + | Proposals_contain_duplicate {proposal} -> Some proposal | _ -> None) + (fun proposal -> Proposals_contain_duplicate {proposal}) ; + register_error_kind + `Branch + ~id:"validate.operation.already_proposed" + ~title:"Already proposed" + ~description: + "The delegate has already submitted one of the operation's proposals." + ~pp:(fun ppf proposal -> + Format.fprintf + ppf + "The delegate has already submitted the proposal %a." + Protocol_hash.pp + proposal) + Data_encoding.(obj1 (req "proposal" Protocol_hash.encoding)) + (function Already_proposed {proposal} -> Some proposal | _ -> None) + (fun proposal -> Already_proposed {proposal}) ; + register_error_kind + `Temporary + ~id:"validate.operation.conflict_too_many_proposals" + ~title:"Conflict too many proposals" + ~description: + "The delegate exceeded the maximum number of allowed proposals due to, \ + among others, previous Proposals operations in the current \ + block/mempool." + ~pp:(fun ppf (previous_count, operation_count) -> + Format.fprintf + ppf + "The delegate cannot submit too many protocol proposals: it \ + currently voted for %d and is trying to vote for %d more." + previous_count + operation_count) + Data_encoding.( + obj2 (req "previous_count" int8) (req "operation_count" int31)) + (function + | Too_many_proposals {previous_count; operation_count} -> + Some (previous_count, operation_count) + | _ -> None) + (fun (previous_count, operation_count) -> + Too_many_proposals {previous_count; operation_count}) ; + register_error_kind + `Temporary + ~id:"validate.operation.conflicting_proposals" + ~title:"Conflicting proposals" + ~description: + "The current block/mempool already contains a testnest dictator \ + proposals operation, so it cannot have any other voting operation." + ~pp:(fun ppf (Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "The current block/mempool already contains a conflicting operation \ + %a." + Operation_hash.pp + existing) + Data_encoding.(obj1 (req "conflict" operation_conflict_encoding)) + (function Conflicting_proposals conflict -> Some conflict | _ -> None) + (fun conflict -> Conflicting_proposals conflict) ; + let description = + "A testnet dictator cannot submit more than one proposal at a time." + in + register_error_kind + `Permanent + ~id:"validate.operation.testnet_dictator_multiple_proposals" + ~title:"Testnet dictator multiple proposals" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Testnet_dictator_multiple_proposals -> Some () | _ -> None) + (fun () -> Testnet_dictator_multiple_proposals) ; + register_error_kind + `Permanent + ~id:"operation.proposals_from_unregistered_delegate" + ~title:"Proposals from an unregistered delegate" + ~description:"Cannot submit proposals with an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot submit proposals with public key hash %a (unregistered \ + delegate)." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Proposals_from_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Proposals_from_unregistered_delegate c) ; + + (* Ballot errors *) + register_error_kind + `Branch + ~id:"validate.operation.ballot_for_wrong_proposal" + ~title:"Ballot for wrong proposal" + ~description:"Ballot provided for a proposal that is not the current one." + ~pp:(fun ppf (current, submitted) -> + Format.fprintf + ppf + "Ballot provided for proposal %a whereas the current proposal is %a." + Protocol_hash.pp + submitted + Protocol_hash.pp + current) + Data_encoding.( + obj2 + (req "current_proposal" Protocol_hash.encoding) + (req "ballot_proposal" Protocol_hash.encoding)) + (function + | Ballot_for_wrong_proposal {current; submitted} -> + Some (current, submitted) + | _ -> None) + (fun (current, submitted) -> + Ballot_for_wrong_proposal {current; submitted}) ; + let description = + "The delegate has already submitted a ballot for the current voting \ + period." + in + register_error_kind + `Branch + ~id:"validate.operation.already_submitted_a_ballot" + ~title:"Already submitted a ballot" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Already_submitted_a_ballot -> Some () | _ -> None) + (fun () -> Already_submitted_a_ballot) ; + register_error_kind + `Permanent + ~id:"operation.ballot_from_unregistered_delegate" + ~title:"Ballot from an unregistered delegate" + ~description:"Cannot cast a ballot for an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot cast a ballot for public key hash %a (unregistered delegate)." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Ballot_from_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Ballot_from_unregistered_delegate c) ; + register_error_kind + `Temporary + ~id:"validate.operation.conflicting_ballot" + ~title:"Conflicting ballot" + ~description: + "The delegate has already submitted a ballot in a previously validated \ + operation of the current block or mempool." + ~pp:(fun ppf (Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "The delegate has already submitted a ballot in the previously \ + validated operation %a of the current block or mempool." + Operation_hash.pp + existing) + Data_encoding.(obj1 (req "conflict" operation_conflict_encoding)) + (function Conflicting_ballot conflict -> Some conflict | _ -> None) + (fun conflict -> Conflicting_ballot conflict) +end + +module Anonymous = struct + type error += + | Invalid_activation of {pkh : Ed25519.Public_key_hash.t} + | Conflicting_activation of { + edpkh : Ed25519.Public_key_hash.t; + conflict : operation_conflict; + } + + let () = + register_error_kind + `Permanent + ~id:"validate.operation.invalid_activation" + ~title:"Invalid activation" + ~description: + "The given key and secret do not correspond to any existing \ + preallocated contract." + ~pp:(fun ppf pkh -> + Format.fprintf + ppf + "Invalid activation. The public key %a and accompanying secret do \ + not match any commitment." + Ed25519.Public_key_hash.pp + pkh) + Data_encoding.(obj1 (req "pkh" Ed25519.Public_key_hash.encoding)) + (function Invalid_activation {pkh} -> Some pkh | _ -> None) + (fun pkh -> Invalid_activation {pkh}) ; + register_error_kind + `Branch + ~id:"validate.operation.conflicting_activation" + ~title:"Account already activated in current validation_state" + ~description: + "The account has already been activated by a previous operation in the \ + current validation state." + ~pp:(fun ppf (edpkh, Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "Invalid activation: the account %a has already been activated in \ + the current validation state by operation %a." + Ed25519.Public_key_hash.pp + edpkh + Operation_hash.pp + existing) + Data_encoding.( + obj2 + (req "edpkh" Ed25519.Public_key_hash.encoding) + (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_activation {edpkh; conflict} -> Some (edpkh, conflict) + | _ -> None) + (fun (edpkh, conflict) -> Conflicting_activation {edpkh; conflict}) + + type denunciation_kind = Misbehaviour.kind + + let pp_denunciation_kind fmt : denunciation_kind -> unit = function + | Double_preattesting -> Format.fprintf fmt "preattestation" + | Double_attesting -> Format.fprintf fmt "attestation" + | Double_baking -> Format.fprintf fmt "block" + + type error += + | Invalid_double_baking_evidence of { + hash1 : Block_hash.t; + level1 : Raw_level.t; + round1 : Round.t; + hash2 : Block_hash.t; + level2 : Raw_level.t; + round2 : Round.t; + } + | Invalid_denunciation of denunciation_kind + | Inconsistent_denunciation of { + kind : denunciation_kind; + delegate1 : Signature.Public_key_hash.t; + delegate2 : Signature.Public_key_hash.t; + } + | Already_denounced of { + kind : denunciation_kind; + delegate : Signature.Public_key_hash.t; + level : Level.t; + } + | Conflicting_denunciation of { + kind : denunciation_kind; + conflict : operation_conflict; + } + | Too_early_denunciation of { + kind : denunciation_kind; + level : Raw_level.t; + current : Raw_level.t; + } + | Outdated_denunciation of { + kind : denunciation_kind; + level : Raw_level.t; + last_cycle : Cycle.t; + } + + let () = + register_error_kind + `Permanent + ~id:"validate.block.invalid_double_baking_evidence" + ~title:"Invalid double baking evidence" + ~description: + "A double-baking evidence is inconsistent (two distinct levels)" + ~pp:(fun ppf (hash1, level1, round1, hash2, level2, round2) -> + Format.fprintf + ppf + "Invalid double-baking evidence (hash: %a and %a, levels/rounds: \ + (%ld,%ld) and (%ld,%ld))" + Block_hash.pp + hash1 + Block_hash.pp + hash2 + (Raw_level.to_int32 level1) + (Round.to_int32 round1) + (Raw_level.to_int32 level2) + (Round.to_int32 round2)) + Data_encoding.( + obj6 + (req "hash1" Block_hash.encoding) + (req "level1" Raw_level.encoding) + (req "round1" Round.encoding) + (req "hash2" Block_hash.encoding) + (req "level2" Raw_level.encoding) + (req "round2" Round.encoding)) + (function + | Invalid_double_baking_evidence + {hash1; level1; round1; hash2; level2; round2} -> + Some (hash1, level1, round1, hash2, level2, round2) + | _ -> None) + (fun (hash1, level1, round1, hash2, level2, round2) -> + Invalid_double_baking_evidence + {hash1; level1; round1; hash2; level2; round2}) ; + register_error_kind + `Permanent + ~id:"validate.operation.block.invalid_denunciation" + ~title:"Invalid denunciation" + ~description:"A denunciation is malformed" + ~pp:(fun ppf kind -> + Format.fprintf + ppf + "Malformed double-%a evidence" + pp_denunciation_kind + kind) + Data_encoding.(obj1 (req "kind" Misbehaviour.kind_encoding)) + (function Invalid_denunciation kind -> Some kind | _ -> None) + (fun kind -> Invalid_denunciation kind) ; + register_error_kind + `Permanent + ~id:"validate.operation.block.inconsistent_denunciation" + ~title:"Inconsistent denunciation" + ~description: + "A denunciation operation is inconsistent (two distinct delegates)" + ~pp:(fun ppf (kind, delegate1, delegate2) -> + Format.fprintf + ppf + "Inconsistent double-%a evidence (distinct delegate: %a and %a)" + pp_denunciation_kind + kind + Signature.Public_key_hash.pp_short + delegate1 + Signature.Public_key_hash.pp_short + delegate2) + Data_encoding.( + obj3 + (req "kind" Misbehaviour.kind_encoding) + (req "delegate1" Signature.Public_key_hash.encoding) + (req "delegate2" Signature.Public_key_hash.encoding)) + (function + | Inconsistent_denunciation {kind; delegate1; delegate2} -> + Some (kind, delegate1, delegate2) + | _ -> None) + (fun (kind, delegate1, delegate2) -> + Inconsistent_denunciation {kind; delegate1; delegate2}) ; + register_error_kind + `Branch + ~id:"validate.operation.already_denounced" + ~title:"Already denounced" + ~description:"The same denunciation has already been validated." + ~pp:(fun ppf (kind, delegate, level) -> + Format.fprintf + ppf + "Delegate %a at level %a has already been denounced for a double %a." + Signature.Public_key_hash.pp + delegate + Level.pp + level + pp_denunciation_kind + kind) + Data_encoding.( + obj3 + (req "denunciation_kind" Misbehaviour.kind_encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Level.encoding)) + (function + | Already_denounced {kind; delegate; level} -> + Some (kind, delegate, level) + | _ -> None) + (fun (kind, delegate, level) -> Already_denounced {kind; delegate; level}) ; + register_error_kind + `Branch + ~id:"validate.operation.conflicting_denunciation" + ~title:"Conflicting denunciation in current validation state" + ~description: + "The same denunciation has already been validated in the current \ + validation state." + ~pp:(fun ppf (kind, Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "Double %a evidence already exists in the current validation state \ + as operation %a." + pp_denunciation_kind + kind + Operation_hash.pp + existing) + Data_encoding.( + obj2 + (req "denunciation_kind" Misbehaviour.kind_encoding) + (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_denunciation {kind; conflict} -> Some (kind, conflict) + | _ -> None) + (fun (kind, conflict) -> Conflicting_denunciation {kind; conflict}) ; + register_error_kind + `Temporary + ~id:"validate.operation.block.too_early_denunciation" + ~title:"Too early denunciation" + ~description:"A denunciation is too far in the future" + ~pp:(fun ppf (kind, level, current) -> + Format.fprintf + ppf + "A double-%a denunciation is too far in the future (current level: \ + %a, given level: %a)" + pp_denunciation_kind + kind + Raw_level.pp + current + Raw_level.pp + level) + Data_encoding.( + obj3 + (req "kind" Misbehaviour.kind_encoding) + (req "level" Raw_level.encoding) + (req "current" Raw_level.encoding)) + (function + | Too_early_denunciation {kind; level; current} -> + Some (kind, level, current) + | _ -> None) + (fun (kind, level, current) -> + Too_early_denunciation {kind; level; current}) ; + register_error_kind + `Permanent + ~id:"validate.operation.block.outdated_denunciation" + ~title:"Outdated denunciation" + ~description:"A denunciation is outdated." + ~pp:(fun ppf (kind, level, last_cycle) -> + Format.fprintf + ppf + "A double-%a denunciation is outdated (last acceptable cycle: %a, \ + given level: %a)." + pp_denunciation_kind + kind + Cycle.pp + last_cycle + Raw_level.pp + level) + Data_encoding.( + obj3 + (req "kind" Misbehaviour.kind_encoding) + (req "level" Raw_level.encoding) + (req "last" Cycle.encoding)) + (function + | Outdated_denunciation {kind; level; last_cycle} -> + Some (kind, level, last_cycle) + | _ -> None) + (fun (kind, level, last_cycle) -> + Outdated_denunciation {kind; level; last_cycle}) + + type error += Conflicting_nonce_revelation of operation_conflict + + let () = + register_error_kind + `Branch + ~id:"validate.operation.conflicting_nonce_revelation" + ~title:"Conflicting nonce revelation in the current validation state)." + ~description: + "A revelation for the same nonce has already been validated for the \ + current validation state." + ~pp:(fun ppf (Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "This nonce revelation is conflicting with an existing revelation %a" + Operation_hash.pp + existing) + Data_encoding.(obj1 (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_nonce_revelation conflict -> Some conflict | _ -> None) + (fun conflict -> Conflicting_nonce_revelation conflict) + + type error += Conflicting_vdf_revelation of operation_conflict + + let () = + register_error_kind + `Branch + ~id:"validate.operation.conflicting_vdf_revelation" + ~title:"Conflicting vdf revelation in the current validation state)." + ~description: + "A revelation for the same vdf has already been validated for the \ + current validation state." + ~pp:(fun ppf (Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "This vdf revelation is conflicting with an existing revelation %a" + Operation_hash.pp + existing) + Data_encoding.(obj1 (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_vdf_revelation conflict -> Some conflict | _ -> None) + (fun conflict -> Conflicting_vdf_revelation conflict) + + type error += + | Drain_delegate_on_unregistered_delegate of Signature.Public_key_hash.t + | Invalid_drain_delegate_inactive_key of { + delegate : Signature.Public_key_hash.t; + consensus_key : Signature.Public_key_hash.t; + active_consensus_key : Signature.Public_key_hash.t; + } + | Invalid_drain_delegate_no_consensus_key of Signature.Public_key_hash.t + | Invalid_drain_delegate_noop of Signature.Public_key_hash.t + | Invalid_drain_delegate_insufficient_funds_for_burn_or_fees of { + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + min_amount : Tez.t; + } + | Conflicting_drain_delegate of { + delegate : Signature.Public_key_hash.t; + conflict : operation_conflict; + } + + let () = + register_error_kind + `Temporary + ~id:"operation.drain_delegate_key_on_unregistered_delegate" + ~title:"Drain delegate key on an unregistered delegate" + ~description:"Cannot drain an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot drain an unregistered delegate %a." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function + | Drain_delegate_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Drain_delegate_on_unregistered_delegate c) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.inactive_key" + ~title:"Drain delegate with an inactive consensus key" + ~description:"Cannot drain with an inactive consensus key." + ~pp:(fun ppf (delegate, consensus_key, active_consensus_key) -> + Format.fprintf + ppf + "Consensus key %a is not the active consensus key for delegate %a. \ + The active consensus key is %a." + Signature.Public_key_hash.pp + consensus_key + Signature.Public_key_hash.pp + delegate + Signature.Public_key_hash.pp + active_consensus_key) + Data_encoding.( + obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "consensus_key" Signature.Public_key_hash.encoding) + (req "active_consensus_key" Signature.Public_key_hash.encoding)) + (function + | Invalid_drain_delegate_inactive_key + {delegate; consensus_key; active_consensus_key} -> + Some (delegate, consensus_key, active_consensus_key) + | _ -> None) + (fun (delegate, consensus_key, active_consensus_key) -> + Invalid_drain_delegate_inactive_key + {delegate; consensus_key; active_consensus_key}) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.no_consensus_key" + ~title:"Drain a delegate without consensus key" + ~description:"Cannot drain a delegate without consensus key." + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "There is no active consensus key for delegate %a." + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function + | Invalid_drain_delegate_no_consensus_key c -> Some c | _ -> None) + (fun c -> Invalid_drain_delegate_no_consensus_key c) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.noop" + ~title:"Invalid drain delegate: noop" + ~description:"Cannot drain a delegate to itself." + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "The destination of a drain operation cannot be the delegate itself \ + (%a)." + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Invalid_drain_delegate_noop c -> Some c | _ -> None) + (fun c -> Invalid_drain_delegate_noop c) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.insufficient_funds_for_burn_or_fees" + ~title: + "Drain delegate without enough balance for allocation burn or drain \ + fees" + ~description:"Cannot drain without enough allocation burn and drain fees." + ~pp:(fun ppf (delegate, destination, min_amount) -> + Format.fprintf + ppf + "Cannot drain delegate from %a to %a: not enough funds for the drain \ + fees in the delegate account (minimum balance required: %a)." + Signature.Public_key_hash.pp + delegate + Signature.Public_key_hash.pp + destination + Tez.pp + min_amount) + Data_encoding.( + obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "destination" Signature.Public_key_hash.encoding) + (req "min_amount" Tez.encoding)) + (function + | Invalid_drain_delegate_insufficient_funds_for_burn_or_fees + {delegate; destination; min_amount} -> + Some (delegate, destination, min_amount) + | _ -> None) + (fun (delegate, destination, min_amount) -> + Invalid_drain_delegate_insufficient_funds_for_burn_or_fees + {delegate; destination; min_amount}) ; + register_error_kind + `Branch + ~id:"validate.operation.conflicting_drain" + ~title:"Conflicting drain in the current validation state)." + ~description: + "A manager operation or another drain operation is in conflict." + ~pp:(fun ppf (delegate, Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "This drain operation conflicts with operation %a for the delegate %a" + Operation_hash.pp + existing + Signature.Public_key_hash.pp + delegate) + Data_encoding.( + obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "conflict" operation_conflict_encoding)) + (function + | Conflicting_drain_delegate {delegate; conflict} -> + Some (delegate, conflict) + | _ -> None) + (fun (delegate, conflict) -> + Conflicting_drain_delegate {delegate; conflict}) +end + +module Manager = struct + type error += + | Manager_restriction of { + source : Signature.Public_key_hash.t; + conflict : operation_conflict; + } + | Inconsistent_sources + | Inconsistent_counters + | Incorrect_reveal_position + | Insufficient_gas_for_manager + | Gas_quota_exceeded_init_deserialize + | Sc_rollup_arith_pvm_disabled + | Sc_rollup_riscv_pvm_disabled + | Zk_rollup_feature_disabled + + let () = + register_error_kind + `Temporary + ~id:"validate.operation.manager_restriction" + ~title:"Manager restriction" + ~description: + "An operation with the same manager has already been validated in the \ + current block." + ~pp:(fun ppf (source, Operation_conflict {existing; _}) -> + Format.fprintf + ppf + "Manager %a already has the operation %a in the current block." + Signature.Public_key_hash.pp + source + Operation_hash.pp + existing) + Data_encoding.( + obj2 + (req "source" Signature.Public_key_hash.encoding) + (req "conflict" operation_conflict_encoding)) + (function + | Manager_restriction {source; conflict} -> Some (source, conflict) + | _ -> None) + (fun (source, conflict) -> Manager_restriction {source; conflict}) ; + let inconsistent_sources_description = + "The operation batch includes operations from different sources." + in + register_error_kind + `Permanent + ~id:"validate.operation.inconsistent_sources" + ~title:"Inconsistent sources in operation batch" + ~description:inconsistent_sources_description + ~pp:(fun ppf () -> + Format.fprintf ppf "%s" inconsistent_sources_description) + Data_encoding.empty + (function Inconsistent_sources -> Some () | _ -> None) + (fun () -> Inconsistent_sources) ; + let inconsistent_counters_description = + "Inconsistent counters in operation. Counters of an operation must be \ + successive." + in + register_error_kind + `Permanent + ~id:"validate.operation.inconsistent_counters" + ~title:"Inconsistent counters in operation" + ~description:inconsistent_counters_description + ~pp:(fun ppf () -> + Format.fprintf ppf "%s" inconsistent_counters_description) + Data_encoding.empty + (function Inconsistent_counters -> Some () | _ -> None) + (fun () -> Inconsistent_counters) ; + let incorrect_reveal_description = + "Incorrect reveal operation position in batch: only allowed in first \ + position." + in + register_error_kind + `Permanent + ~id:"validate.operation.incorrect_reveal_position" + ~title:"Incorrect reveal position" + ~description:incorrect_reveal_description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" incorrect_reveal_description) + Data_encoding.empty + (function Incorrect_reveal_position -> Some () | _ -> None) + (fun () -> Incorrect_reveal_position) ; + register_error_kind + `Permanent + ~id:"validate.operation.insufficient_gas_for_manager" + ~title:"Not enough gas for initial manager cost" + ~description: + (Format.asprintf + "Gas limit is too low to cover the initial cost of manager \ + operations: a minimum of %a gas units is required." + Gas.pp_cost_as_gas + Michelson_v1_gas.Cost_of.manager_operation) + Data_encoding.empty + (function Insufficient_gas_for_manager -> Some () | _ -> None) + (fun () -> Insufficient_gas_for_manager) ; + let gas_deserialize_description = + "Gas limit was not high enough to deserialize the transaction parameters \ + or origination script code or initial storage etc., making the \ + operation impossible to parse within the provided gas bounds." + in + register_error_kind + `Permanent + ~id:"validate.operation.gas_quota_exceeded_init_deserialize" + ~title:"Not enough gas for initial deserialization of script expressions" + ~description:gas_deserialize_description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" gas_deserialize_description) + Data_encoding.empty + (function Gas_quota_exceeded_init_deserialize -> Some () | _ -> None) + (fun () -> Gas_quota_exceeded_init_deserialize) ; + + let scoru_arith_pvm_disabled_description = + "Arith PVM is disabled in this network." + in + register_error_kind + `Permanent + ~id:"operation.arith_pvm_disabled" + ~title:"The Arith PVM is disabled" + ~description:scoru_arith_pvm_disabled_description + ~pp:(fun ppf () -> + Format.fprintf ppf "%s" scoru_arith_pvm_disabled_description) + Data_encoding.unit + (function Sc_rollup_arith_pvm_disabled -> Some () | _ -> None) + (fun () -> Sc_rollup_arith_pvm_disabled) ; + let scoru_riscv_pvm_disabled_description = + "RISCV PVM is disabled in this network." + in + register_error_kind + `Permanent + ~id:"operation.riscv_pvm_disabled" + ~title:"The RISCV PVM is disabled" + ~description:scoru_riscv_pvm_disabled_description + ~pp:(fun ppf () -> + Format.fprintf ppf "%s" scoru_riscv_pvm_disabled_description) + Data_encoding.unit + (function Sc_rollup_riscv_pvm_disabled -> Some () | _ -> None) + (fun () -> Sc_rollup_riscv_pvm_disabled) ; + let zkru_disabled_description = + "ZK rollups will be enabled in a future proposal." + in + register_error_kind + `Permanent + ~id:"validate.operation.zk_rollup_disabled" + ~title:"ZK rollups are disabled" + ~description:zkru_disabled_description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" zkru_disabled_description) + Data_encoding.unit + (function Zk_rollup_feature_disabled -> Some () | _ -> None) + (fun () -> Zk_rollup_feature_disabled) +end + +type error += Failing_noop_error + +let () = + let description = "A failing_noop operation can never be validated." in + register_error_kind + `Permanent + ~id:"validate.operation.failing_noop_error" + ~title:"Failing_noop error" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.empty + (function Failing_noop_error -> Some () | _ -> None) + (fun () -> Failing_noop_error) + +module Block = struct + (* All block errors are permanent. *) + type error += + | Not_enough_attestations of {required : int; provided : int} + | Inconsistent_validation_passes_in_block of { + expected : int; + provided : int; + } + | Invalid_payload_hash of { + expected : Block_payload_hash.t; + provided : Block_payload_hash.t; + } + | Locked_round_after_block_round of { + locked_round : Round.t; + round : Round.t; + } + | Insufficient_locked_round_evidence of { + voting_power : int; + consensus_threshold : int; + } + + let () = + register_error_kind + `Permanent + ~id:"validate.block.not_enough_attestations" + ~title:"Not enough attestations" + ~description: + "The block being validated does not include the required minimum \ + number of attestations." + ~pp:(fun ppf (required, provided) -> + Format.fprintf + ppf + "Wrong number of attestations (%i), at least %i are expected" + provided + required) + Data_encoding.(obj2 (req "required" int31) (req "provided" int31)) + (function + | Not_enough_attestations {required; provided} -> + Some (required, provided) + | _ -> None) + (fun (required, provided) -> Not_enough_attestations {required; provided}) ; + register_error_kind + `Permanent + ~id:"validate.block.inconsistent_validation_passes_in_block" + ~title:"Inconsistent validation passes in block" + ~description: + "Validation of operation should be ordered by their validation passes \ + in a block." + ~pp:(fun ppf (expected, provided) -> + Format.fprintf + ppf + "Validation of operation should be ordered by their validation \ + passes in a block. Got an operation with validation pass: %d while \ + the last validated operation had the validation pass %d." + provided + expected) + Data_encoding.(obj2 (req "expected" int31) (req "provided" int31)) + (function + | Inconsistent_validation_passes_in_block {expected; provided} -> + Some (expected, provided) + | _ -> None) + (fun (expected, provided) -> + Inconsistent_validation_passes_in_block {expected; provided}) ; + register_error_kind + `Permanent + ~id:"validate.block.invalid_payload_hash" + ~title:"Invalid payload hash" + ~description:"Invalid payload hash." + ~pp:(fun ppf (expected, provided) -> + Format.fprintf + ppf + "Invalid payload hash (expected: %a, provided: %a)." + Block_payload_hash.pp_short + expected + Block_payload_hash.pp_short + provided) + Data_encoding.( + obj2 + (req "expected" Block_payload_hash.encoding) + (req "provided" Block_payload_hash.encoding)) + (function + | Invalid_payload_hash {expected; provided} -> Some (expected, provided) + | _ -> None) + (fun (expected, provided) -> Invalid_payload_hash {expected; provided}) ; + () ; + register_error_kind + `Permanent + ~id:"validate.block.locked_round_after_block_round" + ~title:"Locked round after block round" + ~description:"Locked round after block round." + ~pp:(fun ppf (locked_round, round) -> + Format.fprintf + ppf + "Locked round (%a) is after the block round (%a)." + Round.pp + locked_round + Round.pp + round) + Data_encoding.( + obj2 (req "locked_round" Round.encoding) (req "round" Round.encoding)) + (function + | Locked_round_after_block_round {locked_round; round} -> + Some (locked_round, round) + | _ -> None) + (fun (locked_round, round) -> + Locked_round_after_block_round {locked_round; round}) ; + () ; + register_error_kind + `Permanent + ~id:"validate.block.insufficient_locked_round_evidence" + ~title:"Insufficient locked round evidence" + ~description:"Insufficient locked round evidence." + ~pp:(fun ppf (voting_power, consensus_threshold) -> + Format.fprintf + ppf + "The provided locked round evidence is not sufficient: provided %d \ + voting power but was expecting at least %d." + voting_power + consensus_threshold) + Data_encoding.( + obj2 (req "voting_power" int31) (req "consensus_threshold" int31)) + (function + | Insufficient_locked_round_evidence {voting_power; consensus_threshold} + -> + Some (voting_power, consensus_threshold) + | _ -> None) + (fun (voting_power, consensus_threshold) -> + Insufficient_locked_round_evidence {voting_power; consensus_threshold}) +end diff --git a/src/proto_020_PsParisC/lib_protocol/validate_errors.mli b/src/proto_020_PsParisC/lib_protocol/validate_errors.mli new file mode 100644 index 000000000000..01793ab0c7e9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/validate_errors.mli @@ -0,0 +1,216 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +(** type used for conflicting operation. *) +type operation_conflict = + | Operation_conflict of { + existing : Operation_hash.t; + new_operation : Operation_hash.t; + } + +(** Errors that may arise while validating a consensus operation. *) +module Consensus : sig + type consensus_operation_kind = Preattestation | Attestation + + (** Errors for preattestations and attestations. *) + type error += + | Forbidden_delegate of Signature.Public_key_hash.t + | Consensus_operation_not_allowed + | Consensus_operation_for_old_level of { + kind : consensus_operation_kind; + expected : Raw_level.t; + provided : Raw_level.t; + } + | Consensus_operation_for_future_level of { + kind : consensus_operation_kind; + expected : Raw_level.t; + provided : Raw_level.t; + } + | Consensus_operation_for_old_round of { + kind : consensus_operation_kind; + expected : Round.t; + provided : Round.t; + } + | Consensus_operation_for_future_round of { + kind : consensus_operation_kind; + expected : Round.t; + provided : Round.t; + } + | Wrong_payload_hash_for_consensus_operation of { + kind : consensus_operation_kind; + expected : Block_payload_hash.t; + provided : Block_payload_hash.t; + } + | Unexpected_preattestation_in_block + | Unexpected_attestation_in_block + | Preattestation_round_too_high of { + block_round : Round.t; + provided : Round.t; + } + | Wrong_slot_used_for_consensus_operation of { + kind : consensus_operation_kind; + } + | Conflicting_consensus_operation of { + kind : consensus_operation_kind; + conflict : operation_conflict; + } +end + +(** Errors that may arise while validating a voting operation. *) +module Voting : sig + type error += + | (* Shared voting errors *) + Wrong_voting_period_index of { + expected : int32; + provided : int32; + } + | Wrong_voting_period_kind of { + current : Voting_period.kind; + expected : Voting_period.kind list; + } + | Source_not_in_vote_listings + | (* Proposals errors *) + Empty_proposals + | Proposals_contain_duplicate of {proposal : Protocol_hash.t} + | Already_proposed of {proposal : Protocol_hash.t} + | Too_many_proposals of {previous_count : int; operation_count : int} + | Conflicting_proposals of operation_conflict + | Testnet_dictator_multiple_proposals + | Proposals_from_unregistered_delegate of Signature.Public_key_hash.t + | (* Ballot errors *) + Ballot_for_wrong_proposal of { + current : Protocol_hash.t; + submitted : Protocol_hash.t; + } + | Already_submitted_a_ballot + | Ballot_from_unregistered_delegate of Signature.Public_key_hash.t + | Conflicting_ballot of operation_conflict +end + +(** Errors that may arise while validating an anonymous operation. *) +module Anonymous : sig + type denunciation_kind = Misbehaviour.kind + + type error += + | Invalid_activation of {pkh : Ed25519.Public_key_hash.t} + | Conflicting_activation of { + edpkh : Ed25519.Public_key_hash.t; + conflict : operation_conflict; + } + | Invalid_denunciation of denunciation_kind + | Invalid_double_baking_evidence of { + hash1 : Block_hash.t; + level1 : Raw_level.t; + round1 : Round.t; + hash2 : Block_hash.t; + level2 : Raw_level.t; + round2 : Round.t; + } + | Inconsistent_denunciation of { + kind : denunciation_kind; + delegate1 : Signature.Public_key_hash.t; + delegate2 : Signature.Public_key_hash.t; + } + | Already_denounced of { + kind : denunciation_kind; + delegate : Signature.Public_key_hash.t; + level : Level.t; + } + | Conflicting_denunciation of { + kind : denunciation_kind; + conflict : operation_conflict; + } + | Too_early_denunciation of { + kind : denunciation_kind; + level : Raw_level.t; + current : Raw_level.t; + } + | Outdated_denunciation of { + kind : denunciation_kind; + level : Raw_level.t; + last_cycle : Cycle.t; + } + | Conflicting_nonce_revelation of operation_conflict + | Conflicting_vdf_revelation of operation_conflict + | Drain_delegate_on_unregistered_delegate of Signature.Public_key_hash.t + | Invalid_drain_delegate_inactive_key of { + delegate : Signature.Public_key_hash.t; + consensus_key : Signature.Public_key_hash.t; + active_consensus_key : Signature.Public_key_hash.t; + } + | Invalid_drain_delegate_no_consensus_key of Signature.Public_key_hash.t + | Invalid_drain_delegate_noop of Signature.Public_key_hash.t + | Invalid_drain_delegate_insufficient_funds_for_burn_or_fees of { + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + min_amount : Tez.t; + } + | Conflicting_drain_delegate of { + delegate : Signature.Public_key_hash.t; + conflict : operation_conflict; + } +end + +(** Errors that may arise while validating a manager operation. *) +module Manager : sig + type error += + | Manager_restriction of { + source : Signature.Public_key_hash.t; + conflict : operation_conflict; + } + | Inconsistent_sources + | Inconsistent_counters + | Incorrect_reveal_position + | Insufficient_gas_for_manager + | Gas_quota_exceeded_init_deserialize + | Sc_rollup_arith_pvm_disabled + | Sc_rollup_riscv_pvm_disabled + | Zk_rollup_feature_disabled +end + +type error += Failing_noop_error + +module Block : sig + type error += + | Not_enough_attestations of {required : int; provided : int} + | Inconsistent_validation_passes_in_block of { + expected : int; + provided : int; + } + | Invalid_payload_hash of { + expected : Block_payload_hash.t; + provided : Block_payload_hash.t; + } + | Locked_round_after_block_round of { + locked_round : Round.t; + round : Round.t; + } + | Insufficient_locked_round_evidence of { + voting_power : int; + consensus_threshold : int; + } +end diff --git a/src/proto_020_PsParisC/lib_protocol/vote_repr.ml b/src/proto_020_PsParisC/lib_protocol/vote_repr.ml new file mode 100644 index 000000000000..493b5b194683 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/vote_repr.ml @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type proposal = Protocol_hash.t + +type ballot = Yay | Nay | Pass + +let ballot_encoding = + let of_int8 = function + | 0 -> Ok Yay + | 1 -> Ok Nay + | 2 -> Ok Pass + | _ -> Error "ballot_of_int8" + in + let to_int8 = function Yay -> 0 | Nay -> 1 | Pass -> 2 in + let open Data_encoding in + (* union *) + splitted + ~binary:(conv_with_guard to_int8 of_int8 int8) + ~json:(string_enum [("yay", Yay); ("nay", Nay); ("pass", Pass)]) + +let equal_ballot a b = + match (a, b) with Yay, Yay | Nay, Nay | Pass, Pass -> true | _ -> false + +let pp_ballot ppf = function + | Yay -> Format.fprintf ppf "yay" + | Nay -> Format.fprintf ppf "nay" + | Pass -> Format.fprintf ppf "pass" diff --git a/src/proto_020_PsParisC/lib_protocol/vote_repr.mli b/src/proto_020_PsParisC/lib_protocol/vote_repr.mli new file mode 100644 index 000000000000..adfd1a167d09 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/vote_repr.mli @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** a protocol change proposal *) +type proposal = Protocol_hash.t + +(** votes can be for, against or neutral. + Neutral serves to count towards a quorum *) +type ballot = Yay | Nay | Pass + +val ballot_encoding : ballot Data_encoding.t + +val equal_ballot : ballot -> ballot -> bool + +val pp_ballot : Format.formatter -> ballot -> unit diff --git a/src/proto_020_PsParisC/lib_protocol/vote_storage.ml b/src/proto_020_PsParisC/lib_protocol/vote_storage.ml new file mode 100644 index 000000000000..e2eef17ed071 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/vote_storage.ml @@ -0,0 +1,290 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let get_delegate_proposal_count ctxt proposer = + let open Lwt_result_syntax in + let+ value = Storage.Vote.Proposals_count.find ctxt proposer in + Option.value ~default:0 value + +let set_delegate_proposal_count ctxt proposer count = + Storage.Vote.Proposals_count.add ctxt proposer count + +let has_proposed ctxt proposer proposal = + Storage.Vote.Proposals.mem ctxt (proposal, proposer) + +let add_proposal ctxt proposer proposal = + Storage.Vote.Proposals.add ctxt (proposal, proposer) + +let get_proposals ctxt = + let open Lwt_result_syntax in + Storage.Vote.Proposals.fold + ctxt + ~order:`Sorted + ~init:(Ok Protocol_hash.Map.empty) + ~f:(fun (proposal, delegate) acc -> + (* Assuming the same listings is used at votings *) + let* weight = Storage.Vote.Listings.get ctxt delegate in + let*? acc in + let previous = + match Protocol_hash.Map.find proposal acc with + | None -> 0L + | Some x -> x + in + return (Protocol_hash.Map.add proposal (Int64.add weight previous) acc)) + +let clear_proposals ctxt = + let open Lwt_syntax in + let* ctxt = Storage.Vote.Proposals_count.clear ctxt in + Storage.Vote.Proposals.clear ctxt + +type ballots = {yay : int64; nay : int64; pass : int64} + +let ballots_zero = {yay = 0L; nay = 0L; pass = 0L} + +let ballots_encoding = + let open Data_encoding in + conv + (fun {yay; nay; pass} -> (yay, nay, pass)) + (fun (yay, nay, pass) -> {yay; nay; pass}) + @@ obj3 (req "yay" int64) (req "nay" int64) (req "pass" int64) + +let equal_ballots b1 b2 = + Int64.(equal b1.yay b2.yay && equal b1.nay b2.nay && equal b1.pass b2.pass) + +let pp_ballots ppf b = + Format.fprintf ppf "{ yay = %Ld; nay = %Ld; pass = %Ld }" b.yay b.nay b.pass + +let has_recorded_ballot = Storage.Vote.Ballots.mem + +let record_ballot = Storage.Vote.Ballots.init + +let get_ballots ctxt = + let open Lwt_result_syntax in + Storage.Vote.Ballots.fold + ctxt + ~order:`Sorted + ~f:(fun delegate ballot (ballots : ballots tzresult) -> + (* Assuming the same listings is used at votings *) + let* weight = Storage.Vote.Listings.get ctxt delegate in + let count = Int64.add weight in + let*? ballots in + return + (match ballot with + | Yay -> {ballots with yay = count ballots.yay} + | Nay -> {ballots with nay = count ballots.nay} + | Pass -> {ballots with pass = count ballots.pass})) + ~init:(Ok ballots_zero) + +let get_ballot_list = Storage.Vote.Ballots.bindings + +let clear_ballots = Storage.Vote.Ballots.clear + +let listings_encoding = + Data_encoding.( + list + (obj2 + (req "pkh" Signature.Public_key_hash.encoding) + (req "voting_power" int64))) + +let get_current_voting_power_free ctxt delegate = + let open Lwt_result_syntax in + let* stake = Storage.Stake.Staking_balance.get ctxt delegate in + Lwt.return @@ Full_staking_balance_repr.voting_weight stake + +let update_listings ctxt = + let open Lwt_result_syntax in + let*! ctxt = Storage.Vote.Listings.clear ctxt in + let* ctxt, total = + Stake_storage.fold_on_active_delegates_with_minimal_stake_es + ctxt + ~init:(ctxt, 0L) + ~order:`Sorted + ~f:(fun delegate (ctxt, total) -> + let* weight = get_current_voting_power_free ctxt delegate in + let+ ctxt = Storage.Vote.Listings.init ctxt delegate weight in + (ctxt, Int64.add total weight)) + in + let*! ctxt = Storage.Vote.Voting_power_in_listings.add ctxt total in + return ctxt + +type delegate_info = { + voting_power : Int64.t option; + current_ballot : Vote_repr.ballot option; + current_proposals : Protocol_hash.t list; + remaining_proposals : int; +} + +let pp_delegate_info ppf info = + match info.voting_power with + | None -> Format.fprintf ppf "Voting power: none" + | Some p -> ( + Format.fprintf + ppf + "Voting power: %a" + Tez_repr.pp + (Tez_repr.of_mutez_exn p) ; + (match info.current_ballot with + | None -> () + | Some ballot -> + Format.fprintf ppf "@,Current ballot: %a" Vote_repr.pp_ballot ballot) ; + match info.current_proposals with + | [] -> + if Compare.Int.(info.remaining_proposals <> 0) then + Format.fprintf + ppf + "@,Remaining proposals: %d" + info.remaining_proposals + | proposals -> + Format.fprintf ppf "@,@[Current proposals:" ; + List.iter + (fun p -> Format.fprintf ppf "@,- %a" Protocol_hash.pp p) + proposals ; + Format.fprintf ppf "@]" ; + Format.fprintf + ppf + "@,Remaining proposals: %d" + info.remaining_proposals) + +let delegate_info_encoding = + let open Data_encoding in + conv + (fun {voting_power; current_ballot; current_proposals; remaining_proposals} -> + (voting_power, current_ballot, current_proposals, remaining_proposals)) + (fun (voting_power, current_ballot, current_proposals, remaining_proposals) -> + {voting_power; current_ballot; current_proposals; remaining_proposals}) + (obj4 + (opt "voting_power" int64) + (opt "current_ballot" Vote_repr.ballot_encoding) + (dft "current_proposals" (list Protocol_hash.encoding) []) + (dft "remaining_proposals" int31 0)) + +let in_listings = Storage.Vote.Listings.mem + +let get_listings = Storage.Vote.Listings.bindings + +let get_delegate_info ctxt delegate = + let open Lwt_result_syntax in + let* voting_power = Storage.Vote.Listings.find ctxt delegate in + match voting_power with + | None -> + return + { + voting_power; + current_proposals = []; + current_ballot = None; + remaining_proposals = 0; + } + | Some _ -> + let* period = Voting_period_storage.get_current_kind ctxt in + let* current_ballot = + match period with + | Exploration | Promotion -> Storage.Vote.Ballots.find ctxt delegate + | Proposal | Cooldown | Adoption -> return_none + in + let*! current_proposals = + match period with + | Exploration | Promotion | Cooldown | Adoption -> Lwt.return_nil + | Proposal -> + Storage.Vote.Proposals.fold + ctxt + ~order:`Undefined + ~init:[] + ~f:(fun (h, d) acc -> + if Signature.Public_key_hash.equal d delegate then + Lwt.return (h :: acc) + else Lwt.return acc) + in + let remaining_proposals = + match period with + | Proposal -> + Constants_repr.max_proposals_per_delegate + - List.length current_proposals + | _ -> 0 + in + return + {voting_power; current_ballot; current_proposals; remaining_proposals} + +let get_voting_power_free ctxt owner = + let open Lwt_result_syntax in + let+ value = Storage.Vote.Listings.find ctxt owner in + Option.value ~default:0L value + +(* This function bypasses the carbonated functors to account for gas consumption. + This is a temporary situation intended to be fixed by adding the right + carbonated functors in a future amendment *) +let get_voting_power ctxt owner = + let open Lwt_result_syntax in + let open Raw_context in + (* Always consume read access to memory *) + (* Accessing an int64 at /votes/listings// *) + let*? ctxt = + consume_gas ctxt (Storage_costs.read_access ~path_length:4 ~read_bytes:8) + in + let+ power_opt = Storage.Vote.Listings.find ctxt owner in + match power_opt with None -> (ctxt, 0L) | Some power -> (ctxt, power) + +let get_total_voting_power_free = Storage.Vote.Voting_power_in_listings.get + +(* This function bypasses the carbonated functors to account for gas consumption. + This is a temporary situation intended to be fixed by adding the right + carbonated functors in a future amendment *) +let get_total_voting_power ctxt = + let open Lwt_result_syntax in + let open Raw_context in + (* Accessing an int64 at /votes/total_voting_power *) + let*? ctxt = + consume_gas ctxt (Storage_costs.read_access ~path_length:2 ~read_bytes:8) + in + let+ total_voting_power = get_total_voting_power_free ctxt in + (ctxt, total_voting_power) + +let get_current_quorum ctxt = + let open Lwt_result_syntax in + let+ participation_ema = Storage.Vote.Participation_ema.get ctxt in + let quorum_min = Constants_storage.quorum_min ctxt in + let quorum_max = Constants_storage.quorum_max ctxt in + let quorum_diff = Int32.sub quorum_max quorum_min in + Int32.(add quorum_min (div (mul participation_ema quorum_diff) 100_00l)) + +let get_participation_ema = Storage.Vote.Participation_ema.get + +let set_participation_ema = Storage.Vote.Participation_ema.update + +let current_proposal_exists = Storage.Vote.Current_proposal.mem + +let get_current_proposal = Storage.Vote.Current_proposal.get + +let find_current_proposal = Storage.Vote.Current_proposal.find + +let init_current_proposal = Storage.Vote.Current_proposal.init + +let clear_current_proposal = Storage.Vote.Current_proposal.remove + +let init ctxt ~start_position = + let open Lwt_result_syntax in + (* participation EMA is in centile of a percentage *) + let participation_ema = Constants_storage.quorum_max ctxt in + let* ctxt = Storage.Vote.Participation_ema.init ctxt participation_ema in + Voting_period_storage.init_first_period ctxt ~start_position diff --git a/src/proto_020_PsParisC/lib_protocol/vote_storage.mli b/src/proto_020_PsParisC/lib_protocol/vote_storage.mli new file mode 100644 index 000000000000..ae938d7b6115 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/vote_storage.mli @@ -0,0 +1,193 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Manages all the voting related storage in Storage.Vote. *) + +(** [get_delegate_proposal_count ctxt proposer] returns the number of + proposals already made by [proposer] in the current voting cycle. + + This number of proposals, aka [count], has its own storage bucket. + + @return [0] if the [count] of the proposer was not initialized. + + @return [Error Storage_error] if the deserialization of [count] + fails. *) +val get_delegate_proposal_count : + Raw_context.t -> Signature.public_key_hash -> int tzresult Lwt.t + +(** [set_delegate_proposal_count ctxt proposer count] sets + [proposer]'s number of submitted proposals to [count]. + + More precisely, the relevant storage bucket is allocated and + initialized to [count] if it didn't exist; otherwise it is simply + updated. *) +val set_delegate_proposal_count : + Raw_context.t -> Signature.public_key_hash -> int -> Raw_context.t Lwt.t + +(** [has_proposed ctxt proposer proposal] indicates whether the + [proposer] has already proposed the [proposal]. *) +val has_proposed : + Raw_context.t -> Signature.public_key_hash -> Protocol_hash.t -> bool Lwt.t + +(** [add_proposal ctxt proposer proposal] records the submission of + [proposal] by [proposer]. *) +val add_proposal : + Raw_context.t -> + Signature.public_key_hash -> + Protocol_hash.t -> + Raw_context.t Lwt.t + +(** Computes for each proposal how many delegates proposed it. *) +val get_proposals : Raw_context.t -> int64 Protocol_hash.Map.t tzresult Lwt.t + +val clear_proposals : Raw_context.t -> Raw_context.t Lwt.t + +(** Counts of the votes *) +type ballots = {yay : int64; nay : int64; pass : int64} + +(** All vote counts set to zero. *) +val ballots_zero : ballots + +(** Encoding for {!ballots}. *) +val ballots_encoding : ballots Data_encoding.t + +(** Equality check for {!ballots}. *) +val equal_ballots : ballots -> ballots -> bool + +(** Pretty printer for {!ballots}. *) +val pp_ballots : Format.formatter -> ballots -> unit + +val has_recorded_ballot : + Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t + +(** Records a vote for a delegate, returns a + [Error (Storage_error Existing_key)] if the vote was already registered *) +val record_ballot : + Raw_context.t -> + Signature.Public_key_hash.t -> + Vote_repr.ballot -> + Raw_context.t tzresult Lwt.t + +(** Computes the sum of the current ballots weighted by stake. *) +val get_ballots : Raw_context.t -> ballots tzresult Lwt.t + +val get_ballot_list : + Raw_context.t -> (Signature.Public_key_hash.t * Vote_repr.ballot) list Lwt.t + +val clear_ballots : Raw_context.t -> Raw_context.t Lwt.t + +val listings_encoding : + (Signature.Public_key_hash.t * int64) list Data_encoding.t + +(** Populates [!Storage.Vote.Listings] using the currently existing + staking power and sets `Voting_power_in_listings`. Inactive + delegates or delegates without the minimal required stake are not + included in the listings. *) +val update_listings : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Verifies the presence of a delegate in the listing. *) +val in_listings : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t + +val get_listings : + Raw_context.t -> (Signature.Public_key_hash.t * int64) list Lwt.t + +type delegate_info = { + voting_power : Int64.t option; + current_ballot : Vote_repr.ballot option; + current_proposals : Protocol_hash.t list; + remaining_proposals : int; +} + +val pp_delegate_info : Format.formatter -> delegate_info -> unit + +val delegate_info_encoding : delegate_info Data_encoding.t + +val get_delegate_info : + Raw_context.t -> Signature.public_key_hash -> delegate_info tzresult Lwt.t + +(** Returns the voting power of a delegate from the voting power + listings. This function does not account for gas cost. *) +val get_voting_power_free : + Raw_context.t -> Signature.public_key_hash -> int64 tzresult Lwt.t + +(** Same as [get_voting_power_free] but consumes gas. *) +val get_voting_power : + Raw_context.t -> + Signature.public_key_hash -> + (Raw_context.t * int64) tzresult Lwt.t + +(** Same as [get_voting_power_free] but computes the voting power + based on the current stake of the delegate instead of reading it + from the vote listings. *) +val get_current_voting_power_free : + Raw_context.t -> Signature.public_key_hash -> int64 tzresult Lwt.t + +(** Returns the sum of all voting power in the listings, + without accounting for gas cost. *) +val get_total_voting_power_free : Raw_context.t -> int64 tzresult Lwt.t + +(** Returns the sum of all voting power in the listings. *) +val get_total_voting_power : + Raw_context.t -> (Raw_context.t * int64) tzresult Lwt.t + +val get_current_quorum : Raw_context.t -> int32 tzresult Lwt.t + +val get_participation_ema : Raw_context.t -> int32 tzresult Lwt.t + +val set_participation_ema : + Raw_context.t -> int32 -> Raw_context.t tzresult Lwt.t + +(** Indicates whether there is a current proposal in the storage. *) +val current_proposal_exists : Raw_context.t -> bool Lwt.t + +(** Retrieves the current proposal. + + @return [Error Storage_error] if there is no current proposal, or + if the deserialization fails. *) +val get_current_proposal : Raw_context.t -> Protocol_hash.t tzresult Lwt.t + +(** Retrieves the current proposal. + + @return [None] if there is no current proposal. + + @return [Error Storage_error] if the deserialization fails. *) +val find_current_proposal : + Raw_context.t -> Protocol_hash.t option tzresult Lwt.t + +(** Registers a current proposal. + + @return [Error (Storage_error Existing_key)] if there was already + a current proposal. *) +val init_current_proposal : + Raw_context.t -> Protocol_hash.t -> Raw_context.t tzresult Lwt.t + +(** Removes the current proposal. Does nothing if there was no current + proposal. *) +val clear_current_proposal : Raw_context.t -> Raw_context.t Lwt.t + +(** Sets the initial quorum to 80% and period kind to proposal. *) +val init : + Raw_context.t -> start_position:Int32.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.ml b/src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.ml new file mode 100644 index 000000000000..7fa796d42340 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.ml @@ -0,0 +1,146 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Block headers contain some fields whose values represent the block + producer's opinion on some topics. The votes are averaged to get an + estimation of the will of the stake-weighted majority of bakers on + these topics. The protocol can then perform automatic actions + depending on the values of these averages; typically activating or + deactivating some features. + + This module is about the computation of these averages. + + We use exponential moving averages (EMA for short) because they can + easily and efficiently be implemented because a single value needs to + be stored in the context for each average. Each EMA is updated once per + block and stored in the context. It is represented using a 32-bit + signed integer but it can only take non-negative values in a range + of the form 0...ema_max where the constant ema_max, the maximum + value of the EMA, is a parameter of this module. To update an EMA, + we multiply the EMA computed in the previous block by a constant + factor slightly less than 1 called the attenuation factor, and then + we either add or remove (depending on the vote that was casted in + the block header) another constant called the baker's contribution + to the EMA. The baker contribution is also a parameter of this + module. When multiplying by the attenuation factor, we round toward + the middle of the 0...ema_max range. The update formula is thus: + + new_ema = ((old_ema - ema_max/2) * attenuation_factor) +- baker_contribution + ema_max/2 + +*) + +module type EMA_PARAMETERS = sig + val baker_contribution : Z.t + + val ema_max : Int32.t + + (* We don't need to parameterize by the attenuation factor because + it can be computed from the two other parameters with the + following formula: + + attenuation_factor = (ema_max - 2 baker_contribution) / ema_max + *) +end + +module type T = sig + type t + + val of_int32 : Int32.t -> t tzresult Lwt.t + + val zero : t + + val to_int32 : t -> Int32.t + + val encoding : t Data_encoding.t + + val ( < ) : t -> Int32.t -> bool + + val update_ema_up : t -> t + + val update_ema_down : t -> t +end + +module Make (EMA_parameters : EMA_PARAMETERS) : T = struct + type t = Int32.t + (* Invariant 0l <= ema <= EMA_Parameters.ema_max *) + + (* This error is not registered because we don't expect it to be + raised. *) + type error += Toggle_ema_out_of_bound of Int32.t + + let check_bounds x = Compare.Int32.(0l <= x && x <= EMA_parameters.ema_max) + + let of_int32 (x : Int32.t) : t tzresult Lwt.t = + if check_bounds x then return x else tzfail @@ Toggle_ema_out_of_bound x + + let zero : t = Int32.zero + + (* The conv_with_guard combinator of Data_encoding expects a (_, string) result. *) + let of_int32_for_encoding x = + if check_bounds x then Ok x else Error "out of bounds" + + let to_int32 (ema : t) : Int32.t = ema + + (* We perform the computations in Z to avoid overflows. *) + + let ema_max_z = Z.of_int32 EMA_parameters.ema_max + + let attenuation_numerator = + Z.(sub ema_max_z (mul (of_int 2) EMA_parameters.baker_contribution)) + + let attenuation_denominator = ema_max_z + + let attenuate z = + Z.(div (mul attenuation_numerator z) attenuation_denominator) + + let half_ema_max_z = Z.(div ema_max_z (of_int 2)) + + (* Outside of this module, the EMA is always between 0l and ema_max. + This [recenter] wrappers, puts it in between -ema_max/2 and + ema_max/2. The goal of this recentering around zero is to make + [update_ema_off] and [update_ema_on] behave symmetrically with + respect to rounding. *) + let recenter f ema = Z.(add half_ema_max_z (f (sub ema half_ema_max_z))) + + let update_ema_up (ema : t) : t = + let ema = Z.of_int32 ema in + recenter + (fun ema -> Z.add (attenuate ema) EMA_parameters.baker_contribution) + ema + |> Z.to_int32 + + let update_ema_down (ema : t) : t = + let ema = Z.of_int32 ema in + recenter + (fun ema -> Z.sub (attenuate ema) EMA_parameters.baker_contribution) + ema + |> Z.to_int32 + + let ( < ) : t -> Int32.t -> bool = Compare.Int32.( < ) + + let encoding : t Data_encoding.t = + Data_encoding.(conv_with_guard to_int32 of_int32_for_encoding int32) +end diff --git a/src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.mli b/src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.mli new file mode 100644 index 000000000000..bca19dbb44eb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/votes_EMA_repr.mli @@ -0,0 +1,56 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Tocqueville Group, Inc. *) +(* Copyright (c) 2023 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type EMA_PARAMETERS = sig + (* This represents the impact on the EMA of a single block + vote. Between voting On and voting Off, the impact on the EMA is + twice this number. *) + val baker_contribution : Z.t + + (* This is the maximum value that the EMA can take. The minimal + value cannot be set, it is 0L. *) + val ema_max : Int32.t +end + +module type T = sig + type t + + val of_int32 : Int32.t -> t tzresult Lwt.t + + val zero : t + + val to_int32 : t -> Int32.t + + val encoding : t Data_encoding.t + + val ( < ) : t -> Int32.t -> bool + + val update_ema_up : t -> t + + val update_ema_down : t -> t +end + +module Make (_ : EMA_PARAMETERS) : T diff --git a/src/proto_020_PsParisC/lib_protocol/voting_period_repr.ml b/src/proto_020_PsParisC/lib_protocol/voting_period_repr.ml new file mode 100644 index 000000000000..de4cf915bc46 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/voting_period_repr.ml @@ -0,0 +1,175 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type kind = Proposal | Exploration | Cooldown | Promotion | Adoption + +let string_of_kind = function + | Proposal -> "proposal" + | Exploration -> "exploration" + | Cooldown -> "cooldown" + | Promotion -> "promotion" + | Adoption -> "adoption" + +let pp_kind ppf kind = Format.fprintf ppf "%s" @@ string_of_kind kind + +let kind_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + (Tag 0) + ~title:"Proposal" + (constant "proposal") + (function Proposal -> Some () | _ -> None) + (fun () -> Proposal); + case + (Tag 1) + ~title:"exploration" + (constant "exploration") + (function Exploration -> Some () | _ -> None) + (fun () -> Exploration); + case + (Tag 2) + ~title:"Cooldown" + (constant "cooldown") + (function Cooldown -> Some () | _ -> None) + (fun () -> Cooldown); + case + (Tag 3) + ~title:"Promotion" + (constant "promotion") + (function Promotion -> Some () | _ -> None) + (fun () -> Promotion); + case + (Tag 4) + ~title:"Adoption" + (constant "adoption") + (function Adoption -> Some () | _ -> None) + (fun () -> Adoption); + ] + +let succ_kind = function + | Proposal -> Exploration + | Exploration -> Cooldown + | Cooldown -> Promotion + | Promotion -> Adoption + | Adoption -> Proposal + +type voting_period = {index : int32; kind : kind; start_position : int32} + +type t = voting_period + +type info = {voting_period : t; position : int32; remaining : int32} + +let root ~start_position = {index = 0l; kind = Proposal; start_position} + +let pp ppf {index; kind; start_position} = + Format.fprintf + ppf + "@[index: %ld,@ kind:%a,@ start_position: %ld@]" + index + pp_kind + kind + start_position + +let pp_info ppf {voting_period; position; remaining} = + Format.fprintf + ppf + "@[voting_period: %a,@ position:%ld,@ remaining: %ld@]" + pp + voting_period + position + remaining + +let encoding = + let open Data_encoding in + conv + (fun {index; kind; start_position} -> (index, kind, start_position)) + (fun (index, kind, start_position) -> {index; kind; start_position}) + (obj3 + (req + "index" + ~description: + "The voting period's index. Starts at 0 with the first block of \ + the Alpha family of protocols." + int32) + (req + ~description: + "One of the several kinds of periods in the voting procedure." + "kind" + kind_encoding) + (req + ~description: + "The relative position of the first level of the period with \ + respect to the first level of the Alpha family of protocols." + "start_position" + int32)) + +let info_encoding = + let open Data_encoding in + conv + (fun {voting_period; position; remaining} -> + (voting_period, position, remaining)) + (fun (voting_period, position, remaining) -> + {voting_period; position; remaining}) + (obj3 + (req + ~description:"The voting period to which the block belongs." + "voting_period" + encoding) + (req + ~description:"The position of the block within the voting period." + "position" + int32) + (req + ~description: + "The number of blocks remaining till the end of the voting period." + "remaining" + int32)) + +include Compare.Make (struct + type nonrec t = t + + let compare p p' = Compare.Int32.compare p.index p'.index +end) + +let raw_reset period ~start_position = + let index = Int32.succ period.index in + let kind = Proposal in + {index; kind; start_position} + +let raw_succ period ~start_position = + let index = Int32.succ period.index in + let kind = succ_kind period.kind in + {index; kind; start_position} + +let position_since (level : Level_repr.t) (voting_period : t) = + Int32.(sub level.level_position voting_period.start_position) + +let remaining_blocks (level : Level_repr.t) (voting_period : t) + ~blocks_per_voting_period = + let position = position_since level voting_period in + Int32.(sub blocks_per_voting_period (succ position)) diff --git a/src/proto_020_PsParisC/lib_protocol/voting_period_repr.mli b/src/proto_020_PsParisC/lib_protocol/voting_period_repr.mli new file mode 100644 index 000000000000..92e87bf1236c --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/voting_period_repr.mli @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The voting period kinds are ordered as follows: + Proposal -> Exploration -> Cooldown -> Promotion -> Adoption. + This order is the one used be the function [succ] below. + *) +type kind = + | Proposal (** protocols can be proposed *) + | Exploration (** a proposal can be voted *) + | Cooldown (** a delay before the second vote of the Promotion period. *) + | Promotion (** activation can be voted *) + | Adoption (** a delay before activation *) + +val kind_encoding : kind Data_encoding.t + +(** A voting period can be of several kinds and is uniquely identified by + the counter 'index'. The 'start_position' represents the relative + position of the first level of the period with respect to the + first level of the Alpha family of protocols. *) +type voting_period = {index : Int32.t; kind : kind; start_position : Int32.t} + +type t = voting_period + +(** Information about a block with respect to the voting period it + belongs to: the voting period, the position within the voting + period and the number of remaining blocks till the end of the + period. The following invariant is satisfied: + `position + remaining + 1 = blocks_per_voting_period` *) +type info = {voting_period : t; position : Int32.t; remaining : Int32.t} + +val root : start_position:Int32.t -> t + +include Compare.S with type t := voting_period + +val encoding : t Data_encoding.t + +val info_encoding : info Data_encoding.t + +val pp : Format.formatter -> t -> unit + +val pp_info : Format.formatter -> info -> unit + +val pp_kind : Format.formatter -> kind -> unit + +(** [raw_reset period ~start_position] increment the index by one and set the + kind to Proposal which is the period kind that start the voting + process. [start_position] is the level at wich this voting_period started. +*) +val raw_reset : t -> start_position:Int32.t -> t + +(** [raw_succ period ~start_position] increment the index by one and set the + kind to its successor. [start_position] is the level at which this + voting_period started. *) +val raw_succ : t -> start_position:Int32.t -> t + +val position_since : Level_repr.t -> t -> Int32.t + +val remaining_blocks : + Level_repr.t -> t -> blocks_per_voting_period:Int32.t -> Int32.t diff --git a/src/proto_020_PsParisC/lib_protocol/voting_period_storage.ml b/src/proto_020_PsParisC/lib_protocol/voting_period_storage.ml new file mode 100644 index 000000000000..67cc9206f3bf --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/voting_period_storage.ml @@ -0,0 +1,229 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* + The shell uses the convention that a context at level n is the resulting + context of the application of block n. + Therefore when using an RPC on the last level of a voting period, the context + that is inspected is the resulting one. + + However [Amendment.may_start_new_voting_period] is run at the end of voting + period and it has to prepare the context for validating operations of the next + period. This causes the counter-intuitive result that the info returned by RPCs + at last level of a voting period mention data of the next voting period. + + For example, when validating the last block of a proposal period at level n + we have: + - Input context: + + voting_period = { kind = Proposal; + index = i; + start_position = n - blocks_per_voting_period} + + - position = n - start_position = blocks_per_voting_period + - remaining = blocks_per_voting_period - (position + 1) = 0 + + - Output context: + + voting_period = { kind = Exploration; + index = i + 1; + start_position = n + 1} + + Now if we calculate position and remaining in the voting period we get + strange results: + - position = n - (n + 1) = -1 + - remaining = blocks_per_voting_period + + To work around this issue, two RPCs were added + `Voting_period_storage.get_rpc_current_info`, which returns the correct + info also for the last context of a period, and + `Voting_period_storage.get_rpc_succ_info`, which can be used at the last + context of a period to craft operations that will be valid for the first + block of the new period. + + This odd behaviour could be fixed if [Amendment.may_start_new_voting_period] + was called when we start validating the first block of a voting period instead + that at the end of the validation of the last block of a voting period. + This should be carefully done because the voting period listing depends on + the rolls and it might break some invariant. + + When this is implemented one should: + - edit the function [reset_current] and [inc_current] to use the + current level and not the next one. + - remove the storage for pred_kind + - make Voting_period_repr.t abstract + + You can also look at the MR description here: + https://gitlab.com/metastatedev/tezos/-/merge_requests/333 + *) + +(* Voting periods start at the first block of a cycle. More formally, + the invariant of start_position with respect to cycle_position is: + cycle_position mod blocks_per_cycle == + position_in_period mod blocks_per_cycle *) + +let blocks_per_voting_period ctxt = + let open Constants_storage in + Int32.(mul (cycles_per_voting_period ctxt) (blocks_per_cycle ctxt)) + +let set_current = Storage.Vote.Current_period.update + +let get_current = Storage.Vote.Current_period.get + +let init = Storage.Vote.Current_period.init + +let init_first_period ctxt ~start_position = + let open Lwt_result_syntax in + let* ctxt = init ctxt @@ Voting_period_repr.root ~start_position in + Storage.Vote.Pred_period_kind.init ctxt Voting_period_repr.Proposal + +let common ctxt = + let open Lwt_result_syntax in + let* current_period = get_current ctxt in + let+ ctxt = Storage.Vote.Pred_period_kind.update ctxt current_period.kind in + let start_position = + (* because we are preparing the voting period for the next block we need to + use the next level. *) + Int32.succ (Level_storage.current ctxt).level_position + in + (ctxt, current_period, start_position) + +let reset ctxt = + let open Lwt_result_syntax in + let* ctxt, current_period, start_position = common ctxt in + Voting_period_repr.raw_reset current_period ~start_position + |> set_current ctxt + +let succ ctxt = + let open Lwt_result_syntax in + let* ctxt, current_period, start_position = common ctxt in + Voting_period_repr.raw_succ current_period ~start_position |> set_current ctxt + +let get_current_kind ctxt = + let open Lwt_result_syntax in + let+ {kind; _} = get_current ctxt in + kind + +let get_current_info ctxt = + let open Lwt_result_syntax in + let+ voting_period = get_current ctxt in + let blocks_per_voting_period = blocks_per_voting_period ctxt in + let level = Level_storage.current ctxt in + let position = Voting_period_repr.position_since level voting_period in + let remaining = + Voting_period_repr.remaining_blocks + level + voting_period + ~blocks_per_voting_period + in + Voting_period_repr.{voting_period; position; remaining} + +let get_current_remaining ctxt = + let open Lwt_result_syntax in + let+ voting_period = get_current ctxt in + let blocks_per_voting_period = blocks_per_voting_period ctxt in + Voting_period_repr.remaining_blocks + (Level_storage.current ctxt) + voting_period + ~blocks_per_voting_period + +let is_last_block ctxt = + let open Lwt_result_syntax in + let+ remaining = get_current_remaining ctxt in + Compare.Int32.(remaining = 0l) + +let blocks_before_activation ctxt = + let open Lwt_result_syntax in + let* voting_period = get_current ctxt in + match voting_period with + | Voting_period_repr.{kind = Adoption; _} -> + let* result = get_current_remaining ctxt in + return_some result + | _ -> return_none + +let get_rpc_current_info ctxt = + let open Lwt_result_syntax in + let* ({voting_period; position; _} as voting_period_info) = + get_current_info ctxt + in + if Compare.Int32.(position = Int32.minus_one) then + let level = Level_storage.current ctxt in + let blocks_per_voting_period = blocks_per_voting_period ctxt in + let+ pred_kind = Storage.Vote.Pred_period_kind.get ctxt in + let voting_period : Voting_period_repr.t = + { + index = Int32.pred voting_period.index; + kind = pred_kind; + start_position = + Int32.(sub voting_period.start_position blocks_per_voting_period); + } + in + let position = Voting_period_repr.position_since level voting_period in + let remaining = + Voting_period_repr.remaining_blocks + level + voting_period + ~blocks_per_voting_period + in + ({voting_period; remaining; position} : Voting_period_repr.info) + else return voting_period_info + +let get_rpc_succ_info ctxt = + let open Lwt_result_syntax in + let*? level = + Level_storage.from_raw_with_offset + ctxt + ~offset:1l + (Level_storage.current ctxt).level + in + let+ voting_period = get_current ctxt in + let blocks_per_voting_period = blocks_per_voting_period ctxt in + let position = Voting_period_repr.position_since level voting_period in + let remaining = + Voting_period_repr.remaining_blocks + level + voting_period + ~blocks_per_voting_period + in + Voting_period_repr.{voting_period; position; remaining} + +module Testnet_dictator = struct + (* This error must never happen. It is deliberately unregistered so + that the execution fails loudly if [overwrite_current_kind] is + ever called on mainnet. *) + type error += Forbidden_on_mainnet + + let overwrite_current_kind ctxt chain_id kind = + let open Lwt_result_syntax in + let*? () = + error_when + Chain_id.(chain_id = Constants_repr.mainnet_id) + Forbidden_on_mainnet + in + let* current_period = get_current ctxt in + let new_period = {current_period with kind} in + set_current ctxt new_period +end diff --git a/src/proto_020_PsParisC/lib_protocol/voting_period_storage.mli b/src/proto_020_PsParisC/lib_protocol/voting_period_storage.mli new file mode 100644 index 000000000000..2d8a4ea2d8a1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/voting_period_storage.mli @@ -0,0 +1,76 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2020 Metastate AG *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Initializes the current context with voting period information. *) +val init : Raw_context.t -> Voting_period_repr.t -> Raw_context.t tzresult Lwt.t + +(** Sets the initial period to [{voting_period = root; kind = Proposal; + start_position}]. *) +val init_first_period : + Raw_context.t -> start_position:Int32.t -> Raw_context.t tzresult Lwt.t + +(** Increment the index by one and set the kind to Proposal. *) +val reset : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Increment the index by one and set the kind to its successor. *) +val succ : Raw_context.t -> Raw_context.t tzresult Lwt.t + +(** Returns information about the current voting period. *) +val get_current : Raw_context.t -> Voting_period_repr.t tzresult Lwt.t + +(** Returns the current voting period kind. *) +val get_current_kind : Raw_context.t -> Voting_period_repr.kind tzresult Lwt.t + +(** Returns true if the context level is the last of current voting period. *) +val is_last_block : Raw_context.t -> bool tzresult Lwt.t + +(** [blocks_before_activation ctxt] returns [Some b] if the current + voting period is the Adoption and [b] blocks must be waited before activation + of the next protocol amendment. Returns [None] if the current period is not + Adoption (then more than [Constants_storage.blocks_per_voting_period] must + be waited before activation). *) +val blocks_before_activation : Raw_context.t -> int32 option tzresult Lwt.t + +(** Returns the voting period information for the current level. *) +val get_rpc_current_info : + Raw_context.t -> Voting_period_repr.info tzresult Lwt.t + +(** Returns the voting period information for the next level. *) +val get_rpc_succ_info : Raw_context.t -> Voting_period_repr.info tzresult Lwt.t + +module Testnet_dictator : sig + (** Overwrites the kind of the current voting period WITHOUT + incrementing the index. + + Must ONLY be called by the testnet dictator on a testnet. + + @return [Error Storage_error] if the current voting period is + not set or its deserialization fails. *) + val overwrite_current_kind : + Raw_context.t -> + Chain_id.t -> + Voting_period_repr.kind -> + Raw_context.t tzresult Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/voting_services.ml b/src/proto_020_PsParisC/lib_protocol/voting_services.ml new file mode 100644 index 000000000000..5755c0f52490 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/voting_services.ml @@ -0,0 +1,162 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +module S = struct + let path = RPC_path.(open_root / "votes") + + let ballots = + RPC_service.get_service + ~description:"Sum of ballots casted so far during a voting period." + ~query:RPC_query.empty + ~output:Vote.ballots_encoding + RPC_path.(path / "ballots") + + let ballot_list = + RPC_service.get_service + ~description:"Ballots casted so far during a voting period." + ~query:RPC_query.empty + ~output: + Data_encoding.( + list + (obj2 + (req "pkh" Signature.Public_key_hash.encoding) + (req "ballot" Vote.ballot_encoding))) + RPC_path.(path / "ballot_list") + + let current_period = + RPC_service.get_service + ~description: + "Returns the voting period (index, kind, starting position) and \ + related information (position, remaining) of the interrogated block." + ~query:RPC_query.empty + ~output:Voting_period.info_encoding + RPC_path.(path / "current_period") + + let successor_period = + RPC_service.get_service + ~description: + "Returns the voting period (index, kind, starting position) and \ + related information (position, remaining) of the next block.Useful to \ + craft operations that will be valid in the next block." + ~query:RPC_query.empty + ~output:Voting_period.info_encoding + RPC_path.(path / "successor_period") + + let current_quorum = + RPC_service.get_service + ~description:"Current expected quorum." + ~query:RPC_query.empty + ~output:Data_encoding.int32 + RPC_path.(path / "current_quorum") + + let listings = + RPC_service.get_service + ~description:"List of delegates with their voting power." + ~query:RPC_query.empty + ~output:Vote.listings_encoding + RPC_path.(path / "listings") + + let proposals = + RPC_service.get_service + ~description:"List of proposals with number of supporters." + ~query:RPC_query.empty + ~output:(Protocol_hash.Map.encoding Data_encoding.int64) + RPC_path.(path / "proposals") + + let current_proposal = + RPC_service.get_service + ~description:"Current proposal under evaluation." + ~query:RPC_query.empty + ~output:(Data_encoding.option Protocol_hash.encoding) + RPC_path.(path / "current_proposal") + + let total_voting_power = + RPC_service.get_service + ~description:"Total voting power in the voting listings." + ~query:RPC_query.empty + ~output:Data_encoding.int64 + RPC_path.(path / "total_voting_power") + + let delegate_proposal_count = + RPC_service.get_service + ~description:"Number of votes casted during the current period." + ~query:RPC_query.empty + ~output:Data_encoding.int31 + RPC_path.(path / "proposal_count" /: Signature.Public_key_hash.rpc_arg) +end + +let register () = + let open Lwt_syntax in + let open Services_registration in + register0 ~chunked:false S.ballots (fun ctxt () () -> Vote.get_ballots ctxt) ; + register0 ~chunked:true S.ballot_list (fun ctxt () () -> + let+ result = Vote.get_ballot_list ctxt in + Ok result) ; + register0 ~chunked:false S.current_period (fun ctxt () () -> + Voting_period.get_rpc_current_info ctxt) ; + register0 ~chunked:false S.successor_period (fun ctxt () () -> + Voting_period.get_rpc_succ_info ctxt) ; + register0 ~chunked:false S.current_quorum (fun ctxt () () -> + Vote.get_current_quorum ctxt) ; + register0 ~chunked:true S.proposals (fun ctxt () () -> + Vote.get_proposals ctxt) ; + register0 ~chunked:true S.listings (fun ctxt () () -> + let+ result = Vote.get_listings ctxt in + Ok result) ; + register0 ~chunked:false S.current_proposal (fun ctxt () () -> + Vote.find_current_proposal ctxt) ; + register0 ~chunked:false S.total_voting_power (fun ctxt () () -> + Vote.get_total_voting_power_free ctxt) ; + register1 ~chunked:false S.delegate_proposal_count (fun ctxt pkh () () -> + Vote.get_delegate_proposal_count ctxt pkh) + +let ballots ctxt block = RPC_context.make_call0 S.ballots ctxt block () () + +let ballot_list ctxt block = + RPC_context.make_call0 S.ballot_list ctxt block () () + +let current_period ctxt block = + RPC_context.make_call0 S.current_period ctxt block () () + +let successor_period ctxt block = + RPC_context.make_call0 S.successor_period ctxt block () () + +let current_quorum ctxt block = + RPC_context.make_call0 S.current_quorum ctxt block () () + +let listings ctxt block = RPC_context.make_call0 S.listings ctxt block () () + +let proposals ctxt block = RPC_context.make_call0 S.proposals ctxt block () () + +let current_proposal ctxt block = + RPC_context.make_call0 S.current_proposal ctxt block () () + +let total_voting_power ctxt block = + RPC_context.make_call0 S.total_voting_power ctxt block () () + +let delegate_proposal_count ctxt block pkh = + RPC_context.make_call1 S.delegate_proposal_count ctxt block pkh () () diff --git a/src/proto_020_PsParisC/lib_protocol/voting_services.mli b/src/proto_020_PsParisC/lib_protocol/voting_services.mli new file mode 100644 index 000000000000..377ce0806597 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/voting_services.mli @@ -0,0 +1,69 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides RPC services that return voting-related information. *) + +open Alpha_context + +val ballots : 'a #RPC_context.simple -> 'a -> Vote.ballots shell_tzresult Lwt.t + +val ballot_list : + 'a #RPC_context.simple -> + 'a -> + (Signature.Public_key_hash.t * Vote.ballot) list shell_tzresult Lwt.t + +val current_period : + 'a #RPC_context.simple -> 'a -> Voting_period.info shell_tzresult Lwt.t + +val successor_period : + 'a #RPC_context.simple -> 'a -> Voting_period.info shell_tzresult Lwt.t + +val current_quorum : + 'a #RPC_context.simple -> 'a -> Int32.t shell_tzresult Lwt.t + +val listings : + 'a #RPC_context.simple -> + 'a -> + (Signature.Public_key_hash.t * int64) list shell_tzresult Lwt.t + +val proposals : + 'a #RPC_context.simple -> + 'a -> + Int64.t Protocol_hash.Map.t shell_tzresult Lwt.t + +val current_proposal : + 'a #RPC_context.simple -> 'a -> Protocol_hash.t option shell_tzresult Lwt.t + +val register : unit -> unit + +val total_voting_power : + 'a #RPC_context.simple -> 'a -> Int64.t shell_tzresult Lwt.t + +val delegate_proposal_count : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + int shell_tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.ml new file mode 100644 index 000000000000..70efc0015660 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.ml @@ -0,0 +1,127 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module SMap = Map.Make (String) + +type static = { + public_parameters : Plonk.public_parameters; + state_length : int; + circuits_info : [`Public | `Private | `Fee] SMap.t; + nb_ops : int; +} + +type dynamic = { + state : Zk_rollup_state_repr.t; + paid_l2_operations_storage_space : Z.t; + used_l2_operations_storage_space : Z.t; +} + +type t = {static : static; dynamic : dynamic} + +let circuits_info_encoding : [`Public | `Private | `Fee] SMap.t Data_encoding.t + = + let open Data_encoding in + let variant_encoding = + let public_tag, public_encoding = (0, obj1 @@ req "public" unit) in + let private_tag, private_encoding = (1, obj1 @@ req "private" unit) in + let fee_tag, fee_encoding = (2, obj1 @@ req "fee" unit) in + matching + (function + | `Public -> matched public_tag public_encoding () + | `Private -> matched private_tag private_encoding () + | `Fee -> matched fee_tag fee_encoding ()) + [ + case + ~title:"Public" + (Tag public_tag) + public_encoding + (function `Public -> Some () | _ -> None) + (fun () -> `Public); + case + ~title:"Private" + (Tag private_tag) + private_encoding + (function `Private -> Some () | _ -> None) + (fun () -> `Private); + case + ~title:"Fee" + (Tag fee_tag) + fee_encoding + (function `Fee -> Some () | _ -> None) + (fun () -> `Fee); + ] + in + conv_with_guard + (fun m -> List.of_seq @@ SMap.to_seq m) + (fun l -> + let m = SMap.of_seq @@ List.to_seq l in + if + (* Check that the list has no duplicated keys *) + Compare.List_length_with.(l <> SMap.cardinal m) + then Error "Zk_rollup_origination: circuits_info has duplicated keys" + else Ok m) + (list (tup2 (string Plain) variant_encoding)) + +let encoding = + let open Data_encoding in + let static_encoding = + conv + (fun {public_parameters; state_length; circuits_info; nb_ops} -> + (public_parameters, state_length, circuits_info, nb_ops)) + (fun (public_parameters, state_length, circuits_info, nb_ops) -> + {public_parameters; state_length; circuits_info; nb_ops}) + (obj4 + (req "public_parameters" Plonk.public_parameters_encoding) + (req "state_length" int31) + (req "circuits_info" circuits_info_encoding) + (req "nb_ops" int31)) + in + let dynamic_encoding = + conv + (fun { + state; + paid_l2_operations_storage_space; + used_l2_operations_storage_space; + } -> + ( state, + paid_l2_operations_storage_space, + used_l2_operations_storage_space )) + (fun ( state, + paid_l2_operations_storage_space, + used_l2_operations_storage_space ) -> + { + state; + paid_l2_operations_storage_space; + used_l2_operations_storage_space; + }) + (obj3 + (req "state" Zk_rollup_state_repr.encoding) + (req "paid_l2_operations_storage_space" n) + (req "used_l2_operations_storage_space" n)) + in + conv + (fun {static; dynamic} -> (static, dynamic)) + (fun (static, dynamic) -> {static; dynamic}) + (obj2 (req "static" static_encoding) (req "dynamic" dynamic_encoding)) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.mli new file mode 100644 index 000000000000..57c133098a1a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_account_repr.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module SMap : Map.S with type key = string + +(** Representation of a ZK Rollup account. *) + +(** Static part of a ZKRU account. These are set at origination, + after which they cannot be modified. *) +type static = { + public_parameters : Plonk.public_parameters; + (** Input to the Plonk verifier that are fixed once the circuits + are decided. *) + state_length : int; (** Number of scalars in the state. *) + circuits_info : [`Public | `Private | `Fee] SMap.t; + (** Circuit names, alongside a tag indicating its kind. *) + nb_ops : int; (** Valid op codes of L2 operations must be in \[0, nb_ops) *) +} + +(** Dynamic part of a ZKRU account. *) +type dynamic = { + state : Zk_rollup_state_repr.t; + (** Array of scalars representing the state of the rollup + at a given level. *) + paid_l2_operations_storage_space : Z.t; + (** Number of bytes for storage of L2 operations that have + been already paid for. *) + used_l2_operations_storage_space : Z.t; + (** Number of bytes for storage of L2 operations that are + being used. *) +} + +type t = {static : static; dynamic : dynamic} + +val encoding : t Data_encoding.t + +(* Encoding for the [circuits_info] field. + Checks that keys are not duplicated in serialized representation. *) +val circuits_info_encoding : [`Public | `Private | `Fee] SMap.t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.ml new file mode 100644 index 000000000000..2027fe6416de --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.ml @@ -0,0 +1,494 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Alpha_context + +type error += Zk_rollup_feature_disabled | Zk_rollup_negative_nb_ops + +let () = + let description = "ZK rollups will be enabled in a future proposal." in + register_error_kind + `Permanent + ~id:"operation.zk_rollup_disabled" + ~title:"ZK rollups are disabled" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Zk_rollup_feature_disabled -> Some () | _ -> None) + (fun () -> Zk_rollup_feature_disabled) ; + let description = "The value of [nb_ops] should never be negative." in + register_error_kind + `Permanent + ~id:"operation.zk_rollup_negative_nb_ops" + ~title:"ZK rollups negative number of operations" + ~description + ~pp:(fun ppf () -> Format.fprintf ppf "%s" description) + Data_encoding.unit + (function Zk_rollup_negative_nb_ops -> Some () | _ -> None) + (fun () -> Zk_rollup_negative_nb_ops) + +let assert_feature_enabled ctxt = + error_unless (Constants.zk_rollup_enable ctxt) Zk_rollup_feature_disabled + +let originate ~ctxt_before_op ~ctxt ~public_parameters ~circuits_info + ~init_state ~nb_ops = + let open Lwt_result_syntax in + let*? () = assert_feature_enabled ctxt in + let*? () = error_when Compare.Int.(nb_ops < 0) Zk_rollup_negative_nb_ops in + let+ ctxt, originated_zk_rollup, storage_size = + Zk_rollup.originate + ctxt + { + public_parameters; + state_length = Array.length init_state; + circuits_info; + nb_ops; + } + ~init_state + in + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Apply_results.Zk_rollup_origination_result + { + balance_updates = []; + originated_zk_rollup; + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + consumed_gas; + storage_size; + } + in + (ctxt, result, []) + +(** [parse_ticket ~ticketer ~contents ~ty ctxt] reconstructs a ticket from + individual parts submitted as part of a Zk_rollup_publish operation. *) +let parse_ticket ~ticketer ~contents ~ty ctxt = + let open Lwt_result_syntax in + let*? Ex_comparable_ty contents_type, ctxt = + Script_ir_translator.parse_comparable_ty ctxt (Micheline.root ty) + in + let* contents, ctxt = + Script_ir_translator.parse_comparable_data + ctxt + contents_type + (Micheline.root contents) + in + return (ctxt, Ticket_token.Ex_token {ticketer; contents_type; contents}) + +let publish ~ctxt_before_op ~ctxt ~zk_rollup ~l2_ops = + let open Lwt_result_syntax in + let*? () = assert_feature_enabled ctxt in + let open Zk_rollup.Operation in + (* Deposits (i.e. L2 operations with a positive price) cannot be published + through an external operation *) + let*? () = + error_unless + (List.for_all + (fun (l2_op, _ticket_opt) -> Compare.Z.(l2_op.price.amount <= Z.zero)) + l2_ops) + Zk_rollup.Errors.Deposit_as_external + in + (* Check that for every operation to publish: + 1. Their price is zero iff they have no ticket representation + 2. The "token id" of its price is the correct ticket hash + Additionally, for operations with tickets, the hash of the ticket + with the l1 destination from the operation's header is computed. + *) + let* ctxt, l2_ops_with_ticket_hashes = + List.fold_left_map_es + (fun ctxt (l2_op, ticket_opt) -> + match ticket_opt with + | None -> + let*? () = + error_unless + Compare.Z.(l2_op.price.amount = Z.zero) + Zk_rollup.Errors.Invalid_deposit_amount + in + return (ctxt, (l2_op, None)) + | Some Zk_rollup.Ticket.{ticketer; ty; contents} -> + let*? () = + error_when + Compare.Z.(l2_op.price.amount = Z.zero) + Zk_rollup.Errors.Invalid_deposit_amount + in + let* ctxt, ticket_token = + parse_ticket ~ticketer ~contents ~ty ctxt + in + (* Compute the ticket hash with L1 address to be able + to perform an exit / return token *) + let* receiver_ticket_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Contract (Implicit l2_op.l1_dst)) + ticket_token + in + (* Compute the ticket with zk rollup as owner, this is the hash + that is used as token identifier inside the ZKRU (and this + should be price's identifier in this L2 op) *) + let* source_ticket_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Zk_rollup zk_rollup) + ticket_token + in + let*? () = + error_unless + Ticket_hash.(equal l2_op.price.id source_ticket_hash) + Zk_rollup.Errors.Invalid_deposit_ticket + in + return (ctxt, (l2_op, Some receiver_ticket_hash))) + ctxt + l2_ops + in + let+ ctxt, paid_storage_size_diff = + Zk_rollup.add_to_pending ctxt zk_rollup l2_ops_with_ticket_hashes + in + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Apply_results.Zk_rollup_publish_result + {balance_updates = []; consumed_gas; paid_storage_size_diff} + in + (ctxt, result, []) + +let transaction_to_zk_rollup ~ctxt ~parameters_ty ~parameters ~dst_rollup ~since + = + let open Lwt_result_syntax in + let*? () = assert_feature_enabled ctxt in + let*? {ex_ticket; zkru_operation} = + Zk_rollup_parameters.get_deposit_parameters parameters_ty parameters + in + let* ticket_size, ctxt = Ticket_scanner.ex_ticket_size ctxt ex_ticket in + let limit = Constants.zk_rollup_max_ticket_payload_size ctxt in + let*? () = + error_when + Saturation_repr.(ticket_size >! limit) + (Zk_rollup.Errors.Ticket_payload_size_limit_exceeded + {payload_size = ticket_size; limit}) + in + let ex_token, ticket_amount = + Ticket_scanner.ex_token_and_amount_of_ex_ticket ex_ticket + in + (* Compute the ticket hash with zk rollup as owner *) + let* ticket_hash, ctxt = + Ticket_balance_key.of_ex_token ctxt ~owner:(Zk_rollup dst_rollup) ex_token + in + let ticket_amount = Script_int.(to_zint (ticket_amount :> n num)) in + (* Check that the amount and id of the transferred ticket are what + the operation's price claims. *) + let*? () = + error_unless + Compare.Z.(ticket_amount = zkru_operation.price.amount) + Zk_rollup.Errors.Invalid_deposit_amount + in + let*? () = + error_unless + Ticket_hash.(equal ticket_hash zkru_operation.price.id) + Zk_rollup.Errors.Invalid_deposit_ticket + in + (* Compute the ticket hash with L1 address to be able + to perform an exit / return token *) + let* receiver_ticket_hash, ctxt = + Ticket_balance_key.of_ex_token + ctxt + ~owner:(Contract (Implicit zkru_operation.l1_dst)) + ex_token + in + (* Add it to the rollup pending list *) + let+ ctxt, paid_storage_size_diff = + Zk_rollup.add_to_pending + ctxt + Zk_rollup.Operation.(zkru_operation.rollup_id) + [(zkru_operation, Some receiver_ticket_hash)] + in + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + let result = + Apply_internal_results.( + ITransaction_result + (Transaction_to_zk_rollup_result + { + balance_updates = []; + consumed_gas = Gas.consumed ~since ~until:ctxt; + ticket_hash; + paid_storage_size_diff; + })) + in + (ctxt, result, []) + +(* + A ZKRU Update will set a new ZKRU state if the proof sent in the payload + is verified. In order to verify this proof, the protocol needs to + compute the "public inputs" expected by the Plonk circuits that define + a given ZKRU. + The proof's public inputs have to be collected by the protocol, as some of + them will be passed in the operation's payload, but some must be computed + by the protocol (e.g. the current L2 state). + These public inputs will be collected as a string map linking + the circuit identifier to a list of inputs for it (as a circuit might have + been used several times in a proof). + As explained in the documentation, circuits in ZKRUs will be grouped into + three categories: pending (public) operations, private batches and + fee circuit. + Each of these expects a different set of public inputs. For this reason, + the collection of circuit inputs will be collected in three separate steps. +*) + +module SMap = Map.Make (String) + +(* Helper function to collect inputs *) +let insert s x = + SMap.update s (function None -> Some [x] | Some l -> Some (x :: l)) + +(* Traverse the list of pending L2 operations paired with their corresponding + inputs sent in the [Update] computing the full set of inputs for each of + them. + Collect the L2 fees of all L2 operations, and the list of boolean flags + determining whether each L2 operation will trigger an exit. +*) +let collect_pending_ops_inputs ~zk_rollup ~account ~rev_pi_map + ~pending_ops_and_pis = + let open Lwt_result_syntax in + let open Zk_rollup.Update in + let open Zk_rollup.Account in + let* rev_pi_map, new_state, fees, rev_exit_validites = + List.fold_left_es + (fun (rev_pi_map, old_state, fees, rev_exit_validites) + ((l2_op, _ticket_hash_opt), (name, (sent_pi : op_pi))) -> + let new_state = sent_pi.new_state in + let*? () = + error_unless + Compare.Int.(Array.length new_state = account.static.state_length) + Zk_rollup.Errors.Inconsistent_state_update + in + let pi = + Zk_rollup.Circuit_public_inputs.( + Pending_op + { + old_state; + new_state; + fee = sent_pi.fee; + exit_validity = sent_pi.exit_validity; + zk_rollup; + l2_op; + }) + in + let rev_pi_map = + insert + name + (Zk_rollup.Circuit_public_inputs.to_scalar_array pi) + rev_pi_map + in + return + ( rev_pi_map, + new_state, + Bls.Primitive.Fr.add fees sent_pi.fee, + sent_pi.exit_validity :: rev_exit_validites )) + (rev_pi_map, account.dynamic.state, Bls.Primitive.Fr.zero, []) + pending_ops_and_pis + in + return (rev_pi_map, new_state, fees, List.rev rev_exit_validites) + +(* Traverse the partial inputs for the batches of private operations + that the [update] claims to process, computing the full set of inputs. + Check that all circuit identifiers used here are allowed to be used for + private operations and collect the L2 fees. *) +let collect_pivate_batch_inputs ~zk_rollup ~account ~rev_pi_map ~update + ~prev_state ~fees = + let open Lwt_result_syntax in + let open Zk_rollup.Update in + let open Zk_rollup.Account in + let is_private = function Some `Private -> true | _ -> false in + List.fold_left_es + (fun (rev_pi_map, old_state, fees) (name, (sent_pi : private_inner_pi)) -> + let*? () = + error_unless + (is_private + (Zk_rollup.Account.SMap.find name account.static.circuits_info)) + Zk_rollup.Errors.Invalid_circuit + in + let new_state = sent_pi.new_state in + let*? () = + error_unless + Compare.Int.(Array.length new_state = account.static.state_length) + Zk_rollup.Errors.Inconsistent_state_update + in + let pi = + Zk_rollup.Circuit_public_inputs.( + Private_batch {old_state; new_state; fees = sent_pi.fees; zk_rollup}) + in + let rev_pi_map = + insert + name + (Zk_rollup.Circuit_public_inputs.to_scalar_array pi) + rev_pi_map + in + + return (rev_pi_map, new_state, Bls.Primitive.Fr.add fees sent_pi.fees)) + (rev_pi_map, prev_state, fees) + update.private_pis + +let collect_fee_inputs ~prev_state ~update ~fees ~rev_pi_map = + let open Zk_rollup.Update in + let old_state = prev_state in + let new_state = update.fee_pi.new_state in + let pi = Zk_rollup.Circuit_public_inputs.(Fee {old_state; new_state; fees}) in + let rev_pi_map = + insert "fee" (Zk_rollup.Circuit_public_inputs.to_scalar_array pi) rev_pi_map + in + (rev_pi_map, new_state) + +(* Collect and validate the public inputs for the verification *) +let collect_inputs ~zk_rollup ~account ~rev_pi_map ~pending_ops_and_pis ~update + = + let open Lwt_result_syntax in + (* Collect the inputs for the pending L2 ops *) + let* rev_pi_map, new_state, fees, exit_validities = + collect_pending_ops_inputs + ~zk_rollup + ~account + ~rev_pi_map + ~pending_ops_and_pis + in + (* Collect the inputs for private batches of L2 ops *) + let* rev_pi_map, new_state, fees = + collect_pivate_batch_inputs + ~zk_rollup + ~account + ~rev_pi_map + ~update + ~prev_state:new_state + ~fees + in + (* Collect the inputs for the fee circuit, always identified as "fee" *) + let rev_pi_map, new_state = + collect_fee_inputs ~prev_state:new_state ~update ~fees ~rev_pi_map + in + let pi_map = SMap.map List.rev rev_pi_map in + return (pi_map, exit_validities, new_state) + +(* Perform the exits corresponding to the processed public l2 operations *) +let perform_exits ctxt exits = + let open Lwt_result_syntax in + List.fold_left_es + (fun (ctxt, storage_diff) ((op, ticket_hash_opt), exit_validity) -> + let open Zk_rollup.Operation in + match ticket_hash_opt with + | None -> + let*? () = + error_unless + Compare.Z.(Z.zero = op.price.amount) + Zk_rollup.Errors.Invalid_deposit_amount + in + return (ctxt, storage_diff) + | Some receiver_ticket_hash -> + if exit_validity then + let*? amount = + Option.value_e + ~error: + (Error_monad.trace_of_error + Zk_rollup.Errors.Invalid_deposit_amount) + (Ticket_amount.of_zint (Z.abs @@ op.price.amount)) + in + let* ctxt, diff = + Ticket_transfer.transfer_ticket_with_hashes + ctxt + ~sender_hash:op.price.id + ~dst_hash:receiver_ticket_hash + amount + in + return (ctxt, Z.add diff storage_diff) + else return (ctxt, storage_diff)) + (ctxt, Z.zero) + exits + +let update ~ctxt_before_op ~ctxt ~zk_rollup ~update = + let open Lwt_result_syntax in + let open Zk_rollup.Update in + let*? () = assert_feature_enabled ctxt in + let rev_pi_map = SMap.empty in + let* ctxt, account = Zk_rollup.account ctxt zk_rollup in + let update_public_length = List.length update.pending_pis in + let* ctxt, pending_list_length = + Zk_rollup.get_pending_length ctxt zk_rollup + in + let min_pending_to_process = + Constants.zk_rollup_min_pending_to_process ctxt + in + (* The number of pending operations processed by an update must be at least + [min(pending_list_length, min_pending_to_process)] and at most + [pending_list_length].*) + let*? () = + error_when + Compare.Int.( + update_public_length < pending_list_length + && update_public_length < min_pending_to_process) + Zk_rollup.Errors.Pending_bound + in + let* ctxt, pending_ops = + Zk_rollup.get_prefix ctxt zk_rollup update_public_length + in + (* It's safe to use [combine_drop], as at this point both lists will have the + same length. *) + let pending_ops_and_pis = List.combine_drop pending_ops update.pending_pis in + (* Collect the inputs for the verification *) + let* pi_map, exit_validities, new_state = + collect_inputs ~zk_rollup ~account ~rev_pi_map ~pending_ops_and_pis ~update + in + (* Run the verification of the Plonk proof *) + let verified = + Plonk.verify + account.static.public_parameters + (SMap.bindings pi_map) + update.proof + in + let*? () = error_unless verified Zk_rollup.Errors.Invalid_verification in + (* Update the ZKRU storage with the new state and dropping the processed + public L2 operations from the pending list *) + let* ctxt = + Zk_rollup.update + ctxt + zk_rollup + ~pending_to_drop:update_public_length + ~new_account: + {account with dynamic = {account.dynamic with state = new_state}} + in + (* Perform exits of processed public L2 operations *) + let exits = List.combine_drop pending_ops exit_validities in + let* ctxt, exits_paid_storage_size_diff = perform_exits ctxt exits in + + (* TODO https://gitlab.com/tezos/tezos/-/issues/3544 + Carbonate ZKRU operations *) + let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in + let result = + Apply_results.Zk_rollup_update_result + { + balance_updates = []; + consumed_gas; + paid_storage_size_diff = exits_paid_storage_size_diff; + } + in + return (ctxt, result, []) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.mli new file mode 100644 index 000000000000..caf342d8c6c4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_apply.mli @@ -0,0 +1,292 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module handles all the validation/application of any operation + related to the ZK Rollup. + All of the functions defined in this module require that the ZKRU + feature flag is enabled. +*) + +(** In the ZK Rollup, L2 operations are validated in two steps: + {ol + {li The Protocol does the first pass of (light) validation and + appends the L2 operation to a pending list.} + {li The ZKRU Operator does the second pass of validation for a prefix + of the pending list and posts a proof on chain of the validity of + each of them. + Based on this proof, the Protocol is going to remove the prefix + from the pending list, and apply their effect on the ZKRU L2 state + and on the L1 balances.} + } + + The first step of validation is split into two cases, depending on + the type of L2 operation that is being submitted: + {ul + {li If the application of said L2 operation results in a transfer + of a ticket from L1 to L2 (i.e. it is a ZKRU {i deposit}), the + L2 operation has to be submitted through a call to the ZKRU + [%deposit] entrypoint from a smart contract. + This constraint is imposed by the fact that implicit accounts + cannot transfer tickets. + Then, the validation of these L2 operations will be performed + when applying the internal Tezos operation emitted by the call + to the ZKRU's deposit entrypoint. This is implemented by the + [transaction_to_zk_rollup] function in this module. + } + {li If its application results in a ticket transfer from L2 to L1 + (i.e. it is a ZKRU {i withdrawal}) or it has no transfer between + layers, the L2 operation has to be submitted through a + [Zk_rollup_publish] external Tezos operation. + The checks for these L2 operations will be perform upon application + of said external Tezos operation, whose logic is implemented by the + [publish] function in this module. + } + } + + Although L2 operations are mostly opaque, they expose a header that is + transparent to the Protocol (see {!Zk_rollup_operation_repr.t}). + In this header there's a field for the [price] of an L2 operation, which + will expose its kind. Concretely, the [price] encodes the net ticket + transfer from L1 to L2 caused by an L2 operation. Then, deposits have + a positive price, withdrawals a negative one, and pure L2 operations + must have a price of zero. + + An L2 operation's price also encodes which ticket is being transferred, + by storing the ticket's hash (see {!Ticket_hash_repr}). These hashes are + used as token identifiers inside the ZKRU. In both cases, the L2 operations + with a non-zero price (i.e. deposits and withdrawals) will be submitted + alongside the values describing the ticket being transferred + (see {!Zk_rollup_ticket_repr}). These values have to be consistent with + the token identifier used in the L2 operation's price. + + NB: if ticket transfers by implicit accounts was supported, these two cases + could be unified into the application of the [Zk_rollup_publish] operation. +*) + +open Alpha_context + +(** These errors are only to be matched in tests. *) +type error += + | Zk_rollup_feature_disabled + (** Emitted when trying to apply a ZK Rollup operation while the ZKRU + feature flag is not active. *) + | Zk_rollup_negative_nb_ops + (** Emitted when originating a ZK Rollup with a negative [nb_ops]. *) + +(** [assert_feature_enabled ctxt] asserts that the ZK Rollup feature flag + is activated. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated.} + } +*) +val assert_feature_enabled : t -> unit tzresult + +(** [originate ~ctxt_before_op ~ctxt ~public_parameters ~transcript + ~circuits_info ~init_state ~nb_ops] + applies the origination operation for a ZK rollup. + See {!Zk_rollup_storage.originate}. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated.} + {li [Zk_rollup_negative_nb_ops] if [nb_ops] is negative.} + } +*) +val originate : + ctxt_before_op:t -> + ctxt:t -> + public_parameters:Plonk.public_parameters -> + circuits_info:[`Public | `Private | `Fee] Zk_rollup.Account.SMap.t -> + init_state:Zk_rollup.State.t -> + nb_ops:int -> + (t + * Kind.zk_rollup_origination Apply_results.successful_manager_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t + +(** [publish ~ctxt_before_op ~ctxt ~zk_rollup ~l2_ops] + applies a publish operation to [zk_rollup] by adding [l2_ops] to its + pending list. + + All L2 operations in [l2_ops] must claim a non-positive [price] + (see {!Zk_rollup_operation_repr}). In other words, no deposit is + allowed in this operation, as those must go through an internal + transaction. + + This function will first perform a series of validation checks over + the L2 operations in [l2_ops]. If all of them are successful, these L2 + operations will be added to [dst_rollup]'s pending list. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated. + } + {li [Zk_rollup.Errors.Deposit_as_external] if the price of an L2 + operation from [ops] is positive. + } + {li [Zk_rollup.Errors.Invalid_deposit_amount] if an L2 operation + declares no ticket but has a non-zero price or if it declares + a ticket with a price of zero. + } + {li [Zk_rollup.Errors.Invalid_deposit_ticket] if an L2 operation's + ticket identifier (see [Zk_rollup_operation_repr]) is different from + the hash of its corresponding ticket and [l1_dst]. + } + {li [Zk_rollup_storage.Zk_rollup_invalid_op_code op_code] if the + [op_code] of one of the [operations] is greater or equal + to the number of declared operations for this [zk_rollup]. + } + } +*) +val publish : + ctxt_before_op:t -> + ctxt:t -> + zk_rollup:Zk_rollup.t -> + l2_ops:(Zk_rollup.Operation.t * Zk_rollup.Ticket.t option) list -> + (t + * Kind.zk_rollup_publish Apply_results.successful_manager_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t + +(** [transaction_to_zk_rollup + ~ctxt ~parameters_ty ~parameters ~payer ~dst_rollup ~since] applies an + internal transaction to a ZK [dst_rollup]. + + Internal transactions are used for deposits into ZK rollups, which can + be seen as a special case of the publish ZK rollup operation. + The [parameters] should include a ticket and a ZKRU L2 operation, as + explained in the {!Zk_rollup_parameters} module's documentation. + + This function will first perform a series of validation checks. + If successful, the L2 operation from the [parameters] will be added + to [dst_rollup]'s pending list, and [payer] will pay for the + added storage. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated. + } + {li [Zk_rollup.Errors.Ticket_payload_size_limit_exceeded] if the ticket + found in the [parameters] exceeds the maximum ticket size. + } + {li [Script_tc_errors.Forbidden_zero_ticket_quantity] if the ticket + amount is zero. + } + {li [Zk_rollup.Errors.Invalid_deposit_amount] if the amount of the ticket + transferred to the [dst_rollup] is different from the [price] + (see {!Zk_rollup_operation_repr}) claimed by the L2 operation. + } + {li [Zk_rollup.Errors.Invalid_deposit_ticket] if the L2 operation's + ticket identifier (see {!Zk_rollup_operation_repr}) is different to + the hash of the transferred ticket and [dst_rollup]. + } + {li [Zk_rollup_storage.Zk_rollup_invalid_op_code op_code] if the + [op_code] of the operation from the [parameters] is greater or equal + to the number of declared operations for this rollup. + } + {li [Zk_rollup.Errors.Wrong_deposit_parameters] if the [parameters] + are not of the expected type. See {!Zk_rollup_parameters}. + } + } +*) +val transaction_to_zk_rollup : + ctxt:t -> + parameters_ty: + ( ('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair, + 'b ) + Script_typed_ir.ty -> + parameters:('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair -> + dst_rollup:Zk_rollup.t -> + since:t -> + (t + * Kind.transaction Apply_internal_results.successful_internal_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t + +(** [update ~ctxt_before_op ~ctxt ~zk_rollup ~update ~source_contract] + applies an [update] to [zk_rollup]. + + A ZKRU update will verify three sorts of ZK circuits: + {ul + {li Public operation circuits, that handle a single L2 operation + from the pending list.} + {li Private batch circuits, that handle a batch of private L2 + operations.} + {li Fee circuit, which credits the ZKRU operator with all the aggregated + fees from the update.} + } + + The [update] provides some inputs required to perform this verification, + alongside the proof. See {!Zk_rollup_update_repr}. + + If the verification is successful, the [zk_rollup]'s state is updated, + a prefix of its pending list is dropped and the exits from the ZKRU are + performed. + + May fail with: + {ul + {li [Zk_rollup_feature_disabled] if the ZKRU feature flag is not + activated. + } + {li [Zk_rollup.Errors.Pending_bound] if the [update] processes fewer + public operation than allowed. + } + {li [Zk_rollup.Errors.Inconsistent_state_update] if the [update] declares + a new state of incorrect length. + } + {li [Zk_rollup.Errors.Invalid_circuit] if a public operation circuit is + ran as private. + } + {li [Zk_rollup.Errors.Invalid_verification] if the PlonK verification + fails. + } + {li [Zk_rollup.Errors.Invalid_deposit_amount] if an L2 operation without + a corresponding ticket in the pending list has a non-zero price. + } + {li [Zk_rollup_storage.Zk_rollup_pending_list_too_short] + if the [update] tries to process more public operations than those in + the pending list. + } + } +*) +val update : + ctxt_before_op:t -> + ctxt:t -> + zk_rollup:Zk_rollup.t -> + update:Zk_rollup.Update.t -> + (t + * Kind.zk_rollup_update Apply_results.successful_manager_operation_result + * Script_typed_ir.packed_internal_operation list) + tzresult + Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.ml new file mode 100644 index 000000000000..6ed68ffd02a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.ml @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type pending_op_public_inputs = { + old_state : Zk_rollup_state_repr.t; + new_state : Zk_rollup_state_repr.t; + fee : Zk_rollup_scalar.t; + exit_validity : bool; + zk_rollup : Zk_rollup_repr.t; + l2_op : Zk_rollup_operation_repr.t; +} + +type private_batch_public_inputs = { + old_state : Zk_rollup_state_repr.t; + new_state : Zk_rollup_state_repr.t; + fees : Zk_rollup_scalar.t; + zk_rollup : Zk_rollup_repr.t; +} + +type fee_public_inputs = { + old_state : Zk_rollup_state_repr.t; + new_state : Zk_rollup_state_repr.t; + fees : Zk_rollup_scalar.t; +} + +type t = + | Pending_op of pending_op_public_inputs + | Private_batch of private_batch_public_inputs + | Fee of fee_public_inputs + +let bool_to_scalar b = + if b then Zk_rollup_scalar.of_z Z.one else Zk_rollup_scalar.of_z Z.zero + +let to_scalar_array = function + | Pending_op {old_state; new_state; fee; exit_validity; zk_rollup; l2_op} -> + Array.concat + [ + old_state; + new_state; + [| + fee; + bool_to_scalar exit_validity; + Zk_rollup_repr.to_scalar zk_rollup; + |]; + Zk_rollup_operation_repr.to_scalar_array l2_op; + ] + | Private_batch {old_state; new_state; fees; zk_rollup} -> + Array.concat + [old_state; new_state; [|fees; Zk_rollup_repr.to_scalar zk_rollup|]] + | Fee {old_state; new_state; fees} -> + Array.concat [old_state; new_state; [|fees|]] diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.mli new file mode 100644 index 000000000000..74985106c63f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_circuit_public_inputs_repr.mli @@ -0,0 +1,67 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** + Abstraction layer for the public inputs to the ZKRU aPlonk circuits. + + As explained in the documentation, circuits in ZKRUs will be grouped into + three categories: pending (public) operations, private batches and + fee circuit. Each of these expects a different set of public inputs. +*) + +(** Public inputs expected by circuits that handle single public + L2 operations. *) +type pending_op_public_inputs = { + old_state : Zk_rollup_state_repr.t; + new_state : Zk_rollup_state_repr.t; + fee : Zk_rollup_scalar.t; + exit_validity : bool; + zk_rollup : Zk_rollup_repr.t; + l2_op : Zk_rollup_operation_repr.t; +} + +(** Public inputs expected by circuits that handle a batch of private + L2 operations. *) +type private_batch_public_inputs = { + old_state : Zk_rollup_state_repr.t; + new_state : Zk_rollup_state_repr.t; + fees : Zk_rollup_scalar.t; + zk_rollup : Zk_rollup_repr.t; +} + +(** Public inputs expected by the circuit that handles the L2 fees. *) +type fee_public_inputs = { + old_state : Zk_rollup_state_repr.t; + new_state : Zk_rollup_state_repr.t; + fees : Zk_rollup_scalar.t; +} + +type t = + | Pending_op of pending_op_public_inputs + | Private_batch of private_batch_public_inputs + | Fee of fee_public_inputs + +(** Conversion to the type the aPlonk verifier expects. *) +val to_scalar_array : t -> Zk_rollup_scalar.t array diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_errors.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_errors.ml new file mode 100644 index 000000000000..38bbcf2283f5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_errors.ml @@ -0,0 +1,136 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Deposit_as_external + | Invalid_deposit_amount + | Invalid_deposit_ticket + | Wrong_deposit_parameters + | Ticket_payload_size_limit_exceeded of { + payload_size : Saturation_repr.may_saturate Saturation_repr.t; + limit : int; + } + | Invalid_verification + | Invalid_circuit + | Inconsistent_state_update + | Pending_bound + +let () = + register_error_kind + `Temporary + ~id:"operation.zk_rollup_deposit_as_external" + ~title:"Zk_rollup: attempted a deposit through an external op" + ~description:"Zk_rollup: attempted a deposit through an external op" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup: attempted a deposit through an external op") + Data_encoding.empty + (function Deposit_as_external -> Some () | _ -> None) + (fun () -> Deposit_as_external) ; + register_error_kind + `Temporary + ~id:"operation.zk_rollup_invalid_deposit_amount" + ~title:"Zk_rollup: attempted a deposit with an invalid amount" + ~description:"Zk_rollup: attempted a deposit with an invalid amount" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup: attempted a deposit with an invalid amount") + Data_encoding.empty + (function Invalid_deposit_amount -> Some () | _ -> None) + (fun () -> Invalid_deposit_amount) ; + register_error_kind + `Temporary + ~id:"operation.zk_rollup_invalid_deposit_ticket" + ~title:"Zk_rollup: attempted a deposit with an invalid ticket" + ~description:"Zk_rollup: attempted a deposit with an invalid ticket" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup: attempted a deposit with an invalid ticket") + Data_encoding.empty + (function Invalid_deposit_ticket -> Some () | _ -> None) + (fun () -> Invalid_deposit_ticket) ; + register_error_kind + `Permanent + ~id:"operation.zk_rollup_wrong_deposit_parameters" + ~title:"Zk_rollup: attempted a deposit with invalid parameters" + ~description:"Zk_rollup: attempted a deposit with invalid parameters" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Zk_rollup: attempted a deposit with an invalid parameters") + Data_encoding.empty + (function Wrong_deposit_parameters -> Some () | _ -> None) + (fun () -> Wrong_deposit_parameters) ; + register_error_kind + `Permanent + ~id:"zk_rollup_ticket_payload_size_limit_exceeded" + ~title:"The payload of the deposited ticket exceeded the size limit" + ~description:"The payload of the deposited ticket exceeded the size limit" + Data_encoding.( + obj2 (req "payload_size" Saturation_repr.n_encoding) (req "limit" int31)) + (function + | Ticket_payload_size_limit_exceeded {payload_size; limit} -> + Some (payload_size, limit) + | _ -> None) + (fun (payload_size, limit) -> + Ticket_payload_size_limit_exceeded {payload_size; limit}) ; + register_error_kind + `Temporary + ~id:"operation.zk_rollup_failed_verification" + ~title:"Zk_rollup_update: failed verification" + ~description:"Zk_rollup_update: failed verification" + ~pp:(fun ppf () -> Format.fprintf ppf "The proof verification failed") + Data_encoding.empty + (function Invalid_verification -> Some () | _ -> None) + (fun () -> Invalid_verification) ; + register_error_kind + `Permanent + ~id:"operation.zk_rollup_invalid_circuit" + ~title:"Zk_rollup_update: invalid circuit" + ~description:"Zk_rollup_update: invalid circuit" + ~pp:(fun ppf () -> + Format.fprintf ppf "Invalid circuit in proof verification") + Data_encoding.empty + (function Invalid_circuit -> Some () | _ -> None) + (fun () -> Invalid_circuit) ; + register_error_kind + `Permanent + ~id:"operation.zk_rollup_inconsistent_state_update" + ~title:"Zk_rollup_update: inconsistent state update" + ~description:"Zk_rollup_update: new state is of incorrect size" + ~pp:(fun ppf () -> + Format.fprintf ppf "Zk_rollup_update: new state is of incorrect size") + Data_encoding.empty + (function Inconsistent_state_update -> Some () | _ -> None) + (fun () -> Inconsistent_state_update) ; + register_error_kind + `Temporary + ~id:"operation.zk_rollup_pending_bound" + ~title:"Zk_rollup_update: update with fewer pending ops than allowed" + ~description:"Zk_rollup_update: update with fewer pending ops than allowed" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Zk_rollup_update: update with fewer pending ops than allowed") + Data_encoding.empty + (function Pending_bound -> Some () | _ -> None) + (fun () -> Pending_bound) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.ml new file mode 100644 index 000000000000..b7a13d345f34 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.ml @@ -0,0 +1,78 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type price = {id : Ticket_hash_repr.t; amount : Z.t} + +type t = { + op_code : int; + price : price; + l1_dst : Signature.Public_key_hash.t; + rollup_id : Zk_rollup_repr.t; + payload : Zk_rollup_scalar.t array; +} + +let int_to_scalar x = Zk_rollup_scalar.of_z (Z.of_int x) + +let pkh_to_scalar x = + Zk_rollup_scalar.of_bits + (Data_encoding.Binary.to_string_exn Signature.Public_key_hash.encoding x) + +let ticket_hash_to_scalar ticket_hash = + Zk_rollup_scalar.of_bits + @@ Data_encoding.Binary.to_string_exn Ticket_hash_repr.encoding ticket_hash + +let to_scalar_array {op_code; price; l1_dst; rollup_id; payload} = + Array.concat + [ + [| + int_to_scalar op_code; + ticket_hash_to_scalar price.id; + Zk_rollup_scalar.of_z @@ Z.abs price.amount; + pkh_to_scalar l1_dst; + Zk_rollup_repr.to_scalar rollup_id; + |]; + payload; + ] + +let price_encoding = + Data_encoding.( + conv + (fun {id; amount} -> (id, amount)) + (fun (id, amount) -> {id; amount}) + (obj2 (req "id" Ticket_hash_repr.encoding) (req "amount" z))) + +let encoding = + Data_encoding.( + conv + (fun {op_code; price; l1_dst; rollup_id; payload} -> + (op_code, price, l1_dst, rollup_id, payload)) + (fun (op_code, price, l1_dst, rollup_id, payload) -> + {op_code; price; l1_dst; rollup_id; payload}) + (obj5 + (req "op_code" int31) + (req "price" price_encoding) + (req "l1_dst" Signature.Public_key_hash.encoding) + (req "rollup_id" Zk_rollup_repr.Address.encoding) + (req "payload" Plonk.scalar_array_encoding))) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.mli new file mode 100644 index 000000000000..85ce349461bb --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_operation_repr.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The [price] of an L2 operation represents the net ticket + transfer from L1 to L2 that it will produce. + [id] is a ticket hash used as a ticket identifier and [amount] + is positive if the operation transfers tickets from L1 to L2, + negative if it does so from L2 to L1, and zero when no transfer + is done between layers. +*) +type price = {id : Ticket_hash_repr.t; amount : Z.t} + +(** A ZK rollup L2 operation has two parts: a transparent header and + an opaque payload. + The header is made up by: + {ul + {li An [op_code] in the range \[0, nb_ops)} + {li The [price] of this L2 operation} + {li [l1_dst] is the public key hash of the implicit account that will + be credited with the withdrawal generated by this operation, if any} + {li [rollup_id] is the address of the rollup this operation targets} + } + + This type represents the L1's view of L2 operations. It's important + to remember that this is only used for public operations, as the + protocol isn't aware of private ones. +*) +type t = { + op_code : int; + price : price; + l1_dst : Signature.Public_key_hash.t; + rollup_id : Zk_rollup_repr.t; + payload : Zk_rollup_scalar.t array; +} + +val encoding : t Data_encoding.t + +(** Special encoding needed to feed L2 operations to the Plonk verifier *) +val to_scalar_array : t -> Zk_rollup_scalar.t array diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.ml new file mode 100644 index 000000000000..56f73bb82ece --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.ml @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type deposit_parameters = { + ex_ticket : Ticket_scanner.ex_ticket; + zkru_operation : Alpha_context.Zk_rollup.Operation.t; +} + +let get_deposit_parameters : + type a comparable. + ( (a Script_typed_ir.ticket, bytes) Script_typed_ir.pair, + comparable ) + Script_typed_ir.ty -> + (a Script_typed_ir.ticket, bytes) Script_typed_ir.pair -> + deposit_parameters tzresult = + fun ty contents -> + let open Script_typed_ir in + let open Result_syntax in + match (ty, contents) with + | Pair_t (Ticket_t (ty, _), Bytes_t, _, _), (ticket, op_bytes) -> ( + match + Data_encoding.Binary.of_bytes_opt + Alpha_context.Zk_rollup.Operation.encoding + op_bytes + with + | None -> tzfail Alpha_context.Zk_rollup.Errors.Wrong_deposit_parameters + | Some zkru_operation -> + return + {ex_ticket = Ticket_scanner.Ex_ticket (ty, ticket); zkru_operation}) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.mli new file mode 100644 index 000000000000..386d036b13be --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_parameters.mli @@ -0,0 +1,51 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A module for representing and extracting typed ZK rollup + parameters. *) + +(** A type representing deposit parameters for ZK rollups. Deposit + parameters consist of a ticket of arbitrary content along with a + layer-2 ZKRU operation byte representation. *) +type deposit_parameters = { + ex_ticket : Ticket_scanner.ex_ticket; + zkru_operation : Alpha_context.Zk_rollup.Operation.t; +} + +(** [get_deposit_parameters ty value] returns [ex_ticket] and a + [zkru_operation] from a michelson typed value. if [ty] is not of a + pair of ticket and [bytes] then it fails with + [Zk_rollup_errors.Wrong_deposit_parameters]. + + This function is intended to be used to enforce the type of the transaction + to a [zk_rollup%deposit]. It must be used both in [ticket_diffs_of_operations] + to account for the ticket deposited and in [apply] to retrieve the ticket + when applying the transaction to a zk_rollup. *) +val get_deposit_parameters : + ( ('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair, + 'comparable ) + Script_typed_ir.ty -> + ('a Script_typed_ir.ticket, bytes) Script_typed_ir.pair -> + deposit_parameters tzresult diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.ml new file mode 100644 index 000000000000..5ec67359b4b5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.ml @@ -0,0 +1,154 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Address = struct + let prefix = "epx1" + + let encoded_size = 37 + + let decoded_prefix = "\001\023\224\125" + + module H = + Blake2B.Make + (Base58) + (struct + let name = "Zk_rollup_hash" + + let title = "A zk rollup address" + + let b58check_prefix = decoded_prefix + + let size = Some 20 + end) + + include H + + let () = Base58.check_encoded_prefix b58check_encoding prefix encoded_size + + include Path_encoding.Make_hex (H) + + type error += (* `Permanent *) Error_zk_rollup_address_generation + + let () = + let open Data_encoding in + let msg = "Error while generating rollup address" in + register_error_kind + `Permanent + ~id:"rollup.error_zk_rollup_address_generation" + ~title:msg + ~pp:(fun ppf () -> Format.fprintf ppf "%s" msg) + ~description:msg + unit + (function Error_zk_rollup_address_generation -> Some () | _ -> None) + (fun () -> Error_zk_rollup_address_generation) + + let from_nonce nonce = + let open Result_syntax in + Data_encoding.Binary.to_bytes_opt Origination_nonce.encoding nonce + |> function + | None -> tzfail Error_zk_rollup_address_generation + | Some nonce -> return @@ hash_bytes [nonce] + + let of_b58data = function H.Data h -> Some h | _ -> None +end + +type t = Address.t + +let to_scalar x = + Zk_rollup_scalar.of_bits + (Data_encoding.Binary.to_string_exn Address.encoding x) + +type pending_list = + | Empty of {next_index : int64} + | Pending of {next_index : int64; length : int} + +let pending_list_encoding : pending_list Data_encoding.t = + let open Data_encoding in + let empty_tag, pending_tag = (0, 1) in + let empty_encoding = + obj1 (req "next_index" Compact.(make ~tag_size:`Uint8 int64)) + in + let pending_encoding = + obj2 + (req "next_index" Compact.(make ~tag_size:`Uint8 int64)) + (req "length" uint16) + in + matching + (function + | Empty {next_index} -> matched empty_tag empty_encoding next_index + | Pending {next_index; length} -> + matched pending_tag pending_encoding (next_index, length)) + [ + case + ~title:"Empty" + (Tag empty_tag) + empty_encoding + (function Empty {next_index} -> Some next_index | _ -> None) + (fun next_index -> Empty {next_index}); + case + ~title:"Pending" + (Tag pending_tag) + pending_encoding + (function + | Pending {next_index; length} -> Some (next_index, length) + | _ -> None) + (fun (next_index, length) -> Pending {next_index; length}); + ] + +module Index = struct + type nonrec t = t + + let path_length = 1 + + let to_path c l = + let raw_key = Data_encoding.Binary.to_bytes_exn Address.encoding c in + let (`Hex key) = Hex.of_bytes raw_key in + key :: l + + let of_path = function + | [key] -> + Option.bind + (Hex.to_bytes (`Hex key)) + (Data_encoding.Binary.of_bytes_opt Address.encoding) + | _ -> None + + let rpc_arg = Address.rpc_arg + + let encoding = Address.encoding + + let compare = Address.compare +end + +let in_memory_size (_ : t) = + let open Cache_memory_helpers in + h1w +! string_size_gen Address.size + +module Internal_for_tests = struct + let originated_zk_rollup nonce = + let data = + Data_encoding.Binary.to_bytes_exn Origination_nonce.encoding nonce + in + Address.hash_bytes [data] +end diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.mli new file mode 100644 index 000000000000..d36a047fc21f --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_repr.mli @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** A ZK rollup has an address starting with "epx1". + ZKRU addresses have a length of 20 bytes, which means + that they have an injective encoding as BLS12-381 scalars. +*) +module Address : sig + include S.HASH + + (** [from_nonce nonce] produces an address completely determined by + an operation hash and an origination counter. *) + val from_nonce : Origination_nonce.t -> t tzresult + + (** [encoded_size] is the number of bytes needed to represent an address. *) + val encoded_size : int + + val of_b58data : Base58.data -> t option + + val prefix : string +end + +type t = Address.t + +(** [to_scalar address] returns the scalar corresponding to [address] *) +val to_scalar : t -> Zk_rollup_scalar.t + +(** Description of a ZK rollup's pending list. *) +type pending_list = + | Empty of {next_index : int64} + (** Empty pending list but starting point will be [next_index] + when adding to the list *) + | Pending of {next_index : int64; length : int} + (** Pending list with + [(next_index - length) .. (next_index - 1)]. + [length] is encoded as a [uint16]. *) + +val pending_list_encoding : pending_list Data_encoding.t + +module Index : Storage_description.INDEX with type t = t + +(** [in_memory_size zk_rollup] returns the number of bytes a [zk_rollup] + address uses in RAM. *) +val in_memory_size : t -> Cache_memory_helpers.sint + +module Internal_for_tests : sig + val originated_zk_rollup : Origination_nonce.t -> Address.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.ml new file mode 100644 index 000000000000..77ac1b1d7299 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.ml @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Bls.Primitive.Fr.t + +let of_z z = + (* In case [z] is outside of the field, i.e. Z >= Fr.order, + [Bls.Primitive.Fr.of_z] will apply a modulo reduction to ge + t a field element *) + Bls.Primitive.Fr.of_z z + +let of_bits bs = + (* The bits are interpreted as a Z integer *) + let z = Z.of_bits bs in + of_z z diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.mli new file mode 100644 index 000000000000..cdd18d5b38bd --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_scalar.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Representation of scalars used by the ZK Rollup alongside + manipulation functions *) + +(** Scalars are transparently BLS12-381 scalars *) +type t = Bls.Primitive.Fr.t + +(** Safe conversion from Z.t. + If the numerical value is not in the field, modulo reduction + is applied. *) +val of_z : Z.t -> t + +(** Safe conversion from bits, represented as a string. + If the numerical value is not in the field, modulo reduction + is applied. *) +val of_bits : string -> t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.ml new file mode 100644 index 000000000000..64ccb1bdde37 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.ml @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = Zk_rollup_scalar.t array + +let encoding = Plonk.scalar_array_encoding diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.mli new file mode 100644 index 000000000000..359074016ab0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_state_repr.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The state of a ZK Rollup is an opaque array of scalars, and represents + the L1's view of the L2 state. + Although the length of this array is unbound, this type should describe + a succinct representation of the entire RU state. Upon origination, the + length of a ZKRU's state is fixed. +*) +type t = Zk_rollup_scalar.t array + +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.ml new file mode 100644 index 000000000000..6cba5588ec33 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.ml @@ -0,0 +1,315 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Zk_rollup_does_not_exist of Zk_rollup_repr.t + | Zk_rollup_invalid_op_code of int + | Zk_rollup_pending_list_too_short + | Zk_rollup_negative_length + +let () = + register_error_kind + `Temporary + ~id:"zk_rollup_does_not_exist" + ~title:"ZK Rollup does not exist" + ~description:"Attempted to use a ZK rollup that has not been originated." + ~pp:(fun ppf x -> + Format.fprintf ppf "Rollup %a does not exist" Zk_rollup_repr.Address.pp x) + Data_encoding.(obj1 (req "rollup" Zk_rollup_repr.Address.encoding)) + (function Zk_rollup_does_not_exist x -> Some x | _ -> None) + (fun x -> Zk_rollup_does_not_exist x) ; + register_error_kind + `Permanent + ~id:"zk_rollup_invalid_op code" + ~title:"Invalid op code in append" + ~description:"Invalid op code in append" + ~pp:(fun ppf oc -> + Format.fprintf ppf "Op code %d is not valid for this ZK Rollup" oc) + Data_encoding.(obj1 (req "op_code" int31)) + (function Zk_rollup_invalid_op_code oc -> Some oc | _ -> None) + (fun oc -> Zk_rollup_invalid_op_code oc) ; + register_error_kind + `Temporary + ~id:"zk_rollup_pending_list_too_short" + ~title:"Pending list is too short" + ~description:"Pending list is too short" + Data_encoding.unit + (function Zk_rollup_pending_list_too_short -> Some () | _ -> None) + (fun () -> Zk_rollup_pending_list_too_short) ; + register_error_kind + `Permanent + ~id:"zk_rollup_negative_length" + ~title:"Negative length for pending list prefix" + ~description:"Negative length for pending list prefix" + Data_encoding.unit + (function Zk_rollup_negative_length -> Some () | _ -> None) + (fun () -> Zk_rollup_negative_length) + +let account = Storage.Zk_rollup.Account.get + +let pending_list = Storage.Zk_rollup.Pending_list.get + +let pending_op ctxt id = Storage.Zk_rollup.Pending_operation.get (ctxt, id) + +let originate ctxt static ~init_state = + let open Lwt_result_syntax in + let*? ctxt, nonce = Raw_context.increment_origination_nonce ctxt in + let*? address = Zk_rollup_repr.Address.from_nonce nonce in + let origination_size = Constants_storage.zk_rollup_origination_size ctxt in + let initial_account = + Zk_rollup_account_repr. + { + static; + dynamic = + { + state = init_state; + paid_l2_operations_storage_space = Z.of_int origination_size; + used_l2_operations_storage_space = Z.zero; + }; + } + in + let* ctxt, account_size = + Storage.Zk_rollup.Account.init ctxt address initial_account + in + let init_pl = Zk_rollup_repr.(Empty {next_index = 0L}) in + let* ctxt, pl_size = + Storage.Zk_rollup.Pending_list.init ctxt address init_pl + in + let address_size = Zk_rollup_repr.Address.size in + let size = + Z.of_int (origination_size + address_size + account_size + pl_size) + in + return (ctxt, address, size) + +let add_to_pending ctxt rollup ops = + let open Lwt_result_syntax in + let open Zk_rollup_repr in + let open Zk_rollup_operation_repr in + let* ctxt, acc = account ctxt rollup in + let*? () = + List.iter_e + (fun (op, _ticket_hash_opt) -> + if Compare.Int.(op.op_code >= acc.static.nb_ops || op.op_code < 0) then + Result_syntax.tzfail @@ Zk_rollup_invalid_op_code op.op_code + else Result_syntax.return_unit) + ops + in + let* ctxt, pl = Storage.Zk_rollup.Pending_list.get ctxt rollup in + let next_index, length = + match pl with + | Empty {next_index} -> (next_index, 0) + | Pending {next_index; length} -> (next_index, length) + in + let* ctxt, next_index, length, storage_diff = + List.fold_left_es + (fun (ctxt, next_index, length, storage_diff) op -> + let* ctxt, new_storage_diff, _was_bound = + Storage.Zk_rollup.Pending_operation.add (ctxt, rollup) next_index op + in + return + ( ctxt, + Int64.succ next_index, + length + 1, + new_storage_diff + storage_diff )) + (ctxt, next_index, length, 0) + ops + in + let used_l2_operations_storage_space = + Z.(add acc.dynamic.used_l2_operations_storage_space (Z.of_int storage_diff)) + in + let l2_operations_storage_space_to_pay = + Z.( + max + zero + (sub + used_l2_operations_storage_space + acc.dynamic.paid_l2_operations_storage_space)) + in + let paid_l2_operations_storage_space = + Z.( + add + acc.dynamic.paid_l2_operations_storage_space + l2_operations_storage_space_to_pay) + in + let acc = + { + acc with + dynamic = + { + acc.dynamic with + paid_l2_operations_storage_space; + used_l2_operations_storage_space; + }; + } + in + + let pl = + if Compare.Int.(length = 0) then Empty {next_index} + else Pending {next_index; length} + in + (* Users aren't charged for storage diff in the account or pending list + description of a ZKRU. + When updating a ZKRU account, the storage diff can only come from the + dynamically sized [Z.t] used for the watermark. These changes + in storage size will not be accounted for. + As for the pending list description, the storage size is fixed for + each of the two cases (empty / non-empty). Then, there will be a storage + diff when switching between these two, which won't be accounted for + either. + *) + let* ctxt, _diff_acc = Storage.Zk_rollup.Account.update ctxt rollup acc in + let* ctxt, _diff_pl = Storage.Zk_rollup.Pending_list.update ctxt rollup pl in + return (ctxt, l2_operations_storage_space_to_pay) + +let pending_length = + let open Zk_rollup_repr in + function Empty _ -> 0 | Pending {length; _} -> length + +let head = + let open Result_syntax in + let open Zk_rollup_repr in + function + | Empty _ -> tzfail Zk_rollup_pending_list_too_short + | Pending {next_index; length} -> + return Int64.(sub next_index (of_int length)) + +let next_index = + let open Zk_rollup_repr in + function + | Empty {next_index} -> next_index | Pending {next_index; _} -> next_index + +let get_pending_length ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, pl = pending_list ctxt rollup in + return (ctxt, pending_length pl) + +(** Same as [Tezos_stdlib.Utils.fold_n_times] but with Lwt and Error monad *) +let fold_n_times_es ~when_negative n f e = + let open Lwt_result_syntax in + if Compare.Int.(n < 0) then tzfail when_negative + else + let rec go acc = function + | 0 -> return acc + | n -> + let* acc = f acc in + (go [@ocaml.tailcall]) acc (n - 1) + in + go e n + +let get_prefix ctxt rollup n = + let open Lwt_result_syntax in + if Compare.Int.(n = 0) then return (ctxt, []) + else + let* ctxt, pl = pending_list ctxt rollup in + let pl_length = pending_length pl in + let*? () = + error_when Compare.Int.(n > pl_length) Zk_rollup_pending_list_too_short + in + let*? hd = head pl in + let* ctxt, ops, _i = + (* Get the l2 ops corresponding to indeces [hd + n - 1 .. hd], + so that the accumulated list is in the right order *) + fold_n_times_es + ~when_negative:Zk_rollup_negative_length + n + (fun (ctxt, ops, i) -> + let* ctxt, op = pending_op ctxt rollup i in + return (ctxt, op :: ops, Int64.pred i)) + (ctxt, [], Int64.(sub (add hd (of_int n)) 1L)) + in + return (ctxt, ops) + +let update ctxt rollup ~pending_to_drop ~new_account = + let open Lwt_result_syntax in + let open Zk_rollup_repr in + let open Zk_rollup_account_repr in + let* ctxt, pl = pending_list ctxt rollup in + let* ctxt, acc = account ctxt rollup in + let pl_length = pending_length pl in + let*? () = + error_when + Compare.Int.(pending_to_drop > pl_length) + Zk_rollup_pending_list_too_short + in + let next_index = next_index pl in + (* Drop the indeces from [head] to [head + pending_to_drop - 1] + from the storage of L2 operations. *) + let* ctxt, freed = + match head pl with + | Error _e -> + (* If the pending list is empty, then [pending_to_drop] must be 0. *) + return (ctxt, 0) + | Ok head -> + let* ctxt, freed, _i = + fold_n_times_es + ~when_negative:Zk_rollup_negative_length + pending_to_drop + (fun (ctxt, freed, i) -> + let* ctxt, new_freed, _bound = + Storage.Zk_rollup.Pending_operation.remove (ctxt, rollup) i + in + return (ctxt, freed + new_freed, Int64.succ i)) + (ctxt, 0, head) + in + return (ctxt, freed) + in + (* Subtract the bytes freed by removing pending operations from + acc.dynamic.used_l2_operations_storage_space, and update + [new_account]. + *) + let used_l2_operations_storage_space = + Z.(sub acc.dynamic.used_l2_operations_storage_space (Z.of_int freed)) + in + let new_account = + { + new_account with + dynamic = + { + state = new_account.dynamic.state; + paid_l2_operations_storage_space = + new_account.dynamic.paid_l2_operations_storage_space; + used_l2_operations_storage_space; + }; + } + in + let* ctxt, _diff_acc = + Storage.Zk_rollup.Account.update ctxt rollup new_account + in + (* Update the pending list descriptor *) + let pl_length = pl_length - pending_to_drop in + let pl = + if Compare.Int.(pl_length = 0) then Empty {next_index} + else Pending {next_index; length = pl_length} + in + let* ctxt, _diff_pl = Storage.Zk_rollup.Pending_list.update ctxt rollup pl in + return ctxt + +let assert_exist ctxt rollup = + let open Lwt_result_syntax in + let* ctxt, exists = Storage.Zk_rollup.Account.mem ctxt rollup in + let*? () = error_unless exists (Zk_rollup_does_not_exist rollup) in + return ctxt + +let exists ctxt rollup = Storage.Zk_rollup.Account.mem ctxt rollup diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.mli new file mode 100644 index 000000000000..7f4c06e42e8a --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_storage.mli @@ -0,0 +1,158 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** These errors are only to be matched in tests. *) +type error += + | Zk_rollup_does_not_exist of Zk_rollup_repr.t + (** Emitted when trying to perform an operation over a ZK rollup + that hasn't been initialised. *) + | Zk_rollup_invalid_op_code of int + (** Emitted when trying to add to the pending list and operation + with an invalid op code. *) + | Zk_rollup_pending_list_too_short + (** Emitted when trying to process more public operations than + those available in the pending list. *) + +(** [account context rollup] fetches the ZK [rollup]'s account from the + storage. +*) +val account : + Raw_context.t -> + Zk_rollup_repr.t -> + (Raw_context.t * Zk_rollup_account_repr.t) tzresult Lwt.t + +(* [pending_list context rollup] fetches the ZK [rollup]'s + pending list description from the storage. + See {! Zk_rollup_repr.pending_list}. *) +val pending_list : + Raw_context.t -> + Zk_rollup_repr.t -> + (Raw_context.t * Zk_rollup_repr.pending_list) tzresult Lwt.t + +(* [pending_op context rollup i] fetches the [i]th L2 operation from + ZK [rollup]'s pending list, alongside an optional ticket hash + to perform an exit (see {!Zk_rollup_apply} for more details). +*) +val pending_op : + Raw_context.t -> + Zk_rollup_repr.t -> + int64 -> + (Raw_context.t * (Zk_rollup_operation_repr.t * Ticket_hash_repr.t option)) + tzresult + Lwt.t + +(** [originate context static ~init_state] produces an address [a] for + a ZK rollup storage using the [origination_nonce] from + the [context]. This function also initializes the storage, + indexing the initial ZKRU account by [a]. + + Returns the new context and ZKRU address, alongside the size + of the new account. +*) +val originate : + Raw_context.t -> + Zk_rollup_account_repr.static -> + init_state:Zk_rollup_state_repr.t -> + (Raw_context.t * Zk_rollup_repr.t * Z.t) tzresult Lwt.t + +(** [add_to_pending context rollup operations] appends to the + ZK [rollup]'s pending list a list of L2 [operations]. + Returns the new context alongside the size of the new operations. + + May fail with: + {ul + {li [Zk_rollup_invalid_op_code op_code] if the [op_code] + of one of the [operations] is greater or equal to the + number of declared operations for this [rollup]. + } + } +*) +val add_to_pending : + Raw_context.t -> + Zk_rollup_repr.t -> + (Zk_rollup_operation_repr.t * Ticket_hash_repr.t option) list -> + (Raw_context.t * Z.t) tzresult Lwt.t + +(** [get_pending_length context rollup] returns the length of a + ZK [rollup]'s pending list. +*) +val get_pending_length : + Raw_context.t -> Zk_rollup_repr.t -> (Raw_context.t * int) tzresult Lwt.t + +(** [get_prefix context rollup n] returns the prefix of length [n] + of the [rollup]'s pending list. + + May fail with: + {ul + {li [Zk_rollup_pending_list_too_short] if [n] is greater than + the length of the pending list.} + {li [Zk_rollup_negative_length] if [n] is negative.} + } +*) +val get_prefix : + Raw_context.t -> + Zk_rollup_repr.t -> + int -> + (Raw_context.t + * (Zk_rollup_operation_repr.t * Ticket_hash_repr.t option) list) + tzresult + Lwt.t + +(** [update context rollup ~pending_to_drop ~new_account] sets the + [rollup]'s account to [new_account]. Additionally, it removes + the first [pending_to_drop] entries from the [rollup]'s pending + list. + Returns the new context. + + May fail with: + {ul + {li [Zk_rollup_pending_list_too_short] if [pending_to_drop] is + greater than the length of the pending list.} + {li [Zk_rollup_negative_length] if [pending_to_drop] is negative.} + } +*) +val update : + Raw_context.t -> + Zk_rollup_repr.t -> + pending_to_drop:int -> + new_account:Zk_rollup_account_repr.t -> + Raw_context.t tzresult Lwt.t + +(** [assert_exist context rollup] asserts that [rollup] has been initialized. + Returns the new context. + + May fail with: + {ul + {li [Zk_rollup_does_not_exist] if [rollup] is not found.} + } +*) +val assert_exist : + Raw_context.t -> Zk_rollup_repr.t -> Raw_context.t tzresult Lwt.t + +(** [exists context rollup] returns a boolean representing whether + [rollup] has been initialized. +*) +val exists : + Raw_context.t -> Zk_rollup_repr.t -> (Raw_context.t * bool) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.ml new file mode 100644 index 000000000000..a8dfc557c5ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.ml @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type t = { + contents : Script_repr.expr; + ty : Script_repr.expr; + ticketer : Contract_repr.t; +} + +let encoding : t Data_encoding.t = + let open Data_encoding in + conv + (fun {contents; ty; ticketer} -> (contents, ty, ticketer)) + (fun (contents, ty, ticketer) -> {contents; ty; ticketer}) + (obj3 + (req "contents" Script_repr.expr_encoding) + (req "ty" Script_repr.expr_encoding) + (req "ticketer" Contract_repr.encoding)) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.mli new file mode 100644 index 000000000000..34574e7c4f02 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_ticket_repr.mli @@ -0,0 +1,37 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Representation of tickets for the ZKRU. + This data is used by the [Zk_rollup_publish] operation to compute the + ticket hashes needed to transfer tickets from the ZK Rollup to an + implicit account. +*) +type t = { + contents : Script_repr.expr; + ty : Script_repr.expr; + ticketer : Contract_repr.t; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.ml b/src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.ml new file mode 100644 index 000000000000..5357f923beb2 --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.ml @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type op_pi = { + new_state : Zk_rollup_state_repr.t; + fee : Zk_rollup_scalar.t; + exit_validity : bool; +} + +type private_inner_pi = { + new_state : Zk_rollup_state_repr.t; + fees : Zk_rollup_scalar.t; +} + +type fee_pi = {new_state : Zk_rollup_state_repr.t} + +(* Data sent to an update operation *) +type t = { + pending_pis : (string * op_pi) list; + private_pis : (string * private_inner_pi) list; + fee_pi : fee_pi; + proof : Plonk.proof; +} + +let op_pi_encoding : op_pi Data_encoding.t = + Data_encoding.( + conv + (fun {new_state; fee; exit_validity} -> (new_state, fee, exit_validity)) + (fun (new_state, fee, exit_validity) -> {new_state; fee; exit_validity}) + (obj3 + (req "new_state" Zk_rollup_state_repr.encoding) + (req "fee" Plonk.scalar_encoding) + (req "exit_validity" bool))) + +let private_inner_pi_encoding : private_inner_pi Data_encoding.t = + Data_encoding.( + conv + (fun ({new_state; fees} : private_inner_pi) -> (new_state, fees)) + (fun (new_state, fees) -> {new_state; fees}) + (obj2 + (req "new_state" Zk_rollup_state_repr.encoding) + (req "fee" Plonk.scalar_encoding))) + +let fee_pi_encoding : fee_pi Data_encoding.t = + Data_encoding.( + conv + (fun {new_state} -> new_state) + (fun new_state -> {new_state}) + (obj1 (req "new_state" Zk_rollup_state_repr.encoding))) + +let encoding : t Data_encoding.t = + Data_encoding.( + conv + (fun {pending_pis; private_pis; fee_pi; proof} -> + (pending_pis, private_pis, fee_pi, proof)) + (fun (pending_pis, private_pis, fee_pi, proof) -> + {pending_pis; private_pis; fee_pi; proof}) + (obj4 + (req "pending_pis" (list @@ tup2 (string Plain) op_pi_encoding)) + (req + "private_pis" + (list @@ tup2 (string Plain) private_inner_pi_encoding)) + (req "fee_pi" fee_pi_encoding) + (req "proof" Plonk.proof_encoding))) diff --git a/src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.mli b/src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.mli new file mode 100644 index 000000000000..a8a2dfaee70d --- /dev/null +++ b/src/proto_020_PsParisC/lib_protocol/zk_rollup_update_repr.mli @@ -0,0 +1,60 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Payload of a ZK Rollup update operation. + The operator only needs to send a subset of the public inputs + defined in {!Zk_rollup_circuit_public_inputs_repr}, the rest + is provided by the protocol. +*) + +(** Minimal subset of public inputs for the public L2 operations' circuits. *) +type op_pi = { + new_state : Zk_rollup_state_repr.t; + fee : Zk_rollup_scalar.t; + exit_validity : bool; +} + +(** Minimal subset of public inputs for the circuits for batches of + private L2 operations *) +type private_inner_pi = { + new_state : Zk_rollup_state_repr.t; + fees : Zk_rollup_scalar.t; +} + +(** Minimal subset of public inputs for the "fee" circuit. *) +type fee_pi = {new_state : Zk_rollup_state_repr.t} + +(** Payload of an update operation. + Includes the proof and the public inputs that are needed to verify it. + Each set of public inputs also carries the string that identifies the + circuit which they are for. *) +type t = { + pending_pis : (string * op_pi) list; + private_pis : (string * private_inner_pi) list; + fee_pi : fee_pi; + proof : Plonk.proof; +} + +val encoding : t Data_encoding.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup/README.md b/src/proto_020_PsParisC/lib_sc_rollup/README.md new file mode 100644 index 000000000000..47d564929577 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/README.md @@ -0,0 +1,8 @@ +# lib smart rollup =lib_sc_rollup= + +This is a place designed as wrapper of the protocol specifically for +the smart rollup type. It may include helpers for all smart rollup +feature. + +This includes so far in memory context, PVM instance, refutation game +and proof helpers. diff --git a/src/proto_020_PsParisC/lib_sc_rollup/context_helpers.ml b/src/proto_020_PsParisC/lib_sc_rollup/context_helpers.ml new file mode 100644 index 000000000000..87afcbbb22fd --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/context_helpers.ml @@ -0,0 +1,75 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module In_memory = struct + open Tezos_context_memory + + module Tree = struct + include Context_binary.Tree + + type tree = Context_binary.tree + + type t = Context_binary.t + + type key = string list + + type value = bytes + end + + type tree = Tree.tree + + type proof = Context_binary.Proof.tree Context_binary.Proof.t + + let verify_proof p f = + Lwt.map Result.to_option (Context_binary.verify_tree_proof p f) + + let produce_proof context state step = + let open Lwt_syntax in + let* context = Context_binary.add_tree context [] state in + let* h = Context_binary.commit ~time:Time.Protocol.epoch context in + let index = Context_binary.index context in + let* context = Context_binary.checkout_exn index h in + match Tree.kinded_key state with + | Some k -> + let index = Context_binary.index context in + let* p = Context_binary.produce_tree_proof index k step in + return_some p + | None -> return_none + + let kinded_hash_to_state_hash = function + | `Value hash | `Node hash -> + Protocol.Alpha_context.Sc_rollup.State_hash.context_hash_to_state_hash + hash + + let proof_before proof = + kinded_hash_to_state_hash proof.Context_binary.Proof.before + + let proof_after proof = + kinded_hash_to_state_hash proof.Context_binary.Proof.after + + let proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 + .tree_proof_encoding +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup/context_helpers.mli b/src/proto_020_PsParisC/lib_sc_rollup/context_helpers.mli new file mode 100644 index 000000000000..d389c4a6f664 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/context_helpers.mli @@ -0,0 +1,36 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol.Alpha_context + +(** [In_memory] is a context that can be used to instantiate an Arith + or Wasm PVM. It's signature is + {!Protocol.Alpha_context.Sc_rollup.Generic_pvm_context_sig} *) +module In_memory : + Sc_rollup.Generic_pvm_context_sig + with type Tree.tree = Tezos_context_memory.Context_binary.tree + and type Tree.t = Tezos_context_memory.Context_binary.t + and type proof = + Tezos_context_memory.Context.Proof.tree + Tezos_context_memory.Context.Proof.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup/dune b/src/proto_020_PsParisC/lib_sc_rollup/dune new file mode 100644 index 000000000000..8eefbe36f7a5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/dune @@ -0,0 +1,17 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_smart_rollup_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.smart-rollup) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol) + (inline_tests (flags -verbose) (modes native)) + (preprocess (pps ppx_expect)) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup/game_helpers.ml b/src/proto_020_PsParisC/lib_sc_rollup/game_helpers.ml new file mode 100644 index 000000000000..b3ddddc305e1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/game_helpers.ml @@ -0,0 +1,178 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context.Sc_rollup + +let default_new_dissection ~default_number_of_sections + ~(start_chunk : Game.dissection_chunk) + ~(our_stop_chunk : Game.dissection_chunk) = + let max_number_of_sections = Z.of_int default_number_of_sections in + let trace_length = Tick.distance our_stop_chunk.tick start_chunk.tick in + let number_of_sections = Z.min max_number_of_sections trace_length in + let rem = Z.(rem trace_length number_of_sections) in + let first_section_length, section_length = + if Compare.Z.(trace_length <= max_number_of_sections) then + (* In this case, every section is of length one. *) + Z.(one, one) + else + let section_length = Z.(max one (div trace_length number_of_sections)) in + if Compare.Z.(section_length = Z.one) && not Compare.Z.(rem = Z.zero) then + (* If we put [section_length] in this situation, we will most likely + have a very long last section. *) + (rem, section_length) + else (section_length, section_length) + in + (* [k] is the number of sections in [rev_dissection]. *) + let rec make rev_dissection k tick = + if Z.(equal k number_of_sections) then List.rev rev_dissection + else + let next_tick = Tick.jump tick section_length in + make (tick :: rev_dissection) (Z.succ k) next_tick + in + make [] Z.one (Tick.jump start_chunk.tick first_section_length) + +let make_dissection ~state_of_tick ~state_hash_of_eval_state ?start_state + ~start_chunk ~our_stop_chunk ticks = + let rec make_dissection_aux start_state ticks acc = + let open Lwt_result_syntax in + match ticks with + | tick :: rst -> + let* eval_state = state_of_tick ?start_state tick in + let state_hash = Option.map state_hash_of_eval_state eval_state in + let chunk = Dissection_chunk.{tick; state_hash} in + make_dissection_aux eval_state rst (chunk :: acc) + | [] -> return @@ List.rev (our_stop_chunk :: acc) + in + make_dissection_aux start_state ticks [start_chunk] + +module Wasm = struct + let new_dissection ~default_number_of_sections ~start_chunk ~our_stop_chunk = + let open Dissection_chunk in + let dist = Tick.distance start_chunk.tick our_stop_chunk.tick in + let ticks_per_snapshot = Wasm_2_0_0PVM.ticks_per_snapshot in + if Compare.Z.(dist <= ticks_per_snapshot) then + (* + There are two cases that require us to fall back to the + default behavior. Either [start_chunk] is not aligned on the + size of a snapshot (meaning the PVM is stuck) or the distance + between the start and stop chunk is lesser than a snapshot, + meaning we have already found the kernel_run invocation we + were looking for. + *) + default_new_dissection + ~default_number_of_sections + ~start_chunk + ~our_stop_chunk + else + let is_stop_chunk_aligned = + Compare.Z.( + Z.rem (Tick.to_z our_stop_chunk.tick) ticks_per_snapshot = Z.zero) + in + let final_tick = + Tick.of_z + Z.( + div (Tick.to_z our_stop_chunk.tick) ticks_per_snapshot + * ticks_per_snapshot) + in + let dist = Tick.distance start_chunk.tick final_tick in + let max_number_of_sections = Z.(div dist ticks_per_snapshot) in + let number_of_sections = + Z.min + (Z.of_int + (* If [is_stop_chunk_aligned] is false, we allocate one + sections for the surplus. *) + (if is_stop_chunk_aligned then default_number_of_sections + else default_number_of_sections - 1)) + max_number_of_sections + in + + (* [go remaining_sections last_tick dist] tries to compute + [remaining_sections] sections as evenly as possible, starting + from [last_tick] and covering [dist] ticks. *) + let rec go remaining_sections last_tick dist rev_acc = + (* The last section is created by [make_dissection] when it + adds the [stop_chunk]. *) + if Z.(remaining_sections <= one) then + let rev_acc = + (* If [is_stop_chunk_aligned] is false, we insert the + last snapshot point. *) + if is_stop_chunk_aligned then rev_acc else final_tick :: rev_acc + in + List.rev rev_acc + else + (* + We compute the length of the next section of the + dissection as the maximum size such that if we would give + this number to all remaining sections, we would not + consume more than [dist] ticks. This is ensured by + [Z.div], which computes a lower rounding. + *) + let section_len = + Z.( + dist + / (ticks_per_snapshot * remaining_sections) + * ticks_per_snapshot) + in + let next_tick = Tick.jump last_tick section_len in + let next_dist = Z.(dist - section_len) in + (* + There are two cases to consider here. + + 1. Either [dist] was a multiple of + [ticks_per_snapshot]. In that case, the same + [section_len] will be computed in all subsequent + calls of [go]. + 2. Or [dist] was not a multiple of + [ticks_per_snapshot]. In that case, the next + [section_len] in float will be slightly higher than + the previous one, because it will benefit from the + unconsumed reminder of the previous computation, + until enough is left that [dist] becomes a + multiplier of [ticks_per_snapshot]. In that case, we + will fall back to case 1. + + Take case of dividing 60 into 32 chunks. + + - [remaining_sections = 60], [remaining_sections = 32], and + [section_len = 1] (60 / 32 ~= 1.87) + - [remaining_sections = 59], [remaining_sections = 31], and + [section_len = 1] (59 / 31 ~= 1.90) + - [remaining_sections = 58], [remaining_sections = 30], and + [section_len = 1] (58 / 30 ~= 1.93) + - [remaining_sections = 57], [remaining_sections = 29], and + [section_len = 1] (57 / 29 ~= 1.97) + - [remaining_sections = 56], [remaining_sections = 28], and + [section_len = 2] (56 / 28 = 2) + + All remaining sections will be of length 2. + *) + go + Z.(pred remaining_sections) + next_tick + next_dist + (next_tick :: rev_acc) + in + go number_of_sections start_chunk.tick dist [] +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup/game_helpers.mli b/src/proto_020_PsParisC/lib_sc_rollup/game_helpers.mli new file mode 100644 index 000000000000..7e517f296e32 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/game_helpers.mli @@ -0,0 +1,72 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context.Sc_rollup + +(** [default_new_dissection ~default_number_of_sections ~start_chunk + ~our_stop_chunk] computes a list of intermediary ticks that can + later be turned into new dissection from between [start_chunk] and + [our_stop_chunk] with [make_dissection]. The algorithm satisfies + the default predicate on dissection exported by the protocol. *) +val default_new_dissection : + default_number_of_sections:int -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + Tick.t list + +(** [make_dissection ~state_hash_from_tick ~start_chunk + ~our_stop_chunk intermediary_ticks] computes a new dissection from + a list of intermediary ticks between [start_chunk] and + [our_stop_chunk]. + + This function assumes [intermediary_ticks] encodes a valid + dissection from [start_chunk] to [our_stop_chunk], and recomputes + the state hash associated to each ticks. *) +val make_dissection : + state_of_tick:(?start_state:'a -> Tick.t -> ('a option, 'trace) result Lwt.t) -> + state_hash_of_eval_state:('a -> State_hash.t) -> + ?start_state:'a -> + start_chunk:Dissection_chunk.t -> + our_stop_chunk:Dissection_chunk.t -> + Tick.t list -> + (Dissection_chunk.t list, 'trace) result Lwt.t + +module Wasm : sig + (** [new_dissection ~default_number_of_sections ~start_chunk + ~our_stop_chunk] computes a dissection that satisfies the + dissection predicate of the WASM PVM, that is all the ticks in + the dissection are aligned with the size of a snapshot. + + If [start_chunk] is not a multiple of the size of a snapshot or + if the distance between [start_chunk] and [stop_chunk] is not + greater than the size of a snapshot, then + {!default_new_dissection} is called, because it means the WASM + PVM is stuck. *) + val new_dissection : + default_number_of_sections:int -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + Tick.t list +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.ml b/src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.ml new file mode 100644 index 000000000000..ad8f4f0c19e0 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.ml @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +module type PVM = + Sc_rollup.PVM.S + with type context = Tezos_context_memory.Context_binary.t + and type state = Tezos_context_memory.Context_binary.tree + and type proof = + Tezos_context_memory.Context_binary.Proof.tree + Tezos_context_memory.Context_binary.Proof.t + +module type S = sig + include PVM + + val make_empty_context : unit -> context + + val make_empty_state : unit -> state +end + +module Extend (Pvm : PVM) = struct + include Pvm + + let make_empty_context = + Tezos_context_memory.Context_binary.make_empty_context ~root:"dummy" + + let make_empty_state = Tezos_context_memory.Context_binary.make_empty_tree +end + +module Arith : S = Extend (Sc_rollup.ArithPVM.Make (Context_helpers.In_memory)) + +module Wasm : S = + Extend + (Sc_rollup.Wasm_2_0_0PVM.Make + (Environment.Wasm_2_0_0.Make) + (Context_helpers.In_memory)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.mli b/src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.mli new file mode 100644 index 000000000000..551cfcd18520 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup/pvm_in_memory.mli @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +module type S = sig + include + Sc_rollup.PVM.S + with type context = Tezos_context_memory.Context_binary.t + and type state = Tezos_context_memory.Context_binary.tree + and type proof = + Tezos_context_memory.Context_binary.Proof.tree + Tezos_context_memory.Context_binary.Proof.t + + (** [make_empty_context ()] create a new in memory context for + a PVM. *) + val make_empty_context : unit -> context + + (** [make_empty_state ()] create a new state with an in memory + context for a PVM. *) + val make_empty_state : unit -> state +end + +(** [Arith]: Arith PVM with an in memory context {!Tezos_context_memory}. *) +module Arith : S + +(** [Wasm] Wasm PVM with an in memory context {!Tezos_context_memory}. *) +module Wasm : S diff --git a/src/proto_020_PsParisC/lib_sc_rollup_layer2/README.md b/src/proto_020_PsParisC/lib_sc_rollup_layer2/README.md new file mode 100644 index 000000000000..4b77ba36979a --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_layer2/README.md @@ -0,0 +1,7 @@ +# lib smart rollup layer2 =lib_sc_rollup_layer2= + +This is a place designed for types and functions that are needed by +the rollup node and the client. + +This library allows to not have a direct dependency between the client +and the node. diff --git a/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune b/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune new file mode 100644 index 000000000000..53e6ac4ca15f --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune @@ -0,0 +1,21 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name tezos_smart_rollup_layer2_019_PtParisB) + (public_name octez-protocol-019-PtParisB-libs.smart-rollup-layer2) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-injector + octez-l2-libs.smart-rollup) + (inline_tests (flags -verbose) (modes native)) + (preprocess (pps ppx_expect)) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Octez_injector + -open Octez_smart_rollup)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.ml b/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.ml new file mode 100644 index 000000000000..79fca0a3799d --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.ml @@ -0,0 +1,489 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Address = struct + type t = Sc_rollup.Address.t + + (* Same as octez version through environment *) + + let of_octez = Fun.id + + let to_octez = Fun.id +end + +module State_hash = struct + type t = Sc_rollup.State_hash.t + + (* Same as octez version through environment *) + + let of_octez = Fun.id + + let to_octez = Fun.id +end + +module Merkelized_payload_hashes_hash = struct + type t = Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t + + (* Same as octez version through environment *) + + let of_octez = Fun.id + + let to_octez = Fun.id +end + +module Commitment_hash = struct + type t = Sc_rollup.Commitment.Hash.t + + (* Same as octez version through environment *) + + let of_octez = Fun.id + + let to_octez = Fun.id +end + +module Commitment = struct + type t = Sc_rollup.Commitment.t + + let of_octez + Octez_smart_rollup.Commitment. + {compressed_state; inbox_level; predecessor; number_of_ticks} : t = + { + compressed_state = State_hash.of_octez compressed_state; + inbox_level = + Raw_level.of_int32 inbox_level + |> WithExceptions.Result.to_exn_f ~error:(fun _trace -> + Stdlib.failwith "Commitment.of_octez: invalid inbox_level"); + predecessor = Commitment_hash.of_octez predecessor; + number_of_ticks = + Sc_rollup.Number_of_ticks.of_value number_of_ticks + |> WithExceptions.Option.to_exn_f ~none:(fun () -> + Stdlib.failwith "Commitment.of_octez: invalid number_of_ticks"); + } + + let to_octez + Sc_rollup.Commitment. + {compressed_state; inbox_level; predecessor; number_of_ticks} : + Octez_smart_rollup.Commitment.t = + { + compressed_state = State_hash.to_octez compressed_state; + inbox_level = Raw_level.to_int32 inbox_level; + predecessor = Commitment_hash.to_octez predecessor; + number_of_ticks = Sc_rollup.Number_of_ticks.to_value number_of_ticks; + } +end + +module Inbox_hash = struct + type t = Sc_rollup.Inbox.Hash.t + + (* Same as octez version through environment *) + + let of_octez = Fun.id + + let to_octez = Fun.id +end + +module Inbox = struct + type t = Sc_rollup.Inbox.t + + type history_proof = Sc_rollup.Inbox.history_proof + + let to_repr inbox = + inbox + |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.encoding + |> Data_encoding.Binary.of_string_exn Sc_rollup_inbox_repr.encoding + + let of_repr inbox = + inbox + |> Data_encoding.Binary.to_string_exn Sc_rollup_inbox_repr.encoding + |> Data_encoding.Binary.of_string_exn Sc_rollup.Inbox.encoding + + let of_octez (inbox : Octez_smart_rollup.Inbox.t) : t = + inbox |> Octez_smart_rollup.Inbox.to_versioned + |> Data_encoding.Binary.to_string_exn + Octez_smart_rollup.Inbox.versioned_encoding + |> Data_encoding.Binary.of_string_exn + Sc_rollup_inbox_repr.versioned_encoding + |> Sc_rollup_inbox_repr.of_versioned |> of_repr + + let to_octez (inbox : t) : Octez_smart_rollup.Inbox.t = + inbox |> to_repr |> Sc_rollup_inbox_repr.to_versioned + |> Data_encoding.Binary.to_string_exn + Sc_rollup_inbox_repr.versioned_encoding + |> Data_encoding.Binary.of_string_exn + Octez_smart_rollup.Inbox.versioned_encoding + |> Octez_smart_rollup.Inbox.of_versioned + + let history_proof_of_octez (hist : Octez_smart_rollup.Inbox.history_proof) : + history_proof = + hist + |> Data_encoding.Binary.to_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn Sc_rollup.Inbox.history_proof_encoding + + let history_proof_to_octez (hist : history_proof) : + Octez_smart_rollup.Inbox.history_proof = + hist + |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding +end + +module Dal = struct + module Slot_index = struct + type t = Dal.Slot_index.t + + let of_octez ~number_of_slots (i : Octez_smart_rollup.Dal.Slot_index.t) : t + = + match Dal.Slot_index.of_int_opt ~number_of_slots i with + | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i + | Some i -> i + + let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = + Dal.Slot_index.to_int + end + + module Page_index = struct + type t = Dal.Page.Index.t + + let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + + let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id + end + + module Slot_header = struct + type t = Dal.Slot.Header.t + + let of_octez ~number_of_slots + Octez_smart_rollup.Dal.Slot_header. + {id = {published_level; index}; commitment} : t = + Dal.Slot.Header. + { + id = + { + published_level = Raw_level.of_int32_exn published_level; + index = Slot_index.of_octez ~number_of_slots index; + }; + commitment; + } + + let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : + Octez_smart_rollup.Dal.Slot_header.t = + Octez_smart_rollup.Dal.Slot_header. + { + id = + { + published_level = Raw_level.to_int32 published_level; + index = Slot_index.to_octez index; + }; + commitment; + } + end + + module Slot_history = struct + type t = Dal.Slots_history.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = + h + |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + end + + module Slot_history_cache = struct + type t = Dal.Slots_history.History_cache.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Dal.Slots_history.History_cache.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = + h + |> Data_encoding.Binary.to_bytes_exn + Dal.Slots_history.History_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + end +end + +module Game = struct + type dissection_chunk = Sc_rollup.Game.dissection_chunk + + type step = Sc_rollup.Game.step + + type refutation = Sc_rollup.Game.refutation + + type index = Sc_rollup.Game.Index.t + + type player = Sc_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + + let dissection_chunk_of_octez Octez_smart_rollup.Game.{state_hash; tick} : + dissection_chunk = + { + state_hash = Option.map State_hash.of_octez state_hash; + tick = Sc_rollup.Tick.of_z tick; + } + + let dissection_chunk_to_octez Sc_rollup.Dissection_chunk.{state_hash; tick} : + Octez_smart_rollup.Game.dissection_chunk = + { + state_hash = Option.map State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z tick; + } + + let step_of_octez (step : Octez_smart_rollup.Game.step) : step = + match step with + | Dissection chunks -> + Dissection (List.map dissection_chunk_of_octez chunks) + | Proof serialized_proof -> + let proof = + Data_encoding.Binary.of_string + Sc_rollup.Proof.encoding + serialized_proof + |> WithExceptions.Result.to_exn_f ~error:(fun err -> + Format.kasprintf + Stdlib.failwith + "Game.step_of_octez: cannot deserialize proof\n" + Data_encoding.Binary.pp_read_error + err) + in + Proof proof + + let step_to_octez (step : step) : Octez_smart_rollup.Game.step = + match step with + | Dissection chunks -> + Dissection (List.map dissection_chunk_to_octez chunks) + | Proof serialized_proof -> + let proof = + Data_encoding.Binary.to_string_exn + Sc_rollup.Proof.encoding + serialized_proof + in + Proof proof + + let refutation_of_octez (refutation : Octez_smart_rollup.Game.refutation) : + refutation = + match refutation with + | Start {player_commitment_hash; opponent_commitment_hash} -> + Start + { + player_commitment_hash = + Commitment_hash.of_octez player_commitment_hash; + opponent_commitment_hash = + Commitment_hash.of_octez opponent_commitment_hash; + } + | Move {choice; step} -> + Move {choice = Sc_rollup.Tick.of_z choice; step = step_of_octez step} + + let refutation_to_octez (refutation : refutation) : + Octez_smart_rollup.Game.refutation = + match refutation with + | Start {player_commitment_hash; opponent_commitment_hash} -> + Start + { + player_commitment_hash = + Commitment_hash.to_octez player_commitment_hash; + opponent_commitment_hash = + Commitment_hash.to_octez opponent_commitment_hash; + } + | Move {choice; step} -> + Move {choice = Sc_rollup.Tick.to_z choice; step = step_to_octez step} + + let index_of_octez Octez_smart_rollup.Game.{alice; bob} = + Sc_rollup.Game.Index.make alice bob + + let index_to_octez Sc_rollup.Game.Index.{alice; bob} = + Octez_smart_rollup.Game.make_index alice bob + + let player_of_octez : Octez_smart_rollup.Game.player -> player = function + | Alice -> Alice + | Bob -> Bob + + let player_to_octez : player -> Octez_smart_rollup.Game.player = function + | Alice -> Alice + | Bob -> Bob + + let game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_of_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_of_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_of_octez refuted_stop_chunk; + } + + let game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_to_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_to_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_to_octez refuted_stop_chunk; + } + + let of_octez + Octez_smart_rollup.Game. + { + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : t = + { + turn = player_of_octez turn; + inbox_snapshot = Inbox.history_proof_of_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.of_octez dal_snapshot; + start_level = Raw_level.of_int32_exn start_level; + inbox_level = Raw_level.of_int32_exn inbox_level; + game_state = game_state_of_octez game_state; + } + + let to_octez + Sc_rollup.Game. + { + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : Octez_smart_rollup.Game.t = + { + turn = player_to_octez turn; + inbox_snapshot = Inbox.history_proof_to_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.to_octez dal_snapshot; + start_level = Raw_level.to_int32 start_level; + inbox_level = Raw_level.to_int32 inbox_level; + game_state = game_state_to_octez game_state; + } + + let conflict_of_octez + Octez_smart_rollup.Game. + {other; their_commitment; our_commitment; parent_commitment} : conflict + = + { + other; + their_commitment = Commitment.of_octez their_commitment; + our_commitment = Commitment.of_octez our_commitment; + parent_commitment; + } + + let conflict_to_octez + Sc_rollup.Refutation_storage. + {other; their_commitment; our_commitment; parent_commitment} : + Octez_smart_rollup.Game.conflict = + { + other; + their_commitment = Commitment.to_octez their_commitment; + our_commitment = Commitment.to_octez our_commitment; + parent_commitment; + } +end + +module Kind = struct + type t = Sc_rollup.Kind.t + + let of_octez : Octez_smart_rollup.Kind.t -> t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 + | Riscv -> Riscv + + let to_octez : t -> Octez_smart_rollup.Kind.t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 + | Riscv -> Riscv +end + +module Constants = struct + type reveal_activation_level = + Constants.Parametric.sc_rollup_reveal_activation_level + + let reveal_activation_level_of_octez + Octez_smart_rollup.Rollup_constants. + { + blake2B; + metadata; + dal_page; + dal_parameters; + dal_attested_slots_validity_lag; + } : reveal_activation_level = + { + raw_data = {blake2B = Raw_level.of_int32_exn blake2B}; + metadata = Raw_level.of_int32_exn metadata; + dal_page = Raw_level.of_int32_exn dal_page; + dal_parameters = Raw_level.of_int32_exn dal_parameters; + dal_attested_slots_validity_lag = + Int32.to_int dal_attested_slots_validity_lag; + } + + let reveal_activation_level_to_octez + Constants.Parametric. + { + raw_data = {blake2B}; + metadata; + dal_page; + dal_parameters; + dal_attested_slots_validity_lag; + } : Octez_smart_rollup.Rollup_constants.reveal_activation_level = + { + blake2B = Raw_level.to_int32 blake2B; + metadata = Raw_level.to_int32 metadata; + dal_page = Raw_level.to_int32 dal_page; + dal_parameters = Raw_level.to_int32 dal_parameters; + dal_attested_slots_validity_lag = + Int32.of_int dal_attested_slots_validity_lag; + } +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.mli b/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.mli new file mode 100644 index 000000000000..b00d3991fe0d --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_proto_types.mli @@ -0,0 +1,207 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +module Address : sig + type t = Sc_rollup.Address.t + + val of_octez : Octez_smart_rollup.Address.t -> t + + val to_octez : t -> Octez_smart_rollup.Address.t +end + +module State_hash : sig + type t = Sc_rollup.State_hash.t + + val of_octez : Octez_smart_rollup.State_hash.t -> t + + val to_octez : t -> Octez_smart_rollup.State_hash.t +end + +module Merkelized_payload_hashes_hash : sig + type t = Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t + + val of_octez : Octez_smart_rollup.Merkelized_payload_hashes_hash.t -> t + + val to_octez : t -> Octez_smart_rollup.Merkelized_payload_hashes_hash.t +end + +module Commitment_hash : sig + type t = Sc_rollup.Commitment.Hash.t + + val of_octez : Octez_smart_rollup.Commitment.Hash.t -> t + + val to_octez : t -> Octez_smart_rollup.Commitment.Hash.t +end + +module Commitment : sig + type t = Sc_rollup.Commitment.t + + val of_octez : Octez_smart_rollup.Commitment.t -> t + + val to_octez : t -> Octez_smart_rollup.Commitment.t +end + +module Inbox_hash : sig + type t = Sc_rollup.Inbox.Hash.t + + val of_octez : Octez_smart_rollup.Inbox_hash.t -> t + + val to_octez : t -> Octez_smart_rollup.Inbox_hash.t +end + +module Inbox : sig + type t = Sc_rollup.Inbox.t + + type history_proof = Sc_rollup.Inbox.history_proof + + val of_octez : Octez_smart_rollup.Inbox.t -> t + + val to_octez : t -> Octez_smart_rollup.Inbox.t + + val history_proof_of_octez : + Octez_smart_rollup.Inbox.history_proof -> history_proof + + val history_proof_to_octez : + history_proof -> Octez_smart_rollup.Inbox.history_proof +end + +module Game : sig + type dissection_chunk = Sc_rollup.Game.dissection_chunk + + val dissection_chunk_of_octez : + Octez_smart_rollup.Game.dissection_chunk -> dissection_chunk + + val dissection_chunk_to_octez : + dissection_chunk -> Octez_smart_rollup.Game.dissection_chunk + + type step = Sc_rollup.Game.step + + val step_of_octez : Octez_smart_rollup.Game.step -> step + + val step_to_octez : step -> Octez_smart_rollup.Game.step + + type refutation = Sc_rollup.Game.refutation + + val refutation_of_octez : Octez_smart_rollup.Game.refutation -> refutation + + val refutation_to_octez : refutation -> Octez_smart_rollup.Game.refutation + + type index = Sc_rollup.Game.Index.t + + val index_of_octez : Octez_smart_rollup.Game.index -> index + + val index_to_octez : index -> Octez_smart_rollup.Game.index + + type player = Sc_rollup.Game.player + + val player_of_octez : Octez_smart_rollup.Game.player -> player + + val player_to_octez : player -> Octez_smart_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + val game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state + + val game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + val of_octez : Octez_smart_rollup.Game.t -> t + + val to_octez : t -> Octez_smart_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + + val conflict_of_octez : Octez_smart_rollup.Game.conflict -> conflict + + val conflict_to_octez : conflict -> Octez_smart_rollup.Game.conflict +end + +module Kind : sig + type t = Sc_rollup.Kind.t + + val of_octez : Octez_smart_rollup.Kind.t -> t + + val to_octez : t -> Octez_smart_rollup.Kind.t +end + +module Dal : sig + module Slot_index : sig + type t = Dal.Slot_index.t + + val of_octez : + number_of_slots:int -> Octez_smart_rollup.Dal.Slot_index.t -> t + + val to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t + end + + module Page_index : sig + type t = Dal.Page.Index.t + + val of_octez : Octez_smart_rollup.Dal.Page_index.t -> t + + val to_octez : t -> Octez_smart_rollup.Dal.Page_index.t + end + + module Slot_header : sig + type t = Dal.Slot.Header.t + + val of_octez : + number_of_slots:int -> Octez_smart_rollup.Dal.Slot_header.t -> t + + val to_octez : t -> Octez_smart_rollup.Dal.Slot_header.t + end + + module Slot_history : sig + type t = Dal.Slots_history.t + + val of_octez : Octez_smart_rollup.Dal.Slot_history.t -> t + + val to_octez : t -> Octez_smart_rollup.Dal.Slot_history.t + end + + module Slot_history_cache : sig + type t = Dal.Slots_history.History_cache.t + + val of_octez : Octez_smart_rollup.Dal.Slot_history_cache.t -> t + + val to_octez : t -> Octez_smart_rollup.Dal.Slot_history_cache.t + end +end + +module Constants : sig + type reveal_activation_level = + Constants.Parametric.sc_rollup_reveal_activation_level + + val reveal_activation_level_of_octez : + Octez_smart_rollup.Rollup_constants.reveal_activation_level -> + reveal_activation_level + + val reveal_activation_level_to_octez : + reveal_activation_level -> + Octez_smart_rollup.Rollup_constants.reveal_activation_level +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_services.ml b/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_services.ml new file mode 100644 index 000000000000..82f952daf31b --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_layer2/sc_rollup_services.ml @@ -0,0 +1,462 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +type eval_result = { + state_hash : Sc_rollup.State_hash.t; + status : string; + output : Sc_rollup.output list; + inbox_level : int32; + num_ticks : Z.t; + insights : bytes option list; + (** The simulation can ask to look at values on the state after + the simulation. *) +} + +type insight_request = + | Pvm_state_key of string list + | Durable_storage_key of string list + +type simulate_input = { + messages : string list; + reveal_pages : string list option; + insight_requests : insight_request list; + log_kernel_debug_file : string option; +} + +type commitment_info = { + commitment : Sc_rollup.Commitment.t; + commitment_hash : Sc_rollup.Commitment.Hash.t; + first_published_at_level : Raw_level.t; + published_at_level : Raw_level.t; +} + +module Encodings = struct + open Data_encoding + + let hex_string = string' Hex + + let eval_result = + conv + (fun {state_hash; status; output; inbox_level; num_ticks; insights} -> + (state_hash, status, output, inbox_level, num_ticks, insights)) + (fun (state_hash, status, output, inbox_level, num_ticks, insights) -> + {state_hash; status; output; inbox_level; num_ticks; insights}) + @@ obj6 + (req + "state_hash" + Sc_rollup.State_hash.encoding + ~description: + "Hash of the state after execution of the PVM on the input \ + messages") + (req "status" string ~description:"Status of the PVM after evaluation") + (req + "output" + (list Sc_rollup.output_encoding) + ~description:"Output produced by evaluation of the messages") + (req + "inbox_level" + int32 + ~description:"Level of the inbox that would contain these messages") + (req + "num_ticks" + z + ~description:"Ticks taken by the PVM for evaluating the messages") + (dft + "insights" + (list (option bytes)) + [] + ~description:"PVM state values requested after the simulation") + + let insight_request = + union + [ + case + (Tag 0) + ~title:"pvm_state" + ~description:"Path in the PVM state" + (obj2 (req "kind" (constant "pvm_state")) (req "key" (list string))) + (function Pvm_state_key key -> Some ((), key) | _ -> None) + (fun ((), key) -> Pvm_state_key key); + case + (Tag 1) + ~title:"durable_storage" + ~description:"Path in the PVM durable storage" + (obj2 + (req "kind" (constant "durable_storage")) + (req "key" (list string))) + (function Durable_storage_key key -> Some ((), key) | _ -> None) + (fun ((), key) -> Durable_storage_key key); + ] + + let simulate_input = + conv + (fun {messages; reveal_pages; insight_requests; log_kernel_debug_file} -> + (messages, reveal_pages, insight_requests, log_kernel_debug_file)) + (fun (messages, reveal_pages, insight_requests, log_kernel_debug_file) -> + {messages; reveal_pages; insight_requests; log_kernel_debug_file}) + @@ obj4 + (req + "messages" + (list hex_string) + ~description:"Serialized messages for simulation.") + (opt + "reveal_pages" + (list hex_string) + ~description:"Pages (at most 4kB) to be used for revelation ticks") + (dft + "insight_requests" + (list insight_request) + [] + ~description:"Paths in the PVM to inspect after the simulation") + (opt + "log_kernel_debug_file" + string + ~description: + "File in which to emit kernel logs. This file will be created in \ + /simulation_kernel_logs/, where is the \ + data directory of the rollup node.") + + let commitment_info = + conv + (fun { + commitment; + commitment_hash; + first_published_at_level; + published_at_level; + } -> + ( commitment, + commitment_hash, + first_published_at_level, + published_at_level )) + (fun ( commitment, + commitment_hash, + first_published_at_level, + published_at_level ) -> + { + commitment; + commitment_hash; + first_published_at_level; + published_at_level; + }) + @@ obj4 + (req "commitment" Sc_rollup.Commitment.encoding) + (req "hash" Sc_rollup.Commitment.Hash.encoding) + (req "first_published_at_level" Raw_level.encoding) + (req "published_at_level" Raw_level.encoding) +end + +module Query = struct + let outbox_proof_query = + let open Tezos_rpc.Query in + let open Sc_rollup in + let invalid_message e = + raise + (Invalid + (Format.asprintf + "Invalid message (%a)" + Environment.Error_monad.pp_trace + e)) + in + query (fun outbox_level message_index serialized_outbox_message -> + let req name f = function + | None -> + raise + (Invalid (Format.sprintf "Query parameter %s is required" name)) + | Some arg -> f arg + in + let outbox_level = + req "outbox_level" Raw_level.of_int32_exn outbox_level + in + let message_index = req "message_index" Z.of_int64 message_index in + let message = + req + "serialized_outbox_message" + (fun s -> Outbox.Message.(unsafe_of_string s |> deserialize)) + serialized_outbox_message + in + match message with + | Error e -> invalid_message e + | Ok message -> {outbox_level; message_index; message}) + |+ opt_field "outbox_level" Tezos_rpc.Arg.int32 (fun o -> + Some (Raw_level.to_int32 o.outbox_level)) + |+ opt_field "message_index" Tezos_rpc.Arg.int64 (fun o -> + Some (Z.to_int64 o.message_index)) + |+ opt_field "serialized_outbox_message" Tezos_rpc.Arg.string (fun o -> + match Outbox.Message.serialize o.message with + | Ok message -> Some (Outbox.Message.unsafe_to_string message) + | Error e -> invalid_message e) + |> seal + + type key_query = {key : string} + + let key_query : key_query Tezos_rpc.Query.t = + let open Tezos_rpc.Query in + query (fun key -> {key}) + |+ field "key" Tezos_rpc.Arg.string "" (fun t -> t.key) + |> seal + + let outbox_level_query = + let open Tezos_rpc.Query in + query (fun outbox_level -> + let req name f = function + | None -> + raise + (Invalid (Format.sprintf "Query parameter %s is required" name)) + | Some arg -> f arg + in + req "outbox_level" Raw_level.of_int32_exn outbox_level) + |+ opt_field "outbox_level" Tezos_rpc.Arg.int32 (fun o -> + Some (Raw_level.to_int32 o)) + |> seal + + let message_index_query = + let open Tezos_rpc.Query in + query (fun message_index -> + let req name f = function + | None -> + raise + (Invalid (Format.sprintf "Query parameter %s is required" name)) + | Some arg -> f arg + in + req "index" (fun o -> o) message_index) + |+ opt_field "index" Tezos_rpc.Arg.uint (fun o -> Some o) + |> seal +end + +type simulate_query = {fuel : int64 option} + +let simulate_query : simulate_query Tezos_rpc.Query.t = + let open Tezos_rpc.Query in + query (fun fuel -> {fuel}) + |+ opt_field "fuel" Tezos_rpc.Arg.int64 (fun t -> t.fuel) + |> seal + +module Block = struct + open Tezos_rpc.Path + + type prefix = unit * Rollup_node_services.Arg.block_id + + let path : prefix Tezos_rpc.Path.context = open_root + + let prefix = root / "global" / "block" /: Rollup_node_services.Arg.block_id + + let block = + Tezos_rpc.Service.get_service + ~description: + "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ + identifier" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup_block.full_encoding + path + + let hash = + Tezos_rpc.Service.get_service + ~description:"Tezos block hash of block known to the smart rollup node" + ~query:Tezos_rpc.Query.empty + ~output:Block_hash.encoding + (path / "hash") + + let level = + Tezos_rpc.Service.get_service + ~description:"Level of Tezos block known to the smart rollup node" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.int32 + (path / "level") + + let inbox = + Tezos_rpc.Service.get_service + ~description:"Rollup inbox for block" + ~query:Tezos_rpc.Query.empty + ~output:Octez_smart_rollup.Inbox.encoding + (path / "inbox") + + let ticks = + Tezos_rpc.Service.get_service + ~description:"Number of ticks for specified level" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "ticks") + + let total_ticks = + Tezos_rpc.Service.get_service + ~description:"Total number of ticks at specified block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.Tick.encoding + (path / "total_ticks") + + let num_messages = + Tezos_rpc.Service.get_service + ~description:"Number of messages for specified block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "num_messages") + + let state_hash = + Tezos_rpc.Service.get_service + ~description:"State hash for this block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.State_hash.encoding + (path / "state_hash") + + let state_current_level = + Tezos_rpc.Service.get_service + ~description:"Retrieve the current level of a PVM" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Raw_level.encoding) + (path / "state_current_level") + + let state_value = + Tezos_rpc.Service.get_service + ~description:"Retrieve value from key is PVM state of specified block" + ~query:Query.key_query + ~output:Data_encoding.bytes + (path / "state") + + let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve value by key from PVM durable storage. PVM state is taken \ + with respect to the specified block level. Value returned in hex \ + format." + ~query:Query.key_query + ~output:Data_encoding.(option bytes) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") + + let durable_state_length (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) + = + Tezos_rpc.Service.get_service + ~description: + "Retrieve number of bytes in raw representation of value by key from \ + PVM durable storage. PVM state is taken with respect to the specified \ + block level." + ~query:Query.key_query + ~output:Data_encoding.(option int64) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") + + let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve subkeys of the specified key from PVM durable storage. PVM \ + state is taken with respect to the specified block level." + ~query:Query.key_query + ~output:Data_encoding.(list string) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") + + let status = + Tezos_rpc.Service.get_service + ~description:"PVM status at block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.string + (path / "status") + + let outbox = + Tezos_rpc.Service.get_service + ~description:"Outbox at block for a given outbox level" + ~query:Query.outbox_level_query + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox") + + let simulate = + Tezos_rpc.Service.post_service + ~description:"Simulate messages evaluation by the PVM" + ~query:Tezos_rpc.Query.empty + ~input:Encodings.simulate_input + ~output:Encodings.eval_result + (path / "simulate") + + let dal_slots = + Tezos_rpc.Service.get_service + ~description:"Availability slots for a given block" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.list Dal.Slot.Header.encoding) + (path / "dal" / "slot_headers") + + let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = + Data_encoding.string_enum + [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + + let dal_processed_slots = + Tezos_rpc.Service.get_service + ~description:"Data availability processed slots and their statuses" + ~query:Tezos_rpc.Query.empty + ~output: + Data_encoding.( + list + @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) + (path / "dal" / "processed_slots") + + let level_param = + let destruct s = + match Int32.of_string_opt s with + | None -> Error "Invalid level" + | Some l -> ( + match Raw_level.of_int32 l with + | Error _ -> Error "Invalid level" + | Ok l -> Ok l) + in + let construct = Format.asprintf "%a" Raw_level.pp in + Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () + + let outbox_messages = + Tezos_rpc.Service.get_service + ~description:"Outbox at block for a given outbox level" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox" /: level_param / "messages") + + module Helpers = struct + type nonrec prefix = prefix + + let path = path / "helpers" + + let outbox_proof = + Tezos_rpc.Service.get_service + ~description:"Generate serialized output proof for some outbox message" + ~query:Query.outbox_proof_query + ~output: + Data_encoding.( + obj2 + (req "commitment" Sc_rollup.Commitment.Hash.encoding) + (req "proof" Encodings.hex_string)) + (path / "proofs" / "outbox") + + let outbox_proof_simple = + Tezos_rpc.Service.get_service + ~description: + "Generate serialized output proof for some outbox message at level \ + and index" + ~query:Query.message_index_query + ~output: + Data_encoding.( + obj2 + (req "commitment" Sc_rollup.Commitment.Hash.encoding) + (req "proof" Encodings.hex_string)) + (path / "proofs" / "outbox" /: level_param / "messages") + end +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.ml new file mode 100644 index 000000000000..e1b9e398d6ce --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.ml @@ -0,0 +1,338 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2022-2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Rpc_directory_helpers +open Protocol + +module Slot_pages_map = struct + open Protocol + open Alpha_context + include Map.Make (Dal.Slot_index) +end + +let get_dal_processed_slots node_ctxt block = + Node_context.list_slots_statuses node_ctxt ~confirmed_in_block_hash:block + +module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block + + type context = Node_context.rw + + type subcontext = Node_context.ro * Block_hash.t + + let context_of_prefix node_ctxt (((), block) : prefix) = + let open Lwt_result_syntax in + let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in + (Node_context.readonly node_ctxt, block) +end) + +module Block_helpers_directory = Make_sub_directory (struct + include Sc_rollup_services.Block.Helpers + + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) + type context = Node_context.rw + + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) + type subcontext = Node_context.rw * Block_hash.t + + let context_of_prefix node_ctxt (((), block) : prefix) = + let open Lwt_result_syntax in + let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in + (node_ctxt, block) +end) + +module Common = struct + let () = + Block_directory.register0 Sc_rollup_services.Block.block + @@ fun (node_ctxt, block) () () -> + Node_context.get_full_l2_block node_ctxt block + + let () = + Block_directory.register0 Sc_rollup_services.Block.num_messages + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* l2_block = Node_context.get_l2_block node_ctxt block in + let+ num_messages = + Node_context.get_num_messages node_ctxt l2_block.header.inbox_witness + in + Z.of_int num_messages + + let () = + let open Lwt_result_syntax in + Block_directory.register0 Sc_rollup_services.Block.hash + @@ fun (_node_ctxt, block) () () -> return block + + let () = + Block_directory.register0 Sc_rollup_services.Block.level + @@ fun (node_ctxt, block) () () -> + Node_context.level_of_hash node_ctxt block + + let () = + Block_directory.register0 Sc_rollup_services.Block.inbox + @@ fun (node_ctxt, block) () () -> + Node_context.get_inbox_by_block_hash node_ctxt block + + let () = + Block_directory.register0 Sc_rollup_services.Block.ticks + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let+ l2_block = Node_context.get_l2_block node_ctxt block in + Z.of_int64 l2_block.num_ticks +end + +let get_state (node_ctxt : _ Node_context.t) block_hash = + let open Lwt_result_syntax in + let* ctxt = Node_context.checkout_context node_ctxt block_hash in + let*! state = Context.PVMState.find ctxt in + let (module PVM) = Pvm.of_kind node_ctxt.kind in + match state with None -> failwith "No state" | Some state -> return state + +let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages + ~insight_requests ~log_kernel_debug_file messages = + let open Lwt_result_syntax in + let open Alpha_context in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let reveal_map = + match reveal_pages with + | Some pages -> + let (module DAC_plugin) = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in + let map = + List.fold_left + (fun map page -> + let hash = DAC_plugin.hash_string ~scheme:Blake2B [page] in + Utils.Reveal_hash_map.add hash page map) + Utils.Reveal_hash_map.empty + pages + in + Some map + | None -> None + in + let* level = Node_context.level_of_hash node_ctxt block in + let* sim = + Simulation.start_simulation + node_ctxt + ~reveal_map + ?log_kernel_debug_file + Layer1.{hash = block; level} + in + let* sim, num_ticks_0 = Simulation.simulate_messages sim messages in + let* {state; inbox_level; _}, num_ticks_end = Simulation.end_simulation sim in + let*! insights = + let open PVM in + List.map_p + (function + | Sc_rollup_services.Pvm_state_key key -> + State.lookup (Ctxt_wrapper.of_node_pvmstate state) key + | Durable_storage_key key -> + Inspect_durable_state.lookup + (Ctxt_wrapper.of_node_pvmstate state) + key) + insight_requests + in + let num_ticks = Z.(num_ticks_0 + num_ticks_end) in + let level = Raw_level.of_int32_exn inbox_level in + let*! outbox = + PVM.get_outbox level (PVM.Ctxt_wrapper.of_node_pvmstate state) + in + let output = + List.filter (fun Sc_rollup.{outbox_level; _} -> outbox_level = level) outbox + in + let*! state_hash = PVM.state_hash (PVM.Ctxt_wrapper.of_node_pvmstate state) in + let* constants = + Protocol_plugins.get_constants_of_level node_ctxt inbox_level + in + let is_reveal_enabled = + constants.sc_rollup.reveal_activation_level + |> WithExceptions.Option.get ~loc:__LOC__ + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Protocol.Alpha_context.Sc_rollup.is_reveal_enabled_predicate + in + let*! status = + PVM.get_status ~is_reveal_enabled (PVM.Ctxt_wrapper.of_node_pvmstate state) + in + let status = PVM.string_of_status status in + return + Sc_rollup_services. + {state_hash; status; output; inbox_level; num_ticks; insights} + +let () = + Block_directory.register0 Sc_rollup_services.Block.total_ticks + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let open (val Pvm.of_kind node_ctxt.kind) in + let*! tick = get_tick (Ctxt_wrapper.of_node_pvmstate state) in + return tick + +let () = + Block_directory.register0 Sc_rollup_services.Block.state_hash + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let open (val Pvm.of_kind node_ctxt.kind) in + let*! hash = state_hash (Ctxt_wrapper.of_node_pvmstate state) in + return hash + +let () = + Block_directory.register0 Sc_rollup_services.Block.state_current_level + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let open (val Pvm.of_kind node_ctxt.kind) in + let*! current_level = + get_current_level (Ctxt_wrapper.of_node_pvmstate state) + in + return current_level + +let () = + Block_directory.register0 Sc_rollup_services.Block.state_value + @@ fun (node_ctxt, block) {key} () -> + let open Lwt_result_syntax in + let* ctx = get_state node_ctxt block in + let path = String.split_on_char '/' key in + let*! value = Context.PVMState.lookup ctx path in + match value with + | None -> failwith "No such key in PVM state" + | Some value -> + Format.eprintf "Encoded %S\n@.%!" (Bytes.to_string value) ; + return value + +let () = + Block_directory.register0 Sc_rollup_services.Block.status + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let* constants = + Protocol_plugins.get_constants_of_block_hash node_ctxt block + in + let is_reveal_enabled = + constants.sc_rollup.reveal_activation_level + |> WithExceptions.Option.get ~loc:__LOC__ + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Protocol.Alpha_context.Sc_rollup.is_reveal_enabled_predicate + in + let open (val Pvm.of_kind node_ctxt.kind) in + let*! status = + get_status ~is_reveal_enabled (Ctxt_wrapper.of_node_pvmstate state) + in + return (string_of_status status) + +let () = + Block_directory.register0 Sc_rollup_services.Block.dal_slots + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* constants = + Protocol_plugins.get_constants_of_block_hash node_ctxt block + in + let+ slots = + Node_context.get_all_slot_headers node_ctxt ~published_in_block_hash:block + in + List.rev_map + (Sc_rollup_proto_types.Dal.Slot_header.of_octez + ~number_of_slots:constants.dal.number_of_slots) + slots + |> List.rev + +let () = + Block_directory.register0 Sc_rollup_services.Block.dal_processed_slots + @@ fun (node_ctxt, block) () () -> get_dal_processed_slots node_ctxt block + +let () = + Block_directory.register0 Sc_rollup_services.Block.outbox + @@ fun (node_ctxt, block) outbox_level () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let open (val Pvm.of_kind node_ctxt.kind) in + let*! outbox = + get_outbox outbox_level (Ctxt_wrapper.of_node_pvmstate state) + in + return outbox + +let () = + Block_directory.register1 Sc_rollup_services.Block.outbox_messages + @@ fun (node_ctxt, block) outbox_level () () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let open (val Pvm.of_kind node_ctxt.kind) in + let*! outbox = + get_outbox outbox_level (Ctxt_wrapper.of_node_pvmstate state) + in + return outbox + +let () = + Block_helpers_directory.register0 + Sc_rollup_services.Block.Helpers.outbox_proof + @@ fun (node_ctxt, _block_hash) output () -> + let open Lwt_result_syntax in + let+ commitment, proof = Outbox.proof_of_output node_ctxt output in + (Sc_rollup_proto_types.Commitment_hash.of_octez commitment, proof) + +let () = + Block_helpers_directory.register1 + Sc_rollup_services.Block.Helpers.outbox_proof_simple + @@ fun (node_ctxt, _block_hash) outbox_level message_index () -> + let open Lwt_result_syntax in + let+ commitment, proof = + Outbox.proof_of_output_simple node_ctxt ~outbox_level ~message_index + in + (Sc_rollup_proto_types.Commitment_hash.of_octez commitment, proof) + +let () = + Block_directory.register0 Sc_rollup_services.Block.simulate + @@ fun (node_ctxt, block) + () + {messages; reveal_pages; insight_requests; log_kernel_debug_file} + -> + simulate_messages + node_ctxt + block + ~reveal_pages + ~insight_requests + ~log_kernel_debug_file + messages + +let block_directory (node_ctxt : _ Node_context.t) = + let module PVM = (val Pvm_rpc.of_kind node_ctxt.kind) in + List.fold_left + (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) + Tezos_rpc.Directory.empty + [ + Block_directory.build_sub_directory; + Block_helpers_directory.build_sub_directory; + PVM.build_sub_directory; + ] + +let directory (node_ctxt : _ Node_context.t) = + Tezos_rpc.Directory.merge + (Octez_smart_rollup_node.Rpc_directory.top_directory node_ctxt) + (Tezos_rpc.Directory.prefix + Sc_rollup_services.Block.prefix + (block_directory node_ctxt)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.mli new file mode 100644 index 000000000000..1cac46c2ded4 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/RPC_directory.mli @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The RPC directory, specific to blocks, for this rollup node. *) +val block_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t + +(** The full RPC directory for this rollup node, merging the top level directory + and the block directory. *) +val directory : Node_context.rw -> unit Tezos_rpc.Directory.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/arith_pvm.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/arith_pvm.ml new file mode 100644 index 000000000000..e18910690a4e --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/arith_pvm.ml @@ -0,0 +1,112 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022-2023 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This module manifests the proof format used by the Arith PVM as defined by + the Layer 1 implementation for it. + + It is imperative that this is aligned with the protocol's implementation. +*) +module Arith_proof_format = + Irmin_context.Proof + (struct + include Sc_rollup.State_hash + + let of_context_hash = Sc_rollup.State_hash.context_hash_to_state_hash + end) + (struct + let proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 + .tree_proof_encoding + end) + +module Impl : Pvm_sig.S = struct + module PVM = Sc_rollup.ArithPVM.Make (Arith_proof_format) + include PVM + + type repo = Irmin_context.repo + + type tree = Irmin_context.tree + + module Ctxt_wrapper = Context_wrapper.Irmin + + let kind = Sc_rollup.Kind.Example_arith + + module State = Irmin_context.PVMState + + module Inspect_durable_state = struct + let lookup _state _keys = + raise (Invalid_argument "No durable storage for arith PVM") + end + + module Unsafe_patches = struct + (** No unsafe patches for the arith PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . + end + + let new_dissection = Game_helpers.default_new_dissection + + let string_of_status = function + | Halted -> "Halted" + | Waiting_for_input_message -> "Waiting for input message" + | Waiting_for_reveal reveal -> + Format.asprintf + "Waiting for reveal %a" + Sc_rollup_PVM_sig.pp_reveal + reveal + | Parsing -> "Parsing" + | Evaluating -> "Evaluating" + + (* It is safe to pass the [is_reveal_enabled_predicate]: + [eval_many] always stops at the beginning of a new Tezos block, + so no execution of several Tezos block inboxes is possible. *) + let eval_many ~reveal_builtins:_ ~write_debug:_ ~is_reveal_enabled + ?stop_at_snapshot ~max_steps initial_state = + ignore stop_at_snapshot ; + let rec go state step = + let open Lwt.Syntax in + let* is_input_required = is_input_state ~is_reveal_enabled state in + + if is_input_required = No_input_required && step < max_steps then + let open Lwt.Syntax in + (* Note: This is not an efficient implementation because the state is + decoded/encoded to/from the tree at each step but for Arith PVM + it doesn't matter + *) + let* next_state = eval state in + go next_state (Int64.succ step) + else Lwt.return (state, step) + in + go initial_state 0L +end + +include Impl diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.ml new file mode 100644 index 000000000000..edfa3ea32f00 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.ml @@ -0,0 +1,56 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let message_size_limit = Protocol.Constants_repr.sc_rollup_message_size_limit + +let protocol_max_batch_size = + let open Protocol in + let open Alpha_context in + let empty_message_op : _ Operation.t = + let open Operation in + { + shell = {branch = Block_hash.zero}; + protocol_data = + { + signature = Some Signature.zero; + contents = + Single + (Manager_operation + { + source = Signature.Public_key_hash.zero; + fee = Tez.of_mutez_exn Int64.max_int; + counter = Manager_counter.Internal_for_tests.of_int max_int; + gas_limit = + Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); + storage_limit = Z.of_int max_int; + operation = Sc_rollup_add_messages {messages = [""]}; + }); + }; + } + in + Protocol.Constants_repr.max_operation_data_length + - Data_encoding.Binary.length + Operation.encoding + (Operation.pack empty_message_op) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.mli new file mode 100644 index 000000000000..dda41ddc6be1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/batcher_constants.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Maximum size of an L2 message allowed by the prototcol. Is + {!val:Protocol.Constants_repr.sc_rollup_message_size_limit}. *) +val message_size_limit : int + +(** Maximum size in bytes of an batch of L2 messages that can fit in an + operation on L1. It is protocol dependent. *) +val protocol_max_batch_size : int diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.ml new file mode 100644 index 000000000000..68223c1c4e20 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.ml @@ -0,0 +1,110 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Context +open Context_sigs + +let err_implementation_mismatch ~got = + Format.kasprintf invalid_arg "PVM Context implementation mismatch: got %s" got + +module type S = sig + type repo + + type tree + + val of_node_context : 'a Context.t -> ('a, repo, tree) Context_sigs.t + + val to_node_context : ('a, repo, tree) Context_sigs.t -> 'a Context.t + + val of_node_pvmstate : Context.pvmstate -> tree + + val to_node_pvmstate : tree -> Context.pvmstate +end + +(* Context *) +let of_node_context : + type repo tree. + (repo, tree) equality_witness -> + 'a Context.t -> + ('a, repo, tree) Context_sigs.t = + fun eqw (Context {equality_witness; tree; index; _}) -> + match Context.equiv equality_witness eqw with + | Some Refl, Some Refl -> {index; tree} + | _ -> + (* This could happen if the context backend was to change for a + given pvm/rollup. For now we only use Irmin, if this changes, + this will demand to provide migration functions from prior + pmv_context to the next one. *) + assert false + +let to_node_context : + type repo tree. + (module Context_sigs.S with type tree = tree and type repo = repo) -> + ('a, repo, tree) Context_sigs.t -> + 'a Context.t = + fun (module C) {index; tree} -> + Context.make + ~index + ~tree + ~pvm_context_impl:(module C) + ~equality_witness:C.equality_witness + ~impl_name:C.impl_name + +(* PVMState *) +let of_node_pvmstate : + type repo tree. (repo, tree) equality_witness -> Context.pvmstate -> tree = + fun eqw (PVMState {equality_witness; pvmstate; _}) -> + match Context.equiv equality_witness eqw with + | Some Refl, Some Refl -> pvmstate + | _ -> assert false + +let to_node_pvmstate : + type tree. + (module Context_sigs.S with type tree = tree) -> tree -> Context.pvmstate = + fun (module C) pvmstate -> + Context.make_pvmstate + ~pvmstate + ~pvm_context_impl:(module C) + ~equality_witness:C.equality_witness + ~impl_name:C.impl_name + +module Irmin = struct + module I = Irmin_context + + type repo = I.repo + + type tree = I.tree + + let of_node_context : 'a Context.t -> ('a, repo, tree) Context_sigs.t = + fun ctxt -> of_node_context I.equality_witness ctxt + + let to_node_context : ('a, repo, tree) Context_sigs.t -> 'a Context.t = + fun ctxt -> to_node_context (module I) ctxt + + let of_node_pvmstate : Context.pvmstate -> tree = + fun c -> of_node_pvmstate I.equality_witness c + + let to_node_pvmstate : tree -> Context.pvmstate = to_node_pvmstate (module I) +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.mli new file mode 100644 index 000000000000..f91db71fe853 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/context_wrapper.mli @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +val err_implementation_mismatch : got:string -> 'a + +(** Context wrappers translate from/to node-context and node-pvmstate + PVMs internal representation to those used in the PVM. Each + different PVM context will imply a dedicated wrapper.*) +module type S = sig + type repo + + type tree + + val of_node_context : 'a Context.t -> ('a, repo, tree) Context_sigs.t + + val to_node_context : ('a, repo, tree) Context_sigs.t -> 'a Context.t + + val of_node_pvmstate : Context.pvmstate -> tree + + val to_node_pvmstate : tree -> Context.pvmstate +end + +(** Specialized module to handle translation to/from Irmin_context. + Directly used in Arith, Wasm_2_0_0 and RISC-V PVM *) +module Irmin : + S with type repo = Irmin_context.repo and type tree = Irmin_context.tree diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.ml new file mode 100644 index 000000000000..50208c2472e8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.ml @@ -0,0 +1,360 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Apply_results + +(** Returns [Some c] if [their_commitment] is refutable where [c] is our + commitment for the same inbox level. *) +let is_refutable_commitment node_ctxt + (their_commitment : Sc_rollup.Commitment.t) their_commitment_hash = + let open Lwt_result_syntax in + let* l2_block = + Node_context.get_l2_block_by_level + node_ctxt + (Raw_level.to_int32 their_commitment.inbox_level) + in + let* our_commitment_and_hash = + Option.filter_map_es + (fun hash -> + let hash = Sc_rollup_proto_types.Commitment_hash.of_octez hash in + let+ commitment = Node_context.find_commitment node_ctxt hash in + Option.map (fun c -> (c, hash)) commitment) + l2_block.header.commitment_hash + in + match our_commitment_and_hash with + | Some (our_commitment, our_commitment_hash) + when Sc_rollup.Commitment.Hash.( + their_commitment_hash <> our_commitment_hash + && their_commitment.predecessor = our_commitment.predecessor) -> + return our_commitment_and_hash + | _ -> return_none + +(** Publish a commitment when an accuser node sees a refutable commitment. *) +let accuser_publish_commitment_when_refutable node_ctxt ~other rollup + their_commitment their_commitment_hash = + let open Lwt_result_syntax in + when_ (Node_context.is_accuser node_ctxt) @@ fun () -> + (* We are seeing a commitment from someone else. We check if we agree + with it, otherwise the accuser publishes our commitment in order to + play the refutation game. *) + let* refutable = + is_refutable_commitment node_ctxt their_commitment their_commitment_hash + in + match refutable with + | None -> return_unit + | Some (our_commitment, our_commitment_hash) -> + let*! () = + Refutation_game_event.potential_conflict_detected + ~our_commitment_hash + ~their_commitment_hash + ~level:(Raw_level.to_int32 their_commitment.inbox_level) + ~other + in + assert (Sc_rollup.Address.(node_ctxt.config.sc_rollup_address = rollup)) ; + Publisher.publish_single_commitment node_ctxt our_commitment + +(** If in bailout mode and when the operator is not staked on any + commitment, the bond is recovered. *) +let maybe_recover_bond node_ctxt = + let open Lwt_result_syntax in + if Node_context.is_bailout node_ctxt then + let operating_pkh = Node_context.get_operator node_ctxt Operating in + match operating_pkh with + | None -> return_unit + | Some (Single operating_pkh) -> ( + let* staked_on_commitment = + RPC.Sc_rollup.staked_on_commitment + (new Protocol_client_context.wrap_full node_ctxt.cctxt) + (node_ctxt.cctxt#chain, `Head 0) + node_ctxt.config.sc_rollup_address + operating_pkh + in + match staked_on_commitment with + | None -> + (* the operator is no longer stake on any commitment then recover its bond *) + Publisher.recover_bond node_ctxt + | Some _ (* operator still staked on something *) -> return_unit) + else return_unit + +(** Process an L1 SCORU operation (for the node's rollup) which is included + for the first time. {b Note}: this function does not process inboxes for + the rollup, which is done instead by {!Inbox.process_head}. *) +let process_included_l1_operation (type kind) ~catching_up + (node_ctxt : Node_context.rw) (head : Layer1.header) ~source + (operation : kind manager_operation) + (result : kind successful_manager_operation_result) = + let open Lwt_result_syntax in + match (operation, result) with + | ( Sc_rollup_publish {commitment; _}, + Sc_rollup_publish_result {published_at_level; _} ) + when Node_context.is_operator node_ctxt source -> + (* Published commitment --------------------------------------------- *) + let commitment = Sc_rollup_proto_types.Commitment.to_octez commitment in + let commitment_hash = Octez_smart_rollup.Commitment.hash commitment in + let* () = + Node_context.register_published_commitment + node_ctxt + commitment + ~first_published_at_level:(Raw_level.to_int32 published_at_level) + ~level:head.Layer1.level + ~published_by_us:true + in + let*! () = + Commitment_event.last_published_commitment_updated + commitment_hash + head.Layer1.level + in + return_unit + | ( Sc_rollup_publish {commitment = their_commitment; rollup}, + Sc_rollup_publish_result + {published_at_level; staked_hash = their_commitment_hash; _} ) -> + (* Commitment published by someone else *) + (* We first register the publication information *) + let* known_commitment = + Node_context.commitment_exists node_ctxt their_commitment_hash + in + let* () = + if not known_commitment then return_unit + else + Node_context.register_published_commitment + node_ctxt + (Sc_rollup_proto_types.Commitment.to_octez their_commitment) + ~first_published_at_level:(Raw_level.to_int32 published_at_level) + ~level:head.Layer1.level + ~published_by_us:false + in + (* An accuser node will publish its commitment if the other one is + refutable. *) + accuser_publish_commitment_when_refutable + node_ctxt + ~other:source + rollup + their_commitment + their_commitment_hash + | ( Sc_rollup_cement _, + Sc_rollup_cement_result {inbox_level; commitment_hash; _} ) -> + (* Cemented commitment ---------------------------------------------- *) + let proto_commitment_hash = commitment_hash in + let inbox_level = Raw_level.to_int32 inbox_level in + let commitment_hash = + Sc_rollup_proto_types.Commitment_hash.to_octez commitment_hash + in + let* inbox_block = + Node_context.get_l2_block_by_level node_ctxt inbox_level + in + let*? () = + (* We stop the node if we disagree with a cemented commitment *) + let our_commitment_hash = inbox_block.header.commitment_hash in + error_unless + (Option.equal + Octez_smart_rollup.Commitment.Hash.( = ) + our_commitment_hash + (Some commitment_hash)) + (Sc_rollup_node_errors.Disagree_with_cemented + {inbox_level; ours = our_commitment_hash; on_l1 = commitment_hash}) + in + let* () = + Node_context.set_lcc + node_ctxt + {commitment = proto_commitment_hash; level = inbox_level} + in + let* () = maybe_recover_bond node_ctxt in + let* () = + Outbox_execution.publish_execute_whitelist_update_message node_ctxt + in + return_unit + | ( Sc_rollup_refute _, + Sc_rollup_refute_result {game_status = Ended end_status; _} ) + | ( Sc_rollup_timeout _, + Sc_rollup_timeout_result {game_status = Ended end_status; _} ) -> ( + match end_status with + | Loser {loser; reason} when Node_context.is_operator node_ctxt loser -> + let result = + match reason with + | Conflict_resolved -> Sc_rollup_node_errors.Conflict_resolved + | Timeout -> Timeout + in + tzfail (Sc_rollup_node_errors.Lost_game result) + | Loser _ -> + (* Other player lost *) + return_unit + | Draw -> + let stakers = + match operation with + | Sc_rollup_refute {opponent; _} -> [source; opponent] + | Sc_rollup_timeout {stakers = {alice; bob}; _} -> [alice; bob] + | _ -> assert false + in + fail_when + (List.exists (Node_context.is_operator node_ctxt) stakers) + (Sc_rollup_node_errors.Lost_game Draw)) + | Dal_publish_commitment _, Dal_publish_commitment_result {slot_header; _} + when Node_context.dal_supported node_ctxt -> + let* () = + Node_context.save_slot_header + node_ctxt + ~published_in_block_hash:head.Layer1.hash + (Sc_rollup_proto_types.Dal.Slot_header.to_octez slot_header) + in + return_unit + (* If the node is in bailout mode and the bond of the operator has + been recovered then initiate an exit from bailout mode and + gracefully shut down the process. Otherwise, no action is + taken. *) + | Sc_rollup_recover_bond {staker; _}, Sc_rollup_recover_bond_result _ + when Node_context.is_bailout node_ctxt -> ( + match Node_context.get_operator node_ctxt Operating with + | Some (Single operating_pkh) -> + fail_when + Signature.Public_key_hash.(operating_pkh = staker) + Sc_rollup_node_errors.Exit_bond_recovered_bailout_mode + | _ -> return_unit) + | ( Sc_rollup_execute_outbox_message {output_proof; _}, + Sc_rollup_execute_outbox_message_result + {whitelist_update = Some whitelist_update; _} ) -> ( + match whitelist_update with + | Public -> + let () = Reference.set node_ctxt.private_info None in + return_unit + | Private whitelist_update -> + let () = + Reference.map + (Option.map (fun private_info -> + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let output_proof = + Data_encoding.Binary.of_string_exn + PVM.output_proof_encoding + output_proof + in + let Sc_rollup.{outbox_level; message_index; _} = + PVM.output_of_output_proof output_proof + in + Node_context. + { + private_info with + last_whitelist_update = + { + outbox_level = Raw_level.to_int32 outbox_level; + message_index = Z.to_int message_index; + }; + })) + node_ctxt.private_info + in + if + catching_up + (* No need to check whitelist updates for historical data. *) + then return_unit + else + let*? () = + Node_context.check_op_in_whitelist_or_bailout_mode + node_ctxt + whitelist_update + in + return_unit) + | _, _ -> + (* Other manager operations *) + return_unit + +let process_l1_operation (type kind) ~catching_up node_ctxt + (head : Layer1.header) ~source (operation : kind manager_operation) + (result : kind Apply_results.manager_operation_result) = + let open Lwt_result_syntax in + let is_for_my_rollup : type kind. kind manager_operation -> bool = function + | Sc_rollup_add_messages _ -> true + | Sc_rollup_cement {rollup; _} + | Sc_rollup_publish {rollup; _} + | Sc_rollup_refute {rollup; _} + | Sc_rollup_timeout {rollup; _} + | Sc_rollup_execute_outbox_message {rollup; _} + | Sc_rollup_recover_bond {sc_rollup = rollup; staker = _} -> + Sc_rollup.Address.( + rollup = node_ctxt.Node_context.config.sc_rollup_address) + | Dal_publish_commitment _ -> true + | Reveal _ | Transaction _ | Origination _ | Delegation _ + | Update_consensus_key _ | Register_global_constant _ | Set_deposits_limit _ + | Increase_paid_storage _ | Transfer_ticket _ | Sc_rollup_originate _ + | Zk_rollup_origination _ | Zk_rollup_publish _ | Zk_rollup_update _ -> + false + in + (* Only look at operations that are for the node's rollup *) + if not (is_for_my_rollup operation) then return_unit + else + let*! () = + (* Only event for rollup node's own operations *) + if not (Node_context.is_operator node_ctxt source) then Lwt.return_unit + else + match Sc_rollup_injector.injector_operation_of_manager operation with + | None -> Lwt.return_unit + | Some op -> + let status, errors = + match result with + | Applied _ -> (`Applied, None) + | Backtracked (_, e) -> + (`Backtracked, Option.map Environment.wrap_tztrace e) + | Failed (_, e) -> (`Failed, Some (Environment.wrap_tztrace e)) + | Skipped _ -> (`Skipped, None) + in + Daemon_event.included_operation ?errors status op + in + match result with + | Applied success_result -> + process_included_l1_operation + ~catching_up + node_ctxt + head + ~source + operation + success_result + | _ -> + (* No action for non successful operations *) + return_unit + +let process_l1_block_operations ~catching_up node_ctxt (head : Layer1.header) = + let open Lwt_result_syntax in + let* block = + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash + in + let apply (type kind) accu ~source (operation : kind manager_operation) result + = + let open Lwt_result_syntax in + let* () = accu in + process_l1_operation ~catching_up node_ctxt head ~source operation result + in + let apply_internal (type kind) accu ~source:_ + (_operation : kind Apply_internal_results.internal_operation) + (_result : kind Apply_internal_results.internal_operation_result) = + accu + in + let* () = + Layer1_services.process_manager_operations + return_unit + block.operations + {apply; apply_internal} + in + return_unit diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.mli new file mode 100644 index 000000000000..0df410c38bc7 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/daemon_helpers.mli @@ -0,0 +1,30 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** React to L1 operations included in a block of the chain. *) +val process_l1_block_operations : + catching_up:bool -> Node_context.rw -> Layer1.header -> unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.ml new file mode 100644 index 000000000000..9cdcee56c686 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.ml @@ -0,0 +1,232 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** If a slot, published at some level L, is expected to be confirmed at level + L+D then, once the confirmation level is over, the rollup node is supposed to: + - Download and save the content of the slot's pages in the store, if the slot + is confirmed; + - Add entries [None] for the slot's pages in the store, if the slot + is not confirmed. *) + +type error += + | Dal_slot_not_found_in_store of Dal.Slot.Header.id + | Dal_invalid_page_for_slot of Dal.Page.t + +let () = + Sc_rollup_node_errors.register_error_kind + `Permanent + ~id:"dal_pages_request.dal_slot_not_found_in_store" + ~title:"Dal slot not found in store" + ~description:"The Dal slot whose ID is given is not found in the store" + ~pp:(fun ppf -> + Format.fprintf ppf "Dal slot not found in store %a" Dal.Slot.Header.pp_id) + Data_encoding.(obj1 (req "slot_id" Dal.Slot.Header.id_encoding)) + (function Dal_slot_not_found_in_store slot_id -> Some slot_id | _ -> None) + (fun slot_id -> Dal_slot_not_found_in_store slot_id) ; + Sc_rollup_node_errors.register_error_kind + `Permanent + ~id:"dal_pages_request.dal_invalid_page_for_slot" + ~title:"Invalid Dal page requested for slot" + ~description:"The requested Dal page for a given slot is invalid" + ~pp:(fun ppf -> + Format.fprintf ppf "Invalid Dal page requested %a" Dal.Page.pp) + Data_encoding.(obj1 (req "page_id" Dal.Page.encoding)) + (function Dal_invalid_page_for_slot page_id -> Some page_id | _ -> None) + (fun page_id -> Dal_invalid_page_for_slot page_id) + +let store_entry_from_published_level ~dal_attestation_lag ~published_level + node_ctxt = + Node_context.hash_of_level node_ctxt + @@ Int32.( + add (of_int dal_attestation_lag) (Raw_level.to_int32 published_level)) + +(* The cache allows to not fetch pages on the DAL node more than necessary. *) +module Pages_cache = + Aches_lwt.Lache.Make + (Aches.Rache.Transfer + (Aches.Rache.LRU) + (struct + include Cryptobox.Commitment + + let hash commitment = + Data_encoding.Binary.to_string_exn + Cryptobox.Commitment.encoding + commitment + |> Hashtbl.hash + end)) + +let get_slot_pages = + let pages_cache = Pages_cache.create 16 (* 130MB *) in + fun dal_cctxt commitment -> + Pages_cache.bind_or_put + pages_cache + commitment + (Dal_node_client.get_slot_pages dal_cctxt) + Lwt.return + +let download_confirmed_slot_pages ({Node_context.dal_cctxt; _} as node_ctxt) + ~published_level ~index = + let open Lwt_result_syntax in + let* published_in_block_hash = + Node_context.hash_of_level node_ctxt (Raw_level.to_int32 published_level) + in + let* header = + Node_context.get_slot_header node_ctxt ~published_in_block_hash index + in + let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ dal_cctxt in + (* DAL must be configured for this point to be reached *) + get_slot_pages dal_cctxt header.commitment + +let storage_invariant_broken published_level index = + failwith + "Internal error: [Node_context.find_slot_status] is supposed to have \ + registered the status of the slot %d published at level %a in the store" + index + Raw_level.pp + published_level + +let slot_id_is_valid + (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) + ~dal_activation_level ~origination_level ~inbox_level slot_id + ~dal_attested_slots_validity_lag = + let open Alpha_context in + Result.is_ok + (Dal.Slot_index.check_is_in_range + ~number_of_slots:dal_constants.number_of_slots + slot_id.Dal.index) + && + let origination_level_res = Raw_level.of_int32 origination_level in + let commit_inbox_level_res = Raw_level.of_int32 inbox_level in + match (origination_level_res, commit_inbox_level_res) with + | Ok origination_level, Ok commit_inbox_level -> + Alpha_context.Sc_rollup.Proof.Dal_helpers.import_level_is_valid + ~dal_activation_level + ~dal_attestation_lag:dal_constants.attestation_lag + ~origination_level + ~commit_inbox_level + ~dal_attested_slots_validity_lag + ~published_level:slot_id.published_level + | _ -> false + +let page_id_is_valid + (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) + ~dal_activation_level ~origination_level ~inbox_level + Dal.Page.{slot_id; page_index} ~dal_attested_slots_validity_lag = + Result.is_ok + (Dal.Page.Index.check_is_in_range + ~number_of_pages: + (Dal.Page.pages_per_slot dal_constants.cryptobox_parameters) + page_index) + && slot_id_is_valid + dal_constants + ~dal_activation_level + ~origination_level + ~inbox_level + slot_id + ~dal_attested_slots_validity_lag + +let slot_pages + (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) + ~dal_activation_level ~inbox_level node_ctxt slot_id + ~dal_attested_slots_validity_lag = + let open Lwt_result_syntax in + let Node_context.{genesis_info = {level = origination_level; _}; _} = + node_ctxt + in + let Dal.Slot.Header.{published_level; index} = slot_id in + if + not + @@ slot_id_is_valid + dal_constants + ~dal_activation_level + ~origination_level + ~inbox_level + ~dal_attested_slots_validity_lag + slot_id + then return_none + else + let* confirmed_in_block_hash = + store_entry_from_published_level + ~dal_attestation_lag:dal_constants.attestation_lag + ~published_level + node_ctxt + in + let index = Sc_rollup_proto_types.Dal.Slot_index.to_octez index in + let* processed = + Node_context.find_slot_status node_ctxt ~confirmed_in_block_hash index + in + match processed with + | Some `Confirmed -> + let* pages = + download_confirmed_slot_pages node_ctxt ~published_level ~index + in + return (Some pages) + | Some `Unconfirmed -> return_none + | None -> storage_invariant_broken published_level index + +let page_content + (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) + ~dal_activation_level ~inbox_level node_ctxt page_id + ~dal_attested_slots_validity_lag = + let open Lwt_result_syntax in + let Dal.Page.{slot_id; page_index} = page_id in + let Dal.Slot.Header.{published_level; index} = slot_id in + let Node_context.{genesis_info = {level = origination_level; _}; _} = + node_ctxt + in + if + not + @@ page_id_is_valid + dal_constants + ~dal_activation_level + ~origination_level + ~inbox_level + ~dal_attested_slots_validity_lag + page_id + then return_none + else + let* confirmed_in_block_hash = + store_entry_from_published_level + ~dal_attestation_lag:dal_constants.attestation_lag + ~published_level + node_ctxt + in + let index = Sc_rollup_proto_types.Dal.Slot_index.to_octez index in + let* processed = + Node_context.find_slot_status node_ctxt ~confirmed_in_block_hash index + in + match processed with + | Some `Confirmed -> ( + let* pages = + download_confirmed_slot_pages node_ctxt ~published_level ~index + in + match List.nth_opt pages page_index with + | Some page -> return @@ Some page + | None -> tzfail @@ Dal_invalid_page_for_slot page_id) + | Some `Unconfirmed -> return_none + | None -> storage_invariant_broken published_level index diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.mli new file mode 100644 index 000000000000..e365e98fb5b8 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_pages_request.mli @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Access DAL slots and pages content. + + This module is a wrapper on top of {!Store.Dal_slot_pages} module to + access DAL slots and pages' data that have been previously fetched by + the rollup node. +*) + +(** This error is returned when a slot, identified by its ID, is not found in + the store. *) +type error += Dal_slot_not_found_in_store of Dal.Slot.Header.id + +(** Retrieve the pages' content of the given slot ID's from the store. + + The function returns [Dal_slot_not_found_in_store] if no entry is found in + the store for the given ID (i.e. no page is registered with or without content). + + If the returned value is [Some pages], the slot whose ID is given is + supposed to be confirmed and [pages] correspond to the pages of the slot. + Otherwise [None] is returned. + + The function relies on {!Store.Dal_slot_pages}'s invariants to guarantee that: + - the pages are returned in increasing order w.r.t. their indexes in the slot; + - the size of the list, in case it is not empty, is equal to the expected + number of pages in a slot. + + [dal_attestation_lag] is used to retrieve the correct entry in [store]. +*) +val slot_pages : + Octez_smart_rollup.Rollup_constants.dal_constants -> + dal_activation_level:Raw_level.t option -> + inbox_level:int32 -> + _ Node_context.t -> + Dal.slot_id -> + dal_attested_slots_validity_lag:int -> + Dal.Page.content list option tzresult Lwt.t + +(** Retrieve the content of the page identified by the given ID from the store. + + The function returns [Dal_slot_not_found_in_store] if no entry is found in + the store for the given ID. It returns [None] in case the level of the + requested page is out of bounds (e.g. in the future). Said otherwise, + some content is only returned for confirmed pages (slots) for + which the content has already been downloaded and saved to the store. + + [dal_attestation_lag] is used to retrieve the correct entry in [store]. +*) +val page_content : + Octez_smart_rollup.Rollup_constants.dal_constants -> + dal_activation_level:Raw_level.t option -> + inbox_level:int32 -> + _ Node_context.t -> + Dal.Page.t -> + dal_attested_slots_validity_lag:int -> + Dal.Page.content option tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.ml new file mode 100644 index 000000000000..eb4198d69171 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.ml @@ -0,0 +1,187 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +let ancestor_hash ~number_of_levels + ({Node_context.genesis_info; _} as node_ctxt) head = + let genesis_level = genesis_info.level in + let rec go number_of_levels (Layer1.{hash; level} as head) = + let open Lwt_result_syntax in + if level < genesis_level then return_none + else if number_of_levels = 0 then return_some hash + else + let* pred_head = Node_context.get_predecessor_opt node_ctxt head in + match pred_head with + | None -> return_none + | Some pred_head -> go (number_of_levels - 1) pred_head + in + go number_of_levels head + +(* Values of type `confirmations_info` are used to catalog the status of slots + published in a given block hash. These values record whether + the slot has been confirmed after the attestation_lag has passed. *) +type confirmations_info = { + (* The hash of the block in which the slots have been published. *) + published_block_hash : Block_hash.t; + (* The indexes of slots that have beenp published in block + with hash `published_block_hash`, and have later been confirmed. *) + confirmed_slots_indexes : Bitset.t; +} + +(** [slots_info constants node_ctxt head] gathers information about the slot confirmations + of slot indexes. It reads the slot indexes that have been declared available + from [head]'s block receipt. It then returns the hash of + the block where the slot headers have been published and the list of + slot indexes that have been confirmed for that block. *) +let slots_info constants node_ctxt (Layer1.{hash; _} as head) = + (* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3722 + The case for protocol migrations when the lag constant has + been changed is tricky, especially if the lag is reduced. + Suppose that a slot header is published at the second last level of a + cycle, and the lag is 2. The block is expected to be confirmed at the + first level of the new cycle. However, if during the protocol migration + we reduce the lag to 1, then the slots header will never be confirmed. + *) + let open Lwt_result_syntax in + let lag = constants.Rollup_constants.dal.attestation_lag in + (* we are downloading attestation for slots at level [level], so + we need to download the data at level [level - lag]. + *) + let* published_slots_block_hash = + ancestor_hash ~number_of_levels:lag node_ctxt head + in + match published_slots_block_hash with + | None -> + (* Less then lag levels have passed from the rollup origination, and + confirmed slots should not be applied *) + return_none + | Some published_block_hash -> + let* {metadata; _} = + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash + in + let*? metadata = + Option.to_result + ~none:(TzTrace.make @@ Layer1_services.Cannot_read_block_metadata hash) + metadata + in + (* `metadata.protocol_data.dal_attestation` is `None` if we are behind the + `Dal feature flag`: in this case we return an empty slot + attestation. *) + let confirmed_slots = metadata.protocol_data.dal_attestation in + let* published_slots_indexes = + Node_context.get_slot_indexes + node_ctxt + ~published_in_block_hash:published_block_hash + in + let number_of_slots = constants.dal.number_of_slots in + let confirmed_slots_indexes_list = + List.filter + (Dal.Attestation.is_attested confirmed_slots) + (List.filter_map + (Dal.Slot_index.of_int_opt ~number_of_slots) + published_slots_indexes) + in + let*? confirmed_slots_indexes = + Environment.wrap_tzresult + (confirmed_slots_indexes_list + |> List.map Dal.Slot_index.to_int + |> Bitset.from_list) + in + return @@ Some {published_block_hash; confirmed_slots_indexes} + +(* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3884 + avoid going back and forth between bitsets and lists of slot indexes. *) +let to_slot_index_list (constants : Rollup_constants.protocol_constants) bitset + = + let all_slots = Misc.(0 --> (constants.dal.number_of_slots - 1)) in + List.filter_e (Bitset.mem bitset) all_slots + +(* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/4139. + Use a shared storage between dal and rollup node to store slots data. +*) + +let download_and_save_slots constants (node_context : _ Node_context.t) + ~current_block_hash {published_block_hash; confirmed_slots_indexes} = + let open Lwt_result_syntax in + let*? all_slots = + Bitset.fill ~length:constants.Rollup_constants.dal.number_of_slots + |> Environment.wrap_tzresult + in + let*? not_confirmed = + Environment.wrap_tzresult + @@ to_slot_index_list constants + @@ Bitset.diff all_slots confirmed_slots_indexes + in + let*? confirmed = + Environment.wrap_tzresult + @@ to_slot_index_list constants confirmed_slots_indexes + in + (* The contents of each slot index are written to a different location on + disk, therefore calls to store contents for different slot indexes can + be parallelized. *) + let* () = + List.iter_ep + (fun s_slot -> + Node_context.save_slot_status + node_context + current_block_hash + s_slot + `Unconfirmed) + not_confirmed + in + List.iter_ep + (fun s_slot -> + let* () = + Node_context.save_slot_status + node_context + current_block_hash + s_slot + `Confirmed + in + let*! () = + Dal_slots_tracker_event.slot_has_been_confirmed + (Sc_rollup_proto_types.Dal.Slot_index.of_octez + ~number_of_slots:constants.dal.number_of_slots + s_slot) + published_block_hash + current_block_hash + in + return_unit) + confirmed + +let process_head node_ctxt (Layer1.{hash = head_hash; level} as head) = + let open Lwt_result_syntax in + let* constants = Protocol_plugins.get_constants_of_level node_ctxt level in + let* confirmation_info = slots_info constants node_ctxt head in + match confirmation_info with + | None -> return_unit + | Some confirmation_info -> + download_and_save_slots + ~current_block_hash:head_hash + constants + node_ctxt + confirmation_info diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.mli new file mode 100644 index 000000000000..f3b90f08e278 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker.mli @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The rollup node keeps the list of dal slots for each block it needs to + process. This is to determine whether the inbox for a given block will need + to be retrieved from the block operations, or from the data availability + layer after lag levels have passed and the slot for the block has been + declared available. + + The state of slots per block is persistent. *) + +(** [process_head node_ctxt head] performs the following operations: + {ul + {li it reads the attestations for headers published attestation_lag + levels preceding [head] from the block metadata, determines which + ones the rollup node will download, and stores the results in + [Store.Dal_confirmed_slots].} + } *) +val process_head : Node_context.rw -> Layer1.head -> unit tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker_event.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker_event.ml new file mode 100644 index 000000000000..b560cb2509fe --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dal_slots_tracker_event.ml @@ -0,0 +1,49 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module Simple = struct + include Internal_event.Simple + + let section = [Protocol.name; "smart_rollup_node"; "dal_slots_tracker"] + + let slot_has_been_confirmed = + declare_3 + ~section + ~name:"dal_confirmed_slot" + ~msg: + "Slot header for index {slot_index} was published at block \ + {published_hash}. The slot header has been confirmed at \ + {confirmed_hash}. The slot contents will be downloaded" + ~level:Notice + ("slot_index", Dal.Slot_index.encoding) + ("published_hash", Block_hash.encoding) + ("confirmed_hash", Block_hash.encoding) +end + +let slot_has_been_confirmed slot published_hash confirmed_hash = + Simple.(emit slot_has_been_confirmed (slot, published_hash, confirmed_hash)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dune b/src/proto_020_PsParisC/lib_sc_rollup_node/dune new file mode 100644 index 000000000000..05f2db089c34 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dune @@ -0,0 +1,76 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name octez_smart_rollup_node_PtParisB) + (package octez-smart-rollup-node-PtParisB) + (instrumentation (backend bisect_ppx)) + (libraries + octez-libs.base + octez-libs.stdlib-unix + octez-shell-libs.client-base + octez-shell-libs.client-base-unix + octez-protocol-019-PtParisB-libs.client + octez-protocol-019-PtParisB-libs.dal + octez-libs.tezos-context.encoding + octez-libs.tezos-context.helpers + tezos-protocol-019-PtParisB.protocol + octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-019-PtParisB.parameters + octez-libs.rpc + octez-libs.rpc-http + octez-libs.rpc-http-server + octez-libs.tezos-workers + tezos-dal-node-services + tezos-dal-node-lib + octez-protocol-019-PtParisB-libs.dac + tezos-dac-lib + tezos-dac-client-lib + octez-shell-libs.shell-services + octez-l2-libs.smart-rollup + octez-protocol-019-PtParisB-libs.smart-rollup + octez-protocol-019-PtParisB-libs.smart-rollup-layer2 + octez-protocol-019-PtParisB-libs.layer2-utils + octez-l2-libs.layer2_store + octez-crawler + octez-libs.tree-encoding + data-encoding + octez-internal-libs.irmin_pack + octez-internal-libs.irmin_pack.unix + octez-internal-libs.irmin + aches + aches-lwt + octez-injector + octez-smart-rollup-node-lib + octez-l2-libs.scoru-wasm + octez-l2-libs.scoru-wasm-fast + octez-libs.crypto-dal + octez-version.value) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezos_base + -open Tezos_base.TzPervasives + -open Tezos_stdlib_unix + -open Tezos_client_base + -open Tezos_client_base_unix + -open Tezos_client_019_PtParisB + -open Tezos_dal_019_PtParisB + -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_workers + -open Tezos_dal_node_lib + -open Tezos_dac_019_PtParisB + -open Tezos_dac_lib + -open Tezos_dac_client_lib + -open Tezos_shell_services + -open Octez_smart_rollup + -open Tezos_smart_rollup_019_PtParisB + -open Tezos_smart_rollup_layer2_019_PtParisB + -open Tezos_layer2_utils_019_PtParisB + -open Tezos_layer2_store + -open Octez_crawler + -open Octez_injector + -open Octez_smart_rollup_node + -open Tezos_crypto_dal)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/fueled_pvm.ml new file mode 100644 index 000000000000..8473f1d49ffa --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/fueled_pvm.ml @@ -0,0 +1,550 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +module Inbox = Sc_rollup.Inbox +open Pvm_plugin_sig + +module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct + type fuel = F.t + + type pvm_state = Context.pvmstate + + let get_reveal ~dac_client ~pre_images_endpoint ~data_dir ~pvm_kind reveal_map + hash = + let open Lwt_result_syntax in + let found_in_map = + match reveal_map with + | None -> None + | Some map -> + Utils.Reveal_hash_map.find_opt + (Reveals.proto_hash_to_dac_hash hash) + map + in + match found_in_map with + | Some data -> return data + | None -> + Reveals.get ~dac_client ~pre_images_endpoint ~data_dir ~pvm_kind hash + + type eval_completion = + | Aborted of {state : pvm_state; fuel : fuel; current_tick : int64} + | Completed of { + state : pvm_state; + fuel : fuel; + current_tick : int64; + failing_ticks : int64 list; + } + + exception Error_wrapper of tztrace + + let metadata (node_ctxt : _ Node_context.t) = + let address = + Sc_rollup_proto_types.Address.of_octez node_ctxt.config.sc_rollup_address + in + let origination_level = + Raw_level.of_int32_exn node_ctxt.genesis_info.level + in + Sc_rollup.Metadata.{address; origination_level} + + (** [eval_until_input node_ctxt reveal_map level message_index ~fuel + start_tick failing_ticks state] advances a PVM [state] until it wants + more inputs or there are no more [fuel] (if [Some fuel] is + specified). The evaluation is running under the processing of some + [message_index] at a given [level] and this is the [start_tick] of this + message processing. If some [failing_ticks] are planned by the loser + mode, they will be made. *) + let eval_until_input (node_ctxt : _ Node_context.t) reveal_map level + message_index ~fuel start_tick failing_ticks state = + let open Lwt_result_syntax in + let open Delayed_write_monad.Lwt_result_syntax in + let* constants = + Protocol_plugins.get_constants_of_level node_ctxt (Int32.of_int level) + in + let is_reveal_enabled = + match constants.sc_rollup.reveal_activation_level with + | None -> fun ~current_block_level:_ _ -> true + | Some reveal_activation_level -> + reveal_activation_level + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Protocol.Alpha_context.Sc_rollup.is_reveal_enabled_predicate + in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let metadata = metadata node_ctxt in + let dal_attested_slots_validity_lag = + match constants.sc_rollup.reveal_activation_level with + | Some reveal_activation_level when constants.dal.feature_enable -> + Int32.to_int reveal_activation_level.dal_attested_slots_validity_lag + | _ -> max_int + in + let* dal_activation_level = + if constants.dal.feature_enable then + match constants.sc_rollup.reveal_activation_level with + | None -> return_none + | Some reveal_activation_level -> + let*? level = + Raw_level.of_int32 reveal_activation_level.dal_parameters + |> Environment.wrap_tzresult + in + return_some level + else return_none + in + let dal_parameters = + Sc_rollup.Dal_parameters. + { + number_of_slots = Int64.of_int constants.dal.number_of_slots; + attestation_lag = Int64.of_int constants.dal.attestation_lag; + slot_size = Int64.of_int constants.dal.cryptobox_parameters.slot_size; + page_size = Int64.of_int constants.dal.cryptobox_parameters.page_size; + } + in + let reveal_builtins request = + match Sc_rollup.Wasm_2_0_0PVM.decode_reveal request with + | Reveal_raw_data hash -> ( + let*! data = + get_reveal + ~dac_client:node_ctxt.dac_client + ~pre_images_endpoint:node_ctxt.config.pre_images_endpoint + ~data_dir:node_ctxt.data_dir + ~pvm_kind:node_ctxt.kind + reveal_map + hash + in + match data with + | Error error -> + (* The [Error_wrapper] must be caught upstream and converted into + a tzresult. *) + Lwt.fail (Error_wrapper error) + | Ok data -> Lwt.return data) + | Reveal_metadata -> + Lwt.return + (Data_encoding.Binary.to_string_exn + Sc_rollup.Metadata.encoding + metadata) + | Request_dal_page dal_page -> ( + let*! content = + Dal_pages_request.page_content + constants.dal + ~dal_activation_level + ~dal_attested_slots_validity_lag + ~inbox_level:(Int32.of_int level) + node_ctxt + dal_page + in + match content with + | Error error -> + (* The [Error_wrapper] must be caught upstream and converted into + a tzresult. *) + (* This happens when, for example, the kernel requests a page from a future level. *) + Lwt.fail (Error_wrapper error) + | Ok None -> + (* The page was not confirmed by L1. + We return empty string in this case, as done in the slow executon. *) + Lwt.return "" + | Ok (Some b) -> Lwt.return (Bytes.to_string b)) + | Reveal_dal_parameters -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6562 + Consider supporting revealing of historical DAL parameters. *) + Lwt.return + (Data_encoding.Binary.to_string_exn + Sc_rollup.Dal_parameters.encoding + dal_parameters) + in + let eval_tick fuel failing_ticks state = + let max_steps = F.max_ticks fuel in + let normal_eval ?(max_steps = max_steps) state = + Lwt.catch + (fun () -> + let*! state, executed_ticks = + PVM.eval_many + ~reveal_builtins + ~write_debug:(Printer node_ctxt.kernel_debug_logger) + ~max_steps + ~is_reveal_enabled + state + in + return (state, executed_ticks, failing_ticks)) + (function + | Error_wrapper error -> Lwt.return (Error error) + | exn -> Lwt.reraise exn) + in + let failure_insertion_eval state tick failing_ticks' = + let*! () = + Interpreter_event.intended_failure + ~level + ~message_index + ~message_tick:tick + ~internal:true + in + let*! state = PVM.Internal_for_tests.insert_failure state in + return (state, 1L, failing_ticks') + in + match failing_ticks with + | xtick :: failing_ticks' -> + let jump = Int64.(max 0L (pred xtick)) in + if Compare.Int64.(jump = 0L) then + (* Insert the failure in the first tick. *) + failure_insertion_eval state xtick failing_ticks' + else + (* Jump just before the tick where we'll insert a failure. + Nevertheless, we don't execute more than [max_steps]. *) + let max_steps = Int64.max 0L max_steps |> Int64.min max_steps in + let open Delayed_write_monad.Lwt_result_syntax in + let>* state, executed_ticks, _failing_ticks = + normal_eval ~max_steps state + in + (* Insert the failure. *) + let>* state, executed_ticks', failing_ticks' = + failure_insertion_eval state xtick failing_ticks' + in + let executed_ticks = Int64.add executed_ticks executed_ticks' in + return (state, executed_ticks, failing_ticks') + | _ -> normal_eval state + in + let abort (state : PVM.tree) fuel current_tick = + let state = PVM.Ctxt_wrapper.to_node_pvmstate state in + return (Aborted {state; fuel; current_tick}) + in + let complete (state : PVM.tree) fuel current_tick failing_ticks = + let state = PVM.Ctxt_wrapper.to_node_pvmstate state in + return (Completed {state; fuel; current_tick; failing_ticks}) + in + let rec go (fuel : fuel) current_tick failing_ticks state = + let*! input_request = PVM.is_input_state ~is_reveal_enabled state in + match input_request with + | No_input_required when F.is_empty fuel -> abort state fuel current_tick + | No_input_required -> ( + let>* next_state, executed_ticks, failing_ticks = + eval_tick fuel failing_ticks state + in + let fuel_executed = F.of_ticks executed_ticks in + match F.consume fuel_executed fuel with + | None -> abort state fuel current_tick + | Some fuel -> + go + fuel + (Int64.add current_tick executed_ticks) + failing_ticks + next_state) + | Needs_reveal (Reveal_raw_data hash) -> ( + let* data = + get_reveal + ~dac_client:node_ctxt.dac_client + ~pre_images_endpoint:node_ctxt.config.pre_images_endpoint + ~data_dir:node_ctxt.data_dir + ~pvm_kind:node_ctxt.kind + reveal_map + hash + in + let*! next_state = PVM.set_input (Reveal (Raw_data data)) state in + match F.consume F.one_tick_consumption fuel with + | None -> abort state fuel current_tick + | Some fuel -> + go fuel (Int64.succ current_tick) failing_ticks next_state) + | Needs_reveal Reveal_metadata -> ( + let*! next_state = PVM.set_input (Reveal (Metadata metadata)) state in + match F.consume F.one_tick_consumption fuel with + | None -> abort state fuel current_tick + | Some fuel -> + go fuel (Int64.succ current_tick) failing_ticks next_state) + | Needs_reveal (Request_dal_page page_id) -> ( + let* content_opt = + Dal_pages_request.page_content + constants.dal + ~inbox_level:(Int32.of_int level) + ~dal_activation_level + ~dal_attested_slots_validity_lag + node_ctxt + page_id + in + let*! next_state = + PVM.set_input (Reveal (Dal_page content_opt)) state + in + match F.consume F.one_tick_consumption fuel with + | None -> abort state fuel current_tick + | Some fuel -> + go fuel (Int64.succ current_tick) failing_ticks next_state) + | Needs_reveal Reveal_dal_parameters -> ( + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6562 + Consider supporting revealing of historical DAL parameters. *) + let*! next_state = + PVM.set_input (Reveal (Dal_parameters dal_parameters)) state + in + match F.consume F.one_tick_consumption fuel with + | None -> abort state fuel current_tick + | Some fuel -> + go fuel (Int64.succ current_tick) failing_ticks next_state) + | Initial | First_after _ -> + complete state fuel current_tick failing_ticks + in + go fuel start_tick failing_ticks (PVM.Ctxt_wrapper.of_node_pvmstate state) + + (** [mutate input] corrupts the payload of [input] for testing purposes. *) + let mutate input = + let payload = + Sc_rollup.Inbox_message.unsafe_of_string + "\001to the cheater we promise pain and misery" + in + {input with Sc_rollup.payload} + + type feed_input_completion = + | Feed_input_aborted of {state : pvm_state; fuel : fuel; fed_input : bool} + | Feed_input_completed of {state : pvm_state; fuel : fuel} + + (** [feed_input node_ctxt reveal_map level message_index ~fuel + ~failing_ticks state input] feeds [input] (that has a given + [message_index] in inbox of [level]) to the PVM in order to advance + [state] to the next step that requires an input. This function is + controlled by some [fuel] and may introduce intended failures at some + given [failing_ticks]. *) + let feed_input (node_ctxt : _ Node_context.t) reveal_map level message_index + ~fuel ~failing_ticks state input = + let open Lwt_result_syntax in + let open Delayed_write_monad.Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let>* res = + eval_until_input + node_ctxt + reveal_map + level + message_index + ~fuel + 0L + failing_ticks + state + in + match res with + | Aborted {state; fuel; _} -> + return (Feed_input_aborted {state; fuel; fed_input = false}) + | Completed {state; fuel; current_tick = tick; failing_ticks} -> ( + let open Delayed_write_monad.Lwt_result_syntax in + match F.consume F.one_tick_consumption fuel with + | None -> return (Feed_input_aborted {state; fuel; fed_input = false}) + | Some fuel -> ( + let>* input, failing_ticks = + match failing_ticks with + | xtick :: failing_ticks' -> + if xtick = tick then + let*! () = + Interpreter_event.intended_failure + ~level + ~message_index + ~message_tick:tick + ~internal:false + in + return (mutate input, failing_ticks') + else return (input, failing_ticks) + | [] -> return (input, failing_ticks) + in + let*! state = + PVM.set_input + (Inbox_message input) + (PVM.Ctxt_wrapper.of_node_pvmstate state) + in + let state = PVM.Ctxt_wrapper.to_node_pvmstate state in + let>* res = + eval_until_input + node_ctxt + reveal_map + level + message_index + ~fuel + tick + failing_ticks + state + in + match res with + | Aborted {state; fuel; _} -> + return (Feed_input_aborted {state; fuel; fed_input = true}) + | Completed {state; fuel; _} -> + return (Feed_input_completed {state; fuel}))) + + let eval_messages ~reveal_map ~fuel node_ctxt ~message_counter_offset state + inbox_level messages = + let open Delayed_write_monad.Lwt_result_syntax in + let level = Int32.to_int inbox_level in + (* Iterate the PVM state with all the messages. *) + let rec feed_messages (state, fuel) message_index = function + | [] -> + (* Fed all messages *) + return (state, fuel, message_index - message_counter_offset, []) + | messages when F.is_empty fuel -> + (* Consumed all fuel *) + return (state, fuel, message_index - message_counter_offset, messages) + | message :: messages -> ( + let payload = Sc_rollup.Inbox_message.unsafe_of_string message in + let message_counter = Z.of_int message_index in + let input = + Sc_rollup. + { + inbox_level = Raw_level.of_int32_exn inbox_level; + message_counter; + payload; + } + in + let failing_ticks = + Loser_mode.is_failure + node_ctxt.Node_context.config.loser_mode + ~level + ~message_index + in + let>* res = + feed_input + node_ctxt + reveal_map + level + message_index + ~fuel + ~failing_ticks + state + input + in + match res with + | Feed_input_completed {state; fuel} -> + feed_messages (state, fuel) (message_index + 1) messages + | Feed_input_aborted {state; fuel; fed_input = false} -> + return + ( state, + fuel, + message_index - message_counter_offset, + message :: messages ) + | Feed_input_aborted {state; fuel; fed_input = true} -> + return + ( state, + fuel, + message_index + 1 - message_counter_offset, + messages )) + in + (feed_messages [@tailcall]) (state, fuel) message_counter_offset messages + + let eval_block_inbox ~fuel (node_ctxt : _ Node_context.t) (inbox, messages) + (state : Context.pvmstate) : + fuel eval_result Node_context.delayed_write tzresult Lwt.t = + let open Lwt_result_syntax in + let open Delayed_write_monad.Lwt_result_syntax in + let open (val Pvm.of_kind node_ctxt.kind) in + (* Obtain inbox and its messages for this block. *) + let inbox_level = Octez_smart_rollup.Inbox.inbox_level inbox in + let*! initial_tick = get_tick (Ctxt_wrapper.of_node_pvmstate state) in + (* Evaluate all the messages for this level. *) + let>* state, remaining_fuel, num_messages, remaining_messages = + eval_messages + ~reveal_map:None + ~fuel + node_ctxt + ~message_counter_offset:0 + state + inbox_level + messages + in + let pvm_state = Ctxt_wrapper.of_node_pvmstate state in + let*! final_tick = get_tick pvm_state in + let*! state_hash = state_hash pvm_state in + let num_ticks = Sc_rollup.Tick.distance initial_tick final_tick in + let eval_state = + { + state; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = Sc_rollup.Tick.to_z final_tick; + inbox_level; + message_counter_offset = num_messages; + remaining_fuel; + remaining_messages; + } + in + return {state = eval_state; num_ticks; num_messages} + + let eval_messages ?reveal_map (node_ctxt : _ Node_context.t) + { + state; + tick = initial_tick; + inbox_level; + message_counter_offset; + remaining_fuel = fuel; + remaining_messages = messages; + _; + } = + let open Lwt_result_syntax in + let open Delayed_write_monad.Lwt_result_syntax in + let>* state, remaining_fuel, num_messages, remaining_messages = + match messages with + | [] -> + let level = Int32.to_int inbox_level in + let message_index = message_counter_offset - 1 in + let failing_ticks = + Loser_mode.is_failure + node_ctxt.Node_context.config.loser_mode + ~level + ~message_index + in + let>* res = + eval_until_input + node_ctxt + reveal_map + level + message_index + ~fuel + 0L + failing_ticks + state + in + let state, remaining_fuel = + match res with + | Aborted {state; fuel; _} | Completed {state; fuel; _} -> + (state, fuel) + in + return (state, remaining_fuel, 0, []) + | _ -> + eval_messages + ~reveal_map + ~fuel + node_ctxt + ~message_counter_offset + state + inbox_level + messages + in + let open (val Pvm.of_kind node_ctxt.kind) in + let pvm_state = Ctxt_wrapper.of_node_pvmstate state in + let*! final_tick = get_tick pvm_state in + let final_tick = Sc_rollup.Tick.to_z final_tick in + let*! state_hash = state_hash pvm_state in + let num_ticks = Z.sub final_tick initial_tick in + let eval_state = + { + state; + state_hash = Sc_rollup_proto_types.State_hash.to_octez state_hash; + tick = final_tick; + inbox_level; + message_counter_offset = message_counter_offset + num_messages; + remaining_fuel; + remaining_messages; + } + in + return {state = eval_state; num_ticks; num_messages} +end + +module Free = Make_fueled (Fuel.Free) +module Accounted = Make_fueled (Fuel.Accounted) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/inbox.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox.ml new file mode 100644 index 000000000000..96147fd257f9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox.ml @@ -0,0 +1,308 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* module Constants will be shadowed by Alpha_context.Constansts + once we open Alpha_context, hence we we alias it to Rollup_node_constants +*) +open Protocol +open Alpha_context + +let lift promise = Lwt.map Environment.wrap_tzresult promise + +let get_messages Node_context.{l1_ctxt; _} head = + let open Lwt_result_syntax in + let* block = Layer1_helpers.fetch_tezos_block l1_ctxt head in + let apply (type kind) accu ~source:_ (operation : kind manager_operation) + _result = + let open Result_syntax in + let+ accu in + match operation with + | Sc_rollup_add_messages {messages} -> + let messages = + List.map + (fun message -> Sc_rollup.Inbox_message.External message) + messages + in + List.rev_append messages accu + | _ -> accu + in + let apply_internal (type kind) accu ~source + (operation : kind Apply_internal_results.internal_operation) + (result : + kind Apply_internal_results.successful_internal_operation_result) = + let open Result_syntax in + let* accu in + match (operation, result) with + | ( { + operation = Transaction {destination = Sc_rollup rollup; parameters; _}; + sender = Contract (Originated sender); + _; + }, + ITransaction_result (Transaction_to_sc_rollup_result _) ) -> + let+ payload = + Environment.wrap_tzresult @@ Script_repr.force_decode parameters + in + let message = + Sc_rollup.Inbox_message.Transfer + {destination = rollup; payload; sender; source} + in + Sc_rollup.Inbox_message.Internal message :: accu + | _ -> return accu + in + let*? rev_messages = + Layer1_services.( + process_applied_manager_operations + (Ok []) + block.operations + {apply; apply_internal}) + in + let*? messages = + Environment.wrap_tzresult + @@ List.rev_map_e + (fun msg -> + let open Result_syntax in + let+ msg = Sc_rollup.Inbox_message.serialize msg in + Sc_rollup.Inbox_message.unsafe_to_string msg) + rev_messages + in + return messages + +let same_as_layer_1 node_ctxt head_hash inbox = + let open Lwt_result_syntax in + let head_block = `Hash (head_hash, 0) in + let Node_context.{cctxt; _} = node_ctxt in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let* layer1_inbox = + Plugin.RPC.Sc_rollup.inbox cctxt (cctxt#chain, head_block) + in + let layer1_inbox = Sc_rollup_proto_types.Inbox.to_octez layer1_inbox in + fail_unless + (Octez_smart_rollup.Inbox.equal layer1_inbox inbox) + (Sc_rollup_node_errors.Inconsistent_inbox {layer1_inbox; inbox}) + +let add_messages ~is_first_block ~predecessor_timestamp ~predecessor inbox + messages = + let open Lwt_result_syntax in + let no_history = Sc_rollup.Inbox.History.empty ~capacity:0L in + lift + @@ let*? ( messages_history, + _no_history, + inbox, + witness, + messages_with_protocol_internal_messages ) = + Sc_rollup.Inbox.add_all_messages + ~first_block:is_first_block + ~predecessor_timestamp + ~predecessor + no_history + inbox + messages + in + let witness_hash = + Sc_rollup.Inbox_merkelized_payload_hashes.hash witness + in + return + ( messages_history, + witness_hash, + inbox, + messages_with_protocol_internal_messages ) + +let process_messages (node_ctxt : _ Node_context.t) ~is_first_block + ~(predecessor : Layer1.header) (head : Layer1.header) messages = + let open Lwt_result_syntax in + let level = head.level in + let* inbox = + Node_context.inbox_of_head node_ctxt (Layer1.head_of_header predecessor) + in + let predecessor_timestamp = predecessor.header.timestamp in + let inbox_metrics = Metrics.Inbox.metrics in + Prometheus.Gauge.set inbox_metrics.head_inbox_level @@ Int32.to_float level ; + let inbox = Sc_rollup_proto_types.Inbox.of_octez inbox in + let*? messages = + Environment.wrap_tzresult + @@ List.map_e + (fun msg -> + Sc_rollup.Inbox_message.(deserialize @@ unsafe_of_string msg)) + messages + in + let* ( _messages_history, + witness_hash, + inbox, + messages_with_protocol_internal_messages ) = + add_messages + ~is_first_block + ~predecessor_timestamp + ~predecessor:predecessor.hash + inbox + messages + in + Metrics.Inbox.Stats.set + messages_with_protocol_internal_messages + ~is_internal:(function + | Sc_rollup.Inbox_message.Internal _ -> true + | External _ -> false) ; + let*? messages_with_protocol_internal_messages = + Environment.wrap_tzresult + @@ List.map_e + (fun msg -> + let open Result_syntax in + let+ msg = Sc_rollup.Inbox_message.serialize msg in + Sc_rollup.Inbox_message.unsafe_to_string msg) + messages_with_protocol_internal_messages + in + let* () = + Node_context.save_messages + node_ctxt + witness_hash + ~predecessor:predecessor.hash + messages_with_protocol_internal_messages + in + let inbox = Sc_rollup_proto_types.Inbox.to_octez inbox in + let* inbox_hash = Node_context.save_inbox node_ctxt inbox in + let witness_hash = + Sc_rollup_proto_types.Merkelized_payload_hashes_hash.to_octez witness_hash + in + return + (inbox_hash, inbox, witness_hash, messages_with_protocol_internal_messages) + +let process_head (node_ctxt : _ Node_context.t) ~(predecessor : Layer1.header) + (head : Layer1.header) = + let open Lwt_result_syntax in + let first_inbox_level = node_ctxt.genesis_info.level |> Int32.succ in + if head.level >= first_inbox_level then + (* We compute the inbox of this block using the inbox of its + predecessor. That way, the computation of inboxes is robust to chain + reorganization. *) + let* collected_messages = get_messages node_ctxt head.hash in + let*! () = + Inbox_event.get_messages + head.hash + head.level + (List.length collected_messages) + in + let* head_proto = Node_context.protocol_of_level node_ctxt head.level in + let is_first_block = head_proto.first_level_of_protocol in + process_messages + node_ctxt + ~is_first_block + ~predecessor + head + collected_messages + else + let* inbox = + Layer1_helpers.genesis_inbox + node_ctxt.cctxt + ~genesis_level:node_ctxt.genesis_info.level + in + let Octez_smart_rollup.Inbox.{hash = witness; _} = + Octez_smart_rollup.Inbox.Skip_list.content inbox.old_levels_messages + in + let* () = + Node_context.save_messages + node_ctxt + witness + ~predecessor:predecessor.hash + [] + in + let* inbox_hash = Node_context.save_inbox node_ctxt inbox in + return (inbox_hash, inbox, witness, []) + +let payloads_history_of_messages ~is_first_block ~predecessor + ~predecessor_timestamp messages = + let open Result_syntax in + let dummy_inbox = + (* The inbox is not necessary to compute the payloads *) + Sc_rollup.Inbox.genesis ~predecessor_timestamp ~predecessor Raw_level.root + in + let* messages = + Environment.wrap_tzresult + @@ List.map_e + (fun msg -> + Sc_rollup.Inbox_message.(deserialize @@ unsafe_of_string msg)) + messages + in + let+ ( payloads_history, + _history, + _inbox, + _witness, + _messages_with_protocol_internal_messages ) = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4918 Inject + [Protocol_migration (Proto_017)] when migrating to proto_alpha + (N after next snapshot). *) + Environment.wrap_tzresult + @@ Sc_rollup.Inbox.add_all_messages + ~first_block:is_first_block + ~predecessor_timestamp + ~predecessor + (Sc_rollup.Inbox.History.empty ~capacity:0L) + dummy_inbox + messages + in + payloads_history + +let payloads_history_of_all_messages messages = + let open Result_syntax in + let payloads_history = + let capacity = List.length messages |> Int64.of_int in + Sc_rollup.Inbox_merkelized_payload_hashes.History.empty ~capacity + in + match List.map Sc_rollup.Inbox_message.unsafe_of_string messages with + | [] -> assert false + | first :: messages -> + Environment.wrap_tzresult + @@ let* payloads_history, witness = + Sc_rollup.Inbox_merkelized_payload_hashes.genesis + payloads_history + first + in + let* payloads_history, _witness = + List.fold_left_e + (fun (payloads_history, witness) -> + Sc_rollup.Inbox_merkelized_payload_hashes.add_payload + payloads_history + witness) + (payloads_history, witness) + messages + in + return payloads_history + +let serialize_external_message msg = + Environment.wrap_tzresult + @@ + let open Result_syntax in + let open Sc_rollup.Inbox_message in + let+ msg = serialize @@ External msg in + unsafe_to_string msg + +let init ~predecessor_timestamp ~predecessor ~level = + Sc_rollup.Inbox.genesis + ~predecessor_timestamp + ~predecessor + (Raw_level.of_int32_exn level) + |> Sc_rollup_proto_types.Inbox.to_octez + +module Internal_for_tests = struct + let process_messages = process_messages +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/inbox.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox.mli new file mode 100644 index 000000000000..88766f4b65ba --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox.mli @@ -0,0 +1,122 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The rollup node maintains an inbox of incoming messages. + + The incoming messages for a rollup are published on the layer 1. To + maintain the state of its inbox, a rollup node retrieves these + messages each time the tezos blockchain is updated. + + The inbox state is persistent. + +*) + +open Protocol.Alpha_context +open Sc_rollup + +(** [process_head node_ctxt ~predecessor head operations] changes the state of + the inbox to react to [head] (where [predecessor] is the predecessor of + [head] in the L1 chain). In particular, this process filters the provided + [operations] of the [head] block. *) +val process_head : + Node_context.rw -> + predecessor:Layer1.header -> + Layer1.header -> + (Octez_smart_rollup.Inbox.Hash.t + * Octez_smart_rollup.Inbox.t + * Merkelized_payload_hashes_hash.t + * string list) + tzresult + Lwt.t + +(** [add_messages ~is_first_block ~predecessor_timestamp + ~predecessor inbox messages] adds [messages] to the [inbox] using + {!Sc_rollup.Inbox.add_all_messages}. *) +val add_messages : + is_first_block:bool -> + predecessor_timestamp:Timestamp.time -> + predecessor:Block_hash.t -> + Inbox.t -> + Inbox_message.t list -> + (Inbox_merkelized_payload_hashes.History.t + * Inbox_merkelized_payload_hashes.Hash.t + * Inbox.t + * Inbox_message.t list) + tzresult + Lwt.t + +(** [payloads_history_of_messages ~is_first_block ~predecessor + ~predecessor_timestamp messages] builds the payloads history for + the list of [messages]. This allows to not store payloads + histories (which contain merkelized skip lists) but simply + messages. *) +val payloads_history_of_messages : + is_first_block:bool -> + predecessor:Block_hash.t -> + predecessor_timestamp:Timestamp.time -> + string list -> + Sc_rollup.Inbox_merkelized_payload_hashes.History.t tzresult + +(** [payloads_history_of_all_messages messages] builds the merkelized payloads + history for the list of serialzied messages [messages]. *) +val payloads_history_of_all_messages : + string trace -> Sc_rollup.Inbox_merkelized_payload_hashes.History.t tzresult + +(** [same_as_layer_1 node_ctxt block node_inbox] ensures that the rollup + node agrees with the L1 node that inbox for [block] is [node_inbox]. *) +val same_as_layer_1 : + _ Node_context.t -> + Block_hash.t -> + Octez_smart_rollup.Inbox.t -> + unit tzresult Lwt.t + +(** Serialize an external messages to the protocol representation. NOTE: this + adds a tag ['\001'] at the beginning. *) +val serialize_external_message : string -> string tzresult + +(** Returns the initial global inbox where [level] is the first level of the + protocol with smart rollups. *) +val init : + predecessor_timestamp:Time.Protocol.t -> + predecessor:Block_hash.t -> + level:int32 -> + Octez_smart_rollup.Inbox.t + +(**/**) + +module Internal_for_tests : sig + val process_messages : + Node_context.rw -> + is_first_block:bool -> + predecessor:Layer1.header -> + Layer1.header -> + string list -> + (Octez_smart_rollup.Inbox.Hash.t + * Octez_smart_rollup.Inbox.t + * Merkelized_payload_hashes_hash.t + * string list) + tzresult + Lwt.t +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.ml new file mode 100644 index 000000000000..346a494bcd56 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.ml @@ -0,0 +1,45 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Simple = struct + include Internal_event.Simple + + let section = [Protocol.name; "smart_rollup_node"; "inbox"] + + let get_messages = + declare_3 + ~section + ~name:"smart_rollup_node_layer_1_get_messages" + ~msg: + "Fetching {number_of_messages} messages from block {hash} at level \ + {level}" + ~level:Notice + ("hash", Block_hash.encoding) + ("level", Data_encoding.int32) + ("number_of_messages", Data_encoding.int32) +end + +let get_messages hash level number_of_messages = + Simple.(emit get_messages (hash, level, Int32.of_int number_of_messages)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.mli new file mode 100644 index 000000000000..4e313d39797b --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/inbox_event.mli @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [get_messages hash level n] emits the event that [n] messages are being + fetched from the block of the given [hash] at the given [level]. *) +val get_messages : Block_hash.t -> int32 -> int -> unit Lwt.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.ml new file mode 100644 index 000000000000..d5e2e719d1e5 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.ml @@ -0,0 +1,270 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context + +type Layer1.block += Block of Alpha_block_services.block_info + +let fetch cctxt ?metadata ?chain ?block () = + let open Lwt_result_syntax in + let+ block = Alpha_block_services.info cctxt ?metadata ?chain ?block () in + Block block + +let extract_header = function + | Block block -> block.header.shell + | _ -> + invalid_arg ("Internal error: Block is not of protocol " ^ Protocol.name) + +let fetch_tezos_block l1_ctxt hash = + let open Lwt_result_syntax in + let+ block = Layer1.fetch_tezos_block fetch extract_header l1_ctxt hash in + match block with + | Block block -> block + | _ -> + Format.kasprintf + invalid_arg + "Internal error: Block %a is not of protocol %s" + Block_hash.pp + hash + Protocol.name + +let prefetch_tezos_blocks = Layer1.prefetch_tezos_blocks fetch extract_header + +let get_last_cemented_commitment (cctxt : #Client_context.full) rollup_address : + Node_context.lcc tzresult Lwt.t = + let open Lwt_result_syntax in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let rollup_address = Sc_rollup_proto_types.Address.of_octez rollup_address in + let+ commitment, level = + Plugin.RPC.Sc_rollup.last_cemented_commitment_hash_with_level + cctxt + (cctxt#chain, `Head 0) + rollup_address + in + { + Node_context.commitment = + Sc_rollup_proto_types.Commitment_hash.to_octez commitment; + level = Protocol.Alpha_context.Raw_level.to_int32 level; + } + +let get_last_published_commitment ?(allow_unstake = true) + (cctxt : #Client_context.full) rollup_address operator = + let open Lwt_result_syntax in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let rollup_address = Sc_rollup_proto_types.Address.of_octez rollup_address in + let*! res = + Plugin.RPC.Sc_rollup.staked_on_commitment + cctxt + (cctxt#chain, `Head 0) + rollup_address + operator + in + match res with + | Error trace + when allow_unstake + && TzTrace.fold + (fun exists -> function + | Environment.Ecoproto_error + Protocol.Sc_rollup_errors.Sc_rollup_not_staked -> + true + | _ -> exists) + false + trace -> + return_none + | Error trace -> fail trace + | Ok None -> return_none + | Ok (Some (_staked_hash, staked_commitment)) -> + return_some (Sc_rollup_proto_types.Commitment.to_octez staked_commitment) + +let get_kind cctxt rollup_address = + let open Lwt_result_syntax in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let rollup_address = Sc_rollup_proto_types.Address.of_octez rollup_address in + let+ kind = + RPC.Sc_rollup.kind cctxt (cctxt#chain, cctxt#block) rollup_address () + in + Sc_rollup_proto_types.Kind.to_octez kind + +let genesis_inbox cctxt ~genesis_level = + let open Lwt_result_syntax in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let+ inbox = + Plugin.RPC.Sc_rollup.inbox cctxt (cctxt#chain, `Level genesis_level) + in + Sc_rollup_proto_types.Inbox.to_octez inbox + +let constants_of_parametric + Protocol.Alpha_context.Constants.Parametric. + { + minimal_block_delay; + delay_increment_per_round; + sc_rollup = + { + challenge_window_in_blocks; + commitment_period_in_blocks; + reveal_activation_level; + max_number_of_stored_cemented_commitments; + _; + }; + dal = + { + feature_enable; + attestation_lag; + number_of_slots; + cryptobox_parameters; + _; + }; + _; + } = + let open Protocol.Alpha_context in + Rollup_constants. + { + minimal_block_delay = Period.to_seconds minimal_block_delay; + delay_increment_per_round = Period.to_seconds delay_increment_per_round; + sc_rollup = + { + challenge_window_in_blocks; + commitment_period_in_blocks; + reveal_activation_level = + Some + (Sc_rollup_proto_types.Constants.reveal_activation_level_to_octez + reveal_activation_level); + max_number_of_stored_cemented_commitments; + }; + dal = + {feature_enable; attestation_lag; number_of_slots; cryptobox_parameters}; + } + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2901 + The constants are retrieved from the latest tezos block. These constants can + be different from the ones used at the creation at the rollup because of a + protocol amendment that modifies some of them. This need to be fixed when the + rollup nodes will be able to handle the migration of protocol. +*) +let retrieve_constants ?(block = `Head 0) cctxt = + let open Lwt_result_syntax in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let+ {parametric; _} = + Protocol.Constants_services.all cctxt (cctxt#chain, block) + in + constants_of_parametric parametric + +let retrieve_genesis_info cctxt rollup_address = + let open Lwt_result_syntax in + let open Protocol.Alpha_context in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let+ {level; commitment_hash} = + RPC.Sc_rollup.genesis_info cctxt (cctxt#chain, `Head 0) rollup_address + in + Node_context. + { + level = Raw_level.to_int32 level; + commitment_hash = + Sc_rollup_proto_types.Commitment_hash.to_octez commitment_hash; + } + +let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = + let open Protocol in + let open Alpha_context in + let open Lwt_result_syntax in + let exception Found_boot_sector of string in + let* block = fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let missing_boot_sector () = + failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash + in + Lwt.catch + (fun () -> + let apply (type kind) accu ~source:_ (operation : kind manager_operation) + (result : kind Apply_results.successful_manager_operation_result) = + match (operation, result) with + | ( Sc_rollup_originate {boot_sector; _}, + Sc_rollup_originate_result {address; _} ) + when node_ctxt.config.sc_rollup_address = address -> + raise (Found_boot_sector boot_sector) + | _ -> accu + in + let apply_internal (type kind) accu ~source:_ + (_operation : kind Apply_internal_results.internal_operation) + (_result : + kind Apply_internal_results.successful_internal_operation_result) = + accu + in + let*? () = + Layer1_services.( + process_applied_manager_operations + (Ok ()) + block.operations + {apply; apply_internal}) + in + missing_boot_sector ()) + (function + | Found_boot_sector boot_sector -> return boot_sector + | _ -> missing_boot_sector ()) + +let find_whitelist cctxt ?block rollup_address = + let block = match block with Some b -> `Hash (b, 0) | None -> `Head 0 in + Plugin.RPC.Sc_rollup.whitelist + (new Protocol_client_context.wrap_full (cctxt :> Client_context.full)) + (cctxt#chain, block) + rollup_address + +let find_last_whitelist_update cctxt rollup_address = + let open Lwt_result_syntax in + let* last_whitelist_update = + Plugin.RPC.Sc_rollup.last_whitelist_update + (new Protocol_client_context.wrap_full (cctxt :> Client_context.full)) + (cctxt#chain, `Head 0) + rollup_address + in + Option.map + (fun Protocol.Alpha_context.Sc_rollup.Whitelist. + {message_index; outbox_level} -> + (message_index, Protocol.Alpha_context.Raw_level.to_int32 outbox_level)) + last_whitelist_update + |> return + +let get_commitment cctxt rollup_address commitment_hash = + let open Lwt_result_syntax in + let+ commitment = + Plugin.RPC.Sc_rollup.commitment + (new Protocol_client_context.wrap_full (cctxt :> Client_context.full)) + (cctxt#chain, `Head 0) + rollup_address + commitment_hash + in + Sc_rollup_proto_types.Commitment.to_octez commitment diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.mli new file mode 100644 index 000000000000..8a665e9dc2ed --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/layer1_helpers.mli @@ -0,0 +1,17 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2023 Nomadic Labs *) +(* SPDX-FileCopyrightText: 2023-2024 Functori *) +(* *) +(*****************************************************************************) + +include Protocol_plugin_sig.LAYER1_HELPERS + +(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. + Looks for the block in the blocks cache first, and fetches it from the L1 + node otherwise. *) +val fetch_tezos_block : + Layer1.t -> + Block_hash.t -> + Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/outbox.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/outbox.ml new file mode 100644 index 000000000000..62a384011a20 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/outbox.ml @@ -0,0 +1,87 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Node_context +open Context_sigs + +let get_state_of_lcc node_ctxt = + let open Lwt_result_syntax in + let lcc = Reference.get node_ctxt.lcc in + let* block_hash = Node_context.hash_of_level node_ctxt lcc.level in + let* ctxt = Node_context.checkout_context node_ctxt block_hash in + let*! state = Context.PVMState.find ctxt in + return state + +let proof_of_output node_ctxt output = + let open Lwt_result_syntax in + let* state = get_state_of_lcc node_ctxt in + let lcc = Reference.get node_ctxt.lcc in + match state with + | None -> + (* + This case should never happen as origination creates an LCC which + must have been considered by the rollup node at startup time. + *) + failwith "Error producing outbox proof (no cemented state in the node)" + | Some state -> ( + let open (val Pvm.of_kind node_ctxt.kind) in + let*! proof = + produce_output_proof + (Ctxt_wrapper.of_node_context node_ctxt.context).index + (Ctxt_wrapper.of_node_pvmstate state) + output + in + match proof with + | Ok proof -> + let serialized_proof = + Data_encoding.Binary.to_string_exn output_proof_encoding proof + in + return @@ (lcc.commitment, serialized_proof) + | Error err -> + failwith + "Error producing outbox proof (%a)" + Environment.Error_monad.pp + err) + +let proof_of_output_simple node_ctxt ~outbox_level ~message_index = + let open Lwt_result_syntax in + let outbox_level = Protocol.Alpha_context.Raw_level.to_int32 outbox_level in + let* state = get_state_of_lcc node_ctxt in + let lcc = Reference.get node_ctxt.lcc in + match state with + | None -> + (* This case should never happen as origination creates an LCC which + must have been considered by the rollup node at startup time. *) + failwith "Error producing outbox proof (no cemented state in the node)" + | Some state -> + let+ proof = + Pvm_plugin.produce_serialized_output_proof + node_ctxt + state + ~outbox_level + ~message_index + in + (lcc.commitment, proof) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/outbox.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/outbox.mli new file mode 100644 index 000000000000..267c1f4c6913 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/outbox.mli @@ -0,0 +1,26 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2023 TriliTech, *) +(* *) +(*****************************************************************************) + +(** This module provides helper to interact with PVM outboxes. *) + +open Protocol.Alpha_context + +(** [proof_of_output node_ctxt output] returns the last cemented commitment hash + and the proof of the output in the LCC. *) +val proof_of_output : + Node_context.rw -> + Sc_rollup.output -> + (Octez_smart_rollup.Commitment.Hash.t * string) tzresult Lwt.t + +(** [proof_of_output_simple node_ctxt ~level ~message_index] returns the last + cemented commitment hash and the proof of the output in the LCC. *) +val proof_of_output_simple : + Node_context.rw -> + outbox_level:Raw_level.t -> + message_index:int -> + (Octez_smart_rollup.Commitment.Hash.t * string) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/pvm.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm.ml new file mode 100644 index 000000000000..cf18ee4cd990 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm.ml @@ -0,0 +1,35 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022-2023 TriliTech *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type S = Pvm_sig.S + +let of_kind : Kind.t -> (module S) = function + | Example_arith -> (module Arith_pvm) + | Wasm_2_0_0 -> (module Wasm_2_0_0_pvm) + | Riscv -> (module Riscv_pvm) + +let context : Kind.t -> (module Context_sigs.S) = function + | _ -> (module Irmin_context) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.ml new file mode 100644 index 000000000000..8c403dae83ac --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.ml @@ -0,0 +1,188 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Protocol +open Alpha_context +open Context_wrapper + +let context = Pvm.context + +let get_tick kind state = + let open Lwt_syntax in + let open (val Pvm.of_kind kind) in + let+ tick = get_tick (Ctxt_wrapper.of_node_pvmstate state) in + Sc_rollup.Tick.to_z tick + +let state_hash kind state = + let open Lwt_syntax in + let open (val Pvm.of_kind kind) in + let+ hash = state_hash (Ctxt_wrapper.of_node_pvmstate state) in + Sc_rollup_proto_types.State_hash.to_octez hash + +let initial_state kind = + let open Lwt_syntax in + let open (val Pvm.of_kind kind) in + let+ state = initial_state ~empty:(State.empty ()) in + Ctxt_wrapper.to_node_pvmstate state + +let parse_boot_sector kind = + let module PVM = (val Pvm.of_kind kind) in + PVM.parse_boot_sector + +let install_boot_sector kind state boot_sector = + let open Lwt_syntax in + let open (val Pvm.of_kind kind) in + let+ state = + install_boot_sector (Ctxt_wrapper.of_node_pvmstate state) boot_sector + in + Ctxt_wrapper.to_node_pvmstate state + +let get_current_level kind state = + let open Lwt_option_syntax in + let open (val Pvm.of_kind kind) in + let+ current_level = + get_current_level (Ctxt_wrapper.of_node_pvmstate state) + in + Raw_level.to_int32 current_level + +let get_status (node_ctxt : _ Node_context.t) state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let state = PVM.Ctxt_wrapper.of_node_pvmstate state in + let*! current_level = PVM.get_current_level state in + let* constants = + match current_level with + | None -> return node_ctxt.current_protocol.constants + | Some level -> + Protocol_plugins.get_constants_of_level + node_ctxt + (Raw_level.to_int32 level) + in + let is_reveal_enabled = + constants.sc_rollup.reveal_activation_level + |> WithExceptions.Option.get ~loc:__LOC__ + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Protocol.Alpha_context.Sc_rollup.is_reveal_enabled_predicate + in + let*! status = PVM.get_status ~is_reveal_enabled state in + return (PVM.string_of_status status) + +module Fueled = Fueled_pvm + +let start_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string start_of_level_serialized + +let end_of_level_serialized = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string end_of_level_serialized + +let protocol_migration_serialized = + let open Sc_rollup_inbox_message_repr in + Some (unsafe_to_string Raw_context.protocol_migration_serialized_message) + +let info_per_level_serialized ~predecessor ~predecessor_timestamp = + let open Sc_rollup_inbox_message_repr in + unsafe_to_string + (info_per_level_serialized ~predecessor ~predecessor_timestamp) + +let find_whitelist_update_output_index node_ctxt state ~outbox_level = + let open Lwt_syntax in + let outbox_level = Raw_level.of_int32_exn outbox_level in + let open (val Pvm.of_kind node_ctxt.Node_context.kind) in + let* outbox = get_outbox outbox_level (Ctxt_wrapper.of_node_pvmstate state) in + let rec aux i = function + | [] -> None + | Sc_rollup.{message = Whitelist_update _; _} :: _rest -> Some i + | _ :: rest -> aux (i - 1) rest + in + (* looking for the last whitelist update produced by the kernel, + list is reverted for this reason. *) + aux (List.length outbox - 1) (List.rev outbox) |> return + +let produce_serialized_output_proof node_ctxt state ~outbox_level ~message_index + = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.Node_context.kind) in + let state = PVM.Ctxt_wrapper.of_node_pvmstate state in + let outbox_level = Raw_level.of_int32_exn outbox_level in + let*! outbox = PVM.get_outbox outbox_level state in + let output = List.nth outbox message_index in + match output with + | None -> invalid_arg "invalid index" + | Some output -> ( + let*! proof = + PVM.produce_output_proof + (PVM.Ctxt_wrapper.of_node_context node_ctxt.context).index + state + output + in + match proof with + | Ok proof -> + let serialized_proof = + Data_encoding.Binary.to_string_exn PVM.output_proof_encoding proof + in + return serialized_proof + | Error err -> + failwith + "Error producing outbox proof (%a)" + Environment.Error_monad.pp + err) + +module Wasm_2_0_0 = struct + (* We can use Irmin directly here as the Wasm PVM uses only Irmin *) + open Irmin + + let decode_durable_state enc tree = + Wasm_2_0_0_pvm.Durable_state.Tree_encoding_runner.decode + enc + (of_node_pvmstate tree) + + let proof_mem_tree tree = + Wasm_2_0_0_pvm.Wasm_2_0_0_proof_format.Tree.mem_tree (of_node_pvmstate tree) + + let proof_fold_tree ?depth tree key ~order ~init ~f = + Wasm_2_0_0_pvm.Wasm_2_0_0_proof_format.Tree.fold + ?depth + (of_node_pvmstate tree) + key + ~order + ~init + ~f:(fun a b c -> f a (to_node_pvmstate b) c) +end + +module Unsafe = struct + let apply_patch (kind : Octez_smart_rollup.Kind.t) state + (patch : Pvm_patches.unsafe_patch) = + let open Lwt_result_syntax in + let open (val Pvm.of_kind kind) in + let*? patch = Unsafe_patches.of_patch patch in + let* state = + protect @@ fun () -> + Unsafe_patches.apply (Ctxt_wrapper.of_node_pvmstate state) patch + |> Lwt_result.ok + in + return (Ctxt_wrapper.to_node_pvmstate state) +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.mli new file mode 100644 index 000000000000..e0183f81e636 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_plugin.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Pvm_plugin_sig.S diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_rpc.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_rpc.ml new file mode 100644 index 000000000000..b56e3b5d1c5c --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_rpc.ml @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module type S = sig + (** Build RPC directory of the PVM *) + val build_sub_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t +end + +module No_rpc = struct + let build_sub_directory _node_ctxt = Tezos_rpc.Directory.empty +end + +let no_rpc = (module No_rpc : S) + +let of_kind = function + | Kind.Example_arith -> no_rpc + | Wasm_2_0_0 -> + (module Wasm_2_0_0_rpc.Make_RPC (Wasm_2_0_0_pvm.Durable_state) : S) + | Riscv -> no_rpc diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_sig.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_sig.ml new file mode 100644 index 000000000000..7afc012df23e --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/pvm_sig.ml @@ -0,0 +1,128 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022-2023 TriliTech *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** Desired module type of a PVM from the L2 node's perspective *) +module type S = sig + type repo + + type tree + + module Ctxt_wrapper : + Context_wrapper.S with type repo = repo and type tree = tree + + include + Sc_rollup.PVM.S + with type hash = Sc_rollup.State_hash.t + and type context = ([`Read | `Write], repo) Context_sigs.raw_index + and type state = tree + + (** Kind of the PVM. *) + val kind : Sc_rollup.Kind.t + + (** [get_tick state] gets the total tick counter for the given PVM state. *) + val get_tick : state -> Sc_rollup.Tick.t Lwt.t + + (** PVM status *) + type status + + (** [get_status ~is_reveal_enabled state] gives you the current execution status for the PVM. *) + val get_status : + is_reveal_enabled:Sc_rollup.is_reveal_enabled -> state -> status Lwt.t + + (** [string_of_status status] returns a string representation of [status]. *) + val string_of_status : status -> string + + (** [get_outbox outbox_level state] returns a list of outputs + available in the outbox of [state] at a given [outbox_level]. *) + val get_outbox : Raw_level.t -> state -> Sc_rollup.output list Lwt.t + + (** [eval_many ~max_steps s0] returns a state [s1] resulting from the + execution of up to [~max_steps] steps of the rollup at state [s0]. *) + val eval_many : + reveal_builtins:Tezos_scoru_wasm.Builtins.reveals -> + write_debug:Tezos_scoru_wasm.Builtins.write_debug -> + is_reveal_enabled:Sc_rollup.is_reveal_enabled -> + ?stop_at_snapshot:bool -> + max_steps:int64 -> + state -> + (state * int64) Lwt.t + + val new_dissection : + default_number_of_sections:int -> + start_chunk:Sc_rollup.Dissection_chunk.t -> + our_stop_chunk:Sc_rollup.Dissection_chunk.t -> + Sc_rollup.Tick.t list + + (** State storage for this PVM. *) + module State : sig + type value = state + + (** [empty ()] is the empty state. *) + val empty : unit -> state + + (** [find context] returns the PVM state stored in the [context], if any. *) + val find : ('a, repo, tree) Context_sigs.t -> state option Lwt.t + + (** [lookup state path] returns the data stored for the path [path] in the + PVM state [state]. *) + val lookup : state -> string list -> bytes option Lwt.t + + (** [set context state] saves the PVM state [state] in the context and + returns the updated context. Note: [set] does not perform any write on + disk, this information must be committed using {!val:Context.commit}. *) + val set : + ('a, repo, tree) Context_sigs.t -> + state -> + ('a, repo, tree) Context_sigs.t Lwt.t + end + + (** Inspect durable state using a more specialised way of reading the + PVM state. + For example in WASM, it decodes the durable storage in the state + before reading values. + *) + module Inspect_durable_state : sig + (** [lookup state path] returns the data stored for the path [path] in the + PVM state [state]. *) + val lookup : state -> string list -> bytes option Lwt.t + end + + (** Expose unsafe state patching functions for manual intervention. + At the moment this feature is only used to increase the maximum number of + ticks of the WASM PVM in a non refutable setting. *) + module Unsafe_patches : sig + type t + + (** [of_patch p] returns the PVM patch if it has a corresponding one. *) + val of_patch : Pvm_patches.unsafe_patch -> t tzresult + + (** [apply state patch] applies the unsafe patch [patch] on the state. *) + val apply : state -> t -> state Lwt.t + end +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.ml new file mode 100644 index 000000000000..ebd1ce0d99c9 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.ml @@ -0,0 +1,383 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** When the PVM is waiting for a Dal page input, this function attempts to + retrieve the page's content from the store, the data of its slot. Then it + computes the proof that the page is part of the slot and returns the + content along with the proof. + + If the PVM is not waiting for a Dal page input, or if the slot is known to + be unconfirmed on L1, this function returns [None]. If the data of the + slot are not saved to the store, the function returns a failure + in the error monad. *) +let page_info_from_pvm_state constants (node_ctxt : _ Node_context.t) + ~inbox_level (dal_params : Dal.parameters) start_state = + let open Lwt_result_syntax in + let is_reveal_enabled = + match constants.Rollup_constants.sc_rollup.reveal_activation_level with + | Some reveal_activation_level -> + Sc_rollup.is_reveal_enabled_predicate + (Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + reveal_activation_level) + | None -> + (* For older protocol, constants don't have the notion of reveal + activation level. *) + fun ~current_block_level:_ _ -> true + in + let* dal_activation_level, dal_attested_slots_validity_lag = + match constants.sc_rollup.reveal_activation_level with + | Some reveal_activation_level when constants.dal.feature_enable -> + let*? level = + Raw_level.of_int32 reveal_activation_level.dal_parameters + |> Environment.wrap_tzresult + in + return + ( Some level, + Int32.to_int reveal_activation_level.dal_attested_slots_validity_lag + ) + | _ -> return (None, max_int) + in + let*! input_request = + let open (val Pvm.of_kind node_ctxt.kind) in + is_input_state + ~is_reveal_enabled + (Ctxt_wrapper.of_node_pvmstate start_state) + in + match input_request with + | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( + let Dal.Page.{slot_id; page_index} = page_id in + let* pages = + Dal_pages_request.slot_pages + constants.Rollup_constants.dal + ~dal_activation_level + ~dal_attested_slots_validity_lag + ~inbox_level + node_ctxt + slot_id + in + match pages with + | None -> return_none (* The slot is not confirmed. *) + | Some pages -> ( + let pages_per_slot = dal_params.slot_size / dal_params.page_size in + (* check invariant that pages' length is correct. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 + It's better to do the check when the slots are saved into disk. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This check is not resilient to dal parameters change. *) + match List.nth_opt pages page_index with + | Some content -> + let* page_proof = + let dal_cctxt = + WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt + in + Dal_node_client.get_page_proof dal_cctxt page_index + @@ Bytes.concat Bytes.empty pages + in + return_some (content, page_proof) + | None -> + failwith + "Page index %d too big or negative.\n\ + Number of pages in a slot is %d." + page_index + pages_per_slot)) + | _ -> return_none + +let metadata (node_ctxt : _ Node_context.t) = + let address = node_ctxt.config.sc_rollup_address in + let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in + Sc_rollup.Metadata.{address; origination_level} + +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) (start_state : Context.pvmstate) = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in + (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted + inbox (from the skip list) which also matches [game.start_level - 1]. *) + let snapshot_level_int32 = + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level + in + let* context = + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in + let+ context = Node_context.checkout_context node_ctxt start_hash in + Context.index context + in + let dal_slots_history = + (* Similarly to what's done for inbox snapshot above. *) + Sc_rollup_proto_types.Dal.Slot_history.of_octez game.dal_snapshot + in + let get_cell_from_hash hash = + (* each time a DAL skip list cell is requested by hash, we retrieve it from the DAL node. *) + (* TODO: We may want to have a local cache here. *) + let open Lwt_syntax in + let dal_cctxt = node_ctxt.dal_cctxt in + let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ dal_cctxt in + let+ res = + Dal_proto_client.get_commitments_history_hash_content dal_cctxt hash + in + Result.to_option res + in + (* We fetch the value of protocol constants at block snapshot level + where the game started. *) + let* constants = + Protocol_plugins.get_constants_of_level node_ctxt snapshot_level_int32 + in + let dal_l1_parameters = constants.dal in + let dal_parameters = dal_l1_parameters.cryptobox_parameters in + let dal_attestation_lag = dal_l1_parameters.attestation_lag in + let dal_number_of_slots = dal_l1_parameters.number_of_slots in + let* dal_activation_level, dal_attested_slots_validity_lag = + match constants.sc_rollup.reveal_activation_level with + | Some reveal_activation_level when dal_l1_parameters.feature_enable -> + let*? level = + Raw_level.of_int32 reveal_activation_level.dal_parameters + |> Environment.wrap_tzresult + in + return + ( Some level, + Int32.to_int reveal_activation_level.dal_attested_slots_validity_lag + ) + | _ -> return (None, max_int) + in + let* page_info = + page_info_from_pvm_state + constants + ~inbox_level:game.inbox_level + node_ctxt + dal_parameters + start_state + in + let module P = struct + include PVM + + let context : context = (Ctxt_wrapper.of_node_context context).index + + let state = Ctxt_wrapper.of_node_pvmstate start_state + + let reveal hash = + let open Lwt_syntax in + let* res = + Reveals.get + ~dac_client:node_ctxt.dac_client + ~pre_images_endpoint:node_ctxt.config.pre_images_endpoint + ~data_dir:node_ctxt.data_dir + ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) + hash + in + match res with Ok data -> return_some data | Error _ -> return_none + + module Inbox_with_history = struct + let inbox = snapshot + + let get_history inbox_hash = + let open Lwt_syntax in + let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in + match inbox with + | Error err -> + Format.kasprintf + Stdlib.failwith + "Refutation game: Cannot get inbox history for %a, %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + pp_print_trace + err + | Ok inbox -> + Option.map + (fun i -> + Sc_rollup.Inbox.take_snapshot + (Sc_rollup_proto_types.Inbox.of_octez i)) + inbox + + let get_payloads_history witness = + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* messages = Messages.get node_ctxt witness in + let*? hist = Inbox.payloads_history_of_all_messages messages in + return hist + end + + module Dal_with_history = struct + let confirmed_slots_history = dal_slots_history + + let get_history = get_cell_from_hash + + let dal_attestation_lag = dal_attestation_lag + + let dal_parameters = dal_parameters + + let dal_number_of_slots = dal_number_of_slots + + let page_info = page_info + + let dal_activation_level = dal_activation_level + + let dal_attested_slots_validity_lag = dal_attested_slots_validity_lag + end + end in + let metadata = metadata node_ctxt in + let*! start_tick = + PVM.get_tick (PVM.Ctxt_wrapper.of_node_pvmstate start_state) + in + let is_reveal_enabled = + match constants.sc_rollup.reveal_activation_level with + | Some reveal_activation_level -> + Sc_rollup.is_reveal_enabled_predicate + (Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + reveal_activation_level) + | None -> + (* Constants for an older protocol, there is no notion of reveal + activation level for those. *) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6247 + default value for is_reveal_enabled that returns true for all reveal + supported in protocols <= 18. *) + fun ~current_block_level:_ _ -> true + in + let* proof = + trace + (Sc_rollup_node_errors.Cannot_produce_proof + { + inbox_level = game.inbox_level; + start_tick = Sc_rollup.Tick.to_z start_tick; + }) + @@ let*! result = + Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) + ~is_reveal_enabled + in + Lwt.return @@ Environment.wrap_tzresult result + in + let*? pvm_step = + Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step + |> Environment.wrap_tzresult + in + let unserialized_proof = {proof with pvm_step} in + let*! result = + Sc_rollup.Proof.valid + ~metadata + snapshot + (Raw_level.of_int32_exn game.inbox_level) + dal_slots_history + dal_parameters + ~dal_activation_level + ~dal_attestation_lag + ~dal_number_of_slots + ~pvm:(module PVM) + unserialized_proof + ~is_reveal_enabled + ~dal_attested_slots_validity_lag + in + let res = Environment.wrap_tzresult result in + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof + +let make_dissection plugin (node_ctxt : _ Node_context.t) ~start_state + ~start_chunk ~our_stop_chunk ~default_number_of_sections + ~commitment_period_tick_offset ~last_level = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let state_of_tick ?start_state tick = + Interpreter.state_of_tick + plugin + node_ctxt + ?start_state + ~tick:(Z.add (Sc_rollup.Tick.to_z tick) commitment_period_tick_offset) + last_level + in + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in + let start_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez start_chunk + in + let our_stop_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez our_stop_chunk + in + let+ dissection = + Game_helpers.make_dissection + ~state_of_tick + ~state_hash_of_eval_state + ?start_state + ~start_chunk + ~our_stop_chunk + @@ PVM.new_dissection + ~start_chunk + ~our_stop_chunk + ~default_number_of_sections + in + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + +let timeout_reached node_ctxt ~self ~opponent = + let open Lwt_result_syntax in + let Node_context.{config; cctxt; _} = node_ctxt in + let+ game_result = + Plugin.RPC.Sc_rollup.timeout_reached + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Head 0) + config.sc_rollup_address + self + opponent + in + let open Sc_rollup.Game in + match game_result with + | Some (Loser {loser; _}) -> + let is_it_me = Signature.Public_key_hash.(self = loser) in + not is_it_me + | _ -> false + +let get_conflicts cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, `Head 0) rollup staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts + +let get_ongoing_games cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, `Head 0) + rollup + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.mli new file mode 100644 index 000000000000..f1cb92984580 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/refutation_game_helpers.mli @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Protocol_plugin_sig.REFUTATION_GAME_HELPERS diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/reveals.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/reveals.ml new file mode 100644 index 000000000000..809a21eb48fc --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/reveals.ml @@ -0,0 +1,170 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context +module Reveal_hash = Protocol.Sc_rollup_reveal_hash + +type error += Wrong_hash of {found : Reveal_hash.t; expected : Reveal_hash.t} + +let () = + Sc_rollup_node_errors.register_error_kind + ~id:"sc_rollup.node.wrong_hash_of_reveal_preimage" + ~title:"Hash of reveal preimage is not correct" + ~description:"Hash of reveal preimage is not correct." + ~pp:(fun ppf (found, expected) -> + Format.fprintf + ppf + "The hash of reveal preimage is %a while a value of %a is expected" + Reveal_hash.pp + found + Reveal_hash.pp + expected) + `Permanent + Data_encoding.( + obj2 + (req "found" Reveal_hash.encoding) + (req "expected" Reveal_hash.encoding)) + (function + | Wrong_hash {found; expected} -> Some (found, expected) | _ -> None) + (fun (found, expected) -> Wrong_hash {found; expected}) + +type source = String of string | File of string + +let file_contents filename = + let open Lwt_result_syntax in + Lwt.catch + (fun () -> + let*! contents = Lwt_utils_unix.read_file filename in + return_some contents) + (fun _ -> return_none) + +let path data_dir pvm_name hash = + let hash = Protocol.Sc_rollup_reveal_hash.to_hex hash in + Filename.(concat (concat data_dir pvm_name) hash) + +let proto_hash_to_dac_hash ((module Plugin) : Dac_plugin.t) proto_reveal_hash = + proto_reveal_hash + |> Data_encoding.Binary.to_bytes_exn Protocol.Sc_rollup_reveal_hash.encoding + |> Data_encoding.Binary.of_bytes_exn Plugin.encoding + +let get_from_dac dac_client hash = + let dac_plugin = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in + Dac_observer_client.fetch_preimage + dac_client + dac_plugin + (proto_hash_to_dac_hash dac_plugin hash) + +let get_from_preimages_service ~pre_images_endpoint ~local_filename hash = + let open Lwt_result_syntax in + let hash_hex = Protocol.Sc_rollup_reveal_hash.to_hex hash in + let*! () = Interpreter_event.missing_pre_image ~hash:hash_hex in + let url = + Uri.with_path + pre_images_endpoint + String.(concat "/" [Uri.path pre_images_endpoint; hash_hex]) + in + let*! resp, body = Cohttp_lwt_unix.Client.get url in + let*! body_str = Cohttp_lwt.Body.to_string body in + match resp.status with + | `OK -> + let contents_hash = + Reveal_hash.hash_string ~scheme:Reveal_hash.Blake2B [body_str] + in + if Reveal_hash.equal contents_hash hash then + let*! () = + Lwt_utils_unix.create_dir (Filename.dirname local_filename) + in + let*! () = Lwt_utils_unix.create_file local_filename body_str in + return_some body_str + else + let*! () = + Interpreter_event.fetched_incorrect_pre_image + ~expected_hash:hash_hex + ~content_hash:(Protocol.Sc_rollup_reveal_hash.to_hex contents_hash) + in + return_none + | #Cohttp.Code.status_code -> + tzfail (Layer_1.Http_connection_error (resp.status, body_str)) + +let get ~dac_client ~pre_images_endpoint ~data_dir ~pvm_kind hash = + let open Lwt_result_syntax in + let* contents = + let filename = + path data_dir (Octez_smart_rollup.Kind.to_string pvm_kind) hash + in + let* file_contents = file_contents filename in + match file_contents with + | Some contents -> return contents + | None -> ( + match dac_client with + | Some dac_client -> get_from_dac dac_client hash + | None -> ( + match pre_images_endpoint with + | None -> + tzfail + (Sc_rollup_node_errors.Could_not_open_preimage_file filename) + | Some pre_images_endpoint -> ( + let* contents = + get_from_preimages_service + ~pre_images_endpoint + ~local_filename:filename + hash + in + match contents with + | Some contents -> return contents + | None -> + tzfail + (Sc_rollup_node_errors.Could_not_open_preimage_file + filename)))) + in + let*? () = + let contents_hash = + Reveal_hash.hash_string ~scheme:Reveal_hash.Blake2B [contents] + in + error_unless + (Reveal_hash.equal contents_hash hash) + (Wrong_hash {found = contents_hash; expected = hash}) + in + let* _encoded = + (* Check that the reveal input can be encoded within the bounds enforced by + the protocol. *) + trace Sc_rollup_node_errors.Could_not_encode_raw_data + @@ protect + @@ fun () -> + Data_encoding.Binary.to_bytes_exn + Sc_rollup.input_encoding + (Reveal (Raw_data contents)) + |> return + in + return contents + +let proto_hash_to_dac_hash proto_reveal_hash = + let dac_plugin = + WithExceptions.Option.get ~loc:__LOC__ @@ Dac_plugin.get Protocol.hash + in + proto_hash_to_dac_hash dac_plugin proto_reveal_hash diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/reveals.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/reveals.mli new file mode 100644 index 000000000000..746e1c74a7ea --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/reveals.mli @@ -0,0 +1,80 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This module provides basic support for reveals. + + The rollup can ask for data being the reveal of some hash. This + allows transferring data directly to the rollup without going + through the L1 inbox. + + Data length must be under 4KB to be refutable in a single L1 + operation. + + Data must be made available by off-chain mechanisms: it is the + responsibility of the rollup kernel to make sure that the reveal + data is available: otherwise, there is a potential safety issue. + + For the moment, the support is basic and mostly manual as the operator + needs to explicitly import a file in the rollup node data directoy to + enable the rollup node to answer reveal requests. + +*) + +(* FIXME:https://gitlab.com/tezos/tezos/-/issues/3854 + + We should probably have a mechanism to let the kernel declare + sources of reveal data so that the rollup node can automatically + download data in advance. *) + +(** Source of data *) +type source = + | String of string (** A string containing the whole data *) + | File of string + (** A file name whose associated file contains the whole data *) + +(** [get ~dac_client ~pre_images_endpoint ~data_dir ~pvm_name ~hash] retrieves + the data associated with the reveal hash [hash] from disk. If the data is + not already on disk, it will be retrieved with the [dac_client] or from an + HTTP service at [pre_images_endpoint]. May fail with: + {ul + {li [Wrong_hash {found; expected}] where [expected = hash], and + [found <> hash], if the data is retrieved and hashes to the wrong + hash [found],} + {li [Could_not_open_preimage_file filename] if the function tries to + retrieve the data from [filename], but it cannot read the contents + of the file.} + {li [Could_not_encode_raw_data] if the data is too large (more than + 4kB) to be revealed.} + } *) +val get : + dac_client:Dac_observer_client.t option -> + pre_images_endpoint:Uri.t option -> + data_dir:string -> + pvm_kind:Kind.t -> + Protocol.Sc_rollup_reveal_hash.t -> + string tzresult Lwt.t + +(** Conversion from protocol reveal hash to protocol agnostic DAC hash. *) +val proto_hash_to_dac_hash : Protocol.Sc_rollup_reveal_hash.t -> Dac_plugin.hash diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/riscv_pvm.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/riscv_pvm.ml new file mode 100644 index 000000000000..5bdcea883a6a --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/riscv_pvm.ml @@ -0,0 +1,219 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2023 Nomadic Labs. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +module Context = Irmin_context + +type repo = Context.repo + +type tree = Context.tree + +module Ctxt_wrapper = Context_wrapper.Irmin + +module type Serializable_state_S = sig + type context + + type state + + val empty : unit -> state + + val of_index : Context.rw_index -> context + + val state_encoding : state Data_encoding.t + + val directory : string +end + +module Embed_into_Irmin + (P : Sc_rollup.PVM.S) + (S : Serializable_state_S + with type context = P.context + and type state = P.state) : sig + include + Sc_rollup.PVM.S + with type context = Context.rw_index + and type state = Context.tree + and type hash = Sc_rollup.State_hash.t + + val decode : Context.tree -> P.state Lwt.t +end = struct + (* We need to instantiate this functor to access the underlying Tree module. *) + module Irmin_proof_format = + Context.Proof + (struct + include Sc_rollup.State_hash + + let of_context_hash = Sc_rollup.State_hash.context_hash_to_state_hash + end) + (struct + let proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 + .tree_proof_encoding + end) + + module Tree = Irmin_proof_format.Tree + + let decode state = + let open Lwt_syntax in + let* bytes_opt = Tree.find state [S.directory] in + match bytes_opt with + | None -> + Format.kasprintf + Lwt.fail_with + "Riscv_pvm: could not find state in /%s" + S.directory + | Some bytes -> + Data_encoding.Binary.of_bytes_exn S.state_encoding bytes |> Lwt.return + + let apply f state = + let open Lwt_syntax in + let* internal_state = decode state in + f internal_state + + let lift f state = + let open Lwt_syntax in + let* internal_state = decode state in + let* internal_state = f internal_state in + let bytes = + Data_encoding.Binary.to_bytes_exn S.state_encoding internal_state + in + Tree.add state [S.directory] bytes + + type context = Context.rw_index + + let parse_boot_sector = P.parse_boot_sector + + let pp_boot_sector = P.pp_boot_sector + + type state = Context.tree + + type hash = Sc_rollup.State_hash.t + + type proof = P.proof + + let pp = apply P.pp + + let proof_encoding = P.proof_encoding + + let proof_start_state = P.proof_start_state + + let proof_stop_state = P.proof_stop_state + + let state_hash = apply P.state_hash + + let initial_state ~empty = + let empty_state = S.empty () in + let bytes = + Data_encoding.Binary.to_bytes_exn S.state_encoding empty_state + in + Tree.add empty [S.directory] bytes + + let install_boot_sector state boot_sector = + lift (fun state -> P.install_boot_sector state boot_sector) state + + let is_input_state ~is_reveal_enabled state = + apply (P.is_input_state ~is_reveal_enabled) state + + let set_input input state = lift (P.set_input input) state + + let eval = lift P.eval + + let verify_proof = P.verify_proof + + let produce_proof context ~is_reveal_enabled input_opt state = + apply + (P.produce_proof (S.of_index context) ~is_reveal_enabled input_opt) + state + + type output_proof = P.output_proof + + let output_proof_encoding = P.output_proof_encoding + + let output_of_output_proof = P.output_of_output_proof + + let state_of_output_proof = P.state_of_output_proof + + let verify_output_proof = P.verify_output_proof + + let produce_output_proof context state output = + apply + (fun state -> P.produce_output_proof (S.of_index context) state output) + state + + let check_dissection = P.check_dissection + + let get_current_level = apply P.get_current_level + + module Internal_for_tests = struct + let insert_failure = lift P.Internal_for_tests.insert_failure + end +end + +module Serializable_riscv_state = struct + type context = Sc_rollup.Riscv_PVM.Protocol_implementation.context + + type state = Sc_rollup.Riscv_PVM.Protocol_implementation.state + + let empty = Sc_rollup_riscv.make_empty_state + + let directory = "riscv_pvm" + + let of_index _index = () + + let state_encoding = Sc_rollup_riscv.minimal_state_encoding +end + +include + Embed_into_Irmin + (Sc_rollup.Riscv_PVM.Protocol_implementation) + (Serializable_riscv_state) + +let kind = Sc_rollup.Kind.Riscv + +let get_tick state = + let open Lwt_syntax in + let* state = decode state in + Lwt.return (Sc_rollup.Tick.of_z state.Sc_rollup_riscv.tick) + +type status = Riscv_dummy_status + +let get_status ~is_reveal_enabled:_ _state = Lwt.return Riscv_dummy_status + +let string_of_status Riscv_dummy_status = "riscv_dummy_status" + +let get_outbox _level _state = Lwt.return [] + +(* It is safe to pass the [is_reveal_enabled_predicate]: + [eval_many] always stops at the beginning of a new Tezos block, + so no execution of several Tezos block inboxes is possible. *) +(* Copied from [arith_pvm.ml]. *) +let eval_many ~reveal_builtins:_ ~write_debug:_ ~is_reveal_enabled + ?stop_at_snapshot ~max_steps initial_state = + ignore stop_at_snapshot ; + ignore max_steps ; + ignore is_reveal_enabled ; + Lwt.return (initial_state, 0L) + +let new_dissection = Game_helpers.default_new_dissection + +module State = Context.PVMState + +module Inspect_durable_state = struct + let lookup _state _keys = + raise (Invalid_argument "No durable storage for riscv PVM") +end + +module Unsafe_patches = struct + (** No unsafe patches for the riscv PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . +end diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/rollup_node_plugin.ml new file mode 100644 index 000000000000..07f675c950ad --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/rollup_node_plugin.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Plugin : Protocol_plugin_sig.S = struct + let protocol = Protocol.hash + + module RPC_directory = RPC_directory + module Dal_slots_tracker = Dal_slots_tracker + module Inbox = Inbox + module Refutation_game_helpers = Refutation_game_helpers + module Batcher_constants = Batcher_constants + module Layer1_helpers = Layer1_helpers + module L1_processing = Daemon_helpers + module Pvm = Pvm_plugin +end + +let () = Protocol_plugins.register (module Plugin) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.ml new file mode 100644 index 000000000000..6fb74e1753ba --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.ml @@ -0,0 +1,466 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context +open Injector_common +open Injector_sigs +module Block_cache = + Aches_lwt.Lache.Make_result + (Aches.Rache.Transfer (Aches.Rache.LRU) (Block_hash)) + +let injector_operation_to_manager : + L1_operation.t -> Protocol.Alpha_context.packed_manager_operation = function + | Add_messages {messages} -> Manager (Sc_rollup_add_messages {messages}) + | Cement {rollup; commitment = _} -> + let rollup = Sc_rollup_proto_types.Address.of_octez rollup in + Manager (Sc_rollup_cement {rollup}) + | Publish {rollup; commitment} -> + let rollup = Sc_rollup_proto_types.Address.of_octez rollup in + let commitment = Sc_rollup_proto_types.Commitment.of_octez commitment in + Manager (Sc_rollup_publish {rollup; commitment}) + | Refute {rollup; opponent; refutation} -> + let rollup = Sc_rollup_proto_types.Address.of_octez rollup in + let refutation = + Sc_rollup_proto_types.Game.refutation_of_octez refutation + in + Manager (Sc_rollup_refute {rollup; opponent; refutation}) + | Timeout {rollup; stakers} -> + let rollup = Sc_rollup_proto_types.Address.of_octez rollup in + let stakers = Sc_rollup_proto_types.Game.index_of_octez stakers in + Manager (Sc_rollup_timeout {rollup; stakers}) + | Recover_bond {rollup; staker} -> + let rollup = Sc_rollup_proto_types.Address.of_octez rollup in + Manager (Sc_rollup_recover_bond {sc_rollup = rollup; staker}) + | Execute_outbox_message {rollup; cemented_commitment; output_proof} -> + let rollup = Sc_rollup_proto_types.Address.of_octez rollup in + let cemented_commitment = + Sc_rollup_proto_types.Commitment_hash.of_octez cemented_commitment + in + Manager + (Sc_rollup_execute_outbox_message + {rollup; cemented_commitment; output_proof}) + +let injector_operation_of_manager : + type kind. + kind Protocol.Alpha_context.manager_operation -> L1_operation.t option = + function + | Sc_rollup_add_messages {messages} -> Some (Add_messages {messages}) + | Sc_rollup_cement {rollup} -> + let rollup = Sc_rollup_proto_types.Address.to_octez rollup in + let commitment = Octez_smart_rollup.Commitment.Hash.zero in + (* Just for printing *) + Some (Cement {rollup; commitment}) + | Sc_rollup_publish {rollup; commitment} -> + let rollup = Sc_rollup_proto_types.Address.to_octez rollup in + let commitment = Sc_rollup_proto_types.Commitment.to_octez commitment in + Some (Publish {rollup; commitment}) + | Sc_rollup_refute {rollup; opponent; refutation} -> + let rollup = Sc_rollup_proto_types.Address.to_octez rollup in + let refutation = + Sc_rollup_proto_types.Game.refutation_to_octez refutation + in + Some (Refute {rollup; opponent; refutation}) + | Sc_rollup_timeout {rollup; stakers} -> + let rollup = Sc_rollup_proto_types.Address.to_octez rollup in + let stakers = Sc_rollup_proto_types.Game.index_to_octez stakers in + Some (Timeout {rollup; stakers}) + | Sc_rollup_execute_outbox_message {rollup; cemented_commitment; output_proof} + -> + let rollup = Sc_rollup_proto_types.Address.to_octez rollup in + let cemented_commitment = + Sc_rollup_proto_types.Commitment_hash.to_octez cemented_commitment + in + Some (Execute_outbox_message {rollup; cemented_commitment; output_proof}) + | _ -> None + +module Proto_client = struct + open Protocol_client_context + + type operation = L1_operation.t + + type state = Injector.state + + type unsigned_operation = + Tezos_base.Operation.shell_header * packed_contents_list + + let max_operation_data_length = Constants.max_operation_data_length + + let manager_pass = Operation_repr.manager_pass + + let manager_operation_size (Manager operation) = + let contents = + Manager_operation + { + source = Signature.Public_key_hash.zero; + operation; + fee = Tez.zero; + counter = Manager_counter.Internal_for_tests.of_int 0; + gas_limit = Gas.Arith.zero; + storage_limit = Z.zero; + } + in + Data_encoding.Binary.length Operation.contents_encoding (Contents contents) + + let operation_size op = + manager_operation_size (injector_operation_to_manager op) + + (* The operation size overhead is an upper bound (in practice) of the overhead + that will be added to a manager operation. To compute it we can use any + manager operation (here a revelation), add an overhead with upper bounds as + values (for the fees, limits, counters, etc.) and compare the encoded + operations with respect to their size. + NOTE: This information is only used to pre-select operations from the + injector queue as a candidate batch. *) + let operation_size_overhead = + let dummy_operation = + Reveal + (Signature.Public_key.of_b58check_exn + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") + in + let dummy_contents = + Manager_operation + { + source = Signature.Public_key_hash.zero; + operation = dummy_operation; + fee = Tez.of_mutez_exn 3_000_000L; + counter = Manager_counter.Internal_for_tests.of_int 500_000; + gas_limit = Gas.Arith.integral_of_int_exn 500_000; + storage_limit = Z.of_int 500_000; + } + in + let dummy_size = + Data_encoding.Binary.length + Operation.contents_encoding + (Contents dummy_contents) + in + dummy_size - manager_operation_size (Manager dummy_operation) + + let manager_operation_result_status (type kind) + (op_result : kind Apply_results.manager_operation_result) : + operation_status = + match op_result with + | Applied _ -> Successful + | Backtracked (_, None) -> Unsuccessful Backtracked + | Skipped _ -> Unsuccessful Skipped + | Backtracked (_, Some err) + (* Backtracked because internal operation failed *) + | Failed (_, err) -> + Unsuccessful (Failed (Environment.wrap_tztrace err)) + + let operation_result_status (type kind) + (op_result : kind Apply_results.contents_result) : operation_status = + match op_result with + | Preattestation_result _ -> Successful + | Attestation_result _ -> Successful + | Seed_nonce_revelation_result _ -> Successful + | Vdf_revelation_result _ -> Successful + | Double_attestation_evidence_result _ -> Successful + | Double_preattestation_evidence_result _ -> Successful + | Double_baking_evidence_result _ -> Successful + | Activate_account_result _ -> Successful + | Proposals_result -> Successful + | Ballot_result -> Successful + | Drain_delegate_result _ -> Successful + | Manager_operation_result {operation_result; _} -> + manager_operation_result_status operation_result + + let operation_contents_status (type kind) + (contents : kind Apply_results.contents_result_list) ~index : + operation_status tzresult = + let rec rec_status : + type kind. int -> kind Apply_results.contents_result_list -> _ = + fun n -> function + | Apply_results.Single_result _ when n <> 0 -> + error_with "No operation with index %d" index + | Single_result result -> Ok (operation_result_status result) + | Cons_result (result, _rest) when n = 0 -> + Ok (operation_result_status result) + | Cons_result (_result, rest) -> rec_status (n - 1) rest + in + rec_status index contents + + let operation_status_of_receipt (operation : Protocol.operation_receipt) + ~index : operation_status tzresult = + match (operation : _) with + | No_operation_metadata -> + error_with "Cannot find operation status because metadata is missing" + | Operation_metadata {contents} -> operation_contents_status contents ~index + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6339 *) + (* Don't make multiple calls to [operations_in_pass] RPC *) + let get_block_operations = + let ops_cache = Block_cache.create 32 in + fun cctxt block_hash -> + Block_cache.bind_or_put + ops_cache + block_hash + (fun block_hash -> + let open Lwt_result_syntax in + let+ operations = + Alpha_block_services.Operations.operations_in_pass + cctxt + ~chain:cctxt#chain + ~block:(`Hash (block_hash, 0)) + ~metadata:`Always + manager_pass + in + List.fold_left + (fun acc (op : Alpha_block_services.operation) -> + Operation_hash.Map.add op.hash op acc) + Operation_hash.Map.empty + operations) + Lwt.return + + let operation_status {Injector.cctxt; _} block_hash operation_hash ~index = + let open Lwt_result_syntax in + let* operations = get_block_operations cctxt block_hash in + match Operation_hash.Map.find_opt operation_hash operations with + | None -> return_none + | Some operation -> ( + match operation.receipt with + | Empty -> + failwith "Cannot find operation status because metadata is empty" + | Too_large -> + failwith + "Cannot find operation status because metadata is too large" + | Receipt receipt -> + let*? status = operation_status_of_receipt receipt ~index in + return_some status) + + let dummy_sk_uri = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Tezos_signer_backends.Unencrypted.make_sk + @@ Signature.Secret_key.of_b58check_exn + "edsk3UqeiQWXX7NFEY1wUs6J1t2ez5aQ3hEWdqX5Jr5edZiGLW8nZr" + + let simulate_operations cctxt ~force ~source ~src_pk ~successor_level + ~fee_parameter ?safety_guard operations = + let open Lwt_result_syntax in + let fee_parameter : Injection.fee_parameter = + { + minimal_fees = Tez.of_mutez_exn fee_parameter.minimal_fees.mutez; + minimal_nanotez_per_byte = fee_parameter.minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit = + fee_parameter.minimal_nanotez_per_gas_unit; + force_low_fee = fee_parameter.force_low_fee; + fee_cap = Tez.of_mutez_exn fee_parameter.fee_cap.mutez; + burn_cap = Tez.of_mutez_exn fee_parameter.burn_cap.mutez; + } + in + let open Annotated_manager_operation in + let annotated_operations = + List.map + (fun operation -> + let (Manager operation) = injector_operation_to_manager operation in + Annotated_manager_operation + (Injection.prepare_manager_operation + ~fee:Limit.unknown + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + operation)) + operations + in + let (Manager_list annot_op) = + Annotated_manager_operation.manager_of_list annotated_operations + in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let safety_guard = Option.map Gas.Arith.integral_of_int_exn safety_guard in + let*! simulation_result = + Injection.inject_manager_operation + cctxt + ~simulation:true (* Only simulation here *) + ~force + ~chain:cctxt#chain + ~block:(`Head 0) + ~source + ~src_pk + ~src_sk:dummy_sk_uri + (* Use dummy secret key as it is not used by simulation *) + ~successor_level + ~fee:Limit.unknown + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ?safety_guard + ~fee_parameter + annot_op + in + match simulation_result with + | Error trace -> + let exceeds_quota = + TzTrace.fold + (fun exceeds -> function + | Environment.Ecoproto_error + (Gas.Block_quota_exceeded | Gas.Operation_quota_exceeded) -> + true + | _ -> exceeds) + false + trace + in + fail (if exceeds_quota then `Exceeds_quotas trace else `TzError trace) + | Ok (_oph, packed_op, _contents, results) -> + let nb_ops = List.length operations in + let results = Apply_results.to_list (Contents_result_list results) in + (* packed_op can have reveal operations added automatically. *) + let start_index = List.length results - nb_ops in + (* remove extra reveal operations *) + let operations_statuses = + List.fold_left_i + (fun index_in_batch acc (Apply_results.Contents_result result) -> + if index_in_batch < start_index then acc + else + {index_in_batch; status = operation_result_status result} :: acc) + [] + results + |> List.rev + in + let unsigned_operation = + let {shell; protocol_data = Operation_data {contents; signature = _}} + = + packed_op + in + (shell, Contents_list contents) + in + return {operations_statuses; unsigned_operation} + + let sign_operation cctxt src_sk + ((shell, Contents_list contents) as unsigned_op) = + let open Lwt_result_syntax in + let unsigned_bytes = + Data_encoding.Binary.to_bytes_exn Operation.unsigned_encoding unsigned_op + in + let cctxt = + new Protocol_client_context.wrap_full (cctxt :> Client_context.full) + in + let+ signature = + Client_keys.sign + cctxt + ~watermark:Signature.Generic_operation + src_sk + unsigned_bytes + in + let op : packed_operation = + { + shell; + protocol_data = Operation_data {contents; signature = Some signature}; + } + in + Data_encoding.Binary.to_bytes_exn Operation.encoding op + + let time_until_next_block + {Injector.minimal_block_delay; delay_increment_per_round; _} + (header : Tezos_base.Block_header.shell_header option) = + let open Result_syntax in + match header with + | None -> minimal_block_delay |> Int64.to_int |> Ptime.Span.of_int_s + | Some header -> + let minimal_block_delay = Period.of_seconds_exn minimal_block_delay in + let delay_increment_per_round = + Period.of_seconds_exn delay_increment_per_round + in + let next_level_timestamp = + let* durations = + Round.Durations.create + ~first_round_duration:minimal_block_delay + ~delay_increment_per_round + in + let* predecessor_round = Fitness.round_from_raw header.fitness in + Round.timestamp_of_round + durations + ~predecessor_timestamp:header.timestamp + ~predecessor_round + ~round:Round.zero + in + let next_level_timestamp = + Result.value + next_level_timestamp + ~default: + (WithExceptions.Result.get_ok + ~loc:__LOC__ + Timestamp.(header.timestamp +? minimal_block_delay)) + in + Ptime.diff + (Time.System.of_protocol_exn next_level_timestamp) + (Time.System.now ()) + + let check_fee_parameters Injector.{fee_parameters; _} = + let check_value operation_kind name compare to_string mempool_default value + = + if compare mempool_default value > 0 then + error_with + "Bad configuration fee_parameter.%s for %s. It must be at least %s \ + for operations of the injector to be propagated." + name + (Operation_kind.to_string operation_kind) + (to_string mempool_default) + else Ok () + in + let check purpose + { + minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee = _; + fee_cap = _; + burn_cap = _; + } = + let open Result_syntax in + let+ () = + check_value + purpose + "minimal_fees" + Int64.compare + Int64.to_string + (Protocol.Alpha_context.Tez.to_mutez + Plugin.Mempool.default_minimal_fees) + minimal_fees.mutez + and+ () = + check_value + purpose + "minimal_nanotez_per_byte" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_byte + minimal_nanotez_per_byte + and+ () = + check_value + purpose + "minimal_nanotez_per_gas_unit" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_gas_unit + minimal_nanotez_per_gas_unit + in + () + in + Operation_kind.Map.iter_e check fee_parameters + + let checks state = check_fee_parameters state +end + +let () = Injector.register_proto_client Protocol.hash (module Proto_client) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.mli new file mode 100644 index 000000000000..ca4112313ef6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_injector.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Manager operation for a given L1 operation. *) +val injector_operation_to_manager : + L1_operation.t -> Protocol.Alpha_context.packed_manager_operation + +(** L1 operation corresponding to a manager operation if any. *) +val injector_operation_of_manager : + 'a Protocol.Alpha_context.manager_operation -> L1_operation.t option diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_node_errors.ml new file mode 100644 index 000000000000..bf57c29eda9b --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -0,0 +1,33 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +include Rollup_node_errors + +(** Registering protocol specific errors *) + +let make_id id = String.concat "." [Protocol.name; id] + +let register_error_kind ~id = register_error_kind ~id:(make_id id) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune b/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune new file mode 100644 index 000000000000..c2210cafe793 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune @@ -0,0 +1,47 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name src_proto_019_PtParisB_lib_sc_rollup_node_test_tezt_lib) + (instrumentation (backend bisect_ppx)) + (libraries + tezt.core + octez-libs.base + tezos-protocol-019-PtParisB.protocol + octez-libs.test-helpers + octez-protocol-019-PtParisB-libs.smart-rollup-layer2 + octez_smart_rollup_node_PtParisB + octez-alcotezt) + (library_flags (:standard -linkall)) + (flags + (:standard) + -open Tezt_core + -open Tezt_core.Base + -open Tezos_base.TzPervasives + -open Tezos_protocol_019_PtParisB + -open Tezos_test_helpers + -open Tezos_smart_rollup_layer2_019_PtParisB + -open Octez_smart_rollup_node_PtParisB + -open Octez_alcotezt) + (modules serialized_proofs test_octez_conversions)) + +(executable + (name main) + (instrumentation (backend bisect_ppx --bisect-sigterm)) + (libraries + src_proto_019_PtParisB_lib_sc_rollup_node_test_tezt_lib + tezt) + (link_flags + (:standard) + (:include %{workspace_root}/macos-link-flags.sexp)) + (modules main)) + +(rule + (alias runtest) + (package tezos-sc-rollup-node-test) + (enabled_if (<> false %{env:RUNTEZTALIAS=true})) + (action (run %{dep:./main.exe}))) + +(rule + (targets main.ml) + (action (with-stdout-to %{targets} (echo "let () = Tezt.Test.run ()")))) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.ml new file mode 100644 index 000000000000..8ca3226daeb1 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.ml @@ -0,0 +1,121 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let proofs : string list ref = ref [] + +(* Each serialized proof is added to the list with a side effect, so that it is + easy to generate (or augment) this file by instrumenting the rollup node. *) + +let () = + proofs := + "0000007b030002db10db4d3b595f59e0b53740f164bf951bcfae9e0873fd23fbce82fac4f404e1126f1b6c5546a5aeff4f59893ab63211a80e6f88e11b67339186109bf569d74a820b626f6f745f736563746f72c8baff5f78423676a25d9cd27a412dd932327b9b3e1cc26e754a36410a5efbf7b406737461747573c0010000" + :: !proofs + +let () = + proofs := + "000001e2030002dff7b99fc09bd426898107f2a430633c61dde3863a0e29a795826f064d838b4a344b4f2d13d32e6bf10caf9a59ed667666d644bff87fb5ce85243fe46a62d0d400110007c094fb4ab02d1eaeebb21ddb7da4996ab4663db3e1d7b227f2c501aa13ced50e300004c003c40612363f2296a21ab5f72bd8106d16f1189d2512533c14fe023fe2a9505b8204636f6465d04e8c2629e50b60cab76e6c91232e771d142ebcb0467889de40e2a27c168a5591086d65746164617461c01901073e4cb15d82dc12ed63e0f86679a085a8bb3d9400000002000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc00176820b626f6f745f736563746f72c8baff5f78423676a25d9cd27a412dd932327b9b3e1cc26e754a36410a5efbf7b418696e7465726e616c5f6d6573736167655f636f756e746572c00106810d63757272656e745f6c6576656cc0040000000400050003810f6d6573736167655f636f756e746572c00201078206737461747573c001010476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765edc04203ac25917e1d6ded20b0a57bab57da15ba6edfaa63b5c885c2c9985ddc2265ff0000000004070000027b0000020d11e1cf8d8d6637edc27e04a3b6861fbc06336c950314d2f0be3a19bebdd873f47400000012000000607e9df5467aa1c14b8482c20a3e29168879697801892fbb1e896a89904ec1705fc999d259dc5ef030f190d45cfd7e4e503b2b2cad3bbd87b7f481dedbb3bf077fc999d259dc5ef030f190d45cfd7e4e503b2b2cad3bbd87b7f481dedbb3bf077f0f868a1d495f0e46265daaf4edfcc451fdd0e4d178c96807f775b68686e4b6c3ad0000001000000040c8e206c6092f3b50cef178a5ca373722684bf1d4bc4e6a3cf6f18ec8977c4f9ff7f922f475e8ee6eec9078395a379a2a1b905caefc92c75e9d474b8ff7f421440b0bd6c62766cfb2a314d827cead108848c389a9f7d824f5b6baa6920d74757b590000000c0000004020911b9f0a604aa0a669c82cca6015a73e06da67790efc1622e905d3cc7deb0441be5bf60ef04d6806f946483d16974c847e13696b97a5c57679e77bb43ebd520750eb5f108b13387d9bf493d38655d4e49e92958b296b50e11c91ecc37338f0240000000800000040f624258bca6f66863aa5dc00d781a68d01617a4e57c7eeb571586cfd5d4fa42feceb7013cb9a3709f1fabd85eeb1d29f94f01fae86ea1bd48b96d9dc5f2c6e06037aea153e62097eb669959c79ba91e715db84e411ffffee26ee17415e14f9adaf000000040000002033a66cd216417b22be5ff5b40a2884efd21b41ba30710151c8c8b631f78d872900000065078f1f9fd0816a310a79d0e0c4bf605a544c260c561740bcdeb175ea46f5312890000000406aa2f7281c84f94013408e9be51c00f0c269a9e0168bc4e1487f8bd158712b2a0223eb4ac4e1f8d91f67b451f8368483543437958eb47c656650b141eff001d300" + :: !proofs + +let () = + proofs := + "000001e2030002dff7b99fc09bd426898107f2a430633c61dde3863a0e29a795826f064d838b4a344b4f2d13d32e6bf10caf9a59ed667666d644bff87fb5ce85243fe46a62d0d400110007c094fb4ab02d1eaeebb21ddb7da4996ab4663db3e1d7b227f2c501aa13ced50e300004c003c40612363f2296a21ab5f72bd8106d16f1189d2512533c14fe023fe2a9505b8204636f6465d04e8c2629e50b60cab76e6c91232e771d142ebcb0467889de40e2a27c168a5591086d65746164617461c01901073e4cb15d82dc12ed63e0f86679a085a8bb3d9400000002000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc00176820b626f6f745f736563746f72c8baff5f78423676a25d9cd27a412dd932327b9b3e1cc26e754a36410a5efbf7b418696e7465726e616c5f6d6573736167655f636f756e746572c00106810d63757272656e745f6c6576656cc0040000000400050003810f6d6573736167655f636f756e746572c00201078206737461747573c001010476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765edc04203ac25917e1d6ded20b0a57bab57da15ba6edfaa63b5c885c2c9985ddc2265ff0000000004070000027b0000020d118c4447d72cefb932b0ca79afe7e83680a3f5f940af12e510130890de093704e600000012000000608dfebf6bc80d3a6576db8bc05fdca115f1792bc708889f6c1e426a8fba62e41aec379b342e355104630c030f9fcdb2b45c8c1095ab4009aca365bceadabdcfb3ec379b342e355104630c030f9fcdb2b45c8c1095ab4009aca365bceadabdcfb30fbb838b70dafcb73c9fa937401a6b33dd4da8bfb1cc13518986029bd37814e280000000100000004069ef7e20a1f91d679504ab5a48899eec79e079a45f91939f0221a7a508358ef290e46fb7603c1723c2f698460a79f1e9642c1169fa2958961a87a74b9ff9e6430b480a065cd7198a5dc043acedef20e46dc7920c8592cca659cd961f5ea1dd90f00000000c000000406d802c5daf40c7215b73280efba85f67f0cc5747fcd2a0fe2328b5fdc252fd646920e1ffdb78b41f97546e80ad8a7287a1ba422057cad6f65c86c62a472aacfd0787e2b620f5c09d654e85e713d546450d660fc4988c658ddd3914d4bfc699d5cf000000080000004081b3c6ca730810be90b2f5ae9c4886e511f31933be84c0ac30af3b49b61fcdbfca6edbc188119ab8cf16b9e116af5f5a1de725fbaff2804f2508262b8d5dbc5a0347b79ca5ad4b09f9d7e9ead9854c082b664e51fba5558f2830fde4a5762367410000000400000020a17b14300c882553060d2694e5189fb3d86a998504248a47f4d359a29d2d6d6d00000065078f1f9fd0816a310a79d0e0c4bf605a544c260c561740bcdeb175ea46f53128900000004086f216dfb0131becbcc6a7a7e901db744c5030d09830fa3bbd5d0690eb5e2ec36877e8620a9491faa4d1a7c14b9fa50c394d69f699d239c1dce145d86566b49c00" + :: !proofs + +let () = + proofs := + "000001e2030002d83a6fcbfa317ba868d42fae27ddce20ad903cbb357a1b16823a14bce0631d733bdcad893d1ec690f5e7f44b73cc9e7a9119eda7942d6776b70b02b8276cdfcb00110007c0f16246649211503c309f0679ac228a4c510e90cf699d0dd1c71123465e3b1f340004c003c40612363f2296a21ab5f72bd8106d16f1189d2512533c14fe023fe2a9505b8204636f6465d04e8c2629e50b60cab76e6c91232e771d142ebcb0467889de40e2a27c168a5591086d65746164617461c01901073e4cb15d82dc12ed63e0f86679a085a8bb3d9400000002000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc00179820b626f6f745f736563746f72c8baff5f78423676a25d9cd27a412dd932327b9b3e1cc26e754a36410a5efbf7b418696e7465726e616c5f6d6573736167655f636f756e746572c00109810d63757272656e745f6c6576656cc0040000000500050003810f6d6573736167655f636f756e746572c00201078206737461747573c001010476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765edc04203ac25917e1d6ded20b0a57bab57da15ba6edfaa63b5c885c2c9985ddc2265ff0000000005070000036d000002ff11fc6cf0426308d2bffb18bf2b478124887feabcb245cd6b0b9e129588192a54c40000001200000060b12f07c7d9af455f96ddc30c0006cae6a47d4012a1d9ee52381a6ac466b90282a6d0f8cd48d167078b8277d8ea52a7a2b289c1cd57253953d8152987bf527508a6d0f8cd48d167078b8277d8ea52a7a2b289c1cd57253953d8152987bf5275080f064a0994f5eb055ea8e9611989f2af420bbfd91b1114f92f2bc12fe6b7a0cf0e00000010000000406036dc7a4a6e3dd4d7c53e1d31f3ca11949539681aef75c98a1a6e99e5c8023389e71f2788c0928cf48c78e78f4262386d05c26b7afd22a9e8b825bb2641d8140b687657f959d8f4d09d4a5d0dc02a92fad1d4c0c1834cfa52de824c68b71e82220000000c0000004099e839e62f772ca0b40026794b9e375dc254545aa597b3ac92f5769b64be931b59946ddfb2e26dd43fb1b183e13a0676055bdc96c9afec634562f967c16b17a3078d3709187faab160b53420e44f31bf89247940d19c42e0ffb8f741c31eedf49f0000000800000040d02e518af31bb716c6c2b217d488f919a9c358985585a9bc36764e49b1a06d83787ada119155f533cfd8ae0dcf26eee797ad414c4a9cfd77e5bfb25ad9db49180646d0cfe6a53bd991515525f0b69234f6bd255e13f2268b0e7056cc9749fe96a80000000700000040641a59b4d74772af88bd26b01930fdc833e4da32a6a8b134a83eefd5a891c67f787ada119155f533cfd8ae0dcf26eee797ad414c4a9cfd77e5bfb25ad9db491805e3292cfbce3f99c456c357448caf12dbb8d94ae727713e76204070ee7f93ec6f000000060000004025cc6a901f1677467a5effacdbea5918e4fe1db847ca23aa2d32a6009f4e49c3787ada119155f533cfd8ae0dcf26eee797ad414c4a9cfd77e5bfb25ad9db491804440a917893d879e6d120791d6f3686ef0e138f1aafa4218b9f2986f3e6fa83c20000000500000040787ada119155f533cfd8ae0dcf26eee797ad414c4a9cfd77e5bfb25ad9db4918787ada119155f533cfd8ae0dcf26eee797ad414c4a9cfd77e5bfb25ad9db491800000065078f1f9fd0816a310a79d0e0c4bf605a544c260c561740bcdeb175ea46f531289000000040d5177419909a1fbbf44e4d765d6fb055eade688bab86c66f22464dc90d9646a9136cb726c83432b2cf178eb3b1a1c32245d8b30adcc01468dfdd84665824dbb900" + :: !proofs + +let () = + proofs := + "000001e3030002dcfa6603288699daee959046196b807c6802422775a28aefa8955743b22be772b65ed549e8fc86fd1b0e4bfc2fe2e3562fa78bca93b48a46450d259daead220400110007c001fdc52ab8835ab29356f398abd306ece6190f2832649449a075fa02873be7870004c073b11921186a3ad9f169f3ce0b2f80b767ad931ff6e7828e8992ba73b3e72b918204636f6465d04e8c2629e50b60cab76e6c91232e771d142ebcb0467889de40e2a27c168a5591086d65746164617461c01901073e4cb15d82dc12ed63e0f86679a085a8bb3d9400000002000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc002b901820b626f6f745f736563746f72c8baff5f78423676a25d9cd27a412dd932327b9b3e1cc26e754a36410a5efbf7b418696e7465726e616c5f6d6573736167655f636f756e746572c00112810d63757272656e745f6c6576656cc0040000000800050003810f6d6573736167655f636f756e746572c00201078206737461747573c001010476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765edc04203ac25917e1d6ded20b0a57bab57da15ba6edfaa63b5c885c2c9985ddc2265ff00000000080700000232000001c411de172a5abce9a9a316b4d55bddb1f6208bd58546a42224aae7afe87e75103fbe00000012000000600babc274ae5da75f613af0b96c064841dc055fb086c7aee7c5cf59afc7a3c5eadda87e4df1828b9f40e4b3ddcb69903f1eceed5b45f796d5793a2406fc77a1e8dda87e4df1828b9f40e4b3ddcb69903f1eceed5b45f796d5793a2406fc77a1e80f96b234fd8fb7e2b70e9a773d91932d11a8cd2f58c5cff42f7756b4ae5982d2b00000001000000040a21c42cf974f22f9eeddc1cca859cee5e7e74a1d98571b4a48e78a70c867d1e99ae8cd149c8d4389f819cd04167e27b5339537f99a0ec1821b6fff92a92659130b29a8d6c8b6b112bb72dd52f8d68224a240340ebc707053997e1d140cc1625b090000000c00000040b982ce951ef7e4ddca7c1b9371d3dfc7840c1a5b661cdf28d0a727d3a34055fc2ddf903372525d24bca2cb46409f65960a1bb7dec7d4d3cf6107e6bed52c5a62079e4bad092eecab56a6945c7223ec0c7622d91724b7a26106b9bf3efbb0285e960000000800000040803d9fb1c0a3d81cc4806db2b519321bc7873a5e44dcc10f5948b47fc05ff827b0a464db5c39fe5809e2509465b36c17e24c18458175551c746256f129c6882000000065078f1f9fd0816a310a79d0e0c4bf605a544c260c561740bcdeb175ea46f5312890000000402f0b8c5524863a7d8b851a05f51888de954fd75bdb39638fba73bee6cd9f848238b7acf195d72a42ce6594d54911c2d544f581288c71502550916a1a32088f4100" + :: !proofs + +let () = + proofs := + "00000214030002e077bef17af38499b44807fabde3837e2355f4988146b065236bac172087929e24bc4324adefe61ff70a912adfce146400586b408d46b371c287b5df9fcdba4000100006d0030170000382066f7574707574d033ba419fa9cc8b769d0a76f2839bdaee68f7e12566131d1edbebaaa1e12169900c7061727365725f7374617465c00102c0fca618d8cfb53c29e8b61bcf584028571b6b1f563e164df093810f07a93265060003820c6e6578745f6d657373616765c0060100000001310e6f75747075745f636f756e746572c00102c0322d95cbadd30a23603872646abd7b0d341c5f3eca8f39da9da74bd3264d9775000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc00179c03b85b8bcac7168100efeb43114a4679d17808ab9309d16a22be916283fbde863c0d22ceeb53dad5d5a36f1caca13fb2cce988bed6679f7370d0d2e5aa042c6556c00050003c0cb0d5024ea71731c4142bd8b8ce738c9d44298b45ccc3d4fc2717db8d4eb78068206737461747573c001040476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765ed820c6c657865725f627566666572c00800000000000000000e70617273696e675f726573756c74c87a31b1c8e3af61756b336bcfc3b0c292c89b40cc8a5080ba99c45463d110ce8b00" + :: !proofs + +let () = + proofs := + "000002a7030002d918c66aa95d5080874df90faea75962fc4a4443996f8a6be3996739f9a2008804940e7d9453c3a83f99858741988f1b5056f21295ae698df95731c1ca00d70a00110007d0030170000382066f7574707574d0772e6802b1bb0a8f0553b122347b071e426307db4a54ca247a479f51d20c91170c7061727365725f7374617465c00101c0bf2d23e703638502856d46d16407070d7c47a5af5f5e33daa4d46a2d311eba870004820c6e6578745f6d657373616765c8794bebd4366203e527989fc7421c01bfc2976975f118a341ac007b5e0f53a1180e6f75747075745f636f756e746572c88a7ae305885619a2566d1c7fd87e3d67444fb5ce517a8fca5bee68a4061997ed8204636f6465d04e8c2629e50b60cab76e6c91232e771d142ebcb0467889de40e2a27c168a5591086d65746164617461c81bd59bb6258d782bad96d2164548403ee6b50359b81a885f3e11b988dfafe3ae000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc002ec01820b626f6f745f736563746f72c0040000000018696e7465726e616c5f6d6573736167655f636f756e746572c896f1f45bb65c0c32557f9a65d161156b248f2a1e62e1678892300949bd0589a2810d63757272656e745f6c6576656cc0040000000700050003810f6d6573736167655f636f756e746572c00201018206737461747573c001010476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765ed820c6c657865725f627566666572c8a8b484dd0c8b746c1a15618f6fb51a7b37f8c275afc6499d9c524fa0fbb743cc0e70617273696e675f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905ff0000000007010000032b0000022d112216fa511da8cf0ef50a29f5990dc65135aa9a72d1a686b2f1aba0bbdc1710f100000012000000608e03cd7fd0e4aafdb620093525a182431bc198b0ef56218f6e4d1253787df95c4f152285b05c88d8cbd414385df68dc0038a0949a6a2150a5835b64f620225404f152285b05c88d8cbd414385df68dc0038a0949a6a2150a5835b64f620225400f7c5d2e20abd394499b89ff0f01f8ca785cd4b83ac033a2b72bf6fc3ff6f72b76000000100000004030548b2d65eed411aab93a1050898da8b6560560efdeb6f5352ce25edf8990a1033e7e19ba33f12cc42a917f19767d2b0e9517855f905ce9f9b03edc4716511a0be7bc438063c29553e43fc7e0ad8672f2e47bac5622849003df6b29b11a01d4250000000c0000004003ad25557b67a5b5b0d5f484d69b5639d49290e57edbbcfab845a44c6d3caccaccc0ac98c43158ffc5dc55d3370c6a0d95e6f282b3f5c6c9bf924803f603636207797fef9633643ebdee8710d2481f2fe58af4201ef62570c79c1370f48108b5940000000800000040b69cf6e3364934b1d8e2f45152c899f1f787713d362b2d0962e5d2ed603b56f1722208556ce9c4cdffc91825b29d757bd81ef39b074b03b0afb5f9dd6f5601ee06c14c15749c2323c5571de585825120b0fcd8eaeffdbb3f38908581308d0312170000000700000040eabbe433d155ea8739a38e9c24bcfc7e23f4f3d69bdc9bdcb75ed722a605aa8a722208556ce9c4cdffc91825b29d757bd81ef39b074b03b0afb5f9dd6f5601ee000000ef078f1f9fd0816a310a79d0e0c4bf605a544c260c561740bcdeb175ea46f5312890000000401fb49ce2d7b7e3be61d2b4ca1774aa4740a1e1d12413f4a2a7597a9374645d422c20099c6029bbaa5a7cdeec1e3ddddbc5e4630af0ba11554535f657c27e38de035efc3165465aff68d3e5bd549d711f9e0e06e786bc1d6873f2e7e4faa43bbe130000002030cc84dad07aa536dbaaaccba95d4dabd7c5d6c6ca411372ca9326afeae3eed30228a91be1e75d0b3a4f6634ffbe25947d0bd042d41d1ab2f2a2a7d81b564312c000000020b384576e8dfeacafe447c7555442ed6057ec637adc6d72a1863b5e6a8094adf8ff000000020131" + :: !proofs + +let () = + proofs := + "0000021503000204940e7d9453c3a83f99858741988f1b5056f21295ae698df95731c1ca00d70aeb9288624e864a8aeecbb882b30fa04c28830cd6331d1697fd6d78570a47f43e00100006d0030170000382066f7574707574d0772e6802b1bb0a8f0553b122347b071e426307db4a54ca247a479f51d20c91170c7061727365725f7374617465c00102c0bf2d23e703638502856d46d16407070d7c47a5af5f5e33daa4d46a2d311eba870003820c6e6578745f6d657373616765c0060100000001310e6f75747075745f636f756e746572c00104c0322d95cbadd30a23603872646abd7b0d341c5f3eca8f39da9da74bd3264d9775000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc002ed01c052c196fbe4546e163fd1d777dfb388cece157a88fe10cc0e1ae48aa053fac3fec0e0590ca6ea22f7dabe3889c02d87873535203b5a450ef9e5ce102d2f99d8c0b800050003c0cb0d5024ea71731c4142bd8b8ce738c9d44298b45ccc3d4fc2717db8d4eb78068206737461747573c001040476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765ed820c6c657865725f627566666572c00800000000000000000e70617273696e675f726573756c74c87a31b1c8e3af61756b336bcfc3b0c292c89b40cc8a5080ba99c45463d110ce8b00" + :: !proofs + +let () = + proofs := + "00000215030002f677d054c8e623d1b22ecc8aea74f5074bf0c9529f898cac90db26a3992831d77b74a66258cc09c792da869b9b3bc683e35d9583c4206adc20d3b0296245408a00100006d0030170000382066f7574707574d0d5983c50395ec6533657eccf10ccf8d9c4062ff6501c2074868953ffee9073830c7061727365725f7374617465c00102c0bf2d23e703638502856d46d16407070d7c47a5af5f5e33daa4d46a2d311eba870003820c6e6578745f6d657373616765c0060100000001310e6f75747075745f636f756e746572c00104c0322d95cbadd30a23603872646abd7b0d341c5f3eca8f39da9da74bd3264d9775000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc002f301c01c1fab5de0181afb420733a2d6b0a12ce0b70c494b7dfccff1e2447eee86380fc04607fa9b3ac608330ef58339fb3dc505880bae0b9fae4f3f10ff9f8534a3856a00050003c0cb0d5024ea71731c4142bd8b8ce738c9d44298b45ccc3d4fc2717db8d4eb78068206737461747573c001040476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765ed820c6c657865725f627566666572c00800000000000000000e70617273696e675f726573756c74c87a31b1c8e3af61756b336bcfc3b0c292c89b40cc8a5080ba99c45463d110ce8b00" + :: !proofs + +let () = + proofs := + "00000214030002e077bef17af38499b44807fabde3837e2355f4988146b065236bac172087929e24bc4324adefe61ff70a912adfce146400586b408d46b371c287b5df9fcdba4000100006d0030170000382066f7574707574d033ba419fa9cc8b769d0a76f2839bdaee68f7e12566131d1edbebaaa1e12169900c7061727365725f7374617465c00102c0fca618d8cfb53c29e8b61bcf584028571b6b1f563e164df093810f07a93265060003820c6e6578745f6d657373616765c0060100000001310e6f75747075745f636f756e746572c00102c0322d95cbadd30a23603872646abd7b0d341c5f3eca8f39da9da74bd3264d9775000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc00179c03b85b8bcac7168100efeb43114a4679d17808ab9309d16a22be916283fbde863c0d22ceeb53dad5d5a36f1caca13fb2cce988bed6679f7370d0d2e5aa042c6556c00050003c0cb0d5024ea71731c4142bd8b8ce738c9d44298b45ccc3d4fc2717db8d4eb78068206737461747573c001040476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765ed820c6c657865725f627566666572c00800000000000000000e70617273696e675f726573756c74c87a31b1c8e3af61756b336bcfc3b0c292c89b40cc8a5080ba99c45463d110ce8b00" + :: !proofs + +let () = + proofs := + "00000214030002e077bef17af38499b44807fabde3837e2355f4988146b065236bac172087929e24bc4324adefe61ff70a912adfce146400586b408d46b371c287b5df9fcdba4000100006d0030170000382066f7574707574d033ba419fa9cc8b769d0a76f2839bdaee68f7e12566131d1edbebaaa1e12169900c7061727365725f7374617465c00102c0fca618d8cfb53c29e8b61bcf584028571b6b1f563e164df093810f07a93265060003820c6e6578745f6d657373616765c0060100000001310e6f75747075745f636f756e746572c00102c0322d95cbadd30a23603872646abd7b0d341c5f3eca8f39da9da74bd3264d9775000a0005000482116576616c756174696f6e5f726573756c74c8eda4dcfc891aa48bb021d3ed729b7efc072bfccb367c623f60ed227bc4de4905047469636bc00179c03b85b8bcac7168100efeb43114a4679d17808ab9309d16a22be916283fbde863c0d22ceeb53dad5d5a36f1caca13fb2cce988bed6679f7370d0d2e5aa042c6556c00050003c0cb0d5024ea71731c4142bd8b8ce738c9d44298b45ccc3d4fc2717db8d4eb78068206737461747573c001040476617273d0c8883069b5a30e9ece9f91b68e759f1909bed7c0ccc0f1a3aee8d2d8473765ed820c6c657865725f627566666572c00800000000000000000e70617273696e675f726573756c74c87a31b1c8e3af61756b336bcfc3b0c292c89b40cc8a5080ba99c45463d110ce8b00" + :: !proofs + +let () = + proofs := + "000001af03000203fad519c60ce458d8173d60347a7165a47f94f34bb09563e3f916508a568ae5160daf16732031127d85916da8a2b2ed0b80e2ec6f76aeb5aed05f20e29535aa0005820764757261626c65d0700600b5ba8846f05688abbc84be210e9841df14210b69ecc81768bc2d7fa5be03746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00100196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e707574820468656164c00100066c656e677468c00100066f7574707574820133810f76616c69646974795f706572696f64c00400013b000134810d6d6573736167655f6c696d6974c002a401047761736d00038103746167c00b00000007636f6c6c656374820c63757272656e745f7469636bc001000e7265626f6f745f636f756e746572c002e907ff02" + :: !proofs + +let () = + proofs := + "000004a20300029154c3457e545055d89ece682b7699aa6468646bc118d31183e606af03c8720d8fdb2e43063ba2e4eb6227939439718b119ff743d5c7f1c0cb53efca9290cebd0005820764757261626c65d0700600b5ba8846f05688abbc84be210e9841df14210b69ecc81768bc2d7fa5be03746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00100196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e7075740003810468656164c001008208636f6e74656e747300040003c0a06eb14bc76138f3404aa3d1907e8ea56cdcab66fd9774fa42ceb0b5db70f3678101330004810f6d6573736167652d636f756e746572c00103000381066c656e677468c00800000000000000028208636f6e74656e7473810130c102000131000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000097261772d6c6576656cc00400000003810131d02be9203590ff323f40bb2e6123792ea6fe582c3004e90f2f07e341c357bb256f066c656e677468c00104066f75747075740004820132810a6c6173745f6c6576656cc004000000030133810f76616c69646974795f706572696f64c00400013b0082013181086f7574626f786573d085c221543585cc73785d90b8205fb70e0ff5fb3ec7cfb237c9de35507cdb04f70134810d6d6573736167655f6c696d6974c002a401047761736d00048205696e707574c005000000030303746167c00b00000007636f6c6c656374820c63757272656e745f7469636bc001040e7265626f6f745f636f756e746572c002e907ff000000000303000003fd00000256119e0f517b258ebaafc3b80f9580736196820e85a89a8b1dbcabc188dffb3c202e00000012000000609d64ecb31e24cbae9bffefb6398aeddbf63848d77a09f8abe6ec870520e52824f5ac4a20922d7f69815f53f2bc1d7e814237f7671dddb9b1da294c2dfc4c71def5ac4a20922d7f69815f53f2bc1d7e814237f7671dddb9b1da294c2dfc4c71de0fb08d67fcd4ee0d497ddf6d75ac8e18dc4828b7eaa24c9bab0d177ef15c0042f100000010000000403918d146062923546523ea77f9f279659b3ef195d3b078438f982c027b1d8917a9d39f2691329b1c8c9f7d42b4ebb7dafd332674e52f8abe2a1ab969e64e2fe50b7a898bab55e92ba1d139db2630c207cf08d698cd0a45b87d4f31ad0f863208db0000000c0000004007f78428e527a26c52b3663fe94540c0dcebc5c06812ac73483dc9e163aba6054734bbd10c6f776cfc899e2ed68c9922c46761ddaef39a7d6ad74f51db9a6ba007c33fc08871ca22ec9f40c437074d7c036c0f7f73847d1c06c9a17e1996b7d9440000000800000040b9229c6473b0774f80374639e5a5d67d9cf2a44a3791e716cd9c344158f95d43d1bd41e8f0d23a94f58094dfdd6138fd1789f68a675fac5315ed813d38fa5b9e0364a4a59f6b439e7e70cc6a3db142f3389ebe3c825c0e6415880ce60e4983db260000000400000020426a3cc0ad6a52091e3d0e0db02ee1fcd56f50c46b7d292502485c175d63c9b9020a5f043148e900d19d02f79abf24b4bd582f6e93abfb9bd8c988eaf75408af3a0000000300000020ed9e0e19c20a3b721dab18672f6970178470220ead77baa226397a08bd7e876b00000194078f1f9fd0816a310a79d0e0c4bf605a544c260c561740bcdeb175ea46f531289000000040157503c39a941b28605440c02809ba0c46e7d2f467898c8fb686ce2f3b2468734dd4e700aae1d5046368abd3874e2381a67183a76ee0c0d4470980a6b26c963006a1d6ed77f0922b69266702ace9a97f218b0b5d575e2bbe6a6b01b9412d8c58a000000040c8f36f8363b363b45329f572116fba1982f4d2d733dc6f8088ff3a0157b931874dd4e700aae1d5046368abd3874e2381a67183a76ee0c0d4470980a6b26c963005474c297bef20ab15fb8d93783d324d6f07fb1a017891890f3b606bac241f144c000000400a5735bc6db3536eba3b549320c870fd51ee99747f79d5702cb3c5982224d3ec4dd4e700aae1d5046368abd3874e2381a67183a76ee0c0d4470980a6b26c9630045efc3165465aff68d3e5bd549d711f9e0e06e786bc1d6873f2e7e4faa43bbe13000000404dd4e700aae1d5046368abd3874e2381a67183a76ee0c0d4470980a6b26c96304dd4e700aae1d5046368abd3874e2381a67183a76ee0c0d4470980a6b26c9630ff00000006013120312078" + :: !proofs + +let () = + proofs := + "000004a2030002833ec3c4a0325b95cebe5505e305cc43ff64e52411b9363fe287f55b2dbd84d5499a79571ba2d9e172052e13d1eac510810ac4eca1d5157a65782d50a84b34690005820764757261626c6582066b65726e656cd07d20c53bdd5b536a6be9c4cdad16e69a9af40b93a6564655fffd88bba050519008726561646f6e6c7982066b65726e656cd0a645771d9d5228a31312b282119c596699ccb6b60b93d759c2072a493ddbb5740c7761736d5f76657273696f6e8101408208636f6e74656e7473810130c10200322e302e302d7231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c656e677468c008000000000000000803746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00680f8e0cde105196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e7075740003810468656164c001008208636f6e74656e7473d029ca9b037bc58b2e8795cb5a78a9923e992ecb747d73aea69221f0bbf8862d9c066c656e677468c00108066f75747075740004820132810a6c6173745f6c6576656cc004000000050133810f76616c69646974795f706572696f64c00400013b0082013181086f7574626f786573d012db3a74b0a7328b572a034fb36111e11ca8db9beeee251c1b636e62b1a369500134810d6d6573736167655f6c696d6974c002a401047761736d00048205696e707574c005000000050703746167c00b0000000770616464696e67820c63757272656e745f7469636bc00688f8e0cde1050e7265626f6f745f636f756e746572c002e90700" + :: !proofs + +let () = + proofs := + "000004a2030002b45db06e873356846dc9bec6df51256edf0ede76c2c4c1fb856ff62a1dd3a71bb4591da0e6a078af531c232280cb8e68554a1879eb6a9e4308c006395fa45d770005820764757261626c6582066b65726e656cd07d20c53bdd5b536a6be9c4cdad16e69a9af40b93a6564655fffd88bba050519008726561646f6e6c7982066b65726e656cd0a645771d9d5228a31312b282119c596699ccb6b60b93d759c2072a493ddbb5740c7761736d5f76657273696f6e8101408208636f6e74656e7473810130c10200322e302e302d7231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c656e677468c008000000000000000803746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00680f0c19bc30b196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e7075740003810468656164c001008208636f6e74656e7473d06a600b954d7302fba4b55875e6025671f6e6364ed0514556b0554107b4c2d245066c656e677468c00108066f75747075740004820132810a6c6173745f6c6576656cc004000000070133810f76616c69646974795f706572696f64c00400013b0082013181086f7574626f786573d0652e374ff90771cb8ec84a7106d62b8cf29b46632699c378aec1afc4aceb3d960134810d6d6573736167655f6c696d6974c002a401047761736d00048205696e707574c005000000070703746167c00b0000000770616464696e67820c63757272656e745f7469636bc00688f0c19bc30b0e7265626f6f745f636f756e746572c002e90700" + :: !proofs + +let () = + proofs := + "000004a203000298c8c12aa31ddb519d4848eca5b5faafafb686fc18232a7af3b9738eedbbf18b1b7a054f5dff5ac3a71c5b54d284633aa8390b7bcfcaad9f6cfab30466dc499c0005820764757261626c6582066b65726e656cd07d20c53bdd5b536a6be9c4cdad16e69a9af40b93a6564655fffd88bba050519008726561646f6e6c7982066b65726e656cd0a645771d9d5228a31312b282119c596699ccb6b60b93d759c2072a493ddbb5740c7761736d5f76657273696f6e8101408208636f6e74656e7473810130c10200322e302e302d7231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c656e677468c008000000000000000803746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00680f0c19bc30b196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e7075740003810468656164c001008208636f6e74656e7473d095d3888221e81b7ccc795571fe150fca0b0b4f8fa6439bc3ad441f6677aa4238066c656e677468c00108066f75747075740004820132810a6c6173745f6c6576656cc004000000070133810f76616c69646974795f706572696f64c00400013b0082013181086f7574626f786573d0652e374ff90771cb8ec84a7106d62b8cf29b46632699c378aec1afc4aceb3d960134810d6d6573736167655f6c696d6974c002a401047761736d00048205696e707574c005000000070703746167c00b0000000770616464696e67820c63757272656e745f7469636bc00688f0c19bc30b0e7265626f6f745f636f756e746572c002e90700" + :: !proofs + +let () = + proofs := + "000004a20300029287c2d0b68cd84c11b0950becf1f954cd26ea6661ce417ee1e871c85d42744a29e1c7e29367c4b40f7d63966bf15195f125a711a800b82f646cd7acc2ef818f0005820764757261626c6582066b65726e656cd07d20c53bdd5b536a6be9c4cdad16e69a9af40b93a6564655fffd88bba050519008726561646f6e6c7982066b65726e656cd0a645771d9d5228a31312b282119c596699ccb6b60b93d759c2072a493ddbb5740c7761736d5f76657273696f6e8101408208636f6e74656e7473810130c10200322e302e302d7231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c656e677468c008000000000000000803746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00680f0c19bc30b196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e7075740003810468656164c001008208636f6e74656e7473d09488f46e420b9e6a86886b62f56f5be815250291de20e0bb901503c473029a24066c656e677468c00108066f75747075740004820132810a6c6173745f6c6576656cc004000000070133810f76616c69646974795f706572696f64c00400013b0082013181086f7574626f786573d0652e374ff90771cb8ec84a7106d62b8cf29b46632699c378aec1afc4aceb3d960134810d6d6573736167655f6c696d6974c002a401047761736d00048205696e707574c005000000070703746167c00b0000000770616464696e67820c63757272656e745f7469636bc00688f0c19bc30b0e7265626f6f745f636f756e746572c002e90700" + :: !proofs + +let () = + proofs := + "000004a20300026c04959b2eeb9719f2fff009b30b1a3e056b2e303e00f30c6fa25649b2db6b6aa82b2e3cf2f36f0dbf44209528859e2ae36f77fc4cc844c91ec349a64e6f2c4f0005820764757261626c6582066b65726e656cd07d20c53bdd5b536a6be9c4cdad16e69a9af40b93a6564655fffd88bba050519008726561646f6e6c7982066b65726e656cd0a645771d9d5228a31312b282119c596699ccb6b60b93d759c2072a493ddbb5740c7761736d5f76657273696f6e8101408208636f6e74656e7473810130c10200322e302e302d7231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c656e677468c008000000000000000803746167c00800000004536f6d650003810370766d00050004000381166f7574626f785f76616c69646974795f706572696f64c00400013b0082136c6173745f746f705f6c6576656c5f63616c6cc00680f0c19bc30b196d6178696d756d5f7265626f6f74735f7065725f696e707574c002e80781146f7574626f785f6d6573736167655f6c696d6974c002a401810c6d61785f6e625f7469636b73c00580dc9afd28820576616c7565810370766d8107627566666572738205696e7075740003810468656164c001008208636f6e74656e7473d02a07f402a57a796a07ac3ad8c832391cbf3b09435464e3c181c171a67ccf2dcc066c656e677468c00108066f75747075740004820132810a6c6173745f6c6576656cc004000000070133810f76616c69646974795f706572696f64c00400013b0082013181086f7574626f786573d0652e374ff90771cb8ec84a7106d62b8cf29b46632699c378aec1afc4aceb3d960134810d6d6573736167655f6c696d6974c002a401047761736d00048205696e707574c005000000070703746167c00b0000000770616464696e67820c63757272656e745f7469636bc00688f0c19bc30b0e7265626f6f745f636f756e746572c002e90700" + :: !proofs + +let proofs = !proofs diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.mli b/src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.mli new file mode 100644 index 000000000000..7f39b3313c89 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/test/serialized_proofs.mli @@ -0,0 +1,27 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** List of pre-computed serialized refutation proofs. *) +val proofs : string list diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/test/test_octez_conversions.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/test/test_octez_conversions.ml new file mode 100644 index 000000000000..a23162821e75 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/test/test_octez_conversions.ml @@ -0,0 +1,490 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Smart rollup node library, type conversions + Invocation: dune exec src/proto_020_PsParisC/lib_sc_rollup_node/test/main.exe \ + -- -f test_octez_conversions.ml + Subject: Ensure conversions between octez smart rollup structures and + protocol ones are bijective. +*) + +open Qcheck2_helpers +open Octez_smart_rollup + +let gen_hash ~size of_bytes = + let open QCheck2.Gen in + let gen = + let* x = bytes_size (pure size) in + return @@ of_bytes x + in + (* This is not beautiful, but there is currently no other way to + remove the shrinker. *) + make_primitive + ~gen:(fun rand -> generate1 ~rand gen) + ~shrink:(fun _ -> Seq.empty) + +let gen_address = gen_hash ~size:Address.size Address.of_bytes_exn + +let gen_state_hash = gen_hash ~size:State_hash.size State_hash.of_bytes_exn + +let gen_inbox_hash = gen_hash ~size:Inbox.Hash.size Inbox.Hash.of_bytes_exn + +let gen_commitment_hash = + gen_hash ~size:Commitment.Hash.size Commitment.Hash.of_bytes_exn + +let gen_payload_hash = + gen_hash + ~size:Merkelized_payload_hashes_hash.size + Merkelized_payload_hashes_hash.of_bytes_exn + +let gen_kind = QCheck2.Gen.oneofl Kind.[Example_arith; Wasm_2_0_0] + +let gen_level = int32_range_gen 0l Int32.max_int + +let uint64 = int64_range_gen 0L Int64.max_int + +let gen_tick = + let open QCheck2.Gen in + let+ i = uint64 in + Z.of_int64 i + +let gen_commitment = + let open QCheck2.Gen in + let* compressed_state = gen_state_hash in + let* inbox_level = gen_level in + let* predecessor = gen_commitment_hash in + let+ number_of_ticks = uint64 in + Octez_smart_rollup.Commitment. + {compressed_state; inbox_level; predecessor; number_of_ticks} + +let gen_dissection_chunk = + let open QCheck2.Gen in + let* state_hash = option gen_state_hash in + let+ tick = gen_tick in + Octez_smart_rollup.Game.{state_hash; tick} + +let gen_dissection = QCheck2.Gen.small_list gen_dissection_chunk + +let gen_proof = + let open QCheck2.Gen in + let+ hex = oneofl Serialized_proofs.proofs in + Hex.to_string (`Hex hex) |> WithExceptions.Option.get ~loc:__LOC__ + +let gen_step = + let open QCheck2.Gen in + let* what = option ~ratio:0.1 (pure ()) in + match what with + | None -> + (* shrink there *) + let+ dissection = gen_dissection in + Octez_smart_rollup.Game.Dissection dissection + | Some () -> + let+ proof = gen_proof in + Octez_smart_rollup.Game.Proof proof + +let random_seed ~rng_state = + Bytes.init Tezos_crypto.Hacl.Ed25519.sk_size (fun _i -> + Char.chr (Random.State.int rng_state 256)) + +let random_algo ~rng_state : Signature.algo = + match Random.State.int rng_state 3 with + | 0 -> Ed25519 + | 1 -> Secp256k1 + | 2 -> P256 + | 3 -> Bls + | _ -> assert false + +let gen_algo = QCheck2.Gen.oneofl [Signature.Ed25519; Secp256k1; P256; Bls] + +let gen_pkh = + let open QCheck2.Gen in + let+ algo = gen_algo in + let pkh, _pk, _sk = Signature.generate_key ~algo () in + pkh + +let gen_stakers = + let open QCheck2.Gen in + let* p1 = gen_pkh in + let+ p2 = gen_pkh in + Octez_smart_rollup.Game.make_index p1 p2 + +let gen_refutation = + let open QCheck2.Gen in + let* b = bool in + match b with + | true -> + let* player_commitment_hash = gen_commitment_hash in + let+ opponent_commitment_hash = gen_commitment_hash in + Octez_smart_rollup.Game.Start + {player_commitment_hash; opponent_commitment_hash} + | false -> + let* choice = gen_tick in + let+ step = gen_step in + Octez_smart_rollup.Game.Move {choice; step} + +let gen_inbox = + let open Protocol in + let open Alpha_context in + let open QCheck2.Gen in + let gen_msg = small_string ~gen:printable in + let* hd = gen_msg in + let* tail = small_list gen_msg in + let payloads = hd :: tail in + let* level = gen_level in + let level = Raw_level.of_int32_exn level in + let witness_and_inbox = + let open Result_syntax in + let inbox = + Sc_rollup.Inbox.genesis + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + level + in + Environment.wrap_tzresult + @@ + let witness = Sc_rollup.Inbox.init_witness_no_history in + let witness = + Sc_rollup.Inbox.add_info_per_level_no_history + ~predecessor_timestamp:Time.Protocol.epoch + ~predecessor:Block_hash.zero + witness + in + let* input_messages = + List.map_e + (fun msg -> Sc_rollup.Inbox_message.(serialize (External msg))) + payloads + in + let* witness = + Sc_rollup.Inbox.add_messages_no_history input_messages witness + in + return (Sc_rollup.Inbox.finalize_inbox_level_no_history inbox witness) + in + return + @@ (witness_and_inbox |> function + | Ok v -> Sc_rollup_proto_types.Inbox.to_octez v + | Error e -> + Stdlib.failwith (Format.asprintf "%a" Error_monad.pp_print_trace e)) + +let number_of_slots = 256 + +let gen_slot_index = + let open QCheck2.Gen in + let max = number_of_slots - 1 in + graft_corners (int_bound max) [0; 1; 2; max] () + +let gen_page_index = + let open QCheck2.Gen in + let max = 0xfff / 2 in + graft_corners (int_bound max) [0; 1; 2; max] () + +let gen_slot_header_commitment = + let open QCheck2.Gen in + make_primitive + ~gen:(fun state -> + Tezos_crypto_dal.Cryptobox.Internal_for_tests.dummy_commitment ~state ()) + ~shrink:(fun _ -> Seq.empty) + +let gen_slot_header = + let open QCheck2.Gen in + let* published_level = gen_level in + let* index = gen_slot_index in + let+ commitment = gen_slot_header_commitment in + Octez_smart_rollup.Dal.Slot_header.{id = {published_level; index}; commitment} + +let compare_slot_header_id (s1 : Octez_smart_rollup.Dal.Slot_header.id) + (s2 : Octez_smart_rollup.Dal.Slot_header.id) = + let c = Int32.compare s1.published_level s2.published_level in + if c <> 0 then c else Int.compare s1.index s2.index + +let gen_slot_headers = + let open QCheck2.Gen in + let size = int_bound 50 in + let+ l = list_size size gen_slot_header in + List.sort + (fun (h1 : Octez_smart_rollup.Dal.Slot_header.t) + (h2 : Octez_smart_rollup.Dal.Slot_header.t) -> + compare_slot_header_id h1.id h2.id) + l + |> fun l -> + match l with + | [] -> [] + | (h : Octez_smart_rollup.Dal.Slot_header.t) :: _ -> + let min_level = h.id.published_level in + (* smallest level *) + List.mapi + (fun i (h : Octez_smart_rollup.Dal.Slot_header.t) -> + (* patch the published level to comply with the invariants *) + let published_level = Int32.(add min_level (of_int i)) in + let h = {h with id = {h.id with published_level}} in + (published_level, [h])) + l + +let gen_slot_history = + let open Protocol.Alpha_context in + let open QCheck2.Gen in + let+ l = gen_slot_headers in + let l = + List.map + (fun (lvl, h) -> + ( Raw_level.of_int32_exn lvl, + List.map + (Sc_rollup_proto_types.Dal.Slot_header.of_octez ~number_of_slots) + h )) + l + in + List.fold_left_e + (fun hist (published_level, attested_slots) -> + Dal.Slots_history.add_confirmed_slot_headers_no_cache + ~number_of_slots + hist + published_level + attested_slots) + Dal.Slots_history.genesis + l + |> function + | Error e -> + Stdlib.failwith (Format.asprintf "%a" Environment.Error_monad.pp_trace e) + | Ok v -> Sc_rollup_proto_types.Dal.Slot_history.to_octez v + +let gen_slot_history_cache = + let open Protocol.Alpha_context in + let open QCheck2.Gen in + let+ l = gen_slot_headers in + let cache = Dal.Slots_history.History_cache.empty ~capacity:Int64.max_int in + let l = + List.map + (fun (lvl, h) -> + ( Raw_level.of_int32_exn lvl, + List.map + (Sc_rollup_proto_types.Dal.Slot_header.of_octez ~number_of_slots) + h )) + l + in + List.fold_left_e + (fun (hist, cache) (published_level, attested_slots) -> + Dal.Slots_history.add_confirmed_slot_headers + ~number_of_slots + hist + cache + published_level + attested_slots) + (Dal.Slots_history.genesis, cache) + l + |> function + | Error e -> + Stdlib.failwith (Format.asprintf "%a" Environment.Error_monad.pp_trace e) + | Ok (_, c) -> Sc_rollup_proto_types.Dal.Slot_history_cache.to_octez c + +let test_roundtrip ~count name gen to_octez from_octez octez_encoding + proto_encoding = + let test octez1 = + try + let proto1 = from_octez octez1 in + let octez2 = to_octez proto1 in + let proto2 = from_octez octez2 in + let check version enc v1 v2 = + let b1 = Data_encoding.Binary.to_bytes_exn enc v1 in + let b2 = Data_encoding.Binary.to_bytes_exn enc v2 in + if not (Bytes.equal b1 b2) then + QCheck2.Test.fail_reportf + "%s-%s not identical after roundtrip conversion" + name + version + in + check "protocol" proto_encoding proto1 proto2 ; + check "octez" octez_encoding octez1 octez2 ; + true + with exn -> + QCheck2.Test.fail_reportf + "%s roundtrip conversion error: %s" + name + (Printexc.to_string exn) + in + let print v = + Data_encoding.Json.construct octez_encoding v + |> Data_encoding.Json.to_string ~minify:false + in + QCheck2.Test.make + ~count + ~print + ~name:(Format.asprintf "roundtrip %s" name) + gen + test + +let test_address = + test_roundtrip + ~count:1000 + "address" + gen_address + Sc_rollup_proto_types.Address.to_octez + Sc_rollup_proto_types.Address.of_octez + Octez_smart_rollup.Address.encoding + Protocol.Alpha_context.Sc_rollup.Address.encoding + +let test_state_hash = + test_roundtrip + ~count:1000 + "state_hash" + gen_state_hash + Sc_rollup_proto_types.State_hash.to_octez + Sc_rollup_proto_types.State_hash.of_octez + Octez_smart_rollup.State_hash.encoding + Protocol.Alpha_context.Sc_rollup.State_hash.encoding + +let test_payload_hash = + test_roundtrip + ~count:1000 + "payload_hash" + gen_payload_hash + Sc_rollup_proto_types.Merkelized_payload_hashes_hash.to_octez + Sc_rollup_proto_types.Merkelized_payload_hashes_hash.of_octez + Octez_smart_rollup.Merkelized_payload_hashes_hash.encoding + Protocol.Alpha_context.Sc_rollup.Inbox_merkelized_payload_hashes.Hash + .encoding + +let test_commitment_hash = + test_roundtrip + ~count:1000 + "commitment_hash" + gen_commitment_hash + Sc_rollup_proto_types.Commitment_hash.to_octez + Sc_rollup_proto_types.Commitment_hash.of_octez + Octez_smart_rollup.Commitment.Hash.encoding + Protocol.Alpha_context.Sc_rollup.Commitment.Hash.encoding + +let test_commitment = + test_roundtrip + ~count:1000 + "commitment" + gen_commitment + Sc_rollup_proto_types.Commitment.to_octez + Sc_rollup_proto_types.Commitment.of_octez + Octez_smart_rollup.Commitment.encoding + Protocol.Alpha_context.Sc_rollup.Commitment.encoding + +let test_stakers = + test_roundtrip + ~count:1000 + "stakers" + gen_stakers + Sc_rollup_proto_types.Game.index_to_octez + Sc_rollup_proto_types.Game.index_of_octez + Octez_smart_rollup.Game.index_encoding + Protocol.Alpha_context.Sc_rollup.Game.Index.encoding + +let test_refutation = + test_roundtrip + ~count:1000 + "refutation" + gen_refutation + Sc_rollup_proto_types.Game.refutation_to_octez + Sc_rollup_proto_types.Game.refutation_of_octez + Octez_smart_rollup.Game.refutation_encoding + Protocol.Alpha_context.Sc_rollup.Game.refutation_encoding + +let test_inbox = + test_roundtrip + ~count:1000 + "inbox" + gen_inbox + Sc_rollup_proto_types.Inbox.to_octez + Sc_rollup_proto_types.Inbox.of_octez + Octez_smart_rollup.Inbox.encoding + Protocol.Alpha_context.Sc_rollup.Inbox.encoding + +let test_slot_index = + test_roundtrip + ~count:100 + "dal_slot_index" + gen_slot_index + Sc_rollup_proto_types.Dal.Slot_index.to_octez + (Sc_rollup_proto_types.Dal.Slot_index.of_octez ~number_of_slots) + Octez_smart_rollup.Dal.Slot_index.encoding + Protocol.Alpha_context.Dal.Slot_index.encoding + +let test_page_index = + test_roundtrip + ~count:100 + "dal_page_index" + gen_page_index + Sc_rollup_proto_types.Dal.Page_index.to_octez + Sc_rollup_proto_types.Dal.Page_index.of_octez + Octez_smart_rollup.Dal.Page_index.encoding + Protocol.Alpha_context.Dal.Page.Index.encoding + +let test_slot_header = + test_roundtrip + ~count:1000 + "dal_slot_header" + gen_slot_header + Sc_rollup_proto_types.Dal.Slot_header.to_octez + (Sc_rollup_proto_types.Dal.Slot_header.of_octez ~number_of_slots) + Octez_smart_rollup.Dal.Slot_header.encoding + Protocol.Alpha_context.Dal.Slot.Header.encoding + +let test_slot_history = + test_roundtrip + ~count:300 + "dal_slot_history" + gen_slot_history + Sc_rollup_proto_types.Dal.Slot_history.to_octez + Sc_rollup_proto_types.Dal.Slot_history.of_octez + Octez_smart_rollup.Dal.Slot_history.encoding + Protocol.Alpha_context.Dal.Slots_history.encoding + +let test_slot_history_cache = + test_roundtrip + ~count:300 + "dal_slot_history_cache" + gen_slot_history_cache + Sc_rollup_proto_types.Dal.Slot_history_cache.to_octez + Sc_rollup_proto_types.Dal.Slot_history_cache.of_octez + Octez_smart_rollup.Dal.Slot_history_cache.encoding + Protocol.Alpha_context.Dal.Slots_history.History_cache.encoding + +let tests = + [ + test_address; + test_state_hash; + test_payload_hash; + test_commitment_hash; + test_commitment; + test_stakers; + test_refutation; + test_inbox; + test_slot_index; + test_page_index; + test_slot_header; + test_slot_history; + test_slot_history_cache; + ] + +let () = + Alcotest.run + ~__FILE__ + (Protocol.name ^ ": Smart rollup types octez conversions") + [("roundtrip", qcheck_wrap tests)] diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_pvm.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_pvm.ml new file mode 100644 index 000000000000..65c678722509 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_pvm.ml @@ -0,0 +1,202 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022-2023 TriliTech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This module manifests the proof format used by the Wasm PVM as defined by + the Layer 1 implementation for it. + + It is imperative that this is aligned with the protocol's implementation. +*) +module Wasm_2_0_0_proof_format = + Irmin_context.Proof + (struct + include Sc_rollup.State_hash + + let of_context_hash = Sc_rollup.State_hash.context_hash_to_state_hash + end) + (struct + let proof_encoding = + Tezos_context_merkle_proof_encoding.Merkle_proof_encoding.V2.Tree2 + .tree_proof_encoding + end) + +module type TreeS = + Tezos_context_sigs.Context.TREE + with type key = string list + and type value = bytes + +module Make_wrapped_tree (Tree : TreeS) : + Tezos_tree_encoding.TREE with type tree = Tree.tree = struct + type Tezos_tree_encoding.tree_instance += PVM_tree of Tree.tree + + include Tree + + let select = function + | PVM_tree t -> t + | _ -> raise Tezos_tree_encoding.Incorrect_tree_type + + let wrap t = PVM_tree t +end + +module Make_backend (Tree : TreeS) = struct + include Tezos_scoru_wasm_fast.Pvm.Make (Make_wrapped_tree (Tree)) + + let compute_step = + compute_step ~wasm_entrypoint:Tezos_scoru_wasm.Constants.wasm_entrypoint +end + +(** Durable part of the storage of this PVM. *) +module type Durable_state = sig + type state + + (** [value_length state key] returns the length of data stored + for the [key] in the durable storage of the PVM state [state], if any. *) + val value_length : state -> string -> int64 option Lwt.t + + (** [lookup state key] returns the data stored + for the [key] in the durable storage of the PVM state [state], if any. *) + val lookup : state -> string -> bytes option Lwt.t + + (** [subtrees state key] returns subtrees + for the [key] in the durable storage of the PVM state [state]. + Empty list in case if path doesn't exist. *) + val list : state -> string -> string list Lwt.t + + module Tree_encoding_runner : + Tezos_tree_encoding.Runner.S with type tree = state +end + +module Make_durable_state + (T : Tezos_tree_encoding.TREE with type tree = Irmin_context.tree) : + Durable_state with type state = T.tree = struct + module Tree_encoding_runner = Tezos_tree_encoding.Runner.Make (T) + + type state = T.tree + + let decode_durable tree = + Tree_encoding_runner.decode + Tezos_scoru_wasm.Wasm_pvm.durable_storage_encoding + tree + + let value_length tree key_str = + let open Lwt_syntax in + let key = Tezos_scoru_wasm.Durable.key_of_string_exn key_str in + let* durable = decode_durable tree in + let+ res_opt = Tezos_scoru_wasm.Durable.find_value durable key in + Option.map Tezos_lazy_containers.Chunked_byte_vector.length res_opt + + let lookup tree key_str = + let open Lwt_syntax in + let key = Tezos_scoru_wasm.Durable.key_of_string_exn key_str in + let* durable = decode_durable tree in + let* res_opt = Tezos_scoru_wasm.Durable.find_value durable key in + match res_opt with + | None -> return_none + | Some v -> + let+ bts = Tezos_lazy_containers.Chunked_byte_vector.to_bytes v in + Some bts + + let list tree key_str = + let open Lwt_syntax in + let key = Tezos_scoru_wasm.Durable.key_of_string_exn key_str in + let* durable = decode_durable tree in + Tezos_scoru_wasm.Durable.list durable key +end + +module Durable_state = + Make_durable_state (Make_wrapped_tree (Wasm_2_0_0_proof_format.Tree)) + +type unsafe_patch = Increase_max_nb_ticks of int64 + +module Impl : Pvm_sig.S with type Unsafe_patches.t = unsafe_patch = struct + module PVM = + Sc_rollup.Wasm_2_0_0PVM.Make (Make_backend) (Wasm_2_0_0_proof_format) + include PVM + + type repo = Irmin_context.repo + + type tree = Irmin_context.tree + + module Ctxt_wrapper = Context_wrapper.Irmin + + let kind = Sc_rollup.Kind.Wasm_2_0_0 + + let new_dissection = Game_helpers.Wasm.new_dissection + + module State = Irmin_context.PVMState + + module Inspect_durable_state = struct + let lookup state keys = + let key = "/" ^ String.concat "/" keys in + Durable_state.lookup state key + end + + module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) + + module Unsafe_patches = struct + type t = unsafe_patch + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with + | Increase_max_nb_ticks max_nb_ticks -> + Ok (Increase_max_nb_ticks max_nb_ticks) + + let apply state (Increase_max_nb_ticks max_nb_ticks) = + let open Lwt_syntax in + let* registered_max_nb_ticks = Backend.Unsafe.get_max_nb_ticks state in + let max_nb_ticks = Z.of_int64 max_nb_ticks in + if Z.Compare.(max_nb_ticks < registered_max_nb_ticks) then + Format.ksprintf + invalid_arg + "Decreasing tick limit of WASM PVM from %s to %s is not allowed" + (Z.to_string registered_max_nb_ticks) + (Z.to_string max_nb_ticks) ; + Backend.Unsafe.set_max_nb_ticks max_nb_ticks state + end + + let string_of_status : status -> string = function + | Waiting_for_input_message -> "Waiting for input message" + | Waiting_for_reveal (Sc_rollup.Reveal_raw_data hash) -> + Format.asprintf + "Waiting for preimage reveal %a" + Sc_rollup_reveal_hash.pp + hash + | Waiting_for_reveal Sc_rollup.Reveal_metadata -> "Waiting for metadata" + | Waiting_for_reveal (Sc_rollup.Request_dal_page page_id) -> + Format.asprintf "Waiting for page data %a" Dal.Page.pp page_id + | Waiting_for_reveal Sc_rollup.Reveal_dal_parameters -> + "Waiting for DAL parameters" + | Computing -> "Computing" + + let eval_many ~reveal_builtins ~write_debug ~is_reveal_enabled:_ = + Backend.compute_step_many + ~wasm_entrypoint:Tezos_scoru_wasm.Constants.wasm_entrypoint + ~reveal_builtins + ~write_debug +end + +include Impl diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_rpc.ml b/src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_rpc.ml new file mode 100644 index 000000000000..fe4d530eb9d6 --- /dev/null +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/wasm_2_0_0_rpc.ml @@ -0,0 +1,82 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Rpc_directory_helpers +open Context_wrapper.Irmin + +module Make_RPC + (Durable_state : Wasm_2_0_0_pvm.Durable_state + with type state = Irmin_context.tree) = +struct + module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block + + type context = Node_context.rw + + type subcontext = Node_context.ro * Block_hash.t + + let context_of_prefix node_ctxt (((), block) : prefix) = + let open Lwt_result_syntax in + let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in + (Node_context.readonly node_ctxt, block) + end) + + let get_state (node_ctxt : _ Node_context.t) block_hash = + let open Lwt_result_syntax in + let* ctxt = Node_context.checkout_context node_ctxt block_hash in + let*! state = Context.PVMState.find ctxt in + match state with None -> failwith "No state" | Some state -> return state + + let register () = + let open Protocol.Alpha_context.Sc_rollup in + ( Block_directory.register0 + (Sc_rollup_services.Block.durable_state_value Kind.Wasm_2_0_0) + @@ fun (node_ctxt, block) {key} () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let*! value = Durable_state.lookup (of_node_pvmstate state) key in + return value ) ; + + ( Block_directory.register0 + (Sc_rollup_services.Block.durable_state_length Kind.Wasm_2_0_0) + @@ fun (node_ctxt, block) {key} () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let*! leng = Durable_state.value_length (of_node_pvmstate state) key in + return leng ) ; + + Block_directory.register0 + (Sc_rollup_services.Block.durable_state_subkeys Kind.Wasm_2_0_0) + @@ fun (node_ctxt, block) {key} () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let*! subkeys = Durable_state.list (of_node_pvmstate state) key in + return subkeys + + let build_sub_directory node_ctxt = + register () ; + Block_directory.build_sub_directory node_ctxt +end diff --git a/src/proto_020_PsParisC/parameters/dune b/src/proto_020_PsParisC/parameters/dune new file mode 100644 index 000000000000..ed909e037d66 --- /dev/null +++ b/src/proto_020_PsParisC/parameters/dune @@ -0,0 +1,4 @@ +(copy_files + (alias copy-parameters) + (mode (promote (until-clean))) + (files ../lib_parameters/*.json)) \ No newline at end of file -- GitLab From 752a9b71b9d6dc2f405437af1121740f4441b2fe Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 11:32:50 +0200 Subject: [PATCH 02/16] ParisC: Update vanity nonce --- src/proto_020_PsParisC/lib_protocol/main.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/proto_020_PsParisC/lib_protocol/main.ml b/src/proto_020_PsParisC/lib_protocol/main.ml index 727ff7616ea1..3d64df0baa8d 100644 --- a/src/proto_020_PsParisC/lib_protocol/main.ml +++ b/src/proto_020_PsParisC/lib_protocol/main.ml @@ -480,4 +480,4 @@ module Mempool = struct ~predecessor_hash:head_hash) end -(* Vanity nonce: 2904751756914914 *) +(* Vanity nonce: 8669992433146046 *) -- GitLab From bcc3ac3c54f9c85f7fbab0a3bc8921f00e8f95a2 Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 15:58:03 +0200 Subject: [PATCH 03/16] ParisC: Update Protocol content --- .../final_protocol_versions | 1 + ...ParisB.ml => main_accuser_020_PsParisC.ml} | 0 ...PtParisB.ml => main_baker_020_PsParisC.ml} | 0 src/proto_020_PsParisC/lib_client/proxy.ml | 2 +- .../lib_protocol/TEZOS_PROTOCOL | 4 +- .../constants_parametric_previous_repr.ml | 285 ++++++++---- .../constants_parametric_previous_repr.mli | 47 +- .../lib_protocol/constants_repr.ml | 4 +- .../lib_protocol/constants_repr.mli | 2 + src/proto_020_PsParisC/lib_protocol/dune | 8 +- .../lib_protocol/init_storage.ml | 198 ++------- .../lib_protocol/raw_context.ml | 414 +++++++----------- .../lib_protocol/raw_context.mli | 2 +- .../lib_protocol/sc_rollup_stake_storage.ml | 33 +- .../lib_protocol/sc_rollup_storage.ml | 15 + .../lib_protocol/sc_rollup_storage.mli | 19 + .../lib_protocol/storage.ml | 20 + .../lib_protocol/storage.mli | 8 + 18 files changed, 537 insertions(+), 525 deletions(-) rename src/proto_020_PsParisC/bin_accuser/{main_accuser_019_PtParisB.ml => main_accuser_020_PsParisC.ml} (100%) rename src/proto_020_PsParisC/bin_baker/{main_baker_019_PtParisB.ml => main_baker_020_PsParisC.ml} (100%) diff --git a/src/lib_protocol_compiler/final_protocol_versions b/src/lib_protocol_compiler/final_protocol_versions index e8698e0b4a0a..b25a5f42cb80 100644 --- a/src/lib_protocol_compiler/final_protocol_versions +++ b/src/lib_protocol_compiler/final_protocol_versions @@ -20,3 +20,4 @@ PtMumbai2TmsJHNGRkD8v8YDbtao7BLUC3wjASn1inAKLFCjaH1 PtNairobiyssHuh87hEhfVBGCVrK3WnS8Z2FT4ymB5tAa4r1nQf ProxfordYmVfjWnRcgjWH36fW6PArwqykTFzotUxRs6gmTcZDuH PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ +PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi diff --git a/src/proto_020_PsParisC/bin_accuser/main_accuser_019_PtParisB.ml b/src/proto_020_PsParisC/bin_accuser/main_accuser_020_PsParisC.ml similarity index 100% rename from src/proto_020_PsParisC/bin_accuser/main_accuser_019_PtParisB.ml rename to src/proto_020_PsParisC/bin_accuser/main_accuser_020_PsParisC.ml diff --git a/src/proto_020_PsParisC/bin_baker/main_baker_019_PtParisB.ml b/src/proto_020_PsParisC/bin_baker/main_baker_020_PsParisC.ml similarity index 100% rename from src/proto_020_PsParisC/bin_baker/main_baker_019_PtParisB.ml rename to src/proto_020_PsParisC/bin_baker/main_baker_020_PsParisC.ml diff --git a/src/proto_020_PsParisC/lib_client/proxy.ml b/src/proto_020_PsParisC/lib_client/proxy.ml index 7df741021ab0..3e22df43b88f 100644 --- a/src/proto_020_PsParisC/lib_client/proxy.ml +++ b/src/proto_020_PsParisC/lib_client/proxy.ml @@ -116,7 +116,7 @@ let initial_context (ctx : Tezos_proxy.Proxy_getter.rpc_context_args) Tezos_protocol_environment.Proxy_context.empty @@ Some (module ProxyDelegation) in - let version_value = "paris_019" in + let version_value = "paris_020" in let*! ctxt = Tezos_protocol_environment.Context.add empty diff --git a/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL b/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL index d3e1bef8a58f..7df27bd65d02 100644 --- a/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_020_PsParisC/lib_protocol/TEZOS_PROTOCOL @@ -1,6 +1,6 @@ { "expected_env_version": 12, - "hash": "PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ", + "hash": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", "modules": [ "Misc", "Non_empty_string", @@ -206,8 +206,8 @@ "Sc_rollup_commitment_storage", "Sc_rollup_outbox_storage", "Sc_rollup_whitelist_storage", - "Sc_rollup_stake_storage", "Sc_rollup_storage", + "Sc_rollup_stake_storage", "Dal_slot_storage", "Sc_rollup_refutation_storage", "Zk_rollup_errors", diff --git a/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml index 96b257e4cd1d..db6a94845fea 100644 --- a/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml +++ b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.ml @@ -27,10 +27,10 @@ type dal = { feature_enable : bool; + incentives_enable : bool; number_of_slots : int; attestation_lag : int; attestation_threshold : int; - blocks_per_epoch : int32; cryptobox_parameters : Dal.parameters; } @@ -39,39 +39,39 @@ let dal_encoding = conv (fun { feature_enable; + incentives_enable; number_of_slots; attestation_lag; attestation_threshold; cryptobox_parameters; - blocks_per_epoch; } -> ( ( feature_enable, + incentives_enable, number_of_slots, attestation_lag, - attestation_threshold, - blocks_per_epoch ), + attestation_threshold ), cryptobox_parameters )) (fun ( ( feature_enable, + incentives_enable, number_of_slots, attestation_lag, - attestation_threshold, - blocks_per_epoch ), + attestation_threshold ), cryptobox_parameters ) -> { feature_enable; + incentives_enable; number_of_slots; attestation_lag; attestation_threshold; - blocks_per_epoch; cryptobox_parameters; }) (merge_objs (obj5 (req "feature_enable" bool) - (req "number_of_slots" int16) - (req "attestation_lag" int16) - (req "attestation_threshold" int16) - (req "blocks_per_epoch" int32)) + (req "incentives_enable" bool) + (req "number_of_slots" uint16) + (req "attestation_lag" uint8) + (req "attestation_threshold" uint8)) Dal.parameters_encoding) (* The encoded representation of this type is stored in the context as @@ -90,6 +90,23 @@ type sc_rollup_reveal_activation_level = { metadata : Raw_level_repr.t; dal_page : Raw_level_repr.t; dal_parameters : Raw_level_repr.t; + (* Once a DAL slot is attested, a rollup can only import it within the range + of levels [attested_level; attested_level + + dal_attested_slots_validity_lag]. *) + (* Warning: the semantics of valid slots needs to be adapted if the + value of this parameter is changed in the future. + - If it is increased, some attested slots that were outdated with + the old value will become valid again. + - If it is decreased, some attested slots that were valid with + the old value will become outdated. + + In both cases, the status of slots before and after the value change is + different. Said otherwise, the validity of the slot may differ depending on + the time of the check, in particular it may be different in the following + two cases: (a) the slot is imported before the value upgrade, (2) a + refutation game targeting a page of that slot is started after the + upgrade. *) + dal_attested_slots_validity_lag : int; } let sc_rollup_reveal_hashing_schemes_encoding = @@ -103,14 +120,30 @@ let sc_rollup_reveal_activation_level_encoding : sc_rollup_reveal_activation_level Data_encoding.t = let open Data_encoding in conv - (fun t -> (t.raw_data, t.metadata, t.dal_page, t.dal_parameters)) - (fun (raw_data, metadata, dal_page, dal_parameters) -> - {raw_data; metadata; dal_page; dal_parameters}) - (obj4 + (fun t -> + ( t.raw_data, + t.metadata, + t.dal_page, + t.dal_parameters, + t.dal_attested_slots_validity_lag )) + (fun ( raw_data, + metadata, + dal_page, + dal_parameters, + dal_attested_slots_validity_lag ) -> + { + raw_data; + metadata; + dal_page; + dal_parameters; + dal_attested_slots_validity_lag; + }) + (obj5 (req "raw_data" sc_rollup_reveal_hashing_schemes_encoding) (req "metadata" Raw_level_repr.encoding) (req "dal_page" Raw_level_repr.encoding) - (req "dal_parameters" Raw_level_repr.encoding)) + (req "dal_parameters" Raw_level_repr.encoding) + (req "dal_attested_slots_validity_lag" Data_encoding.int31)) type sc_rollup = { arith_pvm_enable : bool; @@ -138,8 +171,12 @@ type zk_rollup = { } type adaptive_rewards_params = { - issuance_ratio_min : Q.t; - issuance_ratio_max : Q.t; + issuance_ratio_final_min : Q.t; + issuance_ratio_final_max : Q.t; + issuance_ratio_initial_min : Q.t; + issuance_ratio_initial_max : Q.t; + initial_period : int; + transition_period : int; max_bonus : Issuance_bonus_repr.max_bonus; growth_rate : Q.t; center_dz : Q.t; @@ -153,6 +190,8 @@ type adaptive_issuance = { adaptive_rewards_params : adaptive_rewards_params; activation_vote_enable : bool; autostaking_enable : bool; + force_activation : bool; + ns_enable : bool; } type issuance_weights = { @@ -160,17 +199,17 @@ type issuance_weights = { baking_reward_fixed_portion_weight : int; baking_reward_bonus_weight : int; attesting_reward_weight : int; - liquidity_baking_subsidy_weight : int; seed_nonce_revelation_tip_weight : int; vdf_revelation_tip_weight : int; } type t = { - preserved_cycles : int; + consensus_rights_delay : int; + blocks_preservation_cycles : int; + delegate_parameters_activation_delay : int; blocks_per_cycle : int32; blocks_per_commitment : int32; nonce_revelation_threshold : int32; - blocks_per_stake_snapshot : int32; cycles_per_voting_period : int32; hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; @@ -185,6 +224,7 @@ type t = { quorum_min : int32; quorum_max : int32; min_proposal_quorum : int32; + liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_toggle_ema_threshold : int32; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; @@ -195,6 +235,8 @@ type t = { limit_of_delegation_over_baking : int; percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; (* If a new cache is added, please also modify the @@ -206,6 +248,7 @@ type t = { sc_rollup : sc_rollup; zk_rollup : zk_rollup; adaptive_issuance : adaptive_issuance; + direct_ticket_spending_enable : bool; } let sc_rollup_encoding = @@ -357,36 +400,56 @@ let adaptive_rewards_params_encoding = let open Data_encoding in conv (fun { - issuance_ratio_min; - issuance_ratio_max; + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; max_bonus; growth_rate; center_dz; radius_dz; } -> - ( issuance_ratio_min, - issuance_ratio_max, + ( issuance_ratio_final_min, + issuance_ratio_final_max, + issuance_ratio_initial_min, + issuance_ratio_initial_max, + initial_period, + transition_period, max_bonus, growth_rate, center_dz, radius_dz )) - (fun ( issuance_ratio_min, - issuance_ratio_max, + (fun ( issuance_ratio_final_min, + issuance_ratio_final_max, + issuance_ratio_initial_min, + issuance_ratio_initial_max, + initial_period, + transition_period, max_bonus, growth_rate, center_dz, radius_dz ) -> { - issuance_ratio_min; - issuance_ratio_max; + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; max_bonus; growth_rate; center_dz; radius_dz; }) - (obj6 - (req "issuance_ratio_min" extremum_encoding) - (req "issuance_ratio_max" extremum_encoding) + (obj10 + (req "issuance_ratio_final_min" extremum_encoding) + (req "issuance_ratio_final_max" extremum_encoding) + (req "issuance_ratio_initial_min" extremum_encoding) + (req "issuance_ratio_initial_max" extremum_encoding) + (req "initial_period" uint8) + (req "transition_period" uint8) (req "max_bonus" Issuance_bonus_repr.max_bonus_encoding) (req "growth_rate" growth_rate_encoding) (req "center_dz" center_encoding) @@ -402,19 +465,25 @@ let adaptive_issuance_encoding = adaptive_rewards_params; activation_vote_enable; autostaking_enable; + force_activation; + ns_enable; } -> ( global_limit_of_staking_over_baking, edge_of_staking_over_delegation, launch_ema_threshold, adaptive_rewards_params, activation_vote_enable, - autostaking_enable )) + autostaking_enable, + force_activation, + ns_enable )) (fun ( global_limit_of_staking_over_baking, edge_of_staking_over_delegation, launch_ema_threshold, adaptive_rewards_params, activation_vote_enable, - autostaking_enable ) -> + autostaking_enable, + force_activation, + ns_enable ) -> { global_limit_of_staking_over_baking; edge_of_staking_over_delegation; @@ -422,14 +491,18 @@ let adaptive_issuance_encoding = adaptive_rewards_params; activation_vote_enable; autostaking_enable; + force_activation; + ns_enable; }) - (obj6 + (obj8 (req "global_limit_of_staking_over_baking" uint8) (req "edge_of_staking_over_delegation" uint8) (req "adaptive_issuance_launch_ema_threshold" int32) (req "adaptive_rewards_params" adaptive_rewards_params_encoding) (req "adaptive_issuance_activation_vote_enable" bool) - (req "autostaking_enable" bool)) + (req "autostaking_enable" bool) + (req "adaptive_issuance_force_activation" bool) + (req "ns_enable" bool)) let issuance_weights_encoding = let open Data_encoding in @@ -439,7 +512,6 @@ let issuance_weights_encoding = baking_reward_fixed_portion_weight; baking_reward_bonus_weight; attesting_reward_weight; - liquidity_baking_subsidy_weight; seed_nonce_revelation_tip_weight; vdf_revelation_tip_weight; } : @@ -448,14 +520,12 @@ let issuance_weights_encoding = baking_reward_fixed_portion_weight, baking_reward_bonus_weight, attesting_reward_weight, - liquidity_baking_subsidy_weight, seed_nonce_revelation_tip_weight, vdf_revelation_tip_weight )) (fun ( base_total_issued_per_minute, baking_reward_fixed_portion_weight, baking_reward_bonus_weight, attesting_reward_weight, - liquidity_baking_subsidy_weight, seed_nonce_revelation_tip_weight, vdf_revelation_tip_weight ) -> { @@ -463,16 +533,14 @@ let issuance_weights_encoding = baking_reward_fixed_portion_weight; baking_reward_bonus_weight; attesting_reward_weight; - liquidity_baking_subsidy_weight; seed_nonce_revelation_tip_weight; vdf_revelation_tip_weight; }) - (obj7 + (obj6 (req "base_total_issued_per_minute" Tez_repr.encoding) (req "baking_reward_fixed_portion_weight" int31) (req "baking_reward_bonus_weight" int31) (req "attesting_reward_weight" int31) - (req "liquidity_baking_subsidy_weight" int31) (req "seed_nonce_revelation_tip_weight" int31) (req "vdf_revelation_tip_weight" int31)) @@ -480,16 +548,17 @@ let encoding = let open Data_encoding in conv (fun c -> - ( ( c.preserved_cycles, - c.blocks_per_cycle, - c.blocks_per_commitment, - c.nonce_revelation_threshold, - c.blocks_per_stake_snapshot, - c.cycles_per_voting_period, - c.hard_gas_limit_per_operation, - c.hard_gas_limit_per_block, - c.proof_of_work_threshold, - c.minimal_stake ), + ( ( ( c.consensus_rights_delay, + c.blocks_preservation_cycles, + c.delegate_parameters_activation_delay ), + ( c.blocks_per_cycle, + c.blocks_per_commitment, + c.nonce_revelation_threshold, + c.cycles_per_voting_period, + c.hard_gas_limit_per_operation, + c.hard_gas_limit_per_block, + c.proof_of_work_threshold, + c.minimal_stake ) ), ( ( c.minimal_frozen_stake, c.vdf_difficulty, c.origination_size, @@ -499,6 +568,7 @@ let encoding = c.quorum_min ), ( ( c.quorum_max, c.min_proposal_quorum, + c.liquidity_baking_subsidy, c.liquidity_baking_toggle_ema_threshold, c.max_operations_time_to_live, c.minimal_block_delay, @@ -509,23 +579,28 @@ let encoding = c.limit_of_delegation_over_baking, c.percentage_of_frozen_deposits_slashed_per_double_baking, c.percentage_of_frozen_deposits_slashed_per_double_attestation, + c.max_slashing_per_block, + c.max_slashing_threshold, c.testnet_dictator, c.initial_seed ), ( ( c.cache_script_size, c.cache_stake_distribution_cycles, c.cache_sampler_state_cycles ), - (c.dal, ((c.sc_rollup, c.zk_rollup), c.adaptive_issuance)) ) ) - ) ) )) - (fun ( ( preserved_cycles, - blocks_per_cycle, - blocks_per_commitment, - nonce_revelation_threshold, - blocks_per_stake_snapshot, - cycles_per_voting_period, - hard_gas_limit_per_operation, - hard_gas_limit_per_block, - proof_of_work_threshold, - minimal_stake ), + ( c.dal, + ( (c.sc_rollup, c.zk_rollup), + (c.adaptive_issuance, c.direct_ticket_spending_enable) ) ) + ) ) ) ) )) + (fun ( ( ( consensus_rights_delay, + blocks_preservation_cycles, + delegate_parameters_activation_delay ), + ( blocks_per_cycle, + blocks_per_commitment, + nonce_revelation_threshold, + cycles_per_voting_period, + hard_gas_limit_per_operation, + hard_gas_limit_per_block, + proof_of_work_threshold, + minimal_stake ) ), ( ( minimal_frozen_stake, vdf_difficulty, origination_size, @@ -535,6 +610,7 @@ let encoding = quorum_min ), ( ( quorum_max, min_proposal_quorum, + liquidity_baking_subsidy, liquidity_baking_toggle_ema_threshold, max_operations_time_to_live, minimal_block_delay, @@ -545,18 +621,24 @@ let encoding = limit_of_delegation_over_baking, percentage_of_frozen_deposits_slashed_per_double_baking, percentage_of_frozen_deposits_slashed_per_double_attestation, + max_slashing_per_block, + max_slashing_threshold, testnet_dictator, initial_seed ), ( ( cache_script_size, cache_stake_distribution_cycles, cache_sampler_state_cycles ), - (dal, ((sc_rollup, zk_rollup), adaptive_issuance)) ) ) ) ) ) -> + ( dal, + ( (sc_rollup, zk_rollup), + (adaptive_issuance, direct_ticket_spending_enable) ) ) ) + ) ) ) ) -> { - preserved_cycles; + consensus_rights_delay; + blocks_preservation_cycles; + delegate_parameters_activation_delay; blocks_per_cycle; blocks_per_commitment; nonce_revelation_threshold; - blocks_per_stake_snapshot; cycles_per_voting_period; hard_gas_limit_per_operation; hard_gas_limit_per_block; @@ -571,6 +653,7 @@ let encoding = quorum_min; quorum_max; min_proposal_quorum; + liquidity_baking_subsidy; liquidity_baking_toggle_ema_threshold; max_operations_time_to_live; minimal_block_delay; @@ -581,6 +664,8 @@ let encoding = limit_of_delegation_over_baking; percentage_of_frozen_deposits_slashed_per_double_baking; percentage_of_frozen_deposits_slashed_per_double_attestation; + max_slashing_per_block; + max_slashing_threshold; testnet_dictator; initial_seed; cache_script_size; @@ -590,23 +675,27 @@ let encoding = sc_rollup; zk_rollup; adaptive_issuance; + direct_ticket_spending_enable; }) (merge_objs - (obj10 - (req "preserved_cycles" uint8) - (req "blocks_per_cycle" int32) - (req "blocks_per_commitment" int32) - (req "nonce_revelation_threshold" int32) - (req "blocks_per_stake_snapshot" int32) - (req "cycles_per_voting_period" int32) - (req - "hard_gas_limit_per_operation" - Gas_limit_repr.Arith.z_integral_encoding) - (req - "hard_gas_limit_per_block" - Gas_limit_repr.Arith.z_integral_encoding) - (req "proof_of_work_threshold" int64) - (req "minimal_stake" Tez_repr.encoding)) + (merge_objs + (obj3 + (req "consensus_rights_delay" uint8) + (req "blocks_preservation_cycles" uint8) + (req "delegate_parameters_activation_delay" uint8)) + (obj8 + (req "blocks_per_cycle" int32) + (req "blocks_per_commitment" int32) + (req "nonce_revelation_threshold" int32) + (req "cycles_per_voting_period" int32) + (req + "hard_gas_limit_per_operation" + Gas_limit_repr.Arith.z_integral_encoding) + (req + "hard_gas_limit_per_block" + Gas_limit_repr.Arith.z_integral_encoding) + (req "proof_of_work_threshold" int64) + (req "minimal_stake" Tez_repr.encoding))) (merge_objs (obj7 (req "minimal_frozen_stake" Tez_repr.encoding) @@ -617,9 +706,10 @@ let encoding = (req "hard_storage_limit_per_operation" z) (req "quorum_min" int32)) (merge_objs - (obj8 + (obj9 (req "quorum_max" int32) (req "min_proposal_quorum" int32) + (req "liquidity_baking_subsidy" Tez_repr.encoding) (req "liquidity_baking_toggle_ema_threshold" int32) (req "max_operations_time_to_live" int16) (req "minimal_block_delay" Period_repr.encoding) @@ -627,15 +717,17 @@ let encoding = (req "consensus_committee_size" int31) (req "consensus_threshold" int31)) (merge_objs - (obj6 + (obj8 (req "minimal_participation_ratio" Ratio_repr.encoding) (req "limit_of_delegation_over_baking" uint8) (req "percentage_of_frozen_deposits_slashed_per_double_baking" - Percentage.encoding_legacy_in_o) + Percentage.encoding) (req "percentage_of_frozen_deposits_slashed_per_double_attestation" - Percentage.encoding_legacy_in_o) + Percentage.encoding) + (req "max_slashing_per_block" Percentage.encoding) + (req "max_slashing_threshold" int31) (opt "testnet_dictator" Signature.Public_key_hash.encoding) (opt "initial_seed" State_hash.encoding)) (merge_objs @@ -647,4 +739,23 @@ let encoding = (obj1 (req "dal_parametric" dal_encoding)) (merge_objs (merge_objs sc_rollup_encoding zk_rollup_encoding) - adaptive_issuance_encoding))))))) + (merge_objs + adaptive_issuance_encoding + (obj1 (req "direct_ticket_spending_enable" bool)))))))))) + +let update_sc_rollup_parameter ~block_time c = + let seconds_in_a_day = 60 * 60 * 24 in + let seconds_in_a_week = seconds_in_a_day * 7 in + { + c with + challenge_window_in_blocks = seconds_in_a_week * 2 / block_time; + (* Same as challenge_window_in_blocks *) + max_active_outbox_levels = Int32.of_int (seconds_in_a_week * 2 / block_time); + commitment_period_in_blocks = 60 * 15 / block_time; + max_lookahead_in_blocks = Int32.of_int (seconds_in_a_day * 30 / block_time); + timeout_period_in_blocks = seconds_in_a_week / block_time; + } + +module Internal_for_tests = struct + let sc_rollup_encoding = sc_rollup_encoding +end diff --git a/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli index 3dc580b00222..37cf9a2168f2 100644 --- a/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli +++ b/src/proto_020_PsParisC/lib_protocol/constants_parametric_previous_repr.mli @@ -27,10 +27,10 @@ type dal = { feature_enable : bool; + incentives_enable : bool; number_of_slots : int; attestation_lag : int; attestation_threshold : int; - blocks_per_epoch : int32; cryptobox_parameters : Dal.parameters; } @@ -44,6 +44,7 @@ type sc_rollup_reveal_activation_level = { metadata : Raw_level_repr.t; dal_page : Raw_level_repr.t; dal_parameters : Raw_level_repr.t; + dal_attested_slots_validity_lag : int; } type sc_rollup = { @@ -107,8 +108,20 @@ type zk_rollup = { } type adaptive_rewards_params = { - issuance_ratio_min : (* Maximum yearly issuance rate *) Q.t; - issuance_ratio_max : (* Minimum yearly issuance rate *) Q.t; + issuance_ratio_final_min : (* Minimum yearly issuance rate *) Q.t; + issuance_ratio_final_max : (* Maximum yearly issuance rate *) Q.t; + issuance_ratio_initial_min : + (* Minimum yearly issuance rate at adaptive issuance activation *) Q.t; + issuance_ratio_initial_max : + (* Maximum yearly issuance rate at adaptive issuance activation *) Q.t; + initial_period : + (* Period in cycles during which the minimum and maximum yearly + issuance rate values stay at their initial values *) + int; + transition_period : + (* Period in cycles during which the minimum and maximum yearly + issuance rate values decrease/increase until they reach their global values *) + int; max_bonus : (* Maximum issuance bonus value *) Issuance_bonus_repr.max_bonus; growth_rate : (* Bonus value's growth rate *) Q.t; center_dz : (* Center for bonus *) Q.t; @@ -134,6 +147,12 @@ type adaptive_issuance = { (* If set to true, a stake/unstake/finalize operation will be triggered for all delegate at end of cycle. *) bool; + force_activation : + (* For testing purposes. If set to true, the adaptive issuance feature is + enabled without waiting to reach the launch_ema_threshold.*) + bool; + ns_enable : (* If set to true, enables the NS feature *) + bool; } type issuance_weights = { @@ -147,17 +166,23 @@ type issuance_weights = { baking_reward_fixed_portion_weight : int; baking_reward_bonus_weight : int; attesting_reward_weight : int; - liquidity_baking_subsidy_weight : int; seed_nonce_revelation_tip_weight : int; vdf_revelation_tip_weight : int; } type t = { - preserved_cycles : int; + (* Number of cycles after which computed consensus rights are used to actually + participate in the consensus *) + consensus_rights_delay : int; + (* Number of past cycles about which the protocol hints the shell that it should + keep them in its history. *) + blocks_preservation_cycles : int; + (* Number of cycles after which submitted delegate parameters are being + used. *) + delegate_parameters_activation_delay : int; blocks_per_cycle : int32; blocks_per_commitment : int32; nonce_revelation_threshold : int32; - blocks_per_stake_snapshot : int32; cycles_per_voting_period : int32; hard_gas_limit_per_operation : Gas_limit_repr.Arith.integral; hard_gas_limit_per_block : Gas_limit_repr.Arith.integral; @@ -173,6 +198,7 @@ type t = { (* in centile of a percentage *) quorum_max : int32; min_proposal_quorum : int32; + liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_toggle_ema_threshold : int32; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; @@ -186,6 +212,8 @@ type t = { (* upper bound on the (delegated tz / own frozen tz) ratio *) percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; cache_script_size : int; @@ -198,6 +226,13 @@ type t = { sc_rollup : sc_rollup; zk_rollup : zk_rollup; adaptive_issuance : adaptive_issuance; + direct_ticket_spending_enable : bool; } val encoding : t Data_encoding.encoding + +val update_sc_rollup_parameter : block_time:int -> sc_rollup -> sc_rollup + +module Internal_for_tests : sig + val sc_rollup_encoding : sc_rollup Data_encoding.t +end diff --git a/src/proto_020_PsParisC/lib_protocol/constants_repr.ml b/src/proto_020_PsParisC/lib_protocol/constants_repr.ml index e483b98dd5d8..9a1a0bead163 100644 --- a/src/proto_020_PsParisC/lib_protocol/constants_repr.ml +++ b/src/proto_020_PsParisC/lib_protocol/constants_repr.ml @@ -24,12 +24,14 @@ (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) -let version_value = "paris_019" +let version_value = "paris_020" let version = "v1" let mainnet_id = Chain_id.of_b58check_exn "NetXdQprcVkpaWU" +let ghostnet_id = Chain_id.of_b58check_exn "NetXnHfVqm9iesp" + (* The fitness version number was: - "\000" until and including proto 004 - "\001" until and including proto 010 diff --git a/src/proto_020_PsParisC/lib_protocol/constants_repr.mli b/src/proto_020_PsParisC/lib_protocol/constants_repr.mli index 29e20a85e38f..2c1f02700218 100644 --- a/src/proto_020_PsParisC/lib_protocol/constants_repr.mli +++ b/src/proto_020_PsParisC/lib_protocol/constants_repr.mli @@ -30,6 +30,8 @@ val version : string val mainnet_id : Chain_id.t +val ghostnet_id : Chain_id.t + val fitness_version_number : string val proof_of_work_nonce_size : int diff --git a/src/proto_020_PsParisC/lib_protocol/dune b/src/proto_020_PsParisC/lib_protocol/dune index 97bb137338e8..9406d4f624eb 100644 --- a/src/proto_020_PsParisC/lib_protocol/dune +++ b/src/proto_020_PsParisC/lib_protocol/dune @@ -218,8 +218,8 @@ Sc_rollup_commitment_storage Sc_rollup_outbox_storage Sc_rollup_whitelist_storage - Sc_rollup_stake_storage Sc_rollup_storage + Sc_rollup_stake_storage Dal_slot_storage Sc_rollup_refutation_storage Zk_rollup_errors @@ -518,8 +518,8 @@ sc_rollup_commitment_storage.ml sc_rollup_commitment_storage.mli sc_rollup_outbox_storage.ml sc_rollup_outbox_storage.mli sc_rollup_whitelist_storage.ml sc_rollup_whitelist_storage.mli - sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli sc_rollup_storage.ml sc_rollup_storage.mli + sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli dal_slot_storage.ml dal_slot_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml @@ -819,8 +819,8 @@ sc_rollup_commitment_storage.ml sc_rollup_commitment_storage.mli sc_rollup_outbox_storage.ml sc_rollup_outbox_storage.mli sc_rollup_whitelist_storage.ml sc_rollup_whitelist_storage.mli - sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli sc_rollup_storage.ml sc_rollup_storage.mli + sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli dal_slot_storage.ml dal_slot_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml @@ -1104,8 +1104,8 @@ sc_rollup_commitment_storage.ml sc_rollup_commitment_storage.mli sc_rollup_outbox_storage.ml sc_rollup_outbox_storage.mli sc_rollup_whitelist_storage.ml sc_rollup_whitelist_storage.mli - sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli sc_rollup_storage.ml sc_rollup_storage.mli + sc_rollup_stake_storage.ml sc_rollup_stake_storage.mli dal_slot_storage.ml dal_slot_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml diff --git a/src/proto_020_PsParisC/lib_protocol/init_storage.ml b/src/proto_020_PsParisC/lib_protocol/init_storage.ml index 020f518cf36d..5256f51f09e8 100644 --- a/src/proto_020_PsParisC/lib_protocol/init_storage.ml +++ b/src/proto_020_PsParisC/lib_protocol/init_storage.ml @@ -109,143 +109,10 @@ let patch_script ctxt (address, hash, patched_code) = address ; return ctxt -let migrate_already_denounced_from_Oxford ctxt = - let open Lwt_syntax in - let migrate_cycle ctxt cycle = - let* ctxt = - Storage.Already_denounced__Oxford.fold - (ctxt, cycle) - ~order:`Undefined - ~init:ctxt - ~f:(fun (level, delegate) {for_double_attesting; for_double_baking} ctxt - -> - Storage.Already_denounced.add - (ctxt, cycle) - ((level, Round_repr.zero), delegate) - { - for_double_preattesting = for_double_attesting; - for_double_attesting; - for_double_baking; - }) - in - Storage.Already_denounced__Oxford.clear (ctxt, cycle) - in - (* Since the max_slashing_period is 2, denunciations are only - relevant if the misbehaviour happened in either the current cycle - or the previous cycle. *) - let current_cycle = (Level_storage.current ctxt).cycle in - let* ctxt = migrate_cycle ctxt current_cycle in - match Cycle_repr.pred current_cycle with - | None -> return ctxt - | Some previous_cycle -> migrate_cycle ctxt previous_cycle - -(* This removes snapshots and moves the current [staking_balance] one level - up. Same thing for active delegates with minimal stake but renames the key - at the same time. *) -let migrate_staking_balance_and_active_delegates_for_p ctxt = - let open Lwt_result_syntax in - let* staking_balance_tree = - Raw_context.get_tree ctxt ["staking_balance"; "current"] - in - let*! ctxt = - Raw_context.add_tree ctxt ["staking_balance"] staking_balance_tree - in - let* active_delegates_tree = - Raw_context.get_tree ctxt ["active_delegate_with_one_roll"; "current"] - in - let*! ctxt = Raw_context.remove ctxt ["active_delegate_with_one_roll"] in - let*! ctxt = - Raw_context.add_tree - ctxt - ["active_delegates_with_minimal_stake"] - active_delegates_tree - in - return ctxt - -(* This should clean most of the remaining fields [frozen_deposits]. - The field was removed in Oxford but cleaning it using [remove] was too - costly as it iterated over all contracts. - Instead we iterate over activate delegates. - If there are remaining [frozen_deposits] once P activates, they can still be - removed one by one in Q. *) -let clean_frozen_deposits_for_p ctxt = - let open Lwt_result_syntax in - let contracts_index = ["contracts"; "index"] in - let* contracts_tree = Raw_context.get_tree ctxt contracts_index in - let field = ["frozen_deposits"] in - let*! contracts_tree = - Storage.Stake.Active_delegates_with_minimal_stake.fold - ctxt - ~order:`Undefined - ~init:contracts_tree - ~f:(fun pkh contracts_tree -> - let path = Contract_repr.Index.to_path (Implicit pkh) field in - Raw_context.Tree.remove contracts_tree path) - in - Raw_context.update_tree ctxt contracts_index contracts_tree - -let cleanup_values_for_protocol_p ctxt - (previous_proto_constants : Constants_parametric_previous_repr.t option) - level = - let open Lwt_result_syntax in - let preserved_cycles = - let previous_proto_constants = - match previous_proto_constants with - | None -> - (* Shouldn't happen *) - failwith - "Internal error: cannot read previous protocol constants in \ - context." - | Some c -> c - in - previous_proto_constants.preserved_cycles - in - let consensus_rights_delay = Constants_storage.consensus_rights_delay ctxt in - let new_cycle = - let next_level = Raw_level_repr.succ level in - let cycle_eras = Raw_context.cycle_eras ctxt in - (Level_repr.level_from_raw ~cycle_eras next_level).cycle - in - let* ctxt = - Stake_storage.cleanup_values_for_protocol_p - ctxt - ~preserved_cycles - ~consensus_rights_delay - ~new_cycle - in - let* ctxt = - Delegate_sampler.cleanup_values_for_protocol_p - ctxt - ~preserved_cycles - ~consensus_rights_delay - ~new_cycle - in - return ctxt - -let reset_adaptive_issuance_ema_for_p ctxt = - Storage.Adaptive_issuance.Launch_ema.add ctxt 0l - -(** Updates the total supply with refined estimation at the activation - of P using measures from - https://gitlab.com/tezos/tezos/-/merge_requests/11978. - - Remove me in Q. *) -let update_total_supply_for_p chain_id ctxt = - let open Lwt_result_syntax in - (* We only update the total supply for mainnet. *) - if Chain_id.equal Constants_repr.mainnet_id chain_id then - let* current_total_supply = Storage.Contract.Total_supply.get ctxt in - let*? updated_total_supply = - Tez_repr.(current_total_supply +? of_mutez_exn 16458634911983L) - in - let*! ctxt = Storage.Contract.Total_supply.add ctxt updated_total_supply in - return ctxt - else return ctxt - let prepare_first_block chain_id ctxt ~typecheck_smart_contract ~typecheck_smart_rollup ~level ~timestamp ~predecessor = let open Lwt_result_syntax in - let* previous_protocol, previous_proto_constants, ctxt = + let* previous_protocol, _previous_proto_constants, ctxt = Raw_context.prepare_first_block ~level ~timestamp chain_id ctxt in let parametric = Raw_context.constants ctxt in @@ -316,14 +183,18 @@ let prepare_first_block chain_id ctxt ~typecheck_smart_contract in let* ctxt = Sc_rollup_inbox_storage.init_inbox ~predecessor ctxt in let* ctxt = Adaptive_issuance_storage.init ctxt in + + (* TODO: Remove this for Q, and fallback to use the previous constants + and [Tenderbake.First_level_of_protocol] *) + let*! ctxt = + Storage.Sc_rollup.Parisb2_activation_level.add + ctxt + Raw_level_repr.root + in + let*! ctxt = Sc_rollup_storage.set_previous_commitment_period ctxt 1 in + return (ctxt, commitments_balance_updates @ bootstrap_balance_updates) - | Oxford_018 - (* Please update [next_protocol] and [previous_protocol] in - [tezt/lib_tezos/protocol.ml] when you update this value. *) -> - (* TODO (#2704): possibly handle attestations for migration block (in bakers); - if that is done, do not set Storage.Tenderbake.First_level_of_protocol. - /!\ this storage is also use to add the smart rollup - inbox migration message. see `sc_rollup_inbox_storage`. *) + | ParisB_019 -> let*? level = Raw_level_repr.of_int32 level in let* ctxt = Storage.Tenderbake.First_level_of_protocol.update ctxt level @@ -332,22 +203,37 @@ let prepare_first_block chain_id ctxt ~typecheck_smart_contract let* ctxt = Sc_rollup_refutation_storage.migrate_clean_refutation_games ctxt in - (* Adaptive Issuance-related migrations from Oxford to P. *) - (* We usually clear the table at the end of the cycle but the migration - can happen in the middle of the cycle, so we clear it here. - Possible consequence: the slashing history could be inconsistent with - the pending denunciations, i.e., there could be unstaked_frozen_deposits - that are not slashed whereas unstake_requests are slashed. *) - let*! ctxt = Pending_denunciations_storage.clear ctxt in - let*! ctxt = migrate_already_denounced_from_Oxford ctxt in - let* ctxt = migrate_staking_balance_and_active_delegates_for_p ctxt in - let* ctxt = clean_frozen_deposits_for_p ctxt in - let*! ctxt = Raw_context.remove ctxt ["last_snapshot"] in - let* ctxt = - cleanup_values_for_protocol_p ctxt previous_proto_constants level + + (* TODO: Remove this for Q, and fallback to use the previous constants + and [Tenderbake.First_level_of_protocol]. + + We need to hard-code Oxford2 values, because they are the one of + interest, not ParisB2’s. *) + let parisb2_activation_level, previous_commitment_period = + if Chain_id.(chain_id = Constants_repr.mainnet_id) then + (Raw_level_repr.of_int32_exn 5726209l, 60) + else if Chain_id.(chain_id = Constants_repr.ghostnet_id) then + (Raw_level_repr.of_int32_exn 6422529l, 60) + else + (* Setting [paris2b_activation_level = Raw_level_repr.root] ensures + that we will never consider an uncemented commitment as posted + during the previous protocol. *) + (Raw_level_repr.root, 1) in - let* ctxt = update_total_supply_for_p chain_id ctxt in - let*! ctxt = reset_adaptive_issuance_ema_for_p ctxt in + (* Remember the previous commitment period value, in order to deal with + commitments posted during previous protocol but not yet cemented + when this protocol was activated. *) + let*! ctxt = + Sc_rollup_storage.set_previous_commitment_period + ctxt + previous_commitment_period + in + let*! ctxt = + Storage.Sc_rollup.Parisb2_activation_level.add + ctxt + parisb2_activation_level + in + return (ctxt, []) in let* ctxt = diff --git a/src/proto_020_PsParisC/lib_protocol/raw_context.ml b/src/proto_020_PsParisC/lib_protocol/raw_context.ml index 80b457124f2f..1cd256977eec 100644 --- a/src/proto_020_PsParisC/lib_protocol/raw_context.ml +++ b/src/proto_020_PsParisC/lib_protocol/raw_context.ml @@ -881,7 +881,7 @@ let prepare ~level ~predecessor_timestamp ~timestamp ~adaptive_issuance_enable }; } -type previous_protocol = Genesis of Parameters_repr.t | Oxford_018 +type previous_protocol = Genesis of Parameters_repr.t | ParisB_019 let check_and_update_protocol_version ctxt = let open Lwt_result_syntax in @@ -897,7 +897,7 @@ let check_and_update_protocol_version ctxt = else if Compare.String.(s = "genesis") then let+ param, ctxt = get_proto_param ctxt in (Genesis param, ctxt) - else if Compare.String.(s = "oxford_018") then return (Oxford_018, ctxt) + else if Compare.String.(s = "paris_019") then return (ParisB_019, ctxt) else Lwt.return @@ storage_error (Incompatible_protocol_version s) in let*! ctxt = @@ -925,66 +925,6 @@ let[@warning "-32"] get_previous_protocol_constants ctxt = context." | Some constants -> return constants) -let update_block_time_related_constants (c : Constants_parametric_repr.t) = - let divide_period p = - Period_repr.of_seconds_exn - Int64.(div (mul (Period_repr.to_seconds p) 2L) 3L) - in - let minimal_block_delay = divide_period c.minimal_block_delay in - let delay_increment_per_round = divide_period c.delay_increment_per_round in - let hard_gas_limit_per_block = - let two = Z.(succ one) in - let three = Z.(succ two) in - Gas_limit_repr.Arith.( - integral_exn - (Z.div (Z.mul (integral_to_z c.hard_gas_limit_per_block) two) three)) - in - let half_more x = Int32.(div (mul 3l x) 2l) in - let blocks_per_cycle = half_more c.blocks_per_cycle in - let blocks_per_commitment = half_more c.blocks_per_commitment in - let nonce_revelation_threshold = half_more c.nonce_revelation_threshold in - let max_operations_time_to_live = 3 * c.max_operations_time_to_live / 2 in - let block_time = Int64.to_int (Period_repr.to_seconds minimal_block_delay) in - let sc_rollup = - Constants_parametric_repr.update_sc_rollup_parameter c.sc_rollup ~block_time - in - { - c with - sc_rollup; - blocks_per_cycle; - blocks_per_commitment; - nonce_revelation_threshold; - max_operations_time_to_live; - minimal_block_delay; - delay_increment_per_round; - hard_gas_limit_per_block; - } - -let update_cycle_eras ctxt level ~prev_blocks_per_cycle ~blocks_per_cycle - ~blocks_per_commitment = - let open Lwt_result_syntax in - let* cycle_eras = get_cycle_eras ctxt in - let current_era = Level_repr.current_era cycle_eras in - let current_cycle = - let level_position = - Int32.sub level (Raw_level_repr.to_int32 current_era.first_level) - in - Cycle_repr.add - current_era.first_cycle - (Int32.to_int (Int32.div level_position prev_blocks_per_cycle)) - in - let new_cycle_era = - Level_repr. - { - first_level = Raw_level_repr.of_int32_exn (Int32.succ level); - first_cycle = Cycle_repr.succ current_cycle; - blocks_per_cycle; - blocks_per_commitment; - } - in - let*? new_cycle_eras = Level_repr.add_cycle_era new_cycle_era cycle_eras in - set_cycle_eras ctxt new_cycle_eras - (* You should ensure that if the type `Constants_parametric_repr.t` is different from `Constants_parametric_previous_repr.t` or the value of these constants is modified, is changed from the previous protocol, then @@ -1015,204 +955,182 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = let* ctxt = set_cycle_eras ctxt cycle_eras in let*! result = add_constants ctxt param.constants in return (result, None) - | Oxford_018 -> + | ParisB_019 -> let*! c = get_previous_protocol_constants ctxt in - - (* When modifying the line below, be careful that the values are - compatible with the encodings exported by the environment did not - change. *) - let cryptobox_parameters = - { - Dal.page_size = 3967; - slot_size = 126_944; - redundancy_factor = 8; - number_of_shards = 512; - } - in let dal = + let Constants_parametric_previous_repr. + { + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; + cryptobox_parameters; + } = + c.dal + in Constants_parametric_repr. { - feature_enable = true; - incentives_enable = false; - number_of_slots = 32; - attestation_lag = 8; - attestation_threshold = 66; + feature_enable; + incentives_enable; + number_of_slots; + attestation_lag; + attestation_threshold; cryptobox_parameters; } in - (* This test prevents the activation of the protocol if the - set of parameters given for the DAL is invalid. *) - let*? () = - match Dal.make cryptobox_parameters with - | Ok _cryptobox -> ok () - | Error (`Fail explanation) -> - error (Dal_errors_repr.Dal_cryptobox_error {explanation}) - in - let dal_activation_level = - if c.dal.feature_enable then - (* if dal was enable in previous protocol, do as if it were always - activated *) - Raw_level_repr.succ Raw_level_repr.root - else - (* dal activates at first level of the new protocol. *) - Raw_level_repr.of_int32_exn (Int32.succ level) - in - let dal_attested_slots_validity_lag = - (* A rollup node shouldn't import a page of an attested slot whose attested - level is too far in the past w.r.t. the current level. Importation window - is fixed to 241_920 levels below. It is the number of blocks produced - during 28 days (4 weeks) with a block time of 10 seconds. *) - 241_920 - in - let reveal_activation_level : - Constants_parametric_repr.sc_rollup_reveal_activation_level = - let ({ - raw_data = {blake2B}; - metadata; - dal_page = _; - dal_parameters = _; - } - : Constants_parametric_previous_repr - .sc_rollup_reveal_activation_level) = - c.sc_rollup.reveal_activation_level - in - { - raw_data = {blake2B}; - metadata; - dal_page = dal_activation_level; - dal_parameters = dal_activation_level; - (* Warning: the semantics of valid slots needs to be adapted if the - value of this parameter is changed in the future. - - If it is increased, some attested slots that were outdated with - the old value will become valid again. - - If it is decreased, some attested slots that were valid with - the old value will become outdated. - - In both cases, the status of slots before and after the value - change is different. So, the behaviour if a valid slot is - imported before the value upgrade but a refutation game - targetting a page of that slot is started after the upgrade is - not the correct/expected one. *) - dal_attested_slots_validity_lag; - } - in let sc_rollup = + let Constants_parametric_previous_repr. + { + arith_pvm_enable; + origination_size; + challenge_window_in_blocks; + stake_amount; + commitment_period_in_blocks; + max_lookahead_in_blocks; + max_active_outbox_levels; + max_outbox_messages_per_level; + number_of_sections_in_dissection; + timeout_period_in_blocks; + max_number_of_stored_cemented_commitments; + max_number_of_parallel_games; + reveal_activation_level = + { + raw_data = {blake2B}; + metadata; + dal_page; + dal_parameters; + dal_attested_slots_validity_lag; + }; + private_enable; + riscv_pvm_enable; + } = + c.sc_rollup + in Constants_parametric_repr. { - arith_pvm_enable = c.sc_rollup.arith_pvm_enable; - origination_size = c.sc_rollup.origination_size; - challenge_window_in_blocks = - c.sc_rollup.challenge_window_in_blocks; - stake_amount = c.sc_rollup.stake_amount; - commitment_period_in_blocks = - c.sc_rollup.commitment_period_in_blocks; - max_lookahead_in_blocks = c.sc_rollup.max_lookahead_in_blocks; - max_active_outbox_levels = c.sc_rollup.max_active_outbox_levels; - max_outbox_messages_per_level = - c.sc_rollup.max_outbox_messages_per_level; - number_of_sections_in_dissection = - c.sc_rollup.number_of_sections_in_dissection; - timeout_period_in_blocks = c.sc_rollup.timeout_period_in_blocks; - max_number_of_stored_cemented_commitments = - c.sc_rollup.max_number_of_stored_cemented_commitments; - max_number_of_parallel_games = - c.sc_rollup.max_number_of_parallel_games; - reveal_activation_level; - private_enable = c.sc_rollup.private_enable; - riscv_pvm_enable = c.sc_rollup.riscv_pvm_enable; + arith_pvm_enable; + origination_size; + challenge_window_in_blocks; + stake_amount; + commitment_period_in_blocks; + max_lookahead_in_blocks; + max_active_outbox_levels; + max_outbox_messages_per_level; + number_of_sections_in_dissection; + timeout_period_in_blocks; + max_number_of_stored_cemented_commitments; + max_number_of_parallel_games; + reveal_activation_level = + { + raw_data = {blake2B}; + metadata; + dal_page; + dal_parameters; + dal_attested_slots_validity_lag; + }; + private_enable; + riscv_pvm_enable; } in let zk_rollup = + let Constants_parametric_previous_repr. + { + enable; + origination_size; + min_pending_to_process; + max_ticket_payload_size; + } = + c.zk_rollup + in Constants_parametric_repr. { - enable = c.zk_rollup.enable; - origination_size = c.zk_rollup.origination_size; - min_pending_to_process = c.zk_rollup.min_pending_to_process; - max_ticket_payload_size = c.zk_rollup.max_ticket_payload_size; + enable; + origination_size; + min_pending_to_process; + max_ticket_payload_size; } in - let adaptive_rewards_params = - Constants_parametric_repr. - { - issuance_ratio_final_min = Q.(0_25 // 100_00); - (* 0.25% *) - issuance_ratio_final_max = Q.(10 // 100) (* 10% *); - issuance_ratio_initial_min = Q.(45 // 1000); - (* 4.5% *) - issuance_ratio_initial_max = Q.(55 // 1000); - (* 5.5% *) - initial_period = 10; - (* 1 month *) - transition_period = 50; - (* 5 months *) - max_bonus = c.adaptive_issuance.adaptive_rewards_params.max_bonus; - growth_rate = - c.adaptive_issuance.adaptive_rewards_params.growth_rate; - center_dz = c.adaptive_issuance.adaptive_rewards_params.center_dz; - radius_dz = c.adaptive_issuance.adaptive_rewards_params.radius_dz; - } - in let adaptive_issuance = + let Constants_parametric_previous_repr. + { + global_limit_of_staking_over_baking; + edge_of_staking_over_delegation; + launch_ema_threshold; + adaptive_rewards_params = + { + issuance_ratio_final_max; + issuance_ratio_final_min; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; + max_bonus; + growth_rate; + center_dz; + radius_dz; + }; + activation_vote_enable; + autostaking_enable; + force_activation; + ns_enable; + } = + c.adaptive_issuance + in Constants_parametric_repr. { - global_limit_of_staking_over_baking = - c.adaptive_issuance.global_limit_of_staking_over_baking; - edge_of_staking_over_delegation = - c.adaptive_issuance.edge_of_staking_over_delegation; - launch_ema_threshold = 0l; - adaptive_rewards_params; - activation_vote_enable = true; - autostaking_enable = c.adaptive_issuance.autostaking_enable; - force_activation = false; - ns_enable = true; + global_limit_of_staking_over_baking; + edge_of_staking_over_delegation; + launch_ema_threshold; + adaptive_rewards_params = + { + issuance_ratio_final_max; + issuance_ratio_final_min; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; + max_bonus; + growth_rate; + center_dz; + radius_dz; + }; + activation_vote_enable; + autostaking_enable; + force_activation; + ns_enable; } in - let liquidity_baking_subsidy = Tez_repr.(mul_exn one 5) in let (issuance_weights : Constants_parametric_repr.issuance_weights) = - let ({ - base_total_issued_per_minute; - baking_reward_fixed_portion_weight; - baking_reward_bonus_weight; - attesting_reward_weight; - liquidity_baking_subsidy_weight = _; - seed_nonce_revelation_tip_weight; - vdf_revelation_tip_weight; - } - : Constants_parametric_previous_repr.issuance_weights) = + let Constants_parametric_previous_repr. + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } = c.issuance_weights in - let base_total_issued_per_minute = - let x = - Tez_repr.( - sub_opt base_total_issued_per_minute liquidity_baking_subsidy) - in - match x with None -> assert false | Some x -> x - in - { - base_total_issued_per_minute; - baking_reward_fixed_portion_weight; - baking_reward_bonus_weight; - attesting_reward_weight; - seed_nonce_revelation_tip_weight; - vdf_revelation_tip_weight; - } - in - let direct_ticket_spending_enable = false in - let consensus_rights_delay = - (* We change the consensus_rights_delay value only for mainnet *) - if Compare.Int.(c.preserved_cycles = 5) then 2 else c.preserved_cycles - in - let Constants_repr.Generated.{max_slashing_threshold; _} = - Constants_repr.Generated.generate - ~consensus_committee_size:c.consensus_committee_size + Constants_parametric_repr. + { + base_total_issued_per_minute; + baking_reward_fixed_portion_weight; + baking_reward_bonus_weight; + attesting_reward_weight; + seed_nonce_revelation_tip_weight; + vdf_revelation_tip_weight; + } in let constants = Constants_parametric_repr. { - consensus_rights_delay; - blocks_preservation_cycles = 1; - delegate_parameters_activation_delay = c.preserved_cycles; + consensus_rights_delay = c.consensus_rights_delay; + blocks_preservation_cycles = c.blocks_preservation_cycles; + delegate_parameters_activation_delay = + c.delegate_parameters_activation_delay; blocks_per_cycle = c.blocks_per_cycle; blocks_per_commitment = c.blocks_per_commitment; nonce_revelation_threshold = c.nonce_revelation_threshold; @@ -1232,7 +1150,7 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = quorum_min = c.quorum_min; quorum_max = c.quorum_max; min_proposal_quorum = c.min_proposal_quorum; - liquidity_baking_subsidy; + liquidity_baking_subsidy = c.liquidity_baking_subsidy; liquidity_baking_toggle_ema_threshold = c.liquidity_baking_toggle_ema_threshold; minimal_block_delay = c.minimal_block_delay; @@ -1243,13 +1161,11 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = limit_of_delegation_over_baking = c.limit_of_delegation_over_baking; percentage_of_frozen_deposits_slashed_per_double_baking = - Percentage.convert_from_o_to_p - c.percentage_of_frozen_deposits_slashed_per_double_baking; + c.percentage_of_frozen_deposits_slashed_per_double_baking; percentage_of_frozen_deposits_slashed_per_double_attestation = - Percentage.convert_from_o_to_p - c.percentage_of_frozen_deposits_slashed_per_double_attestation; - max_slashing_per_block = Percentage.p100; - max_slashing_threshold; + c.percentage_of_frozen_deposits_slashed_per_double_attestation; + max_slashing_per_block = c.max_slashing_per_block; + max_slashing_threshold = c.max_slashing_threshold; (* The `testnet_dictator` should absolutely be None on mainnet *) testnet_dictator = c.testnet_dictator; initial_seed = c.initial_seed; @@ -1261,31 +1177,9 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = sc_rollup; zk_rollup; adaptive_issuance; - direct_ticket_spending_enable; + direct_ticket_spending_enable = c.direct_ticket_spending_enable; } in - let block_time_is_at_least_8s = - (* This check is used to trigger the constants changes at migration on - this protocol for network that have block time strictly greater - than 7s such as mainnet and ghostnet *) - Compare.Int64.(Period_repr.to_seconds c.minimal_block_delay >= 8L) - in - let* ctxt, constants = - if block_time_is_at_least_8s then - let new_constants : Constants_parametric_repr.t = - update_block_time_related_constants constants - in - let* ctxt = - update_cycle_eras - ctxt - level - ~prev_blocks_per_cycle:constants.blocks_per_cycle - ~blocks_per_cycle:new_constants.blocks_per_cycle - ~blocks_per_commitment:new_constants.blocks_per_commitment - in - return (ctxt, new_constants) - else return (ctxt, constants) - in let*! ctxt = add_constants ctxt constants in return (ctxt, Some c) in diff --git a/src/proto_020_PsParisC/lib_protocol/raw_context.mli b/src/proto_020_PsParisC/lib_protocol/raw_context.mli index 8ce1fbe2de04..1f34b498ba21 100644 --- a/src/proto_020_PsParisC/lib_protocol/raw_context.mli +++ b/src/proto_020_PsParisC/lib_protocol/raw_context.mli @@ -93,7 +93,7 @@ val prepare : Context.t -> t tzresult Lwt.t -type previous_protocol = Genesis of Parameters_repr.t | Oxford_018 +type previous_protocol = Genesis of Parameters_repr.t | ParisB_019 val prepare_first_block : level:int32 -> diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml index c25546aecb46..ec4f48e99924 100644 --- a/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_stake_storage.ml @@ -275,17 +275,27 @@ let assert_commitment_period ctxt rollup commitment = let* pred, ctxt = Commitment_storage.get_commitment_unsafe ctxt rollup pred_hash in + let* last_proto_activation_level, last_commitment_period = + Sc_rollup_storage.previous_protocol_constants ctxt + in let pred_level = Commitment.(pred.inbox_level) in (* Commitments needs to be posted for inbox levels every [commitment_period]. Therefore, [commitment.inbox_level] must be [predecessor_commitment.inbox_level + commitment_period]. *) - let sc_rollup_commitment_period = - Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + let last_proto_expected_level = + Raw_level_repr.(add pred_level last_commitment_period) + in + let expected_level = + if Raw_level_repr.(last_proto_expected_level < last_proto_activation_level) + then last_proto_expected_level + else + Raw_level_repr.add + pred_level + Constants_storage.(sc_rollup_commitment_period_in_blocks ctxt) in let* () = fail_unless - Raw_level_repr.( - commitment.inbox_level = add pred_level sc_rollup_commitment_period) + Raw_level_repr.(commitment.inbox_level = expected_level) Sc_rollup_bad_inbox_level in return ctxt @@ -761,11 +771,20 @@ let cement_commitment ctxt rollup = let* old_lcc, old_lcc_level, ctxt = Commitment_storage.last_cemented_commitment_hash_with_level ctxt rollup in - let sc_rollup_commitment_period = - Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + let* last_proto_activation_level, last_commitment_period = + Sc_rollup_storage.previous_protocol_constants ctxt + in + let new_lcc_previous_protocol = + Raw_level_repr.add old_lcc_level last_commitment_period in let new_lcc_level = - Raw_level_repr.add old_lcc_level sc_rollup_commitment_period + if Raw_level_repr.(new_lcc_previous_protocol < last_proto_activation_level) + then new_lcc_previous_protocol + else + let sc_rollup_commitment_period = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + Raw_level_repr.add old_lcc_level sc_rollup_commitment_period in (* Assert conditions to cement are met. *) let* ctxt, (new_lcc_commitment, new_lcc_commitment_hash), dangling_commitments diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml index fe875fc93483..98dc25507493 100644 --- a/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.ml @@ -224,3 +224,18 @@ let must_exist ctxt rollup = let open Lwt_result_syntax in let* ctxt, exists = Store.Genesis_info.mem ctxt rollup in if exists then return ctxt else tzfail (Sc_rollup_does_not_exist rollup) + +let set_previous_commitment_period ctxt value = + Storage.Sc_rollup.Previous_commitment_period.add ctxt value + +let previous_protocol_constants ctxt = + let open Lwt_result_syntax in + let* activation_level = + Storage.Sc_rollup.Parisb2_activation_level.find ctxt + in + let* previous_commitment_period = + Storage.Sc_rollup.Previous_commitment_period.get ctxt + in + return + ( Option.value ~default:Raw_level_repr.root activation_level, + previous_commitment_period ) diff --git a/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli index 8da1651e5a5b..f1a6f6632130 100644 --- a/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli +++ b/src/proto_020_PsParisC/lib_protocol/sc_rollup_storage.mli @@ -100,3 +100,22 @@ val parameters_type : returned. *) val must_exist : Raw_context.t -> Sc_rollup_repr.t -> Raw_context.t tzresult Lwt.t + +(** [set_previous_commitment_period ctxt previous_period] is expected to be + called during the protocol stitching, to ensure the previous commitment + period length remains available in the next protocol, in order to deal + with the commitments posted during the previous protocol but not yet + cemented. *) +val set_previous_commitment_period : Raw_context.t -> int -> Raw_context.t Lwt.t + +(** [previous_protocol_constants ctxt] fetches from [ctxt] the first level + of the current protocol and the previous commitment period. + + Both values are bounded in size and small, so we don’t carbonate the + call. + + {b Warning: b} This function requires that the previous commitment + period has been correctly set with {!set_previous_commitment_period} + during the latest stitching. *) +val previous_protocol_constants : + Raw_context.t -> (Raw_level_repr.t * int) tzresult Lwt.t diff --git a/src/proto_020_PsParisC/lib_protocol/storage.ml b/src/proto_020_PsParisC/lib_protocol/storage.ml index ad2b76ee94cb..b4720c6110b5 100644 --- a/src/proto_020_PsParisC/lib_protocol/storage.ml +++ b/src/proto_020_PsParisC/lib_protocol/storage.ml @@ -1821,6 +1821,26 @@ module Sc_rollup = struct add_or_remove ctxt key (Option.map Versioned_value.to_versioned value) end + (* TODO: To be removed in Q, to use [Tenderbake.First_level_of_protocol] + instead. *) + module Parisb2_activation_level = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["parisb2_activation_level"] + end) + (Raw_level_repr) + + module Previous_commitment_period = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["previous_commitment_period"] + end) + (struct + type t = int + + let encoding = Data_encoding.int31 + end) + module PVM_kind = Indexed_context.Make_carbonated_map (Registered) diff --git a/src/proto_020_PsParisC/lib_protocol/storage.mli b/src/proto_020_PsParisC/lib_protocol/storage.mli index 2b905fcce5e4..cb2733d5f964 100644 --- a/src/proto_020_PsParisC/lib_protocol/storage.mli +++ b/src/proto_020_PsParisC/lib_protocol/storage.mli @@ -844,6 +844,14 @@ module Sc_rollup : sig See module {!Sc_rollup_repr.Commitment} for details. *) + module Previous_commitment_period : + Single_data_storage with type value = int and type t := Raw_context.t + + module Parisb2_activation_level : + Single_data_storage + with type value = Raw_level_repr.t + and type t := Raw_context.t + module PVM_kind : Non_iterable_indexed_carbonated_data_storage with type key = Sc_rollup_repr.t -- GitLab From 62c12e1eb386cdae1e02915f6bca2795f1309e9d Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Thu, 13 Jun 2024 00:17:32 +0200 Subject: [PATCH 04/16] Manifest, ParisC: Link ParisC protocol --- client-libs/bin_codec_kaitai/dune | 4 + contrib/octez_injector_server/dune | 4 + devtools/get_contracts/dune | 2 + .../get_contracts_020_PsParisC.ml | 315 ++++++ devtools/testnet_experiment_tools/dune | 11 +- .../tool_020_PsParisC.ml | 994 ++++++++++++++++++ devtools/yes_wallet/dune | 1 + .../yes_wallet/get_delegates_020_PsParisC.ml | 125 +++ docs/doc_gen/dune | 1 + dune-project | 10 + manifest/product_octez.ml | 2 + opam/octez-accuser-PsParisC.opam | 23 + opam/octez-baker-PsParisC.opam | 23 + opam/octez-client.opam | 1 + opam/octez-codec-kaitai.opam | 1 + opam/octez-codec.opam | 2 + opam/octez-dac-client.opam | 1 + opam/octez-dac-node.opam | 1 + opam/octez-dal-node.opam | 1 + opam/octez-injector-server.opam | 2 + opam/octez-node.opam | 2 + opam/octez-protocol-020-PsParisC-libs.opam | 41 + opam/octez-proxy-server.opam | 2 + opam/octez-smart-rollup-node-PsParisC.opam | 39 + opam/octez-smart-rollup-node.opam | 1 + opam/tezos-benchmark-020-PsParisC.opam | 27 + ...benchmark-type-inference-020-PsParisC.opam | 24 + opam/tezos-benchmarks-proto-020-PsParisC.opam | 27 + opam/tezos-injector-020-PsParisC.opam | 24 + opam/tezos-protocol-020-PsParisC-tests.opam | 32 + opam/tezos-protocol-020-PsParisC.opam | 22 + opam/tezos-sc-rollup-node-test.opam | 3 + opam/tezos-smart-rollup-node-lib-test.opam | 1 + script-inputs/active_protocol_versions | 1 + .../active_protocol_versions_without_number | 1 + script-inputs/ci-opam-package-tests | 17 +- script-inputs/released-executables | 2 + src/bin_client/dune | 3 + src/bin_codec/dune | 4 + src/bin_dac_client/dune | 1 + src/bin_dac_node/dune | 1 + src/bin_dal_node/dune | 1 + src/bin_node/dune | 2 + src/bin_proxy_server/dune | 8 + src/bin_smart_rollup_node/dune | 1 + src/lib_smart_rollup_node/test/helpers/dune | 1 + src/proto_020_PsParisC/bin_accuser/dune | 18 +- src/proto_020_PsParisC/bin_baker/dune | 18 +- src/proto_020_PsParisC/lib_benchmark/dune | 18 +- .../lib_benchmark_type_inference/dune | 8 +- .../lib_benchmark_type_inference/test/dune | 12 +- .../lib_benchmark/test/dune | 16 +- .../lib_benchmarks_proto/dune | 34 +- src/proto_020_PsParisC/lib_client/dune | 24 +- src/proto_020_PsParisC/lib_client/test/dune | 14 +- .../lib_client_commands/dune | 48 +- .../lib_client_sapling/dune | 20 +- src/proto_020_PsParisC/lib_dac_plugin/dune | 16 +- .../lib_dac_plugin/test/dune | 18 +- src/proto_020_PsParisC/lib_dal/dune | 24 +- src/proto_020_PsParisC/lib_dal/test/dune | 18 +- src/proto_020_PsParisC/lib_delegate/dune | 60 +- src/proto_020_PsParisC/lib_delegate/test/dune | 24 +- .../lib_delegate/test/mockup_simulator/dune | 26 +- .../lib_delegate/test/tenderbrute/dune | 12 +- .../lib_delegate/test/tenderbrute/lib/dune | 12 +- src/proto_020_PsParisC/lib_injector/dune | 16 +- src/proto_020_PsParisC/lib_layer2_utils/dune | 12 +- src/proto_020_PsParisC/lib_parameters/dune | 18 +- src/proto_020_PsParisC/lib_plugin/dune | 26 +- src/proto_020_PsParisC/lib_plugin/index.mld | 26 +- src/proto_020_PsParisC/lib_plugin/test/dune | 24 +- src/proto_020_PsParisC/lib_protocol/dune | 56 +- .../lib_protocol/test/helpers/dune | 29 +- .../test/integration/consensus/dune | 22 +- .../lib_protocol/test/integration/dune | 30 +- .../lib_protocol/test/integration/gas/dune | 14 +- .../test/integration/michelson/dune | 32 +- .../test/integration/operations/dune | 22 +- .../test/integration/validate/dune | 26 +- .../lib_protocol/test/pbt/dune | 34 +- .../lib_protocol/test/regression/dune | 22 +- .../lib_protocol/test/unit/dune | 26 +- src/proto_020_PsParisC/lib_sc_rollup/dune | 8 +- .../lib_sc_rollup_layer2/dune | 8 +- .../lib_sc_rollup_node/dune | 40 +- .../lib_sc_rollup_node/test/dune | 16 +- tezt/tests/dune | 15 + 88 files changed, 2296 insertions(+), 478 deletions(-) create mode 100644 devtools/get_contracts/get_contracts_020_PsParisC.ml create mode 100644 devtools/testnet_experiment_tools/tool_020_PsParisC.ml create mode 100644 devtools/yes_wallet/get_delegates_020_PsParisC.ml create mode 100644 opam/octez-accuser-PsParisC.opam create mode 100644 opam/octez-baker-PsParisC.opam create mode 100644 opam/octez-protocol-020-PsParisC-libs.opam create mode 100644 opam/octez-smart-rollup-node-PsParisC.opam create mode 100644 opam/tezos-benchmark-020-PsParisC.opam create mode 100644 opam/tezos-benchmark-type-inference-020-PsParisC.opam create mode 100644 opam/tezos-benchmarks-proto-020-PsParisC.opam create mode 100644 opam/tezos-injector-020-PsParisC.opam create mode 100644 opam/tezos-protocol-020-PsParisC-tests.opam create mode 100644 opam/tezos-protocol-020-PsParisC.opam diff --git a/client-libs/bin_codec_kaitai/dune b/client-libs/bin_codec_kaitai/dune index f026818a76ee..f9507be36bc2 100644 --- a/client-libs/bin_codec_kaitai/dune +++ b/client-libs/bin_codec_kaitai/dune @@ -64,6 +64,9 @@ (select void_for_linking-octez-protocol-019-PtParisB-libs-client from (octez-protocol-019-PtParisB-libs.client -> void_for_linking-octez-protocol-019-PtParisB-libs-client.empty) (-> void_for_linking-octez-protocol-019-PtParisB-libs-client.empty)) + (select void_for_linking-octez-protocol-020-PsParisC-libs-client from + (octez-protocol-020-PsParisC-libs.client -> void_for_linking-octez-protocol-020-PsParisC-libs-client.empty) + (-> void_for_linking-octez-protocol-020-PsParisC-libs-client.empty)) (select void_for_linking-octez-protocol-alpha-libs-client from (octez-protocol-alpha-libs.client -> void_for_linking-octez-protocol-alpha-libs-client.empty) (-> void_for_linking-octez-protocol-alpha-libs-client.empty))) @@ -99,6 +102,7 @@ (write-file void_for_linking-octez-protocol-017-PtNairob-libs-client.empty "") (write-file void_for_linking-octez-protocol-018-Proxford-libs-client.empty "") (write-file void_for_linking-octez-protocol-019-PtParisB-libs-client.empty "") + (write-file void_for_linking-octez-protocol-020-PsParisC-libs-client.empty "") (write-file void_for_linking-octez-protocol-alpha-libs-client.empty "")))) (cram (deps codec.exe) (package octez-codec-kaitai)) diff --git a/contrib/octez_injector_server/dune b/contrib/octez_injector_server/dune index 439931514642..827b1bc9a220 100644 --- a/contrib/octez_injector_server/dune +++ b/contrib/octez_injector_server/dune @@ -21,6 +21,9 @@ (select void_for_linking-octez_injector_PtParisB from (octez_injector_PtParisB -> void_for_linking-octez_injector_PtParisB.empty) (-> void_for_linking-octez_injector_PtParisB.empty)) + (select void_for_linking-octez_injector_PsParisC from + (octez_injector_PsParisC -> void_for_linking-octez_injector_PsParisC.empty) + (-> void_for_linking-octez_injector_PsParisC.empty)) (select void_for_linking-octez_injector_alpha from (octez_injector_alpha -> void_for_linking-octez_injector_alpha.empty) (-> void_for_linking-octez_injector_alpha.empty))) @@ -44,4 +47,5 @@ (progn (write-file void_for_linking-octez_injector_Proxford.empty "") (write-file void_for_linking-octez_injector_PtParisB.empty "") + (write-file void_for_linking-octez_injector_PsParisC.empty "") (write-file void_for_linking-octez_injector_alpha.empty "")))) diff --git a/devtools/get_contracts/dune b/devtools/get_contracts/dune index a7066dfeb55b..ea038ce3c62b 100644 --- a/devtools/get_contracts/dune +++ b/devtools/get_contracts/dune @@ -11,6 +11,8 @@ octez-protocol-018-Proxford-libs.client tezos-protocol-019-PtParisB.protocol octez-protocol-019-PtParisB-libs.client + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client tezos-protocol-alpha.protocol octez-protocol-alpha-libs.client) (library_flags (:standard -linkall)) diff --git a/devtools/get_contracts/get_contracts_020_PsParisC.ml b/devtools/get_contracts/get_contracts_020_PsParisC.ml new file mode 100644 index 000000000000..7c6f960823d9 --- /dev/null +++ b/devtools/get_contracts/get_contracts_020_PsParisC.ml @@ -0,0 +1,315 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) +open Tezos_protocol_020_PsParisC +open Tezos_client_020_PsParisC +open Protocol + +module Proto = struct + let hash = hash + + let wrap_tzresult = Environment.wrap_tzresult + + module Context = struct + type t = Raw_context.t + + let prepare ~level ~predecessor_timestamp ~timestamp ctxt = + let open Lwt_result_syntax in + let+ ctxt = + Lwt.map wrap_tzresult + @@ Raw_context.prepare + ~level + ~predecessor_timestamp + ~timestamp + ~adaptive_issuance_enable:false + ctxt + in + Raw_context.set_gas_limit + ctxt + (Gas_limit_repr.fp_of_milligas_int (max_int - 1)) + end + + type context = Context.t + + module Contract = struct + type repr = Contract_repr.t + + let pp = Contract_repr.pp + + let is_implicit = function + | Contract_repr.Implicit _ -> true + | Contract_repr.Originated _ -> false + + let get_code ctxt contract = + Lwt.map wrap_tzresult @@ Storage.Contract.Code.get ctxt contract + + let get_storage ctxt contract = + Lwt.map wrap_tzresult @@ Storage.Contract.Storage.get ctxt contract + + let fold ctxt ~init ~f = + Storage.Contract.fold ctxt ~order:`Undefined ~init ~f + end + + module Script = struct + include Alpha_context.Script + module Hash = Script_expr_hash + + let print_expr = Michelson_v1_printer.print_expr + + let decode_and_costs lazy_expr = + let open Result_syntax in + let decode_cost = Script_repr.stable_force_decode_cost lazy_expr in + let+ expr = wrap_tzresult @@ Script_repr.force_decode lazy_expr in + let encode_cost = + let decoded_lazy_expr = Script_repr.lazy_expr expr in + Script_repr.force_bytes_cost decoded_lazy_expr + in + (expr, (decode_cost :> int), (encode_cost :> int)) + end + + module Translator = struct + type toplevel = Script_ir_translator.toplevel + + type ('a, 'b) ty = ('a, 'b) Script_typed_ir.ty + + type ex_ty = Ex_ty : ('a, 'b) ty -> ex_ty + + type ex_code = Script_ir_translator.ex_code + + let expected_code_size Script_ir_translator.(Ex_code (Code {code_size; _})) + = + (code_size :> int) + + let actual_code_size Script_ir_translator.(Ex_code (Code {code; _})) = + 8 * Obj.(reachable_words @@ repr code) + + let parse_ty (raw_ctxt : Raw_context.t) ~allow_lazy_storage ~allow_operation + ~allow_contract ~allow_ticket script = + let open Result_syntax in + let ctxt : Alpha_context.context = Obj.magic raw_ctxt in + let+ Script_typed_ir.Ex_ty ty, updated_ctxt = + wrap_tzresult + @@ Script_ir_translator.parse_ty + ctxt + ~legacy:true + ~allow_lazy_storage + ~allow_operation + ~allow_contract + ~allow_ticket + script + in + let consumed = + (Alpha_context.Gas.consumed ~since:ctxt ~until:updated_ctxt :> int) + in + assert (consumed > 0) ; + (Ex_ty ty, consumed) + + let parse_data (raw_ctxt : Raw_context.t) ~allow_forged ty expr = + let open Lwt_result_syntax in + let ctxt : Alpha_context.context = Obj.magic raw_ctxt in + let+ data, updated_ctxt = + Lwt.map wrap_tzresult + @@ Script_ir_translator.parse_data + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ctxt + ~allow_forged_tickets:allow_forged + ~allow_forged_lazy_storage_id:allow_forged + ty + expr + in + let consumed = + (Alpha_context.Gas.consumed ~since:ctxt ~until:updated_ctxt :> int) + in + assert (consumed > 0) ; + (data, consumed) + + let unparse_data_cost (raw_ctxt : Raw_context.t) ty data = + let open Lwt_result_syntax in + let ctxt : Alpha_context.context = Obj.magic raw_ctxt in + let+ _expr, updated_ctxt = + Lwt.map wrap_tzresult + @@ Script_ir_translator.unparse_data + ctxt + Script_ir_unparser.Optimized + ty + data + in + let consumed = + (Alpha_context.Gas.consumed ~since:ctxt ~until:updated_ctxt :> int) + in + assert (consumed > 0) ; + consumed + + let unparse_ty (raw_ctxt : Raw_context.t) (Ex_ty ty) = + let open Result_syntax in + let ctxt : Alpha_context.context = Obj.magic raw_ctxt in + let+ expr, _ = + wrap_tzresult @@ Script_ir_unparser.unparse_ty ~loc:0 ctxt ty + in + expr + + let parse_toplevel (raw_ctxt : Raw_context.t) expr = + let open Lwt_result_syntax in + let ctxt : Alpha_context.context = Obj.magic raw_ctxt in + let+ toplevel, updated_ctxt = + Lwt.map wrap_tzresult @@ Script_ir_translator.parse_toplevel ctxt expr + in + let consumed = + (Alpha_context.Gas.consumed ~since:ctxt ~until:updated_ctxt :> int) + in + assert (consumed > 0) ; + (toplevel, consumed) + + let parse_code (raw_ctxt : Raw_context.t) code = + let open Lwt_result_syntax in + let ctxt : Alpha_context.context = Obj.magic raw_ctxt in + let+ parsed_code, _ = + Lwt.map wrap_tzresult + @@ Script_ir_translator.parse_code + ctxt + ~elab_conf:(Script_ir_translator_config.make ~legacy:true ()) + ~code + in + parsed_code + end + + module Storage = struct + type big_map_id = Storage.Big_map.id + + let id_to_z = Lazy_storage_kind.Big_map.Id.unparse_to_z + + let list_values ?offset ?length (ctxt, id) = + let open Lwt_result_syntax in + let* ctxt, key_values = + Lwt.map wrap_tzresult + @@ Storage.Big_map.Contents.list_key_values ?offset ?length (ctxt, id) + in + let values = List.map snd key_values in + return (ctxt, values) + + let get ctxt id = + Lwt.map wrap_tzresult @@ Storage.Big_map.Value_type.get ctxt id + + let fold ctxt ~init ~f = + Storage.Big_map.fold ctxt ~order:`Undefined ~init ~f + end + + module Lambda = struct + type ex_lambda = + | Ex_lambda : + (('a, 'b) Script_typed_ir.lambda, _) Script_typed_ir.ty + * ('a, 'b) Script_typed_ir.lambda + -> ex_lambda + + type ex_ty_lambdas = + | Ex_ty_lambdas : + ('a, _) Script_typed_ir.ty * ('a -> ex_lambda list) list + -> ex_ty_lambdas + + let lam_node node = + match node with + | Ex_lambda (_, Lam (_, node)) | Ex_lambda (_, LamRec (_, node)) -> node + + let rec find_lambda_tys : + type a c. (a, c) Script_typed_ir.ty -> (a -> ex_lambda list) list = + fun ty -> + let open Script_typed_ir in + match ty with + | Unit_t | Int_t | Nat_t | Signature_t | String_t | Bytes_t | Mutez_t + | Key_hash_t | Key_t | Timestamp_t | Address_t | Bool_t | Set_t _ + | Big_map_t _ | Contract_t _ | Operation_t | Sapling_transaction_t _ + | Sapling_transaction_deprecated_t _ | Sapling_state_t _ | Never_t + | Bls12_381_g1_t | Bls12_381_g2_t | Bls12_381_fr_t | Ticket_t _ + | Chain_id_t | Chest_key_t | Chest_t -> + [] + | Pair_t (t1, t2, _, _) -> + let g1 = List.map (fun g (v, _) -> g v) @@ find_lambda_tys t1 in + let g2 = List.map (fun g (_, v) -> g v) @@ find_lambda_tys t2 in + g1 @ g2 + | Or_t (t1, t2, _, _) -> + let g1 = + List.map (fun g -> function L v -> g v | R _ -> []) + @@ find_lambda_tys t1 + in + let g2 = + List.map (fun g -> function L _ -> [] | R v -> g v) + @@ find_lambda_tys t2 + in + g1 @ g2 + | Lambda_t _ -> [(fun g -> [Ex_lambda (ty, g)])] + | Option_t (t, _, _) -> + List.map (fun g -> function None -> [] | Some v -> g v) + @@ find_lambda_tys t + | List_t (t, _) -> + List.map (fun g l -> + List.flatten @@ List.map g @@ Script_list.to_list l) + @@ find_lambda_tys t + | Map_t (_, tv, _) -> find_lambda_tys_map tv + + and find_lambda_tys_map : + type tk tv c. + (tv, c) Script_typed_ir.ty -> + ((tk, tv) Script_typed_ir.map -> ex_lambda list) list = + fun tv -> + let open Script_typed_ir in + List.map (fun g (Map_tag (module Box) : (tk, tv) map) -> + Box.OPS.fold (fun _k v acc -> g v @ acc) Box.boxed []) + @@ find_lambda_tys tv + + let collect_lambda_tys (Translator.Ex_ty ty) = + match find_lambda_tys ty with + | [] -> None + | lams -> Some (Ex_ty_lambdas (ty, lams)) + + let fold_ex_ty_lambdas (type a) ~(ctxt : Context.t) ~(expr : Script.node) + ~(f : a -> Script.node -> ex_lambda list -> a) ~(acc : a) + (Ex_ty_lambdas (ty, getters)) = + let open Lwt_syntax in + let+ parse_result = + Translator.parse_data ctxt ~allow_forged:true ty expr + in + match parse_result with + | Error _ -> acc + | Ok (data, _cost) -> ( + match Script_ir_unparser.unparse_ty ~loc:0 (Obj.magic ctxt) ty with + | Error _ -> assert false + | Ok (ty_expr, _) -> + List.fold_left (fun acc g -> f acc ty_expr @@ g data) acc getters) + end + + let is_unpack = function + | Michelson_v1_primitives.I_UNPACK -> true + | _ -> false + + let code_storage_type ({storage_type; _} : Translator.toplevel) = storage_type + + module Global_constants = struct + let expand ctxt (expr : Script.expr) = + let open Lwt_syntax in + let+ res = Global_constants_storage.expand ctxt expr in + match res with Error _ -> (ctxt, expr) | Ok x -> x + end +end + +let () = Known_protocols.register (module Proto) diff --git a/devtools/testnet_experiment_tools/dune b/devtools/testnet_experiment_tools/dune index c59adce64d07..ca236ba18031 100644 --- a/devtools/testnet_experiment_tools/dune +++ b/devtools/testnet_experiment_tools/dune @@ -43,6 +43,10 @@ octez-protocol-019-PtParisB-libs.client octez-protocol-019-PtParisB-libs.client.commands tezos-protocol-019-PtParisB.protocol + octez-protocol-020-PsParisC-libs.baking + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.client.commands + tezos-protocol-020-PsParisC.protocol octez-protocol-alpha-libs.baking octez-protocol-alpha-libs.client octez-protocol-alpha-libs.client.commands @@ -58,7 +62,12 @@ -open Tezos_store -open Tezos_store_shared -open Tezos_context) - (modules sigs tool_018_Proxford tool_019_PtParisB tool_alpha)) + (modules + sigs + tool_018_Proxford + tool_019_PtParisB + tool_020_PsParisC + tool_alpha)) (executable (name simulation_scenario) diff --git a/devtools/testnet_experiment_tools/tool_020_PsParisC.ml b/devtools/testnet_experiment_tools/tool_020_PsParisC.ml new file mode 100644 index 000000000000..e1fa8a4cf719 --- /dev/null +++ b/devtools/testnet_experiment_tools/tool_020_PsParisC.ml @@ -0,0 +1,994 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Lwt_result_syntax +open Tezos_shell_services +open Tezos_client_020_PsParisC +open Tezos_baking_020_PsParisC +open Tezos_protocol_020_PsParisC +open Protocol +open Alpha_context + +(** Sync node *) + +class wrap_silent_memory_client (t : Client_context.full) : + Protocol_client_context.full = + object + inherit Protocol_client_context.wrap_full t + + method! message : type a. (a, unit) Client_context.lwt_format -> a = + fun x -> Format.kasprintf (fun _msg -> Lwt.return_unit) x + + method! last_modification_time _ = return_some 0. + + (* We rely on the client's cache mechanism to store in memory the + extracted delegate keys. *) + method! load _ ~default _ = return default + + method! write _ _ _ = return_unit + + method! with_lock f = f () + end + +module Sorted_baker_map = Map.Make (struct + type t = Signature.Public_key_hash.t * Tez.t + + let compare (h, x) (h', x') = + (* Descending order *) + let v = Tez.compare x' x in + if v <> 0 then v else Signature.Public_key_hash.compare h h' +end) + +module Consensus_key_set = Set.Make (struct + type t = Signature.Public_key.t * Signature.Public_key_hash.t + + let compare = compare +end) + +type ctxt_kind = + | Wrapped of Protocol_client_context.full + | Generic of Client_context.full + +let load_client_context (cctxt : ctxt_kind) = + let cctxt = + match cctxt with + | Wrapped x -> x + | Generic cctxt -> new Protocol_client_context.wrap_full cctxt + in + let open Lwt_result_syntax in + let open Protocol_client_context in + let* (b : Tezos_shell_services.Block_services.Proof.raw_context) = + Alpha_block_services.Context.read + cctxt + ["active_delegate_with_one_roll"; "current"] + in + let rec get_pkhs (p : string -> Signature.Public_key_hash.t) + (d : Tezos_shell_services.Block_services.Proof.raw_context) acc = + match d with + | Key _b -> assert false + | Dir m -> + String.Map.fold + (function + | "ed25519" -> + get_pkhs (fun s -> + Signature.( + Ed25519 (Ed25519.Public_key_hash.of_hex_exn (`Hex s)))) + | "p256" -> + get_pkhs (fun s -> + Signature.(P256 (P256.Public_key_hash.of_hex_exn (`Hex s)))) + | "secp256k1" -> + get_pkhs (fun s -> + Signature.( + Secp256k1 (Secp256k1.Public_key_hash.of_hex_exn (`Hex s)))) + | s -> fun _v acc -> p s :: acc) + m + acc + | _ -> assert false + in + let delegates = get_pkhs (fun _ -> assert false) b [] |> List.rev in + let* sorted_bakers = + List.fold_left_es + (fun acc delegate -> + let*! r = + Alpha_services.Delegate.consensus_key cctxt (`Main, `Head 0) delegate + in + let* delegate_frozen_deposits = + Alpha_services.Delegate.frozen_deposits + cctxt + (`Main, `Head 0) + delegate + in + let k = (delegate, delegate_frozen_deposits) in + match r with + | Error _ -> return (Sorted_baker_map.add k Consensus_key_set.empty acc) + | Ok ck_info -> + let open Alpha_services.Delegate in + let cks = + let pendings = + List.map + (fun (_, ck) -> (ck.consensus_key_pk, ck.consensus_key_pkh)) + ck_info.pendings + in + if + Signature.Public_key_hash.( + ck_info.active.consensus_key_pkh = delegate) + then pendings + else + ( ck_info.active.consensus_key_pk, + ck_info.active.consensus_key_pkh ) + :: pendings + in + let cks_set = Consensus_key_set.of_list cks in + return (Sorted_baker_map.add k cks_set acc)) + Sorted_baker_map.empty + delegates + in + let mk_unencrypted f x = + Uri.of_string (Format.sprintf "unencrypted:%s" (f x)) + in + let random_sk = + let b = Bytes.create 32 in + fun (pk : Signature.public_key) : Signature.secret_key -> + let open Signature in + let algo : algo = + match pk with + | Ed25519 _ -> Ed25519 + | Secp256k1 _ -> Secp256k1 + | P256 _ -> P256 + | _ -> assert false + in + let i = Random.bits () |> Int32.of_int in + Bytes.set_int32_be b 0 i ; + let _, _, sk = V_latest.generate_key ~algo ~seed:b () in + sk + in + let* delegates_l = + List.mapi_es + (fun i ((pkh, _), cks) -> + let alias = Format.sprintf "baker_%d" i in + let make ?pk alias pkh = + let* pk_opt = + match pk with + | None -> + Alpha_services.Contract.manager_key cctxt (`Main, `Head 0) pkh + | Some pk -> return_some pk + in + let pk = WithExceptions.Option.get ~loc:__LOC__ pk_opt in + let pk_uri = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Client_keys.make_pk_uri + (mk_unencrypted Signature.Public_key.to_b58check pk) + in + let sk_uri = + WithExceptions.Result.get_ok ~loc:__LOC__ + @@ Client_keys.make_sk_uri + (mk_unencrypted + Signature.Secret_key.to_b58check + (random_sk pk)) + in + return (alias, pkh, pk, pk_uri, sk_uri) + in + let* baker = make alias pkh in + let* cks = + List.mapi_es + (fun i (ck_pk, ck_pkh) -> + make ~pk:ck_pk (Printf.sprintf "%s_ck_%d" alias i) ck_pkh) + (Consensus_key_set.elements cks) + in + return (baker :: cks)) + (Sorted_baker_map.bindings sorted_bakers) + in + let delegates = List.flatten delegates_l in + let* () = Client_keys.register_keys cctxt delegates in + return_unit + +let get_delegates (cctxt : Protocol_client_context.full) = + let proj_delegate (alias, public_key_hash, public_key, secret_key_uri) = + { + Baking_state.alias = Some alias; + public_key_hash; + public_key; + secret_key_uri; + } + in + let* keys = Client_keys.get_keys cctxt in + let delegates = List.map proj_delegate keys in + + let* () = + Tezos_signer_backends.Encrypted.decrypt_list + cctxt + (List.filter_map + (function + | {Baking_state.alias = Some alias; _} -> Some alias | _ -> None) + delegates) + in + let delegates_no_duplicates = List.sort_uniq compare delegates in + let*! () = + if List.compare_lengths delegates delegates_no_duplicates <> 0 then + cctxt#warning + "Warning: the list of public key hash aliases contains duplicate \ + hashes, which are ignored" + else Lwt.return_unit + in + return delegates_no_duplicates + +let get_current_proposal cctxt ?cache () = + let* block_stream, block_stream_stopper = + Node_rpc.monitor_heads cctxt ?cache ~chain:cctxt#chain () + in + let*! stream_head = Lwt_stream.get block_stream in + match stream_head with + | Some current_head -> + return (block_stream, current_head, block_stream_stopper) + | None -> failwith "head stream unexpectedly ended" + +let create_state cctxt ?synchronize ?monitor_node_mempool ~config + ~current_proposal delegates = + let open Lwt_result_syntax in + let chain = cctxt#chain in + let monitor_node_operations = monitor_node_mempool in + let*! operation_worker = + Operation_worker.create ?monitor_node_operations cctxt + in + Baking_scheduling.create_initial_state + cctxt + ?synchronize + ~chain + config + operation_worker + ~current_proposal + delegates + +let compute_current_round_duration round_durations + ~(predecessor : Baking_state.block_info) round = + let open Result_syntax in + let* start = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp:predecessor.shell.timestamp + ~predecessor_round:predecessor.round + ~round + in + let start = Timestamp.to_seconds start in + let* _end = + Round.timestamp_of_round + round_durations + ~predecessor_timestamp:predecessor.shell.timestamp + ~predecessor_round:predecessor.round + ~round:(Round.succ round) + in + let _end = Timestamp.to_seconds _end in + Ok (Ptime.Span.of_int_s Int64.(sub _end start |> to_int)) + +let one_minute = Ptime.Span.of_int_s 60 + +let wait_next_block block_stream current_proposal = + let open Baking_state in + let open Lwt_syntax in + Lwt.catch + (fun () -> + Lwt_unix.with_timeout 10. @@ fun () -> + let* () = + Lwt_stream.junk_while_s + (fun proposal -> + Lwt.return + (Compare.Int32.( + current_proposal.block.shell.level = proposal.block.shell.level) + && Round.(current_proposal.block.round = proposal.block.round))) + block_stream + in + let* new_block_opt = Lwt_stream.get block_stream in + WithExceptions.Option.get ~loc:__LOC__ new_block_opt |> Lwt.return) + (function + | Lwt_unix.Timeout -> + Format.printf + "Failed to receive expected block, continuing anyway...@." ; + Lwt.return current_proposal + | exn -> Lwt.fail exn) + +let check_round_duration cctxt ?round_duration_target () = + let open Lwt_result_syntax in + let* param = Alpha_services.Constants.parametric cctxt (`Main, `Head 0) in + match round_duration_target with + | None -> + let*? r = + Period.mult 4l param.minimal_block_delay |> Environment.wrap_tzresult + in + let r = Period.to_seconds r |> Int64.to_int |> Ptime.Span.of_int_s in + Format.printf "Default round duration target set to %a@." Ptime.Span.pp r ; + return r + | Some target -> + let minimal_proto_period = + Period.add param.delay_increment_per_round param.minimal_block_delay + |> WithExceptions.Result.get_ok ~loc:__LOC__ + in + let minimal_round_target = + max 5L (Period.to_seconds minimal_proto_period) |> Int64.to_int + in + if target < minimal_round_target then + failwith + "Invalid round duration target, the minimal accepted round duration \ + target for this chain is %a" + Ptime.Span.pp + (Ptime.Span.of_int_s minimal_round_target) + else return (Ptime.Span.of_int_s target) + +let sync_node (cctxt : Client_context.full) ?round_duration_target () = + let open Lwt_result_syntax in + let*! () = Tezos_base_unix.Internal_event_unix.close () in + let cctxt = new wrap_silent_memory_client cctxt in + let* round_duration_target = + check_round_duration cctxt ?round_duration_target () + in + Format.printf "Loading faked delegate keys@." ; + let* () = load_client_context (Wrapped cctxt) in + let* delegates = get_delegates cctxt in + let* block_stream, current_proposal, stopper = + get_current_proposal cctxt () + in + let* is_pred_metadata_present = + let*! r = + Protocol_client_context.Alpha_block_services.metadata + cctxt + ~block:(`Hash (current_proposal.predecessor.hash, 0)) + () + in + match r with Ok _protocols -> return_true | Error _err -> return_false + in + let* current_proposal = + if not is_pred_metadata_present then ( + Format.printf + "Predecessor's metadata are not present: baking a dummy block@." ; + let* () = + Baking_lib.bake cctxt ~minimal_timestamp:true ~force:true delegates + in + (* Waiting next block... *) + let*! new_proposal = Lwt_stream.get block_stream in + return (WithExceptions.Option.get ~loc:__LOC__ new_proposal)) + else return current_proposal + in + let config = Baking_configuration.make ~force:true () in + let rec loop current_proposal = + let* state = create_state cctxt ~config ~current_proposal delegates in + let*? current_round_duration = + Environment.wrap_tzresult + @@ compute_current_round_duration + state.global_state.round_durations + ~predecessor:state.level_state.latest_proposal.predecessor + state.round_state.current_round + in + Format.printf + "Current head level: %ld, current head round: %a@." + state.level_state.latest_proposal.block.shell.level + Round.pp + state.level_state.latest_proposal.block.round ; + Format.printf + "Current round %a. Duration: %a@." + Round.pp + state.round_state.current_round + Ptime.Span.pp + current_round_duration ; + if Ptime.Span.(compare current_round_duration round_duration_target) > 0 + then ( + Format.printf + "Current round duration is higher than %a, retrying...@." + Ptime.Span.pp + round_duration_target ; + let pred_round = + Result.value + ~default:Round.zero + (Round.pred state.round_state.current_round) + in + Format.printf "Proposing at previous round: %a@." Round.pp pred_round ; + let* () = + Baking_lib.repropose cctxt delegates ~force:true ~force_round:pred_round + in + let*! new_block = wait_next_block block_stream current_proposal in + Format.printf "Baking at next level with minimal round@." ; + let* () = + Baking_lib.bake cctxt delegates ~force:true ~minimal_timestamp:true + in + let*! new_block = wait_next_block block_stream new_block in + loop new_block) + else ( + Format.printf + "Current round duration is %a which is less than %a. Bakers may now be \ + started@." + Ptime.Span.pp + current_round_duration + Ptime.Span.pp + round_duration_target ; + return_unit) + in + let* () = loop current_proposal in + stopper () ; + let*! () = + Tezos_base_unix.Internal_event_unix.( + init ~config:(make_with_defaults ()) ()) + in + return_unit + +(** Manager injector *) + +module ManagerMap = Signature.Public_key_hash.Map +module ManagerSet = Signature.Public_key_hash.Set + +type injected_operation = { + original_hash : Operation_hash.t; + modified_hash : Operation_hash.t; +} + +type t = { + last_injected_op_per_manager : injected_operation ManagerMap.t; + operation_queues : (Operation_hash.t * packed_operation) Queue.t ManagerMap.t; +} + +let pp_state fmt {last_injected_op_per_manager; operation_queues} = + Format.fprintf + fmt + "%d injected operations pending, %d manager queues left" + (ManagerMap.cardinal last_injected_op_per_manager) + (ManagerMap.cardinal operation_queues) + +let pp_initial_state fmt {operation_queues; _} = + Format.( + fprintf + fmt + "@[%d manager queues:@ %a@]@." + (ManagerMap.cardinal operation_queues) + (pp_print_list ~pp_sep:pp_print_cut (fun fmt (manager, queue) -> + Format.fprintf + fmt + "%a: %d" + Signature.Public_key_hash.pp + manager + (Queue.length queue))) + (ManagerMap.bindings operation_queues)) + +let init ~operations_file_path = + Format.printf "Parsing operations file@." ; + let op_encoding = Protocol.Alpha_context.Operation.encoding in + let buffer = Bytes.create (10 * 1024 * 1024) (* 10mb *) in + let*! ic = Lwt_io.open_file ~mode:Input operations_file_path in + let rec loop acc = + let*! op_len = + Lwt.catch + (fun () -> + let*! op_len = Lwt_io.BE.read_int32 ic in + let*! () = + Lwt_io.read_into_exactly ic buffer 0 (Int32.to_int op_len) + in + Lwt.return_ok (`Op_len op_len)) + (function + | End_of_file -> Lwt.return_ok `EOF + | exn -> failwith "%s" (Printexc.to_string exn)) + in + match op_len with + | Error x -> Lwt.return_error x + | Ok `EOF -> return (List.rev acc) + | Ok (`Op_len op_len) -> + let op = + Data_encoding.Binary.of_bytes_exn + op_encoding + (Bytes.sub buffer 0 (Int32.to_int op_len)) + in + loop (op :: acc) + in + let total = ref 0 in + let* all_ops = loop [] in + let*! () = Lwt_io.close ic in + Format.printf "Loading operations file@." ; + let rec loop + (acc : (Operation_hash.t * packed_operation) Queue.t ManagerMap.t) : + packed_operation list -> + (Operation_hash.t * packed_operation) Queue.t ManagerMap.t = function + | [] -> acc + | ({ + protocol_data = + Operation_data {contents = Single (Manager_operation {source; _}); _}; + _; + } as op) + :: r + | ({ + protocol_data = + Operation_data + {contents = Cons (Manager_operation {source; _}, _); _}; + _; + } as op) + :: r -> + incr total ; + let oph = Operation.hash_packed op in + let acc = + ManagerMap.update + source + (function + | None -> + let q = Queue.create () in + Queue.add (oph, op) q ; + Some q + | Some q -> + Queue.add (oph, op) q ; + Some q) + acc + in + loop acc r + | _non_manager_op :: r -> loop acc r + in + let operation_queues = loop ManagerMap.empty all_ops in + Format.printf "%d manager operations loaded@." !total ; + return + { + last_injected_op_per_manager = Signature.Public_key_hash.Map.empty; + operation_queues; + } + +let choose_new_operations state prohibited_managers n = + (* Prioritize large operations queues *) + let sorted_queues = + ManagerMap.bindings state.operation_queues + |> List.sort (fun (_, q) (_, q') -> + Int.compare (Queue.length q') (Queue.length q)) + in + let ops = ref [] in + let cpt = ref 0 in + let updated_operation_queues = ref state.operation_queues in + let selected_ops = + let exception End in + try + List.iter + (fun (manager, op_q) -> + if !cpt = n then raise End ; + if not (ManagerSet.mem manager prohibited_managers) then + match Queue.take_opt op_q with + | Some op -> + incr cpt ; + ops := (manager, op) :: !ops + | None -> + updated_operation_queues := + ManagerMap.remove manager !updated_operation_queues) + sorted_queues ; + !ops + with End -> !ops + in + let state = {state with operation_queues = !updated_operation_queues} in + (selected_ops, state) + +let choose_and_inject_operations cctxt state prohibited_managers n = + let* finalized_head = Shell_services.Blocks.hash cctxt ~block:(`Head 2) () in + let cpt = ref 0 in + let errors = ref 0 in + let updated_state = ref state in + let exception End in + let* nb_injected, nb_erroneous, new_state = + Lwt.catch + (fun () -> + let* () = + ManagerMap.iter_es + (fun manager op_q -> + let* () = if !cpt = n then raise End else return_unit in + if ManagerSet.mem manager prohibited_managers then return_unit + else + match Queue.take_opt op_q with + | None -> + updated_state := + { + !updated_state with + operation_queues = + ManagerMap.remove + manager + !updated_state.operation_queues; + } ; + return_unit + | Some (original_hash, op) -> ( + let modified_op = + {op with shell = {branch = finalized_head}} + in + let modified_hash = Operation.hash_packed modified_op in + let op = {modified_hash; original_hash} in + let*! injection_result = + Shell_services.Injection.operation + cctxt + (Data_encoding.Binary.to_bytes_exn + Operation.encoding + modified_op) + in + match injection_result with + | Ok _h -> + incr cpt ; + updated_state := + { + !updated_state with + last_injected_op_per_manager = + ManagerMap.add + manager + op + !updated_state.last_injected_op_per_manager; + } ; + return_unit + | Error _err -> + incr errors ; + updated_state := + { + !updated_state with + operation_queues = + ManagerMap.remove + manager + !updated_state.operation_queues; + } ; + return_unit)) + state.operation_queues + in + return (!cpt, !errors, !updated_state)) + (function + | End -> return (!cpt, !errors, !updated_state) | exn -> Lwt.fail exn) + in + Format.printf + "%d new manager operations injected, %d erroneous operation manager queues \ + discarded@." + nb_injected + nb_erroneous ; + return new_state + +let start_injector cctxt ~op_per_mempool ~min_manager_queues + ~operations_file_path = + let* state = init ~operations_file_path in + Format.printf "Starting injector@." ; + let* head_stream, _stopper = Monitor_services.heads cctxt `Main in + let block_stream = + Lwt_stream.map_s + (fun (bh, header) -> + let*! opl = + Protocol_client_context.Alpha_block_services.Operations + .operations_in_pass + cctxt + ~metadata:`Always + ~block:(`Hash (bh, 0)) + Operation_repr.manager_pass + in + let opl = WithExceptions.Result.get_ok ~loc:__LOC__ opl in + Lwt.return (header, opl)) + head_stream + in + let*! current_head_opt = Lwt_stream.get block_stream in + let ((header, _mopl) as _current_head) = + WithExceptions.Option.get ~loc:__LOC__ current_head_opt + in + let current_level = header.shell.level in + let rec loop state current_level = + let*! r = Lwt_stream.get block_stream in + match r with + | None -> failwith "Head stream ended: lost connection with node?" + | Some (header, _opll) + when Compare.Int32.(header.shell.level <= current_level) -> + (* reorg *) + Format.printf "New head with non-increasing level: ignoring@." ; + loop state current_level + | Some (_header, mopl) as _new_head -> + Format.printf + "New increasing head received with %d included operations@." + (List.length mopl) ; + let* mempool = + Protocol_client_context.Alpha_block_services.Mempool + .pending_operations + cctxt + ~validated:true + ~refused:false + ~outdated:false + ~branch_refused:false + ~branch_delayed:false + ~validation_passes:[Operation_repr.manager_pass] + () + in + let live_operations = + Operation_hash.Set.( + union + (of_list + (List.map + fst + (Operation_hash.Map.bindings mempool.unprocessed))) + (of_list (List.map fst mempool.validated))) + in + Format.printf + "%d manager operations still live in the mempool@." + (Operation_hash.Set.cardinal live_operations) ; + let new_last_injected, prohibited_managers = + let last_injected_op_per_manager = + state.last_injected_op_per_manager + in + ManagerMap.fold + (fun manager {modified_hash; _} (new_last_injected, acc) -> + if Operation_hash.Set.mem modified_hash live_operations then + (new_last_injected, ManagerSet.add manager acc) + else (ManagerMap.remove manager new_last_injected, acc)) + last_injected_op_per_manager + (last_injected_op_per_manager, ManagerSet.empty) + in + let state = + {state with last_injected_op_per_manager = new_last_injected} + in + let nb_missing_operations = + op_per_mempool + - ManagerMap.cardinal state.last_injected_op_per_manager + in + Format.printf + "Injecting %d new manager operations...@." + nb_missing_operations ; + let* state = + choose_and_inject_operations + cctxt + state + prohibited_managers + nb_missing_operations + in + let remaining_manager_queues = + ManagerMap.cardinal state.operation_queues + in + Format.printf "Current state: %a@." pp_state state ; + (* Stop when there the number of manager operation queues left is lower + than `min_manager_queues`. *) + if remaining_manager_queues < min_manager_queues then ( + Format.printf + "Not enough manager operation queues left to continue the \ + experiment (%d left, %d required). Terminating.@. " + remaining_manager_queues + min_manager_queues ; + return_unit) + else loop state header.shell.level + in + loop state current_level + +(* Block time "hot-patch" *) + +type cycle_era = { + first_level : Raw_level_repr.t; + first_cycle : Cycle_repr.t; + blocks_per_cycle : int32; + blocks_per_commitment : int32; +} + +(* Copy-paste of the protocol abstracted cycle_eras type and + encoding *) + +type cycle_eras = cycle_era list + +let cycle_eras_encoding = + let open Result_syntax in + let create_cycle_eras cycle_eras = + match cycle_eras with + | [] -> assert false + | newest_era :: older_eras -> + let rec aux {first_level; first_cycle; _} older_eras = + match older_eras with + | ({ + first_level = first_level_of_previous_era; + first_cycle = first_cycle_of_previous_era; + _; + } as previous_era) + :: even_older_eras -> + if + Raw_level_repr.(first_level > first_level_of_previous_era) + && Cycle_repr.(first_cycle > first_cycle_of_previous_era) + then aux previous_era even_older_eras + else assert false + | [] -> return_unit + in + let* () = aux newest_era older_eras in + return cycle_eras + in + let cycle_era_encoding = + let open Data_encoding in + conv + (fun {first_level; first_cycle; blocks_per_cycle; blocks_per_commitment} -> + (first_level, first_cycle, blocks_per_cycle, blocks_per_commitment)) + (fun (first_level, first_cycle, blocks_per_cycle, blocks_per_commitment) -> + {first_level; first_cycle; blocks_per_cycle; blocks_per_commitment}) + (obj4 + (req + "first_level" + ~description:"The first level of a new cycle era." + Raw_level_repr.encoding) + (req + "first_cycle" + ~description:"The first cycle of a new cycle era." + Cycle_repr.encoding) + (req + "blocks_per_cycle" + ~description: + "The value of the blocks_per_cycle constant used during the \ + cycle era starting with first_level." + int32) + (req + "blocks_per_commitment" + ~description: + "The value of the blocks_per_commitment constant used during the \ + cycle era starting with first_level." + int32)) + in + Data_encoding.conv_with_guard + (fun eras -> eras) + (fun eras -> + match create_cycle_eras eras with + | Ok eras -> Ok eras + | Error _ -> Error "Invalid cycle eras") + (Data_encoding.list cycle_era_encoding) + +let patch_block_time ctxt ~head_level ~block_time_target ~patch_max_op_ttl = + let pf = Format.printf in + let open Environment in + let patch_flag_key = ["patch_flag"] in + let* () = + let*! opt = Context.find ctxt patch_flag_key in + match opt with + | Some _ -> + failwith + "The context was already patched with a custom block time. The patch \ + must be applied on a fresh context." + | None -> return_unit + in + let constants_key = ["v1"; "constants"] in + let* (constants : Constants_parametric_repr.t) = + let*! opt = Context.find ctxt constants_key in + match opt with + | None -> failwith "Internal error: cannot read constants in context." + | Some bytes -> ( + match + Data_encoding.Binary.of_bytes_opt + Constants_parametric_repr.encoding + bytes + with + | None -> failwith "Internal error: cannot parse constants in context." + | Some constants -> return constants) + in + let current_block_time = + Int64.to_int @@ Period_repr.to_seconds constants.minimal_block_delay + in + let speedup_ratio = float current_block_time /. float block_time_target in + let blocks_per_cycle = + float (Int32.to_int constants.blocks_per_cycle) *. speedup_ratio + |> int_of_float |> Int32.of_int + in + let hard_gas_limit_per_block = + let patched_block_gas_limit = + let b_gas_lim_f = + Gas_limit_repr.Arith.integral_to_z constants.hard_gas_limit_per_block + |> Z.to_int |> float + in + b_gas_lim_f /. speedup_ratio + |> int_of_float |> Gas_limit_repr.Arith.integral_of_int_exn + in + Gas_limit_repr.Arith.max + constants.hard_gas_limit_per_operation + patched_block_gas_limit + in + let proof_of_work_threshold = + Int64.shift_right + constants.proof_of_work_threshold + (max 0 (log speedup_ratio /. log 2. |> int_of_float)) + in + let max_operations_time_to_live = + if patch_max_op_ttl then + float constants.max_operations_time_to_live *. speedup_ratio + |> int_of_float + else constants.max_operations_time_to_live + in + let minimal_block_delay = + Period_repr.of_seconds_exn (Int64.of_int block_time_target) + in + let delay_increment_per_round = + Period_repr.of_seconds_exn (Int64.of_int (max 1 (block_time_target / 2))) + in + let blocks_per_commitment = constants.blocks_per_commitment in + pf "Block time speed up ratio: %.2f%%@." (speedup_ratio *. 100.) ; + pf + "Minimal block delay: %a -> %a@." + Period_repr.pp + constants.minimal_block_delay + Period_repr.pp + minimal_block_delay ; + pf + "Delay increment per round: %a -> %a@." + Period_repr.pp + constants.delay_increment_per_round + Period_repr.pp + delay_increment_per_round ; + pf "Block per cycle: %ld -> %ld@." constants.blocks_per_cycle blocks_per_cycle ; + pf + "Hard gas limit per block: %a -> %a (minimum = hard gas limit per op. = \ + %a)@." + Gas_limit_repr.Arith.pp + constants.hard_gas_limit_per_block + Gas_limit_repr.Arith.pp + hard_gas_limit_per_block + Gas_limit_repr.Arith.pp + constants.hard_gas_limit_per_operation ; + pf + "Proof of work difficulty: %.1f -> %.1f@." + (log (float (Int64.to_int constants.proof_of_work_threshold))) + (log (float (Int64.to_int proof_of_work_threshold))) ; + pf + "Max operations time to live: %d -> %d@." + constants.max_operations_time_to_live + max_operations_time_to_live ; + let patched_constants = + { + constants with + Constants_parametric_repr.minimal_block_delay; + delay_increment_per_round; + blocks_per_cycle; + hard_gas_limit_per_block; + proof_of_work_threshold; + max_operations_time_to_live; + } + |> Data_encoding.Binary.to_bytes_exn Constants_parametric_repr.encoding + in + let cycle_eras_key = ["v1"; "cycle_eras"] in + let* patched_cycle_eras = + let*! opt = Context.find ctxt cycle_eras_key in + match opt with + | None -> failwith "Internal error: cannot read cycle eras in context." + | Some bytes -> ( + match Data_encoding.Binary.of_bytes_opt cycle_eras_encoding bytes with + | Some (latest_era :: _rest as l) -> + let head_level = Raw_level_repr.of_int32_exn head_level in + let cycle = + let level_position_in_era = + Raw_level_repr.diff head_level latest_era.first_level + in + let cycles_since_era_start = + Int32.div level_position_in_era latest_era.blocks_per_cycle + in + Cycle_repr.add + latest_era.first_cycle + (Int32.to_int cycles_since_era_start) + in + let cycle_eras = + { + first_level = head_level; + first_cycle = cycle; + blocks_per_cycle; + blocks_per_commitment; + } + :: l + in + return + (Data_encoding.Binary.to_bytes_exn cycle_eras_encoding cycle_eras) + | _ -> failwith "Internal error: cannot parse cycle eras in context.") + in + let*! ctxt = Context.add ctxt constants_key patched_constants in + let*! ctxt = Context.add ctxt cycle_eras_key patched_cycle_eras in + let*! ctxt = Context.add ctxt patch_flag_key Bytes.empty in + return ctxt + +module Tool : Sigs.PROTO_TOOL = struct + let extract_client_context cctxt = load_client_context (Generic cctxt) + + let sync_node = sync_node + + let start_injector = start_injector + + let patch_block_time = patch_block_time +end + +let () = Sigs.register Protocol.hash (module Tool) diff --git a/devtools/yes_wallet/dune b/devtools/yes_wallet/dune index 77788fe14812..18e6d9343fcc 100644 --- a/devtools/yes_wallet/dune +++ b/devtools/yes_wallet/dune @@ -14,6 +14,7 @@ octez-libs.tezos-context tezos-protocol-018-Proxford.protocol tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol tezos-protocol-alpha.protocol) (library_flags (:standard -linkall)) (flags diff --git a/devtools/yes_wallet/get_delegates_020_PsParisC.ml b/devtools/yes_wallet/get_delegates_020_PsParisC.ml new file mode 100644 index 000000000000..b817754b6d33 --- /dev/null +++ b/devtools/yes_wallet/get_delegates_020_PsParisC.ml @@ -0,0 +1,125 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Get_delegates = struct + open Tezos_protocol_020_PsParisC + open Protocol + + type context = Alpha_context.t + + type contract = Alpha_context.Contract.t + + let hash = hash + + module Tez = struct + include Alpha_context.Tez + + let ( +? ) a b = Environment.wrap_tzresult (a +? b) + end + + module Signature = struct + include Tezos_crypto.Signature.V1 + module To_latest = Tezos_crypto.Signature.Of_V1 + end + + module Contract = struct + open Alpha_context.Contract + + let fold context ~init ~f = + let open Lwt_syntax in + let* l = list context in + Lwt_list.fold_left_s f init l + + let balance ctxt t = get_balance ctxt t |> Lwt.map Environment.wrap_tzresult + + let frozen_bonds ctxt t = + get_frozen_bonds ctxt t |> Lwt.map Environment.wrap_tzresult + + let get_staked_balance ctxt t = + For_RPC.get_staked_balance ctxt t |> Lwt.map Environment.wrap_tzresult + + let get_unstaked_frozen_balance ctxt t = + For_RPC.get_unstaked_frozen_balance ctxt t + |> Lwt.map Environment.wrap_tzresult + + let get_unstaked_finalizable_balance ctxt t = + For_RPC.get_unstaked_finalizable_balance ctxt t + |> Lwt.map Environment.wrap_tzresult + + let get_full_balance ctxt t = + For_RPC.get_full_balance ctxt t |> Lwt.map Environment.wrap_tzresult + + let contract_address contract = Alpha_context.Contract.to_b58check contract + + let total_supply ctxt = + Alpha_context.Contract.get_total_supply ctxt + |> Lwt.map Environment.wrap_tzresult + end + + module Commitment = struct + include Alpha_context.Commitment + + type t = Blinded_public_key_hash.t + + let fold ctxt ~order ~init ~f = + fold ctxt ~order ~init ~f:(fun c t acc -> f c (Tez_repr.to_mutez t) acc) + end + + module Delegate = struct + open Alpha_context.Delegate + + let fold ctxt ~order ~init ~f = fold ctxt ~order ~init ~f + + let pubkey ctxt pkh = + Alpha_context.Contract.get_manager_key ctxt pkh + |> Lwt.map Environment.wrap_tzresult + + let staking_balance ctxt pkh = + For_RPC.staking_balance ctxt pkh |> Lwt.map Environment.wrap_tzresult + + let current_frozen_deposits ctxt pkh = + current_frozen_deposits ctxt pkh |> Lwt.map Environment.wrap_tzresult + + let unstaked_frozen_deposits ctxt pkh = + Alpha_context.Unstaked_frozen_deposits.balance + ctxt + pkh + Alpha_context.Level.(current ctxt).cycle + |> Lwt.map Environment.wrap_tzresult + + let deactivated ctxt pkh = + deactivated ctxt pkh |> Lwt.map Environment.wrap_tzresult + end + + let prepare_context ctxt ~level ~predecessor_timestamp ~timestamp = + let open Lwt_result_syntax in + let+ ctxt, _, _ = + Alpha_context.prepare ctxt ~level ~predecessor_timestamp ~timestamp + |> Lwt.map Environment.wrap_tzresult + in + ctxt +end + +let () = Known_protocols.register (module Get_delegates) diff --git a/docs/doc_gen/dune b/docs/doc_gen/dune index ab7490502240..ca5cf8eebc52 100644 --- a/docs/doc_gen/dune +++ b/docs/doc_gen/dune @@ -17,6 +17,7 @@ tezos-protocol-genesis.embedded-protocol tezos-protocol-018-Proxford.embedded-protocol tezos-protocol-019-PtParisB.embedded-protocol + tezos-protocol-020-PsParisC.embedded-protocol tezos-protocol-alpha.embedded-protocol) (link_flags (:standard) diff --git a/dune-project b/dune-project index b6d2625a5d71..9d547df31c7b 100644 --- a/dune-project +++ b/dune-project @@ -10,10 +10,12 @@ (package (name kaitai)) (package (name kaitai-of-data-encoding)) (package (name octez-accuser-Proxford)) +(package (name octez-accuser-PsParisC)) (package (name octez-accuser-PtParisB)) (package (name octez-accuser-alpha)) (package (name octez-alcotezt)) (package (name octez-baker-Proxford)) +(package (name octez-baker-PsParisC)) (package (name octez-baker-PtParisB)) (package (name octez-baker-alpha)) (package (name octez-client)) @@ -56,6 +58,7 @@ (package (name octez-protocol-017-PtNairob-libs)) (package (name octez-protocol-018-Proxford-libs)) (package (name octez-protocol-019-PtParisB-libs)) +(package (name octez-protocol-020-PsParisC-libs)) (package (name octez-protocol-alpha-libs)) (package (name octez-protocol-compiler)) (package (name octez-proxy-server)) @@ -67,6 +70,7 @@ (package (name octez-signer)) (package (name octez-smart-rollup-node)) (package (name octez-smart-rollup-node-Proxford)(allow_empty)) +(package (name octez-smart-rollup-node-PsParisC)(allow_empty)) (package (name octez-smart-rollup-node-PtNairob)(allow_empty)) (package (name octez-smart-rollup-node-PtParisB)(allow_empty)) (package (name octez-smart-rollup-node-alpha)(allow_empty)) @@ -82,14 +86,17 @@ (package (name tezos-benchmark)) (package (name tezos-benchmark-018-Proxford)) (package (name tezos-benchmark-019-PtParisB)) +(package (name tezos-benchmark-020-PsParisC)) (package (name tezos-benchmark-alpha)) (package (name tezos-benchmark-examples)) (package (name tezos-benchmark-tests)(allow_empty)) (package (name tezos-benchmark-type-inference-018-Proxford)) (package (name tezos-benchmark-type-inference-019-PtParisB)) +(package (name tezos-benchmark-type-inference-020-PsParisC)) (package (name tezos-benchmark-type-inference-alpha)) (package (name tezos-benchmarks-proto-018-Proxford)) (package (name tezos-benchmarks-proto-019-PtParisB)) +(package (name tezos-benchmarks-proto-020-PsParisC)) (package (name tezos-benchmarks-proto-alpha)) (package (name tezos-client-demo-counter)) (package (name tezos-client-genesis)) @@ -102,6 +109,7 @@ (package (name tezos-dal-node-services)) (package (name tezos-injector-018-Proxford)(allow_empty)) (package (name tezos-injector-019-PtParisB)(allow_empty)) +(package (name tezos-injector-020-PsParisC)(allow_empty)) (package (name tezos-injector-alpha)(allow_empty)) (package (name tezos-lazy-containers-tests)(allow_empty)) (package (name tezos-micheline-rewriting)) @@ -130,6 +138,8 @@ (package (name tezos-protocol-018-Proxford-tests)(allow_empty)) (package (name tezos-protocol-019-PtParisB)) (package (name tezos-protocol-019-PtParisB-tests)(allow_empty)) +(package (name tezos-protocol-020-PsParisC)) +(package (name tezos-protocol-020-PsParisC-tests)(allow_empty)) (package (name tezos-protocol-alpha)) (package (name tezos-protocol-alpha-tests)(allow_empty)) (package (name tezos-protocol-demo-counter)) diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 34b6ed9d9ffb..77958999a256 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -6704,6 +6704,8 @@ let hash = Protocol.hash let _019_PtParisB = active (Name.v "PtParisB" 019) + let _020_PsParisC = active (Name.v "PsParisC" 020) + let alpha = active Name.alpha let all = List.rev !all_rev diff --git a/opam/octez-accuser-PsParisC.opam b/opam/octez-accuser-PsParisC.opam new file mode 100644 index 000000000000..5cbb47bc67a1 --- /dev/null +++ b/opam/octez-accuser-PsParisC.opam @@ -0,0 +1,23 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "octez-protocol-020-PsParisC-libs" { = version } + "octez-shell-libs" { = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: accuser binary" diff --git a/opam/octez-baker-PsParisC.opam b/opam/octez-baker-PsParisC.opam new file mode 100644 index 000000000000..cce7abcd5eba --- /dev/null +++ b/opam/octez-baker-PsParisC.opam @@ -0,0 +1,23 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "octez-protocol-020-PsParisC-libs" { = version } + "octez-shell-libs" { = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: baker binary" diff --git a/opam/octez-client.opam b/opam/octez-client.opam index b661b1ea2400..bdcee44fda05 100644 --- a/opam/octez-client.opam +++ b/opam/octez-client.opam @@ -15,6 +15,7 @@ depends: [ "uri" { >= "3.1.0" } "octez-protocol-018-Proxford-libs" { = version } "octez-protocol-019-PtParisB-libs" { = version } + "octez-protocol-020-PsParisC-libs" { = version } ] depopts: [ "tezos-client-genesis" diff --git a/opam/octez-codec-kaitai.opam b/opam/octez-codec-kaitai.opam index 31448c5e0f79..fd3ad127c8a8 100644 --- a/opam/octez-codec-kaitai.opam +++ b/opam/octez-codec-kaitai.opam @@ -33,6 +33,7 @@ depopts: [ "octez-protocol-017-PtNairob-libs" "octez-protocol-018-Proxford-libs" "octez-protocol-019-PtParisB-libs" + "octez-protocol-020-PsParisC-libs" "octez-protocol-alpha-libs" ] build: [ diff --git a/opam/octez-codec.opam b/opam/octez-codec.opam index 579001792d76..9b025af27b3a 100644 --- a/opam/octez-codec.opam +++ b/opam/octez-codec.opam @@ -32,6 +32,7 @@ depopts: [ "octez-protocol-017-PtNairob-libs" "octez-protocol-018-Proxford-libs" "octez-protocol-019-PtParisB-libs" + "octez-protocol-020-PsParisC-libs" "octez-protocol-alpha-libs" ] conflicts: [ @@ -50,6 +51,7 @@ conflicts: [ "octez-protocol-017-PtNairob-libs" { != version } "octez-protocol-018-Proxford-libs" { != version } "octez-protocol-019-PtParisB-libs" { != version } + "octez-protocol-020-PsParisC-libs" { != version } "octez-protocol-alpha-libs" { != version } ] build: [ diff --git a/opam/octez-dac-client.opam b/opam/octez-dac-client.opam index 02c0dcfc649a..6b7754c5558f 100644 --- a/opam/octez-dac-client.opam +++ b/opam/octez-dac-client.opam @@ -16,6 +16,7 @@ depends: [ "tezos-dac-client-lib" { = version } "octez-protocol-018-Proxford-libs" { = version } "octez-protocol-019-PtParisB-libs" { = version } + "octez-protocol-020-PsParisC-libs" { = version } ] depopts: [ "octez-protocol-alpha-libs" diff --git a/opam/octez-dac-node.opam b/opam/octez-dac-node.opam index cfa950a4ca54..e8383f3effab 100644 --- a/opam/octez-dac-node.opam +++ b/opam/octez-dac-node.opam @@ -18,6 +18,7 @@ depends: [ "octez-internal-libs" { = version } "octez-protocol-018-Proxford-libs" { = version } "octez-protocol-019-PtParisB-libs" { = version } + "octez-protocol-020-PsParisC-libs" { = version } ] depopts: [ "octez-protocol-alpha-libs" diff --git a/opam/octez-dal-node.opam b/opam/octez-dal-node.opam index 4549b253a875..f82d78fac038 100644 --- a/opam/octez-dal-node.opam +++ b/opam/octez-dal-node.opam @@ -21,6 +21,7 @@ depends: [ "prometheus" { >= "1.2" } "octez-protocol-018-Proxford-libs" { = version } "octez-protocol-019-PtParisB-libs" { = version } + "octez-protocol-020-PsParisC-libs" { = version } ] depopts: [ "octez-protocol-alpha-libs" diff --git a/opam/octez-injector-server.opam b/opam/octez-injector-server.opam index 7bc6327c9fb9..ab690072c024 100644 --- a/opam/octez-injector-server.opam +++ b/opam/octez-injector-server.opam @@ -18,11 +18,13 @@ depends: [ depopts: [ "tezos-injector-018-Proxford" "tezos-injector-019-PtParisB" + "tezos-injector-020-PsParisC" "tezos-injector-alpha" ] conflicts: [ "tezos-injector-018-Proxford" { != version } "tezos-injector-019-PtParisB" { != version } + "tezos-injector-020-PsParisC" { != version } "tezos-injector-alpha" { != version } ] build: [ diff --git a/opam/octez-node.opam b/opam/octez-node.opam index 8d71c324d0bb..c1ec046d3d0d 100644 --- a/opam/octez-node.opam +++ b/opam/octez-node.opam @@ -26,6 +26,8 @@ depends: [ "octez-protocol-018-Proxford-libs" { = version } "tezos-protocol-019-PtParisB" { = version } "octez-protocol-019-PtParisB-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "octez-protocol-020-PsParisC-libs" { = version } ] depopts: [ "tezos-protocol-genesis" diff --git a/opam/octez-protocol-020-PsParisC-libs.opam b/opam/octez-protocol-020-PsParisC-libs.opam new file mode 100644 index 000000000000..7f9c29212e8e --- /dev/null +++ b/opam/octez-protocol-020-PsParisC-libs.opam @@ -0,0 +1,41 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "ppx_expect" + "octez-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "octez-shell-libs" { = version } + "uri" { >= "3.1.0" } + "tezt" { >= "4.0.0" & < "5.0.0" } + "tezt-tezos" { = version } + "qcheck-alcotest" { >= "0.20" } + "octez-proto-libs" { = version } + "octez-version" { = version } + "tezos-dal-node-services" { = version } + "lwt-canceler" { >= "0.3" & < "0.4" } + "lwt-exit" + "data-encoding" { >= "1.0.1" & < "1.1" } + "octez-protocol-compiler" { = version } + "tezos-dal-node-lib" { = version } + "tezos-dac-lib" { = version } + "tezos-dac-client-lib" { = version } + "octez-injector" { = version } + "octez-l2-libs" { = version } + "octez-alcotezt" { with-test & = version } + "tezos-dac-node-lib" { with-test & = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Octez protocol 020-PsParisC libraries" diff --git a/opam/octez-proxy-server.opam b/opam/octez-proxy-server.opam index 90215beff338..bc2f57075096 100644 --- a/opam/octez-proxy-server.opam +++ b/opam/octez-proxy-server.opam @@ -42,6 +42,7 @@ depopts: [ "octez-protocol-017-PtNairob-libs" "octez-protocol-018-Proxford-libs" "octez-protocol-019-PtParisB-libs" + "octez-protocol-020-PsParisC-libs" "octez-protocol-alpha-libs" ] conflicts: [ @@ -67,6 +68,7 @@ conflicts: [ "octez-protocol-017-PtNairob-libs" { != version } "octez-protocol-018-Proxford-libs" { != version } "octez-protocol-019-PtParisB-libs" { != version } + "octez-protocol-020-PsParisC-libs" { != version } "octez-protocol-alpha-libs" { != version } ] build: [ diff --git a/opam/octez-smart-rollup-node-PsParisC.opam b/opam/octez-smart-rollup-node-PsParisC.opam new file mode 100644 index 000000000000..c1b7440f4ecd --- /dev/null +++ b/opam/octez-smart-rollup-node-PsParisC.opam @@ -0,0 +1,39 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "octez-shell-libs" { = version } + "octez-protocol-020-PsParisC-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "tezos-dal-node-services" { = version } + "tezos-dal-node-lib" { = version } + "tezos-dac-lib" { = version } + "tezos-dac-client-lib" { = version } + "octez-l2-libs" { = version } + "octez-crawler" { = version } + "data-encoding" { >= "1.0.1" & < "1.1" } + "octez-internal-libs" { = version } + "aches" { >= "1.0.0" } + "aches-lwt" { >= "1.0.0" } + "octez-injector" { = version } + "octez-smart-rollup-node-lib" { = version } + "octez-version" { = version } +] +conflicts: [ + "checkseum" { = "0.5.0" } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Protocol specific (for 020-PsParisC) library for smart rollup node" diff --git a/opam/octez-smart-rollup-node.opam b/opam/octez-smart-rollup-node.opam index 9cc6e3353cc1..116e98fe62fb 100644 --- a/opam/octez-smart-rollup-node.opam +++ b/opam/octez-smart-rollup-node.opam @@ -16,6 +16,7 @@ depends: [ "octez-smart-rollup-node-lib" { = version } "octez-smart-rollup-node-Proxford" { = version } "octez-smart-rollup-node-PtParisB" { = version } + "octez-smart-rollup-node-PsParisC" { = version } ] depopts: [ "octez-smart-rollup-node-PtNairob" diff --git a/opam/tezos-benchmark-020-PsParisC.opam b/opam/tezos-benchmark-020-PsParisC.opam new file mode 100644 index 000000000000..5a6d89517336 --- /dev/null +++ b/opam/tezos-benchmark-020-PsParisC.opam @@ -0,0 +1,27 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "tezos-micheline-rewriting" { = version } + "tezos-benchmark" { = version } + "tezos-benchmark-type-inference-020-PsParisC" { = version } + "tezos-protocol-020-PsParisC" { = version } + "hashcons" + "octez-protocol-020-PsParisC-libs" { = version } + "prbnmcn-stats" { = "0.0.6" } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: library for writing benchmarks (protocol-specific part)" diff --git a/opam/tezos-benchmark-type-inference-020-PsParisC.opam b/opam/tezos-benchmark-type-inference-020-PsParisC.opam new file mode 100644 index 000000000000..e24514250300 --- /dev/null +++ b/opam/tezos-benchmark-type-inference-020-PsParisC.opam @@ -0,0 +1,24 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "tezos-micheline-rewriting" { = version } + "tezos-protocol-020-PsParisC" { = version } + "hashcons" + "octez-protocol-020-PsParisC-libs" { with-test & = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos: type inference for partial Michelson expressions" diff --git a/opam/tezos-benchmarks-proto-020-PsParisC.opam b/opam/tezos-benchmarks-proto-020-PsParisC.opam new file mode 100644 index 000000000000..eae07c61918b --- /dev/null +++ b/opam/tezos-benchmarks-proto-020-PsParisC.opam @@ -0,0 +1,27 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "tezos-benchmark" { = version } + "tezos-benchmark-020-PsParisC" { = version } + "tezos-benchmark-type-inference-020-PsParisC" { = version } + "octez-shell-libs" { = version } + "octez-protocol-020-PsParisC-libs" { = version } + "octez-proto-libs" { = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol benchmarks" diff --git a/opam/tezos-injector-020-PsParisC.opam b/opam/tezos-injector-020-PsParisC.opam new file mode 100644 index 000000000000..79dd84fee280 --- /dev/null +++ b/opam/tezos-injector-020-PsParisC.opam @@ -0,0 +1,24 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "tezos-protocol-020-PsParisC" { = version } + "octez-injector" { = version } + "octez-protocol-020-PsParisC-libs" { = version } + "octez-shell-libs" { = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: protocol-specific library for the injector binary" diff --git a/opam/tezos-protocol-020-PsParisC-tests.opam b/opam/tezos-protocol-020-PsParisC-tests.opam new file mode 100644 index 000000000000..2bedc58f5034 --- /dev/null +++ b/opam/tezos-protocol-020-PsParisC-tests.opam @@ -0,0 +1,32 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "tezt" { with-test & >= "4.0.0" & < "5.0.0" } + "octez-libs" {with-test} + "octez-alcotezt" {with-test} + "octez-protocol-020-PsParisC-libs" {with-test} + "tezos-protocol-020-PsParisC" {with-test} + "tezos-benchmark" {with-test} + "tezos-benchmark-020-PsParisC" {with-test} + "tezos-benchmark-type-inference-020-PsParisC" {with-test} + "qcheck-alcotest" { with-test & >= "0.20" } + "tezt-tezos" {with-test} + "octez-shell-libs" {with-test} + "octez-proto-libs" {with-test} + "octez-l2-libs" {with-test} +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos/Protocol: tests for economic-protocol definition" diff --git a/opam/tezos-protocol-020-PsParisC.opam b/opam/tezos-protocol-020-PsParisC.opam new file mode 100644 index 000000000000..aae6464e4274 --- /dev/null +++ b/opam/tezos-protocol-020-PsParisC.opam @@ -0,0 +1,22 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-proto-libs" { = version } + "octez-shell-libs" { = version } + "octez-libs" { = version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Tezos protocol 020-PsParisC package" diff --git a/opam/tezos-sc-rollup-node-test.opam b/opam/tezos-sc-rollup-node-test.opam index bc6af69406f6..bcfc566bbdf1 100644 --- a/opam/tezos-sc-rollup-node-test.opam +++ b/opam/tezos-sc-rollup-node-test.opam @@ -19,6 +19,9 @@ depends: [ "tezos-protocol-019-PtParisB" {with-test} "octez-protocol-019-PtParisB-libs" {with-test} "octez-smart-rollup-node-PtParisB" {with-test} + "tezos-protocol-020-PsParisC" {with-test} + "octez-protocol-020-PsParisC-libs" {with-test} + "octez-smart-rollup-node-PsParisC" {with-test} "tezos-protocol-alpha" {with-test} "octez-protocol-alpha-libs" {with-test} "octez-smart-rollup-node-alpha" {with-test} diff --git a/opam/tezos-smart-rollup-node-lib-test.opam b/opam/tezos-smart-rollup-node-lib-test.opam index a9c1c17920f7..b043e3ffc018 100644 --- a/opam/tezos-smart-rollup-node-lib-test.opam +++ b/opam/tezos-smart-rollup-node-lib-test.opam @@ -21,6 +21,7 @@ depends: [ "octez-shell-libs" {with-test} "octez-smart-rollup-node-Proxford" {with-test} "octez-smart-rollup-node-PtParisB" {with-test} + "octez-smart-rollup-node-PsParisC" {with-test} ] depopts: [ "octez-smart-rollup-node-PtNairob" {with-test} diff --git a/script-inputs/active_protocol_versions b/script-inputs/active_protocol_versions index aa19dea4f2f3..764fb0a6af8e 100644 --- a/script-inputs/active_protocol_versions +++ b/script-inputs/active_protocol_versions @@ -1,3 +1,4 @@ 018-Proxford 019-PtParisB +020-PsParisC alpha diff --git a/script-inputs/active_protocol_versions_without_number b/script-inputs/active_protocol_versions_without_number index 4233f30fc70f..474c463c3de3 100644 --- a/script-inputs/active_protocol_versions_without_number +++ b/script-inputs/active_protocol_versions_without_number @@ -1,3 +1,4 @@ Proxford PtParisB +PsParisC alpha diff --git a/script-inputs/ci-opam-package-tests b/script-inputs/ci-opam-package-tests index 5f8550844e1e..554a7d3df0fe 100644 --- a/script-inputs/ci-opam-package-tests +++ b/script-inputs/ci-opam-package-tests @@ -1,8 +1,10 @@ bls12-381 all 7 octez-accuser-Proxford exec 1 +octez-accuser-PsParisC exec 1 octez-accuser-PtParisB exec 1 octez-alcotezt all 7 octez-baker-Proxford exec 1 +octez-baker-PsParisC exec 1 octez-baker-PtParisB exec 1 octez-client exec 1 octez-codec exec 1 @@ -19,8 +21,8 @@ octez-libs all 7 octez-node exec 1 octez-node-config all 4 octez-proto-libs all 6 -octez-protocol-000-Ps9mPmXa-libs all 2 -octez-protocol-001-PtCJ7pwo-libs all 2 +octez-protocol-000-Ps9mPmXa-libs all 3 +octez-protocol-001-PtCJ7pwo-libs all 3 octez-protocol-002-PsYLVpVv-libs all 3 octez-protocol-003-PsddFKi3-libs all 3 octez-protocol-004-Pt24m4xi-libs all 3 @@ -34,11 +36,12 @@ octez-protocol-011-PtHangz2-libs all 3 octez-protocol-012-Psithaca-libs all 3 octez-protocol-013-PtJakart-libs all 3 octez-protocol-014-PtKathma-libs all 3 -octez-protocol-015-PtLimaPt-libs all 3 +octez-protocol-015-PtLimaPt-libs all 4 octez-protocol-016-PtMumbai-libs all 2 octez-protocol-017-PtNairob-libs all 2 octez-protocol-018-Proxford-libs all 2 octez-protocol-019-PtParisB-libs all 2 +octez-protocol-020-PsParisC-libs all 2 octez-protocol-alpha-libs all 2 octez-protocol-compiler exec 6 octez-proxy-server exec 1 @@ -46,7 +49,8 @@ octez-rpc-process all 4 octez-shell-libs all 6 octez-signer exec 4 octez-smart-rollup-node exec 1 -octez-smart-rollup-node-Proxford all 1 +octez-smart-rollup-node-Proxford all 2 +octez-smart-rollup-node-PsParisC all 2 octez-smart-rollup-node-PtNairob all 2 octez-smart-rollup-node-PtParisB all 2 octez-smart-rollup-node-alpha all 2 @@ -83,12 +87,13 @@ tezos-protocol-013-PtJakart all 5 tezos-protocol-014-PtKathma all 5 tezos-protocol-015-PtLimaPt all 5 tezos-protocol-016-PtMumbai all 5 -tezos-protocol-017-PtNairob all 6 +tezos-protocol-017-PtNairob all 5 tezos-protocol-018-Proxford all 6 tezos-protocol-019-PtParisB all 6 +tezos-protocol-020-PsParisC all 6 tezos-protocol-alpha all 6 tezos-protocol-demo-counter all 6 tezos-protocol-demo-noops all 6 tezos-protocol-genesis all 6 -tezos-proxy-server-config all 7 +tezos-proxy-server-config all 6 tezt-tezos all 7 diff --git a/script-inputs/released-executables b/script-inputs/released-executables index 462897b18482..8616215cc396 100644 --- a/script-inputs/released-executables +++ b/script-inputs/released-executables @@ -9,6 +9,8 @@ octez-codec octez-client octez-admin-client octez-node +octez-accuser-PsParisC +octez-baker-PsParisC octez-accuser-PtParisB octez-baker-PtParisB octez-accuser-Proxford diff --git a/src/bin_client/dune b/src/bin_client/dune index 06c09878a9f3..795d9abf8c4d 100644 --- a/src/bin_client/dune +++ b/src/bin_client/dune @@ -119,6 +119,9 @@ octez-protocol-019-PtParisB-libs.client.commands-registration octez-protocol-019-PtParisB-libs.baking-commands.registration octez-protocol-019-PtParisB-libs.plugin + octez-protocol-020-PsParisC-libs.client.commands-registration + octez-protocol-020-PsParisC-libs.baking-commands.registration + octez-protocol-020-PsParisC-libs.plugin (select void_for_linking-octez-protocol-alpha-libs-client-commands-registration from (octez-protocol-alpha-libs.client.commands-registration -> void_for_linking-octez-protocol-alpha-libs-client-commands-registration.empty) (-> void_for_linking-octez-protocol-alpha-libs-client-commands-registration.empty)) diff --git a/src/bin_codec/dune b/src/bin_codec/dune index 779ec0b3d725..9db6dd1c061e 100644 --- a/src/bin_codec/dune +++ b/src/bin_codec/dune @@ -63,6 +63,9 @@ (select void_for_linking-octez-protocol-019-PtParisB-libs-client from (octez-protocol-019-PtParisB-libs.client -> void_for_linking-octez-protocol-019-PtParisB-libs-client.empty) (-> void_for_linking-octez-protocol-019-PtParisB-libs-client.empty)) + (select void_for_linking-octez-protocol-020-PsParisC-libs-client from + (octez-protocol-020-PsParisC-libs.client -> void_for_linking-octez-protocol-020-PsParisC-libs-client.empty) + (-> void_for_linking-octez-protocol-020-PsParisC-libs-client.empty)) (select void_for_linking-octez-protocol-alpha-libs-client from (octez-protocol-alpha-libs.client -> void_for_linking-octez-protocol-alpha-libs-client.empty) (-> void_for_linking-octez-protocol-alpha-libs-client.empty))) @@ -98,4 +101,5 @@ (write-file void_for_linking-octez-protocol-017-PtNairob-libs-client.empty "") (write-file void_for_linking-octez-protocol-018-Proxford-libs-client.empty "") (write-file void_for_linking-octez-protocol-019-PtParisB-libs-client.empty "") + (write-file void_for_linking-octez-protocol-020-PsParisC-libs-client.empty "") (write-file void_for_linking-octez-protocol-alpha-libs-client.empty "")))) diff --git a/src/bin_dac_client/dune b/src/bin_dac_client/dune index 0aa52d1b0acf..daa4ba07f13b 100644 --- a/src/bin_dac_client/dune +++ b/src/bin_dac_client/dune @@ -19,6 +19,7 @@ tezos-dac-client-lib octez-protocol-018-Proxford-libs.dac octez-protocol-019-PtParisB-libs.dac + octez-protocol-020-PsParisC-libs.dac (select void_for_linking-octez-protocol-alpha-libs-dac from (octez-protocol-alpha-libs.dac -> void_for_linking-octez-protocol-alpha-libs-dac.empty) (-> void_for_linking-octez-protocol-alpha-libs-dac.empty))) diff --git a/src/bin_dac_node/dune b/src/bin_dac_node/dune index 8a1f1d2994c2..8ad187fc8151 100644 --- a/src/bin_dac_node/dune +++ b/src/bin_dac_node/dune @@ -27,6 +27,7 @@ octez-internal-libs.irmin octez-protocol-018-Proxford-libs.dac octez-protocol-019-PtParisB-libs.dac + octez-protocol-020-PsParisC-libs.dac (select void_for_linking-octez-protocol-alpha-libs-dac from (octez-protocol-alpha-libs.dac -> void_for_linking-octez-protocol-alpha-libs-dac.empty) (-> void_for_linking-octez-protocol-alpha-libs-dac.empty))) diff --git a/src/bin_dal_node/dune b/src/bin_dal_node/dune index bcb6b9ed882e..4dfb156e4bb6 100644 --- a/src/bin_dal_node/dune +++ b/src/bin_dal_node/dune @@ -40,6 +40,7 @@ prometheus octez-protocol-018-Proxford-libs.dal octez-protocol-019-PtParisB-libs.dal + octez-protocol-020-PsParisC-libs.dal (select void_for_linking-octez-protocol-alpha-libs-dal from (octez-protocol-alpha-libs.dal -> void_for_linking-octez-protocol-alpha-libs-dal.empty) (-> void_for_linking-octez-protocol-alpha-libs-dal.empty))) diff --git a/src/bin_node/dune b/src/bin_node/dune index 69fc5865abc8..a36696825334 100644 --- a/src/bin_node/dune +++ b/src/bin_node/dune @@ -139,6 +139,8 @@ octez-protocol-018-Proxford-libs.plugin-registerer tezos-protocol-019-PtParisB.embedded-protocol octez-protocol-019-PtParisB-libs.plugin-registerer + tezos-protocol-020-PsParisC.embedded-protocol + octez-protocol-020-PsParisC-libs.plugin-registerer (select void_for_linking-tezos-protocol-alpha-embedded-protocol from (tezos-protocol-alpha.embedded-protocol -> void_for_linking-tezos-protocol-alpha-embedded-protocol.empty) (-> void_for_linking-tezos-protocol-alpha-embedded-protocol.empty)) diff --git a/src/bin_proxy_server/dune b/src/bin_proxy_server/dune index 6f15638a181d..bfdffc3cc7de 100644 --- a/src/bin_proxy_server/dune +++ b/src/bin_proxy_server/dune @@ -127,6 +127,12 @@ (select void_for_linking-octez-protocol-019-PtParisB-libs-plugin from (octez-protocol-019-PtParisB-libs.plugin -> void_for_linking-octez-protocol-019-PtParisB-libs-plugin.empty) (-> void_for_linking-octez-protocol-019-PtParisB-libs-plugin.empty)) + (select void_for_linking-octez-protocol-020-PsParisC-libs-client from + (octez-protocol-020-PsParisC-libs.client -> void_for_linking-octez-protocol-020-PsParisC-libs-client.empty) + (-> void_for_linking-octez-protocol-020-PsParisC-libs-client.empty)) + (select void_for_linking-octez-protocol-020-PsParisC-libs-plugin from + (octez-protocol-020-PsParisC-libs.plugin -> void_for_linking-octez-protocol-020-PsParisC-libs-plugin.empty) + (-> void_for_linking-octez-protocol-020-PsParisC-libs-plugin.empty)) (select void_for_linking-octez-protocol-alpha-libs-client from (octez-protocol-alpha-libs.client -> void_for_linking-octez-protocol-alpha-libs-client.empty) (-> void_for_linking-octez-protocol-alpha-libs-client.empty)) @@ -182,5 +188,7 @@ (write-file void_for_linking-octez-protocol-018-Proxford-libs-plugin.empty "") (write-file void_for_linking-octez-protocol-019-PtParisB-libs-client.empty "") (write-file void_for_linking-octez-protocol-019-PtParisB-libs-plugin.empty "") + (write-file void_for_linking-octez-protocol-020-PsParisC-libs-client.empty "") + (write-file void_for_linking-octez-protocol-020-PsParisC-libs-plugin.empty "") (write-file void_for_linking-octez-protocol-alpha-libs-client.empty "") (write-file void_for_linking-octez-protocol-alpha-libs-plugin.empty "")))) diff --git a/src/bin_smart_rollup_node/dune b/src/bin_smart_rollup_node/dune index acefc5583cc8..f7ad43eb41fb 100644 --- a/src/bin_smart_rollup_node/dune +++ b/src/bin_smart_rollup_node/dune @@ -20,6 +20,7 @@ (-> void_for_linking-octez_smart_rollup_node_PtNairob.empty)) octez_smart_rollup_node_Proxford octez_smart_rollup_node_PtParisB + octez_smart_rollup_node_PsParisC (select void_for_linking-octez_smart_rollup_node_alpha from (octez_smart_rollup_node_alpha -> void_for_linking-octez_smart_rollup_node_alpha.empty) (-> void_for_linking-octez_smart_rollup_node_alpha.empty))) diff --git a/src/lib_smart_rollup_node/test/helpers/dune b/src/lib_smart_rollup_node/test/helpers/dune index 4b51b57fbfe0..e94ebcee622f 100644 --- a/src/lib_smart_rollup_node/test/helpers/dune +++ b/src/lib_smart_rollup_node/test/helpers/dune @@ -21,6 +21,7 @@ (-> void_for_linking-octez_smart_rollup_node_PtNairob.empty)) octez_smart_rollup_node_Proxford octez_smart_rollup_node_PtParisB + octez_smart_rollup_node_PsParisC (select void_for_linking-octez_smart_rollup_node_alpha from (octez_smart_rollup_node_alpha -> void_for_linking-octez_smart_rollup_node_alpha.empty) (-> void_for_linking-octez_smart_rollup_node_alpha.empty))) diff --git a/src/proto_020_PsParisC/bin_accuser/dune b/src/proto_020_PsParisC/bin_accuser/dune index 503007b46e4d..20baed29a0b2 100644 --- a/src/proto_020_PsParisC/bin_accuser/dune +++ b/src/proto_020_PsParisC/bin_accuser/dune @@ -2,17 +2,17 @@ ; Edit file manifest/main.ml instead. (executable - (name main_accuser_019_PtParisB) - (public_name octez-accuser-PtParisB) - (package octez-accuser-PtParisB) + (name main_accuser_020_PsParisC) + (public_name octez-accuser-PsParisC) + (package octez-accuser-PsParisC) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.clic - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands - octez-protocol-019-PtParisB-libs.baking-commands + octez-protocol-020-PsParisC-libs.baking-commands octez-libs.stdlib-unix octez-shell-libs.client-base-unix) (link_flags @@ -22,9 +22,9 @@ (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC -open Tezos_client_commands - -open Tezos_baking_019_PtParisB_commands + -open Tezos_baking_020_PsParisC_commands -open Tezos_stdlib_unix -open Tezos_client_base_unix)) diff --git a/src/proto_020_PsParisC/bin_baker/dune b/src/proto_020_PsParisC/bin_baker/dune index 29400fb90f62..e85009f57d53 100644 --- a/src/proto_020_PsParisC/bin_baker/dune +++ b/src/proto_020_PsParisC/bin_baker/dune @@ -2,17 +2,17 @@ ; Edit file manifest/main.ml instead. (executable - (name main_baker_019_PtParisB) - (public_name octez-baker-PtParisB) - (package octez-baker-PtParisB) + (name main_baker_020_PsParisC) + (public_name octez-baker-PsParisC) + (package octez-baker-PsParisC) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.clic - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands - octez-protocol-019-PtParisB-libs.baking-commands + octez-protocol-020-PsParisC-libs.baking-commands octez-libs.stdlib-unix octez-shell-libs.client-base-unix) (link_flags @@ -22,9 +22,9 @@ (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC -open Tezos_client_commands - -open Tezos_baking_019_PtParisB_commands + -open Tezos_baking_020_PsParisC_commands -open Tezos_stdlib_unix -open Tezos_client_base_unix)) diff --git a/src/proto_020_PsParisC/lib_benchmark/dune b/src/proto_020_PsParisC/lib_benchmark/dune index 6e34995fefab..d9f6c0540e30 100644 --- a/src/proto_020_PsParisC/lib_benchmark/dune +++ b/src/proto_020_PsParisC/lib_benchmark/dune @@ -2,8 +2,8 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_benchmark_019_PtParisB) - (public_name tezos-benchmark-019-PtParisB) + (name tezos_benchmark_020_PsParisC) + (public_name tezos-benchmark-020-PsParisC) (libraries octez-libs.stdlib octez-libs.base @@ -11,12 +11,12 @@ octez-libs.micheline tezos-micheline-rewriting tezos-benchmark - tezos-benchmark-type-inference-019-PtParisB - tezos-protocol-019-PtParisB.protocol + tezos-benchmark-type-inference-020-PsParisC + tezos-protocol-020-PsParisC.protocol octez-libs.crypto - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.parameters hashcons - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers prbnmcn-stats) (library_flags (:standard -linkall)) (flags @@ -27,7 +27,7 @@ -open Tezos_micheline -open Tezos_micheline_rewriting -open Tezos_benchmark - -open Tezos_benchmark_type_inference_019_PtParisB - -open Tezos_protocol_019_PtParisB - -open Tezos_019_PtParisB_test_helpers) + -open Tezos_benchmark_type_inference_020_PsParisC + -open Tezos_protocol_020_PsParisC + -open Tezos_020_PsParisC_test_helpers) (private_modules kernel rules state_space)) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune index 451962a79cbb..252a64386f15 100644 --- a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/dune @@ -2,8 +2,8 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_benchmark_type_inference_019_PtParisB) - (public_name tezos-benchmark-type-inference-019-PtParisB) + (name tezos_benchmark_type_inference_020_PsParisC) + (public_name tezos-benchmark-type-inference-020-PsParisC) (instrumentation (backend bisect_ppx)) (libraries octez-libs.stdlib @@ -11,7 +11,7 @@ octez-libs.crypto octez-libs.micheline tezos-micheline-rewriting - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol hashcons) (flags (:standard) @@ -20,4 +20,4 @@ -open Tezos_crypto -open Tezos_micheline -open Tezos_micheline_rewriting - -open Tezos_protocol_019_PtParisB)) + -open Tezos_protocol_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune index b8e36d5fc439..487db1d3556b 100644 --- a/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune +++ b/src/proto_020_PsParisC/lib_benchmark/lib_benchmark_type_inference/test/dune @@ -6,24 +6,24 @@ (libraries octez-libs.micheline tezos-micheline-rewriting - tezos-benchmark-type-inference-019-PtParisB - tezos-protocol-019-PtParisB.protocol + tezos-benchmark-type-inference-020-PsParisC + tezos-protocol-020-PsParisC.protocol octez-libs.error-monad - octez-protocol-019-PtParisB-libs.client) + octez-protocol-020-PsParisC-libs.client) (link_flags (:standard) (:include %{workspace_root}/macos-link-flags.sexp)) (flags (:standard) -open Tezos_micheline - -open Tezos_benchmark_type_inference_019_PtParisB)) + -open Tezos_benchmark_type_inference_020_PsParisC)) (rule (alias runtest) - (package tezos-benchmark-type-inference-019-PtParisB) + (package tezos-benchmark-type-inference-020-PsParisC) (action (run %{dep:./test_uf.exe}))) (rule (alias runtest) - (package tezos-benchmark-type-inference-019-PtParisB) + (package tezos-benchmark-type-inference-020-PsParisC) (action (run %{dep:./test_inference.exe}))) diff --git a/src/proto_020_PsParisC/lib_benchmark/test/dune b/src/proto_020_PsParisC/lib_benchmark/test/dune index c679d23d8cbf..6fc4c5715245 100644 --- a/src/proto_020_PsParisC/lib_benchmark/test/dune +++ b/src/proto_020_PsParisC/lib_benchmark/test/dune @@ -11,11 +11,11 @@ octez-libs.base octez-libs.micheline tezos-micheline-rewriting - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol tezos-benchmark - tezos-benchmark-type-inference-019-PtParisB - tezos-benchmark-019-PtParisB - octez-protocol-019-PtParisB-libs.test-helpers + tezos-benchmark-type-inference-020-PsParisC + tezos-benchmark-020-PsParisC + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.error-monad prbnmcn-stats) (link_flags @@ -24,11 +24,11 @@ (flags (:standard) -open Tezos_micheline - -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_020_PsParisC -open Tezos_benchmark - -open Tezos_benchmark_type_inference_019_PtParisB - -open Tezos_benchmark_019_PtParisB - -open Tezos_019_PtParisB_test_helpers)) + -open Tezos_benchmark_type_inference_020_PsParisC + -open Tezos_benchmark_020_PsParisC + -open Tezos_020_PsParisC_test_helpers)) (rule (alias runtest_micheline_rewriting_data) diff --git a/src/proto_020_PsParisC/lib_benchmarks_proto/dune b/src/proto_020_PsParisC/lib_benchmarks_proto/dune index e03de329df4d..5786c6af507a 100644 --- a/src/proto_020_PsParisC/lib_benchmarks_proto/dune +++ b/src/proto_020_PsParisC/lib_benchmarks_proto/dune @@ -2,27 +2,27 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_benchmarks_proto_019_PtParisB) - (public_name tezos-benchmarks-proto-019-PtParisB) + (name tezos_benchmarks_proto_020_PsParisC) + (public_name tezos-benchmarks-proto-020-PsParisC) (instrumentation (backend bisect_ppx)) (libraries str octez-libs.stdlib octez-libs.base octez-libs.error-monad - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.parameters octez-libs.lazy-containers tezos-benchmark - tezos-benchmark-019-PtParisB - tezos-benchmark-type-inference-019-PtParisB - tezos-protocol-019-PtParisB.protocol + tezos-benchmark-020-PsParisC + tezos-benchmark-type-inference-020-PsParisC + tezos-protocol-020-PsParisC.protocol octez-libs.crypto octez-shell-libs.shell-benchmarks octez-libs.micheline - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.tezos-sapling - octez-protocol-019-PtParisB-libs.client - octez-protocol-019-PtParisB-libs.plugin + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.plugin octez-proto-libs.protocol-environment) (library_flags (:standard -linkall)) (flags @@ -31,14 +31,14 @@ -open Tezos_base -open Tezos_base.TzPervasives -open Tezos_error_monad - -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_020_PsParisC_parameters -open Tezos_lazy_containers -open Tezos_benchmark - -open Tezos_benchmark_019_PtParisB - -open Tezos_benchmark_type_inference_019_PtParisB - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB.Protocol + -open Tezos_benchmark_020_PsParisC + -open Tezos_benchmark_type_inference_020_PsParisC + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC.Protocol -open Tezos_micheline - -open Tezos_019_PtParisB_test_helpers - -open Tezos_client_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB)) + -open Tezos_020_PsParisC_test_helpers + -open Tezos_client_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_client/dune b/src/proto_020_PsParisC/lib_client/dune index 2e5d4d9b209e..77ab23077212 100644 --- a/src/proto_020_PsParisC/lib_client/dune +++ b/src/proto_020_PsParisC/lib_client/dune @@ -2,23 +2,23 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_client_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.client) + (name tezos_client_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.client) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.clic octez-shell-libs.shell-services octez-shell-libs.client-base - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.protocol.lifted + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.protocol.lifted octez-shell-libs.mockup-registration octez-shell-libs.proxy octez-shell-libs.signer-backends - octez-protocol-019-PtParisB-libs.plugin - tezos-protocol-019-PtParisB.parameters + octez-protocol-020-PsParisC-libs.plugin + tezos-protocol-020-PsParisC.parameters octez-libs.rpc - octez-protocol-019-PtParisB-libs.smart-rollup + octez-protocol-020-PsParisC-libs.smart-rollup uri) (inline_tests (flags -verbose) (modes native)) (preprocess (pps ppx_expect)) @@ -28,8 +28,8 @@ -open Tezos_base.TzPervasives -open Tezos_shell_services -open Tezos_client_base - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB_lifted - -open Tezos_protocol_plugin_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_smart_rollup_019_PtParisB)) + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC_lifted + -open Tezos_protocol_plugin_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_smart_rollup_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_client/test/dune b/src/proto_020_PsParisC/lib_client/test/dune index 6986c7c033ea..21a692d9c6dc 100644 --- a/src/proto_020_PsParisC/lib_client/test/dune +++ b/src/proto_020_PsParisC/lib_client/test/dune @@ -2,14 +2,14 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_client_test_tezt_lib) + (name src_proto_020_PsParisC_lib_client_test_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base octez-libs.micheline - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.protocol + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.protocol octez-libs.base-test-helpers octez-libs.test-helpers octez-alcotezt @@ -21,8 +21,8 @@ -open Tezt_core.Base -open Tezos_base.TzPervasives -open Tezos_micheline - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC -open Tezos_base_test_helpers -open Tezos_test_helpers -open Octez_alcotezt) @@ -36,7 +36,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_client_test_tezt_lib + src_proto_020_PsParisC_lib_client_test_tezt_lib tezt) (link_flags (:standard) @@ -45,7 +45,7 @@ (rule (alias runtest) - (package octez-protocol-019-PtParisB-libs) + (package octez-protocol-020-PsParisC-libs) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_client_commands/dune b/src/proto_020_PsParisC/lib_client_commands/dune index ed33aaddf65c..5a66524c3be1 100644 --- a/src/proto_020_PsParisC/lib_client_commands/dune +++ b/src/proto_020_PsParisC/lib_client_commands/dune @@ -2,14 +2,14 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_client_019_PtParisB_commands) - (public_name octez-protocol-019-PtParisB-libs.client.commands) + (name tezos_client_020_PsParisC_commands) + (public_name octez-protocol-020-PsParisC-libs.client.commands) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.clic - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.parameters octez-libs.stdlib-unix octez-proto-libs.protocol-environment octez-shell-libs.shell-services @@ -17,56 +17,56 @@ octez-shell-libs.mockup-registration octez-shell-libs.mockup-commands octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands octez-libs.rpc octez-shell-libs.client-base-unix - octez-protocol-019-PtParisB-libs.plugin + octez-protocol-020-PsParisC-libs.plugin uri) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters -open Tezos_stdlib_unix -open Tezos_shell_services -open Tezos_client_base - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_client_commands -open Tezos_client_base_unix - -open Tezos_protocol_plugin_019_PtParisB) + -open Tezos_protocol_plugin_020_PsParisC) (modules (:standard \ alpha_commands_registration))) (library - (name tezos_client_019_PtParisB_commands_registration) - (public_name octez-protocol-019-PtParisB-libs.client.commands-registration) + (name tezos_client_020_PsParisC_commands_registration) + (public_name octez-protocol-020-PsParisC-libs.client.commands-registration) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.clic - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.parameters octez-proto-libs.protocol-environment octez-shell-libs.shell-services octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands - octez-protocol-019-PtParisB-libs.client.commands - octez-protocol-019-PtParisB-libs.client.sapling + octez-protocol-020-PsParisC-libs.client.commands + octez-protocol-020-PsParisC-libs.client.sapling octez-libs.rpc - octez-protocol-019-PtParisB-libs.plugin) + octez-protocol-020-PsParisC-libs.plugin) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters -open Tezos_shell_services -open Tezos_client_base - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_client_commands - -open Tezos_client_019_PtParisB_commands - -open Tezos_client_sapling_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB) + -open Tezos_client_020_PsParisC_commands + -open Tezos_client_sapling_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC) (modules alpha_commands_registration)) diff --git a/src/proto_020_PsParisC/lib_client_sapling/dune b/src/proto_020_PsParisC/lib_client_sapling/dune index 0de513f3320b..c26311f881a6 100644 --- a/src/proto_020_PsParisC/lib_client_sapling/dune +++ b/src/proto_020_PsParisC/lib_client_sapling/dune @@ -2,8 +2,8 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_client_sapling_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.client.sapling) + (name tezos_client_sapling_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.client.sapling) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base @@ -12,17 +12,17 @@ octez-libs.stdlib-unix octez-shell-libs.client-base octez-shell-libs.signer-backends - octez-protocol-019-PtParisB-libs.client - octez-protocol-019-PtParisB-libs.client.commands - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.plugin) + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.client.commands + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.plugin) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives -open Tezos_stdlib_unix -open Tezos_client_base - -open Tezos_client_019_PtParisB - -open Tezos_client_019_PtParisB_commands - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB)) + -open Tezos_client_020_PsParisC + -open Tezos_client_020_PsParisC_commands + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_dac_plugin/dune b/src/proto_020_PsParisC/lib_dac_plugin/dune index b468f4bb4f1d..5aeaf4909a48 100644 --- a/src/proto_020_PsParisC/lib_dac_plugin/dune +++ b/src/proto_020_PsParisC/lib_dac_plugin/dune @@ -2,8 +2,8 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_dac_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.dac) + (name tezos_dac_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.dac) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base @@ -11,9 +11,9 @@ octez-libs.stdlib-unix tezos-dac-lib tezos-dac-client-lib - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.embedded-protocol - tezos-protocol-019-PtParisB.protocol) + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.embedded-protocol + tezos-protocol-020-PsParisC.protocol) (inline_tests (flags -verbose) (modes native)) (preprocess (pps ppx_expect)) (library_flags (:standard -linkall)) @@ -24,6 +24,6 @@ -open Tezos_stdlib_unix -open Tezos_dac_lib -open Tezos_dac_client_lib - -open Tezos_client_019_PtParisB - -open Tezos_embedded_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB)) + -open Tezos_client_020_PsParisC + -open Tezos_embedded_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_dac_plugin/test/dune b/src/proto_020_PsParisC/lib_dac_plugin/test/dune index 59768ef3b524..42057d13733d 100644 --- a/src/proto_020_PsParisC/lib_dac_plugin/test/dune +++ b/src/proto_020_PsParisC/lib_dac_plugin/test/dune @@ -2,15 +2,15 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_dac_plugin_test_tezt_lib) + (name src_proto_020_PsParisC_lib_dac_plugin_test_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base - octez-protocol-019-PtParisB-libs.dac - tezos-protocol-019-PtParisB.protocol + octez-protocol-020-PsParisC-libs.dac + tezos-protocol-020-PsParisC.protocol octez-libs.base-test-helpers - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers tezos-dac-lib tezos_dac_node_lib octez-alcotezt) @@ -20,10 +20,10 @@ -open Tezt_core -open Tezt_core.Base -open Tezos_base.TzPervasives - -open Tezos_dac_019_PtParisB - -open Tezos_protocol_019_PtParisB + -open Tezos_dac_020_PsParisC + -open Tezos_protocol_020_PsParisC -open Tezos_base_test_helpers - -open Tezos_019_PtParisB_test_helpers + -open Tezos_020_PsParisC_test_helpers -open Tezos_dac_lib -open Tezos_dac_node_lib -open Octez_alcotezt) @@ -33,7 +33,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_dac_plugin_test_tezt_lib + src_proto_020_PsParisC_lib_dac_plugin_test_tezt_lib tezt) (link_flags (:standard) @@ -42,7 +42,7 @@ (rule (alias runtest) - (package octez-protocol-019-PtParisB-libs) + (package octez-protocol-020-PsParisC-libs) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_dal/dune b/src/proto_020_PsParisC/lib_dal/dune index d981d929769f..ad448d3f7fc2 100644 --- a/src/proto_020_PsParisC/lib_dal/dune +++ b/src/proto_020_PsParisC/lib_dal/dune @@ -2,19 +2,19 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_dal_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.dal) + (name tezos_dal_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.dal) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-protocol-compiler.registerer octez-libs.stdlib-unix tezos-dal-node-lib - octez-protocol-019-PtParisB-libs.client - octez-protocol-019-PtParisB-libs.plugin - tezos-protocol-019-PtParisB.embedded-protocol - octez-protocol-019-PtParisB-libs.layer2-utils - tezos-protocol-019-PtParisB.protocol) + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.plugin + tezos-protocol-020-PsParisC.embedded-protocol + octez-protocol-020-PsParisC-libs.layer2-utils + tezos-protocol-020-PsParisC.protocol) (inline_tests (flags -verbose) (modes native)) (preprocess (pps ppx_expect)) (library_flags (:standard -linkall)) @@ -24,8 +24,8 @@ -open Tezos_protocol_registerer -open Tezos_stdlib_unix -open Tezos_dal_node_lib - -open Tezos_client_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB - -open Tezos_embedded_protocol_019_PtParisB - -open Tezos_layer2_utils_019_PtParisB - -open Tezos_protocol_019_PtParisB)) + -open Tezos_client_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC + -open Tezos_embedded_protocol_020_PsParisC + -open Tezos_layer2_utils_020_PsParisC + -open Tezos_protocol_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_dal/test/dune b/src/proto_020_PsParisC/lib_dal/test/dune index acfc24d2bde2..8b33d06f07ea 100644 --- a/src/proto_020_PsParisC/lib_dal/test/dune +++ b/src/proto_020_PsParisC/lib_dal/test/dune @@ -2,15 +2,15 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_dal_test_tezt_lib) + (name src_proto_020_PsParisC_lib_dal_test_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base - octez-protocol-019-PtParisB-libs.dal - tezos-protocol-019-PtParisB.protocol + octez-protocol-020-PsParisC-libs.dal + tezos-protocol-020-PsParisC.protocol octez-libs.base-test-helpers - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers octez-alcotezt) (library_flags (:standard -linkall)) (flags @@ -18,10 +18,10 @@ -open Tezt_core -open Tezt_core.Base -open Tezos_base.TzPervasives - -open Tezos_dal_019_PtParisB - -open Tezos_protocol_019_PtParisB + -open Tezos_dal_020_PsParisC + -open Tezos_protocol_020_PsParisC -open Tezos_base_test_helpers - -open Tezos_019_PtParisB_test_helpers + -open Tezos_020_PsParisC_test_helpers -open Octez_alcotezt) (modules test_dal_slot_frame_encoding test_helpers)) @@ -29,7 +29,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_dal_test_tezt_lib + src_proto_020_PsParisC_lib_dal_test_tezt_lib tezt) (link_flags (:standard) @@ -38,7 +38,7 @@ (rule (alias runtest) - (package octez-protocol-019-PtParisB-libs) + (package octez-protocol-020-PsParisC-libs) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_delegate/dune b/src/proto_020_PsParisC/lib_delegate/dune index 718f8d67e25c..6e23f4970a27 100644 --- a/src/proto_020_PsParisC/lib_delegate/dune +++ b/src/proto_020_PsParisC/lib_delegate/dune @@ -2,20 +2,20 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_baking_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.baking) + (name tezos_baking_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.baking) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.clic octez-version.value - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.protocol.lifted - octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.protocol.lifted + octez-protocol-020-PsParisC-libs.plugin octez-proto-libs.protocol-environment octez-shell-libs.shell-services octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands octez-libs.stdlib octez-libs.stdlib-unix @@ -35,12 +35,12 @@ (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB_lifted - -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC_lifted + -open Tezos_protocol_plugin_020_PsParisC -open Tezos_shell_services -open Tezos_client_base - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_client_commands -open Tezos_stdlib -open Tezos_stdlib_unix @@ -52,60 +52,60 @@ (modules (:standard \ Baking_commands Baking_commands_registration))) (library - (name tezos_baking_019_PtParisB_commands) - (public_name octez-protocol-019-PtParisB-libs.baking-commands) + (name tezos_baking_020_PsParisC_commands) + (public_name octez-protocol-020-PsParisC-libs.baking-commands) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.parameters octez-libs.stdlib-unix octez-proto-libs.protocol-environment octez-shell-libs.shell-services octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands - octez-protocol-019-PtParisB-libs.baking + octez-protocol-020-PsParisC-libs.baking octez-libs.rpc uri) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters -open Tezos_stdlib_unix -open Tezos_shell_services -open Tezos_client_base - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_client_commands - -open Tezos_baking_019_PtParisB) + -open Tezos_baking_020_PsParisC) (modules Baking_commands)) (library - (name tezos_baking_019_PtParisB_commands_registration) - (public_name octez-protocol-019-PtParisB-libs.baking-commands.registration) + (name tezos_baking_020_PsParisC_commands_registration) + (public_name octez-protocol-020-PsParisC-libs.baking-commands.registration) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-proto-libs.protocol-environment octez-shell-libs.shell-services octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands - octez-protocol-019-PtParisB-libs.baking - octez-protocol-019-PtParisB-libs.baking-commands + octez-protocol-020-PsParisC-libs.baking + octez-protocol-020-PsParisC-libs.baking-commands octez-libs.rpc) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_020_PsParisC -open Tezos_shell_services -open Tezos_client_base - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_client_commands - -open Tezos_baking_019_PtParisB - -open Tezos_baking_019_PtParisB_commands) + -open Tezos_baking_020_PsParisC + -open Tezos_baking_020_PsParisC_commands) (modules Baking_commands_registration)) diff --git a/src/proto_020_PsParisC/lib_delegate/test/dune b/src/proto_020_PsParisC/lib_delegate/test/dune index 699a5fa07970..dcc25854f43a 100644 --- a/src/proto_020_PsParisC/lib_delegate/test/dune +++ b/src/proto_020_PsParisC/lib_delegate/test/dune @@ -2,19 +2,19 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_delegate_test_tezt_lib) + (name src_proto_020_PsParisC_lib_delegate_test_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base octez-libs.test-helpers octez-libs.micheline - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.protocol + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.protocol octez-libs.base-test-helpers - octez-protocol-019-PtParisB-libs.bakings.mockup-simulator - octez-protocol-019-PtParisB-libs.baking - tezos-protocol-019-PtParisB.parameters + octez-protocol-020-PsParisC-libs.bakings.mockup-simulator + octez-protocol-020-PsParisC-libs.baking + tezos-protocol-020-PsParisC.parameters octez-libs.crypto octez-libs.event-logging-test-helpers uri) @@ -26,11 +26,11 @@ -open Tezos_base.TzPervasives -open Tezos_test_helpers -open Tezos_micheline - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC -open Tezos_base_test_helpers - -open Tezos_019_PtParisB_mockup_simulator - -open Tezos_baking_019_PtParisB + -open Tezos_020_PsParisC_mockup_simulator + -open Tezos_baking_020_PsParisC -open Tezos_event_logging_test_helpers) (modules test_scenario)) @@ -38,7 +38,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_delegate_test_tezt_lib + src_proto_020_PsParisC_lib_delegate_test_tezt_lib tezt) (link_flags (:standard) @@ -47,7 +47,7 @@ (rule (alias runtest) - (package octez-protocol-019-PtParisB-libs) + (package octez-protocol-020-PsParisC-libs) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune index 5a3b2c975dc2..4fdee5905eb5 100644 --- a/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune +++ b/src/proto_020_PsParisC/lib_delegate/test/mockup_simulator/dune @@ -2,32 +2,32 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_019_PtParisB_mockup_simulator) - (public_name octez-protocol-019-PtParisB-libs.bakings.mockup-simulator) + (name tezos_020_PsParisC_mockup_simulator) + (public_name octez-protocol-020-PsParisC-libs.bakings.mockup-simulator) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-commands - octez-protocol-019-PtParisB-libs.baking + octez-protocol-020-PsParisC-libs.baking octez-libs.stdlib-unix octez-shell-libs.client-base-unix - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.parameters octez-shell-libs.mockup octez-shell-libs.mockup-proxy octez-shell-libs.mockup-commands - octez-protocol-019-PtParisB-libs.baking.tenderbrute + octez-protocol-020-PsParisC-libs.baking.tenderbrute tezt.core) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB.Protocol - -open Tezos_client_019_PtParisB + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC.Protocol + -open Tezos_client_020_PsParisC -open Tezos_client_commands - -open Tezos_baking_019_PtParisB + -open Tezos_baking_020_PsParisC -open Tezos_stdlib_unix -open Tezos_client_base_unix - -open Tezos_protocol_019_PtParisB_parameters - -open Tenderbrute_019_PtParisB + -open Tezos_protocol_020_PsParisC_parameters + -open Tenderbrute_020_PsParisC -open Tezt_core)) diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune index e9661434fc68..842f678b3824 100644 --- a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/dune @@ -6,9 +6,9 @@ (libraries octez-libs.base octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.baking.tenderbrute) + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.baking.tenderbrute) (link_flags (:standard) (:include %{workspace_root}/macos-link-flags.sexp) @@ -18,6 +18,6 @@ -open Tezos_base.TzPervasives -open Tezos_base -open Tezos_client_base - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB - -open Tenderbrute_019_PtParisB)) + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC + -open Tenderbrute_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune index 945584a1c651..a63c5ffb2f29 100644 --- a/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune +++ b/src/proto_020_PsParisC/lib_delegate/test/tenderbrute/lib/dune @@ -2,20 +2,20 @@ ; Edit file manifest/main.ml instead. (library - (name tenderbrute_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.baking.tenderbrute) + (name tenderbrute_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.baking.tenderbrute) (libraries data-encoding octez-libs.base octez-libs.base.unix - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.client) + octez-protocol-020-PsParisC-libs.client) (flags (:standard) -open Data_encoding -open Tezos_base.TzPervasives -open Tezos_base - -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_020_PsParisC -open Tezos_client_base - -open Tezos_client_019_PtParisB)) + -open Tezos_client_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_injector/dune b/src/proto_020_PsParisC/lib_injector/dune index 6f6bba969ac9..c63ee0d2028e 100644 --- a/src/proto_020_PsParisC/lib_injector/dune +++ b/src/proto_020_PsParisC/lib_injector/dune @@ -2,22 +2,22 @@ ; Edit file manifest/main.ml instead. (library - (name octez_injector_PtParisB) - (package tezos-injector-019-PtParisB) + (name octez_injector_PsParisC) + (package tezos-injector-020-PsParisC) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-injector - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-base - octez-protocol-019-PtParisB-libs.plugin) + octez-protocol-020-PsParisC-libs.plugin) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_020_PsParisC -open Octez_injector - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_client_base - -open Tezos_protocol_plugin_019_PtParisB)) + -open Tezos_protocol_plugin_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_layer2_utils/dune b/src/proto_020_PsParisC/lib_layer2_utils/dune index d721314a5de4..8dce1168eb4e 100644 --- a/src/proto_020_PsParisC/lib_layer2_utils/dune +++ b/src/proto_020_PsParisC/lib_layer2_utils/dune @@ -2,18 +2,18 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_layer2_utils_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.layer2-utils) + (name tezos_layer2_utils_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.layer2-utils) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client) + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client) (inline_tests (flags -verbose) (modes native)) (preprocess (pps ppx_expect)) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB)) + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_parameters/dune b/src/proto_020_PsParisC/lib_parameters/dune index cd12c132259a..11db5fa597b0 100644 --- a/src/proto_020_PsParisC/lib_parameters/dune +++ b/src/proto_020_PsParisC/lib_parameters/dune @@ -2,26 +2,26 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_protocol_019_PtParisB_parameters) - (public_name tezos-protocol-019-PtParisB.parameters) + (name tezos_protocol_020_PsParisC_parameters) + (public_name tezos-protocol-020-PsParisC.parameters) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-proto-libs.protocol-environment - tezos-protocol-019-PtParisB.protocol) + tezos-protocol-020-PsParisC.protocol) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB) + -open Tezos_protocol_020_PsParisC) (modules (:standard \ gen))) (executable (name gen) (libraries octez-libs.base - tezos-protocol-019-PtParisB.parameters - tezos-protocol-019-PtParisB.protocol) + tezos-protocol-020-PsParisC.parameters + tezos-protocol-020-PsParisC.protocol) (link_flags (:standard) (:include %{workspace_root}/macos-link-flags.sexp) @@ -29,8 +29,8 @@ (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_protocol_019_PtParisB) + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_protocol_020_PsParisC) (modules gen)) (rule @@ -54,7 +54,7 @@ (action (run %{deps} --mainnet-with-chain-id))) (install - (package tezos-protocol-019-PtParisB) + (package tezos-protocol-020-PsParisC) (section lib) (files sandbox-parameters.json test-parameters.json mainnet-parameters.json diff --git a/src/proto_020_PsParisC/lib_plugin/dune b/src/proto_020_PsParisC/lib_plugin/dune index f9f974d571fb..3adf033c524f 100644 --- a/src/proto_020_PsParisC/lib_plugin/dune +++ b/src/proto_020_PsParisC/lib_plugin/dune @@ -2,35 +2,35 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_protocol_plugin_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.plugin) + (name tezos_protocol_plugin_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.plugin) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.smart-rollup) + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.smart-rollup) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_smart_rollup_019_PtParisB) + -open Tezos_protocol_020_PsParisC + -open Tezos_smart_rollup_020_PsParisC) (modules (:standard \ Plugin_registerer))) -(documentation (package octez-protocol-019-PtParisB-libs)) +(documentation (package octez-protocol-020-PsParisC-libs)) (library - (name tezos_protocol_plugin_019_PtParisB_registerer) - (public_name octez-protocol-019-PtParisB-libs.plugin-registerer) + (name tezos_protocol_plugin_020_PsParisC_registerer) + (public_name octez-protocol-020-PsParisC-libs.plugin-registerer) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.embedded-protocol - octez-protocol-019-PtParisB-libs.plugin + tezos-protocol-020-PsParisC.embedded-protocol + octez-protocol-020-PsParisC-libs.plugin octez-shell-libs.validation) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_embedded_protocol_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_embedded_protocol_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC -open Tezos_validation) (modules Plugin_registerer)) diff --git a/src/proto_020_PsParisC/lib_plugin/index.mld b/src/proto_020_PsParisC/lib_plugin/index.mld index 5df8df340496..0b6361df15b8 100644 --- a/src/proto_020_PsParisC/lib_plugin/index.mld +++ b/src/proto_020_PsParisC/lib_plugin/index.mld @@ -1,17 +1,17 @@ -{0 Octez-protocol-019-PtParisB-libs: octez protocol 019-PtParisB libraries} +{0 Octez-protocol-020-PsParisC-libs: octez protocol 020-PsParisC libraries} -This is a package containing some libraries related to the Tezos 019-PtParisB protocol. +This is a package containing some libraries related to the Tezos 020-PsParisC protocol. It contains the following libraries: -- {{!module-Tezos_019_PtParisB_test_helpers}Tezos_019_PtParisB_test_helpers}: Protocol testing framework -- {{!module-Tezos_baking_019_PtParisB}Tezos_baking_019_PtParisB}: Base library for `tezos-baker/accuser` -- {{!module-Tezos_baking_019_PtParisB_commands}Tezos_baking_019_PtParisB_commands}: Protocol-specific commands for baking -- {{!module-Tezos_client_019_PtParisB}Tezos_client_019_PtParisB}: Protocol specific library for `octez-client` -- {{!module-Tezos_dac_019_PtParisB}Tezos_dac_019_PtParisB}: Protocol specific library for the Data availability Committee -- {{!module-Tezos_dal_019_PtParisB}Tezos_dal_019_PtParisB}: Protocol specific library for the Data availability Layer -- {{!module-Tezos_layer2_utils_019_PtParisB}Tezos_layer2_utils_019_PtParisB}: Protocol specific library for Layer 2 utils -- {{!module-Tezos_protocol_plugin_019_PtParisB}Tezos_protocol_plugin_019_PtParisB}: Protocol plugin -- {{!module-Tezos_protocol_plugin_019_PtParisB_registerer}Tezos_protocol_plugin_019_PtParisB_registerer}: Protocol plugin registerer -- {{!module-Tezos_smart_rollup_019_PtParisB}Tezos_smart_rollup_019_PtParisB}: Protocol specific library of helpers for `tezos-smart-rollup` -- {{!module-Tezos_smart_rollup_layer2_019_PtParisB}Tezos_smart_rollup_layer2_019_PtParisB}: Protocol specific library for `tezos-smart-rollup` +- {{!module-Tezos_020_PsParisC_test_helpers}Tezos_020_PsParisC_test_helpers}: Protocol testing framework +- {{!module-Tezos_baking_020_PsParisC}Tezos_baking_020_PsParisC}: Base library for `tezos-baker/accuser` +- {{!module-Tezos_baking_020_PsParisC_commands}Tezos_baking_020_PsParisC_commands}: Protocol-specific commands for baking +- {{!module-Tezos_client_020_PsParisC}Tezos_client_020_PsParisC}: Protocol specific library for `octez-client` +- {{!module-Tezos_dac_020_PsParisC}Tezos_dac_020_PsParisC}: Protocol specific library for the Data availability Committee +- {{!module-Tezos_dal_020_PsParisC}Tezos_dal_020_PsParisC}: Protocol specific library for the Data availability Layer +- {{!module-Tezos_layer2_utils_020_PsParisC}Tezos_layer2_utils_020_PsParisC}: Protocol specific library for Layer 2 utils +- {{!module-Tezos_protocol_plugin_020_PsParisC}Tezos_protocol_plugin_020_PsParisC}: Protocol plugin +- {{!module-Tezos_protocol_plugin_020_PsParisC_registerer}Tezos_protocol_plugin_020_PsParisC_registerer}: Protocol plugin registerer +- {{!module-Tezos_smart_rollup_020_PsParisC}Tezos_smart_rollup_020_PsParisC}: Protocol specific library of helpers for `tezos-smart-rollup` +- {{!module-Tezos_smart_rollup_layer2_020_PsParisC}Tezos_smart_rollup_layer2_020_PsParisC}: Protocol specific library for `tezos-smart-rollup` diff --git a/src/proto_020_PsParisC/lib_plugin/test/dune b/src/proto_020_PsParisC/lib_plugin/test/dune index 2f0d3d088fae..5c0ca843966b 100644 --- a/src/proto_020_PsParisC/lib_plugin/test/dune +++ b/src/proto_020_PsParisC/lib_plugin/test/dune @@ -2,7 +2,7 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_plugin_test_tezt_lib) + (name src_proto_020_PsParisC_lib_plugin_test_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core @@ -14,10 +14,10 @@ qcheck-alcotest octez-libs.stdlib-unix octez-libs.micheline - octez-protocol-019-PtParisB-libs.plugin - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.parameters - octez-protocol-019-PtParisB-libs.test-helpers) + octez-protocol-020-PsParisC-libs.plugin + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.parameters + octez-protocol-020-PsParisC-libs.test-helpers) (library_flags (:standard -linkall)) (flags (:standard) @@ -28,11 +28,11 @@ -open Octez_alcotezt -open Tezos_test_helpers -open Tezos_micheline - -open Tezos_protocol_plugin_019_PtParisB - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB.Protocol - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_019_PtParisB_test_helpers) + -open Tezos_protocol_plugin_020_PsParisC + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC.Protocol + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_020_PsParisC_test_helpers) (modules helpers test_conflict_handler @@ -44,7 +44,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_plugin_test_tezt_lib + src_proto_020_PsParisC_lib_plugin_test_tezt_lib tezt) (link_flags (:standard) @@ -53,7 +53,7 @@ (rule (alias runtest) - (package octez-protocol-019-PtParisB-libs) + (package octez-protocol-020-PsParisC-libs) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/dune b/src/proto_020_PsParisC/lib_protocol/dune index 9406d4f624eb..609abf83b24c 100644 --- a/src/proto_020_PsParisC/lib_protocol/dune +++ b/src/proto_020_PsParisC/lib_protocol/dune @@ -2,35 +2,35 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_protocol_environment_019_PtParisB) - (public_name tezos-protocol-019-PtParisB.protocol.environment) + (name tezos_protocol_environment_020_PsParisC) + (public_name tezos-protocol-020-PsParisC.protocol.environment) (instrumentation (backend bisect_ppx)) (libraries octez-proto-libs.protocol-environment) (library_flags (:standard -linkall)) - (modules Tezos_protocol_environment_019_PtParisB)) + (modules Tezos_protocol_environment_020_PsParisC)) (rule - (targets tezos_protocol_environment_019_PtParisB.ml) + (targets tezos_protocol_environment_020_PsParisC.ml) (action (write-file %{targets} - "module Name = struct let name = \"019-PtParisB\" end\ninclude Tezos_protocol_environment.V12.Make(Name)()\n"))) + "module Name = struct let name = \"020-PsParisC\" end\ninclude Tezos_protocol_environment.V12.Make(Name)()\n"))) (library - (name tezos_raw_protocol_019_PtParisB) - (public_name tezos-protocol-019-PtParisB.protocol.raw) + (name tezos_raw_protocol_020_PsParisC) + (public_name tezos-protocol-020-PsParisC.protocol.raw) (instrumentation (backend bisect_ppx)) (libraries - tezos-protocol-019-PtParisB.protocol.environment) + tezos-protocol-020-PsParisC.protocol.environment) (library_flags (:standard -linkall)) (flags (:standard) -nostdlib -nopervasives - -open Tezos_protocol_environment_019_PtParisB - -open Tezos_protocol_environment_019_PtParisB.Pervasives - -open Tezos_protocol_environment_019_PtParisB.Error_monad) + -open Tezos_protocol_environment_020_PsParisC + -open Tezos_protocol_environment_020_PsParisC.Pervasives + -open Tezos_protocol_environment_020_PsParisC.Error_monad) (modules Misc Non_empty_string @@ -294,20 +294,20 @@ Main)) (library - (name tezos_protocol_019_PtParisB) - (public_name tezos-protocol-019-PtParisB.protocol) + (name tezos_protocol_020_PsParisC) + (public_name tezos-protocol-020-PsParisC.protocol) (instrumentation (backend bisect_ppx)) (libraries octez-proto-libs.protocol-environment octez-proto-libs.protocol-environment.sigs - tezos-protocol-019-PtParisB.protocol.raw) + tezos-protocol-020-PsParisC.protocol.raw) (flags (:standard) -nopervasives) - (modules Protocol Tezos_protocol_019_PtParisB)) + (modules Protocol Tezos_protocol_020_PsParisC)) (install - (package tezos-protocol-019-PtParisB) + (package tezos-protocol-020-PsParisC) (section lib) (files (TEZOS_PROTOCOL as protocol/raw/TEZOS_PROTOCOL))) @@ -316,14 +316,14 @@ (action (write-file %{targets} - "\nlet hash = Tezos_crypto.Hashed.Protocol_hash.of_b58check_exn \"PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ\"\nlet name = Tezos_protocol_environment_019_PtParisB.Name.name\ninclude Tezos_raw_protocol_019_PtParisB\ninclude Tezos_raw_protocol_019_PtParisB.Main\n"))) + "\nlet hash = Tezos_crypto.Hashed.Protocol_hash.of_b58check_exn \"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi\"\nlet name = Tezos_protocol_environment_020_PsParisC.Name.name\ninclude Tezos_raw_protocol_020_PsParisC\ninclude Tezos_raw_protocol_020_PsParisC.Main\n"))) (rule - (targets tezos_protocol_019_PtParisB.ml) + (targets tezos_protocol_020_PsParisC.ml) (action (write-file %{targets} - "\nmodule Environment = Tezos_protocol_environment_019_PtParisB\nmodule Protocol = Protocol\n"))) + "\nmodule Environment = Tezos_protocol_environment_020_PsParisC\nmodule Protocol = Protocol\n"))) (rule (alias runtest_compile_protocol) @@ -596,17 +596,17 @@ (action (run %{bin:octez-protocol-compiler} -warn-error +a .))) (library - (name tezos_protocol_019_PtParisB_lifted) - (public_name tezos-protocol-019-PtParisB.protocol.lifted) + (name tezos_protocol_020_PsParisC_lifted) + (public_name tezos-protocol-020-PsParisC.protocol.lifted) (instrumentation (backend bisect_ppx)) (libraries octez-proto-libs.protocol-environment octez-proto-libs.protocol-environment.sigs - tezos-protocol-019-PtParisB.protocol) + tezos-protocol-020-PsParisC.protocol) (flags (:standard) -nopervasives - -open Tezos_protocol_019_PtParisB) + -open Tezos_protocol_020_PsParisC) (modules Lifted_protocol)) (rule @@ -617,7 +617,7 @@ "\ninclude Environment.Lift (Protocol)\nlet hash = Protocol.hash\n"))) (library - (name tezos_protocol_019_PtParisB_functor) + (name tezos_protocol_020_PsParisC_functor) (libraries octez-proto-libs.protocol-environment octez-proto-libs.protocol-environment.sigs) @@ -901,11 +901,11 @@ (run %{bin:octez-protocol-compiler.octez-protocol-packer} %{src_dir}))))) (library - (name tezos_embedded_protocol_019_PtParisB) - (public_name tezos-protocol-019-PtParisB.embedded-protocol) + (name tezos_embedded_protocol_020_PsParisC) + (public_name tezos-protocol-020-PsParisC.embedded-protocol) (instrumentation (backend bisect_ppx)) (libraries - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-shell-libs.protocol-updater octez-proto-libs.protocol-environment) (library_flags (:standard -linkall)) @@ -1183,4 +1183,4 @@ %{targets} (chdir %{workspace_root} - (run %{bin:octez-embedded-protocol-packer} %{src_dir} 019_PtParisB))))) + (run %{bin:octez-embedded-protocol-packer} %{src_dir} 020_PsParisC))))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/dune b/src/proto_020_PsParisC/lib_protocol/test/helpers/dune index 6167b19c955f..999b4caafed5 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/helpers/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/dune @@ -2,41 +2,38 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_019_PtParisB_test_helpers) - (public_name octez-protocol-019-PtParisB-libs.test-helpers) + (name tezos_020_PsParisC_test_helpers) + (public_name octez-protocol-020-PsParisC-libs.test-helpers) (instrumentation (backend bisect_ppx)) (libraries tezt.core - octez-alcotezt + tezt-tezos tezt - octez-libs.base-test-helpers qcheck-alcotest octez-libs.test-helpers octez-libs.base octez-libs.micheline octez-libs.stdlib-unix - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.parameters octez-proto-libs.protocol-environment - octez-protocol-019-PtParisB-libs.plugin + octez-protocol-020-PsParisC-libs.plugin octez-shell-libs.shell-services octez-libs.plompiler octez-libs.crypto-dal - octez-protocol-019-PtParisB-libs.smart-rollup) + octez-protocol-020-PsParisC-libs.smart-rollup) (flags (:standard) -open Tezt_core -open Tezt_core.Base - -open Octez_alcotezt - -open Tezos_base_test_helpers -open Tezos_base.TzPervasives -open Tezos_micheline -open Tezos_stdlib_unix - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_protocol_plugin_019_PtParisB + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_protocol_plugin_020_PsParisC -open Tezos_shell_services -open Tezos_crypto_dal - -open Tezos_smart_rollup_019_PtParisB)) + -open Tezos_smart_rollup_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune index 422f3420d041..9b3d0f065130 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/consensus/dune @@ -3,17 +3,17 @@ (library (name - src_proto_019_PtParisB_lib_protocol_test_integration_consensus_tezt_lib) + src_proto_020_PsParisC_lib_protocol_test_integration_consensus_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-alcotezt octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.test-helpers + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.base-test-helpers - tezos-protocol-019-PtParisB.parameters - octez-protocol-019-PtParisB-libs.plugin) + tezos-protocol-020-PsParisC.parameters + octez-protocol-020-PsParisC-libs.plugin) (library_flags (:standard -linkall)) (flags (:standard) @@ -21,11 +21,11 @@ -open Tezt_core.Base -open Octez_alcotezt -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_019_PtParisB_test_helpers + -open Tezos_protocol_020_PsParisC + -open Tezos_020_PsParisC_test_helpers -open Tezos_base_test_helpers - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_protocol_plugin_019_PtParisB) + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_protocol_plugin_020_PsParisC) (modules test_baking test_consensus_key @@ -46,7 +46,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_integration_consensus_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_consensus_tezt_lib tezt) (link_flags (:standard) @@ -55,7 +55,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/dune index d4ede79ff063..e9a72d32f06a 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/dune @@ -2,7 +2,7 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_protocol_test_integration_tezt_lib) + (name src_proto_020_PsParisC_lib_protocol_test_integration_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core @@ -10,10 +10,10 @@ octez-libs.tezos-context octez-alcotezt octez-libs.base - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.protocol - tezos-protocol-019-PtParisB.parameters - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.protocol + tezos-protocol-020-PsParisC.parameters + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.base-test-helpers) (library_flags (:standard -linkall)) (flags @@ -22,16 +22,22 @@ -open Tezt_core.Base -open Octez_alcotezt -open Tezos_base.TzPervasives - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_019_PtParisB_test_helpers + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_020_PsParisC_test_helpers -open Tezos_base_test_helpers) (modules test_constants test_frozen_bonds test_adaptive_issuance_launch - test_adaptive_issuance_roundtrip + test_scenario_base + test_scenario_stake + test_scenario_rewards + test_scenario_autostaking + test_scenario_slashing + test_scenario_slashing_stakers + test_scenario_deactivation test_liquidity_baking test_storage_functions test_storage @@ -41,7 +47,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_integration_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_tezt_lib tezt) (link_flags (:standard) @@ -50,7 +56,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (deps (glob_files wasm_kernel/*.wasm)) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune index 35b93cb45f6b..826dafaa6a01 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/gas/dune @@ -2,14 +2,14 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_protocol_test_integration_gas_tezt_lib) + (name src_proto_020_PsParisC_lib_protocol_test_integration_gas_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-alcotezt octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.test-helpers + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.base-test-helpers) (library_flags (:standard -linkall)) (flags @@ -18,8 +18,8 @@ -open Tezt_core.Base -open Octez_alcotezt -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_019_PtParisB_test_helpers + -open Tezos_protocol_020_PsParisC + -open Tezos_020_PsParisC_test_helpers -open Tezos_base_test_helpers) (modules test_gas_costs test_gas_levels)) @@ -27,7 +27,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_integration_gas_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_gas_tezt_lib tezt) (link_flags (:standard) @@ -36,7 +36,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune index 352e6faced36..acc7a871ae8a 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/michelson/dune @@ -3,22 +3,22 @@ (library (name - src_proto_019_PtParisB_lib_protocol_test_integration_michelson_tezt_lib) + src_proto_020_PsParisC_lib_protocol_test_integration_michelson_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-alcotezt octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.test-helpers + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.base-test-helpers - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client tezos-benchmark octez-libs.micheline - tezos-benchmark-019-PtParisB - tezos-benchmark-type-inference-019-PtParisB - octez-protocol-019-PtParisB-libs.plugin - tezos-protocol-019-PtParisB.parameters) + tezos-benchmark-020-PsParisC + tezos-benchmark-type-inference-020-PsParisC + octez-protocol-020-PsParisC-libs.plugin + tezos-protocol-020-PsParisC.parameters) (library_flags (:standard -linkall)) (flags (:standard) @@ -26,14 +26,14 @@ -open Tezt_core.Base -open Octez_alcotezt -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_019_PtParisB_test_helpers + -open Tezos_protocol_020_PsParisC + -open Tezos_020_PsParisC_test_helpers -open Tezos_base_test_helpers - -open Tezos_client_019_PtParisB + -open Tezos_client_020_PsParisC -open Tezos_micheline - -open Tezos_benchmark_019_PtParisB - -open Tezos_benchmark_type_inference_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB) + -open Tezos_benchmark_020_PsParisC + -open Tezos_benchmark_type_inference_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC) (modules test_annotations test_block_time_instructions @@ -62,7 +62,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_integration_michelson_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_michelson_tezt_lib tezt) (link_flags (:standard) @@ -71,7 +71,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (deps (glob_files contracts/*) (glob_files patched_contracts/*) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune index d6f7b59ddcd5..2deac2b7d71f 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/operations/dune @@ -3,17 +3,17 @@ (library (name - src_proto_019_PtParisB_lib_protocol_test_integration_operations_tezt_lib) + src_proto_020_PsParisC_lib_protocol_test_integration_operations_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-alcotezt octez-libs.base - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client - octez-protocol-019-PtParisB-libs.test-helpers + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.base-test-helpers - octez-protocol-019-PtParisB-libs.plugin) + octez-protocol-020-PsParisC-libs.plugin) (library_flags (:standard -linkall)) (flags (:standard) @@ -21,11 +21,11 @@ -open Tezt_core.Base -open Octez_alcotezt -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB - -open Tezos_019_PtParisB_test_helpers + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC + -open Tezos_020_PsParisC_test_helpers -open Tezos_base_test_helpers - -open Tezos_protocol_plugin_019_PtParisB) + -open Tezos_protocol_plugin_020_PsParisC) (modules test_activation test_combined_operations @@ -44,7 +44,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_integration_operations_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_operations_tezt_lib tezt) (link_flags (:standard) @@ -53,7 +53,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (deps (glob_files contracts/*)) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune index 7b81904f2c9e..7aa4345821b4 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/validate/dune @@ -2,20 +2,20 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_protocol_test_integration_validate_tezt_lib) + (name src_proto_020_PsParisC_lib_protocol_test_integration_validate_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-alcotezt octez-libs.base - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol qcheck-alcotest - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-libs.test-helpers - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.base-test-helpers - tezos-protocol-019-PtParisB.parameters - octez-protocol-019-PtParisB-libs.plugin) + tezos-protocol-020-PsParisC.parameters + octez-protocol-020-PsParisC-libs.plugin) (library_flags (:standard -linkall)) (flags (:standard) @@ -23,13 +23,13 @@ -open Tezt_core.Base -open Octez_alcotezt -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC -open Tezos_test_helpers - -open Tezos_019_PtParisB_test_helpers + -open Tezos_020_PsParisC_test_helpers -open Tezos_base_test_helpers - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_protocol_plugin_019_PtParisB) + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_protocol_plugin_020_PsParisC) (modules generator_descriptors generators @@ -47,7 +47,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_integration_validate_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_validate_tezt_lib tezt) (link_flags (:standard) @@ -56,7 +56,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/pbt/dune b/src/proto_020_PsParisC/lib_protocol/test/pbt/dune index 750b149398e7..8c7f53504efd 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/pbt/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/pbt/dune @@ -2,26 +2,26 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_protocol_test_pbt_tezt_lib) + (name src_proto_020_PsParisC_lib_protocol_test_pbt_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base octez-libs.micheline - octez-protocol-019-PtParisB-libs.client - tezos-protocol-019-PtParisB.protocol + octez-protocol-020-PsParisC-libs.client + tezos-protocol-020-PsParisC.protocol octez-libs.tezos-context.merkle_proof_encoding octez-libs.test-helpers - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers octez-alcotezt qcheck-alcotest tezos-benchmark - tezos-benchmark-019-PtParisB - tezos-benchmark-type-inference-019-PtParisB - octez-protocol-019-PtParisB-libs.smart-rollup + tezos-benchmark-020-PsParisC + tezos-benchmark-type-inference-020-PsParisC + octez-protocol-020-PsParisC-libs.smart-rollup octez-libs.crypto-dal octez-libs.base-test-helpers - tezos-protocol-019-PtParisB.parameters) + tezos-protocol-020-PsParisC.parameters) (library_flags (:standard -linkall)) (flags (:standard) @@ -29,17 +29,17 @@ -open Tezt_core.Base -open Tezos_base.TzPervasives -open Tezos_micheline - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC -open Tezos_test_helpers - -open Tezos_019_PtParisB_test_helpers + -open Tezos_020_PsParisC_test_helpers -open Octez_alcotezt - -open Tezos_benchmark_019_PtParisB - -open Tezos_benchmark_type_inference_019_PtParisB - -open Tezos_smart_rollup_019_PtParisB + -open Tezos_benchmark_020_PsParisC + -open Tezos_benchmark_type_inference_020_PsParisC + -open Tezos_smart_rollup_020_PsParisC -open Tezos_crypto_dal -open Tezos_base_test_helpers - -open Tezos_protocol_019_PtParisB_parameters) + -open Tezos_protocol_020_PsParisC_parameters) (modules liquidity_baking_pbt saturation_fuzzing @@ -66,7 +66,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_pbt_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_pbt_tezt_lib tezt) (link_flags (:standard) @@ -75,7 +75,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_protocol/test/regression/dune b/src/proto_020_PsParisC/lib_protocol/test/regression/dune index ee981591859d..2d0cf1cacae0 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/regression/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/regression/dune @@ -2,16 +2,16 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_protocol_test_regression_tezt_lib) + (name src_proto_020_PsParisC_lib_protocol_test_regression_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base tezt-tezos - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.client - octez-protocol-019-PtParisB-libs.plugin - octez-protocol-019-PtParisB-libs.test-helpers + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.plugin + octez-protocol-020-PsParisC-libs.test-helpers octez-libs.micheline) (library_flags (:standard -linkall)) (flags @@ -20,10 +20,10 @@ -open Tezt_core.Base -open Tezos_base.TzPervasives -open Tezt_tezos - -open Tezos_protocol_019_PtParisB - -open Tezos_client_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB - -open Tezos_019_PtParisB_test_helpers + -open Tezos_protocol_020_PsParisC + -open Tezos_client_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC + -open Tezos_020_PsParisC_test_helpers -open Tezos_micheline) (modules test_logging)) @@ -31,7 +31,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_regression_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_regression_tezt_lib tezt) (link_flags (:standard) @@ -40,7 +40,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (deps (glob_files contracts/*.tz) (glob_files expected/test_logging.ml/*.out)) diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/dune b/src/proto_020_PsParisC/lib_protocol/test/unit/dune index ee17efd40360..87f0d50242ef 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/unit/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/dune @@ -2,21 +2,21 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_protocol_test_unit_tezt_lib) + (name src_proto_020_PsParisC_lib_protocol_test_unit_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base octez-libs.base-test-helpers octez-libs.micheline - octez-protocol-019-PtParisB-libs.client + octez-protocol-020-PsParisC-libs.client octez-shell-libs.client-base - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.parameters octez-proto-libs.protocol-environment octez-libs.stdlib-unix - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-libs.test-helpers - octez-protocol-019-PtParisB-libs.test-helpers + octez-protocol-020-PsParisC-libs.test-helpers octez-alcotezt octez-l2-libs.scoru-wasm-helpers octez-libs.stdlib @@ -31,11 +31,11 @@ -open Tezos_base.TzPervasives -open Tezos_base_test_helpers -open Tezos_micheline - -open Tezos_client_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters - -open Tezos_protocol_019_PtParisB + -open Tezos_client_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters + -open Tezos_protocol_020_PsParisC -open Tezos_test_helpers - -open Tezos_019_PtParisB_test_helpers + -open Tezos_020_PsParisC_test_helpers -open Octez_alcotezt -open Tezos_scoru_wasm_helpers -open Tezos_stdlib @@ -73,13 +73,15 @@ test_dal_slot_proof test_adaptive_issuance test_adaptive_issuance_ema - test_percentage)) + test_percentage + test_full_staking_balance_repr + test_slashing_percentage)) (executable (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_protocol_test_unit_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_unit_tezt_lib tezt) (link_flags (:standard) @@ -88,7 +90,7 @@ (rule (alias runtest) - (package tezos-protocol-019-PtParisB-tests) + (package tezos-protocol-020-PsParisC-tests) (enabled_if (<> false %{env:RUNTEZTALIAS=true})) (action (run %{dep:./main.exe}))) diff --git a/src/proto_020_PsParisC/lib_sc_rollup/dune b/src/proto_020_PsParisC/lib_sc_rollup/dune index 8eefbe36f7a5..3698ad22cfac 100644 --- a/src/proto_020_PsParisC/lib_sc_rollup/dune +++ b/src/proto_020_PsParisC/lib_sc_rollup/dune @@ -2,16 +2,16 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_smart_rollup_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.smart-rollup) + (name tezos_smart_rollup_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.smart-rollup) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol) + tezos-protocol-020-PsParisC.protocol) (inline_tests (flags -verbose) (modes native)) (preprocess (pps ppx_expect)) (library_flags (:standard -linkall)) (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB)) + -open Tezos_protocol_020_PsParisC)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune b/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune index 53e6ac4ca15f..e811074b24c9 100644 --- a/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune +++ b/src/proto_020_PsParisC/lib_sc_rollup_layer2/dune @@ -2,12 +2,12 @@ ; Edit file manifest/main.ml instead. (library - (name tezos_smart_rollup_layer2_019_PtParisB) - (public_name octez-protocol-019-PtParisB-libs.smart-rollup-layer2) + (name tezos_smart_rollup_layer2_020_PsParisC) + (public_name octez-protocol-020-PsParisC-libs.smart-rollup-layer2) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-injector octez-l2-libs.smart-rollup) (inline_tests (flags -verbose) (modes native)) @@ -16,6 +16,6 @@ (flags (:standard) -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_020_PsParisC -open Octez_injector -open Octez_smart_rollup)) diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/dune b/src/proto_020_PsParisC/lib_sc_rollup_node/dune index 05f2db089c34..72044de07183 100644 --- a/src/proto_020_PsParisC/lib_sc_rollup_node/dune +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/dune @@ -2,35 +2,35 @@ ; Edit file manifest/main.ml instead. (library - (name octez_smart_rollup_node_PtParisB) - (package octez-smart-rollup-node-PtParisB) + (name octez_smart_rollup_node_PsParisC) + (package octez-smart-rollup-node-PsParisC) (instrumentation (backend bisect_ppx)) (libraries octez-libs.base octez-libs.stdlib-unix octez-shell-libs.client-base octez-shell-libs.client-base-unix - octez-protocol-019-PtParisB-libs.client - octez-protocol-019-PtParisB-libs.dal + octez-protocol-020-PsParisC-libs.client + octez-protocol-020-PsParisC-libs.dal octez-libs.tezos-context.encoding octez-libs.tezos-context.helpers - tezos-protocol-019-PtParisB.protocol - octez-protocol-019-PtParisB-libs.plugin - tezos-protocol-019-PtParisB.parameters + tezos-protocol-020-PsParisC.protocol + octez-protocol-020-PsParisC-libs.plugin + tezos-protocol-020-PsParisC.parameters octez-libs.rpc octez-libs.rpc-http octez-libs.rpc-http-server octez-libs.tezos-workers tezos-dal-node-services tezos-dal-node-lib - octez-protocol-019-PtParisB-libs.dac + octez-protocol-020-PsParisC-libs.dac tezos-dac-lib tezos-dac-client-lib octez-shell-libs.shell-services octez-l2-libs.smart-rollup - octez-protocol-019-PtParisB-libs.smart-rollup - octez-protocol-019-PtParisB-libs.smart-rollup-layer2 - octez-protocol-019-PtParisB-libs.layer2-utils + octez-protocol-020-PsParisC-libs.smart-rollup + octez-protocol-020-PsParisC-libs.smart-rollup-layer2 + octez-protocol-020-PsParisC-libs.layer2-utils octez-l2-libs.layer2_store octez-crawler octez-libs.tree-encoding @@ -54,21 +54,21 @@ -open Tezos_stdlib_unix -open Tezos_client_base -open Tezos_client_base_unix - -open Tezos_client_019_PtParisB - -open Tezos_dal_019_PtParisB - -open Tezos_protocol_019_PtParisB - -open Tezos_protocol_plugin_019_PtParisB - -open Tezos_protocol_019_PtParisB_parameters + -open Tezos_client_020_PsParisC + -open Tezos_dal_020_PsParisC + -open Tezos_protocol_020_PsParisC + -open Tezos_protocol_plugin_020_PsParisC + -open Tezos_protocol_020_PsParisC_parameters -open Tezos_workers -open Tezos_dal_node_lib - -open Tezos_dac_019_PtParisB + -open Tezos_dac_020_PsParisC -open Tezos_dac_lib -open Tezos_dac_client_lib -open Tezos_shell_services -open Octez_smart_rollup - -open Tezos_smart_rollup_019_PtParisB - -open Tezos_smart_rollup_layer2_019_PtParisB - -open Tezos_layer2_utils_019_PtParisB + -open Tezos_smart_rollup_020_PsParisC + -open Tezos_smart_rollup_layer2_020_PsParisC + -open Tezos_layer2_utils_020_PsParisC -open Tezos_layer2_store -open Octez_crawler -open Octez_injector diff --git a/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune b/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune index c2210cafe793..c9684647e5fc 100644 --- a/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune +++ b/src/proto_020_PsParisC/lib_sc_rollup_node/test/dune @@ -2,15 +2,15 @@ ; Edit file manifest/main.ml instead. (library - (name src_proto_019_PtParisB_lib_sc_rollup_node_test_tezt_lib) + (name src_proto_020_PsParisC_lib_sc_rollup_node_test_tezt_lib) (instrumentation (backend bisect_ppx)) (libraries tezt.core octez-libs.base - tezos-protocol-019-PtParisB.protocol + tezos-protocol-020-PsParisC.protocol octez-libs.test-helpers - octez-protocol-019-PtParisB-libs.smart-rollup-layer2 - octez_smart_rollup_node_PtParisB + octez-protocol-020-PsParisC-libs.smart-rollup-layer2 + octez_smart_rollup_node_PsParisC octez-alcotezt) (library_flags (:standard -linkall)) (flags @@ -18,10 +18,10 @@ -open Tezt_core -open Tezt_core.Base -open Tezos_base.TzPervasives - -open Tezos_protocol_019_PtParisB + -open Tezos_protocol_020_PsParisC -open Tezos_test_helpers - -open Tezos_smart_rollup_layer2_019_PtParisB - -open Octez_smart_rollup_node_PtParisB + -open Tezos_smart_rollup_layer2_020_PsParisC + -open Octez_smart_rollup_node_PsParisC -open Octez_alcotezt) (modules serialized_proofs test_octez_conversions)) @@ -29,7 +29,7 @@ (name main) (instrumentation (backend bisect_ppx --bisect-sigterm)) (libraries - src_proto_019_PtParisB_lib_sc_rollup_node_test_tezt_lib + src_proto_020_PsParisC_lib_sc_rollup_node_test_tezt_lib tezt) (link_flags (:standard) diff --git a/tezt/tests/dune b/tezt/tests/dune index 78b99ae1a61d..d5747067ed03 100644 --- a/tezt/tests/dune +++ b/tezt/tests/dune @@ -34,6 +34,21 @@ src_proto_alpha_lib_dal_test_tezt_lib src_proto_alpha_lib_dac_plugin_test_tezt_lib src_proto_alpha_lib_client_test_tezt_lib + src_proto_020_PsParisC_lib_sc_rollup_node_test_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_unit_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_regression_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_pbt_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_validate_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_operations_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_michelson_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_gas_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_consensus_tezt_lib + src_proto_020_PsParisC_lib_protocol_test_integration_tezt_lib + src_proto_020_PsParisC_lib_plugin_test_tezt_lib + src_proto_020_PsParisC_lib_delegate_test_tezt_lib + src_proto_020_PsParisC_lib_dal_test_tezt_lib + src_proto_020_PsParisC_lib_dac_plugin_test_tezt_lib + src_proto_020_PsParisC_lib_client_test_tezt_lib src_proto_019_PtParisB_lib_sc_rollup_node_test_tezt_lib src_proto_019_PtParisB_lib_protocol_test_unit_tezt_lib src_proto_019_PtParisB_lib_protocol_test_regression_tezt_lib -- GitLab From 06e86efce5090955e1d3524b1bb4ba05982cd21b Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 21:52:43 +0200 Subject: [PATCH 05/16] Tezt: Add ParisC --- tezt/lib_alcotezt/alcotezt_utils.ml | 3 ++- tezt/lib_tezos/protocol.ml | 23 +++++++++++++++-------- tezt/lib_tezos/protocol.mli | 2 +- tezt/tests/adaptive_issuance.ml | 8 ++++---- tezt/tests/sc_rollup.ml | 5 +++-- tezt/tests/tickets.ml | 4 ++-- 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/tezt/lib_alcotezt/alcotezt_utils.ml b/tezt/lib_alcotezt/alcotezt_utils.ml index f53254add158..558ae15480d5 100644 --- a/tezt/lib_alcotezt/alcotezt_utils.ml +++ b/tezt/lib_alcotezt/alcotezt_utils.ml @@ -33,5 +33,6 @@ let is_proto_test file = | Some "016_PtMumbai" -> ["mumbai"] | Some "017_PtNairob" -> ["nairobi"] | Some "018_Proxford" -> ["oxford"] - | Some "019_PtParisB" -> ["paris"] + | Some "019_PtParisB" -> ["parisb"] + | Some "020_PsParisC" -> ["parisc"] | Some _ -> assert false diff --git a/tezt/lib_tezos/protocol.ml b/tezt/lib_tezos/protocol.ml index fe0b74521a6c..acf08f358af9 100644 --- a/tezt/lib_tezos/protocol.ml +++ b/tezt/lib_tezos/protocol.ml @@ -25,11 +25,13 @@ (*****************************************************************************) (* Declaration order must respect the version order. *) -type t = Paris | Alpha +type t = ParisB | ParisC | Alpha -let all = [Paris; Alpha] +let all = [ParisB; ParisC; Alpha] -let encoding = Data_encoding.string_enum [("paris", Paris); ("alpha", Alpha)] +let encoding = + Data_encoding.string_enum + [("parisb", ParisB); ("parisc", ParisC); ("alpha", Alpha)] type constants = | Constants_sandbox @@ -43,20 +45,22 @@ let constants_to_string = function | Constants_mainnet_with_chain_id -> "mainnet-with-chain-id" | Constants_test -> "test" -let name = function Alpha -> "Alpha" | Paris -> "Paris" +let name = function Alpha -> "Alpha" | ParisB -> "Parisb" | ParisC -> "Parisc" -let number = function Paris -> 019 | Alpha -> 020 +let number = function ParisB -> 019 | ParisC -> 020 | Alpha -> 021 let directory = function | Alpha -> "proto_alpha" - | Paris -> "proto_019_PtParisB" + | ParisB -> "proto_019_PtParisB" + | ParisC -> "proto_020_PsParisC" (* Test tags must be lowercase. *) let tag protocol = String.lowercase_ascii (name protocol) let hash = function | Alpha -> "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK" - | Paris -> "PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ" + | ParisB -> "PtParisBxoLz5gzMmn3d9WBQNoPSZakgnkMC2VNuQ3KXfUtUQeZ" + | ParisC -> "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi" let genesis_hash = "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im" @@ -265,7 +269,10 @@ let write_parameter_file : JSON.encode_to_file_u output_file parameters ; Lwt.return output_file -let previous_protocol = function Alpha -> Some Paris | Paris -> None +let previous_protocol = function + | Alpha -> Some ParisB + | ParisC -> Some ParisB + | ParisB -> None let has_predecessor p = previous_protocol p <> None diff --git a/tezt/lib_tezos/protocol.mli b/tezt/lib_tezos/protocol.mli index 2ebdb873e25f..845af10fb3ac 100644 --- a/tezt/lib_tezos/protocol.mli +++ b/tezt/lib_tezos/protocol.mli @@ -24,7 +24,7 @@ (*****************************************************************************) (** Protocols we may want to test with. *) -type t = Paris | Alpha +type t = ParisB | ParisC | Alpha val encoding : t Data_encoding.t diff --git a/tezt/tests/adaptive_issuance.ml b/tezt/tests/adaptive_issuance.ml index c3812b0b9f7c..8ae929431f09 100644 --- a/tezt/tests/adaptive_issuance.ml +++ b/tezt/tests/adaptive_issuance.ml @@ -214,7 +214,7 @@ let activate_ai protocol sandbox_client sandbox_endpoint = let test_AI_activation = Protocol.register_test ~__FILE__ - ~supports:Protocol.(From_protocol (number Paris)) + ~supports:Protocol.(From_protocol (number ParisB)) ~title:"AI Activation - test AI activation after feature vote" ~tags:["adaptive_issuance"; "staking"] @@ fun protocol -> @@ -303,7 +303,7 @@ let test_AI_activation = let test_AI_activation_bypass_vote = Protocol.register_test ~__FILE__ - ~supports:Protocol.(From_protocol (number Paris)) + ~supports:Protocol.(From_protocol (number ParisB)) ~title: "AI Activation - test AI activation with feature flag force_activation \ set" @@ -473,7 +473,7 @@ let test_staking = ~__FILE__ ~title: "Staking - test staking with delegate and staker in a simple scenario" - ~supports:Protocol.(From_protocol (number Paris)) + ~supports:Protocol.(From_protocol (number ParisB)) ~tags: [ "adaptive_issuance"; @@ -1415,7 +1415,7 @@ let check_rpc_ok client rpc = let test_fix_delegated_balance = Protocol.register_test ~__FILE__ - ~supports:Protocol.(From_protocol (number Paris)) + ~supports:Protocol.(From_protocol (number ParisB)) ~title:"Test protocol fix for delegated balance rpc" ~tags:["rpc"; "delegated_balance"] @@ fun protocol -> diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index c9e3393eccee..856df037d4a5 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -42,10 +42,11 @@ open Sc_rollup_helpers *) -let default_wasm_pvm_revision = function Protocol.Alpha | Paris -> "2.0.0-r4" +let default_wasm_pvm_revision = function + | Protocol.Alpha | ParisB | ParisC -> "2.0.0-r4" let max_nb_ticks = function - | Protocol.Paris -> 50_000_000_000_000 + | Protocol.ParisB | ParisC -> 50_000_000_000_000 | Alpha -> 11_000_000_000 let get_outbox_proof ?rpc_hooks ~__LOC__ sc_rollup_node ~message_index diff --git a/tezt/tests/tickets.ml b/tezt/tests/tickets.ml index 3f40d824cc70..225712a09706 100644 --- a/tezt/tests/tickets.ml +++ b/tezt/tests/tickets.ml @@ -350,7 +350,7 @@ let test_direct_transfer_tickets_from_implicit_account_to_originated_with_pair_c ~__FILE__ ~title:"Send Pair tickets from implicit account to originated directly" ~tags:["client"; "michelson"; "implicit"; "ticket"; "originated"] - ~supports:(Protocol.From_protocol 20) + ~supports:(Protocol.From_protocol 21) @@ fun protocol -> test_direct_transfer_tickets_from_implicit_account_to_originated protocol @@ -554,7 +554,7 @@ let test_direct_transfer_tickets_from_implicit_account_to_originated_complex_wit "Send Pair tickets (with complex parameters) from implicit account to \ originated directly" ~tags:["client"; "michelson"; "implicit"; "ticket"; "originated"] - ~supports:(Protocol.From_protocol 20) + ~supports:(Protocol.From_protocol 21) @@ fun protocol -> test_direct_transfer_tickets_from_implicit_account_to_originated_complex protocol -- GitLab From f9041f8a7206c8eaed035c9f94ee5ed415e2968d Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Thu, 13 Jun 2024 00:39:14 +0200 Subject: [PATCH 06/16] CI: Regenerate CI --- .gitlab/ci/jobs/packaging/opam_package.yml | 356 +++++++++++++++++++-- 1 file changed, 338 insertions(+), 18 deletions(-) diff --git a/.gitlab/ci/jobs/packaging/opam_package.yml b/.gitlab/ci/jobs/packaging/opam_package.yml index 3a07bc196566..b15356162116 100644 --- a/.gitlab/ci/jobs/packaging/opam_package.yml +++ b/.gitlab/ci/jobs/packaging/opam_package.yml @@ -193,6 +193,70 @@ opam:octez-accuser-PtParisB: when: always retry: 2 +opam:octez-accuser-PtParisC: + image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} + stage: packaging + tags: + - gcp + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" + when: delayed + start_in: 1 minute + - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ + when: delayed + start_in: 1 minute + - changes: + - '**/dune' + - '**/dune.inc' + - '**/*.dune.inc' + - '**/dune-project' + - '**/dune-workspace' + - '**/*.opam' + - .gitlab/ci/jobs/packaging/opam:prepare.yml + - .gitlab/ci/jobs/packaging/opam_package.yml + - manifest/manifest.ml + - manifest/main.ml + - scripts/opam-prepare-repo.sh + - scripts/version.sh + if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: delayed + start_in: 1 minute + - when: never + needs: + - opam:prepare + dependencies: + - opam:prepare + cache: + key: opam-sccache + paths: + - _build/_sccache + before_script: + - eval $(opam env) + - mkdir -p $CI_PROJECT_DIR/opam_logs + - . ./scripts/ci/sccache-start.sh + script: + - opam remote add dev-repo ./_opam-repo-for-release + - opam install --yes ${package}.dev + - opam reinstall --yes --with-test ${package}.dev + after_script: + - sccache --stop-server || true + - eval $(opam env) + - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh + variables: + RUNTEZTALIAS: "true" + package: octez-accuser-PtParisC + SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache + RUSTC_WRAPPER: sccache + SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log + SCCACHE_IDLE_TIMEOUT: "0" + SCCACHE_LOG: debug + artifacts: + expire_in: 1 week + paths: + - opam_logs/ + when: always + retry: 2 + opam:octez-alcotezt: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging @@ -385,6 +449,70 @@ opam:octez-baker-PtParisB: when: always retry: 2 +opam:octez-baker-PtParisC: + image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} + stage: packaging + tags: + - gcp + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" + when: delayed + start_in: 1 minute + - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ + when: delayed + start_in: 1 minute + - changes: + - '**/dune' + - '**/dune.inc' + - '**/*.dune.inc' + - '**/dune-project' + - '**/dune-workspace' + - '**/*.opam' + - .gitlab/ci/jobs/packaging/opam:prepare.yml + - .gitlab/ci/jobs/packaging/opam_package.yml + - manifest/manifest.ml + - manifest/main.ml + - scripts/opam-prepare-repo.sh + - scripts/version.sh + if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: delayed + start_in: 1 minute + - when: never + needs: + - opam:prepare + dependencies: + - opam:prepare + cache: + key: opam-sccache + paths: + - _build/_sccache + before_script: + - eval $(opam env) + - mkdir -p $CI_PROJECT_DIR/opam_logs + - . ./scripts/ci/sccache-start.sh + script: + - opam remote add dev-repo ./_opam-repo-for-release + - opam install --yes ${package}.dev + - opam reinstall --yes --with-test ${package}.dev + after_script: + - sccache --stop-server || true + - eval $(opam env) + - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh + variables: + RUNTEZTALIAS: "true" + package: octez-baker-PtParisC + SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache + RUSTC_WRAPPER: sccache + SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log + SCCACHE_IDLE_TIMEOUT: "0" + SCCACHE_LOG: debug + artifacts: + expire_in: 1 week + paths: + - opam_logs/ + when: always + retry: 2 + opam:octez-client: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging @@ -1353,10 +1481,10 @@ opam:octez-protocol-000-Ps9mPmXa-libs: rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" when: delayed - start_in: 2 minutes + start_in: 3 minutes - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ when: delayed - start_in: 2 minutes + start_in: 3 minutes - changes: - '**/dune' - '**/dune.inc' @@ -1372,7 +1500,7 @@ opam:octez-protocol-000-Ps9mPmXa-libs: - scripts/version.sh if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" when: delayed - start_in: 2 minutes + start_in: 3 minutes - when: never needs: - opam:prepare @@ -1417,10 +1545,10 @@ opam:octez-protocol-001-PtCJ7pwo-libs: rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" when: delayed - start_in: 2 minutes + start_in: 3 minutes - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ when: delayed - start_in: 2 minutes + start_in: 3 minutes - changes: - '**/dune' - '**/dune.inc' @@ -1436,7 +1564,7 @@ opam:octez-protocol-001-PtCJ7pwo-libs: - scripts/version.sh if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" when: delayed - start_in: 2 minutes + start_in: 3 minutes - when: never needs: - opam:prepare @@ -2313,10 +2441,10 @@ opam:octez-protocol-015-PtLimaPt-libs: rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" when: delayed - start_in: 3 minutes + start_in: 4 minutes - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ when: delayed - start_in: 3 minutes + start_in: 4 minutes - changes: - '**/dune' - '**/dune.inc' @@ -2332,7 +2460,7 @@ opam:octez-protocol-015-PtLimaPt-libs: - scripts/version.sh if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" when: delayed - start_in: 3 minutes + start_in: 4 minutes - when: never needs: - opam:prepare @@ -2625,6 +2753,70 @@ opam:octez-protocol-019-PtParisB-libs: when: always retry: 2 +opam:octez-protocol-020-PtParisC-libs: + image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} + stage: packaging + tags: + - gcp + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" + when: delayed + start_in: 2 minutes + - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ + when: delayed + start_in: 2 minutes + - changes: + - '**/dune' + - '**/dune.inc' + - '**/*.dune.inc' + - '**/dune-project' + - '**/dune-workspace' + - '**/*.opam' + - .gitlab/ci/jobs/packaging/opam:prepare.yml + - .gitlab/ci/jobs/packaging/opam_package.yml + - manifest/manifest.ml + - manifest/main.ml + - scripts/opam-prepare-repo.sh + - scripts/version.sh + if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" + when: delayed + start_in: 2 minutes + - when: never + needs: + - opam:prepare + dependencies: + - opam:prepare + cache: + key: opam-sccache + paths: + - _build/_sccache + before_script: + - eval $(opam env) + - mkdir -p $CI_PROJECT_DIR/opam_logs + - . ./scripts/ci/sccache-start.sh + script: + - opam remote add dev-repo ./_opam-repo-for-release + - opam install --yes ${package}.dev + - opam reinstall --yes --with-test ${package}.dev + after_script: + - sccache --stop-server || true + - eval $(opam env) + - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh + variables: + RUNTEZTALIAS: "true" + package: octez-protocol-020-PtParisC-libs + SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache + RUSTC_WRAPPER: sccache + SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log + SCCACHE_IDLE_TIMEOUT: "0" + SCCACHE_LOG: debug + artifacts: + expire_in: 1 week + paths: + - opam_logs/ + when: always + retry: 2 + opam:octez-protocol-alpha-libs: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging @@ -3081,10 +3273,10 @@ opam:octez-smart-rollup-node-Proxford: rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" when: delayed - start_in: 1 minute + start_in: 2 minutes - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ when: delayed - start_in: 1 minute + start_in: 2 minutes - changes: - '**/dune' - '**/dune.inc' @@ -3100,7 +3292,7 @@ opam:octez-smart-rollup-node-Proxford: - scripts/version.sh if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" when: delayed - start_in: 1 minute + start_in: 2 minutes - when: never needs: - opam:prepare @@ -3265,6 +3457,70 @@ opam:octez-smart-rollup-node-PtParisB: when: always retry: 2 +opam:octez-smart-rollup-node-PtParisC: + image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} + stage: packaging + tags: + - gcp + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" + when: delayed + start_in: 2 minutes + - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ + when: delayed + start_in: 2 minutes + - changes: + - '**/dune' + - '**/dune.inc' + - '**/*.dune.inc' + - '**/dune-project' + - '**/dune-workspace' + - '**/*.opam' + - .gitlab/ci/jobs/packaging/opam:prepare.yml + - .gitlab/ci/jobs/packaging/opam_package.yml + - manifest/manifest.ml + - manifest/main.ml + - scripts/opam-prepare-repo.sh + - scripts/version.sh + if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" + when: delayed + start_in: 2 minutes + - when: never + needs: + - opam:prepare + dependencies: + - opam:prepare + cache: + key: opam-sccache + paths: + - _build/_sccache + before_script: + - eval $(opam env) + - mkdir -p $CI_PROJECT_DIR/opam_logs + - . ./scripts/ci/sccache-start.sh + script: + - opam remote add dev-repo ./_opam-repo-for-release + - opam install --yes ${package}.dev + - opam reinstall --yes --with-test ${package}.dev + after_script: + - sccache --stop-server || true + - eval $(opam env) + - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh + variables: + RUNTEZTALIAS: "true" + package: octez-smart-rollup-node-PtParisC + SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache + RUSTC_WRAPPER: sccache + SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log + SCCACHE_IDLE_TIMEOUT: "0" + SCCACHE_LOG: debug + artifacts: + expire_in: 1 week + paths: + - opam_logs/ + when: always + retry: 2 + opam:octez-smart-rollup-node-alpha: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging @@ -5449,10 +5705,10 @@ opam:tezos-protocol-017-PtNairob: rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" when: delayed - start_in: 6 minutes + start_in: 5 minutes - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ when: delayed - start_in: 6 minutes + start_in: 5 minutes - changes: - '**/dune' - '**/dune.inc' @@ -5468,7 +5724,7 @@ opam:tezos-protocol-017-PtNairob: - scripts/version.sh if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" when: delayed - start_in: 6 minutes + start_in: 5 minutes - when: never needs: - opam:prepare @@ -5633,6 +5889,70 @@ opam:tezos-protocol-019-PtParisB: when: always retry: 2 +opam:tezos-protocol-020-PtParisC: + image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} + stage: packaging + tags: + - gcp + rules: + - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" + when: delayed + start_in: 6 minutes + - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ + when: delayed + start_in: 6 minutes + - changes: + - '**/dune' + - '**/dune.inc' + - '**/*.dune.inc' + - '**/dune-project' + - '**/dune-workspace' + - '**/*.opam' + - .gitlab/ci/jobs/packaging/opam:prepare.yml + - .gitlab/ci/jobs/packaging/opam_package.yml + - manifest/manifest.ml + - manifest/main.ml + - scripts/opam-prepare-repo.sh + - scripts/version.sh + if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" + when: delayed + start_in: 6 minutes + - when: never + needs: + - opam:prepare + dependencies: + - opam:prepare + cache: + key: opam-sccache + paths: + - _build/_sccache + before_script: + - eval $(opam env) + - mkdir -p $CI_PROJECT_DIR/opam_logs + - . ./scripts/ci/sccache-start.sh + script: + - opam remote add dev-repo ./_opam-repo-for-release + - opam install --yes ${package}.dev + - opam reinstall --yes --with-test ${package}.dev + after_script: + - sccache --stop-server || true + - eval $(opam env) + - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh + variables: + RUNTEZTALIAS: "true" + package: tezos-protocol-020-PtParisC + SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache + RUSTC_WRAPPER: sccache + SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log + SCCACHE_IDLE_TIMEOUT: "0" + SCCACHE_LOG: debug + artifacts: + expire_in: 1 week + paths: + - opam_logs/ + when: always + retry: 2 + opam:tezos-protocol-alpha: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging @@ -5897,10 +6217,10 @@ opam:tezos-proxy-server-config: rules: - if: $CI_PIPELINE_SOURCE == "schedule" && $TZ_SCHEDULE_KIND == "EXTENDED_TESTS" when: delayed - start_in: 7 minutes + start_in: 6 minutes - if: $CI_MERGE_REQUEST_LABELS =~ /(?:^|,)ci--opam(?:$|,)/ when: delayed - start_in: 7 minutes + start_in: 6 minutes - changes: - '**/dune' - '**/dune.inc' @@ -5916,7 +6236,7 @@ opam:tezos-proxy-server-config: - scripts/version.sh if: $CI_PIPELINE_SOURCE == "merge_request_event" && $GITLAB_USER_LOGIN == "nomadic-margebot" when: delayed - start_in: 7 minutes + start_in: 6 minutes - when: never needs: - opam:prepare -- GitLab From 3da0150982532592d205659c28fc009baf7bae4c Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 18:49:14 +0200 Subject: [PATCH 07/16] ParisC: backport !13619 --- .../lib_delegate/state_transitions.ml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/proto_020_PsParisC/lib_delegate/state_transitions.ml b/src/proto_020_PsParisC/lib_delegate/state_transitions.ml index efba1fd1d252..7610ea010eb7 100644 --- a/src/proto_020_PsParisC/lib_delegate/state_transitions.ml +++ b/src/proto_020_PsParisC/lib_delegate/state_transitions.ml @@ -73,6 +73,12 @@ let is_acceptable_proposal_for_current_level state is a predecessor therefore the proposal is valid *) return Valid_proposal +(* This function retrieves the branch of the predecessor's predecessor (block + finalized) instead of the predecessor. This is done to avoid having consensus + operation branched on block that are not part of the canonical chain + anymore. *) +let get_branch_from_proposal proposal = proposal.predecessor.shell.predecessor + let make_consensus_vote_batch state proposal kind = let level = Raw_level.of_int32 state.level_state.current_level |> function @@ -89,7 +95,9 @@ let make_consensus_vote_batch state proposal kind = (Delegate_slots.own_delegates state.level_state.delegate_slots) in (* The branch is the latest finalized block. *) - let batch_branch = state.level_state.latest_proposal.predecessor.hash in + let batch_branch = + get_branch_from_proposal state.level_state.latest_proposal + in Baking_state.make_unsigned_consensus_vote_batch kind batch_content @@ -740,7 +748,9 @@ let inject_early_arrived_attestations state = | first_signed_attestation :: _ as unbatched_signed_attestations -> ( let new_round_state = {state.round_state with early_attestations = []} in let new_state = {state with round_state = new_round_state} in - let batch_branch = state.level_state.latest_proposal.predecessor.hash in + let batch_branch = + get_branch_from_proposal state.level_state.latest_proposal + in let batch_content = let vote_consensus_content = first_signed_attestation.unsigned_consensus_vote -- GitLab From e8f05960d7abace19d95099bd74958a87cf3f50b Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Thu, 13 Jun 2024 13:43:39 +0200 Subject: [PATCH 08/16] Devtools: Update for ParisC --- .../testnet_experiment_tools.ml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/devtools/testnet_experiment_tools/testnet_experiment_tools.ml b/devtools/testnet_experiment_tools/testnet_experiment_tools.ml index 975f5bcb5ef4..fe79d9939f6d 100644 --- a/devtools/testnet_experiment_tools/testnet_experiment_tools.ml +++ b/devtools/testnet_experiment_tools/testnet_experiment_tools.ml @@ -95,11 +95,16 @@ let protocol_alpha_parameters_template = let network_activation_parameters_templates protocol_hash = match protocol_hash with - | Tezt_tezos.Protocol.Paris -> + | Tezt_tezos.Protocol.ParisB -> Some (Filename.concat network_parameters_templates_dir - "proto_019_PtParisA_mainnet.json") + "proto_019_PtParisB_mainnet.json") + | Tezt_tezos.Protocol.ParisC -> + Some + (Filename.concat + network_parameters_templates_dir + "proto_020_PsParisC_mainnet.json") | Tezt_tezos.Protocol.Alpha -> (* Fetching the network parameters from the src/proto_alpha directory, to be sure that we are in synch with current protocl parameters. *) @@ -373,7 +378,7 @@ let () = ~__FILE__ ~title:"Generate Network Activation Parameters" ~tags:["generate_activation_parameters"] - (Local.generate_network_activation_parameters Protocol.Paris) ; + (Local.generate_network_activation_parameters Protocol.ParisC) ; register ~__FILE__ ~title:"Partition bakers by node" -- GitLab From 758984f8c4ab98c83899d0e22a5ffbfb611f0037 Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 22:36:01 +0200 Subject: [PATCH 09/16] Manifest: Bump 019 to 020 --- .gitlab/ci/jobs/packaging/opam_package.yml | 36 +++++++++---------- manifest/product_octez.ml | 22 ++++++------ opam/octez-protocol-020-PsParisC-libs.opam | 1 - .../lib_protocol/test/helpers/dune | 1 - .../lib_protocol/test/integration/dune | 8 +---- .../lib_protocol/test/unit/dune | 4 +-- 6 files changed, 31 insertions(+), 41 deletions(-) diff --git a/.gitlab/ci/jobs/packaging/opam_package.yml b/.gitlab/ci/jobs/packaging/opam_package.yml index b15356162116..3712014a6d0d 100644 --- a/.gitlab/ci/jobs/packaging/opam_package.yml +++ b/.gitlab/ci/jobs/packaging/opam_package.yml @@ -129,7 +129,7 @@ opam:octez-accuser-Proxford: when: always retry: 2 -opam:octez-accuser-PtParisB: +opam:octez-accuser-PsParisC: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -180,7 +180,7 @@ opam:octez-accuser-PtParisB: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-accuser-PtParisB + package: octez-accuser-PsParisC SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -193,7 +193,7 @@ opam:octez-accuser-PtParisB: when: always retry: 2 -opam:octez-accuser-PtParisC: +opam:octez-accuser-PtParisB: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -244,7 +244,7 @@ opam:octez-accuser-PtParisC: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-accuser-PtParisC + package: octez-accuser-PtParisB SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -385,7 +385,7 @@ opam:octez-baker-Proxford: when: always retry: 2 -opam:octez-baker-PtParisB: +opam:octez-baker-PsParisC: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -436,7 +436,7 @@ opam:octez-baker-PtParisB: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-baker-PtParisB + package: octez-baker-PsParisC SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -449,7 +449,7 @@ opam:octez-baker-PtParisB: when: always retry: 2 -opam:octez-baker-PtParisC: +opam:octez-baker-PtParisB: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -500,7 +500,7 @@ opam:octez-baker-PtParisC: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-baker-PtParisC + package: octez-baker-PtParisB SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -2753,7 +2753,7 @@ opam:octez-protocol-019-PtParisB-libs: when: always retry: 2 -opam:octez-protocol-020-PtParisC-libs: +opam:octez-protocol-020-PsParisC-libs: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -2804,7 +2804,7 @@ opam:octez-protocol-020-PtParisC-libs: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-protocol-020-PtParisC-libs + package: octez-protocol-020-PsParisC-libs SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -3329,7 +3329,7 @@ opam:octez-smart-rollup-node-Proxford: when: always retry: 2 -opam:octez-smart-rollup-node-PtNairob: +opam:octez-smart-rollup-node-PsParisC: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -3380,7 +3380,7 @@ opam:octez-smart-rollup-node-PtNairob: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-smart-rollup-node-PtNairob + package: octez-smart-rollup-node-PsParisC SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -3393,7 +3393,7 @@ opam:octez-smart-rollup-node-PtNairob: when: always retry: 2 -opam:octez-smart-rollup-node-PtParisB: +opam:octez-smart-rollup-node-PtNairob: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -3444,7 +3444,7 @@ opam:octez-smart-rollup-node-PtParisB: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-smart-rollup-node-PtParisB + package: octez-smart-rollup-node-PtNairob SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -3457,7 +3457,7 @@ opam:octez-smart-rollup-node-PtParisB: when: always retry: 2 -opam:octez-smart-rollup-node-PtParisC: +opam:octez-smart-rollup-node-PtParisB: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -3508,7 +3508,7 @@ opam:octez-smart-rollup-node-PtParisC: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: octez-smart-rollup-node-PtParisC + package: octez-smart-rollup-node-PtParisB SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log @@ -5889,7 +5889,7 @@ opam:tezos-protocol-019-PtParisB: when: always retry: 2 -opam:tezos-protocol-020-PtParisC: +opam:tezos-protocol-020-PsParisC: image: ${build_deps_image_name}:runtime-prebuild-dependencies--${build_deps_image_version} stage: packaging tags: @@ -5940,7 +5940,7 @@ opam:tezos-protocol-020-PtParisC: - OPAM_LOGS=opam_logs ./scripts/ci/opam_handle_output.sh variables: RUNTEZTALIAS: "true" - package: tezos-protocol-020-PtParisC + package: tezos-protocol-020-PsParisC SCCACHE_DIR: $CI_PROJECT_DIR/_build/_sccache RUSTC_WRAPPER: sccache SCCACHE_ERROR_LOG: $CI_PROJECT_DIR/opam_logs/sccache.log diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 77958999a256..b25ac87bee5f 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -5063,14 +5063,14 @@ end = struct ("test_frozen_bonds", true); ("test_adaptive_issuance_launch", N.(number >= 018)); ( "test_adaptive_issuance_roundtrip", - N.(number == 018 || number == 019) ); - ("test_scenario_base", N.(number >= 020)); - ("test_scenario_stake", N.(number >= 020)); - ("test_scenario_rewards", N.(number >= 020)); - ("test_scenario_autostaking", N.(number >= 020)); - ("test_scenario_slashing", N.(number >= 020)); - ("test_scenario_slashing_stakers", N.(number >= 020)); - ("test_scenario_deactivation", N.(number >= 020)); + N.(number == 018 || number == 019 || number == 020) ); + ("test_scenario_base", N.(number >= 021)); + ("test_scenario_stake", N.(number >= 021)); + ("test_scenario_rewards", N.(number >= 021)); + ("test_scenario_autostaking", N.(number >= 021)); + ("test_scenario_slashing", N.(number >= 021)); + ("test_scenario_slashing_stakers", N.(number >= 021)); + ("test_scenario_deactivation", N.(number >= 021)); ("test_liquidity_baking", true); ("test_storage_functions", true); ("test_storage", true); @@ -5192,8 +5192,8 @@ end = struct ("test_adaptive_issuance", N.(number >= 018)); ("test_adaptive_issuance_ema", N.(number >= 018)); ("test_percentage", N.(number >= 019)); - ("test_full_staking_balance_repr", N.(number >= 020)); - ("test_slashing_percentage", N.(number >= 020)); + ("test_full_staking_balance_repr", N.(number >= 021)); + ("test_slashing_percentage", N.(number >= 021)); ] |> conditional_list in @@ -5851,7 +5851,7 @@ let hash = Protocol.hash [ tezt_core_lib |> if_ N.(number >= 019) |> open_ |> open_ ~m:"Base"; alcotezt |> if_ N.(number == 019); - tezt_tezos |> if_ N.(number >= 020); + tezt_tezos |> if_ N.(number >= 021); tezt_lib |> if_ N.(number >= 019); octez_base_test_helpers |> if_ N.(number == 019) |> open_; qcheck_alcotest; diff --git a/opam/octez-protocol-020-PsParisC-libs.opam b/opam/octez-protocol-020-PsParisC-libs.opam index 7f9c29212e8e..4e3799cfe162 100644 --- a/opam/octez-protocol-020-PsParisC-libs.opam +++ b/opam/octez-protocol-020-PsParisC-libs.opam @@ -16,7 +16,6 @@ depends: [ "octez-shell-libs" { = version } "uri" { >= "3.1.0" } "tezt" { >= "4.0.0" & < "5.0.0" } - "tezt-tezos" { = version } "qcheck-alcotest" { >= "0.20" } "octez-proto-libs" { = version } "octez-version" { = version } diff --git a/src/proto_020_PsParisC/lib_protocol/test/helpers/dune b/src/proto_020_PsParisC/lib_protocol/test/helpers/dune index 999b4caafed5..2ba9382b9636 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/helpers/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/helpers/dune @@ -7,7 +7,6 @@ (instrumentation (backend bisect_ppx)) (libraries tezt.core - tezt-tezos tezt qcheck-alcotest octez-libs.test-helpers diff --git a/src/proto_020_PsParisC/lib_protocol/test/integration/dune b/src/proto_020_PsParisC/lib_protocol/test/integration/dune index e9a72d32f06a..476c22a252ae 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/integration/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/integration/dune @@ -31,13 +31,7 @@ test_constants test_frozen_bonds test_adaptive_issuance_launch - test_scenario_base - test_scenario_stake - test_scenario_rewards - test_scenario_autostaking - test_scenario_slashing - test_scenario_slashing_stakers - test_scenario_deactivation + test_adaptive_issuance_roundtrip test_liquidity_baking test_storage_functions test_storage diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/dune b/src/proto_020_PsParisC/lib_protocol/test/unit/dune index 87f0d50242ef..3b2d52050cb7 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/unit/dune +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/dune @@ -73,9 +73,7 @@ test_dal_slot_proof test_adaptive_issuance test_adaptive_issuance_ema - test_percentage - test_full_staking_balance_repr - test_slashing_percentage)) + test_percentage)) (executable (name main) -- GitLab From 4df115d80c716bedac6f49176a5a6b44ee49c2ec Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 23:41:49 +0200 Subject: [PATCH 10/16] Node: Add UAU for ParisC --- src/lib_node_config/config_file.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib_node_config/config_file.ml b/src/lib_node_config/config_file.ml index 32a9a015b8c6..2d9af34619c8 100644 --- a/src/lib_node_config/config_file.ml +++ b/src/lib_node_config/config_file.ml @@ -93,6 +93,7 @@ let mainnet_user_activated_upgrades = [ (28082l, "PsYLVpVvgbLhAhoqAkMFUo6gudkJ9weNXhUYCiLDzcUpFpkk8Wt"); (204761l, "PsddFKi32cMJ2qPjf43Qv5GDWLDPZb3T3bF6fLKiF5HtvHNU7aP"); + (5898241l, "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi"); ] (* END_PATCHING_ZONE_FOR_MAINNET_USER_ACTIVATED_UPGRADES *) @@ -173,6 +174,7 @@ let blockchain_network_ghostnet = (765952l, "PtJakart2xVj7pYXJBXrqHgd82rdkLey5ZeeGwDgPp9rhQUbSqY"); (1191936l, "PtKathmankSpLLDALzWw7CGD2j2MtyveTwboEYokqUCP4a1LxMg"); (1654784l, "PtLimaPtLMwfNinJi9rCfDPWea8dFgTZ1MeJ9f1m2SRic6ayiwW"); + (6729729l, "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi"); ] ~default_bootstrap_peers: [ -- GitLab From 6ae15480e9f6b36557a55ed81ab3cd0b33161fad Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Thu, 13 Jun 2024 15:12:28 +0200 Subject: [PATCH 11/16] Scoru_wasm: Add ParisC constant --- src/lib_scoru_wasm/constants.ml | 4 +++- src/lib_scoru_wasm/pvm_input_kind.ml | 13 +++++++++---- src/lib_scoru_wasm/pvm_input_kind.mli | 2 +- src/lib_scoru_wasm/test/test_protocol_migration.ml | 9 +++++++-- src/lib_scoru_wasm/wasm_vm.ml | 3 ++- .../lib_protocol/test/unit/test_sc_rollup_wasm.ml | 4 ++-- .../lib_protocol/test/unit/test_sc_rollup_wasm.ml | 4 ++-- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/lib_scoru_wasm/constants.ml b/src/lib_scoru_wasm/constants.ml index d2edf65dd840..5d191a4f3b07 100644 --- a/src/lib_scoru_wasm/constants.ml +++ b/src/lib_scoru_wasm/constants.ml @@ -73,6 +73,8 @@ let nairobi_name = "nairobi_017" let oxford_name = "oxford_018" -let paris_name = "paris_019" +let parisb_name = "paris_019" + +let parisc_name = "paris_020" let proto_alpha_name = "alpha_current" diff --git a/src/lib_scoru_wasm/pvm_input_kind.ml b/src/lib_scoru_wasm/pvm_input_kind.ml index d9ef5d81b58d..e87318236ee0 100644 --- a/src/lib_scoru_wasm/pvm_input_kind.ml +++ b/src/lib_scoru_wasm/pvm_input_kind.ml @@ -24,7 +24,7 @@ (*****************************************************************************) (* You can only add variants to this type. You cannot remove them. *) -type protocol = Nairobi | Oxford | Paris | Proto_alpha +type protocol = Nairobi | Oxford | ParisB | ParisC | Proto_alpha (* This type mimics [Sc_rollup_inbox_repr.internal_inbox_messages], without fully deserializing the `Transfer`, and is produced by reading the first bytes @@ -61,8 +61,10 @@ let protocol_from_raw payload = Some (Protocol_migration Nairobi) | payload when String.equal payload Constants.oxford_name -> Some (Protocol_migration Oxford) - | payload when String.equal payload Constants.paris_name -> - Some (Protocol_migration Paris) + | payload when String.equal payload Constants.parisb_name -> + Some (Protocol_migration ParisB) + | payload when String.equal payload Constants.parisc_name -> + Some (Protocol_migration ParisC) | payload when String.equal payload Constants.proto_alpha_name -> Some (Protocol_migration Proto_alpha) | _ -> None @@ -96,7 +98,10 @@ module Internal_for_tests = struct Data_encoding.(Binary.to_string_exn string Constants.nairobi_name) | Oxford -> Data_encoding.(Binary.to_string_exn string Constants.oxford_name) - | Paris -> Data_encoding.(Binary.to_string_exn string Constants.paris_name) + | ParisB -> + Data_encoding.(Binary.to_string_exn string Constants.parisb_name) + | ParisC -> + Data_encoding.(Binary.to_string_exn string Constants.parisc_name) | Proto_alpha -> Data_encoding.(Binary.to_string_exn string Constants.proto_alpha_name) diff --git a/src/lib_scoru_wasm/pvm_input_kind.mli b/src/lib_scoru_wasm/pvm_input_kind.mli index fcb4ce0aede7..cce961bb93df 100644 --- a/src/lib_scoru_wasm/pvm_input_kind.mli +++ b/src/lib_scoru_wasm/pvm_input_kind.mli @@ -23,7 +23,7 @@ (* *) (*****************************************************************************) -type protocol = Nairobi | Oxford | Paris | Proto_alpha +type protocol = Nairobi | Oxford | ParisB | ParisC | Proto_alpha (** [internal_message_kind] represent an internal message in a inbox. *) type internal_message_kind = diff --git a/src/lib_scoru_wasm/test/test_protocol_migration.ml b/src/lib_scoru_wasm/test/test_protocol_migration.ml index 7e75f04c7626..ec012738830c 100644 --- a/src/lib_scoru_wasm/test/test_protocol_migration.ml +++ b/src/lib_scoru_wasm/test/test_protocol_migration.ml @@ -62,7 +62,8 @@ let test_protocol_migration_message ~from_version ~to_version let proto_name : Tezos_scoru_wasm.Pvm_input_kind.protocol -> string = function | Nairobi -> "Nairobi" | Oxford -> "Oxford" - | Paris -> "Paris" + | ParisB -> "ParisB" + | ParisC -> "ParisC" | Proto_alpha -> "Proto_alpha" let tests = @@ -84,7 +85,11 @@ let tests = ~to_version ~after_protocol_activation:protocol)) [ - (V2, V4, Proto_alpha); (V2, V4, Paris); (V1, V2, Oxford); (V0, V1, Nairobi); + (V2, V4, Proto_alpha); + (V2, V4, ParisB); + (V2, V4, ParisC); + (V1, V2, Oxford); + (V0, V1, Nairobi); ] let () = diff --git a/src/lib_scoru_wasm/wasm_vm.ml b/src/lib_scoru_wasm/wasm_vm.ml index b243252317b7..7f4ad7ca983a 100644 --- a/src/lib_scoru_wasm/wasm_vm.ml +++ b/src/lib_scoru_wasm/wasm_vm.ml @@ -30,7 +30,8 @@ let version_for_protocol : Pvm_input_kind.protocol -> Wasm_pvm_state.version = function | Nairobi -> V1 | Oxford -> V2 - | Paris -> V4 + | ParisB -> V4 + | ParisC -> V4 | Proto_alpha -> V4 let link_finished (ast : Wasm.Ast.module_) offset = diff --git a/src/proto_019_PtParisB/lib_protocol/test/unit/test_sc_rollup_wasm.ml b/src/proto_019_PtParisB/lib_protocol/test/unit/test_sc_rollup_wasm.ml index a49e2bf32023..863cf7bcc3a4 100644 --- a/src/proto_019_PtParisB/lib_protocol/test/unit/test_sc_rollup_wasm.ml +++ b/src/proto_019_PtParisB/lib_protocol/test/unit/test_sc_rollup_wasm.ml @@ -338,10 +338,10 @@ let test_protocol_names () = Tezos_scoru_wasm.Pvm_input_kind.from_raw_input protocol_migration_message_str in - assert (kind = Internal (Protocol_migration Paris)) ; + assert (kind = Internal (Protocol_migration ParisB)) ; assert ( protocol_migration_internal_message - = Protocol_migration Tezos_scoru_wasm.Constants.paris_name) ; + = Protocol_migration Tezos_scoru_wasm.Constants.parisb_name) ; Lwt_result_syntax.return_unit let test_reveal_host_function_can_request_dal_pages () = diff --git a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml index be1d6dd2bbb5..a97edc22e2a8 100644 --- a/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml +++ b/src/proto_020_PsParisC/lib_protocol/test/unit/test_sc_rollup_wasm.ml @@ -338,10 +338,10 @@ let test_protocol_names () = Tezos_scoru_wasm.Pvm_input_kind.from_raw_input protocol_migration_message_str in - assert (kind = Internal (Protocol_migration Paris)) ; + assert (kind = Internal (Protocol_migration ParisC)) ; assert ( protocol_migration_internal_message - = Protocol_migration Tezos_scoru_wasm.Constants.paris_name) ; + = Protocol_migration Tezos_scoru_wasm.Constants.parisc_name) ; Lwt_result_syntax.return_unit let test_reveal_host_function_can_request_dal_pages () = -- GitLab From ed1b4016aea34416a3e319fbad91508c05780286 Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Thu, 13 Jun 2024 16:41:21 +0200 Subject: [PATCH 12/16] Clients-libs: Update katai-struct-files --- .../files/id_020__psparisc__block_header.ksy | 57 + ..._020__psparisc__block_header__contents.ksy | 43 + ..._psparisc__block_header__protocol_data.ksy | 49 + .../id_020__psparisc__block_header__raw.ksy | 9 + ...__psparisc__block_header__shell_header.ksy | 9 + ..._020__psparisc__block_header__unsigned.ksy | 47 + .../files/id_020__psparisc__constants.ksy | 366 +++ .../id_020__psparisc__constants__fixed.ksy | 53 + ...d_020__psparisc__constants__parametric.ksy | 338 +++ .../files/id_020__psparisc__contract.ksy | 56 + .../files/id_020__psparisc__cycle.ksy | 7 + .../files/id_020__psparisc__errors.ksy | 21 + ..._020__psparisc__fa1__2__token_transfer.ksy | 73 + .../files/id_020__psparisc__fitness.ksy | 26 + .../files/id_020__psparisc__frozen_staker.ksy | 91 + .../files/id_020__psparisc__gas.ksy | 35 + .../files/id_020__psparisc__gas__cost.ksy | 27 + .../id_020__psparisc__lazy_storage_diff.ksy | 768 +++++++ .../files/id_020__psparisc__level.ksy | 33 + .../files/id_020__psparisc__nonce.ksy | 7 + .../files/id_020__psparisc__operation.ksy | 2037 +++++++++++++++++ .../id_020__psparisc__operation__contents.ksy | 1974 ++++++++++++++++ ...20__psparisc__operation__contents_list.ksy | 1979 ++++++++++++++++ .../id_020__psparisc__operation__internal.ksy | 800 +++++++ ...20__psparisc__operation__protocol_data.ksy | 2035 ++++++++++++++++ .../id_020__psparisc__operation__raw.ksy | 9 + .../id_020__psparisc__operation__unsigned.ksy | 1985 ++++++++++++++++ ...operation_with_legacy_attestation_name.ksy | 2037 +++++++++++++++++ ...with_legacy_attestation_name__unsigned.ksy | 2019 ++++++++++++++++ .../files/id_020__psparisc__parameters.ksy | 616 +++++ .../files/id_020__psparisc__period.ksy | 7 + .../files/id_020__psparisc__raw_level.ksy | 7 + ...20__psparisc__receipt__balance_updates.ksy | 355 +++ .../files/id_020__psparisc__script.ksy | 22 + .../files/id_020__psparisc__script__expr.ksy | 584 +++++ .../id_020__psparisc__script__lazy_expr.ksy | 16 + .../files/id_020__psparisc__script__loc.ksy | 23 + .../files/id_020__psparisc__script__prim.ksy | 411 ++++ .../files/id_020__psparisc__seed.ksy | 7 + ...d_020__psparisc__smart_rollup__address.ksy | 7 + ...0__psparisc__smart_rollup__commmitment.ksy | 13 + .../id_020__psparisc__smart_rollup__game.ksy | 218 ++ .../id_020__psparisc__smart_rollup__inbox.ksy | 54 + ...psparisc__smart_rollup__inbox__message.ksy | 655 ++++++ .../id_020__psparisc__smart_rollup__kind.ksy | 13 + ..._020__psparisc__smart_rollup__metadata.ksy | 9 + ...sparisc__smart_rollup__outbox__message.ksy | 719 ++++++ ...id_020__psparisc__smart_rollup__output.ksy | 733 ++++++ .../id_020__psparisc__smart_rollup__proof.ksy | 104 + ...id_020__psparisc__smart_rollup__reveal.ksy | 39 + ...mart_rollup__wasm_2_0_0__output__proof.ksy | 1183 ++++++++++ ...020__psparisc__smart_rollup__whitelist.ksy | 46 + .../files/id_020__psparisc__tez.ksy | 24 + .../files/id_020__psparisc__timestamp.ksy | 9 + ..._020__psparisc__unstaked_frozen_staker.ksy | 82 + .../files/id_020__psparisc__vote__ballot.ksy | 7 + .../files/id_020__psparisc__vote__ballots.ksy | 11 + .../id_020__psparisc__vote__listings.ksy | 48 + .../files/id_020__psparisc__voting_period.ksy | 26 + .../id_020__psparisc__voting_period__kind.ksy | 15 + 60 files changed, 23053 insertions(+) create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__block_header.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__contents.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__protocol_data.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__raw.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__shell_header.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__unsigned.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__constants.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__constants__fixed.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__constants__parametric.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__contract.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__cycle.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__errors.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__fa1__2__token_transfer.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__fitness.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__frozen_staker.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__gas.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__gas__cost.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__lazy_storage_diff.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__level.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__nonce.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents_list.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation__internal.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation__protocol_data.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation__raw.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation__unsigned.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name__unsigned.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__parameters.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__period.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__raw_level.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__receipt__balance_updates.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__script.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__script__expr.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__script__lazy_expr.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__script__loc.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__script__prim.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__seed.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__address.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__commmitment.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__game.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox__message.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__kind.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__metadata.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__outbox__message.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__output.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__proof.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__reveal.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__wasm_2_0_0__output__proof.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__whitelist.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__tez.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__timestamp.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__unstaked_frozen_staker.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballot.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballots.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__vote__listings.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period.ksy create mode 100644 client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period__kind.ksy diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header.ksy new file mode 100644 index 000000000000..60067300fb5c --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header.ksy @@ -0,0 +1,57 @@ +meta: + id: id_020__psparisc__block_header + endian: be + imports: + - block_header__shell +doc: ! 'Encoding id: 020-PsParisC.block_header' +types: + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag +enums: + bool: + 0: false + 255: true + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 +seq: +- id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__contents.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__contents.ksy new file mode 100644 index 000000000000..993f2b061421 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__contents.ksy @@ -0,0 +1,43 @@ +meta: + id: id_020__psparisc__block_header__contents + endian: be +doc: ! 'Encoding id: 020-PsParisC.block_header.contents' +types: + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag +enums: + bool: + 0: false + 255: true + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 +seq: +- id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__protocol_data.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__protocol_data.ksy new file mode 100644 index 000000000000..678c0aee09c5 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__protocol_data.ksy @@ -0,0 +1,49 @@ +meta: + id: id_020__psparisc__block_header__protocol_data + endian: be +doc: ! 'Encoding id: 020-PsParisC.block_header.protocol_data' +types: + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag +enums: + bool: + 0: false + 255: true + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 +seq: +- id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__raw.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__raw.ksy new file mode 100644 index 000000000000..77669a08549f --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__raw.ksy @@ -0,0 +1,9 @@ +meta: + id: id_020__psparisc__block_header__raw + endian: be + imports: + - block_header +doc: ! 'Encoding id: 020-PsParisC.block_header.raw' +seq: +- id: id_020__psparisc__block_header__raw + type: block_header diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__shell_header.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__shell_header.ksy new file mode 100644 index 000000000000..874c1812f9f2 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__shell_header.ksy @@ -0,0 +1,9 @@ +meta: + id: id_020__psparisc__block_header__shell_header + endian: be + imports: + - block_header__shell +doc: ! 'Encoding id: 020-PsParisC.block_header.shell_header' +seq: +- id: id_020__psparisc__block_header__shell_header + type: block_header__shell diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__unsigned.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__unsigned.ksy new file mode 100644 index 000000000000..5a108bd0ec11 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__block_header__unsigned.ksy @@ -0,0 +1,47 @@ +meta: + id: id_020__psparisc__block_header__unsigned + endian: be + imports: + - block_header__shell +doc: ! 'Encoding id: 020-PsParisC.block_header.unsigned' +types: + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag +enums: + bool: + 0: false + 255: true + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 +seq: +- id: id_020__psparisc__block_header__unsigned + type: block_header__shell +- id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__constants.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__constants.ksy new file mode 100644 index 000000000000..2f8e59ce8767 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__constants.ksy @@ -0,0 +1,366 @@ +meta: + id: id_020__psparisc__constants + endian: be +doc: ! 'Encoding id: 020-PsParisC.constants' +types: + adaptive_rewards_params: + seq: + - id: issuance_ratio_final_min + type: issuance_ratio_final_min + - id: issuance_ratio_final_max + type: issuance_ratio_final_max + - id: issuance_ratio_initial_min + type: issuance_ratio_initial_min + - id: issuance_ratio_initial_max + type: issuance_ratio_initial_max + - id: initial_period + type: u1 + - id: transition_period + type: u1 + - id: max_bonus + type: s8be + - id: growth_rate + type: growth_rate + - id: center_dz + type: center_dz + - id: radius_dz + type: radius_dz + center_dz: + seq: + - id: numerator + type: z + - id: denominator + type: z + dal_parametric: + seq: + - id: feature_enable + type: u1 + enum: bool + - id: incentives_enable + type: u1 + enum: bool + - id: number_of_slots + type: u2be + - id: attestation_lag + type: u1 + - id: attestation_threshold + type: u1 + - id: redundancy_factor + type: u1 + - id: page_size + type: u2be + - id: slot_size + type: int31 + - id: number_of_shards + type: u2be + growth_rate: + seq: + - id: numerator + type: z + - id: denominator + type: z + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + issuance_ratio_final_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_final_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_weights: + seq: + - id: base_total_issued_per_minute + type: id_020__psparisc__mutez + - id: baking_reward_fixed_portion_weight + type: int31 + - id: baking_reward_bonus_weight + type: int31 + - id: attesting_reward_weight + type: int31 + - id: seed_nonce_revelation_tip_weight + type: int31 + - id: vdf_revelation_tip_weight + type: int31 + minimal_participation_ratio: + seq: + - id: numerator + type: u2be + - id: denominator + type: u2be + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + radius_dz: + seq: + - id: numerator + type: z + - id: denominator + type: z + smart_rollup_reveal_activation_level: + seq: + - id: raw_data + type: s4be + - id: metadata + type: s4be + - id: dal_page + type: s4be + - id: dal_parameters + type: s4be + - id: dal_attested_slots_validity_lag + type: int31 + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: proof_of_work_nonce_size + type: u1 +- id: nonce_length + type: u1 +- id: max_anon_ops_per_block + type: u1 +- id: max_operation_data_length + type: int31 +- id: max_proposals_per_delegate + type: u1 +- id: max_micheline_node_count + type: int31 +- id: max_micheline_bytes_limit + type: int31 +- id: max_allowed_global_constants_depth + type: int31 +- id: cache_layout_size + type: u1 +- id: michelson_maximum_type_size + type: u2be +- id: max_slashing_period + type: u1 +- id: smart_rollup_max_wrapped_proof_binary_size + type: int31 +- id: smart_rollup_message_size_limit + type: int31 +- id: smart_rollup_max_number_of_messages_per_level + type: n +- id: consensus_rights_delay + type: u1 +- id: blocks_preservation_cycles + type: u1 +- id: delegate_parameters_activation_delay + type: u1 +- id: blocks_per_cycle + type: s4be +- id: blocks_per_commitment + type: s4be +- id: nonce_revelation_threshold + type: s4be +- id: cycles_per_voting_period + type: s4be +- id: hard_gas_limit_per_operation + type: z +- id: hard_gas_limit_per_block + type: z +- id: proof_of_work_threshold + type: s8be +- id: minimal_stake + type: id_020__psparisc__mutez +- id: minimal_frozen_stake + type: id_020__psparisc__mutez +- id: vdf_difficulty + type: s8be +- id: origination_size + type: int31 +- id: issuance_weights + type: issuance_weights +- id: cost_per_byte + type: id_020__psparisc__mutez +- id: hard_storage_limit_per_operation + type: z +- id: quorum_min + type: s4be +- id: quorum_max + type: s4be +- id: min_proposal_quorum + type: s4be +- id: liquidity_baking_subsidy + type: id_020__psparisc__mutez +- id: liquidity_baking_toggle_ema_threshold + type: s4be +- id: max_operations_time_to_live + type: s2be +- id: minimal_block_delay + type: s8be +- id: delay_increment_per_round + type: s8be +- id: consensus_committee_size + type: int31 +- id: consensus_threshold + type: int31 +- id: minimal_participation_ratio + type: minimal_participation_ratio +- id: limit_of_delegation_over_baking + type: u1 +- id: percentage_of_frozen_deposits_slashed_per_double_baking + type: u2be +- id: percentage_of_frozen_deposits_slashed_per_double_attestation + type: u2be +- id: max_slashing_per_block + type: u2be +- id: max_slashing_threshold + type: int31 +- id: testnet_dictator_tag + type: u1 + enum: bool +- id: testnet_dictator + type: public_key_hash + if: (testnet_dictator_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash +- id: initial_seed_tag + type: u1 + enum: bool +- id: initial_seed + size: 32 + if: (initial_seed_tag == bool::true) +- id: cache_script_size + type: int31 +- id: cache_stake_distribution_cycles + type: s1 +- id: cache_sampler_state_cycles + type: s1 +- id: dal_parametric + type: dal_parametric +- id: smart_rollup_arith_pvm_enable + type: u1 + enum: bool +- id: smart_rollup_origination_size + type: int31 +- id: smart_rollup_challenge_window_in_blocks + type: int31 +- id: smart_rollup_stake_amount + type: id_020__psparisc__mutez +- id: smart_rollup_commitment_period_in_blocks + type: int31 +- id: smart_rollup_max_lookahead_in_blocks + type: s4be +- id: smart_rollup_max_active_outbox_levels + type: s4be +- id: smart_rollup_max_outbox_messages_per_level + type: int31 +- id: smart_rollup_number_of_sections_in_dissection + type: u1 +- id: smart_rollup_timeout_period_in_blocks + type: int31 +- id: smart_rollup_max_number_of_cemented_commitments + type: int31 +- id: smart_rollup_max_number_of_parallel_games + type: int31 +- id: smart_rollup_reveal_activation_level + type: smart_rollup_reveal_activation_level +- id: smart_rollup_private_enable + type: u1 + enum: bool +- id: smart_rollup_riscv_pvm_enable + type: u1 + enum: bool +- id: zk_rollup_enable + type: u1 + enum: bool +- id: zk_rollup_origination_size + type: int31 +- id: zk_rollup_min_pending_to_process + type: int31 +- id: zk_rollup_max_ticket_payload_size + type: int31 +- id: global_limit_of_staking_over_baking + type: u1 +- id: edge_of_staking_over_delegation + type: u1 +- id: adaptive_issuance_launch_ema_threshold + type: s4be +- id: adaptive_rewards_params + type: adaptive_rewards_params +- id: adaptive_issuance_activation_vote_enable + type: u1 + enum: bool +- id: autostaking_enable + type: u1 + enum: bool +- id: adaptive_issuance_force_activation + type: u1 + enum: bool +- id: ns_enable + type: u1 + enum: bool +- id: direct_ticket_spending_enable + type: u1 + enum: bool diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__constants__fixed.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__constants__fixed.ksy new file mode 100644 index 000000000000..74a2aa657546 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__constants__fixed.ksy @@ -0,0 +1,53 @@ +meta: + id: id_020__psparisc__constants__fixed + endian: be +doc: ! 'Encoding id: 020-PsParisC.constants.fixed' +types: + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be +seq: +- id: proof_of_work_nonce_size + type: u1 +- id: nonce_length + type: u1 +- id: max_anon_ops_per_block + type: u1 +- id: max_operation_data_length + type: int31 +- id: max_proposals_per_delegate + type: u1 +- id: max_micheline_node_count + type: int31 +- id: max_micheline_bytes_limit + type: int31 +- id: max_allowed_global_constants_depth + type: int31 +- id: cache_layout_size + type: u1 +- id: michelson_maximum_type_size + type: u2be +- id: max_slashing_period + type: u1 +- id: smart_rollup_max_wrapped_proof_binary_size + type: int31 +- id: smart_rollup_message_size_limit + type: int31 +- id: smart_rollup_max_number_of_messages_per_level + type: n diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__constants__parametric.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__constants__parametric.ksy new file mode 100644 index 000000000000..4a36bfbe91eb --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__constants__parametric.ksy @@ -0,0 +1,338 @@ +meta: + id: id_020__psparisc__constants__parametric + endian: be +doc: ! 'Encoding id: 020-PsParisC.constants.parametric' +types: + adaptive_rewards_params: + seq: + - id: issuance_ratio_final_min + type: issuance_ratio_final_min + - id: issuance_ratio_final_max + type: issuance_ratio_final_max + - id: issuance_ratio_initial_min + type: issuance_ratio_initial_min + - id: issuance_ratio_initial_max + type: issuance_ratio_initial_max + - id: initial_period + type: u1 + - id: transition_period + type: u1 + - id: max_bonus + type: s8be + - id: growth_rate + type: growth_rate + - id: center_dz + type: center_dz + - id: radius_dz + type: radius_dz + center_dz: + seq: + - id: numerator + type: z + - id: denominator + type: z + dal_parametric: + seq: + - id: feature_enable + type: u1 + enum: bool + - id: incentives_enable + type: u1 + enum: bool + - id: number_of_slots + type: u2be + - id: attestation_lag + type: u1 + - id: attestation_threshold + type: u1 + - id: redundancy_factor + type: u1 + - id: page_size + type: u2be + - id: slot_size + type: int31 + - id: number_of_shards + type: u2be + growth_rate: + seq: + - id: numerator + type: z + - id: denominator + type: z + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + issuance_ratio_final_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_final_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_weights: + seq: + - id: base_total_issued_per_minute + type: id_020__psparisc__mutez + - id: baking_reward_fixed_portion_weight + type: int31 + - id: baking_reward_bonus_weight + type: int31 + - id: attesting_reward_weight + type: int31 + - id: seed_nonce_revelation_tip_weight + type: int31 + - id: vdf_revelation_tip_weight + type: int31 + minimal_participation_ratio: + seq: + - id: numerator + type: u2be + - id: denominator + type: u2be + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + radius_dz: + seq: + - id: numerator + type: z + - id: denominator + type: z + smart_rollup_reveal_activation_level: + seq: + - id: raw_data + type: s4be + - id: metadata + type: s4be + - id: dal_page + type: s4be + - id: dal_parameters + type: s4be + - id: dal_attested_slots_validity_lag + type: int31 + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: consensus_rights_delay + type: u1 +- id: blocks_preservation_cycles + type: u1 +- id: delegate_parameters_activation_delay + type: u1 +- id: blocks_per_cycle + type: s4be +- id: blocks_per_commitment + type: s4be +- id: nonce_revelation_threshold + type: s4be +- id: cycles_per_voting_period + type: s4be +- id: hard_gas_limit_per_operation + type: z +- id: hard_gas_limit_per_block + type: z +- id: proof_of_work_threshold + type: s8be +- id: minimal_stake + type: id_020__psparisc__mutez +- id: minimal_frozen_stake + type: id_020__psparisc__mutez +- id: vdf_difficulty + type: s8be +- id: origination_size + type: int31 +- id: issuance_weights + type: issuance_weights +- id: cost_per_byte + type: id_020__psparisc__mutez +- id: hard_storage_limit_per_operation + type: z +- id: quorum_min + type: s4be +- id: quorum_max + type: s4be +- id: min_proposal_quorum + type: s4be +- id: liquidity_baking_subsidy + type: id_020__psparisc__mutez +- id: liquidity_baking_toggle_ema_threshold + type: s4be +- id: max_operations_time_to_live + type: s2be +- id: minimal_block_delay + type: s8be +- id: delay_increment_per_round + type: s8be +- id: consensus_committee_size + type: int31 +- id: consensus_threshold + type: int31 +- id: minimal_participation_ratio + type: minimal_participation_ratio +- id: limit_of_delegation_over_baking + type: u1 +- id: percentage_of_frozen_deposits_slashed_per_double_baking + type: u2be +- id: percentage_of_frozen_deposits_slashed_per_double_attestation + type: u2be +- id: max_slashing_per_block + type: u2be +- id: max_slashing_threshold + type: int31 +- id: testnet_dictator_tag + type: u1 + enum: bool +- id: testnet_dictator + type: public_key_hash + if: (testnet_dictator_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash +- id: initial_seed_tag + type: u1 + enum: bool +- id: initial_seed + size: 32 + if: (initial_seed_tag == bool::true) +- id: cache_script_size + type: int31 +- id: cache_stake_distribution_cycles + type: s1 +- id: cache_sampler_state_cycles + type: s1 +- id: dal_parametric + type: dal_parametric +- id: smart_rollup_arith_pvm_enable + type: u1 + enum: bool +- id: smart_rollup_origination_size + type: int31 +- id: smart_rollup_challenge_window_in_blocks + type: int31 +- id: smart_rollup_stake_amount + type: id_020__psparisc__mutez +- id: smart_rollup_commitment_period_in_blocks + type: int31 +- id: smart_rollup_max_lookahead_in_blocks + type: s4be +- id: smart_rollup_max_active_outbox_levels + type: s4be +- id: smart_rollup_max_outbox_messages_per_level + type: int31 +- id: smart_rollup_number_of_sections_in_dissection + type: u1 +- id: smart_rollup_timeout_period_in_blocks + type: int31 +- id: smart_rollup_max_number_of_cemented_commitments + type: int31 +- id: smart_rollup_max_number_of_parallel_games + type: int31 +- id: smart_rollup_reveal_activation_level + type: smart_rollup_reveal_activation_level +- id: smart_rollup_private_enable + type: u1 + enum: bool +- id: smart_rollup_riscv_pvm_enable + type: u1 + enum: bool +- id: zk_rollup_enable + type: u1 + enum: bool +- id: zk_rollup_origination_size + type: int31 +- id: zk_rollup_min_pending_to_process + type: int31 +- id: zk_rollup_max_ticket_payload_size + type: int31 +- id: global_limit_of_staking_over_baking + type: u1 +- id: edge_of_staking_over_delegation + type: u1 +- id: adaptive_issuance_launch_ema_threshold + type: s4be +- id: adaptive_rewards_params + type: adaptive_rewards_params +- id: adaptive_issuance_activation_vote_enable + type: u1 + enum: bool +- id: autostaking_enable + type: u1 + enum: bool +- id: adaptive_issuance_force_activation + type: u1 + enum: bool +- id: ns_enable + type: u1 + enum: bool +- id: direct_ticket_spending_enable + type: u1 + enum: bool diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__contract.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__contract.ksy new file mode 100644 index 000000000000..b5995991c371 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__contract.ksy @@ -0,0 +1,56 @@ +meta: + id: id_020__psparisc__contract + endian: be +doc: ! 'Encoding id: 020-PsParisC.contract' +types: + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) +enums: + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__contract_id + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. Can + be a base58 implicit contract hash or a base58 originated contract hash. diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__cycle.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__cycle.ksy new file mode 100644 index 000000000000..9082e0a5a9b9 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__cycle.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__cycle + endian: be +doc: ! 'Encoding id: 020-PsParisC.cycle' +seq: +- id: id_020__psparisc__cycle + type: s4be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__errors.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__errors.ksy new file mode 100644 index 000000000000..027701c3b9b7 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__errors.ksy @@ -0,0 +1,21 @@ +meta: + id: id_020__psparisc__errors + endian: be +doc: ! >- + Encoding id: 020-PsParisC.errors + + Description: The full list of RPC errors would be too long to include.It is + + available through the RPC `/errors` (GET). +types: + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 +seq: +- id: id_020__psparisc__errors + type: bytes_dyn_uint30 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__fa1__2__token_transfer.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__fa1__2__token_transfer.ksy new file mode 100644 index 000000000000..6b265e847727 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__fa1__2__token_transfer.ksy @@ -0,0 +1,73 @@ +meta: + id: id_020__psparisc__fa1__2__token_transfer + endian: be +doc: ! 'Encoding id: 020-PsParisC.fa1.2.token_transfer' +types: + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true +seq: +- id: token_contract + type: bytes_dyn_uint30 +- id: destination + type: bytes_dyn_uint30 +- id: amount + type: z +- id: tez__amount_tag + type: u1 + enum: bool +- id: tez__amount + type: bytes_dyn_uint30 + if: (tez__amount_tag == bool::true) +- id: fee_tag + type: u1 + enum: bool +- id: fee + type: bytes_dyn_uint30 + if: (fee_tag == bool::true) +- id: gas__limit_tag + type: u1 + enum: bool +- id: gas__limit + type: n + if: (gas__limit_tag == bool::true) +- id: storage__limit_tag + type: u1 + enum: bool +- id: storage__limit + type: z + if: (storage__limit_tag == bool::true) diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__fitness.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__fitness.ksy new file mode 100644 index 000000000000..4f0d587a0ba5 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__fitness.ksy @@ -0,0 +1,26 @@ +meta: + id: id_020__psparisc__fitness + endian: be +doc: ! 'Encoding id: 020-PsParisC.fitness' +types: + locked_round: + seq: + - id: locked_round_tag + type: u1 + enum: locked_round_tag + - id: some + type: s4be + if: (locked_round_tag == locked_round_tag::some) +enums: + locked_round_tag: + 0: none + 1: some +seq: +- id: level + type: s4be +- id: locked_round + type: locked_round +- id: predecessor_round + type: s4be +- id: round + type: s4be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__frozen_staker.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__frozen_staker.ksy new file mode 100644 index 000000000000..763ce20fdf31 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__frozen_staker.ksy @@ -0,0 +1,91 @@ +meta: + id: id_020__psparisc__frozen_staker + endian: be +doc: ! 'Encoding id: 020-PsParisC.frozen_staker' +types: + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__frozen_staker: + seq: + - id: id_020__psparisc__frozen_staker_tag + type: u1 + enum: id_020__psparisc__frozen_staker_tag + - id: single + type: single + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::single) + - id: shared + type: public_key_hash + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::shared) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: baker + type: public_key_hash + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::baker) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: baker_edge + type: public_key_hash + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::baker_edge) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + single: + seq: + - id: contract + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash +enums: + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__frozen_staker_tag: + 0: single + 1: shared + 2: baker + 3: baker_edge + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__frozen_staker + type: id_020__psparisc__frozen_staker + doc: ! >- + frozen_staker: Abstract notion of staker used in operation receipts for frozen + deposits, either a single staker or all the stakers delegating to some delegate. diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__gas.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__gas.ksy new file mode 100644 index 000000000000..a54405511bfc --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__gas.ksy @@ -0,0 +1,35 @@ +meta: + id: id_020__psparisc__gas + endian: be +doc: ! 'Encoding id: 020-PsParisC.gas' +types: + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + id_020__psparisc__gas_tag: + 0: limited + 1: unaccounted +seq: +- id: id_020__psparisc__gas_tag + type: u1 + enum: id_020__psparisc__gas_tag +- id: limited + type: z + if: (id_020__psparisc__gas_tag == id_020__psparisc__gas_tag::limited) diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__gas__cost.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__gas__cost.ksy new file mode 100644 index 000000000000..7cfd7781312e --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__gas__cost.ksy @@ -0,0 +1,27 @@ +meta: + id: id_020__psparisc__gas__cost + endian: be +doc: ! 'Encoding id: 020-PsParisC.gas.cost' +types: + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +seq: +- id: id_020__psparisc__gas__cost + type: z diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__lazy_storage_diff.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__lazy_storage_diff.ksy new file mode 100644 index 000000000000..e857e935eb18 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__lazy_storage_diff.ksy @@ -0,0 +1,768 @@ +meta: + id: id_020__psparisc__lazy_storage_diff + endian: be + imports: + - sapling__transaction__ciphertext + - sapling__transaction__commitment + - sapling__transaction__nullifier +doc: ! 'Encoding id: 020-PsParisC.lazy_storage_diff' +types: + alloc: + seq: + - id: updates + type: updates_0 + - id: key_type + type: micheline__020__psparisc__michelson_v1__expression + - id: value_type + type: micheline__020__psparisc__michelson_v1__expression + alloc_0: + seq: + - id: updates + type: updates_1 + - id: memo_size + type: u2be + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + big_map: + seq: + - id: id + type: id_020__psparisc__big_map_id + doc: ! 'Big map identifier: A big map identifier' + - id: diff + type: diff + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + commitments_and_ciphertexts: + seq: + - id: commitments_and_ciphertexts_entries + type: commitments_and_ciphertexts_entries + repeat: eos + commitments_and_ciphertexts_0: + seq: + - id: len_commitments_and_ciphertexts + type: u4be + valid: + max: 1073741823 + - id: commitments_and_ciphertexts + type: commitments_and_ciphertexts + size: len_commitments_and_ciphertexts + commitments_and_ciphertexts_entries: + seq: + - id: commitments_and_ciphertexts_elt_field0 + type: sapling__transaction__commitment + - id: commitments_and_ciphertexts_elt_field1 + type: sapling__transaction__ciphertext + copy: + seq: + - id: source + type: id_020__psparisc__big_map_id + doc: ! 'Big map identifier: A big map identifier' + - id: updates + type: updates_0 + copy_0: + seq: + - id: source + type: id_020__psparisc__sapling_state_id + doc: ! 'Sapling state identifier: A sapling state identifier' + - id: updates + type: updates_1 + diff: + seq: + - id: diff_tag + type: u1 + enum: diff_tag + - id: update + type: updates_0 + if: (diff_tag == diff_tag::update) + - id: copy + type: copy + if: (diff_tag == diff_tag::copy) + - id: alloc + type: alloc + if: (diff_tag == diff_tag::alloc) + diff_0: + seq: + - id: diff_tag + type: u1 + enum: diff_tag + - id: update + type: updates_1 + if: (diff_tag == diff_tag::update) + - id: copy + type: copy_0 + if: (diff_tag == diff_tag::copy) + - id: alloc + type: alloc_0 + if: (diff_tag == diff_tag::alloc) + id_020__psparisc__big_map_id: + seq: + - id: id_020__psparisc__big_map_id + type: z + id_020__psparisc__lazy_storage_diff: + seq: + - id: id_020__psparisc__lazy_storage_diff_entries + type: id_020__psparisc__lazy_storage_diff_entries + repeat: eos + id_020__psparisc__lazy_storage_diff_entries: + seq: + - id: id_020__psparisc__lazy_storage_diff_elt_tag + type: u1 + enum: id_020__psparisc__lazy_storage_diff_elt_tag + - id: big_map + type: big_map + if: (id_020__psparisc__lazy_storage_diff_elt_tag == id_020__psparisc__lazy_storage_diff_elt_tag::big_map) + - id: sapling_state + type: sapling_state + if: (id_020__psparisc__lazy_storage_diff_elt_tag == id_020__psparisc__lazy_storage_diff_elt_tag::sapling_state) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__sapling_state_id: + seq: + - id: id_020__psparisc__sapling_state_id + type: z + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + nullifiers: + seq: + - id: nullifiers_entries + type: nullifiers_entries + repeat: eos + nullifiers_0: + seq: + - id: len_nullifiers + type: u4be + valid: + max: 1073741823 + - id: nullifiers + type: nullifiers + size: len_nullifiers + nullifiers_entries: + seq: + - id: nullifiers_elt + type: sapling__transaction__nullifier + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + sapling_state: + seq: + - id: id + type: id_020__psparisc__sapling_state_id + doc: ! 'Sapling state identifier: A sapling state identifier' + - id: diff + type: diff_0 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + updates: + seq: + - id: updates_entries + type: updates_entries + repeat: eos + updates_0: + seq: + - id: len_updates + type: u4be + valid: + max: 1073741823 + - id: updates + type: updates + size: len_updates + updates_1: + seq: + - id: commitments_and_ciphertexts + type: commitments_and_ciphertexts_0 + - id: nullifiers + type: nullifiers_0 + updates_entries: + seq: + - id: key_hash + size: 32 + - id: key + type: micheline__020__psparisc__michelson_v1__expression + - id: value_tag + type: u1 + enum: bool + - id: value + type: micheline__020__psparisc__michelson_v1__expression + if: (value_tag == bool::true) + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + diff_tag: + 0: update + 1: remove + 2: copy + 3: alloc + id_020__psparisc__lazy_storage_diff_elt_tag: + 0: big_map + 1: sapling_state + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes +seq: +- id: len_id_020__psparisc__lazy_storage_diff + type: u4be + valid: + max: 1073741823 +- id: id_020__psparisc__lazy_storage_diff + type: id_020__psparisc__lazy_storage_diff + size: len_id_020__psparisc__lazy_storage_diff diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__level.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__level.ksy new file mode 100644 index 000000000000..1cbef7db989b --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__level.ksy @@ -0,0 +1,33 @@ +meta: + id: id_020__psparisc__level + endian: be +doc: ! 'Encoding id: 020-PsParisC.level' +enums: + bool: + 0: false + 255: true +seq: +- id: level + type: s4be + doc: ! >- + The level of the block relative to genesis. This is also the Shell's notion of + level. +- id: level_position + type: s4be + doc: ! >- + The level of the block relative to the successor of the genesis block. More precisely, + it is the position of the block relative to the block that starts the "Alpha family" + of protocols, which includes all protocols except Genesis (that is, from 001 onwards). +- id: cycle + type: s4be + doc: ! >- + The current cycle's number. Note that cycles are a protocol-specific notion. As + a result, the cycle number starts at 0 with the first block of the Alpha family + of protocols. +- id: cycle_position + type: s4be + doc: The current level of the block relative to the first block of the current cycle. +- id: expected_commitment + type: u1 + enum: bool + doc: Tells whether the baker of this block has to commit a seed nonce hash. diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__nonce.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__nonce.ksy new file mode 100644 index 000000000000..9cd171278e97 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__nonce.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__nonce + endian: be +doc: ! 'Encoding id: 020-PsParisC.nonce' +seq: +- id: id_020__psparisc__nonce + size: 32 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation.ksy new file mode 100644 index 000000000000..7c1afc68794e --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation.ksy @@ -0,0 +1,2037 @@ +meta: + id: id_020__psparisc__operation + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + attestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bls_signature_prefix: + seq: + - id: bls_signature_prefix_tag + type: u1 + enum: bls_signature_prefix_tag + - id: bls_prefix + size: 32 + if: (bls_signature_prefix_tag == bls_signature_prefix_tag::bls_prefix) + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + contents_and_signature_prefix_entries: + seq: + - id: id_020__psparisc__operation__alpha__contents_or_signature_prefix + type: id_020__psparisc__operation__alpha__contents_or_signature_prefix + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_attestation_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_preattestation_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__attestation: + seq: + - id: id_020__psparisc__inlined__attestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__attestation_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__attestation_mempool__contents: + seq: + - id: id_020__psparisc__inlined__attestation_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__attestation_mempool__contents_tag + - id: attestation + type: attestation + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation_with_dal) + id_020__psparisc__inlined__preattestation: + seq: + - id: id_020__psparisc__inlined__preattestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preattestation__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preattestation__contents: + seq: + - id: id_020__psparisc__inlined__preattestation__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preattestation__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__inlined__preattestation__contents_tag == id_020__psparisc__inlined__preattestation__contents_tag::preattestation) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation__alpha__contents_and_signature: + seq: + - id: contents_and_signature_prefix + type: contents_and_signature_prefix_entries + repeat: eos + - id: signature_suffix + size: 64 + id_020__psparisc__operation__alpha__contents_or_signature_prefix: + seq: + - id: id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag + type: u1 + enum: id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag + - id: signature_prefix + type: bls_signature_prefix + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::signature_prefix) + doc: The prefix of a BLS signature, i.e. the first 32 bytes. + - id: preattestation + type: preattestation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::preattestation) + - id: attestation + type: attestation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::attestation_with_dal) + - id: double_preattestation_evidence + type: double_preattestation_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_preattestation_evidence) + - id: double_attestation_evidence + type: double_attestation_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_attestation_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_update) + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preattestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bls_signature_prefix_tag: + 3: bls_prefix + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__attestation_mempool__contents_tag: + 21: attestation + 23: attestation_with_dal + id_020__psparisc__inlined__preattestation__contents_tag: + 20: preattestation + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag: + 1: seed_nonce_revelation + 2: double_attestation_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preattestation_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preattestation + 21: attestation + 23: attestation_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + 255: signature_prefix + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation + type: operation__shell_header +- id: id_020__psparisc__operation__alpha__contents_and_signature + type: id_020__psparisc__operation__alpha__contents_and_signature diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents.ksy new file mode 100644 index 000000000000..374ee41b3e15 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents.ksy @@ -0,0 +1,1974 @@ +meta: + id: id_020__psparisc__operation__contents + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation.contents' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + attestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_attestation_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_preattestation_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__attestation: + seq: + - id: id_020__psparisc__inlined__attestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__attestation_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__attestation_mempool__contents: + seq: + - id: id_020__psparisc__inlined__attestation_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__attestation_mempool__contents_tag + - id: attestation + type: attestation + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation_with_dal) + id_020__psparisc__inlined__preattestation: + seq: + - id: id_020__psparisc__inlined__preattestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preattestation__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preattestation__contents: + seq: + - id: id_020__psparisc__inlined__preattestation__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preattestation__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__inlined__preattestation__contents_tag == id_020__psparisc__inlined__preattestation__contents_tag::preattestation) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation__alpha__contents: + seq: + - id: id_020__psparisc__operation__alpha__contents_tag + type: u1 + enum: id_020__psparisc__operation__alpha__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::preattestation) + - id: attestation + type: attestation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::attestation_with_dal) + - id: double_preattestation_evidence + type: double_preattestation_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_preattestation_evidence) + - id: double_attestation_evidence + type: double_attestation_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_attestation_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_update) + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preattestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__attestation_mempool__contents_tag: + 21: attestation + 23: attestation_with_dal + id_020__psparisc__inlined__preattestation__contents_tag: + 20: preattestation + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation__alpha__contents_tag: + 1: seed_nonce_revelation + 2: double_attestation_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preattestation_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preattestation + 21: attestation + 23: attestation_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation__alpha__contents + type: id_020__psparisc__operation__alpha__contents diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents_list.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents_list.ksy new file mode 100644 index 000000000000..2811ae3b6350 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__contents_list.ksy @@ -0,0 +1,1979 @@ +meta: + id: id_020__psparisc__operation__contents_list + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation.contents_list' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + attestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_attestation_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_preattestation_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__attestation: + seq: + - id: id_020__psparisc__inlined__attestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__attestation_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__attestation_mempool__contents: + seq: + - id: id_020__psparisc__inlined__attestation_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__attestation_mempool__contents_tag + - id: attestation + type: attestation + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation_with_dal) + id_020__psparisc__inlined__preattestation: + seq: + - id: id_020__psparisc__inlined__preattestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preattestation__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preattestation__contents: + seq: + - id: id_020__psparisc__inlined__preattestation__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preattestation__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__inlined__preattestation__contents_tag == id_020__psparisc__inlined__preattestation__contents_tag::preattestation) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation__alpha__contents: + seq: + - id: id_020__psparisc__operation__alpha__contents_tag + type: u1 + enum: id_020__psparisc__operation__alpha__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::preattestation) + - id: attestation + type: attestation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::attestation_with_dal) + - id: double_preattestation_evidence + type: double_preattestation_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_preattestation_evidence) + - id: double_attestation_evidence + type: double_attestation_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_attestation_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_update) + id_020__psparisc__operation__contents_list_entries: + seq: + - id: id_020__psparisc__operation__alpha__contents + type: id_020__psparisc__operation__alpha__contents + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preattestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__attestation_mempool__contents_tag: + 21: attestation + 23: attestation_with_dal + id_020__psparisc__inlined__preattestation__contents_tag: + 20: preattestation + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation__alpha__contents_tag: + 1: seed_nonce_revelation + 2: double_attestation_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preattestation_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preattestation + 21: attestation + 23: attestation_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation__contents_list_entries + type: id_020__psparisc__operation__contents_list_entries + repeat: eos diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__internal.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__internal.ksy new file mode 100644 index 000000000000..77fce393f3a5 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__internal.ksy @@ -0,0 +1,800 @@ +meta: + id: id_020__psparisc__operation__internal + endian: be +doc: ! 'Encoding id: 020-PsParisC.operation.internal' +types: + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + delegation: + seq: + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + event: + seq: + - id: type + type: micheline__020__psparisc__michelson_v1__expression + - id: tag_tag + type: u1 + enum: bool + - id: tag + type: id_020__psparisc__entrypoint + if: (tag_tag == bool::true) + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: payload_tag + type: u1 + enum: bool + - id: payload + type: micheline__020__psparisc__michelson_v1__expression + if: (payload_tag == bool::true) + id_020__psparisc__apply_internal_results__alpha__operation_result: + seq: + - id: source + type: id_020__psparisc__transaction_destination + doc: ! >- + A destination of a transaction: A destination notation compatible with the + contract notation as given to an RPC or inside scripts. Can be a base58 implicit + contract hash, a base58 originated contract hash, a base58 originated transaction + rollup, or a base58 originated smart rollup. + - id: nonce + type: u2be + - id: id_020__psparisc__apply_internal_results__alpha__operation_result_tag + type: u1 + enum: id_020__psparisc__apply_internal_results__alpha__operation_result_tag + - id: transaction + type: transaction + if: (id_020__psparisc__apply_internal_results__alpha__operation_result_tag == + id_020__psparisc__apply_internal_results__alpha__operation_result_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__apply_internal_results__alpha__operation_result_tag == + id_020__psparisc__apply_internal_results__alpha__operation_result_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__apply_internal_results__alpha__operation_result_tag == + id_020__psparisc__apply_internal_results__alpha__operation_result_tag::delegation) + - id: event + type: event + if: (id_020__psparisc__apply_internal_results__alpha__operation_result_tag == + id_020__psparisc__apply_internal_results__alpha__operation_result_tag::event) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + id_020__psparisc__transaction_destination: + seq: + - id: id_020__psparisc__transaction_destination_tag + type: u1 + enum: id_020__psparisc__transaction_destination_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__transaction_destination_tag == id_020__psparisc__transaction_destination_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__transaction_destination_tag == id_020__psparisc__transaction_destination_tag::originated) + - id: smart_rollup + type: smart_rollup + if: (id_020__psparisc__transaction_destination_tag == id_020__psparisc__transaction_destination_tag::smart_rollup) + - id: zk_rollup + type: zk_rollup + if: (id_020__psparisc__transaction_destination_tag == id_020__psparisc__transaction_destination_tag::zk_rollup) + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + smart_rollup: + seq: + - id: smart_rollup_address + size: 20 + - id: smart_rollup_padding + size: 1 + doc: This field is for padding, ignore + transaction: + seq: + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__transaction_destination + doc: ! >- + A destination of a transaction: A destination notation compatible with the + contract notation as given to an RPC or inside scripts. Can be a base58 implicit + contract hash, a base58 originated contract hash, a base58 originated transaction + rollup, or a base58 originated smart rollup. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup: + seq: + - id: zk_rollup_hash + size: 20 + - id: zk_rollup_padding + size: 1 + doc: This field is for padding, ignore +enums: + bool: + 0: false + 255: true + id_020__psparisc__apply_internal_results__alpha__operation_result_tag: + 1: transaction + 2: origination + 3: delegation + 4: event + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__transaction_destination_tag: + 0: implicit + 1: originated + 3: smart_rollup + 4: zk_rollup + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__apply_internal_results__alpha__operation_result + type: id_020__psparisc__apply_internal_results__alpha__operation_result diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__protocol_data.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__protocol_data.ksy new file mode 100644 index 000000000000..4179cb71ae1b --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__protocol_data.ksy @@ -0,0 +1,2035 @@ +meta: + id: id_020__psparisc__operation__protocol_data + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation.protocol_data' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + attestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bls_signature_prefix: + seq: + - id: bls_signature_prefix_tag + type: u1 + enum: bls_signature_prefix_tag + - id: bls_prefix + size: 32 + if: (bls_signature_prefix_tag == bls_signature_prefix_tag::bls_prefix) + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + contents_and_signature_prefix_entries: + seq: + - id: id_020__psparisc__operation__alpha__contents_or_signature_prefix + type: id_020__psparisc__operation__alpha__contents_or_signature_prefix + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_attestation_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_preattestation_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__attestation: + seq: + - id: id_020__psparisc__inlined__attestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__attestation_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__attestation_mempool__contents: + seq: + - id: id_020__psparisc__inlined__attestation_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__attestation_mempool__contents_tag + - id: attestation + type: attestation + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation_with_dal) + id_020__psparisc__inlined__preattestation: + seq: + - id: id_020__psparisc__inlined__preattestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preattestation__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preattestation__contents: + seq: + - id: id_020__psparisc__inlined__preattestation__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preattestation__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__inlined__preattestation__contents_tag == id_020__psparisc__inlined__preattestation__contents_tag::preattestation) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation__alpha__contents_and_signature: + seq: + - id: contents_and_signature_prefix + type: contents_and_signature_prefix_entries + repeat: eos + - id: signature_suffix + size: 64 + id_020__psparisc__operation__alpha__contents_or_signature_prefix: + seq: + - id: id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag + type: u1 + enum: id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag + - id: signature_prefix + type: bls_signature_prefix + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::signature_prefix) + doc: The prefix of a BLS signature, i.e. the first 32 bytes. + - id: preattestation + type: preattestation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::preattestation) + - id: attestation + type: attestation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::attestation_with_dal) + - id: double_preattestation_evidence + type: double_preattestation_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_preattestation_evidence) + - id: double_attestation_evidence + type: double_attestation_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_attestation_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_update) + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preattestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bls_signature_prefix_tag: + 3: bls_prefix + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__attestation_mempool__contents_tag: + 21: attestation + 23: attestation_with_dal + id_020__psparisc__inlined__preattestation__contents_tag: + 20: preattestation + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag: + 1: seed_nonce_revelation + 2: double_attestation_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preattestation_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preattestation + 21: attestation + 23: attestation_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + 255: signature_prefix + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation__alpha__contents_and_signature + type: id_020__psparisc__operation__alpha__contents_and_signature diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__raw.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__raw.ksy new file mode 100644 index 000000000000..97643e85db7b --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__raw.ksy @@ -0,0 +1,9 @@ +meta: + id: id_020__psparisc__operation__raw + endian: be + imports: + - operation +doc: ! 'Encoding id: 020-PsParisC.operation.raw' +seq: +- id: id_020__psparisc__operation__raw + type: operation diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__unsigned.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__unsigned.ksy new file mode 100644 index 000000000000..db9e36a9ac29 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation__unsigned.ksy @@ -0,0 +1,1985 @@ +meta: + id: id_020__psparisc__operation__unsigned + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation.unsigned' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + attestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + contents_entries: + seq: + - id: id_020__psparisc__operation__alpha__contents + type: id_020__psparisc__operation__alpha__contents + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_attestation_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_preattestation_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__attestation: + seq: + - id: id_020__psparisc__inlined__attestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__attestation_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__attestation_mempool__contents: + seq: + - id: id_020__psparisc__inlined__attestation_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__attestation_mempool__contents_tag + - id: attestation + type: attestation + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation_with_dal) + id_020__psparisc__inlined__preattestation: + seq: + - id: id_020__psparisc__inlined__preattestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preattestation__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preattestation__contents: + seq: + - id: id_020__psparisc__inlined__preattestation__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preattestation__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__inlined__preattestation__contents_tag == id_020__psparisc__inlined__preattestation__contents_tag::preattestation) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation__alpha__contents: + seq: + - id: id_020__psparisc__operation__alpha__contents_tag + type: u1 + enum: id_020__psparisc__operation__alpha__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::preattestation) + - id: attestation + type: attestation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::attestation_with_dal) + - id: double_preattestation_evidence + type: double_preattestation_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_preattestation_evidence) + - id: double_attestation_evidence + type: double_attestation_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_attestation_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation__alpha__contents_tag == id_020__psparisc__operation__alpha__contents_tag::zk_rollup_update) + id_020__psparisc__operation__alpha__unsigned_operation: + seq: + - id: id_020__psparisc__operation__alpha__unsigned_operation + type: operation__shell_header + - id: contents + type: contents_entries + repeat: eos + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preattestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__attestation_mempool__contents_tag: + 21: attestation + 23: attestation_with_dal + id_020__psparisc__inlined__preattestation__contents_tag: + 20: preattestation + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation__alpha__contents_tag: + 1: seed_nonce_revelation + 2: double_attestation_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preattestation_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preattestation + 21: attestation + 23: attestation_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation__alpha__unsigned_operation + type: id_020__psparisc__operation__alpha__unsigned_operation diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name.ksy new file mode 100644 index 000000000000..5cc30bfee013 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name.ksy @@ -0,0 +1,2037 @@ +meta: + id: id_020__psparisc__operation_with_legacy_attestation_name + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation_with_legacy_attestation_name' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + attestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bls_signature_prefix: + seq: + - id: bls_signature_prefix_tag + type: u1 + enum: bls_signature_prefix_tag + - id: bls_prefix + size: 32 + if: (bls_signature_prefix_tag == bls_signature_prefix_tag::bls_prefix) + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + contents_and_signature_prefix_entries: + seq: + - id: id_020__psparisc__operation__alpha__contents_or_signature_prefix + type: id_020__psparisc__operation__alpha__contents_or_signature_prefix + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_attestation_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_preattestation_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__attestation: + seq: + - id: id_020__psparisc__inlined__attestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__attestation_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__attestation_mempool__contents: + seq: + - id: id_020__psparisc__inlined__attestation_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__attestation_mempool__contents_tag + - id: attestation + type: attestation + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__inlined__attestation_mempool__contents_tag == id_020__psparisc__inlined__attestation_mempool__contents_tag::attestation_with_dal) + id_020__psparisc__inlined__preattestation: + seq: + - id: id_020__psparisc__inlined__preattestation + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preattestation__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preattestation__contents: + seq: + - id: id_020__psparisc__inlined__preattestation__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preattestation__contents_tag + - id: preattestation + type: preattestation + if: (id_020__psparisc__inlined__preattestation__contents_tag == id_020__psparisc__inlined__preattestation__contents_tag::preattestation) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation__alpha__contents_or_signature_prefix: + seq: + - id: id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag + type: u1 + enum: id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag + - id: signature_prefix + type: bls_signature_prefix + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::signature_prefix) + doc: The prefix of a BLS signature, i.e. the first 32 bytes. + - id: preattestation + type: preattestation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::preattestation) + - id: attestation + type: attestation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::attestation_with_dal) + - id: double_preattestation_evidence + type: double_preattestation_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_preattestation_evidence) + - id: double_attestation_evidence + type: double_attestation_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_attestation_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag == + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag::zk_rollup_update) + id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_and_signature: + seq: + - id: contents_and_signature_prefix + type: contents_and_signature_prefix_entries + repeat: eos + - id: signature_suffix + size: 64 + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preattestation + type: id_020__psparisc__inlined__preattestation + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__attestation + type: id_020__psparisc__inlined__attestation + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preattestation: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bls_signature_prefix_tag: + 3: bls_prefix + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__attestation_mempool__contents_tag: + 21: attestation + 23: attestation_with_dal + id_020__psparisc__inlined__preattestation__contents_tag: + 20: preattestation + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation__alpha__contents_or_signature_prefix_tag: + 1: seed_nonce_revelation + 2: double_attestation_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preattestation_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preattestation + 21: attestation + 23: attestation_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + 255: signature_prefix + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation_with_legacy_attestation_name + type: operation__shell_header +- id: id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_and_signature + type: id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_and_signature diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name__unsigned.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name__unsigned.ksy new file mode 100644 index 000000000000..169fc7eaf94d --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__operation_with_legacy_attestation_name__unsigned.ksy @@ -0,0 +1,2019 @@ +meta: + id: id_020__psparisc__operation_with_legacy_attestation_name__unsigned + endian: be + imports: + - block_header__shell + - operation__shell_header +doc: ! 'Encoding id: 020-PsParisC.operation_with_legacy_attestation_name.unsigned' +types: + activate_account: + seq: + - id: pkh + size: 20 + - id: secret + size: 20 + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + ballot: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposal + size: 32 + - id: ballot + type: s1 + bh1: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh1_0: + seq: + - id: len_bh1 + type: u4be + valid: + max: 1073741823 + - id: bh1 + type: bh1 + size: len_bh1 + bh2: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: id_020__psparisc__block_header__alpha__full_header + bh2_0: + seq: + - id: len_bh2 + type: u4be + valid: + max: 1073741823 + - id: bh2 + type: bh2 + size: len_bh2 + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + circuits_info: + seq: + - id: circuits_info_entries + type: circuits_info_entries + repeat: eos + circuits_info_0: + seq: + - id: len_circuits_info + type: u4be + valid: + max: 1073741823 + - id: circuits_info + type: circuits_info + size: len_circuits_info + circuits_info_entries: + seq: + - id: circuits_info_elt_field0 + type: bytes_dyn_uint30 + - id: circuits_info_elt_field1 + type: u1 + enum: circuits_info_elt_field1_tag + doc: circuits_info_elt_field1_tag + commitment: + seq: + - id: compressed_state + size: 32 + - id: inbox_level + type: s4be + - id: predecessor + size: 32 + - id: number_of_ticks + type: s8be + contents_entries: + seq: + - id: id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents + type: id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + dal_publish_commitment: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: slot_header + type: slot_header + delegation: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + double_baking_evidence: + seq: + - id: bh1 + type: bh1_0 + - id: bh2 + type: bh2_0 + double_endorsement_evidence: + seq: + - id: op1 + type: op1_2 + - id: op2 + type: op2_2 + double_preendorsement_evidence: + seq: + - id: op1 + type: op1_0 + - id: op2 + type: op2_0 + drain_delegate: + seq: + - id: consensus_key + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + endorsement: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + endorsement_with_dal: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z + id_020__psparisc__block_header__alpha__full_header: + seq: + - id: id_020__psparisc__block_header__alpha__full_header + type: block_header__shell + - id: id_020__psparisc__block_header__alpha__signed_contents + type: id_020__psparisc__block_header__alpha__signed_contents + id_020__psparisc__block_header__alpha__signed_contents: + seq: + - id: id_020__psparisc__block_header__alpha__unsigned_contents + type: id_020__psparisc__block_header__alpha__unsigned_contents + - id: signature + size-eos: true + id_020__psparisc__block_header__alpha__unsigned_contents: + seq: + - id: payload_hash + size: 32 + - id: payload_round + type: s4be + - id: proof_of_work_nonce + size: 8 + - id: seed_nonce_hash_tag + type: u1 + enum: bool + - id: seed_nonce_hash + size: 32 + if: (seed_nonce_hash_tag == bool::true) + - id: per_block_votes + type: id_020__psparisc__per_block_votes + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__entrypoint: + seq: + - id: id_020__psparisc__entrypoint_tag + type: u1 + enum: id_020__psparisc__entrypoint_tag + - id: named + type: named_0 + if: (id_020__psparisc__entrypoint_tag == id_020__psparisc__entrypoint_tag::named) + id_020__psparisc__inlined__endorsement: + seq: + - id: id_020__psparisc__inlined__endorsement + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__endorsement_mempool__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__endorsement_mempool__contents: + seq: + - id: id_020__psparisc__inlined__endorsement_mempool__contents_tag + type: u1 + enum: id_020__psparisc__inlined__endorsement_mempool__contents_tag + - id: endorsement + type: endorsement + if: (id_020__psparisc__inlined__endorsement_mempool__contents_tag == id_020__psparisc__inlined__endorsement_mempool__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (id_020__psparisc__inlined__endorsement_mempool__contents_tag == id_020__psparisc__inlined__endorsement_mempool__contents_tag::endorsement_with_dal) + id_020__psparisc__inlined__preendorsement: + seq: + - id: id_020__psparisc__inlined__preendorsement + type: operation__shell_header + - id: operations + type: id_020__psparisc__inlined__preendorsement__contents + - id: signature_tag + type: u1 + enum: bool + - id: signature + size-eos: true + if: (signature_tag == bool::true) + id_020__psparisc__inlined__preendorsement__contents: + seq: + - id: id_020__psparisc__inlined__preendorsement__contents_tag + type: u1 + enum: id_020__psparisc__inlined__preendorsement__contents_tag + - id: preendorsement + type: preendorsement + if: (id_020__psparisc__inlined__preendorsement__contents_tag == id_020__psparisc__inlined__preendorsement__contents_tag::preendorsement) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents: + seq: + - id: id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + type: u1 + enum: id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + - id: preendorsement + type: preendorsement + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::preendorsement) + - id: endorsement + type: endorsement + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement_with_dal) + - id: double_preendorsement_evidence + type: double_preendorsement_evidence + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::double_preendorsement_evidence) + - id: double_endorsement_evidence + type: double_endorsement_evidence + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::double_endorsement_evidence) + - id: seed_nonce_revelation + type: seed_nonce_revelation + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::seed_nonce_revelation) + - id: vdf_revelation + type: solution + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::vdf_revelation) + - id: double_baking_evidence + type: double_baking_evidence + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::double_baking_evidence) + - id: activate_account + type: activate_account + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::activate_account) + - id: proposals + type: proposals_1 + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::proposals) + - id: ballot + type: ballot + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::ballot) + - id: reveal + type: reveal + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::reveal) + - id: transaction + type: transaction + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::transaction) + - id: origination + type: origination + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::origination) + - id: delegation + type: delegation + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::delegation) + - id: set_deposits_limit + type: set_deposits_limit + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::set_deposits_limit) + - id: increase_paid_storage + type: increase_paid_storage + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::increase_paid_storage) + - id: update_consensus_key + type: update_consensus_key + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::update_consensus_key) + - id: drain_delegate + type: drain_delegate + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::drain_delegate) + - id: failing_noop + type: bytes_dyn_uint30 + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::failing_noop) + - id: register_global_constant + type: register_global_constant + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::register_global_constant) + - id: transfer_ticket + type: transfer_ticket + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::transfer_ticket) + - id: dal_publish_commitment + type: dal_publish_commitment + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::dal_publish_commitment) + - id: smart_rollup_originate + type: smart_rollup_originate + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_originate) + - id: smart_rollup_add_messages + type: smart_rollup_add_messages + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_add_messages) + - id: smart_rollup_cement + type: smart_rollup_cement + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_cement) + - id: smart_rollup_publish + type: smart_rollup_publish + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_publish) + - id: smart_rollup_refute + type: smart_rollup_refute + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_refute) + - id: smart_rollup_timeout + type: smart_rollup_timeout + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_timeout) + - id: smart_rollup_execute_outbox_message + type: smart_rollup_execute_outbox_message + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_execute_outbox_message) + - id: smart_rollup_recover_bond + type: smart_rollup_recover_bond + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::smart_rollup_recover_bond) + - id: zk_rollup_origination + type: zk_rollup_origination + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::zk_rollup_origination) + - id: zk_rollup_publish + type: zk_rollup_publish + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::zk_rollup_publish) + - id: zk_rollup_update + type: zk_rollup_update + if: (id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag + == id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag::zk_rollup_update) + id_020__psparisc__operation_with_legacy_attestation_name__alpha__unsigned_operation: + seq: + - id: id_020__psparisc__operation_with_legacy_attestation_name__alpha__unsigned_operation + type: operation__shell_header + - id: contents + type: contents_entries + repeat: eos + id_020__psparisc__per_block_votes: + seq: + - id: id_020__psparisc__per_block_votes_tag + type: u1 + enum: id_020__psparisc__per_block_votes_tag + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + increase_paid_storage: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: z + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + init_state: + seq: + - id: init_state_entries + type: init_state_entries + repeat: eos + init_state_0: + seq: + - id: len_init_state + type: u4be + valid: + max: 1073741823 + - id: init_state + type: init_state + size: len_init_state + init_state_entries: + seq: + - id: init_state_elt + size: 32 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + message: + seq: + - id: message_entries + type: message_entries + repeat: eos + message_0: + seq: + - id: len_message + type: u4be + valid: + max: 1073741823 + - id: message + type: message + size: len_message + message_entries: + seq: + - id: message_elt + type: bytes_dyn_uint30 + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + move: + seq: + - id: choice + type: n + - id: step + type: step + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + named: + seq: + - id: named + size-eos: true + named_0: + seq: + - id: len_named + type: u1 + valid: + max: 31 + - id: named + type: named + size: len_named + new_state: + seq: + - id: new_state_entries + type: new_state_entries + repeat: eos + new_state_0: + seq: + - id: len_new_state + type: u4be + valid: + max: 1073741823 + - id: new_state + type: new_state + size: len_new_state + new_state_entries: + seq: + - id: new_state_elt + size: 32 + op: + seq: + - id: op_entries + type: op_entries + repeat: eos + op1: + seq: + - id: id_020__psparisc__inlined__preendorsement + type: id_020__psparisc__inlined__preendorsement + op1_0: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1 + size: len_op1 + op1_1: + seq: + - id: id_020__psparisc__inlined__endorsement + type: id_020__psparisc__inlined__endorsement + op1_2: + seq: + - id: len_op1 + type: u4be + valid: + max: 1073741823 + - id: op1 + type: op1_1 + size: len_op1 + op2: + seq: + - id: id_020__psparisc__inlined__preendorsement + type: id_020__psparisc__inlined__preendorsement + op2_0: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2 + size: len_op2 + op2_1: + seq: + - id: id_020__psparisc__inlined__endorsement + type: id_020__psparisc__inlined__endorsement + op2_2: + seq: + - id: len_op2 + type: u4be + valid: + max: 1073741823 + - id: op2 + type: op2_1 + size: len_op2 + op_0: + seq: + - id: len_op + type: u4be + valid: + max: 1073741823 + - id: op + type: op + size: len_op + op_elt_field0: + seq: + - id: op_code + type: int31 + - id: price + type: price + - id: l1_dst + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: rollup_id + size: 20 + - id: payload + type: payload_0 + op_elt_field1: + seq: + - id: op_elt_field1_tag + type: u1 + enum: op_elt_field1_tag + - id: some + type: some + if: (op_elt_field1_tag == op_elt_field1_tag::some) + op_entries: + seq: + - id: op_elt_field0 + type: op_elt_field0 + - id: op_elt_field1 + type: op_elt_field1 + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: balance + type: id_020__psparisc__mutez + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: script + type: id_020__psparisc__scripted__contracts + parameters: + seq: + - id: entrypoint + type: id_020__psparisc__entrypoint + doc: ! 'entrypoint: Named entrypoint to a Michelson smart contract' + - id: value + type: bytes_dyn_uint30 + payload: + seq: + - id: payload_entries + type: payload_entries + repeat: eos + payload_0: + seq: + - id: len_payload + type: u4be + valid: + max: 1073741823 + - id: payload + type: payload + size: len_payload + payload_entries: + seq: + - id: payload_elt + size: 32 + pending_pis: + seq: + - id: pending_pis_entries + type: pending_pis_entries + repeat: eos + pending_pis_0: + seq: + - id: len_pending_pis + type: u4be + valid: + max: 1073741823 + - id: pending_pis + type: pending_pis + size: len_pending_pis + pending_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + - id: exit_validity + type: u1 + enum: bool + pending_pis_entries: + seq: + - id: pending_pis_elt_field0 + type: bytes_dyn_uint30 + - id: pending_pis_elt_field1 + type: pending_pis_elt_field1 + preendorsement: + seq: + - id: slot + type: u2be + - id: level + type: s4be + - id: round + type: s4be + - id: block_payload_hash + size: 32 + price: + seq: + - id: id + size: 32 + - id: amount + type: z + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + private_pis: + seq: + - id: private_pis_entries + type: private_pis_entries + repeat: eos + private_pis_0: + seq: + - id: len_private_pis + type: u4be + valid: + max: 1073741823 + - id: private_pis + type: private_pis + size: len_private_pis + private_pis_elt_field1: + seq: + - id: new_state + type: new_state_0 + - id: fee + size: 32 + private_pis_entries: + seq: + - id: private_pis_elt_field0 + type: bytes_dyn_uint30 + - id: private_pis_elt_field1 + type: private_pis_elt_field1 + proof: + seq: + - id: pvm_step + type: bytes_dyn_uint30 + - id: input_proof_tag + type: u1 + enum: bool + - id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) + proposals: + seq: + - id: proposals_entries + type: proposals_entries + repeat: eos + proposals_0: + seq: + - id: len_proposals + type: u4be + valid: + max: 640 + - id: proposals + type: proposals + size: len_proposals + proposals_1: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: period + type: s4be + - id: proposals + type: proposals_0 + proposals_entries: + seq: + - id: protocol_hash + size: 32 + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + refutation: + seq: + - id: refutation_tag + type: u1 + enum: refutation_tag + - id: start + type: start + if: (refutation_tag == refutation_tag::start) + - id: move + type: move + if: (refutation_tag == refutation_tag::move) + register_global_constant: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: value + type: bytes_dyn_uint30 + reveal: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_key + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) + seed_nonce_revelation: + seq: + - id: level + type: s4be + - id: nonce + size: 32 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + set_deposits_limit: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: limit_tag + type: u1 + enum: bool + - id: limit + type: id_020__psparisc__mutez + if: (limit_tag == bool::true) + slot_header: + seq: + - id: slot_index + type: u1 + - id: commitment + size: 48 + - id: commitment_proof + size: 96 + smart_rollup_add_messages: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: message + type: message_0 + smart_rollup_cement: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + smart_rollup_execute_outbox_message: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: cemented_commitment + size: 32 + - id: output_proof + type: bytes_dyn_uint30 + smart_rollup_originate: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + smart_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: commitment + type: commitment + smart_rollup_recover_bond: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: staker + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + smart_rollup_refute: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: opponent + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: refutation + type: refutation + smart_rollup_timeout: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: rollup + size: 20 + - id: stakers + type: stakers + solution: + seq: + - id: solution_field0 + size: 100 + - id: solution_field1 + size: 100 + some: + seq: + - id: contents + type: micheline__020__psparisc__michelson_v1__expression + - id: ty + type: micheline__020__psparisc__michelson_v1__expression + - id: ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + stakers: + seq: + - id: alice + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: bob + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + start: + seq: + - id: player_commitment_hash + size: 32 + - id: opponent_commitment_hash + size: 32 + step: + seq: + - id: step_tag + type: u1 + enum: step_tag + - id: dissection + type: dissection_0 + if: (step_tag == step_tag::dissection) + - id: proof + type: proof + if: (step_tag == step_tag::proof) + transaction: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: amount + type: id_020__psparisc__mutez + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: parameters_tag + type: u1 + enum: bool + - id: parameters + type: parameters + if: (parameters_tag == bool::true) + transfer_ticket: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: ticket_contents + type: bytes_dyn_uint30 + - id: ticket_ty + type: bytes_dyn_uint30 + - id: ticket_ticketer + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: ticket_amount + type: n + - id: destination + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + update: + seq: + - id: pending_pis + type: pending_pis_0 + - id: private_pis + type: private_pis_0 + - id: fee_pi + type: new_state_0 + - id: proof + type: bytes_dyn_uint30 + update_consensus_key: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: pk + type: public_key + doc: A Ed25519, Secp256k1, or P256 public key + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as + zk_rollup_origination: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: public_parameters + type: bytes_dyn_uint30 + - id: circuits_info + type: circuits_info_0 + - id: init_state + type: init_state_0 + - id: nb_ops + type: int31 + zk_rollup_publish: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: op + type: op_0 + zk_rollup_update: + seq: + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: fee + type: id_020__psparisc__mutez + - id: counter + type: n + - id: gas_limit + type: n + - id: storage_limit + type: n + - id: zk_rollup + size: 20 + - id: update + type: update +enums: + bool: + 0: false + 255: true + circuits_info_elt_field1_tag: + 0: public + 1: private + 2: fee + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__entrypoint_tag: + 0: default + 1: root + 2: do + 3: set_delegate + 4: remove_delegate + 5: deposit + 6: stake + 7: unstake + 8: finalize_unstake + 9: set_delegate_parameters + 255: named + id_020__psparisc__inlined__endorsement_mempool__contents_tag: + 21: endorsement + 23: endorsement_with_dal + id_020__psparisc__inlined__preendorsement__contents_tag: + 20: preendorsement + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__operation_with_legacy_attestation_name__alpha__contents_tag: + 1: seed_nonce_revelation + 2: double_endorsement_evidence + 3: double_baking_evidence + 4: activate_account + 5: proposals + 6: ballot + 7: double_preendorsement_evidence + 8: vdf_revelation + 9: drain_delegate + 17: failing_noop + 20: preendorsement + 21: endorsement + 23: endorsement_with_dal + 107: reveal + 108: transaction + 109: origination + 110: delegation + 111: register_global_constant + 112: set_deposits_limit + 113: increase_paid_storage + 114: update_consensus_key + 158: transfer_ticket + 200: smart_rollup_originate + 201: smart_rollup_add_messages + 202: smart_rollup_cement + 203: smart_rollup_publish + 204: smart_rollup_refute + 205: smart_rollup_timeout + 206: smart_rollup_execute_outbox_message + 207: smart_rollup_recover_bond + 230: dal_publish_commitment + 250: zk_rollup_origination + 251: zk_rollup_publish + 252: zk_rollup_update + id_020__psparisc__per_block_votes_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 4: case_4 + 5: case_5 + 6: case_6 + 8: case_8 + 9: case_9 + 10: case_10 + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + op_elt_field1_tag: + 0: none + 1: some + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv + refutation_tag: + 0: start + 1: move + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof + step_tag: + 0: dissection + 1: proof +seq: +- id: id_020__psparisc__operation_with_legacy_attestation_name__alpha__unsigned_operation + type: id_020__psparisc__operation_with_legacy_attestation_name__alpha__unsigned_operation diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__parameters.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__parameters.ksy new file mode 100644 index 000000000000..88046d627265 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__parameters.ksy @@ -0,0 +1,616 @@ +meta: + id: id_020__psparisc__parameters + endian: be +doc: ! 'Encoding id: 020-PsParisC.parameters' +types: + adaptive_rewards_params: + seq: + - id: issuance_ratio_final_min + type: issuance_ratio_final_min + - id: issuance_ratio_final_max + type: issuance_ratio_final_max + - id: issuance_ratio_initial_min + type: issuance_ratio_initial_min + - id: issuance_ratio_initial_max + type: issuance_ratio_initial_max + - id: initial_period + type: u1 + - id: transition_period + type: u1 + - id: max_bonus + type: s8be + - id: growth_rate + type: growth_rate + - id: center_dz + type: center_dz + - id: radius_dz + type: radius_dz + bootstrap_accounts: + seq: + - id: bootstrap_accounts_entries + type: bootstrap_accounts_entries + repeat: eos + bootstrap_accounts_0: + seq: + - id: len_bootstrap_accounts + type: u4be + valid: + max: 1073741823 + - id: bootstrap_accounts + type: bootstrap_accounts + size: len_bootstrap_accounts + bootstrap_accounts_entries: + seq: + - id: bootstrap_accounts_elt_tag + type: u1 + enum: bootstrap_accounts_elt_tag + - id: public_key_known + type: public_key_known + if: (bootstrap_accounts_elt_tag == bootstrap_accounts_elt_tag::public_key_known) + - id: public_key_unknown + type: public_key_unknown + if: (bootstrap_accounts_elt_tag == bootstrap_accounts_elt_tag::public_key_unknown) + - id: public_key_known_with_delegate + type: public_key_known_with_delegate + if: (bootstrap_accounts_elt_tag == bootstrap_accounts_elt_tag::public_key_known_with_delegate) + - id: public_key_unknown_with_delegate + type: public_key_unknown_with_delegate + if: (bootstrap_accounts_elt_tag == bootstrap_accounts_elt_tag::public_key_unknown_with_delegate) + - id: public_key_known_with_consensus_key + type: public_key_known_with_consensus_key + if: (bootstrap_accounts_elt_tag == bootstrap_accounts_elt_tag::public_key_known_with_consensus_key) + bootstrap_contracts: + seq: + - id: bootstrap_contracts_entries + type: bootstrap_contracts_entries + repeat: eos + bootstrap_contracts_0: + seq: + - id: len_bootstrap_contracts + type: u4be + valid: + max: 1073741823 + - id: bootstrap_contracts + type: bootstrap_contracts + size: len_bootstrap_contracts + bootstrap_contracts_entries: + seq: + - id: delegate_tag + type: u1 + enum: bool + - id: delegate + type: public_key_hash + if: (delegate_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: amount + type: id_020__psparisc__mutez + - id: script + type: id_020__psparisc__scripted__contracts + - id: hash_tag + type: u1 + enum: bool + - id: hash + size: 20 + if: (hash_tag == bool::true) + bootstrap_smart_rollups: + seq: + - id: bootstrap_smart_rollups_entries + type: bootstrap_smart_rollups_entries + repeat: eos + bootstrap_smart_rollups_0: + seq: + - id: len_bootstrap_smart_rollups + type: u4be + valid: + max: 1073741823 + - id: bootstrap_smart_rollups + type: bootstrap_smart_rollups + size: len_bootstrap_smart_rollups + bootstrap_smart_rollups_entries: + seq: + - id: address + size: 20 + - id: pvm_kind + type: u1 + enum: pvm_kind + - id: kernel + type: bytes_dyn_uint30 + - id: parameters_ty + type: bytes_dyn_uint30 + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + center_dz: + seq: + - id: numerator + type: z + - id: denominator + type: z + commitments: + seq: + - id: commitments_entries + type: commitments_entries + repeat: eos + commitments_0: + seq: + - id: len_commitments + type: u4be + valid: + max: 1073741823 + - id: commitments + type: commitments + size: len_commitments + commitments_entries: + seq: + - id: commitments_elt_field0 + size: 20 + doc: blinded__public__key__hash + - id: commitments_elt_field1 + type: id_020__psparisc__mutez + doc: id_020__psparisc__mutez + dal_parametric: + seq: + - id: feature_enable + type: u1 + enum: bool + - id: incentives_enable + type: u1 + enum: bool + - id: number_of_slots + type: u2be + - id: attestation_lag + type: u1 + - id: attestation_threshold + type: u1 + - id: redundancy_factor + type: u1 + - id: page_size + type: u2be + - id: slot_size + type: int31 + - id: number_of_shards + type: u2be + growth_rate: + seq: + - id: numerator + type: z + - id: denominator + type: z + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + issuance_ratio_final_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_final_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_weights: + seq: + - id: base_total_issued_per_minute + type: id_020__psparisc__mutez + - id: baking_reward_fixed_portion_weight + type: int31 + - id: baking_reward_bonus_weight + type: int31 + - id: attesting_reward_weight + type: int31 + - id: seed_nonce_revelation_tip_weight + type: int31 + - id: vdf_revelation_tip_weight + type: int31 + minimal_participation_ratio: + seq: + - id: numerator + type: u2be + - id: denominator + type: u2be + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + public_key: + seq: + - id: public_key_tag + type: u1 + enum: public_key_tag + - id: ed25519 + size: 32 + if: (public_key_tag == public_key_tag::ed25519) + - id: secp256k1 + size: 33 + if: (public_key_tag == public_key_tag::secp256k1) + - id: p256 + size: 33 + if: (public_key_tag == public_key_tag::p256) + - id: bls + size: 48 + if: (public_key_tag == public_key_tag::bls) + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + public_key_known: + seq: + - id: public_key_known_field0 + type: public_key + doc: ! 'A Ed25519, Secp256k1, or P256 public key + + + signature__public_key' + - id: public_key_known_field1 + type: id_020__psparisc__mutez + doc: id_020__psparisc__mutez + public_key_known_with_consensus_key: + seq: + - id: public_key_known_with_consensus_key_field0 + type: public_key + doc: ! 'A Ed25519, Secp256k1, or P256 public key + + + signature__public_key' + - id: public_key_known_with_consensus_key_field1 + type: id_020__psparisc__mutez + doc: id_020__psparisc__mutez + - id: public_key_known_with_consensus_key_field2 + type: public_key + doc: ! 'A Ed25519, Secp256k1, or P256 public key + + + signature__public_key' + public_key_known_with_delegate: + seq: + - id: public_key_known_with_delegate_field0 + type: public_key + doc: ! 'A Ed25519, Secp256k1, or P256 public key + + + signature__public_key' + - id: public_key_known_with_delegate_field1 + type: id_020__psparisc__mutez + doc: id_020__psparisc__mutez + - id: public_key_known_with_delegate_field2 + type: public_key_hash + doc: ! 'A Ed25519, Secp256k1, P256, or BLS public key hash + + + signature__public_key_hash' + public_key_unknown: + seq: + - id: public_key_unknown_field0 + type: public_key_hash + doc: ! 'A Ed25519, Secp256k1, P256, or BLS public key hash + + + signature__public_key_hash' + - id: public_key_unknown_field1 + type: id_020__psparisc__mutez + doc: id_020__psparisc__mutez + public_key_unknown_with_delegate: + seq: + - id: public_key_unknown_with_delegate_field0 + type: public_key_hash + doc: ! 'A Ed25519, Secp256k1, P256, or BLS public key hash + + + signature__public_key_hash' + - id: public_key_unknown_with_delegate_field1 + type: id_020__psparisc__mutez + doc: id_020__psparisc__mutez + - id: public_key_unknown_with_delegate_field2 + type: public_key_hash + doc: ! 'A Ed25519, Secp256k1, P256, or BLS public key hash + + + signature__public_key_hash' + radius_dz: + seq: + - id: numerator + type: z + - id: denominator + type: z + smart_rollup_reveal_activation_level: + seq: + - id: raw_data + type: s4be + - id: metadata + type: s4be + - id: dal_page + type: s4be + - id: dal_parameters + type: s4be + - id: dal_attested_slots_validity_lag + type: int31 + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + bootstrap_accounts_elt_tag: + 0: public_key_known + 1: public_key_unknown + 2: public_key_known_with_delegate + 3: public_key_unknown_with_delegate + 4: public_key_known_with_consensus_key + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + public_key_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + pvm_kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv +seq: +- id: bootstrap_accounts + type: bootstrap_accounts_0 +- id: bootstrap_contracts + type: bootstrap_contracts_0 +- id: bootstrap_smart_rollups + type: bootstrap_smart_rollups_0 +- id: commitments + type: commitments_0 +- id: security_deposit_ramp_up_cycles_tag + type: u1 + enum: bool +- id: security_deposit_ramp_up_cycles + type: int31 + if: (security_deposit_ramp_up_cycles_tag == bool::true) +- id: no_reward_cycles_tag + type: u1 + enum: bool +- id: no_reward_cycles + type: int31 + if: (no_reward_cycles_tag == bool::true) +- id: consensus_rights_delay + type: u1 +- id: blocks_preservation_cycles + type: u1 +- id: delegate_parameters_activation_delay + type: u1 +- id: blocks_per_cycle + type: s4be +- id: blocks_per_commitment + type: s4be +- id: nonce_revelation_threshold + type: s4be +- id: cycles_per_voting_period + type: s4be +- id: hard_gas_limit_per_operation + type: z +- id: hard_gas_limit_per_block + type: z +- id: proof_of_work_threshold + type: s8be +- id: minimal_stake + type: id_020__psparisc__mutez +- id: minimal_frozen_stake + type: id_020__psparisc__mutez +- id: vdf_difficulty + type: s8be +- id: origination_size + type: int31 +- id: issuance_weights + type: issuance_weights +- id: cost_per_byte + type: id_020__psparisc__mutez +- id: hard_storage_limit_per_operation + type: z +- id: quorum_min + type: s4be +- id: quorum_max + type: s4be +- id: min_proposal_quorum + type: s4be +- id: liquidity_baking_subsidy + type: id_020__psparisc__mutez +- id: liquidity_baking_toggle_ema_threshold + type: s4be +- id: max_operations_time_to_live + type: s2be +- id: minimal_block_delay + type: s8be +- id: delay_increment_per_round + type: s8be +- id: consensus_committee_size + type: int31 +- id: consensus_threshold + type: int31 +- id: minimal_participation_ratio + type: minimal_participation_ratio +- id: limit_of_delegation_over_baking + type: u1 +- id: percentage_of_frozen_deposits_slashed_per_double_baking + type: u2be +- id: percentage_of_frozen_deposits_slashed_per_double_attestation + type: u2be +- id: max_slashing_per_block + type: u2be +- id: max_slashing_threshold + type: int31 +- id: testnet_dictator_tag + type: u1 + enum: bool +- id: testnet_dictator + type: public_key_hash + if: (testnet_dictator_tag == bool::true) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash +- id: initial_seed_tag + type: u1 + enum: bool +- id: initial_seed + size: 32 + if: (initial_seed_tag == bool::true) +- id: cache_script_size + type: int31 +- id: cache_stake_distribution_cycles + type: s1 +- id: cache_sampler_state_cycles + type: s1 +- id: dal_parametric + type: dal_parametric +- id: smart_rollup_arith_pvm_enable + type: u1 + enum: bool +- id: smart_rollup_origination_size + type: int31 +- id: smart_rollup_challenge_window_in_blocks + type: int31 +- id: smart_rollup_stake_amount + type: id_020__psparisc__mutez +- id: smart_rollup_commitment_period_in_blocks + type: int31 +- id: smart_rollup_max_lookahead_in_blocks + type: s4be +- id: smart_rollup_max_active_outbox_levels + type: s4be +- id: smart_rollup_max_outbox_messages_per_level + type: int31 +- id: smart_rollup_number_of_sections_in_dissection + type: u1 +- id: smart_rollup_timeout_period_in_blocks + type: int31 +- id: smart_rollup_max_number_of_cemented_commitments + type: int31 +- id: smart_rollup_max_number_of_parallel_games + type: int31 +- id: smart_rollup_reveal_activation_level + type: smart_rollup_reveal_activation_level +- id: smart_rollup_private_enable + type: u1 + enum: bool +- id: smart_rollup_riscv_pvm_enable + type: u1 + enum: bool +- id: zk_rollup_enable + type: u1 + enum: bool +- id: zk_rollup_origination_size + type: int31 +- id: zk_rollup_min_pending_to_process + type: int31 +- id: zk_rollup_max_ticket_payload_size + type: int31 +- id: global_limit_of_staking_over_baking + type: u1 +- id: edge_of_staking_over_delegation + type: u1 +- id: adaptive_issuance_launch_ema_threshold + type: s4be +- id: adaptive_rewards_params + type: adaptive_rewards_params +- id: adaptive_issuance_activation_vote_enable + type: u1 + enum: bool +- id: autostaking_enable + type: u1 + enum: bool +- id: adaptive_issuance_force_activation + type: u1 + enum: bool +- id: ns_enable + type: u1 + enum: bool +- id: direct_ticket_spending_enable + type: u1 + enum: bool diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__period.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__period.ksy new file mode 100644 index 000000000000..15b7ab355aa5 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__period.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__period + endian: be +doc: ! 'Encoding id: 020-PsParisC.period' +seq: +- id: id_020__psparisc__period + type: s8be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__raw_level.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__raw_level.ksy new file mode 100644 index 000000000000..1e4919f98dbe --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__raw_level.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__raw_level + endian: be +doc: ! 'Encoding id: 020-PsParisC.raw_level' +seq: +- id: id_020__psparisc__raw_level + type: s4be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__receipt__balance_updates.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__receipt__balance_updates.ksy new file mode 100644 index 000000000000..ba2fd5c4f32a --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__receipt__balance_updates.ksy @@ -0,0 +1,355 @@ +meta: + id: id_020__psparisc__receipt__balance_updates + endian: be +doc: ! 'Encoding id: 020-PsParisC.receipt.balance_updates' +types: + commitments: + seq: + - id: committer + size: 20 + - id: id_020__psparisc__operation_metadata__alpha__tez_balance_update + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + contract: + seq: + - id: contract + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: id_020__psparisc__operation_metadata__alpha__tez_balance_update + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + deposits: + seq: + - id: staker + type: id_020__psparisc__frozen_staker + doc: ! >- + frozen_staker: Abstract notion of staker used in operation receipts for frozen + deposits, either a single staker or all the stakers delegating to some delegate. + - id: id_020__psparisc__operation_metadata__alpha__tez_balance_update + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + frozen_bonds: + seq: + - id: contract + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: bond_id + type: id_020__psparisc__bond_id + - id: id_020__psparisc__operation_metadata__alpha__tez_balance_update + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + id_020__psparisc__bond_id: + seq: + - id: id_020__psparisc__bond_id_tag + type: u1 + enum: id_020__psparisc__bond_id_tag + - id: smart_rollup_bond_id + size: 20 + if: (id_020__psparisc__bond_id_tag == id_020__psparisc__bond_id_tag::smart_rollup_bond_id) + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__frozen_staker: + seq: + - id: id_020__psparisc__frozen_staker_tag + type: u1 + enum: id_020__psparisc__frozen_staker_tag + - id: single + type: single + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::single) + - id: shared + type: public_key_hash + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::shared) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: baker + type: public_key_hash + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::baker) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: baker_edge + type: public_key_hash + if: (id_020__psparisc__frozen_staker_tag == id_020__psparisc__frozen_staker_tag::baker_edge) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + id_020__psparisc__operation_metadata__alpha__balance_and_update: + seq: + - id: id_020__psparisc__operation_metadata__alpha__balance_and_update_tag + type: u1 + enum: id_020__psparisc__operation_metadata__alpha__balance_and_update_tag + - id: contract + type: contract + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::contract) + - id: block_fees + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::block_fees) + - id: deposits + type: deposits + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::deposits) + - id: nonce_revelation_rewards + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::nonce_revelation_rewards) + - id: attesting_rewards + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::attesting_rewards) + - id: baking_rewards + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::baking_rewards) + - id: baking_bonuses + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::baking_bonuses) + - id: storage_fees + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::storage_fees) + - id: double_signing_punishments + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::double_signing_punishments) + - id: lost_attesting_rewards + type: lost_attesting_rewards + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::lost_attesting_rewards) + - id: liquidity_baking_subsidies + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::liquidity_baking_subsidies) + - id: burned + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::burned) + - id: commitments + type: commitments + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::commitments) + - id: bootstrap + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::bootstrap) + - id: invoice + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::invoice) + - id: initial_commitments + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::initial_commitments) + - id: minted + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::minted) + - id: frozen_bonds + type: frozen_bonds + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::frozen_bonds) + - id: smart_rollup_refutation_punishments + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::smart_rollup_refutation_punishments) + - id: smart_rollup_refutation_rewards + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::smart_rollup_refutation_rewards) + - id: unstaked_deposits + type: unstaked_deposits + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::unstaked_deposits) + - id: staking_delegator_numerator + type: staking_delegator_numerator + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::staking_delegator_numerator) + - id: staking_delegate_denominator + type: staking_delegate_denominator + if: (id_020__psparisc__operation_metadata__alpha__balance_and_update_tag == + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag::staking_delegate_denominator) + id_020__psparisc__operation_metadata__alpha__balance_updates: + seq: + - id: id_020__psparisc__operation_metadata__alpha__balance_updates_entries + type: id_020__psparisc__operation_metadata__alpha__balance_updates_entries + repeat: eos + id_020__psparisc__operation_metadata__alpha__balance_updates_0: + seq: + - id: len_id_020__psparisc__operation_metadata__alpha__balance_updates + type: u4be + valid: + max: 1073741823 + - id: id_020__psparisc__operation_metadata__alpha__balance_updates + type: id_020__psparisc__operation_metadata__alpha__balance_updates + size: len_id_020__psparisc__operation_metadata__alpha__balance_updates + id_020__psparisc__operation_metadata__alpha__balance_updates_entries: + seq: + - id: id_020__psparisc__operation_metadata__alpha__balance_and_update + type: id_020__psparisc__operation_metadata__alpha__balance_and_update + - id: id_020__psparisc__operation_metadata__alpha__update_origin + type: id_020__psparisc__operation_metadata__alpha__update_origin + id_020__psparisc__operation_metadata__alpha__staking_abstract_quantity: + seq: + - id: change + type: s8be + id_020__psparisc__operation_metadata__alpha__tez_balance_update: + seq: + - id: change + type: s8be + id_020__psparisc__operation_metadata__alpha__update_origin: + seq: + - id: id_020__psparisc__operation_metadata__alpha__update_origin_tag + type: u1 + enum: id_020__psparisc__operation_metadata__alpha__update_origin_tag + - id: delayed_operation + size: 32 + if: (id_020__psparisc__operation_metadata__alpha__update_origin_tag == id_020__psparisc__operation_metadata__alpha__update_origin_tag::delayed_operation) + id_020__psparisc__staker: + seq: + - id: id_020__psparisc__staker_tag + type: u1 + enum: id_020__psparisc__staker_tag + - id: single + type: single + if: (id_020__psparisc__staker_tag == id_020__psparisc__staker_tag::single) + - id: shared + type: public_key_hash + if: (id_020__psparisc__staker_tag == id_020__psparisc__staker_tag::shared) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + lost_attesting_rewards: + seq: + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: participation + type: u1 + enum: bool + - id: revelation + type: u1 + enum: bool + - id: id_020__psparisc__operation_metadata__alpha__tez_balance_update + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + single: + seq: + - id: contract + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + staking_delegate_denominator: + seq: + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: id_020__psparisc__operation_metadata__alpha__staking_abstract_quantity + type: id_020__psparisc__operation_metadata__alpha__staking_abstract_quantity + staking_delegator_numerator: + seq: + - id: delegator + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: id_020__psparisc__operation_metadata__alpha__staking_abstract_quantity + type: id_020__psparisc__operation_metadata__alpha__staking_abstract_quantity + unstaked_deposits: + seq: + - id: staker + type: id_020__psparisc__staker + doc: ! >- + unstaked_frozen_staker: Abstract notion of staker used in operation receipts + for unstaked frozen deposits, either a single staker or all the stakers delegating + to some delegate. + - id: cycle + type: s4be + - id: id_020__psparisc__operation_metadata__alpha__tez_balance_update + type: id_020__psparisc__operation_metadata__alpha__tez_balance_update +enums: + bool: + 0: false + 255: true + id_020__psparisc__bond_id_tag: + 1: smart_rollup_bond_id + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__frozen_staker_tag: + 0: single + 1: shared + 2: baker + 3: baker_edge + id_020__psparisc__operation_metadata__alpha__balance_and_update_tag: + 0: contract + 2: block_fees + 4: deposits + 5: nonce_revelation_rewards + 7: attesting_rewards + 8: baking_rewards + 9: baking_bonuses + 11: storage_fees + 12: double_signing_punishments + 13: lost_attesting_rewards + 14: liquidity_baking_subsidies + 15: burned + 16: commitments + 17: bootstrap + 18: invoice + 19: initial_commitments + 20: minted + 21: frozen_bonds + 24: smart_rollup_refutation_punishments + 25: smart_rollup_refutation_rewards + 26: unstaked_deposits + 27: staking_delegator_numerator + 28: staking_delegate_denominator + id_020__psparisc__operation_metadata__alpha__update_origin_tag: + 0: block_application + 1: protocol_migration + 2: subsidy + 3: simulation + 4: delayed_operation + id_020__psparisc__staker_tag: + 0: single + 1: shared + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__operation_metadata__alpha__balance_updates + type: id_020__psparisc__operation_metadata__alpha__balance_updates_0 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__script.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__script.ksy new file mode 100644 index 000000000000..cc39bf86f994 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__script.ksy @@ -0,0 +1,22 @@ +meta: + id: id_020__psparisc__script + endian: be +doc: ! 'Encoding id: 020-PsParisC.script' +types: + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + id_020__psparisc__scripted__contracts: + seq: + - id: code + type: bytes_dyn_uint30 + - id: storage + type: bytes_dyn_uint30 +seq: +- id: id_020__psparisc__scripted__contracts + type: id_020__psparisc__scripted__contracts diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__script__expr.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__expr.ksy new file mode 100644 index 000000000000..475880c16553 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__expr.ksy @@ -0,0 +1,584 @@ +meta: + id: id_020__psparisc__script__expr + endian: be +doc: ! 'Encoding id: 020-PsParisC.script.expr' +types: + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes +seq: +- id: micheline__020__psparisc__michelson_v1__expression + type: micheline__020__psparisc__michelson_v1__expression diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__script__lazy_expr.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__lazy_expr.ksy new file mode 100644 index 000000000000..7b647f0e5c50 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__lazy_expr.ksy @@ -0,0 +1,16 @@ +meta: + id: id_020__psparisc__script__lazy_expr + endian: be +doc: ! 'Encoding id: 020-PsParisC.script.lazy_expr' +types: + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 +seq: +- id: id_020__psparisc__script__lazy_expr + type: bytes_dyn_uint30 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__script__loc.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__loc.ksy new file mode 100644 index 000000000000..dacece974872 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__loc.ksy @@ -0,0 +1,23 @@ +meta: + id: id_020__psparisc__script__loc + endian: be +doc: ! 'Encoding id: 020-PsParisC.script.loc' +types: + int31: + seq: + - id: int31 + type: s4be + valid: + min: -1073741824 + max: 1073741823 + micheline__location: + seq: + - id: micheline__location + type: int31 +seq: +- id: micheline__location + type: micheline__location + doc: ! >- + Canonical location in a Micheline expression: The location of a node in a Micheline + expression tree in prefix order, with zero being the root and adding one for every + basic node, sequence and primitive application. diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__script__prim.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__prim.ksy new file mode 100644 index 000000000000..9e36b24dc58c --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__script__prim.ksy @@ -0,0 +1,411 @@ +meta: + id: id_020__psparisc__script__prim + endian: be +doc: ! 'Encoding id: 020-PsParisC.script.prim' +types: + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives +enums: + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket +seq: +- id: id_020__psparisc__michelson__v1__primitives + type: id_020__psparisc__michelson__v1__primitives diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__seed.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__seed.ksy new file mode 100644 index 000000000000..d23a0ea81906 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__seed.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__seed + endian: be +doc: ! 'Encoding id: 020-PsParisC.seed' +seq: +- id: id_020__psparisc__seed + size: 32 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__address.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__address.ksy new file mode 100644 index 000000000000..8524d55d8415 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__address.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__smart_rollup__address + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.address' +seq: +- id: smart_rollup_address + size: 20 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__commmitment.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__commmitment.ksy new file mode 100644 index 000000000000..8066507d352a --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__commmitment.ksy @@ -0,0 +1,13 @@ +meta: + id: id_020__psparisc__smart_rollup__commmitment + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.commmitment' +seq: +- id: compressed_state + size: 32 +- id: inbox_level + type: s4be +- id: predecessor + size: 32 +- id: number_of_ticks + type: s8be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__game.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__game.ksy new file mode 100644 index 000000000000..ca69d340e492 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__game.ksy @@ -0,0 +1,218 @@ +meta: + id: id_020__psparisc__smart_rollup__game + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.game' +types: + agreed_start_chunk: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + attested: + seq: + - id: attested_tag + type: u1 + enum: attested_tag + - id: v0 + type: v0 + if: (attested_tag == attested_tag::v0) + back_pointers: + seq: + - id: back_pointers_entries + type: back_pointers_entries + repeat: eos + back_pointers_0: + seq: + - id: len_back_pointers + type: u4be + valid: + max: 1073741823 + - id: back_pointers + type: back_pointers + size: len_back_pointers + back_pointers_1: + seq: + - id: back_pointers_entries + type: back_pointers_entries_0 + repeat: eos + back_pointers_2: + seq: + - id: len_back_pointers + type: u4be + valid: + max: 1073741823 + - id: back_pointers + type: back_pointers_1 + size: len_back_pointers + back_pointers_entries: + seq: + - id: smart_rollup_inbox_hash + size: 32 + back_pointers_entries_0: + seq: + - id: dal_skip_list_pointer + size: 32 + content: + seq: + - id: hash + size: 32 + - id: level + type: s4be + content_0: + seq: + - id: content_tag + type: u1 + enum: content_tag + - id: unattested + type: unattested + if: (content_tag == content_tag::unattested) + - id: attested + type: attested + if: (content_tag == content_tag::attested) + dal_snapshot: + seq: + - id: dal_snapshot_tag + type: u1 + enum: dal_snapshot_tag + - id: dal_skip_list_legacy + size: 57 + if: (dal_snapshot_tag == dal_snapshot_tag::dal_skip_list_legacy) + - id: dal_skip_list + type: skip_list + if: (dal_snapshot_tag == dal_snapshot_tag::dal_skip_list) + dissecting: + seq: + - id: dissection + type: dissection_0 + - id: default_number_of_sections + type: u1 + dissection: + seq: + - id: dissection_entries + type: dissection_entries + repeat: eos + dissection_0: + seq: + - id: len_dissection + type: u4be + valid: + max: 1073741823 + - id: dissection + type: dissection + size: len_dissection + dissection_entries: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + final_move: + seq: + - id: agreed_start_chunk + type: agreed_start_chunk + - id: refuted_stop_chunk + type: refuted_stop_chunk + game_state: + seq: + - id: game_state_tag + type: u1 + enum: game_state_tag + - id: dissecting + type: dissecting + if: (game_state_tag == game_state_tag::dissecting) + - id: final_move + type: final_move + if: (game_state_tag == game_state_tag::final_move) + inbox_snapshot: + seq: + - id: index + type: n + - id: content + type: content + - id: back_pointers + type: back_pointers_0 + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + refuted_stop_chunk: + seq: + - id: state_tag + type: u1 + enum: bool + - id: state + size: 32 + if: (state_tag == bool::true) + - id: tick + type: n + skip_list: + seq: + - id: index + type: n + - id: content + type: content_0 + - id: back_pointers + type: back_pointers_2 + unattested: + seq: + - id: level + type: s4be + - id: index + type: u1 + v0: + seq: + - id: level + type: s4be + - id: index + type: u1 + - id: commitment + size: 48 +enums: + attested_tag: + 0: v0 + bool: + 0: false + 255: true + content_tag: + 0: unattested + 1: attested + dal_snapshot_tag: + 0: dal_skip_list_legacy + 1: dal_skip_list + game_state_tag: + 0: dissecting + 1: final_move + turn_tag: + 0: alice + 1: bob +seq: +- id: turn + type: u1 + enum: turn_tag +- id: inbox_snapshot + type: inbox_snapshot +- id: dal_snapshot + type: dal_snapshot +- id: start_level + type: s4be +- id: inbox_level + type: s4be +- id: game_state + type: game_state diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox.ksy new file mode 100644 index 000000000000..2744768483d2 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox.ksy @@ -0,0 +1,54 @@ +meta: + id: id_020__psparisc__smart_rollup__inbox + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.inbox' +types: + back_pointers: + seq: + - id: back_pointers_entries + type: back_pointers_entries + repeat: eos + back_pointers_0: + seq: + - id: len_back_pointers + type: u4be + valid: + max: 1073741823 + - id: back_pointers + type: back_pointers + size: len_back_pointers + back_pointers_entries: + seq: + - id: smart_rollup_inbox_hash + size: 32 + content: + seq: + - id: hash + size: 32 + - id: level + type: s4be + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + old_levels_messages: + seq: + - id: index + type: n + - id: content + type: content + - id: back_pointers + type: back_pointers_0 +seq: +- id: level + type: s4be +- id: old_levels_messages + type: old_levels_messages diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox__message.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox__message.ksy new file mode 100644 index 000000000000..b844397e2e11 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__inbox__message.ksy @@ -0,0 +1,655 @@ +meta: + id: id_020__psparisc__smart_rollup__inbox__message + endian: be + imports: + - timestamp__protocol +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.inbox.message' +types: + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + info_per_level: + seq: + - id: predecessor_timestamp + type: timestamp__protocol + - id: predecessor + size: 32 + internal: + seq: + - id: internal_tag + type: u1 + enum: internal_tag + - id: transfer + type: transfer + if: (internal_tag == internal_tag::transfer) + - id: info_per_level + type: info_per_level + if: (internal_tag == internal_tag::info_per_level) + - id: protocol_migration + type: bytes_dyn_uint30 + if: (internal_tag == internal_tag::protocol_migration) + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + transfer: + seq: + - id: payload + type: micheline__020__psparisc__michelson_v1__expression + - id: sender + size: 20 + - id: source + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: destination + size: 20 + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__smart_rollup__inbox__message_tag: + 0: internal + 1: external + internal_tag: + 0: transfer + 1: start_of_level + 2: end_of_level + 3: info_per_level + 4: protocol_migration + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__smart_rollup__inbox__message_tag + type: u1 + enum: id_020__psparisc__smart_rollup__inbox__message_tag +- id: internal + type: internal + if: (id_020__psparisc__smart_rollup__inbox__message_tag == id_020__psparisc__smart_rollup__inbox__message_tag::internal) +- id: external + size-eos: true + if: (id_020__psparisc__smart_rollup__inbox__message_tag == id_020__psparisc__smart_rollup__inbox__message_tag::external) diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__kind.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__kind.ksy new file mode 100644 index 000000000000..e0b3736c672a --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__kind.ksy @@ -0,0 +1,13 @@ +meta: + id: id_020__psparisc__smart_rollup__kind + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.kind' +enums: + id_020__psparisc__smart_rollup__kind: + 0: arith + 1: wasm_2_0_0 + 2: riscv +seq: +- id: id_020__psparisc__smart_rollup__kind + type: u1 + enum: id_020__psparisc__smart_rollup__kind diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__metadata.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__metadata.ksy new file mode 100644 index 000000000000..654b5d7cbb12 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__metadata.ksy @@ -0,0 +1,9 @@ +meta: + id: id_020__psparisc__smart_rollup__metadata + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.metadata' +seq: +- id: address + size: 20 +- id: origination_level + type: s4be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__outbox__message.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__outbox__message.ksy new file mode 100644 index 000000000000..09a0a8e62c51 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__outbox__message.ksy @@ -0,0 +1,719 @@ +meta: + id: id_020__psparisc__smart_rollup__outbox__message + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.outbox.message' +types: + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + transactions: + seq: + - id: transactions_entries + type: transactions_entries + repeat: eos + transactions_0: + seq: + - id: len_transactions + type: u4be + valid: + max: 1073741823 + - id: transactions + type: transactions + size: len_transactions + transactions_1: + seq: + - id: transactions_entries + type: transactions_entries_0 + repeat: eos + transactions_2: + seq: + - id: len_transactions + type: u4be + valid: + max: 1073741823 + - id: transactions + type: transactions_1 + size: len_transactions + transactions_entries: + seq: + - id: parameters + type: micheline__020__psparisc__michelson_v1__expression + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + transactions_entries_0: + seq: + - id: parameters + type: micheline__020__psparisc__michelson_v1__expression + - id: parameters_ty + type: micheline__020__psparisc__michelson_v1__expression + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + whitelist_update: + seq: + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + id_020__psparisc__smart_rollup__outbox__message_tag: + 0: atomic_transaction_batch + 1: atomic_transaction_batch_typed + 2: whitelist_update + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__smart_rollup__outbox__message_tag + type: u1 + enum: id_020__psparisc__smart_rollup__outbox__message_tag +- id: atomic_transaction_batch + type: transactions_0 + if: (id_020__psparisc__smart_rollup__outbox__message_tag == id_020__psparisc__smart_rollup__outbox__message_tag::atomic_transaction_batch) +- id: atomic_transaction_batch_typed + type: transactions_2 + if: (id_020__psparisc__smart_rollup__outbox__message_tag == id_020__psparisc__smart_rollup__outbox__message_tag::atomic_transaction_batch_typed) +- id: whitelist_update + type: whitelist_update + if: (id_020__psparisc__smart_rollup__outbox__message_tag == id_020__psparisc__smart_rollup__outbox__message_tag::whitelist_update) diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__output.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__output.ksy new file mode 100644 index 000000000000..e2f729964295 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__output.ksy @@ -0,0 +1,733 @@ +meta: + id: id_020__psparisc__smart_rollup__output + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.output' +types: + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + message: + seq: + - id: message_tag + type: u1 + enum: message_tag + - id: atomic_transaction_batch + type: transactions_0 + if: (message_tag == message_tag::atomic_transaction_batch) + - id: atomic_transaction_batch_typed + type: transactions_2 + if: (message_tag == message_tag::atomic_transaction_batch_typed) + - id: whitelist_update + type: whitelist_update + if: (message_tag == message_tag::whitelist_update) + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + transactions: + seq: + - id: transactions_entries + type: transactions_entries + repeat: eos + transactions_0: + seq: + - id: len_transactions + type: u4be + valid: + max: 1073741823 + - id: transactions + type: transactions + size: len_transactions + transactions_1: + seq: + - id: transactions_entries + type: transactions_entries_0 + repeat: eos + transactions_2: + seq: + - id: len_transactions + type: u4be + valid: + max: 1073741823 + - id: transactions + type: transactions_1 + size: len_transactions + transactions_entries: + seq: + - id: parameters + type: micheline__020__psparisc__michelson_v1__expression + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + transactions_entries_0: + seq: + - id: parameters + type: micheline__020__psparisc__michelson_v1__expression + - id: parameters_ty + type: micheline__020__psparisc__michelson_v1__expression + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + whitelist_update: + seq: + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + message_tag: + 0: atomic_transaction_batch + 1: atomic_transaction_batch_typed + 2: whitelist_update + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: outbox_level + type: s4be +- id: message_index + type: n +- id: message + type: message diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__proof.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__proof.ksy new file mode 100644 index 000000000000..d8d2ca45c733 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__proof.ksy @@ -0,0 +1,104 @@ +meta: + id: id_020__psparisc__smart_rollup__proof + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.proof' +types: + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + dal__page__proof: + seq: + - id: dal_page_id + type: dal_page_id + - id: dal_proof + type: bytes_dyn_uint30 + dal_page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be + inbox__proof: + seq: + - id: level + type: s4be + - id: message_counter + type: n + - id: serialized_proof + type: bytes_dyn_uint30 + input_proof: + seq: + - id: input_proof_tag + type: u1 + enum: input_proof_tag + - id: inbox__proof + type: inbox__proof + if: (input_proof_tag == input_proof_tag::inbox__proof) + - id: reveal__proof + type: reveal_proof + if: (input_proof_tag == input_proof_tag::reveal__proof) + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + raw_data: + seq: + - id: raw_data + size-eos: true + raw_data_0: + seq: + - id: len_raw_data + type: u2be + valid: + max: 4096 + - id: raw_data + type: raw_data + size: len_raw_data + reveal_proof: + seq: + - id: reveal_proof_tag + type: u1 + enum: reveal_proof_tag + - id: raw__data__proof + type: raw_data_0 + if: (reveal_proof_tag == reveal_proof_tag::raw__data__proof) + - id: dal__page__proof + type: dal__page__proof + if: (reveal_proof_tag == reveal_proof_tag::dal__page__proof) +enums: + bool: + 0: false + 255: true + input_proof_tag: + 0: inbox__proof + 1: reveal__proof + 2: first__input + reveal_proof_tag: + 0: raw__data__proof + 1: metadata__proof + 2: dal__page__proof + 3: dal__parameters__proof +seq: +- id: pvm_step + type: bytes_dyn_uint30 +- id: input_proof_tag + type: u1 + enum: bool +- id: input_proof + type: input_proof + if: (input_proof_tag == bool::true) diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__reveal.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__reveal.ksy new file mode 100644 index 000000000000..87d80360f49e --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__reveal.ksy @@ -0,0 +1,39 @@ +meta: + id: id_020__psparisc__smart_rollup__reveal + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.reveal' +types: + input_hash: + seq: + - id: input_hash_tag + type: u1 + enum: input_hash_tag + - id: reveal_data_hash_v0 + size: 32 + if: (input_hash_tag == input_hash_tag::reveal_data_hash_v0) + page_id: + seq: + - id: published_level + type: s4be + - id: slot_index + type: u1 + - id: page_index + type: s2be +enums: + id_020__psparisc__smart_rollup__reveal_tag: + 0: reveal_raw_data + 1: reveal_metadata + 2: request_dal_page + 3: reveal_dal_parameters + input_hash_tag: + 0: reveal_data_hash_v0 +seq: +- id: id_020__psparisc__smart_rollup__reveal_tag + type: u1 + enum: id_020__psparisc__smart_rollup__reveal_tag +- id: reveal_raw_data + type: input_hash + if: (id_020__psparisc__smart_rollup__reveal_tag == id_020__psparisc__smart_rollup__reveal_tag::reveal_raw_data) +- id: request_dal_page + type: page_id + if: (id_020__psparisc__smart_rollup__reveal_tag == id_020__psparisc__smart_rollup__reveal_tag::request_dal_page) diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__wasm_2_0_0__output__proof.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__wasm_2_0_0__output__proof.ksy new file mode 100644 index 000000000000..240502e4357c --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__wasm_2_0_0__output__proof.ksy @@ -0,0 +1,1183 @@ +meta: + id: id_020__psparisc__smart_rollup__wasm_2_0_0__output__proof + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.wasm_2_0_0.output.proof' +types: + args: + seq: + - id: args_entries + type: args_entries + repeat: eos + args_0: + seq: + - id: len_args + type: u4be + valid: + max: 1073741823 + - id: args + type: args + size: len_args + args_entries: + seq: + - id: args_elt + type: micheline__020__psparisc__michelson_v1__expression + bytes_dyn_uint30: + seq: + - id: len_bytes_dyn_uint30 + type: u4be + valid: + max: 1073741823 + - id: bytes_dyn_uint30 + size: len_bytes_dyn_uint30 + case_0: + seq: + - id: case_0_field0 + type: s2be + - id: case_0_field1 + size: 32 + doc: context_hash + - id: case_0_field2 + size: 32 + doc: context_hash + - id: case_0_field3 + type: tree_encoding + doc: tree_encoding + case_1: + seq: + - id: case_1_field0 + type: s2be + - id: case_1_field1 + size: 32 + doc: context_hash + - id: case_1_field2 + size: 32 + doc: context_hash + - id: case_1_field3 + type: tree_encoding + case_2: + seq: + - id: case_2_field0 + type: s2be + - id: case_2_field1 + size: 32 + doc: context_hash + - id: case_2_field2 + size: 32 + doc: context_hash + - id: case_2_field3 + type: tree_encoding + case_3: + seq: + - id: case_3_field0 + type: s2be + - id: case_3_field1 + size: 32 + doc: context_hash + - id: case_3_field2 + size: 32 + doc: context_hash + - id: case_3_field3 + type: tree_encoding + id_020__psparisc__contract_id__originated: + seq: + - id: id_020__psparisc__contract_id__originated_tag + type: u1 + enum: id_020__psparisc__contract_id__originated_tag + - id: originated + type: originated + if: (id_020__psparisc__contract_id__originated_tag == id_020__psparisc__contract_id__originated_tag::originated) + id_020__psparisc__michelson__v1__primitives: + seq: + - id: id_020__psparisc__michelson__v1__primitives + type: u1 + enum: id_020__psparisc__michelson__v1__primitives + inode: + seq: + - id: inode_field0 + type: u1 + - id: inode_field1 + type: inode_field1 + inode_0: + seq: + - id: inode_field0 + type: u2be + - id: inode_field1 + type: inode_field1_0 + inode_1: + seq: + - id: inode_field0 + type: s4be + - id: inode_field1 + type: inode_field1_0 + inode_2: + seq: + - id: inode_field0 + type: s8be + - id: inode_field1 + type: inode_field1_0 + inode_field1: + seq: + - id: inode_field1_field0 + type: inode_tree_3 + doc: inode_tree + - id: inode_field1_field1 + type: inode_tree + inode_field1_0: + seq: + - id: inode_field1_field0 + type: inode_tree + - id: inode_field1_field1 + type: inode_tree + inode_tree: + seq: + - id: inode_tree_field0 + type: u1 + - id: inode_tree_field1 + type: inode_tree_field1 + inode_tree_0: + seq: + - id: inode_tree_field0 + type: u2be + - id: inode_tree_field1 + type: inode_tree_field1 + inode_tree_1: + seq: + - id: inode_tree_field0 + type: s4be + - id: inode_tree_field1 + type: inode_tree_field1 + inode_tree_2: + seq: + - id: inode_tree_field0 + type: s8be + - id: inode_tree_field1 + type: inode_tree_field1 + inode_tree_3: + seq: + - id: inode_tree_tag + type: u1 + enum: inode_tree_tag + - id: inode_tree + type: inode_tree + if: (inode_tree_tag == inode_tree_tag::inode_tree) + - id: inode_tree + type: inode_tree_0 + if: (inode_tree_tag == inode_tree_tag::inode_tree) + - id: inode_tree + type: inode_tree_1 + if: (inode_tree_tag == inode_tree_tag::inode_tree) + - id: inode_tree + type: inode_tree_2 + if: (inode_tree_tag == inode_tree_tag::inode_tree) + - id: other_inode_trees + type: other_inode_trees_entries + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + type: other_inode_trees_entries + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + type: other_inode_trees_0 + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + size: 32 + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + type: other_inode_trees_1 + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + type: other_inode_trees_2 + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + type: other_inode_trees_3 + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + - id: other_inode_trees + type: other_inode_trees_4 + if: (inode_tree_tag == inode_tree_tag::other_inode_trees) + inode_tree_field1: + seq: + - id: inode_tree_field1_field0 + type: inode_tree + - id: inode_tree_field1_field1 + type: inode_tree + message: + seq: + - id: message_tag + type: u1 + enum: message_tag + - id: atomic_transaction_batch + type: transactions_0 + if: (message_tag == message_tag::atomic_transaction_batch) + - id: atomic_transaction_batch_typed + type: transactions_2 + if: (message_tag == message_tag::atomic_transaction_batch_typed) + - id: whitelist_update + type: whitelist_update + if: (message_tag == message_tag::whitelist_update) + micheline__020__psparisc__michelson_v1__expression: + seq: + - id: micheline__020__psparisc__michelson_v1__expression_tag + type: u1 + enum: micheline__020__psparisc__michelson_v1__expression_tag + - id: int + type: z + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::int) + - id: string + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::string) + - id: sequence + type: sequence_0 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::sequence) + - id: prim__no_args__no_annots + type: id_020__psparisc__michelson__v1__primitives + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__no_annots) + - id: prim__no_args__some_annots + type: prim__no_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__no_args__some_annots) + - id: prim__1_arg__no_annots + type: prim__1_arg__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__no_annots) + - id: prim__1_arg__some_annots + type: prim__1_arg__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__1_arg__some_annots) + - id: prim__2_args__no_annots + type: prim__2_args__no_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__no_annots) + - id: prim__2_args__some_annots + type: prim__2_args__some_annots + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__2_args__some_annots) + - id: prim__generic + type: prim__generic + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::prim__generic) + - id: bytes + type: bytes_dyn_uint30 + if: (micheline__020__psparisc__michelson_v1__expression_tag == micheline__020__psparisc__michelson_v1__expression_tag::bytes) + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + other_inode_trees: + seq: + - id: other_inode_trees_entries + type: other_inode_trees_entries + repeat: eos + other_inode_trees_0: + seq: + - id: len_other_inode_trees + type: u4be + valid: + max: 1073741823 + - id: other_inode_trees + type: other_inode_trees + size: len_other_inode_trees + other_inode_trees_1: + seq: + - id: other_inode_trees_field0 + type: u1 + - id: other_inode_trees_field1 + type: other_inode_trees_field1_0 + - id: other_inode_trees_field2 + type: inode_tree + other_inode_trees_2: + seq: + - id: other_inode_trees_field0 + type: u2be + - id: other_inode_trees_field1 + type: other_inode_trees_field1_0 + - id: other_inode_trees_field2 + type: inode_tree + other_inode_trees_3: + seq: + - id: other_inode_trees_field0 + type: s4be + - id: other_inode_trees_field1 + type: other_inode_trees_field1_0 + - id: other_inode_trees_field2 + type: inode_tree + other_inode_trees_4: + seq: + - id: other_inode_trees_field0 + type: s8be + - id: other_inode_trees_field1 + type: other_inode_trees_field1_0 + - id: other_inode_trees_field2 + type: inode_tree + other_inode_trees_elt_field0: + seq: + - id: other_inode_trees_elt_field0 + size-eos: true + other_inode_trees_elt_field0_0: + seq: + - id: len_other_inode_trees_elt_field0 + type: u1 + valid: + max: 255 + - id: other_inode_trees_elt_field0 + type: other_inode_trees_elt_field0 + size: len_other_inode_trees_elt_field0 + other_inode_trees_entries: + seq: + - id: other_inode_trees_elt_field0 + type: other_inode_trees_elt_field0_0 + - id: other_inode_trees_elt_field1 + type: tree_encoding + other_inode_trees_field1: + seq: + - id: other_inode_trees_field1 + size-eos: true + other_inode_trees_field1_0: + seq: + - id: len_other_inode_trees_field1 + type: u1 + valid: + max: 255 + - id: other_inode_trees_field1 + type: other_inode_trees_field1 + size: len_other_inode_trees_field1 + other_trees: + seq: + - id: other_trees_entries + type: other_trees_entries + repeat: eos + other_trees_0: + seq: + - id: len_other_trees + type: u4be + valid: + max: 1073741823 + - id: other_trees + type: other_trees + size: len_other_trees + other_trees_1: + seq: + - id: other_trees + size-eos: true + other_trees_2: + seq: + - id: len_other_trees + type: u1 + valid: + max: 255 + - id: other_trees + type: other_trees_1 + size: len_other_trees + other_trees_3: + seq: + - id: len_other_trees + type: u2be + valid: + max: 65535 + - id: other_trees + type: other_trees_1 + size: len_other_trees + other_trees_4: + seq: + - id: other_trees_field0 + type: u1 + - id: other_trees_field1 + type: other_trees_field1_0 + - id: other_trees_field2 + type: inode_tree + other_trees_5: + seq: + - id: other_trees_field0 + type: u2be + - id: other_trees_field1 + type: other_trees_field1_0 + - id: other_trees_field2 + type: inode_tree + other_trees_6: + seq: + - id: other_trees_field0 + type: s4be + - id: other_trees_field1 + type: other_trees_field1_0 + - id: other_trees_field2 + type: inode_tree + other_trees_7: + seq: + - id: other_trees_field0 + type: s8be + - id: other_trees_field1 + type: other_trees_field1_0 + - id: other_trees_field2 + type: inode_tree + other_trees_elt_field0: + seq: + - id: other_trees_elt_field0 + size-eos: true + other_trees_elt_field0_0: + seq: + - id: len_other_trees_elt_field0 + type: u1 + valid: + max: 255 + - id: other_trees_elt_field0 + type: other_trees_elt_field0 + size: len_other_trees_elt_field0 + other_trees_entries: + seq: + - id: other_trees_elt_field0 + type: other_trees_elt_field0_0 + - id: other_trees_elt_field1 + type: tree_encoding + other_trees_field1: + seq: + - id: other_trees_field1 + size-eos: true + other_trees_field1_0: + seq: + - id: len_other_trees_field1 + type: u1 + valid: + max: 255 + - id: other_trees_field1 + type: other_trees_field1 + size: len_other_trees_field1 + output_proof: + seq: + - id: output_proof_tag + type: u1 + enum: output_proof_tag + - id: case_0 + type: case_0 + if: (output_proof_tag == output_proof_tag::case_0) + - id: case_2 + type: case_2 + if: (output_proof_tag == output_proof_tag::case_2) + - id: case_1 + type: case_1 + if: (output_proof_tag == output_proof_tag::case_1) + - id: case_3 + type: case_3 + if: (output_proof_tag == output_proof_tag::case_3) + output_proof_output: + seq: + - id: outbox_level + type: s4be + - id: message_index + type: n + - id: message + type: message + prim__1_arg__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + prim__1_arg__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__2_args__no_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + prim__2_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: arg1 + type: micheline__020__psparisc__michelson_v1__expression + - id: arg2 + type: micheline__020__psparisc__michelson_v1__expression + - id: annots + type: bytes_dyn_uint30 + prim__generic: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: args + type: args_0 + - id: annots + type: bytes_dyn_uint30 + prim__no_args__some_annots: + seq: + - id: prim + type: id_020__psparisc__michelson__v1__primitives + - id: annots + type: bytes_dyn_uint30 + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + sequence: + seq: + - id: sequence_entries + type: sequence_entries + repeat: eos + sequence_0: + seq: + - id: len_sequence + type: u4be + valid: + max: 1073741823 + - id: sequence + type: sequence + size: len_sequence + sequence_entries: + seq: + - id: sequence_elt + type: micheline__020__psparisc__michelson_v1__expression + transactions: + seq: + - id: transactions_entries + type: transactions_entries + repeat: eos + transactions_0: + seq: + - id: len_transactions + type: u4be + valid: + max: 1073741823 + - id: transactions + type: transactions + size: len_transactions + transactions_1: + seq: + - id: transactions_entries + type: transactions_entries_0 + repeat: eos + transactions_2: + seq: + - id: len_transactions + type: u4be + valid: + max: 1073741823 + - id: transactions + type: transactions_1 + size: len_transactions + transactions_entries: + seq: + - id: parameters + type: micheline__020__psparisc__michelson_v1__expression + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + transactions_entries_0: + seq: + - id: parameters + type: micheline__020__psparisc__michelson_v1__expression + - id: parameters_ty + type: micheline__020__psparisc__michelson_v1__expression + - id: destination + type: id_020__psparisc__contract_id__originated + doc: ! >- + A contract handle -- originated account: A contract notation as given to an + RPC or inside scripts. Can be a base58 originated contract hash. + - id: entrypoint + type: bytes_dyn_uint30 + tree_encoding: + seq: + - id: tree_encoding_tag + type: u1 + enum: tree_encoding_tag + - id: inode + type: inode + if: (tree_encoding_tag == tree_encoding_tag::inode) + - id: inode + type: inode_0 + if: (tree_encoding_tag == tree_encoding_tag::inode) + - id: inode + type: inode_1 + if: (tree_encoding_tag == tree_encoding_tag::inode) + - id: inode + type: inode_2 + if: (tree_encoding_tag == tree_encoding_tag::inode) + - id: other_trees + type: other_trees_entries + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_entries + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_0 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_2 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_3 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: bytes_dyn_uint30 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + size: 32 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + size: 32 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_4 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_5 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_6 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + - id: other_trees + type: other_trees_7 + if: (tree_encoding_tag == tree_encoding_tag::other_trees) + whitelist: + seq: + - id: whitelist_entries + type: whitelist_entries + repeat: eos + whitelist_0: + seq: + - id: len_whitelist + type: u4be + valid: + max: 1073741823 + - id: whitelist + type: whitelist + size: len_whitelist + whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + whitelist_update: + seq: + - id: whitelist_tag + type: u1 + enum: bool + - id: whitelist + type: whitelist_0 + if: (whitelist_tag == bool::true) + z: + seq: + - id: has_tail + type: b1be + - id: sign + type: b1be + - id: payload + type: b6be + - id: tail + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + if: has_tail.as +enums: + bool: + 0: false + 255: true + id_020__psparisc__contract_id__originated_tag: + 1: originated + id_020__psparisc__michelson__v1__primitives: + 0: parameter + 1: storage + 2: code + 3: + id: false + doc: False + 4: + id: elt + doc: Elt + 5: + id: left + doc: Left + 6: + id: none + doc: None + 7: + id: pair_1 + doc: Pair + 8: + id: right + doc: Right + 9: + id: some_0 + doc: Some + 10: + id: true + doc: True + 11: + id: unit_1 + doc: Unit + 12: + id: pack + doc: PACK + 13: + id: unpack + doc: UNPACK + 14: + id: blake2b + doc: BLAKE2B + 15: + id: sha256 + doc: SHA256 + 16: + id: sha512 + doc: SHA512 + 17: + id: abs + doc: ABS + 18: + id: add + doc: ADD + 19: + id: amount + doc: AMOUNT + 20: + id: and + doc: AND + 21: + id: balance + doc: BALANCE + 22: + id: car + doc: CAR + 23: + id: cdr + doc: CDR + 24: + id: check_signature + doc: CHECK_SIGNATURE + 25: + id: compare + doc: COMPARE + 26: + id: concat + doc: CONCAT + 27: + id: cons + doc: CONS + 28: + id: create_account + doc: CREATE_ACCOUNT + 29: + id: create_contract + doc: CREATE_CONTRACT + 30: + id: implicit_account + doc: IMPLICIT_ACCOUNT + 31: + id: dip + doc: DIP + 32: + id: drop + doc: DROP + 33: + id: dup + doc: DUP + 34: + id: ediv + doc: EDIV + 35: + id: empty_map + doc: EMPTY_MAP + 36: + id: empty_set + doc: EMPTY_SET + 37: + id: eq + doc: EQ + 38: + id: exec + doc: EXEC + 39: + id: failwith + doc: FAILWITH + 40: + id: ge + doc: GE + 41: + id: get + doc: GET + 42: + id: gt + doc: GT + 43: + id: hash_key + doc: HASH_KEY + 44: + id: if + doc: IF + 45: + id: if_cons + doc: IF_CONS + 46: + id: if_left + doc: IF_LEFT + 47: + id: if_none + doc: IF_NONE + 48: + id: int_0 + doc: INT + 49: + id: lambda_0 + doc: LAMBDA + 50: + id: le + doc: LE + 51: + id: left_0 + doc: LEFT + 52: + id: loop + doc: LOOP + 53: + id: lsl + doc: LSL + 54: + id: lsr + doc: LSR + 55: + id: lt + doc: LT + 56: + id: map_0 + doc: MAP + 57: + id: mem + doc: MEM + 58: + id: mul + doc: MUL + 59: + id: neg + doc: NEG + 60: + id: neq + doc: NEQ + 61: + id: nil + doc: NIL + 62: + id: none_0 + doc: NONE + 63: + id: not + doc: NOT + 64: + id: now + doc: NOW + 65: + id: or_0 + doc: OR + 66: + id: pair_0 + doc: PAIR + 67: + id: push + doc: PUSH + 68: + id: right_0 + doc: RIGHT + 69: + id: size + doc: SIZE + 70: + id: some + doc: SOME + 71: + id: source + doc: SOURCE + 72: + id: sender + doc: SENDER + 73: + id: self + doc: SELF + 74: + id: steps_to_quota + doc: STEPS_TO_QUOTA + 75: + id: sub + doc: SUB + 76: + id: swap + doc: SWAP + 77: + id: transfer_tokens + doc: TRANSFER_TOKENS + 78: + id: set_delegate + doc: SET_DELEGATE + 79: + id: unit_0 + doc: UNIT + 80: + id: update + doc: UPDATE + 81: + id: xor + doc: XOR + 82: + id: iter + doc: ITER + 83: + id: loop_left + doc: LOOP_LEFT + 84: + id: address_0 + doc: ADDRESS + 85: + id: contract_0 + doc: CONTRACT + 86: + id: isnat + doc: ISNAT + 87: + id: cast + doc: CAST + 88: + id: rename + doc: RENAME + 89: bool + 90: contract + 91: int + 92: key + 93: key_hash + 94: lambda + 95: list + 96: map + 97: big_map + 98: nat + 99: option + 100: or + 101: pair + 102: set + 103: signature + 104: string + 105: bytes + 106: mutez + 107: timestamp + 108: unit + 109: operation + 110: address + 111: + id: slice + doc: SLICE + 112: + id: dig + doc: DIG + 113: + id: dug + doc: DUG + 114: + id: empty_big_map + doc: EMPTY_BIG_MAP + 115: + id: apply + doc: APPLY + 116: chain_id + 117: + id: chain_id_0 + doc: CHAIN_ID + 118: + id: level + doc: LEVEL + 119: + id: self_address + doc: SELF_ADDRESS + 120: never + 121: + id: never_0 + doc: NEVER + 122: + id: unpair + doc: UNPAIR + 123: + id: voting_power + doc: VOTING_POWER + 124: + id: total_voting_power + doc: TOTAL_VOTING_POWER + 125: + id: keccak + doc: KECCAK + 126: + id: sha3 + doc: SHA3 + 127: + id: pairing_check + doc: PAIRING_CHECK + 128: bls12_381_g1 + 129: bls12_381_g2 + 130: bls12_381_fr + 131: sapling_state + 132: sapling_transaction_deprecated + 133: + id: sapling_empty_state + doc: SAPLING_EMPTY_STATE + 134: + id: sapling_verify_update + doc: SAPLING_VERIFY_UPDATE + 135: ticket + 136: + id: ticket_deprecated + doc: TICKET_DEPRECATED + 137: + id: read_ticket + doc: READ_TICKET + 138: + id: split_ticket + doc: SPLIT_TICKET + 139: + id: join_tickets + doc: JOIN_TICKETS + 140: + id: get_and_update + doc: GET_AND_UPDATE + 141: chest + 142: chest_key + 143: + id: open_chest + doc: OPEN_CHEST + 144: + id: view_0 + doc: VIEW + 145: view + 146: constant + 147: + id: sub_mutez + doc: SUB_MUTEZ + 148: tx_rollup_l2_address + 149: + id: min_block_time + doc: MIN_BLOCK_TIME + 150: sapling_transaction + 151: + id: emit + doc: EMIT + 152: + id: lambda_rec_0 + doc: Lambda_rec + 153: + id: lambda_rec + doc: LAMBDA_REC + 154: + id: ticket_0 + doc: TICKET + 155: + id: bytes_0 + doc: BYTES + 156: + id: nat_0 + doc: NAT + 157: + id: ticket_1 + doc: Ticket + inode_tree_tag: + 0: inode_tree + 1: inode_tree + 2: inode_tree + 3: inode_tree + 128: other_inode_trees + 129: other_inode_trees + 130: other_inode_trees + 131: other_inode_trees + 192: other_inode_trees + 208: other_inode_trees + 209: other_inode_trees + 210: other_inode_trees + 211: other_inode_trees + 224: other_inode_trees + message_tag: + 0: atomic_transaction_batch + 1: atomic_transaction_batch_typed + 2: whitelist_update + micheline__020__psparisc__michelson_v1__expression_tag: + 0: int + 1: string + 2: sequence + 3: + id: prim__no_args__no_annots + doc: Primitive with no arguments and no annotations + 4: + id: prim__no_args__some_annots + doc: Primitive with no arguments and some annotations + 5: + id: prim__1_arg__no_annots + doc: Primitive with one argument and no annotations + 6: + id: prim__1_arg__some_annots + doc: Primitive with one argument and some annotations + 7: + id: prim__2_args__no_annots + doc: Primitive with two arguments and no annotations + 8: + id: prim__2_args__some_annots + doc: Primitive with two arguments and some annotations + 9: + id: prim__generic + doc: Generic primitive (any number of args with or without annotations) + 10: bytes + output_proof_tag: + 0: case_0 + 1: case_1 + 2: case_2 + 3: case_3 + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls + tree_encoding_tag: + 0: inode + 1: inode + 2: inode + 3: inode + 128: other_trees + 129: other_trees + 130: other_trees + 131: other_trees + 192: other_trees + 193: other_trees + 195: other_trees + 200: other_trees + 208: other_trees + 216: other_trees + 217: other_trees + 218: other_trees + 219: other_trees + 224: other_trees +seq: +- id: output_proof + type: output_proof +- id: output_proof_output + type: output_proof_output diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__whitelist.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__whitelist.ksy new file mode 100644 index 000000000000..5cad0e5ff7d5 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__smart_rollup__whitelist.ksy @@ -0,0 +1,46 @@ +meta: + id: id_020__psparisc__smart_rollup__whitelist + endian: be +doc: ! 'Encoding id: 020-PsParisC.smart_rollup.whitelist' +types: + id_020__psparisc__smart_rollup__whitelist: + seq: + - id: id_020__psparisc__smart_rollup__whitelist_entries + type: id_020__psparisc__smart_rollup__whitelist_entries + repeat: eos + id_020__psparisc__smart_rollup__whitelist_entries: + seq: + - id: signature__public_key_hash + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) +enums: + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: len_id_020__psparisc__smart_rollup__whitelist + type: u4be + valid: + max: 1073741823 +- id: id_020__psparisc__smart_rollup__whitelist + type: id_020__psparisc__smart_rollup__whitelist + size: len_id_020__psparisc__smart_rollup__whitelist diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__tez.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__tez.ksy new file mode 100644 index 000000000000..f0c7d379fe8c --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__tez.ksy @@ -0,0 +1,24 @@ +meta: + id: id_020__psparisc__tez + endian: be +doc: ! 'Encoding id: 020-PsParisC.tez' +types: + id_020__psparisc__mutez: + seq: + - id: id_020__psparisc__mutez + type: n + n: + seq: + - id: n + type: n_chunk + repeat: until + repeat-until: not (_.has_more).as + n_chunk: + seq: + - id: has_more + type: b1be + - id: payload + type: b7be +seq: +- id: id_020__psparisc__mutez + type: id_020__psparisc__mutez diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__timestamp.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__timestamp.ksy new file mode 100644 index 000000000000..dc1241497eff --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__timestamp.ksy @@ -0,0 +1,9 @@ +meta: + id: id_020__psparisc__timestamp + endian: be + imports: + - timestamp__protocol +doc: ! 'Encoding id: 020-PsParisC.timestamp' +seq: +- id: id_020__psparisc__timestamp + type: timestamp__protocol diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__unstaked_frozen_staker.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__unstaked_frozen_staker.ksy new file mode 100644 index 000000000000..905185a99f32 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__unstaked_frozen_staker.ksy @@ -0,0 +1,82 @@ +meta: + id: id_020__psparisc__unstaked_frozen_staker + endian: be +doc: ! 'Encoding id: 020-PsParisC.unstaked_frozen_staker' +types: + id_020__psparisc__contract_id: + seq: + - id: id_020__psparisc__contract_id_tag + type: u1 + enum: id_020__psparisc__contract_id_tag + - id: implicit + type: public_key_hash + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::implicit) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: originated + type: originated + if: (id_020__psparisc__contract_id_tag == id_020__psparisc__contract_id_tag::originated) + id_020__psparisc__staker: + seq: + - id: id_020__psparisc__staker_tag + type: u1 + enum: id_020__psparisc__staker_tag + - id: single + type: single + if: (id_020__psparisc__staker_tag == id_020__psparisc__staker_tag::single) + - id: shared + type: public_key_hash + if: (id_020__psparisc__staker_tag == id_020__psparisc__staker_tag::shared) + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + originated: + seq: + - id: contract_hash + size: 20 + - id: originated_padding + size: 1 + doc: This field is for padding, ignore + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) + single: + seq: + - id: contract + type: id_020__psparisc__contract_id + doc: ! >- + A contract handle: A contract notation as given to an RPC or inside scripts. + Can be a base58 implicit contract hash or a base58 originated contract hash. + - id: delegate + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash +enums: + id_020__psparisc__contract_id_tag: + 0: implicit + 1: originated + id_020__psparisc__staker_tag: + 0: single + 1: shared + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: id_020__psparisc__staker + type: id_020__psparisc__staker + doc: ! >- + unstaked_frozen_staker: Abstract notion of staker used in operation receipts for + unstaked frozen deposits, either a single staker or all the stakers delegating + to some delegate. diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballot.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballot.ksy new file mode 100644 index 000000000000..39511959f286 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballot.ksy @@ -0,0 +1,7 @@ +meta: + id: id_020__psparisc__vote__ballot + endian: be +doc: ! 'Encoding id: 020-PsParisC.vote.ballot' +seq: +- id: id_020__psparisc__vote__ballot + type: s1 diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballots.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballots.ksy new file mode 100644 index 000000000000..634a7c1d5beb --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__ballots.ksy @@ -0,0 +1,11 @@ +meta: + id: id_020__psparisc__vote__ballots + endian: be +doc: ! 'Encoding id: 020-PsParisC.vote.ballots' +seq: +- id: yay + type: s8be +- id: nay + type: s8be +- id: pass + type: s8be diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__listings.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__listings.ksy new file mode 100644 index 000000000000..dba9fb4622e6 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__vote__listings.ksy @@ -0,0 +1,48 @@ +meta: + id: id_020__psparisc__vote__listings + endian: be +doc: ! 'Encoding id: 020-PsParisC.vote.listings' +types: + id_020__psparisc__vote__listings: + seq: + - id: id_020__psparisc__vote__listings_entries + type: id_020__psparisc__vote__listings_entries + repeat: eos + id_020__psparisc__vote__listings_entries: + seq: + - id: pkh + type: public_key_hash + doc: A Ed25519, Secp256k1, P256, or BLS public key hash + - id: voting_power + type: s8be + public_key_hash: + seq: + - id: public_key_hash_tag + type: u1 + enum: public_key_hash_tag + - id: ed25519 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::ed25519) + - id: secp256k1 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::secp256k1) + - id: p256 + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::p256) + - id: bls + size: 20 + if: (public_key_hash_tag == public_key_hash_tag::bls) +enums: + public_key_hash_tag: + 0: ed25519 + 1: secp256k1 + 2: p256 + 3: bls +seq: +- id: len_id_020__psparisc__vote__listings + type: u4be + valid: + max: 1073741823 +- id: id_020__psparisc__vote__listings + type: id_020__psparisc__vote__listings + size: len_id_020__psparisc__vote__listings diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period.ksy new file mode 100644 index 000000000000..22b5e060d353 --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period.ksy @@ -0,0 +1,26 @@ +meta: + id: id_020__psparisc__voting_period + endian: be +doc: ! 'Encoding id: 020-PsParisC.voting_period' +enums: + kind_tag: + 0: proposal + 1: exploration + 2: cooldown + 3: promotion + 4: adoption +seq: +- id: index + type: s4be + doc: ! >- + The voting period's index. Starts at 0 with the first block of the Alpha family + of protocols. +- id: kind + type: u1 + enum: kind_tag + doc: One of the several kinds of periods in the voting procedure. +- id: start_position + type: s4be + doc: ! >- + The relative position of the first level of the period with respect to the first + level of the Alpha family of protocols. diff --git a/client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period__kind.ksy b/client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period__kind.ksy new file mode 100644 index 000000000000..1f1370e04a0a --- /dev/null +++ b/client-libs/kaitai-struct-files/files/id_020__psparisc__voting_period__kind.ksy @@ -0,0 +1,15 @@ +meta: + id: id_020__psparisc__voting_period__kind + endian: be +doc: ! 'Encoding id: 020-PsParisC.voting_period.kind' +enums: + id_020__psparisc__voting_period__kind_tag: + 0: proposal + 1: exploration + 2: cooldown + 3: promotion + 4: adoption +seq: +- id: id_020__psparisc__voting_period__kind_tag + type: u1 + enum: id_020__psparisc__voting_period__kind_tag -- GitLab From 4da712b83ba1e68deb00389ac93666f990dfd836 Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Wed, 12 Jun 2024 18:04:33 +0200 Subject: [PATCH 13/16] Test: Reset regression files --- ...sb- Regression test for L2 block hash.out} | 0 ...isc- Regression test for L2 block hash.out | 1 + .../runtime-dependency-tags.out | 2 + .../block_header.raw.sample.json | 11 + .../block_header.unsigned.sample.json | 19 + .../block_header/block_header.sample.json | 20 + .../big_map_diff-alloc.sample.json | 10 + .../big_map_diff-copy.sample.json | 5 + .../big_map_diff-remove.sample.json | 4 + .../big_map_diff-update.sample.json | 11 + .../contract/contract-implicit.sample.json | 1 + .../contract/contract-originated.sample.json | 1 + .../parisb/cycle/cycle-positive.sample.json | 1 + .../parisb/cycle/cycle-zero.sample.json | 1 + .../parisb/fitness/fitness.sample.json | 1 + .../gas.cost/gas.cost-positive.sample.json | 1 + .../parisb/gas.cost/gas.cost-zero.sample.json | 1 + .../parisb/gas/gas-positive.sample.json | 1 + .../parisb/gas/gas-unaccounted.sample.json | 1 + .../parisb/gas/gas-zero.sample.json | 1 + .../parisb/level/level.sample.json | 7 + .../parisb/nonce/nonce.sample.json | 1 + ...internal-delegation-withdrawal.sample.json | 5 + .../operation.internal-delegation.sample.json | 6 + ...operation.internal-origination.sample.json | 48 + ...ternal-transaction-to-implicit.sample.json | 7 + ...rnal-transaction-to-originated.sample.json | 13 + .../operation.raw/operation.raw.sample.json | 4 + ...tion.unsigned-activate-account.sample.json | 8 + ...operation.unsigned-attestation.sample.json | 12 + .../operation.unsigned-ballot.sample.json | 10 + ...unsigned-delegation-withdrawal.sample.json | 11 + .../operation.unsigned-delegation.sample.json | 12 + ...ed-double-attestation-evidence.sample.json | 30 + ...nsigned-double-baking-evidence.sample.json | 46 + ...double-preattestation-evidence.sample.json | 30 + ...operation.unsigned-origination.sample.json | 54 + ...ration.unsigned-preaatestation.sample.json | 12 + .../operation.unsigned-proposals.sample.json | 11 + .../operation.unsigned-reveal.sample.json | 12 + ...unsigned-seed-nonce-revelation.sample.json | 8 + ...signed-transaction-to-implicit.sample.json | 13 + ...gned-transaction-to-originated.sample.json | 19 + .../operation-activate-account.sample.json | 9 + .../operation-attestation.sample.json | 13 + .../operation/operation-ballot.sample.json | 11 + ...peration-delegation-withdrawal.sample.json | 12 + .../operation-delegation.sample.json | 13 + ...on-double-attestation-evidence.sample.json | 13 + ...eration-double-baking-evidence.sample.json | 39 + ...double-preattestation-evidence.sample.json | 31 + .../operation-origination.sample.json | 55 + .../operation-preattestation.sample.json | 13 + .../operation/operation-proposals.sample.json | 12 + .../operation/operation-reveal.sample.json | 13 + ...peration-seed-nonce-revelation.sample.json | 9 + ...ration-transaction-to-implicit.sample.json | 14 + ...tion-transaction-to-originated.sample.json | 20 + ...tion.unsigned-activate-account.sample.json | 8 + .../operation.unsigned-ballot.sample.json | 10 + ...unsigned-delegation-withdrawal.sample.json | 11 + .../operation.unsigned-delegation.sample.json | 12 + ...nsigned-double-baking-evidence.sample.json | 46 + ...ed-double-endorsement-evidence.sample.json | 30 + ...double-preendorsement-evidence.sample.json | 30 + ...operation.unsigned-endorsement.sample.json | 12 + ...operation.unsigned-origination.sample.json | 54 + ...ration.unsigned-preendorsement.sample.json | 12 + .../operation.unsigned-proposals.sample.json | 11 + .../operation.unsigned-reveal.sample.json | 12 + ...unsigned-seed-nonce-revelation.sample.json | 8 + ...signed-transaction-to-implicit.sample.json | 13 + ...gned-transaction-to-originated.sample.json | 19 + .../operation-activate-account.sample.json | 9 + .../operation-ballot.sample.json | 11 + ...peration-delegation-withdrawal.sample.json | 12 + .../operation-delegation.sample.json | 13 + ...eration-double-baking-evidence.sample.json | 39 + ...on-double-endorsement-evidence.sample.json | 31 + ...double-preendorsement-evidence.sample.json | 31 + .../operation-endorsement.sample.json | 13 + .../operation-origination.sample.json | 55 + .../operation-preendorsement.sample.json | 13 + .../operation-proposals.sample.json | 12 + .../operation-reveal.sample.json | 13 + ...peration-seed-nonce-revelation.sample.json | 9 + ...ration-transaction-to-implicit.sample.json | 14 + ...tion-transaction-to-originated.sample.json | 20 + .../parisb/period/period-positive.sample.json | 1 + .../parisb/period/period-zero.sample.json | 1 + .../raw_level/raw_level-positive.sample.json | 1 + .../raw_level/raw_level-zero.sample.json | 1 + ...ance_updates-contract-implicit.sample.json | 6 + ...ce_updates-contract-originated.sample.json | 6 + ...lance_updates-freezer-deposits.sample.json | 7 + ...t.balance_updates-freezer-fees.sample.json | 8 + ...pdates-freezer-legacy_deposits.sample.json | 8 + ...updates-freezer-legacy_rewards.sample.json | 8 + ...alance_updates-freezer-rewards.sample.json | 7 + ...es-migration-contract-implicit.sample.json | 6 + ...-migration-contract-originated.sample.json | 6 + .../parisb/roll/roll-positive.sample.json | 1 + .../parisb/roll/roll-zero.sample.json | 1 + .../parisb/seed/seed.sample.json | 1 + .../parisb/tez/tez-positive.sample.json | 1 + .../parisb/tez/tez-zero.sample.json | 1 + .../parisb/timestamp/timestamp.sample.json | 1 + .../vote.ballot/vote.ballot-nay.sample.json | 1 + .../vote.ballot/vote.ballot-pass.sample.json | 1 + .../vote.ballot/vote.ballot-yay.sample.json | 1 + .../vote.ballots/vote.ballots.sample.json | 5 + .../vote.listings/vote.listings.sample.json | 9 + ...ing_period.kind-promotion-vote.sample.json | 1 + .../voting_period.kind-proposal.sample.json | 1 + ...oting_period.kind-testing-vote.sample.json | 1 + .../voting_period.kind-testing.sample.json | 1 + .../voting_period-positive.sample.json | 5 + .../voting_period-zero.sample.json | 5 + .../block_header.raw.sample.json | 11 + .../block_header.unsigned.sample.json | 19 + .../block_header/block_header.sample.json | 20 + .../big_map_diff-alloc.sample.json | 10 + .../big_map_diff-copy.sample.json | 5 + .../big_map_diff-remove.sample.json | 4 + .../big_map_diff-update.sample.json | 11 + .../contract/contract-implicit.sample.json | 1 + .../contract/contract-originated.sample.json | 1 + .../parisc/cycle/cycle-positive.sample.json | 1 + .../parisc/cycle/cycle-zero.sample.json | 1 + .../parisc/fitness/fitness.sample.json | 1 + .../gas.cost/gas.cost-positive.sample.json | 1 + .../parisc/gas.cost/gas.cost-zero.sample.json | 1 + .../parisc/gas/gas-positive.sample.json | 1 + .../parisc/gas/gas-unaccounted.sample.json | 1 + .../parisc/gas/gas-zero.sample.json | 1 + .../parisc/level/level.sample.json | 7 + .../parisc/nonce/nonce.sample.json | 1 + ...internal-delegation-withdrawal.sample.json | 5 + .../operation.internal-delegation.sample.json | 6 + ...operation.internal-origination.sample.json | 48 + ...ternal-transaction-to-implicit.sample.json | 7 + ...rnal-transaction-to-originated.sample.json | 13 + .../operation.raw/operation.raw.sample.json | 4 + ...tion.unsigned-activate-account.sample.json | 8 + ...operation.unsigned-attestation.sample.json | 12 + .../operation.unsigned-ballot.sample.json | 10 + ...unsigned-delegation-withdrawal.sample.json | 11 + .../operation.unsigned-delegation.sample.json | 12 + ...ed-double-attestation-evidence.sample.json | 30 + ...nsigned-double-baking-evidence.sample.json | 46 + ...double-preattestation-evidence.sample.json | 30 + ...operation.unsigned-origination.sample.json | 54 + ...ration.unsigned-preaatestation.sample.json | 12 + .../operation.unsigned-proposals.sample.json | 11 + .../operation.unsigned-reveal.sample.json | 12 + ...unsigned-seed-nonce-revelation.sample.json | 8 + ...signed-transaction-to-implicit.sample.json | 13 + ...gned-transaction-to-originated.sample.json | 19 + .../operation-activate-account.sample.json | 9 + .../operation-attestation.sample.json | 13 + .../operation/operation-ballot.sample.json | 11 + ...peration-delegation-withdrawal.sample.json | 12 + .../operation-delegation.sample.json | 13 + ...on-double-attestation-evidence.sample.json | 13 + ...eration-double-baking-evidence.sample.json | 39 + ...double-preattestation-evidence.sample.json | 31 + .../operation-origination.sample.json | 55 + .../operation-preattestation.sample.json | 13 + .../operation/operation-proposals.sample.json | 12 + .../operation/operation-reveal.sample.json | 13 + ...peration-seed-nonce-revelation.sample.json | 9 + ...ration-transaction-to-implicit.sample.json | 14 + ...tion-transaction-to-originated.sample.json | 20 + ...tion.unsigned-activate-account.sample.json | 8 + .../operation.unsigned-ballot.sample.json | 10 + ...unsigned-delegation-withdrawal.sample.json | 11 + .../operation.unsigned-delegation.sample.json | 12 + ...nsigned-double-baking-evidence.sample.json | 46 + ...ed-double-endorsement-evidence.sample.json | 30 + ...double-preendorsement-evidence.sample.json | 30 + ...operation.unsigned-endorsement.sample.json | 12 + ...operation.unsigned-origination.sample.json | 54 + ...ration.unsigned-preendorsement.sample.json | 12 + .../operation.unsigned-proposals.sample.json | 11 + .../operation.unsigned-reveal.sample.json | 12 + ...unsigned-seed-nonce-revelation.sample.json | 8 + ...signed-transaction-to-implicit.sample.json | 13 + ...gned-transaction-to-originated.sample.json | 19 + .../operation-activate-account.sample.json | 9 + .../operation-ballot.sample.json | 11 + ...peration-delegation-withdrawal.sample.json | 12 + .../operation-delegation.sample.json | 13 + ...eration-double-baking-evidence.sample.json | 39 + ...on-double-endorsement-evidence.sample.json | 31 + ...double-preendorsement-evidence.sample.json | 31 + .../operation-endorsement.sample.json | 13 + .../operation-origination.sample.json | 55 + .../operation-preendorsement.sample.json | 13 + .../operation-proposals.sample.json | 12 + .../operation-reveal.sample.json | 13 + ...peration-seed-nonce-revelation.sample.json | 9 + ...ration-transaction-to-implicit.sample.json | 14 + ...tion-transaction-to-originated.sample.json | 20 + .../parisc/period/period-positive.sample.json | 1 + .../parisc/period/period-zero.sample.json | 1 + .../raw_level/raw_level-positive.sample.json | 1 + .../raw_level/raw_level-zero.sample.json | 1 + ...ance_updates-contract-implicit.sample.json | 6 + ...ce_updates-contract-originated.sample.json | 6 + ...lance_updates-freezer-deposits.sample.json | 7 + ...t.balance_updates-freezer-fees.sample.json | 8 + ...pdates-freezer-legacy_deposits.sample.json | 8 + ...updates-freezer-legacy_rewards.sample.json | 8 + ...alance_updates-freezer-rewards.sample.json | 7 + ...es-migration-contract-implicit.sample.json | 6 + ...-migration-contract-originated.sample.json | 6 + .../parisc/roll/roll-positive.sample.json | 1 + .../parisc/roll/roll-zero.sample.json | 1 + .../parisc/seed/seed.sample.json | 1 + .../parisc/tez/tez-positive.sample.json | 1 + .../parisc/tez/tez-zero.sample.json | 1 + .../parisc/timestamp/timestamp.sample.json | 1 + .../vote.ballot/vote.ballot-nay.sample.json | 1 + .../vote.ballot/vote.ballot-pass.sample.json | 1 + .../vote.ballot/vote.ballot-yay.sample.json | 1 + .../vote.ballots/vote.ballots.sample.json | 5 + .../vote.listings/vote.listings.sample.json | 9 + ...ing_period.kind-promotion-vote.sample.json | 1 + .../voting_period.kind-proposal.sample.json | 1 + ...oting_period.kind-testing-vote.sample.json | 1 + .../voting_period.kind-testing.sample.json | 1 + .../voting_period-positive.sample.json | 5 + .../voting_period-zero.sample.json | 5 + ...C regression tests- adaptive_issuance.out} | 0 ...ient) RPC regression tests- contracts.out} | 0 ...ient) RPC regression tests- delegates.out} | 0 ...client) RPC regression tests- mempool.out} | 0 ...) RPC regression tests- misc_protocol.out} | 0 ...e client) RPC regression tests- votes.out} | 0 ...C regression tests- adaptive_issuance.out} | 0 ...ight) RPC regression tests- contracts.out} | 0 ...ight) RPC regression tests- delegates.out} | 0 ...) RPC regression tests- misc_protocol.out} | 0 ...de light) RPC regression tests- votes.out} | 0 ...C regression tests- adaptive_issuance.out} | 0 ...roxy) RPC regression tests- contracts.out} | 0 ...roxy) RPC regression tests- delegates.out} | 0 ... proxy) RPC regression tests- mempool.out} | 0 ...) RPC regression tests- misc_protocol.out} | 0 ...de proxy) RPC regression tests- votes.out} | 0 ...C regression tests- adaptive_issuance.out} | 0 ..._dir) RPC regression tests- contracts.out} | 0 ..._dir) RPC regression tests- delegates.out} | 0 ...) RPC regression tests- misc_protocol.out} | 0 ...data_dir) RPC regression tests- votes.out} | 0 ...C regression tests- adaptive_issuance.out} | 0 ..._rpc) RPC regression tests- contracts.out} | 0 ..._rpc) RPC regression tests- delegates.out} | 0 ...) RPC regression tests- misc_protocol.out} | 0 ...rver_rpc) RPC regression tests- votes.out} | 0 ...PC regression tests- adaptive_issuance.out | 66 + ...lient) RPC regression tests- contracts.out | 553 + ...lient) RPC regression tests- delegates.out | 102 + ... client) RPC regression tests- mempool.out | 570 + ...t) RPC regression tests- misc_protocol.out | 137 + ...de client) RPC regression tests- votes.out | 78 + ...PC regression tests- adaptive_issuance.out | 66 + ...light) RPC regression tests- contracts.out | 553 + ...light) RPC regression tests- delegates.out | 102 + ...t) RPC regression tests- misc_protocol.out | 137 + ...ode light) RPC regression tests- votes.out | 78 + ...PC regression tests- adaptive_issuance.out | 66 + ...proxy) RPC regression tests- contracts.out | 553 + ...proxy) RPC regression tests- delegates.out | 102 + ...e proxy) RPC regression tests- mempool.out | 570 + ...y) RPC regression tests- misc_protocol.out | 137 + ...ode proxy) RPC regression tests- votes.out | 78 + ...PC regression tests- adaptive_issuance.out | 67 + ...a_dir) RPC regression tests- contracts.out | 553 + ...a_dir) RPC regression tests- delegates.out | 102 + ...r) RPC regression tests- misc_protocol.out | 137 + ..._data_dir) RPC regression tests- votes.out | 78 + ...PC regression tests- adaptive_issuance.out | 67 + ...r_rpc) RPC regression tests- contracts.out | 553 + ...r_rpc) RPC regression tests- delegates.out | 102 + ...c) RPC regression tests- misc_protocol.out | 137 + ...erver_rpc) RPC regression tests- votes.out | 78 + ... rewards.out => Parisb- Baker rewards.out} | 0 .../baker_test.ml/Parisc- Baker rewards.out | 133 + ...- delegate - consensus - destination).out} | 0 ... delegate - consensus -- destination).out} | 0 ...- delegate - consensus - destination).out} | 0 ... delegate - consensus -- destination).out} | 0 ...isb- Test register with consensus key.out} | 0 ...set consensus key - baker is delegate.out} | 0 ...consensus key - baker is not delegate.out} | 0 ... - delegate - consensus - destination).out | 143 + ...- delegate - consensus -- destination).out | 143 + ...-- delegate - consensus - destination).out | 143 + ...- delegate - consensus -- destination).out | 143 + ...risc- Test register with consensus key.out | 90 + ... set consensus key - baker is delegate.out | 73 + ... consensus key - baker is not delegate.out | 73 + ...add-approve-transfer-remove liquidity.out} | 0 ...est trades.out => Parisb- Test trades.out} | 0 ... add-approve-transfer-remove liquidity.out | 416 + .../Parisc- Test trades.out | 446 + ...arisb- Macro expansion- macros-assert.out} | 0 ... Macro expansion- macros-assert_cmpeq.out} | 0 ... Macro expansion- macros-assert_cmpge.out} | 0 ... Macro expansion- macros-assert_cmpgt.out} | 0 ... Macro expansion- macros-assert_cmple.out} | 0 ... Macro expansion- macros-assert_cmplt.out} | 0 ...Macro expansion- macros-assert_cmpneq.out} | 0 ...sb- Macro expansion- macros-assert_eq.out} | 0 ...sb- Macro expansion- macros-assert_ge.out} | 0 ...sb- Macro expansion- macros-assert_gt.out} | 0 ...sb- Macro expansion- macros-assert_le.out} | 0 ...sb- Macro expansion- macros-assert_lt.out} | 0 ...b- Macro expansion- macros-assert_neq.out} | 0 ...cro expansion- macros-big_map_get_add.out} | 0 ...- Macro expansion- macros-big_map_mem.out} | 0 ...b- Macro expansion- macros-build_list.out} | 0 ...Macro expansion- macros-carn_and_cdrn.out} | 0 ...risb- Macro expansion- macros-compare.out} | 0 ...Macro expansion- macros-compare_bytes.out} | 0 ... Parisb- Macro expansion- macros-fail.out} | 0 ...sb- Macro expansion- macros-guestbook.out} | 0 ...o expansion- macros-macro_annotations.out} | 0 ... Macro expansion- macros-map_caddaadr.out} | 0 ...- Macro expansion- macros-max_in_list.out} | 0 ...> Parisb- Macro expansion- macros-min.out} | 0 ...b- Macro expansion- macros-pair_macro.out} | 0 ... Macro expansion- macros-set_caddaadr.out} | 0 ...Macro expansion- macros-take_my_money.out} | 0 ... Macro expansion- macros-unpair_macro.out} | 0 ...Parisc- Macro expansion- macros-assert.out | 8 + ...- Macro expansion- macros-assert_cmpeq.out | 11 + ...- Macro expansion- macros-assert_cmpge.out | 11 + ...- Macro expansion- macros-assert_cmpgt.out | 11 + ...- Macro expansion- macros-assert_cmple.out | 11 + ...- Macro expansion- macros-assert_cmplt.out | 11 + ... Macro expansion- macros-assert_cmpneq.out | 11 + ...isc- Macro expansion- macros-assert_eq.out | 12 + ...isc- Macro expansion- macros-assert_ge.out | 12 + ...isc- Macro expansion- macros-assert_gt.out | 12 + ...isc- Macro expansion- macros-assert_le.out | 12 + ...isc- Macro expansion- macros-assert_lt.out | 12 + ...sc- Macro expansion- macros-assert_neq.out | 12 + ...acro expansion- macros-big_map_get_add.out | 22 + ...c- Macro expansion- macros-big_map_mem.out | 13 + ...sc- Macro expansion- macros-build_list.out | 23 + ... Macro expansion- macros-carn_and_cdrn.out | 28 + ...arisc- Macro expansion- macros-compare.out | 21 + ... Macro expansion- macros-compare_bytes.out | 21 + .../Parisc- Macro expansion- macros-fail.out | 2 + ...isc- Macro expansion- macros-guestbook.out | 17 + ...ro expansion- macros-macro_annotations.out | 12 + ...- Macro expansion- macros-map_caddaadr.out | 39 + ...c- Macro expansion- macros-max_in_list.out | 16 + .../Parisc- Macro expansion- macros-min.out | 12 + ...sc- Macro expansion- macros-pair_macro.out | 17 + ...- Macro expansion- macros-set_caddaadr.out | 32 + ... Macro expansion- macros-take_my_money.out | 13 + ...- Macro expansion- macros-unpair_macro.out | 19 + ...ain opcodes- test_big_map_origination.out} | 0 ... onchain opcodes- test_contract_fails.out} | 0 ... Contract onchain opcodes- test_level.out} | 0 ...b- Contract onchain opcodes- test_now.out} | 0 ...- Contract onchain opcodes- test_self.out} | 0 ...Contract onchain opcodes- test_sender.out} | 0 ...ct onchain opcodes- test_set_delegate.out} | 0 ... Contract onchain opcodes- test_slice.out} | 0 ...Contract onchain opcodes- test_source.out} | 0 ...act onchain opcodes- test_split_bytes.out} | 0 ...ct onchain opcodes- test_split_string.out} | 0 ...act onchain opcodes- test_store_input.out} | 0 ...st_trace_origination_compare_big_type.out} | 0 ...t_trace_origination_compare_big_type2.out} | 0 ...onchain opcodes- test_transfer_amount.out} | 0 ...onchain opcodes- test_transfer_tokens.out} | 0 ...hain opcodes- test_big_map_origination.out | 148 + ...t onchain opcodes- test_contract_fails.out | 70 + ...- Contract onchain opcodes- test_level.out | 113 + ...sc- Contract onchain opcodes- test_now.out | 77 + ...c- Contract onchain opcodes- test_self.out | 77 + ... Contract onchain opcodes- test_sender.out | 170 + ...act onchain opcodes- test_set_delegate.out | 118 + ...- Contract onchain opcodes- test_slice.out | 461 + ... Contract onchain opcodes- test_source.out | 170 + ...ract onchain opcodes- test_split_bytes.out | 142 + ...act onchain opcodes- test_split_string.out | 142 + ...ract onchain opcodes- test_store_input.out | 116 + ...est_trace_origination_compare_big_type.out | 89 + ...st_trace_origination_compare_big_type2.out | 93 + ... onchain opcodes- test_transfer_amount.out | 83 + ... onchain opcodes- test_transfer_tokens.out | 228 + ...bs--storage125992234--input254251340-.out} | 0 ...bs--storage125992234--input420401245-.out} | 0 ...bs--storage125992234--input680650890-.out} | 0 ...dd--storage125992234--input125992234-.out} | 0 ...fr--storage921624073--input322109491-.out} | 0 ...fr--storage921624073--input461261325-.out} | 0 ...fr--storage921624073--input530006774-.out} | 0 ...fr--storage921624073--input712570300-.out} | 0 ...mp--storage921624073--input249636002-.out} | 0 ...mp--storage921624073--input267363182-.out} | 0 ...mp--storage921624073--input438561129-.out} | 0 ...ta--storage921624073--input249636002-.out} | 0 ...ta--storage921624073--input307538219-.out} | 0 ...ta--storage921624073--input373737581-.out} | 0 ...ss--storage921624073--input117475800-.out} | 0 ...nd--storage921624073--input106930123-.out} | 0 ...nd--storage921624073--input181204719-.out} | 0 ...nd--storage921624073--input223774825-.out} | 0 ...nd--storage921624073--input908807505-.out} | 0 ...ry--storage125992234--input125992234-.out} | 0 ...es--storage125992234--input125992234-.out} | 0 ..._1--storage570553153--input106930123-.out} | 0 ..._1--storage570553153--input181204719-.out} | 0 ..._1--storage570553153--input223774825-.out} | 0 ..._1--storage570553153--input908807505-.out} | 0 ...ce--storage492856247--input125992234-.out} | 0 ...at--storage495706788--input453441034-.out} | 0 ...nat--storage56274299--input453441034-.out} | 0 ...nat--storage56274299--input564400327-.out} | 0 ...nat--storage56274299--input654274102-.out} | 0 ...at--storage690637660--input453441034-.out} | 0 ...at--storage806237530--input453441034-.out} | 0 ...g--storage109689253--input1071610051-.out} | 0 ...ng--storage109689253--input700475845-.out} | 0 ...ng--storage109689253--input905318451-.out} | 0 ...ng--storage495706788--input700475845-.out} | 0 ...ng--storage915708427--input700475845-.out} | 0 ...ng--storage936682951--input905318451-.out} | 0 ...t_padded--storage921624073--input1259.out} | 0 ...at--storage921624073--input125992234-.out} | 0 ...t--storage680650890--input1043734173-.out} | 0 ...nt--storage680650890--input151303925-.out} | 0 ...nt--storage680650890--input520610122-.out} | 0 ...nt--storage680650890--input558805129-.out} | 0 ...ez--storage680650890--input229402968-.out} | 0 ...t--storage287336412--input1019409032-.out} | 0 ...nt--storage698210250--input949526473-.out} | 0 ...nt--storage739946440--input166435292-.out} | 0 ...nt--storage739946440--input583291483-.out} | 0 ...t--storage994282947--input1055524890-.out} | 0 ...nt--storage994282947--input453441034-.out} | 0 ...nt--storage994282947--input564400327-.out} | 0 ...nt--storage994282947--input585234482-.out} | 0 ...nt--storage994282947--input680650890-.out} | 0 ...nt--storage994282947--input701858804-.out} | 0 ...t--storage287336412--input1019409032-.out} | 0 ...at--storage698210250--input949526473-.out} | 0 ...at--storage739946440--input166435292-.out} | 0 ...at--storage739946440--input583291483-.out} | 0 ...t--storage994282947--input1055524890-.out} | 0 ...at--storage994282947--input453441034-.out} | 0 ...at--storage994282947--input564400327-.out} | 0 ...at--storage994282947--input680650890-.out} | 0 ...t--storage287336412--input1019409032-.out} | 0 ...nt--storage698210250--input949526473-.out} | 0 ...nt--storage739946440--input166435292-.out} | 0 ...nt--storage739946440--input583291483-.out} | 0 ...t--storage994282947--input1055524890-.out} | 0 ...nt--storage994282947--input453441034-.out} | 0 ...nt--storage994282947--input564400327-.out} | 0 ...nt--storage994282947--input585234482-.out} | 0 ...nt--storage994282947--input680650890-.out} | 0 ...nt--storage994282947--input701858804-.out} | 0 ...t--storage287336412--input1019409032-.out} | 0 ...at--storage698210250--input949526473-.out} | 0 ...at--storage739946440--input166435292-.out} | 0 ...at--storage739946440--input583291483-.out} | 0 ...t--storage994282947--input1055524890-.out} | 0 ...at--storage994282947--input453441034-.out} | 0 ...at--storage994282947--input564400327-.out} | 0 ...at--storage994282947--input680650890-.out} | 0 ...nt--storage125992234--input125992234-.out} | 0 ...at--storage125992234--input125992234-.out} | 0 ...ar--storage680650890--input783124233-.out} | 0 ...dr--storage680650890--input783124233-.out} | 0 ...re--storage109160754--input125992234-.out} | 0 ...re--storage921624073--input125992234-.out} | 0 ...re--storage981066851--input125992234-.out} | 0 ...mb--storage950292965--input125992234-.out} | 0 ...et--storage125992234--input186507116-.out} | 0 ...et--storage186507116--input125992234-.out} | 0 ...-2--storage921624073--input186507116-.out} | 0 ...re--storage125992234--input125992234-.out} | 0 ...ns--storage457300675--input281780712-.out} | 0 ...lo--storage457300675--input392583650-.out} | 0 ...lo--storage457300675--input457300675-.out} | 0 ...lo--storage457300675--input640104625-.out} | 0 ...es--storage457300675--input354091714-.out} | 0 ...es--storage457300675--input441061063-.out} | 0 ...es--storage457300675--input457300675-.out} | 0 ...ist--storage79230375--input264787654-.out} | 0 ...ist--storage79230375--input316676251-.out} | 0 ...ist--storage79230375--input457300675-.out} | 0 ...ns--storage457300675--input798141440-.out} | 0 ...ns--storage581876226--input166122047-.out} | 0 ...ns--storage793461282--input781487591-.out} | 0 ...ll--storage921624073--input315650912-.out} | 0 ...all--storage921624073--input51111414-.out} | 0 ...ll--storage921624073--input545734274-.out} | 0 ...ll--storage921624073--input772794967-.out} | 0 ...ll--storage921624073--input917967660-.out} | 0 ...ll--storage921624073--input964818218-.out} | 0 ...ct--storage125992234--input117475800-.out} | 0 ...ct--storage921624073--input125992234-.out} | 0 ...s--storage492856247--input1011138251-.out} | 0 ...s--storage492856247--input1018564342-.out} | 0 ...s--storage492856247--input1031049988-.out} | 0 ...ps--storage492856247--input685590443-.out} | 0 ...eq--storage125992234--input246866101-.out} | 0 ..._eq--storage125992234--input26856104-.out} | 0 ...gn--storage680650890--input529388602-.out} | 0 ...p--storage1011138251--input590117173-.out} | 0 ...p--storage1011138251--input850887554-.out} | 0 ...pn--storage680650890--input529388602-.out} | 0 ...pn--storage680650890--input529388602-.out} | 0 ...gn--storage680650890--input529388602-.out} | 0 ...-n--storage125992234--input125992234-.out} | 0 ...iv--storage994417987--input247451205-.out} | 0 ...iv--storage994417987--input250545589-.out} | 0 ...div--storage994417987--input79625541-.out} | 0 ...ez--storage977883604--input147133089-.out} | 0 ...ez--storage977883604--input215785357-.out} | 0 ...ez--storage977883604--input389351431-.out} | 0 ...tez--storage977883604--input44513000-.out} | 0 ...ez--storage977883604--input635398196-.out} | 0 ...ez--storage977883604--input734264738-.out} | 0 ...ez--storage977883604--input993071382-.out} | 0 ...it--storage125992234--input125992234-.out} | 0 ...ap--storage457300675--input125992234-.out} | 0 ...at--storage398998998--input246262487-.out} | 0 ...cat--storage398998998--input79230375-.out} | 0 ...st--storage492856247--input478406404-.out} | 0 ...st--storage492856247--input962874972-.out} | 0 ...p--storage1026405794--input329240220-.out} | 0 ...ap--storage382368661--input329240220-.out} | 0 ...ap--storage496578814--input329240220-.out} | 0 ...ap--storage496578814--input507231566-.out} | 0 ...ap--storage547821324--input329240220-.out} | 0 ...ap--storage796012494--input156280093-.out} | 0 ...ap--storage796012494--input228164856-.out} | 0 ...ue--storage139236239--input329240220-.out} | 0 ...lue--storage139236239--input79230375-.out} | 0 ...ue--storage329396864--input156280093-.out} | 0 ...y--storage921624073--input1040351577-.out} | 0 ...ey--storage921624073--input153350004-.out} | 0 ...ring--storage151303925--input3431716-.out} | 0 ...ng--storage151303925--input535018041-.out} | 0 ...if--storage921624073--input570553153-.out} | 0 ...if--storage921624073--input954397288-.out} | 0 ...me--storage398998998--input288201633-.out} | 0 ...me--storage398998998--input921624073-.out} | 0 ...nt--storage921624073--input453441034-.out} | 0 ...nt--storage921624073--input535454136-.out} | 0 ...nt--storage921624073--input680650890-.out} | 0 ...k--storage921624073--input1008262038-.out} | 0 ...ight--storage4177631--input202098045-.out} | 0 ...right--storage4177631--input44576556-.out} | 0 ...el--storage492856247--input125992234-.out} | 0 ...at--storage717096222--input457300675-.out} | 0 ...at--storage717096222--input546523343-.out} | 0 ...es--storage149262694--input220724351-.out} | 0 ...es--storage149262694--input457300675-.out} | 0 ...tes--storage65410082--input457300675-.out} | 0 ...es--storage726220441--input972761363-.out} | 0 ...id--storage528921618--input264787654-.out} | 0 ...id--storage528921618--input457300675-.out} | 0 ...id--storage528921618--input656499821-.out} | 0 ...ap--storage528921618--input264787654-.out} | 0 ...ap--storage528921618--input457300675-.out} | 0 ...ap--storage528921618--input656499821-.out} | 0 ...er--storage680650890--input568817463-.out} | 0 ...er--storage680650890--input737923774-.out} | 0 ...ck--storage907453363--input457300675-.out} | 0 ...ck--storage907453363--input648737279-.out} | 0 ...ck--storage907453363--input908379154-.out} | 0 ...ze--storage492856247--input403499055-.out} | 0 ...ze--storage492856247--input457300675-.out} | 0 ...ze--storage492856247--input469078912-.out} | 0 ...ze--storage492856247--input802622031-.out} | 0 ...ft--storage528921618--input457300675-.out} | 0 ...ft--storage528921618--input851203613-.out} | 0 ...es--storage125992234--input125992234-.out} | 0 ...es--storage125992234--input125992234-.out} | 0 ...d--storage457300675--input1027566226-.out} | 0 ...id--storage457300675--input276660554-.out} | 0 ...id--storage457300675--input599923743-.out} | 0 ...r--storage1011138251--input403579222-.out} | 0 ...r--storage1011138251--input532072758-.out} | 0 ...ap--storage457300675--input798141440-.out} | 0 ...ap--storage794999348--input152441147-.out} | 0 ...map--storage88008216--input798141440-.out} | 0 ...at--storage495706788--input453441034-.out} | 0 ...nat--storage56274299--input453441034-.out} | 0 ...nat--storage56274299--input564400327-.out} | 0 ...nat--storage56274299--input654274102-.out} | 0 ...at--storage690637660--input453441034-.out} | 0 ...at--storage806237530--input453441034-.out} | 0 ...g--storage109689253--input1071610051-.out} | 0 ...ng--storage109689253--input700475845-.out} | 0 ...ng--storage109689253--input905318451-.out} | 0 ...ng--storage495706788--input700475845-.out} | 0 ...ng--storage915708427--input700475845-.out} | 0 ...ng--storage936682951--input905318451-.out} | 0 ...ize--storage492856247--input15265129-.out} | 0 ...ze--storage492856247--input158311065-.out} | 0 ...ze--storage492856247--input456982702-.out} | 0 ...ze--storage492856247--input457300675-.out} | 0 ...ul--storage125992234--input125992234-.out} | 0 ...fr--storage151303925--input216277421-.out} | 0 ...fr--storage287799761--input485842614-.out} | 0 ...g--storage680650890--input1067298059-.out} | 0 ...eg--storage680650890--input380029349-.out} | 0 ...eg--storage680650890--input563503226-.out} | 0 ...eg--storage680650890--input788662499-.out} | 0 ...eg--storage680650890--input972832189-.out} | 0 ...one--storage11179311--input125992234-.out} | 0 ...ot--storage921624073--input570553153-.out} | 0 ...ot--storage921624073--input954397288-.out} | 0 ...y--storage921624073--input1051197453-.out} | 0 ...ry--storage921624073--input123939249-.out} | 0 ...ary--storage921624073--input24243730-.out} | 0 ...ry--storage921624073--input518945720-.out} | 0 ...ry--storage921624073--input788662499-.out} | 0 ...ry--storage921624073--input906118781-.out} | 0 ...ry--storage921624073--input921874253-.out} | 0 ...ry--storage921624073--input972832189-.out} | 0 ...es--storage125992234--input125992234-.out} | 0 ...or--storage921624073--input106930123-.out} | 0 ...or--storage921624073--input181204719-.out} | 0 ...or--storage921624073--input223774825-.out} | 0 ...or--storage921624073--input908807505-.out} | 0 ...y--storage921624073--input1056991424-.out} | 0 ...ry--storage921624073--input375993021-.out} | 0 ...ry--storage921624073--input673240563-.out} | 0 ...ry--storage921624073--input747448890-.out} | 0 ...ry--storage921624073--input832403787-.out} | 0 ...ry--storage921624073--input858098961-.out} | 0 ...es--storage125992234--input125992234-.out} | 0 ...ev--storage125992234--input305844558-.out} | 0 ...ev--storage125992234--input646365167-.out} | 0 ...y--storage125992234--input1028781121-.out} | 0 ...ty--storage125992234--input802670583-.out} | 0 ...id--storage921624073--input106930123-.out} | 0 ...id--storage921624073--input181204719-.out} | 0 ...id--storage921624073--input223774825-.out} | 0 ...id--storage921624073--input908807505-.out} | 0 ...c--storage256947135--input1050356042-.out} | 0 ..._2--storage197120858--input179371027-.out} | 0 ...nt--storage921624073--input125992234-.out} | 0 ...se--storage528921618--input457300675-.out} | 0 ...se--storage528921618--input851203613-.out} | 0 ...op--storage528921618--input457300675-.out} | 0 ...op--storage528921618--input851203613-.out} | 0 ...te--storage457300675--input125992234-.out} | 0 ...ss--storage125992234--input125992234-.out} | 0 ...nt--storage125992234--input125992234-.out} | 0 ...nt--storage125992234--input289072903-.out} | 0 ...ar--storage224747103--input620760059-.out} | 0 ...ar--storage224747103--input717096222-.out} | 0 ...car--storage224747103--input79230375-.out} | 0 ...dr--storage205576101--input654274102-.out} | 0 ...dr--storage224747103--input453441034-.out} | 0 ...dr--storage611418174--input967284912-.out} | 0 ...id--storage457300675--input264787654-.out} | 0 ...id--storage457300675--input457300675-.out} | 0 ...id--storage457300675--input989507347-.out} | 0 ...er--storage492856247--input457300675-.out} | 0 ...er--storage492856247--input701684511-.out} | 0 ...er--storage492856247--input802622031-.out} | 0 ...ber--storage495706788--input33757838-.out} | 0 ...ber--storage550087893--input79230375-.out} | 0 ...ber--storage605111220--input33757838-.out} | 0 ...ze--storage492856247--input403499055-.out} | 0 ...ze--storage492856247--input457300675-.out} | 0 ...ze--storage492856247--input469078912-.out} | 0 ...ze--storage492856247--input802622031-.out} | 0 ...3--storage921624073--input1008262038-.out} | 0 ...ts--storage921624073--input115382786-.out} | 0 ...ts--storage921624073--input271566295-.out} | 0 ...ts--storage921624073--input340971987-.out} | 0 ...ts--storage921624073--input374168553-.out} | 0 ...ts--storage921624073--input413621582-.out} | 0 ...ts--storage921624073--input424849461-.out} | 0 ...ts--storage921624073--input485030042-.out} | 0 ...ts--storage921624073--input705767726-.out} | 0 ...ts--storage921624073--input769385932-.out} | 0 ...ts--storage921624073--input913715337-.out} | 0 ...ice--storage351480851--input65907686-.out} | 0 ...ce--storage364922380--input198821575-.out} | 0 ...ce--storage364922380--input359592843-.out} | 0 ...ce--storage364922380--input551316239-.out} | 0 ...ce--storage364922380--input722749044-.out} | 0 ...ce--storage364922380--input839234860-.out} | 0 ...ce--storage364922380--input919180079-.out} | 0 ...ce--storage921624073--input551316239-.out} | 0 ...es--storage229749865--input198821575-.out} | 0 ...es--storage229749865--input462551352-.out} | 0 ...es--storage229749865--input489157380-.out} | 0 ...es--storage229749865--input551316239-.out} | 0 ...es--storage229749865--input669330759-.out} | 0 ...es--storage229749865--input743596105-.out} | 0 ...es--storage229749865--input839234860-.out} | 0 ...tes--storage504917929--input65907686-.out} | 0 ...es--storage921624073--input462551352-.out} | 0 ...d--storage921624073--input1016369050-.out} | 0 ..._id--storage921624073--input93477117-.out} | 0 ...ta--storage492856247--input249636002-.out} | 0 ...ta--storage492856247--input307538219-.out} | 0 ...ta--storage492856247--input831449542-.out} | 0 ...ub--storage921624073--input706350605-.out} | 0 ...ub--storage921624073--input856198194-.out} | 0 ...mb--storage680650890--input394061083-.out} | 0 ...ir--storage125992234--input125992234-.out} | 0 ...--storage1011138251--input1040351577-.out} | 0 ...r--storage921624073--input1058477720-.out} | 0 ...r--storage921624073--input1073176155-.out} | 0 ...or--storage921624073--input246594902-.out} | 0 ...or--storage921624073--input506603577-.out} | 0 ...or--storage921624073--input576248088-.out} | 0 ...or--storage921624073--input612012282-.out} | 0 ...or--storage921624073--input617591686-.out} | 0 ...or--storage921624073--input639311176-.out} | 0 ...or--storage921624073--input688315180-.out} | 0 ...or--storage921624073--input967929605-.out} | 0 ...es--storage125992234--input125992234-.out} | 0 ...risb- test Michelson opcodes- BALANCE.out} | 0 ...Parisb- test Michelson opcodes- LEVEL.out} | 0 ...> Parisb- test Michelson opcodes- NOW.out} | 0 ...ichelson opcodes- arithmetic_overflow.out} | 0 ...ichelson opcodes- big_map_contract_io.out} | 0 ...st Michelson opcodes- check_signature.out} | 0 ...t Michelson opcodes- hash_consistency.out} | 0 ...ichelson opcodes- map_map_side_effect.out} | 0 ...- test Michelson opcodes- pack_unpack.out} | 0 ...abs--storage125992234--input254251340-.out | 38 + ...abs--storage125992234--input420401245-.out | 38 + ...abs--storage125992234--input680650890-.out | 38 + ...add--storage125992234--input125992234-.out | 211 + ..._fr--storage921624073--input322109491-.out | 30 + ..._fr--storage921624073--input461261325-.out | 30 + ..._fr--storage921624073--input530006774-.out | 30 + ..._fr--storage921624073--input712570300-.out | 30 + ...amp--storage921624073--input249636002-.out | 36 + ...amp--storage921624073--input267363182-.out | 36 + ...amp--storage921624073--input438561129-.out | 36 + ...lta--storage921624073--input249636002-.out | 36 + ...lta--storage921624073--input307538219-.out | 36 + ...lta--storage921624073--input373737581-.out | 36 + ...ess--storage921624073--input117475800-.out | 23 + ...and--storage921624073--input106930123-.out | 31 + ...and--storage921624073--input181204719-.out | 31 + ...and--storage921624073--input223774825-.out | 31 + ...and--storage921624073--input908807505-.out | 31 + ...ary--storage125992234--input125992234-.out | 93 + ...tes--storage125992234--input125992234-.out | 75 + ...l_1--storage570553153--input106930123-.out | 24 + ...l_1--storage570553153--input181204719-.out | 24 + ...l_1--storage570553153--input223774825-.out | 24 + ...l_1--storage570553153--input908807505-.out | 24 + ...nce--storage492856247--input125992234-.out | 21 + ...nat--storage495706788--input453441034-.out | 42 + ..._nat--storage56274299--input453441034-.out | 44 + ..._nat--storage56274299--input564400327-.out | 44 + ..._nat--storage56274299--input654274102-.out | 44 + ...nat--storage690637660--input453441034-.out | 43 + ...nat--storage806237530--input453441034-.out | 43 + ...ng--storage109689253--input1071610051-.out | 44 + ...ing--storage109689253--input700475845-.out | 44 + ...ing--storage109689253--input905318451-.out | 44 + ...ing--storage495706788--input700475845-.out | 42 + ...ing--storage915708427--input700475845-.out | 43 + ...ing--storage936682951--input905318451-.out | 43 + ...ot_padded--storage921624073--input1259.out | 24 + ...nat--storage921624073--input125992234-.out | 24 + ...nt--storage680650890--input1043734173-.out | 21 + ...int--storage680650890--input151303925-.out | 21 + ...int--storage680650890--input520610122-.out | 22 + ...int--storage680650890--input558805129-.out | 22 + ...tez--storage680650890--input229402968-.out | 32 + ...nt--storage287336412--input1019409032-.out | 23 + ...int--storage698210250--input949526473-.out | 23 + ...int--storage739946440--input166435292-.out | 23 + ...int--storage739946440--input583291483-.out | 23 + ...nt--storage994282947--input1055524890-.out | 23 + ...int--storage994282947--input453441034-.out | 22 + ...int--storage994282947--input564400327-.out | 22 + ...int--storage994282947--input585234482-.out | 22 + ...int--storage994282947--input680650890-.out | 22 + ...int--storage994282947--input701858804-.out | 22 + ...at--storage287336412--input1019409032-.out | 23 + ...nat--storage698210250--input949526473-.out | 23 + ...nat--storage739946440--input166435292-.out | 23 + ...nat--storage739946440--input583291483-.out | 23 + ...at--storage994282947--input1055524890-.out | 23 + ...nat--storage994282947--input453441034-.out | 22 + ...nat--storage994282947--input564400327-.out | 22 + ...nat--storage994282947--input680650890-.out | 22 + ...nt--storage287336412--input1019409032-.out | 26 + ...int--storage698210250--input949526473-.out | 26 + ...int--storage739946440--input166435292-.out | 26 + ...int--storage739946440--input583291483-.out | 26 + ...nt--storage994282947--input1055524890-.out | 26 + ...int--storage994282947--input453441034-.out | 25 + ...int--storage994282947--input564400327-.out | 25 + ...int--storage994282947--input585234482-.out | 25 + ...int--storage994282947--input680650890-.out | 25 + ...int--storage994282947--input701858804-.out | 25 + ...at--storage287336412--input1019409032-.out | 26 + ...nat--storage698210250--input949526473-.out | 26 + ...nat--storage739946440--input166435292-.out | 26 + ...nat--storage739946440--input583291483-.out | 26 + ...at--storage994282947--input1055524890-.out | 26 + ...nat--storage994282947--input453441034-.out | 25 + ...nat--storage994282947--input564400327-.out | 25 + ...nat--storage994282947--input680650890-.out | 25 + ...int--storage125992234--input125992234-.out | 261 + ...nat--storage125992234--input125992234-.out | 126 + ...car--storage680650890--input783124233-.out | 21 + ...cdr--storage680650890--input783124233-.out | 21 + ...ore--storage109160754--input125992234-.out | 23 + ...ore--storage921624073--input125992234-.out | 23 + ...ore--storage981066851--input125992234-.out | 23 + ...omb--storage950292965--input125992234-.out | 30 + ...get--storage125992234--input186507116-.out | 123 + ...set--storage186507116--input125992234-.out | 39 + ...t-2--storage921624073--input186507116-.out | 36 + ...are--storage125992234--input125992234-.out | 398 + ...ons--storage457300675--input281780712-.out | 350 + ...llo--storage457300675--input392583650-.out | 35 + ...llo--storage457300675--input457300675-.out | 21 + ...llo--storage457300675--input640104625-.out | 28 + ...tes--storage457300675--input354091714-.out | 35 + ...tes--storage457300675--input441061063-.out | 28 + ...tes--storage457300675--input457300675-.out | 21 + ...list--storage79230375--input264787654-.out | 96 + ...list--storage79230375--input316676251-.out | 119 + ...list--storage79230375--input457300675-.out | 27 + ...ons--storage457300675--input798141440-.out | 22 + ...ons--storage581876226--input166122047-.out | 22 + ...ons--storage793461282--input781487591-.out | 22 + ...all--storage921624073--input315650912-.out | 166 + ..._all--storage921624073--input51111414-.out | 410 + ...all--storage921624073--input545734274-.out | 166 + ...all--storage921624073--input772794967-.out | 63 + ...all--storage921624073--input917967660-.out | 437 + ...all--storage921624073--input964818218-.out | 166 + ...act--storage125992234--input117475800-.out | 29 + ...act--storage921624073--input125992234-.out | 49 + ...ps--storage492856247--input1011138251-.out | 34 + ...ps--storage492856247--input1018564342-.out | 34 + ...ps--storage492856247--input1031049988-.out | 34 + ...mps--storage492856247--input685590443-.out | 34 + ..._eq--storage125992234--input246866101-.out | 1240 + ...g_eq--storage125992234--input26856104-.out | 1240 + ...ign--storage680650890--input529388602-.out | 61 + ...ip--storage1011138251--input590117173-.out | 36 + ...ip--storage1011138251--input850887554-.out | 36 + ...ipn--storage680650890--input529388602-.out | 68 + ...opn--storage680650890--input529388602-.out | 39 + ...ugn--storage680650890--input529388602-.out | 57 + ...p-n--storage125992234--input125992234-.out | 248 + ...div--storage994417987--input247451205-.out | 135 + ...div--storage994417987--input250545589-.out | 135 + ...ediv--storage994417987--input79625541-.out | 135 + ...tez--storage977883604--input147133089-.out | 37 + ...tez--storage977883604--input215785357-.out | 37 + ...tez--storage977883604--input389351431-.out | 37 + ...utez--storage977883604--input44513000-.out | 37 + ...tez--storage977883604--input635398196-.out | 37 + ...tez--storage977883604--input734264738-.out | 37 + ...tez--storage977883604--input993071382-.out | 37 + ...mit--storage125992234--input125992234-.out | 72 + ...map--storage457300675--input125992234-.out | 33 + ...cat--storage398998998--input246262487-.out | 48 + ...ncat--storage398998998--input79230375-.out | 48 + ...rst--storage492856247--input478406404-.out | 30 + ...rst--storage492856247--input962874972-.out | 30 + ...ap--storage1026405794--input329240220-.out | 34 + ...map--storage382368661--input329240220-.out | 34 + ...map--storage496578814--input329240220-.out | 34 + ...map--storage496578814--input507231566-.out | 34 + ...map--storage547821324--input329240220-.out | 34 + ...map--storage796012494--input156280093-.out | 34 + ...map--storage796012494--input228164856-.out | 34 + ...lue--storage139236239--input329240220-.out | 41 + ...alue--storage139236239--input79230375-.out | 41 + ...lue--storage329396864--input156280093-.out | 41 + ...ey--storage921624073--input1040351577-.out | 23 + ...key--storage921624073--input153350004-.out | 23 + ...tring--storage151303925--input3431716-.out | 23 + ...ing--storage151303925--input535018041-.out | 23 + ...-if--storage921624073--input570553153-.out | 27 + ...-if--storage921624073--input954397288-.out | 27 + ...ome--storage398998998--input288201633-.out | 23 + ...ome--storage398998998--input921624073-.out | 25 + ...int--storage921624073--input453441034-.out | 23 + ...int--storage921624073--input535454136-.out | 23 + ...int--storage921624073--input680650890-.out | 23 + ...ak--storage921624073--input1008262038-.out | 24 + ...right--storage4177631--input202098045-.out | 25 + ..._right--storage4177631--input44576556-.out | 25 + ...vel--storage492856247--input125992234-.out | 21 + ...cat--storage717096222--input457300675-.out | 27 + ...cat--storage717096222--input546523343-.out | 27 + ...tes--storage149262694--input220724351-.out | 27 + ...tes--storage149262694--input457300675-.out | 27 + ...ytes--storage65410082--input457300675-.out | 27 + ...tes--storage726220441--input972761363-.out | 27 + ..._id--storage528921618--input264787654-.out | 19 + ..._id--storage528921618--input457300675-.out | 19 + ..._id--storage528921618--input656499821-.out | 19 + ...map--storage528921618--input264787654-.out | 27 + ...map--storage528921618--input457300675-.out | 21 + ...map--storage528921618--input656499821-.out | 27 + ...ter--storage680650890--input568817463-.out | 42 + ...ter--storage680650890--input737923774-.out | 42 + ...ock--storage907453363--input457300675-.out | 36 + ...ock--storage907453363--input648737279-.out | 136 + ...ock--storage907453363--input908379154-.out | 136 + ...ize--storage492856247--input403499055-.out | 21 + ...ize--storage492856247--input457300675-.out | 21 + ...ize--storage492856247--input469078912-.out | 21 + ...ize--storage492856247--input802622031-.out | 21 + ...eft--storage528921618--input457300675-.out | 52 + ...eft--storage528921618--input851203613-.out | 163 + ...tes--storage125992234--input125992234-.out | 93 + ...tes--storage125992234--input125992234-.out | 129 + ...id--storage457300675--input1027566226-.out | 19 + ..._id--storage457300675--input276660554-.out | 19 + ..._id--storage457300675--input599923743-.out | 19 + ...er--storage1011138251--input403579222-.out | 152 + ...er--storage1011138251--input532072758-.out | 152 + ...map--storage457300675--input798141440-.out | 32 + ...map--storage794999348--input152441147-.out | 68 + ..._map--storage88008216--input798141440-.out | 50 + ...nat--storage495706788--input453441034-.out | 42 + ..._nat--storage56274299--input453441034-.out | 42 + ..._nat--storage56274299--input564400327-.out | 42 + ..._nat--storage56274299--input654274102-.out | 42 + ...nat--storage690637660--input453441034-.out | 42 + ...nat--storage806237530--input453441034-.out | 42 + ...ng--storage109689253--input1071610051-.out | 42 + ...ing--storage109689253--input700475845-.out | 42 + ...ing--storage109689253--input905318451-.out | 42 + ...ing--storage495706788--input700475845-.out | 42 + ...ing--storage915708427--input700475845-.out | 42 + ...ing--storage936682951--input905318451-.out | 42 + ...size--storage492856247--input15265129-.out | 21 + ...ize--storage492856247--input158311065-.out | 21 + ...ize--storage492856247--input456982702-.out | 21 + ...ize--storage492856247--input457300675-.out | 21 + ...mul--storage125992234--input125992234-.out | 131 + ..._fr--storage151303925--input216277421-.out | 38 + ..._fr--storage287799761--input485842614-.out | 38 + ...eg--storage680650890--input1067298059-.out | 25 + ...neg--storage680650890--input380029349-.out | 25 + ...neg--storage680650890--input563503226-.out | 25 + ...neg--storage680650890--input788662499-.out | 25 + ...neg--storage680650890--input972832189-.out | 25 + ...none--storage11179311--input125992234-.out | 21 + ...not--storage921624073--input570553153-.out | 23 + ...not--storage921624073--input954397288-.out | 23 + ...ry--storage921624073--input1051197453-.out | 27 + ...ary--storage921624073--input123939249-.out | 27 + ...nary--storage921624073--input24243730-.out | 27 + ...ary--storage921624073--input518945720-.out | 27 + ...ary--storage921624073--input788662499-.out | 27 + ...ary--storage921624073--input906118781-.out | 27 + ...ary--storage921624073--input921874253-.out | 27 + ...ary--storage921624073--input972832189-.out | 27 + ...tes--storage125992234--input125992234-.out | 66 + ...-or--storage921624073--input106930123-.out | 35 + ...-or--storage921624073--input181204719-.out | 35 + ...-or--storage921624073--input223774825-.out | 35 + ...-or--storage921624073--input908807505-.out | 35 + ...ry--storage921624073--input1056991424-.out | 26 + ...ary--storage921624073--input375993021-.out | 26 + ...ary--storage921624073--input673240563-.out | 26 + ...ary--storage921624073--input747448890-.out | 26 + ...ary--storage921624073--input832403787-.out | 26 + ...ary--storage921624073--input858098961-.out | 26 + ...tes--storage125992234--input125992234-.out | 75 + ...rev--storage125992234--input305844558-.out | 845 + ...rev--storage125992234--input646365167-.out | 845 + ...ty--storage125992234--input1028781121-.out | 1194 + ...cty--storage125992234--input802670583-.out | 1032 + ..._id--storage921624073--input106930123-.out | 21 + ..._id--storage921624073--input181204719-.out | 21 + ..._id--storage921624073--input223774825-.out | 21 + ..._id--storage921624073--input908807505-.out | 21 + ...ec--storage256947135--input1050356042-.out | 47 + ...c_2--storage197120858--input179371027-.out | 282 + ...int--storage921624073--input125992234-.out | 23 + ...rse--storage528921618--input457300675-.out | 27 + ...rse--storage528921618--input851203613-.out | 42 + ...oop--storage528921618--input457300675-.out | 50 + ...oop--storage528921618--input851203613-.out | 131 + ...ate--storage457300675--input125992234-.out | 21 + ...ess--storage125992234--input125992234-.out | 46 + ...int--storage125992234--input125992234-.out | 47 + ...int--storage125992234--input289072903-.out | 93 + ...car--storage224747103--input620760059-.out | 49 + ...car--storage224747103--input717096222-.out | 49 + ..._car--storage224747103--input79230375-.out | 49 + ...cdr--storage205576101--input654274102-.out | 46 + ...cdr--storage224747103--input453441034-.out | 46 + ...cdr--storage611418174--input967284912-.out | 46 + ..._id--storage457300675--input264787654-.out | 19 + ..._id--storage457300675--input457300675-.out | 19 + ..._id--storage457300675--input989507347-.out | 19 + ...ter--storage492856247--input457300675-.out | 27 + ...ter--storage492856247--input701684511-.out | 47 + ...ter--storage492856247--input802622031-.out | 32 + ...mber--storage495706788--input33757838-.out | 61 + ...mber--storage550087893--input79230375-.out | 61 + ...mber--storage605111220--input33757838-.out | 61 + ...ize--storage492856247--input403499055-.out | 21 + ...ize--storage492856247--input457300675-.out | 21 + ...ize--storage492856247--input469078912-.out | 21 + ...ize--storage492856247--input802622031-.out | 21 + ...a3--storage921624073--input1008262038-.out | 24 + ...fts--storage921624073--input115382786-.out | 30 + ...fts--storage921624073--input271566295-.out | 30 + ...fts--storage921624073--input340971987-.out | 30 + ...fts--storage921624073--input374168553-.out | 30 + ...fts--storage921624073--input413621582-.out | 30 + ...fts--storage921624073--input424849461-.out | 30 + ...fts--storage921624073--input485030042-.out | 30 + ...fts--storage921624073--input705767726-.out | 30 + ...fts--storage921624073--input769385932-.out | 30 + ...fts--storage921624073--input913715337-.out | 30 + ...lice--storage351480851--input65907686-.out | 38 + ...ice--storage364922380--input198821575-.out | 37 + ...ice--storage364922380--input359592843-.out | 37 + ...ice--storage364922380--input551316239-.out | 37 + ...ice--storage364922380--input722749044-.out | 37 + ...ice--storage364922380--input839234860-.out | 37 + ...ice--storage364922380--input919180079-.out | 37 + ...ice--storage921624073--input551316239-.out | 31 + ...tes--storage229749865--input198821575-.out | 37 + ...tes--storage229749865--input462551352-.out | 37 + ...tes--storage229749865--input489157380-.out | 37 + ...tes--storage229749865--input551316239-.out | 37 + ...tes--storage229749865--input669330759-.out | 37 + ...tes--storage229749865--input743596105-.out | 37 + ...tes--storage229749865--input839234860-.out | 37 + ...ytes--storage504917929--input65907686-.out | 38 + ...tes--storage921624073--input462551352-.out | 31 + ...id--storage921624073--input1016369050-.out | 21 + ...r_id--storage921624073--input93477117-.out | 21 + ...lta--storage492856247--input249636002-.out | 34 + ...lta--storage492856247--input307538219-.out | 34 + ...lta--storage492856247--input831449542-.out | 34 + ...sub--storage921624073--input706350605-.out | 71 + ...sub--storage921624073--input856198194-.out | 71 + ...omb--storage680650890--input394061083-.out | 50 + ...air--storage125992234--input125992234-.out | 462 + ...r--storage1011138251--input1040351577-.out | 32 + ...or--storage921624073--input1058477720-.out | 32 + ...or--storage921624073--input1073176155-.out | 32 + ...xor--storage921624073--input246594902-.out | 32 + ...xor--storage921624073--input506603577-.out | 32 + ...xor--storage921624073--input576248088-.out | 32 + ...xor--storage921624073--input612012282-.out | 32 + ...xor--storage921624073--input617591686-.out | 32 + ...xor--storage921624073--input639311176-.out | 32 + ...xor--storage921624073--input688315180-.out | 32 + ...xor--storage921624073--input967929605-.out | 32 + ...tes--storage125992234--input125992234-.out | 75 + ...arisc- test Michelson opcodes- BALANCE.out | 147 + .../Parisc- test Michelson opcodes- LEVEL.out | 21 + .../Parisc- test Michelson opcodes- NOW.out | 21 + ...Michelson opcodes- arithmetic_overflow.out | 224 + ...Michelson opcodes- big_map_contract_io.out | 1088 + ...est Michelson opcodes- check_signature.out | 243 + ...st Michelson opcodes- hash_consistency.out | 32 + ...Michelson opcodes- map_map_side_effect.out | 273 + ...c- test Michelson opcodes- pack_unpack.out | 108 + ... Tc scripts.out => Parisb- Tc scripts.out} | 0 .../Parisc- Tc scripts.out | 50658 ++++++++++++++++ ...ntract.out => Parisb- Create contract.out} | 0 .../Parisc- Create contract.out | 109 + ...re (test Coordinator-s post preimage).out} | 0 ...rastructure (test GET v0-certificate).out} | 0 ...astructure (test GET v0-missing_page).out} | 0 ...ure (test GET v0-monitor-certificate).out} | 0 ...ure (test GET v0-monitor-root_hashes).out} | 0 ...infrastructure (test GET v0-preimage).out} | 0 ...re (test PUT v0-dac_member_signature).out} | 0 ...ure (test Coordinator-s post preimage).out | 7 + ...frastructure (test GET v0-certificate).out | 6 + ...rastructure (test GET v0-missing_page).out | 6 + ...ture (test GET v0-monitor-certificate).out | 6 + ...ture (test GET v0-monitor-root_hashes).out | 4 + ... infrastructure (test GET v0-preimage).out | 6 + ...ure (test PUT v0-dac_member_signature).out | 11 + ...owing dal and baker tutorial commands.out} | 0 ...integration (Use all available slots).out} | 0 ...th L1 (rollup_node_applies_dal_pages).out} | 0 ...with L1 (rollup_node_downloads_slots).out} | 0 ...p and node with L1 (test echo_kernel).out} | 0 ... (test reveal_dal_page in fast exec w.out} | 0 ...lup and node with L1 (test tx_kernel).out} | 0 ... (test_lag-10_time-8_preinject-1_slot.out} | 0 ...lowing dal and baker tutorial commands.out | 125 + ... integration (Use all available slots).out | 163 + ...ith L1 (rollup_node_applies_dal_pages).out | 109 + ... with L1 (rollup_node_downloads_slots).out | 76 + ...up and node with L1 (test echo_kernel).out | 39 + ...1 (test reveal_dal_page in fast exec w.out | 39 + ...llup and node with L1 (test tx_kernel).out | 35 + ...1 (test_lag-10_time-8_preinject-1_slot.out | 101 + ...mit.out => Parisb- set deposits limit.out} | 0 ...t.out => Parisb- unset deposits limit.out} | 0 .../Parisc- set deposits limit.out | 26 + .../Parisc- unset deposits limit.out | 26 + ...ncoding regression test- block_header.out} | 0 ...ing regression test- block_header.raw.out} | 0 ...egression test- block_header.unsigned.out} | 0 ...ol encoding regression test- contract.out} | 0 ...tocol encoding regression test- cycle.out} | 0 ...col encoding regression test- fitness.out} | 0 ...ol encoding regression test- gas.cost.out} | 0 ...rotocol encoding regression test- gas.out} | 0 ...tocol encoding regression test- level.out} | 0 ...tocol encoding regression test- nonce.out} | 0 ...g regression test- operation.internal.out} | 0 ...l encoding regression test- operation.out} | 0 ...coding regression test- operation.raw.out} | 0 ...g regression test- operation.unsigned.out} | 0 ...egression test- operation_with_legacy.out} | 0 ... test- operation_with_legacy.unsigned.out} | 0 ...ocol encoding regression test- period.out} | 0 ...l encoding regression test- raw_level.out} | 0 ...otocol encoding regression test- seed.out} | 0 ...rotocol encoding regression test- tez.out} | 0 ...l encoding regression test- timestamp.out} | 0 ...encoding regression test- vote.ballot.out} | 0 ...ncoding regression test- vote.ballots.out} | 0 ...coding regression test- vote.listings.out} | 0 ...g regression test- voting_period.kind.out} | 0 ...coding regression test- voting_period.out} | 0 ...encoding regression test- block_header.out | 36 + ...ding regression test- block_header.raw.out | 26 + ...regression test- block_header.unsigned.out | 33 + ...col encoding regression test- contract.out | 12 + ...otocol encoding regression test- cycle.out | 12 + ...ocol encoding regression test- fitness.out | 11 + ...col encoding regression test- gas.cost.out | 12 + ...protocol encoding regression test- gas.out | 18 + ...otocol encoding regression test- level.out | 13 + ...otocol encoding regression test- nonce.out | 6 + ...ng regression test- operation.internal.out | 140 + ...ol encoding regression test- operation.out | 561 + ...ncoding regression test- operation.raw.out | 11 + ...ng regression test- operation.unsigned.out | 548 + ...regression test- operation_with_legacy.out | 593 + ...n test- operation_with_legacy.unsigned.out | 548 + ...tocol encoding regression test- period.out | 12 + ...ol encoding regression test- raw_level.out | 12 + ...rotocol encoding regression test- seed.out | 6 + ...protocol encoding regression test- tez.out | 12 + ...ol encoding regression test- timestamp.out | 6 + ... encoding regression test- vote.ballot.out | 18 + ...encoding regression test- vote.ballots.out | 10 + ...ncoding regression test- vote.listings.out | 16 + ...ng regression test- voting_period.kind.out | 24 + ...ncoding regression test- voting_period.out | 20 + ...risb- hash data ... of type ... (bad).out} | 0 ...isb- hash data ... of type ... (good).out} | 0 ...arisc- hash data ... of type ... (bad).out | 0 ...risc- hash data ... of type ... (good).out | 594 + ....out => Parisb- increase paid storage.out} | 0 .../Parisc- increase paid storage.out | 30 + ...b- Test Michelson stack normalization.out} | 0 ...isb- Test normalize in unparsing mode.out} | 0 ....out => Parisb- Test normalize script.out} | 0 ...pe.out => Parisb- Test normalize type.out} | 0 ...risb- Test normalize with legacy flag.out} | 0 ...sc- Test Michelson stack normalization.out | 520 + ...risc- Test normalize in unparsing mode.out | 14 + .../Parisc- Test normalize script.out | 42 + .../Parisc- Test normalize type.out | 24 + ...arisc- Test normalize with legacy flag.out | 10 + ...h - RPC API should work and be stable.out} | 0 ...isted staker can publish a commitment.out} | 0 ...isb- arith - boot sector is evaluated.out} | 0 ...ion of a SCORU executes without error.out} | 0 ... refutation game are slashed-rewarded.out} | 0 ...risb- arith - recover bond of stakers.out} | 0 ...mes winning strategies (degraded_new).out} | 0 ...winning strategies (degraded_ongoing).out} | 0 ...ames winning strategies (inbox_proof).out} | 0 ...g strategies (inbox_proof_at_genesis).out} | 0 ...rategies (inbox_proof_many_empty_leve.out} | 0 ...rategies (inbox_proof_one_empty_level.out} | 0 ...rategies (inbox_proof_with_new_conten.out} | 0 ...ames winning strategies (pvm_proof_0).out} | 0 ...ames winning strategies (pvm_proof_1).out} | 0 ...ames winning strategies (pvm_proof_2).out} | 0 ...ames winning strategies (pvm_proof_3).out} | 0 ...ing strategies (pvm_proof_at_genesis).out} | 0 ... strategies (pvm_proof_second_period).out} | 0 ...strategies (reset_honest_during_game).out} | 0 ...on games winning strategies (timeout).out} | 0 ...0 - RPC API should work and be stable.out} | 0 ...ion of a SCORU executes without error.out} | 0 ...es winning strategies (inbox_proof_0).out} | 0 ...es winning strategies (inbox_proof_1).out} | 0 ...ames winning strategies (pvm_proof_0).out} | 0 ...ames winning strategies (pvm_proof_1).out} | 0 ...ames winning strategies (pvm_proof_2).out} | 0 ...ames winning strategies (pvm_proof_3).out} | 0 ...ng strategies (pvm_proof_second_perio.out} | 0 ...th - RPC API should work and be stable.out | 261 + ...listed staker can publish a commitment.out | 2 + ...risc- arith - boot sector is evaluated.out | 92 + ...tion of a SCORU executes without error.out | 35 + ...a refutation game are slashed-rewarded.out | 141 + ...arisc- arith - recover bond of stakers.out | 195 + ...ames winning strategies (degraded_new).out | 158 + ... winning strategies (degraded_ongoing).out | 158 + ...games winning strategies (inbox_proof).out | 156 + ...ng strategies (inbox_proof_at_genesis).out | 158 + ...trategies (inbox_proof_many_empty_leve.out | 155 + ...trategies (inbox_proof_one_empty_level.out | 155 + ...trategies (inbox_proof_with_new_conten.out | 156 + ...games winning strategies (pvm_proof_0).out | 158 + ...games winning strategies (pvm_proof_1).out | 156 + ...games winning strategies (pvm_proof_2).out | 158 + ...games winning strategies (pvm_proof_3).out | 158 + ...ning strategies (pvm_proof_at_genesis).out | 158 + ...g strategies (pvm_proof_second_period).out | 158 + ... strategies (reset_honest_during_game).out | 158 + ...ion games winning strategies (timeout).out | 158 + ..._0 - RPC API should work and be stable.out | 275 + ...tion of a SCORU executes without error.out | 35 + ...mes winning strategies (inbox_proof_0).out | 501 + ...mes winning strategies (inbox_proof_1).out | 501 + ...games winning strategies (pvm_proof_0).out | 504 + ...games winning strategies (pvm_proof_1).out | 504 + ...games winning strategies (pvm_proof_2).out | 504 + ...games winning strategies (pvm_proof_3).out | 504 + ...ing strategies (pvm_proof_second_perio.out | 501 + ...> Parisb- Test script hash regression.out} | 0 .../Parisc- Test script hash regression.out | 445 + ....out => Parisb- Self address transfer.out} | 0 .../Parisc- Self address transfer.out | 141 + ...r bytes parameters more than 32 bytes.out} | 0 ...ls12_381 contract primitives- fr- add.out} | 0 ...ls12_381 contract primitives- fr- mul.out} | 0 ...2_381 contract primitives- fr- negate.out} | 0 ...12_381 contract primitives- fr- store.out} | 0 ...ls12_381 contract primitives- g1- add.out} | 0 ...ls12_381 contract primitives- g1- mul.out} | 0 ...2_381 contract primitives- g1- negate.out} | 0 ...12_381 contract primitives- g1- store.out} | 0 ...ls12_381 contract primitives- g2- add.out} | 0 ...ls12_381 contract primitives- g2- mul.out} | 0 ...2_381 contract primitives- g2- negate.out} | 0 ...12_381 contract primitives- g2- store.out} | 0 ...tract primitives- pairing_check empty.out} | 0 ...t primitives- pairing_check(neg- pos).out} | 0 ...t primitives- pairing_check(pos- neg).out} | 0 ...t primitives- pairing_check(pos- pos).out} | 0 ...act primitives- signature_aggregation.out} | 0 ...381 contract primitives- test_groth16.out} | 0 ...fr bytes parameters more than 32 bytes.out | 8 + ...Bls12_381 contract primitives- fr- add.out | 1296 + ...Bls12_381 contract primitives- fr- mul.out | 1296 + ...12_381 contract primitives- fr- negate.out | 108 + ...s12_381 contract primitives- fr- store.out | 108 + ...Bls12_381 contract primitives- g1- add.out | 1296 + ...Bls12_381 contract primitives- g1- mul.out | 1296 + ...12_381 contract primitives- g1- negate.out | 108 + ...s12_381 contract primitives- g1- store.out | 108 + ...Bls12_381 contract primitives- g2- add.out | 1296 + ...Bls12_381 contract primitives- g2- mul.out | 1296 + ...12_381 contract primitives- g2- negate.out | 108 + ...s12_381 contract primitives- g2- store.out | 108 + ...ntract primitives- pairing_check empty.out | 9 + ...ct primitives- pairing_check(neg- pos).out | 1296 + ...ct primitives- pairing_check(pos- neg).out | 1296 + ...ct primitives- pairing_check(pos- pos).out | 1296 + ...ract primitives- signature_aggregation.out | 180 + ..._381 contract primitives- test_groth16.out | 9 + ... => Parisb- Ticket updates in receipt.out} | 0 .../Parisc- Ticket updates in receipt.out | 153 + ... => Parisb- Create and remove tickets.out} | 0 ...rt-contract rollup should succeed wit.out} | 0 ...om implicit accounts must be rejected.out} | 0 ...nated contracts and implicit accounts.out} | 0 ...implicit accounts with some Tez along.out} | 0 ...icit accounts with the wrong type mus.out} | 0 ...s from contracts to implicit accounts.out} | 0 ...out => Parisb- Send tickets in bigmap.out} | 0 ...r (with complex parameters) from impl.out} | 0 ...r from implicit account to originated.out} | 0 ...contract storage to implicit accounts.out} | 0 ...om implicit accounts must be rejected.out} | 0 ...rt-contract rollup should succeed wit.out} | 0 ...accounts or originated contracts acce.out} | 0 ...om implicit accounts must be rejected.out} | 0 .../Parisc- Create and remove tickets.out | 220 + ...art-contract rollup should succeed wit.out | 55 + ...rom implicit accounts must be rejected.out | 210 + ...inated contracts and implicit accounts.out | 387 + ... implicit accounts with some Tez along.out | 115 + ...licit accounts with the wrong type mus.out | 195 + ...ts from contracts to implicit accounts.out | 111 + .../Parisc- Send tickets in bigmap.out | 296 + ...or (with complex parameters) from impl.out | 61 + ...or from implicit account to originated.out | 48 + ... contract storage to implicit accounts.out | 294 + ...rom implicit accounts must be rejected.out | 129 + ...art-contract rollup should succeed wit.out | 111 + ... accounts or originated contracts acce.out | 197 + ...rom implicit accounts must be rejected.out | 174 + ...tx kernel should run e2e (kernel_e2e).out} | 0 ... tx kernel should run e2e (kernel_e2e).out | 224 + ...Paris- Run TZT.out => Parisb- Run TZT.out} | 0 .../tzt_regression.ml/Parisc- Run TZT.out | 69 + ...s- Run views.out => Parisb- Run views.out} | 0 .../expected/views.ml/Parisc- Run views.out | 213 + 1331 files changed, 116116 insertions(+) rename etherlink/tezt/tests/expected/evm_rollup.ml/{Paris- Regression test for L2 block hash.out => Parisb- Regression test for L2 block hash.out} (100%) create mode 100644 etherlink/tezt/tests/expected/evm_rollup.ml/Parisc- Regression test for L2 block hash.out create mode 100644 tezt/tests/encoding_samples/parisb/block_header.raw/block_header.raw.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/block_header.unsigned/block_header.unsigned.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/block_header/block_header.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-alloc.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-copy.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-remove.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-update.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/contract/contract-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/contract/contract-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/cycle/cycle-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/cycle/cycle-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/fitness/fitness.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/gas/gas-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/gas/gas-unaccounted.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/gas/gas-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/level/level.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/nonce/nonce.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.raw/operation.raw.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-attestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-preaatestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-attestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-double-attestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-double-preattestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-preattestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-endorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-preendorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/period/period-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/period/period-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/raw_level/raw_level-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/raw_level/raw_level-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/roll/roll-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/roll/roll-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/seed/seed.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/tez/tez-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/tez/tez-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/timestamp/timestamp.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-nay.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-pass.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-yay.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/vote.ballots/vote.ballots.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/vote.listings/vote.listings.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-promotion-vote.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-proposal.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing-vote.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/voting_period/voting_period-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisb/voting_period/voting_period-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/block_header.raw/block_header.raw.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/block_header.unsigned/block_header.unsigned.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/block_header/block_header.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-alloc.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-copy.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-remove.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-update.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/contract/contract-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/contract/contract-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/cycle/cycle-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/cycle/cycle-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/fitness/fitness.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/gas/gas-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/gas/gas-unaccounted.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/gas/gas-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/level/level.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/nonce/nonce.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.raw/operation.raw.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-attestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-preaatestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-attestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-double-attestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-double-preattestation-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-preattestation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-activate-account.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-ballot.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-endorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-origination.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-preendorsement.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-proposals.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-reveal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/period/period-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/period/period-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/raw_level/raw_level-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/raw_level/raw_level-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/roll/roll-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/roll/roll-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/seed/seed.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/tez/tez-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/tez/tez-zero.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/timestamp/timestamp.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-nay.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-pass.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-yay.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/vote.ballots/vote.ballots.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/vote.listings/vote.listings.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-promotion-vote.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-proposal.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing-vote.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/voting_period/voting_period-positive.sample.json create mode 100644 tezt/tests/encoding_samples/parisc/voting_period/voting_period-zero.sample.json rename tezt/tests/expected/RPC_test.ml/{Paris- (mode client) RPC regression tests- adaptive_issuance.out => Parisb- (mode client) RPC regression tests- adaptive_issuance.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode client) RPC regression tests- contracts.out => Parisb- (mode client) RPC regression tests- contracts.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode client) RPC regression tests- delegates.out => Parisb- (mode client) RPC regression tests- delegates.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode client) RPC regression tests- mempool.out => Parisb- (mode client) RPC regression tests- mempool.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode client) RPC regression tests- misc_protocol.out => Parisb- (mode client) RPC regression tests- misc_protocol.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode client) RPC regression tests- votes.out => Parisb- (mode client) RPC regression tests- votes.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode light) RPC regression tests- adaptive_issuance.out => Parisb- (mode light) RPC regression tests- adaptive_issuance.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode light) RPC regression tests- contracts.out => Parisb- (mode light) RPC regression tests- contracts.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode light) RPC regression tests- delegates.out => Parisb- (mode light) RPC regression tests- delegates.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode light) RPC regression tests- misc_protocol.out => Parisb- (mode light) RPC regression tests- misc_protocol.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode light) RPC regression tests- votes.out => Parisb- (mode light) RPC regression tests- votes.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy) RPC regression tests- adaptive_issuance.out => Parisb- (mode proxy) RPC regression tests- adaptive_issuance.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy) RPC regression tests- contracts.out => Parisb- (mode proxy) RPC regression tests- contracts.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy) RPC regression tests- delegates.out => Parisb- (mode proxy) RPC regression tests- delegates.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy) RPC regression tests- mempool.out => Parisb- (mode proxy) RPC regression tests- mempool.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy) RPC regression tests- misc_protocol.out => Parisb- (mode proxy) RPC regression tests- misc_protocol.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy) RPC regression tests- votes.out => Parisb- (mode proxy) RPC regression tests- votes.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out => Parisb- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_data_dir) RPC regression tests- contracts.out => Parisb- (mode proxy_server_data_dir) RPC regression tests- contracts.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_data_dir) RPC regression tests- delegates.out => Parisb- (mode proxy_server_data_dir) RPC regression tests- delegates.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out => Parisb- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_data_dir) RPC regression tests- votes.out => Parisb- (mode proxy_server_data_dir) RPC regression tests- votes.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out => Parisb- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_rpc) RPC regression tests- contracts.out => Parisb- (mode proxy_server_rpc) RPC regression tests- contracts.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_rpc) RPC regression tests- delegates.out => Parisb- (mode proxy_server_rpc) RPC regression tests- delegates.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out => Parisb- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out} (100%) rename tezt/tests/expected/RPC_test.ml/{Paris- (mode proxy_server_rpc) RPC regression tests- votes.out => Parisb- (mode proxy_server_rpc) RPC regression tests- votes.out} (100%) create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- adaptive_issuance.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- contracts.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- delegates.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- mempool.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- misc_protocol.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- votes.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- adaptive_issuance.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- contracts.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- delegates.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- misc_protocol.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- votes.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- adaptive_issuance.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- contracts.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- delegates.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- mempool.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- misc_protocol.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- votes.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- contracts.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- delegates.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- votes.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- contracts.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- delegates.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out create mode 100644 tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- votes.out rename tezt/tests/expected/baker_test.ml/{Paris- Baker rewards.out => Parisb- Baker rewards.out} (100%) create mode 100644 tezt/tests/expected/baker_test.ml/Parisc- Baker rewards.out rename tezt/tests/expected/consensus_key.ml/{Paris- Test drain delegate with (baker - delegate - consensus - destination).out => Parisb- Test drain delegate with (baker - delegate - consensus - destination).out} (100%) rename tezt/tests/expected/consensus_key.ml/{Paris- Test drain delegate with (baker - delegate - consensus -- destination).out => Parisb- Test drain delegate with (baker - delegate - consensus -- destination).out} (100%) rename tezt/tests/expected/consensus_key.ml/{Paris- Test drain delegate with (baker -- delegate - consensus - destination).out => Parisb- Test drain delegate with (baker -- delegate - consensus - destination).out} (100%) rename tezt/tests/expected/consensus_key.ml/{Paris- Test drain delegate with (baker -- delegate - consensus -- destination).out => Parisb- Test drain delegate with (baker -- delegate - consensus -- destination).out} (100%) rename tezt/tests/expected/consensus_key.ml/{Paris- Test register with consensus key.out => Parisb- Test register with consensus key.out} (100%) rename tezt/tests/expected/consensus_key.ml/{Paris- Test set consensus key - baker is delegate.out => Parisb- Test set consensus key - baker is delegate.out} (100%) rename tezt/tests/expected/consensus_key.ml/{Paris- Test set consensus key - baker is not delegate.out => Parisb- Test set consensus key - baker is not delegate.out} (100%) create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus - destination).out create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus -- destination).out create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus - destination).out create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus -- destination).out create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test register with consensus key.out create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is delegate.out create mode 100644 tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is not delegate.out rename tezt/tests/expected/contract_liquidity_baking.ml/{Paris- Test add-approve-transfer-remove liquidity.out => Parisb- Test add-approve-transfer-remove liquidity.out} (100%) rename tezt/tests/expected/contract_liquidity_baking.ml/{Paris- Test trades.out => Parisb- Test trades.out} (100%) create mode 100644 tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test add-approve-transfer-remove liquidity.out create mode 100644 tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test trades.out rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert.out => Parisb- Macro expansion- macros-assert.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_cmpeq.out => Parisb- Macro expansion- macros-assert_cmpeq.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_cmpge.out => Parisb- Macro expansion- macros-assert_cmpge.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_cmpgt.out => Parisb- Macro expansion- macros-assert_cmpgt.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_cmple.out => Parisb- Macro expansion- macros-assert_cmple.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_cmplt.out => Parisb- Macro expansion- macros-assert_cmplt.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_cmpneq.out => Parisb- Macro expansion- macros-assert_cmpneq.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_eq.out => Parisb- Macro expansion- macros-assert_eq.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_ge.out => Parisb- Macro expansion- macros-assert_ge.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_gt.out => Parisb- Macro expansion- macros-assert_gt.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_le.out => Parisb- Macro expansion- macros-assert_le.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_lt.out => Parisb- Macro expansion- macros-assert_lt.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-assert_neq.out => Parisb- Macro expansion- macros-assert_neq.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-big_map_get_add.out => Parisb- Macro expansion- macros-big_map_get_add.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-big_map_mem.out => Parisb- Macro expansion- macros-big_map_mem.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-build_list.out => Parisb- Macro expansion- macros-build_list.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-carn_and_cdrn.out => Parisb- Macro expansion- macros-carn_and_cdrn.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-compare.out => Parisb- Macro expansion- macros-compare.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-compare_bytes.out => Parisb- Macro expansion- macros-compare_bytes.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-fail.out => Parisb- Macro expansion- macros-fail.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-guestbook.out => Parisb- Macro expansion- macros-guestbook.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-macro_annotations.out => Parisb- Macro expansion- macros-macro_annotations.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-map_caddaadr.out => Parisb- Macro expansion- macros-map_caddaadr.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-max_in_list.out => Parisb- Macro expansion- macros-max_in_list.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-min.out => Parisb- Macro expansion- macros-min.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-pair_macro.out => Parisb- Macro expansion- macros-pair_macro.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-set_caddaadr.out => Parisb- Macro expansion- macros-set_caddaadr.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-take_my_money.out => Parisb- Macro expansion- macros-take_my_money.out} (100%) rename tezt/tests/expected/contract_macros.ml/{Paris- Macro expansion- macros-unpair_macro.out => Parisb- Macro expansion- macros-unpair_macro.out} (100%) create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpeq.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpge.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpgt.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmple.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmplt.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpneq.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_eq.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_ge.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_gt.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_le.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_lt.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_neq.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_get_add.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_mem.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-build_list.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-carn_and_cdrn.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare_bytes.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-fail.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-guestbook.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-macro_annotations.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-map_caddaadr.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-max_in_list.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-min.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-pair_macro.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-set_caddaadr.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-take_my_money.out create mode 100644 tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-unpair_macro.out rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_big_map_origination.out => Parisb- Contract onchain opcodes- test_big_map_origination.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_contract_fails.out => Parisb- Contract onchain opcodes- test_contract_fails.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_level.out => Parisb- Contract onchain opcodes- test_level.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_now.out => Parisb- Contract onchain opcodes- test_now.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_self.out => Parisb- Contract onchain opcodes- test_self.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_sender.out => Parisb- Contract onchain opcodes- test_sender.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_set_delegate.out => Parisb- Contract onchain opcodes- test_set_delegate.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_slice.out => Parisb- Contract onchain opcodes- test_slice.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_source.out => Parisb- Contract onchain opcodes- test_source.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_split_bytes.out => Parisb- Contract onchain opcodes- test_split_bytes.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_split_string.out => Parisb- Contract onchain opcodes- test_split_string.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_store_input.out => Parisb- Contract onchain opcodes- test_store_input.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_trace_origination_compare_big_type.out => Parisb- Contract onchain opcodes- test_trace_origination_compare_big_type.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_trace_origination_compare_big_type2.out => Parisb- Contract onchain opcodes- test_trace_origination_compare_big_type2.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_transfer_amount.out => Parisb- Contract onchain opcodes- test_transfer_amount.out} (100%) rename tezt/tests/expected/contract_onchain_opcodes.ml/{Paris- Contract onchain opcodes- test_transfer_tokens.out => Parisb- Contract onchain opcodes- test_transfer_tokens.out} (100%) create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_big_map_origination.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_contract_fails.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_level.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_now.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_self.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_sender.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_set_delegate.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_slice.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_source.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_bytes.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_string.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_store_input.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type2.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_amount.out create mode 100644 tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_tokens.out rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -abs--storage125992234--input254251340-.out => Parisb- opcodes -abs--storage125992234--input254251340-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -abs--storage125992234--input420401245-.out => Parisb- opcodes -abs--storage125992234--input420401245-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -abs--storage125992234--input680650890-.out => Parisb- opcodes -abs--storage125992234--input680650890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add--storage125992234--input125992234-.out => Parisb- opcodes -add--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out => Parisb- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out => Parisb- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out => Parisb- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out => Parisb- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_delta_timestamp--storage921624073--input249636002-.out => Parisb- opcodes -add_delta_timestamp--storage921624073--input249636002-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_delta_timestamp--storage921624073--input267363182-.out => Parisb- opcodes -add_delta_timestamp--storage921624073--input267363182-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_delta_timestamp--storage921624073--input438561129-.out => Parisb- opcodes -add_delta_timestamp--storage921624073--input438561129-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_timestamp_delta--storage921624073--input249636002-.out => Parisb- opcodes -add_timestamp_delta--storage921624073--input249636002-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_timestamp_delta--storage921624073--input307538219-.out => Parisb- opcodes -add_timestamp_delta--storage921624073--input307538219-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -add_timestamp_delta--storage921624073--input373737581-.out => Parisb- opcodes -add_timestamp_delta--storage921624073--input373737581-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -address--storage921624073--input117475800-.out => Parisb- opcodes -address--storage921624073--input117475800-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and--storage921624073--input106930123-.out => Parisb- opcodes -and--storage921624073--input106930123-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and--storage921624073--input181204719-.out => Parisb- opcodes -and--storage921624073--input181204719-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and--storage921624073--input223774825-.out => Parisb- opcodes -and--storage921624073--input223774825-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and--storage921624073--input908807505-.out => Parisb- opcodes -and--storage921624073--input908807505-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and_binary--storage125992234--input125992234-.out => Parisb- opcodes -and_binary--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and_bytes--storage125992234--input125992234-.out => Parisb- opcodes -and_bytes--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and_logical_1--storage570553153--input106930123-.out => Parisb- opcodes -and_logical_1--storage570553153--input106930123-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and_logical_1--storage570553153--input181204719-.out => Parisb- opcodes -and_logical_1--storage570553153--input181204719-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and_logical_1--storage570553153--input223774825-.out => Parisb- opcodes -and_logical_1--storage570553153--input223774825-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -and_logical_1--storage570553153--input908807505-.out => Parisb- opcodes -and_logical_1--storage570553153--input908807505-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -balance--storage492856247--input125992234-.out => Parisb- opcodes -balance--storage492856247--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_nat--storage495706788--input453441034-.out => Parisb- opcodes -big_map_mem_nat--storage495706788--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_nat--storage56274299--input453441034-.out => Parisb- opcodes -big_map_mem_nat--storage56274299--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_nat--storage56274299--input564400327-.out => Parisb- opcodes -big_map_mem_nat--storage56274299--input564400327-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_nat--storage56274299--input654274102-.out => Parisb- opcodes -big_map_mem_nat--storage56274299--input654274102-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_nat--storage690637660--input453441034-.out => Parisb- opcodes -big_map_mem_nat--storage690637660--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_nat--storage806237530--input453441034-.out => Parisb- opcodes -big_map_mem_nat--storage806237530--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_string--storage109689253--input1071610051-.out => Parisb- opcodes -big_map_mem_string--storage109689253--input1071610051-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_string--storage109689253--input700475845-.out => Parisb- opcodes -big_map_mem_string--storage109689253--input700475845-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_string--storage109689253--input905318451-.out => Parisb- opcodes -big_map_mem_string--storage109689253--input905318451-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_string--storage495706788--input700475845-.out => Parisb- opcodes -big_map_mem_string--storage495706788--input700475845-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_string--storage915708427--input700475845-.out => Parisb- opcodes -big_map_mem_string--storage915708427--input700475845-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -big_map_mem_string--storage936682951--input905318451-.out => Parisb- opcodes -big_map_mem_string--storage936682951--input905318451-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input12599.out => Parisb- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out => Parisb- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out => Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out => Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out => Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out => Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out => Parisb- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out => Parisb- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out => Parisb- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out => Parisb- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out => Parisb- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out => Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out => Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out => Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out => Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out => Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out => Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out => Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out => Parisb- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out => Parisb- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out => Parisb- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out => Parisb- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out => Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out => Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out => Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out => Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out => Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out => Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out => Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bytes_of_int--storage125992234--input125992234-.out => Parisb- opcodes -bytes_of_int--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -bytes_of_nat--storage125992234--input125992234-.out => Parisb- opcodes -bytes_of_nat--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -car--storage680650890--input783124233-.out => Parisb- opcodes -car--storage680650890--input783124233-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -cdr--storage680650890--input783124233-.out => Parisb- opcodes -cdr--storage680650890--input783124233-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -chain_id_store--storage109160754--input125992234-.out => Parisb- opcodes -chain_id_store--storage109160754--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -chain_id_store--storage921624073--input125992234-.out => Parisb- opcodes -chain_id_store--storage921624073--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -chain_id_store--storage981066851--input125992234-.out => Parisb- opcodes -chain_id_store--storage981066851--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -comb--storage950292965--input125992234-.out => Parisb- opcodes -comb--storage950292965--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -comb-get--storage125992234--input186507116-.out => Parisb- opcodes -comb-get--storage125992234--input186507116-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -comb-set--storage186507116--input125992234-.out => Parisb- opcodes -comb-set--storage186507116--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -comb-set-2--storage921624073--input186507116-.out => Parisb- opcodes -comb-set-2--storage921624073--input186507116-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -compare--storage125992234--input125992234-.out => Parisb- opcodes -compare--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -comparisons--storage457300675--input281780712-.out => Parisb- opcodes -comparisons--storage457300675--input281780712-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_hello--storage457300675--input392583650-.out => Parisb- opcodes -concat_hello--storage457300675--input392583650-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_hello--storage457300675--input457300675-.out => Parisb- opcodes -concat_hello--storage457300675--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_hello--storage457300675--input640104625-.out => Parisb- opcodes -concat_hello--storage457300675--input640104625-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_hello_bytes--storage457300675--input354091714-.out => Parisb- opcodes -concat_hello_bytes--storage457300675--input354091714-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_hello_bytes--storage457300675--input441061063-.out => Parisb- opcodes -concat_hello_bytes--storage457300675--input441061063-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_hello_bytes--storage457300675--input457300675-.out => Parisb- opcodes -concat_hello_bytes--storage457300675--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_list--storage79230375--input264787654-.out => Parisb- opcodes -concat_list--storage79230375--input264787654-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_list--storage79230375--input316676251-.out => Parisb- opcodes -concat_list--storage79230375--input316676251-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -concat_list--storage79230375--input457300675-.out => Parisb- opcodes -concat_list--storage79230375--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -cons--storage457300675--input798141440-.out => Parisb- opcodes -cons--storage457300675--input798141440-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -cons--storage581876226--input166122047-.out => Parisb- opcodes -cons--storage581876226--input166122047-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -cons--storage793461282--input781487591-.out => Parisb- opcodes -cons--storage793461282--input781487591-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contains_all--storage921624073--input315650912-.out => Parisb- opcodes -contains_all--storage921624073--input315650912-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contains_all--storage921624073--input51111414-.out => Parisb- opcodes -contains_all--storage921624073--input51111414-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contains_all--storage921624073--input545734274-.out => Parisb- opcodes -contains_all--storage921624073--input545734274-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contains_all--storage921624073--input772794967-.out => Parisb- opcodes -contains_all--storage921624073--input772794967-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contains_all--storage921624073--input917967660-.out => Parisb- opcodes -contains_all--storage921624073--input917967660-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contains_all--storage921624073--input964818218-.out => Parisb- opcodes -contains_all--storage921624073--input964818218-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -contract--storage125992234--input117475800-.out => Parisb- opcodes -contract--storage125992234--input117475800-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -create_contract--storage921624073--input125992234-.out => Parisb- opcodes -create_contract--storage921624073--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -diff_timestamps--storage492856247--input1011138251-.out => Parisb- opcodes -diff_timestamps--storage492856247--input1011138251-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -diff_timestamps--storage492856247--input1018564342-.out => Parisb- opcodes -diff_timestamps--storage492856247--input1018564342-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -diff_timestamps--storage492856247--input1031049988-.out => Parisb- opcodes -diff_timestamps--storage492856247--input1031049988-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -diff_timestamps--storage492856247--input685590443-.out => Parisb- opcodes -diff_timestamps--storage492856247--input685590443-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dig_eq--storage125992234--input246866101-.out => Parisb- opcodes -dig_eq--storage125992234--input246866101-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dig_eq--storage125992234--input26856104-.out => Parisb- opcodes -dig_eq--storage125992234--input26856104-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dign--storage680650890--input529388602-.out => Parisb- opcodes -dign--storage680650890--input529388602-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dip--storage1011138251--input590117173-.out => Parisb- opcodes -dip--storage1011138251--input590117173-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dip--storage1011138251--input850887554-.out => Parisb- opcodes -dip--storage1011138251--input850887554-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dipn--storage680650890--input529388602-.out => Parisb- opcodes -dipn--storage680650890--input529388602-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dropn--storage680650890--input529388602-.out => Parisb- opcodes -dropn--storage680650890--input529388602-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dugn--storage680650890--input529388602-.out => Parisb- opcodes -dugn--storage680650890--input529388602-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -dup-n--storage125992234--input125992234-.out => Parisb- opcodes -dup-n--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv--storage994417987--input247451205-.out => Parisb- opcodes -ediv--storage994417987--input247451205-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv--storage994417987--input250545589-.out => Parisb- opcodes -ediv--storage994417987--input250545589-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv--storage994417987--input79625541-.out => Parisb- opcodes -ediv--storage994417987--input79625541-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input147133089-.out => Parisb- opcodes -ediv_mutez--storage977883604--input147133089-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input215785357-.out => Parisb- opcodes -ediv_mutez--storage977883604--input215785357-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input389351431-.out => Parisb- opcodes -ediv_mutez--storage977883604--input389351431-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input44513000-.out => Parisb- opcodes -ediv_mutez--storage977883604--input44513000-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input635398196-.out => Parisb- opcodes -ediv_mutez--storage977883604--input635398196-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input734264738-.out => Parisb- opcodes -ediv_mutez--storage977883604--input734264738-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ediv_mutez--storage977883604--input993071382-.out => Parisb- opcodes -ediv_mutez--storage977883604--input993071382-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -emit--storage125992234--input125992234-.out => Parisb- opcodes -emit--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -empty_map--storage457300675--input125992234-.out => Parisb- opcodes -empty_map--storage457300675--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -exec_concat--storage398998998--input246262487-.out => Parisb- opcodes -exec_concat--storage398998998--input246262487-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -exec_concat--storage398998998--input79230375-.out => Parisb- opcodes -exec_concat--storage398998998--input79230375-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -first--storage492856247--input478406404-.out => Parisb- opcodes -first--storage492856247--input478406404-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -first--storage492856247--input962874972-.out => Parisb- opcodes -first--storage492856247--input962874972-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage1026405794--input329240220-.out => Parisb- opcodes -get_and_update_map--storage1026405794--input329240220-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage382368661--input329240220-.out => Parisb- opcodes -get_and_update_map--storage382368661--input329240220-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage496578814--input329240220-.out => Parisb- opcodes -get_and_update_map--storage496578814--input329240220-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage496578814--input507231566-.out => Parisb- opcodes -get_and_update_map--storage496578814--input507231566-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage547821324--input329240220-.out => Parisb- opcodes -get_and_update_map--storage547821324--input329240220-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage796012494--input156280093-.out => Parisb- opcodes -get_and_update_map--storage796012494--input156280093-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_and_update_map--storage796012494--input228164856-.out => Parisb- opcodes -get_and_update_map--storage796012494--input228164856-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_map_value--storage139236239--input329240220-.out => Parisb- opcodes -get_map_value--storage139236239--input329240220-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_map_value--storage139236239--input79230375-.out => Parisb- opcodes -get_map_value--storage139236239--input79230375-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -get_map_value--storage329396864--input156280093-.out => Parisb- opcodes -get_map_value--storage329396864--input156280093-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -hash_key--storage921624073--input1040351577-.out => Parisb- opcodes -hash_key--storage921624073--input1040351577-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -hash_key--storage921624073--input153350004-.out => Parisb- opcodes -hash_key--storage921624073--input153350004-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -hash_string--storage151303925--input3431716-.out => Parisb- opcodes -hash_string--storage151303925--input3431716-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -hash_string--storage151303925--input535018041-.out => Parisb- opcodes -hash_string--storage151303925--input535018041-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -if--storage921624073--input570553153-.out => Parisb- opcodes -if--storage921624073--input570553153-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -if--storage921624073--input954397288-.out => Parisb- opcodes -if--storage921624073--input954397288-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -if_some--storage398998998--input288201633-.out => Parisb- opcodes -if_some--storage398998998--input288201633-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -if_some--storage398998998--input921624073-.out => Parisb- opcodes -if_some--storage398998998--input921624073-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -int--storage921624073--input453441034-.out => Parisb- opcodes -int--storage921624073--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -int--storage921624073--input535454136-.out => Parisb- opcodes -int--storage921624073--input535454136-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -int--storage921624073--input680650890-.out => Parisb- opcodes -int--storage921624073--input680650890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -keccak--storage921624073--input1008262038-.out => Parisb- opcodes -keccak--storage921624073--input1008262038-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -left_right--storage4177631--input202098045-.out => Parisb- opcodes -left_right--storage4177631--input202098045-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -left_right--storage4177631--input44576556-.out => Parisb- opcodes -left_right--storage4177631--input44576556-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -level--storage492856247--input125992234-.out => Parisb- opcodes -level--storage492856247--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_concat--storage717096222--input457300675-.out => Parisb- opcodes -list_concat--storage717096222--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_concat--storage717096222--input546523343-.out => Parisb- opcodes -list_concat--storage717096222--input546523343-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_concat_bytes--storage149262694--input220724351-.out => Parisb- opcodes -list_concat_bytes--storage149262694--input220724351-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_concat_bytes--storage149262694--input457300675-.out => Parisb- opcodes -list_concat_bytes--storage149262694--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_concat_bytes--storage65410082--input457300675-.out => Parisb- opcodes -list_concat_bytes--storage65410082--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_concat_bytes--storage726220441--input972761363-.out => Parisb- opcodes -list_concat_bytes--storage726220441--input972761363-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_id--storage528921618--input264787654-.out => Parisb- opcodes -list_id--storage528921618--input264787654-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_id--storage528921618--input457300675-.out => Parisb- opcodes -list_id--storage528921618--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_id--storage528921618--input656499821-.out => Parisb- opcodes -list_id--storage528921618--input656499821-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_id_map--storage528921618--input264787654-.out => Parisb- opcodes -list_id_map--storage528921618--input264787654-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_id_map--storage528921618--input457300675-.out => Parisb- opcodes -list_id_map--storage528921618--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_id_map--storage528921618--input656499821-.out => Parisb- opcodes -list_id_map--storage528921618--input656499821-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_iter--storage680650890--input568817463-.out => Parisb- opcodes -list_iter--storage680650890--input568817463-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_iter--storage680650890--input737923774-.out => Parisb- opcodes -list_iter--storage680650890--input737923774-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_map_block--storage907453363--input457300675-.out => Parisb- opcodes -list_map_block--storage907453363--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_map_block--storage907453363--input648737279-.out => Parisb- opcodes -list_map_block--storage907453363--input648737279-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_map_block--storage907453363--input908379154-.out => Parisb- opcodes -list_map_block--storage907453363--input908379154-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_size--storage492856247--input403499055-.out => Parisb- opcodes -list_size--storage492856247--input403499055-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_size--storage492856247--input457300675-.out => Parisb- opcodes -list_size--storage492856247--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_size--storage492856247--input469078912-.out => Parisb- opcodes -list_size--storage492856247--input469078912-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -list_size--storage492856247--input802622031-.out => Parisb- opcodes -list_size--storage492856247--input802622031-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -loop_left--storage528921618--input457300675-.out => Parisb- opcodes -loop_left--storage528921618--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -loop_left--storage528921618--input851203613-.out => Parisb- opcodes -loop_left--storage528921618--input851203613-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -lsl_bytes--storage125992234--input125992234-.out => Parisb- opcodes -lsl_bytes--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -lsr_bytes--storage125992234--input125992234-.out => Parisb- opcodes -lsr_bytes--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_id--storage457300675--input1027566226-.out => Parisb- opcodes -map_id--storage457300675--input1027566226-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_id--storage457300675--input276660554-.out => Parisb- opcodes -map_id--storage457300675--input276660554-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_id--storage457300675--input599923743-.out => Parisb- opcodes -map_id--storage457300675--input599923743-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_iter--storage1011138251--input403579222-.out => Parisb- opcodes -map_iter--storage1011138251--input403579222-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_iter--storage1011138251--input532072758-.out => Parisb- opcodes -map_iter--storage1011138251--input532072758-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_map--storage457300675--input798141440-.out => Parisb- opcodes -map_map--storage457300675--input798141440-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_map--storage794999348--input152441147-.out => Parisb- opcodes -map_map--storage794999348--input152441147-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_map--storage88008216--input798141440-.out => Parisb- opcodes -map_map--storage88008216--input798141440-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_nat--storage495706788--input453441034-.out => Parisb- opcodes -map_mem_nat--storage495706788--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_nat--storage56274299--input453441034-.out => Parisb- opcodes -map_mem_nat--storage56274299--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_nat--storage56274299--input564400327-.out => Parisb- opcodes -map_mem_nat--storage56274299--input564400327-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_nat--storage56274299--input654274102-.out => Parisb- opcodes -map_mem_nat--storage56274299--input654274102-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_nat--storage690637660--input453441034-.out => Parisb- opcodes -map_mem_nat--storage690637660--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_nat--storage806237530--input453441034-.out => Parisb- opcodes -map_mem_nat--storage806237530--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_string--storage109689253--input1071610051-.out => Parisb- opcodes -map_mem_string--storage109689253--input1071610051-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_string--storage109689253--input700475845-.out => Parisb- opcodes -map_mem_string--storage109689253--input700475845-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_string--storage109689253--input905318451-.out => Parisb- opcodes -map_mem_string--storage109689253--input905318451-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_string--storage495706788--input700475845-.out => Parisb- opcodes -map_mem_string--storage495706788--input700475845-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_string--storage915708427--input700475845-.out => Parisb- opcodes -map_mem_string--storage915708427--input700475845-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_mem_string--storage936682951--input905318451-.out => Parisb- opcodes -map_mem_string--storage936682951--input905318451-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_size--storage492856247--input15265129-.out => Parisb- opcodes -map_size--storage492856247--input15265129-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_size--storage492856247--input158311065-.out => Parisb- opcodes -map_size--storage492856247--input158311065-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_size--storage492856247--input456982702-.out => Parisb- opcodes -map_size--storage492856247--input456982702-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -map_size--storage492856247--input457300675-.out => Parisb- opcodes -map_size--storage492856247--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -mul--storage125992234--input125992234-.out => Parisb- opcodes -mul--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out => Parisb- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out => Parisb- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -neg--storage680650890--input1067298059-.out => Parisb- opcodes -neg--storage680650890--input1067298059-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -neg--storage680650890--input380029349-.out => Parisb- opcodes -neg--storage680650890--input380029349-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -neg--storage680650890--input563503226-.out => Parisb- opcodes -neg--storage680650890--input563503226-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -neg--storage680650890--input788662499-.out => Parisb- opcodes -neg--storage680650890--input788662499-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -neg--storage680650890--input972832189-.out => Parisb- opcodes -neg--storage680650890--input972832189-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -none--storage11179311--input125992234-.out => Parisb- opcodes -none--storage11179311--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not--storage921624073--input570553153-.out => Parisb- opcodes -not--storage921624073--input570553153-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not--storage921624073--input954397288-.out => Parisb- opcodes -not--storage921624073--input954397288-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input1051197453-.out => Parisb- opcodes -not_binary--storage921624073--input1051197453-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input123939249-.out => Parisb- opcodes -not_binary--storage921624073--input123939249-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input24243730-.out => Parisb- opcodes -not_binary--storage921624073--input24243730-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input518945720-.out => Parisb- opcodes -not_binary--storage921624073--input518945720-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input788662499-.out => Parisb- opcodes -not_binary--storage921624073--input788662499-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input906118781-.out => Parisb- opcodes -not_binary--storage921624073--input906118781-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input921874253-.out => Parisb- opcodes -not_binary--storage921624073--input921874253-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_binary--storage921624073--input972832189-.out => Parisb- opcodes -not_binary--storage921624073--input972832189-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -not_bytes--storage125992234--input125992234-.out => Parisb- opcodes -not_bytes--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or--storage921624073--input106930123-.out => Parisb- opcodes -or--storage921624073--input106930123-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or--storage921624073--input181204719-.out => Parisb- opcodes -or--storage921624073--input181204719-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or--storage921624073--input223774825-.out => Parisb- opcodes -or--storage921624073--input223774825-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or--storage921624073--input908807505-.out => Parisb- opcodes -or--storage921624073--input908807505-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_binary--storage921624073--input1056991424-.out => Parisb- opcodes -or_binary--storage921624073--input1056991424-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_binary--storage921624073--input375993021-.out => Parisb- opcodes -or_binary--storage921624073--input375993021-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_binary--storage921624073--input673240563-.out => Parisb- opcodes -or_binary--storage921624073--input673240563-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_binary--storage921624073--input747448890-.out => Parisb- opcodes -or_binary--storage921624073--input747448890-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_binary--storage921624073--input832403787-.out => Parisb- opcodes -or_binary--storage921624073--input832403787-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_binary--storage921624073--input858098961-.out => Parisb- opcodes -or_binary--storage921624073--input858098961-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -or_bytes--storage125992234--input125992234-.out => Parisb- opcodes -or_bytes--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -packunpack_rev--storage125992234--input305844558-.out => Parisb- opcodes -packunpack_rev--storage125992234--input305844558-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -packunpack_rev--storage125992234--input646365167-.out => Parisb- opcodes -packunpack_rev--storage125992234--input646365167-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out => Parisb- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out => Parisb- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -pair_id--storage921624073--input106930123-.out => Parisb- opcodes -pair_id--storage921624073--input106930123-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -pair_id--storage921624073--input181204719-.out => Parisb- opcodes -pair_id--storage921624073--input181204719-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -pair_id--storage921624073--input223774825-.out => Parisb- opcodes -pair_id--storage921624073--input223774825-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -pair_id--storage921624073--input908807505-.out => Parisb- opcodes -pair_id--storage921624073--input908807505-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -pexec--storage256947135--input1050356042-.out => Parisb- opcodes -pexec--storage256947135--input1050356042-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -pexec_2--storage197120858--input179371027-.out => Parisb- opcodes -pexec_2--storage197120858--input179371027-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -ret_int--storage921624073--input125992234-.out => Parisb- opcodes -ret_int--storage921624073--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -reverse--storage528921618--input457300675-.out => Parisb- opcodes -reverse--storage528921618--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -reverse--storage528921618--input851203613-.out => Parisb- opcodes -reverse--storage528921618--input851203613-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -reverse_loop--storage528921618--input457300675-.out => Parisb- opcodes -reverse_loop--storage528921618--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -reverse_loop--storage528921618--input851203613-.out => Parisb- opcodes -reverse_loop--storage528921618--input851203613-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -sapling_empty_state--storage457300675--input125992234-.out => Parisb- opcodes -sapling_empty_state--storage457300675--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -self_address--storage125992234--input125992234-.out => Parisb- opcodes -self_address--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out => Parisb- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -self_with_entrypoint--storage125992234--input289072903-.out => Parisb- opcodes -self_with_entrypoint--storage125992234--input289072903-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_car--storage224747103--input620760059-.out => Parisb- opcodes -set_car--storage224747103--input620760059-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_car--storage224747103--input717096222-.out => Parisb- opcodes -set_car--storage224747103--input717096222-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_car--storage224747103--input79230375-.out => Parisb- opcodes -set_car--storage224747103--input79230375-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_cdr--storage205576101--input654274102-.out => Parisb- opcodes -set_cdr--storage205576101--input654274102-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_cdr--storage224747103--input453441034-.out => Parisb- opcodes -set_cdr--storage224747103--input453441034-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_cdr--storage611418174--input967284912-.out => Parisb- opcodes -set_cdr--storage611418174--input967284912-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_id--storage457300675--input264787654-.out => Parisb- opcodes -set_id--storage457300675--input264787654-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_id--storage457300675--input457300675-.out => Parisb- opcodes -set_id--storage457300675--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_id--storage457300675--input989507347-.out => Parisb- opcodes -set_id--storage457300675--input989507347-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_iter--storage492856247--input457300675-.out => Parisb- opcodes -set_iter--storage492856247--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_iter--storage492856247--input701684511-.out => Parisb- opcodes -set_iter--storage492856247--input701684511-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_iter--storage492856247--input802622031-.out => Parisb- opcodes -set_iter--storage492856247--input802622031-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_member--storage495706788--input33757838-.out => Parisb- opcodes -set_member--storage495706788--input33757838-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_member--storage550087893--input79230375-.out => Parisb- opcodes -set_member--storage550087893--input79230375-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_member--storage605111220--input33757838-.out => Parisb- opcodes -set_member--storage605111220--input33757838-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_size--storage492856247--input403499055-.out => Parisb- opcodes -set_size--storage492856247--input403499055-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_size--storage492856247--input457300675-.out => Parisb- opcodes -set_size--storage492856247--input457300675-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_size--storage492856247--input469078912-.out => Parisb- opcodes -set_size--storage492856247--input469078912-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -set_size--storage492856247--input802622031-.out => Parisb- opcodes -set_size--storage492856247--input802622031-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -sha3--storage921624073--input1008262038-.out => Parisb- opcodes -sha3--storage921624073--input1008262038-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input115382786-.out => Parisb- opcodes -shifts--storage921624073--input115382786-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input271566295-.out => Parisb- opcodes -shifts--storage921624073--input271566295-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input340971987-.out => Parisb- opcodes -shifts--storage921624073--input340971987-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input374168553-.out => Parisb- opcodes -shifts--storage921624073--input374168553-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input413621582-.out => Parisb- opcodes -shifts--storage921624073--input413621582-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input424849461-.out => Parisb- opcodes -shifts--storage921624073--input424849461-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input485030042-.out => Parisb- opcodes -shifts--storage921624073--input485030042-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input705767726-.out => Parisb- opcodes -shifts--storage921624073--input705767726-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input769385932-.out => Parisb- opcodes -shifts--storage921624073--input769385932-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -shifts--storage921624073--input913715337-.out => Parisb- opcodes -shifts--storage921624073--input913715337-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage351480851--input65907686-.out => Parisb- opcodes -slice--storage351480851--input65907686-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage364922380--input198821575-.out => Parisb- opcodes -slice--storage364922380--input198821575-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage364922380--input359592843-.out => Parisb- opcodes -slice--storage364922380--input359592843-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage364922380--input551316239-.out => Parisb- opcodes -slice--storage364922380--input551316239-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage364922380--input722749044-.out => Parisb- opcodes -slice--storage364922380--input722749044-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage364922380--input839234860-.out => Parisb- opcodes -slice--storage364922380--input839234860-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage364922380--input919180079-.out => Parisb- opcodes -slice--storage364922380--input919180079-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice--storage921624073--input551316239-.out => Parisb- opcodes -slice--storage921624073--input551316239-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input198821575-.out => Parisb- opcodes -slice_bytes--storage229749865--input198821575-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input462551352-.out => Parisb- opcodes -slice_bytes--storage229749865--input462551352-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input489157380-.out => Parisb- opcodes -slice_bytes--storage229749865--input489157380-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input551316239-.out => Parisb- opcodes -slice_bytes--storage229749865--input551316239-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input669330759-.out => Parisb- opcodes -slice_bytes--storage229749865--input669330759-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input743596105-.out => Parisb- opcodes -slice_bytes--storage229749865--input743596105-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage229749865--input839234860-.out => Parisb- opcodes -slice_bytes--storage229749865--input839234860-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage504917929--input65907686-.out => Parisb- opcodes -slice_bytes--storage504917929--input65907686-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -slice_bytes--storage921624073--input462551352-.out => Parisb- opcodes -slice_bytes--storage921624073--input462551352-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -str_id--storage921624073--input1016369050-.out => Parisb- opcodes -str_id--storage921624073--input1016369050-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -str_id--storage921624073--input93477117-.out => Parisb- opcodes -str_id--storage921624073--input93477117-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out => Parisb- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out => Parisb- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out => Parisb- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -tez_add_sub--storage921624073--input706350605-.out => Parisb- opcodes -tez_add_sub--storage921624073--input706350605-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -tez_add_sub--storage921624073--input856198194-.out => Parisb- opcodes -tez_add_sub--storage921624073--input856198194-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -uncomb--storage680650890--input394061083-.out => Parisb- opcodes -uncomb--storage680650890--input394061083-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -unpair--storage125992234--input125992234-.out => Parisb- opcodes -unpair--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -voting_power--storage1011138251--input1040351577-.out => Parisb- opcodes -voting_power--storage1011138251--input1040351577-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input1058477720-.out => Parisb- opcodes -xor--storage921624073--input1058477720-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input1073176155-.out => Parisb- opcodes -xor--storage921624073--input1073176155-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input246594902-.out => Parisb- opcodes -xor--storage921624073--input246594902-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input506603577-.out => Parisb- opcodes -xor--storage921624073--input506603577-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input576248088-.out => Parisb- opcodes -xor--storage921624073--input576248088-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input612012282-.out => Parisb- opcodes -xor--storage921624073--input612012282-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input617591686-.out => Parisb- opcodes -xor--storage921624073--input617591686-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input639311176-.out => Parisb- opcodes -xor--storage921624073--input639311176-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input688315180-.out => Parisb- opcodes -xor--storage921624073--input688315180-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor--storage921624073--input967929605-.out => Parisb- opcodes -xor--storage921624073--input967929605-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- opcodes -xor_bytes--storage125992234--input125992234-.out => Parisb- opcodes -xor_bytes--storage125992234--input125992234-.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- BALANCE.out => Parisb- test Michelson opcodes- BALANCE.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- LEVEL.out => Parisb- test Michelson opcodes- LEVEL.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- NOW.out => Parisb- test Michelson opcodes- NOW.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- arithmetic_overflow.out => Parisb- test Michelson opcodes- arithmetic_overflow.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- big_map_contract_io.out => Parisb- test Michelson opcodes- big_map_contract_io.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- check_signature.out => Parisb- test Michelson opcodes- check_signature.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- hash_consistency.out => Parisb- test Michelson opcodes- hash_consistency.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- map_map_side_effect.out => Parisb- test Michelson opcodes- map_map_side_effect.out} (100%) rename tezt/tests/expected/contract_opcodes.ml/{Paris- test Michelson opcodes- pack_unpack.out => Parisb- test Michelson opcodes- pack_unpack.out} (100%) create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input254251340-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input420401245-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input680650890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input249636002-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input267363182-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input438561129-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input249636002-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input307538219-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input373737581-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -address--storage921624073--input117475800-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input106930123-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input181204719-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input223774825-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input908807505-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_binary--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_bytes--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input106930123-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input181204719-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input223774825-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input908807505-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -balance--storage492856247--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage495706788--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input564400327-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input654274102-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage690637660--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage806237530--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input1071610051-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input700475845-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input905318451-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage495706788--input700475845-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage915708427--input700475845-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage936682951--input905318451-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_int--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_nat--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -car--storage680650890--input783124233-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cdr--storage680650890--input783124233-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage109160754--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage921624073--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage981066851--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb--storage950292965--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-get--storage125992234--input186507116-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set--storage186507116--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set-2--storage921624073--input186507116-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -compare--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comparisons--storage457300675--input281780712-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input392583650-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input640104625-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input354091714-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input441061063-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input264787654-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input316676251-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage457300675--input798141440-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage581876226--input166122047-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage793461282--input781487591-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input315650912-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input51111414-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input545734274-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input772794967-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input917967660-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input964818218-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contract--storage125992234--input117475800-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -create_contract--storage921624073--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1011138251-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1018564342-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1031049988-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input685590443-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input246866101-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input26856104-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dign--storage680650890--input529388602-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input590117173-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input850887554-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dipn--storage680650890--input529388602-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dropn--storage680650890--input529388602-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dugn--storage680650890--input529388602-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dup-n--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input247451205-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input250545589-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input79625541-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input147133089-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input215785357-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input389351431-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input44513000-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input635398196-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input734264738-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input993071382-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -emit--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -empty_map--storage457300675--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input246262487-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input79230375-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input478406404-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input962874972-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage1026405794--input329240220-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage382368661--input329240220-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input329240220-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input507231566-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage547821324--input329240220-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input156280093-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input228164856-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input329240220-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input79230375-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage329396864--input156280093-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input1040351577-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input153350004-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input3431716-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input535018041-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input570553153-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input954397288-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input288201633-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input921624073-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input535454136-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input680650890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -keccak--storage921624073--input1008262038-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input202098045-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input44576556-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -level--storage492856247--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input546523343-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input220724351-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage65410082--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage726220441--input972761363-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input264787654-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input656499821-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input264787654-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input656499821-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input568817463-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input737923774-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input648737279-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input908379154-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input403499055-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input469078912-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input802622031-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input851203613-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsl_bytes--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsr_bytes--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input1027566226-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input276660554-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input599923743-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input403579222-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input532072758-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage457300675--input798141440-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage794999348--input152441147-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage88008216--input798141440-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage495706788--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input564400327-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input654274102-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage690637660--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage806237530--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input1071610051-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input700475845-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input905318451-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage495706788--input700475845-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage915708427--input700475845-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage936682951--input905318451-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input15265129-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input158311065-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input456982702-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mul--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input1067298059-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input380029349-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input563503226-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input788662499-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input972832189-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -none--storage11179311--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input570553153-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input954397288-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input1051197453-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input123939249-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input24243730-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input518945720-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input788662499-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input906118781-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input921874253-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input972832189-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_bytes--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input106930123-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input181204719-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input223774825-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input908807505-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input1056991424-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input375993021-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input673240563-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input747448890-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input832403787-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input858098961-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_bytes--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input305844558-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input646365167-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input106930123-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input181204719-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input223774825-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input908807505-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec--storage256947135--input1050356042-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec_2--storage197120858--input179371027-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ret_int--storage921624073--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input851203613-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input851203613-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sapling_empty_state--storage457300675--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_address--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_entrypoint--storage125992234--input289072903-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input620760059-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input717096222-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input79230375-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage205576101--input654274102-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage224747103--input453441034-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage611418174--input967284912-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input264787654-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input989507347-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input701684511-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input802622031-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage495706788--input33757838-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage550087893--input79230375-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage605111220--input33757838-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input403499055-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input457300675-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input469078912-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input802622031-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sha3--storage921624073--input1008262038-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input115382786-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input271566295-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input340971987-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input374168553-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input413621582-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input424849461-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input485030042-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input705767726-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input769385932-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input913715337-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage351480851--input65907686-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input198821575-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input359592843-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input551316239-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input722749044-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input839234860-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input919180079-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage921624073--input551316239-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input198821575-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input462551352-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input489157380-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input551316239-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input669330759-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input743596105-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input839234860-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage504917929--input65907686-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage921624073--input462551352-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input1016369050-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input93477117-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input706350605-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input856198194-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -uncomb--storage680650890--input394061083-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -unpair--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -voting_power--storage1011138251--input1040351577-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1058477720-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1073176155-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input246594902-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input506603577-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input576248088-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input612012282-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input617591686-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input639311176-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input688315180-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input967929605-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor_bytes--storage125992234--input125992234-.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- BALANCE.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- LEVEL.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- NOW.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- arithmetic_overflow.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- big_map_contract_io.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- check_signature.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- hash_consistency.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- map_map_side_effect.out create mode 100644 tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- pack_unpack.out rename tezt/tests/expected/contract_typecheck_regression.ml/{Paris- Tc scripts.out => Parisb- Tc scripts.out} (100%) create mode 100644 tezt/tests/expected/contract_typecheck_regression.ml/Parisc- Tc scripts.out rename tezt/tests/expected/create_contract.ml/{Paris- Create contract.out => Parisb- Create contract.out} (100%) create mode 100644 tezt/tests/expected/create_contract.ml/Parisc- Create contract.out rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test Coordinator-s post preimage).out => Parisb- Testing Full DAC infrastructure (test Coordinator-s post preimage).out} (100%) rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test GET v0-certificate).out => Parisb- Testing Full DAC infrastructure (test GET v0-certificate).out} (100%) rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test GET v0-missing_page).out => Parisb- Testing Full DAC infrastructure (test GET v0-missing_page).out} (100%) rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out => Parisb- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out} (100%) rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out => Parisb- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out} (100%) rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test GET v0-preimage).out => Parisb- Testing Full DAC infrastructure (test GET v0-preimage).out} (100%) rename tezt/tests/expected/dac.ml/{Paris- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out => Parisb- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out} (100%) create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test Coordinator-s post preimage).out create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-certificate).out create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-missing_page).out create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-preimage).out create mode 100644 tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out rename tezt/tests/expected/dal.ml/{Paris- Test following dal and baker tutorial commands.out => Parisb- Test following dal and baker tutorial commands.out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL L1 integration (Use all available slots).out => Parisb- Testing DAL L1 integration (Use all available slots).out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out => Parisb- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out => Parisb- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL rollup and node with L1 (test echo_kernel).out => Parisb- Testing DAL rollup and node with L1 (test echo_kernel).out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec wa.out => Parisb- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL rollup and node with L1 (test tx_kernel).out => Parisb- Testing DAL rollup and node with L1 (test tx_kernel).out} (100%) rename tezt/tests/expected/dal.ml/{Paris- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slots.out => Parisb- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out} (100%) create mode 100644 tezt/tests/expected/dal.ml/Parisc- Test following dal and baker tutorial commands.out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL L1 integration (Use all available slots).out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test echo_kernel).out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test tx_kernel).out create mode 100644 tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out rename tezt/tests/expected/deposits_limit.ml/{Paris- set deposits limit.out => Parisb- set deposits limit.out} (100%) rename tezt/tests/expected/deposits_limit.ml/{Paris- unset deposits limit.out => Parisb- unset deposits limit.out} (100%) create mode 100644 tezt/tests/expected/deposits_limit.ml/Parisc- set deposits limit.out create mode 100644 tezt/tests/expected/deposits_limit.ml/Parisc- unset deposits limit.out rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- block_header.out => Parisb- protocol encoding regression test- block_header.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- block_header.raw.out => Parisb- protocol encoding regression test- block_header.raw.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- block_header.unsigned.out => Parisb- protocol encoding regression test- block_header.unsigned.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- contract.out => Parisb- protocol encoding regression test- contract.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- cycle.out => Parisb- protocol encoding regression test- cycle.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- fitness.out => Parisb- protocol encoding regression test- fitness.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- gas.cost.out => Parisb- protocol encoding regression test- gas.cost.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- gas.out => Parisb- protocol encoding regression test- gas.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- level.out => Parisb- protocol encoding regression test- level.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- nonce.out => Parisb- protocol encoding regression test- nonce.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- operation.internal.out => Parisb- protocol encoding regression test- operation.internal.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- operation.out => Parisb- protocol encoding regression test- operation.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- operation.raw.out => Parisb- protocol encoding regression test- operation.raw.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- operation.unsigned.out => Parisb- protocol encoding regression test- operation.unsigned.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- operation_with_legacy.out => Parisb- protocol encoding regression test- operation_with_legacy.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- operation_with_legacy.unsigned.out => Parisb- protocol encoding regression test- operation_with_legacy.unsigned.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- period.out => Parisb- protocol encoding regression test- period.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- raw_level.out => Parisb- protocol encoding regression test- raw_level.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- seed.out => Parisb- protocol encoding regression test- seed.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- tez.out => Parisb- protocol encoding regression test- tez.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- timestamp.out => Parisb- protocol encoding regression test- timestamp.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- vote.ballot.out => Parisb- protocol encoding regression test- vote.ballot.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- vote.ballots.out => Parisb- protocol encoding regression test- vote.ballots.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- vote.listings.out => Parisb- protocol encoding regression test- vote.listings.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- voting_period.kind.out => Parisb- protocol encoding regression test- voting_period.kind.out} (100%) rename tezt/tests/expected/encoding.ml/{Paris- protocol encoding regression test- voting_period.out => Parisb- protocol encoding regression test- voting_period.out} (100%) create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.raw.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.unsigned.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- contract.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- cycle.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- fitness.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.cost.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- level.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- nonce.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.internal.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.raw.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.unsigned.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.unsigned.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- period.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- raw_level.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- seed.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- tez.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- timestamp.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballot.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballots.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.listings.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.kind.out create mode 100644 tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.out rename tezt/tests/expected/hash_data.ml/{Paris- hash data ... of type ... (bad).out => Parisb- hash data ... of type ... (bad).out} (100%) rename tezt/tests/expected/hash_data.ml/{Paris- hash data ... of type ... (good).out => Parisb- hash data ... of type ... (good).out} (100%) create mode 100644 tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (bad).out create mode 100644 tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (good).out rename tezt/tests/expected/increase_paid_storage.ml/{Paris- increase paid storage.out => Parisb- increase paid storage.out} (100%) create mode 100644 tezt/tests/expected/increase_paid_storage.ml/Parisc- increase paid storage.out rename tezt/tests/expected/normalize.ml/{Paris- Test Michelson stack normalization.out => Parisb- Test Michelson stack normalization.out} (100%) rename tezt/tests/expected/normalize.ml/{Paris- Test normalize in unparsing mode.out => Parisb- Test normalize in unparsing mode.out} (100%) rename tezt/tests/expected/normalize.ml/{Paris- Test normalize script.out => Parisb- Test normalize script.out} (100%) rename tezt/tests/expected/normalize.ml/{Paris- Test normalize type.out => Parisb- Test normalize type.out} (100%) rename tezt/tests/expected/normalize.ml/{Paris- Test normalize with legacy flag.out => Parisb- Test normalize with legacy flag.out} (100%) create mode 100644 tezt/tests/expected/normalize.ml/Parisc- Test Michelson stack normalization.out create mode 100644 tezt/tests/expected/normalize.ml/Parisc- Test normalize in unparsing mode.out create mode 100644 tezt/tests/expected/normalize.ml/Parisc- Test normalize script.out create mode 100644 tezt/tests/expected/normalize.ml/Parisc- Test normalize type.out create mode 100644 tezt/tests/expected/normalize.ml/Parisc- Test normalize with legacy flag.out rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - RPC API should work and be stable.out => Parisb- arith - RPC API should work and be stable.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - Whitelisted staker can publish a commitment.out => Parisb- arith - Whitelisted staker can publish a commitment.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - boot sector is evaluated.out => Parisb- arith - boot sector is evaluated.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - origination of a SCORU executes without error.out => Parisb- arith - origination of a SCORU executes without error.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - participant of a refutation game are slashed-rewarded.out => Parisb- arith - participant of a refutation game are slashed-rewarded.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - recover bond of stakers.out => Parisb- arith - recover bond of stakers.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (degraded_new).out => Parisb- arith - refutation games winning strategies (degraded_new).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (degraded_ongoing).out => Parisb- arith - refutation games winning strategies (degraded_ongoing).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (inbox_proof).out => Parisb- arith - refutation games winning strategies (inbox_proof).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (inbox_proof_at_genesis).out => Parisb- arith - refutation games winning strategies (inbox_proof_at_genesis).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (inbox_proof_many_empty_level.out => Parisb- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (inbox_proof_one_empty_level).out => Parisb- arith - refutation games winning strategies (inbox_proof_one_empty_level.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (inbox_proof_with_new_content.out => Parisb- arith - refutation games winning strategies (inbox_proof_with_new_conten.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (pvm_proof_0).out => Parisb- arith - refutation games winning strategies (pvm_proof_0).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (pvm_proof_1).out => Parisb- arith - refutation games winning strategies (pvm_proof_1).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (pvm_proof_2).out => Parisb- arith - refutation games winning strategies (pvm_proof_2).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (pvm_proof_3).out => Parisb- arith - refutation games winning strategies (pvm_proof_3).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (pvm_proof_at_genesis).out => Parisb- arith - refutation games winning strategies (pvm_proof_at_genesis).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (pvm_proof_second_period).out => Parisb- arith - refutation games winning strategies (pvm_proof_second_period).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (reset_honest_during_game).out => Parisb- arith - refutation games winning strategies (reset_honest_during_game).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- arith - refutation games winning strategies (timeout).out => Parisb- arith - refutation games winning strategies (timeout).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - RPC API should work and be stable.out => Parisb- wasm_2_0_0 - RPC API should work and be stable.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - origination of a SCORU executes without error.out => Parisb- wasm_2_0_0 - origination of a SCORU executes without error.out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out => Parisb- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out => Parisb- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out => Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out => Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out => Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out => Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out} (100%) rename tezt/tests/expected/sc_rollup.ml/{Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_period.out => Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out} (100%) create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - RPC API should work and be stable.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - Whitelisted staker can publish a commitment.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - boot sector is evaluated.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - origination of a SCORU executes without error.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - participant of a refutation game are slashed-rewarded.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - recover bond of stakers.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_new).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_ongoing).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_at_genesis).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_one_empty_level.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_with_new_conten.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_0).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_1).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_2).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_3).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_at_genesis).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_second_period).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (reset_honest_during_game).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (timeout).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - RPC API should work and be stable.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - origination of a SCORU executes without error.out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out create mode 100644 tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out rename tezt/tests/expected/script_hash_regression.ml/{Paris- Test script hash regression.out => Parisb- Test script hash regression.out} (100%) create mode 100644 tezt/tests/expected/script_hash_regression.ml/Parisc- Test script hash regression.out rename tezt/tests/expected/self_address_transfer.ml/{Paris- Self address transfer.out => Parisb- Self address transfer.out} (100%) create mode 100644 tezt/tests/expected/self_address_transfer.ml/Parisc- Self address transfer.out rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out => Parisb- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- fr- add.out => Parisb- Bls12_381 contract primitives- fr- add.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- fr- mul.out => Parisb- Bls12_381 contract primitives- fr- mul.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- fr- negate.out => Parisb- Bls12_381 contract primitives- fr- negate.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- fr- store.out => Parisb- Bls12_381 contract primitives- fr- store.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g1- add.out => Parisb- Bls12_381 contract primitives- g1- add.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g1- mul.out => Parisb- Bls12_381 contract primitives- g1- mul.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g1- negate.out => Parisb- Bls12_381 contract primitives- g1- negate.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g1- store.out => Parisb- Bls12_381 contract primitives- g1- store.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g2- add.out => Parisb- Bls12_381 contract primitives- g2- add.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g2- mul.out => Parisb- Bls12_381 contract primitives- g2- mul.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g2- negate.out => Parisb- Bls12_381 contract primitives- g2- negate.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- g2- store.out => Parisb- Bls12_381 contract primitives- g2- store.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- pairing_check empty.out => Parisb- Bls12_381 contract primitives- pairing_check empty.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- pairing_check(neg- pos).out => Parisb- Bls12_381 contract primitives- pairing_check(neg- pos).out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- pairing_check(pos- neg).out => Parisb- Bls12_381 contract primitives- pairing_check(pos- neg).out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- pairing_check(pos- pos).out => Parisb- Bls12_381 contract primitives- pairing_check(pos- pos).out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- signature_aggregation.out => Parisb- Bls12_381 contract primitives- signature_aggregation.out} (100%) rename tezt/tests/expected/test_contract_bls12_381.ml/{Paris- Bls12_381 contract primitives- test_groth16.out => Parisb- Bls12_381 contract primitives- test_groth16.out} (100%) create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- add.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- mul.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- negate.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- store.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- add.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- mul.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- negate.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- store.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- add.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- mul.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- negate.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- store.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check empty.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(neg- pos).out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- neg).out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- pos).out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- signature_aggregation.out create mode 100644 tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- test_groth16.out rename tezt/tests/expected/ticket_receipt_and_rpc.ml/{Paris- Ticket updates in receipt.out => Parisb- Ticket updates in receipt.out} (100%) create mode 100644 tezt/tests/expected/ticket_receipt_and_rpc.ml/Parisc- Ticket updates in receipt.out rename tezt/tests/expected/tickets.ml/{Paris- Create and remove tickets.out => Parisb- Create and remove tickets.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Minting then sending tickets to smart-contract rollup should succeed with.out => Parisb- Minting then sending tickets to smart-contract rollup should succeed wit.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Overdrafting ticket from implicit accounts must be rejected.out => Parisb- Overdrafting ticket from implicit accounts must be rejected.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets between originated contracts and implicit accounts.out => Parisb- Send tickets between originated contracts and implicit accounts.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets from contracts to implicit accounts with some Tez along.out => Parisb- Send tickets from contracts to implicit accounts with some Tez along.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets from contracts to implicit accounts with the wrong type must.out => Parisb- Send tickets from contracts to implicit accounts with the wrong type mus.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets from contracts to implicit accounts.out => Parisb- Send tickets from contracts to implicit accounts.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets in bigmap.out => Parisb- Send tickets in bigmap.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets with Ticket constructor (with complex parameters) from impli.out => Parisb- Send tickets with Ticket constructor (with complex parameters) from impl.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Send tickets with Ticket constructor from implicit account to originated .out => Parisb- Send tickets with Ticket constructor from implicit account to originated.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Sending ticket from contract storage to implicit accounts.out => Parisb- Sending ticket from contract storage to implicit accounts.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Sending ticket of wrong type from implicit accounts must be rejected.out => Parisb- Sending ticket of wrong type from implicit accounts must be rejected.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Sending tickets from storage to smart-contract rollup should succeed with.out => Parisb- Sending tickets from storage to smart-contract rollup should succeed wit.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Sending tickets to either implicit accounts or originated contracts accep.out => Parisb- Sending tickets to either implicit accounts or originated contracts acce.out} (100%) rename tezt/tests/expected/tickets.ml/{Paris- Sending zero ticket from implicit accounts must be rejected.out => Parisb- Sending zero ticket from implicit accounts must be rejected.out} (100%) create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Create and remove tickets.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Minting then sending tickets to smart-contract rollup should succeed wit.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Overdrafting ticket from implicit accounts must be rejected.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets between originated contracts and implicit accounts.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with some Tez along.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with the wrong type mus.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets in bigmap.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor (with complex parameters) from impl.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor from implicit account to originated.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Sending ticket from contract storage to implicit accounts.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Sending ticket of wrong type from implicit accounts must be rejected.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Sending tickets from storage to smart-contract rollup should succeed wit.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Sending tickets to either implicit accounts or originated contracts acce.out create mode 100644 tezt/tests/expected/tickets.ml/Parisc- Sending zero ticket from implicit accounts must be rejected.out rename tezt/tests/expected/tx_sc_rollup.ml/{Paris- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out => Parisb- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out} (100%) create mode 100644 tezt/tests/expected/tx_sc_rollup.ml/Parisc- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out rename tezt/tests/expected/tzt_regression.ml/{Paris- Run TZT.out => Parisb- Run TZT.out} (100%) create mode 100644 tezt/tests/expected/tzt_regression.ml/Parisc- Run TZT.out rename tezt/tests/expected/views.ml/{Paris- Run views.out => Parisb- Run views.out} (100%) create mode 100644 tezt/tests/expected/views.ml/Parisc- Run views.out diff --git a/etherlink/tezt/tests/expected/evm_rollup.ml/Paris- Regression test for L2 block hash.out b/etherlink/tezt/tests/expected/evm_rollup.ml/Parisb- Regression test for L2 block hash.out similarity index 100% rename from etherlink/tezt/tests/expected/evm_rollup.ml/Paris- Regression test for L2 block hash.out rename to etherlink/tezt/tests/expected/evm_rollup.ml/Parisb- Regression test for L2 block hash.out diff --git a/etherlink/tezt/tests/expected/evm_rollup.ml/Parisc- Regression test for L2 block hash.out b/etherlink/tezt/tests/expected/evm_rollup.ml/Parisc- Regression test for L2 block hash.out new file mode 100644 index 000000000000..f73ffd34cf9d --- /dev/null +++ b/etherlink/tezt/tests/expected/evm_rollup.ml/Parisc- Regression test for L2 block hash.out @@ -0,0 +1 @@ +Block hash: 0x966e2c6d2f99bbb94d76962fcb3e9f778c7635d3bab446720d587a31db5dd990 diff --git a/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out b/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out index 90289f0dbfc6..31ecb36f11ab 100644 --- a/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out +++ b/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out @@ -5,10 +5,12 @@ failed_migration: etherlink/kernel_evm/kernel/tests/resources/failed_migration.w ghostnet_evm_kernel: etherlink/kernel_evm/kernel/tests/resources/ghostnet_evm_kernel.wasm evm_kernel: evm_kernel.wasm accuser_proxford: octez-accuser-Proxford +accuser_psparisc: octez-accuser-PsParisC accuser_ptparisb: octez-accuser-PtParisB accuser_alpha: octez-accuser-alpha admin_client: octez-admin-client baker_proxford: octez-baker-Proxford +baker_psparisc: octez-baker-PsParisC baker_ptparisb: octez-baker-PtParisB baker_alpha: octez-baker-alpha client: octez-client diff --git a/tezt/tests/encoding_samples/parisb/block_header.raw/block_header.raw.sample.json b/tezt/tests/encoding_samples/parisb/block_header.raw/block_header.raw.sample.json new file mode 100644 index 000000000000..221910309fe0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/block_header.raw/block_header.raw.sample.json @@ -0,0 +1,11 @@ +{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "protocol_data": "521d101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" +} diff --git a/tezt/tests/encoding_samples/parisb/block_header.unsigned/block_header.unsigned.sample.json b/tezt/tests/encoding_samples/parisb/block_header.unsigned/block_header.unsigned.sample.json new file mode 100644 index 000000000000..d454af6287b8 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/block_header.unsigned/block_header.unsigned.sample.json @@ -0,0 +1,19 @@ +{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 +} diff --git a/tezt/tests/encoding_samples/parisb/block_header/block_header.sample.json b/tezt/tests/encoding_samples/parisb/block_header/block_header.sample.json new file mode 100644 index 000000000000..444f1b31de7e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/block_header/block_header.sample.json @@ -0,0 +1,20 @@ +{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 +} diff --git a/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-alloc.sample.json b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-alloc.sample.json new file mode 100644 index 000000000000..b114496b7578 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-alloc.sample.json @@ -0,0 +1,10 @@ +[{ + "action": "alloc", + "big_map": "0", + "key_type": [{ + "prim": "nat" + }], + "value_type": [{ + "prim": "unit" + }] +}] diff --git a/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-copy.sample.json b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-copy.sample.json new file mode 100644 index 000000000000..5f43f0cecfc5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-copy.sample.json @@ -0,0 +1,5 @@ +[{ + "action": "copy", + "source_big_map": "0", + "destination_big_map": "1" +}] diff --git a/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-remove.sample.json b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-remove.sample.json new file mode 100644 index 000000000000..f654587236f4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-remove.sample.json @@ -0,0 +1,4 @@ +[{ + "action": "remove", + "big_map": "0" +}] diff --git a/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-update.sample.json b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-update.sample.json new file mode 100644 index 000000000000..1b129b22c4e5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/contract.big_map_diff/big_map_diff-update.sample.json @@ -0,0 +1,11 @@ +[{ + "action": "update", + "big_map": "0", + "key_hash": "exprv6UsC1sN3Fk2XfgcJCL8NCerP5rCGy1PRESZAqr7L2JdzX55EN", + "key": [{ + "int": "1" + }], + "value": [{ + "prim": "UNIT" + }] +}] diff --git a/tezt/tests/encoding_samples/parisb/contract/contract-implicit.sample.json b/tezt/tests/encoding_samples/parisb/contract/contract-implicit.sample.json new file mode 100644 index 000000000000..27b113be04b2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/contract/contract-implicit.sample.json @@ -0,0 +1 @@ +"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" diff --git a/tezt/tests/encoding_samples/parisb/contract/contract-originated.sample.json b/tezt/tests/encoding_samples/parisb/contract/contract-originated.sample.json new file mode 100644 index 000000000000..72ab1777f3a7 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/contract/contract-originated.sample.json @@ -0,0 +1 @@ +"KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat" diff --git a/tezt/tests/encoding_samples/parisb/cycle/cycle-positive.sample.json b/tezt/tests/encoding_samples/parisb/cycle/cycle-positive.sample.json new file mode 100644 index 000000000000..a51fa7d1efef --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/cycle/cycle-positive.sample.json @@ -0,0 +1 @@ +2147483647 diff --git a/tezt/tests/encoding_samples/parisb/cycle/cycle-zero.sample.json b/tezt/tests/encoding_samples/parisb/cycle/cycle-zero.sample.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/cycle/cycle-zero.sample.json @@ -0,0 +1 @@ +0 diff --git a/tezt/tests/encoding_samples/parisb/fitness/fitness.sample.json b/tezt/tests/encoding_samples/parisb/fitness/fitness.sample.json new file mode 100644 index 000000000000..56ae2f8d6f07 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/fitness/fitness.sample.json @@ -0,0 +1 @@ +{"level": 1, "locked_round": 1, "predecessor_round": 1, "round": 2} diff --git a/tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-positive.sample.json b/tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-positive.sample.json new file mode 100644 index 000000000000..0e55e062cab5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-positive.sample.json @@ -0,0 +1 @@ +"8920392083423078" diff --git a/tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-zero.sample.json b/tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/gas.cost/gas.cost-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisb/gas/gas-positive.sample.json b/tezt/tests/encoding_samples/parisb/gas/gas-positive.sample.json new file mode 100644 index 000000000000..94715b79899c --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/gas/gas-positive.sample.json @@ -0,0 +1 @@ +"1238" diff --git a/tezt/tests/encoding_samples/parisb/gas/gas-unaccounted.sample.json b/tezt/tests/encoding_samples/parisb/gas/gas-unaccounted.sample.json new file mode 100644 index 000000000000..839f1ecf5a57 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/gas/gas-unaccounted.sample.json @@ -0,0 +1 @@ +"unaccounted" diff --git a/tezt/tests/encoding_samples/parisb/gas/gas-zero.sample.json b/tezt/tests/encoding_samples/parisb/gas/gas-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/gas/gas-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisb/level/level.sample.json b/tezt/tests/encoding_samples/parisb/level/level.sample.json new file mode 100644 index 000000000000..9a8e74b082e7 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/level/level.sample.json @@ -0,0 +1,7 @@ +{ + "level": 1331, + "level_position": 2147483647, + "cycle": 300, + "cycle_position": 600, + "expected_commitment": true +} diff --git a/tezt/tests/encoding_samples/parisb/nonce/nonce.sample.json b/tezt/tests/encoding_samples/parisb/nonce/nonce.sample.json new file mode 100644 index 000000000000..ca23c3b6a461 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/nonce/nonce.sample.json @@ -0,0 +1 @@ +"0000000000000000000000000000000000000000000000000000000000000000" diff --git a/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..e26fb0179e4e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation-withdrawal.sample.json @@ -0,0 +1,5 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "delegation" +} diff --git a/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation.sample.json b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation.sample.json new file mode 100644 index 000000000000..4bc7ec935564 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-delegation.sample.json @@ -0,0 +1,6 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "delegation", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" +} diff --git a/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-origination.sample.json b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-origination.sample.json new file mode 100644 index 000000000000..b176be7dba11 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-origination.sample.json @@ -0,0 +1,48 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "origination", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } +} diff --git a/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..d1dc4108ad5d --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-implicit.sample.json @@ -0,0 +1,7 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 3, + "kind": "transaction", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" +} diff --git a/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-originated.sample.json new file mode 100644 index 000000000000..e43cfd06b7bb --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.internal/operation.internal-transaction-to-originated.sample.json @@ -0,0 +1,13 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "transaction", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } +} diff --git a/tezt/tests/encoding_samples/parisb/operation.raw/operation.raw.sample.json b/tezt/tests/encoding_samples/parisb/operation.raw/operation.raw.sample.json new file mode 100644 index 000000000000..9f8e4f094af1 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.raw/operation.raw.sample.json @@ -0,0 +1,4 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "data": "000000053366804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-activate-account.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-activate-account.sample.json new file mode 100644 index 000000000000..6e0f40dd83fc --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-activate-account.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-attestation.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-attestation.sample.json new file mode 100644 index 000000000000..b28f47358ec6 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-attestation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-ballot.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-ballot.sample.json new file mode 100644 index 000000000000..c272cedc4f20 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-ballot.sample.json @@ -0,0 +1,10 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..5e3eaa739a99 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation.sample.json new file mode 100644 index 000000000000..401bed1ed6a2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-delegation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json new file mode 100644 index 000000000000..884957c25aed --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_attestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json new file mode 100644 index 000000000000..646e53384099 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json @@ -0,0 +1,46 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json new file mode 100644 index 000000000000..8aa1305a50e3 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preattestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-origination.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-origination.sample.json new file mode 100644 index 000000000000..e3937027e89c --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-origination.sample.json @@ -0,0 +1,54 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-preaatestation.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-preaatestation.sample.json new file mode 100644 index 000000000000..e65a1f2095b9 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-preaatestation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-proposals.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-proposals.sample.json new file mode 100644 index 000000000000..ee628b836024 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-proposals.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-reveal.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-reveal.sample.json new file mode 100644 index 000000000000..b2bd1b78e79f --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-reveal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..3f5b02050587 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..6a22e4a8afa3 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json new file mode 100644 index 000000000000..d376b224eb7a --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json @@ -0,0 +1,19 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-activate-account.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-activate-account.sample.json new file mode 100644 index 000000000000..db9a00a60009 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-activate-account.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-attestation.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-attestation.sample.json new file mode 100644 index 000000000000..fa6ebd461571 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-attestation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-ballot.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-ballot.sample.json new file mode 100644 index 000000000000..e635a124295c --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-ballot.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..a0f728f65b07 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-delegation-withdrawal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-delegation.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-delegation.sample.json new file mode 100644 index 000000000000..7b5149b953fa --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-delegation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-double-attestation-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-double-attestation-evidence.sample.json new file mode 100644 index 000000000000..fa6ebd461571 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-double-attestation-evidence.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-double-baking-evidence.sample.json new file mode 100644 index 000000000000..9550d9d62950 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-double-baking-evidence.sample.json @@ -0,0 +1,39 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-double-preattestation-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-double-preattestation-evidence.sample.json new file mode 100644 index 000000000000..371a2d8e4e55 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-double-preattestation-evidence.sample.json @@ -0,0 +1,31 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preattestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-origination.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-origination.sample.json new file mode 100644 index 000000000000..1bb84ef5d469 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-origination.sample.json @@ -0,0 +1,55 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-preattestation.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-preattestation.sample.json new file mode 100644 index 000000000000..1911762a4437 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-preattestation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-proposals.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-proposals.sample.json new file mode 100644 index 000000000000..a7f958de001d --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-proposals.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-reveal.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-reveal.sample.json new file mode 100644 index 000000000000..5e5c37e058f0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-reveal.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..19dd3b8d9cc1 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-seed-nonce-revelation.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..a8385a84d26e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-implicit.sample.json @@ -0,0 +1,14 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-originated.sample.json new file mode 100644 index 000000000000..c9bf769a3eea --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation/operation-transaction-to-originated.sample.json @@ -0,0 +1,20 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json new file mode 100644 index 000000000000..6e0f40dd83fc --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json new file mode 100644 index 000000000000..c272cedc4f20 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json @@ -0,0 +1,10 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..5e3eaa739a99 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json new file mode 100644 index 000000000000..401bed1ed6a2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json new file mode 100644 index 000000000000..646e53384099 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json @@ -0,0 +1,46 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json new file mode 100644 index 000000000000..284e5fe6bef2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_endorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json new file mode 100644 index 000000000000..bf3abad61863 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preendorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json new file mode 100644 index 000000000000..ffee281b959d --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json new file mode 100644 index 000000000000..e3937027e89c --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json @@ -0,0 +1,54 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json new file mode 100644 index 000000000000..3cf96e2b0325 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json new file mode 100644 index 000000000000..ee628b836024 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json new file mode 100644 index 000000000000..b2bd1b78e79f --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..3f5b02050587 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..6a22e4a8afa3 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json new file mode 100644 index 000000000000..d376b224eb7a --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json @@ -0,0 +1,19 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-activate-account.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-activate-account.sample.json new file mode 100644 index 000000000000..db9a00a60009 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-activate-account.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-ballot.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-ballot.sample.json new file mode 100644 index 000000000000..e635a124295c --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-ballot.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..a0f728f65b07 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation.sample.json new file mode 100644 index 000000000000..7b5149b953fa --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-delegation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json new file mode 100644 index 000000000000..9550d9d62950 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json @@ -0,0 +1,39 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json new file mode 100644 index 000000000000..838a3abe65d0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json @@ -0,0 +1,31 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_endorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json new file mode 100644 index 000000000000..ad947afaa61a --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json @@ -0,0 +1,31 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preendorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-endorsement.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-endorsement.sample.json new file mode 100644 index 000000000000..d948f617b95f --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-endorsement.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-origination.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-origination.sample.json new file mode 100644 index 000000000000..1bb84ef5d469 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-origination.sample.json @@ -0,0 +1,55 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-preendorsement.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-preendorsement.sample.json new file mode 100644 index 000000000000..12cb8aeca006 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-preendorsement.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-proposals.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-proposals.sample.json new file mode 100644 index 000000000000..a7f958de001d --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-proposals.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-reveal.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-reveal.sample.json new file mode 100644 index 000000000000..5e5c37e058f0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-reveal.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..19dd3b8d9cc1 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..a8385a84d26e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json @@ -0,0 +1,14 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json new file mode 100644 index 000000000000..c9bf769a3eea --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json @@ -0,0 +1,20 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisb/period/period-positive.sample.json b/tezt/tests/encoding_samples/parisb/period/period-positive.sample.json new file mode 100644 index 000000000000..48fbee6018c0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/period/period-positive.sample.json @@ -0,0 +1 @@ +"2789" diff --git a/tezt/tests/encoding_samples/parisb/period/period-zero.sample.json b/tezt/tests/encoding_samples/parisb/period/period-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/period/period-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisb/raw_level/raw_level-positive.sample.json b/tezt/tests/encoding_samples/parisb/raw_level/raw_level-positive.sample.json new file mode 100644 index 000000000000..a51fa7d1efef --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/raw_level/raw_level-positive.sample.json @@ -0,0 +1 @@ +2147483647 diff --git a/tezt/tests/encoding_samples/parisb/raw_level/raw_level-zero.sample.json b/tezt/tests/encoding_samples/parisb/raw_level/raw_level-zero.sample.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/raw_level/raw_level-zero.sample.json @@ -0,0 +1 @@ +0 diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json new file mode 100644 index 000000000000..e5da1e57aac2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "0", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json new file mode 100644 index 000000000000..ee5fcec131c6 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "change": "-1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json new file mode 100644 index 000000000000..4bccdc9ace82 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json @@ -0,0 +1,7 @@ +[{ + "kind": "freezer", + "category": "deposits", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "-1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json new file mode 100644 index 000000000000..7b8b05caabac --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json @@ -0,0 +1,8 @@ +[{ + "kind": "freezer", + "category": "fees", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "cycle": 2147483647, + "change": "1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json new file mode 100644 index 000000000000..558faea8ced4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json @@ -0,0 +1,8 @@ +[{ + "kind": "freezer", + "category": "legacy_deposits", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "cycle": 5, + "change": "-1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json new file mode 100644 index 000000000000..e6a164345a63 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json @@ -0,0 +1,8 @@ +[{ + "kind": "freezer", + "category": "legacy_rewards", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "cycle": 0, + "change": "0", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json new file mode 100644 index 000000000000..610a116aa271 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json @@ -0,0 +1,7 @@ +[{ + "kind": "freezer", + "category": "rewards", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "0", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json new file mode 100644 index 000000000000..3d003864885c --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "0", + "origin": "migration" +}] diff --git a/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json new file mode 100644 index 000000000000..d84f63598da2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "change": "-1", + "origin": "migration" +}] diff --git a/tezt/tests/encoding_samples/parisb/roll/roll-positive.sample.json b/tezt/tests/encoding_samples/parisb/roll/roll-positive.sample.json new file mode 100644 index 000000000000..a51fa7d1efef --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/roll/roll-positive.sample.json @@ -0,0 +1 @@ +2147483647 diff --git a/tezt/tests/encoding_samples/parisb/roll/roll-zero.sample.json b/tezt/tests/encoding_samples/parisb/roll/roll-zero.sample.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/roll/roll-zero.sample.json @@ -0,0 +1 @@ +0 diff --git a/tezt/tests/encoding_samples/parisb/seed/seed.sample.json b/tezt/tests/encoding_samples/parisb/seed/seed.sample.json new file mode 100644 index 000000000000..c0e649a61b00 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/seed/seed.sample.json @@ -0,0 +1 @@ +"0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8" diff --git a/tezt/tests/encoding_samples/parisb/tez/tez-positive.sample.json b/tezt/tests/encoding_samples/parisb/tez/tez-positive.sample.json new file mode 100644 index 000000000000..eed79abebfe4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/tez/tez-positive.sample.json @@ -0,0 +1 @@ +"7322135" diff --git a/tezt/tests/encoding_samples/parisb/tez/tez-zero.sample.json b/tezt/tests/encoding_samples/parisb/tez/tez-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/tez/tez-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisb/timestamp/timestamp.sample.json b/tezt/tests/encoding_samples/parisb/timestamp/timestamp.sample.json new file mode 100644 index 000000000000..020ef41de1d5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/timestamp/timestamp.sample.json @@ -0,0 +1 @@ +"2020-04-20T16:19:59Z" diff --git a/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-nay.sample.json b/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-nay.sample.json new file mode 100644 index 000000000000..3e3bb6e1b47d --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-nay.sample.json @@ -0,0 +1 @@ +"nay" diff --git a/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-pass.sample.json b/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-pass.sample.json new file mode 100644 index 000000000000..3cf9c0f1f9ab --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-pass.sample.json @@ -0,0 +1 @@ +"pass" diff --git a/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-yay.sample.json b/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-yay.sample.json new file mode 100644 index 000000000000..3bf44eff71c0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/vote.ballot/vote.ballot-yay.sample.json @@ -0,0 +1 @@ +"yay" diff --git a/tezt/tests/encoding_samples/parisb/vote.ballots/vote.ballots.sample.json b/tezt/tests/encoding_samples/parisb/vote.ballots/vote.ballots.sample.json new file mode 100644 index 000000000000..2de18504c9af --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/vote.ballots/vote.ballots.sample.json @@ -0,0 +1,5 @@ +{ + "yay": "2147483647", + "nay": "0", + "pass": "455" +} diff --git a/tezt/tests/encoding_samples/parisb/vote.listings/vote.listings.sample.json b/tezt/tests/encoding_samples/parisb/vote.listings/vote.listings.sample.json new file mode 100644 index 000000000000..13b3be07b4ec --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/vote.listings/vote.listings.sample.json @@ -0,0 +1,9 @@ +[{ + "pkh": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "voting_power": "20115" + }, + { + "pkh": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "voting_power": "9000" + } +] diff --git a/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-promotion-vote.sample.json b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-promotion-vote.sample.json new file mode 100644 index 000000000000..abfc62e579c4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-promotion-vote.sample.json @@ -0,0 +1 @@ +"promotion" diff --git a/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-proposal.sample.json b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-proposal.sample.json new file mode 100644 index 000000000000..feced6294a44 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-proposal.sample.json @@ -0,0 +1 @@ +"proposal" diff --git a/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing-vote.sample.json b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing-vote.sample.json new file mode 100644 index 000000000000..779e4dd6eac8 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing-vote.sample.json @@ -0,0 +1 @@ +"exploration" diff --git a/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing.sample.json b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing.sample.json new file mode 100644 index 000000000000..345cbbb98109 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/voting_period.kind/voting_period.kind-testing.sample.json @@ -0,0 +1 @@ +"cooldown" diff --git a/tezt/tests/encoding_samples/parisb/voting_period/voting_period-positive.sample.json b/tezt/tests/encoding_samples/parisb/voting_period/voting_period-positive.sample.json new file mode 100644 index 000000000000..c964039ce13b --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/voting_period/voting_period-positive.sample.json @@ -0,0 +1,5 @@ +{ + "start_position": 1159026, + "kind": "proposal", + "index": 0 +} diff --git a/tezt/tests/encoding_samples/parisb/voting_period/voting_period-zero.sample.json b/tezt/tests/encoding_samples/parisb/voting_period/voting_period-zero.sample.json new file mode 100644 index 000000000000..02b1793b2fe0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisb/voting_period/voting_period-zero.sample.json @@ -0,0 +1,5 @@ +{ + "start_position": 0, + "kind": "proposal", + "index": 0 +} diff --git a/tezt/tests/encoding_samples/parisc/block_header.raw/block_header.raw.sample.json b/tezt/tests/encoding_samples/parisc/block_header.raw/block_header.raw.sample.json new file mode 100644 index 000000000000..221910309fe0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/block_header.raw/block_header.raw.sample.json @@ -0,0 +1,11 @@ +{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "protocol_data": "521d101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" +} diff --git a/tezt/tests/encoding_samples/parisc/block_header.unsigned/block_header.unsigned.sample.json b/tezt/tests/encoding_samples/parisc/block_header.unsigned/block_header.unsigned.sample.json new file mode 100644 index 000000000000..d454af6287b8 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/block_header.unsigned/block_header.unsigned.sample.json @@ -0,0 +1,19 @@ +{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 +} diff --git a/tezt/tests/encoding_samples/parisc/block_header/block_header.sample.json b/tezt/tests/encoding_samples/parisc/block_header/block_header.sample.json new file mode 100644 index 000000000000..444f1b31de7e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/block_header/block_header.sample.json @@ -0,0 +1,20 @@ +{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 +} diff --git a/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-alloc.sample.json b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-alloc.sample.json new file mode 100644 index 000000000000..b114496b7578 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-alloc.sample.json @@ -0,0 +1,10 @@ +[{ + "action": "alloc", + "big_map": "0", + "key_type": [{ + "prim": "nat" + }], + "value_type": [{ + "prim": "unit" + }] +}] diff --git a/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-copy.sample.json b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-copy.sample.json new file mode 100644 index 000000000000..5f43f0cecfc5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-copy.sample.json @@ -0,0 +1,5 @@ +[{ + "action": "copy", + "source_big_map": "0", + "destination_big_map": "1" +}] diff --git a/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-remove.sample.json b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-remove.sample.json new file mode 100644 index 000000000000..f654587236f4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-remove.sample.json @@ -0,0 +1,4 @@ +[{ + "action": "remove", + "big_map": "0" +}] diff --git a/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-update.sample.json b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-update.sample.json new file mode 100644 index 000000000000..1b129b22c4e5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/contract.big_map_diff/big_map_diff-update.sample.json @@ -0,0 +1,11 @@ +[{ + "action": "update", + "big_map": "0", + "key_hash": "exprv6UsC1sN3Fk2XfgcJCL8NCerP5rCGy1PRESZAqr7L2JdzX55EN", + "key": [{ + "int": "1" + }], + "value": [{ + "prim": "UNIT" + }] +}] diff --git a/tezt/tests/encoding_samples/parisc/contract/contract-implicit.sample.json b/tezt/tests/encoding_samples/parisc/contract/contract-implicit.sample.json new file mode 100644 index 000000000000..27b113be04b2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/contract/contract-implicit.sample.json @@ -0,0 +1 @@ +"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" diff --git a/tezt/tests/encoding_samples/parisc/contract/contract-originated.sample.json b/tezt/tests/encoding_samples/parisc/contract/contract-originated.sample.json new file mode 100644 index 000000000000..72ab1777f3a7 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/contract/contract-originated.sample.json @@ -0,0 +1 @@ +"KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat" diff --git a/tezt/tests/encoding_samples/parisc/cycle/cycle-positive.sample.json b/tezt/tests/encoding_samples/parisc/cycle/cycle-positive.sample.json new file mode 100644 index 000000000000..a51fa7d1efef --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/cycle/cycle-positive.sample.json @@ -0,0 +1 @@ +2147483647 diff --git a/tezt/tests/encoding_samples/parisc/cycle/cycle-zero.sample.json b/tezt/tests/encoding_samples/parisc/cycle/cycle-zero.sample.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/cycle/cycle-zero.sample.json @@ -0,0 +1 @@ +0 diff --git a/tezt/tests/encoding_samples/parisc/fitness/fitness.sample.json b/tezt/tests/encoding_samples/parisc/fitness/fitness.sample.json new file mode 100644 index 000000000000..56ae2f8d6f07 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/fitness/fitness.sample.json @@ -0,0 +1 @@ +{"level": 1, "locked_round": 1, "predecessor_round": 1, "round": 2} diff --git a/tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-positive.sample.json b/tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-positive.sample.json new file mode 100644 index 000000000000..0e55e062cab5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-positive.sample.json @@ -0,0 +1 @@ +"8920392083423078" diff --git a/tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-zero.sample.json b/tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/gas.cost/gas.cost-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisc/gas/gas-positive.sample.json b/tezt/tests/encoding_samples/parisc/gas/gas-positive.sample.json new file mode 100644 index 000000000000..94715b79899c --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/gas/gas-positive.sample.json @@ -0,0 +1 @@ +"1238" diff --git a/tezt/tests/encoding_samples/parisc/gas/gas-unaccounted.sample.json b/tezt/tests/encoding_samples/parisc/gas/gas-unaccounted.sample.json new file mode 100644 index 000000000000..839f1ecf5a57 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/gas/gas-unaccounted.sample.json @@ -0,0 +1 @@ +"unaccounted" diff --git a/tezt/tests/encoding_samples/parisc/gas/gas-zero.sample.json b/tezt/tests/encoding_samples/parisc/gas/gas-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/gas/gas-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisc/level/level.sample.json b/tezt/tests/encoding_samples/parisc/level/level.sample.json new file mode 100644 index 000000000000..9a8e74b082e7 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/level/level.sample.json @@ -0,0 +1,7 @@ +{ + "level": 1331, + "level_position": 2147483647, + "cycle": 300, + "cycle_position": 600, + "expected_commitment": true +} diff --git a/tezt/tests/encoding_samples/parisc/nonce/nonce.sample.json b/tezt/tests/encoding_samples/parisc/nonce/nonce.sample.json new file mode 100644 index 000000000000..ca23c3b6a461 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/nonce/nonce.sample.json @@ -0,0 +1 @@ +"0000000000000000000000000000000000000000000000000000000000000000" diff --git a/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..e26fb0179e4e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation-withdrawal.sample.json @@ -0,0 +1,5 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "delegation" +} diff --git a/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation.sample.json b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation.sample.json new file mode 100644 index 000000000000..4bc7ec935564 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-delegation.sample.json @@ -0,0 +1,6 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "delegation", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" +} diff --git a/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-origination.sample.json b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-origination.sample.json new file mode 100644 index 000000000000..b176be7dba11 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-origination.sample.json @@ -0,0 +1,48 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "origination", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } +} diff --git a/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..d1dc4108ad5d --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-implicit.sample.json @@ -0,0 +1,7 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 3, + "kind": "transaction", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" +} diff --git a/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-originated.sample.json new file mode 100644 index 000000000000..e43cfd06b7bb --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.internal/operation.internal-transaction-to-originated.sample.json @@ -0,0 +1,13 @@ +{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "transaction", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } +} diff --git a/tezt/tests/encoding_samples/parisc/operation.raw/operation.raw.sample.json b/tezt/tests/encoding_samples/parisc/operation.raw/operation.raw.sample.json new file mode 100644 index 000000000000..9f8e4f094af1 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.raw/operation.raw.sample.json @@ -0,0 +1,4 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "data": "000000053366804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-activate-account.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-activate-account.sample.json new file mode 100644 index 000000000000..6e0f40dd83fc --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-activate-account.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-attestation.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-attestation.sample.json new file mode 100644 index 000000000000..b28f47358ec6 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-attestation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-ballot.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-ballot.sample.json new file mode 100644 index 000000000000..c272cedc4f20 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-ballot.sample.json @@ -0,0 +1,10 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..5e3eaa739a99 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation-withdrawal.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation.sample.json new file mode 100644 index 000000000000..401bed1ed6a2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-delegation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json new file mode 100644 index 000000000000..884957c25aed --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-attestation-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_attestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json new file mode 100644 index 000000000000..646e53384099 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json @@ -0,0 +1,46 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json new file mode 100644 index 000000000000..8aa1305a50e3 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-double-preattestation-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preattestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-origination.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-origination.sample.json new file mode 100644 index 000000000000..e3937027e89c --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-origination.sample.json @@ -0,0 +1,54 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-preaatestation.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-preaatestation.sample.json new file mode 100644 index 000000000000..e65a1f2095b9 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-preaatestation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-proposals.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-proposals.sample.json new file mode 100644 index 000000000000..ee628b836024 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-proposals.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-reveal.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-reveal.sample.json new file mode 100644 index 000000000000..b2bd1b78e79f --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-reveal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..3f5b02050587 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-seed-nonce-revelation.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..6a22e4a8afa3 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-implicit.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json new file mode 100644 index 000000000000..d376b224eb7a --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation.unsigned/operation.unsigned-transaction-to-originated.sample.json @@ -0,0 +1,19 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-activate-account.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-activate-account.sample.json new file mode 100644 index 000000000000..db9a00a60009 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-activate-account.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-attestation.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-attestation.sample.json new file mode 100644 index 000000000000..fa6ebd461571 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-attestation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-ballot.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-ballot.sample.json new file mode 100644 index 000000000000..e635a124295c --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-ballot.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..a0f728f65b07 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-delegation-withdrawal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-delegation.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-delegation.sample.json new file mode 100644 index 000000000000..7b5149b953fa --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-delegation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-double-attestation-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-double-attestation-evidence.sample.json new file mode 100644 index 000000000000..fa6ebd461571 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-double-attestation-evidence.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-double-baking-evidence.sample.json new file mode 100644 index 000000000000..9550d9d62950 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-double-baking-evidence.sample.json @@ -0,0 +1,39 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-double-preattestation-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-double-preattestation-evidence.sample.json new file mode 100644 index 000000000000..371a2d8e4e55 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-double-preattestation-evidence.sample.json @@ -0,0 +1,31 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preattestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-origination.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-origination.sample.json new file mode 100644 index 000000000000..1bb84ef5d469 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-origination.sample.json @@ -0,0 +1,55 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-preattestation.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-preattestation.sample.json new file mode 100644 index 000000000000..1911762a4437 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-preattestation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-proposals.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-proposals.sample.json new file mode 100644 index 000000000000..a7f958de001d --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-proposals.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-reveal.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-reveal.sample.json new file mode 100644 index 000000000000..5e5c37e058f0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-reveal.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..19dd3b8d9cc1 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-seed-nonce-revelation.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..a8385a84d26e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-implicit.sample.json @@ -0,0 +1,14 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-originated.sample.json new file mode 100644 index 000000000000..c9bf769a3eea --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation/operation-transaction-to-originated.sample.json @@ -0,0 +1,20 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json new file mode 100644 index 000000000000..6e0f40dd83fc --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-activate-account.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json new file mode 100644 index 000000000000..c272cedc4f20 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-ballot.sample.json @@ -0,0 +1,10 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..5e3eaa739a99 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation-withdrawal.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json new file mode 100644 index 000000000000..401bed1ed6a2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-delegation.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json new file mode 100644 index 000000000000..646e53384099 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-baking-evidence.sample.json @@ -0,0 +1,46 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json new file mode 100644 index 000000000000..284e5fe6bef2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-endorsement-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_endorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json new file mode 100644 index 000000000000..bf3abad61863 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-double-preendorsement-evidence.sample.json @@ -0,0 +1,30 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preendorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json new file mode 100644 index 000000000000..ffee281b959d --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-endorsement.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json new file mode 100644 index 000000000000..e3937027e89c --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-origination.sample.json @@ -0,0 +1,54 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json new file mode 100644 index 000000000000..3cf96e2b0325 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-preendorsement.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json new file mode 100644 index 000000000000..ee628b836024 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-proposals.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json new file mode 100644 index 000000000000..b2bd1b78e79f --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-reveal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..3f5b02050587 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-seed-nonce-revelation.sample.json @@ -0,0 +1,8 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..6a22e4a8afa3 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-implicit.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json new file mode 100644 index 000000000000..d376b224eb7a --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name.unsigned/operation.unsigned-transaction-to-originated.sample.json @@ -0,0 +1,19 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }] +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-activate-account.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-activate-account.sample.json new file mode 100644 index 000000000000..db9a00a60009 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-activate-account.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-ballot.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-ballot.sample.json new file mode 100644 index 000000000000..e635a124295c --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-ballot.sample.json @@ -0,0 +1,11 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json new file mode 100644 index 000000000000..a0f728f65b07 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation-withdrawal.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation.sample.json new file mode 100644 index 000000000000..7b5149b953fa --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-delegation.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json new file mode 100644 index 000000000000..9550d9d62950 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-baking-evidence.sample.json @@ -0,0 +1,39 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": ["01", "000000000000000a"], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round":0 + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json new file mode 100644 index 000000000000..838a3abe65d0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-endorsement-evidence.sample.json @@ -0,0 +1,31 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_endorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json new file mode 100644 index 000000000000..ad947afaa61a --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-double-preendorsement-evidence.sample.json @@ -0,0 +1,31 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preendorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-endorsement.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-endorsement.sample.json new file mode 100644 index 000000000000..d948f617b95f --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-endorsement.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-origination.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-origination.sample.json new file mode 100644 index 000000000000..1bb84ef5d469 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-origination.sample.json @@ -0,0 +1,55 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [{ + "prim": "parameter", + "args": [{ + "prim": "string" + }] + }, + { + "prim": "storage", + "args": [{ + "prim": "option", + "args": [{ + "prim": "string" + }] + }] + }, + { + "prim": "code", + "args": [ + [{ + "prim": "CAR" + }, { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [{ + "prim": "operation" + }] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [{ + "string": "test" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-preendorsement.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-preendorsement.sample.json new file mode 100644 index 000000000000..12cb8aeca006 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-preendorsement.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-proposals.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-proposals.sample.json new file mode 100644 index 000000000000..a7f958de001d --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-proposals.sample.json @@ -0,0 +1,12 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": ["PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-reveal.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-reveal.sample.json new file mode 100644 index 000000000000..5e5c37e058f0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-reveal.sample.json @@ -0,0 +1,13 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json new file mode 100644 index 000000000000..19dd3b8d9cc1 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-seed-nonce-revelation.sample.json @@ -0,0 +1,9 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json new file mode 100644 index 000000000000..a8385a84d26e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-implicit.sample.json @@ -0,0 +1,14 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json new file mode 100644 index 000000000000..c9bf769a3eea --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/operation_with_legacy_attestation_name/operation-transaction-to-originated.sample.json @@ -0,0 +1,20 @@ +{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [{ + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [{ + "prim": "UNIT" + }] + } + }], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +} diff --git a/tezt/tests/encoding_samples/parisc/period/period-positive.sample.json b/tezt/tests/encoding_samples/parisc/period/period-positive.sample.json new file mode 100644 index 000000000000..48fbee6018c0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/period/period-positive.sample.json @@ -0,0 +1 @@ +"2789" diff --git a/tezt/tests/encoding_samples/parisc/period/period-zero.sample.json b/tezt/tests/encoding_samples/parisc/period/period-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/period/period-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisc/raw_level/raw_level-positive.sample.json b/tezt/tests/encoding_samples/parisc/raw_level/raw_level-positive.sample.json new file mode 100644 index 000000000000..a51fa7d1efef --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/raw_level/raw_level-positive.sample.json @@ -0,0 +1 @@ +2147483647 diff --git a/tezt/tests/encoding_samples/parisc/raw_level/raw_level-zero.sample.json b/tezt/tests/encoding_samples/parisc/raw_level/raw_level-zero.sample.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/raw_level/raw_level-zero.sample.json @@ -0,0 +1 @@ +0 diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json new file mode 100644 index 000000000000..e5da1e57aac2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-implicit.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "0", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json new file mode 100644 index 000000000000..ee5fcec131c6 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-contract-originated.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "change": "-1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json new file mode 100644 index 000000000000..4bccdc9ace82 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-deposits.sample.json @@ -0,0 +1,7 @@ +[{ + "kind": "freezer", + "category": "deposits", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "-1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json new file mode 100644 index 000000000000..7b8b05caabac --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-fees.sample.json @@ -0,0 +1,8 @@ +[{ + "kind": "freezer", + "category": "fees", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "cycle": 2147483647, + "change": "1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json new file mode 100644 index 000000000000..558faea8ced4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_deposits.sample.json @@ -0,0 +1,8 @@ +[{ + "kind": "freezer", + "category": "legacy_deposits", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "cycle": 5, + "change": "-1", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json new file mode 100644 index 000000000000..e6a164345a63 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-legacy_rewards.sample.json @@ -0,0 +1,8 @@ +[{ + "kind": "freezer", + "category": "legacy_rewards", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "cycle": 0, + "change": "0", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json new file mode 100644 index 000000000000..610a116aa271 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-freezer-rewards.sample.json @@ -0,0 +1,7 @@ +[{ + "kind": "freezer", + "category": "rewards", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "0", + "origin": "block" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json new file mode 100644 index 000000000000..3d003864885c --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-implicit.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "change": "0", + "origin": "migration" +}] diff --git a/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json new file mode 100644 index 000000000000..d84f63598da2 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/receipt.balance_updates/receipt.balance_updates-migration-contract-originated.sample.json @@ -0,0 +1,6 @@ +[{ + "kind": "contract", + "contract": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "change": "-1", + "origin": "migration" +}] diff --git a/tezt/tests/encoding_samples/parisc/roll/roll-positive.sample.json b/tezt/tests/encoding_samples/parisc/roll/roll-positive.sample.json new file mode 100644 index 000000000000..a51fa7d1efef --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/roll/roll-positive.sample.json @@ -0,0 +1 @@ +2147483647 diff --git a/tezt/tests/encoding_samples/parisc/roll/roll-zero.sample.json b/tezt/tests/encoding_samples/parisc/roll/roll-zero.sample.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/roll/roll-zero.sample.json @@ -0,0 +1 @@ +0 diff --git a/tezt/tests/encoding_samples/parisc/seed/seed.sample.json b/tezt/tests/encoding_samples/parisc/seed/seed.sample.json new file mode 100644 index 000000000000..c0e649a61b00 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/seed/seed.sample.json @@ -0,0 +1 @@ +"0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8" diff --git a/tezt/tests/encoding_samples/parisc/tez/tez-positive.sample.json b/tezt/tests/encoding_samples/parisc/tez/tez-positive.sample.json new file mode 100644 index 000000000000..eed79abebfe4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/tez/tez-positive.sample.json @@ -0,0 +1 @@ +"7322135" diff --git a/tezt/tests/encoding_samples/parisc/tez/tez-zero.sample.json b/tezt/tests/encoding_samples/parisc/tez/tez-zero.sample.json new file mode 100644 index 000000000000..9bc20d262a9e --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/tez/tez-zero.sample.json @@ -0,0 +1 @@ +"0" diff --git a/tezt/tests/encoding_samples/parisc/timestamp/timestamp.sample.json b/tezt/tests/encoding_samples/parisc/timestamp/timestamp.sample.json new file mode 100644 index 000000000000..020ef41de1d5 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/timestamp/timestamp.sample.json @@ -0,0 +1 @@ +"2020-04-20T16:19:59Z" diff --git a/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-nay.sample.json b/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-nay.sample.json new file mode 100644 index 000000000000..3e3bb6e1b47d --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-nay.sample.json @@ -0,0 +1 @@ +"nay" diff --git a/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-pass.sample.json b/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-pass.sample.json new file mode 100644 index 000000000000..3cf9c0f1f9ab --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-pass.sample.json @@ -0,0 +1 @@ +"pass" diff --git a/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-yay.sample.json b/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-yay.sample.json new file mode 100644 index 000000000000..3bf44eff71c0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/vote.ballot/vote.ballot-yay.sample.json @@ -0,0 +1 @@ +"yay" diff --git a/tezt/tests/encoding_samples/parisc/vote.ballots/vote.ballots.sample.json b/tezt/tests/encoding_samples/parisc/vote.ballots/vote.ballots.sample.json new file mode 100644 index 000000000000..2de18504c9af --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/vote.ballots/vote.ballots.sample.json @@ -0,0 +1,5 @@ +{ + "yay": "2147483647", + "nay": "0", + "pass": "455" +} diff --git a/tezt/tests/encoding_samples/parisc/vote.listings/vote.listings.sample.json b/tezt/tests/encoding_samples/parisc/vote.listings/vote.listings.sample.json new file mode 100644 index 000000000000..13b3be07b4ec --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/vote.listings/vote.listings.sample.json @@ -0,0 +1,9 @@ +[{ + "pkh": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "voting_power": "20115" + }, + { + "pkh": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "voting_power": "9000" + } +] diff --git a/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-promotion-vote.sample.json b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-promotion-vote.sample.json new file mode 100644 index 000000000000..abfc62e579c4 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-promotion-vote.sample.json @@ -0,0 +1 @@ +"promotion" diff --git a/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-proposal.sample.json b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-proposal.sample.json new file mode 100644 index 000000000000..feced6294a44 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-proposal.sample.json @@ -0,0 +1 @@ +"proposal" diff --git a/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing-vote.sample.json b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing-vote.sample.json new file mode 100644 index 000000000000..779e4dd6eac8 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing-vote.sample.json @@ -0,0 +1 @@ +"exploration" diff --git a/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing.sample.json b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing.sample.json new file mode 100644 index 000000000000..345cbbb98109 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/voting_period.kind/voting_period.kind-testing.sample.json @@ -0,0 +1 @@ +"cooldown" diff --git a/tezt/tests/encoding_samples/parisc/voting_period/voting_period-positive.sample.json b/tezt/tests/encoding_samples/parisc/voting_period/voting_period-positive.sample.json new file mode 100644 index 000000000000..c964039ce13b --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/voting_period/voting_period-positive.sample.json @@ -0,0 +1,5 @@ +{ + "start_position": 1159026, + "kind": "proposal", + "index": 0 +} diff --git a/tezt/tests/encoding_samples/parisc/voting_period/voting_period-zero.sample.json b/tezt/tests/encoding_samples/parisc/voting_period/voting_period-zero.sample.json new file mode 100644 index 000000000000..02b1793b2fe0 --- /dev/null +++ b/tezt/tests/encoding_samples/parisc/voting_period/voting_period-zero.sample.json @@ -0,0 +1,5 @@ +{ + "start_position": 0, + "kind": "proposal", + "index": 0 +} diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- adaptive_issuance.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- adaptive_issuance.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- adaptive_issuance.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- contracts.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- contracts.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- contracts.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- delegates.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- delegates.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- delegates.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- mempool.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- mempool.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- mempool.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- mempool.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- misc_protocol.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- misc_protocol.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- misc_protocol.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- votes.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode client) RPC regression tests- votes.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode client) RPC regression tests- votes.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- adaptive_issuance.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- adaptive_issuance.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- adaptive_issuance.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- contracts.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- contracts.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- contracts.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- delegates.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- delegates.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- delegates.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- misc_protocol.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- misc_protocol.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- misc_protocol.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- votes.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode light) RPC regression tests- votes.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode light) RPC regression tests- votes.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- adaptive_issuance.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- adaptive_issuance.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- adaptive_issuance.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- contracts.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- contracts.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- contracts.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- delegates.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- delegates.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- delegates.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- mempool.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- mempool.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- mempool.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- mempool.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- misc_protocol.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- misc_protocol.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- misc_protocol.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- votes.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy) RPC regression tests- votes.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy) RPC regression tests- votes.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- contracts.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- contracts.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- contracts.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- delegates.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- delegates.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- delegates.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- votes.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_data_dir) RPC regression tests- votes.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_data_dir) RPC regression tests- votes.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- contracts.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- contracts.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- contracts.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- delegates.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- delegates.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- delegates.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out diff --git a/tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- votes.out similarity index 100% rename from tezt/tests/expected/RPC_test.ml/Paris- (mode proxy_server_rpc) RPC regression tests- votes.out rename to tezt/tests/expected/RPC_test.ml/Parisb- (mode proxy_server_rpc) RPC regression tests- votes.out diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- adaptive_issuance.out new file mode 100644 index 000000000000..0114e0aaadd5 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- adaptive_issuance.out @@ -0,0 +1,66 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/total_supply +"20000001000100" + +./octez-client rpc get /chains/main/blocks/head/context/total_frozen_stake +"1000000000000" + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate +"210.260" + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_exact +{ "numerator": "42052105987200", "denominator": "200000010001" } + +./octez-client rpc get /chains/main/blocks/head/context/issuance/issuance_per_minute +"80007812" + +./octez-client rpc get /chains/main/blocks/head/context/adaptive_issuance_launch_cycle +null + +./octez-client rpc get /chains/main/blocks/head/context/issuance/expected_issuance +[ { "cycle": 0, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 1, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 2, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" } ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/stakers' +[ { "staker": "[PUBLIC_KEY_HASH]", + "frozen_deposits": "200000000000" } ] + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_details +{ "static": { "numerator": "42052105987200", "denominator": "200000010001" }, + "dynamic": { "numerator": "0", "denominator": "1" } } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/total_delegated_stake' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_denominator' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/staking_numerator' +"0" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- contracts.out new file mode 100644 index 000000000000..f0233dd45418 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- contracts.out @@ -0,0 +1,553 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "3800000000000", + "delegate": "[PUBLIC_KEY_HASH]", "counter": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "100000000", "counter": "1" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"100000000" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"1" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "99999566", "delegate": "[PUBLIC_KEY_HASH]", + "counter": "4" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"99999566" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"4" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": + { "prim": "Some", "args": [ { "string": "initial storage" } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": {} } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": { "prim": "Some", "args": [ { "string": "initial storage" } ] } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Some", "args": [ { "string": "initial storage" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", + "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": + [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": + { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": + { "rem_right": { "prim": "string" }, "rem_left": { "prim": "string" }, + "rem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%rem_left" ] }, + { "prim": "string", "annots": [ "%rem_right" ] } ] }, + "mem_right": { "prim": "string" }, "mem_left": { "prim": "string" }, + "mem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", "annots": [ "%mem_right" ] } ] }, + "default": { "prim": "unit" }, + "add_right": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add_left": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add": + { "prim": "or", + "args": + [ { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_right" ] } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "test" + }, + "type": { + "prim": "string" + } +}' +null + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "dup" + }, + "type": { + "prim": "string" + } +}' +null diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- delegates.out new file mode 100644 index 000000000000..29602dc55a14 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- delegates.out @@ -0,0 +1,102 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 5, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +"200000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +false + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +[ "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +5 + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +Fatal error: + Command failed: The implicit account ([PUBLIC_KEY_HASH]) whose balance was requested is not a registered delegate. To get the balance of this account you can use the ../context/contracts/[PUBLIC_KEY_HASH]/balance RPC. + The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- mempool.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- mempool.out new file mode 100644 index 000000000000..8aba5bc7f1f6 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- mempool.out @@ -0,0 +1,570 @@ + +curl -s 'http://[HOST]:[PORT]/chains/main/mempool/monitor_operations?validated=true&outdated=true&branch_delayed=true&refused=true&branch_refused=true' +[] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"branch","id":"proto.020-PsParisC.contract.counter_in_the_past","contract":"[PUBLIC_KEY_HASH]","expected":"2","found":"1"}]}] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"5","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"temporary","id":"proto.020-PsParisC.contract.counter_in_the_future","contract":"[PUBLIC_KEY_HASH]","expected":"1","found":"5"}]}] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"0","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"}] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"}] + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=0' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": [], "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=3' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=0&validation_pass=3' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=1&validation_pass=2' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": [], "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=false&outdated=false&branch_delayed=false&branch_refused=false' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": [], "outdated": [], "branch_refused": [], "branch_delayed": [], + "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=true&outdated=false&branch_delayed=false&branch_refused=false' +{ "validated": [], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], "branch_refused": [], "branch_delayed": [], + "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=false&outdated=false&branch_delayed=true&branch_refused=false' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=false&outdated=false&branch_delayed=false&branch_refused=true' +{ "validated": [], "refused": [], "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], "branch_delayed": [], + "unprocessed": [] } + +./octez-client rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=false&outdated=true&branch_delayed=false&branch_refused=false' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": [], "unprocessed": [] } + +curl -s 'http://[HOST]:[PORT]/chains/main/mempool/monitor_operations?validated=true&outdated=true&branch_delayed=true&refused=true&branch_refused=true' +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"},{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"0","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"permanent","id":"proto.020-PsParisC.prefilter.fees_too_low"}]},{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"branch","id":"proto.020-PsParisC.contract.counter_in_the_past","contract":"[PUBLIC_KEY_HASH]","expected":"2","found":"1"}]},{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"5","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"temporary","id":"proto.020-PsParisC.contract.counter_in_the_future","contract":"[PUBLIC_KEY_HASH]","expected":"1","found":"5"}]}] + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=false' +{} + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "1", + "minimal_nanotez_per_gas_unit": [ + "2", + "3" + ], + "minimal_nanotez_per_byte": [ + "4", + "5" + ], + "replace_by_fee_factor": [ + "6", + "7" + ], + "max_operations": 8, + "max_total_bytes": 9 +}' +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "25", + "minimal_nanotez_per_byte": [ + "1050", + "1" + ], + "max_operations": 2000 +}' +{ "minimal_fees": "25", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1050", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 2000, + "max_total_bytes": 10000000 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "25", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1050", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 2000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "25", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1050", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 2000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_fees": "25", "minimal_nanotez_per_byte": [ "1050", "1" ], + "max_operations": 2000 } + +./octez-client rpc post /chains/main/mempool/filter with '{}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=false' +{} + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100", + "0" + ] +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "0" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "0" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "0" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_nanotez_per_gas_unit": [ "100", "0" ] } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100", + "1" + ], + "minimal_nanotez_per_byte": [ + "4611686018427387903", + "1" + ], + "max_operations": 10000, + "max_total_bytes": 0 +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "100", + "minimal_nanotez_per_gas_unit": [ + "1050", + "1" + ], + "minimal_nanotez_per_byte": [ + "7", + "5" + ], + "replace_by_fee_factor": [ + "21", + "20" + ], + "max_operations": 10, + "max_total_bytes": 10000000, + "invalid_field_name": 100 +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "true" +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "max_operations": "1000" +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100" + ] +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100", + "1", + "10" + ] +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "-1" +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc post /chains/main/mempool/filter with '{ + "max_operations": -1 +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- misc_protocol.out new file mode 100644 index 000000000000..7b3a6b1d2504 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- misc_protocol.out @@ -0,0 +1,137 @@ + +./octez-client rpc get /chains/main/blocks/head/context/constants +{ "proof_of_work_nonce_size": 8, "nonce_length": 32, + "max_anon_ops_per_block": 132, "max_operation_data_length": 32768, + "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, + "max_micheline_bytes_limit": 50000, + "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, + "michelson_maximum_type_size": 2001, "max_slashing_period": 2, + "smart_rollup_max_wrapped_proof_binary_size": 30000, + "smart_rollup_message_size_limit": 4096, + "smart_rollup_max_number_of_messages_per_level": "1000000", + "consensus_rights_delay": 2, "blocks_preservation_cycles": 1, + "delegate_parameters_activation_delay": 2, "blocks_per_cycle": 8, + "blocks_per_commitment": 4, "nonce_revelation_threshold": 4, + "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", + "hard_gas_limit_per_block": "1733333", + "proof_of_work_threshold": "4611686018427387903", + "minimal_stake": "6000000000", "minimal_frozen_stake": "600000000", + "vdf_difficulty": "50000", "origination_size": 257, + "issuance_weights": + { "base_total_issued_per_minute": "80007812", + "baking_reward_fixed_portion_weight": 5120, + "baking_reward_bonus_weight": 5120, "attesting_reward_weight": 10240, + "seed_nonce_revelation_tip_weight": 1, "vdf_revelation_tip_weight": 1 }, + "cost_per_byte": "250", "hard_storage_limit_per_operation": "60000", + "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, + "liquidity_baking_subsidy": "5000000", + "liquidity_baking_toggle_ema_threshold": 1000000000, + "max_operations_time_to_live": 8, "minimal_block_delay": "1", + "delay_increment_per_round": "1", "consensus_committee_size": 256, + "consensus_threshold": 0, + "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, + "limit_of_delegation_over_baking": 19, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, + "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, + "cache_sampler_state_cycles": 8, + "dal_parametric": + { "feature_enable": true, "incentives_enable": false, + "number_of_slots": 16, "attestation_lag": 8, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, + "smart_rollup_arith_pvm_enable": false, + "smart_rollup_origination_size": 6314, + "smart_rollup_challenge_window_in_blocks": 120960, + "smart_rollup_stake_amount": "10000000000", + "smart_rollup_commitment_period_in_blocks": 90, + "smart_rollup_max_lookahead_in_blocks": 259200, + "smart_rollup_max_active_outbox_levels": 120960, + "smart_rollup_max_outbox_messages_per_level": 100, + "smart_rollup_number_of_sections_in_dissection": 32, + "smart_rollup_timeout_period_in_blocks": 60480, + "smart_rollup_max_number_of_cemented_commitments": 5, + "smart_rollup_max_number_of_parallel_games": 32, + "smart_rollup_reveal_activation_level": + { "raw_data": { "Blake2B": 0 }, "metadata": 0, "dal_page": 1, + "dal_parameters": 1, "dal_attested_slots_validity_lag": 241920 }, + "smart_rollup_private_enable": true, + "smart_rollup_riscv_pvm_enable": false, "zk_rollup_enable": false, + "zk_rollup_origination_size": 4000, "zk_rollup_min_pending_to_process": 10, + "zk_rollup_max_ticket_payload_size": 2048, + "global_limit_of_staking_over_baking": 5, + "edge_of_staking_over_delegation": 2, + "adaptive_issuance_launch_ema_threshold": 0, + "adaptive_rewards_params": + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", + "growth_rate": { "numerator": "1", "denominator": "100" }, + "center_dz": { "numerator": "1", "denominator": "2" }, + "radius_dz": { "numerator": "1", "denominator": "50" } }, + "adaptive_issuance_activation_vote_enable": true, + "autostaking_enable": true, "adaptive_issuance_force_activation": false, + "ns_enable": true, "direct_ticket_spending_enable": false } + +./octez-client rpc get /chains/main/blocks/head/helpers/baking_rights +[ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 10, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/baking_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' +{ "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } + +./octez-client rpc get /chains/main/blocks/head/context/denunciations +[] + +./octez-client rpc get /chains/main/blocks/head/helpers/attestation_rights +[ { "level": 1, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 11, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 4, "attestation_power": 47, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 2, "attestation_power": 46, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 55, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 0, "attestation_power": 58, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/attestation_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 1, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 11, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle +{ "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- votes.out new file mode 100644 index 000000000000..aceb75eb281b --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode client) RPC regression tests- votes.out @@ -0,0 +1,78 @@ + +./octez-client rpc get /chains/main/blocks/head/votes/ballot_list +[] + +./octez-client rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "0", "nay": "0", "pass": "0" } + +./octez-client rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 1, "remaining": 2 } + +./octez-client rpc get /chains/main/blocks/head/votes/current_proposal +null + +./octez-client rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/proposals +[ [ "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp", "4000000000000" ] ] + +./octez-client rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 2, "remaining": 1 } + +./octez-client rpc get /chains/main/blocks/head/votes/total_voting_power +"20000000000000" + +./octez-client rpc get /chains/main/blocks/head/votes/ballot_list +[ { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "nay" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "pass" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "yay" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "4000001679643", "nay": "4000000000000", "pass": "4000000000000" } + +./octez-client rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 0, "remaining": 3 } + +./octez-client rpc get /chains/main/blocks/head/votes/current_proposal +"ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp" + +./octez-client rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000001679643" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/proposals +[] + +./octez-client rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 1, "remaining": 2 } + +./octez-client rpc get /chains/main/blocks/head/votes/total_voting_power +"20000001679643" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- adaptive_issuance.out new file mode 100644 index 000000000000..4cd8cf5d1084 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- adaptive_issuance.out @@ -0,0 +1,66 @@ + +./octez-client --mode light rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get /chains/main/blocks/head/context/total_supply +"20000001000100" + +./octez-client --mode light rpc get /chains/main/blocks/head/context/total_frozen_stake +"1000000000000" + +./octez-client --mode light rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate +"210.260" + +./octez-client --mode light rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_exact +{ "numerator": "42052105987200", "denominator": "200000010001" } + +./octez-client --mode light rpc get /chains/main/blocks/head/context/issuance/issuance_per_minute +"80007812" + +./octez-client --mode light rpc get /chains/main/blocks/head/context/adaptive_issuance_launch_cycle +null + +./octez-client --mode light rpc get /chains/main/blocks/head/context/issuance/expected_issuance +[ { "cycle": 0, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 1, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 2, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" } ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/stakers' +[ { "staker": "[PUBLIC_KEY_HASH]", + "frozen_deposits": "200000000000" } ] + +./octez-client --mode light rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_details +{ "static": { "numerator": "42052105987200", "denominator": "200000010001" }, + "dynamic": { "numerator": "0", "denominator": "1" } } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/total_delegated_stake' +"0" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_denominator' +"0" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/staking_numerator' +"0" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- contracts.out new file mode 100644 index 000000000000..cd67573dc9ab --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- contracts.out @@ -0,0 +1,553 @@ + +./octez-client --mode light rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "3800000000000", + "delegate": "[PUBLIC_KEY_HASH]", "counter": "0" } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800000000000" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"0" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "0" } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "100000000", "counter": "1" } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"100000000" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"1" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +null + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "99999566", "delegate": "[PUBLIC_KEY_HASH]", + "counter": "4" } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"99999566" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"4" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": + { "prim": "Some", "args": [ { "string": "initial storage" } ] } } } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": {} } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": { "prim": "Some", "args": [ { "string": "initial storage" } ] } } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Some", "args": [ { "string": "initial storage" } ] } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", + "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": + [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": + { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client --mode light rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": + { "rem_right": { "prim": "string" }, "rem_left": { "prim": "string" }, + "rem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%rem_left" ] }, + { "prim": "string", "annots": [ "%rem_right" ] } ] }, + "mem_right": { "prim": "string" }, "mem_left": { "prim": "string" }, + "mem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", "annots": [ "%mem_right" ] } ] }, + "default": { "prim": "unit" }, + "add_right": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add_left": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add": + { "prim": "or", + "args": + [ { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_right" ] } ] } } } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } + +./octez-client --mode light rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "test" + }, + "type": { + "prim": "string" + } +}' +null + +./octez-client --mode light rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "dup" + }, + "type": { + "prim": "string" + } +}' +null diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- delegates.out new file mode 100644 index 000000000000..d3577edcf2c1 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- delegates.out @@ -0,0 +1,102 @@ + +./octez-client --mode light rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 5, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +"4000000000000" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +"200000000000" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +false + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +"0" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +[ "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +5 + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +"4000000000000" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +"4000000000000" + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +Fatal error: + Command failed: The implicit account ([PUBLIC_KEY_HASH]) whose balance was requested is not a registered delegate. To get the balance of this account you can use the ../context/contracts/[PUBLIC_KEY_HASH]/balance RPC. + The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- misc_protocol.out new file mode 100644 index 000000000000..e3fcc9f9b786 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- misc_protocol.out @@ -0,0 +1,137 @@ + +./octez-client --mode light rpc get /chains/main/blocks/head/context/constants +{ "proof_of_work_nonce_size": 8, "nonce_length": 32, + "max_anon_ops_per_block": 132, "max_operation_data_length": 32768, + "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, + "max_micheline_bytes_limit": 50000, + "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, + "michelson_maximum_type_size": 2001, "max_slashing_period": 2, + "smart_rollup_max_wrapped_proof_binary_size": 30000, + "smart_rollup_message_size_limit": 4096, + "smart_rollup_max_number_of_messages_per_level": "1000000", + "consensus_rights_delay": 2, "blocks_preservation_cycles": 1, + "delegate_parameters_activation_delay": 2, "blocks_per_cycle": 8, + "blocks_per_commitment": 4, "nonce_revelation_threshold": 4, + "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", + "hard_gas_limit_per_block": "1733333", + "proof_of_work_threshold": "4611686018427387903", + "minimal_stake": "6000000000", "minimal_frozen_stake": "600000000", + "vdf_difficulty": "50000", "origination_size": 257, + "issuance_weights": + { "base_total_issued_per_minute": "80007812", + "baking_reward_fixed_portion_weight": 5120, + "baking_reward_bonus_weight": 5120, "attesting_reward_weight": 10240, + "seed_nonce_revelation_tip_weight": 1, "vdf_revelation_tip_weight": 1 }, + "cost_per_byte": "250", "hard_storage_limit_per_operation": "60000", + "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, + "liquidity_baking_subsidy": "5000000", + "liquidity_baking_toggle_ema_threshold": 1000000000, + "max_operations_time_to_live": 8, "minimal_block_delay": "1", + "delay_increment_per_round": "1", "consensus_committee_size": 256, + "consensus_threshold": 0, + "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, + "limit_of_delegation_over_baking": 19, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, + "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, + "cache_sampler_state_cycles": 8, + "dal_parametric": + { "feature_enable": true, "incentives_enable": false, + "number_of_slots": 16, "attestation_lag": 8, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, + "smart_rollup_arith_pvm_enable": false, + "smart_rollup_origination_size": 6314, + "smart_rollup_challenge_window_in_blocks": 120960, + "smart_rollup_stake_amount": "10000000000", + "smart_rollup_commitment_period_in_blocks": 90, + "smart_rollup_max_lookahead_in_blocks": 259200, + "smart_rollup_max_active_outbox_levels": 120960, + "smart_rollup_max_outbox_messages_per_level": 100, + "smart_rollup_number_of_sections_in_dissection": 32, + "smart_rollup_timeout_period_in_blocks": 60480, + "smart_rollup_max_number_of_cemented_commitments": 5, + "smart_rollup_max_number_of_parallel_games": 32, + "smart_rollup_reveal_activation_level": + { "raw_data": { "Blake2B": 0 }, "metadata": 0, "dal_page": 1, + "dal_parameters": 1, "dal_attested_slots_validity_lag": 241920 }, + "smart_rollup_private_enable": true, + "smart_rollup_riscv_pvm_enable": false, "zk_rollup_enable": false, + "zk_rollup_origination_size": 4000, "zk_rollup_min_pending_to_process": 10, + "zk_rollup_max_ticket_payload_size": 2048, + "global_limit_of_staking_over_baking": 5, + "edge_of_staking_over_delegation": 2, + "adaptive_issuance_launch_ema_threshold": 0, + "adaptive_rewards_params": + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", + "growth_rate": { "numerator": "1", "denominator": "100" }, + "center_dz": { "numerator": "1", "denominator": "2" }, + "radius_dz": { "numerator": "1", "denominator": "50" } }, + "adaptive_issuance_activation_vote_enable": true, + "autostaking_enable": true, "adaptive_issuance_force_activation": false, + "ns_enable": true, "direct_ticket_spending_enable": false } + +./octez-client --mode light rpc get /chains/main/blocks/head/helpers/baking_rights +[ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 10, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/helpers/baking_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' +{ "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } + +./octez-client --mode light rpc get /chains/main/blocks/head/context/denunciations +[] + +./octez-client --mode light rpc get /chains/main/blocks/head/helpers/attestation_rights +[ { "level": 1, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 11, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 4, "attestation_power": 47, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 2, "attestation_power": 46, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 55, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 0, "attestation_power": 58, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client --mode light rpc get '/chains/main/blocks/head/helpers/attestation_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 1, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 11, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client --mode light rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle +{ "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- votes.out new file mode 100644 index 000000000000..8baa3dc26318 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode light) RPC regression tests- votes.out @@ -0,0 +1,78 @@ + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/ballot_list +[] + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "0", "nay": "0", "pass": "0" } + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 1, "remaining": 2 } + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/current_proposal +null + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" } ] + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/proposals +[ [ "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp", "4000000000000" ] ] + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 2, "remaining": 1 } + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/total_voting_power +"20000000000000" + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/ballot_list +[ { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "nay" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "pass" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "yay" } ] + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "4000001679643", "nay": "4000000000000", "pass": "4000000000000" } + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 0, "remaining": 3 } + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/current_proposal +"ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp" + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000001679643" } ] + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/proposals +[] + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 1, "remaining": 2 } + +./octez-client --mode light rpc get /chains/main/blocks/head/votes/total_voting_power +"20000001679643" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- adaptive_issuance.out new file mode 100644 index 000000000000..964ebe474633 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- adaptive_issuance.out @@ -0,0 +1,66 @@ + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/total_supply +"20000001000100" + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/total_frozen_stake +"1000000000000" + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate +"210.260" + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_exact +{ "numerator": "42052105987200", "denominator": "200000010001" } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/issuance/issuance_per_minute +"80007812" + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/adaptive_issuance_launch_cycle +null + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/issuance/expected_issuance +[ { "cycle": 0, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 1, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 2, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" } ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/stakers' +[ { "staker": "[PUBLIC_KEY_HASH]", + "frozen_deposits": "200000000000" } ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_details +{ "static": { "numerator": "42052105987200", "denominator": "200000010001" }, + "dynamic": { "numerator": "0", "denominator": "1" } } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/total_delegated_stake' +"0" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_denominator' +"0" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/staking_numerator' +"0" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- contracts.out new file mode 100644 index 000000000000..f9a84fa41751 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- contracts.out @@ -0,0 +1,553 @@ + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "3800000000000", + "delegate": "[PUBLIC_KEY_HASH]", "counter": "0" } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800000000000" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"0" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "0" } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "100000000", "counter": "1" } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"100000000" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"1" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +null + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "99999566", "delegate": "[PUBLIC_KEY_HASH]", + "counter": "4" } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"99999566" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"4" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": + { "prim": "Some", "args": [ { "string": "initial storage" } ] } } } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": {} } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": { "prim": "Some", "args": [ { "string": "initial storage" } ] } } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Some", "args": [ { "string": "initial storage" } ] } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", + "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": + [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": + { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client --mode proxy rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": + { "rem_right": { "prim": "string" }, "rem_left": { "prim": "string" }, + "rem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%rem_left" ] }, + { "prim": "string", "annots": [ "%rem_right" ] } ] }, + "mem_right": { "prim": "string" }, "mem_left": { "prim": "string" }, + "mem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", "annots": [ "%mem_right" ] } ] }, + "default": { "prim": "unit" }, + "add_right": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add_left": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add": + { "prim": "or", + "args": + [ { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_right" ] } ] } } } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } + +./octez-client --mode proxy rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "test" + }, + "type": { + "prim": "string" + } +}' +null + +./octez-client --mode proxy rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "dup" + }, + "type": { + "prim": "string" + } +}' +null diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- delegates.out new file mode 100644 index 000000000000..6982ef2ae258 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- delegates.out @@ -0,0 +1,102 @@ + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 5, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +"4000000000000" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +"200000000000" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +false + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +"0" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +[ "[PUBLIC_KEY_HASH]" ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +5 + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +"4000000000000" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +"4000000000000" + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +Fatal error: + Command failed: The implicit account ([PUBLIC_KEY_HASH]) whose balance was requested is not a registered delegate. To get the balance of this account you can use the ../context/contracts/[PUBLIC_KEY_HASH]/balance RPC. + The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- mempool.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- mempool.out new file mode 100644 index 000000000000..e9322e0ee1ac --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- mempool.out @@ -0,0 +1,570 @@ + +curl -s 'http://[HOST]:[PORT]/chains/main/mempool/monitor_operations?validated=true&outdated=true&branch_delayed=true&refused=true&branch_refused=true' +[] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"branch","id":"proto.020-PsParisC.contract.counter_in_the_past","contract":"[PUBLIC_KEY_HASH]","expected":"2","found":"1"}]}] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"5","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"temporary","id":"proto.020-PsParisC.contract.counter_in_the_future","contract":"[PUBLIC_KEY_HASH]","expected":"1","found":"5"}]}] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"0","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"}] +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"}] + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=0' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": [], "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=3' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=0&validation_pass=3' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=true&outdated=true&branch_delayed=true&branch_refused=true&validation_pass=1&validation_pass=2' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": [], "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=true&refused=false&outdated=false&branch_delayed=false&branch_refused=false' +{ "validated": + [ { "hash": "[OPERATION_HASH]", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]" } ], + "refused": [], "outdated": [], "branch_refused": [], "branch_delayed": [], + "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=true&outdated=false&branch_delayed=false&branch_refused=false' +{ "validated": [], + "refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", "fee": "0", + "counter": "1", "gas_limit": "1040", "storage_limit": "257", + "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "permanent", + "id": "proto.020-PsParisC.prefilter.fees_too_low" } ] } ], + "outdated": [], "branch_refused": [], "branch_delayed": [], + "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=false&outdated=false&branch_delayed=true&branch_refused=false' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "5", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "temporary", + "id": "proto.020-PsParisC.contract.counter_in_the_future", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "1", "found": "5" } ] } ], "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=false&outdated=false&branch_delayed=false&branch_refused=true' +{ "validated": [], "refused": [], "outdated": [], + "branch_refused": + [ { "hash": "[OPERATION_HASH]", + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "branch": "[BRANCH_HASH]", + "contents": + [ { "kind": "transaction", + "source": "[PUBLIC_KEY_HASH]", + "fee": "1000", "counter": "1", "gas_limit": "1040", + "storage_limit": "257", "amount": "1000000", + "destination": "[PUBLIC_KEY_HASH]" } ], + "signature": + "[SIGNATURE]", + "error": + [ { "kind": "branch", + "id": "proto.020-PsParisC.contract.counter_in_the_past", + "contract": "[PUBLIC_KEY_HASH]", + "expected": "2", "found": "1" } ] } ], "branch_delayed": [], + "unprocessed": [] } + +./octez-client --mode proxy rpc get '/chains/main/mempool/pending_operations?version=2&validated=false&refused=false&outdated=true&branch_delayed=false&branch_refused=false' +{ "validated": [], "refused": [], "outdated": [], "branch_refused": [], + "branch_delayed": [], "unprocessed": [] } + +curl -s 'http://[HOST]:[PORT]/chains/main/mempool/monitor_operations?validated=true&outdated=true&branch_delayed=true&refused=true&branch_refused=true' +[{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"},{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"0","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"permanent","id":"proto.020-PsParisC.prefilter.fees_too_low"}]},{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"branch","id":"proto.020-PsParisC.contract.counter_in_the_past","contract":"[PUBLIC_KEY_HASH]","expected":"2","found":"1"}]},{"hash":"[OPERATION_HASH]","protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"5","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"temporary","id":"proto.020-PsParisC.contract.counter_in_the_future","contract":"[PUBLIC_KEY_HASH]","expected":"1","found":"5"}]}] + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=false' +{} + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "1", + "minimal_nanotez_per_gas_unit": [ + "2", + "3" + ], + "minimal_nanotez_per_byte": [ + "4", + "5" + ], + "replace_by_fee_factor": [ + "6", + "7" + ], + "max_operations": 8, + "max_total_bytes": 9 +}' +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_fees": "1", "minimal_nanotez_per_gas_unit": [ "2", "3" ], + "minimal_nanotez_per_byte": [ "4", "5" ], + "replace_by_fee_factor": [ "6", "7" ], "max_operations": 8, + "max_total_bytes": 9 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "25", + "minimal_nanotez_per_byte": [ + "1050", + "1" + ], + "max_operations": 2000 +}' +{ "minimal_fees": "25", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1050", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 2000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "25", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1050", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 2000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "25", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1050", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 2000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_fees": "25", "minimal_nanotez_per_byte": [ "1050", "1" ], + "max_operations": 2000 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=false' +{} + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100", + "0" + ] +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "0" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "0" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "0" ], + "minimal_nanotez_per_byte": [ "1000", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 10000000 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_nanotez_per_gas_unit": [ "100", "0" ] } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100", + "1" + ], + "minimal_nanotez_per_byte": [ + "4611686018427387903", + "1" + ], + "max_operations": 10000, + "max_total_bytes": 0 +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=false' +{ "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "100", + "minimal_nanotez_per_gas_unit": [ + "1050", + "1" + ], + "minimal_nanotez_per_byte": [ + "7", + "5" + ], + "replace_by_fee_factor": [ + "21", + "20" + ], + "max_operations": 10, + "max_total_bytes": 10000000, + "invalid_field_name": 100 +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "true" +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "max_operations": "1000" +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100" + ] +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_nanotez_per_gas_unit": [ + "100", + "1", + "10" + ] +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "minimal_fees": "-1" +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc post /chains/main/mempool/filter with '{ + "max_operations": -1 +}' +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } + +./octez-client --mode proxy rpc get /chains/main/mempool/filter +{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], + "minimal_nanotez_per_byte": [ "4611686018427387903", "1" ], + "replace_by_fee_factor": [ "21", "20" ], "max_operations": 10000, + "max_total_bytes": 0 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- misc_protocol.out new file mode 100644 index 000000000000..67dcdd688e71 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- misc_protocol.out @@ -0,0 +1,137 @@ + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/constants +{ "proof_of_work_nonce_size": 8, "nonce_length": 32, + "max_anon_ops_per_block": 132, "max_operation_data_length": 32768, + "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, + "max_micheline_bytes_limit": 50000, + "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, + "michelson_maximum_type_size": 2001, "max_slashing_period": 2, + "smart_rollup_max_wrapped_proof_binary_size": 30000, + "smart_rollup_message_size_limit": 4096, + "smart_rollup_max_number_of_messages_per_level": "1000000", + "consensus_rights_delay": 2, "blocks_preservation_cycles": 1, + "delegate_parameters_activation_delay": 2, "blocks_per_cycle": 8, + "blocks_per_commitment": 4, "nonce_revelation_threshold": 4, + "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", + "hard_gas_limit_per_block": "1733333", + "proof_of_work_threshold": "4611686018427387903", + "minimal_stake": "6000000000", "minimal_frozen_stake": "600000000", + "vdf_difficulty": "50000", "origination_size": 257, + "issuance_weights": + { "base_total_issued_per_minute": "80007812", + "baking_reward_fixed_portion_weight": 5120, + "baking_reward_bonus_weight": 5120, "attesting_reward_weight": 10240, + "seed_nonce_revelation_tip_weight": 1, "vdf_revelation_tip_weight": 1 }, + "cost_per_byte": "250", "hard_storage_limit_per_operation": "60000", + "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, + "liquidity_baking_subsidy": "5000000", + "liquidity_baking_toggle_ema_threshold": 1000000000, + "max_operations_time_to_live": 8, "minimal_block_delay": "1", + "delay_increment_per_round": "1", "consensus_committee_size": 256, + "consensus_threshold": 0, + "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, + "limit_of_delegation_over_baking": 19, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, + "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, + "cache_sampler_state_cycles": 8, + "dal_parametric": + { "feature_enable": true, "incentives_enable": false, + "number_of_slots": 16, "attestation_lag": 8, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, + "smart_rollup_arith_pvm_enable": false, + "smart_rollup_origination_size": 6314, + "smart_rollup_challenge_window_in_blocks": 120960, + "smart_rollup_stake_amount": "10000000000", + "smart_rollup_commitment_period_in_blocks": 90, + "smart_rollup_max_lookahead_in_blocks": 259200, + "smart_rollup_max_active_outbox_levels": 120960, + "smart_rollup_max_outbox_messages_per_level": 100, + "smart_rollup_number_of_sections_in_dissection": 32, + "smart_rollup_timeout_period_in_blocks": 60480, + "smart_rollup_max_number_of_cemented_commitments": 5, + "smart_rollup_max_number_of_parallel_games": 32, + "smart_rollup_reveal_activation_level": + { "raw_data": { "Blake2B": 0 }, "metadata": 0, "dal_page": 1, + "dal_parameters": 1, "dal_attested_slots_validity_lag": 241920 }, + "smart_rollup_private_enable": true, + "smart_rollup_riscv_pvm_enable": false, "zk_rollup_enable": false, + "zk_rollup_origination_size": 4000, "zk_rollup_min_pending_to_process": 10, + "zk_rollup_max_ticket_payload_size": 2048, + "global_limit_of_staking_over_baking": 5, + "edge_of_staking_over_delegation": 2, + "adaptive_issuance_launch_ema_threshold": 0, + "adaptive_rewards_params": + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", + "growth_rate": { "numerator": "1", "denominator": "100" }, + "center_dz": { "numerator": "1", "denominator": "2" }, + "radius_dz": { "numerator": "1", "denominator": "50" } }, + "adaptive_issuance_activation_vote_enable": true, + "autostaking_enable": true, "adaptive_issuance_force_activation": false, + "ns_enable": true, "direct_ticket_spending_enable": false } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/helpers/baking_rights +[ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 10, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/helpers/baking_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' +{ "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/context/denunciations +[] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/helpers/attestation_rights +[ { "level": 1, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 11, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 4, "attestation_power": 47, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 2, "attestation_power": 46, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 55, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 0, "attestation_power": 58, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client --mode proxy rpc get '/chains/main/blocks/head/helpers/attestation_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 1, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 11, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle +{ "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- votes.out new file mode 100644 index 000000000000..1bf5d004e281 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy) RPC regression tests- votes.out @@ -0,0 +1,78 @@ + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/ballot_list +[] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "0", "nay": "0", "pass": "0" } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 1, "remaining": 2 } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/current_proposal +null + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" } ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/proposals +[ [ "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp", "4000000000000" ] ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 2, "remaining": 1 } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/total_voting_power +"20000000000000" + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/ballot_list +[ { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "nay" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "pass" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "yay" } ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "4000001679643", "nay": "4000000000000", "pass": "4000000000000" } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 0, "remaining": 3 } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/current_proposal +"ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp" + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000001679643" } ] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/proposals +[] + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 1, "remaining": 2 } + +./octez-client --mode proxy rpc get /chains/main/blocks/head/votes/total_voting_power +"20000001679643" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out new file mode 100644 index 000000000000..ad45f80f6fde --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- adaptive_issuance.out @@ -0,0 +1,67 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/total_supply +"20000001416766" + +./octez-client rpc get /chains/main/blocks/head/context/total_frozen_stake +"1000000000000" + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate +"210.260" + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_exact +{ "numerator": "700868433120000", "denominator": "3333333569461" } + +./octez-client rpc get /chains/main/blocks/head/context/issuance/issuance_per_minute +"80007812" + +./octez-client rpc get /chains/main/blocks/head/context/adaptive_issuance_launch_cycle +5 + +./octez-client rpc get /chains/main/blocks/head/context/issuance/expected_issuance +[ { "cycle": 0, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 1, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 2, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" } ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/stakers' +[ { "staker": "[PUBLIC_KEY_HASH]", + "frozen_deposits": "200000000000" } ] + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_details +{ "static": + { "numerator": "700868433120000", "denominator": "3333333569461" }, + "dynamic": { "numerator": "0", "denominator": "1" } } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/total_delegated_stake' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_denominator' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/staking_numerator' +"0" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- contracts.out new file mode 100644 index 000000000000..f0233dd45418 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- contracts.out @@ -0,0 +1,553 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "3800000000000", + "delegate": "[PUBLIC_KEY_HASH]", "counter": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "100000000", "counter": "1" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"100000000" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"1" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "99999566", "delegate": "[PUBLIC_KEY_HASH]", + "counter": "4" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"99999566" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"4" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": + { "prim": "Some", "args": [ { "string": "initial storage" } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": {} } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": { "prim": "Some", "args": [ { "string": "initial storage" } ] } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Some", "args": [ { "string": "initial storage" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", + "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": + [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": + { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": + { "rem_right": { "prim": "string" }, "rem_left": { "prim": "string" }, + "rem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%rem_left" ] }, + { "prim": "string", "annots": [ "%rem_right" ] } ] }, + "mem_right": { "prim": "string" }, "mem_left": { "prim": "string" }, + "mem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", "annots": [ "%mem_right" ] } ] }, + "default": { "prim": "unit" }, + "add_right": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add_left": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add": + { "prim": "or", + "args": + [ { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_right" ] } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "test" + }, + "type": { + "prim": "string" + } +}' +null + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "dup" + }, + "type": { + "prim": "string" + } +}' +null diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- delegates.out new file mode 100644 index 000000000000..29602dc55a14 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- delegates.out @@ -0,0 +1,102 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 5, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +"200000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +false + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +[ "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +5 + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +Fatal error: + Command failed: The implicit account ([PUBLIC_KEY_HASH]) whose balance was requested is not a registered delegate. To get the balance of this account you can use the ../context/contracts/[PUBLIC_KEY_HASH]/balance RPC. + The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out new file mode 100644 index 000000000000..01b7d506f3af --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out @@ -0,0 +1,137 @@ + +./octez-client rpc get /chains/main/blocks/head/context/constants +{ "proof_of_work_nonce_size": 8, "nonce_length": 32, + "max_anon_ops_per_block": 132, "max_operation_data_length": 32768, + "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, + "max_micheline_bytes_limit": 50000, + "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, + "michelson_maximum_type_size": 2001, "max_slashing_period": 2, + "smart_rollup_max_wrapped_proof_binary_size": 30000, + "smart_rollup_message_size_limit": 4096, + "smart_rollup_max_number_of_messages_per_level": "1000000", + "consensus_rights_delay": 2, "blocks_preservation_cycles": 1, + "delegate_parameters_activation_delay": 2, "blocks_per_cycle": 8, + "blocks_per_commitment": 4, "nonce_revelation_threshold": 4, + "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", + "hard_gas_limit_per_block": "1733333", + "proof_of_work_threshold": "4611686018427387903", + "minimal_stake": "6000000000", "minimal_frozen_stake": "600000000", + "vdf_difficulty": "50000", "origination_size": 257, + "issuance_weights": + { "base_total_issued_per_minute": "80007812", + "baking_reward_fixed_portion_weight": 5120, + "baking_reward_bonus_weight": 5120, "attesting_reward_weight": 10240, + "seed_nonce_revelation_tip_weight": 1, "vdf_revelation_tip_weight": 1 }, + "cost_per_byte": "250", "hard_storage_limit_per_operation": "60000", + "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, + "liquidity_baking_subsidy": "5000000", + "liquidity_baking_toggle_ema_threshold": 1000000000, + "max_operations_time_to_live": 8, "minimal_block_delay": "1", + "delay_increment_per_round": "1", "consensus_committee_size": 256, + "consensus_threshold": 0, + "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, + "limit_of_delegation_over_baking": 19, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, + "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, + "cache_sampler_state_cycles": 8, + "dal_parametric": + { "feature_enable": true, "incentives_enable": false, + "number_of_slots": 16, "attestation_lag": 8, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, + "smart_rollup_arith_pvm_enable": false, + "smart_rollup_origination_size": 6314, + "smart_rollup_challenge_window_in_blocks": 120960, + "smart_rollup_stake_amount": "10000000000", + "smart_rollup_commitment_period_in_blocks": 90, + "smart_rollup_max_lookahead_in_blocks": 259200, + "smart_rollup_max_active_outbox_levels": 120960, + "smart_rollup_max_outbox_messages_per_level": 100, + "smart_rollup_number_of_sections_in_dissection": 32, + "smart_rollup_timeout_period_in_blocks": 60480, + "smart_rollup_max_number_of_cemented_commitments": 5, + "smart_rollup_max_number_of_parallel_games": 32, + "smart_rollup_reveal_activation_level": + { "raw_data": { "Blake2B": 0 }, "metadata": 0, "dal_page": 1, + "dal_parameters": 1, "dal_attested_slots_validity_lag": 241920 }, + "smart_rollup_private_enable": true, + "smart_rollup_riscv_pvm_enable": false, "zk_rollup_enable": false, + "zk_rollup_origination_size": 4000, "zk_rollup_min_pending_to_process": 10, + "zk_rollup_max_ticket_payload_size": 2048, + "global_limit_of_staking_over_baking": 5, + "edge_of_staking_over_delegation": 2, + "adaptive_issuance_launch_ema_threshold": 0, + "adaptive_rewards_params": + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", + "growth_rate": { "numerator": "1", "denominator": "100" }, + "center_dz": { "numerator": "1", "denominator": "2" }, + "radius_dz": { "numerator": "1", "denominator": "50" } }, + "adaptive_issuance_activation_vote_enable": true, + "autostaking_enable": true, "adaptive_issuance_force_activation": false, + "ns_enable": true, "direct_ticket_spending_enable": false } + +./octez-client rpc get /chains/main/blocks/head/helpers/baking_rights +[ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 4, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/baking_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' +{ "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } + +./octez-client rpc get /chains/main/blocks/head/context/denunciations +[] + +./octez-client rpc get /chains/main/blocks/head/helpers/attestation_rights +[ { "level": 2, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 10, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 3, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 2, "attestation_power": 65, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 0, "attestation_power": 41, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/attestation_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 2, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle +{ "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- votes.out new file mode 100644 index 000000000000..92b45913298a --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_data_dir) RPC regression tests- votes.out @@ -0,0 +1,78 @@ + +./octez-client rpc get /chains/main/blocks/head/votes/ballot_list +[] + +./octez-client rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "0", "nay": "0", "pass": "0" } + +./octez-client rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 2, "remaining": 1 } + +./octez-client rpc get /chains/main/blocks/head/votes/current_proposal +null + +./octez-client rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/proposals +[ [ "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp", "4000000000000" ] ] + +./octez-client rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 3, "remaining": 0 } + +./octez-client rpc get /chains/main/blocks/head/votes/total_voting_power +"20000000000000" + +./octez-client rpc get /chains/main/blocks/head/votes/ballot_list +[ { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "nay" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "pass" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "yay" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "4000001679643", "nay": "4000000000000", "pass": "4000000000000" } + +./octez-client rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 1, "remaining": 2 } + +./octez-client rpc get /chains/main/blocks/head/votes/current_proposal +"ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp" + +./octez-client rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000001679643" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/proposals +[] + +./octez-client rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 2, "remaining": 1 } + +./octez-client rpc get /chains/main/blocks/head/votes/total_voting_power +"20000001679643" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out new file mode 100644 index 000000000000..ad45f80f6fde --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- adaptive_issuance.out @@ -0,0 +1,67 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/total_supply +"20000001416766" + +./octez-client rpc get /chains/main/blocks/head/context/total_frozen_stake +"1000000000000" + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate +"210.260" + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_exact +{ "numerator": "700868433120000", "denominator": "3333333569461" } + +./octez-client rpc get /chains/main/blocks/head/context/issuance/issuance_per_minute +"80007812" + +./octez-client rpc get /chains/main/blocks/head/context/adaptive_issuance_launch_cycle +5 + +./octez-client rpc get /chains/main/blocks/head/context/issuance/expected_issuance +[ { "cycle": 0, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 1, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" }, + { "cycle": 2, "baking_reward_fixed_portion": "333333", + "baking_reward_bonus_per_slot": "1302", + "attesting_reward_per_slot": "2604", "seed_nonce_revelation_tip": "260", + "vdf_revelation_tip": "260" } ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/stakers' +[ { "staker": "[PUBLIC_KEY_HASH]", + "frozen_deposits": "200000000000" } ] + +./octez-client rpc get /chains/main/blocks/head/context/issuance/current_yearly_rate_details +{ "static": + { "numerator": "700868433120000", "denominator": "3333333569461" }, + "dynamic": { "numerator": "0", "denominator": "1" } } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/total_delegated_stake' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_denominator' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/staking_numerator' +"0" diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- contracts.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- contracts.out new file mode 100644 index 000000000000..f0233dd45418 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- contracts.out @@ -0,0 +1,553 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "3800000000000", + "delegate": "[PUBLIC_KEY_HASH]", "counter": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "100000000", "counter": "1" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"100000000" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"1" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "99999566", "delegate": "[PUBLIC_KEY_HASH]", + "counter": "4" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"99999566" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/counter' +"4" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/manager_key' +"[PUBLIC_KEY]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/delegate' +"[PUBLIC_KEY_HASH]" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/entrypoints' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/script' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/storage' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": + { "prim": "Some", "args": [ { "string": "initial storage" } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": {} } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": { "prim": "Some", "args": [ { "string": "initial storage" } ] } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Some", "args": [ { "string": "initial storage" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]' +{ "balance": "0", + "script": + { "code": + [ { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", + "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": + [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": + "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": + { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/counter' +Fatal error: + No service found at this URL + + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/manager_key' +Fatal error: + No service found at this URL + + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "int": "0" + }, + "type": { + "prim": "int" + } +}' +null + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/entrypoints' +{ "entrypoints": + { "rem_right": { "prim": "string" }, "rem_left": { "prim": "string" }, + "rem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%rem_left" ] }, + { "prim": "string", "annots": [ "%rem_right" ] } ] }, + "mem_right": { "prim": "string" }, "mem_left": { "prim": "string" }, + "mem": + { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", "annots": [ "%mem_right" ] } ] }, + "default": { "prim": "unit" }, + "add_right": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add_left": + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + "add": + { "prim": "or", + "args": + [ { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": [ { "prim": "string" }, { "prim": "nat" } ], + "annots": [ "%add_right" ] } ] } } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/script' +{ "code": + [ { "prim": "storage", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] }, + { "prim": "big_map", + "args": [ { "prim": "string" }, { "prim": "nat" } ] } ] } ] }, + { "prim": "parameter", + "args": + [ { "prim": "or", + "args": + [ { "prim": "unit", "annots": [ "%default" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "string", "annots": [ "%mem_left" ] }, + { "prim": "string", + "annots": [ "%mem_right" ] } ], + "annots": [ "%mem" ] }, + { "prim": "or", + "args": + [ { "prim": "or", + "args": + [ { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_left" ] }, + { "prim": "pair", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ], + "annots": [ "%add_right" ] } ], + "annots": [ "%add" ] }, + { "prim": "or", + "args": + [ { "prim": "string", + "annots": [ "%rem_left" ] }, + { "prim": "string", + "annots": [ "%rem_right" ] } ], + "annots": [ "%rem" ] } ] } ] } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DROP" }, { "prim": "DUP" }, + { "prim": "CAR" }, + { "prim": "PUSH", + "args": [ { "prim": "mutez" }, { "int": "0" } ] }, + { "prim": "NONE", "args": [ { "prim": "key_hash" } ] }, + { "prim": "CREATE_CONTRACT", + "args": + [ [ { "prim": "parameter", + "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "big_map", + "args": + [ { "prim": "string" }, + { "prim": "nat" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DROP" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] }, + { "prim": "DIP", "args": [ [ { "prim": "DROP" } ] ] }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "SWAP" }, { "prim": "CONS" }, + { "prim": "PAIR" } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ] ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": [ [ { "prim": "DUP" } ] ] }, + { "prim": "MEM" }, + [ { "prim": "IF", + "args": + [ [], + [ [ { "prim": "UNIT" }, + { "prim": "FAILWITH" } ] ] ] } ], + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "UNPAIR" }, + { "prim": "DIP", + "args": + [ { "int": "2" }, + [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "SOME" } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ], + [ { "prim": "IF_LEFT", + "args": + [ [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" } ], + [ { "prim": "DIP", + "args": + [ [ { "prim": "UNPAIR" }, + { "prim": "SWAP" } ] ] }, + { "prim": "DIP", + "args": + [ [ { "prim": "NONE", + "args": + [ { "prim": "nat" } ] } ] ] }, + { "prim": "UPDATE" }, + { "prim": "SWAP" } ] ] } ] ] } ] ] }, + { "prim": "PAIR" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ] ] } ], + "storage": { "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "prim": "Pair", "args": [ { "int": "4" }, { "int": "5" } ] } + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "test" + }, + "type": { + "prim": "string" + } +}' +null + +./octez-client rpc post '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/big_map_get' with '{ + "key": { + "string": "dup" + }, + "type": { + "prim": "string" + } +}' +null diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- delegates.out new file mode 100644 index 000000000000..29602dc55a14 --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- delegates.out @@ -0,0 +1,102 @@ + +./octez-client rpc get /chains/main/blocks/head/context/contracts +[ "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[CONTRACT_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get /chains/main/blocks/head/context/delegates +[ "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]", + "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 5, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +"200000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +false + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +[ "[PUBLIC_KEY_HASH]" ] + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +5 + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +"4000000000000" + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' +Fatal error: + Command failed: The implicit account ([PUBLIC_KEY_HASH]) whose balance was requested is not a registered delegate. To get the balance of this account you can use the ../context/contracts/[PUBLIC_KEY_HASH]/balance RPC. + The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/frozen_deposits' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/deactivated' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/delegated_contracts' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/grace_period' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/staking_balance' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/voting_power' +Fatal error: + Command failed: The provided public key hash ([PUBLIC_KEY_HASH]) is not the address of a registered delegate. If you own this account and want to register it as a delegate, use a delegation operation to delegate the account to itself. + diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out new file mode 100644 index 000000000000..01b7d506f3af --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out @@ -0,0 +1,137 @@ + +./octez-client rpc get /chains/main/blocks/head/context/constants +{ "proof_of_work_nonce_size": 8, "nonce_length": 32, + "max_anon_ops_per_block": 132, "max_operation_data_length": 32768, + "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, + "max_micheline_bytes_limit": 50000, + "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, + "michelson_maximum_type_size": 2001, "max_slashing_period": 2, + "smart_rollup_max_wrapped_proof_binary_size": 30000, + "smart_rollup_message_size_limit": 4096, + "smart_rollup_max_number_of_messages_per_level": "1000000", + "consensus_rights_delay": 2, "blocks_preservation_cycles": 1, + "delegate_parameters_activation_delay": 2, "blocks_per_cycle": 8, + "blocks_per_commitment": 4, "nonce_revelation_threshold": 4, + "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", + "hard_gas_limit_per_block": "1733333", + "proof_of_work_threshold": "4611686018427387903", + "minimal_stake": "6000000000", "minimal_frozen_stake": "600000000", + "vdf_difficulty": "50000", "origination_size": 257, + "issuance_weights": + { "base_total_issued_per_minute": "80007812", + "baking_reward_fixed_portion_weight": 5120, + "baking_reward_bonus_weight": 5120, "attesting_reward_weight": 10240, + "seed_nonce_revelation_tip_weight": 1, "vdf_revelation_tip_weight": 1 }, + "cost_per_byte": "250", "hard_storage_limit_per_operation": "60000", + "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, + "liquidity_baking_subsidy": "5000000", + "liquidity_baking_toggle_ema_threshold": 1000000000, + "max_operations_time_to_live": 8, "minimal_block_delay": "1", + "delay_increment_per_round": "1", "consensus_committee_size": 256, + "consensus_threshold": 0, + "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, + "limit_of_delegation_over_baking": 19, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, + "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, + "cache_sampler_state_cycles": 8, + "dal_parametric": + { "feature_enable": true, "incentives_enable": false, + "number_of_slots": 16, "attestation_lag": 8, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, + "smart_rollup_arith_pvm_enable": false, + "smart_rollup_origination_size": 6314, + "smart_rollup_challenge_window_in_blocks": 120960, + "smart_rollup_stake_amount": "10000000000", + "smart_rollup_commitment_period_in_blocks": 90, + "smart_rollup_max_lookahead_in_blocks": 259200, + "smart_rollup_max_active_outbox_levels": 120960, + "smart_rollup_max_outbox_messages_per_level": 100, + "smart_rollup_number_of_sections_in_dissection": 32, + "smart_rollup_timeout_period_in_blocks": 60480, + "smart_rollup_max_number_of_cemented_commitments": 5, + "smart_rollup_max_number_of_parallel_games": 32, + "smart_rollup_reveal_activation_level": + { "raw_data": { "Blake2B": 0 }, "metadata": 0, "dal_page": 1, + "dal_parameters": 1, "dal_attested_slots_validity_lag": 241920 }, + "smart_rollup_private_enable": true, + "smart_rollup_riscv_pvm_enable": false, "zk_rollup_enable": false, + "zk_rollup_origination_size": 4000, "zk_rollup_min_pending_to_process": 10, + "zk_rollup_max_ticket_payload_size": 2048, + "global_limit_of_staking_over_baking": 5, + "edge_of_staking_over_delegation": 2, + "adaptive_issuance_launch_ema_threshold": 0, + "adaptive_rewards_params": + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", + "growth_rate": { "numerator": "1", "denominator": "100" }, + "center_dz": { "numerator": "1", "denominator": "2" }, + "radius_dz": { "numerator": "1", "denominator": "50" } }, + "adaptive_issuance_activation_vote_enable": true, + "autostaking_enable": true, "adaptive_issuance_force_activation": false, + "ns_enable": true, "direct_ticket_spending_enable": false } + +./octez-client rpc get /chains/main/blocks/head/helpers/baking_rights +[ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 4, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/baking_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' +{ "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } + +./octez-client rpc get /chains/main/blocks/head/context/denunciations +[] + +./octez-client rpc get /chains/main/blocks/head/helpers/attestation_rights +[ { "level": 2, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 10, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 3, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 2, "attestation_power": 65, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, + { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 0, "attestation_power": 41, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client rpc get '/chains/main/blocks/head/helpers/attestation_rights?delegate=[PUBLIC_KEY_HASH]' +[ { "level": 2, + "delegates": + [ { "delegate": "[PUBLIC_KEY_HASH]", + "first_slot": 1, "attestation_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] + +./octez-client rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle +{ "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- votes.out b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- votes.out new file mode 100644 index 000000000000..92b45913298a --- /dev/null +++ b/tezt/tests/expected/RPC_test.ml/Parisc- (mode proxy_server_rpc) RPC regression tests- votes.out @@ -0,0 +1,78 @@ + +./octez-client rpc get /chains/main/blocks/head/votes/ballot_list +[] + +./octez-client rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "0", "nay": "0", "pass": "0" } + +./octez-client rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 2, "remaining": 1 } + +./octez-client rpc get /chains/main/blocks/head/votes/current_proposal +null + +./octez-client rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/proposals +[ [ "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp", "4000000000000" ] ] + +./octez-client rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 3, "remaining": 0 } + +./octez-client rpc get /chains/main/blocks/head/votes/total_voting_power +"20000000000000" + +./octez-client rpc get /chains/main/blocks/head/votes/ballot_list +[ { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "nay" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "pass" }, + { "pkh": "[PUBLIC_KEY_HASH]", "ballot": "yay" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/ballots +{ "yay": "4000001679643", "nay": "4000000000000", "pass": "4000000000000" } + +./octez-client rpc get /chains/main/blocks/head/votes/current_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 1, "remaining": 2 } + +./octez-client rpc get /chains/main/blocks/head/votes/current_proposal +"ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp" + +./octez-client rpc get /chains/main/blocks/head/votes/current_quorum +5500 + +./octez-client rpc get /chains/main/blocks/head/votes/listings +[ { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000000000000" }, + { "pkh": "[PUBLIC_KEY_HASH]", + "voting_power": "4000001679643" } ] + +./octez-client rpc get /chains/main/blocks/head/votes/proposals +[] + +./octez-client rpc get /chains/main/blocks/head/votes/successor_period +{ "voting_period": { "index": 1, "kind": "exploration", "start_position": 4 }, + "position": 2, "remaining": 1 } + +./octez-client rpc get /chains/main/blocks/head/votes/total_voting_power +"20000001679643" diff --git a/tezt/tests/expected/baker_test.ml/Paris- Baker rewards.out b/tezt/tests/expected/baker_test.ml/Parisb- Baker rewards.out similarity index 100% rename from tezt/tests/expected/baker_test.ml/Paris- Baker rewards.out rename to tezt/tests/expected/baker_test.ml/Parisb- Baker rewards.out diff --git a/tezt/tests/expected/baker_test.ml/Parisc- Baker rewards.out b/tezt/tests/expected/baker_test.ml/Parisc- Baker rewards.out new file mode 100644 index 000000000000..b95cd6d1742e --- /dev/null +++ b/tezt/tests/expected/baker_test.ml/Parisc- Baker rewards.out @@ -0,0 +1,133 @@ + +./octez-client rpc get /chains/main/blocks/head/metadata +{ "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "next_protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "test_chain_status": { "status": "not_running" }, "max_operations_ttl": 2, + "max_operation_data_length": 32768, "max_block_header_length": 289, + "max_operation_list_length": + [ { "max_size": 4194304, "max_op": 2048 }, { "max_size": 32768 }, + { "max_size": 135168, "max_op": 132 }, { "max_size": 524288 } ], + "proposer": "[PUBLIC_KEY_HASH]", + "baker": "[PUBLIC_KEY_HASH]", + "level_info": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false }, + "voting_period_info": + { "voting_period": + { "index": 0, "kind": "proposal", "start_position": 0 }, + "position": 1, "remaining": 122878 }, "nonce_hash": null, + "deactivated": [], + "balance_updates": + [ { "kind": "minted", "category": "bootstrap", + "change": "-20000000000000", "origin": "migration" }, + { "kind": "freezer", "category": "deposits", + "staker": + { "baker_own_stake": "[PUBLIC_KEY_HASH]" }, + "change": "400000000000", "origin": "migration" }, + { "kind": "freezer", "category": "deposits", + "staker": + { "baker_own_stake": "[PUBLIC_KEY_HASH]" }, + "change": "400000000000", "origin": "migration" }, + { "kind": "freezer", "category": "deposits", + "staker": + { "baker_own_stake": "[PUBLIC_KEY_HASH]" }, + "change": "400000000000", "origin": "migration" }, + { "kind": "freezer", "category": "deposits", + "staker": + { "baker_own_stake": "[PUBLIC_KEY_HASH]" }, + "change": "400000000000", "origin": "migration" }, + { "kind": "freezer", "category": "deposits", + "staker": + { "baker_own_stake": "[PUBLIC_KEY_HASH]" }, + "change": "400000000000", "origin": "migration" }, + { "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "3600000000000", "origin": "migration" }, + { "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "3600000000000", "origin": "migration" }, + { "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "3600000000000", "origin": "migration" }, + { "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "3600000000000", "origin": "migration" }, + { "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "3600000000000", "origin": "migration" }, + { "kind": "minted", "category": "baking rewards", "change": "-333334", + "origin": "block" }, + { "kind": "freezer", "category": "deposits", + "staker": + { "baker_own_stake": "[PUBLIC_KEY_HASH]" }, + "change": "333334", "origin": "block" }, + { "kind": "minted", "category": "baking rewards", "change": "-2999999", + "origin": "block" }, + { "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "2999999", "origin": "block" } ], + "liquidity_baking_toggle_ema": 0, "adaptive_issuance_vote_ema": 0, + "adaptive_issuance_activation_cycle": 5, + "implicit_operations_results": + [ { "kind": "origination", + "balance_updates": + [ { "kind": "minted", "category": "subsidy", "change": "-64250", + "origin": "migration" }, + { "kind": "burned", "category": "storage fees", + "change": "64250", "origin": "migration" }, + { "kind": "minted", "category": "subsidy", "change": "-1157000", + "origin": "migration" }, + { "kind": "burned", "category": "storage fees", + "change": "1157000", "origin": "migration" }, + { "kind": "minted", "category": "subsidy", "change": "-100", + "origin": "migration" }, + { "kind": "contract", + "contract": "[CONTRACT_HASH]", + "change": "100", "origin": "migration" } ], + "originated_contracts": [ "[CONTRACT_HASH]" ], + "storage_size": "4628", "paid_storage_size_diff": "4628" }, + { "kind": "origination", + "balance_updates": + [ { "kind": "minted", "category": "subsidy", "change": "-64250", + "origin": "migration" }, + { "kind": "burned", "category": "storage fees", + "change": "64250", "origin": "migration" }, + { "kind": "minted", "category": "subsidy", "change": "-494500", + "origin": "migration" }, + { "kind": "burned", "category": "storage fees", + "change": "494500", "origin": "migration" } ], + "originated_contracts": [ "[CONTRACT_HASH]" ], + "storage_size": "1978", "paid_storage_size_diff": "1978" }, + { "kind": "origination", + "balance_updates": + [ { "kind": "minted", "category": "subsidy", "change": "-64250", + "origin": "migration" }, + { "kind": "burned", "category": "storage fees", + "change": "64250", "origin": "migration" }, + { "kind": "minted", "category": "subsidy", "change": "-477750", + "origin": "migration" }, + { "kind": "burned", "category": "storage fees", + "change": "477750", "origin": "migration" }, + { "kind": "minted", "category": "subsidy", "change": "-1000000", + "origin": "migration" }, + { "kind": "contract", + "contract": "[CONTRACT_HASH]", + "change": "1000000", "origin": "migration" } ], + "originated_contracts": [ "[CONTRACT_HASH]" ], + "storage_size": "1911", "paid_storage_size_diff": "1911" }, + { "kind": "transaction", + "storage": + [ { "int": "1" }, { "int": "833433" }, { "int": "100" }, + { "bytes": "01e927f00ef734dfc85919635e9afc9166c83ef9fc00" }, + { "bytes": "0115eb0104481a6d7921160bc982c5e0a561cd8a3a00" } ], + "balance_updates": + [ { "kind": "minted", "category": "subsidy", "change": "-833333", + "origin": "subsidy" }, + { "kind": "contract", + "contract": "[CONTRACT_HASH]", + "change": "833333", "origin": "subsidy" } ], + "consumed_milligas": "2261927", "storage_size": "4629", + "paid_storage_size_diff": "1" } ], + "proposer_consensus_key": "[PUBLIC_KEY_HASH]", + "baker_consensus_key": "[PUBLIC_KEY_HASH]", + "consumed_milligas": "0", "dal_attestation": "0" } diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker - delegate - consensus - destination).out b/tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker - delegate - consensus - destination).out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker - delegate - consensus - destination).out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker - delegate - consensus - destination).out diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker - delegate - consensus -- destination).out b/tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker - delegate - consensus -- destination).out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker - delegate - consensus -- destination).out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker - delegate - consensus -- destination).out diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker -- delegate - consensus - destination).out b/tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker -- delegate - consensus - destination).out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker -- delegate - consensus - destination).out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker -- delegate - consensus - destination).out diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker -- delegate - consensus -- destination).out b/tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker -- delegate - consensus -- destination).out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test drain delegate with (baker -- delegate - consensus -- destination).out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test drain delegate with (baker -- delegate - consensus -- destination).out diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test register with consensus key.out b/tezt/tests/expected/consensus_key.ml/Parisb- Test register with consensus key.out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test register with consensus key.out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test register with consensus key.out diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test set consensus key - baker is delegate.out b/tezt/tests/expected/consensus_key.ml/Parisb- Test set consensus key - baker is delegate.out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test set consensus key - baker is delegate.out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test set consensus key - baker is delegate.out diff --git a/tezt/tests/expected/consensus_key.ml/Paris- Test set consensus key - baker is not delegate.out b/tezt/tests/expected/consensus_key.ml/Parisb- Test set consensus key - baker is not delegate.out similarity index 100% rename from tezt/tests/expected/consensus_key.ml/Paris- Test set consensus key - baker is not delegate.out rename to tezt/tests/expected/consensus_key.ml/Parisb- Test set consensus key - baker is not delegate.out diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus - destination).out b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus - destination).out new file mode 100644 index 000000000000..6c45d78fb530 --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus - destination).out @@ -0,0 +1,143 @@ + +./octez-client --wait none set consensus key for bootstrap1 to dummy_account_0 +Node is bootstrapped. +Estimated gas: 168.946 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000284 + Expected counter: 1 + Gas limit: 269 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000284 + payload fees(the block proposer) ....... +ꜩ0.000284 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 168.880 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000333333", "current_frozen_deposits": "200000016667", + "frozen_deposits": "200000000000", "staking_balance": "4000000333333", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3799999999716", + "level": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000003298113", "current_frozen_deposits": "200000164906", + "frozen_deposits": "200000000000", "staking_balance": "4000003298113", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001595660", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000003298113", "current_frozen_deposits": "200000164906", + "frozen_deposits": "200000000000", "staking_balance": "4000003298113", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001595660", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800003133203" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client --wait none drain delegate bootstrap1 to dummy_account_0 with dummy_account_0 +Node is bootstrapped. +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Drain delegate: + Consensus key hash: [PUBLIC_KEY_HASH] + Delegate: [PUBLIC_KEY_HASH] + Destination: [PUBLIC_KEY_HASH] (allocated) + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ3762003.038264 + [PUBLIC_KEY_HASH] ... +ꜩ3762003.038264 + [PUBLIC_KEY_HASH] ... -ꜩ38000.030689 + [PUBLIC_KEY_HASH] ... +ꜩ38000.030689 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "238000528932", "current_frozen_deposits": "200000181573", + "frozen_deposits": "200000083983", "staking_balance": "238000528932", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "4", + "level": + { "level": 9, "level_position": 8, "cycle": 2, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 4, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"38000347355" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3762003038264" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3762003038264" diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus -- destination).out b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus -- destination).out new file mode 100644 index 000000000000..181861305420 --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker - delegate - consensus -- destination).out @@ -0,0 +1,143 @@ + +./octez-client --wait none set consensus key for bootstrap1 to dummy_account_0 +Node is bootstrapped. +Estimated gas: 168.946 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000284 + Expected counter: 1 + Gas limit: 269 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000284 + payload fees(the block proposer) ....... +ꜩ0.000284 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 168.880 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000333333", "current_frozen_deposits": "200000016667", + "frozen_deposits": "200000000000", "staking_balance": "4000000333333", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3799999999716", + "level": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000003298113", "current_frozen_deposits": "200000164906", + "frozen_deposits": "200000000000", "staking_balance": "4000003298113", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001595660", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000003298113", "current_frozen_deposits": "200000164906", + "frozen_deposits": "200000000000", "staking_balance": "4000003298113", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001595660", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800003133203" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client --wait none drain delegate bootstrap1 to dummy_account_1 with dummy_account_0 +Node is bootstrapped. +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Drain delegate: + Consensus key hash: [PUBLIC_KEY_HASH] + Delegate: [PUBLIC_KEY_HASH] + Destination: [PUBLIC_KEY_HASH] (allocated) + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ3762003.038264 + [PUBLIC_KEY_HASH] ... +ꜩ3762003.038264 + [PUBLIC_KEY_HASH] ... -ꜩ38000.030689 + [PUBLIC_KEY_HASH] ... +ꜩ38000.030689 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "238000528932", "current_frozen_deposits": "200000181573", + "frozen_deposits": "200000083983", "staking_balance": "238000528932", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "4", + "level": + { "level": 9, "level_position": 8, "cycle": 2, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 4, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"38000347355" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3762003038264" diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus - destination).out b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus - destination).out new file mode 100644 index 000000000000..3a0272bda3bb --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus - destination).out @@ -0,0 +1,143 @@ + +./octez-client --wait none set consensus key for bootstrap1 to dummy_account_0 +Node is bootstrapped. +Estimated gas: 168.946 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000284 + Expected counter: 1 + Gas limit: 269 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000284 + payload fees(the block proposer) ....... +ꜩ0.000284 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 168.880 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "3999999999716", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "3999999999716", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3799999999716", + "level": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000002964496", "current_frozen_deposits": "200000148225", + "frozen_deposits": "200000000000", "staking_balance": "4000002964496", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001278724", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000002964496", "current_frozen_deposits": "200000148225", + "frozen_deposits": "200000000000", "staking_balance": "4000002964496", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001278724", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800002816253" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client --wait none drain delegate bootstrap1 to dummy_account_0 with dummy_account_0 +Node is bootstrapped. +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Drain delegate: + Consensus key hash: [PUBLIC_KEY_HASH] + Delegate: [PUBLIC_KEY_HASH] + Destination: [PUBLIC_KEY_HASH] (allocated) + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ3762002.724483 + [PUBLIC_KEY_HASH] ... +ꜩ3762002.724483 + [PUBLIC_KEY_HASH] ... -ꜩ38000.02752 + [PUBLIC_KEY_HASH] ... +ꜩ38000.02752 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "238000509096", "current_frozen_deposits": "200000164892", + "frozen_deposits": "200000067302", "staking_balance": "238000509096", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "18", + "level": + { "level": 9, "level_position": 8, "cycle": 2, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 4, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"38000344186" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3762002724483" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3762002724483" diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus -- destination).out b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus -- destination).out new file mode 100644 index 000000000000..77a75198688f --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test drain delegate with (baker -- delegate - consensus -- destination).out @@ -0,0 +1,143 @@ + +./octez-client --wait none set consensus key for bootstrap1 to dummy_account_0 +Node is bootstrapped. +Estimated gas: 168.946 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000284 + Expected counter: 1 + Gas limit: 269 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000284 + payload fees(the block proposer) ....... +ꜩ0.000284 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 168.880 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "3999999999716", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "3999999999716", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3799999999716", + "level": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000002964496", "current_frozen_deposits": "200000148225", + "frozen_deposits": "200000000000", "staking_balance": "4000002964496", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001278724", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000002964496", "current_frozen_deposits": "200000148225", + "frozen_deposits": "200000000000", "staking_balance": "4000002964496", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001278724", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3800002816253" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client --wait none drain delegate bootstrap1 to dummy_account_1 with dummy_account_0 +Node is bootstrapped. +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Drain delegate: + Consensus key hash: [PUBLIC_KEY_HASH] + Delegate: [PUBLIC_KEY_HASH] + Destination: [PUBLIC_KEY_HASH] (allocated) + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ3762002.724483 + [PUBLIC_KEY_HASH] ... +ꜩ3762002.724483 + [PUBLIC_KEY_HASH] ... -ꜩ38000.02752 + [PUBLIC_KEY_HASH] ... +ꜩ38000.02752 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "238000509096", "current_frozen_deposits": "200000164892", + "frozen_deposits": "200000067302", "staking_balance": "238000509096", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "18", + "level": + { "level": 9, "level_position": 8, "cycle": 2, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 4, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"38000344186" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"0" + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/balance' +"3762002724483" diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test register with consensus key.out b/tezt/tests/expected/consensus_key.ml/Parisc- Test register with consensus key.out new file mode 100644 index 000000000000..4430708cc746 --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test register with consensus key.out @@ -0,0 +1,90 @@ + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "1" } + +./octez-client --wait none register key dummy_account_0 as delegate with consensus key dummy_account_1 +Node is bootstrapped. +Estimated gas: 172.756 units (will add 0 for safety) +Estimated storage: no bytes added +Estimated gas: 100 units (will add 0 for safety) +Estimated storage: no bytes added +Estimated gas: 100 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000275 + Expected counter: 2 + Gas limit: 173 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000275 + payload fees(the block proposer) ....... +ꜩ0.000275 + Revelation of manager public key: + Contract: [PUBLIC_KEY_HASH] + Key: [PUBLIC_KEY] + This revelation was successfully applied + Consumed gas: 172.524 + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000159 + Expected counter: 3 + Gas limit: 100 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000159 + payload fees(the block proposer) ....... +ꜩ0.000159 + Delegation: + Contract: [PUBLIC_KEY_HASH] + To: [PUBLIC_KEY_HASH] + This delegation was successfully applied + Consumed gas: 100 + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000181 + Expected counter: 4 + Gas limit: 200 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000181 + payload fees(the block proposer) ....... +ꜩ0.000181 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 100 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "999999999385", "current_frozen_deposits": "0", + "frozen_deposits": "0", "staking_balance": "999999999385", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "999999999385", + "level": + { "level": 3, "level_position": 2, "cycle": 0, "cycle_position": 2, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]' +{ "balance": "0", "counter": "4" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "999999999385", "current_frozen_deposits": "49999999970", + "frozen_deposits": "0", "staking_balance": "999999999385", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": { "amount": "949999999415" }, + "deactivated": false, "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "active_consensus_key": "[PUBLIC_KEY_HASH]" } diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is delegate.out b/tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is delegate.out new file mode 100644 index 000000000000..b410b3ee2c9e --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is delegate.out @@ -0,0 +1,73 @@ + +./octez-client --wait none set consensus key for bootstrap1 to dummy_account_0 +Node is bootstrapped. +Estimated gas: 168.946 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000284 + Expected counter: 1 + Gas limit: 269 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000284 + payload fees(the block proposer) ....... +ꜩ0.000284 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 168.880 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000333333", "current_frozen_deposits": "200000016667", + "frozen_deposits": "200000000000", "staking_balance": "4000000333333", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3799999999716", + "level": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000003298113", "current_frozen_deposits": "200000164906", + "frozen_deposits": "200000000000", "staking_balance": "4000003298113", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001595660", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } diff --git a/tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is not delegate.out b/tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is not delegate.out new file mode 100644 index 000000000000..bc49237f11bc --- /dev/null +++ b/tezt/tests/expected/consensus_key.ml/Parisc- Test set consensus key - baker is not delegate.out @@ -0,0 +1,73 @@ + +./octez-client --wait none set consensus key for bootstrap1 to dummy_account_0 +Node is bootstrapped. +Estimated gas: 168.946 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000284 + Expected counter: 1 + Gas limit: 269 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000284 + payload fees(the block proposer) ....... +ꜩ0.000284 + Update_consensus_key: + Public key hash: [PUBLIC_KEY_HASH] + This consensus key update was successfully applied + Consumed gas: 168.880 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000000000000", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "4000000000000", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800000000000", + "level": + { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "3999999999716", "current_frozen_deposits": "200000000000", + "frozen_deposits": "200000000000", "staking_balance": "3999999999716", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3799999999716", + "level": + { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]", + "pending_consensus_keys": + [ { "cycle": 2, "pkh": "[PUBLIC_KEY_HASH]" } ] } + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "4000002964496", "current_frozen_deposits": "200000148225", + "frozen_deposits": "200000000000", "staking_balance": "4000002964496", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "3800001278724", + "level": + { "level": 5, "level_position": 4, "cycle": 1, "cycle_position": 0, + "expected_commitment": false } }, "deactivated": false, + "grace_period": 3, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } diff --git a/tezt/tests/expected/contract_liquidity_baking.ml/Paris- Test add-approve-transfer-remove liquidity.out b/tezt/tests/expected/contract_liquidity_baking.ml/Parisb- Test add-approve-transfer-remove liquidity.out similarity index 100% rename from tezt/tests/expected/contract_liquidity_baking.ml/Paris- Test add-approve-transfer-remove liquidity.out rename to tezt/tests/expected/contract_liquidity_baking.ml/Parisb- Test add-approve-transfer-remove liquidity.out diff --git a/tezt/tests/expected/contract_liquidity_baking.ml/Paris- Test trades.out b/tezt/tests/expected/contract_liquidity_baking.ml/Parisb- Test trades.out similarity index 100% rename from tezt/tests/expected/contract_liquidity_baking.ml/Paris- Test trades.out rename to tezt/tests/expected/contract_liquidity_baking.ml/Parisb- Test trades.out diff --git a/tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test add-approve-transfer-remove liquidity.out b/tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test add-approve-transfer-remove liquidity.out new file mode 100644 index 000000000000..cd9ec1cd3f98 --- /dev/null +++ b/tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test add-approve-transfer-remove liquidity.out @@ -0,0 +1,416 @@ + +./octez-client --mode mockup rpc get /chains/main/blocks/head/context/liquidity_baking/cpmm_address +"KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" + +./octez-client --mode mockup get contract storage for KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 +Pair 1 + 100 + 100 + "KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN" + "KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap1 --entrypoint mintOrBurn --arg '(Pair 100000000 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2375.517 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'opNV92qwY7YfY6exkBrJqnJyotKXFbxHdXEk7xNQFNsPRQ7TEjF' +NOT waiting for the operation to be included. +Use command + octez-client wait for opNV92qwY7YfY6exkBrJqnJyotKXFbxHdXEk7xNQFNsPRQ7TEjF to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.00056 + Expected counter: 1 + Gas limit: 2476 + Storage limit: 91 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.00056 + payload fees(the block proposer) ....... +ꜩ0.00056 + Transaction: + Amount: ꜩ0 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: mintOrBurn + Parameter: (Pair 100000000 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(0)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 100000000 + Storage size: 1982 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2375.881 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap1 --entrypoint approve --arg '(Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2377.220 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'op968yui6vHCCztECXMB24FEWbMUHed9jQkXbhL5WGM8wXJw96Q' +NOT waiting for the operation to be included. +Use command + octez-client wait for op968yui6vHCCztECXMB24FEWbMUHed9jQkXbhL5WGM8wXJw96Q to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.000558 + Expected counter: 2 + Gas limit: 2478 + Storage limit: 91 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000558 + payload fees(the block proposer) ....... +ꜩ0.000558 + Transaction: + Amount: ꜩ0 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: approve + Parameter: (Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 1000000000 + Storage size: 2053 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2377.584 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap2 --entrypoint approve --arg '(Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2377.220 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'op8vSFsuf9xDtpELfAXrAD31oBWvx4kvW2QWoEBUKqsiADKYgZB' +NOT waiting for the operation to be included. +Use command + octez-client wait for op8vSFsuf9xDtpELfAXrAD31oBWvx4kvW2QWoEBUKqsiADKYgZB to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.000558 + Expected counter: 1 + Gas limit: 2478 + Storage limit: 91 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.000558 + payload fees(the block proposer) ....... +ꜩ0.000558 + Transaction: + Amount: ꜩ0 + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: approve + Parameter: (Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 1000000000 + Storage size: 2124 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2377.584 + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap3 --entrypoint approve --arg '(Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2377.220 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'opG2xrHRo7XfsfQ6ury6ArfyEJ7SbyhGtpuMS5nTuqjV78pJbh8' +NOT waiting for the operation to be included. +Use command + octez-client wait for opG2xrHRo7XfsfQ6ury6ArfyEJ7SbyhGtpuMS5nTuqjV78pJbh8 to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + Fee to the baker: ꜩ0.000558 + Expected counter: 1 + Gas limit: 2478 + Storage limit: 91 bytes + Balance updates: + tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU ... -ꜩ0.000558 + payload fees(the block proposer) ....... +ꜩ0.000558 + Transaction: + Amount: ꜩ0 + From: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: approve + Parameter: (Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd6 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 1000000000 + Storage size: 2195 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2377.584 + Balance updates: + tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup --wait none transfer 9001 from bootstrap1 to KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 --burn-cap 10 --entrypoint addLiquidity --arg '(Pair "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" 0 1000000000 "2050-01-01T00:00:00Z")' +Node is bootstrapped. +Estimated gas: 9497.488 units (will add 100 for safety) +Estimated storage: 147 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'onsvTjspvs6n3R9fbuQ1ZDvzEibrTJyZaxvrn4hwAEz135CrT5k' +NOT waiting for the operation to be included. +Use command + octez-client wait for onsvTjspvs6n3R9fbuQ1ZDvzEibrTJyZaxvrn4hwAEz135CrT5k to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.001315 + Expected counter: 3 + Gas limit: 9598 + Storage limit: 167 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.001315 + payload fees(the block proposer) ....... +ꜩ0.001315 + Transaction: + Amount: ꜩ9001 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + Entrypoint: addLiquidity + Parameter: (Pair "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" 0 1000000000 "2050-01-01T00:00:00Z") + This transaction was successfully applied + Updated storage: + { 21599 ; + 9001416765 ; + 2159830 ; + 0x01e927f00ef734dfc85919635e9afc9166c83ef9fc00 ; + 0x0115eb0104481a6d7921160bc982c5e0a561cd8a3a00 } + Storage size: 4635 bytes + Paid storage size diff: 6 bytes + Consumed gas: 1450.590 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.0015 + storage fees ........................... +ꜩ0.0015 + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ9001 + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... +ꜩ9001 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: transfer + Parameter: (Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + (Pair 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 21598)) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 999978402 + Set map(0)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 99978402 + Set map(0)[0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600] to 21598 + Storage size: 2264 bytes + Paid storage size diff: 69 bytes + Consumed gas: 3690.965 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.01725 + storage fees ........................... +ꜩ0.01725 + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo + Entrypoint: mintOrBurn + Parameter: (Pair 2159730 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78) + This transaction was successfully applied + Updated storage: + { 2 ; 3 ; 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 ; 2159830 } + Updated big_maps: + Set map(2)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 2159730 + Storage size: 2050 bytes + Paid storage size diff: 72 bytes + Consumed gas: 2300.350 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.018 + storage fees ........................... +ꜩ0.018 + + +./octez-client --mode mockup call KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo from bootstrap1 --entrypoint approve --arg '(Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 1000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2376.999 units (will add 100 for safety) +Estimated storage: 68 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'ootV3zW3k66DvpHiUBoAVhb5dvGaFXD1vFcjNiHvLTJhpSTvk41' +NOT waiting for the operation to be included. +Use command + octez-client wait for ootV3zW3k66DvpHiUBoAVhb5dvGaFXD1vFcjNiHvLTJhpSTvk41 to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.000555 + Expected counter: 4 + Gas limit: 2477 + Storage limit: 88 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000555 + payload fees(the block proposer) ....... +ꜩ0.000555 + Transaction: + Amount: ꜩ0 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo + Entrypoint: approve + Parameter: (Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 1000) + This transaction was successfully applied + Updated storage: + { 2 ; 3 ; 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 ; 2159830 } + Updated big_maps: + Set map(3)[(Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c)] to 1000 + Storage size: 2118 bytes + Paid storage size diff: 68 bytes + Consumed gas: 2377.362 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.017 + storage fees ........................... +ꜩ0.017 + + +./octez-client --mode mockup call KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo from bootstrap2 --entrypoint transfer --arg '(Pair "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 1000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 3741.852 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is 'oo8sACXKDiJJ27gt8kko7jDvywwUS3oLr8ZVEPJ2Kz8HtkQMBya' +NOT waiting for the operation to be included. +Use command + octez-client wait for oo8sACXKDiJJ27gt8kko7jDvywwUS3oLr8ZVEPJ2Kz8HtkQMBya to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.000742 + Expected counter: 2 + Gas limit: 3842 + Storage limit: 0 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.000742 + payload fees(the block proposer) ....... +ꜩ0.000742 + Transaction: + Amount: ꜩ0 + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo + Entrypoint: transfer + Parameter: (Pair "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" + 1000) + This transaction was successfully applied + Updated storage: + { 2 ; 3 ; 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 ; 2159830 } + Updated big_maps: + Unset map(3)[(Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c)] + Set map(2)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 2158730 + Set map(2)[0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c] to 1000 + Storage size: 2118 bytes + Consumed gas: 3742.216 + + +./octez-client --mode mockup call KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 from bootstrap2 --entrypoint removeLiquidity --arg '(Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 1000 0 0 "2050-01-01T00:00:00Z")' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 9102.578 units (will add 100 for safety) +Estimated storage: 67 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'oocZ2DJUHkYB3mFFwk3enBtC39BKNEu6pvyLC7dwnsa6NiDUbJA' +NOT waiting for the operation to be included. +Use command + octez-client wait for oocZ2DJUHkYB3mFFwk3enBtC39BKNEu6pvyLC7dwnsa6NiDUbJA to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.001273 + Expected counter: 3 + Gas limit: 9203 + Storage limit: 87 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.001273 + payload fees(the block proposer) ....... +ꜩ0.001273 + Transaction: + Amount: ꜩ0 + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + Entrypoint: removeLiquidity + Parameter: (Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 1000 0 0 "2050-01-01T00:00:00Z") + This transaction was successfully applied + Updated storage: + { 21589 ; + 8997498998 ; + 2158830 ; + 0x01e927f00ef734dfc85919635e9afc9166c83ef9fc00 ; + 0x0115eb0104481a6d7921160bc982c5e0a561cd8a3a00 } + Storage size: 4635 bytes + Consumed gas: 1452.097 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo + Entrypoint: mintOrBurn + Parameter: (Pair -1000 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c) + This transaction was successfully applied + Updated storage: + { 2 ; 3 ; 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 ; 2158830 } + Updated big_maps: + Unset map(2)[0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c] + Storage size: 2050 bytes + Consumed gas: 2500.309 + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: transfer + Parameter: (Pair 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 + (Pair 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c 10)) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(0)[0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600] to 21588 + Set map(0)[0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c] to 10 + Storage size: 2331 bytes + Paid storage size diff: 67 bytes + Consumed gas: 2994.305 + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.01675 + storage fees ........................... +ꜩ0.01675 + Internal Transaction: + Amount: ꜩ4.167766 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + This transaction was successfully applied + Consumed gas: 100 + Balance updates: + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... -ꜩ4.167766 + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... +ꜩ4.167766 + + +./octez-client --mode mockup get contract storage for KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo +Pair 2 3 "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 2158830 + +./octez-client --mode mockup get contract storage for KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN +Pair 0 1 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" 100010000 diff --git a/tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test trades.out b/tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test trades.out new file mode 100644 index 000000000000..24323c4f03b0 --- /dev/null +++ b/tezt/tests/expected/contract_liquidity_baking.ml/Parisc- Test trades.out @@ -0,0 +1,446 @@ + +./octez-client --mode mockup rpc get /chains/main/blocks/head/context/liquidity_baking/cpmm_address +"KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" + +./octez-client --mode mockup get contract storage for KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 +Pair 1 + 100 + 100 + "KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN" + "KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo" + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap1 --entrypoint mintOrBurn --arg '(Pair 100000000 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2375.517 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'opNV92qwY7YfY6exkBrJqnJyotKXFbxHdXEk7xNQFNsPRQ7TEjF' +NOT waiting for the operation to be included. +Use command + octez-client wait for opNV92qwY7YfY6exkBrJqnJyotKXFbxHdXEk7xNQFNsPRQ7TEjF to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.00056 + Expected counter: 1 + Gas limit: 2476 + Storage limit: 91 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.00056 + payload fees(the block proposer) ....... +ꜩ0.00056 + Transaction: + Amount: ꜩ0 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: mintOrBurn + Parameter: (Pair 100000000 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(0)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 100000000 + Storage size: 1982 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2375.881 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap1 --entrypoint approve --arg '(Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2377.220 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'op968yui6vHCCztECXMB24FEWbMUHed9jQkXbhL5WGM8wXJw96Q' +NOT waiting for the operation to be included. +Use command + octez-client wait for op968yui6vHCCztECXMB24FEWbMUHed9jQkXbhL5WGM8wXJw96Q to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.000558 + Expected counter: 2 + Gas limit: 2478 + Storage limit: 91 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000558 + payload fees(the block proposer) ....... +ꜩ0.000558 + Transaction: + Amount: ꜩ0 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: approve + Parameter: (Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 1000000000 + Storage size: 2053 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2377.584 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap2 --entrypoint approve --arg '(Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2377.220 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'op8vSFsuf9xDtpELfAXrAD31oBWvx4kvW2QWoEBUKqsiADKYgZB' +NOT waiting for the operation to be included. +Use command + octez-client wait for op8vSFsuf9xDtpELfAXrAD31oBWvx4kvW2QWoEBUKqsiADKYgZB to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.000558 + Expected counter: 1 + Gas limit: 2478 + Storage limit: 91 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.000558 + payload fees(the block proposer) ....... +ꜩ0.000558 + Transaction: + Amount: ꜩ0 + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: approve + Parameter: (Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 1000000000 + Storage size: 2124 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2377.584 + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap3 --entrypoint approve --arg '(Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 2377.220 units (will add 100 for safety) +Estimated storage: 71 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'opG2xrHRo7XfsfQ6ury6ArfyEJ7SbyhGtpuMS5nTuqjV78pJbh8' +NOT waiting for the operation to be included. +Use command + octez-client wait for opG2xrHRo7XfsfQ6ury6ArfyEJ7SbyhGtpuMS5nTuqjV78pJbh8 to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + Fee to the baker: ꜩ0.000558 + Expected counter: 1 + Gas limit: 2478 + Storage limit: 91 bytes + Balance updates: + tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU ... -ꜩ0.000558 + payload fees(the block proposer) ....... +ꜩ0.000558 + Transaction: + Amount: ꜩ0 + From: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: approve + Parameter: (Pair "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 1000000000) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd6 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 1000000000 + Storage size: 2195 bytes + Paid storage size diff: 71 bytes + Consumed gas: 2377.584 + Balance updates: + tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU ... -ꜩ0.01775 + storage fees ........................... +ꜩ0.01775 + + +./octez-client --mode mockup --wait none transfer 9001 from bootstrap1 to KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 --burn-cap 10 --entrypoint addLiquidity --arg '(Pair "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" 0 1000000000 "2050-01-01T00:00:00Z")' +Node is bootstrapped. +Estimated gas: 9497.488 units (will add 100 for safety) +Estimated storage: 147 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'onsvTjspvs6n3R9fbuQ1ZDvzEibrTJyZaxvrn4hwAEz135CrT5k' +NOT waiting for the operation to be included. +Use command + octez-client wait for onsvTjspvs6n3R9fbuQ1ZDvzEibrTJyZaxvrn4hwAEz135CrT5k to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.001315 + Expected counter: 3 + Gas limit: 9598 + Storage limit: 167 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.001315 + payload fees(the block proposer) ....... +ꜩ0.001315 + Transaction: + Amount: ꜩ9001 + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + To: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + Entrypoint: addLiquidity + Parameter: (Pair "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" 0 1000000000 "2050-01-01T00:00:00Z") + This transaction was successfully applied + Updated storage: + { 21599 ; + 9001416765 ; + 2159830 ; + 0x01e927f00ef734dfc85919635e9afc9166c83ef9fc00 ; + 0x0115eb0104481a6d7921160bc982c5e0a561cd8a3a00 } + Storage size: 4635 bytes + Paid storage size diff: 6 bytes + Consumed gas: 1450.590 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.0015 + storage fees ........................... +ꜩ0.0015 + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ9001 + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... +ꜩ9001 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: transfer + Parameter: (Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + (Pair 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 21598)) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 999978402 + Set map(0)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 99978402 + Set map(0)[0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600] to 21598 + Storage size: 2264 bytes + Paid storage size diff: 69 bytes + Consumed gas: 3690.965 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.01725 + storage fees ........................... +ꜩ0.01725 + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo + Entrypoint: mintOrBurn + Parameter: (Pair 2159730 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78) + This transaction was successfully applied + Updated storage: + { 2 ; 3 ; 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 ; 2159830 } + Updated big_maps: + Set map(2)[0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78] to 2159730 + Storage size: 2050 bytes + Paid storage size diff: 72 bytes + Consumed gas: 2300.350 + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.018 + storage fees ........................... +ꜩ0.018 + + +./octez-client --mode mockup --wait none transfer 9001 from bootstrap2 to KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 --burn-cap 10 --entrypoint xtzToToken --arg '(Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 0 "2050-01-01T00:00:00Z")' +Node is bootstrapped. +Estimated gas: 6070.421 units (will add 100 for safety) +Estimated storage: 327 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'oogc3Wbh8bGJdTZYeAaKP7YmR9nmp51JCCYPeEc3hqBZ27jKzaK' +NOT waiting for the operation to be included. +Use command + octez-client wait for oogc3Wbh8bGJdTZYeAaKP7YmR9nmp51JCCYPeEc3hqBZ27jKzaK to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.000965 + Expected counter: 2 + Gas limit: 6171 + Storage limit: 347 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.000965 + payload fees(the block proposer) ....... +ꜩ0.000965 + Transaction: + Amount: ꜩ9001 + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + Entrypoint: xtzToToken + Parameter: (Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" 0 "2050-01-01T00:00:00Z") + This transaction was successfully applied + Updated storage: + { 10811 ; + 17993499098 ; + 2159830 ; + 0x01e927f00ef734dfc85919635e9afc9166c83ef9fc00 ; + 0x0115eb0104481a6d7921160bc982c5e0a561cd8a3a00 } + Storage size: 4636 bytes + Paid storage size diff: 1 bytes + Consumed gas: 920.247 + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.00025 + storage fees ........................... +ꜩ0.00025 + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ9001 + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... +ꜩ9001 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: transfer + Parameter: (Pair 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 + (Pair 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c 10788)) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(0)[0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600] to 10810 + Set map(0)[0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c] to 10788 + Storage size: 2333 bytes + Paid storage size diff: 69 bytes + Consumed gas: 2994.339 + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.01725 + storage fees ........................... +ꜩ0.01725 + Internal Transaction: + Amount: ꜩ9.001 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU + This transaction was successfully applied + Consumed gas: 100 + Balance updates: + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... -ꜩ9.001 + tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU ... +ꜩ9.001 + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + + +./octez-client --mode mockup call KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN from bootstrap2 --entrypoint transfer --arg '(Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU" 100)' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 3075.593 units (will add 100 for safety) +Estimated storage: 68 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is 'opCvYgUossHCJMw2bwAuZsKVWZPerUVdvQWEo2JpoM7SAWmX5LU' +NOT waiting for the operation to be included. +Use command + octez-client wait for opCvYgUossHCJMw2bwAuZsKVWZPerUVdvQWEo2JpoM7SAWmX5LU to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.000675 + Expected counter: 3 + Gas limit: 3176 + Storage limit: 88 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.000675 + payload fees(the block proposer) ....... +ꜩ0.000675 + Transaction: + Amount: ꜩ0 + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: transfer + Parameter: (Pair "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" + "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU" + 100) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(0)[0x0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd6] to 100 + Set map(0)[0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c] to 10688 + Storage size: 2401 bytes + Paid storage size diff: 68 bytes + Consumed gas: 3075.957 + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.017 + storage fees ........................... +ꜩ0.017 + + +./octez-client --mode mockup call KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 from bootstrap3 --entrypoint tokenToXtz --arg '(Pair "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU" 100 0 "2050-01-01T00:00:00Z")' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 7067.428 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is 'opSJtQyATVZNAw8iVpDX7V7RU82Q3Kczsjn262NH2jsSJSqzMt6' +NOT waiting for the operation to be included. +Use command + octez-client wait for opSJtQyATVZNAw8iVpDX7V7RU82Q3Kczsjn262NH2jsSJSqzMt6 to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisCCCCCeZiLHU +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + Fee to the baker: ꜩ0.001062 + Expected counter: 2 + Gas limit: 7168 + Storage limit: 0 bytes + Balance updates: + tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU ... -ꜩ0.001062 + payload fees(the block proposer) ....... +ꜩ0.001062 + Transaction: + Amount: ꜩ0 + From: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + To: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + Entrypoint: tokenToXtz + Parameter: (Pair "tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU" 100 0 "2050-01-01T00:00:00Z") + This transaction was successfully applied + Updated storage: + { 10911 ; + 17828916091 ; + 2159830 ; + 0x01e927f00ef734dfc85919635e9afc9166c83ef9fc00 ; + 0x0115eb0104481a6d7921160bc982c5e0a561cd8a3a00 } + Storage size: 4636 bytes + Consumed gas: 920.738 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN + Entrypoint: transfer + Parameter: (Pair 0x0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd6 + (Pair 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600 100)) + This transaction was successfully applied + Updated storage: + { 0 ; 1 ; 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 ; 100010000 } + Updated big_maps: + Set map(1)[(Pair 0x0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd6 + 0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600)] to 999999900 + Unset map(0)[0x0000dac9f52543da1aed0bc1d6b46bf7c10db7014cd6] + Set map(0)[0x01d496def47a3be89f5d54c6e6bb13cc6645d6e16600] to 10910 + Storage size: 2333 bytes + Consumed gas: 3890.781 + Internal Transaction: + Amount: ꜩ164.584923 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU + This transaction was successfully applied + Consumed gas: 100 + Balance updates: + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... -ꜩ164.584923 + tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU ... +ꜩ164.584923 + Internal Transaction: + Amount: ꜩ0.16475 + From: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 + To: tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU + This transaction was successfully applied + Consumed gas: 100 + Balance updates: + KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5 ... -ꜩ0.16475 + tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU ... +ꜩ0.16475 + + +./octez-client --mode mockup get contract storage for KT1AafHA1C1vk959wvHWBispY9Y2f3fxBUUo +Pair 2 3 "KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5" 2159830 + +./octez-client --mode mockup get contract storage for KT1VqarPDicMFn1ejmQqqshUkUXTCTXwmkCN +Pair 0 1 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" 100010000 diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpeq.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpeq.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpeq.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpeq.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpge.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpge.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpge.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpge.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpgt.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpgt.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpgt.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpgt.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmple.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmple.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmple.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmple.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmplt.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmplt.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmplt.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmplt.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpneq.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpneq.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_cmpneq.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_cmpneq.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_eq.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_eq.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_eq.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_eq.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_ge.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_ge.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_ge.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_ge.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_gt.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_gt.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_gt.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_gt.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_le.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_le.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_le.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_le.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_lt.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_lt.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_lt.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_lt.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_neq.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_neq.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-assert_neq.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-assert_neq.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-big_map_get_add.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-big_map_get_add.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-big_map_get_add.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-big_map_get_add.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-big_map_mem.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-big_map_mem.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-big_map_mem.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-big_map_mem.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-build_list.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-build_list.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-build_list.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-build_list.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-carn_and_cdrn.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-carn_and_cdrn.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-carn_and_cdrn.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-carn_and_cdrn.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-compare.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-compare.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-compare.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-compare.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-compare_bytes.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-compare_bytes.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-compare_bytes.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-compare_bytes.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-fail.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-fail.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-fail.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-fail.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-guestbook.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-guestbook.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-guestbook.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-guestbook.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-macro_annotations.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-macro_annotations.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-macro_annotations.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-macro_annotations.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-map_caddaadr.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-map_caddaadr.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-map_caddaadr.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-map_caddaadr.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-max_in_list.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-max_in_list.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-max_in_list.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-max_in_list.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-min.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-min.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-min.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-min.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-pair_macro.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-pair_macro.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-pair_macro.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-pair_macro.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-set_caddaadr.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-set_caddaadr.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-set_caddaadr.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-set_caddaadr.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-take_my_money.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-take_my_money.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-take_my_money.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-take_my_money.out diff --git a/tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-unpair_macro.out b/tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-unpair_macro.out similarity index 100% rename from tezt/tests/expected/contract_macros.ml/Paris- Macro expansion- macros-unpair_macro.out rename to tezt/tests/expected/contract_macros.ml/Parisb- Macro expansion- macros-unpair_macro.out diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert.out new file mode 100644 index 000000000000..5931ced0f288 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert.out @@ -0,0 +1,8 @@ +{ parameter bool ; + storage unit ; + code { CAR ; + { IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpeq.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpeq.out new file mode 100644 index 000000000000..bbe353a76a18 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpeq.out @@ -0,0 +1,11 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpge.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpge.out new file mode 100644 index 000000000000..d56c3a72c717 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpge.out @@ -0,0 +1,11 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; GE } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpgt.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpgt.out new file mode 100644 index 000000000000..ad6419cc57af --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpgt.out @@ -0,0 +1,11 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; GT } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmple.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmple.out new file mode 100644 index 000000000000..80d82ea4eb1e --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmple.out @@ -0,0 +1,11 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; LE } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmplt.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmplt.out new file mode 100644 index 000000000000..a0b5c69b4c90 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmplt.out @@ -0,0 +1,11 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; LT } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpneq.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpneq.out new file mode 100644 index 000000000000..9ae5ea93cbd0 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_cmpneq.out @@ -0,0 +1,11 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + { { COMPARE ; NEQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_eq.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_eq.out new file mode 100644 index 000000000000..ddbecad17d4a --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_eq.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { EQ ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_ge.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_ge.out new file mode 100644 index 000000000000..d4c1645d0517 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_ge.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { GE ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_gt.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_gt.out new file mode 100644 index 000000000000..6cf69f3845cf --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_gt.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { GT ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_le.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_le.out new file mode 100644 index 000000000000..81938328c570 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_le.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { LE ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_lt.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_lt.out new file mode 100644 index 000000000000..3faecebbb2be --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_lt.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { LT ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_neq.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_neq.out new file mode 100644 index 000000000000..97ad56e0faf1 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-assert_neq.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + { NEQ ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_get_add.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_get_add.out new file mode 100644 index 000000000000..fd1950c5e72d --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_get_add.out @@ -0,0 +1,22 @@ +{ parameter (pair (pair %set_pair int (option int)) (pair %check_pair int (option int))) ; + storage (pair (big_map int int) unit) ; + code { DUP ; + DIP { { CDR ; CAR } } ; + DUP ; + DIP { { CAR ; CDR } ; DUP ; CAR ; DIP { CDR } ; UPDATE ; DUP } ; + { CAR ; CDR } ; + DUP ; + CDR ; + DIP { CAR ; GET } ; + { IF_NONE + { { IF_NONE {} { { UNIT ; FAILWITH } } } } + { SWAP ; + { IF_NONE + { { UNIT ; FAILWITH } } + { { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } } } } } ; + UNIT ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_mem.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_mem.out new file mode 100644 index 000000000000..7f58503d9114 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-big_map_mem.out @@ -0,0 +1,13 @@ +{ parameter (pair int bool) ; + storage (pair (big_map int unit) unit) ; + code { DUP ; + DUP ; + { CAR ; CDR } ; + DIP { { CAR ; CAR } ; DIP { { CDR ; CAR } ; DUP } ; MEM } ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + UNIT ; + SWAP ; + PAIR ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-build_list.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-build_list.out new file mode 100644 index 000000000000..4ef9f940b1d0 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-build_list.out @@ -0,0 +1,23 @@ +{ parameter nat ; + storage (list nat) ; + code { CAR @counter ; + NIL @acc nat ; + SWAP ; + DUP @cmp_num ; + PUSH nat 0 ; + { COMPARE ; NEQ } ; + LOOP { DUP ; + DIP { SWAP } ; + CONS @acc ; + SWAP ; + PUSH nat 1 ; + SWAP ; + SUB @counter ; + DUP ; + DIP { ABS } ; + PUSH int 0 ; + { COMPARE ; NEQ } } ; + CONS ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-carn_and_cdrn.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-carn_and_cdrn.out new file mode 100644 index 000000000000..4cda8ad36989 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-carn_and_cdrn.out @@ -0,0 +1,28 @@ +{ parameter (pair nat nat nat unit) ; + storage unit ; + code { CAR ; + DUP ; + CAR ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 1 } ; + PUSH nat 1 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 3 } ; + PUSH nat 4 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 5 } ; + PUSH nat 2 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DUP ; + { GET 6 } ; + UNIT ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare.out new file mode 100644 index 000000000000..4292f6769b91 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare.out @@ -0,0 +1,21 @@ +{ parameter (pair mutez mutez) ; + storage (list bool) ; + code { CAR ; + DUP ; + DUP ; + DUP ; + DUP ; + DIP 5 { NIL bool } ; + DIP 4 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LE ; CONS } ; + DIP 3 { DUP ; CAR ; DIP { CDR } ; COMPARE ; GE ; CONS } ; + DIP 2 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LT ; CONS } ; + DIP { DUP ; CAR ; DIP { CDR } ; COMPARE ; GT ; CONS } ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + EQ ; + CONS ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare_bytes.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare_bytes.out new file mode 100644 index 000000000000..0b52eb3a3741 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-compare_bytes.out @@ -0,0 +1,21 @@ +{ parameter (pair bytes bytes) ; + storage (list bool) ; + code { CAR ; + DUP ; + DUP ; + DUP ; + DUP ; + DIP 5 { NIL bool } ; + DIP 4 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LE ; CONS } ; + DIP 3 { DUP ; CAR ; DIP { CDR } ; COMPARE ; GE ; CONS } ; + DIP 2 { DUP ; CAR ; DIP { CDR } ; COMPARE ; LT ; CONS } ; + DIP { DUP ; CAR ; DIP { CDR } ; COMPARE ; GT ; CONS } ; + DUP ; + CAR ; + DIP { CDR } ; + COMPARE ; + EQ ; + CONS ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-fail.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-fail.out new file mode 100644 index 000000000000..a3007c04a48a --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-fail.out @@ -0,0 +1,2 @@ +{ parameter unit ; storage unit ; code { { UNIT ; FAILWITH } } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-guestbook.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-guestbook.out new file mode 100644 index 000000000000..007315d9f5c1 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-guestbook.out @@ -0,0 +1,17 @@ +{ parameter string ; + storage (map address (option string)) ; + code { UNPAIR @message @guestbook ; + SWAP ; + DUP ; + SENDER ; + GET @previous_message ; + { IF_NONE { { UNIT ; FAILWITH } } {} } ; + { IF_NONE {} { { UNIT ; FAILWITH } } } ; + SWAP ; + SOME ; + SOME ; + SENDER ; + UPDATE ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-macro_annotations.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-macro_annotations.out new file mode 100644 index 000000000000..e0004b030af0 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-macro_annotations.out @@ -0,0 +1,12 @@ +{ parameter unit ; + storage (pair (unit %truc) unit) ; + code { DROP ; + UNIT ; + UNIT ; + PAIR %truc ; + UNIT ; + DUP @new_storage 2 ; + DIP { DROP ; DROP } ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-map_caddaadr.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-map_caddaadr.out new file mode 100644 index 000000000000..58b5cf2acdee --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-map_caddaadr.out @@ -0,0 +1,39 @@ +{ parameter unit ; + storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat) ; + code { { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + CDR @value ; + { PUSH mutez 1000000 ; ADD } ; + SWAP ; + CAR @%% ; + PAIR %@ %value } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ @new_storage } ; + NIL operation ; + SWAP ; + { CDR @%% ; SWAP ; PAIR % %@ } } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-max_in_list.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-max_in_list.out new file mode 100644 index 000000000000..73b02aecae21 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-max_in_list.out @@ -0,0 +1,16 @@ +{ parameter (list int) ; + storage (option int) ; + code { CAR ; + DIP { NONE int } ; + ITER { SWAP ; + IF_NONE + { SOME } + { DIP { DUP } ; + DUP ; + DIP { SWAP } ; + { COMPARE ; LE } ; + IF { DROP } { DIP { DROP } } ; + SOME } } ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-min.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-min.out new file mode 100644 index 000000000000..25b53381539f --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-min.out @@ -0,0 +1,12 @@ +{ parameter (pair int int) ; + storage int ; + code { CAR ; + DUP ; + DUP ; + CAR ; + DIP { CDR } ; + { COMPARE ; LT } ; + IF { CAR } { CDR } ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-pair_macro.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-pair_macro.out new file mode 100644 index 000000000000..c690e041b539 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-pair_macro.out @@ -0,0 +1,17 @@ +{ parameter unit ; + storage unit ; + code { UNIT ; + UNIT ; + UNIT ; + UNIT ; + UNIT ; + { DIP 3 { PAIR %x4 %x5 } ; + DIP 2 { PAIR %x3 } ; + DIP { PAIR %x2 } ; + PAIR %x1 @name } ; + { CDR ; CDR ; CDR ; CAR %x4 @fourth } ; + DROP ; + CDR ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-set_caddaadr.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-set_caddaadr.out new file mode 100644 index 000000000000..40e1f41cf5b3 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-set_caddaadr.out @@ -0,0 +1,32 @@ +{ parameter mutez ; + storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat) ; + code { DUP ; + CAR ; + SWAP ; + CDR ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CDR @%% ; + { DUP ; + DIP { CAR @%% ; + { DUP ; + DIP { CAR @%% ; { DUP ; CDR %value ; DROP ; CAR @%% ; PAIR %@ %value } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CAR @%% ; + PAIR %@ %@ } } ; + CDR @%% ; + SWAP ; + PAIR %@ %@ @toplevel_pair_name } ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-take_my_money.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-take_my_money.out new file mode 100644 index 000000000000..e337e046dd67 --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-take_my_money.out @@ -0,0 +1,13 @@ +{ parameter key_hash ; + storage unit ; + code { CAR ; + IMPLICIT_ACCOUNT ; + DIP { UNIT } ; + PUSH mutez 1000000 ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } + diff --git a/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-unpair_macro.out b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-unpair_macro.out new file mode 100644 index 000000000000..54c838c9052c --- /dev/null +++ b/tezt/tests/expected/contract_macros.ml/Parisc- Macro expansion- macros-unpair_macro.out @@ -0,0 +1,19 @@ +{ parameter (unit :param_unit) ; + storage (unit :u1) ; + code { DROP ; + UNIT :u4 @a4 ; + UNIT :u3 @a3 ; + UNIT :u2 @a2 ; + UNIT :u1 @a1 ; + PAIR ; + UNPAIR @x1 @x2 ; + { DIP 2 { PAIR %x3 %x4 } ; PAIR %x1 %x2 ; PAIR @p1 } ; + { UNPAIR ; UNPAIR ; DIP 2 { UNPAIR } } ; + { DIP 2 { PAIR %x3 %x4 } ; DIP { PAIR %x2 } ; PAIR %x1 @p2 } ; + { UNPAIR ; DIP { UNPAIR } ; DIP 2 { UNPAIR } } ; + { DIP { PAIR %x2 %x3 } ; DIP { PAIR % %x4 } ; PAIR %x1 @p3 } ; + { UNPAIR ; DIP { UNPAIR } ; DIP { UNPAIR } } ; + DIP { DROP ; DROP ; DROP } ; + NIL operation ; + PAIR } } + diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_big_map_origination.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_big_map_origination.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_big_map_origination.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_big_map_origination.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_contract_fails.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_contract_fails.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_contract_fails.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_contract_fails.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_level.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_level.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_level.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_level.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_now.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_now.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_now.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_now.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_self.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_self.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_self.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_self.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_sender.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_sender.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_sender.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_sender.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_set_delegate.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_set_delegate.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_set_delegate.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_set_delegate.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_slice.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_slice.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_slice.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_slice.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_source.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_source.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_source.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_source.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_split_bytes.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_split_bytes.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_split_bytes.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_split_bytes.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_split_string.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_split_string.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_split_string.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_split_string.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_store_input.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_store_input.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_store_input.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_store_input.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_trace_origination_compare_big_type.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_trace_origination_compare_big_type.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_trace_origination_compare_big_type.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_trace_origination_compare_big_type.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_trace_origination_compare_big_type2.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_trace_origination_compare_big_type2.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_trace_origination_compare_big_type2.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_trace_origination_compare_big_type2.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_transfer_amount.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_transfer_amount.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_transfer_amount.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_transfer_amount.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_transfer_tokens.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_transfer_tokens.out similarity index 100% rename from tezt/tests/expected/contract_onchain_opcodes.ml/Paris- Contract onchain opcodes- test_transfer_tokens.out rename to tezt/tests/expected/contract_onchain_opcodes.ml/Parisb- Contract onchain opcodes- test_transfer_tokens.out diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_big_map_origination.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_big_map_origination.out new file mode 100644 index 000000000000..83ccf3fe08bd --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_big_map_origination.out @@ -0,0 +1,148 @@ + +./octez-client --mode mockup --wait none originate contract originate_big_map transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/originate_big_map.tz --init '{Elt 0 0}' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 813.249 units (will add 100 for safety) +Estimated storage: 403 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000374 + Expected counter: 1 + Gas limit: 914 + Storage limit: 423 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000374 + payload fees(the block proposer) ....... +ꜩ0.000374 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: { Elt 0 0 } + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 146 bytes + Updated big_maps: + New map(4) of type (big_map int int) + Set map(4)[0] to 0 + Paid storage size diff: 146 bytes + Consumed gas: 813.216 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0365 + storage fees ........................... +ꜩ0.0365 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as originate_big_map. + +./octez-client --mode mockup --wait none originate contract originate_big_map transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/originate_big_map.tz --init 0 --burn-cap 10 --force +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: 0 + No delegate for this contract + This operation FAILED. + +Ill typed data: 1: 0 is not an expression of type big_map int int +At line 1 characters 0 to 1, value 0 is invalid for type big_map int int. +At line 1 characters 0 to 1, +Unexpected forged value. +Fatal error: + origination simulation failed + +./octez-client --mode mockup --wait none originate contract originate_big_map transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/originate_big_map.tz --init 'Pair 0 {Elt 1 (Some 4)}' --burn-cap 10 --force +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: (Pair 0 { Elt 1 (Some 4) }) + No delegate for this contract + This operation FAILED. + +Ill typed data: 1: (Pair 0 { Elt 1 (Some 4) }) +is not an expression of type big_map int int +At line 1 characters 0 to 26, value (Pair 0 { Elt 1 (Some 4) }) +is invalid for type big_map int int. +At line 1 characters 6 to 7, +Unexpected forged value. +Fatal error: + origination simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg 0 +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: 0 + This operation FAILED. + +Invalid argument passed to contract [CONTRACT_HASH]. +At (unshown) location 0, value 0 is invalid for type big_map int int. +At (unshown) location 0, Unexpected forged value. +Fatal error: + transfer simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg 'Pair 0 {Elt 1 (Some 4)}' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0 { Elt 1 (Some 4) }) + This operation FAILED. + +Invalid argument passed to contract [CONTRACT_HASH]. +At (unshown) location 0, value (Pair 0 { Elt 1 (Some 4) }) +is invalid for type big_map int int. +At (unshown) location 1, Unexpected forged value. +Fatal error: + transfer simulation failed diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_contract_fails.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_contract_fails.out new file mode 100644 index 000000000000..4d8accb66a88 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_contract_fails.out @@ -0,0 +1,70 @@ + +./octez-client --mode mockup --wait none originate contract contract transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/contract.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 589.063 units (will add 100 for safety) +Estimated storage: 329 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000368 + Expected counter: 1 + Gas limit: 690 + Storage limit: 349 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000368 + payload fees(the block proposer) ....... +ꜩ0.000368 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter address ; + storage unit ; + code { CAR ; CONTRACT unit ; ASSERT_SOME ; DROP ; UNIT ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 72 bytes + Paid storage size diff: 72 bytes + Consumed gas: 589.029 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.018 + storage fees ........................... +ꜩ0.018 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as contract. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 1: { parameter address ; + 2: storage unit ; + 3: code { CAR ; CONTRACT unit ; ASSERT_SOME ; DROP ; UNIT ; NIL operation ; PAIR } } +At line 3 characters 31 to 42, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_level.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_level.out new file mode 100644 index 000000000000..7e80a9ada435 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_level.out @@ -0,0 +1,113 @@ + +./octez-client --mode mockup --wait none originate contract level transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/level.tz --init 9999999 --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 579.482 units (will add 100 for safety) +Estimated storage: 300 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000338 + Expected counter: 1 + Gas limit: 680 + Storage limit: 320 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000338 + payload fees(the block proposer) ....... +ꜩ0.000338 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage nat ; + code { DROP ; LEVEL ; NIL operation ; PAIR } } + Initial storage: 9999999 + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 43 bytes + Paid storage size diff: 43 bytes + Consumed gas: 579.449 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01075 + storage fees ........................... +ꜩ0.01075 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as level. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1277.146 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000386 + Expected counter: 2 + Gas limit: 1378 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000386 + payload fees(the block proposer) ....... +ꜩ0.000386 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 1 + Storage size: 40 bytes + Consumed gas: 1277.818 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +1 + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +1 + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1277.758 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000386 + Expected counter: 3 + Gas limit: 1378 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000386 + payload fees(the block proposer) ....... +ꜩ0.000386 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 4 + Storage size: 40 bytes + Consumed gas: 1277.692 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +4 diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_now.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_now.out new file mode 100644 index 000000000000..44009ded0d20 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_now.out @@ -0,0 +1,77 @@ + +./octez-client --mode mockup --wait none originate contract store_now transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/store_now.tz --init '"[TIMESTAMP]"' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 580.706 units (will add 100 for safety) +Estimated storage: 301 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000359 + Expected counter: 1 + Gas limit: 681 + Storage limit: 321 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000359 + payload fees(the block proposer) ....... +ꜩ0.000359 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage timestamp ; + code { DROP ; NOW ; NIL operation ; PAIR } } + Initial storage: "[TIMESTAMP]" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 44 bytes + Paid storage size diff: 44 bytes + Consumed gas: 580.673 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.011 + storage fees ........................... +ꜩ0.011 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as store_now. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1277.238 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000386 + Expected counter: 2 + Gas limit: 1378 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000386 + payload fees(the block proposer) ....... +ꜩ0.000386 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 1 + Storage size: 40 bytes + Consumed gas: 1277.860 + + +./octez-client --mode mockup rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/storage' +{ "string": "[TIMESTAMP]" } diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_self.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_self.out new file mode 100644 index 000000000000..a45707bfefb9 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_self.out @@ -0,0 +1,77 @@ + +./octez-client --mode mockup --wait none originate contract self transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/self.tz --init '"[PUBLIC_KEY_HASH]"' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 586.589 units (will add 100 for safety) +Estimated storage: 324 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000377 + Expected counter: 1 + Gas limit: 687 + Storage limit: 344 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000377 + payload fees(the block proposer) ....... +ꜩ0.000377 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage address ; + code { DROP ; SELF ; ADDRESS ; NIL operation ; PAIR } } + Initial storage: "[PUBLIC_KEY_HASH]" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 67 bytes + Paid storage size diff: 67 bytes + Consumed gas: 586.556 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01675 + storage fees ........................... +ꜩ0.01675 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as self. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1279.520 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000386 + Expected counter: 2 + Gas limit: 1380 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000386 + payload fees(the block proposer) ....... +ꜩ0.000386 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x01fabd76c7ade40ef0e6a7b2be514d9e617e0a424800 + Storage size: 67 bytes + Consumed gas: 1280.099 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"[CONTRACT_HASH]" diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_sender.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_sender.out new file mode 100644 index 000000000000..caf29e0cef4d --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_sender.out @@ -0,0 +1,170 @@ + +./octez-client --mode mockup --wait none originate contract proxy transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/proxy.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 585.098 units (will add 100 for safety) +Estimated storage: 312 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000351 + Expected counter: 1 + Gas limit: 686 + Storage limit: 332 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000351 + payload fees(the block proposer) ....... +ꜩ0.000351 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (contract unit) ; + storage unit ; + code { UNPAIR ; + AMOUNT ; + UNIT ; + TRANSFER_TOKENS ; + DIP { NIL operation } ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 55 bytes + Paid storage size diff: 55 bytes + Consumed gas: 585.065 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01375 + storage fees ........................... +ꜩ0.01375 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as proxy. + +./octez-client --mode mockup --wait none originate contract sender transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/sender.tz --init '"[PUBLIC_KEY_HASH]"' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 585.452 units (will add 100 for safety) +Estimated storage: 322 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000375 + Expected counter: 2 + Gas limit: 686 + Storage limit: 342 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000375 + payload fees(the block proposer) ....... +ꜩ0.000375 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage address ; + code { DROP ; SENDER ; NIL operation ; PAIR } } + Initial storage: "[PUBLIC_KEY_HASH]" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 65 bytes + Paid storage size diff: 65 bytes + Consumed gas: 585.419 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01625 + storage fees ........................... +ꜩ0.01625 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as sender. + +./octez-client --mode mockup --wait none transfer 0 from '[PUBLIC_KEY_HASH]' to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1278.793 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000386 + Expected counter: 1 + Gas limit: 1379 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000386 + payload fees(the block proposer) ....... +ꜩ0.000386 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + Storage size: 65 bytes + Consumed gas: 1279.372 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"[PUBLIC_KEY_HASH]" + +./octez-client --mode mockup --wait none transfer 0 from '[PUBLIC_KEY_HASH]' to '[CONTRACT_HASH]' --burn-cap 10 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 2948.882 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000599 + Expected counter: 2 + Gas limit: 3049 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000599 + payload fees(the block proposer) ....... +ꜩ0.000599 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 55 bytes + Consumed gas: 1739.356 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x01c144b1848cb3943f64c69648f0b9e477d96c540600 + Storage size: 65 bytes + Consumed gas: 1210.707 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"[CONTRACT_HASH]" diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_set_delegate.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_set_delegate.out new file mode 100644 index 000000000000..c7e436fac34b --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_set_delegate.out @@ -0,0 +1,118 @@ + +./octez-client --mode mockup --wait none originate contract set_delegate transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/set_delegate.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 582.907 units (will add 100 for safety) +Estimated storage: 308 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000347 + Expected counter: 1 + Gas limit: 683 + Storage limit: 328 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000347 + payload fees(the block proposer) ....... +ꜩ0.000347 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (option key_hash) ; + storage unit ; + code { UNPAIR ; SET_DELEGATE ; DIP { NIL operation } ; CONS ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 51 bytes + Paid storage size diff: 51 bytes + Consumed gas: 582.874 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01275 + storage fees ........................... +ꜩ0.01275 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as set_delegate. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Some "[PUBLIC_KEY_HASH]")' +Node is bootstrapped. +Estimated gas: 1385.229 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000445 + Expected counter: 2 + Gas limit: 1486 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000445 + payload fees(the block proposer) ....... +ꜩ0.000445 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Some "[PUBLIC_KEY_HASH]") + This transaction was successfully applied + Updated storage: Unit + Storage size: 51 bytes + Consumed gas: 1285.808 + Internal operations: + Internal Delegation: + Contract: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + This delegation was successfully applied + Consumed gas: 100 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg None +Node is bootstrapped. +Estimated gas: 1379.351 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000403 + Expected counter: 3 + Gas limit: 1480 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000403 + payload fees(the block proposer) ....... +ꜩ0.000403 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: None + This transaction was successfully applied + Updated storage: Unit + Storage size: 51 bytes + Consumed gas: 1279.930 + Internal operations: + Internal Delegation: + Contract: [CONTRACT_HASH] + To: nobody + This delegation was successfully applied + Consumed gas: 100 + diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_slice.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_slice.out new file mode 100644 index 000000000000..f59e583b179c --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_slice.out @@ -0,0 +1,461 @@ + +./octez-client --mode mockup --wait none originate contract slices transferring 1 from bootstrap1 running michelson_test_scripts/opcodes/slices.tz --init '"sppk7dBPqMPjDjXgKbb5f7V3PuKUrA4Zuwc3c3H7XqQerqPUWbK7Hna"' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 832.884 units (will add 100 for safety) +Estimated storage: 835 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000922 + Expected counter: 1 + Gas limit: 933 + Storage limit: 855 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000922 + payload fees(the block proposer) ....... +ꜩ0.000922 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ1 + Script: + { parameter (pair bytes signature) ; + storage key ; + code { DUP ; + CAAR ; + DUP ; + SIZE ; + PUSH nat 128 ; + SWAP ; + SUB ; + ISNAT ; + ASSERT_SOME ; + PUSH nat 128 ; + SLICE @payload ; + ASSERT_SOME ; + DUP ; + DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + SHA256 ; + ASSERT_CMPEQ } ; + DUP ; + DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + BLAKE2B ; + ASSERT_CMPEQ } ; + DUP ; + DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + SHA512 ; + ASSERT_CMPEQ } ; + DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + SWAP ; + DIP { SWAP } ; + CHECK_SIGNATURE ; + ASSERT ; + CDR ; + DUP ; + HASH_KEY ; + IMPLICIT_ACCOUNT ; + BALANCE ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } + Initial storage: + "sppk7dBPqMPjDjXgKbb5f7V3PuKUrA4Zuwc3c3H7XqQerqPUWbK7Hna" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 578 bytes + Paid storage size diff: 578 bytes + Consumed gas: 832.851 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.1445 + storage fees ........................... +ꜩ0.1445 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + +New contract [CONTRACT_HASH] originated. +Contract memorized as slices. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "p2sigsceCzcDw2AeYDzUonj4JT341WC9Px4wdhHBxbZcG1FhfqFVuG7f2fGCzrEHSAZgrsrQWpxduDPk9qZRgrpzwJnSHC3gZJ")' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 + "p2sigsceCzcDw2AeYDzUonj4JT341WC9Px4wdhHBxbZcG1FhfqFVuG7f2fGCzrEHSAZgrsrQWpxduDPk9qZRgrpzwJnSHC3gZJ") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 31 characters 9 to 15, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xeaa9ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 + "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 18 characters 15 to 27, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2deaad01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2deaad01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 + "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 22 characters 15 to 27, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150733eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150733eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 + "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 26 characters 15 to 27, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Pair 0xe009ab79e8b84ef0 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 2 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xe009ab79e8b84ef0 + "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter (pair bytes signature) ; + 02: storage key ; + 03: code { DUP ; + 04: CAAR ; + 05: DUP ; + 06: SIZE ; + 07: PUSH nat 128 ; + 08: SWAP ; + 09: SUB ; + 10: ISNAT ; + 11: ASSERT_SOME ; + 12: PUSH nat 128 ; + 13: SLICE @payload ; + 14: ASSERT_SOME ; + 15: DUP ; + 16: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 0 ; SLICE ; ASSERT_SOME } ; + 17: SHA256 ; + 18: ASSERT_CMPEQ } ; + 19: DUP ; + 20: DIP { DIP { DUP ; CAAR ; PUSH nat 32 ; PUSH nat 32 ; SLICE ; ASSERT_SOME } ; + 21: BLAKE2B ; + 22: ASSERT_CMPEQ } ; + 23: DUP ; + 24: DIP { DIP { DUP ; CAAR ; PUSH nat 64 ; PUSH nat 64 ; SLICE ; ASSERT_SOME } ; + 25: SHA512 ; + 26: ASSERT_CMPEQ } ; + 27: DIP { DUP ; CDR ; DIP { DUP ; CADR } } ; + 28: SWAP ; + 29: DIP { SWAP } ; + 30: CHECK_SIGNATURE ; + 31: ASSERT ; + 32: CDR ; + 33: DUP ; + 34: HASH_KEY ; + 35: IMPLICIT_ACCOUNT ; + 36: BALANCE ; + 37: UNIT ; + 38: TRANSFER_TOKENS ; + 39: NIL operation ; + 40: SWAP ; + 41: CONS ; + 42: PAIR } } +At line 11 characters 9 to 20, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '(Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm")' +Node is bootstrapped. +Estimated gas: 1625.177 units (will add 100 for safety) +Estimated storage: 257 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00068 + Expected counter: 2 + Gas limit: 1726 + Storage limit: 277 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00068 + payload fees(the block proposer) ....... +ꜩ0.00068 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0xe009ab79e8b84ef0e55c43a9a857214d8761e67b75ba63500a5694fb2ffe174acc2de22d01ccb7259342437f05e1987949f0ad82e9f32e9a0b79cb252d7f7b8236ad728893f4e7150742eefdbeda254970f9fcd92c6228c178e1a923e5600758eb83f2a05edd0be7625657901f2ba81eaf145d003dbef78e33f43a32a3788bdf0501000000085341554349535345 + "spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm") + This transaction was successfully applied + Updated storage: + 0x0103fe5753baadb56a4836e34571ce4cbe82158ee40eba872b848f709699019725ba + Storage size: 578 bytes + Consumed gas: 1525.659 + Internal operations: + Internal Transaction: + Amount: ꜩ1 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + This transaction was successfully applied + Consumed gas: 100 + Balance updates: + [CONTRACT_HASH] ... -ꜩ1 + [PUBLIC_KEY_HASH] ... +ꜩ1 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_source.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_source.out new file mode 100644 index 000000000000..b7c989cd3449 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_source.out @@ -0,0 +1,170 @@ + +./octez-client --mode mockup --wait none originate contract proxy transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/proxy.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 585.098 units (will add 100 for safety) +Estimated storage: 312 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000351 + Expected counter: 1 + Gas limit: 686 + Storage limit: 332 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000351 + payload fees(the block proposer) ....... +ꜩ0.000351 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (contract unit) ; + storage unit ; + code { UNPAIR ; + AMOUNT ; + UNIT ; + TRANSFER_TOKENS ; + DIP { NIL operation } ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 55 bytes + Paid storage size diff: 55 bytes + Consumed gas: 585.065 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01375 + storage fees ........................... +ꜩ0.01375 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as proxy. + +./octez-client --mode mockup --wait none originate contract source transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/source.tz --init '"[PUBLIC_KEY_HASH]"' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 585.452 units (will add 100 for safety) +Estimated storage: 322 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000375 + Expected counter: 2 + Gas limit: 686 + Storage limit: 342 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000375 + payload fees(the block proposer) ....... +ꜩ0.000375 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage address ; + code { DROP ; SOURCE ; NIL operation ; PAIR } } + Initial storage: "[PUBLIC_KEY_HASH]" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 65 bytes + Paid storage size diff: 65 bytes + Consumed gas: 585.419 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01625 + storage fees ........................... +ꜩ0.01625 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as source. + +./octez-client --mode mockup --wait none transfer 0 from '[PUBLIC_KEY_HASH]' to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1278.793 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000386 + Expected counter: 1 + Gas limit: 1379 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000386 + payload fees(the block proposer) ....... +ꜩ0.000386 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + Storage size: 65 bytes + Consumed gas: 1279.372 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"[PUBLIC_KEY_HASH]" + +./octez-client --mode mockup --wait none transfer 0 from '[PUBLIC_KEY_HASH]' to '[CONTRACT_HASH]' --burn-cap 10 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 2948.882 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000599 + Expected counter: 2 + Gas limit: 3049 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000599 + payload fees(the block proposer) ....... +ꜩ0.000599 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 55 bytes + Consumed gas: 1739.356 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 0x0000e7670f32038107a59a2b9cfefae36ea21f5aa63c + Storage size: 65 bytes + Consumed gas: 1210.707 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"[PUBLIC_KEY_HASH]" diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_bytes.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_bytes.out new file mode 100644 index 000000000000..7ed8e75b7ac6 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_bytes.out @@ -0,0 +1,142 @@ + +./octez-client --mode mockup --wait none originate contract split_bytes transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/split_bytes.tz --init '{}' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 649.771 units (will add 100 for safety) +Estimated storage: 511 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000556 + Expected counter: 1 + Gas limit: 750 + Storage limit: 531 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000556 + payload fees(the block proposer) ....... +ꜩ0.000556 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter bytes ; + storage (list bytes) ; + code { UNPAIR ; + DIP { NIL bytes ; SWAP ; ITER { CONS } } ; + DUP ; + SIZE ; + PUSH nat 0 ; + CMPNEQ ; + DIP { PUSH @index nat 0 } ; + LOOP { PAIR ; + DUP ; + DIP { UNPAIR ; DIP { PUSH nat 1 } ; SLICE ; ASSERT_SOME ; CONS @storage } ; + UNPAIR ; + PUSH nat 1 ; + ADD @index ; + DUP ; + DIP { DIP { DUP } ; SWAP ; SIZE ; CMPNEQ } ; + SWAP } ; + DROP ; + DROP ; + NIL bytes ; + SWAP ; + ITER { CONS } ; + NIL operation ; + PAIR } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 254 bytes + Paid storage size diff: 254 bytes + Consumed gas: 649.738 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0635 + storage fees ........................... +ꜩ0.0635 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as split_bytes. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg 0xaabbcc +Node is bootstrapped. +Estimated gas: 1319.826 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000403 + Expected counter: 2 + Gas limit: 1420 + Storage limit: 38 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000403 + payload fees(the block proposer) ....... +ꜩ0.000403 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: 0xaabbcc + This transaction was successfully applied + Updated storage: { 0xaa ; 0xbb ; 0xcc } + Storage size: 272 bytes + Paid storage size diff: 18 bytes + Consumed gas: 1320.319 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0045 + storage fees ........................... +ꜩ0.0045 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +{ 0xaa ; 0xbb ; 0xcc } + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg 0xddeeff +Node is bootstrapped. +Estimated gas: 1322.442 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000404 + Expected counter: 3 + Gas limit: 1423 + Storage limit: 38 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000404 + payload fees(the block proposer) ....... +ꜩ0.000404 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: 0xddeeff + This transaction was successfully applied + Updated storage: { 0xaa ; 0xbb ; 0xcc ; 0xdd ; 0xee ; 0xff } + Storage size: 290 bytes + Paid storage size diff: 18 bytes + Consumed gas: 1322.935 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0045 + storage fees ........................... +ꜩ0.0045 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +{ 0xaa ; 0xbb ; 0xcc ; 0xdd ; 0xee ; 0xff } diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_string.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_string.out new file mode 100644 index 000000000000..13dea81cffaf --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_split_string.out @@ -0,0 +1,142 @@ + +./octez-client --mode mockup --wait none originate contract split_string transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/split_string.tz --init '{}' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 649.771 units (will add 100 for safety) +Estimated storage: 511 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000556 + Expected counter: 1 + Gas limit: 750 + Storage limit: 531 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000556 + payload fees(the block proposer) ....... +ꜩ0.000556 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter string ; + storage (list string) ; + code { UNPAIR ; + DIP { NIL string ; SWAP ; ITER { CONS } } ; + DUP ; + SIZE ; + PUSH nat 0 ; + CMPNEQ ; + DIP { PUSH @index nat 0 } ; + LOOP { PAIR ; + DUP ; + DIP { UNPAIR ; DIP { PUSH nat 1 } ; SLICE ; ASSERT_SOME ; CONS @storage } ; + UNPAIR ; + PUSH nat 1 ; + ADD @index ; + DUP ; + DIP { DIP { DUP } ; SWAP ; SIZE ; CMPNEQ } ; + SWAP } ; + DROP ; + DROP ; + NIL string ; + SWAP ; + ITER { CONS } ; + NIL operation ; + PAIR } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 254 bytes + Paid storage size diff: 254 bytes + Consumed gas: 649.738 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0635 + storage fees ........................... +ꜩ0.0635 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as split_string. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"abc"' +Node is bootstrapped. +Estimated gas: 1319.891 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000403 + Expected counter: 2 + Gas limit: 1420 + Storage limit: 38 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000403 + payload fees(the block proposer) ....... +ꜩ0.000403 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "abc" + This transaction was successfully applied + Updated storage: { "a" ; "b" ; "c" } + Storage size: 272 bytes + Paid storage size diff: 18 bytes + Consumed gas: 1320.384 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0045 + storage fees ........................... +ꜩ0.0045 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +{ "a" ; "b" ; "c" } + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"def"' +Node is bootstrapped. +Estimated gas: 1322.582 units (will add 100 for safety) +Estimated storage: 18 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000404 + Expected counter: 3 + Gas limit: 1423 + Storage limit: 38 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000404 + payload fees(the block proposer) ....... +ꜩ0.000404 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "def" + This transaction was successfully applied + Updated storage: { "a" ; "b" ; "c" ; "d" ; "e" ; "f" } + Storage size: 290 bytes + Paid storage size diff: 18 bytes + Consumed gas: 1323.075 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0045 + storage fees ........................... +ꜩ0.0045 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +{ "a" ; "b" ; "c" ; "d" ; "e" ; "f" } diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_store_input.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_store_input.out new file mode 100644 index 000000000000..4a2d23ec90c1 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_store_input.out @@ -0,0 +1,116 @@ + +./octez-client --mode mockup --wait none originate contract store_input transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/store_input.tz --init '""' --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 578.287 units (will add 100 for safety) +Estimated storage: 298 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000336 + Expected counter: 1 + Gas limit: 679 + Storage limit: 318 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000336 + payload fees(the block proposer) ....... +ꜩ0.000336 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: "" + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 41 bytes + Paid storage size diff: 41 bytes + Consumed gas: 578.254 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01025 + storage fees ........................... +ꜩ0.01025 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as store_input. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"abcdefg"' +Node is bootstrapped. +Estimated gas: 1277.540 units (will add 100 for safety) +Estimated storage: 7 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000403 + Expected counter: 2 + Gas limit: 1378 + Storage limit: 27 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000403 + payload fees(the block proposer) ....... +ꜩ0.000403 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "abcdefg" + This transaction was successfully applied + Updated storage: "abcdefg" + Storage size: 48 bytes + Paid storage size diff: 7 bytes + Consumed gas: 1278.162 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00175 + storage fees ........................... +ꜩ0.00175 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"abcdefg" + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"xyz"' +Node is bootstrapped. +Estimated gas: 1277.556 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000399 + Expected counter: 3 + Gas limit: 1378 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000399 + payload fees(the block proposer) ....... +ꜩ0.000399 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "xyz" + This transaction was successfully applied + Updated storage: "xyz" + Storage size: 44 bytes + Consumed gas: 1278.178 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +"xyz" diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type.out new file mode 100644 index 000000000000..efac8b5b355c --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type.out @@ -0,0 +1,89 @@ + +./octez-client --mode mockup --wait none originate contract compare_big_type transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/compare_big_type.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 1495.073 units (will add 100 for safety) +Estimated storage: 385 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000515 + Expected counter: 1 + Gas limit: 1596 + Storage limit: 405 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000515 + payload fees(the block proposer) ....... +ꜩ0.000515 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage unit ; + code { DROP ; + PUSH nat 0 ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 128 bytes + Paid storage size diff: 128 bytes + Consumed gas: 1495.039 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.032 + storage fees ........................... +ꜩ0.032 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as compare_big_type. diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type2.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type2.out new file mode 100644 index 000000000000..515d82971a64 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_trace_origination_compare_big_type2.out @@ -0,0 +1,93 @@ + +./octez-client --mode mockup --wait none originate contract compare_big_type2 transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/compare_big_type2.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 1635.852 units (will add 100 for safety) +Estimated storage: 393 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000537 + Expected counter: 1 + Gas limit: 1736 + Storage limit: 413 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000537 + payload fees(the block proposer) ....... +ꜩ0.000537 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage unit ; + code { DROP ; + PUSH nat 0 ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + PAIR ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DUP ; + DUP ; + COMPARE ; + DROP ; + DROP ; + UNIT ; + NIL operation ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 136 bytes + Paid storage size diff: 136 bytes + Consumed gas: 1635.818 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.034 + storage fees ........................... +ꜩ0.034 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as compare_big_type2. diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_amount.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_amount.out new file mode 100644 index 000000000000..d9fe0987239b --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_amount.out @@ -0,0 +1,83 @@ + +./octez-client --mode mockup --wait none originate contract transfer_amount transferring 0 from bootstrap1 running michelson_test_scripts/opcodes/transfer_amount.tz --init 0 --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 579.161 units (will add 100 for safety) +Estimated storage: 297 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000335 + Expected counter: 1 + Gas limit: 680 + Storage limit: 317 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000335 + payload fees(the block proposer) ....... +ꜩ0.000335 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage mutez ; + code { DROP ; AMOUNT ; NIL operation ; PAIR } } + Initial storage: 0 + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 40 bytes + Paid storage size diff: 40 bytes + Consumed gas: 579.127 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01 + storage fees ........................... +ꜩ0.01 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as transfer_amount. + +./octez-client --mode mockup --wait none transfer 500 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg Unit +Node is bootstrapped. +Estimated gas: 1277.412 units (will add 100 for safety) +Estimated storage: 4 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00039 + Expected counter: 2 + Gas limit: 1378 + Storage limit: 24 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00039 + payload fees(the block proposer) ....... +ꜩ0.00039 + Transaction: + Amount: ꜩ500 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: 500000000 + Storage size: 44 bytes + Paid storage size diff: 4 bytes + Consumed gas: 1277.991 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.001 + storage fees ........................... +ꜩ0.001 + [PUBLIC_KEY_HASH] ... -ꜩ500 + [CONTRACT_HASH] ... +ꜩ500 + + +./octez-client --mode mockup get contract storage for '[CONTRACT_HASH]' +500000000 diff --git a/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_tokens.out b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_tokens.out new file mode 100644 index 000000000000..336a37392f68 --- /dev/null +++ b/tezt/tests/expected/contract_onchain_opcodes.ml/Parisc- Contract onchain opcodes- test_transfer_tokens.out @@ -0,0 +1,228 @@ + +./octez-client --mode mockup --wait none originate contract test_transfer_contract1 transferring 100 from bootstrap1 running michelson_test_scripts/opcodes/noop.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 578.200 units (will add 100 for safety) +Estimated storage: 295 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000336 + Expected counter: 1 + Gas limit: 679 + Storage limit: 315 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000336 + payload fees(the block proposer) ....... +ꜩ0.000336 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ100 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 38 bytes + Paid storage size diff: 38 bytes + Consumed gas: 578.167 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0095 + storage fees ........................... +ꜩ0.0095 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + +New contract [CONTRACT_HASH] originated. +Contract memorized as test_transfer_contract1. + +./octez-client --mode mockup --wait none originate contract test_transfer_contract2 transferring 20 from bootstrap1 running michelson_test_scripts/opcodes/noop.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 578.200 units (will add 100 for safety) +Estimated storage: 295 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000336 + Expected counter: 2 + Gas limit: 679 + Storage limit: 315 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000336 + payload fees(the block proposer) ....... +ꜩ0.000336 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ20 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 38 bytes + Paid storage size diff: 38 bytes + Consumed gas: 578.167 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0095 + storage fees ........................... +ꜩ0.0095 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ20 + [CONTRACT_HASH] ... +ꜩ20 + +New contract [CONTRACT_HASH] originated. +Contract memorized as test_transfer_contract2. + +./octez-client --mode mockup --wait none originate contract transfer_tokens transferring 1000 from bootstrap1 running michelson_test_scripts/opcodes/transfer_tokens.tz --burn-cap 10 --force +Node is bootstrapped. +Estimated gas: 589.146 units (will add 100 for safety) +Estimated storage: 323 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000366 + Expected counter: 3 + Gas limit: 690 + Storage limit: 343 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000366 + payload fees(the block proposer) ....... +ꜩ0.000366 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ1000 + Script: + { parameter (contract unit) ; + storage unit ; + code { CAR ; + DIP { UNIT } ; + PUSH mutez 100000000 ; + UNIT ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 66 bytes + Paid storage size diff: 66 bytes + Consumed gas: 589.113 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ1000 + [CONTRACT_HASH] ... +ꜩ1000 + +New contract [CONTRACT_HASH] originated. +Contract memorized as transfer_tokens. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 2948.415 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000599 + Expected counter: 4 + Gas limit: 3049 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000599 + payload fees(the block proposer) ....... +ꜩ0.000599 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 66 bytes + Consumed gas: 1741.268 + Internal operations: + Internal Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: Unit + Storage size: 38 bytes + Consumed gas: 1208.328 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 10 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 2948.415 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000599 + Expected counter: 5 + Gas limit: 3049 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000599 + payload fees(the block proposer) ....... +ꜩ0.000599 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 66 bytes + Consumed gas: 1741.268 + Internal operations: + Internal Transaction: + Amount: ꜩ100 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: Unit + Storage size: 38 bytes + Consumed gas: 1208.328 + Balance updates: + [CONTRACT_HASH] ... -ꜩ100 + [CONTRACT_HASH] ... +ꜩ100 + diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -abs--storage125992234--input254251340-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -abs--storage125992234--input254251340-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -abs--storage125992234--input254251340-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -abs--storage125992234--input254251340-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -abs--storage125992234--input420401245-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -abs--storage125992234--input420401245-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -abs--storage125992234--input420401245-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -abs--storage125992234--input420401245-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -abs--storage125992234--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -abs--storage125992234--input680650890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -abs--storage125992234--input680650890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -abs--storage125992234--input680650890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_delta_timestamp--storage921624073--input249636002-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_delta_timestamp--storage921624073--input249636002-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_delta_timestamp--storage921624073--input249636002-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_delta_timestamp--storage921624073--input249636002-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_delta_timestamp--storage921624073--input267363182-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_delta_timestamp--storage921624073--input267363182-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_delta_timestamp--storage921624073--input267363182-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_delta_timestamp--storage921624073--input267363182-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_delta_timestamp--storage921624073--input438561129-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_delta_timestamp--storage921624073--input438561129-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_delta_timestamp--storage921624073--input438561129-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_delta_timestamp--storage921624073--input438561129-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_timestamp_delta--storage921624073--input249636002-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_timestamp_delta--storage921624073--input249636002-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_timestamp_delta--storage921624073--input249636002-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_timestamp_delta--storage921624073--input249636002-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_timestamp_delta--storage921624073--input307538219-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_timestamp_delta--storage921624073--input307538219-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_timestamp_delta--storage921624073--input307538219-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_timestamp_delta--storage921624073--input307538219-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_timestamp_delta--storage921624073--input373737581-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_timestamp_delta--storage921624073--input373737581-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -add_timestamp_delta--storage921624073--input373737581-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -add_timestamp_delta--storage921624073--input373737581-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -address--storage921624073--input117475800-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -address--storage921624073--input117475800-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -address--storage921624073--input117475800-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -address--storage921624073--input117475800-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input106930123-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input106930123-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input106930123-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input181204719-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input181204719-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input181204719-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input223774825-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input223774825-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input223774825-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input908807505-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and--storage921624073--input908807505-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and--storage921624073--input908807505-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_binary--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_binary--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_binary--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_binary--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_bytes--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_bytes--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_bytes--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input106930123-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input106930123-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input106930123-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input181204719-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input181204719-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input181204719-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input223774825-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input223774825-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input223774825-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input908807505-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -and_logical_1--storage570553153--input908807505-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -and_logical_1--storage570553153--input908807505-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -balance--storage492856247--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -balance--storage492856247--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -balance--storage492856247--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -balance--storage492856247--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage495706788--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage495706788--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage495706788--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage495706788--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage56274299--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage56274299--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage56274299--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage56274299--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage56274299--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage56274299--input564400327-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage56274299--input564400327-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage56274299--input564400327-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage56274299--input654274102-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage56274299--input654274102-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage56274299--input654274102-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage56274299--input654274102-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage690637660--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage690637660--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage690637660--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage690637660--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage806237530--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage806237530--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_nat--storage806237530--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_nat--storage806237530--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage109689253--input1071610051-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage109689253--input1071610051-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage109689253--input1071610051-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage109689253--input1071610051-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage109689253--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage109689253--input700475845-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage109689253--input700475845-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage109689253--input700475845-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage109689253--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage109689253--input905318451-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage109689253--input905318451-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage109689253--input905318451-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage495706788--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage495706788--input700475845-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage495706788--input700475845-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage495706788--input700475845-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage915708427--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage915708427--input700475845-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage915708427--input700475845-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage915708427--input700475845-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage936682951--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage936682951--input905318451-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -big_map_mem_string--storage936682951--input905318451-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -big_map_mem_string--storage936682951--input905318451-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input12599.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input12599.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bytes_of_int--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bytes_of_int--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bytes_of_int--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bytes_of_int--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bytes_of_nat--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bytes_of_nat--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -bytes_of_nat--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -bytes_of_nat--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -car--storage680650890--input783124233-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -car--storage680650890--input783124233-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -car--storage680650890--input783124233-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -car--storage680650890--input783124233-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cdr--storage680650890--input783124233-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cdr--storage680650890--input783124233-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cdr--storage680650890--input783124233-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cdr--storage680650890--input783124233-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -chain_id_store--storage109160754--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -chain_id_store--storage109160754--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -chain_id_store--storage109160754--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -chain_id_store--storage109160754--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -chain_id_store--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -chain_id_store--storage921624073--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -chain_id_store--storage921624073--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -chain_id_store--storage921624073--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -chain_id_store--storage981066851--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -chain_id_store--storage981066851--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -chain_id_store--storage981066851--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -chain_id_store--storage981066851--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb--storage950292965--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb--storage950292965--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb--storage950292965--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb--storage950292965--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb-get--storage125992234--input186507116-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb-get--storage125992234--input186507116-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb-get--storage125992234--input186507116-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb-get--storage125992234--input186507116-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb-set--storage186507116--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb-set--storage186507116--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb-set--storage186507116--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb-set--storage186507116--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb-set-2--storage921624073--input186507116-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb-set-2--storage921624073--input186507116-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comb-set-2--storage921624073--input186507116-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comb-set-2--storage921624073--input186507116-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -compare--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -compare--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -compare--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -compare--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comparisons--storage457300675--input281780712-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comparisons--storage457300675--input281780712-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -comparisons--storage457300675--input281780712-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -comparisons--storage457300675--input281780712-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello--storage457300675--input392583650-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello--storage457300675--input392583650-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello--storage457300675--input392583650-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello--storage457300675--input392583650-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello--storage457300675--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello--storage457300675--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello--storage457300675--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello--storage457300675--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello--storage457300675--input640104625-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello--storage457300675--input640104625-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello--storage457300675--input640104625-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello--storage457300675--input640104625-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello_bytes--storage457300675--input354091714-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello_bytes--storage457300675--input354091714-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello_bytes--storage457300675--input354091714-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello_bytes--storage457300675--input354091714-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello_bytes--storage457300675--input441061063-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello_bytes--storage457300675--input441061063-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello_bytes--storage457300675--input441061063-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello_bytes--storage457300675--input441061063-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello_bytes--storage457300675--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello_bytes--storage457300675--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_hello_bytes--storage457300675--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_hello_bytes--storage457300675--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_list--storage79230375--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_list--storage79230375--input264787654-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_list--storage79230375--input264787654-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_list--storage79230375--input264787654-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_list--storage79230375--input316676251-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_list--storage79230375--input316676251-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_list--storage79230375--input316676251-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_list--storage79230375--input316676251-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_list--storage79230375--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_list--storage79230375--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -concat_list--storage79230375--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -concat_list--storage79230375--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cons--storage457300675--input798141440-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cons--storage457300675--input798141440-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cons--storage457300675--input798141440-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cons--storage457300675--input798141440-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cons--storage581876226--input166122047-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cons--storage581876226--input166122047-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cons--storage581876226--input166122047-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cons--storage581876226--input166122047-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cons--storage793461282--input781487591-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cons--storage793461282--input781487591-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -cons--storage793461282--input781487591-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -cons--storage793461282--input781487591-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input315650912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input315650912-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input315650912-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input315650912-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input51111414-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input51111414-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input51111414-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input51111414-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input545734274-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input545734274-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input545734274-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input545734274-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input772794967-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input772794967-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input772794967-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input772794967-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input917967660-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input917967660-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input917967660-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input917967660-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input964818218-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input964818218-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contains_all--storage921624073--input964818218-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contains_all--storage921624073--input964818218-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contract--storage125992234--input117475800-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contract--storage125992234--input117475800-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -contract--storage125992234--input117475800-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -contract--storage125992234--input117475800-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -create_contract--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -create_contract--storage921624073--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -create_contract--storage921624073--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -create_contract--storage921624073--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input1011138251-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input1011138251-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input1011138251-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input1011138251-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input1018564342-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input1018564342-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input1018564342-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input1018564342-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input1031049988-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input1031049988-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input1031049988-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input1031049988-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input685590443-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input685590443-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -diff_timestamps--storage492856247--input685590443-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -diff_timestamps--storage492856247--input685590443-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dig_eq--storage125992234--input246866101-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dig_eq--storage125992234--input246866101-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dig_eq--storage125992234--input246866101-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dig_eq--storage125992234--input246866101-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dig_eq--storage125992234--input26856104-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dig_eq--storage125992234--input26856104-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dig_eq--storage125992234--input26856104-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dig_eq--storage125992234--input26856104-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dign--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dign--storage680650890--input529388602-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dign--storage680650890--input529388602-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dign--storage680650890--input529388602-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dip--storage1011138251--input590117173-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dip--storage1011138251--input590117173-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dip--storage1011138251--input590117173-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dip--storage1011138251--input590117173-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dip--storage1011138251--input850887554-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dip--storage1011138251--input850887554-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dip--storage1011138251--input850887554-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dip--storage1011138251--input850887554-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dipn--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dipn--storage680650890--input529388602-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dipn--storage680650890--input529388602-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dipn--storage680650890--input529388602-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dropn--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dropn--storage680650890--input529388602-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dropn--storage680650890--input529388602-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dropn--storage680650890--input529388602-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dugn--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dugn--storage680650890--input529388602-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dugn--storage680650890--input529388602-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dugn--storage680650890--input529388602-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dup-n--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dup-n--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -dup-n--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -dup-n--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv--storage994417987--input247451205-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv--storage994417987--input247451205-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv--storage994417987--input247451205-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv--storage994417987--input247451205-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv--storage994417987--input250545589-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv--storage994417987--input250545589-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv--storage994417987--input250545589-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv--storage994417987--input250545589-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv--storage994417987--input79625541-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv--storage994417987--input79625541-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv--storage994417987--input79625541-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv--storage994417987--input79625541-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input147133089-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input147133089-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input147133089-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input147133089-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input215785357-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input215785357-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input215785357-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input215785357-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input389351431-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input389351431-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input389351431-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input389351431-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input44513000-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input44513000-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input44513000-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input44513000-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input635398196-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input635398196-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input635398196-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input635398196-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input734264738-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input734264738-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input734264738-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input734264738-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input993071382-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input993071382-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ediv_mutez--storage977883604--input993071382-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ediv_mutez--storage977883604--input993071382-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -emit--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -emit--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -emit--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -emit--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -empty_map--storage457300675--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -empty_map--storage457300675--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -empty_map--storage457300675--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -empty_map--storage457300675--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -exec_concat--storage398998998--input246262487-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -exec_concat--storage398998998--input246262487-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -exec_concat--storage398998998--input246262487-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -exec_concat--storage398998998--input246262487-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -exec_concat--storage398998998--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -exec_concat--storage398998998--input79230375-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -exec_concat--storage398998998--input79230375-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -exec_concat--storage398998998--input79230375-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -first--storage492856247--input478406404-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -first--storage492856247--input478406404-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -first--storage492856247--input478406404-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -first--storage492856247--input478406404-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -first--storage492856247--input962874972-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -first--storage492856247--input962874972-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -first--storage492856247--input962874972-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -first--storage492856247--input962874972-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage1026405794--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage1026405794--input329240220-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage1026405794--input329240220-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage1026405794--input329240220-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage382368661--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage382368661--input329240220-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage382368661--input329240220-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage382368661--input329240220-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage496578814--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage496578814--input329240220-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage496578814--input329240220-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage496578814--input329240220-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage496578814--input507231566-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage496578814--input507231566-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage496578814--input507231566-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage496578814--input507231566-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage547821324--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage547821324--input329240220-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage547821324--input329240220-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage547821324--input329240220-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage796012494--input156280093-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage796012494--input156280093-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage796012494--input156280093-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage796012494--input156280093-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage796012494--input228164856-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage796012494--input228164856-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_and_update_map--storage796012494--input228164856-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_and_update_map--storage796012494--input228164856-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_map_value--storage139236239--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_map_value--storage139236239--input329240220-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_map_value--storage139236239--input329240220-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_map_value--storage139236239--input329240220-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_map_value--storage139236239--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_map_value--storage139236239--input79230375-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_map_value--storage139236239--input79230375-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_map_value--storage139236239--input79230375-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_map_value--storage329396864--input156280093-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_map_value--storage329396864--input156280093-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -get_map_value--storage329396864--input156280093-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -get_map_value--storage329396864--input156280093-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_key--storage921624073--input1040351577-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_key--storage921624073--input1040351577-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_key--storage921624073--input1040351577-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_key--storage921624073--input1040351577-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_key--storage921624073--input153350004-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_key--storage921624073--input153350004-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_key--storage921624073--input153350004-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_key--storage921624073--input153350004-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_string--storage151303925--input3431716-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_string--storage151303925--input3431716-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_string--storage151303925--input3431716-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_string--storage151303925--input3431716-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_string--storage151303925--input535018041-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_string--storage151303925--input535018041-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -hash_string--storage151303925--input535018041-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -hash_string--storage151303925--input535018041-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if--storage921624073--input570553153-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if--storage921624073--input570553153-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if--storage921624073--input570553153-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if--storage921624073--input570553153-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if--storage921624073--input954397288-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if--storage921624073--input954397288-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if--storage921624073--input954397288-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if--storage921624073--input954397288-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if_some--storage398998998--input288201633-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if_some--storage398998998--input288201633-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if_some--storage398998998--input288201633-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if_some--storage398998998--input288201633-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if_some--storage398998998--input921624073-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if_some--storage398998998--input921624073-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -if_some--storage398998998--input921624073-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -if_some--storage398998998--input921624073-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -int--storage921624073--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -int--storage921624073--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -int--storage921624073--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -int--storage921624073--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -int--storage921624073--input535454136-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -int--storage921624073--input535454136-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -int--storage921624073--input535454136-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -int--storage921624073--input535454136-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -int--storage921624073--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -int--storage921624073--input680650890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -int--storage921624073--input680650890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -int--storage921624073--input680650890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -keccak--storage921624073--input1008262038-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -keccak--storage921624073--input1008262038-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -keccak--storage921624073--input1008262038-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -keccak--storage921624073--input1008262038-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -left_right--storage4177631--input202098045-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -left_right--storage4177631--input202098045-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -left_right--storage4177631--input202098045-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -left_right--storage4177631--input202098045-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -left_right--storage4177631--input44576556-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -left_right--storage4177631--input44576556-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -left_right--storage4177631--input44576556-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -left_right--storage4177631--input44576556-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -level--storage492856247--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -level--storage492856247--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -level--storage492856247--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -level--storage492856247--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat--storage717096222--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat--storage717096222--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat--storage717096222--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat--storage717096222--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat--storage717096222--input546523343-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat--storage717096222--input546523343-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat--storage717096222--input546523343-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat--storage717096222--input546523343-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage149262694--input220724351-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage149262694--input220724351-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage149262694--input220724351-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage149262694--input220724351-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage149262694--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage149262694--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage149262694--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage149262694--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage65410082--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage65410082--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage65410082--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage65410082--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage726220441--input972761363-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage726220441--input972761363-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_concat_bytes--storage726220441--input972761363-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_concat_bytes--storage726220441--input972761363-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id--storage528921618--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id--storage528921618--input264787654-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id--storage528921618--input264787654-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id--storage528921618--input264787654-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id--storage528921618--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id--storage528921618--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id--storage528921618--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id--storage528921618--input656499821-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id--storage528921618--input656499821-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id--storage528921618--input656499821-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id--storage528921618--input656499821-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id_map--storage528921618--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id_map--storage528921618--input264787654-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id_map--storage528921618--input264787654-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id_map--storage528921618--input264787654-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id_map--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id_map--storage528921618--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id_map--storage528921618--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id_map--storage528921618--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id_map--storage528921618--input656499821-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id_map--storage528921618--input656499821-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_id_map--storage528921618--input656499821-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_id_map--storage528921618--input656499821-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_iter--storage680650890--input568817463-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_iter--storage680650890--input568817463-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_iter--storage680650890--input568817463-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_iter--storage680650890--input568817463-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_iter--storage680650890--input737923774-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_iter--storage680650890--input737923774-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_iter--storage680650890--input737923774-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_iter--storage680650890--input737923774-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_map_block--storage907453363--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_map_block--storage907453363--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_map_block--storage907453363--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_map_block--storage907453363--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_map_block--storage907453363--input648737279-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_map_block--storage907453363--input648737279-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_map_block--storage907453363--input648737279-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_map_block--storage907453363--input648737279-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_map_block--storage907453363--input908379154-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_map_block--storage907453363--input908379154-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_map_block--storage907453363--input908379154-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_map_block--storage907453363--input908379154-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input403499055-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input403499055-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input403499055-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input403499055-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input469078912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input469078912-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input469078912-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input469078912-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input802622031-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input802622031-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -list_size--storage492856247--input802622031-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -list_size--storage492856247--input802622031-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -loop_left--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -loop_left--storage528921618--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -loop_left--storage528921618--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -loop_left--storage528921618--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -loop_left--storage528921618--input851203613-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -loop_left--storage528921618--input851203613-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -loop_left--storage528921618--input851203613-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -loop_left--storage528921618--input851203613-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -lsl_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -lsl_bytes--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -lsl_bytes--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -lsl_bytes--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -lsr_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -lsr_bytes--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -lsr_bytes--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -lsr_bytes--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_id--storage457300675--input1027566226-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_id--storage457300675--input1027566226-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_id--storage457300675--input1027566226-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_id--storage457300675--input1027566226-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_id--storage457300675--input276660554-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_id--storage457300675--input276660554-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_id--storage457300675--input276660554-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_id--storage457300675--input276660554-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_id--storage457300675--input599923743-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_id--storage457300675--input599923743-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_id--storage457300675--input599923743-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_id--storage457300675--input599923743-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_iter--storage1011138251--input403579222-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_iter--storage1011138251--input403579222-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_iter--storage1011138251--input403579222-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_iter--storage1011138251--input403579222-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_iter--storage1011138251--input532072758-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_iter--storage1011138251--input532072758-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_iter--storage1011138251--input532072758-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_iter--storage1011138251--input532072758-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_map--storage457300675--input798141440-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_map--storage457300675--input798141440-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_map--storage457300675--input798141440-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_map--storage457300675--input798141440-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_map--storage794999348--input152441147-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_map--storage794999348--input152441147-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_map--storage794999348--input152441147-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_map--storage794999348--input152441147-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_map--storage88008216--input798141440-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_map--storage88008216--input798141440-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_map--storage88008216--input798141440-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_map--storage88008216--input798141440-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage495706788--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage495706788--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage495706788--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage495706788--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage56274299--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage56274299--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage56274299--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage56274299--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage56274299--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage56274299--input564400327-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage56274299--input564400327-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage56274299--input564400327-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage56274299--input654274102-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage56274299--input654274102-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage56274299--input654274102-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage56274299--input654274102-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage690637660--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage690637660--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage690637660--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage690637660--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage806237530--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage806237530--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_nat--storage806237530--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_nat--storage806237530--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage109689253--input1071610051-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage109689253--input1071610051-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage109689253--input1071610051-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage109689253--input1071610051-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage109689253--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage109689253--input700475845-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage109689253--input700475845-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage109689253--input700475845-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage109689253--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage109689253--input905318451-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage109689253--input905318451-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage109689253--input905318451-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage495706788--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage495706788--input700475845-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage495706788--input700475845-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage495706788--input700475845-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage915708427--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage915708427--input700475845-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage915708427--input700475845-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage915708427--input700475845-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage936682951--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage936682951--input905318451-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_mem_string--storage936682951--input905318451-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_mem_string--storage936682951--input905318451-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input15265129-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input15265129-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input15265129-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input15265129-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input158311065-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input158311065-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input158311065-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input158311065-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input456982702-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input456982702-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input456982702-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input456982702-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -map_size--storage492856247--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -map_size--storage492856247--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -mul--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -mul--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -mul--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -mul--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input1067298059-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input1067298059-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input1067298059-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input1067298059-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input380029349-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input380029349-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input380029349-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input380029349-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input563503226-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input563503226-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input563503226-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input563503226-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input788662499-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input788662499-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input788662499-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input788662499-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input972832189-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input972832189-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -neg--storage680650890--input972832189-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -neg--storage680650890--input972832189-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -none--storage11179311--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -none--storage11179311--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -none--storage11179311--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -none--storage11179311--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not--storage921624073--input570553153-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not--storage921624073--input570553153-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not--storage921624073--input570553153-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not--storage921624073--input570553153-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not--storage921624073--input954397288-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not--storage921624073--input954397288-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not--storage921624073--input954397288-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not--storage921624073--input954397288-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input1051197453-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input1051197453-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input1051197453-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input1051197453-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input123939249-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input123939249-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input123939249-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input123939249-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input24243730-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input24243730-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input24243730-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input24243730-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input518945720-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input518945720-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input518945720-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input518945720-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input788662499-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input788662499-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input788662499-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input788662499-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input906118781-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input906118781-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input906118781-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input906118781-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input921874253-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input921874253-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input921874253-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input921874253-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input972832189-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input972832189-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_binary--storage921624073--input972832189-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_binary--storage921624073--input972832189-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_bytes--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -not_bytes--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -not_bytes--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input106930123-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input106930123-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input106930123-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input181204719-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input181204719-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input181204719-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input223774825-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input223774825-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input223774825-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input908807505-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or--storage921624073--input908807505-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or--storage921624073--input908807505-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input1056991424-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input1056991424-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input1056991424-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input1056991424-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input375993021-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input375993021-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input375993021-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input375993021-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input673240563-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input673240563-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input673240563-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input673240563-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input747448890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input747448890-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input747448890-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input747448890-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input832403787-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input832403787-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input832403787-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input832403787-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input858098961-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input858098961-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_binary--storage921624073--input858098961-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_binary--storage921624073--input858098961-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_bytes--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -or_bytes--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -or_bytes--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev--storage125992234--input305844558-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev--storage125992234--input305844558-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev--storage125992234--input305844558-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev--storage125992234--input305844558-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev--storage125992234--input646365167-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev--storage125992234--input646365167-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev--storage125992234--input646365167-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev--storage125992234--input646365167-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input106930123-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input106930123-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input106930123-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input181204719-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input181204719-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input181204719-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input223774825-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input223774825-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input223774825-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input908807505-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pair_id--storage921624073--input908807505-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pair_id--storage921624073--input908807505-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pexec--storage256947135--input1050356042-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pexec--storage256947135--input1050356042-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pexec--storage256947135--input1050356042-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pexec--storage256947135--input1050356042-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pexec_2--storage197120858--input179371027-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pexec_2--storage197120858--input179371027-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -pexec_2--storage197120858--input179371027-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -pexec_2--storage197120858--input179371027-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ret_int--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ret_int--storage921624073--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -ret_int--storage921624073--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -ret_int--storage921624073--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse--storage528921618--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse--storage528921618--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse--storage528921618--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse--storage528921618--input851203613-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse--storage528921618--input851203613-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse--storage528921618--input851203613-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse--storage528921618--input851203613-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse_loop--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse_loop--storage528921618--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse_loop--storage528921618--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse_loop--storage528921618--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse_loop--storage528921618--input851203613-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse_loop--storage528921618--input851203613-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -reverse_loop--storage528921618--input851203613-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -reverse_loop--storage528921618--input851203613-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sapling_empty_state--storage457300675--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sapling_empty_state--storage457300675--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sapling_empty_state--storage457300675--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sapling_empty_state--storage457300675--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -self_address--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -self_address--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -self_address--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -self_address--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -self_with_entrypoint--storage125992234--input289072903-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -self_with_entrypoint--storage125992234--input289072903-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -self_with_entrypoint--storage125992234--input289072903-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -self_with_entrypoint--storage125992234--input289072903-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_car--storage224747103--input620760059-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_car--storage224747103--input620760059-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_car--storage224747103--input620760059-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_car--storage224747103--input620760059-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_car--storage224747103--input717096222-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_car--storage224747103--input717096222-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_car--storage224747103--input717096222-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_car--storage224747103--input717096222-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_car--storage224747103--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_car--storage224747103--input79230375-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_car--storage224747103--input79230375-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_car--storage224747103--input79230375-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_cdr--storage205576101--input654274102-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_cdr--storage205576101--input654274102-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_cdr--storage205576101--input654274102-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_cdr--storage205576101--input654274102-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_cdr--storage224747103--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_cdr--storage224747103--input453441034-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_cdr--storage224747103--input453441034-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_cdr--storage224747103--input453441034-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_cdr--storage611418174--input967284912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_cdr--storage611418174--input967284912-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_cdr--storage611418174--input967284912-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_cdr--storage611418174--input967284912-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_id--storage457300675--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_id--storage457300675--input264787654-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_id--storage457300675--input264787654-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_id--storage457300675--input264787654-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_id--storage457300675--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_id--storage457300675--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_id--storage457300675--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_id--storage457300675--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_id--storage457300675--input989507347-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_id--storage457300675--input989507347-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_id--storage457300675--input989507347-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_id--storage457300675--input989507347-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_iter--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_iter--storage492856247--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_iter--storage492856247--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_iter--storage492856247--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_iter--storage492856247--input701684511-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_iter--storage492856247--input701684511-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_iter--storage492856247--input701684511-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_iter--storage492856247--input701684511-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_iter--storage492856247--input802622031-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_iter--storage492856247--input802622031-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_iter--storage492856247--input802622031-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_iter--storage492856247--input802622031-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_member--storage495706788--input33757838-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_member--storage495706788--input33757838-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_member--storage495706788--input33757838-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_member--storage495706788--input33757838-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_member--storage550087893--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_member--storage550087893--input79230375-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_member--storage550087893--input79230375-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_member--storage550087893--input79230375-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_member--storage605111220--input33757838-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_member--storage605111220--input33757838-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_member--storage605111220--input33757838-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_member--storage605111220--input33757838-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input403499055-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input403499055-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input403499055-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input403499055-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input457300675-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input457300675-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input457300675-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input469078912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input469078912-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input469078912-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input469078912-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input802622031-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input802622031-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -set_size--storage492856247--input802622031-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -set_size--storage492856247--input802622031-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sha3--storage921624073--input1008262038-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sha3--storage921624073--input1008262038-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sha3--storage921624073--input1008262038-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sha3--storage921624073--input1008262038-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input115382786-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input115382786-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input115382786-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input115382786-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input271566295-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input271566295-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input271566295-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input271566295-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input340971987-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input340971987-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input340971987-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input340971987-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input374168553-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input374168553-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input374168553-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input374168553-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input413621582-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input413621582-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input413621582-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input413621582-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input424849461-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input424849461-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input424849461-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input424849461-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input485030042-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input485030042-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input485030042-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input485030042-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input705767726-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input705767726-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input705767726-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input705767726-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input769385932-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input769385932-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input769385932-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input769385932-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input913715337-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input913715337-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -shifts--storage921624073--input913715337-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -shifts--storage921624073--input913715337-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage351480851--input65907686-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage351480851--input65907686-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage351480851--input65907686-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage351480851--input65907686-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input198821575-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input198821575-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input198821575-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input198821575-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input359592843-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input359592843-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input359592843-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input359592843-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input551316239-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input551316239-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input551316239-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input551316239-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input722749044-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input722749044-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input722749044-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input722749044-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input839234860-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input839234860-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input839234860-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input839234860-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input919180079-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input919180079-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage364922380--input919180079-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage364922380--input919180079-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage921624073--input551316239-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage921624073--input551316239-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice--storage921624073--input551316239-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice--storage921624073--input551316239-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input198821575-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input198821575-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input198821575-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input198821575-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input462551352-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input462551352-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input462551352-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input462551352-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input489157380-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input489157380-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input489157380-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input489157380-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input551316239-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input551316239-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input551316239-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input551316239-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input669330759-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input669330759-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input669330759-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input669330759-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input743596105-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input743596105-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input743596105-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input743596105-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input839234860-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input839234860-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage229749865--input839234860-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage229749865--input839234860-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage504917929--input65907686-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage504917929--input65907686-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage504917929--input65907686-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage504917929--input65907686-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage921624073--input462551352-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage921624073--input462551352-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -slice_bytes--storage921624073--input462551352-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -slice_bytes--storage921624073--input462551352-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -str_id--storage921624073--input1016369050-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -str_id--storage921624073--input1016369050-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -str_id--storage921624073--input1016369050-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -str_id--storage921624073--input1016369050-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -str_id--storage921624073--input93477117-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -str_id--storage921624073--input93477117-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -str_id--storage921624073--input93477117-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -str_id--storage921624073--input93477117-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -tez_add_sub--storage921624073--input706350605-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -tez_add_sub--storage921624073--input706350605-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -tez_add_sub--storage921624073--input706350605-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -tez_add_sub--storage921624073--input706350605-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -tez_add_sub--storage921624073--input856198194-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -tez_add_sub--storage921624073--input856198194-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -tez_add_sub--storage921624073--input856198194-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -tez_add_sub--storage921624073--input856198194-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -uncomb--storage680650890--input394061083-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -uncomb--storage680650890--input394061083-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -uncomb--storage680650890--input394061083-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -uncomb--storage680650890--input394061083-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -unpair--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -unpair--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -unpair--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -unpair--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -voting_power--storage1011138251--input1040351577-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -voting_power--storage1011138251--input1040351577-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -voting_power--storage1011138251--input1040351577-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -voting_power--storage1011138251--input1040351577-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input1058477720-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input1058477720-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input1058477720-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input1058477720-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input1073176155-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input1073176155-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input1073176155-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input1073176155-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input246594902-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input246594902-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input246594902-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input246594902-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input506603577-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input506603577-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input506603577-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input506603577-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input576248088-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input576248088-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input576248088-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input576248088-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input612012282-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input612012282-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input612012282-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input612012282-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input617591686-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input617591686-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input617591686-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input617591686-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input639311176-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input639311176-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input639311176-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input639311176-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input688315180-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input688315180-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input688315180-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input688315180-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input967929605-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input967929605-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor--storage921624073--input967929605-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor--storage921624073--input967929605-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor_bytes--storage125992234--input125992234-.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- opcodes -xor_bytes--storage125992234--input125992234-.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- opcodes -xor_bytes--storage125992234--input125992234-.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- BALANCE.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- BALANCE.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- BALANCE.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- BALANCE.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- LEVEL.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- LEVEL.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- LEVEL.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- LEVEL.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- NOW.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- NOW.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- NOW.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- NOW.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- arithmetic_overflow.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- arithmetic_overflow.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- arithmetic_overflow.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- arithmetic_overflow.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- big_map_contract_io.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- big_map_contract_io.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- big_map_contract_io.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- big_map_contract_io.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- check_signature.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- check_signature.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- check_signature.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- check_signature.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- hash_consistency.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- hash_consistency.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- hash_consistency.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- hash_consistency.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- map_map_side_effect.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- map_map_side_effect.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- map_map_side_effect.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- map_map_side_effect.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- pack_unpack.out b/tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- pack_unpack.out similarity index 100% rename from tezt/tests/expected/contract_opcodes.ml/Paris- test Michelson opcodes- pack_unpack.out rename to tezt/tests/expected/contract_opcodes.ml/Parisb- test Michelson opcodes- pack_unpack.out diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input254251340-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input254251340-.out new file mode 100644 index 000000000000..82c98dcf2918 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input254251340-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/abs.tz on storage Unit and input 948 --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 9.929) + [ (Pair 948 Unit) ] + - location: 7 (just consumed gas: 0.010) + [ 948 ] + - location: 8 (just consumed gas: 0.010) + [ 948 + 948 ] + - location: 9 (just consumed gas: 0.026) + [ -948 + 948 ] + - location: 10 (just consumed gas: 0.021) + [ 948 + 948 ] + - location: 11 (just consumed gas: 0.035) + [ 0 ] + - location: 13 (just consumed gas: 0.010) + [ True ] + - location: 14 (just consumed gas: 0.010) + [ ] + - location: 14 (just consumed gas: 0.025) + [ ] + - location: 20 (just consumed gas: 0.010) + [ Unit ] + - location: 21 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input420401245-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input420401245-.out new file mode 100644 index 000000000000..2ca7b6ca2c9f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input420401245-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/abs.tz on storage Unit and input 12039123919239192312931 --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 9.929) + [ (Pair 12039123919239192312931 Unit) ] + - location: 7 (just consumed gas: 0.010) + [ 12039123919239192312931 ] + - location: 8 (just consumed gas: 0.010) + [ 12039123919239192312931 + 12039123919239192312931 ] + - location: 9 (just consumed gas: 0.030) + [ -12039123919239192312931 + 12039123919239192312931 ] + - location: 10 (just consumed gas: 0.025) + [ 12039123919239192312931 + 12039123919239192312931 ] + - location: 11 (just consumed gas: 0.035) + [ 0 ] + - location: 13 (just consumed gas: 0.010) + [ True ] + - location: 14 (just consumed gas: 0.010) + [ ] + - location: 14 (just consumed gas: 0.025) + [ ] + - location: 20 (just consumed gas: 0.010) + [ Unit ] + - location: 21 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input680650890-.out new file mode 100644 index 000000000000..44da17582956 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -abs--storage125992234--input680650890-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/abs.tz on storage Unit and input 0 --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 9.929) + [ (Pair 0 Unit) ] + - location: 7 (just consumed gas: 0.010) + [ 0 ] + - location: 8 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 9 (just consumed gas: 0.025) + [ 0 + 0 ] + - location: 10 (just consumed gas: 0.020) + [ 0 + 0 ] + - location: 11 (just consumed gas: 0.035) + [ 0 ] + - location: 13 (just consumed gas: 0.010) + [ True ] + - location: 14 (just consumed gas: 0.010) + [ ] + - location: 14 (just consumed gas: 0.025) + [ ] + - location: 20 (just consumed gas: 0.010) + [ Unit ] + - location: 21 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add--storage125992234--input125992234-.out new file mode 100644 index 000000000000..57cf793f4ee3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add--storage125992234--input125992234-.out @@ -0,0 +1,211 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 67.780) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ Unit ] + - location: 8 (just consumed gas: 0.010) + [ 2 + Unit ] + - location: 11 (just consumed gas: 0.010) + [ 2 + 2 + Unit ] + - location: 14 (just consumed gas: 0.035) + [ 4 + Unit ] + - location: 15 (just consumed gas: 0.010) + [ 4 + 4 + Unit ] + - location: 20 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 21 (just consumed gas: 0.010) + [ True + Unit ] + - location: 22 (just consumed gas: 0.010) + [ Unit ] + - location: 22 (just consumed gas: 0.025) + [ Unit ] + - location: 28 (just consumed gas: 0.010) + [ 2 + Unit ] + - location: 31 (just consumed gas: 0.010) + [ 2 + 2 + Unit ] + - location: 34 (just consumed gas: 0.035) + [ 4 + Unit ] + - location: 35 (just consumed gas: 0.010) + [ 4 + 4 + Unit ] + - location: 40 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 41 (just consumed gas: 0.010) + [ True + Unit ] + - location: 42 (just consumed gas: 0.010) + [ Unit ] + - location: 42 (just consumed gas: 0.025) + [ Unit ] + - location: 48 (just consumed gas: 0.010) + [ 2 + Unit ] + - location: 51 (just consumed gas: 0.010) + [ 2 + 2 + Unit ] + - location: 54 (just consumed gas: 0.035) + [ 4 + Unit ] + - location: 55 (just consumed gas: 0.010) + [ 4 + 4 + Unit ] + - location: 60 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 61 (just consumed gas: 0.010) + [ True + Unit ] + - location: 62 (just consumed gas: 0.010) + [ Unit ] + - location: 62 (just consumed gas: 0.025) + [ Unit ] + - location: 68 (just consumed gas: 0.010) + [ 2 + Unit ] + - location: 71 (just consumed gas: 0.010) + [ 2 + 2 + Unit ] + - location: 74 (just consumed gas: 0.035) + [ 4 + Unit ] + - location: 75 (just consumed gas: 0.010) + [ 4 + 4 + Unit ] + - location: 80 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 81 (just consumed gas: 0.010) + [ True + Unit ] + - location: 82 (just consumed gas: 0.010) + [ Unit ] + - location: 82 (just consumed gas: 0.025) + [ Unit ] + - location: 88 (just consumed gas: 0.010) + [ 2 + Unit ] + - location: 91 (just consumed gas: 0.010) + [ 2 + 2 + Unit ] + - location: 94 (just consumed gas: 0.035) + [ 4 + Unit ] + - location: 95 (just consumed gas: 0.010) + [ 4 + 4 + Unit ] + - location: 100 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 101 (just consumed gas: 0.010) + [ True + Unit ] + - location: 102 (just consumed gas: 0.010) + [ Unit ] + - location: 102 (just consumed gas: 0.025) + [ Unit ] + - location: 108 (just consumed gas: 0.010) + [ 60 + Unit ] + - location: 111 (just consumed gas: 0.010) + [ "2019-09-09T12:08:37Z" + 60 + Unit ] + - location: 114 (just consumed gas: 0.037) + [ "2019-09-09T12:09:37Z" + Unit ] + - location: 115 (just consumed gas: 0.010) + [ "2019-09-09T12:09:37Z" + "2019-09-09T12:09:37Z" + Unit ] + - location: 120 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 121 (just consumed gas: 0.010) + [ True + Unit ] + - location: 122 (just consumed gas: 0.010) + [ Unit ] + - location: 122 (just consumed gas: 0.025) + [ Unit ] + - location: 128 (just consumed gas: 0.010) + [ "2019-09-09T12:08:37Z" + Unit ] + - location: 131 (just consumed gas: 0.010) + [ 60 + "2019-09-09T12:08:37Z" + Unit ] + - location: 134 (just consumed gas: 0.037) + [ "2019-09-09T12:09:37Z" + Unit ] + - location: 135 (just consumed gas: 0.010) + [ "2019-09-09T12:09:37Z" + "2019-09-09T12:09:37Z" + Unit ] + - location: 140 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 141 (just consumed gas: 0.010) + [ True + Unit ] + - location: 142 (just consumed gas: 0.010) + [ Unit ] + - location: 142 (just consumed gas: 0.025) + [ Unit ] + - location: 148 (just consumed gas: 0.010) + [ 1000 + Unit ] + - location: 151 (just consumed gas: 0.010) + [ 1000 + 1000 + Unit ] + - location: 154 (just consumed gas: 0.020) + [ 2000 + Unit ] + - location: 155 (just consumed gas: 0.010) + [ 2000 + 2000 + Unit ] + - location: 160 (just consumed gas: 0.035) + [ 0 + Unit ] + - location: 161 (just consumed gas: 0.010) + [ True + Unit ] + - location: 162 (just consumed gas: 0.010) + [ Unit ] + - location: 162 (just consumed gas: 0.025) + [ Unit ] + - location: 168 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 170 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out new file mode 100644 index 000000000000..e43cab01c4e8 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input322109491-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x01 0x00' --level 1 --trace-stack +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.239) + [ (Pair (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 11 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.030) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out new file mode 100644 index 000000000000..28e69c152159 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input461261325-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x010000 0x010000' --level 1 --trace-stack +storage + (Some 0x0200000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.239) + [ (Pair (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0100000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 11 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.030) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} + (Some 0x0200000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out new file mode 100644 index 000000000000..bc4454e5b822 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input530006774-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x010000 0x00' --level 1 --trace-stack +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.239) + [ (Pair (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 11 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.030) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} + (Some 0x0100000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out new file mode 100644 index 000000000000..773711b1453f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_bls12_381_fr--storage921624073--input712570300-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x00 0x00' --level 1 --trace-stack +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.239) + [ (Pair (Pair 0x0000000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) + None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0x0000000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 11 (just consumed gas: 0.010) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.030) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input249636002-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input249636002-.out new file mode 100644 index 000000000000..33dff120bd23 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input249636002-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_delta_timestamp.tz on storage None and input '(Pair 100 100)' --level 1 --trace-stack +storage + (Some "1970-01-01T00:03:20Z") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 8.093) + [ (Pair (Pair 100 "1970-01-01T00:01:40Z") None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 100 "1970-01-01T00:01:40Z") ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 100 "1970-01-01T00:01:40Z") + (Pair 100 "1970-01-01T00:01:40Z") ] + - location: 12 (just consumed gas: 0.010) + [ 100 + (Pair 100 "1970-01-01T00:01:40Z") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair 100 "1970-01-01T00:01:40Z") ] + - location: 15 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" ] + - location: 13 (just consumed gas: 0.035) + [ 100 + "1970-01-01T00:01:40Z" ] + - location: 16 (just consumed gas: 0.035) + [ "1970-01-01T00:03:20Z" ] + - location: 17 (just consumed gas: 0.010) + [ (Some "1970-01-01T00:03:20Z") ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Some "1970-01-01T00:03:20Z") ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some "1970-01-01T00:03:20Z")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input267363182-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input267363182-.out new file mode 100644 index 000000000000..c2f0d1ff262c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input267363182-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_delta_timestamp.tz on storage None and input '(Pair -100 100)' --level 1 --trace-stack +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 8.093) + [ (Pair (Pair -100 "1970-01-01T00:01:40Z") None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair -100 "1970-01-01T00:01:40Z") ] + - location: 11 (just consumed gas: 0.010) + [ (Pair -100 "1970-01-01T00:01:40Z") + (Pair -100 "1970-01-01T00:01:40Z") ] + - location: 12 (just consumed gas: 0.010) + [ -100 + (Pair -100 "1970-01-01T00:01:40Z") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair -100 "1970-01-01T00:01:40Z") ] + - location: 15 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" ] + - location: 13 (just consumed gas: 0.035) + [ -100 + "1970-01-01T00:01:40Z" ] + - location: 16 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (just consumed gas: 0.010) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input438561129-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input438561129-.out new file mode 100644 index 000000000000..2934ad95fd16 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_delta_timestamp--storage921624073--input438561129-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_delta_timestamp.tz on storage None and input '(Pair 0 "1970-01-01T00:00:00Z")' --level 1 --trace-stack +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 8.201) + [ (Pair (Pair 0 "1970-01-01T00:00:00Z") None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 "1970-01-01T00:00:00Z") ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 0 "1970-01-01T00:00:00Z") + (Pair 0 "1970-01-01T00:00:00Z") ] + - location: 12 (just consumed gas: 0.010) + [ 0 + (Pair 0 "1970-01-01T00:00:00Z") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair 0 "1970-01-01T00:00:00Z") ] + - location: 15 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" ] + - location: 13 (just consumed gas: 0.035) + [ 0 + "1970-01-01T00:00:00Z" ] + - location: 16 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (just consumed gas: 0.010) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input249636002-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input249636002-.out new file mode 100644 index 000000000000..e86173273084 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input249636002-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_timestamp_delta.tz on storage None and input '(Pair 100 100)' --level 1 --trace-stack +storage + (Some "1970-01-01T00:03:20Z") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 8.093) + [ (Pair (Pair "1970-01-01T00:01:40Z" 100) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 100) + (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 12 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 15 (just consumed gas: 0.010) + [ 100 ] + - location: 13 (just consumed gas: 0.035) + [ "1970-01-01T00:01:40Z" + 100 ] + - location: 16 (just consumed gas: 0.035) + [ "1970-01-01T00:03:20Z" ] + - location: 17 (just consumed gas: 0.010) + [ (Some "1970-01-01T00:03:20Z") ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Some "1970-01-01T00:03:20Z") ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some "1970-01-01T00:03:20Z")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input307538219-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input307538219-.out new file mode 100644 index 000000000000..468b0bfca406 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input307538219-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_timestamp_delta.tz on storage None and input '(Pair 100 -100)' --level 1 --trace-stack +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 8.093) + [ (Pair (Pair "1970-01-01T00:01:40Z" -100) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" -100) + (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 12 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 15 (just consumed gas: 0.010) + [ -100 ] + - location: 13 (just consumed gas: 0.035) + [ "1970-01-01T00:01:40Z" + -100 ] + - location: 16 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (just consumed gas: 0.010) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input373737581-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input373737581-.out new file mode 100644 index 000000000000..b018f8e88ede --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -add_timestamp_delta--storage921624073--input373737581-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/add_timestamp_delta.tz on storage None and input '(Pair "1970-01-01T00:00:00Z" 0)' --level 1 --trace-stack +storage + (Some "1970-01-01T00:00:00Z") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 8.201) + [ (Pair (Pair "1970-01-01T00:00:00Z" 0) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" 0) + (Pair "1970-01-01T00:00:00Z" 0) ] + - location: 12 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" + (Pair "1970-01-01T00:00:00Z" 0) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" 0) ] + - location: 15 (just consumed gas: 0.010) + [ 0 ] + - location: 13 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" + 0 ] + - location: 16 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" ] + - location: 17 (just consumed gas: 0.010) + [ (Some "1970-01-01T00:00:00Z") ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Some "1970-01-01T00:00:00Z") ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some "1970-01-01T00:00:00Z")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -address--storage921624073--input117475800-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -address--storage921624073--input117475800-.out new file mode 100644 index 000000000000..e212021f8099 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -address--storage921624073--input117475800-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/address.tz on storage None and input '"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"' --level 1 --trace-stack +storage + (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 8.984) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" None) ] + - location: 9 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 10 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 11 (just consumed gas: 0.010) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 12 (just consumed gas: 0.010) + [ {} + (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input106930123-.out new file mode 100644 index 000000000000..3f8b3f266f71 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input106930123-.out @@ -0,0 +1,31 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and.tz on storage None and input '(Pair False True)' --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.431) + [ (Pair (Pair False True) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair False True) ] + - location: 11 (just consumed gas: 0.010) + [ False + True ] + - location: 12 (just consumed gas: 0.010) + [ False ] + - location: 13 (just consumed gas: 0.010) + [ (Some False) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input181204719-.out new file mode 100644 index 000000000000..28f35cfd93b8 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input181204719-.out @@ -0,0 +1,31 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and.tz on storage None and input '(Pair True False)' --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.431) + [ (Pair (Pair True False) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair True False) ] + - location: 11 (just consumed gas: 0.010) + [ True + False ] + - location: 12 (just consumed gas: 0.010) + [ False ] + - location: 13 (just consumed gas: 0.010) + [ (Some False) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input223774825-.out new file mode 100644 index 000000000000..166370ac8812 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input223774825-.out @@ -0,0 +1,31 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and.tz on storage None and input '(Pair False False)' --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.431) + [ (Pair (Pair False False) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair False False) ] + - location: 11 (just consumed gas: 0.010) + [ False + False ] + - location: 12 (just consumed gas: 0.010) + [ False ] + - location: 13 (just consumed gas: 0.010) + [ (Some False) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input908807505-.out new file mode 100644 index 000000000000..700446f39983 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and--storage921624073--input908807505-.out @@ -0,0 +1,31 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and.tz on storage None and input '(Pair True True)' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.431) + [ (Pair (Pair True True) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair True True) ] + - location: 11 (just consumed gas: 0.010) + [ True + True ] + - location: 12 (just consumed gas: 0.010) + [ True ] + - location: 13 (just consumed gas: 0.010) + [ (Some True) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_binary--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_binary--storage125992234--input125992234-.out new file mode 100644 index 000000000000..df5dac0a2f0d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_binary--storage125992234--input125992234-.out @@ -0,0 +1,93 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and_binary.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 35.762) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 5 ] + - location: 11 (just consumed gas: 0.010) + [ 6 + 5 ] + - location: 14 (just consumed gas: 0.035) + [ 4 ] + - location: 15 (just consumed gas: 0.010) + [ 4 + 4 ] + - location: 20 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 6 ] + - location: 31 (just consumed gas: 0.010) + [ 5 + 6 ] + - location: 34 (just consumed gas: 0.035) + [ 4 ] + - location: 35 (just consumed gas: 0.010) + [ 4 + 4 ] + - location: 40 (just consumed gas: 0.035) + [ 0 ] + - location: 41 (just consumed gas: 0.010) + [ True ] + - location: 42 (just consumed gas: 0.010) + [ ] + - location: 42 (just consumed gas: 0.025) + [ ] + - location: 48 (just consumed gas: 0.010) + [ 12 ] + - location: 51 (just consumed gas: 0.010) + [ -1 + 12 ] + - location: 54 (just consumed gas: 0.035) + [ 12 ] + - location: 55 (just consumed gas: 0.010) + [ 12 + 12 ] + - location: 60 (just consumed gas: 0.035) + [ 0 ] + - location: 61 (just consumed gas: 0.010) + [ True ] + - location: 62 (just consumed gas: 0.010) + [ ] + - location: 62 (just consumed gas: 0.025) + [ ] + - location: 68 (just consumed gas: 0.010) + [ 12 ] + - location: 71 (just consumed gas: 0.010) + [ -5 + 12 ] + - location: 74 (just consumed gas: 0.035) + [ 8 ] + - location: 75 (just consumed gas: 0.010) + [ 8 + 8 ] + - location: 80 (just consumed gas: 0.035) + [ 0 ] + - location: 81 (just consumed gas: 0.010) + [ True ] + - location: 82 (just consumed gas: 0.010) + [ ] + - location: 82 (just consumed gas: 0.025) + [ ] + - location: 88 (just consumed gas: 0.010) + [ Unit ] + - location: 89 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 91 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_bytes--storage125992234--input125992234-.out new file mode 100644 index 000000000000..faec812269e0 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_bytes--storage125992234--input125992234-.out @@ -0,0 +1,75 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and_bytes_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 27.915) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0x05 ] + - location: 11 (just consumed gas: 0.010) + [ 0x06 + 0x05 ] + - location: 14 (just consumed gas: 0.035) + [ 0x04 ] + - location: 15 (just consumed gas: 0.010) + [ 0x04 + 0x04 ] + - location: 20 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 0x0005 ] + - location: 31 (just consumed gas: 0.010) + [ 0x0106 + 0x0005 ] + - location: 34 (just consumed gas: 0.036) + [ 0x0004 ] + - location: 35 (just consumed gas: 0.010) + [ 0x0004 + 0x0004 ] + - location: 40 (just consumed gas: 0.035) + [ 0 ] + - location: 41 (just consumed gas: 0.010) + [ True ] + - location: 42 (just consumed gas: 0.010) + [ ] + - location: 42 (just consumed gas: 0.025) + [ ] + - location: 48 (just consumed gas: 0.010) + [ 0x05 ] + - location: 51 (just consumed gas: 0.010) + [ 0x0106 + 0x05 ] + - location: 54 (just consumed gas: 0.035) + [ 0x04 ] + - location: 55 (just consumed gas: 0.010) + [ 0x04 + 0x04 ] + - location: 60 (just consumed gas: 0.035) + [ 0 ] + - location: 61 (just consumed gas: 0.010) + [ True ] + - location: 62 (just consumed gas: 0.010) + [ ] + - location: 62 (just consumed gas: 0.025) + [ ] + - location: 68 (just consumed gas: 0.010) + [ Unit ] + - location: 69 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 71 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input106930123-.out new file mode 100644 index 000000000000..f208d8c515a1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input106930123-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and_logical_1.tz on storage False and input '(Pair False True)' --level 1 --trace-stack +storage + False +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.330) + [ (Pair (Pair False True) False) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair False True) ] + - location: 10 (just consumed gas: 0.010) + [ False + True ] + - location: 11 (just consumed gas: 0.010) + [ False ] + - location: 12 (just consumed gas: 0.010) + [ {} + False ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} False) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input181204719-.out new file mode 100644 index 000000000000..1aadbd892f2a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input181204719-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and_logical_1.tz on storage False and input '(Pair True False)' --level 1 --trace-stack +storage + False +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.330) + [ (Pair (Pair True False) False) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair True False) ] + - location: 10 (just consumed gas: 0.010) + [ True + False ] + - location: 11 (just consumed gas: 0.010) + [ False ] + - location: 12 (just consumed gas: 0.010) + [ {} + False ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} False) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input223774825-.out new file mode 100644 index 000000000000..c53813e62de2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input223774825-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and_logical_1.tz on storage False and input '(Pair False False)' --level 1 --trace-stack +storage + False +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.330) + [ (Pair (Pair False False) False) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair False False) ] + - location: 10 (just consumed gas: 0.010) + [ False + False ] + - location: 11 (just consumed gas: 0.010) + [ False ] + - location: 12 (just consumed gas: 0.010) + [ {} + False ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} False) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input908807505-.out new file mode 100644 index 000000000000..59211a0e1372 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -and_logical_1--storage570553153--input908807505-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/and_logical_1.tz on storage False and input '(Pair True True)' --level 1 --trace-stack +storage + True +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.330) + [ (Pair (Pair True True) False) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair True True) ] + - location: 10 (just consumed gas: 0.010) + [ True + True ] + - location: 11 (just consumed gas: 0.010) + [ True ] + - location: 12 (just consumed gas: 0.010) + [ {} + True ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} True) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -balance--storage492856247--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -balance--storage492856247--input125992234-.out new file mode 100644 index 000000000000..81d6f6df3205 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -balance--storage492856247--input125992234-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/balance.tz on storage 111 and input Unit --level 1 --trace-stack +storage + 4000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 111) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 4000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 4000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 4000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage495706788--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage495706788--input453441034-.out new file mode 100644 index 000000000000..3b4b61d3660d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage495706788--input453441034-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_nat.tz on storage '(Pair {} None)' and input 1 --level 1 --trace-stack +storage + (Pair 4 (Some False)) +emitted operations + +big_map diff + New map(4) of type (big_map nat nat) +trace + - location: 12 (just consumed gas: 9.644) + [ (Pair 1 {} None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair {} None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} None) ] + - location: 15 (just consumed gas: 0.010) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.035) + [ 1 + {} + {} ] + - location: 17 (just consumed gas: 0.722) + [ False + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + {} ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair {} (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input453441034-.out new file mode 100644 index 000000000000..b532b0b261c2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input453441034-.out @@ -0,0 +1,44 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_nat.tz on storage '(Pair { Elt 1 4 ; Elt 2 11 } None)' and input 1 --level 1 --trace-stack +storage + (Pair 4 (Some True)) +emitted operations + +big_map diff + New map(4) of type (big_map nat nat) + Set map(4)[1] to 4 + Set map(4)[2] to 11 +trace + - location: 12 (just consumed gas: 11.552) + [ (Pair 1 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (just consumed gas: 0.035) + [ 1 + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (just consumed gas: 0.723) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input564400327-.out new file mode 100644 index 000000000000..300548c30485 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input564400327-.out @@ -0,0 +1,44 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_nat.tz on storage '(Pair { Elt 1 4 ; Elt 2 11 } None)' and input 2 --level 1 --trace-stack +storage + (Pair 4 (Some True)) +emitted operations + +big_map diff + New map(4) of type (big_map nat nat) + Set map(4)[1] to 4 + Set map(4)[2] to 11 +trace + - location: 12 (just consumed gas: 11.552) + [ (Pair 2 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 2 + (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (just consumed gas: 0.035) + [ 2 + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (just consumed gas: 0.723) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input654274102-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input654274102-.out new file mode 100644 index 000000000000..08e6df3dba31 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage56274299--input654274102-.out @@ -0,0 +1,44 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_nat.tz on storage '(Pair { Elt 1 4 ; Elt 2 11 } None)' and input 3 --level 1 --trace-stack +storage + (Pair 4 (Some False)) +emitted operations + +big_map diff + New map(4) of type (big_map nat nat) + Set map(4)[1] to 4 + Set map(4)[2] to 11 +trace + - location: 12 (just consumed gas: 11.552) + [ (Pair 3 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 3 + (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (just consumed gas: 0.035) + [ 3 + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (just consumed gas: 0.723) + [ False + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage690637660--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage690637660--input453441034-.out new file mode 100644 index 000000000000..ace4af654d2d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage690637660--input453441034-.out @@ -0,0 +1,43 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_nat.tz on storage '(Pair { Elt 1 0 } None)' and input 1 --level 1 --trace-stack +storage + (Pair 4 (Some True)) +emitted operations + +big_map diff + New map(4) of type (big_map nat nat) + Set map(4)[1] to 0 +trace + - location: 12 (just consumed gas: 10.579) + [ (Pair 1 { Elt 1 0 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair { Elt 1 0 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 0 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 0 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: 13 (just consumed gas: 0.035) + [ 1 + { Elt 1 0 } + { Elt 1 0 } ] + - location: 17 (just consumed gas: 0.723) + [ True + { Elt 1 0 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt 1 0 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 0 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 0 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 0 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 0 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage806237530--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage806237530--input453441034-.out new file mode 100644 index 000000000000..8a41d2b1e31a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_nat--storage806237530--input453441034-.out @@ -0,0 +1,43 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_nat.tz on storage '(Pair { Elt 0 1 } None)' and input 1 --level 1 --trace-stack +storage + (Pair 4 (Some False)) +emitted operations + +big_map diff + New map(4) of type (big_map nat nat) + Set map(4)[0] to 1 +trace + - location: 12 (just consumed gas: 10.554) + [ (Pair 1 { Elt 0 1 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair { Elt 0 1 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 0 1 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 0 1 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: 13 (just consumed gas: 0.035) + [ 1 + { Elt 0 1 } + { Elt 0 1 } ] + - location: 17 (just consumed gas: 0.723) + [ False + { Elt 0 1 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt 0 1 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 0 1 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 0 1 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 0 1 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 0 1 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input1071610051-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input1071610051-.out new file mode 100644 index 000000000000..0a74df4d1692 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input1071610051-.out @@ -0,0 +1,44 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_string.tz on storage '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)' and input '"baz"' --level 1 --trace-stack +storage + (Pair 4 (Some False)) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["bar"] to 4 + Set map(4)["foo"] to 11 +trace + - location: 12 (just consumed gas: 11.711) + [ (Pair "baz" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "baz" + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (just consumed gas: 0.035) + [ "baz" + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (just consumed gas: 0.735) + [ False + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input700475845-.out new file mode 100644 index 000000000000..29a55bb58d59 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input700475845-.out @@ -0,0 +1,44 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_string.tz on storage '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)' and input '"bar"' --level 1 --trace-stack +storage + (Pair 4 (Some True)) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["bar"] to 4 + Set map(4)["foo"] to 11 +trace + - location: 12 (just consumed gas: 11.711) + [ (Pair "bar" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "bar" + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (just consumed gas: 0.035) + [ "bar" + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (just consumed gas: 0.735) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input905318451-.out new file mode 100644 index 000000000000..d36dcabaa07c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage109689253--input905318451-.out @@ -0,0 +1,44 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_string.tz on storage '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)' and input '"foo"' --level 1 --trace-stack +storage + (Pair 4 (Some True)) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["bar"] to 4 + Set map(4)["foo"] to 11 +trace + - location: 12 (just consumed gas: 11.711) + [ (Pair "foo" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "foo" + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (just consumed gas: 0.035) + [ "foo" + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (just consumed gas: 0.735) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage495706788--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage495706788--input700475845-.out new file mode 100644 index 000000000000..22bcf6787d83 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage495706788--input700475845-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_string.tz on storage '(Pair {} None)' and input '"bar"' --level 1 --trace-stack +storage + (Pair 4 (Some False)) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) +trace + - location: 12 (just consumed gas: 9.689) + [ (Pair "bar" {} None) ] + - location: 12 (just consumed gas: 0.010) + [ "bar" + (Pair {} None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} None) ] + - location: 15 (just consumed gas: 0.010) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.035) + [ "bar" + {} + {} ] + - location: 17 (just consumed gas: 0.734) + [ False + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + {} ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair {} (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage915708427--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage915708427--input700475845-.out new file mode 100644 index 000000000000..f1720cab34a2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage915708427--input700475845-.out @@ -0,0 +1,43 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_string.tz on storage '(Pair { Elt "foo" 1 } None)' and input '"bar"' --level 1 --trace-stack +storage + (Pair 4 (Some False)) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["foo"] to 1 +trace + - location: 12 (just consumed gas: 10.681) + [ (Pair "bar" { Elt "foo" 1 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "bar" + (Pair { Elt "foo" 1 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 1 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "foo" 1 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 13 (just consumed gas: 0.035) + [ "bar" + { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 17 (just consumed gas: 0.735) + [ False + { Elt "foo" 1 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt "foo" 1 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "foo" 1 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 1 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "foo" 1 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "foo" 1 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage936682951--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage936682951--input905318451-.out new file mode 100644 index 000000000000..8c4391817d47 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -big_map_mem_string--storage936682951--input905318451-.out @@ -0,0 +1,43 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/big_map_mem_string.tz on storage '(Pair { Elt "foo" 0 } None)' and input '"foo"' --level 1 --trace-stack +storage + (Pair 4 (Some True)) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["foo"] to 0 +trace + - location: 12 (just consumed gas: 10.681) + [ (Pair "foo" { Elt "foo" 0 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "foo" + (Pair { Elt "foo" 0 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 0 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "foo" 0 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 13 (just consumed gas: 0.035) + [ "foo" + { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 17 (just consumed gas: 0.735) + [ True + { Elt "foo" 0 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt "foo" 0 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "foo" 0 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 0 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "foo" 0 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "foo" 0 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out new file mode 100644 index 000000000000..05433275014a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_bytes_not_padded--storage921624073--input1259.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_push_bytes_not_padded.tz on storage None and input Unit --level 1 --trace-stack +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.491) + [ (Pair Unit None) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.010) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 13 (just consumed gas: 0.010) + [ {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair {} + (Some 0x0000000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out new file mode 100644 index 000000000000..0897c32b0e87 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_push_nat--storage921624073--input125992234-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_push_nat.tz on storage None and input Unit --level 1 --trace-stack +storage + (Some 0x1000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.491) + [ (Pair Unit None) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.010) + [ 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Some 0x1000000000000000000000000000000000000000000000000000000000000000) ] + - location: 13 (just consumed gas: 0.010) + [ {} + (Some 0x1000000000000000000000000000000000000000000000000000000000000000) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair {} + (Some 0x1000000000000000000000000000000000000000000000000000000000000000)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out new file mode 100644 index 000000000000..3098bbac51ec --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input1043734173-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz on storage 0 and input 0x01 --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0) ] + - location: 7 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.115) + [ 1 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out new file mode 100644 index 000000000000..a85dc103883c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input151303925-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz on storage 0 and input 0x00 --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0) ] + - location: 7 (just consumed gas: 0.010) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.115) + [ 0 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out new file mode 100644 index 000000000000..e3a412476bcf --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input520610122-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz on storage 0 and input 0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c0b0719 --level 1 --trace-stack +storage + 11320265829256585830781521966149529460476767408210445238902869222031333517497 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c0b0719 0) ] + - location: 7 (just consumed gas: 0.010) + [ 0xb9e8abf8dc324a010007addde986fe0f7c81fab16d26819d0534b7691c0b0719 ] + - location: 8 (just consumed gas: 0.115) + [ 11320265829256585830781521966149529460476767408210445238902869222031333517497 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 11320265829256585830781521966149529460476767408210445238902869222031333517497 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} + 11320265829256585830781521966149529460476767408210445238902869222031333517497) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out new file mode 100644 index 000000000000..e7ff646aa1e1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_int--storage680650890--input558805129-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz on storage 0 and input 0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9af16c27 --level 1 --trace-stack +storage + 17832688077013577776524784494464728518213913213412866604053735695200962927400 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9af16c27 0) ] + - location: 7 (just consumed gas: 0.010) + [ 0x28db8e57af88d9576acd181b89f24e50a89a6423f939026ed91349fc9af16c27 ] + - location: 8 (just consumed gas: 0.115) + [ 17832688077013577776524784494464728518213913213412866604053735695200962927400 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 17832688077013577776524784494464728518213913213412866604053735695200962927400 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} + 17832688077013577776524784494464728518213913213412866604053735695200962927400) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out new file mode 100644 index 000000000000..96be3231bd72 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_to_mutez--storage680650890--input229402968-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_to_mutez.tz on storage 0 and input 0x10 --level 1 --trace-stack +storage + 16 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 9.127) + [ (Pair 0x1000000000000000000000000000000000000000000000000000000000000000 0) ] + - location: 7 (just consumed gas: 0.010) + [ 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.115) + [ 16 ] + - location: 9 (just consumed gas: 0.010) + [ (Some 16) ] + - location: 11 (just consumed gas: 0.010) + [ 16 ] + - location: 11 (just consumed gas: 0.025) + [ 16 ] + - location: 17 (just consumed gas: 0.010) + [ 1 + 16 ] + - location: 20 (just consumed gas: 0.050) + [ 16 ] + - location: 21 (just consumed gas: 0.010) + [ {} + 16 ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} 16) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out new file mode 100644 index 000000000000..77388b3a01ee --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage287336412--input1019409032-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f and input 22620284817922784902564672469917992996328211127984472897491698543785655336309 --level 1 --trace-stack +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (just consumed gas: 0.010) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f ] + - location: 8 (just consumed gas: 0.299) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out new file mode 100644 index 000000000000..c5c5e686a94e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage698210250--input949526473-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f and input 33644916630334844239120348434626468649534186770809802792596996408934105684394 --level 1 --trace-stack +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (just consumed gas: 0.010) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f ] + - location: 8 (just consumed gas: 0.299) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out new file mode 100644 index 000000000000..2caa8d3fe709 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input166435292-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 69615968247920749285624776342583898043608129789011377475114141186797415307882 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out new file mode 100644 index 000000000000..2f78fde8e77b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage739946440--input583291483-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 17180093072794558806177035834397932205917577288483739652510482486858834123369 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out new file mode 100644 index 000000000000..a38d18ead3e2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input1055524890-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 52435875175126190479447740508185965837690552500527637822603658699938581184514 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.299) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out new file mode 100644 index 000000000000..ec88da1bdc0b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input453441034-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 1 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 1 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.266) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out new file mode 100644 index 000000000000..b829a7645fe2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input564400327-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 2 --level 1 --trace-stack +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 2 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.266) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out new file mode 100644 index 000000000000..44dcd6df7496 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input585234482-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input -42 --level 1 --trace-stack +storage + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair -42 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ -42 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.266) + [ 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out new file mode 100644 index 000000000000..0ec0a4f6ca85 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input680650890-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 0 --level 1 --trace-stack +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 0 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.265) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out new file mode 100644 index 000000000000..d99155086cb5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_int--storage994282947--input701858804-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input -1 --level 1 --trace-stack +storage + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair -1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ -1 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.266) + [ 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out new file mode 100644 index 000000000000..473a4357be01 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage287336412--input1019409032-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f and input 22620284817922784902564672469917992996328211127984472897491698543785655336309 --level 1 --trace-stack +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (just consumed gas: 0.010) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f ] + - location: 8 (just consumed gas: 0.299) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out new file mode 100644 index 000000000000..08ce729e7173 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage698210250--input949526473-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f and input 33644916630334844239120348434626468649534186770809802792596996408934105684394 --level 1 --trace-stack +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (just consumed gas: 0.010) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f ] + - location: 8 (just consumed gas: 0.299) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out new file mode 100644 index 000000000000..9c769f2197fc --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input166435292-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 69615968247920749285624776342583898043608129789011377475114141186797415307882 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out new file mode 100644 index 000000000000..0e5c09f71f0b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage739946440--input583291483-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 17180093072794558806177035834397932205917577288483739652510482486858834123369 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out new file mode 100644 index 000000000000..6ccb4b279eb6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input1055524890-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 52435875175126190479447740508185965837690552500527637822603658699938581184514 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.299) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out new file mode 100644 index 000000000000..65adff1df7d8 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input453441034-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 1 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 1 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.266) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out new file mode 100644 index 000000000000..2934008c8275 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input564400327-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 2 --level 1 --trace-stack +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 2 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.266) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out new file mode 100644 index 000000000000..293f5f1d80d4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_fr_z_nat--storage994282947--input680650890-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 0 --level 1 --trace-stack +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.278) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 0 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.265) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out new file mode 100644 index 000000000000..7faab30dba8f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage287336412--input1019409032-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f and input 22620284817922784902564672469917992996328211127984472897491698543785655336309 --level 1 --trace-stack +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (just consumed gas: 0.010) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f ] + - location: 8 (just consumed gas: 0.010) + [ 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f + 22620284817922784902564672469917992996328211127984472897491698543785655336309 ] + - location: 9 (just consumed gas: 0.299) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out new file mode 100644 index 000000000000..6418e3001f44 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage698210250--input949526473-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f and input 33644916630334844239120348434626468649534186770809802792596996408934105684394 --level 1 --trace-stack +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (just consumed gas: 0.010) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f ] + - location: 8 (just consumed gas: 0.010) + [ 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f + 33644916630334844239120348434626468649534186770809802792596996408934105684394 ] + - location: 9 (just consumed gas: 0.299) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out new file mode 100644 index 000000000000..785f9b18694b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input166435292-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 69615968247920749285624776342583898043608129789011377475114141186797415307882 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.010) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d + 69615968247920749285624776342583898043608129789011377475114141186797415307882 ] + - location: 9 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out new file mode 100644 index 000000000000..91a0e4ca5a46 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage739946440--input583291483-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 17180093072794558806177035834397932205917577288483739652510482486858834123369 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.010) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d + 17180093072794558806177035834397932205917577288483739652510482486858834123369 ] + - location: 9 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out new file mode 100644 index 000000000000..25cf95d0d3ea --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input1055524890-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 52435875175126190479447740508185965837690552500527637822603658699938581184514 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 52435875175126190479447740508185965837690552500527637822603658699938581184514 ] + - location: 9 (just consumed gas: 0.299) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out new file mode 100644 index 000000000000..61cc53f291bd --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input453441034-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 1 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 1 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 1 ] + - location: 9 (just consumed gas: 0.266) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out new file mode 100644 index 000000000000..a503770787c5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input564400327-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 2 --level 1 --trace-stack +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 2 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 2 ] + - location: 9 (just consumed gas: 0.266) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out new file mode 100644 index 000000000000..aa8192d4eab7 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input585234482-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input -42 --level 1 --trace-stack +storage + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair -42 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ -42 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + -42 ] + - location: 9 (just consumed gas: 0.266) + [ 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0xd7fffffffefffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out new file mode 100644 index 000000000000..779e8ed804cb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input680650890-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 0 --level 1 --trace-stack +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 0 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0 ] + - location: 9 (just consumed gas: 0.265) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out new file mode 100644 index 000000000000..3f4d7a12f1dd --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_int--storage994282947--input701858804-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input -1 --level 1 --trace-stack +storage + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair -1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ -1 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + -1 ] + - location: 9 (just consumed gas: 0.266) + [ 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out new file mode 100644 index 000000000000..b60ad89680f3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage287336412--input1019409032-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f and input 22620284817922784902564672469917992996328211127984472897491698543785655336309 --level 1 --trace-stack +storage + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f) ] + - location: 7 (just consumed gas: 0.010) + [ 22620284817922784902564672469917992996328211127984472897491698543785655336309 + 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f ] + - location: 8 (just consumed gas: 0.010) + [ 0x4147a5ad0a633e4880d2296f08ec5c12d03e3fa4a6b49ecbd16a30a3cfcdbe3f + 22620284817922784902564672469917992996328211127984472897491698543785655336309 ] + - location: 9 (just consumed gas: 0.299) + [ 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x4e387e0ebfb3d1633153c195036e0c0b672955c4a0e420f93ec20a76fe677c62) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out new file mode 100644 index 000000000000..15edddd1b9e6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage698210250--input949526473-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f and input 33644916630334844239120348434626468649534186770809802792596996408934105684394 --level 1 --trace-stack +storage + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f) ] + - location: 7 (just consumed gas: 0.010) + [ 33644916630334844239120348434626468649534186770809802792596996408934105684394 + 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f ] + - location: 8 (just consumed gas: 0.010) + [ 0x5b0ecd0fa853810e356f1eb79721e80b30510fcc3a455f4fc02fdd9a90c5401f + 33644916630334844239120348434626468649534186770809802792596996408934105684394 ] + - location: 9 (just consumed gas: 0.299) + [ 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x2ef123703093cbbbd124e15f2054fa5781ed0b8d092ec3c6e5d76b4ca918a221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out new file mode 100644 index 000000000000..97199d5d9387 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input166435292-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 69615968247920749285624776342583898043608129789011377475114141186797415307882 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 69615968247920749285624776342583898043608129789011377475114141186797415307882 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.010) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d + 69615968247920749285624776342583898043608129789011377475114141186797415307882 ] + - location: 9 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out new file mode 100644 index 000000000000..e5c930416b17 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage739946440--input583291483-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d and input 17180093072794558806177035834397932205917577288483739652510482486858834123369 --level 1 --trace-stack +storage + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d) ] + - location: 7 (just consumed gas: 0.010) + [ 17180093072794558806177035834397932205917577288483739652510482486858834123369 + 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d ] + - location: 8 (just consumed gas: 0.010) + [ 0x8578be1766f92cd82c5e5135c374a03a8562e263ea953a3f9711b0153b7fcf2d + 17180093072794558806177035834397932205917577288483739652510482486858834123369 ] + - location: 9 (just consumed gas: 0.299) + [ 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0xfaa60dacea8e26112e524d379720fe4f95fbc5a26f1b1a67e229e26ddecbf221) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out new file mode 100644 index 000000000000..4765d03e87f3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input1055524890-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 52435875175126190479447740508185965837690552500527637822603658699938581184514 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 52435875175126190479447740508185965837690552500527637822603658699938581184514 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 52435875175126190479447740508185965837690552500527637822603658699938581184514 ] + - location: 9 (just consumed gas: 0.299) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out new file mode 100644 index 000000000000..c1b196de1e91 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input453441034-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 1 --level 1 --trace-stack +storage + 0x0100000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 1 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 1 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 1 ] + - location: 9 (just consumed gas: 0.266) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0100000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out new file mode 100644 index 000000000000..823ab6b8e58b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input564400327-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 2 --level 1 --trace-stack +storage + 0x0200000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 2 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 2 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 2 ] + - location: 9 (just consumed gas: 0.266) + [ 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0200000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0200000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out new file mode 100644 index 000000000000..d56101833806 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bls12_381_z_fr_nat--storage994282947--input680650890-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz on storage 0x0100000000000000000000000000000000000000000000000000000000000000 and input 0 --level 1 --trace-stack +storage + 0x0000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.831) + [ (Pair 0 0x0100000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 0 + 0x0100000000000000000000000000000000000000000000000000000000000000 ] + - location: 8 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 0 ] + - location: 9 (just consumed gas: 0.265) + [ 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x0000000000000000000000000000000000000000000000000000000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x0000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_int--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_int--storage125992234--input125992234-.out new file mode 100644 index 000000000000..94a038ed4c26 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_int--storage125992234--input125992234-.out @@ -0,0 +1,261 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bytes_of_int_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 116.835) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0 ] + - location: 11 (just consumed gas: 0.090) + [ 0x ] + - location: 12 (just consumed gas: 0.010) + [ 0x + 0x ] + - location: 17 (just consumed gas: 0.035) + [ 0 ] + - location: 18 (just consumed gas: 0.010) + [ True ] + - location: 19 (just consumed gas: 0.010) + [ ] + - location: 19 (just consumed gas: 0.025) + [ ] + - location: 25 (just consumed gas: 0.010) + [ 1 ] + - location: 28 (just consumed gas: 0.093) + [ 0x01 ] + - location: 29 (just consumed gas: 0.010) + [ 0x01 + 0x01 ] + - location: 34 (just consumed gas: 0.035) + [ 0 ] + - location: 35 (just consumed gas: 0.010) + [ True ] + - location: 36 (just consumed gas: 0.010) + [ ] + - location: 36 (just consumed gas: 0.025) + [ ] + - location: 42 (just consumed gas: 0.010) + [ 1193046 ] + - location: 45 (just consumed gas: 0.099) + [ 0x123456 ] + - location: 46 (just consumed gas: 0.010) + [ 0x123456 + 0x123456 ] + - location: 51 (just consumed gas: 0.035) + [ 0 ] + - location: 52 (just consumed gas: 0.010) + [ True ] + - location: 53 (just consumed gas: 0.010) + [ ] + - location: 53 (just consumed gas: 0.025) + [ ] + - location: 59 (just consumed gas: 0.010) + [ 0x123456 ] + - location: 62 (just consumed gas: 0.027) + [ 1193046 ] + - location: 63 (just consumed gas: 0.010) + [ 1193046 + 1193046 ] + - location: 68 (just consumed gas: 0.035) + [ 0 ] + - location: 69 (just consumed gas: 0.010) + [ True ] + - location: 70 (just consumed gas: 0.010) + [ ] + - location: 70 (just consumed gas: 0.025) + [ ] + - location: 76 (just consumed gas: 0.010) + [ 0x0000123456 ] + - location: 79 (just consumed gas: 0.032) + [ 1193046 ] + - location: 80 (just consumed gas: 0.010) + [ 1193046 + 1193046 ] + - location: 85 (just consumed gas: 0.035) + [ 0 ] + - location: 86 (just consumed gas: 0.010) + [ True ] + - location: 87 (just consumed gas: 0.010) + [ ] + - location: 87 (just consumed gas: 0.025) + [ ] + - location: 93 (just consumed gas: 0.010) + [ 0x ] + - location: 96 (just consumed gas: 0.020) + [ 0 ] + - location: 97 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 102 (just consumed gas: 0.035) + [ 0 ] + - location: 103 (just consumed gas: 0.010) + [ True ] + - location: 104 (just consumed gas: 0.010) + [ ] + - location: 104 (just consumed gas: 0.025) + [ ] + - location: 110 (just consumed gas: 0.010) + [ 0x0000 ] + - location: 113 (just consumed gas: 0.025) + [ 0 ] + - location: 114 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 119 (just consumed gas: 0.035) + [ 0 ] + - location: 120 (just consumed gas: 0.010) + [ True ] + - location: 121 (just consumed gas: 0.010) + [ ] + - location: 121 (just consumed gas: 0.025) + [ ] + - location: 127 (just consumed gas: 0.010) + [ -128 ] + - location: 130 (just consumed gas: 0.093) + [ 0x80 ] + - location: 131 (just consumed gas: 0.010) + [ 0x80 + 0x80 ] + - location: 136 (just consumed gas: 0.035) + [ 0 ] + - location: 137 (just consumed gas: 0.010) + [ True ] + - location: 138 (just consumed gas: 0.010) + [ ] + - location: 138 (just consumed gas: 0.025) + [ ] + - location: 144 (just consumed gas: 0.010) + [ -129 ] + - location: 147 (just consumed gas: 0.093) + [ 0xff7f ] + - location: 148 (just consumed gas: 0.010) + [ 0xff7f + 0xff7f ] + - location: 153 (just consumed gas: 0.035) + [ 0 ] + - location: 154 (just consumed gas: 0.010) + [ True ] + - location: 155 (just consumed gas: 0.010) + [ ] + - location: 155 (just consumed gas: 0.025) + [ ] + - location: 161 (just consumed gas: 0.010) + [ -33024 ] + - location: 164 (just consumed gas: 0.096) + [ 0xff7f00 ] + - location: 165 (just consumed gas: 0.010) + [ 0xff7f00 + 0xff7f00 ] + - location: 170 (just consumed gas: 0.035) + [ 0 ] + - location: 171 (just consumed gas: 0.010) + [ True ] + - location: 172 (just consumed gas: 0.010) + [ ] + - location: 172 (just consumed gas: 0.025) + [ ] + - location: 178 (just consumed gas: 0.010) + [ -4294967296 ] + - location: 181 (just consumed gas: 0.105) + [ 0xff00000000 ] + - location: 182 (just consumed gas: 0.010) + [ 0xff00000000 + 0xff00000000 ] + - location: 187 (just consumed gas: 0.035) + [ 0 ] + - location: 188 (just consumed gas: 0.010) + [ True ] + - location: 189 (just consumed gas: 0.010) + [ ] + - location: 189 (just consumed gas: 0.025) + [ ] + - location: 195 (just consumed gas: 0.010) + [ 0x80 ] + - location: 198 (just consumed gas: 0.022) + [ -128 ] + - location: 199 (just consumed gas: 0.010) + [ -128 + -128 ] + - location: 204 (just consumed gas: 0.035) + [ 0 ] + - location: 205 (just consumed gas: 0.010) + [ True ] + - location: 206 (just consumed gas: 0.010) + [ ] + - location: 206 (just consumed gas: 0.025) + [ ] + - location: 212 (just consumed gas: 0.010) + [ 0xff7f ] + - location: 215 (just consumed gas: 0.025) + [ -129 ] + - location: 216 (just consumed gas: 0.010) + [ -129 + -129 ] + - location: 221 (just consumed gas: 0.035) + [ 0 ] + - location: 222 (just consumed gas: 0.010) + [ True ] + - location: 223 (just consumed gas: 0.010) + [ ] + - location: 223 (just consumed gas: 0.025) + [ ] + - location: 229 (just consumed gas: 0.010) + [ 0xff7f00 ] + - location: 232 (just consumed gas: 0.027) + [ -33024 ] + - location: 233 (just consumed gas: 0.010) + [ -33024 + -33024 ] + - location: 238 (just consumed gas: 0.035) + [ 0 ] + - location: 239 (just consumed gas: 0.010) + [ True ] + - location: 240 (just consumed gas: 0.010) + [ ] + - location: 240 (just consumed gas: 0.025) + [ ] + - location: 246 (just consumed gas: 0.010) + [ 0xffffff7f00 ] + - location: 249 (just consumed gas: 0.032) + [ -33024 ] + - location: 250 (just consumed gas: 0.010) + [ -33024 + -33024 ] + - location: 255 (just consumed gas: 0.035) + [ 0 ] + - location: 256 (just consumed gas: 0.010) + [ True ] + - location: 257 (just consumed gas: 0.010) + [ ] + - location: 257 (just consumed gas: 0.025) + [ ] + - location: 263 (just consumed gas: 0.010) + [ 0xff00000000 ] + - location: 266 (just consumed gas: 0.032) + [ -4294967296 ] + - location: 267 (just consumed gas: 0.010) + [ -4294967296 + -4294967296 ] + - location: 272 (just consumed gas: 0.035) + [ 0 ] + - location: 273 (just consumed gas: 0.010) + [ True ] + - location: 274 (just consumed gas: 0.010) + [ ] + - location: 274 (just consumed gas: 0.025) + [ ] + - location: 280 (just consumed gas: 0.010) + [ Unit ] + - location: 281 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 283 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_nat--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_nat--storage125992234--input125992234-.out new file mode 100644 index 000000000000..27f4c432e873 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -bytes_of_nat--storage125992234--input125992234-.out @@ -0,0 +1,126 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/bytes_of_nat_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 52.991) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0 ] + - location: 11 (just consumed gas: 0.075) + [ 0x ] + - location: 12 (just consumed gas: 0.010) + [ 0x + 0x ] + - location: 17 (just consumed gas: 0.035) + [ 0 ] + - location: 18 (just consumed gas: 0.010) + [ True ] + - location: 19 (just consumed gas: 0.010) + [ ] + - location: 19 (just consumed gas: 0.025) + [ ] + - location: 25 (just consumed gas: 0.010) + [ 1 ] + - location: 28 (just consumed gas: 0.078) + [ 0x01 ] + - location: 29 (just consumed gas: 0.010) + [ 0x01 + 0x01 ] + - location: 34 (just consumed gas: 0.035) + [ 0 ] + - location: 35 (just consumed gas: 0.010) + [ True ] + - location: 36 (just consumed gas: 0.010) + [ ] + - location: 36 (just consumed gas: 0.025) + [ ] + - location: 42 (just consumed gas: 0.010) + [ 1193046 ] + - location: 45 (just consumed gas: 0.084) + [ 0x123456 ] + - location: 46 (just consumed gas: 0.010) + [ 0x123456 + 0x123456 ] + - location: 51 (just consumed gas: 0.035) + [ 0 ] + - location: 52 (just consumed gas: 0.010) + [ True ] + - location: 53 (just consumed gas: 0.010) + [ ] + - location: 53 (just consumed gas: 0.025) + [ ] + - location: 59 (just consumed gas: 0.010) + [ 0x123456 ] + - location: 62 (just consumed gas: 0.052) + [ 1193046 ] + - location: 63 (just consumed gas: 0.010) + [ 1193046 + 1193046 ] + - location: 68 (just consumed gas: 0.035) + [ 0 ] + - location: 69 (just consumed gas: 0.010) + [ True ] + - location: 70 (just consumed gas: 0.010) + [ ] + - location: 70 (just consumed gas: 0.025) + [ ] + - location: 76 (just consumed gas: 0.010) + [ 0x0000123456 ] + - location: 79 (just consumed gas: 0.057) + [ 1193046 ] + - location: 80 (just consumed gas: 0.010) + [ 1193046 + 1193046 ] + - location: 85 (just consumed gas: 0.035) + [ 0 ] + - location: 86 (just consumed gas: 0.010) + [ True ] + - location: 87 (just consumed gas: 0.010) + [ ] + - location: 87 (just consumed gas: 0.025) + [ ] + - location: 93 (just consumed gas: 0.010) + [ 0x ] + - location: 96 (just consumed gas: 0.045) + [ 0 ] + - location: 97 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 102 (just consumed gas: 0.035) + [ 0 ] + - location: 103 (just consumed gas: 0.010) + [ True ] + - location: 104 (just consumed gas: 0.010) + [ ] + - location: 104 (just consumed gas: 0.025) + [ ] + - location: 110 (just consumed gas: 0.010) + [ 0x0000 ] + - location: 113 (just consumed gas: 0.050) + [ 0 ] + - location: 114 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 119 (just consumed gas: 0.035) + [ 0 ] + - location: 120 (just consumed gas: 0.010) + [ True ] + - location: 121 (just consumed gas: 0.010) + [ ] + - location: 121 (just consumed gas: 0.025) + [ ] + - location: 127 (just consumed gas: 0.010) + [ Unit ] + - location: 128 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 130 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -car--storage680650890--input783124233-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -car--storage680650890--input783124233-.out new file mode 100644 index 000000000000..4385fccfde23 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -car--storage680650890--input783124233-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/car.tz on storage 0 and input '(Pair 34 17)' --level 1 --trace-stack +storage + 34 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.615) + [ (Pair (Pair 34 17) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair 34 17) ] + - location: 10 (just consumed gas: 0.010) + [ 34 ] + - location: 11 (just consumed gas: 0.010) + [ {} + 34 ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} 34) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cdr--storage680650890--input783124233-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cdr--storage680650890--input783124233-.out new file mode 100644 index 000000000000..cdd80e285c9d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cdr--storage680650890--input783124233-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/cdr.tz on storage 0 and input '(Pair 34 17)' --level 1 --trace-stack +storage + 17 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.615) + [ (Pair (Pair 34 17) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair 34 17) ] + - location: 10 (just consumed gas: 0.010) + [ 17 ] + - location: 11 (just consumed gas: 0.010) + [ {} + 17 ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} 17) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage109160754--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage109160754--input125992234-.out new file mode 100644 index 000000000000..16edc91f64c7 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage109160754--input125992234-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/chain_id_store.tz on storage '(Some 0x7a06a770)' and input Unit --level 1 --trace-stack +storage + (Some "NetXynUjJNZm7wi") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.057) + [ (Pair Unit (Some "NetXdQprcVkpaWU")) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.015) + [ "NetXynUjJNZm7wi" ] + - location: 10 (just consumed gas: 0.010) + [ (Some "NetXynUjJNZm7wi") ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some "NetXynUjJNZm7wi") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some "NetXynUjJNZm7wi")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage921624073--input125992234-.out new file mode 100644 index 000000000000..e07ae813017c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage921624073--input125992234-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/chain_id_store.tz on storage None and input Unit --level 1 --trace-stack +storage + (Some "NetXynUjJNZm7wi") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair Unit None) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.015) + [ "NetXynUjJNZm7wi" ] + - location: 10 (just consumed gas: 0.010) + [ (Some "NetXynUjJNZm7wi") ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some "NetXynUjJNZm7wi") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some "NetXynUjJNZm7wi")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage981066851--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage981066851--input125992234-.out new file mode 100644 index 000000000000..8ab438a454ab --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -chain_id_store--storage981066851--input125992234-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/chain_id_store.tz on storage '(Some "NetXynUjJNZm7wi")' and input Unit --level 1 --trace-stack +storage + (Some "NetXynUjJNZm7wi") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.607) + [ (Pair Unit (Some "NetXynUjJNZm7wi")) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.015) + [ "NetXynUjJNZm7wi" ] + - location: 10 (just consumed gas: 0.010) + [ (Some "NetXynUjJNZm7wi") ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some "NetXynUjJNZm7wi") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some "NetXynUjJNZm7wi")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb--storage950292965--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb--storage950292965--input125992234-.out new file mode 100644 index 000000000000..77ac6b721805 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb--storage950292965--input125992234-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/comb.tz on storage '(Pair 0 0 0)' and input Unit --level 1 --trace-stack +storage + (Pair 1 2 3) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.970) + [ (Pair Unit 0 0 0) ] + - location: 10 (just consumed gas: 0.010) + [ ] + - location: 11 (just consumed gas: 0.010) + [ 3 ] + - location: 14 (just consumed gas: 0.010) + [ 2 + 3 ] + - location: 17 (just consumed gas: 0.010) + [ 1 + 2 + 3 ] + - location: 20 (just consumed gas: 0.010) + [ {} + 1 + 2 + 3 ] + - location: 22 (just consumed gas: 0.046) + [ (Pair {} 1 2 3) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-get--storage125992234--input186507116-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-get--storage125992234--input186507116-.out new file mode 100644 index 000000000000..3f98bc2f3cc6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-get--storage125992234--input186507116-.out @@ -0,0 +1,123 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/comb-get.tz on storage Unit and input '(Pair 1 4 2 Unit)' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 42.680) + [ (Pair (Pair 1 4 2 Unit) Unit) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - location: 13 (just consumed gas: 0.010) + [ 1 + (Pair 1 4 2 Unit) ] + - location: 14 (just consumed gas: 0.010) + [ 1 + 1 + (Pair 1 4 2 Unit) ] + - location: 19 (just consumed gas: 0.035) + [ 0 + (Pair 1 4 2 Unit) ] + - location: 20 (just consumed gas: 0.010) + [ True + (Pair 1 4 2 Unit) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 21 (just consumed gas: 0.025) + [ (Pair 1 4 2 Unit) ] + - location: 27 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - location: 28 (just consumed gas: 0.020) + [ 1 + (Pair 1 4 2 Unit) ] + - location: 30 (just consumed gas: 0.010) + [ 1 + 1 + (Pair 1 4 2 Unit) ] + - location: 35 (just consumed gas: 0.035) + [ 0 + (Pair 1 4 2 Unit) ] + - location: 36 (just consumed gas: 0.010) + [ True + (Pair 1 4 2 Unit) ] + - location: 37 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 37 (just consumed gas: 0.025) + [ (Pair 1 4 2 Unit) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - location: 44 (just consumed gas: 0.021) + [ 4 + (Pair 1 4 2 Unit) ] + - location: 46 (just consumed gas: 0.010) + [ 4 + 4 + (Pair 1 4 2 Unit) ] + - location: 51 (just consumed gas: 0.035) + [ 0 + (Pair 1 4 2 Unit) ] + - location: 52 (just consumed gas: 0.010) + [ True + (Pair 1 4 2 Unit) ] + - location: 53 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 53 (just consumed gas: 0.025) + [ (Pair 1 4 2 Unit) ] + - location: 59 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - location: 60 (just consumed gas: 0.022) + [ 2 + (Pair 1 4 2 Unit) ] + - location: 62 (just consumed gas: 0.010) + [ 2 + 2 + (Pair 1 4 2 Unit) ] + - location: 67 (just consumed gas: 0.035) + [ 0 + (Pair 1 4 2 Unit) ] + - location: 68 (just consumed gas: 0.010) + [ True + (Pair 1 4 2 Unit) ] + - location: 69 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 69 (just consumed gas: 0.025) + [ (Pair 1 4 2 Unit) ] + - location: 75 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) + (Pair 1 4 2 Unit) ] + - location: 76 (just consumed gas: 0.023) + [ Unit + (Pair 1 4 2 Unit) ] + - location: 78 (just consumed gas: 0.010) + [ Unit + Unit + (Pair 1 4 2 Unit) ] + - location: 81 (just consumed gas: 0.010) + [ 0 + (Pair 1 4 2 Unit) ] + - location: 82 (just consumed gas: 0.010) + [ True + (Pair 1 4 2 Unit) ] + - location: 83 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 83 (just consumed gas: 0.025) + [ (Pair 1 4 2 Unit) ] + - location: 89 (just consumed gas: 0.010) + [ ] + - location: 90 (just consumed gas: 0.010) + [ Unit ] + - location: 91 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 93 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set--storage186507116--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set--storage186507116--input125992234-.out new file mode 100644 index 000000000000..0bade07c2b20 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set--storage186507116--input125992234-.out @@ -0,0 +1,39 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/comb-set.tz on storage '(Pair 1 4 2 Unit)' and input Unit --level 1 --trace-stack +storage + (Pair 2 12 8 Unit) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 12.261) + [ (Pair Unit 1 4 2 Unit) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 12 (just consumed gas: 0.010) + [ 2 + (Pair 1 4 2 Unit) ] + - location: 15 (just consumed gas: 0.031) + [ (Pair 2 4 2 Unit) ] + - location: 17 (just consumed gas: 0.010) + [ 12 + (Pair 2 4 2 Unit) ] + - location: 20 (just consumed gas: 0.033) + [ (Pair 2 12 2 Unit) ] + - location: 22 (just consumed gas: 0.010) + [ 8 + (Pair 2 12 2 Unit) ] + - location: 25 (just consumed gas: 0.036) + [ (Pair 2 12 8 Unit) ] + - location: 27 (just consumed gas: 0.010) + [ Unit + (Pair 2 12 8 Unit) ] + - location: 28 (just consumed gas: 0.037) + [ (Pair 2 12 8 Unit) ] + - location: 30 (just consumed gas: 0.010) + [ {} + (Pair 2 12 8 Unit) ] + - location: 32 (just consumed gas: 0.010) + [ (Pair {} 2 12 8 Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set-2--storage921624073--input186507116-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set-2--storage921624073--input186507116-.out new file mode 100644 index 000000000000..0ae4739f4e27 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comb-set-2--storage921624073--input186507116-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/comb-set-2.tz on storage None and input '(Pair 1 4 2 Unit)' --level 1 --trace-stack +storage + (Some (Pair 2 4 "toto" 0x01)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 12.494) + [ (Pair (Pair 1 4 2 Unit) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 1 4 2 Unit) ] + - location: 17 (just consumed gas: 0.010) + [ 2 + (Pair 1 4 2 Unit) ] + - location: 20 (just consumed gas: 0.031) + [ (Pair 2 4 2 Unit) ] + - location: 22 (just consumed gas: 0.010) + [ "toto" + (Pair 2 4 2 Unit) ] + - location: 25 (just consumed gas: 0.036) + [ (Pair 2 4 "toto" Unit) ] + - location: 27 (just consumed gas: 0.010) + [ 0x01 + (Pair 2 4 "toto" Unit) ] + - location: 30 (just consumed gas: 0.037) + [ (Pair 2 4 "toto" 0x01) ] + - location: 32 (just consumed gas: 0.010) + [ (Some (Pair 2 4 "toto" 0x01)) ] + - location: 33 (just consumed gas: 0.010) + [ {} + (Some (Pair 2 4 "toto" 0x01)) ] + - location: 35 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair 2 4 "toto" 0x01))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -compare--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -compare--storage125992234--input125992234-.out new file mode 100644 index 000000000000..e15ee83ea557 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -compare--storage125992234--input125992234-.out @@ -0,0 +1,398 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/compare.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 198.113) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ True ] + - location: 11 (just consumed gas: 0.010) + [ True + True ] + - location: 12 (just consumed gas: 0.035) + [ 0 ] + - location: 14 (just consumed gas: 0.010) + [ True ] + - location: 15 (just consumed gas: 0.010) + [ ] + - location: 15 (just consumed gas: 0.025) + [ ] + - location: 21 (just consumed gas: 0.010) + [ False ] + - location: 24 (just consumed gas: 0.010) + [ False + False ] + - location: 25 (just consumed gas: 0.035) + [ 0 ] + - location: 27 (just consumed gas: 0.010) + [ True ] + - location: 28 (just consumed gas: 0.010) + [ ] + - location: 28 (just consumed gas: 0.025) + [ ] + - location: 34 (just consumed gas: 0.010) + [ False ] + - location: 37 (just consumed gas: 0.010) + [ True + False ] + - location: 40 (just consumed gas: 0.035) + [ 1 ] + - location: 42 (just consumed gas: 0.010) + [ True ] + - location: 43 (just consumed gas: 0.010) + [ ] + - location: 43 (just consumed gas: 0.025) + [ ] + - location: 49 (just consumed gas: 0.010) + [ True ] + - location: 52 (just consumed gas: 0.010) + [ False + True ] + - location: 55 (just consumed gas: 0.035) + [ -1 ] + - location: 57 (just consumed gas: 0.010) + [ True ] + - location: 58 (just consumed gas: 0.010) + [ ] + - location: 58 (just consumed gas: 0.025) + [ ] + - location: 64 (just consumed gas: 0.010) + [ 0xaabbcc ] + - location: 67 (just consumed gas: 0.010) + [ 0xaabbcc + 0xaabbcc ] + - location: 68 (just consumed gas: 0.035) + [ 0 ] + - location: 70 (just consumed gas: 0.010) + [ True ] + - location: 71 (just consumed gas: 0.010) + [ ] + - location: 71 (just consumed gas: 0.025) + [ ] + - location: 77 (just consumed gas: 0.010) + [ 0x ] + - location: 80 (just consumed gas: 0.010) + [ 0x + 0x ] + - location: 83 (just consumed gas: 0.035) + [ 0 ] + - location: 85 (just consumed gas: 0.010) + [ True ] + - location: 86 (just consumed gas: 0.010) + [ ] + - location: 86 (just consumed gas: 0.025) + [ ] + - location: 92 (just consumed gas: 0.010) + [ 0x ] + - location: 95 (just consumed gas: 0.010) + [ 0x01 + 0x ] + - location: 98 (just consumed gas: 0.035) + [ 1 ] + - location: 100 (just consumed gas: 0.010) + [ True ] + - location: 101 (just consumed gas: 0.010) + [ ] + - location: 101 (just consumed gas: 0.025) + [ ] + - location: 107 (just consumed gas: 0.010) + [ 0x01 ] + - location: 110 (just consumed gas: 0.010) + [ 0x02 + 0x01 ] + - location: 113 (just consumed gas: 0.035) + [ 1 ] + - location: 115 (just consumed gas: 0.010) + [ True ] + - location: 116 (just consumed gas: 0.010) + [ ] + - location: 116 (just consumed gas: 0.025) + [ ] + - location: 122 (just consumed gas: 0.010) + [ 0x02 ] + - location: 125 (just consumed gas: 0.010) + [ 0x01 + 0x02 ] + - location: 128 (just consumed gas: 0.035) + [ -1 ] + - location: 130 (just consumed gas: 0.010) + [ True ] + - location: 131 (just consumed gas: 0.010) + [ ] + - location: 131 (just consumed gas: 0.025) + [ ] + - location: 137 (just consumed gas: 0.010) + [ 1 ] + - location: 140 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 141 (just consumed gas: 0.035) + [ 0 ] + - location: 143 (just consumed gas: 0.010) + [ True ] + - location: 144 (just consumed gas: 0.010) + [ ] + - location: 144 (just consumed gas: 0.025) + [ ] + - location: 150 (just consumed gas: 0.010) + [ 10 ] + - location: 153 (just consumed gas: 0.010) + [ 5 + 10 ] + - location: 156 (just consumed gas: 0.035) + [ -1 ] + - location: 158 (just consumed gas: 0.010) + [ True ] + - location: 159 (just consumed gas: 0.010) + [ ] + - location: 159 (just consumed gas: 0.025) + [ ] + - location: 165 (just consumed gas: 0.010) + [ -4 ] + - location: 168 (just consumed gas: 0.010) + [ 1923 + -4 ] + - location: 171 (just consumed gas: 0.035) + [ 1 ] + - location: 173 (just consumed gas: 0.010) + [ True ] + - location: 174 (just consumed gas: 0.010) + [ ] + - location: 174 (just consumed gas: 0.025) + [ ] + - location: 180 (just consumed gas: 0.010) + [ 1 ] + - location: 183 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 184 (just consumed gas: 0.035) + [ 0 ] + - location: 186 (just consumed gas: 0.010) + [ True ] + - location: 187 (just consumed gas: 0.010) + [ ] + - location: 187 (just consumed gas: 0.025) + [ ] + - location: 193 (just consumed gas: 0.010) + [ 10 ] + - location: 196 (just consumed gas: 0.010) + [ 5 + 10 ] + - location: 199 (just consumed gas: 0.035) + [ -1 ] + - location: 201 (just consumed gas: 0.010) + [ True ] + - location: 202 (just consumed gas: 0.010) + [ ] + - location: 202 (just consumed gas: 0.025) + [ ] + - location: 208 (just consumed gas: 0.010) + [ 4 ] + - location: 211 (just consumed gas: 0.010) + [ 1923 + 4 ] + - location: 214 (just consumed gas: 0.035) + [ 1 ] + - location: 216 (just consumed gas: 0.010) + [ True ] + - location: 217 (just consumed gas: 0.010) + [ ] + - location: 217 (just consumed gas: 0.025) + [ ] + - location: 223 (just consumed gas: 0.010) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 226 (just consumed gas: 0.010) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 227 (just consumed gas: 0.036) + [ 0 ] + - location: 229 (just consumed gas: 0.010) + [ True ] + - location: 230 (just consumed gas: 0.010) + [ ] + - location: 230 (just consumed gas: 0.025) + [ ] + - location: 236 (just consumed gas: 0.010) + [ "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" ] + - location: 239 (just consumed gas: 0.010) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" ] + - location: 242 (just consumed gas: 0.036) + [ -1 ] + - location: 244 (just consumed gas: 0.010) + [ True ] + - location: 245 (just consumed gas: 0.010) + [ ] + - location: 245 (just consumed gas: 0.025) + [ ] + - location: 251 (just consumed gas: 0.010) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 254 (just consumed gas: 0.010) + [ "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" + "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 257 (just consumed gas: 0.036) + [ 1 ] + - location: 259 (just consumed gas: 0.010) + [ True ] + - location: 260 (just consumed gas: 0.010) + [ ] + - location: 260 (just consumed gas: 0.025) + [ ] + - location: 266 (just consumed gas: 0.010) + [ 1 ] + - location: 269 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 270 (just consumed gas: 0.035) + [ 0 ] + - location: 272 (just consumed gas: 0.010) + [ True ] + - location: 273 (just consumed gas: 0.010) + [ ] + - location: 273 (just consumed gas: 0.025) + [ ] + - location: 279 (just consumed gas: 0.010) + [ 10 ] + - location: 282 (just consumed gas: 0.010) + [ 5 + 10 ] + - location: 285 (just consumed gas: 0.035) + [ -1 ] + - location: 287 (just consumed gas: 0.010) + [ True ] + - location: 288 (just consumed gas: 0.010) + [ ] + - location: 288 (just consumed gas: 0.025) + [ ] + - location: 294 (just consumed gas: 0.010) + [ 4 ] + - location: 297 (just consumed gas: 0.010) + [ 1923 + 4 ] + - location: 300 (just consumed gas: 0.035) + [ 1 ] + - location: 302 (just consumed gas: 0.010) + [ True ] + - location: 303 (just consumed gas: 0.010) + [ ] + - location: 303 (just consumed gas: 0.025) + [ ] + - location: 309 (just consumed gas: 0.010) + [ "AABBCC" ] + - location: 312 (just consumed gas: 0.010) + [ "AABBCC" + "AABBCC" ] + - location: 313 (just consumed gas: 0.035) + [ 0 ] + - location: 315 (just consumed gas: 0.010) + [ True ] + - location: 316 (just consumed gas: 0.010) + [ ] + - location: 316 (just consumed gas: 0.025) + [ ] + - location: 322 (just consumed gas: 0.010) + [ "" ] + - location: 325 (just consumed gas: 0.010) + [ "" + "" ] + - location: 328 (just consumed gas: 0.035) + [ 0 ] + - location: 330 (just consumed gas: 0.010) + [ True ] + - location: 331 (just consumed gas: 0.010) + [ ] + - location: 331 (just consumed gas: 0.025) + [ ] + - location: 337 (just consumed gas: 0.010) + [ "" ] + - location: 340 (just consumed gas: 0.010) + [ "a" + "" ] + - location: 343 (just consumed gas: 0.035) + [ 1 ] + - location: 345 (just consumed gas: 0.010) + [ True ] + - location: 346 (just consumed gas: 0.010) + [ ] + - location: 346 (just consumed gas: 0.025) + [ ] + - location: 352 (just consumed gas: 0.010) + [ "a" ] + - location: 355 (just consumed gas: 0.010) + [ "b" + "a" ] + - location: 358 (just consumed gas: 0.035) + [ 1 ] + - location: 360 (just consumed gas: 0.010) + [ True ] + - location: 361 (just consumed gas: 0.010) + [ ] + - location: 361 (just consumed gas: 0.025) + [ ] + - location: 367 (just consumed gas: 0.010) + [ "b" ] + - location: 370 (just consumed gas: 0.010) + [ "a" + "b" ] + - location: 373 (just consumed gas: 0.035) + [ -1 ] + - location: 375 (just consumed gas: 0.010) + [ True ] + - location: 376 (just consumed gas: 0.010) + [ ] + - location: 376 (just consumed gas: 0.025) + [ ] + - location: 382 (just consumed gas: 0.010) + [ "2019-09-16T08:38:05Z" ] + - location: 385 (just consumed gas: 0.010) + [ "2019-09-16T08:38:05Z" + "2019-09-16T08:38:05Z" ] + - location: 386 (just consumed gas: 0.035) + [ 0 ] + - location: 388 (just consumed gas: 0.010) + [ True ] + - location: 389 (just consumed gas: 0.010) + [ ] + - location: 389 (just consumed gas: 0.025) + [ ] + - location: 395 (just consumed gas: 0.010) + [ "2017-09-16T08:38:04Z" ] + - location: 398 (just consumed gas: 0.010) + [ "2019-09-16T08:38:05Z" + "2017-09-16T08:38:04Z" ] + - location: 401 (just consumed gas: 0.035) + [ 1 ] + - location: 403 (just consumed gas: 0.010) + [ True ] + - location: 404 (just consumed gas: 0.010) + [ ] + - location: 404 (just consumed gas: 0.025) + [ ] + - location: 410 (just consumed gas: 0.010) + [ "2019-09-16T08:38:05Z" ] + - location: 413 (just consumed gas: 0.010) + [ "2019-09-16T08:38:04Z" + "2019-09-16T08:38:05Z" ] + - location: 416 (just consumed gas: 0.035) + [ -1 ] + - location: 418 (just consumed gas: 0.010) + [ True ] + - location: 419 (just consumed gas: 0.010) + [ ] + - location: 419 (just consumed gas: 0.025) + [ ] + - location: 425 (just consumed gas: 0.010) + [ Unit ] + - location: 426 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 428 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comparisons--storage457300675--input281780712-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comparisons--storage457300675--input281780712-.out new file mode 100644 index 000000000000..f43b0cfd5b74 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -comparisons--storage457300675--input281780712-.out @@ -0,0 +1,350 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/comparisons.tz on storage '{}' and input '{ -9999999; -1 ; 0 ; 1 ; 9999999 }' --level 1 --trace-stack +storage + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 29.053) + [ (Pair { -9999999 ; -1 ; 0 ; 1 ; 9999999 } {}) ] + - location: 10 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 11 (just consumed gas: 0.010) + [ {} + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 14 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 16 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 17 (just consumed gas: 0.050) + [ -9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 19 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 17 (just consumed gas: 0.055) + [ -1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 19 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 17 (just consumed gas: 0.055) + [ 0 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 19 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 17 (just consumed gas: 0.055) + [ 1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 19 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 17 (just consumed gas: 0.055) + [ 9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 19 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 17 (just consumed gas: 0.073) + [ { False ; False ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 14 (just consumed gas: 0.035) + [ {} + { False ; False ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 20 (just consumed gas: 0.010) + [ { False ; False ; True ; False ; False } + {} + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 21 (just consumed gas: 0.010) + [ { { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 22 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 24 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 25 (just consumed gas: 0.050) + [ -9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 27 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 25 (just consumed gas: 0.055) + [ -1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 27 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 25 (just consumed gas: 0.055) + [ 0 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 27 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 25 (just consumed gas: 0.055) + [ 1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 27 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 25 (just consumed gas: 0.055) + [ 9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 27 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 25 (just consumed gas: 0.073) + [ { True ; True ; False ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 22 (just consumed gas: 0.035) + [ { { False ; False ; True ; False ; False } } + { True ; True ; False ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 28 (just consumed gas: 0.010) + [ { True ; True ; False ; True ; True } + { { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 29 (just consumed gas: 0.010) + [ { { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 30 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 32 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 33 (just consumed gas: 0.050) + [ -9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 35 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 33 (just consumed gas: 0.055) + [ -1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 35 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 33 (just consumed gas: 0.055) + [ 0 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 35 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 33 (just consumed gas: 0.055) + [ 1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 35 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 33 (just consumed gas: 0.055) + [ 9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 35 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 33 (just consumed gas: 0.073) + [ { True ; True ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 30 (just consumed gas: 0.035) + [ { { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { True ; True ; True ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 36 (just consumed gas: 0.010) + [ { True ; True ; True ; False ; False } + { { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 37 (just consumed gas: 0.010) + [ { { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 38 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 40 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 41 (just consumed gas: 0.050) + [ -9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 43 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 41 (just consumed gas: 0.055) + [ -1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 43 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 41 (just consumed gas: 0.055) + [ 0 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 43 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 41 (just consumed gas: 0.055) + [ 1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 43 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 41 (just consumed gas: 0.055) + [ 9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 43 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 41 (just consumed gas: 0.073) + [ { True ; True ; False ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 38 (just consumed gas: 0.035) + [ { { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { True ; True ; False ; False ; False } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 44 (just consumed gas: 0.010) + [ { True ; True ; False ; False ; False } + { { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 45 (just consumed gas: 0.010) + [ { { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 46 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 48 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 49 (just consumed gas: 0.050) + [ -9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 51 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 49 (just consumed gas: 0.055) + [ -1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 51 (just consumed gas: 0.010) + [ False + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 49 (just consumed gas: 0.055) + [ 0 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 51 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 49 (just consumed gas: 0.055) + [ 1 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 51 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 49 (just consumed gas: 0.055) + [ 9999999 + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 51 (just consumed gas: 0.010) + [ True + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 49 (just consumed gas: 0.073) + [ { False ; False ; True ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 46 (just consumed gas: 0.035) + [ { { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { False ; False ; True ; True ; True } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 52 (just consumed gas: 0.010) + [ { False ; False ; True ; True ; True } + { { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 53 (just consumed gas: 0.010) + [ { { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 54 (just consumed gas: 0.010) + [ { -9999999 ; -1 ; 0 ; 1 ; 9999999 } ] + - location: 56 (just consumed gas: 0.050) + [ -9999999 ] + - location: 58 (just consumed gas: 0.010) + [ False ] + - location: 56 (just consumed gas: 0.055) + [ -1 ] + - location: 58 (just consumed gas: 0.010) + [ False ] + - location: 56 (just consumed gas: 0.055) + [ 0 ] + - location: 58 (just consumed gas: 0.010) + [ False ] + - location: 56 (just consumed gas: 0.055) + [ 1 ] + - location: 58 (just consumed gas: 0.010) + [ True ] + - location: 56 (just consumed gas: 0.055) + [ 9999999 ] + - location: 58 (just consumed gas: 0.010) + [ True ] + - location: 56 (just consumed gas: 0.073) + [ { False ; False ; False ; True ; True } ] + - location: 54 (just consumed gas: 0.035) + [ { { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } + { False ; False ; False ; True ; True } ] + - location: 59 (just consumed gas: 0.010) + [ { False ; False ; False ; True ; True } + { { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } ] + - location: 60 (just consumed gas: 0.010) + [ { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } ] + - location: 61 (just consumed gas: 0.010) + [ {} + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } } ] + - location: 63 (just consumed gas: 0.010) + [ (Pair {} + { { False ; False ; False ; True ; True } ; + { False ; False ; True ; True ; True } ; + { True ; True ; False ; False ; False } ; + { True ; True ; True ; False ; False } ; + { True ; True ; False ; True ; True } ; + { False ; False ; True ; False ; False } }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input392583650-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input392583650-.out new file mode 100644 index 000000000000..d3d977dfb92d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input392583650-.out @@ -0,0 +1,35 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_hello.tz on storage '{}' and input '{ "test1" ; "test2" }' --level 1 --trace-stack +storage + { "Hello test1" ; "Hello test2" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.631) + [ (Pair { "test1" ; "test2" } {}) ] + - location: 9 (just consumed gas: 0.010) + [ { "test1" ; "test2" } ] + - location: 10 (just consumed gas: 0.050) + [ "test1" ] + - location: 12 (just consumed gas: 0.010) + [ "Hello " + "test1" ] + - location: 15 (just consumed gas: 0.050) + [ "Hello test1" ] + - location: 10 (just consumed gas: 0.055) + [ "test2" ] + - location: 12 (just consumed gas: 0.010) + [ "Hello " + "test2" ] + - location: 15 (just consumed gas: 0.050) + [ "Hello test2" ] + - location: 10 (just consumed gas: 0.068) + [ { "Hello test1" ; "Hello test2" } ] + - location: 16 (just consumed gas: 0.010) + [ {} + { "Hello test1" ; "Hello test2" } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} { "Hello test1" ; "Hello test2" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input457300675-.out new file mode 100644 index 000000000000..71b68e577d8f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input457300675-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_hello.tz on storage '{}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.301) + [ (Pair {} {}) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.060) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input640104625-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input640104625-.out new file mode 100644 index 000000000000..99b43c04be3c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello--storage457300675--input640104625-.out @@ -0,0 +1,28 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_hello.tz on storage '{}' and input '{ "World!" }' --level 1 --trace-stack +storage + { "Hello World!" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.476) + [ (Pair { "World!" } {}) ] + - location: 9 (just consumed gas: 0.010) + [ { "World!" } ] + - location: 10 (just consumed gas: 0.050) + [ "World!" ] + - location: 12 (just consumed gas: 0.010) + [ "Hello " + "World!" ] + - location: 15 (just consumed gas: 0.051) + [ "Hello World!" ] + - location: 10 (just consumed gas: 0.066) + [ { "Hello World!" } ] + - location: 16 (just consumed gas: 0.010) + [ {} + { "Hello World!" } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} { "Hello World!" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input354091714-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input354091714-.out new file mode 100644 index 000000000000..c87c9c20c792 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input354091714-.out @@ -0,0 +1,35 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_hello_bytes.tz on storage '{}' and input '{ 0xab ; 0xcd }' --level 1 --trace-stack +storage + { 0xffab ; 0xffcd } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.381) + [ (Pair { 0xab ; 0xcd } {}) ] + - location: 9 (just consumed gas: 0.010) + [ { 0xab ; 0xcd } ] + - location: 10 (just consumed gas: 0.050) + [ 0xab ] + - location: 12 (just consumed gas: 0.010) + [ 0xff + 0xab ] + - location: 15 (just consumed gas: 0.046) + [ 0xffab ] + - location: 10 (just consumed gas: 0.055) + [ 0xcd ] + - location: 12 (just consumed gas: 0.010) + [ 0xff + 0xcd ] + - location: 15 (just consumed gas: 0.046) + [ 0xffcd ] + - location: 10 (just consumed gas: 0.068) + [ { 0xffab ; 0xffcd } ] + - location: 16 (just consumed gas: 0.010) + [ {} + { 0xffab ; 0xffcd } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} { 0xffab ; 0xffcd }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input441061063-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input441061063-.out new file mode 100644 index 000000000000..08b4c6f68492 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input441061063-.out @@ -0,0 +1,28 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_hello_bytes.tz on storage '{}' and input '{ 0xcd }' --level 1 --trace-stack +storage + { 0xffcd } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.281) + [ (Pair { 0xcd } {}) ] + - location: 9 (just consumed gas: 0.010) + [ { 0xcd } ] + - location: 10 (just consumed gas: 0.050) + [ 0xcd ] + - location: 12 (just consumed gas: 0.010) + [ 0xff + 0xcd ] + - location: 15 (just consumed gas: 0.046) + [ 0xffcd ] + - location: 10 (just consumed gas: 0.066) + [ { 0xffcd } ] + - location: 16 (just consumed gas: 0.010) + [ {} + { 0xffcd } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} { 0xffcd }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input457300675-.out new file mode 100644 index 000000000000..38c7767a2e41 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_hello_bytes--storage457300675--input457300675-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_hello_bytes.tz on storage '{}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.181) + [ (Pair {} {}) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.060) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input264787654-.out new file mode 100644 index 000000000000..0819c9c390f2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input264787654-.out @@ -0,0 +1,96 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_list.tz on storage '""' and input '{ "a" ; "b" ; "c" }' --level 1 --trace-stack +storage + "abc" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 10.763) + [ (Pair { "a" ; "b" ; "c" } "") ] + - location: 8 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 9 (just consumed gas: 0.010) + [ "" + { "a" ; "b" ; "c" } ] + - location: 12 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } + "" ] + - location: 13 (just consumed gas: 0.030) + [ "a" + "" ] + - location: 15 (just consumed gas: 0.010) + [ "" + "a" ] + - location: 16 (just consumed gas: 0.010) + [ "a" ] + - location: 18 (just consumed gas: 0.010) + [ {} + "a" ] + - location: 20 (just consumed gas: 0.010) + [ "a" + {} ] + - location: 21 (just consumed gas: 0.010) + [ { "a" } ] + - location: 16 (just consumed gas: 0.035) + [ "" + { "a" } ] + - location: 22 (just consumed gas: 0.010) + [ { "" ; "a" } ] + - location: 23 (just consumed gas: 0.120) + [ "a" ] + - location: 13 (just consumed gas: 0.025) + [ "b" + "a" ] + - location: 15 (just consumed gas: 0.010) + [ "a" + "b" ] + - location: 16 (just consumed gas: 0.010) + [ "b" ] + - location: 18 (just consumed gas: 0.010) + [ {} + "b" ] + - location: 20 (just consumed gas: 0.010) + [ "b" + {} ] + - location: 21 (just consumed gas: 0.010) + [ { "b" } ] + - location: 16 (just consumed gas: 0.035) + [ "a" + { "b" } ] + - location: 22 (just consumed gas: 0.010) + [ { "a" ; "b" } ] + - location: 23 (just consumed gas: 0.121) + [ "ab" ] + - location: 13 (just consumed gas: 0.025) + [ "c" + "ab" ] + - location: 15 (just consumed gas: 0.010) + [ "ab" + "c" ] + - location: 16 (just consumed gas: 0.010) + [ "c" ] + - location: 18 (just consumed gas: 0.010) + [ {} + "c" ] + - location: 20 (just consumed gas: 0.010) + [ "c" + {} ] + - location: 21 (just consumed gas: 0.010) + [ { "c" } ] + - location: 16 (just consumed gas: 0.035) + [ "ab" + { "c" } ] + - location: 22 (just consumed gas: 0.010) + [ { "ab" ; "c" } ] + - location: 23 (just consumed gas: 0.121) + [ "abc" ] + - location: 13 (just consumed gas: 0.035) + [ "abc" ] + - location: 24 (just consumed gas: 0.010) + [ {} + "abc" ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} "abc") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input316676251-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input316676251-.out new file mode 100644 index 000000000000..5a6c87498dad --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input316676251-.out @@ -0,0 +1,119 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_list.tz on storage '""' and input '{ "Hello" ; " " ; "World" ; "!" }' --level 1 --trace-stack +storage + "Hello World!" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 10.968) + [ (Pair { "Hello" ; " " ; "World" ; "!" } "") ] + - location: 8 (just consumed gas: 0.010) + [ { "Hello" ; " " ; "World" ; "!" } ] + - location: 9 (just consumed gas: 0.010) + [ "" + { "Hello" ; " " ; "World" ; "!" } ] + - location: 12 (just consumed gas: 0.010) + [ { "Hello" ; " " ; "World" ; "!" } + "" ] + - location: 13 (just consumed gas: 0.030) + [ "Hello" + "" ] + - location: 15 (just consumed gas: 0.010) + [ "" + "Hello" ] + - location: 16 (just consumed gas: 0.010) + [ "Hello" ] + - location: 18 (just consumed gas: 0.010) + [ {} + "Hello" ] + - location: 20 (just consumed gas: 0.010) + [ "Hello" + {} ] + - location: 21 (just consumed gas: 0.010) + [ { "Hello" } ] + - location: 16 (just consumed gas: 0.035) + [ "" + { "Hello" } ] + - location: 22 (just consumed gas: 0.010) + [ { "" ; "Hello" } ] + - location: 23 (just consumed gas: 0.122) + [ "Hello" ] + - location: 13 (just consumed gas: 0.025) + [ " " + "Hello" ] + - location: 15 (just consumed gas: 0.010) + [ "Hello" + " " ] + - location: 16 (just consumed gas: 0.010) + [ " " ] + - location: 18 (just consumed gas: 0.010) + [ {} + " " ] + - location: 20 (just consumed gas: 0.010) + [ " " + {} ] + - location: 21 (just consumed gas: 0.010) + [ { " " } ] + - location: 16 (just consumed gas: 0.035) + [ "Hello" + { " " } ] + - location: 22 (just consumed gas: 0.010) + [ { "Hello" ; " " } ] + - location: 23 (just consumed gas: 0.123) + [ "Hello " ] + - location: 13 (just consumed gas: 0.025) + [ "World" + "Hello " ] + - location: 15 (just consumed gas: 0.010) + [ "Hello " + "World" ] + - location: 16 (just consumed gas: 0.010) + [ "World" ] + - location: 18 (just consumed gas: 0.010) + [ {} + "World" ] + - location: 20 (just consumed gas: 0.010) + [ "World" + {} ] + - location: 21 (just consumed gas: 0.010) + [ { "World" } ] + - location: 16 (just consumed gas: 0.035) + [ "Hello " + { "World" } ] + - location: 22 (just consumed gas: 0.010) + [ { "Hello " ; "World" } ] + - location: 23 (just consumed gas: 0.125) + [ "Hello World" ] + - location: 13 (just consumed gas: 0.025) + [ "!" + "Hello World" ] + - location: 15 (just consumed gas: 0.010) + [ "Hello World" + "!" ] + - location: 16 (just consumed gas: 0.010) + [ "!" ] + - location: 18 (just consumed gas: 0.010) + [ {} + "!" ] + - location: 20 (just consumed gas: 0.010) + [ "!" + {} ] + - location: 21 (just consumed gas: 0.010) + [ { "!" } ] + - location: 16 (just consumed gas: 0.035) + [ "Hello World" + { "!" } ] + - location: 22 (just consumed gas: 0.010) + [ { "Hello World" ; "!" } ] + - location: 23 (just consumed gas: 0.126) + [ "Hello World!" ] + - location: 13 (just consumed gas: 0.035) + [ "Hello World!" ] + - location: 24 (just consumed gas: 0.010) + [ {} + "Hello World!" ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} "Hello World!") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input457300675-.out new file mode 100644 index 000000000000..b74aaa9db73a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -concat_list--storage79230375--input457300675-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/concat_list.tz on storage '""' and input '{}' --level 1 --trace-stack +storage + "" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 10.388) + [ (Pair {} "") ] + - location: 8 (just consumed gas: 0.010) + [ {} ] + - location: 9 (just consumed gas: 0.010) + [ "" + {} ] + - location: 12 (just consumed gas: 0.010) + [ {} + "" ] + - location: 13 (just consumed gas: 0.040) + [ "" ] + - location: 24 (just consumed gas: 0.010) + [ {} + "" ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} "") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage457300675--input798141440-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage457300675--input798141440-.out new file mode 100644 index 000000000000..0c29f34606e6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage457300675--input798141440-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/cons.tz on storage '{}' and input 10 --level 1 --trace-stack +storage + { 10 } +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.410) + [ (Pair 10 {}) ] + - location: 8 (just consumed gas: 0.010) + [ 10 + {} ] + - location: 9 (just consumed gas: 0.010) + [ { 10 } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { 10 } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { 10 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage581876226--input166122047-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage581876226--input166122047-.out new file mode 100644 index 000000000000..91e50f9464a0 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage581876226--input166122047-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/cons.tz on storage '{ 10 }' and input -5 --level 1 --trace-stack +storage + { -5 ; 10 } +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.510) + [ (Pair -5 { 10 }) ] + - location: 8 (just consumed gas: 0.010) + [ -5 + { 10 } ] + - location: 9 (just consumed gas: 0.010) + [ { -5 ; 10 } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { -5 ; 10 } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { -5 ; 10 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage793461282--input781487591-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage793461282--input781487591-.out new file mode 100644 index 000000000000..e9f7d806a870 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -cons--storage793461282--input781487591-.out @@ -0,0 +1,22 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/cons.tz on storage '{ -5 ; 10 }' and input 99 --level 1 --trace-stack +storage + { 99 ; -5 ; 10 } +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.610) + [ (Pair 99 { -5 ; 10 }) ] + - location: 8 (just consumed gas: 0.010) + [ 99 + { -5 ; 10 } ] + - location: 9 (just consumed gas: 0.010) + [ { 99 ; -5 ; 10 } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { 99 ; -5 ; 10 } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { 99 ; -5 ; 10 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input315650912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input315650912-.out new file mode 100644 index 000000000000..722c709ef5f6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input315650912-.out @@ -0,0 +1,166 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contains_all.tz on storage None and input '(Pair { "B" } { "B" })' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 31.962) + [ (Pair (Pair { "B" } { "B" }) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { "B" } { "B" }) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { "B" } { "B" }) + (Pair { "B" } { "B" }) ] + - location: 14 (just consumed gas: 0.010) + [ { "B" } + (Pair { "B" } { "B" }) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair { "B" } { "B" }) ] + - location: 17 (just consumed gas: 0.010) + [ { "B" } ] + - location: 15 (just consumed gas: 0.035) + [ { "B" } + { "B" } ] + - location: 18 (just consumed gas: 0.300) + [ {} + { "B" } + { "B" } ] + - location: 20 (just consumed gas: 0.010) + [ { "B" } + {} + { "B" } ] + - location: 21 (just consumed gas: 0.030) + [ "B" + {} + { "B" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "B" {}) + { "B" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "B" {}) + (Pair "B" {}) + { "B" } ] + - location: 25 (just consumed gas: 0.010) + [ "B" + (Pair "B" {}) + { "B" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "B" {}) + { "B" } ] + - location: 28 (just consumed gas: 0.010) + [ {} + { "B" } ] + - location: 26 (just consumed gas: 0.035) + [ "B" + {} + { "B" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "B" + {} + { "B" } ] + - location: 32 (just consumed gas: 0.010) + [ "B" + True + {} + { "B" } ] + - location: 33 (just consumed gas: 0.050) + [ { "B" } + { "B" } ] + - location: 21 (just consumed gas: 0.035) + [ { "B" } + { "B" } ] + - location: 34 (just consumed gas: 0.010) + [ True + { "B" } + { "B" } ] + - location: 37 (just consumed gas: 0.010) + [ { "B" } + True + { "B" } ] + - location: 38 (just consumed gas: 0.010) + [ (Pair { "B" } True) + { "B" } ] + - location: 39 (just consumed gas: 0.010) + [ { "B" } + (Pair { "B" } True) ] + - location: 40 (just consumed gas: 0.030) + [ "B" + (Pair { "B" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "B" { "B" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "B" { "B" } True) + (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "B" { "B" } True) + (Pair "B" { "B" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" } True) + (Pair "B" { "B" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" } + (Pair "B" { "B" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "B" { "B" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" } + { "B" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "B" + { "B" } + { "B" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" } True) ] + - location: 40 (just consumed gas: 0.035) + [ (Pair { "B" } True) ] + - location: 64 (just consumed gas: 0.010) + [ True ] + - location: 65 (just consumed gas: 0.010) + [ (Some True) ] + - location: 66 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 68 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input51111414-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input51111414-.out new file mode 100644 index 000000000000..dd845edf0fd4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input51111414-.out @@ -0,0 +1,410 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contains_all.tz on storage None and input '(Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" })' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 32.647) + [ (Pair (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) + (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) ] + - location: 14 (just consumed gas: 0.010) + [ { "B" ; "B" ; "asdf" ; "C" } + (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair { "B" ; "B" ; "asdf" ; "C" } { "B" ; "C" ; "asdf" }) ] + - location: 17 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } ] + - location: 15 (just consumed gas: 0.035) + [ { "B" ; "B" ; "asdf" ; "C" } + { "B" ; "C" ; "asdf" } ] + - location: 18 (just consumed gas: 0.300) + [ {} + { "B" ; "B" ; "asdf" ; "C" } + { "B" ; "C" ; "asdf" } ] + - location: 20 (just consumed gas: 0.010) + [ { "B" ; "B" ; "asdf" ; "C" } + {} + { "B" ; "C" ; "asdf" } ] + - location: 21 (just consumed gas: 0.030) + [ "B" + {} + { "B" ; "C" ; "asdf" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "B" {}) + (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 25 (just consumed gas: 0.010) + [ "B" + (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "B" {}) + { "B" ; "C" ; "asdf" } ] + - location: 28 (just consumed gas: 0.010) + [ {} + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.035) + [ "B" + {} + { "B" ; "C" ; "asdf" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "B" + {} + { "B" ; "C" ; "asdf" } ] + - location: 32 (just consumed gas: 0.010) + [ "B" + True + {} + { "B" ; "C" ; "asdf" } ] + - location: 33 (just consumed gas: 0.050) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 21 (just consumed gas: 0.025) + [ "B" + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "B" { "B" }) + (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 25 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "B" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 28 (just consumed gas: 0.010) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.035) + [ "B" + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "B" + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 32 (just consumed gas: 0.010) + [ "B" + True + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 33 (just consumed gas: 0.050) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 21 (just consumed gas: 0.025) + [ "asdf" + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" }) + (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 25 (just consumed gas: 0.010) + [ "asdf" + (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" }) + { "B" ; "C" ; "asdf" } ] + - location: 28 (just consumed gas: 0.010) + [ { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.035) + [ "asdf" + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "asdf" + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 32 (just consumed gas: 0.010) + [ "asdf" + True + { "B" } + { "B" ; "C" ; "asdf" } ] + - location: 33 (just consumed gas: 0.051) + [ { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 21 (just consumed gas: 0.025) + [ "C" + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "asdf" }) + (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 25 (just consumed gas: 0.010) + [ "C" + (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "asdf" }) + { "B" ; "C" ; "asdf" } ] + - location: 28 (just consumed gas: 0.010) + [ { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 26 (just consumed gas: 0.035) + [ "C" + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "C" + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 32 (just consumed gas: 0.010) + [ "C" + True + { "B" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 33 (just consumed gas: 0.050) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 21 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 34 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } ] + - location: 37 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True + { "B" ; "C" ; "asdf" } ] + - location: 38 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + { "B" ; "C" ; "asdf" } ] + - location: 39 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.030) + [ "B" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "B" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.025) + [ "C" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "C" + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "C" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.025) + [ "asdf" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "asdf" + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "asdf" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.035) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 64 (just consumed gas: 0.010) + [ True ] + - location: 65 (just consumed gas: 0.010) + [ (Some True) ] + - location: 66 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 68 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input545734274-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input545734274-.out new file mode 100644 index 000000000000..d5d3298eac9c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input545734274-.out @@ -0,0 +1,166 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contains_all.tz on storage None and input '(Pair { "A" } { "B" })' --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 31.962) + [ (Pair (Pair { "A" } { "B" }) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { "A" } { "B" }) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { "A" } { "B" }) + (Pair { "A" } { "B" }) ] + - location: 14 (just consumed gas: 0.010) + [ { "A" } + (Pair { "A" } { "B" }) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair { "A" } { "B" }) ] + - location: 17 (just consumed gas: 0.010) + [ { "B" } ] + - location: 15 (just consumed gas: 0.035) + [ { "A" } + { "B" } ] + - location: 18 (just consumed gas: 0.300) + [ {} + { "A" } + { "B" } ] + - location: 20 (just consumed gas: 0.010) + [ { "A" } + {} + { "B" } ] + - location: 21 (just consumed gas: 0.030) + [ "A" + {} + { "B" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "A" {}) + { "B" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "A" {}) + (Pair "A" {}) + { "B" } ] + - location: 25 (just consumed gas: 0.010) + [ "A" + (Pair "A" {}) + { "B" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "A" {}) + { "B" } ] + - location: 28 (just consumed gas: 0.010) + [ {} + { "B" } ] + - location: 26 (just consumed gas: 0.035) + [ "A" + {} + { "B" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "A" + {} + { "B" } ] + - location: 32 (just consumed gas: 0.010) + [ "A" + True + {} + { "B" } ] + - location: 33 (just consumed gas: 0.050) + [ { "A" } + { "B" } ] + - location: 21 (just consumed gas: 0.035) + [ { "A" } + { "B" } ] + - location: 34 (just consumed gas: 0.010) + [ True + { "A" } + { "B" } ] + - location: 37 (just consumed gas: 0.010) + [ { "A" } + True + { "B" } ] + - location: 38 (just consumed gas: 0.010) + [ (Pair { "A" } True) + { "B" } ] + - location: 39 (just consumed gas: 0.010) + [ { "B" } + (Pair { "A" } True) ] + - location: 40 (just consumed gas: 0.030) + [ "B" + (Pair { "A" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "B" { "A" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "B" { "A" } True) + (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "B" { "A" } True) + (Pair "B" { "A" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "A" } True) + (Pair "B" { "A" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "A" } + (Pair "B" { "A" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "B" { "A" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "A" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "A" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "A" } + { "A" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "B" + { "A" } + { "A" } + True ] + - location: 57 (just consumed gas: 0.040) + [ False + { "A" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "A" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "A" } ] + - location: 58 (just consumed gas: 0.035) + [ False + True + { "A" } ] + - location: 61 (just consumed gas: 0.010) + [ False + { "A" } ] + - location: 62 (just consumed gas: 0.010) + [ { "A" } + False ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "A" } False) ] + - location: 40 (just consumed gas: 0.035) + [ (Pair { "A" } False) ] + - location: 64 (just consumed gas: 0.010) + [ False ] + - location: 65 (just consumed gas: 0.010) + [ (Some False) ] + - location: 66 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 68 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input772794967-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input772794967-.out new file mode 100644 index 000000000000..fd4c8c193965 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input772794967-.out @@ -0,0 +1,63 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contains_all.tz on storage None and input '(Pair {} {})' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 31.712) + [ (Pair (Pair {} {}) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} {}) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} {}) + (Pair {} {}) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Pair {} {}) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair {} {}) ] + - location: 17 (just consumed gas: 0.010) + [ {} ] + - location: 15 (just consumed gas: 0.035) + [ {} + {} ] + - location: 18 (just consumed gas: 0.300) + [ {} + {} + {} ] + - location: 20 (just consumed gas: 0.010) + [ {} + {} + {} ] + - location: 21 (just consumed gas: 0.040) + [ {} + {} ] + - location: 34 (just consumed gas: 0.010) + [ True + {} + {} ] + - location: 37 (just consumed gas: 0.010) + [ {} + True + {} ] + - location: 38 (just consumed gas: 0.010) + [ (Pair {} True) + {} ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Pair {} True) ] + - location: 40 (just consumed gas: 0.040) + [ (Pair {} True) ] + - location: 64 (just consumed gas: 0.010) + [ True ] + - location: 65 (just consumed gas: 0.010) + [ (Some True) ] + - location: 66 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 68 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input917967660-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input917967660-.out new file mode 100644 index 000000000000..08a7de1e1c58 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input917967660-.out @@ -0,0 +1,437 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contains_all.tz on storage None and input '(Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" })' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 32.647) + [ (Pair (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) + (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) ] + - location: 14 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } { "B" ; "B" ; "asdf" ; "C" }) ] + - location: 17 (just consumed gas: 0.010) + [ { "B" ; "B" ; "asdf" ; "C" } ] + - location: 15 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 18 (just consumed gas: 0.300) + [ {} + { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 20 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 21 (just consumed gas: 0.030) + [ "B" + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "B" {}) + (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 25 (just consumed gas: 0.010) + [ "B" + (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "B" {}) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 28 (just consumed gas: 0.010) + [ {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (just consumed gas: 0.035) + [ "B" + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "B" + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 32 (just consumed gas: 0.010) + [ "B" + True + {} + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 33 (just consumed gas: 0.050) + [ { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 21 (just consumed gas: 0.025) + [ "C" + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "C" { "B" }) + (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 25 (just consumed gas: 0.010) + [ "C" + (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "C" { "B" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 28 (just consumed gas: 0.010) + [ { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (just consumed gas: 0.035) + [ "C" + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "C" + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 32 (just consumed gas: 0.010) + [ "C" + True + { "B" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 33 (just consumed gas: 0.050) + [ { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 21 (just consumed gas: 0.025) + [ "asdf" + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" }) + (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 25 (just consumed gas: 0.010) + [ "asdf" + (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" }) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 28 (just consumed gas: 0.010) + [ { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 26 (just consumed gas: 0.035) + [ "asdf" + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "asdf" + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 32 (just consumed gas: 0.010) + [ "asdf" + True + { "B" ; "C" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 33 (just consumed gas: 0.051) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 21 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 34 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 37 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 38 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + { "B" ; "B" ; "asdf" ; "C" } ] + - location: 39 (just consumed gas: 0.010) + [ { "B" ; "B" ; "asdf" ; "C" } + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.030) + [ "B" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "B" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.025) + [ "B" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "B" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "B" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.025) + [ "asdf" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "asdf" + (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "asdf" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "asdf" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.025) + [ "C" + (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "C" + (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "C" { "B" ; "C" ; "asdf" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "C" + { "B" ; "C" ; "asdf" } + { "B" ; "C" ; "asdf" } + True ] + - location: 57 (just consumed gas: 0.040) + [ True + { "B" ; "C" ; "asdf" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 58 (just consumed gas: 0.035) + [ True + True + { "B" ; "C" ; "asdf" } ] + - location: 61 (just consumed gas: 0.010) + [ True + { "B" ; "C" ; "asdf" } ] + - location: 62 (just consumed gas: 0.010) + [ { "B" ; "C" ; "asdf" } + True ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 40 (just consumed gas: 0.035) + [ (Pair { "B" ; "C" ; "asdf" } True) ] + - location: 64 (just consumed gas: 0.010) + [ True ] + - location: 65 (just consumed gas: 0.010) + [ (Some True) ] + - location: 66 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 68 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input964818218-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input964818218-.out new file mode 100644 index 000000000000..dc267459176a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contains_all--storage921624073--input964818218-.out @@ -0,0 +1,166 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contains_all.tz on storage None and input '(Pair { "c" } { "B" })' --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 31.962) + [ (Pair (Pair { "c" } { "B" }) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { "c" } { "B" }) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { "c" } { "B" }) + (Pair { "c" } { "B" }) ] + - location: 14 (just consumed gas: 0.010) + [ { "c" } + (Pair { "c" } { "B" }) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair { "c" } { "B" }) ] + - location: 17 (just consumed gas: 0.010) + [ { "B" } ] + - location: 15 (just consumed gas: 0.035) + [ { "c" } + { "B" } ] + - location: 18 (just consumed gas: 0.300) + [ {} + { "c" } + { "B" } ] + - location: 20 (just consumed gas: 0.010) + [ { "c" } + {} + { "B" } ] + - location: 21 (just consumed gas: 0.030) + [ "c" + {} + { "B" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair "c" {}) + { "B" } ] + - location: 24 (just consumed gas: 0.010) + [ (Pair "c" {}) + (Pair "c" {}) + { "B" } ] + - location: 25 (just consumed gas: 0.010) + [ "c" + (Pair "c" {}) + { "B" } ] + - location: 26 (just consumed gas: 0.010) + [ (Pair "c" {}) + { "B" } ] + - location: 28 (just consumed gas: 0.010) + [ {} + { "B" } ] + - location: 26 (just consumed gas: 0.035) + [ "c" + {} + { "B" } ] + - location: 29 (just consumed gas: 0.010) + [ True + "c" + {} + { "B" } ] + - location: 32 (just consumed gas: 0.010) + [ "c" + True + {} + { "B" } ] + - location: 33 (just consumed gas: 0.050) + [ { "c" } + { "B" } ] + - location: 21 (just consumed gas: 0.035) + [ { "c" } + { "B" } ] + - location: 34 (just consumed gas: 0.010) + [ True + { "c" } + { "B" } ] + - location: 37 (just consumed gas: 0.010) + [ { "c" } + True + { "B" } ] + - location: 38 (just consumed gas: 0.010) + [ (Pair { "c" } True) + { "B" } ] + - location: 39 (just consumed gas: 0.010) + [ { "B" } + (Pair { "c" } True) ] + - location: 40 (just consumed gas: 0.030) + [ "B" + (Pair { "c" } True) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair "B" { "c" } True) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 44 (just consumed gas: 0.010) + [ (Pair "B" { "c" } True) + (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 45 (just consumed gas: 0.010) + [ "B" + (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 46 (just consumed gas: 0.010) + [ (Pair "B" { "c" } True) + (Pair "B" { "c" } True) ] + - location: 49 (just consumed gas: 0.010) + [ (Pair { "c" } True) + (Pair "B" { "c" } True) ] + - location: 50 (just consumed gas: 0.010) + [ { "c" } + (Pair "B" { "c" } True) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair "B" { "c" } True) ] + - location: 54 (just consumed gas: 0.010) + [ (Pair { "c" } True) ] + - location: 55 (just consumed gas: 0.010) + [ True ] + - location: 51 (just consumed gas: 0.035) + [ { "c" } + True ] + - location: 56 (just consumed gas: 0.010) + [ { "c" } + { "c" } + True ] + - location: 46 (just consumed gas: 0.035) + [ "B" + { "c" } + { "c" } + True ] + - location: 57 (just consumed gas: 0.040) + [ False + { "c" } + True ] + - location: 58 (just consumed gas: 0.010) + [ { "c" } + True ] + - location: 60 (just consumed gas: 0.010) + [ True + { "c" } ] + - location: 58 (just consumed gas: 0.035) + [ False + True + { "c" } ] + - location: 61 (just consumed gas: 0.010) + [ False + { "c" } ] + - location: 62 (just consumed gas: 0.010) + [ { "c" } + False ] + - location: 63 (just consumed gas: 0.010) + [ (Pair { "c" } False) ] + - location: 40 (just consumed gas: 0.035) + [ (Pair { "c" } False) ] + - location: 64 (just consumed gas: 0.010) + [ False ] + - location: 65 (just consumed gas: 0.010) + [ (Some False) ] + - location: 66 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 68 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contract--storage125992234--input117475800-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contract--storage125992234--input117475800-.out new file mode 100644 index 000000000000..1cf5d6022d0d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -contract--storage125992234--input117475800-.out @@ -0,0 +1,29 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/contract.tz on storage Unit and input '"tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 11.830) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" Unit) ] + - location: 7 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 8 (just consumed gas: 0.307) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 11 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 11 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 17 (just consumed gas: 0.010) + [ ] + - location: 18 (just consumed gas: 0.010) + [ Unit ] + - location: 19 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -create_contract--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -create_contract--storage921624073--input125992234-.out new file mode 100644 index 000000000000..0e0ae526624b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -create_contract--storage921624073--input125992234-.out @@ -0,0 +1,49 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/create_contract.tz on storage None and input Unit --level 1 --trace-stack +storage + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") +emitted operations + Internal Origination: + From: KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi + Credit: ꜩ0.05 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract +big_map diff + +trace + - location: 8 (just consumed gas: 11.525) + [ (Pair Unit None) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.010) + [ Unit ] + - location: 10 (just consumed gas: 0.010) + [ 50000 + Unit ] + - location: 11 (just consumed gas: 0.010) + [ None + 50000 + Unit ] + - location: 13 (just consumed gas: 0.716) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b + "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm" ] + - location: 25 (just consumed gas: 0.010) + [ "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm" ] + - location: 27 (just consumed gas: 0.010) + [ (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 28 (just consumed gas: 0.010) + [ {} + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 25 (just consumed gas: 0.035) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b + {} + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 30 (just consumed gas: 0.010) + [ { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b } + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm") ] + - location: 31 (just consumed gas: 0.010) + [ (Pair { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000002d08603000000001c02000000170500036c0501036c050202000000080317053d036d034200000002030b } + (Some "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1011138251-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1011138251-.out new file mode 100644 index 000000000000..4045f7bb8fab --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1011138251-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/diff_timestamps.tz on storage 111 and input '(Pair 0 0)' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.334) + [ (Pair (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") 111) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:00Z") ] + - location: 14 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" + "1970-01-01T00:00:00Z" ] + - location: 15 (just consumed gas: 0.035) + [ 0 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1018564342-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1018564342-.out new file mode 100644 index 000000000000..d3890c449a98 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1018564342-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/diff_timestamps.tz on storage 111 and input '(Pair 0 1)' --level 1 --trace-stack +storage + -1 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.334) + [ (Pair (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") 111) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" + (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:00Z" "1970-01-01T00:00:01Z") ] + - location: 14 (just consumed gas: 0.010) + [ "1970-01-01T00:00:01Z" ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" + "1970-01-01T00:00:01Z" ] + - location: 15 (just consumed gas: 0.035) + [ -1 ] + - location: 16 (just consumed gas: 0.010) + [ {} + -1 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} -1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1031049988-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1031049988-.out new file mode 100644 index 000000000000..da6ecbc35411 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input1031049988-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/diff_timestamps.tz on storage 111 and input '(Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z")' --level 1 --trace-stack +storage + 200 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.550) + [ (Pair (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") 111) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") + (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:03:20Z" + (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:03:20Z" "1970-01-01T00:00:00Z") ] + - location: 14 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:03:20Z" + "1970-01-01T00:00:00Z" ] + - location: 15 (just consumed gas: 0.035) + [ 200 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 200 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 200) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input685590443-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input685590443-.out new file mode 100644 index 000000000000..95d300f17eac --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -diff_timestamps--storage492856247--input685590443-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/diff_timestamps.tz on storage 111 and input '(Pair 1 0)' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.334) + [ (Pair (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") 111) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") + (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:00:01Z" + (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:00:01Z" "1970-01-01T00:00:00Z") ] + - location: 14 (just consumed gas: 0.010) + [ "1970-01-01T00:00:00Z" ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:00:01Z" + "1970-01-01T00:00:00Z" ] + - location: 15 (just consumed gas: 0.035) + [ 1 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input246866101-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input246866101-.out new file mode 100644 index 000000000000..3d07f1312561 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input246866101-.out @@ -0,0 +1,1240 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dig_eq.tz on storage Unit and input '(Pair 17 (Pair 16 (Pair 15 (Pair 14 (Pair 13 (Pair 12 (Pair 11 (Pair 10 (Pair 9 (Pair 8 (Pair 7 (Pair 6 (Pair 5 (Pair 4 (Pair 3 (Pair 2 1))))))))))))))))' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 24 (just consumed gas: 158.486) + [ (Pair (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) Unit) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 27 (just consumed gas: 0.010) + [ 17 + (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 28 (just consumed gas: 0.010) + [ (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 30 (just consumed gas: 0.010) + [ 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 28 (just consumed gas: 0.035) + [ 17 + 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 31 (just consumed gas: 0.023) + [ (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 34 (just consumed gas: 0.010) + [ 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 31 (just consumed gas: 0.045) + [ 17 + 16 + 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 35 (just consumed gas: 0.027) + [ (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 38 (just consumed gas: 0.010) + [ 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 35 (just consumed gas: 0.055) + [ 17 + 16 + 15 + 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 39 (just consumed gas: 0.031) + [ (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 42 (just consumed gas: 0.010) + [ 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 39 (just consumed gas: 0.065) + [ 17 + 16 + 15 + 14 + 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 43 (just consumed gas: 0.035) + [ (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 46 (just consumed gas: 0.010) + [ 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 43 (just consumed gas: 0.075) + [ 17 + 16 + 15 + 14 + 13 + 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 47 (just consumed gas: 0.039) + [ (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 50 (just consumed gas: 0.010) + [ 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 47 (just consumed gas: 0.085) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 51 (just consumed gas: 0.043) + [ (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 54 (just consumed gas: 0.010) + [ 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 51 (just consumed gas: 0.095) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 55 (just consumed gas: 0.047) + [ (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 58 (just consumed gas: 0.010) + [ 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 55 (just consumed gas: 0.105) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 59 (just consumed gas: 0.051) + [ (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 62 (just consumed gas: 0.010) + [ 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 59 (just consumed gas: 0.115) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 63 (just consumed gas: 0.055) + [ (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 66 (just consumed gas: 0.010) + [ 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 63 (just consumed gas: 0.125) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 67 (just consumed gas: 0.059) + [ (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 70 (just consumed gas: 0.010) + [ 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 67 (just consumed gas: 0.135) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 71 (just consumed gas: 0.063) + [ (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 74 (just consumed gas: 0.010) + [ 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 71 (just consumed gas: 0.145) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 75 (just consumed gas: 0.067) + [ (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 78 (just consumed gas: 0.010) + [ 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 75 (just consumed gas: 0.155) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 79 (just consumed gas: 0.071) + [ (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 82 (just consumed gas: 0.010) + [ 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 79 (just consumed gas: 0.165) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 83 (just consumed gas: 0.075) + [ (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 86 (just consumed gas: 0.010) + [ 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 83 (just consumed gas: 0.175) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 87 (just consumed gas: 0.030) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 89 (just consumed gas: 0.036) + [ 16 + 17 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 91 (just consumed gas: 0.043) + [ 15 + 16 + 17 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 93 (just consumed gas: 0.049) + [ 14 + 15 + 16 + 17 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 95 (just consumed gas: 0.057) + [ 13 + 14 + 15 + 16 + 17 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 97 (just consumed gas: 0.063) + [ 12 + 13 + 14 + 15 + 16 + 17 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 99 (just consumed gas: 0.070) + [ 11 + 12 + 13 + 14 + 15 + 16 + 17 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 101 (just consumed gas: 0.076) + [ 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 103 (just consumed gas: 0.084) + [ 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 105 (just consumed gas: 0.090) + [ 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 107 (just consumed gas: 0.097) + [ 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 109 (just consumed gas: 0.103) + [ 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 111 (just consumed gas: 0.111) + [ 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 113 (just consumed gas: 0.117) + [ 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 115 (just consumed gas: 0.124) + [ 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 117 (just consumed gas: 0.130) + [ 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 119 (just consumed gas: 0.138) + [ 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 121 (just consumed gas: 0.030) + [ 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 123 (just consumed gas: 0.036) + [ 2 + 1 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 125 (just consumed gas: 0.043) + [ 3 + 2 + 1 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 127 (just consumed gas: 0.049) + [ 4 + 3 + 2 + 1 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 129 (just consumed gas: 0.057) + [ 5 + 4 + 3 + 2 + 1 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 131 (just consumed gas: 0.063) + [ 6 + 5 + 4 + 3 + 2 + 1 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 133 (just consumed gas: 0.070) + [ 7 + 6 + 5 + 4 + 3 + 2 + 1 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 135 (just consumed gas: 0.076) + [ 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 137 (just consumed gas: 0.084) + [ 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 139 (just consumed gas: 0.090) + [ 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 141 (just consumed gas: 0.097) + [ 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 12 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 143 (just consumed gas: 0.103) + [ 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 13 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 145 (just consumed gas: 0.111) + [ 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 14 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 147 (just consumed gas: 0.117) + [ 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 15 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 149 (just consumed gas: 0.124) + [ 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 16 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 151 (just consumed gas: 0.130) + [ 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 17 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 153 (just consumed gas: 0.138) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 156 (just consumed gas: 0.075) + [ 2 + 1 + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 159 (just consumed gas: 0.010) + [ (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 156 (just consumed gas: 0.175) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 160 (just consumed gas: 0.071) + [ 3 + (Pair 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 163 (just consumed gas: 0.010) + [ (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 160 (just consumed gas: 0.165) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 164 (just consumed gas: 0.067) + [ 4 + (Pair 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 167 (just consumed gas: 0.010) + [ (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 164 (just consumed gas: 0.155) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 168 (just consumed gas: 0.063) + [ 5 + (Pair 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 171 (just consumed gas: 0.010) + [ (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 168 (just consumed gas: 0.145) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 172 (just consumed gas: 0.059) + [ 6 + (Pair 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 175 (just consumed gas: 0.010) + [ (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 172 (just consumed gas: 0.135) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 176 (just consumed gas: 0.055) + [ 7 + (Pair 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 179 (just consumed gas: 0.010) + [ (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 176 (just consumed gas: 0.125) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 180 (just consumed gas: 0.051) + [ 8 + (Pair 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 183 (just consumed gas: 0.010) + [ (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 180 (just consumed gas: 0.115) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 184 (just consumed gas: 0.047) + [ 9 + (Pair 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 187 (just consumed gas: 0.010) + [ (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 184 (just consumed gas: 0.105) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 188 (just consumed gas: 0.043) + [ 10 + (Pair 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 191 (just consumed gas: 0.010) + [ (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 188 (just consumed gas: 0.095) + [ 17 + 16 + 15 + 14 + 13 + 12 + 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 192 (just consumed gas: 0.039) + [ 11 + (Pair 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 195 (just consumed gas: 0.010) + [ (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 192 (just consumed gas: 0.085) + [ 17 + 16 + 15 + 14 + 13 + 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 196 (just consumed gas: 0.035) + [ 12 + (Pair 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 199 (just consumed gas: 0.010) + [ (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 196 (just consumed gas: 0.075) + [ 17 + 16 + 15 + 14 + 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 200 (just consumed gas: 0.031) + [ 13 + (Pair 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 203 (just consumed gas: 0.010) + [ (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 200 (just consumed gas: 0.065) + [ 17 + 16 + 15 + 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 204 (just consumed gas: 0.027) + [ 14 + (Pair 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 207 (just consumed gas: 0.010) + [ (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 204 (just consumed gas: 0.055) + [ 17 + 16 + 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 208 (just consumed gas: 0.023) + [ 15 + (Pair 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 211 (just consumed gas: 0.010) + [ (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 208 (just consumed gas: 0.045) + [ 17 + 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 212 (just consumed gas: 0.010) + [ 16 + (Pair 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 214 (just consumed gas: 0.010) + [ (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 212 (just consumed gas: 0.035) + [ 17 + (Pair 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 215 (just consumed gas: 0.010) + [ (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) + (Pair 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1) ] + - location: 218 (just consumed gas: 0.755) + [ 0 ] + - location: 219 (just consumed gas: 0.010) + [ True ] + - location: 220 (just consumed gas: 0.010) + [ ] + - location: 220 (just consumed gas: 0.025) + [ ] + - location: 226 (just consumed gas: 0.010) + [ Unit ] + - location: 227 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 229 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input26856104-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input26856104-.out new file mode 100644 index 000000000000..af743a4ef447 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dig_eq--storage125992234--input26856104-.out @@ -0,0 +1,1240 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dig_eq.tz on storage Unit and input '(Pair 2 (Pair 3 (Pair 12 (Pair 16 (Pair 10 (Pair 14 (Pair 19 (Pair 9 (Pair 18 (Pair 6 (Pair 8 (Pair 11 (Pair 4 (Pair 13 (Pair 15 (Pair 5 1))))))))))))))))' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 24 (just consumed gas: 158.486) + [ (Pair (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) Unit) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 27 (just consumed gas: 0.010) + [ 2 + (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 28 (just consumed gas: 0.010) + [ (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 30 (just consumed gas: 0.010) + [ 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 28 (just consumed gas: 0.035) + [ 2 + 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 31 (just consumed gas: 0.023) + [ (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 34 (just consumed gas: 0.010) + [ 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 31 (just consumed gas: 0.045) + [ 2 + 3 + 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 35 (just consumed gas: 0.027) + [ (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 38 (just consumed gas: 0.010) + [ 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 35 (just consumed gas: 0.055) + [ 2 + 3 + 12 + 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 39 (just consumed gas: 0.031) + [ (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 42 (just consumed gas: 0.010) + [ 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 39 (just consumed gas: 0.065) + [ 2 + 3 + 12 + 16 + 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 43 (just consumed gas: 0.035) + [ (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 46 (just consumed gas: 0.010) + [ 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 43 (just consumed gas: 0.075) + [ 2 + 3 + 12 + 16 + 10 + 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 47 (just consumed gas: 0.039) + [ (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 50 (just consumed gas: 0.010) + [ 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 47 (just consumed gas: 0.085) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 51 (just consumed gas: 0.043) + [ (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 54 (just consumed gas: 0.010) + [ 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 51 (just consumed gas: 0.095) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 55 (just consumed gas: 0.047) + [ (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 58 (just consumed gas: 0.010) + [ 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 55 (just consumed gas: 0.105) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 59 (just consumed gas: 0.051) + [ (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 62 (just consumed gas: 0.010) + [ 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 59 (just consumed gas: 0.115) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 63 (just consumed gas: 0.055) + [ (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 66 (just consumed gas: 0.010) + [ 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 63 (just consumed gas: 0.125) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 67 (just consumed gas: 0.059) + [ (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 70 (just consumed gas: 0.010) + [ 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 67 (just consumed gas: 0.135) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 71 (just consumed gas: 0.063) + [ (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 74 (just consumed gas: 0.010) + [ 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 71 (just consumed gas: 0.145) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 75 (just consumed gas: 0.067) + [ (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 78 (just consumed gas: 0.010) + [ 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 75 (just consumed gas: 0.155) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 79 (just consumed gas: 0.071) + [ (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 82 (just consumed gas: 0.010) + [ 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 79 (just consumed gas: 0.165) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 83 (just consumed gas: 0.075) + [ (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 86 (just consumed gas: 0.010) + [ 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 83 (just consumed gas: 0.175) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 87 (just consumed gas: 0.030) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 89 (just consumed gas: 0.036) + [ 3 + 2 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 91 (just consumed gas: 0.043) + [ 12 + 3 + 2 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 93 (just consumed gas: 0.049) + [ 16 + 12 + 3 + 2 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 95 (just consumed gas: 0.057) + [ 10 + 16 + 12 + 3 + 2 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 97 (just consumed gas: 0.063) + [ 14 + 10 + 16 + 12 + 3 + 2 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 99 (just consumed gas: 0.070) + [ 19 + 14 + 10 + 16 + 12 + 3 + 2 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 101 (just consumed gas: 0.076) + [ 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 103 (just consumed gas: 0.084) + [ 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 105 (just consumed gas: 0.090) + [ 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 107 (just consumed gas: 0.097) + [ 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 109 (just consumed gas: 0.103) + [ 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 111 (just consumed gas: 0.111) + [ 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 113 (just consumed gas: 0.117) + [ 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 115 (just consumed gas: 0.124) + [ 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 117 (just consumed gas: 0.130) + [ 5 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 119 (just consumed gas: 0.138) + [ 1 + 5 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 121 (just consumed gas: 0.030) + [ 1 + 5 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 123 (just consumed gas: 0.036) + [ 5 + 1 + 15 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 125 (just consumed gas: 0.043) + [ 15 + 5 + 1 + 13 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 127 (just consumed gas: 0.049) + [ 13 + 15 + 5 + 1 + 4 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 129 (just consumed gas: 0.057) + [ 4 + 13 + 15 + 5 + 1 + 11 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 131 (just consumed gas: 0.063) + [ 11 + 4 + 13 + 15 + 5 + 1 + 8 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 133 (just consumed gas: 0.070) + [ 8 + 11 + 4 + 13 + 15 + 5 + 1 + 6 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 135 (just consumed gas: 0.076) + [ 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 18 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 137 (just consumed gas: 0.084) + [ 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 9 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 139 (just consumed gas: 0.090) + [ 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 19 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 141 (just consumed gas: 0.097) + [ 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 14 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 143 (just consumed gas: 0.103) + [ 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 10 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 145 (just consumed gas: 0.111) + [ 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 16 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 147 (just consumed gas: 0.117) + [ 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 12 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 149 (just consumed gas: 0.124) + [ 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 3 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 151 (just consumed gas: 0.130) + [ 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + 2 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 153 (just consumed gas: 0.138) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 156 (just consumed gas: 0.075) + [ 5 + 1 + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 159 (just consumed gas: 0.010) + [ (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 156 (just consumed gas: 0.175) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 160 (just consumed gas: 0.071) + [ 15 + (Pair 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 163 (just consumed gas: 0.010) + [ (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 160 (just consumed gas: 0.165) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 164 (just consumed gas: 0.067) + [ 13 + (Pair 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 167 (just consumed gas: 0.010) + [ (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 164 (just consumed gas: 0.155) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 168 (just consumed gas: 0.063) + [ 4 + (Pair 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 171 (just consumed gas: 0.010) + [ (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 168 (just consumed gas: 0.145) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 172 (just consumed gas: 0.059) + [ 11 + (Pair 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 175 (just consumed gas: 0.010) + [ (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 172 (just consumed gas: 0.135) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 176 (just consumed gas: 0.055) + [ 8 + (Pair 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 179 (just consumed gas: 0.010) + [ (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 176 (just consumed gas: 0.125) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 180 (just consumed gas: 0.051) + [ 6 + (Pair 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 183 (just consumed gas: 0.010) + [ (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 180 (just consumed gas: 0.115) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 184 (just consumed gas: 0.047) + [ 18 + (Pair 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 187 (just consumed gas: 0.010) + [ (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 184 (just consumed gas: 0.105) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 188 (just consumed gas: 0.043) + [ 9 + (Pair 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 191 (just consumed gas: 0.010) + [ (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 188 (just consumed gas: 0.095) + [ 2 + 3 + 12 + 16 + 10 + 14 + 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 192 (just consumed gas: 0.039) + [ 19 + (Pair 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 195 (just consumed gas: 0.010) + [ (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 192 (just consumed gas: 0.085) + [ 2 + 3 + 12 + 16 + 10 + 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 196 (just consumed gas: 0.035) + [ 14 + (Pair 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 199 (just consumed gas: 0.010) + [ (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 196 (just consumed gas: 0.075) + [ 2 + 3 + 12 + 16 + 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 200 (just consumed gas: 0.031) + [ 10 + (Pair 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 203 (just consumed gas: 0.010) + [ (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 200 (just consumed gas: 0.065) + [ 2 + 3 + 12 + 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 204 (just consumed gas: 0.027) + [ 16 + (Pair 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 207 (just consumed gas: 0.010) + [ (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 204 (just consumed gas: 0.055) + [ 2 + 3 + 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 208 (just consumed gas: 0.023) + [ 12 + (Pair 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 211 (just consumed gas: 0.010) + [ (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 208 (just consumed gas: 0.045) + [ 2 + 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 212 (just consumed gas: 0.010) + [ 3 + (Pair 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 214 (just consumed gas: 0.010) + [ (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 212 (just consumed gas: 0.035) + [ 2 + (Pair 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 215 (just consumed gas: 0.010) + [ (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) + (Pair 2 3 12 16 10 14 19 9 18 6 8 11 4 13 15 5 1) ] + - location: 218 (just consumed gas: 0.755) + [ 0 ] + - location: 219 (just consumed gas: 0.010) + [ True ] + - location: 220 (just consumed gas: 0.010) + [ ] + - location: 220 (just consumed gas: 0.025) + [ ] + - location: 226 (just consumed gas: 0.010) + [ Unit ] + - location: 227 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 229 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dign--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dign--storage680650890--input529388602-.out new file mode 100644 index 000000000000..fca2f19c9c4c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dign--storage680650890--input529388602-.out @@ -0,0 +1,61 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dign.tz on storage 0 and input '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)' --level 1 --trace-stack +storage + 5 +emitted operations + +big_map diff + +trace + - location: 15 (just consumed gas: 12.008) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (just consumed gas: 0.057) + [ 5 + 1 + 2 + 3 + 4 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 ] + - location: 24 (just consumed gas: 0.010) + [ 2 + 3 + 4 ] + - location: 25 (just consumed gas: 0.010) + [ 3 + 4 ] + - location: 26 (just consumed gas: 0.010) + [ 4 ] + - location: 27 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.035) + [ 5 ] + - location: 28 (just consumed gas: 0.010) + [ {} + 5 ] + - location: 30 (just consumed gas: 0.010) + [ (Pair {} 5) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input590117173-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input590117173-.out new file mode 100644 index 000000000000..568ba5282937 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input590117173-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dip.tz on storage '(Pair 0 0)' and input '(Pair 1 1)' --level 1 --trace-stack +storage + (Pair 1 2) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 7.735) + [ (Pair (Pair 1 1) 0 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 1 1) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 13 (just consumed gas: 0.010) + [ 1 + 1 + 1 ] + - location: 14 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 16 (just consumed gas: 0.035) + [ 2 ] + - location: 14 (just consumed gas: 0.035) + [ 1 + 2 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 1 2) ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Pair 1 2) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} 1 2) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input850887554-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input850887554-.out new file mode 100644 index 000000000000..983176e90282 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dip--storage1011138251--input850887554-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dip.tz on storage '(Pair 0 0)' and input '(Pair 15 9)' --level 1 --trace-stack +storage + (Pair 15 24) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 7.735) + [ (Pair (Pair 15 9) 0 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 15 9) ] + - location: 12 (just consumed gas: 0.010) + [ 15 + 9 ] + - location: 13 (just consumed gas: 0.010) + [ 15 + 15 + 9 ] + - location: 14 (just consumed gas: 0.010) + [ 15 + 9 ] + - location: 16 (just consumed gas: 0.035) + [ 24 ] + - location: 14 (just consumed gas: 0.035) + [ 15 + 24 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 15 24) ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Pair 15 24) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} 15 24) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dipn--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dipn--storage680650890--input529388602-.out new file mode 100644 index 000000000000..b789cce1c8c1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dipn--storage680650890--input529388602-.out @@ -0,0 +1,68 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dipn.tz on storage 0 and input '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)' --level 1 --trace-stack +storage + 6 +emitted operations + +big_map diff + +trace + - location: 15 (just consumed gas: 13.118) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (just consumed gas: 0.035) + [ ] + - location: 23 (just consumed gas: 0.010) + [ 6 ] + - location: 20 (just consumed gas: 0.075) + [ 1 + 2 + 3 + 4 + 5 + 6 ] + - location: 26 (just consumed gas: 0.010) + [ 2 + 3 + 4 + 5 + 6 ] + - location: 27 (just consumed gas: 0.010) + [ 3 + 4 + 5 + 6 ] + - location: 28 (just consumed gas: 0.010) + [ 4 + 5 + 6 ] + - location: 29 (just consumed gas: 0.010) + [ 5 + 6 ] + - location: 30 (just consumed gas: 0.010) + [ 6 ] + - location: 31 (just consumed gas: 0.010) + [ {} + 6 ] + - location: 33 (just consumed gas: 0.010) + [ (Pair {} 6) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dropn--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dropn--storage680650890--input529388602-.out new file mode 100644 index 000000000000..160916354693 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dropn--storage680650890--input529388602-.out @@ -0,0 +1,39 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dropn.tz on storage 0 and input '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)' --level 1 --trace-stack +storage + 5 +emitted operations + +big_map diff + +trace + - location: 15 (just consumed gas: 8.950) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (just consumed gas: 0.040) + [ 5 ] + - location: 22 (just consumed gas: 0.010) + [ {} + 5 ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} 5) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dugn--storage680650890--input529388602-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dugn--storage680650890--input529388602-.out new file mode 100644 index 000000000000..b2beadb44ee9 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dugn--storage680650890--input529388602-.out @@ -0,0 +1,57 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dugn.tz on storage 0 and input '(Pair (Pair (Pair (Pair 1 2) 3) 4) 5)' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 15 (just consumed gas: 11.184) + [ (Pair (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) 0) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair (Pair (Pair (Pair 1 2) 3) 4) 5) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair (Pair (Pair 1 2) 3) 4) + 5 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair (Pair 1 2) 3) + 4 + 5 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 1 2) + 3 + 4 + 5 ] + - location: 19 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 20 (just consumed gas: 0.062) + [ 2 + 3 + 4 + 5 + 1 ] + - location: 22 (just consumed gas: 0.010) + [ 3 + 4 + 5 + 1 ] + - location: 23 (just consumed gas: 0.010) + [ 4 + 5 + 1 ] + - location: 24 (just consumed gas: 0.010) + [ 5 + 1 ] + - location: 25 (just consumed gas: 0.010) + [ 1 ] + - location: 26 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 28 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dup-n--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dup-n--storage125992234--input125992234-.out new file mode 100644 index 000000000000..c63b7b6b2f67 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -dup-n--storage125992234--input125992234-.out @@ -0,0 +1,248 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/dup-n.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 41.660) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 5 ] + - location: 11 (just consumed gas: 0.010) + [ 4 + 5 ] + - location: 14 (just consumed gas: 0.010) + [ 3 + 4 + 5 ] + - location: 17 (just consumed gas: 0.010) + [ 2 + 3 + 4 + 5 ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 23 (just consumed gas: 0.021) + [ 1 + 1 + 2 + 3 + 4 + 5 ] + - location: 25 (just consumed gas: 0.010) + [ 1 + 1 + 1 + 2 + 3 + 4 + 5 ] + - location: 30 (just consumed gas: 0.035) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 31 (just consumed gas: 0.010) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 32 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 32 (just consumed gas: 0.025) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 38 (just consumed gas: 0.022) + [ 2 + 1 + 2 + 3 + 4 + 5 ] + - location: 40 (just consumed gas: 0.010) + [ 2 + 2 + 1 + 2 + 3 + 4 + 5 ] + - location: 45 (just consumed gas: 0.035) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 46 (just consumed gas: 0.010) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 47 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 47 (just consumed gas: 0.025) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 53 (just consumed gas: 0.023) + [ 3 + 1 + 2 + 3 + 4 + 5 ] + - location: 55 (just consumed gas: 0.010) + [ 3 + 3 + 1 + 2 + 3 + 4 + 5 ] + - location: 60 (just consumed gas: 0.035) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 61 (just consumed gas: 0.010) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 62 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 62 (just consumed gas: 0.025) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 68 (just consumed gas: 0.025) + [ 4 + 1 + 2 + 3 + 4 + 5 ] + - location: 70 (just consumed gas: 0.010) + [ 4 + 4 + 1 + 2 + 3 + 4 + 5 ] + - location: 75 (just consumed gas: 0.035) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 76 (just consumed gas: 0.010) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 77 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 77 (just consumed gas: 0.025) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 83 (just consumed gas: 0.026) + [ 5 + 1 + 2 + 3 + 4 + 5 ] + - location: 85 (just consumed gas: 0.010) + [ 5 + 5 + 1 + 2 + 3 + 4 + 5 ] + - location: 90 (just consumed gas: 0.035) + [ 0 + 1 + 2 + 3 + 4 + 5 ] + - location: 91 (just consumed gas: 0.010) + [ True + 1 + 2 + 3 + 4 + 5 ] + - location: 92 (just consumed gas: 0.010) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 92 (just consumed gas: 0.025) + [ 1 + 2 + 3 + 4 + 5 ] + - location: 98 (just consumed gas: 0.042) + [ ] + - location: 100 (just consumed gas: 0.010) + [ Unit ] + - location: 101 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 103 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input247451205-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input247451205-.out new file mode 100644 index 000000000000..7148be3324be --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input247451205-.out @@ -0,0 +1,135 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv.tz on storage '(Pair None None None None)' and input '(Pair 10 0)' --level 1 --trace-stack +storage + (Pair None None None None) +emitted operations + +big_map diff + +trace + - location: 25 (just consumed gas: 24.814) + [ (Pair (Pair 10 0) None None None None) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair 10 0) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair 10 0) + (Pair 10 0) ] + - location: 27 (just consumed gas: 0.010) + [ 10 + 0 + (Pair 10 0) ] + - location: 28 (just consumed gas: 0.020) + [ 10 + 0 + (Pair 10 0) ] + - location: 29 (just consumed gas: 0.010) + [ 0 + (Pair 10 0) ] + - location: 31 (just consumed gas: 0.020) + [ 0 + (Pair 10 0) ] + - location: 29 (just consumed gas: 0.035) + [ 10 + 0 + (Pair 10 0) ] + - location: 32 (just consumed gas: 0.163) + [ None + (Pair 10 0) ] + - location: 33 (just consumed gas: 0.010) + [ (Pair 10 0) + None ] + - location: 34 (just consumed gas: 0.010) + [ (Pair 10 0) + (Pair 10 0) + None ] + - location: 35 (just consumed gas: 0.010) + [ 10 + 0 + (Pair 10 0) + None ] + - location: 36 (just consumed gas: 0.020) + [ 10 + 0 + (Pair 10 0) + None ] + - location: 37 (just consumed gas: 0.163) + [ None + (Pair 10 0) + None ] + - location: 38 (just consumed gas: 0.010) + [ (Pair 10 0) + None + None ] + - location: 39 (just consumed gas: 0.010) + [ (Pair 10 0) + (Pair 10 0) + None + None ] + - location: 40 (just consumed gas: 0.010) + [ 10 + 0 + (Pair 10 0) + None + None ] + - location: 41 (just consumed gas: 0.010) + [ 0 + (Pair 10 0) + None + None ] + - location: 43 (just consumed gas: 0.020) + [ 0 + (Pair 10 0) + None + None ] + - location: 41 (just consumed gas: 0.035) + [ 10 + 0 + (Pair 10 0) + None + None ] + - location: 44 (just consumed gas: 0.163) + [ None + (Pair 10 0) + None + None ] + - location: 45 (just consumed gas: 0.010) + [ (Pair 10 0) + None + None + None ] + - location: 46 (just consumed gas: 0.010) + [ 10 + 0 + None + None + None ] + - location: 47 (just consumed gas: 0.163) + [ None + None + None + None ] + - location: 49 (just consumed gas: 0.023) + [ None + None ] + - location: 52 (just consumed gas: 0.010) + [ (Pair None None) ] + - location: 49 (just consumed gas: 0.045) + [ None + None + (Pair None None) ] + - location: 53 (just consumed gas: 0.010) + [ None + (Pair None None) ] + - location: 55 (just consumed gas: 0.010) + [ (Pair None None None) ] + - location: 53 (just consumed gas: 0.035) + [ None + (Pair None None None) ] + - location: 56 (just consumed gas: 0.010) + [ (Pair None None None None) ] + - location: 57 (just consumed gas: 0.010) + [ {} + (Pair None None None None) ] + - location: 59 (just consumed gas: 0.010) + [ (Pair {} None None None None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input250545589-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input250545589-.out new file mode 100644 index 000000000000..78d0f753f518 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input250545589-.out @@ -0,0 +1,135 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv.tz on storage '(Pair None None None None)' and input '(Pair -8 2)' --level 1 --trace-stack +storage + (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) +emitted operations + +big_map diff + +trace + - location: 25 (just consumed gas: 24.814) + [ (Pair (Pair -8 2) None None None None) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair -8 2) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair -8 2) + (Pair -8 2) ] + - location: 27 (just consumed gas: 0.010) + [ -8 + 2 + (Pair -8 2) ] + - location: 28 (just consumed gas: 0.020) + [ 8 + 2 + (Pair -8 2) ] + - location: 29 (just consumed gas: 0.010) + [ 2 + (Pair -8 2) ] + - location: 31 (just consumed gas: 0.020) + [ 2 + (Pair -8 2) ] + - location: 29 (just consumed gas: 0.035) + [ 8 + 2 + (Pair -8 2) ] + - location: 32 (just consumed gas: 0.151) + [ (Some (Pair 4 0)) + (Pair -8 2) ] + - location: 33 (just consumed gas: 0.010) + [ (Pair -8 2) + (Some (Pair 4 0)) ] + - location: 34 (just consumed gas: 0.010) + [ (Pair -8 2) + (Pair -8 2) + (Some (Pair 4 0)) ] + - location: 35 (just consumed gas: 0.010) + [ -8 + 2 + (Pair -8 2) + (Some (Pair 4 0)) ] + - location: 36 (just consumed gas: 0.020) + [ 8 + 2 + (Pair -8 2) + (Some (Pair 4 0)) ] + - location: 37 (just consumed gas: 0.151) + [ (Some (Pair 4 0)) + (Pair -8 2) + (Some (Pair 4 0)) ] + - location: 38 (just consumed gas: 0.010) + [ (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 39 (just consumed gas: 0.010) + [ (Pair -8 2) + (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 40 (just consumed gas: 0.010) + [ -8 + 2 + (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 41 (just consumed gas: 0.010) + [ 2 + (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 43 (just consumed gas: 0.020) + [ 2 + (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 41 (just consumed gas: 0.035) + [ -8 + 2 + (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 44 (just consumed gas: 0.151) + [ (Some (Pair -4 0)) + (Pair -8 2) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 45 (just consumed gas: 0.010) + [ (Pair -8 2) + (Some (Pair -4 0)) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 46 (just consumed gas: 0.010) + [ -8 + 2 + (Some (Pair -4 0)) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 47 (just consumed gas: 0.151) + [ (Some (Pair -4 0)) + (Some (Pair -4 0)) + (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 49 (just consumed gas: 0.023) + [ (Some (Pair 4 0)) + (Some (Pair 4 0)) ] + - location: 52 (just consumed gas: 0.010) + [ (Pair (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 49 (just consumed gas: 0.045) + [ (Some (Pair -4 0)) + (Some (Pair -4 0)) + (Pair (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 53 (just consumed gas: 0.010) + [ (Some (Pair -4 0)) + (Pair (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 55 (just consumed gas: 0.010) + [ (Pair (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 53 (just consumed gas: 0.035) + [ (Some (Pair -4 0)) + (Pair (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 56 (just consumed gas: 0.010) + [ (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 57 (just consumed gas: 0.010) + [ {} + (Pair (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + - location: 59 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair -4 0)) (Some (Pair -4 0)) (Some (Pair 4 0)) (Some (Pair 4 0))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input79625541-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input79625541-.out new file mode 100644 index 000000000000..80f4301e21bb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv--storage994417987--input79625541-.out @@ -0,0 +1,135 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv.tz on storage '(Pair None None None None)' and input '(Pair 10 -3)' --level 1 --trace-stack +storage + (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) +emitted operations + +big_map diff + +trace + - location: 25 (just consumed gas: 24.814) + [ (Pair (Pair 10 -3) None None None None) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair 10 -3) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair 10 -3) + (Pair 10 -3) ] + - location: 27 (just consumed gas: 0.010) + [ 10 + -3 + (Pair 10 -3) ] + - location: 28 (just consumed gas: 0.020) + [ 10 + -3 + (Pair 10 -3) ] + - location: 29 (just consumed gas: 0.010) + [ -3 + (Pair 10 -3) ] + - location: 31 (just consumed gas: 0.020) + [ 3 + (Pair 10 -3) ] + - location: 29 (just consumed gas: 0.035) + [ 10 + 3 + (Pair 10 -3) ] + - location: 32 (just consumed gas: 0.151) + [ (Some (Pair 3 1)) + (Pair 10 -3) ] + - location: 33 (just consumed gas: 0.010) + [ (Pair 10 -3) + (Some (Pair 3 1)) ] + - location: 34 (just consumed gas: 0.010) + [ (Pair 10 -3) + (Pair 10 -3) + (Some (Pair 3 1)) ] + - location: 35 (just consumed gas: 0.010) + [ 10 + -3 + (Pair 10 -3) + (Some (Pair 3 1)) ] + - location: 36 (just consumed gas: 0.020) + [ 10 + -3 + (Pair 10 -3) + (Some (Pair 3 1)) ] + - location: 37 (just consumed gas: 0.151) + [ (Some (Pair -3 1)) + (Pair 10 -3) + (Some (Pair 3 1)) ] + - location: 38 (just consumed gas: 0.010) + [ (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 39 (just consumed gas: 0.010) + [ (Pair 10 -3) + (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 40 (just consumed gas: 0.010) + [ 10 + -3 + (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 41 (just consumed gas: 0.010) + [ -3 + (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 43 (just consumed gas: 0.020) + [ 3 + (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 41 (just consumed gas: 0.035) + [ 10 + 3 + (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 44 (just consumed gas: 0.151) + [ (Some (Pair 3 1)) + (Pair 10 -3) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 45 (just consumed gas: 0.010) + [ (Pair 10 -3) + (Some (Pair 3 1)) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 46 (just consumed gas: 0.010) + [ 10 + -3 + (Some (Pair 3 1)) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 47 (just consumed gas: 0.151) + [ (Some (Pair -3 1)) + (Some (Pair 3 1)) + (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 49 (just consumed gas: 0.023) + [ (Some (Pair -3 1)) + (Some (Pair 3 1)) ] + - location: 52 (just consumed gas: 0.010) + [ (Pair (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 49 (just consumed gas: 0.045) + [ (Some (Pair -3 1)) + (Some (Pair 3 1)) + (Pair (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 53 (just consumed gas: 0.010) + [ (Some (Pair 3 1)) + (Pair (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 55 (just consumed gas: 0.010) + [ (Pair (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 53 (just consumed gas: 0.035) + [ (Some (Pair -3 1)) + (Pair (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 56 (just consumed gas: 0.010) + [ (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 57 (just consumed gas: 0.010) + [ {} + (Pair (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + - location: 59 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair -3 1)) (Some (Pair 3 1)) (Some (Pair -3 1)) (Some (Pair 3 1))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input147133089-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input147133089-.out new file mode 100644 index 000000000000..8279c07f1ebb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input147133089-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 10 (Right 0))' --level 1 --trace-stack +storage + (Right None) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 10 (Right 0)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 (Right 0)) ] + - location: 20 (just consumed gas: 0.010) + [ 10 + (Right 0) ] + - location: 21 (just consumed gas: 0.010) + [ (Right 0) + 10 ] + - location: 22 (just consumed gas: 0.010) + [ 0 + 10 ] + - location: 32 (just consumed gas: 0.010) + [ 10 + 0 ] + - location: 33 (just consumed gas: 0.070) + [ None ] + - location: 34 (just consumed gas: 0.010) + [ (Right None) ] + - location: 22 (just consumed gas: 0.025) + [ (Right None) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Right None) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Right None)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input215785357-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input215785357-.out new file mode 100644 index 000000000000..0c74a938fe8c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input215785357-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 10 (Right 3))' --level 1 --trace-stack +storage + (Right (Some (Pair 3 1))) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 10 (Right 3)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 (Right 3)) ] + - location: 20 (just consumed gas: 0.010) + [ 10 + (Right 3) ] + - location: 21 (just consumed gas: 0.010) + [ (Right 3) + 10 ] + - location: 22 (just consumed gas: 0.010) + [ 3 + 10 ] + - location: 32 (just consumed gas: 0.010) + [ 10 + 3 ] + - location: 33 (just consumed gas: 0.070) + [ (Some (Pair 3 1)) ] + - location: 34 (just consumed gas: 0.010) + [ (Right (Some (Pair 3 1))) ] + - location: 22 (just consumed gas: 0.025) + [ (Right (Some (Pair 3 1))) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Right (Some (Pair 3 1))) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Right (Some (Pair 3 1)))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input389351431-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input389351431-.out new file mode 100644 index 000000000000..483246e7bbc8 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input389351431-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 10 (Left 10))' --level 1 --trace-stack +storage + (Left (Some (Pair 1 0))) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 10 (Left 10)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 (Left 10)) ] + - location: 20 (just consumed gas: 0.010) + [ 10 + (Left 10) ] + - location: 21 (just consumed gas: 0.010) + [ (Left 10) + 10 ] + - location: 22 (just consumed gas: 0.010) + [ 10 + 10 ] + - location: 24 (just consumed gas: 0.010) + [ 10 + 10 ] + - location: 25 (just consumed gas: 0.080) + [ (Some (Pair 1 0)) ] + - location: 26 (just consumed gas: 0.010) + [ (Left (Some (Pair 1 0))) ] + - location: 22 (just consumed gas: 0.025) + [ (Left (Some (Pair 1 0))) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Left (Some (Pair 1 0))) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Left (Some (Pair 1 0)))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input44513000-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input44513000-.out new file mode 100644 index 000000000000..b4dbaf26318e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input44513000-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 10 (Left 0))' --level 1 --trace-stack +storage + (Left None) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 10 (Left 0)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 (Left 0)) ] + - location: 20 (just consumed gas: 0.010) + [ 10 + (Left 0) ] + - location: 21 (just consumed gas: 0.010) + [ (Left 0) + 10 ] + - location: 22 (just consumed gas: 0.010) + [ 0 + 10 ] + - location: 24 (just consumed gas: 0.010) + [ 10 + 0 ] + - location: 25 (just consumed gas: 0.080) + [ None ] + - location: 26 (just consumed gas: 0.010) + [ (Left None) ] + - location: 22 (just consumed gas: 0.025) + [ (Left None) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Left None) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Left None)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input635398196-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input635398196-.out new file mode 100644 index 000000000000..a40ea93982c5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input635398196-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 10 (Left 3))' --level 1 --trace-stack +storage + (Left (Some (Pair 3 1))) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 10 (Left 3)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 (Left 3)) ] + - location: 20 (just consumed gas: 0.010) + [ 10 + (Left 3) ] + - location: 21 (just consumed gas: 0.010) + [ (Left 3) + 10 ] + - location: 22 (just consumed gas: 0.010) + [ 3 + 10 ] + - location: 24 (just consumed gas: 0.010) + [ 10 + 3 ] + - location: 25 (just consumed gas: 0.080) + [ (Some (Pair 3 1)) ] + - location: 26 (just consumed gas: 0.010) + [ (Left (Some (Pair 3 1))) ] + - location: 22 (just consumed gas: 0.025) + [ (Left (Some (Pair 3 1))) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Left (Some (Pair 3 1))) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Left (Some (Pair 3 1)))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input734264738-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input734264738-.out new file mode 100644 index 000000000000..e2af9ee14162 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input734264738-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 10 (Right 10))' --level 1 --trace-stack +storage + (Right (Some (Pair 1 0))) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 10 (Right 10)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 (Right 10)) ] + - location: 20 (just consumed gas: 0.010) + [ 10 + (Right 10) ] + - location: 21 (just consumed gas: 0.010) + [ (Right 10) + 10 ] + - location: 22 (just consumed gas: 0.010) + [ 10 + 10 ] + - location: 32 (just consumed gas: 0.010) + [ 10 + 10 ] + - location: 33 (just consumed gas: 0.070) + [ (Some (Pair 1 0)) ] + - location: 34 (just consumed gas: 0.010) + [ (Right (Some (Pair 1 0))) ] + - location: 22 (just consumed gas: 0.025) + [ (Right (Some (Pair 1 0))) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Right (Some (Pair 1 0))) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Right (Some (Pair 1 0)))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input993071382-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input993071382-.out new file mode 100644 index 000000000000..399883036d3b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ediv_mutez--storage977883604--input993071382-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ediv_mutez.tz on storage '(Left None)' and input '(Pair 5 (Right 10))' --level 1 --trace-stack +storage + (Right (Some (Pair 0 5))) +emitted operations + +big_map diff + +trace + - location: 19 (just consumed gas: 13.318) + [ (Pair (Pair 5 (Right 10)) (Left None)) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 5 (Right 10)) ] + - location: 20 (just consumed gas: 0.010) + [ 5 + (Right 10) ] + - location: 21 (just consumed gas: 0.010) + [ (Right 10) + 5 ] + - location: 22 (just consumed gas: 0.010) + [ 10 + 5 ] + - location: 32 (just consumed gas: 0.010) + [ 5 + 10 ] + - location: 33 (just consumed gas: 0.070) + [ (Some (Pair 0 5)) ] + - location: 34 (just consumed gas: 0.010) + [ (Right (Some (Pair 0 5))) ] + - location: 22 (just consumed gas: 0.025) + [ (Right (Some (Pair 0 5))) ] + - location: 39 (just consumed gas: 0.010) + [ {} + (Right (Some (Pair 0 5))) ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} (Right (Some (Pair 0 5)))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -emit--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -emit--storage125992234--input125992234-.out new file mode 100644 index 000000000000..f9cfe3f890c2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -emit--storage125992234--input125992234-.out @@ -0,0 +1,72 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/emit.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + Internal Event: + From: KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi + Type: (or nat string) + Tag: event + Payload: (Left 10) + Internal Event: + From: KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi + Type: (or (nat %number) (string %words)) + Tag: event + Payload: (Right "lorem ipsum") +big_map diff + +trace + - location: 7 (just consumed gas: 13.014) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ Unit ] + - location: 9 (just consumed gas: 0.010) + [ 10 + Unit ] + - location: 12 (just consumed gas: 0.010) + [ (Left 10) + Unit ] + - location: 14 (just consumed gas: 0.487) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 15 (just consumed gas: 0.010) + [ "lorem ipsum" + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 18 (just consumed gas: 0.010) + [ (Right "lorem ipsum") + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 20 (just consumed gas: 0.572) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 24 (just consumed gas: 0.010) + [ {} + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 26 (just consumed gas: 0.010) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d + {} + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 27 (just consumed gas: 0.010) + [ { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d } + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + Unit ] + - location: 28 (just consumed gas: 0.010) + [ 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a + { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d } + Unit ] + - location: 29 (just consumed gas: 0.010) + [ { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a ; + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d } + Unit ] + - location: 30 (just consumed gas: 0.010) + [ (Pair { 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000004076403620368ffff056576656e74ff0505000a ; + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000001040764046200000007256e756d62657204680000000625776f726473ffff056576656e74ff0508010000000b6c6f72656d20697073756d } + Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -empty_map--storage457300675--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -empty_map--storage457300675--input125992234-.out new file mode 100644 index 000000000000..f8c676aae3af --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -empty_map--storage457300675--input125992234-.out @@ -0,0 +1,33 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/empty_map.tz on storage '{}' and input Unit --level 1 --trace-stack +storage + { Elt "hello" "world" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 8.200) + [ (Pair Unit {}) ] + - location: 9 (just consumed gas: 0.010) + [ ] + - location: 10 (just consumed gas: 0.300) + [ {} ] + - location: 13 (just consumed gas: 0.010) + [ "world" + {} ] + - location: 16 (just consumed gas: 0.010) + [ (Some "world") + {} ] + - location: 17 (just consumed gas: 0.010) + [ "hello" + (Some "world") + {} ] + - location: 20 (just consumed gas: 0.055) + [ { Elt "hello" "world" } ] + - location: 21 (just consumed gas: 0.010) + [ {} + { Elt "hello" "world" } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "hello" "world" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input246262487-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input246262487-.out new file mode 100644 index 000000000000..87658a78c602 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input246262487-.out @@ -0,0 +1,48 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/exec_concat.tz on storage '"?"' and input '"test"' --level 1 --trace-stack +storage + "test_abc" +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 10.835) + [ (Pair "test" "?") ] + - location: 7 (just consumed gas: 0.010) + [ "test" ] + - location: 8 (just consumed gas: 0.010) + [ { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } + "test" ] + - location: 22 (just consumed gas: 0.010) + [ "test" + { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } ] + - location: 12 (just consumed gas: 0.020) + [ "_abc" + "test" ] + - location: 15 (just consumed gas: 0.010) + [ {} + "_abc" + "test" ] + - location: 17 (just consumed gas: 0.010) + [ "_abc" + {} + "test" ] + - location: 18 (just consumed gas: 0.010) + [ { "_abc" } + "test" ] + - location: 19 (just consumed gas: 0.010) + [ "test" + { "_abc" } ] + - location: 20 (just consumed gas: 0.010) + [ { "test" ; "_abc" } ] + - location: 21 (just consumed gas: 0.124) + [ "test_abc" ] + - location: 23 (just consumed gas: 0.035) + [ "test_abc" ] + - location: 24 (just consumed gas: 0.010) + [ {} + "test_abc" ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} "test_abc") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input79230375-.out new file mode 100644 index 000000000000..a3f41564d5a6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -exec_concat--storage398998998--input79230375-.out @@ -0,0 +1,48 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/exec_concat.tz on storage '"?"' and input '""' --level 1 --trace-stack +storage + "_abc" +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 10.795) + [ (Pair "" "?") ] + - location: 7 (just consumed gas: 0.010) + [ "" ] + - location: 8 (just consumed gas: 0.010) + [ { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } + "" ] + - location: 22 (just consumed gas: 0.010) + [ "" + { PUSH string "_abc" ; NIL string ; SWAP ; CONS ; SWAP ; CONS ; CONCAT } ] + - location: 12 (just consumed gas: 0.020) + [ "_abc" + "" ] + - location: 15 (just consumed gas: 0.010) + [ {} + "_abc" + "" ] + - location: 17 (just consumed gas: 0.010) + [ "_abc" + {} + "" ] + - location: 18 (just consumed gas: 0.010) + [ { "_abc" } + "" ] + - location: 19 (just consumed gas: 0.010) + [ "" + { "_abc" } ] + - location: 20 (just consumed gas: 0.010) + [ { "" ; "_abc" } ] + - location: 21 (just consumed gas: 0.122) + [ "_abc" ] + - location: 23 (just consumed gas: 0.035) + [ "_abc" ] + - location: 24 (just consumed gas: 0.010) + [ {} + "_abc" ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} "_abc") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input478406404-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input478406404-.out new file mode 100644 index 000000000000..ff29f3fd1e73 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input478406404-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/first.tz on storage 111 and input '{ 4 }' --level 1 --trace-stack +storage + 4 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 7.331) + [ (Pair { 4 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 4 } ] + - location: 9 (just consumed gas: 0.010) + [ 4 + {} ] + - location: 11 (just consumed gas: 0.010) + [ {} ] + - location: 13 (just consumed gas: 0.010) + [ ] + - location: 11 (just consumed gas: 0.035) + [ 4 ] + - location: 9 (just consumed gas: 0.025) + [ 4 ] + - location: 18 (just consumed gas: 0.010) + [ {} + 4 ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} 4) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input962874972-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input962874972-.out new file mode 100644 index 000000000000..c5c6dc12cc13 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -first--storage492856247--input962874972-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/first.tz on storage 111 and input '{ 1 ; 2 ; 3 ; 4 }' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 7.631) + [ (Pair { 1 ; 2 ; 3 ; 4 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 ; 4 } ] + - location: 9 (just consumed gas: 0.010) + [ 1 + { 2 ; 3 ; 4 } ] + - location: 11 (just consumed gas: 0.010) + [ { 2 ; 3 ; 4 } ] + - location: 13 (just consumed gas: 0.010) + [ ] + - location: 11 (just consumed gas: 0.035) + [ 1 ] + - location: 9 (just consumed gas: 0.025) + [ 1 ] + - location: 18 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage1026405794--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage1026405794--input329240220-.out new file mode 100644 index 000000000000..a00b5d6d98ec --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage1026405794--input329240220-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair None { Elt "hello" 4 })' and input '"hello"' --level 1 --trace-stack +storage + (Pair (Some 4) {}) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 8.004) + [ (Pair "hello" None { Elt "hello" 4 }) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair None { Elt "hello" 4 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" 4 }) ] + - location: 16 (just consumed gas: 0.010) + [ None + { Elt "hello" 4 } ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + None + { Elt "hello" 4 } ] + - location: 17 (just consumed gas: 0.076) + [ (Some 4) + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 4) {}) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 4) {}) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 4) {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage382368661--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage382368661--input329240220-.out new file mode 100644 index 000000000000..368aadbbadba --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage382368661--input329240220-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair (Some 4) {})' and input '"hello"' --level 1 --trace-stack +storage + (Pair None { Elt "hello" 4 }) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 7.784) + [ (Pair "hello" (Some 4) {}) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair (Some 4) {}) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair (Some 4) {}) ] + - location: 16 (just consumed gas: 0.010) + [ (Some 4) + {} ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + (Some 4) + {} ] + - location: 17 (just consumed gas: 0.076) + [ None + { Elt "hello" 4 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" 4 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair None { Elt "hello" 4 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} None { Elt "hello" 4 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input329240220-.out new file mode 100644 index 000000000000..b36b1d08fa17 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input329240220-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair (Some 5) { Elt "hello" 4 })' and input '"hello"' --level 1 --trace-stack +storage + (Pair (Some 4) { Elt "hello" 5 }) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 8.104) + [ (Pair "hello" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 16 (just consumed gas: 0.010) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (just consumed gas: 0.076) + [ (Some 4) + { Elt "hello" 5 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 4) { Elt "hello" 5 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input507231566-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input507231566-.out new file mode 100644 index 000000000000..254dd9e7775f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage496578814--input507231566-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair (Some 5) { Elt "hello" 4 })' and input '"hi"' --level 1 --trace-stack +storage + (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 8.074) + [ (Pair "hi" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (just consumed gas: 0.010) + [ "hi" + (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 16 (just consumed gas: 0.010) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (just consumed gas: 0.035) + [ "hi" + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (just consumed gas: 0.075) + [ None + { Elt "hello" 4 ; Elt "hi" 5 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} None { Elt "hello" 4 ; Elt "hi" 5 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage547821324--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage547821324--input329240220-.out new file mode 100644 index 000000000000..39b2d0076600 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage547821324--input329240220-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair None {})' and input '"hello"' --level 1 --trace-stack +storage + (Pair None {}) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 7.684) + [ (Pair "hello" None {}) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair None {}) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None {}) ] + - location: 16 (just consumed gas: 0.010) + [ None + {} ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + None + {} ] + - location: 17 (just consumed gas: 0.076) + [ None + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair None {}) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair None {}) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} None {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input156280093-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input156280093-.out new file mode 100644 index 000000000000..4dc48c3fd46a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input156280093-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair None { Elt "1" 1 ; Elt "2" 2 })' and input '"1"' --level 1 --trace-stack +storage + (Pair (Some 1) { Elt "2" 2 }) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 8.239) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (just consumed gas: 0.010) + [ "1" + (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 16 (just consumed gas: 0.010) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (just consumed gas: 0.035) + [ "1" + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (just consumed gas: 0.075) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input228164856-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input228164856-.out new file mode 100644 index 000000000000..979e023dce62 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_and_update_map--storage796012494--input228164856-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_and_update_map.tz on storage '(Pair None { Elt "1" 1 ; Elt "2" 2 })' and input '"2"' --level 1 --trace-stack +storage + (Pair (Some 2) { Elt "1" 1 }) +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 8.239) + [ (Pair "2" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (just consumed gas: 0.010) + [ "2" + (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 16 (just consumed gas: 0.010) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (just consumed gas: 0.035) + [ "2" + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (just consumed gas: 0.075) + [ (Some 2) + { Elt "1" 1 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 2) { Elt "1" 1 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 2) { Elt "1" 1 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 2) { Elt "1" 1 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input329240220-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input329240220-.out new file mode 100644 index 000000000000..b33093dde668 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input329240220-.out @@ -0,0 +1,41 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_map_value.tz on storage '(Pair None { Elt "hello" "hi" })' and input '"hello"' --level 1 --trace-stack +storage + (Pair (Some "hi") { Elt "hello" "hi" }) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 10.557) + [ (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "hello" None { Elt "hello" "hi" }) + (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "hello" None { Elt "hello" "hi" }) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" "hi" }) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (just consumed gas: 0.045) + [ (Some "hi") + { Elt "hello" "hi" } ] + - location: 21 (just consumed gas: 0.010) + [ (Pair (Some "hi") { Elt "hello" "hi" }) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Pair (Some "hi") { Elt "hello" "hi" }) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some "hi") { Elt "hello" "hi" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input79230375-.out new file mode 100644 index 000000000000..0a9977d90ecb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage139236239--input79230375-.out @@ -0,0 +1,41 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_map_value.tz on storage '(Pair None { Elt "hello" "hi" })' and input '""' --level 1 --trace-stack +storage + (Pair None { Elt "hello" "hi" }) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 10.507) + [ (Pair "" None { Elt "hello" "hi" }) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "" None { Elt "hello" "hi" }) + (Pair "" None { Elt "hello" "hi" }) ] + - location: 13 (just consumed gas: 0.010) + [ "" + (Pair "" None { Elt "hello" "hi" }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "" None { Elt "hello" "hi" }) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" "hi" }) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (just consumed gas: 0.035) + [ "" + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (just consumed gas: 0.045) + [ None + { Elt "hello" "hi" } ] + - location: 21 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" "hi" }) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Pair None { Elt "hello" "hi" }) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None { Elt "hello" "hi" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage329396864--input156280093-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage329396864--input156280093-.out new file mode 100644 index 000000000000..b7eadc6bc744 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -get_map_value--storage329396864--input156280093-.out @@ -0,0 +1,41 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/get_map_value.tz on storage '(Pair None { Elt "1" "one" ; Elt "2" "two" })' and input '"1"' --level 1 --trace-stack +storage + (Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" }) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 10.847) + [ (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) + (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 13 (just consumed gas: 0.010) + [ "1" + (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "1" None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair None { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 14 (just consumed gas: 0.035) + [ "1" + { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 20 (just consumed gas: 0.045) + [ (Some "one") + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 21 (just consumed gas: 0.010) + [ (Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Pair (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some "one") { Elt "1" "one" ; Elt "2" "two" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input1040351577-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input1040351577-.out new file mode 100644 index 000000000000..e8bea2046b46 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input1040351577-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/hash_key.tz on storage None and input '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"' --level 1 --trace-stack +storage + (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 83.907) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" None) ] + - location: 8 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" ] + - location: 9 (just consumed gas: 0.605) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 10 (just consumed gas: 0.010) + [ (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input153350004-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input153350004-.out new file mode 100644 index 000000000000..a23786e155b4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_key--storage921624073--input153350004-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/hash_key.tz on storage None and input '"edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES"' --level 1 --trace-stack +storage + (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 83.907) + [ (Pair "edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES" None) ] + - location: 8 (just consumed gas: 0.010) + [ "edpkuJqtDcA2m2muMxViSM47MPsGQzmyjnNTawUPqR8vZTAMcx61ES" ] + - location: 9 (just consumed gas: 0.605) + [ "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k" ] + - location: 10 (just consumed gas: 0.010) + [ (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k") ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some "tz1XPTDmvT3vVE5Uunngmixm7gj7zmdbPq6k")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input3431716-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input3431716-.out new file mode 100644 index 000000000000..9bfde6a843c2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input3431716-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/hash_string.tz on storage 0x00 and input '"abcdefg"' --level 1 --trace-stack +storage + 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.841) + [ (Pair "abcdefg" 0x00) ] + - location: 7 (just consumed gas: 0.010) + [ "abcdefg" ] + - location: 8 (just consumed gas: 0.286) + [ 0x05010000000761626364656667 ] + - location: 9 (just consumed gas: 0.444) + [ 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0x46fdbcb4ea4eadad5615cdaa17d67f783e01e21149ce2b27de497600b4cd8f4e) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input535018041-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input535018041-.out new file mode 100644 index 000000000000..260b2b046b6c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -hash_string--storage151303925--input535018041-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/hash_string.tz on storage 0x00 and input '"12345"' --level 1 --trace-stack +storage + 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.821) + [ (Pair "12345" 0x00) ] + - location: 7 (just consumed gas: 0.010) + [ "12345" ] + - location: 8 (just consumed gas: 0.266) + [ 0x0501000000053132333435 ] + - location: 9 (just consumed gas: 0.442) + [ 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0xb4c26c20de52a4eaf0d8a340db47ad8cb1e74049570859c9a9a3952b204c772f) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input570553153-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input570553153-.out new file mode 100644 index 000000000000..62840b311693 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input570553153-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/if.tz on storage None and input False --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 7.179) + [ (Pair False None) ] + - location: 8 (just consumed gas: 0.010) + [ False ] + - location: 9 (just consumed gas: 0.010) + [ ] + - location: 15 (just consumed gas: 0.010) + [ False ] + - location: 9 (just consumed gas: 0.025) + [ False ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input954397288-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input954397288-.out new file mode 100644 index 000000000000..71b0b137c81d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if--storage921624073--input954397288-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/if.tz on storage None and input True --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 7.179) + [ (Pair True None) ] + - location: 8 (just consumed gas: 0.010) + [ True ] + - location: 9 (just consumed gas: 0.010) + [ ] + - location: 11 (just consumed gas: 0.010) + [ True ] + - location: 9 (just consumed gas: 0.025) + [ True ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input288201633-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input288201633-.out new file mode 100644 index 000000000000..a841efba1685 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input288201633-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/if_some.tz on storage '"?"' and input '(Some "hello")' --level 1 --trace-stack +storage + "hello" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.316) + [ (Pair (Some "hello") "?") ] + - location: 8 (just consumed gas: 0.010) + [ (Some "hello") ] + - location: 10 (just consumed gas: 0.010) + [ "hello" ] + - location: 10 (just consumed gas: 0.025) + [ "hello" ] + - location: 16 (just consumed gas: 0.010) + [ {} + "hello" ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} "hello") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input921624073-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input921624073-.out new file mode 100644 index 000000000000..8d40ed698eb3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -if_some--storage398998998--input921624073-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/if_some.tz on storage '"?"' and input None --level 1 --trace-stack +storage + "" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.151) + [ (Pair None "?") ] + - location: 8 (just consumed gas: 0.010) + [ None ] + - location: 10 (just consumed gas: 0.010) + [ ] + - location: 12 (just consumed gas: 0.010) + [ "" ] + - location: 10 (just consumed gas: 0.025) + [ "" ] + - location: 16 (just consumed gas: 0.010) + [ {} + "" ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} "") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input453441034-.out new file mode 100644 index 000000000000..af91661f92a0 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input453441034-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/int.tz on storage None and input 1 --level 1 --trace-stack +storage + (Some 1) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair 1 None) ] + - location: 8 (just consumed gas: 0.010) + [ 1 ] + - location: 9 (just consumed gas: 0.010) + [ 1 ] + - location: 10 (just consumed gas: 0.010) + [ (Some 1) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some 1) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some 1)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input535454136-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input535454136-.out new file mode 100644 index 000000000000..42ca8f27abb8 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input535454136-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/int.tz on storage None and input 9999 --level 1 --trace-stack +storage + (Some 9999) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair 9999 None) ] + - location: 8 (just consumed gas: 0.010) + [ 9999 ] + - location: 9 (just consumed gas: 0.010) + [ 9999 ] + - location: 10 (just consumed gas: 0.010) + [ (Some 9999) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some 9999) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some 9999)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input680650890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input680650890-.out new file mode 100644 index 000000000000..5663f3aea085 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -int--storage921624073--input680650890-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/int.tz on storage None and input 0 --level 1 --trace-stack +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair 0 None) ] + - location: 8 (just consumed gas: 0.010) + [ 0 ] + - location: 9 (just consumed gas: 0.010) + [ 0 ] + - location: 10 (just consumed gas: 0.010) + [ (Some 0) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some 0) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some 0)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -keccak--storage921624073--input1008262038-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -keccak--storage921624073--input1008262038-.out new file mode 100644 index 000000000000..24dc9f6f2f6c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -keccak--storage921624073--input1008262038-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/keccak.tz on storage None and input 0x48656c6c6f2c20776f726c6421 --level 1 --trace-stack +storage + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair 0x48656c6c6f2c20776f726c6421 None) ] + - location: 8 (just consumed gas: 0.010) + [ 0x48656c6c6f2c20776f726c6421 ] + - location: 9 (just consumed gas: 1.457) + [ 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4 ] + - location: 10 (just consumed gas: 0.010) + [ (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} + (Some 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input202098045-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input202098045-.out new file mode 100644 index 000000000000..ad892ddefebc --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input202098045-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/left_right.tz on storage '(Left "X")' and input '(Left True)' --level 1 --trace-stack +storage + (Right True) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 6.990) + [ (Pair (Left True) (Left "X")) ] + - location: 11 (just consumed gas: 0.010) + [ (Left True) ] + - location: 12 (just consumed gas: 0.010) + [ True ] + - location: 14 (just consumed gas: 0.010) + [ (Right True) ] + - location: 12 (just consumed gas: 0.025) + [ (Right True) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Right True) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Right True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input44576556-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input44576556-.out new file mode 100644 index 000000000000..f8f867181af9 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -left_right--storage4177631--input44576556-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/left_right.tz on storage '(Left "X")' and input '(Right "a")' --level 1 --trace-stack +storage + (Left "a") +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 7.015) + [ (Pair (Right "a") (Left "X")) ] + - location: 11 (just consumed gas: 0.010) + [ (Right "a") ] + - location: 12 (just consumed gas: 0.010) + [ "a" ] + - location: 17 (just consumed gas: 0.010) + [ (Left "a") ] + - location: 12 (just consumed gas: 0.025) + [ (Left "a") ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Left "a") ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Left "a")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -level--storage492856247--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -level--storage492856247--input125992234-.out new file mode 100644 index 000000000000..caab1c90b100 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -level--storage492856247--input125992234-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/level.tz on storage 111 and input Unit --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 111) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 1 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input457300675-.out new file mode 100644 index 000000000000..054a788cadb5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input457300675-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_concat.tz on storage '"abc"' and input '{}' --level 1 --trace-stack +storage + "abc" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.567) + [ (Pair {} "abc") ] + - location: 8 (just consumed gas: 0.010) + [ {} + "abc" ] + - location: 9 (just consumed gas: 0.010) + [ "abc" + {} ] + - location: 10 (just consumed gas: 0.010) + [ { "abc" } ] + - location: 11 (just consumed gas: 0.111) + [ "abc" ] + - location: 12 (just consumed gas: 0.010) + [ {} + "abc" ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} "abc") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input546523343-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input546523343-.out new file mode 100644 index 000000000000..bc37acf01a3c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat--storage717096222--input546523343-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_concat.tz on storage '"abc"' and input '{ "d" ; "e" ; "f" }' --level 1 --trace-stack +storage + "abcdef" +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.942) + [ (Pair { "d" ; "e" ; "f" } "abc") ] + - location: 8 (just consumed gas: 0.010) + [ { "d" ; "e" ; "f" } + "abc" ] + - location: 9 (just consumed gas: 0.010) + [ "abc" + { "d" ; "e" ; "f" } ] + - location: 10 (just consumed gas: 0.010) + [ { "abc" ; "d" ; "e" ; "f" } ] + - location: 11 (just consumed gas: 0.143) + [ "abcdef" ] + - location: 12 (just consumed gas: 0.010) + [ {} + "abcdef" ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} "abcdef") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input220724351-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input220724351-.out new file mode 100644 index 000000000000..253bdcbcad96 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input220724351-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_concat_bytes.tz on storage 0x and input '{ 0x00 ; 0x11 ; 0x00 }' --level 1 --trace-stack +storage + 0x001100 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.822) + [ (Pair { 0x00 ; 0x11 ; 0x00 } 0x) ] + - location: 8 (just consumed gas: 0.010) + [ { 0x00 ; 0x11 ; 0x00 } + 0x ] + - location: 9 (just consumed gas: 0.010) + [ 0x + { 0x00 ; 0x11 ; 0x00 } ] + - location: 10 (just consumed gas: 0.010) + [ { 0x ; 0x00 ; 0x11 ; 0x00 } ] + - location: 11 (just consumed gas: 0.141) + [ 0x001100 ] + - location: 12 (just consumed gas: 0.010) + [ {} + 0x001100 ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} 0x001100) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input457300675-.out new file mode 100644 index 000000000000..5a8d36ce9353 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage149262694--input457300675-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_concat_bytes.tz on storage 0x and input '{}' --level 1 --trace-stack +storage + 0x +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.522) + [ (Pair {} 0x) ] + - location: 8 (just consumed gas: 0.010) + [ {} + 0x ] + - location: 9 (just consumed gas: 0.010) + [ 0x + {} ] + - location: 10 (just consumed gas: 0.010) + [ { 0x } ] + - location: 11 (just consumed gas: 0.110) + [ 0x ] + - location: 12 (just consumed gas: 0.010) + [ {} + 0x ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} 0x) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage65410082--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage65410082--input457300675-.out new file mode 100644 index 000000000000..9081703b758f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage65410082--input457300675-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_concat_bytes.tz on storage 0xabcd and input '{}' --level 1 --trace-stack +storage + 0xabcd +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.522) + [ (Pair {} 0xabcd) ] + - location: 8 (just consumed gas: 0.010) + [ {} + 0xabcd ] + - location: 9 (just consumed gas: 0.010) + [ 0xabcd + {} ] + - location: 10 (just consumed gas: 0.010) + [ { 0xabcd } ] + - location: 11 (just consumed gas: 0.111) + [ 0xabcd ] + - location: 12 (just consumed gas: 0.010) + [ {} + 0xabcd ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} 0xabcd) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage726220441--input972761363-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage726220441--input972761363-.out new file mode 100644 index 000000000000..6b335afd9ef3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_concat_bytes--storage726220441--input972761363-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_concat_bytes.tz on storage 0x00ab and input '{ 0xcd ; 0xef ; 0x00 }' --level 1 --trace-stack +storage + 0x00abcdef00 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.822) + [ (Pair { 0xcd ; 0xef ; 0x00 } 0x00ab) ] + - location: 8 (just consumed gas: 0.010) + [ { 0xcd ; 0xef ; 0x00 } + 0x00ab ] + - location: 9 (just consumed gas: 0.010) + [ 0x00ab + { 0xcd ; 0xef ; 0x00 } ] + - location: 10 (just consumed gas: 0.010) + [ { 0x00ab ; 0xcd ; 0xef ; 0x00 } ] + - location: 11 (just consumed gas: 0.142) + [ 0x00abcdef00 ] + - location: 12 (just consumed gas: 0.010) + [ {} + 0x00abcdef00 ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} 0x00abcdef00) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input264787654-.out new file mode 100644 index 000000000000..056c184d8e71 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input264787654-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_id.tz on storage '{""}' and input '{ "a" ; "b" ; "c" }' --level 1 --trace-stack +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.418) + [ (Pair { "a" ; "b" ; "c" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input457300675-.out new file mode 100644 index 000000000000..071f5824ae78 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input457300675-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_id.tz on storage '{""}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.043) + [ (Pair {} { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ {} + {} ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input656499821-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input656499821-.out new file mode 100644 index 000000000000..1f5129ce6a11 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id--storage528921618--input656499821-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_id.tz on storage '{""}' and input '{ "1" ; "2" ; "3" }' --level 1 --trace-stack +storage + { "1" ; "2" ; "3" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.418) + [ (Pair { "1" ; "2" ; "3" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "1" ; "2" ; "3" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "1" ; "2" ; "3" } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { "1" ; "2" ; "3" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input264787654-.out new file mode 100644 index 000000000000..0ad6384ba716 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input264787654-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_id_map.tz on storage '{""}' and input '{ "a" ; "b" ; "c" }' --level 1 --trace-stack +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.377) + [ (Pair { "a" ; "b" ; "c" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 10 (just consumed gas: 0.050) + [ "a" ] + - location: 10 (just consumed gas: 0.055) + [ "b" ] + - location: 10 (just consumed gas: 0.055) + [ "c" ] + - location: 10 (just consumed gas: 0.069) + [ { "a" ; "b" ; "c" } ] + - location: 12 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input457300675-.out new file mode 100644 index 000000000000..950a6a53387b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input457300675-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_id_map.tz on storage '{""}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.002) + [ (Pair {} { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.060) + [ {} ] + - location: 12 (just consumed gas: 0.010) + [ {} + {} ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input656499821-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input656499821-.out new file mode 100644 index 000000000000..786a220fba30 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_id_map--storage528921618--input656499821-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_id_map.tz on storage '{""}' and input '{ "1" ; "2" ; "3" }' --level 1 --trace-stack +storage + { "1" ; "2" ; "3" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.377) + [ (Pair { "1" ; "2" ; "3" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "1" ; "2" ; "3" } ] + - location: 10 (just consumed gas: 0.050) + [ "1" ] + - location: 10 (just consumed gas: 0.055) + [ "2" ] + - location: 10 (just consumed gas: 0.055) + [ "3" ] + - location: 10 (just consumed gas: 0.069) + [ { "1" ; "2" ; "3" } ] + - location: 12 (just consumed gas: 0.010) + [ {} + { "1" ; "2" ; "3" } ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} { "1" ; "2" ; "3" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input568817463-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input568817463-.out new file mode 100644 index 000000000000..452fa47e3be0 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input568817463-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_iter.tz on storage 0 and input '{ 10 ; 2 ; 1 }' --level 1 --trace-stack +storage + 20 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.896) + [ (Pair { 10 ; 2 ; 1 } 0) ] + - location: 8 (just consumed gas: 0.010) + [ { 10 ; 2 ; 1 } ] + - location: 9 (just consumed gas: 0.010) + [ 1 + { 10 ; 2 ; 1 } ] + - location: 12 (just consumed gas: 0.010) + [ { 10 ; 2 ; 1 } + 1 ] + - location: 13 (just consumed gas: 0.030) + [ 10 + 1 ] + - location: 15 (just consumed gas: 0.059) + [ 10 ] + - location: 13 (just consumed gas: 0.025) + [ 2 + 10 ] + - location: 15 (just consumed gas: 0.059) + [ 20 ] + - location: 13 (just consumed gas: 0.025) + [ 1 + 20 ] + - location: 15 (just consumed gas: 0.059) + [ 20 ] + - location: 13 (just consumed gas: 0.035) + [ 20 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 20 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 20) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input737923774-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input737923774-.out new file mode 100644 index 000000000000..2782b26da294 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_iter--storage680650890--input737923774-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_iter.tz on storage 0 and input '{ 3 ; 6 ; 9 }' --level 1 --trace-stack +storage + 162 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.896) + [ (Pair { 3 ; 6 ; 9 } 0) ] + - location: 8 (just consumed gas: 0.010) + [ { 3 ; 6 ; 9 } ] + - location: 9 (just consumed gas: 0.010) + [ 1 + { 3 ; 6 ; 9 } ] + - location: 12 (just consumed gas: 0.010) + [ { 3 ; 6 ; 9 } + 1 ] + - location: 13 (just consumed gas: 0.030) + [ 3 + 1 ] + - location: 15 (just consumed gas: 0.059) + [ 3 ] + - location: 13 (just consumed gas: 0.025) + [ 6 + 3 ] + - location: 15 (just consumed gas: 0.059) + [ 18 ] + - location: 13 (just consumed gas: 0.025) + [ 9 + 18 ] + - location: 15 (just consumed gas: 0.059) + [ 162 ] + - location: 13 (just consumed gas: 0.035) + [ 162 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 162 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 162) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input457300675-.out new file mode 100644 index 000000000000..7a6caf40149b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input457300675-.out @@ -0,0 +1,36 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_map_block.tz on storage '{0}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 11.811) + [ (Pair {} { 0 }) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ 0 + {} ] + - location: 13 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 14 (just consumed gas: 0.060) + [ {} + 0 ] + - location: 26 (just consumed gas: 0.010) + [ {} + {} + 0 ] + - location: 28 (just consumed gas: 0.010) + [ (Pair {} {}) + 0 ] + - location: 29 (just consumed gas: 0.010) + [ 0 ] + - location: 31 (just consumed gas: 0.010) + [ ] + - location: 29 (just consumed gas: 0.035) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input648737279-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input648737279-.out new file mode 100644 index 000000000000..9e4ddcad190e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input648737279-.out @@ -0,0 +1,136 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_map_block.tz on storage '{0}' and input '{ 1 ; 2 ; 3 ; 0 }' --level 1 --trace-stack +storage + { 1 ; 3 ; 5 ; 3 } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 12.211) + [ (Pair { 1 ; 2 ; 3 ; 0 } { 0 }) ] + - location: 9 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 ; 0 } ] + - location: 10 (just consumed gas: 0.010) + [ 0 + { 1 ; 2 ; 3 ; 0 } ] + - location: 13 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 ; 0 } + 0 ] + - location: 14 (just consumed gas: 0.050) + [ 1 + 0 ] + - location: 16 (just consumed gas: 0.010) + [ 0 ] + - location: 18 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 16 (just consumed gas: 0.035) + [ 1 + 0 + 0 ] + - location: 19 (just consumed gas: 0.035) + [ 1 + 0 ] + - location: 20 (just consumed gas: 0.010) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 0 ] + - location: 25 (just consumed gas: 0.035) + [ 1 ] + - location: 20 (just consumed gas: 0.035) + [ 1 + 1 ] + - location: 14 (just consumed gas: 0.055) + [ 2 + 1 ] + - location: 16 (just consumed gas: 0.010) + [ 1 ] + - location: 18 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 16 (just consumed gas: 0.035) + [ 2 + 1 + 1 ] + - location: 19 (just consumed gas: 0.035) + [ 3 + 1 ] + - location: 20 (just consumed gas: 0.010) + [ 1 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 25 (just consumed gas: 0.035) + [ 2 ] + - location: 20 (just consumed gas: 0.035) + [ 3 + 2 ] + - location: 14 (just consumed gas: 0.055) + [ 3 + 2 ] + - location: 16 (just consumed gas: 0.010) + [ 2 ] + - location: 18 (just consumed gas: 0.010) + [ 2 + 2 ] + - location: 16 (just consumed gas: 0.035) + [ 3 + 2 + 2 ] + - location: 19 (just consumed gas: 0.035) + [ 5 + 2 ] + - location: 20 (just consumed gas: 0.010) + [ 2 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 2 ] + - location: 25 (just consumed gas: 0.035) + [ 3 ] + - location: 20 (just consumed gas: 0.035) + [ 5 + 3 ] + - location: 14 (just consumed gas: 0.055) + [ 0 + 3 ] + - location: 16 (just consumed gas: 0.010) + [ 3 ] + - location: 18 (just consumed gas: 0.010) + [ 3 + 3 ] + - location: 16 (just consumed gas: 0.035) + [ 0 + 3 + 3 ] + - location: 19 (just consumed gas: 0.035) + [ 3 + 3 ] + - location: 20 (just consumed gas: 0.010) + [ 3 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 3 ] + - location: 25 (just consumed gas: 0.035) + [ 4 ] + - location: 20 (just consumed gas: 0.035) + [ 3 + 4 ] + - location: 14 (just consumed gas: 0.072) + [ { 1 ; 3 ; 5 ; 3 } + 4 ] + - location: 26 (just consumed gas: 0.010) + [ {} + { 1 ; 3 ; 5 ; 3 } + 4 ] + - location: 28 (just consumed gas: 0.010) + [ (Pair {} { 1 ; 3 ; 5 ; 3 }) + 4 ] + - location: 29 (just consumed gas: 0.010) + [ 4 ] + - location: 31 (just consumed gas: 0.010) + [ ] + - location: 29 (just consumed gas: 0.035) + [ (Pair {} { 1 ; 3 ; 5 ; 3 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input908379154-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input908379154-.out new file mode 100644 index 000000000000..0ec937d0a42c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_map_block--storage907453363--input908379154-.out @@ -0,0 +1,136 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_map_block.tz on storage '{0}' and input '{ 1 ; 1 ; 1 ; 1 }' --level 1 --trace-stack +storage + { 1 ; 2 ; 3 ; 4 } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 12.211) + [ (Pair { 1 ; 1 ; 1 ; 1 } { 0 }) ] + - location: 9 (just consumed gas: 0.010) + [ { 1 ; 1 ; 1 ; 1 } ] + - location: 10 (just consumed gas: 0.010) + [ 0 + { 1 ; 1 ; 1 ; 1 } ] + - location: 13 (just consumed gas: 0.010) + [ { 1 ; 1 ; 1 ; 1 } + 0 ] + - location: 14 (just consumed gas: 0.050) + [ 1 + 0 ] + - location: 16 (just consumed gas: 0.010) + [ 0 ] + - location: 18 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 16 (just consumed gas: 0.035) + [ 1 + 0 + 0 ] + - location: 19 (just consumed gas: 0.035) + [ 1 + 0 ] + - location: 20 (just consumed gas: 0.010) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 0 ] + - location: 25 (just consumed gas: 0.035) + [ 1 ] + - location: 20 (just consumed gas: 0.035) + [ 1 + 1 ] + - location: 14 (just consumed gas: 0.055) + [ 1 + 1 ] + - location: 16 (just consumed gas: 0.010) + [ 1 ] + - location: 18 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 16 (just consumed gas: 0.035) + [ 1 + 1 + 1 ] + - location: 19 (just consumed gas: 0.035) + [ 2 + 1 ] + - location: 20 (just consumed gas: 0.010) + [ 1 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 25 (just consumed gas: 0.035) + [ 2 ] + - location: 20 (just consumed gas: 0.035) + [ 2 + 2 ] + - location: 14 (just consumed gas: 0.055) + [ 1 + 2 ] + - location: 16 (just consumed gas: 0.010) + [ 2 ] + - location: 18 (just consumed gas: 0.010) + [ 2 + 2 ] + - location: 16 (just consumed gas: 0.035) + [ 1 + 2 + 2 ] + - location: 19 (just consumed gas: 0.035) + [ 3 + 2 ] + - location: 20 (just consumed gas: 0.010) + [ 2 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 2 ] + - location: 25 (just consumed gas: 0.035) + [ 3 ] + - location: 20 (just consumed gas: 0.035) + [ 3 + 3 ] + - location: 14 (just consumed gas: 0.055) + [ 1 + 3 ] + - location: 16 (just consumed gas: 0.010) + [ 3 ] + - location: 18 (just consumed gas: 0.010) + [ 3 + 3 ] + - location: 16 (just consumed gas: 0.035) + [ 1 + 3 + 3 ] + - location: 19 (just consumed gas: 0.035) + [ 4 + 3 ] + - location: 20 (just consumed gas: 0.010) + [ 3 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 3 ] + - location: 25 (just consumed gas: 0.035) + [ 4 ] + - location: 20 (just consumed gas: 0.035) + [ 4 + 4 ] + - location: 14 (just consumed gas: 0.072) + [ { 1 ; 2 ; 3 ; 4 } + 4 ] + - location: 26 (just consumed gas: 0.010) + [ {} + { 1 ; 2 ; 3 ; 4 } + 4 ] + - location: 28 (just consumed gas: 0.010) + [ (Pair {} { 1 ; 2 ; 3 ; 4 }) + 4 ] + - location: 29 (just consumed gas: 0.010) + [ 4 ] + - location: 31 (just consumed gas: 0.010) + [ ] + - location: 29 (just consumed gas: 0.035) + [ (Pair {} { 1 ; 2 ; 3 ; 4 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input403499055-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input403499055-.out new file mode 100644 index 000000000000..c0e745a397ce --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input403499055-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_size.tz on storage 111 and input '{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }' --level 1 --trace-stack +storage + 6 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.886) + [ (Pair { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } ] + - location: 9 (just consumed gas: 0.010) + [ 6 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 6 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 6) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input457300675-.out new file mode 100644 index 000000000000..00f8d75d609e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input457300675-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_size.tz on storage 111 and input '{}' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.286) + [ (Pair {} 111) ] + - location: 8 (just consumed gas: 0.010) + [ {} ] + - location: 9 (just consumed gas: 0.010) + [ 0 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input469078912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input469078912-.out new file mode 100644 index 000000000000..2fb0a32ebcce --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input469078912-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_size.tz on storage 111 and input '{ 1 ; 2 ; 3 }' --level 1 --trace-stack +storage + 3 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.586) + [ (Pair { 1 ; 2 ; 3 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 } ] + - location: 9 (just consumed gas: 0.010) + [ 3 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 3 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 3) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input802622031-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input802622031-.out new file mode 100644 index 000000000000..9e60498d1b75 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -list_size--storage492856247--input802622031-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/list_size.tz on storage 111 and input '{ 1 }' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.386) + [ (Pair { 1 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 } ] + - location: 9 (just consumed gas: 0.010) + [ 1 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input457300675-.out new file mode 100644 index 000000000000..b8c89deeb2ae --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input457300675-.out @@ -0,0 +1,52 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/loop_left.tz on storage '{""}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 16.607) + [ (Pair {} { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ {} + {} ] + - location: 12 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} {}) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair {} {})) ] + - location: 41 (just consumed gas: 0.020) + [ (Pair {} {}) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} {}) + (Pair {} {}) ] + - location: 20 (just consumed gas: 0.010) + [ {} + (Pair {} {}) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} {}) ] + - location: 23 (just consumed gas: 0.010) + [ {} ] + - location: 21 (just consumed gas: 0.035) + [ {} + {} ] + - location: 24 (just consumed gas: 0.010) + [ {} ] + - location: 35 (just consumed gas: 0.010) + [ (Right {}) ] + - location: 24 (just consumed gas: 0.025) + [ (Right {}) ] + - location: 41 (just consumed gas: 0.035) + [ {} ] + - location: 41 (just consumed gas: 0.010) + [ {} + {} ] + - location: 43 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input851203613-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input851203613-.out new file mode 100644 index 000000000000..58e5dc6a5db4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -loop_left--storage528921618--input851203613-.out @@ -0,0 +1,163 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/loop_left.tz on storage '{""}' and input '{ "c" ; "b" ; "a" }' --level 1 --trace-stack +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 16.982) + [ (Pair { "c" ; "b" ; "a" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "c" ; "b" ; "a" } ] + - location: 12 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } + {} ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { "c" ; "b" ; "a" } {}) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair { "c" ; "b" ; "a" } {})) ] + - location: 41 (just consumed gas: 0.020) + [ (Pair { "c" ; "b" ; "a" } {}) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair { "c" ; "b" ; "a" } {}) + (Pair { "c" ; "b" ; "a" } {}) ] + - location: 20 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } + (Pair { "c" ; "b" ; "a" } {}) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair { "c" ; "b" ; "a" } {}) ] + - location: 23 (just consumed gas: 0.010) + [ {} ] + - location: 21 (just consumed gas: 0.035) + [ { "c" ; "b" ; "a" } + {} ] + - location: 24 (just consumed gas: 0.010) + [ "c" + { "b" ; "a" } + {} ] + - location: 26 (just consumed gas: 0.010) + [ { "b" ; "a" } + "c" + {} ] + - location: 27 (just consumed gas: 0.010) + [ "c" + {} ] + - location: 29 (just consumed gas: 0.010) + [ { "c" } ] + - location: 27 (just consumed gas: 0.035) + [ { "b" ; "a" } + { "c" } ] + - location: 30 (just consumed gas: 0.010) + [ (Pair { "b" ; "a" } { "c" }) ] + - location: 31 (just consumed gas: 0.010) + [ (Left (Pair { "b" ; "a" } { "c" })) ] + - location: 24 (just consumed gas: 0.025) + [ (Left (Pair { "b" ; "a" } { "c" })) ] + - location: 41 (just consumed gas: 0.025) + [ (Pair { "b" ; "a" } { "c" }) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair { "b" ; "a" } { "c" }) + (Pair { "b" ; "a" } { "c" }) ] + - location: 20 (just consumed gas: 0.010) + [ { "b" ; "a" } + (Pair { "b" ; "a" } { "c" }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair { "b" ; "a" } { "c" }) ] + - location: 23 (just consumed gas: 0.010) + [ { "c" } ] + - location: 21 (just consumed gas: 0.035) + [ { "b" ; "a" } + { "c" } ] + - location: 24 (just consumed gas: 0.010) + [ "b" + { "a" } + { "c" } ] + - location: 26 (just consumed gas: 0.010) + [ { "a" } + "b" + { "c" } ] + - location: 27 (just consumed gas: 0.010) + [ "b" + { "c" } ] + - location: 29 (just consumed gas: 0.010) + [ { "b" ; "c" } ] + - location: 27 (just consumed gas: 0.035) + [ { "a" } + { "b" ; "c" } ] + - location: 30 (just consumed gas: 0.010) + [ (Pair { "a" } { "b" ; "c" }) ] + - location: 31 (just consumed gas: 0.010) + [ (Left (Pair { "a" } { "b" ; "c" })) ] + - location: 24 (just consumed gas: 0.025) + [ (Left (Pair { "a" } { "b" ; "c" })) ] + - location: 41 (just consumed gas: 0.025) + [ (Pair { "a" } { "b" ; "c" }) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair { "a" } { "b" ; "c" }) + (Pair { "a" } { "b" ; "c" }) ] + - location: 20 (just consumed gas: 0.010) + [ { "a" } + (Pair { "a" } { "b" ; "c" }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair { "a" } { "b" ; "c" }) ] + - location: 23 (just consumed gas: 0.010) + [ { "b" ; "c" } ] + - location: 21 (just consumed gas: 0.035) + [ { "a" } + { "b" ; "c" } ] + - location: 24 (just consumed gas: 0.010) + [ "a" + {} + { "b" ; "c" } ] + - location: 26 (just consumed gas: 0.010) + [ {} + "a" + { "b" ; "c" } ] + - location: 27 (just consumed gas: 0.010) + [ "a" + { "b" ; "c" } ] + - location: 29 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 27 (just consumed gas: 0.035) + [ {} + { "a" ; "b" ; "c" } ] + - location: 30 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: 31 (just consumed gas: 0.010) + [ (Left (Pair {} { "a" ; "b" ; "c" })) ] + - location: 24 (just consumed gas: 0.025) + [ (Left (Pair {} { "a" ; "b" ; "c" })) ] + - location: 41 (just consumed gas: 0.025) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) + (Pair {} { "a" ; "b" ; "c" }) ] + - location: 20 (just consumed gas: 0.010) + [ {} + (Pair {} { "a" ; "b" ; "c" }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + - location: 23 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 21 (just consumed gas: 0.035) + [ {} + { "a" ; "b" ; "c" } ] + - location: 24 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 35 (just consumed gas: 0.010) + [ (Right { "a" ; "b" ; "c" }) ] + - location: 24 (just consumed gas: 0.025) + [ (Right { "a" ; "b" ; "c" }) ] + - location: 41 (just consumed gas: 0.035) + [ { "a" ; "b" ; "c" } ] + - location: 41 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 43 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsl_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsl_bytes--storage125992234--input125992234-.out new file mode 100644 index 000000000000..e37520accc1e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsl_bytes--storage125992234--input125992234-.out @@ -0,0 +1,93 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/lsl_bytes_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 35.762) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0 ] + - location: 11 (just consumed gas: 0.010) + [ 0x06 + 0 ] + - location: 14 (just consumed gas: 0.065) + [ 0x06 ] + - location: 15 (just consumed gas: 0.010) + [ 0x06 + 0x06 ] + - location: 20 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 1 ] + - location: 31 (just consumed gas: 0.010) + [ 0x06 + 1 ] + - location: 34 (just consumed gas: 0.065) + [ 0x000c ] + - location: 35 (just consumed gas: 0.010) + [ 0x000c + 0x000c ] + - location: 40 (just consumed gas: 0.035) + [ 0 ] + - location: 41 (just consumed gas: 0.010) + [ True ] + - location: 42 (just consumed gas: 0.010) + [ ] + - location: 42 (just consumed gas: 0.025) + [ ] + - location: 48 (just consumed gas: 0.010) + [ 8 ] + - location: 51 (just consumed gas: 0.010) + [ 0x06 + 8 ] + - location: 54 (just consumed gas: 0.065) + [ 0x0600 ] + - location: 55 (just consumed gas: 0.010) + [ 0x0600 + 0x0600 ] + - location: 60 (just consumed gas: 0.035) + [ 0 ] + - location: 61 (just consumed gas: 0.010) + [ True ] + - location: 62 (just consumed gas: 0.010) + [ ] + - location: 62 (just consumed gas: 0.025) + [ ] + - location: 68 (just consumed gas: 0.010) + [ 1 ] + - location: 71 (just consumed gas: 0.010) + [ 0x0006 + 1 ] + - location: 74 (just consumed gas: 0.066) + [ 0x00000c ] + - location: 75 (just consumed gas: 0.010) + [ 0x00000c + 0x00000c ] + - location: 80 (just consumed gas: 0.035) + [ 0 ] + - location: 81 (just consumed gas: 0.010) + [ True ] + - location: 82 (just consumed gas: 0.010) + [ ] + - location: 82 (just consumed gas: 0.025) + [ ] + - location: 88 (just consumed gas: 0.010) + [ Unit ] + - location: 89 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 91 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsr_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsr_bytes--storage125992234--input125992234-.out new file mode 100644 index 000000000000..bb91f6a9ccc2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -lsr_bytes--storage125992234--input125992234-.out @@ -0,0 +1,129 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/lsr_bytes_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 52.083) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 1 ] + - location: 11 (just consumed gas: 0.010) + [ 0x06 + 1 ] + - location: 14 (just consumed gas: 0.055) + [ 0x03 ] + - location: 15 (just consumed gas: 0.010) + [ 0x03 + 0x03 ] + - location: 20 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 8 ] + - location: 31 (just consumed gas: 0.010) + [ 0x06 + 8 ] + - location: 34 (just consumed gas: 0.055) + [ 0x ] + - location: 35 (just consumed gas: 0.010) + [ 0x + 0x ] + - location: 40 (just consumed gas: 0.035) + [ 0 ] + - location: 41 (just consumed gas: 0.010) + [ True ] + - location: 42 (just consumed gas: 0.010) + [ ] + - location: 42 (just consumed gas: 0.025) + [ ] + - location: 48 (just consumed gas: 0.010) + [ 1 ] + - location: 51 (just consumed gas: 0.010) + [ 0x0006 + 1 ] + - location: 54 (just consumed gas: 0.056) + [ 0x0003 ] + - location: 55 (just consumed gas: 0.010) + [ 0x0003 + 0x0003 ] + - location: 60 (just consumed gas: 0.035) + [ 0 ] + - location: 61 (just consumed gas: 0.010) + [ True ] + - location: 62 (just consumed gas: 0.010) + [ ] + - location: 62 (just consumed gas: 0.025) + [ ] + - location: 68 (just consumed gas: 0.010) + [ 8 ] + - location: 71 (just consumed gas: 0.010) + [ 0x0006 + 8 ] + - location: 74 (just consumed gas: 0.055) + [ 0x00 ] + - location: 75 (just consumed gas: 0.010) + [ 0x00 + 0x00 ] + - location: 80 (just consumed gas: 0.035) + [ 0 ] + - location: 81 (just consumed gas: 0.010) + [ True ] + - location: 82 (just consumed gas: 0.010) + [ ] + - location: 82 (just consumed gas: 0.025) + [ ] + - location: 88 (just consumed gas: 0.010) + [ 0 ] + - location: 91 (just consumed gas: 0.010) + [ 0x001234 + 0 ] + - location: 94 (just consumed gas: 0.056) + [ 0x001234 ] + - location: 95 (just consumed gas: 0.010) + [ 0x001234 + 0x001234 ] + - location: 100 (just consumed gas: 0.035) + [ 0 ] + - location: 101 (just consumed gas: 0.010) + [ True ] + - location: 102 (just consumed gas: 0.010) + [ ] + - location: 102 (just consumed gas: 0.025) + [ ] + - location: 108 (just consumed gas: 0.010) + [ 30 ] + - location: 111 (just consumed gas: 0.010) + [ 0x001234 + 30 ] + - location: 114 (just consumed gas: 0.055) + [ 0x ] + - location: 115 (just consumed gas: 0.010) + [ 0x + 0x ] + - location: 120 (just consumed gas: 0.035) + [ 0 ] + - location: 121 (just consumed gas: 0.010) + [ True ] + - location: 122 (just consumed gas: 0.010) + [ ] + - location: 122 (just consumed gas: 0.025) + [ ] + - location: 128 (just consumed gas: 0.010) + [ Unit ] + - location: 129 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 131 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input1027566226-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input1027566226-.out new file mode 100644 index 000000000000..f36ed2d95c7d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input1027566226-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_id.tz on storage '{}' and input '{ Elt 0 0 }' --level 1 --trace-stack +storage + { Elt 0 0 } +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 4.579) + [ (Pair { Elt 0 0 } {}) ] + - location: 11 (just consumed gas: 0.010) + [ { Elt 0 0 } ] + - location: 12 (just consumed gas: 0.010) + [ {} + { Elt 0 0 } ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} { Elt 0 0 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input276660554-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input276660554-.out new file mode 100644 index 000000000000..db72f167bc41 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input276660554-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_id.tz on storage '{}' and input '{ Elt 0 0 ; Elt 3 4 }' --level 1 --trace-stack +storage + { Elt 0 0 ; Elt 3 4 } +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 4.869) + [ (Pair { Elt 0 0 ; Elt 3 4 } {}) ] + - location: 11 (just consumed gas: 0.010) + [ { Elt 0 0 ; Elt 3 4 } ] + - location: 12 (just consumed gas: 0.010) + [ {} + { Elt 0 0 ; Elt 3 4 } ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} { Elt 0 0 ; Elt 3 4 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input599923743-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input599923743-.out new file mode 100644 index 000000000000..2e8cc649d7e1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_id--storage457300675--input599923743-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_id.tz on storage '{}' and input '{ Elt 0 1 }' --level 1 --trace-stack +storage + { Elt 0 1 } +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 4.579) + [ (Pair { Elt 0 1 } {}) ] + - location: 11 (just consumed gas: 0.010) + [ { Elt 0 1 } ] + - location: 12 (just consumed gas: 0.010) + [ {} + { Elt 0 1 } ] + - location: 14 (just consumed gas: 0.010) + [ (Pair {} { Elt 0 1 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input403579222-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input403579222-.out new file mode 100644 index 000000000000..3cd90120659b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input403579222-.out @@ -0,0 +1,152 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_iter.tz on storage '(Pair 0 0)' and input '{ Elt 1 1 ; Elt 2 100 }' --level 1 --trace-stack +storage + (Pair 3 101) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 18.332) + [ (Pair { Elt 1 1 ; Elt 2 100 } 0 0) ] + - location: 11 (just consumed gas: 0.010) + [ { Elt 1 1 ; Elt 2 100 } ] + - location: 12 (just consumed gas: 0.010) + [ 0 + { Elt 1 1 ; Elt 2 100 } ] + - location: 15 (just consumed gas: 0.010) + [ 0 + 0 + { Elt 1 1 ; Elt 2 100 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 0 0) + { Elt 1 1 ; Elt 2 100 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 1 ; Elt 2 100 } + (Pair 0 0) ] + - location: 20 (just consumed gas: 0.075) + [ (Pair 1 1) + (Pair 0 0) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 0 0) + (Pair 0 0) ] + - location: 25 (just consumed gas: 0.010) + [ 0 + (Pair 0 0) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 28 (just consumed gas: 0.010) + [ 0 ] + - location: 26 (just consumed gas: 0.035) + [ 0 + 0 ] + - location: 22 (just consumed gas: 0.035) + [ (Pair 1 1) + 0 + 0 ] + - location: 29 (just consumed gas: 0.010) + [ (Pair 1 1) + (Pair 1 1) + 0 + 0 ] + - location: 30 (just consumed gas: 0.010) + [ (Pair 1 1) + 0 + 0 ] + - location: 32 (just consumed gas: 0.010) + [ 1 + 0 + 0 ] + - location: 33 (just consumed gas: 0.035) + [ 1 + 0 ] + - location: 30 (just consumed gas: 0.035) + [ (Pair 1 1) + 1 + 0 ] + - location: 34 (just consumed gas: 0.010) + [ 1 + (Pair 1 1) + 0 ] + - location: 35 (just consumed gas: 0.010) + [ (Pair 1 1) + 0 ] + - location: 37 (just consumed gas: 0.010) + [ 1 + 0 ] + - location: 38 (just consumed gas: 0.035) + [ 1 ] + - location: 35 (just consumed gas: 0.035) + [ 1 + 1 ] + - location: 39 (just consumed gas: 0.010) + [ (Pair 1 1) ] + - location: 20 (just consumed gas: 0.025) + [ (Pair 2 100) + (Pair 1 1) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair 1 1) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 1 1) + (Pair 1 1) ] + - location: 25 (just consumed gas: 0.010) + [ 1 + (Pair 1 1) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair 1 1) ] + - location: 28 (just consumed gas: 0.010) + [ 1 ] + - location: 26 (just consumed gas: 0.035) + [ 1 + 1 ] + - location: 22 (just consumed gas: 0.035) + [ (Pair 2 100) + 1 + 1 ] + - location: 29 (just consumed gas: 0.010) + [ (Pair 2 100) + (Pair 2 100) + 1 + 1 ] + - location: 30 (just consumed gas: 0.010) + [ (Pair 2 100) + 1 + 1 ] + - location: 32 (just consumed gas: 0.010) + [ 2 + 1 + 1 ] + - location: 33 (just consumed gas: 0.035) + [ 3 + 1 ] + - location: 30 (just consumed gas: 0.035) + [ (Pair 2 100) + 3 + 1 ] + - location: 34 (just consumed gas: 0.010) + [ 3 + (Pair 2 100) + 1 ] + - location: 35 (just consumed gas: 0.010) + [ (Pair 2 100) + 1 ] + - location: 37 (just consumed gas: 0.010) + [ 100 + 1 ] + - location: 38 (just consumed gas: 0.035) + [ 101 ] + - location: 35 (just consumed gas: 0.035) + [ 3 + 101 ] + - location: 39 (just consumed gas: 0.010) + [ (Pair 3 101) ] + - location: 20 (just consumed gas: 0.035) + [ (Pair 3 101) ] + - location: 40 (just consumed gas: 0.010) + [ {} + (Pair 3 101) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair {} 3 101) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input532072758-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input532072758-.out new file mode 100644 index 000000000000..59e98bc36c56 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_iter--storage1011138251--input532072758-.out @@ -0,0 +1,152 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_iter.tz on storage '(Pair 0 0)' and input '{ Elt 0 100 ; Elt 2 100 }' --level 1 --trace-stack +storage + (Pair 2 200) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 18.332) + [ (Pair { Elt 0 100 ; Elt 2 100 } 0 0) ] + - location: 11 (just consumed gas: 0.010) + [ { Elt 0 100 ; Elt 2 100 } ] + - location: 12 (just consumed gas: 0.010) + [ 0 + { Elt 0 100 ; Elt 2 100 } ] + - location: 15 (just consumed gas: 0.010) + [ 0 + 0 + { Elt 0 100 ; Elt 2 100 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 0 0) + { Elt 0 100 ; Elt 2 100 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 0 100 ; Elt 2 100 } + (Pair 0 0) ] + - location: 20 (just consumed gas: 0.075) + [ (Pair 0 100) + (Pair 0 0) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 0 0) + (Pair 0 0) ] + - location: 25 (just consumed gas: 0.010) + [ 0 + (Pair 0 0) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 28 (just consumed gas: 0.010) + [ 0 ] + - location: 26 (just consumed gas: 0.035) + [ 0 + 0 ] + - location: 22 (just consumed gas: 0.035) + [ (Pair 0 100) + 0 + 0 ] + - location: 29 (just consumed gas: 0.010) + [ (Pair 0 100) + (Pair 0 100) + 0 + 0 ] + - location: 30 (just consumed gas: 0.010) + [ (Pair 0 100) + 0 + 0 ] + - location: 32 (just consumed gas: 0.010) + [ 0 + 0 + 0 ] + - location: 33 (just consumed gas: 0.035) + [ 0 + 0 ] + - location: 30 (just consumed gas: 0.035) + [ (Pair 0 100) + 0 + 0 ] + - location: 34 (just consumed gas: 0.010) + [ 0 + (Pair 0 100) + 0 ] + - location: 35 (just consumed gas: 0.010) + [ (Pair 0 100) + 0 ] + - location: 37 (just consumed gas: 0.010) + [ 100 + 0 ] + - location: 38 (just consumed gas: 0.035) + [ 100 ] + - location: 35 (just consumed gas: 0.035) + [ 0 + 100 ] + - location: 39 (just consumed gas: 0.010) + [ (Pair 0 100) ] + - location: 20 (just consumed gas: 0.025) + [ (Pair 2 100) + (Pair 0 100) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair 0 100) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 0 100) + (Pair 0 100) ] + - location: 25 (just consumed gas: 0.010) + [ 0 + (Pair 0 100) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair 0 100) ] + - location: 28 (just consumed gas: 0.010) + [ 100 ] + - location: 26 (just consumed gas: 0.035) + [ 0 + 100 ] + - location: 22 (just consumed gas: 0.035) + [ (Pair 2 100) + 0 + 100 ] + - location: 29 (just consumed gas: 0.010) + [ (Pair 2 100) + (Pair 2 100) + 0 + 100 ] + - location: 30 (just consumed gas: 0.010) + [ (Pair 2 100) + 0 + 100 ] + - location: 32 (just consumed gas: 0.010) + [ 2 + 0 + 100 ] + - location: 33 (just consumed gas: 0.035) + [ 2 + 100 ] + - location: 30 (just consumed gas: 0.035) + [ (Pair 2 100) + 2 + 100 ] + - location: 34 (just consumed gas: 0.010) + [ 2 + (Pair 2 100) + 100 ] + - location: 35 (just consumed gas: 0.010) + [ (Pair 2 100) + 100 ] + - location: 37 (just consumed gas: 0.010) + [ 100 + 100 ] + - location: 38 (just consumed gas: 0.035) + [ 200 ] + - location: 35 (just consumed gas: 0.035) + [ 2 + 200 ] + - location: 39 (just consumed gas: 0.010) + [ (Pair 2 200) ] + - location: 20 (just consumed gas: 0.035) + [ (Pair 2 200) ] + - location: 40 (just consumed gas: 0.010) + [ {} + (Pair 2 200) ] + - location: 42 (just consumed gas: 0.010) + [ (Pair {} 2 200) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage457300675--input798141440-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage457300675--input798141440-.out new file mode 100644 index 000000000000..dc233fa3e93e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage457300675--input798141440-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_map.tz on storage '{}' and input 10 --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 9.038) + [ (Pair 10 {}) ] + - location: 9 (just consumed gas: 0.010) + [ 10 + {} ] + - location: 10 (just consumed gas: 0.010) + [ {} + 10 ] + - location: 11 (just consumed gas: 0.060) + [ {} + 10 ] + - location: 18 (just consumed gas: 0.010) + [ 10 ] + - location: 20 (just consumed gas: 0.010) + [ ] + - location: 18 (just consumed gas: 0.035) + [ {} ] + - location: 21 (just consumed gas: 0.010) + [ {} + {} ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage794999348--input152441147-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage794999348--input152441147-.out new file mode 100644 index 000000000000..6fd2b5a795c3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage794999348--input152441147-.out @@ -0,0 +1,68 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_map.tz on storage '{ Elt "bar" 5 ; Elt "foo" 1 }' and input 15 --level 1 --trace-stack +storage + { Elt "bar" 20 ; Elt "foo" 16 } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 9.673) + [ (Pair 15 { Elt "bar" 5 ; Elt "foo" 1 }) ] + - location: 9 (just consumed gas: 0.010) + [ 15 + { Elt "bar" 5 ; Elt "foo" 1 } ] + - location: 10 (just consumed gas: 0.010) + [ { Elt "bar" 5 ; Elt "foo" 1 } + 15 ] + - location: 11 (just consumed gas: 0.067) + [ (Pair "bar" 5) + 15 ] + - location: 13 (just consumed gas: 0.010) + [ 5 + 15 ] + - location: 14 (just consumed gas: 0.010) + [ 15 ] + - location: 16 (just consumed gas: 0.010) + [ 15 + 15 ] + - location: 14 (just consumed gas: 0.035) + [ 5 + 15 + 15 ] + - location: 17 (just consumed gas: 0.035) + [ 20 + 15 ] + - location: 11 (just consumed gas: 0.150) + [ (Pair "foo" 1) + 15 ] + - location: 13 (just consumed gas: 0.010) + [ 1 + 15 ] + - location: 14 (just consumed gas: 0.010) + [ 15 ] + - location: 16 (just consumed gas: 0.010) + [ 15 + 15 ] + - location: 14 (just consumed gas: 0.035) + [ 1 + 15 + 15 ] + - location: 17 (just consumed gas: 0.035) + [ 16 + 15 ] + - location: 11 (just consumed gas: 0.160) + [ { Elt "bar" 20 ; Elt "foo" 16 } + 15 ] + - location: 18 (just consumed gas: 0.010) + [ 15 ] + - location: 20 (just consumed gas: 0.010) + [ ] + - location: 18 (just consumed gas: 0.035) + [ { Elt "bar" 20 ; Elt "foo" 16 } ] + - location: 21 (just consumed gas: 0.010) + [ {} + { Elt "bar" 20 ; Elt "foo" 16 } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 20 ; Elt "foo" 16 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage88008216--input798141440-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage88008216--input798141440-.out new file mode 100644 index 000000000000..5974a05936fd --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_map--storage88008216--input798141440-.out @@ -0,0 +1,50 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_map.tz on storage '{ Elt "foo" 1 }' and input 10 --level 1 --trace-stack +storage + { Elt "foo" 11 } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 9.338) + [ (Pair 10 { Elt "foo" 1 }) ] + - location: 9 (just consumed gas: 0.010) + [ 10 + { Elt "foo" 1 } ] + - location: 10 (just consumed gas: 0.010) + [ { Elt "foo" 1 } + 10 ] + - location: 11 (just consumed gas: 0.058) + [ (Pair "foo" 1) + 10 ] + - location: 13 (just consumed gas: 0.010) + [ 1 + 10 ] + - location: 14 (just consumed gas: 0.010) + [ 10 ] + - location: 16 (just consumed gas: 0.010) + [ 10 + 10 ] + - location: 14 (just consumed gas: 0.035) + [ 1 + 10 + 10 ] + - location: 17 (just consumed gas: 0.035) + [ 11 + 10 ] + - location: 11 (just consumed gas: 0.160) + [ { Elt "foo" 11 } + 10 ] + - location: 18 (just consumed gas: 0.010) + [ 10 ] + - location: 20 (just consumed gas: 0.010) + [ ] + - location: 18 (just consumed gas: 0.035) + [ { Elt "foo" 11 } ] + - location: 21 (just consumed gas: 0.010) + [ {} + { Elt "foo" 11 } ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "foo" 11 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage495706788--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage495706788--input453441034-.out new file mode 100644 index 000000000000..f305861b5f55 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage495706788--input453441034-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_nat.tz on storage '(Pair {} None)' and input 1 --level 1 --trace-stack +storage + (Pair {} (Some False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.144) + [ (Pair 1 {} None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair {} None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} None) ] + - location: 15 (just consumed gas: 0.010) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.035) + [ 1 + {} + {} ] + - location: 17 (just consumed gas: 0.045) + [ False + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + {} ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair {} (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input453441034-.out new file mode 100644 index 000000000000..c195dca62987 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input453441034-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_nat.tz on storage '(Pair { Elt 1 4 ; Elt 2 11 } None)' and input 1 --level 1 --trace-stack +storage + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.689) + [ (Pair 1 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (just consumed gas: 0.035) + [ 1 + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (just consumed gas: 0.045) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input564400327-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input564400327-.out new file mode 100644 index 000000000000..7d1785b8bc53 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input564400327-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_nat.tz on storage '(Pair { Elt 1 4 ; Elt 2 11 } None)' and input 2 --level 1 --trace-stack +storage + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.689) + [ (Pair 2 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 2 + (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (just consumed gas: 0.035) + [ 2 + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (just consumed gas: 0.045) + [ True + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input654274102-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input654274102-.out new file mode 100644 index 000000000000..db4f3b99baeb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage56274299--input654274102-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_nat.tz on storage '(Pair { Elt 1 4 ; Elt 2 11 } None)' and input 3 --level 1 --trace-stack +storage + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.689) + [ (Pair 3 { Elt 1 4 ; Elt 2 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 3 + (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 13 (just consumed gas: 0.035) + [ 3 + { Elt 1 4 ; Elt 2 11 } + { Elt 1 4 ; Elt 2 11 } ] + - location: 17 (just consumed gas: 0.045) + [ False + { Elt 1 4 ; Elt 2 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt 1 4 ; Elt 2 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 4 ; Elt 2 11 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 4 ; Elt 2 11 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 4 ; Elt 2 11 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage690637660--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage690637660--input453441034-.out new file mode 100644 index 000000000000..6aa7c8f9e216 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage690637660--input453441034-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_nat.tz on storage '(Pair { Elt 1 0 } None)' and input 1 --level 1 --trace-stack +storage + (Pair { Elt 1 0 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.399) + [ (Pair 1 { Elt 1 0 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair { Elt 1 0 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 1 0 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 1 0 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 1 0 } + { Elt 1 0 } ] + - location: 13 (just consumed gas: 0.035) + [ 1 + { Elt 1 0 } + { Elt 1 0 } ] + - location: 17 (just consumed gas: 0.045) + [ True + { Elt 1 0 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt 1 0 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 1 0 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 1 0 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 1 0 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 1 0 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage806237530--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage806237530--input453441034-.out new file mode 100644 index 000000000000..157b6d76b307 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_nat--storage806237530--input453441034-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_nat.tz on storage '(Pair { Elt 0 1 } None)' and input 1 --level 1 --trace-stack +storage + (Pair { Elt 0 1 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.399) + [ (Pair 1 { Elt 0 1 } None) ] + - location: 12 (just consumed gas: 0.010) + [ 1 + (Pair { Elt 0 1 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt 0 1 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt 0 1 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt 0 1 } + { Elt 0 1 } ] + - location: 13 (just consumed gas: 0.035) + [ 1 + { Elt 0 1 } + { Elt 0 1 } ] + - location: 17 (just consumed gas: 0.045) + [ False + { Elt 0 1 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt 0 1 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt 0 1 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt 0 1 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt 0 1 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt 0 1 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input1071610051-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input1071610051-.out new file mode 100644 index 000000000000..4e267bd79de2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input1071610051-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_string.tz on storage '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)' and input '"baz"' --level 1 --trace-stack +storage + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.824) + [ (Pair "baz" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "baz" + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (just consumed gas: 0.035) + [ "baz" + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (just consumed gas: 0.045) + [ False + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input700475845-.out new file mode 100644 index 000000000000..bfe7d7a6e070 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input700475845-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_string.tz on storage '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)' and input '"bar"' --level 1 --trace-stack +storage + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.824) + [ (Pair "bar" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "bar" + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (just consumed gas: 0.035) + [ "bar" + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (just consumed gas: 0.045) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input905318451-.out new file mode 100644 index 000000000000..9d3c3ceb87d4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage109689253--input905318451-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_string.tz on storage '(Pair { Elt "bar" 4 ; Elt "foo" 11 } None)' and input '"foo"' --level 1 --trace-stack +storage + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.824) + [ (Pair "foo" { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "foo" + (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 13 (just consumed gas: 0.035) + [ "foo" + { Elt "bar" 4 ; Elt "foo" 11 } + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 17 (just consumed gas: 0.045) + [ True + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt "bar" 4 ; Elt "foo" 11 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "bar" 4 ; Elt "foo" 11 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 4 ; Elt "foo" 11 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage495706788--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage495706788--input700475845-.out new file mode 100644 index 000000000000..db92bf0b50a3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage495706788--input700475845-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_string.tz on storage '(Pair {} None)' and input '"bar"' --level 1 --trace-stack +storage + (Pair {} (Some False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.189) + [ (Pair "bar" {} None) ] + - location: 12 (just consumed gas: 0.010) + [ "bar" + (Pair {} None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} None) ] + - location: 15 (just consumed gas: 0.010) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.035) + [ "bar" + {} + {} ] + - location: 17 (just consumed gas: 0.045) + [ False + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + {} ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair {} (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage915708427--input700475845-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage915708427--input700475845-.out new file mode 100644 index 000000000000..d910f35dc342 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage915708427--input700475845-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_string.tz on storage '(Pair { Elt "foo" 1 } None)' and input '"bar"' --level 1 --trace-stack +storage + (Pair { Elt "foo" 1 } (Some False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.489) + [ (Pair "bar" { Elt "foo" 1 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "bar" + (Pair { Elt "foo" 1 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 1 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "foo" 1 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 13 (just consumed gas: 0.035) + [ "bar" + { Elt "foo" 1 } + { Elt "foo" 1 } ] + - location: 17 (just consumed gas: 0.045) + [ False + { Elt "foo" 1 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some False) + { Elt "foo" 1 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "foo" 1 } + (Some False) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 1 } (Some False)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "foo" 1 } (Some False)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "foo" 1 } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage936682951--input905318451-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage936682951--input905318451-.out new file mode 100644 index 000000000000..d9751ea063ba --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_mem_string--storage936682951--input905318451-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_mem_string.tz on storage '(Pair { Elt "foo" 0 } None)' and input '"foo"' --level 1 --trace-stack +storage + (Pair { Elt "foo" 0 } (Some True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 9.489) + [ (Pair "foo" { Elt "foo" 0 } None) ] + - location: 12 (just consumed gas: 0.010) + [ "foo" + (Pair { Elt "foo" 0 } None) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 0 } None) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "foo" 0 } ] + - location: 16 (just consumed gas: 0.010) + [ { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 13 (just consumed gas: 0.035) + [ "foo" + { Elt "foo" 0 } + { Elt "foo" 0 } ] + - location: 17 (just consumed gas: 0.045) + [ True + { Elt "foo" 0 } ] + - location: 18 (just consumed gas: 0.010) + [ (Some True) + { Elt "foo" 0 } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "foo" 0 } + (Some True) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 0 } (Some True)) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair { Elt "foo" 0 } (Some True)) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} { Elt "foo" 0 } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input15265129-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input15265129-.out new file mode 100644 index 000000000000..c63a80795155 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input15265129-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_size.tz on storage 111 and input '{ Elt "a" 1 }' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.695) + [ (Pair { Elt "a" 1 } 111) ] + - location: 9 (just consumed gas: 0.010) + [ { Elt "a" 1 } ] + - location: 10 (just consumed gas: 0.010) + [ 1 ] + - location: 11 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input158311065-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input158311065-.out new file mode 100644 index 000000000000..de1b59f783d4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input158311065-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_size.tz on storage 111 and input '{ Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 }' --level 1 --trace-stack +storage + 3 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 5.325) + [ (Pair { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 } 111) ] + - location: 9 (just consumed gas: 0.010) + [ { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 } ] + - location: 10 (just consumed gas: 0.010) + [ 3 ] + - location: 11 (just consumed gas: 0.010) + [ {} + 3 ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} 3) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input456982702-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input456982702-.out new file mode 100644 index 000000000000..e96ed8ad27c8 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input456982702-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_size.tz on storage 111 and input '{ Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 }' --level 1 --trace-stack +storage + 6 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.270) + [ (Pair { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 } 111) ] + - location: 9 (just consumed gas: 0.010) + [ { Elt "a" 1 ; Elt "b" 2 ; Elt "c" 3 ; Elt "d" 4 ; Elt "e" 5 ; Elt "f" 6 } ] + - location: 10 (just consumed gas: 0.010) + [ 6 ] + - location: 11 (just consumed gas: 0.010) + [ {} + 6 ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} 6) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input457300675-.out new file mode 100644 index 000000000000..0e33c820a242 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -map_size--storage492856247--input457300675-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/map_size.tz on storage 111 and input '{}' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.415) + [ (Pair {} 111) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ 0 ] + - location: 11 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mul--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mul--storage125992234--input125992234-.out new file mode 100644 index 000000000000..382da0ae6e08 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mul--storage125992234--input125992234-.out @@ -0,0 +1,131 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/mul.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 50.763) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ Unit ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.010) + [ 7987 ] + - location: 12 (just consumed gas: 0.010) + [ 10 + 7987 ] + - location: 15 (just consumed gas: 0.050) + [ 79870 ] + - location: 16 (just consumed gas: 0.010) + [ 79870 + 79870 ] + - location: 19 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 10 ] + - location: 31 (just consumed gas: 0.010) + [ 7987 + 10 ] + - location: 34 (just consumed gas: 0.050) + [ 79870 ] + - location: 35 (just consumed gas: 0.010) + [ 79870 + 79870 ] + - location: 38 (just consumed gas: 0.035) + [ 0 ] + - location: 40 (just consumed gas: 0.010) + [ True ] + - location: 41 (just consumed gas: 0.010) + [ ] + - location: 41 (just consumed gas: 0.025) + [ ] + - location: 47 (just consumed gas: 0.010) + [ 10 ] + - location: 50 (just consumed gas: 0.010) + [ -7987 + 10 ] + - location: 53 (just consumed gas: 0.064) + [ -79870 ] + - location: 54 (just consumed gas: 0.010) + [ -79870 + -79870 ] + - location: 57 (just consumed gas: 0.035) + [ 0 ] + - location: 59 (just consumed gas: 0.010) + [ True ] + - location: 60 (just consumed gas: 0.010) + [ ] + - location: 60 (just consumed gas: 0.025) + [ ] + - location: 66 (just consumed gas: 0.010) + [ 10 ] + - location: 69 (just consumed gas: 0.010) + [ -7987 + 10 ] + - location: 72 (just consumed gas: 0.064) + [ -79870 ] + - location: 73 (just consumed gas: 0.010) + [ -79870 + -79870 ] + - location: 76 (just consumed gas: 0.035) + [ 0 ] + - location: 78 (just consumed gas: 0.010) + [ True ] + - location: 79 (just consumed gas: 0.010) + [ ] + - location: 79 (just consumed gas: 0.025) + [ ] + - location: 85 (just consumed gas: 0.010) + [ -10 ] + - location: 88 (just consumed gas: 0.010) + [ 7987 + -10 ] + - location: 91 (just consumed gas: 0.064) + [ -79870 ] + - location: 92 (just consumed gas: 0.010) + [ -79870 + -79870 ] + - location: 95 (just consumed gas: 0.035) + [ 0 ] + - location: 97 (just consumed gas: 0.010) + [ True ] + - location: 98 (just consumed gas: 0.010) + [ ] + - location: 98 (just consumed gas: 0.025) + [ ] + - location: 104 (just consumed gas: 0.010) + [ 10 ] + - location: 107 (just consumed gas: 0.010) + [ 7987 + 10 ] + - location: 110 (just consumed gas: 0.064) + [ 79870 ] + - location: 111 (just consumed gas: 0.010) + [ 79870 + 79870 ] + - location: 114 (just consumed gas: 0.035) + [ 0 ] + - location: 116 (just consumed gas: 0.010) + [ True ] + - location: 117 (just consumed gas: 0.010) + [ ] + - location: 117 (just consumed gas: 0.025) + [ ] + - location: 123 (just consumed gas: 0.010) + [ Unit ] + - location: 124 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 126 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out new file mode 100644 index 000000000000..f10c4e53ea4b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage151303925--input216277421-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/mutez_to_bls12_381_fr.tz on storage 0x00 and input 257 --level 1 --trace-stack +storage + 0x0101000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 10.761) + [ (Pair 257 0x0000000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 257 ] + - location: 8 (just consumed gas: 0.010) + [ 1 + 257 ] + - location: 11 (just consumed gas: 0.010) + [ 257 + 1 ] + - location: 12 (just consumed gas: 0.080) + [ (Some (Pair 257 0)) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair 257 0) ] + - location: 14 (just consumed gas: 0.025) + [ (Pair 257 0) ] + - location: 20 (just consumed gas: 0.010) + [ 257 ] + - location: 21 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 257 ] + - location: 24 (just consumed gas: 0.267) + [ 0x0101000000000000000000000000000000000000000000000000000000000000 ] + - location: 25 (just consumed gas: 0.010) + [ {} + 0x0101000000000000000000000000000000000000000000000000000000000000 ] + - location: 27 (just consumed gas: 0.010) + [ (Pair {} 0x0101000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out new file mode 100644 index 000000000000..29e4c1387ce5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -mutez_to_bls12_381_fr--storage287799761--input485842614-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/mutez_to_bls12_381_fr.tz on storage 0x02 and input 16 --level 1 --trace-stack +storage + 0x1000000000000000000000000000000000000000000000000000000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 10.761) + [ (Pair 16 0x0200000000000000000000000000000000000000000000000000000000000000) ] + - location: 7 (just consumed gas: 0.010) + [ 16 ] + - location: 8 (just consumed gas: 0.010) + [ 1 + 16 ] + - location: 11 (just consumed gas: 0.010) + [ 16 + 1 ] + - location: 12 (just consumed gas: 0.080) + [ (Some (Pair 16 0)) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair 16 0) ] + - location: 14 (just consumed gas: 0.025) + [ (Pair 16 0) ] + - location: 20 (just consumed gas: 0.010) + [ 16 ] + - location: 21 (just consumed gas: 0.010) + [ 0x0100000000000000000000000000000000000000000000000000000000000000 + 16 ] + - location: 24 (just consumed gas: 0.266) + [ 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 25 (just consumed gas: 0.010) + [ {} + 0x1000000000000000000000000000000000000000000000000000000000000000 ] + - location: 27 (just consumed gas: 0.010) + [ (Pair {} 0x1000000000000000000000000000000000000000000000000000000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input1067298059-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input1067298059-.out new file mode 100644 index 000000000000..80cef50b1634 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input1067298059-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/neg.tz on storage 0 and input '(Left -2)' --level 1 --trace-stack +storage + 2 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.063) + [ (Pair (Left -2) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Left -2) ] + - location: 10 (just consumed gas: 0.010) + [ -2 ] + - location: 12 (just consumed gas: 0.025) + [ 2 ] + - location: 10 (just consumed gas: 0.025) + [ 2 ] + - location: 15 (just consumed gas: 0.010) + [ {} + 2 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair {} 2) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input380029349-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input380029349-.out new file mode 100644 index 000000000000..3258010269c5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input380029349-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/neg.tz on storage 0 and input '(Right 2)' --level 1 --trace-stack +storage + -2 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.063) + [ (Pair (Right 2) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Right 2) ] + - location: 10 (just consumed gas: 0.010) + [ 2 ] + - location: 14 (just consumed gas: 0.025) + [ -2 ] + - location: 10 (just consumed gas: 0.025) + [ -2 ] + - location: 15 (just consumed gas: 0.010) + [ {} + -2 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair {} -2) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input563503226-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input563503226-.out new file mode 100644 index 000000000000..236cd6e16acf --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input563503226-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/neg.tz on storage 0 and input '(Left 2)' --level 1 --trace-stack +storage + -2 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.063) + [ (Pair (Left 2) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Left 2) ] + - location: 10 (just consumed gas: 0.010) + [ 2 ] + - location: 12 (just consumed gas: 0.025) + [ -2 ] + - location: 10 (just consumed gas: 0.025) + [ -2 ] + - location: 15 (just consumed gas: 0.010) + [ {} + -2 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair {} -2) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input788662499-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input788662499-.out new file mode 100644 index 000000000000..6ab922f40c0a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input788662499-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/neg.tz on storage 0 and input '(Right 0)' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.063) + [ (Pair (Right 0) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Right 0) ] + - location: 10 (just consumed gas: 0.010) + [ 0 ] + - location: 14 (just consumed gas: 0.025) + [ 0 ] + - location: 10 (just consumed gas: 0.025) + [ 0 ] + - location: 15 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input972832189-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input972832189-.out new file mode 100644 index 000000000000..5e9b7feb0234 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -neg--storage680650890--input972832189-.out @@ -0,0 +1,25 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/neg.tz on storage 0 and input '(Left 0)' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.063) + [ (Pair (Left 0) 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Left 0) ] + - location: 10 (just consumed gas: 0.010) + [ 0 ] + - location: 12 (just consumed gas: 0.025) + [ 0 ] + - location: 10 (just consumed gas: 0.025) + [ 0 ] + - location: 15 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -none--storage11179311--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -none--storage11179311--input125992234-.out new file mode 100644 index 000000000000..03558b87a752 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -none--storage11179311--input125992234-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/none.tz on storage 'Some 10' and input Unit --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.627) + [ (Pair Unit (Some 10)) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.010) + [ None ] + - location: 11 (just consumed gas: 0.010) + [ {} + None ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input570553153-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input570553153-.out new file mode 100644 index 000000000000..6e50146e5acb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input570553153-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not.tz on storage None and input False --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair False None) ] + - location: 8 (just consumed gas: 0.010) + [ False ] + - location: 9 (just consumed gas: 0.010) + [ True ] + - location: 10 (just consumed gas: 0.010) + [ (Some True) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input954397288-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input954397288-.out new file mode 100644 index 000000000000..d9849c8306a3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not--storage921624073--input954397288-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not.tz on storage None and input True --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair True None) ] + - location: 8 (just consumed gas: 0.010) + [ True ] + - location: 9 (just consumed gas: 0.010) + [ False ] + - location: 10 (just consumed gas: 0.010) + [ (Some False) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input1051197453-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input1051197453-.out new file mode 100644 index 000000000000..f88a58336bfc --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input1051197453-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Right 8)' --level 1 --trace-stack +storage + (Some -9) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Right 8) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Right 8) ] + - location: 11 (just consumed gas: 0.010) + [ 8 ] + - location: 15 (just consumed gas: 0.025) + [ -9 ] + - location: 11 (just consumed gas: 0.025) + [ -9 ] + - location: 16 (just consumed gas: 0.010) + [ (Some -9) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some -9) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some -9)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input123939249-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input123939249-.out new file mode 100644 index 000000000000..ef20ff6d5c69 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input123939249-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Left 7)' --level 1 --trace-stack +storage + (Some -8) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Left 7) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Left 7) ] + - location: 11 (just consumed gas: 0.010) + [ 7 ] + - location: 13 (just consumed gas: 0.025) + [ -8 ] + - location: 11 (just consumed gas: 0.025) + [ -8 ] + - location: 16 (just consumed gas: 0.010) + [ (Some -8) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some -8) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some -8)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input24243730-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input24243730-.out new file mode 100644 index 000000000000..52d5f2fd62fd --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input24243730-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Left -8)' --level 1 --trace-stack +storage + (Some 7) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Left -8) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Left -8) ] + - location: 11 (just consumed gas: 0.010) + [ -8 ] + - location: 13 (just consumed gas: 0.025) + [ 7 ] + - location: 11 (just consumed gas: 0.025) + [ 7 ] + - location: 16 (just consumed gas: 0.010) + [ (Some 7) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some 7) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some 7)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input518945720-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input518945720-.out new file mode 100644 index 000000000000..7bfeaa632b95 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input518945720-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Left 8)' --level 1 --trace-stack +storage + (Some -9) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Left 8) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Left 8) ] + - location: 11 (just consumed gas: 0.010) + [ 8 ] + - location: 13 (just consumed gas: 0.025) + [ -9 ] + - location: 11 (just consumed gas: 0.025) + [ -9 ] + - location: 16 (just consumed gas: 0.010) + [ (Some -9) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some -9) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some -9)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input788662499-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input788662499-.out new file mode 100644 index 000000000000..543d89d1c037 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input788662499-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Right 0)' --level 1 --trace-stack +storage + (Some -1) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Right 0) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Right 0) ] + - location: 11 (just consumed gas: 0.010) + [ 0 ] + - location: 15 (just consumed gas: 0.025) + [ -1 ] + - location: 11 (just consumed gas: 0.025) + [ -1 ] + - location: 16 (just consumed gas: 0.010) + [ (Some -1) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some -1) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some -1)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input906118781-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input906118781-.out new file mode 100644 index 000000000000..82b400d153f9 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input906118781-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Right 7)' --level 1 --trace-stack +storage + (Some -8) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Right 7) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Right 7) ] + - location: 11 (just consumed gas: 0.010) + [ 7 ] + - location: 15 (just consumed gas: 0.025) + [ -8 ] + - location: 11 (just consumed gas: 0.025) + [ -8 ] + - location: 16 (just consumed gas: 0.010) + [ (Some -8) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some -8) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some -8)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input921874253-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input921874253-.out new file mode 100644 index 000000000000..8b864832a400 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input921874253-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Left -9)' --level 1 --trace-stack +storage + (Some 8) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Left -9) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Left -9) ] + - location: 11 (just consumed gas: 0.010) + [ -9 ] + - location: 13 (just consumed gas: 0.025) + [ 8 ] + - location: 11 (just consumed gas: 0.025) + [ 8 ] + - location: 16 (just consumed gas: 0.010) + [ (Some 8) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some 8) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some 8)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input972832189-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input972832189-.out new file mode 100644 index 000000000000..74ae43dccd20 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_binary--storage921624073--input972832189-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_binary.tz on storage None and input '(Left 0)' --level 1 --trace-stack +storage + (Some -1) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 6.822) + [ (Pair (Left 0) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Left 0) ] + - location: 11 (just consumed gas: 0.010) + [ 0 ] + - location: 13 (just consumed gas: 0.025) + [ -1 ] + - location: 11 (just consumed gas: 0.025) + [ -1 ] + - location: 16 (just consumed gas: 0.010) + [ (Some -1) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some -1) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some -1)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_bytes--storage125992234--input125992234-.out new file mode 100644 index 000000000000..67f48771810c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -not_bytes--storage125992234--input125992234-.out @@ -0,0 +1,66 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/not_bytes_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 24.963) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0x05 ] + - location: 11 (just consumed gas: 0.030) + [ 0xfa ] + - location: 12 (just consumed gas: 0.010) + [ 0xfa + 0xfa ] + - location: 17 (just consumed gas: 0.035) + [ 0 ] + - location: 18 (just consumed gas: 0.010) + [ True ] + - location: 19 (just consumed gas: 0.010) + [ ] + - location: 19 (just consumed gas: 0.025) + [ ] + - location: 25 (just consumed gas: 0.010) + [ 0x0005 ] + - location: 28 (just consumed gas: 0.031) + [ 0xfffa ] + - location: 29 (just consumed gas: 0.010) + [ 0xfffa + 0xfffa ] + - location: 34 (just consumed gas: 0.035) + [ 0 ] + - location: 35 (just consumed gas: 0.010) + [ True ] + - location: 36 (just consumed gas: 0.010) + [ ] + - location: 36 (just consumed gas: 0.025) + [ ] + - location: 42 (just consumed gas: 0.010) + [ 0xff05 ] + - location: 45 (just consumed gas: 0.031) + [ 0x00fa ] + - location: 46 (just consumed gas: 0.010) + [ 0x00fa + 0x00fa ] + - location: 51 (just consumed gas: 0.035) + [ 0 ] + - location: 52 (just consumed gas: 0.010) + [ True ] + - location: 53 (just consumed gas: 0.010) + [ ] + - location: 53 (just consumed gas: 0.025) + [ ] + - location: 59 (just consumed gas: 0.010) + [ Unit ] + - location: 60 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 62 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input106930123-.out new file mode 100644 index 000000000000..ee72ab5a9bbf --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input106930123-.out @@ -0,0 +1,35 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or.tz on storage None and input '(Pair False True)' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.975) + [ (Pair (Pair False True) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair False True) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair False True) + (Pair False True) ] + - location: 12 (just consumed gas: 0.010) + [ False + (Pair False True) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair False True) + False ] + - location: 14 (just consumed gas: 0.010) + [ True + False ] + - location: 15 (just consumed gas: 0.010) + [ True ] + - location: 16 (just consumed gas: 0.010) + [ (Some True) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input181204719-.out new file mode 100644 index 000000000000..ec4bf4402075 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input181204719-.out @@ -0,0 +1,35 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or.tz on storage None and input '(Pair True False)' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.975) + [ (Pair (Pair True False) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair True False) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair True False) + (Pair True False) ] + - location: 12 (just consumed gas: 0.010) + [ True + (Pair True False) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair True False) + True ] + - location: 14 (just consumed gas: 0.010) + [ False + True ] + - location: 15 (just consumed gas: 0.010) + [ True ] + - location: 16 (just consumed gas: 0.010) + [ (Some True) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input223774825-.out new file mode 100644 index 000000000000..a490b3c2024a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input223774825-.out @@ -0,0 +1,35 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or.tz on storage None and input '(Pair False False)' --level 1 --trace-stack +storage + (Some False) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.975) + [ (Pair (Pair False False) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair False False) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair False False) + (Pair False False) ] + - location: 12 (just consumed gas: 0.010) + [ False + (Pair False False) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair False False) + False ] + - location: 14 (just consumed gas: 0.010) + [ False + False ] + - location: 15 (just consumed gas: 0.010) + [ False ] + - location: 16 (just consumed gas: 0.010) + [ (Some False) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input908807505-.out new file mode 100644 index 000000000000..0746c0af6eb5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or--storage921624073--input908807505-.out @@ -0,0 +1,35 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or.tz on storage None and input '(Pair True True)' --level 1 --trace-stack +storage + (Some True) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 7.975) + [ (Pair (Pair True True) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair True True) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair True True) + (Pair True True) ] + - location: 12 (just consumed gas: 0.010) + [ True + (Pair True True) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair True True) + True ] + - location: 14 (just consumed gas: 0.010) + [ True + True ] + - location: 15 (just consumed gas: 0.010) + [ True ] + - location: 16 (just consumed gas: 0.010) + [ (Some True) ] + - location: 17 (just consumed gas: 0.010) + [ {} + (Some True) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair {} (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input1056991424-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input1056991424-.out new file mode 100644 index 000000000000..0ef5a15221e7 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input1056991424-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_binary.tz on storage None and input '(Pair 0 8)' --level 1 --trace-stack +storage + (Some 8) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 5.999) + [ (Pair (Pair 0 8) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 8) ] + - location: 11 (just consumed gas: 0.010) + [ 0 + 8 ] + - location: 12 (just consumed gas: 0.035) + [ 8 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 8) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 8) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some 8)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input375993021-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input375993021-.out new file mode 100644 index 000000000000..77b100258069 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input375993021-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_binary.tz on storage None and input '(Pair 14 1)' --level 1 --trace-stack +storage + (Some 15) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 5.999) + [ (Pair (Pair 14 1) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 14 1) ] + - location: 11 (just consumed gas: 0.010) + [ 14 + 1 ] + - location: 12 (just consumed gas: 0.035) + [ 15 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 15) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 15) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some 15)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input673240563-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input673240563-.out new file mode 100644 index 000000000000..87cf5816ae63 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input673240563-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_binary.tz on storage None and input '(Pair 8 0)' --level 1 --trace-stack +storage + (Some 8) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 5.999) + [ (Pair (Pair 8 0) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 8 0) ] + - location: 11 (just consumed gas: 0.010) + [ 8 + 0 ] + - location: 12 (just consumed gas: 0.035) + [ 8 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 8) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 8) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some 8)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input747448890-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input747448890-.out new file mode 100644 index 000000000000..22ed114c8155 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input747448890-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_binary.tz on storage None and input '(Pair 7 7)' --level 1 --trace-stack +storage + (Some 7) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 5.999) + [ (Pair (Pair 7 7) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 7 7) ] + - location: 11 (just consumed gas: 0.010) + [ 7 + 7 ] + - location: 12 (just consumed gas: 0.035) + [ 7 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 7) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 7) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some 7)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input832403787-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input832403787-.out new file mode 100644 index 000000000000..63dbcfc09c86 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input832403787-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_binary.tz on storage None and input '(Pair 15 4)' --level 1 --trace-stack +storage + (Some 15) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 5.999) + [ (Pair (Pair 15 4) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 15 4) ] + - location: 11 (just consumed gas: 0.010) + [ 15 + 4 ] + - location: 12 (just consumed gas: 0.035) + [ 15 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 15) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 15) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some 15)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input858098961-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input858098961-.out new file mode 100644 index 000000000000..6521cf12dfea --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_binary--storage921624073--input858098961-.out @@ -0,0 +1,26 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_binary.tz on storage None and input '(Pair 4 8)' --level 1 --trace-stack +storage + (Some 12) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 5.999) + [ (Pair (Pair 4 8) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 4 8) ] + - location: 11 (just consumed gas: 0.010) + [ 4 + 8 ] + - location: 12 (just consumed gas: 0.035) + [ 12 ] + - location: 13 (just consumed gas: 0.010) + [ (Some 12) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some 12) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some 12)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_bytes--storage125992234--input125992234-.out new file mode 100644 index 000000000000..b31f3bc60ea4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -or_bytes--storage125992234--input125992234-.out @@ -0,0 +1,75 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/or_bytes_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 27.915) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0x05 ] + - location: 11 (just consumed gas: 0.010) + [ 0x06 + 0x05 ] + - location: 14 (just consumed gas: 0.035) + [ 0x07 ] + - location: 15 (just consumed gas: 0.010) + [ 0x07 + 0x07 ] + - location: 20 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 0x0005 ] + - location: 31 (just consumed gas: 0.010) + [ 0x0106 + 0x0005 ] + - location: 34 (just consumed gas: 0.036) + [ 0x0107 ] + - location: 35 (just consumed gas: 0.010) + [ 0x0107 + 0x0107 ] + - location: 40 (just consumed gas: 0.035) + [ 0 ] + - location: 41 (just consumed gas: 0.010) + [ True ] + - location: 42 (just consumed gas: 0.010) + [ ] + - location: 42 (just consumed gas: 0.025) + [ ] + - location: 48 (just consumed gas: 0.010) + [ 0x05 ] + - location: 51 (just consumed gas: 0.010) + [ 0x0106 + 0x05 ] + - location: 54 (just consumed gas: 0.036) + [ 0x0107 ] + - location: 55 (just consumed gas: 0.010) + [ 0x0107 + 0x0107 ] + - location: 60 (just consumed gas: 0.035) + [ 0 ] + - location: 61 (just consumed gas: 0.010) + [ True ] + - location: 62 (just consumed gas: 0.010) + [ ] + - location: 62 (just consumed gas: 0.025) + [ ] + - location: 68 (just consumed gas: 0.010) + [ Unit ] + - location: 69 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 71 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input305844558-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input305844558-.out new file mode 100644 index 000000000000..fa5faca74127 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input305844558-.out @@ -0,0 +1,845 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/packunpack_rev.tz on storage Unit and input '(Pair -1 (Pair 1 (Pair "foobar" (Pair 0x00AABBCC (Pair 1000 (Pair False (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"))))))))' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 146.861) + [ (Pair (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 17 (just consumed gas: 0.010) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 18 (just consumed gas: 0.010) + [ -1 + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 19 (just consumed gas: 0.010) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 21 (just consumed gas: 0.010) + [ -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 19 (just consumed gas: 0.035) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 22 (just consumed gas: 0.241) + [ 0x050041 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 23 (just consumed gas: 0.421) + [ (Some -1) + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 26 (just consumed gas: 0.010) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 26 (just consumed gas: 0.025) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 34 (just consumed gas: 0.035) + [ 0 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 35 (just consumed gas: 0.010) + [ True + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 36 (just consumed gas: 0.010) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 36 (just consumed gas: 0.025) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 42 (just consumed gas: 0.010) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 43 (just consumed gas: 0.010) + [ 1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 44 (just consumed gas: 0.010) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 46 (just consumed gas: 0.010) + [ 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 44 (just consumed gas: 0.035) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 47 (just consumed gas: 0.241) + [ 0x050001 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 48 (just consumed gas: 0.421) + [ (Some 1) + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 51 (just consumed gas: 0.010) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 51 (just consumed gas: 0.025) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 59 (just consumed gas: 0.035) + [ 0 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 60 (just consumed gas: 0.010) + [ True + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 61 (just consumed gas: 0.010) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 61 (just consumed gas: 0.025) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 67 (just consumed gas: 0.010) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 68 (just consumed gas: 0.010) + [ "foobar" + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 69 (just consumed gas: 0.010) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 71 (just consumed gas: 0.010) + [ "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 69 (just consumed gas: 0.035) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 72 (just consumed gas: 0.276) + [ 0x050100000006666f6f626172 + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 73 (just consumed gas: 0.681) + [ (Some "foobar") + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 76 (just consumed gas: 0.010) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 76 (just consumed gas: 0.025) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 84 (just consumed gas: 0.035) + [ 0 + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 85 (just consumed gas: 0.010) + [ True + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 86 (just consumed gas: 0.010) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 86 (just consumed gas: 0.025) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 92 (just consumed gas: 0.010) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 93 (just consumed gas: 0.010) + [ 0x00aabbcc + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 94 (just consumed gas: 0.010) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 96 (just consumed gas: 0.010) + [ 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 94 (just consumed gas: 0.035) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 97 (just consumed gas: 0.256) + [ 0x050a0000000400aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 98 (just consumed gas: 0.565) + [ (Some 0x00aabbcc) + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 101 (just consumed gas: 0.010) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 101 (just consumed gas: 0.025) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 109 (just consumed gas: 0.035) + [ 0 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 110 (just consumed gas: 0.010) + [ True + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 111 (just consumed gas: 0.010) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 111 (just consumed gas: 0.025) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 117 (just consumed gas: 0.010) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 118 (just consumed gas: 0.010) + [ 1000 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 119 (just consumed gas: 0.010) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 121 (just consumed gas: 0.010) + [ 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 119 (just consumed gas: 0.035) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 122 (just consumed gas: 0.266) + [ 0x0500a80f + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 123 (just consumed gas: 0.442) + [ (Some 1000) + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 126 (just consumed gas: 0.010) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 126 (just consumed gas: 0.025) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 134 (just consumed gas: 0.035) + [ 0 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 135 (just consumed gas: 0.010) + [ True + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 136 (just consumed gas: 0.010) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 136 (just consumed gas: 0.025) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 142 (just consumed gas: 0.010) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 143 (just consumed gas: 0.010) + [ False + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 144 (just consumed gas: 0.010) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 146 (just consumed gas: 0.010) + [ False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 144 (just consumed gas: 0.035) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 147 (just consumed gas: 0.216) + [ 0x050303 + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 148 (just consumed gas: 0.421) + [ (Some False) + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 151 (just consumed gas: 0.010) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 151 (just consumed gas: 0.025) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 159 (just consumed gas: 0.035) + [ 0 + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 160 (just consumed gas: 0.010) + [ True + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 161 (just consumed gas: 0.010) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 161 (just consumed gas: 0.025) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 167 (just consumed gas: 0.010) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 168 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 169 (just consumed gas: 0.010) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 171 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 169 (just consumed gas: 0.035) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 172 (just consumed gas: 0.506) + [ 0x050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 173 (just consumed gas: 0.973) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 176 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 176 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 184 (just consumed gas: 0.036) + [ 0 + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 185 (just consumed gas: 0.010) + [ True + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 186 (just consumed gas: 0.010) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 186 (just consumed gas: 0.025) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 192 (just consumed gas: 0.010) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 193 (just consumed gas: 0.010) + [ "2019-09-09T08:35:33Z" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 194 (just consumed gas: 0.010) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 196 (just consumed gas: 0.010) + [ "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 194 (just consumed gas: 0.035) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 197 (just consumed gas: 0.316) + [ 0x050095bbb0d70b + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 198 (just consumed gas: 0.503) + [ (Some "2019-09-09T08:35:33Z") + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 201 (just consumed gas: 0.010) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 201 (just consumed gas: 0.025) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 209 (just consumed gas: 0.035) + [ 0 + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 210 (just consumed gas: 0.010) + [ True + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 211 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 211 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 217 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 218 (just consumed gas: 0.516) + [ 0x050a000000160000bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 219 (just consumed gas: 0.994) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 222 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 222 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 230 (just consumed gas: 0.036) + [ 0 ] + - location: 231 (just consumed gas: 0.010) + [ True ] + - location: 232 (just consumed gas: 0.010) + [ ] + - location: 232 (just consumed gas: 0.025) + [ ] + - location: 238 (just consumed gas: 0.010) + [ 0 ] + - location: 241 (just consumed gas: 0.216) + [ 0x050000 ] + - location: 242 (just consumed gas: 0.421) + [ (Some 0) ] + - location: 245 (just consumed gas: 0.010) + [ 0 ] + - location: 245 (just consumed gas: 0.025) + [ 0 ] + - location: 251 (just consumed gas: 0.010) + [ ] + - location: 252 (just consumed gas: 0.010) + [ -1 ] + - location: 255 (just consumed gas: 0.241) + [ 0x050041 ] + - location: 256 (just consumed gas: 96.321) + [ None ] + - location: 259 (just consumed gas: 0.010) + [ ] + - location: 259 (just consumed gas: 0.025) + [ ] + - location: 265 (just consumed gas: 0.010) + [ 0x ] + - location: 268 (just consumed gas: 0.270) + [ None ] + - location: 271 (just consumed gas: 0.010) + [ ] + - location: 271 (just consumed gas: 0.025) + [ ] + - location: 277 (just consumed gas: 0.010) + [ 0x04 ] + - location: 280 (just consumed gas: 0.280) + [ None ] + - location: 283 (just consumed gas: 0.010) + [ ] + - location: 283 (just consumed gas: 0.025) + [ ] + - location: 289 (just consumed gas: 0.010) + [ 0x05 ] + - location: 292 (just consumed gas: 0.280) + [ None ] + - location: 295 (just consumed gas: 0.010) + [ ] + - location: 295 (just consumed gas: 0.025) + [ ] + - location: 301 (just consumed gas: 0.010) + [ Unit ] + - location: 302 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 304 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input646365167-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input646365167-.out new file mode 100644 index 000000000000..19dfdacad24f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev--storage125992234--input646365167-.out @@ -0,0 +1,845 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/packunpack_rev.tz on storage Unit and input '(Pair -1 (Pair 1 (Pair "foobar" (Pair 0x00AABBCC (Pair 1000 (Pair False (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5"))))))))' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 146.861) + [ (Pair (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 17 (just consumed gas: 0.010) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 18 (just consumed gas: 0.010) + [ -1 + (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 19 (just consumed gas: 0.010) + [ (Pair -1 + 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 21 (just consumed gas: 0.010) + [ -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 19 (just consumed gas: 0.035) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 22 (just consumed gas: 0.241) + [ 0x050041 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 23 (just consumed gas: 0.421) + [ (Some -1) + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 26 (just consumed gas: 0.010) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 26 (just consumed gas: 0.025) + [ -1 + -1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 34 (just consumed gas: 0.035) + [ 0 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 35 (just consumed gas: 0.010) + [ True + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 36 (just consumed gas: 0.010) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 36 (just consumed gas: 0.025) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 42 (just consumed gas: 0.010) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 43 (just consumed gas: 0.010) + [ 1 + (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 44 (just consumed gas: 0.010) + [ (Pair 1 + "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 46 (just consumed gas: 0.010) + [ 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 44 (just consumed gas: 0.035) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 47 (just consumed gas: 0.241) + [ 0x050001 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 48 (just consumed gas: 0.421) + [ (Some 1) + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 51 (just consumed gas: 0.010) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 51 (just consumed gas: 0.025) + [ 1 + 1 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 59 (just consumed gas: 0.035) + [ 0 + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 60 (just consumed gas: 0.010) + [ True + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 61 (just consumed gas: 0.010) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 61 (just consumed gas: 0.025) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 67 (just consumed gas: 0.010) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 68 (just consumed gas: 0.010) + [ "foobar" + (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 69 (just consumed gas: 0.010) + [ (Pair "foobar" + 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 71 (just consumed gas: 0.010) + [ "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 69 (just consumed gas: 0.035) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 72 (just consumed gas: 0.276) + [ 0x050100000006666f6f626172 + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 73 (just consumed gas: 0.681) + [ (Some "foobar") + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 76 (just consumed gas: 0.010) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 76 (just consumed gas: 0.025) + [ "foobar" + "foobar" + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 84 (just consumed gas: 0.035) + [ 0 + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 85 (just consumed gas: 0.010) + [ True + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 86 (just consumed gas: 0.010) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 86 (just consumed gas: 0.025) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 92 (just consumed gas: 0.010) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 93 (just consumed gas: 0.010) + [ 0x00aabbcc + (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 94 (just consumed gas: 0.010) + [ (Pair 0x00aabbcc + 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 96 (just consumed gas: 0.010) + [ 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 94 (just consumed gas: 0.035) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 97 (just consumed gas: 0.256) + [ 0x050a0000000400aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 98 (just consumed gas: 0.565) + [ (Some 0x00aabbcc) + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 101 (just consumed gas: 0.010) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 101 (just consumed gas: 0.025) + [ 0x00aabbcc + 0x00aabbcc + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 109 (just consumed gas: 0.035) + [ 0 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 110 (just consumed gas: 0.010) + [ True + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 111 (just consumed gas: 0.010) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 111 (just consumed gas: 0.025) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 117 (just consumed gas: 0.010) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 118 (just consumed gas: 0.010) + [ 1000 + (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 119 (just consumed gas: 0.010) + [ (Pair 1000 + False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 121 (just consumed gas: 0.010) + [ 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 119 (just consumed gas: 0.035) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 122 (just consumed gas: 0.266) + [ 0x0500a80f + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 123 (just consumed gas: 0.442) + [ (Some 1000) + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 126 (just consumed gas: 0.010) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 126 (just consumed gas: 0.025) + [ 1000 + 1000 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 134 (just consumed gas: 0.035) + [ 0 + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 135 (just consumed gas: 0.010) + [ True + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 136 (just consumed gas: 0.010) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 136 (just consumed gas: 0.025) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 142 (just consumed gas: 0.010) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 143 (just consumed gas: 0.010) + [ False + (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 144 (just consumed gas: 0.010) + [ (Pair False + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 146 (just consumed gas: 0.010) + [ False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 144 (just consumed gas: 0.035) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 147 (just consumed gas: 0.216) + [ 0x050303 + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 148 (just consumed gas: 0.421) + [ (Some False) + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 151 (just consumed gas: 0.010) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 151 (just consumed gas: 0.025) + [ False + False + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 159 (just consumed gas: 0.035) + [ 0 + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 160 (just consumed gas: 0.010) + [ True + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 161 (just consumed gas: 0.010) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 161 (just consumed gas: 0.025) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 167 (just consumed gas: 0.010) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 168 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 169 (just consumed gas: 0.010) + [ (Pair "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 171 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 169 (just consumed gas: 0.035) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 172 (just consumed gas: 0.506) + [ 0x050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 173 (just consumed gas: 0.973) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 176 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 176 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 184 (just consumed gas: 0.036) + [ 0 + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 185 (just consumed gas: 0.010) + [ True + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 186 (just consumed gas: 0.010) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 186 (just consumed gas: 0.025) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 192 (just consumed gas: 0.010) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 193 (just consumed gas: 0.010) + [ "2019-09-09T08:35:33Z" + (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 194 (just consumed gas: 0.010) + [ (Pair "2019-09-09T08:35:33Z" "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") ] + - location: 196 (just consumed gas: 0.010) + [ "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 194 (just consumed gas: 0.035) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 197 (just consumed gas: 0.316) + [ 0x050095bbb0d70b + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 198 (just consumed gas: 0.503) + [ (Some "2019-09-09T08:35:33Z") + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 201 (just consumed gas: 0.010) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 201 (just consumed gas: 0.025) + [ "2019-09-09T08:35:33Z" + "2019-09-09T08:35:33Z" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 209 (just consumed gas: 0.035) + [ 0 + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 210 (just consumed gas: 0.010) + [ True + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 211 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 211 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 217 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 218 (just consumed gas: 0.516) + [ 0x050a000000160000bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 219 (just consumed gas: 0.994) + [ (Some "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 222 (just consumed gas: 0.010) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 222 (just consumed gas: 0.025) + [ "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" + "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5" ] + - location: 230 (just consumed gas: 0.036) + [ 0 ] + - location: 231 (just consumed gas: 0.010) + [ True ] + - location: 232 (just consumed gas: 0.010) + [ ] + - location: 232 (just consumed gas: 0.025) + [ ] + - location: 238 (just consumed gas: 0.010) + [ 0 ] + - location: 241 (just consumed gas: 0.216) + [ 0x050000 ] + - location: 242 (just consumed gas: 0.421) + [ (Some 0) ] + - location: 245 (just consumed gas: 0.010) + [ 0 ] + - location: 245 (just consumed gas: 0.025) + [ 0 ] + - location: 251 (just consumed gas: 0.010) + [ ] + - location: 252 (just consumed gas: 0.010) + [ -1 ] + - location: 255 (just consumed gas: 0.241) + [ 0x050041 ] + - location: 256 (just consumed gas: 96.321) + [ None ] + - location: 259 (just consumed gas: 0.010) + [ ] + - location: 259 (just consumed gas: 0.025) + [ ] + - location: 265 (just consumed gas: 0.010) + [ 0x ] + - location: 268 (just consumed gas: 0.270) + [ None ] + - location: 271 (just consumed gas: 0.010) + [ ] + - location: 271 (just consumed gas: 0.025) + [ ] + - location: 277 (just consumed gas: 0.010) + [ 0x04 ] + - location: 280 (just consumed gas: 0.280) + [ None ] + - location: 283 (just consumed gas: 0.010) + [ ] + - location: 283 (just consumed gas: 0.025) + [ ] + - location: 289 (just consumed gas: 0.010) + [ 0x05 ] + - location: 292 (just consumed gas: 0.280) + [ None ] + - location: 295 (just consumed gas: 0.010) + [ ] + - location: 295 (just consumed gas: 0.025) + [ ] + - location: 301 (just consumed gas: 0.010) + [ Unit ] + - location: 302 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 304 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out new file mode 100644 index 000000000000..cc1fb52cf08b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input1028781121-.out @@ -0,0 +1,1194 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/packunpack_rev_cty.tz on storage Unit and input '(Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" (Pair Unit (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") (Pair { Unit } (Pair { True } (Pair (Pair 19 10) (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK } )))))))))' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 28 (just consumed gas: 255.382) + [ (Pair (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + Unit) ] + - location: 28 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 29 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 30 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 33 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 31 (just consumed gas: 0.035) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 34 (just consumed gas: 1.001) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 35 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 37 (just consumed gas: 1.001) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 38 (just consumed gas: 75.159) + [ (Some "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 41 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 41 (just consumed gas: 0.025) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 47 (just consumed gas: 1.001) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 35 (just consumed gas: 0.035) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 50 (just consumed gas: 0.035) + [ 0 + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 51 (just consumed gas: 0.010) + [ True + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 52 (just consumed gas: 0.010) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 52 (just consumed gas: 0.025) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 58 (just consumed gas: 0.010) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 59 (just consumed gas: 0.010) + [ Unit + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 60 (just consumed gas: 0.010) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 62 (just consumed gas: 0.010) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 60 (just consumed gas: 0.035) + [ Unit + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 63 (just consumed gas: 0.216) + [ 0x05030b + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 64 (just consumed gas: 0.010) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 66 (just consumed gas: 0.216) + [ 0x05030b + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 67 (just consumed gas: 0.421) + [ (Some Unit) + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 70 (just consumed gas: 0.010) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 70 (just consumed gas: 0.025) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 76 (just consumed gas: 0.216) + [ 0x05030b + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 64 (just consumed gas: 0.035) + [ 0x05030b + 0x05030b + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 79 (just consumed gas: 0.035) + [ 0 + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 80 (just consumed gas: 0.010) + [ True + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 81 (just consumed gas: 0.010) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 81 (just consumed gas: 0.025) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 87 (just consumed gas: 0.010) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 88 (just consumed gas: 0.010) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 89 (just consumed gas: 0.010) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 91 (just consumed gas: 0.010) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 89 (just consumed gas: 0.035) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 92 (just consumed gas: 0.911) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 93 (just consumed gas: 0.010) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 95 (just consumed gas: 0.911) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 96 (just consumed gas: 1.835) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 99 (just consumed gas: 0.010) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 99 (just consumed gas: 0.025) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 105 (just consumed gas: 0.911) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 93 (just consumed gas: 0.035) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 108 (just consumed gas: 0.036) + [ 0 + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 109 (just consumed gas: 0.010) + [ True + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 110 (just consumed gas: 0.010) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 110 (just consumed gas: 0.025) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 116 (just consumed gas: 0.010) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 117 (just consumed gas: 0.010) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 118 (just consumed gas: 0.010) + [ (Pair (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 120 (just consumed gas: 0.010) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 118 (just consumed gas: 0.035) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 121 (just consumed gas: 1.127) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 122 (just consumed gas: 0.010) + [ (Some "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 124 (just consumed gas: 1.127) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 125 (just consumed gas: 1.976) + [ (Some (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe")) + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 129 (just consumed gas: 0.010) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 129 (just consumed gas: 0.025) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 135 (just consumed gas: 1.127) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 122 (just consumed gas: 0.035) + [ 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + 0x0505090a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 138 (just consumed gas: 0.036) + [ 0 + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 139 (just consumed gas: 0.010) + [ True + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 140 (just consumed gas: 0.010) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 140 (just consumed gas: 0.025) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 146 (just consumed gas: 0.010) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 147 (just consumed gas: 0.010) + [ { Unit } + (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 148 (just consumed gas: 0.010) + [ (Pair { Unit } + { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 150 (just consumed gas: 0.010) + [ { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 148 (just consumed gas: 0.035) + [ { Unit } + { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 151 (just consumed gas: 0.432) + [ 0x050200000002030b + { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 152 (just consumed gas: 0.010) + [ { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 154 (just consumed gas: 0.432) + [ 0x050200000002030b + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 155 (just consumed gas: 0.624) + [ (Some { Unit }) + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 159 (just consumed gas: 0.010) + [ { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 159 (just consumed gas: 0.025) + [ { Unit } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 165 (just consumed gas: 0.432) + [ 0x050200000002030b + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 152 (just consumed gas: 0.035) + [ 0x050200000002030b + 0x050200000002030b + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 168 (just consumed gas: 0.035) + [ 0 + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 169 (just consumed gas: 0.010) + [ True + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 170 (just consumed gas: 0.010) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 170 (just consumed gas: 0.025) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 176 (just consumed gas: 0.010) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 177 (just consumed gas: 0.010) + [ { True } + (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 178 (just consumed gas: 0.010) + [ (Pair { True } + (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 180 (just consumed gas: 0.010) + [ { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 178 (just consumed gas: 0.035) + [ { True } + { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 181 (just consumed gas: 0.432) + [ 0x050200000002030a + { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 182 (just consumed gas: 0.010) + [ { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 184 (just consumed gas: 0.432) + [ 0x050200000002030a + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 185 (just consumed gas: 0.674) + [ (Some { True }) + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 189 (just consumed gas: 0.010) + [ { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 189 (just consumed gas: 0.025) + [ { True } + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 195 (just consumed gas: 0.432) + [ 0x050200000002030a + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 182 (just consumed gas: 0.035) + [ 0x050200000002030a + 0x050200000002030a + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 198 (just consumed gas: 0.035) + [ 0 + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 199 (just consumed gas: 0.010) + [ True + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 200 (just consumed gas: 0.010) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 200 (just consumed gas: 0.025) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 206 (just consumed gas: 0.010) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 207 (just consumed gas: 0.010) + [ (Pair 19 10) + (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 208 (just consumed gas: 0.010) + [ (Pair (Pair 19 10) + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 210 (just consumed gas: 0.010) + [ (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 208 (just consumed gas: 0.035) + [ (Pair 19 10) + (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 211 (just consumed gas: 0.698) + [ 0x0507070013000a + (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 212 (just consumed gas: 0.010) + [ (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 214 (just consumed gas: 0.698) + [ 0x0507070013000a + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 215 (just consumed gas: 0.703) + [ (Some (Pair 19 10)) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 220 (just consumed gas: 0.010) + [ (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 220 (just consumed gas: 0.025) + [ (Pair 19 10) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 226 (just consumed gas: 0.698) + [ 0x0507070013000a + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 212 (just consumed gas: 0.035) + [ 0x0507070013000a + 0x0507070013000a + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 229 (just consumed gas: 0.035) + [ 0 + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 230 (just consumed gas: 0.010) + [ True + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 231 (just consumed gas: 0.010) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 231 (just consumed gas: 0.025) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 237 (just consumed gas: 0.010) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 238 (just consumed gas: 0.010) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 239 (just consumed gas: 0.010) + [ (Pair (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK }) ] + - location: 241 (just consumed gas: 0.010) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 239 (just consumed gas: 0.035) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 242 (just consumed gas: 0.722) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 243 (just consumed gas: 0.010) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 245 (just consumed gas: 0.722) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 246 (just consumed gas: 1.114) + [ (Some (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5")) + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 251 (just consumed gas: 0.010) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 251 (just consumed gas: 0.025) + [ (Left "tz1cxcwwnzENRdhe2Kb8ZdTrdNy4bFNyScx5") + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 257 (just consumed gas: 0.722) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 243 (just consumed gas: 0.035) + [ 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + 0x0505050a0000001500bdfe3885e846fdea23c9acbe3bb1cfcca9c03e4a + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 260 (just consumed gas: 0.035) + [ 0 + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 261 (just consumed gas: 0.010) + [ True + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 262 (just consumed gas: 0.010) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 262 (just consumed gas: 0.025) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 268 (just consumed gas: 0.010) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 269 (just consumed gas: 0.010) + [ { Elt 0 "foo" ; Elt 1 "bar" } + (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 270 (just consumed gas: 0.010) + [ (Pair { Elt 0 "foo" ; Elt 1 "bar" } { PACK }) ] + - location: 272 (just consumed gas: 0.010) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 270 (just consumed gas: 0.035) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 273 (just consumed gas: 1.467) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 + { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 274 (just consumed gas: 0.010) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 276 (just consumed gas: 1.467) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 + { PACK } ] + - location: 277 (just consumed gas: 1.610) + [ (Some { Elt 0 "foo" ; Elt 1 "bar" }) + { PACK } ] + - location: 282 (just consumed gas: 0.010) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 282 (just consumed gas: 0.025) + [ { Elt 0 "foo" ; Elt 1 "bar" } + { PACK } ] + - location: 288 (just consumed gas: 1.467) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 + { PACK } ] + - location: 274 (just consumed gas: 0.035) + [ 0x050200000018070400000100000003666f6f070400010100000003626172 + 0x050200000018070400000100000003666f6f070400010100000003626172 + { PACK } ] + - location: 291 (just consumed gas: 0.035) + [ 0 + { PACK } ] + - location: 292 (just consumed gas: 0.010) + [ True + { PACK } ] + - location: 293 (just consumed gas: 0.010) + [ { PACK } ] + - location: 293 (just consumed gas: 0.025) + [ { PACK } ] + - location: 299 (just consumed gas: 0.010) + [ { PACK } + { PACK } ] + - location: 300 (just consumed gas: 0.597) + [ 0x050200000002030c + { PACK } ] + - location: 301 (just consumed gas: 0.010) + [ { PACK } ] + - location: 303 (just consumed gas: 0.597) + [ 0x050200000002030c ] + - location: 304 (just consumed gas: 1.553) + [ (Some { PACK }) ] + - location: 309 (just consumed gas: 0.010) + [ { PACK } ] + - location: 309 (just consumed gas: 0.025) + [ { PACK } ] + - location: 315 (just consumed gas: 0.597) + [ 0x050200000002030c ] + - location: 301 (just consumed gas: 0.035) + [ 0x050200000002030c + 0x050200000002030c ] + - location: 318 (just consumed gas: 0.035) + [ 0 ] + - location: 319 (just consumed gas: 0.010) + [ True ] + - location: 320 (just consumed gas: 0.010) + [ ] + - location: 320 (just consumed gas: 0.025) + [ ] + - location: 326 (just consumed gas: 0.010) + [ Unit ] + - location: 327 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 329 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out new file mode 100644 index 000000000000..2094931ea0ff --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -packunpack_rev_cty--storage125992234--input802670583-.out @@ -0,0 +1,1032 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/packunpack_rev_cty.tz on storage Unit and input '(Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" (Pair Unit (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" (Pair None (Pair { } (Pair { } (Pair (Pair 40 -10) (Pair (Right "2019-09-09T08:35:33Z") (Pair { } { DUP ; DROP ; PACK } )))))))))' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 28 (just consumed gas: 246.017) + [ (Pair (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + Unit) ] + - location: 28 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 29 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 30 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 33 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 31 (just consumed gas: 0.035) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 34 (just consumed gas: 1.001) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 35 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 37 (just consumed gas: 1.001) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 38 (just consumed gas: 75.159) + [ (Some "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav") + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 41 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 41 (just consumed gas: 0.025) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 47 (just consumed gas: 1.001) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 35 (just consumed gas: 0.035) + [ 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 50 (just consumed gas: 0.035) + [ 0 + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 51 (just consumed gas: 0.010) + [ True + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 52 (just consumed gas: 0.010) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 52 (just consumed gas: 0.025) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 58 (just consumed gas: 0.010) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 59 (just consumed gas: 0.010) + [ Unit + (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 60 (just consumed gas: 0.010) + [ (Pair Unit + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 62 (just consumed gas: 0.010) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 60 (just consumed gas: 0.035) + [ Unit + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 63 (just consumed gas: 0.216) + [ 0x05030b + Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 64 (just consumed gas: 0.010) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 66 (just consumed gas: 0.216) + [ 0x05030b + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 67 (just consumed gas: 0.421) + [ (Some Unit) + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 70 (just consumed gas: 0.010) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 70 (just consumed gas: 0.025) + [ Unit + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 76 (just consumed gas: 0.216) + [ 0x05030b + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 64 (just consumed gas: 0.035) + [ 0x05030b + 0x05030b + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 79 (just consumed gas: 0.035) + [ 0 + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 80 (just consumed gas: 0.010) + [ True + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 81 (just consumed gas: 0.010) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 81 (just consumed gas: 0.025) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 87 (just consumed gas: 0.010) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 88 (just consumed gas: 0.010) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 89 (just consumed gas: 0.010) + [ (Pair "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 91 (just consumed gas: 0.010) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 89 (just consumed gas: 0.035) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 92 (just consumed gas: 0.911) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 93 (just consumed gas: 0.010) + [ "edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 95 (just consumed gas: 0.911) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 96 (just consumed gas: 1.835) + [ (Some "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe") + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 99 (just consumed gas: 0.010) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 99 (just consumed gas: 0.025) + [ "sigXeXB5JD5TaLb3xgTPKjgf9W45judiCmNP9UBdZBdmtHSGBxL1M8ZSUb6LpjGP2MdfUBTB4WHs5APnvyRV1LooU6QHJuDe" + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 105 (just consumed gas: 0.911) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 93 (just consumed gas: 0.035) + [ 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 108 (just consumed gas: 0.036) + [ 0 + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 109 (just consumed gas: 0.010) + [ True + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 110 (just consumed gas: 0.010) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 110 (just consumed gas: 0.025) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 116 (just consumed gas: 0.010) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 117 (just consumed gas: 0.010) + [ None + (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 118 (just consumed gas: 0.010) + [ (Pair None + {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 120 (just consumed gas: 0.010) + [ None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 118 (just consumed gas: 0.035) + [ None + None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 121 (just consumed gas: 0.216) + [ 0x050306 + None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 122 (just consumed gas: 0.010) + [ None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 124 (just consumed gas: 0.216) + [ 0x050306 + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 125 (just consumed gas: 0.421) + [ (Some None) + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 129 (just consumed gas: 0.010) + [ None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 129 (just consumed gas: 0.025) + [ None + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 135 (just consumed gas: 0.216) + [ 0x050306 + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 122 (just consumed gas: 0.035) + [ 0x050306 + 0x050306 + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 138 (just consumed gas: 0.035) + [ 0 + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 139 (just consumed gas: 0.010) + [ True + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 140 (just consumed gas: 0.010) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 140 (just consumed gas: 0.025) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 146 (just consumed gas: 0.010) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 147 (just consumed gas: 0.010) + [ {} + (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 148 (just consumed gas: 0.010) + [ (Pair {} + {} + (Pair 40 -10) + (Right "2019-09-09T08:35:33Z") + {} + { DUP ; DROP ; PACK }) ] + - location: 150 (just consumed gas: 0.010) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 148 (just consumed gas: 0.035) + [ {} + {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 151 (just consumed gas: 0.216) + [ 0x050200000000 + {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 152 (just consumed gas: 0.010) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 154 (just consumed gas: 0.216) + [ 0x050200000000 + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 155 (just consumed gas: 0.483) + [ (Some {}) + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 159 (just consumed gas: 0.010) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 159 (just consumed gas: 0.025) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 165 (just consumed gas: 0.216) + [ 0x050200000000 + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 152 (just consumed gas: 0.035) + [ 0x050200000000 + 0x050200000000 + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 168 (just consumed gas: 0.035) + [ 0 + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 169 (just consumed gas: 0.010) + [ True + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 170 (just consumed gas: 0.010) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 170 (just consumed gas: 0.025) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 176 (just consumed gas: 0.010) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 177 (just consumed gas: 0.010) + [ {} + (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 178 (just consumed gas: 0.010) + [ (Pair {} (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 180 (just consumed gas: 0.010) + [ {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 178 (just consumed gas: 0.035) + [ {} + {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 181 (just consumed gas: 0.216) + [ 0x050200000000 + {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 182 (just consumed gas: 0.010) + [ {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 184 (just consumed gas: 0.216) + [ 0x050200000000 + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 185 (just consumed gas: 0.483) + [ (Some {}) + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 189 (just consumed gas: 0.010) + [ {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 189 (just consumed gas: 0.025) + [ {} + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 195 (just consumed gas: 0.216) + [ 0x050200000000 + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 182 (just consumed gas: 0.035) + [ 0x050200000000 + 0x050200000000 + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 198 (just consumed gas: 0.035) + [ 0 + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 199 (just consumed gas: 0.010) + [ True + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 200 (just consumed gas: 0.010) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 200 (just consumed gas: 0.025) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 206 (just consumed gas: 0.010) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 207 (just consumed gas: 0.010) + [ (Pair 40 -10) + (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 208 (just consumed gas: 0.010) + [ (Pair (Pair 40 -10) (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 210 (just consumed gas: 0.010) + [ (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 208 (just consumed gas: 0.035) + [ (Pair 40 -10) + (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 211 (just consumed gas: 0.698) + [ 0x0507070028004a + (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 212 (just consumed gas: 0.010) + [ (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 214 (just consumed gas: 0.698) + [ 0x0507070028004a + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 215 (just consumed gas: 0.703) + [ (Some (Pair 40 -10)) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 220 (just consumed gas: 0.010) + [ (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 220 (just consumed gas: 0.025) + [ (Pair 40 -10) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 226 (just consumed gas: 0.698) + [ 0x0507070028004a + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 212 (just consumed gas: 0.035) + [ 0x0507070028004a + 0x0507070028004a + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 229 (just consumed gas: 0.035) + [ 0 + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 230 (just consumed gas: 0.010) + [ True + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 231 (just consumed gas: 0.010) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 231 (just consumed gas: 0.025) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 237 (just consumed gas: 0.010) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 238 (just consumed gas: 0.010) + [ (Right "2019-09-09T08:35:33Z") + (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 239 (just consumed gas: 0.010) + [ (Pair (Right "2019-09-09T08:35:33Z") {} { DUP ; DROP ; PACK }) ] + - location: 241 (just consumed gas: 0.010) + [ (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 239 (just consumed gas: 0.035) + [ (Right "2019-09-09T08:35:33Z") + (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 242 (just consumed gas: 0.532) + [ 0x0505080095bbb0d70b + (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 243 (just consumed gas: 0.010) + [ (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 245 (just consumed gas: 0.532) + [ 0x0505080095bbb0d70b + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 246 (just consumed gas: 0.644) + [ (Some (Right "2019-09-09T08:35:33Z")) + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 251 (just consumed gas: 0.010) + [ (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 251 (just consumed gas: 0.025) + [ (Right "2019-09-09T08:35:33Z") + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 257 (just consumed gas: 0.532) + [ 0x0505080095bbb0d70b + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 243 (just consumed gas: 0.035) + [ 0x0505080095bbb0d70b + 0x0505080095bbb0d70b + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 260 (just consumed gas: 0.035) + [ 0 + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 261 (just consumed gas: 0.010) + [ True + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 262 (just consumed gas: 0.010) + [ (Pair {} { DUP ; DROP ; PACK }) ] + - location: 262 (just consumed gas: 0.025) + [ (Pair {} { DUP ; DROP ; PACK }) ] + - location: 268 (just consumed gas: 0.010) + [ (Pair {} { DUP ; DROP ; PACK }) + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 269 (just consumed gas: 0.010) + [ {} + (Pair {} { DUP ; DROP ; PACK }) ] + - location: 270 (just consumed gas: 0.010) + [ (Pair {} { DUP ; DROP ; PACK }) ] + - location: 272 (just consumed gas: 0.010) + [ {} + { DUP ; DROP ; PACK } ] + - location: 270 (just consumed gas: 0.035) + [ {} + {} + { DUP ; DROP ; PACK } ] + - location: 273 (just consumed gas: 0.216) + [ 0x050200000000 + {} + { DUP ; DROP ; PACK } ] + - location: 274 (just consumed gas: 0.010) + [ {} + { DUP ; DROP ; PACK } ] + - location: 276 (just consumed gas: 0.216) + [ 0x050200000000 + { DUP ; DROP ; PACK } ] + - location: 277 (just consumed gas: 0.483) + [ (Some {}) + { DUP ; DROP ; PACK } ] + - location: 282 (just consumed gas: 0.010) + [ {} + { DUP ; DROP ; PACK } ] + - location: 282 (just consumed gas: 0.025) + [ {} + { DUP ; DROP ; PACK } ] + - location: 288 (just consumed gas: 0.216) + [ 0x050200000000 + { DUP ; DROP ; PACK } ] + - location: 274 (just consumed gas: 0.035) + [ 0x050200000000 + 0x050200000000 + { DUP ; DROP ; PACK } ] + - location: 291 (just consumed gas: 0.035) + [ 0 + { DUP ; DROP ; PACK } ] + - location: 292 (just consumed gas: 0.010) + [ True + { DUP ; DROP ; PACK } ] + - location: 293 (just consumed gas: 0.010) + [ { DUP ; DROP ; PACK } ] + - location: 293 (just consumed gas: 0.025) + [ { DUP ; DROP ; PACK } ] + - location: 299 (just consumed gas: 0.010) + [ { DUP ; DROP ; PACK } + { DUP ; DROP ; PACK } ] + - location: 300 (just consumed gas: 1.129) + [ 0x05020000000603210320030c + { DUP ; DROP ; PACK } ] + - location: 301 (just consumed gas: 0.010) + [ { DUP ; DROP ; PACK } ] + - location: 303 (just consumed gas: 1.129) + [ 0x05020000000603210320030c ] + - location: 304 (just consumed gas: 3.147) + [ (Some { DUP ; DROP ; PACK }) ] + - location: 309 (just consumed gas: 0.010) + [ { DUP ; DROP ; PACK } ] + - location: 309 (just consumed gas: 0.025) + [ { DUP ; DROP ; PACK } ] + - location: 315 (just consumed gas: 1.129) + [ 0x05020000000603210320030c ] + - location: 301 (just consumed gas: 0.035) + [ 0x05020000000603210320030c + 0x05020000000603210320030c ] + - location: 318 (just consumed gas: 0.035) + [ 0 ] + - location: 319 (just consumed gas: 0.010) + [ True ] + - location: 320 (just consumed gas: 0.010) + [ ] + - location: 320 (just consumed gas: 0.025) + [ ] + - location: 326 (just consumed gas: 0.010) + [ Unit ] + - location: 327 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 329 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input106930123-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input106930123-.out new file mode 100644 index 000000000000..0f81c4deb3a5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input106930123-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/pair_id.tz on storage None and input '(Pair False True)' --level 1 --trace-stack +storage + (Some (Pair False True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 5.283) + [ (Pair (Pair False True) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair False True) ] + - location: 13 (just consumed gas: 0.010) + [ (Some (Pair False True)) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some (Pair False True)) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair False True))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input181204719-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input181204719-.out new file mode 100644 index 000000000000..74836d1fa617 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input181204719-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/pair_id.tz on storage None and input '(Pair True False)' --level 1 --trace-stack +storage + (Some (Pair True False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 5.283) + [ (Pair (Pair True False) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair True False) ] + - location: 13 (just consumed gas: 0.010) + [ (Some (Pair True False)) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some (Pair True False)) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair True False))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input223774825-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input223774825-.out new file mode 100644 index 000000000000..955d3adff8ae --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input223774825-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/pair_id.tz on storage None and input '(Pair False False)' --level 1 --trace-stack +storage + (Some (Pair False False)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 5.283) + [ (Pair (Pair False False) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair False False) ] + - location: 13 (just consumed gas: 0.010) + [ (Some (Pair False False)) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some (Pair False False)) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair False False))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input908807505-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input908807505-.out new file mode 100644 index 000000000000..d5f646a602d0 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pair_id--storage921624073--input908807505-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/pair_id.tz on storage None and input '(Pair True True)' --level 1 --trace-stack +storage + (Some (Pair True True)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 5.283) + [ (Pair (Pair True True) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair True True) ] + - location: 13 (just consumed gas: 0.010) + [ (Some (Pair True True)) ] + - location: 14 (just consumed gas: 0.010) + [ {} + (Some (Pair True True)) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair True True))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec--storage256947135--input1050356042-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec--storage256947135--input1050356042-.out new file mode 100644 index 000000000000..72dbbc591f14 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec--storage256947135--input1050356042-.out @@ -0,0 +1,47 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/pexec.tz on storage 14 and input 38 --level 1 --trace-stack +storage + 52 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 8.913) + [ (Pair 38 14) ] + - location: 7 (just consumed gas: 0.010) + [ { UNPAIR ; ADD } + (Pair 38 14) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 38 14) + { UNPAIR ; ADD } ] + - location: 16 (just consumed gas: 0.010) + [ 38 + 14 + { UNPAIR ; ADD } ] + - location: 17 (just consumed gas: 0.010) + [ 14 + { UNPAIR ; ADD } ] + - location: 19 (just consumed gas: 0.401) + [ { PUSH nat 14 ; PAIR ; { UNPAIR ; ADD } } ] + - location: 17 (just consumed gas: 0.035) + [ 38 + { PUSH nat 14 ; PAIR ; { UNPAIR ; ADD } } ] + - location: 12 (just consumed gas: 0.020) + [ 14 + 38 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair 14 38) ] + - location: 13 (just consumed gas: 0.010) + [ 14 + 38 ] + - location: 14 (just consumed gas: 0.035) + [ 52 ] + - location: 20 (just consumed gas: 0.035) + [ 52 ] + - location: 21 (just consumed gas: 0.010) + [ {} + 52 ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} 52) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec_2--storage197120858--input179371027-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec_2--storage197120858--input179371027-.out new file mode 100644 index 000000000000..ee18d85b4a09 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -pexec_2--storage197120858--input179371027-.out @@ -0,0 +1,282 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/pexec_2.tz on storage '{ 0 ; 1 ; 2 ; 3}' and input 4 --level 1 --trace-stack +storage + { 0 ; 7 ; 14 ; 21 } +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 16.800) + [ (Pair 4 { 0 ; 1 ; 2 ; 3 }) ] + - location: 8 (just consumed gas: 0.010) + [ 4 + { 0 ; 1 ; 2 ; 3 } ] + - location: 9 (just consumed gas: 0.010) + [ { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } + 4 + { 0 ; 1 ; 2 ; 3 } ] + - location: 23 (just consumed gas: 0.010) + [ 4 + { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } + { 0 ; 1 ; 2 ; 3 } ] + - location: 24 (just consumed gas: 0.401) + [ { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } + { 0 ; 1 ; 2 ; 3 } ] + - location: 25 (just consumed gas: 0.010) + [ 3 + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } + { 0 ; 1 ; 2 ; 3 } ] + - location: 28 (just consumed gas: 0.401) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { 0 ; 1 ; 2 ; 3 } ] + - location: 29 (just consumed gas: 0.010) + [ { 0 ; 1 ; 2 ; 3 } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 30 (just consumed gas: 0.050) + [ 0 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.035) + [ 0 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (just consumed gas: 0.020) + [ 3 + 0 ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 3 0) ] + - location: 16 (just consumed gas: 0.010) + [ 4 + (Pair 3 0) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 4 3 0) ] + - location: 17 (just consumed gas: 0.010) + [ 4 + (Pair 3 0) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 3 0) ] + - location: 20 (just consumed gas: 0.010) + [ 3 + 0 ] + - location: 18 (just consumed gas: 0.035) + [ 4 + 3 + 0 ] + - location: 21 (just consumed gas: 0.035) + [ 7 + 0 ] + - location: 22 (just consumed gas: 0.056) + [ 0 ] + - location: 35 (just consumed gas: 0.035) + [ 0 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 30 (just consumed gas: 0.055) + [ 1 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.035) + [ 1 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (just consumed gas: 0.020) + [ 3 + 1 ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 3 1) ] + - location: 16 (just consumed gas: 0.010) + [ 4 + (Pair 3 1) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 4 3 1) ] + - location: 17 (just consumed gas: 0.010) + [ 4 + (Pair 3 1) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 3 1) ] + - location: 20 (just consumed gas: 0.010) + [ 3 + 1 ] + - location: 18 (just consumed gas: 0.035) + [ 4 + 3 + 1 ] + - location: 21 (just consumed gas: 0.035) + [ 7 + 1 ] + - location: 22 (just consumed gas: 0.059) + [ 7 ] + - location: 35 (just consumed gas: 0.035) + [ 7 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 30 (just consumed gas: 0.055) + [ 2 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.035) + [ 2 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (just consumed gas: 0.020) + [ 3 + 2 ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 3 2) ] + - location: 16 (just consumed gas: 0.010) + [ 4 + (Pair 3 2) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 4 3 2) ] + - location: 17 (just consumed gas: 0.010) + [ 4 + (Pair 3 2) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 3 2) ] + - location: 20 (just consumed gas: 0.010) + [ 3 + 2 ] + - location: 18 (just consumed gas: 0.035) + [ 4 + 3 + 2 ] + - location: 21 (just consumed gas: 0.035) + [ 7 + 2 ] + - location: 22 (just consumed gas: 0.059) + [ 14 ] + - location: 35 (just consumed gas: 0.035) + [ 14 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 30 (just consumed gas: 0.055) + [ 3 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 34 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 32 (just consumed gas: 0.035) + [ 3 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 16 (just consumed gas: 0.020) + [ 3 + 3 ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 3 3) ] + - location: 16 (just consumed gas: 0.010) + [ 4 + (Pair 3 3) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 4 3 3) ] + - location: 17 (just consumed gas: 0.010) + [ 4 + (Pair 3 3) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair 3 3) ] + - location: 20 (just consumed gas: 0.010) + [ 3 + 3 ] + - location: 18 (just consumed gas: 0.035) + [ 4 + 3 + 3 ] + - location: 21 (just consumed gas: 0.035) + [ 7 + 3 ] + - location: 22 (just consumed gas: 0.059) + [ 21 ] + - location: 35 (just consumed gas: 0.035) + [ 21 + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 30 (just consumed gas: 0.072) + [ { 0 ; 7 ; 14 ; 21 } + { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 36 (just consumed gas: 0.010) + [ { PUSH int 3 ; + PAIR ; + { PUSH int 4 ; PAIR ; { UNPAIR ; DIP { UNPAIR } ; ADD ; MUL } } } ] + - location: 38 (just consumed gas: 0.010) + [ ] + - location: 36 (just consumed gas: 0.035) + [ { 0 ; 7 ; 14 ; 21 } ] + - location: 39 (just consumed gas: 0.010) + [ {} + { 0 ; 7 ; 14 ; 21 } ] + - location: 41 (just consumed gas: 0.010) + [ (Pair {} { 0 ; 7 ; 14 ; 21 }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ret_int--storage921624073--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ret_int--storage921624073--input125992234-.out new file mode 100644 index 000000000000..2ec3627f1e0f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -ret_int--storage921624073--input125992234-.out @@ -0,0 +1,23 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/ret_int.tz on storage None and input Unit --level 1 --trace-stack +storage + (Some 300) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.371) + [ (Pair Unit None) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.010) + [ 300 ] + - location: 12 (just consumed gas: 0.010) + [ (Some 300) ] + - location: 13 (just consumed gas: 0.010) + [ {} + (Some 300) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair {} (Some 300)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input457300675-.out new file mode 100644 index 000000000000..89bbe17aa56e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input457300675-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/reverse.tz on storage '{""}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 6.772) + [ (Pair {} { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ {} + {} ] + - location: 12 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.040) + [ {} ] + - location: 16 (just consumed gas: 0.010) + [ {} + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input851203613-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input851203613-.out new file mode 100644 index 000000000000..9fd13ad6974e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse--storage528921618--input851203613-.out @@ -0,0 +1,42 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/reverse.tz on storage '{""}' and input '{ "c" ; "b" ; "a" }' --level 1 --trace-stack +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.147) + [ (Pair { "c" ; "b" ; "a" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "c" ; "b" ; "a" } ] + - location: 12 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } + {} ] + - location: 13 (just consumed gas: 0.030) + [ "c" + {} ] + - location: 15 (just consumed gas: 0.010) + [ { "c" } ] + - location: 13 (just consumed gas: 0.025) + [ "b" + { "c" } ] + - location: 15 (just consumed gas: 0.010) + [ { "b" ; "c" } ] + - location: 13 (just consumed gas: 0.025) + [ "a" + { "b" ; "c" } ] + - location: 15 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 13 (just consumed gas: 0.035) + [ { "a" ; "b" ; "c" } ] + - location: 16 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input457300675-.out new file mode 100644 index 000000000000..aa009cad69e7 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input457300675-.out @@ -0,0 +1,50 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/reverse_loop.tz on storage '{""}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 13.491) + [ (Pair {} { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ {} + {} ] + - location: 12 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.010) + [ True + {} + {} ] + - location: 33 (just consumed gas: 0.020) + [ {} + {} ] + - location: 18 (just consumed gas: 0.010) + [ {} ] + - location: 28 (just consumed gas: 0.010) + [ {} + {} ] + - location: 30 (just consumed gas: 0.010) + [ False + {} + {} ] + - location: 18 (just consumed gas: 0.025) + [ False + {} + {} ] + - location: 33 (just consumed gas: 0.035) + [ {} + {} ] + - location: 33 (just consumed gas: 0.010) + [ {} ] + - location: 34 (just consumed gas: 0.010) + [ {} + {} ] + - location: 36 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input851203613-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input851203613-.out new file mode 100644 index 000000000000..3ea95f3ff06e --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -reverse_loop--storage528921618--input851203613-.out @@ -0,0 +1,131 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/reverse_loop.tz on storage '{""}' and input '{ "c" ; "b" ; "a" }' --level 1 --trace-stack +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 13.866) + [ (Pair { "c" ; "b" ; "a" } { "" }) ] + - location: 9 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "c" ; "b" ; "a" } ] + - location: 12 (just consumed gas: 0.010) + [ { "c" ; "b" ; "a" } + {} ] + - location: 13 (just consumed gas: 0.010) + [ True + { "c" ; "b" ; "a" } + {} ] + - location: 33 (just consumed gas: 0.020) + [ { "c" ; "b" ; "a" } + {} ] + - location: 18 (just consumed gas: 0.010) + [ "c" + { "b" ; "a" } + {} ] + - location: 20 (just consumed gas: 0.010) + [ { "b" ; "a" } + "c" + {} ] + - location: 21 (just consumed gas: 0.010) + [ "c" + {} ] + - location: 23 (just consumed gas: 0.010) + [ { "c" } ] + - location: 21 (just consumed gas: 0.035) + [ { "b" ; "a" } + { "c" } ] + - location: 24 (just consumed gas: 0.010) + [ True + { "b" ; "a" } + { "c" } ] + - location: 18 (just consumed gas: 0.025) + [ True + { "b" ; "a" } + { "c" } ] + - location: 33 (just consumed gas: 0.025) + [ { "b" ; "a" } + { "c" } ] + - location: 18 (just consumed gas: 0.010) + [ "b" + { "a" } + { "c" } ] + - location: 20 (just consumed gas: 0.010) + [ { "a" } + "b" + { "c" } ] + - location: 21 (just consumed gas: 0.010) + [ "b" + { "c" } ] + - location: 23 (just consumed gas: 0.010) + [ { "b" ; "c" } ] + - location: 21 (just consumed gas: 0.035) + [ { "a" } + { "b" ; "c" } ] + - location: 24 (just consumed gas: 0.010) + [ True + { "a" } + { "b" ; "c" } ] + - location: 18 (just consumed gas: 0.025) + [ True + { "a" } + { "b" ; "c" } ] + - location: 33 (just consumed gas: 0.025) + [ { "a" } + { "b" ; "c" } ] + - location: 18 (just consumed gas: 0.010) + [ "a" + {} + { "b" ; "c" } ] + - location: 20 (just consumed gas: 0.010) + [ {} + "a" + { "b" ; "c" } ] + - location: 21 (just consumed gas: 0.010) + [ "a" + { "b" ; "c" } ] + - location: 23 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 21 (just consumed gas: 0.035) + [ {} + { "a" ; "b" ; "c" } ] + - location: 24 (just consumed gas: 0.010) + [ True + {} + { "a" ; "b" ; "c" } ] + - location: 18 (just consumed gas: 0.025) + [ True + {} + { "a" ; "b" ; "c" } ] + - location: 33 (just consumed gas: 0.025) + [ {} + { "a" ; "b" ; "c" } ] + - location: 18 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 28 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 30 (just consumed gas: 0.010) + [ False + {} + { "a" ; "b" ; "c" } ] + - location: 18 (just consumed gas: 0.025) + [ False + {} + { "a" ; "b" ; "c" } ] + - location: 33 (just consumed gas: 0.035) + [ {} + { "a" ; "b" ; "c" } ] + - location: 33 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 34 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 36 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sapling_empty_state--storage457300675--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sapling_empty_state--storage457300675--input125992234-.out new file mode 100644 index 000000000000..76b764466c71 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sapling_empty_state--storage457300675--input125992234-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/sapling_empty_state.tz on storage '{}' and input Unit --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.250) + [ (Pair Unit {}) ] + - location: 8 (just consumed gas: 0.010) + [ ] + - location: 9 (just consumed gas: 0.300) + [ {} ] + - location: 11 (just consumed gas: 0.010) + [ {} + {} ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_address--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_address--storage125992234--input125992234-.out new file mode 100644 index 000000000000..3453ad5d641a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_address--storage125992234--input125992234-.out @@ -0,0 +1,46 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/self_address.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 13.358) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ { DROP ; SELF_ADDRESS } ] + - location: 14 (just consumed gas: 0.010) + [ Unit + { DROP ; SELF_ADDRESS } ] + - location: 12 (just consumed gas: 0.020) + [ ] + - location: 13 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 15 (just consumed gas: 0.035) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 16 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" + "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 17 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" + "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 20 (just consumed gas: 0.036) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ Unit ] + - location: 29 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out new file mode 100644 index 000000000000..43c6a2207ea7 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_default_entrypoint--storage125992234--input125992234-.out @@ -0,0 +1,47 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/self_with_default_entrypoint.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 15.247) + [ (Pair (Right (Left Unit)) Unit) ] + - location: 13 (just consumed gas: 0.010) + [ ] + - location: 14 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 15 (just consumed gas: 0.010) + [ ] + - location: 16 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" ] + - location: 17 (just consumed gas: 0.010) + [ ] + - location: 18 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 19 (just consumed gas: 0.516) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 20 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 21 (just consumed gas: 0.516) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 24 (just consumed gas: 0.035) + [ 0 ] + - location: 25 (just consumed gas: 0.010) + [ True ] + - location: 26 (just consumed gas: 0.010) + [ ] + - location: 26 (just consumed gas: 0.025) + [ ] + - location: 32 (just consumed gas: 0.010) + [ Unit ] + - location: 33 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 35 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_entrypoint--storage125992234--input289072903-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_entrypoint--storage125992234--input289072903-.out new file mode 100644 index 000000000000..b2d7e37f6688 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -self_with_entrypoint--storage125992234--input289072903-.out @@ -0,0 +1,93 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/self_with_entrypoint.tz on storage Unit and input 'Left (Left 0)' --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 13 (just consumed gas: 39.045) + [ (Pair (Left (Left 0)) Unit) ] + - location: 13 (just consumed gas: 0.010) + [ ] + - location: 14 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" ] + - location: 15 (just consumed gas: 0.526) + [ 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 ] + - location: 16 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 ] + - location: 17 (just consumed gas: 0.516) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 ] + - location: 18 (just consumed gas: 0.010) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 ] + - location: 19 (just consumed gas: 0.010) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 ] + - location: 21 (just consumed gas: 0.010) + [ 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 19 (just consumed gas: 0.035) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000017011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60041 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 24 (just consumed gas: 0.035) + [ -1 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 25 (just consumed gas: 0.010) + [ True + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 26 (just consumed gas: 0.010) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 26 (just consumed gas: 0.025) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 32 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 33 (just consumed gas: 0.516) + [ 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 + 0x050a00000016011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600 ] + - location: 36 (just consumed gas: 0.035) + [ 0 ] + - location: 37 (just consumed gas: 0.010) + [ True ] + - location: 38 (just consumed gas: 0.010) + [ ] + - location: 38 (just consumed gas: 0.025) + [ ] + - location: 44 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%A" ] + - location: 48 (just consumed gas: 0.010) + [ ] + - location: 49 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%B" ] + - location: 53 (just consumed gas: 0.010) + [ ] + - location: 54 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%maybe_C" ] + - location: 60 (just consumed gas: 0.010) + [ ] + - location: 61 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi%Z" ] + - location: 65 (just consumed gas: 0.010) + [ ] + - location: 66 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 76 (just consumed gas: 0.010) + [ ] + - location: 77 (just consumed gas: 0.010) + [ "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" ] + - location: 87 (just consumed gas: 0.010) + [ ] + - location: 88 (just consumed gas: 0.010) + [ Unit ] + - location: 89 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 91 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input620760059-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input620760059-.out new file mode 100644 index 000000000000..efd0db902c35 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input620760059-.out @@ -0,0 +1,49 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_car.tz on storage '(Pair "hello" 0)' and input '"world"' --level 1 --trace-stack +storage + (Pair "world" 0) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 10.806) + [ (Pair "world" "hello" 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "world" "hello" 0) + (Pair "world" "hello" 0) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "world" "hello" 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "world" "hello" 0) ] + - location: 13 (just consumed gas: 0.010) + [ "world" ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "hello" 0) + "world" ] + - location: 15 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "hello" 0) + "world" ] + - location: 16 (just consumed gas: 0.010) + [ "hello" + (Pair "hello" 0) + "world" ] + - location: 17 (just consumed gas: 0.010) + [ (Pair "hello" 0) + "world" ] + - location: 18 (just consumed gas: 0.010) + [ 0 + "world" ] + - location: 19 (just consumed gas: 0.010) + [ "world" + 0 ] + - location: 20 (just consumed gas: 0.010) + [ (Pair "world" 0) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair "world" 0) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} "world" 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input717096222-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input717096222-.out new file mode 100644 index 000000000000..56c1005caf79 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input717096222-.out @@ -0,0 +1,49 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_car.tz on storage '(Pair "hello" 0)' and input '"abc"' --level 1 --trace-stack +storage + (Pair "abc" 0) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 10.786) + [ (Pair "abc" "hello" 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "abc" "hello" 0) + (Pair "abc" "hello" 0) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "abc" "hello" 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "abc" "hello" 0) ] + - location: 13 (just consumed gas: 0.010) + [ "abc" ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "hello" 0) + "abc" ] + - location: 15 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "hello" 0) + "abc" ] + - location: 16 (just consumed gas: 0.010) + [ "hello" + (Pair "hello" 0) + "abc" ] + - location: 17 (just consumed gas: 0.010) + [ (Pair "hello" 0) + "abc" ] + - location: 18 (just consumed gas: 0.010) + [ 0 + "abc" ] + - location: 19 (just consumed gas: 0.010) + [ "abc" + 0 ] + - location: 20 (just consumed gas: 0.010) + [ (Pair "abc" 0) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair "abc" 0) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} "abc" 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input79230375-.out new file mode 100644 index 000000000000..543eb564497c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_car--storage224747103--input79230375-.out @@ -0,0 +1,49 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_car.tz on storage '(Pair "hello" 0)' and input '""' --level 1 --trace-stack +storage + (Pair "" 0) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 10.756) + [ (Pair "" "hello" 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "" "hello" 0) + (Pair "" "hello" 0) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "" "hello" 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "" "hello" 0) ] + - location: 13 (just consumed gas: 0.010) + [ "" ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "hello" 0) + "" ] + - location: 15 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "hello" 0) + "" ] + - location: 16 (just consumed gas: 0.010) + [ "hello" + (Pair "hello" 0) + "" ] + - location: 17 (just consumed gas: 0.010) + [ (Pair "hello" 0) + "" ] + - location: 18 (just consumed gas: 0.010) + [ 0 + "" ] + - location: 19 (just consumed gas: 0.010) + [ "" + 0 ] + - location: 20 (just consumed gas: 0.010) + [ (Pair "" 0) ] + - location: 21 (just consumed gas: 0.010) + [ {} + (Pair "" 0) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair {} "" 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage205576101--input654274102-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage205576101--input654274102-.out new file mode 100644 index 000000000000..3fb58b17f234 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage205576101--input654274102-.out @@ -0,0 +1,46 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_cdr.tz on storage '(Pair "hello" 500)' and input 3 --level 1 --trace-stack +storage + (Pair "hello" 3) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 10.182) + [ (Pair 3 "hello" 500) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair 3 "hello" 500) + (Pair 3 "hello" 500) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "hello" 500) + (Pair 3 "hello" 500) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 3 "hello" 500) ] + - location: 13 (just consumed gas: 0.010) + [ 3 ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "hello" 500) + 3 ] + - location: 15 (just consumed gas: 0.010) + [ (Pair "hello" 500) + (Pair "hello" 500) + 3 ] + - location: 16 (just consumed gas: 0.010) + [ 500 + (Pair "hello" 500) + 3 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair "hello" 500) + 3 ] + - location: 18 (just consumed gas: 0.010) + [ "hello" + 3 ] + - location: 19 (just consumed gas: 0.010) + [ (Pair "hello" 3) ] + - location: 20 (just consumed gas: 0.010) + [ {} + (Pair "hello" 3) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair {} "hello" 3) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage224747103--input453441034-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage224747103--input453441034-.out new file mode 100644 index 000000000000..18b84f05354c --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage224747103--input453441034-.out @@ -0,0 +1,46 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_cdr.tz on storage '(Pair "hello" 0)' and input 1 --level 1 --trace-stack +storage + (Pair "hello" 1) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 10.182) + [ (Pair 1 "hello" 0) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair 1 "hello" 0) + (Pair 1 "hello" 0) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair 1 "hello" 0) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 1 "hello" 0) ] + - location: 13 (just consumed gas: 0.010) + [ 1 ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "hello" 0) + 1 ] + - location: 15 (just consumed gas: 0.010) + [ (Pair "hello" 0) + (Pair "hello" 0) + 1 ] + - location: 16 (just consumed gas: 0.010) + [ 0 + (Pair "hello" 0) + 1 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair "hello" 0) + 1 ] + - location: 18 (just consumed gas: 0.010) + [ "hello" + 1 ] + - location: 19 (just consumed gas: 0.010) + [ (Pair "hello" 1) ] + - location: 20 (just consumed gas: 0.010) + [ {} + (Pair "hello" 1) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair {} "hello" 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage611418174--input967284912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage611418174--input967284912-.out new file mode 100644 index 000000000000..58e32231091f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_cdr--storage611418174--input967284912-.out @@ -0,0 +1,46 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_cdr.tz on storage '(Pair "hello" 7)' and input 100 --level 1 --trace-stack +storage + (Pair "hello" 100) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 10.182) + [ (Pair 100 "hello" 7) ] + - location: 9 (just consumed gas: 0.010) + [ (Pair 100 "hello" 7) + (Pair 100 "hello" 7) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "hello" 7) + (Pair 100 "hello" 7) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 100 "hello" 7) ] + - location: 13 (just consumed gas: 0.010) + [ 100 ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "hello" 7) + 100 ] + - location: 15 (just consumed gas: 0.010) + [ (Pair "hello" 7) + (Pair "hello" 7) + 100 ] + - location: 16 (just consumed gas: 0.010) + [ 7 + (Pair "hello" 7) + 100 ] + - location: 17 (just consumed gas: 0.010) + [ (Pair "hello" 7) + 100 ] + - location: 18 (just consumed gas: 0.010) + [ "hello" + 100 ] + - location: 19 (just consumed gas: 0.010) + [ (Pair "hello" 100) ] + - location: 20 (just consumed gas: 0.010) + [ {} + (Pair "hello" 100) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair {} "hello" 100) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input264787654-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input264787654-.out new file mode 100644 index 000000000000..855a38690457 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input264787654-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_id.tz on storage '{}' and input '{ "a" ; "b" ; "c" }' --level 1 --trace-stack +storage + { "a" ; "b" ; "c" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.523) + [ (Pair { "a" ; "b" ; "c" } {}) ] + - location: 9 (just consumed gas: 0.010) + [ { "a" ; "b" ; "c" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "a" ; "b" ; "c" } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { "a" ; "b" ; "c" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input457300675-.out new file mode 100644 index 000000000000..36ae5907ef49 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input457300675-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_id.tz on storage '{}' and input '{}' --level 1 --trace-stack +storage + {} +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 3.928) + [ (Pair {} {}) ] + - location: 9 (just consumed gas: 0.010) + [ {} ] + - location: 10 (just consumed gas: 0.010) + [ {} + {} ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} {}) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input989507347-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input989507347-.out new file mode 100644 index 000000000000..e0cc2c3f6f9b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_id--storage457300675--input989507347-.out @@ -0,0 +1,19 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_id.tz on storage '{}' and input '{ "asdf" ; "bcde" }' --level 1 --trace-stack +storage + { "asdf" ; "bcde" } +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 4.375) + [ (Pair { "asdf" ; "bcde" } {}) ] + - location: 9 (just consumed gas: 0.010) + [ { "asdf" ; "bcde" } ] + - location: 10 (just consumed gas: 0.010) + [ {} + { "asdf" ; "bcde" } ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} { "asdf" ; "bcde" }) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input457300675-.out new file mode 100644 index 000000000000..a49bbb82779b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input457300675-.out @@ -0,0 +1,27 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_iter.tz on storage 111 and input '{}' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.596) + [ (Pair {} 111) ] + - location: 8 (just consumed gas: 0.010) + [ {} ] + - location: 9 (just consumed gas: 0.010) + [ 0 + {} ] + - location: 12 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 13 (just consumed gas: 0.070) + [ 0 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input701684511-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input701684511-.out new file mode 100644 index 000000000000..3849f416c304 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input701684511-.out @@ -0,0 +1,47 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_iter.tz on storage 111 and input '{ -100 ; 1 ; 2 ; 3 }' --level 1 --trace-stack +storage + -94 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 7.301) + [ (Pair { -100 ; 1 ; 2 ; 3 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { -100 ; 1 ; 2 ; 3 } ] + - location: 9 (just consumed gas: 0.010) + [ 0 + { -100 ; 1 ; 2 ; 3 } ] + - location: 12 (just consumed gas: 0.010) + [ { -100 ; 1 ; 2 ; 3 } + 0 ] + - location: 13 (just consumed gas: 0.090) + [ -100 + 0 ] + - location: 15 (just consumed gas: 0.035) + [ -100 ] + - location: 13 (just consumed gas: 0.025) + [ 1 + -100 ] + - location: 15 (just consumed gas: 0.035) + [ -99 ] + - location: 13 (just consumed gas: 0.025) + [ 2 + -99 ] + - location: 15 (just consumed gas: 0.035) + [ -97 ] + - location: 13 (just consumed gas: 0.025) + [ 3 + -97 ] + - location: 15 (just consumed gas: 0.035) + [ -94 ] + - location: 13 (just consumed gas: 0.035) + [ -94 ] + - location: 16 (just consumed gas: 0.010) + [ {} + -94 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} -94) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input802622031-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input802622031-.out new file mode 100644 index 000000000000..f57088996dd2 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_iter--storage492856247--input802622031-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_iter.tz on storage 111 and input '{ 1 }' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 6.746) + [ (Pair { 1 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 } ] + - location: 9 (just consumed gas: 0.010) + [ 0 + { 1 } ] + - location: 12 (just consumed gas: 0.010) + [ { 1 } + 0 ] + - location: 13 (just consumed gas: 0.067) + [ 1 + 0 ] + - location: 15 (just consumed gas: 0.035) + [ 1 ] + - location: 13 (just consumed gas: 0.035) + [ 1 ] + - location: 16 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage495706788--input33757838-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage495706788--input33757838-.out new file mode 100644 index 000000000000..f255e779243d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage495706788--input33757838-.out @@ -0,0 +1,61 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_member.tz on storage '(Pair {} None)' and input '"Hi"' --level 1 --trace-stack +storage + (Pair {} (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 13.623) + [ (Pair "Hi" {} None) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "Hi" {} None) + (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 13 (just consumed gas: 0.010) + [ "Hi" + (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "Hi" {} None) + (Pair "Hi" {} None) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair {} None) + (Pair "Hi" {} None) ] + - location: 18 (just consumed gas: 0.010) + [ {} + (Pair "Hi" {} None) ] + - location: 14 (just consumed gas: 0.035) + [ "Hi" + {} + (Pair "Hi" {} None) ] + - location: 19 (just consumed gas: 0.040) + [ False + (Pair "Hi" {} None) ] + - location: 20 (just consumed gas: 0.010) + [ (Some False) + (Pair "Hi" {} None) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair "Hi" {} None) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + - location: 25 (just consumed gas: 0.010) + [ {} ] + - location: 21 (just consumed gas: 0.035) + [ (Some False) + {} ] + - location: 26 (just consumed gas: 0.010) + [ {} + (Some False) ] + - location: 27 (just consumed gas: 0.010) + [ (Pair {} (Some False)) ] + - location: 28 (just consumed gas: 0.010) + [ {} + (Pair {} (Some False)) ] + - location: 30 (just consumed gas: 0.010) + [ (Pair {} {} (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage550087893--input79230375-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage550087893--input79230375-.out new file mode 100644 index 000000000000..388f9b7599b9 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage550087893--input79230375-.out @@ -0,0 +1,61 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_member.tz on storage '(Pair { "Hello" ; "World" } None)' and input '""' --level 1 --trace-stack +storage + (Pair { "Hello" ; "World" } (Some False)) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 14.070) + [ (Pair "" { "Hello" ; "World" } None) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 13 (just consumed gas: 0.010) + [ "" + (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "" { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair { "Hello" ; "World" } None) + (Pair "" { "Hello" ; "World" } None) ] + - location: 18 (just consumed gas: 0.010) + [ { "Hello" ; "World" } + (Pair "" { "Hello" ; "World" } None) ] + - location: 14 (just consumed gas: 0.035) + [ "" + { "Hello" ; "World" } + (Pair "" { "Hello" ; "World" } None) ] + - location: 19 (just consumed gas: 0.040) + [ False + (Pair "" { "Hello" ; "World" } None) ] + - location: 20 (just consumed gas: 0.010) + [ (Some False) + (Pair "" { "Hello" ; "World" } None) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair "" { "Hello" ; "World" } None) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair { "Hello" ; "World" } None) ] + - location: 25 (just consumed gas: 0.010) + [ { "Hello" ; "World" } ] + - location: 21 (just consumed gas: 0.035) + [ (Some False) + { "Hello" ; "World" } ] + - location: 26 (just consumed gas: 0.010) + [ { "Hello" ; "World" } + (Some False) ] + - location: 27 (just consumed gas: 0.010) + [ (Pair { "Hello" ; "World" } (Some False)) ] + - location: 28 (just consumed gas: 0.010) + [ {} + (Pair { "Hello" ; "World" } (Some False)) ] + - location: 30 (just consumed gas: 0.010) + [ (Pair {} { "Hello" ; "World" } (Some False)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage605111220--input33757838-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage605111220--input33757838-.out new file mode 100644 index 000000000000..484043df36ce --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_member--storage605111220--input33757838-.out @@ -0,0 +1,61 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_member.tz on storage '(Pair { "Hi" } None)' and input '"Hi"' --level 1 --trace-stack +storage + (Pair { "Hi" } (Some True)) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 13.808) + [ (Pair "Hi" { "Hi" } None) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 13 (just consumed gas: 0.010) + [ "Hi" + (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "Hi" { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair { "Hi" } None) + (Pair "Hi" { "Hi" } None) ] + - location: 18 (just consumed gas: 0.010) + [ { "Hi" } + (Pair "Hi" { "Hi" } None) ] + - location: 14 (just consumed gas: 0.035) + [ "Hi" + { "Hi" } + (Pair "Hi" { "Hi" } None) ] + - location: 19 (just consumed gas: 0.040) + [ True + (Pair "Hi" { "Hi" } None) ] + - location: 20 (just consumed gas: 0.010) + [ (Some True) + (Pair "Hi" { "Hi" } None) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair "Hi" { "Hi" } None) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair { "Hi" } None) ] + - location: 25 (just consumed gas: 0.010) + [ { "Hi" } ] + - location: 21 (just consumed gas: 0.035) + [ (Some True) + { "Hi" } ] + - location: 26 (just consumed gas: 0.010) + [ { "Hi" } + (Some True) ] + - location: 27 (just consumed gas: 0.010) + [ (Pair { "Hi" } (Some True)) ] + - location: 28 (just consumed gas: 0.010) + [ {} + (Pair { "Hi" } (Some True)) ] + - location: 30 (just consumed gas: 0.010) + [ (Pair {} { "Hi" } (Some True)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input403499055-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input403499055-.out new file mode 100644 index 000000000000..ca5ebf2d9367 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input403499055-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_size.tz on storage 111 and input '{ 1 ; 2 ; 3 ; 4 ; 5 ; 6 }' --level 1 --trace-stack +storage + 6 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 5.361) + [ (Pair { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 ; 4 ; 5 ; 6 } ] + - location: 9 (just consumed gas: 0.010) + [ 6 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 6 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 6) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input457300675-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input457300675-.out new file mode 100644 index 000000000000..d866978aef91 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input457300675-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_size.tz on storage 111 and input '{}' --level 1 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.286) + [ (Pair {} 111) ] + - location: 8 (just consumed gas: 0.010) + [ {} ] + - location: 9 (just consumed gas: 0.010) + [ 0 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input469078912-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input469078912-.out new file mode 100644 index 000000000000..9466a464668b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input469078912-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_size.tz on storage 111 and input '{ 1 ; 2 ; 3 }' --level 1 --trace-stack +storage + 3 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.806) + [ (Pair { 1 ; 2 ; 3 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 ; 2 ; 3 } ] + - location: 9 (just consumed gas: 0.010) + [ 3 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 3 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 3) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input802622031-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input802622031-.out new file mode 100644 index 000000000000..7988482c74eb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -set_size--storage492856247--input802622031-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/set_size.tz on storage 111 and input '{ 1 }' --level 1 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.436) + [ (Pair { 1 } 111) ] + - location: 8 (just consumed gas: 0.010) + [ { 1 } ] + - location: 9 (just consumed gas: 0.010) + [ 1 ] + - location: 10 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 1) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sha3--storage921624073--input1008262038-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sha3--storage921624073--input1008262038-.out new file mode 100644 index 000000000000..6165e1e83500 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sha3--storage921624073--input1008262038-.out @@ -0,0 +1,24 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/sha3.tz on storage None and input 0x48656c6c6f2c20776f726c6421 --level 1 --trace-stack +storage + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722) +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.907) + [ (Pair 0x48656c6c6f2c20776f726c6421 None) ] + - location: 8 (just consumed gas: 0.010) + [ 0x48656c6c6f2c20776f726c6421 ] + - location: 9 (just consumed gas: 1.457) + [ 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722 ] + - location: 10 (just consumed gas: 0.010) + [ (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722) ] + - location: 11 (just consumed gas: 0.010) + [ {} + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair {} + (Some 0xf345a219da005ebe9c1a1eaad97bbf38a10c8473e41d0af7fb617caa0c6aa722)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input115382786-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input115382786-.out new file mode 100644 index 000000000000..8fc2644e0ad1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input115382786-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 15 2))' --level 1 --trace-stack +storage + (Some 60) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 15 2)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 15 2)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 15 2) ] + - location: 17 (just consumed gas: 0.010) + [ 15 + 2 ] + - location: 18 (just consumed gas: 0.128) + [ 60 ] + - location: 15 (just consumed gas: 0.025) + [ 60 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 60) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 60) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 60)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input271566295-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input271566295-.out new file mode 100644 index 000000000000..5f578d52fd54 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input271566295-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 0 1))' --level 1 --trace-stack +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 0 1)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 0 1)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 0 1) ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 1 ] + - location: 21 (just consumed gas: 0.045) + [ 0 ] + - location: 15 (just consumed gas: 0.025) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 0) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 0) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 0)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input340971987-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input340971987-.out new file mode 100644 index 000000000000..98560606cbbb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input340971987-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 0 0))' --level 1 --trace-stack +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 0 0)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 0 0)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 17 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 18 (just consumed gas: 0.128) + [ 0 ] + - location: 15 (just consumed gas: 0.025) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 0) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 0) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 0)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input374168553-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input374168553-.out new file mode 100644 index 000000000000..4513a3c0fdee --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input374168553-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 15 2))' --level 1 --trace-stack +storage + (Some 3) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 15 2)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 15 2)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 15 2) ] + - location: 20 (just consumed gas: 0.010) + [ 15 + 2 ] + - location: 21 (just consumed gas: 0.045) + [ 3 ] + - location: 15 (just consumed gas: 0.025) + [ 3 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 3) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 3) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 3)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input413621582-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input413621582-.out new file mode 100644 index 000000000000..6d378c2ca692 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input413621582-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 1 2))' --level 1 --trace-stack +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 1 2)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 1 2)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 1 2) ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 2 ] + - location: 21 (just consumed gas: 0.045) + [ 0 ] + - location: 15 (just consumed gas: 0.025) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 0) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 0) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 0)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input424849461-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input424849461-.out new file mode 100644 index 000000000000..925f45286971 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input424849461-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 1 2))' --level 1 --trace-stack +storage + (Some 4) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 1 2)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 1 2)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 1 2) ] + - location: 17 (just consumed gas: 0.010) + [ 1 + 2 ] + - location: 18 (just consumed gas: 0.128) + [ 4 ] + - location: 15 (just consumed gas: 0.025) + [ 4 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 4) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 4) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 4)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input485030042-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input485030042-.out new file mode 100644 index 000000000000..96da8a91dd63 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input485030042-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 8 1))' --level 1 --trace-stack +storage + (Some 16) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 8 1)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 8 1)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 8 1) ] + - location: 17 (just consumed gas: 0.010) + [ 8 + 1 ] + - location: 18 (just consumed gas: 0.128) + [ 16 ] + - location: 15 (just consumed gas: 0.025) + [ 16 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 16) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 16) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 16)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input705767726-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input705767726-.out new file mode 100644 index 000000000000..971eeaefb3f6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input705767726-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 8 1))' --level 1 --trace-stack +storage + (Some 4) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 8 1)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 8 1)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 8 1) ] + - location: 20 (just consumed gas: 0.010) + [ 8 + 1 ] + - location: 21 (just consumed gas: 0.045) + [ 4 ] + - location: 15 (just consumed gas: 0.025) + [ 4 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 4) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 4) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 4)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input769385932-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input769385932-.out new file mode 100644 index 000000000000..0b02153dd439 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input769385932-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 0 1))' --level 1 --trace-stack +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 0 1)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 0 1)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 0 1) ] + - location: 17 (just consumed gas: 0.010) + [ 0 + 1 ] + - location: 18 (just consumed gas: 0.128) + [ 0 ] + - location: 15 (just consumed gas: 0.025) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 0) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 0) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 0)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input913715337-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input913715337-.out new file mode 100644 index 000000000000..d36535d6149d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -shifts--storage921624073--input913715337-.out @@ -0,0 +1,30 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 0 0))' --level 1 --trace-stack +storage + (Some 0) +emitted operations + +big_map diff + +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 0 0)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 0 0)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 21 (just consumed gas: 0.045) + [ 0 ] + - location: 15 (just consumed gas: 0.025) + [ 0 ] + - location: 22 (just consumed gas: 0.010) + [ (Some 0) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Some 0) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} (Some 0)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage351480851--input65907686-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage351480851--input65907686-.out new file mode 100644 index 000000000000..ad90e5a3e10f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage351480851--input65907686-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some"FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo"' and input 'Pair 1 10000' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 69.136) + [ (Pair (Pair 1 10000) + (Some "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 10000) + (Some "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo") + (Pair 1 10000) ] + - location: 13 (just consumed gas: 0.010) + [ "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo" + (Pair 1 10000) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 10000) + "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo" ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 10000 + "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo" ] + - location: 21 (just consumed gas: 3.025) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input198821575-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input198821575-.out new file mode 100644 index 000000000000..790e91ae6101 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input198821575-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some "Foo"' and input 'Pair 1 1' --level 1 --trace-stack +storage + (Some "o") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.166) + [ (Pair (Pair 1 1) (Some "Foo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 1) + (Some "Foo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "Foo") + (Pair 1 1) ] + - location: 13 (just consumed gas: 0.010) + [ "Foo" + (Pair 1 1) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 1) + "Foo" ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 1 + "Foo" ] + - location: 21 (just consumed gas: 0.026) + [ (Some "o") ] + - location: 13 (just consumed gas: 0.025) + [ (Some "o") ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some "o") ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some "o")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input359592843-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input359592843-.out new file mode 100644 index 000000000000..29039e2b9788 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input359592843-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some "Foo"' and input 'Pair 10 5' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.166) + [ (Pair (Pair 10 5) (Some "Foo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 10 5) + (Some "Foo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "Foo") + (Pair 10 5) ] + - location: 13 (just consumed gas: 0.010) + [ "Foo" + (Pair 10 5) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 10 5) + "Foo" ] + - location: 20 (just consumed gas: 0.010) + [ 10 + 5 + "Foo" ] + - location: 21 (just consumed gas: 0.026) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input551316239-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input551316239-.out new file mode 100644 index 000000000000..49c6f87ce3b3 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input551316239-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some "Foo"' and input 'Pair 0 0' --level 1 --trace-stack +storage + (Some "") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.166) + [ (Pair (Pair 0 0) (Some "Foo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 0) + (Some "Foo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "Foo") + (Pair 0 0) ] + - location: 13 (just consumed gas: 0.010) + [ "Foo" + (Pair 0 0) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 0 0) + "Foo" ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 0 + "Foo" ] + - location: 21 (just consumed gas: 0.026) + [ (Some "") ] + - location: 13 (just consumed gas: 0.025) + [ (Some "") ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some "") ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some "")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input722749044-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input722749044-.out new file mode 100644 index 000000000000..91f44bff12ed --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input722749044-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some "Foo"' and input 'Pair 0 10' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.166) + [ (Pair (Pair 0 10) (Some "Foo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 10) + (Some "Foo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "Foo") + (Pair 0 10) ] + - location: 13 (just consumed gas: 0.010) + [ "Foo" + (Pair 0 10) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 0 10) + "Foo" ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 10 + "Foo" ] + - location: 21 (just consumed gas: 0.026) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input839234860-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input839234860-.out new file mode 100644 index 000000000000..422d2a1ac0ae --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input839234860-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some "Foo"' and input 'Pair 1 3' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.166) + [ (Pair (Pair 1 3) (Some "Foo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 3) + (Some "Foo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "Foo") + (Pair 1 3) ] + - location: 13 (just consumed gas: 0.010) + [ "Foo" + (Pair 1 3) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 3) + "Foo" ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 3 + "Foo" ] + - location: 21 (just consumed gas: 0.026) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input919180079-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input919180079-.out new file mode 100644 index 000000000000..75fd51b64c7f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage364922380--input919180079-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage 'Some "Foo"' and input 'Pair 0 2' --level 1 --trace-stack +storage + (Some "Fo") +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.166) + [ (Pair (Pair 0 2) (Some "Foo")) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 2) + (Some "Foo") ] + - location: 11 (just consumed gas: 0.010) + [ (Some "Foo") + (Pair 0 2) ] + - location: 13 (just consumed gas: 0.010) + [ "Foo" + (Pair 0 2) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 0 2) + "Foo" ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 2 + "Foo" ] + - location: 21 (just consumed gas: 0.026) + [ (Some "Fo") ] + - location: 13 (just consumed gas: 0.025) + [ (Some "Fo") ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some "Fo") ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some "Fo")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage921624073--input551316239-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage921624073--input551316239-.out new file mode 100644 index 000000000000..f445a11d1214 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice--storage921624073--input551316239-.out @@ -0,0 +1,31 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice.tz on storage None and input 'Pair 0 0' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.021) + [ (Pair (Pair 0 0) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 0) + None ] + - location: 11 (just consumed gas: 0.010) + [ None + (Pair 0 0) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 15 (just consumed gas: 0.010) + [ ] + - location: 16 (just consumed gas: 0.010) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input198821575-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input198821575-.out new file mode 100644 index 000000000000..f4d3bc420055 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input198821575-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 1 1' --level 1 --trace-stack +storage + (Some 0xbb) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 1 1) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 1) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 1 1) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 1 1) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 1) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 1 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ (Some 0xbb) ] + - location: 13 (just consumed gas: 0.025) + [ (Some 0xbb) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some 0xbb) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some 0xbb)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input462551352-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input462551352-.out new file mode 100644 index 000000000000..ef424ee4e00d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input462551352-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 0 1' --level 1 --trace-stack +storage + (Some 0xaa) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 0 1) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 1) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 0 1) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 0 1) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 0 1) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 1 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ (Some 0xaa) ] + - location: 13 (just consumed gas: 0.025) + [ (Some 0xaa) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some 0xaa) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some 0xaa)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input489157380-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input489157380-.out new file mode 100644 index 000000000000..d86623e945da --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input489157380-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 1 2' --level 1 --trace-stack +storage + (Some 0xbbcc) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 1 2) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 2) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 1 2) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 1 2) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 2) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 2 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ (Some 0xbbcc) ] + - location: 13 (just consumed gas: 0.025) + [ (Some 0xbbcc) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some 0xbbcc) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some 0xbbcc)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input551316239-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input551316239-.out new file mode 100644 index 000000000000..ff1ebb81bfc1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input551316239-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 0 0' --level 1 --trace-stack +storage + (Some 0x) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 0 0) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 0) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 0 0) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 0 0) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 0 0) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 0 + 0 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ (Some 0x) ] + - location: 13 (just consumed gas: 0.025) + [ (Some 0x) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some 0x) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some 0x)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input669330759-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input669330759-.out new file mode 100644 index 000000000000..a05455852464 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input669330759-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 2 2' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 2 2) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 2 2) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 2 2) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 2 2) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 2 2) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 2 + 2 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input743596105-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input743596105-.out new file mode 100644 index 000000000000..2f0ee241d624 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input743596105-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 2 1' --level 1 --trace-stack +storage + (Some 0xcc) +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 2 1) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 2 1) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 2 1) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 2 1) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 2 1) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 2 + 1 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ (Some 0xcc) ] + - location: 13 (just consumed gas: 0.025) + [ (Some 0xcc) ] + - location: 22 (just consumed gas: 0.010) + [ {} + (Some 0xcc) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} (Some 0xcc)) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input839234860-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input839234860-.out new file mode 100644 index 000000000000..38bd212ba3de --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage229749865--input839234860-.out @@ -0,0 +1,37 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbcc' and input 'Pair 1 3' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 1 3) (Some 0xaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 3) + (Some 0xaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbcc) + (Pair 1 3) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbcc + (Pair 1 3) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 3) + 0xaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 3 + 0xaabbcc ] + - location: 21 (just consumed gas: 0.026) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage504917929--input65907686-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage504917929--input65907686-.out new file mode 100644 index 000000000000..9f293721ced9 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage504917929--input65907686-.out @@ -0,0 +1,38 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage 'Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc' and input 'Pair 1 10000' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.121) + [ (Pair (Pair 1 10000) + (Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc)) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 10000) + (Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc) ] + - location: 11 (just consumed gas: 0.010) + [ (Some 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc) + (Pair 1 10000) ] + - location: 13 (just consumed gas: 0.010) + [ 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc + (Pair 1 10000) ] + - location: 19 (just consumed gas: 0.010) + [ (Pair 1 10000) + 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 10000 + 0xaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbccaabbcc ] + - location: 21 (just consumed gas: 3.025) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage921624073--input462551352-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage921624073--input462551352-.out new file mode 100644 index 000000000000..434c2198adcc --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -slice_bytes--storage921624073--input462551352-.out @@ -0,0 +1,31 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/slice_bytes.tz on storage None and input 'Pair 0 1' --level 1 --trace-stack +storage + None +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 9.021) + [ (Pair (Pair 0 1) None) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 0 1) + None ] + - location: 11 (just consumed gas: 0.010) + [ None + (Pair 0 1) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair 0 1) ] + - location: 15 (just consumed gas: 0.010) + [ ] + - location: 16 (just consumed gas: 0.010) + [ None ] + - location: 13 (just consumed gas: 0.025) + [ None ] + - location: 22 (just consumed gas: 0.010) + [ {} + None ] + - location: 24 (just consumed gas: 0.010) + [ (Pair {} None) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input1016369050-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input1016369050-.out new file mode 100644 index 000000000000..da654eab061b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input1016369050-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/str_id.tz on storage None and input '"abcd"' --level 1 --trace-stack +storage + (Some "abcd") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.408) + [ (Pair "abcd" None) ] + - location: 8 (just consumed gas: 0.010) + [ "abcd" ] + - location: 9 (just consumed gas: 0.010) + [ (Some "abcd") ] + - location: 10 (just consumed gas: 0.010) + [ {} + (Some "abcd") ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} (Some "abcd")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input93477117-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input93477117-.out new file mode 100644 index 000000000000..96befd878a92 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -str_id--storage921624073--input93477117-.out @@ -0,0 +1,21 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/str_id.tz on storage None and input '"Hello"' --level 1 --trace-stack +storage + (Some "Hello") +emitted operations + +big_map diff + +trace + - location: 8 (just consumed gas: 4.418) + [ (Pair "Hello" None) ] + - location: 8 (just consumed gas: 0.010) + [ "Hello" ] + - location: 9 (just consumed gas: 0.010) + [ (Some "Hello") ] + - location: 10 (just consumed gas: 0.010) + [ {} + (Some "Hello") ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} (Some "Hello")) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out new file mode 100644 index 000000000000..b4e11f6f9b30 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input249636002-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/sub_timestamp_delta.tz on storage 111 and input '(Pair 100 100)' --level 1 --trace-stack +storage + "1970-01-01T00:00:00Z" +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.334) + [ (Pair (Pair "1970-01-01T00:01:40Z" 100) "1970-01-01T00:01:51Z") ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 100) + (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 100) ] + - location: 14 (just consumed gas: 0.010) + [ 100 ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:01:40Z" + 100 ] + - location: 15 (just consumed gas: 0.035) + [ "1970-01-01T00:00:00Z" ] + - location: 16 (just consumed gas: 0.010) + [ {} + "1970-01-01T00:00:00Z" ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} "1970-01-01T00:00:00Z") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out new file mode 100644 index 000000000000..63b4d760375a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input307538219-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/sub_timestamp_delta.tz on storage 111 and input '(Pair 100 -100)' --level 1 --trace-stack +storage + "1970-01-01T00:03:20Z" +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.334) + [ (Pair (Pair "1970-01-01T00:01:40Z" -100) "1970-01-01T00:01:51Z") ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" -100) + (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" -100) ] + - location: 14 (just consumed gas: 0.010) + [ -100 ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:01:40Z" + -100 ] + - location: 15 (just consumed gas: 0.035) + [ "1970-01-01T00:03:20Z" ] + - location: 16 (just consumed gas: 0.010) + [ {} + "1970-01-01T00:03:20Z" ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} "1970-01-01T00:03:20Z") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out new file mode 100644 index 000000000000..960c350821ee --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -sub_timestamp_delta--storage492856247--input831449542-.out @@ -0,0 +1,34 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/sub_timestamp_delta.tz on storage 111 and input '(Pair 100 2000000000000000000)' --level 1 --trace-stack +storage + -1999999999999999900 +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 7.334) + [ (Pair (Pair "1970-01-01T00:01:40Z" 2000000000000000000) "1970-01-01T00:01:51Z") ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 2000000000000000000) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 2000000000000000000) + (Pair "1970-01-01T00:01:40Z" 2000000000000000000) ] + - location: 11 (just consumed gas: 0.010) + [ "1970-01-01T00:01:40Z" + (Pair "1970-01-01T00:01:40Z" 2000000000000000000) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1970-01-01T00:01:40Z" 2000000000000000000) ] + - location: 14 (just consumed gas: 0.010) + [ 2000000000000000000 ] + - location: 12 (just consumed gas: 0.035) + [ "1970-01-01T00:01:40Z" + 2000000000000000000 ] + - location: 15 (just consumed gas: 0.039) + [ -1999999999999999900 ] + - location: 16 (just consumed gas: 0.010) + [ {} + -1999999999999999900 ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} -1999999999999999900) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input706350605-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input706350605-.out new file mode 100644 index 000000000000..b9ddb7e942cb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input706350605-.out @@ -0,0 +1,71 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/tez_add_sub.tz on storage None and input '(Pair 2310000 1010000)' --level 1 --trace-stack +storage + (Some (Pair 3320000 1300000)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 16.709) + [ (Pair (Pair 2310000 1010000) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) + (Pair 2310000 1010000) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) + (Pair 2310000 1010000) + (Pair 2310000 1010000) ] + - location: 15 (just consumed gas: 0.010) + [ 2310000 + (Pair 2310000 1010000) + (Pair 2310000 1010000) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) + (Pair 2310000 1010000) ] + - location: 18 (just consumed gas: 0.010) + [ 1010000 + (Pair 2310000 1010000) ] + - location: 16 (just consumed gas: 0.035) + [ 2310000 + 1010000 + (Pair 2310000 1010000) ] + - location: 19 (just consumed gas: 0.020) + [ 3320000 + (Pair 2310000 1010000) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) + (Pair 2310000 1010000) ] + - location: 23 (just consumed gas: 0.010) + [ 2310000 + (Pair 2310000 1010000) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 2310000 1010000) ] + - location: 26 (just consumed gas: 0.010) + [ 1010000 ] + - location: 24 (just consumed gas: 0.035) + [ 2310000 + 1010000 ] + - location: 27 (just consumed gas: 0.015) + [ (Some 1300000) ] + - location: 29 (just consumed gas: 0.010) + [ 1300000 ] + - location: 29 (just consumed gas: 0.025) + [ 1300000 ] + - location: 20 (just consumed gas: 0.035) + [ 3320000 + 1300000 ] + - location: 35 (just consumed gas: 0.010) + [ (Pair 3320000 1300000) ] + - location: 36 (just consumed gas: 0.010) + [ (Some (Pair 3320000 1300000)) ] + - location: 37 (just consumed gas: 0.010) + [ {} + (Some (Pair 3320000 1300000)) ] + - location: 39 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair 3320000 1300000))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input856198194-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input856198194-.out new file mode 100644 index 000000000000..a8d8c9edcfa5 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -tez_add_sub--storage921624073--input856198194-.out @@ -0,0 +1,71 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/tez_add_sub.tz on storage None and input '(Pair 2000000 1000000)' --level 1 --trace-stack +storage + (Some (Pair 3000000 1000000)) +emitted operations + +big_map diff + +trace + - location: 12 (just consumed gas: 16.709) + [ (Pair (Pair 2000000 1000000) None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) ] + - location: 13 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) + (Pair 2000000 1000000) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) + (Pair 2000000 1000000) + (Pair 2000000 1000000) ] + - location: 15 (just consumed gas: 0.010) + [ 2000000 + (Pair 2000000 1000000) + (Pair 2000000 1000000) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) + (Pair 2000000 1000000) ] + - location: 18 (just consumed gas: 0.010) + [ 1000000 + (Pair 2000000 1000000) ] + - location: 16 (just consumed gas: 0.035) + [ 2000000 + 1000000 + (Pair 2000000 1000000) ] + - location: 19 (just consumed gas: 0.020) + [ 3000000 + (Pair 2000000 1000000) ] + - location: 20 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) ] + - location: 22 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) + (Pair 2000000 1000000) ] + - location: 23 (just consumed gas: 0.010) + [ 2000000 + (Pair 2000000 1000000) ] + - location: 24 (just consumed gas: 0.010) + [ (Pair 2000000 1000000) ] + - location: 26 (just consumed gas: 0.010) + [ 1000000 ] + - location: 24 (just consumed gas: 0.035) + [ 2000000 + 1000000 ] + - location: 27 (just consumed gas: 0.015) + [ (Some 1000000) ] + - location: 29 (just consumed gas: 0.010) + [ 1000000 ] + - location: 29 (just consumed gas: 0.025) + [ 1000000 ] + - location: 20 (just consumed gas: 0.035) + [ 3000000 + 1000000 ] + - location: 35 (just consumed gas: 0.010) + [ (Pair 3000000 1000000) ] + - location: 36 (just consumed gas: 0.010) + [ (Some (Pair 3000000 1000000)) ] + - location: 37 (just consumed gas: 0.010) + [ {} + (Some (Pair 3000000 1000000)) ] + - location: 39 (just consumed gas: 0.010) + [ (Pair {} (Some (Pair 3000000 1000000))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -uncomb--storage680650890--input394061083-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -uncomb--storage680650890--input394061083-.out new file mode 100644 index 000000000000..819fea3c43bf --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -uncomb--storage680650890--input394061083-.out @@ -0,0 +1,50 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/uncomb.tz on storage 0 and input '(Pair 1 4 2)' --level 1 --trace-stack +storage + 142 +emitted operations + +big_map diff + +trace + - location: 10 (just consumed gas: 10.047) + [ (Pair (Pair 1 4 2) 0) ] + - location: 10 (just consumed gas: 0.010) + [ (Pair 1 4 2) ] + - location: 11 (just consumed gas: 0.034) + [ 1 + 4 + 2 ] + - location: 13 (just consumed gas: 0.010) + [ 100 + 1 + 4 + 2 ] + - location: 16 (just consumed gas: 0.059) + [ 100 + 4 + 2 ] + - location: 17 (just consumed gas: 0.010) + [ 4 + 100 + 2 ] + - location: 18 (just consumed gas: 0.010) + [ 10 + 4 + 100 + 2 ] + - location: 21 (just consumed gas: 0.059) + [ 40 + 100 + 2 ] + - location: 22 (just consumed gas: 0.035) + [ 140 + 2 ] + - location: 23 (just consumed gas: 0.035) + [ 142 ] + - location: 24 (just consumed gas: 0.010) + [ {} + 142 ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} 142) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -unpair--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -unpair--storage125992234--input125992234-.out new file mode 100644 index 000000000000..30148392ccfb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -unpair--storage125992234--input125992234-.out @@ -0,0 +1,462 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/unpair.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 126.560) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ Unit ] + - location: 9 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 10 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 11 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 12 (just consumed gas: 0.035) + [ ] + - location: 14 (just consumed gas: 0.010) + [ Unit ] + - location: 15 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 16 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 17 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 18 (just consumed gas: 0.035) + [ ] + - location: 20 (just consumed gas: 0.010) + [ Unit ] + - location: 21 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 22 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 23 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 24 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 25 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 27 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 28 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 29 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 32 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 33 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 35 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 36 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 37 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 39 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 40 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 41 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 43 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 44 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 45 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 47 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 48 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 49 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 51 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 52 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 53 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 55 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 56 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 57 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 59 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 60 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 61 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 63 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 64 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 65 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 67 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 68 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 69 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 71 (just consumed gas: 0.010) + [ ] + - location: 72 (just consumed gas: 0.010) + [ Unit ] + - location: 73 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 74 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 75 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 76 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 77 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 79 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 80 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 81 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 83 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 84 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 85 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 87 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 88 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 89 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 91 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 92 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 93 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 95 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 96 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 97 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 99 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 100 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 101 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 103 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 104 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 105 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 107 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 108 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 109 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 111 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 112 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 113 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 115 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 116 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 117 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 119 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 120 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 121 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 123 (just consumed gas: 0.010) + [ ] + - location: 124 (just consumed gas: 0.010) + [ Unit ] + - location: 125 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 126 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 127 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 128 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 129 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 131 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 132 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 133 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 135 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 136 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 137 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 139 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 140 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 141 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 143 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 144 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 145 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 147 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 148 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 149 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 151 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 152 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 153 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 155 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 156 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 157 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 159 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 160 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 161 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 163 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 164 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 165 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 167 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 168 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 169 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 171 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 172 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 173 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 175 (just consumed gas: 0.010) + [ ] + - location: 176 (just consumed gas: 0.010) + [ Unit ] + - location: 177 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 178 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 179 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 180 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 181 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 183 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 184 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 185 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 187 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 188 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 189 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 191 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 192 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 193 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 195 (just consumed gas: 0.010) + [ (Pair Unit Unit) + (Pair Unit Unit) ] + - location: 196 (just consumed gas: 0.010) + [ Unit + Unit + (Pair Unit Unit) ] + - location: 197 (just consumed gas: 0.035) + [ (Pair Unit Unit) ] + - location: 199 (just consumed gas: 0.010) + [ ] + - location: 200 (just consumed gas: 0.010) + [ Unit ] + - location: 201 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 202 (just consumed gas: 0.010) + [ (Pair Unit Unit) ] + - location: 203 (just consumed gas: 0.010) + [ Unit + Unit ] + - location: 204 (just consumed gas: 0.035) + [ ] + - location: 206 (just consumed gas: 0.010) + [ Unit ] + - location: 207 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 209 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -voting_power--storage1011138251--input1040351577-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -voting_power--storage1011138251--input1040351577-.out new file mode 100644 index 000000000000..d40efddfbca9 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -voting_power--storage1011138251--input1040351577-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/voting_power.tz on storage '(Pair 0 0)' and input '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"' --level 1 --trace-stack +storage + (Pair 4000000000000 20000000000000) +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 86.168) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" 0 0) ] + - location: 9 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" ] + - location: 10 (just consumed gas: 0.605) + [ "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ] + - location: 11 (just consumed gas: 220.656) + [ 4000000000000 ] + - location: 12 (just consumed gas: 0.010) + [ ] + - location: 14 (just consumed gas: 210.466) + [ 20000000000000 ] + - location: 12 (just consumed gas: 0.035) + [ 4000000000000 + 20000000000000 ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 4000000000000 20000000000000) ] + - location: 16 (just consumed gas: 0.010) + [ {} + (Pair 4000000000000 20000000000000) ] + - location: 18 (just consumed gas: 0.010) + [ (Pair {} 4000000000000 20000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1058477720-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1058477720-.out new file mode 100644 index 000000000000..7f74186b5d24 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1058477720-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Left (Pair False False)' --level 1 --trace-stack +storage + (Some (Left False)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Left (Pair False False)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Left (Pair False False)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair False False) ] + - location: 19 (just consumed gas: 0.010) + [ False + False ] + - location: 20 (just consumed gas: 0.015) + [ False ] + - location: 21 (just consumed gas: 0.010) + [ (Left False) ] + - location: 17 (just consumed gas: 0.025) + [ (Left False) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Left False)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Left False)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Left False))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1073176155-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1073176155-.out new file mode 100644 index 000000000000..90632ac1258d --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input1073176155-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Right (Pair 0 0)' --level 1 --trace-stack +storage + (Some (Right 0)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Right (Pair 0 0)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Right (Pair 0 0)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 0 0) ] + - location: 24 (just consumed gas: 0.010) + [ 0 + 0 ] + - location: 25 (just consumed gas: 0.035) + [ 0 ] + - location: 26 (just consumed gas: 0.010) + [ (Right 0) ] + - location: 17 (just consumed gas: 0.025) + [ (Right 0) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Right 0)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Right 0)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Right 0))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input246594902-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input246594902-.out new file mode 100644 index 000000000000..2402cebd8921 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input246594902-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Left (Pair True False)' --level 1 --trace-stack +storage + (Some (Left True)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Left (Pair True False)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Left (Pair True False)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair True False) ] + - location: 19 (just consumed gas: 0.010) + [ True + False ] + - location: 20 (just consumed gas: 0.015) + [ True ] + - location: 21 (just consumed gas: 0.010) + [ (Left True) ] + - location: 17 (just consumed gas: 0.025) + [ (Left True) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Left True)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Left True)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Left True))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input506603577-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input506603577-.out new file mode 100644 index 000000000000..762c28204dc7 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input506603577-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Right (Pair 1 1)' --level 1 --trace-stack +storage + (Some (Right 0)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Right (Pair 1 1)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Right (Pair 1 1)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 1 1) ] + - location: 24 (just consumed gas: 0.010) + [ 1 + 1 ] + - location: 25 (just consumed gas: 0.035) + [ 0 ] + - location: 26 (just consumed gas: 0.010) + [ (Right 0) ] + - location: 17 (just consumed gas: 0.025) + [ (Right 0) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Right 0)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Right 0)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Right 0))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input576248088-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input576248088-.out new file mode 100644 index 000000000000..95951b53fb23 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input576248088-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Right (Pair 0 1)' --level 1 --trace-stack +storage + (Some (Right 1)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Right (Pair 0 1)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Right (Pair 0 1)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 0 1) ] + - location: 24 (just consumed gas: 0.010) + [ 0 + 1 ] + - location: 25 (just consumed gas: 0.035) + [ 1 ] + - location: 26 (just consumed gas: 0.010) + [ (Right 1) ] + - location: 17 (just consumed gas: 0.025) + [ (Right 1) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Right 1)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Right 1)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Right 1))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input612012282-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input612012282-.out new file mode 100644 index 000000000000..94a920c58e46 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input612012282-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Right (Pair 42 21)' --level 1 --trace-stack +storage + (Some (Right 63)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Right (Pair 42 21)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Right (Pair 42 21)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 42 21) ] + - location: 24 (just consumed gas: 0.010) + [ 42 + 21 ] + - location: 25 (just consumed gas: 0.035) + [ 63 ] + - location: 26 (just consumed gas: 0.010) + [ (Right 63) ] + - location: 17 (just consumed gas: 0.025) + [ (Right 63) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Right 63)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Right 63)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Right 63))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input617591686-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input617591686-.out new file mode 100644 index 000000000000..773023ee2b69 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input617591686-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Left (Pair False True)' --level 1 --trace-stack +storage + (Some (Left True)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Left (Pair False True)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Left (Pair False True)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair False True) ] + - location: 19 (just consumed gas: 0.010) + [ False + True ] + - location: 20 (just consumed gas: 0.015) + [ True ] + - location: 21 (just consumed gas: 0.010) + [ (Left True) ] + - location: 17 (just consumed gas: 0.025) + [ (Left True) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Left True)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Left True)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Left True))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input639311176-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input639311176-.out new file mode 100644 index 000000000000..1238c8db8240 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input639311176-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Left (Pair True True)' --level 1 --trace-stack +storage + (Some (Left False)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Left (Pair True True)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Left (Pair True True)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair True True) ] + - location: 19 (just consumed gas: 0.010) + [ True + True ] + - location: 20 (just consumed gas: 0.015) + [ False ] + - location: 21 (just consumed gas: 0.010) + [ (Left False) ] + - location: 17 (just consumed gas: 0.025) + [ (Left False) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Left False)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Left False)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Left False))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input688315180-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input688315180-.out new file mode 100644 index 000000000000..0e0f11170dbb --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input688315180-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Right (Pair 42 63)' --level 1 --trace-stack +storage + (Some (Right 21)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Right (Pair 42 63)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Right (Pair 42 63)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 42 63) ] + - location: 24 (just consumed gas: 0.010) + [ 42 + 63 ] + - location: 25 (just consumed gas: 0.035) + [ 21 ] + - location: 26 (just consumed gas: 0.010) + [ (Right 21) ] + - location: 17 (just consumed gas: 0.025) + [ (Right 21) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Right 21)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Right 21)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Right 21))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input967929605-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input967929605-.out new file mode 100644 index 000000000000..f3880b628eb6 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor--storage921624073--input967929605-.out @@ -0,0 +1,32 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor.tz on storage None and input 'Right (Pair 1 0)' --level 1 --trace-stack +storage + (Some (Right 1)) +emitted operations + +big_map diff + +trace + - location: 16 (just consumed gas: 10.744) + [ (Pair (Right (Pair 1 0)) None) ] + - location: 16 (just consumed gas: 0.010) + [ (Right (Pair 1 0)) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair 1 0) ] + - location: 24 (just consumed gas: 0.010) + [ 1 + 0 ] + - location: 25 (just consumed gas: 0.035) + [ 1 ] + - location: 26 (just consumed gas: 0.010) + [ (Right 1) ] + - location: 17 (just consumed gas: 0.025) + [ (Right 1) ] + - location: 28 (just consumed gas: 0.010) + [ (Some (Right 1)) ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Some (Right 1)) ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} (Some (Right 1))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor_bytes--storage125992234--input125992234-.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor_bytes--storage125992234--input125992234-.out new file mode 100644 index 000000000000..f461d57eae5f --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- opcodes -xor_bytes--storage125992234--input125992234-.out @@ -0,0 +1,75 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run script michelson_test_scripts/opcodes/xor_bytes_016.tz on storage Unit and input Unit --level 1 --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 27.915) + [ (Pair Unit Unit) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0x05 ] + - location: 11 (just consumed gas: 0.010) + [ 0x06 + 0x05 ] + - location: 14 (just consumed gas: 0.040) + [ 0x03 ] + - location: 15 (just consumed gas: 0.010) + [ 0x03 + 0x03 ] + - location: 20 (just consumed gas: 0.035) + [ 0 ] + - location: 21 (just consumed gas: 0.010) + [ True ] + - location: 22 (just consumed gas: 0.010) + [ ] + - location: 22 (just consumed gas: 0.025) + [ ] + - location: 28 (just consumed gas: 0.010) + [ 0x0005 ] + - location: 31 (just consumed gas: 0.010) + [ 0x0106 + 0x0005 ] + - location: 34 (just consumed gas: 0.041) + [ 0x0103 ] + - location: 35 (just consumed gas: 0.010) + [ 0x0103 + 0x0103 ] + - location: 40 (just consumed gas: 0.035) + [ 0 ] + - location: 41 (just consumed gas: 0.010) + [ True ] + - location: 42 (just consumed gas: 0.010) + [ ] + - location: 42 (just consumed gas: 0.025) + [ ] + - location: 48 (just consumed gas: 0.010) + [ 0x05 ] + - location: 51 (just consumed gas: 0.010) + [ 0x0106 + 0x05 ] + - location: 54 (just consumed gas: 0.041) + [ 0x0103 ] + - location: 55 (just consumed gas: 0.010) + [ 0x0103 + 0x0103 ] + - location: 60 (just consumed gas: 0.035) + [ 0 ] + - location: 61 (just consumed gas: 0.010) + [ True ] + - location: 62 (just consumed gas: 0.010) + [ ] + - location: 62 (just consumed gas: 0.025) + [ ] + - location: 68 (just consumed gas: 0.010) + [ Unit ] + - location: 69 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 71 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- BALANCE.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- BALANCE.out new file mode 100644 index 000000000000..52c4f8fc293b --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- BALANCE.out @@ -0,0 +1,147 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 0 --trace-stack +storage + 0 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 0 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 0 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 0) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 0.000001 --trace-stack +storage + 1 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 1 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 1 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 1) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 0.5 --trace-stack +storage + 500000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 500000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 500000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 500000) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 1 --trace-stack +storage + 1000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 1000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 1000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 1000000) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 5 --trace-stack +storage + 5000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 5000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 5000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 5000000) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 1000 --trace-stack +storage + 1000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 1000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 1000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 1000000000) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/balance.tz on storage 0 and input Unit --balance 8000000 --trace-stack +storage + 8000000000000 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 0) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 8000000000000 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 8000000000000 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 8000000000000) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- LEVEL.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- LEVEL.out new file mode 100644 index 000000000000..8432ef16787a --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- LEVEL.out @@ -0,0 +1,21 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/level.tz on storage 9999999 and input Unit --level 10 --trace-stack +storage + 10 +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.158) + [ (Pair Unit 9999999) ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ 10 ] + - location: 9 (just consumed gas: 0.010) + [ {} + 10 ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} 10) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- NOW.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- NOW.out new file mode 100644 index 000000000000..705950890995 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- NOW.out @@ -0,0 +1,21 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_now.tz on storage '"2017-07-13T09:19:01Z"' and input Unit --trace-stack --now 2021-10-13T10:16:52Z +storage + "2021-10-13T10:16:52Z" +emitted operations + +big_map diff + +trace + - location: 7 (just consumed gas: 4.266) + [ (Pair Unit "2017-07-13T09:19:01Z") ] + - location: 7 (just consumed gas: 0.010) + [ ] + - location: 8 (just consumed gas: 0.010) + [ "2021-10-13T10:16:52Z" ] + - location: 9 (just consumed gas: 0.010) + [ {} + "2021-10-13T10:16:52Z" ] + - location: 11 (just consumed gas: 0.010) + [ (Pair {} "2021-10-13T10:16:52Z") ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- arithmetic_overflow.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- arithmetic_overflow.out new file mode 100644 index 000000000000..e801cebfa1e1 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- arithmetic_overflow.out @@ -0,0 +1,224 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 1 257))' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 10 characters 25 to 28, +unexpected arithmetic overflow +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 1 257)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 1 257)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 1 257) ] + - location: 17 (just consumed gas: 0.010) + [ 1 + 257 ] +Fatal error: + error running script + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Left (Pair 123 257))' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 10 characters 25 to 28, +unexpected arithmetic overflow +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Left (Pair 123 257)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Left (Pair 123 257)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 123 257) ] + - location: 17 (just consumed gas: 0.010) + [ 123 + 257 ] +Fatal error: + error running script + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 1 257))' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 13 characters 25 to 28, +unexpected arithmetic overflow +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 1 257)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 1 257)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 1 257) ] + - location: 20 (just consumed gas: 0.010) + [ 1 + 257 ] +Fatal error: + error running script + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/shifts.tz on storage None and input '(Right (Pair 123 257))' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter (or (pair nat nat) (pair nat nat)); + 02: storage (option nat); + 03: # this contract takes either (Left a b) and stores (a << b) + 04: # or (Right a b) and stores (a >> b). + 05: # i.e., in the first case, the first component shifted to the left by + 06: # the second, and the second case, component shifted to the right by + 07: # the second. + 08: code { CAR; + 09: IF_LEFT { + 10: UNPAIR; LSL; + 11: } + 12: { + 13: UNPAIR; LSR; + 14: }; + 15: SOME; + 16: NIL operation; + 17: PAIR; + 18: }; + 19: +At line 13 characters 25 to 28, +unexpected arithmetic overflow +trace + - location: 14 (just consumed gas: 8.673) + [ (Pair (Right (Pair 123 257)) None) ] + - location: 14 (just consumed gas: 0.010) + [ (Right (Pair 123 257)) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair 123 257) ] + - location: 20 (just consumed gas: 0.010) + [ 123 + 257 ] +Fatal error: + error running script + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_overflow.tz on storage Unit and input 'Left Unit' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter (or unit unit) ; + 02: storage unit ; + 03: code { CAR ; + 04: IF_LEFT + 05: { + 06: PUSH nat 922337203685477580700 ; + 07: PUSH mutez 10 ; + 08: MUL ; # FAILURE + 09: DROP + 10: } + 11: { + 12: PUSH mutez 10 ; + 13: PUSH nat 922337203685477580700 ; + 14: MUL ; # FAILURE + 15: DROP + 16: } ; + 17: + 18: NIL operation ; PAIR } + 19: +At line 8 characters 11 to 14, +unexpected arithmetic overflow +trace + - location: 9 (just consumed gas: 11.154) + [ (Pair (Left Unit) Unit) ] + - location: 9 (just consumed gas: 0.010) + [ (Left Unit) ] + - location: 10 (just consumed gas: 0.010) + [ Unit ] + - location: 12 (just consumed gas: 0.010) + [ 922337203685477580700 + Unit ] + - location: 15 (just consumed gas: 0.010) + [ 10 + 922337203685477580700 + Unit ] +Fatal error: + error running script + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_overflow.tz on storage Unit and input 'Right Unit' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter (or unit unit) ; + 02: storage unit ; + 03: code { CAR ; + 04: IF_LEFT + 05: { + 06: PUSH nat 922337203685477580700 ; + 07: PUSH mutez 10 ; + 08: MUL ; # FAILURE + 09: DROP + 10: } + 11: { + 12: PUSH mutez 10 ; + 13: PUSH nat 922337203685477580700 ; + 14: MUL ; # FAILURE + 15: DROP + 16: } ; + 17: + 18: NIL operation ; PAIR } + 19: +At line 14 characters 11 to 14, +unexpected arithmetic overflow +trace + - location: 9 (just consumed gas: 11.154) + [ (Pair (Right Unit) Unit) ] + - location: 9 (just consumed gas: 0.010) + [ (Right Unit) ] + - location: 10 (just consumed gas: 0.010) + [ Unit ] + - location: 21 (just consumed gas: 0.010) + [ 10 + Unit ] + - location: 24 (just consumed gas: 0.010) + [ 922337203685477580700 + 10 + Unit ] +Fatal error: + error running script diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- big_map_contract_io.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- big_map_contract_io.out new file mode 100644 index 000000000000..e60d4a49ff74 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- big_map_contract_io.out @@ -0,0 +1,1088 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_big_map_value.tz on storage '(Pair { Elt "hello" "hi" } None)' and input '"hello"' --trace-stack +storage + (Pair 4 (Some "hi")) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["hello"] to "hi" +trace + - location: 12 (just consumed gas: 12.330) + [ (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "hello" { Elt "hello" "hi" } None) + (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "hello" { Elt "hello" "hi" } None) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair { Elt "hello" "hi" } None) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (just consumed gas: 0.757) + [ (Some "hi") + { Elt "hello" "hi" } ] + - location: 21 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } + (Some "hi") ] + - location: 22 (just consumed gas: 0.010) + [ (Pair { Elt "hello" "hi" } (Some "hi")) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Pair { Elt "hello" "hi" } (Some "hi")) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} { Elt "hello" "hi" } (Some "hi")) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_big_map_value.tz on storage '(Pair { Elt "hello" "hi" } None)' and input '""' --trace-stack +storage + (Pair 4 None) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["hello"] to "hi" +trace + - location: 12 (just consumed gas: 12.280) + [ (Pair "" { Elt "hello" "hi" } None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "" { Elt "hello" "hi" } None) + (Pair "" { Elt "hello" "hi" } None) ] + - location: 13 (just consumed gas: 0.010) + [ "" + (Pair "" { Elt "hello" "hi" } None) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "" { Elt "hello" "hi" } None) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair { Elt "hello" "hi" } None) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 14 (just consumed gas: 0.035) + [ "" + { Elt "hello" "hi" } + { Elt "hello" "hi" } ] + - location: 20 (just consumed gas: 0.701) + [ None + { Elt "hello" "hi" } ] + - location: 21 (just consumed gas: 0.010) + [ { Elt "hello" "hi" } + None ] + - location: 22 (just consumed gas: 0.010) + [ (Pair { Elt "hello" "hi" } None) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Pair { Elt "hello" "hi" } None) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} { Elt "hello" "hi" } None) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_big_map_value.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } None)' and input '"1"' --trace-stack +storage + (Pair 4 (Some "one")) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" + Set map(4)["1"] to "one" +trace + - location: 12 (just consumed gas: 13.247) + [ (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) + (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 13 (just consumed gas: 0.010) + [ "1" + (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "1" { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 17 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } None) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } ] + - location: 19 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 14 (just consumed gas: 0.035) + [ "1" + { Elt "1" "one" ; Elt "2" "two" } + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 20 (just consumed gas: 0.712) + [ (Some "one") + { Elt "1" "one" ; Elt "2" "two" } ] + - location: 21 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + (Some "one") ] + - location: 22 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + - location: 23 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + - location: 25 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } (Some "one")) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/update_big_map.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)' and input '{}' --trace-stack +storage + (Pair 4 Unit) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" + Set map(4)["1"] to "one" +trace + - location: 15 (just consumed gas: 11.738) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (just consumed gas: 0.035) + [ {} + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.070) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 24 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/update_big_map.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)' and input '{ Elt "1" (Some "two") }' --trace-stack +storage + (Pair 4 Unit) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" + Set map(4)["1"] to "two" +trace + - location: 15 (just consumed gas: 12.163) + [ (Pair { Elt "1" (Some "two") } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "1" (Some "two") } + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (just consumed gas: 0.035) + [ { Elt "1" (Some "two") } + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.067) + [ (Pair "1" (Some "two")) + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (just consumed gas: 0.010) + [ "1" + (Some "two") + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (just consumed gas: 0.727) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.035) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 24 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "two" ; Elt "2" "two" } Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/update_big_map.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)' and input '{ Elt "3" (Some "three") }' --trace-stack +storage + (Pair 4 Unit) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" + Set map(4)["3"] to "three" + Set map(4)["1"] to "one" +trace + - location: 15 (just consumed gas: 12.183) + [ (Pair { Elt "3" (Some "three") } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "3" (Some "three") } + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (just consumed gas: 0.035) + [ { Elt "3" (Some "three") } + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.067) + [ (Pair "3" (Some "three")) + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (just consumed gas: 0.010) + [ "3" + (Some "three") + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (just consumed gas: 0.727) + [ { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } + Unit ] + - location: 19 (just consumed gas: 0.035) + [ { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + - location: 24 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" ; Elt "3" "three" } Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/update_big_map.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)' and input '{ Elt "3" None }' --trace-stack +storage + (Pair 4 Unit) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" + Unset map(4)["3"] + Set map(4)["1"] to "one" +trace + - location: 15 (just consumed gas: 12.018) + [ (Pair { Elt "3" None } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "3" None } + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (just consumed gas: 0.035) + [ { Elt "3" None } + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.067) + [ (Pair "3" None) + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (just consumed gas: 0.010) + [ "3" + None + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (just consumed gas: 0.727) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.035) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 24 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "one" ; Elt "2" "two" } Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/update_big_map.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)' and input '{ Elt "2" None }' --trace-stack +storage + (Pair 4 Unit) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Unset map(4)["2"] + Set map(4)["1"] to "one" +trace + - location: 15 (just consumed gas: 12.018) + [ (Pair { Elt "2" None } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "2" None } + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (just consumed gas: 0.035) + [ { Elt "2" None } + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.067) + [ (Pair "2" None) + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (just consumed gas: 0.010) + [ "2" + None + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (just consumed gas: 0.727) + [ { Elt "1" "one" } + Unit ] + - location: 19 (just consumed gas: 0.035) + [ { Elt "1" "one" } + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" } Unit) ] + - location: 24 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "one" } Unit) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "one" } Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/update_big_map.tz on storage '(Pair { Elt "1" "one" ; Elt "2" "two" } Unit)' and input '{ Elt "1" (Some "two") }' --trace-stack +storage + (Pair 4 Unit) +emitted operations + +big_map diff + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" + Set map(4)["1"] to "two" +trace + - location: 15 (just consumed gas: 12.163) + [ (Pair { Elt "1" (Some "two") } { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 15 (just consumed gas: 0.010) + [ { Elt "1" (Some "two") } + (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "2" "two" } Unit) ] + - location: 18 (just consumed gas: 0.010) + [ { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 16 (just consumed gas: 0.035) + [ { Elt "1" (Some "two") } + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.067) + [ (Pair "1" (Some "two")) + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 21 (just consumed gas: 0.010) + [ "1" + (Some "two") + { Elt "1" "one" ; Elt "2" "two" } + Unit ] + - location: 22 (just consumed gas: 0.727) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 19 (just consumed gas: 0.035) + [ { Elt "1" "two" ; Elt "2" "two" } + Unit ] + - location: 23 (just consumed gas: 0.010) + [ (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 24 (just consumed gas: 0.010) + [ {} + (Pair { Elt "1" "two" ; Elt "2" "two" } Unit) ] + - location: 26 (just consumed gas: 0.010) + [ (Pair {} { Elt "1" "two" ; Elt "2" "two" } Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair None {})' and input '"hello"' --trace-stack +storage + (Pair None 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Unset map(4)["hello"] +trace + - location: 13 (just consumed gas: 8.184) + [ (Pair "hello" None {}) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair None {}) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None {}) ] + - location: 16 (just consumed gas: 0.010) + [ None + {} ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + None + {} ] + - location: 17 (just consumed gas: 0.792) + [ None + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair None {}) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair None {}) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} None {}) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair (Some 4) {})' and input '"hello"' --trace-stack +storage + (Pair None 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["hello"] to 4 +trace + - location: 13 (just consumed gas: 8.284) + [ (Pair "hello" (Some 4) {}) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair (Some 4) {}) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair (Some 4) {}) ] + - location: 16 (just consumed gas: 0.010) + [ (Some 4) + {} ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + (Some 4) + {} ] + - location: 17 (just consumed gas: 0.792) + [ None + { Elt "hello" 4 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" 4 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair None { Elt "hello" 4 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} None { Elt "hello" 4 }) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair None { Elt "hello" 4 })' and input '"hello"' --trace-stack +storage + (Pair (Some 4) 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Unset map(4)["hello"] +trace + - location: 13 (just consumed gas: 9.218) + [ (Pair "hello" None { Elt "hello" 4 }) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair None { Elt "hello" 4 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" 4 }) ] + - location: 16 (just consumed gas: 0.010) + [ None + { Elt "hello" 4 } ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + None + { Elt "hello" 4 } ] + - location: 17 (just consumed gas: 0.796) + [ (Some 4) + {} ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 4) {}) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 4) {}) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 4) {}) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair (Some 5) { Elt "hello" 4 })' and input '"hello"' --trace-stack +storage + (Pair (Some 4) 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["hello"] to 5 +trace + - location: 13 (just consumed gas: 9.318) + [ (Pair "hello" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (just consumed gas: 0.010) + [ "hello" + (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 16 (just consumed gas: 0.010) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (just consumed gas: 0.035) + [ "hello" + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (just consumed gas: 0.796) + [ (Some 4) + { Elt "hello" 5 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 4) { Elt "hello" 5 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 4) { Elt "hello" 5 }) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair (Some 5) { Elt "hello" 4 })' and input '"hi"' --trace-stack +storage + (Pair None 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["hello"] to 4 + Set map(4)["hi"] to 5 +trace + - location: 13 (just consumed gas: 9.288) + [ (Pair "hi" (Some 5) { Elt "hello" 4 }) ] + - location: 13 (just consumed gas: 0.010) + [ "hi" + (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair (Some 5) { Elt "hello" 4 }) ] + - location: 16 (just consumed gas: 0.010) + [ (Some 5) + { Elt "hello" 4 } ] + - location: 14 (just consumed gas: 0.035) + [ "hi" + (Some 5) + { Elt "hello" 4 } ] + - location: 17 (just consumed gas: 0.763) + [ None + { Elt "hello" 4 ; Elt "hi" 5 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair None { Elt "hello" 4 ; Elt "hi" 5 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} None { Elt "hello" 4 ; Elt "hi" 5 }) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair None { Elt "1" 1 ; Elt "2" 2 })' and input '"1"' --trace-stack +storage + (Pair (Some 1) 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["2"] to 2 + Unset map(4)["1"] +trace + - location: 13 (just consumed gas: 10.080) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (just consumed gas: 0.010) + [ "1" + (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 16 (just consumed gas: 0.010) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (just consumed gas: 0.035) + [ "1" + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (just consumed gas: 0.751) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/get_and_update_big_map.tz on storage '(Pair None { Elt "1" 1 ; Elt "2" 2 })' and input '"1"' --trace-stack +storage + (Pair (Some 1) 4) +emitted operations + +big_map diff + New map(4) of type (big_map string nat) + Set map(4)["2"] to 2 + Unset map(4)["1"] +trace + - location: 13 (just consumed gas: 10.080) + [ (Pair "1" None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 13 (just consumed gas: 0.010) + [ "1" + (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 14 (just consumed gas: 0.010) + [ (Pair None { Elt "1" 1 ; Elt "2" 2 }) ] + - location: 16 (just consumed gas: 0.010) + [ None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 14 (just consumed gas: 0.035) + [ "1" + None + { Elt "1" 1 ; Elt "2" 2 } ] + - location: 17 (just consumed gas: 0.751) + [ (Some 1) + { Elt "2" 2 } ] + - location: 18 (just consumed gas: 0.010) + [ (Pair (Some 1) { Elt "2" 2 }) ] + - location: 19 (just consumed gas: 0.010) + [ {} + (Pair (Some 1) { Elt "2" 2 }) ] + - location: 21 (just consumed gas: 0.010) + [ (Pair {} (Some 1) { Elt "2" 2 }) ] + + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/big_map_magic.tz on storage '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))' and input '(Left Unit)' --trace-stack +storage + (Left (Pair 4 5)) +emitted operations + +big_map diff + New map(5) of type (big_map string string) + Set map(5)["1"] to "one" + New map(4) of type (big_map string string) + Set map(4)["2"] to "two" +trace + - location: 43 (just consumed gas: 59.608) + [ (Pair (Left Unit) (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (just consumed gas: 0.010) + [ (Left Unit) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.010) + [ Unit + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 46 (just consumed gas: 0.010) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 48 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) ] + - location: 48 (just consumed gas: 0.025) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) ] + - location: 54 (just consumed gas: 0.010) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 55 (just consumed gas: 0.010) + [ { Elt "2" "two" } + { Elt "1" "one" } ] + - location: 56 (just consumed gas: 0.010) + [ (Pair { Elt "2" "two" } { Elt "1" "one" }) ] + - location: 57 (just consumed gas: 0.010) + [ (Left (Pair { Elt "2" "two" } { Elt "1" "one" })) ] + - location: 44 (just consumed gas: 0.025) + [ (Left (Pair { Elt "2" "two" } { Elt "1" "one" })) ] + - location: 151 (just consumed gas: 0.010) + [ {} + (Left (Pair { Elt "2" "two" } { Elt "1" "one" })) ] + - location: 153 (just consumed gas: 0.010) + [ (Pair {} (Left (Pair { Elt "2" "two" } { Elt "1" "one" }))) ] + + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/big_map_magic.tz on storage '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))' and input '(Right (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" }))))' --trace-stack +storage + (Left (Pair 4 5)) +emitted operations + +big_map diff + New map(5) of type (big_map string string) + Set map(5)["4"] to "four" + New map(4) of type (big_map string string) + Set map(4)["3"] to "three" +trace + - location: 43 (just consumed gas: 62.906) + [ (Pair (Right (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (just consumed gas: 0.010) + [ (Right (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.010) + [ (Left (Left (Pair { Elt "3" "three" } { Elt "4" "four" }))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 60 (just consumed gas: 0.010) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 62 (just consumed gas: 0.010) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) + (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 63 (just consumed gas: 0.010) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 60 (just consumed gas: 0.025) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 44 (just consumed gas: 0.025) + [ (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 151 (just consumed gas: 0.010) + [ {} + (Left (Pair { Elt "3" "three" } { Elt "4" "four" })) ] + - location: 153 (just consumed gas: 0.010) + [ (Pair {} (Left (Pair { Elt "3" "three" } { Elt "4" "four" }))) ] + + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/big_map_magic.tz on storage '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))' and input '(Right (Left (Right Unit)))' --trace-stack +storage + (Right Unit) +emitted operations + +big_map diff + +trace + - location: 43 (just consumed gas: 60.248) + [ (Pair (Right (Left (Right Unit))) (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (just consumed gas: 0.010) + [ (Right (Left (Right Unit))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.010) + [ (Left (Right Unit)) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 60 (just consumed gas: 0.010) + [ (Right Unit) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 62 (just consumed gas: 0.010) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) + (Right Unit) ] + - location: 63 (just consumed gas: 0.010) + [ (Right Unit) ] + - location: 60 (just consumed gas: 0.025) + [ (Right Unit) ] + - location: 44 (just consumed gas: 0.025) + [ (Right Unit) ] + - location: 151 (just consumed gas: 0.010) + [ {} + (Right Unit) ] + - location: 153 (just consumed gas: 0.010) + [ (Pair {} (Right Unit)) ] + + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/big_map_magic.tz on storage '(Right Unit)' and input '(Right (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" }) )))' --trace-stack +storage + (Left (Pair 4 5)) +emitted operations + +big_map diff + New map(5) of type (big_map string string) + Set map(5)["gaz"] to "baz" + New map(4) of type (big_map string string) + Set map(4)["foo"] to "bar" +trace + - location: 43 (just consumed gas: 58.380) + [ (Pair (Right (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" })))) (Right Unit)) ] + - location: 43 (just consumed gas: 0.010) + [ (Right (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" })))) + (Right Unit) ] + - location: 44 (just consumed gas: 0.010) + [ (Right (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" }))) + (Right Unit) ] + - location: 60 (just consumed gas: 0.010) + [ (Left (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" })) + (Right Unit) ] + - location: 65 (just consumed gas: 0.010) + [ (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" }) + (Right Unit) ] + - location: 67 (just consumed gas: 0.010) + [ (Right Unit) ] + - location: 70 (just consumed gas: 0.010) + [ Unit ] + - location: 70 (just consumed gas: 0.025) + [ Unit ] + - location: 76 (just consumed gas: 0.010) + [ ] + - location: 67 (just consumed gas: 0.035) + [ (Pair { Pair "foo" "bar" } { Pair "gaz" "baz" }) ] + - location: 77 (just consumed gas: 0.010) + [ { Pair "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: 78 (just consumed gas: 0.010) + [ { Pair "gaz" "baz" } ] + - location: 80 (just consumed gas: 0.300) + [ {} + { Pair "gaz" "baz" } ] + - location: 78 (just consumed gas: 0.035) + [ { Pair "foo" "bar" } + {} + { Pair "gaz" "baz" } ] + - location: 83 (just consumed gas: 0.030) + [ (Pair "foo" "bar") + {} + { Pair "gaz" "baz" } ] + - location: 85 (just consumed gas: 0.010) + [ "foo" + "bar" + {} + { Pair "gaz" "baz" } ] + - location: 86 (just consumed gas: 0.010) + [ "bar" + {} + { Pair "gaz" "baz" } ] + - location: 88 (just consumed gas: 0.010) + [ (Some "bar") + {} + { Pair "gaz" "baz" } ] + - location: 86 (just consumed gas: 0.035) + [ "foo" + (Some "bar") + {} + { Pair "gaz" "baz" } ] + - location: 89 (just consumed gas: 0.747) + [ { Elt "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: 83 (just consumed gas: 0.035) + [ { Elt "foo" "bar" } + { Pair "gaz" "baz" } ] + - location: 90 (just consumed gas: 0.010) + [ { Pair "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: 91 (just consumed gas: 0.010) + [ { Elt "foo" "bar" } ] + - location: 93 (just consumed gas: 0.300) + [ {} + { Elt "foo" "bar" } ] + - location: 91 (just consumed gas: 0.035) + [ { Pair "gaz" "baz" } + {} + { Elt "foo" "bar" } ] + - location: 96 (just consumed gas: 0.030) + [ (Pair "gaz" "baz") + {} + { Elt "foo" "bar" } ] + - location: 98 (just consumed gas: 0.010) + [ "gaz" + "baz" + {} + { Elt "foo" "bar" } ] + - location: 99 (just consumed gas: 0.010) + [ "baz" + {} + { Elt "foo" "bar" } ] + - location: 101 (just consumed gas: 0.010) + [ (Some "baz") + {} + { Elt "foo" "bar" } ] + - location: 99 (just consumed gas: 0.035) + [ "gaz" + (Some "baz") + {} + { Elt "foo" "bar" } ] + - location: 102 (just consumed gas: 0.747) + [ { Elt "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: 96 (just consumed gas: 0.035) + [ { Elt "gaz" "baz" } + { Elt "foo" "bar" } ] + - location: 103 (just consumed gas: 0.010) + [ { Elt "foo" "bar" } + { Elt "gaz" "baz" } ] + - location: 104 (just consumed gas: 0.010) + [ (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" }) ] + - location: 105 (just consumed gas: 0.010) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 65 (just consumed gas: 0.025) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 60 (just consumed gas: 0.025) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 44 (just consumed gas: 0.025) + [ (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 151 (just consumed gas: 0.010) + [ {} + (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" })) ] + - location: 153 (just consumed gas: 0.010) + [ (Pair {} (Left (Pair { Elt "foo" "bar" } { Elt "gaz" "baz" }))) ] + + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/big_map_magic.tz on storage '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }) )' and input '(Right (Right (Right (Left { Pair "3" "three" }))))' --trace-stack +storage + (Left (Pair 4 5)) +emitted operations + +big_map diff + New map(5) of type (big_map string string) + Set map(5)["2"] to "two" + New map(4) of type (big_map string string) + Set map(4)["3"] to "three" + Set map(4)["1"] to "one" +trace + - location: 43 (just consumed gas: 60.518) + [ (Pair (Right (Right (Right (Left { Pair "3" "three" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (just consumed gas: 0.010) + [ (Right (Right (Right (Left { Pair "3" "three" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.010) + [ (Right (Right (Left { Pair "3" "three" }))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 60 (just consumed gas: 0.010) + [ (Right (Left { Pair "3" "three" })) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 65 (just consumed gas: 0.010) + [ (Left { Pair "3" "three" }) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 108 (just consumed gas: 0.010) + [ { Pair "3" "three" } + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 110 (just consumed gas: 0.010) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 113 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) ] + - location: 113 (just consumed gas: 0.025) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) ] + - location: 119 (just consumed gas: 0.010) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 110 (just consumed gas: 0.035) + [ { Pair "3" "three" } + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 120 (just consumed gas: 0.030) + [ (Pair "3" "three") + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 122 (just consumed gas: 0.010) + [ "3" + "three" + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 123 (just consumed gas: 0.010) + [ "three" + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 125 (just consumed gas: 0.010) + [ (Some "three") + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 123 (just consumed gas: 0.035) + [ "3" + (Some "three") + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 126 (just consumed gas: 0.727) + [ { Elt "1" "one" ; Elt "3" "three" } + { Elt "2" "two" } ] + - location: 120 (just consumed gas: 0.035) + [ { Elt "1" "one" ; Elt "3" "three" } + { Elt "2" "two" } ] + - location: 127 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" }) ] + - location: 128 (just consumed gas: 0.010) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 108 (just consumed gas: 0.025) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 65 (just consumed gas: 0.025) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 60 (just consumed gas: 0.025) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.025) + [ (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 151 (just consumed gas: 0.010) + [ {} + (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" })) ] + - location: 153 (just consumed gas: 0.010) + [ (Pair {} (Left (Pair { Elt "1" "one" ; Elt "3" "three" } { Elt "2" "two" }))) ] + + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/big_map_magic.tz on storage '(Left (Pair { Elt "1" "one" } { Elt "2" "two" }))' and input '(Right (Right (Right (Right { "1" }))))' --trace-stack +storage + (Left (Pair 4 5)) +emitted operations + +big_map diff + New map(5) of type (big_map string string) + Set map(5)["2"] to "two" + New map(4) of type (big_map string string) + Unset map(4)["1"] +trace + - location: 43 (just consumed gas: 60.253) + [ (Pair (Right (Right (Right (Right { "1" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" }))) ] + - location: 43 (just consumed gas: 0.010) + [ (Right (Right (Right (Right { "1" })))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.010) + [ (Right (Right (Right { "1" }))) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 60 (just consumed gas: 0.010) + [ (Right (Right { "1" })) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 65 (just consumed gas: 0.010) + [ (Right { "1" }) + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 108 (just consumed gas: 0.010) + [ { "1" } + (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 131 (just consumed gas: 0.010) + [ (Left (Pair { Elt "1" "one" } { Elt "2" "two" })) ] + - location: 134 (just consumed gas: 0.010) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) ] + - location: 134 (just consumed gas: 0.025) + [ (Pair { Elt "1" "one" } { Elt "2" "two" }) ] + - location: 140 (just consumed gas: 0.010) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 131 (just consumed gas: 0.035) + [ { "1" } + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 141 (just consumed gas: 0.030) + [ "1" + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 143 (just consumed gas: 0.010) + [ { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 145 (just consumed gas: 0.010) + [ None + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 143 (just consumed gas: 0.035) + [ "1" + None + { Elt "1" "one" } + { Elt "2" "two" } ] + - location: 147 (just consumed gas: 0.727) + [ {} + { Elt "2" "two" } ] + - location: 141 (just consumed gas: 0.035) + [ {} + { Elt "2" "two" } ] + - location: 148 (just consumed gas: 0.010) + [ (Pair {} { Elt "2" "two" }) ] + - location: 149 (just consumed gas: 0.010) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 108 (just consumed gas: 0.025) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 65 (just consumed gas: 0.025) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 60 (just consumed gas: 0.025) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 44 (just consumed gas: 0.025) + [ (Left (Pair {} { Elt "2" "two" })) ] + - location: 151 (just consumed gas: 0.010) + [ {} + (Left (Pair {} { Elt "2" "two" })) ] + - location: 153 (just consumed gas: 0.010) + [ (Pair {} (Left (Pair {} { Elt "2" "two" }))) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- check_signature.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- check_signature.out new file mode 100644 index 000000000000..d3b638425301 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- check_signature.out @@ -0,0 +1,243 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/check_signature.tz on storage '(Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" "hello")' and input '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"' --trace-stack +storage + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") +emitted operations + +big_map diff + +trace + - location: 9 (just consumed gas: 100.026) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 15 (just consumed gas: 0.010) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 16 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 18 (just consumed gas: 0.010) + [ "hello" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 19 (just consumed gas: 0.266) + [ 0x05010000000568656c6c6f + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 16 (just consumed gas: 0.035) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 20 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000568656c6c6f + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 21 (just consumed gas: 65.812) + [ True + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 22 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 22 (just consumed gas: 0.025) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 28 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 29 (just consumed gas: 0.010) + [ {} + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + - location: 31 (just consumed gas: 0.010) + [ (Pair {} + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "hello") ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/check_signature.tz on storage '(Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" "abcd")' and input '"edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav"' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 01: parameter key; + 02: storage (pair signature string); + 03: code { + 04: DUP; DUP; + 05: DIP{ CDR; DUP; CAR; + 06: DIP{CDR; PACK}}; + 07: CAR; CHECK_SIGNATURE; + 08: IF {} {FAIL} ; + 09: CDR; NIL operation ; PAIR}; + 10: + 11: +At line 8 characters 14 to 18, +script reached FAILWITH instruction +with Unit +trace + - location: 9 (just consumed gas: 100.016) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 9 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 10 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 11 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 13 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 14 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 15 (just consumed gas: 0.010) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 16 (just consumed gas: 0.010) + [ (Pair "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 18 (just consumed gas: 0.010) + [ "abcd" + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 19 (just consumed gas: 0.256) + [ 0x05010000000461626364 + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 16 (just consumed gas: 0.035) + [ "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 11 (just consumed gas: 0.035) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 20 (just consumed gas: 0.010) + [ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + 0x05010000000461626364 + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 21 (just consumed gas: 65.811) + [ False + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 22 (just consumed gas: 0.010) + [ (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] + - location: 26 (just consumed gas: 0.010) + [ Unit + (Pair "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + "edsigu3QszDjUpeqYqbvhyRxMpVFamEnvm9FYnt7YiiNt9nmjYfh8ZTbsybZ5WnBkhA7zfHsRVyuTnRsGLR6fNHt1Up1FxgyRtF" + "abcd") ] +Fatal error: + error running script diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- hash_consistency.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- hash_consistency.out new file mode 100644 index 000000000000..ea3c513a3845 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- hash_consistency.out @@ -0,0 +1,32 @@ + +./octez-client --mode mockup hash data '(Pair 22220000000 (Pair "2017-12-13T04:49:00Z" 034))' of type '(pair mutez (pair timestamp int))' +Raw packed data: 0x0507070080acd2c6a501070700bcc485a30b0022 +Script-expression-ID-Hash: expruenXhGp5JQoHJTGv4DzBR8Zm3HGvea8Q8BaMPywsY2bxrHAEgC +Raw Script-expression-ID-Hash: 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc +Ledger Blake2b hash: B5B7PuGGVUrdHUW9Df8wPNJQRuUmx56aH1XVpvbUZvW7 +Raw Sha256 hash: 0x538634a0f81b55f1c946c1207a25c262479566d20bd3d5cd2cdbb2940fc45774 +Raw Sha512 hash: 0x49d5c19c2da4ee74f85225c95625a4b77b94724f4285b436b9d4be27d40491354bdc8e9d8a3d9b2857e5fb59b172605edd02fc4b61ce3cd3f84aa11ed1731ff6 +Gas remaining: 1039997.762 units remaining + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/hash_consistency_checker.tz on storage 0x00 and input '(Pair 22220000000 (Pair "2017-12-13T04:49:00Z" 034))' --trace-stack +storage + 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 6.040) + [ (Pair (Pair 22220000000 "2017-12-13T04:49:00Z" 34) 0x00) ] + - location: 11 (just consumed gas: 0.010) + [ (Pair 22220000000 "2017-12-13T04:49:00Z" 34) ] + - location: 12 (just consumed gas: 1.330) + [ 0x0507070080acd2c6a501070700bcc485a30b0022 ] + - location: 13 (just consumed gas: 0.452) + [ 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc ] + - location: 14 (just consumed gas: 0.010) + [ {} + 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc ] + - location: 16 (just consumed gas: 0.010) + [ (Pair {} 0x95a69fcbbf773989333dc9b31e246575812dbea19d25089f83a2aeeea16ab4bc) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- map_map_side_effect.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- map_map_side_effect.out new file mode 100644 index 000000000000..c0ccce9a1057 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- map_map_side_effect.out @@ -0,0 +1,273 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/map_map_sideeffect.tz on storage '(Pair {} 0)' and input 10 --trace-stack +storage + (Pair {} 0) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 16.332) + [ (Pair 10 {} 0) ] + - location: 11 (just consumed gas: 0.010) + [ 10 + (Pair {} 0) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair {} 0) + 10 ] + - location: 13 (just consumed gas: 0.010) + [ {} + 10 ] + - location: 14 (just consumed gas: 0.023) + [ ] + - location: 17 (just consumed gas: 0.010) + [ 0 ] + - location: 14 (just consumed gas: 0.045) + [ {} + 10 + 0 ] + - location: 20 (just consumed gas: 0.060) + [ {} + 10 + 0 ] + - location: 34 (just consumed gas: 0.010) + [ 10 + 0 ] + - location: 36 (just consumed gas: 0.010) + [ 0 ] + - location: 34 (just consumed gas: 0.035) + [ {} + 0 ] + - location: 37 (just consumed gas: 0.010) + [ (Pair {} 0) ] + - location: 38 (just consumed gas: 0.010) + [ {} + (Pair {} 0) ] + - location: 40 (just consumed gas: 0.010) + [ (Pair {} {} 0) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/map_map_sideeffect.tz on storage '(Pair { Elt "foo" 1 } 1)' and input 10 --trace-stack +storage + (Pair { Elt "foo" 11 } 11) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 16.632) + [ (Pair 10 { Elt "foo" 1 } 1) ] + - location: 11 (just consumed gas: 0.010) + [ 10 + (Pair { Elt "foo" 1 } 1) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 1 } 1) + 10 ] + - location: 13 (just consumed gas: 0.010) + [ { Elt "foo" 1 } + 10 ] + - location: 14 (just consumed gas: 0.023) + [ ] + - location: 17 (just consumed gas: 0.010) + [ 0 ] + - location: 14 (just consumed gas: 0.045) + [ { Elt "foo" 1 } + 10 + 0 ] + - location: 20 (just consumed gas: 0.058) + [ (Pair "foo" 1) + 10 + 0 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 10 + 0 ] + - location: 23 (just consumed gas: 0.010) + [ 10 + 0 ] + - location: 25 (just consumed gas: 0.010) + [ 10 + 10 + 0 ] + - location: 23 (just consumed gas: 0.035) + [ 1 + 10 + 10 + 0 ] + - location: 26 (just consumed gas: 0.035) + [ 11 + 10 + 0 ] + - location: 27 (just consumed gas: 0.010) + [ 11 + 11 + 10 + 0 ] + - location: 28 (just consumed gas: 0.048) + [ 11 + 10 + 11 + 0 ] + - location: 30 (just consumed gas: 0.023) + [ 11 + 0 ] + - location: 33 (just consumed gas: 0.035) + [ 11 ] + - location: 30 (just consumed gas: 0.045) + [ 11 + 10 + 11 ] + - location: 20 (just consumed gas: 0.160) + [ { Elt "foo" 11 } + 10 + 11 ] + - location: 34 (just consumed gas: 0.010) + [ 10 + 11 ] + - location: 36 (just consumed gas: 0.010) + [ 11 ] + - location: 34 (just consumed gas: 0.035) + [ { Elt "foo" 11 } + 11 ] + - location: 37 (just consumed gas: 0.010) + [ (Pair { Elt "foo" 11 } 11) ] + - location: 38 (just consumed gas: 0.010) + [ {} + (Pair { Elt "foo" 11 } 11) ] + - location: 40 (just consumed gas: 0.010) + [ (Pair {} { Elt "foo" 11 } 11) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/map_map_sideeffect.tz on storage '(Pair { Elt "bar" 5 ; Elt "foo" 1 } 6)' and input 15 --trace-stack +storage + (Pair { Elt "bar" 20 ; Elt "foo" 16 } 36) +emitted operations + +big_map diff + +trace + - location: 11 (just consumed gas: 16.967) + [ (Pair 15 { Elt "bar" 5 ; Elt "foo" 1 } 6) ] + - location: 11 (just consumed gas: 0.010) + [ 15 + (Pair { Elt "bar" 5 ; Elt "foo" 1 } 6) ] + - location: 12 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 5 ; Elt "foo" 1 } 6) + 15 ] + - location: 13 (just consumed gas: 0.010) + [ { Elt "bar" 5 ; Elt "foo" 1 } + 15 ] + - location: 14 (just consumed gas: 0.023) + [ ] + - location: 17 (just consumed gas: 0.010) + [ 0 ] + - location: 14 (just consumed gas: 0.045) + [ { Elt "bar" 5 ; Elt "foo" 1 } + 15 + 0 ] + - location: 20 (just consumed gas: 0.067) + [ (Pair "bar" 5) + 15 + 0 ] + - location: 22 (just consumed gas: 0.010) + [ 5 + 15 + 0 ] + - location: 23 (just consumed gas: 0.010) + [ 15 + 0 ] + - location: 25 (just consumed gas: 0.010) + [ 15 + 15 + 0 ] + - location: 23 (just consumed gas: 0.035) + [ 5 + 15 + 15 + 0 ] + - location: 26 (just consumed gas: 0.035) + [ 20 + 15 + 0 ] + - location: 27 (just consumed gas: 0.010) + [ 20 + 20 + 15 + 0 ] + - location: 28 (just consumed gas: 0.048) + [ 20 + 15 + 20 + 0 ] + - location: 30 (just consumed gas: 0.023) + [ 20 + 0 ] + - location: 33 (just consumed gas: 0.035) + [ 20 ] + - location: 30 (just consumed gas: 0.045) + [ 20 + 15 + 20 ] + - location: 20 (just consumed gas: 0.150) + [ (Pair "foo" 1) + 15 + 20 ] + - location: 22 (just consumed gas: 0.010) + [ 1 + 15 + 20 ] + - location: 23 (just consumed gas: 0.010) + [ 15 + 20 ] + - location: 25 (just consumed gas: 0.010) + [ 15 + 15 + 20 ] + - location: 23 (just consumed gas: 0.035) + [ 1 + 15 + 15 + 20 ] + - location: 26 (just consumed gas: 0.035) + [ 16 + 15 + 20 ] + - location: 27 (just consumed gas: 0.010) + [ 16 + 16 + 15 + 20 ] + - location: 28 (just consumed gas: 0.048) + [ 16 + 15 + 16 + 20 ] + - location: 30 (just consumed gas: 0.023) + [ 16 + 20 ] + - location: 33 (just consumed gas: 0.035) + [ 36 ] + - location: 30 (just consumed gas: 0.045) + [ 16 + 15 + 36 ] + - location: 20 (just consumed gas: 0.160) + [ { Elt "bar" 20 ; Elt "foo" 16 } + 15 + 36 ] + - location: 34 (just consumed gas: 0.010) + [ 15 + 36 ] + - location: 36 (just consumed gas: 0.010) + [ 36 ] + - location: 34 (just consumed gas: 0.035) + [ { Elt "bar" 20 ; Elt "foo" 16 } + 36 ] + - location: 37 (just consumed gas: 0.010) + [ (Pair { Elt "bar" 20 ; Elt "foo" 16 } 36) ] + - location: 38 (just consumed gas: 0.010) + [ {} + (Pair { Elt "bar" 20 ; Elt "foo" 16 } 36) ] + - location: 40 (just consumed gas: 0.010) + [ (Pair {} { Elt "bar" 20 ; Elt "foo" 16 } 36) ] + diff --git a/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- pack_unpack.out b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- pack_unpack.out new file mode 100644 index 000000000000..89623efd66d4 --- /dev/null +++ b/tezt/tests/expected/contract_opcodes.ml/Parisc- test Michelson opcodes- pack_unpack.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/packunpack.tz on storage Unit and input '(Pair (Pair (Pair "toto" {3;7;9;1}) {1;2;3}) 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003)' --trace-stack +storage + Unit +emitted operations + +big_map diff + +trace + - location: 15 (just consumed gas: 19.185) + [ (Pair (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003) + Unit) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 17 (just consumed gas: 0.010) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 19 (just consumed gas: 0.010) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 17 (just consumed gas: 0.035) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 20 (just consumed gas: 2.807) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 23 (just consumed gas: 0.035) + [ 0 + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 24 (just consumed gas: 0.010) + [ True + 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 25 (just consumed gas: 0.010) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 25 (just consumed gas: 0.025) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 ] + - location: 31 (just consumed gas: 2.514) + [ (Some (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 })) ] + - location: 40 (just consumed gas: 0.010) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) ] + - location: 40 (just consumed gas: 0.025) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) ] + - location: 46 (just consumed gas: 0.010) + [ ] + - location: 47 (just consumed gas: 0.010) + [ Unit ] + - location: 48 (just consumed gas: 0.010) + [ {} + Unit ] + - location: 50 (just consumed gas: 0.010) + [ (Pair {} Unit) ] + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/packunpack.tz on storage Unit and input '(Pair (Pair (Pair "toto" {3;7;9;1}) {1;2;3}) 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004)' --trace-stack +Runtime error in contract KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi: + 1: parameter (pair (pair (pair string (list int)) (set nat)) bytes) ; + 2: storage unit ; + 3: code { CAR ; UNPAIR ; DIP { DUP } ; + 4: PACK ; ASSERT_CMPEQ ; + 5: UNPACK (pair (pair string (list int)) (set nat)) ; ASSERT_SOME ; DROP ; + 6: UNIT ; NIL operation ; PAIR } + 7: +At line 4 characters 14 to 26, +script reached FAILWITH instruction +with Unit +trace + - location: 15 (just consumed gas: 19.185) + [ (Pair (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004) + Unit) ] + - location: 15 (just consumed gas: 0.010) + [ (Pair (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004) ] + - location: 16 (just consumed gas: 0.010) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 17 (just consumed gas: 0.010) + [ 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 19 (just consumed gas: 0.010) + [ 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 17 (just consumed gas: 0.035) + [ (Pair (Pair "toto" { 3 ; 7 ; 9 ; 1 }) { 1 ; 2 ; 3 }) + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 20 (just consumed gas: 2.807) + [ 0x05070707070100000004746f746f020000000800030007000900010200000006000100020003 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 23 (just consumed gas: 0.035) + [ -1 + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 24 (just consumed gas: 0.010) + [ False + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 25 (just consumed gas: 0.010) + [ 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] + - location: 29 (just consumed gas: 0.010) + [ Unit + 0x05070707070100000004746f746f0200000008000300070009000102000000060001000200030004 ] +Fatal error: + error running script diff --git a/tezt/tests/expected/contract_typecheck_regression.ml/Paris- Tc scripts.out b/tezt/tests/expected/contract_typecheck_regression.ml/Parisb- Tc scripts.out similarity index 100% rename from tezt/tests/expected/contract_typecheck_regression.ml/Paris- Tc scripts.out rename to tezt/tests/expected/contract_typecheck_regression.ml/Parisb- Tc scripts.out diff --git a/tezt/tests/expected/contract_typecheck_regression.ml/Parisc- Tc scripts.out b/tezt/tests/expected/contract_typecheck_regression.ml/Parisc- Tc scripts.out new file mode 100644 index 000000000000..bc5ee2697f4e --- /dev/null +++ b/tezt/tests/expected/contract_typecheck_regression.ml/Parisc- Tc scripts.out @@ -0,0 +1,50658 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings typecheck script michelson_test_scripts/attic/accounts.tz michelson_test_scripts/attic/add1.tz michelson_test_scripts/attic/add1_list.tz michelson_test_scripts/attic/after_strategy.tz michelson_test_scripts/attic/always.tz michelson_test_scripts/attic/append.tz michelson_test_scripts/attic/at_least.tz michelson_test_scripts/attic/auction.tz michelson_test_scripts/attic/bad_lockup.tz michelson_test_scripts/attic/big_map_union.tz michelson_test_scripts/attic/cadr_annotation.tz michelson_test_scripts/attic/concat.tz michelson_test_scripts/attic/conditionals.tz michelson_test_scripts/attic/cons_twice.tz michelson_test_scripts/attic/cps_fact.tz michelson_test_scripts/attic/create_add1_lists.tz michelson_test_scripts/attic/data_publisher.tz michelson_test_scripts/attic/dispatch.tz michelson_test_scripts/attic/empty.tz michelson_test_scripts/attic/fail_amount.tz michelson_test_scripts/attic/faucet.tz michelson_test_scripts/attic/forward.tz michelson_test_scripts/attic/id.tz michelson_test_scripts/attic/infinite_loop.tz michelson_test_scripts/attic/insertion_sort.tz michelson_test_scripts/attic/int_publisher.tz michelson_test_scripts/attic/king_of_tez.tz michelson_test_scripts/attic/list_of_transactions.tz michelson_test_scripts/attic/queue.tz michelson_test_scripts/attic/reduce_map.tz michelson_test_scripts/attic/reentrancy.tz michelson_test_scripts/attic/reservoir.tz michelson_test_scripts/attic/scrutable_reservoir.tz michelson_test_scripts/attic/spawn_identities.tz michelson_test_scripts/entrypoints/big_map_entrypoints.tz michelson_test_scripts/entrypoints/delegatable_target.tz michelson_test_scripts/entrypoints/manager.tz michelson_test_scripts/entrypoints/no_default_target.tz michelson_test_scripts/entrypoints/no_entrypoint_target.tz michelson_test_scripts/entrypoints/rooted_target.tz michelson_test_scripts/entrypoints/simple_entrypoints.tz michelson_test_scripts/macros/assert.tz michelson_test_scripts/macros/assert_cmpeq.tz michelson_test_scripts/macros/assert_cmpge.tz michelson_test_scripts/macros/assert_cmpgt.tz michelson_test_scripts/macros/assert_cmple.tz michelson_test_scripts/macros/assert_cmplt.tz michelson_test_scripts/macros/assert_cmpneq.tz michelson_test_scripts/macros/assert_eq.tz michelson_test_scripts/macros/assert_ge.tz michelson_test_scripts/macros/assert_gt.tz michelson_test_scripts/macros/assert_le.tz michelson_test_scripts/macros/assert_lt.tz michelson_test_scripts/macros/assert_neq.tz michelson_test_scripts/macros/big_map_get_add.tz michelson_test_scripts/macros/big_map_mem.tz michelson_test_scripts/macros/build_list.tz michelson_test_scripts/macros/carn_and_cdrn.tz michelson_test_scripts/macros/compare.tz michelson_test_scripts/macros/compare_bytes.tz michelson_test_scripts/macros/fail.tz michelson_test_scripts/macros/guestbook.tz michelson_test_scripts/macros/macro_annotations.tz michelson_test_scripts/macros/map_caddaadr.tz michelson_test_scripts/macros/max_in_list.tz michelson_test_scripts/macros/min.tz michelson_test_scripts/macros/pair_macro.tz michelson_test_scripts/macros/set_caddaadr.tz michelson_test_scripts/macros/take_my_money.tz michelson_test_scripts/macros/unpair_macro.tz michelson_test_scripts/mini_scenarios/999_constant.tz michelson_test_scripts/mini_scenarios/add_clear_tickets_015.tz michelson_test_scripts/mini_scenarios/always_fails.tz michelson_test_scripts/mini_scenarios/authentication.tz michelson_test_scripts/mini_scenarios/big_map_all.tz michelson_test_scripts/mini_scenarios/big_map_entrypoints.tz michelson_test_scripts/mini_scenarios/big_map_magic.tz michelson_test_scripts/mini_scenarios/big_map_read.tz michelson_test_scripts/mini_scenarios/big_map_store.tz michelson_test_scripts/mini_scenarios/big_map_write.tz michelson_test_scripts/mini_scenarios/cache_consistency.tz michelson_test_scripts/mini_scenarios/check_signature.tz michelson_test_scripts/mini_scenarios/constant_entrypoints.tz michelson_test_scripts/mini_scenarios/constant_unit.tz michelson_test_scripts/mini_scenarios/create_contract.tz michelson_test_scripts/mini_scenarios/create_contract_simple.tz michelson_test_scripts/mini_scenarios/default_account.tz michelson_test_scripts/mini_scenarios/emit_events.tz michelson_test_scripts/mini_scenarios/execution_order_appender.tz michelson_test_scripts/mini_scenarios/execution_order_caller.tz michelson_test_scripts/mini_scenarios/execution_order_storer.tz michelson_test_scripts/mini_scenarios/fa12_reference.tz michelson_test_scripts/mini_scenarios/fail_on_false.tz michelson_test_scripts/mini_scenarios/generic_multisig.tz michelson_test_scripts/mini_scenarios/groth16.tz michelson_test_scripts/mini_scenarios/hardlimit.tz michelson_test_scripts/mini_scenarios/large_error.tz michelson_test_scripts/mini_scenarios/large_flat_contract.tz michelson_test_scripts/mini_scenarios/large_str_id.tz michelson_test_scripts/mini_scenarios/legacy_multisig.tz michelson_test_scripts/mini_scenarios/lockup.tz michelson_test_scripts/mini_scenarios/loop.tz michelson_test_scripts/mini_scenarios/lqt_fa12.mligo.tz michelson_test_scripts/mini_scenarios/multiple_en2.tz michelson_test_scripts/mini_scenarios/multiple_entrypoints_counter.tz michelson_test_scripts/mini_scenarios/multisig_dest_entrypoint.tz michelson_test_scripts/mini_scenarios/multisig_dest_entrypoint_arg.tz michelson_test_scripts/mini_scenarios/nat_id.tz michelson_test_scripts/mini_scenarios/noop_bytes.tz michelson_test_scripts/mini_scenarios/originate_contract.tz michelson_test_scripts/mini_scenarios/parameterized_multisig.tz michelson_test_scripts/mini_scenarios/parsable_contract.tz michelson_test_scripts/mini_scenarios/receive_tickets_in_big_map.tz michelson_test_scripts/mini_scenarios/replay.tz michelson_test_scripts/mini_scenarios/reveal_signed_preimage.tz michelson_test_scripts/mini_scenarios/sc_rollup_forward.tz michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz michelson_test_scripts/mini_scenarios/self_address_receiver.tz michelson_test_scripts/mini_scenarios/self_address_sender.tz michelson_test_scripts/mini_scenarios/send_ticket_list_016.tz michelson_test_scripts/mini_scenarios/send_ticket_list_multiple_016.tz michelson_test_scripts/mini_scenarios/send_tickets_from_storage_016.tz michelson_test_scripts/mini_scenarios/send_tickets_in_big_map_015.tz michelson_test_scripts/mini_scenarios/smart_rollup_mint_and_deposit_ticket_016.tz michelson_test_scripts/mini_scenarios/smart_rollup_receive_tickets_016.tz michelson_test_scripts/mini_scenarios/str_id.tz michelson_test_scripts/mini_scenarios/ticket_builder_fungible.tz michelson_test_scripts/mini_scenarios/ticket_builder_non_fungible.tz michelson_test_scripts/mini_scenarios/ticket_wallet_fungible.tz michelson_test_scripts/mini_scenarios/ticket_wallet_non_fungible.tz michelson_test_scripts/mini_scenarios/tickets_015.tz michelson_test_scripts/mini_scenarios/tickets_bag_016.tz michelson_test_scripts/mini_scenarios/tickets_bag_implicit_016.tz michelson_test_scripts/mini_scenarios/tickets_blackhole_016.tz michelson_test_scripts/mini_scenarios/tickets_create_and_send_015.tz michelson_test_scripts/mini_scenarios/tickets_list_blackhole_016.tz michelson_test_scripts/mini_scenarios/tickets_mint_and_store_complex_param.tz michelson_test_scripts/mini_scenarios/tickets_receive_and_store.tz michelson_test_scripts/mini_scenarios/tickets_send_016.tz michelson_test_scripts/mini_scenarios/tickets_send_with_tez_016.tz michelson_test_scripts/mini_scenarios/tickets_store_fst_and_rely_snd.tz michelson_test_scripts/mini_scenarios/tzip4_view.tz michelson_test_scripts/mini_scenarios/very_small.tz michelson_test_scripts/mini_scenarios/view_check_caller.tz michelson_test_scripts/mini_scenarios/view_registers_callers.tz michelson_test_scripts/mini_scenarios/viewable.tz michelson_test_scripts/mini_scenarios/vote_for_delegate.tz michelson_test_scripts/mini_scenarios/weather_insurance.tz michelson_test_scripts/mini_scenarios/xcat.tz michelson_test_scripts/mini_scenarios/xcat_dapp.tz michelson_test_scripts/non_regression/262_bug.tz michelson_test_scripts/non_regression/843_bug.tz michelson_test_scripts/non_regression/bad_annot_contract.tz michelson_test_scripts/non_regression/pairk_annot.tz michelson_test_scripts/opcodes/abs.tz michelson_test_scripts/opcodes/add.tz michelson_test_scripts/opcodes/add_bls12_381_fr.tz michelson_test_scripts/opcodes/add_bls12_381_g1.tz michelson_test_scripts/opcodes/add_bls12_381_g2.tz michelson_test_scripts/opcodes/add_delta_timestamp.tz michelson_test_scripts/opcodes/add_timestamp_delta.tz michelson_test_scripts/opcodes/address.tz michelson_test_scripts/opcodes/amount_after_fib_view.tz michelson_test_scripts/opcodes/amount_after_nonexistent_view.tz michelson_test_scripts/opcodes/amount_after_view.tz michelson_test_scripts/opcodes/and.tz michelson_test_scripts/opcodes/and_binary.tz michelson_test_scripts/opcodes/and_bytes_016.tz michelson_test_scripts/opcodes/and_logical_1.tz michelson_test_scripts/opcodes/balance.tz michelson_test_scripts/opcodes/balance_after_fib_view.tz michelson_test_scripts/opcodes/balance_after_nonexistent_view.tz michelson_test_scripts/opcodes/balance_after_view.tz michelson_test_scripts/opcodes/big_map_mem_nat.tz michelson_test_scripts/opcodes/big_map_mem_string.tz michelson_test_scripts/opcodes/big_map_to_self.tz michelson_test_scripts/opcodes/bls12_381_fr_push_bytes_not_padded.tz michelson_test_scripts/opcodes/bls12_381_fr_push_nat.tz michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz michelson_test_scripts/opcodes/bls12_381_fr_to_mutez.tz michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz michelson_test_scripts/opcodes/bytes.tz michelson_test_scripts/opcodes/bytes_of_int_016.tz michelson_test_scripts/opcodes/bytes_of_nat_016.tz michelson_test_scripts/opcodes/car.tz michelson_test_scripts/opcodes/cdr.tz michelson_test_scripts/opcodes/chain_id.tz michelson_test_scripts/opcodes/chain_id_store.tz michelson_test_scripts/opcodes/check_signature.tz michelson_test_scripts/opcodes/comb.tz michelson_test_scripts/opcodes/comb-get.tz michelson_test_scripts/opcodes/comb-literals.tz michelson_test_scripts/opcodes/comb-set.tz michelson_test_scripts/opcodes/comb-set-2.tz michelson_test_scripts/opcodes/compare.tz michelson_test_scripts/opcodes/compare_big_type.tz michelson_test_scripts/opcodes/compare_big_type2.tz michelson_test_scripts/opcodes/comparisons.tz michelson_test_scripts/opcodes/concat_hello.tz michelson_test_scripts/opcodes/concat_hello_bytes.tz michelson_test_scripts/opcodes/concat_list.tz michelson_test_scripts/opcodes/cons.tz michelson_test_scripts/opcodes/contains_all.tz michelson_test_scripts/opcodes/contract.tz michelson_test_scripts/opcodes/create_contract.tz michelson_test_scripts/opcodes/create_contract_rootname.tz michelson_test_scripts/opcodes/create_contract_rootname_alt.tz michelson_test_scripts/opcodes/create_contract_with_view.tz michelson_test_scripts/opcodes/diff_timestamps.tz michelson_test_scripts/opcodes/dig_eq.tz michelson_test_scripts/opcodes/dign.tz michelson_test_scripts/opcodes/dip.tz michelson_test_scripts/opcodes/dipn.tz michelson_test_scripts/opcodes/dropn.tz michelson_test_scripts/opcodes/dugn.tz michelson_test_scripts/opcodes/dup-n.tz michelson_test_scripts/opcodes/ediv.tz michelson_test_scripts/opcodes/ediv_mutez.tz michelson_test_scripts/opcodes/emit.tz michelson_test_scripts/opcodes/empty_map.tz michelson_test_scripts/opcodes/exec_concat.tz michelson_test_scripts/opcodes/fact.tz michelson_test_scripts/opcodes/first.tz michelson_test_scripts/opcodes/get_and_update_big_map.tz michelson_test_scripts/opcodes/get_and_update_map.tz michelson_test_scripts/opcodes/get_big_map_value.tz michelson_test_scripts/opcodes/get_map_value.tz michelson_test_scripts/opcodes/hash_consistency_checker.tz michelson_test_scripts/opcodes/hash_key.tz michelson_test_scripts/opcodes/hash_string.tz michelson_test_scripts/opcodes/if.tz michelson_test_scripts/opcodes/if_some.tz michelson_test_scripts/opcodes/int.tz michelson_test_scripts/opcodes/iter_fail.tz michelson_test_scripts/opcodes/keccak.tz michelson_test_scripts/opcodes/left_right.tz michelson_test_scripts/opcodes/level.tz michelson_test_scripts/opcodes/list_concat.tz michelson_test_scripts/opcodes/list_concat_bytes.tz michelson_test_scripts/opcodes/list_id.tz michelson_test_scripts/opcodes/list_id_map.tz michelson_test_scripts/opcodes/list_iter.tz michelson_test_scripts/opcodes/list_map_block.tz michelson_test_scripts/opcodes/list_size.tz michelson_test_scripts/opcodes/loop_failwith.tz michelson_test_scripts/opcodes/loop_left.tz michelson_test_scripts/opcodes/loop_left_failwith.tz michelson_test_scripts/opcodes/lsl_bytes_016.tz michelson_test_scripts/opcodes/lsr_bytes_016.tz michelson_test_scripts/opcodes/map_car.tz michelson_test_scripts/opcodes/map_id.tz michelson_test_scripts/opcodes/map_iter.tz michelson_test_scripts/opcodes/map_map.tz michelson_test_scripts/opcodes/map_map_sideeffect.tz michelson_test_scripts/opcodes/map_mem_nat.tz michelson_test_scripts/opcodes/map_mem_string.tz michelson_test_scripts/opcodes/map_size.tz michelson_test_scripts/opcodes/merge_comparable_pairs.tz michelson_test_scripts/opcodes/mul.tz michelson_test_scripts/opcodes/mul_bls12_381_fr.tz michelson_test_scripts/opcodes/mul_bls12_381_g1.tz michelson_test_scripts/opcodes/mul_bls12_381_g2.tz michelson_test_scripts/opcodes/mul_overflow.tz michelson_test_scripts/opcodes/munch.tz michelson_test_scripts/opcodes/mutez_to_bls12_381_fr.tz michelson_test_scripts/opcodes/neg.tz michelson_test_scripts/opcodes/neg_bls12_381_fr.tz michelson_test_scripts/opcodes/neg_bls12_381_g1.tz michelson_test_scripts/opcodes/neg_bls12_381_g2.tz michelson_test_scripts/opcodes/none.tz michelson_test_scripts/opcodes/noop.tz michelson_test_scripts/opcodes/not.tz michelson_test_scripts/opcodes/not_binary.tz michelson_test_scripts/opcodes/not_bytes_016.tz michelson_test_scripts/opcodes/or.tz michelson_test_scripts/opcodes/or_binary.tz michelson_test_scripts/opcodes/or_bytes_016.tz michelson_test_scripts/opcodes/originate_big_map.tz michelson_test_scripts/opcodes/packunpack.tz michelson_test_scripts/opcodes/packunpack_rev.tz michelson_test_scripts/opcodes/packunpack_rev_cty.tz michelson_test_scripts/opcodes/pair_id.tz michelson_test_scripts/opcodes/pairing_check.tz michelson_test_scripts/opcodes/pexec.tz michelson_test_scripts/opcodes/pexec_2.tz michelson_test_scripts/opcodes/proxy.tz michelson_test_scripts/opcodes/ret_int.tz michelson_test_scripts/opcodes/reverse.tz michelson_test_scripts/opcodes/reverse_loop.tz michelson_test_scripts/opcodes/sapling_empty_state.tz michelson_test_scripts/opcodes/self.tz michelson_test_scripts/opcodes/self_address.tz michelson_test_scripts/opcodes/self_address_after_fib_view.tz michelson_test_scripts/opcodes/self_address_after_nonexistent_view.tz michelson_test_scripts/opcodes/self_address_after_view.tz michelson_test_scripts/opcodes/self_after_fib_view.tz michelson_test_scripts/opcodes/self_after_nonexistent_view.tz michelson_test_scripts/opcodes/self_after_view.tz michelson_test_scripts/opcodes/self_with_default_entrypoint.tz michelson_test_scripts/opcodes/self_with_entrypoint.tz michelson_test_scripts/opcodes/sender.tz michelson_test_scripts/opcodes/sender_after_fib_view.tz michelson_test_scripts/opcodes/sender_after_nonexistent_view.tz michelson_test_scripts/opcodes/sender_after_view.tz michelson_test_scripts/opcodes/set_car.tz michelson_test_scripts/opcodes/set_cdr.tz michelson_test_scripts/opcodes/set_delegate.tz michelson_test_scripts/opcodes/set_id.tz michelson_test_scripts/opcodes/set_iter.tz michelson_test_scripts/opcodes/set_member.tz michelson_test_scripts/opcodes/set_size.tz michelson_test_scripts/opcodes/sets.tz michelson_test_scripts/opcodes/sha3.tz michelson_test_scripts/opcodes/shifts.tz michelson_test_scripts/opcodes/slice.tz michelson_test_scripts/opcodes/slice_bytes.tz michelson_test_scripts/opcodes/slices.tz michelson_test_scripts/opcodes/source.tz michelson_test_scripts/opcodes/split_bytes.tz michelson_test_scripts/opcodes/split_string.tz michelson_test_scripts/opcodes/store_bls12_381_fr.tz michelson_test_scripts/opcodes/store_bls12_381_g1.tz michelson_test_scripts/opcodes/store_bls12_381_g2.tz michelson_test_scripts/opcodes/store_input.tz michelson_test_scripts/opcodes/store_now.tz michelson_test_scripts/opcodes/str_id.tz michelson_test_scripts/opcodes/sub_timestamp_delta.tz michelson_test_scripts/opcodes/subset.tz michelson_test_scripts/opcodes/tez_add_sub.tz michelson_test_scripts/opcodes/ticket_bad.tz michelson_test_scripts/opcodes/ticket_big_store.tz michelson_test_scripts/opcodes/ticket_join.tz michelson_test_scripts/opcodes/ticket_read.tz michelson_test_scripts/opcodes/ticket_split.tz michelson_test_scripts/opcodes/ticket_store.tz michelson_test_scripts/opcodes/ticket_store-2.tz michelson_test_scripts/opcodes/ticketer.tz michelson_test_scripts/opcodes/ticketer-2.tz michelson_test_scripts/opcodes/transfer_amount.tz michelson_test_scripts/opcodes/transfer_tokens.tz michelson_test_scripts/opcodes/uncomb.tz michelson_test_scripts/opcodes/unpair.tz michelson_test_scripts/opcodes/unpair_field_annotation_mismatch.tz michelson_test_scripts/opcodes/update_big_map.tz michelson_test_scripts/opcodes/utxo_read.tz michelson_test_scripts/opcodes/utxor.tz michelson_test_scripts/opcodes/view_fib.tz michelson_test_scripts/opcodes/view_mutual_recursion.tz michelson_test_scripts/opcodes/view_op_add.tz michelson_test_scripts/opcodes/view_op_constant.tz michelson_test_scripts/opcodes/view_op_id.tz michelson_test_scripts/opcodes/view_op_nonexistent_addr.tz michelson_test_scripts/opcodes/view_op_nonexistent_func.tz michelson_test_scripts/opcodes/view_op_test_step_contants.tz michelson_test_scripts/opcodes/view_op_toplevel_inconsistent_input_type.tz michelson_test_scripts/opcodes/view_op_toplevel_inconsistent_output_type.tz michelson_test_scripts/opcodes/view_rec.tz michelson_test_scripts/opcodes/view_toplevel_lib.tz michelson_test_scripts/opcodes/voting_power.tz michelson_test_scripts/opcodes/xor.tz michelson_test_scripts/opcodes/xor_bytes_016.tz --details --display-names +Well typed (Gas remaining: 1039933.430 units remaining) michelson_test_scripts/attic/accounts.tz +{ parameter + (or (key_hash %Initialize) + (pair %Withdraw (key %from) (pair (mutez %withdraw_amount) (signature %sig)))) ; + storage (map :stored_balance key_hash mutez) ; + code { DUP + /* [ pair (or key_hash (pair key mutez signature)) (map key_hash mutez) + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + CAR + /* [ or key_hash (pair key mutez signature) + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + IF_LEFT + { DUP + /* [ key_hash : key_hash + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + DIP 2 + { CDR %stored_balance + /* [ map key_hash mutez ] */ ; + DUP + /* [ map key_hash mutez : map key_hash mutez ] */ } + /* [ key_hash : key_hash : map key_hash mutez : map key_hash mutez ] */ ; + DIP { SWAP /* [ map key_hash mutez : key_hash : map key_hash mutez ] */ } + /* [ key_hash : map key_hash mutez : key_hash : map key_hash mutez ] */ ; + GET @opt_prev_balance + /* [ option mutez : key_hash : map key_hash mutez ] */ ; + IF_SOME + { RENAME @previous_balance + /* [ mutez : key_hash : map key_hash mutez ] */ ; + AMOUNT + /* [ mutez : mutez : key_hash : map key_hash mutez ] */ ; + ADD + /* [ mutez : key_hash : map key_hash mutez ] */ ; + SOME + /* [ option mutez : key_hash : map key_hash mutez ] */ ; + SWAP + /* [ key_hash : option mutez : map key_hash mutez ] */ ; + UPDATE + /* [ map key_hash mutez ] */ ; + NIL operation + /* [ list operation : map key_hash mutez ] */ ; + PAIR + /* [ pair (list operation) (map key_hash mutez) ] */ } + { DIP { AMOUNT + /* [ mutez : map key_hash mutez ] */ ; + SOME + /* [ option mutez : map key_hash mutez ] */ } + /* [ key_hash : option mutez : map key_hash mutez ] */ ; + UPDATE + /* [ map key_hash mutez ] */ ; + NIL operation + /* [ list operation : map key_hash mutez ] */ ; + PAIR + /* [ pair (list operation) (map key_hash mutez) ] */ } } + { DUP + /* [ pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + DUP + /* [ pair key mutez signature : pair key mutez signature + : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + DUP + /* [ pair key mutez signature : pair key mutez signature + : pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + DUP + /* [ pair key mutez signature : pair key mutez signature + : pair key mutez signature : pair key mutez signature + : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + CAR %from + /* [ key : pair key mutez signature : pair key mutez signature + : pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + DIP 2 + { CDAR %withdraw_amount ; + PACK + /* [ bytes : pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + BLAKE2B @signed_amount + /* [ bytes : pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ } + /* [ key : pair key mutez signature : bytes : pair key mutez signature + : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + DIP { CDDR %sig } + /* [ key : signature : bytes : pair key mutez signature + : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + CHECK_SIGNATURE + /* [ bool : pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + IF { /* [ pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ } + { PUSH string + "Bad signature" + /* [ string : pair key mutez signature : pair key mutez signature + : pair (or key_hash (pair key mutez signature)) (map key_hash mutez) ] */ ; + FAILWITH + /* [] */ } ; + DIP 2 + { CDR %stored_balance + /* [ map key_hash mutez ] */ ; + DUP + /* [ map key_hash mutez : map key_hash mutez ] */ } + /* [ pair key mutez signature : pair key mutez signature : map key_hash mutez + : map key_hash mutez ] */ ; + CAR %from + /* [ key : pair key mutez signature : map key_hash mutez : map key_hash mutez ] */ ; + HASH_KEY @from_hash + /* [ key_hash : pair key mutez signature : map key_hash mutez + : map key_hash mutez ] */ ; + DUP + /* [ key_hash : key_hash : pair key mutez signature : map key_hash mutez + : map key_hash mutez ] */ ; + DIP { DIP { SWAP + /* [ map key_hash mutez : pair key mutez signature : map key_hash mutez ] */ } + /* [ key_hash : map key_hash mutez : pair key mutez signature + : map key_hash mutez ] */ ; + SWAP + /* [ map key_hash mutez : key_hash : pair key mutez signature + : map key_hash mutez ] */ } + /* [ key_hash : map key_hash mutez : key_hash : pair key mutez signature + : map key_hash mutez ] */ ; + GET + /* [ option mutez : key_hash : pair key mutez signature : map key_hash mutez ] */ ; + IF_NONE + { PUSH string + "Account does not exist" + /* [ string : key_hash : pair key mutez signature : map key_hash mutez ] */ ; + PAIR + /* [ pair string key_hash : pair key mutez signature : map key_hash mutez ] */ ; + FAILWITH + /* [] */ } + { RENAME @previous_balance + /* [ mutez : key_hash : pair key mutez signature : map key_hash mutez ] */ ; + DIP { DROP /* [ pair key mutez signature : map key_hash mutez ] */ } + /* [ mutez : pair key mutez signature : map key_hash mutez ] */ ; + DUP + /* [ mutez : mutez : pair key mutez signature : map key_hash mutez ] */ ; + DIP 2 + { DUP + /* [ pair key mutez signature : pair key mutez signature : map key_hash mutez ] */ ; + CDAR %withdraw_amount ; + DUP + /* [ mutez : mutez : pair key mutez signature : map key_hash mutez ] */ } + /* [ mutez : mutez : mutez : mutez : pair key mutez signature + : map key_hash mutez ] */ ; + DIP { CMPLT @not_enough } + /* [ mutez : bool : mutez : pair key mutez signature : map key_hash mutez ] */ ; + SWAP + /* [ bool : mutez : mutez : pair key mutez signature : map key_hash mutez ] */ ; + IF { PUSH string + "Not enough funds" + /* [ string : mutez : mutez : pair key mutez signature : map key_hash mutez ] */ ; + FAILWITH + /* [] */ } + { SUB_MUTEZ @new_balance + /* [ option mutez : pair key mutez signature : map key_hash mutez ] */ ; + ASSERT_SOME ; + DIP { DUP + /* [ pair key mutez signature : pair key mutez signature : map key_hash mutez ] */ ; + DIP { SWAP /* [ map key_hash mutez : pair key mutez signature ] */ } + /* [ pair key mutez signature : map key_hash mutez : pair key mutez signature ] */ } + /* [ mutez : pair key mutez signature : map key_hash mutez + : pair key mutez signature ] */ ; + DUP + /* [ mutez : mutez : pair key mutez signature : map key_hash mutez + : pair key mutez signature ] */ ; + PUSH @zero + mutez + 0 + /* [ mutez : mutez : mutez : pair key mutez signature : map key_hash mutez + : pair key mutez signature ] */ ; + CMPEQ @null_balance ; + IF { DROP + /* [ pair key mutez signature : map key_hash mutez : pair key mutez signature ] */ ; + NONE @new_balance + mutez + /* [ option mutez : pair key mutez signature : map key_hash mutez + : pair key mutez signature ] */ } + { SOME @new_balance + /* [ option mutez : pair key mutez signature : map key_hash mutez + : pair key mutez signature ] */ } ; + SWAP + /* [ pair key mutez signature : option mutez : map key_hash mutez + : pair key mutez signature ] */ ; + CAR %from + /* [ key : option mutez : map key_hash mutez : pair key mutez signature ] */ ; + HASH_KEY @from_hash + /* [ key_hash : option mutez : map key_hash mutez : pair key mutez signature ] */ ; + UPDATE + /* [ map key_hash mutez : pair key mutez signature ] */ ; + SWAP + /* [ pair key mutez signature : map key_hash mutez ] */ ; + DUP + /* [ pair key mutez signature : pair key mutez signature : map key_hash mutez ] */ ; + CDAR %withdraw_amount ; + DIP { CAR %from + /* [ key : map key_hash mutez ] */ ; + HASH_KEY @from_hash + /* [ key_hash : map key_hash mutez ] */ ; + IMPLICIT_ACCOUNT @from_account + /* [ contract unit : map key_hash mutez ] */ } + /* [ mutez : contract unit : map key_hash mutez ] */ ; + UNIT + /* [ unit : mutez : contract unit : map key_hash mutez ] */ ; + TRANSFER_TOKENS @withdraw_transfer_op + /* [ operation : map key_hash mutez ] */ ; + NIL operation + /* [ list operation : operation : map key_hash mutez ] */ ; + SWAP + /* [ operation : list operation : map key_hash mutez ] */ ; + CONS + /* [ list operation : map key_hash mutez ] */ ; + PAIR + /* [ pair (list operation) (map key_hash mutez) ] */ } } } } } +Well typed (Gas remaining: 1039996.810 units remaining) michelson_test_scripts/attic/add1.tz +{ parameter int ; + storage int ; + code { CAR + /* [ int ] */ ; + PUSH int 1 + /* [ int : int ] */ ; + ADD + /* [ int ] */ ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039996.114 units remaining) michelson_test_scripts/attic/add1_list.tz +{ parameter (list int) ; + storage (list int) ; + code { CAR + /* [ list int ] */ ; + MAP { PUSH int 1 /* [ int : int ] */ ; ADD /* [ int ] */ } + /* [ list int ] */ ; + NIL operation + /* [ list operation : list int ] */ ; + PAIR + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039991.454 units remaining) michelson_test_scripts/attic/after_strategy.tz +{ parameter nat ; + storage (pair (pair nat bool) timestamp) ; + code { DUP + /* [ pair nat (pair nat bool) timestamp : pair nat (pair nat bool) timestamp ] */ ; + CAR + /* [ nat : pair nat (pair nat bool) timestamp ] */ ; + DIP { CDDR ; + DUP + /* [ timestamp : timestamp ] */ ; + NOW + /* [ timestamp : timestamp : timestamp ] */ ; + CMPGT } + /* [ nat : bool : timestamp ] */ ; + PAIR + /* [ pair nat bool : timestamp ] */ ; + PAIR + /* [ pair (pair nat bool) timestamp ] */ ; + NIL operation + /* [ list operation : pair (pair nat bool) timestamp ] */ ; + PAIR + /* [ pair (list operation) (pair nat bool) timestamp ] */ } } +Well typed (Gas remaining: 1039996.120 units remaining) michelson_test_scripts/attic/always.tz +{ parameter nat ; + storage (pair nat bool) ; + code { CAR + /* [ nat ] */ ; + PUSH bool True + /* [ bool : nat ] */ ; + SWAP + /* [ nat : bool ] */ ; + PAIR + /* [ pair nat bool ] */ ; + NIL operation + /* [ list operation : pair nat bool ] */ ; + PAIR + /* [ pair (list operation) nat bool ] */ } } +Well typed (Gas remaining: 1039993.723 units remaining) michelson_test_scripts/attic/append.tz +{ parameter (pair (list int) (list int)) ; + storage (list int) ; + code { CAR + /* [ pair (list int) (list int) ] */ ; + UNPAIR + /* [ list int : list int ] */ ; + NIL int + /* [ list int : list int : list int ] */ ; + SWAP + /* [ list int : list int : list int ] */ ; + ITER { CONS /* [ list int : list int ] */ } + /* [ list int : list int ] */ ; + ITER { CONS /* [ list int ] */ } + /* [ list int ] */ ; + NIL operation + /* [ list operation : list int ] */ ; + PAIR + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039993.973 units remaining) michelson_test_scripts/attic/at_least.tz +{ parameter unit ; + storage mutez ; + code { CDR + /* [ mutez ] */ ; + DUP + /* [ mutez : mutez ] */ ; + AMOUNT + /* [ mutez : mutez : mutez ] */ ; + CMPLT ; + IF { FAIL } + { NIL operation + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } } +Well typed (Gas remaining: 1039974.633 units remaining) michelson_test_scripts/attic/auction.tz +{ parameter key_hash ; + storage (pair timestamp (pair mutez key_hash)) ; + code { DUP + /* [ pair key_hash timestamp mutez key_hash + : pair key_hash timestamp mutez key_hash ] */ ; + CDAR ; + DUP + /* [ timestamp : timestamp : pair key_hash timestamp mutez key_hash ] */ ; + NOW + /* [ timestamp : timestamp : timestamp + : pair key_hash timestamp mutez key_hash ] */ ; + CMPGT ; + IF { FAIL } { /* [ timestamp : pair key_hash timestamp mutez key_hash ] */ } ; + SWAP + /* [ pair key_hash timestamp mutez key_hash : timestamp ] */ ; + DUP + /* [ pair key_hash timestamp mutez key_hash + : pair key_hash timestamp mutez key_hash : timestamp ] */ ; + CAR + /* [ key_hash : pair key_hash timestamp mutez key_hash : timestamp ] */ ; + DIP { CDDR } + /* [ key_hash : pair mutez key_hash : timestamp ] */ ; + AMOUNT + /* [ mutez : key_hash : pair mutez key_hash : timestamp ] */ ; + PAIR + /* [ pair mutez key_hash : pair mutez key_hash : timestamp ] */ ; + SWAP + /* [ pair mutez key_hash : pair mutez key_hash : timestamp ] */ ; + DIP { SWAP + /* [ timestamp : pair mutez key_hash ] */ ; + PAIR + /* [ pair timestamp mutez key_hash ] */ } + /* [ pair mutez key_hash : pair timestamp mutez key_hash ] */ ; + DUP + /* [ pair mutez key_hash : pair mutez key_hash : pair timestamp mutez key_hash ] */ ; + CAR + /* [ mutez : pair mutez key_hash : pair timestamp mutez key_hash ] */ ; + AMOUNT + /* [ mutez : mutez : pair mutez key_hash : pair timestamp mutez key_hash ] */ ; + CMPLE ; + IF { FAIL } { /* [ pair mutez key_hash : pair timestamp mutez key_hash ] */ } ; + DUP + /* [ pair mutez key_hash : pair mutez key_hash : pair timestamp mutez key_hash ] */ ; + CAR + /* [ mutez : pair mutez key_hash : pair timestamp mutez key_hash ] */ ; + DIP { CDR + /* [ key_hash : pair timestamp mutez key_hash ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : pair timestamp mutez key_hash ] */ } + /* [ mutez : contract unit : pair timestamp mutez key_hash ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair timestamp mutez key_hash ] */ ; + TRANSFER_TOKENS + /* [ operation : pair timestamp mutez key_hash ] */ ; + NIL operation + /* [ list operation : operation : pair timestamp mutez key_hash ] */ ; + SWAP + /* [ operation : list operation : pair timestamp mutez key_hash ] */ ; + CONS + /* [ list operation : pair timestamp mutez key_hash ] */ ; + PAIR + /* [ pair (list operation) timestamp mutez key_hash ] */ } } +Well typed (Gas remaining: 1039975.206 units remaining) michelson_test_scripts/attic/bad_lockup.tz +{ parameter unit ; + storage (pair timestamp (pair address address)) ; + code { CDR + /* [ pair timestamp address address ] */ ; + DUP + /* [ pair timestamp address address : pair timestamp address address ] */ ; + CAR + /* [ timestamp : pair timestamp address address ] */ ; + NOW + /* [ timestamp : timestamp : pair timestamp address address ] */ ; + CMPLT ; + IF { FAIL } { /* [ pair timestamp address address ] */ } ; + DUP + /* [ pair timestamp address address : pair timestamp address address ] */ ; + CDAR ; + CONTRACT unit + /* [ option (contract unit) : pair timestamp address address ] */ ; + ASSERT_SOME ; + PUSH mutez 100000000 + /* [ mutez : contract unit : pair timestamp address address ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair timestamp address address ] */ ; + TRANSFER_TOKENS + /* [ operation : pair timestamp address address ] */ ; + SWAP + /* [ pair timestamp address address : operation ] */ ; + DUP + /* [ pair timestamp address address : pair timestamp address address + : operation ] */ ; + CDDR ; + CONTRACT + unit + /* [ option (contract unit) : pair timestamp address address : operation ] */ ; + ASSERT_SOME ; + PUSH mutez + 100000000 + /* [ mutez : contract unit : pair timestamp address address : operation ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair timestamp address address : operation ] */ ; + TRANSFER_TOKENS + /* [ operation : pair timestamp address address : operation ] */ ; + DIP { SWAP /* [ operation : pair timestamp address address ] */ } + /* [ operation : operation : pair timestamp address address ] */ ; + NIL operation + /* [ list operation : operation : operation : pair timestamp address address ] */ ; + SWAP + /* [ operation : list operation : operation : pair timestamp address address ] */ ; + CONS + /* [ list operation : operation : pair timestamp address address ] */ ; + SWAP + /* [ operation : list operation : pair timestamp address address ] */ ; + CONS + /* [ list operation : pair timestamp address address ] */ ; + PAIR + /* [ pair (list operation) timestamp address address ] */ } } +Well typed (Gas remaining: 1039987.872 units remaining) michelson_test_scripts/attic/big_map_union.tz +{ parameter (list (pair string int)) ; + storage (pair (big_map string int) unit) ; + code { UNPAPAIR ; + ITER { UNPAIR + /* [ string : int : big_map string int : unit ] */ ; + DUP 3 + /* [ big_map string int : string : int : big_map string int : unit ] */ ; + DUP 2 + /* [ string : big_map string int : string : int : big_map string int : unit ] */ ; + GET + /* [ option int : string : int : big_map string int : unit ] */ ; + IF_NONE + { PUSH int 0 /* [ int : string : int : big_map string int : unit ] */ } + { /* [ int : string : int : big_map string int : unit ] */ } ; + SWAP + /* [ string : int : int : big_map string int : unit ] */ ; + DIP { ADD + /* [ int : big_map string int : unit ] */ ; + SOME + /* [ option int : big_map string int : unit ] */ } + /* [ string : option int : big_map string int : unit ] */ ; + UPDATE + /* [ big_map string int : unit ] */ } + /* [ big_map string int : unit ] */ ; + PAIR + /* [ pair (big_map string int) unit ] */ ; + NIL operation + /* [ list operation : pair (big_map string int) unit ] */ ; + PAIR + /* [ pair (list operation) (big_map string int) unit ] */ } } +Well typed (Gas remaining: 1039995.487 units remaining) michelson_test_scripts/attic/cadr_annotation.tz +{ parameter (pair (pair %p1 unit (string %no_name)) bool) ; + storage unit ; + code { CAR @param + /* [ pair (pair unit string) bool ] */ ; + CADR @name %no_name ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.685 units remaining) michelson_test_scripts/attic/concat.tz +{ parameter string ; + storage string ; + code { DUP + /* [ pair string string : pair string string ] */ ; + DIP { CDR + /* [ string ] */ ; + NIL string + /* [ list string : string ] */ ; + SWAP + /* [ string : list string ] */ ; + CONS + /* [ list string ] */ } + /* [ pair string string : list string ] */ ; + CAR + /* [ string : list string ] */ ; + CONS + /* [ list string ] */ ; + CONCAT + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039990.665 units remaining) michelson_test_scripts/attic/conditionals.tz +{ parameter (or string (option int)) ; + storage string ; + code { CAR + /* [ or string (option int) ] */ ; + IF_LEFT + { /* [ string ] */ } + { IF_NONE + { FAIL } + { PUSH int 0 + /* [ int : int ] */ ; + CMPGT ; + IF { FAIL } { PUSH string "" /* [ string ] */ } } } ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039993.903 units remaining) michelson_test_scripts/attic/cons_twice.tz +{ parameter nat ; + storage (list nat) ; + code { DUP + /* [ pair nat (list nat) : pair nat (list nat) ] */ ; + CAR + /* [ nat : pair nat (list nat) ] */ ; + DIP { CDR /* [ list nat ] */ } + /* [ nat : list nat ] */ ; + DUP + /* [ nat : nat : list nat ] */ ; + DIP { CONS /* [ list nat ] */ } + /* [ nat : list nat ] */ ; + CONS + /* [ list nat ] */ ; + NIL operation + /* [ list operation : list nat ] */ ; + PAIR + /* [ pair (list operation) (list nat) ] */ } } +Well typed (Gas remaining: 1039976.402 units remaining) michelson_test_scripts/attic/cps_fact.tz +{ storage nat ; + parameter nat ; + code { UNPAIR + /* [ nat : nat ] */ ; + DIP { SELF + /* [ contract nat : nat ] */ ; + ADDRESS + /* [ address : nat ] */ ; + SENDER + /* [ address : address : nat ] */ ; + IFCMPEQ { /* [ nat ] */ } { DROP /* [] */ ; PUSH @storage nat 1 /* [ nat ] */ } } + /* [ nat : nat ] */ ; + DUP + /* [ nat : nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat : nat ] */ ; + IFCMPGE + { DROP + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } + { PUSH nat 1 + /* [ nat : nat : nat ] */ ; + SWAP + /* [ nat : nat : nat ] */ ; + SUB @parameter + /* [ int : nat ] */ ; + ISNAT + /* [ option nat : nat ] */ ; + IF_NONE + { NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } + { DUP + /* [ nat : nat : nat ] */ ; + DIP { PUSH nat 1 + /* [ nat : nat : nat ] */ ; + ADD + /* [ nat : nat ] */ ; + MUL @storage + /* [ nat ] */ } + /* [ nat : nat ] */ ; + SWAP + /* [ nat : nat ] */ ; + DIP { DIP { SELF /* [ contract nat ] */ ; PUSH mutez 0 /* [ mutez : contract nat ] */ } + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ } + /* [ nat : list operation ] */ ; + SWAP + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } } } +Well typed (Gas remaining: 1039990.583 units remaining) michelson_test_scripts/attic/create_add1_lists.tz +{ parameter unit ; + storage address ; + code { DROP + /* [] */ ; + NIL int /* [ list int ] */ + /* [ list int ] */ ; + AMOUNT + /* [ list int ] */ ; + NONE key_hash /* [ int : int ] */ + /* [ option key_hash : mutez : list int ] */ ; + CREATE_CONTRACT + { parameter (list int /* [ list operation : list int ] */) + /* [ int ] */ ; + storage (list int) + /* [ pair (list operation) (list int) ] */ ; + code { CAR ; MAP { PUSH int 1 ; ADD } ; NIL operation ; PAIR } } + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039976.005 units remaining) michelson_test_scripts/attic/data_publisher.tz +{ parameter (pair signature (pair string nat)) ; + storage (pair (pair key nat) string) ; + code { DUP + /* [ pair (pair signature string nat) (pair key nat) string + : pair (pair signature string nat) (pair key nat) string ] */ ; + CAR + /* [ pair signature string nat + : pair (pair signature string nat) (pair key nat) string ] */ ; + DIP { CDR + /* [ pair (pair key nat) string ] */ ; + DUP + /* [ pair (pair key nat) string : pair (pair key nat) string ] */ } + /* [ pair signature string nat : pair (pair key nat) string + : pair (pair key nat) string ] */ ; + SWAP + /* [ pair (pair key nat) string : pair signature string nat + : pair (pair key nat) string ] */ ; + DIP { DUP + /* [ pair signature string nat : pair signature string nat + : pair (pair key nat) string ] */ } + /* [ pair (pair key nat) string : pair signature string nat + : pair signature string nat : pair (pair key nat) string ] */ ; + CAAR ; + DIP { DUP + /* [ pair signature string nat : pair signature string nat + : pair signature string nat : pair (pair key nat) string ] */ ; + CAR + /* [ signature : pair signature string nat : pair signature string nat + : pair (pair key nat) string ] */ ; + DIP { CDR + /* [ pair string nat : pair signature string nat : pair (pair key nat) string ] */ ; + PACK + /* [ bytes : pair signature string nat : pair (pair key nat) string ] */ ; + BLAKE2B + /* [ bytes : pair signature string nat : pair (pair key nat) string ] */ } + /* [ signature : bytes : pair signature string nat + : pair (pair key nat) string ] */ } + /* [ key : signature : bytes : pair signature string nat + : pair (pair key nat) string ] */ ; + CHECK_SIGNATURE + /* [ bool : pair signature string nat : pair (pair key nat) string ] */ ; + IF { CDR + /* [ pair string nat : pair (pair key nat) string ] */ ; + DUP + /* [ pair string nat : pair string nat : pair (pair key nat) string ] */ ; + DIP { CAR + /* [ string : pair (pair key nat) string ] */ ; + DIP { CAAR } + /* [ string : key ] */ } + /* [ pair string nat : string : key ] */ ; + CDR + /* [ nat : string : key ] */ ; + PUSH nat 1 + /* [ nat : nat : string : key ] */ ; + ADD + /* [ nat : string : key ] */ ; + DIP { SWAP /* [ key : string ] */ } + /* [ nat : key : string ] */ ; + SWAP + /* [ key : nat : string ] */ ; + PAIR + /* [ pair key nat : string ] */ ; + PAIR + /* [ pair (pair key nat) string ] */ ; + NIL operation + /* [ list operation : pair (pair key nat) string ] */ ; + PAIR + /* [ pair (list operation) (pair key nat) string ] */ } + { FAIL } } } +Well typed (Gas remaining: 1039983.548 units remaining) michelson_test_scripts/attic/dispatch.tz +{ parameter (or string (pair string (lambda unit string))) ; + storage (pair string (map string (lambda unit string))) ; + code { DUP + /* [ pair (or string (pair string (lambda unit string))) + string + (map string (lambda unit string)) + : pair (or string (pair string (lambda unit string))) + string + (map string (lambda unit string)) ] */ ; + DIP { CDDR } + /* [ pair (or string (pair string (lambda unit string))) + string + (map string (lambda unit string)) : map string (lambda unit string) ] */ ; + CAR + /* [ or string (pair string (lambda unit string)) + : map string (lambda unit string) ] */ ; + IF_LEFT + { DIP { DUP + /* [ map string (lambda unit string) : map string (lambda unit string) ] */ } + /* [ string : map string (lambda unit string) + : map string (lambda unit string) ] */ ; + GET + /* [ option (lambda unit string) : map string (lambda unit string) ] */ ; + IF_NONE + { FAIL } + { /* [ lambda unit string : map string (lambda unit string) ] */ } ; + UNIT + /* [ unit : lambda unit string : map string (lambda unit string) ] */ ; + EXEC + /* [ string : map string (lambda unit string) ] */ } + { DUP + /* [ pair string (lambda unit string) : pair string (lambda unit string) + : map string (lambda unit string) ] */ ; + CAR + /* [ string : pair string (lambda unit string) + : map string (lambda unit string) ] */ ; + DIP { CDR + /* [ lambda unit string : map string (lambda unit string) ] */ ; + SOME + /* [ option (lambda unit string) : map string (lambda unit string) ] */ } + /* [ string : option (lambda unit string) : map string (lambda unit string) ] */ ; + UPDATE + /* [ map string (lambda unit string) ] */ ; + PUSH string "" + /* [ string : map string (lambda unit string) ] */ } ; + PAIR + /* [ pair string (map string (lambda unit string)) ] */ ; + NIL operation + /* [ list operation : pair string (map string (lambda unit string)) ] */ ; + PAIR + /* [ pair (list operation) string (map string (lambda unit string)) ] */ } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/attic/empty.tz +{ parameter unit ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.168 units remaining) michelson_test_scripts/attic/fail_amount.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + AMOUNT + /* [ mutez ] */ ; + PUSH mutez 10000000 + /* [ mutez : mutez ] */ ; + CMPGT ; + IF { FAIL } { /* [] */ } ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039988.163 units remaining) michelson_test_scripts/attic/faucet.tz +{ parameter key_hash ; + storage timestamp ; + code { UNPAIR + /* [ key_hash : timestamp ] */ ; + SWAP + /* [ timestamp : key_hash ] */ ; + PUSH int 300 + /* [ int : timestamp : key_hash ] */ ; + ADD @FIVE_MINUTES_LATER + /* [ timestamp : key_hash ] */ ; + NOW + /* [ timestamp : timestamp : key_hash ] */ ; + ASSERT_CMPGE ; + IMPLICIT_ACCOUNT + /* [ contract unit ] */ ; + PUSH mutez 1000000 + /* [ mutez : contract unit ] */ ; + UNIT + /* [ unit : mutez : contract unit ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + DIP { NOW /* [ timestamp ] */ } + /* [ list operation : timestamp ] */ ; + PAIR + /* [ pair (list operation) timestamp ] */ } } +Well typed (Gas remaining: 1039676.449 units remaining) michelson_test_scripts/attic/forward.tz +{ parameter (or string nat) ; + storage + (pair (pair nat (pair mutez mutez)) + (pair (pair nat (pair timestamp timestamp)) + (pair (pair mutez mutez) (pair (pair address address) address)))) ; + code { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDADDR ; + PUSH int + 86400 + /* [ int : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ timestamp : int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NOW + /* [ timestamp : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + LT + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CAR + /* [ or string nat + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF_LEFT + { DUP + /* [ string : string + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH string + "buyer" + /* [ string : string : string + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int : string + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + EQ + /* [ bool : string + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { DROP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADAR ; + DIP { AMOUNT + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADDR } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH nat + 0 + /* [ nat : pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair nat mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CDDR } + /* [ pair nat mutez mutez + : pair (pair nat timestamp timestamp) (pair mutez mutez) (pair address address) address ] */ ; + PAIR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { PUSH string + "seller" + /* [ string : string + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + EQ + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADDR ; + DIP { AMOUNT + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADAR } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH nat + 0 + /* [ nat : pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair nat mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CDDR } + /* [ pair nat mutez mutez + : pair (pair nat timestamp timestamp) (pair mutez mutez) (pair address address) address ] */ ; + PAIR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { FAIL } } } + { FAIL } } + { BALANCE + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH mutez + 0 + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IFCMPEQ + { FAIL } + { /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } ; + DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDAAR ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDADR } + /* [ nat : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + MUL + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH nat + 2 + /* [ nat : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + MUL + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + BALANCE + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + LT + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { CDR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CADAR ; + DIP { DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDAAR } + /* [ mutez : address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation : operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ operation : list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CONS + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + CADDR ; + DIP { DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + CDDDADR } + /* [ mutez : address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + SWAP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + CADAR ; + DIP { DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + CADDR } + /* [ mutez : mutez + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + ADD + /* [ mutez + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + BALANCE + /* [ mutez : mutez + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + SUB_MUTEZ + /* [ option mutez + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + ASSERT_SOME ; + DIP { DUP + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + CDDDDR } + /* [ mutez : address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address : list operation ] */ ; + DIP { SWAP + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ operation : list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CONS + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDADAR ; + NOW + /* [ timestamp : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + LT + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { FAIL } + { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDADAR ; + PUSH int + 86400 + /* [ int : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NOW + /* [ timestamp : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + LT + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CAR + /* [ or string nat + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF_LEFT + { PUSH string + "buyer" + /* [ string : string + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + EQ + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADAR ; + DIP { AMOUNT + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DUP + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP 2 + { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDAAR ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDAAR } + /* [ nat : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + MUL + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + GT + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { FAIL } + { /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } } + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADDR } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH nat + 0 + /* [ nat : pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair nat mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CDDR } + /* [ pair nat mutez mutez + : pair (pair nat timestamp timestamp) (pair mutez mutez) (pair address address) address ] */ ; + PAIR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { FAIL } } + { FAIL } } + { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDAAR ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDAAR } + /* [ nat : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + MUL + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADAR } + /* [ mutez : mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NEQ + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { BALANCE + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDDADR } + /* [ mutez : address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP 2 + { CDR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation : operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ operation : list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CONS + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDADAR ; + PUSH int + 86400 + /* [ int : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PUSH int + 86400 + /* [ int : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NOW + /* [ timestamp : timestamp + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + LT + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDDDR ; + SENDER + /* [ address : address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NEQ + /* [ bool + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { FAIL } + { /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } ; + DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CAR + /* [ or string nat + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF_LEFT + { FAIL } + { DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDAAR } + /* [ nat : nat + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ADD + /* [ nat + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDADR } + /* [ nat : pair mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair nat mutez mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CDDR } + /* [ pair nat mutez mutez + : pair (pair nat timestamp timestamp) (pair mutez mutez) (pair address address) address ] */ ; + PAIR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + UNIT + /* [ unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DUP + /* [ pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDAAR ; + DIP { DUP + /* [ pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDAAR } + /* [ nat : nat + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + COMPARE + /* [ int + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + LT + /* [ bool + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + IF { CDR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { BALANCE + /* [ mutez + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDDADR } + /* [ mutez : address + : pair unit + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP 2 + { CDR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation : operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ operation : list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CONS + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } } ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + { BALANCE + /* [ mutez + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { DUP + /* [ pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CDDDDAAR } + /* [ mutez : address + : pair (or string nat) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP 2 + { CDR + /* [ pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } + /* [ mutez : address + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + NIL operation + /* [ list operation : operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + SWAP + /* [ operation : list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + CONS + /* [ list operation + : pair (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ ; + PAIR + /* [ pair (list operation) + (pair nat mutez mutez) + (pair nat timestamp timestamp) + (pair mutez mutez) + (pair address address) + address ] */ } } } } } } } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/attic/id.tz +{ parameter string ; + storage string ; + code { CAR + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039995.570 units remaining) michelson_test_scripts/attic/infinite_loop.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH bool True + /* [ bool ] */ ; + LOOP { PUSH bool True /* [ bool ] */ } + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039977.186 units remaining) michelson_test_scripts/attic/insertion_sort.tz +{ parameter (list int) ; + storage (list int) ; + code { CAR + /* [ list int ] */ ; + NIL int + /* [ list int : list int ] */ ; + SWAP + /* [ list int : list int ] */ ; + ITER { SWAP + /* [ list int : int ] */ ; + DIP 2 { NIL int /* [ list int ] */ } + /* [ list int : int : list int ] */ ; + PUSH bool True + /* [ bool : list int : int : list int ] */ ; + LOOP { IF_CONS + { SWAP + /* [ list int : int : int : list int ] */ ; + DIP { DUP + /* [ int : int : int : list int ] */ ; + DIP 2 { DUP /* [ int : int : list int ] */ } + /* [ int : int : int : int : list int ] */ ; + DIP { CMPLT } + /* [ int : bool : int : list int ] */ ; + SWAP + /* [ bool : int : int : list int ] */ } + /* [ list int : bool : int : int : list int ] */ ; + SWAP + /* [ bool : list int : int : int : list int ] */ ; + IF { DIP { SWAP + /* [ int : int : list int ] */ ; + DIP { CONS /* [ list int ] */ } + /* [ int : list int ] */ } + /* [ list int : int : list int ] */ ; + PUSH bool True + /* [ bool : list int : int : list int ] */ } + { SWAP + /* [ int : list int : int : list int ] */ ; + CONS + /* [ list int : int : list int ] */ ; + PUSH bool False + /* [ bool : list int : int : list int ] */ } } + { NIL int + /* [ list int : int : list int ] */ ; + PUSH bool False + /* [ bool : list int : int : list int ] */ } } + /* [ list int : int : list int ] */ ; + SWAP + /* [ int : list int : list int ] */ ; + CONS + /* [ list int : list int ] */ ; + SWAP + /* [ list int : list int ] */ ; + ITER { CONS /* [ list int ] */ } + /* [ list int ] */ } + /* [ list int ] */ ; + NIL operation + /* [ list operation : list int ] */ ; + PAIR + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039970.322 units remaining) michelson_test_scripts/attic/int_publisher.tz +{ parameter (option (pair signature int)) ; + storage (pair key int) ; + code { DUP + /* [ pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + DUP + /* [ pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + CAR + /* [ option (pair signature int) : pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + IF_NONE + { PUSH mutez + 1000000 + /* [ mutez : pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + AMOUNT + /* [ mutez : mutez : pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + CMPLE ; + IF { FAIL } + { /* [ pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ } ; + CDR + /* [ pair key int : pair (option (pair signature int)) key int ] */ ; + DIP { CDDR } + /* [ pair key int : int ] */ } + { DUP + /* [ pair signature int : pair signature int + : pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + DIP { SWAP + /* [ pair (option (pair signature int)) key int : pair signature int + : pair (option (pair signature int)) key int ] */ } + /* [ pair signature int : pair (option (pair signature int)) key int + : pair signature int : pair (option (pair signature int)) key int ] */ ; + SWAP + /* [ pair (option (pair signature int)) key int : pair signature int + : pair signature int : pair (option (pair signature int)) key int ] */ ; + CDAR ; + DIP { DUP + /* [ pair signature int : pair signature int : pair signature int + : pair (option (pair signature int)) key int ] */ ; + CAR + /* [ signature : pair signature int : pair signature int + : pair (option (pair signature int)) key int ] */ ; + DIP { CDR + /* [ int : pair signature int : pair (option (pair signature int)) key int ] */ ; + PACK + /* [ bytes : pair signature int : pair (option (pair signature int)) key int ] */ ; + BLAKE2B + /* [ bytes : pair signature int : pair (option (pair signature int)) key int ] */ } + /* [ signature : bytes : pair signature int + : pair (option (pair signature int)) key int ] */ } + /* [ key : signature : bytes : pair signature int + : pair (option (pair signature int)) key int ] */ ; + CHECK_SIGNATURE + /* [ bool : pair signature int : pair (option (pair signature int)) key int ] */ ; + IF { CDR + /* [ int : pair (option (pair signature int)) key int ] */ ; + SWAP + /* [ pair (option (pair signature int)) key int : int ] */ ; + DIP { DUP /* [ int : int ] */ } + /* [ pair (option (pair signature int)) key int : int : int ] */ ; + CDAR ; + PAIR + /* [ pair key int : int ] */ } + { DROP + /* [ pair (option (pair signature int)) key int ] */ ; + DUP + /* [ pair (option (pair signature int)) key int + : pair (option (pair signature int)) key int ] */ ; + CDR + /* [ pair key int : pair (option (pair signature int)) key int ] */ ; + DIP { CDDR } + /* [ pair key int : int ] */ } } ; + DIP { DROP /* [] */ } + /* [ pair key int ] */ ; + NIL operation + /* [ list operation : pair key int ] */ ; + PAIR + /* [ pair (list operation) key int ] */ } } +Well typed (Gas remaining: 1039974.735 units remaining) michelson_test_scripts/attic/king_of_tez.tz +{ parameter key_hash ; + storage (pair timestamp (pair mutez key_hash)) ; + code { DUP + /* [ pair key_hash timestamp mutez key_hash + : pair key_hash timestamp mutez key_hash ] */ ; + CDAR ; + NOW + /* [ timestamp : timestamp : pair key_hash timestamp mutez key_hash ] */ ; + CMPGT ; + IF { CAR + /* [ key_hash ] */ ; + AMOUNT + /* [ mutez : key_hash ] */ ; + PAIR + /* [ pair mutez key_hash ] */ ; + NOW + /* [ timestamp : pair mutez key_hash ] */ ; + PUSH int 604800 + /* [ int : timestamp : pair mutez key_hash ] */ ; + ADD + /* [ timestamp : pair mutez key_hash ] */ ; + PAIR + /* [ pair timestamp mutez key_hash ] */ ; + NIL operation + /* [ list operation : pair timestamp mutez key_hash ] */ } + { DUP + /* [ pair key_hash timestamp mutez key_hash + : pair key_hash timestamp mutez key_hash ] */ ; + CDDAR ; + AMOUNT + /* [ mutez : mutez : pair key_hash timestamp mutez key_hash ] */ ; + CMPLT ; + IF { FAIL } + { CAR + /* [ key_hash ] */ ; + DUP + /* [ key_hash : key_hash ] */ ; + DIP { AMOUNT + /* [ mutez : key_hash ] */ ; + PAIR + /* [ pair mutez key_hash ] */ ; + NOW + /* [ timestamp : pair mutez key_hash ] */ ; + PUSH int 604800 + /* [ int : timestamp : pair mutez key_hash ] */ ; + ADD + /* [ timestamp : pair mutez key_hash ] */ ; + PAIR + /* [ pair timestamp mutez key_hash ] */ } + /* [ key_hash : pair timestamp mutez key_hash ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : pair timestamp mutez key_hash ] */ ; + AMOUNT + /* [ mutez : contract unit : pair timestamp mutez key_hash ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair timestamp mutez key_hash ] */ ; + TRANSFER_TOKENS + /* [ operation : pair timestamp mutez key_hash ] */ ; + NIL operation + /* [ list operation : operation : pair timestamp mutez key_hash ] */ ; + SWAP + /* [ operation : list operation : pair timestamp mutez key_hash ] */ ; + CONS + /* [ list operation : pair timestamp mutez key_hash ] */ } } ; + PAIR + /* [ pair (list operation) timestamp mutez key_hash ] */ } } +Well typed (Gas remaining: 1039985.851 units remaining) michelson_test_scripts/attic/list_of_transactions.tz +{ parameter unit ; + storage (list address) ; + code { CDR + /* [ list address ] */ ; + DUP + /* [ list address : list address ] */ ; + DIP { NIL operation /* [ list operation : list address ] */ } + /* [ list address : list operation : list address ] */ ; + PUSH bool True + /* [ bool : list address : list operation : list address ] */ ; + LOOP { IF_CONS + { CONTRACT + unit + /* [ option (contract unit) : list address : list operation : list address ] */ ; + ASSERT_SOME ; + PUSH mutez + 1000000 + /* [ mutez : contract unit : list address : list operation : list address ] */ ; + UNIT + /* [ unit : mutez : contract unit : list address : list operation + : list address ] */ ; + TRANSFER_TOKENS + /* [ operation : list address : list operation : list address ] */ ; + SWAP + /* [ list address : operation : list operation : list address ] */ ; + DIP { CONS /* [ list operation : list address ] */ } + /* [ list address : list operation : list address ] */ ; + PUSH bool True + /* [ bool : list address : list operation : list address ] */ } + { NIL address + /* [ list address : list operation : list address ] */ ; + PUSH bool False + /* [ bool : list address : list operation : list address ] */ } } + /* [ list address : list operation : list address ] */ ; + DROP + /* [ list operation : list address ] */ ; + PAIR + /* [ pair (list operation) (list address) ] */ } } +Well typed (Gas remaining: 1039959.640 units remaining) michelson_test_scripts/attic/queue.tz +{ parameter (option string) ; + storage (pair (option string) (pair (pair nat nat) (map nat string))) ; + code { DUP + /* [ pair (option string) (option string) (pair nat nat) (map nat string) + : pair (option string) (option string) (pair nat nat) (map nat string) ] */ ; + CAR + /* [ option string + : pair (option string) (option string) (pair nat nat) (map nat string) ] */ ; + IF_NONE + { CDDR ; + DUP + /* [ pair (pair nat nat) (map nat string) + : pair (pair nat nat) (map nat string) ] */ ; + CAR + /* [ pair nat nat : pair (pair nat nat) (map nat string) ] */ ; + DIP { CDR /* [ map nat string ] */ ; DUP /* [ map nat string : map nat string ] */ } + /* [ pair nat nat : map nat string : map nat string ] */ ; + DUP + /* [ pair nat nat : pair nat nat : map nat string : map nat string ] */ ; + CAR + /* [ nat : pair nat nat : map nat string : map nat string ] */ ; + SWAP + /* [ pair nat nat : nat : map nat string : map nat string ] */ ; + DIP { GET /* [ option string : map nat string ] */ } + /* [ pair nat nat : option string : map nat string ] */ ; + SWAP + /* [ option string : pair nat nat : map nat string ] */ ; + IF_NONE + { NONE string + /* [ option string : pair nat nat : map nat string ] */ ; + DIP { PAIR /* [ pair (pair nat nat) (map nat string) ] */ } + /* [ option string : pair (pair nat nat) (map nat string) ] */ ; + PAIR + /* [ pair (option string) (pair nat nat) (map nat string) ] */ } + { SOME + /* [ option string : pair nat nat : map nat string ] */ ; + DIP { DUP + /* [ pair nat nat : pair nat nat : map nat string ] */ ; + DIP { CAR + /* [ nat : map nat string ] */ ; + DIP { NONE string /* [ option string : map nat string ] */ } + /* [ nat : option string : map nat string ] */ ; + UPDATE + /* [ map nat string ] */ } + /* [ pair nat nat : map nat string ] */ ; + DUP + /* [ pair nat nat : pair nat nat : map nat string ] */ ; + CAR + /* [ nat : pair nat nat : map nat string ] */ ; + PUSH nat 1 + /* [ nat : nat : pair nat nat : map nat string ] */ ; + ADD + /* [ nat : pair nat nat : map nat string ] */ ; + DIP { CDR /* [ nat : map nat string ] */ } + /* [ nat : nat : map nat string ] */ ; + PAIR + /* [ pair nat nat : map nat string ] */ ; + PAIR + /* [ pair (pair nat nat) (map nat string) ] */ } + /* [ option string : pair (pair nat nat) (map nat string) ] */ ; + PAIR + /* [ pair (option string) (pair nat nat) (map nat string) ] */ } } + { DIP { DUP + /* [ pair (option string) (option string) (pair nat nat) (map nat string) + : pair (option string) (option string) (pair nat nat) (map nat string) ] */ ; + CDDAR ; + DIP { CDDDR } + /* [ pair nat nat : map nat string ] */ ; + DUP + /* [ pair nat nat : pair nat nat : map nat string ] */ } + /* [ string : pair nat nat : pair nat nat : map nat string ] */ ; + SWAP + /* [ pair nat nat : string : pair nat nat : map nat string ] */ ; + CAR + /* [ nat : string : pair nat nat : map nat string ] */ ; + DIP { SOME + /* [ option string : pair nat nat : map nat string ] */ ; + SWAP + /* [ pair nat nat : option string : map nat string ] */ ; + CDR + /* [ nat : option string : map nat string ] */ ; + DUP + /* [ nat : nat : option string : map nat string ] */ ; + DIP { UPDATE /* [ map nat string ] */ } + /* [ nat : map nat string ] */ ; + PUSH nat 1 + /* [ nat : nat : map nat string ] */ ; + ADD + /* [ nat : map nat string ] */ } + /* [ nat : nat : map nat string ] */ ; + PAIR + /* [ pair nat nat : map nat string ] */ ; + PAIR + /* [ pair (pair nat nat) (map nat string) ] */ ; + NONE string + /* [ option string : pair (pair nat nat) (map nat string) ] */ ; + PAIR + /* [ pair (option string) (pair nat nat) (map nat string) ] */ } ; + NIL operation + /* [ list operation : pair (option string) (pair nat nat) (map nat string) ] */ ; + PAIR + /* [ pair (list operation) (option string) (pair nat nat) (map nat string) ] */ } } +Well typed (Gas remaining: 1039978.831 units remaining) michelson_test_scripts/attic/reduce_map.tz +{ parameter (pair (lambda int int) (list int)) ; + storage (list int) ; + code { DIP { NIL int /* [ list int ] */ } + /* [ pair (pair (lambda int int) (list int)) (list int) : list int ] */ ; + CAR + /* [ pair (lambda int int) (list int) : list int ] */ ; + DUP + /* [ pair (lambda int int) (list int) : pair (lambda int int) (list int) + : list int ] */ ; + DIP { CAR + /* [ lambda int int : list int ] */ ; + PAIR + /* [ pair (lambda int int) (list int) ] */ } + /* [ pair (lambda int int) (list int) : pair (lambda int int) (list int) ] */ ; + CDR + /* [ list int : pair (lambda int int) (list int) ] */ ; + ITER { PAIR + /* [ pair int (lambda int int) (list int) ] */ ; + DUP + /* [ pair int (lambda int int) (list int) + : pair int (lambda int int) (list int) ] */ ; + CDAR ; + DIP { DUP + /* [ pair int (lambda int int) (list int) + : pair int (lambda int int) (list int) ] */ ; + DIP { CDAR } + /* [ pair int (lambda int int) (list int) : lambda int int ] */ ; + DUP + /* [ pair int (lambda int int) (list int) : pair int (lambda int int) (list int) + : lambda int int ] */ ; + CAR + /* [ int : pair int (lambda int int) (list int) : lambda int int ] */ ; + DIP { CDDR ; SWAP /* [ lambda int int : list int ] */ } + /* [ int : lambda int int : list int ] */ ; + EXEC + /* [ int : list int ] */ ; + CONS + /* [ list int ] */ } + /* [ lambda int int : list int ] */ ; + PAIR + /* [ pair (lambda int int) (list int) ] */ } + /* [ pair (lambda int int) (list int) ] */ ; + CDR + /* [ list int ] */ ; + DIP { NIL int /* [ list int ] */ } + /* [ list int : list int ] */ ; + ITER { CONS /* [ list int ] */ } + /* [ list int ] */ ; + NIL operation + /* [ list operation : list int ] */ ; + PAIR + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039983.510 units remaining) michelson_test_scripts/attic/reentrancy.tz +{ parameter unit ; + storage (pair address address) ; + code { CDR + /* [ pair address address ] */ ; + DUP + /* [ pair address address : pair address address ] */ ; + CAR + /* [ address : pair address address ] */ ; + CONTRACT unit + /* [ option (contract unit) : pair address address ] */ ; + ASSERT_SOME ; + PUSH mutez 5000000 + /* [ mutez : contract unit : pair address address ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair address address ] */ ; + TRANSFER_TOKENS + /* [ operation : pair address address ] */ ; + DIP { DUP + /* [ pair address address : pair address address ] */ ; + CDR + /* [ address : pair address address ] */ ; + CONTRACT unit + /* [ option (contract unit) : pair address address ] */ ; + ASSERT_SOME ; + PUSH mutez 5000000 + /* [ mutez : contract unit : pair address address ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair address address ] */ ; + TRANSFER_TOKENS + /* [ operation : pair address address ] */ } + /* [ operation : operation : pair address address ] */ ; + DIP 2 + { NIL operation /* [ list operation : pair address address ] */ } + /* [ operation : operation : list operation : pair address address ] */ ; + DIP { CONS /* [ list operation : pair address address ] */ } + /* [ operation : list operation : pair address address ] */ ; + CONS + /* [ list operation : pair address address ] */ ; + PAIR + /* [ pair (list operation) address address ] */ } } +Well typed (Gas remaining: 1039970.211 units remaining) michelson_test_scripts/attic/reservoir.tz +{ parameter unit ; + storage (pair (pair (timestamp %T) (mutez %N)) (pair (address %A) (address %B))) ; + code { CDR + /* [ pair (pair timestamp mutez) address address ] */ ; + DUP + /* [ pair (pair timestamp mutez) address address + : pair (pair timestamp mutez) address address ] */ ; + CAAR %T ; + NOW + /* [ timestamp : timestamp : pair (pair timestamp mutez) address address ] */ ; + COMPARE + /* [ int : pair (pair timestamp mutez) address address ] */ ; + LE + /* [ bool : pair (pair timestamp mutez) address address ] */ ; + IF { DUP + /* [ pair (pair timestamp mutez) address address + : pair (pair timestamp mutez) address address ] */ ; + CADR %N ; + BALANCE + /* [ mutez : mutez : pair (pair timestamp mutez) address address ] */ ; + COMPARE + /* [ int : pair (pair timestamp mutez) address address ] */ ; + LE + /* [ bool : pair (pair timestamp mutez) address address ] */ ; + IF { NIL operation + /* [ list operation : pair (pair timestamp mutez) address address ] */ ; + PAIR + /* [ pair (list operation) (pair timestamp mutez) address address ] */ } + { DUP + /* [ pair (pair timestamp mutez) address address + : pair (pair timestamp mutez) address address ] */ ; + CDDR %B ; + CONTRACT + unit + /* [ option (contract unit) : pair (pair timestamp mutez) address address ] */ ; + ASSERT_SOME ; + BALANCE + /* [ mutez : contract unit : pair (pair timestamp mutez) address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair timestamp mutez) address address ] */ ; + TRANSFER_TOKENS + /* [ operation : pair (pair timestamp mutez) address address ] */ ; + NIL operation + /* [ list operation : operation : pair (pair timestamp mutez) address address ] */ ; + SWAP + /* [ operation : list operation : pair (pair timestamp mutez) address address ] */ ; + CONS + /* [ list operation : pair (pair timestamp mutez) address address ] */ ; + PAIR + /* [ pair (list operation) (pair timestamp mutez) address address ] */ } } + { DUP + /* [ pair (pair timestamp mutez) address address + : pair (pair timestamp mutez) address address ] */ ; + CDAR %A ; + CONTRACT + unit + /* [ option (contract unit) : pair (pair timestamp mutez) address address ] */ ; + ASSERT_SOME ; + BALANCE + /* [ mutez : contract unit : pair (pair timestamp mutez) address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair (pair timestamp mutez) address address ] */ ; + TRANSFER_TOKENS + /* [ operation : pair (pair timestamp mutez) address address ] */ ; + NIL operation + /* [ list operation : operation : pair (pair timestamp mutez) address address ] */ ; + SWAP + /* [ operation : list operation : pair (pair timestamp mutez) address address ] */ ; + CONS + /* [ list operation : pair (pair timestamp mutez) address address ] */ ; + PAIR + /* [ pair (list operation) (pair timestamp mutez) address address ] */ } } } +Well typed (Gas remaining: 1039891.106 units remaining) michelson_test_scripts/attic/scrutable_reservoir.tz +{ parameter unit ; + storage + (pair string + (pair timestamp (pair (pair mutez mutez) (pair address (pair address address))))) ; + code { DUP + /* [ pair unit string timestamp (pair mutez mutez) address address address + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + CDAR ; + PUSH string + "open" + /* [ string : string + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + COMPARE + /* [ int + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + NEQ + /* [ bool + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + IF { FAIL } + { DUP + /* [ pair unit string timestamp (pair mutez mutez) address address address + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + CDDAR ; + NOW + /* [ timestamp : timestamp + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + COMPARE + /* [ int + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + LT + /* [ bool + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + IF { PUSH mutez + 0 + /* [ mutez + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + DIP { DUP + /* [ pair unit string timestamp (pair mutez mutez) address address address + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + CDDDAAR } + /* [ mutez : mutez + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + ADD + /* [ mutez + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + DIP { DUP + /* [ pair unit string timestamp (pair mutez mutez) address address address + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + CDDDADR } + /* [ mutez : mutez + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + ADD + /* [ mutez + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + BALANCE + /* [ mutez : mutez + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + COMPARE + /* [ int + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + LT + /* [ bool + : pair unit string timestamp (pair mutez mutez) address address address ] */ ; + IF { CDR + /* [ pair string timestamp (pair mutez mutez) address address address ] */ ; + NIL operation + /* [ list operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + PAIR + /* [ pair (list operation) string timestamp (pair mutez mutez) address address address ] */ } + { CDDR ; + PUSH string + "success" + /* [ string : pair timestamp (pair mutez mutez) address address address ] */ ; + PAIR + /* [ pair string timestamp (pair mutez mutez) address address address ] */ ; + DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDAAR ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDDAR } + /* [ mutez : address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair string timestamp (pair mutez mutez) address address address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDADR ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDDDAR } + /* [ mutez : address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair string timestamp (pair mutez mutez) address address address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair string timestamp (pair mutez mutez) address address address ] */ } + /* [ operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + NIL operation + /* [ list operation : operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + SWAP + /* [ operation : list operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CONS + /* [ list operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + SWAP + /* [ operation : list operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CONS + /* [ list operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + PAIR + /* [ pair (list operation) string timestamp (pair mutez mutez) address address address ] */ } } + { CDDR ; + PUSH string + "timeout" + /* [ string : pair timestamp (pair mutez mutez) address address address ] */ ; + PAIR + /* [ pair string timestamp (pair mutez mutez) address address address ] */ ; + BALANCE + /* [ mutez : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDAAR } + /* [ mutez : mutez + : pair string timestamp (pair mutez mutez) address address address ] */ ; + COMPARE + /* [ int : pair string timestamp (pair mutez mutez) address address address ] */ ; + LT + /* [ bool : pair string timestamp (pair mutez mutez) address address address ] */ ; + IF { BALANCE + /* [ mutez : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDDAR } + /* [ mutez : address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair string timestamp (pair mutez mutez) address address address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair string timestamp (pair mutez mutez) address address address ] */ } + { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDAAR ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDDAR } + /* [ mutez : address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair string timestamp (pair mutez mutez) address address address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair string timestamp (pair mutez mutez) address address address ] */ } ; + DIP { BALANCE + /* [ mutez : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { DUP + /* [ pair string timestamp (pair mutez mutez) address address address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CDDDDDR } + /* [ mutez : address + : pair string timestamp (pair mutez mutez) address address address ] */ ; + DIP { CONTRACT + unit + /* [ option (contract unit) + : pair string timestamp (pair mutez mutez) address address address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + UNIT + /* [ unit : mutez : contract unit + : pair string timestamp (pair mutez mutez) address address address ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair string timestamp (pair mutez mutez) address address address ] */ } + /* [ operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + NIL operation + /* [ list operation : operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + SWAP + /* [ operation : list operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CONS + /* [ list operation : operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + SWAP + /* [ operation : list operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + CONS + /* [ list operation + : pair string timestamp (pair mutez mutez) address address address ] */ ; + PAIR + /* [ pair (list operation) string timestamp (pair mutez mutez) address address address ] */ } } } } +Well typed (Gas remaining: 1039977.017 units remaining) michelson_test_scripts/attic/spawn_identities.tz +{ parameter nat ; + storage (list address) ; + code { /* [ pair string string ] */ + DUP + /* [ list operation : string ] */ ; + CAR + /* [ nat : pair nat (list address) ] */ ; + DIP { CDR /* [ list address ] */ ; NIL operation /* [ list operation : list address ] */ } + /* [ pair (list operation) string ] */ ; + PUSH bool True + /* [ bool : nat : list operation : list address ] */ ; + LOOP { DUP + /* [ nat : nat : list operation : list address ] */ ; + PUSH nat 0 + /* [ nat : nat : nat : list operation : list address ] */ ; + CMPEQ ; + IF { PUSH bool False /* [ bool : nat : list operation : list address ] */ } + { PUSH nat 1 + /* [ nat : nat : list operation : list address ] */ ; + SWAP + /* [ nat : nat : list operation : list address ] */ ; + SUB + /* [ int : list operation : list address ] */ ; + ABS + /* [ nat : list operation : list address ] */ ; + PUSH string "init" + /* [ string : nat : list operation : list address ] */ ; + PUSH mutez 5000000 + /* [ mutez : string : nat : list operation : list address ] */ ; + NONE key_hash + /* [ option key_hash : mutez : string : nat : list operation : list address ] */ ; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } + /* [ operation : address : nat : list operation : list address ] */ ; + SWAP + /* [ address : operation : nat : list operation : list address ] */ ; + DIP { SWAP + /* [ nat : operation : list operation : list address ] */ ; + DIP { CONS /* [ list operation : list address ] */ } + /* [ nat : list operation : list address ] */ } + /* [ address : nat : list operation : list address ] */ ; + SWAP + /* [ nat : address : list operation : list address ] */ ; + DIP { SWAP + /* [ list operation : address : list address ] */ ; + DIP { CONS /* [ list address ] */ } + /* [ list operation : list address ] */ } + /* [ nat : list operation : list address ] */ ; + PUSH bool True + /* [ bool : nat : list operation : list address ] */ } } + /* [ nat : list operation : list address ] */ ; + DROP + /* [ list operation : list address ] */ ; + PAIR + /* [ pair (list operation) (list address) ] */ } } +Well typed (Gas remaining: 1039955.119 units remaining) michelson_test_scripts/entrypoints/big_map_entrypoints.tz +{ storage (pair (big_map string nat) (big_map string nat)) ; + parameter + (or (unit %default + /* [ list operation : big_map string nat ] */) + (or (or %mem + (string %mem_left) + (string %mem_right) + /* [ pair (list operation) (big_map string nat) ] */) + (or (or %add (pair %add_left string nat) (pair %add_right string nat)) + (or %rem (string %rem_left) (string %rem_right)))) + /* [ big_map string nat ] */) + /* [ string : big_map string nat ] */ ; + code { UNPAIR + /* [ or unit + (or (or string string) (or (or (pair string nat) (pair string nat)) (or string string))) + : pair (big_map string nat) (big_map string nat) ] */ ; + IF_LEFT + { DROP + /* [ pair (big_map string nat) (big_map string nat) ] */ ; + DUP + /* [ pair (big_map string nat) (big_map string nat) + : pair (big_map string nat) (big_map string nat) ] */ ; + CAR + /* [ big_map string nat : pair (big_map string nat) (big_map string nat) ] */ ; + PUSH mutez + 0 + /* [ mutez : big_map string nat + : pair (big_map string nat) (big_map string nat) ] */ ; + NONE key_hash + /* [ option key_hash : mutez : big_map string nat + : pair (big_map string nat) (big_map string nat) ] */ ; + CREATE_CONTRACT + { parameter string ; + storage (big_map string nat) ; + code { UNPAIR ; DROP ; NIL operation ; PAIR } } + /* [ operation : address : pair (big_map string nat) (big_map string nat) ] */ ; + DIP { DROP /* [ pair (big_map string nat) (big_map string nat) ] */ } + /* [ operation : pair (big_map string nat) (big_map string nat) ] */ ; + NIL operation + /* [ list operation : operation + : pair (big_map string nat) (big_map string nat) ] */ ; + SWAP + /* [ operation : list operation + : pair (big_map string nat) (big_map string nat) ] */ ; + CONS + /* [ list operation : pair (big_map string nat) (big_map string nat) ] */ ; + PAIR + /* [ pair (list operation) (big_map string nat) (big_map string nat) ] */ } + { IF_LEFT + { IF_LEFT + { DIP { UNPAIR /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { DUP /* [ big_map string nat : big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat : big_map string nat ] */ ; + MEM + /* [ bool : big_map string nat : big_map string nat ] */ ; + ASSERT } + { DIP { UNPAIR + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { DUP /* [ big_map string nat : big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat : big_map string nat ] */ ; + MEM + /* [ bool : big_map string nat : big_map string nat ] */ ; + ASSERT ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } } + { IF_LEFT + { IF_LEFT + { UNPAIR + /* [ string : nat : pair (big_map string nat) (big_map string nat) ] */ ; + DIP 2 + { UNPAIR /* [ big_map string nat : big_map string nat ] */ } + /* [ string : nat : big_map string nat : big_map string nat ] */ ; + DIP { SOME /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ } + { UNPAIR + /* [ string : nat : pair (big_map string nat) (big_map string nat) ] */ ; + DIP 2 + { UNPAIR + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : nat : big_map string nat : big_map string nat ] */ ; + DIP { SOME /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } } + { IF_LEFT + { DIP { UNPAIR /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { NONE nat /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ } + { DIP { UNPAIR + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { NONE nat /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } } } ; + PAIR + /* [ pair (big_map string nat) (big_map string nat) ] */ ; + NIL operation + /* [ list operation : pair (big_map string nat) (big_map string nat) ] */ ; + PAIR + /* [ pair (list operation) (big_map string nat) (big_map string nat) ] */ } } } +Well typed (Gas remaining: 1039961.799 units remaining) michelson_test_scripts/entrypoints/delegatable_target.tz +{ parameter + (or (or (key_hash %set_delegate) (unit %remove_delegate)) (or %default string nat)) ; + storage (pair key_hash (pair string nat)) ; + code { DUP + /* [ pair (or (or key_hash unit) (or string nat)) key_hash string nat + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + CAR + /* [ or (or key_hash unit) (or string nat) + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + IF_LEFT + { PUSH mutez + 0 + /* [ mutez : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + AMOUNT + /* [ mutez : mutez : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + ASSERT_CMPEQ ; + DUP 2 + /* [ pair (or (or key_hash unit) (or string nat)) key_hash string nat + : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + CDR + /* [ pair key_hash string nat : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + CAR + /* [ key_hash : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + ADDRESS + /* [ address : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + SENDER + /* [ address : address : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + IFCMPNEQ + { SENDER + /* [ address : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + PUSH string + "Only the owner can operate." + /* [ string : address : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + PAIR + /* [ pair string address : or key_hash unit + : pair (or (or key_hash unit) (or string nat)) key_hash string nat ] */ ; + FAILWITH + /* [] */ } + { DIP { CDR + /* [ pair key_hash string nat ] */ ; + NIL operation + /* [ list operation : pair key_hash string nat ] */ } + /* [ or key_hash unit : list operation : pair key_hash string nat ] */ ; + IF_LEFT + { SOME + /* [ option key_hash : list operation : pair key_hash string nat ] */ ; + SET_DELEGATE + /* [ operation : list operation : pair key_hash string nat ] */ ; + CONS + /* [ list operation : pair key_hash string nat ] */ ; + PAIR + /* [ pair (list operation) key_hash string nat ] */ } + { DROP + /* [ list operation : pair key_hash string nat ] */ ; + NONE key_hash + /* [ option key_hash : list operation : pair key_hash string nat ] */ ; + SET_DELEGATE + /* [ operation : list operation : pair key_hash string nat ] */ ; + CONS + /* [ list operation : pair key_hash string nat ] */ ; + PAIR + /* [ pair (list operation) key_hash string nat ] */ } } } + { DIP { CDR + /* [ pair key_hash string nat ] */ ; + DUP + /* [ pair key_hash string nat : pair key_hash string nat ] */ ; + CDR + /* [ pair string nat : pair key_hash string nat ] */ } + /* [ or string nat : pair string nat : pair key_hash string nat ] */ ; + PAIR + /* [ pair (or string nat) string nat : pair key_hash string nat ] */ ; + { UNPAIR + /* [ or string nat : pair string nat : pair key_hash string nat ] */ ; + IF_LEFT + { DIP { UNPAIR + /* [ string : nat : pair key_hash string nat ] */ ; + DROP + /* [ nat : pair key_hash string nat ] */ } + /* [ string : nat : pair key_hash string nat ] */ } + { DUG 1 + /* [ pair string nat : nat : pair key_hash string nat ] */ ; + UNPAIR + /* [ string : nat : nat : pair key_hash string nat ] */ ; + DIP { DROP /* [ nat : pair key_hash string nat ] */ } + /* [ string : nat : pair key_hash string nat ] */ } ; + PAIR + /* [ pair string nat : pair key_hash string nat ] */ ; + NIL operation + /* [ list operation : pair string nat : pair key_hash string nat ] */ ; + PAIR + /* [ pair (list operation) string nat : pair key_hash string nat ] */ } ; + SWAP + /* [ pair key_hash string nat : pair (list operation) string nat ] */ ; + CAR + /* [ key_hash : pair (list operation) string nat ] */ ; + SWAP + /* [ pair (list operation) string nat : key_hash ] */ ; + UNPAIR + /* [ list operation : pair string nat : key_hash ] */ ; + DIP { SWAP /* [ key_hash : pair string nat ] */ ; PAIR /* [ pair key_hash string nat ] */ } + /* [ list operation : pair key_hash string nat ] */ ; + PAIR + /* [ pair (list operation) key_hash string nat ] */ } } } +Well typed (Gas remaining: 1039984.594 units remaining) michelson_test_scripts/entrypoints/manager.tz +{ parameter (or (lambda %do unit (list operation)) (unit %default)) ; + storage key_hash ; + code { UNPAIR + /* [ or (lambda unit (list operation)) unit : key_hash ] */ ; + IF_LEFT + { PUSH mutez 0 + /* [ mutez : lambda unit (list operation) : key_hash ] */ ; + AMOUNT + /* [ mutez : mutez : lambda unit (list operation) : key_hash ] */ ; + ASSERT_CMPEQ ; + DUP 2 + /* [ key_hash : lambda unit (list operation) : key_hash ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : lambda unit (list operation) : key_hash ] */ ; + ADDRESS + /* [ address : lambda unit (list operation) : key_hash ] */ ; + SENDER + /* [ address : address : lambda unit (list operation) : key_hash ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit : lambda unit (list operation) : key_hash ] */ ; + EXEC + /* [ list operation : key_hash ] */ ; + PAIR + /* [ pair (list operation) key_hash ] */ } + { DROP + /* [ key_hash ] */ ; + NIL operation + /* [ list operation : key_hash ] */ ; + PAIR + /* [ pair (list operation) key_hash ] */ } } } +Well typed (Gas remaining: 1039990.499 units remaining) michelson_test_scripts/entrypoints/no_default_target.tz +{ storage (pair string nat) ; + parameter (or unit (or %data string nat)) ; + code { UNPAIR + /* [ or unit (or string nat) : pair string nat ] */ ; + IF_LEFT + { DROP + /* [ pair string nat ] */ ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } + { IF_LEFT + { DIP { UNPAIR /* [ string : nat ] */ ; DROP /* [ nat ] */ } /* [ string : nat ] */ } + { DUG 1 + /* [ pair string nat : nat ] */ ; + UNPAIR + /* [ string : nat : nat ] */ ; + DIP { DROP /* [ nat ] */ } + /* [ string : nat ] */ } ; + PAIR + /* [ pair string nat ] */ ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } } } +Well typed (Gas remaining: 1039990.499 units remaining) michelson_test_scripts/entrypoints/no_entrypoint_target.tz +{ storage (pair string nat) ; + parameter (or unit (or string nat)) ; + code { UNPAIR + /* [ or unit (or string nat) : pair string nat ] */ ; + IF_LEFT + { DROP + /* [ pair string nat ] */ ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } + { IF_LEFT + { DIP { UNPAIR /* [ string : nat ] */ ; DROP /* [ nat ] */ } /* [ string : nat ] */ } + { DUG 1 + /* [ pair string nat : nat ] */ ; + UNPAIR + /* [ string : nat : nat ] */ ; + DIP { DROP /* [ nat ] */ } + /* [ string : nat ] */ } ; + PAIR + /* [ pair string nat ] */ ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } } } +Well typed (Gas remaining: 1039990.499 units remaining) michelson_test_scripts/entrypoints/rooted_target.tz +{ storage (pair string nat) ; + parameter (or %root unit (or %default string nat)) ; + code { UNPAIR + /* [ or unit (or string nat) : pair string nat ] */ ; + IF_LEFT + { DROP + /* [ pair string nat ] */ ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } + { IF_LEFT + { DIP { UNPAIR /* [ string : nat ] */ ; DROP /* [ nat ] */ } /* [ string : nat ] */ } + { DUG 1 + /* [ pair string nat : nat ] */ ; + UNPAIR + /* [ string : nat : nat ] */ ; + DIP { DROP /* [ nat ] */ } + /* [ string : nat ] */ } ; + PAIR + /* [ pair string nat ] */ ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } } } +Well typed (Gas remaining: 1039997.610 units remaining) michelson_test_scripts/entrypoints/simple_entrypoints.tz +{ parameter (or (unit %A) (or (string %B) (nat %C))) ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039995.316 units remaining) michelson_test_scripts/macros/assert.tz +{ parameter bool ; + storage unit ; + code { CAR + /* [ bool ] */ ; + ASSERT ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.694 units remaining) michelson_test_scripts/macros/assert_cmpeq.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.694 units remaining) michelson_test_scripts/macros/assert_cmpge.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + ASSERT_CMPGE ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.694 units remaining) michelson_test_scripts/macros/assert_cmpgt.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + ASSERT_CMPGT ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.694 units remaining) michelson_test_scripts/macros/assert_cmple.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + ASSERT_CMPLE ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.694 units remaining) michelson_test_scripts/macros/assert_cmplt.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + ASSERT_CMPLT ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.694 units remaining) michelson_test_scripts/macros/assert_cmpneq.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + ASSERT_CMPNEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.942 units remaining) michelson_test_scripts/macros/assert_eq.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.942 units remaining) michelson_test_scripts/macros/assert_ge.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GE ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.942 units remaining) michelson_test_scripts/macros/assert_gt.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.942 units remaining) michelson_test_scripts/macros/assert_le.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LE ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.942 units remaining) michelson_test_scripts/macros/assert_lt.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.942 units remaining) michelson_test_scripts/macros/assert_neq.tz +{ parameter (pair int int) ; + storage unit ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_NEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039971.464 units remaining) michelson_test_scripts/macros/big_map_get_add.tz +{ parameter (pair (pair %set_pair int (option int)) (pair %check_pair int (option int))) ; + storage (pair (big_map int int) unit) ; + code { DUP + /* [ pair (pair (pair int (option int)) int (option int)) (big_map int int) unit + : pair (pair (pair int (option int)) int (option int)) (big_map int int) unit ] */ ; + DIP { CDAR } + /* [ pair (pair (pair int (option int)) int (option int)) (big_map int int) unit + : big_map int int ] */ ; + DUP + /* [ pair (pair (pair int (option int)) int (option int)) (big_map int int) unit + : pair (pair (pair int (option int)) int (option int)) (big_map int int) unit + : big_map int int ] */ ; + DIP { CADR ; + DUP + /* [ pair int (option int) : pair int (option int) : big_map int int ] */ ; + CAR + /* [ int : pair int (option int) : big_map int int ] */ ; + DIP { CDR /* [ option int : big_map int int ] */ } + /* [ int : option int : big_map int int ] */ ; + UPDATE + /* [ big_map int int ] */ ; + DUP + /* [ big_map int int : big_map int int ] */ } + /* [ pair (pair (pair int (option int)) int (option int)) (big_map int int) unit + : big_map int int : big_map int int ] */ ; + CADR ; + DUP + /* [ pair int (option int) : pair int (option int) : big_map int int + : big_map int int ] */ ; + CDR + /* [ option int : pair int (option int) : big_map int int : big_map int int ] */ ; + DIP { CAR + /* [ int : big_map int int : big_map int int ] */ ; + GET + /* [ option int : big_map int int ] */ } + /* [ option int : option int : big_map int int ] */ ; + IF_SOME + { SWAP + /* [ option int : int : big_map int int ] */ ; + IF_SOME { ASSERT_CMPEQ } { FAIL } } + { ASSERT_NONE } ; + UNIT + /* [ unit : big_map int int ] */ ; + SWAP + /* [ big_map int int : unit ] */ ; + PAIR + /* [ pair (big_map int int) unit ] */ ; + NIL operation + /* [ list operation : pair (big_map int int) unit ] */ ; + PAIR + /* [ pair (list operation) (big_map int int) unit ] */ } } +Well typed (Gas remaining: 1039984.426 units remaining) michelson_test_scripts/macros/big_map_mem.tz +{ parameter (pair int bool) ; + storage (pair (big_map int unit) unit) ; + code { DUP + /* [ pair (pair int bool) (big_map int unit) unit + : pair (pair int bool) (big_map int unit) unit ] */ ; + DUP + /* [ pair (pair int bool) (big_map int unit) unit + : pair (pair int bool) (big_map int unit) unit + : pair (pair int bool) (big_map int unit) unit ] */ ; + CADR ; + DIP { CAAR ; + DIP { CDAR ; DUP /* [ big_map int unit : big_map int unit ] */ } + /* [ int : big_map int unit : big_map int unit ] */ ; + MEM + /* [ bool : big_map int unit ] */ } + /* [ bool : bool : big_map int unit ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit : big_map int unit ] */ ; + SWAP + /* [ big_map int unit : unit ] */ ; + PAIR + /* [ pair (big_map int unit) unit ] */ ; + NIL operation + /* [ list operation : pair (big_map int unit) unit ] */ ; + PAIR + /* [ pair (list operation) (big_map int unit) unit ] */ } } +Well typed (Gas remaining: 1039985.285 units remaining) michelson_test_scripts/macros/build_list.tz +{ parameter nat ; + storage (list nat) ; + code { CAR @counter + /* [ nat ] */ ; + NIL @acc nat + /* [ list nat : nat ] */ ; + SWAP + /* [ nat : list nat ] */ ; + DUP @cmp_num + /* [ nat : nat : list nat ] */ ; + PUSH nat 0 + /* [ nat : nat : nat : list nat ] */ ; + CMPNEQ ; + LOOP { DUP + /* [ nat : nat : list nat ] */ ; + DIP { SWAP /* [ list nat : nat ] */ } + /* [ nat : list nat : nat ] */ ; + CONS @acc + /* [ list nat : nat ] */ ; + SWAP + /* [ nat : list nat ] */ ; + PUSH nat 1 + /* [ nat : nat : list nat ] */ ; + SWAP + /* [ nat : nat : list nat ] */ ; + SUB @counter + /* [ int : list nat ] */ ; + DUP + /* [ int : int : list nat ] */ ; + DIP { ABS /* [ nat : list nat ] */ } + /* [ int : nat : list nat ] */ ; + PUSH int 0 + /* [ int : int : nat : list nat ] */ ; + CMPNEQ } + /* [ nat : list nat ] */ ; + CONS + /* [ list nat ] */ ; + NIL operation + /* [ list operation : list nat ] */ ; + PAIR + /* [ pair (list operation) (list nat) ] */ } } +Well typed (Gas remaining: 1039965.258 units remaining) michelson_test_scripts/macros/carn_and_cdrn.tz +{ parameter (pair nat nat nat unit) ; + storage unit ; + code { CAR + /* [ pair nat nat nat unit ] */ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + CAR + /* [ nat : pair nat nat nat unit ] */ ; + PUSH nat 1 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + CAR 0 ; + PUSH nat 1 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + CAR 1 ; + PUSH nat 4 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + CAR 2 ; + PUSH nat 2 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + CDR 3 ; + UNIT + /* [ unit : unit : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039971.433 units remaining) michelson_test_scripts/macros/compare.tz +{ parameter (pair mutez mutez) ; + storage (list bool) ; + code { CAR + /* [ pair mutez mutez ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez : pair mutez mutez ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez : pair mutez mutez + : pair mutez mutez ] */ ; + DIP 5 + { NIL bool /* [ list bool ] */ } + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez : pair mutez mutez + : pair mutez mutez : list bool ] */ ; + DIP 4 + { DUP + /* [ pair mutez mutez : pair mutez mutez : list bool ] */ ; + CAR + /* [ mutez : pair mutez mutez : list bool ] */ ; + DIP { CDR /* [ mutez : list bool ] */ } + /* [ mutez : mutez : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + LE + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez : pair mutez mutez + : list bool ] */ ; + DIP 3 + { DUP + /* [ pair mutez mutez : pair mutez mutez : list bool ] */ ; + CAR + /* [ mutez : pair mutez mutez : list bool ] */ ; + DIP { CDR /* [ mutez : list bool ] */ } + /* [ mutez : mutez : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + GE + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez : list bool ] */ ; + DIP 2 + { DUP + /* [ pair mutez mutez : pair mutez mutez : list bool ] */ ; + CAR + /* [ mutez : pair mutez mutez : list bool ] */ ; + DIP { CDR /* [ mutez : list bool ] */ } + /* [ mutez : mutez : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + LT + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair mutez mutez : pair mutez mutez : list bool ] */ ; + DIP { DUP + /* [ pair mutez mutez : pair mutez mutez : list bool ] */ ; + CAR + /* [ mutez : pair mutez mutez : list bool ] */ ; + DIP { CDR /* [ mutez : list bool ] */ } + /* [ mutez : mutez : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + GT + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair mutez mutez : list bool ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez : list bool ] */ ; + CAR + /* [ mutez : pair mutez mutez : list bool ] */ ; + DIP { CDR /* [ mutez : list bool ] */ } + /* [ mutez : mutez : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + EQ + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ ; + NIL operation + /* [ list operation : list bool ] */ ; + PAIR + /* [ pair (list operation) (list bool) ] */ } } +Well typed (Gas remaining: 1039971.433 units remaining) michelson_test_scripts/macros/compare_bytes.tz +{ parameter (pair bytes bytes) ; + storage (list bool) ; + code { CAR + /* [ pair bytes bytes ] */ ; + DUP + /* [ pair bytes bytes : pair bytes bytes ] */ ; + DUP + /* [ pair bytes bytes : pair bytes bytes : pair bytes bytes ] */ ; + DUP + /* [ pair bytes bytes : pair bytes bytes : pair bytes bytes : pair bytes bytes ] */ ; + DUP + /* [ pair bytes bytes : pair bytes bytes : pair bytes bytes : pair bytes bytes + : pair bytes bytes ] */ ; + DIP 5 + { NIL bool /* [ list bool ] */ } + /* [ pair bytes bytes : pair bytes bytes : pair bytes bytes : pair bytes bytes + : pair bytes bytes : list bool ] */ ; + DIP 4 + { DUP + /* [ pair bytes bytes : pair bytes bytes : list bool ] */ ; + CAR + /* [ bytes : pair bytes bytes : list bool ] */ ; + DIP { CDR /* [ bytes : list bool ] */ } + /* [ bytes : bytes : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + LE + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair bytes bytes : pair bytes bytes : pair bytes bytes : pair bytes bytes + : list bool ] */ ; + DIP 3 + { DUP + /* [ pair bytes bytes : pair bytes bytes : list bool ] */ ; + CAR + /* [ bytes : pair bytes bytes : list bool ] */ ; + DIP { CDR /* [ bytes : list bool ] */ } + /* [ bytes : bytes : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + GE + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair bytes bytes : pair bytes bytes : pair bytes bytes : list bool ] */ ; + DIP 2 + { DUP + /* [ pair bytes bytes : pair bytes bytes : list bool ] */ ; + CAR + /* [ bytes : pair bytes bytes : list bool ] */ ; + DIP { CDR /* [ bytes : list bool ] */ } + /* [ bytes : bytes : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + LT + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair bytes bytes : pair bytes bytes : list bool ] */ ; + DIP { DUP + /* [ pair bytes bytes : pair bytes bytes : list bool ] */ ; + CAR + /* [ bytes : pair bytes bytes : list bool ] */ ; + DIP { CDR /* [ bytes : list bool ] */ } + /* [ bytes : bytes : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + GT + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ } + /* [ pair bytes bytes : list bool ] */ ; + DUP + /* [ pair bytes bytes : pair bytes bytes : list bool ] */ ; + CAR + /* [ bytes : pair bytes bytes : list bool ] */ ; + DIP { CDR /* [ bytes : list bool ] */ } + /* [ bytes : bytes : list bool ] */ ; + COMPARE + /* [ int : list bool ] */ ; + EQ + /* [ bool : list bool ] */ ; + CONS + /* [ list bool ] */ ; + NIL operation + /* [ list operation : list bool ] */ ; + PAIR + /* [ pair (list operation) (list bool) ] */ } } +Well typed (Gas remaining: 1039998.443 units remaining) michelson_test_scripts/macros/fail.tz +{ parameter unit ; storage unit ; code { FAIL } } +Well typed (Gas remaining: 1039988.389 units remaining) michelson_test_scripts/macros/guestbook.tz +{ parameter string ; + storage (map address (option string)) ; + code { UNPAIR @message @guestbook + /* [ string : map address (option string) ] */ ; + SWAP + /* [ map address (option string) : string ] */ ; + DUP + /* [ map address (option string) : map address (option string) : string ] */ ; + SENDER + /* [ address : map address (option string) : map address (option string) + : string ] */ ; + GET @previous_message + /* [ option (option string) : map address (option string) : string ] */ ; + ASSERT_SOME ; + ASSERT_NONE ; + SWAP + /* [ string : map address (option string) ] */ ; + SOME + /* [ option string : map address (option string) ] */ ; + SOME + /* [ option (option string) : map address (option string) ] */ ; + SENDER + /* [ address : option (option string) : map address (option string) ] */ ; + UPDATE + /* [ map address (option string) ] */ ; + NIL operation + /* [ list operation : map address (option string) ] */ ; + PAIR + /* [ pair (list operation) (map address (option string)) ] */ } } +Well typed (Gas remaining: 1039993.538 units remaining) michelson_test_scripts/macros/macro_annotations.tz +{ parameter unit ; + storage (pair (unit %truc) unit) ; + code { DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + UNIT + /* [ unit : unit ] */ ; + PAIR %truc + /* [ pair unit unit ] */ ; + UNIT + /* [ unit : pair unit unit ] */ ; + DUP @new_storage 2 + /* [ pair unit unit : unit : pair unit unit ] */ ; + DIP { DROP /* [ pair unit unit ] */ ; DROP /* [] */ } + /* [ pair unit unit ] */ ; + NIL operation + /* [ list operation : pair unit unit ] */ ; + PAIR + /* [ pair (list operation) unit unit ] */ } } +Well typed (Gas remaining: 1039967.257 units remaining) michelson_test_scripts/macros/map_caddaadr.tz +{ parameter unit ; + storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat) ; + code { MAP_CDADDAADR @new_storage %value + { PUSH mutez 1000000 + /* [ mutez : mutez : pair nat mutez ] */ ; + ADD + /* [ mutez : pair nat mutez ] */ } ; + NIL operation + /* [ list operation + : pair unit (pair nat nat (pair (pair nat mutez) nat) nat) nat ] */ ; + SWAP + /* [ pair unit (pair nat nat (pair (pair nat mutez) nat) nat) nat + : list operation ] */ ; + SET_CAR } } +Well typed (Gas remaining: 1039988.067 units remaining) michelson_test_scripts/macros/max_in_list.tz +{ parameter (list int) ; + storage (option int) ; + code { CAR + /* [ list int ] */ ; + DIP { NONE int /* [ option int ] */ } + /* [ list int : option int ] */ ; + ITER { SWAP + /* [ option int : int ] */ ; + IF_NONE + { SOME /* [ option int ] */ } + { DIP { DUP /* [ int : int ] */ } + /* [ int : int : int ] */ ; + DUP + /* [ int : int : int : int ] */ ; + DIP { SWAP /* [ int : int : int ] */ } + /* [ int : int : int : int ] */ ; + CMPLE ; + IF { DROP /* [ int ] */ } { DIP { DROP /* [] */ } /* [ int ] */ } ; + SOME + /* [ option int ] */ } } + /* [ option int ] */ ; + NIL operation + /* [ list operation : option int ] */ ; + PAIR + /* [ pair (list operation) (option int) ] */ } } +Well typed (Gas remaining: 1039992.054 units remaining) michelson_test_scripts/macros/min.tz +{ parameter (pair int int) ; + storage int ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + DUP + /* [ pair int int : pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int : pair int int ] */ ; + DIP { CDR /* [ int : pair int int ] */ } + /* [ int : int : pair int int ] */ ; + CMPLT ; + IF { CAR /* [ int ] */ } { CDR /* [ int ] */ } ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039988.944 units remaining) michelson_test_scripts/macros/pair_macro.tz +{ parameter unit ; + storage unit ; + code { UNIT + /* [ unit : pair unit unit ] */ ; + UNIT + /* [ unit : unit : pair unit unit ] */ ; + UNIT + /* [ unit : unit : unit : pair unit unit ] */ ; + UNIT + /* [ unit : unit : unit : unit : pair unit unit ] */ ; + UNIT + /* [ unit : unit : unit : unit : unit : pair unit unit ] */ ; + PAPAPAPAIR @name %x1 %x2 %x3 %x4 %x5 ; + CDDDAR %x4 @fourth ; + DROP + /* [ pair unit unit ] */ ; + CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039971.173 units remaining) michelson_test_scripts/macros/set_caddaadr.tz +{ parameter mutez ; + storage (pair (pair nat (pair nat (pair (pair (pair (nat %p) (mutez %value)) nat) nat))) nat) ; + code { DUP + /* [ pair mutez (pair nat nat (pair (pair nat mutez) nat) nat) nat + : pair mutez (pair nat nat (pair (pair nat mutez) nat) nat) nat ] */ ; + CAR + /* [ mutez : pair mutez (pair nat nat (pair (pair nat mutez) nat) nat) nat ] */ ; + SWAP + /* [ pair mutez (pair nat nat (pair (pair nat mutez) nat) nat) nat : mutez ] */ ; + CDR + /* [ pair (pair nat nat (pair (pair nat mutez) nat) nat) nat : mutez ] */ ; + SET_CADDAADR @toplevel_pair_name %value ; + NIL operation + /* [ list operation : pair (pair nat nat (pair (pair nat mutez) nat) nat) nat ] */ ; + PAIR + /* [ pair (list operation) (pair nat nat (pair (pair nat mutez) nat) nat) nat ] */ } } +Well typed (Gas remaining: 1039993.856 units remaining) michelson_test_scripts/macros/take_my_money.tz +{ parameter key_hash ; + storage unit ; + code { CAR + /* [ key_hash ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit ] */ ; + DIP { UNIT /* [ unit ] */ } + /* [ contract unit : unit ] */ ; + PUSH mutez 1000000 + /* [ mutez : contract unit : unit ] */ ; + UNIT + /* [ unit : mutez : contract unit : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039977.177 units remaining) michelson_test_scripts/macros/unpair_macro.tz +{ parameter (unit :param_unit) ; + storage (unit :u1) ; + code { DROP + /* [] */ ; + UNIT :u4 @a4 + /* [ unit ] */ ; + UNIT :u3 @a3 + /* [ unit : unit ] */ ; + UNIT :u2 @a2 + /* [ unit : unit : unit ] */ ; + UNIT :u1 @a1 + /* [ unit : unit : unit : unit ] */ ; + PAIR + /* [ pair unit unit : unit : unit ] */ ; + UNPAIR @x1 @x2 + /* [ unit : unit : unit : unit ] */ ; + PPAIPAIR @p1 %x1 %x2 %x3 %x4 ; + UNPPAIPAIR %x1 % %x3 %x4 @uno @due @tre @quattro ; + PAPAPAIR @p2 %x1 %x2 %x3 %x4 ; + UNPAPAPAIR @un @deux @trois @quatre ; + PAPPAIIR @p3 %x1 %x2 %x3 %x4 ; + UNPAPPAIIR @one @two @three @four ; + DIP { DROP /* [ unit : unit ] */ ; DROP /* [ unit ] */ ; DROP /* [] */ } + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039563.035 units remaining) michelson_test_scripts/mini_scenarios/999_constant.tz +{ parameter unit ; + storage int ; + code { DROP + /* [] */ ; + PUSH int + (constant + "expruQN5r2umbZVHy6WynYM8f71F8zS4AERz9bugF8UkPBEqrHLuU8" + /* [ list operation : int ] */) + /* [ int ] */ ; + NIL operation /* [ pair (list operation) int ] */ ; + PAIR } } +Well typed (Gas remaining: 1039988.898 units remaining) michelson_test_scripts/mini_scenarios/add_clear_tickets_015.tz +{ parameter (or (pair %add nat string) (unit %clear)) ; + storage (list (ticket string)) ; + code { UNPAIR + /* [ or (pair nat string) unit : list (ticket string) ] */ ; + IF_LEFT + { UNPAIR + /* [ nat : string : list (ticket string) ] */ ; + DIG 2 + /* [ list (ticket string) : nat : string ] */ ; + SWAP + /* [ nat : list (ticket string) : string ] */ ; + DIG 2 + /* [ string : nat : list (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { DROP 2 + /* [] */ ; + NIL (ticket string) + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } } } +Well typed (Gas remaining: 1039999.395 units remaining) michelson_test_scripts/mini_scenarios/always_fails.tz +{ parameter string ; storage unit ; code FAILWITH /* [] */ } +Well typed (Gas remaining: 1039979.965 units remaining) michelson_test_scripts/mini_scenarios/authentication.tz +{ parameter (pair (lambda unit (list operation)) signature) ; + storage (pair (nat %counter) key) ; + code { UNPPAIPAIR ; + DUP 3 + /* [ nat : lambda unit (list operation) : signature : nat : key ] */ ; + DUP 2 + /* [ lambda unit (list operation) : nat : lambda unit (list operation) + : signature : nat : key ] */ ; + SELF + /* [ contract (pair (lambda unit (list operation)) signature) + : lambda unit (list operation) : nat : lambda unit (list operation) + : signature : nat : key ] */ ; + CHAIN_ID + /* [ chain_id : contract (pair (lambda unit (list operation)) signature) + : lambda unit (list operation) : nat : lambda unit (list operation) + : signature : nat : key ] */ ; + PPAIPAIR ; + PACK + /* [ bytes : lambda unit (list operation) : signature : nat : key ] */ ; + DIP { SWAP /* [ signature : lambda unit (list operation) : nat : key ] */ } + /* [ bytes : signature : lambda unit (list operation) : nat : key ] */ ; + DUP 5 + /* [ key : bytes : signature : lambda unit (list operation) : nat : key ] */ ; + DIP { SWAP /* [ signature : bytes : lambda unit (list operation) : nat : key ] */ } + /* [ key : signature : bytes : lambda unit (list operation) : nat : key ] */ ; + DUP 3 + /* [ bytes : key : signature : bytes : lambda unit (list operation) : nat + : key ] */ ; + DIP { CHECK_SIGNATURE /* [ bool : lambda unit (list operation) : nat : key ] */ } + /* [ bytes : bool : lambda unit (list operation) : nat : key ] */ ; + SWAP + /* [ bool : bytes : lambda unit (list operation) : nat : key ] */ ; + IF { DROP /* [ lambda unit (list operation) : nat : key ] */ } { FAILWITH /* [] */ } ; + UNIT + /* [ unit : lambda unit (list operation) : nat : key ] */ ; + EXEC + /* [ list operation : nat : key ] */ ; + DIP { PUSH nat 1 /* [ nat : nat : key ] */ ; ADD /* [ nat : key ] */ } + /* [ list operation : nat : key ] */ ; + PAPAIR } } +Well typed (Gas remaining: 1039996.366 units remaining) michelson_test_scripts/mini_scenarios/big_map_all.tz +{ parameter (pair string (option nat)) ; + storage (big_map string nat) ; + code { UNPAIR + /* [ pair string (option nat) : big_map string nat ] */ ; + UNPAIR + /* [ string : option nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat ] */ ; + NIL operation + /* [ list operation : big_map string nat ] */ ; + PAIR + /* [ pair (list operation) (big_map string nat) ] */ } } +Well typed (Gas remaining: 1039955.119 units remaining) michelson_test_scripts/mini_scenarios/big_map_entrypoints.tz +{ storage (pair (big_map string nat) (big_map string nat)) ; + parameter + (or (unit %default + /* [ list operation : big_map string nat ] */) + (or (or %mem + (string %mem_left) + (string %mem_right) + /* [ pair (list operation) (big_map string nat) ] */) + (or (or %add (pair %add_left string nat) (pair %add_right string nat)) + (or %rem (string %rem_left) (string %rem_right)))) + /* [ big_map string nat ] */) + /* [ string : big_map string nat ] */ ; + code { UNPAIR + /* [ or unit + (or (or string string) (or (or (pair string nat) (pair string nat)) (or string string))) + : pair (big_map string nat) (big_map string nat) ] */ ; + IF_LEFT + { DROP + /* [ pair (big_map string nat) (big_map string nat) ] */ ; + DUP + /* [ pair (big_map string nat) (big_map string nat) + : pair (big_map string nat) (big_map string nat) ] */ ; + CAR + /* [ big_map string nat : pair (big_map string nat) (big_map string nat) ] */ ; + PUSH mutez + 0 + /* [ mutez : big_map string nat + : pair (big_map string nat) (big_map string nat) ] */ ; + NONE key_hash + /* [ option key_hash : mutez : big_map string nat + : pair (big_map string nat) (big_map string nat) ] */ ; + CREATE_CONTRACT + { parameter string ; + storage (big_map string nat) ; + code { UNPAIR ; DROP ; NIL operation ; PAIR } } + /* [ operation : address : pair (big_map string nat) (big_map string nat) ] */ ; + DIP { DROP /* [ pair (big_map string nat) (big_map string nat) ] */ } + /* [ operation : pair (big_map string nat) (big_map string nat) ] */ ; + NIL operation + /* [ list operation : operation + : pair (big_map string nat) (big_map string nat) ] */ ; + SWAP + /* [ operation : list operation + : pair (big_map string nat) (big_map string nat) ] */ ; + CONS + /* [ list operation : pair (big_map string nat) (big_map string nat) ] */ ; + PAIR + /* [ pair (list operation) (big_map string nat) (big_map string nat) ] */ } + { IF_LEFT + { IF_LEFT + { DIP { UNPAIR /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { DUP /* [ big_map string nat : big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat : big_map string nat ] */ ; + MEM + /* [ bool : big_map string nat : big_map string nat ] */ ; + ASSERT } + { DIP { UNPAIR + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { DUP /* [ big_map string nat : big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat : big_map string nat ] */ ; + MEM + /* [ bool : big_map string nat : big_map string nat ] */ ; + ASSERT ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } } + { IF_LEFT + { IF_LEFT + { UNPAIR + /* [ string : nat : pair (big_map string nat) (big_map string nat) ] */ ; + DIP 2 + { UNPAIR /* [ big_map string nat : big_map string nat ] */ } + /* [ string : nat : big_map string nat : big_map string nat ] */ ; + DIP { SOME /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ } + { UNPAIR + /* [ string : nat : pair (big_map string nat) (big_map string nat) ] */ ; + DIP 2 + { UNPAIR + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : nat : big_map string nat : big_map string nat ] */ ; + DIP { SOME /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } } + { IF_LEFT + { DIP { UNPAIR /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { NONE nat /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ } + { DIP { UNPAIR + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + DIP { NONE nat /* [ option nat : big_map string nat : big_map string nat ] */ } + /* [ string : option nat : big_map string nat : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : big_map string nat ] */ } } } ; + PAIR + /* [ pair (big_map string nat) (big_map string nat) ] */ ; + NIL operation + /* [ list operation : pair (big_map string nat) (big_map string nat) ] */ ; + PAIR + /* [ pair (list operation) (big_map string nat) (big_map string nat) ] */ } } } +Well typed (Gas remaining: 1039956.880 units remaining) michelson_test_scripts/mini_scenarios/big_map_magic.tz +{ storage (or (pair (big_map string string) (big_map string string)) unit) ; + parameter + (or (unit %swap) + (or (or %reset (pair (big_map string string) (big_map string string)) unit) + (or (pair %import (list (pair string string)) (list (pair string string))) + (or (list %add (pair string string)) (list %rem string))))) ; + code { UNPAIR + /* [ or unit + (or (or (pair (big_map string string) (big_map string string)) unit) + (or (pair (list (pair string string)) (list (pair string string))) + (or (list (pair string string)) (list string)))) + : or (pair (big_map string string) (big_map string string)) unit ] */ ; + IF_LEFT + { DROP + /* [ or (pair (big_map string string) (big_map string string)) unit ] */ ; + ASSERT_LEFT ; + UNPAIR + /* [ big_map string string : big_map string string ] */ ; + SWAP + /* [ big_map string string : big_map string string ] */ ; + PAIR + /* [ pair (big_map string string) (big_map string string) ] */ ; + LEFT unit + /* [ or (pair (big_map string string) (big_map string string)) unit ] */ } + { IF_LEFT + { SWAP + /* [ or (pair (big_map string string) (big_map string string)) unit + : or (pair (big_map string string) (big_map string string)) unit ] */ ; + DROP + /* [ or (pair (big_map string string) (big_map string string)) unit ] */ } + { IF_LEFT + { DIP { ASSERT_RIGHT ; DROP /* [] */ } + /* [ pair (list (pair string string)) (list (pair string string)) ] */ ; + UNPAIR + /* [ list (pair string string) : list (pair string string) ] */ ; + DIP { EMPTY_BIG_MAP + string + string + /* [ big_map string string : list (pair string string) ] */ } + /* [ list (pair string string) : big_map string string + : list (pair string string) ] */ ; + ITER { UNPAIR + /* [ string : string : big_map string string : list (pair string string) ] */ ; + DIP { SOME + /* [ option string : big_map string string : list (pair string string) ] */ } + /* [ string : option string : big_map string string + : list (pair string string) ] */ ; + UPDATE + /* [ big_map string string : list (pair string string) ] */ } + /* [ big_map string string : list (pair string string) ] */ ; + SWAP + /* [ list (pair string string) : big_map string string ] */ ; + DIP { EMPTY_BIG_MAP string string + /* [ big_map string string : big_map string string ] */ } + /* [ list (pair string string) : big_map string string : big_map string string ] */ ; + ITER { UNPAIR + /* [ string : string : big_map string string : big_map string string ] */ ; + DIP { SOME /* [ option string : big_map string string : big_map string string ] */ } + /* [ string : option string : big_map string string : big_map string string ] */ ; + UPDATE + /* [ big_map string string : big_map string string ] */ } + /* [ big_map string string : big_map string string ] */ ; + SWAP + /* [ big_map string string : big_map string string ] */ ; + PAIR + /* [ pair (big_map string string) (big_map string string) ] */ ; + LEFT unit + /* [ or (pair (big_map string string) (big_map string string)) unit ] */ } + { IF_LEFT + { DIP { ASSERT_LEFT ; UNPAIR /* [ big_map string string : big_map string string ] */ } + /* [ list (pair string string) : big_map string string : big_map string string ] */ ; + ITER { UNPAIR + /* [ string : string : big_map string string : big_map string string ] */ ; + DIP { SOME /* [ option string : big_map string string : big_map string string ] */ } + /* [ string : option string : big_map string string : big_map string string ] */ ; + UPDATE + /* [ big_map string string : big_map string string ] */ } + /* [ big_map string string : big_map string string ] */ ; + PAIR + /* [ pair (big_map string string) (big_map string string) ] */ ; + LEFT unit + /* [ or (pair (big_map string string) (big_map string string)) unit ] */ } + { DIP { ASSERT_LEFT ; UNPAIR /* [ big_map string string : big_map string string ] */ } + /* [ list string : big_map string string : big_map string string ] */ ; + ITER { DIP { NONE string + /* [ option string : big_map string string : big_map string string ] */ } + /* [ string : option string : big_map string string : big_map string string ] */ ; + UPDATE + /* [ big_map string string : big_map string string ] */ } + /* [ big_map string string : big_map string string ] */ ; + PAIR + /* [ pair (big_map string string) (big_map string string) ] */ ; + LEFT unit + /* [ or (pair (big_map string string) (big_map string string)) unit ] */ } } } } ; + NIL operation + /* [ list operation + : or (pair (big_map string string) (big_map string string)) unit ] */ ; + PAIR + /* [ pair (list operation) (or (pair (big_map string string) (big_map string string)) unit) ] */ } } +Well typed (Gas remaining: 1039994.336 units remaining) michelson_test_scripts/mini_scenarios/big_map_read.tz +{ storage nat ; + parameter (big_map nat nat) ; + code { CAR + /* [ big_map nat nat ] */ ; + PUSH nat 1 + /* [ nat : big_map nat nat ] */ ; + GET + /* [ option nat ] */ ; + ASSERT_SOME ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039997.037 units remaining) michelson_test_scripts/mini_scenarios/big_map_store.tz +{ storage (big_map nat nat) ; + parameter unit ; + code { DROP + /* [] */ ; + EMPTY_BIG_MAP nat nat + /* [ big_map nat nat ] */ ; + NIL operation + /* [ list operation : big_map nat nat ] */ ; + PAIR + /* [ pair (list operation) (big_map nat nat) ] */ } } +Well typed (Gas remaining: 1039995.088 units remaining) michelson_test_scripts/mini_scenarios/big_map_write.tz +{ storage unit ; + parameter (big_map nat nat) ; + code { UNPAIR + /* [ big_map nat nat : unit ] */ ; + PUSH (option nat) (Some 1) + /* [ option nat : big_map nat nat : unit ] */ ; + PUSH nat 1 + /* [ nat : option nat : big_map nat nat : unit ] */ ; + UPDATE + /* [ big_map nat nat : unit ] */ ; + DROP + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039995.168 units remaining) michelson_test_scripts/mini_scenarios/cache_consistency.tz +{ parameter (or (unit %renew) (unit %keep)) ; + storage (big_map (nat :a) string) ; + code { UNPAIR + /* [ or unit unit : big_map nat string ] */ ; + IF_LEFT + { DROP 2 /* [] */ ; EMPTY_BIG_MAP nat string /* [ big_map nat string ] */ } + { DROP /* [ big_map nat string ] */ } ; + NIL operation + /* [ list operation : big_map nat string ] */ ; + PAIR + /* [ pair (list operation) (big_map nat string) ] */ } } +Well typed (Gas remaining: 1039986.487 units remaining) michelson_test_scripts/mini_scenarios/check_signature.tz +{ parameter (pair key signature bytes) ; + storage unit ; + code { CAR + /* [ pair key signature bytes ] */ ; + UNPAIR + /* [ key : pair signature bytes ] */ ; + SWAP + /* [ pair signature bytes : key ] */ ; + UNPAIR + /* [ signature : bytes : key ] */ ; + DUP 3 + /* [ key : signature : bytes : key ] */ ; + HASH_KEY + /* [ key_hash : signature : bytes : key ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : signature : bytes : key ] */ ; + SENDER + /* [ address : contract unit : signature : bytes : key ] */ ; + SWAP + /* [ contract unit : address : signature : bytes : key ] */ ; + ADDRESS + /* [ address : address : signature : bytes : key ] */ ; + COMPARE + /* [ int : signature : bytes : key ] */ ; + EQ + /* [ bool : signature : bytes : key ] */ ; + IF { /* [ signature : bytes : key ] */ } + { PUSH string "invalid signer" + /* [ string : signature : bytes : key ] */ ; + FAILWITH + /* [] */ } ; + DIG 2 + /* [ key : signature : bytes ] */ ; + CHECK_SIGNATURE + /* [ bool ] */ ; + IF { UNIT /* [ unit ] */ } + { PUSH string "invalid signature" /* [ string ] */ ; FAILWITH /* [] */ } ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039546.789 units remaining) michelson_test_scripts/mini_scenarios/constant_entrypoints.tz +{ parameter + (or (lambda %do + (constant "exprvKFFbc7SnPjkPZgyhaHewQhmrouNjNae3DpsQ8KuADn9i2WuJ8") + (list operation)) + (unit %default)) ; + storage key_hash ; + code { { { /* [ pair (or (lambda unit (list operation)) unit) key_hash ] */ + DUP + /* [ or (lambda unit (list operation)) unit + : pair (or (lambda unit (list operation)) unit) key_hash ] */ ; + CAR + /* [ or (lambda unit (list operation)) unit : key_hash ] */ ; + DIP { /* [ pair (or (lambda unit (list operation)) unit) key_hash ] */ CDR } } } ; + IF_LEFT + { /* [ lambda unit (list operation) : key_hash ] */ + PUSH mutez 0 /* [ mutez : mutez : lambda unit (list operation) : key_hash ] */ ; + AMOUNT ; + { { /* [ mutez : mutez : lambda unit (list operation) : key_hash ] */ + COMPARE + /* [ bool : lambda unit (list operation) : key_hash ] */ ; + EQ } ; + IF {} + { { /* [ lambda unit (list operation) : key_hash ] */ UNIT /* [] */ ; FAILWITH } } + /* [ lambda unit (list operation) : key_hash ] */ } ; + { /* [ lambda unit (list operation) : key_hash ] */ + DIP { /* [ key_hash ] */ DUP /* [ key_hash : lambda unit (list operation) : key_hash ] */ } ; + SWAP + /* [ contract unit : lambda unit (list operation) : key_hash ] */ } ; + IMPLICIT_ACCOUNT + /* [ address : lambda unit (list operation) : key_hash ] */ ; + ADDRESS + /* [ address : address : lambda unit (list operation) : key_hash ] */ ; + SENDER ; + { { /* [ address : address : lambda unit (list operation) : key_hash ] */ + COMPARE + /* [ bool : lambda unit (list operation) : key_hash ] */ ; + EQ } ; + IF {} + { { /* [ lambda unit (list operation) : key_hash ] */ + UNIT + /* [] */ ; + FAILWITH + /* [ unit : lambda unit (list operation) : key_hash ] */ } } + /* [ lambda unit (list operation) : key_hash ] */ } ; + UNIT + /* [ list operation : key_hash ] */ ; + EXEC + /* [ pair (list operation) key_hash ] */ ; + PAIR } + { /* [ unit : key_hash ] */ + DROP + /* [ list operation : key_hash ] */ ; + NIL operation /* [ pair (list operation) key_hash ] */ ; + PAIR } } } +Well typed (Gas remaining: 1039124.558 units remaining) michelson_test_scripts/mini_scenarios/constant_unit.tz +{ parameter (constant "exprvKFFbc7SnPjkPZgyhaHewQhmrouNjNae3DpsQ8KuADn9i2WuJ8") ; + storage (constant "exprvKFFbc7SnPjkPZgyhaHewQhmrouNjNae3DpsQ8KuADn9i2WuJ8") ; + code { /* [] */ + DROP ; + PUSH unit + /* [ list operation : unit ] */ + (constant + "expruJpGVgueH6vjZDZQRjgXUuHBi4Y6UQ3cbz6swP2FMVybvnDjm5" + /* [ pair (list operation) unit ] */) ; + NIL operation ; + PAIR } + /* [] */ } +Well typed (Gas remaining: 1039973.796 units remaining) michelson_test_scripts/mini_scenarios/create_contract.tz +{ parameter (option address) ; + storage unit ; + code { /* [ pair string string ] */ + CAR + /* [ list operation : string ] */ ; + IF_NONE + { /* [ list operation : string ] */ + PUSH string "dummy" + /* [ string ] */ ; + PUSH mutez 100000000 + /* [ mutez : string ] */ ; + NONE key_hash + /* [ option key_hash : mutez : string ] */ ; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } + /* [ operation : address ] */ ; + DIP { SOME + /* [ option address ] */ ; + DIP { SELF + /* [ contract (option address) ] */ ; + PUSH mutez 0 + /* [ mutez : contract (option address) ] */ } + /* [ option address : mutez : contract (option address) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ } + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } + { SELF + /* [ contract (option address) : address ] */ ; + ADDRESS + /* [ address : address ] */ ; + SENDER + /* [ address : address : address ] */ ; + IFCMPNEQ { FAIL } { /* [ address ] */ } ; + CONTRACT string + /* [ option (contract string) ] */ ; + IF_SOME { /* [ contract string ] */ } { FAIL } ; + PUSH mutez 0 + /* [ mutez : contract string ] */ ; + PUSH string "abcdefg" + /* [ string : mutez : contract string ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } } +Well typed (Gas remaining: 1039992.212 units remaining) michelson_test_scripts/mini_scenarios/create_contract_simple.tz +{ parameter unit ; + storage unit ; + code { CAR + /* [ string ] */ ; + PUSH string "foo" /* [ pair (list operation) string ] */ + /* [ list operation : string ] */ ; + PUSH mutez 0 + /* [ mutez : string : unit ] */ ; + NONE key_hash + /* [ option key_hash : mutez : string : unit ] */ ; + CREATE_CONTRACT + { parameter string ; + storage string ; + code { CAR ; NIL operation ; PAIR } } + /* [ operation : address : unit ] */ ; + DROP + /* [ address : unit ] */ ; + DROP + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.856 units remaining) michelson_test_scripts/mini_scenarios/default_account.tz +{ parameter key_hash ; + storage unit ; + code { DIP { UNIT /* [ unit ] */ } + /* [ pair key_hash unit : unit ] */ ; + CAR + /* [ key_hash : unit ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : unit ] */ ; + PUSH mutez 100000000 + /* [ mutez : contract unit : unit ] */ ; + UNIT + /* [ unit : mutez : contract unit : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.141 units remaining) michelson_test_scripts/mini_scenarios/emit_events.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + PUSH string "right" + /* [ string : unit ] */ ; + RIGHT nat + /* [ or nat string : unit ] */ ; + EMIT %tag1 + /* [ operation : unit ] */ ; + PUSH nat 2 + /* [ nat : operation : unit ] */ ; + LEFT string + /* [ or nat string : operation : unit ] */ ; + EMIT %tag2 (or (nat %int) (string %str)) + /* [ operation : operation : unit ] */ ; + NIL operation + /* [ list operation : operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : operation : unit ] */ ; + CONS + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039990.815 units remaining) michelson_test_scripts/mini_scenarios/execution_order_appender.tz +{ parameter unit ; + storage (pair address string) ; + code { CDR + /* [ pair address string ] */ ; + DUP + /* [ pair address string : pair address string ] */ ; + UNPAIR + /* [ address : string : pair address string ] */ ; + CONTRACT string + /* [ option (contract string) : string : pair address string ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract string : string : pair address string ] */ ; + DIG 2 + /* [ string : mutez : contract string : pair address string ] */ ; + TRANSFER_TOKENS + /* [ operation : pair address string ] */ ; + NIL operation + /* [ list operation : operation : pair address string ] */ ; + SWAP + /* [ operation : list operation : pair address string ] */ ; + CONS + /* [ list operation : pair address string ] */ ; + PAIR + /* [ pair (list operation) address string ] */ } } +Well typed (Gas remaining: 1039992.750 units remaining) michelson_test_scripts/mini_scenarios/execution_order_caller.tz +{ parameter unit ; + storage (list address) ; + code { CDR + /* [ list address ] */ ; + DUP + /* [ list address : list address ] */ ; + MAP { CONTRACT unit + /* [ option (contract unit) : list address ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract unit : list address ] */ ; + UNIT + /* [ unit : mutez : contract unit : list address ] */ ; + TRANSFER_TOKENS + /* [ operation : list address ] */ } + /* [ list operation : list address ] */ ; + PAIR + /* [ pair (list operation) (list address) ] */ } } +Well typed (Gas remaining: 1039997.089 units remaining) michelson_test_scripts/mini_scenarios/execution_order_storer.tz +{ parameter string ; + storage string ; + code { UNPAIR + /* [ string : string ] */ ; + SWAP + /* [ string : string ] */ ; + CONCAT + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039371.088 units remaining) michelson_test_scripts/mini_scenarios/fa12_reference.tz +{ parameter + (or (or (or (pair %transfer (address :from) (pair (address :to) (nat :value))) + (pair %approve (address :spender) (nat :value))) + (or (pair %getAllowance (pair (address :owner) (address :spender)) (contract nat)) + (or (pair %getBalance (address :owner) (contract nat)) + (pair %getTotalSupply unit (contract nat))))) + (or (or (bool %setPause) (address %setAdministrator)) + (or (pair %getAdministrator unit (contract address)) + (or (pair %mint (address :to) (nat :value)) (pair %burn (address :from) (nat :value)))))) ; + storage + (pair (big_map %ledger + (address :user) + (pair (nat :balance) (map :approvals (address :spender) (nat :value)))) + (pair (address %admin) (pair (bool %paused) (nat %totalSupply)))) ; + code { CAST (pair (or (or (or (pair address (pair address nat)) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat))))) + (pair (big_map address (pair nat (map address nat))) (pair address (pair bool nat)))) + /* [ pair (or (or (or (pair address address nat) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat))))) + (big_map address (pair nat (map address nat))) + address + bool + nat ] */ ; + DUP + /* [ pair (or (or (or (pair address address nat) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat))))) + (big_map address (pair nat (map address nat))) + address + bool + nat + : pair (or (or (or (pair address address nat) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat))))) + (big_map address (pair nat (map address nat))) + address + bool + nat ] */ ; + CAR + /* [ or (or (or (pair address address nat) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat)))) + : pair (or (or (or (pair address address nat) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat))))) + (big_map address (pair nat (map address nat))) + address + bool + nat ] */ ; + DIP { CDR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ or (or (or (pair address address nat) (pair address nat)) + (or (pair (pair address address) (contract nat)) + (or (pair address (contract nat)) (pair unit (contract nat))))) + (or (or bool address) + (or (pair unit (contract address)) (or (pair address nat) (pair address nat)))) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_LEFT + { IF_LEFT + { IF_LEFT + { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { UNIT + /* [ unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "TokenOperationsArePaused" + /* [ string : unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + COMPARE + /* [ int : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SENDER + /* [ address : address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + COMPARE + /* [ int : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SENDER + /* [ address : address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address : pair address address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { EMPTY_MAP + address + nat + /* [ map address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { CDR + /* [ map address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ pair address address : map address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : map address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { SENDER + /* [ address : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat : nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SUB + /* [ int : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { DIP { DUP + /* [ nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat : nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "NotEnoughAllowance" + /* [ string : pair nat nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string nat nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ address : nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : pair address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address address nat : pair address address nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DROP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { EMPTY_MAP + address + nat + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EMPTY_MAP + address + nat + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ nat : nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NONE nat + /* [ option nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { SOME + /* [ option nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DIP { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option nat : pair address address nat : map address nat + : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : option nat : map address nat + : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : option nat : map address nat + : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : option nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ map address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : map address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair nat (map address nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { SOME + /* [ option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR /* [ pair address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + DIP { DROP /* [ pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { NONE (pair nat (map address nat)) + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { EMPTY_MAP + address + nat + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SOME + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ADD + /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SOME + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + SWAP + /* [ pair address address nat : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ pair address nat : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR /* [ pair address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + DIP { DROP /* [ pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ int : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ADD + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH string + "Internal: Negative total supply" + /* [ string + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address bool nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair bool nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair bool nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + CDR + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : pair address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + DIP { DROP /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ ; + SWAP + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { CDR + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH nat + 0 + /* [ nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "NotEnoughBalance" + /* [ string : pair nat nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string nat nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SUB + /* [ int : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { CAR + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "NotEnoughBalance" + /* [ string : pair nat nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string nat nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SIZE + /* [ nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NONE (pair nat (map address nat)) + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { SOME + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + { SOME + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + SWAP + /* [ pair address address nat : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR /* [ pair address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + DIP { DROP /* [ pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NEG + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ int : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ADD + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH string + "Internal: Negative total supply" + /* [ string + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address bool nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair bool nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair bool nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + CDR + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : pair address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + DIP { DROP /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ ; + SWAP + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DROP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + NIL operation + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } + { SENDER + /* [ address : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { UNIT + /* [ unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "TokenOperationsArePaused" + /* [ string : unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { EMPTY_MAP + address + nat + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { CDR + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ pair address address nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DUP + /* [ nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { PUSH string + "UnsafeAllowanceChange" + /* [ string : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } } ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : address : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { EMPTY_MAP + address + nat + /* [ map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EMPTY_MAP + address + nat + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ nat : nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NONE nat + /* [ option nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { SOME + /* [ option nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DIP { DIP { DUP + /* [ pair address address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address address nat + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : pair address address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option nat : pair address address nat : map address nat + : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : option nat : map address nat + : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address nat : option nat : map address nat + : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : option nat : map address nat : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ map address nat : pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) + : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ map address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : map address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ map address nat : nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : map address nat : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address address nat : pair nat (map address nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair nat (map address nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { SOME + /* [ option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR /* [ pair address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + DIP { DROP /* [ pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } } + { IF_LEFT + { DUP + /* [ pair (pair address address) (contract nat) + : pair (pair address address) (contract nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ pair address address : pair (pair address address) (contract nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address + : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (pair address address) + (big_map address (pair nat (map address nat))) + address + bool + nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair (pair address address) + (big_map address (pair nat (map address nat))) + address + bool + nat + : pair (pair address address) + (big_map address (pair nat (map address nat))) + address + bool + nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ pair address address + : pair (pair address address) + (big_map address (pair nat (map address nat))) + address + bool + nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address address + : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address address : pair address address + : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { EMPTY_MAP + address + nat + /* [ map address nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { CDR + /* [ map address nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + /* [ pair address address : map address nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ address : map address nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { /* [ nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { AMOUNT + /* [ mutez : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : mutez : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation : operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ operation : list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CONS + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } + { IF_LEFT + { DUP + /* [ pair address (contract nat) : pair address (contract nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair address (contract nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address (big_map address (pair nat (map address nat))) address bool nat + : pair address (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair address (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { CAR + /* [ nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { AMOUNT + /* [ mutez : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : mutez : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation : operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ operation : list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CONS + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair unit (contract nat) : pair unit (contract nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ unit : pair unit (contract nat) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ unit : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ unit : pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair unit (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { AMOUNT + /* [ mutez : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : mutez : contract nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation : operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ operation : list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CONS + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } } } } + { IF_LEFT + { IF_LEFT + { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SENDER + /* [ address : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + COMPARE + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { UNIT + /* [ unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "SenderIsNotAdmin" + /* [ string : unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } } + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ bool : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address bool nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ bool : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair bool nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair bool nat : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ bool : bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + CDR + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : pair address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + DIP { DROP /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ ; + SWAP + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SENDER + /* [ address : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + COMPARE + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { UNIT + /* [ unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "SenderIsNotAdmin" + /* [ string : unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } } + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address bool nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address bool nat : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + CDR + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : pair address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + DIP { DROP /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ ; + SWAP + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } } + { IF_LEFT + { DUP + /* [ pair unit (contract address) : pair unit (contract address) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ unit : pair unit (contract address) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ unit : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ contract address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ unit : pair (big_map address (pair nat (map address nat))) address bool nat + : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair unit (big_map address (pair nat (map address nat))) address bool nat + : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { AMOUNT + /* [ mutez : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : mutez : contract address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + TRANSFER_TOKENS + /* [ operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation : operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ operation : list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CONS + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } + { IF_LEFT + { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SENDER + /* [ address : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + COMPARE + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { UNIT + /* [ unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "SenderIsNotAdmin" + /* [ string : unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { NONE (pair nat (map address nat)) + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { EMPTY_MAP + address + nat + /* [ map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SOME + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + { DIP { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ADD + /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SOME + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + SWAP + /* [ pair address nat : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address nat : pair address nat : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR /* [ pair address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + DIP { DROP /* [ pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ int : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ADD + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH string + "Internal: Negative total supply" + /* [ string + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address bool nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair bool nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair bool nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + CDR + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : pair address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + DIP { DROP /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ ; + SWAP + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DROP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } + { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SENDER + /* [ address : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + COMPARE + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { UNIT + /* [ unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "SenderIsNotAdmin" + /* [ string : unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string unit + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat + : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ big_map address (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : big_map address (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + GET + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH nat + 0 + /* [ nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "NotEnoughBalance" + /* [ string : pair nat nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string nat nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DUP + /* [ pair nat (map address nat) : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat : nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ nat : nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SUB + /* [ int : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { CAR + /* [ nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat : nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PUSH string + "NotEnoughBalance" + /* [ string : pair nat nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair string nat nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : map address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair nat (map address nat) : pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ pair address nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DUP + /* [ pair nat (map address nat) : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ map address nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SIZE + /* [ nat : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + INT + /* [ int : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + EQ + /* [ bool : pair nat (map address nat) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF { DROP + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NONE (pair nat (map address nat)) + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + { SOME + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } } + { SOME + /* [ option (pair nat (map address nat)) : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + SWAP + /* [ pair address nat : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ address : option (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ address : option (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + UPDATE + /* [ big_map address (pair nat (map address nat)) + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR /* [ pair address bool nat ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair address bool nat ] */ ; + CAR + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) + : big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + DIP { DROP /* [ pair address bool nat ] */ } + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DUP + /* [ pair address nat : pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NEG + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ int : nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ADD + /* [ int + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + ISNAT + /* [ option nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + IF_NONE + { PUSH string + "Internal: Negative total supply" + /* [ string + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair address bool nat : pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair bool nat : pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair bool nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + CDR + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DROP + /* [ bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ nat : bool : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ bool : nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair bool nat : address + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + SWAP + /* [ address : pair bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { DUP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DIP { CAR /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair (big_map address (pair nat (map address nat))) address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + CDR + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : pair address bool nat + : big_map address (pair nat (map address nat)) ] */ ; + DIP { DROP /* [ big_map address (pair nat (map address nat)) ] */ } + /* [ pair address bool nat : big_map address (pair nat (map address nat)) ] */ ; + SWAP + /* [ big_map address (pair nat (map address nat)) : pair address bool nat ] */ ; + PAIR + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ } + /* [ pair address nat + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + DROP + /* [ pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address (pair nat (map address nat))) address bool nat ] */ ; + PAIR + /* [ pair (list operation) (big_map address (pair nat (map address nat))) address bool nat ] */ } } } } } } +Well typed (Gas remaining: 1039995.761 units remaining) michelson_test_scripts/mini_scenarios/fail_on_false.tz +{ parameter bool ; + storage unit ; + code { UNPAIR + /* [ bool : unit ] */ ; + IF { NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } + { DROP /* [] */ ; PUSH string "bang" /* [ string ] */ ; FAILWITH /* [] */ } } } +Well typed (Gas remaining: 1039941.741 units remaining) michelson_test_scripts/mini_scenarios/generic_multisig.tz +{ parameter + (or (unit %default) + (pair %main + (pair :payload + (nat %counter) + (or :action + (lambda %operation unit (list operation)) + (pair %change_keys (nat %threshold) (list %keys key)))) + (list %sigs (option signature)))) ; + storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))) ; + code { UNPAIR + /* [ or unit + (pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature))) : pair nat nat (list key) ] */ ; + IF_LEFT + { DROP + /* [ pair nat nat (list key) ] */ ; + NIL operation + /* [ list operation : pair nat nat (list key) ] */ ; + PAIR + /* [ pair (list operation) nat nat (list key) ] */ } + { PUSH mutez + 0 + /* [ mutez + : pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature)) : pair nat nat (list key) ] */ ; + AMOUNT + /* [ mutez : mutez + : pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature)) : pair nat nat (list key) ] */ ; + ASSERT_CMPEQ ; + SWAP + /* [ pair nat nat (list key) + : pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature)) ] */ ; + DUP + /* [ pair nat nat (list key) : pair nat nat (list key) + : pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature)) ] */ ; + DIP { SWAP + /* [ pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature)) : pair nat nat (list key) ] */ } + /* [ pair nat nat (list key) + : pair (pair nat (or (lambda unit (list operation)) (pair nat (list key)))) + (list (option signature)) : pair nat nat (list key) ] */ ; + DIP { UNPAIR + /* [ pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + DUP + /* [ pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + SELF + /* [ contract unit + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + ADDRESS + /* [ address + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + CHAIN_ID + /* [ chain_id : address + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + PAIR + /* [ pair chain_id address + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + PAIR + /* [ pair (pair chain_id address) nat (or (lambda unit (list operation)) (pair nat (list key))) + : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + PACK + /* [ bytes : pair nat (or (lambda unit (list operation)) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + DIP { UNPAIR @counter + /* [ nat : or (lambda unit (list operation)) (pair nat (list key)) + : list (option signature) : pair nat nat (list key) ] */ ; + DIP { SWAP + /* [ list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ nat : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ bytes : nat : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + SWAP + /* [ nat : bytes : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ pair nat nat (list key) : nat : bytes : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + UNPAIR @stored_counter + /* [ nat : pair nat (list key) : nat : bytes : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DIP { SWAP + /* [ nat : pair nat (list key) : bytes : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ nat : nat : pair nat (list key) : bytes : list (option signature) + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + ASSERT_CMPEQ ; + DIP { SWAP + /* [ list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ pair nat (list key) : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + UNPAIR @threshold @keys + /* [ nat : list key : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DIP { PUSH @valid + nat + 0 + /* [ nat : list key : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + SWAP + /* [ list key : nat : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + ITER { DIP { SWAP + /* [ list (option signature) : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ key : list (option signature) : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + SWAP + /* [ list (option signature) : key : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + IF_CONS + { IF_SOME + { SWAP + /* [ list (option signature) : signature : key : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DIP { SWAP + /* [ key : signature : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DIP 2 + { DUP 2 + /* [ bytes : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ key : signature : bytes : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + { DUP 3 + /* [ bytes : key : signature : bytes : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DIP { CHECK_SIGNATURE + /* [ bool : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ bytes : bool : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + SWAP + /* [ bool : bytes : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + IF { DROP + /* [ nat : bytes : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + { FAILWITH /* [] */ } } ; + PUSH nat + 1 + /* [ nat : nat : bytes : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + ADD @valid + /* [ nat : bytes : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ list (option signature) : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + { SWAP + /* [ key : list (option signature) : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DROP + /* [ list (option signature) : nat : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } } + { FAIL } ; + SWAP + /* [ nat : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ nat : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } + /* [ nat : nat : list (option signature) : bytes + : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + ASSERT_CMPLE ; + IF_CONS + { FAIL } + { /* [ bytes : or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ } ; + DROP + /* [ or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + DIP { UNPAIR + /* [ nat : pair nat (list key) ] */ ; + PUSH nat 1 + /* [ nat : nat : pair nat (list key) ] */ ; + ADD @new_counter + /* [ nat : pair nat (list key) ] */ ; + PAIR + /* [ pair nat nat (list key) ] */ } + /* [ or (lambda unit (list operation)) (pair nat (list key)) + : pair nat nat (list key) ] */ ; + IF_LEFT + { UNIT + /* [ unit : lambda unit (list operation) : pair nat nat (list key) ] */ ; + EXEC + /* [ list operation : pair nat nat (list key) ] */ } + { DIP { CAR /* [ nat ] */ } + /* [ pair nat (list key) : nat ] */ ; + SWAP + /* [ nat : pair nat (list key) ] */ ; + PAIR + /* [ pair nat nat (list key) ] */ ; + NIL operation + /* [ list operation : pair nat nat (list key) ] */ } ; + PAIR + /* [ pair (list operation) nat nat (list key) ] */ } } } +Well typed (Gas remaining: 1039536.611 units remaining) michelson_test_scripts/mini_scenarios/groth16.tz +{ storage unit ; + parameter + (pair (pair (bls12_381_fr %input_x) (bls12_381_fr %input_y)) + (pair (pair (bls12_381_g1 %proof_a) (bls12_381_g2 %proof_b)) (bls12_381_g1 %proof_c))) ; + code { CAR + /* [ pair (pair bls12_381_fr bls12_381_fr) (pair bls12_381_g1 bls12_381_g2) bls12_381_g1 ] */ ; + UNPPAIPPAIIR ; + DIP 5 + { PUSH @vk_gamma_c + bls12_381_g1 + 0x063bd6e11e2fcaac1dd8cf68c6b1925a73c3c583e298ed37c41c3715115cf96358a42dbe85a0228cbfd8a6c8a8c54cd015b5ae2860d1cc47f84698d951f14d9448d03f04df2ca0ffe609a2067d6f1a892163a5e05e541279134cae52b1f23c6b + /* [ bls12_381_g1 ] */ ; + PUSH @vk_gamma_b + bls12_381_g1 + 0x11f5b5db1da7f1f26217edcce2219d016003af6e5b4d1ca3ad0ff477e354717e658bf16beddc4f4fb76ce39d3327811e0601709dc7ed98c70463cfa1ba33f99851b52b51d1a042d7425bec6277287441c399973632445ce61e7fdd63a70f0f60 + /* [ bls12_381_g1 : bls12_381_g1 ] */ ; + PUSH @vk_gamma_a + bls12_381_g1 + 0x03535a322edd23c55b0ca025e54d450d95df49cc9ee873dcd500e8219f4771264bf159b3b105954d85c7bea8ffe1ea0400c767fe58989366c2837fba76f1b4f46644f19be8ad01e22d894b649e427e0d7e04677ee3919d982f0f96bb0a2f0c34 + /* [ bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PUSH @vk_delta + bls12_381_g2 + 0x10c6d5cdca84fc3c7f33061add256f48e0ab03a697832b338901898b650419eb6f334b28153fb73ad2ecd1cd2ac67053161e9f46cfbdaf7b1132a4654a55162850249650f9b873ac3113fa8c02ef1cd1df481480a4457f351d28f4da89d19fa405c3d77f686dc9a24d2681c9184bf2b091f62e6b24df651a3da8bd7067e14e7908fb02f8955b84af5081614cb5bc49b416d9edf914fc608c441b3f2eb8b6043736ddb9d4e4d62334a23b5625c14ef3e1a7e99258386310221b22d83a5eac035c + /* [ bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PUSH @vk_gamma + bls12_381_g2 + 0x16dcbd28bff336c2649c7dd1d8391ac7ce6f7ef0124a9db7a4a485a124199eded7ce963c1c18aee1eca9994fe06f192c00e0fb653e1fc737d8d0e2f2f91424ca01f6e6e7c5c04f1c43db03a2900cf6b942aaed6ae77daea6200e094b78c38d770028d531a9d1a118ec23d5a39be7aa6dc28f778da1988856d2235c4a35e81fa48380f050d4baf7ebd7b5e058bf294da916afc34562f097c02a8fcbcf62a00de44f8ae6cfa7acb8ad254e3aeea8b2af12f65b7ee0f54855cb9bd432f3436f238f + /* [ bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PUSH @vk_b + bls12_381_g2 + 0x0e9383f98df2c6e8b5b45f3876c3384596a0cdbc41349f83c4380bf463a050cdbd1d5057aa483a642e66486d1ed7362a1869e423c3877095e215c17282b11108601166f928043254bbce603bf86f4cec9f2e97e9660e98e4f5bce9b2b3bbacb40946b702ccfcc9a31e0bfc1543a2128edcc95807740a2310ae25eb47b935648e392c58dfae5b5e899d3b970d64e4e9e209741ea8bfedcfcc16b3fd890ff02c788ec0943feaaf01bbb354317acb85fcfd611133e4e563d53ca4e0f50e21cf2e7e + /* [ bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g1 ] */ ; + PUSH @vk_a + bls12_381_g1 + 0x1040577c7d349e332735fc947c868c24a665f812f5dc1e7f60e65e2df80be2267a4b7341ed2287285fccd517acd96d910abba947235c364553aa6445f2f2b3a1a728225a330286ba5197ab87f0edc560d89fc7b623812f7d0d633341726e597a + /* [ bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g1 ] */ } + /* [ bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP + /* [ bls12_381_fr : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 12 + /* [ bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_fr : bls12_381_g1 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + MUL + /* [ bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 3 + /* [ bls12_381_fr : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 14 + /* [ bls12_381_g1 : bls12_381_fr : bls12_381_g1 : bls12_381_fr : bls12_381_fr + : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 + : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + MUL + /* [ bls12_381_g1 : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + ADD + /* [ bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 11 + /* [ bls12_381_g1 : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + ADD @vk_x + /* [ bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + NIL (pair bls12_381_g1 bls12_381_g2) + /* [ list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 : bls12_381_fr + : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g1 ] */ ; + DUP 9 + /* [ bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 + : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 9 + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + NEG + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PAIR + /* [ pair bls12_381_g1 bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + CONS + /* [ list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 : bls12_381_fr + : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g1 ] */ ; + DUP 11 + /* [ bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 + : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 8 + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + NEG + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PAIR + /* [ pair bls12_381_g1 bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + CONS + /* [ list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 : bls12_381_fr + : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g1 ] */ ; + DUP 10 + /* [ bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 + : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 3 + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + NEG + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PAIR + /* [ pair bls12_381_g1 bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + CONS + /* [ list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 : bls12_381_fr + : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g1 ] */ ; + DUP 6 + /* [ bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 + : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 + : bls12_381_g1 : bls12_381_g1 ] */ ; + DUP 6 + /* [ bls12_381_g1 : bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + PAIR + /* [ pair bls12_381_g1 bls12_381_g2 : list (pair bls12_381_g1 bls12_381_g2) + : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + CONS + /* [ list (pair bls12_381_g1 bls12_381_g2) : bls12_381_g1 : bls12_381_fr + : bls12_381_fr : bls12_381_g1 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g2 : bls12_381_g2 : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 + : bls12_381_g1 ] */ ; + PAIRING_CHECK + /* [ bool : bls12_381_g1 : bls12_381_fr : bls12_381_fr : bls12_381_g1 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g2 : bls12_381_g2 + : bls12_381_g2 : bls12_381_g1 : bls12_381_g1 : bls12_381_g1 ] */ ; + ASSERT ; + DROP 13 + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039992.602 units remaining) michelson_test_scripts/mini_scenarios/hardlimit.tz +{ parameter unit ; + storage int ; + code { CDR + /* [ int ] */ ; + DUP + /* [ int : int ] */ ; + PUSH int 0 + /* [ int : int : int ] */ ; + CMPLT ; + IF { PUSH int -1 /* [ int : int ] */ ; ADD /* [ int ] */ } { FAIL } ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039991.478 units remaining) michelson_test_scripts/mini_scenarios/large_error.tz +{ parameter int ; + storage unit ; + code { CAR + /* [ int ] */ ; + PUSH string "a" + /* [ string : int ] */ ; + SWAP + /* [ int : string ] */ ; + PUSH bool True + /* [ bool : int : string ] */ ; + LOOP { SWAP + /* [ string : int ] */ ; + DUP + /* [ string : string : int ] */ ; + CONCAT + /* [ string : int ] */ ; + SWAP + /* [ int : string ] */ ; + PUSH int -1 + /* [ int : int : string ] */ ; + ADD + /* [ int : string ] */ ; + DUP + /* [ int : int : string ] */ ; + GT + /* [ bool : int : string ] */ } + /* [ int : string ] */ ; + DROP + /* [ string ] */ ; + FAILWITH + /* [] */ } } +Well typed (Gas remaining: 1035239.092 units remaining) michelson_test_scripts/mini_scenarios/large_flat_contract.tz +{ parameter unit ; + storage unit ; + code { { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + { UNIT /* [ unit : pair unit unit ] */ ; DROP /* [ pair unit unit ] */ } ; + CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1032048.446 units remaining) michelson_test_scripts/mini_scenarios/large_str_id.tz +{ parameter (or int unit) ; + storage (pair string string) ; + code { UNPAIR + /* [ or int unit : pair string string ] */ ; + IF_LEFT + { DIP 1 { UNPAIR /* [ string : string ] */ ; DROP /* [ string ] */ } + /* [ int : string ] */ ; + DUP + /* [ int : int : string ] */ ; + NEQ + /* [ bool : int : string ] */ ; + LOOP { SWAP + /* [ string : int ] */ ; + DUP + /* [ string : string : int ] */ ; + CONCAT + /* [ string : int ] */ ; + SWAP + /* [ int : string ] */ ; + PUSH int 1 + /* [ int : int : string ] */ ; + SWAP + /* [ int : int : string ] */ ; + SUB + /* [ int : string ] */ ; + DUP + /* [ int : int : string ] */ ; + NEQ + /* [ bool : int : string ] */ } + /* [ int : string ] */ ; + DROP + /* [ string ] */ ; + DUP + /* [ string : string ] */ ; + PAIR + /* [ pair string string ] */ } + { DROP + /* [ pair string string ] */ ; + UNPAIR + /* [ string : string ] */ ; + DUP + /* [ string : string : string ] */ ; + DIP 1 { CONCAT /* [ string ] */ } + /* [ string : string ] */ ; + PAIR + /* [ pair string string ] */ } ; + NIL operation + /* [ list operation : pair string string ] */ ; + PAIR + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ ; + DUP + /* [ pair (list operation) string string : pair (list operation) string string ] */ ; + DROP + /* [ pair (list operation) string string ] */ } } +Well typed (Gas remaining: 1039945.396 units remaining) michelson_test_scripts/mini_scenarios/legacy_multisig.tz +{ parameter + (pair (pair :payload + (nat %counter) + (or :action + (pair :transfer (mutez %amount) (contract %dest unit)) + (or (option %delegate key_hash) + (pair %change_keys (nat %threshold) (list %keys key))))) + (list %sigs (option signature))) ; + storage (pair (nat %stored_counter) (pair (nat %threshold) (list %keys key))) ; + code { UNPAIR + /* [ pair (pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))))) + (list (option signature)) : pair nat nat (list key) ] */ ; + SWAP + /* [ pair nat nat (list key) + : pair (pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))))) + (list (option signature)) ] */ ; + DUP + /* [ pair nat nat (list key) : pair nat nat (list key) + : pair (pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))))) + (list (option signature)) ] */ ; + DIP { SWAP + /* [ pair (pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))))) + (list (option signature)) : pair nat nat (list key) ] */ } + /* [ pair nat nat (list key) + : pair (pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))))) + (list (option signature)) : pair nat nat (list key) ] */ ; + DIP { UNPAIR + /* [ pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + DUP + /* [ pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + SELF + /* [ contract + (pair (pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))))) + (list (option signature))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + ADDRESS + /* [ address + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + CHAIN_ID + /* [ chain_id : address + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + PAIR + /* [ pair chain_id address + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + PAIR + /* [ pair (pair chain_id address) + nat + (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + PACK + /* [ bytes + : pair nat (or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key)))) + : list (option signature) : pair nat nat (list key) ] */ ; + DIP { UNPAIR @counter + /* [ nat + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : list (option signature) : pair nat nat (list key) ] */ ; + DIP { SWAP + /* [ list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ nat : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ bytes : nat : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + SWAP + /* [ nat : bytes : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ pair nat nat (list key) : nat : bytes : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + UNPAIR @stored_counter + /* [ nat : pair nat (list key) : nat : bytes : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DIP { SWAP + /* [ nat : pair nat (list key) : bytes : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ nat : nat : pair nat (list key) : bytes : list (option signature) + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + ASSERT_CMPEQ ; + DIP { SWAP + /* [ list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ pair nat (list key) : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + UNPAIR @threshold @keys + /* [ nat : list key : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DIP { PUSH @valid + nat + 0 + /* [ nat : list key : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + SWAP + /* [ list key : nat : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + ITER { DIP { SWAP + /* [ list (option signature) : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ key : list (option signature) : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + SWAP + /* [ list (option signature) : key : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + IF_CONS + { IF_SOME + { SWAP + /* [ list (option signature) : signature : key : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DIP { SWAP + /* [ key : signature : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DIP 2 + { DUP 2 + /* [ bytes : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ key : signature : bytes : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + { DUP 3 + /* [ bytes : key : signature : bytes : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DIP { CHECK_SIGNATURE + /* [ bool : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ bytes : bool : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + SWAP + /* [ bool : bytes : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + IF { DROP + /* [ nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + { FAILWITH /* [] */ } } ; + PUSH nat + 1 + /* [ nat : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + ADD @valid + /* [ nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ list (option signature) : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + { SWAP + /* [ key : list (option signature) : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DROP + /* [ list (option signature) : nat : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } } + { FAIL } ; + SWAP + /* [ nat : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ nat : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ } + /* [ nat : nat : list (option signature) : bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + ASSERT_CMPLE ; + DROP + /* [ bytes + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DROP + /* [ or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + DIP { UNPAIR + /* [ nat : pair nat (list key) ] */ ; + PUSH nat 1 + /* [ nat : nat : pair nat (list key) ] */ ; + ADD @new_counter + /* [ nat : pair nat (list key) ] */ ; + PAIR + /* [ pair nat nat (list key) ] */ } + /* [ or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + NIL operation + /* [ list operation + : or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : pair nat nat (list key) ] */ ; + SWAP + /* [ or (pair mutez (contract unit)) (or (option key_hash) (pair nat (list key))) + : list operation : pair nat nat (list key) ] */ ; + IF_LEFT + { UNPAIR + /* [ mutez : contract unit : list operation : pair nat nat (list key) ] */ ; + UNIT + /* [ unit : mutez : contract unit : list operation : pair nat nat (list key) ] */ ; + TRANSFER_TOKENS + /* [ operation : list operation : pair nat nat (list key) ] */ ; + CONS + /* [ list operation : pair nat nat (list key) ] */ } + { IF_LEFT + { SET_DELEGATE + /* [ operation : list operation : pair nat nat (list key) ] */ ; + CONS + /* [ list operation : pair nat nat (list key) ] */ } + { DIP { SWAP + /* [ pair nat nat (list key) : list operation ] */ ; + CAR + /* [ nat : list operation ] */ } + /* [ pair nat (list key) : nat : list operation ] */ ; + SWAP + /* [ nat : pair nat (list key) : list operation ] */ ; + PAIR + /* [ pair nat nat (list key) : list operation ] */ ; + SWAP + /* [ list operation : pair nat nat (list key) ] */ } } ; + PAIR + /* [ pair (list operation) nat nat (list key) ] */ } } +Well typed (Gas remaining: 1039983.350 units remaining) michelson_test_scripts/mini_scenarios/lockup.tz +{ parameter unit ; + storage (pair timestamp (pair mutez address)) ; + code { CDR + /* [ pair timestamp mutez address ] */ ; + DUP + /* [ pair timestamp mutez address : pair timestamp mutez address ] */ ; + CAR + /* [ timestamp : pair timestamp mutez address ] */ ; + NOW + /* [ timestamp : timestamp : pair timestamp mutez address ] */ ; + CMPLT ; + IF { FAIL } { /* [ pair timestamp mutez address ] */ } ; + DUP + /* [ pair timestamp mutez address : pair timestamp mutez address ] */ ; + CDR + /* [ pair mutez address : pair timestamp mutez address ] */ ; + DUP + /* [ pair mutez address : pair mutez address : pair timestamp mutez address ] */ ; + CAR + /* [ mutez : pair mutez address : pair timestamp mutez address ] */ ; + DIP { CDR /* [ address : pair timestamp mutez address ] */ } + /* [ mutez : address : pair timestamp mutez address ] */ ; + DIP { CONTRACT unit + /* [ option (contract unit) : pair timestamp mutez address ] */ ; + ASSERT_SOME } + /* [ mutez : contract unit : pair timestamp mutez address ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair timestamp mutez address ] */ ; + TRANSFER_TOKENS + /* [ operation : pair timestamp mutez address ] */ ; + NIL operation + /* [ list operation : operation : pair timestamp mutez address ] */ ; + SWAP + /* [ operation : list operation : pair timestamp mutez address ] */ ; + CONS + /* [ list operation : pair timestamp mutez address ] */ ; + PAIR + /* [ pair (list operation) timestamp mutez address ] */ } } +Well typed (Gas remaining: 1039992.719 units remaining) michelson_test_scripts/mini_scenarios/loop.tz +{ parameter int ; + storage unit ; + code { CAR + /* [ int ] */ ; + DUP + /* [ int : int ] */ ; + GT + /* [ bool : int ] */ ; + LOOP { PUSH int 1 + /* [ int : int ] */ ; + SWAP + /* [ int : int ] */ ; + SUB + /* [ int ] */ ; + DUP + /* [ int : int ] */ ; + GT + /* [ bool : int ] */ } + /* [ int ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039751.719 units remaining) michelson_test_scripts/mini_scenarios/lqt_fa12.mligo.tz +{ parameter + (or (or (or (pair %approve (address %spender) (nat %value)) + (pair %getAllowance + (pair %request (address %owner) (address %spender)) + (contract %callback nat))) + (or (pair %getBalance (address %owner) (contract %callback nat)) + (pair %getTotalSupply (unit %request) (contract %callback nat)))) + (or (pair %mintOrBurn (int %quantity) (address %target)) + (pair %transfer (address %from) (pair (address %to) (nat %value))))) ; + storage + (pair (big_map %tokens address nat) + (pair (big_map %allowances (pair (address %owner) (address %spender)) nat) + (pair (address %admin) (nat %total_supply)))) ; + code { DUP + /* [ pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + CDR + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + PUSH mutez + 0 + /* [ mutez + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + AMOUNT + /* [ mutez : mutez + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + COMPARE + /* [ int + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + NEQ + /* [ bool + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + IF { PUSH string + "DontSendTez" + /* [ string + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } ; + SWAP + /* [ pair (or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat))) + (big_map address nat) + (big_map (pair address address) nat) + address + nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ or (or (or (pair address nat) (pair (pair address address) (contract nat))) + (or (pair address (contract nat)) (pair unit (contract nat)))) + (or (pair int address) (pair address address nat)) + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_LEFT + { IF_LEFT + { IF_LEFT + { SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address nat ] */ ; + DUG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address nat : pair address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 2 + /* [ pair address nat : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SENDER + /* [ address : address : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH nat + 0 + /* [ nat : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair address nat : nat : pair address address + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address nat : pair address nat : nat : pair address address + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ pair address nat : nat : pair address address + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : nat : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GT + /* [ bool : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH nat + 0 + /* [ nat : bool : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ big_map (pair address address) nat : nat : bool : pair address address + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ big_map (pair address address) nat : big_map (pair address address) nat + : nat : bool : pair address address : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ big_map (pair address address) nat : nat : bool : pair address address + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair address address : big_map (pair address address) nat : nat : bool + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address : pair address address + : big_map (pair address address) nat : nat : bool + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ pair address address : big_map (pair address address) nat : nat : bool + : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : nat : bool : pair address address + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : nat : bool : pair address address + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : nat : bool : pair address address + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + COMPARE + /* [ int : bool : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GT + /* [ bool : bool : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + AND + /* [ bool : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { PUSH string + "UnsafeAllowanceChange" + /* [ string : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 3 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address address : big_map (pair address address) nat + : pair address nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address address : big_map (pair address address) nat + : pair address nat ] */ ; + DUG 4 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat + : pair address address : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : pair address address + : big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ big_map (pair address address) nat : pair address nat + : pair address address : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair address nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH nat + 0 + /* [ nat : nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ nat : nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ nat : nat : nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 2 + /* [ nat : nat : nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + EQ + /* [ bool : nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { DROP + /* [ big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NONE nat + /* [ option nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { SOME + /* [ option nat : big_map (pair address address) nat : pair address nat + : pair address address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 3 + /* [ pair address address : option nat : big_map (pair address address) nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + UPDATE + /* [ big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map address nat + : pair (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (list operation) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } + { SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (pair address address) (contract nat) ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (pair address address) (contract nat) ] */ ; + DIG 2 + /* [ pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NIL operation + /* [ list operation : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair (pair address address) (contract nat) : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair (pair address address) (contract nat) + : pair (pair address address) (contract nat) : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 2 + /* [ pair (pair address address) (contract nat) : list operation + : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ contract nat : list operation : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH mutez + 0 + /* [ mutez : contract nat : list operation + : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : mutez : contract nat : list operation + : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : mutez + : contract nat : list operation : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map (pair address address) nat : mutez : contract nat : list operation + : pair (pair address address) (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair (pair address address) (contract nat) + : big_map (pair address address) nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ pair address address : big_map (pair address address) nat : mutez + : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + TRANSFER_TOKENS + /* [ operation : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CONS + /* [ list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (list operation) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } } + { IF_LEFT + { SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address (contract nat) ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address (contract nat) ] */ ; + DIG 2 + /* [ pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NIL operation + /* [ list operation : pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair address (contract nat) : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address (contract nat) : pair address (contract nat) : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 2 + /* [ pair address (contract nat) : list operation : pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ contract nat : list operation : pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH mutez + 0 + /* [ mutez : contract nat : list operation : pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : mutez : contract nat : list operation : pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map address nat : mutez : contract nat : list operation + : pair address (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair address (contract nat) : big_map address nat : mutez : contract nat + : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : big_map address nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + TRANSFER_TOKENS + /* [ operation : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CONS + /* [ list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (list operation) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } + { SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair unit (contract nat) ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair unit (contract nat) ] */ ; + DIG 2 + /* [ pair unit (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NIL operation + /* [ list operation : pair unit (contract nat) + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair unit (contract nat) : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH mutez + 0 + /* [ mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : mutez + : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : mutez : contract nat : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + TRANSFER_TOKENS + /* [ operation : list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CONS + /* [ list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (list operation) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } } } + { IF_LEFT + { SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair int address ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair int address ] */ ; + DUG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SENDER + /* [ address : address : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NEQ + /* [ bool : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { PUSH string + "OnlyAdmin" + /* [ string : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + FAILWITH + /* [] */ } + { /* [ pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DUP + /* [ pair int address : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : int : pair int address ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : int : pair int address ] */ ; + DUG 3 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map address nat : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair int address : big_map address nat : int + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair int address : pair int address : big_map address nat : int + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ pair int address : big_map address nat : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ address : big_map address nat : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + ADD + /* [ int : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + ISNAT + /* [ option nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH string + "Cannot burn more than the target's balance." + /* [ string : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + SWAP + /* [ pair int address : nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair int address : pair int address : nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 2 + /* [ pair int address : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ int : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : int : nat : pair int address ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : int : nat : pair int address ] */ ; + DUG 4 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : int : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : int : nat + : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : int : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : int : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + ADD + /* [ int : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + ABS + /* [ nat : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : nat : nat : pair int address ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : nat : nat : pair int address ] */ ; + DUG 4 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : nat : nat : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : nat : nat + : pair int address + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map (pair address address) nat) address nat : nat : nat + : pair int address ] */ ; + CAR + /* [ big_map address nat : pair (big_map (pair address address) nat) address nat + : nat : nat : pair int address ] */ ; + PUSH nat + 0 + /* [ nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat : nat + : pair int address ] */ ; + DIG 4 + /* [ nat : nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat + : pair int address ] */ ; + DUP + /* [ nat : nat : nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat + : pair int address ] */ ; + DUG 5 + /* [ nat : nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat : nat + : pair int address ] */ ; + COMPARE + /* [ int : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat : nat + : pair int address ] */ ; + EQ + /* [ bool : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat : nat + : pair int address ] */ ; + IF { DIG 3 + /* [ nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat + : pair int address ] */ ; + DROP + /* [ big_map address nat : pair (big_map (pair address address) nat) address nat + : nat : pair int address ] */ ; + NONE nat + /* [ option nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat + : pair int address ] */ } + { DIG 3 + /* [ nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat + : pair int address ] */ ; + SOME + /* [ option nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat + : pair int address ] */ } ; + DIG 4 + /* [ pair int address : option nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat ] */ ; + CDR + /* [ address : option nat : big_map address nat + : pair (big_map (pair address address) nat) address nat : nat ] */ ; + UPDATE + /* [ big_map address nat : pair (big_map (pair address address) nat) address nat + : nat ] */ ; + PAIR + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : nat ] */ ; + DUG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address nat ] */ ; + DUG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map address nat + : pair (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (list operation) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } + { SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address address nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address address nat ] */ ; + DUG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat : pair address address nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat : pair address address nat ] */ ; + DUG 3 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair address address nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ pair address address nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SENDER + /* [ address : address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + EQ + /* [ bool : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { SWAP + /* [ big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { SENDER + /* [ address : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair address address nat : address : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : address + : big_map address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ pair address address nat : address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ pair address address nat : pair address address : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : pair address address + : big_map address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ pair address address nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 3 + /* [ big_map (pair address address) nat : nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ big_map (pair address address) nat : big_map (pair address address) nat + : nat : pair address address : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ big_map (pair address address) nat : nat : pair address address + : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair address address : big_map (pair address address) nat : nat + : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address : pair address address + : big_map (pair address address) nat : nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ pair address address : big_map (pair address address) nat : nat + : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + SUB + /* [ int : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + ISNAT + /* [ option nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH string + "NotEnoughAllowance" + /* [ string : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat : pair address address : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 3 + /* [ big_map (pair address address) nat : nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH nat + 0 + /* [ nat : big_map (pair address address) nat : nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ nat : nat : big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ nat : nat : nat : big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ nat : nat : big_map (pair address address) nat : nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : big_map (pair address address) nat : nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + EQ + /* [ bool : big_map (pair address address) nat : nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { SWAP + /* [ nat : big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DROP + /* [ big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NONE nat + /* [ option nat : big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { SWAP + /* [ nat : big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SOME + /* [ option nat : big_map (pair address address) nat : pair address address + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 2 + /* [ pair address address : option nat : big_map (pair address address) nat + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + UPDATE + /* [ big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 2 + /* [ pair address address nat : big_map (pair address address) nat + : big_map address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat + : big_map (pair address address) nat : big_map address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ pair address address nat : big_map (pair address address) nat + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ big_map address nat : big_map address nat : nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ big_map address nat : nat : big_map (pair address address) nat + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair address address nat : big_map address nat : nat + : big_map (pair address address) nat : big_map address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : big_map address nat + : nat : big_map (pair address address) nat : big_map address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 5 + /* [ pair address address nat : big_map address nat : nat + : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : big_map address nat : nat : big_map (pair address address) nat + : big_map address nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + SUB + /* [ int : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + ISNAT + /* [ option nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH string + "NotEnoughBalance" + /* [ string : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + FAILWITH + /* [] */ } + { /* [ nat : big_map (pair address address) nat : big_map address nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 2 + /* [ big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH nat + 0 + /* [ nat : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ nat : nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ nat : nat : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + EQ + /* [ bool : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { SWAP + /* [ nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DROP + /* [ big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NONE nat + /* [ option nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { SWAP + /* [ nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SOME + /* [ option nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 3 + /* [ pair address address nat : option nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : option nat + : big_map address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 4 + /* [ pair address address nat : option nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : option nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + UPDATE + /* [ big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair address address nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ pair address address nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ big_map address nat : big_map address nat : nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 2 + /* [ big_map address nat : nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 4 + /* [ pair address address nat : big_map address nat : nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ pair address address nat : pair address address nat : big_map address nat + : nat : big_map address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 5 + /* [ pair address address nat : big_map address nat : nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : big_map address nat : nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : big_map address nat : nat : big_map address nat + : big_map (pair address address) nat : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + GET + /* [ option nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF_NONE + { PUSH nat + 0 + /* [ nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { /* [ nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + ADD + /* [ nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PUSH nat + 0 + /* [ nat : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUP + /* [ nat : nat : nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DUG 3 + /* [ nat : nat : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + COMPARE + /* [ int : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + EQ + /* [ bool : big_map address nat : nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + IF { SWAP + /* [ nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DROP + /* [ big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NONE nat + /* [ option nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } + { SWAP + /* [ nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SOME + /* [ option nat : big_map address nat : big_map (pair address address) nat + : pair address address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ } ; + DIG 3 + /* [ pair address address nat : option nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CDR + /* [ pair address nat : option nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ address : option nat : big_map address nat + : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + UPDATE + /* [ big_map address nat : big_map (pair address address) nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + DIG 2 + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map address nat : big_map (pair address address) nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat : big_map address nat + : big_map (pair address address) nat ] */ ; + SWAP + /* [ big_map address nat : pair (big_map (pair address address) nat) address nat + : big_map (pair address address) nat ] */ ; + PAIR + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat ] */ ; + DUP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat ] */ ; + CDR + /* [ pair (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat ] */ ; + CDR + /* [ pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat + : big_map (pair address address) nat ] */ ; + DIG 2 + /* [ big_map (pair address address) nat : pair address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (big_map (pair address address) nat) address nat + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + SWAP + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat + : pair (big_map (pair address address) nat) address nat ] */ ; + CAR + /* [ big_map address nat + : pair (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + NIL operation + /* [ list operation + : pair (big_map address nat) (big_map (pair address address) nat) address nat ] */ ; + PAIR + /* [ pair (list operation) + (big_map address nat) + (big_map (pair address address) nat) + address + nat ] */ } } } } +Well typed (Gas remaining: 1039928.626 units remaining) michelson_test_scripts/mini_scenarios/multiple_en2.tz +{ parameter unit ; + storage (option address) ; + code { SENDER + /* [ address : pair unit (option address) ] */ ; + SELF + /* [ contract unit : address : pair unit (option address) ] */ ; + ADDRESS + /* [ address : address : pair unit (option address) ] */ ; + { /* [ pair (or (or nat nat) unit) int ] */ + COMPARE + /* [ mutez : mutez : pair (or (or nat nat) unit) int ] */ ; + EQ + /* [ bool : pair unit (option address) ] */ ; + IF { CDR + /* [ option address ] */ ; + { /* [ mutez : mutez : pair (or (or nat nat) unit) int ] */ + IF_NONE + { { /* [ pair (or (or nat nat) unit) int ] */ UNIT /* [ unit ] */ ; FAILWITH /* [] */ } } + { /* [ pair (or (or nat nat) unit) int ] */ } + /* [ bool : pair (or (or nat nat) unit) int ] */ } ; + DIP { NIL operation + /* [ pair (or (or nat nat) unit) int : pair (or (or nat nat) unit) int ] */ + /* [ list operation ] */ } + /* [] */ ; + DUP + /* [ or (or nat nat) unit : pair (or (or nat nat) unit) int ] */ ; + CONTRACT %add unit + /* [ or (or nat nat) unit : int ] */ ; + { /* [ pair (or (or nat nat) unit) int ] */ + IF_NONE + { /* [ address : list operation ] */ } + { { UNIT /* [ int ] */ ; FAILWITH /* [] */ } } } ; + DUP + /* [ int : nat ] */ ; + CONTRACT %fact nat + /* [ int ] */ ; + { /* [ unit : int ] */ + IF_NONE { /* [] */ } { { UNIT /* [ list operation : int ] */ ; FAILWITH /* [] */ } } + /* [] */ } ; + DUP + /* [ pair (list operation) int ] */ ; + CONTRACT %add nat + /* [ option (contract nat) : address : list operation ] */ ; + { IF_NONE + { { UNIT /* [ unit : address : list operation ] */ ; FAILWITH /* [] */ } } + { /* [ contract nat : address : list operation ] */ } } ; + PUSH mutez 0 + /* [ mutez : contract nat : address : list operation ] */ ; + PUSH nat 12 + /* [ nat : mutez : contract nat : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT unit + /* [ option (contract unit) : address : list operation ] */ ; + { IF_NONE + { { UNIT /* [ unit : address : list operation ] */ ; FAILWITH /* [] */ } } + { /* [ contract unit : address : list operation ] */ } } ; + PUSH mutez 0 + /* [ mutez : contract unit : address : list operation ] */ ; + PUSH unit Unit + /* [ unit : mutez : contract unit : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %sub nat + /* [ option (contract nat) : address : list operation ] */ ; + { IF_NONE + { { UNIT /* [ unit : address : list operation ] */ ; FAILWITH /* [] */ } } + { /* [ contract nat : address : list operation ] */ } } ; + PUSH mutez 0 + /* [ mutez : contract nat : address : list operation ] */ ; + PUSH nat 3 + /* [ nat : mutez : contract nat : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %add nat + /* [ option (contract nat) : address : list operation ] */ ; + { IF_NONE + { { UNIT /* [ unit : address : list operation ] */ ; FAILWITH /* [] */ } } + { /* [ contract nat : address : list operation ] */ } } ; + PUSH mutez 0 + /* [ mutez : contract nat : address : list operation ] */ ; + PUSH nat 5 + /* [ nat : mutez : contract nat : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DROP + /* [ list operation ] */ ; + DIP { NONE address /* [ option address ] */ } + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } + { CAR + /* [ unit ] */ ; + DUP + /* [ unit : unit ] */ ; + DIP { DIP { PUSH int 0 + /* [ int ] */ ; + PUSH mutez 0 + /* [ mutez : int ] */ ; + NONE key_hash + /* [ option key_hash : mutez : int ] */ } + /* [ unit : option key_hash : mutez : int ] */ ; + DROP + /* [ option key_hash : mutez : int ] */ ; + CREATE_CONTRACT + { parameter (or (or (nat %add) (nat %sub)) (unit %default)) ; + storage int ; + code { AMOUNT ; + PUSH mutez 0 ; + { { COMPARE ; EQ } ; IF {} { { UNIT ; FAILWITH } } } ; + { { DUP ; CAR ; DIP { CDR } } } ; + IF_LEFT + { IF_LEFT { ADD } { SWAP ; SUB } } + { DROP ; DROP ; PUSH int 0 } ; + NIL operation ; + PAIR } } + /* [ operation : address ] */ } + /* [ unit : operation : address ] */ ; + DIP { SELF + /* [ contract unit : operation : address ] */ ; + PUSH mutez 0 + /* [ mutez : contract unit : operation : address ] */ } + /* [ unit : mutez : contract unit : operation : address ] */ ; + TRANSFER_TOKENS + /* [ operation : operation : address ] */ ; + NIL operation + /* [ list operation : operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : operation : address ] */ ; + CONS + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + DIP { SOME /* [ option address ] */ } + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } } } +Well typed (Gas remaining: 1039931.343 units remaining) michelson_test_scripts/mini_scenarios/multiple_entrypoints_counter.tz +{ parameter unit ; + storage (option address) ; + code { SENDER + /* [ address : pair unit (option address) ] */ ; + SELF + /* [ contract unit : address : pair unit (option address) ] */ ; + ADDRESS + /* [ address : address : pair unit (option address) ] */ ; + IFCMPEQ + { CDR + /* [ option address ] */ ; + ASSERT_SOME + /* [ int : pair (or (or nat nat) unit) int ] */ ; + DIP { /* [ pair (or (or nat nat) unit) int ] */ NIL operation /* [ list operation ] */ } + /* [] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %add + unit + /* [ int ] */ + /* [ option (contract unit) : address : list operation ] */ ; + ASSERT_NONE ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %fact + nat + /* [ list operation : int ] */ + /* [ option (contract nat) : address : list operation ] */ ; + ASSERT_NONE ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %add nat + /* [ option (contract nat) : address : list operation ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract nat : address : list operation ] */ ; + PUSH nat 12 + /* [ nat : mutez : contract nat : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT unit + /* [ option (contract unit) : address : list operation ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract unit : address : list operation ] */ ; + PUSH unit Unit + /* [ unit : mutez : contract unit : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %sub nat + /* [ option (contract nat) : address : list operation ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract nat : address : list operation ] */ ; + PUSH nat 3 + /* [ nat : mutez : contract nat : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DUP + /* [ address : address : list operation ] */ ; + CONTRACT %add nat + /* [ option (contract nat) : address : list operation ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract nat : address : list operation ] */ ; + PUSH nat 5 + /* [ nat : mutez : contract nat : address : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : address : list operation ] */ ; + SWAP + /* [ address : operation : list operation ] */ ; + DIP { CONS /* [ list operation ] */ } + /* [ address : list operation ] */ ; + DROP + /* [ list operation ] */ ; + DIP { NONE address /* [ option address ] */ } + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } + { CAR + /* [ unit ] */ ; + DUP + /* [ unit : unit ] */ ; + DIP { DIP { PUSH int 0 + /* [ int ] */ ; + PUSH mutez 0 + /* [ mutez : int ] */ ; + NONE key_hash + /* [ option key_hash : mutez : int ] */ } + /* [ unit : option key_hash : mutez : int ] */ ; + DROP + /* [ option key_hash : mutez : int ] */ ; + CREATE_CONTRACT + { parameter (or (or (nat %add) (nat %sub)) (unit %default)) ; + storage int ; + code { AMOUNT ; + PUSH mutez 0 ; + ASSERT_CMPEQ ; + UNPAIR ; + IF_LEFT + { IF_LEFT { ADD } { SWAP ; SUB } } + { DROP ; DROP ; PUSH int 0 } ; + NIL operation ; + PAIR } } + /* [ operation : address ] */ } + /* [ unit : operation : address ] */ ; + DIP { SELF + /* [ contract unit : operation : address ] */ ; + PUSH mutez 0 + /* [ mutez : contract unit : operation : address ] */ } + /* [ unit : mutez : contract unit : operation : address ] */ ; + TRANSFER_TOKENS + /* [ operation : operation : address ] */ ; + NIL operation + /* [ list operation : operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : operation : address ] */ ; + CONS + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + DIP { SOME /* [ option address ] */ } + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } + /* [ mutez : pair (or (or nat nat) unit) int ] */ } } +Well typed (Gas remaining: 1039997.849 units remaining) michelson_test_scripts/mini_scenarios/multisig_dest_entrypoint.tz +{ parameter (or (unit %a) (string %b)) ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.849 units remaining) michelson_test_scripts/mini_scenarios/multisig_dest_entrypoint_arg.tz +{ parameter (or (int %a) (string %b)) ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/mini_scenarios/nat_id.tz +{ parameter nat ; + storage nat ; + code { CAR + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/mini_scenarios/noop_bytes.tz +{ parameter bytes ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.446 units remaining) michelson_test_scripts/mini_scenarios/originate_contract.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [ unit ] */ ; + UNIT + /* [ list operation : unit ] */ ; + AMOUNT + /* [ mutez : unit ] */ ; + NONE key_hash + /* [ pair (list operation) unit ] */ ; + CREATE_CONTRACT + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + /* [ operation : address ] */ ; + DIP { DROP + /* [] */ ; + PUSH unit Unit + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ } + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039942.668 units remaining) michelson_test_scripts/mini_scenarios/parameterized_multisig.tz +{ storage (pair bool (pair (map nat (pair bool bool)) (pair key key))) ; + parameter (or nat (pair signature nat)) ; + code { DUP + /* [ pair (or nat (pair signature nat)) bool (map nat (pair bool bool)) key key + : pair (or nat (pair signature nat)) bool (map nat (pair bool bool)) key key ] */ ; + CAR + /* [ or nat (pair signature nat) + : pair (or nat (pair signature nat)) bool (map nat (pair bool bool)) key key ] */ ; + DIP { CDDR } + /* [ or nat (pair signature nat) : pair (map nat (pair bool bool)) key key ] */ ; + IF_LEFT + { DIP { DUP + /* [ pair (map nat (pair bool bool)) key key + : pair (map nat (pair bool bool)) key key ] */ ; + CAR + /* [ map nat (pair bool bool) : pair (map nat (pair bool bool)) key key ] */ } + /* [ nat : map nat (pair bool bool) : pair (map nat (pair bool bool)) key key ] */ ; + GET + /* [ option (pair bool bool) : pair (map nat (pair bool bool)) key key ] */ ; + IF_NONE + { PUSH bool False /* [ bool : pair (map nat (pair bool bool)) key key ] */ } + { DUP + /* [ pair bool bool : pair bool bool : pair (map nat (pair bool bool)) key key ] */ ; + CAR + /* [ bool : pair bool bool : pair (map nat (pair bool bool)) key key ] */ ; + DIP { CDR /* [ bool : pair (map nat (pair bool bool)) key key ] */ } + /* [ bool : bool : pair (map nat (pair bool bool)) key key ] */ ; + AND + /* [ bool : pair (map nat (pair bool bool)) key key ] */ } ; + PAIR + /* [ pair bool (map nat (pair bool bool)) key key ] */ } + { DUP + /* [ pair signature nat : pair signature nat + : pair (map nat (pair bool bool)) key key ] */ ; + CAR + /* [ signature : pair signature nat : pair (map nat (pair bool bool)) key key ] */ ; + DIP { CDR + /* [ nat : pair (map nat (pair bool bool)) key key ] */ ; + DUP + /* [ nat : nat : pair (map nat (pair bool bool)) key key ] */ ; + PACK + /* [ bytes : nat : pair (map nat (pair bool bool)) key key ] */ ; + BLAKE2B + /* [ bytes : nat : pair (map nat (pair bool bool)) key key ] */ } + /* [ signature : bytes : nat : pair (map nat (pair bool bool)) key key ] */ ; + PAIR + /* [ pair signature bytes : nat : pair (map nat (pair bool bool)) key key ] */ ; + SWAP + /* [ nat : pair signature bytes : pair (map nat (pair bool bool)) key key ] */ ; + DIP { DIP { DUP + /* [ pair (map nat (pair bool bool)) key key + : pair (map nat (pair bool bool)) key key ] */ ; + CDR + /* [ pair key key : pair (map nat (pair bool bool)) key key ] */ ; + DIP { CAR /* [ map nat (pair bool bool) ] */ } + /* [ pair key key : map nat (pair bool bool) ] */ ; + DUP + /* [ pair key key : pair key key : map nat (pair bool bool) ] */ } + /* [ pair signature bytes : pair key key : pair key key + : map nat (pair bool bool) ] */ ; + SWAP + /* [ pair key key : pair signature bytes : pair key key + : map nat (pair bool bool) ] */ ; + CAR + /* [ key : pair signature bytes : pair key key : map nat (pair bool bool) ] */ ; + DIP { DUP + /* [ pair signature bytes : pair signature bytes : pair key key + : map nat (pair bool bool) ] */ ; + UNPAIR + /* [ signature : bytes : pair signature bytes : pair key key + : map nat (pair bool bool) ] */ } + /* [ key : signature : bytes : pair signature bytes : pair key key + : map nat (pair bool bool) ] */ ; + CHECK_SIGNATURE + /* [ bool : pair signature bytes : pair key key : map nat (pair bool bool) ] */ } + /* [ nat : bool : pair signature bytes : pair key key + : map nat (pair bool bool) ] */ ; + SWAP + /* [ bool : nat : pair signature bytes : pair key key + : map nat (pair bool bool) ] */ ; + IF { DIP { DROP + /* [ pair key key : map nat (pair bool bool) ] */ ; + SWAP + /* [ map nat (pair bool bool) : pair key key ] */ ; + DUP + /* [ map nat (pair bool bool) : map nat (pair bool bool) : pair key key ] */ } + /* [ nat : map nat (pair bool bool) : map nat (pair bool bool) : pair key key ] */ ; + DUP + /* [ nat : nat : map nat (pair bool bool) : map nat (pair bool bool) + : pair key key ] */ ; + DIP { GET + /* [ option (pair bool bool) : map nat (pair bool bool) : pair key key ] */ ; + IF_NONE + { PUSH (pair bool bool) + (Pair False False) + /* [ pair bool bool : map nat (pair bool bool) : pair key key ] */ } + { /* [ pair bool bool : map nat (pair bool bool) : pair key key ] */ } ; + CDR + /* [ bool : map nat (pair bool bool) : pair key key ] */ ; + PUSH bool True + /* [ bool : bool : map nat (pair bool bool) : pair key key ] */ ; + PAIR + /* [ pair bool bool : map nat (pair bool bool) : pair key key ] */ ; + SOME + /* [ option (pair bool bool) : map nat (pair bool bool) : pair key key ] */ } + /* [ nat : option (pair bool bool) : map nat (pair bool bool) : pair key key ] */ } + { DIP { DIP { DUP + /* [ pair key key : pair key key : map nat (pair bool bool) ] */ ; + CDR + /* [ key : pair key key : map nat (pair bool bool) ] */ } + /* [ pair signature bytes : key : pair key key : map nat (pair bool bool) ] */ ; + SWAP + /* [ key : pair signature bytes : pair key key : map nat (pair bool bool) ] */ ; + DIP { UNPAIR /* [ signature : bytes : pair key key : map nat (pair bool bool) ] */ } + /* [ key : signature : bytes : pair key key : map nat (pair bool bool) ] */ ; + CHECK_SIGNATURE + /* [ bool : pair key key : map nat (pair bool bool) ] */ } + /* [ nat : bool : pair key key : map nat (pair bool bool) ] */ ; + SWAP + /* [ bool : nat : pair key key : map nat (pair bool bool) ] */ ; + IF { DUP + /* [ nat : nat : pair key key : map nat (pair bool bool) ] */ ; + DIP { DIP { SWAP + /* [ map nat (pair bool bool) : pair key key ] */ ; + DUP + /* [ map nat (pair bool bool) : map nat (pair bool bool) : pair key key ] */ } + /* [ nat : map nat (pair bool bool) : map nat (pair bool bool) : pair key key ] */ ; + GET + /* [ option (pair bool bool) : map nat (pair bool bool) : pair key key ] */ } + /* [ nat : option (pair bool bool) : map nat (pair bool bool) : pair key key ] */ ; + SWAP + /* [ option (pair bool bool) : nat : map nat (pair bool bool) : pair key key ] */ ; + IF_NONE + { PUSH (pair bool bool) + (Pair False False) + /* [ pair bool bool : nat : map nat (pair bool bool) : pair key key ] */ } + { /* [ pair bool bool : nat : map nat (pair bool bool) : pair key key ] */ } ; + CAR + /* [ bool : nat : map nat (pair bool bool) : pair key key ] */ ; + PUSH bool True + /* [ bool : bool : nat : map nat (pair bool bool) : pair key key ] */ ; + SWAP + /* [ bool : bool : nat : map nat (pair bool bool) : pair key key ] */ ; + PAIR + /* [ pair bool bool : nat : map nat (pair bool bool) : pair key key ] */ ; + SOME + /* [ option (pair bool bool) : nat : map nat (pair bool bool) : pair key key ] */ ; + SWAP + /* [ nat : option (pair bool bool) : map nat (pair bool bool) : pair key key ] */ } + { FAIL } } ; + UPDATE + /* [ map nat (pair bool bool) : pair key key ] */ ; + PAIR + /* [ pair (map nat (pair bool bool)) key key ] */ ; + PUSH bool False + /* [ bool : pair (map nat (pair bool bool)) key key ] */ ; + PAIR + /* [ pair bool (map nat (pair bool bool)) key key ] */ } ; + NIL operation + /* [ list operation : pair bool (map nat (pair bool bool)) key key ] */ ; + PAIR + /* [ pair (list operation) bool (map nat (pair bool bool)) key key ] */ } } +Well typed (Gas remaining: 1039980.814 units remaining) michelson_test_scripts/mini_scenarios/parsable_contract.tz +{ parameter int ; + storage (map int address) ; + code { UNPAIR + /* [ int : map int address ] */ ; + PUSH int 0 + /* [ int : int : map int address ] */ ; + SWAP + /* [ int : int : map int address ] */ ; + DUP + /* [ int : int : int : map int address ] */ ; + DUG 2 + /* [ int : int : int : map int address ] */ ; + COMPARE + /* [ int : int : map int address ] */ ; + GT + /* [ bool : int : map int address ] */ ; + IF { SWAP + /* [ map int address : int ] */ ; + SENDER + /* [ address : map int address : int ] */ ; + DIG 2 + /* [ int : address : map int address ] */ ; + SWAP + /* [ address : int : map int address ] */ ; + SOME + /* [ option address : int : map int address ] */ ; + SWAP + /* [ int : option address : map int address ] */ ; + UPDATE + /* [ map int address ] */ } + { SWAP + /* [ map int address : int ] */ ; + DROP + /* [ int ] */ ; + PUSH int 0 + /* [ int : int ] */ ; + SWAP + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + LT + /* [ bool ] */ ; + IF { PUSH string "NEGATIVE_INT" /* [ string ] */ ; FAILWITH /* [] */ } + { PUSH unit Unit + /* [ unit ] */ ; + LEFT (map int address) + /* [ or unit (map int address) ] */ ; + LOOP_LEFT + { DROP + /* [] */ ; + PUSH unit Unit + /* [ unit ] */ ; + LEFT (map int address) + /* [ or unit (map int address) ] */ } + /* [ map int address ] */ } } ; + NIL operation + /* [ list operation : map int address ] */ ; + PAIR + /* [ pair (list operation) (map int address) ] */ } } +Well typed (Gas remaining: 1039997.247 units remaining) michelson_test_scripts/mini_scenarios/receive_tickets_in_big_map.tz +{ parameter (big_map int (ticket string)) ; + storage (big_map int (ticket string)) ; + code { CAR + /* [ big_map int (ticket string) ] */ ; + NIL operation + /* [ list operation : big_map int (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (big_map int (ticket string)) ] */ } } +Well typed (Gas remaining: 1039990.816 units remaining) michelson_test_scripts/mini_scenarios/replay.tz +{ parameter unit ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + SOURCE + /* [ address : list operation : unit ] */ ; + CONTRACT unit + /* [ option (contract unit) : list operation : unit ] */ ; + ASSERT_SOME ; + PUSH mutez 1 + /* [ mutez : contract unit : list operation : unit ] */ ; + UNIT + /* [ unit : mutez : contract unit : list operation : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : list operation : unit ] */ ; + DUP + /* [ operation : operation : list operation : unit ] */ ; + DIP { CONS /* [ list operation : unit ] */ } + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039979.048 units remaining) michelson_test_scripts/mini_scenarios/reveal_signed_preimage.tz +{ parameter (pair bytes signature) ; + storage (pair bytes key) ; + code { DUP + /* [ pair (pair bytes signature) bytes key + : pair (pair bytes signature) bytes key ] */ ; + UNPAIR + /* [ pair bytes signature : pair bytes key + : pair (pair bytes signature) bytes key ] */ ; + CAR + /* [ bytes : pair bytes key : pair (pair bytes signature) bytes key ] */ ; + SHA256 + /* [ bytes : pair bytes key : pair (pair bytes signature) bytes key ] */ ; + DIP { CAR /* [ bytes : pair (pair bytes signature) bytes key ] */ } + /* [ bytes : bytes : pair (pair bytes signature) bytes key ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (pair bytes signature) bytes key + : pair (pair bytes signature) bytes key ] */ ; + UNPAIR + /* [ pair bytes signature : pair bytes key + : pair (pair bytes signature) bytes key ] */ ; + SWAP + /* [ pair bytes key : pair bytes signature + : pair (pair bytes signature) bytes key ] */ ; + DIP { UNPAIR + /* [ bytes : signature : pair (pair bytes signature) bytes key ] */ ; + SWAP + /* [ signature : bytes : pair (pair bytes signature) bytes key ] */ } + /* [ pair bytes key : signature : bytes + : pair (pair bytes signature) bytes key ] */ ; + CDR + /* [ key : signature : bytes : pair (pair bytes signature) bytes key ] */ ; + CHECK_SIGNATURE + /* [ bool : pair (pair bytes signature) bytes key ] */ ; + ASSERT ; + CDR + /* [ pair bytes key ] */ ; + DUP + /* [ pair bytes key : pair bytes key ] */ ; + CDR + /* [ key : pair bytes key ] */ ; + HASH_KEY + /* [ key_hash : pair bytes key ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : pair bytes key ] */ ; + BALANCE + /* [ mutez : contract unit : pair bytes key ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair bytes key ] */ ; + TRANSFER_TOKENS + /* [ operation : pair bytes key ] */ ; + NIL operation + /* [ list operation : operation : pair bytes key ] */ ; + SWAP + /* [ operation : list operation : pair bytes key ] */ ; + CONS + /* [ list operation : pair bytes key ] */ ; + PAIR + /* [ pair (list operation) bytes key ] */ } } +Well typed (Gas remaining: 1039994.499 units remaining) michelson_test_scripts/mini_scenarios/sc_rollup_forward.tz +{ parameter (pair bytes (contract bytes)) ; + storage unit ; + code { UNPAIR + /* [ pair bytes (contract bytes) : unit ] */ ; + DIP { NIL operation /* [ list operation : unit ] */ } + /* [ pair bytes (contract bytes) : list operation : unit ] */ ; + UNPAIR + /* [ bytes : contract bytes : list operation : unit ] */ ; + DIP { PUSH mutez 0 /* [ mutez : contract bytes : list operation : unit ] */ } + /* [ bytes : mutez : contract bytes : list operation : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039990.991 units remaining) michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz +{ parameter (pair (pair bytes nat) (contract (ticket bytes))) ; + storage unit ; + code { UNPAIR + /* [ pair (pair bytes nat) (contract (ticket bytes)) : unit ] */ ; + UNPAIR + /* [ pair bytes nat : contract (ticket bytes) : unit ] */ ; + UNPAIR + /* [ bytes : nat : contract (ticket bytes) : unit ] */ ; + TICKET + /* [ option (ticket bytes) : contract (ticket bytes) : unit ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : ticket bytes : contract (ticket bytes) : unit ] */ ; + SWAP + /* [ ticket bytes : mutez : contract (ticket bytes) : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039992.902 units remaining) michelson_test_scripts/mini_scenarios/self_address_receiver.tz +{ parameter (lambda unit address) ; + storage unit ; + code { UNPAIR + /* [ lambda unit address : unit ] */ ; + UNIT + /* [ unit : lambda unit address : unit ] */ ; + EXEC + /* [ address : unit ] */ ; + SELF_ADDRESS + /* [ address : address : unit ] */ ; + ASSERT_CMPEQ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.501 units remaining) michelson_test_scripts/mini_scenarios/self_address_sender.tz +{ parameter (contract (lambda unit address)) ; + storage unit ; + code { CAR + /* [ contract (lambda unit address) ] */ ; + BALANCE + /* [ mutez : contract (lambda unit address) ] */ ; + LAMBDA + unit + address + { DROP /* [] */ ; SELF_ADDRESS /* [ address ] */ } + /* [ lambda unit address : mutez : contract (lambda unit address) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + DIP { UNIT /* [ unit ] */ ; NIL operation /* [ list operation : unit ] */ } + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039986.349 units remaining) michelson_test_scripts/mini_scenarios/send_ticket_list_016.tz +{ parameter address ; + storage unit ; + code { CAR + /* [ address ] */ ; + CONTRACT (list (ticket string)) + /* [ option (contract (list (ticket string))) ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract (list (ticket string)) ] */ ; + NIL (ticket string) + /* [ list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + PUSH nat + 1 + /* [ nat : list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + PUSH string + "Ticket" + /* [ string : nat : list (ticket string) : mutez + : contract (list (ticket string)) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) : mutez + : contract (list (ticket string)) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039981.327 units remaining) michelson_test_scripts/mini_scenarios/send_ticket_list_multiple_016.tz +{ parameter address ; + storage unit ; + code { CAR + /* [ address ] */ ; + CONTRACT (list (ticket string)) + /* [ option (contract (list (ticket string))) ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract (list (ticket string)) ] */ ; + NIL (ticket string) + /* [ list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + PUSH nat + 1 + /* [ nat : list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + PUSH string + "Ticket" + /* [ string : nat : list (ticket string) : mutez + : contract (list (ticket string)) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) : mutez + : contract (list (ticket string)) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + PUSH nat + 1 + /* [ nat : list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + PUSH string + "Ticket2" + /* [ string : nat : list (ticket string) : mutez + : contract (list (ticket string)) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) : mutez + : contract (list (ticket string)) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039981.564 units remaining) michelson_test_scripts/mini_scenarios/send_tickets_from_storage_016.tz +{ parameter (or (unit %mint) (contract %send (list (ticket string)))) ; + storage (list (ticket string)) ; + code { UNPAIR + /* [ or unit (contract (list (ticket string))) : list (ticket string) ] */ ; + IF_LEFT + { DROP + /* [ list (ticket string) ] */ ; + PUSH nat 1 + /* [ nat : list (ticket string) ] */ ; + PUSH string "Ticket" + /* [ string : nat : list (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) ] */ ; + PUSH nat 1 + /* [ nat : list (ticket string) ] */ ; + PUSH string "Ticket2" + /* [ string : nat : list (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { PUSH mutez 0 + /* [ mutez : contract (list (ticket string)) : list (ticket string) ] */ ; + DIG 2 + /* [ list (ticket string) : mutez : contract (list (ticket string)) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL (ticket string) + /* [ list (ticket string) : operation ] */ ; + NIL operation + /* [ list operation : list (ticket string) : operation ] */ ; + DIG 2 + /* [ operation : list operation : list (ticket string) ] */ ; + CONS + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } } } +Well typed (Gas remaining: 1039968.364 units remaining) michelson_test_scripts/mini_scenarios/send_tickets_in_big_map_015.tz +{ parameter address ; + storage unit ; + code { CAR + /* [ address ] */ ; + CONTRACT + (big_map int (ticket string)) + /* [ option (contract (big_map int (ticket string))) ] */ ; + IF_NONE + { PUSH string "Contract of type `big_map(ticket(string))` not found" + /* [ string ] */ ; + FAILWITH + /* [] */ } + { EMPTY_BIG_MAP + int + (ticket string) + /* [ big_map int (ticket string) : contract (big_map int (ticket string)) ] */ ; + PUSH int + 100 + /* [ int : big_map int (ticket string) + : contract (big_map int (ticket string)) ] */ ; + SWAP + /* [ big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + PAIR + /* [ pair (big_map int (ticket string)) int + : contract (big_map int (ticket string)) ] */ ; + LEFT (big_map int (ticket string)) + /* [ or (pair (big_map int (ticket string)) int) (big_map int (ticket string)) + : contract (big_map int (ticket string)) ] */ ; + LOOP_LEFT + { UNPAIR + /* [ big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + SWAP + /* [ int : big_map int (ticket string) + : contract (big_map int (ticket string)) ] */ ; + DUP + /* [ int : int : big_map int (ticket string) + : contract (big_map int (ticket string)) ] */ ; + DUG 2 + /* [ int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + PUSH int + 0 + /* [ int : int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + COMPARE + /* [ int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + LT + /* [ bool : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + IF { PUSH int + 1 + /* [ int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + DUP 3 + /* [ int : int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + SUB + /* [ int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + SWAP + /* [ big_map int (ticket string) : int : int + : contract (big_map int (ticket string)) ] */ ; + PUSH nat + 1 + /* [ nat : big_map int (ticket string) : int : int + : contract (big_map int (ticket string)) ] */ ; + PUSH string + "BLUE" + /* [ string : nat : big_map int (ticket string) : int : int + : contract (big_map int (ticket string)) ] */ ; + TICKET + /* [ option (ticket string) : big_map int (ticket string) : int : int + : contract (big_map int (ticket string)) ] */ ; + ASSERT_SOME ; + DIG 3 + /* [ int : ticket string : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + SWAP + /* [ ticket string : int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + SOME + /* [ option (ticket string) : int : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + SWAP + /* [ int : option (ticket string) : big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + UPDATE + /* [ big_map int (ticket string) : int + : contract (big_map int (ticket string)) ] */ ; + PAIR + /* [ pair (big_map int (ticket string)) int + : contract (big_map int (ticket string)) ] */ ; + LEFT (big_map int (ticket string)) + /* [ or (pair (big_map int (ticket string)) int) (big_map int (ticket string)) + : contract (big_map int (ticket string)) ] */ } + { SWAP + /* [ int : big_map int (ticket string) + : contract (big_map int (ticket string)) ] */ ; + DROP + /* [ big_map int (ticket string) : contract (big_map int (ticket string)) ] */ ; + RIGHT + (pair (big_map int (ticket string)) int) + /* [ or (pair (big_map int (ticket string)) int) (big_map int (ticket string)) + : contract (big_map int (ticket string)) ] */ } } + /* [ big_map int (ticket string) : contract (big_map int (ticket string)) ] */ ; + SWAP + /* [ contract (big_map int (ticket string)) : big_map int (ticket string) ] */ ; + PUSH mutez + 0 + /* [ mutez : contract (big_map int (ticket string)) + : big_map int (ticket string) ] */ ; + DIG 2 + /* [ big_map int (ticket string) : mutez + : contract (big_map int (ticket string)) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + PUSH unit Unit + /* [ unit : operation ] */ ; + NIL operation + /* [ list operation : unit : operation ] */ ; + DIG 2 + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } } +Well typed (Gas remaining: 1039982.309 units remaining) michelson_test_scripts/mini_scenarios/smart_rollup_mint_and_deposit_ticket_016.tz +{ parameter + (pair (pair (contract %rollup (pair string (ticket string))) (string %rollup_account)) + (pair (nat %ticket_amount) (string %ticket_content))) ; + storage unit ; + code { CAR + /* [ pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + DUP + /* [ pair (pair (contract (pair string (ticket string))) string) nat string + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + CAR + /* [ pair (contract (pair string (ticket string))) string + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + CAR + /* [ contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + PUSH mutez + 0 + /* [ mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + DUP 3 + /* [ pair (pair (contract (pair string (ticket string))) string) nat string + : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + CDR + /* [ pair nat string : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + CAR + /* [ nat : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + DUP 4 + /* [ pair (pair (contract (pair string (ticket string))) string) nat string + : nat : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + CDR + /* [ pair nat string : nat : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + CDR + /* [ string : nat : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + TICKET + /* [ option (ticket string) : mutez : contract (pair string (ticket string)) + : pair (pair (contract (pair string (ticket string))) string) nat string ] */ ; + ASSERT_SOME ; + DIG 3 + /* [ pair (pair (contract (pair string (ticket string))) string) nat string + : ticket string : mutez : contract (pair string (ticket string)) ] */ ; + CAR + /* [ pair (contract (pair string (ticket string))) string : ticket string + : mutez : contract (pair string (ticket string)) ] */ ; + CDR + /* [ string : ticket string : mutez : contract (pair string (ticket string)) ] */ ; + PAIR + /* [ pair string (ticket string) : mutez + : contract (pair string (ticket string)) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + PUSH unit Unit + /* [ unit : operation ] */ ; + NIL operation + /* [ list operation : unit : operation ] */ ; + DIG 2 + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.969 units remaining) michelson_test_scripts/mini_scenarios/smart_rollup_receive_tickets_016.tz +{ parameter (or (unit %burn_all_tickets) (ticket %receive_tickets string)) ; + storage (list (ticket string)) ; + code { UNPAIR + /* [ or unit (ticket string) : list (ticket string) ] */ ; + IF_LEFT + { DROP 2 + /* [] */ ; + NIL (ticket string) + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { CONS + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } } } +Well typed (Gas remaining: 1039997.447 units remaining) michelson_test_scripts/mini_scenarios/str_id.tz +{ parameter string ; + storage (option string) ; + code { CAR + /* [ string ] */ ; + SOME + /* [ option string ] */ ; + NIL operation + /* [ list operation : option string ] */ ; + PAIR + /* [ pair (list operation) (option string) ] */ } } +Well typed (Gas remaining: 1039974.138 units remaining) michelson_test_scripts/mini_scenarios/ticket_builder_fungible.tz +{ parameter + (or (ticket %burn unit) + (pair %mint (contract %destination (ticket unit)) (nat %amount))) ; + storage address ; + code { AMOUNT + /* [ mutez + : pair (or (ticket unit) (pair (contract (ticket unit)) nat)) address ] */ ; + PUSH mutez + 0 + /* [ mutez : mutez + : pair (or (ticket unit) (pair (contract (ticket unit)) nat)) address ] */ ; + ASSERT_CMPEQ ; + UNPAIR + /* [ or (ticket unit) (pair (contract (ticket unit)) nat) : address ] */ ; + IF_LEFT + { READ_TICKET + /* [ pair address unit nat : ticket unit : address ] */ ; + CAR + /* [ address : ticket unit : address ] */ ; + SELF_ADDRESS + /* [ address : address : ticket unit : address ] */ ; + ASSERT_CMPEQ ; + DROP + /* [ address ] */ ; + NIL operation + /* [ list operation : address ] */ } + { DUP @manager 2 + /* [ address : pair (contract (ticket unit)) nat : address ] */ ; + SENDER + /* [ address : address : pair (contract (ticket unit)) nat : address ] */ ; + ASSERT_CMPEQ ; + UNPAIR + /* [ contract (ticket unit) : nat : address ] */ ; + SWAP + /* [ nat : contract (ticket unit) : address ] */ ; + UNIT + /* [ unit : nat : contract (ticket unit) : address ] */ ; + TICKET + /* [ option (ticket unit) : contract (ticket unit) : address ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : ticket unit : contract (ticket unit) : address ] */ ; + SWAP + /* [ ticket unit : mutez : contract (ticket unit) : address ] */ ; + TRANSFER_TOKENS + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ } ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039971.719 units remaining) michelson_test_scripts/mini_scenarios/ticket_builder_non_fungible.tz +{ parameter (or (ticket %burn nat) (contract %mint_destination (ticket nat))) ; + storage (pair (address %manager) (nat %counter)) ; + code { AMOUNT + /* [ mutez : pair (or (ticket nat) (contract (ticket nat))) address nat ] */ ; + PUSH mutez + 0 + /* [ mutez : mutez + : pair (or (ticket nat) (contract (ticket nat))) address nat ] */ ; + ASSERT_CMPEQ ; + UNPAIR 3 + /* [ or (ticket nat) (contract (ticket nat)) : address : nat ] */ ; + IF_LEFT + { READ_TICKET + /* [ pair address nat nat : ticket nat : address : nat ] */ ; + CAR + /* [ address : ticket nat : address : nat ] */ ; + SELF_ADDRESS + /* [ address : address : ticket nat : address : nat ] */ ; + ASSERT_CMPEQ ; + DROP + /* [ address : nat ] */ ; + NIL operation + /* [ list operation : address : nat ] */ } + { DUP @manager 2 + /* [ address : contract (ticket nat) : address : nat ] */ ; + SENDER + /* [ address : address : contract (ticket nat) : address : nat ] */ ; + ASSERT_CMPEQ ; + PUSH @amount nat 1 + /* [ nat : contract (ticket nat) : address : nat ] */ ; + DUP @counter 4 + /* [ nat : nat : contract (ticket nat) : address : nat ] */ ; + TICKET + /* [ option (ticket nat) : contract (ticket nat) : address : nat ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : ticket nat : contract (ticket nat) : address : nat ] */ ; + SWAP + /* [ ticket nat : mutez : contract (ticket nat) : address : nat ] */ ; + TRANSFER_TOKENS + /* [ operation : address : nat ] */ ; + NIL operation + /* [ list operation : operation : address : nat ] */ ; + SWAP + /* [ operation : list operation : address : nat ] */ ; + CONS + /* [ list operation : address : nat ] */ ; + DIP 2 + { PUSH nat 1 /* [ nat : nat ] */ ; ADD /* [ nat ] */ } + /* [ list operation : address : nat ] */ } ; + PAIR 3 + /* [ pair (list operation) address nat ] */ } } +Well typed (Gas remaining: 1039938.422 units remaining) michelson_test_scripts/mini_scenarios/ticket_wallet_fungible.tz +{ parameter + (or (ticket %receive unit) + (pair %send (contract %destination (ticket unit)) (nat %amount) (address %ticketer))) ; + storage (pair (address %manager) (big_map %tickets address (ticket unit))) ; + code { AMOUNT + /* [ mutez + : pair (or (ticket unit) (pair (contract (ticket unit)) nat address)) + address + (big_map address (ticket unit)) ] */ ; + PUSH mutez + 0 + /* [ mutez : mutez + : pair (or (ticket unit) (pair (contract (ticket unit)) nat address)) + address + (big_map address (ticket unit)) ] */ ; + ASSERT_CMPEQ ; + UNPAIR + 3 + /* [ or (ticket unit) (pair (contract (ticket unit)) nat address) : address + : big_map address (ticket unit) ] */ ; + IF_LEFT + { READ_TICKET + /* [ pair address unit nat : ticket unit : address + : big_map address (ticket unit) ] */ ; + CAR @ticketer + /* [ address : ticket unit : address : big_map address (ticket unit) ] */ ; + DUP + /* [ address : address : ticket unit : address : big_map address (ticket unit) ] */ ; + DIG 4 + /* [ big_map address (ticket unit) : address : address : ticket unit : address ] */ ; + NONE (ticket unit) + /* [ option (ticket unit) : big_map address (ticket unit) : address : address + : ticket unit : address ] */ ; + DIG 2 + /* [ address : option (ticket unit) : big_map address (ticket unit) : address + : ticket unit : address ] */ ; + GET_AND_UPDATE + /* [ option (ticket unit) : big_map address (ticket unit) : address + : ticket unit : address ] */ ; + IF_SOME + { DIG 3 + /* [ ticket unit : ticket unit : big_map address (ticket unit) : address + : address ] */ ; + PAIR + /* [ pair (ticket unit) (ticket unit) : big_map address (ticket unit) : address + : address ] */ ; + JOIN_TICKETS + /* [ option (ticket unit) : big_map address (ticket unit) : address : address ] */ ; + ASSERT_SOME } + { DIG 2 + /* [ ticket unit : big_map address (ticket unit) : address : address ] */ } ; + SOME + /* [ option (ticket unit) : big_map address (ticket unit) : address : address ] */ ; + DIG 2 + /* [ address : option (ticket unit) : big_map address (ticket unit) : address ] */ ; + GET_AND_UPDATE + /* [ option (ticket unit) : big_map address (ticket unit) : address ] */ ; + ASSERT_NONE ; + SWAP + /* [ address : big_map address (ticket unit) ] */ ; + PAIR + /* [ pair address (big_map address (ticket unit)) ] */ ; + NIL operation + /* [ list operation : pair address (big_map address (ticket unit)) ] */ } + { DUP @manager + 2 + /* [ address : pair (contract (ticket unit)) nat address : address + : big_map address (ticket unit) ] */ ; + SENDER + /* [ address : address : pair (contract (ticket unit)) nat address : address + : big_map address (ticket unit) ] */ ; + ASSERT_CMPEQ ; + UNPAIR + 3 + /* [ contract (ticket unit) : nat : address : address + : big_map address (ticket unit) ] */ ; + DIG 4 + /* [ big_map address (ticket unit) : contract (ticket unit) : nat : address + : address ] */ ; + NONE (ticket unit) + /* [ option (ticket unit) : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + DUP @ticketer + 5 + /* [ address : option (ticket unit) : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + GET_AND_UPDATE + /* [ option (ticket unit) : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + ASSERT_SOME ; + READ_TICKET + /* [ pair address unit nat : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + GET @total_amount + 4 + /* [ nat : ticket unit : big_map address (ticket unit) : contract (ticket unit) + : nat : address : address ] */ ; + DUP @amount + 5 + /* [ nat : nat : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + SWAP + /* [ nat : nat : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + SUB + /* [ int : ticket unit : big_map address (ticket unit) : contract (ticket unit) + : nat : address : address ] */ ; + DUP + /* [ int : int : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + EQ + /* [ bool : int : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + IF { DROP + /* [ ticket unit : big_map address (ticket unit) : contract (ticket unit) : nat + : address : address ] */ ; + DIG 3 + /* [ nat : ticket unit : big_map address (ticket unit) : contract (ticket unit) + : address : address ] */ ; + DROP + /* [ ticket unit : big_map address (ticket unit) : contract (ticket unit) + : address : address ] */ ; + DIG 3 + /* [ address : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : address ] */ ; + DROP + /* [ ticket unit : big_map address (ticket unit) : contract (ticket unit) + : address ] */ ; + DUG 3 + /* [ big_map address (ticket unit) : contract (ticket unit) : address + : ticket unit ] */ } + { ISNAT + /* [ option nat : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : nat : address : address ] */ ; + ASSERT_SOME @remaining_amount ; + DIG 4 + /* [ nat : nat : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : address : address ] */ ; + PAIR + /* [ pair nat nat : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : address : address ] */ ; + SWAP + /* [ ticket unit : pair nat nat : big_map address (ticket unit) + : contract (ticket unit) : address : address ] */ ; + SPLIT_TICKET + /* [ option (pair (ticket unit) (ticket unit)) : big_map address (ticket unit) + : contract (ticket unit) : address : address ] */ ; + ASSERT_SOME ; + UNPAIR @to_send @to_keep + /* [ ticket unit : ticket unit : big_map address (ticket unit) + : contract (ticket unit) : address : address ] */ ; + DUG 5 + /* [ ticket unit : big_map address (ticket unit) : contract (ticket unit) + : address : address : ticket unit ] */ ; + SOME + /* [ option (ticket unit) : big_map address (ticket unit) + : contract (ticket unit) : address : address : ticket unit ] */ ; + DIG 3 + /* [ address : option (ticket unit) : big_map address (ticket unit) + : contract (ticket unit) : address : ticket unit ] */ ; + GET_AND_UPDATE + /* [ option (ticket unit) : big_map address (ticket unit) + : contract (ticket unit) : address : ticket unit ] */ ; + ASSERT_NONE } ; + DIG 2 + /* [ address : big_map address (ticket unit) : contract (ticket unit) + : ticket unit ] */ ; + PAIR + /* [ pair address (big_map address (ticket unit)) : contract (ticket unit) + : ticket unit ] */ ; + SWAP + /* [ contract (ticket unit) : pair address (big_map address (ticket unit)) + : ticket unit ] */ ; + PUSH mutez + 0 + /* [ mutez : contract (ticket unit) + : pair address (big_map address (ticket unit)) : ticket unit ] */ ; + DIG 3 + /* [ ticket unit : mutez : contract (ticket unit) + : pair address (big_map address (ticket unit)) ] */ ; + TRANSFER_TOKENS + /* [ operation : pair address (big_map address (ticket unit)) ] */ ; + NIL operation + /* [ list operation : operation : pair address (big_map address (ticket unit)) ] */ ; + SWAP + /* [ operation : list operation : pair address (big_map address (ticket unit)) ] */ ; + CONS + /* [ list operation : pair address (big_map address (ticket unit)) ] */ } ; + PAIR + /* [ pair (list operation) address (big_map address (ticket unit)) ] */ } } +Well typed (Gas remaining: 1039960.699 units remaining) michelson_test_scripts/mini_scenarios/ticket_wallet_non_fungible.tz +{ parameter + (or (ticket %receive nat) + (pair %send (contract %destination (ticket nat)) (address %ticketer) (nat %id))) ; + storage (pair (address %manager) (big_map %tickets (pair address nat) (ticket nat))) ; + code { AMOUNT + /* [ mutez + : pair (or (ticket nat) (pair (contract (ticket nat)) address nat)) + address + (big_map (pair address nat) (ticket nat)) ] */ ; + PUSH mutez + 0 + /* [ mutez : mutez + : pair (or (ticket nat) (pair (contract (ticket nat)) address nat)) + address + (big_map (pair address nat) (ticket nat)) ] */ ; + ASSERT_CMPEQ ; + UNPAIR + 3 + /* [ or (ticket nat) (pair (contract (ticket nat)) address nat) : address + : big_map (pair address nat) (ticket nat) ] */ ; + IF_LEFT + { READ_TICKET + /* [ pair address nat nat : ticket nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + CAST (pair (address %ticketer) (nat %id) (nat %amount)) + /* [ pair address nat nat : ticket nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + UNPAIR + 3 + /* [ address : nat : nat : ticket nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + DIG 2 + /* [ nat : address : nat : ticket nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + PUSH nat + 1 + /* [ nat : nat : address : nat : ticket nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + ASSERT_CMPEQ ; + PAIR + /* [ pair address nat : ticket nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + DIP { SOME + /* [ option (ticket nat) : address : big_map (pair address nat) (ticket nat) ] */ ; + DIP { SWAP /* [ big_map (pair address nat) (ticket nat) : address ] */ } + /* [ option (ticket nat) : big_map (pair address nat) (ticket nat) : address ] */ } + /* [ pair address nat : option (ticket nat) + : big_map (pair address nat) (ticket nat) : address ] */ ; + GET_AND_UPDATE + /* [ option (ticket nat) : big_map (pair address nat) (ticket nat) : address ] */ ; + ASSERT_NONE ; + SWAP + /* [ address : big_map (pair address nat) (ticket nat) ] */ ; + PAIR + /* [ pair address (big_map (pair address nat) (ticket nat)) ] */ ; + NIL operation + /* [ list operation : pair address (big_map (pair address nat) (ticket nat)) ] */ } + { DUP @manager + 2 + /* [ address : pair (contract (ticket nat)) address nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + SENDER + /* [ address : address : pair (contract (ticket nat)) address nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + ASSERT_CMPEQ ; + UNPAIR + /* [ contract (ticket nat) : pair address nat : address + : big_map (pair address nat) (ticket nat) ] */ ; + DIG 3 + /* [ big_map (pair address nat) (ticket nat) : contract (ticket nat) + : pair address nat : address ] */ ; + NONE (ticket nat) + /* [ option (ticket nat) : big_map (pair address nat) (ticket nat) + : contract (ticket nat) : pair address nat : address ] */ ; + DIG 3 + /* [ pair address nat : option (ticket nat) + : big_map (pair address nat) (ticket nat) : contract (ticket nat) : address ] */ ; + GET_AND_UPDATE + /* [ option (ticket nat) : big_map (pair address nat) (ticket nat) + : contract (ticket nat) : address ] */ ; + ASSERT_SOME ; + SWAP + /* [ big_map (pair address nat) (ticket nat) : ticket nat + : contract (ticket nat) : address ] */ ; + DIG 3 + /* [ address : big_map (pair address nat) (ticket nat) : ticket nat + : contract (ticket nat) ] */ ; + PAIR + /* [ pair address (big_map (pair address nat) (ticket nat)) : ticket nat + : contract (ticket nat) ] */ ; + DUG 2 + /* [ ticket nat : contract (ticket nat) + : pair address (big_map (pair address nat) (ticket nat)) ] */ ; + PUSH mutez + 0 + /* [ mutez : ticket nat : contract (ticket nat) + : pair address (big_map (pair address nat) (ticket nat)) ] */ ; + SWAP + /* [ ticket nat : mutez : contract (ticket nat) + : pair address (big_map (pair address nat) (ticket nat)) ] */ ; + TRANSFER_TOKENS + /* [ operation : pair address (big_map (pair address nat) (ticket nat)) ] */ ; + NIL operation + /* [ list operation : operation + : pair address (big_map (pair address nat) (ticket nat)) ] */ ; + SWAP + /* [ operation : list operation + : pair address (big_map (pair address nat) (ticket nat)) ] */ ; + CONS + /* [ list operation : pair address (big_map (pair address nat) (ticket nat)) ] */ } ; + PAIR + /* [ pair (list operation) address (big_map (pair address nat) (ticket nat)) ] */ } } +Well typed (Gas remaining: 1039993.131 units remaining) michelson_test_scripts/mini_scenarios/tickets_015.tz +{ parameter unit ; + storage (list (ticket string)) ; + code { CDR + /* [ list (ticket string) ] */ ; + PUSH nat 1 + /* [ nat : list (ticket string) ] */ ; + PUSH string "Red" + /* [ string : nat : list (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : list (ticket string) ] */ ; + ASSERT_SOME ; + CONS + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } } +Well typed (Gas remaining: 1039986.391 units remaining) michelson_test_scripts/mini_scenarios/tickets_bag_016.tz +{ parameter (or (ticket %save string) (address %send)) ; + storage (list (ticket string)) ; + code { UNPAIR + /* [ or (ticket string) address : list (ticket string) ] */ ; + IF_LEFT + { CONS + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { SWAP + /* [ list (ticket string) : address ] */ ; + IF_CONS + { DIG 2 + /* [ address : ticket string : list (ticket string) ] */ ; + CONTRACT %ticket + (ticket string) + /* [ option (contract (ticket string)) : ticket string : list (ticket string) ] */ ; + ASSERT_SOME ; + PUSH mutez + 0 + /* [ mutez : contract (ticket string) : ticket string : list (ticket string) ] */ ; + DIG 2 + /* [ ticket string : mutez : contract (ticket string) : list (ticket string) ] */ ; + TRANSFER_TOKENS + /* [ operation : list (ticket string) ] */ ; + NIL operation + /* [ list operation : operation : list (ticket string) ] */ ; + SWAP + /* [ operation : list operation : list (ticket string) ] */ ; + CONS + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { PUSH string "no ticket to send" /* [ string : address ] */ ; FAILWITH /* [] */ } } } } +Well typed (Gas remaining: 1039986.391 units remaining) michelson_test_scripts/mini_scenarios/tickets_bag_implicit_016.tz +{ parameter (or (ticket %save string) (address %send)) ; + storage (list (ticket string)) ; + code { UNPAIR + /* [ or (ticket string) address : list (ticket string) ] */ ; + IF_LEFT + { CONS + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { SWAP + /* [ list (ticket string) : address ] */ ; + IF_CONS + { DIG 2 + /* [ address : ticket string : list (ticket string) ] */ ; + CONTRACT + (ticket string) + /* [ option (contract (ticket string)) : ticket string : list (ticket string) ] */ ; + ASSERT_SOME ; + PUSH mutez + 0 + /* [ mutez : contract (ticket string) : ticket string : list (ticket string) ] */ ; + DIG 2 + /* [ ticket string : mutez : contract (ticket string) : list (ticket string) ] */ ; + TRANSFER_TOKENS + /* [ operation : list (ticket string) ] */ ; + NIL operation + /* [ list operation : operation : list (ticket string) ] */ ; + SWAP + /* [ operation : list operation : list (ticket string) ] */ ; + CONS + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } + { PUSH string "no ticket to send" /* [ string : address ] */ ; FAILWITH /* [] */ } } } } +Well typed (Gas remaining: 1039997.932 units remaining) michelson_test_scripts/mini_scenarios/tickets_blackhole_016.tz +{ parameter (ticket %ticket string) ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039961.303 units remaining) michelson_test_scripts/mini_scenarios/tickets_create_and_send_015.tz +{ parameter (pair address address) ; + storage (list (ticket string)) ; + code { CAR + /* [ pair address address ] */ ; + UNPAIR + /* [ address : address ] */ ; + PUSH nat 1 + /* [ nat : address : address ] */ ; + PUSH string "red" + /* [ string : nat : address : address ] */ ; + TICKET + /* [ option (ticket string) : address : address ] */ ; + ASSERT_SOME ; + PUSH nat 1 + /* [ nat : ticket string : address : address ] */ ; + PUSH string "green" + /* [ string : nat : ticket string : address : address ] */ ; + TICKET + /* [ option (ticket string) : ticket string : address : address ] */ ; + ASSERT_SOME ; + PUSH nat 1 + /* [ nat : ticket string : ticket string : address : address ] */ ; + PUSH string + "green" + /* [ string : nat : ticket string : ticket string : address : address ] */ ; + TICKET + /* [ option (ticket string) : ticket string : ticket string : address + : address ] */ ; + ASSERT_SOME ; + PUSH nat + 1 + /* [ nat : ticket string : ticket string : ticket string : address : address ] */ ; + PUSH string + "blue" + /* [ string : nat : ticket string : ticket string : ticket string : address + : address ] */ ; + TICKET + /* [ option (ticket string) : ticket string : ticket string : ticket string + : address : address ] */ ; + ASSERT_SOME ; + PUSH nat + 1 + /* [ nat : ticket string : ticket string : ticket string : ticket string + : address : address ] */ ; + PUSH string + "blue" + /* [ string : nat : ticket string : ticket string : ticket string + : ticket string : address : address ] */ ; + TICKET + /* [ option (ticket string) : ticket string : ticket string : ticket string + : ticket string : address : address ] */ ; + ASSERT_SOME ; + DIG 5 + /* [ address : ticket string : ticket string : ticket string : ticket string + : ticket string : address ] */ ; + CONTRACT + (pair (pair (ticket string) (ticket string)) address) + /* [ option (contract (pair (pair (ticket string) (ticket string)) address)) + : ticket string : ticket string : ticket string : ticket string + : ticket string : address ] */ ; + IF_NONE + { PUSH string + "option is None" + /* [ string : ticket string : ticket string : ticket string : ticket string + : ticket string : address ] */ ; + FAILWITH + /* [] */ } + { /* [ contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string : ticket string + : ticket string : address ] */ } ; + PUSH mutez + 0 + /* [ mutez : contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string : ticket string + : ticket string : address ] */ ; + DIG 7 + /* [ address : mutez + : contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string : ticket string + : ticket string ] */ ; + DIG 3 + /* [ ticket string : address : mutez + : contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string : ticket string ] */ ; + DIG 4 + /* [ ticket string : ticket string : address : mutez + : contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string ] */ ; + PAIR + /* [ pair (ticket string) (ticket string) : address : mutez + : contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string ] */ ; + PAIR + /* [ pair (pair (ticket string) (ticket string)) address : mutez + : contract (pair (pair (ticket string) (ticket string)) address) + : ticket string : ticket string : ticket string ] */ ; + TRANSFER_TOKENS + /* [ operation : ticket string : ticket string : ticket string ] */ ; + NIL (ticket string) + /* [ list (ticket string) : operation : ticket string : ticket string + : ticket string ] */ ; + DIG 2 + /* [ ticket string : list (ticket string) : operation : ticket string + : ticket string ] */ ; + CONS + /* [ list (ticket string) : operation : ticket string : ticket string ] */ ; + DIG 2 + /* [ ticket string : list (ticket string) : operation : ticket string ] */ ; + CONS + /* [ list (ticket string) : operation : ticket string ] */ ; + DIG 2 + /* [ ticket string : list (ticket string) : operation ] */ ; + CONS + /* [ list (ticket string) : operation ] */ ; + NIL operation + /* [ list operation : list (ticket string) : operation ] */ ; + DIG 2 + /* [ operation : list operation : list (ticket string) ] */ ; + CONS + /* [ list operation : list (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } } +Well typed (Gas remaining: 1039997.849 units remaining) michelson_test_scripts/mini_scenarios/tickets_list_blackhole_016.tz +{ parameter (list (ticket string)) ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039985.858 units remaining) michelson_test_scripts/mini_scenarios/tickets_mint_and_store_complex_param.tz +{ parameter + (or (pair %mint_and_send string nat (contract (ticket string))) + (pair %store int (list (pair string (ticket string))))) ; + storage (list (ticket string)) ; + code { UNPAIR + /* [ or (pair string nat (contract (ticket string))) + (pair int (list (pair string (ticket string)))) : list (ticket string) ] */ ; + IF_LEFT + { UNPAIR 3 + /* [ string : nat : contract (ticket string) : list (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : contract (ticket string) : list (ticket string) ] */ ; + IF_NONE + { PUSH string + "option is None" + /* [ string : contract (ticket string) : list (ticket string) ] */ ; + FAILWITH + /* [] */ } + { /* [ ticket string : contract (ticket string) : list (ticket string) ] */ } ; + SWAP + /* [ contract (ticket string) : ticket string : list (ticket string) ] */ ; + PUSH mutez + 0 + /* [ mutez : contract (ticket string) : ticket string : list (ticket string) ] */ ; + DIG 2 + /* [ ticket string : mutez : contract (ticket string) : list (ticket string) ] */ ; + TRANSFER_TOKENS + /* [ operation : list (ticket string) ] */ ; + SWAP + /* [ list (ticket string) : operation ] */ ; + NIL operation + /* [ list operation : list (ticket string) : operation ] */ ; + DIG 2 + /* [ operation : list operation : list (ticket string) ] */ ; + CONS + /* [ list operation : list (ticket string) ] */ } + { CDR + /* [ list (pair string (ticket string)) : list (ticket string) ] */ ; + ITER { CDR + /* [ ticket string : list (ticket string) ] */ ; + CONS + /* [ list (ticket string) ] */ } + /* [ list (ticket string) ] */ ; + NIL operation + /* [ list operation : list (ticket string) ] */ } ; + PAIR + /* [ pair (list operation) (list (ticket string)) ] */ } } +Well typed (Gas remaining: 1039997.186 units remaining) michelson_test_scripts/mini_scenarios/tickets_receive_and_store.tz +{ parameter (ticket string) ; + storage (option (ticket string)) ; + code { CAR + /* [ ticket string ] */ ; + SOME + /* [ option (ticket string) ] */ ; + NIL operation + /* [ list operation : option (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (option (ticket string)) ] */ } } +Well typed (Gas remaining: 1039987.529 units remaining) michelson_test_scripts/mini_scenarios/tickets_send_016.tz +{ parameter (pair address nat) ; + storage unit ; + code { CAR + /* [ pair address nat ] */ ; + UNPAIR + /* [ address : nat ] */ ; + CONTRACT (ticket string) + /* [ option (contract (ticket string)) : nat ] */ ; + IF_NONE + { PUSH string "Contract not found" /* [ string : nat ] */ ; FAILWITH /* [] */ } + { PUSH mutez 0 + /* [ mutez : contract (ticket string) : nat ] */ ; + DIG 2 + /* [ nat : mutez : contract (ticket string) ] */ ; + PUSH string "Ticket" + /* [ string : nat : mutez : contract (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : mutez : contract (ticket string) ] */ ; + ASSERT_SOME ; + TRANSFER_TOKENS + /* [ operation ] */ ; + PUSH unit Unit + /* [ unit : operation ] */ ; + NIL operation + /* [ list operation : unit : operation ] */ ; + DIG 2 + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } } +Well typed (Gas remaining: 1039988.096 units remaining) michelson_test_scripts/mini_scenarios/tickets_send_with_tez_016.tz +{ parameter address ; + storage unit ; + code { CAR + /* [ address ] */ ; + CONTRACT (ticket string) + /* [ option (contract (ticket string)) ] */ ; + IF_NONE + { PUSH string "Contract not found" /* [ string ] */ ; FAILWITH /* [] */ } + { PUSH mutez 1 + /* [ mutez : contract (ticket string) ] */ ; + PUSH nat 1 + /* [ nat : mutez : contract (ticket string) ] */ ; + PUSH string "Ticket" + /* [ string : nat : mutez : contract (ticket string) ] */ ; + TICKET + /* [ option (ticket string) : mutez : contract (ticket string) ] */ ; + ASSERT_SOME ; + TRANSFER_TOKENS + /* [ operation ] */ ; + PUSH unit Unit + /* [ unit : operation ] */ ; + NIL operation + /* [ list operation : unit : operation ] */ ; + DIG 2 + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } } +Well typed (Gas remaining: 1039988.829 units remaining) michelson_test_scripts/mini_scenarios/tickets_store_fst_and_rely_snd.tz +{ parameter (pair (pair (ticket string) (ticket string)) address) ; + storage (option (ticket string)) ; + code { CAR + /* [ pair (pair (ticket string) (ticket string)) address ] */ ; + UNPAIR + /* [ pair (ticket string) (ticket string) : address ] */ ; + UNPAIR + /* [ ticket string : ticket string : address ] */ ; + DIG 2 + /* [ address : ticket string : ticket string ] */ ; + CONTRACT + (ticket string) + /* [ option (contract (ticket string)) : ticket string : ticket string ] */ ; + IF_NONE + { PUSH string "option is None" + /* [ string : ticket string : ticket string ] */ ; + FAILWITH + /* [] */ } + { /* [ contract (ticket string) : ticket string : ticket string ] */ } ; + PUSH mutez + 0 + /* [ mutez : contract (ticket string) : ticket string : ticket string ] */ ; + DIG 3 + /* [ ticket string : mutez : contract (ticket string) : ticket string ] */ ; + TRANSFER_TOKENS + /* [ operation : ticket string ] */ ; + SWAP + /* [ ticket string : operation ] */ ; + SOME + /* [ option (ticket string) : operation ] */ ; + NIL operation + /* [ list operation : option (ticket string) : operation ] */ ; + DIG 2 + /* [ operation : list operation : option (ticket string) ] */ ; + CONS + /* [ list operation : option (ticket string) ] */ ; + PAIR + /* [ pair (list operation) (option (ticket string)) ] */ } } +Well typed (Gas remaining: 1039986.304 units remaining) michelson_test_scripts/mini_scenarios/tzip4_view.tz +{ parameter + (or (pair %view_const unit (contract nat)) + (pair %view_add (pair int int) (contract int))) ; + storage unit ; + code { CAR + /* [ or (pair unit (contract nat)) (pair (pair int int) (contract int)) ] */ ; + IF_LEFT + { CDR + /* [ contract nat ] */ ; + AMOUNT + /* [ mutez : contract nat ] */ ; + PUSH nat 5 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } + { UNPAIR + /* [ pair int int : contract int ] */ ; + UNPAIR + /* [ int : int : contract int ] */ ; + ADD + /* [ int : contract int ] */ ; + AMOUNT + /* [ mutez : int : contract int ] */ ; + SWAP + /* [ int : mutez : contract int ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/mini_scenarios/very_small.tz +{ parameter unit ; + storage unit ; + code { UNPAIR + /* [ unit : unit ] */ ; + DROP + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039982.522 units remaining) michelson_test_scripts/mini_scenarios/view_check_caller.tz +{ parameter address ; + storage (option address) ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + UNIT + /* [ unit : address : address ] */ ; + VIEW "calls_count" nat + /* [ option nat : address ] */ ; + IF_NONE { UNIT /* [ unit : address ] */ ; FAILWITH /* [] */ } { /* [ nat : address ] */ } ; + DIP { UNIT + /* [ unit : address ] */ ; + VIEW "last_caller" (option address) + /* [ option (option address) ] */ } + /* [ nat : option (option address) ] */ ; + PUSH nat 0 + /* [ nat : nat : option (option address) ] */ ; + IFCMPEQ + { IF_NONE + { UNIT /* [ unit ] */ ; FAILWITH /* [] */ } + { IF_NONE { /* [] */ } { UNIT /* [ unit : address ] */ ; FAILWITH /* [] */ } } ; + NONE address + /* [ option address ] */ } + { IF_NONE + { UNIT /* [ unit ] */ ; FAILWITH /* [] */ } + { IF_NONE { UNIT /* [ unit ] */ ; FAILWITH /* [] */ } { /* [ address ] */ } } ; + SOME + /* [ option address ] */ } ; + NIL operation + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } +Well typed (Gas remaining: 1039991.454 units remaining) michelson_test_scripts/mini_scenarios/view_registers_callers.tz +{ parameter unit ; + storage (list address) ; + code { CDR + /* [ list address ] */ ; + SOURCE + /* [ address : list address ] */ ; + CONS + /* [ list address ] */ ; + NIL operation + /* [ list operation : list address ] */ ; + PAIR + /* [ pair (list operation) (list address) ] */ } ; + view "calls_count" unit nat { CDR /* [ list address ] */ ; SIZE /* [ nat ] */ } ; + view "last_caller" + unit + (option address) + { CDR + /* [ list address ] */ ; + IF_CONS + { DIP { DROP /* [] */ } /* [ address ] */ ; SOME /* [ option address ] */ } + { NONE address /* [ option address ] */ } } } +Well typed (Gas remaining: 1039960.608 units remaining) michelson_test_scripts/mini_scenarios/viewable.tz +{ parameter nat ; + storage nat ; + code { CAR + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } ; + view "add_v" nat nat { UNPAIR /* [ nat : nat ] */ ; ADD /* [ nat ] */ } ; + view "mul_v" nat nat { UNPAIR /* [ nat : nat ] */ ; MUL /* [ nat ] */ } ; + view "value" unit nat { CDR /* [ nat ] */ } ; + view "loop" + int + unit + { CAR + /* [ int ] */ ; + DUP + /* [ int : int ] */ ; + EQ + /* [ bool : int ] */ ; + IF { DROP /* [] */ ; UNIT /* [ unit ] */ } + { SELF_ADDRESS + /* [ address : int ] */ ; + SWAP + /* [ int : address ] */ ; + PUSH int -1 + /* [ int : int : address ] */ ; + ADD + /* [ int : address ] */ ; + VIEW "loop" unit + /* [ option unit ] */ ; + ASSERT_SOME } } ; + view "my_external_view" + int + int + { LAMBDA + int + int + { DUP /* [ int : int ] */ ; MUL /* [ int ] */ } + /* [ lambda int int : pair int nat ] */ ; + SWAP + /* [ pair int nat : lambda int int ] */ ; + UNPAIR + /* [ int : nat : lambda int int ] */ ; + DUP 3 + /* [ lambda int int : int : nat : lambda int int ] */ ; + SWAP + /* [ int : lambda int int : nat : lambda int int ] */ ; + EXEC + /* [ int : nat : lambda int int ] */ ; + SWAP + /* [ nat : int : lambda int int ] */ ; + DIG 2 + /* [ lambda int int : nat : int ] */ ; + SWAP + /* [ nat : lambda int int : int ] */ ; + INT + /* [ int : lambda int int : int ] */ ; + EXEC + /* [ int : int ] */ ; + ADD + /* [ int ] */ ; + PUSH int 1000000 + /* [ int : int ] */ ; + NEG + /* [ int : int ] */ ; + ADD + /* [ int ] */ } ; + view "v_external" + address + int + { UNPAIR + /* [ address : nat ] */ ; + PUSH int 33 + /* [ int : address : nat ] */ ; + VIEW "my_external_view" int + /* [ option int : nat ] */ ; + IF_NONE + { DROP + /* [] */ ; + PUSH string "Call to 'my_external_view' returned None" + /* [ string ] */ ; + FAILWITH + /* [] */ } + { ADD /* [ int ] */ } } ; + view "v_entrypoint" + int + int + { LAMBDA + int + int + { DUP /* [ int : int ] */ ; MUL /* [ int ] */ } + /* [ lambda int int : pair int nat ] */ ; + SWAP + /* [ pair int nat : lambda int int ] */ ; + UNPAIR + /* [ int : nat : lambda int int ] */ ; + DUP 3 + /* [ lambda int int : int : nat : lambda int int ] */ ; + SWAP + /* [ int : lambda int int : nat : lambda int int ] */ ; + EXEC + /* [ int : nat : lambda int int ] */ ; + SWAP + /* [ nat : int : lambda int int ] */ ; + DIG 2 + /* [ lambda int int : nat : int ] */ ; + SWAP + /* [ nat : lambda int int : int ] */ ; + INT + /* [ int : lambda int int : int ] */ ; + EXEC + /* [ int : int ] */ ; + ADD + /* [ int ] */ } } +Well typed (Gas remaining: 1039947.221 units remaining) michelson_test_scripts/mini_scenarios/vote_for_delegate.tz +{ parameter (option key_hash) ; + storage + (pair (pair %mgr1 (address %addr) (option %key key_hash)) + (pair %mgr2 (address %addr) (option %key key_hash))) ; + code { DUP + /* [ pair (option key_hash) (pair address (option key_hash)) address (option key_hash) + : pair (option key_hash) (pair address (option key_hash)) address (option key_hash) ] */ ; + CDAAR %addr @% ; + SENDER + /* [ address : address + : pair (option key_hash) (pair address (option key_hash)) address (option key_hash) ] */ ; + PAIR %@ %@ + /* [ pair address address + : pair (option key_hash) (pair address (option key_hash)) address (option key_hash) ] */ ; + UNPAIR + /* [ address : address + : pair (option key_hash) (pair address (option key_hash)) address (option key_hash) ] */ ; + IFCMPEQ + { UNPAIR + /* [ option key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + SWAP + /* [ pair (pair address (option key_hash)) address (option key_hash) + : option key_hash ] */ ; + SET_CADR %key @changed_mgr1_key } + { DUP + /* [ pair (option key_hash) (pair address (option key_hash)) address (option key_hash) + : pair (option key_hash) (pair address (option key_hash)) address (option key_hash) ] */ ; + CDDAR ; + SENDER + /* [ address : address + : pair (option key_hash) (pair address (option key_hash)) address (option key_hash) ] */ ; + IFCMPEQ + { UNPAIR + /* [ option key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + SWAP + /* [ pair (pair address (option key_hash)) address (option key_hash) + : option key_hash ] */ ; + SET_CDDR %key } + { FAIL } } ; + DUP + /* [ pair (pair address (option key_hash)) address (option key_hash) + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + CADR ; + DIP { DUP + /* [ pair (pair address (option key_hash)) address (option key_hash) + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + CDDR } + /* [ option key_hash : option key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + IF_NONE + { IF_NONE + { NONE key_hash + /* [ option key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + SET_DELEGATE + /* [ operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + NIL operation + /* [ list operation : operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + SWAP + /* [ operation : list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + CONS + /* [ list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ } + { DROP + /* [ pair (pair address (option key_hash)) address (option key_hash) ] */ ; + NIL operation + /* [ list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ } } + { SWAP + /* [ option key_hash : key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + IF_SOME + { DIP { DUP + /* [ key_hash : key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ } + /* [ key_hash : key_hash : key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + IFCMPEQ + { SOME + /* [ option key_hash + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + SET_DELEGATE + /* [ operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + NIL operation + /* [ list operation : operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + SWAP + /* [ operation : list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ ; + CONS + /* [ list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ } + { DROP + /* [ pair (pair address (option key_hash)) address (option key_hash) ] */ ; + NIL operation + /* [ list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ } } + { DROP + /* [ pair (pair address (option key_hash)) address (option key_hash) ] */ ; + NIL operation + /* [ list operation + : pair (pair address (option key_hash)) address (option key_hash) ] */ } } ; + PAIR + /* [ pair (list operation) (pair address (option key_hash)) address (option key_hash) ] */ } } +Well typed (Gas remaining: 1039964.178 units remaining) michelson_test_scripts/mini_scenarios/weather_insurance.tz +{ parameter (pair (signature %signed_weather_data) (nat :rain %actual_level)) ; + storage + (pair (pair (address %under_key) (address %over_key)) + (pair (nat :rain %rain_level) (key %weather_service_key))) ; + code { DUP + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + DUP + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + CAR + /* [ pair signature nat + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + MAP_CDR + { PACK + /* [ bytes : pair signature nat + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + BLAKE2B + /* [ bytes : pair signature nat + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ } ; + SWAP + /* [ pair (pair signature nat) (pair address address) nat key + : pair signature bytes + : pair (pair signature nat) (pair address address) nat key ] */ ; + CDDDR %weather_service_key ; + DIP { UNPAIR + /* [ signature : bytes + : pair (pair signature nat) (pair address address) nat key ] */ } + /* [ key : signature : bytes + : pair (pair signature nat) (pair address address) nat key ] */ ; + CHECK_SIGNATURE @sigok + /* [ bool : pair (pair signature nat) (pair address address) nat key ] */ ; + ASSERT ; + DUP + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + DUP + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + DUP + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key ] */ ; + DIP 3 + { CDR %storage /* [ pair (pair address address) nat key ] */ } + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair (pair address address) nat key ] */ ; + DIP 2 + { CDAR } + /* [ pair (pair signature nat) (pair address address) nat key + : pair (pair signature nat) (pair address address) nat key + : pair address address : pair (pair address address) nat key ] */ ; + DIP { CADR %actual_level } + /* [ pair (pair signature nat) (pair address address) nat key : nat + : pair address address : pair (pair address address) nat key ] */ ; + CDDAR %rain_level ; + CMPLT ; + IF { CAR %under_key /* [ address : pair (pair address address) nat key ] */ } + { CDR %over_key /* [ address : pair (pair address address) nat key ] */ } ; + CONTRACT unit + /* [ option (contract unit) : pair (pair address address) nat key ] */ ; + ASSERT_SOME ; + BALANCE + /* [ mutez : contract unit : pair (pair address address) nat key ] */ ; + UNIT + /* [ unit : mutez : contract unit : pair (pair address address) nat key ] */ ; + TRANSFER_TOKENS @trans.op + /* [ operation : pair (pair address address) nat key ] */ ; + NIL operation + /* [ list operation : operation : pair (pair address address) nat key ] */ ; + SWAP + /* [ operation : list operation : pair (pair address address) nat key ] */ ; + CONS + /* [ list operation : pair (pair address address) nat key ] */ ; + PAIR + /* [ pair (list operation) (pair address address) nat key ] */ } } +Well typed (Gas remaining: 1039967.364 units remaining) michelson_test_scripts/mini_scenarios/xcat.tz +{ parameter bytes ; + storage unit ; + code { CAR @preimage + /* [ bytes ] */ ; + DIP { PUSH @from key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + /* [ key_hash ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit ] */ ; + PUSH @to + key_hash + "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN" + /* [ key_hash : contract unit ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : contract unit ] */ ; + PUSH @target_hash bytes 0x123456 + /* [ bytes : contract unit : contract unit ] */ ; + PUSH @deadline + timestamp + "2018-08-08 00:00:00Z" + /* [ timestamp : bytes : contract unit : contract unit ] */ } + /* [ bytes : timestamp : bytes : contract unit : contract unit ] */ ; + SWAP + /* [ timestamp : bytes : bytes : contract unit : contract unit ] */ ; + NOW + /* [ timestamp : timestamp : bytes : bytes : contract unit : contract unit ] */ ; + IFCMPLT + { DROP + /* [ bytes : contract unit : contract unit ] */ ; + DROP + /* [ contract unit : contract unit ] */ ; + DROP + /* [ contract unit ] */ ; + BALANCE + /* [ mutez : contract unit ] */ ; + UNIT + /* [ unit : mutez : contract unit ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ } + { DUP + /* [ bytes : bytes : bytes : contract unit : contract unit ] */ ; + SIZE + /* [ nat : bytes : bytes : contract unit : contract unit ] */ ; + PUSH @max_length + nat + 32 + /* [ nat : nat : bytes : bytes : contract unit : contract unit ] */ ; + IFCMPLT + { PUSH string + "preimage too long" + /* [ string : bytes : bytes : contract unit : contract unit ] */ ; + FAILWITH + /* [] */ } + { SHA256 @candidate_hash + /* [ bytes : bytes : contract unit : contract unit ] */ ; + IFCMPNEQ + { PUSH string "invalid preimage" + /* [ string : contract unit : contract unit ] */ ; + FAILWITH + /* [] */ } + { BALANCE + /* [ mutez : contract unit : contract unit ] */ ; + UNIT + /* [ unit : mutez : contract unit : contract unit ] */ ; + TRANSFER_TOKENS + /* [ operation : contract unit ] */ ; + DIP { DROP /* [] */ } + /* [ operation ] */ } } } ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039924.536 units remaining) michelson_test_scripts/mini_scenarios/xcat_dapp.tz +{ parameter + (or (pair %fund + (address %dest) + (pair %settings (bytes %target_hash) (timestamp %deadline))) + (or %claim_refund (bytes %preimage_claim) (bytes %refund_hash))) ; + storage + (pair (big_map + bytes + (pair (pair %recipients (address %from) (address %dest)) + (pair %settings (mutez %amount) (timestamp %deadline)))) + unit) ; + code { NIL @operations + operation + /* [ list operation + : pair (or (pair address bytes timestamp) (or bytes bytes)) + (big_map bytes (pair (pair address address) mutez timestamp)) + unit ] */ ; + SWAP + /* [ pair (or (pair address bytes timestamp) (or bytes bytes)) + (big_map bytes (pair (pair address address) mutez timestamp)) + unit : list operation ] */ ; + UNPAPAIR @% @% @% ; + DIP { DUP + /* [ big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ } + /* [ or (pair address bytes timestamp) (or bytes bytes) + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + IF_LEFT + { UNPAIR @% @% + /* [ address : pair bytes timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DUP + /* [ address : address : pair bytes timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + CONTRACT @dest + unit + /* [ option (contract unit) : address : pair bytes timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_SOME ; + DROP + /* [ address : pair bytes timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SWAP + /* [ pair bytes timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + UNPAIR @% @% + /* [ bytes : timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DIP { AMOUNT @amount + /* [ mutez : timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SENDER + /* [ address : mutez : timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DUP + /* [ address : address : mutez : timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + CONTRACT @from + unit + /* [ option (contract unit) : address : mutez : timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_SOME ; + DROP + /* [ address : mutez : timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DIP { PAIR + /* [ pair mutez timestamp : address + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SWAP + /* [ address : pair mutez timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ } + /* [ address : address : pair mutez timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + PAIR + /* [ pair address address : pair mutez timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + PAIR + /* [ pair (pair address address) mutez timestamp + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SOME @xcat + /* [ option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SWAP + /* [ big_map bytes (pair (pair address address) mutez timestamp) + : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ } + /* [ bytes : big_map bytes (pair (pair address address) mutez timestamp) + : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DUP + /* [ bytes : bytes : big_map bytes (pair (pair address address) mutez timestamp) + : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DIP { MEM + /* [ bool : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + NOT + /* [ bool : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT } + /* [ bytes : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + UPDATE + /* [ big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + PAIR @new_storage + /* [ pair (big_map bytes (pair (pair address address) mutez timestamp)) unit + : list operation ] */ ; + SWAP + /* [ list operation + : pair (big_map bytes (pair (pair address address) mutez timestamp)) unit ] */ ; + PAIR + /* [ pair (list operation) + (big_map bytes (pair (pair address address) mutez timestamp)) + unit ] */ } + { IF_LEFT + { DUP + /* [ bytes : bytes : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SIZE + /* [ nat : bytes : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + PUSH nat + 32 + /* [ nat : nat : bytes + : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_CMPGE ; + SHA256 @hash + /* [ bytes : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DUP + /* [ bytes : bytes : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DIP { SWAP + /* [ big_map bytes (pair (pair address address) mutez timestamp) : bytes + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ } + /* [ bytes : big_map bytes (pair (pair address address) mutez timestamp) : bytes + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DIP 2 + { GET + /* [ option (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_SOME ; + DUP + /* [ pair (pair address address) mutez timestamp + : pair (pair address address) mutez timestamp : unit : list operation ] */ ; + CADR @% ; + CONTRACT @dest + unit + /* [ option (contract unit) : pair (pair address address) mutez timestamp : unit + : list operation ] */ ; + ASSERT_SOME ; + SWAP + /* [ pair (pair address address) mutez timestamp : contract unit : unit + : list operation ] */ ; + CDR @% + /* [ pair mutez timestamp : contract unit : unit : list operation ] */ ; + UNPAIR @% @% + /* [ mutez : timestamp : contract unit : unit : list operation ] */ ; + SWAP + /* [ timestamp : mutez : contract unit : unit : list operation ] */ ; + NOW + /* [ timestamp : timestamp : mutez : contract unit : unit : list operation ] */ ; + ASSERT_CMPLT ; + UNIT + /* [ unit : mutez : contract unit : unit : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : unit : list operation ] */ } + /* [ bytes : big_map bytes (pair (pair address address) mutez timestamp) + : operation : unit : list operation ] */ } + { DUP + /* [ bytes : bytes : big_map bytes (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + DIP { GET + /* [ option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_SOME ; + DUP + /* [ pair (pair address address) mutez timestamp + : pair (pair address address) mutez timestamp + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + CAAR @% ; + CONTRACT @from + unit + /* [ option (contract unit) : pair (pair address address) mutez timestamp + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_SOME ; + SWAP + /* [ pair (pair address address) mutez timestamp : contract unit + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + CDR + /* [ pair mutez timestamp : contract unit + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + UNPAIR @% @% + /* [ mutez : timestamp : contract unit + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + SWAP + /* [ timestamp : mutez : contract unit + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + NOW + /* [ timestamp : timestamp : mutez : contract unit + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + ASSERT_CMPGE ; + UNIT + /* [ unit : mutez : contract unit + : big_map bytes (pair (pair address address) mutez timestamp) : unit + : list operation ] */ ; + TRANSFER_TOKENS + /* [ operation : big_map bytes (pair (pair address address) mutez timestamp) + : unit : list operation ] */ ; + SWAP + /* [ big_map bytes (pair (pair address address) mutez timestamp) : operation + : unit : list operation ] */ } + /* [ bytes : big_map bytes (pair (pair address address) mutez timestamp) + : operation : unit : list operation ] */ } ; + NONE @none + (pair (pair address address) (pair mutez timestamp)) + /* [ option (pair (pair address address) mutez timestamp) : bytes + : big_map bytes (pair (pair address address) mutez timestamp) : operation + : unit : list operation ] */ ; + SWAP + /* [ bytes : option (pair (pair address address) mutez timestamp) + : big_map bytes (pair (pair address address) mutez timestamp) : operation + : unit : list operation ] */ ; + UPDATE @cleared_map + /* [ big_map bytes (pair (pair address address) mutez timestamp) : operation + : unit : list operation ] */ ; + SWAP + /* [ operation : big_map bytes (pair (pair address address) mutez timestamp) + : unit : list operation ] */ ; + DIP { PAIR + /* [ pair (big_map bytes (pair (pair address address) mutez timestamp)) unit + : list operation ] */ ; + SWAP + /* [ list operation + : pair (big_map bytes (pair (pair address address) mutez timestamp)) unit ] */ } + /* [ operation : list operation + : pair (big_map bytes (pair (pair address address) mutez timestamp)) unit ] */ ; + CONS + /* [ list operation + : pair (big_map bytes (pair (pair address address) mutez timestamp)) unit ] */ ; + PAIR + /* [ pair (list operation) + (big_map bytes (pair (pair address address) mutez timestamp)) + unit ] */ } } } +Well typed (Gas remaining: 1039996.019 units remaining) michelson_test_scripts/non_regression/262_bug.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + LAMBDA unit unit { /* [ unit ] */ } + /* [ lambda unit unit ] */ ; + UNIT + /* [ unit : lambda unit unit ] */ ; + EXEC + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.536 units remaining) michelson_test_scripts/non_regression/843_bug.tz +{ parameter never ; + storage (pair address (lambda unit unit)) ; + code { CAR + /* [ never ] */ ; + PUSH address "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + /* [ address : never ] */ ; + DROP + /* [ never ] */ ; + NEVER + /* [] */ } } +Well typed (Gas remaining: 1039996.898 units remaining) michelson_test_scripts/non_regression/bad_annot_contract.tz +{ parameter bytes ; + storage (option (lambda unit unit)) ; + code { CAR + /* [ bytes ] */ ; + UNPACK (lambda unit unit) + /* [ option (lambda unit unit) ] */ ; + NIL operation + /* [ list operation : option (lambda unit unit) ] */ ; + PAIR + /* [ pair (list operation) (option (lambda unit unit)) ] */ } } +Well typed (Gas remaining: 1039993.858 units remaining) michelson_test_scripts/non_regression/pairk_annot.tz +{ parameter unit ; + storage unit ; + code { SENDER + /* [ address : pair unit unit ] */ ; + SOURCE + /* [ address : address : pair unit unit ] */ ; + PAIR 2 + /* [ pair address address : pair unit unit ] */ ; + SOURCE + /* [ address : pair address address : pair unit unit ] */ ; + SENDER + /* [ address : address : pair address address : pair unit unit ] */ ; + PAIR 2 + /* [ pair address address : pair address address : pair unit unit ] */ ; + COMPARE + /* [ int : pair unit unit ] */ ; + DROP + /* [ pair unit unit ] */ ; + CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039992.816 units remaining) michelson_test_scripts/opcodes/abs.tz +{ parameter nat ; + storage unit ; + code { CAR + /* [ nat ] */ ; + DUP + /* [ nat : nat ] */ ; + NEG + /* [ int : nat ] */ ; + ABS + /* [ nat : nat ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039947.520 units remaining) michelson_test_scripts/opcodes/add.tz +{ parameter unit ; + storage unit ; + code { CAR + /* [ unit ] */ ; + PUSH int 2 + /* [ int : unit ] */ ; + PUSH int 2 + /* [ int : int : unit ] */ ; + ADD + /* [ int : unit ] */ ; + PUSH int 4 + /* [ int : int : unit ] */ ; + ASSERT_CMPEQ ; + PUSH int 2 + /* [ int : unit ] */ ; + PUSH int 2 + /* [ int : int : unit ] */ ; + ADD + /* [ int : unit ] */ ; + PUSH int 4 + /* [ int : int : unit ] */ ; + ASSERT_CMPEQ ; + PUSH int 2 + /* [ int : unit ] */ ; + PUSH nat 2 + /* [ nat : int : unit ] */ ; + ADD + /* [ int : unit ] */ ; + PUSH int 4 + /* [ int : int : unit ] */ ; + ASSERT_CMPEQ ; + PUSH nat 2 + /* [ nat : unit ] */ ; + PUSH int 2 + /* [ int : nat : unit ] */ ; + ADD + /* [ int : unit ] */ ; + PUSH int 4 + /* [ int : int : unit ] */ ; + ASSERT_CMPEQ ; + PUSH nat 2 + /* [ nat : unit ] */ ; + PUSH nat 2 + /* [ nat : nat : unit ] */ ; + ADD + /* [ nat : unit ] */ ; + PUSH nat 4 + /* [ nat : nat : unit ] */ ; + ASSERT_CMPEQ ; + PUSH int 60 + /* [ int : unit ] */ ; + PUSH timestamp "2019-09-09T12:08:37Z" + /* [ timestamp : int : unit ] */ ; + ADD + /* [ timestamp : unit ] */ ; + PUSH timestamp "2019-09-09T12:09:37Z" + /* [ timestamp : timestamp : unit ] */ ; + ASSERT_CMPEQ ; + PUSH timestamp "2019-09-09T12:08:37Z" + /* [ timestamp : unit ] */ ; + PUSH int 60 + /* [ int : timestamp : unit ] */ ; + ADD + /* [ timestamp : unit ] */ ; + PUSH timestamp "2019-09-09T12:09:37Z" + /* [ timestamp : timestamp : unit ] */ ; + ASSERT_CMPEQ ; + PUSH mutez 1000 + /* [ mutez : unit ] */ ; + PUSH mutez 1000 + /* [ mutez : mutez : unit ] */ ; + ADD + /* [ mutez : unit ] */ ; + PUSH mutez 2000 + /* [ mutez : mutez : unit ] */ ; + ASSERT_CMPEQ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/add_bls12_381_fr.tz +{ parameter (pair bls12_381_fr bls12_381_fr) ; + storage (option bls12_381_fr) ; + code { CAR + /* [ pair bls12_381_fr bls12_381_fr ] */ ; + UNPAIR + /* [ bls12_381_fr : bls12_381_fr ] */ ; + ADD + /* [ bls12_381_fr ] */ ; + SOME + /* [ option bls12_381_fr ] */ ; + NIL operation + /* [ list operation : option bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_fr) ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/add_bls12_381_g1.tz +{ parameter (pair bls12_381_g1 bls12_381_g1) ; + storage (option bls12_381_g1) ; + code { CAR + /* [ pair bls12_381_g1 bls12_381_g1 ] */ ; + UNPAIR + /* [ bls12_381_g1 : bls12_381_g1 ] */ ; + ADD + /* [ bls12_381_g1 ] */ ; + SOME + /* [ option bls12_381_g1 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g1 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g1) ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/add_bls12_381_g2.tz +{ parameter (pair bls12_381_g2 bls12_381_g2) ; + storage (option bls12_381_g2) ; + code { CAR + /* [ pair bls12_381_g2 bls12_381_g2 ] */ ; + UNPAIR + /* [ bls12_381_g2 : bls12_381_g2 ] */ ; + ADD + /* [ bls12_381_g2 ] */ ; + SOME + /* [ option bls12_381_g2 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g2 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g2) ] */ } } +Well typed (Gas remaining: 1039994.537 units remaining) michelson_test_scripts/opcodes/add_delta_timestamp.tz +{ parameter (pair int timestamp) ; + storage (option timestamp) ; + code { CAR + /* [ pair int timestamp ] */ ; + DUP + /* [ pair int timestamp : pair int timestamp ] */ ; + CAR + /* [ int : pair int timestamp ] */ ; + DIP { CDR /* [ timestamp ] */ } + /* [ int : timestamp ] */ ; + ADD + /* [ timestamp ] */ ; + SOME + /* [ option timestamp ] */ ; + NIL operation + /* [ list operation : option timestamp ] */ ; + PAIR + /* [ pair (list operation) (option timestamp) ] */ } } +Well typed (Gas remaining: 1039994.537 units remaining) michelson_test_scripts/opcodes/add_timestamp_delta.tz +{ parameter (pair timestamp int) ; + storage (option timestamp) ; + code { CAR + /* [ pair timestamp int ] */ ; + DUP + /* [ pair timestamp int : pair timestamp int ] */ ; + CAR + /* [ timestamp : pair timestamp int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ timestamp : int ] */ ; + ADD + /* [ timestamp ] */ ; + SOME + /* [ option timestamp ] */ ; + NIL operation + /* [ list operation : option timestamp ] */ ; + PAIR + /* [ pair (list operation) (option timestamp) ] */ } } +Well typed (Gas remaining: 1039996.828 units remaining) michelson_test_scripts/opcodes/address.tz +{ parameter (contract unit) ; + storage (option address) ; + code { CAR + /* [ contract unit ] */ ; + ADDRESS + /* [ address ] */ ; + SOME + /* [ option address ] */ ; + NIL operation + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } +Well typed (Gas remaining: 1039986.649 units remaining) michelson_test_scripts/opcodes/amount_after_fib_view.tz +{ parameter address ; + storage mutez ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 3 + /* [ nat : address : address ] */ ; + VIEW "fib" nat + /* [ option nat : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 15000000 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + AMOUNT + /* [ mutez : operation ] */ ; + SWAP + /* [ operation : mutez ] */ ; + NIL operation + /* [ list operation : operation : mutez ] */ ; + SWAP + /* [ operation : list operation : mutez ] */ ; + CONS + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039986.856 units remaining) michelson_test_scripts/opcodes/amount_after_nonexistent_view.tz +{ parameter address ; + storage mutez ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "nonexistent" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_NONE ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 15000000 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + AMOUNT + /* [ mutez : operation ] */ ; + SWAP + /* [ operation : mutez ] */ ; + NIL operation + /* [ list operation : operation : mutez ] */ ; + SWAP + /* [ operation : list operation : mutez ] */ ; + CONS + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039986.472 units remaining) michelson_test_scripts/opcodes/amount_after_view.tz +{ parameter address ; + storage mutez ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 15000000 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + AMOUNT + /* [ mutez : operation ] */ ; + SWAP + /* [ operation : mutez ] */ ; + NIL operation + /* [ list operation : operation : mutez ] */ ; + SWAP + /* [ operation : list operation : mutez ] */ ; + CONS + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039995.334 units remaining) michelson_test_scripts/opcodes/and.tz +{ parameter (pair :param (bool %first) (bool %second)) ; + storage (option bool) ; + code { CAR + /* [ pair bool bool ] */ ; + UNPAIR + /* [ bool : bool ] */ ; + AND @and + /* [ bool ] */ ; + SOME @res + /* [ option bool ] */ ; + NIL @noop operation + /* [ list operation : option bool ] */ ; + PAIR + /* [ pair (list operation) (option bool) ] */ ; + UNPAIR @x @y + /* [ list operation : option bool ] */ ; + PAIR %a %b + /* [ pair (list operation) (option bool) ] */ } } +Well typed (Gas remaining: 1039972.833 units remaining) michelson_test_scripts/opcodes/and_binary.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 5 + /* [ nat ] */ ; + PUSH nat 6 + /* [ nat : nat ] */ ; + AND + /* [ nat ] */ ; + PUSH nat 4 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + PUSH nat 6 + /* [ nat ] */ ; + PUSH int 5 + /* [ int : nat ] */ ; + AND + /* [ nat ] */ ; + PUSH nat 4 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + PUSH nat 12 + /* [ nat ] */ ; + PUSH int -1 + /* [ int : nat ] */ ; + AND + /* [ nat ] */ ; + PUSH nat 12 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + PUSH nat 12 + /* [ nat ] */ ; + PUSH int -5 + /* [ int : nat ] */ ; + AND + /* [ nat ] */ ; + PUSH nat 8 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039978.970 units remaining) michelson_test_scripts/opcodes/and_bytes_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + PUSH bytes 0x06 + /* [ bytes : bytes ] */ ; + AND + /* [ bytes ] */ ; + PUSH bytes 0x04 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0005 + /* [ bytes ] */ ; + PUSH bytes 0x0106 + /* [ bytes : bytes ] */ ; + AND + /* [ bytes ] */ ; + PUSH bytes 0x0004 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + PUSH bytes 0x0106 + /* [ bytes : bytes ] */ ; + AND + /* [ bytes ] */ ; + PUSH bytes 0x04 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.850 units remaining) michelson_test_scripts/opcodes/and_logical_1.tz +{ parameter (pair bool bool) ; + storage bool ; + code { CAR + /* [ pair bool bool ] */ ; + UNPAIR + /* [ bool : bool ] */ ; + AND @and + /* [ bool ] */ ; + NIL @noop operation + /* [ list operation : bool ] */ ; + PAIR + /* [ pair (list operation) bool ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/balance.tz +{ parameter unit ; + storage mutez ; + code { DROP + /* [] */ ; + BALANCE + /* [ mutez ] */ ; + NIL operation + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039986.649 units remaining) michelson_test_scripts/opcodes/balance_after_fib_view.tz +{ parameter address ; + storage mutez ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 3 + /* [ nat : address : address ] */ ; + VIEW "fib" nat + /* [ option nat : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 15000000 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + BALANCE + /* [ mutez : operation ] */ ; + SWAP + /* [ operation : mutez ] */ ; + NIL operation + /* [ list operation : operation : mutez ] */ ; + SWAP + /* [ operation : list operation : mutez ] */ ; + CONS + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039986.856 units remaining) michelson_test_scripts/opcodes/balance_after_nonexistent_view.tz +{ parameter address ; + storage mutez ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "nonexistent" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_NONE ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 15000000 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + BALANCE + /* [ mutez : operation ] */ ; + SWAP + /* [ operation : mutez ] */ ; + NIL operation + /* [ list operation : operation : mutez ] */ ; + SWAP + /* [ operation : list operation : mutez ] */ ; + CONS + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039986.472 units remaining) michelson_test_scripts/opcodes/balance_after_view.tz +{ parameter address ; + storage mutez ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 15000000 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + BALANCE + /* [ mutez : operation ] */ ; + SWAP + /* [ operation : mutez ] */ ; + NIL operation + /* [ list operation : operation : mutez ] */ ; + SWAP + /* [ operation : list operation : mutez ] */ ; + CONS + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039993.786 units remaining) michelson_test_scripts/opcodes/big_map_mem_nat.tz +{ parameter nat ; + storage (pair (big_map nat nat) (option bool)) ; + code { UNPAIR + /* [ nat : pair (big_map nat nat) (option bool) ] */ ; + DIP { CAR /* [ big_map nat nat ] */ ; DUP /* [ big_map nat nat : big_map nat nat ] */ } + /* [ nat : big_map nat nat : big_map nat nat ] */ ; + MEM + /* [ bool : big_map nat nat ] */ ; + SOME + /* [ option bool : big_map nat nat ] */ ; + SWAP + /* [ big_map nat nat : option bool ] */ ; + PAIR + /* [ pair (big_map nat nat) (option bool) ] */ ; + NIL operation + /* [ list operation : pair (big_map nat nat) (option bool) ] */ ; + PAIR + /* [ pair (list operation) (big_map nat nat) (option bool) ] */ } } +Well typed (Gas remaining: 1039993.786 units remaining) michelson_test_scripts/opcodes/big_map_mem_string.tz +{ parameter string ; + storage (pair (big_map string nat) (option bool)) ; + code { UNPAIR + /* [ string : pair (big_map string nat) (option bool) ] */ ; + DIP { CAR + /* [ big_map string nat ] */ ; + DUP + /* [ big_map string nat : big_map string nat ] */ } + /* [ string : big_map string nat : big_map string nat ] */ ; + MEM + /* [ bool : big_map string nat ] */ ; + SOME + /* [ option bool : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : option bool ] */ ; + PAIR + /* [ pair (big_map string nat) (option bool) ] */ ; + NIL operation + /* [ list operation : pair (big_map string nat) (option bool) ] */ ; + PAIR + /* [ pair (list operation) (big_map string nat) (option bool) ] */ } } +Well typed (Gas remaining: 1039987.823 units remaining) michelson_test_scripts/opcodes/big_map_to_self.tz +{ parameter (or (pair %have_fun (big_map string nat) unit) (unit %default)) ; + storage (big_map string nat) ; + code { UNPAIR + /* [ or (pair (big_map string nat) unit) unit : big_map string nat ] */ ; + DIP { NIL operation /* [ list operation : big_map string nat ] */ } + /* [ or (pair (big_map string nat) unit) unit : list operation + : big_map string nat ] */ ; + IF_LEFT + { DROP /* [ list operation : big_map string nat ] */ } + { DROP + /* [ list operation : big_map string nat ] */ ; + SELF %have_fun + /* [ contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + PUSH mutez + 0 + /* [ mutez : contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + DUP 4 + /* [ big_map string nat : mutez : contract (pair (big_map string nat) unit) + : list operation : big_map string nat ] */ ; + PUSH (option nat) + (Some 8) + /* [ option nat : big_map string nat : mutez + : contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + PUSH string + "hahaha" + /* [ string : option nat : big_map string nat : mutez + : contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + UPDATE + /* [ big_map string nat : mutez : contract (pair (big_map string nat) unit) + : list operation : big_map string nat ] */ ; + UNIT + /* [ unit : big_map string nat : mutez + : contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + SWAP + /* [ big_map string nat : unit : mutez + : contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + PAIR + /* [ pair (big_map string nat) unit : mutez + : contract (pair (big_map string nat) unit) : list operation + : big_map string nat ] */ ; + TRANSFER_TOKENS + /* [ operation : list operation : big_map string nat ] */ ; + CONS + /* [ list operation : big_map string nat ] */ } ; + PAIR + /* [ pair (list operation) (big_map string nat) ] */ } } +Well typed (Gas remaining: 1039996.579 units remaining) michelson_test_scripts/opcodes/bls12_381_fr_push_bytes_not_padded.tz +{ parameter unit ; + storage (option bls12_381_fr) ; + code { DROP + /* [] */ ; + PUSH bls12_381_fr 0x00 + /* [ bls12_381_fr ] */ ; + SOME + /* [ option bls12_381_fr ] */ ; + NIL operation + /* [ list operation : option bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_fr) ] */ } } +Well typed (Gas remaining: 1039996.579 units remaining) michelson_test_scripts/opcodes/bls12_381_fr_push_nat.tz +{ parameter unit ; + storage (option bls12_381_fr) ; + code { DROP + /* [] */ ; + PUSH bls12_381_fr 16 + /* [ bls12_381_fr ] */ ; + SOME + /* [ option bls12_381_fr ] */ ; + NIL operation + /* [ list operation : option bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_fr) ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz +{ parameter bls12_381_fr ; + storage int ; + code { CAR + /* [ bls12_381_fr ] */ ; + INT + /* [ int ] */ ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039993.693 units remaining) michelson_test_scripts/opcodes/bls12_381_fr_to_mutez.tz +{ parameter bls12_381_fr ; + storage mutez ; + code { CAR + /* [ bls12_381_fr ] */ ; + INT + /* [ int ] */ ; + ISNAT + /* [ option nat ] */ ; + ASSERT_SOME ; + PUSH mutez 1 + /* [ mutez : nat ] */ ; + MUL + /* [ mutez ] */ ; + NIL operation + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz +{ parameter int ; + storage bls12_381_fr ; + code { UNPAIR + /* [ int : bls12_381_fr ] */ ; + MUL + /* [ bls12_381_fr ] */ ; + NIL operation + /* [ list operation : bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) bls12_381_fr ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz +{ parameter nat ; + storage bls12_381_fr ; + code { UNPAIR + /* [ nat : bls12_381_fr ] */ ; + MUL + /* [ bls12_381_fr ] */ ; + NIL operation + /* [ list operation : bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) bls12_381_fr ] */ } } +Well typed (Gas remaining: 1039997.089 units remaining) michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz +{ parameter int ; + storage bls12_381_fr ; + code { UNPAIR + /* [ int : bls12_381_fr ] */ ; + SWAP + /* [ bls12_381_fr : int ] */ ; + MUL + /* [ bls12_381_fr ] */ ; + NIL operation + /* [ list operation : bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) bls12_381_fr ] */ } } +Well typed (Gas remaining: 1039997.089 units remaining) michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz +{ parameter nat ; + storage bls12_381_fr ; + code { UNPAIR + /* [ nat : bls12_381_fr ] */ ; + SWAP + /* [ bls12_381_fr : nat ] */ ; + MUL + /* [ bls12_381_fr ] */ ; + NIL operation + /* [ list operation : bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) bls12_381_fr ] */ } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/opcodes/bytes.tz +{ parameter bytes ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039907.915 units remaining) michelson_test_scripts/opcodes/bytes_of_int_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH int 0 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH int 1 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x01 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH int 1193046 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x123456 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x123456 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int 1193046 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0000123456 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int 1193046 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int 0 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0000 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int 0 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH int -128 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x80 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH int -129 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0xff7f + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH int -33024 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0xff7f00 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH int -4294967296 + /* [ int ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0xff00000000 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x80 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int -128 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0xff7f + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int -129 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0xff7f00 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int -33024 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0xffffff7f00 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int -33024 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0xff00000000 + /* [ bytes ] */ ; + INT + /* [ int ] */ ; + PUSH int -4294967296 + /* [ int : int ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039958.799 units remaining) michelson_test_scripts/opcodes/bytes_of_nat_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 0 + /* [ nat ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 1 + /* [ nat ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x01 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 1193046 + /* [ nat ] */ ; + BYTES + /* [ bytes ] */ ; + PUSH bytes 0x123456 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x123456 + /* [ bytes ] */ ; + NAT + /* [ nat ] */ ; + PUSH nat 1193046 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0000123456 + /* [ bytes ] */ ; + NAT + /* [ nat ] */ ; + PUSH nat 1193046 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x + /* [ bytes ] */ ; + NAT + /* [ nat ] */ ; + PUSH nat 0 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0000 + /* [ bytes ] */ ; + NAT + /* [ nat ] */ ; + PUSH nat 0 + /* [ nat : nat ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.385 units remaining) michelson_test_scripts/opcodes/car.tz +{ parameter (pair (nat :l) (nat :r)) ; + storage nat ; + code { CAR + /* [ pair nat nat ] */ ; + CAR + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039997.385 units remaining) michelson_test_scripts/opcodes/cdr.tz +{ parameter (pair (nat :l) (nat :r)) ; + storage nat ; + code { CAR + /* [ pair nat nat ] */ ; + CDR + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039997.089 units remaining) michelson_test_scripts/opcodes/chain_id.tz +{ parameter unit ; + storage unit ; + code { CHAIN_ID + /* [ chain_id : pair unit unit ] */ ; + DROP + /* [ pair unit unit ] */ ; + CAR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/chain_id_store.tz +{ parameter unit ; + storage (option chain_id) ; + code { DROP + /* [] */ ; + CHAIN_ID + /* [ chain_id ] */ ; + SOME + /* [ option chain_id ] */ ; + NIL operation + /* [ list operation : option chain_id ] */ ; + PAIR + /* [ pair (list operation) (option chain_id) ] */ } } +Well typed (Gas remaining: 1039989.149 units remaining) michelson_test_scripts/opcodes/check_signature.tz +{ parameter key ; + storage (pair signature string) ; + code { DUP + /* [ pair key signature string : pair key signature string ] */ ; + DUP + /* [ pair key signature string : pair key signature string + : pair key signature string ] */ ; + DIP { CDR + /* [ pair signature string : pair key signature string ] */ ; + DUP + /* [ pair signature string : pair signature string : pair key signature string ] */ ; + CAR + /* [ signature : pair signature string : pair key signature string ] */ ; + DIP { CDR + /* [ string : pair key signature string ] */ ; + PACK + /* [ bytes : pair key signature string ] */ } + /* [ signature : bytes : pair key signature string ] */ } + /* [ pair key signature string : signature : bytes : pair key signature string ] */ ; + CAR + /* [ key : signature : bytes : pair key signature string ] */ ; + CHECK_SIGNATURE + /* [ bool : pair key signature string ] */ ; + IF { /* [ pair key signature string ] */ } { FAIL } ; + CDR + /* [ pair signature string ] */ ; + NIL operation + /* [ list operation : pair signature string ] */ ; + PAIR + /* [ pair (list operation) signature string ] */ } } +Well typed (Gas remaining: 1039995.265 units remaining) michelson_test_scripts/opcodes/comb.tz +{ parameter unit ; + storage (pair nat nat nat) ; + code { DROP + /* [] */ ; + PUSH nat 3 + /* [ nat ] */ ; + PUSH nat 2 + /* [ nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat ] */ ; + NIL operation + /* [ list operation : nat : nat : nat ] */ ; + PAIR 4 + /* [ pair (list operation) nat nat nat ] */ } } +Well typed (Gas remaining: 1039966.290 units remaining) michelson_test_scripts/opcodes/comb-get.tz +{ parameter (pair nat nat nat unit) ; + storage unit ; + code { CAR + /* [ pair nat nat nat unit ] */ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + CAR + /* [ nat : pair nat nat nat unit ] */ ; + PUSH nat 1 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + GET 1 + /* [ nat : pair nat nat nat unit ] */ ; + PUSH nat 1 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + GET 3 + /* [ nat : pair nat nat nat unit ] */ ; + PUSH nat 4 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + GET 5 + /* [ nat : pair nat nat nat unit ] */ ; + PUSH nat 2 + /* [ nat : nat : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat nat nat unit : pair nat nat nat unit ] */ ; + GET 6 + /* [ unit : pair nat nat nat unit ] */ ; + UNIT + /* [ unit : unit : pair nat nat nat unit ] */ ; + ASSERT_CMPEQ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.354 units remaining) michelson_test_scripts/opcodes/comb-literals.tz +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 3 6 9 ; Pair 1 (Pair 4 (Pair 7 10)) ; { 2 ; 5 ; 8 ; 11 } } + /* [ list (pair nat nat nat nat) : pair unit unit ] */ ; + DROP 2 + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.939 units remaining) michelson_test_scripts/opcodes/comb-set.tz +{ parameter unit ; + storage (pair nat nat nat unit) ; + code { CDR + /* [ pair nat nat nat unit ] */ ; + PUSH nat 2 + /* [ nat : pair nat nat nat unit ] */ ; + UPDATE 1 + /* [ pair nat nat nat unit ] */ ; + PUSH nat 12 + /* [ nat : pair nat nat nat unit ] */ ; + UPDATE 3 + /* [ pair nat nat nat unit ] */ ; + PUSH nat 8 + /* [ nat : pair nat nat nat unit ] */ ; + UPDATE 5 + /* [ pair nat nat nat unit ] */ ; + UNIT + /* [ unit : pair nat nat nat unit ] */ ; + UPDATE 6 + /* [ pair nat nat nat unit ] */ ; + NIL operation + /* [ list operation : pair nat nat nat unit ] */ ; + PAIR + /* [ pair (list operation) nat nat nat unit ] */ } } +Well typed (Gas remaining: 1039991.931 units remaining) michelson_test_scripts/opcodes/comb-set-2.tz +{ parameter (pair nat nat nat unit) ; + storage (option (pair int nat string bytes)) ; + code { CAR + /* [ pair nat nat nat unit ] */ ; + PUSH int 2 + /* [ int : pair nat nat nat unit ] */ ; + UPDATE 1 + /* [ pair int nat nat unit ] */ ; + PUSH string "toto" + /* [ string : pair int nat nat unit ] */ ; + UPDATE 5 + /* [ pair int nat string unit ] */ ; + PUSH bytes 0x01 + /* [ bytes : pair int nat string unit ] */ ; + UPDATE 6 + /* [ pair int nat string bytes ] */ ; + SOME + /* [ option (pair int nat string bytes) ] */ ; + NIL operation + /* [ list operation : option (pair int nat string bytes) ] */ ; + PAIR + /* [ pair (list operation) (option (pair int nat string bytes)) ] */ } } +Well typed (Gas remaining: 1039839.822 units remaining) michelson_test_scripts/opcodes/compare.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH bool True + /* [ bool ] */ ; + DUP + /* [ bool : bool ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH bool False + /* [ bool ] */ ; + DUP + /* [ bool : bool ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH bool False + /* [ bool ] */ ; + PUSH bool True + /* [ bool : bool ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH bool True + /* [ bool ] */ ; + PUSH bool False + /* [ bool : bool ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH bytes 0xaabbcc + /* [ bytes ] */ ; + DUP + /* [ bytes : bytes ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH bytes 0x + /* [ bytes ] */ ; + PUSH bytes 0x + /* [ bytes : bytes ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH bytes 0x + /* [ bytes ] */ ; + PUSH bytes 0x01 + /* [ bytes : bytes ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH bytes 0x01 + /* [ bytes ] */ ; + PUSH bytes 0x02 + /* [ bytes : bytes ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH bytes 0x02 + /* [ bytes ] */ ; + PUSH bytes 0x01 + /* [ bytes : bytes ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH int 1 + /* [ int ] */ ; + DUP + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH int 10 + /* [ int ] */ ; + PUSH int 5 + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH int -4 + /* [ int ] */ ; + PUSH int 1923 + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH nat 1 + /* [ nat ] */ ; + DUP + /* [ nat : nat ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH nat 10 + /* [ nat ] */ ; + PUSH nat 5 + /* [ nat : nat ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH nat 4 + /* [ nat ] */ ; + PUSH nat 1923 + /* [ nat : nat ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + /* [ key_hash ] */ ; + DUP + /* [ key_hash : key_hash ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH key_hash "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" + /* [ key_hash ] */ ; + PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + /* [ key_hash : key_hash ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH key_hash "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + /* [ key_hash ] */ ; + PUSH key_hash "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" + /* [ key_hash : key_hash ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH mutez 1 + /* [ mutez ] */ ; + DUP + /* [ mutez : mutez ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH mutez 10 + /* [ mutez ] */ ; + PUSH mutez 5 + /* [ mutez : mutez ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH mutez 4 + /* [ mutez ] */ ; + PUSH mutez 1923 + /* [ mutez : mutez ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH string "AABBCC" + /* [ string ] */ ; + DUP + /* [ string : string ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH string "" + /* [ string ] */ ; + PUSH string "" + /* [ string : string ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH string "" + /* [ string ] */ ; + PUSH string "a" + /* [ string : string ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH string "a" + /* [ string ] */ ; + PUSH string "b" + /* [ string : string ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH string "b" + /* [ string ] */ ; + PUSH string "a" + /* [ string : string ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + PUSH timestamp "2019-09-16T08:38:05Z" + /* [ timestamp ] */ ; + DUP + /* [ timestamp : timestamp ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH timestamp "2017-09-16T08:38:04Z" + /* [ timestamp ] */ ; + PUSH timestamp "2019-09-16T08:38:05Z" + /* [ timestamp : timestamp ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_GT ; + PUSH timestamp "2019-09-16T08:38:05Z" + /* [ timestamp ] */ ; + PUSH timestamp "2019-09-16T08:38:04Z" + /* [ timestamp : timestamp ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_LT ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039246.273 units remaining) michelson_test_scripts/opcodes/compare_big_type.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 0 + /* [ nat ] */ ; + DUP + /* [ nat : nat ] */ ; + PAIR + /* [ pair nat nat ] */ ; + DUP + /* [ pair nat nat : pair nat nat ] */ ; + PAIR + /* [ pair (pair nat nat) nat nat ] */ ; + DUP + /* [ pair (pair nat nat) nat nat : pair (pair nat nat) nat nat ] */ ; + PAIR + /* [ pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat ] */ ; + DUP + /* [ pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat + : pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat ] */ ; + PAIR + /* [ pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039130.903 units remaining) michelson_test_scripts/opcodes/compare_big_type2.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 0 + /* [ nat ] */ ; + DUP + /* [ nat : nat ] */ ; + PAIR + /* [ pair nat nat ] */ ; + DUP + /* [ pair nat nat : pair nat nat ] */ ; + PAIR + /* [ pair (pair nat nat) nat nat ] */ ; + DUP + /* [ pair (pair nat nat) nat nat : pair (pair nat nat) nat nat ] */ ; + PAIR + /* [ pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat ] */ ; + DUP + /* [ pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat + : pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat ] */ ; + PAIR + /* [ pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + PAIR + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DUP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + COMPARE + /* [ int + : pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [ pair (pair (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat) + (pair (pair (pair nat nat) nat nat) (pair nat nat) nat nat) + (pair (pair nat nat) nat nat) + (pair nat nat) + nat + nat ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039977.792 units remaining) michelson_test_scripts/opcodes/comparisons.tz +{ parameter (list int) ; + storage (list (list bool)) ; + code { CAR + /* [ list int ] */ ; + NIL (list bool) + /* [ list (list bool) : list int ] */ ; + DIP { DUP + /* [ list int : list int ] */ ; + MAP { EQ /* [ bool : list int ] */ } + /* [ list bool : list int ] */ } + /* [ list (list bool) : list bool : list int ] */ ; + SWAP + /* [ list bool : list (list bool) : list int ] */ ; + CONS + /* [ list (list bool) : list int ] */ ; + DIP { DUP + /* [ list int : list int ] */ ; + MAP { NEQ /* [ bool : list int ] */ } + /* [ list bool : list int ] */ } + /* [ list (list bool) : list bool : list int ] */ ; + SWAP + /* [ list bool : list (list bool) : list int ] */ ; + CONS + /* [ list (list bool) : list int ] */ ; + DIP { DUP + /* [ list int : list int ] */ ; + MAP { LE /* [ bool : list int ] */ } + /* [ list bool : list int ] */ } + /* [ list (list bool) : list bool : list int ] */ ; + SWAP + /* [ list bool : list (list bool) : list int ] */ ; + CONS + /* [ list (list bool) : list int ] */ ; + DIP { DUP + /* [ list int : list int ] */ ; + MAP { LT /* [ bool : list int ] */ } + /* [ list bool : list int ] */ } + /* [ list (list bool) : list bool : list int ] */ ; + SWAP + /* [ list bool : list (list bool) : list int ] */ ; + CONS + /* [ list (list bool) : list int ] */ ; + DIP { DUP + /* [ list int : list int ] */ ; + MAP { GE /* [ bool : list int ] */ } + /* [ list bool : list int ] */ } + /* [ list (list bool) : list bool : list int ] */ ; + SWAP + /* [ list bool : list (list bool) : list int ] */ ; + CONS + /* [ list (list bool) : list int ] */ ; + DIP { MAP { GT /* [ bool ] */ } /* [ list bool ] */ } + /* [ list (list bool) : list bool ] */ ; + SWAP + /* [ list bool : list (list bool) ] */ ; + CONS + /* [ list (list bool) ] */ ; + NIL operation + /* [ list operation : list (list bool) ] */ ; + PAIR + /* [ pair (list operation) (list (list bool)) ] */ } } +Well typed (Gas remaining: 1039996.039 units remaining) michelson_test_scripts/opcodes/concat_hello.tz +{ parameter (list string) ; + storage (list string) ; + code { CAR + /* [ list string ] */ ; + MAP { PUSH @hello string "Hello " /* [ string : string ] */ ; CONCAT /* [ string ] */ } + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039996.114 units remaining) michelson_test_scripts/opcodes/concat_hello_bytes.tz +{ parameter (list bytes) ; + storage (list bytes) ; + code { CAR + /* [ list bytes ] */ ; + MAP { PUSH bytes 0xff /* [ bytes : bytes ] */ ; CONCAT /* [ bytes ] */ } + /* [ list bytes ] */ ; + NIL operation + /* [ list operation : list bytes ] */ ; + PAIR + /* [ pair (list operation) (list bytes) ] */ } } +Well typed (Gas remaining: 1039992.642 units remaining) michelson_test_scripts/opcodes/concat_list.tz +{ parameter (list string) ; + storage string ; + code { CAR + /* [ list string ] */ ; + PUSH string "" + /* [ string : list string ] */ ; + SWAP + /* [ list string : string ] */ ; + ITER { SWAP + /* [ string : string ] */ ; + DIP { NIL string + /* [ list string : string ] */ ; + SWAP + /* [ string : list string ] */ ; + CONS + /* [ list string ] */ } + /* [ string : list string ] */ ; + CONS + /* [ list string ] */ ; + CONCAT + /* [ string ] */ } + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039997.390 units remaining) michelson_test_scripts/opcodes/cons.tz +{ parameter int ; + storage (list int) ; + code { UNPAIR + /* [ int : list int ] */ ; + CONS + /* [ list int ] */ ; + NIL operation + /* [ list operation : list int ] */ ; + PAIR + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039975.058 units remaining) michelson_test_scripts/opcodes/contains_all.tz +{ parameter (pair (list string) (list string)) ; + storage (option bool) ; + code { CAR + /* [ pair (list string) (list string) ] */ ; + DUP + /* [ pair (list string) (list string) : pair (list string) (list string) ] */ ; + CAR + /* [ list string : pair (list string) (list string) ] */ ; + DIP { CDR /* [ list string ] */ } + /* [ list string : list string ] */ ; + EMPTY_SET string + /* [ set string : list string : list string ] */ ; + SWAP + /* [ list string : set string : list string ] */ ; + ITER { PAIR + /* [ pair string (set string) : list string ] */ ; + DUP + /* [ pair string (set string) : pair string (set string) : list string ] */ ; + CAR + /* [ string : pair string (set string) : list string ] */ ; + DIP { CDR /* [ set string : list string ] */ } + /* [ string : set string : list string ] */ ; + PUSH bool True + /* [ bool : string : set string : list string ] */ ; + SWAP + /* [ string : bool : set string : list string ] */ ; + UPDATE + /* [ set string : list string ] */ } + /* [ set string : list string ] */ ; + PUSH bool True + /* [ bool : set string : list string ] */ ; + SWAP + /* [ set string : bool : list string ] */ ; + PAIR + /* [ pair (set string) bool : list string ] */ ; + SWAP + /* [ list string : pair (set string) bool ] */ ; + ITER { PAIR + /* [ pair string (set string) bool ] */ ; + DUP + /* [ pair string (set string) bool : pair string (set string) bool ] */ ; + DUP + /* [ pair string (set string) bool : pair string (set string) bool + : pair string (set string) bool ] */ ; + CAR + /* [ string : pair string (set string) bool : pair string (set string) bool ] */ ; + DIP { CDAR ; + DIP { CDDR } + /* [ set string : bool ] */ ; + DUP + /* [ set string : set string : bool ] */ } + /* [ string : set string : set string : bool ] */ ; + MEM + /* [ bool : set string : bool ] */ ; + DIP { SWAP /* [ bool : set string ] */ } + /* [ bool : bool : set string ] */ ; + AND + /* [ bool : set string ] */ ; + SWAP + /* [ set string : bool ] */ ; + PAIR + /* [ pair (set string) bool ] */ } + /* [ pair (set string) bool ] */ ; + CDR + /* [ bool ] */ ; + SOME + /* [ option bool ] */ ; + NIL operation + /* [ list operation : option bool ] */ ; + PAIR + /* [ pair (list operation) (option bool) ] */ } } +Well typed (Gas remaining: 1039994.290 units remaining) michelson_test_scripts/opcodes/contract.tz +{ parameter address ; + storage unit ; + code { CAR + /* [ address ] */ ; + CONTRACT unit + /* [ option (contract unit) ] */ ; + ASSERT_SOME ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039992.030 units remaining) michelson_test_scripts/opcodes/create_contract.tz +{ parameter unit ; + storage (option address) ; + code { /* [ pair unit unit ] */ + DROP + /* [ list operation : unit ] */ ; + UNIT + /* [ unit ] */ ; + AMOUNT + /* [ pair (list operation) unit ] */ ; + NONE key_hash + /* [ option key_hash : mutez : unit ] */ ; + CREATE_CONTRACT + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + /* [ operation : address ] */ ; + DIP { SOME + /* [ option address ] */ ; + NIL operation + /* [ list operation : option address ] */ } + /* [ operation : list operation : option address ] */ ; + CONS + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } +Well typed (Gas remaining: 1039992.030 units remaining) michelson_test_scripts/opcodes/create_contract_rootname.tz +{ parameter unit ; + storage (option address) ; + code { /* [ pair unit unit ] */ + DROP + /* [ list operation : unit ] */ ; + UNIT + /* [ unit ] */ ; + AMOUNT + /* [ pair (list operation) unit ] */ ; + NONE key_hash + /* [ option key_hash : mutez : unit ] */ ; + CREATE_CONTRACT + { parameter (unit %root) ; + storage unit ; + code { CDR ; NIL operation ; PAIR } } + /* [ operation : address ] */ ; + DIP { SOME + /* [ option address ] */ ; + NIL operation + /* [ list operation : option address ] */ } + /* [ operation : list operation : option address ] */ ; + CONS + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } +Well typed (Gas remaining: 1039992.030 units remaining) michelson_test_scripts/opcodes/create_contract_rootname_alt.tz +{ parameter unit ; + storage (option address) ; + code { /* [ pair unit unit ] */ + DROP + /* [ list operation : unit ] */ ; + UNIT + /* [ unit ] */ ; + AMOUNT + /* [ pair (list operation) unit ] */ ; + NONE key_hash + /* [ option key_hash : mutez : unit ] */ ; + CREATE_CONTRACT + { parameter (unit %root) ; + storage unit ; + code { CDR ; NIL operation ; PAIR } } + /* [ operation : address ] */ ; + DIP { SOME + /* [ option address ] */ ; + NIL operation + /* [ list operation : option address ] */ } + /* [ operation : list operation : option address ] */ ; + CONS + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } +Well typed (Gas remaining: 1039991.039 units remaining) michelson_test_scripts/opcodes/create_contract_with_view.tz +{ parameter unit ; + storage (option address) ; + code { /* [ pair unit unit ] */ + DROP + /* [ list operation : unit ] */ ; + UNIT + /* [ unit ] */ ; + AMOUNT + /* [ pair (list operation) unit ] */ ; + NONE key_hash + /* [ option key_hash : mutez : unit ] */ ; + CREATE_CONTRACT + { parameter unit /* [ nat ] */ ; + storage unit ; + code { CDR ; NIL operation ; PAIR } ; + view "const" nat nat { CAR } } + /* [ operation : address ] */ ; + DIP { SOME + /* [ option address ] */ ; + NIL operation + /* [ list operation : option address ] */ } + /* [ operation : list operation : option address ] */ ; + CONS + /* [ list operation : option address ] */ ; + PAIR + /* [ pair (list operation) (option address) ] */ } } +Well typed (Gas remaining: 1039995.116 units remaining) michelson_test_scripts/opcodes/diff_timestamps.tz +{ parameter (pair timestamp timestamp) ; + storage int ; + code { CAR + /* [ pair timestamp timestamp ] */ ; + DUP + /* [ pair timestamp timestamp : pair timestamp timestamp ] */ ; + CAR + /* [ timestamp : pair timestamp timestamp ] */ ; + DIP { CDR /* [ timestamp ] */ } + /* [ timestamp : timestamp ] */ ; + SUB + /* [ int ] */ ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039910.324 units remaining) michelson_test_scripts/opcodes/dig_eq.tz +{ parameter + (pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat) ; + storage unit ; + code { CAR + /* [ pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DUP + /* [ pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + UNPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAIR ; + DIG 0 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 1 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 2 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 3 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 4 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 5 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 6 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 7 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 8 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 9 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 10 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 11 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 12 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 13 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 14 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 15 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 16 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 0 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 1 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 2 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 3 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 4 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 5 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 6 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 7 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 8 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 9 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 10 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 11 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 12 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 13 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 14 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 15 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + DIG 16 + /* [ nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat : nat + : nat : nat : nat : nat + : pair nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat nat ] */ ; + PAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAIR ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039992.167 units remaining) michelson_test_scripts/opcodes/dign.tz +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR + /* [ pair (pair (pair (pair nat nat) nat) nat) nat ] */ ; + UNPAIR + /* [ pair (pair (pair nat nat) nat) nat : nat ] */ ; + UNPAIR + /* [ pair (pair nat nat) nat : nat : nat ] */ ; + UNPAIR + /* [ pair nat nat : nat : nat : nat ] */ ; + UNPAIR + /* [ nat : nat : nat : nat : nat ] */ ; + DIG 4 + /* [ nat : nat : nat : nat : nat ] */ ; + DIP { DROP /* [ nat : nat : nat ] */ ; DROP /* [ nat : nat ] */ ; DROP /* [ nat ] */ ; DROP /* [] */ } + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039995.095 units remaining) michelson_test_scripts/opcodes/dip.tz +{ parameter (pair nat nat) ; + storage (pair nat nat) ; + code { CAR + /* [ pair nat nat ] */ ; + UNPAIR + /* [ nat : nat ] */ ; + DUP + /* [ nat : nat : nat ] */ ; + DIP { ADD /* [ nat ] */ } + /* [ nat : nat ] */ ; + PAIR + /* [ pair nat nat ] */ ; + NIL operation + /* [ list operation : pair nat nat ] */ ; + PAIR + /* [ pair (list operation) nat nat ] */ } } +Well typed (Gas remaining: 1039991.417 units remaining) michelson_test_scripts/opcodes/dipn.tz +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR + /* [ pair (pair (pair (pair nat nat) nat) nat) nat ] */ ; + UNPAIR + /* [ pair (pair (pair nat nat) nat) nat : nat ] */ ; + UNPAIR + /* [ pair (pair nat nat) nat : nat : nat ] */ ; + UNPAIR + /* [ pair nat nat : nat : nat : nat ] */ ; + UNPAIR + /* [ nat : nat : nat : nat : nat ] */ ; + DIP 5 { PUSH nat 6 /* [ nat ] */ } + /* [ nat : nat : nat : nat : nat : nat ] */ ; + DROP + /* [ nat : nat : nat : nat : nat ] */ ; + DROP + /* [ nat : nat : nat : nat ] */ ; + DROP + /* [ nat : nat : nat ] */ ; + DROP + /* [ nat : nat ] */ ; + DROP + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039994.685 units remaining) michelson_test_scripts/opcodes/dropn.tz +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR + /* [ pair (pair (pair (pair nat nat) nat) nat) nat ] */ ; + UNPAIR + /* [ pair (pair (pair nat nat) nat) nat : nat ] */ ; + UNPAIR + /* [ pair (pair nat nat) nat : nat : nat ] */ ; + UNPAIR + /* [ pair nat nat : nat : nat : nat ] */ ; + UNPAIR + /* [ nat : nat : nat : nat : nat ] */ ; + DROP 4 + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039992.811 units remaining) michelson_test_scripts/opcodes/dugn.tz +{ parameter (pair (pair (pair (pair nat nat) nat) nat) nat) ; + storage nat ; + code { CAR + /* [ pair (pair (pair (pair nat nat) nat) nat) nat ] */ ; + UNPAIR + /* [ pair (pair (pair nat nat) nat) nat : nat ] */ ; + UNPAIR + /* [ pair (pair nat nat) nat : nat : nat ] */ ; + UNPAIR + /* [ pair nat nat : nat : nat : nat ] */ ; + UNPAIR + /* [ nat : nat : nat : nat : nat ] */ ; + DUG 4 + /* [ nat : nat : nat : nat : nat ] */ ; + DROP + /* [ nat : nat : nat : nat ] */ ; + DROP + /* [ nat : nat : nat ] */ ; + DROP + /* [ nat : nat ] */ ; + DROP + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039968.060 units remaining) michelson_test_scripts/opcodes/dup-n.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 5 + /* [ nat ] */ ; + PUSH nat 4 + /* [ nat : nat ] */ ; + PUSH nat 3 + /* [ nat : nat : nat ] */ ; + PUSH nat 2 + /* [ nat : nat : nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat : nat : nat ] */ ; + DUP 1 + /* [ nat : nat : nat : nat : nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat : nat : nat : nat : nat ] */ ; + ASSERT_CMPEQ ; + DUP 2 + /* [ nat : nat : nat : nat : nat : nat ] */ ; + PUSH nat 2 + /* [ nat : nat : nat : nat : nat : nat : nat ] */ ; + ASSERT_CMPEQ ; + DUP 3 + /* [ nat : nat : nat : nat : nat : nat ] */ ; + PUSH nat 3 + /* [ nat : nat : nat : nat : nat : nat : nat ] */ ; + ASSERT_CMPEQ ; + DUP 4 + /* [ nat : nat : nat : nat : nat : nat ] */ ; + PUSH nat 4 + /* [ nat : nat : nat : nat : nat : nat : nat ] */ ; + ASSERT_CMPEQ ; + DUP 5 + /* [ nat : nat : nat : nat : nat : nat ] */ ; + PUSH nat 5 + /* [ nat : nat : nat : nat : nat : nat : nat ] */ ; + ASSERT_CMPEQ ; + DROP 5 + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039982.466 units remaining) michelson_test_scripts/opcodes/ediv.tz +{ parameter (pair int int) ; + storage + (pair (option (pair int nat)) + (option (pair int nat)) + (option (pair int nat)) + (option (pair nat nat))) ; + code { CAR + /* [ pair int int ] */ ; + DUP + /* [ pair int int : pair int int ] */ ; + UNPAIR + /* [ int : int : pair int int ] */ ; + ABS + /* [ nat : int : pair int int ] */ ; + DIP { ABS /* [ nat : pair int int ] */ } + /* [ nat : nat : pair int int ] */ ; + EDIV + /* [ option (pair nat nat) : pair int int ] */ ; + SWAP + /* [ pair int int : option (pair nat nat) ] */ ; + DUP + /* [ pair int int : pair int int : option (pair nat nat) ] */ ; + UNPAIR + /* [ int : int : pair int int : option (pair nat nat) ] */ ; + ABS + /* [ nat : int : pair int int : option (pair nat nat) ] */ ; + EDIV + /* [ option (pair int nat) : pair int int : option (pair nat nat) ] */ ; + SWAP + /* [ pair int int : option (pair int nat) : option (pair nat nat) ] */ ; + DUP + /* [ pair int int : pair int int : option (pair int nat) + : option (pair nat nat) ] */ ; + UNPAIR + /* [ int : int : pair int int : option (pair int nat) : option (pair nat nat) ] */ ; + DIP { ABS + /* [ nat : pair int int : option (pair int nat) : option (pair nat nat) ] */ } + /* [ int : nat : pair int int : option (pair int nat) : option (pair nat nat) ] */ ; + EDIV + /* [ option (pair int nat) : pair int int : option (pair int nat) + : option (pair nat nat) ] */ ; + SWAP + /* [ pair int int : option (pair int nat) : option (pair int nat) + : option (pair nat nat) ] */ ; + UNPAIR + /* [ int : int : option (pair int nat) : option (pair int nat) + : option (pair nat nat) ] */ ; + EDIV + /* [ option (pair int nat) : option (pair int nat) : option (pair int nat) + : option (pair nat nat) ] */ ; + PAPAPAIR ; + NIL operation + /* [ list operation + : pair (option (pair int nat)) + (option (pair int nat)) + (option (pair int nat)) + (option (pair nat nat)) ] */ ; + PAIR + /* [ pair (list operation) + (option (pair int nat)) + (option (pair int nat)) + (option (pair int nat)) + (option (pair nat nat)) ] */ } } +Well typed (Gas remaining: 1039991.312 units remaining) michelson_test_scripts/opcodes/ediv_mutez.tz +{ parameter (pair mutez (or mutez nat)) ; + storage (or (option (pair nat mutez)) (option (pair mutez mutez))) ; + code { CAR + /* [ pair mutez (or mutez nat) ] */ ; + UNPAIR + /* [ mutez : or mutez nat ] */ ; + SWAP + /* [ or mutez nat : mutez ] */ ; + IF_LEFT + { SWAP + /* [ mutez : mutez ] */ ; + EDIV + /* [ option (pair nat mutez) ] */ ; + LEFT (option (pair mutez mutez)) + /* [ or (option (pair nat mutez)) (option (pair mutez mutez)) ] */ } + { SWAP + /* [ mutez : nat ] */ ; + EDIV + /* [ option (pair mutez mutez) ] */ ; + RIGHT + (option (pair nat mutez)) + /* [ or (option (pair nat mutez)) (option (pair mutez mutez)) ] */ } ; + NIL operation + /* [ list operation : or (option (pair nat mutez)) (option (pair mutez mutez)) ] */ ; + PAIR + /* [ pair (list operation) (or (option (pair nat mutez)) (option (pair mutez mutez))) ] */ } } +Well typed (Gas remaining: 1039991.081 units remaining) michelson_test_scripts/opcodes/emit.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + PUSH nat 10 + /* [ nat : unit ] */ ; + LEFT string + /* [ or nat string : unit ] */ ; + EMIT %event + /* [ operation : unit ] */ ; + PUSH string "lorem ipsum" + /* [ string : operation : unit ] */ ; + RIGHT nat + /* [ or nat string : operation : unit ] */ ; + EMIT %event (or (nat %number) (string %words)) + /* [ operation : operation : unit ] */ ; + NIL operation + /* [ list operation : operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : operation : unit ] */ ; + CONS + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039994.545 units remaining) michelson_test_scripts/opcodes/empty_map.tz +{ storage (map string string) ; + parameter unit ; + code { DROP + /* [] */ ; + EMPTY_MAP string string + /* [ map string string ] */ ; + PUSH string "world" + /* [ string : map string string ] */ ; + SOME + /* [ option string : map string string ] */ ; + PUSH string "hello" + /* [ string : option string : map string string ] */ ; + UPDATE + /* [ map string string ] */ ; + NIL operation + /* [ list operation : map string string ] */ ; + PAIR + /* [ pair (list operation) (map string string) ] */ } } +Well typed (Gas remaining: 1039992.485 units remaining) michelson_test_scripts/opcodes/exec_concat.tz +{ parameter string ; + storage string ; + code { CAR + /* [ string ] */ ; + LAMBDA + string + string + { PUSH string "_abc" + /* [ string : string ] */ ; + NIL string + /* [ list string : string : string ] */ ; + SWAP + /* [ string : list string : string ] */ ; + CONS + /* [ list string : string ] */ ; + SWAP + /* [ string : list string ] */ ; + CONS + /* [ list string ] */ ; + CONCAT + /* [ string ] */ } + /* [ lambda string string : string ] */ ; + SWAP + /* [ string : lambda string string ] */ ; + EXEC + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039989.486 units remaining) michelson_test_scripts/opcodes/fact.tz +{ parameter nat ; + storage nat ; + code { CAR + /* [ nat ] */ ; + LAMBDA_REC + nat + nat + { PUSH int -1 + /* [ int : nat : lambda nat nat ] */ ; + ADD + /* [ int : lambda nat nat ] */ ; + ISNAT + /* [ option nat : lambda nat nat ] */ ; + IF_NONE + { DROP /* [] */ ; PUSH nat 1 /* [ nat ] */ } + { DUP + /* [ nat : nat : lambda nat nat ] */ ; + DIP { EXEC /* [ nat ] */ } + /* [ nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat ] */ ; + ADD + /* [ nat : nat ] */ ; + MUL + /* [ nat ] */ } } + /* [ lambda nat nat : nat ] */ ; + SWAP + /* [ nat : lambda nat nat ] */ ; + EXEC + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039995.199 units remaining) michelson_test_scripts/opcodes/first.tz +{ parameter (list nat) ; + storage nat ; + code { CAR + /* [ list nat ] */ ; + IF_CONS { DIP { DROP /* [] */ } /* [ nat ] */ } { FAIL } ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039995.086 units remaining) michelson_test_scripts/opcodes/get_and_update_big_map.tz +{ parameter string ; + storage (pair (option nat) (big_map string nat)) ; + code { UNPAPAIR ; + GET_AND_UPDATE + /* [ option nat : big_map string nat ] */ ; + PAIR + /* [ pair (option nat) (big_map string nat) ] */ ; + NIL operation + /* [ list operation : pair (option nat) (big_map string nat) ] */ ; + PAIR + /* [ pair (list operation) (option nat) (big_map string nat) ] */ } } +Well typed (Gas remaining: 1039995.146 units remaining) michelson_test_scripts/opcodes/get_and_update_map.tz +{ parameter string ; + storage (pair (option nat) (map string nat)) ; + code { UNPAPAIR ; + GET_AND_UPDATE + /* [ option nat : map string nat ] */ ; + PAIR + /* [ pair (option nat) (map string nat) ] */ ; + NIL operation + /* [ list operation : pair (option nat) (map string nat) ] */ ; + PAIR + /* [ pair (list operation) (option nat) (map string nat) ] */ } } +Well typed (Gas remaining: 1039992.369 units remaining) michelson_test_scripts/opcodes/get_big_map_value.tz +{ parameter string ; + storage (pair (big_map string string) (option string)) ; + code { DUP + /* [ pair string (big_map string string) (option string) + : pair string (big_map string string) (option string) ] */ ; + CAR + /* [ string : pair string (big_map string string) (option string) ] */ ; + DIP { CDAR ; DUP /* [ big_map string string : big_map string string ] */ } + /* [ string : big_map string string : big_map string string ] */ ; + GET + /* [ option string : big_map string string ] */ ; + SWAP + /* [ big_map string string : option string ] */ ; + PAIR + /* [ pair (big_map string string) (option string) ] */ ; + NIL operation + /* [ list operation : pair (big_map string string) (option string) ] */ ; + PAIR + /* [ pair (list operation) (big_map string string) (option string) ] */ } } +Well typed (Gas remaining: 1039992.898 units remaining) michelson_test_scripts/opcodes/get_map_value.tz +{ parameter string ; + storage (pair (option string) (map string string)) ; + code { DUP + /* [ pair string (option string) (map string string) + : pair string (option string) (map string string) ] */ ; + CAR + /* [ string : pair string (option string) (map string string) ] */ ; + DIP { CDDR ; DUP /* [ map string string : map string string ] */ } + /* [ string : map string string : map string string ] */ ; + GET + /* [ option string : map string string ] */ ; + PAIR + /* [ pair (option string) (map string string) ] */ ; + NIL operation + /* [ list operation : pair (option string) (map string string) ] */ ; + PAIR + /* [ pair (list operation) (option string) (map string string) ] */ } } +Well typed (Gas remaining: 1039996.673 units remaining) michelson_test_scripts/opcodes/hash_consistency_checker.tz +{ parameter (pair mutez (pair timestamp int)) ; + storage bytes ; + code { CAR + /* [ pair mutez timestamp int ] */ ; + PACK + /* [ bytes ] */ ; + BLAKE2B + /* [ bytes ] */ ; + NIL operation + /* [ list operation : bytes ] */ ; + PAIR + /* [ pair (list operation) bytes ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/hash_key.tz +{ parameter key ; + storage (option key_hash) ; + code { CAR + /* [ key ] */ ; + HASH_KEY + /* [ key_hash ] */ ; + SOME + /* [ option key_hash ] */ ; + NIL operation + /* [ list operation : option key_hash ] */ ; + PAIR + /* [ pair (list operation) (option key_hash) ] */ } } +Well typed (Gas remaining: 1039997.089 units remaining) michelson_test_scripts/opcodes/hash_string.tz +{ parameter string ; + storage bytes ; + code { CAR + /* [ string ] */ ; + PACK + /* [ bytes ] */ ; + BLAKE2B + /* [ bytes ] */ ; + NIL operation + /* [ list operation : bytes ] */ ; + PAIR + /* [ pair (list operation) bytes ] */ } } +Well typed (Gas remaining: 1039995.431 units remaining) michelson_test_scripts/opcodes/if.tz +{ parameter bool ; + storage (option bool) ; + code { CAR + /* [ bool ] */ ; + IF { PUSH bool True /* [ bool ] */ } { PUSH bool False /* [ bool ] */ } ; + SOME + /* [ option bool ] */ ; + NIL operation + /* [ list operation : option bool ] */ ; + PAIR + /* [ pair (list operation) (option bool) ] */ } } +Well typed (Gas remaining: 1039996.124 units remaining) michelson_test_scripts/opcodes/if_some.tz +{ parameter (option string) ; + storage string ; + code { CAR + /* [ option string ] */ ; + IF_SOME { /* [ string ] */ } { PUSH string "" /* [ string ] */ } ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/int.tz +{ parameter nat ; + storage (option int) ; + code { CAR + /* [ nat ] */ ; + INT + /* [ int ] */ ; + SOME + /* [ option int ] */ ; + NIL operation + /* [ list operation : option int ] */ ; + PAIR + /* [ pair (list operation) (option int) ] */ } } +Well typed (Gas remaining: 1039996.910 units remaining) michelson_test_scripts/opcodes/iter_fail.tz +{ parameter (set nat) ; + storage unit ; + code { UNPAIR + /* [ set nat : unit ] */ ; + ITER { FAILWITH /* [] */ } + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/keccak.tz +{ storage (option bytes) ; + parameter bytes ; + code { CAR + /* [ bytes ] */ ; + KECCAK + /* [ bytes ] */ ; + SOME + /* [ option bytes ] */ ; + NIL operation + /* [ list operation : option bytes ] */ ; + PAIR + /* [ pair (list operation) (option bytes) ] */ } } +Well typed (Gas remaining: 1039995.825 units remaining) michelson_test_scripts/opcodes/left_right.tz +{ parameter (or bool string) ; + storage (or string bool) ; + code { CAR + /* [ or bool string ] */ ; + IF_LEFT + { RIGHT string /* [ or string bool ] */ } + { LEFT bool /* [ or string bool ] */ } ; + NIL operation + /* [ list operation : or string bool ] */ ; + PAIR + /* [ pair (list operation) (or string bool) ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/level.tz +{ parameter unit ; + storage nat ; + code { DROP + /* [] */ ; + LEVEL + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039996.413 units remaining) michelson_test_scripts/opcodes/list_concat.tz +{ parameter (list string) ; + storage string ; + code { UNPAIR + /* [ list string : string ] */ ; + SWAP + /* [ string : list string ] */ ; + CONS + /* [ list string ] */ ; + CONCAT + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039996.413 units remaining) michelson_test_scripts/opcodes/list_concat_bytes.tz +{ parameter (list bytes) ; + storage bytes ; + code { UNPAIR + /* [ list bytes : bytes ] */ ; + SWAP + /* [ bytes : list bytes ] */ ; + CONS + /* [ list bytes ] */ ; + CONCAT + /* [ bytes ] */ ; + NIL operation + /* [ list operation : bytes ] */ ; + PAIR + /* [ pair (list operation) bytes ] */ } } +Well typed (Gas remaining: 1039997.827 units remaining) michelson_test_scripts/opcodes/list_id.tz +{ parameter (list string) ; + storage (list string) ; + code { CAR + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039997.048 units remaining) michelson_test_scripts/opcodes/list_id_map.tz +{ parameter (list string) ; + storage (list string) ; + code { CAR + /* [ list string ] */ ; + MAP { /* [ string ] */ } + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039995.699 units remaining) michelson_test_scripts/opcodes/list_iter.tz +{ parameter (list int) ; + storage int ; + code { CAR + /* [ list int ] */ ; + PUSH int 1 + /* [ int : list int ] */ ; + SWAP + /* [ list int : int ] */ ; + ITER { MUL /* [ int ] */ } + /* [ int ] */ ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039991.754 units remaining) michelson_test_scripts/opcodes/list_map_block.tz +{ parameter (list int) ; + storage (list int) ; + code { CAR + /* [ list int ] */ ; + PUSH int 0 + /* [ int : list int ] */ ; + SWAP + /* [ list int : int ] */ ; + MAP { DIP { DUP /* [ int : int ] */ } + /* [ int : int : int ] */ ; + ADD + /* [ int : int ] */ ; + DIP { PUSH int 1 /* [ int : int ] */ ; ADD /* [ int ] */ } + /* [ int : int ] */ } + /* [ list int : int ] */ ; + NIL operation + /* [ list operation : list int : int ] */ ; + PAIR + /* [ pair (list operation) (list int) : int ] */ ; + DIP { DROP /* [] */ } + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039997.469 units remaining) michelson_test_scripts/opcodes/list_size.tz +{ parameter (list int) ; + storage nat ; + code { CAR + /* [ list int ] */ ; + SIZE + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039997.065 units remaining) michelson_test_scripts/opcodes/loop_failwith.tz +{ parameter bool ; + storage unit ; + code { UNPAIR + /* [ bool : unit ] */ ; + LOOP { FAILWITH /* [] */ } + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039988.053 units remaining) michelson_test_scripts/opcodes/loop_left.tz +{ parameter (list string) ; + storage (list string) ; + code { CAR + /* [ list string ] */ ; + NIL string + /* [ list string : list string ] */ ; + SWAP + /* [ list string : list string ] */ ; + PAIR + /* [ pair (list string) (list string) ] */ ; + LEFT (list string) + /* [ or (pair (list string) (list string)) (list string) ] */ ; + LOOP_LEFT + { DUP + /* [ pair (list string) (list string) : pair (list string) (list string) ] */ ; + CAR + /* [ list string : pair (list string) (list string) ] */ ; + DIP { CDR /* [ list string ] */ } + /* [ list string : list string ] */ ; + IF_CONS + { SWAP + /* [ list string : string : list string ] */ ; + DIP { CONS /* [ list string ] */ } + /* [ list string : list string ] */ ; + PAIR + /* [ pair (list string) (list string) ] */ ; + LEFT (list string) + /* [ or (pair (list string) (list string)) (list string) ] */ } + { RIGHT + (pair (list string) (list string)) + /* [ or (pair (list string) (list string)) (list string) ] */ } } + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039996.821 units remaining) michelson_test_scripts/opcodes/loop_left_failwith.tz +{ parameter (or string nat) ; + storage nat ; + code { CAR + /* [ or string nat ] */ ; + LOOP_LEFT { FAILWITH /* [] */ } + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039972.833 units remaining) michelson_test_scripts/opcodes/lsl_bytes_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 0 + /* [ nat ] */ ; + PUSH bytes 0x06 + /* [ bytes : nat ] */ ; + LSL + /* [ bytes ] */ ; + PUSH bytes 0x06 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 1 + /* [ nat ] */ ; + PUSH bytes 0x06 + /* [ bytes : nat ] */ ; + LSL + /* [ bytes ] */ ; + PUSH bytes 0x000c + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 8 + /* [ nat ] */ ; + PUSH bytes 0x06 + /* [ bytes : nat ] */ ; + LSL + /* [ bytes ] */ ; + PUSH bytes 0x0600 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 1 + /* [ nat ] */ ; + PUSH bytes 0x0006 + /* [ bytes : nat ] */ ; + LSL + /* [ bytes ] */ ; + PUSH bytes 0x00000c + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039959.932 units remaining) michelson_test_scripts/opcodes/lsr_bytes_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH nat 1 + /* [ nat ] */ ; + PUSH bytes 0x06 + /* [ bytes : nat ] */ ; + LSR + /* [ bytes ] */ ; + PUSH bytes 0x03 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 8 + /* [ nat ] */ ; + PUSH bytes 0x06 + /* [ bytes : nat ] */ ; + LSR + /* [ bytes ] */ ; + PUSH bytes 0x + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 1 + /* [ nat ] */ ; + PUSH bytes 0x0006 + /* [ bytes : nat ] */ ; + LSR + /* [ bytes ] */ ; + PUSH bytes 0x0003 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 8 + /* [ nat ] */ ; + PUSH bytes 0x0006 + /* [ bytes : nat ] */ ; + LSR + /* [ bytes ] */ ; + PUSH bytes 0x00 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 0 + /* [ nat ] */ ; + PUSH bytes 0x001234 + /* [ bytes : nat ] */ ; + LSR + /* [ bytes ] */ ; + PUSH bytes 0x001234 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH nat 30 + /* [ nat ] */ ; + PUSH bytes 0x001234 + /* [ bytes : nat ] */ ; + LSR + /* [ bytes ] */ ; + PUSH bytes 0x + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039991.235 units remaining) michelson_test_scripts/opcodes/map_car.tz +{ parameter bool ; + storage (pair (bool %b) (nat %n)) ; + code { DUP + /* [ pair bool bool nat : pair bool bool nat ] */ ; + CAR + /* [ bool : pair bool bool nat ] */ ; + DIP { CDR /* [ pair bool nat ] */ } + /* [ bool : pair bool nat ] */ ; + SWAP + /* [ pair bool nat : bool ] */ ; + MAP_CAR @new_storage %b { AND /* [ bool ] */ } ; + NIL operation + /* [ list operation : pair bool nat ] */ ; + PAIR + /* [ pair (list operation) bool nat ] */ } } +Well typed (Gas remaining: 1039997.566 units remaining) michelson_test_scripts/opcodes/map_id.tz +{ parameter (map nat nat) ; + storage (map nat nat) ; + code { CAR + /* [ map nat nat ] */ ; + NIL operation + /* [ list operation : map nat nat ] */ ; + PAIR + /* [ pair (list operation) (map nat nat) ] */ } } +Well typed (Gas remaining: 1039987.183 units remaining) michelson_test_scripts/opcodes/map_iter.tz +{ parameter (map (int :k) (int :e)) ; + storage (pair (int :k) (int :e)) ; + code { CAR + /* [ map int int ] */ ; + PUSH @acc_e (int :e) 0 + /* [ int : map int int ] */ ; + PUSH @acc_k (int :k) 0 + /* [ int : int : map int int ] */ ; + PAIR % %r + /* [ pair int int : map int int ] */ ; + SWAP + /* [ map int int : pair int int ] */ ; + ITER { DIP { DUP + /* [ pair int int : pair int int ] */ ; + CAR + /* [ int : pair int int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ int : int ] */ } + /* [ pair int int : int : int ] */ ; + DUP + /* [ pair int int : pair int int : int : int ] */ ; + DIP { CAR /* [ int : int : int ] */ ; ADD /* [ int : int ] */ } + /* [ pair int int : int : int ] */ ; + SWAP + /* [ int : pair int int : int ] */ ; + DIP { CDR /* [ int : int ] */ ; ADD /* [ int ] */ } + /* [ int : int ] */ ; + PAIR % %r + /* [ pair int int ] */ } + /* [ pair int int ] */ ; + NIL operation + /* [ list operation : pair int int ] */ ; + PAIR + /* [ pair (list operation) int int ] */ } } +Well typed (Gas remaining: 1039993.752 units remaining) michelson_test_scripts/opcodes/map_map.tz +{ parameter nat ; + storage (map string nat) ; + code { UNPAIR + /* [ nat : map string nat ] */ ; + SWAP + /* [ map string nat : nat ] */ ; + MAP { CDR + /* [ nat : nat ] */ ; + DIP { DUP /* [ nat : nat ] */ } + /* [ nat : nat : nat ] */ ; + ADD + /* [ nat : nat ] */ } + /* [ map string nat : nat ] */ ; + DIP { DROP /* [] */ } + /* [ map string nat ] */ ; + NIL operation + /* [ list operation : map string nat ] */ ; + PAIR + /* [ pair (list operation) (map string nat) ] */ } } +Well typed (Gas remaining: 1039988.773 units remaining) michelson_test_scripts/opcodes/map_map_sideeffect.tz +{ parameter nat ; + storage (pair (map string nat) nat) ; + code { UNPAIR + /* [ nat : pair (map string nat) nat ] */ ; + SWAP + /* [ pair (map string nat) nat : nat ] */ ; + CAR + /* [ map string nat : nat ] */ ; + DIP 2 { PUSH @sum nat 0 /* [ nat ] */ } + /* [ map string nat : nat : nat ] */ ; + MAP { CDR + /* [ nat : nat : nat ] */ ; + DIP { DUP /* [ nat : nat : nat ] */ } + /* [ nat : nat : nat : nat ] */ ; + ADD + /* [ nat : nat : nat ] */ ; + DUP + /* [ nat : nat : nat : nat ] */ ; + DUG 2 + /* [ nat : nat : nat : nat ] */ ; + DIP 2 { ADD @sum /* [ nat ] */ } + /* [ nat : nat : nat ] */ } + /* [ map string nat : nat : nat ] */ ; + DIP { DROP /* [ nat ] */ } + /* [ map string nat : nat ] */ ; + PAIR + /* [ pair (map string nat) nat ] */ ; + NIL operation + /* [ list operation : pair (map string nat) nat ] */ ; + PAIR + /* [ pair (list operation) (map string nat) nat ] */ } } +Well typed (Gas remaining: 1039993.846 units remaining) michelson_test_scripts/opcodes/map_mem_nat.tz +{ parameter nat ; + storage (pair (map nat nat) (option bool)) ; + code { UNPAIR + /* [ nat : pair (map nat nat) (option bool) ] */ ; + DIP { CAR /* [ map nat nat ] */ ; DUP /* [ map nat nat : map nat nat ] */ } + /* [ nat : map nat nat : map nat nat ] */ ; + MEM + /* [ bool : map nat nat ] */ ; + SOME + /* [ option bool : map nat nat ] */ ; + SWAP + /* [ map nat nat : option bool ] */ ; + PAIR + /* [ pair (map nat nat) (option bool) ] */ ; + NIL operation + /* [ list operation : pair (map nat nat) (option bool) ] */ ; + PAIR + /* [ pair (list operation) (map nat nat) (option bool) ] */ } } +Well typed (Gas remaining: 1039993.846 units remaining) michelson_test_scripts/opcodes/map_mem_string.tz +{ parameter string ; + storage (pair (map string nat) (option bool)) ; + code { UNPAIR + /* [ string : pair (map string nat) (option bool) ] */ ; + DIP { CAR /* [ map string nat ] */ ; DUP /* [ map string nat : map string nat ] */ } + /* [ string : map string nat : map string nat ] */ ; + MEM + /* [ bool : map string nat ] */ ; + SOME + /* [ option bool : map string nat ] */ ; + SWAP + /* [ map string nat : option bool ] */ ; + PAIR + /* [ pair (map string nat) (option bool) ] */ ; + NIL operation + /* [ list operation : pair (map string nat) (option bool) ] */ ; + PAIR + /* [ pair (list operation) (map string nat) (option bool) ] */ } } +Well typed (Gas remaining: 1039997.385 units remaining) michelson_test_scripts/opcodes/map_size.tz +{ parameter (map string nat) ; + storage nat ; + code { CAR + /* [ map string nat ] */ ; + SIZE + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039992.457 units remaining) michelson_test_scripts/opcodes/merge_comparable_pairs.tz +{ parameter (set (pair (nat %n) (pair %p (string %s) (int %i)))) ; + storage nat ; + code { UNPAIR + /* [ set (pair nat string int) : nat ] */ ; + SWAP + /* [ nat : set (pair nat string int) ] */ ; + PUSH nat 3 + /* [ nat : nat : set (pair nat string int) ] */ ; + COMPARE + /* [ int : set (pair nat string int) ] */ ; + GT + /* [ bool : set (pair nat string int) ] */ ; + IF { /* [ set (pair nat string int) ] */ } + { DROP + /* [] */ ; + EMPTY_SET (pair nat (pair string int)) + /* [ set (pair nat string int) ] */ } ; + SIZE + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039961.027 units remaining) michelson_test_scripts/opcodes/mul.tz +{ parameter unit ; + storage unit ; + code { CAR + /* [ unit ] */ ; + DROP + /* [] */ ; + PUSH nat 7987 + /* [ nat ] */ ; + PUSH mutez 10 + /* [ mutez : nat ] */ ; + MUL + /* [ mutez ] */ ; + PUSH mutez 79870 + /* [ mutez : mutez ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH mutez 10 + /* [ mutez ] */ ; + PUSH nat 7987 + /* [ nat : mutez ] */ ; + MUL + /* [ mutez ] */ ; + PUSH mutez 79870 + /* [ mutez : mutez ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH int 10 + /* [ int ] */ ; + PUSH int -7987 + /* [ int : int ] */ ; + MUL + /* [ int ] */ ; + PUSH int -79870 + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH nat 10 + /* [ nat ] */ ; + PUSH int -7987 + /* [ int : nat ] */ ; + MUL + /* [ int ] */ ; + PUSH int -79870 + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH int -10 + /* [ int ] */ ; + PUSH nat 7987 + /* [ nat : int ] */ ; + MUL + /* [ int ] */ ; + PUSH int -79870 + /* [ int : int ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + PUSH nat 10 + /* [ nat ] */ ; + PUSH nat 7987 + /* [ nat : nat ] */ ; + MUL + /* [ nat ] */ ; + PUSH nat 79870 + /* [ nat : nat ] */ ; + COMPARE + /* [ int ] */ ; + ASSERT_EQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/mul_bls12_381_fr.tz +{ parameter (pair bls12_381_fr bls12_381_fr) ; + storage (option bls12_381_fr) ; + code { CAR + /* [ pair bls12_381_fr bls12_381_fr ] */ ; + UNPAIR + /* [ bls12_381_fr : bls12_381_fr ] */ ; + MUL + /* [ bls12_381_fr ] */ ; + SOME + /* [ option bls12_381_fr ] */ ; + NIL operation + /* [ list operation : option bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_fr) ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/mul_bls12_381_g1.tz +{ parameter (pair bls12_381_g1 bls12_381_fr) ; + storage (option bls12_381_g1) ; + code { CAR + /* [ pair bls12_381_g1 bls12_381_fr ] */ ; + UNPAIR + /* [ bls12_381_g1 : bls12_381_fr ] */ ; + MUL + /* [ bls12_381_g1 ] */ ; + SOME + /* [ option bls12_381_g1 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g1 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g1) ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/mul_bls12_381_g2.tz +{ parameter (pair bls12_381_g2 bls12_381_fr) ; + storage (option bls12_381_g2) ; + code { CAR + /* [ pair bls12_381_g2 bls12_381_fr ] */ ; + UNPAIR + /* [ bls12_381_g2 : bls12_381_fr ] */ ; + MUL + /* [ bls12_381_g2 ] */ ; + SOME + /* [ option bls12_381_g2 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g2 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g2) ] */ } } +Well typed (Gas remaining: 1039992.436 units remaining) michelson_test_scripts/opcodes/mul_overflow.tz +{ parameter (or unit unit) ; + storage unit ; + code { CAR + /* [ or unit unit ] */ ; + IF_LEFT + { PUSH nat 922337203685477580700 + /* [ nat : unit ] */ ; + PUSH mutez 10 + /* [ mutez : nat : unit ] */ ; + MUL + /* [ mutez : unit ] */ ; + DROP + /* [ unit ] */ } + { PUSH mutez 10 + /* [ mutez : unit ] */ ; + PUSH nat 922337203685477580700 + /* [ nat : mutez : unit ] */ ; + MUL + /* [ mutez : unit ] */ ; + DROP + /* [ unit ] */ } ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.167 units remaining) michelson_test_scripts/opcodes/munch.tz +{ parameter + (or (bytes %bytes) (or (lambda %lambda unit unit) (or (nat %nat) (list %list_nat nat)))) ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039992.419 units remaining) michelson_test_scripts/opcodes/mutez_to_bls12_381_fr.tz +{ parameter mutez ; + storage bls12_381_fr ; + code { CAR + /* [ mutez ] */ ; + PUSH mutez 1 + /* [ mutez : mutez ] */ ; + SWAP + /* [ mutez : mutez ] */ ; + EDIV + /* [ option (pair nat mutez) ] */ ; + ASSERT_SOME ; + CAR + /* [ nat ] */ ; + PUSH bls12_381_fr 1 + /* [ bls12_381_fr : nat ] */ ; + MUL + /* [ bls12_381_fr ] */ ; + NIL operation + /* [ list operation : bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) bls12_381_fr ] */ } } +Well typed (Gas remaining: 1039996.267 units remaining) michelson_test_scripts/opcodes/neg.tz +{ parameter (or int nat) ; + storage int ; + code { CAR + /* [ or int nat ] */ ; + IF_LEFT { NEG /* [ int ] */ } { NEG /* [ int ] */ } ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/neg_bls12_381_fr.tz +{ parameter bls12_381_fr ; + storage (option bls12_381_fr) ; + code { CAR + /* [ bls12_381_fr ] */ ; + NEG + /* [ bls12_381_fr ] */ ; + SOME + /* [ option bls12_381_fr ] */ ; + NIL operation + /* [ list operation : option bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_fr) ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/neg_bls12_381_g1.tz +{ parameter bls12_381_g1 ; + storage (option bls12_381_g1) ; + code { CAR + /* [ bls12_381_g1 ] */ ; + NEG + /* [ bls12_381_g1 ] */ ; + SOME + /* [ option bls12_381_g1 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g1 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g1) ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/neg_bls12_381_g2.tz +{ parameter bls12_381_g2 ; + storage (option bls12_381_g2) ; + code { CAR + /* [ bls12_381_g2 ] */ ; + NEG + /* [ bls12_381_g2 ] */ ; + SOME + /* [ option bls12_381_g2 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g2 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g2) ] */ } } +Well typed (Gas remaining: 1039997.363 units remaining) michelson_test_scripts/opcodes/none.tz +{ parameter unit ; + storage (option nat) ; + code { DROP + /* [] */ ; + NONE nat + /* [ option nat ] */ ; + NIL operation + /* [ list operation : option nat ] */ ; + PAIR + /* [ pair (list operation) (option nat) ] */ } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/opcodes/noop.tz +{ parameter unit ; + storage unit ; + code { CDR + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/not.tz +{ parameter bool ; + storage (option bool) ; + code { CAR + /* [ bool ] */ ; + NOT + /* [ bool ] */ ; + SOME + /* [ option bool ] */ ; + NIL operation + /* [ list operation : option bool ] */ ; + PAIR + /* [ pair (list operation) (option bool) ] */ } } +Well typed (Gas remaining: 1039995.688 units remaining) michelson_test_scripts/opcodes/not_binary.tz +{ parameter (or int nat) ; + storage (option int) ; + code { CAR + /* [ or int nat ] */ ; + IF_LEFT { NOT /* [ int ] */ } { NOT /* [ int ] */ } ; + SOME + /* [ option int ] */ ; + NIL operation + /* [ list operation : option int ] */ ; + PAIR + /* [ pair (list operation) (option int) ] */ } } +Well typed (Gas remaining: 1039981.112 units remaining) michelson_test_scripts/opcodes/not_bytes_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + NOT + /* [ bytes ] */ ; + PUSH bytes 0xfa + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0005 + /* [ bytes ] */ ; + NOT + /* [ bytes ] */ ; + PUSH bytes 0xfffa + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0xff05 + /* [ bytes ] */ ; + NOT + /* [ bytes ] */ ; + PUSH bytes 0x00fa + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039994.565 units remaining) michelson_test_scripts/opcodes/or.tz +{ parameter (pair bool bool) ; + storage (option bool) ; + code { CAR + /* [ pair bool bool ] */ ; + DUP + /* [ pair bool bool : pair bool bool ] */ ; + CAR + /* [ bool : pair bool bool ] */ ; + SWAP + /* [ pair bool bool : bool ] */ ; + CDR + /* [ bool : bool ] */ ; + OR + /* [ bool ] */ ; + SOME + /* [ option bool ] */ ; + NIL operation + /* [ list operation : option bool ] */ ; + PAIR + /* [ pair (list operation) (option bool) ] */ } } +Well typed (Gas remaining: 1039996.271 units remaining) michelson_test_scripts/opcodes/or_binary.tz +{ parameter (pair nat nat) ; + storage (option nat) ; + code { CAR + /* [ pair nat nat ] */ ; + UNPAIR + /* [ nat : nat ] */ ; + OR + /* [ nat ] */ ; + SOME + /* [ option nat ] */ ; + NIL operation + /* [ list operation : option nat ] */ ; + PAIR + /* [ pair (list operation) (option nat) ] */ } } +Well typed (Gas remaining: 1039978.970 units remaining) michelson_test_scripts/opcodes/or_bytes_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + PUSH bytes 0x06 + /* [ bytes : bytes ] */ ; + OR + /* [ bytes ] */ ; + PUSH bytes 0x07 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0005 + /* [ bytes ] */ ; + PUSH bytes 0x0106 + /* [ bytes : bytes ] */ ; + OR + /* [ bytes ] */ ; + PUSH bytes 0x0107 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + PUSH bytes 0x0106 + /* [ bytes : bytes ] */ ; + OR + /* [ bytes ] */ ; + PUSH bytes 0x0107 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.446 units remaining) michelson_test_scripts/opcodes/originate_big_map.tz +{ parameter (big_map int int) ; + storage (big_map int int) ; + code { CAR + /* [ big_map int int ] */ ; + NIL operation + /* [ list operation : big_map int int ] */ ; + PAIR + /* [ pair (list operation) (big_map int int) ] */ } } +Well typed (Gas remaining: 1039987.385 units remaining) michelson_test_scripts/opcodes/packunpack.tz +{ parameter (pair (pair (pair string (list int)) (set nat)) bytes) ; + storage unit ; + code { CAR + /* [ pair (pair (pair string (list int)) (set nat)) bytes ] */ ; + UNPAIR + /* [ pair (pair string (list int)) (set nat) : bytes ] */ ; + DIP { DUP /* [ bytes : bytes ] */ } + /* [ pair (pair string (list int)) (set nat) : bytes : bytes ] */ ; + PACK + /* [ bytes : bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNPACK + (pair (pair string (list int)) (set nat)) + /* [ option (pair (pair string (list int)) (set nat)) ] */ ; + ASSERT_SOME ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039888.537 units remaining) michelson_test_scripts/opcodes/packunpack_rev.tz +{ parameter (pair int nat string bytes mutez bool key_hash timestamp address) ; + storage unit ; + code { CAR + /* [ pair int nat string bytes mutez bool key_hash timestamp address ] */ ; + DUP + /* [ pair int nat string bytes mutez bool key_hash timestamp address + : pair int nat string bytes mutez bool key_hash timestamp address ] */ ; + CAR + /* [ int : pair int nat string bytes mutez bool key_hash timestamp address ] */ ; + DIP { UNPAIR + /* [ int : pair nat string bytes mutez bool key_hash timestamp address ] */ } + /* [ int : int : pair nat string bytes mutez bool key_hash timestamp address ] */ ; + PACK + /* [ bytes : int : pair nat string bytes mutez bool key_hash timestamp address ] */ ; + UNPACK + int + /* [ option int : int + : pair nat string bytes mutez bool key_hash timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair nat string bytes mutez bool key_hash timestamp address + : pair nat string bytes mutez bool key_hash timestamp address ] */ ; + CAR + /* [ nat : pair nat string bytes mutez bool key_hash timestamp address ] */ ; + DIP { UNPAIR /* [ nat : pair string bytes mutez bool key_hash timestamp address ] */ } + /* [ nat : nat : pair string bytes mutez bool key_hash timestamp address ] */ ; + PACK + /* [ bytes : nat : pair string bytes mutez bool key_hash timestamp address ] */ ; + UNPACK + nat + /* [ option nat : nat + : pair string bytes mutez bool key_hash timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair string bytes mutez bool key_hash timestamp address + : pair string bytes mutez bool key_hash timestamp address ] */ ; + CAR + /* [ string : pair string bytes mutez bool key_hash timestamp address ] */ ; + DIP { UNPAIR /* [ string : pair bytes mutez bool key_hash timestamp address ] */ } + /* [ string : string : pair bytes mutez bool key_hash timestamp address ] */ ; + PACK + /* [ bytes : string : pair bytes mutez bool key_hash timestamp address ] */ ; + UNPACK + string + /* [ option string : string : pair bytes mutez bool key_hash timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair bytes mutez bool key_hash timestamp address + : pair bytes mutez bool key_hash timestamp address ] */ ; + CAR + /* [ bytes : pair bytes mutez bool key_hash timestamp address ] */ ; + DIP { UNPAIR /* [ bytes : pair mutez bool key_hash timestamp address ] */ } + /* [ bytes : bytes : pair mutez bool key_hash timestamp address ] */ ; + PACK + /* [ bytes : bytes : pair mutez bool key_hash timestamp address ] */ ; + UNPACK + bytes + /* [ option bytes : bytes : pair mutez bool key_hash timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair mutez bool key_hash timestamp address + : pair mutez bool key_hash timestamp address ] */ ; + CAR + /* [ mutez : pair mutez bool key_hash timestamp address ] */ ; + DIP { UNPAIR /* [ mutez : pair bool key_hash timestamp address ] */ } + /* [ mutez : mutez : pair bool key_hash timestamp address ] */ ; + PACK + /* [ bytes : mutez : pair bool key_hash timestamp address ] */ ; + UNPACK mutez + /* [ option mutez : mutez : pair bool key_hash timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair bool key_hash timestamp address + : pair bool key_hash timestamp address ] */ ; + CAR + /* [ bool : pair bool key_hash timestamp address ] */ ; + DIP { UNPAIR /* [ bool : pair key_hash timestamp address ] */ } + /* [ bool : bool : pair key_hash timestamp address ] */ ; + PACK + /* [ bytes : bool : pair key_hash timestamp address ] */ ; + UNPACK bool + /* [ option bool : bool : pair key_hash timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair key_hash timestamp address : pair key_hash timestamp address ] */ ; + CAR + /* [ key_hash : pair key_hash timestamp address ] */ ; + DIP { UNPAIR /* [ key_hash : pair timestamp address ] */ } + /* [ key_hash : key_hash : pair timestamp address ] */ ; + PACK + /* [ bytes : key_hash : pair timestamp address ] */ ; + UNPACK key_hash + /* [ option key_hash : key_hash : pair timestamp address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ pair timestamp address : pair timestamp address ] */ ; + CAR + /* [ timestamp : pair timestamp address ] */ ; + DIP { UNPAIR /* [ timestamp : address ] */ } + /* [ timestamp : timestamp : address ] */ ; + PACK + /* [ bytes : timestamp : address ] */ ; + UNPACK timestamp + /* [ option timestamp : timestamp : address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + DUP + /* [ address : address ] */ ; + PACK + /* [ bytes : address ] */ ; + UNPACK address + /* [ option address : address ] */ ; + ASSERT_SOME ; + ASSERT_CMPEQ ; + PUSH int 0 + /* [ int ] */ ; + PACK + /* [ bytes ] */ ; + UNPACK nat + /* [ option nat ] */ ; + ASSERT_SOME ; + DROP + /* [] */ ; + PUSH int -1 + /* [ int ] */ ; + PACK + /* [ bytes ] */ ; + UNPACK nat + /* [ option nat ] */ ; + ASSERT_NONE ; + PUSH bytes 0x + /* [ bytes ] */ ; + UNPACK nat + /* [ option nat ] */ ; + ASSERT_NONE ; + PUSH bytes 0x04 + /* [ bytes ] */ ; + UNPACK nat + /* [ option nat ] */ ; + ASSERT_NONE ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + UNPACK nat + /* [ option nat ] */ ; + ASSERT_NONE ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039874.912 units remaining) michelson_test_scripts/opcodes/packunpack_rev_cty.tz +{ parameter + (pair key + unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes)) ; + storage unit ; + code { CAR + /* [ pair key + unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DUP + /* [ pair key + unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) + : pair key + unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + CAR + /* [ key + : pair key + unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ key + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ key : key + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + PACK + /* [ bytes : key + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + UNPACK + key + /* [ option key + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + CAR + /* [ unit + : pair unit + signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ unit + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ unit : unit + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + PACK + /* [ bytes : unit + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + UNPACK + unit + /* [ option unit + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + CAR + /* [ signature + : pair signature + (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ signature + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ signature : signature + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + PACK + /* [ bytes : signature + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + UNPACK + signature + /* [ option signature + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + CAR + /* [ option signature + : pair (option signature) + (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ option signature + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ option signature : option signature + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + PACK + /* [ bytes : option signature + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + UNPACK + (option signature) + /* [ option (option signature) + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + CAR + /* [ list unit + : pair (list unit) + (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ list unit + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ list unit : list unit + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + PACK + /* [ bytes : list unit + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + UNPACK + (list unit) + /* [ option (list unit) + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + CAR + /* [ set bool + : pair (set bool) + (pair int int) + (or key_hash timestamp) + (map int string) + (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ set bool + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ } + /* [ set bool : set bool + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + PACK + /* [ bytes : set bool + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + UNPACK + (set bool) + /* [ option (set bool) + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + CAR + /* [ pair int int + : pair (pair int int) (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ pair int int + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ } + /* [ pair int int : pair int int + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + PACK + /* [ bytes : pair int int + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + UNPACK + (pair int int) + /* [ option (pair int int) + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ } + /* [ bytes : bytes + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (or key_hash timestamp) (map int string) (lambda string bytes) + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + CAR + /* [ or key_hash timestamp + : pair (or key_hash timestamp) (map int string) (lambda string bytes) ] */ ; + DIP { UNPAIR + /* [ or key_hash timestamp : pair (map int string) (lambda string bytes) ] */ } + /* [ or key_hash timestamp : or key_hash timestamp + : pair (map int string) (lambda string bytes) ] */ ; + PACK + /* [ bytes : or key_hash timestamp + : pair (map int string) (lambda string bytes) ] */ ; + DIP { PACK + /* [ bytes : pair (map int string) (lambda string bytes) ] */ ; + UNPACK + (or key_hash timestamp) + /* [ option (or key_hash timestamp) + : pair (map int string) (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes : pair (map int string) (lambda string bytes) ] */ } + /* [ bytes : bytes : pair (map int string) (lambda string bytes) ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ pair (map int string) (lambda string bytes) + : pair (map int string) (lambda string bytes) ] */ ; + CAR + /* [ map int string : pair (map int string) (lambda string bytes) ] */ ; + DIP { UNPAIR /* [ map int string : lambda string bytes ] */ } + /* [ map int string : map int string : lambda string bytes ] */ ; + PACK + /* [ bytes : map int string : lambda string bytes ] */ ; + DIP { PACK + /* [ bytes : lambda string bytes ] */ ; + UNPACK (map int string) + /* [ option (map int string) : lambda string bytes ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes : lambda string bytes ] */ } + /* [ bytes : bytes : lambda string bytes ] */ ; + ASSERT_CMPEQ ; + DUP + /* [ lambda string bytes : lambda string bytes ] */ ; + PACK + /* [ bytes : lambda string bytes ] */ ; + DIP { PACK + /* [ bytes ] */ ; + UNPACK (lambda string bytes) + /* [ option (lambda string bytes) ] */ ; + ASSERT_SOME ; + PACK + /* [ bytes ] */ } + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.987 units remaining) michelson_test_scripts/opcodes/pair_id.tz +{ parameter (pair bool bool) ; + storage (option (pair bool bool)) ; + code { CAR + /* [ pair bool bool ] */ ; + SOME + /* [ option (pair bool bool) ] */ ; + NIL operation + /* [ list operation : option (pair bool bool) ] */ ; + PAIR + /* [ pair (list operation) (option (pair bool bool)) ] */ } } +Well typed (Gas remaining: 1039996.651 units remaining) michelson_test_scripts/opcodes/pairing_check.tz +{ parameter (list (pair bls12_381_g1 bls12_381_g2)) ; + storage (option bool) ; + code { CAR + /* [ list (pair bls12_381_g1 bls12_381_g2) ] */ ; + PAIRING_CHECK + /* [ bool ] */ ; + SOME + /* [ option bool ] */ ; + NIL operation + /* [ list operation : option bool ] */ ; + PAIR + /* [ pair (list operation) (option bool) ] */ } } +Well typed (Gas remaining: 1039994.102 units remaining) michelson_test_scripts/opcodes/pexec.tz +{ parameter nat ; + storage nat ; + code { LAMBDA + (pair nat nat) + nat + { UNPAIR /* [ nat : nat ] */ ; ADD /* [ nat ] */ } + /* [ lambda (pair nat nat) nat : pair nat nat ] */ ; + SWAP + /* [ pair nat nat : lambda (pair nat nat) nat ] */ ; + UNPAIR + /* [ nat : nat : lambda (pair nat nat) nat ] */ ; + DIP { APPLY /* [ lambda nat nat ] */ } + /* [ nat : lambda nat nat ] */ ; + EXEC + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039988.370 units remaining) michelson_test_scripts/opcodes/pexec_2.tz +{ parameter int ; + storage (list int) ; + code { UNPAIR @p @s + /* [ int : list int ] */ ; + LAMBDA + (pair int (pair int int)) + int + { UNPAIR + /* [ int : pair int int ] */ ; + DIP { UNPAIR /* [ int : int ] */ } + /* [ int : int : int ] */ ; + ADD + /* [ int : int ] */ ; + MUL + /* [ int ] */ } + /* [ lambda (pair int int int) int : int : list int ] */ ; + SWAP + /* [ int : lambda (pair int int int) int : list int ] */ ; + APPLY + /* [ lambda (pair int int) int : list int ] */ ; + PUSH int 3 + /* [ int : lambda (pair int int) int : list int ] */ ; + APPLY + /* [ lambda int int : list int ] */ ; + SWAP + /* [ list int : lambda int int ] */ ; + MAP { DIP { DUP /* [ lambda int int : lambda int int ] */ } + /* [ int : lambda int int : lambda int int ] */ ; + EXEC + /* [ int : lambda int int ] */ } + /* [ list int : lambda int int ] */ ; + DIP { DROP /* [] */ } + /* [ list int ] */ ; + NIL operation + /* [ list operation : list int ] */ ; + PAIR + /* [ pair (list operation) (list int) ] */ } } +Well typed (Gas remaining: 1039995.390 units remaining) michelson_test_scripts/opcodes/proxy.tz +{ parameter (contract unit) ; + storage unit ; + code { UNPAIR + /* [ contract unit : unit ] */ ; + AMOUNT + /* [ mutez : contract unit : unit ] */ ; + UNIT + /* [ unit : mutez : contract unit : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + DIP { NIL operation /* [ list operation : unit ] */ } + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.699 units remaining) michelson_test_scripts/opcodes/ret_int.tz +{ parameter unit ; + storage (option nat) ; + code { DROP + /* [] */ ; + PUSH nat 300 + /* [ nat ] */ ; + SOME + /* [ option nat ] */ ; + NIL operation + /* [ list operation : option nat ] */ ; + PAIR + /* [ pair (list operation) (option nat) ] */ } } +Well typed (Gas remaining: 1039995.638 units remaining) michelson_test_scripts/opcodes/reverse.tz +{ parameter (list string) ; + storage (list string) ; + code { CAR + /* [ list string ] */ ; + NIL string + /* [ list string : list string ] */ ; + SWAP + /* [ list string : list string ] */ ; + ITER { CONS /* [ list string ] */ } + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039990.539 units remaining) michelson_test_scripts/opcodes/reverse_loop.tz +{ parameter (list string) ; + storage (list string) ; + code { CAR + /* [ list string ] */ ; + NIL string + /* [ list string : list string ] */ ; + SWAP + /* [ list string : list string ] */ ; + PUSH bool True + /* [ bool : list string : list string ] */ ; + LOOP { IF_CONS + { SWAP + /* [ list string : string : list string ] */ ; + DIP { CONS /* [ list string ] */ } + /* [ list string : list string ] */ ; + PUSH bool True + /* [ bool : list string : list string ] */ } + { NIL string + /* [ list string : list string ] */ ; + PUSH bool False + /* [ bool : list string : list string ] */ } } + /* [ list string : list string ] */ ; + DROP + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039997.505 units remaining) michelson_test_scripts/opcodes/sapling_empty_state.tz +{ parameter unit ; + storage (sapling_state 8) ; + code { DROP + /* [] */ ; + SAPLING_EMPTY_STATE 8 + /* [ sapling_state 8 ] */ ; + NIL operation + /* [ list operation : sapling_state 8 ] */ ; + PAIR + /* [ pair (list operation) (sapling_state 8) ] */ } } +Well typed (Gas remaining: 1039997.054 units remaining) michelson_test_scripts/opcodes/self.tz +{ parameter unit ; + storage address ; + code { DROP + /* [] */ ; + SELF + /* [ contract unit ] */ ; + ADDRESS + /* [ address ] */ ; + NIL operation + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039990.287 units remaining) michelson_test_scripts/opcodes/self_address.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + LAMBDA + unit + address + { DROP /* [] */ ; SELF_ADDRESS /* [ address ] */ } + /* [ lambda unit address ] */ ; + UNIT + /* [ unit : lambda unit address ] */ ; + EXEC + /* [ address ] */ ; + SELF + /* [ contract unit : address ] */ ; + ADDRESS + /* [ address : address ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039986.649 units remaining) michelson_test_scripts/opcodes/self_address_after_fib_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 3 + /* [ nat : address : address ] */ ; + VIEW "fib" nat + /* [ option nat : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SELF_ADDRESS + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039987.133 units remaining) michelson_test_scripts/opcodes/self_address_after_nonexistent_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" string + /* [ option string : address ] */ ; + ASSERT_NONE ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SELF_ADDRESS + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039986.472 units remaining) michelson_test_scripts/opcodes/self_address_after_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SELF_ADDRESS + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039986.141 units remaining) michelson_test_scripts/opcodes/self_after_fib_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 3 + /* [ nat : address : address ] */ ; + VIEW "fib" nat + /* [ option nat : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SELF + /* [ contract address : operation ] */ ; + ADDRESS + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039986.534 units remaining) michelson_test_scripts/opcodes/self_after_nonexistent_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "nonexistent" string + /* [ option string : address ] */ ; + ASSERT_NONE ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SELF + /* [ contract address : operation ] */ ; + ADDRESS + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039985.965 units remaining) michelson_test_scripts/opcodes/self_after_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SELF + /* [ contract address : operation ] */ ; + ADDRESS + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039988.888 units remaining) michelson_test_scripts/opcodes/self_with_default_entrypoint.tz +{ parameter (or (or (nat %A) (bool %B)) (or %maybe_C (unit %default) (string %C))) ; + storage unit ; + code { DROP + /* [] */ ; + SELF + /* [ contract unit ] */ ; + DROP + /* [] */ ; + SELF %A + /* [ contract nat ] */ ; + DROP + /* [] */ ; + SELF %default + /* [ contract unit ] */ ; + PACK + /* [ bytes ] */ ; + SELF + /* [ contract unit : bytes ] */ ; + PACK + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039971.670 units remaining) michelson_test_scripts/opcodes/self_with_entrypoint.tz +{ parameter (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C))) ; + storage unit ; + code { DROP + /* [] */ ; + SELF %A + /* [ contract nat ] */ ; + PACK @Apacked + /* [ bytes ] */ ; + SELF %default + /* [ contract (or (or nat bool) (or unit string)) : bytes ] */ ; + PACK @defpacked + /* [ bytes : bytes ] */ ; + DUP + /* [ bytes : bytes : bytes ] */ ; + DIP { SWAP /* [ bytes : bytes ] */ } + /* [ bytes : bytes : bytes ] */ ; + ASSERT_CMPNEQ ; + SELF + /* [ contract (or (or nat bool) (or unit string)) : bytes ] */ ; + PACK @selfpacked + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + SELF %A + /* [ contract nat ] */ ; + CAST (contract nat) + /* [ contract nat ] */ ; + DROP + /* [] */ ; + SELF %B + /* [ contract bool ] */ ; + CAST (contract bool) + /* [ contract bool ] */ ; + DROP + /* [] */ ; + SELF %maybe_C + /* [ contract (or unit string) ] */ ; + CAST (contract (or unit string)) + /* [ contract (or unit string) ] */ ; + DROP + /* [] */ ; + SELF %Z + /* [ contract unit ] */ ; + CAST (contract unit) + /* [ contract unit ] */ ; + DROP + /* [] */ ; + SELF + /* [ contract (or (or nat bool) (or unit string)) ] */ ; + CAST (contract (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C)))) + /* [ contract (or (or nat bool) (or unit string)) ] */ ; + DROP + /* [] */ ; + SELF %default + /* [ contract (or (or nat bool) (or unit string)) ] */ ; + CAST (contract (or (or (nat %A) (bool %B)) (or %maybe_C (unit %Z) (string %C)))) + /* [ contract (or (or nat bool) (or unit string)) ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/sender.tz +{ parameter unit ; + storage address ; + code { DROP + /* [] */ ; + SENDER + /* [ address ] */ ; + NIL operation + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039986.649 units remaining) michelson_test_scripts/opcodes/sender_after_fib_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 3 + /* [ nat : address : address ] */ ; + VIEW "fib" nat + /* [ option nat : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SENDER + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039987.133 units remaining) michelson_test_scripts/opcodes/sender_after_nonexistent_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" string + /* [ option string : address ] */ ; + ASSERT_NONE ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SENDER + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039986.472 units remaining) michelson_test_scripts/opcodes/sender_after_view.tz +{ parameter address ; + storage address ; + code { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + PUSH nat 0 + /* [ nat : address : address ] */ ; + VIEW "id" (pair nat nat) + /* [ option (pair nat nat) : address ] */ ; + ASSERT_SOME ; + DROP + /* [ address ] */ ; + CONTRACT nat + /* [ option (contract nat) ] */ ; + ASSERT_SOME ; + PUSH mutez 1500 + /* [ mutez : contract nat ] */ ; + PUSH nat 0 + /* [ nat : mutez : contract nat ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + SENDER + /* [ address : operation ] */ ; + SWAP + /* [ operation : address ] */ ; + NIL operation + /* [ list operation : operation : address ] */ ; + SWAP + /* [ operation : list operation : address ] */ ; + CONS + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039992.449 units remaining) michelson_test_scripts/opcodes/set_car.tz +{ parameter string ; + storage (pair (string %s) (nat %n)) ; + code { DUP + /* [ pair string string nat : pair string string nat ] */ ; + CDR + /* [ pair string nat : pair string string nat ] */ ; + DIP { CAR /* [ string ] */ } + /* [ pair string nat : string ] */ ; + SET_CAR %s ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } } +Well typed (Gas remaining: 1039992.918 units remaining) michelson_test_scripts/opcodes/set_cdr.tz +{ parameter nat ; + storage (pair (string %s) (nat %n)) ; + code { DUP + /* [ pair nat string nat : pair nat string nat ] */ ; + CDR + /* [ pair string nat : pair nat string nat ] */ ; + DIP { CAR /* [ nat ] */ } + /* [ pair string nat : nat ] */ ; + SET_CDR %n ; + NIL operation + /* [ list operation : pair string nat ] */ ; + PAIR + /* [ pair (list operation) string nat ] */ } } +Well typed (Gas remaining: 1039996.384 units remaining) michelson_test_scripts/opcodes/set_delegate.tz +{ parameter (option key_hash) ; + storage unit ; + code { UNPAIR + /* [ option key_hash : unit ] */ ; + SET_DELEGATE + /* [ operation : unit ] */ ; + DIP { NIL operation /* [ list operation : unit ] */ } + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.827 units remaining) michelson_test_scripts/opcodes/set_id.tz +{ parameter (set string) ; + storage (set string) ; + code { CAR + /* [ set string ] */ ; + NIL operation + /* [ list operation : set string ] */ ; + PAIR + /* [ pair (list operation) (set string) ] */ } } +Well typed (Gas remaining: 1039995.699 units remaining) michelson_test_scripts/opcodes/set_iter.tz +{ parameter (set int) ; + storage int ; + code { CAR + /* [ set int ] */ ; + PUSH int 0 + /* [ int : set int ] */ ; + SWAP + /* [ set int : int ] */ ; + ITER { ADD /* [ int ] */ } + /* [ int ] */ ; + NIL operation + /* [ list operation : int ] */ ; + PAIR + /* [ pair (list operation) int ] */ } } +Well typed (Gas remaining: 1039989.942 units remaining) michelson_test_scripts/opcodes/set_member.tz +{ parameter string ; + storage (pair (set string) (option bool)) ; + code { DUP + /* [ pair string (set string) (option bool) + : pair string (set string) (option bool) ] */ ; + DUP + /* [ pair string (set string) (option bool) + : pair string (set string) (option bool) + : pair string (set string) (option bool) ] */ ; + CAR + /* [ string : pair string (set string) (option bool) + : pair string (set string) (option bool) ] */ ; + DIP { CDAR } + /* [ string : set string : pair string (set string) (option bool) ] */ ; + MEM + /* [ bool : pair string (set string) (option bool) ] */ ; + SOME + /* [ option bool : pair string (set string) (option bool) ] */ ; + DIP { CDAR } + /* [ option bool : set string ] */ ; + SWAP + /* [ set string : option bool ] */ ; + PAIR + /* [ pair (set string) (option bool) ] */ ; + NIL operation + /* [ list operation : pair (set string) (option bool) ] */ ; + PAIR + /* [ pair (list operation) (set string) (option bool) ] */ } } +Well typed (Gas remaining: 1039997.469 units remaining) michelson_test_scripts/opcodes/set_size.tz +{ parameter (set int) ; + storage nat ; + code { CAR + /* [ set int ] */ ; + SIZE + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039956.190 units remaining) michelson_test_scripts/opcodes/sets.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH (set nat) { 0 ; 1 ; 3 } + /* [ set nat ] */ ; + DROP + /* [] */ ; + PUSH (set int) { -1 ; 0 ; 3 } + /* [ set int ] */ ; + DROP + /* [] */ ; + PUSH (set mutez) { 1 ; 4 ; 5 ; 10 ; 1923 } + /* [ set mutez ] */ ; + DROP + /* [] */ ; + PUSH (set timestamp) + { -1 ; 0 ; "2017-09-16T08:38:04Z" ; "2019-09-16T08:38:05Z" } + /* [ set timestamp ] */ ; + DROP + /* [] */ ; + PUSH (set bool) {} + /* [ set bool ] */ ; + DROP + /* [] */ ; + PUSH (set bool) { True } + /* [ set bool ] */ ; + DROP + /* [] */ ; + PUSH (set bool) { False } + /* [ set bool ] */ ; + DROP + /* [] */ ; + PUSH (set bool) { False ; True } + /* [ set bool ] */ ; + DROP + /* [] */ ; + PUSH (set string) { "" ; "A" ; "B" ; "a" ; "aa" ; "b" } + /* [ set string ] */ ; + DROP + /* [] */ ; + PUSH (set bytes) { 0x ; 0x01 ; 0x02 ; 0xaabbcc } + /* [ set bytes ] */ ; + DROP + /* [] */ ; + PUSH (set key_hash) + { "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ; + "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" } + /* [ set key_hash ] */ ; + DROP + /* [] */ ; + PUSH (set address) + { "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" ; + "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv" ; + "KT1TZCh8fmUbuDqFxetPWC2fsQanAHzLx4W9" } + /* [ set address ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039996.983 units remaining) michelson_test_scripts/opcodes/sha3.tz +{ storage (option bytes) ; + parameter bytes ; + code { CAR + /* [ bytes ] */ ; + SHA3 + /* [ bytes ] */ ; + SOME + /* [ option bytes ] */ ; + NIL operation + /* [ list operation : option bytes ] */ ; + PAIR + /* [ pair (list operation) (option bytes) ] */ } } +Well typed (Gas remaining: 1039994.397 units remaining) michelson_test_scripts/opcodes/shifts.tz +{ parameter (or (pair nat nat) (pair nat nat)) ; + storage (option nat) ; + code { CAR + /* [ or (pair nat nat) (pair nat nat) ] */ ; + IF_LEFT + { UNPAIR /* [ nat : nat ] */ ; LSL /* [ nat ] */ } + { UNPAIR /* [ nat : nat ] */ ; LSR /* [ nat ] */ } ; + SOME + /* [ option nat ] */ ; + NIL operation + /* [ list operation : option nat ] */ ; + PAIR + /* [ pair (list operation) (option nat) ] */ } } +Well typed (Gas remaining: 1039993.924 units remaining) michelson_test_scripts/opcodes/slice.tz +{ parameter (pair nat nat) ; + storage (option string) ; + code { UNPAIR + /* [ pair nat nat : option string ] */ ; + SWAP + /* [ option string : pair nat nat ] */ ; + IF_SOME + { SWAP + /* [ pair nat nat : string ] */ ; + UNPAIR + /* [ nat : nat : string ] */ ; + SLICE + /* [ option string ] */ } + { DROP /* [] */ ; NONE string /* [ option string ] */ } ; + NIL operation + /* [ list operation : option string ] */ ; + PAIR + /* [ pair (list operation) (option string) ] */ } } +Well typed (Gas remaining: 1039993.924 units remaining) michelson_test_scripts/opcodes/slice_bytes.tz +{ parameter (pair nat nat) ; + storage (option bytes) ; + code { UNPAIR + /* [ pair nat nat : option bytes ] */ ; + SWAP + /* [ option bytes : pair nat nat ] */ ; + IF_SOME + { SWAP + /* [ pair nat nat : bytes ] */ ; + UNPAIR + /* [ nat : nat : bytes ] */ ; + SLICE + /* [ option bytes ] */ } + { DROP /* [] */ ; NONE bytes /* [ option bytes ] */ } ; + NIL operation + /* [ list operation : option bytes ] */ ; + PAIR + /* [ pair (list operation) (option bytes) ] */ } } +Well typed (Gas remaining: 1039936.992 units remaining) michelson_test_scripts/opcodes/slices.tz +{ parameter (pair bytes signature) ; + storage key ; + code { DUP + /* [ pair (pair bytes signature) key : pair (pair bytes signature) key ] */ ; + CAAR ; + DUP + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + SIZE + /* [ nat : bytes : pair (pair bytes signature) key ] */ ; + PUSH nat 128 + /* [ nat : nat : bytes : pair (pair bytes signature) key ] */ ; + SWAP + /* [ nat : nat : bytes : pair (pair bytes signature) key ] */ ; + SUB + /* [ int : bytes : pair (pair bytes signature) key ] */ ; + ISNAT + /* [ option nat : bytes : pair (pair bytes signature) key ] */ ; + IF_SOME { /* [ nat : bytes : pair (pair bytes signature) key ] */ } { FAIL } ; + PUSH nat 128 + /* [ nat : nat : bytes : pair (pair bytes signature) key ] */ ; + SLICE @payload + /* [ option bytes : pair (pair bytes signature) key ] */ ; + ASSERT_SOME ; + DUP + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + DIP { DIP { DUP + /* [ pair (pair bytes signature) key : pair (pair bytes signature) key ] */ ; + CAAR ; + PUSH nat 32 + /* [ nat : bytes : pair (pair bytes signature) key ] */ ; + PUSH nat 0 + /* [ nat : nat : bytes : pair (pair bytes signature) key ] */ ; + SLICE + /* [ option bytes : pair (pair bytes signature) key ] */ ; + ASSERT_SOME } + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + SHA256 + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + ASSERT_CMPEQ } + /* [ bytes : pair (pair bytes signature) key ] */ ; + DUP + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + DIP { DIP { DUP + /* [ pair (pair bytes signature) key : pair (pair bytes signature) key ] */ ; + CAAR ; + PUSH nat 32 + /* [ nat : bytes : pair (pair bytes signature) key ] */ ; + PUSH nat 32 + /* [ nat : nat : bytes : pair (pair bytes signature) key ] */ ; + SLICE + /* [ option bytes : pair (pair bytes signature) key ] */ ; + ASSERT_SOME } + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + BLAKE2B + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + ASSERT_CMPEQ } + /* [ bytes : pair (pair bytes signature) key ] */ ; + DUP + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + DIP { DIP { DUP + /* [ pair (pair bytes signature) key : pair (pair bytes signature) key ] */ ; + CAAR ; + PUSH nat 64 + /* [ nat : bytes : pair (pair bytes signature) key ] */ ; + PUSH nat 64 + /* [ nat : nat : bytes : pair (pair bytes signature) key ] */ ; + SLICE + /* [ option bytes : pair (pair bytes signature) key ] */ ; + ASSERT_SOME } + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + SHA512 + /* [ bytes : bytes : pair (pair bytes signature) key ] */ ; + ASSERT_CMPEQ } + /* [ bytes : pair (pair bytes signature) key ] */ ; + DIP { DUP + /* [ pair (pair bytes signature) key : pair (pair bytes signature) key ] */ ; + CDR + /* [ key : pair (pair bytes signature) key ] */ ; + DIP { DUP + /* [ pair (pair bytes signature) key : pair (pair bytes signature) key ] */ ; + CADR } + /* [ key : signature : pair (pair bytes signature) key ] */ } + /* [ bytes : key : signature : pair (pair bytes signature) key ] */ ; + SWAP + /* [ key : bytes : signature : pair (pair bytes signature) key ] */ ; + DIP { SWAP /* [ signature : bytes : pair (pair bytes signature) key ] */ } + /* [ key : signature : bytes : pair (pair bytes signature) key ] */ ; + CHECK_SIGNATURE + /* [ bool : pair (pair bytes signature) key ] */ ; + ASSERT ; + CDR + /* [ key ] */ ; + DUP + /* [ key : key ] */ ; + HASH_KEY + /* [ key_hash : key ] */ ; + IMPLICIT_ACCOUNT + /* [ contract unit : key ] */ ; + BALANCE + /* [ mutez : contract unit : key ] */ ; + UNIT + /* [ unit : mutez : contract unit : key ] */ ; + TRANSFER_TOKENS + /* [ operation : key ] */ ; + NIL operation + /* [ list operation : operation : key ] */ ; + SWAP + /* [ operation : list operation : key ] */ ; + CONS + /* [ list operation : key ] */ ; + PAIR + /* [ pair (list operation) key ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/source.tz +{ parameter unit ; + storage address ; + code { DROP + /* [] */ ; + SOURCE + /* [ address ] */ ; + NIL operation + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039973.560 units remaining) michelson_test_scripts/opcodes/split_bytes.tz +{ parameter bytes ; + storage (list bytes) ; + code { UNPAIR + /* [ bytes : list bytes ] */ ; + DIP { NIL bytes + /* [ list bytes : list bytes ] */ ; + SWAP + /* [ list bytes : list bytes ] */ ; + ITER { CONS /* [ list bytes ] */ } + /* [ list bytes ] */ } + /* [ bytes : list bytes ] */ ; + DUP + /* [ bytes : bytes : list bytes ] */ ; + SIZE + /* [ nat : bytes : list bytes ] */ ; + PUSH nat 0 + /* [ nat : nat : bytes : list bytes ] */ ; + CMPNEQ ; + DIP { PUSH @index nat 0 /* [ nat : bytes : list bytes ] */ } + /* [ bool : nat : bytes : list bytes ] */ ; + LOOP { PAIR + /* [ pair nat bytes : list bytes ] */ ; + DUP + /* [ pair nat bytes : pair nat bytes : list bytes ] */ ; + DIP { UNPAIR + /* [ nat : bytes : list bytes ] */ ; + DIP { PUSH nat 1 /* [ nat : bytes : list bytes ] */ } + /* [ nat : nat : bytes : list bytes ] */ ; + SLICE + /* [ option bytes : list bytes ] */ ; + ASSERT_SOME ; + CONS @storage + /* [ list bytes ] */ } + /* [ pair nat bytes : list bytes ] */ ; + UNPAIR + /* [ nat : bytes : list bytes ] */ ; + PUSH nat 1 + /* [ nat : nat : bytes : list bytes ] */ ; + ADD @index + /* [ nat : bytes : list bytes ] */ ; + DUP + /* [ nat : nat : bytes : list bytes ] */ ; + DIP { DIP { DUP /* [ bytes : bytes : list bytes ] */ } + /* [ nat : bytes : bytes : list bytes ] */ ; + SWAP + /* [ bytes : nat : bytes : list bytes ] */ ; + SIZE + /* [ nat : nat : bytes : list bytes ] */ ; + CMPNEQ } + /* [ nat : bool : bytes : list bytes ] */ ; + SWAP + /* [ bool : nat : bytes : list bytes ] */ } + /* [ nat : bytes : list bytes ] */ ; + DROP + /* [ bytes : list bytes ] */ ; + DROP + /* [ list bytes ] */ ; + NIL bytes + /* [ list bytes : list bytes ] */ ; + SWAP + /* [ list bytes : list bytes ] */ ; + ITER { CONS /* [ list bytes ] */ } + /* [ list bytes ] */ ; + NIL operation + /* [ list operation : list bytes ] */ ; + PAIR + /* [ pair (list operation) (list bytes) ] */ } } +Well typed (Gas remaining: 1039973.560 units remaining) michelson_test_scripts/opcodes/split_string.tz +{ parameter string ; + storage (list string) ; + code { UNPAIR + /* [ string : list string ] */ ; + DIP { NIL string + /* [ list string : list string ] */ ; + SWAP + /* [ list string : list string ] */ ; + ITER { CONS /* [ list string ] */ } + /* [ list string ] */ } + /* [ string : list string ] */ ; + DUP + /* [ string : string : list string ] */ ; + SIZE + /* [ nat : string : list string ] */ ; + PUSH nat 0 + /* [ nat : nat : string : list string ] */ ; + CMPNEQ ; + DIP { PUSH @index nat 0 /* [ nat : string : list string ] */ } + /* [ bool : nat : string : list string ] */ ; + LOOP { PAIR + /* [ pair nat string : list string ] */ ; + DUP + /* [ pair nat string : pair nat string : list string ] */ ; + DIP { UNPAIR + /* [ nat : string : list string ] */ ; + DIP { PUSH nat 1 /* [ nat : string : list string ] */ } + /* [ nat : nat : string : list string ] */ ; + SLICE + /* [ option string : list string ] */ ; + ASSERT_SOME ; + CONS @storage + /* [ list string ] */ } + /* [ pair nat string : list string ] */ ; + UNPAIR + /* [ nat : string : list string ] */ ; + PUSH nat 1 + /* [ nat : nat : string : list string ] */ ; + ADD @index + /* [ nat : string : list string ] */ ; + DUP + /* [ nat : nat : string : list string ] */ ; + DIP { DIP { DUP /* [ string : string : list string ] */ } + /* [ nat : string : string : list string ] */ ; + SWAP + /* [ string : nat : string : list string ] */ ; + SIZE + /* [ nat : nat : string : list string ] */ ; + CMPNEQ } + /* [ nat : bool : string : list string ] */ ; + SWAP + /* [ bool : nat : string : list string ] */ } + /* [ nat : string : list string ] */ ; + DROP + /* [ string : list string ] */ ; + DROP + /* [ list string ] */ ; + NIL string + /* [ list string : list string ] */ ; + SWAP + /* [ list string : list string ] */ ; + ITER { CONS /* [ list string ] */ } + /* [ list string ] */ ; + NIL operation + /* [ list operation : list string ] */ ; + PAIR + /* [ pair (list operation) (list string) ] */ } } +Well typed (Gas remaining: 1039997.447 units remaining) michelson_test_scripts/opcodes/store_bls12_381_fr.tz +{ parameter bls12_381_fr ; + storage (option bls12_381_fr) ; + code { CAR + /* [ bls12_381_fr ] */ ; + SOME + /* [ option bls12_381_fr ] */ ; + NIL operation + /* [ list operation : option bls12_381_fr ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_fr) ] */ } } +Well typed (Gas remaining: 1039997.447 units remaining) michelson_test_scripts/opcodes/store_bls12_381_g1.tz +{ parameter bls12_381_g1 ; + storage (option bls12_381_g1) ; + code { CAR + /* [ bls12_381_g1 ] */ ; + SOME + /* [ option bls12_381_g1 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g1 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g1) ] */ } } +Well typed (Gas remaining: 1039997.447 units remaining) michelson_test_scripts/opcodes/store_bls12_381_g2.tz +{ parameter bls12_381_g2 ; + storage (option bls12_381_g2) ; + code { CAR + /* [ bls12_381_g2 ] */ ; + SOME + /* [ option bls12_381_g2 ] */ ; + NIL operation + /* [ list operation : option bls12_381_g2 ] */ ; + PAIR + /* [ pair (list operation) (option bls12_381_g2) ] */ } } +Well typed (Gas remaining: 1039998.017 units remaining) michelson_test_scripts/opcodes/store_input.tz +{ parameter string ; + storage string ; + code { CAR + /* [ string ] */ ; + NIL operation + /* [ list operation : string ] */ ; + PAIR + /* [ pair (list operation) string ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/store_now.tz +{ parameter unit ; + storage timestamp ; + code { DROP + /* [] */ ; + NOW + /* [ timestamp ] */ ; + NIL operation + /* [ list operation : timestamp ] */ ; + PAIR + /* [ pair (list operation) timestamp ] */ } } +Well typed (Gas remaining: 1039997.447 units remaining) michelson_test_scripts/opcodes/str_id.tz +{ parameter string ; + storage (option string) ; + code { CAR + /* [ string ] */ ; + SOME + /* [ option string ] */ ; + NIL operation + /* [ list operation : option string ] */ ; + PAIR + /* [ pair (list operation) (option string) ] */ } } +Well typed (Gas remaining: 1039995.116 units remaining) michelson_test_scripts/opcodes/sub_timestamp_delta.tz +{ parameter (pair timestamp int) ; + storage timestamp ; + code { CAR + /* [ pair timestamp int ] */ ; + DUP + /* [ pair timestamp int : pair timestamp int ] */ ; + CAR + /* [ timestamp : pair timestamp int ] */ ; + DIP { CDR /* [ int ] */ } + /* [ timestamp : int ] */ ; + SUB + /* [ timestamp ] */ ; + NIL operation + /* [ list operation : timestamp ] */ ; + PAIR + /* [ pair (list operation) timestamp ] */ } } +Well typed (Gas remaining: 1039986.601 units remaining) michelson_test_scripts/opcodes/subset.tz +{ parameter (pair (set string) (set string)) ; + storage bool ; + code { CAR + /* [ pair (set string) (set string) ] */ ; + DUP + /* [ pair (set string) (set string) : pair (set string) (set string) ] */ ; + CDR + /* [ set string : pair (set string) (set string) ] */ ; + DIP { CAR /* [ set string ] */ } + /* [ set string : set string ] */ ; + PUSH bool True + /* [ bool : set string : set string ] */ ; + PAIR + /* [ pair bool (set string) : set string ] */ ; + SWAP + /* [ set string : pair bool (set string) ] */ ; + ITER { DIP { DUP + /* [ pair bool (set string) : pair bool (set string) ] */ ; + DUP + /* [ pair bool (set string) : pair bool (set string) : pair bool (set string) ] */ ; + CDR + /* [ set string : pair bool (set string) : pair bool (set string) ] */ ; + DIP { CAR + /* [ bool : pair bool (set string) ] */ ; + DIP { CDR /* [ set string ] */ } + /* [ bool : set string ] */ } + /* [ set string : bool : set string ] */ } + /* [ string : set string : bool : set string ] */ ; + MEM + /* [ bool : bool : set string ] */ ; + AND + /* [ bool : set string ] */ ; + PAIR + /* [ pair bool (set string) ] */ } + /* [ pair bool (set string) ] */ ; + CAR + /* [ bool ] */ ; + NIL operation + /* [ list operation : bool ] */ ; + PAIR + /* [ pair (list operation) bool ] */ } } +Well typed (Gas remaining: 1039987.541 units remaining) michelson_test_scripts/opcodes/tez_add_sub.tz +{ parameter (pair mutez mutez) ; + storage (option (pair mutez mutez)) ; + code { CAR + /* [ pair mutez mutez ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez ] */ ; + DUP + /* [ pair mutez mutez : pair mutez mutez : pair mutez mutez ] */ ; + CAR + /* [ mutez : pair mutez mutez : pair mutez mutez ] */ ; + DIP { CDR /* [ mutez : pair mutez mutez ] */ } + /* [ mutez : mutez : pair mutez mutez ] */ ; + ADD + /* [ mutez : pair mutez mutez ] */ ; + DIP { DUP + /* [ pair mutez mutez : pair mutez mutez ] */ ; + CAR + /* [ mutez : pair mutez mutez ] */ ; + DIP { CDR /* [ mutez ] */ } + /* [ mutez : mutez ] */ ; + SUB_MUTEZ + /* [ option mutez ] */ ; + ASSERT_SOME } + /* [ mutez : mutez ] */ ; + PAIR + /* [ pair mutez mutez ] */ ; + SOME + /* [ option (pair mutez mutez) ] */ ; + NIL operation + /* [ list operation : option (pair mutez mutez) ] */ ; + PAIR + /* [ pair (list operation) (option (pair mutez mutez)) ] */ } } +Well typed (Gas remaining: 1039997.910 units remaining) michelson_test_scripts/opcodes/ticket_bad.tz +{ parameter unit ; + storage (ticket nat) ; + code { CDR + /* [ ticket nat ] */ ; + NIL operation + /* [ list operation : ticket nat ] */ ; + PAIR + /* [ pair (list operation) (ticket nat) ] */ } } +Well typed (Gas remaining: 1039992.229 units remaining) michelson_test_scripts/opcodes/ticket_big_store.tz +{ parameter nat ; + storage (big_map unit (ticket nat)) ; + code { UNPAIR + /* [ nat : big_map unit (ticket nat) ] */ ; + PUSH nat 1 + /* [ nat : nat : big_map unit (ticket nat) ] */ ; + SWAP + /* [ nat : nat : big_map unit (ticket nat) ] */ ; + TICKET + /* [ option (ticket nat) : big_map unit (ticket nat) ] */ ; + ASSERT_SOME ; + SOME + /* [ option (ticket nat) : big_map unit (ticket nat) ] */ ; + UNIT + /* [ unit : option (ticket nat) : big_map unit (ticket nat) ] */ ; + UPDATE + /* [ big_map unit (ticket nat) ] */ ; + NIL operation + /* [ list operation : big_map unit (ticket nat) ] */ ; + PAIR + /* [ pair (list operation) (big_map unit (ticket nat)) ] */ } } +Well typed (Gas remaining: 1039992.719 units remaining) michelson_test_scripts/opcodes/ticket_join.tz +{ parameter (ticket nat) ; + storage (option (ticket nat)) ; + code { UNPAIR + /* [ ticket nat : option (ticket nat) ] */ ; + SWAP + /* [ option (ticket nat) : ticket nat ] */ ; + IF_NONE + { /* [ ticket nat ] */ } + { PAIR + /* [ pair (ticket nat) (ticket nat) ] */ ; + JOIN_TICKETS + /* [ option (ticket nat) ] */ ; + ASSERT_SOME } ; + SOME + /* [ option (ticket nat) ] */ ; + NIL operation + /* [ list operation : option (ticket nat) ] */ ; + PAIR + /* [ pair (list operation) (option (ticket nat)) ] */ } } +Well typed (Gas remaining: 1039985.428 units remaining) michelson_test_scripts/opcodes/ticket_read.tz +{ parameter (ticket nat) ; + storage address ; + code { CAR + /* [ ticket nat ] */ ; + READ_TICKET + /* [ pair address nat nat : ticket nat ] */ ; + DIP { DROP /* [] */ } + /* [ pair address nat nat ] */ ; + UNPAIR + /* [ address : pair nat nat ] */ ; + DIP { UNPAIR /* [ nat : nat ] */ } + /* [ address : nat : nat ] */ ; + DIP 2 { PUSH nat 1 /* [ nat : nat ] */ ; ASSERT_CMPEQ } + /* [ address : nat ] */ ; + DIP { PUSH nat 42 /* [ nat : nat ] */ ; ASSERT_CMPEQ } + /* [ address ] */ ; + NIL operation + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039979.615 units remaining) michelson_test_scripts/opcodes/ticket_split.tz +{ parameter (ticket nat) ; + storage unit ; + code { CAR + /* [ ticket nat ] */ ; + PUSH (pair nat nat) (Pair 1 2) + /* [ pair nat nat : ticket nat ] */ ; + SWAP + /* [ ticket nat : pair nat nat ] */ ; + SPLIT_TICKET + /* [ option (pair (ticket nat) (ticket nat)) ] */ ; + ASSERT_SOME ; + UNPAIR + /* [ ticket nat : ticket nat ] */ ; + READ_TICKET + /* [ pair address nat nat : ticket nat : ticket nat ] */ ; + CDDR ; + PUSH nat 1 + /* [ nat : nat : ticket nat : ticket nat ] */ ; + ASSERT_CMPEQ ; + DROP + /* [ ticket nat ] */ ; + READ_TICKET + /* [ pair address nat nat : ticket nat ] */ ; + CDDR ; + PUSH nat 2 + /* [ nat : nat : ticket nat ] */ ; + ASSERT_CMPEQ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.186 units remaining) michelson_test_scripts/opcodes/ticket_store.tz +{ parameter (ticket nat) ; + storage (option (ticket nat)) ; + code { CAR + /* [ ticket nat ] */ ; + SOME + /* [ option (ticket nat) ] */ ; + NIL operation + /* [ list operation : option (ticket nat) ] */ ; + PAIR + /* [ pair (list operation) (option (ticket nat)) ] */ } } +Well typed (Gas remaining: 1039997.566 units remaining) michelson_test_scripts/opcodes/ticket_store-2.tz +{ parameter (option (ticket nat)) ; + storage (option (ticket nat)) ; + code { CAR + /* [ option (ticket nat) ] */ ; + NIL operation + /* [ list operation : option (ticket nat) ] */ ; + PAIR + /* [ pair (list operation) (option (ticket nat)) ] */ } } +Well typed (Gas remaining: 1039986.866 units remaining) michelson_test_scripts/opcodes/ticketer.tz +{ parameter address ; + storage nat ; + code { UNPAIR + /* [ address : nat ] */ ; + DIP { DUP /* [ nat : nat ] */ } + /* [ address : nat : nat ] */ ; + SWAP + /* [ nat : address : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : address : nat ] */ ; + SWAP + /* [ nat : nat : address : nat ] */ ; + TICKET + /* [ option (ticket nat) : address : nat ] */ ; + ASSERT_SOME ; + DIP { CONTRACT (ticket nat) + /* [ option (contract (ticket nat)) : nat ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract (ticket nat) : nat ] */ } + /* [ ticket nat : mutez : contract (ticket nat) : nat ] */ ; + TRANSFER_TOKENS + /* [ operation : nat ] */ ; + NIL operation + /* [ list operation : operation : nat ] */ ; + SWAP + /* [ operation : list operation : nat ] */ ; + CONS + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039986.345 units remaining) michelson_test_scripts/opcodes/ticketer-2.tz +{ parameter (pair (pair address nat) nat) ; + storage unit ; + code { CAR + /* [ pair (pair address nat) nat ] */ ; + UNPAIR + /* [ pair address nat : nat ] */ ; + UNPAIR + /* [ address : nat : nat ] */ ; + CONTRACT (ticket nat) + /* [ option (contract (ticket nat)) : nat : nat ] */ ; + ASSERT_SOME ; + DIP { TICKET /* [ option (ticket nat) ] */ ; ASSERT_SOME } + /* [ contract (ticket nat) : ticket nat ] */ ; + SWAP + /* [ ticket nat : contract (ticket nat) ] */ ; + DIP { PUSH mutez 0 /* [ mutez : contract (ticket nat) ] */ } + /* [ ticket nat : mutez : contract (ticket nat) ] */ ; + TRANSFER_TOKENS + /* [ operation ] */ ; + NIL operation + /* [ list operation : operation ] */ ; + SWAP + /* [ operation : list operation ] */ ; + CONS + /* [ list operation ] */ ; + UNIT + /* [ unit : list operation ] */ ; + SWAP + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039997.552 units remaining) michelson_test_scripts/opcodes/transfer_amount.tz +{ parameter unit ; + storage mutez ; + code { DROP + /* [] */ ; + AMOUNT + /* [ mutez ] */ ; + NIL operation + /* [ list operation : mutez ] */ ; + PAIR + /* [ pair (list operation) mutez ] */ } } +Well typed (Gas remaining: 1039994.236 units remaining) michelson_test_scripts/opcodes/transfer_tokens.tz +{ parameter (contract unit) ; + storage unit ; + code { CAR + /* [ contract unit ] */ ; + DIP { UNIT /* [ unit ] */ } + /* [ contract unit : unit ] */ ; + PUSH mutez 100000000 + /* [ mutez : contract unit : unit ] */ ; + UNIT + /* [ unit : mutez : contract unit : unit ] */ ; + TRANSFER_TOKENS + /* [ operation : unit ] */ ; + NIL operation + /* [ list operation : operation : unit ] */ ; + SWAP + /* [ operation : list operation : unit ] */ ; + CONS + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.278 units remaining) michelson_test_scripts/opcodes/uncomb.tz +{ parameter (pair nat nat nat) ; + storage nat ; + code { CAR + /* [ pair nat nat nat ] */ ; + UNPAIR 3 + /* [ nat : nat : nat ] */ ; + PUSH nat 100 + /* [ nat : nat : nat : nat ] */ ; + MUL + /* [ nat : nat : nat ] */ ; + SWAP + /* [ nat : nat : nat ] */ ; + PUSH nat 10 + /* [ nat : nat : nat : nat ] */ ; + MUL + /* [ nat : nat : nat ] */ ; + ADD + /* [ nat : nat ] */ ; + ADD + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039904.400 units remaining) michelson_test_scripts/opcodes/unpair.tz +{ parameter (unit :param_unit) ; + storage (unit :u1) ; + code { DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + UNIT + /* [ unit : unit ] */ ; + PAIR + /* [ pair unit unit ] */ ; + UNPAIR + /* [ unit : unit ] */ ; + DROP 2 + /* [] */ ; + UNIT @b + /* [ unit ] */ ; + UNIT @a + /* [ unit : unit ] */ ; + PAIR + /* [ pair unit unit ] */ ; + UNPAIR @c @d + /* [ unit : unit ] */ ; + DROP 2 + /* [] */ ; + UNIT @b + /* [ unit ] */ ; + UNIT @a + /* [ unit : unit ] */ ; + PAIR %@ %@ + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a %b @a @b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @b %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @% %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @% %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @b %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DROP + /* [] */ ; + UNIT @d + /* [ unit ] */ ; + UNIT @c + /* [ unit : unit ] */ ; + PAIR %a %b + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a %b @a @b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @b %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @% %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @% %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @b %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + UNIT + /* [ unit : unit ] */ ; + PAIR %a %b + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR % + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %a %b @a @b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @b %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @% %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @% %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @b %a %b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + UNIT + /* [ unit : unit ] */ ; + PAIR %a %b @p + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @%% @b + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @a @%% + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @%% @%% + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @% @%% + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR @%% @% + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DROP + /* [] */ ; + UNIT @b + /* [ unit ] */ ; + UNIT @a + /* [ unit : unit ] */ ; + PAIR @c + /* [ pair unit unit ] */ ; + UNPAIR @b @a + /* [ unit : unit ] */ ; + DROP 2 + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.787 units remaining) michelson_test_scripts/opcodes/unpair_field_annotation_mismatch.tz +{ parameter (unit :param_unit) ; + storage (unit :u1) ; + code { DROP + /* [] */ ; + UNIT @b + /* [ unit ] */ ; + UNIT @a + /* [ unit : unit ] */ ; + PAIR %@ %@ + /* [ pair unit unit ] */ ; + DUP + /* [ pair unit unit : pair unit unit ] */ ; + UNPAIR %c %d + /* [ unit : unit : pair unit unit ] */ ; + DROP 2 + /* [ pair unit unit ] */ ; + DROP + /* [] */ ; + UNIT + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039993.808 units remaining) michelson_test_scripts/opcodes/update_big_map.tz +{ storage (pair (big_map string string) unit) ; + parameter (map string (option string)) ; + code { UNPAPAIR ; + ITER { UNPAIR + /* [ string : option string : big_map string string : unit ] */ ; + UPDATE + /* [ big_map string string : unit ] */ } + /* [ big_map string string : unit ] */ ; + PAIR + /* [ pair (big_map string string) unit ] */ ; + NIL operation + /* [ list operation : pair (big_map string string) unit ] */ ; + PAIR + /* [ pair (list operation) (big_map string string) unit ] */ } } +Well typed (Gas remaining: 1039985.468 units remaining) michelson_test_scripts/opcodes/utxo_read.tz +{ parameter (pair (ticket nat) nat) ; + storage address ; + code { CAR + /* [ pair (ticket nat) nat ] */ ; + UNPAIR + /* [ ticket nat : nat ] */ ; + READ_TICKET + /* [ pair address nat nat : ticket nat : nat ] */ ; + DIP { DROP /* [ nat ] */ } + /* [ pair address nat nat : nat ] */ ; + UNPAIR + /* [ address : pair nat nat : nat ] */ ; + DIP { UNPAIR /* [ nat : nat : nat ] */ } + /* [ address : nat : nat : nat ] */ ; + DIP 2 { ASSERT_CMPEQ } + /* [ address : nat ] */ ; + DIP { PUSH nat 42 /* [ nat : nat ] */ ; ASSERT_CMPEQ } + /* [ address ] */ ; + NIL operation + /* [ list operation : address ] */ ; + PAIR + /* [ pair (list operation) address ] */ } } +Well typed (Gas remaining: 1039967.053 units remaining) michelson_test_scripts/opcodes/utxor.tz +{ parameter (pair address address) ; + storage nat ; + code { UNPAIR + /* [ pair address address : nat ] */ ; + DIP { DUP /* [ nat : nat ] */ } + /* [ pair address address : nat : nat ] */ ; + SWAP + /* [ nat : pair address address : nat ] */ ; + PUSH nat 5 + /* [ nat : nat : pair address address : nat ] */ ; + SWAP + /* [ nat : nat : pair address address : nat ] */ ; + TICKET + /* [ option (ticket nat) : pair address address : nat ] */ ; + ASSERT_SOME ; + PUSH nat 2 + /* [ nat : ticket nat : pair address address : nat ] */ ; + PUSH nat 3 + /* [ nat : nat : ticket nat : pair address address : nat ] */ ; + PAIR + /* [ pair nat nat : ticket nat : pair address address : nat ] */ ; + SWAP + /* [ ticket nat : pair nat nat : pair address address : nat ] */ ; + SPLIT_TICKET + /* [ option (pair (ticket nat) (ticket nat)) : pair address address : nat ] */ ; + ASSERT_SOME ; + UNPAIR + /* [ ticket nat : ticket nat : pair address address : nat ] */ ; + DIP { DIP { DUP + /* [ pair address address : pair address address : nat ] */ ; + CAR + /* [ address : pair address address : nat ] */ ; + CONTRACT + (pair (ticket nat) nat) + /* [ option (contract (pair (ticket nat) nat)) : pair address address : nat ] */ ; + ASSERT_SOME ; + PUSH mutez + 0 + /* [ mutez : contract (pair (ticket nat) nat) : pair address address : nat ] */ } + /* [ ticket nat : mutez : contract (pair (ticket nat) nat) + : pair address address : nat ] */ ; + PUSH nat + 2 + /* [ nat : ticket nat : mutez : contract (pair (ticket nat) nat) + : pair address address : nat ] */ ; + SWAP + /* [ ticket nat : nat : mutez : contract (pair (ticket nat) nat) + : pair address address : nat ] */ ; + PAIR + /* [ pair (ticket nat) nat : mutez : contract (pair (ticket nat) nat) + : pair address address : nat ] */ } + /* [ ticket nat : pair (ticket nat) nat : mutez + : contract (pair (ticket nat) nat) : pair address address : nat ] */ ; + DIP { TRANSFER_TOKENS /* [ operation : pair address address : nat ] */ } + /* [ ticket nat : operation : pair address address : nat ] */ ; + SWAP + /* [ operation : ticket nat : pair address address : nat ] */ ; + DIP { DIP { CDR + /* [ address : nat ] */ ; + CONTRACT + (pair (ticket nat) nat) + /* [ option (contract (pair (ticket nat) nat)) : nat ] */ ; + ASSERT_SOME ; + PUSH mutez 0 + /* [ mutez : contract (pair (ticket nat) nat) : nat ] */ } + /* [ ticket nat : mutez : contract (pair (ticket nat) nat) : nat ] */ ; + PUSH nat + 3 + /* [ nat : ticket nat : mutez : contract (pair (ticket nat) nat) : nat ] */ ; + SWAP + /* [ ticket nat : nat : mutez : contract (pair (ticket nat) nat) : nat ] */ ; + PAIR + /* [ pair (ticket nat) nat : mutez : contract (pair (ticket nat) nat) : nat ] */ } + /* [ operation : pair (ticket nat) nat : mutez + : contract (pair (ticket nat) nat) : nat ] */ ; + DIP { TRANSFER_TOKENS /* [ operation : nat ] */ } + /* [ operation : operation : nat ] */ ; + NIL operation + /* [ list operation : operation : operation : nat ] */ ; + SWAP + /* [ operation : list operation : operation : nat ] */ ; + CONS + /* [ list operation : operation : nat ] */ ; + SWAP + /* [ operation : list operation : nat ] */ ; + CONS + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039994.728 units remaining) michelson_test_scripts/opcodes/view_fib.tz +{ parameter (pair nat address) ; + storage nat ; + code { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + VIEW "fib" nat + /* [ option nat ] */ ; + IF_SOME + { NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } + { FAIL } } } +Well typed (Gas remaining: 1039993.431 units remaining) michelson_test_scripts/opcodes/view_mutual_recursion.tz +{ parameter (pair nat address) ; + storage nat ; + code { CAR + /* [ pair nat address ] */ ; + DUP + /* [ pair nat address : pair nat address ] */ ; + CDR + /* [ address : pair nat address ] */ ; + SWAP + /* [ pair nat address : address ] */ ; + VIEW "is_twenty" nat + /* [ option nat ] */ ; + IF_SOME + { NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } + { FAIL } } } +Well typed (Gas remaining: 1039994.508 units remaining) michelson_test_scripts/opcodes/view_op_add.tz +{ parameter (pair nat address) ; + storage nat ; + code { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + VIEW "add" nat + /* [ option nat ] */ ; + IF_SOME { /* [ nat ] */ } { FAIL } ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039994.488 units remaining) michelson_test_scripts/opcodes/view_op_constant.tz +{ parameter (pair nat address) ; + storage nat ; + code { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + VIEW "const" nat + /* [ option nat ] */ ; + IF_SOME { /* [ nat ] */ } { FAIL } ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039994.120 units remaining) michelson_test_scripts/opcodes/view_op_id.tz +{ parameter (pair nat address) ; + storage (pair nat nat) ; + code { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + VIEW "id" (pair nat nat) + /* [ option (pair nat nat) ] */ ; + IF_SOME { /* [ pair nat nat ] */ } { FAIL } ; + NIL operation + /* [ list operation : pair nat nat ] */ ; + PAIR + /* [ pair (list operation) nat nat ] */ } } +Well typed (Gas remaining: 1039989.349 units remaining) michelson_test_scripts/opcodes/view_op_nonexistent_addr.tz +{ parameter (pair nat address) ; + storage bool ; + code { DROP + /* [] */ ; + PUSH address "tz1SuakBpFdG9b4twyfrSMqZzruxhpMeSrE5" + /* [ address ] */ ; + PUSH nat 0 + /* [ nat : address ] */ ; + VIEW "test" bool + /* [ option bool ] */ ; + IF_SOME + { DROP /* [] */ ; PUSH bool True /* [ bool ] */ } + { PUSH bool False /* [ bool ] */ } ; + NIL operation + /* [ list operation : bool ] */ ; + PAIR + /* [ pair (list operation) bool ] */ } } +Well typed (Gas remaining: 1039993.957 units remaining) michelson_test_scripts/opcodes/view_op_nonexistent_func.tz +{ parameter (pair nat address) ; + storage bool ; + code { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + VIEW "not_exist" bool + /* [ option bool ] */ ; + IF_SOME + { DROP /* [] */ ; PUSH bool True /* [ bool ] */ } + { PUSH bool False /* [ bool ] */ } ; + NIL operation + /* [ list operation : bool ] */ ; + PAIR + /* [ pair (list operation) bool ] */ } } +Well typed (Gas remaining: 1039994.900 units remaining) michelson_test_scripts/opcodes/view_op_test_step_contants.tz +{ parameter address ; + storage (option (pair (pair mutez mutez) (pair (pair address address) address))) ; + code { CAR + /* [ address ] */ ; + UNIT + /* [ unit : address ] */ ; + VIEW "step_constants" + (pair (pair mutez mutez) (pair (pair address address) address)) + /* [ option (pair (pair mutez mutez) (pair address address) address) ] */ ; + NIL operation + /* [ list operation + : option (pair (pair mutez mutez) (pair address address) address) ] */ ; + PAIR + /* [ pair (list operation) (option (pair (pair mutez mutez) (pair address address) address)) ] */ } } +Well typed (Gas remaining: 1039994.017 units remaining) michelson_test_scripts/opcodes/view_op_toplevel_inconsistent_input_type.tz +{ parameter (pair int address) ; + storage nat ; + code { CAR + /* [ pair int address ] */ ; + UNPAIR + /* [ int : address ] */ ; + VIEW "add" nat + /* [ option nat ] */ ; + IF_SOME { DROP /* [] */ ; PUSH nat 1 /* [ nat ] */ } { PUSH nat 0 /* [ nat ] */ } ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } } +Well typed (Gas remaining: 1039994.017 units remaining) michelson_test_scripts/opcodes/view_op_toplevel_inconsistent_output_type.tz +{ parameter (pair nat address) ; + storage bool ; + code { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + VIEW "add" bool + /* [ option bool ] */ ; + IF_SOME + { DROP /* [] */ ; PUSH bool True /* [ bool ] */ } + { PUSH bool False /* [ bool ] */ } ; + NIL operation + /* [ list operation : bool ] */ ; + PAIR + /* [ pair (list operation) bool ] */ } } +Well typed (Gas remaining: 1039988.594 units remaining) michelson_test_scripts/opcodes/view_rec.tz +{ parameter unit ; + storage unit ; + view "loop" + address + never + { CAR + /* [ address ] */ ; + DUP + /* [ address : address ] */ ; + VIEW "loop" never + /* [ option never ] */ ; + ASSERT_SOME } ; + code { CDR + /* [ unit ] */ ; + SELF + /* [ contract unit : unit ] */ ; + ADDRESS + /* [ address : unit ] */ ; + DUP + /* [ address : address : unit ] */ ; + VIEW "loop" never + /* [ option never : unit ] */ ; + ASSERT_SOME ; + DROP + /* [ unit ] */ ; + NIL operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } +Well typed (Gas remaining: 1039948.512 units remaining) michelson_test_scripts/opcodes/view_toplevel_lib.tz +{ parameter nat ; + storage nat ; + code { CAR + /* [ nat ] */ ; + NIL operation + /* [ list operation : nat ] */ ; + PAIR + /* [ pair (list operation) nat ] */ } ; + view "add" nat nat { UNPAIR /* [ nat : nat ] */ ; ADD /* [ nat ] */ } ; + view "id" nat (pair nat nat) { /* [ pair nat nat ] */ } ; + view "test_failwith" nat (pair nat nat) { FAILWITH /* [] */ } ; + view "step_constants" + unit + (pair (pair mutez mutez) (pair (pair address address) address)) + { DROP + /* [] */ ; + SOURCE + /* [ address ] */ ; + SENDER + /* [ address : address ] */ ; + SELF_ADDRESS + /* [ address : address : address ] */ ; + PAIR + /* [ pair address address : address ] */ ; + PAIR + /* [ pair (pair address address) address ] */ ; + BALANCE + /* [ mutez : pair (pair address address) address ] */ ; + AMOUNT + /* [ mutez : mutez : pair (pair address address) address ] */ ; + PAIR + /* [ pair mutez mutez : pair (pair address address) address ] */ ; + PAIR + /* [ pair (pair mutez mutez) (pair address address) address ] */ } ; + view "succ" + (pair nat address) + nat + { CAR + /* [ pair nat address ] */ ; + UNPAIR + /* [ nat : address ] */ ; + PUSH nat 1 + /* [ nat : nat : address ] */ ; + ADD + /* [ nat : address ] */ ; + PAIR + /* [ pair nat address ] */ ; + DUP + /* [ pair nat address : pair nat address ] */ ; + CDR + /* [ address : pair nat address ] */ ; + SWAP + /* [ pair nat address : address ] */ ; + VIEW "is_twenty" nat + /* [ option nat ] */ ; + ASSERT_SOME } ; + view "is_twenty" + (pair nat address) + nat + { CAR + /* [ pair nat address ] */ ; + DUP + /* [ pair nat address : pair nat address ] */ ; + CAR + /* [ nat : pair nat address ] */ ; + PUSH nat 20 + /* [ nat : nat : pair nat address ] */ ; + COMPARE + /* [ int : pair nat address ] */ ; + EQ + /* [ bool : pair nat address ] */ ; + IF { CAR /* [ nat ] */ } + { DUP + /* [ pair nat address : pair nat address ] */ ; + CDR + /* [ address : pair nat address ] */ ; + SWAP + /* [ pair nat address : address ] */ ; + VIEW "succ" nat + /* [ option nat ] */ ; + ASSERT_SOME } } ; + view "fib" + nat + nat + { CAR + /* [ nat ] */ ; + DUP + /* [ nat : nat ] */ ; + PUSH nat 0 + /* [ nat : nat : nat ] */ ; + COMPARE + /* [ int : nat ] */ ; + EQ + /* [ bool : nat ] */ ; + IF { /* [ nat ] */ } + { DUP + /* [ nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat ] */ ; + COMPARE + /* [ int : nat ] */ ; + EQ + /* [ bool : nat ] */ ; + IF { /* [ nat ] */ } + { DUP + /* [ nat : nat ] */ ; + PUSH nat 1 + /* [ nat : nat : nat ] */ ; + SWAP + /* [ nat : nat : nat ] */ ; + SUB + /* [ int : nat ] */ ; + ABS + /* [ nat : nat ] */ ; + SELF_ADDRESS + /* [ address : nat : nat ] */ ; + SWAP + /* [ nat : address : nat ] */ ; + VIEW "fib" nat + /* [ option nat : nat ] */ ; + IF_SOME + { SWAP + /* [ nat : nat ] */ ; + PUSH nat 2 + /* [ nat : nat : nat ] */ ; + SWAP + /* [ nat : nat : nat ] */ ; + SUB + /* [ int : nat ] */ ; + ABS + /* [ nat : nat ] */ ; + SELF_ADDRESS + /* [ address : nat : nat ] */ ; + SWAP + /* [ nat : address : nat ] */ ; + VIEW "fib" nat + /* [ option nat : nat ] */ ; + IF_SOME { ADD /* [ nat ] */ } { FAIL } } + { FAIL } } } } } +Well typed (Gas remaining: 1039995.372 units remaining) michelson_test_scripts/opcodes/voting_power.tz +{ parameter key ; + storage (pair nat nat) ; + code { CAR + /* [ key ] */ ; + HASH_KEY + /* [ key_hash ] */ ; + VOTING_POWER + /* [ nat ] */ ; + DIP { TOTAL_VOTING_POWER /* [ nat ] */ } + /* [ nat : nat ] */ ; + PAIR + /* [ pair nat nat ] */ ; + NIL operation + /* [ list operation : pair nat nat ] */ ; + PAIR + /* [ pair (list operation) nat nat ] */ } } +Well typed (Gas remaining: 1039992.866 units remaining) michelson_test_scripts/opcodes/xor.tz +{ parameter (or (pair bool bool) (pair nat nat)) ; + storage (option (or bool nat)) ; + code { CAR + /* [ or (pair bool bool) (pair nat nat) ] */ ; + IF_LEFT + { UNPAIR /* [ bool : bool ] */ ; XOR /* [ bool ] */ ; LEFT nat /* [ or bool nat ] */ } + { UNPAIR /* [ nat : nat ] */ ; XOR /* [ nat ] */ ; RIGHT bool /* [ or bool nat ] */ } ; + SOME + /* [ option (or bool nat) ] */ ; + NIL operation + /* [ list operation : option (or bool nat) ] */ ; + PAIR + /* [ pair (list operation) (option (or bool nat)) ] */ } } +Well typed (Gas remaining: 1039978.970 units remaining) michelson_test_scripts/opcodes/xor_bytes_016.tz +{ parameter unit ; + storage unit ; + code { DROP + /* [] */ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + PUSH bytes 0x06 + /* [ bytes : bytes ] */ ; + XOR + /* [ bytes ] */ ; + PUSH bytes 0x03 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x0005 + /* [ bytes ] */ ; + PUSH bytes 0x0106 + /* [ bytes : bytes ] */ ; + XOR + /* [ bytes ] */ ; + PUSH bytes 0x0103 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + PUSH bytes 0x05 + /* [ bytes ] */ ; + PUSH bytes 0x0106 + /* [ bytes : bytes ] */ ; + XOR + /* [ bytes ] */ ; + PUSH bytes 0x0103 + /* [ bytes : bytes ] */ ; + ASSERT_CMPEQ ; + UNIT + /* [ unit ] */ ; + NIL @noop operation + /* [ list operation : unit ] */ ; + PAIR + /* [ pair (list operation) unit ] */ } } diff --git a/tezt/tests/expected/create_contract.ml/Paris- Create contract.out b/tezt/tests/expected/create_contract.ml/Parisb- Create contract.out similarity index 100% rename from tezt/tests/expected/create_contract.ml/Paris- Create contract.out rename to tezt/tests/expected/create_contract.ml/Parisb- Create contract.out diff --git a/tezt/tests/expected/create_contract.ml/Parisc- Create contract.out b/tezt/tests/expected/create_contract.ml/Parisc- Create contract.out new file mode 100644 index 000000000000..2a884632e8fc --- /dev/null +++ b/tezt/tests/expected/create_contract.ml/Parisc- Create contract.out @@ -0,0 +1,109 @@ + +./octez-client --mode mockup --wait none originate contract originate_contract transferring 200 from bootstrap1 running michelson_test_scripts/mini_scenarios/originate_contract.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 599.311 units (will add 100 for safety) +Estimated storage: 350 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000393 + Expected counter: 1 + Gas limit: 700 + Storage limit: 370 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000393 + payload fees(the block proposer) ....... +ꜩ0.000393 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ200 + Script: + { parameter unit ; + storage unit ; + code { DROP ; + UNIT ; + AMOUNT ; + NONE key_hash ; + CREATE_CONTRACT + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } ; + DIP { DROP ; PUSH unit Unit ; NIL operation } ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 93 bytes + Paid storage size diff: 93 bytes + Consumed gas: 599.277 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.02325 + storage fees ........................... +ꜩ0.02325 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ200 + [CONTRACT_HASH] ... +ꜩ200 + +New contract [CONTRACT_HASH] originated. +Contract memorized as originate_contract. + +./octez-client --mode mockup --wait none transfer 1 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --arg Unit +Node is bootstrapped. +Estimated gas: 1793.731 units (will add 100 for safety) +Estimated storage: 295 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 1894 + Storage limit: 315 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Transaction: + Amount: ꜩ1 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: Unit + Storage size: 93 bytes + Consumed gas: 1289.005 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + Internal operations: + Internal Origination: + From: [CONTRACT_HASH] + Credit: ꜩ1 + Script: + { parameter unit ; storage unit ; code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 38 bytes + Paid storage size diff: 38 bytes + Consumed gas: 505.294 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0095 + storage fees ........................... +ꜩ0.0095 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [CONTRACT_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + +New contract [CONTRACT_HASH] originated. diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test Coordinator-s post preimage).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test Coordinator-s post preimage).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test Coordinator-s post preimage).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test Coordinator-s post preimage).out diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-certificate).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-certificate).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-certificate).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-certificate).out diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-missing_page).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-missing_page).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-missing_page).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-missing_page).out diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-preimage).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-preimage).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test GET v0-preimage).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test GET v0-preimage).out diff --git a/tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out b/tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out similarity index 100% rename from tezt/tests/expected/dac.ml/Paris- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out rename to tezt/tests/expected/dac.ml/Parisb- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test Coordinator-s post preimage).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test Coordinator-s post preimage).out new file mode 100644 index 000000000000..bb7224052703 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test Coordinator-s post preimage).out @@ -0,0 +1,7 @@ +RPC_REQUEST_URI: POST $SCHEME://$HOST:$PORT/v0/preimage +RPC_REQUEST_HEADER: Content-Type: application/json + + +RPC_REQUEST_BODY: "74657374" +RPC_RESPONSE_BODY: "00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6" + diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-certificate).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-certificate).out new file mode 100644 index 000000000000..e4e77754f770 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-certificate).out @@ -0,0 +1,6 @@ +RPC_REQUEST_URI: GET $SCHEME://$HOST:$PORT/v0/certificates/00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6 +RPC_REQUEST_HEADER: Content-Type: application/json + + +RPC_RESPONSE_BODY: {"version":0,"root_hash":"00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6","aggregate_signature":"[AGGREGATED_SIG]","witnesses":"1"} + diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-missing_page).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-missing_page).out new file mode 100644 index 000000000000..11852713b787 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-missing_page).out @@ -0,0 +1,6 @@ +RPC_REQUEST_URI: GET $SCHEME://$HOST:$PORT/v0/missing_page/00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6 +RPC_REQUEST_HEADER: Content-Type: application/json + + +RPC_RESPONSE_BODY: "000000000474657374" + diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out new file mode 100644 index 000000000000..903c9d0a2847 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-certificate).out @@ -0,0 +1,6 @@ +RPC_REQUEST_URI: GET $SCHEME://$HOST:$PORT/v0/monitor/certificate/00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6 +RPC_REQUEST_HEADER: Content-Type: application/json + + +{"version":0,"root_hash":"00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6","aggregate_signature":"[AGGREGATED_SIG]","witnesses":"1"} + diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out new file mode 100644 index 000000000000..4870365dfa08 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-monitor-root_hashes).out @@ -0,0 +1,4 @@ +RPC_REQUEST_URI: GET $SCHEME://$HOST:$PORT/v0/monitor/root_hashes +RPC_REQUEST_HEADER: Content-Type: application/json + + diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-preimage).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-preimage).out new file mode 100644 index 000000000000..cf7625cfc1d6 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test GET v0-preimage).out @@ -0,0 +1,6 @@ +RPC_REQUEST_URI: GET $SCHEME://$HOST:$PORT/v0/preimage/00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6 +RPC_REQUEST_HEADER: Content-Type: application/json + + +RPC_RESPONSE_BODY: "000000000474657374" + diff --git a/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out new file mode 100644 index 000000000000..95ebde52ff78 --- /dev/null +++ b/tezt/tests/expected/dac.ml/Parisc- Testing Full DAC infrastructure (test PUT v0-dac_member_signature).out @@ -0,0 +1,11 @@ +RPC_REQUEST_URI: PUT $SCHEME://$HOST:$PORT/v0/dac_member_signature +RPC_REQUEST_HEADER: Content-Type: application/json + + +RPC_REQUEST_BODY: { + "root_hash": "00a3703854279d2f377d689163d1ec911a840d84b56c4c6f6cafdf0610394df7c6", + "signer_pkh": "[PUBLIC_KEY_HASH]", + "signature": "[AGGREGATED_SIG]" +} +RPC_RESPONSE_BODY: {} + diff --git a/tezt/tests/expected/dal.ml/Paris- Test following dal and baker tutorial commands.out b/tezt/tests/expected/dal.ml/Parisb- Test following dal and baker tutorial commands.out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Test following dal and baker tutorial commands.out rename to tezt/tests/expected/dal.ml/Parisb- Test following dal and baker tutorial commands.out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL L1 integration (Use all available slots).out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL L1 integration (Use all available slots).out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL L1 integration (Use all available slots).out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL L1 integration (Use all available slots).out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test echo_kernel).out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test echo_kernel).out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test echo_kernel).out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test echo_kernel).out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec wa.out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec wa.out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test tx_kernel).out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test tx_kernel).out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test tx_kernel).out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test tx_kernel).out diff --git a/tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slots.out b/tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out similarity index 100% rename from tezt/tests/expected/dal.ml/Paris- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slots.out rename to tezt/tests/expected/dal.ml/Parisb- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out diff --git a/tezt/tests/expected/dal.ml/Parisc- Test following dal and baker tutorial commands.out b/tezt/tests/expected/dal.ml/Parisc- Test following dal and baker tutorial commands.out new file mode 100644 index 000000000000..d9d3a08feb10 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Test following dal and baker tutorial commands.out @@ -0,0 +1,125 @@ + +./octez-client --wait none transfer 500000 from bootstrap1 to my_baker --burn-cap 1 +Node is bootstrapped. +Estimated gas: 168.854 units (will add 0 for safety) +Estimated storage: 257 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000271 + Expected counter: 1 + Gas limit: 169 + Storage limit: 277 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000271 + payload fees(the block proposer) ....... +ꜩ0.000271 + Transaction: + Amount: ꜩ500000 + From: [PUBLIC_KEY_HASH] + To: [PUBLIC_KEY_HASH] + This transaction was successfully applied + Consumed gas: 168.821 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ500000 + [PUBLIC_KEY_HASH] ... +ꜩ500000 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + + +./octez-client rpc get /chains/main/blocks/head/context/adaptive_issuance_launch_cycle +0 + +./octez-client --wait none register key my_baker as delegate +Node is bootstrapped. +Estimated gas: 170.669 units (will add 0 for safety) +Estimated storage: no bytes added +Estimated gas: 100 units (will add 0 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000275 + Expected counter: 2 + Gas limit: 171 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000275 + payload fees(the block proposer) ....... +ꜩ0.000275 + Revelation of manager public key: + Contract: [PUBLIC_KEY_HASH] + Key: [PUBLIC_KEY] + This revelation was successfully applied + Consumed gas: 170.503 + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000159 + Expected counter: 3 + Gas limit: 100 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000159 + payload fees(the block proposer) ....... +ꜩ0.000159 + Delegation: + Contract: [PUBLIC_KEY_HASH] + To: [PUBLIC_KEY_HASH] + This delegation was successfully applied + Consumed gas: 100 + + +./octez-client --wait none stake 499900 for my_baker +Node is bootstrapped. +Estimated gas: 3629.086 units (will add 0 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000623 + Expected counter: 4 + Gas limit: 3630 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000623 + payload fees(the block proposer) ....... +ꜩ0.000623 + Transaction: + Amount: ꜩ499900 + From: [PUBLIC_KEY_HASH] + To: [PUBLIC_KEY_HASH] + Entrypoint: stake + This transaction was successfully applied + Consumed gas: 3629.020 + Balance updates: + [PUBLIC_KEY_HASH] ............. -ꜩ499900 + deposits([PUBLIC_KEY_HASH]) ... +ꜩ499900 + + +./octez-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]' +{ "full_balance": "499999998943", "current_frozen_deposits": "499900000000", + "frozen_deposits": "0", "staking_balance": "499999998943", + "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], + "delegated_balance": "0", + "min_delegated_in_current_cycle": + { "amount": "99998943", + "level": + { "level": 4, "level_position": 3, "cycle": 0, "cycle_position": 3, + "expected_commitment": true } }, "deactivated": false, + "grace_period": 5, "pending_denunciations": false, + "total_delegated_stake": "0", "staking_denominator": "0", + "active_consensus_key": "[PUBLIC_KEY_HASH]" } diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL L1 integration (Use all available slots).out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL L1 integration (Use all available slots).out new file mode 100644 index 000000000000..1aa1074dc365 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL L1 integration (Use all available slots).out @@ -0,0 +1,163 @@ +GET http://[HOST]:[PORT]/chains/main/blocks/head/metadata +200 OK +{"protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","next_protocol":"PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi","test_chain_status":{"status":"not_running"},"max_operations_ttl":3,"max_operation_data_length":32768,"max_block_header_length":289,"max_operation_list_length":[{"max_size":4194304,"max_op":2048},{"max_size":32768},{"max_size":135168,"max_op":132},{"max_size":524288}],"proposer":"[PUBLIC_KEY_HASH]","baker":"[PUBLIC_KEY_HASH]","level_info":{"level":3,"level_position":2,"cycle":0,"cycle_position":2,"expected_commitment":false},"voting_period_info":{"voting_period":{"index":0,"kind":"proposal","start_position":0},"position":2,"remaining":61},"nonce_hash":null,"deactivated":[],"balance_updates":[{"kind":"accumulator","category":"block fees","change":"-416000","origin":"block"},{"kind":"contract","contract":"[PUBLIC_KEY_HASH]","change":"416000","origin":"block"},{"kind":"minted","category":"baking rewards","change":"-16667","origin":"block"},{"kind":"freezer","category":"deposits","staker":{"baker_own_stake":"[PUBLIC_KEY_HASH]"},"change":"16667","origin":"block"},{"kind":"minted","category":"baking rewards","change":"-316666","origin":"block"},{"kind":"contract","contract":"[PUBLIC_KEY_HASH]","change":"316666","origin":"block"},{"kind":"minted","category":"baking bonuses","change":"-16666","origin":"block"},{"kind":"freezer","category":"deposits","staker":{"baker_own_stake":"[PUBLIC_KEY_HASH]"},"change":"16666","origin":"block"},{"kind":"minted","category":"baking bonuses","change":"-316646","origin":"block"},{"kind":"contract","contract":"[PUBLIC_KEY_HASH]","change":"316646","origin":"block"}],"liquidity_baking_toggle_ema":0,"adaptive_issuance_vote_ema":0,"adaptive_issuance_activation_cycle":5,"implicit_operations_results":[{"kind":"transaction","storage":[{"int":"1"},{"int":"166766"},{"int":"100"},{"bytes":"01e927f00ef734dfc85919635e9afc9166c83ef9fc00"},{"bytes":"0115eb0104481a6d7921160bc982c5e0a561cd8a3a00"}],"balance_updates":[{"kind":"minted","category":"subsidy","change":"-83333","origin":"subsidy"},{"kind":"contract","contract":"[CONTRACT_HASH]","change":"83333","origin":"subsidy"}],"consumed_milligas":"206420","storage_size":"4629"}],"proposer_consensus_key":"[PUBLIC_KEY_HASH]","baker_consensus_key":"[PUBLIC_KEY_HASH]","consumed_milligas":"544000000","dal_attestation":"0"} + +{ + "protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "next_protocol": "PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi", + "test_chain_status": { + "status": "not_running" + }, + "max_operations_ttl": 3, + "max_operation_data_length": 32768, + "max_block_header_length": 289, + "max_operation_list_length": [ + { + "max_size": 4194304, + "max_op": 2048 + }, + { + "max_size": 32768 + }, + { + "max_size": 135168, + "max_op": 132 + }, + { + "max_size": 524288 + } + ], + "proposer": "[PUBLIC_KEY_HASH]", + "baker": "[PUBLIC_KEY_HASH]", + "level_info": { + "level": 3, + "level_position": 2, + "cycle": 0, + "cycle_position": 2, + "expected_commitment": false + }, + "voting_period_info": { + "voting_period": { + "index": 0, + "kind": "proposal", + "start_position": 0 + }, + "position": 2, + "remaining": 61 + }, + "nonce_hash": null, + "deactivated": [], + "balance_updates": [ + { + "kind": "accumulator", + "category": "block fees", + "change": "-416000", + "origin": "block" + }, + { + "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "416000", + "origin": "block" + }, + { + "kind": "minted", + "category": "baking rewards", + "change": "-16667", + "origin": "block" + }, + { + "kind": "freezer", + "category": "deposits", + "staker": { + "baker_own_stake": "[PUBLIC_KEY_HASH]" + }, + "change": "16667", + "origin": "block" + }, + { + "kind": "minted", + "category": "baking rewards", + "change": "-316666", + "origin": "block" + }, + { + "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "316666", + "origin": "block" + }, + { + "kind": "minted", + "category": "baking bonuses", + "change": "-16666", + "origin": "block" + }, + { + "kind": "freezer", + "category": "deposits", + "staker": { + "baker_own_stake": "[PUBLIC_KEY_HASH]" + }, + "change": "16666", + "origin": "block" + }, + { + "kind": "minted", + "category": "baking bonuses", + "change": "-316646", + "origin": "block" + }, + { + "kind": "contract", + "contract": "[PUBLIC_KEY_HASH]", + "change": "316646", + "origin": "block" + } + ], + "liquidity_baking_toggle_ema": 0, + "adaptive_issuance_vote_ema": 0, + "adaptive_issuance_activation_cycle": 5, + "implicit_operations_results": [ + { + "kind": "transaction", + "storage": [ + { + "int": "1" + }, + { + "int": "166766" + }, + { + "int": "100" + }, + { + "bytes": "01e927f00ef734dfc85919635e9afc9166c83ef9fc00" + }, + { + "bytes": "0115eb0104481a6d7921160bc982c5e0a561cd8a3a00" + } + ], + "balance_updates": [ + { + "kind": "minted", + "category": "subsidy", + "change": "-83333", + "origin": "subsidy" + }, + { + "kind": "contract", + "contract": "[CONTRACT_HASH]", + "change": "83333", + "origin": "subsidy" + } + ], + "consumed_milligas": "206420", + "storage_size": "4629" + } + ], + "proposer_consensus_key": "[PUBLIC_KEY_HASH]", + "baker_consensus_key": "[PUBLIC_KEY_HASH]", + "consumed_milligas": "544000000", + "dal_attestation": "0" +} diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out new file mode 100644 index 000000000000..b1c30c2808ff --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out @@ -0,0 +1,109 @@ + +./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/genesis_info' +{ "level": 2, + "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } + +./octez-client --wait none send smart rollup message '["dal:16:8:32:0:2:4:6"]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 170.903 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000279 + Expected counter: 1 + Gas limit: 271 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000279 + payload fees(the block proposer) ....... +ꜩ0.000279 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 170.836 + +GET http://[HOST]:[PORT]/global/block/head/dal/slot_headers +200 OK +[{"version":"0","level":4,"index":0,"commitment":"[DAL_SLOT_HEADER]"},{"version":"0","level":4,"index":1,"commitment":"[DAL_SLOT_HEADER]"},{"version":"0","level":4,"index":2,"commitment":"[DAL_SLOT_HEADER]"}] + +GET http://[HOST]:[PORT]/global/block/head/dal/processed_slots +200 OK +[{"index":0,"status":"unconfirmed"},{"index":1,"status":"confirmed"},{"index":2,"status":"confirmed"},{"index":3,"status":"unconfirmed"},{"index":4,"status":"unconfirmed"},{"index":5,"status":"unconfirmed"},{"index":6,"status":"unconfirmed"},{"index":7,"status":"unconfirmed"},{"index":8,"status":"unconfirmed"},{"index":9,"status":"unconfirmed"},{"index":10,"status":"unconfirmed"},{"index":11,"status":"unconfirmed"},{"index":12,"status":"unconfirmed"},{"index":13,"status":"unconfirmed"},{"index":14,"status":"unconfirmed"},{"index":15,"status":"unconfirmed"}] + +GET http://[HOST]:[PORT]/global/block/12/dal/processed_slots +200 OK +[{"index":0,"status":"unconfirmed"},{"index":1,"status":"confirmed"},{"index":2,"status":"confirmed"},{"index":3,"status":"unconfirmed"},{"index":4,"status":"unconfirmed"},{"index":5,"status":"unconfirmed"},{"index":6,"status":"unconfirmed"},{"index":7,"status":"unconfirmed"},{"index":8,"status":"unconfirmed"},{"index":9,"status":"unconfirmed"},{"index":10,"status":"unconfirmed"},{"index":11,"status":"unconfirmed"},{"index":12,"status":"unconfirmed"},{"index":13,"status":"unconfirmed"},{"index":14,"status":"unconfirmed"},{"index":15,"status":"unconfirmed"}] + + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/genesis_info' +{ "level": 2, + "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } + +./octez-client --wait none send smart rollup message '[" 99 3 "," + + value"]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 172.978 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00028 + Expected counter: 3 + Gas limit: 273 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00028 + payload fees(the block proposer) ....... +ꜩ0.00028 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 172.912 + +GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value +200 OK +"000001f6" + diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out new file mode 100644 index 000000000000..b550bb53b458 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out @@ -0,0 +1,76 @@ + +./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/genesis_info' +{ "level": 2, + "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } + +./octez-client --wait none send smart rollup message '["dal:16:8:32:0:2:4:6"]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 170.903 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000279 + Expected counter: 1 + Gas limit: 271 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000279 + payload fees(the block proposer) ....... +ꜩ0.000279 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 170.836 + +GET http://[HOST]:[PORT]/global/block/head/dal/slot_headers +200 OK +[{"version":"0","level":4,"index":0,"commitment":"[DAL_SLOT_HEADER]"},{"version":"0","level":4,"index":1,"commitment":"[DAL_SLOT_HEADER]"},{"version":"0","level":4,"index":2,"commitment":"[DAL_SLOT_HEADER]"}] + +GET http://[HOST]:[PORT]/global/block/head/dal/processed_slots +200 OK +[{"index":0,"status":"unconfirmed"},{"index":1,"status":"confirmed"},{"index":2,"status":"confirmed"},{"index":3,"status":"unconfirmed"},{"index":4,"status":"unconfirmed"},{"index":5,"status":"unconfirmed"},{"index":6,"status":"unconfirmed"},{"index":7,"status":"unconfirmed"},{"index":8,"status":"unconfirmed"},{"index":9,"status":"unconfirmed"},{"index":10,"status":"unconfirmed"},{"index":11,"status":"unconfirmed"},{"index":12,"status":"unconfirmed"},{"index":13,"status":"unconfirmed"},{"index":14,"status":"unconfirmed"},{"index":15,"status":"unconfirmed"}] + +GET http://[HOST]:[PORT]/global/block/12/dal/processed_slots +200 OK +[{"index":0,"status":"unconfirmed"},{"index":1,"status":"confirmed"},{"index":2,"status":"confirmed"},{"index":3,"status":"unconfirmed"},{"index":4,"status":"unconfirmed"},{"index":5,"status":"unconfirmed"},{"index":6,"status":"unconfirmed"},{"index":7,"status":"unconfirmed"},{"index":8,"status":"unconfirmed"},{"index":9,"status":"unconfirmed"},{"index":10,"status":"unconfirmed"},{"index":11,"status":"unconfirmed"},{"index":12,"status":"unconfirmed"},{"index":13,"status":"unconfirmed"},{"index":14,"status":"unconfirmed"},{"index":15,"status":"unconfirmed"}] + diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test echo_kernel).out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test echo_kernel).out new file mode 100644 index 000000000000..2f6f670223d3 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test echo_kernel).out @@ -0,0 +1,39 @@ + +./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind wasm_2_0_0 of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: wasm_2_0_0 + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/value?key=/output/slot-0 +200 OK +"68656c6c6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out new file mode 100644 index 000000000000..d4f6045bf607 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test reveal_dal_page in fast exec w.out @@ -0,0 +1,39 @@ + +./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind wasm_2_0_0 of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: wasm_2_0_0 + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/value?key=/output/slot-0 +200 OK +"6162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162636162" + diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test tx_kernel).out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test tx_kernel).out new file mode 100644 index 000000000000..837c6aecb4d3 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test tx_kernel).out @@ -0,0 +1,35 @@ + +./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind wasm_2_0_0 of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: wasm_2_0_0 + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" diff --git a/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out new file mode 100644 index 000000000000..6222cc4172c1 --- /dev/null +++ b/tezt/tests/expected/dal.ml/Parisc- Testing DAL rollup and node with L1 (test_lag-10_time-8_preinject-1_slot.out @@ -0,0 +1,101 @@ + +./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" + +./octez-client --wait none send smart rollup message '[" dal:16:10:32:5 "]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 170.788 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000276 + Expected counter: 1 + Gas limit: 271 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000276 + payload fees(the block proposer) ....... +ꜩ0.000276 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 170.722 + + +./octez-client --wait none send smart rollup message '["+ value"]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 170.444 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000267 + Expected counter: 4 + Gas limit: 271 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000267 + payload fees(the block proposer) ....... +ꜩ0.000267 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 170.378 + +GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value +200 OK +"0000000d" + +GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value +200 OK +"0000000d" + +GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value +200 OK +"0000000d" + +GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value +200 OK +"0000000d" + diff --git a/tezt/tests/expected/deposits_limit.ml/Paris- set deposits limit.out b/tezt/tests/expected/deposits_limit.ml/Parisb- set deposits limit.out similarity index 100% rename from tezt/tests/expected/deposits_limit.ml/Paris- set deposits limit.out rename to tezt/tests/expected/deposits_limit.ml/Parisb- set deposits limit.out diff --git a/tezt/tests/expected/deposits_limit.ml/Paris- unset deposits limit.out b/tezt/tests/expected/deposits_limit.ml/Parisb- unset deposits limit.out similarity index 100% rename from tezt/tests/expected/deposits_limit.ml/Paris- unset deposits limit.out rename to tezt/tests/expected/deposits_limit.ml/Parisb- unset deposits limit.out diff --git a/tezt/tests/expected/deposits_limit.ml/Parisc- set deposits limit.out b/tezt/tests/expected/deposits_limit.ml/Parisc- set deposits limit.out new file mode 100644 index 000000000000..8ac64a759156 --- /dev/null +++ b/tezt/tests/expected/deposits_limit.ml/Parisc- set deposits limit.out @@ -0,0 +1,26 @@ +Node is bootstrapped. +Estimated gas: 168.052 units (will add 0 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is 'oogPg9fm3Wo8Fub69ehKvyhmefv442MSvvKME7awo3zvZVAsuTo' +NOT waiting for the operation to be included. +Use command + octez-client wait for oogPg9fm3Wo8Fub69ehKvyhmefv442MSvvKME7awo3zvZVAsuTo to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2 +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.000247 + Expected counter: 1 + Gas limit: 169 + Storage limit: 0 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000247 + payload fees(the block proposer) ....... +ꜩ0.000247 + Set deposits limit: + Delegate: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Limit: 1000 + This deposits limit modification was successfully applied + Consumed gas: 167.986 + + diff --git a/tezt/tests/expected/deposits_limit.ml/Parisc- unset deposits limit.out b/tezt/tests/expected/deposits_limit.ml/Parisc- unset deposits limit.out new file mode 100644 index 000000000000..fc4436f54195 --- /dev/null +++ b/tezt/tests/expected/deposits_limit.ml/Parisc- unset deposits limit.out @@ -0,0 +1,26 @@ +Node is bootstrapped. +Estimated gas: 167.886 units (will add 0 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is 'oo1PJ41t8u2VYdoeFVgREH9LKKtASE141H3wWRmKRbuBcshW3hR' +NOT waiting for the operation to be included. +Use command + octez-client wait for oo1PJ41t8u2VYdoeFVgREH9LKKtASE141H3wWRmKRbuBcshW3hR to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2 +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Fee to the baker: ꜩ0.000242 + Expected counter: 1 + Gas limit: 168 + Storage limit: 0 bytes + Balance updates: + tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ0.000242 + payload fees(the block proposer) ....... +ꜩ0.000242 + Set deposits limit: + Delegate: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx + Unlimited deposits + This deposits limit modification was successfully applied + Consumed gas: 167.820 + + diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- block_header.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- block_header.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- block_header.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- block_header.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- block_header.raw.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- block_header.raw.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- block_header.raw.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- block_header.raw.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- block_header.unsigned.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- block_header.unsigned.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- block_header.unsigned.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- block_header.unsigned.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- contract.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- contract.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- contract.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- contract.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- cycle.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- cycle.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- cycle.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- cycle.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- fitness.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- fitness.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- fitness.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- fitness.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- gas.cost.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- gas.cost.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- gas.cost.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- gas.cost.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- gas.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- gas.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- gas.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- gas.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- level.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- level.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- level.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- level.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- nonce.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- nonce.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- nonce.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- nonce.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.internal.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.internal.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.internal.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.internal.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.raw.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.raw.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.raw.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.raw.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.unsigned.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.unsigned.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation.unsigned.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation.unsigned.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation_with_legacy.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation_with_legacy.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation_with_legacy.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation_with_legacy.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation_with_legacy.unsigned.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation_with_legacy.unsigned.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- operation_with_legacy.unsigned.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- operation_with_legacy.unsigned.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- period.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- period.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- period.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- period.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- raw_level.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- raw_level.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- raw_level.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- raw_level.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- seed.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- seed.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- seed.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- seed.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- tez.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- tez.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- tez.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- tez.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- timestamp.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- timestamp.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- timestamp.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- timestamp.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- vote.ballot.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- vote.ballot.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- vote.ballot.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- vote.ballot.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- vote.ballots.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- vote.ballots.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- vote.ballots.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- vote.ballots.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- vote.listings.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- vote.listings.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- vote.listings.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- vote.listings.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- voting_period.kind.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- voting_period.kind.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- voting_period.kind.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- voting_period.kind.out diff --git a/tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- voting_period.out b/tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- voting_period.out similarity index 100% rename from tezt/tests/expected/encoding.ml/Paris- protocol encoding regression test- voting_period.out rename to tezt/tests/expected/encoding.ml/Parisb- protocol encoding regression test- voting_period.out diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.out new file mode 100644 index 000000000000..571822437255 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.out @@ -0,0 +1,36 @@ + +./octez-codec encode 020-PsParisC.block_header from '{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 +}' +00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d5580166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.block_header from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d5580166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "level": 1331, "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.raw.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.raw.out new file mode 100644 index 000000000000..07fed921078f --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.raw.out @@ -0,0 +1,26 @@ + +./octez-codec encode 020-PsParisC.block_header.raw from '{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "protocol_data": "521d101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" +}' +00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c521d101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.block_header.raw from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c521d101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "level": 1331, "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "protocol_data": + "521d101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.unsigned.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.unsigned.out new file mode 100644 index 000000000000..9ac702cb901c --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- block_header.unsigned.out @@ -0,0 +1,33 @@ + +./octez-codec encode 020-PsParisC.block_header.unsigned from '{ + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 +}' +00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55801 + +./octez-codec decode 020-PsParisC.block_header.unsigned from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55801 +{ "level": 1331, "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 2, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", + "liquidity_baking_toggle_vote": "off", "adaptive_issuance_vote": "on" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- contract.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- contract.out new file mode 100644 index 000000000000..dff7d7c33ec1 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- contract.out @@ -0,0 +1,12 @@ + +./octez-codec encode 020-PsParisC.contract from '"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx"' +000002298c03ed7d454a101eb7022bc95f7e5f41ac78 + +./octez-codec decode 020-PsParisC.contract from 000002298c03ed7d454a101eb7022bc95f7e5f41ac78 +"tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + +./octez-codec encode 020-PsParisC.contract from '"KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat"' +0138560805b4c8d7b7fbbafad5c59dbfa3878ca70500 + +./octez-codec decode 020-PsParisC.contract from 0138560805b4c8d7b7fbbafad5c59dbfa3878ca70500 +"KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- cycle.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- cycle.out new file mode 100644 index 000000000000..ec89b04c2727 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- cycle.out @@ -0,0 +1,12 @@ + +./octez-codec encode 020-PsParisC.cycle from 2147483647 +7fffffff + +./octez-codec decode 020-PsParisC.cycle from 7fffffff +2147483647 + +./octez-codec encode 020-PsParisC.cycle from 0 +00000000 + +./octez-codec decode 020-PsParisC.cycle from 00000000 +0 diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- fitness.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- fitness.out new file mode 100644 index 000000000000..57f3f1454280 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- fitness.out @@ -0,0 +1,11 @@ + +./octez-codec encode 020-PsParisC.fitness from '{ + "level": 1, + "locked_round": 1, + "predecessor_round": 1, + "round": 2 +}' +0000000101000000010000000100000002 + +./octez-codec decode 020-PsParisC.fitness from 0000000101000000010000000100000002 +{ "level": 1, "locked_round": 1, "predecessor_round": 1, "round": 2 } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.cost.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.cost.out new file mode 100644 index 000000000000..23f49215a241 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.cost.out @@ -0,0 +1,12 @@ + +./octez-codec encode 020-PsParisC.gas.cost from '"8920392083423078"' +a6fd9d9694c3d81f + +./octez-codec decode 020-PsParisC.gas.cost from a6fd9d9694c3d81f +"8920392083423078" + +./octez-codec encode 020-PsParisC.gas.cost from '"0"' +00 + +./octez-codec decode 020-PsParisC.gas.cost from 00 +"0" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.out new file mode 100644 index 000000000000..884af4de46a2 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- gas.out @@ -0,0 +1,18 @@ + +./octez-codec encode 020-PsParisC.gas from '"1238"' +009613 + +./octez-codec decode 020-PsParisC.gas from 009613 +"1238" + +./octez-codec encode 020-PsParisC.gas from '"unaccounted"' +01 + +./octez-codec decode 020-PsParisC.gas from 01 +"unaccounted" + +./octez-codec encode 020-PsParisC.gas from '"0"' +0000 + +./octez-codec decode 020-PsParisC.gas from 0000 +"0" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- level.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- level.out new file mode 100644 index 000000000000..685e61917ea3 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- level.out @@ -0,0 +1,13 @@ + +./octez-codec encode 020-PsParisC.level from '{ + "level": 1331, + "level_position": 2147483647, + "cycle": 300, + "cycle_position": 600, + "expected_commitment": true +}' +000005337fffffff0000012c00000258ff + +./octez-codec decode 020-PsParisC.level from 000005337fffffff0000012c00000258ff +{ "level": 1331, "level_position": 2147483647, "cycle": 300, + "cycle_position": 600, "expected_commitment": true } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- nonce.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- nonce.out new file mode 100644 index 000000000000..1e51d5a7344d --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- nonce.out @@ -0,0 +1,6 @@ + +./octez-codec encode 020-PsParisC.nonce from '"0000000000000000000000000000000000000000000000000000000000000000"' +0000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.nonce from 0000000000000000000000000000000000000000000000000000000000000000 +"0000000000000000000000000000000000000000000000000000000000000000" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.internal.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.internal.out new file mode 100644 index 000000000000..08dc852723b6 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.internal.out @@ -0,0 +1,140 @@ + +./octez-codec encode 020-PsParisC.operation.internal from '{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "delegation" +}' +000002298c03ed7d454a101eb7022bc95f7e5f41ac7800000300 + +./octez-codec decode 020-PsParisC.operation.internal from 000002298c03ed7d454a101eb7022bc95f7e5f41ac7800000300 +{ "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "nonce": 0, + "kind": "delegation" } + +./octez-codec encode 020-PsParisC.operation.internal from '{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "delegation", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" +}' +000002298c03ed7d454a101eb7022bc95f7e5f41ac78000003ff0002298c03ed7d454a101eb7022bc95f7e5f41ac78 + +./octez-codec decode 020-PsParisC.operation.internal from 000002298c03ed7d454a101eb7022bc95f7e5f41ac78000003ff0002298c03ed7d454a101eb7022bc95f7e5f41ac78 +{ "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "nonce": 0, + "kind": "delegation", "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } + +./octez-codec encode 020-PsParisC.operation.internal from '{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "origination", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [ + { + "prim": "parameter", + "args": [ + { + "prim": "string" + } + ] + }, + { + "prim": "storage", + "args": [ + { + "prim": "option", + "args": [ + { + "prim": "string" + } + ] + } + ] + }, + { + "prim": "code", + "args": [ + [ + { + "prim": "CAR" + }, + { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [ + { + "prim": "operation" + } + ] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [ + { + "string": "test" + } + ] + } +}' +000002298c03ed7d454a101eb7022bc95f7e5f41ac78000002af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e0200000009010000000474657374 + +./octez-codec decode 020-PsParisC.operation.internal from 000002298c03ed7d454a101eb7022bc95f7e5f41ac78000002af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e0200000009010000000474657374 +{ "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "nonce": 0, + "kind": "origination", "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": [ { "string": "test" } ] } } + +./octez-codec encode 020-PsParisC.operation.internal from '{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 3, + "kind": "transaction", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" +}' +000002298c03ed7d454a101eb7022bc95f7e5f41ac780003019703000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 + +./octez-codec decode 020-PsParisC.operation.internal from 000002298c03ed7d454a101eb7022bc95f7e5f41ac780003019703000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 +{ "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "nonce": 3, + "kind": "transaction", "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } + +./octez-codec encode 020-PsParisC.operation.internal from '{ + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "nonce": 0, + "kind": "transaction", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [ + { + "prim": "UNIT" + } + ] + } +}' +000002298c03ed7d454a101eb7022bc95f7e5f41ac7800000197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f + +./octez-codec decode 020-PsParisC.operation.internal from 000002298c03ed7d454a101eb7022bc95f7e5f41ac7800000197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f +{ "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "nonce": 0, + "kind": "transaction", "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { "entrypoint": "action", "value": [ { "prim": "UNIT" } ] } } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.out new file mode 100644 index 000000000000..fae9cfc00d01 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.out @@ -0,0 +1,561 @@ + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "attestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c0066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c0066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "ballot", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4010066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4010066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "attestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_baking_evidence", + "bh1": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "bh2": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preattestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_preattestation_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preattestation", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preattestation", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [ + { + "prim": "parameter", + "args": [ + { + "prim": "string" + } + ] + }, + { + "prim": "storage", + "args": [ + { + "prim": "option", + "args": [ + { + "prim": "string" + } + ] + } + ] + }, + { + "prim": "code", + "args": [ + [ + { + "prim": "CAR" + }, + { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [ + { + "prim": "operation" + } + ] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [ + { + "string": "test" + } + ] + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e020000000901000000047465737466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e020000000901000000047465737466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": [ { "string": "test" } ] } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "preattestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": [ + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "period": 719, + "proposals": + [ "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" ] } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "reveal", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a80100000533000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a80100000533000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "seed_nonce_revelation", "level": 1331, + "nonce": + "0000000000000000000000000000000000000000000000000000000000000000" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac780066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac780066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [ + { + "prim": "UNIT" + } + ] + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": + { "entrypoint": "action", "value": [ { "prim": "UNIT" } ] } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.raw.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.raw.out new file mode 100644 index 000000000000..d29dba9c798e --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.raw.out @@ -0,0 +1,11 @@ + +./octez-codec encode 020-PsParisC.operation.raw from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "data": "000000053366804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000053366804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation.raw from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000053366804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "data": + "000000053366804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.unsigned.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.unsigned.out new file mode 100644 index 000000000000..5719452cad2c --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation.unsigned.out @@ -0,0 +1,548 @@ + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac4 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac4 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a815000000000533000000000000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a815000000000533000000000000000000000000000000000000000000000000000000000000000000000000 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "attestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c00 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c00 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "ballot", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40100 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40100 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac78 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac78 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_attestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "attestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8020000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8020000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_attestation_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "attestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "attestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_baking_evidence", + "bh1": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "bh2": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preattestation_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_preattestation_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preattestation", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preattestation", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [ + { + "prim": "parameter", + "args": [ + { + "prim": "string" + } + ] + }, + { + "prim": "storage", + "args": [ + { + "prim": "option", + "args": [ + { + "prim": "string" + } + ] + } + ] + }, + { + "prim": "code", + "args": [ + [ + { + "prim": "CAR" + }, + { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [ + { + "prim": "operation" + } + ] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [ + { + "string": "test" + } + ] + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e0200000009010000000474657374 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e0200000009010000000474657374 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": [ { "string": "test" } ] } } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preattestation", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a814000000000533000000000000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a814000000000533000000000000000000000000000000000000000000000000000000000000000000000000 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "preattestation", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": [ + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "period": 719, + "proposals": + [ "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" ] } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "reveal", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a801000005330000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a801000005330000000000000000000000000000000000000000000000000000000000000000 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "seed_nonce_revelation", "level": 1331, + "nonce": + "0000000000000000000000000000000000000000000000000000000000000000" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ] } + +./octez-codec encode 020-PsParisC.operation.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [ + { + "prim": "UNIT" + } + ] + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f + +./octez-codec decode 020-PsParisC.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": + { "entrypoint": "action", "value": [ { "prim": "UNIT" } ] } } ] } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.out new file mode 100644 index 000000000000..f50683863720 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.out @@ -0,0 +1,593 @@ + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c0066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c0066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "ballot", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4010066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4010066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7866804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_baking_evidence", + "bh1": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "bh2": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_endorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8020000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8020000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_endorsement_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "endorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "endorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preendorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_preendorsement_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preendorsement", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preendorsement", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "endorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [ + { + "prim": "parameter", + "args": [ + { + "prim": "string" + } + ] + }, + { + "prim": "storage", + "args": [ + { + "prim": "option", + "args": [ + { + "prim": "string" + } + ] + } + ] + }, + { + "prim": "code", + "args": [ + [ + { + "prim": "CAR" + }, + { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [ + { + "prim": "operation" + } + ] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [ + { + "string": "test" + } + ] + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e020000000901000000047465737466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e020000000901000000047465737466804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": [ { "string": "test" } ] } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "preendorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": [ + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "period": 719, + "proposals": + [ "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" ] } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "reveal", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a80100000533000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a80100000533000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "seed_nonce_revelation", "level": 1331, + "nonce": + "0000000000000000000000000000000000000000000000000000000000000000" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac780066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac780066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [ + { + "prim": "UNIT" + } + ] + } + } + ], + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": + { "entrypoint": "action", "value": [ { "prim": "UNIT" } ] } } ], + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.unsigned.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.unsigned.out new file mode 100644 index 000000000000..4a1ec24fa53f --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- operation_with_legacy.unsigned.out @@ -0,0 +1,548 @@ + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac4 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a804c55cf02dbeecc978d9c84625dcae72bb77ea4fbd41f98b15efc63fa893d61d7d6eee4a2ce9427ac4 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "activate_account", + "pkh": "tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv", + "secret": "41f98b15efc63fa893d61d7d6eee4a2ce9427ac4" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "ballot", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c00 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8060002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c00 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "ballot", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposal": "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "ballot": "yay" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40100 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40100 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac78 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86e0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401ff0002298c03ed7d454a101eb7022bc95f7e5f41ac78 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "delegation", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_baking_evidence", + "bh1": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + }, + "bh2": { + "level": 1331, + "proto": 1, + "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", + "validation_pass": 4, + "operations_hash": "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ + "01", + "000000000000000a" + ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", + "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0 + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_baking_evidence", + "bh1": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "bh2": + { "level": 1331, "proto": 1, + "predecessor": + "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 4, + "operations_hash": + "LLoZqBDX1E2ADRXbmwYo8VtMNeHG6Ygzmm4Zqv97i91UPBQHy9Vq3", + "fitness": [ "01", "000000000000000a" ], + "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", + "payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", + "liquidity_baking_toggle_vote": "off", + "adaptive_issuance_vote": "on", + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_endorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8020000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8020000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81500000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_endorsement_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "endorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "endorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "double_preendorsement_evidence", + "op1": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + }, + "op2": { + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + }, + "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8070000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c0000008b0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a81400000000053300000000000000000000000000000000000000000000000000000000000000000000000066804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "double_preendorsement_evidence", + "op1": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preendorsement", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, + "op2": + { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "operations": + { "kind": "preendorsement", "slot": 0, "level": 1331, + "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" }, + "signature": + "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "endorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a815000000000533000000000000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a815000000000533000000000000000000000000000000000000000000000000000000000000000000000000 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "endorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": { + "code": [ + { + "prim": "parameter", + "args": [ + { + "prim": "string" + } + ] + }, + { + "prim": "storage", + "args": [ + { + "prim": "option", + "args": [ + { + "prim": "string" + } + ] + } + ] + }, + { + "prim": "code", + "args": [ + [ + { + "prim": "CAR" + }, + { + "prim": "SOME" + }, + { + "prim": "NIL", + "args": [ + { + "prim": "operation" + } + ] + }, + { + "prim": "PAIR" + } + ] + ] + } + ], + "storage": [ + { + "string": "test" + } + ] + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e0200000009010000000474657374 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86d0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401af9105ff0002298c03ed7d454a101eb7022bc95f7e5f41ac7800000020020000001b050003680501056303680502020000000a03160346053d036d03420000000e0200000009010000000474657374 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "origination", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "balance": "84143", + "delegate": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "script": + { "code": + [ { "prim": "parameter", "args": [ { "prim": "string" } ] }, + { "prim": "storage", + "args": + [ { "prim": "option", "args": [ { "prim": "string" } ] } ] }, + { "prim": "code", + "args": + [ [ { "prim": "CAR" }, { "prim": "SOME" }, + { "prim": "NIL", + "args": [ { "prim": "operation" } ] }, + { "prim": "PAIR" } ] ] } ], + "storage": [ { "string": "test" } ] } } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "preendorsement", + "level": 1331, + "block_payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", + "round": 0, + "slot": 0 + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a814000000000533000000000000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a814000000000533000000000000000000000000000000000000000000000000000000000000000000000000 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "preendorsement", "slot": 0, "level": 1331, "round": 0, + "block_payload_hash": + "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "period": 719, + "proposals": [ + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" + ] + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8050002298c03ed7d454a101eb7022bc95f7e5f41ac78000002cf000000407663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c7663cf120f3dc8189d5dc7d4d7a0483bcc53f3f18e700f5a2f5076aa8b9dc55c +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "proposals", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "period": 719, + "proposals": + [ "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp", + "PscqRYywd243M2eZspXZEJGsRmNchp4ZKfKmoyEZTRHeLQvVGjp" ] } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "reveal", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86b0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d401004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "reveal", "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", + "public_key": + "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "seed_nonce_revelation", + "level": 1331, + "nonce": "0000000000000000000000000000000000000000000000000000000000000000" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a801000005330000000000000000000000000000000000000000000000000000000000000000 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a801000005330000000000000000000000000000000000000000000000000000000000000000 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "seed_nonce_revelation", "level": 1331, + "nonce": + "0000000000000000000000000000000000000000000000000000000000000000" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d4019703000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" } ] } + +./octez-codec encode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from '{ + "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": [ + { + "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "fee": "33", + "counter": "732", + "gas_limit": "9451117", + "storage_limit": "57024931117", + "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": { + "entrypoint": "action", + "value": [ + { + "prim": "UNIT" + } + ] + } + } + ] +}' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f + +./octez-codec decode 020-PsParisC.operation_with_legacy_attestation_name.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a86c0002298c03ed7d454a101eb7022bc95f7e5f41ac7821dc05edecc004adcacdb7d40197030138560805b4c8d7b7fbbafad5c59dbfa3878ca70500ffff06616374696f6e000000070200000002034f +{ "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", + "contents": + [ { "kind": "transaction", + "source": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "fee": "33", + "counter": "732", "gas_limit": "9451117", + "storage_limit": "57024931117", "amount": "407", + "destination": "KT1DieU51jzXLerQx5AqMCiLC1SsCeM8yRat", + "parameters": + { "entrypoint": "action", "value": [ { "prim": "UNIT" } ] } } ] } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- period.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- period.out new file mode 100644 index 000000000000..3798bd4a5ed6 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- period.out @@ -0,0 +1,12 @@ + +./octez-codec encode 020-PsParisC.period from '"2789"' +0000000000000ae5 + +./octez-codec decode 020-PsParisC.period from 0000000000000ae5 +"2789" + +./octez-codec encode 020-PsParisC.period from '"0"' +0000000000000000 + +./octez-codec decode 020-PsParisC.period from 0000000000000000 +"0" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- raw_level.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- raw_level.out new file mode 100644 index 000000000000..85b48ecd2405 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- raw_level.out @@ -0,0 +1,12 @@ + +./octez-codec encode 020-PsParisC.raw_level from 2147483647 +7fffffff + +./octez-codec decode 020-PsParisC.raw_level from 7fffffff +2147483647 + +./octez-codec encode 020-PsParisC.raw_level from 0 +00000000 + +./octez-codec decode 020-PsParisC.raw_level from 00000000 +0 diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- seed.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- seed.out new file mode 100644 index 000000000000..4f596296a93e --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- seed.out @@ -0,0 +1,6 @@ + +./octez-codec encode 020-PsParisC.seed from '"0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8"' +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8 + +./octez-codec decode 020-PsParisC.seed from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8 +"0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- tez.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- tez.out new file mode 100644 index 000000000000..10706968fa3a --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- tez.out @@ -0,0 +1,12 @@ + +./octez-codec encode 020-PsParisC.tez from '"7322135"' +97f4be03 + +./octez-codec decode 020-PsParisC.tez from 97f4be03 +"7322135" + +./octez-codec encode 020-PsParisC.tez from '"0"' +00 + +./octez-codec decode 020-PsParisC.tez from 00 +"0" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- timestamp.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- timestamp.out new file mode 100644 index 000000000000..9c20a4591486 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- timestamp.out @@ -0,0 +1,6 @@ + +./octez-codec encode 020-PsParisC.timestamp from '"2020-04-20T16:19:59Z"' +000000005e9dcbaf + +./octez-codec decode 020-PsParisC.timestamp from 000000005e9dcbaf +"2020-04-20T16:19:59Z" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballot.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballot.out new file mode 100644 index 000000000000..d083859609ba --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballot.out @@ -0,0 +1,18 @@ + +./octez-codec encode 020-PsParisC.vote.ballot from '"nay"' +01 + +./octez-codec decode 020-PsParisC.vote.ballot from 01 +"nay" + +./octez-codec encode 020-PsParisC.vote.ballot from '"pass"' +02 + +./octez-codec decode 020-PsParisC.vote.ballot from 02 +"pass" + +./octez-codec encode 020-PsParisC.vote.ballot from '"yay"' +00 + +./octez-codec decode 020-PsParisC.vote.ballot from 00 +"yay" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballots.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballots.out new file mode 100644 index 000000000000..754c630e331b --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.ballots.out @@ -0,0 +1,10 @@ + +./octez-codec encode 020-PsParisC.vote.ballots from '{ + "yay": "2147483647", + "nay": "0", + "pass": "455" +}' +000000007fffffff000000000000000000000000000001c7 + +./octez-codec decode 020-PsParisC.vote.ballots from 000000007fffffff000000000000000000000000000001c7 +{ "yay": "2147483647", "nay": "0", "pass": "455" } diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.listings.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.listings.out new file mode 100644 index 000000000000..d69c6adce257 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- vote.listings.out @@ -0,0 +1,16 @@ + +./octez-codec encode 020-PsParisC.vote.listings from '[ + { + "pkh": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", + "voting_power": "20115" + }, + { + "pkh": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "voting_power": "9000" + } +]' +0000003a0002298c03ed7d454a101eb7022bc95f7e5f41ac780000000000004e9300e7670f32038107a59a2b9cfefae36ea21f5aa63c0000000000002328 + +./octez-codec decode 020-PsParisC.vote.listings from 0000003a0002298c03ed7d454a101eb7022bc95f7e5f41ac780000000000004e9300e7670f32038107a59a2b9cfefae36ea21f5aa63c0000000000002328 +[ { "pkh": "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx", "voting_power": "20115" }, + { "pkh": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", "voting_power": "9000" } ] diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.kind.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.kind.out new file mode 100644 index 000000000000..554245a2aa3a --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.kind.out @@ -0,0 +1,24 @@ + +./octez-codec encode 020-PsParisC.voting_period.kind from '"promotion"' +03 + +./octez-codec decode 020-PsParisC.voting_period.kind from 03 +"promotion" + +./octez-codec encode 020-PsParisC.voting_period.kind from '"proposal"' +00 + +./octez-codec decode 020-PsParisC.voting_period.kind from 00 +"proposal" + +./octez-codec encode 020-PsParisC.voting_period.kind from '"exploration"' +01 + +./octez-codec decode 020-PsParisC.voting_period.kind from 01 +"exploration" + +./octez-codec encode 020-PsParisC.voting_period.kind from '"cooldown"' +02 + +./octez-codec decode 020-PsParisC.voting_period.kind from 02 +"cooldown" diff --git a/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.out b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.out new file mode 100644 index 000000000000..d99215c39af0 --- /dev/null +++ b/tezt/tests/expected/encoding.ml/Parisc- protocol encoding regression test- voting_period.out @@ -0,0 +1,20 @@ + +./octez-codec encode 020-PsParisC.voting_period from '{ + "start_position": 1159026, + "kind": "proposal", + "index": 0 +}' +00000000000011af72 + +./octez-codec decode 020-PsParisC.voting_period from 00000000000011af72 +{ "index": 0, "kind": "proposal", "start_position": 1159026 } + +./octez-codec encode 020-PsParisC.voting_period from '{ + "start_position": 0, + "kind": "proposal", + "index": 0 +}' +000000000000000000 + +./octez-codec decode 020-PsParisC.voting_period from 000000000000000000 +{ "index": 0, "kind": "proposal", "start_position": 0 } diff --git a/tezt/tests/expected/hash_data.ml/Paris- hash data ... of type ... (bad).out b/tezt/tests/expected/hash_data.ml/Parisb- hash data ... of type ... (bad).out similarity index 100% rename from tezt/tests/expected/hash_data.ml/Paris- hash data ... of type ... (bad).out rename to tezt/tests/expected/hash_data.ml/Parisb- hash data ... of type ... (bad).out diff --git a/tezt/tests/expected/hash_data.ml/Paris- hash data ... of type ... (good).out b/tezt/tests/expected/hash_data.ml/Parisb- hash data ... of type ... (good).out similarity index 100% rename from tezt/tests/expected/hash_data.ml/Paris- hash data ... of type ... (good).out rename to tezt/tests/expected/hash_data.ml/Parisb- hash data ... of type ... (good).out diff --git a/tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (bad).out b/tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (bad).out new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (good).out b/tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (good).out new file mode 100644 index 000000000000..314a2e670a6f --- /dev/null +++ b/tezt/tests/expected/hash_data.ml/Parisc- hash data ... of type ... (good).out @@ -0,0 +1,594 @@ + +./octez-client --mode mockup hash data -92233720368547758089223372036854775807 of type int +Raw packed data: 0x0500ffffffffffffffffff8180c09e91c191c79502 +Script-expression-ID-Hash: expruG5Q9N4beaRnBNDX9c1rQ1QUGRyPgQyTpwJedPhTpxXfTkguXn +Raw Script-expression-ID-Hash: 0x6216452f655bf0e4ba4f86c58a7bface77c01dc88e9db83102212e1fe3d50ca7 +Ledger Blake2b hash: 7bteidcLhhSczK6rV7WZQMFW1S7jEApuMPPEUvZDk2B8 +Raw Sha256 hash: 0x19392ac75f657ecb477bf79085a4490f1be98a31c03434b40d38e089cf345e33 +Raw Sha512 hash: 0x94afe9bdf473c06f33fb1c59854e1c15b13d76eeef4b2c4d27605f9be3f3113d13fc0b979870fff2604bf816510522abdee8622535917fc112813fabb5d38a9a +Gas remaining: 1039999.224 units remaining + +./octez-client --mode mockup hash data -9223372036854775808 of type int +Raw packed data: 0x0500c0808080808080808002 +Script-expression-ID-Hash: exprv3Fy2Seq49zs6JYAGd9zGkFFqiACPjyyHf3sCZFFRnxVvYKUPz +Raw Script-expression-ID-Hash: 0xc8adbddf5949c1d4d104c1b7d658baa7a4c5813c1ae7cbee9d099bbb73ccb5a3 +Ledger Blake2b hash: EWNCTfpNyM4iYvGgWPNoCxkFbGYnNzM61zTAUkc2gh4E +Raw Sha256 hash: 0x6ff401ab35f93209f6c1c8c4d7c36adfd58dba53bca644ecd9107edb30e184cd +Raw Sha512 hash: 0x9ae07221db7b28fdd73a89744a7d7b94fbe44a150cf752a864aa554adf9ac849a73cfdf0bc682c2b830b4dcaec5ac4de71a19eb1fbc58ded3d7a793f96cc4afa +Gas remaining: 1039999.424 units remaining + +./octez-client --mode mockup hash data -4611686018427387904 of type int +Raw packed data: 0x0500c0808080808080808001 +Script-expression-ID-Hash: exprtdBSRcCcmApcTq7pu378scXyxCVPbLxfiQ5uCsqNATnXQGaDbQ +Raw Script-expression-ID-Hash: 0x0e4f763b32f9f61a670de9049e17b51051a7eb39110a2fc978d4075fcad01cb1 +Ledger Blake2b hash: xrz5vpBWhFXPadfA7xjRBmhCRahN5UzoQE73iBMnkbi +Raw Sha256 hash: 0x99f3e8cb5de4405979d25b07b08d7e0c040c185f9e1ba22f4165f23f959b5765 +Raw Sha512 hash: 0x21f8c0bdb48495f65e9933b9a66ab86e5f980acd2e1c247c17c1f707474682e8f88fbd0ff6ad7eece958bb80c1963a2cc30ebd81708de4bb79f86878468c651e +Gas remaining: 1039999.424 units remaining + +./octez-client --mode mockup hash data -1 of type int +Raw packed data: 0x050041 +Script-expression-ID-Hash: expru57wdzZCHCeGnKwUzxCJjG1HjveGXp1CCusScXEMq9kbidSvDG +Raw Script-expression-ID-Hash: 0x4935af0cbcc38e08fae2742399a95eaa2a8aa3c4504971b72afbf1e336fd9d8b +Ledger Blake2b hash: 5vnEvsKtB8ojf9DuVntudWnfy6yRLfY4Duwx2j6a36dp +Raw Sha256 hash: 0x5db11f873d99e0d9c25e52c9137676326f8a03f18c6c802fecbcd4a5543c28f7 +Raw Sha512 hash: 0x45256a6d4fe9afc4eda42131ad62e28b5903c43243afdbc69709e8bb9a7cf49a0c117c26d58849f41757beae1052d00d78deb10bd62728a7c04afb32afb637e2 +Gas remaining: 1039999.599 units remaining + +./octez-client --mode mockup hash data 1 of type int +Raw packed data: 0x050001 +Script-expression-ID-Hash: expru2dKqDfZG8hu4wNGkiyunvq2hdSKuVYtcKta7BWP6Q18oNxKjS +Raw Script-expression-ID-Hash: 0x438c52065d4605460b12d1b9446876a1c922b416103a20d44e994a9fd2b8ed07 +Ledger Blake2b hash: 5YgR7rjfSbSbzGEYhhBG9ENRHhdVSUu2TJ6RyNLawjiv +Raw Sha256 hash: 0x57072915640d052f4e2843e1498b10c4f71b62df565525d33c4a66a724e3e20a +Raw Sha512 hash: 0x112e6b61a60ecf001d501f39284ff8a575d818f2f79295b90b24f045d165a490c19cac2add9149dbdd23a8f2cf956dbee0efe17449111e6326e97ab21532f445 +Gas remaining: 1039999.599 units remaining + +./octez-client --mode mockup hash data 2 of type int +Raw packed data: 0x050002 +Script-expression-ID-Hash: expruDuAZnFKqmLoisJqUGqrNzXTvw7PJM2rYk97JErM5FHCerQqgn +Raw Script-expression-ID-Hash: 0x5d2525095b5382da2c9c295a739a189382cfaa2ebfa54e320d15bc6f178d6820 +Ledger Blake2b hash: 7GbmUchPX2Y61XEnLc2xfFHA8bAqQ8Qj8o1xEkU4g3VR +Raw Sha256 hash: 0x0a8efab5eba4157330b3113690508ee944e684a3c6949c00d64fcab2d565e5a6 +Raw Sha512 hash: 0x4747a1aba769d89519dddbee3a1fb9d79555831b9044508efee0bd4f1837bd78dfeb585bf1e150d3c7f8dc79e815c4c3f7e4c7ef477e77bdc84dc4f5fb0598c5 +Gas remaining: 1039999.599 units remaining + +./octez-client --mode mockup hash data 4611686018427387903 of type int +Raw packed data: 0x0500bfffffffffffffff7f +Script-expression-ID-Hash: exprtucdegDH8uqtjprBzMMVaAFJxsctauXP7Qzmfu3KxcyTwnRnfk +Raw Script-expression-ID-Hash: 0x33a06c095748ee4505cba0c1b7ef8d7666ff5cff1ebf865d7b75b4fb8606a130 +Ledger Blake2b hash: 4UXfu1ECmNSrir6LkbB1wkcptuVFk1Supjch6Si4PfkT +Raw Sha256 hash: 0x563ee067653bda5b3609ef10c5fba6f76392642b950dca8ab70e85343caa6c41 +Raw Sha512 hash: 0x40691c0bb573951c3c48c13db7acf03cbb3c5164197555c98ff5a4858acbb2957e2daf0178bedcfd7e5cbd2cf045d693d822cb218b417e10ed517da1f34fe8c5 +Gas remaining: 1039999.424 units remaining + +./octez-client --mode mockup hash data 9223372036854775807 of type int +Raw packed data: 0x0500bfffffffffffffffff01 +Script-expression-ID-Hash: exprupFUK8vtnxuBeiwi8ajvzyqT3eytHd5RueTNQztXn6Q1rFGPKM +Raw Script-expression-ID-Hash: 0xab242636b94a88d317af40fe4928ede501f51249840fa44b2e57c2ff6d7d326b +Ledger Blake2b hash: CX4gqnkyYpudVKQVtwkvq2JbfjzPPZsgQG547UGxcKg6 +Raw Sha256 hash: 0x15d152f6eeb5baf6bf2630719997223fe2c1bedf2730656a755b36f841cc8606 +Raw Sha512 hash: 0x63af709255528779eeb42613bc0385b3564aa4882a7b8a3f9387850a907e7cee3f2a8a22b881f1222400dae352b1363b7ffb4ff7528995f8b8384932be5af625 +Gas remaining: 1039999.424 units remaining + +./octez-client --mode mockup hash data 92233720368547758079223372036854775807 of type int +Raw packed data: 0x0500bfffbfe1eebeeeb8eaffffbf9e91c191c79502 +Script-expression-ID-Hash: expruEdpvhN7bLdgrLpgAGvrzHSu9gs2K7V474qz6BjpAP9uXegr3q +Raw Script-expression-ID-Hash: 0x5ed0b316a2ab47e3698fa3b046ebefc2e775ad37426a0886c4f14d3f7650c462 +Ledger Blake2b hash: 7P7u7hLd2MNuGyXfWD6bzYdXhBxfGn8LPmcMRgzEYath +Raw Sha256 hash: 0xeb749cd1d6d7184d6d0d6f0aae0cf379082bc340f468e2b89a9beb3190f59a91 +Raw Sha512 hash: 0xb8bec79fbca40add468205be6c6ec631f3977fadcf843ef65ca288dd6b8f18ddaa822608163d825ca00e4d348bb3c79abacc0b1555d45ac9c235fd38234dbe31 +Gas remaining: 1039999.224 units remaining + +./octez-client --mode mockup hash data False of type bool +Raw packed data: 0x050303 +Script-expression-ID-Hash: exprvDnoPjyKeR9FSnvwYg5a1v6mDyB6TmnATwWySSP6VmJxrzQb9E +Raw Script-expression-ID-Hash: 0xe0978ddc9329cbd84d25fd15a161a7d2e7e555da91e2a335ece8c8bc11ade245 +Ledger Blake2b hash: G7iMrYNckCFRujDLFgtj3cDMCnfeSQ2cmhnDtkh9REc4 +Raw Sha256 hash: 0x35ef99f7718e7d1f065bae635780f41c0cd201e9ffb3390ba6ef428c2815fa66 +Raw Sha512 hash: 0x2c9ca967bf47f6cc76861693379b7397f65e6a1b6e633df28cf02be0b0d18319ae783b4c199fd61115e000a15a5ba8a292a3b1468c2cfe2b3e3a9fa08d419698 +Gas remaining: 1039999.624 units remaining + +./octez-client --mode mockup hash data True of type bool +Raw packed data: 0x05030a +Script-expression-ID-Hash: exprvMjTcyX8e8HskSUV3ipMhPzMLKTn92vsWZkiJTTYj7U9J8sAyP +Raw Script-expression-ID-Hash: 0xf2a04e59c51d374e01df59a69495e400c6548415d628cf212a108f46697e4f53 +Ledger Blake2b hash: HL7SRbwe6n7r92rqsPQqN1hu1kd8uJhECY6Z5PJTwSRp +Raw Sha256 hash: 0xfb2a0db46fe82f0aeb2824b2f0840cc1437bf7bdf836d5164351e0cfe5b0f330 +Raw Sha512 hash: 0xcd0d052ce182cb449207cbb0781be4c9eb3f48c631fe210a03996f6a287e528d8a94817758102a647820007d18cb8e94f0f8bb829ca571287d390b47ab6ae389 +Gas remaining: 1039999.624 units remaining + +./octez-client --mode mockup hash data '{}' of type 'list(bool)' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039999.564 units remaining + +./octez-client --mode mockup hash data '{}' of type 'list(int)' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039999.564 units remaining + +./octez-client --mode mockup hash data '{}' of type 'list(unit)' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039999.564 units remaining + +./octez-client --mode mockup hash data '{True; False}' of type 'list(bool)' +Raw packed data: 0x050200000004030a0303 +Script-expression-ID-Hash: exprvAgoBrfufCNYoqAjdTcW2zD965bvLPD76xT7bVBNSn9SU6UgVd +Raw Script-expression-ID-Hash: 0xd98b8c66ef2fb29d4d2ad21a667a753e0dd7044571e709330d4b92a5dc3d622c +Ledger Blake2b hash: FeCtVSz9QEDR78yiR1aQwQaFMaoGES8VjX2HQCjZAfz3 +Raw Sha256 hash: 0xc939a10e1f26f0fddb7d00e26595b383bcd8d5fad6cc5427e8b0385a323d2a78 +Raw Sha512 hash: 0x98e4f14ef8e5ad0fa7520f07459fec0d5eb2f5759f0beebd5fa63beb950f6afa0d51c2573402d09684308677bae667ae8323fc2a32b5358be3155f56b73e263f +Gas remaining: 1039998.932 units remaining + +./octez-client --mode mockup hash data '{True; True}' of type 'list(bool)' +Raw packed data: 0x050200000004030a030a +Script-expression-ID-Hash: expruRvaTS59Lau3wHMFuiADbSkSTPf61W3UCW25ej1kY8TnioYiG4 +Raw Script-expression-ID-Hash: 0x7872a58d23f32f0e045de43738dc925bcab9c84c4ea5e7d25774832cdf66f2a8 +Ledger Blake2b hash: 97BKSDXQr12DzEiMg2HiFoA2Aq9QnzDpmVatc2nrr5xB +Raw Sha256 hash: 0x709190aaed8bda9abbca553974949a4a81dcdb927ebbc89aa7aef53bee218ff4 +Raw Sha512 hash: 0x7e67d91c4bb7a7c56e66ca752878e07ec45d61c6ff413b210384be67e946ca63cb1f852137d29494a7e232e2439092270e3b7abd834bcf2b18d192729794dbf7 +Gas remaining: 1039998.932 units remaining + +./octez-client --mode mockup hash data '{-1; 0}' of type 'list(int)' +Raw packed data: 0x05020000000400410000 +Script-expression-ID-Hash: expruNySy7xWaeniq7qraAeEtFzBvJvFA4Jt3op3Dt2m6PddU2Hqr7 +Raw Script-expression-ID-Hash: 0x71bf94bc4515cc0afc439e3714423dfa3ef180fa8ff2c671f245dba990eb41ce +Ledger Blake2b hash: 8f2WHzqFH7YhWa1rrFtHehTMxTUFJg49iwSNokpdZLSR +Raw Sha256 hash: 0x28e46755a35977ff466f50cb4224bf71541ca519ca1a3f900e1d2cd7da4537b3 +Raw Sha512 hash: 0x0f79f40cb2c56e753120d405b1bb5bb843ac34fc2b362b4f8f684913318ecbf3d99e4be5fc6f8ed16ee11fef6f4c412ecfc8c6efbab1684585b0ceb8a6bad3b1 +Gas remaining: 1039998.907 units remaining + +./octez-client --mode mockup hash data '"[CONTRACT_HASH]"' of type address +Raw packed data: 0x050a0000001601d1a37c088a1221b636bb5fccb35e05181038ba7c00 +Script-expression-ID-Hash: expruKMyQaSREJvvRY1engxJjG9eExbrS22JaZUiBmMnhVew5nyu98 +Raw Script-expression-ID-Hash: 0x698c356a1846c517db5b16f7a8ff507c3eb4aaa46c316a6936e955123358b306 +Ledger Blake2b hash: 871oxBK1GsehvbFAwL4bBF4w22oBKfxom746gk7wnr8d +Raw Sha256 hash: 0xa5f6f6520cfa43309e72f6745efcbebc1edd1486ab219421e349c8000ddfe485 +Raw Sha512 hash: 0x4618bdd8850b8707c52bbf7f64526f8d83e59ccb3f2f1067ca33b5c470c709be21dc9242db15d5428af7b13dfb77353ab39d9367e2a6a12986e95aaf2d4285a7 +Gas remaining: 1039995.724 units remaining + +./octez-client --mode mockup hash data '"[CONTRACT_HASH]%entrypoint"' of type address +Raw packed data: 0x050a00000020011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600656e747279706f696e74 +Script-expression-ID-Hash: exprttX9EL2UJb6Jw6tALybjjfRB3YUC4XsXdYjoGs7SnwZwwiEDHB +Raw Script-expression-ID-Hash: 0x31241f23ec93014cd7b7cfe1e0a21517bfd0f08b38e348d78f45d37a40da530c +Ledger Blake2b hash: 4JpvZAMQiWdgASBEyfLJB45oCrsFocB5ApSNa99DbRPZ +Raw Sha256 hash: 0xf1c661a1663f788977e3508c6fe3c85346a34101d76b1d47783839ed2d756303 +Raw Sha512 hash: 0x781bd064edc01ff80b436682932dd2f0550a6dbf26be32ac434c6386235f4b4c5bb4610b9fad23374d606dcf853a7e16fcce4e3c20fd796e116adb587cdddcbd +Gas remaining: 1039995.624 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY_HASH]"' of type address +Raw packed data: 0x050a00000016000002298c03ed7d454a101eb7022bc95f7e5f41ac78 +Script-expression-ID-Hash: expruH3qgknRBJVLVkwdzf6wfBxd7Y1uqNxr7zuMFxTC12e5PacLfv +Raw Script-expression-ID-Hash: 0x644beb3894b35023de5b76a4c054a32eb7a818b2a83a1b0eb3974184faad1cbe +Ledger Blake2b hash: 7kWuwaa65KxeAcBTC9U9TvSn4d7eo4hzmTReXrFU6QA1 +Raw Sha256 hash: 0x690cf3688186dafd5f78765b514f62ebf98804ed4732d3e9504d1e5d10f62c64 +Raw Sha512 hash: 0x9fe6e4a006013a541dde89aeef0db58a39c1b6d06f12554c8d01dc67dff183602d4e5d4a04ac37088d8e7e7836d08f044b279bc70a752b3ad3f1ed0131a9ea03 +Gas remaining: 1039995.724 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY_HASH]"' of type address +Raw packed data: 0x050a000000160001e5c6d1f726796e98b2bad2a819a36f742b2fe25b +Script-expression-ID-Hash: exprte1BpSKiw9DnLocxVhaUQYqPGZiCbHrENpe2VsvfjvNZ3LTiGf +Raw Script-expression-ID-Hash: 0x102dff270630ac032e24ae0a62b478930f56f4f5a27c9c3c799a8496d749b8a6 +Ledger Blake2b hash: 26ACmTEYpcjnxbUcXQZxYQgWbig1zpHXpmjKecLqMJEH +Raw Sha256 hash: 0xc7016dde1b3b0a15dbfc476de05480386d8781f996769b0113bcf8d3a0f73502 +Raw Sha512 hash: 0x8446a69748c9e209bbd9e2d7ec652b3edd1516905b2ef11008993c27d239a237b3372c26854b8a1d393aa504478de76560a9fdd96fef24faff8483851814c6c7 +Gas remaining: 1039995.724 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY_HASH]"' of type address +Raw packed data: 0x050a0000001600026c9b3ad59e0f8bdc2bd2011675825f9f547131da +Script-expression-ID-Hash: expruXqtng8pcQAshhkrVpENv9xXSirB19McDD4geN3aFFSbjJQMRy +Raw Script-expression-ID-Hash: 0x85e36142a913e3c8d6fb5a77aaad753b01ebe40096bf46090737b8e80effbee3 +Ledger Blake2b hash: A1eKYfrX11WNdtxr3QeEzEpY95epaJtJhmeTQEhw3BTg +Raw Sha256 hash: 0x1520063584bffabc0cc4d64d1d9f35c205ee403789653fef4465fad7da23a484 +Raw Sha512 hash: 0xe8fa1be3ab9fc177a731fdea29e3242831ccea70db15fa5f0dd8f592794261c9e49b51311e0b5387a81472c77edd87cba3afa6207e36ef0bce7f30b0c03bacb0 +Gas remaining: 1039995.724 units remaining + +./octez-client --mode mockup hash data 0 of type bls12_381_fr +Raw packed data: 0x050a000000200000000000000000000000000000000000000000000000000000000000000000 +Script-expression-ID-Hash: exprvGRJUuBnkCc3vi2nFiCKonniDQhcJxTGRuJY68uJubvS1bxnmA +Raw Script-expression-ID-Hash: 0xe68feee8b6ba14292b006b585748c4bd4757955f04320efd37fc0c719bdd7258 +Ledger Blake2b hash: GX24pFg5TqeFyCjH3dpXHP3tWZs8ZMm4MVo61DQnXRzo +Raw Sha256 hash: 0xc928f798bdcab5fc59c9c06f348c2b1dd1d846ef8d2694ff3359a7fa98e5aaf1 +Raw Sha512 hash: 0x56d50c63bacfbac2102091e99071b824150d2c61cbfba9b65a9bad467f1e364a3e1286b0c5de1e7084c7dd3d27a29c19ecbac42d4f5d7797c003b75063f688b4 +Gas remaining: 1039999.104 units remaining + +./octez-client --mode mockup hash data 1 of type bls12_381_fr +Raw packed data: 0x050a000000200100000000000000000000000000000000000000000000000000000000000000 +Script-expression-ID-Hash: exprtgCbDCSxBsG1xnR5B2MmdvwomjRwGZdM2MxfW5NdcB3uXiUUgD +Raw Script-expression-ID-Hash: 0x152ad70bf1a27b6885d3085953411591cbeccd289c0c9fae3257cec340745254 +Ledger Blake2b hash: 2RdT5REqvvzsKNsc2wkGeVcve9j8srXqAqbz6ZPECHi3 +Raw Sha256 hash: 0x251c21e3c764b0993d4e49a7939ebc0192c9af7f6fbb5073f1035ea17a2cbe22 +Raw Sha512 hash: 0x31a063e0701b89ff1a19364d44c39c7ba28fbeb20b95e5a12be432fcc419666fcf030ed6349e3bca6f7446989b5cb9fb3b4425c4eff01ca1993efca695db199b +Gas remaining: 1039999.104 units remaining + +./octez-client --mode mockup hash data 0x01 of type bls12_381_fr +Raw packed data: 0x050a000000200100000000000000000000000000000000000000000000000000000000000000 +Script-expression-ID-Hash: exprtgCbDCSxBsG1xnR5B2MmdvwomjRwGZdM2MxfW5NdcB3uXiUUgD +Raw Script-expression-ID-Hash: 0x152ad70bf1a27b6885d3085953411591cbeccd289c0c9fae3257cec340745254 +Ledger Blake2b hash: 2RdT5REqvvzsKNsc2wkGeVcve9j8srXqAqbz6ZPECHi3 +Raw Sha256 hash: 0x251c21e3c764b0993d4e49a7939ebc0192c9af7f6fbb5073f1035ea17a2cbe22 +Raw Sha512 hash: 0x31a063e0701b89ff1a19364d44c39c7ba28fbeb20b95e5a12be432fcc419666fcf030ed6349e3bca6f7446989b5cb9fb3b4425c4eff01ca1993efca695db199b +Gas remaining: 1039999.104 units remaining + +./octez-client --mode mockup hash data 0x0001 of type bls12_381_fr +Raw packed data: 0x050a000000200001000000000000000000000000000000000000000000000000000000000000 +Script-expression-ID-Hash: exprtitZpQKmhwwbedezDJBMs2aC9a9xwK1QgAEyZXsArw4d2FQ5Kt +Raw Script-expression-ID-Hash: 0x1b460a4d53d8b7029da22adfcaa257555be45259e3480690cafa1e997212afcf +Ledger Blake2b hash: 2qTxCogJudjrxMBHHvtNsurx1dc1P9Gx1JPUbBaJXDre +Raw Sha256 hash: 0xe7038c6478963c7e52c61c9590b774280cfacf0547adc4943a26a608bdb0f277 +Raw Sha512 hash: 0x70e7340161a29e3dc08258b154fc797e2ea407ed35dcaf7782e0ad693906c75d15fd68887f2b03375f5c869c9912c390d020b47aee1ca6d20c5ac714c45b678e +Gas remaining: 1039999.104 units remaining + +./octez-client --mode mockup hash data 0x0572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28 of type bls12_381_g1 +Raw packed data: 0x050a000000600572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28 +Script-expression-ID-Hash: exprupSAayZNCY4pMsSxx2Cbqr8LUcZ5YUnRG38hXjqRhkCAkVvt9q +Raw Script-expression-ID-Hash: 0xab8f542bd84f792908f266964e5329c1532fd6e932de8c34256c3dd5d972fd91 +Ledger Blake2b hash: CYhUfj7xreN4aQ1vV8YWApwu8o1Yuhuv9JrHKdFivGuN +Raw Sha256 hash: 0xeb0effa0878f7c1dfba8a579b282f45ae24715eebc01929bad29dcd9ab44d4da +Raw Sha512 hash: 0x918f9b3b2b615817b4108beca643225a11796825fb00a9126c950f59afbf95364b11ac468150e6fd458b01d1ad3d77ccb0c08a2849e9262e66058014c41cd487 +Gas remaining: 1039940.864 units remaining + +./octez-client --mode mockup hash data 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899 of type bls12_381_g2 +Raw packed data: 0x050a000000c00a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899 +Script-expression-ID-Hash: expruyowq2jYmYPBWkdc5ZSgqP4daGevfjJePrhDTUtP7YQL4Dzi5x +Raw Script-expression-ID-Hash: 0xc0d91f9ad81185f09853efcfc5951eca5c19f9b983808d824637f7bdc03ff595 +Ledger Blake2b hash: DyoJaUpE63MSnYEmW1pBQCK4DjLCURe2My2snWkmyC9S +Raw Sha256 hash: 0xa160577bd9510066d5aa8043d4ce365f03a4f5057516d951c380a521c04fddd8 +Raw Sha512 hash: 0xb0ce4a3348adff71470fc470d700b28fd991a91d4013cc6d89bd34a2f1c05f9d0be5cfe64f6b5d79fdbc27eb3e84be520e4e2d864d6b6649722b22061bbfbd7b +Gas remaining: 1039924.804 units remaining + +./octez-client --mode mockup hash data 0x of type bytes +Raw packed data: 0x050a00000000 +Script-expression-ID-Hash: expru3w5vUB5kLiEvvbFA81Su29kZM9bvCuVVPDNqVQq9RJ5PZ8oRw +Raw Script-expression-ID-Hash: 0x468397e139c257d8cd242c3e9a9a821f987eaab1e2e5098f11095258f1f11eec +Ledger Blake2b hash: 5kFvPvb5eUSrt99ekYQYag1Yfz5AsvsUTzVQFHeNPoW3 +Raw Sha256 hash: 0x59b7ebd426a428d05b6f1d634e56708f7711bd6d0495578281115368c1635e2d +Raw Sha512 hash: 0xb3dd201d5209fd911e193f3490154db2335205f472f0a7730e28182c5a3f07fa997f266226b12efb1bb39e8bc39d7a54d9c69fb575664bfb0be3bdd0550f7d65 +Gas remaining: 1039999.624 units remaining + +./octez-client --mode mockup hash data 0xABCDEF42 of type bytes +Raw packed data: 0x050a00000004abcdef42 +Script-expression-ID-Hash: exprtbzFhHQHhmEMHRqKi6k1fzAQYiVtuCXauZvM1VrN1p8iJLhJeG +Raw Script-expression-ID-Hash: 0x0b9a15faff1a1effa06a876cb86e81c9df2ca55fa8adfc4759449c602720a8c9 +Ledger Blake2b hash: nHm2FU2b9wwdwJVPrUS4tYmBbrsTrhsqY1U4moGsFNG +Raw Sha256 hash: 0x616628cdbcd057574ae41c224271249cd8b1cca683b206d58c088922cb9f9222 +Raw Sha512 hash: 0xc93e6e937d63f506af719edccc50d15d0faf7b213e5f572dd3ac73271815816ebdf738fc6345464af7a2ce7fbace473a03ae38157dea3fb4cc34a6c3b17b7dbc +Gas remaining: 1039999.584 units remaining + +./octez-client --mode mockup hash data 0x7a06a770 of type chain_id +Raw packed data: 0x050a000000047a06a770 +Script-expression-ID-Hash: expruWMYwqN4LDi29J8v47jRfpLkqjEkUaYtn6N9RZL8PB6z7Kca2w +Raw Script-expression-ID-Hash: 0x82820dedcd30b1b2c3253042b252e0b385dd365eaffdac09fbadf19cea1fab4a +Ledger Blake2b hash: 9nT2FHdDkNKBJZie1VRm6WookGzwzZ57FYetGbjvgam7 +Raw Sha256 hash: 0x092220899acefcdc4870e3c2d6ce436cf3e7a27855ebca4d3b24da62bc294a5c +Raw Sha512 hash: 0x99d8d47bed4a102b519062df6f04a65ce5ab7f98fadd3fdf7cdc6c21c652d9a59e8116781683c08b2094bb4fd99f516b690978d0a1f105aa05443a3e7e087697 +Gas remaining: 1039999.484 units remaining + +./octez-client --mode mockup hash data '"NetXynUjJNZm7wi"' of type chain_id +Raw packed data: 0x050a00000004f3d48554 +Script-expression-ID-Hash: exprtXgy1oXtj7HHY7Vw9rw3nKoPmrWaGE9iYF6ToeYfvcwmKTFECY +Raw Script-expression-ID-Hash: 0x01d7b61758f39c12865684f612da8f479d3755efaa0af26636254068a31c5083 +Ledger Blake2b hash: 8CBfWC4xY9SgFvQidL2r53pwquTtGhW8UJGcgu5wcYa +Raw Sha256 hash: 0xf6a25e29f615b4f5edb309db8229c4e607828111795f6ac68a30684bd04bcda5 +Raw Sha512 hash: 0x09ef7ad4129366f7c7e3beae66514b91728428b1b6b62454876fd7b07621bffa068de15dbc4cf3b550682481663df2a64435f65ed231787feeec183221dd4c6b +Gas remaining: 1039997.934 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY]"' of type key +Raw packed data: 0x050a00000021004798d2cc98473d7e250c898885718afd2e4efbcb1a1595ab9730761ed830de0f +Script-expression-ID-Hash: exprtbUKNrgLiggTQePME77Tgz9QcD1HK2pEVWHFLnR1qaah41D2XF +Raw Script-expression-ID-Hash: 0x0a6e0f781438d15aea8aeb41e8f00ea25bacc3d1efedfc62ca2eed7fcf299e3a +Ledger Blake2b hash: hiR4yro9kA38FKWeB8Ps8hzNyeqSoskUNGePRJQi4Uy +Raw Sha256 hash: 0x30467dc415ef58a775a6aa618f515d856287ad20b56477a16c0cfdf0f2a2ed3c +Raw Sha512 hash: 0x1b3f5993512659e0164d186381de64bd6a4c678cefd7ca756ec087769208fc62b4563df31cd4680707e3c43a5a8c7a4579ad5c34ae471a5731ebcbe0db2255ec +Gas remaining: 1039919.839 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY]"' of type key +Raw packed data: 0x050a000000210057b0e07666fe26167f92bffe667dc2ba2214a404f4fe5d1bb8ce01baef5663a5 +Script-expression-ID-Hash: expruJXx976B1KtYQeE96FS74k4VRXRKBAWx5e9TMWEBGPwv8VG5tt +Raw Script-expression-ID-Hash: 0x67aaee572e9d4e0673e66273b43e2300393ee44eb95984304b1407abb5809c24 +Ledger Blake2b hash: 7ygAaVU28qwNcCvg5stUKDPUikjnoMtDJM6FbNnrEmeT +Raw Sha256 hash: 0x13830142ebb330c5f0177637a05894338307e1179b67c45d90eb2e98151175a9 +Raw Sha512 hash: 0x075b346f72fb69759345eff13f52ad51b9c5c138fc6155742c309910412e2efc9a33615a8d4a3e6724c15de7960807cd7e83185d24ab5c096f766916ac035982 +Gas remaining: 1039919.839 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY_HASH]"' of type key_hash +Raw packed data: 0x050a000000150002298c03ed7d454a101eb7022bc95f7e5f41ac78 +Script-expression-ID-Hash: expru6fotvwsd3SnSHp5qhcUTHAmd1hqQA24srgXcGRRaCA2gPLYkf +Raw Script-expression-ID-Hash: 0x4cba54c206c1ccfd72a4a5492b21ae41f1faa6a7a7cce3f1b270218dc79814d3 +Ledger Blake2b hash: 6AWn5TRUkgYJe4fjjZrovKq81K9bNDNNgcS7xiTszkbC +Raw Sha256 hash: 0x4156dbe479999c7df14d90ae46e304304534cc38795d73ecc76d60c78724f2a1 +Raw Sha512 hash: 0xffb476c7d1ae269c82ea4d09a1513a8d915a8b50acb759c351228edc5e623e6f7390f2bd856625476ba14bb17b4dac07572fc40341e9eedf44e372a40550d798 +Gas remaining: 1039995.734 units remaining + +./octez-client --mode mockup hash data '"[PUBLIC_KEY_HASH]"' of type key_hash +Raw packed data: 0x050a000000150080dfbed18097a4cb62dea643ebc5346600b5204d +Script-expression-ID-Hash: expruEg1o4eXzeCwhgod4hTPbJjdpULmL2cbYphGFC9trLLhNaK3kw +Raw Script-expression-ID-Hash: 0x5ee69f25f750a193690ec32802a7a33b9572c7856791471d21fc4e73199dbaf3 +Ledger Blake2b hash: 7PTHd1XgawoAQDjiktNjDyPC5tsse21LnNFufiRifYbc +Raw Sha256 hash: 0x6f54374213823a79f912fb52cb57793466b4a39267dfbdcfdc918eeef296499f +Raw Sha512 hash: 0x2cb036951cd1725c7863f5c04f6f81a879bd0a533b1422a60a2a38d0c8243b10a0a879766e2a04c3cd47c532e417089839c3cf621621060f00bc5c79bda058bb +Gas remaining: 1039995.734 units remaining + +./octez-client --mode mockup hash data '{ }' of type 'lambda unit unit' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039998.846 units remaining + +./octez-client --mode mockup hash data '{ PUSH nat 1; ADD }' of type 'lambda nat nat' +Raw packed data: 0x0502000000080743036200010312 +Script-expression-ID-Hash: expru2DqBT8sxeHNp8FZnU3yEsE3eBRttz553dx3ct4fLZKvag6KXz +Raw Script-expression-ID-Hash: 0x42a0dcc26c782dcc094ba725e4bcc4f8710c72203a895b5e888990c12d03d7df +Ledger Blake2b hash: 5V6BBTaoBmSdwu8pv5xNMNBwm1mQGdPJ8e8N3s22Gcwp +Raw Sha256 hash: 0x113616e40fd9fcf4cb73a9cf9c57fc0ab1853fa4432b9ca975b472d0173bc007 +Raw Sha512 hash: 0x2256250f59e3c1c708eae9aa4d6f7d2dafdf82cb12b872db8320048c0dab3e225e96e846e284382fcfc832b83f0bf3ee3945fc6936357b2c29d96f29ba90315a +Gas remaining: 1039995.858 units remaining + +./octez-client --mode mockup hash data '{}' of type 'list unit' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039999.564 units remaining + +./octez-client --mode mockup hash data '{ 0 ; 10 }' of type 'list nat' +Raw packed data: 0x0502000000040000000a +Script-expression-ID-Hash: expru4vWphhWxDfcnCeXUdGZAhDpNTNt7qSvcoEAF58Se8dVgC2fBR +Raw Script-expression-ID-Hash: 0x48c32738e9d3772486ca8e0d150d6b94cebcd2421e3e8112434192c3c1df3a86 +Ledger Blake2b hash: 5u2x2XQZVxYHKm1LpjamMs894nT2CnvMKTQmeZsrtPH7 +Raw Sha256 hash: 0xaf9e7cce96fb6243ab05cd630f260862264dfe7eccda6fa24050a7cb9043134d +Raw Sha512 hash: 0xc699a04538d2cc260b183e65a02b1ea9fdeeca4c3bc253ae8e70d9824b7e79ebae34f6da3dd5eb3ceb29e9d18dc5e6f36d630b13be50adf566e9badb810f3349 +Gas remaining: 1039998.907 units remaining + +./octez-client --mode mockup hash data '{ Some 10 ; None }' of type 'list (option int)' +Raw packed data: 0x0502000000060509000a0306 +Script-expression-ID-Hash: exprv7yYyxehrZrCaxT9CLhMtAmQCUjjv9PDBZMkqASKLHUVGQUQHk +Raw Script-expression-ID-Hash: 0xd363a18306b7fc740debf0d1a981b5c4e5a3b7914eb04b90d6d406bce9f74d41 +Ledger Blake2b hash: FEB92G5KaAbrFnAp7UjD1AR9daiKQinjcvrAi3sRYG3S +Raw Sha256 hash: 0xa24baf1b39078a1811069da825039c4e6e8ab2de34d58f29baab4ffa9323fdfd +Raw Sha512 hash: 0xb92f1245587939c4ade1554874192d1bbd83f9d34a044e778fca611a6eac5f1a91a259b5fb0682495c1735a0f50e7da5fbdc4e4029e66ed64ecdc7a832a36e7c +Gas remaining: 1039998.531 units remaining + +./octez-client --mode mockup hash data '{}' of type 'map nat unit' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039999.504 units remaining + +./octez-client --mode mockup hash data '{ Elt 0 0xCB ; Elt 1 0xAB }' of type 'map nat bytes' +Raw packed data: 0x050200000014070400000a00000001cb070400010a00000001ab +Script-expression-ID-Hash: exprupowg2SRTtvx8kU3J6iV3Nta1rZ54KFMMHvX9ADcB9kg8vDR8u +Raw Script-expression-ID-Hash: 0xac6995309e75f33132a6819b36c2ae787684be3c23e7cf2a44533229b0aec974 +Ledger Blake2b hash: Cc2W7aPZgPoiuVfuxR8j6gjxgpuZDBJGjSaRQemzTnFM +Raw Sha256 hash: 0x732bb539d52c41e6cc09d6116b1b3d25257b27dfd7adc7a09e03d345c09e0594 +Raw Sha512 hash: 0x0d565633ca0b3c3751aee0fe54d9be744bea79b1a714d97227397dfe79b5058d6385bc86dcdabbb280c5fc2fb56fc073550ac63d947df2787a5927a1342c343b +Gas remaining: 1039997.748 units remaining + +./octez-client --mode mockup hash data 0 of type mutez +Raw packed data: 0x050000 +Script-expression-ID-Hash: exprtZBwZUeYYYfUs9B9Rg2ywHezVHnCCnmF9WsDQVrs582dSK63dC +Raw Script-expression-ID-Hash: 0x053f610929e2b6ea458c54dfd8b29716d379c13f5c8fd82d5c793a9e31271743 +Ledger Blake2b hash: MV6HviXsJnEwxPKHLSUxEvxZVZr14cYYiQth4DFa2NN +Raw Sha256 hash: 0x69c492e24afa52c556de5ea70e1b5d7da3f0bc7a5a7fd1d413444c1a42a7e9b3 +Raw Sha512 hash: 0x6fb0c536a65271998988dffee83efeb370514fcfecd339ebda1f97bde876ea5ecde4a2e8e93b22071849f5625639936ebc55b71c3b4118254f5bff444e515a85 +Gas remaining: 1039999.624 units remaining + +./octez-client --mode mockup hash data 1 of type mutez +Raw packed data: 0x050001 +Script-expression-ID-Hash: expru2dKqDfZG8hu4wNGkiyunvq2hdSKuVYtcKta7BWP6Q18oNxKjS +Raw Script-expression-ID-Hash: 0x438c52065d4605460b12d1b9446876a1c922b416103a20d44e994a9fd2b8ed07 +Ledger Blake2b hash: 5YgR7rjfSbSbzGEYhhBG9ENRHhdVSUu2TJ6RyNLawjiv +Raw Sha256 hash: 0x57072915640d052f4e2843e1498b10c4f71b62df565525d33c4a66a724e3e20a +Raw Sha512 hash: 0x112e6b61a60ecf001d501f39284ff8a575d818f2f79295b90b24f045d165a490c19cac2add9149dbdd23a8f2cf956dbee0efe17449111e6326e97ab21532f445 +Gas remaining: 1039999.599 units remaining + +./octez-client --mode mockup hash data 99999 of type mutez +Raw packed data: 0x05009f9a0c +Script-expression-ID-Hash: expruQUsZtokRsnKdzPwveAiq1QX2TgnMeRdhQ3rqBJw6LbfK7nJEa +Raw Script-expression-ID-Hash: 0x752bc02931fa202b4f7c174c0cea1254e6a007bc42f53d00d7f51556392f84f0 +Ledger Blake2b hash: 8tPPr8hLWFsY27xsdiM85nrPUoCXxEPR3PTWyma5JTyH +Raw Sha256 hash: 0xd794d67b0648f7a498c96eb5b8b8ab14d15c45dd13ae8168b4a3741e7b4cc701 +Raw Sha512 hash: 0xed76e4309dcbd480e19bb3e942adaada5ead9eeec944c0f90798c978cccee14b80d2a1b8f0f2346ca54b56d1662b02c6b0b58a2caa1a7187d5281e70ccd43ce6 +Gas remaining: 1039999.549 units remaining + +./octez-client --mode mockup hash data 0 of type nat +Raw packed data: 0x050000 +Script-expression-ID-Hash: exprtZBwZUeYYYfUs9B9Rg2ywHezVHnCCnmF9WsDQVrs582dSK63dC +Raw Script-expression-ID-Hash: 0x053f610929e2b6ea458c54dfd8b29716d379c13f5c8fd82d5c793a9e31271743 +Ledger Blake2b hash: MV6HviXsJnEwxPKHLSUxEvxZVZr14cYYiQth4DFa2NN +Raw Sha256 hash: 0x69c492e24afa52c556de5ea70e1b5d7da3f0bc7a5a7fd1d413444c1a42a7e9b3 +Raw Sha512 hash: 0x6fb0c536a65271998988dffee83efeb370514fcfecd339ebda1f97bde876ea5ecde4a2e8e93b22071849f5625639936ebc55b71c3b4118254f5bff444e515a85 +Gas remaining: 1039999.624 units remaining + +./octez-client --mode mockup hash data 1 of type nat +Raw packed data: 0x050001 +Script-expression-ID-Hash: expru2dKqDfZG8hu4wNGkiyunvq2hdSKuVYtcKta7BWP6Q18oNxKjS +Raw Script-expression-ID-Hash: 0x438c52065d4605460b12d1b9446876a1c922b416103a20d44e994a9fd2b8ed07 +Ledger Blake2b hash: 5YgR7rjfSbSbzGEYhhBG9ENRHhdVSUu2TJ6RyNLawjiv +Raw Sha256 hash: 0x57072915640d052f4e2843e1498b10c4f71b62df565525d33c4a66a724e3e20a +Raw Sha512 hash: 0x112e6b61a60ecf001d501f39284ff8a575d818f2f79295b90b24f045d165a490c19cac2add9149dbdd23a8f2cf956dbee0efe17449111e6326e97ab21532f445 +Gas remaining: 1039999.599 units remaining + +./octez-client --mode mockup hash data 99999 of type nat +Raw packed data: 0x05009f9a0c +Script-expression-ID-Hash: expruQUsZtokRsnKdzPwveAiq1QX2TgnMeRdhQ3rqBJw6LbfK7nJEa +Raw Script-expression-ID-Hash: 0x752bc02931fa202b4f7c174c0cea1254e6a007bc42f53d00d7f51556392f84f0 +Ledger Blake2b hash: 8tPPr8hLWFsY27xsdiM85nrPUoCXxEPR3PTWyma5JTyH +Raw Sha256 hash: 0xd794d67b0648f7a498c96eb5b8b8ab14d15c45dd13ae8168b4a3741e7b4cc701 +Raw Sha512 hash: 0xed76e4309dcbd480e19bb3e942adaada5ead9eeec944c0f90798c978cccee14b80d2a1b8f0f2346ca54b56d1662b02c6b0b58a2caa1a7187d5281e70ccd43ce6 +Gas remaining: 1039999.549 units remaining + +./octez-client --mode mockup hash data None of type 'option unit' +Raw packed data: 0x050306 +Script-expression-ID-Hash: exprtn5DaoF31YMuSLAJFjARQmKwsdUUnHMCKBqZ6zoH1SiAyqHkFh +Raw Script-expression-ID-Hash: 0x22809fd952c3478272e90aa2f8e59260e81bfa5c35329845dddbd462470f61bc +Ledger Blake2b hash: 3KgcqHyPuSS1yTH3UyqenupZv8z2dDJjXmuDNUoZa8ew +Raw Sha256 hash: 0xe61760f1647df1aa8f3f64cf8a93fecddf536ed4867d4111cbedab7652f8267f +Raw Sha512 hash: 0x4a3457a98c4f863fb53dfa90af26aa46becda18150cda8e2d3d1de2a1f6536b7c5bc7c99f0216610650e90653d69badca147cd88e3d6f472b5be617c076980e0 +Gas remaining: 1039999.564 units remaining + +./octez-client --mode mockup hash data 'Some "foo"' of type 'option string' +Raw packed data: 0x0505090100000003666f6f +Script-expression-ID-Hash: expruWj1i3NoT1rSzrv22q9uTuL8Ax5LcRkhHQJLDbRfaHSydRmpx4 +Raw Script-expression-ID-Hash: 0x83592457741d2dbb22af78846b3040e92614170c2e4850110a88b2d924a10ac7 +Ledger Blake2b hash: 9qjFGa2NhRMBbutDccsFotBEpNeCuK4mJu95q3hiJZ3U +Raw Sha256 hash: 0xcd56882646da9e0c3309537fb762087316b9bd0c754e7c858b30445e5a4df6a0 +Raw Sha512 hash: 0xb7c841f6c2ab26702ce4b2a72b0f70e63c561ed97bc77df78c2f763e492eb8c86ecf755b60aa1246cc1ba95b0de2d1a3afa3de408325b3b2c764efcb24d1a9e5 +Gas remaining: 1039999.173 units remaining + +./octez-client --mode mockup hash data '(Left True)' of type 'or bool string' +Raw packed data: 0x050505030a +Script-expression-ID-Hash: exprufiG2ZNeHqrtWKs4bJ3yPwqxxe2W1jPv8NfHezGjadF15ruvUw +Raw Script-expression-ID-Hash: 0x97c11ba899e5d0cb4772b7932f1669b4ab29113b0f17c88e22fd10fc1faf991e +Ledger Blake2b hash: BDPMBz4ejDv6jv7uARzSz4Uv5LbixRHZJ2K7vfXGhzhT +Raw Sha256 hash: 0x07b7ad9ed53b16bf17d52aa7eb3ae77fba8671f6f979eccc92ecf9e6702f7b1f +Raw Sha512 hash: 0xb2de8eb67db0b449a7b5b844e6c7d1cb8ca874003a1e43b802bf273474e621deaefe7cdfb27c2bd2c78326e2e0506f1ecae038be143cf5b4b4d7e918b6ebc72e +Gas remaining: 1039999.188 units remaining + +./octez-client --mode mockup hash data '(Right "foo")' of type 'or bool string' +Raw packed data: 0x0505080100000003666f6f +Script-expression-ID-Hash: exprvD9V6jDDCiYUQjkqNdnD2eFyqMA76Rkoa6rpVXkim7hcqHFFEz +Raw Script-expression-ID-Hash: 0xdf2193b9a689f10ac5c8a48c577f3e2a94221bd9ac884b5fa1b74f3f916d7dd3 +Ledger Blake2b hash: G21cWq5PkGo84UkfufjDCMXWsSQA3PEDBLKYPt1qtvan +Raw Sha256 hash: 0x2477b0dad8808245eacf22a51ef1f6b9bcb59b8f4d4b3a979132fa74dd129abf +Raw Sha512 hash: 0x64d21e4c66c2c1da70cda80a9609a28e8571734e42a63927753c2027f5c168086fd9925ddaee1544b254fbf63b055bc5ee4e9a987f457b58be04abbdfd29ac57 +Gas remaining: 1039999.113 units remaining + +./octez-client --mode mockup hash data '(Pair 0 True)' of type 'pair int bool' +Raw packed data: 0x0507070000030a +Script-expression-ID-Hash: exprubgTpz2xzfqw7VxoZ9CfmYeQCayFc4mAA9pgnXDKXo64FD2tDw +Raw Script-expression-ID-Hash: 0x8e99fc570ca12731c2a09203fb84b25f93264a234dc1dc6abd8b920a06309794 +Ledger Blake2b hash: Abf5a9UGQ2gcU7V918Pcss2DaTVaqdkBrDYUi55p4Bfh +Raw Sha256 hash: 0x754da3f12fe6c0317d39bc71ff0489d763047648833d3403cdb348c93f9c2678 +Raw Sha512 hash: 0xfc2f3d753f8749bec06d6cccadd8263d69ca4121af57d0fce69b62bdb82173d3403b28cd69eb551827c7b80384d77e48b42be7399f06e310762a80ebcdfb5e1b +Gas remaining: 1039998.872 units remaining + +./octez-client --mode mockup hash data '(Pair 0 (Pair True 0x))' of type 'pair int bool bytes' +Raw packed data: 0x05070700000707030a0a00000000 +Script-expression-ID-Hash: expruJK4yoH9hmZUDgbb5DBtjekERQd913ar43wFgkLVL4eYcFtDsT +Raw Script-expression-ID-Hash: 0x6729d37ba0b7c4f8746e53816067fec805fbbd37253d81cf974b6edd054da22b +Ledger Blake2b hash: 7whz5UYUjV52kQv1B1QUoYk1pMwRay1gEsB8XwP5ce5Q +Raw Sha256 hash: 0x2ee3aa1d789b740d21b535384a8ec28c7c375484576f070a0ea03f0ada7917fd +Raw Sha512 hash: 0x83faf6a6c5c205a86087d77460f54a582f285918f45847376b7a722520f69acf23d6a9f09cce2646fcd279f33241ab345e2e17613f0babd1ebc5979713bff784 +Gas remaining: 1039998.120 units remaining + +./octez-client --mode mockup hash data '(Pair 0 True 0x)' of type 'pair int bool bytes' +Raw packed data: 0x05070700000707030a0a00000000 +Script-expression-ID-Hash: expruJK4yoH9hmZUDgbb5DBtjekERQd913ar43wFgkLVL4eYcFtDsT +Raw Script-expression-ID-Hash: 0x6729d37ba0b7c4f8746e53816067fec805fbbd37253d81cf974b6edd054da22b +Ledger Blake2b hash: 7whz5UYUjV52kQv1B1QUoYk1pMwRay1gEsB8XwP5ce5Q +Raw Sha256 hash: 0x2ee3aa1d789b740d21b535384a8ec28c7c375484576f070a0ea03f0ada7917fd +Raw Sha512 hash: 0x83faf6a6c5c205a86087d77460f54a582f285918f45847376b7a722520f69acf23d6a9f09cce2646fcd279f33241ab345e2e17613f0babd1ebc5979713bff784 +Gas remaining: 1039998.120 units remaining + +./octez-client --mode mockup hash data '{0; True; 0x}' of type 'pair int bool bytes' +Raw packed data: 0x05070700000707030a0a00000000 +Script-expression-ID-Hash: expruJK4yoH9hmZUDgbb5DBtjekERQd913ar43wFgkLVL4eYcFtDsT +Raw Script-expression-ID-Hash: 0x6729d37ba0b7c4f8746e53816067fec805fbbd37253d81cf974b6edd054da22b +Ledger Blake2b hash: 7whz5UYUjV52kQv1B1QUoYk1pMwRay1gEsB8XwP5ce5Q +Raw Sha256 hash: 0x2ee3aa1d789b740d21b535384a8ec28c7c375484576f070a0ea03f0ada7917fd +Raw Sha512 hash: 0x83faf6a6c5c205a86087d77460f54a582f285918f45847376b7a722520f69acf23d6a9f09cce2646fcd279f33241ab345e2e17613f0babd1ebc5979713bff784 +Gas remaining: 1039998.120 units remaining + +./octez-client --mode mockup hash data '{}' of type 'set bool' +Raw packed data: 0x050200000000 +Script-expression-ID-Hash: exprvLcRMXArBMo4ZGN2fxbyDgW4hQTTTRd48VUbEwC4o2dMR2YjFP +Raw Script-expression-ID-Hash: 0xf0147b0fcd9ed958297e3e663f25d0427f7f70576f22047a8d52953941a8b057 +Ledger Blake2b hash: HAAxipLZ7LdX9GLgN7p1bX9KneQ82FcCsss3YicsKaAS +Raw Sha256 hash: 0x077e8b5d0b528d84284d773f8cc36da052248bb96c341d68d51b86e0ce098262 +Raw Sha512 hash: 0x7553bc601c56a361eb537e2bcba685ae6fbf3b68003bd9426db318352db433445aee770bab94631ce5bdf29b948caf1665e208c9be33d8b70fa67d2839d4a16a +Gas remaining: 1039999.564 units remaining + +./octez-client --mode mockup hash data '{ 0 ; 3 ; 4 }' of type 'set nat' +Raw packed data: 0x050200000006000000030004 +Script-expression-ID-Hash: expruTArjjBYFarD9wM3cZJWXr4ZGzDNmZ4NzJja4evPDhDaGRRS5F +Raw Script-expression-ID-Hash: 0x7b470c4d4cd099659964e7ae56f49599a16e5c4ddbe03898a7f87b08f8cb4a6f +Ledger Blake2b hash: 9JDyxjR1Pex14hzrrVN6wUuVdug418EbGy9PytyWi36E +Raw Sha256 hash: 0x79b8b0a86bb4e9939b552d8bfc98c50b991ae227235a3d39381349817ebdda9f +Raw Sha512 hash: 0x34de860c30437423f988cff5ed945981ed4b82dc8a9153f1fbb387e3a05d502d494aa3fb627698a2d7d3b769715e24f844274d0a86bbddff3d955d97ba39d410 +Gas remaining: 1039998.346 units remaining + +./octez-client --mode mockup hash data '"ABC\n123"' of type string +Raw packed data: 0x0501000000074142430a313233 +Script-expression-ID-Hash: expru9epr1Q99NjjgfhQBBmLiAb55ATvHcpvXqVfxnjQyAo3qLpTSU +Raw Script-expression-ID-Hash: 0x53804fa1fb0854914ed6562bc7dde5d9c2307bbf5ac70e787a715c113e36d6c6 +Ledger Blake2b hash: 6cxKSKRL7E2Bpg1ZPZkWT7hXgLKyHJxLc5NA2Q2H1jqX +Raw Sha256 hash: 0x3ebab0c348173626afcb9c982d06ee1189fb1a6359eecd33b30af851aacdcc0f +Raw Sha512 hash: 0x086fccde9f22aba378cd47833d9613f6d1cfd3f15fb6a8dde0eb57e1da651de8ef69886a7a4ebbadf50155910d1fbcc9048e0d9acb196be04adf519476d52307 +Gas remaining: 1039999.469 units remaining + +./octez-client --mode mockup hash data '"edsigthTzJ8X7MPmNeEwybRAvdxS1pupqcM5Mk4uCuyZAe7uEk68YpuGDeViW8wSXMrCi5CwoNgqs8V2w8ayB5dMJzrYCHhD8C7"' of type signature +Raw packed data: 0x050a0000004049d47dba27bd76208b092f3e500f64818920c817491b8b9094f28c2c2b9c6721b257b8878ce47182122b8ea84aeacd84a8aa28cb1f1fe48a26355a7bca4b8306 +Script-expression-ID-Hash: exprtXK3xDMDMu3vGVkb6m9JxwRb3t62tZZNWZPS6FGCY5oFVcZuaM +Raw Script-expression-ID-Hash: 0x00fc144dd18ae1a2d0c6247aa7dad67b2f8bec1b26984437b4bdf02e2d296783 +Ledger Blake2b hash: 14qwXuZ6GDwjvb9GEyurnLg9ZABtnQUAVuDXuGtFAYhp +Raw Sha256 hash: 0xf432ec1cf86bc818d9dff9f69870eaedbbfaee429f2619500757f3ce1d7bc1a9 +Raw Sha512 hash: 0xd7f46bdf12090e235e59f0a61af1ca90f64f6022bd5df479a62f16fd829c6cec431dc081ee16f0c103eec70be968d3f70ec9f584f8948d31c804a87ddc82b1b3 +Gas remaining: 1039992.529 units remaining + +./octez-client --mode mockup hash data '"spsig1PPUFZucuAQybs5wsqsNQ68QNgFaBnVKMFaoZZfi1BtNnuCAWnmL9wVy5HfHkR6AeodjVGxpBVVSYcJKyMURn6K1yknYLm"' of type signature +Raw packed data: 0x050a00000040865b0ceaa2decd64fea1b7e0e97d6ae8035125d821ebe99d7d5c8a559f36fdd43388a570e475011f6d2bbef184ece9bafbf0ac12157f7257988e9575ae2cbca9 +Script-expression-ID-Hash: expruiLTZFkM8c6b9yURRmpLK3f7AAQbPQc11DeCSLoWUqGMUwLiSn +Raw Script-expression-ID-Hash: 0x9db673f2907fafceb934a674351b57e76ba2bf9b3ee2f6edac327089ef5aa749 +Ledger Blake2b hash: BceNWVXjPX5jc4D1kauy4Evh21C8q53aQRJFMzEpLXWx +Raw Sha256 hash: 0x42fe71aa3f9fa7d868a2a8aee492b2a559fba87f8c15403ffe753fc0effffd17 +Raw Sha512 hash: 0xc9a9d704af153d9a2d046bd428f817c9db9ec5d52881ac31e28ed1faca821d34b797bee5171855d6f35ecefed7db2800a20639fc1f877672d03b456af7cf296e +Gas remaining: 1039992.529 units remaining + +./octez-client --mode mockup hash data '"foo"' of type string +Raw packed data: 0x050100000003666f6f +Script-expression-ID-Hash: expruTFUPVsqkuD5iwLMJuzoyGSFABnxLo7CZrgnS1czt1WbTwpVrJ +Raw Script-expression-ID-Hash: 0x7b754bee2b13dd9f9486e6f933e27afc2c31765a8414fc98422255138b04a366 +Ledger Blake2b hash: 9JvtJaNHvYP5bpF7tjbbtpr8o7Jtptz445dZ8pemDnvH +Raw Sha256 hash: 0xe9341dd81166c9253032c8296ae443fbe0d6878502c31cdc431407c4f46dd094 +Raw Sha512 hash: 0x8bf21486ea4a0789bf772b75b3cd8f9edace809f79c38146dbbe2d447edf99f9fcc7c53f511063fe9de21b22baa01710ef6a300546fcc6529812128488e91309 +Gas remaining: 1039999.549 units remaining + +./octez-client --mode mockup hash data '"[TIMESTAMP]"' of type timestamp +Raw packed data: 0x0500a7e8e4d80b +Script-expression-ID-Hash: expruPr6RXBVA966PMQk4kFKyiph9smByS7tFn1hKE6RwAv77VxPes +Raw Script-expression-ID-Hash: 0x73bb27e87ad251d54484fc93a59fac977e3e1af83dfaaa33df4cb7646e01ffdf +Ledger Blake2b hash: 8nmQbgYU3gU2uTXAoJ77miKgQicBLCYYWtnoLzvF5k7Q +Raw Sha256 hash: 0x883ec8d70eeb0beb91bb34dbb5a9a49ffdbe79fd99d8a5fe2b5b508381597bce +Raw Sha512 hash: 0x2b7e8c38c164c6fd93d454fc2ac07122c45616cc616e2789bfb77cc023ef005cf97c8fb8e7c38565d52d0a5fd941a5be0e26e0fd323261069445b89f7ba6086a +Gas remaining: 1039999.416 units remaining + +./octez-client --mode mockup hash data 1571659294 of type timestamp +Raw packed data: 0x05009ef8ecda0b +Script-expression-ID-Hash: exprvPBUjsoev8w7shCt9SLykngSNL393Q8xHJS5eTMSrA2KbecS2x +Raw Script-expression-ID-Hash: 0xf5ea5a2add84cb09fcf97c1d6e931a177dc6b47c27859d0a8c67e6a89c87098c +Ledger Blake2b hash: HYx9bgNpSXhVfVKjoToFJ55LGxpZ8NGNwnfZJdGkYJSP +Raw Sha256 hash: 0xa4e6a8748a04d460e75e1420baa3f4e9d53c758f076a0a5e3730941eade9c72f +Raw Sha512 hash: 0x69c9ac176f1c5da7b15e859224d9877da0ecb9ecb84e0fa580405c46f13cc8ea11365502298f45354dc21ddeccd7ad3772c8d11091870536f156a6fc94aad89a +Gas remaining: 1039999.524 units remaining + +./octez-client --mode mockup hash data Unit of type unit +Raw packed data: 0x05030b +Script-expression-ID-Hash: expruaDPoTWXcTR6fiQPy4KZSW72U6Swc1rVmMiP1KdwmCceeEpVjd +Raw Script-expression-ID-Hash: 0x8b456a4530fb6d0fea9a0dcd0e9d6ff6b30d13b05d05cb4a375dd91bf2a7eadc +Ledger Blake2b hash: ANf4YSkDc71Uy14uWg3wL8u49LUAHdVVnVHbSwNKyEJo +Raw Sha256 hash: 0x5f6d1c5a35306dc8be3a54058774f9cb8f1bc71a6a743a253aad0bfe3a43feef +Raw Sha512 hash: 0xe89c39b714a041046cf421532526b466a8ad29a89a4f027954e4dbdc61b4557f54721ba9e12bf4b901d511037d39481379394e7f86a571bba60f2414e2a56b4c +Gas remaining: 1039999.624 units remaining diff --git a/tezt/tests/expected/increase_paid_storage.ml/Paris- increase paid storage.out b/tezt/tests/expected/increase_paid_storage.ml/Parisb- increase paid storage.out similarity index 100% rename from tezt/tests/expected/increase_paid_storage.ml/Paris- increase paid storage.out rename to tezt/tests/expected/increase_paid_storage.ml/Parisb- increase paid storage.out diff --git a/tezt/tests/expected/increase_paid_storage.ml/Parisc- increase paid storage.out b/tezt/tests/expected/increase_paid_storage.ml/Parisc- increase paid storage.out new file mode 100644 index 000000000000..449cf426ccdf --- /dev/null +++ b/tezt/tests/expected/increase_paid_storage.ml/Parisc- increase paid storage.out @@ -0,0 +1,30 @@ +Node is bootstrapped. +Estimated gas: 168.648 units (will add 0 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is 'oo4vECCgpTowVrRRSPwYcBM3FpkyvitMqVvpHonrjNstrqgR9yU' +NOT waiting for the operation to be included. +Use command + octez-client wait for oo4vECCgpTowVrRRSPwYcBM3FpkyvitMqVvpHonrjNstrqgR9yU to be included --confirmations 1 --branch BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2 +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + Fee to the baker: ꜩ0.000265 + Expected counter: 1 + Gas limit: 169 + Storage limit: 0 bytes + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.000265 + payload fees(the block proposer) ....... +ꜩ0.000265 + Increase paid storage: + Increased size: 1000 bytes + From: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN + To: KT1QmpjYa3WKEtp27inFsS66PS1UyBuvQ2TW + This paid storage increase was successfully applied + Balance updates: + tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... -ꜩ0.25 + storage fees ........................... +ꜩ0.25 + Consumed gas: 168.582 + + diff --git a/tezt/tests/expected/normalize.ml/Paris- Test Michelson stack normalization.out b/tezt/tests/expected/normalize.ml/Parisb- Test Michelson stack normalization.out similarity index 100% rename from tezt/tests/expected/normalize.ml/Paris- Test Michelson stack normalization.out rename to tezt/tests/expected/normalize.ml/Parisb- Test Michelson stack normalization.out diff --git a/tezt/tests/expected/normalize.ml/Paris- Test normalize in unparsing mode.out b/tezt/tests/expected/normalize.ml/Parisb- Test normalize in unparsing mode.out similarity index 100% rename from tezt/tests/expected/normalize.ml/Paris- Test normalize in unparsing mode.out rename to tezt/tests/expected/normalize.ml/Parisb- Test normalize in unparsing mode.out diff --git a/tezt/tests/expected/normalize.ml/Paris- Test normalize script.out b/tezt/tests/expected/normalize.ml/Parisb- Test normalize script.out similarity index 100% rename from tezt/tests/expected/normalize.ml/Paris- Test normalize script.out rename to tezt/tests/expected/normalize.ml/Parisb- Test normalize script.out diff --git a/tezt/tests/expected/normalize.ml/Paris- Test normalize type.out b/tezt/tests/expected/normalize.ml/Parisb- Test normalize type.out similarity index 100% rename from tezt/tests/expected/normalize.ml/Paris- Test normalize type.out rename to tezt/tests/expected/normalize.ml/Parisb- Test normalize type.out diff --git a/tezt/tests/expected/normalize.ml/Paris- Test normalize with legacy flag.out b/tezt/tests/expected/normalize.ml/Parisb- Test normalize with legacy flag.out similarity index 100% rename from tezt/tests/expected/normalize.ml/Paris- Test normalize with legacy flag.out rename to tezt/tests/expected/normalize.ml/Parisb- Test normalize with legacy flag.out diff --git a/tezt/tests/expected/normalize.ml/Parisc- Test Michelson stack normalization.out b/tezt/tests/expected/normalize.ml/Parisc- Test Michelson stack normalization.out new file mode 100644 index 000000000000..3f4caec3f3b5 --- /dev/null +++ b/tezt/tests/expected/normalize.ml/Parisc- Test Michelson stack normalization.out @@ -0,0 +1,520 @@ + +./octez-client --mode mockup normalize stack '{}' +{} + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9)}' +{ Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9) } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10)))}' +{ Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9) ; + Stack_elt (pair nat nat nat nat) (Pair 1 4 7 10) } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10))); Stack_elt (pair nat nat (pair nat nat)) {2; 5; 8; 11}}' +{ Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9) ; + Stack_elt (pair nat nat nat nat) (Pair 1 4 7 10) ; + Stack_elt (pair nat nat nat nat) (Pair 2 5 8 11) } + +./octez-client --mode mockup normalize stack '{}' --unparsing-mode Readable +{} + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9)}' --unparsing-mode Readable +{ Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9) } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10)))}' --unparsing-mode Readable +{ Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9) ; + Stack_elt (pair nat nat nat nat) (Pair 1 4 7 10) } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10))); Stack_elt (pair nat nat (pair nat nat)) {2; 5; 8; 11}}' --unparsing-mode Readable +{ Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9) ; + Stack_elt (pair nat nat nat nat) (Pair 1 4 7 10) ; + Stack_elt (pair nat nat nat nat) (Pair 2 5 8 11) } + +./octez-client --mode mockup normalize stack '{}' --unparsing-mode Optimized +{} + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9)}' --unparsing-mode Optimized +{ Stack_elt (pair nat nat nat nat) { 0 ; 3 ; 6 ; 9 } } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10)))}' --unparsing-mode Optimized +{ Stack_elt (pair nat nat nat nat) { 0 ; 3 ; 6 ; 9 } ; + Stack_elt (pair nat nat nat nat) { 1 ; 4 ; 7 ; 10 } } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10))); Stack_elt (pair nat nat (pair nat nat)) {2; 5; 8; 11}}' --unparsing-mode Optimized +{ Stack_elt (pair nat nat nat nat) { 0 ; 3 ; 6 ; 9 } ; + Stack_elt (pair nat nat nat nat) { 1 ; 4 ; 7 ; 10 } ; + Stack_elt (pair nat nat nat nat) { 2 ; 5 ; 8 ; 11 } } + +./octez-client --mode mockup normalize stack '{}' --unparsing-mode Optimized_legacy +{} + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9)}' --unparsing-mode Optimized_legacy +{ Stack_elt (pair nat nat nat nat) (Pair 0 (Pair 3 (Pair 6 9))) } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10)))}' --unparsing-mode Optimized_legacy +{ Stack_elt (pair nat nat nat nat) (Pair 0 (Pair 3 (Pair 6 9))) ; + Stack_elt (pair nat nat nat nat) (Pair 1 (Pair 4 (Pair 7 10))) } + +./octez-client --mode mockup normalize stack '{Stack_elt (pair nat nat nat nat) (Pair 0 3 6 9); Stack_elt (pair nat (pair nat (pair nat nat))) (Pair 1 (Pair 4 (Pair 7 10))); Stack_elt (pair nat nat (pair nat nat)) {2; 5; 8; 11}}' --unparsing-mode Optimized_legacy +{ Stack_elt (pair nat nat nat nat) (Pair 0 (Pair 3 (Pair 6 9))) ; + Stack_elt (pair nat nat nat nat) (Pair 1 (Pair 4 (Pair 7 10))) ; + Stack_elt (pair nat nat nat nat) (Pair 2 (Pair 5 (Pair 8 11))) } + +./octez-client --mode mockup normalize stack +Error: + Erroneous command line argument 3 (). + empty expression + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack '{' +Error: + Erroneous command line argument 3 ({). + At line 1 characters 0 to 1, unclosed curly brace + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack 0 +Error: + At line 1 characters 0 to 1, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got 0. + +./octez-client --mode mockup normalize stack '{Stack_elt}' +Error: + At line 1 characters 0 to 11, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt }. + At line 1 characters 1 to 10, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack '{Stack_elt nat}' +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat }. + At line 1 characters 1 to 14, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat. + +./octez-client --mode mockup normalize stack '{Stack_elt 0 nat}' +At (unshown) location 0, unexpected int, only a primitive can be used here. +Fatal error: + ill-typed stack + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0 1}' +Error: + At line 1 characters 0 to 19, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 1 }. + At line 1 characters 1 to 18, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat 0 1. + +./octez-client --mode mockup normalize stack 'Stack_elt nat 0' +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got Stack_elt nat 0. + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0; Stack_elt}' +Error: + At line 1 characters 0 to 28, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 ; Stack_elt }. + At line 1 characters 18 to 27, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack --unparsing-mode Readable +Error: + Erroneous command line argument 3 (). + empty expression + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack '{' --unparsing-mode Readable +Error: + Erroneous command line argument 3 ({). + At line 1 characters 0 to 1, unclosed curly brace + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack 0 --unparsing-mode Readable +Error: + At line 1 characters 0 to 1, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got 0. + +./octez-client --mode mockup normalize stack '{Stack_elt}' --unparsing-mode Readable +Error: + At line 1 characters 0 to 11, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt }. + At line 1 characters 1 to 10, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack '{Stack_elt nat}' --unparsing-mode Readable +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat }. + At line 1 characters 1 to 14, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat. + +./octez-client --mode mockup normalize stack '{Stack_elt 0 nat}' --unparsing-mode Readable +At (unshown) location 0, unexpected int, only a primitive can be used here. +Fatal error: + ill-typed stack + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0 1}' --unparsing-mode Readable +Error: + At line 1 characters 0 to 19, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 1 }. + At line 1 characters 1 to 18, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat 0 1. + +./octez-client --mode mockup normalize stack 'Stack_elt nat 0' --unparsing-mode Readable +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got Stack_elt nat 0. + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0; Stack_elt}' --unparsing-mode Readable +Error: + At line 1 characters 0 to 28, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 ; Stack_elt }. + At line 1 characters 18 to 27, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack --unparsing-mode Optimized +Error: + Erroneous command line argument 3 (). + empty expression + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack '{' --unparsing-mode Optimized +Error: + Erroneous command line argument 3 ({). + At line 1 characters 0 to 1, unclosed curly brace + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack 0 --unparsing-mode Optimized +Error: + At line 1 characters 0 to 1, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got 0. + +./octez-client --mode mockup normalize stack '{Stack_elt}' --unparsing-mode Optimized +Error: + At line 1 characters 0 to 11, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt }. + At line 1 characters 1 to 10, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack '{Stack_elt nat}' --unparsing-mode Optimized +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat }. + At line 1 characters 1 to 14, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat. + +./octez-client --mode mockup normalize stack '{Stack_elt 0 nat}' --unparsing-mode Optimized +At (unshown) location 0, unexpected int, only a primitive can be used here. +Fatal error: + ill-typed stack + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0 1}' --unparsing-mode Optimized +Error: + At line 1 characters 0 to 19, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 1 }. + At line 1 characters 1 to 18, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat 0 1. + +./octez-client --mode mockup normalize stack 'Stack_elt nat 0' --unparsing-mode Optimized +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got Stack_elt nat 0. + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0; Stack_elt}' --unparsing-mode Optimized +Error: + At line 1 characters 0 to 28, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 ; Stack_elt }. + At line 1 characters 18 to 27, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack --unparsing-mode Optimized_legacy +Error: + Erroneous command line argument 3 (). + empty expression + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack '{' --unparsing-mode Optimized_legacy +Error: + Erroneous command line argument 3 ({). + At line 1 characters 0 to 1, unclosed curly brace + +Usage: + octez-client [global options] command [command options] + octez-client --help (for global options) + octez-client [global options] command --help (for command options) + octez-client --version (for version information) + +To browse the documentation: + octez-client [global options] man (for a list of commands) + octez-client [global options] man -v 3 (for the full manual) + +Global options (must come before the command): + -d --base-dir : client data directory (absent: TEZOS_CLIENT_DIR env) + -n --no-base-dir-warnings: silence warnings about client data directory + -c --config-file : configuration file + -t --timings: show RPC request times + --chain : chain on which to apply contextual commands (commands dependent on the context associated with the specified chain). Possible tags are 'main' and 'test'. + -b --block : block on which to apply contextual commands (commands dependent on the context associated with the specified block). Possible tags include 'head' and 'genesis' +/- an optional offset (e.g. "octez-client -b head-1 get timestamp"). Note that block queried must exist in node's storage. + -w --wait >: how many confirmation blocks are needed before an operation is considered included + -p --protocol : use commands of a specific protocol + -l --log-requests: log all requests to the node + --better-errors: Error reporting is more detailed. Can be used if a call to an RPC fails or if you don't know the input accepted by the RPC. It may happen that the RPC calls take more time however. + -A --addr : [DEPRECATED: use --endpoint instead] IP address of the node + -P --port : [DEPRECATED: use --endpoint instead] RPC port of the node + -S --tls: [DEPRECATED: use --endpoint instead] use TLS to connect to node. + -m --media-type : Sets the "media-type" value for the "accept" header for RPC requests to the node. The media accept header indicates to the node which format of data serialisation is supported. Use the value "json" for serialisation to the JSON format. + -E --endpoint : HTTP(S) endpoint of the node RPC interface; e.g. 'http://localhost:8732' + -s --sources : path to JSON file containing sources for --mode light. Example file content: {"min_agreement": 1.0, "uris": ["http://localhost:8732", "https://localhost:8733"]} + -R --remote-signer : URI of the remote signer + -f --password-filename : path to the password filename + -M --mode : how to interact with the node + +./octez-client --mode mockup normalize stack 0 --unparsing-mode Optimized_legacy +Error: + At line 1 characters 0 to 1, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got 0. + +./octez-client --mode mockup normalize stack '{Stack_elt}' --unparsing-mode Optimized_legacy +Error: + At line 1 characters 0 to 11, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt }. + At line 1 characters 1 to 10, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. + +./octez-client --mode mockup normalize stack '{Stack_elt nat}' --unparsing-mode Optimized_legacy +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat }. + At line 1 characters 1 to 14, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat. + +./octez-client --mode mockup normalize stack '{Stack_elt 0 nat}' --unparsing-mode Optimized_legacy +At (unshown) location 0, unexpected int, only a primitive can be used here. +Fatal error: + ill-typed stack + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0 1}' --unparsing-mode Optimized_legacy +Error: + At line 1 characters 0 to 19, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 1 }. + At line 1 characters 1 to 18, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt nat 0 1. + +./octez-client --mode mockup normalize stack 'Stack_elt nat 0' --unparsing-mode Optimized_legacy +Error: + At line 1 characters 0 to 15, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got Stack_elt nat 0. + +./octez-client --mode mockup normalize stack '{Stack_elt nat 0; Stack_elt}' --unparsing-mode Optimized_legacy +Error: + At line 1 characters 0 to 28, + Unexpected format for a typed stack. Expected a sequence of Stack_elt ; got { Stack_elt nat 0 ; Stack_elt }. + At line 1 characters 18 to 27, + Unexpected format for an item in a typed stack. Expected: Stack_elt ; got Stack_elt. diff --git a/tezt/tests/expected/normalize.ml/Parisc- Test normalize in unparsing mode.out b/tezt/tests/expected/normalize.ml/Parisc- Test normalize in unparsing mode.out new file mode 100644 index 000000000000..80323b4574cb --- /dev/null +++ b/tezt/tests/expected/normalize.ml/Parisc- Test normalize in unparsing mode.out @@ -0,0 +1,14 @@ + +./octez-client --mode mockup normalize data '{Pair 0 3 6 9; Pair 1 (Pair 4 (Pair 7 10)); {2; 5; 8; 11}}' of type 'list (pair nat nat nat nat)' +{ Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } + +./octez-client --mode mockup normalize data '{Pair 0 3 6 9; Pair 1 (Pair 4 (Pair 7 10)); {2; 5; 8; 11}}' of type 'list (pair nat nat nat nat)' --unparsing-mode Readable +{ Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } + +./octez-client --mode mockup normalize data '{Pair 0 3 6 9; Pair 1 (Pair 4 (Pair 7 10)); {2; 5; 8; 11}}' of type 'list (pair nat nat nat nat)' --unparsing-mode Optimized +{ { 0 ; 3 ; 6 ; 9 } ; { 1 ; 4 ; 7 ; 10 } ; { 2 ; 5 ; 8 ; 11 } } + +./octez-client --mode mockup normalize data '{Pair 0 3 6 9; Pair 1 (Pair 4 (Pair 7 10)); {2; 5; 8; 11}}' of type 'list (pair nat nat nat nat)' --unparsing-mode Optimized_legacy +{ Pair 0 (Pair 3 (Pair 6 9)) ; + Pair 1 (Pair 4 (Pair 7 10)) ; + Pair 2 (Pair 5 (Pair 8 11)) } diff --git a/tezt/tests/expected/normalize.ml/Parisc- Test normalize script.out b/tezt/tests/expected/normalize.ml/Parisc- Test normalize script.out new file mode 100644 index 000000000000..b4642bc280ed --- /dev/null +++ b/tezt/tests/expected/normalize.ml/Parisc- Test normalize script.out @@ -0,0 +1,42 @@ + +./octez-client --mode mockup normalize script michelson_test_scripts/opcodes/comb-literals.tz +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } + +./octez-client --mode mockup normalize script michelson_test_scripts/opcodes/comb-literals.tz --unparsing-mode Readable +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 3 6 9 ; Pair 1 4 7 10 ; Pair 2 5 8 11 } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } + +./octez-client --mode mockup normalize script michelson_test_scripts/opcodes/comb-literals.tz --unparsing-mode Optimized +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { { 0 ; 3 ; 6 ; 9 } ; { 1 ; 4 ; 7 ; 10 } ; { 2 ; 5 ; 8 ; 11 } } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } + +./octez-client --mode mockup normalize script michelson_test_scripts/opcodes/comb-literals.tz --unparsing-mode Optimized_legacy +{ parameter unit ; + storage unit ; + code { PUSH (list (pair nat nat nat nat)) + { Pair 0 (Pair 3 (Pair 6 9)) ; + Pair 1 (Pair 4 (Pair 7 10)) ; + Pair 2 (Pair 5 (Pair 8 11)) } ; + DROP 2 ; + UNIT ; + NIL operation ; + PAIR } } diff --git a/tezt/tests/expected/normalize.ml/Parisc- Test normalize type.out b/tezt/tests/expected/normalize.ml/Parisc- Test normalize type.out new file mode 100644 index 000000000000..c35ef0e62ff8 --- /dev/null +++ b/tezt/tests/expected/normalize.ml/Parisc- Test normalize type.out @@ -0,0 +1,24 @@ + +./octez-client --mode mockup normalize type nat +nat + +./octez-client --mode mockup normalize type 'list nat' +list nat + +./octez-client --mode mockup normalize type 'pair nat int' +pair nat int + +./octez-client --mode mockup normalize type 'list (pair nat int)' +list (pair nat int) + +./octez-client --mode mockup normalize type 'pair nat int bool' +pair nat (pair int bool) + +./octez-client --mode mockup normalize type 'list (pair nat int bool)' +list (pair nat (pair int bool)) + +./octez-client --mode mockup normalize type 'pair nat int bool bytes' +pair nat (pair int (pair bool bytes)) + +./octez-client --mode mockup normalize type 'list (pair nat int bool bytes)' +list (pair nat (pair int (pair bool bytes))) diff --git a/tezt/tests/expected/normalize.ml/Parisc- Test normalize with legacy flag.out b/tezt/tests/expected/normalize.ml/Parisc- Test normalize with legacy flag.out new file mode 100644 index 000000000000..8ecc6976ccf6 --- /dev/null +++ b/tezt/tests/expected/normalize.ml/Parisc- Test normalize with legacy flag.out @@ -0,0 +1,10 @@ + +./octez-client --mode mockup normalize data '{Elt %a 0 1}' of type 'map nat nat' --legacy +{ Elt 0 1 } + +./octez-client --mode mockup normalize data '{Elt %a 0 1}' of type 'map nat nat' +At (unshown) location 0, value { Elt %a 0 1 } +is invalid for type map nat nat. +At (unshown) location 1, unexpected annotation. +Fatal error: + ill-typed data expression diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - RPC API should work and be stable.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - RPC API should work and be stable.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - RPC API should work and be stable.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - RPC API should work and be stable.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - Whitelisted staker can publish a commitment.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - Whitelisted staker can publish a commitment.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - Whitelisted staker can publish a commitment.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - Whitelisted staker can publish a commitment.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - boot sector is evaluated.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - boot sector is evaluated.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - boot sector is evaluated.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - boot sector is evaluated.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - origination of a SCORU executes without error.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - origination of a SCORU executes without error.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - origination of a SCORU executes without error.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - origination of a SCORU executes without error.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - participant of a refutation game are slashed-rewarded.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - participant of a refutation game are slashed-rewarded.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - participant of a refutation game are slashed-rewarded.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - participant of a refutation game are slashed-rewarded.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - recover bond of stakers.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - recover bond of stakers.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - recover bond of stakers.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - recover bond of stakers.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (degraded_new).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (degraded_new).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (degraded_new).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (degraded_new).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (degraded_ongoing).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (degraded_ongoing).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (degraded_ongoing).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (degraded_ongoing).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_at_genesis).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_at_genesis).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_at_genesis).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_at_genesis).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_many_empty_level.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_many_empty_level.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_one_empty_level).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_one_empty_level.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_one_empty_level).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_one_empty_level.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_with_new_content.out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_with_new_conten.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (inbox_proof_with_new_content.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (inbox_proof_with_new_conten.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_0).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_0).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_0).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_0).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_1).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_1).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_1).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_1).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_2).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_2).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_2).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_2).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_3).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_3).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_3).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_3).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_at_genesis).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_at_genesis).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_at_genesis).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_at_genesis).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_second_period).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_second_period).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (pvm_proof_second_period).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (pvm_proof_second_period).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (reset_honest_during_game).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (reset_honest_during_game).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (reset_honest_during_game).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (reset_honest_during_game).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (timeout).out b/tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (timeout).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- arith - refutation games winning strategies (timeout).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- arith - refutation games winning strategies (timeout).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - RPC API should work and be stable.out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - RPC API should work and be stable.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - RPC API should work and be stable.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - RPC API should work and be stable.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - origination of a SCORU executes without error.out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - origination of a SCORU executes without error.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - origination of a SCORU executes without error.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - origination of a SCORU executes without error.out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out diff --git a/tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_period.out b/tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out similarity index 100% rename from tezt/tests/expected/sc_rollup.ml/Paris- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_period.out rename to tezt/tests/expected/sc_rollup.ml/Parisb- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - RPC API should work and be stable.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - RPC API should work and be stable.out new file mode 100644 index 000000000000..8e0cc49b1459 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - RPC API should work and be stable.out @@ -0,0 +1,261 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" +GET http://[HOST]:[PORT]/global/smart_rollup_address +200 OK +"[SMART_ROLLUP_HASH]" + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "312d31", + "312d32", + "312d33", + "312d34", + "312d35" +] +200 OK +["scmsg37MjxsWwLdnhRqRn8suc1oMvpa9riqGvazTg7giMNKDDU56Qfv","scmsg3X1MAjzt2B4r6gZnLf7mzoRf9UohkLw3Q2DTzLKctivKPYLXZ9","scmsg3prfVZhL8jFf5LSmxijjd96pKcz98ws6xe81qKagYcSg53e22N","scmsg2SY3VZWZ8y8491xbXvn8tQtHRCAq3zPJWQ7n4K6Rusw2YKVyNx","scmsg2zdjgY1tnuHMZqMavgPyc7qNj9MMvY4ywd38yauj3WfaiqDieE"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "322d31", + "322d32", + "322d33", + "322d34", + "322d35" +] +200 OK +["scmsg33G4qMwJ869CUzuYWpsdF9bnQ4ezN2YHyERN64j2Q4t9L99CnA","scmsg3ew4TRYot9RPWjagZdNGdSTD3wzUAKU5WFz6JosGBtEr1UT5o5","scmsg3Q6eecZLng9BK7maLP1DGqRpfbygCsQj8vPxc3USjpQxhCfEkn","scmsg2GAoC8FEUfHZfQAKotvjRMpmSknHRpn4w35Y1YWZ4uVZDYvzUL","scmsg2sqy4npoYQq8iWJWQQgrdG126y3Btxn8ZzVPav8JmptWnVowGz"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "332d31", + "332d32", + "332d33", + "332d34", + "332d35" +] +200 OK +["scmsg3EYkw2o4MC45NXUKZsEpzugW9sfumidS78TC8ygnJJznyAe9Yb","scmsg23CHWGTe3u8Utu3RpafBSEzvwnBKNRLxufPp8QindEWanu8UB6","scmsg3WnqzTRN8wvANvLKV4MouiTQZzq7X2G3CfKcomuQy4nKDFGRhX","scmsg3PVb7jXpE723XWdC1B8L34wVenMTi8r4b62Qja6owSMVo3h73C","scmsg2BZBgg1AFG7Zsar6DD1ZKPK36UakNZNj78npg6SUBoR26FpBdQ"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "342d31", + "342d32", + "342d33", + "342d34", + "342d35" +] +200 OK +["scmsg3BLN9sVbJN6BrDh8mu3yDYeVfTBnm83Ciom55sS3dKvvXMk1nR","scmsg2Nsbi6zbwQUTwpBVcTEhi7oVWxbuka1kiHMJ9BLiUg8QfzyLYM","scmsg3Ti1eX6WyPXKjy3NdkJnQdzi5RbkFJ8piWhEpDQwWn8VdNMuCK","scmsg3TMS4Q8jtUhr6YcgkMqwWAXKkXLJMhSRvJcMEgq61t8xftRMFv","scmsg2AWA1jULPBJb7usha9gJg62T5PdiW9Uz1HdHLhaYDRx4qRvLTL"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "352d31", + "352d32", + "352d33", + "352d34", + "352d35" +] +200 OK +["scmsg26t9x2GH9Pt9hiGLnSyNRALPzL8BYcTHik6PvU4vGDbUYM6JkV","scmsg3rtv5BpkWSR835sbwXJDBYZZW1ptXr8KKxprn4nJnhSacn6t1R","scmsg32QBihqJwKecppnv3o4MpRVYycR6puAHyhZhDVtewFQwmTdR3Z","scmsg3LQsvXBvj1qDWFRACbLuyAbZK6tHVTUeiYsPSU9KGxyf6ySxrY","scmsg3oXBwG2rAT3cjgDbRNyBnTirrkqTAeVMxMSJ5KUno8daWpY2rL"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "362d31", + "362d32", + "362d33", + "362d34", + "362d35" +] +200 OK +["scmsg2pUJoCjenPKAK3WnftrcnnKFf8RjTmoie2PS5Xa9jh2f6V4CpU","scmsg3M61S4suJDXn1yZyQrk9iy3WrDTXbPA6JHaeDWMjUJ4bhFTyAf","scmsg3SSJRKjcqvMFg2y6tuKWbikFx49kE5PfGg71uhxYdoMHBzutgU","scmsg3MPjHQ6m6BPJaGnAan8kCnadyCbn37DKAZa7LTbTtz3N36JgtW","scmsg2mUAHp9G2cJoqKwr4dpagFK6Wa4cNu7NGPXXB3zTfCpLmCP3Yr"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "372d31", + "372d32", + "372d33", + "372d34", + "372d35" +] +200 OK +["scmsg2VzSQUy8uj6yXYjwhLp2Qsmr77NixYmsXqqBGJpGsSxVBZHBPN","scmsg2p1iyQ4MHjNZrZhRmatcGXCzSr3Af7GKg6jawijWAe5ZpwFUMR","scmsg2xU6itfmj6XeuzYVqGza4Z95uAUXG44mnkM8uKkkdmbv8DyhS3","scmsg3YhsmhbfMXKmhsjGXej2ySwYFDYKQE1yUs7LcVkZ2ikaotWQKg","scmsg28neefD54Wsf46QgPtv22mKT32oNFv5ToU95DDsufcWFCZoovM"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "382d31", + "382d32", + "382d33", + "382d34", + "382d35" +] +200 OK +["scmsg3krb3ZX2JqPJkoBkrrFJcEtguu4sJDFS1XukN4PboYfxVRMZB8","scmsg2CXLxs8exJxS49Fi1bQFHhyy27fpTUwNZ8xhbuyd2uo4YmgWYL","scmsg2XJwuzAw5tZhfiTpUoDNSiM56W97YNEB4YyzGnrBcEgYpL9KMh","scmsg3RM54nLATBFqzCjvSwPybSbiiWJZey2ZiLbe1gjr9v9Vmoc9H3","scmsg2NpFWt1MhyDGhacEUpaeEheC8XWzNC3LaNaECXwzpi39QqPX14"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "392d31", + "392d32", + "392d33", + "392d34", + "392d35" +] +200 OK +["scmsg2nWa7VYthVQxL9antueegTTcyGzTqZzbFPVibWk8xzRGWvfdt8","scmsg3KfqCW3JtQAFWYUUKfaxUZ3zeR8t6233UU5frsUgZXjwyRaftR","scmsg2TJRQjXv5VYgrcVYM4upqfptRz4gLmDV1AMLcxqGJz2faoKfDK","scmsg2DBhcJVTm8JRWQHLWDXxiCi2PvUZzixqxkqyYupDZW2XU3cdvJ","scmsg2jKWtDbw5Jsdpc453XsgAVBKyYUzt3pKKsZtQNtvJvhPemp4WN"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31302d31", + "31302d32", + "31302d33", + "31302d34", + "31302d35" +] +200 OK +["scmsg3hFFdb5QTM1kbP7UmHviyd6VWfYaT9KTWDcTjE51BtRdjbCJjq","scmsg318GJr61qixBt6P4BxuUZ9zXZGct9fpknY7bky676r8esQjLrt","scmsg2twRwJCXXzvMYcD4Zu3zQSkHjhsDs9ZBczAi4Lvx7ogvJmeCGZ","scmsg3YFj784yYxTr4LbNfaLpHGpN5hKJgbBA8gUEJ4vief5KL8U5vS","scmsg2GY9Q5VTRSrjCPewduDXtPtZZ9hhMshPe3zUToBvFHTD9AhKkB"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31312d31", + "31312d32", + "31312d33", + "31312d34", + "31312d35" +] +200 OK +["scmsg2S7XcHeyAHTQy6cJ6pVgxYqdW7XTBz3PsiCx26gyp2EHfCUJTh","scmsg34AzeCpQWbx2MicoEqumBeh5PzkmeB3XkASNCeEn4u5AC2TQtC","scmsg23m7SEy65fobQJ22FS7dmnHqPe2pmpCaA5iVWA8KYm4ZU3CVfK","scmsg3KLGXHeokSBbJcfsrvRkoAjMt5Yi7nj67WFHh6nkW8Ce8Kd4yn","scmsg2Eaop6LYBSnKMQXqPWijq9fBa4nPw5ZLndHRCH97kumZqLT7pn"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31322d31", + "31322d32", + "31322d33", + "31322d34", + "31322d35" +] +200 OK +["scmsg3Rbcvi4zn7DSuXY8FHordHD4BMqXGi8XhrYAg9Z369qN2qPuPf","scmsg2JtmeQPL8JBY2MgEKx5f6XvH1bJjnqrjTpPVapmDaVBVcGHf8L","scmsg2xrhpVNNsUzYNF7LsNmeAbX2wJsZWE8Ub7DQRe8sToXxSjKR4T","scmsg3HMVWn75kiJ4Lr3KquJNQTkkFtwg9pmiKMythhUJ5h74Nznjd3","scmsg24y1317Sy46HnzTpvCLRe88LghadZ4eAjkb6EzvEsQVRhPbKzu"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31332d31", + "31332d32", + "31332d33", + "31332d34", + "31332d35" +] +200 OK +["scmsg2vjhNLAF3AeKmzkWbwkVELTGnQcEdsPeD6imGgeejsQta46LxA","scmsg2mQYGCav4HTBebHEeeVscAeMGL8d17eDZSCeTEBsukRyri51mZ","scmsg3CyDxp7PAws2HXGTyCeeamNDCs3acBnN7Jymj3GVW3WCS1GKEz","scmsg2Safqm8tXs1k51v1A7VMyALCDRn5DAgYCJ9kbUD38jwPqtob6B","scmsg28V9X7iiXCDZM4mFCHKsMxuvc8wNopLGkcnZwo14sSs4dW1E73"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31342d31", + "31342d32", + "31342d33", + "31342d34", + "31342d35" +] +200 OK +["scmsg2LeoW8SZzjCREGXpS2kwSfWCQBLf4M39gCQbuo7MPdcNUQgskZ","scmsg3KJEQRBNfv4DUb4LCA7EWAh9swowVibwH4Hx7CYn4mjFTEKNfC","scmsg2fWu16weRJCcgdvJzNtdWDNATvftgUVFfpgi5z3BDn9h2zE1Z2","scmsg29adqVUp1NnCAVSZVaKCVbrUdMth3C1yuUvBRZtmW9hsDtm8d1","scmsg2cDM9bscYDvXwkeB6h7RmN82wFgmL3wv5jJmwJukS9ju5zgKWA"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31352d31", + "31352d32", + "31352d33", + "31352d34", + "31352d35" +] +200 OK +["scmsg2DSE1zcsJXhEFsAFMo3qN7jV13LoxrG6qa1RaJtUFkPgJCBN5R","scmsg2StxsCnbG5vQmzdiY3F4M5bsrkb6Qh3CyrMod5thRVAbZHd38c","scmsg3fzM3qS4iPZ6qGHCNfupVUKiuYmrNe4k13uUj3ggrzX6rayaVA","scmsg3qHUB6rys7GmC8XGGKRDrcKX2veZGkT9SkScHyWqLUCjq9PLjx","scmsg3ZVMYBmAPwFfLDNXFDcBGzRChdFzLJ8tUMW46mGPGumZ6aq79q"] + +GET http://[HOST]:[PORT]/global/block/head/hash +200 OK +"[BLOCK_HASH]" + +GET http://[HOST]:[PORT]/global/block/5/hash +200 OK +"[BLOCK_HASH]" + +GET http://[HOST]:[PORT]/global/block/finalized/level +200 OK +16 + +GET http://[HOST]:[PORT]/global/block/head/num_messages +200 OK +"8" + +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/value?key=/readonly/wasm_version +404 Not Found + +GET http://[HOST]:[PORT]/global/block/head/durable/arith/value?key=/readonly/wasm_version +404 Not Found + +GET http://[HOST]:[PORT]/global/block/head/status +200 OK +"Waiting for input message" + +GET http://[HOST]:[PORT]/global/block/head/ticks +200 OK +"28" + +GET http://[HOST]:[PORT]/global/block/head/state_hash +200 OK +"[SC_ROLLUP_PVM_STATE_HASH]" + +GET http://[HOST]:[PORT]/global/tezos_head +200 OK +"[BLOCK_HASH]" + +GET http://[HOST]:[PORT]/global/tezos_level +200 OK +18 + diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - Whitelisted staker can publish a commitment.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - Whitelisted staker can publish a commitment.out new file mode 100644 index 000000000000..ee48e034e0ba --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - Whitelisted staker can publish a commitment.out @@ -0,0 +1,2 @@ + +./octez-client --wait none publish commitment from bootstrap1 for smart rollup '[SMART_ROLLUP_HASH]' with compressed state '[SC_ROLLUP_PVM_STATE_HASH]' at inbox level 2 and predecessor '[SC_ROLLUP_COMMITMENT_HASH]' and number of ticks 1 diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - boot sector is evaluated.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - boot sector is evaluated.out new file mode 100644 index 000000000000..fd5968cda067 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - boot sector is evaluated.out @@ -0,0 +1,92 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind arith of type string with kernel '10 10 10 + +' --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.469 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000453 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000453 + payload fees(the block proposer) ....... +ꜩ0.000453 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '8eb6ccf70902fcd3fa2040cf27dda202a71d85625516f22a0c9c67fc86057a7b' + This smart rollup origination was successfully applied + Consumed gas: 1930.436 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" + +./octez-client --wait none originate smart rollup rollup2 from bootstrap2 of kind arith of type string with kernel 31 --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.103 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000443 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000443 + payload fees(the block proposer) ....... +ꜩ0.000443 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: 'b682df8c87f218dfa8151f2eaafe20e6f8d87b243f8fe63de6d49485a8bf6eea' + This smart rollup origination was successfully applied + Consumed gas: 1930.070 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup2" + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/genesis_info' +{ "level": 2, + "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/commitment/[SC_ROLLUP_COMMITMENT_HASH]' +{ "compressed_state": + "[SC_ROLLUP_PVM_STATE_HASH]", + "inbox_level": 2, + "predecessor": "[SC_ROLLUP_COMMITMENT_HASH]", + "number_of_ticks": "0" } + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/genesis_info' +{ "level": 3, + "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } + +./octez-client rpc get '/chains/main/blocks/head/context/smart_rollups/smart_rollup/[SMART_ROLLUP_HASH]/commitment/[SC_ROLLUP_COMMITMENT_HASH]' +{ "compressed_state": + "[SC_ROLLUP_PVM_STATE_HASH]", + "inbox_level": 3, + "predecessor": "[SC_ROLLUP_COMMITMENT_HASH]", + "number_of_ticks": "0" } diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - origination of a SCORU executes without error.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - origination of a SCORU executes without error.out new file mode 100644 index 000000000000..af45c295c5d9 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - origination of a SCORU executes without error.out @@ -0,0 +1,35 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - participant of a refutation game are slashed-rewarded.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - participant of a refutation game are slashed-rewarded.out new file mode 100644 index 000000000000..dd1dc9010ea4 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - participant of a refutation game are slashed-rewarded.out @@ -0,0 +1,141 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" + +./octez-client --wait none publish commitment from '[PUBLIC_KEY_HASH]' for smart rollup '[SMART_ROLLUP_HASH]' with compressed state '[SC_ROLLUP_PVM_STATE_HASH]' at inbox level 4 and predecessor '[SC_ROLLUP_COMMITMENT_HASH]' and number of ticks 1 +Node is bootstrapped. +Estimated gas: 6588.924 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000989 + Expected counter: 1 + Gas limit: 6689 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000989 + payload fees(the block proposer) ....... +ꜩ0.000989 + Smart rollup commitment publishing: + Address: [SMART_ROLLUP_HASH] + Commitment: + compressed_state: [SC_ROLLUP_PVM_STATE_HASH] + inbox_level: 4 + predecessor: [SC_ROLLUP_COMMITMENT_HASH] + number_of_ticks: 1 + This smart rollup commitment publishing was successfully applied + Consumed gas: 6588.858 + Hash of commit: [SC_ROLLUP_COMMITMENT_HASH] + Commitment published at level: 6 + Balance updates: + [PUBLIC_KEY_HASH] ...................................................... -ꜩ10000 + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... +ꜩ10000 + + +./octez-client --wait none publish commitment from '[PUBLIC_KEY_HASH]' for smart rollup '[SMART_ROLLUP_HASH]' with compressed state '[SC_ROLLUP_PVM_STATE_HASH]' at inbox level 4 and predecessor '[SC_ROLLUP_COMMITMENT_HASH]' and number of ticks 2 +Node is bootstrapped. +Estimated gas: 7287.126 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.001059 + Expected counter: 1 + Gas limit: 7388 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.001059 + payload fees(the block proposer) ....... +ꜩ0.001059 + Smart rollup commitment publishing: + Address: [SMART_ROLLUP_HASH] + Commitment: + compressed_state: [SC_ROLLUP_PVM_STATE_HASH] + inbox_level: 4 + predecessor: [SC_ROLLUP_COMMITMENT_HASH] + number_of_ticks: 2 + This smart rollup commitment publishing was successfully applied + Consumed gas: 7287.060 + Hash of commit: [SC_ROLLUP_COMMITMENT_HASH] + Commitment published at level: 7 + Balance updates: + [PUBLIC_KEY_HASH] ...................................................... -ꜩ10000 + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... +ꜩ10000 + + +./octez-client --wait none timeout dispute on smart rollup '[SMART_ROLLUP_HASH]' with '[PUBLIC_KEY_HASH]' against '[PUBLIC_KEY_HASH]' from bootstrap1 +Node is bootstrapped. +Estimated gas: 3715.433 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000668 + Expected counter: 2 + Gas limit: 3816 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000668 + payload fees(the block proposer) ....... +ꜩ0.000668 + Smart rollup refutation timeout: + Address: [SMART_ROLLUP_HASH] + First staker (Alice): [PUBLIC_KEY_HASH] + Second staker (Bob): [PUBLIC_KEY_HASH] + This smart rollup refutation timeout was successfully applied + Consumed gas: 3715.367 + Refutation game status: Game ended: [PUBLIC_KEY_HASH] lost because: timeout + Balance updates: + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... -ꜩ10000 + smart rollup refutation punishments ....................................................... +ꜩ10000 + smart rollup refutation rewards ........................................................... -ꜩ5000 + [PUBLIC_KEY_HASH] ...................................................... +ꜩ5000 + diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - recover bond of stakers.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - recover bond of stakers.out new file mode 100644 index 000000000000..07922b00364e --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - recover bond of stakers.out @@ -0,0 +1,195 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind arith of type string with kernel --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1930.030 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 1 + Gas limit: 2031 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Smart rollup origination: + Kind: arith + Parameter type: string + Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' + This smart rollup origination was successfully applied + Consumed gas: 1929.997 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" + +./octez-client --wait none publish commitment from '[PUBLIC_KEY_HASH]' for smart rollup '[SMART_ROLLUP_HASH]' with compressed state '[SC_ROLLUP_PVM_STATE_HASH]' at inbox level 12 and predecessor '[SC_ROLLUP_COMMITMENT_HASH]' and number of ticks 1 +Node is bootstrapped. +Estimated gas: 6588.924 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000989 + Expected counter: 2 + Gas limit: 6689 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000989 + payload fees(the block proposer) ....... +ꜩ0.000989 + Smart rollup commitment publishing: + Address: [SMART_ROLLUP_HASH] + Commitment: + compressed_state: [SC_ROLLUP_PVM_STATE_HASH] + inbox_level: 12 + predecessor: [SC_ROLLUP_COMMITMENT_HASH] + number_of_ticks: 1 + This smart rollup commitment publishing was successfully applied + Consumed gas: 6588.858 + Hash of commit: [SC_ROLLUP_COMMITMENT_HASH] + Commitment published at level: 14 + Balance updates: + [PUBLIC_KEY_HASH] ...................................................... -ꜩ10000 + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... +ꜩ10000 + + +./octez-client --wait none publish commitment from '[PUBLIC_KEY_HASH]' for smart rollup '[SMART_ROLLUP_HASH]' with compressed state '[SC_ROLLUP_PVM_STATE_HASH]' at inbox level 12 and predecessor '[SC_ROLLUP_COMMITMENT_HASH]' and number of ticks 1 +Node is bootstrapped. +Estimated gas: 6810.852 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.001012 + Expected counter: 1 + Gas limit: 6911 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.001012 + payload fees(the block proposer) ....... +ꜩ0.001012 + Smart rollup commitment publishing: + Address: [SMART_ROLLUP_HASH] + Commitment: + compressed_state: [SC_ROLLUP_PVM_STATE_HASH] + inbox_level: 12 + predecessor: [SC_ROLLUP_COMMITMENT_HASH] + number_of_ticks: 1 + This smart rollup commitment publishing was successfully applied + Consumed gas: 6810.786 + Hash of commit: [SC_ROLLUP_COMMITMENT_HASH] + Commitment published at level: 14 + Balance updates: + [PUBLIC_KEY_HASH] ...................................................... -ꜩ10000 + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... +ꜩ10000 + + +./octez-client --wait none cement commitment from bootstrap1 for smart rollup '[SMART_ROLLUP_HASH]' +Node is bootstrapped. +Estimated gas: 4839.262 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000738 + Expected counter: 3 + Gas limit: 4940 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000738 + payload fees(the block proposer) ....... +ꜩ0.000738 + Smart rollup commitment cementing: + Address: [SMART_ROLLUP_HASH] + This smart rollup commitment cementing was successfully applied + Consumed gas: 4839.196 + Inbox level: 12 + Commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + + +./octez-client --wait none recover bond of '[PUBLIC_KEY_HASH]' for smart rollup '[SMART_ROLLUP_HASH]' from '[PUBLIC_KEY_HASH]' --fee 1 +Node is bootstrapped. +Estimated gas: 3084.518 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ1 + Expected counter: 4 + Gas limit: 3185 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1 + payload fees(the block proposer) ....... +ꜩ1 + Smart rollup bond retrieval: + Address: [SMART_ROLLUP_HASH] + Staker: [PUBLIC_KEY_HASH] + This smart rollup bond retrieval was successfully applied + Balance updates: + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... -ꜩ10000 + [PUBLIC_KEY_HASH] ...................................................... +ꜩ10000 + Consumed gas: 3084.418 + + +./octez-client --wait none recover bond of '[PUBLIC_KEY_HASH]' for smart rollup '[SMART_ROLLUP_HASH]' from '[PUBLIC_KEY_HASH]' --fee 1 +Node is bootstrapped. +Estimated gas: 3084.518 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ1 + Expected counter: 5 + Gas limit: 3185 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1 + payload fees(the block proposer) ....... +ꜩ1 + Smart rollup bond retrieval: + Address: [SMART_ROLLUP_HASH] + Staker: [PUBLIC_KEY_HASH] + This smart rollup bond retrieval was successfully applied + Balance updates: + Frozen_bonds([PUBLIC_KEY_HASH],[SMART_ROLLUP_HASH]) ... -ꜩ10000 + [PUBLIC_KEY_HASH] ...................................................... +ꜩ10000 + Consumed gas: 3084.418 + diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_new).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_new).out new file mode 100644 index 000000000000..21dd59570246 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_new).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "417", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs11XB2HCGteKCrjd3RzTeJErbFbFQFbWtztckuCCTF6rgMjFxJDX", + "tick": "13" + }, + { + "state": "srs12VUVuf4HJpcGQJDzVcpb3aaFuAvjENSgV4nRztkmWBSxL5WHaF", + "tick": "26" + }, + { + "state": "srs12ZnLptmHevRWau257DcrcnM2eNnFo7bFbc2sv2foTD8ZKCXTZe", + "tick": "39" + }, + { + "state": "srs12xQANQN4eAkSsP8zmcYkPpAFK4UTpAU6TvoumjmBiYy6CkVYzC", + "tick": "52" + }, + { + "state": "srs12s3Cb9eyFoavFQUWAZNjSnSFi5HEnkYfHyapLB2P5u7eB2Dd4K", + "tick": "65" + }, + { + "state": "srs128dvNSvYvCSMJfddzr7PcbH2HVynAF4dxEwLvTeVVSejCCa3bE", + "tick": "78" + }, + { + "state": "srs12B5HfbEsm6JPLh8Mm7xrbwpz4A3YLw7r5fKkyqZjgmGns647jV", + "tick": "91" + }, + { + "state": "srs124dtumicoAkWyp3KDjdtix2bZUMmhK4E8eP3RQnJtpVWJ9gQit", + "tick": "104" + }, + { + "state": "srs121MBsHEQZF8ytUDwsP6bj4vVdhMgvD1ELph9vCQsCAj7umHK7m", + "tick": "117" + }, + { + "state": "srs13NVfKCCRucqkqBw1x84RTmf4haNGL6dPbQYzEgQ36EHJfhnC9j", + "tick": "130" + }, + { + "state": "srs11qS1sYhQJGb2ceCuRXAd4u3nyVwboRVK7Bwud73zhTXiR1rr3Z", + "tick": "143" + }, + { + "state": "srs12Q78Qxi7yt6WqycuUTkPNqfd4osFgXLtDaDFgC8TGLTzUJWSZN", + "tick": "156" + }, + { + "state": "srs12YeRf1kLpwGy41jk263uNgs7qai2m1y7XGeBancyn6NPShdAac", + "tick": "169" + }, + { + "state": "srs12ybMDhWm9Nc6nRuir2fjDXjDc55zpEttHvLihc3Uj2WnEf4FA9", + "tick": "182" + }, + { + "state": "srs13DimeJzN59Sxz36YD5XWVNg36DPwMrEBAa1MHAyqAw4MsNK3e8", + "tick": "195" + }, + { + "state": "srs11rLYvJZR3pFR7czgeyqXx9BAecKP2GX9Xob59W5VNuSPUacGtt", + "tick": "208" + }, + { + "state": "srs11in5mAETxNPfnpce9FDrcQZoe4gJtmFLHXYVs4qbn5G6SU7Zcd", + "tick": "221" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12MYeKGU7Z4FaTLv1zvVnM5LSyU4rxa8AYYcww2eFCZVKdMZuEb", + "tick": "247" + }, + { + "state": "srs137JBFZyQNJJM52n71pdejwufxfwQrQ4z41Xb2TZFi3kPxo9GVK", + "tick": "260" + }, + { + "state": "srs12EYym2XxLNcVELe52ayForgTHud15bZ4DvZPMMbkVtHfpamF96", + "tick": "273" + }, + { + "state": "srs12i9d5DFwE9mwBJ7dZ1CNBVpRkHgB5Jw3HkKzsQXFjDAjezdk3G", + "tick": "286" + }, + { + "state": "srs12vL82Rtjse9cbjRPKKm3D6CMcyCMJrnaKLAzFoksXZwtH485nS", + "tick": "299" + }, + { + "state": "srs11WShqggcBnBpSieSH5xKz2F6xKmWJpR2i7TEJpVwkhJzPPYdud", + "tick": "312" + }, + { + "state": "srs11xF2PURqwnLMV1euEAT4tAqxkQ8TXbuzX5Db9ecXzEmq4vdNVc", + "tick": "325" + }, + { + "state": "srs13Loomnt2mmeCnkeL2Aj8dCKDVHKyboHgYo1czxciX7cGTw6FBw", + "tick": "338" + }, + { + "state": "srs136CJnze7BAo2W7QfeXfTDCgPiJb1B96ZjRTwFBDPSEj4TxRAms", + "tick": "351" + }, + { + "state": "srs11mTsFKqAKVhxCpemyP7ZgRSxp6MEmsDg8TbQuFE9KR6JhLvMVt", + "tick": "364" + }, + { + "state": "srs1224yjiE2kaEwojELN5JxPqBWN1Tg2GexDyqSXR9nF8zcycdnLi", + "tick": "377" + }, + { + "state": "srs11UPJL2dsoKuoYTLaC4P4btBQpX64nAZKPP91cbcjB8EtooyxoX", + "tick": "390" + }, + { + "state": "srs11mzrfqsjbL2PqsFpMDwyF876tz4tLpVbSrZRq52kuyYJCMYCKh", + "tick": "403" + }, + { + "state": "srs12GENJ4uXAQmRdZJQuitRbD6LxNYLkKK4yysjwBLmV2mZJosroC", + "tick": "417" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "237", + "end_tick": "238", + "dissection": [ + { + "state": "srs12bo57GfkUkpNopgptNPbtz68dZfojHbyC6ubeJVgptm6vBVSns", + "tick": "237" + }, + { + "state": "srs132gM47wMyDBtD4LLHRLjJwTtThhVJZD41egGDbupcNC9C43N3K", + "tick": "238" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_ongoing).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_ongoing).out new file mode 100644 index 000000000000..21dd59570246 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (degraded_ongoing).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "417", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs11XB2HCGteKCrjd3RzTeJErbFbFQFbWtztckuCCTF6rgMjFxJDX", + "tick": "13" + }, + { + "state": "srs12VUVuf4HJpcGQJDzVcpb3aaFuAvjENSgV4nRztkmWBSxL5WHaF", + "tick": "26" + }, + { + "state": "srs12ZnLptmHevRWau257DcrcnM2eNnFo7bFbc2sv2foTD8ZKCXTZe", + "tick": "39" + }, + { + "state": "srs12xQANQN4eAkSsP8zmcYkPpAFK4UTpAU6TvoumjmBiYy6CkVYzC", + "tick": "52" + }, + { + "state": "srs12s3Cb9eyFoavFQUWAZNjSnSFi5HEnkYfHyapLB2P5u7eB2Dd4K", + "tick": "65" + }, + { + "state": "srs128dvNSvYvCSMJfddzr7PcbH2HVynAF4dxEwLvTeVVSejCCa3bE", + "tick": "78" + }, + { + "state": "srs12B5HfbEsm6JPLh8Mm7xrbwpz4A3YLw7r5fKkyqZjgmGns647jV", + "tick": "91" + }, + { + "state": "srs124dtumicoAkWyp3KDjdtix2bZUMmhK4E8eP3RQnJtpVWJ9gQit", + "tick": "104" + }, + { + "state": "srs121MBsHEQZF8ytUDwsP6bj4vVdhMgvD1ELph9vCQsCAj7umHK7m", + "tick": "117" + }, + { + "state": "srs13NVfKCCRucqkqBw1x84RTmf4haNGL6dPbQYzEgQ36EHJfhnC9j", + "tick": "130" + }, + { + "state": "srs11qS1sYhQJGb2ceCuRXAd4u3nyVwboRVK7Bwud73zhTXiR1rr3Z", + "tick": "143" + }, + { + "state": "srs12Q78Qxi7yt6WqycuUTkPNqfd4osFgXLtDaDFgC8TGLTzUJWSZN", + "tick": "156" + }, + { + "state": "srs12YeRf1kLpwGy41jk263uNgs7qai2m1y7XGeBancyn6NPShdAac", + "tick": "169" + }, + { + "state": "srs12ybMDhWm9Nc6nRuir2fjDXjDc55zpEttHvLihc3Uj2WnEf4FA9", + "tick": "182" + }, + { + "state": "srs13DimeJzN59Sxz36YD5XWVNg36DPwMrEBAa1MHAyqAw4MsNK3e8", + "tick": "195" + }, + { + "state": "srs11rLYvJZR3pFR7czgeyqXx9BAecKP2GX9Xob59W5VNuSPUacGtt", + "tick": "208" + }, + { + "state": "srs11in5mAETxNPfnpce9FDrcQZoe4gJtmFLHXYVs4qbn5G6SU7Zcd", + "tick": "221" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12MYeKGU7Z4FaTLv1zvVnM5LSyU4rxa8AYYcww2eFCZVKdMZuEb", + "tick": "247" + }, + { + "state": "srs137JBFZyQNJJM52n71pdejwufxfwQrQ4z41Xb2TZFi3kPxo9GVK", + "tick": "260" + }, + { + "state": "srs12EYym2XxLNcVELe52ayForgTHud15bZ4DvZPMMbkVtHfpamF96", + "tick": "273" + }, + { + "state": "srs12i9d5DFwE9mwBJ7dZ1CNBVpRkHgB5Jw3HkKzsQXFjDAjezdk3G", + "tick": "286" + }, + { + "state": "srs12vL82Rtjse9cbjRPKKm3D6CMcyCMJrnaKLAzFoksXZwtH485nS", + "tick": "299" + }, + { + "state": "srs11WShqggcBnBpSieSH5xKz2F6xKmWJpR2i7TEJpVwkhJzPPYdud", + "tick": "312" + }, + { + "state": "srs11xF2PURqwnLMV1euEAT4tAqxkQ8TXbuzX5Db9ecXzEmq4vdNVc", + "tick": "325" + }, + { + "state": "srs13Loomnt2mmeCnkeL2Aj8dCKDVHKyboHgYo1czxciX7cGTw6FBw", + "tick": "338" + }, + { + "state": "srs136CJnze7BAo2W7QfeXfTDCgPiJb1B96ZjRTwFBDPSEj4TxRAms", + "tick": "351" + }, + { + "state": "srs11mTsFKqAKVhxCpemyP7ZgRSxp6MEmsDg8TbQuFE9KR6JhLvMVt", + "tick": "364" + }, + { + "state": "srs1224yjiE2kaEwojELN5JxPqBWN1Tg2GexDyqSXR9nF8zcycdnLi", + "tick": "377" + }, + { + "state": "srs11UPJL2dsoKuoYTLaC4P4btBQpX64nAZKPP91cbcjB8EtooyxoX", + "tick": "390" + }, + { + "state": "srs11mzrfqsjbL2PqsFpMDwyF876tz4tLpVbSrZRq52kuyYJCMYCKh", + "tick": "403" + }, + { + "state": "srs12GENJ4uXAQmRdZJQuitRbD6LxNYLkKK4yysjwBLmV2mZJosroC", + "tick": "417" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "237", + "end_tick": "238", + "dissection": [ + { + "state": "srs12bo57GfkUkpNopgptNPbtz68dZfojHbyC6ubeJVgptm6vBVSns", + "tick": "237" + }, + { + "state": "srs132gM47wMyDBtD4LLHRLjJwTtThhVJZD41egGDbupcNC9C43N3K", + "tick": "238" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof).out new file mode 100644 index 000000000000..818f95186943 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof).out @@ -0,0 +1,156 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "633", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs136djDFuVnqYeyDr9UbyHP2SCqQbq8dnXZY6ePsS2aThtWDr2Ai", + "tick": "19" + }, + { + "state": "srs11sqLRJh2RwZdtg71dn5VddXExoYHQByQWYr7XsvnXojVXaLaRo", + "tick": "38" + }, + { + "state": "srs12qSwJBtkq9B4VcpcSQAigEVBw5gsLTLgWoZ3h8WQm5FU5vSxpy", + "tick": "57" + }, + { + "state": "srs12SbiEtcNeAPNX1YNC83Ysm2wUToTbP14m7nAR3NUcJKTprUGfV", + "tick": "76" + }, + { + "state": "srs11TLxQ6xy4HxoT4tonedSZ4nR3wS6nPEt9k4kJgCTpCbfwATfZU", + "tick": "95" + }, + { + "state": "srs13Cy8eZRTBm5QM6BXKRJ1NPQzNibT8UBUDLKedW5RG9ojyygEja", + "tick": "114" + }, + { + "state": "srs12gYytLqonfQQp3Q1wW5kPywFxgBmR6168L6bW9TUCTdP7rimpQ", + "tick": "133" + }, + { + "state": "srs129US7aZPgijAeWY81dXLGPrvfyY5PVbH5vMdG4dLmVcgNiTpSn", + "tick": "152" + }, + { + "state": "srs13CHzURWpekmoxepmLWivVNZqUEeUrztuGuWeswokZYrRnWRR6S", + "tick": "171" + }, + { + "state": "srs12BVfJAc9r5JRVSXcJFMGTBc6e7qGrdGUmrXfdN8QUiqkDQoSUC", + "tick": "190" + }, + { + "state": "srs12k9nfFw67eGmyTtaHMBSLjRaPMkJMjvKtK2ubcdVy63wkCoBhY", + "tick": "209" + }, + { + "state": "srs12DjAvkDmSo8FSMamgMHhWitZj4KVuNTCisiCYeJkycfn5pcjjE", + "tick": "228" + }, + { + "state": "srs12MYeKGU7Z4FaTLv1zvVnM5LSyU4rxa8AYYcww2eFCZVKdMZuEb", + "tick": "247" + }, + { + "state": "srs11vntikstjho8tvq7CSEGi8STaZ3EpuKQ6mtdnKX5ymMff9zdYE", + "tick": "266" + }, + { + "state": "srs135KBowyeD3NQCtEh4ufvja4JUVStxSCNWZcTGZ7J5YRy9Ci3Sv", + "tick": "285" + }, + { + "state": "srs12oGJ623voxVYotTwCVhs1X6PkNSie61VY41FtKcoUJ92Pzjkwc", + "tick": "304" + }, + { + "state": "srs12LkRiYqgvJLTHtQ16WAKfESd1M7szoq85baWTs7q773JCPJm2o", + "tick": "323" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12oTSNspRC6jYQBC6SBbbjLGvZdwzHGB3MpH9YauX5WnG1nR3rk", + "tick": "361" + }, + { + "state": "srs11yCYcjjygmBdQBHdVJiWTu4iPrK74PvXqqTPAuvDWnWRFdt8zR", + "tick": "380" + }, + { + "state": "srs12euFuDjku1Aht4aSrt9vu92pWNWYCG2WCPfj9Unnx6Sp1gCu1H", + "tick": "399" + }, + { + "state": "srs11YiQvUc9xWrqY75PHU134RYHVYqDvnPHWdCGkYEMyMMx7H6NiZ", + "tick": "418" + }, + { + "state": "srs12AMmCyw3wsxK28Cdg8WPhzdRe4W2V1u6z6MukY52XzMoiASAv8", + "tick": "437" + }, + { + "state": "srs11dsgEhcACoZfZFioGpSYX2mTZNdtmV2E6CZRM7Ctu3jPjvvVTR", + "tick": "456" + }, + { + "state": "srs11orZFWdbyT5nb3UWV8Gp76ZUq57aUXaXhQiLYLVD9qW8VVgijJ", + "tick": "475" + }, + { + "state": "srs12zM6jTWMXtgAyJgEt4uR7ZNv8b2zjNBBNy6t2k8EyEhJ31rhBV", + "tick": "494" + }, + { + "state": "srs11nZY6GFt1bDrgANFKSb5EfzWQ1tx4ioyWY1ZkSRhKRujXG7PhM", + "tick": "513" + }, + { + "state": "srs12yo5wkoFZjL6cHgPPMqzz2HZ5Y4ThYejfhB5QUqhAzrk7UJBGW", + "tick": "532" + }, + { + "state": "srs13DpzUuwPEBhHBxr2CfRcyycJZYxRTjWJ4GBy4HfzNiNxkjW1mS", + "tick": "551" + }, + { + "state": "srs11pWX2JdSoTB4vdvEBnZFhkKujFyYHFFtnbLUKhduJnriGYWbHM", + "tick": "570" + }, + { + "tick": "589" + }, + { + "tick": "633" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "118", + "end_tick": "119", + "dissection": [ + { + "state": "srs13C1SQJWwLbx5NEAwWhXZK4R3rkYSQDu23PE2BD6GogwPAJTvN6", + "tick": "118" + }, + { + "state": "srs12tb3f8f32fybaGsYXZRwsGz3zr3N97n9VyDpDkkbEGzEn12W4J", + "tick": "119" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_at_genesis).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_at_genesis).out new file mode 100644 index 000000000000..8cc709af826f --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_at_genesis).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "582", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12fH3qaJPnV1ffBy6CmCeWNbnrRTYnBAJmpKmSijG4qAr1nF5qq", + "tick": "18" + }, + { + "state": "srs12U5Qo3eYMXF21V2WSqECogLqvuQFzFj46V8gCV44jTt9JbfPAt", + "tick": "36" + }, + { + "state": "srs11ojK4N7Jd3Yp71thpTaria7vxTqLVvJ78bq7AzBUK1Lfq19iXx", + "tick": "54" + }, + { + "state": "srs12mBVd34mTSQtHaJhCS5xBAzP4adN9RCPM6QnMnFqKCCK8AWCKB", + "tick": "72" + }, + { + "state": "srs122h7n2D1zgiE4rHLmzeoDQV1RLRJ73ha32DDbU3d54U7zaZPXc", + "tick": "90" + }, + { + "state": "srs129Wp6b9eXF9gZweXmNWeBKYTbXUDkMZY2szYgmrNzEgqk2YpDV", + "tick": "108" + }, + { + "state": "srs125AF7aoft7puAeoxtUmP1aajfLJeUKJA57LNJusncWd6zKRJjK", + "tick": "126" + }, + { + "state": "srs12kzv8cSYFt4DMUacbK32CTdReQqPRBYwMRsrKK6btByT3hbTLY", + "tick": "144" + }, + { + "state": "srs12QvEgKbjbZZ3ANqPMrqiMi3mw3tTEcsWixXgAY7X2gHABBNQNZ", + "tick": "162" + }, + { + "state": "srs11g395YpbNK3ZJopvv6cc7Gcc8H4Lv2MNhaQsCqfV7LztCUBvV1", + "tick": "180" + }, + { + "state": "srs11xVcimxB4Gb8LuzVyVXqjaB9S6YVbw2uR7rqoZr1VStr4b7QZS", + "tick": "198" + }, + { + "state": "srs11x2S5HDRwueA6tCKhipwohi2pWntjTpruhF1gmUWw3bRYW6szf", + "tick": "216" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12kh4XcDdzKZ8Pc4T7QsXm36XUqVe4cxtWJ2BxHrHwENrqEL9Ay", + "tick": "252" + }, + { + "state": "srs11hjoicX5kycSCkvbxZ7LDWwdbsV2qWEXBDurY3Sf5zwS8tUL3a", + "tick": "270" + }, + { + "state": "srs11n9qrtzJPgMSFze3erzSzvB5EAm48kTnEC9oJJYqxV6vRApyK5", + "tick": "288" + }, + { + "state": "srs1336xiQkLT9knTk1fco58u9hxKNqdHS1YPUwxGKLT2MhPzEMC7N", + "tick": "306" + }, + { + "state": "srs12CfNGraungvWxhYVdXr26w2aS1Ei6Eo5XgzDLdqn4LRDdduqom", + "tick": "324" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12ekcYu6yArjgAGuJAg5cwq6zPvKxdk6KCmnBtGYy7JP6kEBFqb", + "tick": "360" + }, + { + "state": "srs12a3AthkZ1i6H2x4RrPXN49iUmCVBSBkteWQTgEyWzQhpCzpoZD", + "tick": "378" + }, + { + "state": "srs12EXB6ARrgEz3pi71R6nzxtQ4PMY8Azwy2DYmmTJRkne8d6rW42", + "tick": "396" + }, + { + "state": "srs11fDjhakCGzwrmM7bHy4RJp8aGUgSFRN57tDDL2LzhXvDukwEJ1", + "tick": "414" + }, + { + "state": "srs1397ahAZp3GHxcSuvgvSk3MrdNaosN2nhkx8kDwuh3GF2ruEWzB", + "tick": "432" + }, + { + "state": "srs12sZ9L8e4CVC86wfn8o5KwroqUxMdGyzkjdkaVC4BM3PCeu1foW", + "tick": "450" + }, + { + "state": "srs13Jw5EzkDA1kK1ysWBT7QoQdoBWPtWLxbcg7tzhqmoQpMAzPDyr", + "tick": "468" + }, + { + "state": "srs12TjQfFTgrKzckqg65A3FUJfErZ2Eu6SXj2tWDAsi8iRf5hTcR6", + "tick": "486" + }, + { + "state": "srs12qYpCJiJoTiro1gs1y1HJNVLYv9Dp72bKDqwick9speqAPonWg", + "tick": "504" + }, + { + "state": "srs12JqZ2LaeC5RSw5xiaKDnUyW3uoH1L7qLB29fTR6tX7UH5VeXjk", + "tick": "522" + }, + { + "state": "srs13JbbzvBhzL8gjxyUGBQfZ67i4gFbab3qVQYSJoMg9xgQuovNMB", + "tick": "540" + }, + { + "state": "srs12ZGKGftAktgHZThDcahUSdoRjn214kafcq5eNqcUjb3SesLeWd", + "tick": "558" + }, + { + "state": "srs11Z7LSVYF6rBXAsR8Y5LjiQNgjPNs2eLAyUp2jWCf5QDMcSHqa6", + "tick": "582" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12RDgQ8yqwC1a1uSQjYRKEAu6LBL728S4tbiS1dwpUrpMZjmHYr", + "tick": "1" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out new file mode 100644 index 000000000000..66d4986ceb7a --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_many_empty_leve.out @@ -0,0 +1,155 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "468", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs11mFhGYhmnUEDp8VKKAymfL1WnHPiji8TLfK4JFSzgmwgWLuQzW", + "tick": "14" + }, + { + "state": "srs12HJZywRKWJrUNgvMaMndHKhY4abXWG1B4JBMAfky3sT6rP7Bkp", + "tick": "28" + }, + { + "state": "srs124gdB2V3E6GRPs7DvAwQ5BXqpWYtEN53WKzzsWfRPFp44mkE7X", + "tick": "42" + }, + { + "state": "srs11VND254VD9QiMcfeLGHdfriC3gTes2Sc7oo7suxbkqBxPaLkMj", + "tick": "56" + }, + { + "state": "srs11pcERsT7kE3orPMT1QF1kaquL2CtmYxeHAzxwQHVJGUCREpXUF", + "tick": "70" + }, + { + "state": "srs11i7eW3JXLDUzNVdbLoqqyQyqpZZaM5MdctK1sNXgLwr35bwXEU", + "tick": "84" + }, + { + "state": "srs128ALFziWJfj3jLMXDDiaKURdGgdF8AjBi5XRuYRPd52hdbx59o", + "tick": "98" + }, + { + "state": "srs126vZs4PRgz7TU1gJeEhg8qh8SE8KibtBuQgDphM6kKFCawJMLv", + "tick": "112" + }, + { + "state": "srs11eT18ckw8GtyQnUbetuAtyAJv3x1pWoTX3zLn4c3pYcFPhUyyy", + "tick": "126" + }, + { + "state": "srs12jiYyqL18PFUcaySmdo2xPaYPmXzTzjXAmvp96tyM8vBP1Lfbx", + "tick": "140" + }, + { + "state": "srs12kjseLn7g46w3XzCnCJDpTAzpb7z1DrLFKityV2cdmM7YfXgMN", + "tick": "154" + }, + { + "state": "srs12RSxWwwJHSKBr5aNGYVo1Aqqio9zpwZ54aoqZyvUzfVJGNQ7Ym", + "tick": "168" + }, + { + "state": "srs11eYzEcJgHdSnCnjteqGL27TNZNMTobMB92Nvu8QszLnNbdk44D", + "tick": "182" + }, + { + "state": "srs12LdMAokn4yqa7qkvqiYVUhztu1j29ECzeMtYwKgxP1XwZyky2m", + "tick": "196" + }, + { + "state": "srs11rEpPUKDg8uf6nKGyrZ9QYi5kBkR76RBCUYE32yMocjXQ9kgKy", + "tick": "210" + }, + { + "state": "srs11m354vvdXuyZxgufEqFDpRRtZK8Pq14QMAteLsrf3q9jbN3oHA", + "tick": "224" + }, + { + "state": "srs11gPQehoutgdKUc2fUzYCGKCdptPzdxZwzUzvCC5Gw9TvfDg818", + "tick": "238" + }, + { + "state": "srs12VY7x7YN6GtfPCuobVt5sccYimAQctSBPEJq3agXvpzCAVhtK1", + "tick": "252" + }, + { + "state": "srs11b8zZz9hEyQBEASLAeY9iR3vzYu7kLUibwU9MzC4DkS6FnrT2o", + "tick": "266" + }, + { + "state": "srs12RMropdVKfjBXxg4aiKnnDToYyXz7RnKYD3xqigw89zeHaagr9", + "tick": "280" + }, + { + "state": "srs11UdJmsUyPdEWjEpsqEfB9K3y7CvE5Z8AneSXkzjJZpe3fj8B45", + "tick": "294" + }, + { + "state": "srs12bntDHvCKCE8QehACD4aWbsK1YnUwus1UBKgC7Q6VgVUvyqB1r", + "tick": "308" + }, + { + "state": "srs12ruYFSeGbRcrTXzyULe53z2V4xdwdyxGXR7Jak5CpowWfFrfn5", + "tick": "322" + }, + { + "state": "srs11qQ526RFb8tgYhQygykeHFMkE9x7sTMtcKYgUHCESaQwb7UQeE", + "tick": "336" + }, + { + "state": "srs138ouCunrGSVmwgWzyzKhvD9qyjabyg8p2NGpoug4fat7DeRi4u", + "tick": "350" + }, + { + "state": "srs11YfbH7v6KD47GUYSN1uaMG1yZRzMsUfyXSGD7PYE5gVjnApDSx", + "tick": "364" + }, + { + "state": "srs13EWg6JsxZNxzrizd3qmeee57JjkTpEejJSucmiZeyCRnCvNnj6", + "tick": "378" + }, + { + "state": "srs13KS7z9UPGhPPu5W1m3c4VSKNohcvZqzDDKUFDrfLNeyePTGzta", + "tick": "392" + }, + { + "state": "srs12HPqTYu6Vc62Dqza3mvwRPjiAb14UAoFnqdSMk4AbpraXYHSji", + "tick": "406" + }, + { + "tick": "420" + }, + { + "tick": "434" + }, + { + "tick": "468" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "185", + "end_tick": "186", + "dissection": [ + { + "state": "srs123kr9jNQ7o9Cmn2TNiMjmKXzvoPJMamWWbA6xXAKAjNDpBtLFZ", + "tick": "185" + }, + { + "state": "srs11bEYDo5u6UYf66E1iDYJqUennbQJKEfD7H4AnjbkgHbvFwmxho", + "tick": "186" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_one_empty_level.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_one_empty_level.out new file mode 100644 index 000000000000..a5f7e83a0460 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_one_empty_level.out @@ -0,0 +1,155 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "578", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs13EyKmH4zHcR2VRMvChXjY2btcGgtG7ePSiwbbUH44QquvpMmXF", + "tick": "18" + }, + { + "state": "srs11ZhDcMkzrgzaUwBCyqAi2bs7ELmEnuTsAQ8szypDBsSoya37pM", + "tick": "36" + }, + { + "state": "srs11ouJa8bg85gzQzKudVstJop7RZevo9yZ45KGKWbEP4yXvXm2K8", + "tick": "54" + }, + { + "state": "srs12k7TbQdeHEnRF7iqCkVykWN3NtxoA5nPtd1TVYetjQWHnJBde5", + "tick": "72" + }, + { + "state": "srs124DcbqAa9FaQwqf25JqLk16up5FTWoPg7twNP8m5XSHLkxj5w9", + "tick": "90" + }, + { + "state": "srs11jny6Gy1YmR829G2wT2xNxquQpfZ5BLCinxftSnMpq96Y6VSAc", + "tick": "108" + }, + { + "state": "srs1344L1N7aQDwzaQQzBuvcC8Ez2zeifprgEHp7no3oKcGBeQER5J", + "tick": "126" + }, + { + "state": "srs11q2MbbRy4RN9EueRYKkf2xasoYeQWQmbrrXxAuLQL8jhUBkou8", + "tick": "144" + }, + { + "state": "srs121dsCBLn83rzcrg8HGL8hkM7tcYdP5WRGtDrMC4MrkWZSn1TAj", + "tick": "162" + }, + { + "state": "srs11umVKAFsvm1Y8L8CneYRMuhYq79SX83WPWcX3G5QGjfBeCHEEv", + "tick": "180" + }, + { + "state": "srs11yCG69eQaUzS2GH6MZq9Nu9oyhH61EZEjHyEjwnD4yteAYhESK", + "tick": "198" + }, + { + "state": "srs11YRpTrAwHofaf7oq1Fc6c9Qcj5UBJaZyVwmem21hFWZPST6f7Y", + "tick": "216" + }, + { + "state": "srs11wQVXH2En7sjb3cwPiE7yWRseSu6te879VaMuWTdQ6pUCwQCad", + "tick": "234" + }, + { + "state": "srs12ivGrKkby8YraJYiMQbLSVUzwcFfbzq3hG8nKdjSYdvL4yC8sP", + "tick": "252" + }, + { + "state": "srs12AVXc6LZpJkHJsyWyLkyL7iRv3seua8aYYwH28Yh8LtAbeKmNZ", + "tick": "270" + }, + { + "state": "srs133HeMV81Y3FcNv87tXbZGzodcH8Vy8xvj2ppYT1QfjuF6ewP9W", + "tick": "288" + }, + { + "state": "srs134ZQWewgB3Yo7VYXj8BpfGN7prLuAkWjNKqE4mGNPjoLXzK7s8", + "tick": "306" + }, + { + "state": "srs11tLF4MK95vEkAUmPWtmSVKN8G6u4WLzb8sTqz5ewNipkxByAGG", + "tick": "324" + }, + { + "state": "srs12pTUXxCuKPAZHnfjLQj6Ar2PZKnPxR5zHeF1N7C3zG7kc6dsEF", + "tick": "342" + }, + { + "state": "srs13D76KsLu376MA3U39Di7sFFUgRLfQTyXEgfWMX8GF5T44AT4kv", + "tick": "360" + }, + { + "state": "srs133PUgBtNPiTFsn7cVhKjkt9PueNa3nnE7pDhcSsYS2rXABC34q", + "tick": "378" + }, + { + "state": "srs12mUGsaCLwLFhrjy3G1Nn2pgzuAjnHB4QmBLgmAh9XUdU8a4hXR", + "tick": "396" + }, + { + "state": "srs11rTadB7UA31wwXKn5Y6rnaWNds68J1zH3DndTXMUZUZv4QPRQr", + "tick": "414" + }, + { + "state": "srs13E4CczoA6w4jYjQG9ZLxA1YmMBRduErcYct9ufaaTNtvDAVdsT", + "tick": "432" + }, + { + "state": "srs11osncmJUZDEK9x8sruFGhf97BqMyqvZXfTRKmyLPqtXAbAffmp", + "tick": "450" + }, + { + "state": "srs13LssXmYaEiNsws25RYcbvmQrbLKeLnD7kFggMMXHJKX8RuH73J", + "tick": "468" + }, + { + "state": "srs1355rgVvZFKex1HGmdSrMtEU76rn8BfGd3zbm92F8TsDfrbSpyW", + "tick": "486" + }, + { + "state": "srs12CT52vFheynRu95kdrBPdeygb1SjeZ1v7GkYSXDkVWMhJVDnmP", + "tick": "504" + }, + { + "state": "srs11fzXLQRn2cNfZZXdy25NnktU5r63WM2cWS4Md9KvGUsHzm8owU", + "tick": "522" + }, + { + "tick": "540" + }, + { + "tick": "558" + }, + { + "tick": "578" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "121", + "end_tick": "122", + "dissection": [ + { + "state": "srs12N3r3dk2XnWkNyrhCGofixAuZQHE7a8zVsnrbACQCnxARsvUY1", + "tick": "121" + }, + { + "state": "srs12adb637iB9CP9wymJcqnhwwXtqEorZ33RWnLCGEg4LDFuqFfeY", + "tick": "122" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_with_new_conten.out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_with_new_conten.out new file mode 100644 index 000000000000..818f95186943 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (inbox_proof_with_new_conten.out @@ -0,0 +1,156 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "633", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs136djDFuVnqYeyDr9UbyHP2SCqQbq8dnXZY6ePsS2aThtWDr2Ai", + "tick": "19" + }, + { + "state": "srs11sqLRJh2RwZdtg71dn5VddXExoYHQByQWYr7XsvnXojVXaLaRo", + "tick": "38" + }, + { + "state": "srs12qSwJBtkq9B4VcpcSQAigEVBw5gsLTLgWoZ3h8WQm5FU5vSxpy", + "tick": "57" + }, + { + "state": "srs12SbiEtcNeAPNX1YNC83Ysm2wUToTbP14m7nAR3NUcJKTprUGfV", + "tick": "76" + }, + { + "state": "srs11TLxQ6xy4HxoT4tonedSZ4nR3wS6nPEt9k4kJgCTpCbfwATfZU", + "tick": "95" + }, + { + "state": "srs13Cy8eZRTBm5QM6BXKRJ1NPQzNibT8UBUDLKedW5RG9ojyygEja", + "tick": "114" + }, + { + "state": "srs12gYytLqonfQQp3Q1wW5kPywFxgBmR6168L6bW9TUCTdP7rimpQ", + "tick": "133" + }, + { + "state": "srs129US7aZPgijAeWY81dXLGPrvfyY5PVbH5vMdG4dLmVcgNiTpSn", + "tick": "152" + }, + { + "state": "srs13CHzURWpekmoxepmLWivVNZqUEeUrztuGuWeswokZYrRnWRR6S", + "tick": "171" + }, + { + "state": "srs12BVfJAc9r5JRVSXcJFMGTBc6e7qGrdGUmrXfdN8QUiqkDQoSUC", + "tick": "190" + }, + { + "state": "srs12k9nfFw67eGmyTtaHMBSLjRaPMkJMjvKtK2ubcdVy63wkCoBhY", + "tick": "209" + }, + { + "state": "srs12DjAvkDmSo8FSMamgMHhWitZj4KVuNTCisiCYeJkycfn5pcjjE", + "tick": "228" + }, + { + "state": "srs12MYeKGU7Z4FaTLv1zvVnM5LSyU4rxa8AYYcww2eFCZVKdMZuEb", + "tick": "247" + }, + { + "state": "srs11vntikstjho8tvq7CSEGi8STaZ3EpuKQ6mtdnKX5ymMff9zdYE", + "tick": "266" + }, + { + "state": "srs135KBowyeD3NQCtEh4ufvja4JUVStxSCNWZcTGZ7J5YRy9Ci3Sv", + "tick": "285" + }, + { + "state": "srs12oGJ623voxVYotTwCVhs1X6PkNSie61VY41FtKcoUJ92Pzjkwc", + "tick": "304" + }, + { + "state": "srs12LkRiYqgvJLTHtQ16WAKfESd1M7szoq85baWTs7q773JCPJm2o", + "tick": "323" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12oTSNspRC6jYQBC6SBbbjLGvZdwzHGB3MpH9YauX5WnG1nR3rk", + "tick": "361" + }, + { + "state": "srs11yCYcjjygmBdQBHdVJiWTu4iPrK74PvXqqTPAuvDWnWRFdt8zR", + "tick": "380" + }, + { + "state": "srs12euFuDjku1Aht4aSrt9vu92pWNWYCG2WCPfj9Unnx6Sp1gCu1H", + "tick": "399" + }, + { + "state": "srs11YiQvUc9xWrqY75PHU134RYHVYqDvnPHWdCGkYEMyMMx7H6NiZ", + "tick": "418" + }, + { + "state": "srs12AMmCyw3wsxK28Cdg8WPhzdRe4W2V1u6z6MukY52XzMoiASAv8", + "tick": "437" + }, + { + "state": "srs11dsgEhcACoZfZFioGpSYX2mTZNdtmV2E6CZRM7Ctu3jPjvvVTR", + "tick": "456" + }, + { + "state": "srs11orZFWdbyT5nb3UWV8Gp76ZUq57aUXaXhQiLYLVD9qW8VVgijJ", + "tick": "475" + }, + { + "state": "srs12zM6jTWMXtgAyJgEt4uR7ZNv8b2zjNBBNy6t2k8EyEhJ31rhBV", + "tick": "494" + }, + { + "state": "srs11nZY6GFt1bDrgANFKSb5EfzWQ1tx4ioyWY1ZkSRhKRujXG7PhM", + "tick": "513" + }, + { + "state": "srs12yo5wkoFZjL6cHgPPMqzz2HZ5Y4ThYejfhB5QUqhAzrk7UJBGW", + "tick": "532" + }, + { + "state": "srs13DpzUuwPEBhHBxr2CfRcyycJZYxRTjWJ4GBy4HfzNiNxkjW1mS", + "tick": "551" + }, + { + "state": "srs11pWX2JdSoTB4vdvEBnZFhkKujFyYHFFtnbLUKhduJnriGYWbHM", + "tick": "570" + }, + { + "tick": "589" + }, + { + "tick": "633" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "118", + "end_tick": "119", + "dissection": [ + { + "state": "srs13C1SQJWwLbx5NEAwWhXZK4R3rkYSQDu23PE2BD6GogwPAJTvN6", + "tick": "118" + }, + { + "state": "srs12tb3f8f32fybaGsYXZRwsGz3zr3N97n9VyDpDkkbEGzEn12W4J", + "tick": "119" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_0).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_0).out new file mode 100644 index 000000000000..5352b3a29b3c --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_0).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "582", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12fH3qaJPnV1ffBy6CmCeWNbnrRTYnBAJmpKmSijG4qAr1nF5qq", + "tick": "18" + }, + { + "state": "srs12U5Qo3eYMXF21V2WSqECogLqvuQFzFj46V8gCV44jTt9JbfPAt", + "tick": "36" + }, + { + "state": "srs11ojK4N7Jd3Yp71thpTaria7vxTqLVvJ78bq7AzBUK1Lfq19iXx", + "tick": "54" + }, + { + "state": "srs12mBVd34mTSQtHaJhCS5xBAzP4adN9RCPM6QnMnFqKCCK8AWCKB", + "tick": "72" + }, + { + "state": "srs122h7n2D1zgiE4rHLmzeoDQV1RLRJ73ha32DDbU3d54U7zaZPXc", + "tick": "90" + }, + { + "state": "srs129Wp6b9eXF9gZweXmNWeBKYTbXUDkMZY2szYgmrNzEgqk2YpDV", + "tick": "108" + }, + { + "state": "srs125AF7aoft7puAeoxtUmP1aajfLJeUKJA57LNJusncWd6zKRJjK", + "tick": "126" + }, + { + "state": "srs12kzv8cSYFt4DMUacbK32CTdReQqPRBYwMRsrKK6btByT3hbTLY", + "tick": "144" + }, + { + "state": "srs12QvEgKbjbZZ3ANqPMrqiMi3mw3tTEcsWixXgAY7X2gHABBNQNZ", + "tick": "162" + }, + { + "state": "srs11g395YpbNK3ZJopvv6cc7Gcc8H4Lv2MNhaQsCqfV7LztCUBvV1", + "tick": "180" + }, + { + "state": "srs11xVcimxB4Gb8LuzVyVXqjaB9S6YVbw2uR7rqoZr1VStr4b7QZS", + "tick": "198" + }, + { + "state": "srs11x2S5HDRwueA6tCKhipwohi2pWntjTpruhF1gmUWw3bRYW6szf", + "tick": "216" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12kh4XcDdzKZ8Pc4T7QsXm36XUqVe4cxtWJ2BxHrHwENrqEL9Ay", + "tick": "252" + }, + { + "state": "srs11hjoicX5kycSCkvbxZ7LDWwdbsV2qWEXBDurY3Sf5zwS8tUL3a", + "tick": "270" + }, + { + "state": "srs11n9qrtzJPgMSFze3erzSzvB5EAm48kTnEC9oJJYqxV6vRApyK5", + "tick": "288" + }, + { + "state": "srs1336xiQkLT9knTk1fco58u9hxKNqdHS1YPUwxGKLT2MhPzEMC7N", + "tick": "306" + }, + { + "state": "srs12CfNGraungvWxhYVdXr26w2aS1Ei6Eo5XgzDLdqn4LRDdduqom", + "tick": "324" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12ekcYu6yArjgAGuJAg5cwq6zPvKxdk6KCmnBtGYy7JP6kEBFqb", + "tick": "360" + }, + { + "state": "srs12a3AthkZ1i6H2x4RrPXN49iUmCVBSBkteWQTgEyWzQhpCzpoZD", + "tick": "378" + }, + { + "state": "srs12EXB6ARrgEz3pi71R6nzxtQ4PMY8Azwy2DYmmTJRkne8d6rW42", + "tick": "396" + }, + { + "state": "srs11fDjhakCGzwrmM7bHy4RJp8aGUgSFRN57tDDL2LzhXvDukwEJ1", + "tick": "414" + }, + { + "state": "srs1397ahAZp3GHxcSuvgvSk3MrdNaosN2nhkx8kDwuh3GF2ruEWzB", + "tick": "432" + }, + { + "state": "srs12sZ9L8e4CVC86wfn8o5KwroqUxMdGyzkjdkaVC4BM3PCeu1foW", + "tick": "450" + }, + { + "state": "srs13Jw5EzkDA1kK1ysWBT7QoQdoBWPtWLxbcg7tzhqmoQpMAzPDyr", + "tick": "468" + }, + { + "state": "srs12TjQfFTgrKzckqg65A3FUJfErZ2Eu6SXj2tWDAsi8iRf5hTcR6", + "tick": "486" + }, + { + "state": "srs12qYpCJiJoTiro1gs1y1HJNVLYv9Dp72bKDqwick9speqAPonWg", + "tick": "504" + }, + { + "state": "srs12JqZ2LaeC5RSw5xiaKDnUyW3uoH1L7qLB29fTR6tX7UH5VeXjk", + "tick": "522" + }, + { + "state": "srs13JbbzvBhzL8gjxyUGBQfZ67i4gFbab3qVQYSJoMg9xgQuovNMB", + "tick": "540" + }, + { + "state": "srs12ZGKGftAktgHZThDcahUSdoRjn214kafcq5eNqcUjb3SesLeWd", + "tick": "558" + }, + { + "state": "srs11Z7LSVYF6rBXAsR8Y5LjiQNgjPNs2eLAyUp2jWCf5QDMcSHqa6", + "tick": "582" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "121", + "end_tick": "122", + "dissection": [ + { + "state": "srs12gTMVH2Jm8MTRtBmtjCuVtQxsRdPKd6fmLgqUeizfdTCHpzb8V", + "tick": "121" + }, + { + "state": "srs12ziRy1mzsTCGdXRuzHERaB5gWs4nTByjVdGQ5chVQPucjfx7MA", + "tick": "122" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_1).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_1).out new file mode 100644 index 000000000000..75f71d6b4d1a --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_1).out @@ -0,0 +1,156 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "629", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs136djDFuVnqYeyDr9UbyHP2SCqQbq8dnXZY6ePsS2aThtWDr2Ai", + "tick": "19" + }, + { + "state": "srs11sqLRJh2RwZdtg71dn5VddXExoYHQByQWYr7XsvnXojVXaLaRo", + "tick": "38" + }, + { + "state": "srs12qSwJBtkq9B4VcpcSQAigEVBw5gsLTLgWoZ3h8WQm5FU5vSxpy", + "tick": "57" + }, + { + "state": "srs12SbiEtcNeAPNX1YNC83Ysm2wUToTbP14m7nAR3NUcJKTprUGfV", + "tick": "76" + }, + { + "state": "srs11TLxQ6xy4HxoT4tonedSZ4nR3wS6nPEt9k4kJgCTpCbfwATfZU", + "tick": "95" + }, + { + "state": "srs13Cy8eZRTBm5QM6BXKRJ1NPQzNibT8UBUDLKedW5RG9ojyygEja", + "tick": "114" + }, + { + "state": "srs12gYytLqonfQQp3Q1wW5kPywFxgBmR6168L6bW9TUCTdP7rimpQ", + "tick": "133" + }, + { + "state": "srs129US7aZPgijAeWY81dXLGPrvfyY5PVbH5vMdG4dLmVcgNiTpSn", + "tick": "152" + }, + { + "state": "srs13CHzURWpekmoxepmLWivVNZqUEeUrztuGuWeswokZYrRnWRR6S", + "tick": "171" + }, + { + "state": "srs12BVfJAc9r5JRVSXcJFMGTBc6e7qGrdGUmrXfdN8QUiqkDQoSUC", + "tick": "190" + }, + { + "state": "srs12k9nfFw67eGmyTtaHMBSLjRaPMkJMjvKtK2ubcdVy63wkCoBhY", + "tick": "209" + }, + { + "state": "srs12DjAvkDmSo8FSMamgMHhWitZj4KVuNTCisiCYeJkycfn5pcjjE", + "tick": "228" + }, + { + "state": "srs12MYeKGU7Z4FaTLv1zvVnM5LSyU4rxa8AYYcww2eFCZVKdMZuEb", + "tick": "247" + }, + { + "state": "srs11vntikstjho8tvq7CSEGi8STaZ3EpuKQ6mtdnKX5ymMff9zdYE", + "tick": "266" + }, + { + "state": "srs135KBowyeD3NQCtEh4ufvja4JUVStxSCNWZcTGZ7J5YRy9Ci3Sv", + "tick": "285" + }, + { + "state": "srs12oGJ623voxVYotTwCVhs1X6PkNSie61VY41FtKcoUJ92Pzjkwc", + "tick": "304" + }, + { + "state": "srs12LkRiYqgvJLTHtQ16WAKfESd1M7szoq85baWTs7q773JCPJm2o", + "tick": "323" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12oTSNspRC6jYQBC6SBbbjLGvZdwzHGB3MpH9YauX5WnG1nR3rk", + "tick": "361" + }, + { + "state": "srs11yCYcjjygmBdQBHdVJiWTu4iPrK74PvXqqTPAuvDWnWRFdt8zR", + "tick": "380" + }, + { + "state": "srs12euFuDjku1Aht4aSrt9vu92pWNWYCG2WCPfj9Unnx6Sp1gCu1H", + "tick": "399" + }, + { + "state": "srs11YiQvUc9xWrqY75PHU134RYHVYqDvnPHWdCGkYEMyMMx7H6NiZ", + "tick": "418" + }, + { + "state": "srs12AMmCyw3wsxK28Cdg8WPhzdRe4W2V1u6z6MukY52XzMoiASAv8", + "tick": "437" + }, + { + "state": "srs11dsgEhcACoZfZFioGpSYX2mTZNdtmV2E6CZRM7Ctu3jPjvvVTR", + "tick": "456" + }, + { + "state": "srs11orZFWdbyT5nb3UWV8Gp76ZUq57aUXaXhQiLYLVD9qW8VVgijJ", + "tick": "475" + }, + { + "state": "srs12zM6jTWMXtgAyJgEt4uR7ZNv8b2zjNBBNy6t2k8EyEhJ31rhBV", + "tick": "494" + }, + { + "state": "srs11nZY6GFt1bDrgANFKSb5EfzWQ1tx4ioyWY1ZkSRhKRujXG7PhM", + "tick": "513" + }, + { + "state": "srs12yo5wkoFZjL6cHgPPMqzz2HZ5Y4ThYejfhB5QUqhAzrk7UJBGW", + "tick": "532" + }, + { + "state": "srs13DpzUuwPEBhHBxr2CfRcyycJZYxRTjWJ4GBy4HfzNiNxkjW1mS", + "tick": "551" + }, + { + "state": "srs11pWX2JdSoTB4vdvEBnZFhkKujFyYHFFtnbLUKhduJnriGYWbHM", + "tick": "570" + }, + { + "tick": "589" + }, + { + "tick": "629" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "236", + "end_tick": "237", + "dissection": [ + { + "state": "srs12hEz4xo8JgnSaaJQFGpa9JbASVeZUt5CTBtaRQZMwTawbn2H6X", + "tick": "236" + }, + { + "state": "srs12bo57GfkUkpNopgptNPbtz68dZfojHbyC6ubeJVgptm6vBVSns", + "tick": "237" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_2).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_2).out new file mode 100644 index 000000000000..21dd59570246 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_2).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "417", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs11XB2HCGteKCrjd3RzTeJErbFbFQFbWtztckuCCTF6rgMjFxJDX", + "tick": "13" + }, + { + "state": "srs12VUVuf4HJpcGQJDzVcpb3aaFuAvjENSgV4nRztkmWBSxL5WHaF", + "tick": "26" + }, + { + "state": "srs12ZnLptmHevRWau257DcrcnM2eNnFo7bFbc2sv2foTD8ZKCXTZe", + "tick": "39" + }, + { + "state": "srs12xQANQN4eAkSsP8zmcYkPpAFK4UTpAU6TvoumjmBiYy6CkVYzC", + "tick": "52" + }, + { + "state": "srs12s3Cb9eyFoavFQUWAZNjSnSFi5HEnkYfHyapLB2P5u7eB2Dd4K", + "tick": "65" + }, + { + "state": "srs128dvNSvYvCSMJfddzr7PcbH2HVynAF4dxEwLvTeVVSejCCa3bE", + "tick": "78" + }, + { + "state": "srs12B5HfbEsm6JPLh8Mm7xrbwpz4A3YLw7r5fKkyqZjgmGns647jV", + "tick": "91" + }, + { + "state": "srs124dtumicoAkWyp3KDjdtix2bZUMmhK4E8eP3RQnJtpVWJ9gQit", + "tick": "104" + }, + { + "state": "srs121MBsHEQZF8ytUDwsP6bj4vVdhMgvD1ELph9vCQsCAj7umHK7m", + "tick": "117" + }, + { + "state": "srs13NVfKCCRucqkqBw1x84RTmf4haNGL6dPbQYzEgQ36EHJfhnC9j", + "tick": "130" + }, + { + "state": "srs11qS1sYhQJGb2ceCuRXAd4u3nyVwboRVK7Bwud73zhTXiR1rr3Z", + "tick": "143" + }, + { + "state": "srs12Q78Qxi7yt6WqycuUTkPNqfd4osFgXLtDaDFgC8TGLTzUJWSZN", + "tick": "156" + }, + { + "state": "srs12YeRf1kLpwGy41jk263uNgs7qai2m1y7XGeBancyn6NPShdAac", + "tick": "169" + }, + { + "state": "srs12ybMDhWm9Nc6nRuir2fjDXjDc55zpEttHvLihc3Uj2WnEf4FA9", + "tick": "182" + }, + { + "state": "srs13DimeJzN59Sxz36YD5XWVNg36DPwMrEBAa1MHAyqAw4MsNK3e8", + "tick": "195" + }, + { + "state": "srs11rLYvJZR3pFR7czgeyqXx9BAecKP2GX9Xob59W5VNuSPUacGtt", + "tick": "208" + }, + { + "state": "srs11in5mAETxNPfnpce9FDrcQZoe4gJtmFLHXYVs4qbn5G6SU7Zcd", + "tick": "221" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12MYeKGU7Z4FaTLv1zvVnM5LSyU4rxa8AYYcww2eFCZVKdMZuEb", + "tick": "247" + }, + { + "state": "srs137JBFZyQNJJM52n71pdejwufxfwQrQ4z41Xb2TZFi3kPxo9GVK", + "tick": "260" + }, + { + "state": "srs12EYym2XxLNcVELe52ayForgTHud15bZ4DvZPMMbkVtHfpamF96", + "tick": "273" + }, + { + "state": "srs12i9d5DFwE9mwBJ7dZ1CNBVpRkHgB5Jw3HkKzsQXFjDAjezdk3G", + "tick": "286" + }, + { + "state": "srs12vL82Rtjse9cbjRPKKm3D6CMcyCMJrnaKLAzFoksXZwtH485nS", + "tick": "299" + }, + { + "state": "srs11WShqggcBnBpSieSH5xKz2F6xKmWJpR2i7TEJpVwkhJzPPYdud", + "tick": "312" + }, + { + "state": "srs11xF2PURqwnLMV1euEAT4tAqxkQ8TXbuzX5Db9ecXzEmq4vdNVc", + "tick": "325" + }, + { + "state": "srs13Loomnt2mmeCnkeL2Aj8dCKDVHKyboHgYo1czxciX7cGTw6FBw", + "tick": "338" + }, + { + "state": "srs136CJnze7BAo2W7QfeXfTDCgPiJb1B96ZjRTwFBDPSEj4TxRAms", + "tick": "351" + }, + { + "state": "srs11mTsFKqAKVhxCpemyP7ZgRSxp6MEmsDg8TbQuFE9KR6JhLvMVt", + "tick": "364" + }, + { + "state": "srs1224yjiE2kaEwojELN5JxPqBWN1Tg2GexDyqSXR9nF8zcycdnLi", + "tick": "377" + }, + { + "state": "srs11UPJL2dsoKuoYTLaC4P4btBQpX64nAZKPP91cbcjB8EtooyxoX", + "tick": "390" + }, + { + "state": "srs11mzrfqsjbL2PqsFpMDwyF876tz4tLpVbSrZRq52kuyYJCMYCKh", + "tick": "403" + }, + { + "state": "srs12GENJ4uXAQmRdZJQuitRbD6LxNYLkKK4yysjwBLmV2mZJosroC", + "tick": "417" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "237", + "end_tick": "238", + "dissection": [ + { + "state": "srs12bo57GfkUkpNopgptNPbtz68dZfojHbyC6ubeJVgptm6vBVSns", + "tick": "237" + }, + { + "state": "srs132gM47wMyDBtD4LLHRLjJwTtThhVJZD41egGDbupcNC9C43N3K", + "tick": "238" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_3).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_3).out new file mode 100644 index 000000000000..ab7d995e3c02 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_3).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "417", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs11XB2HCGteKCrjd3RzTeJErbFbFQFbWtztckuCCTF6rgMjFxJDX", + "tick": "13" + }, + { + "state": "srs12VUVuf4HJpcGQJDzVcpb3aaFuAvjENSgV4nRztkmWBSxL5WHaF", + "tick": "26" + }, + { + "state": "srs12ZnLptmHevRWau257DcrcnM2eNnFo7bFbc2sv2foTD8ZKCXTZe", + "tick": "39" + }, + { + "state": "srs12xQANQN4eAkSsP8zmcYkPpAFK4UTpAU6TvoumjmBiYy6CkVYzC", + "tick": "52" + }, + { + "state": "srs12s3Cb9eyFoavFQUWAZNjSnSFi5HEnkYfHyapLB2P5u7eB2Dd4K", + "tick": "65" + }, + { + "state": "srs128dvNSvYvCSMJfddzr7PcbH2HVynAF4dxEwLvTeVVSejCCa3bE", + "tick": "78" + }, + { + "state": "srs12B5HfbEsm6JPLh8Mm7xrbwpz4A3YLw7r5fKkyqZjgmGns647jV", + "tick": "91" + }, + { + "state": "srs124dtumicoAkWyp3KDjdtix2bZUMmhK4E8eP3RQnJtpVWJ9gQit", + "tick": "104" + }, + { + "state": "srs121MBsHEQZF8ytUDwsP6bj4vVdhMgvD1ELph9vCQsCAj7umHK7m", + "tick": "117" + }, + { + "state": "srs11xQXKBqDraMGaxd2KJcawk1FouRsPyKANyf3QGNUeScS7NJahG", + "tick": "130" + }, + { + "state": "srs11cndqBbKjH7Xmsjvhaow4LVt8ibXsG58AJmLjmMQejtwwKFfhW", + "tick": "143" + }, + { + "state": "srs12S2b3SUbzSDJvzDmoygzjJ5zBuHprmNqeiYGPam8CFk4v1Ghz1", + "tick": "156" + }, + { + "state": "srs13LwAVsaLGot8CXwdQCoZZCSJd5caDqY5cvAcG1Gg5wgE4vjj6k", + "tick": "169" + }, + { + "state": "srs129XpNKeM5bAwjT7smpJd4K7dqGN1pcHWk8n4LfDY86a9u85HWr", + "tick": "182" + }, + { + "state": "srs11moWhUJU4ANmfg26qh91hUdGPm5pMc8BTAQo4hybNF71FfiVfb", + "tick": "195" + }, + { + "state": "srs121GoPbVJJKJwngTEnkVTzEVsrTuS856NYwA2YjVWmjjgDA1U9Y", + "tick": "208" + }, + { + "state": "srs12faQL2Xt2m6fzH3d6AjVwgnSze1GNJv3S1tncKr7EpBqTvfJU2", + "tick": "221" + }, + { + "state": "srs12eZrvFpE7j8A3xXJu15EJ8VFyq69bVUGp1DsbKgGrsAZARDNqB", + "tick": "234" + }, + { + "state": "srs12jmJnW9fa73wBYAQceaMmujABFWLURi8CiVM1xnBf8uykSRG7H", + "tick": "247" + }, + { + "state": "srs12QSMPk5F5rCzxPg5nVBS1vvUsspVxvtuX5t1st6d1JfaozdPzN", + "tick": "260" + }, + { + "state": "srs122mV7vNce5JFQpwix4XSBZefeEXGg54BGJxexqw3UzVE4Brsnb", + "tick": "273" + }, + { + "state": "srs11dxSMagQkdfkwMHaqZuswLzJG8SE1MfDw8a5gqAMsCS5ACVbLA", + "tick": "286" + }, + { + "state": "srs12neAD3iYrggK49kju4z8AZVoT1bLGzSRhj1jQngU6fnMtNieNn", + "tick": "299" + }, + { + "state": "srs12xM3ZTkkgYAhhuRV5qFW9Kyf9ELSy45GyQKUCwSKj9Wijvb5pL", + "tick": "312" + }, + { + "state": "srs11rs9hwHdT1p5FEkW21PnVzDPE9Sue3z6Au34r4LDdDfmikoAmy", + "tick": "325" + }, + { + "state": "srs12sT431BouvRHfhRuJpsi1cPF74TUiEPTixMecxgK7tmjEL15dq", + "tick": "338" + }, + { + "state": "srs13DAT2ZZrJ995TDj88ThE3TMrfQTBizHGMiJDeTuBNuttRC6LeF", + "tick": "351" + }, + { + "state": "srs12fPSMpTt3k3FucTppe77oF5j5Kk8TiPiuAppzj9zv8NMz7ZKZz", + "tick": "364" + }, + { + "state": "srs12p6Ze96RAE9QjukEQ2smiajtHfjRBb7VnZAPLCt7yNoi2y8hBX", + "tick": "377" + }, + { + "state": "srs12M2fwC2tPUA7ExgsrwhRh3w9UvAZspgo6KkewqDHe17m62Fx8G", + "tick": "390" + }, + { + "state": "srs12QHYT16yvsvTHKKrKpJBCUQfxXy2hKYatoNsCCwpBq4YwPpeEi", + "tick": "403" + }, + { + "state": "srs12EBKTPBis6K4XgSZGAjFcnFjQ33dycG7WFvHAhEYxYJMqamnKk", + "tick": "417" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "243", + "end_tick": "244", + "dissection": [ + { + "state": "srs11pZwAag5f2fQLx99SqjwqN7172c44C2ToUadFEHh4hzhkrA8gF", + "tick": "243" + }, + { + "state": "srs12W4hj2ixtk9mM9Etb1AuYizhvkft1RPsaZvfnTdUt56BHYtrHP", + "tick": "244" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_at_genesis).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_at_genesis).out new file mode 100644 index 000000000000..8cc709af826f --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_at_genesis).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "582", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12fH3qaJPnV1ffBy6CmCeWNbnrRTYnBAJmpKmSijG4qAr1nF5qq", + "tick": "18" + }, + { + "state": "srs12U5Qo3eYMXF21V2WSqECogLqvuQFzFj46V8gCV44jTt9JbfPAt", + "tick": "36" + }, + { + "state": "srs11ojK4N7Jd3Yp71thpTaria7vxTqLVvJ78bq7AzBUK1Lfq19iXx", + "tick": "54" + }, + { + "state": "srs12mBVd34mTSQtHaJhCS5xBAzP4adN9RCPM6QnMnFqKCCK8AWCKB", + "tick": "72" + }, + { + "state": "srs122h7n2D1zgiE4rHLmzeoDQV1RLRJ73ha32DDbU3d54U7zaZPXc", + "tick": "90" + }, + { + "state": "srs129Wp6b9eXF9gZweXmNWeBKYTbXUDkMZY2szYgmrNzEgqk2YpDV", + "tick": "108" + }, + { + "state": "srs125AF7aoft7puAeoxtUmP1aajfLJeUKJA57LNJusncWd6zKRJjK", + "tick": "126" + }, + { + "state": "srs12kzv8cSYFt4DMUacbK32CTdReQqPRBYwMRsrKK6btByT3hbTLY", + "tick": "144" + }, + { + "state": "srs12QvEgKbjbZZ3ANqPMrqiMi3mw3tTEcsWixXgAY7X2gHABBNQNZ", + "tick": "162" + }, + { + "state": "srs11g395YpbNK3ZJopvv6cc7Gcc8H4Lv2MNhaQsCqfV7LztCUBvV1", + "tick": "180" + }, + { + "state": "srs11xVcimxB4Gb8LuzVyVXqjaB9S6YVbw2uR7rqoZr1VStr4b7QZS", + "tick": "198" + }, + { + "state": "srs11x2S5HDRwueA6tCKhipwohi2pWntjTpruhF1gmUWw3bRYW6szf", + "tick": "216" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12kh4XcDdzKZ8Pc4T7QsXm36XUqVe4cxtWJ2BxHrHwENrqEL9Ay", + "tick": "252" + }, + { + "state": "srs11hjoicX5kycSCkvbxZ7LDWwdbsV2qWEXBDurY3Sf5zwS8tUL3a", + "tick": "270" + }, + { + "state": "srs11n9qrtzJPgMSFze3erzSzvB5EAm48kTnEC9oJJYqxV6vRApyK5", + "tick": "288" + }, + { + "state": "srs1336xiQkLT9knTk1fco58u9hxKNqdHS1YPUwxGKLT2MhPzEMC7N", + "tick": "306" + }, + { + "state": "srs12CfNGraungvWxhYVdXr26w2aS1Ei6Eo5XgzDLdqn4LRDdduqom", + "tick": "324" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12ekcYu6yArjgAGuJAg5cwq6zPvKxdk6KCmnBtGYy7JP6kEBFqb", + "tick": "360" + }, + { + "state": "srs12a3AthkZ1i6H2x4RrPXN49iUmCVBSBkteWQTgEyWzQhpCzpoZD", + "tick": "378" + }, + { + "state": "srs12EXB6ARrgEz3pi71R6nzxtQ4PMY8Azwy2DYmmTJRkne8d6rW42", + "tick": "396" + }, + { + "state": "srs11fDjhakCGzwrmM7bHy4RJp8aGUgSFRN57tDDL2LzhXvDukwEJ1", + "tick": "414" + }, + { + "state": "srs1397ahAZp3GHxcSuvgvSk3MrdNaosN2nhkx8kDwuh3GF2ruEWzB", + "tick": "432" + }, + { + "state": "srs12sZ9L8e4CVC86wfn8o5KwroqUxMdGyzkjdkaVC4BM3PCeu1foW", + "tick": "450" + }, + { + "state": "srs13Jw5EzkDA1kK1ysWBT7QoQdoBWPtWLxbcg7tzhqmoQpMAzPDyr", + "tick": "468" + }, + { + "state": "srs12TjQfFTgrKzckqg65A3FUJfErZ2Eu6SXj2tWDAsi8iRf5hTcR6", + "tick": "486" + }, + { + "state": "srs12qYpCJiJoTiro1gs1y1HJNVLYv9Dp72bKDqwick9speqAPonWg", + "tick": "504" + }, + { + "state": "srs12JqZ2LaeC5RSw5xiaKDnUyW3uoH1L7qLB29fTR6tX7UH5VeXjk", + "tick": "522" + }, + { + "state": "srs13JbbzvBhzL8gjxyUGBQfZ67i4gFbab3qVQYSJoMg9xgQuovNMB", + "tick": "540" + }, + { + "state": "srs12ZGKGftAktgHZThDcahUSdoRjn214kafcq5eNqcUjb3SesLeWd", + "tick": "558" + }, + { + "state": "srs11Z7LSVYF6rBXAsR8Y5LjiQNgjPNs2eLAyUp2jWCf5QDMcSHqa6", + "tick": "582" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12RDgQ8yqwC1a1uSQjYRKEAu6LBL728S4tbiS1dwpUrpMZjmHYr", + "tick": "1" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_second_period).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_second_period).out new file mode 100644 index 000000000000..9549e08f3843 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (pvm_proof_second_period).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "470", + "dissection": [ + { + "state": "srs11Z7LSVYF6rBXAsR8Y5LjiQNgjPNs2eLAyUp2jWCf5QDMcSHqa6", + "tick": "0" + }, + { + "state": "srs11mzbaQWFusRK8rbJtacVn8WxamepxA4BoH9naZE8cCTuzb9BKE", + "tick": "14" + }, + { + "state": "srs12VqPjB9rfqNFqmpPG7cB3vtn4jfxsYGP7oG9VBMCXauwwf7bnr", + "tick": "28" + }, + { + "state": "srs11bWN7mUqA8uyLcNbnxKPaiNDwc41PCKiz3AbSoraWF62VGuHmU", + "tick": "42" + }, + { + "state": "srs13B8p9BJmB2Zz6pXMHE69xzBaEpFrSpqh4tginHwPGdMeJh6QU6", + "tick": "56" + }, + { + "state": "srs136RdoogwdcCNhKdWWhB4Ys95VNXLNdxGGhDJawLjnnw7PEZ6Yw", + "tick": "70" + }, + { + "state": "srs12b9sAAK6XmKtFqSeA8GQrb3covrgf1pR4PBjq6rcoLNjRuvAcm", + "tick": "84" + }, + { + "state": "srs133VwCBqTHxwdkAvztrk3H3SCzCEE1F8PDrZd5fX52p9Y6Vr7Qe", + "tick": "98" + }, + { + "state": "srs129dtcW2V8FLC25QSFCdGeS7g1XvMQuNE99MVJnqa43gJfLtq38", + "tick": "112" + }, + { + "state": "srs11Zo7zUQC6NF8sbKo5pddKU4AhdvGaNqto6crFE3ByoYm3VEdHe", + "tick": "126" + }, + { + "state": "srs131hDMypk565mvwZkt8Ljd7jb9BPRWG29MdJzu3s8VkMPPNuZ8r", + "tick": "140" + }, + { + "state": "srs12xzLvQsABjiWFTSZ828pmTznGsUL2VVJM3JYBr3B4v7g3Srxpc", + "tick": "154" + }, + { + "state": "srs13FCPMFoBB93ejJoL2GWdjCfdcfPSgJDvVFCY8fGAiD33nvp3F3", + "tick": "168" + }, + { + "state": "srs11vhjsGYSuuM1fbFTJH4z4C67YBW9NNxqwPiUcazokuzPkmGgFq", + "tick": "182" + }, + { + "state": "srs13D8cnxRYs6B39Ta7H9XA65T7i9xPoGxHqg13rQ2EBWWJAYBVVQ", + "tick": "196" + }, + { + "state": "srs11kQs7LDJ3ZMFL4NYZ3DJkfHG6xDnxvMRRjD3naPo2Xs6ZmigRF", + "tick": "210" + }, + { + "state": "srs12u6kEegZxHWhtRgSZ9HCLMoQeEK53wS9LcVgSXhYaprMUW3tBZ", + "tick": "224" + }, + { + "state": "srs12sfrzHVxk3tXXZytHVxAVwZzjwZ1ZT6ebwepMXysrhSTtTVWNi", + "tick": "238" + }, + { + "state": "srs12KcUYabDR7L4Rf4ZM5hov3dR9rbg4fHXUnrUXjHzRwBwpEEugY", + "tick": "252" + }, + { + "state": "srs13MNAo1FK7smhue4vC58fxrQBKSy6NXnj82Wqo8rjHwxyLe2QfV", + "tick": "266" + }, + { + "state": "srs11kE9hTfTZKfbsucZebkSsM3hk9w8RLkA5UrHMnpF1sEacv1Raj", + "tick": "280" + }, + { + "state": "srs127nTh6bthHQFFzGPePWRdKKU9HKzGWYTh77PrVTFqTk6r55UzE", + "tick": "294" + }, + { + "state": "srs12Pk3ewtevqFts13bpYkvysXw7SMggkoqqEGqESytgpve9qHQ29", + "tick": "308" + }, + { + "state": "srs12EoJD2NGAeViyru7oxMx1NFEFQjUBJ14k3YmWbrjf1GeqJHHSa", + "tick": "322" + }, + { + "state": "srs11YWBfiRncwtt7mjZNmjQJzAQZt89qkZrY9TmH78Jc3ZYqiCETL", + "tick": "336" + }, + { + "state": "srs125iNMYAZQq5mu2jSWaqMYowaRvk7TjUKH7Z6EEQZCqJtWBT6sh", + "tick": "350" + }, + { + "state": "srs12nBhLg2eFKoq3yvnV1qtwCpB5SRqyYi8YbeNoDopcRAhhZjujh", + "tick": "364" + }, + { + "state": "srs138b2LtYoLRpYp4JonVesFU28NccbdUbN3JdXWWtayEjLj4WYp9", + "tick": "378" + }, + { + "state": "srs12HGP7mhqmxF4LMmfF8uwSnwPcNphVrPw1oWJ5BDmpQuBHaeEBy", + "tick": "392" + }, + { + "state": "srs12BmKjVNdoTCyd7GQXjZMcsqYRbdFCRbEAiPhZNiMhmWcYmzV2S", + "tick": "406" + }, + { + "state": "srs12YvWguefwCazMmDoqTxdYSsPC9Sfbi5f2fJ8sAZVH38Q17ngno", + "tick": "420" + }, + { + "state": "srs11vzwocNM9VB24nv2f1Pv11FvWx1WbuRQZFNiKkVKckM2R22s5d", + "tick": "434" + }, + { + "state": "srs11zQFAbwSNjG9G9JG5zdYa9fsjSAaGEPeaYxxswKye9Fsk2tHCZ", + "tick": "470" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "119", + "end_tick": "120", + "dissection": [ + { + "state": "srs11ZgNf6wN1qpfYuv1jGgTaRcyZ2hAXtiXSjzx8zZ3YApMXzm72N", + "tick": "119" + }, + { + "state": "srs133GWsCMg74kubRZ2Gsm9Brca1GG8rMHr2jtBsgAXVdteRZmLNK", + "tick": "120" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (reset_honest_during_game).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (reset_honest_during_game).out new file mode 100644 index 000000000000..5352b3a29b3c --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (reset_honest_during_game).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "582", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12fH3qaJPnV1ffBy6CmCeWNbnrRTYnBAJmpKmSijG4qAr1nF5qq", + "tick": "18" + }, + { + "state": "srs12U5Qo3eYMXF21V2WSqECogLqvuQFzFj46V8gCV44jTt9JbfPAt", + "tick": "36" + }, + { + "state": "srs11ojK4N7Jd3Yp71thpTaria7vxTqLVvJ78bq7AzBUK1Lfq19iXx", + "tick": "54" + }, + { + "state": "srs12mBVd34mTSQtHaJhCS5xBAzP4adN9RCPM6QnMnFqKCCK8AWCKB", + "tick": "72" + }, + { + "state": "srs122h7n2D1zgiE4rHLmzeoDQV1RLRJ73ha32DDbU3d54U7zaZPXc", + "tick": "90" + }, + { + "state": "srs129Wp6b9eXF9gZweXmNWeBKYTbXUDkMZY2szYgmrNzEgqk2YpDV", + "tick": "108" + }, + { + "state": "srs125AF7aoft7puAeoxtUmP1aajfLJeUKJA57LNJusncWd6zKRJjK", + "tick": "126" + }, + { + "state": "srs12kzv8cSYFt4DMUacbK32CTdReQqPRBYwMRsrKK6btByT3hbTLY", + "tick": "144" + }, + { + "state": "srs12QvEgKbjbZZ3ANqPMrqiMi3mw3tTEcsWixXgAY7X2gHABBNQNZ", + "tick": "162" + }, + { + "state": "srs11g395YpbNK3ZJopvv6cc7Gcc8H4Lv2MNhaQsCqfV7LztCUBvV1", + "tick": "180" + }, + { + "state": "srs11xVcimxB4Gb8LuzVyVXqjaB9S6YVbw2uR7rqoZr1VStr4b7QZS", + "tick": "198" + }, + { + "state": "srs11x2S5HDRwueA6tCKhipwohi2pWntjTpruhF1gmUWw3bRYW6szf", + "tick": "216" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12kh4XcDdzKZ8Pc4T7QsXm36XUqVe4cxtWJ2BxHrHwENrqEL9Ay", + "tick": "252" + }, + { + "state": "srs11hjoicX5kycSCkvbxZ7LDWwdbsV2qWEXBDurY3Sf5zwS8tUL3a", + "tick": "270" + }, + { + "state": "srs11n9qrtzJPgMSFze3erzSzvB5EAm48kTnEC9oJJYqxV6vRApyK5", + "tick": "288" + }, + { + "state": "srs1336xiQkLT9knTk1fco58u9hxKNqdHS1YPUwxGKLT2MhPzEMC7N", + "tick": "306" + }, + { + "state": "srs12CfNGraungvWxhYVdXr26w2aS1Ei6Eo5XgzDLdqn4LRDdduqom", + "tick": "324" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12ekcYu6yArjgAGuJAg5cwq6zPvKxdk6KCmnBtGYy7JP6kEBFqb", + "tick": "360" + }, + { + "state": "srs12a3AthkZ1i6H2x4RrPXN49iUmCVBSBkteWQTgEyWzQhpCzpoZD", + "tick": "378" + }, + { + "state": "srs12EXB6ARrgEz3pi71R6nzxtQ4PMY8Azwy2DYmmTJRkne8d6rW42", + "tick": "396" + }, + { + "state": "srs11fDjhakCGzwrmM7bHy4RJp8aGUgSFRN57tDDL2LzhXvDukwEJ1", + "tick": "414" + }, + { + "state": "srs1397ahAZp3GHxcSuvgvSk3MrdNaosN2nhkx8kDwuh3GF2ruEWzB", + "tick": "432" + }, + { + "state": "srs12sZ9L8e4CVC86wfn8o5KwroqUxMdGyzkjdkaVC4BM3PCeu1foW", + "tick": "450" + }, + { + "state": "srs13Jw5EzkDA1kK1ysWBT7QoQdoBWPtWLxbcg7tzhqmoQpMAzPDyr", + "tick": "468" + }, + { + "state": "srs12TjQfFTgrKzckqg65A3FUJfErZ2Eu6SXj2tWDAsi8iRf5hTcR6", + "tick": "486" + }, + { + "state": "srs12qYpCJiJoTiro1gs1y1HJNVLYv9Dp72bKDqwick9speqAPonWg", + "tick": "504" + }, + { + "state": "srs12JqZ2LaeC5RSw5xiaKDnUyW3uoH1L7qLB29fTR6tX7UH5VeXjk", + "tick": "522" + }, + { + "state": "srs13JbbzvBhzL8gjxyUGBQfZ67i4gFbab3qVQYSJoMg9xgQuovNMB", + "tick": "540" + }, + { + "state": "srs12ZGKGftAktgHZThDcahUSdoRjn214kafcq5eNqcUjb3SesLeWd", + "tick": "558" + }, + { + "state": "srs11Z7LSVYF6rBXAsR8Y5LjiQNgjPNs2eLAyUp2jWCf5QDMcSHqa6", + "tick": "582" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "121", + "end_tick": "122", + "dissection": [ + { + "state": "srs12gTMVH2Jm8MTRtBmtjCuVtQxsRdPKd6fmLgqUeizfdTCHpzb8V", + "tick": "121" + }, + { + "state": "srs12ziRy1mzsTCGdXRuzHERaB5gWs4nTByjVdGQ5chVQPucjfx7MA", + "tick": "122" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (timeout).out b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (timeout).out new file mode 100644 index 000000000000..5352b3a29b3c --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- arith - refutation games winning strategies (timeout).out @@ -0,0 +1,158 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "582", + "dissection": [ + { + "state": "srs136U2KJweAXf7Excw61Zeu5R5L7mi2TCb1WKkowQJ6UdHJ2VZWS", + "tick": "0" + }, + { + "state": "srs12fH3qaJPnV1ffBy6CmCeWNbnrRTYnBAJmpKmSijG4qAr1nF5qq", + "tick": "18" + }, + { + "state": "srs12U5Qo3eYMXF21V2WSqECogLqvuQFzFj46V8gCV44jTt9JbfPAt", + "tick": "36" + }, + { + "state": "srs11ojK4N7Jd3Yp71thpTaria7vxTqLVvJ78bq7AzBUK1Lfq19iXx", + "tick": "54" + }, + { + "state": "srs12mBVd34mTSQtHaJhCS5xBAzP4adN9RCPM6QnMnFqKCCK8AWCKB", + "tick": "72" + }, + { + "state": "srs122h7n2D1zgiE4rHLmzeoDQV1RLRJ73ha32DDbU3d54U7zaZPXc", + "tick": "90" + }, + { + "state": "srs129Wp6b9eXF9gZweXmNWeBKYTbXUDkMZY2szYgmrNzEgqk2YpDV", + "tick": "108" + }, + { + "state": "srs125AF7aoft7puAeoxtUmP1aajfLJeUKJA57LNJusncWd6zKRJjK", + "tick": "126" + }, + { + "state": "srs12kzv8cSYFt4DMUacbK32CTdReQqPRBYwMRsrKK6btByT3hbTLY", + "tick": "144" + }, + { + "state": "srs12QvEgKbjbZZ3ANqPMrqiMi3mw3tTEcsWixXgAY7X2gHABBNQNZ", + "tick": "162" + }, + { + "state": "srs11g395YpbNK3ZJopvv6cc7Gcc8H4Lv2MNhaQsCqfV7LztCUBvV1", + "tick": "180" + }, + { + "state": "srs11xVcimxB4Gb8LuzVyVXqjaB9S6YVbw2uR7rqoZr1VStr4b7QZS", + "tick": "198" + }, + { + "state": "srs11x2S5HDRwueA6tCKhipwohi2pWntjTpruhF1gmUWw3bRYW6szf", + "tick": "216" + }, + { + "state": "srs11tG4LUtdPmQocurJWscsZqWGELkynfDYq9hYfP9Z3yv4KQ1B2w", + "tick": "234" + }, + { + "state": "srs12kh4XcDdzKZ8Pc4T7QsXm36XUqVe4cxtWJ2BxHrHwENrqEL9Ay", + "tick": "252" + }, + { + "state": "srs11hjoicX5kycSCkvbxZ7LDWwdbsV2qWEXBDurY3Sf5zwS8tUL3a", + "tick": "270" + }, + { + "state": "srs11n9qrtzJPgMSFze3erzSzvB5EAm48kTnEC9oJJYqxV6vRApyK5", + "tick": "288" + }, + { + "state": "srs1336xiQkLT9knTk1fco58u9hxKNqdHS1YPUwxGKLT2MhPzEMC7N", + "tick": "306" + }, + { + "state": "srs12CfNGraungvWxhYVdXr26w2aS1Ei6Eo5XgzDLdqn4LRDdduqom", + "tick": "324" + }, + { + "state": "srs12BwLvVrWQv531zELu8TrCymUS1Gm9Naafz3PX6miVBYcZycJjr", + "tick": "342" + }, + { + "state": "srs12ekcYu6yArjgAGuJAg5cwq6zPvKxdk6KCmnBtGYy7JP6kEBFqb", + "tick": "360" + }, + { + "state": "srs12a3AthkZ1i6H2x4RrPXN49iUmCVBSBkteWQTgEyWzQhpCzpoZD", + "tick": "378" + }, + { + "state": "srs12EXB6ARrgEz3pi71R6nzxtQ4PMY8Azwy2DYmmTJRkne8d6rW42", + "tick": "396" + }, + { + "state": "srs11fDjhakCGzwrmM7bHy4RJp8aGUgSFRN57tDDL2LzhXvDukwEJ1", + "tick": "414" + }, + { + "state": "srs1397ahAZp3GHxcSuvgvSk3MrdNaosN2nhkx8kDwuh3GF2ruEWzB", + "tick": "432" + }, + { + "state": "srs12sZ9L8e4CVC86wfn8o5KwroqUxMdGyzkjdkaVC4BM3PCeu1foW", + "tick": "450" + }, + { + "state": "srs13Jw5EzkDA1kK1ysWBT7QoQdoBWPtWLxbcg7tzhqmoQpMAzPDyr", + "tick": "468" + }, + { + "state": "srs12TjQfFTgrKzckqg65A3FUJfErZ2Eu6SXj2tWDAsi8iRf5hTcR6", + "tick": "486" + }, + { + "state": "srs12qYpCJiJoTiro1gs1y1HJNVLYv9Dp72bKDqwick9speqAPonWg", + "tick": "504" + }, + { + "state": "srs12JqZ2LaeC5RSw5xiaKDnUyW3uoH1L7qLB29fTR6tX7UH5VeXjk", + "tick": "522" + }, + { + "state": "srs13JbbzvBhzL8gjxyUGBQfZ67i4gFbab3qVQYSJoMg9xgQuovNMB", + "tick": "540" + }, + { + "state": "srs12ZGKGftAktgHZThDcahUSdoRjn214kafcq5eNqcUjb3SesLeWd", + "tick": "558" + }, + { + "state": "srs11Z7LSVYF6rBXAsR8Y5LjiQNgjPNs2eLAyUp2jWCf5QDMcSHqa6", + "tick": "582" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "121", + "end_tick": "122", + "dissection": [ + { + "state": "srs12gTMVH2Jm8MTRtBmtjCuVtQxsRdPKd6fmLgqUeizfdTCHpzb8V", + "tick": "121" + }, + { + "state": "srs12ziRy1mzsTCGdXRuzHERaB5gWs4nTByjVdGQ5chVQPucjfx7MA", + "tick": "122" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - RPC API should work and be stable.out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - RPC API should work and be stable.out new file mode 100644 index 000000000000..a38b307a1468 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - RPC API should work and be stable.out @@ -0,0 +1,275 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind wasm_2_0_0 of type string with kernel 0061736d0100000001280760037f7f7f017f60027f7f017f60057f7f7f7f7f017f60017f0060017f017f60027f7f0060000002610311736d6172745f726f6c6c75705f636f72650a726561645f696e707574000011736d6172745f726f6c6c75705f636f72650c77726974655f6f7574707574000111736d6172745f726f6c6c75705f636f72650b73746f72655f77726974650002030504030405060503010001071402036d656d02000a6b65726e656c5f72756e00060aa401042a01027f41fa002f0100210120002f010021022001200247044041e4004112410041e400410010021a0b0b0800200041c4006b0b5001057f41fe002d0000210341fc002f0100210220002d0000210420002f0100210520011004210620042003460440200041016a200141016b10011a0520052002460440200041076a200610011a0b0b0b1d01017f41dc0141840241901c100021004184022000100541840210030b0b38050041e4000b122f6b65726e656c2f656e762f7265626f6f740041f8000b0200010041fa000b0200020041fc000b0200000041fe000b0101 --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1944.973 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00085 + Expected counter: 1 + Gas limit: 2045 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00085 + payload fees(the block proposer) ....... +ꜩ0.00085 + Smart rollup origination: + Kind: wasm_2_0_0 + Parameter type: string + Kernel Blake2B hash: '24df9e3c520dd9a9c49b447766e8a604d31138c1aacb4a67532499c6a8b348cc' + This smart rollup origination was successfully applied + Consumed gas: 1944.940 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" +GET http://[HOST]:[PORT]/global/smart_rollup_address +200 OK +"[SMART_ROLLUP_HASH]" + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "312d31", + "312d32", + "312d33", + "312d34", + "312d35" +] +200 OK +["scmsg37MjxsWwLdnhRqRn8suc1oMvpa9riqGvazTg7giMNKDDU56Qfv","scmsg3X1MAjzt2B4r6gZnLf7mzoRf9UohkLw3Q2DTzLKctivKPYLXZ9","scmsg3prfVZhL8jFf5LSmxijjd96pKcz98ws6xe81qKagYcSg53e22N","scmsg2SY3VZWZ8y8491xbXvn8tQtHRCAq3zPJWQ7n4K6Rusw2YKVyNx","scmsg2zdjgY1tnuHMZqMavgPyc7qNj9MMvY4ywd38yauj3WfaiqDieE"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "322d31", + "322d32", + "322d33", + "322d34", + "322d35" +] +200 OK +["scmsg33G4qMwJ869CUzuYWpsdF9bnQ4ezN2YHyERN64j2Q4t9L99CnA","scmsg3ew4TRYot9RPWjagZdNGdSTD3wzUAKU5WFz6JosGBtEr1UT5o5","scmsg3Q6eecZLng9BK7maLP1DGqRpfbygCsQj8vPxc3USjpQxhCfEkn","scmsg2GAoC8FEUfHZfQAKotvjRMpmSknHRpn4w35Y1YWZ4uVZDYvzUL","scmsg2sqy4npoYQq8iWJWQQgrdG126y3Btxn8ZzVPav8JmptWnVowGz"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "332d31", + "332d32", + "332d33", + "332d34", + "332d35" +] +200 OK +["scmsg3EYkw2o4MC45NXUKZsEpzugW9sfumidS78TC8ygnJJznyAe9Yb","scmsg23CHWGTe3u8Utu3RpafBSEzvwnBKNRLxufPp8QindEWanu8UB6","scmsg3WnqzTRN8wvANvLKV4MouiTQZzq7X2G3CfKcomuQy4nKDFGRhX","scmsg3PVb7jXpE723XWdC1B8L34wVenMTi8r4b62Qja6owSMVo3h73C","scmsg2BZBgg1AFG7Zsar6DD1ZKPK36UakNZNj78npg6SUBoR26FpBdQ"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "342d31", + "342d32", + "342d33", + "342d34", + "342d35" +] +200 OK +["scmsg3BLN9sVbJN6BrDh8mu3yDYeVfTBnm83Ciom55sS3dKvvXMk1nR","scmsg2Nsbi6zbwQUTwpBVcTEhi7oVWxbuka1kiHMJ9BLiUg8QfzyLYM","scmsg3Ti1eX6WyPXKjy3NdkJnQdzi5RbkFJ8piWhEpDQwWn8VdNMuCK","scmsg3TMS4Q8jtUhr6YcgkMqwWAXKkXLJMhSRvJcMEgq61t8xftRMFv","scmsg2AWA1jULPBJb7usha9gJg62T5PdiW9Uz1HdHLhaYDRx4qRvLTL"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "352d31", + "352d32", + "352d33", + "352d34", + "352d35" +] +200 OK +["scmsg26t9x2GH9Pt9hiGLnSyNRALPzL8BYcTHik6PvU4vGDbUYM6JkV","scmsg3rtv5BpkWSR835sbwXJDBYZZW1ptXr8KKxprn4nJnhSacn6t1R","scmsg32QBihqJwKecppnv3o4MpRVYycR6puAHyhZhDVtewFQwmTdR3Z","scmsg3LQsvXBvj1qDWFRACbLuyAbZK6tHVTUeiYsPSU9KGxyf6ySxrY","scmsg3oXBwG2rAT3cjgDbRNyBnTirrkqTAeVMxMSJ5KUno8daWpY2rL"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "362d31", + "362d32", + "362d33", + "362d34", + "362d35" +] +200 OK +["scmsg2pUJoCjenPKAK3WnftrcnnKFf8RjTmoie2PS5Xa9jh2f6V4CpU","scmsg3M61S4suJDXn1yZyQrk9iy3WrDTXbPA6JHaeDWMjUJ4bhFTyAf","scmsg3SSJRKjcqvMFg2y6tuKWbikFx49kE5PfGg71uhxYdoMHBzutgU","scmsg3MPjHQ6m6BPJaGnAan8kCnadyCbn37DKAZa7LTbTtz3N36JgtW","scmsg2mUAHp9G2cJoqKwr4dpagFK6Wa4cNu7NGPXXB3zTfCpLmCP3Yr"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "372d31", + "372d32", + "372d33", + "372d34", + "372d35" +] +200 OK +["scmsg2VzSQUy8uj6yXYjwhLp2Qsmr77NixYmsXqqBGJpGsSxVBZHBPN","scmsg2p1iyQ4MHjNZrZhRmatcGXCzSr3Af7GKg6jawijWAe5ZpwFUMR","scmsg2xU6itfmj6XeuzYVqGza4Z95uAUXG44mnkM8uKkkdmbv8DyhS3","scmsg3YhsmhbfMXKmhsjGXej2ySwYFDYKQE1yUs7LcVkZ2ikaotWQKg","scmsg28neefD54Wsf46QgPtv22mKT32oNFv5ToU95DDsufcWFCZoovM"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "382d31", + "382d32", + "382d33", + "382d34", + "382d35" +] +200 OK +["scmsg3krb3ZX2JqPJkoBkrrFJcEtguu4sJDFS1XukN4PboYfxVRMZB8","scmsg2CXLxs8exJxS49Fi1bQFHhyy27fpTUwNZ8xhbuyd2uo4YmgWYL","scmsg2XJwuzAw5tZhfiTpUoDNSiM56W97YNEB4YyzGnrBcEgYpL9KMh","scmsg3RM54nLATBFqzCjvSwPybSbiiWJZey2ZiLbe1gjr9v9Vmoc9H3","scmsg2NpFWt1MhyDGhacEUpaeEheC8XWzNC3LaNaECXwzpi39QqPX14"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "392d31", + "392d32", + "392d33", + "392d34", + "392d35" +] +200 OK +["scmsg2nWa7VYthVQxL9antueegTTcyGzTqZzbFPVibWk8xzRGWvfdt8","scmsg3KfqCW3JtQAFWYUUKfaxUZ3zeR8t6233UU5frsUgZXjwyRaftR","scmsg2TJRQjXv5VYgrcVYM4upqfptRz4gLmDV1AMLcxqGJz2faoKfDK","scmsg2DBhcJVTm8JRWQHLWDXxiCi2PvUZzixqxkqyYupDZW2XU3cdvJ","scmsg2jKWtDbw5Jsdpc453XsgAVBKyYUzt3pKKsZtQNtvJvhPemp4WN"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31302d31", + "31302d32", + "31302d33", + "31302d34", + "31302d35" +] +200 OK +["scmsg3hFFdb5QTM1kbP7UmHviyd6VWfYaT9KTWDcTjE51BtRdjbCJjq","scmsg318GJr61qixBt6P4BxuUZ9zXZGct9fpknY7bky676r8esQjLrt","scmsg2twRwJCXXzvMYcD4Zu3zQSkHjhsDs9ZBczAi4Lvx7ogvJmeCGZ","scmsg3YFj784yYxTr4LbNfaLpHGpN5hKJgbBA8gUEJ4vief5KL8U5vS","scmsg2GY9Q5VTRSrjCPewduDXtPtZZ9hhMshPe3zUToBvFHTD9AhKkB"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31312d31", + "31312d32", + "31312d33", + "31312d34", + "31312d35" +] +200 OK +["scmsg2S7XcHeyAHTQy6cJ6pVgxYqdW7XTBz3PsiCx26gyp2EHfCUJTh","scmsg34AzeCpQWbx2MicoEqumBeh5PzkmeB3XkASNCeEn4u5AC2TQtC","scmsg23m7SEy65fobQJ22FS7dmnHqPe2pmpCaA5iVWA8KYm4ZU3CVfK","scmsg3KLGXHeokSBbJcfsrvRkoAjMt5Yi7nj67WFHh6nkW8Ce8Kd4yn","scmsg2Eaop6LYBSnKMQXqPWijq9fBa4nPw5ZLndHRCH97kumZqLT7pn"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31322d31", + "31322d32", + "31322d33", + "31322d34", + "31322d35" +] +200 OK +["scmsg3Rbcvi4zn7DSuXY8FHordHD4BMqXGi8XhrYAg9Z369qN2qPuPf","scmsg2JtmeQPL8JBY2MgEKx5f6XvH1bJjnqrjTpPVapmDaVBVcGHf8L","scmsg2xrhpVNNsUzYNF7LsNmeAbX2wJsZWE8Ub7DQRe8sToXxSjKR4T","scmsg3HMVWn75kiJ4Lr3KquJNQTkkFtwg9pmiKMythhUJ5h74Nznjd3","scmsg24y1317Sy46HnzTpvCLRe88LghadZ4eAjkb6EzvEsQVRhPbKzu"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31332d31", + "31332d32", + "31332d33", + "31332d34", + "31332d35" +] +200 OK +["scmsg2vjhNLAF3AeKmzkWbwkVELTGnQcEdsPeD6imGgeejsQta46LxA","scmsg2mQYGCav4HTBebHEeeVscAeMGL8d17eDZSCeTEBsukRyri51mZ","scmsg3CyDxp7PAws2HXGTyCeeamNDCs3acBnN7Jymj3GVW3WCS1GKEz","scmsg2Safqm8tXs1k51v1A7VMyALCDRn5DAgYCJ9kbUD38jwPqtob6B","scmsg28V9X7iiXCDZM4mFCHKsMxuvc8wNopLGkcnZwo14sSs4dW1E73"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31342d31", + "31342d32", + "31342d33", + "31342d34", + "31342d35" +] +200 OK +["scmsg2LeoW8SZzjCREGXpS2kwSfWCQBLf4M39gCQbuo7MPdcNUQgskZ","scmsg3KJEQRBNfv4DUb4LCA7EWAh9swowVibwH4Hx7CYn4mjFTEKNfC","scmsg2fWu16weRJCcgdvJzNtdWDNATvftgUVFfpgi5z3BDn9h2zE1Z2","scmsg29adqVUp1NnCAVSZVaKCVbrUdMth3C1yuUvBRZtmW9hsDtm8d1","scmsg2cDM9bscYDvXwkeB6h7RmN82wFgmL3wv5jJmwJukS9ju5zgKWA"] + +POST http://[HOST]:[PORT]/local/batcher/injection +Content-type: application/json +[ + "31352d31", + "31352d32", + "31352d33", + "31352d34", + "31352d35" +] +200 OK +["scmsg2DSE1zcsJXhEFsAFMo3qN7jV13LoxrG6qa1RaJtUFkPgJCBN5R","scmsg2StxsCnbG5vQmzdiY3F4M5bsrkb6Qh3CyrMod5thRVAbZHd38c","scmsg3fzM3qS4iPZ6qGHCNfupVUKiuYmrNe4k13uUj3ggrzX6rayaVA","scmsg3qHUB6rys7GmC8XGGKRDrcKX2veZGkT9SkScHyWqLUCjq9PLjx","scmsg3ZVMYBmAPwFfLDNXFDcBGzRChdFzLJ8tUMW46mGPGumZ6aq79q"] + +GET http://[HOST]:[PORT]/global/block/head/hash +200 OK +"[BLOCK_HASH]" + +GET http://[HOST]:[PORT]/global/block/5/hash +200 OK +"[BLOCK_HASH]" + +GET http://[HOST]:[PORT]/global/block/finalized/level +200 OK +16 + +GET http://[HOST]:[PORT]/global/block/head/num_messages +200 OK +"8" + +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/value?key=/kernel/boot.wasm +200 OK +"0061736d0100000001280760037f7f7f017f60027f7f017f60057f7f7f7f7f017f60017f0060017f017f60027f7f0060000002610311736d6172745f726f6c6c75705f636f72650a726561645f696e707574000011736d6172745f726f6c6c75705f636f72650c77726974655f6f7574707574000111736d6172745f726f6c6c75705f636f72650b73746f72655f77726974650002030504030405060503010001071402036d656d02000a6b65726e656c5f72756e00060aa401042a01027f41fa002f0100210120002f010021022001200247044041e4004112410041e400410010021a0b0b0800200041c4006b0b5001057f41fe002d0000210341fc002f0100210220002d0000210420002f0100210520011004210620042003460440200041016a200141016b10011a0520052002460440200041076a200610011a0b0b0b1d01017f41dc0141840241901c100021004184022000100541840210030b0b38050041e4000b122f6b65726e656c2f656e762f7265626f6f740041f8000b0200010041fa000b0200020041fc000b0200000041fe000b0101" + +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/value?key=/kernel/boot.wasm2 +200 OK +null + +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/value?key=/readonly/wasm_version +200 OK +"322e302e302d7234" + +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/length?key=/readonly/wasm_version +200 OK +"8" + +GET http://[HOST]:[PORT]/global/block/head/durable/wasm_2_0_0/subkeys?key=/readonly/kernel +200 OK +["boot.wasm","env"] + +GET http://[HOST]:[PORT]/global/block/head/status +200 OK +"Waiting for input message" + +GET http://[HOST]:[PORT]/global/block/head/ticks +200 OK +"450000000000000" + +GET http://[HOST]:[PORT]/global/block/head/state_hash +200 OK +"[SC_ROLLUP_PVM_STATE_HASH]" + +GET http://[HOST]:[PORT]/global/tezos_head +200 OK +"[BLOCK_HASH]" + +GET http://[HOST]:[PORT]/global/tezos_level +200 OK +18 + diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - origination of a SCORU executes without error.out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - origination of a SCORU executes without error.out new file mode 100644 index 000000000000..70c6e0d5c7b0 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - origination of a SCORU executes without error.out @@ -0,0 +1,35 @@ + +./octez-client --wait none originate smart rollup rollup from bootstrap1 of kind wasm_2_0_0 of type string with kernel 0061736d0100000001280760037f7f7f017f60027f7f017f60057f7f7f7f7f017f60017f0060017f017f60027f7f0060000002610311736d6172745f726f6c6c75705f636f72650a726561645f696e707574000011736d6172745f726f6c6c75705f636f72650c77726974655f6f7574707574000111736d6172745f726f6c6c75705f636f72650b73746f72655f77726974650002030504030405060503010001071402036d656d02000a6b65726e656c5f72756e00060aa401042a01027f41fa002f0100210120002f010021022001200247044041e4004112410041e400410010021a0b0b0800200041c4006b0b5001057f41fe002d0000210341fc002f0100210220002d0000210420002f0100210520011004210620042003460440200041016a200141016b10011a0520052002460440200041076a200610011a0b0b0b1d01017f41dc0141840241901c100021004184022000100541840210030b0b38050041e4000b122f6b65726e656c2f656e762f7265626f6f740041f8000b0200010041fa000b0200020041fc000b0200000041fe000b0101 --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1944.973 units (will add 100 for safety) +Estimated storage: 6552 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00085 + Expected counter: 1 + Gas limit: 2045 + Storage limit: 6572 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00085 + payload fees(the block proposer) ....... +ꜩ0.00085 + Smart rollup origination: + Kind: wasm_2_0_0 + Parameter type: string + Kernel Blake2B hash: '24df9e3c520dd9a9c49b447766e8a604d31138c1aacb4a67532499c6a8b348cc' + This smart rollup origination was successfully applied + Consumed gas: 1944.940 + Storage size: 6552 bytes + Address: [SMART_ROLLUP_HASH] + Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.638 + storage fees ........................... +ꜩ1.638 + +Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out new file mode 100644 index 000000000000..1d8fa6b419dc --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_0).out @@ -0,0 +1,501 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "100000000000000", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "50000000000000" + }, + { + "tick": "100000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1562500000000", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "48828125000" + }, + { + "tick": "97656250000" + }, + { + "tick": "146484375000" + }, + { + "tick": "195312500000" + }, + { + "tick": "244140625000" + }, + { + "tick": "292968750000" + }, + { + "tick": "341796875000" + }, + { + "tick": "390625000000" + }, + { + "tick": "439453125000" + }, + { + "tick": "488281250000" + }, + { + "tick": "537109375000" + }, + { + "tick": "585937500000" + }, + { + "tick": "634765625000" + }, + { + "tick": "683593750000" + }, + { + "tick": "732421875000" + }, + { + "tick": "781250000000" + }, + { + "tick": "830078125000" + }, + { + "tick": "878906250000" + }, + { + "tick": "927734375000" + }, + { + "tick": "976562500000" + }, + { + "tick": "1025390625000" + }, + { + "tick": "1074218750000" + }, + { + "tick": "1123046875000" + }, + { + "tick": "1171875000000" + }, + { + "tick": "1220703125000" + }, + { + "tick": "1269531250000" + }, + { + "tick": "1318359375000" + }, + { + "tick": "1367187500000" + }, + { + "tick": "1416015625000" + }, + { + "tick": "1464843750000" + }, + { + "tick": "1513671875000" + }, + { + "tick": "1562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1525878906", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "47683715" + }, + { + "tick": "95367430" + }, + { + "tick": "143051145" + }, + { + "tick": "190734860" + }, + { + "tick": "238418575" + }, + { + "tick": "286102290" + }, + { + "tick": "333786005" + }, + { + "tick": "381469720" + }, + { + "tick": "429153435" + }, + { + "tick": "476837150" + }, + { + "tick": "524520865" + }, + { + "tick": "572204580" + }, + { + "tick": "619888295" + }, + { + "tick": "667572010" + }, + { + "tick": "715255725" + }, + { + "tick": "762939440" + }, + { + "tick": "810623155" + }, + { + "tick": "858306870" + }, + { + "tick": "905990585" + }, + { + "tick": "953674300" + }, + { + "tick": "1001358015" + }, + { + "tick": "1049041730" + }, + { + "tick": "1096725445" + }, + { + "tick": "1144409160" + }, + { + "tick": "1192092875" + }, + { + "tick": "1239776590" + }, + { + "tick": "1287460305" + }, + { + "tick": "1335144020" + }, + { + "tick": "1382827735" + }, + { + "tick": "1430511450" + }, + { + "tick": "1478195165" + }, + { + "tick": "1525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1490116", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "46566" + }, + { + "tick": "93132" + }, + { + "tick": "139698" + }, + { + "tick": "186264" + }, + { + "tick": "232830" + }, + { + "tick": "279396" + }, + { + "tick": "325962" + }, + { + "tick": "372528" + }, + { + "tick": "419094" + }, + { + "tick": "465660" + }, + { + "tick": "512226" + }, + { + "tick": "558792" + }, + { + "tick": "605358" + }, + { + "tick": "651924" + }, + { + "tick": "698490" + }, + { + "tick": "745056" + }, + { + "tick": "791622" + }, + { + "tick": "838188" + }, + { + "tick": "884754" + }, + { + "tick": "931320" + }, + { + "tick": "977886" + }, + { + "tick": "1024452" + }, + { + "tick": "1071018" + }, + { + "tick": "1117584" + }, + { + "tick": "1164150" + }, + { + "tick": "1210716" + }, + { + "tick": "1257282" + }, + { + "tick": "1303848" + }, + { + "tick": "1350414" + }, + { + "tick": "1396980" + }, + { + "tick": "1443546" + }, + { + "tick": "1490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1455", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "45" + }, + { + "tick": "90" + }, + { + "tick": "135" + }, + { + "tick": "180" + }, + { + "tick": "225" + }, + { + "tick": "270" + }, + { + "tick": "315" + }, + { + "tick": "360" + }, + { + "tick": "405" + }, + { + "tick": "450" + }, + { + "tick": "495" + }, + { + "tick": "540" + }, + { + "tick": "585" + }, + { + "tick": "630" + }, + { + "tick": "675" + }, + { + "tick": "720" + }, + { + "tick": "765" + }, + { + "tick": "810" + }, + { + "tick": "855" + }, + { + "tick": "900" + }, + { + "tick": "945" + }, + { + "tick": "990" + }, + { + "tick": "1035" + }, + { + "tick": "1080" + }, + { + "tick": "1125" + }, + { + "tick": "1170" + }, + { + "tick": "1215" + }, + { + "tick": "1260" + }, + { + "tick": "1305" + }, + { + "tick": "1350" + }, + { + "tick": "1395" + }, + { + "tick": "1455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "13", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "1" + }, + { + "tick": "2" + }, + { + "tick": "3" + }, + { + "tick": "4" + }, + { + "tick": "5" + }, + { + "tick": "6" + }, + { + "tick": "7" + }, + { + "tick": "8" + }, + { + "tick": "9" + }, + { + "tick": "10" + }, + { + "tick": "11" + }, + { + "tick": "12" + }, + { + "tick": "13" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out new file mode 100644 index 000000000000..1d8fa6b419dc --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (inbox_proof_1).out @@ -0,0 +1,501 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "100000000000000", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "50000000000000" + }, + { + "tick": "100000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1562500000000", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "48828125000" + }, + { + "tick": "97656250000" + }, + { + "tick": "146484375000" + }, + { + "tick": "195312500000" + }, + { + "tick": "244140625000" + }, + { + "tick": "292968750000" + }, + { + "tick": "341796875000" + }, + { + "tick": "390625000000" + }, + { + "tick": "439453125000" + }, + { + "tick": "488281250000" + }, + { + "tick": "537109375000" + }, + { + "tick": "585937500000" + }, + { + "tick": "634765625000" + }, + { + "tick": "683593750000" + }, + { + "tick": "732421875000" + }, + { + "tick": "781250000000" + }, + { + "tick": "830078125000" + }, + { + "tick": "878906250000" + }, + { + "tick": "927734375000" + }, + { + "tick": "976562500000" + }, + { + "tick": "1025390625000" + }, + { + "tick": "1074218750000" + }, + { + "tick": "1123046875000" + }, + { + "tick": "1171875000000" + }, + { + "tick": "1220703125000" + }, + { + "tick": "1269531250000" + }, + { + "tick": "1318359375000" + }, + { + "tick": "1367187500000" + }, + { + "tick": "1416015625000" + }, + { + "tick": "1464843750000" + }, + { + "tick": "1513671875000" + }, + { + "tick": "1562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1525878906", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "47683715" + }, + { + "tick": "95367430" + }, + { + "tick": "143051145" + }, + { + "tick": "190734860" + }, + { + "tick": "238418575" + }, + { + "tick": "286102290" + }, + { + "tick": "333786005" + }, + { + "tick": "381469720" + }, + { + "tick": "429153435" + }, + { + "tick": "476837150" + }, + { + "tick": "524520865" + }, + { + "tick": "572204580" + }, + { + "tick": "619888295" + }, + { + "tick": "667572010" + }, + { + "tick": "715255725" + }, + { + "tick": "762939440" + }, + { + "tick": "810623155" + }, + { + "tick": "858306870" + }, + { + "tick": "905990585" + }, + { + "tick": "953674300" + }, + { + "tick": "1001358015" + }, + { + "tick": "1049041730" + }, + { + "tick": "1096725445" + }, + { + "tick": "1144409160" + }, + { + "tick": "1192092875" + }, + { + "tick": "1239776590" + }, + { + "tick": "1287460305" + }, + { + "tick": "1335144020" + }, + { + "tick": "1382827735" + }, + { + "tick": "1430511450" + }, + { + "tick": "1478195165" + }, + { + "tick": "1525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1490116", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "46566" + }, + { + "tick": "93132" + }, + { + "tick": "139698" + }, + { + "tick": "186264" + }, + { + "tick": "232830" + }, + { + "tick": "279396" + }, + { + "tick": "325962" + }, + { + "tick": "372528" + }, + { + "tick": "419094" + }, + { + "tick": "465660" + }, + { + "tick": "512226" + }, + { + "tick": "558792" + }, + { + "tick": "605358" + }, + { + "tick": "651924" + }, + { + "tick": "698490" + }, + { + "tick": "745056" + }, + { + "tick": "791622" + }, + { + "tick": "838188" + }, + { + "tick": "884754" + }, + { + "tick": "931320" + }, + { + "tick": "977886" + }, + { + "tick": "1024452" + }, + { + "tick": "1071018" + }, + { + "tick": "1117584" + }, + { + "tick": "1164150" + }, + { + "tick": "1210716" + }, + { + "tick": "1257282" + }, + { + "tick": "1303848" + }, + { + "tick": "1350414" + }, + { + "tick": "1396980" + }, + { + "tick": "1443546" + }, + { + "tick": "1490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "1455", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "45" + }, + { + "tick": "90" + }, + { + "tick": "135" + }, + { + "tick": "180" + }, + { + "tick": "225" + }, + { + "tick": "270" + }, + { + "tick": "315" + }, + { + "tick": "360" + }, + { + "tick": "405" + }, + { + "tick": "450" + }, + { + "tick": "495" + }, + { + "tick": "540" + }, + { + "tick": "585" + }, + { + "tick": "630" + }, + { + "tick": "675" + }, + { + "tick": "720" + }, + { + "tick": "765" + }, + { + "tick": "810" + }, + { + "tick": "855" + }, + { + "tick": "900" + }, + { + "tick": "945" + }, + { + "tick": "990" + }, + { + "tick": "1035" + }, + { + "tick": "1080" + }, + { + "tick": "1125" + }, + { + "tick": "1170" + }, + { + "tick": "1215" + }, + { + "tick": "1260" + }, + { + "tick": "1305" + }, + { + "tick": "1350" + }, + { + "tick": "1395" + }, + { + "tick": "1455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "0", + "end_tick": "13", + "dissection": [ + { + "tick": "0" + }, + { + "tick": "1" + }, + { + "tick": "2" + }, + { + "tick": "3" + }, + { + "tick": "4" + }, + { + "tick": "5" + }, + { + "tick": "6" + }, + { + "tick": "7" + }, + { + "tick": "8" + }, + { + "tick": "9" + }, + { + "tick": "10" + }, + { + "tick": "11" + }, + { + "tick": "12" + }, + { + "tick": "13" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out new file mode 100644 index 000000000000..886e587ad6c4 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_0).out @@ -0,0 +1,504 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "1050000000000000", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "950000000000000" + }, + { + "tick": "1000000000000000" + }, + { + "tick": "1050000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "901562500000000", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900048828125000" + }, + { + "tick": "900097656250000" + }, + { + "tick": "900146484375000" + }, + { + "tick": "900195312500000" + }, + { + "tick": "900244140625000" + }, + { + "tick": "900292968750000" + }, + { + "tick": "900341796875000" + }, + { + "tick": "900390625000000" + }, + { + "tick": "900439453125000" + }, + { + "tick": "900488281250000" + }, + { + "tick": "900537109375000" + }, + { + "tick": "900585937500000" + }, + { + "tick": "900634765625000" + }, + { + "tick": "900683593750000" + }, + { + "tick": "900732421875000" + }, + { + "tick": "900781250000000" + }, + { + "tick": "900830078125000" + }, + { + "tick": "900878906250000" + }, + { + "tick": "900927734375000" + }, + { + "tick": "900976562500000" + }, + { + "tick": "901025390625000" + }, + { + "tick": "901074218750000" + }, + { + "tick": "901123046875000" + }, + { + "tick": "901171875000000" + }, + { + "tick": "901220703125000" + }, + { + "tick": "901269531250000" + }, + { + "tick": "901318359375000" + }, + { + "tick": "901367187500000" + }, + { + "tick": "901416015625000" + }, + { + "tick": "901464843750000" + }, + { + "tick": "901513671875000" + }, + { + "tick": "901562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900001525878906", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000047683715" + }, + { + "tick": "900000095367430" + }, + { + "tick": "900000143051145" + }, + { + "tick": "900000190734860" + }, + { + "tick": "900000238418575" + }, + { + "tick": "900000286102290" + }, + { + "tick": "900000333786005" + }, + { + "tick": "900000381469720" + }, + { + "tick": "900000429153435" + }, + { + "tick": "900000476837150" + }, + { + "tick": "900000524520865" + }, + { + "tick": "900000572204580" + }, + { + "tick": "900000619888295" + }, + { + "tick": "900000667572010" + }, + { + "tick": "900000715255725" + }, + { + "tick": "900000762939440" + }, + { + "tick": "900000810623155" + }, + { + "tick": "900000858306870" + }, + { + "tick": "900000905990585" + }, + { + "tick": "900000953674300" + }, + { + "tick": "900001001358015" + }, + { + "tick": "900001049041730" + }, + { + "tick": "900001096725445" + }, + { + "tick": "900001144409160" + }, + { + "tick": "900001192092875" + }, + { + "tick": "900001239776590" + }, + { + "tick": "900001287460305" + }, + { + "tick": "900001335144020" + }, + { + "tick": "900001382827735" + }, + { + "tick": "900001430511450" + }, + { + "tick": "900001478195165" + }, + { + "tick": "900001525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900000001490116", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000000046566" + }, + { + "tick": "900000000093132" + }, + { + "tick": "900000000139698" + }, + { + "tick": "900000000186264" + }, + { + "tick": "900000000232830" + }, + { + "tick": "900000000279396" + }, + { + "tick": "900000000325962" + }, + { + "tick": "900000000372528" + }, + { + "tick": "900000000419094" + }, + { + "tick": "900000000465660" + }, + { + "tick": "900000000512226" + }, + { + "tick": "900000000558792" + }, + { + "tick": "900000000605358" + }, + { + "tick": "900000000651924" + }, + { + "tick": "900000000698490" + }, + { + "tick": "900000000745056" + }, + { + "tick": "900000000791622" + }, + { + "tick": "900000000838188" + }, + { + "tick": "900000000884754" + }, + { + "tick": "900000000931320" + }, + { + "tick": "900000000977886" + }, + { + "tick": "900000001024452" + }, + { + "tick": "900000001071018" + }, + { + "tick": "900000001117584" + }, + { + "tick": "900000001164150" + }, + { + "tick": "900000001210716" + }, + { + "tick": "900000001257282" + }, + { + "tick": "900000001303848" + }, + { + "tick": "900000001350414" + }, + { + "tick": "900000001396980" + }, + { + "tick": "900000001443546" + }, + { + "tick": "900000001490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900000000001455", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000000000045" + }, + { + "tick": "900000000000090" + }, + { + "tick": "900000000000135" + }, + { + "tick": "900000000000180" + }, + { + "tick": "900000000000225" + }, + { + "tick": "900000000000270" + }, + { + "tick": "900000000000315" + }, + { + "tick": "900000000000360" + }, + { + "tick": "900000000000405" + }, + { + "tick": "900000000000450" + }, + { + "tick": "900000000000495" + }, + { + "tick": "900000000000540" + }, + { + "tick": "900000000000585" + }, + { + "tick": "900000000000630" + }, + { + "tick": "900000000000675" + }, + { + "tick": "900000000000720" + }, + { + "tick": "900000000000765" + }, + { + "tick": "900000000000810" + }, + { + "tick": "900000000000855" + }, + { + "tick": "900000000000900" + }, + { + "tick": "900000000000945" + }, + { + "tick": "900000000000990" + }, + { + "tick": "900000000001035" + }, + { + "tick": "900000000001080" + }, + { + "tick": "900000000001125" + }, + { + "tick": "900000000001170" + }, + { + "tick": "900000000001215" + }, + { + "tick": "900000000001260" + }, + { + "tick": "900000000001305" + }, + { + "tick": "900000000001350" + }, + { + "tick": "900000000001395" + }, + { + "tick": "900000000001455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900000000000013", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000000000001" + }, + { + "tick": "900000000000002" + }, + { + "tick": "900000000000003" + }, + { + "tick": "900000000000004" + }, + { + "tick": "900000000000005" + }, + { + "tick": "900000000000006" + }, + { + "tick": "900000000000007" + }, + { + "tick": "900000000000008" + }, + { + "tick": "900000000000009" + }, + { + "tick": "900000000000010" + }, + { + "tick": "900000000000011" + }, + { + "tick": "900000000000012" + }, + { + "tick": "900000000000013" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out new file mode 100644 index 000000000000..26f068148582 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_1).out @@ -0,0 +1,504 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1950000000000000", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1850000000000000" + }, + { + "tick": "1900000000000000" + }, + { + "tick": "1950000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1801562500000000", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800048828125000" + }, + { + "tick": "1800097656250000" + }, + { + "tick": "1800146484375000" + }, + { + "tick": "1800195312500000" + }, + { + "tick": "1800244140625000" + }, + { + "tick": "1800292968750000" + }, + { + "tick": "1800341796875000" + }, + { + "tick": "1800390625000000" + }, + { + "tick": "1800439453125000" + }, + { + "tick": "1800488281250000" + }, + { + "tick": "1800537109375000" + }, + { + "tick": "1800585937500000" + }, + { + "tick": "1800634765625000" + }, + { + "tick": "1800683593750000" + }, + { + "tick": "1800732421875000" + }, + { + "tick": "1800781250000000" + }, + { + "tick": "1800830078125000" + }, + { + "tick": "1800878906250000" + }, + { + "tick": "1800927734375000" + }, + { + "tick": "1800976562500000" + }, + { + "tick": "1801025390625000" + }, + { + "tick": "1801074218750000" + }, + { + "tick": "1801123046875000" + }, + { + "tick": "1801171875000000" + }, + { + "tick": "1801220703125000" + }, + { + "tick": "1801269531250000" + }, + { + "tick": "1801318359375000" + }, + { + "tick": "1801367187500000" + }, + { + "tick": "1801416015625000" + }, + { + "tick": "1801464843750000" + }, + { + "tick": "1801513671875000" + }, + { + "tick": "1801562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800001525878906", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000047683715" + }, + { + "tick": "1800000095367430" + }, + { + "tick": "1800000143051145" + }, + { + "tick": "1800000190734860" + }, + { + "tick": "1800000238418575" + }, + { + "tick": "1800000286102290" + }, + { + "tick": "1800000333786005" + }, + { + "tick": "1800000381469720" + }, + { + "tick": "1800000429153435" + }, + { + "tick": "1800000476837150" + }, + { + "tick": "1800000524520865" + }, + { + "tick": "1800000572204580" + }, + { + "tick": "1800000619888295" + }, + { + "tick": "1800000667572010" + }, + { + "tick": "1800000715255725" + }, + { + "tick": "1800000762939440" + }, + { + "tick": "1800000810623155" + }, + { + "tick": "1800000858306870" + }, + { + "tick": "1800000905990585" + }, + { + "tick": "1800000953674300" + }, + { + "tick": "1800001001358015" + }, + { + "tick": "1800001049041730" + }, + { + "tick": "1800001096725445" + }, + { + "tick": "1800001144409160" + }, + { + "tick": "1800001192092875" + }, + { + "tick": "1800001239776590" + }, + { + "tick": "1800001287460305" + }, + { + "tick": "1800001335144020" + }, + { + "tick": "1800001382827735" + }, + { + "tick": "1800001430511450" + }, + { + "tick": "1800001478195165" + }, + { + "tick": "1800001525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000001490116", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000046566" + }, + { + "tick": "1800000000093132" + }, + { + "tick": "1800000000139698" + }, + { + "tick": "1800000000186264" + }, + { + "tick": "1800000000232830" + }, + { + "tick": "1800000000279396" + }, + { + "tick": "1800000000325962" + }, + { + "tick": "1800000000372528" + }, + { + "tick": "1800000000419094" + }, + { + "tick": "1800000000465660" + }, + { + "tick": "1800000000512226" + }, + { + "tick": "1800000000558792" + }, + { + "tick": "1800000000605358" + }, + { + "tick": "1800000000651924" + }, + { + "tick": "1800000000698490" + }, + { + "tick": "1800000000745056" + }, + { + "tick": "1800000000791622" + }, + { + "tick": "1800000000838188" + }, + { + "tick": "1800000000884754" + }, + { + "tick": "1800000000931320" + }, + { + "tick": "1800000000977886" + }, + { + "tick": "1800000001024452" + }, + { + "tick": "1800000001071018" + }, + { + "tick": "1800000001117584" + }, + { + "tick": "1800000001164150" + }, + { + "tick": "1800000001210716" + }, + { + "tick": "1800000001257282" + }, + { + "tick": "1800000001303848" + }, + { + "tick": "1800000001350414" + }, + { + "tick": "1800000001396980" + }, + { + "tick": "1800000001443546" + }, + { + "tick": "1800000001490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000000001455", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000000045" + }, + { + "tick": "1800000000000090" + }, + { + "tick": "1800000000000135" + }, + { + "tick": "1800000000000180" + }, + { + "tick": "1800000000000225" + }, + { + "tick": "1800000000000270" + }, + { + "tick": "1800000000000315" + }, + { + "tick": "1800000000000360" + }, + { + "tick": "1800000000000405" + }, + { + "tick": "1800000000000450" + }, + { + "tick": "1800000000000495" + }, + { + "tick": "1800000000000540" + }, + { + "tick": "1800000000000585" + }, + { + "tick": "1800000000000630" + }, + { + "tick": "1800000000000675" + }, + { + "tick": "1800000000000720" + }, + { + "tick": "1800000000000765" + }, + { + "tick": "1800000000000810" + }, + { + "tick": "1800000000000855" + }, + { + "tick": "1800000000000900" + }, + { + "tick": "1800000000000945" + }, + { + "tick": "1800000000000990" + }, + { + "tick": "1800000000001035" + }, + { + "tick": "1800000000001080" + }, + { + "tick": "1800000000001125" + }, + { + "tick": "1800000000001170" + }, + { + "tick": "1800000000001215" + }, + { + "tick": "1800000000001260" + }, + { + "tick": "1800000000001305" + }, + { + "tick": "1800000000001350" + }, + { + "tick": "1800000000001395" + }, + { + "tick": "1800000000001455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000000000013", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000000001" + }, + { + "tick": "1800000000000002" + }, + { + "tick": "1800000000000003" + }, + { + "tick": "1800000000000004" + }, + { + "tick": "1800000000000005" + }, + { + "tick": "1800000000000006" + }, + { + "tick": "1800000000000007" + }, + { + "tick": "1800000000000008" + }, + { + "tick": "1800000000000009" + }, + { + "tick": "1800000000000010" + }, + { + "tick": "1800000000000011" + }, + { + "tick": "1800000000000012" + }, + { + "tick": "1800000000000013" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out new file mode 100644 index 000000000000..26f068148582 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_2).out @@ -0,0 +1,504 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1950000000000000", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1850000000000000" + }, + { + "tick": "1900000000000000" + }, + { + "tick": "1950000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1801562500000000", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800048828125000" + }, + { + "tick": "1800097656250000" + }, + { + "tick": "1800146484375000" + }, + { + "tick": "1800195312500000" + }, + { + "tick": "1800244140625000" + }, + { + "tick": "1800292968750000" + }, + { + "tick": "1800341796875000" + }, + { + "tick": "1800390625000000" + }, + { + "tick": "1800439453125000" + }, + { + "tick": "1800488281250000" + }, + { + "tick": "1800537109375000" + }, + { + "tick": "1800585937500000" + }, + { + "tick": "1800634765625000" + }, + { + "tick": "1800683593750000" + }, + { + "tick": "1800732421875000" + }, + { + "tick": "1800781250000000" + }, + { + "tick": "1800830078125000" + }, + { + "tick": "1800878906250000" + }, + { + "tick": "1800927734375000" + }, + { + "tick": "1800976562500000" + }, + { + "tick": "1801025390625000" + }, + { + "tick": "1801074218750000" + }, + { + "tick": "1801123046875000" + }, + { + "tick": "1801171875000000" + }, + { + "tick": "1801220703125000" + }, + { + "tick": "1801269531250000" + }, + { + "tick": "1801318359375000" + }, + { + "tick": "1801367187500000" + }, + { + "tick": "1801416015625000" + }, + { + "tick": "1801464843750000" + }, + { + "tick": "1801513671875000" + }, + { + "tick": "1801562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800001525878906", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000047683715" + }, + { + "tick": "1800000095367430" + }, + { + "tick": "1800000143051145" + }, + { + "tick": "1800000190734860" + }, + { + "tick": "1800000238418575" + }, + { + "tick": "1800000286102290" + }, + { + "tick": "1800000333786005" + }, + { + "tick": "1800000381469720" + }, + { + "tick": "1800000429153435" + }, + { + "tick": "1800000476837150" + }, + { + "tick": "1800000524520865" + }, + { + "tick": "1800000572204580" + }, + { + "tick": "1800000619888295" + }, + { + "tick": "1800000667572010" + }, + { + "tick": "1800000715255725" + }, + { + "tick": "1800000762939440" + }, + { + "tick": "1800000810623155" + }, + { + "tick": "1800000858306870" + }, + { + "tick": "1800000905990585" + }, + { + "tick": "1800000953674300" + }, + { + "tick": "1800001001358015" + }, + { + "tick": "1800001049041730" + }, + { + "tick": "1800001096725445" + }, + { + "tick": "1800001144409160" + }, + { + "tick": "1800001192092875" + }, + { + "tick": "1800001239776590" + }, + { + "tick": "1800001287460305" + }, + { + "tick": "1800001335144020" + }, + { + "tick": "1800001382827735" + }, + { + "tick": "1800001430511450" + }, + { + "tick": "1800001478195165" + }, + { + "tick": "1800001525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000001490116", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000046566" + }, + { + "tick": "1800000000093132" + }, + { + "tick": "1800000000139698" + }, + { + "tick": "1800000000186264" + }, + { + "tick": "1800000000232830" + }, + { + "tick": "1800000000279396" + }, + { + "tick": "1800000000325962" + }, + { + "tick": "1800000000372528" + }, + { + "tick": "1800000000419094" + }, + { + "tick": "1800000000465660" + }, + { + "tick": "1800000000512226" + }, + { + "tick": "1800000000558792" + }, + { + "tick": "1800000000605358" + }, + { + "tick": "1800000000651924" + }, + { + "tick": "1800000000698490" + }, + { + "tick": "1800000000745056" + }, + { + "tick": "1800000000791622" + }, + { + "tick": "1800000000838188" + }, + { + "tick": "1800000000884754" + }, + { + "tick": "1800000000931320" + }, + { + "tick": "1800000000977886" + }, + { + "tick": "1800000001024452" + }, + { + "tick": "1800000001071018" + }, + { + "tick": "1800000001117584" + }, + { + "tick": "1800000001164150" + }, + { + "tick": "1800000001210716" + }, + { + "tick": "1800000001257282" + }, + { + "tick": "1800000001303848" + }, + { + "tick": "1800000001350414" + }, + { + "tick": "1800000001396980" + }, + { + "tick": "1800000001443546" + }, + { + "tick": "1800000001490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000000001455", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000000045" + }, + { + "tick": "1800000000000090" + }, + { + "tick": "1800000000000135" + }, + { + "tick": "1800000000000180" + }, + { + "tick": "1800000000000225" + }, + { + "tick": "1800000000000270" + }, + { + "tick": "1800000000000315" + }, + { + "tick": "1800000000000360" + }, + { + "tick": "1800000000000405" + }, + { + "tick": "1800000000000450" + }, + { + "tick": "1800000000000495" + }, + { + "tick": "1800000000000540" + }, + { + "tick": "1800000000000585" + }, + { + "tick": "1800000000000630" + }, + { + "tick": "1800000000000675" + }, + { + "tick": "1800000000000720" + }, + { + "tick": "1800000000000765" + }, + { + "tick": "1800000000000810" + }, + { + "tick": "1800000000000855" + }, + { + "tick": "1800000000000900" + }, + { + "tick": "1800000000000945" + }, + { + "tick": "1800000000000990" + }, + { + "tick": "1800000000001035" + }, + { + "tick": "1800000000001080" + }, + { + "tick": "1800000000001125" + }, + { + "tick": "1800000000001170" + }, + { + "tick": "1800000000001215" + }, + { + "tick": "1800000000001260" + }, + { + "tick": "1800000000001305" + }, + { + "tick": "1800000000001350" + }, + { + "tick": "1800000000001395" + }, + { + "tick": "1800000000001455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000000000013", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000000001" + }, + { + "tick": "1800000000000002" + }, + { + "tick": "1800000000000003" + }, + { + "tick": "1800000000000004" + }, + { + "tick": "1800000000000005" + }, + { + "tick": "1800000000000006" + }, + { + "tick": "1800000000000007" + }, + { + "tick": "1800000000000008" + }, + { + "tick": "1800000000000009" + }, + { + "tick": "1800000000000010" + }, + { + "tick": "1800000000000011" + }, + { + "tick": "1800000000000012" + }, + { + "tick": "1800000000000013" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out new file mode 100644 index 000000000000..26f068148582 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_3).out @@ -0,0 +1,504 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1950000000000000", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1850000000000000" + }, + { + "tick": "1900000000000000" + }, + { + "tick": "1950000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1801562500000000", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800048828125000" + }, + { + "tick": "1800097656250000" + }, + { + "tick": "1800146484375000" + }, + { + "tick": "1800195312500000" + }, + { + "tick": "1800244140625000" + }, + { + "tick": "1800292968750000" + }, + { + "tick": "1800341796875000" + }, + { + "tick": "1800390625000000" + }, + { + "tick": "1800439453125000" + }, + { + "tick": "1800488281250000" + }, + { + "tick": "1800537109375000" + }, + { + "tick": "1800585937500000" + }, + { + "tick": "1800634765625000" + }, + { + "tick": "1800683593750000" + }, + { + "tick": "1800732421875000" + }, + { + "tick": "1800781250000000" + }, + { + "tick": "1800830078125000" + }, + { + "tick": "1800878906250000" + }, + { + "tick": "1800927734375000" + }, + { + "tick": "1800976562500000" + }, + { + "tick": "1801025390625000" + }, + { + "tick": "1801074218750000" + }, + { + "tick": "1801123046875000" + }, + { + "tick": "1801171875000000" + }, + { + "tick": "1801220703125000" + }, + { + "tick": "1801269531250000" + }, + { + "tick": "1801318359375000" + }, + { + "tick": "1801367187500000" + }, + { + "tick": "1801416015625000" + }, + { + "tick": "1801464843750000" + }, + { + "tick": "1801513671875000" + }, + { + "tick": "1801562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800001525878906", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000047683715" + }, + { + "tick": "1800000095367430" + }, + { + "tick": "1800000143051145" + }, + { + "tick": "1800000190734860" + }, + { + "tick": "1800000238418575" + }, + { + "tick": "1800000286102290" + }, + { + "tick": "1800000333786005" + }, + { + "tick": "1800000381469720" + }, + { + "tick": "1800000429153435" + }, + { + "tick": "1800000476837150" + }, + { + "tick": "1800000524520865" + }, + { + "tick": "1800000572204580" + }, + { + "tick": "1800000619888295" + }, + { + "tick": "1800000667572010" + }, + { + "tick": "1800000715255725" + }, + { + "tick": "1800000762939440" + }, + { + "tick": "1800000810623155" + }, + { + "tick": "1800000858306870" + }, + { + "tick": "1800000905990585" + }, + { + "tick": "1800000953674300" + }, + { + "tick": "1800001001358015" + }, + { + "tick": "1800001049041730" + }, + { + "tick": "1800001096725445" + }, + { + "tick": "1800001144409160" + }, + { + "tick": "1800001192092875" + }, + { + "tick": "1800001239776590" + }, + { + "tick": "1800001287460305" + }, + { + "tick": "1800001335144020" + }, + { + "tick": "1800001382827735" + }, + { + "tick": "1800001430511450" + }, + { + "tick": "1800001478195165" + }, + { + "tick": "1800001525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000001490116", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000046566" + }, + { + "tick": "1800000000093132" + }, + { + "tick": "1800000000139698" + }, + { + "tick": "1800000000186264" + }, + { + "tick": "1800000000232830" + }, + { + "tick": "1800000000279396" + }, + { + "tick": "1800000000325962" + }, + { + "tick": "1800000000372528" + }, + { + "tick": "1800000000419094" + }, + { + "tick": "1800000000465660" + }, + { + "tick": "1800000000512226" + }, + { + "tick": "1800000000558792" + }, + { + "tick": "1800000000605358" + }, + { + "tick": "1800000000651924" + }, + { + "tick": "1800000000698490" + }, + { + "tick": "1800000000745056" + }, + { + "tick": "1800000000791622" + }, + { + "tick": "1800000000838188" + }, + { + "tick": "1800000000884754" + }, + { + "tick": "1800000000931320" + }, + { + "tick": "1800000000977886" + }, + { + "tick": "1800000001024452" + }, + { + "tick": "1800000001071018" + }, + { + "tick": "1800000001117584" + }, + { + "tick": "1800000001164150" + }, + { + "tick": "1800000001210716" + }, + { + "tick": "1800000001257282" + }, + { + "tick": "1800000001303848" + }, + { + "tick": "1800000001350414" + }, + { + "tick": "1800000001396980" + }, + { + "tick": "1800000001443546" + }, + { + "tick": "1800000001490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000000001455", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000000045" + }, + { + "tick": "1800000000000090" + }, + { + "tick": "1800000000000135" + }, + { + "tick": "1800000000000180" + }, + { + "tick": "1800000000000225" + }, + { + "tick": "1800000000000270" + }, + { + "tick": "1800000000000315" + }, + { + "tick": "1800000000000360" + }, + { + "tick": "1800000000000405" + }, + { + "tick": "1800000000000450" + }, + { + "tick": "1800000000000495" + }, + { + "tick": "1800000000000540" + }, + { + "tick": "1800000000000585" + }, + { + "tick": "1800000000000630" + }, + { + "tick": "1800000000000675" + }, + { + "tick": "1800000000000720" + }, + { + "tick": "1800000000000765" + }, + { + "tick": "1800000000000810" + }, + { + "tick": "1800000000000855" + }, + { + "tick": "1800000000000900" + }, + { + "tick": "1800000000000945" + }, + { + "tick": "1800000000000990" + }, + { + "tick": "1800000000001035" + }, + { + "tick": "1800000000001080" + }, + { + "tick": "1800000000001125" + }, + { + "tick": "1800000000001170" + }, + { + "tick": "1800000000001215" + }, + { + "tick": "1800000000001260" + }, + { + "tick": "1800000000001305" + }, + { + "tick": "1800000000001350" + }, + { + "tick": "1800000000001395" + }, + { + "tick": "1800000000001455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "1800000000000000", + "end_tick": "1800000000000013", + "dissection": [ + { + "tick": "1800000000000000" + }, + { + "tick": "1800000000000001" + }, + { + "tick": "1800000000000002" + }, + { + "tick": "1800000000000003" + }, + { + "tick": "1800000000000004" + }, + { + "tick": "1800000000000005" + }, + { + "tick": "1800000000000006" + }, + { + "tick": "1800000000000007" + }, + { + "tick": "1800000000000008" + }, + { + "tick": "1800000000000009" + }, + { + "tick": "1800000000000010" + }, + { + "tick": "1800000000000011" + }, + { + "tick": "1800000000000012" + }, + { + "tick": "1800000000000013" + } + ] +} diff --git a/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out new file mode 100644 index 000000000000..7f4e245ad8c1 --- /dev/null +++ b/tezt/tests/expected/sc_rollup.ml/Parisc- wasm_2_0_0 - refutation games winning strategies (pvm_proof_second_perio.out @@ -0,0 +1,501 @@ + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "1000000000000000", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "950000000000000" + }, + { + "tick": "1000000000000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "901562500000000", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900048828125000" + }, + { + "tick": "900097656250000" + }, + { + "tick": "900146484375000" + }, + { + "tick": "900195312500000" + }, + { + "tick": "900244140625000" + }, + { + "tick": "900292968750000" + }, + { + "tick": "900341796875000" + }, + { + "tick": "900390625000000" + }, + { + "tick": "900439453125000" + }, + { + "tick": "900488281250000" + }, + { + "tick": "900537109375000" + }, + { + "tick": "900585937500000" + }, + { + "tick": "900634765625000" + }, + { + "tick": "900683593750000" + }, + { + "tick": "900732421875000" + }, + { + "tick": "900781250000000" + }, + { + "tick": "900830078125000" + }, + { + "tick": "900878906250000" + }, + { + "tick": "900927734375000" + }, + { + "tick": "900976562500000" + }, + { + "tick": "901025390625000" + }, + { + "tick": "901074218750000" + }, + { + "tick": "901123046875000" + }, + { + "tick": "901171875000000" + }, + { + "tick": "901220703125000" + }, + { + "tick": "901269531250000" + }, + { + "tick": "901318359375000" + }, + { + "tick": "901367187500000" + }, + { + "tick": "901416015625000" + }, + { + "tick": "901464843750000" + }, + { + "tick": "901513671875000" + }, + { + "tick": "901562500000000" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900001525878906", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000047683715" + }, + { + "tick": "900000095367430" + }, + { + "tick": "900000143051145" + }, + { + "tick": "900000190734860" + }, + { + "tick": "900000238418575" + }, + { + "tick": "900000286102290" + }, + { + "tick": "900000333786005" + }, + { + "tick": "900000381469720" + }, + { + "tick": "900000429153435" + }, + { + "tick": "900000476837150" + }, + { + "tick": "900000524520865" + }, + { + "tick": "900000572204580" + }, + { + "tick": "900000619888295" + }, + { + "tick": "900000667572010" + }, + { + "tick": "900000715255725" + }, + { + "tick": "900000762939440" + }, + { + "tick": "900000810623155" + }, + { + "tick": "900000858306870" + }, + { + "tick": "900000905990585" + }, + { + "tick": "900000953674300" + }, + { + "tick": "900001001358015" + }, + { + "tick": "900001049041730" + }, + { + "tick": "900001096725445" + }, + { + "tick": "900001144409160" + }, + { + "tick": "900001192092875" + }, + { + "tick": "900001239776590" + }, + { + "tick": "900001287460305" + }, + { + "tick": "900001335144020" + }, + { + "tick": "900001382827735" + }, + { + "tick": "900001430511450" + }, + { + "tick": "900001478195165" + }, + { + "tick": "900001525878906" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900000001490116", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000000046566" + }, + { + "tick": "900000000093132" + }, + { + "tick": "900000000139698" + }, + { + "tick": "900000000186264" + }, + { + "tick": "900000000232830" + }, + { + "tick": "900000000279396" + }, + { + "tick": "900000000325962" + }, + { + "tick": "900000000372528" + }, + { + "tick": "900000000419094" + }, + { + "tick": "900000000465660" + }, + { + "tick": "900000000512226" + }, + { + "tick": "900000000558792" + }, + { + "tick": "900000000605358" + }, + { + "tick": "900000000651924" + }, + { + "tick": "900000000698490" + }, + { + "tick": "900000000745056" + }, + { + "tick": "900000000791622" + }, + { + "tick": "900000000838188" + }, + { + "tick": "900000000884754" + }, + { + "tick": "900000000931320" + }, + { + "tick": "900000000977886" + }, + { + "tick": "900000001024452" + }, + { + "tick": "900000001071018" + }, + { + "tick": "900000001117584" + }, + { + "tick": "900000001164150" + }, + { + "tick": "900000001210716" + }, + { + "tick": "900000001257282" + }, + { + "tick": "900000001303848" + }, + { + "tick": "900000001350414" + }, + { + "tick": "900000001396980" + }, + { + "tick": "900000001443546" + }, + { + "tick": "900000001490116" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900000000001455", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000000000045" + }, + { + "tick": "900000000000090" + }, + { + "tick": "900000000000135" + }, + { + "tick": "900000000000180" + }, + { + "tick": "900000000000225" + }, + { + "tick": "900000000000270" + }, + { + "tick": "900000000000315" + }, + { + "tick": "900000000000360" + }, + { + "tick": "900000000000405" + }, + { + "tick": "900000000000450" + }, + { + "tick": "900000000000495" + }, + { + "tick": "900000000000540" + }, + { + "tick": "900000000000585" + }, + { + "tick": "900000000000630" + }, + { + "tick": "900000000000675" + }, + { + "tick": "900000000000720" + }, + { + "tick": "900000000000765" + }, + { + "tick": "900000000000810" + }, + { + "tick": "900000000000855" + }, + { + "tick": "900000000000900" + }, + { + "tick": "900000000000945" + }, + { + "tick": "900000000000990" + }, + { + "tick": "900000000001035" + }, + { + "tick": "900000000001080" + }, + { + "tick": "900000000001125" + }, + { + "tick": "900000000001170" + }, + { + "tick": "900000000001215" + }, + { + "tick": "900000000001260" + }, + { + "tick": "900000000001305" + }, + { + "tick": "900000000001350" + }, + { + "tick": "900000000001395" + }, + { + "tick": "900000000001455" + } + ] +} + + +{ + "opponent": "tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN", + "start_tick": "900000000000000", + "end_tick": "900000000000013", + "dissection": [ + { + "tick": "900000000000000" + }, + { + "tick": "900000000000001" + }, + { + "tick": "900000000000002" + }, + { + "tick": "900000000000003" + }, + { + "tick": "900000000000004" + }, + { + "tick": "900000000000005" + }, + { + "tick": "900000000000006" + }, + { + "tick": "900000000000007" + }, + { + "tick": "900000000000008" + }, + { + "tick": "900000000000009" + }, + { + "tick": "900000000000010" + }, + { + "tick": "900000000000011" + }, + { + "tick": "900000000000012" + }, + { + "tick": "900000000000013" + } + ] +} diff --git a/tezt/tests/expected/script_hash_regression.ml/Paris- Test script hash regression.out b/tezt/tests/expected/script_hash_regression.ml/Parisb- Test script hash regression.out similarity index 100% rename from tezt/tests/expected/script_hash_regression.ml/Paris- Test script hash regression.out rename to tezt/tests/expected/script_hash_regression.ml/Parisb- Test script hash regression.out diff --git a/tezt/tests/expected/script_hash_regression.ml/Parisc- Test script hash regression.out b/tezt/tests/expected/script_hash_regression.ml/Parisc- Test script hash regression.out new file mode 100644 index 000000000000..e16fe16b92d1 --- /dev/null +++ b/tezt/tests/expected/script_hash_regression.ml/Parisc- Test script hash regression.out @@ -0,0 +1,445 @@ +exprvFK4dJmFGinHHBe92WR4kA7L8WSBQQYDigmyVCyKpiQHCXe9fk michelson_test_scripts/attic/accounts.tz +expruucsMyaSmmP5gmkFWjJfv4a52FQV5EGaf3XpHoeXHQgyJgMJfF michelson_test_scripts/attic/add1.tz +exprvEM4Lvihz6jFYszxazuQQPsHjxA4J54tfLeowwDkY1jjTi8Qft michelson_test_scripts/attic/add1_list.tz +exprta1x6QtexpFktejHoB1KwuMQRXePhgre9rDiJ3GDSZCqb3vtqL michelson_test_scripts/attic/after_strategy.tz +expruEosJCXYteRXxfbAVJ5XythgpVQPMdiu3kbbZj3VAVSVjk8ud7 michelson_test_scripts/attic/always.tz +exprvR9m6PaVeLfPHZjA3A929bbfjonzMJs1Kzcmj8baoEvLct9Ry9 michelson_test_scripts/attic/append.tz +exprvQh7vw7vYfp2qdiyYPCFgd6jVkxqYZimmqoYCGZbqaoMgfLifS michelson_test_scripts/attic/at_least.tz +exprtyZC9vL831BnATCkdrP585F4cEzQQQp1ZqnZSqvCDLqp7S33V1 michelson_test_scripts/attic/auction.tz +expruZ4wjBCm3DQNhEf69L27tqaqAJa1TF34728yyPJ9BUg3sEwcxB michelson_test_scripts/attic/bad_lockup.tz +expruazd13u4uPHS7oFWFeZ5nodWR5QC6nQwgy5LGoUTAR3KXsYPXg michelson_test_scripts/attic/big_map_union.tz +exprv7aEg823PTvrEG5bXr4QGk3XCsEkodhUxWCaMBBSq44ZuAxnNf michelson_test_scripts/attic/cadr_annotation.tz +expruwmej4r1RSMDEmmU4SjWUbrzpURnAwybrSwBaMkHpxVobLkWAe michelson_test_scripts/attic/concat.tz +exprte328K2NmgWrmHLbFrGVjvoZKZNFB7577Vt7cWQa8KdvWbfxYk michelson_test_scripts/attic/conditionals.tz +exprvRVXhJFcFjGMkatDwgaLRcJq4TctY979bjniTqwACgXtC3mWko michelson_test_scripts/attic/cons_twice.tz +exprtcnAL38pt7fyZdCiqd97qcYeESWQStPR6sbN2SxMCfbPJhVjau michelson_test_scripts/attic/cps_fact.tz +exprv9BquR6NXVwKMwD4MS5vdWqqvMzjvWumrBf6NsGQXSfgm2Rtqk michelson_test_scripts/attic/create_add1_lists.tz +exprv4cq5g9hsxWU65zCp8dfUi3RtBzu9rGXZ7otetL23tj1zSkNQ2 michelson_test_scripts/attic/data_publisher.tz +expruavAC89RfrZxSrYwdoA6Wr5ghwdUSns8SNaHcng1JRcqR1dwpR michelson_test_scripts/attic/dispatch.tz +expruat2BS4KCwn9kbopeX1ZwxtrtJbyFhpnpnG6A5KdCBCwHNsdod michelson_test_scripts/attic/empty.tz +exprubD7VQHa8qeqRsFByes3ANZ24mvUnqW3qKAsKVUCncjxYEXtGp michelson_test_scripts/attic/fail_amount.tz +expruYCfXuFoyakdWc3C6Np5ojQrGLDMMN6btVbVEAc97MJzpQYVrm michelson_test_scripts/attic/faucet.tz +expruuvYJkV5YndLNMHFg54yDF1HG6AP4zMsui7RgQBLr6vCZVBVYt michelson_test_scripts/attic/forward.tz +exprv8K6ceBpFH5SFjQm4BRYSLJCHQBFeQU6BFTdvQSRPaPkzdLyAL michelson_test_scripts/attic/id.tz +exprujqMuqia1zKuReMgjumpsn8XAJ5N6RWaoz3kZpLNRUyyQXwrtY michelson_test_scripts/attic/infinite_loop.tz +exprtoE9fvqNeHngkFPopZv412GoqoZ57HgaCi2XFR7YxkwPpvHXBZ michelson_test_scripts/attic/insertion_sort.tz +exprux8tMeArJNXUekbuHqLb6epu2eWXJy85f8Yts5oHASHyWp6bva michelson_test_scripts/attic/int_publisher.tz +expruosSkGQbRDc3NUt5oEqSkt3dqxymQDKDeNxcjRgFNLxARG414v michelson_test_scripts/attic/king_of_tez.tz +exprtZcF9NutGBwyuXTqEi4SyL3bZdAWqzkDc782wxNhYT7LtdY4Lb michelson_test_scripts/attic/list_of_transactions.tz +expruDiMLqyYi67RbkDfNyEjBDgJqQLiCGVx2xLUiWujSkwr7rVyRD michelson_test_scripts/attic/queue.tz +exprtZYeWyxANtdrSANECgXdeakcP9fJm7ecJhpeuGR55a8gDTSXWe michelson_test_scripts/attic/reduce_map.tz +exprvMneQMtBQzcPKboFsEV7R4BAuoF8QLUDMWB62iYLmKz9tztNdJ michelson_test_scripts/attic/reentrancy.tz +exprueaa65wkL9ennP6vZoUP6yCkzz6Wc4cF3w11q8bGXguokXAEvK michelson_test_scripts/attic/reservoir.tz +exprtwrNpVRUJaVTBs5vXFLbt4v6Fb8LRySwc1Ap8ZWZh4JbLfgJ6P michelson_test_scripts/attic/scrutable_reservoir.tz +expruwtkYFMkNLVjKD8hypuDc53SHLQQ65g6VPGiHFXbY5hHwmb552 michelson_test_scripts/attic/spawn_identities.tz +exprtjdvZr5J7WfN4SyNgKueLnxX4fALUYJ4cmi675EHJdUu5yyg2n michelson_test_scripts/entrypoints/big_map_entrypoints.tz +expruwheT76ehrMrKiyNw8pQEEUfQ1t184BMXGqhaMEuJUCKHNytMj michelson_test_scripts/entrypoints/delegatable_target.tz +exprv2AhXPjk56KeNgWmzN15v8f9SoLHMQhNmDAgt6SpAMFmYRCQjx michelson_test_scripts/entrypoints/manager.tz +exprv2SsGeZ6PiC2CXiSePHYQhn88XWmsKVGgG8ZGyNo8p9CNPrRXj michelson_test_scripts/entrypoints/no_default_target.tz +exprvFzfTFqHSFZuDHh91nrupqpULYorBNZRgLEEiPkUhkNVyskyTz michelson_test_scripts/entrypoints/no_entrypoint_target.tz +exprtw1GsUzdCfFR6bHsdF78uTbejEJ4iTdXn7YTYRU5C7XS89dyxU michelson_test_scripts/entrypoints/rooted_target.tz +exprtaqrrvZzcS8wKS8u6RcVqRJhnu2Qbex9jRUZHQxJJeqhhfhtXJ michelson_test_scripts/entrypoints/simple_entrypoints.tz +exprv8K6ceBpFH5SFjQm4BRYSLJCHQBFeQU6BFTdvQSRPaPkzdLyAL michelson_test_scripts/ill_typed/badly_indented.tz +expruN224mpoNLwPiVuGuaJ22QZjMuK6sKjGFAeSyQY8PQoBC7Hoim michelson_test_scripts/ill_typed/big_dip.tz +exprtnvncrJA5Fo5iyGnhyXhHXyWJuwvzWHP6Rbokbr7HsSqxQ7QLC michelson_test_scripts/ill_typed/big_drop.tz +expruBzaC26c6mckE8g8wLBH7t1JnFi8Uyn7WjdWKGT6sJftboCFTJ michelson_test_scripts/ill_typed/big_map_arity.tz +expruMk21qTMDDKvFNjTNLab33QEbdnG3kP7M1WEWcXhpPLkCAA21X michelson_test_scripts/ill_typed/chain_id_arity.tz +exprtrJKmsNVineQxEPp8Eq7FcC7edZHbJEdrn56WpqxW61QCpjacm michelson_test_scripts/ill_typed/comb0.tz +expruQsBtw9Fg9gmZSiCPUDD8FjqzDvQDTG5FSFbSJsr7j64DLbwjE michelson_test_scripts/ill_typed/comb1.tz +expruDceVcE3mACUGZhntGk2BMQNNn8UaFZhd8BnRfyWWzdFav7VyP michelson_test_scripts/ill_typed/contract_annotation_default.tz +exprv8no3WSXCsf89WYazUNurLm8hwZRwTWYBQrzihscQcR6M1uKEu michelson_test_scripts/ill_typed/create_contract_rootname.tz +exprtxuT8vf615qpJ9ycmVu7XUGBB8pZZjnPKnZhFhBMfdUpw2JarU michelson_test_scripts/ill_typed/dip_failwith.tz +expruUrLEKFhakNNzTRBigYqnGi2DkvS64m52omEYizdjmscmgF2AQ michelson_test_scripts/ill_typed/dup0.tz +expruUbLS1knNLEJMoE8c7oTbNo3EXiEgagPewKZLFUukFpQZJ7zce michelson_test_scripts/ill_typed/failwith_big_map.tz +expruk5YNGKzCkCMbLhr3euh9xQWZcmtZkGV891LMhNHbxpe1P5QTW michelson_test_scripts/ill_typed/invalid_self_entrypoint.tz +exprtX6MmAqAQ37LRgnkdv525PKHiGdGXyKT33M1NASahAMSCt43VS michelson_test_scripts/ill_typed/map_failwith.tz +expru9tAzQAm6c8Uv4oU6EpkJR6wWXZ8b7MUfyQMorpR8j3HKb2xQM michelson_test_scripts/ill_typed/missing_only_code_field.tz +expru1TjqXpC2u8BLGP5Ps6DPyXLvRY7arR187zjhTJsT3ovrbyqSm michelson_test_scripts/ill_typed/missing_only_parameter_field.tz +exprtnqtHEs13CBddyrcWuvRzsBqgk4vFqdaYTGp2UzY4Z8ahAW6Ej michelson_test_scripts/ill_typed/missing_only_storage_field.tz +expruyMAkvFzMm9ANKFgnpX5cfTVufBcrEn47wYGmnD1hocSbHJLxp michelson_test_scripts/ill_typed/missing_parameter_and_storage_fields.tz +expruRoBeRu3HBshceKrBikpiJWgz9pET8UC6QH7xvM33wPtxJ5cxL michelson_test_scripts/ill_typed/multiple_code_field.tz +exprvLL1MBfbBRMb3R4cy6bJ6KgoMuzNmL6u2y6NaT1hhbCmkprDi1 michelson_test_scripts/ill_typed/multiple_parameter_field.tz +exprudNsSikUJ8etsu55GFBJY33H2x9tzT7v2k1w5m5gLJBb8vU2B9 michelson_test_scripts/ill_typed/multiple_storage_and_code_fields.tz +expruLyv1V3fshbeb9HzsodyQFGDihmbt9wZD8UdP3NJEXzBvkaUL8 michelson_test_scripts/ill_typed/multiple_storage_field.tz +expruvbJCzBYasMCg3DcjmYK9FodRbLokBpWNxZpJDyyunsQK6gWCF michelson_test_scripts/ill_typed/never_literal.tz +exprvBkft3ii7B5gjvqFJKsEGq1z9VhnRHW5JAdPNGWPvMdkMRKjTA michelson_test_scripts/ill_typed/pack_big_map.tz +exprutSqwcaXa6tmF2D4asfxkb6QN5CDn128U4ntCgRG5JKUPan7i2 michelson_test_scripts/ill_typed/pack_operation.tz +expru6yXKqKsiikqZe4hgfbACNDFiGtSSoRsuEtcJy5iYwkwDCG9T4 michelson_test_scripts/ill_typed/pack_sapling_state.tz +exprvQzTcT6STxdp9CJi4mtrY9fvv6VvmfRjEqoQwUqYwEK85mjw5H michelson_test_scripts/ill_typed/push_big_map_with_id_with_parens.tz +exprvMz8TqvLs55NtZzBJ2quCwCB7FqxhVuAiMtEZGK8MWxQw6H9Xx michelson_test_scripts/ill_typed/push_big_map_with_id_without_parens.tz +expruW1dZrFKoyXWLXr3Yeqhmivj9qqqnDyWSc3NzyVHudEANGYjVW michelson_test_scripts/ill_typed/sapling_build_empty_state_with_int_parameter.tz +exprv7mqCULEgnAUKoU4foKVKZeuM6uMSkCCgoMeE1oGYMXGebu5L7 michelson_test_scripts/ill_typed/set_update_non_comparable.tz +expruVMMR2tyqqRqpVQzhLXF47658GNFQB2gLaemhrV8gRm9yZt1x4 michelson_test_scripts/ill_typed/stack_bottom_undig2able.tz +expruxH5WZ4TkhVCUq767J2fHG2yuqL13fWjcKK8azQmy2N9ud11RG michelson_test_scripts/ill_typed/stack_bottom_undigable.tz +expruVvGWPSfsZCtSGEm3qMmCgyveYXhVLQhhxpYBv7GTqaDL91kLf michelson_test_scripts/ill_typed/stack_bottom_undip2able.tz +exprtYhZdG4uP6y2pq4ewHDahRQP4fZ2iBMEYRgpq1hqMFQmMRZuWR michelson_test_scripts/ill_typed/stack_bottom_undipable.tz +exprttbYRZnFJLumEAvLpyH6R1A1GjcwuP39EZTqwNWYyceAAWFKoK michelson_test_scripts/ill_typed/stack_bottom_undropable.tz +expruRbdhi81mKdvamEnP2LoCNVVz6ewvyWhezKqZGxjrVFt7hpcq2 michelson_test_scripts/ill_typed/stack_bottom_undug2able.tz +exprtgLFbB3vNCxh9hHfH2rQdS2Vnqqucwqa2PGZScv6f64agKeay3 michelson_test_scripts/ill_typed/stack_bottom_undugable.tz +exprvQjZYDufKeuRxvKsMEPFMyuZYWYVUSe2GZJw8eXRXYSD73buTB michelson_test_scripts/ill_typed/stack_bottom_undup2able.tz +exprtz1gy2jW3mpiJxgquMA68mjWh8s61HDQJzVp5hhUQnVsP9xR5L michelson_test_scripts/ill_typed/stack_bottom_unfailwithable.tz +exprvDK14kRaERXV4ygtEJTgd5UQikyupAMdTWbZFTULAFPzARqAdQ michelson_test_scripts/ill_typed/stack_bottom_ungetable.tz +exprtydB8VD3snEKSXYgV2SphRE8bZvPJd3o1QEU6GPqZm8cHc1iTR michelson_test_scripts/ill_typed/stack_bottom_unleftable.tz +expruKgcBzkj11KzkbRKYAsWrngu4rBuqNmhPdGWudV4KeePSJGoEk michelson_test_scripts/ill_typed/stack_bottom_unpairable.tz +expruFLiTmNwLXuXVaPGquovMCYjgCeJzKKV27DK14NQAG7z4nGxvQ michelson_test_scripts/ill_typed/stack_bottom_unpopable.tz +expruQAEgAnhPLZuaywyGgJGqcRFWn2rEDprqNHvRDxirdShLwc26c michelson_test_scripts/ill_typed/stack_bottom_unpopable_in_lambda.tz +expruGDfhqvw6oH6cA6Vvvjdn8FyEmJ7SUizhNFCYNSfG2ikmBr5ea michelson_test_scripts/ill_typed/stack_bottom_unrightable.tz +exprunAg8DteXhBhjmmEPasSRe5u18oN5UdwJUyz7crzktR1n7aj7g michelson_test_scripts/ill_typed/ticket_apply.tz +exprtv5Yt3ihwrqvfZm2CZdHkJk544CdepaQ5g6jTF5UhfvK3y1PAc michelson_test_scripts/ill_typed/ticket_dup.tz +expruQfVM57mGxNiY7XpV3Rex8xhqLwRyXvvSEBEZuHKvoVgo8sfsU michelson_test_scripts/ill_typed/ticket_in_ticket.tz +exprtw4id4R45wkzJz7g5GBiRStuREcD515mjMvECP2Nsjt1GCDQSb michelson_test_scripts/ill_typed/ticket_unpack.tz +exprtsPNzBdoHNqsiGGzD83vzY4QhRGFgj2aBhVkRjryg8UCzgB7rm michelson_test_scripts/ill_typed/timelock.tz +expruWHcaUVqG6kmYxQF1Mxx5hmB2SYUeNVWNkVrprgax67e9sLATa michelson_test_scripts/ill_typed/uncomb0.tz +exprtrL9J2534bFgoBvVC1YaNVXDsE1c2FXWxgyDhDHtUz5zghortN michelson_test_scripts/ill_typed/uncomb1.tz +exprujrucGLAmdmT3k2iRC2imquB7sUbcvSg6zVrvAxcvbrrkodSRb michelson_test_scripts/ill_typed/unpack_sapling_state.tz +expru2vU5zmzGh2HRrwNeSnysgcVLMbPb1tkGoFTrNg6YiNMqm2dxD michelson_test_scripts/ill_typed/view_op_bad_name_invalid_char_set.tz +exprufbbZ4jHZ6PJJT614zAJU4ZdSEEmjTpxM9YMnEMSLLR85tKe97 michelson_test_scripts/ill_typed/view_op_bad_name_invalid_type.tz +exprtZFiFcS8quUpTKd6cdop8WKZ9km6X18pF8gWngrTarAiVWWuxv michelson_test_scripts/ill_typed/view_op_bad_name_non_printable_char.tz +exprtn9rV6YNYRDCKtShnzAeKaYh8jqTNKjGxVYo1twk7hrAhPaLrT michelson_test_scripts/ill_typed/view_op_bad_name_too_long.tz +expruBC7TwAKWgKbY8dpuDR7cuvxjFM6nCd935jCcWq9rSJNw1aA75 michelson_test_scripts/ill_typed/view_op_bad_return_type.tz +expruoFRmDZuVddy7VmkV2QBcLgSStqpEDMDacTWsFzqTxZXdWdZfC michelson_test_scripts/ill_typed/view_op_dupable_type.tz +expruxYAxsENuXbe9kyhfUaWWAjBfWkbuQy8irkyJkevrfLBsWt7xc michelson_test_scripts/ill_typed/view_op_invalid_arity.tz +exprvPFLSH8Yzs7khoVZkEz4sYWbh6b8ekM6iHrGY5Ds1BjUm763QM michelson_test_scripts/ill_typed/view_op_lazy_storage.tz +exprvPFLSH8Yzs7khoVZkEz4sYWbh6b8ekM6iHrGY5Ds1BjUm763QM michelson_test_scripts/ill_typed/view_op_lazy_storage_type.tz +expruUdCLKAbj9Ww3JkAZ4W2UuTiJ7ugE7kg9DVe4AUfXKE8Q1iPVQ michelson_test_scripts/ill_typed/view_toplevel_bad_input_type.tz +expruWvd91ycMrLFH8jF534BhTWjnHxaHrEubeRNeodafNWfjqqBXC michelson_test_scripts/ill_typed/view_toplevel_bad_name_invalid_char_set.tz +expruethdzDpBvRtq9UQPdXGwRZqkWnqs6CrcNagNVhDU9vCwsMdzA michelson_test_scripts/ill_typed/view_toplevel_bad_name_invalid_type.tz +exprtnn8xxH2nr6UErb9DNv9Z9xngpSzpYnNk6hwBTbye4x5uacMeQ michelson_test_scripts/ill_typed/view_toplevel_bad_name_non_printable_char.tz +exprunFKRQPF9Hobtkqx32WyQ6ikygyLkL7DCBMNuMoG95NqzVF6si michelson_test_scripts/ill_typed/view_toplevel_bad_name_too_long.tz +exprvMAXDRZuAVGhFHJwnWVoZ411MwmQ9EdVh2JuRnw5qcdz6MjQC1 michelson_test_scripts/ill_typed/view_toplevel_bad_return_type.tz +exprv56pnBNv6EsEHTHjWhJ3tdv5qptVpQGw4ShYC4ojPMxk7Nkxok michelson_test_scripts/ill_typed/view_toplevel_bad_type.tz +exprvAA9gioYUserBNWfg3dM3tpUkeJpEvQBhdCYo6Zkbj8cDciEHE michelson_test_scripts/ill_typed/view_toplevel_dupable_type_input.tz +expru63YpYAZBw9UnRy2pmB9uMQRH4EJXF1BcRAV5xeq3tBdtKtt1F michelson_test_scripts/ill_typed/view_toplevel_dupable_type_output.tz +expruhHAADYeL1YyPJJ6JJDVG1uZMtUChzTRY7wUqjqDJv42WF9iuM michelson_test_scripts/ill_typed/view_toplevel_duplicated_name.tz +exprugDV6TiQP1tmA2JMGXiuF29EKmqacQeF3q7rWkfwzVrw5Qgksd michelson_test_scripts/ill_typed/view_toplevel_invalid_arity.tz +exprum4MVnmugWSpeJysnzAkDFshNeuWboGS3qsgCi3eo9GCxGWZC1 michelson_test_scripts/ill_typed/view_toplevel_lazy_storage_input.tz +expruT8foeFBSvHXuiN9UvAxj6d3ZhidwFteyE4pNHNe3zxcC1LKNv michelson_test_scripts/ill_typed/view_toplevel_lazy_storage_output.tz +exprtf4cGFGDne118G4RFZkHFXFdZMNgAtm1h3zXohFS4n6mzEe4Bp michelson_test_scripts/legacy/create_account.tz +exprtcuNLyAhcZ7Zt6K8pH3KzVyU9YELeSXkJsMPG1h3FyKebyzBz9 michelson_test_scripts/legacy/create_contract.tz +exprutTcX1BwgaPug446zmc16pnipd59ytpVmA6JxAAEyUwJbD47Qv michelson_test_scripts/legacy/create_contract_flags.tz +expruypHz1N6PhereVyiB349tQbrYJhBDr6pJBck1BAUudKRMvMH77 michelson_test_scripts/legacy/create_contract_rootname.tz +exprvPF2hwUEU3GeucamVx6wnv9VWH39QsJVtQW3uUWwXc4aQWJVEw michelson_test_scripts/legacy/originator.tz +expruyPygjWK6gmUgsRZgv7Df2rnqpQUMj65ApbCqmHXNbS2o6QAMk michelson_test_scripts/legacy/steps_to_quota.tz +expruiDvGyQG5GzKzcBP7d5Z5doUcdxTmUcM6vL1jCTyTmxLrekmP7 michelson_test_scripts/macros/assert.tz +expruMKaaLoPjYfDaKymizi9fnFY7hSDyPj2NfJFxSuAoEVknDxSM6 michelson_test_scripts/macros/assert_cmpeq.tz +exprtqiRJEnWeqF5KKBRPjamJGoi2oQvekfnRwsdZNRy8w8wkbroKJ michelson_test_scripts/macros/assert_cmpge.tz +exprtZWviL38eegiNAN55KfEtAHhAqUWoadkbxyFCGs3vDnDRzueft michelson_test_scripts/macros/assert_cmpgt.tz +exprvBWTmSLBAGgcuBFSToCQPqH5J1F5R2vf8iJMiPVdZjG3B7hWq7 michelson_test_scripts/macros/assert_cmple.tz +expruuDzygKxAaQ348e6BcRSk8A2Chq4WinaTUCTvg5YEVnGpptBg3 michelson_test_scripts/macros/assert_cmplt.tz +expruxeuWRoEFHhzv7tG1rwderXePZzxtpL9BRQ9N7ZhoFXS6RPy9a michelson_test_scripts/macros/assert_cmpneq.tz +expruaqEBPqAjaUawnFTSbGZXXr1HemnecV8GuLGD15nQvtxaXiH3z michelson_test_scripts/macros/assert_eq.tz +expru9etUCKvNXZyDCx1x55QfZzyGxmgsteFNBoWAZeh6F5FHEHy3m michelson_test_scripts/macros/assert_ge.tz +exprvP9aPgepXY1C4hVPWPMoDGhvSjNvH5sJvB25qcMMPFHurVyH9c michelson_test_scripts/macros/assert_gt.tz +exprtbLVpjXVnhdMUyDM53MXHH2HBNSMxdnXsVTNtFFMHHVn18yUuZ michelson_test_scripts/macros/assert_le.tz +exprtx7nibNobG8Y7asBYktu2NdPv3k3No29rM4nP1WSbricymunvc michelson_test_scripts/macros/assert_lt.tz +exprvQM6Ukz3TKVSo4dqNDYmMvNG5rs3U7WGXpvjSVsM2oQj6SbdLM michelson_test_scripts/macros/assert_neq.tz +exprueGaPWpG6szfmTAccNH5MaoqxovN7JCbx4CDsmpvnhBAUrAizc michelson_test_scripts/macros/big_map_get_add.tz +exprvFc9HFkvwNGZVrJkU2KpXuXieVKCJ9VXbTo51LRWBMAB6oEbWq michelson_test_scripts/macros/big_map_mem.tz +exprv7Gwz5KP32zP9FYPSng9mPqLYbxwttDZin5QPnqzsUM3MZBvLK michelson_test_scripts/macros/build_list.tz +exprvNqdnnqWgrrZYgnkuFeXrboqQYnYiRLSb7wV4E27bdZcbrU5GK michelson_test_scripts/macros/carn_and_cdrn.tz +exprtknptGzyx8quFM8gHyGcpyX5xYeUxUpoVPhZeBkRqz5hUHfuq7 michelson_test_scripts/macros/compare.tz +exprussGZ9wiqKqGkCsFJrfvr5DXxqZiLuHATJuvr3D8ar3KCeNaCz michelson_test_scripts/macros/compare_bytes.tz +expru4Mmhu46yLQj4Q767jgVgvbaNe7B6EwvYvWA9KCrfzCxwBnzCQ michelson_test_scripts/macros/fail.tz +exprtyJ1YYdejX7jRUh8FDjbbwrbAFwZYKPjdEZMNUUWdncqEwvuyr michelson_test_scripts/macros/guestbook.tz +exprvMCL9Ti9C12EZUiFR1YtSp7nYjPN4DoyJPQiyVDYCZsSsheTeV michelson_test_scripts/macros/macro_annotations.tz +expruq2AH96hXvqFqphuMKhJUY8mGMmdHuiHWHjkZqooZoEusTNNRf michelson_test_scripts/macros/map_caddaadr.tz +exprueEkWTdWS8F25vnUP8gWd75MCfxk3vMhETn5dUYtrifV6FU8x5 michelson_test_scripts/macros/max_in_list.tz +expruGfNErSHzpWnoNpgvZ3MRc52jiCHu8YTDUvh2T643QABr7NDZN michelson_test_scripts/macros/min.tz +exprtw4kigYCiREgky6KBKryS7JkaGih6ju8jkjaXtpdcWYrYukRKX michelson_test_scripts/macros/pair_macro.tz +exprtxutG1Nu8d198ebiCraNuQ8a6iYYqJYfGXq19aykNPB1uECc8w michelson_test_scripts/macros/set_caddaadr.tz +exprvCE6JDXrzEfZuxTQzSgxWXtxX5GoNxvidL84CN2TAm6Hk3kuK6 michelson_test_scripts/macros/take_my_money.tz +exprunGqZLZZwm9mY31NFGbBemCgXGevYqLRKdeRKQArPf824Npnni michelson_test_scripts/macros/unpair_macro.tz +expru6Roa34xofgoK2pnwz1gUNUiPX8qugbPeXn9Lyh8kD3zJNYvim michelson_test_scripts/mini_scenarios/999_constant.tz +expruwYQvEdTgNzbm3228Xp6srt9FbG2v7w2F8yVH7BCK1P2NJTJUi michelson_test_scripts/mini_scenarios/add_clear_tickets_015.tz +expruz2R676Zvnc8cnu3nF28w8mc2gwGbCdNDmyLc2BfpsgaVQHteF michelson_test_scripts/mini_scenarios/always_fails.tz +exprufRUAYF6r5QHQvK8CzWkKQcdvYkPx5fjEYzWPXc35Dry77KDT1 michelson_test_scripts/mini_scenarios/authentication.tz +exprtqebvyM9AjhRMT2WRMo1yiuScCwMf4VLjBdhJFig1ERW7knouj michelson_test_scripts/mini_scenarios/big_map_all.tz +exprtjdvZr5J7WfN4SyNgKueLnxX4fALUYJ4cmi675EHJdUu5yyg2n michelson_test_scripts/mini_scenarios/big_map_entrypoints.tz +exprtfWRfK4RoY8CF9VXvcHeBxizfjMMPAkLojfUTuoZkMSyiPKoyK michelson_test_scripts/mini_scenarios/big_map_magic.tz +expruRE8G1Qc1dU8ZeQCTA48D69uPv8hpZYtDiKKHbfiy1mQLno8nx michelson_test_scripts/mini_scenarios/big_map_read.tz +exprtotUpA2o34SHPX7ZQHD69WvJyEykTvPJ8T3RFErKAq4TQHFAgP michelson_test_scripts/mini_scenarios/big_map_store.tz +exprtbeKR4fc2tqCWahuCeXAb42Hpye5dwmq8sj2guSztorTFJnh1J michelson_test_scripts/mini_scenarios/big_map_write.tz +exprvMZ59ZHwL8JHywsDMt51uUNCJub3nrhgciCyCh57FgZRVAHUCk michelson_test_scripts/mini_scenarios/cache_consistency.tz +exprtywgtRD1K7PCc7Bgvo3BhdbnStcdQd5JVk8r1BKBsH6ULXcwN1 michelson_test_scripts/mini_scenarios/check_signature.tz +expruQ3eniBy4BdEnCBNeTB9qQApVnBNnfqpnVw9iWgSBAHpBqaFqV michelson_test_scripts/mini_scenarios/constant_entrypoints.tz +expruaYHJwQ2NNRV8iUu9iXZ4AhE4conKnkwkaEYtX8BhngWkgLuqW michelson_test_scripts/mini_scenarios/constant_unit.tz +exprvTRcwMZnUPdSeRG8DdiC2xH3DrfMbp8qCwg76Av4pqbX5k4tHw michelson_test_scripts/mini_scenarios/create_contract.tz +exprubRYeqf14u8CU4cEri2RWBrx26gkxyGe5wGeVAf4PDjKdsNhLK michelson_test_scripts/mini_scenarios/create_contract_simple.tz +exprvLDpqaNLp1Cb8hbCqRU6tyU53n9PQkixgcBwFdSLJWsUdwhCQU michelson_test_scripts/mini_scenarios/default_account.tz +exprunMD4kfFx3QbgjyS3VHm6Sy63Km4P4XZiJz3PtZkaZNe2zcmd9 michelson_test_scripts/mini_scenarios/emit_events.tz +expruaNoYRNTQxG5yujhHLetzS68ppQ38MFyi2ZhzNs5WNFv3wBAHG michelson_test_scripts/mini_scenarios/execution_order_appender.tz +exprv6GXw7FheWdWKfY5oxtkB1AcqWkpKQDq4w7rxYFvwypZQijymK michelson_test_scripts/mini_scenarios/execution_order_caller.tz +exprvSqfUw3oLZmQDwys8V5Qn9K1RAgMDGxdUUxzx1wpnyif3uSZG8 michelson_test_scripts/mini_scenarios/execution_order_storer.tz +expruhMQvp6kKepaVGL8EEMPPk6zY1uyyW22Ugrr4ty21dtjDcVdbq michelson_test_scripts/mini_scenarios/fa12_reference.tz +exprutp2rbqbAjUxgneVRzRxv7ppTEvKdA6tNAeDDnGN1zsftskUQQ michelson_test_scripts/mini_scenarios/fail_on_false.tz +exprub9UzpxmhedNQnsv1J1DazWGJnj1dLhtG1fxkUoWSdFLBGLqJ4 michelson_test_scripts/mini_scenarios/generic_multisig.tz +exprvTVuhJ2wNH8LHYEUiNC6ugx264rdfka1HkGfdVxV5632GjqgNv michelson_test_scripts/mini_scenarios/groth16.tz +expru1u3Ta2uCGgcz6Z86K2mA5ierGB9RMaSwSppzVFxeuiXpBFZrf michelson_test_scripts/mini_scenarios/hardlimit.tz +expruYCY8RiqSCiWarxVgha3fCWqbZTzMVtf4cFSrvB7J6kxZW3DAH michelson_test_scripts/mini_scenarios/large_error.tz +expru362itxUvgRTAaaRaZiRsB2jMV7sv4WzcGPQtzp7z44rp7AdZe michelson_test_scripts/mini_scenarios/large_flat_contract.tz +expru23Uo5EJQEDVWx2JViKwosQ2Ri9ysY9CkftfB8X5D9qh3KRRPJ michelson_test_scripts/mini_scenarios/large_str_id.tz +exprutz4BVGJ3Qms6qjmqvUF8sEk27H1cfqhRT17qpTdhEs5hEjbWm michelson_test_scripts/mini_scenarios/legacy_multisig.tz +exprvRy1WUs7SQaNJm478UQHzz8uJAQoWT3bR5TXSnmbxWAcpZdGKu michelson_test_scripts/mini_scenarios/lockup.tz +exprtaZK3uo7KJ5WK96o6vR9atAPqFGnq6ew23Jwve6VFYy3kAmiDQ michelson_test_scripts/mini_scenarios/loop.tz +exprufAK15C2FCbxGLCEVXFe26p3eQdYuwZRk1morJUwy9NBUmEZVB michelson_test_scripts/mini_scenarios/lqt_fa12.mligo.tz +expruBi6wgss7SRmpBCseBzcu3L283Jfx2CpUjgfuT2MgsozUsvBwt michelson_test_scripts/mini_scenarios/multiple_en2.tz +exprtgxcdQP1EVvEYN2BHjbqTvwzywuYAdCmnfVgeP9zcgkxUrmScN michelson_test_scripts/mini_scenarios/multiple_entrypoints_counter.tz +exprtw9v7A9CwKaNKQFVYuwtYbSkcnMWHeV2T4bMY71P31pgrf7v7M michelson_test_scripts/mini_scenarios/multisig_dest_entrypoint.tz +exprusoefPk2e7L24cikJeYJPb6EfMKwcmHXWRYmUDZ38s9FRjyQUt michelson_test_scripts/mini_scenarios/multisig_dest_entrypoint_arg.tz +exprtqmA1RUirUeuGYz9aUFyg161DjfMXPjxtrA6Jrq2dTs59j3Ft4 michelson_test_scripts/mini_scenarios/nat_id.tz +exprui72n1Jur5Px5ESXgxiF9Uw86DsoXPt1edGDpSv4CvnuPCtBPR michelson_test_scripts/mini_scenarios/noop_bytes.tz +exprtzYM9ERr612k6ZBwGFJYHYcFbrG44y3KsanKg6Rz5VtEV7vUZK michelson_test_scripts/mini_scenarios/originate_contract.tz +exprucgYdABPRbbq2yy2rpyt4Z8fv7PN4yhkch3QYZ5QQ5ehbtNA4K michelson_test_scripts/mini_scenarios/parameterized_multisig.tz +exprvEkEGDttTD4uzRXGtJ9Usq98M9Y27B8wjrSD4YkhsZ17kgEtyu michelson_test_scripts/mini_scenarios/parsable_contract.tz +expruyXnWo3aJfqo9Z6ycLDjyJygYCeH5JUrchAfFHZcvU1ebtDBXx michelson_test_scripts/mini_scenarios/receive_tickets_in_big_map.tz +exprvJ8zXaBkyXMhJ2eKtPwdwbg5NLrggvW8MEpVK3hk3nAe215PQ6 michelson_test_scripts/mini_scenarios/replay.tz +exprtuiYUMjM6d8XxPda1yfKeN61ko6riom35PzybC31NKXkVhgBQy michelson_test_scripts/mini_scenarios/reveal_signed_preimage.tz +exprvHREG4G45HEucJxKDgc97zKvtHSHH19EJNGJdTvTjPD4xVW64f michelson_test_scripts/mini_scenarios/sc_rollup_forward.tz +exprtjCFzmoU7Z5DAfA2NX69CdWG68wmgLUKgsNY4THyjBU4kofTF8 michelson_test_scripts/mini_scenarios/sc_rollup_mint_and_forward.tz +expruB4maBvk1y4JaeSLpDXWC3zKiXK5QFYv4B3R5KfdGEt4B5VvTT michelson_test_scripts/mini_scenarios/self_address_receiver.tz +exprvTG7hjtWXeogStj3pzM1MCVcNg1q6KnivqNVzQjviUrJvsjfQn michelson_test_scripts/mini_scenarios/self_address_sender.tz +exprtahxrrP8ovDPykXLtbNsHGKTA8BwAvcwKCZR9LZtomdEfMaRDP michelson_test_scripts/mini_scenarios/send_ticket_list_016.tz +expruPp2RQZWq4HoEZ8UzSeMc2C8WDFpd5KzwgvPYNubSjbGui7bHX michelson_test_scripts/mini_scenarios/send_ticket_list_multiple_016.tz +exprvLTHbFX1yKGLikbkxpUuXzu3zoKTh3Hveg1uFg9YBauQWWY8Ts michelson_test_scripts/mini_scenarios/send_tickets_from_storage_016.tz +expru6tUaVWpaR7D5invwY7inJnPZGPXTcDqFvirrHPMRxSeHki5Fz michelson_test_scripts/mini_scenarios/send_tickets_in_big_map_015.tz +expruZQmVUQpyeX1RJbTjGswm4L3xjH93Pbo1bwAgH3yqMCfPeb9BG michelson_test_scripts/mini_scenarios/smart_rollup_mint_and_deposit_ticket_016.tz +expruSijXeDKWECoCNHi9UBxX4HJ2UwdoRVKKeryux64D6hajHw555 michelson_test_scripts/mini_scenarios/smart_rollup_receive_tickets_016.tz +exprtZPsTsBtNf9hjv7Yfda2EV4Sz3iaHpk4NkYHcKteXbsyQ9d6pH michelson_test_scripts/mini_scenarios/str_id.tz +expruaFvFLsin2MWRuDkLRfe56pdPTUQ8RK9k1ks1rUTjBnwryPyPx michelson_test_scripts/mini_scenarios/ticket_builder_fungible.tz +expruMFhigCZpXrGaL5sMyjGw5k7CanAa7XRkHFemCoCwMfJFJjDuD michelson_test_scripts/mini_scenarios/ticket_builder_non_fungible.tz +exprthFU1n1xhXLi4D2G4andPJsLcem1g1UtKiKJjXkCfVHztC393b michelson_test_scripts/mini_scenarios/ticket_wallet_fungible.tz +expruoGtEJH3sXXm2ruNG6DGTFE3GM6fjAS6fzDZKtdaMnRzHvi3Xd michelson_test_scripts/mini_scenarios/ticket_wallet_non_fungible.tz +exprufmCT3yVRjmsPS9f8eX3ZAbbUhdmUccDMWgdtSNA1QRx1i1U2s michelson_test_scripts/mini_scenarios/tickets_015.tz +expruzkvr4K2JgDWJqjwT9B1epNG1aDDjmvh6UN2kmecs3d6yHPPAN michelson_test_scripts/mini_scenarios/tickets_bag_016.tz +exprteapARTC3TcgQgBLVei9HoTq28M5xLbaEjmBaiUt46ipgP2TEq michelson_test_scripts/mini_scenarios/tickets_bag_implicit_016.tz +exprthATKGK2oc4oVbEDM4TYgJ9wHRsgbP4QwdpgwaNbjvswCeP3iT michelson_test_scripts/mini_scenarios/tickets_blackhole_016.tz +expru3BvEZn3LQEeUGjADWtNsRomSDi7LumwBDZEPnqo7j6iTnC5G1 michelson_test_scripts/mini_scenarios/tickets_create_and_send_015.tz +exprutzAruVCL3YX7JEwZf6bJ9Tq4bj19vWR9S3wofjNFXga1LzQSd michelson_test_scripts/mini_scenarios/tickets_list_blackhole_016.tz +exprvRyB18cUg5GmD5fzdkozmBMJyRm6my9hCFMMXQA4UgEGF6rdcH michelson_test_scripts/mini_scenarios/tickets_mint_and_store_complex_param.tz +expruhv4oofRVia4jt9hoTcYyohmNPiFqHTGTAyquyWu6R24eRdbEu michelson_test_scripts/mini_scenarios/tickets_receive_and_store.tz +exprtfF4hinrA2UJXB12eDnXV2ZjGAXX5ADneq5ezkuVi3PJvVFwnN michelson_test_scripts/mini_scenarios/tickets_send_016.tz +expruTjbiyNePk21v9BsharZPaT7xLkTzwTU5aSeHya4pXqn2DTBz5 michelson_test_scripts/mini_scenarios/tickets_send_with_tez_016.tz +exprvRXkn5p6qw3T7mjBud9XCDsgDGmyZZzMRscNAkaG6F1CitPYgz michelson_test_scripts/mini_scenarios/tickets_store_fst_and_rely_snd.tz +exprtnBz8poqNTrK4rzTXZFKQx7HWpx4WidHB5wxcM2oTS8NcrkAUt michelson_test_scripts/mini_scenarios/tzip4_view.tz +exprvG3gj2DnewiiqoLMpo9g5bHLtbk9NgqinPgGezHnpfK8jqGsm3 michelson_test_scripts/mini_scenarios/very_small.tz +expruws94oEpYqUjzea9obsa9j5tF4wtccbAPnRaLHRkL7G2gWa6Y1 michelson_test_scripts/mini_scenarios/view_check_caller.tz +expruFec7jRXa5z5sdoYyr6RUK4Uw8xwgXHYQhDF39mciEdoyVgcX2 michelson_test_scripts/mini_scenarios/view_registers_callers.tz +expruBgdNVqgPu4YL7fzivE9BYu7vQvbuoe8V9XwqVbWj7p6M5egCj michelson_test_scripts/mini_scenarios/viewable.tz +exprugya6ngixBfjyxV28ffnC8jmJPi4vbJdqD1aVUx82YLhzbH8Tn michelson_test_scripts/mini_scenarios/vote_for_delegate.tz +expruaKedvXmhg6wbV361DHykomz5dPqLi473KxBwJwyicEnKMhpb9 michelson_test_scripts/mini_scenarios/weather_insurance.tz +exprv9PvyjnsPjPCg5f13WtBiuD3o6idDAVWU6QfPtdWMjCLGRpwTh michelson_test_scripts/mini_scenarios/xcat.tz +exprvKm5t6a6LL2d3HjvRiJumGrGei24aRXscJk3zB1hs516Ju4oMZ michelson_test_scripts/mini_scenarios/xcat_dapp.tz +exprucvy7NUDPu2yTWEA6WVsusEZgGRmU1WpVzrFnNZV7m2H8BVysF michelson_test_scripts/non_regression/262_bug.tz +exprumT8doqCpoTqPAuJa8dsnrC7giaz6aGnMkJDF9kg8j8mBEafAC michelson_test_scripts/non_regression/843_bug.tz +exprtyJrKmrcvMroXNvbNSJr4hrWcLqa6QHmKSSJLMNqe1nueq1MSt michelson_test_scripts/non_regression/bad_annot_contract.tz +exprv3FvpUYzomvhmzxsQyuR1katpswNnicQZB4jA5uec3MERXk1cB michelson_test_scripts/non_regression/pairk_annot.tz +exprujPzkrPVucSvhHc1d9xm6kcs7oggkQyJXN8L2Rj3fteEABAkTe michelson_test_scripts/opcodes/abs.tz +expruNtqq51Lm75X61pxUx7P2FyR2uyUKLsZNHMXWx6X5rsyJ5M6WX michelson_test_scripts/opcodes/add.tz +exprupWD554EpqFBjo4KUpTqrfQcJAHqr3ijKmv5cmLRJ93Q1SgwGX michelson_test_scripts/opcodes/add_bls12_381_fr.tz +exprugu3H5MPrpWJRZMPMGDM3Dbvykaa1fHejEvYr7ePKaLtahjQV5 michelson_test_scripts/opcodes/add_bls12_381_g1.tz +expru41eYPF7gPvBRAtantBxbFU75RqBEwHPZ7UeX2EgHmExRoA4dh michelson_test_scripts/opcodes/add_bls12_381_g2.tz +exprtcPYR7TZHxzcpmZWjjLgMWp6CeRWAxQ5Bt2bgpUK5uKjmNAdzL michelson_test_scripts/opcodes/add_delta_timestamp.tz +expruLFQ1mcR5sg9sqyFHThknANoBeL4C5HFGgH55MqwPBEb1TUxLt michelson_test_scripts/opcodes/add_timestamp_delta.tz +exprtz1uUW5sVUVaKNLhPaKGjA7jK9JmzWBCQu5Xn1MC3aS1FjTUmK michelson_test_scripts/opcodes/address.tz +expruskF2nSeJeBaVHZsp45yN7mer9a4f8fAUBYvU3oRzbmpm5cVmt michelson_test_scripts/opcodes/amount_after_fib_view.tz +exprucSgNGh1wkijmUcjLdifceE7GeMdLnxL3JZKpbxAmzF41ALo91 michelson_test_scripts/opcodes/amount_after_nonexistent_view.tz +expruUQ1z6YqZM1baKofNLYhK9nocp9puAXCo4MYzEkQPbQcXTnajq michelson_test_scripts/opcodes/amount_after_view.tz +exprvJ4NRS33cboLuTx58f3sbYpXf1m7Cq2ou9gpCh1k8foaCZAoas michelson_test_scripts/opcodes/and.tz +expru5BXwmdpWQ3WDKA24g6gYGwLxPc868wKkdeAaGh899nD77Uxwn michelson_test_scripts/opcodes/and_binary.tz +expruthG9mteYkv8qKgRq13VjZTvbjtJYt1HmQg8HktkvjCvKZgdhR michelson_test_scripts/opcodes/and_bytes_016.tz +expruL6aKRTXN2hWb9EXLuJASu7nuBGJxL7VyT1oEjX9b2s3u6Y5Ff michelson_test_scripts/opcodes/and_logical_1.tz +exprtpYYuLewZWKCK1aPb9gfYSiPWSaeXRM4P2e4rpa6UktVueB1uf michelson_test_scripts/opcodes/balance.tz +expruWVQymVzetzkRaBYh4thmdWCvzWZNqdGrCTinGxLn58rPXDkgC michelson_test_scripts/opcodes/balance_after_fib_view.tz +exprukgm7LHJiEywzSseHXp23nXM5Y9GfJ61ULij58BgRQ4nt3bYYT michelson_test_scripts/opcodes/balance_after_nonexistent_view.tz +expruggCnM7PeEcUr2BapBmFMhD1QGvEoM4dUfyxp2u64ic1fM9SYN michelson_test_scripts/opcodes/balance_after_view.tz +exprtZRAy4QHqpF8c3CusD6e1kxWA3KAUrmgeXndfQYSEGArDmkWUm michelson_test_scripts/opcodes/big_map_mem_nat.tz +exprugsT35M51mCw6Fim3ysNKpCh8JyW9m7CYW65QQ7XUEDmspqz2i michelson_test_scripts/opcodes/big_map_mem_string.tz +exprvN3tk4o5YPYJB6aYAxEx8KU93yNSaw4K6mbEZZh9RQayua6odv michelson_test_scripts/opcodes/big_map_to_self.tz +exprv712JoEC7RRhoP7gbTUiVgLbtAgHmenwa5TqhVykDZ3e538MGU michelson_test_scripts/opcodes/bls12_381_fr_push_bytes_not_padded.tz +exprufF1yaR5QHdy8iECBLjhBtDZVLiEjZRuJntSkXjsrJRYozXLmW michelson_test_scripts/opcodes/bls12_381_fr_push_nat.tz +expruSVRATSSsbfHowLHGs5XHms95RuqBWSdDJoUKdns3fWbwasU1p michelson_test_scripts/opcodes/bls12_381_fr_to_int.tz +exprvTBYxSJ7d1z1aZvvAgPrdZUXHzoFxkwBC7McES5BS56xvqkGXg michelson_test_scripts/opcodes/bls12_381_fr_to_mutez.tz +expruTppbXBm1YHSCB4uYv9MQs6zxqRWqbkwGWoiKfF5Sjj5n2TpJx michelson_test_scripts/opcodes/bls12_381_fr_z_int.tz +exprv5Si29PfXErNuJdEvJWQhWRJ3qPETygaWzRE3ctmCU4s6y2V9v michelson_test_scripts/opcodes/bls12_381_fr_z_nat.tz +expruRsYz6JopAFGU95WfFU61SE3RbMGn3XPR9PFiTfLbgQr2kzu7u michelson_test_scripts/opcodes/bls12_381_z_fr_int.tz +expruyE3E3o8EAptRBZtQAB5Kv3sxUZGv7DK6CpJ2YdotQj9gqW5wN michelson_test_scripts/opcodes/bls12_381_z_fr_nat.tz +exprui72n1Jur5Px5ESXgxiF9Uw86DsoXPt1edGDpSv4CvnuPCtBPR michelson_test_scripts/opcodes/bytes.tz +expruxed4mBnPkdz81bZmzgQ6wFEEdKZqFazTkD9cTGWAuHAB2HTfA michelson_test_scripts/opcodes/bytes_of_int_016.tz +exprue485QnZ1W1ctgYRzPCy3pAcQmUAkAGGp6StowguHVCqMCVo7E michelson_test_scripts/opcodes/bytes_of_nat_016.tz +exprtvRRYmpToi9y67ZzNmgjtdrgNkwVduSnBi7GZVrsmgDna8TSjB michelson_test_scripts/opcodes/car.tz +expru5dDnxp1rhgXGmKigbLJ9ASaVHbkpkL6gLggtk9krgYC3jusc8 michelson_test_scripts/opcodes/cdr.tz +expruxH6gEuBmNzg5nWEM4tv3jMBbknbEtTHKTPMeC4EBdFdujbRph michelson_test_scripts/opcodes/chain_id.tz +expruGhHABGLz2wxAyyx3RpfyKHa8HE9voC19vLiAKYWYMMsUUTFdd michelson_test_scripts/opcodes/chain_id_store.tz +exprtjDuLEzh8dcjpCcJiiuKXDdG3XusjuuURVCh3JWKBgjJGsVsMs michelson_test_scripts/opcodes/check_signature.tz +expruHKTiWeY6mty7RokwdyZdwdzHQbu7udbbZbpu3C8h9n6jXnp4v michelson_test_scripts/opcodes/comb-get.tz +exprtsyJo5ceZQM76zpAUeTren1YnBxw2MNDKmx8k11Ejai8T296Sg michelson_test_scripts/opcodes/comb-literals.tz +exprv733yfMh1C9uyuAJJP66WPQDXAjjfcTcSfHhbboJnz6DUCEh41 michelson_test_scripts/opcodes/comb-set-2.tz +exprvHamsTHMJKF6ohaSAwdgp2Sv33LGgYnjase3LUcwXKnJfh53wn michelson_test_scripts/opcodes/comb-set.tz +expruufsxtik2vxyQfL3QKNWWH9TnJZgGx1ELi3AR5L3LM71uqxiP4 michelson_test_scripts/opcodes/comb.tz +expruKknV6VYzPHkSxc3EFb488JPBfUX1UHsJUzceaGFafdnbgsKw2 michelson_test_scripts/opcodes/compare.tz +exprvGXTYwatNh32w78r83SuLAW1YQefufYN1Bcu9AZ1BLDUU77dKR michelson_test_scripts/opcodes/compare_big_type.tz +expruR3ZCLJTuojpTuS2sR3SGxqait52kXQNKfy8bipv69b2XJZG8A michelson_test_scripts/opcodes/compare_big_type2.tz +expruUDL3EP43hFhcdCZD7K1xvfPtiNWfkU2Nyq8jmr9XgZuXqWXc5 michelson_test_scripts/opcodes/comparisons.tz +exprtjqEmEBnmG7yiDXn224ER9bt4qh18LF4LzFSfoeuo1cbJpNBPy michelson_test_scripts/opcodes/concat_hello.tz +exprtqd5qPLeh5Fi52YdkgWuvRXctgUoxU1Q4JDB2VseRk6DAEpMvd michelson_test_scripts/opcodes/concat_hello_bytes.tz +expruv8MHvRmp3ipXYRyyP4aEE4iFHWsNZjNQSaCWUt7fwbgLeFBXY michelson_test_scripts/opcodes/concat_list.tz +expruYk7GXYQ7bKbUcqcHDKs97USVBrxAkzSo2Bkj5AXVjSawDkNAS michelson_test_scripts/opcodes/cons.tz +expruMW9W9kkb2JaQWzKVThky4ULQ6ckgLzE2xD49XUp5E1iwWfUbe michelson_test_scripts/opcodes/contains_all.tz +exprvDvotLP1G2qjPJiqz2RvVUm8wJ2cEuFvKtm7YUNW3w6krDponF michelson_test_scripts/opcodes/contract.tz +exprvNrgGoLvfEaXw6QmjQrkXESpWo72JHR4G4mhTJy7Y266YXa3fe michelson_test_scripts/opcodes/create_contract.tz +exprttdxhC3YwJ9SGJNTDMQRpyWX1KwqAUuPbkQHX3uMPHNt3GKkZK michelson_test_scripts/opcodes/create_contract_rootname.tz +exprttdxhC3YwJ9SGJNTDMQRpyWX1KwqAUuPbkQHX3uMPHNt3GKkZK michelson_test_scripts/opcodes/create_contract_rootname_alt.tz +expruxUAUoijmC6A4rZK9XHcQL4WmgreJwT17hrgpuYkg1VeELBdbF michelson_test_scripts/opcodes/create_contract_with_view.tz +exprteqmco8PDGH1PnTGgF5jPjBPCYyZfyvER2ULtv2y3MRgGdcP8T michelson_test_scripts/opcodes/diff_timestamps.tz +exprtt6joHWnYr4AAW3uem8nzbxYgLcSpEJtaUT66qWchoKPS8sFXx michelson_test_scripts/opcodes/dig_eq.tz +exprvKBfwAg4hVHrTtq3UV8AunaqUKxAkvx35TScbZDARNSgH737Ck michelson_test_scripts/opcodes/dign.tz +exprv8t3ZfoBs6B7LMeFNN6U4PRpE1M6MhdtKPT5keNZT4je3RBadj michelson_test_scripts/opcodes/dip.tz +expruncwh1qqNqSwq6kHYXfwhQyjpuJjbernTsyHAMnaLjU5h3qjxr michelson_test_scripts/opcodes/dipn.tz +exprv62zo2ACMdseAu1HKzDDLSjBrYr2nZzi36PCTVJqcBwSdvt4yU michelson_test_scripts/opcodes/dropn.tz +exprujbvaRkoroj5eVgboUyeP3578oJgScTQ78eBYMgfdLVaGWPPTW michelson_test_scripts/opcodes/dugn.tz +exprur99uFkrwM63FXSTqSTypHcfEmzb5KQ9EypTRqZWDY5NP6tCHL michelson_test_scripts/opcodes/dup-n.tz +exprtarW6tiguR7YAo6SxhCUDs1pLDhx9xJEG78h6GnXLAWpt3H1pT michelson_test_scripts/opcodes/ediv.tz +exprvQhRaLYxiWN3QsJgT6VKf6DmGVuXR8DxeU63P9A8iNWA4TVQfs michelson_test_scripts/opcodes/ediv_mutez.tz +exprtuM993oiKiYWoztZwpAaUuvDDcx9xDX31Q88kpuo7owk6Q8JeR michelson_test_scripts/opcodes/emit.tz +exprv8Sy3DsiKMm3ZQPmi46kZGn9ctTigpLB2t6xYFdYkkeVHMXy6z michelson_test_scripts/opcodes/empty_map.tz +exprufqf2G8PoZN768K2YGex6M7zmz7bYHE5LF5QHJBVvFtAFLi6qr michelson_test_scripts/opcodes/exec_concat.tz +exprucYyrHMR3wgJLwFq1o6GPuByry7sroRiBPrt58fz3dRSRSzC3S michelson_test_scripts/opcodes/fact.tz +exprut53jocMPdPP8FXrKRDYSoRaxk1FXqCt7o46ak2wQaocjsSwwx michelson_test_scripts/opcodes/first.tz +expru5fjTGWP1BXZz3BbbEFyDFkyZGJKHcZ2Y6jDT3CdHHp81n6G1r michelson_test_scripts/opcodes/get_and_update_big_map.tz +exprua5oh3PDJEPQbEsnbHYCz6L7bY6kNvpyhEt7Cg9sPsrx82UmHQ michelson_test_scripts/opcodes/get_and_update_map.tz +exprtgnkjSH6Tdw5C1BMKr8kCJjEnxCfMiaAxHTVLnEcyCQ6WmJ1jr michelson_test_scripts/opcodes/get_big_map_value.tz +expruv8JdHeURNpuLHao37SGJauDPwB9yxFXUaL6hNCdXGzbHSqCZN michelson_test_scripts/opcodes/get_map_value.tz +exprvHC1MDkeqCNL8yrN74nmqk5qrZCvR42qoVUxYCB4ALpgDfmhbL michelson_test_scripts/opcodes/hash_consistency_checker.tz +expruzeve85eDLTpQ1EbgrQQcEUft7AGauZBwtK1ibuvJpwmZt9AE8 michelson_test_scripts/opcodes/hash_key.tz +expruycqvZn4ufKjVQmYXcCfAfm7C81zN3BAqxuYVVfnpFibSKsahG michelson_test_scripts/opcodes/hash_string.tz +expru34ooMhYSarFg7vZCe1Y23jwfxfHiDqwaE1wGXC48yjB21PLi1 michelson_test_scripts/opcodes/if.tz +exprtmbKAmbV2XioTbmpJQpg9QDAxXkTBXmKRWdC8zbk8CWAtVXwAc michelson_test_scripts/opcodes/if_some.tz +expruTGRZeiojz3Rrr45KUcwtpJuJYu6U8pxi4DBZpL2kGavVxxM4H michelson_test_scripts/opcodes/int.tz +exprtu4Xbe67UZyTubEtKx83bMyQGXDwBibcdgLF5hftZYTEL2kSst michelson_test_scripts/opcodes/iter_fail.tz +exprudLYgw6yWSrTHpXYsg9NcZxGGpCxdNFbNv7ksr6Ss8rNmh2fgT michelson_test_scripts/opcodes/keccak.tz +exprusrBf5Sakr6dRngzuPmwsP28X6W56nVqCXqG1Jcfrd1SYwPRuU michelson_test_scripts/opcodes/left_right.tz +exprvHZpmtBKjjsUZmchx2RTLmFAZnYKCnHSKXaKUdP5EUpiPYwsp2 michelson_test_scripts/opcodes/level.tz +exprtkasRZbYRQg7WKnoXwJnRwXkvmjZEY4yPYXKGAQQFUupt5VAmt michelson_test_scripts/opcodes/list_concat.tz +expru32VE4LnqAqhbpUFCdgEdRSHjLQipkXTjn624fL41yk3a4H5Q3 michelson_test_scripts/opcodes/list_concat_bytes.tz +exprvCkexzSQFgEWkFvrkrQ8wATasfkbKCyeXYSM4qZft3g3UuoTBi michelson_test_scripts/opcodes/list_id.tz +exprtbHaLLF4cUTh4VCjtnH32EAA2AFwvPBsCzUTgrrdofbotKMyr7 michelson_test_scripts/opcodes/list_id_map.tz +expruAxpePKSFaGkjukWx4HEZAvXaWvyfyGyxCfhvK9tZjkPNSpZ1m michelson_test_scripts/opcodes/list_iter.tz +exprvSCwmQGBkxgu2Tg5rYUXbyv33SpUskCJS7sPF4LN7e5pQ1fn7z michelson_test_scripts/opcodes/list_map_block.tz +expruu6vcnLhDhSkSo8NNNJWQL99VCFr6iArtKrmavJWSNkQwDJsKC michelson_test_scripts/opcodes/list_size.tz +expru8Et3hTjxKQpydKSThjR6fXSmPEmZDjBTNhTAbuyNjcPYoUQUL michelson_test_scripts/opcodes/loop_failwith.tz +exprv15pFChKhH3QKoJn5BCT1bP4R7DjnXWtTDsSfwf2eVonZNxzZs michelson_test_scripts/opcodes/loop_left.tz +expruAKUrHWCxb3qtVQ1a8qDzrS19HnTm7bS146AztFHekvpqbehaU michelson_test_scripts/opcodes/loop_left_failwith.tz +exprtch5jHa718ipv2f28nbAQzQxk5LneyayirKxTBf8Q4gtS1XNGo michelson_test_scripts/opcodes/lsl_bytes_016.tz +expruaRKkzMwKE6uDBPyUZ2u9nfKo1HenCVQLkBvevtteAxh7ey3w2 michelson_test_scripts/opcodes/lsr_bytes_016.tz +exprubosuA8peKBt4EEo1RsYjxSxK7HXytSkBFAjns5Zg7ncicPWrC michelson_test_scripts/opcodes/map_car.tz +expruqCpEBS2R8FqpBfDNUNrPhXZr39CBL6zKpyMogJR94sve62iv9 michelson_test_scripts/opcodes/map_id.tz +exprtb1QBmNfCYjce9FnvKdikbtgqcN5o2VdVwZZP2Fmy8C3TJjA7q michelson_test_scripts/opcodes/map_iter.tz +exprtuspLRSrYnp2FyqNcLfsBrBBFD8nnFog2Em3p7tfG4DcGujS3f michelson_test_scripts/opcodes/map_map.tz +exprtipeMFcMFwYRAmzZBMoUjrtPYDk5ZyhMSyuhSgfiJV5UNAcLGp michelson_test_scripts/opcodes/map_map_sideeffect.tz +exprtc9HPyzpfc71TE4a8UbRPxfdm4WGRPNQhfB5fHiWwkh1aA8uzm michelson_test_scripts/opcodes/map_mem_nat.tz +exprtrkfCSUckShrEP5TmC5Y4CdeU35FFL7R8kyJHQUFZ4DNdJZasD michelson_test_scripts/opcodes/map_mem_string.tz +expruqncptpX6oXeX88mAkVHh9DnzWb6vPwT6LvuND9yobgcH5Gd2x michelson_test_scripts/opcodes/map_size.tz +expruZ7Tb7uhcAu3MhiDJFWrJiYseWyagZYEnzjEdpjSei8i73hsfG michelson_test_scripts/opcodes/merge_comparable_pairs.tz +exprvNxEfUTwaryUzets4qyTbHAfNPb5ARQsMsxbm8CnGNHDedqxgy michelson_test_scripts/opcodes/mul.tz +exprtYi1xHmB1AY6j4e3XTPvXpmuWnM4b4o78yVihYt1i2yNjrQqhY michelson_test_scripts/opcodes/mul_bls12_381_fr.tz +expruFTKqYqMmWSakzE1gjs2p8kWtcRWTaddkYL5p2Z8wpcCfe5ei1 michelson_test_scripts/opcodes/mul_bls12_381_g1.tz +exprvBDM3kep2f7bRkhRa2XWt9sdPGJ79sq6TdWNNnM4yydTQ88TaH michelson_test_scripts/opcodes/mul_bls12_381_g2.tz +exprujbPsZAUa1tzgWNgeHEQ22JXDfNhkgx6sCCxbWjYoNWPbTvwhy michelson_test_scripts/opcodes/mul_overflow.tz +exprth31LKm5FDFGxcXg1Rv9z9YeAQ8eu2oYTh2zZ7kJas3f5CWkZm michelson_test_scripts/opcodes/munch.tz +expruP5gECQdRLkmuYg8xqvEAdE4oRGFjDVG3ZkWxtCyxve1jviw6k michelson_test_scripts/opcodes/mutez_to_bls12_381_fr.tz +exprtw9PgkJCxyqdLjuA4dEdRjQXY7Ge4a7jjd2UoU6Q6KrvhFgciM michelson_test_scripts/opcodes/neg.tz +expru5fYi1tAG8a9j2dYT561dXaox8wYjsZDZP18xPa5JN3bUNfHWS michelson_test_scripts/opcodes/neg_bls12_381_fr.tz +expruY94PxNhmT8BeyGrFurRF6gC7XfgsBY9Vjh6hJyiDPaR8nFmri michelson_test_scripts/opcodes/neg_bls12_381_g1.tz +exprv9bM4xnqjA33RkvUzz8ZppJXT32KdNXoYqY2NSh7whBcFPn2QS michelson_test_scripts/opcodes/neg_bls12_381_g2.tz +expruZzA96Rh5o6HBboygY3iD97dgQcepXd45WBBD4DYZ2qcn8cxyY michelson_test_scripts/opcodes/none.tz +expruat2BS4KCwn9kbopeX1ZwxtrtJbyFhpnpnG6A5KdCBCwHNsdod michelson_test_scripts/opcodes/noop.tz +expruMUpBKBPGde4GfNLM8NgMq9nL6KsQXGA3LPt4C6wtMTxcUnE9A michelson_test_scripts/opcodes/not.tz +exprtnpHGyp2TurQb2YzbXBKTipXnrUQ4RrZwPxWfa1yMXS7oi49jV michelson_test_scripts/opcodes/not_binary.tz +exprtr3AhRfBVUibP5MtbenGDTEasfxSJAFsuYgkjmLqfpHnDahfWz michelson_test_scripts/opcodes/not_bytes_016.tz +exprusKUuYeoKXUAYtUhtknryT9MpbPZVZtbfUNCdRpXUbdzEzbwmN michelson_test_scripts/opcodes/or.tz +exprvG84juZWwLHTrhtvWFWBs8D2wZw6rfpoAbXp2pkekuCMAaPbAn michelson_test_scripts/opcodes/or_binary.tz +exprvN5DmSbMk2JQ9nNSEakbicPj4vfGP4N4iWo3yabNAFvqNxCAkq michelson_test_scripts/opcodes/or_bytes_016.tz +exprv39cZxxm6fTcFSbLcwpBbAPW56FPqjdf6aGm21KqGA6DQtwn6u michelson_test_scripts/opcodes/originate_big_map.tz +exprunveMvzjDskHYCvYJzDfRR9aGwwvXkVUMqTwSxJJbEjeq63c2D michelson_test_scripts/opcodes/packunpack.tz +expruKkmmajE1UFXRHXtntLZU8VvnLfFKwYPd4azsAdcrDMaq5zu9H michelson_test_scripts/opcodes/packunpack_rev.tz +exprtk9p4ur3KZK2w8ziFoZVHPABxQWZXeSNowcJuTauL3zTxr1zcH michelson_test_scripts/opcodes/packunpack_rev_cty.tz +expruSamDrL2Dh4zp92cVgfV7ETT7VcnqACDVcvnafi3qgBZq9v3PL michelson_test_scripts/opcodes/pair_id.tz +expru3WFEX5bVjBUkZzuWspLG18hy5jTzbr2WtKEYpfPHGpDFvcqhd michelson_test_scripts/opcodes/pairing_check.tz +expru2U5Bi7ehgkQvP7Qmij4c8gkSFUBNtiCyXMX3WwGjEdRRZc5x1 michelson_test_scripts/opcodes/pexec.tz +expruPr8QtATywJFqPjDhF7gyqdF15L6J7pxgpypzorEvtubdJN8U2 michelson_test_scripts/opcodes/pexec_2.tz +exprvBUenyTMJKwERZ1ULzMVrJ1owqymBF32f627arqtFUzMpaMvbC michelson_test_scripts/opcodes/proxy.tz +exprvPaPcYHvKmnyBMaYXtp6ZuaSEHWr5y92bcroKKppAZvF4RvcWE michelson_test_scripts/opcodes/ret_int.tz +expru8MKLXqiNRYnPccUN4if3VnWfthDy24K4zuJrFh2JaMmmh6Rii michelson_test_scripts/opcodes/reverse.tz +expruta4Bjo3FggDcvZDzEVwzeTcdZptzkJZyFEkdB8suFGbMVtT2Z michelson_test_scripts/opcodes/reverse_loop.tz +exprueR2MPCHUFtPjMZXE57X3EsysuWJXGRz8ZgcPJj21UySLqULV1 michelson_test_scripts/opcodes/sapling_empty_state.tz +exprvSNMswzVUk47vqs4wTGipDb3qDKVUwNBDwXtGzjCprEYx4nWPo michelson_test_scripts/opcodes/self.tz +exprtzokY2FHvPvB9YHSi8MM5YUbPdUPLi7tEKkp8BKongPb2zrZch michelson_test_scripts/opcodes/self_address.tz +exprukm3NvsYbS9ymX3MuXh6LciuF8ef2qt8ktTGaXtyFxCpisMBdD michelson_test_scripts/opcodes/self_address_after_fib_view.tz +expruV4HCC6sRdEL5HyXVC9gTkMZbh8BnxXsKZDTydtztRhDUT3qxa michelson_test_scripts/opcodes/self_address_after_nonexistent_view.tz +expruUWxiqrD566farETUi3VChWNZ5teemC3q4G8tf83xhjTwRSEws michelson_test_scripts/opcodes/self_address_after_view.tz +exprvQ8rhMFcCrwNSLZERQSQ9TMR1Tsnyj7R1jS8J2UESKXUoJuLTV michelson_test_scripts/opcodes/self_after_fib_view.tz +exprvKoMUnUmthGpVmQfYkLa8F6GRwmU36D9jYXNG8j8QbQYNWUoAC michelson_test_scripts/opcodes/self_after_nonexistent_view.tz +exprtXqpN6sqTKUVNissE3rkzKGSBuW2gTh8pRb3XyHZ4dpaAqLnhL michelson_test_scripts/opcodes/self_after_view.tz +exprvDVUQXNsfs9FiHkMSofonWCWcBfYbfxeQy9DRaa5Tnbw1XM18Y michelson_test_scripts/opcodes/self_with_default_entrypoint.tz +expruXGf2YpXKkr74mcv83fQ6bztVD1RBoFXaEnAd9bidnRXcfD3Nj michelson_test_scripts/opcodes/self_with_entrypoint.tz +exprudmJ37Q8ZASPbZSSBfy5UezxLhniszTVkLAB8QKvxkav4gVVYr michelson_test_scripts/opcodes/sender.tz +exprtufbuVP6RKm1PGPUQnZy6dqwxCha1jbafqyVGpCUNWeUVpcBhc michelson_test_scripts/opcodes/sender_after_fib_view.tz +exprug4Jd1WdLqrZWiG8PsGDETN1ahpX5PycBrdNWadM96M5SjvLae michelson_test_scripts/opcodes/sender_after_nonexistent_view.tz +exprvR3pRxvwuwM1c4Jk1zRfuDabRPwLnazpSsySQkzymatANufH9h michelson_test_scripts/opcodes/sender_after_view.tz +exprurSxmHBRCHUxtXcqNkPA8UE6gaFeJa19bBhq1CarZ3CZuAzShs michelson_test_scripts/opcodes/set_car.tz +expruogQk6tG5W7CtZrcMzsRtJ1f9moG9y5Qg5j29NATiaSywvQCcS michelson_test_scripts/opcodes/set_cdr.tz +exprvCt5LtbC3mLLWHdvyxGcX3ND21Ym5GayCvePEHHGXAtgWu32sJ michelson_test_scripts/opcodes/set_delegate.tz +expru133Wm63xA1qs5ymovjbP3N3iwPoTMcdUsbUqqbTf896jU78WR michelson_test_scripts/opcodes/set_id.tz +expru151wgMY5reA7WVbnvkHrh9MVnfYFbCDaiE2aTGmkKACu2ZbJA michelson_test_scripts/opcodes/set_iter.tz +expru13v2dm35MgMgTbwDJ4nEwNjRTau8mqztAyxGxXVbHNmskAA2q michelson_test_scripts/opcodes/set_member.tz +expruE8c9EzG6kYQdp5RQXrAt2CekSFXVtKUzNDUnpVTDygEBP7VvF michelson_test_scripts/opcodes/set_size.tz +exprtzSBcPatLYnGe5xtsSNGVjNBLMmHefxsQ7Q2QNjDMGmADKdWUC michelson_test_scripts/opcodes/sets.tz +exprteVcB53uqnwQsZMTsBojwez6tkgRqj1qWCQTLgaQWxQGiNWXEE michelson_test_scripts/opcodes/sha3.tz +exprvPbB5NtiV87RARduqoXtMoRjjy6jX8WYrfiu3RDjQrTKxPQnoe michelson_test_scripts/opcodes/shifts.tz +exprtnS2EjwJ3MdSWS7R6UbZMqFoUHj1JpUhhtJacXdfmmzRNHL33W michelson_test_scripts/opcodes/slice.tz +exprugZMQtZN7safMU7hV5QpM7nh7Vi5ur9sGjeWsmGRkW1ETox8uR michelson_test_scripts/opcodes/slice_bytes.tz +exprvCqvDAp66YnPaZDdaAkCNafoGtw1fEuWaLxMFeMnX6oqrb93nP michelson_test_scripts/opcodes/slices.tz +exprtzW4jh4MgY6iXgiCXft5q3Mig5XXANHn9CmcL8ApTrdnQgWzAm michelson_test_scripts/opcodes/source.tz +exprvD9HJMfLEUdamfH9U8ozBaxA7hYVRMbK7At6sUqFMmhZ6UorWv michelson_test_scripts/opcodes/split_bytes.tz +exprvJcmHwozD2DTtagjJJfyPgoCvBx5bMzXAkrsteYVvxeMr9SWm3 michelson_test_scripts/opcodes/split_string.tz +expruDY992zB37mWpZwFQCrfDbkwmrCmjSHD4fzQcW1z1AeWeW8M3r michelson_test_scripts/opcodes/store_bls12_381_fr.tz +expruZAkBxtwSXuMp6ZDNp41mJ6uZ4bw7RF9HNzJS9EnzTLxVhQ4SB michelson_test_scripts/opcodes/store_bls12_381_g1.tz +expruZfFC7WkBQhK4Ksg5k5WxBamF4PvH2NGCxcd4DHUkKfeqQEBUe michelson_test_scripts/opcodes/store_bls12_381_g2.tz +exprv8K6ceBpFH5SFjQm4BRYSLJCHQBFeQU6BFTdvQSRPaPkzdLyAL michelson_test_scripts/opcodes/store_input.tz +exprvStWRo24QuETruMmMqkmLme6UAMHuTRNNq9Lq65oFgUvQmJGPV michelson_test_scripts/opcodes/store_now.tz +exprtZPsTsBtNf9hjv7Yfda2EV4Sz3iaHpk4NkYHcKteXbsyQ9d6pH michelson_test_scripts/opcodes/str_id.tz +exprv4UZUuBDCZZjtW5kaezZjaKqpi1GN6vxHsvQNNkFktnaEbDb1M michelson_test_scripts/opcodes/sub_timestamp_delta.tz +expruVuXhQmoBMzZjPeY7VQSuJxefBBTuPyNR7PGnYhwouo9zKg3T1 michelson_test_scripts/opcodes/subset.tz +exprtz2jbsXuMMPAXYAGJZqjuBp8iF38XadE3YuZoC2W5NkyhhHMuq michelson_test_scripts/opcodes/tez_add_sub.tz +exprugbVFDGWcSSozyN3EK3AcdwtPeES3ao45HNogWc5V8fsJ8NsSP michelson_test_scripts/opcodes/ticket_bad.tz +expruwtzPEyCm4Vaq42Fct7QG5eD1MzXzkJbRqm6EVQH6YSV2QLkr1 michelson_test_scripts/opcodes/ticket_big_store.tz +expruqx789AMcKUYwDeeeRvSnwdCw8gMVvWA6vuzPzBQwBM2qcDXJB michelson_test_scripts/opcodes/ticket_join.tz +exprvMp1LX8aeyEq9NiMXGyD34J4offZDANGRwFTxoEWXumEsDdAP8 michelson_test_scripts/opcodes/ticket_read.tz +exprtvtEFi6v3awAwbHivJkjki6mDNivewiCBeJDJT78PqWtq7VyUD michelson_test_scripts/opcodes/ticket_split.tz +exprtifPFaLqHvR9uGWbeLj5r3YVBnKaawt12q3BMhM9wsUdM9dFNy michelson_test_scripts/opcodes/ticket_store-2.tz +exprvJGjz1EDdnAPWZQ7ZngDNDDDXnxA2VY6SHdHKu8LxqcVHd3E6z michelson_test_scripts/opcodes/ticket_store.tz +exprvDjqte3hX8aieidgPA2qyPWA5eYuVrvb3KKZ8aYkeDotovgkQ4 michelson_test_scripts/opcodes/ticketer-2.tz +exprvSU3oSiKqMLpWgBhwJZbEMDnvKiNW57MYQ8YG787N7jocXMEuR michelson_test_scripts/opcodes/ticketer.tz +expruhV9RSEPAtKAUhBbdTw5gPFdjcKk8zr7cVLSsGtmJuH3o7VXXo michelson_test_scripts/opcodes/transfer_amount.tz +expru3MSjYZRmQi3yiN6gYa4X6rs88XLWH4H8ivzrCvxs8z8cJfu4Z michelson_test_scripts/opcodes/transfer_tokens.tz +exprtbACDcFtDfEwsBA5LAG13uMRAjnQsFjzNELMS7jQ87bcqgdE6r michelson_test_scripts/opcodes/uncomb.tz +exprufJpS3BWpgv4QBaBEMucbn1jsVpdqEGLLMfXjDuKGPRGCpZUkj michelson_test_scripts/opcodes/unpair.tz +exprtqjpmEs9GUjSEzJYSnN3skiCb8js2bY48R9Lhxk9JW1CKnm6VP michelson_test_scripts/opcodes/unpair_field_annotation_mismatch.tz +exprv4ACaZe4aECCfG93NGVVHbQBNQ5Atxtju5vWASZSEp5sLECcjg michelson_test_scripts/opcodes/update_big_map.tz +expruWzM36ATA3fAee4WHDS4vvMeewkwhya1fZaa6HFPbjwt9vvGpg michelson_test_scripts/opcodes/utxo_read.tz +expruNCoB4n3KQTeXbDJWLwynT32T6dz2Nxw5f7SwaqRNkQSBog79A michelson_test_scripts/opcodes/utxor.tz +expruJxgC2Q8Ubt8tPyQbZ41j6w4b8yw5f6bxjrMMM81TmMC9x5Lrc michelson_test_scripts/opcodes/view_fib.tz +expru9EavkgPCUAwHccJf9j1t4aTTssPKoBkCqC4YNr12kxXSwqFqD michelson_test_scripts/opcodes/view_mutual_recursion.tz +exprv4QXQuZtQE7CpKyecjrXJ8U2ovU1qjUKtw37J6kAEmu3fAKyN5 michelson_test_scripts/opcodes/view_op_add.tz +exprugGjNh2tTsofJyhkNMrQVJnkyLydJywNVMAXL9rW3nhnCmRd3F michelson_test_scripts/opcodes/view_op_constant.tz +exprtn56ZZ3mXHoz9GMS9HGMfmgayukvVXub8zXeDKbE4U7L5L8dXX michelson_test_scripts/opcodes/view_op_id.tz +exprtaNDFRcdw8SB4Bz1a6CKARxZaoxpc6G2hnJYedp1iZgJqEwMNV michelson_test_scripts/opcodes/view_op_nonexistent_addr.tz +exprtmA9Auh8GAHpvKP2qkVhiaRCtokWcw7qg31CaxbouJW1g8yYK7 michelson_test_scripts/opcodes/view_op_nonexistent_func.tz +exprubMFU6xrnHREoXUZinEeV3PuZBjSw35M6gti7tyQ83S6LTKja1 michelson_test_scripts/opcodes/view_op_test_step_contants.tz +exprtj9pixxS7UHchhthZa8zdU2GAjvW7oA7QEMA3PHgf88vmAEjFb michelson_test_scripts/opcodes/view_op_toplevel_inconsistent_input_type.tz +exprurrbjDgnipRBhqb7pPLQFAgtPm5jrpwJjJL5ZvQyFJZzGvqteY michelson_test_scripts/opcodes/view_op_toplevel_inconsistent_output_type.tz +exprvSPcq1w7iTMA3LjQcHegnRUQ621sqQLRJm1Zh4tjHCkmeZV268 michelson_test_scripts/opcodes/view_rec.tz +exprv1LkSMvSyZSBrg9Tf2PdcoiWDYPz2npmYb7rH6bWx2sYMAHMgg michelson_test_scripts/opcodes/view_toplevel_lib.tz +expruF13NKWWyF51seiYv4tsb55dZHYViNWDKTmhLq9b1LXXenwaB2 michelson_test_scripts/opcodes/voting_power.tz +exprvSZMaiMSbKgRYm1W4rcoBGN21bPu8NMQuYBH9ujhXGeHhdtVGk michelson_test_scripts/opcodes/xor.tz +expruDwpzxhBEyYY2Tqt9HE9iL18wWJEUJtF9WnkfAyHg1mqkRqs91 michelson_test_scripts/opcodes/xor_bytes_016.tz diff --git a/tezt/tests/expected/self_address_transfer.ml/Paris- Self address transfer.out b/tezt/tests/expected/self_address_transfer.ml/Parisb- Self address transfer.out similarity index 100% rename from tezt/tests/expected/self_address_transfer.ml/Paris- Self address transfer.out rename to tezt/tests/expected/self_address_transfer.ml/Parisb- Self address transfer.out diff --git a/tezt/tests/expected/self_address_transfer.ml/Parisc- Self address transfer.out b/tezt/tests/expected/self_address_transfer.ml/Parisc- Self address transfer.out new file mode 100644 index 000000000000..4592b107141d --- /dev/null +++ b/tezt/tests/expected/self_address_transfer.ml/Parisc- Self address transfer.out @@ -0,0 +1,141 @@ + +./octez-client --mode mockup --wait none originate contract self_address_sender transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/self_address_sender.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 592.496 units (will add 100 for safety) +Estimated storage: 339 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000379 + Expected counter: 1 + Gas limit: 693 + Storage limit: 359 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000379 + payload fees(the block proposer) ....... +ꜩ0.000379 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (contract (lambda unit address)) ; + storage unit ; + code { CAR ; + BALANCE ; + LAMBDA unit address { DROP ; SELF_ADDRESS } ; + TRANSFER_TOKENS ; + DIP { UNIT ; NIL operation } ; + CONS ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 82 bytes + Paid storage size diff: 82 bytes + Consumed gas: 592.463 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0205 + storage fees ........................... +ꜩ0.0205 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as self_address_sender. + +./octez-client --mode mockup --wait none originate contract self_address_receiver transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/self_address_receiver.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 592.927 units (will add 100 for safety) +Estimated storage: 340 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00038 + Expected counter: 2 + Gas limit: 693 + Storage limit: 360 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00038 + payload fees(the block proposer) ....... +ꜩ0.00038 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (lambda unit address) ; + storage unit ; + code { UNPAIR ; + UNIT ; + EXEC ; + SELF_ADDRESS ; + ASSERT_CMPEQ ; + NIL operation ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 83 bytes + Paid storage size diff: 83 bytes + Consumed gas: 592.894 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.02075 + storage fees ........................... +ꜩ0.02075 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as self_address_receiver. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 2961.427 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000601 + Expected counter: 1 + Gas limit: 3062 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000601 + payload fees(the block proposer) ....... +ꜩ0.000601 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 82 bytes + Consumed gas: 1745.840 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: { DROP ; SELF_ADDRESS } + This transaction was successfully applied + Updated storage: Unit + Storage size: 83 bytes + Consumed gas: 1216.725 + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- add.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- add.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- add.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- add.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- mul.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- mul.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- mul.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- mul.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- negate.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- negate.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- negate.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- negate.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- store.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- store.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- fr- store.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- fr- store.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- add.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- add.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- add.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- add.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- mul.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- mul.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- mul.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- mul.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- negate.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- negate.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- negate.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- negate.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- store.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- store.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g1- store.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g1- store.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- add.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- add.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- add.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- add.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- mul.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- mul.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- mul.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- mul.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- negate.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- negate.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- negate.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- negate.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- store.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- store.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- g2- store.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- g2- store.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check empty.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check empty.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check empty.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check empty.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check(neg- pos).out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check(neg- pos).out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check(neg- pos).out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check(neg- pos).out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check(pos- neg).out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check(pos- neg).out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check(pos- neg).out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check(pos- neg).out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check(pos- pos).out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check(pos- pos).out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- pairing_check(pos- pos).out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- pairing_check(pos- pos).out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- signature_aggregation.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- signature_aggregation.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- signature_aggregation.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- signature_aggregation.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- test_groth16.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- test_groth16.out similarity index 100% rename from tezt/tests/expected/test_contract_bls12_381.ml/Paris- Bls12_381 contract primitives- test_groth16.out rename to tezt/tests/expected/test_contract_bls12_381.ml/Parisb- Bls12_381 contract primitives- test_groth16.out diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out new file mode 100644 index 000000000000..d1cd3eec32c7 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr bytes parameters more than 32 bytes.out @@ -0,0 +1,8 @@ + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/groth16.tz on storage 0 and input 0xf7ef66f95c90b2f953eb0555af65f22095d4f54b40ea8c6dcc2014740e8662c16bb8786723 +Ill typed data: 1: 0 is not an expression of type unit +At line 1 characters 0 to 1, value 0 is invalid for type unit. +At line 1 characters 0 to 1, unexpected int, only a primitive +can be used here. +Fatal error: + error running script diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- add.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- add.out new file mode 100644 index 000000000000..1eea408b8268 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- add.out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0200000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xa8b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0xfbf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x38beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x989b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x2648fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0xe568301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x5b2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x2a3a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x711a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x2b2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xa8b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0x4e61c1b9739b09c6136d03f10db4f1fe66368104f9dfb4a1ff2e147dc3209a5c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0xa1a688aadbbdba2965131e014d737cb8d52567301e3941d940e4617d0eb1534a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0xde6e9039874c89906a3f0161ad49e4e02e4bf18a44fcdd8f30ad1493e4b7c544) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x3e4c6416c64ad3c5e36efe949318a6d9b1724e3a40432d12eeff653428ae0f33) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0xccf8dd7732f3a043893d84d12bd5af746b567dce7751ebbb4ea2cae149105c3a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x8a1911fb6130ada278495eaaf297b06cc32b72924e177910e6a953b50eeb1826) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x01dc41c11307df45df4e95d942c61da257af08aa1c61ff67f7a3b8765d716e72) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0xcfea7e1e6ba3b0c89d32738c659c4efd5509edaf7e64b45af13d91d19d4a1526) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x16cb481085742002a06e43e19ba8f1a36064493d2437fc2cff621722e9db6513) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0xd1d327c5ea7170b5f9039c203e898b36ad288eaddfa69deb6025523a4663884d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xfbf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xa1a688aadbbdba2965131e014d737cb8d52567301e3941d940e4617d0eb1534a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0xf4eb4f9b43e06b8db6b938118c32077244154d5c4392cd108299af7d59410d38) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x31b4572aef6e3af4bbe51b71ec086f9a9d3ad7b669556ac7716262932f487f32) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x91912b072e6d8429351519a5d2d7309320623466659cb9492fb5b334733ec920) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x1f3ea5689a1552a7dae39ee16a943a2eda4563fa9caa77f38f5718e294a01528) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0xdd5ed8ebc9525e06caef78ba31573b26321b58be73700548275fa1b5597bd213) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x542109b27b2990a930f5afe98185a85bc69eeed541ba8b9f38590677a8012860) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x2230460fd3c5612cefd88d9ca45bd9b6c4f8d2dba3bd409232f3ded1e8dace13) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x69101001ed96d165f1145ef1da677c5dcf532f694990886440186522346c1f01) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x2419efb5529421194baab6307d4816f01b1874d904002a23a2da9f3a91f3413b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x38beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xde6e9039874c89906a3f0161ad49e4e02e4bf18a44fcdd8f30ad1493e4b7c544) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x31b4572aef6e3af4bbe51b71ec086f9a9d3ad7b669556ac7716262932f487f32) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x6e7c5fb99afd085bc111ffd04cdfd6c2f65f61119018077e612b15a9054ff12c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0xce593396d9fb52903a41fc0433ae98bb7987bec08b5f56001f7e664a49453b1b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x5c06adf745a4200ee00f8241cb6aa256336bed54c36d14aa7f20cbf76aa78722) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x1a27e07a75e12c6dcf1b5c1a922da34e8b40e2189a33a2fe162854cb2f82440e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x91e9104127b85e1036219349e25b10841fc47830687d28562822b98c7e089a5a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x5ff84d9e7e543093f40471fc043241df1d1e5d36ca80dd4822bc91e7bee1400e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0xa7d817909725a0ccf59c3f513ee2a1d92d515bcd772b5f4e785eb5615d1a7f6f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x61e1f644fe22f07f50d69990dd1e7e18753dfe332bc3c6d991a3525067fab335) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x989b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0x3e4c6416c64ad3c5e36efe949318a6d9b1724e3a40432d12eeff653428ae0f33) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x91912b072e6d8429351519a5d2d7309320623466659cb9492fb5b334733ec920) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0xce593396d9fb52903a41fc0433ae98bb7987bec08b5f56001f7e664a49453b1b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x2e37077318fa9cc5b370f938197d5ab4fcae1b7087a6a582dcd0b7eb8c3b8509) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0xbce380d484a26a43593f7f75b139644fb6924a04bfb4632c3d731c99ae9dd110) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x7b04b457b3df76a247a7574e7ba0229b1340e1d19d522bb41cf84296c61f7c70) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0xf1c6e41d66b6a845af50907dc82ad27ca2ebd5df63c477d8e5740a2ec2fee348) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0xc0d5217bbc527ac86c906c30eea4c02ba61d5cefcd9f66fe278c80b2557f7870) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x07b6eb6cd623ea016fcc3c8524b163d2b078b87c7372aed035b10603a110c95d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0xc1beca213d213ab5c90597c4c3ed3f11f8645be3260a165c4ff6a3f1aaf0fd23) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2648fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xccf8dd7732f3a043893d84d12bd5af746b567dce7751ebbb4ea2cae149105c3a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x1f3ea5689a1552a7dae39ee16a943a2eda4563fa9caa77f38f5718e294a01528) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x5c06adf745a4200ee00f8241cb6aa256336bed54c36d14aa7f20cbf76aa78722) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0xbce380d484a26a43593f7f75b139644fb6924a04bfb4632c3d731c99ae9dd110) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x4a90fa35f14a38c1fe0d05b249f66dea6f767998f6c221d69d158146d0ff1d18) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x08b12db920884420ee19df8a10b96ee2c74b6e5ccd88af2a351d0a1a95dada03) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x7f735e7fd25e76c3541f16ba60e7db175ccf04749bd2358246176fdbe3603050) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x4d829bdc29fb47461303f46c83bd0c735a29e979fdd5ea7440b14736243ad703) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x956265ce42ccb77f149bc2c1bc6d6d6d6a5ce710ab806c7a96536bb0c2721565) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x4f6b4483a9c907336fd41c015caa49acb1488a775e18d405b098089fcc524a2b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xe568301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0x8a1911fb6130ada278495eaaf297b06cc32b72924e177910e6a953b50eeb1826) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0xdd5ed8ebc9525e06caef78ba31573b26321b58be73700548275fa1b5597bd213) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x1a27e07a75e12c6dcf1b5c1a922da34e8b40e2189a33a2fe162854cb2f82440e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x7b04b457b3df76a247a7574e7ba0229b1340e1d19d522bb41cf84296c61f7c70) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x08b12db920884420ee19df8a10b96ee2c74b6e5ccd88af2a351d0a1a95dada03) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0xc7d1603c4fc5507fdc81b763da1f2d2e25f9042aac2677b214a23017ad5c8563) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x3d949102029c8222442bf09227aadc0fb4a4f9377298c3d6dd1ef8aea83bed3b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x0ca3ce5f583854a5016bcc454d24cbbeb7d67f47dc73b2fc1f366e333cbc8163) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x538398517209c4de03a79c9a83306e65c231dcd48146face2d5bf483874dd250) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x0d8c7706d90614925ee0f6d9226d4aa4091e7f3b35de615a47a09172912d0717) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x5b2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0x01dc41c11307df45df4e95d942c61da257af08aa1c61ff67f7a3b8765d716e72) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x542109b27b2990a930f5afe98185a85bc69eeed541ba8b9f38590677a8012860) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x91e9104127b85e1036219349e25b10841fc47830687d28562822b98c7e089a5a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0xf1c6e41d66b6a845af50907dc82ad27ca2ebd5df63c477d8e5740a2ec2fee348) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x7f735e7fd25e76c3541f16ba60e7db175ccf04749bd2358246176fdbe3603050) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x3d949102029c8222442bf09227aadc0fb4a4f9377298c3d6dd1ef8aea83bed3b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0xb356c2c8b472b4c5abd428c274348cf14250ee45380a10fba69bbf46a41a5514) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x8265ff250b0f8648691405759aae7aa046827455a2e5fe20e9b235cb379be93b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0xc945c91725e0f5816b50d5c9d0ba1d4751ddd0e247b846f3f6d7bb1b832c3a29) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x844ea8cc8add4535c5e52d09739bb7d99da115530328e8b1589af633e0b35c63) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2a3a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xcfea7e1e6ba3b0c89d32738c659c4efd5509edaf7e64b45af13d91d19d4a1526) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x2230460fd3c5612cefd88d9ca45bd9b6c4f8d2dba3bd409232f3ded1e8dace13) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x5ff84d9e7e543093f40471fc043241df1d1e5d36ca80dd4822bc91e7bee1400e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0xc0d5217bbc527ac86c906c30eea4c02ba61d5cefcd9f66fe278c80b2557f7870) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x4d829bdc29fb47461303f46c83bd0c735a29e979fdd5ea7440b14736243ad703) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x0ca3ce5f583854a5016bcc454d24cbbeb7d67f47dc73b2fc1f366e333cbc8163) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x8265ff250b0f8648691405759aae7aa046827455a2e5fe20e9b235cb379be93b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x51743c8361ab57cb2654e127c028694f4ab4fa640cc1ed462bcaab4fcb1b7e63) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x985406757b7cc7042990b17cf6340cf6540f57f2b193351939ef31a016adce50) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x525de529e27917b883c90bbc9571e8349cfbf958652b9da45234cf8e208d0317) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x711a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0x16cb481085742002a06e43e19ba8f1a36064493d2437fc2cff621722e9db6513) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x69101001ed96d165f1145ef1da677c5dcf532f694990886440186522346c1f01) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0xa7d817909725a0ccf59c3f513ee2a1d92d515bcd772b5f4e785eb5615d1a7f6f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0x07b6eb6cd623ea016fcc3c8524b163d2b078b87c7372aed035b10603a110c95d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x956265ce42ccb77f149bc2c1bc6d6d6d6a5ce710ab806c7a96536bb0c2721565) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x538398517209c4de03a79c9a83306e65c231dcd48146face2d5bf483874dd250) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0xc945c91725e0f5816b50d5c9d0ba1d4751ddd0e247b846f3f6d7bb1b832c3a29) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x985406757b7cc7042990b17cf6340cf6540f57f2b193351939ef31a016adce50) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0xdf34d066954d373e2bcc81d12c41af9c5f6ab37f57667deb4614b8f0613e1f3e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x993daf1bfc4a87f18505dc10cc7d8bdba65656e60afee476605955df6b1e5404) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2b2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e' +storage + (Some 0xd1d327c5ea7170b5f9039c203e898b36ad288eaddfa69deb6025523a4663884d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c' +storage + (Some 0x2419efb5529421194baab6307d4816f01b1874d904002a23a2da9f3a91f3413b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816' +storage + (Some 0x61e1f644fe22f07f50d69990dd1e7e18753dfe332bc3c6d991a3525067fab335) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204' +storage + (Some 0xc1beca213d213ab5c90597c4c3ed3f11f8645be3260a165c4ff6a3f1aaf0fd23) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c' +storage + (Some 0x4f6b4483a9c907336fd41c015caa49acb1488a775e18d405b098089fcc524a2b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b' +storage + (Some 0x0d8c7706d90614925ee0f6d9226d4aa4091e7f3b35de615a47a09172912d0717) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144' +storage + (Some 0x844ea8cc8add4535c5e52d09739bb7d99da115530328e8b1589af633e0b35c63) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b' +storage + (Some 0x525de529e27917b883c90bbc9571e8349cfbf958652b9da45234cf8e208d0317) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659' +storage + (Some 0x993daf1bfc4a87f18505dc10cc7d8bdba65656e60afee476605955df6b1e5404) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f' +storage + (Some 0x54468ed06148d7a4df9a34506e5e256ef31a9b56c66d8635c21b90f7c8a5763e) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- mul.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- mul.out new file mode 100644 index 000000000000..5e75603e14bb --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- mul.out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0100000000000000000000000000000000000000000000000000000000000000 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x0000000000000000000000000000000000000000000000000000000000000000 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x87a25b280438cfc7b350b0e2d8b21f5f8408e9bdf090571dd3094b319ae86868) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0xa6c9f4c0d4cdce57a0b62ce3e72cec52eae0a3fcfa76c36bd21c7c86e99fc83d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x25804ebabb2d9780d1407a55d30de32e9f2b7adf3c8ea0f75ca1de81460d474d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0xb40894438c8e2fe116dcf7359f9749ae3acb10ebb4d32c6a728872c2a4d2b26d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0xf49b419a11a70e24e0e5709d6076ca94423feb999d85ff80225f17b013b27d50) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x9320b3135e9af05cf18d6bf877c5c1d23fdc0359698e1afbe695b158eac21368) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x55ab878b91343d6afd97062bd3fbe33773bb9c73959cbbfffdaa809407480b0e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x8183fcdd8c98e009e3f37fa8b5522e39c304c2879bceee0561d0cde46b28c373) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x3563756c4ff5c12b913114017799af8428e6e8a4ac9e58566539217602169452) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0xc1b67ece270e04902acf261eb093ace0a7d5e31767d8a7e8f5b0e9fa27738250) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x3e32303d8a7d5461cf652bdb31bfbcd57b9dac493154494636d13e39b42a7f17) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x768c7286874cc5348f7c3d0f3688525ce62cb31417b167d84447957f3933be33) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0xa926135de1582acd8aa4cbcafbe9fc2311984981900ab7efe694131f567e7a61) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x43069535a17a72feb7170f2fc0ed42662d866518a44dea0d1928b05a05d0f30a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x270733ecc8ad2646ebd078f69c26e86a8a11aa2911f358b2cfaec47c09898871) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x572ea10d39037776f9c830677be3cd209a53045f1736150964af2726d79ce93f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x6739e14eed742687df9c9072284495d7670da73fa6df7f71d55f1c085751b61f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0xdc456cc8b4d389dd1ce937982176a0db91214868e20559fb72cedf4cb535442b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x4a1e1fed85421caf61a7454d4527cf88cc4b2ec77256e7876777951dd6728d6e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0xb8cb27f9926d77d681bb886a65a91631e7305a08f4f2bc646d703b0dbd07d639) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0xf81b4b288001fe1541f5ecec5e70dfb268e6ec4a5d29afddc38cb5a05b01ee03) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x3b06b22f06e8cc99e262d8128c6473114e46f835628b01f70a2516ec32ee1246) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x943bfd1b7156b3183bc62e89627f23403a3980105e40259f663a6c88b570b818) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0xcdae0ee9d2e80ea223e22e74a42b17a3fda65d2a83f12f177fd4f3f15965b721) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x6f5de32417068ac83a058d76c42ead4aa0f2a772844b89c383fe8cafd8c23e42) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x4c64333f14e58d1f18840e610bf95b6ffd029eb7e9626a7de1317de07bc06b70) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x3071e1921ec27beee7c56aec7489cd72721ee17d27310f655a1b13fca7758704) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x6439143ec011e4b75ddaa6a9111a31522b31d3b4318f2a3e02c157184a8d990f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x95a1515b3a6a7fba11021b63139d0b1f6b5b3ea32c4f77a7e82d8b5c9206e900) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x6f1f62eabe0a4784ef32d940736b82946dfc5658a2b8d1e0c09bcd01945bed26) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x0fb5c6cdcec66d9e61822adf622581a3c3c2326aa15452022f85c6301ab6431e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x870fbf317f37e2ebbdf3e4a0cd821319eb3b8c159d42e7cafc360bfe42918959) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x5935c1ef5cded751a700599df9b247dfd66c2cdd9bd0dece969af31dd4db3e52) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0xa15e4850ea8a5be5f8d11cb8dcdd74076a13bb3887162a48c43f95e665800f53) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x18d4795bc198725f61c8ddeb04907180c369c39dae5deb6e02012f948f05c062) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x4d13486d53e43e63d4b05414379253c2d9fb2c3084737eb4295aacebcc9a9856) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x8ae6ee958f2c40886ea97f724f4d59f23d9afc69043024380d75c7a52c3e8314) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0xcb9c0565e3195b9bd7880cf92039af354648c93943fc9c597c7bdd6adba50f60) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0xcc314f9f215f1b0e511f3cadbc16fbc9a8be2957996768314e9667609176aa3b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x6b11aa1e88300282fc067020fc71e355158db40e2a65170370ea7267175ca307) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x3c9fd860f69f0338ef5e4bb1f561085ba3c6755e7c4d28624fe7d6473ff3f920) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x272721157452654bf0ae566d51db5229bf277791e42899530390c002035d0d1d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0xffc690cab4a872c0f0af7536f9af84c7a4a6012dfe777467635a0aac48e0763c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0xda5d746519732d2b289ab841d41708ef65e43ab1c9fd52b39146ad044f6b2a73) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x748bc12266cd016dfb56d8b976465e2595865a65cd220e54e868356ebc23594a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x0049d565766ae2384b2fd097c810ff5a52b49bf22b77b28cf8cc4ae94e23a625) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x808b140f1d708376ea5fda3d808467bd3fe6f6b749012270a9b9c0046165c72d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x8745aa87036abec609d26ca4d70d9fb6db78e151d9f20c6bc8aa579533e9662d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x44edfb33fc4ac9ef521419c823b6af02e53428e692542ebb7efa351b4fed096a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x1a215ae0252140eb36d367e414c74e848fa04008dbddacc4daecde4148a2231b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x89b312941fb46bf3ed66a5815ac5068f471d0ae7f18a3b0659c09bcbf9697f0b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x9acbe51d20ae85fd3bc40684f42fe7a0c7a5d95bb9836fa31439e7e14b26f416) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x6118124c521ebca6de31388b9fa83fcb4138a5a6087b7f94550efb86e61b2605) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x0da33e534705d29aec1569b0533fc84a9065e78cded913aa6b4fcb8e6dc78457) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x8ea43020b125a8cf25d56541757707f44756a34c48d2c1b1dd01568744eaa746) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x2309a557bf125239f17b1bf039eaeb2aa35fb86cd130d4a8e526499dfe5ac84e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x14feabe62d03bf84e49ca4bcf4f32ec9e69b647f65561c75e40ab3bcb5e8a24f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x564309a3de0fe9bd097f6ef5786e799966e2722a61cdae1378ce1842ae56d46a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0xfcfd6b65ccfc1ca0f76aa65149f89c8a37e9cf46d11273cc2e5a6a683afae51b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x411fadf092e7a3dc0a95926b58eee20dbb90761598fcffd4cf9cf67c4394dc0d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x1f11f44683fa6f887a4ee25769ada17ee34442ca28717d465850b37a12f4304d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0xbcc1b73b410363d82a7067cd12d0ddfda6f1d8450ca39fd5d466eaac2df42f09) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x76e440c59f34bc987a7808f66bac37b0ceec0723447ecf97193df5e0d5531b04) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x6dc4feb2b650db171d026794151af66ca5de3932a93012aa415f6ddb76428d70) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x3ca3d9a981d4692f396717a8ad3b439df75f71c084dd77bf061a400a7a8ecf36) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x495b461df06822ca749b43f1b9c7cfa94d997bdfc486c15b6a163ca84df0cc72) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x15245e97997fb4d7f77c958fb584b5437a70138cb25050d205d3e7ea7adf742b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x2d9334cf8067eac72250f2f542b210143fdba091e3284552f65ef9c529d5c050) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0x909b9aa234ca8c415fc271be5efa6580ac08fa507dfebc3b0fba8303c54d5215) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0xbbab3f2a73ec15c1524192c00727c746deffddc1f96a2475e2d30cc94882e82b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x6806200732f39ae9263a93d4770846aeb6984fb3043d7564ecd1a29fc572e33b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0xa4eb13e8a97e2b5c0923e38d20e42d5fcdef5f0fbe4794e89ad0f4cbab071c15) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0xcccfd0286d9796efd1c3a3152050358b8e385198ef3d8cafc4a702ebc925bc41) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x5573629a59f3745c4e37746f40ffce48f5d262b6b9f977e9a082a51da639f20a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x1a55a49219259dfcc5f43f108c2f378f91dfab8b0eacb39a4c7d5faf5d28dd3c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0xfb794df3d54d535862c33dc4c9fd44e7dcaf63947c9222ba149edb9c5e80590f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0xe362cd13cbc3aea9117bc1e5133b29b044a81d4594daeab05a8ad910e9674c06) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0xa7d4fb01e871e9696ac6b4352942fe7f0e4b82285a5a4340834fb8cf1d16bf6b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0xe8e9a92d243462323ddc3fac7ea8f620be1f4ea5cdfcc28c4cb2f3e944000e72) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x5c5931083e04dff412544ee5c8f2eae5dfb6f85327a348c1840be1f2228aae4a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x3cab64084c5cf930ee67515efaa9a4ff3652d83b50c21f84b4b18cecc82cd727) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0x3664d4c448a9c4bf1ca65a6e6f559f9514007c2496261bc4edcacbb53abe7c70) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0x5dac7534752b142ad0a4454ff17b06aae01d001e71968cfd270a6ca7eeb6986d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0xf7976f089a7b8fa570d983e54563734c47d584f4699c4ed4b70b4e0a7b278772) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0x415fca05fe5f8a5f1f8d1b0f98e2ea3d825fc1c6355365df9b45c4c39d8e8c33) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0x5f093c21f58d3b872011c9af9e916b2f7c8b78719388029fe2c0a184671b3023) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0xf512cb0c62dd2247fac6318a8e77c5adfe40724320517d325213ca5742263148) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x34d90ed392f4abad17b679356ae63f6a55084b530c18a3a88fd75365548c8c25) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0xdc3888e1ec70f104d18c09e63bb13c341738fbc20a416a8b68a3710878ec2c45) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0xd2c3ef335391513f05b8882585542773818fcd7db3b34f031f8ed422627c3d44) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x4dbff329ffb7cf3daf857a397ab121e80d1064f1bf07279c0715ce04eb8af625' +storage + (Some 0x8122686c678dcbc0a302f9d75197643108207fd79d8e911452f22383af064a64) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xb0c5816556729f95aaa68be2fb34eb2edfd3c9ac98669596ca9f262572963829' +storage + (Some 0xf46d74afcfe9036a2dc59ade3e33ab2e0fdeca7108527907f9a87fe17dbcef48) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x4da504775fa6efb66a94b0c74b5b9c80920483c32bf016807dae87c705d0b805' +storage + (Some 0xcad3c31ac0d68830faa65f55a7e812f2cf8ae2eba8f15e94d51f859d46320815) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x719eeeee8ade493ac3a0a3a742a9cee423c2f6790f8e8e448ba4618bf4d5b80f' +storage + (Some 0x5c9a4dc7dfaa30973a60bb1792b062bcd93ba8715d50b350185d957af0852300) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xa058f1d8283834dfcc9e6f76d5f58172faddc3a51a16e5c92823da4fca890742' +storage + (Some 0xfbf6f4100924d0f64653cfb859bf036268dd678fd5360e67140194ba8e90ba4f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x03b0af5909feab04f285e4470dbae4a19e9a23c9438e2a57538433326d7cce27' +storage + (Some 0xeff6a7ab1bcf078ddadd2a4f5dcc847951f475852a30c585e53e02a8919eac47) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xf49df98960a59c8d937bada91f7226fedbb5a02771fcce56780d6a0168186e01' +storage + (Some 0x44ac9ab247ed628c8e96daffc075f7cb3925effd568e78a7f691629fef28df3a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xbeb56d8150689b21e164f70cdbfd81e72e0071b6d005033aa30dad5b3656f924' +storage + (Some 0x05fb8adcfb2026e2c9609c7edcbfbd33f4df44cb80a2274bc8fdd1a58cd4690e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0x3867092164442c26405ab5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532c' +storage + (Some 0xa2681666d2a92b8b4268bf287e81e274ef196cf93de96c25dd3541e61c5cc364) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_fr.tz on storage None and input 'Pair 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f 0xd008362943c1237f5b297f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f6126' +storage + (Some 0x45d081e131a285730dc55f7e347a56cf6f07236ba44bc93af9423db057227560) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- negate.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- negate.out new file mode 100644 index 000000000000..596d0837a3e2 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- negate.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x0100000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x00000000fffffffffe5bfeff02a4bd5305d8a10908d83933487d9d2953a7ed73) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x0000000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e +storage + (Some 0x5a4f1f234532fb1c75a57c07fcc944d4d13c61870b685f62c865136bf196a045) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c +storage + (Some 0x070a5832dd0f4ab923ff61f7bc0aba1a634d7b5be60ed32a87b0c56aa606e757) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 +storage + (Some 0xca4150a331817b521ed37e975c3452f20928f100c04b367497e71255d0ff745d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 +storage + (Some 0x6a647cc6f282311da5a38163766590f986009451c404e7f1d994c1b38c092b6f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c +storage + (Some 0xdcb7026586da639fffd4fb26dea8865ecd1c65bd8cf6284879f25c066ba7de67) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b +storage + (Some 0x1d97cfe1579d5740116d234e1442c812706fceefad5861c0996d360953253408) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 +storage + (Some 0xa7d49e1ba5c6259da9c3ea1ec7b71831e1c3d9e1e7e6149cd0f06e715746cc2f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b +storage + (Some 0xd8c561be4e2a541aec830e6ca13d2a82dd9153d27d0b26768ed9f8ecc3c53708) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 +storage + (Some 0x91e597cc3459e4e0e9473e176b3187dbd236f744d838dea380b4729c7834e71a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_fr.tz on storage None and input 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f +storage + (Some 0xd7dcb817ce5b942d8f0ee4d7cbf4aa9c8b4a54de24a17618676fd5ad6e54b254) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- store.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- store.out new file mode 100644 index 000000000000..1c5640386dd0 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- fr- store.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x0100000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x0100000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x0000000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x0000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e +storage + (Some 0xa7b0e0dcb9cd04e389b681f806da787f339b4082fc6fdad07f178abe61104d2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c +storage + (Some 0xfaf5a7cd21f0b546db5c9c0846990339a28a26ae21c96608c1ccd7beaca0061c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816 +storage + (Some 0x37beaf5ccd7e84ade0887f68a66f6b61fbafb008488c03bfb0958ad482a77816) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204 +storage + (Some 0x979b83390c7dcee259b87c9c8c3e2d5a7ed70db843d352416ee8db75c69dc204) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c +storage + (Some 0x2548fd9a78259c60ff8602d924fb36f537bb3c4c7be110ebce8a4023e8ff0e0c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b +storage + (Some 0xe468301ea762a8bfedeedab1ee61f5409568d3195a7fd872ae0f67200082b96b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144 +storage + (Some 0x5a2b61e45939da62559813e13beca4222414c82720f12497778c2eb8fb602144) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b +storage + (Some 0x293a9e41b0d5abe512d8ef93616693d127464e378acc13bdb9a3a43c8fe1b56b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659 +storage + (Some 0x701a6833caa61b1f1514c0e89772367832a1aac42f9f5b8fc7c82a8dda720659) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_fr.tz on storage None and input 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f +storage + (Some 0x2a2347e830a46bd26f4d1a2837af12b7798d4d2be336c31ae10dc87be4523b1f) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- add.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- add.out new file mode 100644 index 000000000000..a2c91722fa80 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- add.out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x0572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x02bbe75ccfac8903cfb203d8aabe7973cf45c4dbb9505242cdf0db5ef5510661bd9fe29e45108a2ede89b6f91698313c038e354ee839e5b3d4e4cf89a5415c578395396a0fb3e170d5ebfe8443920ce5a237f317a7fde9750aeeaa6d995cec23) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x0b0076d6ef76e28344833ea759697fdd353b754a7207ae0c0c3ae5465150daa84bd888116b05ae14e922b469cbcda95106c1843e97627707d4ca3502fac07ca61de50f24118714ba6114f66bd7a2a3eb83f98bc92d88b6d9607159a57e8de5e4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x1928666d52b29e0355aba253192611a77283b6f028fe4b6d49fa88ad47237fad9228de9acd50c3f2b9f4885efc08673406a8e7278f95030bc2a1804fabb589643cfa58dbeec752c516c799e108c66b879d60ffabfd9fbf4f05c5e4974dd05de9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x16fde910b5f003049c80e1dc46475b65bcf2604b25344c6808b57ec25fd4352ee64b5bf5197ab9d8ec274cea8096d93b01c03ca9cf4a78b818ca4a08393963d9f86dfbac64e3881d1220241ecc7036d0906004a56841cc0336e24d9bec59a569) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x158edd43e9464a9e18497aca8ff36e247c1e155dc5eb233da377d2b908ad3a7bb60a30845c21f16b0d4965c301dc8c1e125faf41e0c80a9e5ebd98e0d88c3d6d0ac897dc6d37942a239ef970dcb4b455b1ce0471c047427fc46ef53ab061a96c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x0c3901b112af7f9797fc9cf71cfa90a7951c250b5dcfa235d2d6cfd9c416b1496d461d5e08645aae731d1759e255e72f0434edbfb503c50dbd75a13a6f50f35a653d6971335e4767cff0bf5a9f0e554253d821c6b0cf96a299f7d7f781586208) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x144e5918959eb7c28dc9117210e11ed52b7fe1aaec4655a9b41b87188595c2636c33adb7ee156a63ce1f40c7cbf4cf8712216b40366ebc2a1c5a284a5bff3804f9dc698756d92e10f5d72bb51150ab2dfe3a5ef09eb9cc699a8cc87d4534da85) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x04e38621e3c1a335f0a6b75b28fbb79fe08970315a5abf13a23d7670c0ea5c323f3d329ffddc197a9a5ec2bec93512a20687806bad5967587ece2bc63e23f29adb5902660a559ee706a3a6d587d035d184504a4b9e8a1dde7106e6d179d4b441) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x0e69e0dab929d1f5ead3cebba16e0370f3ef18a72b80e2704dcff600d8e6c11b84d01c66ff7cec576ffaefc49a74aff00cb9d3d2a771815120ed332d888d444155234d0047af62b278ac6494b80753de716ecdabd4e77f8364feb65035545c6a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x174b443090acd24b63f00bd9ccfa4ca4f07c82ab80b3d02c8436e2bffdc6c8f6f058735ca48187fec910d53f3207c3d0050187821dd662d4f7680ce6eea608cb10164d3267ce217027dbdab08821e5905bbbbd30077a2812247ec251f61815f1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x02bbe75ccfac8903cfb203d8aabe7973cf45c4dbb9505242cdf0db5ef5510661bd9fe29e45108a2ede89b6f91698313c038e354ee839e5b3d4e4cf89a5415c578395396a0fb3e170d5ebfe8443920ce5a237f317a7fde9750aeeaa6d995cec23) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x0c29e29764d169fa7434f1cbe450f275cbafa5624a925093b56db64c5eb780993f74181407e521bcacf6c403966667aa11b9d76b42e519d2b094b1236875e1264354a7ba27ea590093b8cde9bce0835d84c98fb554d46590bb9ddbdaa3896d35) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x16fceeacbaa0201169b7cce9644b848249bd24e73d59df92315af1308718e771fa54708cab5c4509ee59c2688766039c091485a68d271b94f59014e25178102ca52416b4ebc9252f935b4dbadc44ec0858e3d6f20898b9fbfece25153c961163) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x19777d66b554119010e98ebe0a474ab68c58420f1d23f7b940e0b2d394c04f2655da207651543e883a8d545de911225f0af3262fc02c93b8fbebb5a04b5c1794e725c208ea53c96e51b42be25af28868c6951b267e699413afc30835d97a7891) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x09a09f7ba0b93860f16afc7f41a24eaf6f04be5c537a77acb31b2d1321ef90a3aafae9e3e4beaf9f9c3a8ea9b59204201105c73f6ca2b7414aae29417988c3862bb445ca8b7635d336c7caf560c58e42d76f99694bf8d2b3f9ec4004e2edee77) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x06d42ca0cf11ff62839ab18ca3df1170ab4029a1249c618ecc34f7856c549139d10e4242a85aa8c53679e35095d5c1c20a1d007b8cb6cc308834f9c953b18c62ff1709f12471893794145272930cba5ab4188f6950110dcce78b7aa11a77be9f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x05e73bd48731387f18857ac832af5b42779c0e8ee325af3637c28d311db1c208f46ccea104ab0d6d591f5430e8bd646c093718124d92beda4254f02a750b92f87af634e79983e893d3b931a27896a223fc6353a529226e87866eec80f4777666) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x05e5bd713e2b43295e9b50784b2416dc7431f057155560b6b260fc164676f5b3a2bfe84061a12ce5c31069aca695f1790354f267c52a1c3ba6601390e4436fd369194abeeb5f30cab899107cc830179480aff5d138d327a9fc1006a31837b0d8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x03773e554ec120b47b48e37dab64fa0efc22d6a3320ca9aa75a9e0d2d52a4f15599fecd4c9e6a7615ef14647720defb516d0ba1fffb303896ceeb44111b78d64b966326f12cf69692f54796701c13dcd605c278cddc15289c9f9e4bec142b167) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x075d7888f555f9e7eac62ee7b07aa7f8ae5118ea5cbccbfe9a116ddb9ec21c7dad3c29a8c4ab1bc765652d96f171ef5103ca9d795022086b1faad91136592663b8fecb6ca32610c91dc4ef5b594d4e66e3fd737ab8091d917ca240ca4c5f14cf) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x189c9031a7c9fa23f5d733b19353bc60559c75d3008eeeb635d72225e6c3ab8a4e6adf19353f41eebb2fbd3b9aa6ebea18a9fcee2568b75d6c47fced67a88749f512592dd0b3490b31c8a9c6f8c3a89e66bb2436ecd30a4454659304b382bc16) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x0b0076d6ef76e28344833ea759697fdd353b754a7207ae0c0c3ae5465150daa84bd888116b05ae14e922b469cbcda95106c1843e97627707d4ca3502fac07ca61de50f24118714ba6114f66bd7a2a3eb83f98bc92d88b6d9607159a57e8de5e4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x16fceeacbaa0201169b7cce9644b848249bd24e73d59df92315af1308718e771fa54708cab5c4509ee59c2688766039c091485a68d271b94f59014e25178102ca52416b4ebc9252f935b4dbadc44ec0858e3d6f20898b9fbfece25153c961163) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x12daec20770efc59b6dfff9596fadbaceea1e53480256a98cdc5901222631a861a35681dc13e872aaaef3427cc1b9ca3011f543680da504e4aef1a948afe8f616429ac93d4ab594f52ab8ac894fb12bfd68c04592bb6b479966857c503ee9800) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x13009650f609243bda63f99d6b239e1867a1e97881f1a12006c7c40fa6e72ac84395968ac04374a781f916d9d7115f4a0e8baa9d7e11075cba1eb4fa63070f9f6f001424055f6fc107d4dc0d4b7add882281d5a6ae0a7d903927b79376de813f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x01010ce9f58f4893b1a4cc99ac6409e521864ac0c4c8fbef07864df6badb7bdee4bca2cda802a056337a327db27acceb0211256aa48401dd761706de9b9155515d170d93d400d9bc9753d042fd9aee4fa41fd060e9dc8d491f54acb34ebe8fec) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x084dd4489fa10e3470501ff825805ab41c7a889c1c4aa6acbe66795cb5b628a5c05065ca29fd6b8bfa04d62a0fe0b8170881da608bdc6089b8ae9de6fb4b996d68487476eeb8dad2606ef55ead4008548213c276c88fd1c7aff23cdbd69379f3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x0e3314e3aaeece65f3a6d864ea763494a71df97b65606e347552a338b899011f3531173b4c0a37d215d5452eda39915117c0f4e520fb6dd38000e4b8cd19986e2af235409e25be2df2bd8024beff25499f4c90478eb8491346ee13afe078388b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x0a049b6b2bf86d778d6666ed819c3147f0aaaa28315e7b1e1b904bc12f4a8db4f50690d68bf2250c019449e15d126b9a080f2870588412063535032672fe879daa966e6e40294e9d29a6ce4a6b0be3f26b0a1d032d762a7762622bbe749726d8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x0ea4ab0585e9d531d5a2affbb6e9d14da85dbea5e5ab78835961c699f5d4d1de5cb761d1cd07771cd8e56dcb977db07507ada85f8bab0a7aeedd85a61bd84bb505ed3c136c9f116cca8ca77a164502493599b00f3d0ad722a72c931f81ebedf1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x03269e2de673af093ae911c6ca36338d121a06034ae305569b43878a533206d713a15bfe25f2f69a356f023415799ed805669e11c9509a68fa752847a2691e8b66a8cd2acef8e9f8a421d56985fbc5610f625a926a3db22aa2f3b9598e3a5d4f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x07a125ff7730fbbb0a0b009ce801ceb5af3b26a398f92d666a6ba086589401d5c9757abaac52da844bca04ff1a06a6370192af3fd6f36c1da7ca65c3bbab1d7f94976041eda19e5c796a11118c7c53fa73829b1128d5ba0824e29deb6183c530) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x1928666d52b29e0355aba253192611a77283b6f028fe4b6d49fa88ad47237fad9228de9acd50c3f2b9f4885efc08673406a8e7278f95030bc2a1804fabb589643cfa58dbeec752c516c799e108c66b879d60ffabfd9fbf4f05c5e4974dd05de9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x19777d66b554119010e98ebe0a474ab68c58420f1d23f7b940e0b2d394c04f2655da207651543e883a8d545de911225f0af3262fc02c93b8fbebb5a04b5c1794e725c208ea53c96e51b42be25af28868c6951b267e699413afc30835d97a7891) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x13009650f609243bda63f99d6b239e1867a1e97881f1a12006c7c40fa6e72ac84395968ac04374a781f916d9d7115f4a0e8baa9d7e11075cba1eb4fa63070f9f6f001424055f6fc107d4dc0d4b7add882281d5a6ae0a7d903927b79376de813f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x060b5432626c3318aa1658c51be62d04f06c1f26184b384756644651c0a1c31a60c4b6de726b2fce757d3bda50b1225a0cdd5db334f75033fb58116c38d15005f1bdf988de6d3a9837e683623c5c1b751740158f44ab900d9ec227b9fc901f11) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x02bff2e129aae3d00ba3ba6906707816043e2ffec02acd47304b933713e545a350bbda8b54bd00960d804e0bdf6413b8181220b684d56b805cc6d5fa67b38d7b13618b813b0c9ed0d381101e4a02bc4268fe048f46c533217992169d8d6c6948) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x1821a5229b04055ca0a65a61fe9c5b62e2919fe89bad68f3521f82f2ece7d08481c1da0d3f3b78c7c38d16aeca5460690ec2fe6d1631f266187d7e252e9c1933cef416cfdf2fe353c19f3adfd5b175de090efe941bc6c7d31a92601a6c9762ee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x05811adb3715612be05d3fec660098749e265527678f91ade2d28d74736f2d74c9e83634853749b43c0412b5c41f5512145396cb258907d9177c1c6618810e309015bc55dd1047589fe34b4bc54bae1b3745c5ea6466c11c611041934d62d91a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x07499c01c066da94c70ae0c883d59339098e2ae1c265020508486a04c17cdd59b6789dca1134297a2458307737cc65eb02bf943d425cc75ecce827e2953cda3bea4c96d87a2c4ae6f385024c824a24793bc644ead2a77179075b51db951d8692) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x18f82e4740dc20cc275cf1cc7160b13c62a4c757df9ad698e7f5df5fbc4a1118a9e453c92dd67472c3e5c61a3d19a5aa102691e5125cb9ddbfe8d13f9975c5299612e534f2a83c35aa7ceba964573fe371195e741d270392c2be713bd5329e30) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x145c9be227113316ac8e8512128619b41c45a63ab20edf62f53daa3d3ace9240174bbe9f46cbda102bef7b897568c0fa00f54d7771e7fb5e93c8c75b4576849fc1172351336db0dbe89a4cc1eec6847542ca8b1ce0da4e86d2f3e5d830674bf1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x04fb7ad2c096670cf3375d148b32c85ab1a6c4c6ebd35abd5ad2ae0a8d8d35561ca4a5d4b3fdd72f3184a25b1769058b0f4b9f0e50c0c70e2d0733ec6be54f7754fd134054d13aa67b5bb86a935b64d29b994340a5c8c2c34fcb6cd5ac3f2b80) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x16fde910b5f003049c80e1dc46475b65bcf2604b25344c6808b57ec25fd4352ee64b5bf5197ab9d8ec274cea8096d93b01c03ca9cf4a78b818ca4a08393963d9f86dfbac64e3881d1220241ecc7036d0906004a56841cc0336e24d9bec59a569) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x09a09f7ba0b93860f16afc7f41a24eaf6f04be5c537a77acb31b2d1321ef90a3aafae9e3e4beaf9f9c3a8ea9b59204201105c73f6ca2b7414aae29417988c3862bb445ca8b7635d336c7caf560c58e42d76f99694bf8d2b3f9ec4004e2edee77) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x01010ce9f58f4893b1a4cc99ac6409e521864ac0c4c8fbef07864df6badb7bdee4bca2cda802a056337a327db27acceb0211256aa48401dd761706de9b9155515d170d93d400d9bc9753d042fd9aee4fa41fd060e9dc8d491f54acb34ebe8fec) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x02bff2e129aae3d00ba3ba6906707816043e2ffec02acd47304b933713e545a350bbda8b54bd00960d804e0bdf6413b8181220b684d56b805cc6d5fa67b38d7b13618b813b0c9ed0d381101e4a02bc4268fe048f46c533217992169d8d6c6948) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x171dcc4142881ccba470029989ae3958da0be0249ba098f4118c512c219e9f1c6fe1b4e33b6a27cc0b9ca676747d469b06395941ba7dc2d3c5be2c0d785d13f60330cf06f0711091ec0409f6bbf0125efb70a2f67f4a4b51b2b32f1b6e5c7a0b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x0fa9c7b81257390a7476d09ecfdbb7e30d6950be653969b30dcfd7bf6e2bac21906292564a60aae113c1588e7021e0520d472fdac10ae6568cb57809b4412a181e9cc19eb48ab35ef2bdf738e682360d3f97e2c94229da4fea9a2f4eb0662de8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x02273bacef69b570c2cda2f45662739444e0e77d8fb8034af3fdb178e91f337b5972d6a4878cb9e02750313ce832f24502ecfca2d38e0190fe68fef1e7a45aa97f5f3e3e1404de411faa1cfa0b7debc435e2a3c3db0d047431ab49381af5c681) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x1233e8755ad7ef8c6fe37abd8322e15a34270e84a1931af3225f8ee1ed0761fbb9059662c3f86fd91f4fa3b0aea7e67e063ffb0d3ec9593365c7c16a3f1589a56de59200128f0f031a51165a6484f35a49dc8b9189bba6976079ce19e5e35404) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x0a86684fc72a4e2dee49a5ea383178e3a795bda53cd2af4cd428374c62ed64d403dd2d8b90a9739d682edf37b26f1021047a441cde9b6b3c1839f4b8f9c07a443ca35d44e878a04609dedb71eb056ae840862fe9e933fce4b894a96906aab066) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x029aaccc4cc78866eadd686825a2b48bf98b59f9c827c84d6a7663c20254f564c9bcd84bcad0ff1f6d0dcd96fa59ea0b0e47259745ba95228a9813f05942cbbc2186012eb63e23de41bbea46bc1cab64f80b9e1041de98f49c119df14f001522) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x0b68fb08cb23c2087951474646488c4b8cc53e8b2355243955ba35ee10a154a41893978a43e25ebd19aa279b2374d0c10c15cb33448a95c9fcf9ed8171ebcbba030ac7d07ec5e391a937f3b0bd6f469175de8c13a964667d85cf6031ebe94b56) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x158edd43e9464a9e18497aca8ff36e247c1e155dc5eb233da377d2b908ad3a7bb60a30845c21f16b0d4965c301dc8c1e125faf41e0c80a9e5ebd98e0d88c3d6d0ac897dc6d37942a239ef970dcb4b455b1ce0471c047427fc46ef53ab061a96c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x06d42ca0cf11ff62839ab18ca3df1170ab4029a1249c618ecc34f7856c549139d10e4242a85aa8c53679e35095d5c1c20a1d007b8cb6cc308834f9c953b18c62ff1709f12471893794145272930cba5ab4188f6950110dcce78b7aa11a77be9f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x084dd4489fa10e3470501ff825805ab41c7a889c1c4aa6acbe66795cb5b628a5c05065ca29fd6b8bfa04d62a0fe0b8170881da608bdc6089b8ae9de6fb4b996d68487476eeb8dad2606ef55ead4008548213c276c88fd1c7aff23cdbd69379f3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x1821a5229b04055ca0a65a61fe9c5b62e2919fe89bad68f3521f82f2ece7d08481c1da0d3f3b78c7c38d16aeca5460690ec2fe6d1631f266187d7e252e9c1933cef416cfdf2fe353c19f3adfd5b175de090efe941bc6c7d31a92601a6c9762ee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x0fa9c7b81257390a7476d09ecfdbb7e30d6950be653969b30dcfd7bf6e2bac21906292564a60aae113c1588e7021e0520d472fdac10ae6568cb57809b4412a181e9cc19eb48ab35ef2bdf738e682360d3f97e2c94229da4fea9a2f4eb0662de8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x046a2790add475f1fe065066d88b478ea5d288ec4175776bffc94a2ed41d749678d54ac91b6e152e207d03eefabd0569029f74862ff0c85d4e7871b32e7b08701e4f0961e4ab0cffffa52895ade51062358e8ab8f78137631eeb17d52a3d1787) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x01efa5d893d4df2decb69d582a64b701736f942670ee214bcd798c2ace462d3423c4cc5668575beb0348ed27e904740f12c381599e9b0c38e56e97dadf861ca1e298d230a059365b30df2e49903131b1176a914a793c5a957675acd9b5abec9a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x047b382113356f5bf7585f739104668f89d0cdedb89266c151aed5367a8f322c6e9912ff8aa653574c1e406dcaebe5bd0f6bb00734420c448042fb5c13051159614919578383329ff0696ac565562fdb9dc5854122ef0036561f67721b3c0ed3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x0ffc615d86d835dddfce2847aefa2b9356560d0c13df0ca80902fd3000a2ed6857f784b26143d2e425d959801346633b0a9e1097650528b9cf99d91adeb41957560426cc7adab6e45db39d5791c35c6373aa333772943efc9363661abc2c8315) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x0f2239a8444b783758f3e5d7873f05b3c939315918986421a02241a2ba2fb8e7de4c193483f9bb9989e328f3e4aa026f0a1f359cba3e91c5978b66e4c0ca02e5c6966e5173aeb942211351ea8ab59b73b9da7e49b9ff602299e3553d2e6024f3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x045dba3dc8f9e481ce42fce5a8f07501d1faada257439f987273acabc0d3aed00e4cc3948fae082ed24cba5b12b54e5f0d55da0aec1136a24464a5f8f1ac8d58eb893ba95131f2fce03bcb35fcff40993f48b5aad6a80aabeaf0b9d8d7d957ae) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x0c3901b112af7f9797fc9cf71cfa90a7951c250b5dcfa235d2d6cfd9c416b1496d461d5e08645aae731d1759e255e72f0434edbfb503c50dbd75a13a6f50f35a653d6971335e4767cff0bf5a9f0e554253d821c6b0cf96a299f7d7f781586208) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x05e73bd48731387f18857ac832af5b42779c0e8ee325af3637c28d311db1c208f46ccea104ab0d6d591f5430e8bd646c093718124d92beda4254f02a750b92f87af634e79983e893d3b931a27896a223fc6353a529226e87866eec80f4777666) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x0e3314e3aaeece65f3a6d864ea763494a71df97b65606e347552a338b899011f3531173b4c0a37d215d5452eda39915117c0f4e520fb6dd38000e4b8cd19986e2af235409e25be2df2bd8024beff25499f4c90478eb8491346ee13afe078388b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x05811adb3715612be05d3fec660098749e265527678f91ade2d28d74736f2d74c9e83634853749b43c0412b5c41f5512145396cb258907d9177c1c6618810e309015bc55dd1047589fe34b4bc54bae1b3745c5ea6466c11c611041934d62d91a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x02273bacef69b570c2cda2f45662739444e0e77d8fb8034af3fdb178e91f337b5972d6a4878cb9e02750313ce832f24502ecfca2d38e0190fe68fef1e7a45aa97f5f3e3e1404de411faa1cfa0b7debc435e2a3c3db0d047431ab49381af5c681) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x01efa5d893d4df2decb69d582a64b701736f942670ee214bcd798c2ace462d3423c4cc5668575beb0348ed27e904740f12c381599e9b0c38e56e97dadf861ca1e298d230a059365b30df2e49903131b1176a914a793c5a957675acd9b5abec9a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x052472b1ea65d3e7936a4bb032cbd9e5119def59e5e84225746f45353f63cb6192e03d5891704672cbe064b03934f01e19ada310f6ad2b47103929fb6220bd22fd183ab58234505f8deed6f282b2a0570fa2361524048acf6c9291af0826c827) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x063129a2aaec9991ae5bf8324bb697ca1c490ce4fdfcd167a760e3088156379b4a9cfbb422707c52d6cc091501f082ab0e106951f452f0302bfcee0158da135ab5e5bd773910b0202d6d062ce92577dbe978603c574afbf462b196350a6b194a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x1025135f27293afbf772034aca006b89058660521923695d76a4ff1e5b3d54e0f7bde8b9b21900351cfc8e713492dbac124b0736330a323f446cce047efbc42cf5d46dc9b6dfded90161667b69b14f33b42eaacce04e03a1597e890aa29feb9e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x171b12075ea694d62f6100b26b0f22d72ace085eceee2d60e449d18f57e639e73c950b04c995ee9abec90184062071a60d3603eca9e4e216de19d91786ece6ec2669242ee9178b4cef7c0bafb14f16f2a78323f1cc51b91a9eade8cefaf59ffc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x0bacdbd680fd96840607b2df89d3ee01def1d51b91a106a99d106b1538b37f62c6c8333919fb00df82cfba4c6469201905010561f08cbc732763f300a4c461b6938224870fc97eb1bebbdbb63f3969cd5fb4b4bc1fc300203749433e5ba71850) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x144e5918959eb7c28dc9117210e11ed52b7fe1aaec4655a9b41b87188595c2636c33adb7ee156a63ce1f40c7cbf4cf8712216b40366ebc2a1c5a284a5bff3804f9dc698756d92e10f5d72bb51150ab2dfe3a5ef09eb9cc699a8cc87d4534da85) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x05e5bd713e2b43295e9b50784b2416dc7431f057155560b6b260fc164676f5b3a2bfe84061a12ce5c31069aca695f1790354f267c52a1c3ba6601390e4436fd369194abeeb5f30cab899107cc830179480aff5d138d327a9fc1006a31837b0d8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x0a049b6b2bf86d778d6666ed819c3147f0aaaa28315e7b1e1b904bc12f4a8db4f50690d68bf2250c019449e15d126b9a080f2870588412063535032672fe879daa966e6e40294e9d29a6ce4a6b0be3f26b0a1d032d762a7762622bbe749726d8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x07499c01c066da94c70ae0c883d59339098e2ae1c265020508486a04c17cdd59b6789dca1134297a2458307737cc65eb02bf943d425cc75ecce827e2953cda3bea4c96d87a2c4ae6f385024c824a24793bc644ead2a77179075b51db951d8692) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x1233e8755ad7ef8c6fe37abd8322e15a34270e84a1931af3225f8ee1ed0761fbb9059662c3f86fd91f4fa3b0aea7e67e063ffb0d3ec9593365c7c16a3f1589a56de59200128f0f031a51165a6484f35a49dc8b9189bba6976079ce19e5e35404) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x047b382113356f5bf7585f739104668f89d0cdedb89266c151aed5367a8f322c6e9912ff8aa653574c1e406dcaebe5bd0f6bb00734420c448042fb5c13051159614919578383329ff0696ac565562fdb9dc5854122ef0036561f67721b3c0ed3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x063129a2aaec9991ae5bf8324bb697ca1c490ce4fdfcd167a760e3088156379b4a9cfbb422707c52d6cc091501f082ab0e106951f452f0302bfcee0158da135ab5e5bd773910b0202d6d062ce92577dbe978603c574afbf462b196350a6b194a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x156836c5f3a270fbfc71786441a470a2737aab92b3b6b3027607865cefa3d10c2a5ee366ec1db598e563eca041ebec621412a99776342cd4defb3673f2b5fa0d3064255d74146c7455e55d9a6e14198125b95c4cf7cc0dfbff77c39889c610f1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x176f5f1f57288e4b133cbff5611b8028b46460f2084e004ea6bf1c3e33911cd2c020e1f7389a99e8f4db30e881d8f5e00773aadfff8429fd161c285977090b5005e136748f27b465ae89e26295906df33227395fad4d99b466c7141e94e8c293) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x02c7a78eb4807b538c0014ec5ba44d58780d6e700ea54ae45b3866dff8c4aa668f845ad91f6a16720d865032b5c71add19843b1f0169a987c279f4f3e3955b4c4349227d33981748b28f604a8aed9471fd91272a157b55b7ee71ec23ce6db02d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x0153465b9dc8227efd8f18adce0ba1eabc17cffd7ed627456c537a582fead8463806ac459981a96bd1cb99ba58c2ebec1835a685a9a27928162d57f51e2b52c166c640bb9bd2e72c9a0033d4e2cb016d041b1b1304ed40cdcad66b3d963e5aeb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x04e38621e3c1a335f0a6b75b28fbb79fe08970315a5abf13a23d7670c0ea5c323f3d329ffddc197a9a5ec2bec93512a20687806bad5967587ece2bc63e23f29adb5902660a559ee706a3a6d587d035d184504a4b9e8a1dde7106e6d179d4b441) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x03773e554ec120b47b48e37dab64fa0efc22d6a3320ca9aa75a9e0d2d52a4f15599fecd4c9e6a7615ef14647720defb516d0ba1fffb303896ceeb44111b78d64b966326f12cf69692f54796701c13dcd605c278cddc15289c9f9e4bec142b167) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x0ea4ab0585e9d531d5a2affbb6e9d14da85dbea5e5ab78835961c699f5d4d1de5cb761d1cd07771cd8e56dcb977db07507ada85f8bab0a7aeedd85a61bd84bb505ed3c136c9f116cca8ca77a164502493599b00f3d0ad722a72c931f81ebedf1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x18f82e4740dc20cc275cf1cc7160b13c62a4c757df9ad698e7f5df5fbc4a1118a9e453c92dd67472c3e5c61a3d19a5aa102691e5125cb9ddbfe8d13f9975c5299612e534f2a83c35aa7ceba964573fe371195e741d270392c2be713bd5329e30) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x0a86684fc72a4e2dee49a5ea383178e3a795bda53cd2af4cd428374c62ed64d403dd2d8b90a9739d682edf37b26f1021047a441cde9b6b3c1839f4b8f9c07a443ca35d44e878a04609dedb71eb056ae840862fe9e933fce4b894a96906aab066) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x0ffc615d86d835dddfce2847aefa2b9356560d0c13df0ca80902fd3000a2ed6857f784b26143d2e425d959801346633b0a9e1097650528b9cf99d91adeb41957560426cc7adab6e45db39d5791c35c6373aa333772943efc9363661abc2c8315) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x1025135f27293afbf772034aca006b89058660521923695d76a4ff1e5b3d54e0f7bde8b9b21900351cfc8e713492dbac124b0736330a323f446cce047efbc42cf5d46dc9b6dfded90161667b69b14f33b42eaacce04e03a1597e890aa29feb9e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x176f5f1f57288e4b133cbff5611b8028b46460f2084e004ea6bf1c3e33911cd2c020e1f7389a99e8f4db30e881d8f5e00773aadfff8429fd161c285977090b5005e136748f27b465ae89e26295906df33227395fad4d99b466c7141e94e8c293) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x04c868cda881721aa9476ef08b428e4c9cb3167d54dbcb34313df677ede9d7632a4dc56616f2b4d7283e6004972dcaa11957f89ed9bceeac2e9db5e2ca282e342086214f54d7faf2c3bd7d198ffd98bd95f2e713d6f95d2bbea40404312020ac) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x0a0406a6dfca19affbf8daf605873eddab784824015f9e4689e73fa86daa39771d3a4610f9df95fa322f55b322344e930dbf2d00f047bad0aa8d3054bbd000cc5ebef0a2843e3f5ff555042c232463f2dbd888f5c113b89fd378445b57f3a898) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x0903f27e56361a1bd0e8e4badd679acaac4af9fa036129e8a8091a2e897bb2ed4d5de5100a52eca069f124be2ea964ec01bd4d07f84e5faf4fcc6fb055082041b6f82c416a4d469f9ce5b4a8d51b85365d871f967e221dfcb32bdb703175c2df) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x0e69e0dab929d1f5ead3cebba16e0370f3ef18a72b80e2704dcff600d8e6c11b84d01c66ff7cec576ffaefc49a74aff00cb9d3d2a771815120ed332d888d444155234d0047af62b278ac6494b80753de716ecdabd4e77f8364feb65035545c6a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x075d7888f555f9e7eac62ee7b07aa7f8ae5118ea5cbccbfe9a116ddb9ec21c7dad3c29a8c4ab1bc765652d96f171ef5103ca9d795022086b1faad91136592663b8fecb6ca32610c91dc4ef5b594d4e66e3fd737ab8091d917ca240ca4c5f14cf) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x03269e2de673af093ae911c6ca36338d121a06034ae305569b43878a533206d713a15bfe25f2f69a356f023415799ed805669e11c9509a68fa752847a2691e8b66a8cd2acef8e9f8a421d56985fbc5610f625a926a3db22aa2f3b9598e3a5d4f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x145c9be227113316ac8e8512128619b41c45a63ab20edf62f53daa3d3ace9240174bbe9f46cbda102bef7b897568c0fa00f54d7771e7fb5e93c8c75b4576849fc1172351336db0dbe89a4cc1eec6847542ca8b1ce0da4e86d2f3e5d830674bf1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x029aaccc4cc78866eadd686825a2b48bf98b59f9c827c84d6a7663c20254f564c9bcd84bcad0ff1f6d0dcd96fa59ea0b0e47259745ba95228a9813f05942cbbc2186012eb63e23de41bbea46bc1cab64f80b9e1041de98f49c119df14f001522) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x0f2239a8444b783758f3e5d7873f05b3c939315918986421a02241a2ba2fb8e7de4c193483f9bb9989e328f3e4aa026f0a1f359cba3e91c5978b66e4c0ca02e5c6966e5173aeb942211351ea8ab59b73b9da7e49b9ff602299e3553d2e6024f3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x171b12075ea694d62f6100b26b0f22d72ace085eceee2d60e449d18f57e639e73c950b04c995ee9abec90184062071a60d3603eca9e4e216de19d91786ece6ec2669242ee9178b4cef7c0bafb14f16f2a78323f1cc51b91a9eade8cefaf59ffc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x02c7a78eb4807b538c0014ec5ba44d58780d6e700ea54ae45b3866dff8c4aa668f845ad91f6a16720d865032b5c71add19843b1f0169a987c279f4f3e3955b4c4349227d33981748b28f604a8aed9471fd91272a157b55b7ee71ec23ce6db02d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x0a0406a6dfca19affbf8daf605873eddab784824015f9e4689e73fa86daa39771d3a4610f9df95fa322f55b322344e930dbf2d00f047bad0aa8d3054bbd000cc5ebef0a2843e3f5ff555042c232463f2dbd888f5c113b89fd378445b57f3a898) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x0e0d8dc48ca8e5eb401a1e77dac46466f9795354ec6ae59119b8fb561c5e8c80031bf66404c16d370ae263eee2bfffb80ad0e49c0deffe979877451138d54d4846c363c62391da88c37e4cc4304e8f00bc75b0a50d5d4f2d19c129570d4cd709) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x0ff16e5c2228f7d1ba79342eb5ce926a1c9172516c29618bf5067d9babe822c649f5d0af16dde7f58856f79fe8c0642c0276e6f9e29896828296e8084cdcf9520d766c96c985351cc692c5a680cb3f2bdbd798830bd059a9a40ca35b2bc42bcc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1' +storage + (Some 0x174b443090acd24b63f00bd9ccfa4ca4f07c82ab80b3d02c8436e2bffdc6c8f6f058735ca48187fec910d53f3207c3d0050187821dd662d4f7680ce6eea608cb10164d3267ce217027dbdab08821e5905bbbbd30077a2812247ec251f61815f1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab' +storage + (Some 0x189c9031a7c9fa23f5d733b19353bc60559c75d3008eeeb635d72225e6c3ab8a4e6adf19353f41eebb2fbd3b9aa6ebea18a9fcee2568b75d6c47fced67a88749f512592dd0b3490b31c8a9c6f8c3a89e66bb2436ecd30a4454659304b382bc16) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87' +storage + (Some 0x07a125ff7730fbbb0a0b009ce801ceb5af3b26a398f92d666a6ba086589401d5c9757abaac52da844bca04ff1a06a6370192af3fd6f36c1da7ca65c3bbab1d7f94976041eda19e5c796a11118c7c53fa73829b1128d5ba0824e29deb6183c530) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9' +storage + (Some 0x04fb7ad2c096670cf3375d148b32c85ab1a6c4c6ebd35abd5ad2ae0a8d8d35561ca4a5d4b3fdd72f3184a25b1769058b0f4b9f0e50c0c70e2d0733ec6be54f7754fd134054d13aa67b5bb86a935b64d29b994340a5c8c2c34fcb6cd5ac3f2b80) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4' +storage + (Some 0x0b68fb08cb23c2087951474646488c4b8cc53e8b2355243955ba35ee10a154a41893978a43e25ebd19aa279b2374d0c10c15cb33448a95c9fcf9ed8171ebcbba030ac7d07ec5e391a937f3b0bd6f469175de8c13a964667d85cf6031ebe94b56) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89' +storage + (Some 0x045dba3dc8f9e481ce42fce5a8f07501d1faada257439f987273acabc0d3aed00e4cc3948fae082ed24cba5b12b54e5f0d55da0aec1136a24464a5f8f1ac8d58eb893ba95131f2fce03bcb35fcff40993f48b5aad6a80aabeaf0b9d8d7d957ae) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5' +storage + (Some 0x0bacdbd680fd96840607b2df89d3ee01def1d51b91a106a99d106b1538b37f62c6c8333919fb00df82cfba4c6469201905010561f08cbc732763f300a4c461b6938224870fc97eb1bebbdbb63f3969cd5fb4b4bc1fc300203749433e5ba71850) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42' +storage + (Some 0x0153465b9dc8227efd8f18adce0ba1eabc17cffd7ed627456c537a582fead8463806ac459981a96bd1cb99ba58c2ebec1835a685a9a27928162d57f51e2b52c166c640bb9bd2e72c9a0033d4e2cb016d041b1b1304ed40cdcad66b3d963e5aeb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60' +storage + (Some 0x0903f27e56361a1bd0e8e4badd679acaac4af9fa036129e8a8091a2e897bb2ed4d5de5100a52eca069f124be2ea964ec01bd4d07f84e5faf4fcc6fb055082041b6f82c416a4d469f9ce5b4a8d51b85365d871f967e221dfcb32bdb703175c2df) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c' +storage + (Some 0x0ff16e5c2228f7d1ba79342eb5ce926a1c9172516c29618bf5067d9babe822c649f5d0af16dde7f58856f79fe8c0642c0276e6f9e29896828296e8084cdcf9520d766c96c985351cc692c5a680cb3f2bdbd798830bd059a9a40ca35b2bc42bcc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb' +storage + (Some 0x0b0e66847e9e898a1ce59e952e7432cc12ec35a2c2f833564f60a005d213e32f93ae2049240d9ea4cf35b57f3226be0f052607166cb214d9cdb837fccc2e1c5f0b6dad8e6d8e2dd17128b3689aa3121dd455cdf228898f9570a82f6773574a79) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- mul.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- mul.out new file mode 100644 index 000000000000..57ca0eae08ae --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- mul.out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0d6e26a792fa06ca00d9b8de7b764194a035b75f8e55da4fe2c7c8df6c732e61f1cd4a5453ff19f48eaf7d8d35945a8a01153bf80f1924e3419b5b5426d56f18de4ee561b53b83a548550db77a6110bcef17edca9bb63473611bc77fc7a5d5eb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x17fe2df3460e58f64423b86a85f51080ddda61f77fa98a4205faae453f9752d45a8d8cdd3e2c2b55975e1907c7ad32bc0922f1eb6c45c9d7520ccde588959b79eaaf70b393d780698cde0a6fdf6ca048cebe0f0fbc5f5ab801f13e8cee452c64) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x0b214a8a80d9907dc8673387c7ce8580236b7dba1acc6dac23397df4086ac627fcd9e1e6dc6d0f35005a254d2d5e596316793aa0ce436a371fe4e2ba29b8030c589334a580ef0b64a4b62b894105486b12b2a2ebd3e12e834157b6eb766a1a46) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x043f37fa78a29f961f94ec41b7106e72c8bd964d987fe98e3b923af78e82eae131cc1384cc1ab5b1297050e4c8f5981918ceb0c411187ec8dac82ac65d5f857b806025be878d67c68a3f7f577a6d67ba86a97f46af156302159623eb943d88dd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x080a6002efcceeb454fefba8de269a0dcddaf1a31277b9401c394c27bf93f6cee5c3a61aa51249366df85e142691cc360222dff9b4cc37bb26bda84a0b07f57a87ff916a1684fe21aedf35361c2e2d4027438eaf5124cf0a65316b311fb9daa7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x08754c98e4c7db757b21e834f4796d2cdbc5e4def2b810b61950c8de91c952ebef5b4fc24c24eaaba16e905acc610f360cba7430aea81354d2b199de002bff0505483967c4d89119e58a417374e80253a09b64dd8e5866a39310d5c6c458f8b8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x04b65648dd092c99073e6de155f71684a774baad9dac389386532de497f215a58ac1fe2f6a47ee9be3b7487eec32b98807a5369fd1c9c9f562cd815174cc29ddf313dd016d29e33e8e4fbb99c6090eb487c7a4a09bd2d68262f517fefd89feab) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x0ee94578ebc9106e3e193d6d43803d53206baf8467a9c387a122d67364c06e6b386bd3d4a519e436811dea5335f001ae03b0ca8045c3e9877f522f6c72669b7a5dce3954941dfcde3ad65add4b32ed285bc7762dc81cb4aa8dd30466e8e58cdd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x058d3f9138e02d209f1558c2dfe2461ea55dd3173cb680befe0b27c6ec0809393e5625d5d10edc54f8765d657fd960cd0a511c9ec52fd74f583dae9a45b19bedd2f0c9ce75315622cee29357bccd2bdfc986603691117c9d724ce0205389303c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x0c972ba34b8c6ef2ec4773c0514d51da1e434b56b137895aec2903dbd39e1f46795578a8761474852689ef734d963a3a0c1f7a974a05641e95fb07a64105c403fca42032a04a0e86595f28093322f0452c11b683a0d86f1189414fd8422bb7f2) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x01209e158bc71f282c096757285359a9978c143b02d0a29675168d2b86b3229a8eb9c213c59793fe85d861df05eedbe001526419a19110e7d15fd47e6065534566cebdc72a737d67d6e10773383541d1f30cdf07c00b3eedaaf4648896ed9321) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x0efdbcf90456b6111b67d48bb66c384eae0e3ecf9ba0d9a232d26b7615bb3bb97e14d4476a46e34f34de2325094e61e805cdd9f46928c868b92c0f7e8b1bee1f026d311363e7bd8cd52aed9c5fd94049bc515a9fc689a60b3c603bdcacbc2757) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x16bfe181c59d68df36da9ecb00873116b68564b6dc4bb85f9de517ce67200edcbf4d702750a9f1922c006499fcd101b103e690bbaf48b60a6c2ccd745e2218f1378d11a9b05bc8cbab4e9ebce6efdf4a1f01e7a83c40ae65d5c0688fb4c5f929) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x0cd9ee919f76512305edd0dc3a4e8b6836d128f4d057a6ad043eb1009d8363e4d3d114f91722441871bb03b4436b9db30a6435fe87a9a201d395a339e09d5aeaf7343023d897828c54d1c6f523b17e11a0b7225960886fe0a72ae28ac542b826) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x10d5f9be440dbab37077bd4a47eac753a08b0e7259378586c5a767e9f60db07ad0377e4303b765c1264de0d920c9e1c60203123943e2292b7fd772d97b6bfc87f13b3118f23e5a73eee0c013af220293c5672487d8a420dad371425778ab77f5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x0bd654c304dcef58af952ca2facb26a6edd39299c8e6e84c2183dccd1983d54c42527e0775bdf0c41a2692f7ee2956ff1414dcc51826e1a30784e97dc2a6c22fa5a4613018675367f94ec38f5c0918b1a3497496257d8498c9d059dd78ea0f25) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x0063c796eff234d7868560f197512cfe7573c699e56dee2e45cc8cb066764879390f45fb629ebf867b050c0533c3c78604377f82dc13589f87a5b50e386c24e0a43ea56ce66f18482ed99b36c4b19751907d3388f9868d9bc7df0a505c4eb717) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x0af79cae8576b4995da38e6a8df9227f5415802db3f8aa4c3974030454bcce23328c0a5a255a6276b5fa60fd14757673153047aaf80c925bb11d252ee92d3336b610e12a1a9c5501cd3371d9f7d686c984b22c87b85567983d742b2675fbadd3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x19c0b6b19c11fa412a86d88eca2816ba25670d893c135e0ee5989656522af100691986f0060b64d0fbaad9638679de5b107ebc992deef3e31f34b16eb3e44c110d224ede95a2917b70fef143105b5ad7f938c0b97921b2e118aaf36021d709d9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x05d46d0fe823a21ad3b92c3deddc6cee80b776999e443a87849cab0431d66c092b64555ccdad0be84c59c7750136bae1193ec841f45f830f5bab5bc5d5014480c769499886a248b96fc8c9f52069b7541b8325d54a673c1dcdaf987cc76c2986) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0581a60e8bd8b0f1afa867dbe6d131da6b717b349cecfbdeef91389c897fd516e48dfde89a3c27e411dc0648a684ee0705d00bc33d960ac54d895e80131633ec084a47ada7c3dc1e67b6bd67156facc995680292c2a3f941c36fb9bfe61feb35) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x16358e52d519a86b053da1fe72a1e883c5fccea9c4664ce7c0328f6a7026a8111707dcf0e88ee80b2cca22d411a7332812ba25b327c899540069136c45f2682fc27e5b1554b93a52c1740a154e93d7fc70f736515cb88c825f4cf7d2faa278ae) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x109f769c6c1db02368152922c9a6a8485c87bb9caf77b6100a4f1f5793d3c5e626b8c55ab3893c1022916ed59f401a39033697f5dd1db013bbc7ccd6e03298e87e2875951fcf420ee945b6079f8436f9f244f57f546a0e5f7778a9b6cbe00f22) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x191154d5a2eb393270aac8e4b85f6b28d6e2d0e8a714f36415192387826c7792a1f852cf268c811c65826120901a9196083f3e305a0fa97e67ce8ddad76603ee1ff8a8aaba6eff4058ec4e848860321818cbf190f52f4dddef254cf0c9e3f9d9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x02cf1bdcfc6d26f1fed78c7fae531e43de9e623c13d418114dd9725607d642f5f26fadbf9d355ca47128fee32a82eb2c092382870014bd64bfea089f0f6223a85086f87732c01d38d0421be72da85c72568e4fd7f8e7fcc349acceac725d767e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x093578079471563622bc948bf363cba956e331d785c606fdf76ff09c8720befa99e7a6dd2b01133ca1107845aa9ecb4912166e035e664963740f46c3568e611801a8e5819881f4bda8790da9c69dcd02254f669973c9fd67802ef6ed07d232a3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x0825703afe4debd2b09208272077e0b301d3a2f10cf436657107ee668d481a441c037d1ba3f1301bc6477433c0079784037d217fc5ebd4f315c615716d6845c2c91002c3170b55f8c20616d6bdc310fd2936f2e50da93fe880eeeca93ea86d2f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x03cb48d18e9adb6b3d3dc449110dbea4629d40523e6200d4c9332f092cc594bd6591cfcf71ff88e7ad722d60656e56e60f8c17788b46d9fd6bc6105115896170d7741b5fe14805325e1561693ee2a4784d48db858e0aafcee62b921f385abb2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x0157d419405ecca995ed95d32f371bdb386bf3058f71fc6b950175274dfacc2538ba0fd8b0fb0424911cc5963fcd4001144eb623857acef3621b1e6ec0f5a8eb165b699c8d8b9e3e6f38fa6da6b3be44c9b5c741e1969a70703292aca20516f0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x04c34b7695ba3c6a364c0f966808f0fbbd8bdeee360dbaa0edba5f7669bc680d002fea0c7ca791bd9c993ba068bb9d2410dd522d6afe1938b9bf0deabf7df30c4e30f7bf1b2691e062a8636f0cb61cbc7f666429785d59119c5c41df18613ecd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0412203264d756bf628d76d1b477493facc1c90068d318fbf33949903de2eca11f6ed5cb3203faebef94cfff11f357471815e371eb8552dee3f38fab27c7aa0e88dbedc8bb7319c02d155686ba73ecb905440508b5fc7889c755e85bcbce36b3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x09fa323fe1c580c8d71525094cf8cb8f7b55a73e0368b9c969e11e2a134c2ad7105b9372fe54748f090f2d9699a08bd80ec04e61d1f6e61d7e4db2a71fb882d9021b377842b7c23ae501b812df1a0ebe39727b98027da5c911574f34492a9502) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x0815e357c2bc69e70d4c07c46a2e9d193e5ae458f756106b8c47b9d300838918377c592bec0589a76095f3147ac669f00df6c2ba7d1e05626802726a8ccb0be4f1a824ae5ace601ee827fbfb2f01cc476129928b42fa98a6a417de56dc66cba0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x12b3f0225229b39345c7be73973387f2d2f2ca09fe46365b01da1d37e67c8bd90e652fa5bdc155fe9689396f1a4186030484ba1bdcbf27188ceca03bdd300deb000c0b1babc7f598c724678742d7ec38fbe0a8919fa370515db41ab306dcffed) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x06e459cb9410459386c79b2fbc3629937e84c031c6204987b75736a05069a1f7740ea59ecd874a44903d151bd2f101080bcde69f48c6fcde9d38070fabc3ad3d9f6b66397fc5c59e2906e4d5a987f19391ba1a5b612ce442bc33fd141ffbce2e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x13a643311835dab38e1324b293645b7f5c02d65851d818e869fc82dee998a28ee22b24c96355c4d957dde9b86814d0ed17dad0a4a74fb5cf26bd18e409dbf78c83edabe84ce7cfbef4b1f626f31ef0458e3e1a36e3cdebe0c09e102a4b24a644) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x06ed9541af33151e350f48b4935c5337561511bd4d6cbef143d81233df830d2df6d2397cb926ece52ba657a25c4eaeb00d7c8a9ae83d4cc786369a5c9ae73c0521f21f424563977f78b9de39aba60d8ab6420247227c5ae374ec100076543878) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x0842d0104ec53b7923bb1a74207f4a11d989dc8fc6c466961e94f9ac0fd5a2cdf69a637ca8e425115d9963ca7d66938500ea145353b6382fbbbe69ae3d09f25e907bf58d892211ab0bd2713cb68a1a3ec72ad8e54daf893ca8646a8745142fb7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x007fb59ca921180a904ef6b65a48ea3a04344dc5bff73323bd10fb3c7dea69ed5525be5812986ca025ac3e11c96dc4a1198790659672a962d70bd1996efb7769f36fbe4ed9cf55d071427666f2c5d73655f193f20be7801cbe2ef168d497a58c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x02cb9272e282673ccdf8a17e77f9e62919e40670f9844f0a85e7169a431f16341fcca482d26b0bb4b3dd92815c2e725f13f36f55336203e46335e2645f80fe8d9cde1bf5004757ea94baf2a97f548bf851433c0ede5f6354d26d7dfaecf791b1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0ac32d3741b3c21b18ecfede1bc11830df9091e06dc97e01a81c423b26b092dfcaefafe329ae3e372953f977c43c47d6022dedceea66a9b7ddf2b97f271840295d7847fa32e2c71b4a49efc82a474dc7684e7ef2880cbb5f9256e9ef03606562) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x0036c4d013887bc6a143e179677ff8f26bcb79ba0988e12f24846ecf188b65c5718e11c8de2b6226d008d4624284cc3b151c0e5c1e1d54ef2dc56370c82f6b849938b47609f1816ff3a3cf798f8eeb0d00b43539f8d280cbe79f3ecdf33eb0a3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x19c226a9dcbe4364ff0e70814ce83d1babf4cb0425a6d483717fae66859e0341e856a09a14c6bad075d3b523bce47666133aac0bd2ea22d48294764c254b7b4812c11044138e958cc050789b12255a0f28ef5d4a0990d57006d48448e6b9b6a2) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x0f703f711e1d82ba20be14d2f38c2e7c16986c917bcfdd733781e84b0f4acec21ac735420f07d57afb19c815f700395b0699f961928f57ff8f1ee79612ec447f0a67df0b12a73bc7c5c99d8fadb59dd2e46dbf24853b2d2b697ca02da94616e3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x0e49831f67b497f143e2084ba6e1c2f68f959e8d39201a5779b6549cb96487f9ecdd21fe21f11202ca419472b526f14e0d45f58a0c3a81a2c549ba7753898f080c3c763d72421189403742c4ed6c4ab588672bdb6f491b4b16538196a6869f01) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x0e929417f5b4f243f601edef1957f6376188c0e79d4948b3f3b3f8364ca1666f34fcc51d8be3661eb6e835abe8b1896d19d3e29517f6da19cf29ee2655da501d1427a3e4a2ca30a291faae2610a0467c7de31fd16c197e8458f7cc5047a0a385) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x08781f6ddc3dce9c405c283c560ad4ca580fdd754c0041e226272084d4f1d99b54e70c9a31706e0f5af360a4bcfb261c05fe250228db136c26ae15e5037cbd6016398e0a6e06e1494d37fff31bde2e7613c3a68f487a2d2af80cd65d9a4aa984) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x115c25600a2070d2427243bcdb7dd830e71cdf857fc9e5cbe1d68c953cb958313525764e7dc8066b68eca6733f1a883a18c59e9c634c3b96c9f2bf7fee37d051921a581f5e3df22a1342b67c312c7d65c17b2fa9fc108a80624b0b43358335f5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x1003a80b03182c8f2818ad1afbb6d6b96d6e54c2caccc065270c9f47ce5d31776356404a9fcdd8f9a7231facfada2ad00e543844307834564371126b701746614751a3d16f5accb4c95c888ff1978a12f3572afe2240367e36c1dce9ea63cac9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x06bf7ffa94226e2153205e53651de677bee80c436071611d20f1a9693f73449b97b72536a0e268e3173a24817232ab8806ebe9cace12d9b6151133b6d0808cd53ae57465159b0b2960a59e38080ca1ba23971455b87f7c8fb85e801baa3a31c6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0ddbdcd86ccec51f96b0a57375d75ca04645c81ac28d1bce2527163b8cac1a61741a733af4760e79cc22b243d4537ad919cbaf2df20a4b2855fba6a11385ac6592ad2b75688fbf954a32987654d2c73726a3fe43f850517c6a84ad32376ca9d0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x002730ca798014e3dc1841536b8dcae73326802527e040f9f97766b78187bdeea1177575d979b182ee2442b2e4e053ab0932dbaac27d3b426086be8159e7c7fea786fc923e7905cadaab3e2217a2a6a163e51820f9aa19edd4f4c13ef411fc0e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x0d66a57e1f124899bfc14806aef8910ced55dc5e2207c4db61be383e9dacb5e3a5900870c9decb10119a7a9b3a4be9ba0ee8889a386b696ceaa9b14c2e2043a5096ef886fe3e9d3dcefe3c98d486e33a82567aaca5e92f9f1876a1465f3fd88f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x1420f06251a40c38488d2dd5ff497730bab5ebdf34a95fa11bfa318469dbdd4c02a9312e88cbf7a017aca8ddcf752b9a0c28b1bad0bb96b057cbc269b5ab9ac27bbe70d12811531b9bd005a64a3a84678449186d6bcc2ce3e48a8e883f173b3b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x113974887d62d5b9377648bed8adff649685b7ead814cc196ddbd7518e7678dbfa86bc8bdd9575d42611dbfcf152cf43032c9ec93e81df8289914fb15e78d78bcbb4343525eb6af5e49fcb98c6586e044f464e3b8692418ef0b28358cfdb124f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x1402c2b145c9b76dffd86446dbfb776937ee10f568aa405e08bd5e6a0f7ee4b21f29b9bd159445198b602756c81ed58e005b2fc7db8095d4917ab0485cde75b2a75268859940859ccb53805a5885ec012ff6bb3ab063275f27044eed49b1665e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x19f7e1fc95fff4e88bbafbb8dcfe23ea621bc1f769b5d3d1dc349d2d14f74c88fd11f02bbe4659d47b8eadcfc31531850aac73a54e023a918b9c50d24f887898180db4146b99d3d667e6c05e827ed75c1a7e7d0255a83a77abe3b02a0807cb14) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x07e1c14775179b867f6ebfa1e4eac7d0bc2d53a90007715d7b841634f2fd78484e86ff9a17c5c4c698754d7fc3c5a2e7112e6d8df62a83f58cb270c130f947905eab0fb97a0af59268b09e0decf6dd18922b296adb0e49e6905b49fb9e6313bf) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x0ed6a47e24e4ce134d1988c1c8c9e0d3afd8ea39e8134f3d6d37cb73e1041a4608ff056224eb1d257091c74ed44945591149d34d74e2e2e81af2587e3a217ffdbb51ab66f490735bd737facb7b959c9d2699a9d7f11c167e58f3af452f597156) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x0cdd5304ddc0d9753d36e5201dd0b951d01f6f9f5ba818479f6331228567afb672a9f4d34befecd51f371a1a3b2c11920d14ddba2c46ef3f55b93e6d4b6769456f1150e60ab802f573eb10f35d98b96290c8c58de3b10669289bd08ca8eccb5d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0108f6c0ddb42d060a3af5bc726bcb432453c3d3e1d1d8ccd795cc6701335cad137dff61b45e03bcea976a2cd67feadc130a706a407be7237a9d6de914854007291abbd730afcf597670d92b38e6403d509bf1d0848b495d7a4d8d9b3d446d65) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x18232e6e86cc51cbe6070a17bfb510b5e3a708750520bd532fe6c58bc6cac63c9f581234db968a4625d1d4ab90f08d9e12df5cd600e9c63123d4afddb4cdc57e13571aa7b8ed21fb2f54a4a988de14128847718fee4c6c5c3d4c9173d48f4a33) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x05975c859134c5632bb4b246f039b0a45f43dd3d31488760420d40bb52938c9aae329d7ed1fd6c4871b088942a3f50c517b282a2e4f8206249ba05d50a5851b0c03e9ba0a6b0c829755a5b6d31f098a9e7e4adcea5c27f6fe4a4e0c6e4b1e56c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x0d76931ca7049490da586a0c79a51ff76c0e475d9fd1ad034f6fa5eb882b6b8dbcbb3eeefc37d13f6a3272ff9bc858b014e2a3325172bdfea48b616a6b21972f5d4768959efe3e77b3f96b9183d8e93b46712ab1629beea8e03007f4a17ff1ea) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x08f10601fa25e24bf52035d5a8216294ae54378d4b2b6df3e348cdf76a61ceeae5a31777af8b9199ba42f24639b533510d6e9f7cec3a5470e47b04d3acf416d748806890f315636a5d3daded30829dedb795f0b88afd73cd82a2211a5eb1a4f5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x0c9df80bf292db274c0867f8e9de81ffeaba73674cbe0b05f7ccd224e44da54beeab50134c0470963b1f2f02b1a31f851612ff8717619409552b3a086726e3a5d4476694fe82443a78b782e28140e9c904e3db65a9449579185cf6ddee835829) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x00063d556853e5f82a53d6462d6b19f98a7bbce98df79bd82519016e6ab1be0daf3999ff024520c58d54c21133b579ed039afa406025f3afa2424b18e5aae85cf6f8fc5cacfdf72c44848e6f60bd2f2e9884989a324fb6375d2d27ce9c3c55da) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x080f3639bd29544160205620d52f07cb7c35e35b67336205d9f02bd7e7712457be7ed6e7dfd1674c976cb373a4dfc5bf0c4b4cba46235dc16f818d5337477fbc127d78aaeb514cb40142f93aee241122e0585e2bd5ceeb54cf0ff85e028d215c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x066d91ea0514e7d94e8ee2ecd8a3039d37fba6f263e725d3699ec8bfa29f866356cb6d104879bc562771baeae49a299c073998eccb434785bc205388a03dfab4af27249771397863249f0bbd8f78b15c8335e20c2ef6f53f48447c20d196951f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x18bd3b1e442351d3101d3c0eb50649714fb574beb4871a8b41a590a57ed2fa1e84e52714eb6f523ad7d3cbab0234449d07929ebd8ed819624cb2e7730142a8cc3e30d5a743d2504ae1ab766fba5ee2f0f1ad2e70ba765660f5879d8f2391587b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x189ad044ab536b008692b149d1d08678bd1682a2401a2837f41aba45c49210c393334e48bd7027423f5d33a0ab20a4991224e075b527700847a22ddf2163348477aa808f6811541d10b118929458a15a6760b5a3c3841c005fe5860970abe46a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x118d259c4d1924621fe0430c9b0eee252ebe9bbaee91e3f30abff7197c14d5f28afb2e1897631a8f3faf8d59223c32601306cc1c52ac7b090aef9078128030b373e251e8e77d16e5ac6f76e31a2e70a52bf7572ac824f21ae978fb7896da7552) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x1517b8ccca640e4a5bba4324187b4c793032e998abf5dde5f1c908bfe6043804288dde3b2510217d2cc900696a65e855037aea02c6a1a13b13c735121c167c29597007fcbefa359fe6f0ce27faa64db3675bae0d07cad071bf2fa00bc5e9e5ee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x0f6d8a8af238867f7ad996376328fba94cc45661a9064ba1a701870e88100e95223bba125538f55efbc7c6bcf75024ce0a6d758b2b6d5a7a85422a58f8a821b455e6c094194c23f3bf600e7117de4b35763007ed28d488865381940c9df65a74) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x17320a69a37a272eec8fe76a288e0bbf3c79c08b7f09de8c704cbafa8c01f4b65a915cf83cad499d870db8458a46136d10c2d589959194d422090e94075559923f02977fcd2ee8f5d168a1c59ae61c918e6d9bdbcc4e3cc4b7689a79481bf650) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x1449666cef3bc8e2cfad84a51db42fe78614f22c33b4dbf365e7be085a3d707e743f9e2d137cd8ff8dbea833426064141433ef319622fb2aa9ce5cb60341bdccc6b7cec550f09e12dcda0ec0fe48b119e5099a4a8d6e799902abd9b2eacea393) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x175e97f7345149ab9b0e843282989beabf92101f4012d9f99497d6711dd60683509f6e17f05ca7f080651b76ff9b78e00f9ea76aaf96e93eac161355a82ccd1a23660085e206ba21b17469c7c3f1d640218813abd606747a06021b1bb3f7a2f4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x14aa58c52ade1687daa89a62ab46a877b37feb8522613b9ac6ba3f38b696cf881ef5dcf25ffaf6e0309464918a18c5250f08f16eff0c3cd0bb3fb8c55407c7e3e416b4734c20064d234ff741f2820d157d9f4ccd7a9dd4b6d23f2a27f7427314) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x148f63418b0ddb0c4743651c6746e9c733cce23249be1d022738bf3a7f612e5116e974e62af35e54211a59b2be1e6a2f0ac062a73c2cf73e28241f0d452fafcfcae114e95e6e19f8cd01e0c21b48787000e05dc5142ffd2aba7ba8f35cd5f170) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x15525131010da41c91eaa0099c5143c6fc4d6597b3c0318082131909e0df3b08444a5bb77811f7ecde47174852315cd8000953ecd2c4a72db6f0188c009c947f71f2b5ace4c86d6c5b95839ce3eba6ebc206a6f85a098f7ad49e44678f5c8da5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0cbd79a3830a6b2426ed71675d6d1b0cdeaca9e1540d4c70b123c4ad2ce788ff606bd378545252019ee79023c8179521196f036818ca95956b2098a8363c3aeb7a12dc77cfded4000f1907ca3ddf5cf925e09dd4fde73e59a7554fda13e11f15) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x171a5c0b4b68cf054fb95797b0d61a45ad209c5e503454d04a4edb66bdb785934e25ae9988e7e7510b4a01287c2427a21483f23dec1fae160dca9356aeb9f599e5ab81eb3338c61e11a55f601fabb6ec4a92375006d10ae3042efd5732be60b9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x0334eac1963514cfb283bbf838658dd3ec5440768b95653431a20776b2ff56a38f4f216362fda81c7881b8fea94810ed09777d7e9b5717389c18ff0418f4db95d1464920cb48777547c9397e41664b508e244f67b3f9c336c1a0e184862a09f0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x1974a9648d96b93664d816bee78c023b8c758caa70b98f4e84d81c10c7e860115c610d2749b68682126d6f750cb2f00d13b560fdf12370aa290bbbe875f957bc1128e7a5ed06474aa6dee111f844dd4930ed7e2313c0fbea8c062c114462ec51) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x1602aef64d7582574a15c5dbfaa55f541c4b1936313a1522bf099d0fb55fa3a092d4ef4f0fa79d3c7d71fad0537e0b2200184aad8e371521b5a632a8b8b499339a917907ee5678994c48a78c29c0e5e481d2b8d9cd882dd306fc54670e1ed0e2) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x0b3d98f7917b7640a724a4508f2b45a658ec5f96f74732bdb7f5478eb02e974b8b2c212efa5f8511a133037cd7dc493007f58a141712efd80287130b4f93743402eb9d7c9258966a5e469d12346d9e85f0f9d5af40549b8687c4b189b610c819) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x079c490c224a88cc5def7af24ce353e7785a1bcb613f8075dd207eda8f21b07e90cf4f8b7d87494a4d5b8f35942007170dff789955eee9e6435ae0688c57951054f878c75002aec6c1a9fe0c4f9d647439d2f02aaf0c497ac5bd47b5a32bbd69) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x057c1db35cfe8938b57b7e647b725a11ce7f31f9ca96eb3020acdc3541bda8526d7cdc0577beb2b719dd389225216ae004b845bddbd5a08e807b2a27ddfd46403840ff0ec45d7529e5c3fedab297ddd7e6c5c0affea25e0b562105caebeddf2d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x0a81b0aab24a7b0818e030bcd0110394650021563ccfab84bda3bd1455d3ec6be9adf7e213ad2a4e47208c51330aeb2e0b1f80333a3ebe0871048d81aa7d736dd9ad2221a72efa4e3b7a3623977d14889049a6ad2cb368e06ef6d3fda4c9039c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x1456ab1fd1f34aa2387a150a3c4229d526c80ab1cd56bd61504ce666d6161c94301056a23bd5b55fb12a5296a4f236fe0a5b131c5374c0abb76124a09c3371be456df830c80e1484ea78ce7ef7d20242ca73a731a099ceb09af4b56ec4b22409) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x064311e4e9bf3e56333869669b283512059634911fbb882df4ff7d4dd9004044ec1ffc6ec41fe31e7e9bf802155130c2001edd64cf3e67f510c17bf47a6e18927f97f7bfd5f7933c355d5dcf2614fddd0806ce173ba5277af7cf991ac5ec0866) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x08596f9d4caea620acd7243a48bd1d678ca07fcc132c7ade82b931548c35b116fff0571f71f0b5baa3834cac4b4a3ed5008b312a1908fd68c173e54f9aa1aa1a35d04d3556aa47cdebce73ec3223ca4b38bbcbe558effdc75f3df8d7331c0539) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x19d5bbe4281667553492e19d31591a2b9b530f49f3e8d0aee5582b3b6aaff8ce3cdae86bd8da3ad78f98db54db0500ec151aa7063def967cc3f8742d6bfcc1a5effe2756c92c25227d37df0b96fffbbf8cbf6f8b9065dd7d26e915de23dbec28) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x06177116e0540177982e98464577ed3321eeb44bc08fed0f62e43c2dcbc5e05c8b9fb25b35ed7167cd09e5200a2e4e010d2757207ae5fdbd134b08b151e58982290a84274b00f1318f39145a8b430ee1bb9ea5ccfe61ac5e4f283d48e9115413) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x1081dba4d09a91baa0569ba390942a1e377531c6ae25b6d31c936c5822ae5dcb9341ca731f6506b24e920310e0f4e6af00bed415d9d23c9b88b1399e205905ec323f5867480033eae354d564fcaad70e859f1496a832ae426e4a708425ac16f9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x08952dc3ad990d8f0af38dee050dc45c89cee78148a19af6e105f13642dc2a8dc567050dfc0554ac42d26d8b5ace72e7018a0d8f7c2779e4638bea9c4661b20a6282bd478d4ce97af506c0d63a7e3b7bd3a9db1da9dc295cbbb1edb2e1009725) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x164d40ffad176068800c32f27a21f3dca1994594aa3d766d04c356fedc943773d91140070c43addff98e79b865767dc716a161db3f99faac3ba20f811113a17c93f6e4165a3c98a20e59e314e9efef31b521d3d0d44e2bb22ce05a11e5522bc9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x149224a246e2b14dd1a514a388cc7fca3aaccdfc9d1f0c82d00771504fd47b004a64f81b686d1cea66fff7e90a455081046f826d4dbd43ca19ee87e1e66798d076eb6e4b89caa7b14903fe0214010776398eb0a0d0509363f8b657b59e521e40) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x018994a13ed6f527adb7f1445660fede5989b265e2024dacf27629bce8d22ced09f117d16ec5cf8cf55fb2d36ef4f38d05e441d58eeaf085771de245da3b27f6d39ee3116cb29e0e19a25e5ad1a2ad38a7d91aaebb5dddb50025f13a44ac996e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x030b980ad2ee471c29d8200469d18494fee7c3d58fe446dd2ad67b6d5225dc6dfca718f73bdc078c63f15a9fac67b1550f90d4def4daddfdbc940db5b95bdce08137d87b9d3da7ed4c5c9616a724e9ca982f63d1703ae2f0c0ab3e2d395b0b1f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0xf796c9eea8195bd57ca5f3c27f7219bf2c250bd3f49fbeb56d8150689b21e164' +storage + (Some 0x0aa35e2f582a1caf2cf03ae43bf081685ee86a508e6a6506314f44eacd405b6175640619e163c018871995aba27577040988f2c73259d14c374b1089876718b8af7bc927acb1cd061bfa3f5baf1b7862ce5a9bf3a6f8a9d5a84377d079c6af82) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0xf70cdbfd81e72e0071b6d005033aa30dad5b3656f9243867092164442c26405a' +storage + (Some 0x0ab5f26308387a5e5300c4391c57fca5d04990778972c7bd3a5091c7cb678fbea728820d2baf234c4f10bed1af582458015004f283d08dba4d34a36a1f05a93dfb7395e027d24cdb024d50d0dcb5515721d506d467146fa599fd14edbf95e5c1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0xb5cdc0e76348bc94f2d9c9f1cb4eb21adf8fcc87532cd008362943c1237f5b29' +storage + (Some 0x0bb7053566cf001d96d47c8ef75df36dfa0338934e152f23dc9b92a38e1fd11bc47d0153ed7703a0ea464d3c650c651b07720e06d0057d16782b8e713a5bb38c072bad6dff6cdae4f61e9f5b72f6198800461ef016a98a7da161721d354636e0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x7f95ef6e6962a0ae1bec3aca77ef83ecaf40d97f612665e9fb07ab8edb13aa6b' +storage + (Some 0x086144f6a05a43805c6931d2028199a9240a02b5e280f0cdd909c0eda2caccd515822156e3b5117cba6bf8bfd471dd4c0dbabcfd3520461beae5f9db727d7aad699914a23b387662f7800f266363e84ff54a1bad79adb589bea30c2e1aaad25d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0xb29805353b39c32a593129948561c75c4cfd2665d6b6df1a4382852cabdd5a17' +storage + (Some 0x0406a55686efda6979432c9341b85e43ad67737300c96dfb62db75b848e63ecc93646b1e592b635817482963c984cfc70d3597fa84773c5e3500d61b407dcf0a932698a8a2de4285c81a8587452ea5c9a9996ffb625f81c0cbe0b9e8c8b7b76f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0xbf259528122a2e60641781c7383d4fcd6d63e18680131a0a8ae9a5d5eb34664c' +storage + (Some 0x0185cab6fd147f77b35d6fe0f1770a9859127bae94ecbd402b1ac2b1f65c27d0c83ad8da963be1b9635176b2e5c5a1d3072c47311cf5aae7a9c621b06bb154a4b89a65e73d311a75f1007c3e9606f366b05d6be349bd825694d1b7e48238cd12) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0xc412aa942ebc1384282ebdd5afc0ff0049e03fb26e2cee36193e010a6199b442' +storage + (Some 0x0e9736e5772bc8a33aef6d9a8ced43e9ffbbed29ba572e5597bca97806b64982f29b79d9958f4501bf4a74629cbf9253068d0105f3f16d8b03e3e7f7e73a67f98e1f2a20cb6f2d7467403b1b8f69cff726256becda08d187cdd5fc263165b21b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x22386f55e46149a2a3b86941da0b19cedbe3845a505b89df4fb8a99d3ad2cf5a' +storage + (Some 0x00ceb4de98ec92f7a3b6eadff0f3dd41830e20d5bf83b70123f70021ef22b7fcdeae86bcdecbfff4f61f77a015372a4e0ecfe1ca78dd49a39c9eeb36719e6b18d8be54f55fe3c18e0749a81af4a7b3019c8ffec71970631d76d2ad03b62e1436) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x692617953b3cc0fd9b98e44b381803f9138e78c9ec3c3e78ed10e430402a041e' +storage + (Some 0x0b663e6c5376162a968f41f23ba1c2ede975995078be3ed850442845d1fc6ebc91ecc591b58db1e568c2ca9e9e91b40b15c602104a060a08ebfd31e8aadef51b40357003f24223020553876767b83b1f51afef6a5d2756e0f26036eb6ee24aaa) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g1.tz on storage None and input 'Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x1713902a27c37a85f4c6233f52f3ebc6a85718185b9efbdb190bf5025113a962' +storage + (Some 0x0d9b1e3f917ef949642a2a30da1031096abf49145bd66efeb52e52ff0bd517e77a740d7bfe08a44d57f1f216c7b952c40b1a84788e90b7a37dd66b7ff6fe4b188670445003753f48235abf5f1e1d6d193f8182e5608d3ffdd2e2877e4d1a9214) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- negate.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- negate.out new file mode 100644 index 000000000000..1690636618f3 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- negate.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab +storage + (Some 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 +storage + (Some 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 +storage + (Some 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 +storage + (Some 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 +storage + (Some 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 +storage + (Some 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 +storage + (Some 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 +storage + (Some 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c +storage + (Some 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g1.tz on storage None and input 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb +storage + (Some 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- store.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- store.out new file mode 100644 index 000000000000..c07599583ab2 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g1- store.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 +storage + (Some 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab +storage + (Some 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 +storage + (Some 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 +storage + (Some 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 +storage + (Some 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 +storage + (Some 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 +storage + (Some 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 +storage + (Some 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 +storage + (Some 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c +storage + (Some 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g1.tz on storage None and input 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb +storage + (Some 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- add.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- add.out new file mode 100644 index 000000000000..b6cc71745773 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- add.out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x0fa220d57ef6e4195bef1c15c25d36d303589da95432ecf1231872d322dd6d1aa9195e14521269f60906b929f5e511c616ad91b95913e6d5f03c7144ea9a8ac2cbca74d4e4661a744c1c31e666a3b9e229d19f0f4a0849dabf8d42a999429688153a350f527d5b45b66f4fb7362472a9a14ac2e5be7fc7a1c07735b62fa366eb7d6b938dea2b3476c4efee97211ab51513312efd116de802599d7fe3406ecc09d9cd128fb6f6ec92cf4fc92ba02d9ecd623a7124f9936ae05810095b07daf50e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x046035dfa9f3f77c402f467c98c79d31cdaa04b517ca830495fd211bd96007d9e86e77f52b563a678a283a93e990b1cd0e920c1b17a7c522a1cf06d9eae11fe7a83ad560e264ca83539f129ec7781b2aab6aea834c7cf3790ea8bbf36bc8047f06fd35fac95c31470220839b5067d8324b8bc7cdc64cd02483d08fcac9d0ae2803ceeedb4ca0491c8d01543d57c0773a0b356cc1179eef81b6db0e5cf4a82eb452c038f2d84e3c523165c7bcee56984b43c78ebceefa58e75071cfc4298d8ffb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x0c915014aed040179e85ac98cebaa76ed11a7de7d2a9b50b8c595ddb660a7ba20352d34d3a1a682e416488d51c627db50d3ce8ddcc38ce2c0c44527d45e540a38dbff1324324b8cab15a89c00d18198277e22a48e959bb88f87d81f22207a03712a5b4e4d758741d995ec296cf72903ea3af86a3615df586334a0bfe787af1c9efcd97fad13afe8fbcdd60aa87744a1e0dbf2340c9e8edd52954ce815e3559ce021dd0676af7e82d1f26457ad4e64effd3ba90b2101aea30fee2aad64c779417) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x048e783c39590796da9ce919b19a7179fbf7ca422986428d9ca4c00afeb3da88f78e4f85ee312910119a31ac675803c703e8f3560833feab146988683e7c192154c6741f449f711ceb0b5c732ad8f488fe57cd5fe3e5b1eac5b1d43af705ac4d1298b37bce78a4bb17b138b420efcceae18f300c8cfdc6417bdb84ecad21ecf6dda75d040401061e07e19a114dcd059f0354cdb917a218179ed3c1cee43a2dd932ae73cde416730172e886321c2f828cf2fd2c03fc522f3df06f571685eacafd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x0dc42d2bf532bcce973671bc74419a7d43b504f66667356c00b68126501cdd69edc6dfea8ca9bf757f9286c30aafb31d07cceafd4ea4ec714a310648ea80180e439a6ccfdc6ddf62b9876bd5aef725b4cf999f25006635d7cff2ec0b70abb92e12cc523377fcbb5dfd41cc087fbd675b1309f700513d5ea90d2a3b08cf005377cb34f64242fbd775ba63d5368ea6a2bf0d3487eb537b7a8ccdf230728b71e41056ef93b27e5476df0cc4246bca3640b37c1cdf1af59910a7a474148d55901b95) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x0d211843d3116fe2962e44424d5e1bdda2bc55b0c07a4eec8c0d417d3597faeb202e986cb03711e879f3286c8574615f14e779485d1389631195cce6b413184128352544968c0c48df886eb7284361d514dc38999f77dbf5d743add4bbecd4301288339cffd03d1098cc0bed90dcd583bec892c5f3c6922831d21cb8b7150c76ac4612ea5489c7476c1bcba216eba61b0a7447b1fd3d5383f5b2acd06c322ddfea84fadba0fcd995ec5ee701a34b9846e93974dd3cdcc5754bc7f21705b0b58a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x013e98c54426b5c356a094af259f5a6c3e3a16dee1b4699157dcd7b4b3dccfab401dbf1b628b60293512b5ba8060c7b80f3360d8b7afc977b5ed76e640ede1cd785d0c021a0478d6be0f43288ad75dce019551110ab5d251bc6c789b8a4d9c74078c767bad0eb06bb1447818304a37280ffefdfd862b137572fc3e2131d03cdc89f2637227e7303e7ab685f87d5f386e00102910864b02ff09d9ef9b534486c11b9ff933e8d2445137fc01e0505986e28b0c4b1608e5cd646a8c5a63b4febd77) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x170489c51747e88f11af77fe2d5a8e3615e99924a106963d8c34a966f643a7eb66bbad37c2c333cce34a9971f2ca87a8115b884e4f6c964127d3741fb6fe8b19a81108fb38135498dc4e582bfec87981bb814294c8a5e09dc7fd06097d253c950045ebff141ac9afd3d848fe89b37373978bf030afd38ad713caaa28ff9138d0bd0f6c4a323cc96864e1b1b6aefe1b850feec0b7f1b911f2c320f30411c33737251637803ba4ff4ef1fd480b9b98305a5a5f9ab4faa92b169eda541879af36be) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x1242ac850b78779a40f548b2ec3e5dde33bf432def2c6790a8099096ad6933e2c7faa78bde8a4d4e2b586d6a4d1f4225062fdff88df3cb0df8d5e2097e53ce61b17e211c63579aa95dc63df0a1824ee36852af030034bc218b9b1ce229cb9c8c149807239b0e175e864c704ef55ae2cc2ec33c71186461caee8e7771c5ca4d2eda4388d8fdc15090e026b3654d049957114812fdd6b7f9fe01b98c1c03eca0b7fd62e0113d902ef37f3bc5191182c983251af153b36f478c3eac4d967a5820ee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x18b4558b569b0e5b227388c9d844dc37bc0ad40ee5d5098871d396e09b7f85db50b78b2b33fbf656d02e83b45d04962e0ac8336661fd1bee9f074f35f3413c81d22825c469c70afcbfc724ff25750b7598493ea501e5ee79e0fb2d1e8fb5ee9f0b95aa27a6f20c52438ef3daa6f03c8bc41db48fb24fe73921425b1b4906bc60ab7e4b4c290f3c5aeef9a40f094e3dbe0a031822e3366d77078f5e93a80f8035f6f2941593f4f30481399f91431ec85dfc81ce11b824e9b7c08da1634b8e9c83) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x0fa220d57ef6e4195bef1c15c25d36d303589da95432ecf1231872d322dd6d1aa9195e14521269f60906b929f5e511c616ad91b95913e6d5f03c7144ea9a8ac2cbca74d4e4661a744c1c31e666a3b9e229d19f0f4a0849dabf8d42a999429688153a350f527d5b45b66f4fb7362472a9a14ac2e5be7fc7a1c07735b62fa366eb7d6b938dea2b3476c4efee97211ab51513312efd116de802599d7fe3406ecc09d9cd128fb6f6ec92cf4fc92ba02d9ecd623a7124f9936ae05810095b07daf50e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x12e844776dcc54686e33e5e2f76e4ee1cd3bb53a8b93be65342715478baf39038bfa376032a3c73e0b289139afde6c88140c4f3f0eedab77bda5d94b53f0842596fa673c1a8646a6aa8dd91ee72e1d508d0269d14efc106eab6f51e6f08c7a210c77db6748c89b678b3bca8e2ab6156a21f019bae19948d7e183c36cbb3d6faa7cef0ab8756645b52c97ad26569d71c80305f8cc81292b5fd14aa32933d3356ba5de2a9df2f216e5d01d18be8f4191f5a8012b786f34330a6142e73625fe7f2d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x0794c08576b1ca634646815a4dbee1be812a844e0e66d2e36ac1c1f03d30c290eaba39c1c330aebfe118fdaf3b5fa50216b2fa022e510d8502979b189c7d2ea12cabf1971636fee9c9288bcd3c3f9e5d525d44668234ec816ff6ce5bb29a0e0016736353f2200e00ebe389d5d6471f41d00d0d110396e2b6557476ce46586b8f42a569e2035f6407638d7a501fc99f89053d356e9f23575f131f51114e51a7d5cd3924d233828a18da262983f87adc6931aba26054b692f3fce47dea8d588ddb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x0a6aac5634ec9d9ec7ae20368fa1cd242fd56df6e470b2bac3c7087404724c11d0cea1aad848098d71ddb9d2708cef460abe0e2f2a7c29dd718ef4007fc9c872ef9fcf53656db14560d5e94638ee9baeae92e76b99889e650f1361d73d0b85a304168544ff972b9973313266cf84d5b2dadbd40a76d741d45dc75379765708dc2384a161702dba5a2bbd8bdcb1bbef7d02a3eb80499e7a428d48fe2fa99c6f3ea3c729db0176b3ac1cd48b8ff81d279c133078d6417efbf884c7fac39071ecf4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x1719f1a04b75f8dfdffa75695dd406b35d899d91325401355d2f3fc17abe20e6c04bf95cf265989050ea6be5285aea1708f5efaa1b197d90861811d8497844bf6b8e3cac9fb729bdbceb7d78bf324ceac87035afed4eff6b87efdea86974751e0d9ee16eb55482e287e2bdbf80d63dd5c83a1b16336b4ad078e2d09ce1255cf614209dd7a16228f242ef65c4b79fd2a71276c7a79747f69344c28692384b91b38f85c7bc10ae3f9ea3df0d8ffde7374d3a20f2ab662019b8770853bd39e21573) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x0655de0cf51271c9490062e29b8da70ee4c82939b26218118519aaf6298f2ef60721ffa7daa6a37133077b0dabd296830949eff2b5b24843c956b09c9417f2fa4820fd35ae9a01d5f0430329795f5e39abe6fd35ef8e9fccd43af92246207a5d0b37866f86062eb555caffeae739def30bbc454f2c8bfb1a2480e2f91926cd12b53f85691710c75802cf921b8a5b0fc016f834c60d5e79ce20b3172b777dfffae9046d09e52aa188e45be26b0e3e8e77b8328530a6446fb441a3e145535367bd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x0e9448fd828b81168cbaa65496078edf4690017ef6628e6cc5687082f255a16a9ad51bf31cd780cd03fd7946ce0b14460bdfcb61fa233217a63a372380068585f7fadc6978213e87c1cec52e52c5e84010446b4197e5e15ea7712f0603627eab0076cc785550ef9de1693c46481719f089d33d320fb58eb5e68c63f7dd3a4a511268506fe949ea89b320848d7c5ecf1a03ca948df7b1fa4905fc129a50b0b6e61faf0b05912f0c3eb397089a9752a228cb881331f7d6d9b1e44bfbf3f9090f49) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x097aaa14ee186c44f4781526acfa3a83929f5e39c65ff1266b0133e18d4c6ad549087a2aff86235eb6080f2c6f4fe2d1046748aa1dbfa1ae72dd3116fb4ace512d11a4df272bf34fbddb6c8020791cfdfd29eb4508e8bfd54a1d8b7e16535f7904eb63f70a94be19eb06f2a337006b4583267b9d8ba72e8eec424a445b423118a68a0ea992345c8ef4a13cb68e8ad80b108e284b312f574cfa7afc3ab6d9598cb342807b7686c2326d4d7a257d73ed383a420287d2e3c38eb321bdbd2aa861e3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x1583640fa782fb3c949c9a89b95e52818fae6fa7f130ffc5a8304ab7f78fc4d0050b0061a8e90b29f334fc7168084f4810486574b450bc33691aca553a6aad3123844d39c265ff52e5dc66f0d797a80cba141db073ba767a1021c654eb1a316b0193bd94baca5c7c0fcd370532502b6ac4eb19b3d10a3f4a48bda5858a888c5df42dc9153e70cdddd7393fe381aa1c6416e2203e42a66b43189b3789270d20ff285e3279667e01f18f686caed2c0a252d306afc2598a17ed518acac4e8b1b7ed) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x16e6319ec68d88c4ec5d017df123af94e924963d7e62cff44ac709e22282dc904f8367e30de2cb40af8a237a9641e82f00a18451fe0e97eb1c88b8a05aacf8fd3756c4703cae982bf8b9af0f864a0afbe62feb1a532aa8f8b332168b6c298055179319c180a36ea2b55096b645e8c42f31cfae50884cb06263ffe11b0a210d7f3bdb1ebf2acfeefda47cbfb717487e870255e5ac63c4ec740e2a3aec2e5134c6ce8afd43a1c793c42abd87fe0fa93c578dfd6e5d604510e1a8109b4b35b172d5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x050db0ea21b45502d1672a82bca3e6305f8a37689460f225920f4de664a9b3df4912f035314ec9b35d972ba67a522b8d11031b259adaaab72858a94000b15200254698fce139fe4f647a3a38e759144d7c7a12fe263194e3443b95f0e863c9f804ab9bf6e3eb7dc3515644dd29e5572f1ba34a18feebd12da678d35fffeb65071d18bb2dde6b6e70fbb14458e5adee12113aa6dcc7d3f7c25b84031fef1ce34e8b7eb8921b9ccb08d7a49f4c54e0e2cafe9eb9a009d86f2d118c784848c67db9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x046035dfa9f3f77c402f467c98c79d31cdaa04b517ca830495fd211bd96007d9e86e77f52b563a678a283a93e990b1cd0e920c1b17a7c522a1cf06d9eae11fe7a83ad560e264ca83539f129ec7781b2aab6aea834c7cf3790ea8bbf36bc8047f06fd35fac95c31470220839b5067d8324b8bc7cdc64cd02483d08fcac9d0ae2803ceeedb4ca0491c8d01543d57c0773a0b356cc1179eef81b6db0e5cf4a82eb452c038f2d84e3c523165c7bcee56984b43c78ebceefa58e75071cfc4298d8ffb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x0794c08576b1ca634646815a4dbee1be812a844e0e66d2e36ac1c1f03d30c290eaba39c1c330aebfe118fdaf3b5fa50216b2fa022e510d8502979b189c7d2ea12cabf1971636fee9c9288bcd3c3f9e5d525d44668234ec816ff6ce5bb29a0e0016736353f2200e00ebe389d5d6471f41d00d0d110396e2b6557476ce46586b8f42a569e2035f6407638d7a501fc99f89053d356e9f23575f131f51114e51a7d5cd3924d233828a18da262983f87adc6931aba26054b692f3fce47dea8d588ddb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x13de93d2f82a4593a29d234fb227db03f16f89b393f015623a52b05fb36813a3fcbbf21e29b95d78978025d9d5a6396a0ff1f395ee54e4cbfb57d3dc2ed0fea341f0c6e38266fd3d6e81cf9797f59e14d1f8a0d2ff53addc076cdffd23f997810c9767ee2f3f1c842f453cd4aefeb8adf07688d4811da35414c1a7433fbe5d6f59fa8c0574cef2a2d7e703c1954c19e411ba2316640e231ab6428cfb8d1d25f6a7bbe3ce0d8842d45151099ff9e845cd1eb75fd8d5c4494a2de389a0e9350ee6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x18bf19fa45d0936ad736e8f0ba44e75b71e263a5f0b64dd4338a33d98243c13b34125b9f49bc8653437e45de9d30a93a17ebef17433f244d7a64c0fb2b6667fc3f5bd0b11752b11ca48db539506cc87d1255ea878c9476f12fa76baced1e1dc40d2c7a1a772abe14400a371e2dc53b0e30139c173c4b63af51e0a8f098f779652ab6a7366ece6e726d0db36d4d869c1f15b760f663abfab268d9282848751fb6bf37b73d45a499a5b13d944177be3c183ea90a22c707bb1102c802c7ee72beda) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x040a521e7f62b87f49a3f96b3c33b3f92db0f6bb0e708b6929eb59829bfddee5005e98176447c65e2054703be2fd10df0cca3815ceb23335da24867b07563b6d4696b27e3da1cb00a120bdb1f506113c0df675c1923a791523d83b45a13102c101ff42b0097527d2b1d88646b1e68513b7f61533bce07fef8bbd17a592f3d7dc5e148a165633337607495e614eba86b410ae2cb3d04d352036f95c34417364368b862a29199668bab9ff5261f94fb6e5a00f8eef9d0a3906e57720dd315f7921) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x05b81eb847ac46ba0a7dd65998e59571ecd7ef546b7683388f631777015fa72f4e2463b4d193b8ab575b0aa8d077cbf105d25ba702f7c774572a60719894156141940a0a39e7ab838cb55524617826775b9ae494ad11213834dd86b1f02fbb5e12a932312f159aa63ff0817f8e4e478092fdfab946e5db0c05a0021374716d167cff0164ff823dfc39ec1f871233dbda0110bb37e8d5b4764fc40d6c7c62bddda525765a53385ead794d6442cf5b79fe14e2bf4a74874da68aab1507be8b31bc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x090024be3e658d797ea05cdcf404ba80847cd69c3585217310973fbdd59b3ccdf9bec4437325f24816beefae2c2986b6073d93a3d5f5d2758dd6dafeed80c6e730a512471c227036b0cba91369f2c1043e8722c1d87de3ba901780a0824ad90204a467083e873a87884ddb1b6455d36314ac953c47dc86f01221c97b2c70a62f24b852c291d49845744c1812b85a2ebf15ab172859a93dd93be43b59d784079bedf952b6596ec6926a22ce8511f503805914b72752b022bb32faf521764cb268) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x1390ef409a99796aef7b741837f04ac5b0971436b71987ed2164e89950b9834257d50b1e1595e7d423b70abbe9ab5d33110ba5f262ee8cd728c8d20116827832198aa304fea6bf519d767260f947027f544903b9ec4ad73b0404f705ad1bb7e70b8f4bb943637d1830d31f24383f251ba5d64281472d5230fb974afdc27014af81689d5f830f17b76d4fe61b6bbe4a21128c6036642b9f636ab3215921545b3d886df46475f9a11a4ae9a173069675a4a02560a7dd717f7d204427a5b33563f9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x0bd2a8921e426f811f8ca3820348cff6dc8efc095010d4068717724a3a076a565e609be3f1c78c4b37a61dda5259a3750e70265a91f14d71b38ab1df6f14ffc11f8ff8c552401dc1ec2a70862905724a928888ab5000cab2c206f147f49a9e01019581dfea445b53898ad37d69dcd97f00db2023fa4049a3a3fe3158275aab62cc16f14f766dd9df07852f7c5df27b2111dc81ab19b80f5842c7763b036090e3a8368b6db669d80e74c0231073a46835f7dcb34aab2bbb79faad55940977dead) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x0d6af0671af039e4046dfa84fc7aef856495f732e95a24e0958b9729ca4b87ccf8b115ed6d1b60265b838116f5c56c8e0e1732e3dcaaa2c0a44c5f58a3e2cba84005b2aaf4fa70b995d8c30f5d0c25c0a9f3b6388ac91da8f7c4c9fd084917e80c1152762adcb783bc96ae1e2c37d6870a174b5cbdb1adf5adbda7d88671247471b36c9d5573ecebbd068087f45dee5d16925acf0e18b5adeeb1d4659f2f8df4e8af39da572e425c796f486ba67e05f3b7c15747f35781294128e32cc66ab87f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x0a300f596c740d3a332118e868fb8a0ea04688ebb394489785ecebf2739443b346b324e3fd9246050d0aa1d3aea9f1ce0ad93338ac85b6a66c0f3fa35c81ade175275570facec6395631a1d5a977afbfdd44dcd174d2d782105a1503d25e9baa1717a6f3d40df12d5003fbef8dd4e176fdafd6c1bf5e62908aa160ecfabbc1a9d608c32417a1221d589f70f5335603200c9e15e9288f7fb90cf7101301dbfde0ee2051b698310f855b1d876cddc553d4ac3a88f8de8a99d7645595b4ee64d3cc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x0c915014aed040179e85ac98cebaa76ed11a7de7d2a9b50b8c595ddb660a7ba20352d34d3a1a682e416488d51c627db50d3ce8ddcc38ce2c0c44527d45e540a38dbff1324324b8cab15a89c00d18198277e22a48e959bb88f87d81f22207a03712a5b4e4d758741d995ec296cf72903ea3af86a3615df586334a0bfe787af1c9efcd97fad13afe8fbcdd60aa87744a1e0dbf2340c9e8edd52954ce815e3559ce021dd0676af7e82d1f26457ad4e64effd3ba90b2101aea30fee2aad64c779417) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x0a6aac5634ec9d9ec7ae20368fa1cd242fd56df6e470b2bac3c7087404724c11d0cea1aad848098d71ddb9d2708cef460abe0e2f2a7c29dd718ef4007fc9c872ef9fcf53656db14560d5e94638ee9baeae92e76b99889e650f1361d73d0b85a304168544ff972b9973313266cf84d5b2dadbd40a76d741d45dc75379765708dc2384a161702dba5a2bbd8bdcb1bbef7d02a3eb80499e7a428d48fe2fa99c6f3ea3c729db0176b3ac1cd48b8ff81d279c133078d6417efbf884c7fac39071ecf4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x18bf19fa45d0936ad736e8f0ba44e75b71e263a5f0b64dd4338a33d98243c13b34125b9f49bc8653437e45de9d30a93a17ebef17433f244d7a64c0fb2b6667fc3f5bd0b11752b11ca48db539506cc87d1255ea878c9476f12fa76baced1e1dc40d2c7a1a772abe14400a371e2dc53b0e30139c173c4b63af51e0a8f098f779652ab6a7366ece6e726d0db36d4d869c1f15b760f663abfab268d9282848751fb6bf37b73d45a499a5b13d944177be3c183ea90a22c707bb1102c802c7ee72beda) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x0913a51db9080ea2c98f0d39ca48c1a13c1da70e31dc19881aebc8e8372bd01a9a20f7b537aac8d3a7ca04560a2203050a89da45917cbde7ce124eb1f1a71ad99360787e3c9dcef63b49293e00939619cfd2772c9016dc58ec561b9fc896f0a10a2072b1e73a5c45e8d9eedb0f51aac1c6eb9205f4f22633c3e4188f702bffcc9c47bb7e4dbf24323021c4b5502f96b703a37de84b8d408a8da127fc3ca3b73d44ffc766c9009d46ea7dbcb0239ed853ab779e59fad95a2bc1a385a5299b84e9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x0f07a4dba873d6a94e491900c012798c4fabc655b547246881b8f32dc445a1c4b526f6df1c44147e840e5e19afe0b6961294f805495eed4fe60a9f7598bd74222ae3499b74266c75cf28c6f60710fc03900f6932086a56e746b0ee345c5f3bf1009058242c0583a7457a2e4453dd3b9a27f73d5880273338aad994a9fa6f7920e103611dec931e2bdebfa181a129bd130e002aafdcd6e3adcd33ec7381b4e1ee4ea00eb5d9aa23dabab75904097fb85580786a923121512aa6e3c2c2fea6c2c6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x007a9f1614d062b255a27b83458a3aff3c81866153982a9ce763dcd10e908c44656c2edd264a1b61396efade79d80499058cae9125376748389dbdbad55088d1509c1a6614c57dcfd3e1cc47395ffd9ed195ebb60dab36cf6b6083ca10b49b791363970cdbd6072ae4e6ca782f508abf0a2d7ebd87c3eeaf07fb0c6158a16a807e1371e1802fa090ffb3813049f22e02054688c54a9d803f46fcc3f9576ccfcaa0c7f90b766330aaab3a4ae32134dba9e48fd6830b503687fba4c8053fa6a93b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x17a51f0dc1e6bf2aa154ae6d97fdbf0f9549b8a8257fcf4a90229f0a001715515c6fa8ac0a97537cd0c87c5722014358147d464e2d080e68d648a9b9e85ae4b1e5d6001f08dd6e0fcdfd20c6932534de458127c9c39322227546d1d2b898b613072f7375c55fbb46a4e122a7e1c45de6d6319fa2c487cfbc5547c6dbf82b38c81e8bb765144e997fab37da639a14a8f018a22c427db84499cd2bba0c736bd9da03cd183568c27741b589f94ad59ae372a6833b2caafdd088fea7eeb2fdc6790d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x10f1197dcb5335bbc9fd9b0ee96ed160c1d8cf7cd5a2c23550f75c7d41014328934594c87d0fc79690575e3bcad723ae094a72493ff86d36163129d59cff970820a9ea2a9ff57bba76aeecfc378e14941030b91bdfd0710d2d531e368b1959ef035d6b262ecfbbe0277c7c09758fcba6fe5b3f35f6d3e2e35b45f22beb6873b4e4a3b4293e58230ad4318313c3c6ef5c11e4fa223503b33cb6bde56d611716631b55c3307946a72b7090f12b6f04695f2432836516d65cf70e76dfecd47f3eba) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x0d81babfefbd132108cd4e247204997823727cd2267020d505821c2ae0d5a73103d40fb8c876492ce84fa43b7c97352202344ed091fcb8a4173325899b70122da54d00e67f3265676204f06d952b21d92605a7d70e1a9fb7019201873755239f06730064af9a494bd52ecb00250c317bf067df6a6eda21bc92c9adfe746b056e65dfc4badd22b832060092b018cee22a096f0f6bd5fb0218e1b3a5ca8119e6c40bef5a6dc9cc74f34517d3a8997b1e0cb36479ccd6e46b3d9fe2de3159d0e8c0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x178fd42698e846ab09f28e4b945bf51a573a5f67b01a50e7de386e0c2cfbd4d436ca77d0586aebfd3ebcf0cb03d247d600f2b025bc852bd51eeb61f0394f3fe553a2353272f8673a1a1720bc472181d16f884dd78bb17b080f693bf1ceb139430d2786584df371d15ab7529aec1fb1890818961979210babfe275729d11678117629b50b6971a5734844c856f1ad4cf909f85560e3a5dd049dc357e6806b2ccc8661032eb206cd718e27fa266f7e2f86240e655f72538936185697a94c122f7d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x10875427dc85c110b01f3bb782936f27a8cd5466fa0f0cf5917befb74c467104bf0a2fa605d465d902e1ce414f571a000468b7ccdef205be10db5fcf6c3d935f273a2f3bac6329c30c1d5493d77ab1068a93f5f3a93de9a96e57a77ccec573f413c396a7d9e079253c98302ca3e10dde046279848c9ae49e24b14158f9091e84bbcd61e13f09b57cb310a4c6a973acff0836fa3e258df34ad0c89e7b280e92f00acfc220eeb5bf8647a30d3971f08987f7191983a45396d68454d552c903cd13) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x048e783c39590796da9ce919b19a7179fbf7ca422986428d9ca4c00afeb3da88f78e4f85ee312910119a31ac675803c703e8f3560833feab146988683e7c192154c6741f449f711ceb0b5c732ad8f488fe57cd5fe3e5b1eac5b1d43af705ac4d1298b37bce78a4bb17b138b420efcceae18f300c8cfdc6417bdb84ecad21ecf6dda75d040401061e07e19a114dcd059f0354cdb917a218179ed3c1cee43a2dd932ae73cde416730172e886321c2f828cf2fd2c03fc522f3df06f571685eacafd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x1719f1a04b75f8dfdffa75695dd406b35d899d91325401355d2f3fc17abe20e6c04bf95cf265989050ea6be5285aea1708f5efaa1b197d90861811d8497844bf6b8e3cac9fb729bdbceb7d78bf324ceac87035afed4eff6b87efdea86974751e0d9ee16eb55482e287e2bdbf80d63dd5c83a1b16336b4ad078e2d09ce1255cf614209dd7a16228f242ef65c4b79fd2a71276c7a79747f69344c28692384b91b38f85c7bc10ae3f9ea3df0d8ffde7374d3a20f2ab662019b8770853bd39e21573) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x040a521e7f62b87f49a3f96b3c33b3f92db0f6bb0e708b6929eb59829bfddee5005e98176447c65e2054703be2fd10df0cca3815ceb23335da24867b07563b6d4696b27e3da1cb00a120bdb1f506113c0df675c1923a791523d83b45a13102c101ff42b0097527d2b1d88646b1e68513b7f61533bce07fef8bbd17a592f3d7dc5e148a165633337607495e614eba86b410ae2cb3d04d352036f95c34417364368b862a29199668bab9ff5261f94fb6e5a00f8eef9d0a3906e57720dd315f7921) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x0f07a4dba873d6a94e491900c012798c4fabc655b547246881b8f32dc445a1c4b526f6df1c44147e840e5e19afe0b6961294f805495eed4fe60a9f7598bd74222ae3499b74266c75cf28c6f60710fc03900f6932086a56e746b0ee345c5f3bf1009058242c0583a7457a2e4453dd3b9a27f73d5880273338aad994a9fa6f7920e103611dec931e2bdebfa181a129bd130e002aafdcd6e3adcd33ec7381b4e1ee4ea00eb5d9aa23dabab75904097fb85580786a923121512aa6e3c2c2fea6c2c6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x1652363a9bd3609c22f6c5f10c8768241de0d1c618e704b0e325394b315a7ef87ed5168d497ccf2c3a49d1d4896af16d09e1eb819ca6af9192af93b67f5a7421dba6341219ba2bd75a9e12811de4b51df938389f7cc9779a75c19057ef83a4010ab86d7781a14b40516ed6fcbca26854a57b2db78a306efcde40f68adf013dbc571f99e7474592016fab08f5dedc12f10dd07ea9e487477f24f901fca69ba33acfffd74fc545cc745e1130fbfc3fe35b7d9cf21f94a9aad692c1df2cefeceefb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x0faee564e739a7e9d9b2eff2f35979f8c893d0fb5de5271e87ae9fe3ea42f0ba75d7eb1dca9693890de995b40ed7dcd600161d6fa0462125050a0bf369d9858cc893669f3984463d40af2547cf1a6dfadadada5f3c70d05b3b774b8e3683464a06a7830e2c2bbce87a8680b2493aa25aba646bca8b5b818a09581b7bb1be131e08c4168a043e45d56eb41b8b00a6507012cf7fb8520bf61b78bd019df07865c0b1d267e889b104551595f5034c798fc9b69dcfa5b9dbc6002e186cf9abfe0802) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x0101c54987955e4eb4a0f6423fd7b3a2f06ff5f2b98213529d2174c52b33f8cac47c770821a4133b7f153e98e1669f2f057ca3fe1f9420a22afcb783ccbc950d5e0c3c8a3762d66c31b627e93f9e169fba3269fc3cdc1e904d37c900b80254df10abedc8e7cf31a272448329518cf12c1cdb0edcdc5c895f841092a98a0ff37c3556cd079f0d821a22b413a56f55b6bb0de003bc4059dffd6153580abcf4b27b8426d9439e4d4da431c193f1d62c55e7161b2f790f4b31413aa8cfc1a1c45cd8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x0568e06e680dcdbb2d68fe791e938363a7745910b3cb48d5b3a70aaa6f4e4fe2100334864bdd33033cec36ced33892cf0505e34bd60aaa951aa619535951ef24f633bc346797d240095e4826ecd461d6f8b0b7e61cb34a552f85ba7ea44ad32709f7e4e554d56b687ff494ed2d7dcc4861e1a67cb044a84327f9054b8e313beb68147d5adc70525b3dff7f358e864e060667f4ac5edfb803dee782e88cf9dad054d38b7192abfab52231b73b6410c2ad58920988189c07566290b4358d6696f9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x0389a5e8cda6286ab1e92f4c6b4e42cae46fd148359499b41e621d960892732247f291284f305c17377a7f703c804ff80ee8cbc431aca16be396de371af1f17959524dfbee3c6bde917c9155699d4a2bf6cc11bbe9c1393ce8bfb67d3765b5330d8321fb114c6aea1587d420ce7ca47126a75180656ed806d530302b35e3aaba0cec9ec31f94a15248c082c1143e625f1344754b953b5ddc1ae40f732696c6f99d900dc880a78c750460822ea36cc86e9350a25ee4e4d82696111477b18ee9e4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x041d34c5ddef9ac443dd7848cf29d87c9ee93f9a1433e0cf214e558e93d488374812a9d2b43791e8be6351ed6b0c8efb04bd817bcbf3426b059e7d0905931b309d41e46378a62d0ae0c335d754afd0f4aad27ef66e6cf81883999cc3e19d5cf300dcf814ace1aff20dd3e8cd77392190663679a83289becb9cb669b4c04c1328d11147e928d96e42272815b91d0602931219e805b8d2b35c3ce231c6ff70a93c3100b858e55e42c5f797fac45ae2c19b6afc3e9d4d3d24e0ccfd3ab23fdd973b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x0a85418bbb38c1ebe99c3e1b76e509a9e765bb876c6a567b12e1e07d80a45d8de1aa9d6425aee533d38c716be18e4cf5123d60d85aa0d15271761bf6fe5c75d291602d0bbccaf7ea30625fb18f4f2012286abe933de82871e27bc995aee08ccf0a4a905214907b3ed66515c29319e705b2892d1f54eeb61010cb68a135b5c0eceebdae1f3e510d49223a79abbd1e5ce412f38eb5ea519c65f950ac8b4a274ec8d2742073d4d4603f050c8751202830f8d19465fc6024a4d52c7183c47be42325) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x0dc42d2bf532bcce973671bc74419a7d43b504f66667356c00b68126501cdd69edc6dfea8ca9bf757f9286c30aafb31d07cceafd4ea4ec714a310648ea80180e439a6ccfdc6ddf62b9876bd5aef725b4cf999f25006635d7cff2ec0b70abb92e12cc523377fcbb5dfd41cc087fbd675b1309f700513d5ea90d2a3b08cf005377cb34f64242fbd775ba63d5368ea6a2bf0d3487eb537b7a8ccdf230728b71e41056ef93b27e5476df0cc4246bca3640b37c1cdf1af59910a7a474148d55901b95) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x0655de0cf51271c9490062e29b8da70ee4c82939b26218118519aaf6298f2ef60721ffa7daa6a37133077b0dabd296830949eff2b5b24843c956b09c9417f2fa4820fd35ae9a01d5f0430329795f5e39abe6fd35ef8e9fccd43af92246207a5d0b37866f86062eb555caffeae739def30bbc454f2c8bfb1a2480e2f91926cd12b53f85691710c75802cf921b8a5b0fc016f834c60d5e79ce20b3172b777dfffae9046d09e52aa188e45be26b0e3e8e77b8328530a6446fb441a3e145535367bd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x05b81eb847ac46ba0a7dd65998e59571ecd7ef546b7683388f631777015fa72f4e2463b4d193b8ab575b0aa8d077cbf105d25ba702f7c774572a60719894156141940a0a39e7ab838cb55524617826775b9ae494ad11213834dd86b1f02fbb5e12a932312f159aa63ff0817f8e4e478092fdfab946e5db0c05a0021374716d167cff0164ff823dfc39ec1f871233dbda0110bb37e8d5b4764fc40d6c7c62bddda525765a53385ead794d6442cf5b79fe14e2bf4a74874da68aab1507be8b31bc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x007a9f1614d062b255a27b83458a3aff3c81866153982a9ce763dcd10e908c44656c2edd264a1b61396efade79d80499058cae9125376748389dbdbad55088d1509c1a6614c57dcfd3e1cc47395ffd9ed195ebb60dab36cf6b6083ca10b49b791363970cdbd6072ae4e6ca782f508abf0a2d7ebd87c3eeaf07fb0c6158a16a807e1371e1802fa090ffb3813049f22e02054688c54a9d803f46fcc3f9576ccfcaa0c7f90b766330aaab3a4ae32134dba9e48fd6830b503687fba4c8053fa6a93b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x0faee564e739a7e9d9b2eff2f35979f8c893d0fb5de5271e87ae9fe3ea42f0ba75d7eb1dca9693890de995b40ed7dcd600161d6fa0462125050a0bf369d9858cc893669f3984463d40af2547cf1a6dfadadada5f3c70d05b3b774b8e3683464a06a7830e2c2bbce87a8680b2493aa25aba646bca8b5b818a09581b7bb1be131e08c4168a043e45d56eb41b8b00a6507012cf7fb8520bf61b78bd019df07865c0b1d267e889b104551595f5034c798fc9b69dcfa5b9dbc6002e186cf9abfe0802) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x190a43e654201a22f136074d73670943f55d9aecb573265aeb468a3981be4312fb9a4433226bf732ee30785d96777902129caa52e3c917b52a5986a3a2e0988c5b4599758dfdd8b8024d4c7fe2367d32fc76daa9ff49908e166bdde45f92047916bf8dbb99122b1ff4c9ee86139baf105ee10e43b5f0498922124f3586b8028b7e625f823adbd245f727af481e8b857f066ff52607848581ba0b3bb234fae345836e721e87da734004ad9b2d5bd9c5715cf4a319fe1446fcd44d903696d7cfd9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x157ccaf298e6f2f5bb8181cbaa6aa328017941016c64cfa74cc3e00f5cf2869f3c8860faa6ff5311ea350683ee5ff7c60d1e6e4b821dc8a93f62dc44a51ab22bc7abf454674c71ff827a180c3795023d2b1e68a8e7737751822f9c4bd6aacf000bb75ab2b25a7ab7fbe14bb31ee654e403414daa2555f7b5118f863e6bb7e21037bab85dbd91056da6ecada4865acde118c24c9e50c23fdffb2039a28462907531ba502403a4b5f4bf319d9eec76986d5e6b1073c144c9037d68c1d5c1206346) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x09401247b0ec3821e76eac4d2f7781b8a7103a3eca47bff3901144b312d388a85e73784b13283b13c790a3965b3ee30608a825b98c11eacfc5a49fc7a4926fda4530a264726bb64b7f770b03a7e0d8238656e983d1d0b09e1ba8b3a2cc8d95160f471fb3849b88618aad9d3887c4f3c4caf640b9df522199e31874b4fe25e3d47ffe876ba7581c1efcb61564fef5de411320363b8068921585104922eac63d5c761a91febb3c59c692cd1f7af390c7a9b194b267ed602ca04f6649b7f1c6c82f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x11b8b6aa6be5808d466a05c0a081ad49c76b4981c090ec40d5aaff4f76769d2a40977832b891edb15c3183acd4ef27440c4d690d911c273a99fc02ff972e6065ba27e20963fd31cce1dad2f43262c7134505342cbb50986af5e2ccfd23028c140dac1d43bcdfb3db56a04a6ffbbefef37920745f008740ac0d203a0c107060da2c2d76541cb99106a4f6b2a92901f1c10cb83b3a5f8cd8cfefddd33e00e4d1aa74c943a630119bf7e9af37a2502fde14e9c7c7ea128d0d8ac008492180630b5c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x0fc834b3e22f165ca01322359f1a444b9d908bdda1da37c73d859166e28eb2d18f364766fd1a9ce475088f5eb87273cb0102e1732224bcd7e357fd147b6f41919b90afa7c01a7ad1067f39c5f216f067ad224fd70182fe8cadfb05d0f42a5fb5004f21703cb18754d8e5dc7fe79dc7e2043bc50f7a583f399b5ca04d8941a92165403b4d845863dce7da1cff98d461b91979c4dc4e9fb3874aaabdfdc87ebd9f5f45c21ffdd8ad043643b2804edf9be567c641fad3f5a8b2b6abb8d6712f998f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x160966746459617c6cab57b84381ec97015be3cc8478361f399648f49ce8c5fb3585add8e721ce81c4a352067dad40f30c5f2faa59125982009f01206706e6298133570dc4f029776abc6aca7c143059200a50e6ddb67a0550759b442300af52167c1420b0fdd70b2c44ab737fbd32e2c470cc29418fa553d502e8b1eb6e3878007aba165eaf4ff1b6743863895b4be706e1193be3ad7c6a3968c0d787989d935451aa17ae9d60568f4fb0507be96308243090e3ccdf3075faf8ee54c8a2f803) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x0d211843d3116fe2962e44424d5e1bdda2bc55b0c07a4eec8c0d417d3597faeb202e986cb03711e879f3286c8574615f14e779485d1389631195cce6b413184128352544968c0c48df886eb7284361d514dc38999f77dbf5d743add4bbecd4301288339cffd03d1098cc0bed90dcd583bec892c5f3c6922831d21cb8b7150c76ac4612ea5489c7476c1bcba216eba61b0a7447b1fd3d5383f5b2acd06c322ddfea84fadba0fcd995ec5ee701a34b9846e93974dd3cdcc5754bc7f21705b0b58a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x0e9448fd828b81168cbaa65496078edf4690017ef6628e6cc5687082f255a16a9ad51bf31cd780cd03fd7946ce0b14460bdfcb61fa233217a63a372380068585f7fadc6978213e87c1cec52e52c5e84010446b4197e5e15ea7712f0603627eab0076cc785550ef9de1693c46481719f089d33d320fb58eb5e68c63f7dd3a4a511268506fe949ea89b320848d7c5ecf1a03ca948df7b1fa4905fc129a50b0b6e61faf0b05912f0c3eb397089a9752a228cb881331f7d6d9b1e44bfbf3f9090f49) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x090024be3e658d797ea05cdcf404ba80847cd69c3585217310973fbdd59b3ccdf9bec4437325f24816beefae2c2986b6073d93a3d5f5d2758dd6dafeed80c6e730a512471c227036b0cba91369f2c1043e8722c1d87de3ba901780a0824ad90204a467083e873a87884ddb1b6455d36314ac953c47dc86f01221c97b2c70a62f24b852c291d49845744c1812b85a2ebf15ab172859a93dd93be43b59d784079bedf952b6596ec6926a22ce8511f503805914b72752b022bb32faf521764cb268) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x17a51f0dc1e6bf2aa154ae6d97fdbf0f9549b8a8257fcf4a90229f0a001715515c6fa8ac0a97537cd0c87c5722014358147d464e2d080e68d648a9b9e85ae4b1e5d6001f08dd6e0fcdfd20c6932534de458127c9c39322227546d1d2b898b613072f7375c55fbb46a4e122a7e1c45de6d6319fa2c487cfbc5547c6dbf82b38c81e8bb765144e997fab37da639a14a8f018a22c427db84499cd2bba0c736bd9da03cd183568c27741b589f94ad59ae372a6833b2caafdd088fea7eeb2fdc6790d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x0101c54987955e4eb4a0f6423fd7b3a2f06ff5f2b98213529d2174c52b33f8cac47c770821a4133b7f153e98e1669f2f057ca3fe1f9420a22afcb783ccbc950d5e0c3c8a3762d66c31b627e93f9e169fba3269fc3cdc1e904d37c900b80254df10abedc8e7cf31a272448329518cf12c1cdb0edcdc5c895f841092a98a0ff37c3556cd079f0d821a22b413a56f55b6bb0de003bc4059dffd6153580abcf4b27b8426d9439e4d4da431c193f1d62c55e7161b2f790f4b31413aa8cfc1a1c45cd8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x157ccaf298e6f2f5bb8181cbaa6aa328017941016c64cfa74cc3e00f5cf2869f3c8860faa6ff5311ea350683ee5ff7c60d1e6e4b821dc8a93f62dc44a51ab22bc7abf454674c71ff827a180c3795023d2b1e68a8e7737751822f9c4bd6aacf000bb75ab2b25a7ab7fbe14bb31ee654e403414daa2555f7b5118f863e6bb7e21037bab85dbd91056da6ecada4865acde118c24c9e50c23fdffb2039a28462907531ba502403a4b5f4bf319d9eec76986d5e6b1073c144c9037d68c1d5c1206346) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x17e84dfa0ea7d745d5edac21925ebceab64e50cd3aac7bbadfdd0a0f22b53f529ca9878711942dda334748ddf03375ef16f3d4876216621270a06d9e98da5dce50f032593c39de8a5d8a24b5b161dc778ffc4b8541a5acbea543899d28846821151e33cd504aa31852e324a540cc4cabde2b9005060d2b3cd83891f4bc7dad1b790a62608ae8ba6c1922b21cab0b072002f87e1d6f2e2ca8707a250084343ef5e6559d5823cc68dd6f626d680b421997918442e03a09f6536cc7c9a778c2e6e0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x0c406abc6ba1e8c440436434ef7d9267464eff36edd585dfc75f577f365c9db3fb9c19c13e3e89c0a337a8b729523f32167a1833aab483ff1e412a71e267b60ba69b041aa8c5a59e6640cdaa6ff33e2a5bf1b60f32bd202bbb3dccc7aba613230756e1df0b2a0466aa7a27e21e9ca58698fbc22d840e5fdbc8cf1faaec79a41d833ca9d5f39011665fefcc17dca1390201d811237817821f0e9542d612bab688c8c376c13da0bd2c781263589a423cba089200ca81113526b8768dd3c737488a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x16c262c40999ca1e5a1e72b13beaa919bc10d08466df19e456a033684b013d4100a36ddb6cdc3887dd97e8db4b86818d08e52a91709b30f3ad36e2593789e280518ae5e4ce9821d378bcd7882f6f70c1a7cf9dd2d8b15f985f0c2c5bf08f54dc0452b9dde9a272149bfbb2a32c6a1f69f659cf130c30a27afd3fa3be26bd8989d17f2be11b386a318b6972593b7393c90c4f22e1ed7f148d35acc321c3a3ee2069e368ab8df3635dc5950258afa398228d4d2c53dd3c12bf1361623a69ba2fb4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x1487364b239f67fcc324212755b15f25999401cbd86cbf4a526807391fa6773593c9392810d6689a4a0558d89ab72f4f00d4801e639c8d4987569a262be2001af7f8e98ddbf41f37c054b21e1d6818a12f391dc206c558e9f04148dc00a530820fd747276d53488214eb0cf8bba8e4711a4c3c209078a01293ce06d900d3c1a3a2060a6bb9a8f94ba6896773ab2061ef0ac7f39533e34c6aedd26dda7abdb3e3489d17d1636a65017423a7ec696e4eb00bba6b15907b606c719ee4c3cd341958) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x031951f3615a669880243165f6eacc6f5fa02daca321907ccb06770cdcd9c92d368cf58cc4da05fe857e9fc551744c8201b4c54cabf0c8d0d8d49872393aecb32aae3b1a3441ecf7bf15bc1d1dfb2aece9ed92afed8a75c7508ec4be49fd8bf00059bceec915ff60237a600916ae589dfba6dffb71d552f65d80b042bcba249f906784869c6445303561565e0e17f0841977e319775541feba65f0600e082fadea21c5ab09b0f9f6c79cab5e902e3de712104ae6c254ebb000cac8f3dfac9726) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x013e98c54426b5c356a094af259f5a6c3e3a16dee1b4699157dcd7b4b3dccfab401dbf1b628b60293512b5ba8060c7b80f3360d8b7afc977b5ed76e640ede1cd785d0c021a0478d6be0f43288ad75dce019551110ab5d251bc6c789b8a4d9c74078c767bad0eb06bb1447818304a37280ffefdfd862b137572fc3e2131d03cdc89f2637227e7303e7ab685f87d5f386e00102910864b02ff09d9ef9b534486c11b9ff933e8d2445137fc01e0505986e28b0c4b1608e5cd646a8c5a63b4febd77) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x097aaa14ee186c44f4781526acfa3a83929f5e39c65ff1266b0133e18d4c6ad549087a2aff86235eb6080f2c6f4fe2d1046748aa1dbfa1ae72dd3116fb4ace512d11a4df272bf34fbddb6c8020791cfdfd29eb4508e8bfd54a1d8b7e16535f7904eb63f70a94be19eb06f2a337006b4583267b9d8ba72e8eec424a445b423118a68a0ea992345c8ef4a13cb68e8ad80b108e284b312f574cfa7afc3ab6d9598cb342807b7686c2326d4d7a257d73ed383a420287d2e3c38eb321bdbd2aa861e3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x1390ef409a99796aef7b741837f04ac5b0971436b71987ed2164e89950b9834257d50b1e1595e7d423b70abbe9ab5d33110ba5f262ee8cd728c8d20116827832198aa304fea6bf519d767260f947027f544903b9ec4ad73b0404f705ad1bb7e70b8f4bb943637d1830d31f24383f251ba5d64281472d5230fb974afdc27014af81689d5f830f17b76d4fe61b6bbe4a21128c6036642b9f636ab3215921545b3d886df46475f9a11a4ae9a173069675a4a02560a7dd717f7d204427a5b33563f9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x10f1197dcb5335bbc9fd9b0ee96ed160c1d8cf7cd5a2c23550f75c7d41014328934594c87d0fc79690575e3bcad723ae094a72493ff86d36163129d59cff970820a9ea2a9ff57bba76aeecfc378e14941030b91bdfd0710d2d531e368b1959ef035d6b262ecfbbe0277c7c09758fcba6fe5b3f35f6d3e2e35b45f22beb6873b4e4a3b4293e58230ad4318313c3c6ef5c11e4fa223503b33cb6bde56d611716631b55c3307946a72b7090f12b6f04695f2432836516d65cf70e76dfecd47f3eba) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x0568e06e680dcdbb2d68fe791e938363a7745910b3cb48d5b3a70aaa6f4e4fe2100334864bdd33033cec36ced33892cf0505e34bd60aaa951aa619535951ef24f633bc346797d240095e4826ecd461d6f8b0b7e61cb34a552f85ba7ea44ad32709f7e4e554d56b687ff494ed2d7dcc4861e1a67cb044a84327f9054b8e313beb68147d5adc70525b3dff7f358e864e060667f4ac5edfb803dee782e88cf9dad054d38b7192abfab52231b73b6410c2ad58920988189c07566290b4358d6696f9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x09401247b0ec3821e76eac4d2f7781b8a7103a3eca47bff3901144b312d388a85e73784b13283b13c790a3965b3ee30608a825b98c11eacfc5a49fc7a4926fda4530a264726bb64b7f770b03a7e0d8238656e983d1d0b09e1ba8b3a2cc8d95160f471fb3849b88618aad9d3887c4f3c4caf640b9df522199e31874b4fe25e3d47ffe876ba7581c1efcb61564fef5de411320363b8068921585104922eac63d5c761a91febb3c59c692cd1f7af390c7a9b194b267ed602ca04f6649b7f1c6c82f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x0c406abc6ba1e8c440436434ef7d9267464eff36edd585dfc75f577f365c9db3fb9c19c13e3e89c0a337a8b729523f32167a1833aab483ff1e412a71e267b60ba69b041aa8c5a59e6640cdaa6ff33e2a5bf1b60f32bd202bbb3dccc7aba613230756e1df0b2a0466aa7a27e21e9ca58698fbc22d840e5fdbc8cf1faaec79a41d833ca9d5f39011665fefcc17dca1390201d811237817821f0e9542d612bab688c8c376c13da0bd2c781263589a423cba089200ca81113526b8768dd3c737488a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x1187c1c4a41b057967c7555492ebbf1901b3879b0c245fc07eed3d75b8fe214d27b4b192d7787dd9efb6144cafdf0ef319040d583646a66954d38d4d0aaa83cf4988fecb448ed5c20d0e30b0f2ebac49d6c35c62800271c84148960455d8d8c302f15044e389412d432389b608bdfc7251ccdc555904248b09160d12c7dcfea3f6d675ca2450a3ad01fee0db94dc7a8d1937a1a1627390ff2e1bee480e4cb54037c7b8836049a39d758ca6c4427dee464ffee79576c66d33e9443c7716a8d37b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x028f518613b138505c6d90b6e0121e01fc99af5cea6ab138892fd2b360212342d70074b5533f45650fc0b9393fb67b7a0770e4d54774c2d27c041f17020003719f9ae0e02d894ee0426cd065cbf5c637f1f2c64714b70deefabd21f9bff17bb900874197fdf56dc904c80dc3c13cb6836cd55be0d154d9385023f48813cc7d27b4386f1c357dd239962f527d4be0b2861261781e283e1fced9e8724f2047843ef1d2de89b8350f2ef0e654e3e053aa0aef768ea4919129f6a5eb26bb7c485384) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x10cf8ebadc5b77f21fd9ac63f34ffb8b27b266f816f1151f9d0b74bd20722b4bb5146f6635e5486a82ff1ade692851580e294b151f624dab1bb74c7666cf3183e19b41917c61a0a837d0f1fada5ff601f07165d9ceaa1e74eef48108161b573005083a3136786a6fd87a67e01eb7f228be41714f472dd977839b07e59481aa13dae5255ca79b7e3ccd8c3e94586b55200614032b6ce4e08bb441c880a202faae212322f211774073a531da09ce865b7f1001c1d126ef190071e29b942accd31d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x0466cc739385018a0585249bf02ca21644f56aee02fc8617fc0b7339f34147f994ab016068b77ec03025284d28cb334b033f3e14fd9c2c9acdf961d48b6456540663f504a8cbf28f40ac43c0d1d6abe2386810a63893fd69995b32078d98c4b00c08708b17362f86be1222a05cdeab17adfd8679f0b03d18c5301f4d07aa51fa1885e1bb32570189260dda42bd7de0f70d12c41a910cc32154f2d2c1320e473669a5b071bab634f561c2f0a98f72324977c74b7041757907d6441d847ca103c3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x170489c51747e88f11af77fe2d5a8e3615e99924a106963d8c34a966f643a7eb66bbad37c2c333cce34a9971f2ca87a8115b884e4f6c964127d3741fb6fe8b19a81108fb38135498dc4e582bfec87981bb814294c8a5e09dc7fd06097d253c950045ebff141ac9afd3d848fe89b37373978bf030afd38ad713caaa28ff9138d0bd0f6c4a323cc96864e1b1b6aefe1b850feec0b7f1b911f2c320f30411c33737251637803ba4ff4ef1fd480b9b98305a5a5f9ab4faa92b169eda541879af36be) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x1583640fa782fb3c949c9a89b95e52818fae6fa7f130ffc5a8304ab7f78fc4d0050b0061a8e90b29f334fc7168084f4810486574b450bc33691aca553a6aad3123844d39c265ff52e5dc66f0d797a80cba141db073ba767a1021c654eb1a316b0193bd94baca5c7c0fcd370532502b6ac4eb19b3d10a3f4a48bda5858a888c5df42dc9153e70cdddd7393fe381aa1c6416e2203e42a66b43189b3789270d20ff285e3279667e01f18f686caed2c0a252d306afc2598a17ed518acac4e8b1b7ed) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x0bd2a8921e426f811f8ca3820348cff6dc8efc095010d4068717724a3a076a565e609be3f1c78c4b37a61dda5259a3750e70265a91f14d71b38ab1df6f14ffc11f8ff8c552401dc1ec2a70862905724a928888ab5000cab2c206f147f49a9e01019581dfea445b53898ad37d69dcd97f00db2023fa4049a3a3fe3158275aab62cc16f14f766dd9df07852f7c5df27b2111dc81ab19b80f5842c7763b036090e3a8368b6db669d80e74c0231073a46835f7dcb34aab2bbb79faad55940977dead) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x0d81babfefbd132108cd4e247204997823727cd2267020d505821c2ae0d5a73103d40fb8c876492ce84fa43b7c97352202344ed091fcb8a4173325899b70122da54d00e67f3265676204f06d952b21d92605a7d70e1a9fb7019201873755239f06730064af9a494bd52ecb00250c317bf067df6a6eda21bc92c9adfe746b056e65dfc4badd22b832060092b018cee22a096f0f6bd5fb0218e1b3a5ca8119e6c40bef5a6dc9cc74f34517d3a8997b1e0cb36479ccd6e46b3d9fe2de3159d0e8c0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x0389a5e8cda6286ab1e92f4c6b4e42cae46fd148359499b41e621d960892732247f291284f305c17377a7f703c804ff80ee8cbc431aca16be396de371af1f17959524dfbee3c6bde917c9155699d4a2bf6cc11bbe9c1393ce8bfb67d3765b5330d8321fb114c6aea1587d420ce7ca47126a75180656ed806d530302b35e3aaba0cec9ec31f94a15248c082c1143e625f1344754b953b5ddc1ae40f732696c6f99d900dc880a78c750460822ea36cc86e9350a25ee4e4d82696111477b18ee9e4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x11b8b6aa6be5808d466a05c0a081ad49c76b4981c090ec40d5aaff4f76769d2a40977832b891edb15c3183acd4ef27440c4d690d911c273a99fc02ff972e6065ba27e20963fd31cce1dad2f43262c7134505342cbb50986af5e2ccfd23028c140dac1d43bcdfb3db56a04a6ffbbefef37920745f008740ac0d203a0c107060da2c2d76541cb99106a4f6b2a92901f1c10cb83b3a5f8cd8cfefddd33e00e4d1aa74c943a630119bf7e9af37a2502fde14e9c7c7ea128d0d8ac008492180630b5c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x16c262c40999ca1e5a1e72b13beaa919bc10d08466df19e456a033684b013d4100a36ddb6cdc3887dd97e8db4b86818d08e52a91709b30f3ad36e2593789e280518ae5e4ce9821d378bcd7882f6f70c1a7cf9dd2d8b15f985f0c2c5bf08f54dc0452b9dde9a272149bfbb2a32c6a1f69f659cf130c30a27afd3fa3be26bd8989d17f2be11b386a318b6972593b7393c90c4f22e1ed7f148d35acc321c3a3ee2069e368ab8df3635dc5950258afa398228d4d2c53dd3c12bf1361623a69ba2fb4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x028f518613b138505c6d90b6e0121e01fc99af5cea6ab138892fd2b360212342d70074b5533f45650fc0b9393fb67b7a0770e4d54774c2d27c041f17020003719f9ae0e02d894ee0426cd065cbf5c637f1f2c64714b70deefabd21f9bff17bb900874197fdf56dc904c80dc3c13cb6836cd55be0d154d9385023f48813cc7d27b4386f1c357dd239962f527d4be0b2861261781e283e1fced9e8724f2047843ef1d2de89b8350f2ef0e654e3e053aa0aef768ea4919129f6a5eb26bb7c485384) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x0b089de7ee48558091087fccc178d589012ad887ba74494ae8f9cf9a83e4fe609d679b4dc9edb8d21051cd1a8eb5113616420b9bf9d9889b463ac6a54fca9758388d083d2021cdeb06bc324879e3295ca54fd7f52d28d074037fb004730923c9039674578c7ad67c991fe824b4631db3f2364169a046824142803dcdfdf6bc529b78528f27f72fe11a052b6b9fc199fb09f4b7f35160469f2031abf6d30be668820f018ecd195e91bb62909d9d3e7eafb3a6bb40321dca20db58544680915607) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x16b49b64c01860908a2c55bd6ec9a792bdcbdbe388163db9ebd49065fe0a8658a6bd1e5d7e08fe288c48f321bc7fc08b09dbda34423396476ad4ef81af816f8e8ab25f4c548e841a9c07f7a1698586477d79dc64e2a34ddd31d4e0b83aeb0c4212df349c91d43a78d9912aa35d94ad6943ad32954824982fe3d425606d6d2c90b84a8e934487879644296f7ddaf4f97901e4493caf0b408e47c095ad1c4393a22286e386f7291d736fa21813b8de5c92ccb94d80923e082db44f5ce306355066) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x16e0903fd39bec397180063fb1d34b97fb44a3964921a0f0e54213f80e2f1b0f155dc773281c2ce9c35a9841b4f0822f0f15d3e82d629849bdc901147897249ffd0a00380cf214be77bb596918134f31f7520971919ddbe94ff598096e010a86038fb77c5bc0ee5e8d04368d5bd7cc9ee3c3a149f8eb2eca49cfa2031666e7ba0e6d42940cf077ab82765503312e465b0f1fc38ea8e88f8724faf3b3ac9dca9e10c9c374f41875ed61116454a899d0aa413ff4109d50ed4838c3e74e5a63681e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x1242ac850b78779a40f548b2ec3e5dde33bf432def2c6790a8099096ad6933e2c7faa78bde8a4d4e2b586d6a4d1f4225062fdff88df3cb0df8d5e2097e53ce61b17e211c63579aa95dc63df0a1824ee36852af030034bc218b9b1ce229cb9c8c149807239b0e175e864c704ef55ae2cc2ec33c71186461caee8e7771c5ca4d2eda4388d8fdc15090e026b3654d049957114812fdd6b7f9fe01b98c1c03eca0b7fd62e0113d902ef37f3bc5191182c983251af153b36f478c3eac4d967a5820ee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x16e6319ec68d88c4ec5d017df123af94e924963d7e62cff44ac709e22282dc904f8367e30de2cb40af8a237a9641e82f00a18451fe0e97eb1c88b8a05aacf8fd3756c4703cae982bf8b9af0f864a0afbe62feb1a532aa8f8b332168b6c298055179319c180a36ea2b55096b645e8c42f31cfae50884cb06263ffe11b0a210d7f3bdb1ebf2acfeefda47cbfb717487e870255e5ac63c4ec740e2a3aec2e5134c6ce8afd43a1c793c42abd87fe0fa93c578dfd6e5d604510e1a8109b4b35b172d5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x0d6af0671af039e4046dfa84fc7aef856495f732e95a24e0958b9729ca4b87ccf8b115ed6d1b60265b838116f5c56c8e0e1732e3dcaaa2c0a44c5f58a3e2cba84005b2aaf4fa70b995d8c30f5d0c25c0a9f3b6388ac91da8f7c4c9fd084917e80c1152762adcb783bc96ae1e2c37d6870a174b5cbdb1adf5adbda7d88671247471b36c9d5573ecebbd068087f45dee5d16925acf0e18b5adeeb1d4659f2f8df4e8af39da572e425c796f486ba67e05f3b7c15747f35781294128e32cc66ab87f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x178fd42698e846ab09f28e4b945bf51a573a5f67b01a50e7de386e0c2cfbd4d436ca77d0586aebfd3ebcf0cb03d247d600f2b025bc852bd51eeb61f0394f3fe553a2353272f8673a1a1720bc472181d16f884dd78bb17b080f693bf1ceb139430d2786584df371d15ab7529aec1fb1890818961979210babfe275729d11678117629b50b6971a5734844c856f1ad4cf909f85560e3a5dd049dc357e6806b2ccc8661032eb206cd718e27fa266f7e2f86240e655f72538936185697a94c122f7d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x041d34c5ddef9ac443dd7848cf29d87c9ee93f9a1433e0cf214e558e93d488374812a9d2b43791e8be6351ed6b0c8efb04bd817bcbf3426b059e7d0905931b309d41e46378a62d0ae0c335d754afd0f4aad27ef66e6cf81883999cc3e19d5cf300dcf814ace1aff20dd3e8cd77392190663679a83289becb9cb669b4c04c1328d11147e928d96e42272815b91d0602931219e805b8d2b35c3ce231c6ff70a93c3100b858e55e42c5f797fac45ae2c19b6afc3e9d4d3d24e0ccfd3ab23fdd973b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x0fc834b3e22f165ca01322359f1a444b9d908bdda1da37c73d859166e28eb2d18f364766fd1a9ce475088f5eb87273cb0102e1732224bcd7e357fd147b6f41919b90afa7c01a7ad1067f39c5f216f067ad224fd70182fe8cadfb05d0f42a5fb5004f21703cb18754d8e5dc7fe79dc7e2043bc50f7a583f399b5ca04d8941a92165403b4d845863dce7da1cff98d461b91979c4dc4e9fb3874aaabdfdc87ebd9f5f45c21ffdd8ad043643b2804edf9be567c641fad3f5a8b2b6abb8d6712f998f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x1487364b239f67fcc324212755b15f25999401cbd86cbf4a526807391fa6773593c9392810d6689a4a0558d89ab72f4f00d4801e639c8d4987569a262be2001af7f8e98ddbf41f37c054b21e1d6818a12f391dc206c558e9f04148dc00a530820fd747276d53488214eb0cf8bba8e4711a4c3c209078a01293ce06d900d3c1a3a2060a6bb9a8f94ba6896773ab2061ef0ac7f39533e34c6aedd26dda7abdb3e3489d17d1636a65017423a7ec696e4eb00bba6b15907b606c719ee4c3cd341958) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x10cf8ebadc5b77f21fd9ac63f34ffb8b27b266f816f1151f9d0b74bd20722b4bb5146f6635e5486a82ff1ade692851580e294b151f624dab1bb74c7666cf3183e19b41917c61a0a837d0f1fada5ff601f07165d9ceaa1e74eef48108161b573005083a3136786a6fd87a67e01eb7f228be41714f472dd977839b07e59481aa13dae5255ca79b7e3ccd8c3e94586b55200614032b6ce4e08bb441c880a202faae212322f211774073a531da09ce865b7f1001c1d126ef190071e29b942accd31d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x16b49b64c01860908a2c55bd6ec9a792bdcbdbe388163db9ebd49065fe0a8658a6bd1e5d7e08fe288c48f321bc7fc08b09dbda34423396476ad4ef81af816f8e8ab25f4c548e841a9c07f7a1698586477d79dc64e2a34ddd31d4e0b83aeb0c4212df349c91d43a78d9912aa35d94ad6943ad32954824982fe3d425606d6d2c90b84a8e934487879644296f7ddaf4f97901e4493caf0b408e47c095ad1c4393a22286e386f7291d736fa21813b8de5c92ccb94d80923e082db44f5ce306355066) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x16e8f7907f9448d12ff6d2d5db462cb603d3d65691f00658b5da524caa92bb3a97451b1b56acb7f5c205394ea137bb700882280d8881d6c6323ec438d423f5694fd13a6d4cb773764ab1aa5f4c451bc112d6df349f4d02bf2730536821d52ff60885014b74ff7058fcd203adbed59e0d24b16f1b3114f1f9eebdab2d5c58cf404b1f9bec447f2b1afc9afa76859098ec18796fa8fef1fd674a5bc23dd6204bf736855e123e46262e489450018088b134dbe70459ec525945d24b619d857bbce5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x01df9017974be93b18af1de7f3bd83623bea55a23a588f529c1e58cca91103e9cb5e865160b41f1110bb2163f66de2940f84486ba56622f5cbe0d0ae166fcfe72231aef90ca7f9905fa797e536a7ad531c67973162a136059a00a6e6825797940a3383f4163365349e112037a963f1de6df3e45f1b58205a4c18cbfbddfdcb10ffc271f3239aa288aacf7f16650439d415243fe31938fb300a1ff3aaf17d18ce639945ab4698d69a160813f267f2eee0031dc6bd3975944f911fe57be6cd56d1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801' +storage + (Some 0x18b4558b569b0e5b227388c9d844dc37bc0ad40ee5d5098871d396e09b7f85db50b78b2b33fbf656d02e83b45d04962e0ac8336661fd1bee9f074f35f3413c81d22825c469c70afcbfc724ff25750b7598493ea501e5ee79e0fb2d1e8fb5ee9f0b95aa27a6f20c52438ef3daa6f03c8bc41db48fb24fe73921425b1b4906bc60ab7e4b4c290f3c5aeef9a40f094e3dbe0a031822e3366d77078f5e93a80f8035f6f2941593f4f30481399f91431ec85dfc81ce11b824e9b7c08da1634b8e9c83) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156' +storage + (Some 0x050db0ea21b45502d1672a82bca3e6305f8a37689460f225920f4de664a9b3df4912f035314ec9b35d972ba67a522b8d11031b259adaaab72858a94000b15200254698fce139fe4f647a3a38e759144d7c7a12fe263194e3443b95f0e863c9f804ab9bf6e3eb7dc3515644dd29e5572f1ba34a18feebd12da678d35fffeb65071d18bb2dde6b6e70fbb14458e5adee12113aa6dcc7d3f7c25b84031fef1ce34e8b7eb8921b9ccb08d7a49f4c54e0e2cafe9eb9a009d86f2d118c784848c67db9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327' +storage + (Some 0x0a300f596c740d3a332118e868fb8a0ea04688ebb394489785ecebf2739443b346b324e3fd9246050d0aa1d3aea9f1ce0ad93338ac85b6a66c0f3fa35c81ade175275570facec6395631a1d5a977afbfdd44dcd174d2d782105a1503d25e9baa1717a6f3d40df12d5003fbef8dd4e176fdafd6c1bf5e62908aa160ecfabbc1a9d608c32417a1221d589f70f5335603200c9e15e9288f7fb90cf7101301dbfde0ee2051b698310f855b1d876cddc553d4ac3a88f8de8a99d7645595b4ee64d3cc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca' +storage + (Some 0x10875427dc85c110b01f3bb782936f27a8cd5466fa0f0cf5917befb74c467104bf0a2fa605d465d902e1ce414f571a000468b7ccdef205be10db5fcf6c3d935f273a2f3bac6329c30c1d5493d77ab1068a93f5f3a93de9a96e57a77ccec573f413c396a7d9e079253c98302ca3e10dde046279848c9ae49e24b14158f9091e84bbcd61e13f09b57cb310a4c6a973acff0836fa3e258df34ad0c89e7b280e92f00acfc220eeb5bf8647a30d3971f08987f7191983a45396d68454d552c903cd13) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5' +storage + (Some 0x0a85418bbb38c1ebe99c3e1b76e509a9e765bb876c6a567b12e1e07d80a45d8de1aa9d6425aee533d38c716be18e4cf5123d60d85aa0d15271761bf6fe5c75d291602d0bbccaf7ea30625fb18f4f2012286abe933de82871e27bc995aee08ccf0a4a905214907b3ed66515c29319e705b2892d1f54eeb61010cb68a135b5c0eceebdae1f3e510d49223a79abbd1e5ce412f38eb5ea519c65f950ac8b4a274ec8d2742073d4d4603f050c8751202830f8d19465fc6024a4d52c7183c47be42325) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732' +storage + (Some 0x160966746459617c6cab57b84381ec97015be3cc8478361f399648f49ce8c5fb3585add8e721ce81c4a352067dad40f30c5f2faa59125982009f01206706e6298133570dc4f029776abc6aca7c143059200a50e6ddb67a0550759b442300af52167c1420b0fdd70b2c44ab737fbd32e2c470cc29418fa553d502e8b1eb6e3878007aba165eaf4ff1b6743863895b4be706e1193be3ad7c6a3968c0d787989d935451aa17ae9d60568f4fb0507be96308243090e3ccdf3075faf8ee54c8a2f803) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c' +storage + (Some 0x031951f3615a669880243165f6eacc6f5fa02daca321907ccb06770cdcd9c92d368cf58cc4da05fe857e9fc551744c8201b4c54cabf0c8d0d8d49872393aecb32aae3b1a3441ecf7bf15bc1d1dfb2aece9ed92afed8a75c7508ec4be49fd8bf00059bceec915ff60237a600916ae589dfba6dffb71d552f65d80b042bcba249f906784869c6445303561565e0e17f0841977e319775541feba65f0600e082fadea21c5ab09b0f9f6c79cab5e902e3de712104ae6c254ebb000cac8f3dfac9726) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9' +storage + (Some 0x0466cc739385018a0585249bf02ca21644f56aee02fc8617fc0b7339f34147f994ab016068b77ec03025284d28cb334b033f3e14fd9c2c9acdf961d48b6456540663f504a8cbf28f40ac43c0d1d6abe2386810a63893fd69995b32078d98c4b00c08708b17362f86be1222a05cdeab17adfd8679f0b03d18c5301f4d07aa51fa1885e1bb32570189260dda42bd7de0f70d12c41a910cc32154f2d2c1320e473669a5b071bab634f561c2f0a98f72324977c74b7041757907d6441d847ca103c3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7' +storage + (Some 0x16e0903fd39bec397180063fb1d34b97fb44a3964921a0f0e54213f80e2f1b0f155dc773281c2ce9c35a9841b4f0822f0f15d3e82d629849bdc901147897249ffd0a00380cf214be77bb596918134f31f7520971919ddbe94ff598096e010a86038fb77c5bc0ee5e8d04368d5bd7cc9ee3c3a149f8eb2eca49cfa2031666e7ba0e6d42940cf077ab82765503312e465b0f1fc38ea8e88f8724faf3b3ac9dca9e10c9c374f41875ed61116454a899d0aa413ff4109d50ed4838c3e74e5a63681e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18' +storage + (Some 0x01df9017974be93b18af1de7f3bd83623bea55a23a588f529c1e58cca91103e9cb5e865160b41f1110bb2163f66de2940f84486ba56622f5cbe0d0ae166fcfe72231aef90ca7f9905fa797e536a7ad531c67973162a136059a00a6e6825797940a3383f4163365349e112037a963f1de6df3e45f1b58205a4c18cbfbddfdcb10ffc271f3239aa288aacf7f16650439d415243fe31938fb300a1ff3aaf17d18ce639945ab4698d69a160813f267f2eee0031dc6bd3975944f911fe57be6cd56d1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/add_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7' +storage + (Some 0x110594337db827f5e6559d35aae9cdb28a727ad4fe9898737fd454a50ccbe28f152f6c9f3b0dd66f462bc0199ef204290d6324c2966a07481d449176f51464e6fc53c2b8ca76be490abc0df341587a719fe4131467ccd4a0ed2bf0bd993f7ce8192c6afb17be170babe59ab1b52ac010aac19544e888943ff0257dd4da52ea75b0da1ef7d8e2a29a28b506b9d9210a2b006dd5994ae3b78e81b217d2750caa0d29dcce23ff7e697403fa380a7df279a55a42bf990c10b1eb54a20b86f2aa97b4) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- mul.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- mul.out new file mode 100644 index 000000000000..59ea5f063df7 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- mul.out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x080b4550187f35017cdf7084f2427586dcc9e3bb5f254d3059b1d0e9029f7a9a12f1f34581992dc99d26fbadb8a4bbf6184cf390e5a04138711e8b47eaf2ee31620ce75d15b8eed650b82d53c69363866953261b50f7cfec0bfaeadf87eae8050bf14d3e8b1914bd903f0044d4bf550b6b76ebc01be4716afaf0b4b1ebf025a979368539aa65ad9293f18dff874823eb0f58f4f1d138c902a335a80294c136517438ffb91545268060711734cebbab770e34ad18ef149ac3e4fa884ceb4b7443) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x00bc7bce08dce7ec829d7a13ab2faced9e717f30c7370b8d6cc7b1bb46d1898f0743505348d83ac3cefa91dfba9b0b230f62f20c8f71df32769d5b49c1a4cde32cf8f20a05ace136e4dd9737baaed000bbbca439f7cae438f3fafa6f3c599f250d771456237dcebfbb68264c96599e9c949ea7a425021f75a5e057472ab9a1ee30bddad75b57c0f2fdc436daddac8b7c0b022e6eca54d3cdab5fb2d33dd771992047dfce1146c59036f3ce011800e2939721431c83f971237002a0d555d62138) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x03a989f5e9c957726994e2af30bfd00313c8c1af1d9e6f353bd179d403b6221bdea2a8af62bb98b5982cc551699116f20492bd7a87456de1222bd45fb4e85b426a4db0a4581a2ed86cefd2d15ecd81873ed91f70db079866a19d399f41b648f813b5c3a67ba6db557ae831299ece46ab98ed6134014019675b885c3708f7bdd99ad3d57756fe2084f7fd0df9cd47027c186174431b56442231350b7facf00fb9ec214bc9af97ab093573e97dc5838d2b173d11b7cd064122607263fa116d16da) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x193633a1df3e9c976d71fc7d3fad74918da1fad919ca9cd1fc174886d5966cf26b17ff31641ba949d1b6ee785916d9ba0344ff7dbf56bfc10ac546ed2dd0a4cd826a0d1cddd189ba718c15d4adc35856566a85b09b493c91646213821754c05412caf16bc7366a6dc39ff27e8b08fa60037b50b6c84d2b51986fe5f2ba76ffab43fcb6a0cc79a07ad777549e38cb252407bd677f34d6e810d8cc5dafa0f6503c5e0f09ee20f561778a83491745727e6da8fa3f378d4cc6594a3673ff04ec8303) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x088b49ac24b1bb213a8f5928cb16fb8bf89e44bc2b6781ecec6d32baa1ac0bd0efb4beb89df3561434065ef6e9de873204ea33f8dc13c9a07edac755fe0137afd7d2d1b22b8d7577275e09c96a3e5d92a97148806d9cf11bc2aca2dbc53820c20d8d042fa14b47ff7b93784298bba93a50cfaa9a79d875dcbbc108d8169ed51ae4795c819235d95bc7331befe813369c0b1c68720930a710e635afe84a99518bee959921b04116b95076f13e5b9e74629edffb119900454ec11087e0b6305b32) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x0e4970556f8f0393b84dd0acfaa48537287b24a4d0c0a7bb1715961b20e179d5b95e97e8aa34958e71ddab72c04e2b921678b10e90e34486fef2db6785da364e836d37b9a214a35d3252c3dfe9277d4df333eb9839d437e3e5fb18bf67d74aae121289a9fdf6fbf2edde120e5b99f8c3b374ab7c13e1258ddb115d4b08680d9f62d5082f27bbcdbfd7512877c630340c09658ceed69e7603235f1fe2b86c6586d7595119ff74892da6f5618f4bb6d9e1a6e17fb3620a52826e4cdea473976061) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x080add8f0426f9505b5fdd4e17acfd5ab4c31d5d3e4cc0ecf91ba42598b3af9fcda50cb6dbcd5941c643d70cd877bcae0fbe1d50a3275743237fe7fd82520eb1d18c4eb32ce3d573a97bdd5f48af83c0ae02dda154df544f3456673ab943b5c8047efa1153f8c6b07bcf1aac4073f80b4d8e39bfc6b1ca2ec75f240bb1213a2c2feff0707cdc78467d39e9070c197b450bbea0c527b83f56af225ed946dc98e55e57ce7e6c9d479bcdf1f62b86dc7eaff5662878dc04dc20df57e67d5a06e1d0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x18cba79a989acbb00d64a7d7878cf2648874a1090d3e40b518355b1a384f48b4027f810dddc5be647023f666c4bde527128a028e952f95bad52b7cf076e6ca99ed5f8160848fcc02eeb780738ef5184a92cd8bfaf8c86c4b4bc15b5ef37932461114fc7d7203b105b0a609ec1770afa3a4a85b5802ee80e115d9f121822f2330db572d79990dbd58527cd13b703ab34b03a57838853edcb170450f5c7c20f61ca97bfcdd223278b9eb7c556a15ace5e959f27a67894d9af41821bc26ce2dfc42) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x09b08d80f11c18eae208f0cf4f0a3000a934c67afe4d01ae1bedd78c86753e251b210b0563ec9151004941601b1fcdf304285333862833f83569e4a6d769c740a4fb256d401d6cd475a6faaf06b3cf8ad2c14c8f00d29f268c050dabef06c9ac0aa45b530cbf92516bcc81b9bd662076d87dd7870aa4824906f61d6186b68925d96062b1a103463f48bce4fc8bbcf47e0aff4b0b2f74e46ae06f8b40991e6b13516396e264fcc78fbe7c94a68e114d6afbfc386ae75dc29783fccff5f93deb77) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x1647a67d6a6e7b6d058c4acd5a8d075fd6613bc63548109a74eb74e79f16ca6c73315d18492d551785fe7b53be40bec0004a62366b5f7167743bb723b6c3976e1cef9a55e0aa37578072bd0dba2079396a789044a49c631d879311efdcf2acf71184e8de0e688e4ab064d54e59e53aca91df0c3db5226d81b47ed64e80c5a5c6e5184490f59831bfd6acb491e39d056c0fb00969176fb34217462f4284eaedbbcf49dc0e00af5e6b20a7eeeb96f68ee9e629617ce7a6a593313b744df0d0e403) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x08c4b1133fb04221ec4b3c6157b6b3b47083f68737d0196ea6cdc2bf2e4cb701620817b0882027c0983671e11ef124e70c991a592c11c52c5e9e39c33532fa3affdda445eb4aa0912e6d99598cdcd0fcc725c2671ecae0b195882ddd122906d601d0a7bcead1c48603b7ca82f171181e7eae23937ee87817e6eb1ff6df5103d1a9c7072818f1fcc3796431797dc0aa5117b918e1f4e6c0a2a868ab37dcd6d16c4adab33fa39f7c2814c0ec4d6cf0a944a1ed86c87f7e93fab9861b99342ad0f3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x00b50d7a32f7d7161d1a64152001ce9ab734ce2c0bc15696e01b10022181df0842d14f91b652e8948cce811bcc1acd49032fee6edd84bad1a73f3c3720ab052762d628c53c0fa2385962fe538020ab3b657b6c647250159c1957bb58d10749e70e0d05f6a99698dae1b40d51853501f258f94caf25bdfe9a9befa4712f77fdc976f5929a856601f41039ae5747c13ad516e231331ab1067b732d0d23550cda733e3202da58e7f00c007d308595cf7309c73f1e23ed8d7d61508a67d9ff8160d8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x0a5729d3b49f1cbcea57a0a92e5156ef98847af34fd33ae5eb765730d455a754e0c163e3056944e07c883cf721ab151c18dc99c67cbf6ddfcc302662351372eb48150e7b9d233ae186690d17c36845c1c96ca58d5b1ec41d45d30d2d0523d98a03c295377a2ff5f1d694fb5c164a52330419bcfdf0e5f6d5f6f19f1a72c498cedfed51e7ca305879b63b49fa2a3accb912198ef4e8bca866b50fa5e8a753251e7ad324d4e3975052c24511c7db961d0a3ea7976d55db24e8d7d388403f1c71ec) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x17142c63772f51b91e3d71acca2ad4009aa42612994e7445f18f86f8a73abda7ae73b446be7c0f075675e1d137b8ec9e057f9e6b6aa1c4717a16ffc11a809401a18ede873063be42086e2bc8a4b36d6d0db0057fea2cfdca1a7d72390540b7c41638b5d0959f312f0b2fa27b219a41517db741d8ae5d771d94a676aafc8804b06202e92f30ec226fa6113650568d1c7708810cc0034b69645975e44a5bc741200ace0e4d4dc8cec65848c183e4369ead1e593a95e632cf2929662bcb732e2d7d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x017fdb444d88038e81a39c56455894927fa3444988b7cb56e79c3c75ce79681cdc0712622fc67d8461c6925ad806df130d6cc35fe316c3160c28a9282c05e3b3e80852bbf0d723e4e6304fbfbcd38cce06262dfca36fd0f72c04c502e54ac2c401dec7da47b690d2f4ad83163c384c311b8c87f8c3b29241fc280404a0eafb5021d562d45c234f38c3414f1c837d9db5061773f5102baa93e1b9f1efcafbe4519988e1996a2db13ec1d21e54d7c53b93e8ae35238854325b92d33f2cfd288025) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x16bad36d376c426b40fcef1d965b4611f5db43467ae56f0ca1d3ffbd239e951891218ad2f345b81b5b66aaaedcd961140684a5e081214f5a3bf55631cba5dc77c028b94a928383534fd3d8be6ff0e46503d0f9011bc65f09d4ac72f65dca7b4005b8ce787c8676857281ff7e6c2737fc8cfd47a36940744c910be339a1df4cee1aec93c1f7f0098a092550fb7ffd840d0ae3eb05453b4b44090a94c15caca731c6ce2b2e4b6414481dc20d170161d0d87154c59144b9690b8835ad60810438c0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x09ad873d26b23277ba021484b9299c6195b793f731d115dab378499db3259d471ce4600bc45665200f57b5706d16d3eb11c9042d0a78e40944cf028bfee568efb0ab6c13687fadd9b8bb139c21192c89550baa342877c80b38dfef721076056c0264ed93a026c52c1e102387b6f153c3163f206a638844a71086f40231281aae250e4cf2cfa99018977c64ea6a879ddc11fd3d07ef91f2a2168c02d071d311c90374e6a80203df70d948ff84180422bf45170ee34e673b71f3bb6ead5bcf19c9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x047701757c7a80a63adcbabf9b74040a28c402bce12bde5221f2aafc940c2c9b3b0c47fd8a8357ef17fc9ebdc248e93c0bd70fcd5398a637a1c746878e24825764e46be75b0616588683975fb99c7ea9ef211a462b9d991ae513f6dd6ce0c81d171a92cd782de9187726ac071d725f4a02323e08a9b6e75dda7b83dd0a6776dc1c14d4c245aa9c9560613c806389dab7174068f0d8d538b9f8e08542c7490037a7d1030c375c9a3aab4d2adb661e05b4ddfe73c7903f4c2e2def17335c4e8a2d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x0149d59edda997bea3f012cbff6d8ae6226da88fa75f0cc7a25ca5834aaa59b5a05ea0e758b7fc10df3bff61772ea1b114017d52c5e30b5b6e242137ae0565e2b0889980360cedd8bb7f6d07aa8f0f0e789a1a8bcb1e08cef63fee9456d4184d1231ec9fd8f71543b8d4ae7fc7d48775c874943f5025da80af37ce8b180819d2c50f438dd3f2d514cf0e1ba1a3a49e071057eb1af4e1c25fba2a9ed9006fff2799d201783d663858de05b679aa96b53cd9fce55cbc4696272cee0778d4db6ae2) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x07efa8f19fbf8165f850220dcf16a05239b9915055fce261f5dd1b109e64ceb51f4b8d23f571010c7d6acc4bd00bcbaf17b540ecebb5361c99a071f99e5a209df25e8024379cc722e0d030d3806dc49635b8c47f311154822fd30ea26a3e655e0952c84306362d3673e70d274964d12bf7d4871f77af3e7808cd7791d167783a30ad682e2a0f22b18bd49dde86d5a7ee13a27ff6eded20209c21dfc885b9b00935005aa1cf3dc6aec890d3cf3a98b555d4416b977999bb0bee0b32abe5d23795) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x171a38d9525ccb3115bde4d0f6d68ea0dbbbcaab7af24807addba4d2e3e16777f223c67a02d5475b4262bf90c63b02e600a4a8261c879c3d8938421443d3e881201be559f97292f6cef8af4edc5cff142b4a5b108e2cf07e2a5c99447e4f733019ff4b5719f6be0211c7cd1fa099a4c2fd3aa64ec639088a09966093a4f752dd1308ee63d99a93885e26e79911b85f8106ed5dfe89c103266bc588857db762c4a31b443e4721ca30c7787466c2be9e7f715303ff0d158b6118af53373ed667f0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x053d026216b40027f403b10af167f41989cfdb64687d997aa23e71d35062aea7a81356fde64e4d01e7356113e01a36140ee9ab3f43f8b13656d44d7cf2f4657d390ab0f12630078c6078145657cdada1fee6b105d34a2651f9c2770e37eb95630db82bd7a29e8068d7dec583ad46a49ef20ea77ea38153102977f5808c925817a146701ca5e673b09ebdc9d430c8092c0596125df4862ebbb9f312db3d1768e3d391da136cff325c58e90d0e337b3f18071eaaf86c2fe5be578cd4b48ed498cf) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x13937ed4f44301346c9fb71c0a598ca90d8571e9dd30e1d93d1b45f6cdc5c38d84ccafee0b81a6d70ada8e6f80b0aab616e9bd224c0e61528b41bce5dd86d289bc689d4ddc8fcb8f018e19f8939a897084123cad133a0aa332ecf59bcad791af075e5e37711c5e96485a897dcf82d75b9e40c4bf58ef4592570e7500f832820840f12047c5e7be7c40acbdd89faf0d1210253d1dc12130e420d0027a7908b13d827d1503ee0b8a34582910e1040dedd8601bb64617aec2b04e95e76356dcb220) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x1447bf58cf98d93fe16ebf1617f430d45ba8ff259bc609277c6d196556221ac8299cc865a4fcdbfe69a05221913ceb8e1904cf04e98129d25f5fd1b990c21ab4e6423e88f7215b89f21ae4f6b979773d2d43b33714b56ebbf75f4a0e8360c3a519280694e6f8ecb64f330f6c1c5c0a588c2468d89f661ce5dbe2a5a9639fb570ead89a4788b0ae580f9e417d5331a0e001b1622cf69c3e0c610ab3a47d29bb331e22b556a820e8a8206abdc91e1b258c44ea9644f3326a307aaaaccdeecaa948) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x07c172e7aa78488ff62ee0d11fd04615db340331de14f267cc87e261ac80df4aadad76852e755d0e7482b93cfe5a5b08102c9fb3f178486b9353e651f74bad37c0c2bad1fa61dced79078fcd6abf2aaabaf282619d6e1a49e63a2682d1fdb12215937a571973ed76179f05a66603d0dfbddcfd5b7459f75f04bba328b5cb76fa61bebd7034c10701972e40330f9cf27c0889cea90145991551ce64dcc3d7815f80ae4e65c2b77553a5ed8ec53a0698671af0834a8e1636e9f0da7cda98ff636b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x0568de4c43d5ddf7eb997963cd82935fd9cc3af0d8d26775595e2812293ea37d1c02bc2803b85b0fdacdad86f74c791d0017e526365f8d83ed0924745f66a14b306525ffe620d21da5df3da7f62f1694106f6097deff1d706b808320ca4df1bd1377f807008711e661d0ec7ef6c3eba5c4f1534c929e7f5afca8f2ab90e7ae0468623ab3f6e3def665281b5bd8c0fd710eb711619abc8966487996d763a0f0db66a5f898b227bff0c22c36defeb02a90a2a4f877962ca0b7f7f2c6c834e2c1f3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x0a334affaedd9118d8178f8d0fbb0e7ac89fb2dc000010668c9a4b65c66f65f3ae1aed9609cfef7038cd751949f04fc3115ed42575eabb4efa41b024775f7b71bf308e96efac8bd7a41c79c0150acd5c87318792c08ff2d23d8ccc7c189be7e4059742373637643e00943aaca573ecf667808e1ec1f7bca0391ce8f563c1efad8a9c65238e2f566a770fce14ebd9713506845dcc04208b5891d2f78a2ac4f6907f49853f25cfacfccb5bc95a97fc14945ae83de1166029ad5eb413cc7ad87f86) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x11e1a76b036b8845ad620367a792cb68a28ad8e1bb75e45f27d1d6a4fc92418f24030044ed1ee7bbfef133c8713931c619760a3ea671e13fa50424ac21a68d8edda3eacf807591a043cd9a469e420175cbbd8b6dc6943aaf57c9805c4f214b6d083d6f014f9f7a5fdd96a5552f091cc9705227dfb9e6c6ff052ebdb732ef5ce9d131552d1dc5c82c2880c1602ff8b223031313031dd4d0a71f70142a427e97f88487d2452acb85606d9a232dafc9a565895b095ded6514d128d5d182845d1d78) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x06c280a9a9a8d84441d3fbf1983c95f88ac6935bff9249d12974b5285ec180ae0614986a486140531ec7a201557247a903cf0d5e18c593dd71d0ef1af8adc98c3355817ef9729e2f438670ff4785618715fedbddf2f73408de48558293349471051b051f18077c7ddf5cd7c72f62395ba09971a60f0fcf9808875c7c9ca1f86050c85dce4013ba26c4170a8e63f9a4200eef8e1bf4cd1575cfa420a06f80b64fbdb927d7fec9b7a3ec4a9f40fe2bbb555b275501837b3145fece9eabf06dd9b5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x001fd17b0fe25eea2243b80db443e23ffb66459990d77f0f8c0daabeec844cb9d85665fb709b5fd44f91f87145af9ccf16ea4f0971c551355bb47d42fcc46e6fb5973249d0277ac3a36f79a04a422813a4b47ae6108f8f2c18d62ed2a5d378ec11012d4d516690abc205018c2c608be3684c69ea203dc478fa648b04e2285127ede6e2ca17f0f3de6f84b971c44c223d153e69505b2f41baa98d0f439dabe204d9b7d211ceede384000d8ab5b7b0d5c786b251535866ea9b79f0efdb794bab43) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x0dfa56f12e588e47e1b4a9779b8ba3e1f8aec6332f000e1191a3a9241db421cd2bd1f2674d1d65971e1bae15ac85705f02fe72dd8919a4ffc3f6361d41babb756ef436be44daa6564b2cddbb3f677373716c3f35b67aeba6e95a807753dc93d90eb26d4246ebc61132846d3f607a2644843ce7db26502d37a230609c0000ac6bc31cab911936b99d784ee982b986eb74105c50ea1e8ce885e4e0ae92e62235561cd21ca69d561b4d101b2c8895953c3261ced4d643804315615a625ec96199cc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x0c6047ec6e415dd2002c6d88d79fd756aeebec12890af2a4ef3f21786780aa4b996bdfec8de8df72930f3eef7a382e2a070dde3629e78565dad4b5c5909162cf678f0170cb8501d89aff66680d1a53a606a2d92f08df9816f6434cb77759c4f11778fe8ea72b96f3d3df2aed12d24dff9f2e659c326dce50af40a20a1fe7a5dab949803e191aad4b6bdacff2bf3257050b047d82cfda72ad42046998afc22c26c489b194ca6fefefdf34c763cce8ccf5dccd1c25e97569d05da0379009a06aef) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x0b21cb653932e8b05d8c935cd449b7d9382a2308e98d8c085d8c9ef183b6d3537195dfc3db8290321c54113c093b2d0100324822826d7108bc78373fa2bf6e8b7dfc4f56930915326a2f853fff2e66e427f18c761901158089f4534f0bb1103c0edc38f6e800b500c6e2c88c15c41cd1f4f9ca108b670123adfb6e066764c8671dd938eb03cc2cc88afee79e9c395e330a9f3ba8c8ec05d2e08720f45d77ef44a8cd254fd40967f28aad7652dc78346fad87237bf69ba6d49e9de50f840cdc7d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x0ebb4389d50140ddb952b8a0ca2ca472036a267c9f99445d7801abb8e0da3419349b7cd5758d2db0434afddc084c3c7f00d145002298452006b323697911974ef5d9b40f2bac4b304f8e512ad5df8fb343e8da6cad115520098bb1098a0a6e2411e2da3956a9d744f0ea464e4fddb94da23465f4b32e8bc44eeae6fbda605486b7d7815d90a40c21666f32806d5001d8133682f3236ac2d3d82c4ab48d48ee99180599b3af7723c6735443c19968788d6fd38b64a67f086175c237c4a6922a55) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x05deace89d55b9e4314b5fb8db2bcabcf8dffc2933ac3993ded7a9709b76fcbe58d390f57682928dd9ddb19524ec7c3b0142884d73c1ffaa7ffb201ffe573821ae92bcf1fa318655c2a47f7350e942acd70a014d5fed155e0ed9a815389da22d006b06604ca750ab0041de31f7fe5affe41a8eb5c159ab487cbcd70d6c0c393180acbb9c1113a4f72849f0e301db32dc047958cbb73754c21b27eb2cd849832e37dfda13e4c293c524b6c08e3942e0cf25b9782b7f48a9d59cc9ccce17deb9d3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x0c82d13cf3a2a85f888aba7d3024dec42cf940fb55047323315a6abe8d96309d9f2bdfbd7a4c9a5b89fa9f6fdc853f5d0deaa1760c184dfe66b68084478f585499d5b8eae6562ff5776efcb651e61b1147c76c55f5169fdac737bd92aecfbe7b1882a14935def144462758c3b088d1adba413dde26abfb9fcf2fab65fa3e262cc97001f88051f213388b80345df1ba1a072610d6d918562f0b5f7b1ff073e7a8426ef2d5722f526590e71735d21185cf58905ef6c5621d42bc676e5e3a239441) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x015edd2aebf511d69dc97bac7e4946443a2395a4a896e5d03df674bd7d0704e9ccf2c54b33e011850817f36a09938e590dda207d5be7105121e1ec23d8000af6a9bd122ce89e19521eee10b254f2128b34e98bec8fe0c72010b64b643b4d99b501b59d6c6c934a3d114fb9787fb2da8f830f1804ef239ae63a211648292923d388b26f57736dc8fce793326fffb440e601d922b33d830ac228b7ddd0481e3e89357556bf9da9cae0549dbb40e2b5e7dff76ee9de4c3a48dcd2a27cbe361d0b00) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x08b66387458bc668bcb6a8cbb22fb8776c980eb4f75856777a164503d78935a5754b144b6dd25942bfd30a16f90c796d0a725749727f727c26848434ee5ee0e55c68767184a843d738b02e52be0b720a53284d81fc25437a60651db6ee92604f0ecef2858749a6496c923b7c7e8e92d337077ea6a9834266857ab732d5f998a1cb0161fc8ffa8be17998996411864d28167cee2467f8d1d3da355f2ce67076e94bbdde4db911b99d40827283131d63f5887680b43865a4425621e47d025fe6f9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x0bcbcf739530433a8b0fa69fd40020339a2c1eb08a0d3712032cdfa2e599676d9b815636c3f731db06e48fb362d1104f015bbcaa8e137a18ac0f35083a8d2a0ab02c12fed6311189f2fa288180c3e9959360f76dda4c83cbc1e12e3b9d2df19801e8aee395a1dea81e942ef555469d1bc18bd3aeb94e6f9a2bf6a305dd2ce4612d3aaf69c8892a684544d7dc26c9f7e7073b312159e53e3bc2be81ab348e2e038822d4a6f380cfbb94bca8cd0099501f4ab5f3afe60a47f89afb6d230120a956) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x17a973ca78d77e4090408eecf5decb03e9672cca7aaab21b52597814ba3c557a97997efa71a2dfec15bc6767508189501903fac81ed8f8d31b7fcf6259939c9ec906889196f7c5a39ea8603fe3996fbebdce8c121dc7ea514d208c51d019ecd51066fe4e7311ad9d59b7b5b0a3c3a9a55c0576ab1e768df9a6cb888fdbaf6430f9a3c643c16157e17623a0da6e5f82720d487bd66d6e27cee42603408d29d4a6de0ab859bddcce105af9977083050cba11ce25341cb02062569228bdd78f733c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x059d9ffa51ad4cce6aa552c633f3e23ae56df32e55f28a0d1fb48587b230d6d52b5c46be3fc77d05bbb88d8a92a26a550d5544621ff4e3e83c716c4e9d81c28ec87329754b46fa62d7fe0c7f8b4d45db58028f7f86fa15661c503ea8ad946e8b095399a881d6e2bd9b1a941d6d3ee28249b1d035d544ff58aba4ef30f8161955ff2606666fcd35af8d5fa03ff92917520125e02c7ecfcc7f9ac1c2324e8b566bacd8a250e863c0494826c629f529fee87b2ef53726c9b7e02b9894c528d0d214) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x0567af503b136c79f62c3c426c51ca098f0f0ed75e5084cc59ec5e975fa5b2c347464d816d85f80f8a8589519381d25011a45beac93027f83ad76daedd06eb103226a36afa61783d5d96fa7e54bf5433788a87f41e51d61f791fc0fdd0d6389e143a7800cda14a046fc211f6dd73675eb56a887e026478d81cfcdf8dbae0fdcc34d0ed2e7d321da42d1ebf7d0024f0b409e1a753f7b9d67fcba28639b3f333b004c32e569cf8fe2b5a4c95804e6c45e5d3f1fdb1f25e476e7ac76868ebddf8a3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x18c9593b1c67b4cc38133e3061cd96d50dc073930df218abd91f1c4ba0d90028f2d92927cfbca7516b0df85fc9ba2b9714fa5f14b2942b9f39bc1366b81be9432ac33eaf04387b98f6e0fb8ad32de99d542510783f2d1e064a77e6f42af1c98416ebc9786dc213e6ebd40670dc2d904ff60a5bce43cb246bbc6733413228f0e540a510e2985b7aa3c0fc4f5e5347e72f11464839a8caf107af63e8216d38c3ddfeb1d16657c0eb876ed3ea3ff9333165cb48a26da3fd989695d789cc0855d07b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x0db4522335e284df12f38ef3a7e4598796247abc77f7b2e1e603e8bb6579d1e34c399374d3800aa032e71fd4463e0210002417766d430b498c89ee71fb8130657c412c0933e01aa4f1a7e80e2942effb42bb20d0c725ab2571e8b83a209fc07007c7de731caaee6522441d0b39285af51477474a87bf84fd5f65edb6dc641960e963e72e9cd4aff77e407591a086fbea158ab626b7a978b242ec2d872db7904704a400bdb76da784f5336ddf0ff06f401feb4eeaee5af6e4089447085119c513) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x112eb205ded147fb6311e3fc37e07103c0204de7fb9ac9599a9b42cec9c88a032fa10927591202f9bb96faef5a3e096919f859480a1c935dde21350f29c0c4a6aa99be84fbbaaa3a1b063e81634052e0c38237f34d0cb227b4aaa6256a350e6f0c18966b61c44ece02081a6d55608555d5ee655338c5e4165a02e2718fb26403515de65228ba00bdb784b3fe45186bb201fcdf242491736de4597a03b41c4a8035c680b45029e62088084ef938ca015e6bfa9dfffac2bcf8e077feab4c098d13) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x0d9954bf21fc9f7b23368690dc64f1e9123bc04f8840aef2e10bdc34a69868ce1868595664dfc9473ee489016419f2730cda11fc675b0c509b33b97f6ddc80fd07acabd7f730be7d64e1f4f113caf5c59259233d08ae1943158ef12e46491e0d193f910f15d0574b0a50831c4670c8a59665c02fb7b211befeba1e67a9cfbfaf8584821628c356771fc72f2a1e8c75621906c6b74057201a6214f135e406ff40069c3ff561efb6f2d18d0203fe8ecdb46cdb20afc6960fa34dbbea49c4c008da) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x0fb66ef421c6f80b62266297d6e9c65a6195229fc6ebab3cb3d27bec45fd4aaf30368cb5f4236d16e52711880941445a167f3a6b064ceadba41399f08276e67b54adba620b22081bad73f8b0f792e4521ac8b27c1af4648836c1e15702e9926a082360ba2ddbd29da654c41c091cacb79213cb4c1bdcc3533e2a9e8f5842cf2e86f8d7134035dcdd907a857f057e0ff014f112a508dc23b597e190b95b66b1ff51e20491dfac470b8507ce7fbf0c4c246fc7825e49b351319f6d972b7f0c6ffb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x0c2e1a40ab2a6d83f9f93455f16d13686c29b3f8b8901082930600465936e8cc3eb8e98d214738f8f01e0681572592d800335dc6701acc4d8065832b66782b1af548c39df4e2eb6b0621900f155b0bbe693a2cf4bf42042208bd6ee32b127eb61565fb0b7f257c93ebd5b3e5147be147f9441a3d650adf860192a09f1ef93fa3659b55138a0e89419c4d8ff8a9e3914d03e649eb3569eaaba156c8ebdcba385ebf74e457b18c1db7933285b0d70bd902b3b2a703ca5d8b907073836ae3f3802a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x0493817e28aa42a1ad3fec1032efc3555c24e0ac61cd6c0e3cade1d50723d83c6aaa0fa7448b79c1d92d2475cc37d95015d68c11ba7fa6869edd5342f4ee7de7df60004cfafffc8e3df465489b0479b6feebe86c559b43459f9974367f9ba802112a4d4de7daffe8f69741d2b57f06cdaf23ab81eb34ab70a5a71ef6b5a5f638c5b04fe02cd174a768f4bd9cd259ee1305b534f596c559a5b1223980e8f314c1857499b94df5b9faabe18d7665d1f1e981c47b1c4b16a3d6cb249910ac0b193e) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x0d7560e7bf910cd7c567efca055564120aa864e625ecea96fef527a3884176aac421fde3a1b0d8b99e4d0b77167fed43121653c79dc44d33c2a18d90f31cf5de78494bc99132a608d7f4f36470b2c4156feaa74b130dce1ce81ef352d167f7fc147c2918f2eebf339df2b09ed42e5a378c322c2eacc41db64a4c4c503b82a016a19c9a1420b1f8408fc6e9143081bcbd13e01059cf5755ace419ea052e288c2e89036782893b7a6e6babf720e269f65fc68529963502cd98f2d27c59419a7405) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x06e73f37c36181f4c7a3bb03020f928a86456be3a07aa159589ff7a7708f6c8baaf6759edbd7c112820a3b65e3af0a1c17990ff1ff16ebe8ba94018688e5cfd0fe45a599eb677da498dedc30f311c0f5b3f6bced41aeace904394fbb88cdb28202ff21172c79dce08cc135f614439ad58abb8b5a8c9fc9d9a577cccf0deb3a6582d4574513ec06d2c26daa75b8ab42b80bea79b78e9bf647315683a06681f87e2c181e272956e1e3b4af24de7667a018c0cc7f54d09833df13b9c7b55e859a2a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x18e3f183e245bd0e9f34b5f2fba7be0b00d472bc97c9a8fbbd31f0eb7336762caa0460466df22190b223ce5cad2953ff18c954ce23612f8ce76a8bb63a0a02cfdb73b051c6eb4687747ed58ecffdcbce1f25f400932168a40a09c99b8cc177d9047c3154f719e6b7174387fea6b8c5d3b0e57c1dc631b95d0195629c1dbe13ed561ace07e96f363b1311c2682d06cfa0020df2dec9dca112505a35318bdedcafdba9983fa89112a6093424d132038883e9487145d6748874fdb29f25549e649a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x023f7d9827bae1d216c3b5d53bf27895d873d326dfd52c8928f309a41a6b7118ed58986d2eb5823119ad11750e1578530174f8a442461f7cdf90bc7310f2098aec57ce96b8df596ef51044334cd7c6caac9ecfa07d54e0c4c32206d65e4ae14f0080401b835896d283524ec6c247f2752d340076c34c03ef1540fb18dff644320682b65e40f9673488123fb915ebe7ef0d308446fb822474a79ff5b8c60528f2f397a98043f4f552e3b7a8eccc1d5f06d83fda350d12773324d8157fa12d2872) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x0cf04cba242dc3d277316d573ab85865bff1003a6c9b2a14243ecbc70de0c8d42359d282a6c244cb32c8e2c9fa80c33a0d843f5af5f3197513f1104657b22cbdb037df46c59cf9866b3c92f89b02f80f43aef2e945b7fe51c4d20a746e23b10c0810b03243b4fce39e75155fb0be9dfe58c4fc9ae38c4842dcfb2adb108c28d23742d976febfa83db441bee72874341411344d26f4bf28ee81e8ce8440d6daed027d0f50a91475ab1896bb2abe00283c3fb5c3163b1e9f62dce0b3a2bfdceabe) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x0a7febe0b967b83cb0268100083eaabe0b795d8005c5d2b8420e1d7bf085c622beb84605052ceb840b70ee22c93e94dd0f1b1ef24d4c5d7a0fff4a85143ed3d25e720584984f63394247924a7c6f16b86e625f4c474024bda3a9477b42a8f07508cdd689342ead177dde1846863ab39fb05b2c39f003e2019d8905563ae8bc352fe1fd5dd9aa17d45a430ac8d2c455bc06bd5571d25153ac5728ebace1f558c0e0b6898e38e28e5855cb5615c4938f4f90e89c4c24780e4b725c633d41dec341) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x02588c524ece6aa9f6b39beb34dec76ac2e413a1c8278fd195ce8004522fae2c03f5d39db93d2e0518810b89d84824f402d8bef8c8c95ab3a1f12b146bb6f79bc1710716a3fe07f00be9c999bea287725c9f7304d7dc8d8113cab9ebbf65de9904d0faf527c399199fdf82288d0bad821df257abeb0af87e4a7a6d1152cdc130d9494a254e102695f69cf6a7e67d5b4c130e25fc5f1cea9fa2af715f28369331c8631e3b45ef5ba0c176140895fe3d4952ca830b024ba639af123e0663286aa6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x05f4e6e78054d5f57c0f966ae722143cd942ddd0701d1d250469001dfa00a7665f892cdb10ec01d73edd2fdb6b4b7e5904d839d8f2304f07af2aa949e2f6990e755c158a131a0021db8e9087b64c8fb299dbb88cbebc6df040f0855c6ea3c12c16e4126aba531a2716af104043884b45ae86643885a4352f846c00bebe06d95a864aecaadf90796a9fef2e94493556be0c62d8c4ae8a6da5831748c1f49d5652fff319ee3001a7043af456729cc75a0ce6cd1a8cb7b8faaf83bf16e220545b6d) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x06ede848560e5bb7548e1242039d23d2d295aae1bba28d81f1f575d659ddd845ead27be44da48500713866ce32bac98b190749654b979702c1eec434c0392c7906b729caf5a1de202c54ee3ba60d18cd47b0cfec9c1f6d7628553eff579b1e9c152d908065af0c2928aaa674a75e9d971fd05568b0dfab0997acc07e8d1671703b8f32d39f1b2d0d667267a11757e4480d989185c92e9e8059712501ed093f83d420f1b42e569d204add6bf80771de9d05d35d90e2a09991f185c37fed32a2d6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x08d2db820c7c621ab36801b50fa305664db97aa112fc3cb2e42ee763bf87a1e42351a4a33d8e193985f698517a03201d0233e3ab5f5a88b0ae54be152198c00aa8bb7dfd3c44ec1adeb854fbc8c127d7e82c45f923d3702c8c56d186861751bf011506a10f05647f4831a681f817781756f9c202573cbbf3793842fdff6b930a47bab336d68d5d92e7a9faeacf19388819a88ed556537dc025314de00503412eac8e2b3502db8310e1c853abdc13b5760a31c5df677fca11b8d894ee46737fae) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x0b418425a494a194b1e61a5e9c7f33ccd57fc0ade63a7ec39f6844b81a5bcc66ad0fdd5c5fafa9ec7b6e4f618100aa8901ff959e922a1917bde9c60f2b72d3dea0a953d06887031f7bb1962b30aad9dd7d2b7e368a96e09de7ef3ed072887f9316588eedcc134b01318669e3ba159456b66392a022244a424272b02358332d259f0c7401ad9b94a6ba6d75cbffe3cdb8040c35d5a9563fb48f1428fff211db8195da051cb85c693969ea681f7ef25084ddef35ab31d9af60079a8954923de8a0) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x01fb5b8374be433f9e1908c01a934c5d90f92e1f64f9826470450506dc83e07c8dcf56eae6e971bc2add7bab61fa376404f83291b88f355c33b77714bf4bb8e55972a86eb17610a40e9418a18cdc9427b33149670c80a1a3166b7ff97b60308c171744774facd14df4bc23aa5906744ab2fe93d54f921a0d726138cdd52acd3b920528ed3e512d1c6b602ec1b4abb143036c525e701d18ba9bae07862ef6c4e533cd5b48c09f57872c57ef5efd8e719e06984081c399fd6d91fa6f9f71e173ba) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x10fecc2b0b824a4e3cb949d0f604afa9565b1d993f606f0746e5debdf919cee12d2b6ec90f5a0777329d7be4b1811dfa0eb420652f106b375d19c616b29d83b240d95d571012970e4fe18a2fd103f4815a729ac5116f828125dea40871aca06a1352ca00fbe052193f5c87693b19c619541482f9fe4b96a5b87aa27d2e3c90b3daeadf706c4e03774bf15d75d1499b1401b9f225b3b2cd4c662f22fbc16101942259b0d60a584c1fff4214fdbad21266dbd1161d107c2db3882ea1e76db6bd8b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x1936c0b7c3d79501db11eae0e61003cf177cb88e6d227c4da44865fcdb91e61a3b08f3c8404c043e83bfcbb8502d7ca3073c348cdd192bcb578af92a18cb0fcd39fb4e42183d6d80469c8883c72d537960e405f39c739525cb223318c2f008230d62439b566ca428ae44e5c1b6a589cfe6b29a60fec77c63fe7559da0f076a9d832ab2b406ce333bfa1063b80e20be131836a637bc8a0e967dd3c8c57c7a3071676aea8b4b8d7dfefd755abf4f5c1188e87651535542802cc0bccf9c71db0be1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x051f4837d54a539bfd64b8f0aec82274813524579e0b61f8fc0bd65748796b6c374c9af207cb4916e77568937068a25a0a94831a3cb564b1e67c10842e3067f78d6895734d5c751cbf35ac2a54d590e655631c27779f9147acfefac0efdb45a11365ca69c824d8a4f583b72a8e82bbc61ec60e80b43eb9f31390f0b48a3d043b2fd87aaf803f037157d256146fc83d6501a7dcb3af681bdac8f39822d9a964dc603fcccc13357c6227a15f4e613eeb6826f021a06081270009e2633e3e814214) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x05e30ddd7d912be3fd43e86532d79aeb60c1a65ff69813195467403d0eee1f10d28e72962aa0da418c5473b11911616e059a71d47ff899d4301cabc9ea9a224fe014de235eb97004cad32ad3d96c96139c7694a34b7f058e4133916fb9074c0917ddcc61be042f8f8a488ac387708fbf17291cd032691def4af2ad59c454665cc4f30cd6dc1ebcdc3a644d51db8b456b0d7562d6eaf317472014711160ebf4c60186d1d5155f0338707035833aa77d2e63343df7ea054b52c2a47d23cde92c63) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x09796cb4112c32f3d673a13ba02ebda297c6c44b8b82cc731702788c64fcf552823d86380a0d87b03bcef9c3c374333309871fa678f0980eb27d2d8feecf92979d4248bcf5a3c52e43ac103f97c11572e37c32f89d497b3fbc737b8bbda81fa915a31a4b7a63e27df9d7ac93bd60b320f72c166170751f9c3581bbe37f4a7e87123e79d4744582a4124d569c3207a178148cbff1b45ebd7c72d9b66a713395c82873fd93be5836eae70f9c28c97c947ff5411c66d59102efd4b609ab6adfe148) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x0ef55120c52f8ff2fab3e0d8df060455e6bc568df494ecbbd0b3d42d9efc49ebc5819f9ea3f41c5d308d118af3850a9d03d7daf556a20e50204d80319dc73e78e03555a16a5d0ed40e4b324863226d72bcc3dd6313e846a40c101a7183e20031158b37855a1d9747b887739fe8b7789419db5a6e7451be477a584a958c42834c8f8cbf19fe0026a91dd0f3893ee44dc00f6f91258dc436c45da4b3e4516a83f563bc47aa8b2f5038f1fd1222fe6828886a1e93b0dc7b782bc631528d30439ac3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x164697d6f33b01d17a0346a14ce7ce19a9da7a9b50fcfda5d54506b5c8db71816025bbae72b2dc79206c0dbc212fd704015d7083f71040e8d96fc12891a1d25abfa31888b6a979293c6981b85ede61569e08a6106fa4dede8fd0d65e6ac1df5908cff6f38cd6f08391be6eebfd4d9d930d8186a5a74a7873e38e74a5afc1af0392711ef285017d01d82b7eb7d2ca08d30b7d1e5acb97dac61708a1e39eda8c3dff83ace70592c7fe4fdeb0615598a73f5f3f6f80b65674441aa1f3218bae3df1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x0f54bb273a6030da4bae7bbf62cba2232c4255610165e5598ba5411188edb6f20d99ee58e7a7af4d696cb304a07ebf2912c5133de2e27b0bdd1da07fccc0f9929dade6c7e37f39b3093c3e9cf5365f62b58d27b767c3ea8d64881c1f6de14b6b19a8433728071989d64002403928ea4126a9ac05e3928c5ca30dbec55bce1ef27e88e4fd321734588f7c31c447f81da21465cccdf04ae8e310780cf5225407de50c94a1a8eb65c475df88dcd5842efbaab2193de3f146eb78c06b9d2a38b2225) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x04d9a9124549958c1a11b2db4fe76b9b79f9328c316dddb2c09c2abd1415545b7397d65fe483d98fe4fb232a868ba67f010450d80cdac1738088013b5f00f0db1823caf600cb1577742e63a87bded90d4223dea6846ef35faf3c59e79b376a9b10f2cf9cd5ac868a172747bd67c9477f39ebf93c5dc150e51f4821de8839ee2f730910d6f8449d9de48714601607194819d26c8aa7499c58bf4e97ccbd28ab1f24ca0b43f091fef8e5eb04d6a12accedbc0da34cdadc495512a5a409172a40b7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x067fb21e2f1192ec16981ffd2f295a748295f255c572326f4fd3eab787d3ee33d229debd5e4450df3b90f972682eb9200a72287bd63c85a9a339acefa4ccfcbe80dd03575e9932b2a154635f31cedbe41a3c4c5365c5cfbaba1de4e22109701f06be87d222833d8038cfc9a11fa5e60bf83d9e9a7e2dadb4031ab2381119d4dde67020affbaa9c776696fb90d0a38a8119e58bb1a850334a2099a45f38039380918ba4c939b1373799cbaecc1604760e810d44a23da90eeb5b951a727da8d581) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x0ae2f725fef75b8f47a111dc998d4cf1176392d6ebd436fc090b564c867697ee592b20813ae421c15f79ea87574fcd2b19bdc85d98f0e9fd10de46907a12d97c3211df3a1ac8df43eb2fcea3d97ed8d704321b253dc7b8efd8fba71d468fea04053cc11354cb81bbfbfebdc2950e043e59bc0f391eb5552a6da2036cd02fc6d4adb7391eb5fc1f7abb621dce078036cb158c1e0d39e8598fd10c0f83d83070ceaff1afacc159f009253dce5076a601fc355c085f47461fa7486de2230245920a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x10f9b44ecd58d1f17624fa7681bf756fcb339346d3d412f03566ae196fdea24da42a257d4e345eef7601fb1b17e005550853a22b71d9d36707054970d5b1bdd6f5055e846fa5a4f124250f5a259e6aa4000d9c063d99e691c9c17709942cd22f0bfb15e32ec77bd2cc13875b34d8c44cebdc8734fd580c607cceb701030277705b1b9fd46e8b44dabef2d315c70119920efd6d775233e13dfab608788111cc3dbb1b2f6f92bbdfd5a482cd2bd865184153eea824351e79bbea60bdc964ee77ee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x16a05820a0a16664cfcc71cb648705640a056c9d9cc6c5993aff22f6b61c7508db19fbf0e544b9019293ff7ad93e59b002d91e6566ec18a8e3bfd8e3725fe7a027b055273b86f1f1ab5c02855825e24d08964ff0b16a24ccca158f5616eb762510d798c4e710e264a85f9ef00e18b0184382e07608fd2a213f829ddeb9b286c1d12cd547c5985ebdbd6aa490553a72df06eb478d6332ab4bd4d64c325824761b811c0ed8122b6e36f23f06ad1fac720e7f1e7b772e567c7c0a283969c5557807) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x13b51f50b39a82cc6ea6062033dfd349c523f80ecc88cdf69a80f5888f94b9890ee06bc735cba06cee58c5bb231b17e816309ef2d3e7825b96a2070521960fab9ae5caee8d35850d47d3e6a7a68112796292cee40bfdec31705e21ef45375261081030da70ad7c5f27909abc920150f17d14f46710e40bc0b761e7110f4ef6dd08faf8f70395fb6b659bb797f241cc2912a68dcd90bf184e54db5c48808dfa2cc9bb16569500abf7520936ba3d7192240e050651201cde83f51c10eaa66f5156) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x1939a758be0a4569e65da1c38df793a425ba148ec01fee063d8aef304cb0cecd4612034256e38bd365929604d27656f306384a1fdf4742e1f3ee39b2b6145e74d346e8b94eb6d1d55cc3293438ce7b4425f4b838f4de91dd352cef03b11100b406cb1ae2b40eaa79cfc619f6f0cd55d97550e4f6fb777063a92abfb46d9ffe9821c08ab9c798e0800e305354f3c6ee49067dd176aa3b4a561b8fe980ad7b660a41a5563ceb1de278aecfa963237c5a050fa588d155924fc1ced9c7a5528ee120) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x0603ab5573e02f442c3a466382998a95d95c4592b3cbe34eef323e588ab1d46b1d98b089e0646561bb6ab834d2ad2d780912ecc7bd31abc0a5f2fb5e6c56ece8a3149a8986d347d31968f9180b73b1fa6e8f05aa2adb4008d594f3fb06f1f4290933ad5563d42a45d156aa64819a59c34ac4432fd51bb104f6a32fe421edfa064acef05dd5f2bc91bc37f5ec0ec832ce15f13c5a9c3d281c0ee314f8ba6a80dfbdd009c2081decb62d06397a4355c740e3841a5d50e776c56de8390b2dbc4875) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x18870e8f4464f3bb7e79222f6eadc0c7e3e08ded07da9648f0759b74a4b09a18684f88469a88b1ec73ecd7175260dc630dfb9efafe23dfb8b26904a00a9407a7966ea4fa25615c31eaf9044d671369a8aec5c3efda6c4c1c4b80a7b8f6e65ebe1258d12a7b8e7e64271420f667231dd7b5724945ba1527e56319645135e3b33ec14fd90b53cafec63bdffda506e8f10404c3a7918ae658e54b5a78c7c076bbfc0ba4d0ef955bb09c0023172e870ba7fb94c44102ba8b3001c5431046f6b9e761) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x03d06662af3934ccdff4d28fac7281bc9ed149ea2e4ce9a2c7727a6cb84f31fd61ccaa2059be8fd41ff6c8425f5d7e510534d3851a56e72f97ebfacb9ccddcf4d4571d14ae4ac7aaf046ccd4ee903fb06681a8aba0d02fd5a1be5b45e40f84b117187fd5a26936ebdef1e288ebd03d9edb787cf2ed06538bb24f895b8007e6442b3b6f3f878d09ba6790e403b6c34c5b071c00b7237693870fb40823a08642de2db8ceaced2dc832c77f3754711fa39df03f1f57624e9a0570039de6f9bf89a9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x0f59ef1c5fd12c2e50a78f9dcd4ce371b890f356f3c66d2ef70bbef53d713dff17a9738cb09e8574f6e812cf1fc8459c08cd159f8e3385e32aeac4a7227d5c0b8a87469aa70bf9fe9c1064efec96ec6dbf9c2af429f0a48d66495688d244049b07ca45abecd4f97135fa8dd25e40cadd501f8753502f48cf3d102016c43e361e84ff2aeff5e40e289788d2f944d783ef058d9c8ec4d7e7b941e261b5f9e342b5006bd8c3cc50e8cf37280199463b06776d42303c1bfbe823e807ee74344f3803) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x124353c0c0e37e598ab5c76344ba2c82c40e24862eb4490b8d3ffe54b9c228db0a22b5a8a3d3ede1b2de18c436bbfe4c0b7ec4e4973d2e742e387484458916d35ab73f17e927f81b0bdae2b0b3b467c5081db4e9ea3f3d65c2c017f32db916b30f1e29e5074396a921ccdf5d2cfe54351169613d481aba30d0d903410b87f6b50403835cfaee9d2ef5c2cb237d11d5ee0b8f64e1cef69c652094de46cec9705dc9ca501c7c9c7af060303753de58fa97ad12e03f850fe9d65b0852acc5b58f26) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x1213d72767b0fa5c926a3b058ca3a9aa10fdc2b0d0b97adf91f660c13dfed4f7e57fb467ac0c9f189da2ad5ed8c04ebd0e92b1e90a842e6ca42cc66c26196084b833214a4b1fcbafb01837ad086790fbc757c537163be73772454a7d0feb28370581169867006417ef509317891b36f2e332953d3f637f6835b58e4cd3b5a1cc6091a1e17792d23d41cb206de73c1ba0108e8ed23b2b15cadf3bc89188569872d702b3a1c2f06684e294d77ebcd8409f736932c59c075ff97c926530afc09728) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x1326f98dbadf4dbaa18df0fd87271b7a34c8eadbdac18f92cf712066295078b4d12b48de1346a8c0f0fc2431f82c91460ea4d3ee221040d0b669be9f5b6e4a2e719b899770c2f17a345b746377d003953db1b5f9cee71d6e4af17b71dc0151f20f4d08e2fd406003967ddfb1a5d6c8d013896875df0cefd6d3395496d2ad5ef6694b2feae8952fa1ef1b52876133b57813da5a30be043006fe9333c14279abbbcffbc47fb46c67ed7c1264a39e53841e2d2c126f207dd055f373abcc2923e916) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x05c11a8356a82f725a9f484eb5376ef831351e4815ee9696bdecb4d0a31bdf671108321796129b3dd7e62692ddbf3a980143b29d8e132df1cb431e16b4307ba061c6db86d018a44f55568f686915b48c37606fc28ff29a68cc2e72b2fc56a196188aa6125a92876142aaeac49a4ea0b65ae6e53b1837f87134ee243055a420097eca13ada16878727ea0a3804a1638a00a41d0255bba9c8aac9296e01a181f9c0572a1b2e89349988b65f0c3548e2fa279c1d7a3a3a5d89b8c9c3787e0bc919a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x0cc59adfdf284b46ceef9e94fd82808ed58fb5b269ad57eb1f53b9faa586107ff1020d8dac3f3ccae3ca4a3f6f0e37f8195f2e52ee9347a5c2edaf78672fbebeabe0944f61908a4454a5ab7fe7a4a49291fce6dc8ba85570ba6ed43e41f3efc716267d38cb286e90dfe0177f4a757439ea52dc2f4e33b9d02d1578fc46c394bd8bd5c8d90b8743b085d0830d4ea51a8a125379289caf50e1373e331cc43643025c9c06f682e8bf2e2cd44f6ceb04f629f23fa2d5d12b04ed3ade91fb51adf9ea) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x146425b42bcb86ca1a9338b7f97911e2c29f558c7511e33a2940066fd97fd0ca98651bf28629af87c7223abf60bbe5e000f26c6480ecb410e87dd5117fcf874f044501d391ad264761dad919a66181ee47ad22c53de6343a2287add11fde2a960f05e7349a086d1df1fce0e711ee1fd825dfc26323b23d0f9d67bd5a31eafe29e8380793fa443f9ac86735e005dea9230ebe2471063b42e5468390f089670b7590c67e0fdc16854d6a8b84062676da2d2022c6232faf46755afacb84ecfd1358) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x08782d43237f97a5cf4b4df3849c5edaddc2116f998652cd1a0deeae26314bc7bc4e931b2658ff59437f6c23a630a70a1541e4c91e3f5c5cb5b75998c974f949033cea3da6ac0125300dede47b58eca3f72b103fcdc4b2c0b54773821ffd9cc10fa1d239fc77ba97c27d76fa05e70af53ebd44562697c5e7891ae502ebe8c801c0d8737a069b9a91762283361cab97d617d72a20886f0d7da28d33c4f3bbedb36b09f17554e9f45dfc25e9348ee841bf971be9d33a75af69ffcef3bebbde5480) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x18f273b9c39e27c942cd80c28d9ad000919c8d1e89a151ffccb0cd431eb246fd622fc1bbfdba7d4217cb988a408b2d3c14a9cd4d9a2991c8a7b4e4aaa7a85816ecb70caacc8c557777257aed3a207eac5beeac7e527c2c7a41e367a08a08d3f40654faabbeb87873fad510360e7af9dd0bf0a8644423966703f97f227a4a8db78e1a0ecb26e73cd2193c85837447fe030bb98c5d130636f451d4f88b73c6ebc07b3a6555f99f9ffcc31d4950d87716333153ae80a3ae8809e45a63d3fbc6f51a) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x144df1ee0d7578b9cc430784734fc61d537a691297d24791c55fd7f84a120de74992f28ea2d946f6bcf749bea383dde7092e9aee4033520ccc5cfdd1ea129d0d37d659c56e161c11d6b7186cade1f4c9da8890481bd7453aa291f96a395f72360de71a74c732f740daca5646ffc15cfbfa326a98183bcb39ca01ae1ab5eae7ba93786ea1668d85538f29ba018b1b272a0525940f76acffa8389d2fd16bf2782092193812f934084a151815da57b3f0728c04dde3b9ed4177d3f0ddf185eef422) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x1093a56c60d4e4272585ebe02b04111b3bcff524ca0ca47e87831109b63348de87b7b069cb75a269d888a4d0e74836c412b6042e961380470bd3c8f383dfb6326570ac12aa4779744b4d4232b4d559ba693c16ff79f44988b896a01709d373321353ebf4c9a0878cc8f19c7802bb63e617a905baede501780e5fbd7594b79bf04641ee85daa1b28971fd00be1bbe6de405a7718928c4aa21e76739c9831e9db84381b9337dda9bf63328171ca07710d93ed1b004f67f131d4eb2868b1a727aab) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x0419393d95c6e4facc4467b752de6cd554e2d2fb8af5005c4541d11d43ea41417484c39e40adfe4bd91763d77209e15916b9a914aa7dded7d5ca1eedc3c1c9210fdd75bcc68ab3c9a6fa2867e1560d26c90b025540adc2a7447f3d5b1b2c5677117e3d9eafb97c4bc8cea1e2950349db4d7b5e981054a55065a5cab48aff4e8c4ea4781cdf19c5625f4982bf76ffac1c018a891fbac1686e9c5be0a5ea8db50ce77fca81616f0a80e0ec2e21d9630d32c0d1e1e30d73e1838cbadc63f6123b61) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x056fa4dc97c55b5b48ec94eccdf82117f95f529130ae4fa66dc30360639db6c1a51a44ff24b8fccb3554521c2cbde8e50d2f31cf281e3ca0ec5bb392896881f7c0de3f4be17f38ab256e12be071682e114e4dd58f4f6dcfe28c91dc98fd6a2a9033c52d47c41780f056cd75cd26b8367e7d573ef896ba9fd22a01b4ecc4f2c666b89565766fb9ef1a69f52eaceb603e806f2310cfb040faa7b9cad64fb834a859287271bcd4eaf85056061c7a0fc0a347b4545967345c2b678130d1f00ba5446) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x07f5c7378ba427b8030cc07b74a7ac6be3f26bb7427d4de4199b390d611338cb53ead89f3d64a6d2fa82f361ed5d6a1c0136fff6b37faf56f46ee1ed69bd8292e92330fb65146221ee33d86b4471cca4a249fd66f7c3a6be6c9639380e767a57016bfaaa68ea57833c77c10997dcb6ea564d4d6994e43dc92f62e0e74f7493324d4ebeafd3e3574fee754fabc3fedc6e1767af50ddb2c80622f49931c320c34b5cccbdfbaac25f144added43d4e6a13ba9fab3a648c31d54fb70379bbc676f03) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x0db47b23ea8655d8bdea4a964d287dea93e2051d6b0898b8f227ccd5caddc06927a3417063b47ece53eec7a71aeea36308f478ad03a0e1a46e552cd5bcbb78c1ad774f8a1a21196ea186099c7c65c141b4400e3543630e5ff4951c2d634e43770ffff842b9065591f61bf71accceaea967060e3c8c4c3a6f3f5cceb6d9d43decc45081e6c73b25433ee07a1dd554de7e03b526741059c6037b20ab02d2183c2a63948a2d24b6745f8b99709eb440f70e839a6af23f1fb05c0434a25dfeec8518) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x096faaa2a2e6f86339533be33fb37dcfa202a757497dd6a2ead0d27a8943e909f2a8b1748cfef0ecb80ca7dffeecdd87198390e65d8f6cd3a77d006992ca2d2f8af52b5cca18acb0bf1b9631dc544c3572c9746f5e9d422dc73d2aabc9cce5df18ea4bdce226d443ce4252d77d42c5e5d95b80aa7630a3d5561b9df1b55732dd418a362e3042d80c83754817491437ed01443e49536534683d0f91a832ff6fb4b6fa3172f4ed6510bb1f5033d8fb287c7c9ae1f95ebf0e9121ccfe1f6d869249) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x1018f045f9c0bf23270c53e93e57d86534a92a07450d6ec23d7ddd0948f1bf28dc5712bb537afe14975348c0c139ee8f12931f846fa0fa8b90e43311dfe117e83f599e54bc48f8ff287ae41071d668a898a542779d2a5fcb4845d1ae97ee28290eec5e9f8228dc200d563969d9ecf5e67eda35cf2ad8399b23aacca233bb0a5f556164c3b79751a3f175f7f922b90b5e052d1b8786e0d4109ae7b8b55589cabf3bf4e63962ae3eb6a8ee96a0a202cdd49dcea4700142398c410bfd5ef1370a94) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x10773264c20e034bb3b1940aaf16c09b9514e9ab386a75bf242414aeca5d00837d926ddad1bf73d6e8e3868c65c2360d081d920c6986f04340e6d288b5d6cd0e293d808c797e50a138ea8f2eafcb62660dfc376ca37bd83383e613ef02947cb200cf62f889f8eadc8a75f2bbcbd5948af4def506b2a91af37710fabe09136ad998e72891b57316b2501d707b6e77d2dc10610a3f1b5c9d3551b234a22270225d579bff41a6bac7fd8d88f5a0b0bf5320b2435774adf05a59c98a4e02e25cc0f6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x0802ce52aa3827ca0c448659c5e752946d4559cbfe831a1a3fe1961e46c4d82fe7e7dce894eab491828b8204361ba67c188844521c610d755db8fdfa3a8d984e715e688a8de91b431b7a39e55527770ae6bfdd9dcd4d823870edb7b507fb8ba70337543622fa6d36faa7af085fcb810a9d6269fe5ea41e197ec3724662d436d0a5197eb21277160bc895dc0befe26336196f2d23ae192448908aa4afce25f76b24e3e482c57201651c6cde3ed02f04b7a51918a49ccd8e10dae597c64b6fe9eb) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x028ed975c6b20cdfe6407975052717080c11fb0139dfbda12c82c61225e07958f388a8977b7564487a3d09c54da95df203601bb8c797a8b17214b9b96250341adea5f0a70896302e4379a7819bc54722cd055e9ab4fbc74e833b2ed38e2a856211acf6aed8a4aefa31566ef473bed06c6c849c0efe391d335924cb41bc7da47f62c9d2a3df7d634ba6e10ea29fbd43c305a0acaccca51804a8ef4e24b4754322e13126345b83dde0fcbf5396bd746b21f8c223239441c21359e1e5c22aa203f4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x064a98dcc354faeddefd85c4875dd501248d76272170417169ed41ccaf87824316dd799a32bf72fa93c757aaa2de82de0bc452e4bf80f9d9019f47c74854c3a5c091c5ee1d36a09df9e532af952acf209251bf751aa2c901de2e767d146968f51196a5ee76b5fb38f9af32d3cf76026a1164ea220c66d70cb389785741dddcb8e47057989f7006175a759f4ff48afae001ec48cfbb0ba4f28fd1d98c623da183206479c49660a84b2effb8052889e0e671e1abbfe5595e43fa0812734aa4f0dd) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x0100000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x0000000000000000000000000000000000000000000000000000000000000000' +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x41ee112fba7c41314eb14660a396fee42bf2b5c0598bd3bcd42db2ff5b2ce027' +storage + (Some 0x06ef487290cf9a63c50b288f0d61a6df4b2285b575bc9f3ad69a0ab5ebcebd53a61fa08ca56e13ae9c737ca68571131c08d0a7218c15f0e0fe13522bd3c778825c94a4b5bb0f166d0a6ff98cfaaa26d8daa223f84b1f695df1409e60521625010af8d68419109eee57c2c2c90a832773be1a39ce99adfb59a7b4105d3ed36bd75c27f28f3c07a124092a550d5f5298470e3e8cc369b2d9e172f972122dd20587a20dbe37d00638b4f506f6b4f9e96c93ef4e2ecba8cb1fc7cd7760d950ea137b) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0xc442754d43fe94b94bc69cf090bcc64af22448dab9991e65123baf57f996dd73' +storage + (Some 0x0baba172361551b9b0efab885364e474ed868daa2bf79b2fefb2028fcca9081873dca5d7b20c638ea4d6b69553da5a7c0b175a2976fa0e2c4a7c7b9a795825b8c0fde5b3b6a01f189b9b9abfee5f925639c0d29c5c803df7a973b0bf0bf7edcf0854bbff06330652371c1076edf15ca6747db911d2aa0d624ba62eef7e158e8f72f7713207e772b84468ea05ed86738602288d131a5cd18b6d41a9e696bef6f31a196b241fad173b6ab21052da67b8a8c13f34b6083c8da2712dd578ff8179d8) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x8ba730fd4757e7b5a7a0b00a98c91539ce3878b0d6ea5628c5a675e233a95365' +storage + (Some 0x02ead5ffe35e4e026510bfa8ac4dd8c93203d4ca70eef6212861438c1c6cd2f9ac3fb80ad4d0dbeb62464429756098e10dee895535374bf9a3c286b740965a863cb75eeff96478e6fcbfc48e57309dfe2361869a3318d46f19dc82a05c48f3f80b05c98a156dd65796188c57fb389df353df45802a1970ea6521ba9d62792225bc109af013d57d93e875aac7c1ba8cd4126070d747e9f31a5775ced91a3baa2584ae466b8a9857e815118d18b416ee30a88ce70f314ae5ce644e85b08387e128) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x198da3ef817efc195ec0f8df2a6b9a23a849518d3358c39103be11650785ad5f' +storage + (Some 0x0076ec60c712a69a6b958f93ef7ca83c541367ab9bb7de3b06d70bf92b41abc866d50fcda0d488e05a6a8d8b2e7b2b790eb88abed2e1b3ee471267e039b658cc683da60f8c469330bcf99d23baacbc686778bbf384883ebdc30fd44504e9ef450dddccdb902fc57101ddb0ffa091fb619959ffb7742f91046a945d666e49e8963d47368443bdcc48d9c59e64d31c11c200a9f4caf68f46d7cc374dd9c4f4a5420021c61d9ca22bb5ab8d4570955466f0c685fbad338a8ac1f01114809f49a646) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0xe3b17a70a9422fe8a965618716f8e31903ea5744d8cd015eadbaa32b248cbd0d' +storage + (Some 0x162a4b7ddde8ef9894d765205541f2e60c9e316b18e1e48a64725f98e4844175183d4d5e06192a5127b8d780083daa8b0338056e76a497df055f943e68c45fa8a829cbe8289d731ed568081f671a260ebd624e44b7816f113c0c89aae5347751079c37d7eb00db6938449e00c74fe5ceb611197be4dd904bbbca4fe171007da62f9c925103d1d3f554434b289cdaa4f016ca00ccce538e727435017a72bc738e450bb6e14c9cc5a9e2e501a56b8419d1367a8d122a10fc0823c7dd9c5a517dee) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x60b29b8986a5b7708ef2438a385221bd5f99ec81ecabcc8d731ba2d3d1dff50d' +storage + (Some 0x02d1cbf6a5b7eb538f431ab1cca143b1ca02e33d90107f8e82871fb1f33f7310d6ace083fd7faa2a2c1857a4e72638ff175c8422c820d94e2956d27ee2f791eff19e705f0a62b17fc74ab6794a0dddea4d72faba9b8230c4f9dbaf1c44534876111d65a360e6d0c1937b600b7f37b5b5b4d326c08119a4ce905d9c9103a8260fd766294d7cb25f90b5d152b9e9418b9f0bce7a5a0111ff7c4ebea5e4f87b6a149e6357386f2461f70688514cb97b1013a0a0ff610c25dcddb81f1e48e8849f27) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0xe46e41c55be0e958ecfd46b3f69bb8b4803dd982894ad6b03d96806538284651' +storage + (Some 0x062e01652129da7f81d1ebf0f0530e2f9f7470d2ee453eac6abcaa84bedf8b2e98f4c8ea2b61032813cf7adc0796274604ab49a10604f75265c448dfba91b9b630bd96f490a0cb6cf68bdb2ffb6253c765c663840322e4ca3db73140251d93c5085c2bf6c8922ef5cf2fa85c531b59ddbfbb1197e081b4110d36d05655f5a10d818e29462221fcaa5d363c074a55be3400eb5b4334683f4186baa2aca2a676b6fbd627ad2b621364d2095b4e4d076fe06eaeebbe410e6146b800d4c3841dd2fc) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x3959963124bd47d8c84fb6beee98ed90066e7835ebd463c41323595fba944f5b' +storage + (Some 0x098a164689e471ce28502495326966b31e7db931bf8a613adf50888c1f60f6a1aa364ad27683cbc4caa9f4f3bad4431004473e376f1b7bf72354469f61dd9ed207a947676751db08af95b7e0c7ffbb58e89000927a85844bc0bb794b6fbb707e1168a86af2bdea39c3cbb9a4c10b129ac760989872a80122c1420c94210a6eff0e78250831e0df6787a2330c2ef4fce9135f3492f88dd277667d785feeacaab2385cf17d610b8368a5894928f5f685ecf4472107a1d60be8c1d0b54840ca37b3) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0x6c240a669e04c8ded73529373c01f741bf092fcc89ee795afde840a59b251c3d' +storage + (Some 0x04f20cc77326e57857147e59fefc56b44d83df17b7f875ab2e494783e5dc09620ec797196f88f3aeaea101d13c40721d0b69df47c3c997cdb0247cb6109b6dc75574c7f9b4fa34ac0009e2d0205c5e3fa2c409f8370a5d599fd92130a21c439b0cf49bf2ea294aa880a828eb335968ac27838a247b6f1b6c3b313e1fafe9460e56d513085c618fecc2ff1483567f9c5a07afbe632eadb9f19107abcd878b38812cee34b5f393cb1abcbae0e8fdb5d86f1053e36770600414b798a492a31ddc90) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/mul_bls12_381_g2.tz on storage None and input 'Pair 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 0xa0d55de572481bf7cdda17431faa763cf9bfbcbd76812667205017322be00c6e' +storage + (Some 0x14637664950ab9cf00089ca37749e38a61693d4cc526e0e45bbcef9db98454cc2bd1a87a93ee9f6e568388c49633a0e4116cec15613587b591007b3ef090e2af37072443c1d66cddc0f5cc1e45ffd093343a8cd09268d63f3fa0cfb07aac01da01ef73db6bef32a8c40dfa62f5bac884b271a71bd78566068c334a5ee087dc07d8f6d67d73f43f57bc2314bc8d927e47168d99dfa82a9812bd9b5a9bcd3e7c3fdc885865d2780fd08c93fcec32e3c0703e39ddd3f3b334fa552288efa9febcad) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- negate.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- negate.out new file mode 100644 index 000000000000..292f661d45ee --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- negate.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 +storage + (Some 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf3501687299151d018be22afc17ed11479aa6ef4c205379eb54f4bbd1e919a2a382c4843df694df7ef1910ac533cbb3e8ecb33e2eec16ab38ba0c80592e9b2f105c432736e54662e8e1f25ad65b7b0229800955022b8e5cec4c56a6be4fb995dc42de629955) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 +storage + (Some 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10b7719be4db7d6a7de406512066a2309df6ca1966315010e1cf28e81e13742df54577c6beb64e3f5ac12f3c897ab75d5149fa8d126e4fad68e275a7a36b21b650a9ccbcad5b0d8fe3fb5e91a83277294a8f24ab050c8c610a621e1e090cad784) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca +storage + (Some 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb818e1801cd57eaeb542c3a49b2b4e2c95ddc71cb806127e84f640980049b2662d04df1e82b2f2d7e59a9ed0e927ea015c104e3d756d7c2760f144b705d2cdd4bdfc4b1db5db1c8e4293a8b00b6e7a010f4088fc6196286cb9f3b63977c0cbe8e1) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 +storage + (Some 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd1362b34a1681a222674a06dccb99823a884404edf7668691f445437bc9fe1468096e12d37bfe869e4642c2d4d831f1fc001036c23229941761763e78750c44d6df95f1f598bd57cf6ddbbf7bed01aa8acd43d6062b9a9b8a74f6fc6884eaf0f6) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 +storage + (Some 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0f33ae9a02495781152d75855185e0eb192b88a30f85f72710d5ed190e1ed0b9069279b96cb20957344e8d58cd810cf20f9d84d97ea05441c8440259082701bc034c3759dcff0e98b91259ce05e10df347b3eeed1a72663fb0117950bd9ce379) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c +storage + (Some 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c3711bd4e94f2a14575b3dabd8673d80d683302a15b0d24dcfbf593f6610dd2930d044b1561b007e2ea0631a6589e8afb1d0b40842c2ce80fb6eab8d5c91e9fd4f851f350f4e182b96516acba6a809a3a1eeb8a15729edc92b03b1fcc12d69deb0f) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 +storage + (Some 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710d3658058c31ac8b988131c738a38db0e86dd467f04aae4336b75c8c0e5811e1db5890648af1ac8babc1432324ed28bb0954df14e1b66d36379070441e1d2ec4b29497fd94de7944cc170e96b9d899063fba25e4a0171af84385ef7af47ff8f2) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 +storage + (Some 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec74298191ac2fb2d6688e4103baaaef0c893c604402489c73e1fda888fd47c68ff75e3ddf9ee91edb6e7f63af69e36120916cd16e8fa8605097236a7bbf6d16166aaa3d5c8d7b79e806cc6c7581b2f64fa3fb2255623097beb04753bd0d87a355a56b4) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 +storage + (Some 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0e29d6aa4cd9cd5d9b19c18a3b76dd7dfb4603bd28dbdcd013bbb11239556965d91cee23ed3e8b0b1649dcce6a1b2572079f467f12b9d4fcc59ba60aa0b1eae7745c7fc6bd2c62651310166a182698c0b3b3812e9bcfd8d58a37cc53fd031b93) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/neg_bls12_381_g2.tz on storage None and input 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 +storage + (Some 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a752057df09f6b21e00af755abaac2d76a5ac0fe7cbaa41a59df442fdb1bb72a45be1a62011ade8a4fdcc6cff0d82e3b2e7e11c86ec76b71bf216be737be1bf2b757e4b06165f62ada1cf7d12211c60c42df8d58fecfa784ac190d63bcf57970c404) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- store.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- store.out new file mode 100644 index 000000000000..4c3daa3f6251 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- g2- store.out @@ -0,0 +1,108 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801 +storage + (Some 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +storage + (Some 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156 +storage + (Some 0x048e66c003cb07b01854c4e80e9b98d54bc9ed9a47193ae67676629a6edf46de3b8c46581bfa87764bd637d550a172f6167ceebaa1c1ea190460215c6e154e1226915289185cf04612cef778ebfe42fed44f853011b96c19b8a2cf350168729904e4105e5754ea825e0a601b9c5c60b710fd602ffec940d64d8e2f1e322cb82d89cc810d20493acbee4b17134cc17bbf0355d9302cff8d6bafec975a002475f21e1462a3012a3c63ec2ea920ed5bf3f8904f13b25aad41b0006923bd219d1156) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327 +storage + (Some 0x0279884628439bc4921371297859280eabd9d6c0e53cad71c8f8934739ba50d79ddd1544843235aba1a26a36bfb2ced515b40eb2039356276eee81389605b8ae6c904f8a27e885c4d159ae033471da9c141eba99ee5efad947dbfa999af6cfd10e89f82bebc80ff26cdb42a43ce189cd850aa9ee907011b14a3e441f1579b344ca548392c5ef1c0a0dec0c37685434d605616919129aebc3bcf44d3c0c99917259da7fba1dd439c1277ae9867389838f75b9b54e608b39ef13dd1e1f6f34d327) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca +storage + (Some 0x0664d0fddc05400c4fab60bef6dcd339ae3f99bcba072227f08d1c283f51397c8ac042fcb31dd0d52ee3986f7e9eb2eb024fdce315613dfa85c3e7cccdeee2c8536e373f1ed97451f49d1bfbb10bf074bd3e5bdea86f4a1d9cef681520476eb8011f91cd640137e50858031b17fd804186b02ecced72943a70f03aa0acfe8ff719cce17bfe61281a1f602f16d815a94f09b2d474cc03bf3959d6f0b0707dd819682c2dcf1868847cd38822958836f514de23039d1b2b9345c648c6883f33c1ca) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5 +storage + (Some 0x021e2fdfb66974000c5d51f648aceb27115721c2d1de3678929a17435e8eb039e0d8f89d4d093a700d100a8c9a01934c197a4e20085a20e451e22f46979eda8e5b7061280cb58e157e3f0a5073b6656c0574b47b5e0410574a3b452c6e447ccd069e5ea022fe4477e3d1a0d977b22a9cdc334696fc1e8c2d72eb8f252cb2e1bc153ded2b3555796173bc3d2b27cdb8af19f0db2807565282e9a5693dce3f680084e1598f5ac7baeff955132509af4b99516829f885b96475450803977b14b9b5) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732 +storage + (Some 0x015c946c13b84387740cf5819727445ee94c61f228c340efe76a8cf1b8017447a6ace3df4b7e75a45a05f84bfa6b8e3a027c66ee9b741edf50726225783b632f976d1013edef14c60189217e297bb5020cd6c0412a4a436b189f1233e37a5eba0acd635037368f1935ee3230f1c5cbec4b4bc2e1e3ff1b98565ae587e892256b1819864544a1f6a885b072a7327e9db90a638d10badf925882d7a55d3b24ab1b612b142b16860426ae1e78d2f0cfe830d6f8111196e199c009ed86af4262c732) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c +storage + (Some 0x185cddf00204fa60aa0d2d31a7f6e72282bd818d99b2592caf7f8bf7aecdc744edb257e30aec8d8d784fdec3429b4dd40c311f3decd4f1fec6d1bfc2d5d0a521f3969a3633b8834b4f145d8ef4995704339c31df383192f5968ebe313b421c370843c35546dea1249740ea2fcf739f6f3174aa29e66035c3719cdc3fe8de63171a60ea9d014c1d15b3cd59a76174af8e0ec08dbe0c97d6e36062d1ed24abd7df1283fa901202595a508418367616bc053321ea8c12776d4f7edf33ed2961bf9c) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9 +storage + (Some 0x0d842634253f976abc6b2f8717b67f07a04654495973639815bf7c4f8fe9ef66fb72737ece8efb14185f92c7d64696d318509f5e9d5016313639090c92ea510f416cd36737dd35f3a2ac5cb28fbbb81eceaf82eaef2c5a2bcd0a699d2f600d710ccab9e4ad4e3a0eb29a75ef0aa81f267c09771d033a647c30797614e858e44243536f9a266253740e3dbcdcdb1281f010ac32d557c97964138b3772252e7e12b1e2b3875ea6997a9b19c40a3cd85d1ddef1da1a113ce507767910850b7fb1b9) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7 +storage + (Some 0x0d1078cb857c9220d0767d2359193a6ecac1f925f6104b076daf32da2cb557b8674fa40d849f2be08b713eb6c42a2fff094506665ae13319746c7602208d7d57aec06a06c4955872cc172f79bc81a0a2f35721678b744765ae9f6b061ec7429800e64eef0c195db63adffd0752831911603726fb2c46f2e4dea0fe248db1804040b2116cc39d18097f0861c9edf693de0318176434767463a35fb0e4e1e502338eae73cd5504a5f89fd8b77191b6b671f955dcf53568fb8a7e2e2785caa553f7) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18 +storage + (Some 0x04b3ce0ec841968d60e14eadbd8f26db9409bde0465611d10c81ce13c01e7c8ce8859e836c9d481e672af7e1abb5fb0401b2d53814b8df9a7c1f6d77ba0626f3f1e5d301f5138a734b56de63596c49af4664151e3801e19b0618fce9c8d10d3a0bd73b3feca6193cb001e62c07d4cf59693147c7caa935ef5375218ebd5b8cbe458f11dac41574f4a3b5233195e485391261cb6b26c6119d858001aba299c1eff01acbbe3658b05a5420bc36de8a5d636af87ed01584272a2fc733ac02fc8f18) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/store_bls12_381_g2.tz on storage None and input 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7 +storage + (Some 0x068737d03f75944a6de3af8006cc46deabba7c08bd1c500094ead2c446b18a04093685cace99d6c7ddd2857455432193041bc6fd71097603e7a410cb79b338bd078a2ac96574afff4b84f205e08bf84c0eca52fe4fe7bd95602e7dd80d90a7521483214ace5e068f53c5fc0b8074427ca378ceca4f6ab8e02300f7853f86b0660449fee3d2c9b022f32f0f27d1c47c2d0838a322ce0e2778df346ff82758f57f7fc6ea1efd5a38a26f5fb08f30a4b3449153012f09cf53e6ac9b430a868ee6a7) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check empty.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check empty.out new file mode 100644 index 000000000000..88e8d6786aee --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check empty.out @@ -0,0 +1,9 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{}' +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(neg- pos).out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(neg- pos).out new file mode 100644 index 000000000000..83312b878c13 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(neg- pos).out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d710ea71fe470a949a162b6eb7c208ae39ea757db9b95ce97497b99bf9f804f54f7792fbb5560d4fb7bb17ab3640dc4700 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500d4843f1486ebcfbcb9f7d628119b20e9079757dec1999c5487228e345190d1454f28d3a36d781964279de5e9fedcd24 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30d47802cbe19afdc9478272cd0160d92fc58b6ca4327e3aca5cfdfc68af3d8466bacb258b053d4281edb6d329a4cab02 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907706c1045e73c0f9e3b4af1b27a73feccafec4c8d252cf5019cd524e150bea2b71b74c064c9a2884024273e3dd5152ced7 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c285702090561b8033ad1b744ba6220f0a6c4bce2819bff957663db716b7e569a3df43008aa7eebfeb162bf42f4bc6f9990ed22 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da168ecb7ab4922d346c5cb3cf166d436ef6064fa0e8c60bc1af09f10a2106dd26fd17ef66367418ee64022cac1a577dc6 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620ba1fca4afa765a2780fb147aa13b6d7b18affcd22b4f5d2e75af94222adbda30add63ed4593dcbabcd835ea311f3069 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe354500041b1c97654caa094d820fb46b874d2ca25a3e44c99fbbe45ba0f5afad6982a1f589c528d857167b9ebb2e6b42de8f4b 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280ecf7b78dda0ca1625fbfd9cada5351ba3bd300c4f3643cc0d51bf1289c00256f35905f46c6e6e96857169d3f2b8d72f 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf10a822dc5de36b9396424657f0aa07601c5fc613dd00d7b12d9efeb2619d10fdd40c856fb23450ba4000ef73f1f3a5b0 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- neg).out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- neg).out new file mode 100644 index 000000000000..f1399c0d1dd7 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- neg).out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb813fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed0d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d904c892a52f7e4019610602d25200f8abc6d63b92a41e277858fdebde92b158045788a9721ebc3281749cb31a61b37cb10fb1f9796f2da579d6d98a2586f9dfb54c6eb3ef431d4dd13a95148bcf9da43be5e9c6c5c2358096b912d12c9c99b2de}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae47000061a18b3c1f7df46d06cc5028122f643d2597e3eac79531ff7900340df197e5f275958f4e3f32f9b6eb6e12f1fd7554504ecf2c868411032de16f54899cb4f00be27d3a1c34cbf4d774a539eca119233abc7d699bb9b57f4937ea4be707c7064}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d53097c2f7229e4a233d710de9342964f4c2212e4254bb0ea247123fa770a0c590f01947724608215615a9bc7053450e5800b30bd7bee89ae787756f49f163768ca9cec91b66da79fe324497af657d2434f42a38ed6ea27ea02d49541dc96c10b5b}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400ae8267265fec8d3bc9881aef2a50c6314ada633a748ff1fe4f50c115ac27e61b3f08a06138d4475a93f2f7596cc03ad00c7afd9d32055b0aa61a56ba94801d6d6e0f58743a2db627a3830fefb6003bfc4ea2b17dbf127f9a12ada5ea3a93bd1}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa52104bb1a188a359f1b3ef4b4c4173cd436268b048c2f6a8518a801c996de02891b4195d8bc28a6ab9c8977d19f3496fea16051fa21d3ddf3b30180a33963082865a4e09daae932d59eb966d09aeadc33724c5e17f2f396bda4e373c3329c34d49}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c111608110afbebdf04c1b030a2726132bc723bfe3946e00fcbab3d503b32d3f8be2565704347b52ffac5d2d95701238c1206ae177310b7f5e46f71bdb596153753366abc6ec100acb9e30708abeaa5eafd1356157082e9327d146cb42121fea604f359}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce181a2de2aa5d34e068002517d77c5d882ad965fa9857b8b21220ff0b61e8b1e2eccf7fb364f7348759af46e771b592780ef5b6782d2ca8644b36e422b92b4c9431952936228d532fb984905efc871b3eb68904869a4f525a9e73a3df577dc535}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c2478164a61644f8fe7544935ead55e43f8274e193a1a3bc97eae15e861d1918e5e3f9145949233d617ad76598fb3c396912f102cc36be4d1f2361bc00187301efac15a7168ae334c40595f0d6e50e540ceafd9aab613571452f6c6902311cec502b8}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce69006f59f72ae1bd4b7b12f6eb03b202c86a1923243cd9fe36bf93054ac242eeb2ce28cfd793022d1c2825626c66bf23c7f05b745411343699455f40f0bd449b956109552cf1af704a3cbf79442e76601c418df5cb047ab9f7e99559e01260ddcd6}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0feecaff571f244f2e07dcf17d5433b594792676aa63cd4a85ea213c35a74af2ef40f27981896eedce365dec4c43504211d4dc6970368ad273601d4a60b2af556bbce2d8d9ff5eab730ff179a2082595d0bbec9d04e26d878e5eed2631309a9f}' +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- pos).out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- pos).out new file mode 100644 index 000000000000..98d925d1c287 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- pairing_check(pos- pos).out @@ -0,0 +1,1296 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1261406f7867f145efcfbf91a156d0f97fd489fbc6fc739d1006947ea0407801ddfbf451d5e6cd8c00540fa63afce7d709169febf275520034f038fe8142fe9d7a01cdcb3a28294acf7736a6feac00d4a71904495b46b047fee754c9bf2363ab 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x076d3b38b48759b0c38e4c49204f1b74b625f98257387308319636aaf01206aab51a37fa3c39080f25e333accff821500cb8cdf8f111299e7f7c2a53c231fac8d3fdd607076b78fa1ebea9bdb197e90fc9b972c47a7c7e69778521a16011dd87 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x05787fa85a0fee21b15083360acd358eb814743fd7d7e2bb961728c8896024d69c5bf517032f1df299a5ca43507a29e30cb991bd7b6636bdb6a3808973359f44681e94bab05d2f12c160f2da6bbd1dddb2ff4da601002bd79b2392cd65b2ffa9 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0338b37a92607a45711425e7ef58cdd202803fdc40f1ebaa3ff49ee7a0b7da9e33e700a0d737416257daa0c1baf8907713400d8bc5beecb6966c8c8e9c0bc00c65b282b2a0b5c2a599de848beac6cab2675ff9b2172b7bfd778b1c22aeacdbd4 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x15f3268289babb75d5dd0a4163ba96c5b564daa3e50b0b0aa6d7461114f62e1420fc38f832341811c7dcdda21c28570210fbb032364514e30661459552a4e81a81f5af855e0eaee3f5c5544a5c7301f416018112b2a29d40770a4390666ebd89 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x06c22184e04091e42352a14652a3672b9b5a46d8383f7e905e45065ed8ed2ed1b8d7f4691934ef8d1fd0551d76ac56da0372466f84edb965debef3e72cde69686e70fbe40abf06fdb826e196d5aa18fd219410987adfe71155fcd353e5a82ce5 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1112dab3a6686a4414b3b787c6ab334dcc779d9d7c016e03e3b33dc884a4d4d88b4ea788694219395c77b3e753213a620e5f154589d880f7d30bf66e9937f5ffb2ec4bb7d0d01cec7fd5d95ed403388113ce9c116bc02344fd26ca15cee07a42 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x148fbde315967a1372f1ec37e8d2c8060ee8f5bc2a46c7dc7524e7754354dcfd317bfff62b8e774e9ef7f7fbbe35450015e5f552d4333c90fd999801d7c45faac21d0d4029e556db0b8fdcf14947738229223ad5d8fce9841b43d194bd211b60 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x0c72c61e5a186398ec4683ff2df510f74570c02f66e4d5d47a735f7655e1a7d4a9b7436368d37133aab44cbbf5f001280b3196715bdf1c84251faa1995a677bbc0ba1b78a44ecef359df138e6cf0f3cd2b52fa0a44e59169348d962c0d46d37c 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x166f76ccdba2865ca5e3cfb6dfa3885edae19b5a0d749c8e94ad0deeb33a5149b1e7325f36bd9708cf7df5d1762a2e2f12fd8534db56b1f90e7b135fe82c8351d85af2f8e8b2d5ca395572965c596169fd5c6824ac1c2e983ab9645d4855a3d915387f450a01a680ea15a4e3f14ab42b9da10ff24f66eb470e32e6c263ff9e1fc723568c9297cd7e45624ce59e4c2dfa0a4f1870ca52412074421d90bc51cd2218089795b067c4ee2c9bbe15271351e838c23938ef1e7f6900ec2ed36365f7cd}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0423dd6f6dda9ba5209c9ef7f5aa04fa7d779f54b9da16bdff836ce906f09992f45539671c033314a7d41a3ce6c13dca0ab9812e89f6783b62a92ac2c87513dc101e0e2d03488221f48b5bea319d7156b3826aaa46831148ef618fa16ae4700013e6f936778807537aaee2b3c228b693921dcd46470bbf9f6fa0cf60179777c4f752a709cd60d0644b481ed0e028556615141f21d13ed6676d04b26da9805dd6a64f77e330385371efe67f022c9f63f072e42964f5b8a80b26805b418f833a47}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x14e7c39d87b5524990a5c1498f8835f916fff76c4235d0c90c2a83ee5fadcfa0da3e9abed31596a82ac20245f5fd6c42050a789aa6b62b09d01fbc0a1c7f72e1af1f40f0905cea56fc7e6612224164fc66dbd1329c565d829d3676a616437d531084e2780f9b4466740ac92300b55d8b4264675fa7d4289af60cd829eca49d151d1788da50d1ea9e5f6338facbaec52b0ed0546e4af63821d3c4b3172d14440cc78ab9ce85dd72dc42e757aa9edeb2d4dc087127c72c15fce569be23693e9f50}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x00e076d4f8fb121bbad0cf0aabccc381cd6af57ed52a084d6de8839244c8fd41c9e9e755bd5085e623cd1312b9eaa2e10b9ba2a34a6d627241e1bf0fd5bf16a9d80b92b079d7a7f540fc7229fd4ed753edb7e1d559a908dc9c614c6b445ce3400f18eb77d3811dc68e83260750a6a0744fc9a5514c3c139f823bc68f9bee77c26abb75f89dc6bb8a10bfd08a6933a6fe19396210665f90e9a0ba024a9a03ab008d9655fdafe2375cecf8a1a1fb50f26459c1d4e6d562d80618d425a15c566eda}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x08ece632050f4beef7be5f050d2d0dbbc80cf77dab7aa74931566cae5edcf551d4f49b9dc153f6f91bfcc5921f66e8e70fc99ecb955eae4bc78c8e498ead8d1bfd8e27796173ebf47e7751e62471ccafd0c178a1998be576c5155e8631befa5209b56048b0dc8ca8972c5c6a01d7df94020e9b3c308e6a6ddcb0b60788d0cd926a92a272eec99545f16782e60cb63ac103fbf2481c42075f1b039d82ad1b2a510a2941aa44f1e5657b9a6597480332ecf9e61e7f821a94256bc7c3ccd63c5d62}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x109a07058b74f8ac430d3971db89e3c157ba5f767b7ad5c1d8997d4f5d9b8a83869c7769283e4393b60252ce2752d1330e2d6ce8ff93cc432ad2e26fa09f86c35bffaf416ed9b7ac4734329d38930ae96310bfe466eab1d4bb7a59bd7c11160808f615fe5a7b24ea1a793555108f3a9b663e04a4e3b9678216f59fccfdf2d0beae68b84981593a2ce0a7fedc73eda3fd028e0132439b77288d6611a10bf8766ca8088a8446cb2fb85e84e7fb0bb3e2ce093b7d157ed6eb9305ddde0159fab752}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x0eb5349b1cc220b50c42ea66f08c2bc59b2bc4810cb8025883f980ac26a0c4d263e6ce53b17f6c5e81a621a329fb306c144974fea8b32f5074e2922a6652236548eba95a93f51f718acfb45c6009b6ce7821ecef3f5591c7d2a08f8b827b0fce01e6e4078f22b1b9e31b829e6bcf4f4f399de58a5b2d5a0d550fd39594c8444131dc804b4c5ccb78604fb9188e4a18330b0b5b720c533e35ffe4c3938a20604332e2224ed0f7bf8fadac4241fa29dae56822fb781704ada51b8b5c20a881e576}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x1686dfdabbf42256245bcd46e879b83ff1cadc1e98fab4483166f4e971de8ec66190669601ccc37817336827b5c7363510a5f6dce3d7f23cf8f7b8d73557814db44b2331b80820810a8e68c6297924735b3914d93e5a6fb855f43daf455c247803b6b085e9efff4601e5bce0e507b4b0165e116ab7bb9411514870cf652297e48d666b6c7d7de85243a5704c3c69197c09d44e7e54adf4642f5ba62f132cb2160a05e2d6c038d2660823645011702774450149eb5a3fad08f36edcee313aa7f3}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x18d844fded7a6bf849a2b75817a3b5c0e025c76c0743a18e9ce33e94e4bc2ad2d3ccb0b01c439df88953e70a3bcd06710126a5494220db0746a16c8300062ca151670be555ae2a68983a47768a494cf5a1141d211b3b6e6577ced1752a8ce690130b72778b6411e299ec3906082b8050c2e5194125e52f536e007df4d2820af73c1f028581312e3d37a8d939940d6e2c1449cca9263c7d05f52798aa6f01f38153e1f8b5d88e0e1b9b393e5e0f4af46005cca34e69a8608120a961fed9f1cdd5}' +storage + (Some False) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x042efbd6b57af4235a6344a3f2130041815a4fbb44839451667255d958e3e8ba7a1d06fad83af056cf839b77470015bf0958ef0ddb9c7b06b4d9615e52a1a5774817857116843b0e3991d3ee9513e5264a9f7a8eff1faf4579fe108c0e0c04fb 0x04a2dd29ddd4bafbeb5b7c26cf77463d4b6d0e42a7a3ceb1ee4691671033816ad592171e19d648ab899eca7da5e77e7c0089346cf8c7ecddf517f085525bd2f5f75838cc7aaaba59f478a3ce3aa4ca96e1e9ad84b09e0495c614eaa44b6c58cb0a1246eae260c24b1d13cac4c5f77921cffe250e49214574e146b164c109ab312f6b0d852fca9111ebc8a213b3bc5a69082c3580c9495bc7d7bb8a6be298fd81f8ba68ac1985b413f420e12754a8d08e4df01361ac7192782ba012d9cecf100c}' +storage + (Some False) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- signature_aggregation.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- signature_aggregation.out new file mode 100644 index 000000000000..19bd514ce8a1 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- signature_aggregation.out @@ -0,0 +1,180 @@ + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x19d8a1f79d761f07f5849ed60c4d8372c271ebc3b8731e888b4fd3babc15d716e64f3df671f6e9f2a1726ab29431afbf0f1de63aadf3dcc954fd5b58bda50fa8f80655aae55eb1423a97aef6e16cd7d320871359764581e6abfa735aeeda45b6 0x1988b3f37c78bf39ad0000125cdd9de7b5b774b5221d137b9dbe24b7b69f0970feab7aa52e59087b0a427de9bb6deee2190a9857b2ed4c6dcd7e5c18af6a5170ed1d6046cac81c58a6d2ade394b829ff9b8e02580c975307fa744d0747c6e68208975d9efe381be5cd300b76b887d93dba7a1f144f2c7d9714d8a0e4749519a7d4d403d12e88a4aa83859d1025b3b68c152e565a57caea54be81e13f77b4ad73b88d3e5ebe7dd227d6f3c4aa678895b73f15b30407e13732ac60c74b81de9b6e; Pair 0x10463b3743defc3aee6d6596906938450a429285990ef50b41df63889c42bdc5f1c830cd403506db9df9f1254d3f2b1f1043260bd4122e695546b10d07b5e517c0d0e8f5f0c0de13683a4ca42f6001aaae072fb3d529a8792966f2e0d5e45301 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801}' +storage + (Some True) +emitted operations + +big_map diff + + + +./octez-client --mode mockup run script michelson_test_scripts/opcodes/pairing_check.tz on storage None and input '{Pair 0x1273992fd0773410fcadbb55a6914c32c2314d03b4cd0b3da699e0c7b74bab001b4311fdd1bb58630b43b80be3974ca90282f633318822c082c93580febfd5421acd7ce3b0b38fe148c114a0c42ffd6faafb8ab0cff43d6471fc6ff222be6373 0x00ff54c7a2f6b5af235a704dafb1c2e166bdf67c2c6a4e54a9af84349b8676bcb0b1cc1f56f621af67921bbb82fa9806155d6024e64f6d5163ece546259169d2b054acfddfa45a8502b66ecf8582f11b23472b793a84e86599887de4f42cf8360c63251d615a4e7efee27db36d118b5761fe754c3ed3f5439ec6ec3f620378ff15d659ab0f563246cfd023b665daa3f80825788dd115e716fda26f9d55297d720b7bed0f935b254a9e99e0d3d0856421bf0ac3b1ff2bce61f0cdafa0139a7465; Pair 0x0e652b8a10100237ef90db2efe6e3aba6023659ef22d170f55871436fda45a613199fad02bff8a3dfbe00f5c4b7efe590f9287f0ef8c1458a3863459886cccd53cbb4dcb0e724891f667b30835018c8de3bc049a02105a0a55d36808a0e4b5c7 0x0a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a0530f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf30468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899}' +storage + (Some True) +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- test_groth16.out b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- test_groth16.out new file mode 100644 index 000000000000..bc6763804082 --- /dev/null +++ b/tezt/tests/expected/test_contract_bls12_381.ml/Parisc- Bls12_381 contract primitives- test_groth16.out @@ -0,0 +1,9 @@ + +./octez-client --mode mockup run script michelson_test_scripts/mini_scenarios/groth16.tz on storage Unit and input 'Pair (Pair 0xa1bb010000000000000000000000000000000000000000000000000000000000 0x0100000000000000000000000000000000000000000000000000000000000000) (Pair (Pair 0x0a2841423326ab08f5f406409775e43fa0f9a0b97631fa85d2dd9242507d25059e9cf48b8b98f99a0008671423a148ec106d70637056972ef49fb6f62de2e89ba3682b9972292b6bb4e6f53799a75d2f8001ccfde280d8ac05fc209352236cbd 0x0fced939fb1ad733f99669f50a383ef632f6d41dfbde434a6715afd5c7dfbb7bc5835e058ad8b590c7b38dd137d0bd0f0e1540f1b45d8aa626c360e2ea484a116243f7c802034de915db6b18d5303946f676e423cbd6046d37a82208d500625a11c7250ccb953a7ee49d704ad14de4b727733cff7cf06875d8b6444f3c0a8cbf0bd980e539c74bd5b37bb15fe816f23407d269193105fda71adf35fae9309d9d46729fcd4685699097a86f0460a2bc8b16293940cabfdcfe0f27e4107e74e90c) 0x0a1fb5a144ca3bdfe4ad0f183cf71dd7fdd28cbef4fcd47b5b419f65186703f62ecaaa1255fa21a6ebdd917ab1f9bd9707de7066865e2ff3875e22088619125a0d4088a622ab42224425ef89a5a149ce2db9c8292b62c7e7aaa7e87f3535304b)' +storage + Unit +emitted operations + +big_map diff + + diff --git a/tezt/tests/expected/ticket_receipt_and_rpc.ml/Paris- Ticket updates in receipt.out b/tezt/tests/expected/ticket_receipt_and_rpc.ml/Parisb- Ticket updates in receipt.out similarity index 100% rename from tezt/tests/expected/ticket_receipt_and_rpc.ml/Paris- Ticket updates in receipt.out rename to tezt/tests/expected/ticket_receipt_and_rpc.ml/Parisb- Ticket updates in receipt.out diff --git a/tezt/tests/expected/ticket_receipt_and_rpc.ml/Parisc- Ticket updates in receipt.out b/tezt/tests/expected/ticket_receipt_and_rpc.ml/Parisc- Ticket updates in receipt.out new file mode 100644 index 000000000000..3e1bc9c2e94a --- /dev/null +++ b/tezt/tests/expected/ticket_receipt_and_rpc.ml/Parisc- Ticket updates in receipt.out @@ -0,0 +1,153 @@ + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --arg '(Pair "[CONTRACT_HASH]" "[CONTRACT_HASH]")' +Node is bootstrapped. +Estimated gas: 7899.569 units (will add 100 for safety) +Estimated storage: 475 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.001138 + Expected counter: 1 + Gas limit: 8000 + Storage limit: 495 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.001138 + payload fees(the block proposer) ....... +ꜩ0.001138 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[CONTRACT_HASH]" "[CONTRACT_HASH]") + This transaction was successfully applied + Updated storage: + { Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "red" 1) ; + Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "green" 1) ; + Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "green" 1) } + Storage size: 525 bytes + Paid storage size diff: 325 bytes + Consumed gas: 3193.024 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.08125 + storage fees ........................... +ꜩ0.08125 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "red" + Account updates: + [CONTRACT_HASH] ... +1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "green" + Account updates: + [CONTRACT_HASH] ... +2 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair (Pair (Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "blue" 1)) + (Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "blue" 1))) + 0x0192ce5ac8f542c49e64c7b6c73c445515ddc20f9400) + This transaction was successfully applied + Updated storage: + (Some (Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "blue" 1))) + Storage size: 169 bytes + Paid storage size diff: 108 bytes + Consumed gas: 2818.019 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.027 + storage fees ........................... +ꜩ0.027 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "blue" + Account updates: + [CONTRACT_HASH] ... +1 + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "blue" 1)) + This transaction was successfully applied + Updated storage: + (Some (Pair 0x01c97ff8e547ecb335bdf832511361d68e928c6ec300 (Pair "blue" 1))) + Storage size: 88 bytes + Paid storage size diff: 42 bytes + Consumed gas: 1889.697 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0105 + storage fees ........................... +ꜩ0.0105 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "blue" + Account updates: + [CONTRACT_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"red"' +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"green"' +2 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"blue"' +0 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"blue"' +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"blue"' +1 + +./octez-client --mode mockup rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/all_ticket_balances' +[ { "ticketer": "[CONTRACT_HASH]", + "content_type": { "prim": "string" }, "content": { "string": "red" }, + "amount": "1" }, + { "ticketer": "[CONTRACT_HASH]", + "content_type": { "prim": "string" }, "content": { "string": "green" }, + "amount": "2" } ] + +./octez-client --mode mockup get all ticket balances for '[CONTRACT_HASH]' +Ticketer: [CONTRACT_HASH] +Content type: string +Content: "red" +Amount: 1 + +Ticketer: [CONTRACT_HASH] +Content type: string +Content: "green" +Amount: 2 + +./octez-client --mode mockup rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/all_ticket_balances' +[ { "ticketer": "[CONTRACT_HASH]", + "content_type": { "prim": "string" }, "content": { "string": "blue" }, + "amount": "1" } ] + +./octez-client --mode mockup get all ticket balances for '[CONTRACT_HASH]' +Ticketer: [CONTRACT_HASH] +Content type: string +Content: "blue" +Amount: 1 + +./octez-client --mode mockup rpc get '/chains/main/blocks/head/context/contracts/[CONTRACT_HASH]/all_ticket_balances' +[ { "ticketer": "[CONTRACT_HASH]", + "content_type": { "prim": "string" }, "content": { "string": "blue" }, + "amount": "1" } ] + +./octez-client --mode mockup get all ticket balances for '[CONTRACT_HASH]' +Ticketer: [CONTRACT_HASH] +Content type: string +Content: "blue" +Amount: 1 + +./octez-client --mode mockup rpc get '/chains/main/blocks/head/context/contracts/[PUBLIC_KEY_HASH]/all_ticket_balances' +Fatal error: + No service found at this URL + diff --git a/tezt/tests/expected/tickets.ml/Paris- Create and remove tickets.out b/tezt/tests/expected/tickets.ml/Parisb- Create and remove tickets.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Create and remove tickets.out rename to tezt/tests/expected/tickets.ml/Parisb- Create and remove tickets.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Minting then sending tickets to smart-contract rollup should succeed with.out b/tezt/tests/expected/tickets.ml/Parisb- Minting then sending tickets to smart-contract rollup should succeed wit.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Minting then sending tickets to smart-contract rollup should succeed with.out rename to tezt/tests/expected/tickets.ml/Parisb- Minting then sending tickets to smart-contract rollup should succeed wit.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Overdrafting ticket from implicit accounts must be rejected.out b/tezt/tests/expected/tickets.ml/Parisb- Overdrafting ticket from implicit accounts must be rejected.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Overdrafting ticket from implicit accounts must be rejected.out rename to tezt/tests/expected/tickets.ml/Parisb- Overdrafting ticket from implicit accounts must be rejected.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets between originated contracts and implicit accounts.out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets between originated contracts and implicit accounts.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets between originated contracts and implicit accounts.out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets between originated contracts and implicit accounts.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets from contracts to implicit accounts with some Tez along.out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets from contracts to implicit accounts with some Tez along.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets from contracts to implicit accounts with some Tez along.out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets from contracts to implicit accounts with some Tez along.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets from contracts to implicit accounts with the wrong type must.out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets from contracts to implicit accounts with the wrong type mus.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets from contracts to implicit accounts with the wrong type must.out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets from contracts to implicit accounts with the wrong type mus.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets from contracts to implicit accounts.out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets from contracts to implicit accounts.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets from contracts to implicit accounts.out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets from contracts to implicit accounts.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets in bigmap.out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets in bigmap.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets in bigmap.out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets in bigmap.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets with Ticket constructor (with complex parameters) from impli.out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets with Ticket constructor (with complex parameters) from impl.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets with Ticket constructor (with complex parameters) from impli.out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets with Ticket constructor (with complex parameters) from impl.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Send tickets with Ticket constructor from implicit account to originated .out b/tezt/tests/expected/tickets.ml/Parisb- Send tickets with Ticket constructor from implicit account to originated.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Send tickets with Ticket constructor from implicit account to originated .out rename to tezt/tests/expected/tickets.ml/Parisb- Send tickets with Ticket constructor from implicit account to originated.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Sending ticket from contract storage to implicit accounts.out b/tezt/tests/expected/tickets.ml/Parisb- Sending ticket from contract storage to implicit accounts.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Sending ticket from contract storage to implicit accounts.out rename to tezt/tests/expected/tickets.ml/Parisb- Sending ticket from contract storage to implicit accounts.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Sending ticket of wrong type from implicit accounts must be rejected.out b/tezt/tests/expected/tickets.ml/Parisb- Sending ticket of wrong type from implicit accounts must be rejected.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Sending ticket of wrong type from implicit accounts must be rejected.out rename to tezt/tests/expected/tickets.ml/Parisb- Sending ticket of wrong type from implicit accounts must be rejected.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Sending tickets from storage to smart-contract rollup should succeed with.out b/tezt/tests/expected/tickets.ml/Parisb- Sending tickets from storage to smart-contract rollup should succeed wit.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Sending tickets from storage to smart-contract rollup should succeed with.out rename to tezt/tests/expected/tickets.ml/Parisb- Sending tickets from storage to smart-contract rollup should succeed wit.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Sending tickets to either implicit accounts or originated contracts accep.out b/tezt/tests/expected/tickets.ml/Parisb- Sending tickets to either implicit accounts or originated contracts acce.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Sending tickets to either implicit accounts or originated contracts accep.out rename to tezt/tests/expected/tickets.ml/Parisb- Sending tickets to either implicit accounts or originated contracts acce.out diff --git a/tezt/tests/expected/tickets.ml/Paris- Sending zero ticket from implicit accounts must be rejected.out b/tezt/tests/expected/tickets.ml/Parisb- Sending zero ticket from implicit accounts must be rejected.out similarity index 100% rename from tezt/tests/expected/tickets.ml/Paris- Sending zero ticket from implicit accounts must be rejected.out rename to tezt/tests/expected/tickets.ml/Parisb- Sending zero ticket from implicit accounts must be rejected.out diff --git a/tezt/tests/expected/tickets.ml/Parisc- Create and remove tickets.out b/tezt/tests/expected/tickets.ml/Parisc- Create and remove tickets.out new file mode 100644 index 000000000000..fb805354308b --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Create and remove tickets.out @@ -0,0 +1,220 @@ + +./octez-client --mode mockup --wait none originate contract add_clear_tickets transferring 200 from bootstrap1 running michelson_test_scripts/mini_scenarios/add_clear_tickets_015.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 610.029 units (will add 100 for safety) +Estimated storage: 398 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000443 + Expected counter: 1 + Gas limit: 711 + Storage limit: 418 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000443 + payload fees(the block proposer) ....... +ꜩ0.000443 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ200 + Script: + { parameter (or (pair %add nat string) (unit %clear)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { UNPAIR ; + DIG 2 ; + SWAP ; + DIG 2 ; + TICKET ; + ASSERT_SOME ; + CONS ; + NIL operation ; + PAIR } + { DROP 2 ; NIL (ticket string) ; NIL operation ; PAIR } } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 141 bytes + Paid storage size diff: 141 bytes + Consumed gas: 609.995 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.03525 + storage fees ........................... +ꜩ0.03525 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ200 + [CONTRACT_HASH] ... +ꜩ200 + +New contract [CONTRACT_HASH] originated. +Contract memorized as add_clear_tickets. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --entrypoint add --arg 'Pair 1 "A"' +Node is bootstrapped. +Estimated gas: 1751.651 units (will add 100 for safety) +Estimated storage: 105 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000453 + Expected counter: 1 + Gas limit: 1852 + Storage limit: 125 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000453 + payload fees(the block proposer) ....... +ꜩ0.000453 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: add + Parameter: (Pair 1 "A") + This transaction was successfully applied + Updated storage: + { Pair 0x01435e1f410af86271d7c8c3c98a8708157a45269200 (Pair "A" 1) } + Storage size: 180 bytes + Paid storage size diff: 105 bytes + Consumed gas: 1752.186 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.02625 + storage fees ........................... +ꜩ0.02625 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "A" + Account updates: + [CONTRACT_HASH] ... +1 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --entrypoint clear --arg Unit +Node is bootstrapped. +Estimated gas: 1941.323 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000466 + Expected counter: 2 + Gas limit: 2042 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000466 + payload fees(the block proposer) ....... +ꜩ0.000466 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: clear + This transaction was successfully applied + Updated storage: {} + Storage size: 141 bytes + Consumed gas: 1941.859 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "A" + Account updates: + [CONTRACT_HASH] ... -1 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --entrypoint add --arg 'Pair 1 "B"' +Node is bootstrapped. +Estimated gas: 1751.651 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000453 + Expected counter: 3 + Gas limit: 1852 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000453 + payload fees(the block proposer) ....... +ꜩ0.000453 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: add + Parameter: (Pair 1 "B") + This transaction was successfully applied + Updated storage: + { Pair 0x01435e1f410af86271d7c8c3c98a8708157a45269200 (Pair "B" 1) } + Storage size: 180 bytes + Consumed gas: 1752.186 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "B" + Account updates: + [CONTRACT_HASH] ... +1 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 2 --entrypoint add --arg 'Pair 1 "C"' +Node is bootstrapped. +Estimated gas: 2433.661 units (will add 100 for safety) +Estimated storage: 105 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000521 + Expected counter: 4 + Gas limit: 2534 + Storage limit: 125 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000521 + payload fees(the block proposer) ....... +ꜩ0.000521 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: add + Parameter: (Pair 1 "C") + This transaction was successfully applied + Updated storage: + { Pair 0x01435e1f410af86271d7c8c3c98a8708157a45269200 (Pair "C" 1) ; + Pair 0x01435e1f410af86271d7c8c3c98a8708157a45269200 (Pair "B" 1) } + Storage size: 219 bytes + Paid storage size diff: 105 bytes + Consumed gas: 2434.196 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.02625 + storage fees ........................... +ꜩ0.02625 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "C" + Account updates: + [CONTRACT_HASH] ... +1 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Minting then sending tickets to smart-contract rollup should succeed wit.out b/tezt/tests/expected/tickets.ml/Parisc- Minting then sending tickets to smart-contract rollup should succeed wit.out new file mode 100644 index 000000000000..0b5df1b13f4a --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Minting then sending tickets to smart-contract rollup should succeed wit.out @@ -0,0 +1,55 @@ + +./octez-client --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[SMART_ROLLUP_HASH]"' +Node is bootstrapped. +Estimated gas: 2784.256 units (will add 100 for safety) +Estimated storage: 132 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000584 + Expected counter: 3 + Gas limit: 2885 + Storage limit: 152 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000584 + payload fees(the block proposer) ....... +ꜩ0.000584 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[SMART_ROLLUP_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 197 bytes + Paid storage size diff: 132 bytes + Consumed gas: 2674.291 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.033 + storage fees ........................... +ꜩ0.033 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [SMART_ROLLUP_HASH] + Parameter: { Pair 0x01f6719dc3bd86b5c531d6551553c467a31a54717800 (Pair "Ticket2" 1) ; + Pair 0x01f6719dc3bd86b5c531d6551553c467a31a54717800 (Pair "Ticket" 1) } + This transaction was successfully applied + Consumed gas: 109.932 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [SMART_ROLLUP_HASH] ... +1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket2" + Account updates: + [SMART_ROLLUP_HASH] ... +1 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Overdrafting ticket from implicit accounts must be rejected.out b/tezt/tests/expected/tickets.ml/Parisc- Overdrafting ticket from implicit accounts must be rejected.out new file mode 100644 index 000000000000..fbda5ce5a18b --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Overdrafting ticket from implicit accounts must be rejected.out @@ -0,0 +1,210 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 1' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 2 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup --wait none transfer 2 tickets from bootstrap1 to bootstrap2 with entrypoint default and contents '"Ticket"' and type string and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 3 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transfer tickets: + Ticket content: "Ticket" + Ticket content type: string + Ticket ticketer: [CONTRACT_HASH] + Ticket amount: 2 + Destination: [PUBLIC_KEY_HASH] + From: [PUBLIC_KEY_HASH] + This operation FAILED. + +Error: + Attempted to set negative ticket balance value '-1' for key exprubCTZXvJKqgSzwRfVHM3SJSU8MUFST8FnrYTxTLwn8F9oGyh8P. + +./octez-client --mode mockup --wait none originate contract tickets_bag transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_bag_016.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 620.183 units (will add 100 for safety) +Estimated storage: 451 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 3 + Gas limit: 721 + Storage limit: 471 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (or (ticket %save string) (address %send)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { CONS ; NIL operation ; PAIR } + { SWAP ; + IF_CONS + { DIG 2 ; + CONTRACT %ticket (ticket string) ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } + { PUSH string "no ticket to send" ; FAILWITH } } } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 194 bytes + Paid storage size diff: 194 bytes + Consumed gas: 620.150 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0485 + storage fees ........................... +ꜩ0.0485 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_bag. + +./octez-client --mode mockup --wait none transfer 2 tickets from bootstrap1 to '[CONTRACT_HASH]' with entrypoint save and contents '"Ticket"' and type string and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 4 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transfer tickets: + Ticket content: "Ticket" + Ticket content type: string + Ticket ticketer: [CONTRACT_HASH] + Ticket amount: 2 + Destination: [CONTRACT_HASH] + Entrypoint: save + From: [PUBLIC_KEY_HASH] + This operation FAILED. + +Error: + Attempted to set negative ticket balance value '-1' for key exprubCTZXvJKqgSzwRfVHM3SJSU8MUFST8FnrYTxTLwn8F9oGyh8P. diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets between originated contracts and implicit accounts.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets between originated contracts and implicit accounts.out new file mode 100644 index 000000000000..6b8e235c5ded --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets between originated contracts and implicit accounts.out @@ -0,0 +1,387 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none originate contract tickets_bag transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_bag_016.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 620.183 units (will add 100 for safety) +Estimated storage: 451 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 2 + Gas limit: 721 + Storage limit: 471 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (or (ticket %save string) (address %send)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { CONS ; NIL operation ; PAIR } + { SWAP ; + IF_CONS + { DIG 2 ; + CONTRACT %ticket (ticket string) ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } + { PUSH string "no ticket to send" ; FAILWITH } } } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 194 bytes + Paid storage size diff: 194 bytes + Consumed gas: 620.150 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0485 + storage fees ........................... +ꜩ0.0485 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_bag. + +./octez-client --mode mockup --wait none originate contract tickets_blackhole transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_blackhole_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 579.704 units (will add 100 for safety) +Estimated storage: 308 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000346 + Expected counter: 3 + Gas limit: 680 + Storage limit: 328 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000346 + payload fees(the block proposer) ....... +ꜩ0.000346 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (ticket %ticket string) ; + storage unit ; + code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 51 bytes + Paid storage size diff: 51 bytes + Consumed gas: 579.671 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01275 + storage fees ........................... +ꜩ0.01275 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_blackhole. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 3' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 4 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 3) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 3)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +3 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +3 + +./octez-client --mode mockup --wait none transfer 2 tickets from bootstrap1 to bootstrap2 with entrypoint default and contents '"Ticket"' and type string and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 1295.155 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000441 + Expected counter: 5 + Gas limit: 1396 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000441 + payload fees(the block proposer) ....... +ꜩ0.000441 + Transfer tickets: + Ticket content: "Ticket" + Ticket content type: string + Ticket ticketer: [CONTRACT_HASH] + Ticket amount: 2 + Destination: [PUBLIC_KEY_HASH] + From: [PUBLIC_KEY_HASH] + This tickets transfer was successfully applied + Paid storage size diff: 66 bytes + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... -2 + [PUBLIC_KEY_HASH] ... +2 + Consumed gas: 1295.089 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup get ticket balance for bootstrap2 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +2 + +./octez-client --mode mockup --wait none transfer 1 tickets from bootstrap2 to '[CONTRACT_HASH]' with entrypoint save and contents '"Ticket"' and type string and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 3206.843 units (will add 100 for safety) +Estimated storage: 110 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00063 + Expected counter: 1 + Gas limit: 3307 + Storage limit: 130 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00063 + payload fees(the block proposer) ....... +ꜩ0.00063 + Transfer tickets: + Ticket content: "Ticket" + Ticket content type: string + Ticket ticketer: [CONTRACT_HASH] + Ticket amount: 1 + Destination: [CONTRACT_HASH] + Entrypoint: save + From: [PUBLIC_KEY_HASH] + This tickets transfer was successfully applied + Paid storage size diff: 66 bytes + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... -1 + Consumed gas: 1296.552 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: save + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Updated storage: + { Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1) } + Storage size: 238 bytes + Paid storage size diff: 44 bytes + Consumed gas: 1910.859 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.011 + storage fees ........................... +ꜩ0.011 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap2 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --entrypoint send --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 4716.890 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000781 + Expected counter: 6 + Gas limit: 4817 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000781 + payload fees(the block proposer) ....... +ꜩ0.000781 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: send + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: {} + Storage size: 194 bytes + Consumed gas: 2864.303 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... -1 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Entrypoint: ticket + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Updated storage: Unit + Storage size: 51 bytes + Consumed gas: 1853.638 + + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +0 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +0 diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with some Tez along.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with some Tez along.out new file mode 100644 index 000000000000..ae7d4d6f731b --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with some Tez along.out @@ -0,0 +1,115 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send_with_tez transferring 1 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_with_tez_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 612.418 units (will add 100 for safety) +Estimated storage: 411 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000455 + Expected counter: 1 + Gas limit: 713 + Storage limit: 431 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000455 + payload fees(the block proposer) ....... +ꜩ0.000455 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ1 + Script: + { parameter address ; + storage unit ; + code { CAR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 1 ; + PUSH nat 1 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 154 bytes + Paid storage size diff: 154 bytes + Consumed gas: 612.385 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0385 + storage fees ........................... +ꜩ0.0385 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send_with_tez. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[PUBLIC_KEY_HASH]"' +Node is bootstrapped. +Estimated gas: 1857.132 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00049 + Expected counter: 2 + Gas limit: 1958 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00049 + payload fees(the block proposer) ....... +ꜩ0.00049 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[PUBLIC_KEY_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 154 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1757.270 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0.000001 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x017c8454eff9ad796cd8baba365d2592ad1b60efb100 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Balance updates: + [CONTRACT_HASH] ... -ꜩ0.000001 + [PUBLIC_KEY_HASH] ... +ꜩ0.000001 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with the wrong type mus.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with the wrong type mus.out new file mode 100644 index 000000000000..5d919fc8d60f --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts with the wrong type mus.out @@ -0,0 +1,195 @@ + +./octez-client --mode mockup --wait none originate contract send_ticket_list transferring 1 from bootstrap1 running michelson_test_scripts/mini_scenarios/send_ticket_list_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.205 units (will add 100 for safety) +Estimated storage: 402 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000446 + Expected counter: 1 + Gas limit: 715 + Storage limit: 422 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000446 + payload fees(the block proposer) ....... +ꜩ0.000446 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ1 + Script: + { parameter address ; + storage unit ; + code { CAR ; + CONTRACT (list (ticket string)) ; + ASSERT_SOME ; + PUSH mutez 0 ; + NIL (ticket string) ; + PUSH nat 1 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + CONS ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + UNIT ; + SWAP ; + PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 145 bytes + Paid storage size diff: 145 bytes + Consumed gas: 614.172 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.03625 + storage fees ........................... +ꜩ0.03625 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + +New contract [CONTRACT_HASH] originated. +Contract memorized as send_ticket_list. + +./octez-client --mode mockup --wait none originate contract tickets_list_blackhole transferring 1 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_list_blackhole_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 579.433 units (will add 100 for safety) +Estimated storage: 299 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000339 + Expected counter: 2 + Gas limit: 680 + Storage limit: 319 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000339 + payload fees(the block proposer) ....... +ꜩ0.000339 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ1 + Script: + { parameter (list (ticket string)) ; + storage unit ; + code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 42 bytes + Paid storage size diff: 42 bytes + Consumed gas: 579.400 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0105 + storage fees ........................... +ꜩ0.0105 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_list_blackhole. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 4063.855 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000711 + Expected counter: 3 + Gas limit: 4164 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000711 + payload fees(the block proposer) ....... +ꜩ0.000711 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Storage size: 145 bytes + Paid storage size diff: 66 bytes + Consumed gas: 2211.251 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: { Pair 0x011213b3979289bef70dc1d1a4fb7574f306bf7f2400 (Pair "Ticket" 1) } + This transaction was successfully applied + Updated storage: Unit + Storage size: 42 bytes + Consumed gas: 1853.656 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[PUBLIC_KEY_HASH]"' +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 4 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[PUBLIC_KEY_HASH]" + This operation FAILED. + +Runtime error in contract [CONTRACT_HASH]: + 01: { parameter address ; + 02: storage unit ; + 03: code { CAR ; + 04: CONTRACT (list (ticket string)) ; + 05: ASSERT_SOME ; + 06: PUSH mutez 0 ; + 07: NIL (ticket string) ; + 08: PUSH nat 1 ; + 09: PUSH string "Ticket" ; + 10: TICKET ; + 11: ASSERT_SOME ; + 12: CONS ; + 13: TRANSFER_TOKENS ; + 14: NIL operation ; + 15: SWAP ; + 16: CONS ; + 17: UNIT ; + 18: SWAP ; + 19: PAIR } } +At line 5 characters 9 to 20, +script reached FAILWITH instruction +with Unit +Fatal error: + transfer simulation failed diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts.out new file mode 100644 index 000000000000..4c081c37cc6d --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets from contracts to implicit accounts.out @@ -0,0 +1,111 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 1' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 2 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets in bigmap.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets in bigmap.out new file mode 100644 index 000000000000..74ef597a6ef7 --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets in bigmap.out @@ -0,0 +1,296 @@ + +./octez-client --mode mockup --wait none originate contract receive_tickets_in_big_map transferring 200 from bootstrap1 running michelson_test_scripts/mini_scenarios/receive_tickets_in_big_map.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 582.883 units (will add 100 for safety) +Estimated storage: 340 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000352 + Expected counter: 1 + Gas limit: 683 + Storage limit: 360 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000352 + payload fees(the block proposer) ....... +ꜩ0.000352 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ200 + Script: + { parameter (big_map int (ticket string)) ; + storage (big_map int (ticket string)) ; + code { CAR ; NIL operation ; PAIR } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 83 bytes + Updated big_maps: + New map(4) of type (big_map int (ticket string)) + Paid storage size diff: 83 bytes + Consumed gas: 582.849 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.02075 + storage fees ........................... +ꜩ0.02075 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ200 + [CONTRACT_HASH] ... +ꜩ200 + +New contract [CONTRACT_HASH] originated. +Contract memorized as receive_tickets_in_big_map. + +./octez-client --mode mockup --wait none originate contract send_tickets_in_big_map transferring 200 from bootstrap1 running michelson_test_scripts/mini_scenarios/send_tickets_in_big_map_015.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 674.694 units (will add 100 for safety) +Estimated storage: 577 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000628 + Expected counter: 2 + Gas limit: 775 + Storage limit: 597 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000628 + payload fees(the block proposer) ....... +ꜩ0.000628 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ200 + Script: + { parameter address ; + storage unit ; + code { CAR ; + CONTRACT (big_map int (ticket string)) ; + IF_NONE + { PUSH string "Contract of type `big_map(ticket(string))` not found" ; + FAILWITH } + { EMPTY_BIG_MAP int (ticket string) ; + PUSH int 100 ; + SWAP ; + PAIR ; + LEFT (big_map int (ticket string)) ; + LOOP_LEFT + { UNPAIR ; + SWAP ; + DUP ; + DUG 2 ; + PUSH int 0 ; + COMPARE ; + LT ; + IF { PUSH int 1 ; + DUP 3 ; + SUB ; + SWAP ; + PUSH nat 1 ; + PUSH string "BLUE" ; + TICKET ; + ASSERT_SOME ; + DIG 3 ; + SWAP ; + SOME ; + SWAP ; + UPDATE ; + PAIR ; + LEFT (big_map int (ticket string)) } + { SWAP ; DROP ; RIGHT (pair (big_map int (ticket string)) int) } } ; + SWAP ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 320 bytes + Paid storage size diff: 320 bytes + Consumed gas: 674.661 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.08 + storage fees ........................... +ꜩ0.08 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + [PUBLIC_KEY_HASH] ... -ꜩ200 + [CONTRACT_HASH] ... +ꜩ200 + +New contract [CONTRACT_HASH] originated. +Contract memorized as send_tickets_in_big_map. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap2 to '[CONTRACT_HASH]' --burn-cap 30 --storage-limit 1000000 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 98835.369 units (will add 100 for safety) +Estimated storage: 10767 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.01019 + Expected counter: 1 + Gas limit: 98936 + Storage limit: 10787 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01019 + payload fees(the block proposer) ....... +ꜩ0.01019 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: Unit + Updated big_maps: + New temp(1) of type (big_map int (ticket string)) + Set temp(1)[22] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[48] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[20] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[67] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[30] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[33] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[42] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[13] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[50] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[84] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[44] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[41] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[4] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[73] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[5] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[28] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[19] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[9] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[86] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[76] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[8] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[97] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[80] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[45] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[87] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[1] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[26] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[38] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[65] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[99] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[69] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[2] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[81] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[82] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[64] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[92] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[90] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[98] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[37] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[66] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[32] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[71] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[51] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[56] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[14] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[12] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[85] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[47] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[74] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[18] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[10] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[35] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[96] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[27] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[77] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[62] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[58] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[25] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[94] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[60] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[7] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[53] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[11] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[17] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[83] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[72] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[6] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[88] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[75] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[3] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[70] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[52] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[95] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[68] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[78] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[23] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[79] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[59] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[100] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[24] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[21] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[49] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[93] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[39] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[63] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[55] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[15] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[16] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[31] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[43] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[29] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[54] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[89] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[36] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[46] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[91] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[61] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[34] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[57] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Set temp(1)[40] to (Pair 0x010d30dc625f57274f300abc4af284934bc05fc46c00 (Pair "BLUE" 1)) + Storage size: 320 bytes + Paid storage size diff: 67 bytes + Consumed gas: 49909.937 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01675 + storage fees ........................... +ꜩ0.01675 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: -1 + This transaction was successfully applied + Updated storage: 5 + Updated big_maps: + Clear map(4) + Copy temp(1) to map(5) + Storage size: 10783 bytes + Paid storage size diff: 10700 bytes + Consumed gas: 48926.421 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ2.675 + storage fees ........................... +ꜩ2.675 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "BLUE" + Account updates: + [CONTRACT_HASH] ... +100 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor (with complex parameters) from impl.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor (with complex parameters) from impl.out new file mode 100644 index 000000000000..2f058a677b5e --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor (with complex parameters) from impl.out @@ -0,0 +1,61 @@ + +./octez-client --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --entrypoint store --arg 'Pair 99 {Pair "garbage" (Ticket "[CONTRACT_HASH]" string "Ticket1" 1) ; Pair "garbage" (Ticket "[CONTRACT_HASH]" string "Ticket2" 2)}' +Node is bootstrapped. +Estimated gas: 4002.105 units (will add 100 for safety) +Estimated storage: 222 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000843 + Expected counter: 4 + Gas limit: 4103 + Storage limit: 242 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000843 + payload fees(the block proposer) ....... +ꜩ0.000843 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: store + Parameter: (Pair 99 + { Pair "garbage" (Ticket "[CONTRACT_HASH]" string "Ticket1" 1) ; + Pair "garbage" (Ticket "[CONTRACT_HASH]" string "Ticket2" 2) }) + This transaction was successfully applied + Updated storage: + { Pair 0x01b9ce1609aab1100170d2ea4f94e3407244090b1000 (Pair "Ticket2" 2) ; + Pair 0x01b9ce1609aab1100170d2ea4f94e3407244090b1000 (Pair "Ticket1" 1) } + Storage size: 287 bytes + Paid storage size diff: 222 bytes + Consumed gas: 4002.072 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0555 + storage fees ........................... +ꜩ0.0555 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket1" + Account updates: + [PUBLIC_KEY_HASH] ... -1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket2" + Account updates: + [PUBLIC_KEY_HASH] ... -2 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket2" + Account updates: + [CONTRACT_HASH] ... +2 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket1" + Account updates: + [CONTRACT_HASH] ... +1 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor from implicit account to originated.out b/tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor from implicit account to originated.out new file mode 100644 index 000000000000..f228d2fbf1ef --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Send tickets with Ticket constructor from implicit account to originated.out @@ -0,0 +1,48 @@ + +./octez-client --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --entrypoint save --arg 'Ticket "[CONTRACT_HASH]" string "Ticket" 1' +Node is bootstrapped. +Estimated gas: 3081.961 units (will add 100 for safety) +Estimated storage: 44 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000643 + Expected counter: 4 + Gas limit: 3182 + Storage limit: 64 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000643 + payload fees(the block proposer) ....... +ꜩ0.000643 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: save + Parameter: (Ticket "[CONTRACT_HASH]" string "Ticket" 1) + This transaction was successfully applied + Updated storage: + { Pair 0x01fb08747351ab3652f772910c4565880d8df616f800 (Pair "Ticket" 1) } + Storage size: 238 bytes + Paid storage size diff: 44 bytes + Consumed gas: 3081.895 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.011 + storage fees ........................... +ꜩ0.011 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... -1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... +1 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Sending ticket from contract storage to implicit accounts.out b/tezt/tests/expected/tickets.ml/Parisc- Sending ticket from contract storage to implicit accounts.out new file mode 100644 index 000000000000..aeeee4d4a876 --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Sending ticket from contract storage to implicit accounts.out @@ -0,0 +1,294 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none originate contract tickets_bag_implicit transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_bag_implicit_016.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 619.169 units (will add 100 for safety) +Estimated storage: 440 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000482 + Expected counter: 2 + Gas limit: 720 + Storage limit: 460 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000482 + payload fees(the block proposer) ....... +ꜩ0.000482 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (or (ticket %save string) (address %send)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { CONS ; NIL operation ; PAIR } + { SWAP ; + IF_CONS + { DIG 2 ; + CONTRACT (ticket string) ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } + { PUSH string "no ticket to send" ; FAILWITH } } } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 183 bytes + Paid storage size diff: 183 bytes + Consumed gas: 619.136 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.04575 + storage fees ........................... +ꜩ0.04575 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_bag_implicit. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 1' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 3 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup --wait none transfer 1 tickets from bootstrap1 to '[CONTRACT_HASH]' with entrypoint save and contents '"Ticket"' and type string and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 3176.332 units (will add 100 for safety) +Estimated storage: 44 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000626 + Expected counter: 4 + Gas limit: 3277 + Storage limit: 64 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000626 + payload fees(the block proposer) ....... +ꜩ0.000626 + Transfer tickets: + Ticket content: "Ticket" + Ticket content type: string + Ticket ticketer: [CONTRACT_HASH] + Ticket amount: 1 + Destination: [CONTRACT_HASH] + Entrypoint: save + From: [PUBLIC_KEY_HASH] + This tickets transfer was successfully applied + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... -1 + Consumed gas: 1266.515 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: save + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Updated storage: + { Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1) } + Storage size: 227 bytes + Paid storage size diff: 44 bytes + Consumed gas: 1910.352 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.011 + storage fees ........................... +ꜩ0.011 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +0 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --entrypoint send --arg '"[PUBLIC_KEY_HASH]"' +Node is bootstrapped. +Estimated gas: 2511.210 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000561 + Expected counter: 5 + Gas limit: 2612 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000561 + payload fees(the block proposer) ....... +ꜩ0.000561 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: send + Parameter: "[PUBLIC_KEY_HASH]" + This transaction was successfully applied + Updated storage: {} + Storage size: 183 bytes + Consumed gas: 2411.347 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... -1 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap2 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup get ticket balance for '[CONTRACT_HASH]' with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +0 diff --git a/tezt/tests/expected/tickets.ml/Parisc- Sending ticket of wrong type from implicit accounts must be rejected.out b/tezt/tests/expected/tickets.ml/Parisc- Sending ticket of wrong type from implicit accounts must be rejected.out new file mode 100644 index 000000000000..24c16086d26f --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Sending ticket of wrong type from implicit accounts must be rejected.out @@ -0,0 +1,129 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 1' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 2 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup --wait none transfer 2 tickets from bootstrap1 to bootstrap2 with entrypoint default and contents 0 and type nat and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +This simulation failed: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0 + Expected counter: 3 + Gas limit: 1040000 + Storage limit: 60000 bytes + Transfer tickets: + Ticket content: 0 + Ticket content type: nat + Ticket ticketer: [CONTRACT_HASH] + Ticket amount: 2 + Destination: [PUBLIC_KEY_HASH] + From: [PUBLIC_KEY_HASH] + This operation FAILED. + +Error: + Attempted to set negative ticket balance value '-2' for key expru2shUeN2Ah7TLWrM937cMzrqkGL4LirEXUQYVZU4YvjdqGrkB2. diff --git a/tezt/tests/expected/tickets.ml/Parisc- Sending tickets from storage to smart-contract rollup should succeed wit.out b/tezt/tests/expected/tickets.ml/Parisc- Sending tickets from storage to smart-contract rollup should succeed wit.out new file mode 100644 index 000000000000..d916565f422a --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Sending tickets from storage to smart-contract rollup should succeed wit.out @@ -0,0 +1,111 @@ + +./octez-client --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --entrypoint mint +Node is bootstrapped. +Estimated gas: 2222.033 units (will add 100 for safety) +Estimated storage: 221 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 3 + Gas limit: 2323 + Storage limit: 241 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: mint + This transaction was successfully applied + Updated storage: + { Pair 0x017a22a4e42f88383dbb327d548e263b53f4f3b91100 (Pair "Ticket2" 1) ; + Pair 0x017a22a4e42f88383dbb327d548e263b53f4f3b91100 (Pair "Ticket" 1) } + Storage size: 309 bytes + Paid storage size diff: 221 bytes + Consumed gas: 2222 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.05525 + storage fees ........................... +ꜩ0.05525 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket2" + Account updates: + [CONTRACT_HASH] ... +1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... +1 + + +./octez-client --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --entrypoint send --arg '"[SMART_ROLLUP_HASH]"' +Node is bootstrapped. +Estimated gas: 3141.953 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000624 + Expected counter: 4 + Gas limit: 3242 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000624 + payload fees(the block proposer) ....... +ꜩ0.000624 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Entrypoint: send + Parameter: "[SMART_ROLLUP_HASH]" + This transaction was successfully applied + Updated storage: {} + Storage size: 220 bytes + Consumed gas: 3031.954 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket2" + Account updates: + [CONTRACT_HASH] ... -1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [CONTRACT_HASH] ... -1 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [SMART_ROLLUP_HASH] + Parameter: { Pair 0x017a22a4e42f88383dbb327d548e263b53f4f3b91100 (Pair "Ticket2" 1) ; + Pair 0x017a22a4e42f88383dbb327d548e263b53f4f3b91100 (Pair "Ticket" 1) } + This transaction was successfully applied + Consumed gas: 109.932 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket2" + Account updates: + [SMART_ROLLUP_HASH] ... +1 + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [SMART_ROLLUP_HASH] ... +1 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Sending tickets to either implicit accounts or originated contracts acce.out b/tezt/tests/expected/tickets.ml/Parisc- Sending tickets to either implicit accounts or originated contracts acce.out new file mode 100644 index 000000000000..68e808e16d82 --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Sending tickets to either implicit accounts or originated contracts acce.out @@ -0,0 +1,197 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none originate contract tickets_blackhole transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_blackhole_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 579.704 units (will add 100 for safety) +Estimated storage: 308 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000346 + Expected counter: 2 + Gas limit: 680 + Storage limit: 328 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000346 + payload fees(the block proposer) ....... +ꜩ0.000346 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (ticket %ticket string) ; + storage unit ; + code { CDR ; NIL operation ; PAIR } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 51 bytes + Paid storage size diff: 51 bytes + Consumed gas: 579.671 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01275 + storage fees ........................... +ꜩ0.01275 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_blackhole. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 1' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 3 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[CONTRACT_HASH]" 1' +Node is bootstrapped. +Estimated gas: 4063.823 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000715 + Expected counter: 4 + Gas limit: 4164 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000715 + payload fees(the block proposer) ....... +ꜩ0.000715 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[CONTRACT_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 2211.236 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Updated storage: Unit + Storage size: 51 bytes + Consumed gas: 1853.638 + diff --git a/tezt/tests/expected/tickets.ml/Parisc- Sending zero ticket from implicit accounts must be rejected.out b/tezt/tests/expected/tickets.ml/Parisc- Sending zero ticket from implicit accounts must be rejected.out new file mode 100644 index 000000000000..ca58a93b53c6 --- /dev/null +++ b/tezt/tests/expected/tickets.ml/Parisc- Sending zero ticket from implicit accounts must be rejected.out @@ -0,0 +1,174 @@ + +./octez-client --mode mockup --wait none originate contract tickets_send transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_send_016.tz --init Unit --burn-cap 1 +Node is bootstrapped. +Estimated gas: 614.216 units (will add 100 for safety) +Estimated storage: 415 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000457 + Expected counter: 1 + Gas limit: 715 + Storage limit: 435 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000457 + payload fees(the block proposer) ....... +ꜩ0.000457 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (pair address nat) ; + storage unit ; + code { CAR ; + UNPAIR ; + CONTRACT (ticket string) ; + IF_NONE + { PUSH string "Contract not found" ; FAILWITH } + { PUSH mutez 0 ; + DIG 2 ; + PUSH string "Ticket" ; + TICKET ; + ASSERT_SOME ; + TRANSFER_TOKENS ; + PUSH unit Unit ; + NIL operation ; + DIG 2 ; + CONS ; + PAIR } } } + Initial storage: Unit + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 158 bytes + Paid storage size diff: 158 bytes + Consumed gas: 614.183 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0395 + storage fees ........................... +ꜩ0.0395 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_send. + +./octez-client --mode mockup --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg 'Pair "[PUBLIC_KEY_HASH]" 1' +Node is bootstrapped. +Estimated gas: 1858.650 units (will add 100 for safety) +Estimated storage: 66 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 2 + Gas limit: 1959 + Storage limit: 86 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" 1) + This transaction was successfully applied + Updated storage: Unit + Storage size: 158 bytes + Paid storage size diff: 66 bytes + Consumed gas: 1758.787 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0165 + storage fees ........................... +ꜩ0.0165 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [PUBLIC_KEY_HASH] + Parameter: (Pair 0x01fca241ad513615858a813a6019c5a5b3977c27dc00 (Pair "Ticket" 1)) + This transaction was successfully applied + Consumed gas: 100.398 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Ticket" + Account updates: + [PUBLIC_KEY_HASH] ... +1 + + +./octez-client --mode mockup get ticket balance for bootstrap1 with ticketer '[CONTRACT_HASH]' and type string and content '"Ticket"' +1 + +./octez-client --mode mockup --wait none originate contract tickets_bag transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/tickets_bag_016.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 620.183 units (will add 100 for safety) +Estimated storage: 451 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000494 + Expected counter: 3 + Gas limit: 721 + Storage limit: 471 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000494 + payload fees(the block proposer) ....... +ꜩ0.000494 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter (or (ticket %save string) (address %send)) ; + storage (list (ticket string)) ; + code { UNPAIR ; + IF_LEFT + { CONS ; NIL operation ; PAIR } + { SWAP ; + IF_CONS + { DIG 2 ; + CONTRACT %ticket (ticket string) ; + ASSERT_SOME ; + PUSH mutez 0 ; + DIG 2 ; + TRANSFER_TOKENS ; + NIL operation ; + SWAP ; + CONS ; + PAIR } + { PUSH string "no ticket to send" ; FAILWITH } } } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 194 bytes + Paid storage size diff: 194 bytes + Consumed gas: 620.150 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.0485 + storage fees ........................... +ꜩ0.0485 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as tickets_bag. + +./octez-client --mode mockup --wait none transfer 0 tickets from bootstrap1 to '[CONTRACT_HASH]' with entrypoint save and contents '"Ticket"' and type string and ticketer '[CONTRACT_HASH]' --burn-cap 1 +Fatal error: + ticket quantity should not be zero or negative diff --git a/tezt/tests/expected/tx_sc_rollup.ml/Paris- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out b/tezt/tests/expected/tx_sc_rollup.ml/Parisb- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out similarity index 100% rename from tezt/tests/expected/tx_sc_rollup.ml/Paris- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out rename to tezt/tests/expected/tx_sc_rollup.ml/Parisb- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out diff --git a/tezt/tests/expected/tx_sc_rollup.ml/Parisc- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out b/tezt/tests/expected/tx_sc_rollup.ml/Parisc- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out new file mode 100644 index 000000000000..52a59d964c2f --- /dev/null +++ b/tezt/tests/expected/tx_sc_rollup.ml/Parisc- wasm_2_0_0 - tx kernel should run e2e (kernel_e2e).out @@ -0,0 +1,224 @@ + +./octez-client --wait none transfer 0 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1000 --arg 'Pair (Pair "[SMART_ROLLUP_HASH]" "[PUBLIC_KEY_HASH]") (Pair 450 "Hello, Ticket!")' +Node is bootstrapped. +Estimated gas: 2329.875 units (will add 100 for safety) +Estimated storage: 67 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000606 + Expected counter: 3 + Gas limit: 2430 + Storage limit: 87 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000606 + payload fees(the block proposer) ....... +ꜩ0.000606 + Transaction: + Amount: ꜩ0 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: (Pair (Pair "[SMART_ROLLUP_HASH]" "[PUBLIC_KEY_HASH]") + (Pair 450 "Hello, Ticket!")) + This transaction was successfully applied + Updated storage: Unit + Storage size: 205 bytes + Paid storage size diff: 67 bytes + Consumed gas: 2222.857 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01675 + storage fees ........................... +ꜩ0.01675 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [CONTRACT_HASH] + To: [SMART_ROLLUP_HASH] + Parameter: (Pair "[PUBLIC_KEY_HASH]" + (Pair [MICHELINE_KT1_BYTES] (Pair "Hello, Ticket!" 450))) + This transaction was successfully applied + Consumed gas: 106.951 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Hello, Ticket!" + Account updates: + [SMART_ROLLUP_HASH] ... +450 + + +./octez-client --wait none send smart rollup message '[SMART_ROLLUP_EXTERNAL_MESSAGES]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 183.869 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000619 + Expected counter: 1 + Gas limit: 284 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000619 + payload fees(the block proposer) ....... +ꜩ0.000619 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 183.803 + +GET http://[HOST]:[PORT]/global/block/head/total_ticks +200 OK +"650000000000000" + + +./octez-client --wait none send smart rollup message '[SMART_ROLLUP_EXTERNAL_MESSAGES]' from bootstrap2 +Node is bootstrapped. +Estimated gas: 186.279 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000682 + Expected counter: 2 + Gas limit: 287 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000682 + payload fees(the block proposer) ....... +ꜩ0.000682 + Smart rollup messages submission: + This smart rollup messages submission was successfully applied + Consumed gas: 186.213 + +GET http://[HOST]:[PORT]/global/block/12/total_ticks +200 OK +"1550000000000000" + + +./octez-client --wait none execute outbox message of smart rollup '[SMART_ROLLUP_HASH]' from bootstrap1 for commitment hash '[SC_ROLLUP_COMMITMENT_HASH]' and output proof '[SMART_ROLLUP_BYTES]' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 6269.903 units (will add 100 for safety) +Estimated storage: 125 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.001625 + Expected counter: 8 + Gas limit: 6370 + Storage limit: 145 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.001625 + payload fees(the block proposer) ....... +ꜩ0.001625 + Smart rollup output message execution: + Address: [SMART_ROLLUP_HASH] + Cemented commitment: [SC_ROLLUP_COMMITMENT_HASH] + This smart output message execution was successfully applied + Paid storage size diff: 72 bytes + Consumed gas: 5060.896 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.018 + storage fees ........................... +ꜩ0.018 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Hello, Ticket!" + Account updates: + [SMART_ROLLUP_HASH] ... -220 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [SMART_ROLLUP_HASH] + To: [CONTRACT_HASH] + Entrypoint: receive_tickets + Parameter: (Pair [MICHELINE_KT1_BYTES] (Pair "Hello, Ticket!" 220)) + This transaction was successfully applied + Updated storage: + { Pair [MICHELINE_KT1_BYTES] (Pair "Hello, Ticket!" 220) } + Storage size: 175 bytes + Paid storage size diff: 53 bytes + Consumed gas: 1208.974 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.01325 + storage fees ........................... +ꜩ0.01325 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Hello, Ticket!" + Account updates: + [CONTRACT_HASH] ... +220 + + +./octez-client --wait none execute outbox message of smart rollup '[SMART_ROLLUP_HASH]' from bootstrap1 for commitment hash '[SC_ROLLUP_COMMITMENT_HASH]' and output proof '[SMART_ROLLUP_BYTES]' --burn-cap 10 +Node is bootstrapped. +Estimated gas: 5818.472 units (will add 100 for safety) +Estimated storage: 52 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.001577 + Expected counter: 9 + Gas limit: 5919 + Storage limit: 72 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.001577 + payload fees(the block proposer) ....... +ꜩ0.001577 + Smart rollup output message execution: + Address: [SMART_ROLLUP_HASH] + Cemented commitment: [SC_ROLLUP_COMMITMENT_HASH] + This smart output message execution was successfully applied + Consumed gas: 4601.209 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Hello, Ticket!" + Account updates: + [SMART_ROLLUP_HASH] ... -40 + Internal operations: + Internal Transaction: + Amount: ꜩ0 + From: [SMART_ROLLUP_HASH] + To: [CONTRACT_HASH] + Entrypoint: receive_tickets + Parameter: (Pair [MICHELINE_KT1_BYTES] (Pair "Hello, Ticket!" 40)) + This transaction was successfully applied + Updated storage: + { Pair [MICHELINE_KT1_BYTES] (Pair "Hello, Ticket!" 40) ; + Pair [MICHELINE_KT1_BYTES] (Pair "Hello, Ticket!" 220) } + Storage size: 227 bytes + Paid storage size diff: 52 bytes + Consumed gas: 1217.197 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.013 + storage fees ........................... +ꜩ0.013 + Ticket updates: + Ticketer: [CONTRACT_HASH] + Content type: string + Content: "Hello, Ticket!" + Account updates: + [CONTRACT_HASH] ... +40 + diff --git a/tezt/tests/expected/tzt_regression.ml/Paris- Run TZT.out b/tezt/tests/expected/tzt_regression.ml/Parisb- Run TZT.out similarity index 100% rename from tezt/tests/expected/tzt_regression.ml/Paris- Run TZT.out rename to tezt/tests/expected/tzt_regression.ml/Parisb- Run TZT.out diff --git a/tezt/tests/expected/tzt_regression.ml/Parisc- Run TZT.out b/tezt/tests/expected/tzt_regression.ml/Parisc- Run TZT.out new file mode 100644 index 000000000000..faa65facf32f --- /dev/null +++ b/tezt/tests/expected/tzt_regression.ml/Parisc- Run TZT.out @@ -0,0 +1,69 @@ + +./octez-client --protocol PsParisCZo7KAh1Z1smVd9ZMZ1HHn5gkzbM94V3PLCpknFWhUAi --mode mockup --no-base-dir-warnings run unit tests from tzt_reference_test_suite/abs_00.tzt tzt_reference_test_suite/abs_01.tzt tzt_reference_test_suite/abs_02.tzt tzt_reference_test_suite/add_00.tc.tzt tzt_reference_test_suite/add_01.tc.tzt tzt_reference_test_suite/add_int-int_00.tzt tzt_reference_test_suite/add_int-nat_00.tzt tzt_reference_test_suite/add_int-nat_01.tzt tzt_reference_test_suite/add_int-timestamp_00.tzt tzt_reference_test_suite/add_mutez-mutez_00.tzt tzt_reference_test_suite/add_mutez-mutez_01.tzt tzt_reference_test_suite/add_nat-int_00.tzt tzt_reference_test_suite/add_nat-nat_00.tzt tzt_reference_test_suite/add_timestamp-int_00.tzt tzt_reference_test_suite/add_timestamp-int_01.tzt tzt_reference_test_suite/add_timestamp-int_02.tzt tzt_reference_test_suite/add_timestamp-int_03.tzt tzt_reference_test_suite/address_00.tzt tzt_reference_test_suite/address_00.tc.tzt tzt_reference_test_suite/address_01.tzt tzt_reference_test_suite/address_02.tzt tzt_reference_test_suite/amount_00.tzt tzt_reference_test_suite/and_bool-bool_00.tzt tzt_reference_test_suite/and_bool-bool_01.tzt tzt_reference_test_suite/and_bool-bool_02.tzt tzt_reference_test_suite/and_bool-bool_03.tzt tzt_reference_test_suite/and_bytes-bytes_00.tzt tzt_reference_test_suite/and_bytes-bytes_01.tzt tzt_reference_test_suite/and_bytes-bytes_02.tzt tzt_reference_test_suite/and_bytes-bytes_03.tzt tzt_reference_test_suite/and_bytes-bytes_04.tzt tzt_reference_test_suite/and_bytes-bytes_05.tzt tzt_reference_test_suite/and_bytes-bytes_06.tzt tzt_reference_test_suite/and_int-nat_00.tzt tzt_reference_test_suite/and_int-nat_01.tzt tzt_reference_test_suite/and_int-nat_02.tzt tzt_reference_test_suite/and_int-nat_03.tzt tzt_reference_test_suite/and_int-nat_04.tzt tzt_reference_test_suite/and_int-nat_05.tzt tzt_reference_test_suite/and_int-nat_06.tzt tzt_reference_test_suite/and_nat-nat_00.tzt tzt_reference_test_suite/and_nat-nat_01.tzt tzt_reference_test_suite/and_nat-nat_02.tzt tzt_reference_test_suite/apply_00.tzt tzt_reference_test_suite/apply_01.tzt tzt_reference_test_suite/apply_02.tzt tzt_reference_test_suite/balance_00.tzt tzt_reference_test_suite/blake2b_00.tzt tzt_reference_test_suite/blake2b_01.tzt tzt_reference_test_suite/car_00.tzt tzt_reference_test_suite/car_00.tc.tzt tzt_reference_test_suite/car_01.tzt tzt_reference_test_suite/cdr_00.tzt tzt_reference_test_suite/cdr_00.tc.tzt tzt_reference_test_suite/cdr_01.tzt tzt_reference_test_suite/chain_id_00.tzt tzt_reference_test_suite/chain_id_01.tzt tzt_reference_test_suite/checksignature_00.tzt tzt_reference_test_suite/checksignature_00.tc.tzt tzt_reference_test_suite/checksignature_01.tzt tzt_reference_test_suite/compare_00.tc.tzt tzt_reference_test_suite/compare_01.tc.tzt tzt_reference_test_suite/compare_02.tc.tzt tzt_reference_test_suite/compare_bool_00.tzt tzt_reference_test_suite/compare_bool_01.tzt tzt_reference_test_suite/compare_bool_02.tzt tzt_reference_test_suite/compare_bool_03.tzt tzt_reference_test_suite/compare_bytes_00.tzt tzt_reference_test_suite/compare_bytes_01.tzt tzt_reference_test_suite/compare_bytes_02.tzt tzt_reference_test_suite/compare_bytes_03.tzt tzt_reference_test_suite/compare_bytes_04.tzt tzt_reference_test_suite/compare_int_00.tzt tzt_reference_test_suite/compare_int_01.tzt tzt_reference_test_suite/compare_int_02.tzt tzt_reference_test_suite/compare_int_03.tzt tzt_reference_test_suite/compare_int_04.tzt tzt_reference_test_suite/compare_keyhash_00.tzt tzt_reference_test_suite/compare_keyhash_01.tzt tzt_reference_test_suite/compare_keyhash_02.tzt tzt_reference_test_suite/compare_mutez_00.tzt tzt_reference_test_suite/compare_mutez_01.tzt tzt_reference_test_suite/compare_mutez_02.tzt tzt_reference_test_suite/compare_mutez_03.tzt tzt_reference_test_suite/compare_mutez_04.tzt tzt_reference_test_suite/compare_mutez_05.tzt tzt_reference_test_suite/compare_nat_00.tzt tzt_reference_test_suite/compare_nat_01.tzt tzt_reference_test_suite/compare_nat_02.tzt tzt_reference_test_suite/compare_nat_03.tzt tzt_reference_test_suite/compare_nat_04.tzt tzt_reference_test_suite/compare_nat_05.tzt tzt_reference_test_suite/compare_never_00.tzt tzt_reference_test_suite/compare_pairintint_00.tzt tzt_reference_test_suite/compare_pairintint_01.tzt tzt_reference_test_suite/compare_pairintint_02.tzt tzt_reference_test_suite/compare_pairintint_03.tzt tzt_reference_test_suite/compare_string_00.tzt tzt_reference_test_suite/compare_string_01.tzt tzt_reference_test_suite/compare_string_02.tzt tzt_reference_test_suite/compare_string_03.tzt tzt_reference_test_suite/compare_string_04.tzt tzt_reference_test_suite/compare_timestamp_00.tzt tzt_reference_test_suite/compare_timestamp_01.tzt tzt_reference_test_suite/compare_timestamp_02.tzt tzt_reference_test_suite/compare_timestamp_03.tzt tzt_reference_test_suite/compare_timestamp_04.tzt tzt_reference_test_suite/compare_timestamp_05.tzt tzt_reference_test_suite/concat_00.tc.tzt tzt_reference_test_suite/concat_bytes_00.tzt tzt_reference_test_suite/concat_bytes_01.tzt tzt_reference_test_suite/concat_listbytes_00.tzt tzt_reference_test_suite/concat_listbytes_01.tzt tzt_reference_test_suite/concat_listbytes_02.tzt tzt_reference_test_suite/concat_liststring_00.tzt tzt_reference_test_suite/concat_liststring_01.tzt tzt_reference_test_suite/concat_liststring_02.tzt tzt_reference_test_suite/concat_liststring_03.tzt tzt_reference_test_suite/concat_liststring_04.tzt tzt_reference_test_suite/concat_string_00.tzt tzt_reference_test_suite/concat_string_01.tzt tzt_reference_test_suite/concat_string_02.tzt tzt_reference_test_suite/cons_int_00.tzt tzt_reference_test_suite/cons_int_01.tzt tzt_reference_test_suite/cons_int_02.tzt tzt_reference_test_suite/cons_lists_00.tc.tzt tzt_reference_test_suite/cons_string_00.tzt tzt_reference_test_suite/contract_00.tzt tzt_reference_test_suite/contract_01.tzt tzt_reference_test_suite/contract_02.tzt tzt_reference_test_suite/contract_03.tzt tzt_reference_test_suite/contract_04.tzt tzt_reference_test_suite/contract_05.tzt tzt_reference_test_suite/createcontract_00.tzt tzt_reference_test_suite/createcontract_01.tzt tzt_reference_test_suite/dig_00.tzt tzt_reference_test_suite/dig_01.tzt tzt_reference_test_suite/dig_02.tzt tzt_reference_test_suite/dig_03.tzt tzt_reference_test_suite/dig_04.tzt tzt_reference_test_suite/dip_00.tzt tzt_reference_test_suite/dip_00.tc.tzt tzt_reference_test_suite/dip_01.tzt tzt_reference_test_suite/dip_02.tzt tzt_reference_test_suite/dipn_00.tzt tzt_reference_test_suite/dipn_00.tc.tzt tzt_reference_test_suite/dipn_01.tzt tzt_reference_test_suite/dipn_01.tc.tzt tzt_reference_test_suite/dipn_02.tzt tzt_reference_test_suite/dipn_02.tc.tzt tzt_reference_test_suite/dipn_03.tzt tzt_reference_test_suite/drop_00.tzt tzt_reference_test_suite/drop_00.tc.tzt tzt_reference_test_suite/dropn_00.tzt tzt_reference_test_suite/dropn_00.tc.tzt tzt_reference_test_suite/dropn_01.tzt tzt_reference_test_suite/dropn_02.tzt tzt_reference_test_suite/dropn_03.tzt tzt_reference_test_suite/dugn_00.tzt tzt_reference_test_suite/dup_00.tzt tzt_reference_test_suite/dup_00.tc.tzt tzt_reference_test_suite/dupn_00.tzt tzt_reference_test_suite/dupn_00.tc.tzt tzt_reference_test_suite/dupn_01.tzt tzt_reference_test_suite/dupn_01.tc.tzt tzt_reference_test_suite/dupn_02.tzt tzt_reference_test_suite/dupn_03.tzt tzt_reference_test_suite/dupn_04.tzt tzt_reference_test_suite/ediv_int-int_00.tzt tzt_reference_test_suite/ediv_int-int_01.tzt tzt_reference_test_suite/ediv_int-int_02.tzt tzt_reference_test_suite/ediv_int-int_03.tzt tzt_reference_test_suite/ediv_mutez-mutez_00.tzt tzt_reference_test_suite/ediv_mutez-mutez_01.tzt tzt_reference_test_suite/ediv_mutez-mutez_02.tzt tzt_reference_test_suite/ediv_mutez-mutez_03.tzt tzt_reference_test_suite/ediv_mutez-nat_00.tzt tzt_reference_test_suite/ediv_mutez-nat_01.tzt tzt_reference_test_suite/ediv_mutez-nat_02.tzt tzt_reference_test_suite/ediv_mutez-nat_03.tzt tzt_reference_test_suite/ediv_mutez-nat_04.tzt tzt_reference_test_suite/ediv_mutez-nat_05.tzt tzt_reference_test_suite/ediv_mutez-nat_06.tzt tzt_reference_test_suite/emptybigmap_nat-nat_00.tzt tzt_reference_test_suite/emptymap_nat-nat_00.tzt tzt_reference_test_suite/emptymap_string-string_00.tzt tzt_reference_test_suite/emptyset_00.tc.tzt tzt_reference_test_suite/emptyset_nat_00.tzt tzt_reference_test_suite/eq_00.tzt tzt_reference_test_suite/eq_01.tzt tzt_reference_test_suite/eq_02.tzt tzt_reference_test_suite/eq_03.tzt tzt_reference_test_suite/eq_04.tzt tzt_reference_test_suite/exec_00.tzt tzt_reference_test_suite/exec_01.tzt tzt_reference_test_suite/exec_02.tzt tzt_reference_test_suite/exec_03.tzt tzt_reference_test_suite/failwith_00.tzt tzt_reference_test_suite/failwith_00.tc.tzt tzt_reference_test_suite/gas_exhaustion.tzt tzt_reference_test_suite/ge_00.tzt tzt_reference_test_suite/ge_01.tzt tzt_reference_test_suite/ge_02.tzt tzt_reference_test_suite/ge_03.tzt tzt_reference_test_suite/ge_04.tzt tzt_reference_test_suite/get_00.tc.tzt tzt_reference_test_suite/get_bigmapstringstring_00.tzt tzt_reference_test_suite/get_bigmapstringstring_01.tzt tzt_reference_test_suite/get_bigmapstringstring_02.tzt tzt_reference_test_suite/get_map_00.tc.tzt tzt_reference_test_suite/get_mapintint_00.tzt tzt_reference_test_suite/get_mapintint_01.tzt tzt_reference_test_suite/get_mapstringstring_00.tzt tzt_reference_test_suite/get_mapstringstring_01.tzt tzt_reference_test_suite/get_mapstringstring_02.tzt tzt_reference_test_suite/gt_00.tzt tzt_reference_test_suite/gt_00.tc.tzt tzt_reference_test_suite/gt_01.tzt tzt_reference_test_suite/gt_02.tzt tzt_reference_test_suite/gt_03.tzt tzt_reference_test_suite/gt_04.tzt tzt_reference_test_suite/if_00.tzt tzt_reference_test_suite/if_00.tc.tzt tzt_reference_test_suite/if_01.tzt tzt_reference_test_suite/if_01.tc.tzt tzt_reference_test_suite/ifcons_00.tc.tzt tzt_reference_test_suite/ifcons_listint_00.tzt tzt_reference_test_suite/ifcons_listint_01.tzt tzt_reference_test_suite/ifcons_listnat_00.tzt tzt_reference_test_suite/ifcons_listnat_01.tzt tzt_reference_test_suite/ifleft_00.tc.tzt tzt_reference_test_suite/ifleft_orintstring_00.tzt tzt_reference_test_suite/ifleft_orstringint_00.tzt tzt_reference_test_suite/ifnone_00.tc.tzt tzt_reference_test_suite/ifnone_optionint_00.tzt tzt_reference_test_suite/ifnone_optionnat_00.tzt tzt_reference_test_suite/implicitaccount_00.tzt tzt_reference_test_suite/int_00.tc.tzt tzt_reference_test_suite/int_nat_00.tzt tzt_reference_test_suite/int_nat_01.tzt tzt_reference_test_suite/isnat_00.tzt tzt_reference_test_suite/isnat_01.tzt tzt_reference_test_suite/iter_00.tc.tzt tzt_reference_test_suite/iter_listint_00.tzt tzt_reference_test_suite/iter_listint_01.tzt tzt_reference_test_suite/iter_listint_02.tzt tzt_reference_test_suite/iter_listint_03.tzt tzt_reference_test_suite/iter_liststring_00.tzt tzt_reference_test_suite/iter_liststring_01.tzt tzt_reference_test_suite/iter_mapintint_00.tzt tzt_reference_test_suite/iter_mapintint_01.tzt tzt_reference_test_suite/iter_mapintint_02.tzt tzt_reference_test_suite/iter_mapintint_03.tzt tzt_reference_test_suite/iter_mapintint_04.tzt tzt_reference_test_suite/iter_mapstringstring_00.tzt tzt_reference_test_suite/iter_setint_00.tzt tzt_reference_test_suite/iter_setint_01.tzt tzt_reference_test_suite/iter_setint_02.tzt tzt_reference_test_suite/iter_setstring_00.tzt tzt_reference_test_suite/iter_setstring_01.tzt tzt_reference_test_suite/iter_setstring_02.tzt tzt_reference_test_suite/join_tickets_00.tzt tzt_reference_test_suite/join_tickets_01.tzt tzt_reference_test_suite/join_tickets_02.tzt tzt_reference_test_suite/join_tickets_03.tzt tzt_reference_test_suite/keccak_00.tzt tzt_reference_test_suite/keccak_01.tzt tzt_reference_test_suite/le_00.tzt tzt_reference_test_suite/le_01.tzt tzt_reference_test_suite/le_02.tzt tzt_reference_test_suite/le_03.tzt tzt_reference_test_suite/le_04.tzt tzt_reference_test_suite/left_int-nat_00.tzt tzt_reference_test_suite/loop_00.tzt tzt_reference_test_suite/loop_00.tc.tzt tzt_reference_test_suite/loop_01.tzt tzt_reference_test_suite/loop_01.tc.tzt tzt_reference_test_suite/loop_02.tzt tzt_reference_test_suite/loopleft_00.tzt tzt_reference_test_suite/loopleft_01.tzt tzt_reference_test_suite/loopleft_02.tzt tzt_reference_test_suite/loopleft_03.tzt tzt_reference_test_suite/loopleft_04.tzt tzt_reference_test_suite/lsl_00.tzt tzt_reference_test_suite/lsl_01.tzt tzt_reference_test_suite/lsl_02.tzt tzt_reference_test_suite/lsl_03.tzt tzt_reference_test_suite/lsl_04.tzt tzt_reference_test_suite/lsl_05.tzt tzt_reference_test_suite/lsl_06.tzt tzt_reference_test_suite/lsr_00.tzt tzt_reference_test_suite/lsr_01.tzt tzt_reference_test_suite/lsr_02.tzt tzt_reference_test_suite/lsr_03.tzt tzt_reference_test_suite/lsr_04.tzt tzt_reference_test_suite/lsr_05.tzt tzt_reference_test_suite/lt_00.tzt tzt_reference_test_suite/lt_01.tzt tzt_reference_test_suite/lt_02.tzt tzt_reference_test_suite/lt_03.tzt tzt_reference_test_suite/lt_04.tzt tzt_reference_test_suite/macro_pack/assert_00.tzt tzt_reference_test_suite/macro_pack/assert_cmpeq_00.tzt tzt_reference_test_suite/macro_pack/assert_cmpge_00.tzt tzt_reference_test_suite/macro_pack/assert_cmpgt_00.tzt tzt_reference_test_suite/macro_pack/assert_cmple_00.tzt tzt_reference_test_suite/macro_pack/assert_cmplt_00.tzt tzt_reference_test_suite/macro_pack/assert_cmpneq_00.tzt tzt_reference_test_suite/macro_pack/assert_eq_00.tzt tzt_reference_test_suite/macro_pack/assert_ge_00.tzt tzt_reference_test_suite/macro_pack/assert_gt_00.tzt tzt_reference_test_suite/macro_pack/assert_le_00.tzt tzt_reference_test_suite/macro_pack/assert_left_00.tzt tzt_reference_test_suite/macro_pack/assert_lt_00.tzt tzt_reference_test_suite/macro_pack/assert_neq_00.tzt tzt_reference_test_suite/macro_pack/assert_none_00.tzt tzt_reference_test_suite/macro_pack/assert_right_00.tzt tzt_reference_test_suite/macro_pack/assert_some_00.tzt tzt_reference_test_suite/macro_pack/cadr_00.tzt tzt_reference_test_suite/macro_pack/carn_00.tzt tzt_reference_test_suite/macro_pack/carn_01.tzt tzt_reference_test_suite/macro_pack/cdrn_00.tzt tzt_reference_test_suite/macro_pack/cdrn_01.tzt tzt_reference_test_suite/macro_pack/cmpeq_00.tzt tzt_reference_test_suite/macro_pack/cmpge_00.tzt tzt_reference_test_suite/macro_pack/cmpgt_00.tzt tzt_reference_test_suite/macro_pack/cmple_00.tzt tzt_reference_test_suite/macro_pack/cmplt_00.tzt tzt_reference_test_suite/macro_pack/cmpneq_00.tzt tzt_reference_test_suite/macro_pack/fail_00.tzt tzt_reference_test_suite/macro_pack/ifcmpeq_00.tzt tzt_reference_test_suite/macro_pack/ifcmpge_00.tzt tzt_reference_test_suite/macro_pack/ifcmpgt_00.tzt tzt_reference_test_suite/macro_pack/ifcmple_00.tzt tzt_reference_test_suite/macro_pack/ifcmplt_00.tzt tzt_reference_test_suite/macro_pack/ifcmpneq_00.tzt tzt_reference_test_suite/macro_pack/ifeq_00.tzt tzt_reference_test_suite/macro_pack/ifge_00.tzt tzt_reference_test_suite/macro_pack/ifgt_00.tzt tzt_reference_test_suite/macro_pack/ifle_00.tzt tzt_reference_test_suite/macro_pack/iflt_00.tzt tzt_reference_test_suite/macro_pack/ifneq_00.tzt tzt_reference_test_suite/macro_pack/ifright_00.tzt tzt_reference_test_suite/macro_pack/ifsome_00.tzt tzt_reference_test_suite/macro_pack/mapcadr_00.tzt tzt_reference_test_suite/macro_pack/mapcar_00.tzt tzt_reference_test_suite/macro_pack/mapcdr_00.tzt tzt_reference_test_suite/macro_pack/papair_00.tzt tzt_reference_test_suite/macro_pack/setcadr_00.tzt tzt_reference_test_suite/macro_pack/setcar_00.tzt tzt_reference_test_suite/macro_pack/setcdr_00.tzt tzt_reference_test_suite/macro_pack/unpapair_00.tzt tzt_reference_test_suite/map_listint_00.tzt tzt_reference_test_suite/map_listint_01.tzt tzt_reference_test_suite/map_listint_02.tzt tzt_reference_test_suite/map_listint_03.tzt tzt_reference_test_suite/map_listint_04.tzt tzt_reference_test_suite/map_listint_05.tzt tzt_reference_test_suite/map_listint_06.tzt tzt_reference_test_suite/map_liststring_00.tzt tzt_reference_test_suite/map_liststring_01.tzt tzt_reference_test_suite/map_liststring_02.tzt tzt_reference_test_suite/map_liststring_04.tzt tzt_reference_test_suite/map_liststring_05.tzt tzt_reference_test_suite/map_liststring_06.tzt tzt_reference_test_suite/map_liststring_07.tzt tzt_reference_test_suite/map_liststring_08.tzt tzt_reference_test_suite/map_mapintint_00.tzt tzt_reference_test_suite/map_mapintint_01.tzt tzt_reference_test_suite/map_mapintstring_00.tzt tzt_reference_test_suite/map_mapintstring_01.tzt tzt_reference_test_suite/map_mapstringnat_00.tzt tzt_reference_test_suite/map_mapstringnat_01.tzt tzt_reference_test_suite/map_mapstringnat_02.tzt tzt_reference_test_suite/mem_bigmapnatnat_00.tzt tzt_reference_test_suite/mem_bigmapnatnat_01.tzt tzt_reference_test_suite/mem_bigmapnatnat_02.tzt tzt_reference_test_suite/mem_bigmapnatnat_03.tzt tzt_reference_test_suite/mem_bigmapnatnat_04.tzt tzt_reference_test_suite/mem_bigmapnatnat_05.tzt tzt_reference_test_suite/mem_bigmapstringnat_00.tzt tzt_reference_test_suite/mem_bigmapstringnat_01.tzt tzt_reference_test_suite/mem_bigmapstringnat_02.tzt tzt_reference_test_suite/mem_bigmapstringnat_03.tzt tzt_reference_test_suite/mem_bigmapstringnat_04.tzt tzt_reference_test_suite/mem_bigmapstringnat_05.tzt tzt_reference_test_suite/mem_mapintint_00.tzt tzt_reference_test_suite/mem_mapnatnat_00.tzt tzt_reference_test_suite/mem_mapnatnat_01.tzt tzt_reference_test_suite/mem_mapnatnat_02.tzt tzt_reference_test_suite/mem_mapnatnat_03.tzt tzt_reference_test_suite/mem_mapnatnat_04.tzt tzt_reference_test_suite/mem_mapnatnat_05.tzt tzt_reference_test_suite/mem_mapstringnat_00.tzt tzt_reference_test_suite/mem_mapstringnat_01.tzt tzt_reference_test_suite/mem_mapstringnat_02.tzt tzt_reference_test_suite/mem_mapstringnat_03.tzt tzt_reference_test_suite/mem_mapstringnat_04.tzt tzt_reference_test_suite/mem_mapstringnat_05.tzt tzt_reference_test_suite/mem_setint_00.tzt tzt_reference_test_suite/mem_setint_01.tzt tzt_reference_test_suite/mem_setstring_00.tzt tzt_reference_test_suite/mem_setstring_01.tzt tzt_reference_test_suite/mem_setstring_02.tzt tzt_reference_test_suite/mul_int-int_00.tzt tzt_reference_test_suite/mul_int-nat_00.tzt tzt_reference_test_suite/mul_mutez-nat_00.tzt tzt_reference_test_suite/mul_mutez-nat_01.tzt tzt_reference_test_suite/mul_nat-int_00.tzt tzt_reference_test_suite/mul_nat-mutez_00.tzt tzt_reference_test_suite/mul_nat-mutez_01.tzt tzt_reference_test_suite/mul_nat-nat_00.tzt tzt_reference_test_suite/neg_int_00.tzt tzt_reference_test_suite/neg_int_01.tzt tzt_reference_test_suite/neg_int_02.tzt tzt_reference_test_suite/neg_nat_00.tzt tzt_reference_test_suite/neg_nat_01.tzt tzt_reference_test_suite/neq_00.tzt tzt_reference_test_suite/neq_01.tzt tzt_reference_test_suite/neq_02.tzt tzt_reference_test_suite/neq_03.tzt tzt_reference_test_suite/neq_04.tzt tzt_reference_test_suite/never_00.tzt tzt_reference_test_suite/never_00.tc.tzt tzt_reference_test_suite/nil_nat_00.tzt tzt_reference_test_suite/none_int_00.tzt tzt_reference_test_suite/none_pair-nat-string.tzt tzt_reference_test_suite/not_bool_00.tzt tzt_reference_test_suite/not_bool_01.tzt tzt_reference_test_suite/not_bytes_00.tzt tzt_reference_test_suite/not_bytes_01.tzt tzt_reference_test_suite/not_bytes_02.tzt tzt_reference_test_suite/not_bytes_03.tzt tzt_reference_test_suite/not_bytes_04.tzt tzt_reference_test_suite/not_bytes_05.tzt tzt_reference_test_suite/not_int_00.tzt tzt_reference_test_suite/not_nat_00.tzt tzt_reference_test_suite/not_nat_01.tzt tzt_reference_test_suite/not_nat_02.tzt tzt_reference_test_suite/not_nat_03.tzt tzt_reference_test_suite/not_nat_04.tzt tzt_reference_test_suite/not_nat_05.tzt tzt_reference_test_suite/not_nat_06.tzt tzt_reference_test_suite/not_nat_07.tzt tzt_reference_test_suite/now_00.tzt tzt_reference_test_suite/or_bool-bool_00.tzt tzt_reference_test_suite/or_bool-bool_01.tzt tzt_reference_test_suite/or_bool-bool_02.tzt tzt_reference_test_suite/or_bool-bool_03.tzt tzt_reference_test_suite/or_bytes-bytes_00.tzt tzt_reference_test_suite/or_bytes-bytes_01.tzt tzt_reference_test_suite/or_bytes-bytes_02.tzt tzt_reference_test_suite/or_bytes-bytes_03.tzt tzt_reference_test_suite/or_bytes-bytes_04.tzt tzt_reference_test_suite/or_bytes-bytes_05.tzt tzt_reference_test_suite/or_bytes-bytes_06.tzt tzt_reference_test_suite/or_nat-nat_00.tzt tzt_reference_test_suite/or_nat-nat_01.tzt tzt_reference_test_suite/or_nat-nat_02.tzt tzt_reference_test_suite/or_nat-nat_03.tzt tzt_reference_test_suite/or_nat-nat_04.tzt tzt_reference_test_suite/or_nat-nat_05.tzt tzt_reference_test_suite/or_nat-nat_06.tzt tzt_reference_test_suite/pack_address_00.tzt tzt_reference_test_suite/pack_address_01.tzt tzt_reference_test_suite/pack_address_02.tzt tzt_reference_test_suite/pack_address_03.tzt tzt_reference_test_suite/pack_address_04.tzt tzt_reference_test_suite/pack_address_05.tzt tzt_reference_test_suite/pack_bool_00.tzt tzt_reference_test_suite/pack_bool_01.tzt tzt_reference_test_suite/pack_bytes_00.tzt tzt_reference_test_suite/pack_bytes_01.tzt tzt_reference_test_suite/pack_bytes_02.tzt tzt_reference_test_suite/pack_chainid_00.tzt tzt_reference_test_suite/pack_contract_00.tzt tzt_reference_test_suite/pack_key_00.tzt tzt_reference_test_suite/pack_key_01.tzt tzt_reference_test_suite/pack_key_02.tzt tzt_reference_test_suite/pack_key_03.tzt tzt_reference_test_suite/pack_keyhash_01.tzt tzt_reference_test_suite/pack_keyhash_02.tzt tzt_reference_test_suite/pack_keyhash_03.tzt tzt_reference_test_suite/pack_keyhash_04.tzt tzt_reference_test_suite/pack_lambda_comb_pairs.tzt tzt_reference_test_suite/pack_list-bool_00.tzt tzt_reference_test_suite/pack_list-bool_01.tzt tzt_reference_test_suite/pack_list-list-bool.tzt tzt_reference_test_suite/pack_list_large_00.tzt tzt_reference_test_suite/pack_map-bool-unit_00.tzt tzt_reference_test_suite/pack_operation_00.tc.tzt tzt_reference_test_suite/pack_option-unit_00.tzt tzt_reference_test_suite/pack_option-unit_01.tzt tzt_reference_test_suite/pack_or-unit-bool_00.tzt tzt_reference_test_suite/pack_or-unit-bool_01.tzt tzt_reference_test_suite/pack_pair-bool-unit_00.tzt tzt_reference_test_suite/pack_signature_00.tzt tzt_reference_test_suite/pack_signature_01.tzt tzt_reference_test_suite/pack_signature_02.tzt tzt_reference_test_suite/pack_signature_03.tzt tzt_reference_test_suite/pack_string_00.tzt tzt_reference_test_suite/pack_string_01.tzt tzt_reference_test_suite/pack_string_02.tzt tzt_reference_test_suite/pack_string_03.tzt tzt_reference_test_suite/pack_unit_00.tzt tzt_reference_test_suite/packunpack_address_00.tzt tzt_reference_test_suite/packunpack_bool_00.tzt tzt_reference_test_suite/packunpack_bytes_00.tzt tzt_reference_test_suite/packunpack_int_00.tzt tzt_reference_test_suite/packunpack_keyhash_00.tzt tzt_reference_test_suite/packunpack_mutez_00.tzt tzt_reference_test_suite/packunpack_nat_00.tzt tzt_reference_test_suite/packunpack_string_00.tzt tzt_reference_test_suite/packunpack_timestamp_00.tzt tzt_reference_test_suite/pair_00.tc.tzt tzt_reference_test_suite/pair_int-int_00.tzt tzt_reference_test_suite/pair_nat-string_00.tzt tzt_reference_test_suite/pair_pair-nat-string-pair-string-nat_00.tzt tzt_reference_test_suite/push_00.tc.tzt tzt_reference_test_suite/push_int_00.tzt tzt_reference_test_suite/push_string_00.tzt tzt_reference_test_suite/read_ticket_00.tzt tzt_reference_test_suite/right_nat-int_00.tzt tzt_reference_test_suite/self_00.tzt tzt_reference_test_suite/self_01.tzt tzt_reference_test_suite/self_in_lambda.tc.tzt tzt_reference_test_suite/sender_00.tzt tzt_reference_test_suite/setdelegate_00.tzt tzt_reference_test_suite/setdelegate_00.tc.tzt tzt_reference_test_suite/sha256_00.tzt tzt_reference_test_suite/sha256_01.tzt tzt_reference_test_suite/sha3_00.tzt tzt_reference_test_suite/sha3_01.tzt tzt_reference_test_suite/sha512_00.tzt tzt_reference_test_suite/sha512_01.tzt tzt_reference_test_suite/size_bytes_00.tzt tzt_reference_test_suite/size_listint_00.tzt tzt_reference_test_suite/size_listint_01.tzt tzt_reference_test_suite/size_listint_02.tzt tzt_reference_test_suite/size_listint_03.tzt tzt_reference_test_suite/size_mapintint_00.tzt tzt_reference_test_suite/size_mapstringnat_00.tzt tzt_reference_test_suite/size_mapstringnat_01.tzt tzt_reference_test_suite/size_mapstringnat_02.tzt tzt_reference_test_suite/size_mapstringnat_03.tzt tzt_reference_test_suite/size_setint_00.tzt tzt_reference_test_suite/size_setint_01.tzt tzt_reference_test_suite/size_setint_02.tzt tzt_reference_test_suite/size_setint_03.tzt tzt_reference_test_suite/size_setstring_00.tzt tzt_reference_test_suite/size_string_00.tzt tzt_reference_test_suite/slice_bytes_00.tzt tzt_reference_test_suite/slice_bytes_01.tzt tzt_reference_test_suite/slice_bytes_02.tzt tzt_reference_test_suite/slice_bytes_03.tzt tzt_reference_test_suite/slice_bytes_04.tzt tzt_reference_test_suite/slice_string_00.tzt tzt_reference_test_suite/slice_string_01.tzt tzt_reference_test_suite/slice_string_02.tzt tzt_reference_test_suite/slice_string_03.tzt tzt_reference_test_suite/slice_string_04.tzt tzt_reference_test_suite/slice_string_05.tzt tzt_reference_test_suite/some_00.tc.tzt tzt_reference_test_suite/some_int_00.tzt tzt_reference_test_suite/some_pairintint_00.tzt tzt_reference_test_suite/some_string_00.tzt tzt_reference_test_suite/source_00.tzt tzt_reference_test_suite/split_ticket_00.tzt tzt_reference_test_suite/split_ticket_01.tzt tzt_reference_test_suite/split_ticket_02.tzt tzt_reference_test_suite/split_ticket_03.tzt tzt_reference_test_suite/split_ticket_04.tzt tzt_reference_test_suite/sub_int-int_00.tzt tzt_reference_test_suite/sub_int-int_01.tzt tzt_reference_test_suite/sub_mutez-mutez_00.tzt tzt_reference_test_suite/sub_mutez-mutez_01.tzt tzt_reference_test_suite/sub_timestamp-int_00.tzt tzt_reference_test_suite/sub_timestamp-int_01.tzt tzt_reference_test_suite/sub_timestamp-int_02.tzt tzt_reference_test_suite/sub_timestamp-int_03.tzt tzt_reference_test_suite/sub_timestamp-int_04.tzt tzt_reference_test_suite/sub_timestamp-timestamp_00.tzt tzt_reference_test_suite/sub_timestamp-timestamp_01.tzt tzt_reference_test_suite/sub_timestamp-timestamp_02.tzt tzt_reference_test_suite/sub_timestamp-timestamp_03.tzt tzt_reference_test_suite/swap_00.tzt tzt_reference_test_suite/swap_00.tc.tzt tzt_reference_test_suite/swap_01.tc.tzt tzt_reference_test_suite/ticket_00.tzt tzt_reference_test_suite/ticket_01.tzt tzt_reference_test_suite/transfertokens_00.tzt tzt_reference_test_suite/transfertokens_00.tc.tzt tzt_reference_test_suite/transfertokens_01.tzt tzt_reference_test_suite/unit_00.tzt tzt_reference_test_suite/unpair_00.tc.tzt tzt_reference_test_suite/unpair_pairstringstring_00.tzt tzt_reference_test_suite/update_00.tc.tzt tzt_reference_test_suite/update_bigmapstringstring_00.tzt tzt_reference_test_suite/update_bigmapstringstring_01.tzt tzt_reference_test_suite/update_bigmapstringstring_02.tzt tzt_reference_test_suite/update_bigmapstringstring_03.tzt tzt_reference_test_suite/update_bigmapstringstring_04.tzt tzt_reference_test_suite/update_bigmapstringstring_05.tzt tzt_reference_test_suite/update_bigmapstringstring_06.tzt tzt_reference_test_suite/update_bigmapstringstring_07.tzt tzt_reference_test_suite/update_mapintint_00.tzt tzt_reference_test_suite/update_mapintint_01.tzt tzt_reference_test_suite/update_setint_00.tzt tzt_reference_test_suite/update_setint_01.tzt tzt_reference_test_suite/update_setint_02.tzt tzt_reference_test_suite/xor_bool-bool_00.tzt tzt_reference_test_suite/xor_bool-bool_01.tzt tzt_reference_test_suite/xor_bool-bool_02.tzt tzt_reference_test_suite/xor_bool-bool_03.tzt tzt_reference_test_suite/xor_bytes-bytes_00.tzt tzt_reference_test_suite/xor_bytes-bytes_01.tzt tzt_reference_test_suite/xor_bytes-bytes_02.tzt tzt_reference_test_suite/xor_bytes-bytes_03.tzt tzt_reference_test_suite/xor_bytes-bytes_04.tzt tzt_reference_test_suite/xor_bytes-bytes_05.tzt tzt_reference_test_suite/xor_bytes-bytes_06.tzt tzt_reference_test_suite/xor_nat-nat_00.tzt tzt_reference_test_suite/xor_nat-nat_01.tzt tzt_reference_test_suite/xor_nat-nat_02.tzt tzt_reference_test_suite/xor_nat-nat_03.tzt tzt_reference_test_suite/xor_nat-nat_04.tzt tzt_reference_test_suite/xor_nat-nat_05.tzt tzt_reference_test_suite/xor_nat-nat_06.tzt +tzt_reference_test_suite/transfertokens_01.tzt: +Got output: { Stack_elt + operation + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000000010501a9845b61ac052cdd0428af72a35bf75151dc754800ff00000000020014 } +Expected: { Stack_elt operation (Transfer_tokens 20 5 "KT1Q36KWPSba7dHsH5E4ZsQHehrChc51e19d" _) } + +tzt_reference_test_suite/transfertokens_00.tzt: +Got output: { Stack_elt + operation + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe60000000105000002298c03ed7d454a101eb7022bc95f7e5f41ac7800 } +Expected: { Stack_elt + operation + (Transfer_tokens Unit 5 "tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" _) } + +tzt_reference_test_suite/ticket_01.tzt: +Got output: StaticError "Error:\n Contract_storage.Failure \"get_balance\"\n" +Expected: { Stack_elt (option (ticket string)) None } + +tzt_reference_test_suite/ticket_00.tzt: +Got output: StaticError "Error:\n Contract_storage.Failure \"get_balance\"\n" +Expected: { Stack_elt + (option (ticket string)) + (Some (Pair "KT1Q36KWPSba7dHsH5E4ZsQHehrChc51e19d" "Blue" 42)) } + +tzt_reference_test_suite/setdelegate_00.tzt: +Got output: { Stack_elt + operation + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe600000003ff002431516be31f3f7bb3c8169f930a024142696af7 } +Expected: { Stack_elt operation (Set_delegate (Some "tz1NwQ6hkenkn6aYYio8VnJvjtb4K1pfeU1Z") _) } + +tzt_reference_test_suite/createcontract_01.tzt: +Got output: { Stack_elt + operation + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000000020c000000001e02000000190502020000000a0320034f053d036d03420501036c0500036c00000002030b ; + Stack_elt address "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm" } +Expected: { Stack_elt + operation + (Create_contract + { code { DROP ; UNIT ; NIL operation ; PAIR } ; + storage unit ; + parameter unit } + None + 12 + Unit + _) ; + Stack_elt address _ } + +tzt_reference_test_suite/createcontract_00.tzt: +Got output: { Stack_elt + operation + 0x011d23c1d3d2f8a4ea5e8784b8f7ecf2ad304c0fe6000000020cff002431516be31f3f7bb3c8169f930a024142696af70000001e02000000190502020000000a0320034f053d036d03420501036c0500036c00000002030b ; + Stack_elt address "KT1Mjjcb6tmSsLm7Cb3DSQszePjfchPM4Uxm" } +Expected: { Stack_elt + operation + (Create_contract + { code { DROP ; UNIT ; NIL operation ; PAIR } ; + storage unit ; + parameter unit } + (Some "tz1NwQ6hkenkn6aYYio8VnJvjtb4K1pfeU1Z") + 12 + Unit + _) ; + Stack_elt address _ } + +Test results: Passed:621 Failed:7 Total:628 +Fatal error: + Some tests have failed diff --git a/tezt/tests/expected/views.ml/Paris- Run views.out b/tezt/tests/expected/views.ml/Parisb- Run views.out similarity index 100% rename from tezt/tests/expected/views.ml/Paris- Run views.out rename to tezt/tests/expected/views.ml/Parisb- Run views.out diff --git a/tezt/tests/expected/views.ml/Parisc- Run views.out b/tezt/tests/expected/views.ml/Parisc- Run views.out new file mode 100644 index 000000000000..93b71a2c4f05 --- /dev/null +++ b/tezt/tests/expected/views.ml/Parisc- Run views.out @@ -0,0 +1,213 @@ + +./octez-client --mode mockup --wait none originate contract view_registers_callers transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/view_registers_callers.tz --init '{}' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 603.226 units (will add 100 for safety) +Estimated storage: 409 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.00045 + Expected counter: 1 + Gas limit: 704 + Storage limit: 429 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00045 + payload fees(the block proposer) ....... +ꜩ0.00045 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter unit ; + storage (list address) ; + code { CDR ; SOURCE ; CONS ; NIL operation ; PAIR } ; + view "calls_count" unit nat { CDR ; SIZE } ; + view "last_caller" + unit + (option address) + { CDR ; IF_CONS { DIP { DROP } ; SOME } { NONE address } } } + Initial storage: {} + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 152 bytes + Paid storage size diff: 152 bytes + Consumed gas: 603.192 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.038 + storage fees ........................... +ꜩ0.038 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as view_registers_callers. + +./octez-client --mode mockup --wait none originate contract view_check_caller transferring 0 from bootstrap1 running michelson_test_scripts/mini_scenarios/view_check_caller.tz --init None --burn-cap 1 +Node is bootstrapped. +Estimated gas: 628.309 units (will add 100 for safety) +Estimated storage: 465 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000508 + Expected counter: 2 + Gas limit: 729 + Storage limit: 485 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000508 + payload fees(the block proposer) ....... +ꜩ0.000508 + Origination: + From: [PUBLIC_KEY_HASH] + Credit: ꜩ0 + Script: + { parameter address ; + storage (option address) ; + code { CAR ; + DUP ; + UNIT ; + VIEW "calls_count" nat ; + IF_NONE { UNIT ; FAILWITH } {} ; + DIP { UNIT ; VIEW "last_caller" (option address) } ; + PUSH nat 0 ; + IFCMPEQ + { IF_NONE { UNIT ; FAILWITH } { IF_NONE {} { UNIT ; FAILWITH } } ; + NONE address } + { IF_NONE { UNIT ; FAILWITH } { IF_NONE { UNIT ; FAILWITH } {} } ; + SOME } ; + NIL operation ; + PAIR } } + Initial storage: None + No delegate for this contract + This origination was successfully applied + Originated contracts: + [CONTRACT_HASH] + Storage size: 208 bytes + Paid storage size diff: 208 bytes + Consumed gas: 628.275 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.052 + storage fees ........................... +ꜩ0.052 + [PUBLIC_KEY_HASH] ... -ꜩ0.06425 + storage fees ........................... +ꜩ0.06425 + +New contract [CONTRACT_HASH] originated. +Contract memorized as view_check_caller. + +./octez-client --mode mockup --wait none transfer 1 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 3582.580 units (will add 100 for safety) +Estimated storage: no bytes added +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000665 + Expected counter: 3 + Gas limit: 3683 + Storage limit: 0 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000665 + payload fees(the block proposer) ....... +ꜩ0.000665 + Transaction: + Amount: ꜩ1 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: None + Storage size: 208 bytes + Consumed gas: 3583.116 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + + +./octez-client --mode mockup --wait none transfer 1 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 +Node is bootstrapped. +Estimated gas: 1285.773 units (will add 100 for safety) +Estimated storage: 27 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000389 + Expected counter: 4 + Gas limit: 1386 + Storage limit: 47 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000389 + payload fees(the block proposer) ....... +ꜩ0.000389 + Transaction: + Amount: ꜩ1 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + This transaction was successfully applied + Updated storage: { 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78 } + Storage size: 179 bytes + Paid storage size diff: 27 bytes + Consumed gas: 1286.351 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00675 + storage fees ........................... +ꜩ0.00675 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + + +./octez-client --mode mockup --wait none transfer 1 from bootstrap1 to '[CONTRACT_HASH]' --burn-cap 1 --arg '"[CONTRACT_HASH]"' +Node is bootstrapped. +Estimated gas: 3586.212 units (will add 100 for safety) +Estimated storage: 27 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000665 + Expected counter: 5 + Gas limit: 3687 + Storage limit: 47 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000665 + payload fees(the block proposer) ....... +ꜩ0.000665 + Transaction: + Amount: ꜩ1 + From: [PUBLIC_KEY_HASH] + To: [CONTRACT_HASH] + Parameter: "[CONTRACT_HASH]" + This transaction was successfully applied + Updated storage: (Some 0x000002298c03ed7d454a101eb7022bc95f7e5f41ac78) + Storage size: 235 bytes + Paid storage size diff: 27 bytes + Consumed gas: 3586.748 + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.00675 + storage fees ........................... +ꜩ0.00675 + [PUBLIC_KEY_HASH] ... -ꜩ1 + [CONTRACT_HASH] ... +ꜩ1 + -- GitLab From 04105d7171e79bf7a14658ba300f7a7c1e5e1094 Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Fri, 14 Jun 2024 09:08:00 +0200 Subject: [PATCH 14/16] =?UTF-8?q?Tezt:=20Temporarily=20disable=20smart=20r?= =?UTF-8?q?ollup=E2=80=99s=20migration=20for=20ParisC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tezt/tests/sc_rollup_migration.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tezt/tests/sc_rollup_migration.ml b/tezt/tests/sc_rollup_migration.ml index 98cc3f06be79..9b9480025fdf 100644 --- a/tezt/tests/sc_rollup_migration.ml +++ b/tezt/tests/sc_rollup_migration.ml @@ -908,6 +908,8 @@ let test_refutation_migration ~migrate_from ~migrate_to = ]) tests +let assume cond test = if cond then test () else () + let register_migration ~kind ~migrate_from ~migrate_to = test_migration_inbox ~kind ~migrate_from ~migrate_to ; test_migration_ticket_inbox ~kind ~migrate_from ~migrate_to ; @@ -924,6 +926,7 @@ let register_migration_only_wasm ~migrate_from ~migrate_to = test_refutation_migration ~migrate_from ~migrate_to let register ~migrate_from ~migrate_to = + assume (migrate_to <> Protocol.ParisC) @@ fun () -> register_migration ~kind:"arith" ~migrate_from ~migrate_to ; register_migration ~kind:"wasm_2_0_0" ~migrate_from ~migrate_to ; register_migration_only_wasm ~migrate_from ~migrate_to -- GitLab From a6d1a48debe9071773106f2e21b30ce6e972681d Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Fri, 14 Jun 2024 14:36:19 +0200 Subject: [PATCH 15/16] Tezt: Reduce the commitment period for commitment scenarios --- tezt/tests/sc_rollup.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 856df037d4a5..70e24b988bae 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -1504,11 +1504,11 @@ let check_published_commitment_in_l1 ?(force_new_level = true) sc_rollup client (published_commitment, "published") ; unit -let test_commitment_scenario ?supports ?commitment_period ?challenge_window - ?(extra_tags = []) ~variant = +let test_commitment_scenario ?supports ?(commitment_period = 10) + ?challenge_window ?(extra_tags = []) ~variant = test_full_scenario ?supports - ?commitment_period + ~commitment_period ?challenge_window { tags = ["commitment"] @ extra_tags; -- GitLab From 74937fb9b8c369675bf0f106179f37354edffb40 Mon Sep 17 00:00:00 2001 From: Killian Delarue Date: Mon, 17 Jun 2024 13:58:59 +0200 Subject: [PATCH 16/16] Tezt: Disable [p2p-swap] test --- tezt/tests/p2p.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tezt/tests/p2p.ml b/tezt/tests/p2p.ml index 0942be9686b7..06c0d6b905ba 100644 --- a/tezt/tests/p2p.ml +++ b/tezt/tests/p2p.ml @@ -578,7 +578,7 @@ module Swap = struct Test.register ~__FILE__ ~title:"p2p-swap" - ~tags:["p2p"; "node"; "swap"] + ~tags:["p2p"; "node"; "swap"; Tag.ci_disabled] ~uses_client:false ~uses_admin_client:false @@ fun () -> test_swap_raw () -- GitLab